ep93xx-kernel: add kernel for ep93xx machine + patch from cirrus-logic git tree ...
authorKoen Kooi <koen@openembedded.org>
Wed, 8 Feb 2006 10:19:41 +0000 (10:19 +0000)
committerOpenEmbedded Project <openembedded-devel@lists.openembedded.org>
Wed, 8 Feb 2006 10:19:41 +0000 (10:19 +0000)
packages/linux/ep93xx-kernel/.mtn2git_empty [new file with mode: 0644]
packages/linux/ep93xx-kernel/defconfig [new file with mode: 0644]
packages/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff [new file with mode: 0644]
packages/linux/ep93xx-kernel_2.6.15.bb [new file with mode: 0644]

diff --git a/packages/linux/ep93xx-kernel/.mtn2git_empty b/packages/linux/ep93xx-kernel/.mtn2git_empty
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/packages/linux/ep93xx-kernel/defconfig b/packages/linux/ep93xx-kernel/defconfig
new file mode 100644 (file)
index 0000000..1a0aa51
--- /dev/null
@@ -0,0 +1,920 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2-ep93xx
+# Mon Nov  8 16:40:30 2004
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+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_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+
+#
+# EP93xx
+#
+# CONFIG_ARCH_EP9301 is not set
+# CONFIG_ARCH_EP9302 is not set
+CONFIG_ARCH_EP9312=y
+# CONFIG_ARCH_EP9315 is not set
+CONFIG_MACH_EDB9312=y
+# CONFIG_MACH_ACC is not set
+CONFIG_EP93XX_DMA=y
+CONFIG_ARCH_EP93XX_IDE=y
+CONFIG_EP93XX_SSP=y
+CONFIG_EP93XX_SSP_CIRRUS=y
+# CONFIG_EP93XX_SSP_LINUX is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# General setup
+#
+CONFIG_DISCONTIGMEM=y
+CONFIG_ARM_AMBA=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=/dev/hda1"
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=y
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+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=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_ABSENT=y
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x60000000
+CONFIG_MTD_PHYSMAP_LEN=0x02000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_IMPA7 is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_SLRAM=y
+CONFIG_MTD_PHRAM=y
+CONFIG_MTD_MTDRAM=y
+CONFIG_MTDRAM_TOTAL_SIZE=512
+CONFIG_MTDRAM_ERASE_SIZE=1
+CONFIG_MTDRAM_ABS_POS=0x20000000
+# CONFIG_MTD_BLKMTD 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=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD 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_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=12288
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# 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 is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER 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_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_EP93XX_ETHERNET=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
+
+#
+# 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=y
+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
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_EP93XX=y
+# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
+CONFIG_IDE_ARM=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG 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 is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN 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=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# 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 I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_AMBAKMI is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_EP93XX=y
+CONFIG_KEYBOARD_EP93XX_SPI=y
+CONFIG_KEYBOARD_EP93XX_8X8=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+CONFIG_TOUCHSCREEN_EP93XX=y
+# CONFIG_INPUT_MISC 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 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_EP93XX=y
+CONFIG_SERIAL_EP93XX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+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 is not set
+# CONFIG_RTC is not set
+# CONFIG_EP93XX_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+CONFIG_I2C_EP93XX=y
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 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_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_DS1337=y
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 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
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# 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_NAND is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE 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_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_EXPORTFS is not set
+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
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# 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=y
+CONFIG_NLS_ISO8859_1=y
+# 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=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_CX25871_I2C is not set
+CONFIG_FB_EP93XX=y
+# CONFIG_FB_CRT_EP93XX is not set
+CONFIG_FB_LCD_EP93XX=y
+# CONFIG_FB_LCD_EP93XX_SHARP is not set
+# CONFIG_FB_CX25871 is not set
+# CONFIG_FB_EP93XX_8BPP is not set
+# CONFIG_FB_EP93XX_16BPP_565 is not set
+# CONFIG_FB_EP93XX_24BPP is not set
+CONFIG_FB_EP93XX_32BPP=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_6x11=y
+CONFIG_FONT_PEARL_8x8=y
+CONFIG_FONT_ACORN_8x8=y
+# CONFIG_FONT_MINI_4x6 is not set
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_PRINTK_HACK=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/packages/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff b/packages/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff
new file mode 100644 (file)
index 0000000..3dc6b00
--- /dev/null
@@ -0,0 +1,43746 @@
+diff --git a/Documentation/arm/ep93xx/config.txt b/Documentation/arm/ep93xx/config.txt
+new file mode 100644
+index 0000000..9d13a15
+--- /dev/null
++++ b/Documentation/arm/ep93xx/config.txt
+@@ -0,0 +1,207 @@
++-------------------------------------------------------------------------
++config.txt
++
++Information on configuration options in the Linux kernel for the Cirrus
++EP93xx.
++
++Note to developers:  Let's stick to the essentials on "how to turn things
++on in the Linux build."  This information is presented from the standpoint
++of someone doing a build, looking at a make menuconfig screen.  If what you
++are describing doesn't fit here, it should get its own document to go into
++the level of detail you feel is most practicle.
++-------------------------------------------------------------------------
++
++All options configured as built-in drivers, not loadable modules.
++So on options that are selected by < >, select <*>, not <M>.  To
++do this either hit 'y' or hit the space bar twice.
++
++
++----------------
++Audio
++----------------
++Needed by:
++Needs: DMA Support, dev fs.
++
++Ac97 and I2S audio are currently mutually exclusive.
++
++To enable Ac97 Audio:
++      Go into "Sound --->"
++      Enable "Sound Support"
++      Enable "OSS sound modules"
++      Select "Ac97" for "Cirrus EP93xx Sound Support"
++
++To enable I2S Audio:
++      Go into "Sound --->"
++      Enable "Sound Support"
++      Enable "OSS sound modules"
++      Select "I2S" for "Cirrus EP93xx Sound Support"
++      If you have an EDB9312 board, select "CS4228A" for "Cirrus I2S Codec Support"
++      If you have an EDB9301 board, select "CS4271" for "Cirrus I2S Codec Support"
++
++
++----------------
++Dev Fs
++----------------
++      DEVFS support is no longer available.
++      Please consider using udev or create device nodes manually instead.
++      You might also need to adapt your startup scripts and userspace
++      apps.
++
++----------------
++DMA
++----------------
++Needed by: Audio, IDE/DMA
++Needs:
++
++To enable DMA:
++      Go into "System Type --->"
++      Go into "EP93XX Options --->"
++      Enable "EP93XX Internal DMA Support"
++
++
++----------------
++IDE
++----------------
++Needed by:
++Needs:
++      To Turn on IDE support for the platform, you need to enable
++General IDE support first - CONFIG_BLK_DEV_IDE, CONFIG_BLK_DEV_IDEDISK,
++CONFIG_BLK_DEV_IDECD.
++
++      If multiword DMA and ultra DMA support is needed, general DMA support for
++the platform must be enabled first.  See DMA section of this document for
++options to enable DMA for the platform.
++
++      If CDROM support is enabled, ISO9660 file system support should be enabled.
++If a DVD support is needed, UDF file system support should be enabled.
++
++To enable CONFIG_BLK_DEV_IDE:
++      Go into "ATA /ATAPI/MFM/RLL support --->"
++      Enable "ATA/ATAPI/MFM/RLL support"
++      Go into "IDE, ATA, and ATAPI Block devices --->"
++      Enable "Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support"
++
++To enable CONFIG_BLK_DEV_IDEDISK:
++      Go into "ATA /ATAPI/MFM/RLL support --->"
++      Go into "IDE, ATA, and ATAPI Block devices --->"
++      Enable "Include IDE/ATA-2 DISK support"
++
++To enable CONFIG_BLK_DEV_IDECD:
++      Go into "ATA /ATAPI/MFM/RLL support --->"
++      Go into "IDE, ATA, and ATAPI Block devices --->"
++      Enable "Include IDE/ATAPI CDROM support"
++
++To enable EP93XX IDE (PIO mode only):
++      Go into "ATA /ATAPI/MFM/RLL support --->"
++      Go into "IDE, ATA, and ATAPI Block devices --->"
++      Enable "EP93XX IDE Support"
++
++To enable EP93XX IDE DMA (mdma and udma modes):
++      Go into "ATA /ATAPI/MFM/RLL support --->"
++      Go into "IDE, ATA, and ATAPI Block devices --->"
++      Enable "EP93XX IDE DMA support"
++
++To enabled ISO 9660 file system support:
++      Go into "File systems --->"
++      Enable "ISo 9660 CDROM file system support"
++      Enable "Microsoft Joliet CDROM extensions"
++
++To enable UDF file system support:
++      Go into "File systems --->"
++      Enable "UDF file system support (read only)"
++
++See also /Documentation/arm/ep93xx/ide-hard-drive-support.txt for information
++on configuring the hard drive.
++
++----------------
++IrDA
++----------------
++Described in /Documentation/arm/ep93xx/irda.txt
++
++
++----------------
++NFS
++----------------
++Described in /Documentation/arm/ep93xx/nfs.txt
++
++
++----------------
++Serial Terminal
++----------------
++To enable serial terminal:
++      Go into "Character devices --->"
++      Turn off "Support for console on virtual terminal"
++      Turn off "Virtual terminal"
++      Go into "Serial drivers --->"
++      Turn on "Cirrus EP93xx ARM AMBA serial port support"
++      Turn on "Support for console on EP93xx serial port"
++
++Serial terminal is the bottom jack of J7.
++Format is 57600,8N1, flow control: "none".
++
++
++----------------
++Touchscreen
++----------------
++To enable touchscreen driver:
++      Go into "Character devices --->"
++      Go into "Mice --->"
++      Enable "Mouse Support (not serial and bus mice)"
++      Disable "PS/2 Mouse (aka "auxiliary device") support
++      Enable "EP93xx touch screen support"
++
++
++----------------
++USB
++----------------
++The order of all of the following statements is critical as some options enable
++other options.
++
++To enable basic USB support(required for all devices listed below):
++   Go into "USB support --->"
++   Enable "Support for USB"
++   Enable "Preliminary USB device filesystem" (optional)
++   Enable "EP93XX OHCI-compatible host interface support"
++
++To enable support for USB mouse:
++   Go into "Input core support --->"
++   Enable "Input core support"
++   Enable "Mouse support"
++
++   Go back to the top level of menuconfig
++
++   Go into "USB support --->"
++   Enable "USB Human Interface Device (full HID) support"
++   Enable "HID input layer support"
++
++To enable support for USB Keyboard:
++   Go into "Input core support --->"
++   Enable "Input core support"
++   Enable "Keyboard support"
++
++   Go back to the top level of menuconfig
++
++   Go into "USB support --->"
++   Enable "USB Human Interface Device (full HID) support"
++   Enable "HID input layer support"
++
++   Go back to the top level of menuconfig
++   Go into "Character devices --->"
++   Set EP93xx Keyboard Support to "USB"
++
++To enable USB Mass Storage support:
++   Go into "SCSI Support --->"
++   Enable "SCSI Support"
++   Enable "SCSI disk support"
++
++   Go back to the top level of menuconfig
++
++   Go into "USB support --->"
++   Enable "USB Mass Storage support"
++
++   Go back to the top level of menuconfig
++
++(optional - Do this if you want to mount a USB flash drive)
++   Go into "File systems --->"
++   Enable "DOS FAT fs support"
++   Enable "VFAT (Windows-95) fs support"
+diff --git a/Documentation/arm/ep93xx/dma.txt b/Documentation/arm/ep93xx/dma.txt
+new file mode 100644
+index 0000000..e7fc1bb
+--- /dev/null
++++ b/Documentation/arm/ep93xx/dma.txt
+@@ -0,0 +1,300 @@
++Support Functions for the Cirrus Logic ep93xx Internal DMA controller.
++==============================================================================
++
++State diagram
++
++States:
++Uninitialized (!pause & !xfer_enable)
++Stopped (pause & !xfer_enable)
++Transferring (!pause & xfer_enable)
++Stopped by starvation (pause & xfer_enable)
++
++                                    _______________
++               request ----------> |               | <------- free -----------
++                                   | Uninitialized |                        /\
++                                   |_______________|                        ||
++                                                                            ||
++                                        ||                                  ||
++                                  init  ||   ------------------------------>||
++                                        ||   /\                             ||
++                                        \/   ||                             ||
++                                      _________                             ||
++  ||<-- start && new_buffers <= 1 -- |         | <----- flush <---------    ||
++  ||                                 | Stopped |                      /\    ||
++  ||         ---------> pause------> |_________| -------------------->||    ||
++  ||         /\                                                             ||
++  ||         ||                        ||                                   ||
++  ||         ||                        || start && new_buffers > 1          ||
++  ||         ||                        ||                                   ||
++  ||         ||                        \/                                   ||
++  ||         ||                   ______________                            ||
++  ||         ||                  |              | ------------------------->||
++  ||         ||<---------------- | Transferring | ------------------->||    ||
++  ||         ||                  |______________|                     ||    ||
++  ||         ||                                                       ||    ||
++  ||         ||                             ||                        ||    ||
++  ||         ||                             || new_buffers = 0        ||    ||
++  ||         ||                       /\    ||                        ||    ||
++  ||         ||                       ||    \/                        ||    ||
++  ||         ||       new_buffers > 1 ||                              ||    ||
++  ||         ||                       ||                              ||    ||
++  ||         ||                 _______________________               ||    ||
++  ||         ||<-------------- |                       |              ||    ||
++  \/                           | Stopped by starvation | ------------>||    ||
++  ---------------------------> |_______________________|              ||    ||
++                                                                      ||    ||
++                                ||    /\                              ||    ||
++                                ||    ||                              ||    ||
++                                ||    ||<-------- flush <---------------    ||
++                                ||                                          ||
++                                ------------------------------------------->||
++
++
++------------------------------------------------------------------------------
++EP93XX DMA API Functions
++------------------------------------------------------------------------------
++
++    int ep93xx_dma_request(int * handle, const char * device_id,
++                           ep93xx_dma_dev_t device)
++
++This function will allocate a DMA channel for a particular hardware
++peripheral.  Before initiating  a transfer on the allocated channel, the
++channel has to be setup, and buffers have to be added to the channel.
++
++Parameters:
++    int * handle                A pointer which is filled in with a unique
++                                integer value, or handle. The handle is used
++                                to verify the validity of each call to
++                                access the dma channel.
++
++    const char * device_id      string which is the name of the device
++                                attached to the dma channel.
++
++    ep93xx_dma_dev_t device     hardware port to attach to the dma channel
++
++------------------------------------------------------------------------------
++
++    int ep93xx_dma_free(int handle)
++
++This function disables and powers down the dma channel, and releases it
++for future requests. Buffers queued up for the specified channel are
++released without transferring.
++
++Parameters:
++    int handle              A unique integer value, assigned
++                            during open, used to verify the validity of
++                            this call to access a DMA channel.
++
++------------------------------------------------------------------------------
++
++    int ep93xx_dma_add_buffer(int handle, unsigned int source,
++                              unsigned int dest, unsigned int size
++                              unsigned int last, unsigned int buf_id)
++
++This function adds a buffer entry to the DMA buffer queue.  If the channel is
++in the active transfer state, the buffer is immediately transferred,
++otherwise the buffer is not transferred until a start or resume
++command is issued. A -1 is returned if an error occurs, otherwise
++a 0 is returned.
++
++Parameter:
++    int handle                  A unique integer value, assigned
++                                during open, used to verify the validity of
++                                this call to access a dma channel.
++
++    unsigned int source         physical address for the start of this
++                                buffer.
++
++    unsigned int source         physical address destination of the data.
++
++    unsigned int size           buffer size in bytes
++
++    unsigned int last           1 if this is the last buffer in the transfer.
++                                If 1, disable the NFBint so we aren't
++                                interrupted for another buffer
++                                when we know there won't be another.
++
++    unsigned int buf_id         Unique value used to identify this buffer.
++
++------------------------------------------------------------------------------
++
++    int ep93xx_dma_remove_buffer(int handle, unsigned int * address,
++                                 unsigned int * size)
++
++This function removes a buffer entry from the DMA buffer queue. If a buffer
++was removed successfully, a 0 is returned, otherwise -1 is returned.
++
++Parameter:
++    int handle                  A unique integer value, assigned
++                                during open, used to verify the validity of
++                                this call to access a dma channel.
++
++    unsigned int * buf_id       Pointer to an integer which is filled in
++                                with the buffer id..
++
++------------------------------------------------------------------------------
++
++    int ep93xx_dma_queue_full(int handle)
++
++This function queries to determine if the buffer queue for the specified
++channel is full. A return value of 1 indicates the queue is not full, and a
++0 indicates the queue is full.
++
++Parameters:
++    int handle              A unique integer value, assigned
++                            during open, used to verify the validity of
++                            this call to access a dma channel.
++
++------------------------------------------------------------------------------
++
++      int ep93xx_dma_get_position(int handle, unsigned int * buf_id,
++                                unsigned int * total)
++
++This function fills in the buffer ID of the current buffer and fills in the
++total bytes transferred on the channel. If no buffer is active on the channel,
++buf_id is filled in with a -1, otherwise it is the active buffer.
++
++Parameter:
++    int handle              A unique integer value, assigned
++                            during open, used to verify the validity of
++                            this call to access a dma channel.
++
++    unsigned int * buf_id   pointer to an integer which is filled in with
++                            buffer ID of the buffer currently
++                            transferring.
++
++    unsigned int * total    pointer to an integer which is filled in
++                            with the total bytes transferred on the channel.
++
++------------------------------------------------------------------------------
++
++    int ep93xx_dma_config(int handle, unsigned int flags_m2m,
++                          unsigned int flags_m2p, dma_callback callback,
++                          unsigned int user_data)
++
++This function configures the DMA channel registers and installs a dma
++callback function into the DMA instance.  The DMA callback function is
++defined by the driver which is using this DMA channel. It is called in
++response to DMA interrupts, at the end of the DMA channel's interrupt
++handler.  A -1 is returned if an error occurs, otherwise a 0 is returned.
++
++Parameter:
++    int handle              A unique integer value, assigned
++                            during open, used to verify the validity of
++                            this call to access a dma channel.
++
++    unsigned int flags_m2m  Flags used for M2M channel configuration.
++
++    unsigned int flags_m2p  Flags used for M2P/P2M channel
++                            configuration.
++
++    dma_callback callback   Pointer to the callback function which will
++                            be called at the end of the dma interrupt
++                            service routine.
++
++    unsigned int user_data  Data defined by the driver installing the
++                            callback function.  This piece of data will
++                            be returned to the driver when the callback
++                            function is called.
++
++Callback function prototype:
++
++    void (* dma_callback)(ep93xx_dma_int_t interrupt,
++                          ep93xx_dma_dev_t device, unsigned int user_data)
++
++    Parameters:
++        ep93xx_dma_int_t interrupt
++            used by the DMA driver to inform the DMA callback
++            function of the type of DMA interrupt that happened.
++
++        ep93xx_dma_dev_t device
++            hardware port attached to the dma channel.
++
++        unsigned int user_data
++            is a value defined and passed in by the driver which
++            registered the callback function.
++
++------------------------------------------------------------------------------
++
++    int ep93xx_dma_start(int handle, unsigned int channels,
++                         unsigned int * handles
++
++This function enables the DMA channel, and initiates the transfer.  If the
++peripheral interface calls for it, multiple DMA channels can be started
++with one call to this IOCTL.    A -1 is returned if an error occurs,
++otherwise a 0 is returned.
++
++Parameter:
++    int handle              A unique integer value, assigned
++                            during open, used to verify the validity of
++                            this call to access a dma channel.  For a start
++                            multiple, this handle can be the handle
++                            for any of the channels to be started.
++
++    unsigned int channels   Number of channels to start for this transfer.
++                            Specifically this applies to an audio interface
++                            where you can have up to 3 dma channels
++                            servicing a 6 audio channel output, in which case
++                            you need to initiate transfers on all 3 dma
++                            channels as closely together as possible. For
++                            the case of only one channel to be started, this
++                            field should be a 1.
++
++    unsigned int * handles  Pointer to an array of handles, one for
++                            each channel which is to be started.  If only one
++                            channel is to be started, this field should be
++                            NULL.
++
++------------------------------------------------------------------------------
++
++    int ep93xx_dma_pause(int handle, unsigned int channels,
++                         unsigned int * handles)
++
++This function disables the DMA channel, pausing the transfer.  The
++position within the currently transferring buffer is saved, and restored upon
++restarting the transfer on this channel. If the peripheral interface calls
++for it, multiple DMA channels can be paused with one call to this IOCTL.
++A -1 is returned if an error occurs, otherwise a 0 is returned.
++
++Parameter:
++    int handle              A unique integer value, assigned
++                            during open, used to verify the validity of
++                            this call to access a dma channel.
++
++    unsigned int channels   Number of channels to pause for this
++                            transfer.  Specifically this applies to
++                            an audio interface where you can have
++                            up to 3 dma channels servicing a 6
++                            audio channel output, in which case you
++                            need to pause transfers on all 3 dma
++                            channels as closely together as possible.
++
++    unsigned int * handles  Pointer to an array of handles, one for
++                            each channel which is to be paused.
++
++NOTE: There is another way to pause the DMA channel - starve it.
++When the dma channel reaches the point where there are no buffers in
++the queue, but the interface has not been paused, then the dma instance
++will indicate that the channel is in the transfer state, but the
++channel itself is disabled until a new buffer is added to the queue
++If the channel is stopped via this method, a resume command is not
++required to restart a transfer.  A transfer is started immediately
++after two new buffers are added to the queue.  The reason for two is
++so that both channel buffer descriptors can be programmed with valid
++buffers
++
++------------------------------------------------------------------------------
++
++    int ep93xx_dma_flush(int handle)
++
++This function completely flushes all queued buffers and any on going
++DMA transfers on a given channel.  If the dma channel is in the
++active transfer state, once two buffers are added to the queue, the
++channel will begin transferring data right away.  If in the stop
++state, a start command must be issued before any new buffers are
++processed. A -1 is returned if an error occurs, otherwise a 0 is returned.
++
++Parameters:
++    int handle      A unique integer value, assigned
++                    during open, used to verify the validity of
++                    this call to access a dma channel.
+diff --git a/Documentation/arm/ep93xx/status.txt b/Documentation/arm/ep93xx/status.txt
+new file mode 100644
+index 0000000..082c2dd
+--- /dev/null
++++ b/Documentation/arm/ep93xx/status.txt
+@@ -0,0 +1,288 @@
++#
++#   EP93xx driver support status
++#
++
++======================================================================
++(I) Introduction
++======================================================================
++
++The EP93xx are embedded System On Chip (SOC) processors produced
++by Cirrus (www.cirrus.com). They provided support based on 2.4.21-rmk1
++kernels, and they said that there might be 2.6.x support some day.
++Meanwhile they've released a 2.6.8.1 based kernel called "ursus".
++
++Currently we still have got a communication problem with cirrus,
++for some reason it seems to be impossible to directly talk to their
++developers. Hope this will change some day, but we really cannot afford
++to just sit down and wait.
++
++The purpose of this file is to document success and todo's.
++
++  - Section II describes hardware support, organized according to the
++    EP9315 datasheet.  Other device datasheets are ordered similarly,
++    though section numbers may vary.
++
++  - Section III contains other miscellaneous information.
++
++The latest version of this document may be found at:
++
++  linux/Documentation/arm/ep93xx/status.txt
++
++projects homepage can be found at:
++
++  http://members.inode.at/m.burian/ep93xx/index.html
++
++
++======================================================================
++(II)   Hardware Support
++======================================================================
++
++These section numbers mirror the EP9315 datasheet.
++
++1. Introduction
++---------------
++N/A
++
++2. ARM920T Core and Advanced High-Speed Bus (AHB)
++-------------------------------------------------
++We have standard Linux 2.6 support for ARM920T Core. Thumb support
++is pretty shaky, as most people do not seem to use Thumb in the
++kernel. Address translation uses 16K small pages exclusively (FIXME:
++is this true?)
++
++3. MaverickCrunch Coprocessor
++-----------------------------
++People have started with forward porting. Note that there's more
++to it than just kernel support. You also need to have a toolchain
++supporting it. We're in need of a comprehensive HOWTO that explains kernel,
++toolchain and userspace aspects to a point where average developers can use it
++
++
++4. Boot ROM
++-----------
++Well, not really kernel related, most people start with redboot. Make
++sure to use a version that passes the correct machine type.  Some
++people also started porting blob / uboot.
++
++If any support is added for this device, it will likely be a simple
++char device that allows you to read the contents of the boot rom
++for interests sake.
++
++5. System Controller
++--------------------
++System Controllers registers are set by startup code and by individual
++drivers as needed, we try to keep the processor dependent stuff to
++a minimum.
++
++Ray really wants to overhaul the system configuration stuff and move
++towards something like the SA1100 people are doing. It should make
++things a lot cleaner for drivers that share physical pins, or for
++multifunctional blocks that require several drivers (eg: UART2 with
++IrDA support)
++
++There is currently no dynamic clock control support.  We'll probably
++want to tie into the CPUfreq code at some point.
++
++There is no support for querying the system boot configuration or
++last reset source.
++
++There is no power management support.  Individual drivers may power
++up silicon blocks as required. Some research is needed to map the
++EP93xx power states onto the ACPI or PCI states that everyone seems
++to use.
++
++There is no support for the TICK and WATCHDOGEXPIRED interrupts
++generated by this block.
++
++There is no support for the AHB bus arbiter priority settings.
++
++6. Vectored Interrupt Controller
++--------------------------------
++Since we can boot this can't be done dead wrong. Standard level-triggered
++interrupt support is present.
++
++No FIQ interrupts are supported.
++
++Support for demultiplexing GPIO IRQs is available.
++
++
++7. Raster Engine With Analog/LCD Integrated Timing and Interface
++----------------------------------------------------------------
++
++Michael has rewritten large parts of the framebuffer driver based on
++skeleton.c. You need to adapt this in case you can't live with
++the standard display(s) that are included. Framebuffer is fixed
++size, you can change some settings at compile time, though.
++TODO: clean ups, different resolutions, etc
++
++
++8. Graphics Accelerator
++-----------------------
++not available yet, will be done after the framebuffer code has been
++cleaned up.
++
++
++9. 1/10/100 Mbps Ethernet LAN Controller
++----------------------------------------
++Supported. Driver has been reviewed and cleaned up.
++Uses generic mii routines now. It might be possible
++to use DMA - but in that case we'd need to find a
++workaround to get around the fact that it can only
++transfer 32bit aligned data, while we'd need to transfer
++data that's only 16 bit aligned.
++
++NICE-TO-HAVE: Could be ported to use NAPI.
++
++10. DMA Controller
++------------------
++There is some code and documentation ported forward from the Cirrus
++2.4 port.
++
++11. Universal Serial Bus Host Controller
++----------------------------------------
++Ray has written some glue code to plug the OHCI host controller into
++the Linux 2.6 USB stack.  This has been tested on an EDB9301 board with
++a single port populated.  A serial dongle worked fine, and several
++different flash keys seem to work okay with the USB mass storage
++driver using SCSI disk emulation.  This hasn't really been stress tested
++yet, but initial results look very encouraging.
++
++12. Static Memory Controller
++----------------------------
++Not sure how much kernel support is required here. Flash and memory
++timing needs to be setup by the bootloader, so there's not much
++that needs to be done here.
++
++No support for PCMCIA at this time.
++
++13. SDRAM, SyncROM, and SyncFLASH Controller
++--------------------------------------------
++Again, this is probably the bootloaders problem.
++
++There is an errata about system instability when suspending with
++an SDRAM bus speed over 50 MHz.  May need to tweak this if we start
++doing power management modes.
++
++14. UART1 With HDLC and Modem Control Signals
++---------------------------------------------
++We've got a driver to use this one as UART. No DMA support. FIFO support
++works. No HDLC support.  Needs some syscon support to cleanly handle
++HDLC and some modem signals.
++
++15. UART2
++---------
++We've got a driver to use this one as UART. No DMA support. FIFO support
++works. No IrDA SIR support.  Needs some syscon support to cleanly handle
++IrDA SIR.
++
++16. UART3 With HDLC Encoder
++---------------------------
++We've got a driver to use this one as UART. No DMA support. FIFO support
++works. No HDLC or RS-485 support.  Needs some syscon support to cleanly
++handle HDLC and RS-485.
++
++17. IRDA
++--------
++There is some code and documentation ported forward from the Cirrus
++2.4 port.  No idea how well this works, if at all.
++
++18. TIMERS
++----------
++Timer1 is used at 508 kHz with a reload value of 5080 to provide a 100 Hz
++tick signal to drive the kernel.
++
++Timer 2 and 3 are not currently used, nor is the debug timer 4.
++
++
++19. WATCHDOG Timer
++------------------
++Ray has some initial experimental code written (not pushed) to drive this.
++The onboard watchdog seems to have a 250 ms (!) timeout, while most PC
++dogs seem to have timeouts on the order of one minute or more. The standard
++approach of having a user level process open the watchdog device and
++kick it every so often seems like a bad idea here... a momentary system
++load spike could easily delay the monitor from being scheduled, and the
++system would reboot.
++
++Test out a watchdog monitor running at a high scheduling priority, or else
++design a kernel watchdog that kicks the dog every timer tick and exports
++a more reasonable timeout value to userspace.
++
++20. Real Time Clock With Software Trim
++--------------------------------------
++We did not bother to write a driver yet, it would require a design
++that ensures CPU is always powered on, and always have at least
++a 32kHz clock running. Most people prefer to use and external RTC.
++We've got support for the DS1337 RTC that seems to be popular on
++ep93xx based boards.
++
++21. I2S Controller
++------------------
++No support yet.  Klaus is working on it.
++
++22. AC97 Controller
++-------------------
++Supported but could need some testing.
++
++23. Synchronous Serial Port
++---------------------------
++Two driver are available, a forward port from the cirrus driver and
++another driver from Ray.
++
++24. Pulse Width Modulator
++-------------------------
++No support yet.
++
++25. Analog Touch Screen Interface
++---------------------------------
++People already played with this, AFAIK one would need a silicon
++revision > D1 (November 2004) for this to work properly.
++
++26. Keypad Interface
++--------------------
++We've got a driver for the 8x8 keypad. Chances are that you might
++want to create a custom keymap. There's also support for mobile
++phone like input (key 1 becomes -> A -> B -> C) if pressed repeatedly
++within half a second.
++
++27. IDE interface
++-----------------
++We've got IDE working in polling only, no DMA support so far.
++It needs to be cleaned up, too.
++
++28. GPIO
++--------
++Standard LED support for red and green leds is present.
++
++Michael has written an I2C bus driver using the new Linux device driver model.
++It supports an external DS1337 RTC device on the EECLK/EEDAT pins.
++
++Need some syscon support to cleanly handle the multi-function GPIO pins.
++
++Demultiplexing of GPIO interrupts is possible now.
++
++29. Security
++------------
++No information available on this, so support is unlikely in the near future.
++
++30. Glossary
++------------
++N/A
++
++
++======================================================================
++(III) Stuff not found in the datasheet
++======================================================================
++
++1. printascii hack has been removed from our tree.
++
++2. I2C driver
++We've got a bit banging I2C driver
++
++3. External RTC (DS1337)
++Setting and getting the time works
++TODO: advanced features, such as alarm, timer for /dev/rtc
++
++4. Controller Area Network (CAN)
++We have got a character device based driver for the OKI ML9620 CAN Controller.
++
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 4b15f5f..f23341e 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -103,6 +103,17 @@ config ARCH_EBSA110
+         Ethernet interface, two PCMCIA sockets, two serial ports and a
+         parallel port.
++config ARCH_EP93XX
++      bool "EP93xx"
++      select ARM_AMBA
++      help
++        Say Y here to enable support for the Cirrus EP93xx CPU family
++        and choose your specific CPU below.
++
++        See the Cirrus web page for details.
++
++        <http://www.cirrus.com/>
++
+ config ARCH_CAMELOT
+       bool "Epxa10db"
+       help
+@@ -219,6 +230,8 @@ endchoice
+ source "arch/arm/mach-clps711x/Kconfig"
++source "arch/arm/mach-ep93xx/Kconfig"
++
+ source "arch/arm/mach-epxa10db/Kconfig"
+ source "arch/arm/mach-footbridge/Kconfig"
+@@ -403,7 +416,7 @@ config NO_IDLE_HZ
+ config ARCH_DISCONTIGMEM_ENABLE
+       bool
+-      default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
++      default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) || ARCH_EP93XX
+       help
+         Say Y to support efficient handling of discontiguous physical memory,
+         for architectures which are either NUMA (Non-Uniform Memory Access)
+@@ -415,7 +428,7 @@ source "mm/Kconfig"
+ config LEDS
+       bool "Timer and CPU usage LEDs"
+       depends on ARCH_CDB89712 || ARCH_CO285 || ARCH_EBSA110 || \
+-                 ARCH_EBSA285 || ARCH_IMX || ARCH_INTEGRATOR || \
++                 ARCH_EBSA285 || ARCH_EP93XX || ARCH_IMX || ARCH_INTEGRATOR || \
+                  ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \
+                  ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
+                  ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE
+@@ -432,7 +445,7 @@ config LEDS
+ config LEDS_TIMER
+       bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
+-                          MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
++                           MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
+       depends on LEDS
+       default y if ARCH_EBSA110
+       help
+@@ -702,9 +715,10 @@ source "drivers/block/Kconfig"
+ source "drivers/acorn/block/Kconfig"
+-if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
+-      || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
+-      || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
++if PCMCIA || ARCH_CLPS7500 || ARCH_EP9312 || ARCH_EP9315 \
++      || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X \
++      || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK \
++      || FOOTBRIDGE
+ source "drivers/ide/Kconfig"
+ endif
+diff --git a/arch/arm/Makefile b/arch/arm/Makefile
+index 81bd219..924d31f 100644
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -92,6 +92,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET)   := 0x
+  machine-$(CONFIG_ARCH_IOP3XX)           := iop3xx
+  machine-$(CONFIG_ARCH_IXP4XX)           := ixp4xx
+  machine-$(CONFIG_ARCH_IXP2000)    := ixp2000
++ machine-$(CONFIG_ARCH_EP93XX)     := ep93xx
+  machine-$(CONFIG_ARCH_OMAP1)    := omap1
+  machine-$(CONFIG_ARCH_OMAP2)    := omap2
+   incdir-$(CONFIG_ARCH_OMAP)     := omap
+diff --git a/arch/arm/configs/adssphere_defconfig b/arch/arm/configs/adssphere_defconfig
+new file mode 100644
+index 0000000..195d80e
+--- /dev/null
++++ b/arch/arm/configs/adssphere_defconfig
+@@ -0,0 +1,1240 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.12.2
++# Wed Jul  6 13:49:08 2005
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_IOMAP=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_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 is not set
++# 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_CC_OPTIMIZE_FOR_SIZE=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 is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_H720X is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++CONFIG_ARCH_EP9315=y
++# CONFIG_MACH_EDB9315 is not set
++CONFIG_MACH_ADSSPHERE=y
++# CONFIG_MACH_ZEFEERDZQ is not set
++CONFIG_EP93XX_DMA=y
++# CONFIG_ARCH_EP93XX_IDE is not set
++# CONFIG_EP93XX_SSP is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_THUMB is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++CONFIG_ISA_DMA_API=y
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++CONFIG_PCCARD=y
++# CONFIG_PCMCIA_DEBUG is not set
++CONFIG_PCMCIA=y
++
++#
++# PC-card bridges
++#
++# CONFIG_TCIC is not set
++CONFIG_PCMCIA_EP93XX=y
++
++#
++# Kernel Features
++#
++# CONFIG_SMP is not set
++# CONFIG_PREEMPT is not set
++CONFIG_DISCONTIGMEM=y
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++# CONFIG_LEDS_CPU is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="console=ttyAM0,38400 rw root=/dev/ram initrd=0x00600000,5m ramdisk_size=12288 rootfstype=ext2 mtdparts=flash:256k(boot),256k(bootvars),1536k(zImage),5m(ramdisk.gz),-(flashfs1) SERIALGETTY=ttyAM0 SERIALBAUD=38400"
++# CONFIG_XIP_KERNEL is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER 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=y
++# CONFIG_MTD_AFS_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=y
++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=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 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 is not set
++# CONFIG_MTD_ABSENT is not set
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_ADSFLASH=y
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++
++#
++# Self-contained MTD device drivers
++#
++# 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_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_UB 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_INITRAMFS_SOURCE=""
++# 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_IDECS=y
++# CONFIG_BLK_DEV_IDECD is not set
++# 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_EP93XX=y
++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
++CONFIG_IDE_ARM=y
++# CONFIG_BLK_DEV_IDEDMA is not set
++# CONFIG_IDEDMA_AUTO is not set
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++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 is not set
++CONFIG_CHR_DEV_SG=y
++
++#
++# 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 is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# PCMCIA SCSI adapter support
++#
++# CONFIG_PCMCIA_AHA152X is not set
++# CONFIG_PCMCIA_FDOMAIN is not set
++# CONFIG_PCMCIA_NINJA_SCSI is not set
++# CONFIG_PCMCIA_QLOGIC is not set
++# CONFIG_PCMCIA_SYM53C500 is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Fusion MPT device support
++#
++
++#
++# IEEE 1394 (FireWire) support
++#
++
++#
++# I2O device support
++#
++
++#
++# Networking support
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++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=y
++# CONFIG_IP_PIMSM_V1 is not set
++# CONFIG_IP_PIMSM_V2 is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_IP_TCPDIAG=y
++# CONFIG_IP_TCPDIAG_IPV6 is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER 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
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++CONFIG_BT=y
++CONFIG_BT_L2CAP=y
++# CONFIG_BT_SCO is not set
++# CONFIG_BT_RFCOMM is not set
++CONFIG_BT_BNEP=y
++# CONFIG_BT_BNEP_MC_FILTER is not set
++# CONFIG_BT_BNEP_PROTO_FILTER is not set
++# CONFIG_BT_HIDP is not set
++
++#
++# Bluetooth device drivers
++#
++CONFIG_BT_HCIUSB=y
++# CONFIG_BT_HCIUSB_SCO is not set
++# CONFIG_BT_HCIUART is not set
++# CONFIG_BT_HCIBCM203X is not set
++# CONFIG_BT_HCIBPA10X is not set
++# CONFIG_BT_HCIBFUSB is not set
++# CONFIG_BT_HCIDTL1 is not set
++# CONFIG_BT_HCIBT3C is not set
++# CONFIG_BT_HCIBLUECARD is not set
++# CONFIG_BT_HCIBTUART is not set
++# CONFIG_BT_HCIVHCI is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++CONFIG_NET_RADIO=y
++
++#
++# Obsolete Wireless cards support (pre-802.11)
++#
++# CONFIG_STRIP is not set
++# CONFIG_PCMCIA_WAVELAN is not set
++# CONFIG_PCMCIA_NETWAVE is not set
++
++#
++# Wireless 802.11 Frequency Hopping cards support
++#
++# CONFIG_PCMCIA_RAYCS is not set
++
++#
++# Wireless 802.11b ISA/PCI cards support
++#
++CONFIG_HERMES=y
++CONFIG_ATMEL=y
++
++#
++# Wireless 802.11b Pcmcia/Cardbus cards support
++#
++CONFIG_PCMCIA_HERMES=y
++CONFIG_AIRO_CS=y
++CONFIG_PCMCIA_ATMEL=y
++CONFIG_PCMCIA_WL3501=y
++CONFIG_NET_WIRELESS=y
++
++#
++# PCMCIA network device support
++#
++CONFIG_NET_PCMCIA=y
++# CONFIG_PCMCIA_3C589 is not set
++# CONFIG_PCMCIA_3C574 is not set
++# CONFIG_PCMCIA_FMVJ18X is not set
++CONFIG_PCMCIA_PCNET=y
++# CONFIG_PCMCIA_NMCLAN is not set
++# CONFIG_PCMCIA_SMC91C92 is not set
++# CONFIG_PCMCIA_XIRC2PS is not set
++# CONFIG_PCMCIA_AXNET is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN 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=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_TSDEV=y
++CONFIG_INPUT_TSDEV_SCREEN_X=640
++CONFIG_INPUT_TSDEV_SCREEN_Y=480
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_EP93XX is not set
++CONFIG_INPUT_MOUSE=y
++# CONFIG_MOUSE_PS2 is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++CONFIG_TOUCHSCREEN_EP93XX=y
++# 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 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++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_EP93XX_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++# CONFIG_EP93XX_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_DRM is not set
++
++#
++# PCMCIA character devices
++#
++# CONFIG_SYNCLINK_CS is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Hardware Sensors Chip support
++#
++CONFIG_I2C_SENSOR=y
++# 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_ASB100 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# 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_SMSC47B397 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++
++#
++# Other I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++CONFIG_SENSORS_DS1307=y
++CONFIG_SENSORS_EEPROM=y
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 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
++
++#
++# Misc devices
++#
++
++#
++# Multimedia devices
++#
++CONFIG_VIDEO_DEV=y
++
++#
++# Video For Linux
++#
++
++#
++# Video Adapters
++#
++# CONFIG_VIDEO_CPIA is not set
++# CONFIG_VIDEO_SAA5246A is not set
++# CONFIG_VIDEO_SAA5249 is not set
++# CONFIG_TUNER_3036 is not set
++# CONFIG_VIDEO_OVCAMCHIP is not set
++
++#
++# Radio Adapters
++#
++# CONFIG_RADIO_MAESTRO is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# Graphics support
++#
++CONFIG_FB=y
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++CONFIG_FB_SOFT_CURSOR=y
++# CONFIG_FB_MACMODES is not set
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_TILEBLITTING is not set
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_CX25871_I2C is not set
++CONFIG_FB_EP93XX=y
++# CONFIG_FB_CRT_EP93XX is not set
++# CONFIG_FB_LCD_EP93XX is not set
++# CONFIG_FB_LCD_EP93XX_SHARP is not set
++CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343=y
++# CONFIG_FB_CX25871 is not set
++# CONFIG_FB_EP93XX_8BPP is not set
++CONFIG_FB_EP93XX_16BPP_565=y
++# CONFIG_FB_EP93XX_24BPP is not set
++# CONFIG_FB_EP93XX_32BPP is not set
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++# CONFIG_FONT_MINI_4x6 is not set
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++
++#
++# Logo configuration
++#
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_LOGO_LINUX_CLUT224=y
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++# CONFIG_SND is not set
++
++#
++# Open Sound System
++#
++CONFIG_SOUND_PRIME=y
++# CONFIG_SOUND_BT878 is not set
++# CONFIG_SOUND_FUSION is not set
++# CONFIG_SOUND_CS4281 is not set
++# CONFIG_SOUND_SONICVIBES is not set
++# CONFIG_SOUND_TRIDENT is not set
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++CONFIG_SOUND_OSS=y
++# CONFIG_SOUND_TRACEINIT is not set
++# CONFIG_SOUND_DMAP is not set
++# CONFIG_SOUND_AD1816 is not set
++# CONFIG_SOUND_SGALAXY is not set
++# CONFIG_SOUND_ADLIB is not set
++# CONFIG_SOUND_ACI_MIXER is not set
++# CONFIG_SOUND_CS4232 is not set
++# CONFIG_SOUND_SSCAPE is not set
++# CONFIG_SOUND_GUS is not set
++# CONFIG_SOUND_VMIDI is not set
++# CONFIG_SOUND_TRIX is not set
++# CONFIG_SOUND_MSS is not set
++# CONFIG_SOUND_MPU401 is not set
++# CONFIG_SOUND_NM256 is not set
++# CONFIG_SOUND_MAD16 is not set
++# CONFIG_SOUND_PAS is not set
++# CONFIG_SOUND_PSS is not set
++# CONFIG_SOUND_SB is not set
++# CONFIG_SOUND_AWE32_SYNTH is not set
++# CONFIG_SOUND_WAVEFRONT is not set
++# CONFIG_SOUND_MAUI is not set
++# CONFIG_SOUND_YM3812 is not set
++# CONFIG_SOUND_OPL3SA1 is not set
++# CONFIG_SOUND_OPL3SA2 is not set
++# CONFIG_SOUND_UART6850 is not set
++# CONFIG_SOUND_AEDSP16 is not set
++CONFIG_SOUND_EP93XX_AC97=y
++# CONFIG_SOUND_TVMIXER is not set
++# CONFIG_SOUND_AD1980 is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++# 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_SL811_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_AUDIO is not set
++
++#
++# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
++#
++# CONFIG_USB_MIDI 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 is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# 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_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE 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
++# CONFIG_USB_VICAM is not set
++# CONFIG_USB_DSBR is not set
++# CONFIG_USB_IBMCAM is not set
++# CONFIG_USB_KONICAWC is not set
++CONFIG_USB_OV511=y
++# CONFIG_USB_SE401 is not set
++# CONFIG_USB_SN9C102 is not set
++# CONFIG_USB_STV680 is not set
++# CONFIG_USB_PWC is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++CONFIG_USB_PEGASUS=y
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_USB_ZD1201 is not set
++CONFIG_USB_MON=y
++
++#
++# 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
++
++#
++# USB ATM/DSL drivers
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++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
++
++#
++# XFS support
++#
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++# CONFIG_MSDOS_FS is not set
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++# CONFIG_DEVFS_FS is not set
++CONFIG_DEVPTS_FS_XATTR=y
++# CONFIG_DEVPTS_FS_SECURITY is not set
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_XATTR is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# 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_NAND is not set
++# CONFIG_JFFS2_FS_NOR_ECC is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# 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_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_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
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++CONFIG_NLS_CODEPAGE_850=y
++# 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=y
++# 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=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_LOG_BUF_SHIFT=14
++# 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_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_FS is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_LL is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Hardware crypto devices
++#
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/dma03_defconfig b/arch/arm/configs/dma03_defconfig
+new file mode 100644
+index 0000000..59b677c
+--- /dev/null
++++ b/arch/arm/configs/dma03_defconfig
+@@ -0,0 +1,1281 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.15-rc4
++# Fri Dec  9 21:21:27 2005
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++# CONFIG_CLEAN_COMPILE is not set
++CONFIG_BROKEN=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 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_CC_OPTIMIZE_FOR_SIZE=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=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_AAEC2000 is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++CONFIG_ARCH_EP9315=y
++# CONFIG_MACH_EDB9315 is not set
++# CONFIG_MACH_ADSSPHERE is not set
++# CONFIG_MACH_ZEFEERDZQ is not set
++CONFIG_MACH_DMA03=y
++CONFIG_ARCH_EP93XX_GPIO_IRQ=y
++CONFIG_EP93XX_DMA=y
++CONFIG_EP93XX_SSP=y
++CONFIG_EP93XX_SSP_CIRRUS=y
++# CONFIG_EP93XX_SSP_LINUX is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_THUMB is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++CONFIG_ISA_DMA_API=y
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_PREEMPT is not set
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
++CONFIG_SELECT_MEMORY_MODEL=y
++# CONFIG_FLATMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM_MANUAL=y
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_NEED_MULTIPLE_NODES=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="root=/dev/hda1 slram=sram,0x20000000,0x2010000 parport=0xD0000020,74 lp=parport0"
++# CONFIG_XIP_KERNEL is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_AOUT=y
++CONFIG_BINFMT_MISC=y
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++
++#
++# 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 is not set
++# 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 is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_BIC=y
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER 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
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED 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 is not set
++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=y
++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
++CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_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
++# CONFIG_RFD_FTL 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 is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++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=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++CONFIG_MTD_CFI_AMDSTD_RETRY=0
++CONFIG_MTD_CFI_STAA=y
++CONFIG_MTD_CFI_UTIL=y
++CONFIG_MTD_RAM=y
++CONFIG_MTD_ROM=y
++CONFIG_MTD_ABSENT=y
++# CONFIG_MTD_OBSOLETE_CHIPS is not set
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x60000000
++CONFIG_MTD_PHYSMAP_LEN=0x02000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_IMPA7 is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_SLRAM=y
++CONFIG_MTD_PHRAM=y
++# 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=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++
++#
++# OneNAND Flash Device Drivers
++#
++# CONFIG_MTD_ONENAND is not set
++
++#
++# Parallel port support
++#
++CONFIG_PARPORT=y
++CONFIG_PARPORT_PC=y
++# CONFIG_PARPORT_PC_FIFO is not set
++# CONFIG_PARPORT_PC_SUPERIO is not set
++# CONFIG_PARPORT_ARC is not set
++# CONFIG_PARPORT_GSC is not set
++CONFIG_PARPORT_1284=y
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_PARIDE 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_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=12288
++CONFIG_BLK_DEV_INITRD=y
++# CONFIG_CDROM_PKTCDVD is not set
++# 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=y
++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_EP93XX=y
++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
++CONFIG_IDE_ARM=y
++# CONFIG_BLK_DEV_IDEDMA is not set
++# CONFIG_IDEDMA_AUTO is not set
++# 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 is not set
++# CONFIG_CHR_DEV_SG is not set
++# 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 is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# 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_ISCSI_TCP is not set
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_PPA is not set
++# CONFIG_SCSI_IMM 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
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# PHY device support
++#
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_NET_POCKET is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PLIP is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++CONFIG_NETCONSOLE=y
++CONFIG_NETPOLL=y
++# CONFIG_NETPOLL_RX is not set
++# CONFIG_NETPOLL_TRAP is not set
++CONFIG_NET_POLL_CONTROLLER=y
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN 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=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# 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=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++CONFIG_KEYBOARD_EP93XX=y
++CONFIG_KEYBOARD_EP93XX_SPI=y
++CONFIG_KEYBOARD_EP93XX_8X8=y
++CONFIG_KEYBOARD_EP93XX_8X8_CYCLING=y
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++CONFIG_TOUCHSCREEN_EP93XX=y
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_PARKBD is not set
++# CONFIG_SERIO_AMBAKMI is not set
++CONFIG_SERIO_LIBPS2=y
++# 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=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++CONFIG_PRINTER=m
++# CONFIG_LP_CONSOLE is not set
++CONFIG_PPDEV=m
++# CONFIG_TIPAR is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++
++#
++# Watchdog Cards
++#
++# CONFIG_WATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++# CONFIG_EP93XX_RTC is not set
++CONFIG_DS1337_RTC=y
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++
++#
++# CAN bus devices
++#
++CONFIG_CAN_BUS=y
++CONFIG_OKI_CAN_ML9620=y
++# CONFIG_OKI_CAN_ML9620_MICRO9 is not set
++CONFIG_OKI_CAN_ML9620_GASSNER=y
++CONFIG_OKI_CAN_ML9620_2DEV=y
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_TELCLOCK is not set
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_PARPORT is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++CONFIG_SENSORS_DS1337=y
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_SENSORS_DS1307 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# 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_MAX6875 is not set
++# CONFIG_RTC_X1205_I2C 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
++
++#
++# 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 is not set
++# 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_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 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=y
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_MACMODES is not set
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_TILEBLITTING is not set
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_CX25871_I2C is not set
++CONFIG_FB_EP93XX=y
++# CONFIG_FB_CRT_EP93XX is not set
++# CONFIG_FB_LCD_EP93XX is not set
++CONFIG_FB_LCD_EP93XX_SHARP=y
++# CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343 is not set
++# CONFIG_FB_CX25871 is not set
++# CONFIG_FB_LCD_TX09D50VM1CCA is not set
++# CONFIG_FB_EP93XX_8BPP is not set
++# CONFIG_FB_EP93XX_16BPP_565 is not set
++# CONFIG_FB_EP93XX_24BPP is not set
++CONFIG_FB_EP93XX_32BPP=y
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++CONFIG_FONT_6x11=y
++CONFIG_FONT_7x14=y
++CONFIG_FONT_PEARL_8x8=y
++CONFIG_FONT_ACORN_8x8=y
++CONFIG_FONT_MINI_4x6=y
++CONFIG_FONT_SUN8x16=y
++CONFIG_FONT_SUN12x22=y
++CONFIG_FONT_10x18=y
++
++#
++# Logo configuration
++#
++# CONFIG_LOGO is not set
++CONFIG_BACKLIGHT_LCD_SUPPORT=y
++CONFIG_BACKLIGHT_CLASS_DEVICE=y
++CONFIG_BACKLIGHT_DEVICE=y
++CONFIG_LCD_CLASS_DEVICE=y
++CONFIG_LCD_DEVICE=y
++
++#
++# Sound
++#
++CONFIG_SOUND=m
++
++#
++# Advanced Linux Sound Architecture
++#
++# CONFIG_SND is not set
++
++#
++# Open Sound System
++#
++CONFIG_SOUND_PRIME=m
++# CONFIG_OBSOLETE_OSS_DRIVER is not set
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++CONFIG_SOUND_OSS=m
++# CONFIG_SOUND_TRACEINIT is not set
++# CONFIG_SOUND_DMAP is not set
++# CONFIG_SOUND_AD1816 is not set
++# CONFIG_SOUND_ADLIB is not set
++# CONFIG_SOUND_ACI_MIXER is not set
++# CONFIG_SOUND_VMIDI is not set
++# CONFIG_SOUND_TRIX is not set
++# CONFIG_SOUND_MSS is not set
++# CONFIG_SOUND_MPU401 is not set
++# CONFIG_SOUND_PAS is not set
++# CONFIG_SOUND_PSS is not set
++# CONFIG_SOUND_SB is not set
++# CONFIG_SOUND_OPL3SA2 is not set
++# CONFIG_SOUND_UART6850 is not set
++# CONFIG_SOUND_AEDSP16 is not set
++CONFIG_SOUND_EP93XX_AC97=m
++CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297=y
++# CONFIG_SOUND_EP93XX_AUDIO_PIO is not set
++# CONFIG_SOUND_TVMIXER 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_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_SL811_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
++# CONFIG_USB_ACM is not set
++CONFIG_USB_PRINTER=y
++
++#
++# 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=y
++CONFIG_USB_STORAGE_ISD200=y
++CONFIG_USB_STORAGE_DPCM=y
++CONFIG_USB_STORAGE_USBAT=y
++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=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_USS720 is not set
++
++#
++# 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_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
++
++#
++# 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=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++CONFIG_REISERFS_FS=y
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_REISERFS_FS_XATTR 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=y
++CONFIG_INOTIFY=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++CONFIG_AUTOFS_FS=y
++# CONFIG_AUTOFS4_FS is not set
++CONFIG_FUSE_FS=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_ZISOFS_FS=y
++CONFIG_UDF_FS=y
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=850
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++# CONFIG_NTFS_RW is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_HUGETLBFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++CONFIG_RELAYFS_FS=y
++
++#
++# 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_SUMMARY is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE 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=y
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++CONFIG_NLS_CODEPAGE_850=y
++# 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=y
++CONFIG_NLS_ISO8859_1=y
++# 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=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_LOG_BUF_SHIFT=17
++# CONFIG_DETECT_SOFTLOCKUP is not set
++# 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_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_FS is not set
++# CONFIG_DEBUG_VM is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_TORTURE_TEST is not set
++CONFIG_DEBUG_USER=y
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC 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=y
++CONFIG_CRYPTO_MD4=y
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=y
++CONFIG_CRYPTO_SHA256=y
++CONFIG_CRYPTO_SHA512=y
++CONFIG_CRYPTO_WP512=y
++CONFIG_CRYPTO_TGR192=y
++CONFIG_CRYPTO_DES=y
++CONFIG_CRYPTO_BLOWFISH=y
++CONFIG_CRYPTO_TWOFISH=y
++CONFIG_CRYPTO_SERPENT=y
++CONFIG_CRYPTO_AES=y
++CONFIG_CRYPTO_CAST5=y
++CONFIG_CRYPTO_CAST6=y
++CONFIG_CRYPTO_TEA=y
++CONFIG_CRYPTO_ARC4=y
++CONFIG_CRYPTO_KHAZAD=y
++CONFIG_CRYPTO_ANUBIS=y
++CONFIG_CRYPTO_DEFLATE=y
++CONFIG_CRYPTO_MICHAEL_MIC=y
++CONFIG_CRYPTO_CRC32C=y
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Hardware crypto devices
++#
++
++#
++# Library routines
++#
++CONFIG_CRC_CCITT=y
++CONFIG_CRC16=y
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/edb9301_defconfig b/arch/arm/configs/edb9301_defconfig
+new file mode 100644
+index 0000000..e105976
+--- /dev/null
++++ b/arch/arm/configs/edb9301_defconfig
+@@ -0,0 +1,965 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.9-rc2-ep93xx
++# Mon Nov  8 16:32:53 2004
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_IOMAP=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_CLEAN_COMPILE=y
++CONFIG_BROKEN_ON_SMP=y
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++# CONFIG_SWAP is not set
++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_LOG_BUF_SHIFT=14
++CONFIG_HOTPLUG=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_EMBEDDED=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++CONFIG_IOSCHED_DEADLINE=y
++# CONFIG_IOSCHED_CFQ is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++# CONFIG_TINY_SHMEM is not set
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE_PB is not set
++# CONFIG_ARCH_IMX is not set
++
++#
++# EP93xx
++#
++CONFIG_ARCH_EP9301=y
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++# CONFIG_ARCH_EP9315 is not set
++CONFIG_MACH_EDB9301=y
++# CONFIG_MACH_TTML is not set
++CONFIG_EP93XX_DMA=y
++CONFIG_EP93XX_SSP=y
++CONFIG_EP93XX_SSP_CIRRUS=y
++# CONFIG_EP93XX_SSP_LINUX is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# General setup
++#
++CONFIG_DISCONTIGMEM=y
++CONFIG_ARM_AMBA=y
++# CONFIG_ZBOOT_ROM is not set
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++
++#
++# PCMCIA/CardBus support
++#
++# CONFIG_PCMCIA is not set
++
++#
++# At least one math emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_PM is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_ARTHUR is not set
++CONFIG_CMDLINE="root=/dev/nfs ip=dhcp"
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_REDBOOT_PARTS=y
++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_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 is not set
++# 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=y
++# CONFIG_MTD_CFI_I2 is not set
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 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=y
++CONFIG_MTD_PHYSMAP_START=0x60000000
++CONFIG_MTD_PHYSMAP_LEN=0x01000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLKMTD 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
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Networking support
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++# CONFIG_NETLINK_DEV is not set
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++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_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER 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_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI=y
++# CONFIG_SCSI_PROC_FS is not set
++
++#
++# 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 is not set
++# CONFIG_CHR_DEV_SG 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 is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Fusion MPT device support
++#
++
++#
++# IEEE 1394 (FireWire) support
++#
++
++#
++# I2O device support
++#
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++CONFIG_INPUT_EVDEV=y
++CONFIG_INPUT_EVBUG=y
++
++#
++# Input I/O drivers
++#
++# CONFIG_GAMEPORT is not set
++CONFIG_SOUND_GAMEPORT=y
++# CONFIG_SERIO 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=y
++CONFIG_INPUT_UINPUT=y
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# 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_EP93XX_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++CONFIG_EP93XX_RTC=y
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_DRM is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_EP93XX is not set
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_SCx200_ACB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Hardware Sensors Chip support
++#
++# CONFIG_I2C_SENSOR is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_IT87 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_LM90 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++
++#
++# Other I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++CONFIG_I2C_DEBUG_CORE=y
++CONFIG_I2C_DEBUG_ALGO=y
++CONFIG_I2C_DEBUG_BUS=y
++CONFIG_I2C_DEBUG_CHIP=y
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_JBD is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++# CONFIG_MSDOS_FS is not set
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++# CONFIG_DEVFS_FS is not set
++CONFIG_DEVPTS_FS_XATTR=y
++CONFIG_DEVPTS_FS_SECURITY=y
++CONFIG_TMPFS=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# 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_NAND is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE 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_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_EXPORTFS is not set
++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
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# 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=y
++# 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
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Graphics support
++#
++# CONFIG_FB is not set
++# CONFIG_FB_CX25871_I2C is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++# CONFIG_SND_SEQUENCER is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=y
++CONFIG_SND_PCM_OSS=y
++CONFIG_SND_VERBOSE_PRINTK=y
++CONFIG_SND_DEBUG=y
++CONFIG_SND_DEBUG_MEMORY=y
++CONFIG_SND_DEBUG_DETECT=y
++
++#
++# Generic devices
++#
++CONFIG_SND_DUMMY=y
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA ARM devices
++#
++
++#
++# ALSA USB devices
++#
++# CONFIG_SND_USB_AUDIO is not set
++# CONFIG_SND_USB_USX2Y is not set
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++
++#
++# Misc devices
++#
++
++#
++# USB support
++#
++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 is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811HS is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_AUDIO is not set
++# CONFIG_USB_BLUETOOTH_TTY is not set
++# CONFIG_USB_MIDI is not set
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++CONFIG_USB_STORAGE_RW_DETECT=y
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_HP8200e is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# USB Human Interface Devices (HID)
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_HPUSBSCSI is not set
++
++#
++# USB Multimedia devices
++#
++# CONFIG_USB_DABUSB is not set
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network adaptors
++#
++# 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
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++CONFIG_USB_SERIAL=y
++# CONFIG_USB_SERIAL_CONSOLE is not set
++# CONFIG_USB_SERIAL_GENERIC is not set
++# CONFIG_USB_SERIAL_BELKIN is not set
++# CONFIG_USB_SERIAL_WHITEHEAT is not set
++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
++# CONFIG_USB_SERIAL_EMPEG is not set
++# CONFIG_USB_SERIAL_FTDI_SIO is not set
++# CONFIG_USB_SERIAL_VISOR is not set
++# CONFIG_USB_SERIAL_IPAQ is not set
++# CONFIG_USB_SERIAL_IR is not set
++# CONFIG_USB_SERIAL_EDGEPORT is not set
++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
++# CONFIG_USB_SERIAL_KEYSPAN is not set
++# CONFIG_USB_SERIAL_KLSI is not set
++# CONFIG_USB_SERIAL_KOBIL_SCT is not set
++# CONFIG_USB_SERIAL_MCT_U232 is not set
++CONFIG_USB_SERIAL_PL2303=y
++# CONFIG_USB_SERIAL_SAFE is not set
++# CONFIG_USB_SERIAL_CYBERJACK is not set
++# CONFIG_USB_SERIAL_XIRCOM is not set
++# CONFIG_USB_SERIAL_OMNINET is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_TIGL 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_PHIDGETSERVO is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# Kernel hacking
++#
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_DEBUG_SLAB=y
++CONFIG_DEBUG_SPINLOCK=y
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_WAITQ=y
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_LL_PRINTK_HACK is not set
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/edb9312_defconfig b/arch/arm/configs/edb9312_defconfig
+new file mode 100644
+index 0000000..1a0aa51
+--- /dev/null
++++ b/arch/arm/configs/edb9312_defconfig
+@@ -0,0 +1,920 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.9-rc2-ep93xx
++# Mon Nov  8 16:40:30 2004
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_IOMAP=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++# CONFIG_CLEAN_COMPILE is not set
++CONFIG_BROKEN=y
++CONFIG_BROKEN_ON_SMP=y
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++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_LOG_BUF_SHIFT=14
++# CONFIG_HOTPLUG is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++# CONFIG_EMBEDDED is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++# CONFIG_TINY_SHMEM is not set
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE_PB is not set
++# CONFIG_ARCH_IMX is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++# CONFIG_ARCH_EP9302 is not set
++CONFIG_ARCH_EP9312=y
++# CONFIG_ARCH_EP9315 is not set
++CONFIG_MACH_EDB9312=y
++# CONFIG_MACH_ACC is not set
++CONFIG_EP93XX_DMA=y
++CONFIG_ARCH_EP93XX_IDE=y
++CONFIG_EP93XX_SSP=y
++CONFIG_EP93XX_SSP_CIRRUS=y
++# CONFIG_EP93XX_SSP_LINUX is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_THUMB is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# General setup
++#
++CONFIG_DISCONTIGMEM=y
++CONFIG_ARM_AMBA=y
++# CONFIG_ZBOOT_ROM is not set
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++
++#
++# At least one math emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_AOUT=y
++CONFIG_BINFMT_MISC=y
++
++#
++# Generic Driver Options
++#
++# CONFIG_STANDALONE is not set
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_PM is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_ARTHUR is not set
++CONFIG_CMDLINE="root=/dev/hda1"
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_PARTITIONS=y
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_REDBOOT_PARTS=y
++CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++CONFIG_FTL=y
++CONFIG_NFTL=y
++CONFIG_NFTL_RW=y
++CONFIG_INFTL=y
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++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=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_CFI_AMDSTD=y
++CONFIG_MTD_CFI_AMDSTD_RETRY=0
++CONFIG_MTD_CFI_STAA=y
++CONFIG_MTD_CFI_UTIL=y
++CONFIG_MTD_RAM=y
++CONFIG_MTD_ROM=y
++CONFIG_MTD_ABSENT=y
++# CONFIG_MTD_OBSOLETE_CHIPS is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x60000000
++CONFIG_MTD_PHYSMAP_LEN=0x02000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++# CONFIG_MTD_IMPA7 is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_SLRAM=y
++CONFIG_MTD_PHRAM=y
++CONFIG_MTD_MTDRAM=y
++CONFIG_MTDRAM_TOTAL_SIZE=512
++CONFIG_MTDRAM_ERASE_SIZE=1
++CONFIG_MTDRAM_ABS_POS=0x20000000
++# CONFIG_MTD_BLKMTD 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=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD 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_RAM=y
++CONFIG_BLK_DEV_RAM_SIZE=12288
++CONFIG_BLK_DEV_INITRD=y
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Networking support
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++# CONFIG_NETLINK_DEV is not set
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# 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 is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER 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_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++CONFIG_NETPOLL=y
++# CONFIG_NETPOLL_RX is not set
++# CONFIG_NETPOLL_TRAP is not set
++CONFIG_NET_POLL_CONTROLLER=y
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++CONFIG_NETCONSOLE=y
++
++#
++# 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=y
++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
++# CONFIG_IDE_TASKFILE_IO is not set
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++CONFIG_BLK_DEV_EP93XX=y
++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
++CONFIG_IDE_ARM=y
++# CONFIG_BLK_DEV_IDEDMA is not set
++# CONFIG_IDEDMA_AUTO is not set
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI=y
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG 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 is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Fusion MPT device support
++#
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN 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=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# 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 I/O drivers
++#
++# CONFIG_GAMEPORT is not set
++CONFIG_SOUND_GAMEPORT=y
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_CT82C710 is not set
++# CONFIG_SERIO_AMBAKMI is not set
++# CONFIG_SERIO_RAW is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++CONFIG_KEYBOARD_EP93XX=y
++CONFIG_KEYBOARD_EP93XX_SPI=y
++CONFIG_KEYBOARD_EP93XX_8X8=y
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++CONFIG_TOUCHSCREEN_EP93XX=y
++# CONFIG_INPUT_MISC 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 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++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 is not set
++# CONFIG_RTC is not set
++# CONFIG_EP93XX_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_DRM is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_SCx200_ACB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Hardware Sensors Chip support
++#
++CONFIG_I2C_SENSOR=y
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_IT87 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_LM90 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++
++#
++# Other I2C Chip support
++#
++CONFIG_SENSORS_DS1337=y
++CONFIG_SENSORS_EEPROM=y
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 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
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++CONFIG_REISERFS_FS=y
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_REISERFS_FS_XATTR is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++CONFIG_ROMFS_FS=y
++# CONFIG_QUOTA is not set
++CONFIG_AUTOFS_FS=y
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_ZISOFS_FS=y
++CONFIG_UDF_FS=y
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++# CONFIG_DEVFS_FS is not set
++# CONFIG_DEVFS_MOUNT is not set
++# CONFIG_DEVFS_DEBUG is not set
++# CONFIG_DEVPTS_FS_XATTR is not set
++CONFIG_TMPFS=y
++# CONFIG_HUGETLBFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# 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_NAND is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE 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_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_EXPORTFS is not set
++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
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# 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=y
++CONFIG_NLS_ISO8859_1=y
++# 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=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Graphics support
++#
++CONFIG_FB=y
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_CX25871_I2C is not set
++CONFIG_FB_EP93XX=y
++# CONFIG_FB_CRT_EP93XX is not set
++CONFIG_FB_LCD_EP93XX=y
++# CONFIG_FB_LCD_EP93XX_SHARP is not set
++# CONFIG_FB_CX25871 is not set
++# CONFIG_FB_EP93XX_8BPP is not set
++# CONFIG_FB_EP93XX_16BPP_565 is not set
++# CONFIG_FB_EP93XX_24BPP is not set
++CONFIG_FB_EP93XX_32BPP=y
++# CONFIG_FB_VIRTUAL is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++CONFIG_FONT_6x11=y
++CONFIG_FONT_PEARL_8x8=y
++CONFIG_FONT_ACORN_8x8=y
++# CONFIG_FONT_MINI_4x6 is not set
++CONFIG_FONT_SUN8x16=y
++CONFIG_FONT_SUN12x22=y
++
++#
++# Logo configuration
++#
++CONFIG_LOGO=y
++CONFIG_LOGO_LINUX_MONO=y
++CONFIG_LOGO_LINUX_VGA16=y
++CONFIG_LOGO_LINUX_CLUT224=y
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++# CONFIG_SND is not set
++
++#
++# Open Sound System
++#
++CONFIG_SOUND_PRIME=y
++# CONFIG_SOUND_BT878 is not set
++# CONFIG_SOUND_FUSION is not set
++# CONFIG_SOUND_CS4281 is not set
++# CONFIG_SOUND_SONICVIBES is not set
++# CONFIG_SOUND_TRIDENT is not set
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++# CONFIG_SOUND_OSS is not set
++# CONFIG_SOUND_TVMIXER is not set
++# CONFIG_SOUND_AD1980 is not set
++
++#
++# Misc devices
++#
++
++#
++# USB support
++#
++# CONFIG_USB is not set
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# Kernel hacking
++#
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++CONFIG_DEBUG_LL_PRINTK_HACK=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_CRC_CCITT=y
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/edb9315_defconfig b/arch/arm/configs/edb9315_defconfig
+new file mode 100644
+index 0000000..3e6033b
+--- /dev/null
++++ b/arch/arm/configs/edb9315_defconfig
+@@ -0,0 +1,954 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.9-rc2-ep93xx
++# Mon Nov  8 17:01:50 2004
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_IOMAP=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++# CONFIG_CLEAN_COMPILE is not set
++CONFIG_BROKEN=y
++CONFIG_BROKEN_ON_SMP=y
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++CONFIG_SYSCTL=y
++# CONFIG_AUDIT is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_HOTPLUG is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_EMBEDDED=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++# CONFIG_TINY_SHMEM is not set
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE_PB is not set
++# CONFIG_ARCH_IMX is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++CONFIG_ARCH_EP9315=y
++CONFIG_MACH_EDB9315=y
++CONFIG_EP93XX_DMA=y
++# CONFIG_ARCH_EP93XX_IDE is not set
++CONFIG_EP93XX_SSP=y
++CONFIG_EP93XX_SSP_CIRRUS=y
++# CONFIG_EP93XX_SSP_LINUX is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# General setup
++#
++CONFIG_DISCONTIGMEM=y
++CONFIG_ARM_AMBA=y
++# CONFIG_ZBOOT_ROM is not set
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++
++#
++# At least one math emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_PM is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_ARTHUR is not set
++CONFIG_CMDLINE="console=ttyCL0 map=mtd6,0x30000000,+0x200000 root=/dev/nfs nfsroot=192.168.1.224:/nfsarm_grma video=ep93xxfb ip=192.168.1.220:192.168.1.224:192.168.1.2:255.255.255.0::eth0:"
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++CONFIG_MTD_DEBUG=y
++CONFIG_MTD_DEBUG_VERBOSE=3
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_REDBOOT_PARTS=y
++CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
++CONFIG_MTD_REDBOOT_PARTS_READONLY=y
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_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 is not set
++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_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=y
++CONFIG_MTD_ROM=y
++# CONFIG_MTD_ABSENT is not set
++# CONFIG_MTD_OBSOLETE_CHIPS is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x60000000
++CONFIG_MTD_PHYSMAP_LEN=0x2000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++CONFIG_MTD_MTDRAM=y
++CONFIG_MTDRAM_TOTAL_SIZE=512
++CONFIG_MTDRAM_ERASE_SIZE=128
++CONFIG_MTDRAM_ABS_POS=0x20000000
++# CONFIG_MTD_BLKMTD 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
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD 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_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Networking support
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++# CONFIG_NETLINK_DEV is not set
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# 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 is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER 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_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++
++#
++# ATA/ATAPI/MFM/RLL support
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++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 is not set
++CONFIG_CHR_DEV_SG=y
++
++#
++# 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 is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Fusion MPT device support
++#
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN 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=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# 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 I/O drivers
++#
++# CONFIG_GAMEPORT is not set
++CONFIG_SOUND_GAMEPORT=y
++CONFIG_SERIO=y
++# CONFIG_SERIO_SERPORT is not set
++# CONFIG_SERIO_CT82C710 is not set
++# CONFIG_SERIO_AMBAKMI is not set
++# CONFIG_SERIO_RAW is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++CONFIG_KEYBOARD_EP93XX=y
++# CONFIG_KEYBOARD_EP93XX_SPI is not set
++# CONFIG_KEYBOARD_EP93XX_8X8 is not set
++CONFIG_INPUT_MOUSE=y
++# CONFIG_MOUSE_PS2 is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++CONFIG_TOUCHSCREEN_EP93XX=y
++# CONFIG_INPUT_MISC 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 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++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 is not set
++# CONFIG_RTC is not set
++# CONFIG_EP93XX_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_DRM is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_SCx200_ACB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Hardware Sensors Chip support
++#
++# CONFIG_I2C_SENSOR is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_IT87 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_LM90 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++
++#
++# Other I2C Chip support
++#
++CONFIG_SENSORS_DS1337=y
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++CONFIG_I2C_DEBUG_CORE=y
++CONFIG_I2C_DEBUG_ALGO=y
++CONFIG_I2C_DEBUG_BUS=y
++CONFIG_I2C_DEBUG_CHIP=y
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_JBD is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_QUOTA is not set
++CONFIG_AUTOFS_FS=y
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++# CONFIG_DEVFS_FS is not set
++CONFIG_DEVPTS_FS_XATTR=y
++# CONFIG_DEVPTS_FS_SECURITY is not set
++CONFIG_TMPFS=y
++# CONFIG_HUGETLBFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# 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=2
++# CONFIG_JFFS2_FS_NAND is not set
++# 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_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_EXPORTFS is not set
++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
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++CONFIG_LDM_PARTITION=y
++# CONFIG_LDM_DEBUG is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++CONFIG_NLS_CODEPAGE_850=y
++# 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=y
++# 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=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Graphics support
++#
++CONFIG_FB=y
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_CX25871_I2C is not set
++CONFIG_FB_EP93XX=y
++# CONFIG_FB_CRT_EP93XX is not set
++CONFIG_FB_LCD_EP93XX=y
++# CONFIG_FB_LCD_EP93XX_SHARP is not set
++# CONFIG_FB_CX25871 is not set
++# CONFIG_FB_EP93XX_8BPP is not set
++CONFIG_FB_EP93XX_16BPP_565=y
++# CONFIG_FB_EP93XX_24BPP is not set
++# CONFIG_FB_EP93XX_32BPP is not set
++# CONFIG_FB_VIRTUAL is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++# CONFIG_FONT_MINI_4x6 is not set
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++
++#
++# Logo configuration
++#
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_LOGO_LINUX_CLUT224=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# Misc devices
++#
++
++#
++# USB support
++#
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++# 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 is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811HS 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
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_RW_DETECT is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_HP8200e is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# USB Human Interface Devices (HID)
++#
++CONFIG_USB_HID=y
++CONFIG_USB_HIDINPUT=y
++# CONFIG_HID_FF is not set
++CONFIG_USB_HIDDEV=y
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_HPUSBSCSI is not set
++
++#
++# USB Multimedia devices
++#
++# CONFIG_USB_DABUSB is not set
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network adaptors
++#
++# 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
++
++#
++# 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_TIGL 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_PHIDGETSERVO is not set
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# Kernel hacking
++#
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_LL_PRINTK_HACK is not set
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/ttml_defconfig b/arch/arm/configs/ttml_defconfig
+new file mode 100644
+index 0000000..e0b96ae
+--- /dev/null
++++ b/arch/arm/configs/ttml_defconfig
+@@ -0,0 +1,1052 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.13
++# Thu Sep  8 16:54:14 2005
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_CALIBRATE_DELAY=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_SWAP is not set
++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_EMBEDDED=y
++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_CC_OPTIMIZE_FOR_SIZE=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 is not set
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_AAEC2000 is not set
++
++#
++# EP93xx
++#
++CONFIG_ARCH_EP9301=y
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++# CONFIG_ARCH_EP9315 is not set
++# CONFIG_MACH_EDB9301 is not set
++CONFIG_MACH_TTML=y
++# CONFIG_ARCH_EP93XX_GPIO_IRQ is not set
++CONFIG_EP93XX_DMA=y
++CONFIG_EP93XX_SSP=y
++# CONFIG_EP93XX_SSP_CIRRUS is not set
++CONFIG_EP93XX_SSP_LINUX=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++CONFIG_ISA_DMA_API=y
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_PREEMPT is not set
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
++CONFIG_SELECT_MEMORY_MODEL=y
++# CONFIG_FLATMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM_MANUAL=y
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_NEED_MULTIPLE_NODES=y
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="ip=off root=1f02 rootfstype=jffs2"
++# CONFIG_XIP_KERNEL is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++
++#
++# 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 is not set
++# 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_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_IP_TCPDIAG=y
++# CONFIG_IP_TCPDIAG_IPV6 is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_BIC=y
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER 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
++
++#
++# 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
++
++#
++# 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=y
++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_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 is not set
++# 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=y
++# CONFIG_MTD_CFI_I2 is not set
++# 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
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x60000000
++CONFIG_MTD_PHYSMAP_LEN=0x01000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# 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_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CDROM_PKTCDVD is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI=y
++# CONFIG_SCSI_PROC_FS is not set
++
++#
++# 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 is not set
++# CONFIG_CHR_DEV_SG is not set
++# 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 is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA 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
++
++#
++# IEEE 1394 (FireWire) support
++#
++
++#
++# I2O device support
++#
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP 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
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++CONFIG_INPUT_EVDEV=y
++CONFIG_INPUT_EVBUG=y
++
++#
++# 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=y
++CONFIG_INPUT_UINPUT=y
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_TTML_DEVICES=y
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# 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_EP93XX_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++CONFIG_EP93XX_RTC=y
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++
++#
++# CAN bus devices
++#
++# CONFIG_CAN_BUS is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_EP93XX is not set
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_PCA_ISA is not set
++# CONFIG_I2C_SENSOR is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_SENSORS_DS1307 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# 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_MAX6875 is not set
++CONFIG_I2C_DEBUG_CORE=y
++CONFIG_I2C_DEBUG_ALGO=y
++CONFIG_I2C_DEBUG_BUS=y
++CONFIG_I2C_DEBUG_CHIP=y
++
++#
++# Hardware Monitoring support
++#
++CONFIG_HWMON=y
++# 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 is not set
++# 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_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_W83781D 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 devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# Graphics support
++#
++# CONFIG_FB is not set
++# CONFIG_FB_CX25871_I2C is not set
++
++#
++# 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_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_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 is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE 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_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++# CONFIG_USB_KEYSPAN_REMOTE 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=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++CONFIG_USB_SERIAL=y
++# CONFIG_USB_SERIAL_CONSOLE is not set
++# CONFIG_USB_SERIAL_GENERIC is not set
++# CONFIG_USB_SERIAL_AIRPRIME is not set
++# CONFIG_USB_SERIAL_BELKIN is not set
++# CONFIG_USB_SERIAL_WHITEHEAT is not set
++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
++# CONFIG_USB_SERIAL_CP2101 is not set
++# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
++# CONFIG_USB_SERIAL_EMPEG is not set
++# CONFIG_USB_SERIAL_FTDI_SIO is not set
++# CONFIG_USB_SERIAL_VISOR is not set
++# CONFIG_USB_SERIAL_IPAQ is not set
++# CONFIG_USB_SERIAL_IR is not set
++# CONFIG_USB_SERIAL_EDGEPORT is not set
++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
++# CONFIG_USB_SERIAL_GARMIN is not set
++# CONFIG_USB_SERIAL_IPW is not set
++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
++# CONFIG_USB_SERIAL_KEYSPAN is not set
++# CONFIG_USB_SERIAL_KLSI is not set
++# CONFIG_USB_SERIAL_KOBIL_SCT is not set
++# CONFIG_USB_SERIAL_MCT_U232 is not set
++CONFIG_USB_SERIAL_PL2303=y
++# CONFIG_USB_SERIAL_HP4X is not set
++# CONFIG_USB_SERIAL_SAFE is not set
++# CONFIG_USB_SERIAL_TI is not set
++# CONFIG_USB_SERIAL_CYBERJACK is not set
++# CONFIG_USB_SERIAL_XIRCOM is not set
++# CONFIG_USB_SERIAL_OMNINET 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_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
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_JBD is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++
++#
++# XFS support
++#
++# 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
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++# CONFIG_MSDOS_FS is not set
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++CONFIG_DEVPTS_FS_XATTR=y
++CONFIG_DEVPTS_FS_SECURITY=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_XATTR is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# 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=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE 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
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# 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=y
++# 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
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_LOG_BUF_SHIFT=14
++# 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_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_FS is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_DEBUG_USER is not set
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Hardware crypto devices
++#
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/zefeerdzb_defconfig b/arch/arm/configs/zefeerdzb_defconfig
+new file mode 100644
+index 0000000..39aefdd
+--- /dev/null
++++ b/arch/arm/configs/zefeerdzb_defconfig
+@@ -0,0 +1,961 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.9-rc2-ep93xx
++# Fri Jan  7 11:19:19 2005
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_IOMAP=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_CLEAN_COMPILE=y
++CONFIG_BROKEN_ON_SMP=y
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++# CONFIG_SWAP is not set
++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_LOG_BUF_SHIFT=14
++CONFIG_HOTPLUG=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_EMBEDDED=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++CONFIG_IOSCHED_DEADLINE=y
++# CONFIG_IOSCHED_CFQ is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++# CONFIG_TINY_SHMEM is not set
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE_PB is not set
++# CONFIG_ARCH_IMX is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++CONFIG_ARCH_EP9302=y
++# CONFIG_ARCH_EP9312 is not set
++# CONFIG_ARCH_EP9315 is not set
++# CONFIG_MACH_EDB9302 is not set
++CONFIG_MACH_ZEFEERDZB=y
++CONFIG_ARCH_EP93XX_GPIO_IRQ=y
++CONFIG_EP93XX_DMA=y
++# CONFIG_EP93XX_SSP is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# General setup
++#
++CONFIG_DISCONTIGMEM=y
++CONFIG_ARM_AMBA=y
++# CONFIG_ZBOOT_ROM is not set
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++
++#
++# PCMCIA/CardBus support
++#
++# CONFIG_PCMCIA is not set
++
++#
++# At least one math emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_PM is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_ARTHUR is not set
++CONFIG_CMDLINE="root=/dev/nfs ip=dhcp"
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_REDBOOT_PARTS=y
++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_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 is not set
++# 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=y
++# CONFIG_MTD_CFI_I2 is not set
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 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_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++CONFIG_MTD_ZEFEERDZB=y
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLKMTD 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=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++CONFIG_MTD_NAND_IDS=y
++CONFIG_MTD_NAND_ZEFEEREVB=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD 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_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_SIZE=6144
++CONFIG_BLK_DEV_INITRD=y
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Networking support
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++# CONFIG_NETLINK_DEV is not set
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++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_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER 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_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI=y
++# CONFIG_SCSI_PROC_FS is not set
++
++#
++# 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 is not set
++# CONFIG_CHR_DEV_SG 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 is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Fusion MPT device support
++#
++
++#
++# IEEE 1394 (FireWire) support
++#
++
++#
++# I2O device support
++#
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++CONFIG_INPUT_EVDEV=y
++CONFIG_INPUT_EVBUG=y
++
++#
++# Input I/O drivers
++#
++# CONFIG_GAMEPORT is not set
++CONFIG_SOUND_GAMEPORT=y
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_CT82C710 is not set
++# CONFIG_SERIO_AMBAKMI is not set
++# CONFIG_SERIO_RAW is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++CONFIG_KEYBOARD_EP93XX=y
++# CONFIG_KEYBOARD_EP93XX_SPI is not set
++# CONFIG_KEYBOARD_EP93XX_8X8 is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_UINPUT=y
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# 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_EP93XX_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++CONFIG_EP93XX_RTC=y
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_DRM is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_SCx200_ACB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Hardware Sensors Chip support
++#
++# CONFIG_I2C_SENSOR is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_IT87 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_LM90 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++
++#
++# Other I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++# CONFIG_SENSORS_M41T00 is not set
++CONFIG_I2C_DEBUG_CORE=y
++CONFIG_I2C_DEBUG_ALGO=y
++CONFIG_I2C_DEBUG_BUS=y
++CONFIG_I2C_DEBUG_CHIP=y
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT3_FS is not set
++# CONFIG_JBD 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_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++# CONFIG_MSDOS_FS is not set
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++# CONFIG_DEVFS_FS is not set
++CONFIG_DEVPTS_FS_XATTR=y
++CONFIG_DEVPTS_FS_SECURITY=y
++CONFIG_TMPFS=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# 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_NAND=y
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE 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_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_EXPORTFS is not set
++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
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# 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=y
++# 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
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Graphics support
++#
++# CONFIG_FB is not set
++# CONFIG_FB_CX25871_I2C is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++# CONFIG_SND_SEQUENCER is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=y
++CONFIG_SND_PCM_OSS=y
++CONFIG_SND_VERBOSE_PRINTK=y
++CONFIG_SND_DEBUG=y
++CONFIG_SND_DEBUG_MEMORY=y
++CONFIG_SND_DEBUG_DETECT=y
++
++#
++# Generic devices
++#
++CONFIG_SND_DUMMY=y
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA ARM devices
++#
++
++#
++# ALSA USB devices
++#
++# CONFIG_SND_USB_AUDIO is not set
++# CONFIG_SND_USB_USX2Y is not set
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++
++#
++# Misc devices
++#
++
++#
++# USB support
++#
++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 is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811HS is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_AUDIO is not set
++# CONFIG_USB_BLUETOOTH_TTY is not set
++# CONFIG_USB_MIDI is not set
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++CONFIG_USB_STORAGE_RW_DETECT=y
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_HP8200e is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# USB Human Interface Devices (HID)
++#
++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_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_HPUSBSCSI is not set
++
++#
++# USB Multimedia devices
++#
++# CONFIG_USB_DABUSB is not set
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network adaptors
++#
++# 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
++
++#
++# 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_TIGL 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_PHIDGETSERVO is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# Kernel hacking
++#
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_DEBUG_SLAB=y
++CONFIG_DEBUG_SPINLOCK=y
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_WAITQ=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_DONT_REORDER_CODE is not set
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_LL_PRINTK_HACK is not set
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/zefeerdzq_defconfig b/arch/arm/configs/zefeerdzq_defconfig
+new file mode 100644
+index 0000000..8314eee
+--- /dev/null
++++ b/arch/arm/configs/zefeerdzq_defconfig
+@@ -0,0 +1,1174 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.13
++# Tue Oct  4 10:04:06 2005
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++# CONFIG_CLEAN_COMPILE is not set
++CONFIG_BROKEN=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++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 is not set
++CONFIG_KOBJECT_UEVENT=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++# 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_CC_OPTIMIZE_FOR_SIZE=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=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_AAEC2000 is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++CONFIG_ARCH_EP9315=y
++# CONFIG_MACH_EDB9315 is not set
++# CONFIG_MACH_ADSSPHERE is not set
++CONFIG_MACH_ZEFEERDZQ=y
++# CONFIG_MACH_DMA03 is not set
++# CONFIG_ARCH_EP93XX_GPIO_IRQ is not set
++CONFIG_EP93XX_DMA=y
++# CONFIG_ARCH_EP93XX_IDE is not set
++# CONFIG_EP93XX_SSP is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_THUMB is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++CONFIG_ISA_DMA_API=y
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_SMP is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
++CONFIG_SELECT_MEMORY_MODEL=y
++# CONFIG_FLATMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM_MANUAL=y
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_NEED_MULTIPLE_NODES=y
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="root=/dev/ram"
++# CONFIG_XIP_KERNEL is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_AOUT=y
++CONFIG_BINFMT_MISC=y
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++
++#
++# 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 is not set
++# 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 is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_IP_TCPDIAG=y
++# CONFIG_IP_TCPDIAG_IPV6 is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_BIC=y
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER 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
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++# CONFIG_STANDALONE is not set
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER 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
++# CONFIG_MTD_AFS_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 is not set
++# 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=y
++# CONFIG_MTD_CFI_I2 is not set
++# 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 is not set
++# CONFIG_MTD_ABSENT is not set
++# CONFIG_MTD_OBSOLETE_CHIPS is not set
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++# CONFIG_MTD_PLATRAM is not set
++CONFIG_MTD_ZEFEERDZQ=y
++
++#
++# Self-contained MTD device drivers
++#
++# 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=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++CONFIG_MTD_NAND_IDS=y
++CONFIG_MTD_NAND_ZEFEEREVB=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# 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_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=12288
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# 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_EP93XX=y
++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
++CONFIG_IDE_ARM=y
++# CONFIG_BLK_DEV_IDEDMA is not set
++# CONFIG_IDEDMA_AUTO is not set
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++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 is not set
++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 is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA 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
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++CONFIG_NET_RADIO=y
++
++#
++# Obsolete Wireless cards support (pre-802.11)
++#
++# CONFIG_STRIP is not set
++# CONFIG_ATMEL is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++CONFIG_NETCONSOLE=y
++CONFIG_NETPOLL=y
++# CONFIG_NETPOLL_RX is not set
++# CONFIG_NETPOLL_TRAP is not set
++CONFIG_NET_POLL_CONTROLLER=y
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN 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=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++CONFIG_INPUT_EVDEV=y
++CONFIG_INPUT_EVBUG=y
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++CONFIG_KEYBOARD_EP93XX=y
++# CONFIG_KEYBOARD_EP93XX_SPI is not set
++# CONFIG_KEYBOARD_EP93XX_8X8 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_SERPORT=y
++# CONFIG_SERIO_AMBAKMI 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 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++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 is not set
++# CONFIG_RTC is not set
++# CONFIG_EP93XX_RTC is not set
++# CONFIG_DS1337_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++
++#
++# CAN bus devices
++#
++# CONFIG_CAN_BUS is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_PCA_ISA is not set
++# CONFIG_I2C_SENSOR is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_SENSORS_DS1307 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# 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_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
++
++#
++# Hardware Monitoring support
++#
++CONFIG_HWMON=y
++# 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 is not set
++# 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_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_W83781D 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 devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# Graphics support
++#
++CONFIG_FB=y
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++CONFIG_FB_SOFT_CURSOR=y
++# CONFIG_FB_MACMODES is not set
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_TILEBLITTING is not set
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_CX25871_I2C is not set
++CONFIG_FB_EP93XX=y
++# CONFIG_FB_CRT_EP93XX is not set
++# CONFIG_FB_LCD_EP93XX is not set
++# CONFIG_FB_LCD_EP93XX_SHARP is not set
++# CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343 is not set
++# CONFIG_FB_CX25871 is not set
++CONFIG_FB_LCD_TX09D50VM1CCA=y
++# CONFIG_FB_EP93XX_8BPP is not set
++# CONFIG_FB_EP93XX_16BPP_565 is not set
++CONFIG_FB_EP93XX_24BPP=y
++# CONFIG_FB_EP93XX_32BPP is not set
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FONTS=y
++# CONFIG_FONT_8x8 is not set
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_7x14 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++# CONFIG_FONT_MINI_4x6 is not set
++CONFIG_FONT_SUN8x16=y
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_10x18 is not set
++
++#
++# Logo configuration
++#
++CONFIG_LOGO=y
++CONFIG_LOGO_LINUX_MONO=y
++CONFIG_LOGO_LINUX_VGA16=y
++CONFIG_LOGO_LINUX_CLUT224=y
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++# CONFIG_SND is not set
++
++#
++# Open Sound System
++#
++CONFIG_SOUND_PRIME=y
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++# CONFIG_SOUND_OSS is not set
++# CONFIG_SOUND_TVMIXER is not set
++# CONFIG_SOUND_AD1980 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_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_SL811_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_AUDIO is not set
++# CONFIG_USB_BLUETOOTH_TTY is not set
++# CONFIG_USB_MIDI 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 is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# 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_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++# CONFIG_USB_KEYSPAN_REMOTE 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_ZD1201 is not set
++CONFIG_USB_MON=y
++
++#
++# 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_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
++
++#
++# 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=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++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 is not set
++
++#
++# XFS support
++#
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++CONFIG_ROMFS_FS=y
++CONFIG_INOTIFY=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++CONFIG_AUTOFS_FS=y
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_ZISOFS_FS=y
++CONFIG_UDF_FS=y
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++# CONFIG_DEVPTS_FS_XATTR is not set
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_XATTR is not set
++# CONFIG_HUGETLBFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# 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=y
++# 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_SUNRPC_GSS=y
++CONFIG_RPCSEC_GSS_KRB5=y
++# 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
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# 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=y
++# 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=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=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_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_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_FS is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_DONT_REORDER_CODE=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# 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 is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Hardware crypto devices
++#
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
+new file mode 100644
+index 0000000..2b5c2d6
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/Kconfig
+@@ -0,0 +1,193 @@
++
++menu "EP93xx"
++      depends on ARCH_EP93XX
++
++choice
++      prompt "EP93xx CPU Type"
++      default EP9312
++      help
++        There are several types of EP93xx CPUs available.
++        Choosing the right one here enables you to select
++        model specific drivers later.
++
++config ARCH_EP9301
++      bool "EP9301"
++      help
++        Say Y here if you have intend to run this kernel on a EP9301 CPU.
++
++config ARCH_EP9302
++      bool "EP9302"
++      help
++        Say Y here if you have intend to run this kernel on a EP9302 CPU.
++
++config ARCH_EP9312
++      bool "EP9312"
++      help
++        Say Y here if you intend to run this kernel on a EP9312 CPU.
++
++
++config ARCH_EP9315
++      bool "EP9315"
++      help
++        Say Y here if you intend to run this kernel on a EP9315 CPU.
++endchoice
++
++choice
++      prompt "EP9301 Boards"
++      depends on ARCH_EP9301
++      default EDB9301
++      help
++        There are several EP9301-based boards available.
++        Choosing the right one here enables various board-
++        specific options.
++
++config MACH_EDB9301
++      bool "Cirrus Logic EDB9301"
++      select MTD
++      select MTD_PHYSMAP
++      help
++        Say Y here if you intend to run this kernel on an EDB9301.
++
++config MACH_TTML
++      bool "TTML TripDawg"
++      help
++        Say Y here if you intend to run this kernel on an TTML TripDawg.
++
++endchoice
++
++choice
++      prompt "EP9302 Boards"
++      depends on ARCH_EP9302
++      default EDB9302
++      help
++        There are several EP9302-based boards available.
++        Choosing the right one here enables various board-
++        specific options.
++
++config MACH_EDB9302
++      bool "Cirrus Logic EDB9302"
++      select MTD
++      select MTD_PHYSMAP
++      help
++        Say Y here if you intend to run this kernel on an EDB9302.
++
++config MACH_ZEFEERDZB
++      bool "Dave Zefeer DZB on ZefeerEVB-L"
++      select MTD
++      help
++        Say Y here if you intend to run this kernel on an Zefeer DZB.
++        pluggend onto ZefeerEVB-L board.
++
++config MACH_ZEFEER_EVBL_107
++      bool " Dave ZefeerEVB-L - version 1.0.7 (PCB CS044404)"
++      depends on MACH_ZEFEERDZB
++      default n
++      help
++        Say Y here if you intend to run this kernel on an ZefeerEVB-L
++        version 1.0.7.
++
++endchoice
++
++choice
++      prompt "EP9312 Boards"
++      depends on ARCH_EP9312
++      default EDB9312
++      help
++        There are several EP9312-based boards available.
++        Choosing the right one here enables various board-
++        specific options.
++
++config MACH_EDB9312
++      bool "Cirrus Logic EDB9312"
++      select MTD
++      select MTD_PHYSMAP
++      help
++        Say Y here if you intend to run this kernel on an EDB9312.
++
++
++config MACH_ACC
++      bool "HiFish ACC"
++      help
++        Say Y here if you are using the HiFish Audio Control Center"
++
++endchoice
++
++choice
++      prompt "EP9315 Boards"
++      depends on ARCH_EP9315
++      default EDB9315
++      help
++        There are several EP9315-based boards available.
++        Choosing the right one here enables various board-
++        specific options.
++
++config MACH_EDB9315
++      bool "Cirrus Logic EDB9315"
++      select MTD
++      select MTD_PHYSMAP
++      help
++        Say Y here if you intend to run this kernel on an EDB9315.
++
++config MACH_ADSSPHERE
++      bool "Applied Data Systems Sphere"
++      select MTD
++      help
++        Say Y here if you intend to run this kernel on an ADSSPHERE.
++
++config MACH_ZEFEERDZQ
++      bool "Dave Zefeer DZQ on ZefeerEVB (L or H)"
++      select MTD
++      help
++        Say Y here if you intend to run this kernel on an Zefeer DZQ.
++        Both evaluation board are supported (ZefeerEVB-L/ZefeerEVB-H).
++
++config MACH_DMA03
++      bool "Gassner DMA03"
++      select MTD
++      select MTD_PHYSMAP
++      help
++        Say Y here if you intend to run this kernel on an DMA03.
++
++endchoice
++
++config ARCH_EP93XX_GPIO_IRQ
++      bool " EP93xx GPIO IRQ demux"
++      depends on ARCH_EP93XX
++      help
++        Say Y here if you want to expand the IRQ number to GPIO IRQ.
++
++config EP93XX_DMA
++      bool " EP93xx Internal DMA Support"
++      default y
++      help
++        Say Y here if you want to enable DMA Support for EP93XX family
++        CPUs.
++
++config EP93XX_SSP
++      bool "SSP support"
++      help
++        If you require SSP support, there are two SSP drivers
++        available to choose from.
++
++choice
++      prompt "SSP driver"
++      depends on EP93XX_SSP
++      default EP93XX_SSP_LINUX
++
++config EP93XX_SSP_CIRRUS
++      tristate "Cirrus Logic SSP driver"
++      depends on EP93XX_SSP
++      help
++        Say Y here for the Cirrus-supplied SSP driver. It is
++        quite specific to the EDB93xx evaluation boards.
++
++config EP93XX_SSP_LINUX
++      tristate "Linux SSP driver"
++      depends on EP93XX_SSP
++      help
++        Say Y here for an SSP driver which is heavily based on the
++        SA-1100 and PXA2xx SSP drivers.
++
++endchoice
++
++endmenu
+diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
+new file mode 100644
+index 0000000..19c56b3
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/Makefile
+@@ -0,0 +1,17 @@
++obj-y                         += ep93xx.o irq.o time.o
++
++obj-$(CONFIG_MACH_ACC)                += mach-acc.o
++obj-$(CONFIG_MACH_EDB9301)    += mach-edb9301.o
++obj-$(CONFIG_MACH_EDB9302)    += mach-edb9302.o
++obj-$(CONFIG_MACH_EDB9312)    += mach-edb9312.o
++obj-$(CONFIG_MACH_EDB9315)    += mach-edb9315.o
++obj-$(CONFIG_MACH_ADSSPHERE)  += mach-adssphere.o
++obj-$(CONFIG_MACH_TTML)               += mach-ttml.o
++obj-$(CONFIG_MACH_ZEFEERDZB)  += mach-zefeerdzb.o
++obj-$(CONFIG_MACH_ZEFEERDZQ)  += mach-zefeerdzq.o
++obj-$(CONFIG_MACH_DMA03)      += mach-dma03.o
++
++obj-$(CONFIG_EP93XX_DMA)      += dma_ep93xx.o
++
++obj-$(CONFIG_EP93XX_SSP_LINUX)        += ssp.o ssp2.o
++obj-$(CONFIG_EP93XX_SSP_CIRRUS)       += ssp-cirrus.o
+diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot
+new file mode 100644
+index 0000000..c87653e
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/Makefile.boot
+@@ -0,0 +1,6 @@
++   zreladdr-y   := 0x00008000
++params_phys-y   := 0x00000100
++   zreladdr-$(CONFIG_MACH_ZEFEERDZB)    := 0xD0008000
++params_phys-$(CONFIG_MACH_ZEFEERDZB)    := 0xD0000100
++   zreladdr-$(CONFIG_MACH_ZEFEERDZQ)    := 0xD0008000
++params_phys-$(CONFIG_MACH_ZEFEERDZQ)    := 0xD0000100
+diff --git a/arch/arm/mach-ep93xx/dma_ep93xx.c b/arch/arm/mach-ep93xx/dma_ep93xx.c
+new file mode 100644
+index 0000000..817de48
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/dma_ep93xx.c
+@@ -0,0 +1,3346 @@
++/******************************************************************************
++ * arch/arm/mach-ep9312/dma_ep93xx.c
++ *
++ * Support functions for the ep93xx internal DMA channels.
++ * (see also Documentation/arm/ep93xx/dma.txt)
++ *
++ * Copyright (C) 2003  Cirrus Logic
++ *
++ * A large portion of this file is based on the dma api implemented by
++ * Nicolas Pitre, dma-sa1100.c, copyrighted 2000.
++ *
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ ****************************************************************************/
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++
++#include <asm/system.h>
++#include <asm/irq.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++#include <asm/mach/dma.h>
++#include "dma_ep93xx.h"
++
++/*****************************************************************************
++ *
++ * Debugging macros
++ *
++ ****************************************************************************/
++#undef DEBUG
++/*#define DEBUG   1 */
++#ifdef DEBUG
++#define DPRINTK( x... )  printk( ##x )
++#else
++#define DPRINTK( x... )
++#endif
++
++/*****************************************************************************
++ *
++ * static global variables
++ *
++ ****************************************************************************/
++ep93xx_dma_t dma_chan[MAX_EP93XX_DMA_CHANNELS];
++
++/*
++ *  Maximum physical DMA buffer size
++ */
++#define MAX_DMA_SIZE        0xffff
++#define MAX_DMA_ORDER       12
++
++/*
++ *  lock used to protect the list of dma channels while searching for a free
++ *  channel during dma_request.
++ */
++static spinlock_t dma_list_lock = SPIN_LOCK_UNLOCKED;
++
++/*****************************************************************************
++ *
++ *  Internal DMA processing functions.
++ *
++ ****************************************************************************/
++/*****************************************************************************
++ *
++ *  get_dma_channel_from_handle()
++ *
++ *  If Handle is valid, returns the DMA channel # (0 to 9 for channels 1-10)
++ *  If Handle is not valid, returns -1.
++ *
++ ****************************************************************************/
++static int dma_get_channel_from_handle(int handle)
++{
++      int channel;
++
++      /*
++       *  Get the DMA channel # from the handle.
++       */
++      channel = ((int)handle & DMA_HANDLE_SPECIFIER_MASK) >> 28;
++
++      /*
++       *  See if this is a valid handle.
++       */
++      if (dma_chan[channel].last_valid_handle != (int)handle) {
++              DPRINTK("DMA ERROR - invalid handle 0x%x \n", handle);
++              /*
++               *  Fail, invalid handle
++               */
++              return (-1);
++      }
++
++      /*
++       *  See if this instance is still open
++       */
++      if (!dma_chan[channel].ref_count) {
++              /*
++               *  Fail, instance closed
++               */
++              return (-1);
++      }
++
++      return (channel);
++}
++
++/*****************************************************************************
++ *
++ * dma_m2m_irq_handler
++ *
++ * TODO: need to add support for M2M interrupt handling!!!
++ *
++ ****************************************************************************/
++static irqreturn_t
++dma_m2m_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++{
++      ep93xx_dma_t *dma = (ep93xx_dma_t *) dev_id;
++      unsigned int M2M_reg_base = dma->reg_base;
++      ep93xx_dma_dev_t dma_int = UNDEF_INT;
++      unsigned int read_back, loop, uiCONTROL, uiINTERRUPT;
++
++      loop = readl(M2M_reg_base + M2M_OFFSET_INTERRUPT);
++
++      /*
++       *  Determine what kind of dma interrupt this is.
++       */
++      if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) &
++          INTERRUPT_M2M_STALLINT)
++              dma_int = STALL;
++      else if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) &
++               INTERRUPT_M2M_NFBINT)
++              dma_int = NFB;
++      else if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) &
++               INTERRUPT_M2M_DONEINT)
++              dma_int = DONE;
++
++      DPRINTK("IRQ: b=%#x st=%#x\n", (int)dma->current_buffer->source,
++              dma_int);
++
++      /*
++       * Stall Interrupt: The Channel is stalled, meaning nothing is
++       * programmed to transfer right now.  So, we're back to the
++       * beginnning.  If there's a buffer to transfer, program it into
++       * max and base 0 registers.
++       */
++      if (dma_int == STALL) {
++              DPRINTK("1  ");
++
++              if (dma->total_buffers) {
++
++                      if (readl(M2M_reg_base + M2M_OFFSET_BCR0) !=
++                          0) {
++                              writel(0x0, M2M_reg_base + M2M_OFFSET_INTERRUPT);
++                              return IRQ_HANDLED;
++
++                      }
++
++                      /*
++                       *  The current_buffer has already been tranfered, so add the
++                       *  byte count to the total_bytes field.
++                       */
++                      dma->total_bytes = dma->total_bytes +
++                          dma->buffer_queue[dma->current_buffer].size;
++
++                      /*
++                       *  Mark the current_buffer as used.
++                       */
++                      dma->buffer_queue[dma->current_buffer].used = TRUE;
++
++                      /*
++                       *  Increment the used buffer counter
++                       */
++                      dma->used_buffers++;
++
++                      DPRINTK("#%d", dma->current_buffer);
++
++                      /*
++                       *  Increment the current_buffer
++                       */
++                      dma->current_buffer = (dma->current_buffer + 1) %
++                          MAX_EP93XX_DMA_BUFFERS;
++
++                      /*
++                       *  check if there's a new buffer to transfer.
++                       */
++                      if (dma->new_buffers && dma->xfer_enable) {
++                              /*
++                               *  We have a new buffer to transfer so program in the buffer
++                               *  values.  Since a STALL interrupt was triggered, we
++                               *  program the buffer descriptor 0
++                               *
++                               *  Set the SAR_BASE/DAR_BASE/BCR registers with values from the
++                               *  next buffer in the queue.
++                               */
++                              writel(dma->buffer_queue[dma->current_buffer].
++                                     source,
++                                     M2M_reg_base + M2M_OFFSET_SAR_BASE0);
++                              writel(dma->buffer_queue[dma->current_buffer].
++                                     dest,
++                                     M2M_reg_base + M2M_OFFSET_DAR_BASE0);
++                              writel(dma->buffer_queue[dma->current_buffer].
++                                     size,
++                                     M2M_reg_base + M2M_OFFSET_BCR0);
++
++                              /*
++                               *  Decrement the new buffer counter
++                               */
++                              dma->new_buffers--;
++
++                              /*
++                               *  If there's a second new buffer, we program the second
++                               *  buffer descriptor.
++                               */
++#if 0
++                              if (dma->new_buffers) {
++                                      DPRINTK("A  ");
++
++                                      /*
++                                       *  Set the SAR_BASE/DAR_BASE/BCR registers with values from the
++                                       *  next buffer in the queue.
++                                       */
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             source,
++                                             M2M_reg_base + M2M_OFFSET_SAR_BASE1);
++
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             dest,
++                                             M2M_reg_base + M2M_OFFSET_DAR_BASE0);
++
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             size,
++                                             M2M_reg_base + M2M_OFFSET_BCR0);
++
++                                      /*
++                                       *  Decrement the new buffer counter
++                                       */
++                                      dma->new_buffers--;
++
++                                      /*
++                                       *  Enable the NFB Interrupt.
++                                       */
++                                      uiCONTROL =
++                                          readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++                                      uiCONTROL |= CONTROL_M2M_NFBINTEN;
++                                      writel(uiCONTROL,
++                                             M2M_reg_base + M2M_OFFSET_CONTROL);
++                              }
++#endif
++                      }
++                      /*
++                       *  Read my lips.  No new buffers.
++                       */
++                      else {
++                              DPRINTK("2 \n");
++                              /*
++                               *  There's a chance we setup both buffer descriptors, but
++                               *  didn't service the NFB quickly enough, causing the channel
++                               *  to transfer both buffers, then enter the stall state.
++                               *  So, we need to be able to process the second buffer.
++                               */
++                              if ((dma->used_buffers + dma->new_buffers) <
++                                  dma->total_buffers) {
++                                      DPRINTK("3 ");
++
++                                      /*
++                                       *  The current_buffer has already been tranfered, so add the
++                                       *  byte count to the total_bytes field.
++                                       */
++                                      dma->total_bytes = dma->total_bytes +
++                                          dma->buffer_queue[dma->
++                                                            current_buffer].
++                                          size;
++
++                                      /*
++                                       *  Mark the current_buffer as used.
++                                       */
++                                      dma->buffer_queue[dma->current_buffer].
++                                          used = TRUE;
++
++                                      /*
++                                       *  Increment the used buffer counter
++                                       */
++                                      dma->used_buffers++;
++
++                                      DPRINTK("#%d", dma->current_buffer);
++
++                                      /*
++                                       *  Increment the current buffer pointer.
++                                       */
++                                      dma->current_buffer =
++                                          (dma->current_buffer +
++                                           1) % MAX_EP93XX_DMA_BUFFERS;
++
++                              }
++
++                              /*
++                               *  No new buffers to transfer, so disable the channel.
++                               */
++                              uiCONTROL =
++                                  readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++                              uiCONTROL &= ~CONTROL_M2M_ENABLE;
++                              writel(uiCONTROL,
++                                     M2M_reg_base + M2M_OFFSET_CONTROL);
++
++                              /*
++                               *  Indicate that this channel is in the pause by starvation
++                               *  state by setting the pause bit to true.
++                               */
++                              dma->pause = TRUE;
++
++                              DPRINTK("End of stall handling. \n");
++                              DPRINTK("STATUS - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_OFFSET_STATUS));
++                              DPRINTK("CONTROL - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_CONTROL.Value));
++                              DPRINTK("REMAIN - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_REMAIN.Value));
++                              DPRINTK("PPALLOC - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_PPALLOC.Value));
++                              DPRINTK("BASE0 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_BASE0.Value));
++                              DPRINTK("MAXCNT0 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_MAXCNT0.Value));
++                              DPRINTK("CURRENT0 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_CURRENT0.Value));
++                              DPRINTK("BASE1 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_BASE1.Value));
++                              DPRINTK("MAXCNT1 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_MAXCNT1.Value));
++                              DPRINTK("CURRENT1 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_CURRENT1.Value));
++
++                              DPRINTK
++                                  ("Buffer    buf_id     source       size       last       used \n");
++                              for (loop = 0; loop < 32; loop++) {
++                                      DPRINTK
++                                          ("%d        0x%x        0x%x         0x%x        %d         %d \n",
++                                           loop,
++                                           dma->buffer_queue[loop].buf_id,
++                                           dma->buffer_queue[loop].source,
++                                           dma->buffer_queue[loop].size,
++                                           dma->buffer_queue[loop].last,
++                                           dma->buffer_queue[loop].used);
++                              }
++                              DPRINTK("Pause - %d \n", dma->pause);
++                              DPRINTK("xfer_enable - %d \n",
++                                      dma->xfer_enable);
++                              DPRINTK("total bytes - 0x%x \n",
++                                      dma->total_bytes);
++                              DPRINTK("total buffer - %d \n",
++                                      dma->total_buffers);
++                              DPRINTK("new buffers - %d \n",
++                                      dma->new_buffers);
++                              DPRINTK("current buffer - %d \n",
++                                      dma->current_buffer);
++                              DPRINTK("last buffer - %d \n",
++                                      dma->last_buffer);
++                              DPRINTK("used buffers - %d \n",
++                                      dma->used_buffers);
++                              DPRINTK("callback addr - 0x%x \n",
++                                      dma->callback);
++                      }
++              }
++              /*
++               *  Total number of buffers in the queue is 0.
++               */
++              else {
++                      /*
++                       *  No buffers to transfer, or old buffers to mark as used,
++                       *  so Disable the channel
++                       */
++                      uiCONTROL =
++                          readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++                      uiCONTROL &= ~CONTROL_M2M_ENABLE;
++                      writel(uiCONTROL,
++                             M2M_reg_base + M2M_OFFSET_CONTROL);
++
++                      /*
++                       *  Must read the control register back after a write.
++                       */
++                      read_back =
++                          readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++
++                      /*
++                       *  Indicate that this channel is in the pause by
++                       *  starvation state by setting the pause bit to true.
++                       */
++                      dma->pause = TRUE;
++              }
++      }
++      /*
++       *  Next Frame Buffer Interrupt.  If there's a new buffer program it
++       *  Check if this is the last buffer in the transfer,
++       *  and if it is, disable the NFB int to prevent being
++       *  interrupted for another buffer when we know there won't be
++       *  another.
++       */
++      if (dma_int == NFB) {
++              DPRINTK("5  ");
++
++              if (dma->total_buffers) {
++                      DPRINTK("6  ");
++                      /*
++                       *  The iCurrentBuffer has already been transfered.  so add the
++                       *  byte count from the current buffer to the total byte count.
++                       */
++                      dma->total_bytes = dma->total_bytes +
++                          dma->buffer_queue[dma->current_buffer].size;
++
++                      /*
++                       *  Mark the Current Buffer as used.
++                       */
++                      dma->buffer_queue[dma->current_buffer].used = TRUE;
++
++                      /*
++                       *  Increment the used buffer counter
++                       */
++                      dma->used_buffers++;
++
++                      DPRINTK("#%d", dma->current_buffer);
++
++                      if ((dma->buffer_queue[(dma->current_buffer +
++                                              1) %
++                                             MAX_EP93XX_DMA_BUFFERS].last)
++                          || (dma->new_buffers == 0)
++                          || (dma->xfer_enable == FALSE)) {
++                              DPRINTK("7  ");
++
++                              /*
++                               *  This is the last Buffer in this transaction, so disable
++                               *  the NFB interrupt.  We shouldn't get an NFB int when the
++                               *  FSM moves to the ON state where it would typically get the
++                               *  NFB int indicating a new buffer can be programmed.
++                               *  Instead, once in the ON state, the DMA will just proceed
++                               *  to complet the transfer of the current buffer, move the
++                               *  FSB directly to the STALL state where a STALL interrupt
++                               *  will be generated.
++                               */
++                              uiCONTROL =
++                                  readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++                              uiCONTROL &= ~CONTROL_M2M_NFBINTEN;
++                              writel(uiCONTROL,
++                                     M2M_reg_base + M2M_OFFSET_CONTROL);
++
++                              /*
++                               *  The current buffer has been transferred, so increment
++                               *  the current buffer counter to reflect this.
++                               */
++                              dma->current_buffer =
++                                  (dma->current_buffer +
++                                   1) % MAX_EP93XX_DMA_BUFFERS;
++
++                              DPRINTK("End of NFB handling. \n");
++                              DPRINTK("STATUS - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_OFFSET_STATUS));
++                              DPRINTK("CONTROL - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_OFFSET_CONTROL));
++                              DPRINTK("REMAIN - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_OFFSET_REMAIN));
++                              DPRINTK("PPALLOC - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_OFFSET_PPALLOC));
++                              DPRINTK("BASE0 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_OFFSET_BASE0));
++                              DPRINTK("MAXCNT0 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_OFFSET_MAXCNT0));
++                              DPRINTK("CURRENT0 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_OFFSET_CURRENT0));
++                              DPRINTK("BASE1 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_OFFSET_BASE1));
++                              DPRINTK("MAXCNT1 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_OFFSET_MAXCNT1));
++                              DPRINTK("CURRENT1 - 0x%x \n",
++                                      readl(M2M_reg_base + M2M_OFFSET_CURRENT1));
++
++                              DPRINTK
++                                  ("Buffer    buf_id     source       size       last       used \n");
++                              for (loop = 0; loop < 32; loop++) {
++                                      DPRINTK
++                                          ("%d        0x%x        0x%x         0x%x        %d         %d \n",
++                                           loop,
++                                           dma->buffer_queue[loop].buf_id,
++                                           dma->buffer_queue[loop].source,
++                                           dma->buffer_queue[loop].size,
++                                           dma->buffer_queue[loop].last,
++                                           dma->buffer_queue[loop].used);
++                              }
++                              DPRINTK
++                                  ("pause     0x%x        0x%x         0x%x        %d         %d \n",
++                                   dma->pause_buf.buf_id,
++                                   dma->pause_buf.source, dma->pause_buf.size,
++                                   dma->pause_buf.last, dma->pause_buf.used);
++
++                              DPRINTK("Pause - %d \n", dma->pause);
++                              DPRINTK("xfer_enable - %d \n",
++                                      dma->xfer_enable);
++                              DPRINTK("total bytes - 0x%x \n",
++                                      dma->total_bytes);
++                              DPRINTK("total buffer - %d \n",
++                                      dma->total_buffers);
++                              DPRINTK("new buffers - %d \n",
++                                      dma->new_buffers);
++                              DPRINTK("current buffer - %d \n",
++                                      dma->current_buffer);
++                              DPRINTK("last buffer - %d \n",
++                                      dma->last_buffer);
++                              DPRINTK("used buffers - %d \n",
++                                      dma->used_buffers);
++                              DPRINTK("callback addr - 0x%x \n",
++                                      dma->callback);
++
++                      } else if (dma->new_buffers) {
++                              DPRINTK("8  ");
++                              /*
++                               *  we have a new buffer, so increment the current buffer to
++                               *  point to the next buffer, which is already programmed into
++                               *  the DMA. Next time around, it'll be pointing to the
++                               *  current buffer.
++                               */
++                              dma->current_buffer =
++                                  (dma->current_buffer +
++                                   1) % MAX_EP93XX_DMA_BUFFERS;
++
++                              /*
++                               *  we know we have a new buffer to program as the next
++                               *  buffer, so check which set of SAR_BASE/DAR_BASE/BCR registers
++                               *  to program.
++                               */
++                              if (readl(M2M_reg_base + M2M_OFFSET_STATUS) & STATUS_M2M_NB) {
++                                      /*
++                                       *  Set the SAR_BASE1/DAR_BASE1/BCR1 registers with values from the
++                                       *  next buffer in the queue.
++                                       */
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             source,
++                                             M2M_reg_base + M2M_OFFSET_SAR_BASE1);
++
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             dest,
++                                             M2M_reg_base + M2M_OFFSET_DAR_BASE1);
++
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             size,
++                                             M2M_reg_base + M2M_OFFSET_BCR1);
++                              } else {
++                                      /*
++                                       *  Set the SAR_BASE0/DAR_BASE0/BCR0 registers with values from the
++                                       *  next buffer in the queue.
++                                       */
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             source,
++                                             M2M_reg_base + M2M_OFFSET_SAR_BASE0);
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             dest,
++                                             M2M_reg_base + M2M_OFFSET_DAR_BASE0);
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             size,
++                                             M2M_reg_base + M2M_OFFSET_BCR0);
++                              }
++
++                              /*
++                               *  Decrement the new buffers counter
++                               */
++                              dma->new_buffers--;
++                      }
++              }
++              /*
++               *  Total number of buffers is 0 - really we should never get here,
++               *  but just in case.
++               */
++              else {
++                      DPRINTK("9 \n");
++
++                      /*
++                       *  No new buffers to transfer, so Disable the channel
++                       */
++                      uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++                      uiCONTROL &= ~CONTROL_M2M_ENABLE;
++                      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++                      /*
++                       *  Indicate that the channel is paused by starvation.
++                       */
++                      dma->pause = 1;
++              }
++      }
++
++      /*
++       *  Done interrupt generated, indicating that the transfer is complete.
++       */
++      if (dma_int == DONE) {
++#if 0
++              /*  The current_buffer has already been tranfered, so add the
++               *  byte count to the total_bytes field.
++               */
++              dma->total_bytes = dma->total_bytes +
++                  dma->buffer_queue[dma->current_buffer].size;
++
++              /*
++               *  Mark the current_buffer as used.
++               */
++              dma->buffer_queue[dma->current_buffer].used = TRUE;
++
++              /*
++               *  Increment the used buffer counter
++               */
++              dma->used_buffers++;
++
++              /*
++               *  Increment the current_buffer
++               */
++              dma->current_buffer = (dma->current_buffer + 1) %
++                  MAX_EP93XX_DMA_BUFFERS;
++#endif
++              /*
++               *  Clear the interrupt.
++               */
++              uiINTERRUPT =
++                  readl(M2M_reg_base + M2M_OFFSET_INTERRUPT);
++              uiINTERRUPT &= ~INTERRUPT_M2M_DONEINT;
++              writel(uiINTERRUPT,
++                     M2M_reg_base + M2M_OFFSET_INTERRUPT);
++
++              DPRINTK("STATUS - 0x%x \n",
++                      readl(M2M_reg_base + M2M_OFFSET_STATUS));
++              DPRINTK("CONTROL - 0x%x \n",
++                      readl(M2M_reg_base + M2M_OFFSET_CONTROL));
++              DPRINTK("SAR_BASE0 - 0x%x \n",
++                      readl(M2M_reg_base + M2M_OFFSET_SAR_BASE0));
++              DPRINTK("DAR_BASE0 - 0x%x \n",
++                      readl(M2M_reg_base + M2M_OFFSET_DAR_BASE0));
++              DPRINTK("SAR_CURRENT0 - 0x%x \n",
++                      readl(M2M_reg_base + M2M_OFFSET_SAR_CURRENT0));
++              DPRINTK("DAR_CURRENT0 - 0x%x \n",
++                      readl(M2M_reg_base + M2M_OFFSET_DAR_CURRENT0));
++              DPRINTK("BCR0 - 0x%x \n",
++                      readl(M2M_reg_base + M2M_OFFSET_BCR0));
++              DPRINTK("SAR_BASE1 - 0x%x \n",
++                      readl(M2M_reg_base + M2M_OFFSET_SAR_BASE1));
++              DPRINTK("DAR_BASE1 - 0x%x \n",
++                      readl(M2M_reg_base + M2M_OFFSET_DAR_BASE1));
++              DPRINTK("BCR1 - 0x%x \n",
++                      readl(M2M_reg_base + M2M_OFFSET_BCR1));
++
++              /*
++               *  Disable the channel.
++               */
++              uiCONTROL =
++                  readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++              uiCONTROL &= ~CONTROL_M2M_ENABLE;
++              writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++              /*
++               *  Indicate that we're in the stopped mode.
++               */
++              dma->pause = 1;
++              dma->xfer_enable = 0;
++      }
++
++      /*
++       *  Make sure the interrupt was valid, and if it was, then check
++       *  if a callback function was installed for this DMA channel.  If a
++       *  callback was installed call it.
++       */
++      if ((dma_int != UNDEF_INT) && dma->callback) {
++              dma->callback(dma_int, dma->device, dma->user_data);
++      }
++      return IRQ_HANDLED;
++}
++
++/*****************************************************************************
++ *
++ * dma_m2p_irq_handler
++ *
++ *
++ *
++ ****************************************************************************/
++static irqreturn_t
++dma_m2p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++{
++      ep93xx_dma_t *dma = (ep93xx_dma_t *) dev_id;
++      unsigned int M2P_reg_base = dma->reg_base;
++      unsigned int read_back;
++      ep93xx_dma_dev_t dma_int = UNDEF_INT;
++      unsigned int loop, uiCONTROL, uiINTERRUPT;
++
++      /*
++       *  Determine what kind of dma interrupt this is.
++       */
++      if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) &
++          INTERRUPT_M2P_STALLINT)
++              dma_int = STALL;
++      else if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) &
++               INTERRUPT_M2P_NFBINT)
++              dma_int = NFB;
++      else if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) &
++               INTERRUPT_M2P_CHERRORINT)
++              dma_int = CHERROR;
++
++      /*
++       *  Stall Interrupt: The Channel is stalled, meaning nothing is
++       *  programmed to transfer right now.  So, we're back to the
++       *  beginnning.  If there's a buffer to transfer, program it into
++       *  max and base 0 registers.
++       */
++      if (dma_int == STALL) {
++              DPRINTK("1  ");
++
++              if (dma->total_buffers) {
++                      /*
++                       *  The current_buffer has already been tranfered, so add the
++                       *  byte count to the total_bytes field.
++                       */
++                      dma->total_bytes = dma->total_bytes +
++                          dma->buffer_queue[dma->current_buffer].size;
++
++                      /*
++                       *  Mark the current_buffer as used.
++                       */
++                      dma->buffer_queue[dma->current_buffer].used = TRUE;
++
++                      /*
++                       *  Increment the used buffer counter
++                       */
++                      dma->used_buffers++;
++
++                      DPRINTK("#%d", dma->current_buffer);
++
++                      /*
++                       *  Increment the current_buffer
++                       */
++                      dma->current_buffer = (dma->current_buffer + 1) %
++                          MAX_EP93XX_DMA_BUFFERS;
++
++                      /*
++                       *  check if there's a new buffer to transfer.
++                       */
++                      if (dma->new_buffers && dma->xfer_enable) {
++                              /*
++                               *  We have a new buffer to transfer so program in the buffer
++                               *  values.  Since a STALL interrupt was triggered, we
++                               *  program the base0 and maxcnt0
++                               *
++                               *  Set the MAXCNT0 register with the buffer size
++                               */
++                              writel(dma->buffer_queue[dma->current_buffer].size,
++                                       M2P_reg_base + M2P_OFFSET_MAXCNT0);
++
++                              /*
++                               *  Set the BASE0 register with the buffer base address
++                               */
++                              writel(dma->buffer_queue[dma->current_buffer].source,
++                                      M2P_reg_base + M2P_OFFSET_BASE0);
++
++                              /*
++                               *  Decrement the new buffer counter
++                               */
++                              dma->new_buffers--;
++
++                              if (dma->new_buffers) {
++                                      DPRINTK("A  ");
++                                      /*
++                                       *  Set the MAXCNT1 register with the buffer size
++                                       */
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             size,
++                                             M2P_reg_base + M2P_OFFSET_MAXCNT1);
++
++                                      /*
++                                       *  Set the BASE1 register with the buffer base address
++                                       */
++                                      writel(dma->
++                                             buffer_queue[dma->
++                                                          current_buffer +
++                                                          1 %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             source,
++                                             M2P_reg_base + M2P_OFFSET_BASE1);
++
++                                      /*
++                                       *  Decrement the new buffer counter
++                                       */
++                                      dma->new_buffers--;
++
++                                      /*
++                                       *  Enable the NFB Interrupt.
++                                       */
++                                      uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++                                      uiCONTROL |= CONTROL_M2P_NFBINTEN;
++                                      writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++                              }
++                      }
++                      /*
++                       *  No new buffers.
++                       */
++                      else {
++                              DPRINTK("2 \n");
++                              /*
++                               *  There's a chance we setup both buffer descriptors, but
++                               *  didn't service the NFB quickly enough, causing the channel
++                               *  to transfer both buffers, then enter the stall state.
++                               *  So, we need to be able to process the second buffer.
++                               */
++                              if ((dma->used_buffers + dma->new_buffers) <
++                                  dma->total_buffers) {
++                                      DPRINTK("3 ");
++
++                                      /*
++                                       *  The current_buffer has already been tranfered, so add the
++                                       *  byte count to the total_bytes field.
++                                       */
++                                      dma->total_bytes = dma->total_bytes +
++                                          dma->buffer_queue[dma->
++                                                            current_buffer].
++                                          size;
++
++                                      /*
++                                       *  Mark the current_buffer as used.
++                                       */
++                                      dma->buffer_queue[dma->current_buffer].
++                                          used = TRUE;
++
++                                      /*
++                                       *  Increment the used buffer counter
++                                       */
++                                      dma->used_buffers++;
++
++                                      DPRINTK("#%d", dma->current_buffer);
++
++                                      /*
++                                       *  Increment the current buffer pointer.
++                                       */
++                                      dma->current_buffer =
++                                          (dma->current_buffer +
++                                           1) % MAX_EP93XX_DMA_BUFFERS;
++
++                              }
++
++                              /*
++                               *  No new buffers to transfer, so disable the channel.
++                               */
++                              /* go dma_regs->CONTROL.Field.ENABLE = 0; */
++                              uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++                              uiCONTROL &= ~CONTROL_M2P_ENABLE;
++                              writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++                              /*
++                               *  Indicate that this channel is in the pause by starvation
++                               *  state by setting the pause bit to true.
++                               */
++                              dma->pause = TRUE;
++
++                              DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS));
++                              DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL));
++                              DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN));
++                              DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC));
++                              DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0));
++                              DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0));
++                              DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0));
++                              DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1));
++                              DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1));
++                              DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
++
++                              DPRINTK
++                                  ("Buffer    buf_id     source       size       last       used \n");
++                              for (loop = 0; loop < 32; loop++) {
++                                      DPRINTK
++                                          ("%d        0x%x        0x%x         0x%x        %d         %d \n",
++                                           loop,
++                                           dma->buffer_queue[loop].buf_id,
++                                           dma->buffer_queue[loop].source,
++                                           dma->buffer_queue[loop].size,
++                                           dma->buffer_queue[loop].last,
++                                           dma->buffer_queue[loop].used);
++                              }
++                              DPRINTK
++                                  ("pause     0x%x        0x%x         0x%x        %d         %d \n",
++                                   dma->pause_buf.buf_id,
++                                   dma->pause_buf.source, dma->pause_buf.size,
++                                   dma->pause_buf.last, dma->pause_buf.used);
++
++                              DPRINTK("Pause - %d \n", dma->pause);
++                              DPRINTK("xfer_enable - %d \n",
++                                      dma->xfer_enable);
++                              DPRINTK("total bytes - 0x%x \n",
++                                      dma->total_bytes);
++                              DPRINTK("total buffer - %d \n",
++                                      dma->total_buffers);
++                              DPRINTK("new buffers - %d \n",
++                                      dma->new_buffers);
++                              DPRINTK("current buffer - %d \n",
++                                      dma->current_buffer);
++                              DPRINTK("last buffer - %d \n",
++                                      dma->last_buffer);
++                              DPRINTK("used buffers - %d \n",
++                                      dma->used_buffers);
++                              DPRINTK("callback addr - 0x%x \n",
++                                      dma->callback);
++                      }
++              }
++              /*
++               *  Total number of buffers in the queue is 0.
++               */
++              else {
++                      /*
++                       *  No buffers to transfer, or old buffers to mark as used,
++                       *  so Disable the channel
++                       */
++                      uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++                      uiCONTROL &= ~CONTROL_M2P_ENABLE;
++                      writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++                      /*
++                       *  Must read the control register back after a write.
++                       */
++                      read_back = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++
++                      /*
++                       *  Indicate that this channel is in the pause by
++                       *  starvation state by setting the pause bit to true.
++                       */
++                      dma->pause = TRUE;
++              }
++      }
++      /*
++       *  Next Frame Buffer Interrupt.  If there's a new buffer program it
++       *  Check if this is the last buffer in the transfer,
++       *  and if it is, disable the NFB int to prevent being
++       *  interrupted for another buffer when we know there won't be
++       *  another.
++       */
++      if (dma_int == NFB) {
++              DPRINTK("5  ");
++
++              if (dma->total_buffers) {
++                      DPRINTK("6  ");
++                      /*
++                       *  The iCurrentBuffer has already been transfered.  so add the
++                       *  byte count from the current buffer to the total byte count.
++                       */
++                      dma->total_bytes = dma->total_bytes +
++                          dma->buffer_queue[dma->current_buffer].size;
++
++                      /*
++                       *  Mark the Current Buffer as used.
++                       */
++                      dma->buffer_queue[dma->current_buffer].used = TRUE;
++
++                      /*
++                       *  Increment the used buffer counter
++                       */
++                      dma->used_buffers++;
++
++                      DPRINTK("#%d", dma->current_buffer);
++
++                      if ((dma->buffer_queue[(dma->current_buffer +
++                                              1) %
++                                             MAX_EP93XX_DMA_BUFFERS].last)
++                          || (dma->new_buffers == 0)
++                          || (dma->xfer_enable == FALSE)) {
++                              DPRINTK("7  ");
++
++                              /*
++                               *  This is the last Buffer in this transaction, so disable
++                               *  the NFB interrupt.  We shouldn't get an NFB int when the
++                               *  FSM moves to the ON state where it would typically get the
++                               *  NFB int indicating a new buffer can be programmed.
++                               *  Instead, once in the ON state, the DMA will just proceed
++                               *  to complet the transfer of the current buffer, move the
++                               *  FSB directly to the STALL state where a STALL interrupt
++                               *  will be generated.
++                               */
++                              uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++                              uiCONTROL &= ~CONTROL_M2P_NFBINTEN;
++                              writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++                              /*
++                               *  The current buffer has been transferred, so increment
++                               *  the current buffer counter to reflect this.
++                               */
++                              dma->current_buffer =
++                                  (dma->current_buffer +
++                                   1) % MAX_EP93XX_DMA_BUFFERS;
++
++                              DPRINTK("End of NFB handling. \n");
++                              DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS));
++                              DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL));
++                              DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN));
++                              DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC));
++                              DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0));
++                              DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0));
++                              DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0));
++                              DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1));
++                              DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1));
++                              DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
++
++                              DPRINTK
++                                  ("Buffer    buf_id     source       size       last       used \n");
++                              for (loop = 0; loop < 32; loop++) {
++                                      DPRINTK
++                                          ("%d        0x%x        0x%x         0x%x        %d         %d \n",
++                                           loop,
++                                           dma->buffer_queue[loop].buf_id,
++                                           dma->buffer_queue[loop].source,
++                                           dma->buffer_queue[loop].size,
++                                           dma->buffer_queue[loop].last,
++                                           dma->buffer_queue[loop].used);
++                              }
++                              DPRINTK
++                                  ("pause     0x%x        0x%x         0x%x        %d         %d \n",
++                                   dma->pause_buf.buf_id,
++                                   dma->pause_buf.source, dma->pause_buf.size,
++                                   dma->pause_buf.last, dma->pause_buf.used);
++
++                              DPRINTK("Pause - %d \n", dma->pause);
++                              DPRINTK("xfer_enable - %d \n",
++                                      dma->xfer_enable);
++                              DPRINTK("total bytes - 0x%x \n",
++                                      dma->total_bytes);
++                              DPRINTK("total buffer - %d \n",
++                                      dma->total_buffers);
++                              DPRINTK("new buffers - %d \n",
++                                      dma->new_buffers);
++                              DPRINTK("current buffer - %d \n",
++                                      dma->current_buffer);
++                              DPRINTK("last buffer - %d \n",
++                                      dma->last_buffer);
++                              DPRINTK("used buffers - %d \n",
++                                      dma->used_buffers);
++                              DPRINTK("callback addr - 0x%x \n",
++                                      dma->callback);
++
++                      } else if (dma->new_buffers) {
++                              DPRINTK("8  ");
++                              /*
++                               *  we have a new buffer, so increment the current buffer to
++                               *  point to the next buffer, which is already programmed into
++                               *  the DMA. Next time around, it'll be pointing to the
++                               *  current buffer.
++                               */
++                              dma->current_buffer =
++                                  (dma->current_buffer +
++                                   1) % MAX_EP93XX_DMA_BUFFERS;
++
++                              /*
++                               *  we know we have a new buffer to program as the next
++                               *  buffer, so check which set of MAXCNT and BASE registers
++                               *  to program.
++                               */
++                              if (readl(M2P_reg_base + M2P_OFFSET_STATUS) &
++                                  STATUS_M2P_NEXTBUFFER) {
++                                      /*
++                                       *  Set the MAXCNT1 register with the buffer size
++                                       */
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             size,
++                                             M2P_reg_base + M2P_OFFSET_MAXCNT1);
++
++                                      /*
++                                       *  Set the BASE1 register with the buffer base address
++                                       */
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             source,
++                                             M2P_reg_base + M2P_OFFSET_BASE1);
++                              } else {
++                                      /*
++                                       *  Set the MAXCNT0 register with the buffer size
++                                       */
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             size,
++                                             M2P_reg_base + M2P_OFFSET_MAXCNT0);
++
++                                      /*
++                                       *  Set the BASE0 register with the buffer base address
++                                       */
++                                      writel(dma->
++                                             buffer_queue[(dma->
++                                                           current_buffer +
++                                                           1) %
++                                                          MAX_EP93XX_DMA_BUFFERS].
++                                             source,
++                                             M2P_reg_base + M2P_OFFSET_BASE0);
++                              }
++
++                              /*
++                               *  Decrement the new buffers counter
++                               */
++                              dma->new_buffers--;
++                      }
++              }
++              /*
++               *  Total number of buffers is 0 - really we should never get here,
++               *  but just in case.
++               */
++              else {
++                      DPRINTK("9 \n");
++
++                      /*
++                       *  No new buffers to transfer, so Disable the channel
++                       */
++                      uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++                      uiCONTROL &= ~CONTROL_M2P_ENABLE;
++                      writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++              }
++      }
++      /*
++       *  Channel Error Interrupt, or perhipheral interrupt, specific to the
++       *  memory to/from peripheral channels.
++       */
++      if (dma_int == CHERROR) {
++              /*
++               *  just clear the interrupt, it's really up to the peripheral
++               *  driver to determine if any further action is necessary.
++               */
++              uiINTERRUPT =
++                  readl(M2P_reg_base + M2P_OFFSET_INTERRUPT);
++              uiINTERRUPT &= ~INTERRUPT_M2P_CHERRORINT;
++              writel(uiINTERRUPT, M2P_reg_base + M2P_OFFSET_INTERRUPT);
++      }
++
++      /*
++       *  Make sure the interrupt was valid, and if it was, then check
++       *  if a callback function was installed for this DMA channel.  If a
++       *  callback was installed call it.
++       */
++      if ((dma_int != UNDEF_INT) && dma->callback) {
++              dma->callback(dma_int, dma->device, dma->user_data);
++      }
++      return IRQ_HANDLED;
++}
++
++/*****************************************************************************
++ *
++ * ep9312_dma_open_m2p(int device)
++ *
++ * Description: This function will attempt to open a M2P/P2M DMA channel.
++ *              If the open is successful, the channel number is returned,
++ *              otherwise a negative number is returned.
++ *
++ * Parameters:
++ *  device:     device for which the dma channel is requested.
++ *
++ ****************************************************************************/
++static int dma_open_m2p(int device)
++{
++      int channel = -1;
++      unsigned int loop;
++      unsigned int M2P_reg_base;
++      unsigned int uiPWRCNT;
++
++      DPRINTK("DMA Open M2P with hw dev %d\n", device);
++
++      /*
++       *  Lock the dma channel list.
++       */
++      spin_lock(&dma_list_lock);
++      DPRINTK("1\n");
++      /*
++       * Verify that the device requesting DMA isn't already using a DMA channel
++       */
++      if (device >= 10) {
++              loop = 1;       /* Rx transfer requested */
++      } else {
++              loop = 0;       /* Tx transfer requested */
++      }
++
++      for (; loop < 10; loop = loop + 2) {
++              /*
++               *  Before checking for a matching device, check that the
++               *  channel is in use, otherwise the device field is
++               *  invalid.
++               */
++              if (dma_chan[loop].ref_count) {
++                      if (device == dma_chan[loop].device) {
++                              DPRINTK("DMA Open M2P - Error\n");
++                              /*
++                               *  Fail.
++                               */
++                              return (-1);
++                      }
++              }
++      }
++
++      /*
++       *  Get a DMA channel instance for the given hardware device.
++       *  If this is a TX look for even numbered channels, else look for
++       *  odd numbered channels
++       */
++      if (device >= 10) {
++              loop = 1;       /* Rx transfer requested */
++      } else {
++              loop = 0;       /* Tx transfer requested */
++      }
++
++      for (; loop < 10; loop = loop + 2) {
++              if (!dma_chan[loop].ref_count) {
++                      /*
++                       *  Capture the channel and increment the reference count.
++                       */
++                      channel = loop;
++                      dma_chan[channel].ref_count++;
++                      break;
++              }
++      }
++
++      /*
++       *  Unlock the dma channel list.
++       */
++      spin_unlock(&dma_list_lock);
++
++      /*
++       *  See if we got a valid channel.
++       */
++      if (channel < 0) {
++              /*
++               *  Fail.
++               */
++              return (-1);
++      }
++
++      /*
++       *  Point regs to the correct dma channel register base.
++       */
++      M2P_reg_base = dma_chan[channel].reg_base;
++
++      /*
++       *  Turn on the clock for the specified DMA channel
++       *  TODO: need to use the correct register name for the
++       *  power control register.
++       */
++      uiPWRCNT = readl(SYSCON_PWRCNT);
++      switch (channel) {
++      case 0:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH0;
++                      break;
++              }
++
++      case 1:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH1;
++                      break;
++              }
++
++      case 2:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH2;
++                      break;
++              }
++
++      case 3:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH3;
++                      break;
++              }
++
++      case 4:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH4;
++                      break;
++              }
++
++      case 5:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH5;
++                      break;
++              }
++
++      case 6:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH6;
++                      break;
++              }
++
++      case 7:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH7;
++                      break;
++              }
++      case 8:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH8;
++                      break;
++              }
++      case 9:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH9;
++                      break;
++              }
++
++      default:
++              {
++                      return (-1);
++              }
++      }
++      writel(uiPWRCNT, SYSCON_PWRCNT);
++
++      /*
++       *  Clear out the control register before any further setup.
++       */
++      writel(0, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++      /*
++       *  Setup the peripheral port value in the DMA channel registers.
++       */
++      if (device < 10) {
++              writel((unsigned int)device,
++                     M2P_reg_base + M2P_OFFSET_PPALLOC);
++      } else {
++              writel((unsigned int)(device - 10),
++                     M2P_reg_base + M2P_OFFSET_PPALLOC);
++      }
++
++      /*
++       *  Let's hold on to the value of the Hw device for comparison later.
++       */
++      dma_chan[channel].device = device;
++
++      /*
++       *  Success.
++       */
++      return (channel);
++}
++
++/*****************************************************************************
++ *
++ * dma_open_m2m(int device)
++ *
++ * Description: This function will attempt to open a M2M DMA channel.
++ *              If the open is successful, the channel number is returned,
++ *              otherwise a negative number is returned.
++ *
++ * Parameters:
++ *  device:     device for which the dma channel is requested.
++ *
++ ****************************************************************************/
++static int dma_open_m2m(int device)
++{
++      int channel = -1;
++      unsigned int loop;
++      unsigned int M2M_reg_base;
++      unsigned int uiPWRCNT, uiCONTROL;
++
++      DPRINTK("DMA Open M2M with hw dev %d\n", device);
++
++      /*
++       *  Lock the dma channel list.
++       */
++      spin_lock(&dma_list_lock);
++      DPRINTK("1\n");
++
++      /*
++       *  Check if this device is already allocated a channel.
++       *  TODO: can one M2M device be allocated multiple channels?
++       */
++      for (loop = DMA_MEMORY; loop < UNDEF; loop++) {
++              /*
++               *  Before checking for a matching device, check that the
++               *  channel is in use, otherwise the device field is
++               *  invalid.
++               */
++              if (dma_chan[loop].ref_count) {
++                      if (device == dma_chan[loop].device) {
++                              DPRINTK
++                                  ("Error - dma_open_m2m - already allocated channel\n");
++
++                              /*
++                               *  Unlock the dma channel list.
++                               */
++                              spin_unlock(&dma_list_lock);
++
++                              /*
++                               *  Fail.
++                               */
++                              return (-1);
++                      }
++              }
++      }
++
++      /*
++       *  Get a DMA channel instance for the given hardware device.
++       */
++      for (loop = 10; loop < 12; loop++) {
++              if (!dma_chan[loop].ref_count) {
++                      /*
++                       *  Capture the channel and increment the reference count.
++                       */
++                      channel = loop;
++                      dma_chan[channel].ref_count++;
++                      break;
++              }
++      }
++
++      /*
++       *  Unlock the dma channel list.
++       */
++      spin_unlock(&dma_list_lock);
++
++      /*
++       *  See if we got a valid channel.
++       */
++      if (channel < 0) {
++              /*
++               *  Fail.
++               */
++              return (-1);
++      }
++
++      /*
++       *  Point regs to the correct dma channel register base.
++       */
++      M2M_reg_base = dma_chan[channel].reg_base;
++
++      /*
++       *  Turn on the clock for the specified DMA channel
++       *  TODO: need to use the correct register name for the
++       *  power control register.
++       */
++      uiPWRCNT = readl(SYSCON_PWRCNT);
++      switch (channel) {
++      case 10:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH0;
++                      break;
++              }
++
++      case 11:
++              {
++                      uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH1;
++                      break;
++              }
++
++      default:
++              {
++                      return (-1);
++              }
++      }
++      writel(uiPWRCNT, SYSCON_PWRCNT);
++
++      DPRINTK("DMA Open - power control: 0x%x \n",
++              readl(SYSCON_PWRCNT));
++
++      /*
++       *  Clear out the control register before any further setup.
++       */
++      writel(0, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++      /*
++       *  Setup the transfer mode and the request source selection within
++       *  the DMA M2M channel registers.
++       */
++      switch (device) {
++      case DMA_MEMORY:
++              {
++                      /*
++                       * Clear TM field, set RSS field to 0
++                       */
++                      uiCONTROL =
++                          readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++                      uiCONTROL &=
++                          ~(CONTROL_M2M_TM_MASK | CONTROL_M2M_RSS_MASK);
++                      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++                      break;
++              }
++
++      case DMA_IDE:
++              {
++                      /*
++                       * Set RSS field to 3, Set NO_HDSK, Set PW field to 1
++                       */
++                      uiCONTROL =
++                          readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++                      uiCONTROL &=
++                          ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_PW_MASK);
++                      uiCONTROL |=
++                          (3 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK |
++                          (2 << CONTROL_M2M_PW_SHIFT);
++
++                      uiCONTROL &= ~(CONTROL_M2M_ETDP_MASK);
++                      uiCONTROL &= ~(CONTROL_M2M_DACKP);
++                      uiCONTROL &= ~(CONTROL_M2M_DREQP_MASK);
++
++                      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++                      break;
++              }
++
++      case DMARx_SSP:
++              {
++                      /*
++                       * Set RSS field to 1, Set NO_HDSK, Set TM field to 2
++                       */
++                      uiCONTROL =
++                          readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++                      uiCONTROL &=
++                          ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
++                      uiCONTROL |=
++                          (1 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK |
++                          (2 << CONTROL_M2M_TM_SHIFT);
++                      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++                      break;
++              }
++
++      case DMATx_SSP:
++              {
++                      /*
++                       * Set RSS field to 2, Set NO_HDSK, Set TM field to 1
++                       */
++                      uiCONTROL =
++                          readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++                      uiCONTROL &=
++                          ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
++                      uiCONTROL |=
++                          (2 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK |
++                          (1 << CONTROL_M2M_TM_SHIFT);
++                      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++                      break;
++              }
++
++      case DMATx_EXT_DREQ:
++              {
++                      /*
++                       * Set TM field to 2, set RSS field to 0
++                       */
++                      uiCONTROL =
++                          readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++                      uiCONTROL &=
++                          ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
++                      uiCONTROL |= 1 << CONTROL_M2M_TM_SHIFT;
++                      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++                      break;
++              }
++
++      case DMARx_EXT_DREQ:
++              {
++
++                      /*
++                       * Set TM field to 2, set RSS field to 0
++                       */
++                      uiCONTROL =
++                          readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++                      uiCONTROL &=
++                          ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
++                      uiCONTROL |= 2 << CONTROL_M2M_TM_SHIFT;
++                      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++                      break;
++              }
++
++      default:
++              {
++                      return -1;
++              }
++      }
++
++      /*
++       *  Let's hold on to the value of the Hw device for comparison later.
++       */
++      dma_chan[channel].device = device;
++
++      /*
++       *  Success.
++       */
++      return (channel);
++}
++
++/*****************************************************************************
++ *
++ *  int dma_config_m2m(ep93xx_dma_t * dma, unsigned int flags_m2m,
++ *               dma_callback callback, unsigned int user_data)
++ *
++ *  Description: Configure the DMA channel and install a callback function.
++ *               This function will have to be called for every transfer
++ *
++ *  dma:        Pointer to the dma instance data for the M2M channel to
++ *              configure.
++ *  flags_m2m   Flags used to configure an M2M dma channel and determine
++ *              if a callback function and user_data information are included
++ *              in this call.
++ *  callback    function pointer which is called near the end of the
++ *              dma channel's irq handler.
++ *  user_data   defined by the calling driver.
++ *
++ ****************************************************************************/
++static int
++dma_config_m2m(ep93xx_dma_t * dma, unsigned int flags_m2m,
++             dma_callback callback, unsigned int user_data)
++{
++      unsigned long flags;
++      unsigned int M2M_reg_base, uiCONTROL;
++
++      /*
++       *  Make sure the channel is disabled before configuring the channel.
++       *
++       *  TODO: Is this correct??   Making a big change here...
++       */
++      /* if(!dma->pause || (!dma->pause && dma->xfer_enable)) */
++      if (dma->xfer_enable) {
++              /*
++               *  DMA channel is not paused, so we can't configure it.
++               */
++              DPRINTK("DMA channel not paused, so can't configure! \n");
++              return (-1);
++      }
++
++      /*
++       *  Mask interrupts.
++       */
++      local_irq_save(flags);
++
++      /*
++       *  Setup a pointer into the dma channel's register set.
++       */
++      M2M_reg_base = dma->reg_base;
++
++      /*
++       *  By default we enable the stall interrupt.
++       */
++      uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++      uiCONTROL |= CONTROL_M2M_STALLINTEN;
++      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++      /*
++       *  By default we enable the done interrupt.
++       */
++      uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++      uiCONTROL &= ~CONTROL_M2M_DONEINTEN;
++      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++      /*
++       *  Set up the transfer control fields based on values passed in
++       *  the flags_m2m field.
++       */
++      uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++
++      if (flags_m2m & DESTINATION_HOLD) {
++              uiCONTROL |= CONTROL_M2M_DAH;
++      } else {
++              uiCONTROL &= ~CONTROL_M2M_DAH;
++      }
++
++      if (flags_m2m & SOURCE_HOLD) {
++              uiCONTROL |= CONTROL_M2M_SAH;
++      } else {
++              uiCONTROL &= ~CONTROL_M2M_SAH;
++      }
++
++      uiCONTROL &= ~CONTROL_M2M_TM_MASK;
++      uiCONTROL |=
++          (((flags_m2m & TRANSFER_MODE_MASK) >> TRANSFER_MODE_SHIFT) <<
++           CONTROL_M2M_TM_SHIFT) & CONTROL_M2M_TM_MASK;
++
++      uiCONTROL &= ~CONTROL_M2M_PWSC_MASK;
++      uiCONTROL |= (((flags_m2m & WAIT_STATES_MASK) >> WAIT_STATES_SHIFT) <<
++                    CONTROL_M2M_PWSC_SHIFT) & CONTROL_M2M_PWSC_MASK;
++
++      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++      /*
++       *  Save the callback function in the dma instance for this channel.
++       */
++      dma->callback = callback;
++
++      /*
++       *  Save the user data in the the dma instance for this channel.
++       */
++      dma->user_data = user_data;
++
++      /*
++       *  Put the dma instance into the pause state by setting the
++       *  pause bit to true.
++       */
++      dma->pause = TRUE;
++
++      local_irq_restore(flags);
++
++      /*
++       *  Success.
++       */
++      return (0);
++}
++
++/*****************************************************************************
++ *
++ *  int dma_start(int handle, unsigned int channels, unsigned int * handles)
++ *
++ *  Description: Initiate a transfer on up to 3 channels.
++ *
++ *  handle:     handle for the channel to initiate transfer on.
++ *  channels:   number of channels to initiate transfers on.
++ *  handles:    pointer to an array of handles, one for each channel which
++ *               is to be started.
++ *
++ ****************************************************************************/
++static int dma_start_m2m(int channel, ep93xx_dma_t * dma)
++{
++      unsigned long flags;
++      unsigned int M2M_reg_base = dma->reg_base;
++      unsigned int uiCONTROL;
++
++      /*
++       *  Mask interrupts while we get this started.
++       */
++      local_irq_save(flags);
++
++      /*
++       *  Make sure the channel has at least one buffer in the queue.
++       */
++      if (dma->new_buffers < 1) {
++              /*
++               *  Unmask irqs
++               */
++              local_irq_restore(flags);
++
++              DPRINTK("DMA Start: Channel starved.\n");
++
++              /*
++               *  This channel does not have enough buffers queued up,
++               *  so enter the pause by starvation state.
++               */
++              dma->xfer_enable = TRUE;
++              dma->pause = TRUE;
++
++              /*
++               *  Success.
++               */
++              return (0);
++      }
++
++      /*
++       *  Clear any pending interrupts.
++       */
++      writel(0x0, M2M_reg_base + M2M_OFFSET_INTERRUPT);
++
++      /*
++       *  Set up one or both buffer descriptors with values from the next one or
++       *  two buffers in the queue.  By default enable the next frame buffer
++       *  interrupt on the channel.
++       */
++      uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++      uiCONTROL &= ~CONTROL_M2M_NFBINTEN;
++      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++      /*
++       * enable the stall interrupt.
++       */
++      uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++      uiCONTROL |= CONTROL_M2M_STALLINTEN;
++      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++      /*
++       *  Update the dma channel instance transfer state.
++       */
++      dma->xfer_enable = TRUE;
++      dma->pause = FALSE;
++
++      /*
++       *  Decrement the new buffers counter.
++       */
++      dma->new_buffers--;
++
++      /*
++       *  Program up the first buffer descriptor with a source and destination
++       *  and a byte count.
++       */
++      writel(dma->buffer_queue[dma->current_buffer].source,
++             M2M_reg_base + M2M_OFFSET_SAR_BASE0);
++
++      writel(dma->buffer_queue[dma->current_buffer].dest,
++             M2M_reg_base + M2M_OFFSET_DAR_BASE0);
++
++      writel(dma->buffer_queue[dma->current_buffer].size,
++             M2M_reg_base + M2M_OFFSET_BCR0);
++
++      /*
++       *  Now we enable the channel.  This initiates the transfer.
++       */
++      uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++      uiCONTROL |= CONTROL_M2M_ENABLE;
++      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++      writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++      /*
++       *  Before restoring irqs set up the second buffer descriptor
++       *  with a second buffer if we have a second buffer.
++       */
++      /* if(dma->new_buffers)
++         {
++         outl( dma->buffer_queue[(dma->current_buffer + 1) %
++         MAX_EP93XX_DMA_BUFFERS].source,
++         M2M_reg_base+M2M_OFFSET_SAR_BASE1 );
++
++         outl( dma->buffer_queue[(dma->current_buffer + 1) %
++         MAX_EP93XX_DMA_BUFFERS].dest,
++         M2M_reg_base+M2M_OFFSET_DAR_BASE1 );
++
++         outl( dma->buffer_queue[(dma->current_buffer + 1) %
++         MAX_EP93XX_DMA_BUFFERS].size,
++         M2M_reg_base+M2M_OFFSET_BCR1 );
++         }  */
++
++      /*
++       *  If this is a memory to memory transfer, we need to s/w trigger the
++       *  transfer by setting the start bit within the control register.
++       */
++      if (dma->device == DMA_MEMORY) {
++              uiCONTROL =
++                  readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++              uiCONTROL |= CONTROL_M2M_START;
++              writel(uiCONTROL,
++                     M2M_reg_base + M2M_OFFSET_CONTROL);
++      }
++
++      DPRINTK("DMA - It's been started!!");
++      DPRINTK("STATUS - 0x%x \n",     readl(M2M_reg_base + M2M_OFFSET_STATUS));
++      DPRINTK("CONTROL - 0x%x \n", readl(M2M_reg_base + M2M_CONTROL.Value));
++      DPRINTK("REMAIN - 0x%x \n", readl(M2M_reg_base + M2M_REMAIN.Value));
++      DPRINTK("PPALLOC - 0x%x \n", readl(M2M_reg_base + M2M_PPALLOC.Value));
++      DPRINTK("BASE0 - 0x%x \n", readl(M2M_reg_base + M2M_BASE0.Value));
++      DPRINTK("MAXCNT0 - 0x%x \n", readl(M2M_reg_base + M2M_MAXCNT0.Value));
++      DPRINTK("CURRENT0 - 0x%x \n", readl(M2M_reg_base + M2M_CURRENT0.Value));
++      DPRINTK("BASE1 - 0x%x \n", readl(M2M_reg_base + M2M_BASE1.Value));
++      DPRINTK("MAXCNT1 - 0x%x \n", readl(M2M_reg_base + M2M_MAXCNT1.Value));
++      DPRINTK("CURRENT1 - 0x%x \n", readl(M2M_reg_base + M2M_CURRENT1.Value));
++
++      DPRINTK("Pause - %d \n", dma_pointers[0]->pause);
++      DPRINTK("xfer_enable - %d \n", dma_pointers[0]->xfer_enable);
++      DPRINTK("total bytes - 0x%x \n", dma_pointers[0]->total_bytes);
++      DPRINTK("total buffer - %d \n", dma_pointers[0]->total_buffers);
++      DPRINTK("new buffers - %d \n", dma_pointers[0]->new_buffers);
++      DPRINTK("current buffer - %d \n", dma_pointers[0]->current_buffer);
++      DPRINTK("last buffer - %d \n", dma_pointers[0]->last_buffer);
++      DPRINTK("used buffers - %d \n", dma_pointers[0]->used_buffers);
++
++      /*
++       *  Unmask irqs
++       */
++      local_irq_restore(flags);
++
++      /*
++       *  Success.
++       */
++      return (0);
++}
++
++/*****************************************************************************
++ *
++ *  DMA interface functions
++ *
++ ****************************************************************************/
++
++/*****************************************************************************
++ *
++ *  int dma_init(int handle, unsigned int flags_m2p, unsigned int flags_m2m,
++ *               dma_callback callback, unsigned int user_data)
++ *
++ *  Description: Configure the DMA channel and install a callback function.
++ *
++ *  handle:     Handle unique the each instance of the dma interface, used
++ *              to verify this call.
++ *  flags_m2p   Flags used to configure an M2P/P2M dma channel and determine
++ *              if a callback function and user_data information are included
++ *              in this call. This field should be NULL if handle represents
++ *              an M2M channel.
++ *  flags_m2m   Flags used to configure an M2M dma channel and determine
++ *              if a callback function and user_data information are included
++ *              in this call. This field should be NULL if handle represents
++ *              an M2P/P2M channel.
++ *  callback    function pointer which is called near the end of the
++ *              dma channel's irq handler.
++ *  user_data   defined by the calling driver.
++ *
++ ****************************************************************************/
++int
++ep93xx_dma_config(int handle, unsigned int flags_m2p, unsigned int flags_m2m,
++                dma_callback callback, unsigned int user_data)
++{
++      int channel;
++      ep93xx_dma_t *dma;
++      unsigned long flags;
++      unsigned int M2P_reg_base, uiCONTROL;
++
++      /*
++       *  Get the DMA hw channel # from the handle.
++       */
++      channel = dma_get_channel_from_handle(handle);
++
++      /*
++       *  See if this is a valid handle.
++       */
++      if (channel < 0) {
++              printk(KERN_ERR "DMA Config: Invalid dma handle.\n");
++
++              /*
++               *  Fail.
++               */
++              return (-EINVAL);
++      }
++
++      DPRINTK("DMA Config \n");
++
++      dma = &dma_chan[channel];
++
++      local_irq_save(flags);
++
++      /*
++       *  Check if the channel is currently transferring.
++       */
++      if (dma->xfer_enable) {
++              local_irq_restore(flags);
++
++              /*
++               *  Already transferring, invalid command.
++               */
++              return (-EINVAL);
++      }
++
++      /*
++       *  Check if this is an m2m function.
++       */
++      if (channel >= 10) {
++              local_irq_restore(flags);
++
++              /*
++               *  Call another function to handle m2m config.
++               */
++              return (dma_config_m2m(dma, flags_m2m, callback, user_data));
++      }
++
++      /*
++       *  Setup a pointer into the dma channel's register set.
++       */
++      M2P_reg_base = dma->reg_base;
++
++      /*
++       *  By default we enable the stall interrupt.
++       */
++      uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++      uiCONTROL |= CONTROL_M2P_STALLINTEN;
++      writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++      /*
++       *  Configure the channel for an error from the peripheral.
++       */
++      uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++      if (flags_m2p && CHANNEL_ERROR_INT_ENABLE)
++              uiCONTROL |= CONTROL_M2P_CHERRORINTEN;
++      else
++              uiCONTROL &= ~CONTROL_M2P_CHERRORINTEN;
++      writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++      uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++      if (flags_m2p && EP93XX_DMA_ABORT)
++              uiCONTROL |= CONTROL_M2P_ABRT;
++      else
++              uiCONTROL &= ~CONTROL_M2P_ABRT;
++      writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++      uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++      if (flags_m2p && IGNORE_CHANNEL_ERROR)
++              uiCONTROL |= CONTROL_M2P_ICE;
++      else
++              uiCONTROL &= ~CONTROL_M2P_ICE;
++      writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++      /*
++       *  Save the callback function in the dma instance for this channel.
++       */
++      dma->callback = callback;
++
++      /*
++       *  Save the user data in the the dma instance for this channel.
++       */
++      dma->user_data = user_data;
++
++      /*
++       *  Put the dma instance into the pause state by setting the
++       *  pause bit to true.
++       */
++      dma->pause = TRUE;
++
++      local_irq_restore(flags);
++
++      /*
++       *  Success.
++       */
++      return (0);
++}
++
++/*****************************************************************************
++ *
++ *  int dma_start(int handle, unsigned int channels, unsigned int * handles)
++ *
++ *  Description: Initiate a transfer on up to 3 channels.
++ *
++ *  handle:     handle for the channel to initiate transfer on.
++ *  channels:   number of channels to initiate transfers on.
++ *  handles:    pointer to an array of handles, one for each channel which
++ *               is to be started.
++ *
++ ****************************************************************************/
++int ep93xx_dma_start(int handle, unsigned int channels, unsigned int *handles)
++{
++      ep93xx_dma_t *dma_pointers[3];
++      unsigned int M2P_reg_bases[3];
++      unsigned int loop, uiCONTROL;
++      unsigned long flags;
++      int channel;
++
++      /*
++       *  Get the DMA hw channel # from the handle.
++       */
++      channel = dma_get_channel_from_handle(handle);
++
++      /*
++       *  See if this is a valid handle.
++       */
++      if (channel < 0) {
++              printk(KERN_ERR "DMA Start: Invalid dma handle.\n");
++
++              /*
++               *  Fail.
++               */
++              return (-EINVAL);
++      }
++
++      if (channels < 1) {
++              printk(KERN_ERR "DMA Start: Invalid parameter.\n");
++
++              return (-EINVAL);
++      }
++
++      DPRINTK("DMA Start \n");
++
++      /*
++       *  Mask off registers.
++       */
++      local_irq_save(flags);
++
++      /*
++       *  Check if this is a start multiple.
++       */
++      if (channels > 1) {
++              DPRINTK
++                  ("DMA ERROR: Start, multiple start not supported yet \n");
++              return (-1);
++      }
++      /*
++       *  Only one channel
++       */
++      else {
++              /*
++               *  Check if this channel is already transferring.
++               */
++              if (dma_chan[channel].xfer_enable && !dma_chan[channel].pause) {
++                      printk(KERN_ERR
++                             "DMA Start: Invalid command for channel %d.\n",
++                             channel);
++                      DPRINTK("DMA Start: Invalid command for channel %d.\n",
++                              channel);
++
++                      /*
++                       *  Unmask irqs
++                       */
++                      local_irq_restore(flags);
++
++                      /*
++                       *  This channel is already transferring, so return an error.
++                       */
++                      return (-EINVAL);
++              }
++
++              /*
++               *  If this is an M2M channel, call a different function.
++               */
++              if (channel >= 10) {
++                      /*
++                       *  Unmask irqs
++                       */
++                      local_irq_restore(flags);
++
++                      /*
++                       *  Call the m2m start function.  Only start one channel.
++                       */
++                      return (dma_start_m2m(channel, &dma_chan[channel]));
++              }
++
++              /*
++               *  Make sure the channel has at least one buffer in the queue.
++               */
++              if (dma_chan[channel].new_buffers < 1) {
++                      DPRINTK("DMA Start: Channel starved.\n");
++
++                      /*
++                       *  This channel does not have enough buffers queued up,
++                       *  so enter the pause by starvation state.
++                       */
++                      dma_chan[channel].xfer_enable = TRUE;
++                      dma_chan[channel].pause = TRUE;
++
++                      /*
++                       *  Unmask irqs
++                       */
++                      local_irq_restore(flags);
++
++                      /*
++                       *  Success.
++                       */
++                      return (0);
++              }
++
++              /*
++               *  Set up a dma instance pointer for this dma channel.
++               */
++              dma_pointers[0] = &dma_chan[channel];
++
++              /*
++               * Set up a pointer to the register set for this channel.
++               */
++              M2P_reg_bases[0] = dma_pointers[0]->reg_base;
++      }
++
++      /*
++       *  Setup both MAXCNT registers with values from the next two buffers
++       *  in the queue, and enable the next frame buffer interrupt on the channel.
++       */
++      for (loop = 0; loop < channels; loop++) {
++              /*
++               *  By default we enable the next frame buffer interrupt.
++               */
++              uiCONTROL = readl(M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
++              uiCONTROL |= CONTROL_M2P_NFBINTEN;
++              writel(uiCONTROL, M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
++
++              /*
++               *  Check if we need to restore a paused transfer.
++               */
++              if (dma_pointers[loop]->pause_buf.buf_id != -1) {
++                      writel(dma_pointers[loop]->pause_buf.size,
++                             M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT0);
++              } else {
++                      writel(dma_pointers[loop]->
++                             buffer_queue[dma_pointers[loop]->current_buffer].
++                             size,
++                             M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT0);
++              }
++      }
++
++      for (loop = 0; loop < channels; loop++) {
++              /*
++               *  Enable the specified dma channels.
++               */
++              uiCONTROL =
++                  readl(M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
++              uiCONTROL |= CONTROL_M2P_ENABLE;
++              writel(uiCONTROL,
++                     M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
++
++              /*
++               *  Update the dma channel instance transfer state.
++               */
++              dma_pointers[loop]->xfer_enable = TRUE;
++              dma_pointers[loop]->pause = FALSE;
++
++              if (dma_pointers[loop]->pause_buf.buf_id == -1) {
++                      dma_pointers[loop]->new_buffers--;
++              }
++      }
++
++      /*
++       *  Program up the BASE0 registers for all specified channels, this
++       *  will initiate transfers on all specified channels.
++       */
++      for (loop = 0; loop < channels; loop++) {
++              /*
++               *  Check if we need to restore a paused transfer.
++               */
++              if (dma_pointers[loop]->pause_buf.buf_id != -1) {
++                      writel(dma_pointers[loop]->pause_buf.source,
++                             M2P_reg_bases[loop] + M2P_OFFSET_BASE0);
++
++                      /*
++                       *  Set the pause buffer to NULL
++                       */
++                      dma_pointers[loop]->pause_buf.buf_id = -1;
++                      dma_pointers[loop]->pause_buf.size = 0;
++              } else {
++                      writel(dma_pointers[loop]->
++                             buffer_queue[dma_pointers[loop]->current_buffer].
++                             source,
++                             M2P_reg_bases[loop] + M2P_OFFSET_BASE0);
++              }
++      }
++
++      /*
++       *  Before restoring irqs setup the second MAXCNT/BASE
++       *  register with a second buffer.
++       */
++      for (loop = 0; loop < channels; loop++) {
++              if (dma_pointers[loop]->new_buffers) {
++                      writel(dma_pointers[loop]->
++                             buffer_queue[(dma_pointers[loop]->
++                                           current_buffer +
++                                           1) % MAX_EP93XX_DMA_BUFFERS].size,
++                             M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT1);
++                      writel(dma_pointers[loop]->
++                             buffer_queue[(dma_pointers[loop]->
++                                           current_buffer +
++                                           1) %
++                                          MAX_EP93XX_DMA_BUFFERS].source,
++                             M2P_reg_bases[loop] + M2P_OFFSET_BASE1);
++              }
++      }
++
++/*
++    DPRINTK("DMA - It's been started!!");
++    DPRINTK("STATUS - 0x%x \n",     readl(M2P_reg_base+M2P_OFFSET_STATUS)));
++    DPRINTK("CONTROL - 0x%x \n",    readl(M2P_reg_base+M2P_OFFSET_CONTROL)));
++    DPRINTK("REMAIN - 0x%x \n",     readl(M2P_reg_base+M2P_OFFSET_REMAIN)));
++    DPRINTK("PPALLOC - 0x%x \n",    readl(M2P_reg_base+M2P_OFFSET_PPALLOC)));
++    DPRINTK("BASE0 - 0x%x \n",      readl(M2P_reg_base+M2P_OFFSET_BASE0)));
++    DPRINTK("MAXCNT0 - 0x%x \n",    readl(M2P_reg_base+M2P_OFFSET_MAXCNT0)));
++    DPRINTK("CURRENT0 - 0x%x \n",   readl(M2P_reg_base+M2P_OFFSET_CURRENT0)));
++    DPRINTK("BASE1 - 0x%x \n",      readl(M2P_reg_base+M2P_OFFSET_BASE1)));
++    DPRINTK("MAXCNT1 - 0x%x \n",    readl(M2P_reg_base+M2P_OFFSET_MAXCNT1)));
++    DPRINTK("CURRENT1 - 0x%x \n",   readl(M2P_reg_base+M2P_OFFSET_CURRENT1)));
++
++    DPRINTK("Pause - %d \n", dma_pointers[0]->pause);
++    DPRINTK("xfer_enable - %d \n", dma_pointers[0]->xfer_enable);
++    DPRINTK("total bytes - 0x%x \n", dma_pointers[0]->total_bytes);
++    DPRINTK("total buffer - %d \n", dma_pointers[0]->total_buffers);
++    DPRINTK("new buffers - %d \n", dma_pointers[0]->new_buffers);
++    DPRINTK("current buffer - %d \n", dma_pointers[0]->current_buffer);
++    DPRINTK("last buffer - %d \n", dma_pointers[0]->last_buffer);
++    DPRINTK("used buffers - %d \n", dma_pointers[0]->used_buffers);
++*/
++      /*
++       *  Unmask irqs
++       */
++      local_irq_restore(flags);
++
++      /*
++       *  Success.
++       */
++      return (0);
++}
++
++/*****************************************************************************
++ *
++ *  int ep93xx_dma_add_buffer(int handle, unsigned int * address,
++ *                         unsigned int size, unsigned int last)
++ *
++ *  Description: Add a buffer entry to the DMA buffer queue.
++ *
++ *  handle:     handle for the channel to add this buffer to.
++ *  address:    Pointer to an integer which is the start address of the
++ *              buffer which is to be added to the queue.
++ *  size:       size of the buffer in bytes.
++ *  last:       1 if this is the last buffer in this stream, 0 otherwise.
++ *
++ ****************************************************************************/
++int
++ep93xx_dma_add_buffer(int handle, unsigned int source, unsigned int dest,
++                    unsigned int size, unsigned int last, unsigned int buf_id)
++{
++      unsigned long flags;
++      ep93xx_dma_t *dma;
++      int channel;
++
++      /*
++       *  Get the DMA hw channel # from the handle.
++       */
++      channel = dma_get_channel_from_handle(handle);
++
++      /*
++       *  See if this is a valid handle.
++       */
++      if (channel < 0) {
++              printk(KERN_ERR "DMA Add Buffer: Invalid dma handle.\n");
++
++              /*
++               *  Fail.
++               */
++              return (-EINVAL);
++      }
++
++      /*
++       *  Get a pointer to the dma instance.
++       */
++      dma = &dma_chan[channel];
++
++      /*
++       *  Mask interrupts and hold on to the original state.
++       */
++      local_irq_save(flags);
++
++      /*
++       *  If the buffer queue is full, last_buffer is the same as current_buffer and
++       *  we're not tranfering, or last_buffer is pointing to a used buffer, then exit.
++       *  TODO: do I need to do any more checks?
++       */
++      if (dma->total_buffers >= MAX_EP93XX_DMA_BUFFERS) {
++              /*
++               *  Restore the state of the irqs
++               */
++              local_irq_restore(flags);
++
++              /*
++               *  Fail.
++               */
++              return (-1);
++      }
++
++      /*
++       *  Add this buffer to the queue
++       */
++      dma->buffer_queue[dma->last_buffer].source = source;
++      dma->buffer_queue[dma->last_buffer].dest = dest;
++      dma->buffer_queue[dma->last_buffer].size = size;
++      dma->buffer_queue[dma->last_buffer].last = last;
++      dma->buffer_queue[dma->last_buffer].buf_id = buf_id;
++
++      /*
++       *  Reset the used field of the buffer structure.
++       */
++      dma->buffer_queue[dma->last_buffer].used = FALSE;
++
++      /*
++       *  Increment the End Item Pointer.
++       */
++      dma->last_buffer = (dma->last_buffer + 1) % MAX_EP93XX_DMA_BUFFERS;
++
++      /*
++       *  Increment the new buffers counter and the total buffers counter
++       */
++      dma->new_buffers++;
++      dma->total_buffers++;
++
++      /*
++       *  restore the interrupt state.
++       */
++      local_irq_restore(flags);
++
++      /*
++       *  Check if the channel was starved into a stopped state.
++       */
++      if (dma->pause && dma->xfer_enable) {
++              if (dma->new_buffers >= 1) {
++                      DPRINTK
++                          ("DMA - calling start from add after starve. \n");
++
++                      /*
++                       *  The channel was starved into a stopped state, and we've got
++                       *  2 new buffers, so start tranferring again.
++                       */
++                      ep93xx_dma_start(handle, 1, NULL);
++              }
++      }
++
++      /*
++       *  Success.
++       */
++      return (0);
++}
++
++/*****************************************************************************
++ *
++ *  int ep93xx_dma_remove_buffer(int handle, unsigned int * address,
++ *                                unsigned int * size)
++ *
++ *  Description: Remove a buffer entry from the DMA buffer queue. If
++ *               buffer was removed successfully, return 0, otherwise
++ *               return -1.
++ *
++ *  handle:     handle for the channel to remove a buffer from.
++ *  address:    Pointer to an integer which is filled in with the start
++ *              address of the removed buffer.
++ *  size:       Pointer to an integer which is filled in with the size in
++ *              bytes of the removed buffer.
++ *
++ ****************************************************************************/
++int ep93xx_dma_remove_buffer(int handle, unsigned int *buf_id)
++{
++      unsigned int test;
++      unsigned int loop;
++      int return_val = -1;
++      unsigned long flags;
++      ep93xx_dma_t *dma;
++      int channel;
++
++      /*
++       *  Get the DMA hw channel # from the handle.
++       */
++      channel = dma_get_channel_from_handle(handle);
++
++      /*
++       *  See if this is a valid handle.
++       */
++      if (channel < 0) {
++              printk(KERN_ERR "DMA Remove Buffer: Invalid dma handle.\n");
++
++              /*
++               *  Fail.
++               */
++              return (-EINVAL);
++      }
++
++      dma = &dma_chan[channel];
++
++      /*
++       *  Mask interrupts and hold on to the original state.
++       */
++      local_irq_save(flags);
++
++      /*
++       *  Make sure there are used buffers to be returned.
++       */
++      if (dma->used_buffers) {
++              test = dma->last_buffer;
++
++              for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) {
++                      if (dma->buffer_queue[test].used
++                          && (dma->buffer_queue[test].buf_id != -1)) {
++                              /*DPRINTK("buffer %d used \n", test); */
++
++                              /*
++                               *  This is a used buffer, fill in the buf_id pointer
++                               *  with the buf_id for this buffer.
++                               */
++                              *buf_id = dma->buffer_queue[test].buf_id;
++
++                              /*
++                               *  Reset this buffer structure
++                               */
++                              dma->buffer_queue[test].buf_id = -1;
++
++                              /*
++                               *  Decrement the used buffer counter, and the total buffer counter.
++                               */
++                              dma->used_buffers--;
++                              dma->total_buffers--;
++
++                              /*
++                               *  Successful removal of a buffer, so set the return
++                               *  value to 0, then exit this loop.
++                               */
++                              return_val = 0;
++                              break;
++                      }
++
++                      /*
++                       *  This buffer isn't used, let's see if the next one is.
++                       */
++                      test = (test + 1) % MAX_EP93XX_DMA_BUFFERS;
++              }
++      }
++
++      /*
++       *  Restore interrupts.
++       */
++      local_irq_restore(flags);
++
++      /*
++       *  Success.
++       */
++      return (return_val);
++}
++
++/*****************************************************************************
++ *
++ *  int ep93xx_dma_pause(int handle, unsigned int channels,
++ *                       unsigned int * handles)
++ *
++ *  Description: Disable any ongoing transfer for the given channel, retaining
++ *               the state of the current buffer transaction so that upon
++ *               resume, the dma will continue where it left off.
++ *
++ *  handle:     Handle for the channel to be paused.  If this is a pause for
++ *              for multiple channels, handle is a valid handle for one of
++ *              the channels to be paused.
++ *  channels:   number of channel to pause transfers on.
++ *  handles:    Pointer to an array of handles, one for each channel which
++ *              to be paused.  If this pause is intended only for one
++ *              channel, this field should be set to NULL.
++ *
++ ****************************************************************************/
++int ep93xx_dma_pause(int handle, unsigned int channels, unsigned int *handles)
++{
++      unsigned long flags;
++      ep93xx_dma_t *dma;
++      int channel;
++      unsigned int M2M_reg_base, M2P_reg_base;
++
++      DPRINTK("ep93xx_dma_pause \n");
++
++      /*
++       *  Mask interrupts and hold on to the original state.
++       */
++      local_irq_save(flags);
++
++      /*
++       *  Get the DMA hw channel # from the handle.
++       */
++      channel = dma_get_channel_from_handle(handle);
++
++      /*
++       *  See if this is a valid handle.
++       */
++      if (channel < 0) {
++              /*
++               *  restore interrupts.
++               */
++              local_irq_restore(flags);
++
++              printk(KERN_ERR "DMA Pause: Invalid dma handle.\n");
++
++              /*
++               *  Fail.
++               */
++              return (-EINVAL);
++      }
++
++      DPRINTK("DMA %d: pause \n", channel);
++
++      /*
++       *  Set up a pointer to the dma instance data.
++       */
++      dma = &dma_chan[channel];
++
++      /*
++       *  Set a pointer to the dma channel registers.
++       */
++      if (channel < 10) {
++              M2P_reg_base = dma->reg_base;
++      } else {
++              M2M_reg_base = dma->reg_base;
++      }
++
++      /*
++       *  Check if we're already paused.
++       */
++      if (dma->pause) {
++              /*
++               *  We're paused, but are we stopped?
++               */
++              if (dma->xfer_enable) {
++                      /*
++                       *  Put the channel in the stopped state.
++                       */
++                      dma->xfer_enable = FALSE;
++              }
++
++              DPRINTK("DMA Pause - already paused.");
++      } else {
++              /*
++               *  Put the channel into the stopped state.
++               */
++              dma->xfer_enable = FALSE;
++              dma->pause = TRUE;
++      }
++
++      /*
++       *  restore interrupts.
++       */
++      local_irq_restore(flags);
++
++      /*
++       *  Already paused, so exit.
++       */
++      return (0);
++}
++
++/*****************************************************************************
++ *
++ *  void ep93xx_dma_flush(int handle)
++ *
++ *  Description: Flushes all queued buffers and transfers in progress
++ *               for the given channel.  Return the buffer entries
++ *               to the calling function.
++ *
++ *  handle:     handle for the channel for which the flush is intended.
++ *
++ ****************************************************************************/
++int ep93xx_dma_flush(int handle)
++{
++      unsigned int loop;
++      unsigned long flags;
++      ep93xx_dma_t *dma;
++      int channel;
++      unsigned int M2P_reg_base;
++
++      /*
++       *  Get the DMA hw channel # from the handle.
++       */
++      channel = dma_get_channel_from_handle(handle);
++
++      /*
++       *  See if this is a valid handle.
++       */
++      if (channel < 0) {
++              printk(KERN_ERR "DMA Flush: Invalid dma handle.\n");
++
++              /*
++               *  Fail.
++               */
++              return (-EINVAL);
++      }
++
++      DPRINTK("DMA %d: flush \n", channel);
++
++      /*
++       *  Set up a pointer to the dma instance data for this channel
++       */
++      dma = &dma_chan[channel];
++
++      /*
++       *  Mask interrupts and hold on to the original state.
++       */
++      local_irq_save(flags);
++
++      for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) {
++              dma->buffer_queue[loop].buf_id = -1;
++      }
++
++      /*
++       *  Set the Current and Last item to zero.
++       */
++      dma->current_buffer = 0;
++      dma->last_buffer = 0;
++
++      /*
++       *  Reset the Buffer counters
++       */
++      dma->used_buffers = 0;
++      dma->new_buffers = 0;
++      dma->total_buffers = 0;
++
++      /*
++       *  reset the Total bytes counter.
++       */
++      dma->total_bytes = 0;
++
++      M2P_reg_base = dma_chan[channel].reg_base;
++
++      /*
++       *  restore interrupts.
++       */
++      local_irq_restore(flags);
++
++      /*
++       *  Success.
++       */
++      return (0);
++}
++
++/*****************************************************************************
++ *
++ *  int ep93xx_dma_queue_full(int handle)
++ *
++ *  Description: Query to determine if the DMA queue of buffers for
++ *              a given channel is full.
++ *              0 = queue is full
++ *              1 = queue is not full
++ *
++ *  handle:     handle for the channel to query.
++ *
++ ****************************************************************************/
++int ep93xx_dma_queue_full(int handle)
++{
++      int list_full = 0;
++      unsigned long flags;
++      int channel;
++
++      /*
++       *  Get the DMA hw channel # from the handle.
++       */
++      channel = dma_get_channel_from_handle(handle);
++
++      /*
++       *  See if this is a valid handle.
++       */
++      if (channel < 0) {
++              printk(KERN_ERR "DMA Queue Full: Invalid dma handle.\n");
++
++              /*
++               *  Fail.
++               */
++              return (-EINVAL);
++      }
++
++      DPRINTK("DMA %d: queue full \n", channel);
++
++      /*
++       *  Mask interrupts and hold on to the original state.
++       */
++      local_irq_save(flags);
++
++      /*
++       *  If the last item is equal to the used item then
++       *  the queue is full.
++       */
++      if (dma_chan[channel].total_buffers < MAX_EP93XX_DMA_BUFFERS) {
++              list_full = FALSE;
++      } else {
++              list_full = TRUE;
++      }
++
++      /*
++       *  restore interrupts.
++       */
++      local_irq_restore(flags);
++
++      return (list_full);
++}
++
++
++/*****************************************************************************
++ *
++ *  int ep93xx_dma_get_position()
++ *
++ *  Description:  Takes two integer pointers and fills them with the start
++ *                and current address of the buffer currently transferring
++ *                on the specified DMA channel.
++ *
++ *  handle         handle for the channel to query.
++ *  *buf_id        buffer id for the current buffer transferring on the
++ *                 dma channel.
++ *  *total         total bytes transferred on the channel.  Only counts
++ *                 whole buffers transferred.
++ *  *current_frac  number of bytes transferred so far in the current buffer.
++ ****************************************************************************/
++int
++ep93xx_dma_get_position(int handle, unsigned int * buf_id,
++                        unsigned int * total, unsigned int * current_frac )
++{
++      int  channel;
++      ep93xx_dma_t * dma;
++      unsigned int buf_id1, total1, current_frac1, buf_id2, total2;
++      unsigned int Status, NextBuffer, StateIsBufNext, M2P_reg_base=0;
++      unsigned int pause1, pause2;
++
++      /*
++       *  Get the DMA hw channel # from the handle.  See if this is a
++       *  valid handle.
++       */
++      channel = dma_get_channel_from_handle(handle);
++      if (channel < 0) {
++              printk(KERN_ERR "DMA Get Position: Invalid dma handle.\n");
++              return(-EINVAL);
++      }
++
++      dma = &dma_chan[channel];
++
++      /*
++       * If DMA moves to a new buffer in the middle of us grabbing the
++       * buffer info, then do it over again.
++       */
++      do{
++              buf_id1 = dma->buffer_queue[dma->current_buffer].buf_id;
++              total1  = dma->total_bytes;
++              pause1  = dma->pause;
++
++              if (channel < 10) {
++                      /* M2P */
++                      M2P_reg_base = dma->reg_base;
++
++                      Status = inl(M2P_reg_base+M2P_OFFSET_STATUS);
++
++                      NextBuffer = ((Status & STATUS_M2P_NEXTBUFFER) != 0);
++
++                      StateIsBufNext = ((Status & STATUS_M2P_CURRENT_MASK) ==
++                                        STATUS_M2P_DMA_BUF_NEXT);
++
++                      if( NextBuffer ^ StateIsBufNext )
++                              current_frac1 = inl(M2P_reg_base+M2P_OFFSET_CURRENT1) -
++                                              inl(M2P_reg_base+M2P_OFFSET_BASE1);
++                      else
++                              current_frac1 = inl(M2P_reg_base+M2P_OFFSET_CURRENT0) -
++                                              inl(M2P_reg_base+M2P_OFFSET_BASE0);
++
++              } else {
++                      /* M2M - TODO implement this for M2M */
++                      current_frac1 = 0;
++              }
++
++              buf_id2 = dma->buffer_queue[dma->current_buffer].buf_id;
++              total2 = dma->total_bytes;
++              pause2  = dma->pause;
++
++      } while ( (buf_id1 != buf_id2) || (total1 != total2) || (pause1 != pause2) );
++
++      if (pause1)
++              current_frac1 = 0;
++
++      if (buf_id)
++              *buf_id = buf_id1;
++
++      if (total)
++              *total  = total1;
++
++      if (current_frac)
++              *current_frac = current_frac1;
++
++      /*
++       *  Success.
++       */
++      return(0);
++}
++
++/*  changed for AC97 port from Virgo 1-4-3 */
++#if 0
++/*****************************************************************************
++ *
++ *  int ep93xx_dma_get_position(int handle, unsigned int * buf_id,
++                                unsigned int * total)
++ *
++ *  Description:    Takes two integer pointers and fills them with the start
++ *                  and current address of the buffer currently transferring
++ *                  on the specified DMA channel.
++ *
++ *  handle:         handle for the channel to query.
++ *  buf_id:         pointer which is filled in with the buffer id for the
++ *                  current buffer transferring on the dma channel.
++ *                  buffer being transferred.
++ *  total  :        pointer which is filled in with the total bytes
++ *                  transferred on the channel.
++ ****************************************************************************/
++int
++ep93xx_dma_get_position(int handle, unsigned int *buf_id, unsigned int *total)
++{
++      int channel;
++      ep93xx_dma_t *dma;
++
++      /*
++       *  Get the DMA hw channel # from the handle.
++       */
++      channel = dma_get_channel_from_handle(handle);
++
++      /*
++       *  See if this is a valid handle.
++       */
++      if (channel < 0) {
++              printk(KERN_ERR "DMA Get Position: Invalid dma handle.\n");
++
++              /*
++               *  Fail.
++               */
++              return (-EINVAL);
++      }
++
++      dma = &dma_chan[channel];
++
++      /*
++       *  TODO: should irqs be disabled here?
++       */
++
++      *buf_id = dma->buffer_queue[dma->current_buffer].buf_id;
++
++      *total = dma->total_bytes;
++
++      DPRINTK("DMA buf_id %d, total %d\n", *buf_id, *total);
++
++      /*
++       *  Success.
++       */
++      return (0);
++}
++#endif
++
++
++
++/*****************************************************************************
++ *
++ *  int ep93xx_dma_get_total(int handle)
++ *
++ *  Description:    Returns the total number of bytes transferred on the
++ *                  specified channel since the channel was requested.
++ *
++ *  handle:     handle for the channel to query.
++ *
++ ****************************************************************************/
++int ep93xx_dma_get_total(int handle)
++{
++      int channel;
++
++      /*
++       *  Get the DMA hw channel # from the handle.
++       */
++      channel = dma_get_channel_from_handle(handle);
++
++      /*
++       *  See if this is a valid handle.
++       */
++      if (channel < 0) {
++              printk(KERN_ERR "DMA Get Total: Invalid dma handle.\n");
++
++              /*
++               *  Fail.
++               */
++              return (-EINVAL);
++      }
++
++      DPRINTK("DMA %d: total: %d \n", channel, dma_chan[channel].total_bytes);
++
++      /*
++       *  Return the total number of bytes transferred on this channel since
++       *  it was requested.
++       */
++      return (dma_chan[channel].total_bytes);
++}
++
++/*****************************************************************************
++ * ep93xx_dma_request
++ *
++ * Description: This function will allocate a DMA channel for a particular
++ * hardware peripheral.  Before initiating a transfer on the allocated
++ * channel, the channel must be set up and buffers have to queued up.
++ *
++ *  handle:     pointer to an integer which is filled in with a unique
++ *              handle for this instance of the dma interface.
++ *  device_id   string with the device name, primarily used by /proc.
++ *  device      hardware device ID for which the requested dma channel will
++ *              transfer data.
++ *
++ ****************************************************************************/
++int
++ep93xx_dma_request(int *handle, const char *device_id, ep93xx_dma_dev_t device)
++{
++      ep93xx_dma_t *dma = NULL;
++      int channel;
++      unsigned int error = 0;
++      unsigned int loop;
++      unsigned int M2P_reg_base;
++
++      /*
++       *  Check if the device requesting a DMA channel is a valid device.
++       */
++      if ((device >= UNDEF) || (device < 0)) {
++              /*
++               *  Invalid device, so return an error.
++               */
++              return (-ENODEV);
++      }
++
++      /*
++       *  We've got a valid hardware device requesting a DMA channel.
++       *  Now check if the device should open an M2P or M2M channel
++       */
++      if (device < 20) {
++              channel = dma_open_m2p(device);
++      } else {
++              channel = dma_open_m2m(device);
++      }
++
++      /*
++       *  Check if we successfully opened a DMA channel
++       */
++      if (channel < 0) {
++              printk(KERN_ERR
++                     "%s: Could not open dma channel for this device.\n",
++                     device_id);
++
++              /*
++               *  Fail.
++               */
++              return (-EBUSY);
++      }
++
++      dma = &dma_chan[channel];
++
++      /*
++       *  Request the appropriate IRQ for the specified channel
++       */
++      if (channel < 10) {
++              error = request_irq(dma->irq, dma_m2p_irq_handler, SA_INTERRUPT,
++                                  device_id, (void *)dma);
++      } else {
++              error =
++                  request_irq(dma->irq, &dma_m2m_irq_handler, SA_INTERRUPT,
++                              device_id, (void *)dma);
++      }
++
++      /*
++       *  Check for any errors during the irq request
++       */
++      if (error) {
++              printk(KERN_ERR
++                     "%s: unable to request IRQ %d for DMA channel\n",
++                     device_id, dma->irq);
++              /*
++               *  Fail.
++               */
++              return (error);
++      }
++
++      /*
++       *  Generate a valid handle and exit.
++       *
++       *  Increment the last valid handle.
++       *  Check for wraparound (unlikely, but we like to be complete).
++       */
++      dma->last_valid_handle++;
++
++      if ((dma->last_valid_handle & DMA_HANDLE_SPECIFIER_MASK) !=
++          (channel << 28)) {
++              /*
++               *  If we wrapped around start over.
++               */
++              dma->last_valid_handle = (channel << 28) + 1;
++      }
++
++      /*
++       *  Fill in the handle pointer with a valid handle for
++       *  this dma channel instance.
++       */
++      *handle = dma->last_valid_handle;
++
++      DPRINTK("Handle for channel %d: 0x%x\n", channel, *handle);
++
++      /*
++       * Save the device ID and device name.
++       */
++      dma->device = device;
++      dma->device_id = device_id;
++
++      /*
++       *  Init all fields within the dma instance.
++       */
++      for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) {
++              dma->buffer_queue[loop].buf_id = -1;
++      }
++
++      /*
++       *  Initialize all buffer queue variables.
++       */
++      dma->current_buffer = 0;
++      dma->last_buffer = 0;
++
++      dma->new_buffers = 0;
++      dma->used_buffers = 0;
++      dma->total_buffers = 0;
++
++      /*
++       *  Initialize the total bytes variable
++       */
++      dma->total_bytes = 0;
++
++      /*
++       *  Initialize the transfer and pause state variables to 0.
++       */
++      dma->xfer_enable = 0;
++
++      dma->pause = 0;
++
++      /*
++       *  Initialize the pause buffer structure.
++       */
++      dma->pause_buf.buf_id = -1;
++
++      /*
++       *  Initialize the callback function and user data fields.
++       */
++      dma->callback = NULL;
++
++      /*
++       * User data used as a parameter for the Callback function.  The user
++       * sets up the data and sends it with the callback function.
++       */
++      dma->user_data = 0;
++
++      M2P_reg_base = dma_chan[channel].reg_base;
++
++      /*
++       *  Debugging message.
++       */
++      DPRINTK("Successfully requested dma channel %d\n", channel);
++      DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS));
++      DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL));
++      DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN));
++      DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC));
++      DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0));
++      DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0));
++      DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0));
++      DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1));
++      DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1));
++      DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
++
++      DPRINTK("Buffer    source       size       last       used \n");
++      for (loop = 0; loop < 5; loop++) {
++              DPRINTK("%d        0x%x         0x%x        %d         %d \n",
++                      loop, dma->buffer_queue[loop].source,
++                      dma->buffer_queue[loop].size,
++                      dma->buffer_queue[loop].last,
++                      dma->buffer_queue[loop].used);
++      }
++      DPRINTK("pause     0x%x         0x%x        %d         %d \n",
++              dma->pause_buf.source, dma->pause_buf.size,
++              dma->pause_buf.last, dma->pause_buf.used);
++
++      DPRINTK("Pause - %d \n", dma->pause);
++      DPRINTK("xfer_enable - %d \n", dma->xfer_enable);
++      DPRINTK("total bytes - 0x%x \n", dma->total_bytes);
++      DPRINTK("total buffer - %d \n", dma->total_buffers);
++      DPRINTK("new buffers - %d \n", dma->new_buffers);
++      DPRINTK("current buffer - %d \n", dma->current_buffer);
++      DPRINTK("last buffer - %d \n", dma->last_buffer);
++      DPRINTK("used buffers - %d \n", dma->used_buffers);
++
++      DPRINTK("CURRENT1 - 0x%x \n",
++              readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
++      DPRINTK("VIC0IRQSTATUS - 0x%x, VIC0INTENABLE - 0x%x \n",
++              *(unsigned int *)(VIC0IRQSTATUS),
++              *(unsigned int *)(VIC0INTENABLE));
++
++      /*
++       *  Success.
++       */
++      return (0);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_dma_free
++ *
++ * Description: This function will free the dma channel for future requests.
++ *
++ *  handle:     handle for the channel to be freed.
++ *
++ ****************************************************************************/
++int ep93xx_dma_free(int handle)
++{
++      ep93xx_dma_t *dma;
++      unsigned int M2M_reg_base, M2P_reg_base, uiCONTROL;
++      int channel;
++
++      /*
++       *  Get the DMA hw channel # from the handle.
++       */
++      channel = dma_get_channel_from_handle(handle);
++
++      /*
++       *  See if this is a valid handle.
++       */
++      if (channel < 0) {
++              printk(KERN_ERR "DMA Free: Invalid dma handle.\n");
++
++              /*
++               *  Fail.
++               */
++              return (-EINVAL);
++      }
++
++      /*
++       *  Get a pointer to the dma instance.
++       */
++      dma = &dma_chan[channel];
++
++      /*
++       *  Disable the dma channel
++       */
++      if (channel < 10) {
++              /*
++               *  M2P channel
++               */
++              M2P_reg_base = dma->reg_base;
++
++              uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++              uiCONTROL &= ~CONTROL_M2P_ENABLE;
++              writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++      } else {
++              /*
++               *  M2M channel
++               */
++              M2M_reg_base = dma->reg_base;
++
++              uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++              uiCONTROL &= ~CONTROL_M2M_ENABLE;
++              writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++      }
++
++      /*
++       *  Free the interrupt servicing this dma channel
++       */
++      free_irq(dma->irq, (void *)dma);
++
++      /*
++       *  Decrement the reference count for this instance of the dma interface
++       */
++      dma->ref_count--;
++
++      /*
++       *  Set the transfer and pause state variables to 0
++       *  (unititialized state).
++       */
++      dma->xfer_enable = 0;
++      dma->pause = 0;
++
++      /*
++       *  Debugging message.
++       */
++      DPRINTK("Successfully freed dma channel %d\n", channel);
++
++      /*
++       *  Success.
++       */
++      return (0);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_dma_init(void)
++ *
++ * Description: This function is called during system initialization to
++ * setup the interrupt number and register set base address for each DMA
++ * channel.
++ *
++ ****************************************************************************/
++static int __init ep93xx_dma_init(void)
++{
++      int channel;
++
++      /*
++       * Init some values in each dma instance.
++       */
++      for (channel = 0; channel < MAX_EP93XX_DMA_CHANNELS; channel++) {
++              /*
++               *  IRQ for the specified dma channel.
++               */
++              dma_chan[channel].irq = IRQ_DMAM2P0 + channel;
++
++              /*
++               *  Initial value of the dma channel handle.
++               */
++              dma_chan[channel].last_valid_handle = channel << 28;
++
++              /*
++               *  Give the instance a pointer to the dma channel register
++               *  base.
++               */
++              if (channel < 10) {
++                      dma_chan[channel].reg_base = DMAM2PChannelBase[channel];
++              } else {
++                      dma_chan[channel].reg_base =
++                          DMAM2MChannelBase[channel - 10];
++              }
++
++              /*
++               *  Initialize the reference count for this channel.
++               */
++              dma_chan[channel].ref_count = 0;
++      }
++
++      DPRINTK("DMA Interface intitialization complete\n");
++
++      /*
++       * Success
++       */
++      return 0;
++}
++
++__initcall(ep93xx_dma_init);
++
++EXPORT_SYMBOL(ep93xx_dma_add_buffer);
++EXPORT_SYMBOL(ep93xx_dma_config);
++EXPORT_SYMBOL(ep93xx_dma_flush);
++EXPORT_SYMBOL(ep93xx_dma_free);
++EXPORT_SYMBOL(ep93xx_dma_get_position);
++EXPORT_SYMBOL(ep93xx_dma_get_total);
++EXPORT_SYMBOL(ep93xx_dma_init);
++EXPORT_SYMBOL(ep93xx_dma_pause);
++EXPORT_SYMBOL(ep93xx_dma_queue_full);
++EXPORT_SYMBOL(ep93xx_dma_remove_buffer);
++EXPORT_SYMBOL(ep93xx_dma_request);
++EXPORT_SYMBOL(ep93xx_dma_start);
++
+diff --git a/arch/arm/mach-ep93xx/dma_ep93xx.h b/arch/arm/mach-ep93xx/dma_ep93xx.h
+new file mode 100644
+index 0000000..3ec0b0d
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/dma_ep93xx.h
+@@ -0,0 +1,194 @@
++/*****************************************************************************
++ *
++ * arch/arm/mach-ep93xx/dma_ep93xx.h
++ *
++ * DESCRIPTION:    93XX DMA controller API private defintions.
++ *
++ * Copyright Cirrus Logic Corporation, 2003.  All rights reserved
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ ****************************************************************************/
++#ifndef _EP93XX_DMA_H_
++#define _EP93XX_DMA_H_
++
++#define MAX_EP93XX_DMA_BUFFERS      32
++
++#ifndef TRUE
++#define TRUE                        1
++#endif
++
++#ifndef FALSE
++#define FALSE                       0
++#endif
++
++#ifndef NULL
++#define NULL                        0
++#endif
++
++/*****************************************************************************
++ *
++ * DMA buffer structure type.
++ *
++ ****************************************************************************/
++typedef struct ep93xx_dma_buffer_s {
++      unsigned int source;    /* buffer physical source address.          */
++      unsigned int dest;      /* buffer physical destination address,     */
++      /* only used with the 2 M2M channels.       */
++      unsigned int size;      /* buffer size in bytes                     */
++      unsigned int last;      /* 1 if this is the last buffer             */
++      /* in this transaction.  If 1,              */
++      /* disable the NFBint so we aren't          */
++      /* interrupted for another buffer           */
++      /* when we know there won't be another.     */
++      unsigned int used;      /* This field is set to 1 by the DMA        */
++      /* interface after the buffer is transferred */
++      int buf_id;             /* unique identifyer specified by the       */
++      /* the driver which requested the dma       */
++} ep93xx_dma_buffer_t;
++
++typedef ep93xx_dma_buffer_t *ep93xx_dma_buffer_p;
++
++/*****************************************************************************
++ *
++ * Instance definition for the DMA interface.
++ *
++ ****************************************************************************/
++typedef struct ep7312_dma_s {
++      /*
++       *  This 1 when the instance is in use, and 0 when it's not.
++       */
++      unsigned int ref_count;
++
++      /*
++       * This is the last valid handle for this instance.  When giving out a
++       * new handle this will be incremented and given out.
++       */
++      int last_valid_handle;
++
++      /*
++       * device specifies one of the 20 DMA hardware ports this
++       * DMA channel will service.
++       */
++      ep93xx_dma_dev_t device;
++
++      /*
++       * DMABufferQueue is the queue of buffer structure pointers which the
++       * dma channel will use to setup transfers.
++       */
++      ep93xx_dma_buffer_t buffer_queue[MAX_EP93XX_DMA_BUFFERS];
++
++      /*
++       * currnt_buffer : This is the buffer currently being transfered on
++       *                 this channel.
++       * last_buffer : This is the last buffer for this transfer.
++       * Note: current_buffer + 1 is already programmed into the dma
++       *       channel as the next buffer to transfer. Don't write
++       *       over either entry.
++       */
++      int current_buffer;
++      int last_buffer;
++
++      /*
++       * The following 3 fields are buffer counters.
++       *
++       * iNewBuffers: Buffers in the queue which have not been transfered.
++       * iUsedBuffers: Buffers in the queue which have have been tranferred,
++       *               and are waiting to be returned.
++       * iTotalBuffers: Total number of buffers in the queue.
++       */
++      int new_buffers;
++      int used_buffers;
++      int total_buffers;
++
++      /*
++       * uiTotalBytes has the total bytes transfered on the channel since the
++       * last flush.  This value does not include the bytes tranfered in the
++       * current buffer.  A byte count is only added after a complete buffer
++       * is tranfered.
++       */
++      unsigned int total_bytes;
++
++      /*
++       *  Interrupt number for this channel
++       */
++      unsigned int irq;
++
++      /*
++       * Indicates whether or not the channel is currently enabled to transfer
++       * data.
++       */
++      unsigned int xfer_enable;
++
++      /*
++       * pause indicates if the dma channel was paused by calling the pause
++       * ioctl.
++       */
++      unsigned int pause;
++
++      /*
++       *  buffer structure used during a pause to capture the current
++       *  address and remaining bytes for the buffer actively being transferred
++       *  on the channel. This buffer will be used to reprogram the dma
++       *  channel upon a resume.
++       */
++      ep93xx_dma_buffer_t pause_buf;
++
++      /*
++       * DMACallback is a function pointer which the calling application can
++       * use install a function to.  this fuction can be used to notify the
++       * calling application of an interrupt.
++       */
++      dma_callback callback;
++
++      /*
++       * User data used as a parameter for the Callback function.  The user
++       * sets up the data and sends it with the callback function.
++       */
++      unsigned int user_data;
++
++      /*
++       * A string representation of the device attached to the channel.
++       */
++      const char *device_id;
++
++      /*
++       * The register base address for this dma channel.
++       */
++      unsigned int reg_base;
++
++} ep93xx_dma_t;
++
++/*****************************************************************************
++ *
++ * DMA macros
++ *
++ ****************************************************************************/
++#define DMA_HANDLE_SPECIFIER_MASK   0xF0000000
++#define DMA_CH0_HANDLE_SPECIFIER    0x00000000
++#define DMA_CH1_HANDLE_SPECIFIER    0x10000000
++#define DMA_CH2_HANDLE_SPECIFIER    0x20000000
++#define DMA_CH3_HANDLE_SPECIFIER    0x30000000
++#define DMA_CH4_HANDLE_SPECIFIER    0x40000000
++#define DMA_CH5_HANDLE_SPECIFIER    0x50000000
++#define DMA_CH6_HANDLE_SPECIFIER    0x60000000
++#define DMA_CH7_HANDLE_SPECIFIER    0x70000000
++#define DMA_CH8_HANDLE_SPECIFIER    0x80000000
++#define DMA_CH9_HANDLE_SPECIFIER    0x90000000
++#define DMA_CH10_HANDLE_SPECIFIER   0xA0000000
++#define DMA_CH11_HANDLE_SPECIFIER   0xB0000000
++
++#endif
++
+diff --git a/arch/arm/mach-ep93xx/ep93xx.c b/arch/arm/mach-ep93xx/ep93xx.c
+new file mode 100644
+index 0000000..a565f14
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/ep93xx.c
+@@ -0,0 +1,571 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/ep93xx.c
++ *
++ *  Copyright (C) 2000-2003 Deep Blue Solutions Ltd
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *  Copyright (C) 2005 Michael Burian
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2, as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/device.h>
++#include <linux/interrupt.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/hardware/amba.h>
++#include <asm/mach/time.h>
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++static __init void check_model(void)
++{
++      unsigned long x;
++      char *model;
++      char *rev;
++
++      printk(KERN_INFO "CPU model: ");
++
++      x = readl(USRFLG);
++      switch (x) {
++      case 0:
++              model = "15";
++              break;
++      case 2:
++              model = "12";
++              break;
++      case 4:
++              model = "01";
++              break;
++      default:
++              printk("(unknown model %ld) ", x);
++              model = "xx";
++              break;
++      }
++
++      x = readl(SYSCON_SYSCFG) >> 28;
++      switch (x) {
++      case 0:
++              rev = "A";
++              break;
++      case 1:
++              rev = "B";
++              break;
++      case 2:
++              rev = "C";
++              break;
++      case 3:
++              rev = "D0";
++              break;
++      case 4:
++              rev = "D1";
++              break;
++      case 5:
++              rev = "E";
++              break;
++      default:
++              printk("(unknown revision %ld) ", x);
++              rev = "unknown";
++              break;
++      }
++
++      printk("Cirrus Logic EP93%s, silicon rev %s\n", model, rev);
++}
++
++static struct amba_device dma_device = {
++      .dev = {
++              .bus_id = "0x80000000:dma",
++              },
++      .res = {
++              .start = DMA_BASE,
++              .end = DMA_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80000000,
++};
++
++static struct amba_device mac_device = {
++      .dev = {
++              .bus_id = "0x80010000:mac",
++              },
++      .res = {
++              .start = MAC_BASE,
++              .end = MAC_BASE + SZ_64K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80010000,
++};
++
++static struct amba_device usb_device = {
++      .dev = {
++              .bus_id = "0x80020000:usb",
++              .coherent_dma_mask = 0xffffffff,
++              },
++      .res = {
++              .start = USB_BASE,
++              .end = USB_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {IRQ_USH, NO_IRQ},
++      .periphid = 0x80020000,
++};
++
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++static struct amba_device raster_device = {
++      .dev = {
++              .bus_id = "0x80030000:raster",
++              },
++      .res = {
++              .start = RASTER_BASE,
++              .end = RASTER_BASE + SZ_8K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80030000,
++};
++#endif
++
++static struct amba_device sdram_device = {
++      .dev = {
++              .bus_id = "0x80060000:sdram",
++              },
++      .res = {
++              .start = SDRAM_BASE,
++              .end = SDRAM_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80060000,
++};
++
++static struct amba_device smc_device = {
++      .dev = {
++              .bus_id = "0x80080000:smc",
++              },
++      .res = {
++              .start = SMC_BASE,
++              .end = SMC_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80080000,
++};
++
++static struct amba_device boot_device = {
++      .dev = {
++              .bus_id = "0x80090000:boot",
++              },
++      .res = {
++              .start = BOOT_BASE,
++              .end = BOOT_BASE + SZ_16K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80090000,
++};
++
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++static struct amba_device ide_device = {
++      .dev = {
++              .bus_id = "0x800a0000:ide",
++              },
++      .res = {
++              .start = IDE_BASE,
++              .end = IDE_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x800a0000,
++};
++#endif
++
++static struct amba_device vic1_device = {
++      .dev = {
++              .bus_id = "0x800b0000:vic1",
++              },
++      .res = {
++              .start = VIC0_BASE,
++              .end = VIC0_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x800b0000,
++};
++
++static struct amba_device vic2_device = {
++      .dev = {
++              .bus_id = "0x800c0000:vic2",
++              },
++      .res = {
++              .start = VIC1_BASE,
++              .end = VIC1_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x800c0000,
++};
++
++static struct amba_device timer_device = {
++      .dev = {
++              .bus_id = "0x80810000:timer",
++              },
++      .res = {
++              .start = TIMERS_BASE,
++              .end = TIMERS_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80810000,
++};
++
++static struct amba_device i2s_device = {
++      .dev = {
++              .bus_id = "0x80820000:i2s",
++              },
++      .res = {
++              .start = I2S_BASE,
++              .end = I2S_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80820000,
++};
++
++static struct amba_device security_device = {
++      .dev = {
++              .bus_id = "0x80830000:security",
++              },
++      .res = {
++              .start = SECURITY_BASE,
++              .end = SECURITY_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80830000,
++};
++
++static struct amba_device gpio_device = {
++      .dev = {
++              .bus_id = "0x80840000:gpio",
++              },
++      .res = {
++              .start = GPIO_BASE,
++              .end = GPIO_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80840000,
++};
++
++static struct amba_device ac97_device = {
++      .dev = {
++              .bus_id = "0x80880000:ac97",
++              },
++      .res = {
++              .start = AC97_BASE,
++              .end = AC97_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80880000,
++};
++
++static struct amba_device ssp_device = {
++      .dev = {
++              .bus_id = "0x808a0000:ssp",
++              },
++      .res = {
++              .start = SSP_BASE,
++              .end = SSP_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x808a0000,
++};
++
++static struct amba_device irda_device = {
++      .dev = {
++              .bus_id = "0x808b0000:irda",
++              },
++      .res = {
++              .start = IRDA_BASE,
++              .end = IRDA_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x808b0000,
++};
++
++static struct amba_device uart1_device = {
++      .dev = {
++              .bus_id = "0x808c0000:uart1",
++              },
++      .res = {
++              .start = UART1_BASE,
++              .end = UART1_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {IRQ_UART1, NO_IRQ},
++      .periphid = 0x808c0000,
++};
++
++static struct amba_device uart2_device = {
++      .dev = {
++              .bus_id = "0x808d0000:uart2",
++              },
++      .res = {
++              .start = UART2_BASE,
++              .end = UART2_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {IRQ_UART2, NO_IRQ},
++      .periphid = 0x808d0000,
++};
++
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++static struct amba_device uart3_device = {
++      .dev = {
++              .bus_id = "0x808e0000:uart3",
++              },
++      .res = {
++              .start = UART3_BASE,
++              .end = UART3_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {IRQ_UART3, NO_IRQ},
++      .periphid = 0x808e0000,
++};
++
++static struct amba_device key_device = {
++      .dev = {
++              .bus_id = "0x808f0000:key",
++              },
++      .res = {
++              .start = KEY_BASE,
++              .end = KEY_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x808f0000,
++};
++
++static struct amba_device touch_device = {
++      .dev = {
++              .bus_id = "0x80900000:touch",
++              },
++      .res = {
++              .start = TOUCH_BASE,
++              .end = TOUCH_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80900000,
++};
++
++static struct amba_device pwm_device = {
++      .dev = {
++              .bus_id = "0x80910000:pwm",
++              },
++      .res = {
++              .start = PWM_BASE,
++              .end = PWM_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80910000,
++};
++#endif
++
++static struct amba_device rtc_device = {
++      .dev = {
++              .bus_id = "0x80920000:rtc",
++              },
++      .res = {
++              .start = RTC_BASE,
++              .end = RTC_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {IRQ_RTC, NO_IRQ},
++      .periphid = 0x80920000,
++};
++
++static struct amba_device syscon_device = {
++      .dev = {
++              .bus_id = "0x80930000:syscon",
++              },
++      .res = {
++              .start = SYSCON_BASE,
++              .end = SYSCON_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80930000,
++};
++
++static struct amba_device watchdog_device = {
++      .dev = {
++              .bus_id = "0x80940000:watchdog",
++              },
++      .res = {
++              .start = WATCHDOG_BASE,
++              .end = WATCHDOG_BASE + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++              },
++      .irq = {NO_IRQ, NO_IRQ},
++      .periphid = 0x80940000,
++};
++
++static struct amba_device *amba_devs[] __initdata = {
++      /* AHB devices */
++      &dma_device,
++      &mac_device,
++      &usb_device,
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++      &raster_device,
++#endif
++      &sdram_device,
++      &smc_device,
++      &boot_device,
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++      &ide_device,
++#endif
++      &vic1_device,
++      &vic2_device,
++
++      /* APB devices */
++      &timer_device,
++      &i2s_device,
++      &security_device,
++      &gpio_device,
++      &ac97_device,
++      &ssp_device,
++      &irda_device,
++      &uart1_device,
++      &uart2_device,
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++      &uart3_device,
++      &key_device,
++      &touch_device,
++      &pwm_device,
++#endif
++      &rtc_device,
++      &syscon_device,
++      &watchdog_device,
++};
++
++static int __init ep93xx_init(void)
++{
++      int i;
++
++      check_model();
++
++      for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
++              struct amba_device *d = amba_devs[i];
++              amba_device_register(d, &iomem_resource);
++      }
++
++      return 0;
++}
++
++arch_initcall(ep93xx_init);
++
++#define TIMER_INTERVAL        (508 * mSEC_10 / 1000)
++#define TICKS2USECS(x)        ((x) * 1000 / 508)
++
++static unsigned long timer_reload;
++
++/*
++ * Returns number of ms since last clock interrupt.  Note that interrupts
++ * will have been disabled by do_gettimeoffset()
++ */
++static unsigned long ep93xx_gettimeoffset(void)
++{
++      unsigned long ticks1, ticks2, status;
++
++      /*
++       * Get the current number of ticks.  Note that there is a race
++       * condition between us reading the timer and checking for
++       * an interrupt.  We get around this by ensuring that the
++       * counter has not reloaded between our two reads.
++       */
++      ticks2 = readl(TIMER1VALUE) & 0xffff;
++      do {
++              ticks1 = ticks2;
++              status = readl(VIC0RAWINTR);
++              ticks2 = readl(TIMER1VALUE) & 0xffff;
++      } while (ticks2 > ticks1);
++
++      /*
++       * Number of ticks since last interrupt.
++       */
++      ticks1 = timer_reload - ticks2;
++
++      /*
++       * Interrupt pending?  If so, we've reloaded once already.
++       */
++      if (status & (1 << IRQ_TIMER1))
++              ticks1 += timer_reload;
++
++      return TICKS2USECS(ticks1);
++}
++
++/*
++ * IRQ handler for the timer
++ */
++static irqreturn_t
++ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++      /* ...clear the interrupt */
++      writel(1, TIMER1CLEAR);
++
++      timer_tick(regs);
++
++      return IRQ_HANDLED;
++}
++
++static struct irqaction ep93xx_timer_irq = {
++      .name = "timer",
++      .flags = SA_INTERRUPT,
++      .handler = ep93xx_timer_interrupt
++};
++
++/*
++ * Set up timer interrupt
++ */
++static void __init __ep93xx_init_timer(unsigned long reload, unsigned int ctrl)
++{
++      unsigned int timer_ctrl = 0x80 | 0x40 | 0x08;   /* periodic at 508 kHz */
++
++      timer_reload = reload;
++      timer_ctrl |= ctrl;
++
++      /*
++       * Initialise to a known state (all timers off)
++       */
++
++      writel(0, TIMER1CONTROL);
++      writel(0, TIMER2CONTROL);
++      writel(0, TIMER3CONTROL);
++
++      writel(timer_reload, TIMER1LOAD);
++      writel(timer_reload, TIMER1VALUE);
++      writel(timer_ctrl, TIMER1CONTROL);
++
++      setup_irq(IRQ_TIMER1, &ep93xx_timer_irq);
++}
++
++static void __init ep93xx_init_timer(void)
++{
++      /* 10 ms interval on a 508 kHz clock */
++      __ep93xx_init_timer(5080, 0);
++}
++
++struct sys_timer ep93xx_timer = {
++      .init = ep93xx_init_timer,
++      .offset = ep93xx_gettimeoffset,
++};
+diff --git a/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h b/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h
+new file mode 100644
+index 0000000..d396e96
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h
+@@ -0,0 +1,41 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h
++ *
++ *  Copyright (C) 2004 Contec Steuerungstechnik & Automation GmbH
++ *                   Manfred Gruber <manfred.gruber@contec.at>
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/*
++ * configuration struct for GPIO IRQs
++ *
++ * enable = 1 --> this EGIO is a irq
++ * enable = 0 --> this EGIO is a GPIO
++ * flags can be               IRQT_RISING
++ *                    IRQT_FALLING
++ *                    IRQT_LOW
++ *                    IRQT_HIGH
++ *                    IRQT_PROBE
++ *
++ * On IRQT_PROBE nothing is done in setup irq code
++ */
++
++struct ep93xx_egpio_irq
++{
++      unsigned int enable;
++      unsigned int flags;
++};
++
+diff --git a/arch/arm/mach-ep93xx/irq.c b/arch/arm/mach-ep93xx/irq.c
+new file mode 100644
+index 0000000..578c783
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/irq.c
+@@ -0,0 +1,601 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/irq.c
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *
++ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA.  All rights reserved.
++ *
++ *  Copyright (C) 2002-2003 Cirrus Logic, Inc.
++ *
++ * Demux IRQ 59 by
++ * Copyright (C) 2004 Contec Steuerungstechnik & Automation GmbH
++ *                   Manfred Gruber <manfred.gruber@contec.at>
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ *
++ * Modified by Stefano Lena <stefano.lena@dave-tech.it>, DAVE s.r.l.
++ * for Cirrus Logic EP93xx series
++ *
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/timer.h>
++#include <linux/init.h>
++
++#include <asm/irq.h>
++
++#include <asm/arch/irqs.h>
++
++#include <asm/mach/irq.h>
++#include <asm/io.h>
++#include <asm/arch/hardware.h>
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++#include <asm/arch/regmap.h>
++#include <linux/errno.h>
++#include "ep93xx_gpio_irq.h"
++extern struct ep93xx_egpio_irq egpio_irqs[];
++
++/* GPIO Port A/B debug messages */
++/* #define DEBUG_GPIO */
++#ifdef DEBUG_GPIO
++#define IRQDBG(args...) printk(args)
++#else
++#define IRQDBG(args...) do {} while(0)
++#endif
++#endif
++/********************************************************************
++ *    Interrupt functions are defined as machine specific here.
++ *
++ *    Note:
++ *            1.  Only normal interrupts are defined here.
++ *            FIQs are a separate class of interrupts and would
++ *            be slowed down if handled like normal interrupts.
++ *
++ *            2.  TBD Invalid interrupt numbers are not checked.
++ *            Some interrupt inputs are tied to GND, which means
++ *            they will immediately activate when unmasked.
++ *            Which may be useful for some devices.
++ *
++ *            3.  TBD Edge triggered interrupts are not specially
++ *            handled.  The architecture should provide a way to
++ *            set up the edge trigger features and then a way to
++ *            control the acknowledge to the interrupt.
++ *
++ ************************************************************************/
++
++ /********************************************************************
++ *    demux interrupt handler for GPIO Port A and B on ep93xx
++ *
++ *    Note:
++      That IRQs from 64 to 79 defined as GPIO_IRQ0 - GPIO_IRQ15
++ *    GPIO IRQs on port F are as the are defined as IRQ_GPIOX
++ *    which are NOT handled in demux interrupt handler !!!!!
++ *
++ *    Default in mach-xy file a struct ep93xx_egpio_irq
++ *    can be set up, there you can configure which gpio
++ *    of Port A/B should be used as interrupt on startup.
++ *    Setting up this IRQs in your driver direct not on startup
++ *    you have to do a set_irq_type(GPIO_IRQX, flags) before
++ *    calling request irq. Possible Flags are:
++ *    IRQT_RISING, IRQT_FALLING, IRQT_LOW, IRQT_HIGH, IRQT_PROBE, IRQ_DB, IRQ_NOTDB
++ *    On IRQT_PROBE nothing is done.
++ ************************************************************************/
++
++ /********************************************************************
++ *    TODO:
++ *
++ *    Configure ack, mask, unsmask to use the right
++ *    Port F GPIO registers.
++ *
++************************************************************************/
++
++static void ep93xx_vic1_mask(unsigned int irq)
++{
++      writel((1 << irq), VIC0INTENCLEAR);
++}
++
++static void ep93xx_vic1_unmask(unsigned int irq)
++{
++      writel((1 << irq), VIC0INTENABLE);
++}
++
++static struct irqchip vic1_chip = {
++      .ack = ep93xx_vic1_mask,
++      .mask = ep93xx_vic1_mask,
++      .unmask = ep93xx_vic1_unmask,
++};
++
++static void ep93xx_vic2_mask(unsigned int irq)
++{
++      writel((1 << (irq - 32)), VIC1INTENCLEAR);
++}
++
++static void ep93xx_vic2_unmask(unsigned int irq)
++{
++      writel((1 << (irq - 32)), VIC1INTENABLE);
++}
++
++static struct irqchip vic2_chip = {
++      .ack = ep93xx_vic2_mask,
++      .mask = ep93xx_vic2_mask,
++      .unmask = ep93xx_vic2_unmask,
++};
++
++static void ep93xx_rtc_ack(unsigned int irq)
++{
++}
++
++static struct irqchip rtc_chip = {
++      .ack = ep93xx_rtc_ack,
++      .mask = ep93xx_vic2_mask,
++      .unmask = ep93xx_vic2_unmask,
++};
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++/*
++ * ack EGPIO irq's
++ * Ack only for edge triggered int's valid
++ */
++static void inline ep93xx_ack_gpio_irq(u32 irq)
++{
++      u32 irq_status;
++      u32 bit = IRQ_TO_BIT(irq);
++
++      IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++      /* Port A */
++      if(bit & 0xFF) {
++              irq_status = readl(GPIO_INTSTATUSA);
++              if(irq_status & bit)
++                      writel(bit, GPIO_AEOI);
++      }
++
++      /* Port B */
++      if(bit & 0xFF00) {
++              irq_status = readl(GPIO_INTSTATUSB);
++              if(irq_status & (bit >> 8))
++                      writel((bit >> 8), GPIO_BEOI);
++
++      }
++}
++
++/*
++ * unmask EGPIO irq's (enable)
++ */
++static void inline ep93xx_unmask_gpio_irq(u32 irq)
++{
++      u32 irq_status;
++      u32 bit = IRQ_TO_BIT(irq);
++
++      IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++      /* Port A */
++      if(bit & 0xFF) {
++              irq_status = readl(GPIO_AINTEN);
++              irq_status |=  bit;
++              writel(irq_status, GPIO_AINTEN);
++      }
++
++      /* Port B */
++      if(bit & 0xFF00) {
++              irq_status = readl(GPIO_BINTEN);
++              irq_status |= (bit >> 8);
++              writel(irq_status, GPIO_BINTEN);
++      }
++}
++
++/*
++ * Enable debounce on EGPIO IRQ
++ */
++
++static void ep93xx_debounce_enable(u32 irq)
++{
++      u32 db_status;
++      u32 bit = IRQ_TO_BIT(irq);
++
++      IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++      /* Port A */
++      if (bit & 0xFF) {
++              db_status = readl(GPIO_ADB);
++              db_status |= bit ;
++              writel(db_status, GPIO_ADB);
++      }
++
++      /* Port B */
++      if (bit & 0xFF00 ) {
++                      db_status = readl(GPIO_BDB);
++                      db_status |= (bit >> 8) ;
++                      writel(db_status, GPIO_BDB);
++      }
++
++}
++
++/*
++ * Disable debounce on EGPIO IRQ
++ */
++static void ep93xx_debounce_disable(u32 irq)
++{
++      u32 db_status;
++      u32 bit = IRQ_TO_BIT(irq);
++
++      IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++      /* Port A */
++      if (bit & 0xFF) {
++              db_status = readl(GPIO_ADB);
++              db_status &= ~bit ;
++              writel(db_status, GPIO_ADB);
++      }
++
++      /* Port B */
++      if (bit & 0xFF00 ) {
++                      db_status = readl(GPIO_BDB);
++                      db_status &= ~(bit >> 8) ;
++                      writel(db_status, GPIO_BDB);
++      }
++
++}
++
++/*
++ * mask EGPIO irq's (disable)
++ */
++static void inline ep93xx_mask_gpio_irq(u32 irq)
++{
++      u32 irq_status;
++      u32 bit = IRQ_TO_BIT(irq);
++
++      IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++      /* Port A */
++      if(bit & 0xFF) {
++              irq_status = readl(GPIO_AINTEN);
++              irq_status &= ~bit;
++              writel(irq_status, GPIO_AINTEN);
++      }
++
++      /* Port B */
++      if(bit & 0xFF00) {
++              irq_status = readl(GPIO_BINTEN);
++              irq_status &= ~(bit >> 8);
++              writel(irq_status, GPIO_BINTEN);
++      }
++}
++
++
++
++/*
++ * make a EGPIO to a irq input
++ */
++static int ep93xx_make_egio_to_irq(u32 bit,u32 irq)
++{
++      u32 irq_value;
++      int ret;
++
++      IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++      if(bit & 0xFF) {
++              /* Set direction to input for EGPIOA */
++              irq_value = readl(GPIO_PADDR);
++              irq_value &= ~bit;
++              if((ret = writel(irq_value, GPIO_PADDR)) != irq_value) {
++                      printk("%s irq: %d cannot set direction register(GPIO_PADDR) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
++                      return -EFAULT;
++              }
++      }
++      /* Port B */
++      if(bit & 0xFF00) {
++              /* Set direction to input for EGPIOB */
++              irq_value = readl(GPIO_PBDDR);
++              irq_value &= ~(bit >> 8);
++              if((ret = writel(irq_value, GPIO_PBDDR)) != irq_value) {
++                      printk("%s irq: %d cannot set direction register(GPIO_PBDDR) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
++                      return -EFAULT;
++              }
++      }
++
++      return 0;
++}
++
++/*
++ * make a EGPIO edge/level sensitive
++ */
++static int ep93xx_make_egio_sensitive(u32 bit, unsigned int flags,u32 irq)
++{
++      u32 irq_value;
++      int ret;
++
++      /* PORT A */
++      if(bit & 0xFF) {
++              /* Enable edge/level sensitive IRQ on EGPIO PORT A */
++              irq_value = readl(GPIO_AINTTYPE1);
++              if(flags && 1)
++                      irq_value |= bit;
++              else
++                      irq_value &= ~bit;
++              if((ret = writel(irq_value, GPIO_AINTTYPE1)) != irq_value) {
++                      printk("%s irq: %d cannot set IRQ parameter(GPIO_AINTYPE1) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
++                      return -EFAULT;
++              }
++      }
++
++      /* Port B */
++      if(bit & 0xFF00) {
++              /* Enable edge/level sensitive IRQ on EGPIO PORT B */
++              irq_value = readl(GPIO_BINTTYPE1);
++              if(flags && 1)
++                      irq_value |= (bit >> 8);
++              else
++                      irq_value &= ~(bit >> 8);
++              if((ret = writel(irq_value, GPIO_BINTTYPE1)) != irq_value) {
++                      /* printk("%s irq: %d cannot set IRQ parameter(GPIO_BINTYPE1) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret); */
++                      return -EFAULT;
++              }
++      }
++
++      return 0;
++}
++
++/*
++ * make a EGPIO high/low sensitive
++ */
++static int ep93xx_make_egio_high_low_sensitive(u32 bit, unsigned int flags,u32 irq)
++{
++      u32 irq_value;
++      int ret;
++
++      /* PORT A */
++      if(bit & 0xFF) {
++              /* Enable high/low sensitive IRQ on EGPIO PORT A */
++              irq_value = readl(GPIO_AINTTYPE2);
++              if(flags && 1)
++                      irq_value |= bit;
++              else
++                      irq_value &= ~bit;
++              if((ret = writel(irq_value, GPIO_AINTTYPE2)) != irq_value) {
++                      printk("%s irq: %d cannot set IRQ parameter(GPIO_AINTTYPE2) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
++                      return -EFAULT;
++              }
++      }
++
++      /* Port B */
++      if(bit & 0xFF00) {
++              /* Enable high/low sensitive IRQ on EGPIO PORT B */
++              irq_value = readl(GPIO_BINTTYPE2);
++              if(flags && 1)
++                      irq_value |= (bit >> 8);
++              else
++                      irq_value &= ~(bit >> 8);
++              if((ret = writel(irq_value, GPIO_BINTTYPE2)) != irq_value)
++              {
++                      printk("%s irq: %d cannot set IRQ parameter(GPIO_BINTYPE2) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
++                      return -EFAULT;
++              }
++      }
++
++      return 0;
++}
++
++
++
++
++/*
++ * type of GPIO irq's
++ */
++static int ep93xx_gpio_demux_handler_type(unsigned int irq, unsigned int flags)
++{
++      u32 bit = IRQ_TO_BIT(irq);
++      unsigned int debounce = 0;
++
++      IRQDBG("%s irq: %d\n",__FUNCTION__,irq);
++
++      /*if (flags == IRQT_PROBE)
++              return 0;*/
++
++      if ((flags & __IRQT_RISEDGE) | (flags & __IRQT_FALEDGE) | (flags & __IRQT_LOWLVL) | (flags & __IRQT_HIGHLVL) | (flags & IRQT_DB) | (flags & IRQT_NOTDB)) {
++              if(0 != ep93xx_make_egio_to_irq(bit,irq)) {
++                      printk("%s irq: %d cannot set direction register GPIO_PXDDR\n",__FUNCTION__,irq);
++                      return -EINVAL;
++              } else {
++                      if ((flags & IRQT_DB) | (flags & IRQT_NOTDB)) { /*      To use switch structure extract debounce
++                                                                                                                              flags from flags variable */
++                              debounce = (flags & IRQT_DB) | (flags & IRQT_NOTDB);
++                              flags &= ~debounce;
++                      }
++                      if((flags & __IRQT_RISEDGE) | (flags & __IRQT_FALEDGE)) {
++                              /* Configure for edge IRQ */
++                              if(0 == ep93xx_make_egio_sensitive(bit, 1,irq)) {
++                                      switch(flags) {
++                                      case __IRQT_RISEDGE:
++                                              if(0 != ep93xx_make_egio_high_low_sensitive(bit, 1,irq)) {
++                                                      printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
++                                                      return -EINVAL;
++                                              }
++                                      break;
++                                      case __IRQT_FALEDGE:
++                                              if(0 != ep93xx_make_egio_high_low_sensitive(bit, 0,irq)) {
++                                                      printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
++                                                      return -EINVAL;
++                                              }
++                                              break;
++                                      }
++
++                                      /* Now we set IRQ handler for edge */
++                                      /* set_irq_handler(irq, do_edge_IRQ); */
++                              } else {
++                                      printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE1\n",__FUNCTION__,irq);
++                                      return -EINVAL;
++                              }
++
++                      } else {
++                              if((flags & __IRQT_LOWLVL) | (flags & __IRQT_HIGHLVL)) {
++                                      /* Configure for level IRQ */
++                                      if(0 == ep93xx_make_egio_sensitive(bit, 0,irq)) {
++                                              switch(flags)
++                                              {
++                                                      case __IRQT_HIGHLVL:
++                                                              if(0 != ep93xx_make_egio_high_low_sensitive(bit, 1,irq))
++                                                              {
++                                                                      printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
++                                                                      return -EINVAL;
++                                                              }
++                                                              break;
++                                                      case __IRQT_LOWLVL:
++                                                              if(0 != ep93xx_make_egio_high_low_sensitive(bit, 0,irq))
++                                                              {
++                                                                      printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
++                                                                      return -EINVAL;
++                                                              }
++                                                              break;
++                                              }
++
++                                              /* Now we set IRQ handler level sensitive */
++                                              /* set_irq_handler(irq, do_level_IRQ); */
++                                      } else {
++                                              printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE1\n",__FUNCTION__,irq);
++                                              return -EINVAL;
++                                      }
++
++                              }
++                      }
++              }
++              /* For debounce flags handling */
++              if ((debounce & IRQT_DB) | (debounce & IRQT_NOTDB)) {
++                      switch(debounce)
++                      {
++                              case IRQT_DB:
++                                      ep93xx_debounce_enable(irq);
++                                      break;
++                              case IRQT_NOTDB:
++                                      ep93xx_debounce_disable(irq);
++                                      break;
++                      }
++              }
++      } else {
++              printk("ep93xx_type_gpio_irq: IRQ:%d no flags defined\n",irq);
++              return -EINVAL;
++      }
++return 0;
++}
++
++/*
++ * GPIO call handler
++ */
++static void ep93xx_gpio_handler(unsigned int mask, unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
++{
++      IRQDBG("%s irq: %d\n",__FUNCTION__,irq);
++
++      desc = irq_desc + irq;
++
++      while (mask) {
++              if (mask & 1) {
++                      IRQDBG("handling irq %d\n", irq);
++                      desc->handle(irq, desc, regs);
++              }
++              irq++;
++              desc++;
++              mask >>= 1;
++      }
++
++}
++
++/*
++ * GPIO dmux handler
++ */
++static void ep93xx_gpio_demux_handler(unsigned int irq_gpio, struct irqdesc *desc, struct pt_regs *regs)
++{
++      unsigned int mask;
++      unsigned int irq = IRQ_CHAINED_GPIO(0);
++
++      /*
++       * Mask the parent IRQ.
++       */
++      ep93xx_vic2_mask(irq_gpio);
++
++      mask =  readl(GPIO_INTSTATUSA) | (readl(GPIO_INTSTATUSB) << 8);
++
++      irq = IRQ_CHAINED_GPIO(0);
++      IRQDBG("%s mask: 0x%x irq: %d\n",__FUNCTION__,mask,irq);
++      ep93xx_gpio_handler(mask, irq, desc, regs);
++
++      /*
++       * Unmask the parent IRQ
++       */
++      ep93xx_vic2_unmask(irq_gpio);
++}
++
++
++static struct irqchip ep93xx_gpio_irq = {
++      .ack            = ep93xx_ack_gpio_irq,
++      .mask           = ep93xx_mask_gpio_irq,
++      .unmask         = ep93xx_unmask_gpio_irq,
++      .set_type       = ep93xx_gpio_demux_handler_type,
++};
++
++#endif
++
++
++void __init ep93xx_init_irq(void)
++{
++      unsigned int i;
++
++      /* Interrupt bits 0 and 1 are unused  */
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++      for (i = 2; i < NR_GLBL_IRQS; i++) {
++#else
++      for (i = 2; i < NR_IRQS; i++) {
++#endif
++              if(i < 32){
++                      /* Interrupts below 32 belong to VIC1 */
++                      set_irq_handler(i, do_level_IRQ);
++                      set_irq_chip(i, &vic1_chip);
++                      set_irq_flags(i, IRQF_VALID);
++
++              } else {
++                      if (i == IRQ_1HZ) {
++                              /* 1 Hz int is edge trigered, and not ackable */
++                              set_irq_handler(i, do_edge_IRQ);
++                              set_irq_chip(i, &rtc_chip);
++                              set_irq_flags(i, IRQF_VALID | IRQF_NOAUTOEN);
++                      } else {
++                              /* Interrupt 32 and above belong to VIC2 */
++                              set_irq_handler(i, do_level_IRQ);
++                              set_irq_chip(i, &vic2_chip);
++                              set_irq_flags(i, IRQF_VALID);
++                      }
++              }
++      }
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++      for (i = IRQ_CHAINED_GPIO(0) ; i <= IRQ_CHAINED_GPIO(15); i++) {
++
++              IRQDBG("%s irq: %d init \n",__FUNCTION__, i);
++
++              /* GPIO Interrupt is demux to 16 IRQs */
++              set_irq_chip(i, &ep93xx_gpio_irq);
++              set_irq_flags(i, IRQF_VALID);
++
++              if(egpio_irqs[i - NR_GLBL_IRQS].enable == 1) {
++                      set_irq_handler(i, do_level_IRQ);
++                      set_irq_type(i, egpio_irqs[i - NR_GLBL_IRQS].flags);
++              } else {
++                      set_irq_handler(i, do_edge_IRQ);
++              }
++      }
++      set_irq_chained_handler(IRQ_GPIO, ep93xx_gpio_demux_handler);
++#endif
++}
+diff --git a/arch/arm/mach-ep93xx/mach-acc.c b/arch/arm/mach-ep93xx/mach-acc.c
+new file mode 100644
+index 0000000..aa002ac
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-acc.c
+@@ -0,0 +1,67 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/acc.c
++ *
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *  Copyright (C) 2004 Klaus Fetscher
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++
++#include <asm/arch/platform.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++   the associated device drivers */
++
++static struct map_desc acc_io_desc[] __initdata = {
++      { EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
++      { EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
++};
++
++static void __init acc_map_io(void)
++{
++      iotable_init(acc_io_desc, ARRAY_SIZE(acc_io_desc));
++}
++
++static void __init acc_init(void)
++{
++}
++
++MACHINE_START(ACC, "acc")
++    /* Maintainer HiFish */
++      .phys_ram       = SDRAM_START,
++      .phys_io        = 0x80000000,
++      .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
++      .boot_params    = (SDRAM_START + 0x00000100),
++
++      .map_io         = acc_map_io,
++      .init_irq       = ep93xx_init_irq,
++      .init_machine   = acc_init,
++      .timer          = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-adssphere.c b/arch/arm/mach-ep93xx/mach-adssphere.c
+new file mode 100644
+index 0000000..2cbf5ca
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-adssphere.c
+@@ -0,0 +1,281 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/adssphere.c
++ *
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *  Copyright (C) 2005 Robert Whaley, ADS
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/fb.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/arch/adssphere.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++   the associated device drivers */
++
++static struct map_desc adssphere_io_desc[] __initdata =
++{
++      { EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
++      { EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
++      { ADSSPHERE_BASE_VIRT,  ADSSPHERE_BASE_PHYS,  SZ_1M,  MT_DEVICE },
++};
++
++static void __init adssphere_map_io(void)
++{
++      iotable_init(adssphere_io_desc, ARRAY_SIZE(adssphere_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++      return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++      .map_name       = "cfi_probe",
++      .width          = 4,
++      .init           = flash_init,
++      .exit           = flash_exit,
++      .set_vpp        = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++      .start          = 0x60000000,
++      .end            = 0x60000000 + SZ_32M - 1,
++      .flags          = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++      .name           = "flash",
++      .id             = 0,
++      .dev            = {
++                          .platform_data      = &flash_data,
++                        },
++      .num_resources  = 1,
++      .resource       = &cfi_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED     1
++#define LED_STATE_CLAIMED     2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_GREEN     1
++#define LED_MASK      (LED_GREEN)
++
++void adssphere_leds_event(led_event_t evt)
++{
++      unsigned long flags;
++
++      local_irq_save(flags);
++
++      switch (evt) {
++      case led_start:
++              led_state = LED_STATE_ENABLED;
++              hw_led_state = LED_GREEN;
++              break;
++
++      case led_stop:
++              led_state &= ~LED_STATE_ENABLED;
++              hw_led_state = 0;
++              break;
++
++      case led_claim:
++              led_state |= LED_STATE_CLAIMED;
++              hw_led_state = LED_GREEN;
++              break;
++
++      case led_release:
++              led_state &= ~LED_STATE_CLAIMED;
++              hw_led_state = 0;
++              break;
++
++      case led_timer:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state ^= LED_GREEN;
++              break;
++
++      case led_idle_start:
++              break;
++
++      case led_idle_end:
++              break;
++
++      case led_halted:
++              break;
++
++      case led_green_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_GREEN;
++              break;
++
++      case led_green_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_GREEN;
++              break;
++
++      case led_amber_on:
++              break;
++
++      case led_amber_off:
++              break;
++
++      case led_red_on:
++              break;
++
++      case led_red_off:
++              break;
++
++      default:
++              break;
++      }
++
++      writel(0x03, GPIO_PEDDR);
++
++      if  (led_state & LED_STATE_ENABLED)
++              writel(hw_led_state, GPIO_PEDR);
++      local_irq_restore(flags);
++}
++
++#endif
++
++#ifdef CONFIG_SOUND_EP93XX_AC97
++void adssphere_audio_power(int on)
++{
++      unsigned int tmp;
++
++      tmp = readb(ADSSPHERE_CR1);
++      if (on) {
++              tmp |=  ADSSPHERE_CR1_AMP_ON;
++              tmp &= ~ADSSPHERE_CR1_CDC_ON;
++      } else {
++              tmp &= ~ADSSPHERE_CR1_AMP_ON;
++              tmp |=  ADSSPHERE_CR1_CDC_ON;
++      }
++      writeb(tmp, ADSSPHERE_CR1);
++}
++
++#endif
++
++#ifdef CONFIG_FB_EP93XX
++void adssphere_blank(int blank_mode)
++{
++      unsigned int tmp;
++
++      switch (blank_mode) {
++      case FB_BLANK_UNBLANK:
++      case FB_BLANK_NORMAL:
++              /* turn on backlight via enable and pwm */
++              /* enable fb signals */
++              tmp = readl(ADSSPHERE_CR1);
++              tmp &= ~ADSSPHERE_CR1_PNL_ON;
++              tmp |= ADSSPHERE_CR1_PNL_EN | ADSSPHERE_CR1_BL_ON;
++              writel(tmp, ADSSPHERE_CR1);
++
++              writel(100, PWM0_TC);
++              writel(99, PWM0_DC);
++              writel(1, PWM0_EN);
++
++              break;
++
++
++      case FB_BLANK_VSYNC_SUSPEND:
++      case FB_BLANK_HSYNC_SUSPEND:
++      case FB_BLANK_POWERDOWN:
++
++              /* disable fb signals */
++              /* turn off backlight via enable and pwm */
++              tmp = readl(ADSSPHERE_CR1);
++              tmp |= ADSSPHERE_CR1_PNL_ON;
++              tmp &= ~(ADSSPHERE_CR1_PNL_EN | ADSSPHERE_CR1_BL_ON);
++              writel(tmp, ADSSPHERE_CR1);
++
++              writel(0, PWM0_EN);
++
++              break;
++      }
++}
++#endif
++
++static void __init adssphere_init (void)
++{
++#if 0
++      printk("physmap_configure\n");
++      physmap_configure(0x60000000, 0x02000000, 4, NULL);
++#endif
++      printk("platform_device_register\n");
++      platform_device_register(&cfi_flash_device);
++#ifdef CONFIG_LEDS
++      leds_event = adssphere_leds_event;
++#endif
++      leds_event(led_start);
++#ifdef CONFIG_SOUND_EP93XX_AC97
++      adssphere_audio_power(1);
++#endif
++}
++
++MACHINE_START(ADSSPHERE, "adssphere")
++      /* Maintainer: Applied Data Systems */
++      .phys_ram       = SDRAM_START,
++      .phys_io        = 0x80000000,
++      .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
++      .boot_params    = (SDRAM_START + 0x00000100),
++
++      .map_io         = adssphere_map_io,
++      .init_irq       = ep93xx_init_irq,
++      .init_machine   = adssphere_init,
++      .timer          = &ep93xx_timer,
++MACHINE_END
++
+diff --git a/arch/arm/mach-ep93xx/mach-dma03.c b/arch/arm/mach-ep93xx/mach-dma03.c
+new file mode 100644
+index 0000000..2223f80
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-dma03.c
+@@ -0,0 +1,343 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/mach-dma03.c
++ *  Copyright (C) 2005 Michael Burian
++ *
++ * based on arch/arm/mach-ep93xx/mach-edb9315.c
++ *
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#ifdef CONFIG_SERIAL_8250
++#include <linux/serial_8250.h>
++#endif 
++
++#ifdef CONFIG_PARPORT_PC
++#include <linux/parport.h>
++#endif
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++#ifdef CONFIG_SERIAL_8250
++#include <asm/serial.h>
++#endif
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++#include "ep93xx_gpio_irq.h"
++#endif
++
++
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++   the associated device drivers */
++
++static struct map_desc dma03_io_desc[] __initdata = {
++      {EP93XX_AHB_BASE, __phys_to_pfn(io_v2p(EP93XX_AHB_BASE)), SZ_1M, MT_DEVICE},
++      {EP93XX_APB_BASE, __phys_to_pfn(io_v2p(EP93XX_APB_BASE)), SZ_8M, MT_DEVICE},
++#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_PARPORT_PC)
++      { 0xD0000000, __phys_to_pfn(0x70000000),  SZ_4K,  MT_DEVICE }, /* 2x UARTS, LPT; 16C552 */
++#endif
++};
++
++static void __init dma03_map_io(void)
++{
++      iotable_init(dma03_io_desc, ARRAY_SIZE(dma03_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++      return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++      .map_name = "cfi_probe",
++      .width = 4,
++      .init = flash_init,
++      .exit = flash_exit,
++      .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++      .start = 0x60000000,
++      .end = 0x60000000 + SZ_32M - 1,
++      .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++      .name = "flash",
++      .dev = {
++              .platform_data = &flash_data,
++              },
++      .num_resources = 1,
++      .resource = &cfi_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED     1
++#define LED_STATE_CLAIMED     2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED               2
++#define LED_GREEN     1
++#define LED_MASK      (LED_GREEN | LED_RED)
++
++void dma03_leds_event(led_event_t evt)
++{
++      unsigned long flags;
++
++      local_irq_save(flags);
++
++      switch (evt) {
++      case led_start:
++              led_state = LED_STATE_ENABLED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_stop:
++              led_state &= ~LED_STATE_ENABLED;
++              hw_led_state = 0;
++              break;
++
++      case led_claim:
++              led_state |= LED_STATE_CLAIMED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_release:
++              led_state &= ~LED_STATE_CLAIMED;
++              hw_led_state = 0;
++              break;
++
++      case led_timer:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state ^= LED_GREEN;
++              break;
++
++      case led_idle_start:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      case led_idle_end:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_halted:
++              break;
++
++      case led_green_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_GREEN;
++              break;
++
++      case led_green_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_GREEN;
++              break;
++
++      case led_amber_on:
++              break;
++
++      case led_amber_off:
++              break;
++
++      case led_red_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_red_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      default:
++              break;
++      }
++
++      writel(0x03, GPIO_PEDDR);
++
++      if (led_state & LED_STATE_ENABLED)
++              writel(hw_led_state, GPIO_PEDR);
++
++      local_irq_restore(flags);
++}
++
++#endif
++
++
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++/* GPIO irq description
++ * IRQs are set up in arch/arm/mach-ep93xx/irq.c
++ * flags can be               IRQT_RISING
++ *                    IRQT_FALLING
++ *                    IRQT_LOW
++ *                    IRQT_HIGH
++ *                    IRQT_PROBE
++ *
++ * On IRQT_PROBE nothing is done in setup irq code
++ */
++
++/* For IRQ Demux */
++
++#define DISABLED 0
++#define ENABLED 1
++struct ep93xx_egpio_irq egpio_irqs[] __initdata =
++{
++      /* EGPIO IRQ 0 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 1 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 2 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 3 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 4 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 5 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 6 */
++      { ENABLED, IRQT_HIGH    },      /* OKI ML9620 CAN controller can0 */
++      /* EGPIO IRQ 7 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 8 */
++      { ENABLED, IRQT_HIGH    },      /* 16C552 serial UART 1 */
++      /* EGPIO IRQ 9 */
++      { ENABLED, IRQT_HIGH    },      /* 16C552 serial UART 2 */
++      /* EGPIO IRQ 10 */
++      { ENABLED, IRQT_RISING  },      /* 16C552 parallel port 1 */
++      /* EGPIO IRQ 11 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 12 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 13 */
++      { ENABLED, IRQT_HIGH    },      /* OKI ML9620 CAN controller can1 */
++      /* EGPIO IRQ 14 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 15 */
++      { DISABLED, IRQT_PROBE  },
++};
++#endif
++
++#ifdef CONFIG_SERIAL_8250
++static struct plat_serial8250_port serial_platform_data[] = {
++        {
++              .mapbase        = 0x70000008,
++              .irq            = GPIO_IRQ8,
++              .flags          = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SHARE_IRQ,
++              .iotype         = UPIO_MEM,
++              .regshift       = 0,
++              .uartclk        = BASE_BAUD*16,
++         } , {
++              .mapbase        = 0x70000010,
++              .irq            = GPIO_IRQ9,
++              .flags          = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SHARE_IRQ,
++              .iotype         = UPIO_MEM,
++              .regshift       = 0,
++              .uartclk        = BASE_BAUD*16,
++        }, { },
++};
++
++static struct platform_device serial_device = {
++      .name = "serial8250",
++      .id = PLAT8250_DEV_PLATFORM,
++      .dev = {
++              .platform_data  = serial_platform_data,
++      },
++};
++#endif
++
++static struct platform_device *devices[] __initdata = {
++      &cfi_flash_device,
++#ifdef CONFIG_SERIAL_8250
++      &serial_device,
++#endif
++};
++
++static void __init dma03_init(void)
++{
++      struct parport *port;
++      physmap_configure(0x60000000, 0x02000000, 4, NULL);
++      platform_add_devices(devices, ARRAY_SIZE(devices));
++
++#ifdef CONFIG_PARPORT_PC
++      port = parport_pc_probe_port(0xD0000020, 0, GPIO_IRQ10, 0, NULL);
++// How to register that beast without crashing?
++//    if(port)
++//            port = parport_register_port(0xD0000020, GPIO_IRQ10, 0, NULL); // note that passing NULL as fops arg is a bad idea(tm)
++//    if(port)
++//            parport_announce_port(port);
++#endif
++
++#ifdef CONFIG_LEDS
++      leds_event = dma03_leds_event;
++#endif
++      leds_event(led_start);
++}
++
++MACHINE_START(DMA03, "dma03")
++      /* Maintainer: Michael Burian */
++      .phys_ram       = SDRAM_START,
++      .phys_io        = 0x80000000,
++      .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
++      .boot_params    = (SDRAM_START + 0x00000100),
++
++      .map_io         = dma03_map_io,
++      .init_irq       = ep93xx_init_irq,
++      .init_machine   = dma03_init,
++      .timer          = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-edb9301.c b/arch/arm/mach-ep93xx/mach-edb9301.c
+new file mode 100644
+index 0000000..68004e2
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-edb9301.c
+@@ -0,0 +1,219 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/edb9301.c
++ *
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++   the associated device drivers */
++
++static struct map_desc edb9301_io_desc[] __initdata = {
++      { EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
++      { EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
++};
++
++static void __init edb9301_map_io(void)
++{
++      iotable_init(edb9301_io_desc, ARRAY_SIZE(edb9301_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++      return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++      .map_name = "cfi_probe",
++      .width = 2,
++      .init = flash_init,
++      .exit = flash_exit,
++      .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++      .start = 0x60000000,
++      .end = 0x60000000 + SZ_16M - 1,
++      .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++      .name = "flash",
++      .dev = {
++              .platform_data = &flash_data,
++              },
++      .num_resources = 1,
++      .resource = &cfi_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED     1
++#define LED_STATE_CLAIMED     2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED               2
++#define LED_GREEN     1
++#define LED_MASK      (LED_GREEN | LED_RED)
++
++void edb9301_leds_event(led_event_t evt)
++{
++      unsigned long flags;
++
++      local_irq_save(flags);
++
++      switch (evt) {
++      case led_start:
++              led_state = LED_STATE_ENABLED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_stop:
++              led_state &= ~LED_STATE_ENABLED;
++              hw_led_state = 0;
++              break;
++
++      case led_claim:
++              led_state |= LED_STATE_CLAIMED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_release:
++              led_state &= ~LED_STATE_CLAIMED;
++              hw_led_state = 0;
++              break;
++
++      case led_timer:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state ^= LED_GREEN;
++              break;
++
++      case led_idle_start:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      case led_idle_end:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_halted:
++              break;
++
++      case led_green_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_GREEN;
++              break;
++
++      case led_green_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_GREEN;
++              break;
++
++      case led_amber_on:
++              break;
++
++      case led_amber_off:
++              break;
++
++      case led_red_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_red_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      default:
++              break;
++      }
++
++      writel(0x03, GPIO_PEDDR);
++
++      if (led_state & LED_STATE_ENABLED)
++              writel(hw_led_state, GPIO_PEDR);
++
++      local_irq_restore(flags);
++}
++
++#endif
++
++static void __init edb9301_init(void)
++{
++      physmap_configure(0x60000000, 0x01000000, 2, NULL);
++      platform_device_register(&cfi_flash_device);
++#ifdef CONFIG_LEDS
++      leds_event = edb9301_leds_event;
++#endif
++      leds_event(led_start);
++}
++
++MACHINE_START(EDB9301, "edb9301")
++      /* Maintainer: Michael Burian */
++      .phys_ram       = SDRAM_START,
++      .phys_io        = 0x80000000,
++      .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
++      .boot_params    = (SDRAM_START + 0x00000100),
++
++      .map_io         = edb9301_map_io,
++      .init_irq       = ep93xx_init_irq,
++      .init_machine   = edb9301_init,
++      .timer          = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-edb9302.c b/arch/arm/mach-ep93xx/mach-edb9302.c
+new file mode 100644
+index 0000000..ac74a1e
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-edb9302.c
+@@ -0,0 +1,362 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/edb9302.c
++ *
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++#include <asm/arch/mach-edb9302.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++   the associated device drivers */
++
++static struct map_desc edb9302_io_desc[] __initdata = {
++      { EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
++      { EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
++};
++
++static void __init edb9302_map_io(void)
++{
++      iotable_init(edb9302_io_desc, ARRAY_SIZE(edb9302_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++      return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++      .map_name = "cfi_probe",
++      .width = 2,
++      .init = flash_init,
++      .exit = flash_exit,
++      .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++      .start = 0x60000000,
++      .end = 0x60000000 + SZ_16M - 1,
++      .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++      .name = "flash",
++      .dev = {
++              .platform_data = &flash_data,
++              },
++      .num_resources = 1,
++      .resource = &cfi_flash_resource,
++};
++
++/* SSP hackery */
++
++static void ssp_cs_flash(struct ssp_slave *s, int enable)
++{
++      unsigned long x = readl(GPIO_PADR);
++      if (enable)
++              x &= ~0x80;
++      else
++              x |= 0x80;
++      writel(x, GPIO_PADR);
++}
++
++struct ep93xx_ssp_slave ep93xx_ssp_flash = {
++      {
++       LIST_HEAD_INIT(ep93xx_ssp_flash.slave.list),
++       NULL,
++       0,
++       0,
++       8,
++       1,
++       ssp_cs_flash},
++      ((0 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_MOTOROLA << SSPCR0_FRF_SHIFT) |
++       SSPCR0_SPO | SSPCR0_SPH | (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)),
++      (SSPC1_SSE | SSPC1_RORIE),
++      2
++};
++
++EXPORT_SYMBOL(ep93xx_ssp_flash);
++
++static void ssp_cs_codec(struct ssp_slave *s, int enable)
++{
++      unsigned long x = readl(GPIO_PADR);
++      if (enable)
++              x &= ~0x40;
++      else
++              x |= 0x40;
++      writel(x, GPIO_PADR);
++}
++
++struct ep93xx_ssp_slave ep93xx_ssp_codec = {
++      {
++       LIST_HEAD_INIT(ep93xx_ssp_codec.slave.list),
++       NULL,
++       0,
++       0,
++       8,
++       1,
++       ssp_cs_codec},
++      ((31 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_TI << SSPCR0_FRF_SHIFT) |
++       (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)),
++      (SSPC1_SSE | SSPC1_RORIE),
++      48
++};
++
++EXPORT_SYMBOL(ep93xx_ssp_codec);
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED     1
++#define LED_STATE_CLAIMED     2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED               2
++#define LED_GREEN     1
++#define LED_MASK      (LED_GREEN | LED_RED)
++
++void edb9302_leds_event(led_event_t evt)
++{
++      unsigned long flags;
++
++      local_irq_save(flags);
++
++      switch (evt) {
++      case led_start:
++              led_state = LED_STATE_ENABLED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_stop:
++              led_state &= ~LED_STATE_ENABLED;
++              hw_led_state = 0;
++              break;
++
++      case led_claim:
++              led_state |= LED_STATE_CLAIMED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_release:
++              led_state &= ~LED_STATE_CLAIMED;
++              hw_led_state = 0;
++              break;
++
++      case led_timer:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state ^= LED_GREEN;
++              break;
++
++      case led_idle_start:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      case led_idle_end:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_halted:
++              break;
++
++      case led_green_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_GREEN;
++              break;
++
++      case led_green_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_GREEN;
++              break;
++
++      case led_amber_on:
++              break;
++
++      case led_amber_off:
++              break;
++
++      case led_red_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_red_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      default:
++              break;
++      }
++
++      writel(0x03, GPIO_PEDDR);
++
++      if (led_state & LED_STATE_ENABLED)
++              writel(hw_led_state, GPIO_PEDR);
++
++      local_irq_restore(flags);
++}
++
++#endif
++
++static void __init edb9302_init_gpio(void)
++{
++      /* port A */
++      /* EGPIO0-7 */
++      writel(0xc2, GPIO_PADDR);
++      writel(0xc0, GPIO_PADR);
++
++      /* port B */
++      /* EGPIO8-15 */
++      writel(0x00, GPIO_PBDDR);
++      writel(0x00, GPIO_PBDR);
++
++      /* port C */
++      /* GPIO0 */
++      writel(0x00, GPIO_PCDDR);
++      writel(0x00, GPIO_PCDR);
++
++      /* port E */
++      /* RDLED, GRLED */
++      writel(0x03, GPIO_PEDDR);
++      writel(0x03, GPIO_PEDR);
++
++      /* port F */
++      /* GPIO5, GPIO6, GPIO7 */
++      writel(0x00, GPIO_PFDDR);
++      writel(0x00, GPIO_PFDR);
++
++      /* port G */
++      /* EECLK, EEDAT */
++      writel(0x00, GPIO_PGDDR);
++      writel(0x00, GPIO_PGDR);
++
++      /* port H */
++      /* GPIO1, GPIO2, GPIO3, GPIO4 */
++      writel(0x00, GPIO_PHDDR);
++      writel(0x00, GPIO_PHDR);
++}
++
++/* looks like this might be more generic than just edb9302... */
++int ssp_do_asymmetric(struct ep93xx_ssp_slave *ss, void *tx, int tlen, void *rx,
++                    int rlen)
++{
++      struct ssp_slave *s = (struct ssp_slave *)ss;
++      int err;
++
++      if ((err = ssp_start(s)) < 0)
++              goto out1;
++
++      ssp_select(s);
++
++      if ((err = ssp_post(s, tlen, tx, NULL)) < 0)
++              goto out2;
++
++      ssp_wait(s);
++
++      if ((err = ssp_post(s, rlen, NULL, rx)) < 0)
++              goto out2;
++
++      ssp_wait(s);
++
++      out2:
++      ssp_deselect(s);
++      ssp_finish(s);
++      out1:
++      return err;
++}
++
++/* start poking at the Atmel AT25F1024 flash chip */
++void poke_flash(void)
++{
++      unsigned char rdsr[1] = { 0x05 };
++      unsigned char rdid[1] = { 0x15 };
++      unsigned char rsp[10];
++
++      ssp_do_asymmetric(&ep93xx_ssp_flash, rdsr, 1, rsp, 1);
++      printk(KERN_WARNING "RDSR returns %02x\n", rsp[0]);
++
++      ssp_do_asymmetric(&ep93xx_ssp_flash, rdid, 1, rsp, 2);
++      printk(KERN_WARNING "RDID returns %02x:%02x\n", rsp[0], rsp[1]);
++}
++
++static void __init edb9302_init(void)
++{
++      physmap_configure(0x60000000, 0x01000000, 2, NULL);
++      platform_device_register(&cfi_flash_device);
++      edb9302_init_gpio();
++#ifdef CONFIG_LEDS
++      leds_event = edb9302_leds_event;
++#endif
++      leds_event(led_start);
++      if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_flash.slave) < 0)
++              printk(KERN_ERR "EDB9302: unable to add flash slave\n");
++      if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_codec.slave) < 0)
++              printk(KERN_ERR "EDB9302: unable to add codec slave\n");
++}
++
++MACHINE_START(EDB9302, "edb9302")
++      /* Maintainer: Michael Burian */
++      .phys_ram       = SDRAM_START,
++      .phys_io        = 0x80000000,
++      .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
++      .boot_params    = (SDRAM_START + 0x00000100),
++
++      .map_io         = edb9302_map_io,
++      .init_irq       = ep93xx_init_irq,
++      .init_machine   = edb9302_init,
++      .timer          = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-edb9312.c b/arch/arm/mach-ep93xx/mach-edb9312.c
+new file mode 100644
+index 0000000..e67b673
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-edb9312.c
+@@ -0,0 +1,219 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/edb9312.c
++ *
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++   the associated device drivers */
++
++static struct map_desc edb9312_io_desc[] __initdata = {
++      { EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
++      { EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
++};
++
++static void __init edb9312_map_io(void)
++{
++      iotable_init(edb9312_io_desc, ARRAY_SIZE(edb9312_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++      return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++      .map_name = "cfi_probe",
++      .width = 4,
++      .init = flash_init,
++      .exit = flash_exit,
++      .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++      .start = 0x60000000,
++      .end = 0x60000000 + SZ_32M - 1,
++      .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++      .name = "flash",
++      .dev = {
++              .platform_data = &flash_data,
++              },
++      .num_resources = 1,
++      .resource = &cfi_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED     1
++#define LED_STATE_CLAIMED     2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED               2
++#define LED_GREEN     1
++#define LED_MASK      (LED_GREEN | LED_RED)
++
++void edb9312_leds_event(led_event_t evt)
++{
++      unsigned long flags;
++
++      local_irq_save(flags);
++
++      switch (evt) {
++      case led_start:
++              led_state = LED_STATE_ENABLED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_stop:
++              led_state &= ~LED_STATE_ENABLED;
++              hw_led_state = 0;
++              break;
++
++      case led_claim:
++              led_state |= LED_STATE_CLAIMED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_release:
++              led_state &= ~LED_STATE_CLAIMED;
++              hw_led_state = 0;
++              break;
++
++      case led_timer:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state ^= LED_GREEN;
++              break;
++
++      case led_idle_start:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      case led_idle_end:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_halted:
++              break;
++
++      case led_green_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_GREEN;
++              break;
++
++      case led_green_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_GREEN;
++              break;
++
++      case led_amber_on:
++              break;
++
++      case led_amber_off:
++              break;
++
++      case led_red_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_red_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      default:
++              break;
++      }
++
++      writel(0x03, GPIO_PEDDR);
++
++      if (led_state & LED_STATE_ENABLED)
++              writel(hw_led_state, GPIO_PEDR);
++
++      local_irq_restore(flags);
++}
++
++#endif
++
++static void __init edb9312_init(void)
++{
++      physmap_configure(0x60000000, 0x02000000, 4, NULL);
++      platform_device_register(&cfi_flash_device);
++#ifdef CONFIG_LEDS
++      leds_event = edb9312_leds_event;
++#endif
++      leds_event(led_start);
++}
++
++MACHINE_START(EDB9312, "edb9312")
++      /* Maintainer: Michael Burian */
++      .phys_ram       = SDRAM_START,
++      .phys_io        = 0x80000000,
++      .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
++      .boot_params    = (SDRAM_START + 0x00000100),
++
++      .map_io         = edb9312_map_io,
++      .init_irq       = ep93xx_init_irq,
++      .init_machine   = edb9312_init,
++      .timer          = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-edb9315.c b/arch/arm/mach-ep93xx/mach-edb9315.c
+new file mode 100644
+index 0000000..14c680a
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-edb9315.c
+@@ -0,0 +1,219 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/edb9315.c
++ *
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++   the associated device drivers */
++
++static struct map_desc edb9315_io_desc[] __initdata = {
++      { EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
++      { EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
++};
++
++static void __init edb9315_map_io(void)
++{
++      iotable_init(edb9315_io_desc, ARRAY_SIZE(edb9315_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++      return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++      .map_name = "cfi_probe",
++      .width = 4,
++      .init = flash_init,
++      .exit = flash_exit,
++      .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++      .start = 0x60000000,
++      .end = 0x60000000 + SZ_32M - 1,
++      .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++      .name = "flash",
++      .dev = {
++              .platform_data = &flash_data,
++              },
++      .num_resources = 1,
++      .resource = &cfi_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED     1
++#define LED_STATE_CLAIMED     2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED               2
++#define LED_GREEN     1
++#define LED_MASK      (LED_GREEN | LED_RED)
++
++void edb9315_leds_event(led_event_t evt)
++{
++      unsigned long flags;
++
++      local_irq_save(flags);
++
++      switch (evt) {
++      case led_start:
++              led_state = LED_STATE_ENABLED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_stop:
++              led_state &= ~LED_STATE_ENABLED;
++              hw_led_state = 0;
++              break;
++
++      case led_claim:
++              led_state |= LED_STATE_CLAIMED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_release:
++              led_state &= ~LED_STATE_CLAIMED;
++              hw_led_state = 0;
++              break;
++
++      case led_timer:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state ^= LED_GREEN;
++              break;
++
++      case led_idle_start:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      case led_idle_end:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_halted:
++              break;
++
++      case led_green_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_GREEN;
++              break;
++
++      case led_green_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_GREEN;
++              break;
++
++      case led_amber_on:
++              break;
++
++      case led_amber_off:
++              break;
++
++      case led_red_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_red_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      default:
++              break;
++      }
++
++      writel(0x03, GPIO_PEDDR);
++
++      if (led_state & LED_STATE_ENABLED)
++              writel(hw_led_state, GPIO_PEDR);
++
++      local_irq_restore(flags);
++}
++
++#endif
++
++static void __init edb9315_init(void)
++{
++      physmap_configure(0x60000000, 0x02000000, 4, NULL);
++      platform_device_register(&cfi_flash_device);
++#ifdef CONFIG_LEDS
++      leds_event = edb9315_leds_event;
++#endif
++      leds_event(led_start);
++}
++
++MACHINE_START(EDB9315, "edb9315")
++      /* Maintainer: Michael Burian */
++      .phys_ram       = SDRAM_START,
++      .phys_io        = 0x80000000,
++      .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
++      .boot_params    = (SDRAM_START + 0x00000100),
++
++      .map_io         = edb9315_map_io,
++      .init_irq       = ep93xx_init_irq,
++      .init_machine   = edb9315_init,
++      .timer          = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-ttml.c b/arch/arm/mach-ep93xx/mach-ttml.c
+new file mode 100644
+index 0000000..872dd01
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-ttml.c
+@@ -0,0 +1,369 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/mach-ttml.c
++ *
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++#include <asm/arch/mach-ttml.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++   the associated device drivers */
++
++static struct map_desc ttml_io_desc[] __initdata = {
++      { EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
++      { EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
++};
++
++static void __init ttml_map_io(void)
++{
++      iotable_init(ttml_io_desc, ARRAY_SIZE(ttml_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++      return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++      .map_name = "cfi_probe",
++      .width = 2,
++      .init = flash_init,
++      .exit = flash_exit,
++      .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++      .start = 0x60000000,
++      .end = 0x60000000 + SZ_16M - 1,
++      .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++      .name = "flash",
++      .dev = {
++              .platform_data = &flash_data,
++              },
++      .num_resources = 1,
++      .resource = &cfi_flash_resource,
++};
++
++/* SSP hackery */
++
++static void ssp_cs_timicro(struct ssp_slave *s, int enable)
++{
++      unsigned long x = readl(GPIO_PBDR);
++      if (enable)
++              x &= ~0x10;
++      else
++              x |= 0x10;
++      writel(x, GPIO_PBDR);
++}
++
++struct ep93xx_ssp_slave ep93xx_ssp_micro = {
++      {
++       LIST_HEAD_INIT(ep93xx_ssp_micro.slave.list),
++       NULL,
++       0,
++       0,
++       8,
++       1,
++       ssp_cs_timicro},
++      ((31 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_TI << SSPCR0_FRF_SHIFT) |
++       (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)),
++      (SSPC1_SSE | SSPC1_RORIE),
++      48
++};
++
++EXPORT_SYMBOL(ep93xx_ssp_micro);
++
++static void ssp_cs_expansion(struct ssp_slave *s, int enable)
++{
++      unsigned long x = readl(GPIO_PBDR);
++      if (enable)
++              x &= ~0x20;
++      else
++              x |= 0x20;
++      writel(x, GPIO_PBDR);
++}
++
++struct ep93xx_ssp_slave ep93xx_ssp_expansion = {
++      {
++       LIST_HEAD_INIT(ep93xx_ssp_expansion.slave.list),
++       NULL,
++       0,
++       0,
++       8,
++       1,
++       ssp_cs_expansion},
++      0,
++      0,
++      0
++};
++
++EXPORT_SYMBOL(ep93xx_ssp_expansion);
++
++/**
++ * ssp_do_ttml - perform a single SSP transaction to the TTML micro
++ * @s: the slave
++ * @len: the number of words to transfer
++ * @tx: a buffer of @len words to clock out to slave
++ * @rx: a buffer of @len words to clock in from slave
++ *
++ * Use the SSP transaction interface to drive the TTML micro. The
++ * first byte back from the micro is the length of the reply, excluding
++ * the len and the csum bytes. @rlen and @rx had better be bigger
++ * than any reply the micro might generate.
++ */
++int ssp_do_ttml(struct ep93xx_ssp_slave *ss, void *tx, int tlen, void *rx,
++              int rlen)
++{
++      struct ssp_slave *s = (struct ssp_slave *)ss;
++      int len;
++      int err;
++
++      if ((err = ssp_start(s)) < 0)
++              goto out1;
++
++      ssp_select(s);
++
++      if ((err = ssp_post(s, tlen, tx, NULL)) < 0)
++              goto out2;
++
++      ssp_wait(s);
++
++      if ((err = ssp_post(s, 1, NULL, rx)) < 0)
++              goto out2;
++
++      ssp_wait(s);
++
++      {
++              char *b = rx;
++              len = ((b[0] >> 4) & 0x07) + 2;
++      }
++
++      if (len > rlen) {
++              printk(KERN_WARNING "SSP: rx buffer truncated\n");
++              len = rlen;
++      }
++
++      if ((err = ssp_post(s, len - 1, NULL, rx + 1)) < 0)
++              goto out2;
++
++      err = ssp_wait(s);
++
++      out2:
++      ssp_deselect(s);
++      out1:
++      ssp_finish(s);
++      return err;
++}
++
++EXPORT_SYMBOL(ssp_do_ttml);
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED     1
++#define LED_STATE_CLAIMED     2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED               2
++#define LED_GREEN     1
++#define LED_MASK      (LED_GREEN | LED_RED)
++
++void ttml_leds_event(led_event_t evt)
++{
++      unsigned long flags;
++
++      local_irq_save(flags);
++
++      switch (evt) {
++      case led_start:
++              led_state = LED_STATE_ENABLED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_stop:
++              led_state &= ~LED_STATE_ENABLED;
++              hw_led_state = 0;
++              break;
++
++      case led_claim:
++              led_state |= LED_STATE_CLAIMED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_release:
++              led_state &= ~LED_STATE_CLAIMED;
++              hw_led_state = 0;
++              break;
++
++      case led_timer:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state ^= LED_GREEN;
++              break;
++
++      case led_idle_start:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      case led_idle_end:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_halted:
++              break;
++
++      case led_green_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_GREEN;
++              break;
++
++      case led_green_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_GREEN;
++              break;
++
++      case led_amber_on:
++              break;
++
++      case led_amber_off:
++              break;
++
++      case led_red_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_red_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      default:
++              break;
++      }
++
++      writel(0x03, GPIO_PEDDR);
++
++      if (led_state & LED_STATE_ENABLED)
++              writel(hw_led_state, GPIO_PEDR);
++
++      local_irq_restore(flags);
++}
++
++#endif
++
++static void __init ttml_init_gpio(void)
++{
++      /* port A */
++      writel(0x00, GPIO_PADDR);
++
++      /* port B */
++      writel(0xf1, GPIO_PBDDR);
++      writel(0xf1, GPIO_PBDR);
++
++      /* port C */
++      writel(0x01, GPIO_PCDDR);
++      writel(0x01, GPIO_PCDR);
++
++      /* port E */
++      writel(0x03, GPIO_PEDDR);
++      writel(0x03, GPIO_PEDR);
++
++      /* port F */
++      writel(0x00, GPIO_PFDDR);
++      writel(0x00, GPIO_PFDR);
++
++      /* port G */
++      writel(0x00, GPIO_PGDDR);
++      writel(0x00, GPIO_PGDR);
++
++      /* port H */
++      writel(0x04, GPIO_PHDDR);
++      writel(0x00, GPIO_PHDR);
++}
++
++static void __init ttml_init(void)
++{
++      physmap_configure(0x60000000, 0x01000000, 2, NULL);
++      platform_device_register(&cfi_flash_device);
++      ttml_init_gpio();
++#ifdef CONFIG_LEDS
++      leds_event = ttml_leds_event;
++#endif
++      leds_event(led_start);
++
++      if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_micro.slave) < 0)
++              printk(KERN_ERR "EP93XX: unable to add micro slave\n");
++
++      if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_expansion.slave) < 0)
++              printk(KERN_ERR "EP93XX: unable to add expansion slave\n");
++
++}
++
++MACHINE_START(EDB9301, "ttml")
++      /* Maintainer: Michael Burian */
++      .phys_ram       = SDRAM_START,
++      .phys_io        = 0x80000000,
++      .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
++      .boot_params    = (SDRAM_START + 0x00000100),
++
++      .map_io         = ttml_map_io,
++      .init_irq       = ep93xx_init_irq,
++      .init_machine   = ttml_init,
++      .timer          = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-zefeerdzb.c b/arch/arm/mach-ep93xx/mach-zefeerdzb.c
+new file mode 100644
+index 0000000..c224ca1
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-zefeerdzb.c
+@@ -0,0 +1,237 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/zefeerdzb.c
++ *
++ *  Copyright (C) 2004, 2005 DAVE Srl <www.dave-tech.it>
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++   the associated device drivers */
++
++static struct map_desc zefeerdzb_io_desc[] __initdata = {
++      { EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
++      { EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
++};
++
++static void __init zefeerdzb_map_io(void)
++{
++      iotable_init(zefeerdzb_io_desc, ARRAY_SIZE(zefeerdzb_io_desc));
++}
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED     1
++#define LED_STATE_CLAIMED     2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED               2
++#define LED_GREEN     1
++#define LED_MASK      (LED_GREEN | LED_RED)
++
++void zefeerdzb_leds_event(led_event_t evt)
++{
++      unsigned long flags;
++
++      local_irq_save(flags);
++
++      switch (evt) {
++      case led_start:
++              led_state = LED_STATE_ENABLED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_stop:
++              led_state &= ~LED_STATE_ENABLED;
++              hw_led_state = 0;
++              break;
++
++      case led_claim:
++              led_state |= LED_STATE_CLAIMED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_release:
++              led_state &= ~LED_STATE_CLAIMED;
++              hw_led_state = 0;
++              break;
++
++      case led_timer:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state ^= LED_GREEN;
++              break;
++
++      case led_idle_start:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      case led_idle_end:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_halted:
++              break;
++
++      case led_green_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_GREEN;
++              break;
++
++      case led_green_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_GREEN;
++              break;
++
++      case led_amber_on:
++              break;
++
++      case led_amber_off:
++              break;
++
++      case led_red_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_red_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      default:
++              break;
++      }
++
++      writel(0x03, GPIO_PEDDR);
++
++      if (led_state & LED_STATE_ENABLED)
++              writel(hw_led_state, GPIO_PEDR);
++
++      local_irq_restore(flags);
++}
++
++#endif
++
++static void __init zefeerdzb_init(void)
++{
++      /*
++         physmap_configure(0x60000000, 0x01000000, 2, NULL);
++         platform_device_register(&cfi_flash_device);
++       */
++
++#ifdef CONFIG_LEDS
++      leds_event = zefeerdzb_leds_event;
++#endif
++      leds_event(led_start);
++}
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++#include "ep93xx_gpio_irq.h"
++#endif
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++/* GPIO irq description
++ * IRQs are set up in arch/arm/mach-ep93xx/irq.c
++ * flags can be               IRQT_RISING
++ *                    IRQT_FALLING
++ *                    IRQT_LOW
++ *                    IRQT_HIGH
++ *                    IRQT_PROBE
++ *
++ * On IRQT_PROBE nothing is done in setup irq code
++ */
++
++/* For IRQ Demux */
++
++#define DISABLED 0
++#define ENABLED 1
++struct ep93xx_egpio_irq egpio_irqs[] __initdata =
++{
++      /* EGPIO IRQ 0 */
++      { DISABLED , IRQT_PROBE },
++      /* EGPIO IRQ 1 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 2 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 3 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 4 */
++      { ENABLED, IRQT_LOW     },      /* CAN 0 GPIO IRQ */
++      /* EGPIO IRQ 5 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 6 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 7 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 8 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 9 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 10 */
++      { ENABLED, IRQT_LOW     },      /* CAN 1 GPIO IRQ */
++      /* EGPIO IRQ 11 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 12 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 13 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 14 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 15 */
++      { DISABLED, IRQT_PROBE  },
++};
++#endif
++
++MACHINE_START(ZEFEERDZB, "Zefeer DZB")
++      /* Maintainer: DAVE Srl <www.dave-tech.it> */
++      .phys_ram       = SDRAM_START,
++      .phys_io        = 0x80000000,
++      .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
++      .boot_params    = (SDRAM_START + 0x00000100),
++
++      .map_io         = zefeerdzb_map_io,
++      .init_irq       = ep93xx_init_irq,
++      .init_machine   = zefeerdzb_init,
++      .timer          = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-zefeerdzq.c b/arch/arm/mach-ep93xx/mach-zefeerdzq.c
+new file mode 100644
+index 0000000..4cae7a7
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-zefeerdzq.c
+@@ -0,0 +1,279 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/zefeerdzq.c
++ *
++ *  Copyright (C) 2004, 2005 DAVE Srl <www.dave-tech.it>
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++   the associated device drivers */
++
++static struct map_desc zefeerdzq_io_desc[] __initdata = {
++      { EP93XX_AHB_BASE,  io_v2p(EP93XX_AHB_BASE),  SZ_1M,  MT_DEVICE },
++      { EP93XX_APB_BASE,  io_v2p(EP93XX_APB_BASE),  SZ_8M,  MT_DEVICE },
++};
++
++static void __init zefeerdzq_map_io(void)
++{
++      iotable_init(zefeerdzq_io_desc, ARRAY_SIZE(zefeerdzq_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++/*
++static int flash_init(void)
++{
++      return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++      .map_name       = "cfi_probe",
++      .width          = 4,
++      .init           = flash_init,
++      .exit           = flash_exit,
++      .set_vpp        = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++      .start          = 0x60000000,
++      .end            = 0x60000000 + SZ_32M - 1,
++      .flags          = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++      .name           = "ZefeerDZQ Boot Flash",
++      .dev            = {
++                          .platform_data      = &flash_data,
++                        },
++      .num_resources  = 1,
++      .resource       = &cfi_flash_resource,
++};
++*/
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED     1
++#define LED_STATE_CLAIMED     2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED               2
++#define LED_GREEN     1
++#define LED_MASK      (LED_GREEN | LED_RED)
++
++void zefeerdzq_leds_event(led_event_t evt)
++{
++      unsigned long flags;
++
++      local_irq_save(flags);
++
++      switch (evt) {
++      case led_start:
++              led_state = LED_STATE_ENABLED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_stop:
++              led_state &= ~LED_STATE_ENABLED;
++              hw_led_state = 0;
++              break;
++
++      case led_claim:
++              led_state |= LED_STATE_CLAIMED;
++              hw_led_state = LED_RED | LED_GREEN;
++              break;
++
++      case led_release:
++              led_state &= ~LED_STATE_CLAIMED;
++              hw_led_state = 0;
++              break;
++
++      case led_timer:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state ^= LED_GREEN;
++              break;
++
++      case led_idle_start:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      case led_idle_end:
++              if (!(led_state & LED_STATE_CLAIMED))
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_halted:
++              break;
++
++      case led_green_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_GREEN;
++              break;
++
++      case led_green_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_GREEN;
++              break;
++
++      case led_amber_on:
++              break;
++
++      case led_amber_off:
++              break;
++
++      case led_red_on:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state |= LED_RED;
++              break;
++
++      case led_red_off:
++              if (led_state & LED_STATE_CLAIMED)
++                      hw_led_state &= ~LED_RED;
++              break;
++
++      default:
++              break;
++      }
++
++      writel(0x03, GPIO_PEDDR);
++
++      if (led_state & LED_STATE_ENABLED)
++              writel(hw_led_state, GPIO_PEDR);
++
++      local_irq_restore(flags);
++}
++
++#endif
++
++static void __init zefeerdzq_init(void)
++{
++      /*
++         physmap_configure(0x60000000, 0x01000000, 2, NULL);
++         platform_device_register(&cfi_flash_device);
++       */
++
++#ifdef CONFIG_LEDS
++      leds_event = zefeerdzq_leds_event;
++#endif
++      leds_event(led_start);
++}
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++#include "ep93xx_gpio_irq.h"
++#endif
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++/* GPIO irq description
++ * IRQs are set up in arch/arm/mach-ep93xx/irq.c
++ * flags can be               IRQT_RISING
++ *                    IRQT_FALLING
++ *                    IRQT_LOW
++ *                    IRQT_HIGH
++ *                    IRQT_PROBE
++ *
++ * On IRQT_PROBE nothing is done in setup irq code
++ */
++
++/* For IRQ Demux */
++
++#define DISABLED 0
++#define ENABLED 1
++struct ep93xx_egpio_irq egpio_irqs[] __initdata =
++{
++      /* EGPIO IRQ 0 */
++      { DISABLED , IRQT_PROBE },
++      /* EGPIO IRQ 1 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 2 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 3 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 4 */
++      { ENABLED, IRQT_LOW     },      /* CAN 0 GPIO IRQ */
++      /* EGPIO IRQ 5 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 6 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 7 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 8 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 9 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 10 */
++      { ENABLED, IRQT_LOW     },      /* CAN 1 GPIO IRQ */
++      /* EGPIO IRQ 11 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 12 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 13 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 14 */
++      { DISABLED, IRQT_PROBE  },
++      /* EGPIO IRQ 15 */
++      { DISABLED, IRQT_PROBE  },
++};
++#endif
++
++MACHINE_START(ZEFEERDZQ, "Zefeer DZQ")
++      /* Maintainer: DAVE Srl <www.dave-tech.it> */
++      .phys_ram       = SDRAM_START,
++      .phys_io        = 0x80000000,
++      .io_pg_offst    = ((0xe0000000) >> 18) & 0xfffc,
++      .boot_params    = (SDRAM_START + 0x00000100),
++
++      .map_io         = zefeerdzq_map_io,
++      .init_irq       = ep93xx_init_irq,
++      .init_machine   = zefeerdzq_init,
++      .timer          = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/ssp-cirrus.c b/arch/arm/mach-ep93xx/ssp-cirrus.c
+new file mode 100644
+index 0000000..853c6c4
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/ssp-cirrus.c
+@@ -0,0 +1,646 @@
++/*
++ *  FILE:                     ssp.c
++ *
++ *  DESCRIPTION:      SSP Interface Driver Module implementation
++ *
++ *  Copyright Cirrus Logic Corporation, 2001-2003.  All rights reserved
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/*
++ *  This driver provides a way to read and write devices on the SSP
++ *  interface.
++ *
++ *  For Tx devices, EGPIO7 is used as an address pin:
++ *  I2S Codec CS4228        = EGPIO7 == 1
++ *  Serial Flash AT25F1024  = EGPIO7 == 0
++ */
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++
++#include <asm/irq.h>
++#include <asm/semaphore.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/ssp-cirrus.h>
++
++#undef DEBUG
++/* #define DEBUG 1 */
++#ifdef DEBUG
++#define DPRINTK( x... )  printk( ##x )
++#else
++#define DPRINTK( x... )
++#endif
++
++#define EP93XX_KEY_TIMER_PERIOD_MSEC 20
++
++static int SSP_Open(enum SSPDeviceType Device, SSPDataCallback Callback);
++static int SSP_Close(int Handle);
++static int SSP_Read(int Handle, unsigned int Addr, unsigned int *pValue);
++static int SSP_Write(int Handle, unsigned int Addr, unsigned int Value);
++static int CheckHandle(int Handle);
++
++static void SetSSPtoPS2(void);
++static void SetSSPtoI2S(void);
++static int ReadIntoBuffer(void);
++
++static int SSP_Write_I2SCodec(int Handle, unsigned int RegAddr,
++                            unsigned int RegValue);
++
++/*
++ * Key buffer...
++ */
++#define KEYBUF_SIZE 256
++static unsigned int uiKeyBuffer[KEYBUF_SIZE];
++
++static spinlock_t ssp_spinlock = SPIN_LOCK_UNLOCKED;
++
++enum SSPmodes {
++      SSP_MODE_UNKNOWN = 0,
++      SSP_MODE_PS2,
++      SSP_MODE_I2S,
++      SSP_MODE_FLASH,
++};
++
++static struct timer_list g_KbdTimer;
++static enum SSPmodes gSSPmode = SSP_MODE_UNKNOWN;
++static SSPDataCallback gKeyCallback = NULL;
++static int gHookedInterrupt = 0;
++
++/*
++ * Keep the last valid handle for SSP for kbd, i2s, and flash
++ */
++static int iLastValidHandle = -1;
++static int KeyboardHandle = 0;
++static int I2SHandle = 0;
++static int FlashHandle = 0;
++
++#define SSP_DEVICE_MASK    0xf0000000
++#define SSP_DEVICE_SHIFT       28
++
++SSP_DRIVER_API SSPinstance = {
++      SSP_Open,
++      SSP_Read,
++      SSP_Write,
++      SSP_Close,
++};
++
++/*
++ * The only instance of this driver.
++ */
++SSP_DRIVER_API *SSPDriver = &SSPinstance;
++
++/**
++ * SSPIrqHandler - get all of the keys out of the SPI FIFO.
++ */
++irqreturn_t SSPIrqHandler(int irq, void *dev_id, struct pt_regs *regs)
++{
++      /*
++       * Get key codes from SSP and send them to the keyboard callback.
++       */
++      ReadIntoBuffer();
++
++      /*
++       * Clear the interrupt.
++       */
++      writel(0, SSPIIR);
++      return IRQ_HANDLED;
++}
++
++/**
++ * TimerRoutine
++ *
++ * This function is called periodically to make sure that no keys are stuck in
++ * the SPI FIFO.  This is necessary because the SPI only interrupts on half
++ * full FIFO which can leave up to one keyboard event in the FIFO until another
++ * key is pressed.
++ */
++static void TimerRoutine(unsigned long Data)
++{
++      int keycount;
++
++      /*
++       * Get key codes from SSP and send them to the keyboard callback.
++       */
++      keycount = ReadIntoBuffer();
++
++      /*
++       * If no keys were received, call the Data callback anyway so it can
++       * check for stuck keys.
++       */
++      if ((keycount == 0) && gKeyCallback)
++              gKeyCallback(-1);
++
++      /*
++       * Reschedule our timer in another 20 mSec.
++       */
++      g_KbdTimer.expires =
++          jiffies + MSECS_TO_JIFFIES(EP93XX_KEY_TIMER_PERIOD_MSEC);
++      add_timer(&g_KbdTimer);
++}
++
++/**
++ * HookInterrupt
++ *
++ * Requests SSP interrupt, sets up interrupt handler, sets up keyboard polling
++ * timer.
++ */
++static int HookInterrupt(void)
++{
++      if (gHookedInterrupt) {
++              printk(KERN_ERR "SSP driver interrupt already hooked\n");
++              return -1;
++      }
++
++      if (request_irq
++          (IRQ_SSPRX, SSPIrqHandler, SA_INTERRUPT, "ep93xxsspd", NULL)) {
++              printk(KERN_ERR "SSP driver failed to get IRQ handler\n");
++              return -1;
++      }
++
++      gHookedInterrupt = 1;
++
++      /*
++       * Initialize the timer that we will use to poll the SPI.
++       */
++      init_timer(&g_KbdTimer);
++      g_KbdTimer.function = TimerRoutine;
++      g_KbdTimer.data = 1;
++      g_KbdTimer.expires =
++          jiffies + MSECS_TO_JIFFIES(EP93XX_KEY_TIMER_PERIOD_MSEC);
++
++      add_timer(&g_KbdTimer);
++
++      return 0;
++}
++
++static int SSP_Open(enum SSPDeviceType Device, SSPDataCallback Callback)
++{
++      int Handle;
++
++      /*
++       * Generate a handle and pass it back.
++       *
++       * Increment the last valid handle.
++       * Check for wraparound (unlikely, but we like to be complete).
++       */
++      iLastValidHandle++;
++
++      /*
++       * If we wrapped around start over.  Unlikely.
++       */
++      if ((iLastValidHandle & ~SSP_DEVICE_MASK) == 0)
++              iLastValidHandle = 1;
++
++      Handle = iLastValidHandle | (Device << SSP_DEVICE_SHIFT);
++
++      switch (Device) {
++      case PS2_KEYBOARD:
++              {
++                      DPRINTK("SSP_Open - PS2_KEYBOARD\n");
++                      if (KeyboardHandle)
++                              return -1;
++
++                      DPRINTK("Handle:%08x  Callback:%08x  -- Success\n",
++                              Handle, (unsigned int)Callback);
++
++                      KeyboardHandle = Handle;
++                      /* Hook the interrupt if we have not yet. */
++                      HookInterrupt();
++                      SetSSPtoPS2();
++                      gKeyCallback = Callback;
++
++                      break;
++              }
++      case I2S_CODEC:
++              {
++                      DPRINTK("SSP_Open - I2S_CODEC\n");
++                      if (I2SHandle)
++                              return -1;
++
++                      DPRINTK("Handle:%08x  Callback:%08x  -- Success\n",
++                              Handle, (unsigned int)Callback);
++
++                      I2SHandle = Handle;
++                      break;
++              }
++      case SERIAL_FLASH:
++              {
++                      DPRINTK("SSP_Open - SERIAL_FLASH\n");
++                      if (FlashHandle)
++                              return -1;
++
++                      DPRINTK("Handle:%08x  Callback:%08x  -- Success\n",
++                              Handle, (unsigned int)Callback);
++
++                      FlashHandle = Handle;
++                      break;
++              }
++      default:
++              {
++                      return -1;
++              }
++      }
++
++      return Handle;
++}
++
++/**
++ * SSP_Close
++ *
++ * Release that Handle!
++ */
++static int SSP_Close(int Handle)
++{
++      /*
++       * Find out which device this API was called for.
++       */
++      switch (CheckHandle(Handle)) {
++      case PS2_KEYBOARD:
++              {
++                      DPRINTK("SSP_Open - PS2_KEYBOARD\n");
++                      del_timer(&g_KbdTimer);
++                      free_irq(IRQ_SSPRX, NULL);
++                      gKeyCallback = NULL;
++                      KeyboardHandle = 0;
++                      gHookedInterrupt = 0;
++                      break;
++              }
++      case I2S_CODEC:
++              {
++                      DPRINTK("SSP_Open - I2S_CODEC\n");
++                      I2SHandle = 0;
++                      break;
++              }
++      case SERIAL_FLASH:
++              {
++                      DPRINTK("SSP_Open - SERIAL_FLASH\n");
++                      FlashHandle = 0;
++                      break;
++              }
++      default:
++              {
++                      return -1;
++              }
++      }
++      return 0;
++}
++
++static int SSP_Read(int Handle, unsigned int Addr, unsigned int *pValue)
++{
++      DPRINTK("SSP_Read\n");
++      return 0;
++}
++
++static int SSP_Write(int Handle, unsigned int Addr, unsigned int Value)
++{
++      int iRet = 0;
++      /* DPRINTK("SSP_Write - Handle:0x%08x  Addr:0x%08x  Value:0x%08x\n",
++         Handle, Addr, Value ); */
++
++      /*
++       * Find out which device this API was called for.
++       */
++      switch (CheckHandle(Handle)) {
++      case PS2_KEYBOARD:
++              {
++                      break;
++              }
++      case I2S_CODEC:
++              {
++                      iRet = SSP_Write_I2SCodec(Handle, Addr, Value);
++                      break;
++              }
++      case SERIAL_FLASH:
++              {
++                      break;
++              }
++      default:
++              {
++                      return -1;
++              }
++      }
++
++      return iRet;
++}
++
++static void SetSSPtoPS2(void)
++{
++      unsigned int uiRegTemp;
++
++      if (gSSPmode == SSP_MODE_PS2)
++              return;
++
++      /*
++       * Disable the SSP, disable interrupts
++       */
++      writel(0, SSPCR1);
++
++      /*
++       * It takes almost a millisecond for a key to come in so
++       * make sure we have completed all transactions.
++       */
++      mdelay(1);
++
++      /*
++       * Set EGPIO7 to disable EEPROM device on EDB9312.
++       */
++      uiRegTemp = readl(GPIO_PADDR);
++      writel(uiRegTemp | 0x80, GPIO_PADDR);
++
++      uiRegTemp = readl(GPIO_PADR);
++      writel(uiRegTemp | 0x80, GPIO_PADR);
++
++      /*
++       * Still haven't enabled the keyboard.  So anything in
++       * the rx fifo is garbage.  Time to take out the trash.
++       */
++      while (readl(SSPSR) & SSPSR_RNE) {
++              uiRegTemp = readl(SSPDR);
++      }
++
++      /*
++       * SPICR0_SPO - SCLKOUT Polarity
++       * SPICR0_SPH - SCLKOUT Phase
++       * Motorola format, 11 bit, one start, 8 data, one bit for
++       * parity, one stop bit.
++       */
++      writel((SSPCR0_FRF_MOTOROLA | SSPCR0_SPH | SSPCR0_SPO |
++              SSPCR0_DSS_11BIT), SSPCR0);
++      /*
++       * Configure the device as a slave, Clear FIFO overrun interrupts,
++       * enable interrupts and reset the device.
++       */
++      writel((SSPC1_MS | SSPC1_RIE | SSPC1_SOD), SSPCR1);
++      writel(0, SSPIIR);
++      writel((SSPC1_MS | SSPC1_RIE | SSPC1_SOD | SSPC1_SSE),
++             SSPCR1);
++
++      /*
++       * Configure EGPIO pins 12 and 14 as outputs because they are used
++       * as buffer enables for the SPI interface to the ps2 keyboard.
++       * Clear EGPIO pins 12 and 14, this will enable the SPI keyboard.
++       */
++      uiRegTemp = readl(GPIO_PBDDR);
++      writel(uiRegTemp | 0x50, GPIO_PBDDR);
++
++      uiRegTemp = readl(GPIO_PBDR);
++      writel(uiRegTemp & ~0x50, GPIO_PBDR);
++
++      gSSPmode = SSP_MODE_PS2;
++}
++
++static void SetSSPtoI2S(void)
++{
++      unsigned int uiRegTemp;
++
++      if (gSSPmode == SSP_MODE_I2S)
++              return;
++
++      /*
++       * Disable recieve interrupts.
++       */
++      writel((SSPC1_MS | SSPC1_SSE), SSPCR1);
++
++      /*
++       * Set GPIO pins 12 and 14, this will bring the clock line low
++       * which signals to the keyboard to buffer keystrokes.
++       * Note that EGPIO 14 is the clock line and EGPIO 12 is data line.
++       */
++      uiRegTemp = readl(GPIO_PBDR);
++      writel(0x50 | uiRegTemp, GPIO_PBDR);
++
++      /*
++       * It takes almost a millisecond for an partial keystrokes to come in.
++       * Delay to make sure we have completed all transactions.
++       */
++      mdelay(1);
++
++      /*
++       * Anything we just recieved is garbage.  Time to take out the trash.
++       */
++      while (readl(SSPSR) & SSPSR_RNE) {
++              uiRegTemp = readl(SSPDR);
++      }
++
++      /*
++       * Disable the SSP and disable interrupts
++       */
++      writel(0, SSPCR1);
++
++      /*
++       * Clock will be 14.7 MHz divided by 4.
++       */
++      writel(2, SSPCPSR);
++
++      /*
++       * Configure EGPIO7 as an output and set it.  This selects
++       * I2S codec as the device on the SSP output instead of
++       * the serial flash.
++       */
++      uiRegTemp = readl(GPIO_PADDR);
++      writel(uiRegTemp | 0x80, GPIO_PADDR);
++
++      uiRegTemp = readl(GPIO_PADR);
++      writel(uiRegTemp | 0x80, GPIO_PADR);
++
++      /*
++       * Motorola format, 8 bit.
++       */
++      writel((SSPCR0_SPO | SSPCR0_SPH | SSPCR0_FRF_MOTOROLA |
++              SSPCR0_DSS_8BIT), SSPCR0);
++
++      /*
++       * Configure the device as master, reenable the device.
++       */
++      writel(SSPC1_SSE, SSPCR1);
++
++      gSSPmode = SSP_MODE_I2S;
++
++      udelay(10);
++}
++
++/**
++ *  CheckHandle
++ *
++ *  If Handle is valid, returns 0.  Otherwise it returns -1.
++ */
++static int CheckHandle(int Handle)
++{
++      int iRet;
++
++      if ((Handle != KeyboardHandle) &&
++          (Handle != I2SHandle) && (Handle != FlashHandle)) {
++              DPRINTK("OOPS! Invalid SSP Handle!\n");
++              return -1;
++      }
++
++      /*
++       * Get the SSP driver instance number from the handle.
++       */
++      iRet = (((int)Handle & SSP_DEVICE_MASK) >> SSP_DEVICE_SHIFT);
++
++#if 0
++      switch (iRet) {
++      case PS2_KEYBOARD:
++              DPRINTK("CheckHandle - valid - Keyboard\n");
++              break;
++
++      case I2S_CODEC:
++              DPRINTK("CheckHandle - valid - I2S\n");
++              break;
++
++      case SERIAL_FLASH:
++              DPRINTK("CheckHandle - valid - Keyboard\n");
++              break;
++      }
++#endif
++
++      return iRet;
++}
++
++/**
++ * ReadIntoBuffer
++ *
++ * Drains the SSP rx fifo into a buffer here.  If we overflow this buffer
++ * then something's wrong.
++ */
++static int ReadIntoBuffer(void)
++{
++      unsigned int count, index, saved_count, uiRegTemp;
++
++      count = 0;
++      index = 0;
++
++      if (gSSPmode != SSP_MODE_PS2)
++              return 0;
++
++      /*
++       * This spinlock will prevent I2S from grabbing the SSP to do a
++       * write while we are using the SSP for PS2.
++       *
++       * There is a slight chance that we are in the beginning phase
++       * of doing an I2S write but the mode flag hadn't yet switched
++       * to I2S.  If that happens we will end up waiting on I2S to
++       * finish a write.  Not great.
++       */
++      spin_lock(&ssp_spinlock);
++
++      while (readl(SSPSR) & SSPSR_RNE) {
++              /*
++               * Read in the value from the SPI controller into
++               * the partial key buffer.
++               */
++              uiKeyBuffer[count] = readl(SSPDR);
++              if (((uiKeyBuffer[count] & 0x3fc) != 0x3e0) &&
++                  ((uiKeyBuffer[count] & 0x3fc) != 0x3c0)) {
++                      /*
++                       * Set GPIO pins 12 and 14, this will bring the clock line low
++                       * which signals to the keyboard to buffer keystrokes.
++                       * Note that EGPIO 14 is the clock line and EGPIO 12 is data line.
++                       */
++                      uiRegTemp = readl(GPIO_PBDR);
++                      writel(0x50 | uiRegTemp, GPIO_PBDR);
++
++                      writel(0, SSPCR1);
++                      writel((SSPC1_MS | SSPC1_RIE | SSPC1_SSE),
++                             SSPCR1);
++
++                      /*
++                       * Clear EGPIO pins 12 and 14, this will enable the SPI keyboard.
++                       */
++                      uiRegTemp = readl(GPIO_PBDR);
++                      writel(uiRegTemp & ~0x50, GPIO_PBDR);
++
++                      count++;
++                      break;
++              }
++              count++;
++      }
++
++      saved_count = count;
++      index = 0;
++      while (count) {
++              /*
++               * No callback, dump data.
++               */
++              if (gKeyCallback)
++                      gKeyCallback(uiKeyBuffer[index++]);
++
++              count--;
++      }
++
++      spin_unlock(&ssp_spinlock);
++
++      return saved_count;
++}
++
++/**
++ * SSP_Write_I2SCodec
++ *
++ */
++static int SSP_Write_I2SCodec
++    (int Handle, unsigned int RegAddr, unsigned int RegValue) {
++      enum SSPmodes saved_mode;
++
++      DPRINTK("SSP_Write_I2SCodec\n");
++
++      spin_lock(&ssp_spinlock);
++
++      /*
++       * Save the SSP mode.  Switch to I2S mode if we're not
++       * already in I2S mode.
++       */
++      saved_mode = gSSPmode;
++      SetSSPtoI2S();
++
++      /*
++       * Let TX fifo clear out.  Poll the Transmit Fifo Empty bit.
++       */
++      while (!(readl(SSPSR) & SSPSR_TFE)) ;
++
++      /*
++       * Write the data out to the tx fifo.
++       */
++      writel(0x20, SSPDR);    /* chip address for CS4228 */
++      writel((RegAddr & 0xff), SSPDR);
++      writel((RegValue & 0xff), SSPDR);
++
++      /*
++       * Let TX fifo clear out.  Poll the Transmit Fifo Empty bit.
++       */
++      while (!(readl(SSPSR) & SSPSR_TFE)) ;
++
++      /*
++       * Delay to let stuff make it out of the SR before doing
++       * anthing else to the SSP.  It takes 6.8 uSec to do a
++       * I2S codec register write.
++       */
++      udelay(10);
++
++      /*
++       * If we were in PS2 mode, switch back to PS2 mode.
++       * If we weren't in PS2 mode, that means we didn't compile in
++       * the PS2 keyboard support, so no need to switch to PS2 mode.
++       */
++      if (saved_mode == SSP_MODE_PS2)
++              SetSSPtoPS2();
++
++      spin_unlock(&ssp_spinlock);
++
++      return 0;
++}
+diff --git a/arch/arm/mach-ep93xx/ssp.c b/arch/arm/mach-ep93xx/ssp.c
+new file mode 100644
+index 0000000..4e1b973
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/ssp.c
+@@ -0,0 +1,246 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/ssp.c
++ *
++ *  Generic SSP driver. This provides shared access to the SSP
++ *  interface operating in master mode.
++ *
++ *  Copyright (C) 2004 Ray Lehtiniemi.
++ *  Copyright (C) 2004 Siconix, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++
++#include <asm/arch/ssp.h>
++
++/* ================================================================
++                       Front End Interface
++   ================================================================ */
++
++/***
++ * ssp_add_slave - register an ssp_slave with an ssp_master
++ * @m: the master
++ * @s: the slave
++ *
++ * Grabs the frontend lock and adds slave to list.
++ */
++int ssp_add_slave(struct ssp_master *m, struct ssp_slave *s)
++{
++      if (s->master != NULL)
++              return -EBUSY;
++      down(&m->sem);
++      list_add(&s->list, &m->slave);
++      s->master = m;
++      up(&m->sem);
++      return 0;
++}
++
++EXPORT_SYMBOL(ssp_add_slave);
++
++/***
++ * ssp_remove_slave - de-register an ssp_slave from its master
++ * @m: the master
++ * @s: the slave
++ *
++ * Grabs the frontend lock and removes slave from list.
++ */
++void ssp_remove_slave(struct ssp_master *m, struct ssp_slave *s)
++{
++      if (s->master != m)
++              return;
++      down(&m->sem);
++      list_del(&s->list);
++      s->master = NULL;
++      up(&m->sem);
++}
++
++EXPORT_SYMBOL(ssp_remove_slave);
++
++/***
++ * ssp_do - perform a single SSP transaction on the slave
++ * @s: the slave
++ * @len: the number of words to transfer
++ * @tx: a buffer of @len words to clock out to slave
++ * @rx: a buffer of @len words to clock in from slave
++ *
++ * Grabs the frontend lock, configures the ssp master as required
++ * by the slave, asserts the slave devices chip select line, and
++ * schedules the backend to perform the transfer.
++ *
++ * Once the backend signals completion, the chip select is negated
++ * and the frontend lock is released.
++ *
++ * The backend will transfer @len * @s->nbytes from @tx and
++ * into @rx.  Make sure your buffers are big enough! If @tx
++ * or @rx are null, then null data will be clocked in and/or out.
++ */
++int ssp_do(struct ssp_slave *s, int len, void *tx, void *rx)
++{
++      int err;
++
++      if ((err = ssp_start(s)) < 0)
++              goto out1;
++
++      ssp_select(s);
++
++      if ((err = ssp_post(s, len, tx, rx)) < 0)
++              goto out2;
++
++      err = ssp_wait(s);
++
++      out2:
++      ssp_deselect(s);
++      ssp_finish(s);
++      out1:
++      return err;
++}
++
++EXPORT_SYMBOL(ssp_do);
++
++/* ================================================================
++                       Transaction Interface
++   ================================================================ */
++
++static int __ssp_txn_start(struct ssp_slave *s);
++
++/***
++ * ssp_start - Grab and configure the SSP bus (blocking)
++ * @s: the slave
++ *
++ * This call will grab and initialize the SSP bus, blocking
++ * until the bus is ready.
++ */
++int ssp_start(struct ssp_slave *s)
++{
++      down(&s->master->sem);
++      return __ssp_txn_start(s);
++}
++
++EXPORT_SYMBOL(ssp_start);
++
++/***
++ * ssp_trystart - Grab and configure the SSP bus (non-blocking)
++ * @s: the slave
++ *
++ * This call will grab and initialize the SSP bus, returning
++ * with an error if the bus is not free.
++ */
++int ssp_trystart(struct ssp_slave *s)
++{
++      if (!down_trylock(&s->master->sem))
++              return -EBUSY;
++      return __ssp_txn_start(s);
++}
++
++EXPORT_SYMBOL(ssp_trystart);
++
++static int __ssp_txn_start(struct ssp_slave *s)
++{
++      return s->master->ops->configure(s);
++}
++
++/***
++ * ssp_select - assert the slave CS line
++ * @s: the slave
++ *
++ * assert the device-specific CS line
++ */
++void ssp_select(struct ssp_slave *s)
++{
++      s->chip_select(s, 1);
++}
++
++EXPORT_SYMBOL(ssp_select);
++
++/***
++ * ssp_post - start the backend for the slave's master
++ * @s: the slave
++ *
++ * Start the backend data transfer for this master.
++ */
++int ssp_post(struct ssp_slave *s, int len, void *tx, void *rx)
++{
++      struct ssp_transfer *t;
++
++      t = &s->master->transfer;
++
++      t->size = s->nbytes;
++      t->len = len;
++      t->rlen = len;
++      t->tx = tx;
++      t->rx = rx;
++      t->c = &s->master->completion;
++      init_completion(t->c);
++
++      return s->master->ops->enable(t);
++}
++
++EXPORT_SYMBOL(ssp_post);
++
++/***
++ * ssp_wait - block until the SP transfer is complete
++ * @s: the slave
++ *
++ * block until the SP transfer is complete.
++ */
++int ssp_wait(struct ssp_slave *s)
++{
++      wait_for_completion(&s->master->completion);
++      return s->master->ops->disable();
++}
++
++EXPORT_SYMBOL(ssp_wait);
++
++/***
++ * ssp_deselect - assert the slave CS line
++ * @s: the slave
++ *
++ * negate the device-specific CS line
++ */
++void ssp_deselect(struct ssp_slave *s)
++{
++      s->chip_select(s, 0);
++}
++
++EXPORT_SYMBOL(ssp_deselect);
++
++/***
++ * ssp_finish - release the ssp bus
++ * @s: the slave
++ *
++ * Releases the frontend lock.
++ */
++void ssp_finish(struct ssp_slave *s)
++{
++      up(&s->master->sem);
++}
++
++EXPORT_SYMBOL(ssp_finish);
++
++/* ================================================================
++                       Module Stuff
++   ================================================================ */
++
++int __init ssp_init(void)
++{
++      printk(KERN_INFO "Generic SSP Support version 0.1\n");
++      return 0;
++}
++
++void __exit ssp_exit(void)
++{
++}
++
++module_init(ssp_init);
++module_exit(ssp_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi");
++MODULE_DESCRIPTION("Generic SSP driver");
++MODULE_LICENSE("GPL");
+diff --git a/arch/arm/mach-ep93xx/ssp2.c b/arch/arm/mach-ep93xx/ssp2.c
+new file mode 100644
+index 0000000..6a4ff10
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/ssp2.c
+@@ -0,0 +1,354 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/ssp.c
++ *
++ *  EP93xx SSP driver. This provides shared access to the SSP
++ *  interface operating in master mode.
++ *
++ *  Copyright (C) 2004 Ray Lehtiniemi.
++ *  Copyright (C) 2004 Siconix, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/spinlock.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/hardware.h>
++
++#include <asm/arch/ssp.h>
++#include <asm/arch/ssp2.h>
++
++/* print out all chars tx, rx, and dropped */
++#define _(x...)                       /* printk(KERN_WARNING x); printk("\n") */
++
++/* the current transfer */
++static struct ssp_transfer *transfer;
++
++/* stupid SSP gives rx int only when rx fifo > half full :-P */
++static void do_rx_poll(void *x);
++static DECLARE_WORK(work, do_rx_poll, NULL);
++
++/* also implement a timeout in the worker, to prevent hard lockups
++   if something goes south... */
++static int timeout;
++
++/* serialize the rx irq and the work poller routines */
++static spinlock_t spinlock = SPIN_LOCK_UNLOCKED;
++
++/* ----------------- Hardware Control --------------------- */
++
++/* send a word */
++static __inline__ void x_ssp_send(__u16 dat)
++{
++      writel(dat, SSPDR);
++      _("\ttx %08x", dat);
++}
++
++/* send a word to clock the recv */
++static __inline__ void x_ssp_clock(void)
++{
++      writel(0, SSPDR);
++      _("\tt- --------");
++}
++
++/* recv a word */
++static __inline__ __u16 x_ssp_recv(void)
++{
++      unsigned long dat = readl(SSPDR);
++      _("\trx %08lx", dat);
++      return dat & 0xffff;
++}
++
++/* discard a word */
++static __inline__ void x_ssp_discard(void)
++{
++#if 1
++      unsigned long dat = readl(SSPDR);
++      _("\tr- %08lx  (discard)", dat);
++#else
++      (void)readl(SSPDR);
++      _("\tr- --------");
++#endif
++}
++
++/* are there chars in the rx fifo? */
++static __inline__ int x_ssp_available(void)
++{
++      return (readl(SSPSR) & SSPSR_RNE) ? 1 : 0;
++}
++
++/* is there room in the tx fifo? */
++static __inline__ int x_ssp_has_room(void)
++{
++      return (readl(SSPSR) & SSPSR_TNF) ? 1 : 0;
++}
++
++/* is the transmitter busy? */
++static __inline__ int x_ssp_busy(void)
++{
++      return (readl(SSPSR) & SSPSR_BSY) ? 1 : 0;
++}
++
++/* flush the RX and TX fifos */
++static void x_ssp_flush(void)
++{
++      do {
++              while (x_ssp_available())
++                      x_ssp_discard();
++      } while (x_ssp_busy());
++
++      /* just in case there is a race... in any event, this should be harmless */
++      x_ssp_discard();
++}
++
++/* set up all regs as required by the slave */
++static void x_ssp_configure(struct ep93xx_ssp_slave *s)
++{
++      writel(s->cr1, SSPCR1);
++      writel(s->cr0, SSPCR0);
++      writel(s->cpsr, SSPCPSR);
++      writel(s->cr1 & ~SSPC1_SSE, SSPCR1);
++      writel(s->cr1, SSPCR1);
++}
++
++/* enable chip select and all ints */
++static __inline__ void x_ssp_enable(void)
++{
++      unsigned long x = readl(SSPCR1);
++      writel(x | SSPC1_TIE | SSPC1_RIE | SSPC1_RORIE, SSPCR1);
++}
++
++/* disable chip select and all ints */
++static __inline__ void x_ssp_disable(void)
++{
++      unsigned long x = readl(SSPCR1);
++      writel(x & ~(SSPC1_TIE | SSPC1_RIE | SSPC1_RORIE), SSPCR1);
++}
++
++/* disable tx int */
++static __inline__ void x_ssp_stop_tx(void)
++{
++      unsigned long x = readl(SSPCR1);
++      writel(x & ~SSPC1_TIE, SSPCR1);
++}
++
++/* ---------------------- Master Methods ------------------------- */
++
++static int ep93xx_ssp_configure(struct ssp_slave *ss)
++{
++      struct ep93xx_ssp_slave *s = (struct ep93xx_ssp_slave *)ss;
++      _("SSP transfer");
++      x_ssp_configure(s);
++      return 0;
++}
++
++static int ep93xx_ssp_enable(struct ssp_transfer *t)
++{
++      _("{");
++      transfer = t;
++      timeout = 0;
++      schedule_delayed_work(&work, 1);
++      x_ssp_enable();
++      return 0;
++}
++
++static int ep93xx_ssp_disable(void)
++{
++      x_ssp_disable();
++      cancel_delayed_work(&work);
++      transfer = NULL;
++      _("}");
++      return 0;
++}
++
++static struct ssp_master_ops my_ops = {
++      .configure = ep93xx_ssp_configure,
++      .enable = ep93xx_ssp_enable,
++      .disable = ep93xx_ssp_disable,
++};
++
++/* ----------------- Registration Stuff FIXME ------------- */
++
++#include <linux/completion.h>
++#include <asm/types.h>
++#include <asm/semaphore.h>
++
++struct ssp_master ep93xx_ssp_master = {
++      __MUTEX_INITIALIZER(ep93xx_ssp_master.sem),
++      COMPLETION_INITIALIZER(ep93xx_ssp_master.completion),
++      LIST_HEAD_INIT(ep93xx_ssp_master.slave),
++      {
++       0,
++       0,
++       0,
++       NULL,
++       NULL,
++       NULL},
++      &my_ops
++};
++
++EXPORT_SYMBOL(ep93xx_ssp_master);
++
++/* -------------------- Bottom Half ----------------------- */
++
++static void do_tx(void)
++{
++      if (transfer == NULL) {
++              printk(KERN_WARNING "Null tx transfer...\n");
++              return;
++      }
++
++      while (transfer->len != 0) {
++
++              if (!x_ssp_has_room())
++                      return;
++
++              if (transfer->tx == NULL) {
++                      x_ssp_clock();
++
++              } else if (transfer->size == 1) {
++                      __u8 *t = transfer->tx;
++                      x_ssp_send(*t);
++                      transfer->tx += 1;
++
++              } else if (transfer->size == 2) {
++                      __u16 *t = transfer->tx;
++                      x_ssp_send(*t);
++                      transfer->tx += 2;
++
++              } else if (transfer->size == 4) {
++                      __u32 *t = transfer->tx;
++                      x_ssp_send(*t);
++                      transfer->tx += 4;
++              }
++
++              transfer->len--;
++      }
++
++      x_ssp_stop_tx();
++}
++
++static void __do_rx(void)
++{
++      if (transfer == NULL) {
++              printk(KERN_WARNING "Null rx transfer...\n");
++              return;
++      }
++
++      while (transfer->rlen != 0) {
++
++              if (!x_ssp_available())
++                      return;
++
++              if (transfer->rx == NULL) {
++                      x_ssp_discard();
++
++              } else if (transfer->size == 1) {
++                      __u8 *t = transfer->rx;
++                      *t = x_ssp_recv();
++                      transfer->rx += 1;
++
++              } else if (transfer->size == 2) {
++                      __u16 *t = transfer->rx;
++                      *t = x_ssp_recv();
++                      transfer->rx += 2;
++
++              } else if (transfer->size == 4) {
++                      __u32 *t = transfer->rx;
++                      *t = x_ssp_recv();
++                      transfer->rx += 4;
++              }
++
++              transfer->rlen--;
++              timeout = 0;
++      }
++
++      complete(transfer->c);
++}
++
++static void do_rx(void)
++{
++      unsigned long flags;
++      spin_lock_irqsave(&spinlock, flags);
++      __do_rx();
++      spin_unlock_irqrestore(&spinlock, flags);
++}
++
++static void do_rx_poll(void *x)
++{
++      unsigned long flags;
++      spin_lock_irqsave(&spinlock, flags);
++      __do_rx();
++      timeout++;
++      if (timeout == 100) {
++              x_ssp_disable();
++              complete(transfer->c);
++      } else {
++              schedule_delayed_work(&work, 1);
++      }
++      spin_unlock_irqrestore(&spinlock, flags);
++}
++
++static irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++{
++      unsigned int status = readl(SSPIIR);
++
++      if (transfer == NULL) {
++              printk(KERN_WARNING "SSP: no active transfer\n");
++              x_ssp_flush();
++              x_ssp_disable();
++      }
++
++      if (status & SSPIIR_RORIS)
++              printk(KERN_WARNING "SSP: receiver overrun\n");
++
++      if (status & SSPIIR_TIS)
++              do_tx();
++
++      if (status & SSPIIR_RIS)
++              do_rx();
++
++      writel(0, SSPICR);
++
++      return status ? IRQ_HANDLED : IRQ_NONE;
++}
++
++/* -------------------- Module Stuff ---------------------- */
++
++int __init ep93xx_ssp_init(void)
++{
++      int i;
++
++      if (readl(SYSCON_DEVCFG) & SYSCON_DEVCFG_I2SonSSP)
++              return -ENODEV;
++
++      i = request_irq(IRQ_SSP, irq_handler, 0, "SSP", NULL);
++
++      if (i)
++              printk(KERN_ERR
++                     "EP93XX: unable to grab SSP interrupt, error %d\n", i);
++
++      printk(KERN_INFO "EP93xx SSP driver version 0.1\n");
++      return 0;
++}
++
++void __exit ep93xx_ssp_exit(void)
++{
++      free_irq(IRQ_SSP, NULL);
++}
++
++module_init(ep93xx_ssp_init);
++module_exit(ep93xx_ssp_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi");
++MODULE_DESCRIPTION("EP93xx SSP driver");
++MODULE_LICENSE("GPL");
+diff --git a/arch/arm/mach-ep93xx/time.c b/arch/arm/mach-ep93xx/time.c
+new file mode 100644
+index 0000000..459a179
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/time.c
+@@ -0,0 +1,40 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/time.c
++ *
++ *  Copyright (C) 2000-2001 Deep Blue Solutions
++ *
++ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA.  All rights reserved.
++ *  Copyright (C) 2002-2003 Cirrus Logic, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++
++extern int (*set_rtc) (void);
++
++static int ep93xx_set_rtc(void)
++{
++      writel(xtime.tv_sec, RTCLR);
++      return 1;
++}
++
++static int ep93xx_rtc_init(void)
++{
++      writel(0, RTCCR);
++      writel(0, RTCEOI);
++
++      writel(xtime.tv_sec, RTCDR);
++
++      set_rtc = ep93xx_set_rtc;
++
++      return 0;
++}
++
++__initcall(ep93xx_rtc_init);
+diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
+index e84fdde..85c90bf 100644
+--- a/arch/arm/mm/Kconfig
++++ b/arch/arm/mm/Kconfig
+@@ -62,8 +62,8 @@ config CPU_ARM720T
+ # ARM920T
+ config CPU_ARM920T
+       bool "Support ARM920T processor" if !ARCH_S3C2410
+-      depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000
+-      default y if ARCH_S3C2410
++      depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000  || ARCH_EP93XX
++      default y if ARCH_S3C2410 || ARCH_EP93XX
+       select CPU_32v4
+       select CPU_ABRT_EV4T
+       select CPU_CACHE_V4WT
+diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
+index 8b276ee..cc8aedb 100644
+--- a/arch/arm/mm/init.c
++++ b/arch/arm/mm/init.c
+@@ -212,6 +212,10 @@ static __init void reserve_node_zero(pg_
+       if (machine_is_integrator() || machine_is_cintegrator())
+               res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
++      /* TBD vector table and initial stack below pg_dir */
++      if (machine_is_edb9301() || machine_is_edb9312() || machine_is_edb9315() || machine_is_acc())
++              res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
++
+       /*
+        * These should likewise go elsewhere.  They pre-reserve the
+        * screen memory region at the start of main system memory.
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+index 84e68cd..c4a267b 100644
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -4,6 +4,16 @@
+ menu "Character devices"
++config TTML_DEVICES
++      tristate "TTML TripDawg system devices"
++      depends on MACH_TTML
++      default m
++      ---help---
++        If you say y or m here, you will get several character devices
++        which allow you to use the LEDs, buzzer, speedometer, and so
++        on. These devices are mapped into the 10,{240-254} range, which
++        is reserved for local devices.
++
+ config VT
+       bool "Virtual terminal" if EMBEDDED
+       select INPUT
+@@ -762,6 +772,26 @@ config EFI_RTC
+       bool "EFI Real Time Clock Services"
+       depends on IA64
++config EP93XX_RTC
++      bool "Cirrus EP93xx Real Time Clock support"
++      depends on ARCH_EP93XX
++      help
++        Provides EFI and legacy RTC support on the Cirrus EP93xx family of
++        devices via the /dev/rtc character node (10/135).
++
++config DS1337_RTC
++      tristate "Dallas Semiconductor DS1337 Real Time Clock /dev/rtc interface"
++      depends on I2C && EXPERIMENTAL && !EP93XX_RTC
++      select SENSORS_DS1337
++      help
++        Say Y here you have got a DS1337 real time clock on your I2C bus.
++        This here is just an interface to access it via the /dev/rtc
++        character node (10/135).  All the hard work will be done
++        in the I2C driver (drivers/i2c/chips/ds1337.c).
++
++        This driver can also be built as a module.  If so, the module
++        will be called ds1337glue.
++
+ config DS1302
+       tristate "DS1302 RTC support"
+       depends on M32R && (PLAT_M32700UT || PLAT_OPSPUT)
+@@ -893,6 +923,8 @@ source "drivers/char/drm/Kconfig"
+ source "drivers/char/pcmcia/Kconfig"
++source "drivers/char/can/Kconfig"
++
+ config MWAVE
+       tristate "ACP Modem (Mwave) support"
+       depends on X86
+diff --git a/drivers/char/Makefile b/drivers/char/Makefile
+index 4aeae68..579570d 100644
+--- a/drivers/char/Makefile
++++ b/drivers/char/Makefile
+@@ -9,6 +9,7 @@ FONTMAPFILE = cp437.uni
+ obj-y  += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
++obj-$(CONFIG_TTML_DEVICES)    += ttml.o
+ obj-$(CONFIG_LEGACY_PTYS)     += pty.o
+ obj-$(CONFIG_UNIX98_PTYS)     += pty.o
+ obj-y                         += misc.o
+@@ -65,6 +66,8 @@ obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
+ obj-$(CONFIG_DS1302) += ds1302.o
+ obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
+ obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o
++obj-$(CONFIG_EP93XX_RTC) += ep93xx-rtc.o
++obj-$(CONFIG_DS1337_RTC)      += ds1337glue.o
+ ifeq ($(CONFIG_GENERIC_NVRAM),y)
+   obj-$(CONFIG_NVRAM) += generic_nvram.o
+ else
+@@ -119,3 +122,6 @@ $(obj)/defkeymap.c $(obj)/qtronixmap.c: 
+       rm $@.tmp
+ endif
++
++obj-$(CONFIG_CAN_BUS) += can/
++
+diff --git a/drivers/char/can/Kconfig b/drivers/char/can/Kconfig
+new file mode 100644
+index 0000000..9834c66
+--- /dev/null
++++ b/drivers/char/can/Kconfig
+@@ -0,0 +1,46 @@
++#
++# CAN bus character devices configuration
++#
++
++menu "CAN bus devices"
++
++config CAN_BUS
++      bool "CAN bus character devices"
++      help
++        If you say y here, you will get support for CAN bus
++        character device drivers.
++
++config OKI_CAN_ML9620
++      tristate "OKI ML9620 CAN BUS"
++      depends on CAN_BUS
++      help
++        If you say y or m here, you will get support for OKI ML9620
++        character device based CAN driver for one CAN bus.
++
++choice
++      prompt "OKI ML9620 configuration"
++      depends on OKI_CAN_ML9620
++      help
++       Specific configuration for OKI ML9620 configuration.
++
++config OKI_CAN_ML9620_MICRO9
++      bool "OKI ML9620 Contec Hypercontrol Micro9 configuration"
++      depends on OKI_CAN_ML9620
++      help
++       Select this if you have Contec Hypercontrol Micro9 board.
++
++config OKI_CAN_ML9620_GASSNER
++      bool "OKI ML9620 Gassner configuration"
++      help
++         Select this if you want to have Gassner specific changes.
++
++endchoice
++
++config OKI_CAN_ML9620_2DEV
++      bool "OKI ML9620 CAN BUS 2nd DEVICE"
++      depends on OKI_CAN_ML9620
++      help
++       If you say y here, you will get support for a second
++       OKI ML9620 CAN bus.
++
++endmenu
+diff --git a/drivers/char/can/Makefile b/drivers/char/can/Makefile
+new file mode 100644
+index 0000000..f9bcf2a
+--- /dev/null
++++ b/drivers/char/can/Makefile
+@@ -0,0 +1,4 @@
++#
++# Makefile for CAN BUS character devices
++#
++obj-$(CONFIG_OKI_CAN_ML9620) += oki_ml9620.o
+diff --git a/drivers/char/can/oki_ml9620.c b/drivers/char/can/oki_ml9620.c
+new file mode 100644
+index 0000000..d60cca4
+--- /dev/null
++++ b/drivers/char/can/oki_ml9620.c
+@@ -0,0 +1,1006 @@
++/*
++ * drivers/char/can/oki_ml9620_core.c
++ *
++ * OKI ML9620 CAN Controler driver
++ *
++ * Author: Manfred Gruber <manfred.gruber@contec.at>
++ *
++ * Copyright 2004 (c) Manfred Gruber
++ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H
++ * Kufstein/Austria   www.contec.at
++ *
++ * This driver was written for Contec Hypercontrol Micro9 Board:
++ * 1. CAN Controller is on Hypercontrol Micro9 CPU board
++ * 2. CAN Controller is on Hypercontrol Micro9 Eval board
++ *
++ * Contec uses this driver on their Hypercontrol Micro9 boards based on
++ * Cirrus Logic EP93XX, we have changed Adr-/Databus timing to use OKI ML9620.
++ *
++ * This file is licensed under  the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ *
++ */
++
++/*Versions:
++  - 0.01 Inital version Only worked CAN1
++  - 0.02 CAN1/CAN2 worked, EVAL-board and CPU-BOARD Micro9
++  - 0.03 changes from Michael Burian to correct:
++         errors, functions, adr/databus-problems - thanks a lot Michael
++         changed to correct name oki_ml9620_X and put in drivers/char/can/
++         deleted some wrong statements
++  - 0.04 Michael Burian: read/write expect/return count in bytes now, cleanups
++  - 0.05 Michael Burian: use mux'd IRQs for both devices now 
++  - 0.06 Michael Burian: only queue messages when /dev/can[01] is open
++  - 0.07 Michael Burian: implement non-blocking read
++  - 0.08 Michael Burian: replace completion with waitq, implement poll support
++*/
++
++/*Todo:
++  - Baudrate over /proc configure
++  - remove potential infinite loop in write / make write return immediately 
++    (no longer wait for hardware, do this in background)
++  - implement fsync to allow waiting till hardware has written, if desired
++  - implement poll for write
++  - implement buffered write
++  - use kfifo for buffering read
++  - use kfifo for buffering write
++  - look for a more elegant solution for 
++*/
++
++/* Enable for debugging */
++/*#define OKI_DEBUG */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/signal.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/major.h>
++#include <linux/config.h>
++#include <linux/moduleparam.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/stddef.h>     /* offsetof(), etc. */
++#include <linux/completion.h>
++#include <linux/poll.h>
++#include <linux/can/oki_ml9620_ctrl.h>
++#include <asm/segment.h>
++#include <asm/hardware.h>
++#include <asm/bitops.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/arch/regmap.h>
++#include "oki_ml9620.h"
++
++/* fops                       */
++static int oki_read(struct file *file, char *buf, size_t count,loff_t *ppos);
++static int oki_write(struct file *file, const char *buf, size_t count,loff_t *ppos);
++static int oki_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
++static int oki_open(struct inode *inode, struct file *file);
++static int oki_release(struct inode *inode, struct file *file);
++static unsigned int oki_poll(struct file *file, poll_table *wait);
++
++/* IRQ  */
++static irqreturn_t oki_irqhandler(int irq, void *dev_id, struct pt_regs *regs);
++
++/* CAN */
++static void hw_init(struct can_device *c);
++static int set_baudrate(struct can_device *c, int baud);
++static int check_status(struct can_device *c);
++static int activate(struct can_device *c, unsigned char new_status);
++static void store_data_in_buffer(struct can_device *c, struct can_msg *data);
++
++void store_data_in_buffer(struct can_device *c, struct can_msg *data)
++{
++      /* No need to fill up the queue when nobody cares. */
++      if (atomic_read(&c->can_opened))
++              return;
++      
++      DBG_OKI(KERN_INFO, "DATA Stored: ID 0x%x dlc 0x%x rtr 0x%x ext 0x%x DATA: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",data->id,data->dlc,data->rtr,data->ext,data->data[0],data->data[1],data->data[2],data->data[3],data->data[4],data->data[5],data->data[6],data->data[7]);
++
++      if (memcpy(&c->tail->msg, data, sizeof(struct can_msg)) != NULL) {
++              c->tail->next = kmalloc(sizeof(struct recbuf), GFP_KERNEL);
++              if (c->tail->next != NULL) {
++                      c->tail->next->prev = c->tail;
++                      c->tail = c->tail->next;
++                      /* up sema to allow read */
++                      wake_up_interruptible(&c->rx_waitq);
++                      return;
++              }
++      }
++}
++
++int set_baudrate(struct can_device *c, int baud)
++{
++      unsigned long v = (unsigned long)c->virt_addr_can;
++      int index = 0;
++
++      /* unlock hardware */
++      c->reg.cancont = readb(v + CANCONT);
++      c->reg.cancont |= CONT_FLAG_INIT;
++      writeb(c->reg.cancont, v + CANCONT);
++
++      c->reg.cancont = readb(v + CANCONT);
++      c->reg.cancont |= CONT_FLAG_CCE;
++      writeb(c->reg.cancont, v + CANCONT);
++
++      DBG_OUT(KERN_DEBUG, ": /dev/can%d set_baudrate %dkb\n", c->minor, baud);
++
++      /* Lookuptable baudrate => Timing array index */
++      switch (baud){
++      case 10:        index = 0; break;
++      case 20:        index = 1; break;
++      case 50:        index = 2; break;
++      case 100:       index = 3; break;
++      case 125:       index = 4; break;
++      case 250:       index = 5; break;
++      case 500:       index = 6; break;
++      case 800:       index = 7; break;
++      case 1000:      index = 8; break;
++      default:        index = 4; break;
++      }
++
++      /* set baudrate */
++      c->reg.canbitt[0] = bd_tbl[index].btiming0;
++      c->reg.canbitt[1] = bd_tbl[index].btiming1;
++      c->reg.canbpre = bd_tbl[index].bpre;
++      writeb(c->reg.canbitt[0], v + CANBITT0);
++      writeb(c->reg.canbitt[1], v + CANBITT1);
++      writeb(c->reg.canbpre, v + CANBPRE);
++
++      /* lock hardware */
++      c->reg.cancont = readb(v + CANCONT);
++      c->reg.cancont &= ~CONT_FLAG_CCE;
++      writeb(c->reg.cancont, v + CANCONT);
++
++      c->reg.cancont = readb(v + CANCONT);
++      c->reg.cancont &= ~CONT_FLAG_INIT;
++      writeb(c->reg.cancont, v + CANCONT);
++
++      return baud;
++}
++
++void hw_init(struct can_device *c)
++{
++      unsigned char i;
++      unsigned long v = (unsigned long)c->virt_addr_can;
++
++      spin_lock_init(&c->can_lock);
++
++      c->reg.cancont |= CONT_FLAG_INIT;
++      writeb(c->reg.cancont, v + CANCONT);
++
++      /* All Messages disabled with MsgVal = 0 */
++      c->reg.if1id[3] = 0x00;
++      writeb(c->reg.if1id[3], v + IF1ID3);
++
++      /* set, so that ID Register will get transfered */
++      c->reg.if1cmask = 0x38;
++      writeb(c->reg.if1cmask, v + IF1CMASK);
++
++      for (i = 1; i < (NUM_MSG + 1); i++) {
++              while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
++              c->reg.if1creq = i;
++              writeb(c->reg.if1creq, v + IF1CREQ);
++      }
++
++      for (i = CAN_STD_RX_BUFFER_START; i < (CAN_STD_RX_BUFFER_END + 1); i++) {
++              c->reg.if1id[3] = 0x80;
++              writeb(c->reg.if1id[3], v + IF1ID3);
++
++              c->reg.if1id[2] = 0x00;
++              writeb(c->reg.if1id[2], v + IF1ID2);
++
++              /*c->reg.if1mask[3] = 0x00; */
++              c->reg.if1mask[3] = 0x20;
++              writeb(c->reg.if1mask[3], v + IF1MASK3);
++
++              c->reg.if1mask[2] = 0x00;
++              writeb(c->reg.if1mask[2], v + IF1MASK2);
++
++              /* Transfer Controll u. ID bits */
++              c->reg.if1cmask = 0xF8;
++              writeb(c->reg.if1cmask, v + IF1CMASK);
++
++              if (i == CAN_STD_RX_BUFFER_END) {
++                      c->reg.if1mcont[0] = 0x80;      /* FIFO END */
++                      writeb(c->reg.if1mcont[0], v + IF1MCONT0);
++              } else {
++                      c->reg.if1mcont[0] = 0x00;
++                      writeb(c->reg.if1mcont[0], v + IF1MCONT0);
++              }
++
++              c->reg.if1mcont[1] = 0x14;      /* this MsgObj trig. Int on Rx */
++              writeb(c->reg.if1mcont[1], v + IF1MCONT1);
++
++              c->reg.if1creq = i;
++              writeb(c->reg.if1creq, v + IF1CREQ);
++
++              while ((c->reg.if1busy = readb(v + IF1BUSY) & 0x80)) ;
++      }
++
++      /* Extended Frames */
++      c->reg.if1id[3] = 0xC0;
++      writeb(c->reg.if1id[3], v + IF1ID3);
++
++      c->reg.if1id[2] = 0x00;
++      writeb(c->reg.if1id[2], v + IF1ID2);
++
++      c->reg.if1id[1] = 0x00;
++      writeb(c->reg.if1id[1], v + IF1ID1);
++
++      c->reg.if1id[0] = 0x00;
++      writeb(c->reg.if1id[0], v + IF1ID0);
++
++      c->reg.if1mask[3] = 0x00;
++      writeb(c->reg.if1mask[3], v + IF1MASK3);
++
++      c->reg.if1mask[2] = 0x00;
++      writeb(c->reg.if1mask[2], v + IF1MASK2);
++
++      c->reg.if1mask[1] = 0x00;
++      writeb(c->reg.if1mask[1], v + IF1MASK1);
++
++      c->reg.if1mask[0] = 0x00;
++      writeb(c->reg.if1mask[0], v + IF1MASK0);
++
++      /* Transfer Control and ID bits */
++      c->reg.if1cmask = 0xF8;
++      writeb(c->reg.if1cmask, v + IF1CMASK);
++
++      c->reg.if1mcont[0] = 0x80;      /* EOB = 1 */
++      writeb(c->reg.if1mcont[0], v + IF1MCONT0);
++
++      c->reg.if1mcont[1] = 0x14;      /* this MsgObj trig. Int on Rx */
++      writeb(c->reg.if1mcont[1], v + IF1MCONT1);
++
++      c->reg.if1creq = CAN_EXT_RX_BUFFER;
++      writeb(c->reg.if1creq, v + IF1CREQ);
++
++      /* Wait till everything has been written */
++      while ((c->reg.if1busy = readb(v + IF1BUSY) & 0x80)) ;
++
++      c->reg.cancont = readl(v + CANCONT);
++      c->reg.cancont |= CONT_FLAG_IE + CONT_FLAG_SIE + CONT_FLAG_EIE;
++      writeb(c->reg.cancont, v + CANCONT);
++
++      /*End Init */
++      c->reg.cancont = readb(v + CANCONT);
++      c->reg.cancont &= ~CONT_FLAG_INIT;
++      writeb(c->reg.cancont, v + CANCONT);
++
++      /* store baudrate default 125 kBit/sec */
++      c->baudrate = (unsigned short)set_baudrate(c, 125);
++
++      /* reset overrun counter */
++      c->overrun = 0;
++}
++
++static irqreturn_t oki_irqhandler(int irq, void *dev_id, struct pt_regs *regs)
++{
++      unsigned short int_type = 0;
++      unsigned short i;
++      unsigned char stat_reg, k;
++      struct can_msg msg;
++      struct can_device *c = dev_id;
++      unsigned long v = (unsigned long)c->virt_addr_can;
++      int minor = c->minor;
++      unsigned long flags;
++      int irq_count = 0;
++
++      spin_lock_irqsave(&c->can_lock, flags);
++
++      /*
++       * read can interrupt register1,
++       * we only want to detect if it is a status interrupt!
++       */
++      int_type += (readb(v + CANINT1) << 8);
++
++      DBG_OKI(KERN_ERR, ": /dev/can%d IRQ 0x%x occured, virt addr:0x%08x\n",minor,int_type,v);
++
++      /* STATUS IRQ    */
++      if (int_type & 0x8000) {
++              c->reg.canstat = stat_reg = readb(v + CANSTAT);
++              c->reg.canstat = 0x00;
++              writeb(c->reg.canstat, v + CANSTAT);
++
++              DBG_OKI(KERN_ERR, "/dev/can%d IRQ is STATUS IRQ BSTAT is 0x%x\n",minor,stat_reg);
++
++              /*if ((stat_reg & 0xE0) == 0xE0) */
++              /* changed back to get bus off state */
++              if ((stat_reg & 0x80) == 0x80) {
++                      DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is BUS OFF\n",minor);
++                      /* set "Bus off" flag  */
++                      c->status |= CAN_STS_BUS_OFF;
++                      /* clear flag */
++                      c->status &= ~CAN_STS_TXOK;
++
++                      c->last_error_code = 10;
++              } else {
++                      /* clear "Bus off" flag  */
++                      c->status &= ~CAN_STS_BUS_OFF;
++              }
++
++              if ((stat_reg & 0x60) == 0x60) {
++                      DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS CAN_STS_WARNING %x \n",minor,(stat_reg & 0x7));
++                      c->last_error_code = (stat_reg & 0x7);
++                      /* set WARNING flag  */
++                      c->status |= CAN_STS_WARNING;
++              } else {
++                      /* clear WARNING flag  */
++                      c->status &= ~CAN_STS_WARNING;
++              }
++
++              /* TXOK */
++              if ((stat_reg & 0x08) == 0x08) {
++                      DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS TXOK\n",minor);
++
++                      /* clear error */
++                      c->last_error_code_write = 0;
++                      /* clear error --> no error  */
++                      c->last_error_code = 0;
++                      /* clear error var for debug */
++                      c->last_error_code_debug = 0;
++              }
++
++              /* ROK */
++              if ((stat_reg & 0x10) == 0x10) {
++                      DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS IRQ RXOK\n",minor);
++
++                      /* clear error --> no error  */
++                      c->last_error_code = 0;
++                      /* clear error var for debug */
++                      c->last_error_code_debug = 0;
++              }
++
++              if((c->last_error_code >= 1 && c->last_error_code <= 7) || c->last_error_code == 10){
++                      if(c->last_error_code < 10 && ((stat_reg & 0x80) == 0x80) && (c->last_error_code != c->last_error_code_debug)){
++                              c->last_error_code_debug = 10;
++                              DBG_OUT(KERN_ERR, ": /dev/can%d Error BUS OFF, do ioctl STATUS\n",minor);
++
++                      }
++
++                      if (c->last_error_code != c->last_error_code_debug) {
++                              c->last_error_code_debug = c->last_error_code;
++                              DBG_OUT(KERN_ERR, ": /dev/can%d %s\n",minor,err[c->last_error_code]);
++                      }
++
++                      if (c->last_error_code > 0) {
++                              /* switch off controller, warning state is higher than 1 */
++                              /* so CAN message has a form error or was not  */
++                              /* acknwledged by other devices or we are in bus off state */
++                              activate(c, CAN_STS_CNTRL_OFF);
++                      }
++                      goto out;
++              }
++
++              DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS IRQ END \n",minor);
++      }
++
++      /* read next IRQ */
++      /* only read can interrupt register0, we don't want detect a status interrupt here! */
++      int_type = readb(v + CANINT0);
++
++      while (int_type && (irq_count++ < OKI_CAN_MAX_IRQS)) {
++              switch (int_type) {
++              case CAN_TX_BUFFER:
++              case CAN_RTX_BUFFER:
++
++                      DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_TX_BUFFER/CAN_RTX_BUFFER IRQ 0x%x\n",minor,int_type);
++                      while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
++
++                      /* Clear Int Pnd */
++                      c->reg.if1cmask = 0x08;
++                      writeb(c->reg.if1cmask, v + IF1CMASK);
++
++                      c->reg.if1creq = (unsigned char)int_type;
++                      writeb(c->reg.if1creq, v + IF1CREQ);
++
++                      CAN_DEBUG(IF1CMASK,"CAN_TX_BUFFER/CAN_RTX_BUFFER IF1CMASK");
++                      CAN_DEBUG(IF1CREQ,"CAN_TX_BUFFER/CAN_RTX_BUFFER IF1CREQ");
++
++                      /* Wait till everything has been written */
++                      while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
++                      c->status |= CAN_STS_TXOK;
++                      c->tx_in_progress = 0;
++                      DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_TX_BUFFER/CAN_RTX_BUFFER IRQ 0x%x END\n",minor,int_type);
++                      break;
++              case CAN_STD_RX_BUFFER_START:
++              case 2:
++              case 3:
++              case 4:
++              case 5:
++              case 6:
++              case 7:
++              case 8:
++              case 9:
++              case 10:
++              case 11:
++              case CAN_STD_RX_BUFFER_END:
++                      DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_STD_RX_BUFFER_START/CAN_STD_RX_BUFFER_END IRQ 0x%x\n",minor,int_type);
++                      do {
++                              while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
++                              /* Get all unsigned chars */
++                              c->reg.if2cmask = 0x3F;
++                              writeb(c->reg.if2cmask, v + IF2CMASK);
++                              c->reg.if2creq = (unsigned char)int_type;
++                              writeb(c->reg.if2creq, v + IF2CREQ);
++
++                              /* Wait till everything has been written */
++                              while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
++                              /* is NewData set? */
++                              if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x80) {
++                                      /* Extended Frame? */
++                                      if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x40)
++                                              msg.ext = 1;
++                                      else
++                                              msg.ext = 0;
++
++                                      msg.dlc = ((c->reg.if2mcont[0] = readb(v + IF2MCONT0)) & 0x0F);
++                                      msg.id = (((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x1F) << 6);
++                                      msg.id += ((c->reg.if2id[2] = readb(v + IF2ID2)) >> 2);
++
++                                      k = (unsigned char)((msg.dlc <= 8) ? (msg.dlc) : 8);
++                                      for (i = 0; i < k; i++)
++                                              msg.data[i] = c->reg.if2data[i] = readb(v + IF2DATA0 +i);
++
++                                      /* Is MsgLost set? */
++                                      if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x40)
++                                              c->status |= CAN_STS_OVERRUN;
++                                      else
++                                              c->status &= ~CAN_STS_OVERRUN;
++                                      /* is DIR set? */
++                                      if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x20)
++                                              msg.rtr = 1;
++                                      else
++                                              msg.rtr = 0;
++                                      /* clear MsgLst */
++                                      c->reg.if2mcont[1] &= 0xBF;
++                                      writeb(c->reg.if2mcont[1], v + IF2MCONT1);
++                                      c->reg.if2cmask = 0x10;
++                                      writeb(c->reg.if2cmask, v + IF2CMASK);
++                                      c->reg.if2creq = (unsigned char)int_type;
++                                      writeb(c->reg.if2creq, v + IF2CREQ);
++
++                                      /* Wait till everything has been written */
++                                      while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
++
++                                      /* Store Data */
++                                      store_data_in_buffer(c,&msg);
++                              } else {
++                                      /* exit while loop */
++                                      break;
++                              }
++                              int_type++;
++                      }
++                      while (int_type <= CAN_STD_RX_BUFFER_END);
++                      DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_STD_RX_BUFFER_START/CAN_STD_RX_BUFFER_END IRQ 0x%x\n",minor,int_type);
++                      break;
++              /* Extended Frames */
++              case CAN_EXT_RX_BUFFER:
++                      DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_EXT_RX_BUFFER IRQ 0x%x\n",minor,int_type);
++                      while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
++                      /* Get all unsigned chars */
++                      c->reg.if2cmask = 0x3F;
++                      writeb(c->reg.if2cmask, v + IF2CMASK);
++                      c->reg.if2creq = (unsigned char)int_type;
++                      writeb(c->reg.if2creq, v + IF2CREQ);
++                      /* Wait till everything has been written */
++                      while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80) ;
++                      /* is NewData set? */
++                      if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x80) {
++                              /* Extended Frame? */
++                              if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x40)
++                                      msg.ext = 1;
++                              else
++                                      msg.ext = 0;
++
++                              msg.dlc = ((c->reg.if2mcont[0] = readb(v + IF2MCONT0)) & 0x0F);
++                              msg.id = c->reg.if2id[0] = readb(v + IF2ID0);
++                              msg.id += ((c->reg.if2id[1] = readb(v + IF2ID1)) << 8);
++                              msg.id += ((c->reg.if2id[2] = readb(v + IF2ID2)) << 16);
++                              msg.id += (((c->reg.if2id[3] = readb(v + IF2ID2)) & 0x1F) << 24);
++
++                              k = (unsigned char)((msg.dlc <= 8) ? (msg.dlc) : 8);
++                              for (i = 0; i < k; i++)
++                                      msg.data[i] = c->reg.if2data[i] = readb(v + IF2DATA0 + i);
++                              /* Is MsgLost set? */
++                              if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x40)
++                                      c->status |= CAN_STS_OVERRUN;
++                              else
++                                      c->status &= ~CAN_STS_OVERRUN;
++
++                              /* clear MsgLst */
++                              c->reg.if2mcont[1] &= 0xBF;
++                              writeb(c->reg.if2mcont[1], v + IF2MCONT1);
++                              c->reg.if2cmask = 0x10;
++                              writeb(c->reg.if2cmask, v + IF2CMASK);
++                              c->reg.if2creq = (unsigned char)int_type;
++                              writeb(c->reg.if2creq, v + IF2CREQ);
++
++                              /* Wait till everything has been written */
++                              while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
++                              /* Store Data */
++                              store_data_in_buffer(c, &msg);
++                      }
++              DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_EXT_RX_BUFFER IRQ 0x%x\n",minor,int_type);
++              break;
++              default:
++              DBG_OKI(KERN_ERR, " /dev/can%d IRQ is default 0x%x\n",minor,int_type);
++              goto out;
++              break;
++              }
++              /* read next IRQ */
++              /* only read can interrupt register0, we don't want detect a status interrupt here! */
++              int_type = readb(v + CANINT0);
++      }                       /* while */
++out:
++      spin_unlock_irqrestore(&c->can_lock, flags);
++      return IRQ_HANDLED;
++}
++
++static struct file_operations oki_fops = {
++      .owner = THIS_MODULE,
++      .read = oki_read,
++      .write = oki_write,
++      .ioctl = oki_ioctl,
++      .open = oki_open,
++      .release = oki_release,
++      .poll = oki_poll,
++};
++
++int oki_read(struct file *file, char *buf, size_t count, loff_t * ppos)
++{
++      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
++      struct can_device *c = info_can[minor];
++      int ret = 0;
++      int i, tmp;
++
++      if (count < sizeof(struct can_msg))
++              return -EINVAL;
++
++      if ((c->head == c->tail) && (file->f_flags & O_NONBLOCK))
++              return  -EAGAIN;
++              
++      ret = wait_event_interruptible(c->rx_waitq, c->head != c->tail);
++      if (ret)
++              return -ERESTARTSYS;
++
++      for (i = 0; i < (count / sizeof(struct can_msg)); i++) {
++              if (c->head == c->tail)
++                      break;
++
++              tmp = copy_to_user(buf, &c->head->msg, sizeof(struct can_msg));
++              if (tmp > 0) {
++                      printk("copy_to_user could not copy %d bytes", ret);
++                      ret = -EIO;
++              } else {
++                      buf += sizeof(struct can_msg);
++                      ret += sizeof(struct can_msg);
++              }
++
++              c->head = c->head->next;
++              kfree(c->head->prev);
++      }
++
++      return ret;
++}
++
++int oki_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
++{
++      unsigned char i;        /* counter, temp var */
++      unsigned char k;        /* counter */
++      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
++      struct can_device *c = info_can[minor];
++      unsigned long v = (unsigned long)c->virt_addr_can;
++      struct can_msg tmp;
++      struct can_msg *txbuf = &tmp;
++
++      if (!buf || !count)
++              return 0;
++
++      /* be stricter than in read here, require multiples of whole msgs */
++      if (count % sizeof(struct can_msg)) {
++              printk("count must be N * sizeof(struct can_msg)!\n");
++              return -EINVAL;
++      }
++
++      /*
++       * This can be removed as soon as we have implemented support for
++       * writing multiple messages
++       */
++      if (count != sizeof(struct can_msg)) {
++              printk("FIXME: support writing multiple messages at once!\n");
++              return -EINVAL;
++      }
++
++      if (0 != copy_from_user(txbuf, buf, count)) {
++              printk("%s: Error: copy from user failed!\n", __FUNCTION__);
++              return -EIO;
++      }
++
++      DBG_OKI(KERN_ERR, ": WRITE minor %d\n", c->minor);
++      DBG_OKI(KERN_ERR, ": WRITE virt 0x%x\n", c->virt_addr_can);
++      DBG_OKI(KERN_ERR, ": WRITE id %d\n", txbuf->id);
++      DBG_OKI(KERN_ERR, ": WRITE dlc %d\n", txbuf->dlc);
++      DBG_OKI(KERN_ERR, ": WRITE rtr %d\n", txbuf->rtr);
++      DBG_OKI(KERN_ERR, ": WRITE ext %d\n", txbuf->ext);
++      for (i = 0; i < 8; i++)
++              DBG_OKI(KERN_ERR, ": WRITE data[%d] %d\n", i, txbuf->data[i]);
++
++      c->reg.cancont = readb(v + CANCONT);
++
++      CAN_DEBUG(CANCONT, "CANCONT");
++
++      if ((c->reg.cancont & CONT_FLAG_INIT) == CONT_FLAG_INIT) {
++              if (c->last_error_code_write < 1) {
++                      c->last_error_code_write = 1;
++                      DBG_OUT(KERN_ERR, ": /dev/can%d not initalised or switched off, do ioctl: COMMAND CAN_STS_CNTRL_ON \n",minor );
++              }
++              return -EAGAIN;
++      }
++
++      /* Check the status, so we can handle warning and bus off state */
++      check_status(c);
++
++      if (c->status == CAN_STS_WARNING) {
++              if (c->last_error_code_write < 2) {
++                      c->last_error_code_write = 2;
++                      DBG_OUT(KERN_ERR, ": /dev/can%d is in WARNING State, do ioctl STATUS\n",minor );
++              }
++              return -EAGAIN;
++      }
++
++      if (c->status == CAN_STS_BUS_OFF) {
++              if (c->last_error_code_write < 3) {
++                      c->last_error_code_write = 3;
++                      DBG_OUT(KERN_ERR, ": /dev/can%d is in BUS OFF State, do ioctl STATUS\n",minor );
++              }
++              return -EAGAIN;
++      }
++
++      c->status &= ~CAN_STS_TXOK;
++
++      /* Wait till everything has been written */
++      if (c->tx_in_progress) {
++              DBG_OKI(KERN_ERR, ": WRITE CAN%d BUSY\n", minor);
++              return -EBUSY;
++      } else {
++              c->tx_in_progress = 1;
++              CAN_DEBUG(IF1BUSY, " WRITE 2 for while IF1BUSY");
++              while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
++
++              /* set, so that ID Register will get transfered */
++              c->reg.if1cmask = 0xB7;
++              writeb(c->reg.if1cmask, v + IF1CMASK);
++              CAN_DEBUG(IF1CMASK, " WRITE 3 for while  IF1CMASK");
++      }
++
++      if (txbuf->ext == 0) {
++              /* DIR and WR */
++              c->reg.if1id[3] = 0xA0;
++              c->reg.if1id[3] |= (unsigned char)((txbuf->id >> 6) & 0x1F);
++              DBG_OKI(KERN_ERR, "WRITE c->reg.if1id[3] 0x%x\n",c->reg.if1id[3]);
++              writeb(c->reg.if1id[3], v + IF1ID3);
++              CAN_DEBUG(IF1ID3, " WRITE 4  IF1ID3");
++              c->reg.if1id[2] = (unsigned char)((txbuf->id << 2) & 0xFC);
++              DBG_OKI(KERN_ERR, "WRITE c->reg.if1id[2] 0x%x\n",c->reg.if1id[2]);
++              writeb(c->reg.if1id[2], v + IF1ID2);
++              CAN_DEBUG(IF1ID2, "WRITE 4  IF1ID2");
++      } else {
++              /* extended Frame */
++              c->reg.if1id[3] = 0xE0;
++              c->reg.if1id[3] += (unsigned char)((txbuf->id >> 24) & 0x1F);
++              c->reg.if1id[2] = (unsigned char)((txbuf->id >> 16) & 0xFF);
++              c->reg.if1id[1] = (unsigned char)((txbuf->id >> 8) & 0xFF);
++              c->reg.if1id[0] = (unsigned char)(txbuf->id & 0xFF);
++              writeb(c->reg.if1id[3], v + IF1ID3);
++              CAN_DEBUG(IF1ID3, "WRITE 4 IF1ID3");
++              writeb(c->reg.if1id[2], v + IF1ID2);
++              CAN_DEBUG(IF1ID2, "WRITE 4 IF1ID2");
++              writeb(c->reg.if1id[1], v + IF1ID1);
++              CAN_DEBUG(IF1ID1, "WRITE 4 IF1ID1");
++              writeb(c->reg.if1id[0], v + IF1ID0);
++              CAN_DEBUG(IF1ID1, "WRITE 4 IF1ID1");
++      }
++
++      k = (unsigned char)(((txbuf->dlc) <= 8) ? (txbuf->dlc) : 8);
++      for (i = 0; i < k; i++) {
++              c->reg.if1data[i] = txbuf->data[i];
++              writeb(c->reg.if1data[i], v + IF1DATA0 + i);
++              DBG_OKI(KERN_ERR, ": WRITE in for data[%d] %d\n",i,txbuf->data[i]);
++              CAN_DEBUG(IF1DATA0 + i, "WRITE 4   IF1DATA0 + i");
++      }
++      /* End of Buffer (EOB) */
++
++      c->reg.if1mcont[0] = 0x80 + (txbuf->dlc & 0x0F);
++      DBG_OKI(KERN_ERR, ": WRITE 5 if1mcont[0] 0x%x\n", c->reg.if1mcont[0]);
++      writeb(c->reg.if1mcont[0], v + IF1MCONT0);
++      CAN_DEBUG(IF1MCONT0, "WRITE 5   IF1MCONT0");
++
++      if (txbuf->rtr == 1) {
++              c->reg.if1id[3] &= 0xDF;
++              DBG_OKI(KERN_ERR, ": WRITE 6 if1id[3] 0x%x\n", c->reg.if1id[3]);
++              writeb(c->reg.if1id[3], v + IF1ID3);
++              CAN_DEBUG(IF1ID3, "WRITE 6   IF1ID3");
++              /* TXIE, TXRqst and RXIE */
++              c->reg.if1mcont[1] = 0x0D;
++              DBG_OKI(KERN_ERR, ": WRITE 6 if1mcont[1] 0x%x\n",c->reg.if1mcont[1]);
++              writeb(c->reg.if1mcont[1], v + IF1MCONT1);
++              CAN_DEBUG(IF1MCONT1, "WRITE 6   IF1MCONT1");
++              c->reg.if1creq = CAN_RTX_BUFFER;
++              DBG_OKI(KERN_ERR, ": WRITE 6 if1creq  0x%x\n", c->reg.if1creq);
++              writeb(c->reg.if1creq, v + IF1CREQ);
++              CAN_DEBUG(IF1CREQ, "WRITE 6   IF1CREQ");
++      } else {
++              c->reg.if1mcont[1] = 0x09;
++              DBG_OKI(KERN_ERR, ": WRITE 6 if1mcont[1] 0x%x\n",c->reg.if1mcont[1]);
++              writeb(c->reg.if1mcont[1], v + IF1MCONT1);
++              CAN_DEBUG(IF1MCONT1, "WRITE 6   IF1MCONT1");
++              c->reg.if1creq = CAN_TX_BUFFER;
++              DBG_OKI(KERN_ERR, ": WRITE 6 if1creq  0x%x\n", c->reg.if1creq);
++              writeb(c->reg.if1creq, v + IF1CREQ);
++              CAN_DEBUG(IF1CREQ, "WRITE 6   IF1CREQ");
++      }
++      return count;
++}
++
++int oki_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++      unsigned int minor = iminor(inode);
++      struct can_device *c = info_can[minor]; /* better ideas than using globals anyone? */
++      int ret = -ENOIOCTLCMD;
++      int new_options = 0;
++      void __user *argp = (void __user *)arg;
++      int __user *p = argp;
++      int cntr_ret;
++
++      switch (cmd) {
++      case COMMAND:
++              {
++                      if (get_user(new_options, p) != 0)
++                              return -EFAULT;
++
++                      DBG_OKI(KERN_ERR, ": IOCTL COMMAND WITH %d\n", new_options);
++                      cntr_ret = activate(c, new_options);
++                      if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0)
++                              return 0;
++                      else
++                              return ret;
++
++                      break;
++              }
++      case CONFIG:
++              {
++                      if (get_user(new_options, p) != 0)
++                              return -EFAULT;
++
++                      cntr_ret = set_baudrate(c, new_options);
++                      if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0)
++                              return 0;
++                      else
++                              return ret;
++
++                      break;
++              }
++      case SEND:
++              break;
++      case RECEIVE:
++              break;
++      case STATUS:
++              {
++                      int cntr_ret;
++                      /* Check status */
++                      cntr_ret = check_status(c);
++                      if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0)
++                              return 0;
++                      else
++                              return ret;
++                      break;
++              }
++      default:
++              return -ENOIOCTLCMD;
++              break;
++      }
++
++      return -ENOIOCTLCMD;
++}
++
++static unsigned int oki_poll(struct file *file, poll_table * wait)
++{
++      unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
++      struct can_device *c = info_can[minor];
++        unsigned int mask = 0;
++
++      poll_wait(file, &c->rx_waitq, wait);
++      if (c->head != c->tail)
++              mask |= POLLIN | POLLRDNORM;
++      return mask;
++}
++
++int check_status(struct can_device *c)
++{
++      int stat_reg;
++      unsigned long v = (unsigned long)c->virt_addr_can;
++
++      stat_reg = readb(v + CANSTAT);
++      DBG_OKI(KERN_DEBUG, "check_status canstat 0x%x\n", stat_reg);
++
++      /* Bus is in "Error Passive" state */
++      if ((stat_reg & 0x20) == 0) {
++              c->status &= ~CAN_STS_WARNING;
++              c->status &= ~CAN_STS_BUS_OFF;
++      }
++
++      if ((stat_reg & 0x60) == 0x60) {
++              if (c->last_error_code != (stat_reg & 0x7)) {
++                      c->last_error_code = (stat_reg & 0x7);
++              }
++              c->status |= CAN_STS_WARNING;
++      }
++
++      if ((stat_reg & 0x80) == 0x80) {
++              if (c->last_error_code < 10) {
++                      c->last_error_code = 10;
++              }
++              c->status |= CAN_STS_BUS_OFF;
++      }
++
++      /* clear overrun  */
++      c->status &= ~CAN_STS_OVERRUN;
++      return c->status;
++}
++
++int activate(struct can_device *c, unsigned char new_status)
++{
++      unsigned long v = (unsigned long)c->virt_addr_can;
++
++      switch (new_status) {
++      case CAN_STS_CNTRL_OFF:
++              do {
++                      c->reg.cancont |= CONT_FLAG_INIT;
++                      writeb(c->reg.cancont, v + CANCONT);
++              }
++              while (!((c->reg.cancont = readb(v + CANCONT)) & CONT_FLAG_INIT));
++
++              c->status |= CAN_STS_RESET;
++
++              DBG_OKI(KERN_DEBUG, " /dev/can%d activate CAN_STS_CNTRL_OFF CANCONT 0x%x\n",c->minor,c->reg.cancont);
++              break;
++      case CAN_STS_CNTRL_ON:
++              do {
++                      c->reg.cancont &= ~CONT_FLAG_INIT;
++                      writeb(c->reg.cancont, v + CANCONT);
++              }
++              while (((c->reg.cancont = readb(v + CANCONT)) & CONT_FLAG_INIT));
++
++              c->status &= ~CAN_STS_RESET;
++
++              DBG_OKI(KERN_DEBUG, " /dev/can%d activate CAN_STS_CNTRL_ON CANCONT 0x%x\n",c->minor,c->reg.cancont);
++              break;
++      case CAN_STS_CNTRL_SLEEP:
++              break;
++      case CAN_STS_CNTRL_AWAKE:
++              break;
++      default:
++              break;
++      }
++
++      return c->status;
++}
++
++int oki_open(struct inode *inode, struct file *file)
++{
++      unsigned int minor = iminor(inode);
++      struct can_device *c = info_can[minor]; /* better ideas than using globals anyone? */
++
++      if (!atomic_dec_and_test(&c->can_opened)) {
++              DBG_OUT(KERN_ERR, ": /dev/can%d already opened.\n", minor);
++              atomic_inc(&c->can_opened);
++              return -EBUSY;
++      }
++      return 0;
++}
++
++int oki_release(struct inode *inode, struct file *file)
++{
++      unsigned int minor = iminor(inode);
++      struct can_device *c = info_can[minor]; /* better ideas than using globals anyone? */
++
++      atomic_dec(&c->can_opened);
++      if (!atomic_inc_and_test(&c->can_opened)) {
++              DBG_OUT(KERN_ERR, ": /dev/can%d open, busy.\n", minor);
++              return -EBUSY;
++      }
++
++      atomic_inc(&c->can_opened);
++      return 0;
++}
++
++int can_register(struct can_device *c)
++{
++      atomic_set(&c->can_opened, 1);
++
++      /* map memory */
++      c->virt_addr_can = ioremap(c->phys_addr_can, c->phys_size_can);
++      if (!c->virt_addr_can) {
++              DBG_OUT(KERN_ERR, ": Unable to remap /dev/can%d memory.\n", c->minor);
++              return -ENOMEM;
++      }
++
++      DBG_OUT(KERN_INFO, ": remap /dev/can%d memory physical 0x%x to virtual 0x%x.\n",c->minor,c->phys_addr_can,c->virt_addr_can);
++
++      /* Message buffers */
++      c->tail = kzalloc(sizeof(struct recbuf), GFP_KERNEL);
++      c->head = c->tail;
++
++      /* CAN init */
++      hw_init(c);
++
++      /* waitq init */
++      init_waitqueue_head(&c->rx_waitq);
++
++      /* Install IRQ handler */
++      if(0 != request_irq(c->irq, oki_irqhandler, c->irq_flags, "OKI_CAN", (void *)c)){
++              DBG_OUT(KERN_ERR, ": /dev/can%d cannot install IRQ-handler\n",c->minor);
++              return -ENOMEM;
++      }
++
++      DBG_OUT(KERN_INFO, ": /dev/can%d IRQ-handler installed.\n", c->minor);
++
++      return 0;
++}
++
++int __init oki_init(void)
++{
++      can_register(info_can[0]);
++#ifdef CONFIG_OKI_CAN_ML9620_2DEV
++      can_register(info_can[1]);
++#endif
++
++      /* Register char device */
++      if (register_chrdev(OKI_CAN_CHAR_MAJOR, OKI_CAN_DEVICE_NAME, &oki_fops)) {
++              DBG_OUT(KERN_ERR, "Can't allocate major number %d for CAN driver.\n",OKI_CAN_CHAR_MAJOR);
++              return -EIO;
++      }
++
++      DBG_OUT(KERN_INFO, ": Version: " OKI_CAN_VERSION " registered successfully.\n");
++      /*DBG_OUT(KERN_INFO, "Installed %d IRQ handlers for %d CAN devices.\n",irq_nr,can_dev); */
++
++      printk(KERN_INFO "Contec Steuerungstechnik und Automation Ges.m.b.H\n");
++      printk(KERN_INFO "Waldeck 1 / 6330 Kufstein / Austria\n");
++
++      return 0;
++}
++
++module_init(oki_init);
++
++void unregister_can(struct can_device *c)
++{
++      DBG_OUT(KERN_INFO, ": unregister /dev/can%d  .\n", c->minor);
++      free_irq(c->irq, (void *)c);
++
++      if (c->virt_addr_can != NULL) {
++              iounmap(c->virt_addr_can);
++      } else {
++              DBG_OUT(KERN_ERR, ": /dev/can%d was not mapped, skipping iounmap!\n", c->minor);
++      }
++}
++
++void __exit oki_exit(void)
++{
++      unregister_can(info_can[0]);
++#ifdef CONFIG_OKI_CAN_ML9620_2DEV
++      unregister_can(info_can[1]);
++#endif
++      unregister_chrdev(OKI_CAN_CHAR_MAJOR, OKI_CAN_DEVICE_NAME);
++}
++
++module_exit(oki_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Manfred Gruber <manfred.gruber@contec.at>");
++MODULE_DESCRIPTION("OKI ML9620 CAN Driver");
+diff --git a/drivers/char/can/oki_ml9620.h b/drivers/char/can/oki_ml9620.h
+new file mode 100644
+index 0000000..f8ece1e
+--- /dev/null
++++ b/drivers/char/can/oki_ml9620.h
+@@ -0,0 +1,397 @@
++/*
++ * drivers/char/can/oki_ml9620_core.h
++ *
++ * OKI ML9620 CAN Controler driver
++ *
++ * Author: Manfred Gruber <manfred.gruber@contec.at>
++ *
++ * Copyright 2004 (c) Manfred Gruber
++ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H
++ * Kufstein/Austria   www.contec.at
++ *
++ * This driver was written for Contec Hypercontrol Micro9 Board:
++ * 1. CAN Controller is on Hypercontrol Micro9 CPU board
++ * 2. CAN Controller is on Hypercontrol Micro9 Eval board
++ *
++ * Contec uses this driver on their Hypercontrol Micro9 boards based on
++ * Cirrus Logic EP93XX,we have changed Adr-/Databus timinig to use OKI ML9620.
++ *
++ * This file is licensed under  the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ *
++ */
++
++#ifndef _OKI_ML9620_CORE_H_
++#define _OKI_ML9620_CORE_H_
++
++#include <linux/can/oki_ml9620_ctrl.h>
++#include <linux/kernel.h>
++
++#define OKI_CAN_CHAR_MAJOR    91
++#define OKI_CAN_DEVICE_NAME   "oki_ml9260"
++#define OKI_CAN_VERSION       "0.08"
++
++#define OKI_CAN_MAX_IRQS      20
++#define PHYS_SIZE_CAN 0x00000100
++
++/* Contec */
++#ifdef CONFIG_OKI_CAN_ML9620_MICRO9
++#define CAN_CLOCK_8MHZ
++#define PHYS_ADDR_CAN0 0x20000000
++#define PHYS_ADDR_CAN1 0x21000000
++#define IRQ_CAN0 GPIO_IRQ4
++#define IRQ_CAN1 GPIO_IRQ10
++#ifdef CONFIG_GENERIC_HARDIRQS
++#define IRQ_FLAGS_CAN0 (SA_INTERRUPT)
++#define IRQ_FLAGS_CAN1 (SA_INTERRUPT)
++#else
++#define IRQ_FLAGS_CAN0 (SA_INTERRUPT | SA_SHIRQ)
++#define IRQ_FLAGS_CAN1 (SA_INTERRUPT | SA_SHIRQ)
++#endif
++#endif                                /* CONFIG_OKI_CAN_ML9620_MICRO9 */
++
++/* Gassner */
++#ifdef CONFIG_OKI_CAN_ML9620_GASSNER
++#define CAN_CLOCK_8MHZ
++#define PHYS_ADDR_CAN0 0x10000000
++#define PHYS_ADDR_CAN1 0x30000000
++#define IRQ_CAN0 GPIO_IRQ6    /* Line EGPIO6 (multiplexed) */
++#define IRQ_CAN1 GPIO_IRQ13   /* Line EGPIO13 (multiplexed) */
++#define IRQ_FLAGS_CAN0 (SA_INTERRUPT | SA_SHIRQ)
++#define IRQ_FLAGS_CAN1 (SA_INTERRUPT | SA_SHIRQ)
++#endif                                /* CONFIG_OKI_CAN_ML9620_GASSNER */
++
++char *err[7] = {
++      "Warning 1, Stuff Error",
++      "Warning 2, Form Error",
++      "Warning 3, ACK Error",
++      "Warning 4, Bits 1 Error",
++      "Warning 5, Bits 0 Error",
++      "Warning 6, CRC Error",
++      "Warning 7, MCU has produced this Error",
++};
++
++#define DRIVER_MAX_MINOR 2
++
++struct CANML9620REG {
++      unsigned char cancont;
++      unsigned char reserve1;
++      unsigned char canstat;
++      unsigned char reserve2;
++      unsigned char cantxerrc;
++      unsigned char canrxerrc;
++      unsigned char canbitt[2];
++      unsigned char canint[2];
++      unsigned char canopt;
++      unsigned char reserve3;
++      unsigned char canbpre;
++      unsigned char reserve4[3];
++
++      unsigned char if1creq;
++      unsigned char if1busy;
++      unsigned char if1cmask;
++      unsigned char reserve5;
++      unsigned char if1mask[4];
++      unsigned char if1id[4];
++      unsigned char if1mcont[2];
++      unsigned char if1data[8];
++      unsigned char reserve6[26];
++
++      unsigned char if2creq;
++      unsigned char if2busy;
++      unsigned char if2cmask;
++      unsigned char reserve7;
++      unsigned char if2mask[4];
++      unsigned char if2id[4];
++      unsigned char if2mcont[2];
++      unsigned char if2data[8];
++      unsigned char reserve8[42];
++
++      unsigned char cantreq[4];
++      unsigned char reserve9[12];
++
++      unsigned char canndata[4];
++      unsigned char reserve10[12];
++
++      unsigned char canipend[4];
++      unsigned char reserve11[12];
++
++      unsigned char canmval[4];
++      unsigned char reserve12[12];
++
++      unsigned char canstby;
++      unsigned char reserve13[12];
++};
++
++#define CANCONT       0x0
++#define RESERVE1      0x1
++#define CANSTAT       0x2
++#define RESERVE2      0x3
++#define CANTXERRC     0x4
++#define CANRXERRC     0x5
++#define CANBITT0      0x6
++#define CANBITT1      0x7
++#define CANINT0       0x8
++#define CANINT1       0x9
++#define CANOPT        0xA
++
++#define CANBPRE       0xC
++
++#define IF1CREQ       0x10
++#define IF1BUSY       0x11
++#define IF1CMASK      0x12
++
++#define IF1MASK0      0x14
++#define IF1MASK1      0x15
++#define IF1MASK2      0x16
++#define IF1MASK3      0x17
++
++#define IF1ID0        0x18
++#define IF1ID1        0x19
++#define IF1ID2        0x1A
++#define IF1ID3        0x1B
++
++#define IF1MCONT0     0x1C
++#define IF1MCONT1     0x1D
++
++#define IF1DATA0      0x1E
++#define IF1DATA1      0x1F
++#define IF1DATA2      0x20
++#define IF1DATA3      0x21
++#define IF1DATA4      0x22
++#define IF1DATA5      0x23
++#define IF1DATA6      0x24
++#define IF1DATA7      0x25
++
++#define IF2CREQ       0x40
++#define IF2BUSY       0x41
++#define IF2CMASK      0x42
++
++#define IF2MASK0      0x44
++#define IF2MASK1      0x45
++#define IF2MASK2      0x46
++#define IF2MASK3      0x47
++
++#define IF2ID0        0x48
++#define IF2ID1        0x49
++#define IF2ID2        0x4A
++#define IF2ID3        0x4B
++
++#define IF2MCONT0     0x4C
++#define IF2MCONT1     0x4D
++
++#define IF2DATA0      0x4E
++#define IF2DATA1      0x4F
++#define IF2DATA2      0x50
++#define IF2DATA3      0x51
++#define IF2DATA4      0x52
++#define IF2DATA5      0x53
++#define IF2DATA6      0x54
++#define IF2DATA7      0x55
++
++#define CANTREQ0      0x80
++#define CANTREQ1      0x81
++#define CANTREQ2      0x82
++#define CANTREQ3      0x83
++
++#define CANNDATA0     0x90
++#define CANNDATA1     0x91
++#define CANNDATA2     0x92
++#define CANNDATA3     0x93
++
++#define CANIPEND0     0xA0
++#define CANIPEND1     0xA1
++#define CANIPEND2     0xA2
++#define CANIPEND3     0xA3
++
++#define CANMVAL0      0xB0
++#define CANMVAL1      0xB1
++#define CANMVAL2      0xB2
++#define CANMVAL3      0xB3
++
++#define CANSTBY       0xC0
++struct recbuf {
++      struct can_msg msg;
++      struct recbuf *next;
++      struct recbuf *prev;
++};
++
++struct can_device {
++      /* Phys addresses and size */
++      unsigned long phys_addr_can;
++      unsigned long phys_size_can;
++      /* IRQ */
++      unsigned int irq;
++      unsigned long irq_flags;
++
++      /* Device node */
++      int minor;
++
++      /* waitqueue for read, poll */
++      wait_queue_head_t rx_waitq;
++
++      atomic_t can_opened;
++
++      struct recbuf *tail;
++      struct recbuf *head;
++
++      /* Virt addresses size */
++      unsigned char __iomem *virt_addr_can;
++
++      /*  CAN-Baustein */
++      struct CANML9620REG reg;
++      unsigned short baudrate;        /* baudrate */
++      unsigned short overrun; /* overrun counter */
++      struct can_msg msg;     /* CAN message buffer */
++      int status;             /* actual CAN status  */
++      int last_error_code_write;
++      unsigned char tx_in_progress;
++      unsigned char last_error_code;  /* LEC */
++      unsigned char last_error_code_debug;    /* LEC when printed out */
++      spinlock_t can_lock;
++};
++
++/* Global Device Struct can0 */
++static struct can_device info_can0 = {
++      .phys_addr_can = PHYS_ADDR_CAN0,
++      .phys_size_can = PHYS_SIZE_CAN,
++      .irq = IRQ_CAN0,
++      .minor = 0,
++      .irq_flags = IRQ_FLAGS_CAN0,
++      .can_opened = ATOMIC_INIT(1),
++      .status = CAN_STS_NORMAL,
++};
++
++/* Global Device Struct can1 */
++static struct can_device info_can1 = {
++      .phys_addr_can = PHYS_ADDR_CAN1,
++      .phys_size_can = PHYS_SIZE_CAN,
++      .irq = IRQ_CAN1,
++      .irq_flags = IRQ_FLAGS_CAN1,
++      .minor = 1,
++      .can_opened = ATOMIC_INIT(1),
++      .status = CAN_STS_NORMAL,
++};
++
++static struct can_device *info_can[] = { &info_can0, &info_can1 };
++
++#define NUM_MSG                       32
++
++#define CONT_FLAG_INIT                0x01
++#define CONT_FLAG_IE          0x02
++#define CONT_FLAG_SIE         0x04
++#define CONT_FLAG_EIE         0x08
++#define CONT_FLAG_CCE         0x40
++
++/* message buffers */
++
++#define CAN_STD_RX_BUFFER_START  1    /* CAN standard receive buffer */
++#define CAN_STD_RX_BUFFER_END    12   /* CAN standard receive buffer */
++#define CAN_EXT_RX_BUFFER        13   /* CAN extended receive buffer */
++
++#define CAN_TX_BUFFER          14     /* CAN transmit buffer         */
++#define CAN_RTX_BUFFER         15     /* CAN remote frame transmit buffer */
++
++struct ML9620BDRATE {
++      unsigned char btiming0;
++      unsigned char btiming1;
++      unsigned char bpre;
++};
++
++const struct ML9620BDRATE bd_tbl[9] = {
++#ifdef CAN_CLOCK_16MHZ
++/* for 16 Mhz Quarz                */
++/* bus timing 0  | bus timing 1    */
++/* SJW PRESCALER | SAM TSEG1 TSEG2 */
++      {0x23, 0x1C},           /*  10K bit/s */
++      {0x31, 0x1C},           /*  20K bit/s */
++      {0x13, 0x1C},           /*  50K bit/s */
++      {0x09, 0x1C},           /* 100K bit/s */
++      {0x07, 0x1C},           /* 125K bit/s */
++      {0x03, 0x1C},           /* 250K bit/s */
++      {0x01, 0x1C},           /* 500K bit/s */
++      {0x01, 0x16},           /* 800K bit/s */
++      {0x01, 0x14}            /*   1M bit/s */
++#endif
++#ifdef CAN_CLOCK_8MHZ
++/* for 8 Mhz Quarz                */
++/* bus timing 0  | bus timing 1    */
++/* SJW PRESCALER | SAM TSEG1 TSEG2 | CANBRPE */
++      {0x31, 0x1C, 0x01},     /*  10K bit/s           */
++      {0x18, 0x1C, 0x00},     /*  20K bit/s           */
++      {0x09, 0x1C, 0x00},     /*  50K bit/s           */
++      {0x04, 0x1C, 0x00},     /* 100K bit/s           */
++      {0x03, 0x1C, 0x00},     /* 125K bit/s           */
++      {0x01, 0x1C, 0x00},     /* 250K bit/s           */
++      {0x00, 0x1C, 0x00},     /* 500K bit/s           */
++      {0x00, 0x16, 0x00},     /* 800K bit/s           */
++      {0x00, 0x14, 0x00}      /*   1M bit/s           */
++#endif
++};
++
++/* DEBUG STUFF */
++
++#ifdef OKI_DEBUG
++#define CAN_DEBUG(REG,string)                                                 \
++{                                                                     \
++      DBG_OUT(KERN_ERR, " %s 0x%x\n",string,readb(v+REG));            \
++}
++#else
++#define CAN_DEBUG(REG,string)
++#endif
++
++#ifdef OKI_DEBUG
++#define DBG_OKI DBG_OUT
++#else
++#define DBG_OKI(...)
++#endif
++
++int drv_dbg = 7;
++
++void DBG_OUT(const char *type, const char *dbg_msg, ...)
++{
++      va_list ap;
++      char buf[1024];
++      int len;
++      unsigned int level;
++
++      va_start(ap, dbg_msg);
++      len = vsprintf(buf, dbg_msg, ap);
++      va_end(ap);
++      buf[len] = '\0';
++
++      if (0 == sscanf(type, "<%i>", &level))
++              printk(KERN_ALERT "%s", buf);
++
++      if (level > drv_dbg)
++              return;
++
++      switch (level) {
++      case 0:
++              printk(KERN_EMERG OKI_CAN_DEVICE_NAME "EMERG: %s", buf);
++              break;
++      case 1:
++              printk(KERN_ALERT OKI_CAN_DEVICE_NAME "%s", buf);
++              break;
++      case 2:
++              printk(KERN_CRIT OKI_CAN_DEVICE_NAME "%s", buf);
++              break;
++      case 3:
++              printk(KERN_ERR OKI_CAN_DEVICE_NAME "%s", buf);
++              break;
++      case 4:
++              printk(KERN_WARNING OKI_CAN_DEVICE_NAME "%s", buf);
++              break;
++      case 5:
++              printk(KERN_NOTICE OKI_CAN_DEVICE_NAME "%s", buf);
++              break;
++      case 6:
++              printk(KERN_INFO OKI_CAN_DEVICE_NAME "%s", buf);
++              break;
++      case 7:
++              printk(KERN_DEBUG OKI_CAN_DEVICE_NAME "%s", buf);
++              break;
++      }
++}
++#endif                                /* _OKI_ML9620_CORE_H_ */
+diff --git a/drivers/char/ds1337glue.c b/drivers/char/ds1337glue.c
+new file mode 100644
+index 0000000..c7d168b
+--- /dev/null
++++ b/drivers/char/ds1337glue.c
+@@ -0,0 +1,69 @@
++/*
++ *  linux/arch/arm/mach-ep93xx/ds1337glue.c
++ *
++ *  Copyright (C) 2005 Michael Burian
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * /dev/rtc interface for Dallas Semiconductor DS133[79]RTC I2C driver
++ *
++ * Also see "drivers/i2c/chips/ds1337.c"
++ *
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/rtc.h>
++#include <linux/miscdevice.h>
++#include <linux/poll.h>
++
++#include <asm/rtc.h>
++
++/* FIXME BEGIN: include this from "ds1337.h" as soon as there exists one */
++#warning FIXME: no official ds1337 interface available, hardcoding defaults.
++#define DS1337_GET_DATE         0
++#define DS1337_SET_DATE         1
++extern int ds1337_do_command(int bus, int cmd, void *arg);
++/* FIXME END */
++
++static int rtc_read_time(struct rtc_time *tm)
++{
++      return ds1337_do_command(0, DS1337_GET_DATE, (void*)(tm));
++}
++
++static int rtc_set_time(struct rtc_time *tm)
++{
++      return ds1337_do_command(0, DS1337_SET_DATE, (void*)(tm));
++}
++
++static struct rtc_ops dma03_rtc_ops = {
++      .owner = THIS_MODULE,
++      .read_time = rtc_read_time,
++      .set_time = rtc_set_time,
++};
++
++static int __init rtc_interface_init(void)
++{
++      int err;
++      printk(KERN_INFO "registering /dev/rtc interface for DS133[79]\n");
++
++      err = register_rtc(&dma03_rtc_ops);
++      if(err)
++              printk(KERN_ERR "could not register DS1337 /dev/rtc interface:"
++                                                      " error=%d!\n",err);
++
++      return err;
++}
++
++static void __exit rtc_interface_exit(void)
++{
++      unregister_rtc(&dma03_rtc_ops);
++}
++
++MODULE_AUTHOR("Michael Burian");
++MODULE_DESCRIPTION("/dev/rtc interface for ds1337.c");
++MODULE_LICENSE("GPL");
++
++module_init(rtc_interface_init);
++module_exit(rtc_interface_exit);
+diff --git a/drivers/char/ep93xx-rtc.c b/drivers/char/ep93xx-rtc.c
+new file mode 100644
+index 0000000..399d0b0
+--- /dev/null
++++ b/drivers/char/ep93xx-rtc.c
+@@ -0,0 +1,376 @@
++/*
++ *      Real Time Clock for Cirrus EP93xx
++ *
++ *      Copyright (C) 2004 Ray Lehtiniemi
++ *
++ *      Support for realtime clock device on the Cirrus
++ *      EP93xx family of devices.
++ *
++ *      Based on rtc.c, and other rtc drivers.
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/sysctl.h>
++#include <linux/rtc.h>
++#include <linux/poll.h>
++#include <linux/miscdevice.h>
++
++#include <asm/io.h>
++#include <asm/arch/regmap.h>
++
++#define RTC_VERSION "0.01"
++
++#define RTC_IS_OPEN        0x01       /* means /dev/rtc is in use     */
++
++extern spinlock_t rtc_lock;   /* seems to be only present in older rtc header? */
++static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED;
++static rtc_task_t *rtc_callback = NULL;
++static unsigned long rtc_status = 0;
++static unsigned long rtc_irq_data = 0;
++static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
++
++/*
++ *      the 1 Hz real time interrupt
++ */
++
++irqreturn_t interrupt_1hz(int irq, void *dev_id, struct pt_regs *regs)
++{
++      static unsigned long x = 0;
++      static int i = 0;
++
++      rtc_irq_data += 0x100;
++      rtc_irq_data &= ~0xff;
++
++      wake_up_interruptible(&rtc_wait);
++
++      printk(KERN_ERR);
++      printk(" delta: %04ld", jiffies - x);
++      printk("  data: %08x", readl(RTCDR));
++      printk(" match: %08x", readl(RTCMR));
++      printk("  stat: %08x", readl(RTCSTAT));
++      printk("  load: %08x", readl(RTCLR));
++      printk("  ctrl: %08x", readl(RTCCR));
++      printk("  comp: %08x", readl(RTCSCOMP));
++      printk("\n");
++
++      x = jiffies;
++      i++;
++
++      if ((i & 0x7) == 0) {
++              writel(i << 5, RTCLR);
++              printk(KERN_ERR "NEW LOAD VALUE: %08x\n", i << 5);
++      }
++
++      writel(0, RTCEOI);
++
++      return IRQ_HANDLED;
++}
++
++/*
++ *      the RTC match interrupt
++ */
++
++irqreturn_t interrupt_match(int irq, void *dev_id, struct pt_regs * regs)
++{
++      return IRQ_HANDLED;
++}
++
++/*
++ *      the bulk of the usr interface is done here
++ */
++
++static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
++{
++      return -ENOSYS;
++}
++
++/*
++ *      file operations for character device node
++ */
++
++static ssize_t rtc_read(struct file *file, char __user * buf, size_t count,
++                      loff_t * ppos)
++{
++      unsigned long data;
++      ssize_t retval;
++      DECLARE_WAITQUEUE(wait, current);
++
++      if (count < sizeof(unsigned int))
++              return -EINVAL;
++
++      add_wait_queue(&rtc_wait, &wait);
++
++      do {
++              __set_current_state(TASK_INTERRUPTIBLE);
++
++              spin_lock_irq(&rtc_lock);
++              data = rtc_irq_data;
++              rtc_irq_data = 0;
++              spin_unlock_irq(&rtc_lock);
++
++              if (data != 0)
++                      break;
++
++              if (file->f_flags & O_NONBLOCK) {
++                      retval = -EAGAIN;
++                      goto out;
++              }
++
++              if (signal_pending(current)) {
++                      retval = -ERESTARTSYS;
++                      goto out;
++              }
++
++              schedule();
++      } while (1);
++
++      if (count < sizeof(unsigned long))
++              retval =
++                  put_user(data, (unsigned int __user *)buf) ? : sizeof(int);
++      else
++              retval =
++                  put_user(data,
++                           (unsigned long __user *)buf) ? : sizeof(long);
++
++      out:
++      current->state = TASK_RUNNING;
++      remove_wait_queue(&rtc_wait, &wait);
++
++      return retval;
++}
++
++static unsigned int rtc_poll(struct file *file, poll_table * wait)
++{
++      return -ENOSYS;
++}
++
++static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
++                   unsigned long arg)
++{
++      return rtc_do_ioctl(cmd, arg, 0);
++}
++
++static int rtc_open(struct inode *inode, struct file *file)
++{
++      spin_lock_irq(&rtc_lock);
++
++      if (rtc_status & RTC_IS_OPEN) {
++              spin_unlock_irq(&rtc_lock);
++              return -EBUSY;
++      }
++
++      rtc_status |= RTC_IS_OPEN;
++      rtc_irq_data = 0;
++      enable_irq(IRQ_1HZ);
++
++      spin_unlock_irq(&rtc_lock);
++      return 0;
++}
++
++static int rtc_release(struct inode *inode, struct file *file)
++{
++      spin_lock_irq(&rtc_lock);
++
++      disable_irq(IRQ_1HZ);
++      rtc_irq_data = 0;
++      rtc_status &= ~RTC_IS_OPEN;
++
++      spin_unlock_irq(&rtc_lock);
++
++      return 0;
++}
++
++static int rtc_fasync(int fd, struct file *filp, int on)
++{
++      return -ENOSYS;
++}
++
++static struct file_operations rtc_fops = {
++      .owner = THIS_MODULE,
++      .llseek = no_llseek,
++      .read = rtc_read,
++      .poll = rtc_poll,
++      .ioctl = rtc_ioctl,
++      .open = rtc_open,
++      .release = rtc_release,
++      .fasync = rtc_fasync,
++};
++
++static struct miscdevice rtc_dev = {
++      RTC_MINOR,
++      "rtc",
++      &rtc_fops
++};
++
++/*
++ *      sysctl-tuning infrastructure.
++ */
++
++int no_proc(ctl_table * table, int write, struct file *filp,
++          void __user * buffer, size_t * lenp, loff_t * ppos)
++{
++      return -ENOSYS;
++}
++
++static ctl_table rtc_table[] = {
++      {
++       .ctl_name = 1,
++       .procname = "max-user-freq",
++       .data = NULL,
++       .maxlen = sizeof(int),
++       .mode = 0644,
++       .proc_handler = &no_proc,
++       },
++      {.ctl_name = 0}
++};
++
++static ctl_table rtc_root[] = {
++      {
++       .ctl_name = 1,
++       .procname = "rtc",
++       .maxlen = 0,
++       .mode = 0555,
++       .child = rtc_table,
++       },
++      {.ctl_name = 0}
++};
++
++static ctl_table dev_root[] = {
++      {
++       .ctl_name = CTL_DEV,
++       .procname = "dev",
++       .maxlen = 0,
++       .mode = 0555,
++       .child = rtc_root,
++       },
++      {.ctl_name = 0}
++};
++
++static struct ctl_table_header *sysctl_header;
++
++static int __init init_sysctl(void)
++{
++      sysctl_header = register_sysctl_table(dev_root, 0);
++      return 0;
++}
++
++static void __exit cleanup_sysctl(void)
++{
++      unregister_sysctl_table(sysctl_header);
++}
++
++/*
++ *      Public functions from rtc.h
++ */
++
++EXPORT_SYMBOL(rtc_register);
++EXPORT_SYMBOL(rtc_unregister);
++EXPORT_SYMBOL(rtc_control);
++
++int rtc_register(rtc_task_t * task)
++{
++      if (task == NULL || task->func == NULL)
++              return -EINVAL;
++
++      spin_lock_irq(&rtc_lock);
++
++      if (rtc_status & RTC_IS_OPEN) {
++              spin_unlock_irq(&rtc_lock);
++              return -EBUSY;
++      }
++
++      spin_lock(&rtc_task_lock);
++
++      if (rtc_callback) {
++              spin_unlock(&rtc_task_lock);
++              spin_unlock_irq(&rtc_lock);
++              return -EBUSY;
++      }
++
++      rtc_status |= RTC_IS_OPEN;
++      rtc_callback = task;
++
++      spin_unlock(&rtc_task_lock);
++      spin_unlock_irq(&rtc_lock);
++
++      return 0;
++}
++
++int rtc_unregister(rtc_task_t * task)
++{
++      spin_lock_irq(&rtc_lock);
++      spin_lock(&rtc_task_lock);
++
++      if (rtc_callback != task) {
++              spin_unlock(&rtc_task_lock);
++              spin_unlock_irq(&rtc_lock);
++              return -ENXIO;
++      }
++
++      /* disable PIE/AIE/UIE interrupts */
++
++      rtc_status &= ~RTC_IS_OPEN;
++      rtc_callback = NULL;
++
++      spin_unlock(&rtc_task_lock);
++      spin_unlock_irq(&rtc_lock);
++
++      return 0;
++}
++
++int rtc_control(rtc_task_t * task, unsigned int cmd, unsigned long arg)
++{
++      spin_lock_irq(&rtc_task_lock);
++
++      if (rtc_callback != task) {
++              spin_unlock_irq(&rtc_task_lock);
++              return -ENXIO;
++      }
++
++      spin_unlock_irq(&rtc_task_lock);
++
++      return rtc_do_ioctl(cmd, arg, 1);
++}
++
++void rtc_get_rtc_time(struct rtc_time *rtc_tm)
++{
++}
++
++/*
++ *      Module init/exit
++ */
++
++static int __init rtc_init(void)
++{
++      if (request_irq(IRQ_1HZ, interrupt_1hz, SA_INTERRUPT, "rtc-1hz", NULL)) {
++              printk(KERN_ERR "rtc: IRQ %d is not free.\n", IRQ_1HZ);
++              return -EIO;
++      }
++
++      if (misc_register(&rtc_dev)) {
++              free_irq(IRQ_1HZ, NULL);
++              return -ENODEV;
++      }
++
++      init_sysctl();
++
++      printk(KERN_INFO "Real Time Clock Driver v" RTC_VERSION "\n");
++      return 0;
++}
++
++static void __exit rtc_exit(void)
++{
++      cleanup_sysctl();
++      misc_deregister(&rtc_dev);
++      free_irq(IRQ_1HZ, NULL);
++}
++
++module_init(rtc_init);
++module_exit(rtc_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/char/ttml.c b/drivers/char/ttml.c
+new file mode 100644
+index 0000000..ba2cb8e
+--- /dev/null
++++ b/drivers/char/ttml.c
+@@ -0,0 +1,643 @@
++/*
++ * linux/drivers/char/ttml.c
++ *
++ * TTML TripDawg system devices.
++ *
++ * Copyright 2004, Ray Lehtiniemi
++ * Copyright 2004, Siconix, Inc
++ */
++
++#include <linux/module.h>
++#include <linux/config.h>
++
++#include <linux/spinlock.h>
++#include <linux/fs.h>
++#include <linux/device.h>
++#include <linux/cdev.h>
++#include <linux/major.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/poll.h>
++#include <linux/ttml.h>
++#include <linux/timer.h>
++#include <linux/slab.h>
++
++#include <asm/io.h>
++#include <asm/uaccess.h>
++
++#include <asm/arch/regmap.h>
++#include <asm/arch/ssp.h>
++#include <asm/arch/ssp2.h>
++#include <asm/arch/mach-ttml.h>
++
++/* device open/release stuff */
++static DECLARE_MUTEX(mutex);
++static struct cdev ttml_cdev;
++static struct class *ttml_class;
++static int is_open[MAX_TTML_MINORS];
++
++#define minor_get(minor) is_open[(minor)-TTML_MINOR_LED] = 1
++#define minor_put(minor) is_open[(minor)-TTML_MINOR_LED] = 0
++#define minor_busy(minor) (is_open[(minor)-TTML_MINOR_LED] != 0)
++
++static struct {
++      int minor;
++      char *name;
++} devlist[] = {
++      {
++      TTML_MINOR_LED, "led"}, {
++      TTML_MINOR_BUZZER, "buzzer"}, {
++      TTML_MINOR_SPEEDO, "speedo"}, {
++      TTML_MINOR_GPIO, "gpio"}, {
++      TTML_MINOR_BUTTON, "button"}, {
++TTML_MINOR_WD, "wd"},};
++
++/* button and gpio event handling */
++static kmem_cache_t *event_cachep;
++static spinlock_t event_lock = SPIN_LOCK_UNLOCKED;
++static LIST_HEAD(button_events);
++static LIST_HEAD(gpio_events);
++static DECLARE_WAIT_QUEUE_HEAD(button_wait);
++static DECLARE_WAIT_QUEUE_HEAD(gpio_wait);
++
++enum ttml_events {
++      TTML_BUTTON_PRESS,
++      TTML_BUTTON_RELEASE,
++      TTML_PTO_RISE,
++      TTML_PTO_FALL,
++      TTML_IGNITION_RISE,
++      TTML_IGNITION_FALL,
++      TTML_SPARE_RISE,
++      TTML_SPARE_FALL,
++};
++
++struct ttml_event {
++      struct list_head l;
++      struct timeval t;
++      enum ttml_events e;
++};
++
++/*  Button and GPIO event monitoring timer */
++
++static struct timer_list monitor_timer;
++static void handle_timer(unsigned long);
++
++static void setup_timer(void)
++{
++      monitor_timer.expires = jiffies + 1;
++      monitor_timer.data = 0;
++      monitor_timer.function = handle_timer;
++      add_timer(&monitor_timer);
++}
++
++static void handle_timer_button(void)
++{
++      static int state = 0;
++      int portf = readl(GPIO_PFDR);
++      int new = (portf & 0x04) ? 0 : 1;
++
++      if (state ^ new) {
++              struct ttml_event *b =
++                  kmem_cache_alloc(event_cachep, GFP_KERNEL);
++              if (b != NULL) {
++                      do_gettimeofday(&b->t);
++                      b->t.tv_usec |=
++                          ((new ? TTML_BUTTON_PRESS : TTML_BUTTON_RELEASE) <<
++                           24);
++                      list_add(&b->l, &button_events);
++                      wake_up_interruptible(&button_wait);
++              }
++              state = new;
++      }
++}
++
++static void handle_timer_pto(void)
++{
++      static int state = 0;
++      int portf = readl(GPIO_PFDR);
++      int new = (portf & 0x08) ? 1 : 0;
++
++      if (state ^ new) {
++              struct ttml_event *b =
++                  kmem_cache_alloc(event_cachep, GFP_KERNEL);
++              if (b != NULL) {
++                      do_gettimeofday(&b->t);
++                      b->t.tv_usec |=
++                          ((new ? TTML_PTO_RISE : TTML_PTO_FALL) << 24);
++                      list_add(&b->l, &gpio_events);
++                      wake_up_interruptible(&gpio_wait);
++              }
++              state = new;
++      }
++}
++
++static void handle_timer_ignition(void)
++{
++      static int state = 0;
++      int portf = readl(GPIO_PFDR);
++      int new = (portf & 0x02) ? 1 : 0;
++
++      if (state ^ new) {
++              struct ttml_event *b =
++                  kmem_cache_alloc(event_cachep, GFP_KERNEL);
++              if (b != NULL) {
++                      do_gettimeofday(&b->t);
++                      b->t.tv_usec |=
++                          ((new ? TTML_IGNITION_RISE : TTML_IGNITION_FALL) <<
++                           24);
++                      list_add(&b->l, &gpio_events);
++                      wake_up_interruptible(&gpio_wait);
++              }
++              state = new;
++      }
++}
++
++static void handle_timer_spare(void)
++{
++      static int state = 0;
++      int porta = readl(GPIO_PADR);
++      int new = (porta & 0x08) ? 1 : 0;
++
++      if (state ^ new) {
++              struct ttml_event *b =
++                  kmem_cache_alloc(event_cachep, GFP_KERNEL);
++              if (b != NULL) {
++                      do_gettimeofday(&b->t);
++                      b->t.tv_usec |=
++                          ((new ? TTML_SPARE_RISE : TTML_SPARE_FALL) << 24);
++                      list_add(&b->l, &gpio_events);
++                      wake_up_interruptible(&gpio_wait);
++              }
++              state = new;
++      }
++}
++
++static void handle_timer(unsigned long foo)
++{
++      handle_timer_button();
++      handle_timer_pto();
++      handle_timer_ignition();
++      handle_timer_spare();
++      setup_timer();
++}
++
++static int ttml_read_gpio(struct file *filp, char __user * buf, size_t size,
++                        loff_t * off);
++static int ttml_read_button(struct file *filp, char __user * buf, size_t size,
++                          loff_t * off);
++static unsigned int ttml_poll_gpio(struct file *filp,
++                                 struct poll_table_struct *poll);
++static unsigned int ttml_poll_button(struct file *filp,
++                                   struct poll_table_struct *poll);
++static int ttml_ioctl(struct inode *inode, struct file *filp,
++                    unsigned int command, unsigned long arg);
++static int ttml_open(struct inode *inode, struct file *filp);
++static int ttml_release(struct inode *inode, struct file *filp);
++
++static struct file_operations ttml_fops = {
++      .owner = THIS_MODULE,
++      .ioctl = ttml_ioctl,
++      .open = ttml_open,
++      .release = ttml_release,
++};
++
++static struct file_operations ttml_fops_gpio = {
++      .owner = THIS_MODULE,
++      .read = ttml_read_gpio,
++      .poll = ttml_poll_gpio,
++      .ioctl = ttml_ioctl,
++      .open = ttml_open,
++      .release = ttml_release,
++};
++
++static struct file_operations ttml_fops_button = {
++      .owner = THIS_MODULE,
++      .read = ttml_read_button,
++      .poll = ttml_poll_button,
++      .ioctl = ttml_ioctl,
++      .open = ttml_open,
++      .release = ttml_release,
++};
++
++static int do_get_led(void __user * arg)
++{
++      struct ttml_ioctl_led a;
++      int porte = readl(GPIO_PEDR);
++      int portb = readl(GPIO_PBDR);
++
++      a.blue = (portb & 0x01) ? 1 : 0;
++      a.red = (porte & 0x02) ? 1 : 0;
++      a.yellow = (porte & 0x01) ? 1 : 0;
++
++      return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
++}
++
++static int do_get_buzzer(void __user * arg)
++{
++      struct ttml_ioctl_buzzer a;
++
++      a.buzzer1 = 0;          /* FIXME */
++
++      return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
++}
++
++static int do_get_speedo(void __user * arg)
++{
++      struct ttml_ioctl_speedo a;
++      unsigned char msg[3] = { 0xaa, 0x82, 0xd7 };
++      unsigned char reply[10];
++      int err;
++
++      err = ssp_do_ttml(&ep93xx_ssp_micro, msg, 3, reply, 10);
++
++      if (err != 0)
++              return err;
++
++      a.instant = 0;          /* FIXME */
++      a.average = (reply[1] << 8) | (reply[2]);
++
++      return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
++}
++
++static int do_get_gpio(void __user * arg)
++{
++      struct ttml_ioctl_gpio a;
++      int porta = readl(GPIO_PADR);
++      int portf = readl(GPIO_PFDR);
++
++      a.pto = (portf & 0x08) ? 0 : 1;
++      a.ignition = (portf & 0x02) ? 0 : 1;
++      a.spare = (porta & 0x08) ? 0 : 1;
++
++      return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
++}
++
++static int do_get_button(void __user * arg)
++{
++      struct ttml_ioctl_button a;
++      int portf = readl(GPIO_PFDR);
++
++      a.button1 = (portf & 0x04) ? 0 : 1;
++
++      return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
++}
++
++static int do_set_led(void __user * arg)
++{
++      struct ttml_ioctl_led a;
++      int porte = readl(GPIO_PEDR);
++      int portb = readl(GPIO_PBDR);
++
++      if (copy_from_user(&a, arg, sizeof(a)))
++              return -EIO;
++
++      if (a.yellow)
++              porte |= 0x01;
++      else
++              porte &= ~0x01;
++
++      if (a.red)
++              porte |= 0x02;
++      else
++              porte &= ~0x02;
++
++      if (a.blue)
++              portb |= 0x01;
++      else
++              portb &= ~0x01;
++
++      writel(porte, GPIO_PEDR);
++      writel(portb, GPIO_PBDR);
++
++      return 0;
++}
++
++static int do_set_buzzer(void __user * arg)
++{
++      struct ttml_ioctl_buzzer a;
++      unsigned char msg0[4] = { 0xaa, 0x93, 0x00, 0xc6 };
++      unsigned char msg1[4] = { 0xaa, 0x93, 0x01, 0xc7 };
++      unsigned char reply[10];
++      int err = 0;
++
++      if (copy_from_user(&a, arg, sizeof(a)))
++              return -EIO;
++
++      if (a.buzzer1)
++              err = ssp_do_ttml(&ep93xx_ssp_micro, msg1, 4, reply, 10);
++      else
++              err = ssp_do_ttml(&ep93xx_ssp_micro, msg0, 4, reply, 10);
++
++      return err;
++}
++
++static int ttml_read_gpio(struct file *filp, char __user * buf, size_t size,
++                        loff_t * off)
++{
++      DECLARE_WAITQUEUE(wait, current);
++      struct ttml_event *g = NULL;
++      int retval = -EINVAL;
++
++      if (size != sizeof(struct timeval))
++              return -EINVAL;
++
++      add_wait_queue(&gpio_wait, &wait);
++
++      while (1) {
++              unsigned long flags;
++
++              __set_current_state(TASK_INTERRUPTIBLE);
++
++              spin_lock_irqsave(&event_lock, flags);
++              if (!list_empty(&gpio_events))
++                      list_for_each_entry(g, &gpio_events, l) {
++                      list_del(&g->l);
++                      break;
++                      }
++
++              spin_unlock_irqrestore(&event_lock, flags);
++
++              if (g != NULL)
++                      break;
++
++              if (filp->f_flags & O_NONBLOCK) {
++                      retval = -EAGAIN;
++                      goto out;
++              }
++
++              if (signal_pending(current)) {
++                      retval = -ERESTARTSYS;
++                      goto out;
++              }
++
++              schedule();
++
++      };
++
++      if (copy_to_user(buf, &g->t, sizeof(struct timeval)))
++              retval = -EFAULT;
++      else
++              retval = sizeof(struct timeval);
++
++      kmem_cache_free(event_cachep, g);
++
++      out:
++      current->state = TASK_RUNNING;
++      remove_wait_queue(&gpio_wait, &wait);
++
++      return retval;
++}
++
++static unsigned int ttml_poll_gpio(struct file *filp,
++                                 struct poll_table_struct *poll)
++{
++      unsigned long flags;
++      int retval = 0;
++
++      poll_wait(filp, &gpio_wait, poll);
++
++      spin_lock_irqsave(&event_lock, flags);
++      if (!list_empty(&gpio_events))
++              retval = (POLLIN | POLLRDNORM);
++      spin_unlock_irqrestore(&event_lock, flags);
++
++      return retval;
++}
++
++static int ttml_read_button(struct file *filp, char __user * buf, size_t size,
++                          loff_t * off)
++{
++      DECLARE_WAITQUEUE(wait, current);
++      struct ttml_event *b = NULL;
++      int retval = -EINVAL;
++
++      if (size != sizeof(struct timeval))
++              return -EINVAL;
++
++      add_wait_queue(&button_wait, &wait);
++
++      while (1) {
++              unsigned long flags;
++
++              __set_current_state(TASK_INTERRUPTIBLE);
++
++              spin_lock_irqsave(&event_lock, flags);
++              if (!list_empty(&button_events)) {
++                      list_for_each_entry(b, &button_events, l) {
++                              list_del(&b->l);
++                              break;
++                      }
++              }
++              spin_unlock_irqrestore(&event_lock, flags);
++
++              if (b != NULL)
++                      break;
++
++              if (filp->f_flags & O_NONBLOCK) {
++                      retval = -EAGAIN;
++                      goto out;
++              }
++
++              if (signal_pending(current)) {
++                      retval = -ERESTARTSYS;
++                      goto out;
++              }
++
++              schedule();
++
++      };
++
++      if (copy_to_user(buf, &b->t, sizeof(struct timeval)))
++              retval = -EFAULT;
++      else
++              retval = sizeof(struct timeval);
++
++      kmem_cache_free(event_cachep, b);
++
++      out:
++      current->state = TASK_RUNNING;
++      remove_wait_queue(&button_wait, &wait);
++
++      return retval;
++}
++
++static unsigned int ttml_poll_button(struct file *filp,
++                                   struct poll_table_struct *poll)
++{
++      unsigned long flags;
++      int retval = 0;
++
++      poll_wait(filp, &button_wait, poll);
++
++      spin_lock_irqsave(&event_lock, flags);
++      if (!list_empty(&button_events))
++              retval = (POLLIN | POLLRDNORM);
++      spin_unlock_irqrestore(&event_lock, flags);
++
++      return retval;
++}
++
++static int ttml_ioctl(struct inode *inode, struct file *filp,
++                    unsigned int command, unsigned long arg)
++{
++      void __user *p = (void __user *)arg;
++      const int minor = iminor(inode);
++      int err = -ENOSYS;
++
++      switch (command) {
++      case TTML_GET_LED:
++              if (minor == TTML_MINOR_LED)
++                      err = do_get_led(p);
++              break;
++      case TTML_GET_BUZZER:
++              if (minor == TTML_MINOR_BUZZER)
++                      err = do_get_buzzer(p);
++              break;
++      case TTML_GET_SPEEDO:
++              if (minor == TTML_MINOR_SPEEDO)
++                      err = do_get_speedo(p);
++              break;
++      case TTML_GET_GPIO:
++              if (minor == TTML_MINOR_GPIO)
++                      err = do_get_gpio(p);
++              break;
++      case TTML_GET_BUTTON:
++              if (minor == TTML_MINOR_BUTTON)
++                      err = do_get_button(p);
++              break;
++      case TTML_SET_LED:
++              if (minor == TTML_MINOR_LED)
++                      err = do_set_led(p);
++              break;
++      case TTML_SET_BUZZER:
++              if (minor == TTML_MINOR_BUZZER)
++                      err = do_set_buzzer(p);
++              break;
++      }
++
++      return err;
++}
++
++static int ttml_open(struct inode *inode, struct file *filp)
++{
++      const int minor = iminor(inode);
++      int err = -EBUSY;
++
++      if (minor == TTML_MINOR_WD) {
++              unsigned char msg[3] = { 0xaa, 0x82, 0xd7 };
++              unsigned char reply[10];
++              ssp_do_ttml(&ep93xx_ssp_micro, msg, 3, reply, 10);
++      }
++
++      down(&mutex);
++      if (minor_busy(minor))
++              goto err;
++      minor_get(minor);
++      if (minor == TTML_MINOR_GPIO)
++              filp->f_op = &ttml_fops_gpio;
++      if (minor == TTML_MINOR_BUTTON)
++              filp->f_op = &ttml_fops_button;
++      err = 0;
++
++      err:
++      up(&mutex);
++      return err;
++}
++
++static int ttml_release(struct inode *inode, struct file *filp)
++{
++      down(&mutex);
++      minor_put(iminor(inode));
++      up(&mutex);
++      return 0;
++}
++
++static int __init ttml_init(void)
++{
++      dev_t dev = MKDEV(TTML_MAJOR, 240);
++      int err = -EIO;
++      int i;
++
++      err = -ENOMEM;
++      event_cachep = kmem_cache_create("ttml_event",
++                                       sizeof(struct ttml_event),
++                                       0, 0, NULL, NULL);
++      if (event_cachep == NULL)
++              goto err;
++
++      err = -EIO;
++      if (register_chrdev_region(dev, MAX_TTML_MINORS, "ttml"))
++              goto err_uncache;
++
++      cdev_init(&ttml_cdev, &ttml_fops);
++
++      if (cdev_add(&ttml_cdev, dev, MAX_TTML_MINORS)) {
++              kobject_put(&ttml_cdev.kobj);
++              goto err_unreg;
++      }
++
++      ttml_class = class_create(THIS_MODULE, "ttml");
++
++      if (IS_ERR(ttml_class)) {
++              err = PTR_ERR(ttml_class);
++              cdev_del(&ttml_cdev);
++              goto err_unreg;
++      }
++
++      for (i = 0; i < ARRAY_SIZE(devlist); i++)
++              class_device_create(ttml_class,
++                                      MKDEV(TTML_MAJOR, devlist[i].minor),
++                                      NULL, "%s", devlist[i].name);
++
++      init_timer(&monitor_timer);
++      setup_timer();
++
++      printk(KERN_INFO "TTML system devices version 0.1\n");
++      return 0;
++
++      err_unreg:
++      unregister_chrdev_region(dev, MAX_TTML_MINORS);
++      err_uncache:
++      kmem_cache_destroy(event_cachep);
++      err:
++      printk(KERN_WARNING "unable to register ttml devices\n");
++      return err;
++}
++
++static void __exit ttml_exit(void)
++{
++      struct ttml_event *b;
++      int i;
++
++      /* stop our button polling timer */
++      del_timer_sync(&monitor_timer);
++
++      /* delete any events captured but not yet read */
++      list_for_each_entry(b, &button_events, l) {
++              list_del(&b->l);
++              kmem_cache_free(event_cachep, b);
++      }
++
++      list_for_each_entry(b, &gpio_events, l) {
++              list_del(&b->l);
++              kmem_cache_free(event_cachep, b);
++      }
++
++      /* free up the event cache */
++      kmem_cache_destroy(event_cachep);
++
++      /* clean up the device */
++      for (i = 0; i < ARRAY_SIZE(devlist); i++)
++              class_device_destroy(ttml_class,
++                              MKDEV(TTML_MAJOR, devlist[i].minor));
++      class_destroy(ttml_class);
++      cdev_del(&ttml_cdev);
++      unregister_chrdev_region(MKDEV(TTML_MAJOR, 240), MAX_TTML_MINORS);
++}
++
++module_init(ttml_init);
++module_exit(ttml_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi");
++MODULE_DESCRIPTION("TTML system devices");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
+index 344001b..b5a7a90 100644
+--- a/drivers/char/watchdog/Kconfig
++++ b/drivers/char/watchdog/Kconfig
+@@ -148,6 +148,17 @@ config MPCORE_WATCHDOG
+         To compile this driver as a module, choose M here: the
+         module will be called mpcore_wdt.
++config EP93XX_WATCHDOG
++      tristate "EP93xx Watchdog"
++      depends on WATCHDOG && ARCH_EP93XX
++      help
++        Say Y here if to include support for the watchdog timer
++        in the Cirrus EP93xx family of devices. This driver can
++        be built as a module by choosing M. The module will
++        be called ep93xx_wdt.
++
++        Say N if you are unsure.
++
+ # X86 (i386 + ia64 + x86_64) Architecture
+ config ACQUIRE_WDT
+diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
+index cfd0a39..061671b 100644
+--- a/drivers/char/watchdog/Makefile
++++ b/drivers/char/watchdog/Makefile
+@@ -25,6 +25,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.
+ # ARM Architecture
+ obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
+ obj-$(CONFIG_977_WATCHDOG) += wdt977.o
++obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
+ obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
+ obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
+ obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
+diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/char/watchdog/ep93xx_wdt.c
+new file mode 100644
+index 0000000..a2a7a49
+--- /dev/null
++++ b/drivers/char/watchdog/ep93xx_wdt.c
+@@ -0,0 +1,210 @@
++/*
++ * drivers/watchdog/ep93xx_wdt.c
++ *
++ * Watchdog driver for Cirrus EP93xx family of devices.
++ *
++ * Author: Ray Lehtiniemi <rayl@mail.com>
++ *
++ * Copyright 2004 (c) Ray Lehtiniemi
++ * Based on ep93xx driver.
++ *
++ * This file is licensed under  the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++/*
++    Todo:
++
++    - test last rst from watchdog status
++    - test module loading
++    - test nowayout
++    - test all ioctl, add missing ones
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/watchdog.h>
++#include <linux/init.h>
++
++#include <asm/hardware.h>
++#include <asm/bitops.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/arch/regmap.h>
++
++#define WD_VERSION "0.01"
++
++#ifdef CONFIG_WATCHDOG_NOWAYOUT
++static int nowayout = 1;
++#else
++static int nowayout = 0;
++#endif
++
++static unsigned long wdt_status;
++static unsigned long boot_status;
++
++#define       WDT_IN_USE              0
++#define       WDT_OK_TO_CLOSE         1
++
++static void wdt_enable(void)
++{
++      writel(0xaaaa, WATCHDOG);
++}
++
++static void wdt_disable(void)
++{
++      writel(0xaa55, WATCHDOG);
++}
++
++static void wdt_ping(void)
++{
++      writel(0x5555, WATCHDOG);
++}
++
++static int ep93xx_wdt_open(struct inode *inode, struct file *file)
++{
++      if (test_and_set_bit(WDT_IN_USE, &wdt_status))
++              return -EBUSY;
++
++      clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
++
++      wdt_enable();
++
++      return 0;
++}
++
++static ssize_t
++ep93xx_wdt_write(struct file *file, const char __user * data, size_t len,
++               loff_t * ppos)
++{
++      /* Can't seek (pwrite) on this device  */
++      if (*ppos != file->f_pos)
++              return -ESPIPE;
++
++      if (len) {
++              if (!nowayout) {
++                      size_t i;
++
++                      clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
++
++                      for (i = 0; i != len; i++) {
++                              char c;
++
++                              if (get_user(c, data + i))
++                                      return -EFAULT;
++
++                              if (c == 'V')
++                                      set_bit(WDT_OK_TO_CLOSE, &wdt_status);
++                              else
++                                      clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
++                      }
++              }
++              wdt_ping();
++      }
++
++      return len;
++}
++
++static struct watchdog_info ident = {
++      .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE,
++      .identity = "EP93xx Watchdog",
++};
++
++static int
++ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
++               unsigned long arg)
++{
++      int ret = -ENOIOCTLCMD;
++
++      switch (cmd) {
++      case WDIOC_GETSUPPORT:
++              ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
++                                 sizeof(ident)) ? -EFAULT : 0;
++              break;
++
++      case WDIOC_GETSTATUS:
++              ret = put_user(0, (int __user *)arg);
++              break;
++
++      case WDIOC_GETBOOTSTATUS:
++              ret = put_user(boot_status, (int __user *)arg);
++              break;
++
++      case WDIOC_GETTIMEOUT:
++              /* actually, it is 0.250 seconds.... */
++              ret = put_user(1, (int __user *)arg);
++              break;
++
++      case WDIOC_KEEPALIVE:
++              wdt_ping();
++              ret = 0;
++              break;
++      }
++      return ret;
++}
++
++static int ep93xx_wdt_release(struct inode *inode, struct file *file)
++{
++      if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
++              wdt_disable();
++      else
++              printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
++                     "timer will not stop\n");
++
++      clear_bit(WDT_IN_USE, &wdt_status);
++      clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
++
++      return 0;
++}
++
++static struct file_operations ep93xx_wdt_fops = {
++      .owner = THIS_MODULE,
++      .write = ep93xx_wdt_write,
++      .ioctl = ep93xx_wdt_ioctl,
++      .open = ep93xx_wdt_open,
++      .release = ep93xx_wdt_release,
++};
++
++static struct miscdevice ep93xx_wdt_miscdev = {
++      .minor = WATCHDOG_MINOR,
++      .name = "EP93xx Watchdog",
++      .fops = &ep93xx_wdt_fops,
++};
++
++static int __init ep93xx_wdt_init(void)
++{
++      int ret;
++
++      ret = misc_register(&ep93xx_wdt_miscdev);
++
++      boot_status = readl(WATCHDOG) & 0x01 ? 1 : 0;
++
++      printk("EP93xx Watchdog: Version " WD_VERSION "%s\n",
++             (readl(WATCHDOG) & 0x08) ? " (nCS1 disable detected)"
++             : "");
++
++      return ret;
++}
++
++static void __exit ep93xx_wdt_exit(void)
++{
++      misc_deregister(&ep93xx_wdt_miscdev);
++}
++
++module_init(ep93xx_wdt_init);
++module_exit(ep93xx_wdt_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>");
++MODULE_DESCRIPTION("EP93xx Watchdog");
++
++module_param(nowayout, int, 0);
++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
++
++MODULE_LICENSE("GPL");
++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index 4010fe9..895dfa8 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -95,6 +95,19 @@ config I2C_ELEKTOR
+         This support is also available as a module.  If so, the module 
+         will be called i2c-elektor.
++config I2C_EP93XX
++      tristate "Cirrus EP93XX interface"
++      depends on I2C && ARCH_EP93XX
++      select I2C_ALGOBIT
++      help
++        This supports the Cirrus EP93xx CPU family I2C bus. Choose this
++        if you want to access I2C devices connected to EECLK and EEDAT pins
++        of your EP93XX.
++
++        This support is also available as a module.  If so, the module
++        will be called i2c-ep93xx.
++
++
+ config I2C_HYDRA
+       tristate "CHRP Apple Hydra Mac I/O I2C interface"
+       depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index f1df00f..fbb35f7 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_I2C_AMD756_S4882)       += i2c-am
+ obj-$(CONFIG_I2C_AMD8111)     += i2c-amd8111.o
+ obj-$(CONFIG_I2C_AU1550)      += i2c-au1550.o
+ obj-$(CONFIG_I2C_ELEKTOR)     += i2c-elektor.o
++obj-$(CONFIG_I2C_EP93XX)      += i2c-ep93xx.o
+ obj-$(CONFIG_I2C_HYDRA)               += i2c-hydra.o
+ obj-$(CONFIG_I2C_I801)                += i2c-i801.o
+ obj-$(CONFIG_I2C_I810)                += i2c-i810.o
+diff --git a/drivers/i2c/busses/i2c-ep93xx.c b/drivers/i2c/busses/i2c-ep93xx.c
+new file mode 100644
+index 0000000..1477bf3
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-ep93xx.c
+@@ -0,0 +1,180 @@
++/* ------------------------------------------------------------------------ *
++ * i2c-ep933xx.c I2C bus glue for Cirrus EP93xx                             *
++ * ------------------------------------------------------------------------ *
++
++   Copyright (C) 2004 Michael Burian
++
++   Based on i2c-parport-light.c
++   Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
++
++   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 <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/i2c-algo-bit.h>
++#include <asm/io.h>
++#include <asm/arch/regmap.h>
++
++/* 1/(2*clockfrequency) */
++#define EE_DELAY_USEC       50
++#define GPIOG_EECLK 1
++#define GPIOG_EEDAT 2
++
++/* ----- I2C algorithm call-back functions and structures ----------------- */
++
++static void ep93xx_setscl(void *data, int state)
++{
++      unsigned int val, dir;
++
++      val = readl(GPIO_PGDR);
++      dir = readl(GPIO_PGDDR);
++
++      /* Configure the clock line as output. */
++      dir |= GPIOG_EECLK;
++      writel(dir, GPIO_PGDDR);
++
++      /* Set clock line to state */
++      if (state)
++              val |= GPIOG_EECLK;
++      else
++              val &= ~GPIOG_EECLK;
++
++      writel(val, GPIO_PGDR);
++}
++
++static void ep93xx_setsda(void *data, int state)
++{
++      unsigned int val, dir;
++      val = readl(GPIO_PGDR);
++      dir = readl(GPIO_PGDDR);
++
++      /* Configure the data line as output. */
++      dir |= GPIOG_EEDAT;
++      writel(dir, GPIO_PGDDR);
++
++      /* Set data line to state */
++      if (state)
++              val |= GPIOG_EEDAT;
++      else
++              val &= ~GPIOG_EEDAT;
++
++      writel(val, GPIO_PGDR);
++}
++
++static int ep93xx_getscl(void *data)
++{
++      unsigned int val, dir;
++      val = readl(GPIO_PGDR);
++      dir = readl(GPIO_PGDDR);
++
++      /* Configure the clock line as input */
++      dir &= ~GPIOG_EECLK;
++      writel(dir, GPIO_PGDDR);
++
++      /* Return state of the clock line */
++      return (readl(GPIO_PGDR) & GPIOG_EECLK) ? 1 : 0;
++}
++
++static int ep93xx_getsda(void *data)
++{
++      unsigned int val, dir;
++      val = readl(GPIO_PGDR);
++      dir = readl(GPIO_PGDDR);
++
++      /* Configure the data line as input */
++      dir &= ~GPIOG_EEDAT;
++      writel(dir, GPIO_PGDDR);
++
++      /* Return state of the data line */
++      return (readl(GPIO_PGDR) & GPIOG_EEDAT) ? 1 : 0;
++}
++
++static struct i2c_algo_bit_data ep93xx_algo_data = {
++      .setsda = ep93xx_setsda,
++      .setscl = ep93xx_setscl,
++      .getsda = ep93xx_getsda,
++      .getscl = ep93xx_getscl,
++      .udelay = EE_DELAY_USEC,
++      .mdelay = EE_DELAY_USEC * 1000,
++      .timeout = HZ,
++};
++
++/* ----- I2c structure ---------------------------------------------------- */
++
++static struct i2c_adapter ep93xx_adapter = {
++      .owner = THIS_MODULE,
++      .class = I2C_CLASS_HWMON,
++      .id = I2C_HW_B_LP,
++      .algo_data = &ep93xx_algo_data,
++      .name = "EP93XX I2C interface",
++};
++
++/* ----- Module loading, unloading and information ------------------------ */
++
++static int __init i2c_ep93xx_init(void)
++{
++      unsigned long uiVal, uiDDR;
++
++      /* Read the current value of the GPIO data and data direction registers. */
++      uiVal = readl(GPIO_PGDR);
++      uiDDR = readl(GPIO_PGDDR);
++
++      /* If the GPIO pins have not been configured since reset, the data
++       * and clock lines will be set as inputs and with data value of 0.
++       * External pullup resisters are pulling them high.
++       * Set them both high before configuring them as outputs. */
++      uiVal |= (GPIOG_EEDAT | GPIOG_EECLK);
++      writel(uiVal, GPIO_PGDR);
++
++      /* Delay to meet the EE Interface timing specification. */
++      udelay(EE_DELAY_USEC);
++
++      /* Configure the EE data and clock lines as outputs. */
++      writel(0x3, GPIO_EEDRIVE); /* use open drain outputs! */
++      uiDDR |= (GPIOG_EEDAT | GPIOG_EECLK);
++      writel(uiDDR, GPIO_PGDDR);
++
++      /* Delay to meet the EE Interface timing specification. */
++      udelay(EE_DELAY_USEC);
++
++      /* Reset hardware to a sane state (SCL and SDA high) */
++      ep93xx_setsda(NULL, 1);
++      ep93xx_setscl(NULL, 1);
++
++      if (i2c_bit_add_bus(&ep93xx_adapter) < 0) {
++              printk(KERN_ERR "i2c-ep93xx: Unable to register with I2C\n");
++              return -ENODEV;
++      }
++
++      return 0;
++}
++
++static void __exit i2c_ep93xx_exit(void)
++{
++      i2c_bit_del_bus(&ep93xx_adapter);
++}
++
++MODULE_AUTHOR("Michael Burian");
++MODULE_DESCRIPTION("I2C bus glue for Cirrus EP93xx processors");
++MODULE_LICENSE("GPL");
++
++module_init(i2c_ep93xx_init);
++module_exit(i2c_ep93xx_exit);
+diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
+index f9fae28..45f9286 100644
+--- a/drivers/i2c/chips/Kconfig
++++ b/drivers/i2c/chips/Kconfig
+@@ -25,6 +25,18 @@ config SENSORS_DS1374
+         This driver can also be built as a module.  If so, the module
+         will be called ds1374.
++config SENSORS_DS1307
++      tristate "Dallas Semiconductor DS1307 RTC"
++      depends on I2C && EXPERIMENTAL
++      help
++        If you say yes here you get support for the Dallas Semiconductor
++        DS1307 RTC. Usually only embedded devices will need this.
++
++        Only say yes here if your sure you have such a chip.
++
++        This driver can also be built as a module.  If so, the module
++        will be called ds1307.
++
+ config SENSORS_EEPROM
+       tristate "EEPROM reader"
+       depends on I2C && EXPERIMENTAL
+diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
+index 46178b5..90be351 100644
+--- a/drivers/i2c/chips/Makefile
++++ b/drivers/i2c/chips/Makefile
+@@ -3,6 +3,7 @@
+ #
+ obj-$(CONFIG_SENSORS_DS1337)  += ds1337.o
++obj-$(CONFIG_SENSORS_DS1307)  += ds1307.o
+ obj-$(CONFIG_SENSORS_DS1374)  += ds1374.o
+ obj-$(CONFIG_SENSORS_EEPROM)  += eeprom.o
+ obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
+diff --git a/drivers/i2c/chips/ds1307.c b/drivers/i2c/chips/ds1307.c
+new file mode 100644
+index 0000000..76ea8b8
+--- /dev/null
++++ b/drivers/i2c/chips/ds1307.c
+@@ -0,0 +1,651 @@
++/*
++ * ds1307.c
++ *
++ * Device driver for Dallas Semiconductor's Real Time Controller DS1307.
++ *
++ * Copyright (C) 2002 Intrinsyc Software Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/version.h>
++
++#include <linux/kernel.h>
++#include <linux/poll.h>
++#include <linux/i2c.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/rtc.h>
++#include <linux/string.h>
++#include <linux/miscdevice.h>
++#include <linux/proc_fs.h>
++
++#include "ds1307.h"
++
++#undef DEBUG
++#ifdef DEBUG
++static unsigned int rtc_debug = DEBUG;
++#define DPRINTK(i,x...)       do { if (rtc_debug > (i)) printk(x); } while (0)
++#else
++#define rtc_debug 0   /* gcc will remove all the debug code for us */
++#define DPRINTK(i,x...)       do { } while (0)
++#endif
++
++static unsigned short slave_address = DS1307_I2C_SLAVE_ADDR;
++
++struct i2c_driver ds1307_driver;
++struct i2c_client *ds1307_i2c_client = 0;
++
++static unsigned short ignore[] = { I2C_CLIENT_END };
++static unsigned short normal_addr[] = { DS1307_I2C_SLAVE_ADDR, I2C_CLIENT_END };
++
++static struct i2c_client_address_data addr_data = {
++      normal_i2c:             normal_addr,
++      probe:                  ignore,
++      ignore:                 ignore,
++      force:                  ignore,
++};
++
++static int ds1307_rtc_ioctl( struct inode *, struct file *, unsigned int, unsigned long);
++static int ds1307_rtc_open(struct inode *inode, struct file *file);
++static int ds1307_rtc_release(struct inode *inode, struct file *file);
++
++static struct file_operations rtc_fops = {
++      owner:          THIS_MODULE,
++      ioctl:          ds1307_rtc_ioctl,
++      open:           ds1307_rtc_open,
++      release:        ds1307_rtc_release,
++};
++
++static struct miscdevice ds1307_rtc_miscdev = {
++      RTC_MINOR,
++      "rtc",
++      &rtc_fops
++};
++
++static int ds1307_probe(struct i2c_adapter *adap);
++static int ds1307_detach(struct i2c_client *client);
++static int ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg);
++
++struct i2c_driver ds1307_driver = {
++      .owner          = THIS_MODULE,
++      .name           = "DS1307",
++      .id             = I2C_DRIVERID_DS1307,
++      .flags          = I2C_DF_NOTIFY,
++      .attach_adapter = ds1307_probe,
++      .detach_client  = ds1307_detach,
++      .command        = ds1307_command,
++};
++
++static spinlock_t ds1307_rtc_lock = SPIN_LOCK_UNLOCKED;
++
++static int
++ds1307_readram( char *buf, int len)
++{
++      unsigned long   flags;
++      unsigned char ad[1] = { 0 };
++      int ret;
++      struct i2c_msg msgs[2] = {
++              { ds1307_i2c_client->addr  , 0,        1, ad  },
++              { ds1307_i2c_client->addr  , I2C_M_RD, len, buf } };
++
++      spin_lock_irqsave(&ds1307_rtc_lock, flags);
++      ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
++      spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
++
++      return ret;
++}
++
++static void
++ds1307_dumpram( void)
++{
++      unsigned char buf[DS1307_RAM_SIZE];
++      int ret;
++
++      ret = ds1307_readram( buf, DS1307_RAM_SIZE);
++
++      if( ret > 0)
++      {
++              int i;
++              for( i=0; i<DS1307_RAM_SIZE; i++)
++              {
++                      printk ("%02X ", buf[i]);
++                      if( (i%8) == 7) printk ("\n");
++              }
++              printk ("\n");
++      }
++}
++
++static void
++ds1307_enable_clock( int enable)
++{
++      unsigned char buf[2], ad[1] = { 0 };
++      struct i2c_msg msgs[2] = {
++              { ds1307_i2c_client->addr       , 0,        1, ad  },
++              { ds1307_i2c_client->addr       , I2C_M_RD, 1, buf }
++      };
++      unsigned char ctrl_info;
++      int ret;
++
++      DPRINTK(1, "%s()\n", __FUNCTION__);
++
++      if (enable)
++              ctrl_info = SQW_ENABLE | RATE_32768HZ;
++      else
++              ctrl_info = SQW_DISABLE;
++      ret = ds1307_command(ds1307_i2c_client, DS1307_SETCTRL, &ctrl_info);
++      DPRINTK(2, "%s: set ctrl rtn'd %d\n", __FUNCTION__, ret);
++
++      /* read addr 0 (Clock-Halt bit and second counter */
++      ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
++      DPRINTK(2, "%s: %s msg xfer rtn'd %d\n", __FUNCTION__, enable ? "enable" : "disable", ret);
++
++      if (enable)
++              buf[1] = buf[0] & ~CLOCK_HALT; /* clear Clock-Halt bit */
++      else
++              buf[1] = buf[0] | CLOCK_HALT; /* set Clock-Halt bit */
++      buf[0] = 0;     /* control register address on DS1307 */
++
++      ret = i2c_master_send(ds1307_i2c_client, (char *)buf, 2);
++      DPRINTK(2, "%s: master send rtn'd %d\n", __FUNCTION__, ret);
++}
++
++static int
++ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt);
++
++static int
++ds1307_attach(struct i2c_adapter *adap, int addr, int kind)
++{
++      struct i2c_client *c;
++
++      DPRINTK(1, "%s()\n", __FUNCTION__);
++
++      c = (struct i2c_client *)kmalloc(sizeof(*c), GFP_KERNEL);
++      if (!c)
++              return -ENOMEM;
++      memset(c, 0, sizeof(*c));
++
++      strcpy(c->name, "DS1307");
++      c->flags        = 0;
++      c->addr         = addr;
++      c->adapter      = adap;
++      c->driver       = &ds1307_driver;
++
++      ds1307_i2c_client = c;
++      ds1307_enable_clock(1);
++
++#define DS1307_SET_TIME_ON_BOOT
++#ifdef DS1307_SET_TIME_ON_BOOT
++      {
++              struct rtc_time dt;
++              ds1307_get_datetime(c, &dt);
++              xtime.tv_sec = mktime(dt.tm_year + 1900,
++                                    dt.tm_mon + 1, /* tm_mon starts from 0 */
++                                    dt.tm_mday,
++                                    dt.tm_hour,
++                                    dt.tm_min,
++                                    dt.tm_sec);
++      }
++#endif
++
++      return i2c_attach_client(c);
++}
++
++static int
++ds1307_probe(struct i2c_adapter *adap)
++{
++      DPRINTK(1, "%s()\n", __FUNCTION__);
++
++      return i2c_probe(adap, &addr_data, ds1307_attach);
++}
++
++static int
++ds1307_detach(struct i2c_client *client)
++{
++      DPRINTK(1, "%s()\n", __FUNCTION__);
++
++      i2c_detach_client(client);
++      ds1307_enable_clock(0);
++
++      return 0;
++}
++
++static void
++ds1307_convert_to_time( struct rtc_time *dt, char *buf)
++{
++      dt->tm_sec = BCD_TO_BIN(buf[0]);
++      dt->tm_min = BCD_TO_BIN(buf[1]);
++
++      if ( TWELVE_HOUR_MODE(buf[2]) )
++      {
++              dt->tm_hour = HOURS_12(buf[2]);
++              if (HOURS_AP(buf[2])) /* PM */
++              {
++                      dt->tm_hour += 12;
++              }
++      }
++      else /* 24-hour-mode */
++      {
++              dt->tm_hour = HOURS_24(buf[2]);
++      }
++
++      dt->tm_mday = BCD_TO_BIN(buf[4]);
++      /* dt->tm_mon is zero-based */
++      dt->tm_mon = BCD_TO_BIN(buf[5]) - 1;
++      /* year is 1900 + dt->tm_year */
++      dt->tm_year = BCD_TO_BIN(buf[6]) + 100;
++
++      if (rtc_debug > 1)
++      {
++              printk("ds1307_get_datetime: year = %d\n", dt->tm_year);
++              printk("ds1307_get_datetime: mon  = %d\n", dt->tm_mon);
++              printk("ds1307_get_datetime: mday = %d\n", dt->tm_mday);
++              printk("ds1307_get_datetime: hour = %d\n", dt->tm_hour);
++              printk("ds1307_get_datetime: min  = %d\n", dt->tm_min);
++              printk("ds1307_get_datetime: sec  = %d\n", dt->tm_sec);
++      }
++}
++
++static int
++ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt)
++{
++      unsigned char buf[7], addr[1] = { 0 };
++      struct i2c_msg msgs[2] = {
++              { 0, 0,   1, addr },
++              { 0, I2C_M_RD, 7, buf  }
++      };
++      int ret = -EIO;
++
++      DPRINTK(1, "%s()\n", __FUNCTION__);
++
++      if (client) {
++
++              msgs[0].addr = client->addr;
++              msgs[1].addr = client->addr;
++
++              memset(buf, 0, sizeof(buf));
++
++              ret = i2c_transfer(client->adapter, msgs, 2);
++
++              if (ret == 2) {
++                      ds1307_convert_to_time( dt, buf);
++                      ret = 0;
++              } else {
++                      DPRINTK(0, "%s: i2c_transfer() returned %d\n", __FUNCTION__, ret);
++              }
++      }
++      return ret;
++}
++
++static int
++ds1307_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
++{
++      unsigned char buf[8];
++      int ret, len = 4;
++
++      DPRINTK(1, "%s()\n", __FUNCTION__);
++
++      if (!client) return -EIO;
++
++      if (rtc_debug > 1)
++      {
++              printk("ds1307_set_datetime: tm_year = %d\n", dt->tm_year);
++              printk("ds1307_set_datetime: tm_mon  = %d\n", dt->tm_mon);
++              printk("ds1307_set_datetime: tm_mday = %d\n", dt->tm_mday);
++              printk("ds1307_set_datetime: tm_hour = %d\n", dt->tm_hour);
++              printk("ds1307_set_datetime: tm_min  = %d\n", dt->tm_min);
++              printk("ds1307_set_datetime: tm_sec  = %d\n", dt->tm_sec);
++      }
++
++      buf[0] = 0;     /* register address on DS1307 */
++      buf[1] = (BIN_TO_BCD(dt->tm_sec));
++      buf[2] = (BIN_TO_BCD(dt->tm_min));
++      buf[3] = (BIN_TO_BCD(dt->tm_hour));
++
++      if (datetoo) {
++              len = 8;
++              /* we skip buf[4] as we don't use day-of-week. */
++              buf[5] = (BIN_TO_BCD(dt->tm_mday));
++              buf[6] = (BIN_TO_BCD(dt->tm_mon + 1));
++              /* The year only ranges from 0-99, we are being passed an offset from 1900,
++               * and the chip calulates leap years based on 2000, thus we adjust by 100.
++               */
++              buf[7] = (BIN_TO_BCD(dt->tm_year - 100));
++      }
++      ret = i2c_master_send(client, (char *)buf, len);
++      if (ret == len)
++              ret = 0;
++      else
++              DPRINTK(0, "%s: i2c_master_send() returned %d\n", __FUNCTION__, ret);
++
++      return ret;
++}
++
++static int
++ds1307_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
++{
++      unsigned char addr[1] = { 7 };  /* control register address on DS1307 */
++      struct i2c_msg msgs[2] = {
++              { 0, 0,        1, addr },
++              { 0, I2C_M_RD, 1, ctrl }
++      };
++      int ret = -EIO;
++
++      DPRINTK(1, "%s()\n", __FUNCTION__);
++
++      if (client) {
++
++              msgs[0].addr = client->addr;
++              msgs[1].addr = client->addr;
++
++              *ctrl = 0;
++
++              ret = i2c_transfer(client->adapter, msgs, 2);
++
++              if (ret == 2) {
++                      DPRINTK(2, "%s: info %d\n", __FUNCTION__, *ctrl);
++                      ret = 0;
++              } else {
++                      DPRINTK(0, "%s: i2c_transfer() returned %d\n", __FUNCTION__, ret);
++              }
++      }
++
++      return ret;
++}
++
++static int
++ds1307_set_ctrl(struct i2c_client *client, unsigned char *cinfo)
++{
++      unsigned char buf[2];
++      int ret;
++
++      buf[0] = 7;     /* control register address on DS1307 */
++      buf[1] = *cinfo;
++
++      DPRINTK(2, "%s: info %d\n", __FUNCTION__, buf[1]);
++
++      ret = i2c_master_send(client, (char *)buf, 2);
++
++      return ret;
++}
++
++static int
++ds1307_read_mem(struct i2c_client *client, struct rtc_mem *mem)
++{
++      unsigned char addr[1];
++      struct i2c_msg msgs[2] = {
++              { client->addr, 0,        1, addr },
++              { client->addr, I2C_M_RD, mem->nr, mem->data }
++      };
++
++      if ( (mem->loc < DS1307_RAM_ADDR_START) ||
++           ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
++              return -EINVAL;
++
++      addr[0] = mem->loc;
++
++      return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
++}
++
++static int
++ds1307_write_mem(struct i2c_client *client, struct rtc_mem *mem)
++{
++      unsigned char addr[1];
++      struct i2c_msg msgs[2] = {
++              { client->addr, 0, 1, addr },
++              { client->addr, 0, mem->nr, mem->data }
++      };
++
++      if ( (mem->loc < DS1307_RAM_ADDR_START) ||
++           ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
++              return -EINVAL;
++
++      addr[0] = mem->loc;
++
++      return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
++}
++
++static int
++ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg)
++{
++      DPRINTK(1, "%s: cmd %d\n", __FUNCTION__, cmd);
++
++      switch (cmd) {
++      case DS1307_GETDATETIME:
++              return ds1307_get_datetime(client, arg);
++
++      case DS1307_SETTIME:
++              return ds1307_set_datetime(client, arg, 0);
++
++      case DS1307_SETDATETIME:
++              return ds1307_set_datetime(client, arg, 1);
++
++      case DS1307_GETCTRL:
++              return ds1307_get_ctrl(client, arg);
++
++      case DS1307_SETCTRL:
++              return ds1307_set_ctrl(client, arg);
++
++      case DS1307_MEM_READ:
++              return ds1307_read_mem(client, arg);
++
++      case DS1307_MEM_WRITE:
++              return ds1307_write_mem(client, arg);
++
++      default:
++              return -EINVAL;
++      }
++}
++
++static int
++ds1307_rtc_open(struct inode *inode, struct file *file)
++{
++      return 0;
++}
++
++static int
++ds1307_rtc_release(struct inode *inode, struct file *file)
++{
++      return 0;
++}
++
++static int
++ds1307_rtc_ioctl( struct inode *inode, struct file *file,
++              unsigned int cmd, unsigned long arg)
++{
++      unsigned long   flags;
++      struct rtc_time wtime;
++      int status = 0;
++
++      DPRINTK(2, "%s: cmd %c %x\n", __FUNCTION__, (char)(cmd>>8)&0xff, cmd&0xff);
++
++      switch (cmd) {
++              default:
++              case RTC_UIE_ON:
++              case RTC_UIE_OFF:
++              case RTC_PIE_ON:
++              case RTC_PIE_OFF:
++              case RTC_AIE_ON:
++              case RTC_AIE_OFF:
++              case RTC_ALM_SET:
++              case RTC_ALM_READ:
++              case RTC_IRQP_READ:
++              case RTC_IRQP_SET:
++              case RTC_EPOCH_READ:
++              case RTC_EPOCH_SET:
++              case RTC_WKALM_SET:
++              case RTC_WKALM_RD:
++                      status = -EINVAL;
++                      break;
++
++              case RTC_RD_TIME:
++                      spin_lock_irqsave(&ds1307_rtc_lock, flags);
++                      ds1307_command( ds1307_i2c_client, DS1307_GETDATETIME, &wtime);
++                      spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
++
++                      if( copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)))
++                              status = -EFAULT;
++                      break;
++
++              case RTC_SET_TIME:
++                      if (!capable(CAP_SYS_TIME))
++                      {
++                              status = -EACCES;
++                              break;
++                      }
++
++                      if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) )
++                      {
++                              status = -EFAULT;
++                              break;
++                      }
++
++                      spin_lock_irqsave(&ds1307_rtc_lock, flags);
++                      ds1307_command( ds1307_i2c_client, DS1307_SETDATETIME, &wtime);
++                      spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
++                      break;
++      }
++
++      return status;
++}
++
++static char *
++ds1307_mon2str( unsigned int mon)
++{
++      char *mon2str[12] = {
++        "Jan", "Feb", "Mar", "Apr", "May", "Jun",
++        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
++      };
++      if( mon > 11) return "error";
++      else return mon2str[ mon];
++}
++
++static int ds1307_rtc_proc_output( char *buf)
++{
++#define CHECK(ctrl,bit) ((ctrl & bit) ? "yes" : "no")
++      unsigned char ram[DS1307_RAM_SIZE];
++      int ret;
++
++      char *p = buf;
++
++      ret = ds1307_readram( ram, DS1307_RAM_SIZE);
++      if( ret > 0)
++      {
++              int i;
++              struct rtc_time dt;
++              char text[9];
++
++              p += sprintf(p, "DS1307 (64x8 Serial Real Time Clock)\n");
++
++              ds1307_convert_to_time( &dt, ram);
++              p += sprintf(p, "Date/Time           : %02d-%s-%04d %02d:%02d:%02d\n",
++                      dt.tm_mday, ds1307_mon2str(dt.tm_mon), dt.tm_year + 1900,
++                      dt.tm_hour, dt.tm_min, dt.tm_sec);
++
++              p += sprintf(p, "Clock halted        : %s\n", CHECK(ram[0],0x80));
++              p += sprintf(p, "24h mode            : %s\n", CHECK(ram[2],0x40));
++              p += sprintf(p, "Square wave enabled : %s\n", CHECK(ram[7],0x10));
++              p += sprintf(p, "Freq                : ");
++
++              switch( ram[7] & 0x03)
++              {
++                      case RATE_1HZ:
++                              p += sprintf(p, "1Hz\n");
++                              break;
++                      case RATE_4096HZ:
++                              p += sprintf(p, "4.096kHz\n");
++                              break;
++                      case RATE_8192HZ:
++                              p += sprintf(p, "8.192kHz\n");
++                              break;
++                      case RATE_32768HZ:
++                      default:
++                              p += sprintf(p, "32.768kHz\n");
++                              break;
++
++              }
++
++              p += sprintf(p, "RAM dump:\n");
++              text[8]='\0';
++              for( i=0; i<DS1307_RAM_SIZE; i++)
++              {
++                      p += sprintf(p, "%02X ", ram[i]);
++
++                      if( (ram[i] < 32) || (ram[i]>126)) ram[i]='.';
++                      text[i%8] = ram[i];
++                      if( (i%8) == 7) p += sprintf(p, "%s\n",text);
++              }
++              p += sprintf(p, "\n");
++      }
++      else
++      {
++              p += sprintf(p, "Failed to read RTC memory!\n");
++      }
++
++      return  p - buf;
++}
++
++static int ds1307_rtc_read_proc(char *page, char **start, off_t off,
++              int count, int *eof, void *data)
++{
++      int len = ds1307_rtc_proc_output (page);
++      if (len <= off+count) *eof = 1;
++      *start = page + off;
++      len -= off;
++      if (len>count) len = count;
++      if (len<0) len = 0;
++      return len;
++}
++
++static __init int ds1307_init(void)
++{
++      int retval=0;
++
++      DPRINTK(1, "%s()\n", __FUNCTION__);
++
++      if (slave_address != 0xffff)
++      {
++              DPRINTK(2, "%s: slave address is %#x\n", __FUNCTION__, slave_address);
++              normal_addr[0] = slave_address;
++      }
++
++      if (normal_addr[0] == 0xffff)
++      {
++              printk(KERN_ERR"I2C: Invalid slave address for DS1307 RTC (%#x)\n",
++                      normal_addr[0]);
++              return -EINVAL;
++      }
++
++      retval = i2c_add_driver(&ds1307_driver);
++
++      if (retval==0)
++      {
++              misc_register (&ds1307_rtc_miscdev);
++              create_proc_read_entry (PROC_DS1307_NAME, 0, 0, ds1307_rtc_read_proc, NULL);
++              printk("I2C: DS1307 RTC driver successfully loaded\n");
++              if (rtc_debug > 2) ds1307_dumpram();
++      }
++      return retval;
++}
++
++static __exit void ds1307_exit(void)
++{
++      DPRINTK(1, "%s()\n", __FUNCTION__);
++      remove_proc_entry (PROC_DS1307_NAME, NULL);
++      misc_deregister(&ds1307_rtc_miscdev);
++      i2c_del_driver(&ds1307_driver);
++}
++
++module_init(ds1307_init);
++module_exit(ds1307_exit);
++
++MODULE_PARM (slave_address, "i");
++MODULE_PARM_DESC (slave_address, "I2C slave address for DS1307 RTC.");
++
++MODULE_AUTHOR ("Intrinsyc Software Inc.");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/i2c/chips/ds1307.h b/drivers/i2c/chips/ds1307.h
+new file mode 100644
+index 0000000..bf8cc20
+--- /dev/null
++++ b/drivers/i2c/chips/ds1307.h
+@@ -0,0 +1,54 @@
++/*
++ * ds1307.h
++ *
++ * Copyright (C) 2002 Intrinsyc Software Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ */
++#ifndef DS1307_H
++#define DS1307_H
++
++#define DS1307_I2C_SLAVE_ADDR 0x68
++
++#define DS1307_RAM_ADDR_START 0x08
++#define DS1307_RAM_ADDR_END   0x3F
++#define DS1307_RAM_SIZE 0x40
++
++#define PROC_DS1307_NAME      "driver/ds1307"
++
++struct rtc_mem {
++      unsigned int    loc;
++      unsigned int    nr;
++      unsigned char   *data;
++};
++
++#define DS1307_GETDATETIME    0
++#define DS1307_SETTIME                1
++#define DS1307_SETDATETIME    2
++#define DS1307_GETCTRL                3
++#define DS1307_SETCTRL                4
++#define DS1307_MEM_READ               5
++#define DS1307_MEM_WRITE      6
++
++#define SQW_ENABLE    0x10    /* Square Wave Enable */
++#define SQW_DISABLE   0x00    /* Square Wave disable */
++
++#define RATE_32768HZ  0x03    /* Rate Select 32.768KHz */
++#define RATE_8192HZ   0x02    /* Rate Select 8.192KHz */
++#define RATE_4096HZ   0x01    /* Rate Select 4.096KHz */
++#define RATE_1HZ      0x00    /* Rate Select 1Hz */
++
++#define CLOCK_HALT    0x80    /* Clock Halt */
++
++#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
++#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
++
++#define TWELVE_HOUR_MODE(n)   (((n)>>6)&1)
++#define HOURS_AP(n)           (((n)>>5)&1)
++#define HOURS_12(n)           BCD_TO_BIN((n)&0x1F)
++#define HOURS_24(n)           BCD_TO_BIN((n)&0x3F)
++
++#endif
+diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
+index 02682fb..6a28f08 100644
+--- a/drivers/i2c/chips/ds1337.c
++++ b/drivers/i2c/chips/ds1337.c
+@@ -338,12 +338,37 @@ exit:
+ static void ds1337_init_client(struct i2c_client *client)
+ {
+       s32 val;
++      u8 status, control;
++
++      /* On some boards, the RTC isn't configured by boot firmware.
++       * Handle that case by starting/configuring the RTC now.
++       */
++      status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
++      control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
++
++      if ((status & 0x80) || (control & 0x80)) {
++              /* RTC not running */
++              u8 buf[16];
++              struct i2c_msg msg[1];
++              
++              dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
++
++              /* Initialize all, including STATUS and CONTROL to zero */
++              memset(buf, 0, sizeof(buf));
++              msg[0].addr = client->addr;
++              msg[0].flags = 0;
++              msg[0].len = sizeof(buf);
++              msg[0].buf = &buf[0];
++              
++              i2c_transfer(client->adapter, msg, 1);
++      } else {
++              /* Running: ensure that device is set in 24-hour mode */
++              val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
++              if ((val >= 0) && (val & (1 << 6)))
++                      i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
++                                                val & 0x3f);
++      }
+-      /* Ensure that device is set in 24-hour mode */
+-      val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
+-      if ((val >= 0) && (val & (1 << 6)))
+-              i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
+-                                        val & 0x3f);
+ }
+ static int ds1337_detach_client(struct i2c_client *client)
+diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
+index 1c81174..e0fcc08 100644
+--- a/drivers/ide/Kconfig
++++ b/drivers/ide/Kconfig
+@@ -314,6 +314,18 @@ config BLK_DEV_CMD640_ENHANCED
+         and your BIOS does not already do this for you, then say Y here.
+         Otherwise say N.
++config BLK_DEV_EP93XX
++      bool "EP93xx support"
++      depends on (ARCH_EP9312 || ARCH_EP9315)
++      help
++        If you want IDE support for your EP93xx based board say Y here.
++
++config BLK_DEV_IDEDMA_EP93XX
++      bool "EP93xx DMA support"
++      depends on BLK_DEV_EP93XX && EP93XX_DMA
++      help
++        If you want DMA support for your EP93xx based board say Y here.
++
+ config BLK_DEV_IDEPNP
+       bool "PNP EIDE support"
+       depends on PNP
+@@ -813,7 +825,7 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
+        depends BLK_DEV_IDE_AU1XXX
+ config IDE_ARM
+-      def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
++      def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK || BLK_DEV_EP93XX)
+ config BLK_DEV_IDE_ICSIDE
+       tristate "ICS IDE interface support"
+@@ -1047,7 +1059,7 @@ config BLK_DEV_UMC8672
+ endif
+ config BLK_DEV_IDEDMA
+-      def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
++      def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA || BLK_DEV_IDEDMA_EP93XX
+ config IDEDMA_IVB
+       bool "IGNORE word93 Validation BITS"
+diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile
+index 6a78f07..cf0f91a 100644
+--- a/drivers/ide/arm/Makefile
++++ b/drivers/ide/arm/Makefile
+@@ -2,5 +2,6 @@
+ obj-$(CONFIG_BLK_DEV_IDE_ICSIDE)      += icside.o
+ obj-$(CONFIG_BLK_DEV_IDE_RAPIDE)      += rapide.o
+ obj-$(CONFIG_BLK_DEV_IDE_BAST)                += bast-ide.o
++obj-$(CONFIG_BLK_DEV_EP93XX)          += ide-ep93xx.o
+ EXTRA_CFLAGS  := -Idrivers/ide
+diff --git a/drivers/ide/arm/ide-ep93xx.c b/drivers/ide/arm/ide-ep93xx.c
+new file mode 100644
+index 0000000..75fbbf5
+--- /dev/null
++++ b/drivers/ide/arm/ide-ep93xx.c
+@@ -0,0 +1,1957 @@
++/*****************************************************************************
++ *
++ * drivers/ide/ide-ep93xx.c
++ *
++ *  Copyright (c) 2003 Cirrus Logic, Inc.
++ *
++ * Some code based in whole or in part on:
++ *
++ *      linux/drivers/ide/ide-dma.c           Version 4.13    May 21, 2003
++ *
++ *      Copyright (c) 1999-2000       Andre Hedrick <andre@linux-ide.org>
++ *      May be copied or modified under the terms of the GNU General Public License
++ *
++ *      Portions Copyright Red Hat 2003
++ *
++ *      Special Thanks to Mark for his Six years of work.
++ *
++ *      Copyright (c) 1995-1998  Mark Lord
++ *      May be copied or modified under the terms of the GNU General Public License
++ *
++ *
++ * Some code taken from the PowerMac implentation
++ *
++ *      Copyright (C) 1998-2001 Paul Mackerras & Ben. Herrenschmidt
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ * ***************************************************************************
++ *
++ * Cirrus Logic's EP93XX architecture specific ide driver. This driver
++ * supports the following ide transfer modes:
++ *  PIO modes 0 - 4
++ *  MDMA modes 0 - 2
++ *  UDMA modes 0 - 4
++ *
++ * 2/17/04 - TO - Initial DMA support.  Only UDMA on ATA hard drives for now.
++ *
++ ****************************************************************************/
++#include <linux/ide.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++#include <asm/ide.h>
++#include <asm/io.h>
++
++#include <asm/arch/ide.h>
++
++#include <asm/arch/dma.h>
++#include <asm/hardware.h>
++
++/*****************************************************************************
++ *
++ * Debugging macros
++ *
++ ****************************************************************************/
++#undef DEBUG
++ /* #define DEBUG 1 */
++#ifdef DEBUG
++#define DPRINTK( x... )  printk( ##x )
++#else
++#define DPRINTK( x... )
++#endif
++
++/*
++ *  IDE control register mask used when setting the CS0n, CS1n and DA bits
++ *  in this register.
++ */
++#define IDECR_REG_MASK          (IDECtrl_CS0n | IDECtrl_CS1n | IDECtrl_DA_MASK)
++
++/*****************************************************************************
++ *
++ * Functions and macros for handling dma transfers.
++ *
++ ****************************************************************************/
++#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX
++
++/*****************************************************************************
++ *
++ * Our Physical Region Descriptor (PRD) table should be large enough
++ * to handle the biggest I/O request we are likely to see.  Since requests
++ * can have no more than 256 sectors, and since the typical blocksize is
++ * two or more sectors, we could get by with a limit of 128 entries here for
++ * the usual worst case.  Most requests seem to include some contiguous blocks,
++ * further reducing the number of table entries required.
++ *
++ * The driver reverts to PIO mode for individual requests that exceed
++ * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling
++ * 100% of all crazy scenarios here is not necessary.
++ *
++ * As it turns out though, we must allocate a full 4KB page for this,
++ * so the two PRD tables (ide0 & ide1) will each get half of that,
++ * allowing each to have about 256 entries (8 bytes each) from this.
++ *
++ ****************************************************************************/
++#define PRD_BYTES     8
++#define PRD_ENTRIES   (PAGE_SIZE / (2 * PRD_BYTES))
++
++/*****************************************************************************
++ *
++ * Global to keep track of the number of entries in the dma buffer
++ * table for each transfer.
++ *
++ ****************************************************************************/
++static int g_prd_count;
++static unsigned int g_prd_total;
++static unsigned int g_prd_returned;
++static unsigned int g_dma_table_base;
++
++/*****************************************************************************
++ *
++ * Global to set during the dma callback function to indicate that from
++ * the dma perspective, the transfer is complete.
++ *
++ ****************************************************************************/
++static unsigned int g_done;
++
++/*****************************************************************************
++ *
++ * The following is directly from ide-dma.c.
++ *
++ ****************************************************************************/
++struct drive_list_entry {
++      const char *id_model;
++      const char *id_firmware;
++};
++
++static const struct
++drive_list_entry drive_whitelist[] = {
++      {"Micropolis 2112A", "ALL"},
++      {"CONNER CTMA 4000", "ALL"},
++      {"CONNER CTT8000-A", "ALL"},
++      {"ST34342A", "ALL"},
++      {NULL, NULL}
++};
++
++static const struct
++drive_list_entry drive_blacklist[] = {
++      {"WDC AC11000H", "ALL"},
++      {"WDC AC22100H", "ALL"},
++      {"WDC AC32500H", "ALL"},
++      {"WDC AC33100H", "ALL"},
++      {"WDC AC31600H", "ALL"},
++      {"WDC AC32100H", "24.09P07"},
++      {"WDC AC23200L", "21.10N21"},
++      {"Compaq CRD-8241B", "ALL"},
++      {"CRD-8400B", "ALL"},
++      {"CRD-8480B", "ALL"},
++      {"CRD-8480C", "ALL"},
++      {"CRD-8482B", "ALL"},
++      {"CRD-84", "ALL"},
++      {"SanDisk SDP3B", "ALL"},
++      {"SanDisk SDP3B-64", "ALL"},
++      {"SANYO CD-ROM CRD", "ALL"},
++      {"HITACHI CDR-8", "ALL"},
++      {"HITACHI CDR-8335", "ALL"},
++      {"HITACHI CDR-8435", "ALL"},
++      {"Toshiba CD-ROM XM-6202B", "ALL"},
++      {"CD-532E-A", "ALL"},
++      {"E-IDE CD-ROM CR-840", "ALL"},
++      {"CD-ROM Drive/F5A", "ALL"},
++      {"RICOH CD-R/RW MP7083A", "ALL"},
++      {"WPI CDD-820", "ALL"},
++      {"SAMSUNG CD-ROM SC-148C", "ALL"},
++      {"SAMSUNG CD-ROM SC-148F", "ALL"},
++      {"SAMSUNG CD-ROM SC", "ALL"},
++      {"SanDisk SDP3B-64", "ALL"},
++      {"SAMSUNG CD-ROM SN-124", "ALL"},
++      {"PLEXTOR CD-R PX-W8432T", "ALL"},
++      {"ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL"},
++      {"_NEC DV5800A", "ALL"},
++      {NULL, NULL}
++};
++
++/*****************************************************************************
++ *
++ *    This is directly from ide-dma.c
++ *
++ *  in_drive_list     -       look for drive in black/white list
++ *    @id: drive identifier
++ *    @drive_table: list to inspect
++ *
++ *    Look for a drive in the blacklist and the whitelist tables
++ *    Returns 1 if the drive is found in the table.
++ *
++ ****************************************************************************/
++static int
++in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table)
++{
++      for (; drive_table->id_model; drive_table++)
++              if ((!strcmp(drive_table->id_model, id->model)) &&
++                  ((!strstr(drive_table->id_firmware, id->fw_rev)) ||
++                   (!strcmp(drive_table->id_firmware, "ALL"))))
++                      return 1;
++      return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_intr() is the handler for disk read/write DMA interrupts
++ *
++ ****************************************************************************/
++ide_startstop_t ep93xx_ide_dma_intr(ide_drive_t * drive)
++{
++      int i;
++      byte stat, dma_stat;
++
++      DPRINTK("\n dma_intr \n");
++
++      /*
++       *  Disable the dma for this transfer and cleanup.
++       */
++      dma_stat = ep93xx_ide_dma_end(drive);
++
++      /*
++       *  Get status from the ide device.
++       */
++      stat = HWIF(drive)->INB(IDE_STATUS_REG);
++
++      if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
++              if (!dma_stat) {
++                      struct request *rq = HWGROUP(drive)->rq;
++
++                      for (i = rq->nr_sectors; i > 0;) {
++                              i -= rq->current_nr_sectors;
++                              DRIVER(drive)->end_request(drive, 1);
++                      }
++
++                      return ide_stopped;
++              }
++
++              printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n",
++                     drive->name, dma_stat);
++      }
++
++      return DRIVER(drive)->error(drive, __FUNCTION__, stat);
++}
++
++/*****************************************************************************
++ *
++ * ide_build_sglist()
++ *
++ * Builds a table of buffers to be used by the dma.  Each buffer consists
++ * of a region of memory which is contiguous in virtual memory.
++ *
++ ****************************************************************************/
++static int ide_build_sglist(ide_hwif_t * hwif, struct request *rq)
++{
++      struct buffer_head *buf_head;
++      struct scatterlist *sg = hwif->sg_table;
++      int nents = 0;
++
++      if (hwif->sg_dma_active)
++              BUG();
++
++      DPRINTK("\nbuild_sglist: sg_table 0x%x, ", hwif->sg_table);
++
++      /*
++       *  Set up the direction of the command
++       */
++      if (rq->cmd == READ) {
++              hwif->sg_dma_direction = EP93XX_DMA_FROMDEVICE;
++      } else {
++              hwif->sg_dma_direction = EP93XX_DMA_TODEVICE;
++      }
++
++      /*
++       *  Get a pointer to the buffer head.
++       */
++      buf_head = rq->bh;
++
++      do {
++              unsigned char *virt_addr = buf_head->b_data;
++              unsigned int size = buf_head->b_size;
++
++              if (nents >= PRD_ENTRIES) {
++                      return 0;
++              }
++
++              while ((buf_head = buf_head->b_reqnext) != NULL) {
++                      if ((virt_addr + size) !=
++                          (unsigned char *)buf_head->b_data) {
++                              break;
++                      }
++
++                      size += buf_head->b_size;
++              }
++              memset(&sg[nents], 0, sizeof(*sg));
++              sg[nents].address = virt_addr;
++              sg[nents].length = size;
++              nents++;
++      } while (buf_head != NULL);
++
++      /*
++       *  This call to map_sg will return the number of entries
++       *  for which DMAable memory could be mapped.
++       */
++      return ep93xx_map_sg(sg, nents, hwif->sg_dma_direction);
++}
++
++/****************************************************************************
++ *
++ * report_drive_dmaing()
++ *
++ ****************************************************************************/
++int report_drive_dmaing(ide_drive_t * drive)
++{
++      struct hd_driveid *id = drive->id;
++
++      if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
++          (id->dma_ultra & (id->dma_ultra >> 14) & 3)) {
++              if ((id->dma_ultra >> 15) & 1) {
++                      /*
++                       *  UDMA enabled
++                       */
++                      printk(", UDMA(mode 7)");
++              } else {
++                      /*
++                       *  UDMA enabled.
++                       */
++                      printk(", UDMA(133)");
++              }
++      } else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
++                 (id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
++              DPRINTK("\n report_drive_dmaing: %d \n", id->dma_ultra);
++              if ((id->dma_ultra >> 13) & 1) {
++                      /*
++                       *  UDMA enabled!
++                       */
++                      printk(", UDMA(100)");
++              } else if ((id->dma_ultra >> 12) & 1) {
++                      /*
++                       *  UDMA enabled.
++                       */
++                      printk(", UDMA(66)");
++              } else {
++                      /*
++                       *  UDMA enabled.
++                       */
++                      printk(", UDMA(44)");
++              }
++      } else if ((id->field_valid & 4) &&
++                 (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
++              if ((id->dma_ultra >> 10) & 1) {
++                      /*
++                       * UDMA enabled.
++                       */
++                      printk(", UDMA(33)");
++              } else if ((id->dma_ultra >> 9) & 1) {
++                      /*
++                       *  UDMA enabled.
++                       */
++                      printk(", UDMA(25)");
++              } else {
++                      /*
++                       *  UDMA enabled.
++                       */
++                      printk(", UDMA(16)");
++              }
++      } else if (id->field_valid & 4) {
++              /*
++               *  Can be enabled.
++               */
++              printk(", (U)DMA capable, but not enabled");
++      } else {
++              /*
++               *  maybe MDMA?
++               */
++              printk(", DMA");
++      }
++
++      return 1;
++}
++
++/*****************************************************************************
++ *
++ * ide_build_dmatable() prepares a dma request.
++ * Returns 0 if all went okay, returns 1 otherwise.
++ *
++ ****************************************************************************/
++int ide_build_dmatable(ide_drive_t * drive)
++{
++      unsigned int *table = HWIF(drive)->dmatable_cpu;
++      unsigned int count = 0;
++      int i;
++      struct scatterlist *sg;
++      unsigned int is_trm290_chipset = 0;
++
++      HWIF(drive)->sg_nents = i =
++          ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
++
++      if (!i)
++              return 0;
++
++      sg = HWIF(drive)->sg_table;
++
++      while (i && sg_dma_len(sg)) {
++              u32 cur_addr;
++              u32 cur_len;
++
++              cur_addr = sg_dma_address(sg);
++              cur_len = sg_dma_len(sg);
++
++              /*                                                                                      1
++               * Fill in the dma table, without crossing any 64kB boundaries.
++               * Most hardware requires 16-bit alignment of all blocks,
++               * but the trm290 requires 32-bit alignment.
++               */
++              while (cur_len) {
++
++                      if (count++ >= PRD_ENTRIES) {
++                              printk("%s: DMA table too small\n",
++                                     drive->name);
++                              goto use_pio_instead;
++                      } else {
++                              u32 xcount, bcount =
++                                  0x10000 - (cur_addr & 0xffff);
++
++                              if (bcount > cur_len)
++                                      bcount = cur_len;
++                              *table++ = cpu_to_le32(cur_addr);
++                              xcount = bcount & 0xffff;
++                              if (is_trm290_chipset)
++                                      xcount = ((xcount >> 2) - 1) << 16;
++                              if (xcount == 0x0000) {
++                                      /*
++                                       * Most chipsets correctly interpret a length of 0x0000 as 64KB,
++                                       * but at least one (e.g. CS5530) misinterprets it as zero (!).
++                                       * So here we break the 64KB entry into two 32KB entries instead.
++                                       */
++                                      if (count++ >= PRD_ENTRIES) {
++                                              printk
++                                                  ("%s: DMA table too small\n",
++                                                   drive->name);
++                                              goto use_pio_instead;
++                                      }
++                                      *table++ = cpu_to_le32(0x8000);
++                                      *table++ =
++                                          cpu_to_le32(cur_addr + 0x8000);
++                                      xcount = 0x8000;
++                              }
++                              *table++ = cpu_to_le32(xcount);
++                              cur_addr += bcount;
++                              cur_len -= bcount;
++                      }
++              }
++              sg++;
++              i--;
++      }
++
++      if (count) {
++              if (!is_trm290_chipset)
++                      *--table |= cpu_to_le32(0x80000000);
++              return count;
++      }
++      printk("%s: empty DMA table?\n", drive->name);
++
++      use_pio_instead:
++      /*
++       *  Revert to PIO for this request.
++       */
++      HWIF(drive)->sg_dma_active = 0;
++      return 0;
++}
++
++/*****************************************************************************
++ *
++ * ide_destroy_dmatable()
++ *
++ * Teardown mappings after DMA has completed.
++ *
++ ****************************************************************************/
++void ide_destroy_dmatable(ide_drive_t * drive)
++{
++      /*
++       *  Restore the original dma table base address.
++       */
++      HWIF(drive)->dmatable_cpu = g_dma_table_base;
++
++      /*
++       *  Nothing much to do here.
++       */
++      HWIF(drive)->sg_dma_active = 0;
++}
++
++/*****************************************************************************
++ *
++ * ide_release_dma()
++ *
++ * This function releases the memory allocated for the scatter gather list
++ *  and for the dma table, and frees the dma channel.
++ *
++ ****************************************************************************/
++void ep93xx_ide_release_dma(ide_hwif_t * hwif)
++{
++      /*
++       *  Check if we have a valid dma handle.
++       */
++      if (hwif->hw.dma != NULL) {
++              /*
++               * Pause the DMA channel.
++               */
++              ep93xx_dma_pause(hwif->hw.dma, 1, 0);
++
++              /*
++               *  Flush the DMA channel
++               */
++              ep93xx_dma_flush(hwif->hw.dma);
++      }
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_callback()
++ *
++ * Registered with the ep93xx dma driver and called at the end of the dma
++ * interrupt handler, this function should process the dma buffers.
++ *
++ ****************************************************************************/
++
++static void
++ep93xx_ide_callback(ep93xx_dma_int_t dma_int, ep93xx_dma_dev_t device,
++                  unsigned int user_data)
++{
++      ide_drive_t *drive = (ide_drive_t *) user_data;
++      ide_hwif_t *hwif = HWIF(drive);
++      unsigned int temp;
++
++      /*
++       *  Retrieve from the dma interface as many used buffers as are
++       *  available.
++       */
++      while (ep93xx_dma_remove_buffer(hwif->hw.dma, &temp) == 0) {
++              g_prd_returned++;
++
++      }
++
++      /*
++       *  Add new buffers if we have any available.
++       */
++      while (g_prd_count) {
++              /*
++               *  Check if this is a read or write operation.
++               */
++              if (hwif->sg_dma_direction == 2) {
++                      /*
++                       *  Set up buffers for a read op.
++                       */
++                      temp =
++                          ep93xx_dma_add_buffer(hwif->hw.dma, hwif->dma_base,
++                                                *hwif->dmatable_cpu++,
++                                                *hwif->dmatable_cpu++, 0,
++                                                g_prd_count);
++              } else {
++                      /*
++                       *  Set up buffers for a write op.
++                       */
++                      temp =
++                          ep93xx_dma_add_buffer(hwif->hw.dma,
++                                                *hwif->dmatable_cpu++,
++                                                hwif->dma_base,
++                                                *hwif->dmatable_cpu++, 0,
++                                                g_prd_count);
++              }
++
++              /*
++               *  Add a buffer to the dma interface.
++               */
++              if (temp != 0) {
++                      /*
++                       *  This buffer didn't make it into the dma
++                       *  interface, so move the dma table pointer
++                       *  to the start of the current entry.
++                       */
++                      hwif->dmatable_cpu -= 4;
++                      break;
++              }
++
++              /*
++               *  Decrement the count of dmatable entries
++               */
++              g_prd_count--;
++      }
++
++      /*
++       *  Check if the transfer is complete.
++       */
++      if (dma_int == DONE) {
++              g_done = 1;
++      }
++
++      if (g_prd_returned == g_prd_total) {
++              g_done = 1;
++      }
++}
++
++/*****************************************************************************
++ *
++ *  ep93xx_dma_timer_expiry()
++ *
++ *
++ *    dma_timer_expiry        -       handle a DMA timeout
++ *    @drive: Drive that timed out
++ *
++ *    An IDE DMA transfer timed out. In the event of an error we ask
++ *    the driver to resolve the problem, if a DMA transfer is still
++ *    in progress we continue to wait (arguably we need to add a
++ *    secondary 'I dont care what the drive thinks' timeout here)
++ *    Finally if we have an interrupt we let it complete the I/O.
++ *    But only one time - we clear expiry and if it's still not
++ *    completed after WAIT_CMD, we error and retry in PIO.
++ *    This can occur if an interrupt is lost or due to hang or bugs.
++ *
++ *
++ ****************************************************************************/
++static int ep93xx_idedma_timer_expiry(ide_drive_t * drive)
++{
++      ide_hwif_t *hwif = HWIF(drive);
++      u8 dev_stat = hwif->INB(IDE_ALTSTATUS_REG);
++      u8 irq_stat = ep93xx_ide_regs->IDECR.Value & IDECtrl_INTRQ;
++
++      printk(KERN_WARNING
++             "%s: dma_timer_expiry: dev status == 0x%02x, done= %d, irq= %d\n",
++             drive->name, dev_stat, g_done, irq_stat);
++
++      /*
++       *  Check if the device is busy, or the dma engine is still working.
++       */
++      if ((dev_stat & 0x80) || !g_done)       /* BUSY Stupid Early Timer !! */
++              return (2 * WAIT_CMD);
++
++      /*
++       * Clear the expiry handler in case we decide to wait more,
++       * next time timer expires it is an error
++       */
++      HWGROUP(drive)->expiry = NULL;
++
++      /*
++       *  the device is not busy, so check if there's an error, or if the
++       *  interrupt is asserted.
++       */
++      if (dev_stat & 0x01)    /* ERROR */
++              return -1;
++
++      if (irq_stat || g_done) /* Got an Interrupt or the dma is done */
++              return WAIT_CMD;
++
++      return 0;               /* Unknown status -- reset the bus */
++}
++
++/*****************************************************************************
++ *
++ *    ep93xx_config_ide_dma()
++ *
++ *  This function allocates dma-able memory and configures the ep93xx dma
++ *  interface for use with the ide interface.  This only need be done
++ *  once for the interface.  So, if this is the second drive, we don't have
++ *  much to do here.
++ *
++ ****************************************************************************/
++static int ep93xx_config_ide_dma(ide_drive_t * drive)
++{
++      DPRINTK("ep93xx_config_ide_dma\n");
++
++      /*
++       *  Success.
++       */
++      return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_config_ide_device()
++ *
++ * This function sets up the ep93xx ide device for a dma transfer by first
++ * probing to find the best dma mode supported by the device.
++ *
++ * Returns a 0 for success, and a 1 otherwise.
++ *
++ ****************************************************************************/
++static unsigned int ep93xx_config_ide_device(ide_drive_t * drive)
++{
++      struct hd_driveid *id = drive->id;
++      byte transfer = 0;
++
++      DPRINTK("%s: ep93xx_config_ide_device - dma on\n", HWIF(drive)->name);
++
++      /*
++       * check if the device supports a udma mode.
++       */
++      if (transfer = (id->dma_ultra & 0x001F)) {
++              DPRINTK("IDE: udma xfer support, transfer = %d \n", transfer);
++
++              /*
++               *  UDMA mode 4 support.
++               */
++              if (transfer & 0x10) {
++                      transfer = XFER_UDMA_4;
++              }
++              /*
++               *  UDMA mode 3 support.
++               */
++              else if (transfer & 0x08) {
++                      transfer = XFER_UDMA_3;
++              }
++              /*
++               *  UDMA mode 2.
++               */
++              else if (transfer & 0x04) {
++                      transfer = XFER_UDMA_2;
++              }
++              /*
++               *  UDMA mode 1.
++               */
++              else if (transfer & 0x02) {
++                      transfer = XFER_UDMA_1;
++              }
++              /*
++               *  UDMA mode 0.
++               */
++              else if (transfer & 0x01) {
++                      transfer = XFER_UDMA_0;
++              }
++      }
++      /*
++       *  The device doesn't support a udma mode, so check if it
++       *  supports an mdma mode.
++       */
++      else if (transfer = (drive->id->dma_mword & 0x0007)) {
++              DPRINTK("IDE: mdma support, transfer = %d \n", transfer);
++
++              /*
++               *  MDMA mode 2.
++               */
++              if (transfer & 0x04) {
++                      transfer = XFER_MW_DMA_2;
++              }
++              /*
++               *  MDMA mode 1.
++               */
++              else if (transfer & 0x02) {
++                      transfer = XFER_MW_DMA_1;
++              }
++              /*
++               *  MDMA mode 0.
++               */
++              else if (transfer & 0x01) {
++                      transfer = XFER_MW_DMA_0;
++              }
++      }
++
++      if (transfer == 0) {
++              DPRINTK("IDE: config device failed \n");
++
++              /*
++               *  Fail.
++               */
++              return 1;
++      }
++
++      if (ide_config_drive_speed(drive, transfer) == 0) {
++              printk("%s: %s selected\n", drive->name,
++                     ide_xfer_verbose(transfer));
++
++              /*
++               *  Hold on to this value for use later.
++               */
++              drive->current_speed = transfer;
++
++              /*
++               *  Success, so turn on DMA.
++               */
++              return ep93xx_ide_dma_on(drive);
++      } else {
++              return ep93xx_ide_dma_off(drive);
++      }
++}
++
++/*****************************************************************************
++ *
++ *  ep93xx_set_pio()
++ *
++ *  Configures the ep93xx controller for a PIO mode transfer.
++ *
++ ****************************************************************************/
++static void ep93xx_set_pio(void)
++{
++      /*
++       *  Disable the interface.
++       */
++      ep93xx_ide_regs->IDECFG.Field.IDEEN = 0;
++
++      /*
++       *  Enable PIO mode of operation.
++       */
++      ep93xx_ide_regs->IDECFG.Field.PIO = 1;
++      ep93xx_ide_regs->IDECFG.Field.UDMA = 0;
++      ep93xx_ide_regs->IDECFG.Field.MDMA = 0;
++
++      /*
++       *  Enable the IDE interface.
++       */
++      ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
++}
++
++/*****************************************************************************
++ *
++ *  ep93xx_rwproc()
++ *
++ *  Initializes the ep93xx IDE controller interface with the transfer type,
++ *  transfer mode, and transfer direction.
++ *
++ ****************************************************************************/
++static void ep93xx_rwproc(ide_drive_t * drive, int action)
++{
++      unsigned int temp;
++
++      DPRINTK("\nep93xx_rwproc \n");
++      /*
++       *  Configure the IDE controller for the specified transfer mode.
++       */
++      switch (drive->current_speed) {
++              /*
++               *  Configure for an MDMA operation.
++               */
++      case XFER_MW_DMA_0:
++      case XFER_MW_DMA_1:
++      case XFER_MW_DMA_2:
++              {
++                      DPRINTK("\n ep93xx set up for MDMA \n");
++                      ep93xx_ide_regs->IDECFG.Field.PIO = 0;
++                      ep93xx_ide_regs->IDECFG.Field.UDMA = 0;
++                      ep93xx_ide_regs->IDECFG.Field.MDMA = 1;
++                      ep93xx_ide_regs->IDECFG.Field.MODE =
++                          (0x3 & drive->current_speed);
++                      ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
++                      ep93xx_ide_regs->IDEMDMAOP.Field.RWOP = action;
++                      ep93xx_ide_regs->IDEMDMAOP.Field.MEN = 1;
++                      break;
++              }
++
++              /*
++               *  Configure for a UDMA operation.
++               */
++      case XFER_UDMA_0:
++      case XFER_UDMA_1:
++      case XFER_UDMA_2:
++      case XFER_UDMA_3:
++      case XFER_UDMA_4:
++              {
++                      DPRINTK("\n ep93xx set up for UDMA \n");
++                      ep93xx_ide_regs->IDECFG.Field.IDEEN = 0;
++                      ep93xx_ide_regs->IDEUDMAOP.Field.UEN = 0;
++                      ep93xx_ide_regs->IDECFG.Field.PIO = 0;
++                      ep93xx_ide_regs->IDECFG.Field.MDMA = 0;
++                      ep93xx_ide_regs->IDECFG.Field.UDMA = 0;
++                      ep93xx_ide_regs->IDECFG.Field.WST = 0;
++                      ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
++
++                      ep93xx_ide_regs->IDECFG.Field.MODE =
++                          (0x7 & drive->current_speed);
++                      ep93xx_ide_regs->IDECFG.Field.UDMA = 1;
++                      ep93xx_ide_regs->IDEUDMAOP.Field.RWOP = action;
++                      temp = ep93xx_ide_regs->IDEUDMAOP.Value;
++                      ep93xx_ide_regs->IDEUDMAOP.Field.UEN = 1;
++                      temp = ep93xx_ide_regs->IDEUDMAOP.Value;
++
++                      DPRINTK("\nIDE Regs: config - 0x%x, udmaop - 0x%x \n",
++                              ep93xx_ide_regs->IDECFG.Value,
++                              ep93xx_ide_regs->IDEUDMAOP.Value);
++
++                      break;;
++              }
++
++      default:
++              {
++                      break;
++              }
++      }
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_check()
++ *
++ * This function determines if the device supports dma transfers, and if it
++ * does, then enables dma.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_check(ide_drive_t * drive)
++{
++      ide_hwif_t *hwif = HWIF(drive);
++      struct hd_driveid *id = drive->id;
++
++      DPRINTK("%s: ep93xx_ide_dma_check \n", drive->name);
++
++      if (!id || !(id->capability & 1) || !hwif->autodma) {
++              /*
++               *  Disable dma for this drive.
++               */
++              ep93xx_ide_dma_off(drive);
++      }
++
++      /*
++       * Consult the list of known "bad" drives
++       */
++      if (in_drive_list(id, drive_blacklist)) {
++              printk("%s: Disabling DMA for %s (blacklisted)\n",
++                     drive->name, id->model);
++
++              /*
++               *  Disable dma for this drive.
++               */
++              ep93xx_ide_dma_off(drive);
++      }
++
++      /*
++       *  Check if the drive supports multiword dma or udma modes.
++       *  If it does, then set the device up for that
++       *  type of dma transfer, and call ep93xx_ide_dma_on.
++       */
++      return ep93xx_config_ide_device(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_host_off()
++ *
++ * This function disables dma for the host.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_host_off(ide_drive_t * drive)
++{
++      ide_hwif_t *hwif = HWIF(drive);
++
++      /*
++       *  TODO: what's to be done here?
++       */
++      DPRINTK("%s: ep93xx_ide_dma_host_off() \n", drive->name);
++
++      /*
++       *  Release the dma channel and all memory allocated for dma
++       *  purposes.
++       */
++      ep93xx_ide_release_dma(hwif);
++
++      return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_off_quietly()
++ *
++ * This function, without announcing it,  disables dma for the device.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_off_quietly(ide_drive_t * drive)
++{
++      DPRINTK("%s: ep93xx_ide_dma_off_quietly: \n", drive->name);
++
++      /*
++       *  Clear the using_dma field to indicate that dma is disabled
++       *  for this drive.
++       */
++      drive->using_dma = 0;
++
++      /*
++       *  Disable dma on the host side.
++       */
++      ep93xx_ide_dma_host_off(drive);
++
++      return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_off()
++ *
++ * This function disables dma for the device.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_off(ide_drive_t * drive)
++{
++      printk("%s: DMA disabled\n", drive->name);
++
++      return ep93xx_ide_dma_off_quietly(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_on()
++ *
++ * This function enables dma for the device.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_on(ide_drive_t * drive)
++{
++      DPRINTK("%s: ep93xx_ide_dma_on: \n", drive->name);
++
++      if (drive->using_dma) {
++              DPRINTK("%s: ep93xx_ide_dma_on, already on! \n", drive->name);
++              return 0;
++      }
++
++      /*
++       *  Set the using_dma field to indicate that dma is enabled.
++       */
++      drive->using_dma = 1;
++
++      /*
++       *  Enable DMA on the host side.
++       */
++      return ep93xx_ide_dma_host_on(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_host_on()
++ *
++ * This function enables dma for the device.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_host_on(ide_drive_t * drive)
++{
++      DPRINTK("%s: ep93xx_ide_dma_host_on: \n", drive->name);
++
++      /*
++       *  Enable the ep93xx dma interface for use with IDE.
++       */
++      return ep93xx_config_ide_dma(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_read()
++ *
++ * This function sets up a dma read operation.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_read(ide_drive_t * drive)
++{
++      unsigned int flags, result;
++      ide_hwif_t *hwif = HWIF(drive);
++
++      DPRINTK("%s: ep93xx_ide_dma_read: \n", drive->name);
++
++      /*
++       *  Check if we are already transferring on this dma channel.
++       */
++      BUG_ON(hwif->sg_dma_active);
++
++      /*
++       *  Configure DMA M2M channel flags for a source address hold, h/w
++       *  initiated P2M transfer.
++       */
++      flags = (SOURCE_HOLD | TRANSFER_MODE_HW_P2M);
++
++      if (drive->current_speed & 0x20) {
++              flags |= (WS_IDE_MDMA_READ_WRITE << WAIT_STATES_SHIFT);
++
++              /*
++               *  MDMA data register address.
++               */
++              hwif->dma_base = 0x800A001C;
++      } else {
++              flags |= (WS_IDE_UDMA_READ << WAIT_STATES_SHIFT);
++
++              /*
++               *  UDMA data register address.
++               */
++              hwif->dma_base = 0x800a0024;
++      }
++
++      /*
++       *  Configure the dma interface for this IDE operation.
++       */
++      if (ep93xx_dma_config(hwif->hw.dma, 0, flags, ep93xx_ide_callback,
++                            (unsigned int)drive) != 0) {
++              DPRINTK("%s: ep93xx_ide_dma_read: ERROR- dma config failed",
++                      drive->name);
++
++              /*
++               *  Fail.
++               */
++              return 1;
++      }
++
++      /*
++       *  Build the table of dma-able buffers.
++       */
++      if (!(g_prd_count = ide_build_dmatable(drive))) {
++              DPRINTK
++                  ("%s: ep93xx_ide_dma_read: ERROR- failed to build dma table",
++                   drive->name);
++
++              /*
++               *  Fail, try PIO instead of DMA
++               */
++              return 1;
++      }
++
++      /*
++       *  Indicate that we're waiting for dma.
++       */
++      drive->waiting_for_dma = 1;
++
++      hwif->sg_dma_active = 1;
++
++      /*
++       * test stuff
++       */
++      g_prd_total = g_prd_count;
++      g_prd_returned = 0;
++      g_dma_table_base = hwif->dmatable_cpu;
++
++      /*
++       *  Prepare the dma interface with some buffers from the
++       *  dma_table.
++       */
++      do {
++              /*
++               *  Add a buffer to the dma interface.
++               */
++              result = ep93xx_dma_add_buffer(hwif->hw.dma, hwif->dma_base,
++                                             *hwif->dmatable_cpu++,
++                                             *hwif->dmatable_cpu++, 0,
++                                             g_prd_count);
++
++              if (result != 0) {
++                      /*
++                       *  This buffer didn't make it into the dma
++                       *  interface, so move the dma table pointer
++                       *  to the start of the current entry.
++                       */
++                      hwif->dmatable_cpu -= 4;
++                      break;
++              }
++
++              /*
++               *  Decrement the count of dmatable entries
++               */
++              g_prd_count--;
++
++      } while (g_prd_count);
++
++      /*
++       *  Check if this is a disk or cd drive.
++       */
++      if (drive->media == ide_disk) {
++              /*
++               *  Send the read command to the device.
++               */
++              ide_execute_command(drive, WIN_READDMA, &ep93xx_ide_dma_intr,
++                                  4 * WAIT_CMD, &ep93xx_idedma_timer_expiry);
++
++      }
++
++      /*
++       *  Configure the ep93xx ide controller for a dma read operation.
++       */
++      ep93xx_rwproc(drive, 0);
++
++      /*
++       *  initiate the dma transfer.
++       */
++      return ep93xx_ide_dma_begin(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_write()
++ *
++ * This function sets up a dma write operation.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_write(ide_drive_t * drive)
++{
++      unsigned int flags, result;
++      ide_hwif_t *hwif = HWIF(drive);
++
++      DPRINTK("%s: ep93xx_ide_dma_write: \n", drive->name);
++
++      /*
++       *  Check if we are already transferring on this dma channel.
++       */
++      BUG_ON(hwif->sg_dma_active);
++
++      /*
++       *  Configure DMA M2M channel flags for a destination address
++       *  hold, h/w initiated M2P transfer.
++       */
++      flags = (DESTINATION_HOLD | TRANSFER_MODE_HW_M2P);
++
++      /*
++       *  Determine if we need the MDMA or UDMA data register.
++       */
++      if (drive->current_speed & 0x20) {
++              flags |= (WS_IDE_MDMA_READ_WRITE << WAIT_STATES_SHIFT);
++
++              /*
++               *  MDMA data register address.
++               */
++              hwif->dma_base = 0x800A0018;
++      } else {
++              flags |= (WS_IDE_UDMA_WRITE << WAIT_STATES_SHIFT);
++
++              /*
++               *  UDMA data register address.
++               */
++              hwif->dma_base = 0x800a0020;
++      }
++
++      /*
++       *  Configure the dma interface for this IDE operation.
++       */
++      if (ep93xx_dma_config(hwif->hw.dma, 0, flags, ep93xx_ide_callback,
++                            (unsigned int)drive) != 0) {
++              return 1;
++      }
++
++      /*
++       *  Build the table of dma-able buffers.
++       */
++      if (!(g_prd_count = ide_build_dmatable(drive))) {
++              /*
++               *  Fail, try PIO instead of DMA
++               */
++              return 1;
++      }
++
++      /*
++       *  Indicate that we're waiting for dma.
++       */
++      drive->waiting_for_dma = 1;
++
++      hwif->sg_dma_active = 1;
++
++      /*
++       * test stuff
++       */
++      g_prd_total = g_prd_count;
++      g_prd_returned = 0;
++      g_dma_table_base = hwif->dmatable_cpu;
++
++      /*
++       *  Prepare the dma interface with some buffers from the
++       *  dma_table.
++       */
++      do {
++              /*
++               *  Add a buffer to the dma interface.
++               */
++              result =
++                  ep93xx_dma_add_buffer(hwif->hw.dma, *hwif->dmatable_cpu++,
++                                        hwif->dma_base, *hwif->dmatable_cpu++,
++                                        0, g_prd_count);
++
++              if (result != 0) {
++                      /*
++                       *  This buffer didn't make it into the dma
++                       *  interface, so move the dma table pointer
++                       *  to the start of the current entry.
++                       */
++                      hwif->dmatable_cpu -= 4;
++                      break;
++              }
++
++              /*
++               *  Decrement the count of dmatable entries
++               */
++              g_prd_count--;
++
++      } while (g_prd_count);
++
++      /*
++       * Check if this is a disk or cd drive.
++       */
++      if (drive->media == ide_disk) {
++              /*
++               *  Send the write dma command to the device.
++               */
++              ide_execute_command(drive, WIN_WRITEDMA, &ep93xx_ide_dma_intr,
++                                  4 * WAIT_CMD, &ep93xx_idedma_timer_expiry);
++      }
++
++      /*
++       *  Configure the ep93xx ide controller for a dma read operation.
++       */
++      ep93xx_rwproc(drive, 1);
++
++      /*
++       *  initiate the dma transfer.
++       */
++      return ep93xx_ide_dma_begin(drive);
++
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_begin()
++ *
++ * This function initiates a dma transfer.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_begin(ide_drive_t * drive)
++{
++      ide_hwif_t *hwif = HWIF(drive);
++
++      DPRINTK("%s: ep93xx_ide_dma_begin: \n", drive->name);
++
++      /* Note that this is done *after* the cmd has
++       * been issued to the drive, as per the BM-IDE spec.
++       * The Promise Ultra33 doesn't work correctly when
++       * we do this part before issuing the drive cmd.
++       */
++      g_done = 0;
++
++      /*
++       *  Start the dma transfer.
++       */
++      ep93xx_dma_start(hwif->hw.dma, 1, NULL);
++
++      /*
++       * TODO: not sure if we need to keep track of the end
++       * of the transfer from the dma perspective, but
++       * for now, let's do it.
++       */
++      return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_end()
++ *
++ * This function performs any tasks needed to cleanup after a dma transfer.
++ * Returns 1 if an error occured, and 0 otherwise.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_end(ide_drive_t * drive)
++{
++      unsigned char dev_stat;
++      ide_hwif_t *hwif = HWIF(drive);
++
++      DPRINTK("%s: ep93xx_ide_dma_end: \n", drive->name);
++
++      /*
++       *  Indicate there's no dma transfer currently in progress.
++       */
++      drive->waiting_for_dma = 0;
++
++      /*
++       *  Put the dma interface into pause mode.
++       */
++      ep93xx_dma_pause(hwif->hw.dma, 1, 0);
++      ep93xx_dma_flush(hwif->hw.dma);
++
++      /*
++       *  Enable PIO mode on the IDE interface.
++       */
++      ep93xx_set_pio();
++
++      /*
++       *  Read the ide device status register.  This clears the interrupt.
++       *  TODO: should I read the alt status instead to prevent clearing
++       *  an asserted interrupt??
++       */
++      dev_stat = hwif->INB(IDE_STATUS_REG);
++
++      /*
++       *  Purge the contents of the dma table of buffer entries.
++       */
++      ide_destroy_dmatable(drive);
++
++      hwif->sg_dma_active = 0;
++
++      /*
++       *  If the error bit is set in the device status register,
++       *  return a positive value.
++       */
++      if (dev_stat & ERR_STAT) {
++              printk("ide_dma_end: device error \n");
++              return 1;
++      } else {
++              return 0;
++      }
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_test_irq()
++ *
++ * This function checks if the IDE interrupt is asserted and returns a
++ * 1 if it is, and 0 otherwise..
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_test_irq(ide_drive_t * drive)
++{
++      DPRINTK("%s: ep93xx_ide_dma_test_irq: \n", drive->name);
++
++      if (!drive->waiting_for_dma)
++              printk(KERN_WARNING "%s: (%s) called while not waiting\n",
++                     drive->name, __FUNCTION__);
++
++      /*
++       *  TODO: need to use the io macros to get this value.
++       *  Return the value of the IDE interrupt bit.
++       */
++      return (ep93xx_ide_regs->IDECR.Value & IDECtrl_INTRQ);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_bad_drive()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_bad_drive(ide_drive_t * drive)
++{
++      DPRINTK("%s: ep93xx_ide_dma_bad_drive: \n", drive->name);
++
++      return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_good_drive()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_good_drive(ide_drive_t * drive)
++{
++      DPRINTK("%s: ep93xx_ide_dma_good_drive: \n", drive->name);
++
++      /*
++       *  TODO: need to implement.
++       */
++      return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_count()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_count(ide_drive_t * drive)
++{
++      DPRINTK("%s: ep93xx_ide_dma_count: \n", drive->name);
++
++      return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_verbose()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_verbose(ide_drive_t * drive)
++{
++      DPRINTK("%s: ep93xx_ide_dma_verbose: \n", drive->name);
++
++      printk(", %s ", ide_xfer_verbose(drive->current_speed));
++
++      return 1;
++
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_bad_timeout()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_timeout(ide_drive_t * drive)
++{
++      DPRINTK("%s: ep93xx_ide_dma_timeout: \n", drive->name);
++
++      printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
++      if (HWIF(drive)->ide_dma_test_irq(drive))
++              return 0;
++      return HWIF(drive)->ide_dma_end(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_retune()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_retune(ide_drive_t * drive)
++{
++      DPRINTK("%s: ep93xx_ide_dma_retune\n", drive->name);
++      return 1;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_lostirq()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_lostirq(ide_drive_t * drive)
++{
++      DPRINTK("%s: ep93xx_ide_dma_lostirq\n", drive->name);
++      printk("%s: DMA interrupt recovery\n", drive->name);
++
++      return 1;
++}
++
++#endif                                /* CONFIG_BLK_DEV_IDEDMA_EP93XX */
++
++/*****************************************************************************
++ *
++ *  functions to set up the IDE control register and data register to read
++ *  or write a byte of data to/from the specified IDE device register.
++ *
++ ****************************************************************************/
++static void ep93xx_ide_outb(u8 b, unsigned long addr)
++{
++      unsigned int uiIDECR;
++
++      DPRINTK("ep93xx_ide_outb, addr:%02lx data: %04x\n", addr, b);
++
++      /*
++       * Write the address out (CS0n, CS1n, DA) fields only.
++       */
++      uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
++      writel(uiIDECR, IDECtrl);
++
++      writel((unsigned int)b, IDEDataOut);
++
++      /*
++       * Toggle Write signal.
++       */
++      uiIDECR &= ~IDECtrl_DIOWn;
++      writel(uiIDECR, IDECtrl);
++      uiIDECR |= IDECtrl_DIOWn;
++      writel(uiIDECR, IDECtrl);
++}
++
++static void ep93xx_ide_outbsync(ide_drive_t * drive, u8 b, unsigned long addr)
++{
++      unsigned int uiIDECR;
++
++      DPRINTK("ep93xx_ide_outbsync, addr:%02lx data: %04x\n", addr, b);
++
++      /*
++       * Write the address out (CS0n, CS1n, DA) fields only.
++       */
++      uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
++      writel(uiIDECR, IDECtrl);
++
++      writel((unsigned int)b, IDEDataOut);
++
++      /*
++       * Toggle Write signal.
++       */
++      uiIDECR &= ~IDECtrl_DIOWn;
++      writel(uiIDECR, IDECtrl);
++      uiIDECR |= IDECtrl_DIOWn;
++      writel(uiIDECR, IDECtrl);
++}
++
++static unsigned char ep93xx_ide_inb(unsigned long addr)
++{
++      unsigned int uiIDECR;
++
++      DPRINTK("ep93xx_ide_inb addr: %04lx ", addr);
++
++      /*
++       * Write the address out (CS0n, CS1n, DA) fields only.
++       */
++      uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
++      writel(uiIDECR, IDECtrl);
++
++      /*
++       * Toggle Read signal.
++       */
++      uiIDECR &= ~IDECtrl_DIORn;
++      writel(uiIDECR, IDECtrl);
++      uiIDECR |= IDECtrl_DIORn;
++      writel(uiIDECR, IDECtrl);
++
++      DPRINTK("data: %02x\n", readl(IDEDataIn));
++      return (unsigned char)readl(IDEDataIn);
++}
++
++/*****************************************************************************
++ *
++ *  functions to set up the IDE control register and data restister to read
++ *  or write 16 bits of data to/from the specified IDE device register.
++ *  These functions should only be used when reading/writing data to/from
++ *  the data register.
++ *
++ ****************************************************************************/
++static void ep93xx_ide_outw(u16 w, unsigned long addr)
++{
++      unsigned int uiIDECR;
++
++      DPRINTK("ep93xx_ide_outw addr: %04lx data: %04x\n", addr, w);
++
++      /*
++       * Write the address out (CS0n, CS1n, DA) fields only.
++       */
++      uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
++      writel(uiIDECR, IDECtrl);
++
++      writel((unsigned int)w, IDEDataOut);
++
++      /*
++       * Toggle Write signal.
++       */
++      uiIDECR &= ~IDECtrl_DIOWn;
++      writel(uiIDECR, IDECtrl);
++      uiIDECR |= IDECtrl_DIOWn;
++      writel(uiIDECR, IDECtrl);
++}
++
++static u16 ep93xx_ide_inw(unsigned long addr)
++{
++      unsigned int uiIDECR;
++
++      DPRINTK("ep93xx_ide_inw addr: %04lx ", addr);
++
++      /*
++       * Write the address out (CS0n, CS1n, DA) fields only.
++       */
++      uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
++      writel(uiIDECR, IDECtrl);
++
++      /*
++       * Toggle Read signal.
++       */
++      uiIDECR &= ~IDECtrl_DIORn;
++      writel(uiIDECR, IDECtrl);
++      uiIDECR |= IDECtrl_DIORn;
++      writel(uiIDECR, IDECtrl);
++
++      DPRINTK("data: %04x\n", readl(IDEDataIn));
++      return (unsigned short)readl(IDEDataIn);
++}
++
++/*****************************************************************************
++ *
++ *  functions to read/write a block of data to/from the ide device using
++ *  PIO mode.
++ *
++ ****************************************************************************/
++static void ep93xx_ide_insw(unsigned long addr, void *buf, u32 count)
++{
++      unsigned short *data = (unsigned short *)buf;
++      unsigned char status;
++      DPRINTK("ep93xx_ide_insw\n");
++
++      /*
++       *  Read in data from the data register 16 bits at a time.
++       */
++      while (count) {
++              /*
++               *  Read the status register.
++               */
++              status = ep93xx_ide_inb((STATUSREGISTER << 2) + 2);
++
++              /*
++               *  Check for the BSY to be clear and DRQ to be set.
++               */
++              if ((status & ATADRQ) && !(status & ATABSY)) {
++                      *data = ep93xx_ide_inw(addr);
++                      data++;
++                      count--;
++              }
++      }
++}
++
++static void ep93xx_ide_outsw(unsigned long addr, void *buf, u32 count)
++{
++      unsigned short *data = (unsigned short *)buf;
++      unsigned char status;
++
++      DPRINTK("ep93xx_ide_outsw\n");
++
++      /*
++       *  Write out data to the data register 16 bits at a time.
++       */
++      while (count) {
++              /*
++               *  Read the status register.
++               */
++              status = ep93xx_ide_inb((STATUSREGISTER << 2) + 2);
++
++              /*
++               *  Check for the BSY to be clear and DRQ to be set.
++               */
++              if ((status & ATADRQ) && !(status & ATABSY)) {
++                      ep93xx_ide_outw(*data, addr);
++                      data++;
++                      count--;
++              }
++      }
++}
++
++static void ep93xx_ide_outl(u32 l, unsigned long addr)
++{
++      printk("ep93xx_ide_outl\n");
++}
++
++static u32 ep93xx_ide_inl(unsigned long addr)
++{
++      printk("ep93xx_ide_inl\n");
++      return 0;
++}
++
++static void ep93xx_ide_outsl(unsigned long addr, void *buf, u32 count)
++{
++      printk("ep93xx_ide_inl\n");
++}
++
++static void ep93xx_ide_insl(unsigned long addr, void *buf, u32 count)
++{
++      printk("ep93xx_ide_inl\n");
++}
++
++/*****************************************************************************
++ *
++ *  Functions to read/write a block of data to/from the ide device using
++ *  PIO mode, using an ATAPI interface.
++ *
++ ****************************************************************************/
++static void ep93xx_ide_insw_atapi(unsigned int addr, void *buf, int count)
++{
++      DPRINTK("ep93xx_ide_insw_atapi \n");
++
++      /*
++       * Convert count from bytes to half words.
++       */
++      if (count % 2) {
++              count = count / 2;
++              count++;
++      } else {
++              count = count / 2;
++      }
++
++      /*
++       * Call the function which will read in the data.
++       */
++      ep93xx_ide_insw(addr, buf, count);
++}
++
++static void ep93xx_ide_outsw_atapi(unsigned int addr, void *buf, int count)
++{
++      DPRINTK("ep93xx_ide_outsw_atapi \n");
++
++      /*
++       * Convert count from bytes to half words.
++       */
++      if (count % 2) {
++              count = count / 2;
++              count++;
++      } else {
++              count = count / 2;
++      }
++
++      /*
++       * Call the function which will write out the data.
++       */
++      ep93xx_ide_outsw(addr, buf, count);
++}
++
++void ep93xx_ata_input_data(ide_drive_t * drive, void *buffer, u32 count)
++{
++      DPRINTK("ep93xx_ata_input_data \n");
++
++      /*
++       *  Read in the specified number of half words from the ide interface.
++       */
++      ep93xx_ide_insw(IDE_DATA_REG, buffer, count << 1);
++}
++
++void ep93xx_ata_output_data(ide_drive_t * drive, void *buffer, u32 count)
++{
++      DPRINTK("ep93xx_ata_output_data \n");
++
++      /*
++       *  write the specified number of half words from the ide interface
++       *  to the ide device.
++       */
++      ep93xx_ide_outsw(IDE_DATA_REG, buffer, count << 1);
++}
++
++void ep93xx_atapi_input_bytes(ide_drive_t * drive, void *buffer, u32 count)
++{
++      DPRINTK("ep93xx_atapi_input_bytes \n");
++
++      /*
++       *  read in the specified number of bytes from the ide interface.
++       */
++      ep93xx_ide_insw_atapi(IDE_DATA_REG, buffer, count);
++}
++
++void ep93xx_atapi_output_bytes(ide_drive_t * drive, void *buffer, u32 count)
++{
++      DPRINTK("ep93xx_atapi_output_bytes \n");
++
++      /*
++       *  Write the specified number of bytes from the ide interface
++       *  to the ide device.
++       */
++      ep93xx_ide_outsw_atapi(IDE_DATA_REG, buffer, count);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_init()
++ *
++ * This function sets up a pointer to the ep93xx specific ideproc funciton.
++ *
++ ****************************************************************************/
++void ep93xx_ide_init(struct hwif_s *hwif)
++{
++
++      DPRINTK("ep93xx_ide_init \n");
++
++      /*
++       *  Set up the HW interface function pointers with the ep93xx specific
++       *  function.
++       */
++      hwif->ata_input_data = ep93xx_ata_input_data;
++      hwif->ata_output_data = ep93xx_ata_output_data;
++      hwif->atapi_input_bytes = ep93xx_atapi_input_bytes;
++      hwif->atapi_output_bytes = ep93xx_atapi_output_bytes;
++
++      hwif->OUTB = ep93xx_ide_outb;
++      hwif->OUTBSYNC = ep93xx_ide_outbsync;
++      hwif->OUTW = ep93xx_ide_outw;
++      hwif->OUTL = ep93xx_ide_outl;
++      hwif->OUTSW = ep93xx_ide_outsw;
++      hwif->OUTSL = ep93xx_ide_outsl;
++
++      hwif->INB = ep93xx_ide_inb;
++      hwif->INW = ep93xx_ide_inw;
++      hwif->INL = ep93xx_ide_inl;
++      hwif->INSW = ep93xx_ide_insw;
++      hwif->INSL = ep93xx_ide_insl;
++
++#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX
++
++      DPRINTK("ep93xx_ide_init- dma enabled \n");
++
++      printk("    %s: SG-DMA", hwif->name);
++
++      /*
++       *  Allocate dma-able memory space, in one consistent chunk.  The call
++       *  to alloc_consistent will return a virtual address and fill in a dma
++       *  physical address.  (arch/arm/mm/consistent.c)
++       *
++       */
++      hwif->dmatable_cpu = consistent_alloc(GFP_KERNEL | GFP_DMA,
++                                            PRD_ENTRIES * PRD_BYTES,
++                                            &hwif->dmatable_dma);
++
++      /*
++       *  Check if we allocated memory for dma
++       */
++      if (hwif->dmatable_cpu == NULL) {
++              printk(" -- disabled, UNABLE TO ALLOCATE DMA TABLES\n");
++              return;
++      }
++
++      DPRINTK("    %s: EP93XX-DMA at 0x%x - 0x%x \n", hwif->name,
++              hwif->dmatable_dma,
++              (unsigned int)(hwif->dmatable_dma + (PRD_ENTRIES * PRD_BYTES)));
++
++      /*
++       *  Allocate memory for the scatterlist structures.
++       */
++      hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES,
++                               GFP_KERNEL);
++
++      /*
++       *  Check if we allocated the memory we expected to.
++       */
++      if (hwif->sg_table == NULL) {
++              /*
++               *  Fail, so clean up.
++               */
++              consistent_free(hwif->dmatable_cpu, PRD_ENTRIES * PRD_BYTES,
++                              hwif->dmatable_dma);
++              printk(" -- disabled, UNABLE TO ALLOCATE DMA TABLES\n");
++              return;
++      }
++
++      /*
++       *  Init the dma handle to 0.  This field is used to hold a handle to the
++       *  dma instance.
++       */
++      hwif->hw.dma = NULL;
++
++      /*
++       *  Open an instance of the ep93xx dma interface.
++       */
++      if (ep93xx_dma_request(&hwif->hw.dma, hwif->name, DMA_IDE) != 0) {
++              /*
++               *  Fail, so clean up.
++               */
++              consistent_free(hwif->dmatable_cpu, PRD_ENTRIES * PRD_BYTES,
++                              hwif->dmatable_dma);
++              kfree(hwif->sg_table);
++              printk(" -- disabled, unable to allocate DMA channel.\n");
++      }
++
++      /*
++       *  Now that we've got a dma channel allocated, set up the rest of the
++       *  dma specific stuff.
++       */
++      else {
++              DPRINTK("\n ide init- dma channel allocated: %d \n",
++                      hwif->hw.dma);
++
++              /*
++               *  Enable dma support for atapi devices.
++               */
++              hwif->atapi_dma = 1;
++
++              /*
++               *  TODO: how are these used?
++               */
++              hwif->mwdma_mask = 7;   /* MW0..2 */
++              hwif->ultra_mask = 7;   /* SW0..2 */
++
++              hwif->speedproc = NULL;
++              hwif->autodma = 1;
++
++              hwif->ide_dma_check = ep93xx_ide_dma_check;
++              hwif->ide_dma_host_off = ep93xx_ide_dma_host_off;
++              hwif->ide_dma_off_quietly = ep93xx_ide_dma_off_quietly;
++              hwif->ide_dma_off = ep93xx_ide_dma_off;
++              hwif->ide_dma_host_on = ep93xx_ide_dma_host_on;
++              hwif->ide_dma_on = ep93xx_ide_dma_on;
++              hwif->ide_dma_read = ep93xx_ide_dma_read;
++              hwif->ide_dma_write = ep93xx_ide_dma_write;
++              hwif->ide_dma_count = ep93xx_ide_dma_count;
++              hwif->ide_dma_begin = ep93xx_ide_dma_begin;
++              hwif->ide_dma_end = ep93xx_ide_dma_end;
++              hwif->ide_dma_test_irq = ep93xx_ide_dma_test_irq;
++              hwif->ide_dma_verbose = ep93xx_ide_dma_verbose;
++              hwif->ide_dma_timeout = ep93xx_ide_dma_timeout;
++              hwif->ide_dma_lostirq = ep93xx_ide_dma_lostirq;
++
++              printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");
++      }
++
++#endif
++}
+diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
+index 23488c4..cc411c2 100644
+--- a/drivers/ide/arm/ide_arm.c
++++ b/drivers/ide/arm/ide_arm.c
+@@ -20,6 +20,15 @@
+ # define IDE_ARM_HOST (1)
+ #endif
++/* FIXME: Part 1 of dirty hack to get IDE working for EP93XX Processor */
++#ifdef CONFIG_BLK_DEV_EP93XX
++#include <asm/arch/ide.h>
++#ifndef IRQ_HARDDISK
++# define IRQ_HARDDISK  -1
++#endif
++#endif
++/* END OF HACK */
++
+ #ifdef CONFIG_ARCH_CLPS7500
+ # include <asm/arch/hardware.h>
+ #
+@@ -36,8 +45,15 @@ void __init ide_arm_init(void)
+               hw_regs_t hw;
+               memset(&hw, 0, sizeof(hw));
++
++/* FIXME: Part 2 of dirty hack to get IDE working for EP93XX Processor */
++#ifdef CONFIG_BLK_DEV_EP93XX
++              old_ide_init_default_hwifs();
++#else
+               ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
+               hw.irq = IDE_ARM_IRQ;
+               ide_register_hw(&hw, NULL);
++#endif
+       }
++
+ }
+diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
+index 4a91774..68c06fa 100644
+--- a/drivers/input/keyboard/Kconfig
++++ b/drivers/input/keyboard/Kconfig
+@@ -193,4 +193,38 @@ config KEYBOARD_HIL
+         This driver implements support for HIL-keyboards attached
+         to your machine, so normally you should say Y here.
++config KEYBOARD_EP93XX
++      tristate "EP93xx Keyboard support"
++      depends on ARCH_EP93XX && INPUT && INPUT_KEYBOARD
++      default y
++      help
++        This is support for the Cirrus EP93xx Keyboards. Say yes here if you
++        have such a CPU, and choose some drivers below.
++
++config KEYBOARD_EP93XX_SPI
++      bool "EP93xx PS2 Keyboard support"
++      depends on KEYBOARD_EP93XX
++      help
++        Say Y here if you want support for a PS2 keyboard connected via SPI.
++
++config KEYBOARD_EP93XX_8X8
++      bool "EP93xx 8x8 keypad matrix support"
++      depends on KEYBOARD_EP93XX
++      help
++        Say Y here if you have a 8x8 keypad connected to your EP93xx.
++        You might want to generate a custom keymap for it.
++        If you do not have such a keypad, say N.
++
++config KEYBOARD_EP93XX_8X8_CYCLING
++      bool "EP93xx 8x8 keypad matrix keycode cycling support"
++      depends on KEYBOARD_EP93XX_8X8
++      help
++        Key cycling feature - assign more than one keycode per key.
++        If you press such a key more than twice per second, alternative
++        keycodes will be cycled through.
++        This should result in a behavoir similar to some mobile phones.
++        You might want to generate a custom keymap for this feature, too.
++        See the sourcecode for known limitations.
++        Say N unless you really need it.
++
+ endif
+diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
+index 9ce0b87..7ac6fca 100644
+--- a/drivers/input/keyboard/Makefile
++++ b/drivers/input/keyboard/Makefile
+@@ -17,4 +17,6 @@ obj-$(CONFIG_KEYBOARD_CORGI)         += corgikb
+ obj-$(CONFIG_KEYBOARD_SPITZ)          += spitzkbd.o
+ obj-$(CONFIG_KEYBOARD_HIL)            += hil_kbd.o
+ obj-$(CONFIG_KEYBOARD_HIL_OLD)                += hilkbd.o
++obj-$(CONFIG_KEYBOARD_EP93XX_8X8)             += ep93xx_kbd_8x8.o
++obj-$(CONFIG_KEYBOARD_EP93XX_SPI)             += ep93xx_spi_kbd.o
+diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8.c b/drivers/input/keyboard/ep93xx_kbd_8x8.c
+new file mode 100644
+index 0000000..d772381
+--- /dev/null
++++ b/drivers/input/keyboard/ep93xx_kbd_8x8.c
+@@ -0,0 +1,482 @@
++/******************************************************************************
++ *
++ *  File:     linux/drivers/input/keyboard/ep93xx_kbd_8x8.c
++ *
++ *  Purpose:  Support for Cirrus EP93xx architecture core keyboard scanner.
++ *
++ *
++ *  History:  2005-08-10 Michael Burian added "cycling keys" support
++ *            2004-05-28 Michael Burian ported to 2.6.6
++ *
++ *            010406  Norman Farquhar at LynuxWorks
++ *
++ *            Initial version
++ *            - Will scan keyboard and feed keyboard.c, which translates
++ *            to input codes and puts them into tty console queue.
++ *            - Raw mode tbd
++ *            - keymaps other than default not supported
++ *            - does not support standby mode yet
++ *
++ *  Limitations:
++ *            1.  The EP93xx is limited to supporting small keyboards
++ *            and cannot handle full PC style keyboards and key usage:
++ *            a)  64 key limit: 8x8 key matrix
++ *            b)  limited to 2 keys down MAXIMUM,
++ *            which makes it impossible to support SHIFT+SHIFT+KEY
++ *            states like shift-control or control-alt keys.
++ *            2.  This means the default keyboard, 83key CherryG84-4001QAU/02,
++ *            will have some dead keys.
++ *
++ *
++ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA.  All rights reserved.
++ *
++ *=============================================================================
++ *    Overview of EP93xx Scan Keyboard driver
++ *=============================================================================
++ *
++ *    The EP93xx scanned keyboard driver is a low-level hardware driver which
++ *    supports the core logic scanned keyboard controller block of the
++ *    EP93xx.  These machines are embedded systems and this keyboard driver
++ *    can support small keyboards.
++ *
++ *    The keyboard driver does not have a normal device driver interface
++ *    and instead interfaces to the keyboard.c driver through function calls.
++ *    Note that not all interface function calls are implemented at this time.
++ *    (see /asm/arch/keyboard.h for function definitions):
++ *
++ *    ep93xxkbd_init
++ *            initializes the scan keyboard hw.
++ *
++ *    handle_scancode
++ *            when scan controller generates interrupt, handler
++ *            used to pass scan codes to queue in keyboard.c with this function call.
++ *
++ *            UPDATE: Now this is inplemented right here and just used as a
++ *                    wrapper for the input layer
++ *
++ *    Note that key scan codes will be delivered by this driver on both
++ *    key down and key up events, using a coding similar to PC XT keyboard.
++ *
++ *    Note however that scan compatibility and key code compatibility
++ *    to PC standard are not required by Linux, and are not guaranteed.
++ *
++ ******************************************************************************/
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/input.h>
++#include <linux/init.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/arch/keyboard.h>
++#include <asm/hardware.h>
++
++#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING
++#include "ep93xx_kbd_8x8_keymap-cycling.h"
++#else
++#include "ep93xx_kbd_8x8_keymap.h"
++#endif
++
++#define EP93XX_KEYMAP_SIZE (8*8)
++
++/* #define DEBUG */
++
++#define KEYREG_KEY1_MASK                        0x0000003F
++#define KEYREG_KEY1_SHIFT                       0
++#define KEYREG_KEY2_MASK                        0x00000Fc0
++#define KEYREG_KEY2_SHIFT                       6
++
++#define KEYREG_KEY1ROW_MASK                     0x00000007
++#define KEYREG_KEY1ROW_SHIFT                    0
++#define KEYREG_KEY1COL_MASK                     0x00000038
++#define KEYREG_KEY1COL_SHIFT                    3
++
++#define KEYREG_KEY2ROW_MASK                     0x000001c0
++#define KEYREG_KEY2ROW_SHIFT                    6
++#define KEYREG_KEY2COL_MASK                     0x00000E00
++#define KEYREG_KEY2COL_SHIFT                    9
++
++#define KEYREG_1KEY                             0x00001000
++#define KEYREG_2KEYS                            0x00002000
++#define KEYREG_INT                              0x00004000
++#define KEYREG_K                                0x00008000
++
++#define SCANINIT_DIS3KY                         0x00008000
++
++static struct input_dev *dev;
++
++#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING
++struct last_key_event {
++      unsigned long jiffies;
++      unsigned char scancode;
++};
++
++static struct last_key_event lke;
++
++/**
++ * handle_scancode - wrapper
++ *
++ * We need to do two things here:
++ * 1. wrap old style (2.4.x) to 2.6.x input subsystem
++ * 2. also implement the key cycling feature here.
++ * CYCLING FEATURE:
++ * If the same key is pressed withing 500ms, we send a delete
++ * character to delete the former key, and use the keycode from the next layer
++ * instead. This should result "mobile phone" like behavior.
++ * KNOWN BUG:
++ * This will mess up anything that depends on single keystrokes
++ * (raw mode, non canonical mode, hotkeys, ...)
++ * TODO 1:
++ * A possible fix would be to delay till we know for sure what key it is
++ * and send just that key, but in that case the user would have to type
++ * blindly. :(
++ * TODO 2:
++ * A possible enhancement to the fix would be to provide some kind of preview
++ * with an additional character device and write some userspace app to display
++ * it in a seperate dialog.
++ *
++ */
++static void handle_scancode(unsigned char scancode, int down)
++{
++      unsigned char row = (scancode & 0xF) - 1;
++      unsigned char col = ((scancode & 0x70) >> 4);
++      unsigned char index = row * 8 + col;
++      static int layer = 0;
++
++      /*
++       * straight forward processing in case of:
++       *      "up" events
++       *      repeated keypress events that happen after more than 500ms
++       *      after different key has been pressed ( ignore up/down! )
++       *      there are no alternative keycodes available
++       */
++      if (!down || time_before(lke.jiffies + msecs_to_jiffies(500), jiffies)
++                      || (lke.scancode & 0x7f) != (scancode &0x7F) ||
++                      (keycode[1][index] == KEY_RESERVED) ) {
++              /* no cycling: process straightforward */
++              input_report_key(dev, keycode[0][index], down);
++              input_sync(dev);
++
++              /* end cycling on all but up events */
++              if(down)
++                      layer=0;
++      } else {
++              /*
++               * cycling mode:
++               *
++               * if we have an alternative keycode available:
++               * 1. pretend the former key was wrong (and delete it)
++               * 2. replace with the keycode from the next layer
++               */
++
++              /* suppress real "up" events, as we fake immediate "up" here */
++              if (!down)
++                      return;
++
++              /* switch to next layer, with wraparound */
++              if(++layer >= 16)
++                      layer = 0;
++
++              /* if alternative keycodes are available */
++              if (keycode[layer][index] != KEY_RESERVED) {
++                      /* pretend former key was wrong and delete it */
++                      input_report_key(dev, KEY_BACKSPACE, 1);
++                      input_report_key(dev, KEY_BACKSPACE, 0);
++              } else {
++                      /* no more valid keycodes? => switch to layer 0 */
++                      layer=0;
++                      return;
++              }
++
++              /* send alternative keycode */
++              input_report_key(dev, keycode[layer][index], 1);
++              input_report_key(dev, keycode[layer][index], 0);
++              input_sync(dev);
++
++
++      }
++      lke.scancode = scancode;
++      lke.jiffies = jiffies;
++}
++#else
++/**
++ * handle_scancode - wrapper
++ *
++ * wrap old style (2.4.x) to 2.6.x input subsystem
++ */
++static void handle_scancode(unsigned char scancode, int down)
++{
++      /* printk("handle_scancode(scancode=%04X, down=%d); %02X ", scancode, down, scancode &0x7f); */
++
++      unsigned char row = (scancode & 0xF) - 1;
++      unsigned char col = ((scancode & 0x70) >> 4);
++      unsigned char index = row * 8 + col;
++
++      input_report_key(dev, keycode[index], down);
++      input_sync(dev);
++
++      /* printk("index=%02X\n", index); */
++}
++#endif
++
++static irqreturn_t ep93xxkbd_irq_handler(int irq, void *dev_id,
++                                       struct pt_regs *regs)
++{
++      unsigned int keystat, key1, key2;
++      static unsigned int lastkeystat = 0, lastkey1 = 0, lastkey2 = 0;
++
++      /* Note: IRQ_KEY automatically disabled before entry, */
++      /* and reenabled after exit by Linux interrupt code. */
++
++      /* Reading status clears keyboard interrupt */
++
++      keystat = readl(KEY_REG) &
++          (KEYREG_KEY1COL_MASK | KEYREG_KEY1ROW_MASK |
++           KEYREG_KEY2COL_MASK | KEYREG_KEY2ROW_MASK |
++           KEYREG_1KEY | KEYREG_2KEYS);
++
++#ifdef DEBUG                  /* DEBUGGING */
++      if (keystat == lastkeystat)
++              printk("ep93xx_scan_keyb:  spurious interrupt, stat %x\n",
++                     keystat);
++      else
++              printk("ep93xx_scan_keyb:  interrupt, stat %x\n", keystat);
++#endif
++      if (keystat & KEYREG_1KEY)
++              key1 =
++                  KEYCODE((keystat & KEYREG_KEY1ROW_MASK) >>
++                          KEYREG_KEY1ROW_SHIFT,
++                          (keystat & KEYREG_KEY1COL_MASK) >>
++                          KEYREG_KEY1COL_SHIFT);
++      else
++              key1 = 0;       /* invalid */
++
++      if (keystat & KEYREG_2KEYS)
++              key2 =
++                  KEYCODE((keystat & KEYREG_KEY2ROW_MASK) >>
++                          KEYREG_KEY2ROW_SHIFT,
++                          (keystat & KEYREG_KEY2COL_MASK) >>
++                          KEYREG_KEY2COL_SHIFT);
++      else
++              key2 = 0;       /* invalid */
++
++      /*
++       * This 'monster' decision tree is used to decide what to report
++       * when last key state has changed to current key state.
++       * This may involve up to 4 keys changing state simultaneously:
++       * lastkey1, lastkey2 going up and key1, key2 going down.
++       *
++       * We use keyboard scanner hardware guarantees to simplify the logic:
++       *      key1 < key2     if both are valid
++       *      key1 is valid   if key2 is valid
++       *
++       *      handle_scancode called with down and up scancodes
++       *              scancode = keycode when down
++       *              scancode = keycode|KBUP when up
++       *
++       * Note that if more than one keys change state in the same scan period,
++       * then we really do NOT know the order in which the key events occurred.
++       * Our default behavior is to always report key up events before key down
++       * events.  However, multiple key up events or multiple key down events
++       * will be reported in no special order.
++       */
++      if (!(lastkeystat & (KEYREG_1KEY | KEYREG_2KEYS))) {    /* No keys down lasttime */
++              if (key1)
++                      handle_scancode(key1, 1);
++              if (key2)
++                      handle_scancode(key2, 1);
++      } else if (lastkey1 == key1) {  /* means key still down */
++              /* no change for key1 or lastkey1, both valid */
++              if (lastkey2 != key2) {
++                      /* lastkey2 went up if valid, key2 went down if valid */
++                      if (lastkey2)
++                              handle_scancode(lastkey2 | KBUP, 0);
++                      if (key2)
++                              handle_scancode(key2, 1);
++              }
++              /* else no change for all keys */
++      } else if (key1)
++      {                       /* key1 valid and */
++              /* lastkey1 valid (because NOT no keys lasttime) */
++              if (lastkey1 == key2) {
++                      /* no change for lastkey1 or key2 */
++                      /* lastkey2 went up if valid, key1 went down */
++                      if (lastkey2)
++                              handle_scancode(lastkey2 | KBUP, 0);
++                      handle_scancode(key1, 1);
++
++              } else {
++                      /* we know: lastkey1 valid and went up, key1 valid */
++                      handle_scancode(lastkey1 | KBUP, 0);
++
++                      if (lastkey2 == key1) {
++                              /* no change for lastkey2 or key1 */
++                              /* key2 went down if valid */
++                              if (key2)
++                                      handle_scancode(key2, 1);
++
++                      } else {
++                              if (lastkey2 != key2) {
++                                      /* lastkey2 went up if valid */
++                                      /* key2 went down if valid */
++                                      if (lastkey2)
++                                              handle_scancode(lastkey2 | KBUP,
++                                                              0);
++                                      if (key2)
++                                              handle_scancode(key2, 1);
++                              }
++                              /* else no change for lastkey2 or key2 */
++
++                              /* key1 valid and went down */
++                              handle_scancode(key1, 1);
++                      }
++              }
++      } else {
++              /* key1 not valid and */
++              /* lastkey1 valid (because NOT no keys lasttime) */
++
++              /* key1 not valid means both key1, key2 not valid */
++              /* so lastkey1 went up and lastkey2 went up if valid */
++              handle_scancode(lastkey1 | KBUP, 0);
++              if (lastkey2)
++                      handle_scancode(lastkey2 | KBUP, 0);
++      }
++
++      lastkeystat = keystat;
++      lastkey1 = key1;
++      lastkey2 = key2;
++      return IRQ_HANDLED;
++}
++
++int __init ep93xxkbd_init(void)
++{
++      int i = 3;
++      unsigned int uiTemp;
++      int error = 0;
++      
++      dev = input_allocate_device();
++      if (!dev) {
++              printk(KERN_ERR "ep93xx_kbd_8x8: not enough memory for input device\n");
++              return -ENOMEM;
++      }
++
++      dev->name = "Cirrus EP93xx 8x8 keypad matrix driver";
++      dev->phys = "input0";
++      dev->id.bustype = BUS_HOST;
++      dev->evbit[0] = BIT(EV_KEY);
++
++      printk("%s\n", dev->name);
++
++      /* Make sure scanner enabled, active and that */
++      /* Keyboard ROW/COL interface enabled. */
++
++      uiTemp = readl(SYSCON_DEVCFG);
++
++      uiTemp &= ~(SYSCON_DEVCFG_KEYS | SYSCON_DEVCFG_GONK);
++
++      SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(uiTemp));
++
++      /* SYSCON locked automatically now after RSTCR written */
++
++      /* Enable Keyboard Clock and select clock rate
++       *
++       *      TBD Boot ROM has already inited KTDIV = 0x20018004
++       *      TBD Measured default 64usec scan period with scope.
++
++       * Assume that GPIO registers do not impact row,col pins since
++       * they are assigned to keyboard scanner.
++
++       * Setup Keyboard Scanner
++       *
++       * Note that we change the scanner parameters on the fly
++       * while it is running, which is okay.  No need to disable
++       * scanner while tweaking these.
++       *
++       * TBD Keyboard scan rate will change as master clocks/dividers change
++       *
++       * For now, this gives us measured rate of about 480Hz row scan rate,
++       * which implies 60Hz full kbd scan rate.  Together with debounce
++       * count of 3, means debounce period = 3/60Hz = 50ms>30ms recommended,
++       * so okay.
++       */
++      writel((0x00FC00FA | SCANINIT_DIS3KY), SCANINIT);
++
++      /*TBD If too much capacitance on keyboard */
++      /* writel( (0x00FC0020 | SCBACK | SCDIS3KEY), SCANINIT ); */
++
++      uiTemp = readl(SYSCON_KTDIV) | SYSCON_KTDIV_KEN;
++
++      SysconSetLocked(SYSCON_KTDIV, uiTemp);
++
++      error =
++          request_irq(IRQ_KEY, ep93xxkbd_irq_handler, 0,
++                      "ep93xx_keypad_handler",
++                      (void *)(ep93xxkbd_irq_handler));
++      if (error) {
++              printk("Error: %s could not allocate IRQ%d\n", dev->name, IRQ_KEY);
++              return error;
++      }
++      /* Note: request_irq has just enabled IRQ_KEY for us. */
++
++      /* Warning: We have initialized last key status to indicate
++       * all keys up which may not be the current hardware state.
++       *
++       *      TBD If this is important to detect, to alert user
++       *      TBD to a possibly faulty keyboard, then we could
++       *      TBD manually scan the keyboard to verify all keys up.
++       *
++
++       * Three common cases here:
++       *      1.  All keys up.  This is normal, expected status of keyboard.
++       *      2.  All keys up, although at some time ago during initialization
++       *      a key was momentarily pressed, causing the hardware to latch it.
++       *      3.  Some key is being held down now.
++       *
++       * Reading status clears any pending keyboard interrupt.
++       */
++
++      i = readl(KEY_REG);
++
++      /*
++       * We believe this will have the following impact on common cases:
++       *
++       *      1.  No impact.
++       *      2.  Momentary presses will be cleared out so they do not
++       *      bother us.  Although we get a spurious key up immediately because
++       *      the keyboard hardware will see change from last
++       *      latched status and current status, higher level keyboard driver
++       *      should ignore.
++       *      3.  Key being held will generate a new pending key down
++       *      event which is acceptable.
++       *
++       * Now keyboard is active and will generate interrupts
++       * on key presses.  Driver only needs to handle interrupts.
++       * There are NO driver ioctl or deinit functions in lowlevel.
++       */
++
++#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING
++      for (i = 0; i < EP93XX_KEYMAP_SIZE * 16; i++)
++              set_bit(keycode[i/EP93XX_KEYMAP_SIZE][i%EP93XX_KEYMAP_SIZE], dev->keybit);
++#else
++      for (i = 0; i < EP93XX_KEYMAP_SIZE; i++)
++              set_bit(keycode[i], dev->keybit);
++#endif
++
++      input_register_device(dev);
++
++      return 0;
++}
++
++static void __exit ep93xxkbd_cleanup(void)
++{
++      writel(0x000000AA, SYSCON_SWLOCK);      /* unlock SYSCON Software Lock */
++      writel(readl(SYSCON_KTDIV) & 0xFFFF7FFF, SYSCON_KTDIV); /* disable Key Matrix Clock KEN */
++      free_irq(IRQ_KEY, NULL);
++      input_unregister_device(dev);
++}
++
++module_init(ep93xxkbd_init);
++module_exit(ep93xxkbd_cleanup);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h
+new file mode 100644
+index 0000000..31fd4db
+--- /dev/null
++++ b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h
+@@ -0,0 +1,146 @@
++static unsigned char keycode[16][0x40] = 
++{{
++      KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, 0, 0,
++      KEY_ESC, KEY_BACKSPACE, KEY_7, KEY_8, KEY_9, 0, 0, 0,
++      KEY_PROG1, KEY_PROG2, KEY_4, KEY_5, KEY_6, 0, 0, 0,
++      KEY_MENU, KEY_0, KEY_1, KEY_2, KEY_3, 0, 0, 0,
++      KEY_LEFTSHIFT, KEY_UP, KEY_TAB, 0, 0, 0, 0, 0,
++      KEY_LEFT, KEY_LEFTALT, KEY_RIGHT, 0, 0, 0, 0, 0,
++      KEY_LEFTCTRL, KEY_DOWN, KEY_ENTER, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, KEY_A, KEY_D, KEY_G, 0, 0, 0,
++      0, 0, KEY_J, KEY_M, KEY_P, 0, 0, 0,
++      0, KEY_DOT, KEY_S, KEY_V, KEY_Y, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, KEY_B, KEY_E, KEY_H, 0, 0, 0,
++      0, 0, KEY_K, KEY_N, KEY_Q, 0, 0, 0,
++      0, KEY_COMMA, KEY_T, KEY_W, KEY_Z, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, KEY_C, KEY_F, KEY_I, 0, 0, 0,
++      0, 0, KEY_L, KEY_O, KEY_R, 0, 0, 0,
++      0, KEY_SLASH, KEY_U, KEY_X, KEY_SPACE, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, KEY_KPASTERISK, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, KEY_KPPLUS, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, KEY_KPMINUS, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, KEY_EQUAL, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, KEY_SEMICOLON, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, KEY_APOSTROPHE, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, KEY_KPLEFTPAREN, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, KEY_KPRIGHTPAREN, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, KEY_LEFTBRACE, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, KEY_RIGHTBRACE, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      }, {
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++}};
+diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h
+new file mode 100644
+index 0000000..65dca77
+--- /dev/null
++++ b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h
+@@ -0,0 +1,11 @@
++static unsigned char keycode[0x40] =
++{
++      KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, 0, 0,
++      KEY_ESC, KEY_BACKSPACE, KEY_7, KEY_8, KEY_9, 0, 0, 0,
++      KEY_PROG1, KEY_PROG2, KEY_4, KEY_5, KEY_6, 0, 0, 0,
++      KEY_MENU, KEY_0, KEY_1, KEY_2, KEY_3, 0, 0, 0,
++      KEY_LEFTSHIFT, KEY_UP, KEY_TAB, 0, 0, 0, 0, 0,
++      KEY_LEFT, KEY_LEFTALT, KEY_RIGHT, 0, 0, 0, 0, 0,
++      KEY_LEFTCTRL, KEY_DOWN, KEY_ENTER, 0, 0, 0, 0, 0,
++      0, 0, 0, 0, 0, 0, 0, 0,
++};
+diff --git a/drivers/input/keyboard/ep93xx_spi_kbd.c b/drivers/input/keyboard/ep93xx_spi_kbd.c
+new file mode 100644
+index 0000000..b6ad607
+--- /dev/null
++++ b/drivers/input/keyboard/ep93xx_spi_kbd.c
+@@ -0,0 +1,407 @@
++/******************************************************************************
++ *
++ *  File:     linux/drivers/char/ep93xx_spi_kbd.c
++ *
++ *  Purpose:  Support for SPI Keyboard for a Cirrus Logic EP93xx
++ *
++ *  History:
++ *
++ *  Limitations:
++ *  Break and Print Screen keys not handled yet!
++ *
++ *
++ *  Copyright 2003 Cirrus Logic 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.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ ******************************************************************************/
++
++/*
++ * FIXME: There are more parity problems than there ought to be.
++ * TODO: Track down
++ * WHERE: grep for "BAD_PARITY"
++ * 
++ * WORKAROUND: Do not press too many keys and do not type too fast
++ *             type key another time if it got lost
++ *
++ * WORKAROUND2: Use USB Keyboards or 8x8 matrix keypad instead
++ * 
++ * FIXME2: Keymap should be done properly
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/module.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/hardware.h>
++#include <asm/arch/ssp-cirrus.h>
++
++#include "ep93xx_spi_kbd.h"
++
++#define EP93XX_MAX_KEY_DOWN_COUNT 6
++
++void DataCallback(unsigned int Data);
++static int g_SSP_Handle;
++static struct input_dev *ep93xxkbd_dev;
++
++#undef UART_HACK_DEBUG
++/* #define UART_HACK_DEBUG 1 */
++
++#if defined(UART_HACK_DEBUG) && defined(CONFIG_DEBUG_LL)
++char szBuf[256];
++#define DPRINTK( x... )   \
++      sprintf( szBuf, ##x ); \
++      printascii( szBuf );
++#else
++#define DPRINTK( x... )
++#endif
++
++struct key_down_tracker_t {
++      unsigned char scancode;
++      unsigned char count;
++};
++
++/*
++ * In the interest of efficiency, let's only allow 5 keys to be down
++ * at a time, maximum.  So if anybody is having a temper tantrum on
++ * their keyboard, they may get stuck keys, but that's to be expected.
++ */
++
++#define MAX_KEYS_DOWN 8
++static struct key_down_tracker_t KeyTracker[MAX_KEYS_DOWN];
++
++static unsigned char SPI2KScan(unsigned int uiSPIValue, int *pValid);
++static void InitSniffer(void);
++static void KeySniffer(unsigned char scancode, int down);
++static void Check4StuckKeys(void);
++
++/**
++ * handle_scancode - wrapper
++ *
++ * wrap old style (2.4.x) to 2.6.x input subsystem
++ */
++static void handle_scancode(unsigned char scancode, int down)
++{
++      DPRINTK("handle_scancode(scancode=%04X, down=%d); %02X ", scancode,
++              down, scancode & 0x7f);
++
++      if (scancode > KSCAN_TABLE_SIZE)
++              scancode &= ~EXTENDED_KEY;
++
++      input_report_key(ep93xxkbd_dev, KScanCodeToVKeyTable[scancode], down);
++      input_sync(ep93xxkbd_dev);
++
++      DPRINTK("(virtual) scancode=%02X\n", scancode);
++}
++
++/**
++ * InitSniffer
++ *
++ * Clear our struct to indicate that no keys are down now.
++ * If somebody boots this thing while holding down keys, then they'll
++ * get what they deserve.
++ *
++ */
++static void InitSniffer(void)
++{
++      int i;
++
++      for (i = 0; i < MAX_KEYS_DOWN; i++) {
++              KeyTracker[i].count = 0;
++              KeyTracker[i].scancode = 0;
++      }
++}
++
++/**
++ * KeySniffer
++ *
++ * To prevent stuck keys, keep track of what keys are down.  This information
++ * is used by Check4StuckKeys().
++ */
++static void KeySniffer(unsigned char scancode, int down)
++{
++      int i;
++
++      /*
++       * There are certain keys that will definately get held down
++       * and we can't interfere with that.
++       */
++      switch (scancode) {
++      case 0x12:              /* left  shift */
++      case 0x59:              /* right shift */
++      case 0x14:              /* left  ctrl  */
++      case 0x94:              /* right ctrl  */
++      case 0x11:              /* left  alt   */
++      case 0x91:              /* right alt   */
++      case 0x58:              /* caps lock   */
++      case 0x77:              /* Num lock    */
++              /* printk("Snuff - %02x, %d\n", scancode, down); */
++              handle_scancode(scancode, down);
++              return;
++
++      default:
++              break;
++      }
++
++      /* printk("Sniff - %02x, %d\n", scancode, down ); */
++
++      /*
++       * Go thru our array, looking for the key.  If it already
++       * is recorded, update its count.
++       * Also look for empty cells in the array in case we
++       * need one.
++       */
++      for (i = 0; i < MAX_KEYS_DOWN; i++) {
++              /* If this is a key up in our list then we are done. */
++              if (down == 0) {
++                      if (KeyTracker[i].scancode == scancode) {
++                              KeyTracker[i].count = 0;
++                              KeyTracker[i].scancode = 0;
++                              handle_scancode(scancode, down);
++                              break;
++                      }
++              }
++              /* Hey here's an unused cell.  Save its index. */
++              else if (KeyTracker[i].count == 0) {
++                      KeyTracker[i].scancode = scancode;
++                      KeyTracker[i].count = 1;
++                      handle_scancode(scancode, down);
++                      break;
++              }
++      }
++}
++
++/**
++ * Check4StuckKeys
++ *
++ * When a key is held down longer than 1/2 sec, it start repeating
++ * 10 times a second.  What we do is watch how long each key is
++ * held down.  If longer than X where X is less than 1/2 second
++ * then we assume it is stuck and issue the key up.  If we were
++ * wrong and the key really is being held down, no problem because
++ * the keyboard is about to start sending it to us repeatedly
++ * anyway.
++ */
++static void Check4StuckKeys(void)
++{
++      int i;
++
++      for (i = 0; i < MAX_KEYS_DOWN; i++) {
++              if (KeyTracker[i].count) {
++                      KeyTracker[i].count++;
++                      if (KeyTracker[i].count >= EP93XX_MAX_KEY_DOWN_COUNT) {
++                              handle_scancode(KeyTracker[i].scancode, 0);
++                              KeyTracker[i].count = 0;
++                              KeyTracker[i].scancode = 0;
++                      }
++              }
++      }
++}
++
++/**
++ * HandleKeyPress
++ *
++ * Checks if there are any keys in the FIFO and processes them if there are.
++ */
++void HandleKeyPress(unsigned int Data)
++{
++      static unsigned char ucKScan[4] = { 0, 0, 0, 0 };
++      static unsigned int ulNum = 0;
++      int bParityValid;
++
++      /*
++       * No keys to decode, but the timer went off and is calling us
++       * to check for stuck keys.
++       */
++      if (Data == -1) {
++              Check4StuckKeys();
++              return;
++      }
++      /*
++       * Read in the value from the SPI controller.
++       */
++      ucKScan[ulNum++] = SPI2KScan(Data, &bParityValid);
++
++      /*
++       * Bad parity?  We should read the rest of the fifo and
++       * throw it away, because it will all be bad.  Then the
++       * SSP will be reset when we close the SSP driver and
++       * all will be good again.
++       */
++      if (!bParityValid) {
++              /*      printk("_BAD_PARITY_");   */
++              ulNum = 0;
++      }
++      /* If we have one character in the array, do the following. */
++      if (ulNum == 1) {
++              /*
++               * If it is a simple key without the extended scan code perform
++               * following.
++               */
++              if (ucKScan[0] < KSCAN_TABLE_SIZE) {
++                      DPRINTK("1:Dn %02x\n", ucKScan[0]);
++                      KeySniffer(ucKScan[0], 1);
++                      ulNum = 0;
++              }
++              /*
++               * I don't know what type of character this is so erase the
++               * keys stored in the buffer and continue.
++               */
++              else if ((ucKScan[0] != 0xF0) && (ucKScan[0] != 0xE0)) {
++                      DPRINTK("1:oops - %02x\n", ucKScan[0]);
++                      ulNum = 0;
++              }
++      } else if (ulNum == 2) {
++              /*
++               * 0xF0 means that a key has been released.
++               */
++              if (ucKScan[0] == 0xF0) {
++                      /*
++                       * If it is a simple key without the extended scan code
++                       * perform the following.
++                       */
++                      if (ucKScan[1] < KSCAN_TABLE_SIZE) {
++                              DPRINTK("2:Up %02x %02x\n", ucKScan[0],
++                                      ucKScan[1]);
++                              KeySniffer(ucKScan[1], 0);
++                              ulNum = 0;
++                      }
++                      /*
++                       * If it a extended kscan continue to get the next byte.
++                       */
++                      else if (ucKScan[1] != 0xE0) {
++                              DPRINTK("2:oops - %02x %02x\n", ucKScan[0],
++                                      ucKScan[1]);
++                              ulNum = 0;
++                      }
++              }
++              /*
++               * Find out what extended code it is.
++               */
++              else if (ucKScan[0] == 0xE0 && ucKScan[1] != 0xF0) {
++                      DPRINTK("2:Dn %02x %02x\n", ucKScan[0], ucKScan[1]);
++                      KeySniffer(EXTENDED_KEY | ucKScan[1], 1);
++                      ulNum = 0;
++              }
++      }
++      /* This means that an extended code key has been released. */
++      else if (ulNum == 3) {
++              /* 0xF0 means that a key has been released. */
++              if (ucKScan[0] == 0xE0 && ucKScan[1] == 0xF0) {
++                      DPRINTK("3:Up %02x %02x %02x",
++                              ucKScan[0], ucKScan[1], ucKScan[2]);
++                      KeySniffer(EXTENDED_KEY | ucKScan[2], 0);
++              } else {
++                      DPRINTK("3:oops - %02x %02x %02x\n",
++                              ucKScan[0], ucKScan[1], ucKScan[2]);
++              }
++              ulNum = 0;
++      }
++}
++
++/**
++ * SPI2KScan - Get a character from the spi port if it is available.
++ *
++ * Below is a picture of the spi signal from the PS2.
++ *
++ * CK HHllllHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHllll
++ * DA HHHllllll000000111111222222333333444444555555666666777777ppppppssssssLLLLHHH
++ *        ^                                                                ^
++ *    start bit                                                   important bit
++ *
++ * where:  l = 8042 driving the line
++ *        L = KEYBOARD driving the line
++ *        1..7 data
++ *         = Parity 8042 driving
++ *        s = stop   8042 driving
++ *         = PARITY KEYBOARD driving the line
++ *        S = STOP   KEYBOARD driving the line
++ *
++ *  In our design the value comes high bit first and is inverted.  So we must
++ *  convert it to low byte first and then inverted it back.
++ *
++ */
++static unsigned char SPI2KScan(unsigned int uiSPIValue, int *pValid)
++{
++      unsigned char ucKScan = 0;
++      unsigned int uiParity = 0;
++      unsigned int uiCount = 0;
++
++      for (uiCount = 1; uiCount < 10; uiCount++) {
++              uiParity += (uiSPIValue >> uiCount) & 0x1;
++      }
++
++      if (!(uiParity & 0x1) && (uiSPIValue & 0x401) == 0x400) {
++              *pValid = 1;
++
++              /* Invert the pattern. */
++              uiSPIValue = ~uiSPIValue;
++
++              /* Read in the value from the motorola spi file */
++              ucKScan = (unsigned char)((uiSPIValue & 0x004) << 5);
++              ucKScan |= (unsigned char)((uiSPIValue & 0x008) << 3);
++              ucKScan |= (unsigned char)((uiSPIValue & 0x010) << 1);
++              ucKScan |= (unsigned char)((uiSPIValue & 0x020) >> 1);
++              ucKScan |= (unsigned char)((uiSPIValue & 0x040) >> 3);
++              ucKScan |= (unsigned char)((uiSPIValue & 0x080) >> 5);
++              ucKScan |= (unsigned char)((uiSPIValue & 0x100) >> 7);
++              ucKScan |= (unsigned char)((uiSPIValue & 0x200) >> 9);
++      } else {
++              *pValid = 0;
++      }
++
++      return ucKScan;
++}
++
++int __init EP93XXSpiKbdInit(void)
++{
++      int i;
++      
++      ep93xxkbd_dev = input_allocate_device();
++      if (!ep93xxkbd_dev) {
++              printk(KERN_ERR "ep93xxkbd: not enough memory for input device\n");
++              return -ENOMEM;
++      }
++      
++      ep93xxkbd_dev->name = "Cirrus EP93xx PS/2 keyboard driver";
++      printk("%s\n", ep93xxkbd_dev->name);
++      
++      ep93xxkbd_dev->evbit[0] = BIT(EV_KEY);
++
++      for (i = 0; i < KSCAN_TABLE_SIZE; i++)
++              set_bit(KScanCodeToVKeyTable[i], ep93xxkbd_dev->keybit);
++
++      input_register_device(ep93xxkbd_dev);
++
++      /* Open SSP driver for Keyboard input. */
++      g_SSP_Handle = SSPDriver->Open(PS2_KEYBOARD, HandleKeyPress);
++
++      InitSniffer();
++
++      DPRINTK("Leaving EP93XXSpiKbdInit()\n");
++
++      return 0;
++}
++
++void __exit EP93XXSpiKbdCleanup(void)
++{
++      SSPDriver->Close(g_SSP_Handle);
++      input_unregister_device(ep93xxkbd_dev);
++}
++
++module_init(EP93XXSpiKbdInit);
++module_exit(EP93XXSpiKbdCleanup);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/keyboard/ep93xx_spi_kbd.h b/drivers/input/keyboard/ep93xx_spi_kbd.h
+new file mode 100644
+index 0000000..7f4bd90
+--- /dev/null
++++ b/drivers/input/keyboard/ep93xx_spi_kbd.h
+@@ -0,0 +1,147 @@
++/*
++ * ep93xx_spi_kbd.h Keymap definitions (to be cleaned up)
++ */
++
++#define KSCAN_TABLE_SIZE    0x88
++
++#define EXTENDED_KEY     0x80
++
++/* This table is used to map the scan code to the Linux default keymap. */
++static unsigned int const KScanCodeToVKeyTable[KSCAN_TABLE_SIZE] = {
++      KEY_RESERVED,           /* Scan Code 0x0 */
++      KEY_F9,                 /* Scan Code 0x1 */
++      KEY_RESERVED,           /* Scan Code 0x2 */
++      KEY_F5,                 /* Scan Code 0x3 */
++      KEY_F3,                 /* Scan Code 0x4 */
++      KEY_F1,                 /* Scan Code 0x5 */
++      KEY_F2,                 /* Scan Code 0x6 */
++      KEY_F12,                /* Scan Code 0x7 */
++      KEY_RESERVED,           /* Scan Code 0x8 */
++      KEY_F10,                /* Scan Code 0x9 */
++      KEY_F8,                 /* Scan Code 0xA */
++      KEY_F6,                 /* Scan Code 0xB */
++      KEY_F4,                 /* Scan Code 0xC */
++      KEY_TAB,                /* Scan Code 0xD Tab */
++      KEY_GRAVE,              /* Scan Code 0xE ' */
++      KEY_RESERVED,           /* Scan Code 0xF */
++      KEY_RESERVED,           /* Scan Code 0x10 */
++      KEY_LEFTALT,            /* Scan Code 0x11 Left Menu */
++      KEY_LEFTSHIFT,          /* Scan Code 0x12 Left Shift */
++      KEY_RESERVED,           /* Scan Code 0x13 */
++      KEY_LEFTCTRL,           /* Scan Code 0x14 */
++      KEY_Q,                  /* Scan Code 0x15 */
++      KEY_1,                  /* Scan Code 0x16 */
++      KEY_RESERVED,           /* Scan Code 0x17 */
++      KEY_RESERVED,           /* Scan Code 0x18 */
++      KEY_RESERVED,           /* Scan Code 0x19 */
++      KEY_Z,                  /* Scan Code 0x1A */
++      KEY_S,                  /* Scan Code 0x1B */
++      KEY_A,                  /* Scan Code 0x1C */
++      KEY_W,                  /* Scan Code 0x1D */
++      KEY_2,                  /* Scan Code 0x1E */
++      KEY_RESERVED,           /* Scan Code 0x1F */
++      KEY_RESERVED,           /* Scan Code 0x20 */
++      KEY_C,                  /* Scan Code 0x21 */
++      KEY_X,                  /* Scan Code 0x22 */
++      KEY_D,                  /* Scan Code 0x23 */
++      KEY_E,                  /* Scan Code 0x24 */
++      KEY_4,                  /* Scan Code 0x25 */
++      KEY_3,                  /* Scan Code 0x26 */
++      KEY_RESERVED,           /* Scan Code 0x27 */
++      KEY_RESERVED,           /* Scan Code 0x28 */
++      KEY_SPACE,              /* Scan Code 0x29  Space */
++      KEY_V,                  /* Scan Code 0x2A */
++      KEY_F,                  /* Scan Code 0x2B */
++      KEY_T,                  /* Scan Code 0x2C */
++      KEY_R,                  /* Scan Code 0x2D */
++      KEY_5,                  /* Scan Code 0x2E */
++      KEY_RESERVED,           /* Scan Code 0x2F */
++      KEY_RESERVED,           /* Scan Code 0x30 */
++      KEY_N,                  /* Scan Code 0x31 */
++      KEY_B,                  /* Scan Code 0x32 B */
++      KEY_H,                  /* Scan Code 0x33 */
++      KEY_G,                  /* Scan Code 0x34 */
++      KEY_Y,                  /* Scan Code 0x35 */
++      KEY_6,                  /* Scan Code 0x36 */
++      KEY_RESERVED,           /* Scan Code 0x37 */
++      KEY_RESERVED,           /* Scan Code 0x38 */
++      KEY_RESERVED,           /* Scan Code 0x39 */
++      KEY_M,                  /* Scan Code 0x3A */
++      KEY_J,                  /* Scan Code 0x3B */
++      KEY_U,                  /* Scan Code 0x3C */
++      KEY_7,                  /* Scan Code 0x3D */
++      KEY_8,                  /* Scan Code 0x3E */
++      KEY_RESERVED,           /* Scan Code 0x3F */
++      KEY_RESERVED,           /* Scan Code 0x40 */
++      KEY_COMMA,              /* Scan Code 0x41 */
++      KEY_K,                  /* Scan Code 0x42 */
++      KEY_I,                  /* Scan Code 0x43 */
++      KEY_O,                  /* Scan Code 0x44 */
++      KEY_0,                  /* Scan Code 0x45 */
++      KEY_9,                  /* Scan Code 0x46 */
++      KEY_RESERVED,           /* Scan Code 0x47 */
++      KEY_RESERVED,           /* Scan Code 0x48 */
++      KEY_DOT,                /* Scan Code 0x49 */
++      KEY_SLASH,              /* Scan Code 0x4A */
++      KEY_L,                  /* Scan Code 0x4B */
++      KEY_SEMICOLON,          /* Scan Code 0x4C */
++      KEY_P,                  /* Scan Code 0x4D */
++      KEY_MINUS,              /* Scan Code 0x4E */
++      KEY_RESERVED,           /* Scan Code 0x4F */
++      KEY_RESERVED,           /* Scan Code 0x50 */
++      KEY_RESERVED,           /* Scan Code 0x51 */
++      KEY_APOSTROPHE,         /* Scan Code 0x52 */
++      KEY_RESERVED,           /* Scan Code 0x53 */
++      KEY_LEFTBRACE,          /* Scan Code 0x54 */
++      KEY_EQUAL,              /* Scan Code 0x55 */
++      KEY_BACKSPACE,          /* Scan Code 0x56 */
++      KEY_RESERVED,           /* Scan Code 0x57 */
++      KEY_CAPSLOCK,           /* Scan Code 0x58 Caps Lock */
++      KEY_RIGHTSHIFT,         /* Scan Code 0x59 Right Shift */
++      KEY_ENTER,              /* Scan Code 0x5A */
++      KEY_RIGHTBRACE,         /* Scan Code 0x5B */
++      KEY_RESERVED,           /* Scan Code 0x5C */
++      KEY_BACKSLASH,          /* Scan Code 0x5D */
++      KEY_RESERVED,           /* Scan Code 0x5E */
++      KEY_RESERVED,           /* Scan Code 0x5F */
++      KEY_RESERVED,           /* Scan Code 0x60 */
++      KEY_BACKSLASH,          /* Scan Code 0x61 ?? VK_BSLH,             */
++      KEY_RESERVED,           /* Scan Code 0x62 */
++      KEY_RESERVED,           /* Scan Code 0x63 */
++      KEY_RESERVED,           /* Scan Code 0x64 */
++      KEY_RESERVED,           /* Scan Code 0x65 */
++      KEY_BACKSPACE,          /* Scan Code 0x66 ?? VK_BKSP,             */
++      KEY_RESERVED,           /* Scan Code 0x67 */
++      KEY_RESERVED,           /* Scan Code 0x68 */
++      KEY_KP1,                /* Scan Code 0x69 */
++      KEY_RESERVED,           /* Scan Code 0x6A */
++      KEY_KP4,                /* Scan Code 0x6B */
++      KEY_KP7,                /* Scan Code 0x6C */
++      KEY_RESERVED,           /* Scan Code 0x6D */
++      KEY_RESERVED,           /* Scan Code 0x6E */
++      KEY_RESERVED,           /* Scan Code 0x6F */
++      KEY_KP0,                /* Scan Code 0x70 */
++      KEY_KPDOT,              /* Scan Code 0x71 DECIMAL?? */
++      KEY_KP2,                /* Scan Code 0x72 */
++      KEY_KP5,                /* Scan Code 0x73 */
++      KEY_KP6,                /* Scan Code 0x74 */
++      KEY_KP8,                /* Scan Code 0x75 */
++      KEY_ESC,                /* Scan Code 0x76 */
++      KEY_NUMLOCK,            /* Scan Code 0x77 */
++      KEY_F11,                /* Scan Code 0x78 */
++      KEY_KPPLUS,             /* Scan Code 0x79 */
++      KEY_KP3,                /* Scan Code 0x7A */
++      KEY_KPMINUS,            /* Scan Code 0x7B */
++      KEY_KPASTERISK,         /* Scan Code 0x7C */
++      KEY_KP9,                /* Scan Code 0x7D */
++      KEY_SCROLLLOCK,         /* Scan Code 0x7E */
++      KEY_RESERVED,           /* Scan Code 0x7F */
++      KEY_RESERVED,           /* Scan Code 0x80 */
++      KEY_RESERVED,           /* Scan Code 0x81 */
++      KEY_RESERVED,           /* Scan Code 0x82 */
++      KEY_F7,                 /* Scan Code 0x83 */
++      KEY_RESERVED,           /* Scan Code 0x84 */
++      KEY_RESERVED,           /* Scan Code 0x85 */
++      KEY_RESERVED,           /* Scan Code 0x86 */
++      KEY_RESERVED            /* Scan Code 0x87 */
++};
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index 21d55ed..5453395 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -95,4 +95,15 @@ config TOUCHSCREEN_HP600
+         To compile this driver as a module, choose M here: the
+         module will be called hp680_ts_input.
++config TOUCHSCREEN_EP93XX
++      tristate "EP93xx touchscreen"
++        depends on ARCH_EP93XX
++      help
++        Say Y here if you have a touchscreen connected to your EP93xx CPU.
++
++        If unsure, say N.
++
++        To compile this driver as a module, choose M here: the
++        module will be called ep93xx_ts.
++
+ endif
+diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
+index 6842869..f8e6eb4 100644
+--- a/drivers/input/touchscreen/Makefile
++++ b/drivers/input/touchscreen/Makefile
+@@ -11,3 +11,4 @@ obj-$(CONFIG_TOUCHSCREEN_ELO)        += elo.o
+ obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
+ obj-$(CONFIG_TOUCHSCREEN_MK712)       += mk712.o
+ obj-$(CONFIG_TOUCHSCREEN_HP600)       += hp680_ts_input.o
++obj-$(CONFIG_TOUCHSCREEN_EP93XX) += ep93xx_ts.o
+diff --git a/drivers/input/touchscreen/ep93xx_ts.c b/drivers/input/touchscreen/ep93xx_ts.c
+new file mode 100644
+index 0000000..fc4622e
+--- /dev/null
++++ b/drivers/input/touchscreen/ep93xx_ts.c
+@@ -0,0 +1,748 @@
++/*
++ *  linux/drivers/char/ep93xx_ts.c
++ *
++ *  Copyright (C) 2003-2004 Cirrus Corp.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/input.h>
++#include <linux/pci.h>
++
++#include <asm/irq.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++
++/*
++ * To customize for a new touchscreen, there are various macros that
++ * have to be set.  If you allow UART_HACK_DEBUG to be defined, you
++ * will get real time ts data scrolling up your serial terminal
++ * screen that will help you empirically determine good values for these.
++ *
++ *
++ * These are used as trigger levels to know when we have pen up/down
++ *
++ * The rules:
++ * 1.  TS_HEAVY_INV_PRESSURE < TS_LIGHT_INV_PRESSURE because these
++ *    are Inverse pressure.
++ * 2.  Any touch lighter than TS_LIGHT_INV_PRESSURE is a pen up.
++ * 3.  Any touch heavier than TS_HEAVY_INV_PRESSURE is a pen down.
++ */
++#define TS_HEAVY_INV_PRESSURE (0x1000 - pressure_max)
++#define TS_LIGHT_INV_PRESSURE (0x1000 - pressure_min)
++
++/*
++ * If the x, y, or inverse pressure changes more than these values
++ * between two succeeding points, the point is not reported.
++ */
++#define TS_MAX_VALID_PRESSURE_CHANGE  (pressure_jitter)
++#define TS_MAX_VALID_XY_CHANGE  (xy_jitter)
++
++/* old defaults */
++#if 0
++#define TS_X_MIN      0
++#define TS_Y_MIN      0
++#define TS_X_MAX      0xfff
++#define TS_Y_MAX      0xfff
++#endif
++
++/* "improved" defaults */
++#define TS_X_MIN      0x2d9
++#define TS_Y_MIN      0xd0a
++#define TS_X_MAX      0xd42
++#define TS_Y_MAX      0x2e0
++
++static uint16_t pressure_min = 0x001;
++static uint16_t pressure_max = 0x010;
++static uint16_t pressure_jitter = 0x300;
++static uint16_t xy_jitter = 0x100;
++module_param(pressure_min, ushort, 0);
++module_param(pressure_max, ushort, 0);
++module_param(pressure_jitter, ushort, 0);
++module_param(xy_jitter, ushort, 0);
++MODULE_PARM_DESC(pressure_min, "Minimum pressure (0 - 4095)");
++MODULE_PARM_DESC(pressure_max, "Maximum pressure (0 - 4095)");
++MODULE_PARM_DESC(pressure_jitter, "Minimum pressure jitter (0 - 4095)");
++MODULE_PARM_DESC(xy_jitter, "Minimum X-Y jitter (0 - 4095)");
++
++/* This is the minimum Z1 Value that is valid. */
++#define     MIN_Z1_VALUE                    0x50
++
++/*
++ * Settling delay for taking each ADC measurement.  Increase this
++ * if ts is jittery.
++ */
++#define EP93XX_TS_ADC_DELAY_USEC 2000
++
++/* Delay between TS points. */
++
++#define EP93XX_TS_PER_POINT_DELAY_USEC 10000
++
++/*-----------------------------------------------------------------------------
++ * Debug messaging thru the UARTs
++ *-----------------------------------------------------------------------------
++ *
++ *  Hello there!  Are you trying to get this driver to work with a new
++ *  touschscreen?  Turn this on and you will get useful info coming
++ *  out of your serial port.
++ */
++
++/* #define PRINT_CALIBRATION_FACTORS */
++#ifdef PRINT_CALIBRATION_FACTORS
++#define UART_HACK_DEBUG 1
++int iMaxX = 0, iMaxY = 0, iMinX = 0xfff, iMinY = 0xfff;
++#endif
++
++/*
++ * For debugging, let's spew messages out serial port 1 or 3 at 57,600 baud.
++ */
++#undef UART_HACK_DEBUG
++#if defined(UART_HACK_DEBUG) && defined (CONFIG_DEBUG_LL)
++static char szBuf[256];
++void UARTWriteString(char *msg);
++extern void printascii(const char *msg);
++#define DPRINTK( x... )   \
++    sprintf( szBuf, ##x ); \
++    printascii( szBuf );
++#else
++#define DPRINTK( x... )
++#endif
++
++#define TSSETUP_DEFAULT  ( TSSETUP_NSMP_32 | TSSETUP_DEV_64 |  \
++                           ((128<<TSSETUP_SDLY_SHIFT) & TSSETUP_SDLY_MASK) | \
++                           ((128<<TSSETUP_DLY_SHIFT)  & TSSETUP_DLY_MASK) )
++
++#define TSSETUP2_DEFAULT (TSSETUP2_NSIGND)
++
++static unsigned int guiLastX, guiLastY;
++static unsigned int guiLastInvPressure;
++static int bCurrentPenDown;
++static DECLARE_MUTEX(open_sem);
++
++enum ts_mode_t {
++      TS_MODE_UN_INITIALIZED,
++      TS_MODE_HARDWARE_SCAN,
++      TS_MODE_SOFT_SCAN
++};
++
++static enum ts_mode_t gScanningMode;
++
++enum ts_states_t {
++      TS_STATE_STOPPED = 0,
++      TS_STATE_Z1,
++      TS_STATE_Z2,
++      TS_STATE_Y,
++      TS_STATE_X,
++      TS_STATE_DONE
++};
++
++struct ts_struct_t {
++      unsigned int uiX;
++      unsigned int uiY;
++      unsigned int uiZ1;
++      unsigned int uiZ2;
++      enum ts_states_t state;
++};
++
++static struct ts_struct_t sTouch;
++
++/*
++ * From the spec, here's how to set up the touch screen's switch registers.
++ */
++struct SwitchStructType {
++      unsigned int uiDetect;
++      unsigned int uiDischarge;
++      unsigned int uiXSample;
++      unsigned int uiYSample;
++      unsigned int uiSwitchZ1;
++      unsigned int uiSwitchZ2;
++};
++
++/*
++ * Here's the switch settings for a 4-wire touchscreen.  See the spec
++ * for how to handle a 4, 7, or 8-wire.
++ */
++const static struct SwitchStructType sSwitchSettings =
++/*     s28en=0
++ *   TSDetect    TSDischarge  TSXSample  TSYSample    SwitchZ1   SwitchZ2
++ */
++{ 0x00403604, 0x0007fe04, 0x00081604, 0x00104601, 0x00101601, 0x00101608 };
++
++static void ep93xx_ts_set_direct(unsigned int uiADCSwitch);
++static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id, struct pt_regs *regs);
++static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id,
++                                   struct pt_regs *regs);
++static void ep93xx_hw_setup(void);
++static void ep93xx_hw_shutdown(void);
++static unsigned int CalculateInvPressure(void);
++static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff);
++static void TS_Soft_Scan_Mode(void);
++static void TS_Hardware_Scan_Mode(void);
++static void ProcessPointData(struct input_dev *dev);
++static void Set_Timer2_uSec(unsigned int Delay_mSec);
++static void Stop_Timer2(void);
++
++static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id, struct pt_regs *regs)
++{
++      DPRINTK("isr\n");
++
++      /*
++       * Note that we don't clear the interrupt here.  The interrupt
++       * gets cleared in TS_Soft_Scan_Mode when the TS ENABLE
++       * bit is cleared.
++       *
++
++       *
++       * Set the ts to manual polling mode and schedule a callback.
++       * That way we can return from the isr in a reasonable amount of
++       * time and process the touch in the callback after a brief delay.
++       */
++      TS_Soft_Scan_Mode();
++      return IRQ_HANDLED;
++}
++
++static int ep93xx_ts_open(struct input_dev *dev)
++{
++      int err;
++
++      if (down_trylock(&open_sem))
++              return -EBUSY;
++
++      err =
++          request_irq(IRQ_TOUCH, ep93xx_ts_isr, SA_INTERRUPT, "ep93xx_ts",
++                      dev);
++      if (err) {
++              printk(KERN_WARNING
++                     "ep93xx_ts: failed to get touchscreen IRQ\n");
++              return err;
++      }
++
++      err = request_irq(IRQ_TIMER2, ep93xx_timer2_isr,
++                        SA_INTERRUPT, "ep93xx_timer2", dev);
++      if (err) {
++              printk(KERN_WARNING "ep93xx_ts: failed to get timer2 IRQ\n");
++              free_irq(IRQ_TOUCH, dev);
++              return err;
++      }
++
++      ep93xx_hw_setup();
++
++      return 0;
++}
++
++static void ep93xx_ts_close(struct input_dev *dev)
++{
++      Stop_Timer2();
++
++      ep93xx_hw_shutdown();
++
++      free_irq(IRQ_TIMER2, dev);
++      free_irq(IRQ_TOUCH, dev);
++
++      up(&open_sem);
++}
++
++static void ep93xx_hw_setup(void)
++{
++      unsigned int uiKTDIV, uiTSXYMaxMin;
++
++      /*
++       * Set the TSEN bit in KTDIV so that we are enabling the clock
++       * for the touchscreen.
++       */
++      uiKTDIV = readl(SYSCON_KTDIV);
++      uiKTDIV |= SYSCON_KTDIV_TSEN;
++      SysconSetLocked(SYSCON_KTDIV, uiKTDIV);
++
++      writel(TSSETUP_DEFAULT, TSSetup);
++      writel(TSSETUP2_DEFAULT, TSSetup2);
++
++      /* Set the the touch settings.  */
++      writel(0xaa, TSSWLock);
++      writel(sSwitchSettings.uiDischarge, TSDirect);
++
++      writel(0xaa, TSSWLock);
++      writel(sSwitchSettings.uiDischarge, TSDischarge);
++
++      writel(0xaa, TSSWLock);
++      writel(sSwitchSettings.uiSwitchZ1, TSXSample);
++
++      writel(0xaa, TSSWLock);
++      writel(sSwitchSettings.uiSwitchZ2, TSYSample);
++
++      writel(0xaa, TSSWLock);
++      writel(sSwitchSettings.uiDetect, TSDetect);
++
++      /*
++       * X,YMin set to 0x40 = have to drag that many pixels for a new irq.
++       * X,YMax set to 0x40 = 1024 pixels is the maximum movement within the
++       * time scan limit.
++       */
++      uiTSXYMaxMin = (50 << TSMAXMIN_XMIN_SHIFT) & TSMAXMIN_XMIN_MASK;
++      uiTSXYMaxMin |= (50 << TSMAXMIN_YMIN_SHIFT) & TSMAXMIN_YMIN_MASK;
++      uiTSXYMaxMin |= (0xff << TSMAXMIN_XMAX_SHIFT) & TSMAXMIN_XMAX_MASK;
++      uiTSXYMaxMin |= (0xff << TSMAXMIN_YMAX_SHIFT) & TSMAXMIN_YMAX_MASK;
++      writel(uiTSXYMaxMin, TSXYMaxMin);
++
++      bCurrentPenDown = 0;
++      guiLastX = 0;
++      guiLastY = 0;
++      guiLastInvPressure = 0xffffff;
++
++      /* Enable the touch screen scanning engine. */
++
++      TS_Hardware_Scan_Mode();
++
++}
++
++static void ep93xx_hw_shutdown(void)
++{
++      unsigned int uiKTDIV;
++
++      DPRINTK("ep93xx_hw_shutdown\n");
++
++      sTouch.state = TS_STATE_STOPPED;
++      Stop_Timer2();
++
++      /*
++       * Disable the scanning engine.
++       */
++      writel(0, TSSetup);
++      writel(0, TSSetup2);
++
++      /*
++       * Clear the TSEN bit in KTDIV so that we are disabling the clock
++       * for the touchscreen.
++       */
++      uiKTDIV = readl(SYSCON_KTDIV);
++      uiKTDIV &= ~SYSCON_KTDIV_TSEN;
++      SysconSetLocked(SYSCON_KTDIV, uiKTDIV);
++
++}
++
++static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id,
++                                   struct pt_regs *regs)
++{
++      DPRINTK("%d", (int)sTouch.state);
++
++      switch (sTouch.state) {
++      case TS_STATE_STOPPED:
++              TS_Hardware_Scan_Mode();
++              break;
++
++              /*
++               * Get the Z1 value for pressure measurement and set up
++               * the switch register for getting the Z2 measurement.
++               */
++      case TS_STATE_Z1:
++              Set_Timer2_uSec(EP93XX_TS_ADC_DELAY_USEC);
++              sTouch.uiZ1 = ADCGetData(2, 200);
++              ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ2);
++              sTouch.state = TS_STATE_Z2;
++              break;
++
++              /*
++               * Get the Z2 value for pressure measurement and set up
++               * the switch register for getting the Y measurement.
++               */
++      case TS_STATE_Z2:
++              sTouch.uiZ2 = ADCGetData(2, 200);
++              ep93xx_ts_set_direct(sSwitchSettings.uiYSample);
++              sTouch.state = TS_STATE_Y;
++              break;
++
++              /*
++               * Get the Y value and set up the switch register for
++               * getting the X measurement.
++               */
++      case TS_STATE_Y:
++              sTouch.uiY = ADCGetData(4, 20);
++              ep93xx_ts_set_direct(sSwitchSettings.uiXSample);
++              sTouch.state = TS_STATE_X;
++              break;
++
++              /*
++               * Read the X value.  This is the last of the 4 adc values
++               * we need so we continue on to process the data.
++               */
++      case TS_STATE_X:
++              Stop_Timer2();
++
++              sTouch.uiX = ADCGetData(4, 20);
++
++              writel(0xaa, TSSWLock);
++              writel(sSwitchSettings.uiDischarge, TSDirect);
++
++              sTouch.state = TS_STATE_DONE;
++
++              /* Process this set of ADC readings. */
++              ProcessPointData(dev_id);
++
++              break;
++
++              /* Shouldn't get here.  But if we do, we can recover... */
++      case TS_STATE_DONE:
++              TS_Hardware_Scan_Mode();
++              break;
++      }
++
++      /* Clear the timer2 interrupt. */
++      writel(1, TIMER2CLEAR);
++      return IRQ_HANDLED;
++
++}
++
++/*---------------------------------------------------------------------
++ * ProcessPointData
++ *
++ * This routine processes the ADC data into usable point data and then
++ * puts the driver into hw or sw scanning mode before returning.
++ *
++ * We calculate inverse pressure (lower number = more pressure) then
++ * do a hystheresis with the two pressure values 'light' and 'heavy'.
++ *
++ * If we are above the light, we have pen up.
++ * If we are below the heavy we have pen down.
++ * As long as the pressure stays below the light, pen stays down.
++ * When we get above the light again, pen goes back up.
++ *
++ */
++static void ProcessPointData(struct input_dev *dev)
++{
++      int bValidPoint = 0;
++      unsigned int uiXDiff, uiYDiff, uiInvPressureDiff;
++      unsigned int uiInvPressure;
++
++      /* Calculate the current pressure. */
++      uiInvPressure = CalculateInvPressure();
++
++      DPRINTK(" X=0x%x, Y=0x%x, Z1=0x%x, Z2=0x%x, InvPressure=0x%x",
++              sTouch.uiX, sTouch.uiY, sTouch.uiZ1, sTouch.uiZ2,
++              uiInvPressure);
++
++      /*
++       * If pen pressure is so light that it is greater than the 'max' setting
++       * then we consider this to be a pen up.
++       */
++      if (uiInvPressure >= TS_LIGHT_INV_PRESSURE) {
++              DPRINTK(" -- up \n");
++              bCurrentPenDown = 0;
++/*            input_report_key(dev, BTN_TOUCH, 0); */
++              input_report_abs(dev, ABS_PRESSURE, 0);
++              input_sync(dev);
++              TS_Hardware_Scan_Mode();
++              return;
++      }
++      /*
++       * Hystheresis:
++       * If the pen pressure is hard enough to be less than the 'min' OR
++       * the pen is already down and is still less than the 'max'...
++       */
++      if ((uiInvPressure < TS_HEAVY_INV_PRESSURE) ||
++          (bCurrentPenDown && (uiInvPressure < TS_LIGHT_INV_PRESSURE))) {
++              if (bCurrentPenDown) {
++                      /*
++                       * If pen was previously down, check the difference between
++                       * the last sample and this one... if the difference between
++                       * samples is too great, ignore the sample.
++                       */
++                      uiXDiff = abs(guiLastX - sTouch.uiX);
++                      uiYDiff = abs(guiLastY - sTouch.uiY);
++                      uiInvPressureDiff =
++                          abs(guiLastInvPressure - uiInvPressure);
++
++                      if ((uiXDiff < TS_MAX_VALID_XY_CHANGE) &&
++                          (uiYDiff < TS_MAX_VALID_XY_CHANGE) &&
++                          (uiInvPressureDiff < TS_MAX_VALID_PRESSURE_CHANGE))
++                      {
++                              DPRINTK(" -- valid(two) \n");
++                              bValidPoint = 1;
++                      } else {
++                              DPRINTK(" -- INvalid(two) \n");
++                      }
++              } else {
++                      DPRINTK(" -- valid \n");
++                      bValidPoint = 1;
++              }
++
++              /*
++               * If either the pen was put down or dragged make a note of it.
++               */
++              if (bValidPoint) {
++                      guiLastX = sTouch.uiX;
++                      guiLastY = sTouch.uiY;
++                      guiLastInvPressure = uiInvPressure;
++                      bCurrentPenDown = 1;
++                      input_report_abs(dev, ABS_X, sTouch.uiX);
++                      input_report_abs(dev, ABS_Y, sTouch.uiY);
++/*                    input_report_key(dev, BTN_TOUCH, 1); */
++                      input_report_abs(dev, ABS_PRESSURE, 1);
++                      input_sync(dev);
++              }
++
++              TS_Soft_Scan_Mode();
++              return;
++      }
++
++      DPRINTK(" -- fallout \n");
++      TS_Hardware_Scan_Mode();
++}
++
++static void ep93xx_ts_set_direct(unsigned int uiADCSwitch)
++{
++      unsigned int uiResult;
++
++      /* Set the switch settings in the direct register. */
++      writel(0xaa, TSSWLock);
++      writel(uiADCSwitch, TSDirect);
++
++      /* Read and throw away the first sample. */
++      do {
++              uiResult = readl(TSXYResult);
++      } while (!(uiResult & TSXYRESULT_SDR));
++
++}
++
++static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff)
++{
++      unsigned int uiResult, uiValue, uiCount, uiLowest, uiHighest, uiSum,
++          uiAve;
++
++      do {
++              /* Initialize our values. */
++              uiLowest = 0xfffffff;
++              uiHighest = 0;
++              uiSum = 0;
++
++              for (uiCount = 0; uiCount < uiSamples; uiCount++) {
++                      /* Read the touch screen four more times and average. */
++                      do {
++                              uiResult = readl(TSXYResult);
++                      } while (!(uiResult & TSXYRESULT_SDR));
++
++                      uiValue =
++                          (uiResult & TSXYRESULT_AD_MASK) >>
++                          TSXYRESULT_AD_SHIFT;
++                      uiValue =
++                          ((uiValue >> 4) +
++                           ((1 +
++                             TSXYRESULT_X_MASK) >> 1)) & TSXYRESULT_X_MASK;
++
++                      /* Add up the values. */
++                      uiSum += uiValue;
++
++                      /* Get the lowest and highest values. */
++                      if (uiValue < uiLowest)
++                              uiLowest = uiValue;
++
++                      if (uiValue > uiHighest)
++                              uiHighest = uiValue;
++
++              }
++
++      } while ((uiHighest - uiLowest) > uiMaxDiff);
++
++      /* Calculate the Average value. */
++      uiAve = uiSum / uiSamples;
++
++      return uiAve;
++}
++
++/**
++ * CalculateInvPressure
++ *
++ * Is the Touch Valid.  Touch is not valid if the X or Y value is not
++ * in range and the pressure is not  enough.
++ *
++ * Touch resistance can be measured by the following formula:
++ *
++ *          Rx * X *     Z2
++ * Rtouch = --------- * (-- - 1)
++ *           4096        Z1
++ *
++ * This is simplified in the ration of Rtouch to Rx.  The lower the value, the
++ * higher the pressure.
++ *
++ *                     Z2
++ * InvPressure =  X * (-- - 1)
++ *                     Z1
++ */
++static unsigned int CalculateInvPressure(void)
++{
++      unsigned int uiInvPressure;
++
++      /* Check to see if the point is valid. */
++      if (sTouch.uiZ1 < MIN_Z1_VALUE)
++              uiInvPressure = 0x10000;
++
++      /* Can omit the pressure calculation if you need to get rid of the division. */
++      else {
++              uiInvPressure =
++                  ((sTouch.uiX * sTouch.uiZ2) / sTouch.uiZ1) - sTouch.uiX;
++      }
++
++      return uiInvPressure;
++}
++
++/**
++ * TS_Hardware_Scan_Mode
++ * Enables the ep93xx ts scanning engine so that when the pen goes down
++ * we will get an interrupt.
++ */
++static void TS_Hardware_Scan_Mode(void)
++{
++      unsigned int uiDevCfg;
++
++      DPRINTK("S\n");
++
++      /* Disable the soft scanning engine. */
++      sTouch.state = TS_STATE_STOPPED;
++      Stop_Timer2();
++
++      /*
++       * Clear the TIN (Touchscreen INactive) bit so we can go to
++       * automatic scanning mode.
++       */
++      uiDevCfg = readl(SYSCON_DEVCFG);
++      SysconSetLocked(SYSCON_DEVCFG,
++                      ep93xx_SYSCON_DEVCFG(uiDevCfg & ~SYSCON_DEVCFG_TIN));
++
++      /*
++       * Enable the touch screen scanning state machine by setting
++       * the ENABLE bit.
++       */
++      writel((TSSETUP_DEFAULT | TSSETUP_ENABLE), TSSetup);
++
++      /* Set the flag to show that we are in interrupt mode. */
++      gScanningMode = TS_MODE_HARDWARE_SCAN;
++
++      /* Initialize TSSetup2 register. */
++      writel(TSSETUP2_DEFAULT, TSSetup2);
++
++}
++
++/**
++ * TS_Soft_Scan_Mode - Set the touch screen to manual polling mode.
++ */
++static void TS_Soft_Scan_Mode(void)
++{
++      unsigned int uiDevCfg;
++
++      DPRINTK("M\n");
++
++      if (gScanningMode != TS_MODE_SOFT_SCAN) {
++              /*
++               * Disable the touch screen scanning state machine by clearing
++               * the ENABLE bit.
++               */
++              writel(TSSETUP_DEFAULT, TSSetup);
++
++              /* Set the TIN bit so we can do manual touchscreen polling. */
++              uiDevCfg = readl(SYSCON_DEVCFG);
++              SysconSetLocked(SYSCON_DEVCFG,
++                              ep93xx_SYSCON_DEVCFG(uiDevCfg |
++                                                   SYSCON_DEVCFG_TIN));
++      }
++      /* Set the switch register up for the first ADC reading */
++      ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ1);
++
++      /*
++       * Initialize our software state machine to know which ADC
++       * reading to take
++       */
++      sTouch.state = TS_STATE_Z1;
++
++      /*
++       * Set the timer so after a mSec or two settling delay it will
++       * take the first ADC reading.
++       */
++      Set_Timer2_uSec(EP93XX_TS_PER_POINT_DELAY_USEC);
++
++      /* Note that we are in sw scanning mode not hw scanning mode. */
++      gScanningMode = TS_MODE_SOFT_SCAN;
++
++}
++
++static void Set_Timer2_uSec(unsigned int uiDelay_uSec)
++{
++      unsigned int uiClockTicks;
++
++      /*
++       * Stop timer 2
++       */
++      writel(0, TIMER2CONTROL);
++
++      uiClockTicks = ((uiDelay_uSec * 508) + 999) / 1000;
++      writel(uiClockTicks, TIMER2LOAD);
++      writel(uiClockTicks, TIMER2VALUE);
++
++      /*
++       * Set up Timer 2 for 508 kHz clock and periodic mode.
++       */
++      writel(0xC8, TIMER2CONTROL);
++
++}
++
++static void Stop_Timer2(void)
++{
++      writel(0, TIMER2CONTROL);
++}
++
++static struct input_dev *ep93xx_ts_dev;
++
++static int __init ep93xx_ts_init(void)
++{
++      ep93xx_ts_dev = input_allocate_device();
++      if (!ep93xx_ts_dev) {
++              printk(KERN_ERR "ep93xx_ts_dev: not enough memory for input device\n");
++              return -ENOMEM;
++      }
++                      
++      ep93xx_ts_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
++      ep93xx_ts_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
++      ep93xx_ts_dev->keybit[LONG(BTN_RAW)] = BIT(BTN_RAW);
++
++      /* untested, I haven't got a touchscreen (yet) :( */
++        input_set_abs_params(ep93xx_ts_dev, ABS_X, 0, 4095, 0, 0);
++        input_set_abs_params(ep93xx_ts_dev, ABS_Y, 0, 4095, 0, 0);
++        input_set_abs_params(ep93xx_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);
++      
++      ep93xx_ts_dev->open = ep93xx_ts_open;
++      ep93xx_ts_dev->close = ep93xx_ts_close;
++      ep93xx_ts_dev->name = "Cirrus Logic EP93xx Touchscreen";
++      ep93xx_ts_dev->phys = "ep93xx_ts/input0";
++      ep93xx_ts_dev->id.bustype = BUS_HOST;
++      ep93xx_ts_dev->id.vendor = PCI_VENDOR_ID_CIRRUS;
++      ep93xx_ts_dev->id.product = 0x9300;
++
++      input_set_abs_params(ep93xx_ts_dev, ABS_X, TS_X_MIN, TS_X_MAX, 0, 0);
++      input_set_abs_params(ep93xx_ts_dev, ABS_Y, TS_Y_MIN, TS_Y_MAX, 0, 0);
++      input_register_device(ep93xx_ts_dev);
++
++      sTouch.state = TS_STATE_STOPPED;
++      gScanningMode = TS_MODE_UN_INITIALIZED;
++
++      printk(KERN_NOTICE
++             "EP93xx touchscreen driver configured for 4-wire operation\n");
++      return 0;
++}
++
++static void __exit ep93xx_ts_exit(void)
++{
++      input_unregister_device(ep93xx_ts_dev);
++}
++
++module_init(ep93xx_ts_init);
++module_exit(ep93xx_ts_exit);
++
++MODULE_DESCRIPTION("Cirrus EP93xx touchscreen driver");
++MODULE_SUPPORTED_DEVICE("touchscreen/ep93xx");
+diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
+index b9b77cf..4e0e427 100644
+--- a/drivers/mtd/maps/Kconfig
++++ b/drivers/mtd/maps/Kconfig
+@@ -137,6 +137,13 @@ config MTD_MAINSTONE
+         This provides a driver for the on-board flash of the Intel
+         'Mainstone PXA27x evaluation board.
++config MTD_ADSFLASH
++      tristate "CFI Flash device mapped on ADS"
++      depends on ARM && MTD_CFI && MACH_ADSSPHERE && MTD_PARTITIONS
++      help
++        This enables access to on-board flash memory on ADS platforms that
++        have an Intel XScale PXA2xx CPU.
++
+ config MTD_OCTAGON
+       tristate "JEDEC Flash device mapped on Octagon 5066 SBC"
+       depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS
+@@ -639,5 +646,19 @@ config MTD_PLATRAM
+         This selection automatically selects the map_ram driver.
++config MTD_ZEFEERDZB
++      tristate "Map driver for DAVE Srl ZefeerDZB processor module"
++      depends on (MTD_CFI && MACH_ZEFEERDZB)
++      select MTD_PARTITIONS
++      help
++        Map driver for DAVE Srl ZefeerDZB processor module.
++
++config MTD_ZEFEERDZQ
++      tristate "Map driver for DAVE Srl ZefeerDZQ processor module"
++      depends on (MTD_CFI && MACH_ZEFEERDZQ)
++      select MTD_PARTITIONS
++      help
++        Map driver for DAVE Srl ZefeerDZQ processor module.
++
+ endmenu
+diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
+index 2f7e254..a821568 100644
+--- a/drivers/mtd/maps/Makefile
++++ b/drivers/mtd/maps/Makefile
+@@ -22,6 +22,7 @@ obj-$(CONFIG_MTD_AMD76XROM)  += amd76xrom
+ obj-$(CONFIG_MTD_ICHXROM)     += ichxrom.o
+ obj-$(CONFIG_MTD_TSUNAMI)     += tsunami_flash.o
+ obj-$(CONFIG_MTD_LUBBOCK)     += lubbock-flash.o
++obj-$(CONFIG_MTD_ADSFLASH)    += ads-flash.o
+ obj-$(CONFIG_MTD_MAINSTONE)   += mainstone-flash.o
+ obj-$(CONFIG_MTD_MBX860)      += mbx860.o
+ obj-$(CONFIG_MTD_CEIVA)               += ceiva.o
+@@ -72,3 +73,5 @@ obj-$(CONFIG_MTD_PLATRAM)    += plat-ram.o
+ obj-$(CONFIG_MTD_OMAP_NOR)    += omap_nor.o
+ obj-$(CONFIG_MTD_MTX1)                += mtx-1_flash.o
+ obj-$(CONFIG_MTD_TQM834x)     += tqm834x.o
++obj-$(CONFIG_MTD_ZEFEERDZB)   += zefeerdzb.o
++obj-$(CONFIG_MTD_ZEFEERDZQ)   += zefeerdzq.o
+diff --git a/drivers/mtd/maps/ads-flash.c b/drivers/mtd/maps/ads-flash.c
+new file mode 100644
+index 0000000..2428e9c
+--- /dev/null
++++ b/drivers/mtd/maps/ads-flash.c
+@@ -0,0 +1,221 @@
++/*
++ * Map driver for the ADS PXA Boards.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++#include <asm/io.h>
++#include <asm/hardware.h>
++
++#ifdef CONFIG_MACH_ADSVIX
++#define NUM_CHIPS     1
++#else
++#define NUM_CHIPS     2
++#endif
++
++#ifdef CONFIG_PXA27x
++#define WINDOW_ADDR   0
++#elif defined(CONFIG_ARCH_EP93XX)
++#define WINDOW_ADDR     0x60000000
++#else
++#define WINDOW_ADDR   0x04000000
++#endif
++
++#define WINDOW_SIZE   (NUM_CHIPS * 32*1024*1024)
++#define BLOCKSIZE     (NUM_CHIPS * 0x20000)
++#define BANKWIDTH     (NUM_CHIPS * 2)
++
++static void pxa_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len)
++{
++      consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
++}
++
++static struct map_info pxa_map = {
++      .name           = "pxa",
++      .size           = WINDOW_SIZE,
++      .phys           = WINDOW_ADDR,
++      .virt           = 0,
++      .cached         = (void *)NULL,
++      .bankwidth      = BANKWIDTH,
++      .inval_cache    = pxa_map_inval_cache,
++};
++
++static struct mtd_partition ads_partitions[] = {
++      {
++              name:           "boot",
++              size:           BLOCKSIZE,
++              offset:         0,
++      }, {
++              name:           "bootvars",
++              size:           BLOCKSIZE,
++              offset:         MTDPART_OFS_APPEND,
++      }, {
++              name:           "zImage",
++              size:           0x00180000,
++              offset:         MTDPART_OFS_APPEND,
++      }, {
++              name:           "ramdisk.gz",
++              size:           0x00500000,
++              offset:         MTDPART_OFS_APPEND,
++      }, {
++              name:           "flashfs1",
++              size:           MTDPART_SIZ_FULL,
++              offset:         MTDPART_OFS_APPEND
++      }
++};
++
++unsigned char ads_flash_serial_id[32+2] = {0};
++
++static struct mtd_info *mymtd = NULL;
++static struct mtd_partition *parsed_parts = NULL;
++static int num_parts = 0;
++static const char *probes[] = {
++#ifdef CONFIG_MTD_CMDLINE_PARTS
++  "cmdlinepart",
++#endif
++#ifdef CONFIG_MTD_REDBOOT_PARTS
++  "RedBoot",
++#endif
++  NULL };
++
++// This implementation supports 1 or 2 chips.
++static void ads_get_flash_serial_id(int chips)
++{
++      map_word val;
++      unsigned int addr = 0x81 << chips;
++      unsigned int mask = chips == 1 ? 0xffff : 0xffffffff;
++      unsigned int tmp[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
++      int i;
++
++      /* read array mode */
++      // *(__u32 *)pxa_map.virt = 0x00FF00FF;
++      // *(__u16 *)pxa_map.virt = 0x00ff;
++      val.x[0] = 0x00ff00ff & mask;
++      map_write(&pxa_map, val, 0);
++
++      /* read id mode */
++      // *(__u32 *)pxa_map.virt = 0x00900090;
++      // *(__u16 *)pxa_map.virt = 0x0090;
++      val.x[0] = 0x00900090 & mask;
++      map_write(&pxa_map, val, 0);
++
++      for (i=0; i<8; i++) {
++              // tmp[i] = 0x0000ffff & *(__u32 *)(pxa_map.virt + addr);
++              // tmp[i] = *(__u16 *)(pxa_map.virt + addr);
++              val = map_read(&pxa_map, addr);
++              tmp[i] = val.x[0] & 0xffff;
++              addr += BANKWIDTH;
++      }
++
++      /* back to read array mode */
++      // *(__u32 *)pxa_map.virt = 0x00FF00FF;
++      // *(__u16 *)pxa_map.virt = 0x00ff;
++      val.x[0] = 0x00ff00ff & mask;
++      map_write(&pxa_map, val, 0);
++
++      sprintf(ads_flash_serial_id, "%04x%04x%04x%04x.%04x%04x%04x%04x",
++              tmp[7], tmp[6], tmp[5], tmp[4], tmp[3], tmp[2], tmp[1], tmp[0]);
++
++}
++
++static int __init init_pxa_flash(void)
++{
++      struct mtd_partition *parts;
++      char *part_type;
++      int rtn;
++
++      printk(KERN_NOTICE "Probing PXA flash at physical address 0x%08x\n", WINDOW_ADDR);
++      pxa_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
++      if (!pxa_map.virt) {
++              printk(KERN_ERR "Failed to ioremap flash\n");
++              return -EIO;
++      }
++
++      pxa_map.cached = __ioremap(WINDOW_ADDR, WINDOW_SIZE, L_PTE_CACHEABLE, 1);
++      if (!pxa_map.cached)
++              printk(KERN_WARNING "Failed to ioremap cached flash\n");
++
++      simple_map_init(&pxa_map);
++
++      mymtd = do_map_probe("cfi_probe", &pxa_map);
++      if (!mymtd) {
++              if (pxa_map.cached)
++                      iounmap((void *)pxa_map.cached);
++              if (pxa_map.virt)
++                      iounmap((void *)pxa_map.virt);
++              return -ENXIO;
++      }
++
++#ifdef CONFIG_MTD_CMDLINE_PARTS
++      pxa_map.name = "pxa";
++      rtn = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0);
++      if (rtn <= 0) {
++              pxa_map.name = "sa1100";
++              rtn = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0);
++      }
++      if (rtn > 0) {
++              num_parts = rtn;
++              parts     = parsed_parts;
++              part_type = "command line";
++              goto add_parts;
++      }
++#endif
++      num_parts = ARRAY_SIZE(ads_partitions);
++      parts     = ads_partitions;
++      part_type = "static";
++add_parts:
++      if (num_parts) {
++              printk(KERN_NOTICE "Using %s partition definition\n", part_type);
++              add_mtd_partitions(mymtd, parts, num_parts);
++#if 0
++              if (mymtd->unlock) {
++                      int i;
++                      for (i = 0; i < num_parts; i++) {
++                              // unlock partition
++                              mymtd->unlock(mymtd, parts[num_parts - 1].offset,
++                                                   parts[num_parts - 1].size);
++                      }
++              }
++#endif
++      }
++      else {
++              add_mtd_device(mymtd);
++      }
++
++      ads_get_flash_serial_id(NUM_CHIPS);
++
++      return 0;
++}
++
++static void __exit cleanup_pxa_flash(void)
++{
++      if (mymtd) {
++              if (num_parts)
++                      del_mtd_partitions(mymtd);
++              else
++                      del_mtd_device(mymtd);
++              map_destroy(mymtd);
++              if (parsed_parts)
++                      kfree(parsed_parts);
++      }
++      if (pxa_map.cached)
++              iounmap((void *)pxa_map.cached);
++      if (pxa_map.virt)
++              iounmap((void *)pxa_map.virt);
++}
++
++module_init(init_pxa_flash);
++module_exit(cleanup_pxa_flash);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mtd/maps/zefeerdzb.c b/drivers/mtd/maps/zefeerdzb.c
+new file mode 100644
+index 0000000..bb47bc6
+--- /dev/null
++++ b/drivers/mtd/maps/zefeerdzb.c
+@@ -0,0 +1,134 @@
++/*
++ * $Id: zefeerdzb.c,v 1.8 2004/07/12 21:59:44 dwmw2 Exp $
++ *
++ * drivers/mtd/maps/zefeerdzb.c
++ *
++ * FLASH map for the DAVE Srl ZefeerDZB processor module.
++ *
++ *
++ * 2004 (c) DAVE Srl. This file is licensed under
++ * the terms of the GNU General Public License version 2. This program
++ * is licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++
++#if 0
++/* Support for ZELK <= 0.9.5 */
++#define WINDOW_ADDR 0x60000000
++#else
++#define WINDOW_ADDR 0x00000000
++#endif
++#define WINDOW_SIZE 0x00400000
++
++/* 128 kB U-Boot */
++#define ZEFEERDZB_PART0_OF    0
++#define ZEFEERDZB_PART0_SZ    0x20000
++/* 128  kB U-Boot env #1 */
++#define ZEFEERDZB_PART1_OF    ZEFEERDZB_PART0_OF + ZEFEERDZB_PART0_SZ
++#define ZEFEERDZB_PART1_SZ    0x20000
++/* 128  kB U-Boot env #2 */
++#define ZEFEERDZB_PART2_OF    ZEFEERDZB_PART1_OF + ZEFEERDZB_PART1_SZ
++#define ZEFEERDZB_PART2_SZ    0x20000
++/* Linux kernel */
++#define ZEFEERDZB_PART3_OF    ZEFEERDZB_PART2_OF + ZEFEERDZB_PART2_SZ
++#define ZEFEERDZB_PART3_SZ    (0x200000 - ZEFEERDZB_PART2_SZ - ZEFEERDZB_PART1_SZ - ZEFEERDZB_PART0_SZ)
++/* spare */
++#define ZEFEERDZB_PART4_OF    ZEFEERDZB_PART3_OF + ZEFEERDZB_PART3_SZ
++#define ZEFEERDZB_PART4_SZ    (0x400000 - ZEFEERDZB_PART3_SZ - ZEFEERDZB_PART2_SZ - ZEFEERDZB_PART1_SZ - ZEFEERDZB_PART0_SZ)
++
++static struct mtd_partition zefeerdzb_flash_partitions[] = {
++      {
++       .name = "U-Boot",
++       .offset = ZEFEERDZB_PART0_OF,
++       .size = ZEFEERDZB_PART0_SZ,
++       .mask_flags = MTD_WRITEABLE    /* force read-only */
++       },
++      {
++       .name = "U-Boot environment #1",
++       .offset = ZEFEERDZB_PART1_OF,
++       .size = ZEFEERDZB_PART1_SZ,
++       },
++      {
++       .name = "U-Boot environment #2",
++       .offset = ZEFEERDZB_PART2_OF,
++       .size = ZEFEERDZB_PART2_SZ,
++       },
++      {
++       .name = "Linux kernel",
++       .offset = ZEFEERDZB_PART3_OF,
++       .size = ZEFEERDZB_PART3_SZ,
++       },
++      {
++       .name = "spare 1",
++       .offset = ZEFEERDZB_PART4_OF,
++       .size = ZEFEERDZB_PART4_SZ,
++       }
++};
++
++struct map_info zefeerdzb_flash_map = {
++      .name = "DAVE Srl ZefeerDZB",
++      .size = WINDOW_SIZE,
++      .bankwidth = 2,
++      .phys = WINDOW_ADDR,
++};
++
++#define NUM_ZEFEERDZB_FLASH_PARTITIONS \
++      (sizeof(zefeerdzb_flash_partitions)/sizeof(zefeerdzb_flash_partitions[0]))
++
++static struct mtd_info *zefeerdzb_mtd;
++
++int __init init_zefeerdzb_flash(void)
++{
++      printk(KERN_NOTICE "zefeerdzb: flash mapping: %x at %x\n",
++             WINDOW_SIZE, WINDOW_ADDR);
++
++      zefeerdzb_flash_map.virt =
++          (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
++
++      if (!zefeerdzb_flash_map.virt) {
++              printk("init_zefeerdzb_flash: failed to ioremap\n");
++              return -EIO;
++      }
++      simple_map_init(&zefeerdzb_flash_map);
++
++      zefeerdzb_mtd = do_map_probe("cfi_probe", &zefeerdzb_flash_map);
++
++      if (zefeerdzb_mtd) {
++              zefeerdzb_mtd->owner = THIS_MODULE;
++              return add_mtd_partitions(zefeerdzb_mtd,
++                                        zefeerdzb_flash_partitions,
++                                        NUM_ZEFEERDZB_FLASH_PARTITIONS);
++      }
++
++      return -ENXIO;
++}
++
++static void __exit cleanup_zefeerdzb_flash(void)
++{
++      if (zefeerdzb_mtd) {
++              del_mtd_partitions(zefeerdzb_mtd);
++              /* moved iounmap after map_destroy - armin */
++              map_destroy(zefeerdzb_mtd);
++              iounmap((void *)zefeerdzb_flash_map.virt);
++      }
++}
++
++module_init(init_zefeerdzb_flash);
++module_exit(cleanup_zefeerdzb_flash);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("DAVE Srl <info@dave-tech.it>");
++MODULE_DESCRIPTION
++    ("MTD map driver for the DAVE Srl ZefeerDZB processor module");
+diff --git a/drivers/mtd/maps/zefeerdzq.c b/drivers/mtd/maps/zefeerdzq.c
+new file mode 100644
+index 0000000..dc0e402
+--- /dev/null
++++ b/drivers/mtd/maps/zefeerdzq.c
+@@ -0,0 +1,142 @@
++/*
++ * $Id: zefeerdzq.c,v 1.8 2004/07/12 21:59:44 dwmw2 Exp $
++ *
++ * drivers/mtd/maps/zefeerdzq.c
++ *
++ * FLASH map for the DAVE Srl ZefeerDZQ processor module.
++ *
++ *
++ * 2004 (c) DAVE Srl. This file is licensed under
++ * the terms of the GNU General Public License version 2. This program
++ * is licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++
++#if 0
++/* Support for ZELK <= 0.9.5 */
++#define WINDOW_ADDR 0x60000000
++#else
++#define WINDOW_ADDR 0x00000000
++#endif
++#define WINDOW_SIZE 0x01000000
++
++/* 128 kB U-Boot */
++#define ZEFEERDZQ_PART0_OF    0
++#define ZEFEERDZQ_PART0_SZ    0x20000
++/* 128  kB U-Boot env #1 */
++#define ZEFEERDZQ_PART1_OF    ZEFEERDZQ_PART0_OF + ZEFEERDZQ_PART0_SZ
++#define ZEFEERDZQ_PART1_SZ    0x20000
++/* 128  kB U-Boot env #2 */
++#define ZEFEERDZQ_PART2_OF    ZEFEERDZQ_PART1_OF + ZEFEERDZQ_PART1_SZ
++#define ZEFEERDZQ_PART2_SZ    0x20000
++/* Linux kernel */
++#define ZEFEERDZQ_PART3_OF    ZEFEERDZQ_PART2_OF + ZEFEERDZQ_PART2_SZ
++#define ZEFEERDZQ_PART3_SZ    (0x200000 - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ)
++/* ramdisk */
++#define ZEFEERDZQ_PART4_OF    ZEFEERDZQ_PART3_OF + ZEFEERDZQ_PART3_SZ
++#define ZEFEERDZQ_PART4_SZ    (0x400000 - ZEFEERDZQ_PART3_SZ - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ)
++/* spare */
++#define ZEFEERDZQ_PART5_OF    ZEFEERDZQ_PART4_OF + ZEFEERDZQ_PART4_SZ
++#define ZEFEERDZQ_PART5_SZ    (WINDOW_SIZE - ZEFEERDZQ_PART4_SZ - ZEFEERDZQ_PART3_SZ - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ)
++
++static struct mtd_partition zefeerdzq_flash_partitions[] = {
++      {
++       .name = "U-Boot",
++       .offset = ZEFEERDZQ_PART0_OF,
++       .size = ZEFEERDZQ_PART0_SZ,
++       .mask_flags = MTD_WRITEABLE    /* force read-only */
++       },
++      {
++       .name = "U-Boot environment #1",
++       .offset = ZEFEERDZQ_PART1_OF,
++       .size = ZEFEERDZQ_PART1_SZ,
++       },
++      {
++       .name = "U-Boot environment #2",
++       .offset = ZEFEERDZQ_PART2_OF,
++       .size = ZEFEERDZQ_PART2_SZ,
++       },
++      {
++       .name = "Linux kernel",
++       .offset = ZEFEERDZQ_PART3_OF,
++       .size = ZEFEERDZQ_PART3_SZ,
++       },
++      {
++       .name = "spare 1",
++       .offset = ZEFEERDZQ_PART4_OF,
++       .size = ZEFEERDZQ_PART4_SZ,
++       },
++      {
++       .name = "spare 2",
++       .offset = ZEFEERDZQ_PART5_OF,
++       .size = ZEFEERDZQ_PART5_SZ,
++       }
++};
++
++struct map_info zefeerdzq_flash_map = {
++      .name = "DAVE Srl ZefeerDZQ",
++      .size = WINDOW_SIZE,
++      .bankwidth = 2,
++      .phys = WINDOW_ADDR,
++};
++
++#define NUM_ZEFEERDZQ_FLASH_PARTITIONS \
++      (sizeof(zefeerdzq_flash_partitions)/sizeof(zefeerdzq_flash_partitions[0]))
++
++static struct mtd_info *zefeerdzq_mtd;
++
++int __init init_zefeerdzq_flash(void)
++{
++      printk(KERN_NOTICE "zefeerdzq: flash mapping: %x at %x\n",
++             WINDOW_SIZE, WINDOW_ADDR);
++
++      zefeerdzq_flash_map.virt =
++          (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
++
++      if (!zefeerdzq_flash_map.virt) {
++              printk("init_zefeerdzq_flash: failed to ioremap\n");
++              return -EIO;
++      }
++      simple_map_init(&zefeerdzq_flash_map);
++
++      zefeerdzq_mtd = do_map_probe("cfi_probe", &zefeerdzq_flash_map);
++
++      if (zefeerdzq_mtd) {
++              zefeerdzq_mtd->owner = THIS_MODULE;
++              return add_mtd_partitions(zefeerdzq_mtd,
++                                        zefeerdzq_flash_partitions,
++                                        NUM_ZEFEERDZQ_FLASH_PARTITIONS);
++      }
++
++      return -ENXIO;
++}
++
++static void __exit cleanup_zefeerdzq_flash(void)
++{
++      if (zefeerdzq_mtd) {
++              del_mtd_partitions(zefeerdzq_mtd);
++              /* moved iounmap after map_destroy - armin */
++              map_destroy(zefeerdzq_mtd);
++              iounmap((void *)zefeerdzq_flash_map.virt);
++      }
++}
++
++module_init(init_zefeerdzq_flash);
++module_exit(cleanup_zefeerdzq_flash);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("DAVE Srl <info@dave-tech.it>");
++MODULE_DESCRIPTION
++    ("MTD map driver for the DAVE Srl ZefeerDZQ processor module");
+diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
+index 1fc4c13..8e79d32 100644
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -109,6 +109,12 @@ config MTD_NAND_S3C2410_HWECC
+         currently not be able to switch to software, as there is no
+         implementation for ECC method used by the S3C2410
++config MTD_NAND_ZEFEEREVB
++      tristate "NAND Flash device on ZefeerEVB (L/H) board"
++      depends on (MACH_ZEFEERDZA || MACH_ZEFEERDZB || MACH_ZEFEERDZG || MACH_ZEFEERDZN ||  MACH_ZEFEERDZQ) && MTD_NAND
++      help
++        This enables the NAND flash driver on the ZefeerEVB Board (L or H version).
++
+ config MTD_NAND_DISKONCHIP
+       tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
+       depends on MTD_NAND && EXPERIMENTAL
+diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
+index 4174202..bee7760 100644
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -18,5 +18,6 @@ obj-$(CONFIG_MTD_NAND_H1900)         += h1910.o
+ obj-$(CONFIG_MTD_NAND_RTC_FROM4)      += rtc_from4.o
+ obj-$(CONFIG_MTD_NAND_SHARPSL)                += sharpsl.o
+ obj-$(CONFIG_MTD_NAND_NANDSIM)                += nandsim.o
++obj-$(CONFIG_MTD_NAND_ZEFEEREVB)      += zefeerevb.o
+ nand-objs = nand_base.o nand_bbt.o
+diff --git a/drivers/mtd/nand/zefeerevb.c b/drivers/mtd/nand/zefeerevb.c
+new file mode 100644
+index 0000000..b67e958
+--- /dev/null
++++ b/drivers/mtd/nand/zefeerevb.c
+@@ -0,0 +1,280 @@
++/*
++ *  drivers/mtd/nand/zefeerevb.c
++ *
++ *  Copyright (C) 2004 DAVE Srl (info@dave-tech.it)
++ *
++ *
++ *
++ * $Id: zefeerevb.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ *  Overview:
++ *   This is a device driver for the NAND flash devices found on the
++ *   ZefeerEVB board (Samsung K9F5608U0B 32MB).
++ */
++
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/partitions.h>
++#include <asm/arch/regmap.h>
++#include <asm/arch/zefeerevb.h>
++#include <asm/io.h>
++
++#define USE_READY_BUSY_PIN
++/* see datasheets (tR) */
++#define NAND_BIG_DELAY_US             25
++#define NAND_SMALL_DELAY_US           10
++
++/* handy sizes */
++#define SZ_4M                           0x00400000
++#define NAND_SMALL_SIZE                 0x02000000
++#define NAND_EVB_MTD_NAME     "zefeerevb-nand"
++
++/* Macros to perform I/O operations */
++#define MACRO_NAND_DISABLE_CE(nandptr) do \
++{ \
++      writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_nCE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_ENABLE_CE(nandptr) do \
++{ \
++      writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_nCE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_CTL_CLRALE(nandptr) do \
++{ \
++      writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_ALE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_CTL_SETALE(nandptr) do \
++{ \
++      writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_ALE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_CTL_CLRCLE(nandptr) do \
++{ \
++      writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_CLE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_CTL_SETCLE(nandptr) do \
++{ \
++      writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_CLE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_WAIT_READY(nand) \
++while ( !(readl((volatile unsigned*)GPIO_PADR) & NAND_EVB_RB_GPIO_PIN); )
++
++/*
++ * MTD structure for ZefeerEVB board
++ */
++static struct mtd_info *zefeerevb_mtd = NULL;
++
++/*
++ * Module stuff
++ */
++static int zefeerevb_fio_pbase = ZEFEEREVB_NAND_PADDR;
++
++#ifdef MODULE
++MODULE_PARM(zefeerevb_fio_pbase, "i");
++__setup("zefeerevb_fio_pbase=", zefeerevb_fio_pbase);
++#endif
++
++#ifdef CONFIG_MTD_PARTITIONS
++/*
++ * Define static partitions for flash devices
++ */
++static struct mtd_partition partition_info_evb[] = {
++      {name:"ZefeerEVB Nand Flash",
++            offset:0,
++      size:32 * 1024 * 1024}
++};
++
++#define NUM_PARTITIONS 1
++
++extern int parse_cmdline_partitions(struct mtd_info *master,
++                                  struct mtd_partition **pparts,
++                                  const char *mtd_id);
++#endif
++
++static void zefeerevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
++{
++      switch (cmd) {
++
++      case NAND_CTL_SETCLE:
++              MACRO_NAND_CTL_SETCLE((unsigned long)0);
++              break;
++      case NAND_CTL_CLRCLE:
++              MACRO_NAND_CTL_CLRCLE((unsigned long)0);
++              break;
++      case NAND_CTL_SETALE:
++              MACRO_NAND_CTL_SETALE((unsigned long)0);
++              break;
++      case NAND_CTL_CLRALE:
++              MACRO_NAND_CTL_CLRALE((unsigned long)0);
++              break;
++      case NAND_CTL_SETNCE:
++              MACRO_NAND_ENABLE_CE((unsigned long)0);
++              break;
++      case NAND_CTL_CLRNCE:
++              MACRO_NAND_DISABLE_CE((unsigned long)0);
++              break;
++      }
++}
++
++#ifdef USE_READY_BUSY_PIN
++/*
++ *    read device ready pin
++ */
++static int zefeerevb_device_ready(struct mtd_info *minfo)
++{
++      return (readl((volatile unsigned *)GPIO_PADR) &
++              NAND_EVB_RB_GPIO_PIN);
++}
++#endif
++
++#ifdef CONFIG_MTD_PARTITIONS
++const char *part_probes_evb[] = { "cmdlinepart", NULL };
++#endif
++
++/*
++ * Main initialization routine
++ */
++static int __init zefeerevb_init(void)
++{
++      struct nand_chip *this;
++      const char *part_type = 0;
++      int mtd_parts_nb = 0;
++      struct mtd_partition *mtd_parts = 0;
++      void __iomem *zefeerevb_fio_base;
++      u32 tmp;
++
++      /* Init I/O pins */
++      MACRO_NAND_DISABLE_CE(0);
++      MACRO_NAND_CTL_CLRALE(0);
++      MACRO_NAND_CTL_CLRCLE(0);
++
++      tmp = (u32) readl(GPIO_PADDR);
++      tmp |=
++          (NAND_EVB_nCE_GPIO_PIN | NAND_EVB_CLE_GPIO_PIN |
++           NAND_EVB_ALE_GPIO_PIN);
++#ifdef USE_READY_BUSY_PIN
++      tmp &= ~NAND_EVB_RB_GPIO_PIN;
++#endif
++      writel(tmp, GPIO_PADDR);
++
++      /* Init I/O pins */
++      MACRO_NAND_DISABLE_CE(0);
++      MACRO_NAND_CTL_CLRALE(0);
++      MACRO_NAND_CTL_CLRCLE(0);
++
++      /* Set up chip select */
++      writel((0 << 30) | (0 << 28) | (0 << 27) | (0 << 26) | (0 << 11) |
++             (1 << 10) | (4 << 5) | (6 << 0), SMCBCR2);
++
++      /* Allocate memory for MTD device structure and private data */
++      zefeerevb_mtd = kmalloc(sizeof(struct mtd_info) +
++                              sizeof(struct nand_chip), GFP_KERNEL);
++      if (!zefeerevb_mtd) {
++              printk
++                  ("Unable to allocate ZefeerEVB NAND MTD device structure.\n");
++              return -ENOMEM;
++      }
++
++      /* map physical address */
++      zefeerevb_fio_base =
++          (void __iomem *)ioremap(zefeerevb_fio_pbase, SZ_4M);
++      if (!zefeerevb_fio_base) {
++              printk("ioremap ZefeerEVB NAND flash failed\n");
++              kfree(zefeerevb_mtd);
++              return -EIO;
++      }
++
++      /* Get pointer to private data */
++      this = (struct nand_chip *)(&zefeerevb_mtd[1]);
++
++      /* Initialize structures */
++      memset((char *)zefeerevb_mtd, 0, sizeof(struct mtd_info));
++      memset((char *)this, 0, sizeof(struct nand_chip));
++
++      /* Link the private data with the MTD structure */
++      zefeerevb_mtd->priv = this;
++
++      /* insert callbacks */
++      this->IO_ADDR_R = (void __iomem *)zefeerevb_fio_base;
++      this->IO_ADDR_W = (void __iomem *)zefeerevb_fio_base;
++      this->hwcontrol = zefeerevb_hwcontrol;
++#ifdef USE_READY_BUSY_PIN
++      this->dev_ready = zefeerevb_device_ready;
++#endif
++      this->chip_delay = NAND_SMALL_DELAY_US;
++
++      /* ECC mode */
++      this->eccmode = NAND_ECC_SOFT;
++
++      /* Scan to find existence of the device */
++      if (nand_scan(zefeerevb_mtd, 1)) {
++              iounmap((void *)zefeerevb_fio_base);
++              kfree(zefeerevb_mtd);
++              return -ENXIO;
++      }
++#ifdef CONFIG_MTD_PARTITIONS
++      zefeerevb_mtd->name = NAND_EVB_MTD_NAME;
++      mtd_parts_nb =
++          parse_mtd_partitions(zefeerevb_mtd, part_probes_evb, &mtd_parts, 0);
++      if (mtd_parts_nb > 0)
++              part_type = "command line";
++      else
++              mtd_parts_nb = 0;
++#endif
++      if (mtd_parts_nb == 0) {
++#ifdef CONFIG_MTD_PARTITIONS
++              mtd_parts = partition_info_evb;
++              mtd_parts_nb = NUM_PARTITIONS;
++#endif
++              part_type = "static";
++      }
++
++      /* Register the partitions */
++      printk(KERN_NOTICE "Using %s partition definition\n", part_type);
++      add_mtd_partitions(zefeerevb_mtd, mtd_parts, mtd_parts_nb);
++
++      /* Return happy */
++      return 0;
++}
++
++module_init(zefeerevb_init);
++
++#ifdef MODULE
++/*
++ * Clean up routine
++ */
++static void __exit zefeerevb_cleanup(void)
++{
++      struct nand_chip *this;
++
++      /* Release resources, unregister device(s) */
++      nand_release(zefeer_mtd);
++      nand_release(zefeerevb_mtd);
++
++      /* Release iomaps */
++      this = (struct nand_chip *)&zefeer_mtd[1];
++      iounmap((void *)this->zefeer_fio_base;
++              this = (struct nand_chip *)&zefeerevb_mtd[1];
++              iounmap((void *)this->zefeerevb_fio_base;
++                      /* Free the MTD device structure */
++                      kfree(zefeer_mtd);
++                      kfree(zefeerevb_mtd);
++                      }
++
++                      module_exit(zefeerevb_cleanup);
++#endif
++                      MODULE_LICENSE("GPL");
++                      MODULE_AUTHOR("DAVE Srl <support-zefeer@dave-tech.it>");
++                      MODULE_DESCRIPTION
++                      ("MTD map driver for DAVE Srl ZefeerEVB (L/H) board");
+diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
+index 470364d..12afe1d 100644
+--- a/drivers/net/arm/Kconfig
++++ b/drivers/net/arm/Kconfig
+@@ -44,3 +44,13 @@ config ARM_ETHER00
+         will generate a suitable hw address based on the board serial
+         number (MTD support is required for this). Otherwise you will
+         need to set a suitable hw address using ifconfig.
++
++config EP93XX_ETHERNET
++      tristate "EP93xx Ethernet support"
++      depends on NET_ETHERNET && ARM && ARCH_EP93XX
++      select CRC32
++      select MII
++      help
++        This is a driver for the ethernet hardware included in EP93xx CPUs.
++        Say Y if you are building a kernel for EP93xx based devices.
++
+diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
+index b0d7068..c1539da 100644
+--- a/drivers/net/arm/Makefile
++++ b/drivers/net/arm/Makefile
+@@ -8,3 +8,4 @@ obj-$(CONFIG_ARM_ETHER00)      += ether00.o
+ obj-$(CONFIG_ARM_ETHERH)      += etherh.o
+ obj-$(CONFIG_ARM_ETHER3)      += ether3.o
+ obj-$(CONFIG_ARM_ETHER1)      += ether1.o
++obj-$(CONFIG_EP93XX_ETHERNET) += ep93xx_eth.o
+diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
+new file mode 100644
+index 0000000..e314549
+--- /dev/null
++++ b/drivers/net/arm/ep93xx_eth.c
+@@ -0,0 +1,1412 @@
++/*
++ * ep93xx_eth.c
++ *  Ethernet Device Driver for Cirrus Logic EP93xx.
++ *
++ * Copyright (C) 2003 by Cirrus Logic www.cirrus.com
++ * This software may be used and distributed according to the terms
++ * of the GNU Public License.
++ *
++ *   This driver was written based on skeleton.c by Donald Becker and
++ * smc9194.c by Erik Stahlman.
++ *
++ * Getting a MAC address:
++ *
++ * Former versions of this driver got their MAC from I2C EEPROM or even used
++ * hardcoded ones. Unfortunately I had to remove the board dependant I2C stuff,
++ * and use a random generated MAC instead of the hardcoded one. Good news is
++ * the there is support for setting the MAC from userspace now. (see below)
++ *
++ * first consider some potential problems if you use this random generated MAC:
++ *
++ *    you can no longer count on it to be really unique
++ *    identifying a particular board over network will be difficult
++ *    DHCP servers can no longer use the MAC for assigning static IPs
++ *    DHCP servers with long leasetimes quickly run out of leases
++ *    ...
++ *
++ * So how can you set a valid MAC from userspace then?
++ *
++ * Let's say you've just bought your OUI from IEEE and it's "aa:bb:cc"
++ * Now you'd like to assign the MAC for your EP93xx board with serial #5
++ * MAC = OUI<<24 + serial number = aa:bb:cc:00:00:05
++ *
++ *   ifconfig eth0 hw ether aa:bb:cc:00:00:05            # first set the MAC
++ *   ifconfig eth0 192.168.1.1 netmask 255.255.255.0 up  # then set the IP
++ *
++ * Apart from hardcoding this lines in your startup scripts you could also use
++ * some userspace utility to read (and set) the MAC from eeprom, flash, ...
++ *
++ * History:
++ * 07/19/01 0.1  Sungwook Kim  initial release
++ * 10/16/01 0.2  Sungwook Kim  add workaround for ignorance of Tx request
++ *                              while sending frame
++ *                             add some error stuations handling
++ *
++ * 03/25/03 Melody Lee Modified for EP93xx
++ *
++ * 2004/2005  Michael Burian  porting to linux-2.6
++ * 2005-10-12 Michael Burian  fix problems when setting MAC with ifconfig
++ * 2005-10-30 Michael Burian  cleanups, ethtool support
++ */
++
++/* TODO: 
++ * 1. try if it's possible to use skbuff directly for RX/TX (avoid memcpy)
++ * 2. use kzalloc instead of kmalloc+memset
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/dma-mapping.h>
++#include <linux/mii.h>
++#include <linux/crc32.h>
++#include <linux/random.h>
++#include <linux/ethtool.h>
++
++#include <asm/system.h>
++#include <asm/bitops.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++#include <asm/irq.h>
++#include <asm/arch/hardware.h>
++
++#include "ep93xx_eth.h"
++
++#define DRV_NAME      "ep93xx_eth"
++#define DRV_VERSION   "2.8"
++#define DRV_DATE      "2005-11-08"
++
++static const char *version = DRV_NAME ": version " DRV_VERSION " " DRV_DATE \
++                                                      " Cirrus Logic\n";
++
++/* total number of device instance, 0 means the 1st instance. */
++static int num_of_instance;
++static struct net_device * ep93xx_etherdev;
++
++/*
++ * A List of default device port configuration for auto probing.
++ * At this time, the CPU has only one Ethernet device,
++ * but better to support multiple device configuration.
++ * Keep in mind that the array must end in zero.
++ */
++
++/* We get the MAC_BASE from include/asm-arm/arch-ep93xx/regmap.h */
++static struct {
++      unsigned int base_addr; /* base address, (0:end mark) */
++      int irq;                /* IRQ number, (0:auto detect) */
++} port_list[] __initdata = {
++      {
++      MAC_BASE, 39}, {
++      0 /* end mark */ , 0}
++};
++
++/*
++ * Some definitions belong to the operation of this driver.
++ * You should understand how it affect to driver before any modification.
++ */
++
++/* Interrupt Sources in Use */
++#define  DEF_INT_SRC  (IntEn_TxSQIE|IntEn_RxEOFIE|IntEn_RxEOBIE|IntEn_RxHDRIE)
++
++/*
++ * Length of Device Queue in number of entries
++ * (must be less than or equal to 255)
++ */
++
++/* length of Rx Descriptor Queue (4 or bigger) Must be power of 2. */
++#define  LQRXD  64
++#define  LQRXS   LQRXD                /* length of Rx Status Queue */
++
++/* length of Tx Descriptor Queue (4 or bigger) Must be power of 2. */
++#define  LQTXD  8
++#define  LQTXS   LQTXD                /* length of Tx Status Queue */
++
++/* Tx Queue fill-up level control */
++#define  LVL_TXSTOP    LQTXD - 2      /* level to ask the stack to stop Tx */
++#define  LVL_TXRESUME  2      /* level to ask the stack to resume Tx */
++
++/* Rx Buffer length in byte */
++#define  LRXB  (1518+2+16)    /* length of Rx buf, must be 4-byte aligned */
++#define  LTXB   LRXB
++
++#define EP93XX_DEF_MSG (NETIF_MSG_DRV         | \
++                      NETIF_MSG_PROBE         | \
++                      NETIF_MSG_LINK          | \
++                      NETIF_MSG_RX_ERR        | \
++                      NETIF_MSG_TX_ERR        | \
++                      NETIF_MSG_HW)
++
++#define DBG(lvl,msg,args...) do { printk(lvl"%s:%d: %s(): " msg, __FILE__, \
++              __LINE__,  __FUNCTION__, ## args); } while (0)
++
++/*
++ * Custom Data Structures
++ */
++
++/*
++ * the information about the buffer passed to device.
++ * there are matching bufdsc informations
++ * for each Tx/Rx Descriptor Queue entry to trace
++ * the buffer within those queues.
++ */
++struct bufdsc {
++      /* virtual address representing the buffer passed to device */
++      void *vaddr;
++      /* free routine */
++      int (*free_rout) (void *buf);
++};
++
++/* device private information */
++struct ep93xx_priv {
++      /*  static device information */
++      int id;                 /* device instance ID */
++      /* pointers to various queues (virtual address) */
++      struct rx_dsc *rdq;     /* Rx Descriptor Queue */
++      struct rx_sts *rsq;     /* Rx Status Queue */
++      struct tx_dsc *tdq;     /* Tx Descriptor Queue */
++      struct tx_sts *tsq;     /* Tx Status Queue */
++      unsigned char *rxbuf;   /* base of Rx Buffer pool */
++      unsigned char *txbuf;   /* base of Tx Buffer pool */
++      struct bufdsc *rxbd;    /* Rx Buffers info */
++      struct bufdsc *txbd;    /* Tx Buffers info */
++      /* physical addresses of the same queues */
++      dma_addr_t p_qbase;     /* base */
++      dma_addr_t p_rdq;       /* Rx Descriptor Queue */
++      dma_addr_t p_rsq;       /* Rx Status Queue */
++      dma_addr_t p_tdq;       /* Tx Descriptor Queue */
++      dma_addr_t p_tsq;       /* Tx Status Queue */
++      dma_addr_t p_rxbuf;     /* Rx Buffer pool */
++      dma_addr_t p_txbuf;     /* Tx Buffer pool */
++      /* MII Bus ID of Ethernet PHY */
++      struct mii_if_info mii;
++      /* lock for mii when using ioctls */
++      spinlock_t mii_lock;
++      /*  dynamic information, subject to clear when device open */
++      struct net_device_stats stats;  /* statistic data */
++      /* next processing index of device queues */
++      int idx_rdq;
++      int idx_rsq;
++      int idx_tdqhead;
++      int idx_tdqtail;
++      int idx_tsq;
++      void __iomem *base_addr;        /* base address */
++      u32 msg_enable;
++      int regs_len;
++};
++
++/*
++ * Internal Routines
++ */
++
++static inline unsigned int next_index(unsigned int idx_cur, unsigned int len)
++{
++      return (idx_cur + 1) % len;     /* next array index */
++}
++
++static inline u32 _rdl(struct net_device *dev, u32 reg)
++{
++      return readl(((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
++}
++
++static inline void _wrl(struct net_device *dev, u32 val, u32 reg)
++{
++      writel(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
++}
++
++static inline void _wrw(struct net_device *dev, u16 val, u32 reg)
++{
++      writew(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
++}
++
++static inline void _wrb(struct net_device *dev, u8 val, u32 reg)
++{
++      writeb(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
++}
++
++/**
++ * wait_on_reg()
++ */
++static int wait_on_reg(struct net_device *dev, int reg, unsigned long mask, unsigned long expect)
++{
++      int i, dt;
++
++      for (i = 0; i < 10000; i++) {
++              dt = _rdl(dev, reg);
++              dt = (dt ^ expect) & mask;
++              if (0 == dt)
++                      break;
++      }
++      return dt;
++}
++
++/**
++ * mdio_write()
++ */
++static void mdio_write(struct net_device *dev, int idPhy, int reg, int dt)
++{
++      wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy);
++      _wrl(dev, dt, REG_MIIData);
++      _wrl(dev, MIICmd_OP_WR | ((idPhy & 0x1f) << 5) | ((reg & 0x1f) << 0), REG_MIICmd);
++}
++
++/**
++ * mdio_read()
++ */
++static int mdio_read(struct net_device *dev, int idPhy, int reg)
++{
++      int dt;
++
++      wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy);
++      _wrl(dev, MIICmd_OP_RD | ((idPhy & 0x1f) << 5) | ((reg & 0x1f) << 0), REG_MIICmd);
++
++      wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy);
++      dt = _rdl(dev, REG_MIIData);
++
++      return dt & 0xffff;
++}
++
++/**
++ * phy_init()
++ */
++static void phy_init(struct net_device *dev)
++{
++
++      u32 oldval;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      oldval = _rdl(dev, REG_SelfCTL);
++
++      /* Set MDC clock to be divided by 8 and disable PreambleSuppress bit */
++      _wrl(dev, 0x0e00, REG_SelfCTL);
++
++      if (mii_link_ok(&(priv->mii)))
++              mii_check_media(&(priv->mii), netif_msg_link(priv), 1);
++
++      /* restore the old value */
++      _wrl(dev, oldval, REG_SelfCTL);
++}
++
++/**
++ * devQue_start()
++ *
++ * make descriptor queues active
++ * allocate queue entries if needed
++ * and set device registers up to make it operational
++ * assume device has been initialized
++ */
++static int devQue_start(struct net_device *dev)
++{
++      int err;
++      int i;
++      void *buf;
++      u32 phy_addr;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      /* turn off device bus mastering */
++      _wrl(dev, BMCtl_RxDis | BMCtl_TxDis | _rdl(dev, REG_BMCtl), REG_BMCtl);
++      err = wait_on_reg(dev, REG_BMSts, BMSts_TxAct, ~BMSts_TxAct);
++      err |= wait_on_reg(dev, REG_BMSts, BMSts_RxAct, ~BMSts_RxAct);
++      if (err && netif_msg_hw(priv))
++              DBG(KERN_ERR, "%s: BM does not stop\n", dev->name);
++
++      /* Tx Status Queue */
++      memset(priv->tsq, 0, sizeof(priv->tsq[0]) * LQTXS);
++      priv->idx_tsq = 0;
++      _wrl(dev, priv->p_tsq, REG_TxSBA);
++      _wrl(dev, priv->p_tsq, REG_TxSCA);
++      _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSBL);
++      _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSCL);
++
++      /* Tx Descriptor Queue */
++      memset(priv->tdq, 0, sizeof(priv->tdq[0]) * LQTXD);
++      priv->idx_tdqhead = priv->idx_tdqtail = 0;
++      _wrl(dev, priv->p_tdq, REG_TxDBA);
++      _wrl(dev, priv->p_tdq, REG_TxDCA);
++      _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDBL);
++      _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDCL);
++
++      /* Rx Status Queue */
++      memset(priv->rsq, 0, sizeof(priv->rsq[0]) * LQRXS);
++      priv->idx_rsq = 0;
++      _wrl(dev, priv->p_rsq, REG_RxSBA);
++      _wrl(dev, priv->p_rsq, REG_RxSCA);
++      _wrw(dev, sizeof(priv->rsq[0]) * LQRXS, REG_RxSBL);
++      _wrw(dev, sizeof(priv->rsq[0]) * LQRXS, REG_RxSCL);
++
++      /* Rx Descriptor Queue */
++      memset(priv->rdq, 0, sizeof(priv->rdq[0]) * LQRXD);
++      phy_addr = priv->p_rxbuf;
++      for (i = 0; i < LQRXD; i++) {
++              priv->rdq[i].bi = i;    /* index */
++              priv->rdq[i].ba = phy_addr;     /* physical address */
++              priv->rdq[i].bl = LRXB; /* length */
++              phy_addr += LRXB;
++      }
++      priv->idx_rdq = 0;
++      _wrl(dev, priv->p_rdq, REG_RxDBA);
++      _wrl(dev, priv->p_rdq, REG_RxDCA);
++      _wrw(dev, sizeof(priv->rdq[0]) * LQRXD, REG_RxDBL);
++      _wrw(dev, sizeof(priv->rdq[0]) * LQRXD, REG_RxDCL);
++
++      /* init Rx Buffer Descriptors */
++      buf = priv->rxbuf;
++      for (i = 0; i < LQRXD; i++) {
++              priv->rxbd[i].vaddr = buf;
++              priv->rxbd[i].free_rout = NULL;
++              buf += LRXB;
++      }
++
++      /* init Tx Buffer Descriptors */
++      memset(priv->txbd, 0x0, sizeof(*priv->txbd) * LQTXD);
++
++      buf = priv->txbuf;
++      for (i = 0; i < LQTXD; i++) {
++              priv->txbd[i].vaddr = buf;
++              priv->txbd[i].free_rout = NULL;
++              buf += LTXB;
++      }
++
++      /* turn on device bus mastering */
++      _wrl(dev, BMCtl_TxEn | BMCtl_RxEn | _rdl(dev, REG_BMCtl), REG_BMCtl);
++      err = wait_on_reg(dev, REG_BMSts, BMSts_TxAct | BMSts_TxAct, BMSts_TxAct | BMSts_TxAct);
++      if (err && netif_msg_hw(priv))
++              DBG(KERN_ERR, "%s: BM does not start\n", dev->name);
++
++      /* Enqueue whole entries; this must be done after BM activation */
++      _wrl(dev, LQRXS, REG_RxSEQ);    /* Rx Status Queue */
++      _wrl(dev, LQRXD, REG_RxDEQ);    /* Rx Desc. queue */
++
++      return 0;
++}
++
++/**
++ * devQue_init()
++ * init device descriptor queues at system level
++ *  device access is not recommended at this point
++ *
++ */
++static int devQue_init(struct net_device *dev)
++{
++      void *buf;
++      void *tmp;
++      int size, size2;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      /* verify device Tx/Rx Descriptor/Status Queue data size */
++      if (8 != sizeof(struct rx_dsc)) {
++              if (netif_msg_probe(priv))
++                      DBG(KERN_ERR, "sizeof rx_dsc != 8 bytes!\n");
++              return -ENOMEM;
++      } else if (8 != sizeof(struct rx_sts)) {
++              if (netif_msg_probe(priv))
++                      DBG(KERN_ERR, "sizeof rx_sts != 8 bytes!\n");
++              return -ENOMEM;
++      } else if (8 != sizeof(struct tx_dsc)) {
++              if (netif_msg_probe(priv))
++                      DBG(KERN_ERR, "sizeof tx_dsc != 8 bytes!\n");
++              return -ENOMEM;
++      } else if (4 != sizeof(struct tx_sts)) {
++              if (netif_msg_probe(priv))
++                      DBG(KERN_ERR, "sizeof tx_sts != 4 bytes!\n");
++              return -ENOMEM;
++      }
++
++      /*
++         allocate kernel memory for whole queues
++         best if non-cached memory block due to DMA access by the device
++         if CPU doesn't have bus snooping
++       */
++      size = sizeof(struct rx_dsc) * (LQRXD + 1) +
++          sizeof(struct rx_sts) * (LQRXS + 1) +
++          sizeof(struct tx_dsc) * (LQTXD + 1) +
++          sizeof(struct tx_sts) * (LQTXS + 1) + sizeof(unsigned long) * 4;
++
++      buf = tmp = dma_alloc_coherent(NULL, size, &priv->p_qbase, GFP_KERNEL | GFP_DMA);
++      if (!buf) {
++              if (netif_msg_probe(priv))
++                      DBG(KERN_ERR, "no memory for queue\n");
++              return -ENOMEM;
++      }
++
++      /*
++       * assign memory to each queue
++       */
++      priv->rdq = buf;
++      buf = buf + sizeof(struct rx_dsc) * (LQRXD + 1);
++      priv->rsq = buf;
++      buf = buf + sizeof(struct rx_sts) * (LQRXS + 1);
++      priv->tdq = buf;
++      buf = buf + sizeof(struct tx_dsc) * (LQTXD + 1);
++      priv->tsq = buf;
++      buf = buf + sizeof(struct tx_sts) * (LQTXS + 1);
++
++      /*
++       * store physical address of each queue
++       */
++      priv->p_rdq = priv->p_qbase;
++      priv->p_rsq = priv->p_rdq + ((u32) priv->rsq - (u32) priv->rdq);
++      priv->p_tdq = priv->p_rdq + ((u32) priv->tdq - (u32) priv->rdq);
++      priv->p_tsq = priv->p_rdq + ((u32) priv->tsq - (u32) priv->rdq);
++
++      /*
++       *  init queue entries
++       */
++      memset(priv->rdq, 0, sizeof(struct rx_dsc) * LQRXD);
++      memset(priv->rsq, 0, sizeof(struct rx_sts) * LQRXS);
++      memset(priv->tdq, 0, sizeof(struct tx_dsc) * LQTXD);
++      memset(priv->tsq, 0, sizeof(struct tx_sts) * LQTXS);
++
++      /* Allocate Rx Buffer
++         (We might need to copy from Rx buf to skbuff in whatever case,
++         because device bus master requires 32bit aligned Rx buffer address
++         but Linux network stack requires odd 16bit aligned Rx buf address) */
++      priv->rxbuf = dma_alloc_coherent(NULL, LRXB * LQRXD, &priv->p_rxbuf, GFP_KERNEL | GFP_DMA);
++
++      if (!priv->rxbuf) {
++              priv->rxbuf = NULL;
++              if (netif_msg_probe(priv))
++                      DBG(KERN_ERR, "no memory for RxBuf\n");
++              goto err_free_qbase_1;
++      }
++
++      /* Allocate Tx Buffer */
++      priv->txbuf = dma_alloc_coherent(NULL, LTXB * LQTXD, &priv->p_txbuf, GFP_KERNEL | GFP_DMA);
++
++      if (!priv->txbuf) {
++              priv->txbuf = NULL;
++              if (netif_msg_probe(priv))
++                      DBG(KERN_ERR, "no memory for TxBuf\n");
++              goto err_free_rxbuf_2;
++      }
++
++      /*
++       * allocate kernel memory for buffer descriptors
++       */
++      size2 = sizeof(struct bufdsc) * (LQRXD + LQTXD);
++      buf = kmalloc(size2, GFP_KERNEL);
++      if (!buf) {
++              if (netif_msg_probe(priv))
++                      DBG(KERN_ERR, "no memory for buf desc\n");
++              goto err_free_txbuf_3;
++      }
++      memset(buf, 0x0, size2);        /* clear with 0 */
++      priv->rxbd = buf;
++      priv->txbd = buf + sizeof(struct bufdsc) * LQRXD;
++
++      return 0;
++
++err_free_txbuf_3:
++      dma_free_coherent(NULL, LTXB * LQTXD, priv->txbuf, priv->p_txbuf);
++err_free_rxbuf_2:
++      dma_free_coherent(NULL, LRXB * LQRXD, priv->rxbuf, priv->p_rxbuf);
++err_free_qbase_1:
++      dma_free_coherent(NULL, size, tmp, priv->p_qbase);
++      return -ENOMEM;
++}
++
++/**
++ * devQue_cleanup()
++ * Release queue, Tx buffers and Rx buffers memory
++ * Only call after unregister_netdev
++ */
++static void devQue_cleanup(struct net_device *dev)
++{
++      int size;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      /* descriptor queues size */
++      size = sizeof(struct rx_dsc) * (LQRXD + 1) +
++          sizeof(struct rx_sts) * (LQRXS + 1) +
++          sizeof(struct tx_dsc) * (LQTXD + 1) +
++          sizeof(struct tx_sts) * (LQTXS + 1) + sizeof(unsigned long) * 4;
++
++      dma_free_coherent(NULL, size, priv->rdq, priv->p_qbase);
++      dma_free_coherent(NULL, LTXB * LQTXD, priv->txbuf, priv->p_txbuf);
++      dma_free_coherent(NULL, LRXB * LQRXD, priv->rxbuf, priv->p_rxbuf);
++      kfree(priv->rxbd);
++
++}
++
++/**
++ * set_multicast_tbl()
++ */
++static void set_multicast_tbl(struct net_device *dev, u8 *buf)
++{
++      int i;
++      unsigned char position;
++      struct dev_mc_list *cur_addr;
++
++      memset(buf, 0x00, 8);
++
++      cur_addr = dev->mc_list;
++      for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) {
++
++              if (!cur_addr)
++                      break;
++              if (!(*cur_addr->dmi_addr & 1))
++                      continue;       /* make sure multicast addr */
++              position = ether_crc_le(6, cur_addr->dmi_addr) >> 26;
++              buf[position >> 3] |= 1 << (position & 0x07);
++      }
++}
++
++/**
++ * ind_addr_wr()
++ */
++static int ind_addr_wr(struct net_device *dev, int afp, char *buf)
++{
++      u32 rxctl;
++      int i, len;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      afp &= 0x07;
++      if (4 == afp || 5 == afp) {
++              if (netif_msg_hw(priv))
++                      DBG(KERN_ERR, "invalid afp value\n");
++              return -1;
++      }
++      len = (AFP_AFP_HASH == afp) ? 8 : 6;
++
++      rxctl = _rdl(dev, REG_RxCTL);   /* turn Rx off */
++      _wrl(dev, ~RxCTL_SRxON & rxctl, REG_RxCTL);
++      _wrl(dev, afp, REG_AFP);        /* load new address pattern */
++      for (i = 0; i < len; i++)
++              _wrb(dev, buf[i], REG_IndAD + i);
++      _wrl(dev, rxctl, REG_RxCTL);    /* turn Rx back */
++
++      return 0;
++}
++
++/**
++ * rx_ctl()
++ */
++static int rx_ctl(struct net_device *dev, int sw)
++{
++      unsigned long tmp = _rdl(dev, REG_RxCTL);
++
++      /*
++       * Workaround for MAC lost 60-byte-long frames:
++       * must enable Runt_CRC_Accept bit
++       */
++      if (sw)
++              _wrl(dev, tmp | RxCTL_SRxON | RxCTL_RCRCA, REG_RxCTL);
++      else
++              _wrl(dev, tmp & ~RxCTL_SRxON, REG_RxCTL);
++
++      return 0;
++}
++
++/**
++ * chk_tx_lvl()
++ */
++static void chk_tx_lvl(struct net_device *dev)
++{
++      int filled;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      /* check Tx Descriptor Queue fill-up level */
++      filled = priv->idx_tdqhead - priv->idx_tdqtail;
++      if (filled < 0)
++              filled += LQTXD;
++
++      if (filled <= (LVL_TXRESUME + 1))
++              netif_wake_queue(dev);
++}
++
++/**
++ * cleanup_tx()
++ */
++static void cleanup_tx(struct net_device *dev)
++{
++      struct tx_sts *txsts;
++      int idxsts, bi;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      /*
++       * process Tx Status Queue (no need to limit processing of TxStatus
++       * Queue because each queue entry consist of 1 dword)
++       */
++      while (priv->tsq[priv->idx_tsq].flags & TXSTS_TXFP) {
++              idxsts = priv->idx_tsq;
++              priv->idx_tsq = next_index(priv->idx_tsq, LQTXS);
++              txsts = &priv->tsq[idxsts];
++              if (!(txsts->flags & TXSTS_TXFP)) {     /* empty? */
++                      if (netif_msg_tx_err(priv))
++                              DBG(KERN_ERR, "QueTxSts is empty\n");
++                      return;
++              }
++              txsts->flags &= ~TXSTS_TXFP;    /* mark processed */
++
++              bi = txsts->bi & TXSTS_BI;      /* buffer index */
++
++              /* statistics collection */
++              if (txsts->flags & TXSTS_TXWE) {        /* Sent without error */
++                      priv->stats.tx_packets++;
++                      priv->stats.tx_bytes += ((struct tx_dsc *)(priv->txbd[bi].vaddr))->bl_af & TXDSC_BL;
++              } else {        /* Tx failed due to error */
++                      if (netif_msg_tx_err(priv))
++                              DBG(KERN_ERR, "Tx failed QueTxSts");
++                      priv->stats.tx_errors++;
++                      if (txsts->flags & TXSTS_LCRS)
++                              priv->stats.tx_carrier_errors++;
++                      if (txsts->flags & TXSTS_TXU)
++                              priv->stats.tx_fifo_errors++;
++                      if (txsts->flags & TXSTS_ECOLL)
++                              priv->stats.collisions++;
++              }
++
++              /* free Tx buffer */
++              if (priv->txbd[bi].free_rout) {
++                      (*priv->txbd[bi].free_rout)(priv->txbd[bi].vaddr);
++                      priv->txbd[bi].free_rout = NULL;
++              }
++
++              /* ahead Tx Descriptor Queue tail index */
++              priv->idx_tdqtail = next_index(priv->idx_tdqtail, LQTXD);
++      }
++}
++
++/**
++ * restart_tx()
++ */
++static int restart_tx(struct net_device *dev)
++{
++      int i;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      /* disable int */
++
++      /* turn off master INT control */
++      _wrl(dev, _rdl(dev, REG_GIntMsk) & ~GIntMsk_IntEn, REG_GIntMsk);
++
++      /* stop Tx and disable Tx DMA */
++      _wrl(dev, _rdl(dev, REG_TxCTL) & ~TxCTL_STxON, REG_TxCTL);
++      _wrl(dev, _rdl(dev, REG_BMCtl) | BMCtl_TxDis, REG_BMCtl);
++
++      /* reset Tx DMA */
++      _wrl(dev, BMCtl_TxChR | _rdl(dev, REG_BMCtl), REG_BMCtl);
++
++      /* release Tx buffers */
++      for (i = 0; i < LQTXD; i++) {
++              if (priv->txbd[i].free_rout) {
++                      priv->txbd[i].free_rout(priv->txbd[i].vaddr);
++                      priv->txbd[i].free_rout = NULL;
++              }
++              priv->stats.tx_dropped++;
++      }
++
++      /* init Tx Queues and flush cache */
++      memset(priv->tsq, 0, sizeof(priv->tsq[0]) * LQTXS);
++
++      /* init variables */
++      priv->idx_tsq = priv->idx_tdqhead = priv->idx_tdqtail = 0;
++
++      /* init registers */
++      wait_on_reg(dev, REG_BMSts, BMCtl_TxChR, ~BMCtl_TxChR);
++      _wrl(dev, priv->p_tsq, REG_TxSBA);
++      _wrl(dev, priv->p_tsq, REG_TxSCA);
++      _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSBL);
++      _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSCL);
++      _wrl(dev, priv->p_tdq, REG_TxDBA);
++      _wrl(dev, priv->p_tdq, REG_TxDCA);
++      _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDBL);
++      _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDCL);
++
++      /* start Tx and enable Tx DMA */
++      _wrl(dev, _rdl(dev, REG_TxCTL) | TxCTL_STxON, REG_TxCTL);
++      _wrl(dev, _rdl(dev, REG_BMCtl) | BMCtl_TxEn, REG_BMCtl);
++
++      /* enable int again */
++      _wrl(dev, _rdl(dev, REG_GIntMsk) | GIntMsk_IntEn, REG_GIntMsk);
++
++      return 0;
++}
++
++/**
++ * reset()
++ */
++static void reset(struct net_device *dev)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      /* soft reset command */
++      _wrb(dev, SelfCTL_RESET, REG_SelfCTL);
++      if (wait_on_reg(dev, REG_SelfCTL, SelfCTL_RESET, ~SelfCTL_RESET))
++              if (netif_msg_drv(priv))
++                      DBG(KERN_WARNING, "Soft Reset does not self-clear\n");
++}
++
++/**
++ * eth_shutdown()- closes down the Ethernet module
++ *
++ * Make sure to:
++ *    1. disable all interrupt mask
++ *    2. disable Rx
++ *    3. disable Tx
++ *
++ *    TODO:
++ *   (1) maybe utilize power down mode.
++ *    Why not yet?  Because while the chip will go into power down mode,
++ *    the manual says that it will wake up in response to any I/O requests
++ *    in the register space.   Empirical results do not show this working.
++ */
++static int eth_shutdown(struct net_device *dev)
++{
++      reset(dev);
++      return 0;
++}
++
++/**
++ * eth_init() - Reset and initialize the device.
++ *
++ * Device should be initialized enough to function in polling mode.
++ * Tx and Rx must be disabled and no INT generation.
++ */
++static int eth_init(struct net_device *dev)
++{
++      /* reset device */
++      reset(dev);
++
++      /* init PHY */
++      phy_init(dev);
++
++      /* init MAC */
++
++      /*i Set MDC clock to be divided by 8 and enable PreambleSuppress bit */
++      _wrl(dev, 0x0f00, REG_SelfCTL);
++      /* mask Interrupt */
++      _wrl(dev, 0x00, REG_GIntMsk);
++      /* no Rx on at this point */
++      _wrl(dev, RxCTL_BA | RxCTL_IA0, REG_RxCTL);
++      _wrl(dev, 0x00, REG_TxCTL);
++      _wrl(dev, 0x00, REG_GT);
++      _wrl(dev, 0x00, REG_BMCtl);
++      /* Buffer Threshold */
++      _wrl(dev, (0x80 << 16) | (0x40 << 0), REG_RxBTH);
++      _wrl(dev, (0x80 << 16) | (0x40 << 0), REG_TxBTH);
++      /* Status Threshold */
++      _wrl(dev, (4 << 16) | (2 << 0), REG_RxSTH);
++      _wrl(dev, (4 << 16) | (2 << 0), REG_TxSTH);
++      /* Descriptor Threshold */
++      _wrl(dev, (4 << 16) | (2 << 0), REG_RxDTH);
++      _wrl(dev, (4 << 16) | (2 << 0), REG_TxDTH);
++      /* Max Frame Length & Tx Start Threshold */
++      _wrl(dev, ((1518 + 1) << 16) | (944 << 0), REG_MaxFL);
++
++      _rdl(dev, REG_TxCollCnt);       /* clear Tx Collision Count */
++      _rdl(dev, REG_RxMissCnt);       /* clear Rx Miss Counter */
++      _rdl(dev, REG_RxRntCnt);        /* clear Rx Runt Counter */
++
++      /* clear Pending INT */
++      _rdl(dev, REG_IntStsC);
++      /* Tx on */
++      _wrl(dev, TxCTL_STxON | _rdl(dev, REG_TxCTL), REG_TxCTL);
++
++      /* Set MAC address */
++      ind_addr_wr(dev, AFP_AFP_IA0, &dev->dev_addr[0]);
++
++      /* init queue */
++      devQue_start(dev);
++
++      return 0;
++}
++
++/**
++ * rx_isr() - Receive Interrupt Service Routine
++ */
++static void rx_isr(struct net_device *dev)
++{
++      struct rx_sts *rxsts;
++      /* index of Rx Status Queue Head from device (next put point) */
++      int idx_rsqhead;
++      int idxsts;
++      int cnt_sts_processed, cnt_desc_processed;
++      char *dest;
++      struct sk_buff *skb;
++      int len;
++      unsigned int dt;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      /* get Current Rx Status Queue pointer */
++      dt = _rdl(dev, REG_RxSCA);
++
++      /* convert to array index */
++      idx_rsqhead = (dt - priv->p_rsq) / sizeof(priv->rsq[0]);
++      if (!(0 <= idx_rsqhead && idx_rsqhead < LQRXS)) {
++              if (netif_msg_rx_err(priv))
++                      DBG(KERN_ERR, " invalid REG_RxSCA\n");
++              return;
++      }
++
++      /* process Rx (limit to idx_rsqhead due to cache) */
++      cnt_sts_processed = cnt_desc_processed = 0;
++      while (idx_rsqhead != priv->idx_rsq) {
++              idxsts = priv->idx_rsq;
++              priv->idx_rsq = next_index(priv->idx_rsq, LQRXS);
++              rxsts = &priv->rsq[idxsts];
++              if (!(rxsts->w1 & RXSTS_RFP)) { /* empty? */
++                      if (netif_msg_rx_err(priv))
++                              DBG(KERN_ERR, "QueRxSts empty\n");
++                      return;
++              }
++              rxsts->w1 &= ~RXSTS_RFP;        /* mark processed */
++
++              cnt_sts_processed++;
++
++              if (!(rxsts->w1 & RXSTS_EOB))   /* buffer has no data */
++                      continue;
++
++              if ((rxsts->bi & RXSTS_BI) != priv->idx_rdq) {
++                      if (netif_msg_rx_err(priv))
++                              DBG(KERN_ERR, "unmatching idx_rdq\n");
++                      continue;
++              }
++              priv->idx_rdq = next_index(priv->idx_rdq, LQRXD);
++              cnt_desc_processed++;
++
++              /* received a frame with error */
++              if (!((rxsts->w1 & RXSTS_EOF) && (rxsts->w1 & RXSTS_RWE))) {
++                      if (netif_msg_rx_err(priv))
++                              DBG(KERN_WARNING, "Rx error RxSts\n");
++                      priv->stats.rx_errors++;
++                      if (rxsts->w1 & RXSTS_OE)
++                              priv->stats.rx_fifo_errors++;
++                      if (rxsts->w1 & RXSTS_FE)
++                              priv->stats.rx_frame_errors++;
++                      if ((rxsts->w1 & RXSTS_RUNT) || (rxsts->w1 & RXSTS_EDATA))
++                              priv->stats.rx_length_errors++;
++                      if (rxsts->w1 & RXSTS_CRCE)
++                              priv->stats.rx_crc_errors++;
++                      continue;
++              }
++
++              len = rxsts->fl;
++
++              /* alloc buffer for protocal stack */
++              skb = dev_alloc_skb(len + 5);
++              if (NULL == skb) {
++                      if (netif_msg_rx_err(priv))
++                              DBG(KERN_ERR, "Low Memory, Rx dropped\n");
++                      priv->stats.rx_dropped++;
++                      continue;
++              }
++
++              /* odd 16 bit alignment to make protocal stack happy */
++              skb_reserve(skb, 2);
++              skb->dev = dev;
++              dest = skb_put(skb, len);
++              memcpy(dest, priv->rxbd[(rxsts->bi & RXSTS_BI)].vaddr, len);
++              skb->protocol = eth_type_trans(skb, dev);
++              /* pass Rx packet to system */
++              netif_rx(skb);
++              dev->last_rx = jiffies;
++              priv->stats.rx_packets++;
++              priv->stats.rx_bytes += len;
++              if (RXSTS_AM == (rxsts->w1 & RXSTS_AM))
++                      priv->stats.multicast++;
++      }
++
++      /* enqueue */
++      _wrl(dev, cnt_sts_processed, REG_RxSEQ);
++      _wrl(dev, cnt_desc_processed, REG_RxDEQ);
++}
++
++/**
++ * tx_isr() - Transmit Interrupt Service Routine
++ */
++static int tx_isr(struct net_device *dev)
++{
++      cleanup_tx(dev);
++      chk_tx_lvl(dev);        /* resume Tx if it was stopped */
++      return 0;
++}
++
++/**
++ * ep93xx_isr()
++ */
++static irqreturn_t ep93xx_isr(int irq, void *dev_id, struct pt_regs *pRegs)
++{
++      struct net_device *dev = dev_id;
++      int lpCnt;
++      u32 intS;
++
++      lpCnt = 0;
++      do {
++              /* get INT status and then clear */
++              intS = _rdl(dev, REG_IntStsC);
++
++              if (!intS)
++                      break;  /* no INT */
++              if (IntSts_RxSQ & intS)
++                      rx_isr(dev);    /* Rx INT */
++              if (IntSts_TxSQ & intS)
++                      tx_isr(dev);    /* Tx INT */
++      } while (lpCnt++ < 64); /* limit loop to serve other interrupts too */
++      return IRQ_HANDLED;
++}
++
++/* Exposed Driver Routines to the Outside World */
++
++/**
++ * ep93xx_get_stats()
++ */
++static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      return &priv->stats;
++}
++
++/**
++ * ep93xx_set_multicast_list()
++ */
++static void ep93xx_set_multicast_list(struct net_device *dev)
++{
++      u8 tbl[8 + 1];
++
++      if (IFF_PROMISC & dev->flags) {
++              _wrl(dev, RxCTL_PA | _rdl(dev, REG_RxCTL), REG_RxCTL);
++
++      } else if (IFF_ALLMULTI & dev->flags) { /* receive all multicast addr */
++              _wrl(dev, RxCTL_MA | (~RxCTL_PA & _rdl(dev, REG_RxCTL)), REG_RxCTL);
++              memset(tbl, 0xff, 8);
++              ind_addr_wr(dev, AFP_AFP_HASH, &tbl[0]);
++
++      } else if (dev->mc_count) {     /* set H/W multicasting filter */
++              _wrl(dev, RxCTL_MA | (~RxCTL_PA & _rdl(dev, REG_RxCTL)), REG_RxCTL);
++              set_multicast_tbl(dev, &tbl[0]);
++              ind_addr_wr(dev, AFP_AFP_HASH, &tbl[0]);
++
++      } else {                /* no multicasting */
++              _wrl(dev, ~(RxCTL_PA | RxCTL_MA) & _rdl(dev, REG_RxCTL), REG_RxCTL);
++      }
++}
++
++/**
++ * ep93xx_tx_timeout()
++ */
++static void ep93xx_tx_timeout(struct net_device *dev)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      /* If we get here, some higher level has decided we are broken.
++         There should really be a "kick me" function call instead. */
++      if (netif_msg_tx_err(priv))
++              DBG(KERN_WARNING, "transmit timed out\n");
++
++      phy_init(dev);
++
++      /* kick Tx engine */
++      restart_tx(dev);
++
++      /* ask the Network Stack to resume Tx if there is room available */
++      chk_tx_lvl(dev);
++}
++
++/**
++ * ep93xx_start_xmit()
++ */
++static int ep93xx_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++/* @swk check H/W defect of Tx Underrun Error caused by certain frame length */
++      struct tx_dsc *txdsc;
++      int idx_tdqhd;
++      int filled;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      idx_tdqhd = priv->idx_tdqhead;
++      txdsc = &priv->tdq[idx_tdqhd];
++
++      /* check Tx Descriptor Queue fill-up level */
++      filled = idx_tdqhd - priv->idx_tdqtail;
++      if (filled < 0)
++              filled += LQTXD;
++      filled += 1;
++
++      /* check Queue level */
++      if (LVL_TXSTOP <= filled) {
++              netif_stop_queue(dev);  /* no more Tx allowed */
++              if (netif_msg_tx_err(priv))
++                      DBG(KERN_INFO, "%s: Tx STOP requested\n", dev->name);
++              if (LVL_TXSTOP < filled) {
++                      /* this situation can not be happen */
++                      if (netif_msg_tx_err(priv))
++                              DBG(KERN_ERR, "%s: Tx Request while stopped\n", dev->name);
++                      return NETDEV_TX_BUSY;
++              }
++      }
++
++      /* fill up Tx Descriptor Queue entry */
++      if (skb->len < ETH_ZLEN) {
++              txdsc->bl_af = ETH_ZLEN & TXDSC_BL;     /* also clears AF! */
++              skb = skb_padto(skb, ETH_ZLEN);
++              if (skb == NULL)
++                      return NETDEV_TX_OK;
++      } else {
++              txdsc->bl_af = skb->len & TXDSC_BL;     /* also clears AF! */
++      }
++      txdsc->ba = priv->p_txbuf + (idx_tdqhd * LTXB);
++      txdsc->bi_eof = (idx_tdqhd & TXDSC_BI) | TXDSC_EOF;
++
++      dev->trans_start = jiffies;
++
++      /* copy data to Tx buffer */
++      memcpy(priv->txbd[idx_tdqhd].vaddr, skb->data, skb->len);
++      priv->txbd[idx_tdqhd].free_rout = NULL;
++
++      /* Free the data buffer passed by upper layer */
++      dev_kfree_skb_any(skb);
++
++      /* ahead Tx Desc Queue */
++      priv->idx_tdqhead = next_index(priv->idx_tdqhead, LQTXD);
++      wmb();
++
++      /* Enqueue a Tx Descriptor to the device */
++      _wrl(dev, 1, REG_TxDEQ);
++
++      if (netif_msg_tx_queued(priv))
++              DBG(KERN_DEBUG, "%s: Tx packet queued\n", dev->name);
++
++      return NETDEV_TX_OK;
++}
++
++/**
++ * ep93xx_close()
++ *
++ * this makes the board clean up everything that it can
++ * and not talk to the outside world.   Caused by
++ *. an 'ifconfig ethX down'
++ */
++static int ep93xx_close(struct net_device *dev)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      free_irq(dev->irq, dev);
++
++      netif_stop_queue(dev);
++      eth_shutdown(dev);
++
++      if (netif_msg_ifdown(priv))
++              DBG(KERN_INFO, "%s: ep93xx_close()\n", dev->name);
++
++      return 0;
++}
++
++/**
++ * ep93xx_open() - Open and Initialize the board
++ *
++ * Set up everything, reset the card, etc ..
++ */
++static int ep93xx_open(struct net_device *dev)
++{
++      int status;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      /* clear dynamic device info */
++      memset(&priv->stats, 0, sizeof(priv->stats));
++      priv->idx_rdq = 0;
++      priv->idx_rsq = 0;
++      priv->idx_tdqhead = 0;
++      priv->idx_tdqtail = 0;
++      priv->idx_tsq = 0;
++
++      /* reset/init device */
++      status = eth_init(dev);
++      if (status != 0) {
++              return -EAGAIN;
++      }
++
++      /* turn on INT, turn on Rx */
++      status = request_irq(dev->irq, &ep93xx_isr, 0, DRV_NAME, dev);
++      if (status) {
++              if (netif_msg_ifup(priv))
++                      DBG(KERN_ERR, "%s: unable to get IRQ\n", dev->name);
++              return status;
++      }
++
++      /* Enable interrupt driven operation. Also turn on Rx but no Tx. */
++      /* setup Interrupt sources */
++      _wrl(dev, DEF_INT_SRC, REG_IntEn);
++      /* turn on INT */
++      _wrl(dev, GIntMsk_IntEn, REG_GIntMsk);
++      /* turn on Rx */
++      rx_ctl(dev, 1);
++
++      /* link to upper layer */
++      netif_start_queue(dev);
++
++      if (netif_msg_ifup(priv))
++              DBG(KERN_INFO, "%s: irq=%d\n", dev->name, dev->irq);
++
++      return 0;
++}
++
++static int ep93xx_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      int rc;
++
++      if (!netif_running(dev))
++              return -EINVAL;
++
++      spin_lock_irq(&priv->mii_lock);
++      rc = generic_mii_ioctl(&priv->mii, if_mii(rq), cmd, NULL);
++      spin_unlock_irq(&priv->mii_lock);
++
++      return rc;
++}
++
++/*
++ * Ethtool support
++ */
++
++static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
++{
++      strcpy(info->driver, DRV_NAME);
++      strcpy(info->version, DRV_VERSION);
++}
++
++static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      spin_lock_irq(&priv->mii_lock);
++      mii_ethtool_gset(&priv->mii, cmd);
++      spin_unlock_irq(&priv->mii_lock);
++      return 0;
++}
++
++static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      int rc;
++      spin_lock_irq(&priv->mii_lock);
++      rc = mii_ethtool_sset(&priv->mii, cmd);
++      spin_unlock_irq(&priv->mii_lock);
++      return rc;
++}
++
++static int ep93xx_nway_reset(struct net_device *dev)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      return mii_nway_restart(&priv->mii);
++}
++
++static u32 ep93xx_get_link(struct net_device *dev)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      return mii_link_ok(&priv->mii);
++}
++
++static u32 ep93xx_get_msglevel(struct net_device *dev)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      return priv->msg_enable;
++}
++
++static void ep93xx_set_msglevel(struct net_device *dev, u32 datum)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      priv->msg_enable = datum;
++}
++
++static void ep93xx_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      spin_lock_irq(&priv->mii_lock);
++      memcpy_fromio(regbuf, priv->base_addr, regs->len);
++      spin_unlock_irq(&priv->mii_lock);
++}
++
++static int ep93xx_get_regs_len(struct net_device *dev)
++{
++      struct ep93xx_priv *priv = netdev_priv(dev);
++      return priv->regs_len;
++}
++
++static struct ethtool_ops ep93xx_ethtool_ops = {
++      .get_drvinfo            = ep93xx_get_drvinfo,
++      .get_settings           = ep93xx_get_settings,
++      .set_settings           = ep93xx_set_settings,
++      .get_regs               = ep93xx_get_regs,
++      .get_regs_len           = ep93xx_get_regs_len,
++      .nway_reset             = ep93xx_nway_reset,
++      .get_link               = ep93xx_get_link,
++      .get_msglevel           = ep93xx_get_msglevel,
++      .set_msglevel           = ep93xx_set_msglevel,
++};
++
++/**
++ *  driver_init() - Logical driver initialization for an individual device
++ *
++ *      Minimum device H/W access at this point
++ *
++ *  Task:
++ *        Initialize the structure if needed
++ *        print out my vanity message if not done so already
++ *        print out what type of hardware is detected
++ *        print out the ethernet address
++ *        find the IRQ
++ *        set up my private data
++ *        configure the dev structure with my subroutines
++ *        actually GRAB the irq.
++ *        GRAB the region
++ *
++ */
++static int __init driver_init(struct net_device *dev, u32 baseA, int irq)
++{
++      int i;
++      struct resource *res;
++      struct sockaddr sa;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      if (0 == num_of_instance)
++              printk("%s", version);
++
++      /* skip probing for a second one, we _know_ that it does not exist */
++      if (1 == num_of_instance)
++              return -ENODEV;
++
++      memset(dev->priv, 0x00, sizeof(struct ep93xx_priv));
++
++      /* device instance ID */
++      priv->id = num_of_instance;
++
++      /* mii stuff */
++      spin_lock_init(&priv->mii_lock);
++      priv->mii.dev = dev;
++      priv->mii.mdio_read = mdio_read;
++      priv->mii.mdio_write = mdio_write;
++      priv->mii.phy_id_mask = 0x1f;
++      priv->mii.reg_num_mask = 0x1f;
++      priv->msg_enable = EP93XX_DEF_MSG;
++      priv->regs_len = DEV_REG_SPACE;
++
++      priv->base_addr = (void *)(baseA);
++
++      dev->irq = irq;
++
++      res = request_mem_region(baseA, DEV_REG_SPACE, DRV_NAME);
++      if (res == NULL) {
++              if (netif_msg_probe(priv))
++                      DBG(KERN_ERR, "request_mem_region failed!\n");
++              goto err_free_priv_1;
++      }
++
++      dev->open = &ep93xx_open;
++      dev->stop = &ep93xx_close;
++      dev->do_ioctl = &ep93xx_ioctl;
++      dev->hard_start_xmit = &ep93xx_start_xmit;
++      dev->tx_timeout = &ep93xx_tx_timeout;
++      dev->watchdog_timeo = HZ * 5;
++      dev->get_stats = &ep93xx_get_stats;
++      dev->set_multicast_list = &ep93xx_set_multicast_list;
++      dev->ethtool_ops = &ep93xx_ethtool_ops;
++
++      ether_setup(dev);
++
++      if (devQue_init(dev))
++              goto err_free_bd_memregion_irq_2;
++
++      reset(dev);
++
++      /*
++       * use a random MAC for now -
++       * don't forget to set a valid MAC later on with ifconfig
++       */
++      sa.sa_family = AF_INET;
++      random_ether_addr(sa.sa_data);
++      dev->set_mac_address(dev, &sa);
++
++      if (netif_msg_probe(priv)) {
++              printk(KERN_INFO DRV_NAME ": #%d at 0x%p IRQ:%d\n", priv->id, priv->base_addr, dev->irq);
++              printk(KERN_INFO DRV_NAME ": using random number");
++              for (i = 0; i < 6; i++)
++                      printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
++
++              printk(" as MAC, don't forget to assign a valid MAC later!\n");
++      }
++      num_of_instance++;
++      return 0;
++
++err_free_bd_memregion_irq_2:
++      kfree(priv->rxbd);
++      disable_irq(dev->irq);
++      free_irq(dev->irq, dev);
++      release_mem_region((u32)priv->base_addr, DEV_REG_SPACE);
++err_free_priv_1:
++      kfree(dev->priv);
++      return -EAGAIN;
++}
++
++/**
++ * ep93xx_probe - probe for ep93xx device
++ *
++ * Probe for the one (and only) ethernet device found on
++ * EP93xx SOC CPU.
++ */
++static int __init ep93xx_probe(void)
++{
++      int err;
++      struct ep93xx_priv *priv;
++      struct net_device *dev = alloc_etherdev(sizeof(struct ep93xx_priv));
++
++      if (!dev)
++              return -ENODEV;
++
++      priv = netdev_priv(dev);
++
++      SET_MODULE_OWNER(dev);
++
++      sprintf(dev->name, "eth0");
++
++      priv->base_addr = (void *)(port_list[0].base_addr);
++
++      dev->irq = port_list[0].irq;
++
++      err = driver_init(dev, (u32)priv->base_addr, dev->irq);
++      if (err)
++              goto err_free_netdev;
++
++      err = register_netdev(dev);
++      if (err)
++              goto err_free_memregion_irq_1;
++
++      ep93xx_etherdev = dev;
++      disable_irq(dev->irq);
++      return 0;
++
++err_free_memregion_irq_1:
++      kfree(priv->rxbd);
++      disable_irq(dev->irq);
++      free_irq(dev->irq, dev);
++      release_mem_region((u32)priv->base_addr, DEV_REG_SPACE);
++err_free_netdev:
++      free_netdev(dev);
++      return err;
++}
++
++static void __exit ep93xx_exit(void)
++{
++      struct net_device *dev = ep93xx_etherdev;
++      struct ep93xx_priv *priv = netdev_priv(dev);
++
++      if (dev) {
++              unregister_netdev(dev);
++              devQue_cleanup(dev);
++              free_irq(dev->irq, dev);
++              release_mem_region((u32)priv->base_addr, DEV_REG_SPACE);
++              free_netdev(dev);
++      }
++}
++
++module_init(ep93xx_probe);
++module_exit(ep93xx_exit);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/arm/ep93xx_eth.h b/drivers/net/arm/ep93xx_eth.h
+new file mode 100644
+index 0000000..1752eaf
+--- /dev/null
++++ b/drivers/net/arm/ep93xx_eth.h
+@@ -0,0 +1,355 @@
++/*
++ * ep93xx_eth.h
++ * : header file of Ethernet Device Driver for Cirrus Logic EP93xx.
++ *
++ * Copyright (C) 2003 by Cirrus Logic www.cirrus.com
++ * This software may be used and distributed according to the terms
++ * of the GNU Public License.
++ *
++ * This file contains device related information like register info
++ * and register access method macros for the Ethernet device
++ * embedded within Cirrus Logic's EP93xx SOC chip.
++ *
++ * Information contained in this file was obtained from
++ * the EP9312 Manual Revision 0.12 and 0.14 from Cirrus Logic.
++ *
++ * History
++ * 05/18/01  Sungwook Kim  Initial release
++ * 03/25/2003  Melody Modified for EP92xx
++ */
++
++#ifndef _EP93xx_ETH_H_
++#define _EP93xx_ETH_H_
++
++/*
++ * Definition of the registers.
++ * For details, refer to the datasheet  .
++ *
++ * Basically, most registers are 32 bits width register.
++ * But some are 16 bits and some are 6 or 8 bytes long.
++ */
++
++#define  REG_RxCTL  0x0000    /*offset to Receiver Control Reg */
++#define  RxCTL_PauseA  (1<<20)
++#define  RxCTL_RxFCE1  (1<<19)
++#define  RxCTL_RxFCE0  (1<<18)
++#define  RxCTL_BCRC    (1<<17)
++#define  RxCTL_SRxON   (1<<16)
++#define  RxCTL_RCRCA   (1<<13)
++#define  RxCTL_RA      (1<<12)
++#define  RxCTL_PA      (1<<11)
++#define  RxCTL_BA      (1<<10)
++#define  RxCTL_MA      (1<<9)
++#define  RxCTL_IAHA    (1<<8)
++#define  RxCTL_IA3     (1<<3)
++#define  RxCTL_IA2     (1<<2)
++#define  RxCTL_IA1     (1<<1)
++#define  RxCTL_IA0     (1<<0)
++
++#define  REG_TxCTL  0x0004    /*offset to Transmit Control Reg */
++#define  TxCTL_DefDis  (1<<7)
++#define  TxCTL_MBE     (1<<6)
++#define  TxCTL_ICRC    (1<<5)
++#define  TxCTL_TxPD    (1<<5)
++#define  TxCTL_OColl   (1<<3)
++#define  TxCTL_SP      (1<<2)
++#define  TxCTL_PB      (1<<1)
++#define  TxCTL_STxON   (1<<0)
++
++#define  REG_TestCTL   0x0008 /*Test Control Reg, R/W */
++#define  TestCTL_MACF  (1<<7)
++#define  TestCTL_MFDX  (1<<6)
++#define  TestCTL_DB    (1<<5)
++#define  TestCTL_MIIF  (1<<4)
++
++#define  REG_MIICmd  0x0010   /*offset to MII Command Reg, R/W */
++#define  MIICmd_OP     (0x03<<14)
++#define  MIICmd_OP_RD  (2<<14)
++#define  MIICmd_OP_WR  (1<<14)
++#define  MIICmd_PHYAD  (0x1f<<5)
++#define  MIICmd_REGAD  (0x1f<<0)
++
++#define  REG_MIIData  0x0014  /*offset to MII Data Reg, R/W */
++#define  MIIData_MIIData  (0xffff<<0)
++
++#define  REG_MIISts  0x0018   /*offset to MII Status Reg, R */
++#define  MIISts_Busy  (1<<0)
++
++#define  REG_SelfCTL  0x0020  /*offset to Self Control Reg */
++#define  SelfCTL_RWP    (1<<7)        /*Remote Wake Pin */
++#define  SelfCTL_GPO0   (1<<5)
++#define  SelfCTL_PUWE   (1<<4)
++#define  SelfCTL_PDWE   (1<<3)
++#define  SelfCTL_MIIL   (1<<2)
++#define  SelfCTL_RESET  (1<<0)
++
++#define  REG_IntEn   0x0024   /*Interrupt Enable Reg, R/W */
++#define  IntEn_RWIE    (1<<30)
++#define  IntEn_RxMIE   (1<<29)
++#define  IntEn_RxBIE   (1<<28)
++#define  IntEn_RxSQIE  (1<<27)
++#define  IntEn_TxLEIE  (1<<26)
++#define  IntEn_ECIE    (1<<25)
++#define  IntEn_TxUHIE  (1<<24)
++#define  IntEn_MOIE    (1<<18)
++#define  IntEn_TxCOIE  (1<<17)
++#define  IntEn_RxROIE  (1<<16)
++#define  IntEn_MIIIE   (1<<12)
++#define  IntEn_PHYSIE  (1<<11)
++#define  IntEn_TIE     (1<<10)
++#define  IntEn_SWIE    (1<<8)
++#define  IntEn_TxSQIE   (1<<3)
++#define  IntEn_RxEOFIE  (1<<2)
++#define  IntEn_RxEOBIE  (1<<1)
++#define  IntEn_RxHDRIE  (1<<0)
++
++#define  REG_IntStsP  0x0028  /*offset to Interrupt Status Preserve Reg, R/W */
++#define  REG_IntStsC  0x002c  /*offset to Interrupt Status Clear Reg, R */
++#define  IntSts_RWI    (1<<30)
++#define  IntSts_RxMI   (1<<29)
++#define  IntSts_RxBI   (1<<28)
++#define  IntSts_RxSQI  (1<<27)
++#define  IntSts_TxLEI  (1<<26)
++#define  IntSts_ECI    (1<<25)
++#define  IntSts_TxUHI  (1<<24)
++#define  IntSts_MOI    (1<<18)
++#define  IntSts_TxCOI  (1<<17)
++#define  IntSts_RxROI  (1<<16)
++#define  IntSts_MIII   (1<<12)
++#define  IntSts_PHYSI  (1<<11)
++#define  IntSts_TI     (1<<10)
++#define  IntSts_AHBE   (1<<9)
++#define  IntSts_SWI    (1<<8)
++#define  IntSts_OTHER  (1<<4)
++#define  IntSts_TxSQ   (1<<3)
++#define  IntSts_RxSQ   (1<<2)
++
++#define  REG_GT  0x0040               /*offset to General Timer Reg */
++#define  GT_GTC  (0xffff<<16)
++#define  GT_GTP  (0xffff<<0)
++
++#define  REG_FCT  0x0044      /*offset to Flow Control Timer Reg */
++#define  FCT_FCT  (0x00ffffff<<0)
++
++#define  REG_FCF  0x0048      /*offset to Flow Control Format Reg */
++#define  FCF_MACCT  (0xffff<<16)
++#define  FCF_TPT    (0xffff<<0)
++
++#define  REG_AFP  0x004c      /*offset to Address Filter Pointer Reg */
++#define  AFP_AFP  (0x07<<0)   /*Address Filter Pointer
++                                 (bank control for REG_IndAD) */
++#define  AFP_AFP_IA0   0      /*Primary Individual Address (MAC Addr) */
++#define  AFP_AFP_IA1   1      /*Individual Address 1 */
++#define  AFP_AFP_IA2   2      /*Individual Address 2 */
++#define  AFP_AFP_IA3   3      /*Individual Address 3 */
++#define  AFP_AFP_DTxP  6      /*Destination Address of Tx Pause Frame */
++#define  AFP_AFP_HASH  7      /*Hash Table */
++
++#define  REG_IndAD      0x0050        /*offset to Individual Address Reg,
++                                 n bytes, R/W */
++
++#define  REG_GIntSts    0x0060        /*offset to Global Interrupt
++                                 Status Reg (writing 1 will clear) */
++#define  REG_GIntROS    0x0068        /*offset to Global Interrupt
++                                 Status Read Only Reg */
++#define  GIntSts_INT  (1<<15) /*Global Interrupt Request Status */
++
++#define  REG_GIntMsk    0x0064        /*offset to Global Interrupt Mask Reg */
++#define  GIntMsk_IntEn  (1<<15)       /*Global Interrupt Enable */
++
++#define  REG_GIntFrc    0x006c        /*offset to Global Interrupt Force Reg */
++#define  GIntFrc_INT  (1<<15) /*Force to set GIntSts */
++
++#define  REG_TxCollCnt  0x0070        /*Transmit Collision Count Reg, R */
++#define  REG_RxMissCnt  0x0074        /*Receive Miss Count Reg, R */
++#define  REG_RxRntCnt   0x0078        /*Receive Runt Count Reg, R */
++
++#define  REG_BMCtl  0x0080    /*offset to Bus Master Control Reg, R/W */
++#define  BMCtl_MT     (1<<13)
++#define  BMCtl_TT     (1<<12)
++#define  BMCtl_UnH    (1<<11)
++#define  BMCtl_TxChR  (1<<10)
++#define  BMCtl_TxDis  (1<<9)
++#define  BMCtl_TxEn   (1<<8)
++#define  BMCtl_EH2    (1<<6)
++#define  BMCtl_EH1    (1<<5)
++#define  BMCtl_EEOB   (1<<4)
++#define  BMCtl_RxChR  (1<<2)
++#define  BMCtl_RxDis  (1<<1)
++#define  BMCtl_RxEn   (1<<0)
++
++#define  REG_BMSts  0x0084    /*offset to Bus Master Status Reg, R */
++#define  BMSts_TxAct  (1<<7)
++#define  BMSts_TP     (1<<4)
++#define  BMSts_RxAct  (1<<3)
++#define  BMSts_QID    (0x07<<0)
++#define  BMSts_QID_RxDt   (0<<0)
++#define  BMSts_QID_TxDt   (1<<0)
++#define  BMSts_QID_RxSts  (2<<0)
++#define  BMSts_QID_TxSts  (3<<0)
++#define  BMSts_QID_RxDesc (4<<0)
++#define  BMSts_QID_TxDesc (5<<0)
++
++#define  REG_RBCA   0x0088    /*offset to Receive Buffer
++                                 Current Address Reg, R */
++#define  REG_TBCA   0x008c    /*offset to Transmit Buffer
++                                 Current Address Reg, R */
++
++#define  REG_RxDBA  0x0090    /*offset to Receive Descriptor Queue
++                                 Base Address Reg, R/W */
++#define  REG_RxDBL  0x0094    /*offset to Receive Descriptor Queue
++                                 Base Length Reg, R/W, 16bits */
++#define  REG_RxDCL  0x0096    /*offset to Receive Descriptor Queue
++                                 Current Length Reg, R/W, 16bits */
++#define  REG_RxDCA  0x0098    /*offset to Receive Descriptor Queue
++                                 Current Address Reg, R/W */
++
++#define  REG_RxDEQ  0x009c    /*offset to Receive Descriptor
++                                 Enqueue Reg, R/W */
++#define  RxDEQ_RDV  (0xffff<<16)      /*R 16bit; Receive Descriptor Value */
++#define  RxDEQ_RDI  (0xff<<0) /*W 8bit; Receive Descriptor Increment */
++
++#define  REG_RxSBA  0x00a0    /*offset to Receive Status Queue
++                                 Base Address Reg, R/W */
++#define  REG_RxSBL  0x00a4    /*offset to Receive Status Queue
++                                 Base Length Reg, R/W, 16bits */
++#define  REG_RxSCL  0x00a6    /*offset to Receive Status Queue
++                                 Current Length Reg, R/W, 16bits */
++#define  REG_RxSCA  0x00a8    /*offset to Receive Status Queue
++                                 Current Address Reg, R/W */
++
++#define  REG_RxSEQ  0x00ac    /*offset to Receive Status Queue
++                                 Current Address Reg, R/W */
++#define  RxSEQ_RSV  (0xffff<<16)
++#define  RxSEQ_RSI  (0xff<<0)
++
++#define  REG_TxDBA  0x00b0    /*offset to Transmit Descriptor Queue
++                                 Base Address Reg, R/W */
++#define  REG_TxDBL  0x00b4    /*offset to Transmit Descriptor Queue
++                                 Base Length Reg, R/W, 16bits */
++#define  REG_TxDCL  0x00b6    /*offset to Transmit Descriptor Queue
++                                 Current Length Reg, R/W, 16bits */
++#define  REG_TxDCA  0x00b8    /*offset to Transmit Descriptor Queue
++                                 Current Address Reg, R/W */
++
++#define  REG_TxDEQ  0x00bc    /*offset to Transmit Descriptor Queue
++                                 Current Address Reg, R/W */
++#define  TxDEQ_TDV  (0xffff<<16)
++#define  TxDEQ_TDI  (0xff<<0)
++
++#define  REG_TxSBA  0x00c0    /*offset to Transmit Status Queue
++                                 Base Address Reg, R/W */
++#define  REG_TxSBL  0x00c4    /*offset to Transmit Status Queue
++                                 Base Length Reg, R/W, 16bits */
++#define  REG_TxSCL  0x00c6    /*offset to Transmit Status Queue
++                                 Current Length Reg, R/W, 16bits */
++#define  REG_TxSCA  0x00c8    /*offset to Transmit Status Queue
++                                 Current Address Reg, R/W */
++
++#define  REG_RxBTH  0x00d0    /*offset to Receive Buffer
++                                 Threshold Reg, R/W */
++#define  RxBTH_RDHT  (0x03ff<<16)
++#define  RxBTH_RDST  (0x03ff<<0)
++
++#define  REG_TxBTH  0x00d4    /*offset to Transmit Buffer
++                                 Threshold Reg, R/W */
++#define  TxBTH_TDHT  (0x03ff<<16)
++#define  TxBTH_TDST  (0x03ff<<0)
++
++#define  REG_RxSTH  0x00d8    /*offset to Receive Status
++                                 Threshold Reg, R/W */
++#define  RxSTH_RSHT  (0x003f<<16)
++#define  RxSTH_RSST  (0x003f<<0)
++
++#define  REG_TxSTH  0x00dc    /*offset to Transmit Status
++                                 Threshold Reg, R/W */
++#define  TxSTH_TSHT  (0x003f<<16)
++#define  TxSTH_TSST  (0x003f<<0)
++
++#define  REG_RxDTH  0x00e0    /*offset to Receive Descriptor
++                                 Threshold Reg, R/W */
++#define  RxDTH_RDHT  (0x003f<<16)
++#define  RxDTH_RDST  (0x003f<<0)
++
++#define  REG_TxDTH  0x00e4    /*offset to Transmit Descriptor
++                                 Threshold Reg, R/W */
++#define  TxDTH_TDHT  (0x003f<<16)
++#define  TxDTH_TDST  (0x003f<<0)
++
++#define  REG_MaxFL  0x00e8    /*offset to Max Frame Length Reg, R/W */
++#define  MaxFL_MFL  (0x07ff<<16)
++#define  MaxFL_TST  (0x07ff<<0)
++
++#define  REG_RxHL  0x00ec     /*offset to Receive Header Length Reg, R/W */
++#define  RxHL_RHL2  (0x07ff<<16)
++#define  RxHL_RHL1  (0x03ff<<0)
++
++#define  REG_MACCFG0  0x0100  /*offset to Test Reg #0, R/W */
++#define  MACCFG0_DbgSel  (1<<7)
++#define  MACCFG0_LCKEN   (1<<6)
++#define  MACCFG0_LRATE   (1<<5)
++#define  MACCFG0_RXERR   (1<<4)
++#define  MACCFG0_BIT33   (1<<2)
++#define  MACCFG0_PMEEN   (1<<1)
++#define  MACCFG0_PMEST   (1<<0)
++
++#define  REG_MACCFG1  0x0104  /*offset to Test Reg #1, R/W */
++#define  REG_MACCFG2  0x0108  /*offset to Test Reg #2, R */
++#define  REG_MACCFG3  0x010c  /*offset to Test Reg #3, R */
++
++/*---------------------------------------------------------------
++ * Definition of Descriptor/Status Queue Entry
++ *-------------------------------------------------------------*/
++struct rx_dsc {
++      __be32 ba;
++      __be16 bl;
++      __be16 bi;              /* let nsof flag be part of bi */
++};
++
++#define RXSTS_RFP     0x80000000
++#define RXSTS_RWE     0x40000000
++#define RXSTS_EOF     0x20000000
++#define RXSTS_EOB     0x10000000
++#define RXSTS_AM      0x00C00000
++#define RXSTS_OE      0x00100000
++#define RXSTS_FE      0x00080000
++#define RXSTS_RUNT    0x00040000
++#define RXSTS_EDATA   0x00020000
++#define RXSTS_CRCE    0x00010000
++
++#define RXSTS_BI      0x7FFF
++struct rx_sts {                       /* Receive Status Queue Entry */
++      __be32  w1;             
++      __be16  fl;             
++      __be16  bi;             /* bi and rfp2 */
++};
++
++#define TXDSC_BL      0x0FFF
++#define TXDSC_AF      0x8000
++#define TXDSC_BI      0x7FFF
++#define TXDSC_EOF     0x8000
++struct tx_dsc {                 /* Transmit Descriptor Queue Entry */
++      __be32  ba;     /*b31-0: physical Buffer Address */
++      __be16  bl_af;  /* Buffer Length, Abort Frame */
++      __be16  bi_eof; /* Buffer Index, End Of Frame */
++};
++
++#define TXSTS_BI      0x7fff
++#define TXSTS_TXFP    0x80
++#define TXSTS_TXWE    0x40
++#define TXSTS_LCRS    0x10
++#define TXSTS_TXU     0x02
++#define TXSTS_ECOLL   0x01
++
++struct tx_sts {
++      __be16  bi;
++      u8      ncoll;
++      u8      flags;
++};
++
++/*
++ *  Size of device registers occupied in memory/IO address map
++ */
++#define  DEV_REG_SPACE  0x00010000
++
++#endif                                /* _EP93xx_ETH_H_ */
+diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
+index 309eb55..b7e03e3 100644
+--- a/drivers/pcmcia/Kconfig
++++ b/drivers/pcmcia/Kconfig
+@@ -198,6 +198,19 @@ config PCMCIA_PXA2XX
+       help
+         Say Y here to include support for the PXA2xx PCMCIA controller
++config PCMCIA_EP93XX
++      tristate "EP93xx support"
++      depends on ARM && ARCH_EP93XX && PCMCIA
++      help
++        Say Y here to include support for the EP93xx PCMCIA controller
++
++config PCMCIA_ZEFEEREVBH
++      bool "ZefeerEVB-H support"
++      depends on ARM && ARCH_EP93XX && PCMCIA && PCMCIA_EP93XX && MACH_ZEFEERDZQ
++      help
++        Say Y here to include support for the PCMCIA interface on 
++        ZefeerEVB-H board
++
+ config PCMCIA_PROBE
+       bool
+       default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X
+diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
+index bcecf51..5878b5a 100644
+--- a/drivers/pcmcia/Makefile
++++ b/drivers/pcmcia/Makefile
+@@ -30,6 +30,7 @@ obj-$(CONFIG_HD64465_PCMCIA)                 += hd6446
+ obj-$(CONFIG_PCMCIA_SA1100)                   += sa11xx_core.o sa1100_cs.o
+ obj-$(CONFIG_PCMCIA_SA1111)                   += sa11xx_core.o sa1111_cs.o
+ obj-$(CONFIG_PCMCIA_PXA2XX)                     += pxa2xx_core.o pxa2xx_cs.o
++obj-$(CONFIG_PCMCIA_EP93XX)                     += ep93xx_core.o ep93xx_cs.o
+ obj-$(CONFIG_M32R_PCC)                                += m32r_pcc.o
+ obj-$(CONFIG_M32R_CFC)                                += m32r_cfc.o
+ obj-$(CONFIG_PCMCIA_AU1X00)                   += au1x00_ss.o
+@@ -39,6 +40,7 @@ obj-$(CONFIG_OMAP_CF)                                += omap_cf.o
+ sa11xx_core-y                                 += soc_common.o sa11xx_base.o
+ pxa2xx_core-y                                 += soc_common.o pxa2xx_base.o
++ep93xx_core-y                                 += soc_common.o ep93xx_base.o
+ au1x00_ss-y                                   += au1000_generic.o
+ au1x00_ss-$(CONFIG_MIPS_PB1000)                       += au1000_pb1x00.o
+@@ -69,3 +71,7 @@ pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK)             += pxa
+ pxa2xx_cs-$(CONFIG_MACH_MAINSTONE)            += pxa2xx_mainstone.o
+ pxa2xx_cs-$(CONFIG_PXA_SHARPSL)                       += pxa2xx_sharpsl.o
++ep93xx_cs-$(CONFIG_MACH_ADSSPHERE)            += ep93xx_adssphere.o
++ep93xx_cs-$(CONFIG_MACH_EDB9315)              += ep93xx_edb9315.o
++ep93xx_cs-$(CONFIG_MACH_DMA03)                        += ep93xx_edb9315.o
++ep93xx_cs-$(CONFIG_PCMCIA_ZEFEEREVBH)                 += ep93xx_zefeerevbh.o
+diff --git a/drivers/pcmcia/ep93xx_adssphere.c b/drivers/pcmcia/ep93xx_adssphere.c
+new file mode 100644
+index 0000000..8e1a181
+--- /dev/null
++++ b/drivers/pcmcia/ep93xx_adssphere.c
+@@ -0,0 +1,190 @@
++/*
++ * linux/drivers/pcmcia/ep93xx_adssphere.c
++ *
++ * Adapted from pxa27x_mainstone.c
++ *
++ * Robert Whaley 2005 rwhaley@applieddata.net
++ *
++ * Adssphere PCMCIA specific routines.
++ *
++ * Created:   May 12, 2004
++ * Author:    Nicolas Pitre
++ * Copyright: MontaVista Software Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/device.h>
++
++#include <pcmcia/ss.h>
++
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++
++#include <asm/arch/adssphere.h>
++
++#include "soc_common.h"
++
++static struct pcmcia_irqs irqs[] = {
++      { 0, IRQ_GPIO1, "CF CD1" },
++      { 0, IRQ_GPIO2, "CF CD2" },
++      { 0, IRQ_GPIO3, "CF STSCHG/BVD1" },
++      { 0, IRQ_GPIO4, "CF SPKR/BVD2" },
++};
++
++
++static int adssphere_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
++{
++      int rtn;
++
++      if (skt->nr != 0)
++              return -ENXIO;
++
++      skt->irq = IRQ_GPIO6;
++
++      rtn =  soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
++
++      /* enable GPIO6 as interrupt */
++      writel(0x40, GPIO_INTEN);
++
++      /* enable GPIO1-4 and 6 as interrupt */
++      /* Note: 1-4 need to be edge triggered, but
++         then the irq vectors need to hit GPIOxEIO
++         which they don't currently do - no big deal
++         since CD and BVD are polled anyway */
++      /* writel(0x5e, GPIO_INTEN); */
++
++      return rtn;
++}
++
++static void adssphere_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
++{
++      soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
++}
++
++static void adssphere_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
++                                  struct pcmcia_state *state)
++{
++      unsigned long status;
++
++      status = inl(GPIO_PFDR);
++
++      state->detect = (status & PCMCIA_DETECT) ? 0 : 1;
++      state->ready  = (status & PCMCIA_READY)  ? 1 : 0;
++      state->bvd1   = (status & PCMCIA_BVD1)   ? 1 : 0;
++      state->bvd2   = (status & PCMCIA_BVD2)   ? 1 : 0;
++      state->vs_3v  = (status & PCMCIA_VS_3V)  ? 0 : 1;
++      state->vs_Xv  = (status & PCMCIA_VS_XV)  ? 0 : 1;
++      state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1;
++
++//    printk("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state));
++}
++
++static int adssphere_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
++                                     const socket_state_t *state)
++{
++      unsigned long clrbits = 0, setbits = 0, cr0;
++      int ret = 0;
++
++      switch (state->Vcc) {
++      case 0:  {
++              clrbits = ADSSPHERE_CR0_CF_33 | ADSSPHERE_CR0_CF_50;
++              setbits = 0;
++              break;
++      }
++      case 33: {
++              clrbits = ADSSPHERE_CR0_CF_50;
++              setbits = ADSSPHERE_CR0_CF_33;
++              break;
++      }
++      case 50: {
++              clrbits = ADSSPHERE_CR0_CF_33;
++              setbits = ADSSPHERE_CR0_CF_50;
++              break;
++      }
++      default:
++               printk(KERN_ERR "%s(): bad Vcc %u\n",
++                               __FUNCTION__, state->Vcc);
++               ret = -1;
++      }
++
++      if (!ret && skt->nr == 0) {
++              cr0 = inl(ADSSPHERE_CR0);
++              cr0 &= ~clrbits;
++              cr0 |=  setbits;
++              writel(cr0, ADSSPHERE_CR0);
++
++              if (state->flags & SS_RESET) {
++                      /* see EP93xx User's Guide */
++                      writel(0x15, PCMCIACNT);
++              } else {
++                      /* CF mode -  BIT1 for PCMCIA mode */
++                      writel(0x11, PCMCIACNT);
++              }
++      }
++
++      return ret;
++}
++
++static void adssphere_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
++{
++}
++
++static void adssphere_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
++{
++}
++
++static struct pcmcia_low_level adssphere_pcmcia_ops = {
++      .owner                  = THIS_MODULE,
++      .hw_init                = adssphere_pcmcia_hw_init,
++      .hw_shutdown            = adssphere_pcmcia_hw_shutdown,
++      .socket_state           = adssphere_pcmcia_socket_state,
++      .configure_socket       = adssphere_pcmcia_configure_socket,
++      .socket_init            = adssphere_pcmcia_socket_init,
++      .socket_suspend         = adssphere_pcmcia_socket_suspend,
++      .nr                     = 1,
++};
++
++static struct platform_device *adssphere_pcmcia_device;
++
++static int __init adssphere_pcmcia_init(void)
++{
++      int ret;
++
++      adssphere_pcmcia_device = kmalloc(sizeof(*adssphere_pcmcia_device), GFP_KERNEL);
++      if (!adssphere_pcmcia_device)
++              return -ENOMEM;
++      memset(adssphere_pcmcia_device, 0, sizeof(*adssphere_pcmcia_device));
++      adssphere_pcmcia_device->name = "ep93xx-pcmcia";
++      adssphere_pcmcia_device->dev.platform_data = &adssphere_pcmcia_ops;
++
++      ret = platform_device_register(adssphere_pcmcia_device);
++      if (ret)
++              kfree(adssphere_pcmcia_device);
++
++      return ret;
++}
++
++static void __exit adssphere_pcmcia_exit(void)
++{
++      /*
++       * This call is supposed to free our adssphere_pcmcia_device.
++       * Unfortunately platform_device don't have a free method, and
++       * we can't assume it's free of any reference at this point so we
++       * can't free it either.
++       */
++      platform_device_unregister(adssphere_pcmcia_device);
++}
++
++module_init(adssphere_pcmcia_init);
++module_exit(adssphere_pcmcia_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/pcmcia/ep93xx_base.c b/drivers/pcmcia/ep93xx_base.c
+new file mode 100644
+index 0000000..2377989
+--- /dev/null
++++ b/drivers/pcmcia/ep93xx_base.c
+@@ -0,0 +1,190 @@
++/*======================================================================
++
++  Device driver for the PCMCIA control functionality of EP93xx
++  microprocessors.  Derived from pxa2xx_base.c
++
++    The contents of this file may be used under the
++    terms of the GNU Public License version 2 (the "GPL")
++
++    (c) Ian Molton (spyro@f2s.com) 2003
++    (c) Stefan Eletzhofer (stefan.eletzhofer@inquant.de) 2003,4
++    (c) Robert Whaley (rwhaley@applieddata.net) 2005
++
++    derived from sa11xx_base.c
++
++     Portions created by John G. Dorsey are
++     Copyright (C) 1999 John G. Dorsey.
++
++  ======================================================================*/
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/config.h>
++#include <linux/ioport.h>
++#include <linux/kernel.h>
++#include <linux/spinlock.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++
++#include <pcmcia/cs_types.h>
++#include <pcmcia/ss.h>
++#include <pcmcia/bulkmem.h>
++#include <pcmcia/cistpl.h>
++
++#include "cs_internal.h"
++#include "soc_common.h"
++
++#define MIN(a,b)      ((a)>(b) ? (b) : (a))
++
++#define MCXX_SETUP_MAX     0xff
++#define MCXX_ASST_MAX      0xff
++#define MCXX_HOLD_MAX      0x0f
++
++#define MCXX_SETUP_SHIFT   0
++#define MCXX_ASST_SHIFT    16
++#define MCXX_HOLD_SHIFT    8
++
++
++
++static inline u_int ep93xx_mcxx_hold(u_int pcmcia_cycle_ns,
++                                   u_int hclk_10khz)
++{
++      u_int code = pcmcia_cycle_ns * hclk_10khz;
++      return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
++}
++
++static inline u_int ep93xx_mcxx_asst(u_int pcmcia_cycle_ns,
++                                   u_int hclk_10khz)
++{
++      u_int code = pcmcia_cycle_ns * hclk_10khz;
++      return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
++}
++
++static inline u_int ep93xx_mcxx_setup(u_int pcmcia_cycle_ns,
++                                    u_int hclk_10khz)
++{
++      u_int code = pcmcia_cycle_ns * hclk_10khz;
++      return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
++}
++
++static int ep93xx_pcmcia_set_mcmem( int sock, int speed, int clock )
++{
++        writel(PC16BITSWIDE
++           | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
++           | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
++           | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
++           PC1COMMON);
++
++      return 0;
++}
++
++static int ep93xx_pcmcia_set_mcio( int sock, int speed, int clock )
++{
++        writel(PC16BITSWIDE
++           | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
++           | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
++           | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
++           PC1IO);
++
++      return 0;
++}
++
++static int ep93xx_pcmcia_set_mcatt( int sock, int speed, int clock )
++{
++        writel(PC16BITSWIDE
++           | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
++           | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
++           | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
++           PC1ATTRIB);
++
++      return 0;
++}
++
++static int ep93xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int clk)
++{
++      struct soc_pcmcia_timing timing;
++      int sock = skt->nr;
++
++      soc_common_pcmcia_get_timing(skt, &timing);
++
++      ep93xx_pcmcia_set_mcmem(sock, timing.mem, clk);
++      ep93xx_pcmcia_set_mcatt(sock, timing.attr, clk);
++      ep93xx_pcmcia_set_mcio(sock, timing.io, clk);
++
++      return 0;
++}
++
++static int ep93xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
++{
++      unsigned int hclk = 10000; /* for now just hard code hclk to 100Mhz (in 10khz units)*/
++      return ep93xx_pcmcia_set_mcxx(skt, hclk);
++}
++
++int ep93xx_drv_pcmcia_probe(struct device *dev)
++{
++      int ret;
++      struct pcmcia_low_level *ops;
++      int first, nr;
++
++      if (!dev || !dev->platform_data)
++              return -ENODEV;
++
++      ops = (struct pcmcia_low_level *)dev->platform_data;
++      first = ops->first;
++      nr = ops->nr;
++
++      /* Provide our EP93xx specific timing routines. */
++      ops->set_timing  = ep93xx_pcmcia_set_timing;
++
++      ret = soc_common_drv_pcmcia_probe(dev, ops, first, nr);
++
++      return ret;
++}
++EXPORT_SYMBOL(ep93xx_drv_pcmcia_probe);
++
++static int ep93xx_drv_pcmcia_suspend(struct device *dev, u32 state, u32 level)
++{
++      int ret = 0;
++      if (level == SUSPEND_SAVE_STATE)
++              ret = pcmcia_socket_dev_suspend(dev, state);
++      return ret;
++}
++
++static int ep93xx_drv_pcmcia_resume(struct device *dev, u32 level)
++{
++      int ret = 0;
++      if (level == RESUME_RESTORE_STATE)
++      {
++              ret = pcmcia_socket_dev_resume(dev);
++      }
++      return ret;
++}
++
++static struct device_driver ep93xx_pcmcia_driver = {
++      .probe          = ep93xx_drv_pcmcia_probe,
++      .remove         = soc_common_drv_pcmcia_remove,
++      .suspend        = ep93xx_drv_pcmcia_suspend,
++      .resume         = ep93xx_drv_pcmcia_resume,
++      .name           = "ep93xx-pcmcia",
++      .bus            = &platform_bus_type,
++};
++
++static int __init ep93xx_pcmcia_init(void)
++{
++      return driver_register(&ep93xx_pcmcia_driver);
++}
++
++static void __exit ep93xx_pcmcia_exit(void)
++{
++      driver_unregister(&ep93xx_pcmcia_driver);
++}
++
++module_init(ep93xx_pcmcia_init);
++module_exit(ep93xx_pcmcia_exit);
++
++MODULE_AUTHOR("Robert Whaley (whaley@applieddata.net)");
++MODULE_DESCRIPTION("Linux PCMCIA Card Services: EP93xx core socket driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/pcmcia/ep93xx_edb9315.c b/drivers/pcmcia/ep93xx_edb9315.c
+new file mode 100644
+index 0000000..519fc8d
+--- /dev/null
++++ b/drivers/pcmcia/ep93xx_edb9315.c
+@@ -0,0 +1,283 @@
++/*
++ * linux/drivers/pcmcia/ep93xx_edb9315.c
++ *
++ * Adapted from pxa27x_mainstone.c
++ *
++ * Edb9315 PCMCIA specific routines.
++ *
++ * Created:   May 12, 2004
++ * Author:    Nicolas Pitre
++ * Copyright: MontaVista Software Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/device.h>
++
++#include <pcmcia/ss.h>
++
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++
++#include <asm/arch/edb9315.h>
++
++#include "soc_common.h"
++
++static struct pcmcia_irqs irqs[] = {
++      { 0, IRQ_GPIO1, "CF CD1" },
++      { 0, IRQ_GPIO2, "CF CD2" },
++      { 0, IRQ_GPIO3, "CF STSCHG/BVD1" },
++      { 0, IRQ_GPIO4, "CF SPKR/BVD2" },
++};
++
++
++static int edb9315_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
++{
++      int rtn;
++
++      if (skt->nr == 0)
++              return -ENXIO;
++
++      skt->irq = IRQ_GPIO6;
++
++      rtn =  soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
++
++      /* enable GPIO6 as interrupt */
++      writel(0x40, GPIO_INTEN);
++
++      /* enable GPIO1-4 and 6 as interrupt */
++      /* Note: 1-4 need to be edge triggered, but
++         then the irq vectors need to hit GPIOxEIO
++         which they don't currently do - no big deal
++         since CD and BVD are polled anyway */
++      /* writel(0x5e, GPIO_INTEN); */
++
++      return rtn;
++}
++
++static void edb9315_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
++{
++      soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
++}
++
++static void edb9315_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
++                                  struct pcmcia_state *state)
++{
++      unsigned long status;
++
++      status = inl(GPIO_PFDR);
++
++      state->detect = (status & PCMCIA_DETECT) ? 0 : 1;
++      state->ready  = (status & PCMCIA_READY)  ? 1 : 0;
++      state->bvd1   = (status & PCMCIA_BVD1)   ? 1 : 0;
++      state->bvd2   = (status & PCMCIA_BVD2)   ? 1 : 0;
++      state->vs_3v  = (status & PCMCIA_VS_3V)  ? 0 : 1;
++      state->vs_Xv  = (status & PCMCIA_VS_XV)  ? 0 : 1;
++      state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1;
++
++//    printk("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state));
++}
++
++/*
++ * We bit-bang the pcmcia power controller using this function.
++ */
++static void ep93xx_bitbang( unsigned long ulNewEEValue )
++{
++      unsigned long ulGdata;
++
++      ulGdata = inl( GPIO_PGDR );
++
++      ulGdata &= ~(GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0);
++
++      ulNewEEValue &= (GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0);
++
++      ulGdata |= ulNewEEValue;
++
++      outl( ulGdata, GPIO_PGDR );
++      ulGdata = inl( GPIO_PGDR ); // read to push write out wrapper
++
++      // Voltage controller's data sheet says minimum pulse width is
++      // one microsecond.
++      udelay(5);
++}
++
++static int
++ep93xx_set_voltage( u_short sock, u_char NewVcc )
++{
++      struct socket_info_t * skt = &socket_info[sock];
++      unsigned long ulSwitchSettings, ulDataBit, ulGdirection;
++      int       i;
++
++      if (sock >= EP93XX_MAX_SOCK)
++              return -EINVAL;
++
++      if( skt->Vcc == NewVcc ){
++              DEBUG(3, "Power already set to %d\n", NewVcc );
++              return 0;
++      }
++
++      ulSwitchSettings = EE_ADDRESS | ENABLE;
++      switch( NewVcc )
++      {
++              case 0:
++                      DEBUG(3, "Configure the socket for 0 Volts\n");
++                      ulSwitchSettings |= AVCC_0V;
++                      break;
++
++              case 50:
++                      ulSwitchSettings |= AVCC_5V;
++                      DEBUG(3, "Configure the socket for 5 Volts\n");
++                      break;
++
++              case 33:
++                      DEBUG(3, "Configure the socket for 3.3 Volts\n");
++                      ulSwitchSettings |= AVCC_33V;
++                      break;
++
++              default:
++                      printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
++                              NewVcc);
++                      return -1;
++      }
++
++      //
++      // Configure the proper GPIO pins as outputs.
++      //
++      ep93xx_bitbang( GPIOA_EECLK | GPIOA_EEDAT );
++
++      //
++      // Read modify write the data direction register, set the
++      // proper lines to be outputs.
++      //
++      ulGdirection = inl( GPIO_PGDDR );
++      ulGdirection |= GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0;
++      outl( ulGdirection, GPIO_PGDDR );
++      ulGdirection = inl( GPIO_PGDDR ); // read to push write out wrapper
++
++      //
++      // Clear all except EECLK
++      // Lower the clock.
++      //
++      ep93xx_bitbang( GPIOA_EECLK );
++      ep93xx_bitbang( 0 );
++
++      //
++      // Serial shift the command word out to the voltage controller.
++      //
++      for( i=18 ; i>=0 ; --i )
++      {
++              if( (ulSwitchSettings >> i) & 0x1 )
++                      ulDataBit = GPIOA_EEDAT;
++              else
++                      ulDataBit = 0;
++
++              //
++              // Put the data on the bus and lower the clock.
++              // Raise the clock to latch the data in.
++              // Lower the clock again.
++              //
++              ep93xx_bitbang( ulDataBit );
++              ep93xx_bitbang( ulDataBit | GPIOA_EECLK );
++              ep93xx_bitbang( ulDataBit );
++      }
++
++      //
++      // Raise and lower the Latch.
++      // Raise EECLK, delay, raise EEDAT, leave them that way.
++      //
++      ep93xx_bitbang( GPIOA_SLA0 );
++      ep93xx_bitbang( 0 );
++      ep93xx_bitbang( GPIOA_EECLK );
++      ep93xx_bitbang( GPIOA_EECLK | GPIOA_EEDAT );
++
++      skt->Vcc = NewVcc;
++
++      DEBUG(3, "ep93xx_set_voltage - exit\n");
++
++      return 0;
++}
++
++static int edb9315_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
++                                     const socket_state_t *state)
++{
++      unsigned long clrbits = 0, setbits = 0, cr0;
++      int ret = 0;
++
++      ep93xx_set_voltage(skt->nr, state->Vxx);
++
++      if (!ret && skt->nr == 0) {
++
++              if (state->flags & SS_RESET) {
++                      /* see EP93xx User's Guide */
++                      writel(0x15, PCMCIACNT);
++              } else {
++                      /* CF mode -  BIT1 for PCMCIA mode */
++                      writel(0x11, PCMCIACNT);
++              }
++      }
++
++      return ret;
++}
++
++static void edb9315_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
++{
++}
++
++static void edb9315_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
++{
++}
++
++static struct pcmcia_low_level edb9315_pcmcia_ops = {
++      .owner                  = THIS_MODULE,
++      .hw_init                = edb9315_pcmcia_hw_init,
++      .hw_shutdown            = edb9315_pcmcia_hw_shutdown,
++      .socket_state           = edb9315_pcmcia_socket_state,
++      .configure_socket       = edb9315_pcmcia_configure_socket,
++      .socket_init            = edb9315_pcmcia_socket_init,
++      .socket_suspend         = edb9315_pcmcia_socket_suspend,
++      .nr                     = 1,
++};
++
++static struct platform_device *edb9315_pcmcia_device;
++
++static int __init edb9315_pcmcia_init(void)
++{
++      int ret;
++
++      edb9315_pcmcia_device = kmalloc(sizeof(*edb9315_pcmcia_device), GFP_KERNEL);
++      if (!edb9315_pcmcia_device)
++              return -ENOMEM;
++      memset(edb9315_pcmcia_device, 0, sizeof(*edb9315_pcmcia_device));
++      edb9315_pcmcia_device->name = "ep93xx-pcmcia";
++      edb9315_pcmcia_device->dev.platform_data = &edb9315_pcmcia_ops;
++
++      ret = platform_device_register(edb9315_pcmcia_device);
++      if (ret)
++              kfree(edb9315_pcmcia_device);
++
++      return ret;
++}
++
++static void __exit edb9315_pcmcia_exit(void)
++{
++      /*
++       * This call is supposed to free our edb9315_pcmcia_device.
++       * Unfortunately platform_device don't have a free method, and
++       * we can't assume it's free of any reference at this point so we
++       * can't free it either.
++       */
++      platform_device_unregister(edb9315_pcmcia_device);
++}
++
++module_init(edb9315_pcmcia_init);
++module_exit(edb9315_pcmcia_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/pcmcia/ep93xx_zefeerevbh.c b/drivers/pcmcia/ep93xx_zefeerevbh.c
+new file mode 100644
+index 0000000..44d44ed
+--- /dev/null
++++ b/drivers/pcmcia/ep93xx_zefeerevbh.c
+@@ -0,0 +1,175 @@
++/*
++ * linux/drivers/pcmcia/ep93xx_zefeerevbh.c
++ *
++ * Adapted from ep93xx_zefeerevbh.c
++ *
++ *
++ * ZefeerEVB-H PCMCIA specific routines.
++ *
++ * Copyright: DAVE Srl <www.dave-tech.it>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/device.h>
++
++#include <pcmcia/ss.h>
++
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++
++#include <asm/arch/zefeerevb.h>
++
++#include "soc_common.h"
++
++#if 0
++#define DPRINTK(fmt, args...) printk( "[%s:] \n" fmt, __FUNCTION__, ## args)
++#else
++#define DPRINTK(fmt, args...)
++#endif
++
++static struct pcmcia_irqs irqs[] = {
++      { 0, IRQ_GPIO1, "CF CD1" },
++      { 0, IRQ_GPIO2, "CF CD2" },
++      { 0, IRQ_GPIO3, "CF STSCHG/BVD1" },
++      { 0, IRQ_GPIO4, "CF SPKR/BVD2" },
++};
++
++
++static int zefeerevbh_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
++{
++      int rtn;
++      unsigned long tmp;
++
++      if (skt->nr != 0)
++              return -ENXIO;
++
++      /* Set interrupt lines as input */
++      tmp = readl(GPIO_PFDDR);
++      tmp = (tmp & (~((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 6))));
++      writel(tmp, GPIO_PFDDR);
++              
++      skt->irq = IRQ_GPIO6;
++
++      rtn =  soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
++
++      /* enable GPIO6 as interrupt */
++      writel(0x40, GPIO_INTEN);
++
++      /* enable GPIO1-4 and 6 as interrupt */
++      /* Note: 1-4 need to be edge triggered, but
++         then the irq vectors need to hit GPIOxEIO
++         which they don't currently do - no big deal
++         since CD and BVD are polled anyway */
++      /* writel(0x5e, GPIO_INTEN); */
++
++      return rtn;
++}
++
++static void zefeerevbh_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
++{
++      soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
++}
++
++static void zefeerevbh_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
++                                  struct pcmcia_state *state)
++{
++      unsigned long status;
++
++      status = inl(GPIO_PFDR);
++
++      state->detect = (status & PCMCIA_DETECT) ? 0 : 1;
++      state->ready  = (status & PCMCIA_READY)  ? 1 : 0;
++      state->bvd1   = (status & PCMCIA_BVD1)   ? 1 : 0;
++      state->bvd2   = (status & PCMCIA_BVD2)   ? 1 : 0;
++      state->vs_3v  = (status & PCMCIA_VS_3V)  ? 0 : 1;
++      state->vs_Xv  = (status & PCMCIA_VS_XV)  ? 0 : 1;
++      state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1;
++
++      DPRINTK("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state));
++}
++
++static int zefeerevbh_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
++                                     const socket_state_t *state)
++{
++
++      printk(KERN_INFO "[%s]: Vcc = %u, Vpp = %u\n", __FUNCTION__, state->Vcc, state->Vpp);
++      
++      /* By default power handling is managed by external controller automatically */
++
++      if (skt->nr == 0) {
++              if (state->flags & SS_RESET) {
++                      /* see EP93xx User's Guide */
++                      writel(0x15, PCMCIACNT);
++              } else {
++                      /* CF mode -  BIT1 for PCMCIA mode */
++                      writel(0x11, PCMCIACNT);
++              }
++      }
++
++
++      return 0;
++}
++
++static void zefeerevbh_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
++{
++}
++
++static void zefeerevbh_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
++{
++}
++
++static struct pcmcia_low_level zefeerevbh_pcmcia_ops = {
++      .owner                  = THIS_MODULE,
++      .hw_init                = zefeerevbh_pcmcia_hw_init,
++      .hw_shutdown            = zefeerevbh_pcmcia_hw_shutdown,
++      .socket_state           = zefeerevbh_pcmcia_socket_state,
++      .configure_socket       = zefeerevbh_pcmcia_configure_socket,
++      .socket_init            = zefeerevbh_pcmcia_socket_init,
++      .socket_suspend         = zefeerevbh_pcmcia_socket_suspend,
++      .nr                     = 1,
++};
++
++static struct platform_device *zefeerevbh_pcmcia_device;
++
++static int __init zefeerevbh_pcmcia_init(void)
++{
++      int ret;
++
++      zefeerevbh_pcmcia_device = kmalloc(sizeof(*zefeerevbh_pcmcia_device), GFP_KERNEL);
++      if (!zefeerevbh_pcmcia_device)
++              return -ENOMEM;
++      memset(zefeerevbh_pcmcia_device, 0, sizeof(*zefeerevbh_pcmcia_device));
++      zefeerevbh_pcmcia_device->name = "ep93xx-pcmcia";
++      zefeerevbh_pcmcia_device->dev.platform_data = &zefeerevbh_pcmcia_ops;
++
++      ret = platform_device_register(zefeerevbh_pcmcia_device);
++      if (ret)
++              kfree(zefeerevbh_pcmcia_device);
++
++      return ret;
++}
++
++static void __exit zefeerevbh_pcmcia_exit(void)
++{
++      /*
++       * This call is supposed to free our zefeerevbh_pcmcia_device.
++       * Unfortunately platform_device don't have a free method, and
++       * we can't assume it's free of any reference at this point so we
++       * can't free it either.
++       */
++      platform_device_unregister(zefeerevbh_pcmcia_device);
++}
++
++module_init(zefeerevbh_pcmcia_init);
++module_exit(zefeerevbh_pcmcia_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
+index 812bae6..15bfa5d 100644
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -289,6 +289,25 @@ config SERIAL_CLPS711X_CONSOLE
+         your boot loader (lilo or loadlin) about how to pass options to the
+         kernel at boot time.)
++config SERIAL_EP93XX
++      tristate "EP93XX serial port support"
++      depends on ARM && ARCH_EP93XX
++      select SERIAL_CORE
++      help
++        Support for the serial ports included in the EP93xx CPU SOC.
++
++config SERIAL_EP93XX_CONSOLE
++      bool "Support for console on EP93XX serial port"
++      depends on SERIAL_EP93XX=y
++      select SERIAL_CORE_CONSOLE
++      help
++        Even if you say Y here, the currently visible virtual console
++        (/dev/tty0) will still be used as the system console by default, but
++        you can alter that using a kernel command line option such as
++        "console=ttyCL1". (Try "man bootparam" or see the documentation of
++        your boot loader (lilo or loadlin) about how to pass options to the
++        kernel at boot time.)
++
+ config SERIAL_S3C2410
+       tristate "Samsung S3C2410 Serial port support"
+       depends on ARM && ARCH_S3C2410
+diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
+index d7c7c71..ef074dc 100644
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -26,6 +26,7 @@ obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250
+ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
+ obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
+ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
++obj-$(CONFIG_SERIAL_EP93XX) += ep93xx.o
+ obj-$(CONFIG_SERIAL_PXA) += pxa.o
+ obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
+ obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
+diff --git a/drivers/serial/ep93xx.c b/drivers/serial/ep93xx.c
+new file mode 100644
+index 0000000..60f91a6
+--- /dev/null
++++ b/drivers/serial/ep93xx.c
+@@ -0,0 +1,863 @@
++/*
++ *  drivers/serial/ep93xx.c
++ *
++ *  Driver for EP93xx serial ports
++ *
++ *  Based on drivers/serial/amba-pl011.c
++ *
++ *  Copyright 1999 ARM Limited
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd.
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ *  $Id: ep93xx.c,v 1.42 2002/07/28 10:03:28 rmk Exp $
++ *
++ */
++
++/* todo:
++ *  - correct major/minor numbers
++ *  - implement request/release/verify port
++ *  - from /dev/ttyAM0, 'stty -F /dev/ttyAM1 57600' not working right.
++ *    looks like it changes the divisor, but it gets changed back as
++ *    soon as you enter a char on /dev/ttyAM1.
++ *  - do not enable modem status ints unless HW is setup
++ *  - do not return modem status unless HW is setup
++ *  - figure out a nice way to handle CL0 HDLC/modem, CL1 SIR IrDA,
++ *    and CL2 HDLC/RS485
++ *  - UART DMA operation?
++ *  - handle icount fields rng and buf_overrun?
++ */
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/tty.h>
++#include <linux/device.h>
++#include <linux/sysrq.h>
++#include <linux/console.h>
++#include <linux/serial.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/hardware/amba.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/clocks.h>
++
++#if defined(CONFIG_SERIAL_EP93XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
++#define SUPPORT_SYSRQ
++#endif
++
++#include <linux/serial_core.h>
++
++#if defined(CONFIG_ARCH_EP9312) || defined(CONFIG_ARCH_EP9315)
++#define UART_NR               3
++#else
++#define UART_NR               2
++#endif
++
++#define SERIAL_EP93XX_MAJOR   204
++#define SERIAL_EP93XX_MINOR   16
++
++#define ISR_PASS_LIMIT 256
++
++#define REG(port,name)        ((port)->membase + (name) - EP93XX_APB_BASE - UART1_OFFSET)
++
++#define UARTDR(port)  REG(port,UART1DR)
++#define UARTCR(port)  REG(port,UART1CR)
++#define UARTFR(port)  REG(port,UART1FR)
++#define UARTRSR(port) REG(port,UART1RSR)
++#define UARTECR(port) REG(port,UART1ECR)
++#define UARTMCR(port) REG(port,UART1MCR)
++#define UARTMSR(port) REG(port,UART1MSR)
++#define UARTIIR(port) REG(port,UART1IIR)
++#define UARTICR(port) REG(port,UART1ICR)
++#define UARTLCH(port) REG(port,UART1CR_H)
++#define UARTLCM(port) REG(port,UART1CR_M)
++#define UARTLCL(port) REG(port,UART1CR_L)
++
++#define UARTRSR_CREAD 0x100
++
++static void enable_clocks(struct uart_port *port)
++{
++      unsigned int devcfg = readl(SYSCON_DEVCFG);
++
++      switch (port->line) {
++      case 0:
++              devcfg |= SYSCON_DEVCFG_U1EN;
++              devcfg &= ~SYSCON_DEVCFG_MonG;  /* handle this better... */
++              break;
++      case 1:
++              devcfg |= SYSCON_DEVCFG_U2EN;
++              break;
++      case 2:
++              devcfg |= SYSCON_DEVCFG_U3EN;
++              break;
++      }
++
++      SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(devcfg));
++}
++
++static void disable_clocks(struct uart_port *port)
++{
++      unsigned int devcfg = readl(SYSCON_DEVCFG);
++
++      switch (port->line) {
++      case 0:
++              devcfg &= ~SYSCON_DEVCFG_U1EN;
++              break;
++      case 1:
++              devcfg &= ~SYSCON_DEVCFG_U2EN;
++              break;
++      case 2:
++              devcfg &= ~SYSCON_DEVCFG_U3EN;
++              break;
++      }
++
++      SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(devcfg));
++}
++
++static int is_port_enabled(struct uart_port *port)
++{
++      unsigned int devcfg = readl(SYSCON_DEVCFG);
++
++      switch (port->line) {
++      case 0:
++              devcfg &= SYSCON_DEVCFG_U1EN;
++              break;
++      case 1:
++              devcfg &= SYSCON_DEVCFG_U2EN;
++              break;
++      case 2:
++              devcfg &= SYSCON_DEVCFG_U3EN;
++              break;
++      }
++
++      return devcfg ? 1 : 0;
++}
++
++static void ep93xxuart_stop_tx(struct uart_port *port)
++{
++      unsigned long cr = readl(UARTCR(port));
++      cr &= ~UARTCR_TIE;
++      writel(cr, UARTCR(port));
++}
++
++static void ep93xxuart_start_tx(struct uart_port *port)
++{
++      unsigned long cr = readl(UARTCR(port));
++      cr |= UARTCR_TIE;
++      writel(cr, UARTCR(port));
++}
++
++static void ep93xxuart_stop_rx(struct uart_port *port)
++{
++      unsigned long cr = readl(UARTCR(port));
++      cr &= ~(UARTCR_RIE | UARTCR_RTIE);
++      writel(cr, UARTCR(port));
++}
++
++static void ep93xxuart_enable_ms(struct uart_port *port)
++{
++      /* fixme: add an ms mask to a wrapper port struct */
++      if (port->line == 0) {
++              unsigned long cr = readl(UARTCR(port));
++              cr |= UARTCR_MSIE;
++              writel(cr, UARTCR(port));
++      }
++}
++
++#ifdef SUPPORT_SYSRQ
++static void ep93xxuart_rx_chars(struct uart_port *port, struct pt_regs *regs)
++#else
++static void ep93xxuart_rx_chars(struct uart_port *port)
++#endif
++{
++      struct tty_struct *tty = port->info->tty;
++      unsigned long fifo, chr, stat, flg;
++      unsigned int count = 256;
++
++      fifo = readl(UARTFR(port));
++      while (((fifo & UARTFR_RXFE) == 0) && count--) {
++
++              if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
++                      tty->flip.work.func((void *)tty);
++                      if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
++                              printk(KERN_WARNING "TTY_DONT_FLIP set\n");
++                              return;
++                      }
++              }
++
++              chr = readl(UARTDR(port));
++              flg = TTY_NORMAL;
++
++              port->icount.rx++;
++
++              stat = readl(UARTRSR(port)) | UARTRSR_CREAD;
++
++              if (stat & (UARTRSR_FE | UARTRSR_PE | UARTRSR_OE | UARTRSR_BE)) {
++
++                      writel(0, UARTECR(port));
++
++                      if (stat & UARTRSR_BE) {
++                              stat &= ~(UARTRSR_PE | UARTRSR_FE);
++                              port->icount.brk++;
++                              if (uart_handle_break(port))
++                                      goto ignore_char;
++                      } else if (stat & UARTRSR_PE) {
++                              port->icount.parity++;
++                      } else if (stat & UARTRSR_FE) {
++                              port->icount.frame++;
++                      }
++
++                      if (stat & UARTRSR_OE)
++                              port->icount.overrun++;
++
++                      stat &= port->read_status_mask;
++
++                      if (stat & UARTRSR_BE)
++                              flg = TTY_BREAK;
++                      else if (stat & UARTRSR_PE)
++                              flg = TTY_PARITY;
++                      else if (stat & UARTRSR_FE)
++                              flg = TTY_FRAME;
++              }
++
++              if (uart_handle_sysrq_char(port, chr, regs))
++                      goto ignore_char;
++
++              if ((stat & port->ignore_status_mask) == 0) {
++                      *tty->flip.flag_buf_ptr++ = flg;
++                      *tty->flip.char_buf_ptr++ = chr;
++                      tty->flip.count++;
++              }
++
++              if ((stat & UARTRSR_OE) && tty->flip.count < TTY_FLIPBUF_SIZE) {
++                      *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
++                      *tty->flip.char_buf_ptr++ = 0;
++                      tty->flip.count++;
++              }
++
++            ignore_char:
++              fifo = readl(UARTFR(port));
++      }
++      tty_flip_buffer_push(tty);
++}
++
++static void ep93xxuart_tx_chars(struct uart_port *port)
++{
++      struct circ_buf *xmit = &port->info->xmit;
++      int count;
++
++      if (port->x_char) {
++              writel(port->x_char, UARTDR(port));
++              port->icount.tx++;
++              port->x_char = 0;
++              return;
++      }
++      if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
++              ep93xxuart_stop_tx(port);
++              return;
++      }
++
++      count = port->fifosize >> 1;
++      do {
++              writel(xmit->buf[xmit->tail], UARTDR(port));
++              xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++              port->icount.tx++;
++              if (uart_circ_empty(xmit))
++                      break;
++      } while (--count > 0);
++
++      if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++              uart_write_wakeup(port);
++
++      if (uart_circ_empty(xmit))
++              ep93xxuart_stop_tx(port);
++}
++
++static void ep93xxuart_modem_status(struct uart_port *port)
++{
++      unsigned int status = readl(UARTFR(port));
++
++      writel(0, UARTICR(port));
++
++      if (status & UARTMSR_DDCD)
++              uart_handle_dcd_change(port, status & UARTMSR_DCD);
++
++      if (status & UARTMSR_DDSR)
++              port->icount.dsr++;
++
++      if (status & UARTMSR_DCTS)
++              uart_handle_cts_change(port, status & UARTMSR_CTS);
++
++      if (status & (UARTMSR_DDCD | UARTMSR_DDSR | UARTMSR_DCTS))
++              wake_up_interruptible(&port->info->delta_msr_wait);
++}
++
++static irqreturn_t ep93xxuart_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++      struct uart_port *port = dev_id;
++      unsigned int pass_counter = ISR_PASS_LIMIT;
++      int handled = 0;
++      unsigned long iir;
++
++      spin_lock(&port->lock);
++
++      iir = readl(UARTIIR(port));
++
++      if (iir) {
++              do {
++                      if (iir & (UARTIIR_RIS | UARTIIR_RTIS))
++#ifdef SUPPORT_SYSRQ
++                              ep93xxuart_rx_chars(port, regs);
++#else
++                              ep93xxuart_rx_chars(port);
++#endif
++                      if (iir & UARTIIR_TIS)
++                              ep93xxuart_tx_chars(port);
++                      if (iir & UARTIIR_MIS)
++                              ep93xxuart_modem_status(port);
++
++                      if (pass_counter-- == 0)
++                              break;
++
++                      iir = readl(UARTIIR(port));
++
++              } while (iir &
++                       (UARTIIR_RIS | UARTIIR_RTIS | UARTIIR_TIS |
++                        UARTIIR_MIS));
++              handled = 1;
++      }
++
++      spin_unlock(&port->lock);
++
++      return IRQ_RETVAL(handled);
++}
++
++static unsigned int ep93xxuart_tx_empty(struct uart_port *port)
++{
++      unsigned long status = readl(UARTFR(port));
++      return status & UARTFR_TXFE ? 0 : TIOCSER_TEMT; /* FIXME: klaus used UARTFR_BUSY? */
++}
++
++static unsigned int ep93xxuart_get_mctrl(struct uart_port *port)
++{
++      unsigned int result = 0;
++
++      /* fixme: use a wrapper struct w/ ms flags */
++      if (port->line == 0) {
++              unsigned int msr = readl(UARTMSR(port));
++              if (msr & UARTMSR_CTS)
++                      result |= TIOCM_CTS;
++              if (msr & UARTMSR_DSR)
++                      result |= TIOCM_DSR;
++              if (msr & UARTMSR_RI)
++                      result |= TIOCM_RI;
++              if (msr & UARTMSR_DCD)
++                      result |= TIOCM_CAR;
++      }
++      return result;
++}
++
++static void ep93xxuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
++{
++      unsigned long mcr;
++
++      if (port->line == 0) {
++              mcr = readl(UARTMCR(port));
++              if (mctrl & TIOCM_RTS)
++                      mcr |= UARTMCR_RTS;
++              else
++                      mcr &= ~UARTMCR_RTS;
++              if (mctrl & TIOCM_DTR)
++                      mcr |= UARTMCR_DTR;
++              else
++                      mcr &= ~UARTMCR_DTR;
++              if (mctrl & TIOCM_OUT1)
++                      mcr |= UARTMCR_OUT1;
++              else
++                      mcr &= ~UARTMCR_OUT1;
++              if (mctrl & TIOCM_OUT2)
++                      mcr |= UARTMCR_OUT2;
++              else
++                      mcr &= ~UARTMCR_OUT2;
++              writel(mcr, UARTMCR(port));
++      }
++}
++
++/* FIXME: klaus grabbed the &port->lock spinlock here.. */
++static void ep93xxuart_break_ctl(struct uart_port *port, int break_state)
++{
++      unsigned long lch;
++
++      lch = readl(UARTLCH(port));
++      if (break_state)
++              lch |= UARTLCR_H_BRK;
++      else
++              lch &= ~UARTLCR_H_BRK;
++      writel(lch, UARTLCH(port));
++}
++
++static int ep93xxuart_startup(struct uart_port *port)
++{
++      unsigned int uartcr;
++      int retval;
++
++      retval = request_irq(port->irq, ep93xxuart_int, 0, "ep93xxuart", port);
++      if (retval)
++              return retval;
++
++      enable_clocks(port);
++
++      uartcr = readl(UARTCR(port));
++      uartcr |= UARTCR_UARTE | UARTCR_RIE | UARTCR_RTIE;
++      uartcr &= ~0x6;
++      writel(uartcr, UARTCR(port));
++
++      return 0;
++}
++
++static void ep93xxuart_shutdown(struct uart_port *port)
++{
++      unsigned int uartcr;
++      unsigned int linectl;
++
++      linectl = readl(UARTLCH(port));
++      linectl &= ~(UARTLCR_H_FEN | UARTLCR_H_BRK);
++      writel(linectl, UARTLCH(port));
++
++      uartcr = readl(UARTCR(port));
++      uartcr &= ~(UARTCR_UARTE | UARTCR_RIE | UARTCR_RTIE | UARTCR_TIE);
++      writel(uartcr, UARTCR(port));
++
++      disable_clocks(port);
++
++      free_irq(port->irq, port);
++}
++
++static void
++ep93xxuart_set_termios(struct uart_port *port, struct termios *termios,
++                     struct termios *old)
++{
++      unsigned int baud, quot;
++      unsigned long flags;
++      unsigned long lch;
++
++      /* wait for fifo to drain.. is this needed? upper level should handle it.. */
++      if (is_port_enabled(port))
++              do {
++                      flags = readl(UARTFR(port));
++              } while (flags & UARTFR_BUSY);
++
++      baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
++      quot = uart_get_divisor(port, baud);
++
++      switch (termios->c_cflag & CSIZE) {
++      case CS5:
++              lch = UARTLCR_H_WLEN_5_DATA;
++              break;
++      case CS6:
++              lch = UARTLCR_H_WLEN_6_DATA;
++              break;
++      case CS7:
++              lch = UARTLCR_H_WLEN_7_DATA;
++              break;
++      default:
++              lch = UARTLCR_H_WLEN_8_DATA;
++              break;
++      }
++
++      if (termios->c_cflag & CSTOPB)
++              lch |= UARTLCR_H_STP2;
++
++      if (termios->c_cflag & PARENB) {
++              lch |= UARTLCR_H_PEN;
++              if (!(termios->c_cflag & PARODD))
++                      lch |= UARTLCR_H_EPS;
++      }
++
++      if (port->fifosize > 1)
++              lch |= UARTLCR_H_FEN;
++
++      spin_lock_irqsave(&port->lock, flags);
++
++      lch |= readl(UARTLCH(port)) & UARTLCR_H_BRK;
++
++      uart_update_timeout(port, termios->c_cflag, baud);
++
++      port->read_status_mask = UARTRSR_OE;
++      if (termios->c_iflag & INPCK)
++              port->read_status_mask |= UARTRSR_FE | UARTRSR_PE;
++      if (termios->c_iflag & (BRKINT | PARMRK))
++              port->read_status_mask |= UARTRSR_BE;
++
++      port->ignore_status_mask = 0;
++      if (termios->c_iflag & IGNPAR)
++              port->ignore_status_mask |= UARTRSR_FE | UARTRSR_PE;
++      if (termios->c_iflag & IGNBRK) {
++              port->ignore_status_mask |= UARTRSR_BE;
++              if (termios->c_iflag & IGNPAR)
++                      port->ignore_status_mask |= UARTRSR_OE;
++      }
++      if ((termios->c_cflag & CREAD) == 0)
++              port->ignore_status_mask |= UARTRSR_CREAD;
++
++      quot -= 1;
++
++      writel(quot & 0xff, UARTLCL(port));
++      writel((quot >> 8) & 0xff, UARTLCM(port));
++      writel(lch, UARTLCH(port));
++
++      spin_unlock_irqrestore(&port->lock, flags);
++}
++
++static const char *ep93xxuart_type(struct uart_port *port)
++{
++      return port->type == PORT_EP93XX ? "uart-ep93xx" : NULL;
++}
++
++static void ep93xxuart_release_port(struct uart_port *port)
++{
++      /* update when we break up static io_desc maps */
++}
++
++static int ep93xxuart_request_port(struct uart_port *port)
++{
++      /* update when we break up static io_desc maps */
++      return 0;
++}
++
++static void ep93xxuart_config_port(struct uart_port *port, int flags)
++{
++      if (flags & UART_CONFIG_TYPE)
++              if (ep93xxuart_request_port(port) == 0)
++                      port->type = PORT_EP93XX;
++
++      /* FIXME: handle UART_CONFIG_IRQ? */
++}
++
++static int ep93xxuart_verify_port(struct uart_port *port,
++                                struct serial_struct *ser)
++{
++      if (ser->type != PORT_UNKNOWN && ser->type != PORT_EP93XX)
++              return -EINVAL;
++      if (ser->irq < 0 || ser->irq >= NR_IRQS)
++              return -EINVAL;
++      if (ser->baud_base < 9600)
++              return -EINVAL;
++      return 0;
++}
++
++static struct uart_ops ep93xx_pops = {
++      .tx_empty = ep93xxuart_tx_empty,
++      .set_mctrl = ep93xxuart_set_mctrl,
++      .get_mctrl = ep93xxuart_get_mctrl,
++      .stop_tx = ep93xxuart_stop_tx,
++      .start_tx = ep93xxuart_start_tx,
++      .stop_rx = ep93xxuart_stop_rx,
++      .enable_ms = ep93xxuart_enable_ms,
++      .break_ctl = ep93xxuart_break_ctl,
++      .startup = ep93xxuart_startup,
++      .shutdown = ep93xxuart_shutdown,
++      .set_termios = ep93xxuart_set_termios,
++      .type = ep93xxuart_type,
++      .release_port = ep93xxuart_release_port,
++      .request_port = ep93xxuart_request_port,
++      .config_port = ep93xxuart_config_port,
++      .verify_port = ep93xxuart_verify_port,
++};
++
++static struct uart_port ep93xx_ports[UART_NR] = {
++      {
++       .membase = (void *)UART1_BASE,
++       .mapbase = UART1_BASE,
++       .iotype = UPIO_MEM,
++       .irq = IRQ_UART1,
++       .uartclk = EP93XX_UART_CLK,
++       .fifosize = 16,
++       .ops = &ep93xx_pops,
++       .flags = UPF_BOOT_AUTOCONF,
++       },
++      {
++       .membase = (void *)UART2_BASE,
++       .mapbase = UART2_BASE,
++       .iotype = UPIO_MEM,
++       .irq = IRQ_UART2,
++       .uartclk = EP93XX_UART_CLK,
++       .fifosize = 16,
++       .ops = &ep93xx_pops,
++       .line = 1,
++       .flags = UPF_BOOT_AUTOCONF,
++       },
++#if UART_NR > 2
++      {
++       .membase = (void *)UART3_BASE,
++       .mapbase = UART3_BASE,
++       .iotype = UPIO_MEM,
++       .irq = IRQ_UART3,
++       .uartclk = EP93XX_UART_CLK,
++       .fifosize = 16,
++       .ops = &ep93xx_pops,
++       .line = 2,
++       .flags = UPF_BOOT_AUTOCONF,
++       }
++#endif
++};
++
++#ifdef CONFIG_SERIAL_EP93XX_CONSOLE
++/*
++ *    Print a string to the serial port trying not to disturb
++ *    any possible real use of the port...
++ *
++ *    The console_lock must be held when we get here.
++ *
++ *    Note that this is called with interrupts already disabled
++ */
++static void
++ep93xxuart_console_write(struct console *co, const char *s, unsigned int count)
++{
++      struct uart_port *port = ep93xx_ports + co->index;
++      unsigned long cr, cr2, fr;
++      int i;
++
++      /*
++       *  Ensure that the port is enabled.
++       */
++      cr = readl(UARTCR(port));
++      cr2 = cr & ~(UARTCR_RIE | UARTCR_RTIE | UARTCR_TIE | UARTCR_MSIE);
++      writel((cr2 | UARTCR_UARTE), UARTCR(port));
++
++      /*
++       *      Now, do each character
++       */
++      for (i = 0; i < count; i++) {
++              do {
++                      fr = readl(UARTFR(port));
++              } while (fr & UARTFR_TXFF);
++              writel(s[i], UARTDR(port));
++              if (s[i] == '\n') {
++                      do {
++                              fr = readl(UARTFR(port));
++                      } while (fr & UARTFR_TXFF);
++                      writel('\r', UARTDR(port));
++              }
++      }
++
++      /*
++       *      Finally, wait for transmitter to become empty
++       *      and restore the uart state.
++       */
++      do {
++              fr = readl(UARTFR(port));
++      } while ((fr & UARTFR_TXFE) == 0);
++
++      writel(cr, UARTCR(port));
++}
++
++static void __init
++ep93xxuart_console_get_options(struct uart_port *port, int *baud,
++                             int *parity, int *bits)
++{
++      if (readl(UARTCR(port)) & UARTCR_UARTE) {
++              unsigned long lch, quot;
++
++              lch = readl(UARTLCH(port));
++
++              *parity = 'n';
++              if (lch & UARTLCR_H_PEN) {
++                      if (lch & UARTLCR_H_EPS)
++                              *parity = 'e';
++                      else
++                              *parity = 'o';
++              }
++
++              if ((lch & UARTLCR_H_WLEN) == UARTLCR_H_WLEN_7_DATA)
++                      *bits = 7;
++              else
++                      *bits = 8;
++
++              quot =
++                  ((readl(UARTLCM(port)) & 0xff) << 8) | (readl(UARTLCL(port))
++                                                          & 0xff);
++
++              *baud = port->uartclk / (16 * (quot + 1));
++      }
++}
++
++static int __init ep93xxuart_console_setup(struct console *co, char *options)
++{
++      struct uart_port *port;
++      int baud = 57600;
++      int bits = 8;
++      int parity = 'n';
++      int flow = 'n';
++
++      /*
++       * Check whether an invalid uart number has been specified, and
++       * if so, search for the first available port that does have
++       * console support.
++       */
++      port = uart_get_console(ep93xx_ports, UART_NR, co);
++
++      /*
++       * Temporary fix.
++       */
++      spin_lock_init(&port->lock);
++
++      if (options)
++              uart_parse_options(options, &baud, &parity, &bits, &flow);
++      else
++              ep93xxuart_console_get_options(port, &baud, &parity, &bits);
++
++      return uart_set_options(port, co, baud, parity, bits, flow);
++}
++
++extern struct uart_driver ep93xx_reg;
++static struct console ep93xx_console = {
++      .name = "ttyAM",
++      .write = ep93xxuart_console_write,
++      .device = uart_console_device,
++      .setup = ep93xxuart_console_setup,
++      .flags = CON_PRINTBUFFER,
++      .index = -1,
++      .data = &ep93xx_reg,
++};
++
++static int __init ep93xxuart_console_init(void)
++{
++      register_console(&ep93xx_console);
++      return 0;
++}
++
++console_initcall(ep93xxuart_console_init);
++
++#define EP93XX_CONSOLE        &ep93xx_console
++#else
++#define EP93XX_CONSOLE        NULL
++#endif
++
++static struct uart_driver ep93xx_reg = {
++      .driver_name = "ttyAM",
++      .dev_name = "ttyAM",
++      .major = SERIAL_EP93XX_MAJOR,
++      .minor = SERIAL_EP93XX_MINOR,
++      .nr = UART_NR,
++      .cons = EP93XX_CONSOLE,
++};
++
++static int ep93xxuart_probe(struct amba_device *dev, void *id)
++{
++      int i;
++
++      for (i = 0; i < UART_NR; i++) {
++              if (ep93xx_ports[i].membase != (void *)dev->res.start)
++                      continue;
++
++              ep93xx_ports[i].dev = &dev->dev;
++              uart_add_one_port(&ep93xx_reg, &ep93xx_ports[i]);
++              amba_set_drvdata(dev, &ep93xx_ports[i]);
++              break;
++      }
++
++      return 0;
++}
++
++static int ep93xxuart_remove(struct amba_device *dev)
++{
++      struct uart_port *p = amba_get_drvdata(dev);
++
++      if (p)
++              uart_remove_one_port(&ep93xx_reg, p);
++
++      amba_set_drvdata(dev, NULL);
++
++      return 0;
++}
++
++static int ep93xxuart_suspend(struct amba_device *dev, pm_message_t msg)
++{
++      struct uart_port *p = amba_get_drvdata(dev);
++
++      if (p)
++              uart_suspend_port(&ep93xx_reg, p);
++
++      return 0;
++}
++
++static int ep93xxuart_resume(struct amba_device *dev)
++{
++      struct uart_port *p = amba_get_drvdata(dev);
++
++      if (p)
++              uart_resume_port(&ep93xx_reg, p);
++
++      return 0;
++}
++
++static struct amba_id ep93xxuart_ids[] __initdata = {
++      {                       /* UART1 */
++       .id = 0x808c0000,
++       .mask = 0xffff0000,
++       },
++      {                       /* UART2 */
++       .id = 0x808d0000,
++       .mask = 0xffff0000,
++       },
++      {                       /* UART3 */
++       .id = 0x808e0000,
++       .mask = 0xffff0000,
++       },
++      {0, 0},
++};
++
++static struct amba_driver ep93xxuart_driver = {
++      .drv = {
++              .name = "uart-ep93xx",
++              },
++      .id_table = ep93xxuart_ids,
++      .probe = ep93xxuart_probe,
++      .remove = ep93xxuart_remove,
++      .suspend = ep93xxuart_suspend,
++      .resume = ep93xxuart_resume,
++};
++
++static int __init ep93xxuart_init(void)
++{
++      int ret;
++
++      printk(KERN_INFO "Serial: EP93xx driver $Revision: 1.42 $\n");
++
++      ret = uart_register_driver(&ep93xx_reg);
++      if (ret == 0) {
++              ret = amba_driver_register(&ep93xxuart_driver);
++              if (ret)
++                      uart_unregister_driver(&ep93xx_reg);
++      }
++
++      return ret;
++}
++
++static void __exit ep93xxuart_exit(void)
++{
++      amba_driver_unregister(&ep93xxuart_driver);
++      uart_unregister_driver(&ep93xx_reg);
++}
++
++module_init(ep93xxuart_init);
++module_exit(ep93xxuart_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi");
++MODULE_DESCRIPTION("EP93XX generic serial driver $Revision: 1.42 $");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
+index 85dacc9..e57292f 100644
+--- a/drivers/usb/Kconfig
++++ b/drivers/usb/Kconfig
+@@ -22,6 +22,7 @@ config USB_ARCH_HAS_OHCI
+       default y if ARCH_LH7A404
+       default y if ARCH_S3C2410
+       default y if PXA27x
++      default y if ARCH_EP93XX
+       # PPC:
+       default y if STB03xxx
+       default y if PPC_MPC52xx
+diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
+new file mode 100644
+index 0000000..8aec2fb
+--- /dev/null
++++ b/drivers/usb/host/ohci-ep93xx.c
+@@ -0,0 +1,248 @@
++/*
++ * OHCI HCD (Host Controller Driver) for USB.
++ *
++ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
++ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
++ * (C) Copyright 2002 Hewlett-Packard Company
++ * (C) Copyright 2004 Ray Lehtiniemi
++ *
++ * EP93XX Bus Glue
++ *
++ * Written by Ray Lehtiniemi <rayl@mail.com>
++ * Based on SA-1111 glue.
++ *
++ * This file is licenced under the GPL.
++ */
++
++#include <asm/hardware.h>
++#include <asm/hardware/amba.h>
++
++#ifndef CONFIG_ARCH_EP93XX
++#error "This file is EP93xx bus glue.  CONFIG_ARCH_EP93XX must be defined."
++#endif
++
++extern int usb_disabled(void);
++
++
++/*-------------------------------------------------------------------------*/
++
++static void ep93xx_start_hc(struct amba_device *dev)
++{
++      unsigned int pwrcnt;
++
++      printk(KERN_DEBUG __FILE__ ": starting EP93xx OHCI USB Controller\n");
++
++      pwrcnt = readl(SYSCON_PWRCNT);
++      pwrcnt |= SYSCON_PWRCNT_USHEN;
++      writel(pwrcnt, SYSCON_PWRCNT);
++}
++
++static void ep93xx_stop_hc(struct amba_device *dev)
++{
++      unsigned int pwrcnt;
++
++      printk(KERN_DEBUG __FILE__ ": stopping EP93xx OHCI USB Controller\n");
++
++      pwrcnt = readl(SYSCON_PWRCNT);
++      pwrcnt &= ~SYSCON_PWRCNT_USHEN;
++      writel(pwrcnt, SYSCON_PWRCNT);
++}
++
++/*-------------------------------------------------------------------------*/
++
++#if 0
++static void dump_hci_status(struct usb_hcd *hcd, const char *label)
++{
++      unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
++
++      dbg("%s USB_STATUS = { %s%s%s%s%s}", label,
++          ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""),
++          ((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""),
++          ((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "),
++          ((status & USB_STATUS_NHCIMFCLR) ? "" : "HCIMFCLR "),
++          ((status & USB_STATUS_USBPWRSENSE) ? "USBPWRSENSE " : ""));
++}
++#endif
++
++/*-------------------------------------------------------------------------*/
++
++void usb_hcd_ep93xx_remove(struct usb_hcd *, struct amba_device *);
++
++/* configure so an HC device and id are always provided */
++/* always called with process context; sleeping is OK */
++
++/**
++ * usb_hcd_ep93xx_probe - initialize ep93xx HCD
++ * Context: !in_interrupt()
++ *
++ * Allocates basic resources for this USB host controller, and
++ * then invokes the start() method for the HCD associated with it
++ * through the hotplug entry's driver_data.
++ *
++ * Store this function in the HCD's struct pci_driver as probe().
++ */
++int usb_hcd_ep93xx_probe(const struct hc_driver *driver,
++                       struct amba_device *dev)
++{
++      int retval;
++      struct usb_hcd *hcd;
++
++      hcd = usb_create_hcd(driver, &dev->dev, "ep93xx");
++
++      if (!hcd)
++              return -ENOMEM;
++
++      hcd->rsrc_start = dev->res.start;
++      hcd->rsrc_len = dev->res.end - dev->res.start + 1;
++
++      hcd->regs = (void __iomem *)dev->res.start;
++
++      ep93xx_start_hc(dev);
++      ohci_hcd_init(hcd_to_ohci(hcd));
++
++      retval = usb_add_hcd(hcd, dev->irq[0], SA_INTERRUPT);
++      if (retval == 0)
++              return retval;
++
++      ep93xx_stop_hc(dev);
++
++      usb_put_hcd(hcd);
++      return retval;
++}
++
++/* may be called without controller electrically present */
++/* may be called with controller, bus, and devices active */
++
++/**
++ * usb_hcd_ep93xx_remove - shutdown processing for SA-1111-based HCDs
++ * @dev: USB Host Controller being removed
++ * Context: !in_interrupt()
++ *
++ * Reverses the effect of usb_hcd_ep93xx_probe(), first invoking
++ * the HCD's stop() method.  It is always called from a thread
++ * context, normally "rmmod", "apmd", or something similar.
++ *
++ */
++void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, struct amba_device *dev)
++{
++      usb_remove_hcd(hcd);
++      ep93xx_stop_hc(dev);
++      usb_put_hcd(hcd);
++}
++
++/*-------------------------------------------------------------------------*/
++
++static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd)
++{
++      struct ohci_hcd *ohci = hcd_to_ohci(hcd);
++      int ret;
++
++      ohci_dbg(ohci, "ohci_ep93xx_start, ohci:%p", ohci);
++
++      if ((ret = ohci_init(ohci)) < 0)
++              return ret;
++
++      if ((ret = ohci_run(ohci)) < 0) {
++              err("can't start %s", hcd->self.bus_name);
++              ohci_stop(hcd);
++              return ret;
++      }
++
++      return 0;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static const struct hc_driver ohci_ep93xx_hc_driver = {
++      .description = hcd_name,
++      .product_desc = "EP93xx OHCI",
++      .hcd_priv_size = sizeof(struct ohci_hcd),
++
++      /*
++       * generic hardware linkage
++       */
++      .irq = ohci_irq,
++      .flags = HCD_USB11,
++
++      /*
++       * basic lifecycle operations
++       */
++      .start = ohci_ep93xx_start,
++#ifdef        CONFIG_PM
++      /* suspend:             ohci_ep93xx_suspend,  -- tbd */
++      /* resume:              ohci_ep93xx_resume,   -- tbd */
++#endif
++      .stop = ohci_stop,
++
++      /*
++       * managing i/o requests and associated device resources
++       */
++      .urb_enqueue = ohci_urb_enqueue,
++      .urb_dequeue = ohci_urb_dequeue,
++      .endpoint_disable = ohci_endpoint_disable,
++
++      /*
++       * scheduling support
++       */
++      .get_frame_number = ohci_get_frame,
++
++      /*
++       * root hub support
++       */
++      .hub_status_data = ohci_hub_status_data,
++      .hub_control = ohci_hub_control,
++};
++
++/*-------------------------------------------------------------------------*/
++
++static int ep93xxohci_probe(struct amba_device *dev, void *id)
++{
++      int ret = -ENODEV;
++
++      if (usb_disabled())
++              return -ENODEV;
++
++      ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, dev);
++
++      return ret;
++}
++
++static int ep93xxohci_remove(struct amba_device *dev)
++{
++      struct usb_hcd *hcd = amba_get_drvdata(dev);
++
++      usb_hcd_ep93xx_remove(hcd, dev);
++
++      return 0;
++}
++
++static struct amba_id ep93xxohci_ids[] __initdata = {
++      {
++       .id = 0x80020000,
++       .mask = 0xffff0000,
++       },
++      {0, 0},
++};
++
++static struct amba_driver ep93xxohci_driver = {
++      .drv = {
++              .name = "ohci-ep93xx",
++              },
++      .id_table = ep93xxohci_ids,
++      .probe = ep93xxohci_probe,
++      .remove = ep93xxohci_remove,
++};
++
++static int __init ep93xxohci_init(void)
++{
++      printk(KERN_INFO "USB: EP93xx driver $Revision: 1.42 $\n");
++      return amba_driver_register(&ep93xxohci_driver);
++}
++
++static void __exit ep93xxohci_cleanup(void)
++{
++      amba_driver_unregister(&ep93xxohci_driver);
++}
++
++module_init(ep93xxohci_init);
++module_exit(ep93xxohci_cleanup);
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index bf1d9ab..bb525a2 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -909,6 +909,10 @@ MODULE_LICENSE ("GPL");
+ #include "ohci-pxa27x.c"
+ #endif
++#ifdef CONFIG_ARCH_EP93XX
++#include "ohci-ep93xx.c"
++#endif
++
+ #ifdef CONFIG_SOC_AU1X00
+ #include "ohci-au1xxx.c"
+ #endif
+@@ -923,6 +927,7 @@ MODULE_LICENSE ("GPL");
+       || defined(CONFIG_ARCH_OMAP) \
+       || defined (CONFIG_ARCH_LH7A404) \
+       || defined (CONFIG_PXA27x) \
++      || defined (CONFIG_ARCH_EP93XX) \
+       || defined (CONFIG_SOC_AU1X00) \
+       || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
+       )
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index cc8e3bf..1d46ab0 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -172,6 +172,122 @@ config FB_CLPS711X
+         Say Y to enable the Framebuffer driver for the CLPS7111 and
+         EP7212 processors.
++config FB_CX25871_I2C
++      tristate "Conexant CX25871 video encoder"
++      depends on I2C && EXPERIMENTAL
++      help
++
++        ! ! !   B R O K E N   B R O K E N   B R O K E N   ! ! !
++
++        If you say yes here you get support for the Conexant CX25871
++        video encoder. Currently only EP93xx CPUs use this for some
++        NTSC setup. This setup should be done in ep93xxfb.c instead.
++        It is currently hardcoded here in cx25871, which is wrong, as
++        it will happen anytime instead of exactly when it is needed.
++        I've got no NTSC hardware, and no time to test this either.
++
++        Why I've written it then? Well I had to get I2C working and it
++        helped me on my way there.
++
++        If nobody cares about NTSC support for EP93xx it will go away soon!
++
++        Only say Y if you have such a chip and are prepared to fix the remaining
++        stuff yourself.
++
++        See ep93xxfb.[ch] and cx25871.c for details.
++
++        This driver can also be built as a module.  If so, the module
++        will be called cx25871.
++
++config FB_EP93XX
++      bool "EP93XX Framebuffer support"
++      depends on FB && ARM && (ARCH_EP9312 || ARCH_EP9315)
++      select FB_CFB_FILLRECT
++      select FB_CFB_COPYAREA
++      select FB_CFB_IMAGEBLIT
++      help
++        Say Y here if you want support for the on EP93XX framebuffer.
++
++        You can also say M here to compile this as a module. However this
++        is not recommended as loading the module without a display can
++        be a problem. (Make sure you can login without display before you
++        say M or N here).
++
++        The module will be called ep93xxfb.
++choice
++      prompt "Display Type"
++      depends on FB_EP93XX
++      help
++        Choose the kind of display you want to attach to the EP93XX framebuffer.
++
++config FB_CRT_EP93XX
++      bool "CRT Display"
++
++config FB_LCD_EP93XX
++      bool "LCD Display"
++      help
++        Support for the Philips 640x480 Display on the EDB93XX evaluation board.
++
++config FB_LCD_EP93XX_SHARP
++      bool "LCD Display 320x200 SHARP"
++      help
++        Support for the Sharp LQ057Q3DC02 320x200 Color TFT LCD.
++
++config FB_LCD_EP93XX_SHARP_LQ64D343
++      bool "LCD Display 640x480 SHARP"
++      help
++        Support for the Sharp LQ64D343 640x480 Color TFT LCD.
++
++config FB_CX25871
++      bool "NTSC Display"
++      select FB_CX25871_I2C
++
++config FB_LCD_TX09D50VM1CCA
++      bool "LCD Display 240x320 Hitachi TX09D50VM1CCA"
++      help
++        Support for the Hitachi TX09D50VM1CCA 240x320 Color TFT LCD.
++
++endchoice
++
++choice
++      prompt "Display Color Depth"
++      depends on FB_EP93XX
++      default FB_EP93XX_8BPP
++      help
++        Choose the default color depth for you EP93xx display. Note that using
++        other than 8BPP depths tends to be slow.
++
++config FB_EP93XX_8BPP
++      bool "8bpp"
++      help
++        Use 8 bits per pixel (256 color).
++        Benefits: fastest available mode
++        Drawback: few colors available (might do for console work, though)
++
++config FB_EP93XX_16BPP_565
++      bool "16bpp_565"
++      help
++        Use 16 bits per pixel. Weighting red:green:blue is 5:6:5 bits.
++        Make sure your Xserver / Framebuffer based applications use exactly this
++        weighting.
++
++config FB_EP93XX_24BPP
++      bool "24bpp"
++      help
++        Use 24 bits per pixel. Weighting red:green:blue is 8:8:8 bits. Say Y here
++        if you want lots of colors and do not care that much about performance.
++
++
++
++config FB_EP93XX_32BPP
++      bool "32bpp"
++      help
++        Use 32 bits per pixel. Weighting transparent:red:green:blue is 8:8:8:8 bits.
++        Note that transparency is seldom implemented so this one is just slower and
++        consumes more memory than 24BPP.
++endchoice
++
++
+ config FB_SA1100
+       bool "SA-1100 LCD support"
+       depends on (FB = y) && ARM && ARCH_SA1100
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index aa434e7..82f680b 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -99,6 +99,8 @@ obj-$(CONFIG_FB_S3C2410)       += s3c2410fb.
+ obj-$(CONFIG_FB_VESA)             += vesafb.o
+ obj-$(CONFIG_FB_VGA16)            += vga16fb.o vgastate.o
+ obj-$(CONFIG_FB_OF)               += offb.o
++obj-$(CONFIG_FB_EP93XX)            += ep93xxfb.o
++obj-$(CONFIG_FB_CX25871_I2C)       += cx25871.o
+ # the test framebuffer is last
+ obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
+diff --git a/drivers/video/cx25871.c b/drivers/video/cx25871.c
+new file mode 100644
+index 0000000..816cbef
+--- /dev/null
++++ b/drivers/video/cx25871.c
+@@ -0,0 +1,200 @@
++/*
++    cx25871.c
++
++    Driver for the Conexant CX25871 VIDEO ENCODER
++
++    based on: ds1621.c
++
++
++
++
++    BIG FAT WARNING: THIS IS EXPERIMENTAL AND UNTESTED CODE
++
++
++
++
++
++
++    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 <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <asm/io.h>
++
++/*
++ * assign an invalid (local use) id for now
++ * TODO: get an official one!
++ */
++#define I2C_DRIVERID_EP93XX 0xffff
++
++/* Addresses to scan */
++static unsigned short normal_i2c[] = { 0x44, I2C_CLIENT_END };
++static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
++
++I2C_CLIENT_INSMOD;
++
++static int cx25871_attach_adapter(struct i2c_adapter *adapter);
++static int cx25871_detect(struct i2c_adapter *adapter, int address, int kind);
++static void cx25871_init_client(struct i2c_client *client);
++static int cx25871_detach_client(struct i2c_client *client);
++
++/* This is the driver that will be inserted */
++static struct i2c_driver cx25871_driver = {
++      .owner = THIS_MODULE,
++      .name = "cx25871",
++      .id = I2C_DRIVERID_EP93XX,
++      .flags = I2C_DF_NOTIFY,
++      .attach_adapter = cx25871_attach_adapter,
++      .detach_client = cx25871_detach_client,
++};
++
++static int cx25871_id = 0;
++
++/* Cleanup and introduce cx25871 specific data, if necessary */
++struct cx25871_data {
++      struct i2c_client client;
++      struct semaphore update_lock;
++      char valid;             /* !=0 if following fields are valid */
++      unsigned long last_updated;     /* In jiffies */
++};
++
++static int cx25871_read_value(struct i2c_client *client, u8 reg)
++{
++      return i2c_smbus_read_byte_data(client, reg);
++}
++
++static int cx25871_write_value(struct i2c_client *client, u8 reg, u16 value)
++{
++      return i2c_smbus_write_byte_data(client, reg, value);
++}
++
++static void cx25871_init_client(struct i2c_client *client)
++{
++      /*FIXME: This should be done in ep93xxfb.c, shouldn't it? */
++
++      int _todo__fix_this_ugly_hack_;
++
++      cx25871_write_value(client, 0xB8, 0);
++      mdelay(1000);
++      /* After auto-configuration, setup pseudo-master mode BUT with EN_BLANKO bit cleared */
++      cx25871_write_value(client, 0xBA,
++                          CX25871_REGxBA_SLAVER | CX25871_REGxBA_DACOFF);
++      cx25871_write_value(client, 0xC6, (CX25871_REGxC6_INMODE_MASK & 0x3));
++      cx25871_write_value(client, 0xC4, CX25871_REGxC4_EN_OUT);
++      cx25871_write_value(client, 0x32, 0);
++      cx25871_write_value(client, 0xBA, CX25871_REGxBA_SLAVER);
++}
++
++static int cx25871_attach_adapter(struct i2c_adapter *adapter)
++{
++      printk("cx25871_attach_adapter\n");
++      return i2c_probe(adapter, &addr_data, cx25871_detect);
++}
++
++/* This function is called by i2c_detect */
++int cx25871_detect(struct i2c_adapter *adapter, int address, int kind)
++{
++      struct i2c_client *new_client;
++      struct cx25871_data *data;
++      int err = 0;
++
++      if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
++                                   | I2C_FUNC_SMBUS_WRITE_BYTE))
++              goto exit;
++
++      /* OK. For now, we presume we have a valid client. We now create the
++         client structure, even though we cannot fill it completely yet.
++         But it allows us to access cx25871_{read,write}_value. */
++      if (!(data = kmalloc(sizeof(struct cx25871_data), GFP_KERNEL))) {
++              err = -ENOMEM;
++              goto exit;
++      }
++      memset(data, 0, sizeof(struct cx25871_data));
++
++      new_client = &data->client;
++      i2c_set_clientdata(new_client, data);
++      new_client->addr = address;
++      new_client->adapter = adapter;
++      new_client->driver = &cx25871_driver;
++      new_client->flags = 0;
++
++      /* Fill in remaining client fields and put it into the global list */
++      strlcpy(new_client->name, "cx25871", I2C_NAME_SIZE);
++
++      new_client->id = cx25871_id++;
++      data->valid = 0;
++      init_MUTEX(&data->update_lock);
++
++      /* Tell the I2C layer a new client has arrived */
++      if ((err = i2c_attach_client(new_client)))
++              goto exit_free;
++      /* Initialize the EP93XX chip */
++      cx25871_init_client(new_client);
++
++/* Register sysfs hooks */
++#if 0
++      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);
++#endif
++      return 0;
++
++/* OK, this is not exactly good programming practice, usually. But it is
++   very code-efficient in this case. */
++      exit_free:
++      kfree(data);
++      exit:
++      return err;
++}
++
++static int cx25871_detach_client(struct i2c_client *client)
++{
++      int err;
++
++      if ((err = i2c_detach_client(client))) {
++              dev_err(&client->dev, "Client deregistration failed, "
++                      "client not detached.\n");
++              return err;
++      }
++
++      kfree(i2c_get_clientdata(client));
++
++      return 0;
++}
++
++static int __init cx25871_init(void)
++{
++      printk("cx25871_init\n");
++      return i2c_add_driver(&cx25871_driver);
++}
++
++static void __exit cx25871_exit(void)
++{
++      i2c_del_driver(&cx25871_driver);
++}
++
++MODULE_DESCRIPTION("Conexant CX25871 video encoder");
++MODULE_LICENSE("GPL");
++
++module_init(cx25871_init);
++module_exit(cx25871_exit);
+diff --git a/drivers/video/ep93xxfb.c b/drivers/video/ep93xxfb.c
+new file mode 100644
+index 0000000..475943a
+--- /dev/null
++++ b/drivers/video/ep93xxfb.c
+@@ -0,0 +1,787 @@
++/******************************************************************************
++ *
++ *  File:     linux/drivers/video/ep93xxfb.c
++ *
++ *  Purpose: Framebuffer driver for EP9312/EP9315 evaluation board.
++ *
++ *  based on:
++ *           skeletonfb.c
++ *           ep93xxfb.c from Linux 2.4.21-rmk1-cirrus-1-3-0
++ *
++ *******************************************************************************/
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#include <linux/mm.h>
++#include <linux/tty.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/fb.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/mach-types.h>
++#include <asm/uaccess.h>
++#include <asm/pgtable.h>
++
++#include "ep93xxfb.h"
++
++/*
++#define DEBUG
++#define USE_PRINTASCII
++*/
++
++#ifdef DEBUG
++#  if defined(CONFIG_DEBUG_LL) && defined(USE_PRINTASCII)
++extern void printascii(const char *);
++#    define DPRINTK(fmt, args...) {char str[256];sprintf(str, "%s: " fmt, __FUNCTION__ , ## args);printascii(str);}
++#  else
++#    define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
++#  endif
++#else
++#  define DPRINTK(fmt, args...)
++#endif
++
++static struct fb_info info;
++static struct fb_fix_screeninfo ep93xxfb_fix;
++static struct fb_var_screeninfo ep93xxfb_var;
++static struct ep93xxfb_par ep93xxfb_par;
++static unsigned int pseudo_palette[MAX_PALETTE_NUM_ENTRIES];
++
++int __init ep93xxfb_init(void);
++static int ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
++                            unsigned blue, unsigned transp,
++                            struct fb_info *info);
++static int ep93xxfb_blank(int blank_mode, struct fb_info *info);
++int __init ep93xxfb_init(void);
++static void __exit ep93xxfb_cleanup(void);
++int __init ep93xxfb_setup(char *options);
++
++static struct fb_ops ep93xxfb_ops = {
++      .owner = THIS_MODULE,
++      .fb_setcolreg = ep93xxfb_setcolreg,
++      .fb_blank = ep93xxfb_blank,
++      .fb_fillrect = cfb_fillrect,
++      .fb_copyarea = cfb_copyarea,
++      .fb_imageblit = cfb_imageblit,
++};
++
++/*
++ * ep93xxfb_palette_write:
++ *    Encode palette data to 24bit palette format.
++ *      Write palette data to the master palette and inactive hw palette
++ *    switch palettes.  And handle asynchronous palette switches.
++ */
++static inline void
++ep93xxfb_palette_write(u_int regno, u_int red, u_int green,
++                     u_int blue, u_int trans)
++{
++      unsigned int cont, i, pal;
++
++      /* Only supports color LUT, not gray LUT
++       *
++       *  TBD if not in 4 or 8bpp, then does LUT logic operate?
++       *  TBD or do we need to do nothing here?
++       *
++       * LCD:     TBD RGB mapping may match spec p193.
++       *
++       * CRT: LUT RGB mapping is really R/G/B from high to low bits
++       *  because really determined by wiring to video DAC.
++       *  (disregard spec p 193 showing color LUT B/G/R order)
++       *  Here are the details:
++       *
++       *  Shift mode 1 directs LUT bits 7-2 onto P5-P0,
++       *  LUT bits 15-10 onto P11-P6, and LUT bits 23-16
++       *  onto P17-P12.
++       *
++       *  Board wired P17-12 to video DAC Red inputs,
++       *  P11-P6 wired to video DAC Green inputs, and
++       *  P5-P0 wired to video DAC Blue inputs.
++       */
++      pal = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
++
++      pseudo_palette[regno] = pal;
++
++      /* Two cases here:
++       * 1.       If LUT switch is pending, then write inactive LUT and when
++       *  switch happens, this new palette entry will be active.
++       *  Race condition here between LUT switch and this write is okay
++       *  since we fix it below.
++       *
++       * 2.       If LUT switch is not pending, then write here is incomplete
++       *  and whole palette will be written below.
++       */
++
++      writel(pal, COLOR_LUT + (regno << 2));
++
++      cont = readl(LUTCONT);
++
++      if ((cont & LUTCONT_STAT && cont & LUTCONT_RAM1) ||
++          (!(cont & LUTCONT_STAT) && !(cont & LUTCONT_RAM1))) {
++              /* LUT switch is no longer pending
++               *
++               * We do not know if write to LUT above really went
++               * to currently active LUT.  So need to make sure that
++               * data gets into inactive LUT and switch LUTs.
++               *
++               * But currently inactive LUT may be out of date
++               * in more entries than just last write.
++               * Need to update currently inactive LUT for all writes
++               * which went to currently active LUT.
++               * Fully update the LUT now, which is a simpler policy
++               * than trying to track writes and do partial update of LUT.
++               * (Worstcase impact: we update palette every frame)
++               */
++
++              for (i = 0; i < 256; i++)       // Update inactive LUT
++              {
++                      writel(pseudo_palette[i],
++                             (COLOR_LUT + (i << 2)));
++              }
++              /* Switch active LUTs next frame */
++              writel(cont ^ LUTCONT_RAM1, LUTCONT);
++      }
++}
++
++/**
++ *    xxxfb_setcolreg - Optional function. Sets a color register.
++ *      @regno: Which register in the CLUT we are programming
++ *      @red: The red value which can be up to 16 bits wide
++ *    @green: The green value which can be up to 16 bits wide
++ *    @blue:  The blue value which can be up to 16 bits wide.
++ *    @transp: If supported the alpha value which can be up to 16 bits wide.
++ *      @info: frame buffer info structure
++ *
++ *    Set a single color register. The values supplied have a 16 bit
++ *    magnitude which needs to be scaled in this function for the hardware.
++ *    Things to take into consideration are how many color registers, if
++ *    any, are supported with the current color visual. With truecolor mode
++ *    no color palettes are supported. Here a psuedo palette is created
++ *    which we store the value in pseudo_palette in struct fb_info. For
++ *    pseudocolor mode we have a limited color palette. To deal with this
++ *    we can program what color is displayed for a particular pixel value.
++ *    DirectColor is similar in that we can program each color field. If
++ *    we have a static colormap we don't need to implement this function.
++ *
++ *    Returns negative errno on error, or zero on success.
++ */
++static int
++ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
++                 unsigned transp, struct fb_info *info)
++{
++      if (regno >= MAX_PALETTE_NUM_ENTRIES)   /* no. of hw registers */
++              return 1;
++      /*
++       * Program hardware... do anything you want with transp
++       */
++
++      /* grayscale works only partially under directcolor */
++      if (info->var.grayscale) {
++              /* grayscale = 0.30*R + 0.59*G + 0.11*B */
++              red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
++      }
++
++      /* Directcolor:
++       *   var->{color}.offset contains start of bitfield
++       *   var->{color}.length contains length of bitfield
++       *   {hardwarespecific} contains width of DAC
++       *   cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
++       *   RAMDAC[X] is programmed to (red, green, blue)
++       *
++       * Pseudocolor:
++       *    uses offset = 0 && length = DAC register width.
++       *    var->{color}.offset is 0
++       *    var->{color}.length contains widht of DAC
++       *    cmap is not used
++       *    DAC[X] is programmed to (red, green, blue)
++       * Truecolor:
++       *    does not use RAMDAC (usually has 3 of them).
++       *    var->{color}.offset contains start of bitfield
++       *    var->{color}.length contains length of bitfield
++       *    cmap is programmed to (red << red.offset) | (green << green.offset) |
++       *                      (blue << blue.offset) | (transp << transp.offset)
++       *    RAMDAC does not exist
++       */
++#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
++
++      switch (info->fix.visual) {
++      case FB_VISUAL_PSEUDOCOLOR:
++              /* Feed the dual 256x24 hardware LUT */
++              ep93xxfb_palette_write(regno, red, green, blue, transp);
++              break;
++      case FB_VISUAL_TRUECOLOR:
++              /* Truecolor has hardware independent palette */
++              if (regno >= 16)
++                      return 1;
++
++              red = CNVT_TOHW(red, info->var.red.length);
++              green = CNVT_TOHW(green, info->var.green.length);
++              blue = CNVT_TOHW(blue, info->var.blue.length);
++              transp = CNVT_TOHW(transp, info->var.transp.length);
++              ((u32 *) (info->pseudo_palette))[regno] =
++                  (red << info->var.red.offset) |
++                  (green << info->var.green.offset) |
++                  (blue << info->var.blue.offset) |
++                  (transp << info->var.transp.offset);
++              break;
++      case FB_VISUAL_DIRECTCOLOR:
++              /* example here assumes 8 bit DAC. Might be different
++               * for your hardware */
++              red = CNVT_TOHW(red, 8);
++              green = CNVT_TOHW(green, 8);
++              blue = CNVT_TOHW(blue, 8);
++              /* hey, there is bug in transp handling... */
++              transp = CNVT_TOHW(transp, 8);
++              break;
++      }
++#undef CNVT_TOHW
++
++      return 0;
++}
++
++/**
++ *      xxxfb_blank - NOT a required function. Blanks the display.
++ *      @blank_mode: the blank mode we want.
++ *      @info: frame buffer structure that represents a single frame buffer
++ *
++ *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
++ *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a
++ *      video mode which doesn't support it. Implements VESA suspend
++ *      and powerdown modes on hardware that supports disabling hsync/vsync:
++ *      blank_mode == 2: suspend vsync
++ *      blank_mode == 3: suspend hsync
++ *      blank_mode == 4: powerdown
++ *
++ *      Returns negative errno on error, or zero on success.
++ *
++ */
++static int ep93xxfb_blank(int blank_mode, struct fb_info *info)
++{
++#ifdef CONFIG_MACH_ADSSPHERE
++      void adssphere_blank(int blank_mode);
++
++      adssphere_blank(blank_mode);
++#endif
++
++      return 1;
++}
++
++static struct device ep93xxfb_device = {
++      .bus_id = "ep93xxfb",
++      .coherent_dma_mask = 0xffffffff,
++};
++
++/*
++ * ep9312fb_map_video_memory():
++ *      Allocates the DRAM memory for the frame buffer.  This buffer is
++ *    remapped into a non-cached, non-buffered, memory region to
++ *      allow palette and pixel writes to occur without flushing the
++ *      cache.  Once this area is remapped, all virtual memory
++ *      access to the video memory should occur at the new region.
++ */
++static int
++__init ep9312fb_map_video_memory(void)
++{
++      dma_addr_t handle;
++
++      ep93xxfb_par.dev = &ep93xxfb_device;
++
++      ep93xxfb_par.v_screen_base = dma_alloc_writecombine(ep93xxfb_par.dev,
++                                                          FB_MAPPED_MEM_SIZE,
++                                                          &handle,
++                                                          GFP_KERNEL);
++
++      if (ep93xxfb_par.v_screen_base == NULL) {
++              printk(KERN_ERR "ep93xxfb: unable to allocate screen memory\n");
++              return -ENOMEM;
++      }
++
++      info.screen_base = ep93xxfb_par.v_screen_base;
++      info.fix.smem_start = (unsigned int)ep93xxfb_par.p_screen_base = handle;
++      info.fix.smem_len = FB_MAPPED_MEM_SIZE;
++
++      return 0;
++}
++
++static int ep93xxfb_probe_configuration(void)
++{
++      int xres, yres, bpp, pixelmode, total;
++      unsigned char lookup_bpp[] = {-1, -1, 8, -1, 16, -1, 24, 32};
++
++      pixelmode = readl(PIXELMODE);
++
++      bpp = lookup_bpp[PIXELMODE_P_MASK & pixelmode];
++
++      if (bpp < 0) return 0;
++
++      yres = readl(SCRNLINES);
++
++      if (yres == 0) return 0;
++
++      xres = (32 * readl(VLINESTEP)) / bpp;
++
++      if (xres == 0) return 0;
++
++      info.node = -1;
++      info.flags = FBINFO_FLAG_DEFAULT;
++
++      info.fix = ep93xxfb_fix;
++      info.var = ep93xxfb_var;
++      info.fbops = &ep93xxfb_ops;
++      info.pseudo_palette = pseudo_palette;
++
++      info.monspecs = monspecs;
++
++      strcpy(info.fix.id, "Cirrus EP93xx");
++      info.fix.type = FB_TYPE_PACKED_PIXELS;
++      info.fix.xpanstep = 0;
++      info.fix.ypanstep = 0;
++      info.fix.ywrapstep = 0;
++      info.fix.accel = FB_ACCEL_NONE;
++
++      info.var.xres = xres;
++      info.var.yres = yres;
++      info.var.xres_virtual = xres;
++      info.var.yres_virtual = yres;
++      info.var.bits_per_pixel = bpp;
++      info.var.activate = FB_ACTIVATE_NOW;
++      info.var.height = -1;
++      info.var.width = -1;
++
++      switch (bpp) {
++      case 8:
++              info.var.red.length = 8;
++              info.var.green.length = 8;
++              info.var.blue.length = 8;
++
++              info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
++              ep93xxfb_par.bits_per_pixel = 8;
++              break;
++      case 16:
++              info.var.red.length = 5;
++              info.var.green.length = 6;
++              info.var.blue.length = 5;
++              info.var.transp.length = 0;
++              info.var.red.offset = 11;
++              info.var.green.offset = 5;
++              info.var.blue.offset = 0;
++              info.var.transp.offset = 0;
++
++              info.fix.visual = FB_VISUAL_TRUECOLOR;
++              info.pseudo_palette = ep93xxfb_par.palette;
++
++              ep93xxfb_par.bits_per_pixel = 16;
++              break;
++      case 24:
++              info.var.red.length = 8;
++              info.var.blue.length = 8;
++              info.var.green.length = 8;
++              info.var.transp.length = 0;
++              info.var.red.offset = 16;
++              info.var.green.offset = 8;
++              info.var.blue.offset = 0;
++              info.var.transp.offset = 0;
++
++              info.fix.visual = FB_VISUAL_TRUECOLOR;
++
++              ep93xxfb_par.bits_per_pixel = 24;
++              break;
++      case 32:
++              info.var.red.length = 8;
++              info.var.blue.length = 8;
++              info.var.green.length = 8;
++              info.var.transp.length = 0;
++              info.var.red.offset = 16;
++              info.var.green.offset = 8;
++              info.var.blue.offset = 0;
++              info.var.transp.offset = 0;
++
++              info.fix.visual = FB_VISUAL_TRUECOLOR;
++
++              ep93xxfb_par.bits_per_pixel = 32;
++              break;
++      }
++
++      total = readl(HCLKSTOTAL);
++      info.var.hsync_len = (0x7ff & readl(HSYNCSTRTSTOP)) - ((0x07ff0000 & readl(HSYNCSTRTSTOP)) >> 16);
++      info.var.right_margin = ((0x07ff0000 & readl(HSYNCSTRTSTOP)) >> 16) - (0x7ff & readl(HACTIVESTRTSTOP));
++      info.var.left_margin = total - info.var.hsync_len - info.var.right_margin - xres + 1;
++
++      total = readl(VLINESTOTAL);
++      info.var.vsync_len = (0x7ff & readl(VSYNCSTRTSTOP)) - ((0x07ff0000 & readl(VSYNCSTRTSTOP)) >> 16);
++      info.var.upper_margin = total - (0x7ff & readl(VSYNCSTRTSTOP));
++      info.var.lower_margin = ((0x07ff0000 & readl(VSYNCSTRTSTOP)) >> 16) - yres + 1;
++
++      info.var.sync = 0;
++
++      info.var.vmode = FB_VMODE_NONINTERLACED;
++
++      info.fix.line_length = info.var.xres_virtual * info.var.bits_per_pixel / 8;     // stride in bytes
++
++      info.par = &TimingValues[NULL_MODE];
++
++      ep93xxfb_par.screen_size = FB_MAX_MEM_SIZE;
++      ep93xxfb_par.palette_size = MAX_PALETTE_NUM_ENTRIES;
++      ep93xxfb_par.montype = 1;       //TBD why not 0 since single entry?
++      ep93xxfb_par.currcon = 0;       //TBD is this right?
++
++      return 1;
++}
++
++static void
++__init ep93xxfb_init_fbinfo(void)
++{
++      info.node = -1;
++      info.flags = FBINFO_FLAG_DEFAULT;
++
++      info.fix = ep93xxfb_fix;
++      info.var = ep93xxfb_var;
++      info.fbops = &ep93xxfb_ops;
++      info.pseudo_palette = pseudo_palette;
++      info.par = &ep93xxfb_par;
++
++      info.monspecs = monspecs;
++
++      strcpy(info.fix.id, "Cirrus EP93xx");
++      info.fix.type = FB_TYPE_PACKED_PIXELS;
++      info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
++      info.fix.xpanstep = 0;
++      info.fix.ypanstep = 0;
++      info.fix.ywrapstep = 0;
++      info.fix.accel = FB_ACCEL_NONE;
++
++      info.var.xres = TimingValues[DEFAULT_MODE].HRes;
++      info.var.yres = TimingValues[DEFAULT_MODE].VRes;
++      info.var.xres_virtual = TimingValues[DEFAULT_MODE].HRes;
++      info.var.yres_virtual = TimingValues[DEFAULT_MODE].VRes;
++      info.var.bits_per_pixel = 32;
++      info.var.red.length = 8;
++      info.var.green.length = 8;
++      info.var.blue.length = 8;
++      info.var.activate = FB_ACTIVATE_NOW;
++      info.var.height = -1;
++      info.var.width = -1;
++      info.var.vmode = FB_VMODE_NONINTERLACED;
++
++      /*
++       * setup initial parameters
++       */
++      info.var.xres = TimingValues[DEFAULT_MODE].HRes;
++      info.var.yres = TimingValues[DEFAULT_MODE].VRes;
++
++#ifdef CONFIG_FB_EP93XX_8BPP
++      DPRINTK("Default framebuffer is 8bpp.");
++      info.var.bits_per_pixel = 8;
++
++      info.var.red.length = 8;
++      info.var.green.length = 8;
++      info.var.blue.length = 8;
++
++      info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
++      ep93xxfb_par.bits_per_pixel = 8;
++#endif                                /* CONFIG_FB_EP93XX_8BPP */
++#ifdef CONFIG_FB_EP93XX_16BPP_565
++      DPRINTK("Default framebuffer is 16bpp 565.");
++      info.var.bits_per_pixel = 16;
++
++      info.var.red.length = 5;
++      info.var.green.length = 6;
++      info.var.blue.length = 5;
++      info.var.transp.length = 0;
++      info.var.red.offset = 11;
++      info.var.green.offset = 5;
++      info.var.blue.offset = 0;
++      info.var.transp.offset = 0;
++      info.fix.visual = FB_VISUAL_TRUECOLOR;
++      info.pseudo_palette = ep93xxfb_par.palette;
++
++      ep93xxfb_par.bits_per_pixel = 16;
++#endif                                /* CONFIG_FB_EP93XX_16BPP */
++#ifdef CONFIG_FB_EP93XX_24BPP
++      DPRINTK("Default framebuffer is 24bpp.");
++      info.var.bits_per_pixel = 24;
++
++      info.var.red.length = 8;
++      info.var.blue.length = 8;
++      info.var.green.length = 8;
++      info.var.transp.length = 0;
++      info.var.red.offset = 16;
++      info.var.green.offset = 8;
++      info.var.blue.offset = 0;
++      info.var.transp.offset = 0;
++      info.fix.visual = FB_VISUAL_TRUECOLOR;
++
++      ep93xxfb_par.bits_per_pixel = 24;
++#endif                                /* CONFIG_FB_EP93XX_24BPP */
++#ifdef CONFIG_FB_EP93XX_32BPP
++      DPRINTK("Default framebuffer is 32bpp.");
++      info.var.bits_per_pixel = 32;
++
++      info.var.red.length = 8;
++      info.var.blue.length = 8;
++      info.var.green.length = 8;
++      info.var.transp.length = 0;
++      info.var.red.offset = 16;
++      info.var.green.offset = 8;
++      info.var.blue.offset = 0;
++      info.var.transp.offset = 0;
++      info.fix.visual = FB_VISUAL_TRUECOLOR;
++
++      ep93xxfb_par.bits_per_pixel = 32;
++#endif                                /* CONFIG_FB_EP93XX_32BPP */
++
++      info.var.activate = FB_ACTIVATE_NOW;
++      info.var.height = -1;   /*TBD unknown */
++      info.var.width = -1;    /*TBD unknown */
++
++      info.var.left_margin = TimingValues[DEFAULT_MODE].HFrontPorch;
++      info.var.right_margin = TimingValues[DEFAULT_MODE].HBackPorch;
++      info.var.upper_margin = TimingValues[DEFAULT_MODE].VFrontPorch;
++      info.var.lower_margin = TimingValues[DEFAULT_MODE].VBackPorch;
++      info.var.hsync_len = TimingValues[DEFAULT_MODE].HSyncWidth;
++      info.var.vsync_len = TimingValues[DEFAULT_MODE].VSyncWidth;
++      info.var.sync = 0;
++      info.var.vmode = FB_VMODE_NONINTERLACED;
++
++      info.fix.line_length = info.var.xres_virtual * info.var.bits_per_pixel / 8;     /* stride in bytes */
++
++      info.par = &TimingValues[DEFAULT_MODE];
++
++      ep93xxfb_par.screen_size = FB_MAX_MEM_SIZE;
++      ep93xxfb_par.palette_size = MAX_PALETTE_NUM_ENTRIES;
++      ep93xxfb_par.montype = 1;       /*TBD why not 0 since single entry? */
++      ep93xxfb_par.currcon = 0;       /*TBD is this right? */
++}
++
++static int
++ep93xxfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
++{
++      u_long flags, ulVIDEOATTRIBS;
++      unsigned int total, uiDevCfg, uiBMAR;
++#ifdef CONFIG_FB_LCD_EP93XX
++      unsigned int uiPADDR, uiPADR;
++#endif
++      struct DisplayTimingValues *pTimingValues;
++
++      switch (var->bits_per_pixel) {
++      case 4:
++              ep93xxfb_par.visual = FB_VISUAL_PSEUDOCOLOR;
++              ep93xxfb_par.palette_size = 16;
++              break;
++      case 8:
++              ep93xxfb_par.visual = FB_VISUAL_PSEUDOCOLOR;
++              ep93xxfb_par.palette_size = 256;
++              break;
++      case 16:
++              ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR;
++              ep93xxfb_par.palette_size = 16;
++              break;
++      case 24:
++              ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR;
++              ep93xxfb_par.palette_size = 16;
++              break;
++      case 32:
++              ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR;
++              ep93xxfb_par.palette_size = 16;
++              break;
++      default:
++              printk("ERROR! Bad bpp %d\n", var->bits_per_pixel);
++              return -EINVAL;
++      }
++
++      if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
++              return 0;
++      else if (((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) &&
++               ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NXTOPEN))
++              return -EINVAL;
++
++      pTimingValues = (struct DisplayTimingValues *)info->par;
++
++      /* Disable interrupts and save status */
++      local_irq_save(flags);
++
++      printk("Configuring %dx%dx%dbpp\n", var->xres, var->yres,
++             var->bits_per_pixel);
++
++      /* Disable the video and outputs while changing the video mode. */
++      writel(0, VIDEOATTRIBS);
++      if (pTimingValues->RasterConfigure) {
++              pTimingValues->RasterConfigure((struct DisplayTimingValues *)info->par);        /*pTimingValues); */
++      } else {
++              total = var->vsync_len + var->upper_margin + var->yres +
++                  var->lower_margin - 1;
++
++              RasterSetLocked(VLINESTOTAL, total);
++
++              RasterSetLocked(VSYNCSTRTSTOP, total - var->lower_margin +
++                              ((total -
++                                (var->lower_margin + var->vsync_len)) << 16));
++
++              RasterSetLocked(VACTIVESTRTSTOP, var->yres + (total << 16));
++
++              /* Reverse start/stop since N_VBLANK output
++               * unblanked same as active
++               */
++              RasterSetLocked(VBLANKSTRTSTOP, var->yres + (total << 16));
++
++              RasterSetLocked(VCLKSTRTSTOP, total + (total << 16));
++
++              /* Now configure the Horizontal timings. */
++              total = var->hsync_len + var->left_margin + var->xres +
++                  var->right_margin - 1;
++
++              RasterSetLocked(HCLKSTOTAL, total);
++
++              RasterSetLocked(HSYNCSTRTSTOP, total +
++                              ((total - var->hsync_len) << 16));
++
++              RasterSetLocked(HACTIVESTRTSTOP, total - var->hsync_len -
++                              var->left_margin +
++                              ((var->right_margin - 1) << 16));
++
++              RasterSetLocked(HBLANKSTRTSTOP, total - var->hsync_len -
++                              var->left_margin +
++                              ((var->right_margin - 1) << 16));
++
++              RasterSetLocked(HCLKSTRTSTOP, total + (total << 16));
++
++              RasterSetLocked(LINECARRY, 0);
++
++              RasterSetLocked(VIDEOATTRIBS,
++                              VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_SYNCEN |
++                              VIDEOATTRIBS_DATAEN);
++      }
++
++      /* Configure the Frame Buffer size. */
++      writel((unsigned int)ep93xxfb_par.p_screen_base, VIDSCRNPAGE);
++      writel(var->yres, SCRNLINES);
++
++      /* Set up the Line size. */
++      total = var->xres * var->bits_per_pixel / 32;
++      writel((total - 1), LINELENGTH);
++      writel(total, VLINESTEP);
++
++      switch (var->bits_per_pixel) {
++      case 8:
++              writel((0x8 | PIXELMODE_P_8BPP | PIXELMODE_C_LUT), PIXELMODE);
++              break;
++      case 16:
++              writel(0x8 | PIXELMODE_P_16BPP |
++                     ((PIXELMODE_C_565) << (PIXELMODE_C_SHIFT)), PIXELMODE);
++              break;
++      case 24:
++              writel(0x8 | PIXELMODE_P_24BPP |
++                     ((PIXELMODE_C_888) << (PIXELMODE_C_SHIFT)), PIXELMODE);
++              break;
++      case 32:
++              writel(0x8 | PIXELMODE_P_32BPP |
++                     ((PIXELMODE_C_888) << (PIXELMODE_C_SHIFT)), PIXELMODE);
++              break;
++      default:
++              printk("ERROR! Bad bpp %d\n", var->bits_per_pixel);
++              return -EINVAL;
++      }
++
++      uiDevCfg = readl(SYSCON_DEVCFG);
++      SysconSetLocked(SYSCON_DEVCFG,
++                      ep93xx_SYSCON_DEVCFG(uiDevCfg | SYSCON_DEVCFG_RasOnP3));
++
++      if (pTimingValues->VDiv)
++              SysconSetLocked(SYSCON_VIDDIV, pTimingValues->VDiv);
++
++      uiBMAR = readl(SYSCON_BMAR);
++      writel((uiBMAR | 1), SYSCON_BMAR);
++
++      ulVIDEOATTRIBS = readl(VIDEOATTRIBS);
++      RasterSetLocked(VIDEOATTRIBS, ulVIDEOATTRIBS | VIDEOATTRIBS_EN |
++#if (defined(CONFIG_MACH_ZEFEERDZG) || defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ))
++                      (1 << VIDEOATTRIBS_SDSEL_SHIFT));
++#else
++                      (3 << VIDEOATTRIBS_SDSEL_SHIFT));
++#endif
++                      
++
++#ifdef CONFIG_FB_LCD_EP93XX
++      uiPADDR = readl(GPIO_PADDR) | 0x2;
++      writel(uiPADDR, GPIO_PADDR);
++
++      uiPADR = readl(GPIO_PADR) | 0x2;
++      writel(uiPADR, GPIO_PADR);
++#endif
++
++      local_irq_restore(flags);
++      return 0;
++}
++
++int __init ep93xxfb_init(void)
++{
++      char *option = NULL;
++      DPRINTK("ep93xxfb_init(void)\n");
++
++      /*
++       * For kernel boot options (in 'video=xxxfb:<options>' format)
++       */
++
++      fb_get_options("ep93xxfb", &option);
++      ep93xxfb_setup(option);
++
++      /* init all the important stuff in info */
++      if (!ep93xxfb_probe_configuration())
++              ep93xxfb_init_fbinfo();
++
++      /* Allocate and map framebuffer memory in system DRAM */
++      if (ep9312fb_map_video_memory() != 0)
++              return -ENOMEM;
++
++      /* This has to been done !!! */
++      fb_alloc_cmap(&info.cmap, MAX_PALETTE_NUM_ENTRIES, 0);
++
++      /* hard code, since we don't support modedb & friends yet */
++      ep93xxfb_set_var(&info.var, -1, &info);
++
++      if (register_framebuffer(&info) < 0)
++              return -EINVAL;
++
++      ep93xxfb_blank(FB_BLANK_UNBLANK, &info);
++
++      printk(KERN_INFO "fb%d: %s frame buffer device\n", info.node,
++             info.fix.id);
++
++      printk(KERN_INFO
++             "ep93xxfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
++             info.fix.smem_start, info.screen_base, info.fix.smem_len / 1024);
++      printk(KERN_INFO
++             "ep93xxfb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
++             ep93xxfb_var.xres, ep93xxfb_var.yres,
++             ep93xxfb_var.bits_per_pixel, info.fix.line_length,
++             screen_info.pages);
++
++      return 0;
++}
++
++static void __exit ep93xxfb_cleanup(void)
++{
++      DPRINTK("ep93xxfb_cleanup(void)\n");
++      unregister_framebuffer(&info);
++}
++
++int __init ep93xxfb_setup(char *options)
++{
++      DPRINTK("ep93xxfb_setup(char *options=\"%s\")\n", options);
++      /* TODO: Parse user speficied options (`video=ep93xxfb:') */
++      return 0;
++}
++
++module_init(ep93xxfb_init);
++module_exit(ep93xxfb_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Michael Burian");
+diff --git a/drivers/video/ep93xxfb.h b/drivers/video/ep93xxfb.h
+new file mode 100644
+index 0000000..dec4857
+--- /dev/null
++++ b/drivers/video/ep93xxfb.h
+@@ -0,0 +1,287 @@
++/*
++ * ep93xxfb.h         Cirrus Logic EP93xx Framebuffer header
++ */
++
++/*
++ * TODO:
++ *    Still lot's of messy stuff here that belongs elsewhere.
++ *
++ *    I'd say that each display / display family get an own header file
++ *    maybe even the whole ep93xx stuff should get an own directory, just like ati
++ *    It also could not hurt to test the NTSC stuff, which already was split into cx25871.c
++ *    but not tested to work so far.
++ *
++ *    Display initialisation should become human readable, it should be changed
++ *    to reflect what's going on in hardware.
++ *
++ *    This means we should say which PLL, prescaler, divider, ... is used instead
++ *    of just saying VDIV = 0x0000c207, same goes for all the other hardcoded values.
++ *
++ *    How will we handle higher clocked EP93xx once they are available?
++ *
++ */
++
++#define RasterSetLocked(registername,value) \
++    {                                       \
++        writel( 0xAA, REALITI_SWLOCK );       \
++        writel( value, registername);         \
++    }
++
++static void InitializeCX25871For640x480NTSC(void);
++
++struct ep93xxfb_par {
++      struct device *dev;
++      dma_addr_t p_screen_base;
++      unsigned char *v_screen_base;
++      unsigned long screen_size;
++      unsigned int palette_size;
++      unsigned int xres;
++      unsigned int yres;
++      unsigned int bits_per_pixel;
++      signed int montype;
++      unsigned int currcon;
++      unsigned int visual;
++      u16 palette[16];        /* Funky 16 table lookup used by "optional" Parameter. */
++};
++
++#define MAX_PALETTE_NUM_ENTRIES               256
++#define MAX_CRT_XRES  640
++#define MAX_CRT_YRES  480
++#define MAX_BPP               32
++#define FB_MAX_MEM_SIZE ((MAX_CRT_XRES * MAX_CRT_YRES * MAX_BPP)/8)
++#define FB_MAPPED_MEM_SIZE (PAGE_ALIGN(FB_MAX_MEM_SIZE + PAGE_SIZE))
++
++#define EP93XX_NAME   "EP93XX"
++#define NR_MONTYPES   1
++
++/* Fake monspecs to fill in fbinfo structure */
++static struct fb_monspecs monspecs __initdata = {
++      {30000, 70000, 50, 65, 0}       /* Generic */
++};
++
++#if defined (CONFIG_FB_LCD_EP93XX)
++#define DEFAULT_MODE 1
++#elif defined (CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343)
++#define DEFAULT_MODE 2
++#elif defined (CONFIG_FB_CX25871)
++#define DEFAULT_MODE 3
++#elif defined (CONFIG_FB_CRT_EP93XX)
++#define DEFAULT_MODE 0
++#elif defined (CONFIG_FB_LCD_EP93XX_SHARP)
++#define DEFAULT_MODE 5
++#define CONFIG_FB_LCD_EP93XX 1        /*hack!!! FIXME: put whole display support into different files */
++#elif defined (CONFIG_FB_LCD_TX09D50VM1CCA)
++#define DEFAULT_MODE 6
++#else
++#error What Display Setting was that!!!
++#endif
++
++struct DisplayTimingValues {
++      const char *Name;
++      unsigned long DisplayID;
++      int (*RasterConfigure) (struct DisplayTimingValues * pTimingValues);
++      unsigned short Refresh;
++      unsigned long VDiv;
++
++      unsigned short HRes;
++      unsigned short HFrontPorch;
++      unsigned short HBackPorch;
++      unsigned short HSyncWidth;
++      unsigned short HTotalClocks;
++
++      unsigned short VRes;
++      unsigned short VFrontPorch;
++      unsigned short VBackPorch;
++      unsigned short VSyncWidth;
++      unsigned short VTotalClocks;
++};
++
++typedef int (*fRasterConfigure) (struct DisplayTimingValues *);
++
++enum DisplayType {
++      CRT_GENERIC,
++      Philips_LB064V02A1,
++      CX25871,
++      Sharp
++};
++
++static int Conexant_CX25871(struct DisplayTimingValues *pTimingValues);
++static int NecLCD(struct DisplayTimingValues *pTimingValues);
++
++#define TIMING_VALUES(NAME, DISPID, FUNC, REFRESH, VDIV,                \
++                   HRES, HFP, HBP, HSYNC, VRES, VFP, VBP, VSYNC)        \
++{                                                                       \
++    Name:NAME,                                                          \
++    DISPID, FUNC, REFRESH, VDIV,                                        \
++    HRES, HFP, HBP, HSYNC, (HRES + HFP + HBP + HSYNC),                  \
++    VRES, VFP, VBP, VSYNC, (VRES + VFP + VBP + VSYNC)                   \
++}
++
++/* TODO:
++ *
++ * This is a big, confusing mess right now.
++ * We really should see if we can do it like Documentation/fb/modedb.txt
++ * suggests.
++ *
++ * Fix it, probably by moving this into ep93xx_modes.c or something like that
++ */
++
++static struct DisplayTimingValues TimingValues[] = {
++      /* 640x480 Progressive Scan */
++      TIMING_VALUES("CRT_GENERIC", CRT_GENERIC,
++                    (fRasterConfigure) NULL,
++                    60, 0x0000c108, 640, 16, 48, 96, 480, 11, 31, 2),
++      /* 640x480 Progressive Scan Philips LB064V02A1 on EDB9312 Board. */
++
++      /* Display can handle clocks from 22MHz(VDIV=0xc107)-28Mhz(VDIV=0xc106) */
++      TIMING_VALUES("Philips LB064V02A1", Philips_LB064V02A1,
++                    0,
++                    68, 0x0000c106, 640, 16, 48, 96, 480, 11, 31, 2),
++      /*fast refresh rate (26.7MHz) */
++      /*68, 0x0000c106, 640, 16, 48, 96, 480, 11, 31, 2), */
++      /*original setting (slowest refresh) (22.8MHz) */
++      /*68, 0x0000c107, 640, 16, 48, 96, 480, 11, 31, 2), */
++
++      /* Sharp LQ64D343 LCD Panel */
++      TIMING_VALUES("Sharp LQ64d343", CRT_GENERIC,
++                    (fRasterConfigure) NULL,
++                    60, 0x0000c205, 640, 32, 32, 96, 480, 34, 34, 4),
++      /* NEC LCD Panel */
++      TIMING_VALUES("NEC", CRT_GENERIC,
++                    NecLCD,
++                    60, 0x0000c204, 640, 32, 32, 96, 480, 34, 34, 4),
++      /* 640x480 NTSC Support for Conexant CX25871 */
++      TIMING_VALUES("Conexant CX25871", CX25871,
++                    Conexant_CX25871,
++                    60, 0x0000c317, 640, 0, 0, 0, 480, 0, 0, 0),
++      /* 320x240 Sharp LCD Panel */
++      TIMING_VALUES("Sharp LQ057Q3DC02", CRT_GENERIC,
++                    (fRasterConfigure) NULL,
++                    0, 0x0000c108, 320, 32, 32, 96, 240, 3, 3, 4),
++      /*
++              240x320 Hitachi
++      
++              Max pixel clock freq = 1/83ns ~= 12.048 MHz (VDiv = 0x0000c10a)
++              Typ pixel clock freq = 5.33 MHz (VDiv = 0x0000c125)
++      */
++      TIMING_VALUES("Hitachi TX09D50VM1CCA", CRT_GENERIC,
++                    (fRasterConfigure)NULL,
++                    0, 0x0000c125, 240, 16/*HFP*/, 12/*HBP*/, 5/*HSYNC*/, 320, 3/*VFP*/, 3/*VBP*/, 1/*VSYNC*/), 
++      /* NULL */
++      TIMING_VALUES("Unknown", CRT_GENERIC,
++                    (fRasterConfigure) NULL,
++                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
++
++};
++
++#define NUM_TIMING_VALUES (sizeof(TimingValues)/sizeof(struct DisplayTimingValues))
++
++#define NULL_MODE (NUM_TIMING_VALUES-1)
++
++#define EE_DELAY_USEC       100
++#define EE_READ_TIMEOUT     100
++#define CX25871_DEV_ADDRESS                     0x88
++#define CX25871_REGx32_AUTO_CHK                 0x80
++#define CX25871_REGx32_DRVS_MASK                0x60
++#define CX25871_REGx32_DRVS_SHIFT               5
++#define CX25871_REGx32_SETUP_HOLD               0x10
++#define CX25871_REGx32_INMODE_                  0x08
++#define CX25871_REGx32_DATDLY_RE                0x04
++#define CX25871_REGx32_OFFSET_RGB               0x02
++#define CX25871_REGx32_CSC_SEL                  0x01
++
++/* Register 0xBA */
++#define CX25871_REGxBA_SRESET                   0x80
++#define CX25871_REGxBA_CHECK_STAT               0x40
++#define CX25871_REGxBA_SLAVER                   0x20
++#define CX25871_REGxBA_DACOFF                   0x10
++#define CX25871_REGxBA_DACDISD                  0x08
++#define CX25871_REGxBA_DACDISC                  0x04
++#define CX25871_REGxBA_DACDISB                  0x02
++#define CX25871_REGxBA_DACDISA                  0x01
++
++/* Register 0xC4 */
++#define CX25871_REGxC4_ESTATUS_MASK             0xC0
++#define CX25871_REGxC4_ESTATUS_SHIFT            6
++#define CX25871_REGxC4_ECCF2                    0x20
++#define CX25871_REGxC4_ECCF1                    0x10
++#define CX25871_REGxC4_ECCGATE                  0x08
++#define CX25871_REGxC4_ECBAR                    0x04
++#define CX25871_REGxC4_DCHROMA                  0x02
++#define CX25871_REGxC4_EN_OUT                   0x01
++
++/* Register 0xC6 */
++#define CX25871_REGxC6_EN_BLANKO                0x80
++#define CX25871_REGxC6_EN_DOT                   0x40
++#define CX25871_REGxC6_FIELDI                   0x20
++#define CX25871_REGxC6_VSYNCI                   0x10
++#define CX25871_REGxC6_HSYNCI                   0x08
++#define CX25871_REGxC6_INMODE_MASK              0x07
++#define CX25871_REGxC6_INMODE_SHIFT             0
++
++#define GPIOG_EEDAT 2
++#define GPIOG_EECLK 1
++
++static int Conexant_CX25871(struct DisplayTimingValues *pTimingValues)
++{
++      unsigned int uiTemp;
++      InitializeCX25871For640x480NTSC();
++
++      RasterSetLocked(VIDEOATTRIBS, 0);
++      uiTemp = readl(SYSCON_DEVCFG);
++      SysconSetLocked(SYSCON_DEVCFG, (uiTemp | SYSCON_DEVCFG_EXVC));
++
++      RasterSetLocked(VLINESTOTAL, 0x0257);
++      RasterSetLocked(VSYNCSTRTSTOP, 0x01FF022C);     /* was 024c */
++      RasterSetLocked(VBLANKSTRTSTOP, 0x000001E0);
++      RasterSetLocked(VACTIVESTRTSTOP, 0x000001E0);
++      RasterSetLocked(VCLKSTRTSTOP, 0x07FF01E0);
++
++      RasterSetLocked(HCLKSTOTAL, 0x30F);
++      RasterSetLocked(HSYNCSTRTSTOP, 0x02c0030F);
++      RasterSetLocked(HBLANKSTRTSTOP, 0x00000280);
++      RasterSetLocked(HACTIVESTRTSTOP, 0x00000280);
++      RasterSetLocked(HCLKSTRTSTOP, 0x07ff0280);
++
++      RasterSetLocked(LINECARRY, 0);
++
++      RasterSetLocked(VIDEOATTRIBS,
++                      VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN);
++
++      return 0;
++}
++
++static int NecLCD(struct DisplayTimingValues *pTimingValues)
++{
++      RasterSetLocked(VIDEOATTRIBS, 0);
++
++      RasterSetLocked(VLINESTOTAL, 0x020c);
++      RasterSetLocked(VSYNCSTRTSTOP, 0x01fe0200);     /* was 024c */
++      RasterSetLocked(VBLANKSTRTSTOP, 0x0000000);
++      RasterSetLocked(VACTIVESTRTSTOP, 0x020c01df);
++      RasterSetLocked(VCLKSTRTSTOP, 0x020c020c);
++
++      RasterSetLocked(HCLKSTOTAL, 0x323);
++      RasterSetLocked(HSYNCSTRTSTOP, 0x02c00321);
++      RasterSetLocked(HBLANKSTRTSTOP, 0x00000);
++      RasterSetLocked(HACTIVESTRTSTOP, 0x00100290);
++      RasterSetLocked(HCLKSTRTSTOP, 0x03230323);
++
++      RasterSetLocked(LINECARRY, 0);
++
++      RasterSetLocked(VIDEOATTRIBS, VIDEOATTRIBS_INVCLK |
++                      VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_SYNCEN |
++                      VIDEOATTRIBS_DATAEN);
++
++      return 0;
++}
++
++void InitializeCX25871For640x480NTSC(void)
++{
++/*
++ * If you need this see cx25871.[ch] and grep for "should be done".
++ * see if you can find a suitable and less messy way to do i2c stuff
++ * also see our patch against 2.6.11.7-ep93xx
++ */
++      printk("ERROR: InitializeCX25871For640x480NTSC unimplemented!\n");
++}
+diff --git a/include/asm-arm/arch-ep93xx/adssphere.h b/include/asm-arm/arch-ep93xx/adssphere.h
+new file mode 100644
+index 0000000..97874c1
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/adssphere.h
+@@ -0,0 +1,55 @@
++/*
++ *  linux/include/asm-arm/arch-ep93xx/adssphere.h
++ *
++ *  Copyright (C) 2005 Robert Whaley <rwhaley@applieddata.net>
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef ASM_ARCH_ADSSPHERE_H
++#define ASM_ARCH_ADSSPHERE_H
++
++#define ADSSPHERE_BASE_VIRT  0xe2000000
++#define ADSSPHERE_BASE_PHYS  0xf0000000
++
++#define ADSSPHERE_CR0       (ADSSPHERE_BASE_VIRT+0x00)
++#define ADSSPHERE_CR1       (ADSSPHERE_BASE_VIRT+0x04)
++#define ADSSPHERE_SR        (ADSSPHERE_BASE_VIRT+0x08)
++#define ADSSPHERE_CAN_ADDR  (ADSSPHERE_BASE_VIRT+0x0c)
++#define ADSSPHERE_CAN_DATA  (ADSSPHERE_BASE_VIRT+0x10)
++#define ADSSPHERE_FW_FW_NUM (ADSSPHERE_BASE_VIRT+0x14)
++#define ADSSPHERE_FW_FW_REV (ADSSPHERE_BASE_VIRT+0x18)
++#define ADSSPHERE_FW_BD_REV (ADSSPHERE_BASE_VIRT+0x1c)
++
++#define ADSSPHERE_CR0_CF_33 0x01
++#define ADSSPHERE_CR0_CF_50 0x02
++#define ADSSPHERE_CR0_COMEN 0x04
++#define ADSSPHERE_CR0_IRDA  0x08
++#define ADSSPHERE_CR0_USB   0x10
++#define ADSSPHERE_CR0_PWSAV 0x20
++
++#define ADSSPHERE_CR1_PNL_ON 0x01
++#define ADSSPHERE_CR1_PNL_EN 0x04
++#define ADSSPHERE_CR1_BL_ON  0x08
++#define ADSSPHERE_CR1_AMP_ON 0x10
++#define ADSSPHERE_CR1_CDC_ON 0x20
++#define ADSSPHERE_CR1_BTL_ON 0x40
++
++#define ADSSPHERE_SR1_SW0 0x01
++#define ADSSPHERE_SR1_SW1 0x02
++#define ADSSPHERE_SR1_SW2 0x04
++#define ADSSPHERE_SR1_SW3 0x08
++#define ADSSPHERE_SR1_HP  0x10
++
++#endif /* ASM_ARCH_ADSSPHERE_H */
+diff --git a/include/asm-arm/arch-ep93xx/clocks.h b/include/asm-arm/arch-ep93xx/clocks.h
+new file mode 100644
+index 0000000..acc8023
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/clocks.h
+@@ -0,0 +1,160 @@
++/*
++ *
++ * Filename: clocks.h
++ *
++ * Description: Header file for the clocks.
++ *
++ * Copyright(c) Cirrus Logic Corporation 2003, All Rights Reserved
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
++ *
++ */
++#include <asm/hardware.h>
++#ifndef _H_CLOCKS
++#define _H_CLOCKS
++
++/*
++ * How this file works:
++ * Choose your FCLOCK value this causes FDIV, HDIV, PDIV values to be set
++ *
++ * The Real FDIV, HDIV, and PDIV are set according to the following table.
++ * Processor runs at (PLL1 speed/PLL Divide specified by FDIV)
++ * AHB runs at (PLL1 speed/PLL Divide specified by HDIV)
++ * APB runs at AHB/(2^PDIV)
++ * ------------------------------------------------------------------
++ * HDIV   PLL Divide    FDIV    PLL Divide
++ * 0      1             0       1
++ * 1      2             1       2
++ * 2      4             2       4
++ * 3      5             3       8
++ * 4      6             4       16
++ * 5      8
++ * 6      16
++ * 7      32
++ *
++ */
++
++/* there is some confusion here about MACH vs. ARCH. clean it up
++   once we get a nice clock management system going */
++#ifdef CONFIG_ARCH_EP9301
++#define FCLOCK 166
++#define EP93XX_UART_CLK 14745600
++#endif
++
++#ifdef CONFIG_MACH_EDB9302
++#define FCLOCK 200
++#define EP93XX_UART_CLK 14745600
++#endif
++
++#if defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || defined(CONFIG_MACH_ADSSPHERE)
++#define FCLOCK 200
++#define EP93XX_UART_CLK 14745600
++#endif
++
++#if defined(CONFIG_MACH_DMA03)
++#define FCLOCK 200
++#define EP93XX_UART_CLK 14745600
++#endif
++
++#ifdef CONFIG_MACH_ACC
++#define EP93XX_UART_CLK 24576000
++#endif
++
++#if defined(CONFIG_MACH_ZEFEERDZA)
++#define FCLOCK 166
++#define EP93XX_UART_CLK 14745600
++#endif
++
++#if defined(CONFIG_MACH_ZEFEERDZB) || defined(CONFIG_MACH_ZEFEERDZG) || \
++    defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ)
++#define FCLOCK 200
++#define EP93XX_UART_CLK 14745600
++#endif
++
++/*
++ * PLL1 Clock =442  Mhz
++ *
++ * FClock    = 221  Mhz
++ * HCLock    = 73   Mhz
++ * PClock    = 46   Mhz
++ */
++#if (FCLOCK == 221)
++#define FDIV                        1
++#define HDIV                        5
++#define PDIV                        1
++#define PRE_CLKSET1_VALUE           0x0080b3b6
++#define PLL1_CLOCK                  442368000
++#endif                                /* (FCLOCK == 221) */
++
++/*
++ * PLL1 Clock =400  Mhz
++ *
++ * FClock    = 200  Mhz
++ * HCLock    = 100  Mhz
++ * PClock    = 50   Mhz
++ *
++ */
++#if (FCLOCK == 200)
++#define FDIV                        1
++#define HDIV                        2
++#define PDIV                        1
++#define PRE_CLKSET1_VALUE           0x0080a3d7
++#define PLL1_CLOCK                  399974400
++#endif                                /* (FCLOCK == 200) */
++
++/*
++ * PLL1 Clock =368  Mhz
++ *
++ * FClock    = 184  Mhz
++ * HCLock    = 73   Mhz
++ * PClock    = 46   Mhz
++ *
++ */
++#if (FCLOCK == 183)
++#define FDIV                        1
++#define HDIV                        4
++#define PDIV                        1
++#define PRE_CLKSET1_VALUE           0x0080ab15
++#define PLL1_CLOCK                  368640000
++#endif                                /* (FCLOCK == 183) */
++
++/*
++ * PLL1 Clock =332  Mhz
++ *
++ * FClock    = 166  Mhz
++ * HCLock    = 66   Mhz
++ * PClock    = 33   Mhz
++ *
++ */
++#if (FCLOCK == 166)
++#define FDIV                        1
++#define HDIV                        3
++#define PDIV                        1
++#define PRE_CLKSET1_VALUE           0x0080fa5a
++#define PLL1_CLOCK                  332049067
++#endif                                /* (FCLOCK == 166) */
++
++#define CLKSET1_VALUE   ( PRE_CLKSET1_VALUE | \
++                        ( PDIV << SYSCON_CLKSET1_PCLK_DIV_SHIFT ) | \
++                        ( HDIV << SYSCON_CLKSET1_HCLK_DIV_SHIFT ) | \
++                        ( FDIV << SYSCON_CLKSET1_FCLK_DIV_SHIFT ) )
++
++/*
++ * Value for the PLL 2 register.
++ */
++#define CLKSET2_VALUE           0x300dc317
++#define PLL2_CLOCK              192000000
++
++#endif                                /*  _H_CLOCKS  */
+diff --git a/include/asm-arm/arch-ep93xx/crunch.h b/include/asm-arm/arch-ep93xx/crunch.h
+new file mode 100644
+index 0000000..db9fb2e
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/crunch.h
+@@ -0,0 +1,48 @@
++#ifndef       __asm_crunch_h__
++#define       __asm_crunch_h__
++
++#define       CRUNCH_INIT     0x00900000
++#define       CRUNCH_IRQ      58
++
++#ifndef       __ASSEMBLY__
++
++/* enable the MaverickCrunch clock */
++static inline void crunch_enable(void)
++{
++      int tmp, aa = 0xAA;
++      int *lock = (int *)0xe09300c0;
++      int *syscfg = (int *)0xe0930080;
++
++      asm volatile ("str    %3, [%1]\n\t"
++                    "ldr    %0, [%2]\n\t"
++                    "orr    %0, %0, #(1 << 23)\n\t"
++                    "str    %0, [%2]":"=r" (tmp)
++                    :"r"(lock), "r"(syscfg), "r"(aa)
++                    :"memory");
++}
++
++/* disable the MaverickCrunch clock */
++static inline void crunch_disable(void)
++{
++      int tmp, aa = 0xAA;
++      int *lock = (int *)0xe09300c0;
++      int *syscfg = (int *)0xe0930080;
++
++      asm volatile ("str    %3, [%1]\n\t"
++                    "ldr    %0, [%2]\n\t"
++                    "bic    %0, %0, #(1 << 23)\n\t"
++                    "str    %0, [%2]":"=r" (tmp)
++                    :"r"(lock), "r"(syscfg), "r"(aa)
++                    :"memory");
++}
++
++unsigned int read_dspsc_low(void);
++unsigned int read_dspsc_high(void);
++void write_dspsc(unsigned int);
++void save_fpu(struct task_struct *);
++void restore_fpu(struct task_struct *);
++int setup_crunch(void);
++void crunch_init(void);
++#endif
++
++#endif                                /* __asm_crunch_h__ */
+diff --git a/include/asm-arm/arch-ep93xx/cx25871.h b/include/asm-arm/arch-ep93xx/cx25871.h
+new file mode 100644
+index 0000000..9d68ed9
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/cx25871.h
+@@ -0,0 +1,69 @@
++/*
++ * Filename: cx25871.h
++ *
++ * Description: Regisister Definitions and function prototypes for
++ *             CX25871 NTSC/PAL encoder.
++ *
++ * Copyright(c) Cirrus Logic Corporation 2003, All Rights Reserved
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef _H_CX25871
++#define _H_CX25871
++
++/* CS25871 Device Address. */
++#define CX25871_DEV_ADDRESS                     0x88
++
++/* Register 0x32 */
++#define CX25871_REGx32_AUTO_CHK                 0x80
++#define CX25871_REGx32_DRVS_MASK                0x60
++#define CX25871_REGx32_DRVS_SHIFT               5
++#define CX25871_REGx32_SETUP_HOLD               0x10
++#define CX25871_REGx32_INMODE_                  0x08
++#define CX25871_REGx32_DATDLY_RE                0x04
++#define CX25871_REGx32_OFFSET_RGB               0x02
++#define CX25871_REGx32_CSC_SEL                  0x01
++
++/* Register 0xBA */
++#define CX25871_REGxBA_SRESET                   0x80
++#define CX25871_REGxBA_CHECK_STAT               0x40
++#define CX25871_REGxBA_SLAVER                   0x20
++#define CX25871_REGxBA_DACOFF                   0x10
++#define CX25871_REGxBA_DACDISD                  0x08
++#define CX25871_REGxBA_DACDISC                  0x04
++#define CX25871_REGxBA_DACDISB                  0x02
++#define CX25871_REGxBA_DACDISA                  0x01
++
++/* Register 0xC4 */
++#define CX25871_REGxC4_ESTATUS_MASK             0xC0
++#define CX25871_REGxC4_ESTATUS_SHIFT            6
++#define CX25871_REGxC4_ECCF2                    0x20
++#define CX25871_REGxC4_ECCF1                    0x10
++#define CX25871_REGxC4_ECCGATE                  0x08
++#define CX25871_REGxC4_ECBAR                    0x04
++#define CX25871_REGxC4_DCHROMA                  0x02
++#define CX25871_REGxC4_EN_OUT                   0x01
++
++/* Register 0xC6 */
++#define CX25871_REGxC6_EN_BLANKO                0x80
++#define CX25871_REGxC6_EN_DOT                   0x40
++#define CX25871_REGxC6_FIELDI                   0x20
++#define CX25871_REGxC6_VSYNCI                   0x10
++#define CX25871_REGxC6_HSYNCI                   0x08
++#define CX25871_REGxC6_INMODE_MASK              0x07
++#define CX25871_REGxC6_INMODE_SHIFT             0
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/debug-macro.S b/include/asm-arm/arch-ep93xx/debug-macro.S
+new file mode 100644
+index 0000000..3d97614
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/debug-macro.S
+@@ -0,0 +1,56 @@
++/* linux/include/asm-arm/arch-ep93xx/debug-macro.S
++ *
++ * Debugging macro include header
++ *
++ *  Copyright (C) 1994-1999 Russell King
++ *  Moved from linux/arch/arm/kernel/debug.S by Ray Lehtiniemi
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++*/
++
++                .macro  addruart,rx
++                mrc     p15, 0, \rx, c1, c0
++                tst     \rx, #1                         @ MMU enabled?
++                ldreq   \rx, =IO_BASE_PHYS              @ System peripherals (phys address)
++                ldrne   \rx, =IO_BASE_VIRT              @ System peripherals (virt address)
++                orr     \rx,\rx,#0x008c0000             @ Advance to UART1Base
++
++                @ We probe for the active serial port here.
++                @ We assume r1 can be clobbered.
++
++                @ see if UART1 is active
++                ldr     r1, [\rx, #0x14]                @UART1Ctrl
++                tst     r1, #1
++
++                @ if UART1 is inactive advance to UART2
++                addeq   \rx, \rx, #0x00010000
++                ldreq   r1, [\rx, #0x14]                @UART2Ctrl
++                tsteq   r1, #1
++
++                @ if UART2 is inactive advance to UART3
++                addeq   \rx, \rx, #0x00010000
++                ldreq   r1, [\rx, #0x14]                @UART3Ctrl
++                tsteq   r1, #1
++
++                @ if all ports are inactive, then there is nothing we can do
++                moveq   pc, lr
++                .endm
++
++                .macro  senduart,rd,rx
++                strb    \rd, [\rx]                      @ UARTxData
++                .endm
++
++                .macro  waituart,rd,rx
++1001:           ldr     \rd, [\rx, #0x18]               @ UARTxFlag
++                tst     \rd, #0x20                      @ TXFF = 0 when ok to transmit
++                bne     1001b
++                .endm
++
++                .macro  busyuart,rd,rx
++1001:           ldr     \rd, [\rx, #0x18]               @ UARTxFlag
++                tst     \rd, #0x08                      @ BUSY = 1 while transmitting
++                bne     1001b
++                .endm
+diff --git a/include/asm-arm/arch-ep93xx/dma.h b/include/asm-arm/arch-ep93xx/dma.h
+new file mode 100644
+index 0000000..d3b6493
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/dma.h
+@@ -0,0 +1,233 @@
++/*****************************************************************************
++ *  linux/include/asm-arm/arch-ep93xx/dma.h
++ *
++ *  Copyright (C) 2003 Cirrus Logic
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ ****************************************************************************/
++#ifndef __ASM_ARCH_DMA_H
++#define __ASM_ARCH_DMA_H
++
++#define MAX_DMA_ADDRESS     0xffffffff
++
++/*
++ *  Not using the regular generic DMA interface for ep93xx.
++ */
++#define MAX_DMA_CHANNELS   0
++
++/*
++ * The ep93xx dma controller has 5 memory to peripheral (TX) channels, 5
++ * peripheral to memory (RX) channels and 2 memory to memory channels.
++ */
++#define MAX_EP93XX_DMA_M2P_CHANNELS 10
++#define MAX_EP93XX_DMA_M2M_CHANNELS 2
++
++/*
++ * The generic arm linux api does not support the ep93xx dma model, therefore
++ * we use a set of dma support functions written specifically for this dma
++ * controller.
++ */
++#define MAX_EP93XX_DMA_CHANNELS (MAX_EP93XX_DMA_M2P_CHANNELS + MAX_EP93XX_DMA_M2M_CHANNELS)
++
++/*****************************************************************************
++ *
++ * Max DMA buffer size
++ *
++ ****************************************************************************/
++#define DMA_MAX_BUFFER_BYTES    0xFFFF
++
++/*****************************************************************************
++ *
++ * typedefs
++ *
++ ****************************************************************************/
++
++/*****************************************************************************
++ *
++ * All devices which can use a DMA channel
++ *
++ * NOTE: There exist two types of DMA channels, those that transfer
++ *       between an internal peripheral and memory (M2P/P2M), and
++ *       those that transfer between an external peripheral and memory (M2M).
++ *       This becomes a bit confusing when you take into account the fact
++ *       that the M2M channels can also transfer between two specific
++ *       internal peripherals and memory.
++ *       The first 20 enumerated devices use the first type of channel (M2P/
++ *       P2M).  The last six enumerations are specific to the M2M channels.
++ *
++ ****************************************************************************/
++typedef enum {
++      /*
++       *  Hardware device options for the 10 M2P/P2M DMA channels.
++       */
++      DMATx_I2S1 = 0x00000000,        /* TX peripheral ports can be allocated an  */
++      DMATx_I2S2 = 0x00000001,        /* even numbered DMA channel.               */
++      DMATx_AAC1 = 0x00000002,
++      DMATx_AAC2 = 0x00000003,
++      DMATx_AAC3 = 0x00000004,
++      DMATx_I2S3 = 0x00000005,
++      DMATx_UART1 = 0x00000006,
++      DMATx_UART2 = 0x00000007,
++      DMATx_UART3 = 0x00000008,
++      DMATx_IRDA = 0x00000009,
++      DMARx_I2S1 = 0x0000000A,        /* RX perhipheral ports can be allocated an */
++      DMARx_I2S2 = 0x0000000B,        /* odd numbered DMA channel.                */
++      DMARx_AAC1 = 0x0000000C,
++      DMARx_AAC2 = 0x0000000D,
++      DMARx_AAC3 = 0x0000000E,
++      DMARx_I2S3 = 0x0000000F,
++      DMARx_UART1 = 0x00000010,
++      DMARx_UART2 = 0x00000011,
++      DMARx_UART3 = 0x00000012,
++      DMARx_IRDA = 0x00000013,
++
++      /*
++       *  Device options for the 2 M2M DMA channels
++       */
++      DMA_MEMORY = 0x00000014,
++      DMA_IDE = 0x00000015,
++      DMARx_SSP = 0x00000016,
++      DMATx_SSP = 0x00000017,
++      DMATx_EXT_DREQ = 0x00000018,
++      DMARx_EXT_DREQ = 0x00000019,
++      UNDEF = 0x0000001A
++} ep93xx_dma_dev_t;
++
++/*****************************************************************************
++ *
++ * Enumerated type used as a parameter for a callback function.
++ * Indicates the type of interrupt.
++ *
++ ****************************************************************************/
++typedef enum {
++      /*
++       *  Common interrupts
++       */
++      STALL,
++      NFB,
++
++      /*
++       *  Specific to M2P channels
++       */
++      CHERROR,
++
++      /*
++       *  Specific to M2M channels
++       */
++      DONE,
++      UNDEF_INT
++} ep93xx_dma_int_t;
++
++/*****************************************************************************
++ *
++ * Init flag bit defintions for M2P/P2M flags.
++ *
++ ****************************************************************************/
++
++/*
++ *  Channel error interrupt enable.
++ */
++#define CHANNEL_ERROR_INT_ENABLE    0x00000001
++/*
++ *  Determines how the channel state machine behaves in the NEXT state and
++ *  in receipt of a peripheral error.
++ *  0 -> NEXT -> ON (ignore the peripheral error.)
++ *  1 -> NEXT -> STALL (effectively disable the channel.)
++ */
++#define EP93XX_DMA_ABORT                       0x00000002
++/*
++ *  Ignore channel error interrupt.
++ */
++#define IGNORE_CHANNEL_ERROR        0x00000004
++
++/*****************************************************************************
++ *
++ * Init flag bit defintions for M2M flags.
++ *
++ ****************************************************************************/
++
++/*
++ *  Destination address hold.  This should be set for IDE write transfers
++ */
++#define DESTINATION_HOLD            0x0000001
++/*
++ *  Source Address hold. This should be set for IDE read transfers
++ */
++#define SOURCE_HOLD                 0x0000002
++/*
++ *  Transfer mode.
++ *  00 - s/w initiated M2M transfer
++ *  01 - h/w initiated external peripheral transfer - memory to external
++ *       peripheral/IDE/SSP.
++ *  10 - h/w initiated external peripheral transfer - external
++ *        peripheral/IDE/SSP to memory.
++ *  11 - not used.
++ */
++#define TRANSFER_MODE_MASK          0x000000C
++#define TRANSFER_MODE_SHIFT         2
++#define TRANSFER_MODE_SW            0x0000000
++#define TRANSFER_MODE_HW_M2P        0x0000004
++#define TRANSFER_MODE_HW_P2M        0x0000008
++/*
++ *  Peripheral wait states count. Latency in HCLK cycles needed by the
++ *  peripheral to de-assert its request line once the transfer is
++ *  finished.
++ *
++ *  IDE Operation           Wait States
++ *  --------------          ------------
++ *  IDE MDMA read               0
++ *  IDE MDMA write              0
++ *  IDE UDMA read               1
++ *  IDE UDMA write              2
++ */
++#define WAIT_STATES_MASK            0x00007F0
++#define WAIT_STATES_SHIFT           4
++#define WS_IDE_MDMA_READ_WRITE      0
++#define WS_IDE_UDMA_READ            1
++#define WS_IDE_UDMA_WRITE           2
++
++/*****************************************************************************
++ *
++ * Type definition for the callback function
++ *
++ ****************************************************************************/
++typedef void (*dma_callback) (ep93xx_dma_int_t dma_int,
++                            ep93xx_dma_dev_t device, unsigned int user_data);
++
++/*****************************************************************************
++ *
++ * API function prototypes
++ *
++ ****************************************************************************/
++extern int ep93xx_dma_request(int *handle, const char *device_id,
++                            ep93xx_dma_dev_t device);
++extern int ep93xx_dma_free(int handle);
++extern int ep93xx_dma_config(int handle, unsigned int flags_m2p,
++                           unsigned int flags_m2m,
++                           dma_callback callback, unsigned int user_data);
++extern int ep93xx_dma_add_buffer(int handle, unsigned int source,
++                               unsigned int dest, unsigned int size,
++                               unsigned int last, unsigned int buf_id);
++extern int ep93xx_dma_remove_buffer(int handle, unsigned int *buf_id);
++extern int ep93xx_dma_start(int handle, unsigned int channels,
++                          unsigned int *handles);
++extern int ep93xx_dma_pause(int handle, unsigned int channels,
++                          unsigned int *handles);
++extern int ep93xx_dma_flush(int handle);
++extern int ep93xx_dma_queue_full(int handle);
++extern int ep93xx_dma_get_position(int handle, unsigned int * buf_id,
++                          unsigned int * total, unsigned int * current_frac);
++#endif                                /* _ASM_ARCH_DMA_H */
+diff --git a/include/asm-arm/arch-ep93xx/entry-macro.S b/include/asm-arm/arch-ep93xx/entry-macro.S
+new file mode 100644
+index 0000000..cab811e
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/entry-macro.S
+@@ -0,0 +1,39 @@
++/*
++ * include/asm-arm/arch-ep93xx/entry-macro.S
++ *
++ * Low-level IRQ helper macros for EP93XX-based platforms
++ *
++ * This file is licensed under  the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++                .macro  disable_fiq
++                .endm
++
++                .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
++                ldr     \irqstat, =VIC0IRQSTATUS
++                ldr     \irqstat, [\irqstat, #0]                        @ get masked status
++
++                mov     \irqnr, #0
++1001:           tst     \irqstat, #1
++                bne     1003f
++                add     \irqnr, \irqnr, #1
++                mov     \irqstat, \irqstat, lsr #1
++                cmp     \irqnr, #32
++                bcc     1001b
++                /* EQ will be set if we reach 32 */
++
++                ldr     \irqstat, =VIC1IRQSTATUS
++                ldr     \irqstat, [\irqstat, #0]                        @ get masked status
++
++1002:           tst     \irqstat, #1
++                bne     1003f
++                add     \irqnr, \irqnr, #1
++                mov     \irqstat, \irqstat, lsr #1
++                cmp     \irqnr, #64
++                bcc     1002b
++                /* EQ will be set if we reach 64 */
++
++1003:
++                .endm
+diff --git a/include/asm-arm/arch-ep93xx/hardware.h b/include/asm-arm/arch-ep93xx/hardware.h
+new file mode 100644
+index 0000000..f390858
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/hardware.h
+@@ -0,0 +1,60 @@
++/*
++ *  File:   linux/include/asm-arm/arch-ep93xx/hardware.h
++ *
++ *  Copyright (C) 2003 Cirrus Logic, Inc
++ *
++ *  Copyright (C) 1999 ARM Limited.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef __ASM_ARCH_HARDWARE_H
++#define __ASM_ARCH_HARDWARE_H
++
++#include <asm/arch/clocks.h>
++#include <asm/arch/memory.h>
++#include <asm/arch/regmap.h>
++
++/*
++ * When adding your regs-*.h file here, please be careful to not have any
++ * macros being doubly defined.  You may need to comment out a section of
++ * regmap.h to prevent that.
++ */
++#include <asm/arch/regs_ac97.h>
++#include <asm/arch/regs_dma.h>
++#include <asm/arch/regs_gpio.h>
++#include <asm/arch/regs_ide.h>
++#include <asm/arch/regs_i2s.h>
++#include <asm/arch/regs_irda.h>
++#include <asm/arch/regs_pcmcia.h>
++#include <asm/arch/regs_raster.h>
++#include <asm/arch/regs_spi.h>
++#include <asm/arch/regs_syscon.h>
++#include <asm/arch/regs_touch.h>
++#include <asm/arch/regs_uart.h>
++
++#include <asm/arch/regs_hardcode.h>
++
++#include <asm/arch/cx25871.h>
++
++/*
++ * Here's a safe way for calculating jiffies that won't break if the
++ * value of HZ changes.
++ */
++#ifndef       MSECS_TO_JIFFIES
++#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000)
++#endif
++
++#endif                                /* __ASM_ARCH_HARDWARE_H */
+diff --git a/include/asm-arm/arch-ep93xx/ide.h b/include/asm-arm/arch-ep93xx/ide.h
+new file mode 100644
+index 0000000..7eb7faa
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/ide.h
+@@ -0,0 +1,235 @@
++/*****************************************************************************
++ *  linux/include/asm-arm/arch-ep93xx/ide.h
++ *
++ *  IDE definitions for the EP93XX architecture
++ *
++ *
++ *  Copyright (c) 2003 Cirrus Logic, Inc., All rights reserved.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ ****************************************************************************/
++#ifndef ASM_ARCH_IDE_H
++#define ASM_ARCH_IDE_H
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/hardware.h>
++#include <asm/scatterlist.h>
++
++/*
++ *  Maximum number of IDE interfaces for this architecture is 1.
++ */
++#ifdef CONFIG_BLK_DEV_EP93XX
++#undef  MAX_HWIFS
++#define MAX_HWIFS     1
++#endif
++/*
++ *  Default PIO mode used for setting up DMA commands
++ */
++#define DEFAULT_PIO_MODE          4
++
++/*
++ *  ATA Command Register addresses.
++ */
++
++#define DATAREGISTER            0x00
++#define ERRORREGISTER           0x01
++#define FEATURESREGISTER        0x01
++#define SECTORCOUNTREGISTER     0x02
++#define SECTORNUMBERREGISTER    0x03
++#define CYLINDERLOWREGISTER     0x04
++#define CYLINDERHIGHREGISTER    0x05
++#define DEVICEHEADREGISTER      0x06
++#define COMMANDREGISTER         0x07
++#define STATUSREGISTER          0x07
++
++/*
++ *  ATA Control Register addresses.
++ */
++#define DEVICECONTROLREGISTER   0x06
++#define ALTERNATESTATUSREGISTER 0x06
++
++/*
++ *  ATA Register Bit Masks
++ */
++#define ATASRST                       0x04
++#define ATAnIEN                       0x02
++#define ATADEV                        0x10
++#define ATAABRT                       0x04
++#define ATABSY                        0x80
++#define ATADRDY                       0x40
++#define ATADRQ                        0x08
++#define ATAERR                        0x01
++#define ATADEVFAULT                   0x20
++#define       ATAWRITEFAULT           0x20
++#define ATASERVICE                    0x10
++#define ATACORRECTED          0x04
++#define ATAINDEX                      0x02
++
++#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX
++
++#define EP93XX_DMA_TODEVICE     1
++#define EP93XX_DMA_FROMDEVICE   2
++
++/****************************************************************************
++ *
++ * Map a set of buffers described by scatterlist in streaming
++ * mode for DMA.  This is the scather-gather version of the
++ * above pci_map_single interface.  Here the scatter gather list
++ * elements are each tagged with the appropriate dma address
++ * and length.  They are obtained via sg_dma_{address,length}(SG).
++ *
++ * NOTE: An implementation may be able to use a smaller number of
++ *       DMA address/length pairs than there are SG table elements.
++ *       (for example via virtual mapping capabilities)
++ *       The routine returns the number of addr/length pairs actually
++ *       used, at most nents.
++ *
++ * Device ownership issues as mentioned above for pci_map_single are
++ * the same here.
++ *
++ ****************************************************************************/
++static inline int
++ep93xx_map_sg(struct scatterlist *sg, unsigned int entries,
++            unsigned int direction)
++{
++      unsigned int loop;
++
++      for (loop = 0; loop < entries; loop++, sg++) {
++              consistent_sync(sg->__address, sg->length, direction);
++              sg->dma_address = virt_to_bus(sg->__address);
++      }
++
++      return entries;
++}
++
++#endif                                /* CONFIG_BLK_DEV_IDEDMA_EP93XX */
++
++/*****************************************************************************
++ *
++ * Set up a hw structure for a specified data port, control port and IRQ.
++ * This should follow whatever the default interface uses.
++ *
++ ****************************************************************************/
++static __inline__ void
++old_ide_init_hwif_ports(hw_regs_t * hw, int data_port, int ctrl_port, int *irq)
++{
++      unsigned long reg;
++      int i;
++      printk("ide_init_hwif_ports\n");
++      printk("ide_init_hwif_ports(hw=%p data_port=%08x, ctrl_port=%08x \n",
++             hw, data_port, ctrl_port);
++
++      /*
++       *  Set up the IDE interface for PIO transfers, using the default PIO
++       *  mode.
++       */
++      ep93xx_ide_regs->IDECFG.Field.PIO = 1;
++      ep93xx_ide_regs->IDECFG.Field.MODE = DEFAULT_PIO_MODE;
++      ep93xx_ide_regs->IDECFG.Field.WST = 0;
++
++      /*
++       *  Enable the IDE interface.
++       */
++      ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
++
++      /*
++       *  Set up the ide device command register offsets in the io_port array.
++       *  This offset includes the register offset and the bit settings for
++       *  CS0n and CS1n.
++       */
++      reg = (unsigned long)data_port;
++      for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
++              hw->io_ports[i] = (reg << 2) + 2;
++              reg += 1;
++
++              printk(" io_ports: %08lx\n", hw->io_ports[i]);
++      }
++
++      /*
++       *  Set up the register offset for the device control registers.
++       *  This offset includes the register offset and the bit settings for
++       *  CS0n and CS1n.
++       */
++      reg = (unsigned long)ctrl_port;
++      hw->io_ports[IDE_CONTROL_OFFSET] = (reg << 2) + 1;
++      printk("-io_ports: %08lx\n", hw->io_ports[IDE_CONTROL_OFFSET]);
++
++      if (irq)
++              *irq = 0;
++
++}
++
++extern void ep93xx_ide_init(struct hwif_s *hwif);
++
++/*****************************************************************************
++ *
++ * This registers the standard ports for this architecture with the IDE
++ * driver.
++ *
++ ****************************************************************************/
++static __inline__ void old_ide_init_default_hwifs(void)
++{
++      hw_regs_t hw;
++
++      struct hwif_s *hwif;
++      unsigned int uiTemp;
++
++      /*
++       *  Make sure the GPIO on IDE bits in the DEVCFG register are not set.
++       */
++      uiTemp =
++          readl(SYSCON_DEVCFG) & ~(SYSCON_DEVCFG_EonIDE |
++                                   SYSCON_DEVCFG_GonIDE |
++                                   SYSCON_DEVCFG_HonIDE);
++
++      SysconSetLocked(SYSCON_DEVCFG, uiTemp);
++
++      /*
++       *  Initialize the IDE interface
++       */
++      old_ide_init_hwif_ports(&hw, DATAREGISTER, DEVICECONTROLREGISTER, NULL);
++
++      /*
++       *  Get the interrupt.
++       */
++      hw.irq = IRQ_EIDE;
++
++      /*
++       * This is the dma channel number assigned to this IDE interface. Until
++       * dma is enabled for this interface, we set it to NO_DMA.
++       */
++      hw.dma = NO_DMA;
++      
++      /*
++       * Kernels > 2.6.15-rcX crash when leaving this uninitialized
++       */     
++      hw.dev = NULL;
++      
++      /*
++       *  Register the IDE interface, an ide_hwif_t pointer is passed in,
++       *  which will get filled in with the hwif pointer for this interface.
++       */
++      ide_register_hw(&hw, &hwif);
++
++      /*
++       *  Set up a pointer to the ep93xx ideproc function.
++       */
++      ep93xx_ide_init(hwif);
++
++      printk
++          ("Cirrus Logic EP93XX IDE initialization - driver version 1.0, 5/21/03. \n");
++}
++#endif                                /* ASM_ARCH_IDE_H */
+diff --git a/include/asm-arm/arch-ep93xx/io.h b/include/asm-arm/arch-ep93xx/io.h
+new file mode 100644
+index 0000000..7e2e087
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/io.h
+@@ -0,0 +1,29 @@
++/*
++ *  File:     linux/include/asm-arm/arch-ep93xx/io.h
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __ASM_ARM_ARCH_IO_H
++#define __ASM_ARM_ARCH_IO_H
++
++#define IO_SPACE_LIMIT 0xffffffff
++
++#define __io(a)                       ((void __iomem *)(a))
++#define __mem_pci(a)          (a)
++#define __mem_isa(a)          (a)
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h
+new file mode 100644
+index 0000000..7a58d27
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/irqs.h
+@@ -0,0 +1,150 @@
++/*
++ *  File:     linux/include/asm-arm/arch-ep93xx/irqs.h
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/*
++ *  Linux IRQ interrupts definitions here.
++ *    TBD not worth the effort to put duplicate bit defines in platform.h
++ *
++ *    Current IRQ implementation
++ *
++ *    1.  Current implementation does not support vectored
++ *          interrupts.  support for this feature may be
++ *          added later.
++ *    2.  FIQs are ignored.  None are assigned.
++ *    3.  All interrupts are assigned to IRQs.
++ *    5.  IRQ numbers are same as interrupt bit numbers.
++ *
++ */
++
++/* First two interrupt bit assignments are unused. */
++#define IRQ_RFU0      0
++#define IRQ_RFU1      1
++
++#define IRQ_COMMRX    2
++#define IRQ_COMMTX    3
++
++/* Renamed TCXOI to TIMERX for consistency */
++#define IRQ_TIMER1    4
++#define IRQ_TIMER2    5
++
++#define IRQ_AAC         6
++
++#define IRQ_DMAM2P0   7
++#define IRQ_DMAM2P1   8
++#define IRQ_DMAM2P2     9
++#define IRQ_DMAM2P3   10
++#define IRQ_DMAM2P4   11
++#define IRQ_DMAM2P5   12
++#define IRQ_DMAM2P6   13
++#define IRQ_DMAM2P7   14
++#define IRQ_DMAM2P8   15
++#define IRQ_DMAM2P9     16
++
++#define IRQ_DMAM2M0   17
++#define IRQ_DMAM2M1   18
++
++#define IRQ_GPIO0     19
++#define IRQ_GPIO1     20
++#define IRQ_GPIO2     21
++#define IRQ_GPIO3     22
++
++#define IRQ_UARTRX1   23
++#define IRQ_UARTTX1   24
++#define IRQ_UARTRX2   25
++#define IRQ_UARTTX2   26
++#define IRQ_UARTRX3   27
++#define IRQ_UARTTX3   28
++
++#define IRQ_KEY               29
++#define IRQ_TOUCH     30
++#define IRQ_GRAPHICS  31
++
++/* TODO - this was IRQ_INTX, may need to make changes in code */
++#define IRQ_EXT0      32
++#define IRQ_EXT1      33
++#define IRQ_EXT2      34
++
++#define IRQ_64HZ      35
++#define IRQ_WEINT     36
++#define IRQ_RTC       37
++
++#define IRQ_IRDA      38
++#define IRQ_MAC       39
++
++#define IRQ_EXT3      40
++#define IRQ_EIDE      IRQ_EXT3
++
++#define IRQ_PROG      41
++#define IRQ_1HZ       42
++#define IRQ_VSYNC     43
++#define IRQ_VIDEOFIFO 44
++
++#define IRQ_SSPRX     45
++#define IRQ_SSPTX     46
++
++#define IRQ_GPIO4     47
++
++#define IRQ_GPIO5     48
++#define IRQ_GPIO6     49
++#define IRQ_GPIO7     50
++
++#define IRQ_TIMER3    51
++
++#define IRQ_UART1     52
++#define IRQ_SSP       53
++
++#define IRQ_UART2     54
++#define IRQ_UART3     55
++
++#define IRQ_USH       56
++#define IRQ_PME       57
++#define IRQ_DSP       58
++#define IRQ_GPIO      59
++
++#define IRQ_RFU60     60
++#define IRQ_RFU61     61
++#define IRQ_RFU62     62
++#define IRQ_RFU63     63
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++#define IRQ_TO_BIT(irq) (1 << ((irq - NR_GLBL_IRQS) % 16))
++
++#define NR_GLBL_IRQS    64
++
++#define GPIO_IRQ0     64
++#define GPIO_IRQ1     65
++#define GPIO_IRQ2     66
++#define GPIO_IRQ3     67
++#define GPIO_IRQ4     68
++#define GPIO_IRQ5     69
++#define GPIO_IRQ6     70
++#define GPIO_IRQ7     71
++#define GPIO_IRQ8     72
++#define GPIO_IRQ9     73
++#define GPIO_IRQ10    74
++#define GPIO_IRQ11    75
++#define GPIO_IRQ12    76
++#define GPIO_IRQ13    77
++#define GPIO_IRQ14    78
++#define GPIO_IRQ15    79
++
++#define IRQ_CHAINED_GPIO(x)   (NR_GLBL_IRQS + x)
++#define NR_IRQS               IRQ_CHAINED_GPIO(16)            /* with GPIO IRQs EP9315 has 80 IRQs */
++#else
++#define NR_IRQS    64                                                 /* without GPIO IRQs EP9315 has 64 IRQs */
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/keyboard.h b/include/asm-arm/arch-ep93xx/keyboard.h
+new file mode 100644
+index 0000000..685ff17
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/keyboard.h
+@@ -0,0 +1,54 @@
++/*
++ *  linux/include/asm-arm/arch-integrator/keyboard.h
++ *
++ *  Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ *  Keyboard driver definitions for the Integrator architecture
++ */
++#include <asm/irq.h>
++
++/* Scancode mapping is as follows:
++ *
++ *      Scancode = keycode if key down event
++ *      Scancode = keycode|KBUP if key up event
++ *
++ *      Valid keycodes are 1..0x7F and are defined by the table
++ *      in keymap_dave.map.  Keycode 0 is reserved to mean invalid.
++ *
++ *      Keycodes are computed from scanned key matrix as follows:
++ */
++
++#define       KEYCODE( row, col)      ( ((row)<<4) + (col) + 1)
++#define KBUP  0x80
++#define NR_SCANCODES 128      /*TBD used? */
++
++#ifdef CONFIG_EP93XX_KBD_SCANNED
++void __init ep93xx_scan_kbd_hw_init(void);
++#define kbd_init_hw()                 ep93xx_scan_kbd_hw_init()
++#elif defined CONFIG_EP93XX_KBD_SPI
++void __init EP93XXSpiKbdInit(void);
++#define kbd_init_hw()                 EP93XXSpiKbdInit()
++#elif defined CONFIG_EP93XX_KBD_USB
++void __init EP93XXUSBKbdInit(void);
++#define kbd_init_hw()                 EP93XXUSBKbdInit()
++#endif
++
++#ifdef kbd_sysrq_xlate
++#undef kbd_sysrq_xlate
++#define kbd_sysrq_xlate                       (1)
++#endif
++#define kbd_disable_irq()             disable_irq( IRQ_KEY)
++#define kbd_enable_irq()              enable_irq( IRQ_KEY)
+diff --git a/include/asm-arm/arch-ep93xx/mach-edb9302.h b/include/asm-arm/arch-ep93xx/mach-edb9302.h
+new file mode 100644
+index 0000000..829883a
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/mach-edb9302.h
+@@ -0,0 +1,20 @@
++/*
++ *  linux/include/asm-arm/arch-ep93xx/mach-edb9302.h
++ *
++ *  Copyright 2004 Ray Lehtiniemi
++ *  Copyright 2004 Siconix, 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 __ASM_ARCH_MACHEDB9302_H
++#define __ASM_ARCH_MACHEDB9302_H
++
++#include <asm/arch/ssp2.h>
++
++extern struct ep93xx_ssp_slave ep93xx_ssp_flash;
++extern struct ep93xx_ssp_slave ep93xx_ssp_codec;
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/mach-ttml.h b/include/asm-arm/arch-ep93xx/mach-ttml.h
+new file mode 100644
+index 0000000..665873d
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/mach-ttml.h
+@@ -0,0 +1,23 @@
++/*
++ *  linux/include/asm-arm/arch-ep93xx/mach-ttml.h
++ *
++ *  Copyright 2004 Ray Lehtiniemi
++ *  Copyright 2004 Siconix, 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 __ASM_ARCH_MACHTTML_H
++#define __ASM_ARCH_MACHTTML_H
++
++#include <asm/arch/ssp2.h>
++
++extern struct ep93xx_ssp_slave ep93xx_ssp_micro;
++extern struct ep93xx_ssp_slave ep93xx_ssp_expansion;
++
++extern int ssp_do_ttml(struct ep93xx_ssp_slave *s, void *tx, int tlen, void *rx,
++                     int rlen);
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/memory.h b/include/asm-arm/arch-ep93xx/memory.h
+new file mode 100644
+index 0000000..57e266e
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/memory.h
+@@ -0,0 +1,256 @@
++/*
++ *  linux/include/asm-arm/arch-ep93xx/memory.h
++ *
++ *  ******************************************************
++ *    *    CONFUSED?  Read Documentation/IO-mapping.txt        *
++ *  ******************************************************
++ *
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *  Copyright (C) 2002-2003 Cirrus Logic Corp.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __ASM_ARCH_MMU_H
++#define __ASM_ARCH_MMU_H
++
++/*
++ * For EP93xx, SDRAM can be discontiguous, in a set number of blocks
++ * of equal size and (usually) equal spacing.  The 9301 spacing isn't equal.
++ *
++ * SDRAM_START is the physical address of the start of SDRAM.
++ * SDRAM_NUMBER_OF_BLOCKS = # of blocks of SDRAM.
++ * Each block is of size SDRAM_BLOCK_SIZE and starts at a boundary
++ * of SDRAM_BLOCK_START_BOUNDARY.
++ *
++ * So memory blocks are at:
++ *  SDRAM_START
++ *  SDRAM_START + SDRAM_BLOCK_START_BOUNDARY
++ *  SDRAM_START + (SDRAM_BLOCK_START_BOUNDARY * 2)
++ *  SDRAM_START + (SDRAM_BLOCK_START_BOUNDARY * 3)
++ *  so on
++ */
++
++#ifndef CONFIG_DISCONTIGMEM
++
++/*
++ * Single 32Meg block of physical memory physically located at 0 .
++ */
++#define SDRAM_START                         0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS              1
++#define SDRAM_BLOCK_SIZE                    0x02000000
++#define SDRAM_BLOCK_START_BOUNDARY          0x00000000
++
++#else                         /* CONFIG_DISCONTIGMEM */
++
++#if defined(CONFIG_MACH_EDB9301)
++/*
++ * 4 8Meg blocks at 0x0n000000, n={0145}
++ */
++#define SDRAM_START                         0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS              4
++#define SDRAM_BLOCK_SIZE                    0x00800000
++#define SDRAM_BLOCK_START_BOUNDARY          0x01000000
++#endif
++
++#if defined(CONFIG_MACH_TTML)
++#define SDRAM_START                         0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS              1
++#define SDRAM_BLOCK_SIZE                    0x02000000
++#define SDRAM_BLOCK_START_BOUNDARY          0x02000000
++#endif
++
++#if defined(CONFIG_MACH_EDB9302)
++/*
++ * 4 8Meg blocks at 0x0n000000, n={0145}
++ */
++#define SDRAM_START                         0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS              4
++#define SDRAM_BLOCK_SIZE                    0x00800000
++#define SDRAM_BLOCK_START_BOUNDARY          0x01000000
++#endif
++
++#if defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || defined(CONFIG_MACH_ADSSPHERE)
++/*
++ * 2 32Meg blocks that are located physically at 0 and 64Meg.
++ */
++#define SDRAM_START                         0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS              2
++#define SDRAM_BLOCK_SIZE                    0x02000000
++#define SDRAM_BLOCK_START_BOUNDARY          0x04000000
++#endif
++
++#if defined(CONFIG_MACH_DMA03)
++/*
++ * 2 32Meg blocks that are located physically at 0 and 64Meg.
++ */
++#define SDRAM_START                         0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS              2
++#define SDRAM_BLOCK_SIZE                    0x02000000
++#define SDRAM_BLOCK_START_BOUNDARY          0x04000000
++#endif
++
++#if defined(CONFIG_MACH_ACC)
++/*
++ * 8 8Meg blocks that are located physically at 0xC0000000
++ * total 64Meg.
++ */
++#define SDRAM_START                         0xC0000000
++#define SDRAM_NUMBER_OF_BLOCKS              8
++#define SDRAM_BLOCK_SIZE                    0x00800000
++#define SDRAM_BLOCK_START_BOUNDARY          0x01000000
++#endif
++
++#if defined(CONFIG_MACH_ZEFEERDZB)
++/*
++ * 2 8Meg blocks
++ */
++#define SDRAM_START                         0xD0000000
++#define SDRAM_NUMBER_OF_BLOCKS              2
++#define SDRAM_BLOCK_SIZE                    0x00800000
++#define SDRAM_BLOCK_START_BOUNDARY          0x01000000
++#endif
++
++#if defined(CONFIG_MACH_ZEFEERDZQ)
++/*
++ * 2 32Meg blocks
++ */
++#define SDRAM_START                         0xD0000000
++#define SDRAM_NUMBER_OF_BLOCKS              2
++#define SDRAM_BLOCK_SIZE                    0x02000000
++#define SDRAM_BLOCK_START_BOUNDARY          0x04000000
++#endif
++
++/*
++ * Here we are assuming EP93xx is configured to have two 32MB SDRAM
++ * areas with 32MB of empty space between them.  So use 24 for the node
++ * max shift to get 64MB node sizes.
++ */
++#define NODE_MAX_MEM_SHIFT    26
++#define NODE_MAX_MEM_SIZE     (1<<NODE_MAX_MEM_SHIFT)
++
++#endif                                /* CONFIG_DISCONTIGMEM */
++
++/*
++ * MEM_SIZE and PHYS_OFFSET are used to set size of SDRAM for
++ * initial page table in arch/arm/kernel/setup.c
++ * For ep93xx, PHYS_OFFSET is set to be SDRAM_START.
++ */
++#define MEM_SIZE                            (SDRAM_BLOCK_SIZE)
++
++/*
++ * If memory is not discontiguous, this is #defined   in
++ * arch/arm/mm/init.c to be 1.
++ */
++#ifdef CONFIG_DISCONTIGMEM
++#define NR_NODES                                                      (SDRAM_NUMBER_OF_BLOCKS)
++#endif
++
++/*
++ * Where to load the ramdisk (virtual address, not physical) and how
++ * big to make it. (used in arch/arm/kernel/setup.c
++ * In both cases, when redboot loads the ramdisk image to 0x01000000,
++ * the processor will find it because the linux map is funny.
++ */
++#ifdef CONFIG_ARCH_EP9301
++#define RAMDISK_START_VIRT      (0xC4000000)
++#else
++#define RAMDISK_START_VIRT      (0xC1000000)
++#endif
++
++/*
++ * The ramdisk size comes from a make menuconfig option.
++ */
++#define RAMDISK_SIZE            ((CONFIG_BLK_DEV_RAM_SIZE)<<10)
++
++/*
++ * Task size: 2GB (from 0 to base of IO in virtual space)
++ */
++#define TASK_SIZE             UL(0x7f000000)
++
++/*
++ * This decides where the kernel will search for a free chunk of vm
++ * space during mmap's.
++ */
++#define TASK_UNMAPPED_BASE (0x40000000)
++
++/*
++ * Page offset: 3GB (start of kernel memory in virtual space)
++ * Phys offset: 0   (start of kernel memory in physical space)
++ */
++#define PAGE_OFFSET           UL(0xC0000000)
++#define PHYS_OFFSET           (SDRAM_START)
++
++/*
++ * We take advantage of the fact that physical and virtual address can be the
++ * same.  The NUMA code is handling the large holes that might exist between
++ * all memory banks.
++ */
++#define __virt_to_phys__is_a_macro
++#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + PHYS_OFFSET)
++
++#define __phys_to_virt__is_a_macro
++#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - PHYS_OFFSET)
++
++/*
++ * Virtual view <-> DMA view memory address translations
++ * virt_to_bus: Used to translate the virtual address to an
++ *              address suitable to be passed to set_dma_addr
++ * bus_to_virt: Used to convert an address for DMA operations
++ *              to an address that the kernel can use.
++ */
++#define __virt_to_bus__is_a_macro
++#define __virt_to_bus(x)       __virt_to_phys(x)
++
++#define __bus_to_virt__is_a_macro
++#define __bus_to_virt(x)       __phys_to_virt(x)
++
++/*
++ * Note that this file is included by include/asm-arm/memory.h so
++ * the macros in this file have to play nice with those.
++ */
++#ifdef CONFIG_DISCONTIGMEM
++
++/*
++ * Given a kernel address, find the home node of the underlying memory.
++ */
++#define KVADDR_TO_NID(addr) \
++              (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT)
++
++/*
++ * Given a page frame number, convert it to a node id.
++ */
++#define PFN_TO_NID(pfn) \
++      (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT))
++
++/*
++ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
++ * and returns the mem_map of that node.
++ */
++#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
++
++#define PFN_TO_MAPBASE(pfn)   NODE_MEM_MAP(PFN_TO_NID(pfn))
++
++/*
++ * Given a kaddr, LOCAL_MAR_NR finds the owning node of the memory
++ * and returns the index corresponding to the appropriate page in the
++ * node's mem_map.
++ */
++#define LOCAL_MAP_NR(kaddr) \
++      (((unsigned long)(kaddr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT)
++
++#endif                                /* CONFIG_DISCONTIGMEM */
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/param.h b/include/asm-arm/arch-ep93xx/param.h
+new file mode 100644
+index 0000000..525face
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/param.h
+@@ -0,0 +1,21 @@
++/*
++ *  linux/include/asm-arm/arch-integrator/param.h
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/* #define HZ 100 */
+diff --git a/include/asm-arm/arch-ep93xx/platform.h b/include/asm-arm/arch-ep93xx/platform.h
+new file mode 100644
+index 0000000..d92833d
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/platform.h
+@@ -0,0 +1,43 @@
++/*
++ *  linux/include/asm-arm/arch-ep93xx/platform.h
++ *
++ *  Copyright (C) 2002-2003 Cirrus Logic, 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.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef ASM_ARCH_PLATFORM_H
++#define ASM_ARCH_PLATFORM_H
++
++/*
++ *  Timer definitions
++ *
++ *  Use timers 1, 2, and 3.  Do not use timer 4.
++ *  Timers run at 508 kHz.
++ */
++
++/*
++ *  These are useconds NOT ticks.
++ */
++#define mSEC_1                          1000
++#define mSEC_5                          (mSEC_1 * 5)
++#define mSEC_10                         (mSEC_1 * 10)
++#define mSEC_25                         (mSEC_1 * 25)
++#define SEC_1                           (mSEC_1 * 1000)
++
++#ifndef __ASSEMBLY__
++extern struct sys_timer ep93xx_timer;
++#endif
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/regmap.h b/include/asm-arm/arch-ep93xx/regmap.h
+new file mode 100644
+index 0000000..7b3eeac
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regmap.h
+@@ -0,0 +1,1125 @@
++/*
++ *  File:   linux/include/asm-arm/arch-ep93xx/regmap.h
++ *
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *  Copyright (C) 2003 Cirrus Logic, Inc
++ *  Copyright (C) 1999 ARM Limited.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef __ASM_ARCH_REGMAP_H
++#define __ASM_ARCH_REGMAP_H
++
++/*
++ * Here's the rules:
++ * - EP93xx register addresses in regmap.h are physical addresses.
++ *
++ * - io_p2v translates a physical address to a virtual one for the
++ *   EP93xx's register space only.  Don't use it for actual memory.
++ *
++ */
++
++#define IO_BASE_VIRT        0xE0000000        /* Virtual address of IO */
++#define IO_BASE_PHYS        0x80000000        /* Physical address of IO */
++
++/*
++ * The HW_REG macro assumes that the param is a virtual address
++ */
++#define HW_REG(reg) ((unsigned int volatile *)reg)
++
++/*
++ * Macro to get at IO space when running virtually.
++ * (Translates a physical address to a virtual address)
++ * First cast the pa to an unsigned int in case we are using this
++ * on a macro that is already cast as a pointer.
++ */
++
++#define io_p2v(x) ((x) - (IO_BASE_PHYS - IO_BASE_VIRT))
++#define io_v2p(x) ((x) - (IO_BASE_VIRT - IO_BASE_PHYS))
++
++/******************************************************************/
++/*         EP93xx Memory Map and Register list                    */
++/******************************************************************/
++/*                                                                */
++/* 0000_0000 - 0000_ffff: Internal ROM/nSDCE3/nCS0                */
++/* 0001_0000 - 0fff_ffff: nSDCE3/nCS0                             */
++/* 1000_0000 - 1fff_ffff: nCS1                                    */
++/* 2000_0000 - 2fff_ffff: nCS2                                    */
++/* 3000_0000 - 3fff_ffff: nCS3                                    */
++/* 4000_0000 - 4fff_ffff: Reserved                                */
++/* 5000_0000 - 5fff_ffff: Reserved                                */
++/* 6000_0000 - 6fff_ffff: nCS6                                    */
++/* 7000_0000 - 7fff_ffff: nCS7                                    */
++/* 8000_0000 - 800f_ffff: AHB Registers                           */
++/* 8010_0000 - 807f_ffff: Reserved                                */
++/* 8080_0000 - 8fff_ffff: APB Registers                           */
++/* 9000_0000 - bfff_ffff: Not Used                                */
++/* c000_0000 - cfff_ffff: nSDCE0                                  */
++/* d000_0000 - dfff_ffff: nSDCE1                                  */
++/* e000_0000 - efff_ffff: nSDCE2                                  */
++/* f000_0000 - ffff_ffff: nCS0/nSDCE3                             */
++/*                                                                */
++/******************************************************************/
++
++/******************************************************************/
++/*         EP93xx AHB Blocks                                      */
++/******************************************************************/
++/*                                                                */
++/* Start     End         Usage                                    */
++/* 8000_0000 8000_FFFF:  DMA                                      */
++/* 8001_0000 8001_FFFF:  Ethernet MAC                             */
++/* 8002_0000 8002_FFFF:  USB Host                                 */
++/* 8003_0000 8003_FFFF:  Raster                                   */
++/* 8004_0000 8004_FFFF:  Reserved                                 */
++/* 8005_0000 8005_FFFF:  Reserved                                 */
++/* 8006_0000 8006_FFFF:  SDRAM                                    */
++/* 8007_0000 8007_FFFF:  Reserved                                 */
++/* 8008_0000 8008_FFFF:  SMC                                      */
++/* 8009_0000 8009_FFFF:  Boot ROM physical address                */
++/* 800A_0000 800A_FFFF:  IDE                                      */
++/* 800B_0000 800B_FFFF:  VIC1                                     */
++/* 800C_0000 800C_FFFF:  VIC2                                     */
++/* 800D_0000 800F_FFFF:  Reserved                                 */
++/*                                                                */
++/******************************************************************/
++
++#define EP93XX_AHB_BASE (IO_BASE_VIRT)
++
++/* 8000_0000 - 8000_ffff: DMA  */
++#define DMA_OFFSET              0x000000
++#define DMA_BASE                (EP93XX_AHB_BASE|DMA_OFFSET)
++#define DMAMP_TX_0_CONTROL      (DMA_BASE+0x0000)
++#define DMAMP_TX_0_INTERRUPT    (DMA_BASE+0x0004)
++#define DMAMP_TX_0_PPALLOC      (DMA_BASE+0x0008)
++#define DMAMP_TX_0_STATUS       (DMA_BASE+0x000C)
++#define DMAMP_TX_0_REMAIN       (DMA_BASE+0x0014)
++#define DMAMP_TX_0_MAXCNT0      (DMA_BASE+0x0020)
++#define DMAMP_TX_0_BASE0        (DMA_BASE+0x0024)
++#define DMAMP_TX_0_CURRENT0     (DMA_BASE+0x0028)
++#define DMAMP_TX_0_MAXCNT1      (DMA_BASE+0x0030)
++#define DMAMP_TX_0_BASE1        (DMA_BASE+0x0034)
++#define DMAMP_TX_0_CURRENT1     (DMA_BASE+0x0038)
++
++#define DMAMP_RX_1_CONTROL      (DMA_BASE+0x0040)
++#define DMAMP_RX_1_INTERRUPT    (DMA_BASE+0x0044)
++#define DMAMP_RX_1_PPALLOC      (DMA_BASE+0x0048)
++#define DMAMP_RX_1_STATUS       (DMA_BASE+0x004C)
++#define DMAMP_RX_1_REMAIN       (DMA_BASE+0x0054)
++#define DMAMP_RX_1_MAXCNT0      (DMA_BASE+0x0060)
++#define DMAMP_RX_1_BASE0        (DMA_BASE+0x0064)
++#define DMAMP_RX_1_CURRENT0     (DMA_BASE+0x0068)
++#define DMAMP_RX_1_MAXCNT1      (DMA_BASE+0x0070)
++#define DMAMP_RX_1_BASE1        (DMA_BASE+0x0074)
++#define DMAMP_RX_1_CURRENT1     (DMA_BASE+0x0078)
++
++#define DMAMP_TX_2_CONTROL      (DMA_BASE+0x0080)
++#define DMAMP_TX_2_INTERRUPT    (DMA_BASE+0x0084)
++#define DMAMP_TX_2_PPALLOC      (DMA_BASE+0x0088)
++#define DMAMP_TX_2_STATUS       (DMA_BASE+0x008C)
++#define DMAMP_TX_2_REMAIN       (DMA_BASE+0x0094)
++#define DMAMP_TX_2_MAXCNT0      (DMA_BASE+0x00A0)
++#define DMAMP_TX_2_BASE0        (DMA_BASE+0x00A4)
++#define DMAMP_TX_2_CURRENT0     (DMA_BASE+0x00A8)
++#define DMAMP_TX_2_MAXCNT1      (DMA_BASE+0x00B0)
++#define DMAMP_TX_2_BASE1        (DMA_BASE+0x00B4)
++#define DMAMP_TX_2_CURRENT1     (DMA_BASE+0x00B8)
++
++#define DMAMP_RX_3_CONTROL      (DMA_BASE+0x00C0)
++#define DMAMP_RX_3_INTERRUPT    (DMA_BASE+0x00C4)
++#define DMAMP_RX_3_PPALLOC      (DMA_BASE+0x00C8)
++#define DMAMP_RX_3_STATUS       (DMA_BASE+0x00CC)
++#define DMAMP_RX_3_REMAIN       (DMA_BASE+0x00D4)
++#define DMAMP_RX_3_MAXCNT0      (DMA_BASE+0x00E0)
++#define DMAMP_RX_3_BASE0        (DMA_BASE+0x00E4)
++#define DMAMP_RX_3_CURRENT0     (DMA_BASE+0x00E8)
++#define DMAMP_RX_3_MAXCNT1      (DMA_BASE+0x00F0)
++#define DMAMP_RX_3_BASE1        (DMA_BASE+0x00F4)
++#define DMAMP_RX_3_CURRENT1     (DMA_BASE+0x00F8)
++
++#define DMAMM_0_CONTROL         (DMA_BASE+0x0100)
++#define DMAMM_0_INTERRUPT       (DMA_BASE+0x0104)
++#define DMAMM_0_STATUS          (DMA_BASE+0x010C)
++#define DMAMM_0_BCR0            (DMA_BASE+0x0110)
++#define DMAMM_0_BCR1            (DMA_BASE+0x0114)
++#define DMAMM_0_SAR_BASE0       (DMA_BASE+0x0118)
++#define DMAMM_0_SAR_BASE1       (DMA_BASE+0x011C)
++#define DMAMM_0_SAR_CURRENT0    (DMA_BASE+0x0124)
++#define DMAMM_0_SAR_CURRENT1    (DMA_BASE+0x0128)
++#define DMAMM_0_DAR_BASE0       (DMA_BASE+0x012C)
++#define DMAMM_0_DAR_BASE1       (DMA_BASE+0x0130)
++#define DMAMM_0_DAR_CURRENT0    (DMA_BASE+0x0134)
++#define DMAMM_0_DAR_CURRENT1    (DMA_BASE+0x013C)
++
++#define DMAMM_1_CONTROL         (DMA_BASE+0x0140)
++#define DMAMM_1_INTERRUPT       (DMA_BASE+0x0144)
++#define DMAMM_1_STATUS          (DMA_BASE+0x014C)
++#define DMAMM_1_BCR0            (DMA_BASE+0x0150)
++#define DMAMM_1_BCR1            (DMA_BASE+0x0154)
++#define DMAMM_1_SAR_BASE0       (DMA_BASE+0x0158)
++#define DMAMM_1_SAR_BASE1       (DMA_BASE+0x015C)
++#define DMAMM_1_SAR_CURRENT0    (DMA_BASE+0x0164)
++#define DMAMM_1_SAR_CURRENT1    (DMA_BASE+0x0168)
++#define DMAMM_1_DAR_BASE0       (DMA_BASE+0x016C)
++#define DMAMM_1_DAR_BASE1       (DMA_BASE+0x0170)
++#define DMAMM_1_DAR_CURRENT0    (DMA_BASE+0x0174)
++#define DMAMM_1_DAR_CURRENT1    (DMA_BASE+0x017C)
++
++#define DMAMP_RX_5_CONTROL      (DMA_BASE+0x0200)
++#define DMAMP_RX_5_INTERRUPT    (DMA_BASE+0x0204)
++#define DMAMP_RX_5_PPALLOC      (DMA_BASE+0x0208)
++#define DMAMP_RX_5_STATUS       (DMA_BASE+0x020C)
++#define DMAMP_RX_5_REMAIN       (DMA_BASE+0x0214)
++#define DMAMP_RX_5_MAXCNT0      (DMA_BASE+0x0220)
++#define DMAMP_RX_5_BASE0        (DMA_BASE+0x0224)
++#define DMAMP_RX_5_CURRENT0     (DMA_BASE+0x0228)
++#define DMAMP_RX_5_MAXCNT1      (DMA_BASE+0x0230)
++#define DMAMP_RX_5_BASE1        (DMA_BASE+0x0234)
++#define DMAMP_RX_5_CURRENT1     (DMA_BASE+0x0238)
++
++#define DMAMP_TX_4_CONTROL      (DMA_BASE+0x0240)
++#define DMAMP_TX_4_INTERRUPT    (DMA_BASE+0x0244)
++#define DMAMP_TX_4_PPALLOC      (DMA_BASE+0x0248)
++#define DMAMP_TX_4_STATUS       (DMA_BASE+0x024C)
++#define DMAMP_TX_4_REMAIN       (DMA_BASE+0x0254)
++#define DMAMP_TX_4_MAXCNT0      (DMA_BASE+0x0260)
++#define DMAMP_TX_4_BASE0        (DMA_BASE+0x0264)
++#define DMAMP_TX_4_CURRENT0     (DMA_BASE+0x0268)
++#define DMAMP_TX_4_MAXCNT1      (DMA_BASE+0x0270)
++#define DMAMP_TX_4_BASE1        (DMA_BASE+0x0274)
++#define DMAMP_TX_4_CURRENT1     (DMA_BASE+0x0278)
++
++#define DMAMP_RX_7_CONTROL      (DMA_BASE+0x0280)
++#define DMAMP_RX_7_INTERRUPT    (DMA_BASE+0x0284)
++#define DMAMP_RX_7_PPALLOC      (DMA_BASE+0x0288)
++#define DMAMP_RX_7_STATUS       (DMA_BASE+0x028C)
++#define DMAMP_RX_7_REMAIN       (DMA_BASE+0x0294)
++#define DMAMP_RX_7_MAXCNT0      (DMA_BASE+0x02A0)
++#define DMAMP_RX_7_BASE0        (DMA_BASE+0x02A4)
++#define DMAMP_RX_7_CURRENT0     (DMA_BASE+0x02A8)
++#define DMAMP_RX_7_MAXCNT1      (DMA_BASE+0x02B0)
++#define DMAMP_RX_7_BASE1        (DMA_BASE+0x02B4)
++#define DMAMP_RX_7_CURRENT1     (DMA_BASE+0x02B8)
++
++#define DMAMP_TX_6_CONTROL      (DMA_BASE+0x02C0)
++#define DMAMP_TX_6_INTERRUPT    (DMA_BASE+0x02C4)
++#define DMAMP_TX_6_PPALLOC      (DMA_BASE+0x02C8)
++#define DMAMP_TX_6_STATUS       (DMA_BASE+0x02CC)
++#define DMAMP_TX_6_REMAIN       (DMA_BASE+0x02D4)
++#define DMAMP_TX_6_MAXCNT0      (DMA_BASE+0x02E0)
++#define DMAMP_TX_6_BASE0        (DMA_BASE+0x02E4)
++#define DMAMP_TX_6_CURRENT0     (DMA_BASE+0x02E8)
++#define DMAMP_TX_6_MAXCNT1      (DMA_BASE+0x02F0)
++#define DMAMP_TX_6_BASE1        (DMA_BASE+0x02F4)
++#define DMAMP_TX_6_CURRENT1     (DMA_BASE+0x02F8)
++
++#define DMAMP_RX_9_CONTROL      (DMA_BASE+0x0300)
++#define DMAMP_RX_9_INTERRUPT    (DMA_BASE+0x0304)
++#define DMAMP_RX_9_PPALLOC      (DMA_BASE+0x0308)
++#define DMAMP_RX_9_STATUS       (DMA_BASE+0x030C)
++#define DMAMP_RX_9_REMAIN       (DMA_BASE+0x0314)
++#define DMAMP_RX_9_MAXCNT0      (DMA_BASE+0x0320)
++#define DMAMP_RX_9_BASE0        (DMA_BASE+0x0324)
++#define DMAMP_RX_9_CURRENT0     (DMA_BASE+0x0328)
++#define DMAMP_RX_9_MAXCNT1      (DMA_BASE+0x0330)
++#define DMAMP_RX_9_BASE1        (DMA_BASE+0x0334)
++#define DMAMP_RX_9_CURRENT1     (DMA_BASE+0x0338)
++
++#define DMAMP_TX_8_CONTROL      (DMA_BASE+0x0340)
++#define DMAMP_TX_8_INTERRUPT    (DMA_BASE+0x0344)
++#define DMAMP_TX_8_PPALLOC      (DMA_BASE+0x0348)
++#define DMAMP_TX_8_STATUS       (DMA_BASE+0x034C)
++#define DMAMP_TX_8_REMAIN       (DMA_BASE+0x0354)
++#define DMAMP_TX_8_MAXCNT0      (DMA_BASE+0x0360)
++#define DMAMP_TX_8_BASE0        (DMA_BASE+0x0364)
++#define DMAMP_TX_8_CURRENT0     (DMA_BASE+0x0368)
++#define DMAMP_TX_8_MAXCNT1      (DMA_BASE+0x0370)
++#define DMAMP_TX_8_BASE1        (DMA_BASE+0x0374)
++#define DMAMP_TX_8_CURRENT1     (DMA_BASE+0x0378)
++
++#define DMA_ARBITRATION         (DMA_BASE+0x0380)
++#define DMA_INTERRUPT           (DMA_BASE+0x03C0)
++
++/*
++ * DMA Register Base addresses and Offsets
++ */
++#define DMA_M2P_TX_0_BASE       DMAMP_TX_0_CONTROL
++#define DMA_M2P_RX_1_BASE       DMAMP_RX_1_CONTROL
++#define DMA_M2P_TX_2_BASE       DMAMP_TX_2_CONTROL
++#define DMA_M2P_RX_3_BASE       DMAMP_RX_3_CONTROL
++#define DMA_M2M_0_BASE          DMAMM_0_CONTROL
++#define DMA_M2M_1_BASE          DMAMM_1_CONTROL
++#define DMA_M2P_RX_5_BASE       DMAMP_RX_5_CONTROL
++#define DMA_M2P_TX_4_BASE       DMAMP_TX_4_CONTROL
++#define DMA_M2P_RX_7_BASE       DMAMP_RX_7_CONTROL
++#define DMA_M2P_TX_6_BASE       DMAMP_TX_6_CONTROL
++#define DMA_M2P_RX_9_BASE       DMAMP_RX_9_CONTROL
++#define DMA_M2P_TX_8_BASE       DMAMP_TX_8_CONTROL
++
++#define M2P_OFFSET_CONTROL          0x0000
++#define M2P_OFFSET_INTERRUPT        0x0004
++#define M2P_OFFSET_PPALLOC          0x0008
++#define M2P_OFFSET_STATUS           0x000C
++#define M2P_OFFSET_REMAIN           0x0014
++#define M2P_OFFSET_MAXCNT0          0x0020
++#define M2P_OFFSET_BASE0            0x0024
++#define M2P_OFFSET_CURRENT0         0x0028
++#define M2P_OFFSET_MAXCNT1          0x0030
++#define M2P_OFFSET_BASE1            0x0034
++#define M2P_OFFSET_CURRENT1         0x0038
++
++#define M2M_OFFSET_CONTROL          0x0000
++#define M2M_OFFSET_INTERRUPT        0x0004
++#define M2M_OFFSET_STATUS           0x000C
++#define M2M_OFFSET_BCR0             0x0010
++#define M2M_OFFSET_BCR1             0x0014
++#define M2M_OFFSET_SAR_BASE0        0x0018
++#define M2M_OFFSET_SAR_BASE1        0x001C
++#define M2M_OFFSET_SAR_CURRENT0     0x0024
++#define M2M_OFFSET_SAR_CURRENT1     0x0028
++#define M2M_OFFSET_DAR_BASE0        0x002C
++#define M2M_OFFSET_DAR_BASE1        0x0030
++#define M2M_OFFSET_DAR_CURRENT0     0x0034
++#define M2M_OFFSET_DAR_CURRENT1     0x003C
++
++/*----------------------------------------------------------------*/
++/* 8001_0000 - 8001_ffff: Ether MAC                               */
++/*----------------------------------------------------------------*/
++#define MAC_OFFSET              0x010000
++#define MAC_BASE                (EP93XX_AHB_BASE|MAC_OFFSET)
++
++#define MAC_RXCTL               (MAC_BASE+0x00)
++#define MAC_TXCTL               (MAC_BASE+0x04)
++#define MAC_TESTCTL             (MAC_BASE+0x08)
++#define MAC_MIICMD              (MAC_BASE+0x10)
++#define MAC_MIIDATA             (MAC_BASE+0x14)
++#define MAC_MIISTS              (MAC_BASE+0x18)
++#define MAC_SELFCTL             (MAC_BASE+0x20)
++#define MAC_INTEN               (MAC_BASE+0x24)
++#define MAC_INTSTSP             (MAC_BASE+0x28)
++#define MAC_INTSTSC             (MAC_BASE+0x2C)
++#define MAC_DIAGAD              (MAC_BASE+0x38)
++#define MAC_DIAGDATA            (MAC_BASE+0x3C)
++#define MAC_GT                  (MAC_BASE+0x40)
++#define MAC_FCT                 (MAC_BASE+0x44)
++#define MAC_FCF                 (MAC_BASE+0x48)
++#define MAC_AFP                 (MAC_BASE+0x4C)
++#define MAC_HASHTBL             (MAC_BASE+0x50)
++#define MAC_INDAD               (MAC_BASE+0x50)
++#define MAC_INDAD_UPPER         (MAC_BASE+0x54)
++#define MAC_GIINTSTS            (MAC_BASE+0x60)
++#define MAC_GIINTMSK            (MAC_BASE+0x64)
++#define MAC_GIINTROSTS          (MAC_BASE+0x68)
++#define MAC_GIINTFRC            (MAC_BASE+0x6C)
++#define MAC_TXCOLLCNT           (MAC_BASE+0x70)
++#define MAC_RXMISSCNT           (MAC_BASE+0x74)
++#define MAC_RXRUNTCNT           (MAC_BASE+0x78)
++#define MAC_BMCTL               (MAC_BASE+0x80)
++#define MAC_BMSTS               (MAC_BASE+0x84)
++#define MAC_RXBCA               (MAC_BASE+0x88)
++#define MAC_RXDQBADD            (MAC_BASE+0x90)
++#define MAC_RXDQBLEN            (UINT16*)(MAC_BASE+0x94)
++#define MAC_RXDQCURLEN          (UINT16*)(MAC_BASE+0x96)
++#define MAC_RXDCURADD           (MAC_BASE+0x98)
++#define MAC_RXDENQ              (MAC_BASE+0x9C)
++#define MAC_RXSTSQBADD          (MAC_BASE+0xA0)
++#define MAC_RXSTSQBLEN          (UINT16*)(MAC_BASE+0xA4)
++#define MAC_RXSTSQCURLEN        (UINT16*)(MAC_BASE+0xA6)
++#define MAC_RXSTSQCURADD        (MAC_BASE+0xA8)
++#define MAC_RXSTSENQ            (MAC_BASE+0xAC)
++#define MAC_TXDQBADD            (MAC_BASE+0xB0)
++#define MAC_TXDQBLEN            (MAC_BASE+0xB4)
++#define MAC_TXDQCURLEN          (MAC_BASE+0xB6)
++#define MAC_TXDQCURADD          (MAC_BASE+0xB8)
++#define MAC_TXDENQ              (MAC_BASE+0xBC)
++#define MAC_TXSTSQBADD          (MAC_BASE+0xC0)
++#define MAC_TXSTSQBLEN          (MAC_BASE+0xC4)
++#define MAC_TXSTSQCURLEN        (MAC_BASE+0xC6)
++#define MAC_TXSTSQCURADD        (MAC_BASE+0xC8)
++#define MAC_RXBUFTHRSHLD        (MAC_BASE+0xD0)
++#define MAC_TXBUFTHRSHLD        (MAC_BASE+0xD4)
++#define MAC_RXSTSTHRSHLD        (MAC_BASE+0xD8)
++#define MAC_TXSTSTHRSHLD        (MAC_BASE+0xDC)
++#define MAC_RXDTHRSHLD          (MAC_BASE+0xE0)
++#define MAC_TXDTHRSHLD          (MAC_BASE+0xE4)
++#define MAC_MAXFRMLEN           (MAC_BASE+0xE8)
++#define MAC_RXHDRLEN            (MAC_BASE+0xEC)
++
++#define MAC_FIFO              (MAC_BASE+0x4000)
++#define MAC_FIFO_LEN          0xc000
++
++/*----------------------------------------------------------------*/
++/* 8002_0000 - 8002_ffff: USB                                     */
++/*----------------------------------------------------------------*/
++#define USB_OFFSET              0x020000
++#define USB_BASE                (EP93XX_AHB_BASE|USB_OFFSET)
++
++#define HCREVISION              (USB_BASE+0x00)
++#define HCCONTROL               (USB_BASE+0x04)
++#define HCCOMMANDSTATUS         (USB_BASE+0x08)
++#define HCINTERRUPTSTATUS       (USB_BASE+0x0C)
++#define HCINTERRUPTENABLE       (USB_BASE+0x10)
++#define HCINTERRUPTDISABLE      (USB_BASE+0x14)
++#define HCHCCA                  (USB_BASE+0x18)
++#define HCPERIODCURRENTED       (USB_BASE+0x1C)
++#define HCCONTROLHEADED         (USB_BASE+0x20)
++#define HCCONTROLCURRENTED      (USB_BASE+0x24)
++#define HCBULKHEADED            (USB_BASE+0x28)
++#define HCBULKCURRENTED         (USB_BASE+0x2C)
++#define HCDONEHEAD              (USB_BASE+0x30)
++#define HCFMINTERVAL            (USB_BASE+0x34)
++#define HCFMREMAINING           (USB_BASE+0x38)
++#define HCFMNUMBER              (USB_BASE+0x3C)
++#define HCPERIODICSTART         (USB_BASE+0x40)
++#define HCLSTHRESHOLD           (USB_BASE+0x44)
++#define HCRHDESCRIPTORA         (USB_BASE+0x48)
++#define HCRHDESCRIPTORB         (USB_BASE+0x4C)
++#define HCRHSTATUS              (USB_BASE+0x50)
++#define HCRHPORTSTATUS0         (USB_BASE+0x54)
++#define HCRHPORTSTATUS1         (USB_BASE+0x58)       /* not in 9301 */
++#define HCRHPORTSTATUS2         (USB_BASE+0x5C)
++
++/* additional non-OHCI registers for controlling the AHB-HCI interface */
++#define USBCTRL                 (USB_BASE+0x80)
++#define USBHCISTS               (USB_BASE+0x84)
++
++/* 8003_0000 - 8003_ffff: Raster */
++#define RASTER_OFFSET           0x030000
++#define RASTER_BASE             (EP93XX_AHB_BASE|RASTER_OFFSET)
++#define VLINESTOTAL             (RASTER_BASE+0x00)
++#define VSYNCSTRTSTOP           (RASTER_BASE+0x04)
++#define VACTIVESTRTSTOP         (RASTER_BASE+0x08)
++#define VCLKSTRTSTOP            (RASTER_BASE+0x0C)
++#define HCLKSTOTAL              (RASTER_BASE+0x10)
++#define HSYNCSTRTSTOP           (RASTER_BASE+0x14)
++#define HACTIVESTRTSTOP         (RASTER_BASE+0x18)
++#define HCLKSTRTSTOP            (RASTER_BASE+0x1C)
++#define BRIGHTNESS              (RASTER_BASE+0x20)
++#define VIDEOATTRIBS            (RASTER_BASE+0x24)
++#define VIDSCRNPAGE             (RASTER_BASE+0x28)
++#define VIDSCRNHPG              (RASTER_BASE+0x2C)
++#define SCRNLINES               (RASTER_BASE+0x30)
++#define LINELENGTH              (RASTER_BASE+0x34)
++#define VLINESTEP               (RASTER_BASE+0x38)
++#define LINECARRY               (RASTER_BASE+0x3C)
++#define BLINKRATE               (RASTER_BASE+0x40)
++#define BLINKMASK               (RASTER_BASE+0x44)
++#define BLINKPATTRN             (RASTER_BASE+0x48)
++#define PATTRNMASK              (RASTER_BASE+0x4C)
++#define BG_OFFSET               (RASTER_BASE+0x50)
++#define PIXELMODE               (RASTER_BASE+0x54)
++#define PARLLIFOUT              (RASTER_BASE+0x58)
++#define PARLLIFIN               (RASTER_BASE+0x5C)
++#define CURSOR_ADR_START        (RASTER_BASE+0x60)
++#define CURSOR_ADR_RESET        (RASTER_BASE+0x64)
++#define CURSORSIZE              (RASTER_BASE+0x68)
++#define CURSORCOLOR1            (RASTER_BASE+0x6C)
++#define CURSORCOLOR2            (RASTER_BASE+0x70)
++#define CURSORXYLOC             (RASTER_BASE+0x74)
++#define CURSOR_DHSCAN_LH_YLOC   (RASTER_BASE+0x78)
++#define REALITI_SWLOCK          (RASTER_BASE+0x7C)
++#define GS_LUT                  (RASTER_BASE+0x80)
++#define REALITI_TCR             (RASTER_BASE+0x100)
++#define REALITI_TISRA           (RASTER_BASE+0x104)
++#define REALITI_TISRB           (RASTER_BASE+0x108)
++#define CURSOR_TISR             (RASTER_BASE+0x10C)
++#define REALITI_TOCRA           (RASTER_BASE+0x110)
++#define REALITI_TOCRB           (RASTER_BASE+0x114)
++#define FIFO_TOCRA              (RASTER_BASE+0x118)
++#define FIFO_TOCRB              (RASTER_BASE+0x11C)
++#define BLINK_TISR              (RASTER_BASE+0x120)
++#define DAC_TISRA               (RASTER_BASE+0x124)
++#define DAC_TISRB               (RASTER_BASE+0x128)
++#define SHIFT_TISR              (RASTER_BASE+0x12C)
++#define DACMUX_TOCRA            (RASTER_BASE+0x130)
++#define DACMUX_TOCRB            (RASTER_BASE+0x134)
++#define PELMUX_TOCR             (RASTER_BASE+0x138)
++#define VIDEO_TOCRA             (RASTER_BASE+0x13C)
++#define VIDEO_TOCRB             (RASTER_BASE+0x140)
++#define YCRCB_TOCR              (RASTER_BASE+0x144)
++#define CURSOR_TOCR             (RASTER_BASE+0x148)
++#define VIDEO_TOCRC             (RASTER_BASE+0x14C)
++#define SHIFT_TOCR              (RASTER_BASE+0x150)
++#define BLINK_TOCR              (RASTER_BASE+0x154)
++#define REALITI_TCER            (RASTER_BASE+0x180)
++#define SIGVAL                  (RASTER_BASE+0x200)
++#define SIGCTL                  (RASTER_BASE+0x204)
++#define VSIGSTRTSTOP            (RASTER_BASE+0x208)
++#define HSIGSTRTSTOP            (RASTER_BASE+0x20C)
++#define SIGCLR                  (RASTER_BASE+0x210)
++#define ACRATE                  (RASTER_BASE+0x214)
++#define LUTCONT                 (RASTER_BASE+0x218)
++#define VBLANKSTRTSTOP          (RASTER_BASE+0x228)
++#define HBLANKSTRTSTOP          (RASTER_BASE+0x22C)
++#define LUT                     (RASTER_BASE+0x400)
++#define CURSORBLINK1            (RASTER_BASE+0x21C)
++#define CURSORBLINK2            (RASTER_BASE+0x220)
++#define CURSORBLINK             (RASTER_BASE+0x224)
++#define EOLOFFSET               (RASTER_BASE+0x230)
++#define FIFOLEVEL               (RASTER_BASE+0x234)
++#define GS_LUT2                 (RASTER_BASE+0x280)
++#define GS_LUT3                 (RASTER_BASE+0x300)
++#define COLOR_LUT               (RASTER_BASE+0x400)
++
++/* 8006_0000 - 8006_ffff: SDRAM  */
++#define SDRAM_OFFSET            0x060000
++#define SDRAM_BASE              (EP93XX_AHB_BASE|SDRAM_OFFSET)
++#define SDRAMGLOBALCFG          (SDRAM_BASE+0x04)
++#define SDRAMREFRESHTIME        (SDRAM_BASE+0x08)     /* Refresh Timer */
++#define SDRAMBOOTSTATUS         (SDRAM_BASE+0x0C)
++#define SDRAMCFG0               (SDRAM_BASE+0x10)     /* Configuration Register 0 (nSDCS0) */
++#define SDRAMCFG1               (SDRAM_BASE+0x14)     /* Configuration Register 1 (nSDCS1) */
++#define SDRAMCFG2               (SDRAM_BASE+0x18)     /* Configuration Register 2 (nSDCS2) */
++#define SDRAMCFG3               (SDRAM_BASE+0x1C)     /* Configuration Register 3 (nSDCS3) */
++
++/* 8008_0000 - 8008_ffff: SMC */
++#define SMC_OFFSET              0x080000
++#define SMC_BASE                (EP93XX_AHB_BASE|SMC_OFFSET)
++#define SMCBCR0                 (SMC_BASE+0x00)       /* 0x8008.0000  Bank config register 0 */
++#define SMCBCR1                 (SMC_BASE+0x04)       /* 0x8008.0004  Bank config register 1 */
++#define SMCBCR2                 (SMC_BASE+0x08)       /* 0x8008.0008  Bank config register 2 */
++#define SMCBCR3                 (SMC_BASE+0x0C)       /* 0x8008.000C  Bank config register 3 */
++#define SMCBCR6                 (SMC_BASE+0x18)       /* 0x8008.0018  Bank config register 6 */
++#define SMCBCR7                 (SMC_BASE+0x1C)       /* 0x8008.001C  Bank config register 7 */
++#define PC1ATTRIB               (SMC_BASE+0x20)       /* 0x8008.0020  PC1 Attribute Register */
++#define PC1COMMON               (SMC_BASE+0x24)       /* 0x8008.0024  PC1 Common Register    */
++#define PC1IO                   (SMC_BASE+0x28)       /* 0x8008.0028  PC1 IO Register        */
++#define PC2ATTRIB               (SMC_BASE+0x30)       /* 0x8008.0030 PC2 Attribute Register   */
++#define PC2COMMON               (SMC_BASE+0x34)       /* 0x8008.0034 PC2 Common Register     */
++#define PC2IO                   (SMC_BASE+0x38)       /* 0x8008.0038 PC2 IO Register         */
++#define PCMCIACNT               (SMC_BASE+0x40)       /* 0x8008.0040 PCMCIA control register */
++
++/* 8009_0000 - 8009_ffff: Boot ROM */
++#define BOOT_OFFSET             0x090000
++#define BOOT_BASE               (EP93XX_AHB_BASE|BOOT_OFFSET)
++
++/* 800A_0000 - 800A_ffff: IDE Interface  */
++#define IDE_OFFSET              0x0a0000
++#define IDE_BASE                (EP93XX_AHB_BASE|IDE_OFFSET)
++/*#define IDECR                   (IDE_BASE+0x00)
++ *#define IDECFG                  (IDE_BASE+0x04)
++ *#define IDEMDMAOP               (IDE_BASE+0x08)
++ *#define IDEUDMAOP               (IDE_BASE+0x0C)
++ *#define IDEDATAOUT              (IDE_BASE+0x10)
++ *#define IDEDATAIN               (IDE_BASE+0x14)
++ *#define IDEMDMADATAOUT          (IDE_BASE+0x18)
++ *#define IDEMDMADATAIN           (IDE_BASE+0x1C)
++ *#define IDEUDMADATAOUT          (IDE_BASE+0x20)
++ *#define IDEUDMADATAIN           (IDE_BASE+0x24)
++ *#define IDEUDMASTATUS           (IDE_BASE+0x28)
++ *#define IDEUDMADEBUG            (IDE_BASE+0x2C)
++ *#define IDEUDMAWFST             (IDE_BASE+0x30)
++ *#define IDEUDMARFST             (IDE_BASE+0x34)
++ */
++
++/* 800B_0000 - 800B_FFFF: VIC 0 */
++#define VIC0_OFFSET              0x0B0000
++#define VIC0_BASE                (EP93XX_AHB_BASE|VIC0_OFFSET)
++#define VIC0                     (VIC0_BASE+0x000)
++#define VIC0IRQSTATUS            (VIC0_BASE+0x000)    /* R   IRQ status register               */
++#define VIC0FIQSTATUS            (VIC0_BASE+0x004)    /* R   FIQ status register               */
++#define VIC0RAWINTR              (VIC0_BASE+0x008)    /* R   Raw interrupt status register     */
++#define VIC0INTSELECT            (VIC0_BASE+0x00C)    /* R/W Interrupt select register         */
++#define VIC0INTENABLE            (VIC0_BASE+0x010)    /* R/W Interrupt enable register         */
++#define VIC0INTENCLEAR           (VIC0_BASE+0x014)    /* W   Interrupt enable clear register   */
++#define VIC0SOFTINT              (VIC0_BASE+0x018)    /* R/W Software interrupt register       */
++#define VIC0SOFTINTCLEAR         (VIC0_BASE+0x01C)    /* R/W Software interrupt clear register */
++#define VIC0PROTECTION           (VIC0_BASE+0x020)    /* R/W Protection enable register        */
++#define VIC0VECTADDR             (VIC0_BASE+0x030)    /* R/W Vector address register           */
++#define VIC0DEFVECTADDR          (VIC0_BASE+0x034)    /* R/W Default vector address register   */
++#define VIC0VECTADDR00           (VIC0_BASE+0x100)    /* R/W Vector address 00 register        */
++#define VIC0VECTADDR01           (VIC0_BASE+0x104)    /* R/W Vector address 01 register        */
++#define VIC0VECTADDR02           (VIC0_BASE+0x108)    /* R/W Vector address 02 register        */
++#define VIC0VECTADDR03           (VIC0_BASE+0x10C)    /* R/W Vector address 03 register        */
++#define VIC0VECTADDR04           (VIC0_BASE+0x110)    /* R/W Vector address 04 register        */
++#define VIC0VECTADDR05           (VIC0_BASE+0x114)    /* R/W Vector address 05 register        */
++#define VIC0VECTADDR06           (VIC0_BASE+0x118)    /* R/W Vector address 06 register        */
++#define VIC0VECTADDR07           (VIC0_BASE+0x11C)    /* R/W Vector address 07 register        */
++#define VIC0VECTADDR08           (VIC0_BASE+0x120)    /* R/W Vector address 08 register        */
++#define VIC0VECTADDR09           (VIC0_BASE+0x124)    /* R/W Vector address 09 register        */
++#define VIC0VECTADDR10           (VIC0_BASE+0x128)    /* R/W Vector address 10 register        */
++#define VIC0VECTADDR11           (VIC0_BASE+0x12C)    /* R/W Vector address 11 register        */
++#define VIC0VECTADDR12           (VIC0_BASE+0x130)    /* R/W Vector address 12 register        */
++#define VIC0VECTADDR13           (VIC0_BASE+0x134)    /* R/W Vector address 13 register        */
++#define VIC0VECTADDR14           (VIC0_BASE+0x138)    /* R/W Vector address 14 register        */
++#define VIC0VECTADDR15           (VIC0_BASE+0x13C)    /* R/W Vector address 15 register        */
++#define VIC0VECTCNTL00           (VIC0_BASE+0x200)    /* R/W Vector control 00 register        */
++#define VIC0VECTCNTL01           (VIC0_BASE+0x204)    /* R/W Vector control 01 register        */
++#define VIC0VECTCNTL02           (VIC0_BASE+0x208)    /* R/W Vector control 02 register        */
++#define VIC0VECTCNTL03           (VIC0_BASE+0x20C)    /* R/W Vector control 03 register        */
++#define VIC0VECTCNTL04           (VIC0_BASE+0x210)    /* R/W Vector control 04 register        */
++#define VIC0VECTCNTL05           (VIC0_BASE+0x214)    /* R/W Vector control 05 register        */
++#define VIC0VECTCNTL06           (VIC0_BASE+0x218)    /* R/W Vector control 06 register        */
++#define VIC0VECTCNTL07           (VIC0_BASE+0x21C)    /* R/W Vector control 07 register        */
++#define VIC0VECTCNTL08           (VIC0_BASE+0x220)    /* R/W Vector control 08 register        */
++#define VIC0VECTCNTL09           (VIC0_BASE+0x224)    /* R/W Vector control 09 register        */
++#define VIC0VECTCNTL10           (VIC0_BASE+0x228)    /* R/W Vector control 10 register        */
++#define VIC0VECTCNTL11           (VIC0_BASE+0x22C)    /* R/W Vector control 11 register        */
++#define VIC0VECTCNTL12           (VIC0_BASE+0x230)    /* R/W Vector control 12 register        */
++#define VIC0VECTCNTL13           (VIC0_BASE+0x234)    /* R/W Vector control 13 register        */
++#define VIC0VECTCNTL14           (VIC0_BASE+0x238)    /* R/W Vector control 14 register        */
++#define VIC0VECTCNTL15           (VIC0_BASE+0x23C)    /* R/W Vector control 15 register        */
++#define VIC0ITCR                 (VIC0_BASE+0x300)    /* R/W Test control register             */
++#define VIC0ITIP1                (VIC0_BASE+0x304)    /* R   Test input register (nVICIRQIN/nVICFIQIN) */
++#define VIC0ITIP2                (VIC0_BASE+0x308)    /* R   Test input register (VICVECTADDRIN)      */
++#define VIC0ITOP1                (VIC0_BASE+0x30C)    /* R   Test output register (nVICIRQ/nVICFIQ)   */
++#define VIC0ITOP2                (VIC0_BASE+0x310)    /* R   Test output register (VICVECTADDROUT)    */
++#define VIC0PERIPHID0            (VIC0_BASE+0xFE0)    /* R   Peripheral ID register bits 7:0   */
++#define VIC0PERIPHID1            (VIC0_BASE+0xFE4)    /* R   Peripheral ID register bits 15:8  */
++#define VIC0PERIPHID2            (VIC0_BASE+0xFE8)    /* R   Peripheral ID register bits 23:16 */
++#define VIC0PERIPHID3            (VIC0_BASE+0xFEC)    /* R   Peripheral ID register bits 31:24 */
++
++/* 800C_0000 - 800C_FFFF: VIC 1 */
++#define VIC1_OFFSET              0x0C0000
++#define VIC1_BASE                (EP93XX_AHB_BASE|VIC1_OFFSET)
++#define VIC1                     (VIC1_BASE+0x000)
++#define VIC1IRQSTATUS            (VIC1_BASE+0x000)    /* R   IRQ status register               */
++#define VIC1FIQSTATUS            (VIC1_BASE+0x004)    /* R   FIQ status register               */
++#define VIC1RAWINTR              (VIC1_BASE+0x008)    /* R   Raw interrupt status register     */
++#define VIC1INTSELECT            (VIC1_BASE+0x00C)    /* R/W Interrupt select register         */
++#define VIC1INTENABLE            (VIC1_BASE+0x010)    /* R/W Interrupt enable register         */
++#define VIC1INTENCLEAR           (VIC1_BASE+0x014)    /* W   Interrupt enable clear register   */
++#define VIC1SOFTINT              (VIC1_BASE+0x018)    /* R/W Software interrupt register       */
++#define VIC1SOFTINTCLEAR         (VIC1_BASE+0x01C)    /* R/W Software interrupt clear register */
++#define VIC1PROTECTION           (VIC1_BASE+0x020)    /* R/W Protection enable register        */
++#define VIC1VECTADDR             (VIC1_BASE+0x030)    /* R/W Vector address register           */
++#define VIC1DEFVECTADDR          (VIC1_BASE+0x034)    /* R/W Default vector address register   */
++#define VIC1VECTADDR00           (VIC1_BASE+0x100)    /* R/W Vector address 00 register        */
++#define VIC1VECTADDR01           (VIC1_BASE+0x104)    /* R/W Vector address 01 register        */
++#define VIC1VECTADDR02           (VIC1_BASE+0x108)    /* R/W Vector address 02 register        */
++#define VIC1VECTADDR03           (VIC1_BASE+0x10C)    /* R/W Vector address 03 register        */
++#define VIC1VECTADDR04           (VIC1_BASE+0x110)    /* R/W Vector address 04 register        */
++#define VIC1VECTADDR05           (VIC1_BASE+0x114)    /* R/W Vector address 05 register        */
++#define VIC1VECTADDR06           (VIC1_BASE+0x118)    /* R/W Vector address 06 register        */
++#define VIC1VECTADDR07           (VIC1_BASE+0x11C)    /* R/W Vector address 07 register        */
++#define VIC1VECTADDR08           (VIC1_BASE+0x120)    /* R/W Vector address 08 register        */
++#define VIC1VECTADDR09           (VIC1_BASE+0x124)    /* R/W Vector address 09 register        */
++#define VIC1VECTADDR10           (VIC1_BASE+0x128)    /* R/W Vector address 10 register        */
++#define VIC1VECTADDR11           (VIC1_BASE+0x12C)    /* R/W Vector address 11 register        */
++#define VIC1VECTADDR12           (VIC1_BASE+0x130)    /* R/W Vector address 12 register        */
++#define VIC1VECTADDR13           (VIC1_BASE+0x134)    /* R/W Vector address 13 register        */
++#define VIC1VECTADDR14           (VIC1_BASE+0x138)    /* R/W Vector address 14 register        */
++#define VIC1VECTADDR15           (VIC1_BASE+0x13C)    /* R/W Vector address 15 register        */
++#define VIC1VECTCNTL00           (VIC1_BASE+0x200)    /* R/W Vector control 00 register        */
++#define VIC1VECTCNTL01           (VIC1_BASE+0x204)    /* R/W Vector control 01 register        */
++#define VIC1VECTCNTL02           (VIC1_BASE+0x208)    /* R/W Vector control 02 register        */
++#define VIC1VECTCNTL03           (VIC1_BASE+0x20C)    /* R/W Vector control 03 register        */
++#define VIC1VECTCNTL04           (VIC1_BASE+0x210)    /* R/W Vector control 04 register        */
++#define VIC1VECTCNTL05           (VIC1_BASE+0x214)    /* R/W Vector control 05 register        */
++#define VIC1VECTCNTL06           (VIC1_BASE+0x218)    /* R/W Vector control 06 register        */
++#define VIC1VECTCNTL07           (VIC1_BASE+0x21C)    /* R/W Vector control 07 register        */
++#define VIC1VECTCNTL08           (VIC1_BASE+0x220)    /* R/W Vector control 08 register        */
++#define VIC1VECTCNTL09           (VIC1_BASE+0x224)    /* R/W Vector control 09 register        */
++#define VIC1VECTCNTL10           (VIC1_BASE+0x228)    /* R/W Vector control 10 register        */
++#define VIC1VECTCNTL11           (VIC1_BASE+0x22C)    /* R/W Vector control 11 register        */
++#define VIC1VECTCNTL12           (VIC1_BASE+0x230)    /* R/W Vector control 12 register        */
++#define VIC1VECTCNTL13           (VIC1_BASE+0x234)    /* R/W Vector control 13 register        */
++#define VIC1VECTCNTL14           (VIC1_BASE+0x238)    /* R/W Vector control 14 register        */
++#define VIC1VECTCNTL15           (VIC1_BASE+0x23C)    /* R/W Vector control 15 register        */
++#define VIC1ITCR                 (VIC1_BASE+0x300)    /* R/W Test control register             */
++#define VIC1ITIP1                (VIC1_BASE+0x304)    /* R   Test input register (nVICIRQIN/nVICFIQIN) */
++#define VIC1ITIP2                (VIC1_BASE+0x308)    /* R   Test input register (VICVECTADDRIN)      */
++#define VIC1ITOP1                (VIC1_BASE+0x30C)    /* R   Test output register (nVICIRQ/nVICFIQ)   */
++#define VIC1ITOP2                (VIC1_BASE+0x310)    /* R   Test output register (VICVECTADDROUT)    */
++#define VIC1PERIPHID0            (VIC1_BASE+0xFE0)    /* R   Peripheral ID register bits 7:0   */
++#define VIC1PERIPHID1            (VIC1_BASE+0xFE4)    /* R   Peripheral ID register bits 15:8  */
++#define VIC1PERIPHID2            (VIC1_BASE+0xFE8)    /* R   Peripheral ID register bits 23:16 */
++#define VIC1PERIPHID3            (VIC1_BASE+0xFEC)    /* R   Peripheral ID register bits 31:24 */
++
++/******************************************************************/
++/*         EP93xx APB Blocks                                      */
++/******************************************************************/
++/*                                                                */
++/* Start     End         Usage                                    */
++/* 8080_0000 8080_FFFF:  Reserved                                 */
++/* 8081_0000 8081_FFFF:  Timer                                    */
++/* 8082_0000 8082_FFFF:  I2S                                      */
++/* 8083_0000 8083_FFFF:  Security                                 */
++/* 8084_0000 8084_FFFF:  GPIO                                     */
++/* 8085_0000 8085_FFFF:  Reserved                                 */
++/* 8086_0000 8086_FFFF:  Reserved                                 */
++/* 8087_0000 8087_FFFF:  Reserved                                 */
++/* 8088_0000 8088_FFFF:  AC97                                     */
++/* 8089_0000 8089_FFFF:  Reserved                                 */
++/* 808A_0000 808A_FFFF:  SPI                                      */
++/* 808B_0000 808B_FFFF:  IrDA                                     */
++/* 808C_0000 808C_FFFF:  UART1                                    */
++/* 808D_0000 808D_FFFF:  UART2                                    */
++/* 808E_0000 808E_FFFF:  UART3                                    */
++/* 808F_0000 808F_FFFF:  Key Matrix                               */
++/* 8090_0000 8090_FFFF:  Touch Screen                             */
++/* 8091_0000 8091_FFFF:  PWM                                      */
++/* 8092_0000 8092_FFFF:  Real Time Clock                          */
++/* 8093_0000 8093_FFFF:  Syscon                                   */
++/* 8094_0000 8094_FFFF:  Watchdog                                 */
++/* 8095_0000 8FFF_FFFF:  Reserved                                 */
++/*                                                                */
++/******************************************************************/
++
++#define EP93XX_APB_BASE (IO_BASE_VIRT | 0x00800000)
++
++/*----------------------------------------------------------------*/
++/* 8081_0000 - 8081_ffff: Timers                                  */
++/*----------------------------------------------------------------*/
++
++#define TIMERS_OFFSET           0x010000
++#define TIMERS_BASE             (EP93XX_APB_BASE|TIMERS_OFFSET)
++
++#define TIMER1LOAD              (TIMERS_BASE+0x00)
++#define TIMER1VALUE             (TIMERS_BASE+0x04)    /* RO */
++#define TIMER1CONTROL           (TIMERS_BASE+0x08)
++#define TIMER1CLEAR             (TIMERS_BASE+0x0C)    /* WO */
++
++#define TIMER2LOAD              (TIMERS_BASE+0x20)
++#define TIMER2VALUE             (TIMERS_BASE+0x24)    /* RO */
++#define TIMER2CONTROL           (TIMERS_BASE+0x28)
++#define TIMER2CLEAR             (TIMERS_BASE+0x2C)    /* WO */
++
++#define TIMER3LOAD              (TIMERS_BASE+0x80)
++#define TIMER3VALUE             (TIMERS_BASE+0x84)    /* RO */
++#define TIMER3CONTROL           (TIMERS_BASE+0x88)
++#define TIMER3CLEAR             (TIMERS_BASE+0x8C)    /* WO */
++
++#define TIMER4VALUELOW          (TIMERS_BASE+0x60)
++#define TIMER4VALUEHIGH         (TIMERS_BASE+0x64)
++
++/* 8082_0000 - 8082_ffff: I2S */
++#define I2S_OFFSET            0x020000
++#define I2S_BASE              (EP93XX_APB_BASE|I2S_OFFSET)
++
++#define I2STxClkCfg           (I2S_BASE+0x00) /* 8082.0000 R/W Transmitter clock config register  */
++#define I2SRxClkCfg           (I2S_BASE+0x04) /* 8082.0004 R/W Receiver clock config register     */
++#define I2SGlSts              (I2S_BASE+0x08) /* 8082.0008 R/W SAI Global Status register.        */
++#define I2SGlCtrl             (I2S_BASE+0x0C) /* 8082.000C R/W SAI Global Control register        */
++
++#define I2STX0Lft             (I2S_BASE+0x10) /* 8082.0010 R/W Left  TX data reg for channel 0    */
++#define I2STX0Rt              (I2S_BASE+0x14) /* 8082.0014 R/W Right TX data reg for channel 0    */
++#define I2STX1Lft             (I2S_BASE+0x18) /* 8082.0018 R/W Left  TX data reg for channel 1    */
++#define I2STX1Rt              (I2S_BASE+0x1C) /* 8082.001C R/W Right TX data reg for channel 1    */
++#define I2STX2Lft             (I2S_BASE+0x20) /* 8082.0020 R/W Left  TX data reg for channel 2    */
++#define I2STX2Rt              (I2S_BASE+0x24) /* 8082.0024 R/W Right TX data reg for channel 2    */
++
++#define I2STXLinCtrlData      (I2S_BASE+0x28) /* 8082.0028 R/W TX Line Control data register      */
++#define I2STXCtrl             (I2S_BASE+0x2C) /* 8082.002C R/W TX Control register                */
++#define I2STXWrdLen           (I2S_BASE+0x30) /* 8082.0030 R/W TX Word Length                     */
++#define I2STX0En              (I2S_BASE+0x34) /* 8082.0034 R/W TX0 Channel Enable                 */
++#define I2STX1En              (I2S_BASE+0x38) /* 8082.0038 R/W TX1 Channel Enable                 */
++#define I2STX2En              (I2S_BASE+0x3C) /* 8082.003C R/W TX2 Channel Enable                 */
++
++#define I2SRX0Lft             (I2S_BASE+0x40) /* 8082.0040 R   Left  RX data reg for channel 0    */
++#define I2SRX0Rt              (I2S_BASE+0x44) /* 8082.0044 R   Right RX data reg for channel 0    */
++#define I2SRX1Lft             (I2S_BASE+0x48) /* 8082.0048 R   Left  RX data reg for channel 1    */
++#define I2SRX1Rt              (I2S_BASE+0x4C) /* 8082.004c R   Right RX data reg for channel 1    */
++#define I2SRX2Lft             (I2S_BASE+0x50) /* 8082.0050 R   Left  RX data reg for channel 2    */
++#define I2SRX2Rt              (I2S_BASE+0x54) /* 8082.0054 R   Right RX data reg for channel 2    */
++
++#define I2SRXLinCtrlData      (I2S_BASE+0x58) /* 8082.0058 R/W RX Line Control data register      */
++#define I2SRXCtrl             (I2S_BASE+0x5C) /* 8082.005C R/W RX Control register                */
++#define I2SRXWrdLen           (I2S_BASE+0x60) /* 8082.0060 R/W RX Word Length                     */
++#define I2SRX0En              (I2S_BASE+0x64) /* 8082.0064 R/W RX0 Channel Enable                 */
++#define I2SRX1En              (I2S_BASE+0x68) /* 8082.0068 R/W RX1 Channel Enable                 */
++#define I2SRX2En              (I2S_BASE+0x6C) /* 8082.006C R/W RX2 Channel Enable                 */
++
++/* 8083_0000 - 8083_ffff: Security Block */
++#define SECURITY_OFFSET         0x030000
++#define SECURITY_BASE           (EP93XX_APB_BASE|SECURITY_OFFSET)
++#define SECFLG                  (SECURITY_BASE+0x2400)
++#define SECEN                   (SECURITY_BASE+0x2410)
++#define UNIQID                  (SECURITY_BASE+0x2440)
++#define UNIQCHK                 (SECURITY_BASE+0x2450)
++#define UNIQVAL                 (SECURITY_BASE+0x2460)
++#define CLINBOOT                (SECURITY_BASE+0x2480)
++#define CLINVADDR               (SECURITY_BASE+0x2484)
++#define CLSETSKRNL              (SECURITY_BASE+0x2488)
++#define CLSKRNL                 (SECURITY_BASE+0x248C)
++#define ITTMP                   (SECURITY_BASE+0x2490)
++#define ETBL1                   (SECURITY_BASE+0x24A0)
++#define ETCL1                   (SECURITY_BASE+0x24A4)
++#define ETAPL1                  (SECURITY_BASE+0x24A8)
++#define ETSPTREG1               (SECURITY_BASE+0x24B0)
++#define ETSPTREG2               (SECURITY_BASE+0x24B4)
++#define ETSPTREG3               (SECURITY_BASE+0x24B8)
++
++#define SECID1                  (SECURITY_BASE+0x2500)
++#define SECID2                  (SECURITY_BASE+0x2504)
++#define SECCHK1                 (SECURITY_BASE+0x2520)
++#define SECCHK2                 (SECURITY_BASE+0x2524)
++#define SECVAL1                 (SECURITY_BASE+0x2540)
++#define SECVAL2                 (SECURITY_BASE+0x2544)
++
++#define UNIQID2                 (SECURITY_BASE+0x2700)
++#define UNIQID3                 (SECURITY_BASE+0x2704)
++#define UNIQID4                 (SECURITY_BASE+0x2708)
++#define UNIQID5                 (SECURITY_BASE+0x270C)
++#define UNIQCHK2                (SECURITY_BASE+0x2710)
++#define USRFLG                  (SECURITY_BASE+0x2714)        /* llandre tells me this is also a CPU model flag */
++#define UNIQVAL2                (SECURITY_BASE+0x2720)
++#define UNIQVAL3                (SECURITY_BASE+0x2724)
++#define UNIQVAL4                (SECURITY_BASE+0x2728)
++#define TESTVAL                 (SECURITY_BASE+0x2744)
++#define TESTCHK                 (SECURITY_BASE+0x2754)
++#define ACHK1                   (SECURITY_BASE+0x27A0)
++#define ACHK2                   (SECURITY_BASE+0x27A4)
++#define PROCRESET               (SECURITY_BASE+0x27A8)
++#define TESTIDR                 (SECURITY_BASE+0x27AC)
++#define AVAL1                   (SECURITY_BASE+0x27B0)
++#define AVAL2                   (SECURITY_BASE+0x27B4)
++#define AID1                    (SECURITY_BASE+0x27C4)
++#define AID2                    (SECURITY_BASE+0x27C8)
++#define ADYNREMAP               (SECURITY_BASE+0x27D0)
++#define ALTTMP                  (SECURITY_BASE+0x27D4)
++#define PROCSIGN                (SECURITY_BASE+0x27F0)
++
++#define ECLIDX                  (SECURITY_BASE+0x2800)
++#define ECLINE0                 (SECURITY_BASE+0x2810)
++#define ECLINE1                 (SECURITY_BASE+0x2814)
++#define ECLINE2                 (SECURITY_BASE+0x2818)
++#define ECLINE3                 (SECURITY_BASE+0x281C)
++#define ECLINE4                 (SECURITY_BASE+0x2820)
++#define ECLINE5                 (SECURITY_BASE+0x2824)
++#define ECLINE6                 (SECURITY_BASE+0x2828)
++#define ECLINE7                 (SECURITY_BASE+0x282C)
++#define ETWIDX1                 (SECURITY_BASE+0x2840)
++#define ETWL1                   (SECURITY_BASE+0x2844)
++#define ETWIDX2                 (SECURITY_BASE+0x2848)
++#define ETWL2                   (SECURITY_BASE+0x284C)
++
++#define ETSPT10                 (SECURITY_BASE+0x4000)
++#define ETSPT11                 (SECURITY_BASE+0x4004)
++#define ETSPT12                 (SECURITY_BASE+0x4008)
++#define ETSPT13                 (SECURITY_BASE+0x400C)
++
++#define ETSPT2000               (SECURITY_BASE+0x6000)
++#define ETSPT2020               (SECURITY_BASE+0x6020)
++#define ETSPT2024               (SECURITY_BASE+0x6024)
++
++/* 8084_0000 - 8084_ffff: GPIO */
++#define GPIO_OFFSET              0x040000
++#define GPIO_BASE                (EP93XX_APB_BASE|GPIO_OFFSET)
++#define GPIO_PADR                (GPIO_BASE+0x00)
++#define GPIO_PBDR                (GPIO_BASE+0x04)
++#define GPIO_PCDR                (GPIO_BASE+0x08)
++
++/* For support EP9301 - EP9302 arch */
++
++#if !defined(CONFIG_ARCH_EP9301) && !defined (CONFIG_ARCH_EP9302)
++#define GPIO_PDDR                (GPIO_BASE+0x0C)
++#endif
++
++#define GPIO_PADDR               (GPIO_BASE+0x10)
++#define GPIO_PBDDR               (GPIO_BASE+0x14)
++#define GPIO_PCDDR               (GPIO_BASE+0x18)
++
++/* For support EP9301 - EP9302 arch */
++
++#if !defined(CONFIG_ARCH_EP9301) && !defined (CONFIG_ARCH_EP9302)
++#define GPIO_PDDDR               (GPIO_BASE+0x1C)
++#endif
++
++#define GPIO_PEDR                (GPIO_BASE+0x20)
++#define GPIO_PEDDR               (GPIO_BASE+0x24)
++#define GPIO_PFDR                (GPIO_BASE+0x30)
++#define GPIO_PFDDR               (GPIO_BASE+0x34)
++#define GPIO_PGDR                (GPIO_BASE+0x38)
++#define GPIO_PGDDR               (GPIO_BASE+0x3C)
++#define GPIO_PHDR                (GPIO_BASE+0x40)
++#define GPIO_PHDDR               (GPIO_BASE+0x44)
++#define GPIO_INTTYPE1            (GPIO_BASE+0x4C)
++#define GPIO_INTTYPE2            (GPIO_BASE+0x50)
++#define GPIO_FEOI                (GPIO_BASE+0x54)     /* WRITE ONLY - READ UNDEFINED */
++#define GPIO_INTEN               (GPIO_BASE+0x58)
++#define GPIO_INTSTATUS           (GPIO_BASE+0x5C)
++#define GPIO_RAWINTSTASUS        (GPIO_BASE+0x60)
++#define GPIO_FDB                 (GPIO_BASE+0x64)
++#define GPIO_PAPINDR             (GPIO_BASE+0x68)
++#define GPIO_PBPINDR             (GPIO_BASE+0x6C)
++#define GPIO_PCPINDR             (GPIO_BASE+0x70)
++#define GPIO_PDPINDR             (GPIO_BASE+0x74)
++#define GPIO_PEPINDR             (GPIO_BASE+0x78)
++#define GPIO_PFPINDR             (GPIO_BASE+0x7C)
++#define GPIO_PGPINDR             (GPIO_BASE+0x80)
++#define GPIO_PHPINDR             (GPIO_BASE+0x84)
++#define GPIO_AINTTYPE1           (GPIO_BASE+0x90)
++#define GPIO_AINTTYPE2           (GPIO_BASE+0x94)
++#define GPIO_AEOI                (GPIO_BASE+0x98)     /* WRITE ONLY - READ UNDEFINED */
++#define GPIO_AINTEN              (GPIO_BASE+0x9C)
++#define GPIO_INTSTATUSA          (GPIO_BASE+0xA0)
++#define GPIO_RAWINTSTSTISA       (GPIO_BASE+0xA4)
++#define GPIO_ADB                 (GPIO_BASE+0xA8)
++#define GPIO_BINTTYPE1           (GPIO_BASE+0xAC)
++#define GPIO_BINTTYPE2           (GPIO_BASE+0xB0)
++#define GPIO_BEOI                (GPIO_BASE+0xB4)     /* WRITE ONLY - READ UNDEFINED */
++#define GPIO_BINTEN              (GPIO_BASE+0xB8)
++#define GPIO_INTSTATUSB          (GPIO_BASE+0xBC)
++#define GPIO_RAWINTSTSTISB       (GPIO_BASE+0xC0)
++#define GPIO_BDB                 (GPIO_BASE+0xC4)
++#define GPIO_EEDRIVE             (GPIO_BASE+0xC8)
++/*#define Reserved               (GPIO_BASE+0xCC) */
++#define GPIO_TCR                 (GPIO_BASE+0xD0)     /* Test Registers */
++#define GPIO_TISRA               (GPIO_BASE+0xD4)     /* Test Registers */
++#define GPIO_TISRB               (GPIO_BASE+0xD8)     /* Test Registers */
++#define GPIO_TISRC               (GPIO_BASE+0xDC)     /* Test Registers */
++#define GPIO_TISRD               (GPIO_BASE+0xE0)     /* Test Registers */
++#define GPIO_TISRE               (GPIO_BASE+0xE4)     /* Test Registers */
++#define GPIO_TISRF               (GPIO_BASE+0xE8)     /* Test Registers */
++#define GPIO_TISRG               (GPIO_BASE+0xEC)     /* Test Registers */
++#define GPIO_TISRH               (GPIO_BASE+0xF0)     /* Test Registers */
++#define GPIO_TCER                (GPIO_BASE+0xF4)     /* Test Registers */
++
++/* 8088_0000 - 8088_ffff: Ac97 Controller (AAC) */
++#define AC97_OFFSET             0x080000
++#define AC97_BASE               (EP93XX_APB_BASE|AC97_OFFSET)
++#define AC97DR1                 (AC97_BASE+0x00)      /* 8088.0000 R/W Data read or written from/to FIFO1  */
++#define AC97RXCR1               (AC97_BASE+0x04)      /* 8088.0004 R/W Control register for receive        */
++#define AC97TXCR1               (AC97_BASE+0x08)      /* 8088.0008 R/W Control register for transmit       */
++#define AC97SR1                 (AC97_BASE+0x0C)      /* 8088.000C R   Status register                     */
++#define AC97RISR1               (AC97_BASE+0x10)      /* 8088.0010 R   Raw interrupt status register       */
++#define AC97ISR1                (AC97_BASE+0x14)      /* 8088.0014 R   Interrupt Status                    */
++#define AC97IE1                 (AC97_BASE+0x18)      /* 8088.0018 R/W Interrupt Enable                    */
++#define AC97DR2                 (AC97_BASE+0x20)      /* 8088.0020 R/W Data read or written from/to FIFO2  */
++#define AC97RXCR2               (AC97_BASE+0x24)      /* 8088.0024 R/W Control register for receive        */
++#define AC97TXCR2               (AC97_BASE+0x28)      /* 8088.0028 R/W Control register for transmit       */
++#define AC97SR2                 (AC97_BASE+0x2C)      /* 8088.002C R   Status register                     */
++#define AC97RISR2               (AC97_BASE+0x30)      /* 8088.0030 R   Raw interrupt status register       */
++#define AC97ISR2                (AC97_BASE+0x34)      /* 8088.0034 R   Interrupt Status                    */
++#define AC97IE2                 (AC97_BASE+0x38)      /* 8088.0038 R/W Interrupt Enable                    */
++#define AC97DR3                 (AC97_BASE+0x40)      /* 8088.0040 R/W Data read or written from/to FIFO3. */
++#define AC97RXCR3               (AC97_BASE+0x44)      /* 8088.0044 R/W Control register for receive        */
++#define AC97TXCR3               (AC97_BASE+0x48)      /* 8088.0048 R/W Control register for transmit       */
++#define AC97SR3                 (AC97_BASE+0x4C)      /* 8088.004C R   Status register                     */
++#define AC97RISR3               (AC97_BASE+0x50)      /* 8088.0050 R   Raw interrupt status register       */
++#define AC97ISR3                (AC97_BASE+0x54)      /* 8088.0054 R   Interrupt Status                    */
++#define AC97IE3                 (AC97_BASE+0x58)      /* 8088.0058 R/W Interrupt Enable                    */
++#define AC97DR4                 (AC97_BASE+0x60)      /* 8088.0060 R/W Data read or written from/to FIFO4. */
++#define AC97RXCR4               (AC97_BASE+0x64)      /* 8088.0064 R/W Control register for receive        */
++#define AC97TXCR4               (AC97_BASE+0x68)      /* 8088.0068 R/W Control register for transmit       */
++#define AC97SR4                 (AC97_BASE+0x6C)      /* 8088.006C R   Status register                     */
++#define AC97RISR4               (AC97_BASE+0x70)      /* 8088.0070 R   Raw interrupt status register       */
++#define AC97ISR4                (AC97_BASE+0x74)      /* 8088.0074 R   Interrupt Status                    */
++#define AC97IE4                 (AC97_BASE+0x78)      /* 8088.0078 R/W Interrupt Enable                    */
++#define AC97S1DATA              (AC97_BASE+0x80)      /* 8088.0080 R/W Data received/transmitted on SLOT1  */
++#define AC97S2DATA              (AC97_BASE+0x84)      /* 8088.0084 R/W Data received/transmitted on SLOT2  */
++#define AC97S12DATA             (AC97_BASE+0x88)      /* 8088.0088 R/W Data received/transmitted on SLOT12 */
++#define AC97RGIS                (AC97_BASE+0x8C)      /* 8088.008C R/W Raw Global interrupt status register */
++#define AC97GIS                 (AC97_BASE+0x90)      /* 8088.0090 R   Global interrupt status register    */
++#define AC97IM                  (AC97_BASE+0x94)      /* 8088.0094 R/W Interrupt mask register             */
++#define AC97EOI                 (AC97_BASE+0x98)      /* 8088.0098 W   Interrupt clear register            */
++#define AC97GCR                 (AC97_BASE+0x9C)      /* 8088.009C R/W Main Control register               */
++#define AC97RESET               (AC97_BASE+0xA0)      /* 8088.00A0 R/W RESET control register.             */
++#define AC97SYNC                (AC97_BASE+0xA4)      /* 8088.00A4 R/W SYNC control register.              */
++#define AC97GCIS                (AC97_BASE+0xA8)      /* 8088.00A8 R  Global chan FIFO int status register */
++
++/* 808A_0000 - 808A_ffff: SSP */
++#define SSP_OFFSET             0x0A0000
++#define SSP_BASE               (EP93XX_APB_BASE|SSP_OFFSET)
++#define SSPCR0                 (SSP_BASE+0x00)
++#define SSPCR1                 (SSP_BASE+0x04)
++#define SSPDR                  (SSP_BASE+0x08)
++#define SSPSR                  (SSP_BASE+0x0c)
++#define SSPCPSR                (SSP_BASE+0x10)
++#define SSPIIR                 (SSP_BASE+0x14)
++#define SSPICR                 (SSP_BASE+0x14)
++
++/* 808B_0000 - 808B_ffff: IrDA */
++#define IRDA_OFFSET             0x0B0000
++#define IRDA_BASE               (EP93XX_APB_BASE|IRDA_OFFSET)
++#define IrEnable                (IRDA_BASE+0x00)
++#define IrCtrl                  (IRDA_BASE+0x04)
++#define IrAdrMatchVal           (IRDA_BASE+0x08)
++#define IrFlag                  (IRDA_BASE+0x0C)
++#define IrData                  (IRDA_BASE+0x10)
++#define IrDataTail1             (IRDA_BASE+0x14)
++#define IrDataTail2             (IRDA_BASE+0x18)
++#define IrDataTail3             (IRDA_BASE+0x1c)
++#define IrRIB                   (IRDA_BASE+0x20)
++#define IrTR0                   (IRDA_BASE+0x24)
++#define IrDMACR                 (IRDA_BASE+0x28)
++#define SIRTR0                  (IRDA_BASE+0x30)
++#define MISR                    (IRDA_BASE+0x80)
++#define MIMR                    (IRDA_BASE+0x84)
++#define MIIR                    (IRDA_BASE+0x88)
++#define FISR                    (IRDA_BASE+0x180)
++#define FIMR                    (IRDA_BASE+0x184)
++#define FIIR                    (IRDA_BASE+0x188)
++
++/* 808C_0000 - 808C_ffff: UART1 */
++#define UART1_OFFSET            0x0C0000
++#define UART1_BASE              (EP93XX_APB_BASE|UART1_OFFSET)
++#define UART1DR                 (UART1_BASE+0x000)
++#define UART1RSR                (UART1_BASE+0x004)
++#define UART1ECR                (UART1_BASE+0x004)
++#define UART1CR_H               (UART1_BASE+0x008)
++#define UART1CR_M               (UART1_BASE+0x00C)
++#define UART1CR_L               (UART1_BASE+0x010)
++#define UART1CR                 (UART1_BASE+0x014)
++#define UART1FR                 (UART1_BASE+0x018)
++#define UART1IIR                (UART1_BASE+0x01C)
++#define UART1ICR                (UART1_BASE+0x01C)
++#define UART1ILPR               (UART1_BASE+0x020)
++#define UART1DMACR              (UART1_BASE+0x028)
++#define UART1TMR                (UART1_BASE+0x084)
++#define UART1MCR                (UART1_BASE+0x100)
++#define UART1MSR                (UART1_BASE+0x104)
++#define UART1TCR                (UART1_BASE+0x108)
++#define UART1TISR               (UART1_BASE+0x10C)
++#define UART1TOCR               (UART1_BASE+0x110)
++#define HDLC1CR                 (UART1_BASE+0x20c)
++#define HDLC1AMV                (UART1_BASE+0x210)
++#define HDLC1AMSK               (UART1_BASE+0x214)
++#define HDLC1RIB                (UART1_BASE+0x218)
++#define HDLC1SR                 (UART1_BASE+0x21c)
++
++/* 808d_0000 - 808d_ffff: UART2 */
++#define UART2_OFFSET            0x0D0000
++#define UART2_BASE              (EP93XX_APB_BASE|UART2_OFFSET)
++#define UART2DR                 (UART2_BASE+0x00)
++#define UART2RSR                (UART2_BASE+0x04)     /* Read */
++#define UART2ECR                (UART2_BASE+0x04)     /* Write */
++#define UART2CR_H               (UART2_BASE+0x08)
++#define UART2CR_M               (UART2_BASE+0x0C)
++#define UART2CR_L               (UART2_BASE+0x10)
++#define UART2CR                 (UART2_BASE+0x14)
++#define UART2FR                 (UART2_BASE+0x18)
++#define UART2IIR                (UART2_BASE+0x1C)     /* Read */
++#define UART2ICR                (UART2_BASE+0x1C)     /* Write */
++#define UART2ILPR               (UART2_BASE+0x20)
++#define UART2DMACR              (UART2_BASE+0x28)
++#define UART2TMR                (UART2_BASE+0x84)
++
++/* 808e_0000 - 808e_ffff: UART3 */
++#define UART3_OFFSET            0x0E0000
++#define UART3_BASE              (EP93XX_APB_BASE|UART3_OFFSET)
++#define UART3DR                 (UART3_BASE+0x00)
++#define UART3RSR                (UART3_BASE+0x04)     /* Read */
++#define UART3ECR                (UART3_BASE+0x04)     /* Write */
++#define UART3CR_H               (UART3_BASE+0x08)
++#define UART3CR_M               (UART3_BASE+0x0C)
++#define UART3CR_L               (UART3_BASE+0x10)
++#define UART3CR                 (UART3_BASE+0x14)
++#define UART3FR                 (UART3_BASE+0x18)
++#define UART3IIR                (UART3_BASE+0x1C)     /* Read */
++#define UART3ICR                (UART3_BASE+0x1C)     /* Write */
++#define UART3ILPR               (UART3_BASE+0x20)
++#define UART3DMACR              (UART3_BASE+0x28)
++#define UART3TCR                (UART3_BASE+0x80)
++#define UART3TISR               (UART3_BASE+0x88)
++#define UART3TOCR               (UART3_BASE+0x8C)
++#define UART3TMR                (UART3_BASE+0x84)
++#define UART3MCR                (UART3_BASE+0x100)    /* Modem Control Reg */
++#define UART3MSR                (UART3_BASE+0x104)    /* Modem Status Reg */
++#define UART3HDLCCR             (UART3_BASE+0x20C)    /* HDLC Registers */
++#define UART3HDLCAMV            (UART3_BASE+0x210)    /* HDLC Registers */
++#define UART3HDLCAMSK           (UART3_BASE+0x214)    /* HDLC Registers */
++#define UART3HDLCCRIB           (UART3_BASE+0x218)    /* HDLC Registers */
++#define UART3HDLCSR             (UART3_BASE+0x21C)    /* HDLC Registers */
++
++/* 808f_0000 - 808f_ffff: KEY Matrix */
++#define KEY_OFFSET              0x0F0000
++#define KEY_BASE                (EP93XX_APB_BASE|KEY_OFFSET)
++#define SCANINIT                (KEY_BASE+0x00)
++#define KEY_DIAG                (KEY_BASE+0x04)
++#define KEY_REG                 (KEY_BASE+0x08)
++#define KEY_TCR                 (KEY_BASE+0x10)
++#define KEY_TISR                (KEY_BASE+0x14)
++#define KEY_TOCR                (KEY_BASE+0x18)
++
++/* 8090_0000 - 8090_ffff: Analog Resistive Touchscreen  */
++#define TOUCH_OFFSET            0x100000
++#define TOUCH_BASE              (EP93XX_APB_BASE|TOUCH_OFFSET)
++#define TSSetup                 (TOUCH_BASE+0x00)     /* R/W touchscreen controller setup control register.     */
++#define TSXYMaxMin              (TOUCH_BASE+0x04)     /* R/W touchscreen controller max/min register.           */
++#define TSXYResult              (TOUCH_BASE+0x08)     /* R   touchscreen controller result register.            */
++#define TSDischarge             (TOUCH_BASE+0x0C)     /* LOCKED R/W touchscreen Switch Matrix control register. */
++#define TSXSample               (TOUCH_BASE+0x10)     /* LOCKED R/W touchscreen Switch Matrix control register. */
++#define TSYSample               (TOUCH_BASE+0x14)     /* LOCKED R/W touchscreen Switch Matrix control register. */
++#define TSDirect                (TOUCH_BASE+0x18)     /* LOCKED R/W touchscreen Switch Matrix control register. */
++#define TSDetect                (TOUCH_BASE+0x1C)     /* LOCKED R/W touchscreen Switch Matrix control register. */
++#define TSSWLock                (TOUCH_BASE+0x20)     /*  NA    R/W touchscreen software lock register.         */
++#define TSSetup2                (TOUCH_BASE+0x24)     /* R/W touchscreen setup control register #2.             */
++
++/* 8091_0000 - 8091_ffff: PWM */
++#define PWM_OFFSET              0x110000
++#define PWM_BASE                (EP93XX_APB_BASE|PWM_OFFSET)
++#define PWM0_TC                 (PWM_BASE+0x00)       /* 80910000 R/W PWM_0 Terminal Count */
++#define PWM0_DC                 (PWM_BASE+0x04)       /* 80910004 R/W PWM_0 Duty Cycle     */
++#define PWM0_EN                 (PWM_BASE+0x08)       /* 80910008 R/W PWM_0 Enable         */
++#define PWM0_INV                (PWM_BASE+0x0C)       /* 8091000C R/W PWM_0 Invert         */
++#define PWM0_SYNC               (PWM_BASE+0x10)       /* 80910010 R/W PWM_0 Synchronous    */
++#define PWM1_TC                 (PWM_BASE+0x20)       /* 80910020 R/W PWM_1 Terminal Count */
++#define PWM1_DC                 (PWM_BASE+0x24)       /* 80910024 R/W PWM_1 Duty Cycle     */
++#define PWM1_EN                 (PWM_BASE+0x28)       /* 80910028 R/W PWM_1 Enable         */
++#define PWM1_INV                (PWM_BASE+0x2C)       /* 8091002C R/W PWM_1 Invert         */
++#define PWM1_SYNC               (PWM_BASE+0x30)       /* 80910030 R/W PWM_1 Synchronous    */
++
++/* 8092_0000 - 8092_ffff: RTC */
++#define RTC_OFFSET              0x120000
++#define RTC_BASE                (EP93XX_APB_BASE|RTC_OFFSET)
++#define RTCDR                   (RTC_BASE+0x00)
++#define RTCMR                   (RTC_BASE+0x04)
++#define RTCSTAT                 (RTC_BASE+0x08)       /* Read */
++#define RTCEOI                  (RTC_BASE+0x08)       /* Write */
++#define RTCLR                   (RTC_BASE+0x0C)
++#define RTCCR                   (RTC_BASE+0x10)
++#define RTCSCOMP                (RTC_BASE+0x108)
++
++/* 8093_0000 - 8093_ffff: CSC/Syscon  PLL, clock control, & misc. stuff */
++#define SYSCON_OFFSET           0x130000
++#define SYSCON_BASE             (EP93XX_APB_BASE|SYSCON_OFFSET)
++#define SYSCON_PWRSR            (SYSCON_BASE+0x0000)
++#define SYSCON_PWRCNT           (SYSCON_BASE+0x0004)
++#define SYSCON_HALT             (SYSCON_BASE+0x0008)
++#define SYSCON_STBY             (SYSCON_BASE+0x000c)
++#define SYSCON_BLEOI            (SYSCON_BASE+0x0010)
++#define SYSCON_MCEOI            (SYSCON_BASE+0x0014)
++#define SYSCON_TEOI             (SYSCON_BASE+0x0018)
++#define SYSCON_STFCLR           (SYSCON_BASE+0x001c)
++#define SYSCON_CLKSET1          (SYSCON_BASE+0x0020)
++#define SYSCON_CLKSET2          (SYSCON_BASE+0x0024)
++#define SYSCON_RESV00           (SYSCON_BASE+0x0028)
++#define SYSCON_RESV01           (SYSCON_BASE+0x002c)
++#define SYSCON_RESV02           (SYSCON_BASE+0x0030)
++#define SYSCON_RESV03           (SYSCON_BASE+0x0034)
++#define SYSCON_RESV04           (SYSCON_BASE+0x0038)
++#define SYSCON_RESV05           (SYSCON_BASE+0x003c)
++#define SYSCON_SCRREG0          (SYSCON_BASE+0x0040)
++#define SYSCON_SCRREG1          (SYSCON_BASE+0x0044)
++#define SYSCON_CLKTEST          (SYSCON_BASE+0x0048)
++#define SYSCON_USBRESET         (SYSCON_BASE+0x004c)
++#define SYSCON_APBWAIT          (SYSCON_BASE+0x0050)
++#define SYSCON_BMAR             (SYSCON_BASE+0x0054)
++#define SYSCON_BOOTCLR          (SYSCON_BASE+0x0058)
++#define SYSCON_DEVCFG           (SYSCON_BASE+0x0080)
++#define SYSCON_VIDDIV           (SYSCON_BASE+0x0084)
++#define SYSCON_MIRDIV           (SYSCON_BASE+0x0088)
++#define SYSCON_I2SDIV           (SYSCON_BASE+0x008C)
++#define SYSCON_KTDIV            (SYSCON_BASE+0x0090)
++#define SYSCON_CHIPID           (SYSCON_BASE+0x0094)
++#define SYSCON_TSTCR            (SYSCON_BASE+0x0098)
++#define SYSCON_SYSCFG           (SYSCON_BASE+0x009C)
++#define SYSCON_SWLOCK           (SYSCON_BASE+0x00C0)
++
++#define SYSCON_DEVCFG_KEYS      0x00000002
++#define SYSCON_DEVCFG_RasOnP3   0x00000010
++#define SYSCON_DEVCFG_GONK      0x08000000
++
++#define SYSCON_KTDIV_KEN        0x00008000
++
++/* 8094_0000 - 8094_ffff: Watchdog */
++#define WATCHDOG_OFFSET         0x140000
++#define WATCHDOG_BASE           (EP93XX_APB_BASE|WATCHDOG_OFFSET)
++#define WATCHDOG                (WATCHDOG_BASE+0x00)
++#define WDSTATUS                (WATCHDOG_BASE+0x04)
++
++#endif                                /* __ASM_ARCH_HARDWARE_H */
+diff --git a/include/asm-arm/arch-ep93xx/regs_ac97.h b/include/asm-arm/arch-ep93xx/regs_ac97.h
+new file mode 100644
+index 0000000..efe0015
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_ac97.h
+@@ -0,0 +1,168 @@
++/*=============================================================================
++ *  FILE:           regs_ac97.h
++ *
++ *  DESCRIPTION:    Ac'97 Register Definition
++ *
++ *  Copyright Cirrus Logic, 2001-2003
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *=============================================================================
++ */
++#ifndef _REGS_AC97_H_
++#define _REGS_AC97_H_
++
++/* Bit definitionses */
++#define AC97ISR_RIS                     8
++#define AC97ISR_TIS                     4
++#define AC97ISR_RTIS                    2
++#define AC97ISR_TCIS                    1
++
++#define AC97RGIS_SLOT1TXCOMPLETE     0x01
++#define AC97RGIS_SLOT2RXVALID        0x02
++#define AC97RGIS_GPIOTXCOMPLETE      0x04
++#define AC97RGIS_GPIOINTRX           0x08
++#define AC97RGIS_RWIS                0x10
++#define AC97RGIS_CODECREADY          0x20
++#define AC97RGIS_SLOT2TXCOMPLETE     0x40
++
++#define AC97SR_RXFE                 0x0001
++#define AC97SR_TXFE                 0x0002
++#define AC97SR_RXFF                 0x0004
++#define AC97SR_TXFF                 0x0008
++#define AC97SR_TXBUSY               0x0010
++#define AC97SR_RXOE                 0x0020
++#define AC97SR_TXUE                 0x0040
++
++#define AC97GSR_IFE                     0x1
++#define AC97GSR_LOOP                    0x2
++#define AC97GSR_OVERRIDECODECREADY      0x4
++
++#define AC97RESET_TIMEDRESET            0x1
++#define AC97RESET_FORCEDRESET           0x2
++#define AC97RESET_EFORCER               0x4
++
++#define AC97RXCR_REN                    0x1
++
++#define AC97TXCR_TEN                    0x1
++
++/*
++ * The Ac97 Codec registers, accessable through the Ac-link.
++ * These are not controller registers and are not memory mapped.
++ * Includes registers specific to CS4202 (Beavis).
++ */
++#define AC97_REG_OFFSET_MASK                0x0000007E
++
++#define AC97_00_RESET                          0x00000000
++#define AC97_02_MASTER_VOL                     0x00000002
++#define AC97_04_HEADPHONE_VOL                  0x00000004
++#define AC97_06_MONO_VOL                       0x00000006
++#define AC97_08_TONE                           0x00000008
++#define AC97_0A_PC_BEEP_VOL                    0x0000000A
++#define AC97_0C_PHONE_VOL                      0x0000000C
++#define AC97_0E_MIC_VOL                        0x0000000E
++#define AC97_10_LINE_IN_VOL                    0x00000010
++#define AC97_12_CD_VOL                         0x00000012
++#define AC97_14_VIDEO_VOL                      0x00000014
++#define AC97_16_AUX_VOL                        0x00000016
++#define AC97_18_PCM_OUT_VOL                    0x00000018
++#define AC97_1A_RECORD_SELECT                  0x0000001A
++#define AC97_1C_RECORD_GAIN                    0x0000001C
++#define AC97_1E_RESERVED_1E                    0x0000001E
++#define AC97_20_GENERAL_PURPOSE                0x00000020
++#define AC97_22_3D_CONTROL                     0x00000022
++#define AC97_24_MODEM_RATE                     0x00000024
++#define AC97_26_POWERDOWN                      0x00000026
++#define AC97_28_EXT_AUDIO_ID                   0x00000028
++#define AC97_2A_EXT_AUDIO_POWER                0x0000002A
++#define AC97_2C_PCM_FRONT_DAC_RATE             0x0000002C
++#define AC97_2E_PCM_SURR_DAC_RATE              0x0000002E
++#define AC97_30_PCM_LFE_DAC_RATE               0x00000030
++#define AC97_32_PCM_LR_ADC_RATE                0x00000032
++#define AC97_34_MIC_ADC_RATE                   0x00000034
++#define AC97_36_6CH_VOL_C_LFE                  0x00000036
++#define AC97_38_6CH_VOL_SURROUND               0x00000038
++#define AC97_3A_SPDIF_CONTROL                  0x0000003A
++#define AC97_3C_EXT_MODEM_ID                   0x0000003C
++#define AC97_3E_EXT_MODEM_POWER                0x0000003E
++#define AC97_40_LINE1_CODEC_RATE               0x00000040
++#define AC97_42_LINE2_CODEC_RATE               0x00000042
++#define AC97_44_HANDSET_CODEC_RATE             0x00000044
++#define AC97_46_LINE1_CODEC_LEVEL              0x00000046
++#define AC97_48_LINE2_CODEC_LEVEL              0x00000048
++#define AC97_4A_HANDSET_CODEC_LEVEL            0x0000004A
++#define AC97_4C_GPIO_PIN_CONFIG                0x0000004C
++#define AC97_4E_GPIO_PIN_TYPE                  0x0000004E
++#define AC97_50_GPIO_PIN_STICKY                0x00000050
++#define AC97_52_GPIO_PIN_WAKEUP                0x00000052
++#define AC97_54_GPIO_PIN_STATUS                0x00000054
++#define AC97_56_RESERVED                       0x00000056
++#define AC97_58_RESERVED                       0x00000058
++#define AC97_5A_CRYSTAL_REV_N_FAB_ID           0x0000005A
++#define AC97_5C_TEST_AND_MISC_CTRL             0x0000005C
++#define AC97_5E_AC_MODE                        0x0000005E
++#define AC97_60_MISC_CRYSTAL_CONTROL           0x00000060
++#define AC97_62_VENDOR_RESERVED                0x00000062
++#define AC97_64_DAC_SRC_PHASE_INCR             0x00000064
++#define AC97_66_ADC_SRC_PHASE_INCR             0x00000066
++#define AC97_68_RESERVED_68                    0x00000068
++#define AC97_6A_SERIAL_PORT_CONTROL            0x0000006A
++#define AC97_6C_VENDOR_RESERVED                0x0000006C
++#define AC97_6E_VENDOR_RESERVED                0x0000006E
++#define AC97_70_BDI_CONFIG                     0x00000070
++#define AC97_72_BDI_WAKEUP                     0x00000072
++#define AC97_74_VENDOR_RESERVED                0x00000074
++#define AC97_76_CAL_ADDRESS                    0x00000076
++#define AC97_78_CAL_DATA                       0x00000078
++#define AC97_7A_VENDOR_RESERVED                0x0000007A
++#define AC97_7C_VENDOR_ID1                     0x0000007C
++#define AC97_7E_VENDOR_ID2                     0x0000007E
++
++#ifndef __ASSEMBLY__
++
++/* enum type for use with reg AC97_RECORD_SELECT */
++enum Ac97RecordSources {
++      RECORD_MIC = 0x0000,
++      RECORD_CD = 0x0101,
++      RECORD_VIDEO_IN = 0x0202,
++      RECORD_AUX_IN = 0x0303,
++      RECORD_LINE_IN = 0x0404,
++      RECORD_STEREO_MIX = 0x0505,
++      RECORD_MONO_MIX = 0x0606,
++      RECORD_PHONE_IN = 0x0707
++};
++
++#endif                                /* __ASSEMBLY__ */
++
++/*
++ * Sample rates supported directly in AC97_PCM_FRONT_DAC_RATE and
++ * AC97_PCM_LR_ADC_RATE.
++ */
++#define Ac97_Fs_8000        0x1f40
++#define Ac97_Fs_11025       0x2b11
++#define Ac97_Fs_16000       0x3e80
++#define Ac97_Fs_22050       0x5622
++#define Ac97_Fs_32000       0x7d00
++#define Ac97_Fs_44100       0xac44
++#define Ac97_Fs_48000       0xbb80
++
++/*
++ * RSIZE and TSIZE in AC97RXCR and AC97TXCR
++ */
++#define Ac97_SIZE_20            2
++#define Ac97_SIZE_18            1
++#define Ac97_SIZE_16            0
++#define Ac97_SIZE_12            3
++
++#endif                                /* _REGS_AC97_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_dma.h b/include/asm-arm/arch-ep93xx/regs_dma.h
+new file mode 100644
+index 0000000..926965d
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_dma.h
+@@ -0,0 +1,269 @@
++/*****************************************************************************
++ *
++ * linux/include/asm-arm/arch-ep93xx/regs_dma.h
++ *
++ *  Register definitions for the ep93xx dma channel registers.
++ *
++ *  Copyright (C) 2003 Cirrus Logic
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ ****************************************************************************/
++#ifndef _REGS_DMA_H_
++#define _REGS_DMA_H_
++
++/*****************************************************************************
++ * 0x8000.0000 -> 0x8000.003C M2P Channel 0 Registers (Tx)
++ * 0x8000.0040 -> 0x8000.007C M2P Channel 1 Registers (Rx)
++ * 0x8000.0080 -> 0x8000.00BC M2P Channel 2 Registers (Tx)
++ * 0x8000.00C0 -> 0x8000.00FC M2P Channel 3 Registers (Rx)
++ * 0x8000.0100 -> 0x8000.013C M2M Channel 0 Registers
++ * 0x8000.0140 -> 0x8000.017C M2M Channel 1 Registers
++ * 0x8000.0180 -> 0x8000.01BC Not Used
++ * 0x8000.01C0 -> 0x8000.01FC Not Used
++ * 0x8000.0200 -> 0x8000.023C M2P Channel 5 Registers (Rx)
++ * 0x8000.0240 -> 0x8000.027C M2P Channel 4 Registers (Tx)
++ * 0x8000.0280 -> 0x8000.02BC M2P Channel 7 Registers (Rx)
++ * 0x8000.02C0 -> 0x8000.02FC M2P Channel 6 Registers (Tx)
++ * 0x8000.0300 -> 0x8000.033C M2P Channel 9 Registers (Rx)
++ * 0x8000.0340 -> 0x8000.037C M2P Channel 8 Registers (Tx)
++ * 0x8000.0380 DMA Channel Arbitration register
++ * 0x8000.03C0 DMA Global Interrupt register
++ * 0x8000.03C4 -> 0x8000.03FC Not Used
++ *
++ *
++ * Internal M2P/P2M Channel Register Map
++ *
++ * Offset Name      Access  Bits Reset Value
++ * 0x00   CONTROL   R/W     6    0
++ * 0x04   INTERRUPT R/W TC* 3    0
++ * 0x08   PPALLOC   R/W     4    channel dependant
++ *                               (see reg description)
++ * 0x0C   STATUS    RO      8    0
++ * 0x10   reserved
++ * 0x14   REMAIN    RO      16   0
++ * 0X18   Reserved
++ * 0X1C   Reserved
++ * 0x20   MAXCNT0   R/W     16   0
++ * 0x24   BASE0     R/W     32   0
++ * 0x28   CURRENT0  RO      32   0
++ * 0x2C   Reserved
++ * 0x30   MAXCNT1   R/W     16   0
++ * 0x34   BASE1     R/W     32   0
++ * 0X38   CURRENT1  RO      32   0
++ * 0X3C   Reserved
++ *
++ * M2M Channel Register Map
++ * Offset Name         Access   Bits Reset Value
++ *
++ * 0x00   CONTROL      R/W      22   0
++ * 0x04   INTERRUPT    R/W TC*  3    0
++ * 0x08   Reserved
++ * 0x0C   STATUS       R/W TC*  14   0
++ * 0x10   BCR0         R/W      16   0
++ * 0x14   BCR1         R/W      16   0
++ * 0x18   SAR_BASE0    R/W      32   0
++ * 0x1C   SAR_BASE1    R/W      32   0
++ * 0x20   Reserved
++ * 0x24   SAR_CURRENT0 RO       32   0
++ * 0x28   SAR_CURRENT1 RO       32   0
++ * 0x2C   DAR_BASE0    R/W      32   0
++ * 0x30   DAR_BASE1    R/W      32   0
++ * 0x34   DAR_CURRENT0 RO       32   0
++ * 0X38   Reserved
++ * 0X3C   DAR_CURRENT1 RO       32   0
++ * * Write this location once to clear the bit (see
++ * Interrupt/Status register description for which bits
++ * this rule applies to).
++ *
++ ****************************************************************************/
++
++#ifndef __ASSEMBLY__
++/*
++ * DMA Register Base addresses
++ */
++static unsigned int const DMAM2PChannelBase[10] = {
++      DMA_M2P_TX_0_BASE,
++      DMA_M2P_RX_1_BASE,
++      DMA_M2P_TX_2_BASE,
++      DMA_M2P_RX_3_BASE,
++      DMA_M2P_TX_4_BASE,
++      DMA_M2P_RX_5_BASE,
++      DMA_M2P_TX_6_BASE,
++      DMA_M2P_RX_7_BASE,
++      DMA_M2P_TX_8_BASE,
++      DMA_M2P_RX_9_BASE
++};
++
++static unsigned int const DMAM2MChannelBase[2] = {
++      DMA_M2M_0_BASE,
++      DMA_M2M_1_BASE
++};
++
++#endif                                /* __ASSEMBLY__ */
++
++/*----------------------------------------------------------------------------------*/
++/* M2P Registers                                                                    */
++/*----------------------------------------------------------------------------------*/
++/*
++ * M2P CONTROL register bit defines
++ */
++#define CONTROL_M2P_STALLINTEN      0x00000001        /* Enables the STALL interrupt  */
++#define CONTROL_M2P_NFBINTEN        0x00000002        /* Enables the NFB interrupt    */
++#define CONTROL_M2P_CHERRORINTEN    0x00000008        /* Enables the ChError interrupt */
++#define CONTROL_M2P_ENABLE                0x00000010  /* Enables the channel          */
++#define CONTROL_M2P_ABRT                  0x00000020  /* Determines how DMA behaves in */
++                                                              /* NEXT state with peripheral   */
++                                                  /* error                        */
++                                                              /* 0: NEXT -> ON, ignore error  */
++                                                              /* 1: NEXT -> STALL, disable ch. */
++#define CONTROL_M2P_ICE                           0x00000040  /* Ignore Channel Error         */
++
++/*
++ * M2P INTERRUPT register bit defines
++ */
++#define INTERRUPT_M2P_STALLINT      0x00000001        /* Indicates channel stalled.   */
++#define INTERRUPT_M2P_NFBINT        0x00000002        /* Indicates channel is hungry. */
++#define INTERRUPT_M2P_CHERRORINT    0x00000008        /* Peripheral detects error     */
++
++/*
++ * STATUS register bit defines
++ */
++#define STATUS_M2P_STALL            0x00000001        /* A '1' indicates channel is       */
++                                                  /* stalled                          */
++#define STATUS_M2P_NFB                            0x00000002  /* A '1' indicates channel has moved */
++                                                              /* from NEXT state to ON state, but */
++                                                              /* waiting for next buffer to be    */
++                                                  /* programmed.                      */
++#define STATUS_M2P_CHERROR                0x00000008  /* Enables the ChError interrupt    */
++#define STATUS_M2P_CURRENT_MASK     0x00000030        /* Current state of the FSM         */
++#define STATUS_M2P_CURRENT_SHIFT    4
++#define STATUS_M2P_NEXTBUFFER     0x00000040  /* Informs the int handler after an */
++                                                              /* NFB int which pair of maxcnt and */
++                                                  /* base regs to update.             */
++#define STATUS_M2P_BYTES_MASK       0x0000f800        /* number of valid DMA data         */
++#define STATUS_M2P_BYTES_SHIFT      7 /* currently in                     */
++                                                                                          /* packer/unpacker                  */
++
++#define STATUS_M2P_DMA_NO_BUF         0x00000000
++#define STATUS_M2P_DMA_BUF_ON         0x00000010
++#define STATUS_M2P_DMA_BUF_NEXT               0x00000020
++
++/*
++ * Register masks to mask off reserved bits after reading register.
++ */
++#define M2P_MASK_PPALLOC            0x0000000f
++#define M2P_MASK_REMAIN             0x0000ffff
++#define M2P_MASK_MAXCNT0            0x0000ffff
++#define M2P_MASK_BASE0              0xffffffff
++#define M2P_MASK_CURRENT0           0xffffffff
++#define M2P_MASK_MAXCNT1            0x0000ffff
++#define M2P_MASK_BASE1              0xffffffff
++#define M2P_MASK_CURRENT1           0xffffffff
++
++/*----------------------------------------------------------------------------------*/
++/* M2M Registers                                                                    */
++/*----------------------------------------------------------------------------------*/
++
++#define CONTROL_M2M_STALLINTEN        0x00000001      /* Enables the STALL interrupt                     */
++#define CONTROL_M2M_SCT                       0x00000002      /* Source Copy Transfer. Setup a                   */
++                                                                                  /* block transfer from 1 memory source             */
++                                                                                  /* location.                                       */
++#define CONTROL_M2M_DONEINTEN 0x00000004      /* Enables the DONE interrupt which                */
++                                                                                  /* indicates if the xfer completed                 */
++                                                                                  /* successfully                                    */
++#define CONTROL_M2M_ENABLE            0x00000008      /* Enables the channel                             */
++#define CONTROL_M2M_START             0x00000010      /* Initiates the xfer. 'software trigger'          */
++#define CONTROL_M2M_BWC_MASK  0x000001e0      /* Bandwidth control. Indicate number of           */
++#define CONTROL_M2M_BWC_SHIFT   5     /* bytes in a transfer.                            */
++#define CONTROL_M2M_PW_MASK           0x00000600      /* Peripheral width. Used for xfers                */
++#define CONTROL_M2M_PW_SHIFT    9     /* between memory and external peripheral.         */
++                                                                                  /* 00: byte, 01: halfword, 10: word.               */
++#define CONTROL_M2M_DAH                       0x00000800      /* Destination Address Hold                        */
++#define CONTROL_M2M_SAH                       0x00001000      /* Source Address Hold                             */
++#define CONTROL_M2M_TM_MASK     0x00006000    /* Transfer Mode. 00: sw triggered,                */
++#define CONTROL_M2M_TM_SHIFT    13    /* 01: hw initiated M2P, 01: hw initiated P2M      */
++#define CONTROL_M2M_ETDP_MASK 0x00018000      /* End-of-Transfer/Terminal Count pin              */
++#define CONTROL_M2M_ETDP_SHIFT  15    /* direction and polarity.                         */
++#define CONTROL_M2M_DACKP             0x00020000      /* DMA acknowledge pin polarity                    */
++
++#define CONTROL_M2M_DREQP_MASK  0x00180000    /* DMA request pin polarity. must be set           */
++#define CONTROL_M2M_DREQP_SHIFT 19    /* before enable bit.                              */
++#define CONTROL_M2M_NFBINTEN  0x00200000      /* Enables generation of the NFB interrupt.        */
++#define CONTROL_M2M_RSS_MASK    0x00c00000    /* Request source selection:                       */
++#define CONTROL_M2M_RSS_SHIFT 22      /*              000 - External DReq[0]                     */
++                                                                                  /*          001 - External DReq[1]                     */
++                                                                                  /*          01X - Internal SSPRx                       */
++                                                                                  /*          10X - Internal SSPTx                       */
++                                                                                  /*          11X - Internal IDE                         */
++#define CONTROL_M2M_NO_HDSK           0x01000000      /* No handshake.  When set the peripheral doesn't  */
++                                                                                  /* require the regular handshake protocal. Must    */
++                                                                              /* be set for SSP and IDE operations, optional     */
++                                                                                  /* for external peripherals.                       */
++#define CONTROL_M2M_PWSC_MASK   0xfe000000    /* Peripheral wait states count. Gives the latency */
++#define CONTROL_M2M_PWSC_SHIFT        25      /* (in PCLK cycles) needed by the peripheral to    */
++                                                                              /* deassert its' request once the M2M xfer w/ DMA  */
++                                                                              /* is complete.                                    */
++
++/*
++ * M2M INTERRUPT register bit defines
++ */
++#define INTERRUPT_M2M_STALLINT        0x00000001      /* Stall interrupt indicates channel stalled. */
++#define INTERRUPT_M2M_DONEINT 0x00000002      /* Transaction done.                          */
++#define INTERRUPT_M2M_NFBINT  0x00000004      /* Next frame buffer interrupt indicates      */
++                                                                                      /* channel requires a new buffer              */
++
++/*
++ * M2M STATUS register bit defines
++ */
++#define STATUS_M2M_STALL              0x00000001      /* A '1' indicates channel is stalled           */
++#define STATUS_M2M_CURRENTSTATE_MASK  0x0000003e      /* Indicates state of M2M Channel control       */
++#define STATUS_M2M_CURRENTSTATE_SHIFT 1       /* FSM (0-2):                                   */
++                                                                                  /*  000 - IDLE, 001 - STALL, 010 - MEM_RD,      */
++                                                                                  /*  011 - MEM_WR, 100 - BWC_WAIT                */
++                                                                                  /* and M2M buffer FSM (3-2):                    */
++                                                                                  /*  00 - NO_BUF, 01 - BUF_ON, 10 - BUF_NEXT     */
++#define STATUS_M2M_DONE                   0x00000040  /* Transfer completed successfully if 1.        */
++#define STATUS_M2M_TCS_MASK           0x00000180      /* Terminal Count status. Indicates whether or  */
++#define STATUS_M2M_TCS_SHIFT    7     /* or not the actual byte count reached         */
++                                                                              /* programmed limit for buffer descriptor       */
++#define STATUS_M2M_EOTS_MASK    0x00000600    /* End-of-Transfer status for buffer            */
++#define STATUS_M2M_EOTS_SHIFT   9
++#define STATUS_M2M_NFB                        0x00000800      /* A '1' indicates channel has moved            */
++                                                                                  /* from NEXT state to ON state, but the next    */
++                                                                                  /* byte count reg for next buffer has not been  */
++                                                                                  /* programmed yet.                              */
++#define STATUS_M2M_NB                 0x00001000      /* NextBuffer status. Informs NFB service       */
++                                                                                  /* routine, after NFB int, which pair of buffer */
++                                                                                  /* descriptor registers is free to update.      */
++#define STATUS_M2M_DREQS              0x00002000      /* DREQ status.  Reflects the status of the     */
++                                                                                  /* synchronized external peripherals DMA        */
++                                                                                  /* request signal.                              */
++
++/*
++ * Register masks to mask off reserved bits after reading register.
++ */
++#define M2M_MASK_BCR0             0x0000ffff
++#define M2M_MASK_BCR1             0x0000ffff
++#define M2M_MASK_SAR_BASE0        0xffffffff
++#define M2M_MASK_SAR_BASE1        0xffffffff
++#define M2M_MASK_SAR_CURRENT0     0xffffffff
++#define M2M_MASK_SAR_CURRENT1     0xffffffff
++#define M2M_MASK_DAR_BASE0        0xffffffff
++#define M2M_MASK_DAR_BASE1        0xffffffff
++#define M2M_MASK_DAR_CURRENT0     0xffffffff
++#define M2M_MASK_DAR_CURRENT1     0xffffffff
++
++#endif                                /* _REGS_DMA_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_gpio.h b/include/asm-arm/arch-ep93xx/regs_gpio.h
+new file mode 100644
+index 0000000..12397be
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_gpio.h
+@@ -0,0 +1,31 @@
++/*=======================================================================
++ *
++ *  FILE:       regs_gpio.h
++ *
++ *  DESCRIPTION:    GPIO Register Definition
++ *
++ *  Copyright Cirrus Logic, 2001-2003
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *=======================================================================
++ */
++#ifndef _REGS_GPIO_H_
++#define _REGS_GPIO_H_
++
++/*
++ * This file intentionally blank.
++ */
++
++#endif                                /* _REGS_GPIO_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_hardcode.h b/include/asm-arm/arch-ep93xx/regs_hardcode.h
+new file mode 100644
+index 0000000..ecbc512
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_hardcode.h
+@@ -0,0 +1,110 @@
++/*
++ *  File:   linux/include/asm-arm/arch-ep93xx/regs_hardcode.h
++ *
++ *  Handle 'Must-be-zero' and 'Must-be-one' values for various
++ *  registers on different flavours of the EP93xx family.
++ *
++ *  Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef __ASM_ARCH_HARDCODE_H
++#define __ASM_ARCH_HARDCODE_H
++
++#if defined(CONFIG_ARCH_EP9301)
++#define ep93xx_SYSCON_DEVCFG(v)        (((v) & ~0x0460c220) | 0x08000d00)
++#define ep93xx_VIC0INTSELECT(v)        (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTSELECT(v)        (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_VIC0INTENABLE(v)        (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTENABLE(v)        (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_VIC0INTENCLEAR(v)       (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTENCLEAR(v)       (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_MAC_RXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_UART1MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_UART2TMR(v)             (((v) & ~0x000000fd) | 0x00000000)
++#define ep93xx_IrCtrl(v)               (((v) & ~0x00000001) | 0x00000000)
++#define ep93xx_RTCSCOMP(v)             (((v) & ~0x00200000) | 0x00000000)
++
++/* cut'n'paste from 9301, verify this section... */
++#elif defined(CONFIG_ARCH_EP9302)
++#define ep93xx_SYSCON_DEVCFG(v)        (((v) & ~0x0460c220) | 0x08000d00)
++#define ep93xx_VIC0INTSELECT(v)        (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTSELECT(v)        (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_VIC0INTENABLE(v)        (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTENABLE(v)        (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_VIC0INTENCLEAR(v)       (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTENCLEAR(v)       (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_MAC_RXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_UART1MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_UART2TMR(v)             (((v) & ~0x000000fd) | 0x00000000)
++#define ep93xx_IrCtrl(v)               (((v) & ~0x00000001) | 0x00000000)
++#define ep93xx_RTCSCOMP(v)             (((v) & ~0x00200000) | 0x00000000)
++
++#elif defined(CONFIG_ARCH_EP9312)
++#define ep93xx_SYSCON_DEVCFG(v)        (((v) & ~0x00000020) | 0x00000000)
++#define ep93xx_VIC0INTSELECT(v)        (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTSELECT(v)        (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC0INTENABLE(v)        (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTENABLE(v)        (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC0INTENCLEAR(v)       (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTENCLEAR(v)       (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_PIXELMODE(v)            (((v) & ~0x00010000) | 0x00000000)
++#define ep93xx_MAC_RXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_UART1MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_UART2TMR(v)             (((v) & ~0x000000fd) | 0x00000000)
++#define ep93xx_UART3MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_IrCtrl(v)               (((v) & ~0x00000001) | 0x00000000)
++#define ep93xx_RTCSCOMP(v)             (((v) & ~0x00200000) | 0x00000000)
++
++#elif defined(CONFIG_ARCH_EP9315)
++#define ep93xx_SYSCON_DEVCFG(v)        (((v) & ~0x00000020) | 0x00000000)
++#define ep93xx_VIC0INTSELECT(v)        (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTSELECT(v)        (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC0INTENABLE(v)        (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTENABLE(v)        (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC0INTENCLEAR(v)       (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTENCLEAR(v)       (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_PIXELMODE(v)            (((v) & ~0x00010000) | 0x00000000)
++#define ep93xx_MAC_RXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXBUFTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXSTSTHRSHLD(v)     (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXDTHRSHLD(v)       (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_UART1MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_UART2TMR(v)             (((v) & ~0x000000fd) | 0x00000000)
++#define ep93xx_UART3MCR(v)             (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_IrCtrl(v)               (((v) & ~0x00000001) | 0x00000000)
++#define ep93xx_RTCSCOMP(v)             (((v) & ~0x00200000) | 0x00000000)
++
++#endif
++
++#endif                                /* __ASM_ARCH_HARDWARE_H */
+diff --git a/include/asm-arm/arch-ep93xx/regs_i2s.h b/include/asm-arm/arch-ep93xx/regs_i2s.h
+new file mode 100644
+index 0000000..2ca60df
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_i2s.h
+@@ -0,0 +1,91 @@
++/*=============================================================================
++ *
++ *  FILE:             reg_i2s.h
++ *
++ *  DESCRIPTION:    ep93xx I2S Register Definition
++ *
++ *  Copyright Cirrus Logic, 2001-2003
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ *=============================================================================
++ */
++#ifndef _REG_I2S_H_
++#define _REG_I2S_H_
++
++/* I2STXClkCfg bits */
++#define i2s_txcc_trls           0x00000001
++#define i2s_txcc_tckp           0x00000002
++#define i2s_txcc_trel           0x00000004
++#define i2s_txcc_mstr           0x00000008
++#define i2s_txcc_nbcg           0x00000010
++
++#define i2s_txcc_bcr_32x        0x00000020
++#define i2s_txcc_bcr_64x        0x00000040
++#define i2s_txcc_bcr_128x       0x00000060
++
++/* I2SRxClkCfg bits */
++#define i2s_rxcc_rrls           0x00000001
++#define i2s_rxcc_rckp           0x00000002
++#define i2s_rxcc_rrel           0x00000004
++#define i2s_rxcc_mstr           0x00000008
++#define i2s_rxcc_nbcg           0x00000010
++
++#define i2s_rxcc_bcr_32x        0x00000020
++#define i2s_rxcc_bcr_64x        0x00000040
++#define i2s_rxcc_bcr_128x       0x00000060
++
++/* I2SGlSts bits */
++#define TX0_UNDERFLOW           0x00000001
++#define TX1_UNDERFLOW           0x00000002
++#define TX2_UNDERFLOW           0x00000004
++
++#define RX0_OVERFLOW            0x00000008
++#define RX1_OVERFLOW            0x00000010
++#define RX2_OVERFLOW            0x00000020
++
++#define TX0_OVERFLOW            0x00000040
++#define TX1_OVERFLOW            0x00000080
++#define TX2_OVERFLOW            0x00000100
++
++#define RX0_UNDERFLOW           0x00000200
++#define RX1_UNDERFLOW           0x00000400
++#define RX2_UNDERFLOW           0x00000800
++
++#define TX0_FIFO_FULL           0x00001000
++#define TX0_FIFO_EMPTY          0x00002000
++#define TX0_FIFO_HALF_EMPTY     0x00004000
++
++#define RX0_FIFO_FULL           0x00008000
++#define RX0_FIFO_EMPTY          0x00010000
++#define RX0_FIFO_HALF_FULL      0x00020000
++
++#define TX1_FIFO_FULL           0x00040000
++#define TX1_FIFO_EMPTY          0x00080000
++#define TX1_FIFO_HALF_EMPTY     0x00100000
++
++#define RX1_FIFO_FULL           0x00200000
++#define RX1_FIFO_EMPTY          0x00400000
++#define RX1_FIFO_HALF_FULL      0x00800000
++
++#define TX2_FIFO_FULL           0x01000000
++#define TX2_FIFO_EMPTY          0x02000000
++#define TX2_FIFO_HALF_EMPTY     0x04000000
++
++#define RX2_FIFO_FULL           0x08000000
++#define RX2_FIFO_EMPTY          0x10000000
++#define RX2_FIFO_HALF_FULL      0x20000000
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/regs_ide.h b/include/asm-arm/arch-ep93xx/regs_ide.h
+new file mode 100644
+index 0000000..762ebfd
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_ide.h
+@@ -0,0 +1,250 @@
++/*****************************************************************************
++ *
++ *  linux/include/asm-arm/arch-ep93xx/regs_ide.h
++ *
++ *  Register definitions for the ep93xx ide registers.
++ *
++ *  Copyright (C) 2003 Cirrus Logic
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++
++ *
++ ****************************************************************************/
++#ifndef _REGS_IDE_H_
++#define _REGS_IDE_H_
++
++#ifndef __ASSEMBLY__
++
++/*****************************************************************************
++ *
++ * IDE register definitions
++ *
++ ****************************************************************************/
++typedef struct _ide_regs_s {
++      union {
++              unsigned int Value;
++      } IDECR;                /* 00 */
++
++      union {
++              struct {
++                      unsigned int IDEEN:1;   /* IDE master enable                    */
++                      unsigned int PIO:1;     /* Polled IO operation selection        */
++                      unsigned int MDMA:1;    /* Multiword DMA operation selection    */
++                      unsigned int UDMA:1;    /* Ultra DMA operation selection        */
++                      unsigned int MODE:4;    /* Speed mode number (0 - 4 for PIO,    */
++                      /* 0 - 2 for MDMA, 0 - 4 for UDMA)      */
++                      unsigned int WST:2;     /* Wait State for Turn.  Number of      */
++                      /* HCLK cycles to hold the data bus     */
++                      /* after                                */
++                      /* PIO write operation                  */
++                      unsigned int RAZ:22;    /* read only always zero                */
++              } Field;
++              unsigned int Value;
++      } IDECFG;               /* 04 */
++
++      union {
++              struct {
++                      unsigned int MEN:1;     /* Enable Multiword DMA operation.      */
++                      /* 1 - start mdma, 0 - terminate        */
++                      /* mdma operation by host.              */
++                      unsigned int RWOP:1;    /* Read or write operation selection:   */
++                      /* 0 = read, 1 = write.                 */
++                      unsigned int RAZ:30;    /* read only always zero                */
++              } Field;
++              unsigned int Value;
++      } IDEMDMAOP;            /* 08 */
++
++      union {
++              struct {
++                      unsigned int UEN:1;     /* Enable Ultra DMA operation           */
++                      /* 1 - start udma, 0 - terminate        */
++                      /* udma operation by host.              */
++                      unsigned int RWOP:1;    /* Read or write operation selection:   */
++                      /* 0 = read, 1 = write.                 */
++                      unsigned int RAZ:30;    /* read only always zero                */
++              } Field;
++              unsigned int Value;
++      } IDEUDMAOP;            /* 0C */
++
++      union {
++              unsigned int Value;
++      } IDEDATAOUT;           /* 10 */
++
++      union {
++              unsigned int Value;
++      } IDEDATAIN;            /* 14 */
++
++      union {
++              struct {
++                      unsigned int IDEDD:32;  /* IDE output data in the output buffer */
++                      /* in MDMA mode.  This register should  */
++                      /* only be written to by the DMA engine. */
++              } Field;
++              unsigned int Value;
++      } IDEMDMADATAOUT;       /* 18 */
++
++      union {
++              struct {
++                      unsigned int IDEDD:32;  /* IDE input data in the input buffer   */
++                      /* in MDMA mode.                        */
++              } Field;
++              unsigned int Value;
++      } IDEMDMADATAIN;        /* 1C */
++
++      union {
++              struct {
++                      unsigned int IDEDD:32;  /* IDE output data at the tail of the   */
++                      /* output buffer in UDMA mode.          */
++              } Field;
++              unsigned int Value;
++      } IDEUDMADATAOUT;       /* 20 */
++
++      union {
++              struct {
++                      unsigned int IDEDD:32;  /* IDE input data at teh head of the    */
++                      /* input buffer in UDMA mode.           */
++              } Field;
++              unsigned int Value;
++      } IDEUDMADATAIN;        /* 24 */
++
++      union {
++              struct {
++                      unsigned int CS0n:1;    /* Chip select pin 0 status. Should     */
++                      /* be driven to 1 (deasserted) in UDMA  */
++                      unsigned int CS1n:1;    /* Chip select pin 1 status. Should     */
++                      /* be driven to 1 (deasserted) in UDMA  */
++                      unsigned int DA:3;      /* Device address status, should be     */
++                      /* driven to 0 (deasserted) in UDMA     */
++                      unsigned int HSHD:1;    /* HSTROBE (during data out) status,    */
++                      /* HDMARDYn (during data in) status,    */
++                      /* driven by UDMA state machine.        */
++                      unsigned int STOP:1;    /* STOP (during data out) status, driven */
++                      /* by UDMA state machine.               */
++                      unsigned int DM:1;      /* DMACKn status, driven by UDMA state  */
++                      /* machine.                             */
++                      unsigned int DDOE:1;    /* DD bus output enable as controlled   */
++                      /* by UDMA state machine.               */
++                      unsigned int DMARQ:1;   /* Synchronized version of DMARQ input  */
++                      /* from device.                         */
++                      unsigned int DSDD:1;    /* DSTROBE (during data in) and DDMARDYn */
++                      /* (during data out) status from device. */
++                      unsigned int RAZ1:5;    /* reserved, always zero                */
++                      unsigned int DMAIDE:1;  /* DMA request signal from UDMA state   */
++                      /* machine.                             */
++                      unsigned int INTIDE:1;  /* INT line generated by UDMA state     */
++                      /* machine.                             */
++                      unsigned int SBUSY:1;   /* UDMA state machine busy, not in idle */
++                      /* state.                               */
++                      unsigned int RAZ2:5;    /* Reserved, always zero.               */
++                      unsigned int NDO:1;     /* Error for data out not completed     */
++                      unsigned int NDI:1;     /* Error for data in not completed      */
++                      unsigned int N4X:1;     /* Error for data transferred not       */
++                      /* multiples of 4 32 bit words.         */
++                      unsigned int RAZ3:5;    /* Reserved, always zero                */
++              } Field;
++              unsigned int Value;
++      } IDEUDMASTATUS;        /* 28 */
++
++      union {
++              struct {
++                      unsigned int RWOE:1;    /* Reset UDMA write data out error.     */
++                      unsigned int RWPTR:1;   /* Reset UDMA write buffer ptr to 0.    */
++                      unsigned int RWDR:1;    /* Reset UDMA write DMA request.        */
++                      unsigned int RROE:1;    /* Reset UDMA read data in error.       */
++                      unsigned int RRPTR:1;   /* Reset UDMA read buffer ptr to 0.     */
++                      unsigned int RRDR:1;    /* Reset UDMA read DMA request.         */
++                      unsigned int RAZ:26;    /* reserved, always zero                */
++              } Field;
++              unsigned int Value;
++      } IDEUDMADEBUG;         /* 2C */
++
++      union {
++              struct {
++                      unsigned int HPTR:4;    /* Head pointer in the write buffer     */
++                      unsigned int TPTR:4;    /* Tail pointer in the write buffer     */
++                      unsigned int EMPTY:1;   /* Write buffer empty status            */
++                      unsigned int HOM:1;     /* Half or more entries in write buffer */
++                      /* filled status                        */
++                      unsigned int NFULL:1;   /* Write buffer near full status        */
++                      unsigned int FULL:1;    /* Write buffer full status             */
++                      unsigned int RAZ:4;     /* Reserved, always zero                */
++                      unsigned int CRC:16;    /* CRC result for data operation        */
++                      /* TODO: is there a CRC?                */
++              } Field;
++              unsigned int Value;
++      } IDEUDMAWFST;          /* 30 */
++
++      union {
++              struct {
++                      unsigned int HPTR:4;    /* Head pointer in the read buffer      */
++                      unsigned int TPTR:4;    /* Tail pointer in the read buffer      */
++                      unsigned int EMPTY:1;   /* Read buffer empty status             */
++                      unsigned int HOM:1;     /* Half or more entries in read buffer  */
++                      /* filled status                        */
++                      unsigned int NFULL:1;   /* Read buffer near full status         */
++                      unsigned int FULL:1;    /* Read buffer full status              */
++                      unsigned int RAZ:4;     /* Reserved, always zero                */
++                      unsigned int CRC:16;    /* CRC result for data operation        */
++                      /* TODO: is there a CRC?                */
++              } Field;
++              unsigned int Value;
++      } IDEUDMARFST;          /* 34 */
++
++} IDEREGISTERS;
++
++/*****************************************************************************
++ *
++ * Global Register Anchor Definitions (these address values will change)
++ *
++ ****************************************************************************/
++#ifdef CONFIG_BLK_DEV_EP93XX
++static volatile IDEREGISTERS *const ep93xx_ide_regs =
++    (IDEREGISTERS *) (IDE_BASE);
++#endif
++
++#endif                                /* Not __ASSEMBLY__ */
++
++#define IDECtrl             HW_REG(io_p2v(0x800a0000))
++#define IDECfg              HW_REG(io_p2v(0x800a0004))
++#define IDEMDMAOp           HW_REG(io_p2v(0x800a0008))
++#define IDEUDMAOp           HW_REG(io_p2v(0x800a000c))
++#define IDEDataOut          HW_REG(io_p2v(0x800a0010))
++#define IDEDataIn           HW_REG(io_p2v(0x800a0014))
++#define IDEMDMADataOut      HW_REG(io_p2v(0x800a0018))
++#define IDEMDMADataIn       HW_REG(io_p2v(0x800a001c))
++#define IDEUDMADataOut      HW_REG(io_p2v(0x800a0020))
++#define IDEUDMADataIn       HW_REG(io_p2v(0x800a0024))
++#define IDEUDMASts          HW_REG(io_p2v(0x800a0028))
++#define IDEUDMADebug        HW_REG(io_p2v(0x800a002c))
++#define IDEUDMAWrBufSts     HW_REG(io_p2v(0x800a0030))
++#define IDEUDMARdBufSts     HW_REG(io_p2v(0x800a0034))
++
++/*****************************************************************************
++ *
++ *  Bit definitions for use with assembly code for the ide control register.
++ *
++ ****************************************************************************/
++#define IDECtrl_CS0n          0x00000001
++#define IDECtrl_CS1n          0x00000002
++#define IDECtrl_DA_MASK       0x0000001c
++#define IDECtrl_DA_SHIFT      2
++#define IDECtrl_DIORn         0x00000020
++#define IDECtrl_DIOWn         0x00000040
++#define IDECtrl_DASPn         0x00000080
++#define IDECtrl_DMARQ         0x00000100
++#define IDECtrl_INTRQ         0x00000200
++#define IDECtrl_IORDY         0x00000400
++
++#endif                                /* _REGS_IDE_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_irda.h b/include/asm-arm/arch-ep93xx/regs_irda.h
+new file mode 100644
+index 0000000..77edafa
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_irda.h
+@@ -0,0 +1,24 @@
++/*=======================================================================
++ *
++ *  FILE:       regs_irda.h
++ *
++ *  DESCRIPTION:    IrDA Register Definition
++ *
++ *  Copyright Cirrus Logic, 2001-2003
++ *
++ *=======================================================================
++ */
++#ifndef _REGS_IRDA_H_
++#define _REGS_IRDA_H_
++
++/* Bit definitions */
++
++#define IrEnable_EN_NONE      0x00
++#define IrEnable_EN_SIR               0x01
++#define IrEnable_EN_MIR               0x02
++#define IrEnable_EN_FIR               0x03
++#define IrEnable_LBM          0x04
++#define IrEnable_MD                   0x08
++#define IrEnable_FD                   0x10
++
++#endif                                /* _REGS_IRDA_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_pcmcia.h b/include/asm-arm/arch-ep93xx/regs_pcmcia.h
+new file mode 100644
+index 0000000..6f731e7
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_pcmcia.h
+@@ -0,0 +1,72 @@
++/*
++ *  linux/include/asm-arm/arch-ep93xx/regs-pcmcia.h
++ *
++ *  Derived from:
++ *  linux/include/asm-arm/arch-pxa/pxa-regs.h
++ *
++ *  Author:   Nicolas Pitre
++ *  Created:  Jun 15, 2001
++ *  Copyright:        MontaVista Software Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/*
++ * Personal Computer Memory Card International Association (PCMCIA) sockets
++ * (from pxa-regs.h for compatibility)
++ */
++#ifndef _REGS_PCMCIA_H_
++#define _REGS_PCMCIA_H_
++
++#define PCMCIAPrtSp   0x04000000      /* PCMCIA Partition Space [byte]   */
++#define PCMCIASp      (4*PCMCIAPrtSp) /* PCMCIA Space [byte]             */
++#define PCMCIAIOSp    PCMCIAPrtSp     /* PCMCIA I/O Space [byte]         */
++#define PCMCIAAttrSp  PCMCIAPrtSp     /* PCMCIA Attribute Space [byte]   */
++#define PCMCIAMemSp   PCMCIAPrtSp     /* PCMCIA Memory Space [byte]      */
++
++#define PCMCIA0Sp     PCMCIASp        /* PCMCIA 0 Space [byte]           */
++#define PCMCIA0IOSp   PCMCIAIOSp      /* PCMCIA 0 I/O Space [byte]       */
++#define PCMCIA0AttrSp PCMCIAAttrSp    /* PCMCIA 0 Attribute Space [byte] */
++#define PCMCIA0MemSp  PCMCIAMemSp     /* PCMCIA 0 Memory Space [byte]    */
++
++#define PCMCIA1Sp     PCMCIASp        /* PCMCIA 1 Space [byte]           */
++#define PCMCIA1IOSp   PCMCIAIOSp      /* PCMCIA 1 I/O Space [byte]       */
++#define PCMCIA1AttrSp PCMCIAAttrSp    /* PCMCIA 1 Attribute Space [byte] */
++#define PCMCIA1MemSp  PCMCIAMemSp     /* PCMCIA 1 Memory Space [byte]    */
++
++
++#define _PCMCIA(Nb)                   /* PCMCIA [0..1]                   */ \
++                      (0x40000000 + (Nb)*PCMCIASp)
++#define _PCMCIAIO(Nb) _PCMCIA (Nb)    /* PCMCIA I/O [0..1]               */
++#define _PCMCIAAttr(Nb)                       /* PCMCIA Attribute [0..1]         */ \
++                      (_PCMCIA (Nb) + 2*PCMCIAPrtSp)
++#define _PCMCIAMem(Nb)                        /* PCMCIA Memory [0..1]            */ \
++                      (_PCMCIA (Nb) + 3*PCMCIAPrtSp)
++
++#define _PCMCIA0      _PCMCIA (0)     /* PCMCIA 0                        */
++#define _PCMCIA0IO    _PCMCIAIO (0)   /* PCMCIA 0 I/O                    */
++#define _PCMCIA0Attr  _PCMCIAAttr (0) /* PCMCIA 0 Attribute              */
++#define _PCMCIA0Mem   _PCMCIAMem (0)  /* PCMCIA 0 Memory                 */
++
++#define _PCMCIA1      _PCMCIA (1)     /* PCMCIA 1                        */
++#define _PCMCIA1IO    _PCMCIAIO (1)   /* PCMCIA 1 I/O                    */
++#define _PCMCIA1Attr  _PCMCIAAttr (1) /* PCMCIA 1 Attribute              */
++#define _PCMCIA1Mem   _PCMCIAMem (1)  /* PCMCIA 1 Memory                 */
++
++#define PCATTRIB(sock) ((sock ==0) ? (PC1ATTRIB) : (PC2ATTRIB))
++#define PCCOMMON(sock) ((sock ==0) ? (PC1COMMON) : (PC2COMMON))
++#define PCIO(sock)     ((sock ==0) ? (PC1IO)     : (PC2IO))
++
++#define PC16BITSWIDE 0x80000000
++
++#define PCMCIA_WRPROT 0x01
++#define PCMCIA_DETECT 0x06
++#define PCMCIA_BVD1   0x08
++#define PCMCIA_BVD2   0x10
++#define PCMCIA_VS_3V  0x20
++#define PCMCIA_READY  0x40
++#define PCMCIA_VS_XV  0x80
++
++#endif /* _REGS_PCMCIA_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_raster.h b/include/asm-arm/arch-ep93xx/regs_raster.h
+new file mode 100644
+index 0000000..bfab3ed
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_raster.h
+@@ -0,0 +1,279 @@
++/*=============================================================================
++ *
++ *  FILE:             regs_raster.h
++ *
++ *  DESCRIPTION:    ep93xx Raster Engine Register Definition
++ *
++ *  Copyright Cirrus Logic, 2001-2003
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ *=============================================================================
++ */
++#ifndef _REGS_RASTER_H_
++#define _REGS_RASTER_H_
++
++/* VLINESTOTAL Register Definitions */
++#define VLINESTOTAL_MASK            0x000007ff
++
++/* VSYNCSTRTSTOP Register Definitions */
++#define VSYNCSTRTSTOP_STRT_MASK     0x07ff0000
++#define VSYNCSTRTSTOP_STRT_SHIFT    0
++#define VSYNCSTRTSTOP_STOP_MASK     0x000007ff
++#define VSYNCSTRTSTOP_STOP_SHIFT    16
++
++/* VACTIVESTRTSTOP Register Definitions */
++#define VACTIVESTRTSTOP_STRT_MASK   0x07ff0000
++#define VACTIVESTRTSTOP_STRT_SHIFT  0
++#define VACTIVESTRTSTOP_STOP_MASK   0x000007ff
++#define VACTIVESTRTSTOP_STOP_SHIFT  16
++
++/* VCLKSTRTSTOP Register Definitions */
++#define VCLKSTRTSTOP_STRT_MASK      0x07ff0000
++#define VCLKSTRTSTOP_STRT_SHIFT     0
++#define VCLKSTRTSTOP_STOP_MASK      0x000007ff
++#define VCLKSTRTSTOP_STOP_SHIFT     16
++
++/* VBLANKSTRTSTOP Register Definitions */
++#define VBLANKSTRTSTOP_STRT_MASK  0x07ff0000
++#define VBLANKSTRTSTOP_STRT_SHIFT 0
++#define VBLANKSTRTSTOP_STOP_MASK  0x000007ff
++#define VBLANKSTRTSTOP_STOP_SHIFT 16
++
++/* HSYNCSTRTSTOP Register Definitions */
++#define HSYNCSTRTSTOP_STRT_MASK      0x07ff0000
++#define HSYNCSTRTSTOP_STRT_SHIFT     0
++#define HSYNCSTRTSTOP_STOP_MASK      0x000007ff
++#define HSYNCSTRTSTOP_STOP_SHIFT     16
++
++/* HACTIVESTRTSTOP Register Definitions */
++#define HACTIVESTRTSTOP_STRT_MASK    0x07ff0000
++#define HACTIVESTRTSTOP_STRT_SHIFT   0
++#define HACTIVESTRTSTOP_STOP_MASK    0x000007ff
++#define HACTIVESTRTSTOP_STOP_SHIFT   16
++
++/* HCLKSTRTSTOP Register Definitions */
++#define HCLKSTRTSTOP_STRT_MASK      0x07ff0000
++#define HCLKSTRTSTOP_STRT_SHIFT     0
++#define HCLKSTRTSTOP_STOP_MASK      0x000007ff
++#define HCLKSTRTSTOP_STOP_SHIFT     16
++
++/* BRIGHTNESS Register Definitions */
++#define BRIGHTNESS_MASK             0x0000ffff
++#define BRIGHTNESS_CNT_MASK         0x000000ff
++#define BRIGHTNESS_CNT_SHIFT        0
++#define BRIGHTNESS_CMP_MASK         0x0000ff00
++#define BRIGHTNESS_CMP_SHIFT        8
++
++/* VIDEOATTRIBS Register Definitions */
++#define VIDEOATTRIBS_MASK           0x001fffff
++#define VIDEOATTRIBS_EN             0x00000001
++#define VIDEOATTRIBS_PCLKEN         0x00000002
++#define VIDEOATTRIBS_SYNCEN         0x00000004
++#define VIDEOATTRIBS_DATAEN         0x00000008
++#define VIDEOATTRIBS_CSYNC          0x00000010
++#define VIDEOATTRIBS_VCPOL          0x00000020
++#define VIDEOATTRIBS_HSPOL          0x00000040
++#define VIDEOATTRIBS_BLKPOL         0x00000080
++#define VIDEOATTRIBS_INVCLK         0x00000100
++#define VIDEOATTRIBS_ACEN           0x00000200
++#define VIDEOATTRIBS_LCDEN          0x00000400
++#define VIDEOATTRIBS_RGBEN          0x00000800
++#define VIDEOATTRIBS_CCIREN         0x00001000
++#define VIDEOATTRIBS_PIFEN          0x00002000
++#define VIDEOATTRIBS_INTEN          0x00004000
++#define VIDEOATTRIBS_INT            0x00008000
++#define VIDEOATTRIBS_INTRLC         0x00010000
++#define VIDEOATTRIBS_EQUSER         0x00020000
++#define VIDEOATTRIBS_DHORZ          0x00040000
++#define VIDEOATTRIBS_DVERT          0x00080000
++#define VIDEOATTRIBS_BKPXD          0x00100000
++
++#define VIDEOATTRIBS_SDSEL_MASK     0x00600000
++#define VIDEOATTRIBS_SDSEL_SHIFT    21
++
++/* HBLANKSTRTSTOP Register Definitions */
++#define HBLANKSTRTSTOP_STRT_MASK    0x07ff0000
++#define HBLANKSTRTSTOP_STRT_SHIFT   0
++#define HBLANKSTRTSTOP_STOP_MASK    0x000007ff
++#define HBLANKSTRTSTOP_STOP_SHIFT   16
++
++/* LINECARRY Register Definitions */
++#define LINECARRY_LCARY_MASK        0x000007ff
++#define LINECARRY_LCARY_SHIFT       0
++
++/* BLINKRATE Register Definitons */
++#define BLINKRATE_MASK              0x000000ff
++
++/* BLINKMASK Register Definitons */
++#define BLINKMASK_MASK              0x00ffffff
++
++/* VIDSCRNPAGE Register Definitons */
++#define VIDSCRNPAGE_PAGE_MASK       0x0ffffffc
++
++/* VIDSCRNHPG Register Definitons */
++#define VIDSCRNHPG_MASK             0x0ffffffc
++
++/* SCRNLINES Register Definitons */
++#define SCRNLINES_MASK              0x000007ff
++
++/* LINELENGTH Register Definitons */
++#define LINELENGTH_MASK             0x000007ff
++
++/* VLINESTEP Register Definitons */
++#define VLINESTEP_MASK              0x00000fff
++
++/* REALITI_SWLOCK Register Definitons */
++#define REALITI_SWLOCK_MASK_WR      0xff
++#define REALITI_SWLOCK_MASK_R       0x1
++#define REALITI_SWLOCK_VALUE        0xaa
++
++/* LUTCONT Register Definitions */
++#define LUTCONT_MASK                0x00000003
++#define LUTCONT_SWTCH               0x00000001
++#define LUTCONT_STAT                0x00000002
++#define LUTCONT_RAM0                0
++#define LUTCONT_RAM1                1
++
++/* CURSORBLINK1 Register Definitions */
++#define CURSORBLINK1_MASK           0x00ffffff
++/* CURSORBLINK2 Register Definitions */
++#define CURSORBLINK2_MASK           0x00ffffff
++
++/* CURSORBLINK Register Definitions */
++#define CURSORBLINK_MASK            0x000001ff
++#define CURSORBLINK_RATE_MASK       0x000000ff
++#define CURSORBLINK_RATE_SHIFT      0
++#define CURSORBLINK_EN              0x00000100
++
++/* BLINKPATRN Register Definitions */
++#define BLINKPATRN_MASK             0x00ffffff
++
++/* PATRNMASK Register Definitions */
++#define PATRNMASK_MASK              0x00ffffff
++
++/* BG_OFFSET Register Definitions */
++#define BG_OFFSET_MASK              0x00ffffff
++
++/* PIXELMODE Register Definitions */
++#define PIXELMODE_P_MASK            0x00000007
++#define PIXELMODE_P_MUX_DISABLE     0x00000000
++#define PIXELMODE_P_4BPP            0x00000001
++#define PIXELMODE_P_8BPP            0x00000002
++#define PIXELMODE_P_16BPP           0x00000004
++#define PIXELMODE_P_24BPP           0x00000006
++#define PIXELMODE_P_32BPP           0x00000007
++#define PIXELMODE_P_SHIFT           0
++
++#define PIXELMODE_S_MASK            0x00000038
++#define PIXELMODE_S_SHIFT           3
++#define PIXELMODE_S_1PPC            0x0
++#define PIXELMODE_S_1PPCMAPPED      0x1
++#define PIXELMODE_S_2PPC            0x2
++#define PIXELMODE_S_4PPC            0x3
++#define PIXELMODE_S_8PPC            0x4
++#define PIXELMODE_S_223PPC          0x5
++#define PIXELMODE_S_DS223PPC        0x6
++#define PIXELMODE_S_UNDEF           0x7
++
++#define PIXELMODE_M_MASK            0x000003c0
++#define PIXELMODE_M_SHIFT           6
++#define PIXELMODE_M_NOBLINK         0
++#define PIXELMODE_M_ANDBLINK        1
++#define PIXELMODE_M_ORBLINK         2
++#define PIXELMODE_M_XORBLINK        3
++#define PIXELMODE_M_BGBLINK         4
++#define PIXELMODE_M_OFFSINGBLINK    5
++#define PIXELMODE_M_OFF888BLINK     6
++#define PIXELMODE_M_DIMBLINK        0xc
++#define PIXELMODE_M_BRTBLINK        0xd
++#define PIXELMODE_M_DIM888BLINK     0xe
++#define PIXELMODE_M_BRT888BLINK     0xf
++
++#define PIXELMODE_C_MASK            0x00003c00
++#define PIXELMODE_C_SHIFT           10
++#define PIXELMODE_C_LUT             0
++#define PIXELMODE_C_888             4
++#define PIXELMODE_C_565             5
++#define PIXELMODE_C_555             6
++#define PIXELMODE_C_GSLUT           8
++
++#define PIXELMODE_DSCAN             0x00004000
++#define PIXELMODE_TRBSW             0x00008000
++#define PIXELMODE_P13951            0x00010000
++
++/*PARLLIFOUT Register Defintions */
++#define PARLLIFOUT_DAT_MASK         0x0000000f
++#define PARLLIFOUT_DAT_SHIFT        0
++#define PARLLIFOUT_RD               0x00000010
++
++/*PARLLIFIN Register Defintions */
++#define PARLLIFIN_DAT_MASK          0x0000000f
++#define PARLLIFIN_DAT_SHIFT         0
++#define PARLLIFIN_CNT_MASK          0x000f0000
++#define PARLLIFIN_CNT_SHIFT         16
++#define PARLLIFIN_ESTRT_MASK        0x00f00000
++#define PARLLIFIN_ESTRT_SHIFT       20
++
++/* CURSORADRSTART Register Defintions */
++#define CURSOR_ADR_START_MASK         0xfffffffc
++
++/* CURSORADRSTART Register Defintions */
++#define CURSOR_ADR_RESET_MASK         0xfffffffc
++
++/* CURSORCOLOR1 Register Definitions */
++#define CURSORCOLOR1_MASK               0x00ffffff
++/* CURSORCOLOR2 Register Definitions */
++#define CURSORCOLOR2_MASK               0x00ffffff
++
++/* CURSORXYLOC Register Definitions */
++#define CURSORXYLOC_MASK                0x07ff87ff
++#define CURSORXYLOC_XLOC_MASK           0x000007ff
++#define CURSORXYLOC_XLOC_SHIFT          0
++#define CURSORXYLOC_CEN                 0x00008000
++#define CURSORXYLOC_YLOC_MASK           0x07ff0000
++#define CURSORXYLOC_YLOC_SHIFT          16
++
++/* CURSOR_DSCAN_LH_YLOC Register Definitions */
++#define CURSOR_DSCAN_LH_YLOC_MASK       0x000087ff
++
++#define CURSOR_DSCAN_LH_YLOC_YLOC_MASK  0x000007ff
++#define CURSOR_DSCAN_LH_YLOC_YLOC_SHIFT 0
++#define CURSOR_DSCAN_LH_YLOC_CLHEN      0x00008000
++
++/* CURSORSIZE Register Definitions */
++#define CURSORSIZE_MASK                 0x0000ffff
++
++#define CURSORSIZE_CWID_MASK            0x00000003
++#define CURSORSIZE_CWID_SHIFT           0
++#define CURSORSIZE_CWID_1_WORD          0
++#define CURSORSIZE_CWID_2_WORD          1
++#define CURSORSIZE_CWID_3_WORD          2
++#define CURSORSIZE_CWID_4_WORD          3
++
++#define CURSORSIZE_CLINS_MASK           0x000000fc
++#define CURSORSIZE_CLINS_SHIFT          2
++
++#define CURSORSIZE_CSTEP_MASK           0x00000300
++#define CURSORSIZE_CSTEP_SHIFT          8
++#define CURSORSIZE_CSTEP_1_WORD         0
++#define CURSORSIZE_CSTEP_2_WORD         1
++#define CURSORSIZE_CSTEP_3_WORD         2
++#define CURSORSIZE_CSTEP_4_WORD         3
++
++#define CURSORSIZE_DLNS_MASK            0x0000fc00
++#define CURSORSIZE_DLNS_SHIFT           10
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/regs_spi.h b/include/asm-arm/arch-ep93xx/regs_spi.h
+new file mode 100644
+index 0000000..a51d3dc
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_spi.h
+@@ -0,0 +1,76 @@
++/*=======================================================================
++ *
++ *  FILE:       regs_spi.h
++ *
++ *  DESCRIPTION:    SSP Register Definition
++ *
++ *  Copyright Cirrus Logic, 2001-2003
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *=======================================================================
++ */
++
++#ifndef _REGS_SSP_H_
++#define _REGS_SSP_H_
++
++/* Bits in SSPCR0 */
++#define SSPCR0_DSS_MASK             0x0000000f
++#define SSPCR0_DSS_4BIT             0x00000003
++#define SSPCR0_DSS_5BIT             0x00000004
++#define SSPCR0_DSS_6BIT             0x00000005
++#define SSPCR0_DSS_7BIT             0x00000006
++#define SSPCR0_DSS_8BIT             0x00000007
++#define SSPCR0_DSS_9BIT             0x00000008
++#define SSPCR0_DSS_10BIT            0x00000009
++#define SSPCR0_DSS_11BIT            0x0000000a
++#define SSPCR0_DSS_12BIT            0x0000000b
++#define SSPCR0_DSS_13BIT            0x0000000c
++#define SSPCR0_DSS_14BIT            0x0000000d
++#define SSPCR0_DSS_15BIT            0x0000000e
++#define SSPCR0_DSS_16BIT            0x0000000f
++
++/* Bits in SSPCR1 */
++#define SSPC1_RIE                   0x00000001
++#define SSPC1_TIE                   0x00000002
++#define SSPC1_RORIE                       0x00000004
++#define SSPC1_LBM                   0x00000008
++#define SSPC1_SSE                   0x00000010
++#define SSPC1_MS                    0x00000020
++#define SSPC1_SOD                   0x00000040
++
++#define SSPCR0_DSS_SHIFT            0
++#define SSPCR0_FRF_MASK             0x00000030
++#define SSPCR0_FRF_SHIFT            4
++#define SSPCR0_FRF_MOTOROLA         (0 << SSPCR0_FRF_SHIFT)
++#define SSPCR0_FRF_TI               (1 << SSPCR0_FRF_SHIFT)
++#define SSPCR0_FRF_NI               (2 << SSPCR0_FRF_SHIFT)
++#define SSPCR0_SPO                  0x00000040
++#define SSPCR0_SPH                  0x00000080
++#define SSPCR0_SCR_MASK             0x0000ff00
++#define SSPCR0_SCR_SHIFT            8
++
++/* Bits in SSPSR */
++#define SSPSR_TFE                 0x00000001  /* TX FIFO is empty */
++#define SSPSR_TNF             0x00000002      /* TX FIFO is not full */
++#define SSPSR_RNE             0x00000004      /* RX FIFO is not empty */
++#define SSPSR_RFF             0x00000008      /* RX FIFO is full */
++#define SSPSR_BSY                     0x00000010      /* SSP is busy */
++
++/* Bits in SSPIIR */
++#define SSPIIR_RIS                    0x00000001      /* RX FIFO IRQ status */
++#define SSPIIR_TIS                    0x00000002      /* TX FIFO is not full */
++#define SSPIIR_RORIS          0x00000004      /* RX FIFO is full */
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/regs_syscon.h b/include/asm-arm/arch-ep93xx/regs_syscon.h
+new file mode 100644
+index 0000000..271cfcd
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_syscon.h
+@@ -0,0 +1,257 @@
++/*=============================================================================
++ *
++ *  FILE:             reg_syscon.h
++ *
++ *  DESCRIPTION:    ep93xx Syscon Register Definition
++ *
++ *  Copyright Cirrus Logic, 2001-2003
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *
++ *=============================================================================
++ */
++#ifndef _REGS_SYSCON_H_
++#define _REGS_SYSCON_H_
++
++#ifndef __ASSEMBLY__
++
++#define SysconSetLocked(registername,value)     \
++    {                                           \
++        writel( 0xAA, SYSCON_SWLOCK);             \
++        writel( value, registername);             \
++    }
++
++#endif                                /* Not __ASSEMBLY__ */
++
++/* SYSCON_CLKSET1 */
++#define SYSCON_CLKSET1_PLL1_X2IPD_SHIFT     0
++#define SYSCON_CLKSET1_PLL1_X2IPD_MASK      0x0000001f
++#define SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT    5
++#define SYSCON_CLKSET1_PLL1_X2FBD2_MASK     0x000007e0
++#define SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT    11
++#define SYSCON_CLKSET1_PLL1_X1FBD1_MASK     0x0000f800
++#define SYSCON_CLKSET1_PLL1_PS_SHIFT        16
++#define SYSCON_CLKSET1_PLL1_PS_MASK         0x00030000
++#define SYSCON_CLKSET1_PCLKDIV_SHIFT        18
++#define SYSCON_CLKSET1_PCLKDIV_MASK         0x000c0000
++#define SYSCON_CLKSET1_HCLKDIV_SHIFT        20
++#define SYSCON_CLKSET1_HCLKDIV_MASK         0x00700000
++#define SYSCON_CLKSET1_nBYP1                0x00800000
++#define SYSCON_CLKSET1_SMCROM               0x01000000
++#define SYSCON_CLKSET1_FCLKDIV_SHIFT        25
++#define SYSCON_CLKSET1_FCLKDIV_MASK         0x0e000000
++
++#define SYSCON_CLKSET1_HSEL                 0x00000001
++#define SYSCON_CLKSET1_PLL1_EXCLKSEL        0x00000002
++
++#define SYSCON_CLKSET1_PLL1_P_MASK          0x0000007C
++#define SYSCON_CLKSET1_PLL1_P_SHIFT         2
++
++#define SYSCON_CLKSET1_PLL1_M1_MASK         0x00000780
++#define SYSCON_CLKSET1_PLL1_M1_SHIFT        7
++#define SYSCON_CLKSET1_PLL1_M2_MASK         0x0000F800
++#define SYSCON_CLKSET1_PLL1_M2_SHIFT        11
++#define SYSCON_CLKSET1_PLL1_PS_MASK         0x00030000
++#define SYSCON_CLKSET1_PLL1_PS_SHIFT        16
++#define SYSCON_CLKSET1_PCLK_DIV_MASK        0x000C0000
++#define SYSCON_CLKSET1_PCLK_DIV_SHIFT       18
++#define SYSCON_CLKSET1_HCLK_DIV_MASK        0x00700000
++#define SYSCON_CLKSET1_HCLK_DIV_SHIFT       20
++#define SYSCON_CLKSET1_SMCROM               0x01000000
++#define SYSCON_CLKSET1_FCLK_DIV_MASK        0x0E000000
++#define SYSCON_CLKSET1_FCLK_DIV_SHIFT       25
++
++#define SYSCON_CLKSET2_PLL2_EN              0x00000001
++#define SYSCON_CLKSET2_PLL2EXCLKSEL         0x00000002
++#define SYSCON_CLKSET2_PLL2_P_MASK          0x0000007C
++#define SYSCON_CLKSET2_PLL2_P_SHIFT         2
++#define SYSCON_CLKSET2_PLL2_M2_MASK         0x00000F80
++#define SYSCON_CLKSET2_PLL2_M2_SHIFT        7
++#define SYSCON_CLKSET2_PLL2_M1_MASK         0x0001F000
++#define SYSCON_CLKSET2_PLL2_M1              12
++#define SYSCON_CLKSET2_PLL2_PS_MASK         0x000C0000
++#define SYSCON_CLKSET2_PLL2_PS_SHIFT        18
++#define SYSCON_CLKSET2_USBDIV_MASK          0xF0000000
++#define SYSCON_CLKSET2_USBDIV_SHIFT         28
++
++/* DEV_CFG Register Defines */
++#define SYSCON_DEVCFG_SHena            0x00000001
++#define SYSCON_DEVCFG_KEYS             0x00000002
++#define SYSCON_DEVCFG_ADCPD            0x00000004
++#define SYSCON_DEVCFG_RAS              0x00000008
++#define SYSCON_DEVCFG_RASonP3          0x00000010
++#define SYSCON_DEVCFG_TTIC             0x00000020
++#define SYSCON_DEVCFG_I2SonAC97        0x00000040
++#define SYSCON_DEVCFG_I2SonSSP         0x00000080
++#define SYSCON_DEVCFG_EonIDE           0x00000100
++#define SYSCON_DEVCFG_PonG             0x00000200
++#define SYSCON_DEVCFG_GonIDE           0x00000400
++#define SYSCON_DEVCFG_HonIDE           0x00000800
++#define SYSCON_DEVCFG_HC1CEN           0x00001000
++#define SYSCON_DEVCFG_HC1IN            0x00002000
++#define SYSCON_DEVCFG_HC3CEN           0x00004000
++#define SYSCON_DEVCFG_HC3IN            0x00008000
++#define SYSCON_DEVCFG_ADCEN            0x00010000
++#define SYSCON_DEVCFG_TIN              0x00020000
++#define SYSCON_DEVCFG_U1EN             0x00040000
++#define SYSCON_DEVCFG_EXVC             0x00080000
++#define SYSCON_DEVCFG_U2EN             0x00100000
++#define SYSCON_DEVCFG_A1onG            0x00200000
++#define SYSCON_DEVCFG_A2onG            0x00400000
++#define SYSCON_DEVCFG_CPENA            0x00800000
++#define SYSCON_DEVCFG_U3EN             0x01000000
++#define SYSCON_DEVCFG_MonG             0x02000000
++#define SYSCON_DEVCFG_TonG             0x04000000
++#define SYSCON_DEVCFG_GonK             0x08000000
++#define SYSCON_DEVCFG_IonU2            0x10000000
++#define SYSCON_DEVCFG_D0onG            0x20000000
++#define SYSCON_DEVCFG_D1onG            0x40000000
++#define SYSCON_DEVCFG_SWRST            0x80000000
++
++/* VIDDIV Register Defines */
++#define SYSCON_VIDDIV_VDIV_MASK         0x0000007f
++#define SYSCON_VIDDIV_VDIV_SHIFT        0
++#define SYSCON_VIDDIV_PDIV_MASK         0x00000300
++#define SYSCON_VIDDIV_PDIV_SHIFT        8
++#define SYSCON_VIDDIV_PSEL              0x00002000
++#define SYSCON_VIDDIV_ESEL              0x00004000
++#define SYSCON_VIDDIV_VENA              0x00008000
++
++/* MIRDIV Register Defines */
++#define SYSCON_MIRDIV_MDIV_MASK         0x0000003f
++#define SYSCON_MIRDIV_MDIV_SHIFT        0
++#define SYSCON_MIRDIV_PDIV_MASK         0x00000300
++#define SYSCON_MIRDIV_PDIV_SHIFT        8
++#define SYSCON_MIRDIV_PSEL              0x00002000
++#define SYSCON_MIRDIV_ESEL              0x00004000
++#define SYSCON_MIRDIV_MENA              0x00008000
++
++/* I2SDIV Register Defines */
++#define SYSCON_I2SDIV_MDIV_MASK         0x0000007f
++#define SYSCON_I2SDIV_MDIV_SHIFT        0
++#define SYSCON_I2SDIV_PDIV_MASK         0x00000300
++#define SYSCON_I2SDIV_PDIV_SHIFT        8
++#define SYSCON_I2SDIV_PSEL              0x00002000
++#define SYSCON_I2SDIV_ESEL              0x00004000
++#define SYSCON_I2SDIV_MENA              0x00008000
++#define SYSCON_I2SDIV_SDIV              0x00010000
++#define SYSCON_I2SDIV_LRDIV_MASK        0x00060000
++#define SYSCON_I2SDIV_LRDIV_SHIFT       17
++#define SYSCON_I2SDIV_SPOL              0x00080000
++#define SYSCON_I2SDIV_DROP              0x00100000
++#define SYSCON_I2SDIV_ORIDE             0x20000000
++#define SYSCON_I2SDIV_SLAVE             0x40000000
++#define SYSCON_I2SDIV_SENA              0x80000000
++
++#define SYSCON_I2SDIV_PDIV_OFF          0x00000000
++#define SYSCON_I2SDIV_PDIV_2            0x00000100
++#define SYSCON_I2SDIV_PDIV_25           0x00000200
++#define SYSCON_I2SDIV_PDIV_3            0x00000300
++
++#define SYSCON_I2SDIV_LRDIV_32          0x00000000
++#define SYSCON_I2SDIV_LRDIV_64          0x00020000
++#define SYSCON_I2SDIV_LRDIV_128         0x00040000
++
++/* KTDIV Register Defines */
++#define SYSCON_KTDIV_KDIV               0x00000001
++#define SYSCON_KTDIV_KEN                0x00008000
++#define SYSCON_KTDIV_ADIV               0x00010000
++#define SYSCON_KTDIV_TSEN               0x80000000
++
++/* CHIPID Register Defines */
++#define SYSCON_CHIPID_ID_MASK           0x0000ffff
++#define SYSCON_CHIPID_ID_SHIFT          0
++#define SYSCON_CHIPID_PKID              0x00010000
++#define SYSCON_CHIPID_BND               0x00040000
++#define SYSCON_CHIPID_FAB_MASK          0x0e000000
++#define SYSCON_CHIPID_FAB_SHIFT         25
++#define SYSCON_CHIPID_REV_MASK          0xf0000000
++#define SYSCON_CHIPID_REV_SHIFT         28
++
++/* TESTCR Register Defines */
++#define SYSCON_TESTCR_TMODE_MASK        0x000000ff
++#define SYSCON_TESTCR_TMODE_SHIFT       0
++#define SYSCON_TESTCR_BONDO             0x00000100
++#define SYSCON_TESTCR_PACKO             0x00000800
++#define SYSCON_TESTCR_ETOM              0x00002000
++#define SYSCON_TESTCR_TOM               0x00004000
++#define SYSCON_TESTCR_OVR               0x00008000
++#define SYSCON_TESTCR_TonIDE            0x00010000
++#define SYSCON_TESTCR_RonG              0x00020000
++
++/* SYSCFG Register Defines */
++#define SYSCON_SYSCFG_LCSn1             0x00000001
++#define SYSCON_SYSCFG_LCSn2             0x00000002
++#define SYSCON_SYSCFG_LCSn3             0x00000004
++#define SYSCON_SYSCFG_LEECK             0x00000008
++#define SYSCON_SYSCFG_LEEDA             0x00000010
++#define SYSCON_SYSCFG_LASDO             0x00000020
++#define SYSCON_SYSCFG_LCSn6             0x00000040
++#define SYSCON_SYSCFG_LCSn7             0x00000080
++#define SYSCON_SYSCFG_SBOOT             0x00000100
++#define SYSCON_SYSCFG_FAB_MASK          0x0e000000
++#define SYSCON_SYSCFG_FAB_SHIFT         25
++#define SYSCON_SYSCFG_REV_MASK          0xf0000000
++#define SYSCON_SYSCFG_REV_SHIFT         28
++
++/* PWRSR Register Defines */
++#define SYSCON_PWRSR_CHIPMAN_MASK       0xFF000000
++#define SYSCON_PWRSR_CHIPMAN_SHIFT      24
++#define SYSCON_PWRSR_CHIPID_MASK        0x00FF0000
++#define SYSCON_PWRSR_CHIPID_SHIFT       16
++#define SYSCON_PWRSR_WDTFLG             0x00008000
++#define SYSCON_PWRSR_CLDFLG             0x00002000
++#define SYSCON_PWRSR_TEST_RESET         0x00001000
++#define SYSCON_PWRSR_RSTFLG             0x00000800
++#define SYSCON_PWRSR_SWRESET            0x00000400
++#define SYSCON_PWRSR_PLL2_LOCKREG       0x00000200
++#define SYSCON_PWRSR_PLL2_LOCK          0x00000100
++#define SYSCON_PWRSR_PLL1_LOCKREG       0x00000080
++#define SYSCON_PWRSR_PLL1_LOCK          0x00000040
++#define SYSCON_PWRSR_RTCDIV             0x0000003F
++
++/* PWRCNT Register Defines */
++#define SYSCON_PWRCNT_FIREN             0x80000000
++#define SYSCON_PWRCNT_UARTBAUD          0x20000000
++#define SYSCON_PWRCNT_USHEN             0x10000000
++#define SYSCON_PWRCNT_DMA_M2MCH1        0x08000000
++#define SYSCON_PWRCNT_DMA_M2MCH0        0x04000000
++#define SYSCON_PWRCNT_DMA_M2PCH8        0x02000000
++#define SYSCON_PWRCNT_DMA_M2PCH9        0x01000000
++#define SYSCON_PWRCNT_DMA_M2PCH6        0x00800000
++#define SYSCON_PWRCNT_DMA_M2PCH7        0x00400000
++#define SYSCON_PWRCNT_DMA_M2PCH4        0x00200000
++#define SYSCON_PWRCNT_DMA_M2PCH5        0x00100000
++#define SYSCON_PWRCNT_DMA_M2PCH2        0x00080000
++#define SYSCON_PWRCNT_DMA_M2PCH3        0x00040000
++#define SYSCON_PWRCNT_DMA_M2PCH0        0x00020000
++#define SYSCON_PWRCNT_DMA_M2PCH1        0x00010000
++
++/* BMAR Register Defines */
++#define BMAR_PRIORD_00              0x00000000
++#define BMAR_PRIORD_01              0x00000001
++#define BMAR_PRIORD_02              0x00000002
++#define BMAR_PRIORD_03              0x00000003
++#define BMAR_PRI_CORE               0x00000008
++#define BMAR_DMA_ENIRQ              0x00000010
++#define BMAR_DMA_ENFIQ              0x00000020
++#define BMAR_USB_ENIRQ              0x00000040
++#define BMAR_USB_ENFIQ              0x00000080
++#define BMAR_MAC_ENIRQ              0x00000100
++#define BMAR_MAC_ENFIQ              0x00000200
++#define BMAR_GRAPHICS_ENIRQ         0x00000400
++#define BMAR_GRAPHICS_ENFIQ         0x00000800
++
++#endif                                /* _REGS_SYSCON_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_touch.h b/include/asm-arm/arch-ep93xx/regs_touch.h
+new file mode 100644
+index 0000000..aad8a99
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_touch.h
+@@ -0,0 +1,94 @@
++/*=============================================================================
++ *
++ *  FILE:       regs_touch.h
++ *
++ *  DESCRIPTION:    Analog Touchscreen Register Definition
++ *
++ *  Copyright Cirrus Logic, 2001-2003
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ *=============================================================================
++ */
++#ifndef _REGS_TOUCH_H_
++#define _REGS_TOUCH_H_
++
++/*
++ *-----------------------------------------------------------------------------
++ * Individual bit #defines
++ *-----------------------------------------------------------------------------
++ */
++#define TSSETUP_SDLY_MASK           0x000003FF
++#define TSSETUP_SDLY_SHIFT          0
++#define TSSETUP_NSMP_4              0x00000000
++#define TSSETUP_NSMP_8              0x00000400
++#define TSSETUP_NSMP_16             0x00000800
++#define TSSETUP_NSMP_32             0x00000C00
++#define TSSETUP_NSMP_MASK           0x00000C00
++#define TSSETUP_DEV_4               0x00000000
++#define TSSETUP_DEV_8               0x00001000
++#define TSSETUP_DEV_12              0x00002000
++#define TSSETUP_DEV_16              0x00003000
++#define TSSETUP_DEV_24              0x00004000
++#define TSSETUP_DEV_32              0x00005000
++#define TSSETUP_DEV_64              0x00006000
++#define TSSETUP_DEV_128             0x00007000
++#define TSSETUP_ENABLE              0x00008000
++#define TSSETUP_DLY_MASK            0x03FF0000
++#define TSSETUP_DLY_SHIFT           16
++#define TSSETUP_TDTCT               0x80000000
++
++#define TSMAXMIN_XMIN_MASK          0x000000FF
++#define TSMAXMIN_XMIN_SHIFT         0
++#define TSMAXMIN_YMIN_MASK          0x0000FF00
++#define TSMAXMIN_YMIN_SHIFT         8
++#define TSMAXMIN_XMAX_MASK          0x00FF0000
++#define TSMAXMIN_XMAX_SHIFT         16
++#define TSMAXMIN_YMAX_MASK          0xFF000000
++#define TSMAXMIN_YMAX_SHIFT         24
++
++#define TSXYRESULT_X_MASK           0x00000FFF
++#define TSXYRESULT_X_SHIFT          0
++#define TSXYRESULT_AD_MASK          0x0000FFFF
++#define TSXYRESULT_AD_SHIFT         0
++#define TSXYRESULT_Y_MASK           0x0FFF0000
++#define TSXYRESULT_Y_SHIFT          16
++#define TSXYRESULT_SDR              0x80000000
++
++#define TSX_SAMPLE_MASK             0x00003FFF
++#define TSX_SAMPLE_SHIFT            0x00
++#define TSY_SAMPLE_MASK             0x3FFF0000
++#define TSY_SAMPLE_SHIFT            0x10
++
++#define TSSETUP2_TINT               0x00000001
++#define TSSETUP2_NICOR              0x00000002
++#define TSSETUP2_PINT               0x00000004
++#define TSSETUP2_PENSTS             0x00000008
++#define TSSETUP2_PINTEN             0x00000010
++#define TSSETUP2_DEVINT             0x00000020
++#define TSSETUP2_DINTEN             0x00000040
++#define TSSETUP2_DTMEN              0x00000080
++#define TSSETUP2_DISDEV             0x00000100
++#define TSSETUP2_NSIGND             0x00000200
++#define TSSETUP2_S28EN              0x00000400
++#define TSSETUP2_RINTEN             0x00000800
++
++#define TSXYRESULT_SDR                        0x80000000
++
++/*
++ *-----------------------------------------------------------------------------
++ *-----------------------------------------------------------------------------
++ */
++
++#endif                                /* _REGS_TOUCH_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_uart.h b/include/asm-arm/arch-ep93xx/regs_uart.h
+new file mode 100644
+index 0000000..cfadf4a
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_uart.h
+@@ -0,0 +1,84 @@
++/*
++ *  File:   linux/include/asm-arm/arch-ep93xx/regs_uart.h
++ *
++ *  Copyright (C) 2003 Cirrus Logic, 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.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#ifndef _REGS_UART_H_
++#define _REGS_UART_H_
++
++/* Bits in UARTRSR */
++#define UARTRSR_FE              0x00000001    /* Framing error */
++#define UARTRSR_PE              0x00000002    /* Parity error */
++#define UARTRSR_BE              0x00000004    /* Break error */
++#define UARTRSR_OE              0x00000008    /* Overrun error */
++
++/* Bits in UARTCR - UART1CR, UART2CR, or UART3CR */
++#define UARTLCR_H_BRK           0x00000001
++#define UARTLCR_H_PEN           0x00000002
++#define UARTLCR_H_EPS           0x00000004
++#define UARTLCR_H_STP2          0x00000008
++#define UARTLCR_H_FEN           0x00000010
++#define UARTLCR_H_WLEN          0x00000060
++#define UARTLCR_H_WLEN_8_DATA   0x00000060
++#define UARTLCR_H_WLEN_7_DATA   0x00000040
++#define UARTLCR_H_WLEN_6_DATA   0x00000020
++#define UARTLCR_H_WLEN_5_DATA   0x00000000
++
++/* Bits in UARTFR - UART1FR, UART2FR, or UART3FR */
++#define UARTFR_RSR_ERRORS       0x0000000F
++#define UARTFR_CTS              0x00000001
++#define UARTFR_DSR              0x00000002
++#define UARTFR_DCD              0x00000004
++#define UARTFR_BUSY             0x00000008
++#define UARTFR_RXFE             0x00000010
++#define UARTFR_TXFF             0x00000020
++#define UARTFR_RXFF             0x00000040
++#define UARTFR_TXFE             0x00000080
++
++/* Bits in UARTIIR */
++#define UARTIIR_MIS             0x00000001
++#define UARTIIR_RIS             0x00000002
++#define UARTIIR_TIS             0x00000004
++#define UARTIIR_RTIS            0x00000008
++
++/* Bits in UARTCR */
++#define UARTCR_UARTE            0x00000001
++#define UARTCR_MSIE             0x00000008
++#define UARTCR_RIE              0x00000010
++#define UARTCR_TIE              0x00000020
++#define UARTCR_RTIE             0x00000040
++#define UARTCR_LBE              0x00000080
++
++/* Bits in UARTMCR */
++#define UARTMCR_DTR             0x00000001
++#define UARTMCR_RTS             0x00000002
++#define UARTMCR_OUT1            0x00000004
++#define UARTMCR_OUT2            0x00000008
++#define UARTMCR_LOOP            0x00000010
++
++/* Bits in UARTMSR */
++#define UARTMSR_DCTS            0x00000001
++#define UARTMSR_DDSR            0x00000002
++#define UARTMSR_TERI            0x00000004
++#define UARTMSR_DDCD            0x00000008
++#define UARTMSR_CTS             0x00000010
++#define UARTMSR_DSR             0x00000020
++#define UARTMSR_RI              0x00000040
++#define UARTMSR_DCD             0x00000080
++
++#endif                                /* _REGS_UART_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/serial.h b/include/asm-arm/arch-ep93xx/serial.h
+new file mode 100644
+index 0000000..06ab737
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/serial.h
+@@ -0,0 +1,49 @@
++/*
++ *  linux/include/asm-arm/arch-integrator/serial.h
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __ASM_ARCH_SERIAL_H
++#define __ASM_ARCH_SERIAL_H
++
++#include <asm/arch/platform.h>
++#include <asm/irq.h>
++
++/*
++ * This assumes you have a 1.8432 MHz clock for your UART.
++ *
++ * It'd be nice if someone built a serial card with a 24.576 MHz
++ * clock, since the 16550A is capable of handling a top speed of 1.5
++ * megabits/second; but this requires the faster clock.
++ */
++#define BASE_BAUD (1843200 / 16)
++
++#define _SER_IRQ0     IRQ_UARTINT0
++#define _SER_IRQ1     IRQ_UARTINT1
++
++#define RS_TABLE_SIZE 2
++
++#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
++
++     /* UART CLK        PORT  IRQ     FLAGS        */
++#define STD_SERIAL_PORT_DEFNS \
++      { 0, BASE_BAUD, 0x3F8, _SER_IRQ0, STD_COM_FLAGS },      /* ttyS0 */     \
++      { 0, BASE_BAUD, 0x2F8, _SER_IRQ1, STD_COM_FLAGS },      /* ttyS1 */
++
++#define EXTRA_SERIAL_PORT_DEFNS
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/ssp-cirrus.h b/include/asm-arm/arch-ep93xx/ssp-cirrus.h
+new file mode 100644
+index 0000000..e29dc9d
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/ssp-cirrus.h
+@@ -0,0 +1,30 @@
++/*
++ *
++ *  FILE:           ssp.h
++ *
++ *  DESCRIPTION:    SSP Interface Driver Module implementation
++ *
++ *  Copyright Cirrus Logic Corporation, 2001-2003.  All rights reserved
++ *
++ */
++#ifndef _SSP_DRV_H_
++#define _SSP_DRV_H_
++
++enum SSPDeviceType {
++      PS2_KEYBOARD = 0,
++      I2S_CODEC = 1,
++      SERIAL_FLASH = 2
++};
++
++typedef void (*SSPDataCallback) (unsigned int Data);
++
++typedef struct _SSP_DRIVER_API {
++      int (*Open) (enum SSPDeviceType Device, SSPDataCallback Callback);
++      int (*Read) (int Handle, unsigned int Addr, unsigned int *pValue);
++      int (*Write) (int Handle, unsigned int Addr, unsigned int Value);
++      int (*Close) (int Handle);
++} SSP_DRIVER_API;
++
++extern SSP_DRIVER_API *SSPDriver;
++
++#endif                                /* _SSP_DRV_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/ssp.h b/include/asm-arm/arch-ep93xx/ssp.h
+new file mode 100644
+index 0000000..9102233
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/ssp.h
+@@ -0,0 +1,121 @@
++/*
++ *  ssp.h
++ *
++ *  Copyright (C) 2004 Ray Lehtiniemi, All Rights Reserved.
++ *  Copyright (C) 2004 Siconix, Inc., All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef SSP_H
++#define SSP_H
++
++#include <linux/list.h>
++#include <linux/completion.h>
++#include <asm/semaphore.h>
++
++struct ssp_master_ops;
++struct ssp_slave;
++
++struct ssp_transfer {
++
++      /* how many _bytes_ per unit of data */
++      int size;
++
++      /* how many units of data left to be clocked out */
++      int len;
++
++      /* how many units of data left to be clocked in */
++      int rlen;
++
++      /* buffer of units to shift out to slave */
++      void *tx;
++
++      /* buffer to hold units shifted in from slave */
++      void *rx;
++
++      /* signaled when complete */
++      struct completion *c;
++};
++
++struct ssp_master {
++
++      /* serialize access to the frontend */
++      struct semaphore sem;
++
++      /* synchronize the frontend and the backend */
++      struct completion completion;
++
++      /* the slave devices on this master */
++      struct list_head slave;
++
++      /* the active transfer on the bus  */
++      struct ssp_transfer transfer;
++
++      /* methods for different master controllers */
++      struct ssp_master_ops *ops;
++};
++
++struct ssp_master_ops {
++
++      /* configure the master for accessing a particular slave */
++      int (*configure) (struct ssp_slave *);
++
++      /* enable the backend to start the transfer */
++      int (*enable) (struct ssp_transfer *);
++
++      /* disable the backend to stop the transfer */
++      int (*disable) (void);
++};
++
++struct ssp_slave {
++
++      /* our link in the masters list of slaves */
++      struct list_head list;
++
++      /* our master */
++      struct ssp_master *master;
++#if 0
++      /* the upper level protocol spoken by the device */
++      struct ssp_protocol *protocol;
++#endif
++      /* the phase and polarity modes we support */
++      unsigned long supported_modes;
++
++      /* our maximum clock rate, in Hz */
++      unsigned long max_clock_rate;
++
++      /* our data unit size, in bits */
++      int word_size;
++
++      /* our data unit size, in bytes */
++      int nbytes;
++
++      /* assert or negate the chip select line for this device */
++      void (*chip_select) (struct ssp_slave *, int);
++};
++
++/* manage the master-slave list */
++extern int ssp_add_slave(struct ssp_master *, struct ssp_slave *);
++extern void ssp_remove_slave(struct ssp_master *, struct ssp_slave *);
++
++/* perform a single transaction */
++extern int ssp_do(struct ssp_slave *s, int len, void *tx, void *rx);
++
++/* perform each step of a transaction */
++extern int ssp_start(struct ssp_slave *s);    /* grab master, blocking */
++extern int ssp_trystart(struct ssp_slave *s); /* grab master, non-blocking */
++extern void ssp_select(struct ssp_slave *s);  /* assert CS */
++extern int ssp_post(struct ssp_slave *s, int len, void *tx, void *rx);        /* start a transfer */
++extern int ssp_wait(struct ssp_slave *s);     /* wait for completion */
++                                                     /*extern int  ssp_disable (struct ssp_slave *s);    *//* stop a transfer */
++extern void ssp_deselect(struct ssp_slave *s);        /* negate CS */
++extern void ssp_finish(struct ssp_slave *s);  /* release master */
++
++/* module stuff */
++extern int ssp_init(void);
++extern void ssp_exit(void);
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/ssp2.h b/include/asm-arm/arch-ep93xx/ssp2.h
+new file mode 100644
+index 0000000..93823a0
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/ssp2.h
+@@ -0,0 +1,29 @@
++/*
++ *  ssp.h
++ *
++ *  Copyright (C) 2004 Ray Lehtiniemi, All Rights Reserved.
++ *  Copyright (C) 2004 Siconix, Inc., All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef SSP2_H
++#define SSP2_H
++
++#include <asm/arch/ssp.h>
++
++struct ep93xx_ssp_slave {
++      struct ssp_slave slave;
++      unsigned long cr0;
++      unsigned long cr1;
++      unsigned long cpsr;
++};
++
++extern struct ssp_master ep93xx_ssp_master;
++
++extern int ep93xx_ssp_init(void);
++extern void ep93xx_ssp_exit(void);
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/system.h b/include/asm-arm/arch-ep93xx/system.h
+new file mode 100644
+index 0000000..1030210
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/system.h
+@@ -0,0 +1,68 @@
++/*
++ *  linux/include/asm-arm/arch-ep93xx/system.h
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *  Copyright (C) 2000 Deep Blue Solutions Ltd
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef __ASM_ARCH_SYSTEM_H
++#define __ASM_ARCH_SYSTEM_H
++
++#include <asm/arch/platform.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++
++static void arch_idle(void)
++{
++      unsigned long val = readl(SYSCON_DEVCFG);
++      val = ep93xx_SYSCON_DEVCFG(val | SYSCON_DEVCFG_SHena);
++      SysconSetLocked(SYSCON_DEVCFG, val);
++      readl(SYSCON_HALT);
++}
++
++#if defined(CONFIG_MACH_TTML)
++
++#include <asm/arch/mach-ttml.h>
++extern __inline__ void arch_reset(char mode)
++{
++      /* reboot using micro */
++      unsigned char msg[4] = { 0xaa, 0x90, 0xa0, 0x65 };
++      unsigned char reply[10];
++      (void)ssp_do_ttml(&ep93xx_ssp_micro, msg, 4, reply, 10);
++      while (1) ;
++}
++
++#else
++
++extern __inline__ void arch_reset(char mode)
++{
++#if 1
++      /* reboot using SW_RESET bit in devcfg register */
++      unsigned long val = readl(SYSCON_DEVCFG);
++      SysconSetLocked(SYSCON_DEVCFG,
++                      ep93xx_SYSCON_DEVCFG(val | SYSCON_DEVCFG_SWRST));
++      SysconSetLocked(SYSCON_DEVCFG,
++                      ep93xx_SYSCON_DEVCFG(val & ~SYSCON_DEVCFG_SWRST));
++
++#else
++      /* reboot using 0.250 second onboard watchdog timeout */
++      writel(0xaaaa, WATCHDOG);
++      while (1) ;
++#endif
++}
++#endif
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/timex.h b/include/asm-arm/arch-ep93xx/timex.h
+new file mode 100644
+index 0000000..87a7628
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/timex.h
+@@ -0,0 +1,26 @@
++/*
++ *  linux/include/asm-arm/arch-integrator/timex.h
++ *
++ *  Integrator architecture timex specifications
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/*
++ * ??
++ */
++#define CLOCK_TICK_RATE               (50000000 / 16)
+diff --git a/include/asm-arm/arch-ep93xx/uncompress.h b/include/asm-arm/arch-ep93xx/uncompress.h
+new file mode 100644
+index 0000000..f76de3c
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/uncompress.h
+@@ -0,0 +1,91 @@
++/*
++ *  linux/include/asm-arm/arch-ep93xx/uncompress.h
++ *
++ *  Copyright (C) 1999 ARM Limited
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++#include <asm/io.h>
++#include <asm/hardware.h>
++
++#if defined(CONFIG_MACH_ZEFEERDZA) || defined(CONFIG_MACH_ZEFEERDZB) || \
++    defined(CONFIG_MACH_ZEFEERDZG) || defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ)
++#     define BAUDRATE ((EP93XX_UART_CLK/(16 * 115200)) - 1)
++#else
++#     define BAUDRATE ((EP93XX_UART_CLK/(16 * 57600)) - 1)
++#endif
++
++#define HW_PREG(reg) ((unsigned int volatile *)(io_v2p(reg)))
++
++static void putstr(const char *s)
++{
++      while (*s) {
++              while (*HW_PREG(UART1FR) & UARTFR_TXFF) ;
++
++              *HW_PREG(UART1DR) = *s;
++
++              if (*s == '\n') {
++                      while (*HW_PREG(UART1FR) & UARTFR_TXFF) ;
++
++                      *HW_PREG(UART1DR) = '\r';
++              }
++              s++;
++      }
++      while (*HW_PREG(UART1FR) & UARTFR_BUSY) ;
++}
++
++static void EnableUart(void)
++{
++      /*
++       * Ensure that the base clock to the UARTS is 14.7456Mhz
++       * and that UART1 is enabled.
++       */
++      *HW_PREG(SYSCON_PWRCNT) = SYSCON_PWRCNT_UARTBAUD;
++
++      *HW_PREG(SYSCON_SWLOCK) = 0xaa;
++      *HW_PREG(SYSCON_DEVCFG) = (*HW_PREG(SYSCON_DEVCFG)) | SYSCON_DEVCFG_U1EN;
++
++      /* Disable the UARTS and clear out the old settings. */
++      *HW_PREG(UART1MCR) = 0;
++      *HW_PREG(UART1CR) = 0;
++      *HW_PREG(UART1RSR) = 0;
++      *HW_PREG(UART1CR_L) = 0;
++      *HW_PREG(UART1CR_M) = 0;
++      *HW_PREG(UART1CR_H) = 0;
++
++      /* Set the baud rate and framing */
++      *HW_PREG(UART1CR_L) = (BAUDRATE & 0x0FF);
++      *HW_PREG(UART1CR_M) = ((BAUDRATE >> 8) & 0x0FF);
++
++      /* 8 Data bits, No Parity, 1 Stop bit. */
++      *HW_PREG(UART1CR_H) = (UARTLCR_H_WLEN_8_DATA | UARTLCR_H_FEN);
++
++      /* Enable Uart */
++      *HW_PREG(UART1CR) = UARTCR_UARTE;
++}
++
++#if defined(CONFIG_MACH_ADSSPHERE)
++#define arch_decomp_setup()
++#else
++
++/* Called early before the UART is used for output by the compressed loader. */
++static void arch_decomp_setup(void)
++{
++      EnableUart();
++}
++#endif
++
++#define arch_decomp_wdog()
+diff --git a/include/asm-arm/arch-ep93xx/vmalloc.h b/include/asm-arm/arch-ep93xx/vmalloc.h
+new file mode 100644
+index 0000000..ec8f98d
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/vmalloc.h
+@@ -0,0 +1,32 @@
++/*
++ *  linux/include/asm-arm/arch-integrator/vmalloc.h
++ *
++ *  Copyright (C) 2000 Russell King.
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++
++/*
++ * Just any arbitrary offset to the start of the vmalloc VM area: the
++ * current 8MB value just means that there will be a 8MB "hole" after the
++ * physical memory until the kernel virtual memory starts.  That means that
++ * any out-of-bounds memory accesses will hopefully be caught.
++ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
++ * area for the same reason. ;)
++ */
++#define VMALLOC_OFFSET          (8*1024*1024)
++#define VMALLOC_START   (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
++#define VMALLOC_VMADDR(x) ((unsigned long)(x))
++#define VMALLOC_END       (PAGE_OFFSET + 0x10000000)
+diff --git a/include/asm-arm/arch-ep93xx/zefeerevb.h b/include/asm-arm/arch-ep93xx/zefeerevb.h
+new file mode 100644
+index 0000000..2cb3f84
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/zefeerevb.h
+@@ -0,0 +1,51 @@
++/*
++ *  linux/include/asm-arm/arch-ep93xx/platform.h
++ *
++ *  Copyright (C) 2004 DAVE Srl <www.dave-tech.it>
++ *
++ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
++ */
++#ifndef ASM_ARCH_ZEFEEREVB_H
++#define ASM_ARCH_ZEFEEREVB_H
++
++#ifdef CONFIG_MACH_ZEFEER_EVBL_107
++/* GPIO pins used to drive NAND chip mounted on old EVB */
++/*
++      nCE = EGPIO2
++      CLE = EGPIO0
++      ALE = EGPIO1
++      R/B = EGPIO3
++*/
++#     define NAND_EVB_nCE_GPIO_PIN    (1 << 2)
++#     define NAND_EVB_CLE_GPIO_PIN    (1 << 0)
++#     define NAND_EVB_ALE_GPIO_PIN    (1 << 1)
++#     define NAND_EVB_RB_GPIO_PIN     (1 << 3)
++#else
++/* GPIO pins used to drive NAND chip mounted on EVB */
++/*
++      nCE = EGPIO6
++      CLE = EGPIO4
++      ALE = EGPIO5
++      R/B = EGPIO7
++*/
++#     define NAND_EVB_nCE_GPIO_PIN    (1 << 6)
++#     define NAND_EVB_CLE_GPIO_PIN    (1 << 4)
++#     define NAND_EVB_ALE_GPIO_PIN    (1 << 5)
++#     define NAND_EVB_RB_GPIO_PIN     (1 << 7)
++#endif
++
++#define ZEFEEREVB_NAND_PADDR  0x20000000
++
++#endif /* ASM_ARCH_ZEFEEREVB_H */
+diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h
+index 59975ee..755d9de 100644
+--- a/include/asm-arm/irq.h
++++ b/include/asm-arm/irq.h
+@@ -38,6 +38,12 @@ extern void enable_irq(unsigned int);
+ #define IRQT_HIGH     (__IRQT_HIGHLVL)
+ #define IRQT_PROBE    (1 << 4)
++/*
++ * Flags for enable and disable debounce
++ */
++#define IRQT_DB       ( 1 << 5 )
++#define IRQT_NOTDB    ( 1 << 6 )
++
+ int set_irq_type(unsigned int irq, unsigned int type);
+ void disable_irq_wake(unsigned int irq);
+ void enable_irq_wake(unsigned int irq);
+diff --git a/include/asm-arm/procinfo.h b/include/asm-arm/procinfo.h
+index a9c75b2..556e5d8 100644
+--- a/include/asm-arm/procinfo.h
++++ b/include/asm-arm/procinfo.h
+@@ -56,5 +56,6 @@ extern unsigned int elf_hwcap;
+ #define HWCAP_VFP     64
+ #define HWCAP_EDSP    128
+ #define HWCAP_JAVA    256
++#define       HWCAP_CRUNCH    512
+ #endif
+diff --git a/include/linux/can/oki_ml9620_ctrl.h b/include/linux/can/oki_ml9620_ctrl.h
+new file mode 100644
+index 0000000..d2cfbea
+--- /dev/null
++++ b/include/linux/can/oki_ml9620_ctrl.h
+@@ -0,0 +1,54 @@
++/*
++ * include/linux/can/oki_ml9620_ctrl.h
++ *
++ * OKI ML9620 CAN Controler driver
++ *
++ * Author: Manfred Gruber <manfred.gruber@contec.at>
++ *
++ * Copyright 2004 (c) Manfred Gruber
++ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H
++ * Kufstein/Austria   www.contec.at
++ *
++ * This driver was written for Contec hypercontrol Micro9 Board
++ * 1. CAN Controller is on Hypercontrol Micro9 CPU board
++ * 2. CAN Controller is on Hypercontrol Micro9 eval board
++ *
++ * This file is licensed under  the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef _OKI_ML9620_CTRL_H_
++#define _OKI_ML9620_CTRL_H_
++
++#ifdef __KERNEL__
++struct can_msg {
++      unsigned short id;      /* identifier                          */
++      unsigned short dlc : 4; /* bitfield 4: data length code [0..8] */
++      unsigned short rtr : 1; /* bitfield 1: rtr bit                 */
++      unsigned short ext : 1; /* bitfield 1: extended ID             */
++      unsigned short pad : 10; /* workaround alignment issues: 
++                              FIXME: completely remove that bitfield junk */
++      unsigned char  data[8]; /* data bytes                          */
++};
++#endif
++
++#define CAN_STS_CNTRL_OFF   0       /*!< set CAN controller off         */
++#define CAN_STS_CNTRL_ON    1       /*!< set CAN controller on          */
++#define CAN_STS_CNTRL_SLEEP 2       /*!< set CAN controller sleep mode  */
++#define CAN_STS_CNTRL_AWAKE 3       /*!< set CAN controller wake up     */
++#define CAN_STS_NORMAL      0x00    /*!< CAN controller status normal   */
++#define CAN_STS_RESET       0x01    /*!< CAN controller status reset    */
++#define CAN_STS_WARNING     0x02    /*!< CAN controller status warning  */
++#define CAN_STS_BUS_OFF     0x04    /*!< CAN controller status bus off  */
++#define CAN_STS_SLEEPING    0x08    /*!< CAN controller status sleeping */
++#define CAN_STS_OVERRUN     0x10    /*!< CAN controller status overrun  */
++#define CAN_STS_TXOK        0x20    /*!< CAN message transmitted        */
++
++#define COMMAND                       0
++#define CONFIG                        1
++#define SEND                  2
++#define RECEIVE                       3
++#define STATUS                        4
++
++#endif
+diff --git a/include/linux/input.h b/include/linux/input.h
+index 3c58233..8ea2247 100644
+--- a/include/linux/input.h
++++ b/include/linux/input.h
+@@ -414,6 +414,7 @@ struct input_absinfo {
+ #define BTN_STYLUS2           0x14c
+ #define BTN_TOOL_DOUBLETAP    0x14d
+ #define BTN_TOOL_TRIPLETAP    0x14e
++#define BTN_RAW                       0x14f
+ #define BTN_WHEEL             0x150
+ #define BTN_GEAR_DOWN         0x150
+diff --git a/include/linux/irda.h b/include/linux/irda.h
+index 95dee17..3172c96 100644
+--- a/include/linux/irda.h
++++ b/include/linux/irda.h
+@@ -76,6 +76,7 @@ typedef enum {
+       IRDA_MCP2120_DONGLE      = 9,
+       IRDA_ACT200L_DONGLE      = 10,
+       IRDA_MA600_DONGLE        = 11,
++      IRDA_EP93XX_SIR          = 12,
+ } IRDA_DONGLE;
+ /* Protocol types to be used for SOCK_DGRAM */
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index b0ad6f3..2ee1652 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -883,6 +883,11 @@ extern void __put_task_struct(struct tas
+ #define put_task_struct(tsk) \
+ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
++#ifdef        CONFIG_EP93XX_CRUNCH
++#define       PF_USEDCRUNCH   0x00200000      /* introduced to preserve PF_USEDFPU
++                                         meaning across the architecture */
++#endif
++
+ /*
+  * Per process flags
+  */
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index e3710d7..a1c9b53 100644
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -124,6 +124,9 @@
+ /* Hilscher netx */
+ #define PORT_NETX     71
++/* Cirrus EP93xx family */
++#define PORT_EP93XX   65
++
+ #ifdef __KERNEL__
+ #include <linux/config.h>
+diff --git a/include/linux/ttml.h b/include/linux/ttml.h
+new file mode 100644
+index 0000000..2b0e327
+--- /dev/null
++++ b/include/linux/ttml.h
+@@ -0,0 +1,61 @@
++/*
++ * include/linux/ttml.h
++ *
++ * TTML TripDawg system devices.
++ *
++ * Copyright 2004, Ray Lehtiniemi
++ * Copyright 2004, Siconix, Inc
++ */
++
++#ifndef __TTML_H
++#define __TTML_H
++
++#define TTML_MAJOR         MISC_MAJOR
++
++#define TTML_MINOR_LED     240
++#define TTML_MINOR_BUZZER  241
++#define TTML_MINOR_SPEEDO  242
++#define TTML_MINOR_GPIO    243
++#define TTML_MINOR_BUTTON  244
++#define TTML_MINOR_WD      245
++
++#define MAX_TTML_MINORS 6
++
++struct ttml_ioctl_led {
++      int blue;
++      int red;
++      int yellow;
++};
++
++struct ttml_ioctl_buzzer {
++      int buzzer1;
++};
++
++struct ttml_ioctl_speedo {
++      int instant;
++      int average;
++};
++
++struct ttml_ioctl_gpio {
++      int pto;
++      int ignition;
++      int spare;
++};
++
++struct ttml_ioctl_button {
++      int button1;
++      int portf;
++};
++
++#define TTML_IOCTL 't'
++
++#define TTML_GET_LED      _IOR(TTML_IOCTL, 0, struct ttml_ioctl_led)
++#define TTML_GET_BUZZER   _IOR(TTML_IOCTL, 1, struct ttml_ioctl_buzzer)
++#define TTML_GET_SPEEDO   _IOR(TTML_IOCTL, 2, struct ttml_ioctl_speedo)
++#define TTML_GET_GPIO     _IOR(TTML_IOCTL, 3, struct ttml_ioctl_gpio)
++#define TTML_GET_BUTTON   _IOR(TTML_IOCTL, 4, struct ttml_ioctl_button)
++
++#define TTML_SET_LED      _IOW(TTML_IOCTL, 16, struct ttml_ioctl_led)
++#define TTML_SET_BUZZER   _IOW(TTML_IOCTL, 17, struct ttml_ioctl_buzzer)
++
++#endif
+diff --git a/include/net/irda/ep93xx_irda.h b/include/net/irda/ep93xx_irda.h
+new file mode 100644
+index 0000000..0ee919d
+--- /dev/null
++++ b/include/net/irda/ep93xx_irda.h
+@@ -0,0 +1,261 @@
++ /*********************************************************************
++ *
++ * Filename:      ep93xx_irda.h
++ * Version:       0.2
++ * Description:   Header for the EP93xx SOC IrDA driver.
++ * Status:        Experimental.
++ *
++ * Copyright 2003 Cirrus Logic, Inc.
++ *
++ * Based on the ali-ircc.c implementation:
++ *      Author:        Benjamin Kong <benjamin_kong@ali.com.tw>
++ *      Created at:    2000/10/16 03:46PM
++ *      Modified at:   2001/1/3 02:55PM
++ *      Modified by:   Benjamin Kong <benjamin_kong@ali.com.tw>
++ *
++ *      Copyright (c) 2000 Benjamin Kong <benjamin_kong@ali.com.tw>
++ *      All Rights Reserved
++ *
++ *      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 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:
++ *      Free Software Foundation, Inc.
++ *      59 Temple Place, Suite 330
++ *      Boston, MA  02111-1307  USA
++ ********************************************************************/
++
++#ifndef EP93XX_IRDA_H
++#define EP93XX_IRDA_H
++
++#include <linux/time.h>
++
++#include <linux/spinlock.h>
++#include <linux/pm.h>
++#include <asm/io.h>
++
++/*
++ * Number of DMA channels used
++ */
++#define DMA_COUNT 3
++
++/*
++ * TX/RX window queues
++ */
++#define MAX_TX_WINDOW 7
++#define MAX_RX_WINDOW 7
++
++struct ep93xx_chip {
++      char *name;
++      int iSIR_IRQ, iMFIR_IRQ;
++      ep93xx_dma_dev_t eSIR_DMATx;
++      ep93xx_dma_dev_t eMFIR_DMATx;
++      ep93xx_dma_dev_t eMFIR_DMARx;
++      int (*init) (struct ep93xx_chip * chip);
++};
++
++/* For storing entries in the status FIFO */
++
++struct st_fifo_entry {
++      int status;
++      int len;
++};
++
++struct st_fifo {
++      struct st_fifo_entry entries[MAX_RX_WINDOW];
++      int pending_bytes;
++      int head;
++      int tail;
++      int len;
++};
++
++struct frame_cb {
++      void *start;            /* Start of frame in DMA mem */
++      int len;                /* Lenght of frame in DMA mem */
++};
++
++struct tx_fifo {
++      struct frame_cb queue[MAX_TX_WINDOW];   /* Info about frames in queue */
++      int ptr;                /* Currently being sent */
++      int len;                /* Length of queue */
++      int free;               /* Next free slot */
++      void *tail;             /* Next free start in DMA mem */
++};
++
++/* Private data for each instance */
++struct ep93xx_irda_cb {
++      struct st_fifo st_fifo; /* Info about received frames */
++      struct tx_fifo tx_fifo; /* Info about frames to be transmitted */
++
++      struct net_device *netdev;      /* Net device pointer */
++      struct net_device_stats stats;  /* Net device stats */
++
++      struct irlap_cb *irlap; /* The link layer we are binded with */
++      struct qos_info qos;    /* QoS capabilities for this device */
++
++      int iSIR_irq, iMFIR_irq;        /* Interrupts used */
++
++      ep93xx_dma_dev_t ePorts[DMA_COUNT];     /* DMA port ids */
++
++      int iDMAh[DMA_COUNT];   /* handles for DMA channels */
++      dma_addr_t rx_dmaphysh, tx_dmaphysh;
++
++      int fifo_size;          /* FIFO size */
++      iobuff_t tx_buff;       /* Transmit buffer */
++      iobuff_t rx_buff;       /* Receive buffer */
++
++      char *conv_buf;         /* Buffer used for SIR conversion */
++
++      struct timeval stamp;   /* ? */
++      struct timeval now;     /* ? */
++
++      spinlock_t lock;        /* Used for serializing operations */
++
++      __u32 flags;            /* Interface flags */
++
++      __u8 direction;         /* TX/RX flag */
++
++      __u32 speed;            /* Currently used speed */
++      __u32 new_speed;        /* New target tx/rx speed */
++
++      int index;              /* Instance index */
++
++      int suspended;          /* APM suspend flag */
++      struct pm_dev *dev;     /* Power Management device */
++
++};
++
++/*
++ * DMA array handle index meanings
++ */
++#define DMA_SIR_TX                          0
++#define DMA_MFIR_TX                         1
++#define DMA_MFIR_RX                         2
++
++/*
++ * Directional defines
++ */
++#define DIR_TX                              0x01
++#define DIR_RX                              0x02
++#define DIR_BOTH                            0x03
++
++/*
++ * Modes support flag defines.
++ */
++#define CLK_SIR                                   0x01
++#define CLK_MIR                                   0x02
++#define CLK_FIR                                   0x04
++
++/* Name friendly bit defines for register accesses */
++
++/* UART2/SIR */
++#define U2RSR_OvnErr                        0x08
++#define U2RSR_BrkErr                        0x04
++#define U2RSR_PtyErr                        0x02
++#define U2RSR_FrmErr                        0x01
++
++#define U2CRH_WLen                          0x60
++#define U2CRH_FEn                           0x10
++#define U2CRH_Stp2                          0x08
++#define U2CRH_EPS                           0x04
++#define U2CRH_PEn                           0x02
++#define U2CRH_Brk                           0x01
++
++#define U2CR_LoopBk                         0x80
++#define U2CR_RxTO                           0x40
++#define U2CR_TxIrq                          0x20
++#define U2CR_RxIrq                          0x10
++#define U2CR_MdmStsIrq                      0x08
++#define U2CR_SIRLowPwr                      0x04
++#define U2CR_SIR                            0x02
++#define U2CR_UART                           0x01
++
++#define U2FR_TXFE                           0x80
++#define U2FR_RXFF                           0x40
++#define U2FR_TXFF                           0x20
++#define U2FR_RXFE                           0x10
++#define U2FR_BUSY                           0x08
++#define U2FR_DCD                            0x04
++#define U2FR_DSR                            0x02
++#define U2FR_CTS                            0x01
++
++#define U2IICR_RXTOIRQ                      0x08
++#define U2IICR_TXIRQ                        0x04
++#define U2IICR_RXIRQ                        0x02
++#define U2IICR_MDMIRQ                       0x01
++
++#define U2DMACR_DMAErr                      0x04
++#define U2DMACR_TXDMA                       0x02
++#define U2DMACR_RXDMA                       0x01
++
++#define IrENABLE_SIR                        0x01
++
++/* IrDA block - MIR/FIR */
++#define IrENABLE_FIR                        0x03
++#define IrENABLE_MIR                        0x02
++
++#define IrCONTROL_RXRP                      0x40
++#define IrCONTROL_TXRP                      0x20
++#define IrCONTROL_RXON                      0x10
++#define IrCONTROL_TXON                      0x08
++#define IrCONTROL_TXUNDER                   0x04
++#define IrCONTROL_MIRBR                     0x02
++
++#define IrFLAG_TXBUSY                       0x200
++#define IrFLAG_RXINFRM                      0x100
++#define IrFLAG_RXSYNC                       0x80
++#define IrFLAG_EOF                          0x40
++#define IrFLAG_WIDTHST                      0x30
++#define IrFLAG_FIRFE                        0x08
++#define IrFLAG_RXOR                         0x04
++#define IrFLAG_CRCERR                       0x02
++#define IrFLAG_RXABORT                      0x01
++
++#define IrRIB_ByteCt                        0x7FF0
++#define IrRIB_BUFFE                         0x08
++#define IrRIB_BUFOR                         0x04
++#define IrRIB_BUFCRCERR                     0x02
++#define IrRIB_BUFRXABORT                    0x01
++
++#define IrDMACR_DMAERR                      0x04
++#define IrDMACR_DMATXE                      0x02
++#define IrDMACR_DMARXE                      0x01
++
++#define MFISR_RXFL                          0x40
++#define MFISR_RXIL                          0x20
++#define MFISR_RXFC                          0x10
++#define MFISR_RXFS                          0x08
++#define MFISR_TXFABORT                      0x04
++#define MFISR_TXFC                          0x02
++#define MFISR_TXSR                          0x01
++
++#define MFIMR_RXFL                          0x40
++#define MFIMR_RXIL                          0x20
++#define MFIMR_RXFC                          0x10
++#define MFIMR_RXFS                          0x08
++#define MFIMR_TXABORT                       0x04
++#define MFIMR_TXFC                          0x02
++#define MFIMR_TXFS                          0x01
++
++#define MFIIR_RXFL                          0x40
++#define MFIIR_RXIL                          0x20
++#define MFIIR_RXFC                          0x10
++#define MFIIR_RXFS                          0x08
++#define MFIIR_TXABORT                       0x04
++#define MFIIR_TXFC                          0x02
++#define MFIIR_TXFS                          0x01
++
++#endif                                /* EP93XX_IRDA_H */
+diff --git a/init/do_mounts.c b/init/do_mounts.c
+index b27c110..29d2d52 100644
+--- a/init/do_mounts.c
++++ b/init/do_mounts.c
+@@ -410,7 +410,9 @@ void __init prepare_namespace(void)
+                       root_device_name += 5;
+       }
+-      is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
++      /* llandre */
++      /* To retrieve ramdisk from MTD partition we must add major 31 as suggested by rmk */
++      is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR || MAJOR(ROOT_DEV) == 31;
+       if (initrd_load())
+               goto out;
+diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
+index 88e52dc..cda016b 100644
+--- a/sound/oss/Kconfig
++++ b/sound/oss/Kconfig
+@@ -1004,6 +1004,26 @@ config SOUND_AEDSP16
+         <file:Documentation/sound/oss/AudioExcelDSP16> to get more information
+         about this driver and its configuration.
++
++config SOUND_EP93XX_AC97
++      tristate "EP93xx AC97 Support"
++      depends on SOUND_OSS && ARCH_EP93XX
++      ---help---
++        AC97 sound support for Cirrus EP93xx
++
++config SOUND_EP93XX_AC97_CODEC_CS4297
++      bool "CS4297"
++      depends on SOUND_EP93XX_AC97
++      help
++        Say Y here if you have CS4297 Codec.
++
++config SOUND_EP93XX_AUDIO_PIO
++      bool "EP93xx AC97 in PIO mode"
++      depends on SOUND_EP93XX_AC97
++      ---help---
++        Run EP93XX AC97 in PIO MODE.
++        !!! NOT TESTED !!!
++
+ config SC6600
+       bool "SC-6600 based audio cards (new Audio Excel DSP 16)"
+       depends on SOUND_AEDSP16
+diff --git a/sound/oss/Makefile b/sound/oss/Makefile
+index 9bf3ee5..c7c1927 100644
+--- a/sound/oss/Makefile
++++ b/sound/oss/Makefile
+@@ -91,6 +91,9 @@ obj-$(CONFIG_SOUND_EMU10K1)  += emu10k1/
+ obj-$(CONFIG_SOUND_CS4281)    += cs4281/
+ obj-$(CONFIG_DMASOUND)                += dmasound/
++obj-$(CONFIG_SOUND_EP93XX_I2S)        += ep93xx-audio.o ep93xx-i2s.o
++obj-$(CONFIG_SOUND_EP93XX_AC97)       += ep93xx-audio.o ep93xx-ac97.o
++
+ # Declare multi-part drivers.
+ sound-objs    :=                                                      \
+diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
+index fd25aca..c7c9a02 100644
+--- a/sound/oss/ac97_codec.c
++++ b/sound/oss/ac97_codec.c
+@@ -156,6 +156,8 @@ static const struct {
+       {0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops},
+       {0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops},
+       {0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops},
++      {0x4352594d, "Cirrus Logic CS4201",     &crystal_digital_ops},
++      {0x43525973, "Cirrus Logic CS4202",     &crystal_digital_ops},
+       {0x43585430, "CXT48",                   &default_ops,           AC97_DELUDED_MODEM },
+       {0x43585442, "CXT66",                   &default_ops,           AC97_DELUDED_MODEM },
+       {0x44543031, "Diamond Technology DT0893", &default_ops},
+diff --git a/sound/oss/ep93xx-ac97.c b/sound/oss/ep93xx-ac97.c
+new file mode 100644
+index 0000000..a967f19
+--- /dev/null
++++ b/sound/oss/ep93xx-ac97.c
+@@ -0,0 +1,1200 @@
++/*
++ * Glue audio driver for the Cirrus EP93xx Ac97 Controller
++ *
++ * Copyright (c) 2003 Cirrus Logic Corp.
++ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License.
++ *
++ * This file taken from h3600-uda1341.c
++ * The mixer code is from ac97_codec.c
++ *
++ * History:
++ *
++ * 2000-05-21   Nicolas Pitre   Initial UDA1341 driver release.
++ *
++ * 2000-07-??   George France   Bitsy support.
++ *
++ * 2000-12-13   Deborah Wallach Fixed power handling for iPAQ/h3600
++ *
++ * 2001-06-03   Nicolas Pitre   Made this file a separate module, based on
++ *              the former sa1100-uda1341.c driver.
++ *
++ * 2001-07-13   Nicolas Pitre   Fixes for all supported samplerates.
++ *
++ * 2003-04-04   adt   Changes for Cirrus Logic EP93xx I2S
++ *
++ * 2003-04-25   adt   Changes for Cirrus Logic EP93xx Ac97
++ *
++ * 2005-05-11 Manfred Gruber  Ported this from Cirrus Logic Virgo 1-4-3 release
++ *                              to Kernel 2.6.11.X
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/fs.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/errno.h>
++#include <linux/sound.h>
++#include <linux/soundcard.h>
++#include <linux/bitops.h>
++
++#include <asm/semaphore.h>
++#include <asm/uaccess.h>
++#include <asm/hardware.h>
++#include <asm/dma.h>
++#include <asm/arch/clocks.h>
++#include <asm/io.h>
++#include <asm/arch/dma.h>
++#include <linux/dma-mapping.h>
++
++#include "ep93xx-audio.h"
++
++#undef DEBUG
++//#define DEBUG 1
++#ifdef DEBUG
++#define DPRINTK( x... )  printk( x )
++#else
++#define DPRINTK( x... )
++#endif
++
++#define AUDIO_NAME      "ep93xx_ac97"
++
++#ifdef CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297
++#define AUDIO_SAMPLE_RATE_DEFAULT   48000
++#else
++#define AUDIO_SAMPLE_RATE_DEFAULT   44100
++#endif
++
++/* original check is not good enough in case FOO is greater than
++ * SOUND_MIXER_NRDEVICES because the supported_mixers has exactly
++ * SOUND_MIXER_NRDEVICES elements.
++ * before matching the given mixer against the bitmask in supported_mixers we
++ * check if mixer number exceeds maximum allowed size which is as mentioned
++ * above SOUND_MIXER_NRDEVICES */
++#define supported_mixer(FOO) \
++      ( (FOO >= 0) && \
++      (FOO < SOUND_MIXER_NRDEVICES) && \
++      codec_supported_mixers & (1<<FOO) )
++
++/*
++ * Available record sources.
++ * LINE1 refers to AUX in.
++ * IGAIN refers to input gain which means stereo mix.
++ */
++#define AC97_RECORD_MASK \
++      (SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN | SOUND_MASK_VIDEO |\
++      SOUND_MASK_LINE1 | SOUND_MASK_LINE | SOUND_MASK_PHONEIN)
++
++#define AC97_STEREO_MASK \
++      (SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_CD | \
++      SOUND_MASK_ALTPCM | SOUND_MASK_IGAIN | SOUND_MASK_LINE1 | SOUND_MASK_VIDEO)
++
++#define AC97_SUPPORTED_MASK \
++      (AC97_STEREO_MASK | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
++      SOUND_MASK_SPEAKER | SOUND_MASK_MIC | \
++      SOUND_MASK_PHONEIN | SOUND_MASK_PHONEOUT)
++
++/*
++ * Function prototypes.
++ */
++static int peek(unsigned int uiAddress);
++static int poke(unsigned int uiAddress, unsigned int uiValue);
++static void ep93xx_setup_src(void);
++static void ep93xx_set_samplerate(struct audio_stream_t *stream,
++                                long lSampleRate);
++static void ep93xx_init_ac97_codec(void);
++static void ep93xx_set_hw_format(struct audio_stream_t *stream, long format);
++static void ep93xx_init_ac97_controller(void);
++static int ep93xx_mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
++                            ulong arg);
++static void ep93xx_audio_init(void *dummy);
++static int ep93xx_audio_ioctl(struct inode *inode, struct file *file, uint cmd,
++                            ulong arg);
++
++static int ep93xx_audio_open(struct inode *inode, struct file *file);
++static int __init ep93xx_ac97_init(void);
++static void __exit ep93xx_ac97_exit(void);
++static void ep93xx_init_mixer(void);
++static void ep93xx_audio_enable(struct audio_stream_t *stream);
++static void ep93xx_audio_disable(struct audio_stream_t *stream);
++
++/*
++ * Statics
++ */
++// KERNEL2.4
++//static long audio_samplerate = AUDIO_SAMPLE_RATE_DEFAULT;
++static int ac_link_enabled = 0;
++static int codec_supported_mixers;
++
++/* this table has default mixer values for all OSS mixers. */
++struct mixer_defaults_t {
++      int mixer;
++      unsigned int value;
++};
++
++/*
++ * Default mixer settings that are set up during boot.
++ *
++ * These values are 16 bit numbers in which the upper byte is right volume
++ * and the lower byte is left volume or mono volume for mono controls.
++ *
++ * OSS Range for each of left and right volumes is 0 to 100 (0x00 to 0x64).
++ *
++ */
++static struct mixer_defaults_t mixer_defaults[SOUND_MIXER_NRDEVICES] = {
++      /* Outputs */
++      {SOUND_MIXER_VOLUME, 0x6464},   /* 0 dB *//* -46.5dB to  0 dB */
++      {SOUND_MIXER_ALTPCM, 0x6464},   /* 0 dB *//* -46.5dB to  0 dB */
++      {SOUND_MIXER_PHONEOUT, 0x6464}, /* 0 dB *//* -46.5dB to  0 dB */
++
++      /* PCM playback gain */
++      {SOUND_MIXER_PCM, 0x4b4b},      /* 0 dB *//* -34.5dB to +12dB */
++
++      /* Record gain */
++      {SOUND_MIXER_IGAIN, 0x0000},    /* 0 dB *//*    0 to +22.5 dB */
++
++      /* Inputs */
++      {SOUND_MIXER_MIC, 0x0000},      /* mute *//* -34.5dB to +12dB */
++      {SOUND_MIXER_LINE, 0x4b4b},     /* 0 dB *//* -34.5dB to +12dB */
++
++      /* Inputs that are not connected. */
++      {SOUND_MIXER_SPEAKER, 0x0000},  /* mute *//* -45dB   to   0dB */
++      {SOUND_MIXER_PHONEIN, 0x0000},  /* mute *//* -34.5dB to +12dB */
++      {SOUND_MIXER_CD, 0x0000},       /* mute *//* -34.5dB to +12dB */
++      {SOUND_MIXER_VIDEO, 0x0000},    /* mute *//* -34.5dB to +12dB */
++      {SOUND_MIXER_LINE1, 0x0000},    /* mute *//* -34.5dB to +12dB */
++
++      {-1, 0}                 /* last entry */
++};
++
++static unsigned int guiOSS_Volume[SOUND_MIXER_NRDEVICES];
++
++/* table to scale scale from OSS mixer value to AC97 mixer register value */
++struct ac97_mixer_hw_t {
++      unsigned int offset;
++      int scale;
++};
++
++static struct ac97_mixer_hw_t ac97_hw[SOUND_MIXER_NRDEVICES] = {
++      [SOUND_MIXER_VOLUME] = {AC97_02_MASTER_VOL, 64},
++      [SOUND_MIXER_BASS] = {0, 0},
++      [SOUND_MIXER_TREBLE] = {0, 0},
++      [SOUND_MIXER_SYNTH] = {0, 0},
++      [SOUND_MIXER_PCM] = {AC97_18_PCM_OUT_VOL, 32},
++      [SOUND_MIXER_SPEAKER] = {AC97_0A_PC_BEEP_VOL, 32},
++      [SOUND_MIXER_LINE] = {AC97_10_LINE_IN_VOL, 32},
++      [SOUND_MIXER_MIC] = {AC97_0E_MIC_VOL, 32},
++      [SOUND_MIXER_CD] = {AC97_12_CD_VOL, 32},
++      [SOUND_MIXER_IMIX] = {0, 0},
++      [SOUND_MIXER_ALTPCM] = {AC97_04_HEADPHONE_VOL, 64},
++      [SOUND_MIXER_RECLEV] = {0, 0},
++      [SOUND_MIXER_IGAIN] = {AC97_1C_RECORD_GAIN, 16},
++      [SOUND_MIXER_OGAIN] = {0, 0},
++      [SOUND_MIXER_LINE1] = {AC97_16_AUX_VOL, 32},
++      [SOUND_MIXER_LINE2] = {0, 0},
++      [SOUND_MIXER_LINE3] = {0, 0},
++      [SOUND_MIXER_DIGITAL1] = {0, 0},
++      [SOUND_MIXER_DIGITAL2] = {0, 0},
++      [SOUND_MIXER_DIGITAL3] = {0, 0},
++      [SOUND_MIXER_PHONEIN] = {AC97_0C_PHONE_VOL, 32},
++      [SOUND_MIXER_PHONEOUT] = {AC97_06_MONO_VOL, 64},
++      [SOUND_MIXER_VIDEO] = {AC97_14_VIDEO_VOL, 32},
++      [SOUND_MIXER_RADIO] = {0, 0},
++      [SOUND_MIXER_MONITOR] = {0, 0},
++};
++
++/* the following tables allow us to go from OSS <-> ac97 quickly. */
++enum ac97_recsettings {
++      AC97_REC_MIC = 0,
++      AC97_REC_CD,
++      AC97_REC_VIDEO,
++      AC97_REC_AUX,
++      AC97_REC_LINE,
++      AC97_REC_STEREO,        /* combination of all enabled outputs..  */
++      AC97_REC_MONO,          /*.. or the mono equivalent */
++      AC97_REC_PHONE
++};
++
++static const unsigned int ac97_rm2oss[] = {
++      [AC97_REC_MIC] = SOUND_MIXER_MIC,
++      [AC97_REC_CD] = SOUND_MIXER_CD,
++      [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO,
++      [AC97_REC_AUX] = SOUND_MIXER_LINE1,
++      [AC97_REC_LINE] = SOUND_MIXER_LINE,
++      [AC97_REC_STEREO] = SOUND_MIXER_IGAIN,
++      [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN
++};
++
++/* indexed by bit position */
++static const unsigned int ac97_oss_rm[] = {
++      [SOUND_MIXER_MIC] = AC97_REC_MIC,
++      [SOUND_MIXER_CD] = AC97_REC_CD,
++      [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO,
++      [SOUND_MIXER_LINE1] = AC97_REC_AUX,
++      [SOUND_MIXER_LINE] = AC97_REC_LINE,
++      [SOUND_MIXER_IGAIN] = AC97_REC_STEREO,
++      [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE
++};
++
++static struct audio_stream_t ac97_output_stream0 = {
++      audio_num_channels:EP93XX_DEFAULT_NUM_CHANNELS,
++      audio_format:EP93XX_DEFAULT_FORMAT,
++      audio_stream_bitwidth:EP93XX_DEFAULT_BIT_WIDTH,
++      devicename:"Ac97_out",
++      dmachannel:{DMATx_AAC1, UNDEF, UNDEF},
++      sample_rate:0,
++      hw_bit_width:16,
++      bCompactMode:1,
++};
++
++static struct audio_stream_t ac97_input_stream0 = {
++      audio_num_channels:EP93XX_DEFAULT_NUM_CHANNELS,
++      audio_format:EP93XX_DEFAULT_FORMAT,
++      audio_stream_bitwidth:EP93XX_DEFAULT_BIT_WIDTH,
++      devicename:"Ac97_in",
++      dmachannel:{DMARx_AAC1, UNDEF, UNDEF},
++      sample_rate:0,
++      hw_bit_width:16,
++      bCompactMode:1,
++};
++
++static struct audio_hw_t ep93xx_ac97_hw = {
++      hw_enable:ep93xx_audio_enable,
++      hw_disable:ep93xx_audio_disable,
++      hw_clear_fifo:0,
++      client_ioctl:ep93xx_audio_ioctl,
++
++      set_hw_serial_format:ep93xx_set_hw_format,
++
++      txdmachannels:{DMATx_AAC1, DMATx_AAC2, DMATx_AAC3},
++      rxdmachannels:{DMARx_AAC1, DMARx_AAC2, DMARx_AAC3},
++
++      MaxTxDmaChannels:3,
++      MaxRxDmaChannels:3,
++
++      modcnt:0,
++};
++
++static struct audio_state_t ac97_audio_state0 = {
++      output_stream:&ac97_output_stream0,
++      input_stream:&ac97_input_stream0,
++      // KERNEL2.4 deleted internal sema intialisier, do it in function
++      hw:&ep93xx_ac97_hw,
++      wr_ref:0,
++      rd_ref:0,
++};
++
++/*
++ * peek
++ *
++ * Reads an AC97 codec register.  Returns -1 if there was an error.
++ */
++static int peek(unsigned int uiAddress)
++{
++      unsigned int uiAC97RGIS, uiTemp;
++
++      if (!ac_link_enabled) {
++              DPRINTK
++                  ("ep93xx ac97 peek: attempt to peek before enabling ac-link.\n");
++              return -1;
++      }
++
++      /*
++       * Check to make sure that the address is aligned on a word boundary
++       * and is 7E or less.
++       */
++      if (((uiAddress & 0x1) != 0) || (uiAddress > 0x007e)) {
++              return -1;
++      }
++
++      /*
++       * How it is supposed to work is:
++       *  - The ac97 controller sends out a read addr in slot 1.
++       *  - In the next frame, the codec will echo that address back in slot 1
++       *    and send the data in slot 2.  SLOT2RXVALID will be set to 1.
++       *
++       * Read until SLOT2RXVALID goes to 1.  Reading the data in AC97S2DATA
++       * clears SLOT2RXVALID.
++       */
++
++      /*
++       * First, delay one frame in case of back to back peeks/pokes.
++       */
++      mdelay(1);
++
++      /*
++       * Write the address to AC97S1DATA, delay 1 frame, read the flags.
++       */
++      outl(uiAddress, AC97S1DATA);
++      uiTemp = inl(AC97GCR);  /* read to push write out the wrapper */
++
++      udelay(21 * 4);
++      uiAC97RGIS = inl(AC97RGIS);
++
++      /*
++       * Return error if we timed out.
++       */
++      if (((uiAC97RGIS & AC97RGIS_SLOT1TXCOMPLETE) == 0) &&
++          ((uiAC97RGIS & AC97RGIS_SLOT2RXVALID) == 0)) {
++              DPRINTK("ep93xx-ac97 - peek failed reading reg 0x%02x.\n",
++                      uiAddress);
++              return -1;
++      }
++
++      return (inl(AC97S2DATA) & 0x000fffff);
++}
++
++/*
++ * poke
++ *
++ * Writes an AC97 codec Register.  Return -1 if error.
++ */
++static int poke(unsigned int uiAddress, unsigned int uiValue)
++{
++      unsigned int uiAC97RGIS, uiTemp;
++
++      if (!ac_link_enabled) {
++              DPRINTK
++                  ("ep93xx ac97 poke: attempt to poke before enabling ac-link.\n");
++              return -1;
++      }
++
++      /*
++       * Check to make sure that the address is align on a word boundary and
++       * is 7E or less.  And that the value is a 16 bit value.
++       */
++      if (((uiAddress & 0x1) != 0) || (uiAddress > 0x007e)) {
++              return -1;
++      }
++
++      /*
++       * First, delay one frame in case of back to back peeks/pokes.
++       */
++      mdelay(1);
++
++      /*
++       * Write the data to AC97S2DATA, then the address to AC97S1DATA.
++       */
++      outl(uiValue, AC97S2DATA);
++      outl(uiAddress, AC97S1DATA);
++      uiTemp = inl(AC97GCR);  /* read to push writes out the wrapper */
++
++      /*
++       * Wait for the tx to complete, get status.
++       */
++      udelay(42);
++      uiAC97RGIS = inl(AC97RGIS);
++
++      /*
++       * Return error if we timed out.
++       */
++      if (!(inl(AC97RGIS) & AC97RGIS_SLOT1TXCOMPLETE)) {
++              DPRINTK
++                  ("ep93xx-ac97: poke failed writing reg 0x%02x  value 0x%02x.\n",
++                   uiAddress, uiValue);
++              return -1;
++      }
++
++      return 0;
++}
++
++/*
++ * When we get to the multichannel case the pre-fill and enable code
++ * will go to the dma driver's start routine.
++ */
++static void ep93xx_audio_enable(struct audio_stream_t *stream)
++{
++      unsigned int uiTemp;
++
++      DPRINTK("ep93xx_audio_enable\n");
++
++      /*
++       * Enable the rx or tx channel
++       */
++      if (stream->dmachannel[0] == DMATx_AAC1) {
++              uiTemp = inl(AC97TXCR1);
++              outl((uiTemp | AC97TXCR_TEN), AC97TXCR1);
++              uiTemp = inl(AC97TXCR1);
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++              outl(inl(AC97IE1) | AC97ISR_TIS, AC97IE1);
++#endif
++      }
++
++      if (stream->dmachannel[0] == DMARx_AAC1) {
++              uiTemp = inl(AC97RXCR1);
++              outl((uiTemp | AC97RXCR_REN), AC97RXCR1);
++              uiTemp = inl(AC97RXCR1);
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++              outl(inl(AC97IE1) | AC97ISR_RIS, AC97IE1);
++#endif
++      }
++      //DPRINTK("ep93xx_audio_enable - EXIT\n");
++}
++
++static void ep93xx_audio_disable(struct audio_stream_t *stream)
++{
++      unsigned int uiControl, uiStatus;
++
++      DPRINTK("ep93xx_audio_disable\n");
++
++      /*
++       * Disable the rx or tx channel
++       */
++      if (stream->dmachannel[0] == DMATx_AAC1) {
++              uiControl = inl(AC97TXCR1);
++              if (uiControl & AC97TXCR_TEN) {
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++                      outl(inl(AC97IE1) & ~AC97ISR_TIS, AC97IE1);
++#else
++                      /*
++                       * Wait for fifo to empty.  We've shut down the dma
++                       * so that should happen soon.
++                       */
++                      do {
++                              uiStatus = inl(AC97SR1);
++                      } while (((uiStatus & 0x82) == 0));
++                      //} while( ((uiStatus & 0x20)!=0) ;&&
++                      //((uiStatus & 0x82)==0) );
++#endif
++
++                      outl((uiControl & ~AC97TXCR_TEN), AC97TXCR1);
++                      uiControl = inl(AC97TXCR1);
++              }
++      }
++
++      if (stream->dmachannel[0] == DMARx_AAC1) {
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++              outl(inl(AC97IE1) & ~AC97ISR_RIS, AC97IE1);
++#endif
++              uiControl = inl(AC97RXCR1);
++              outl((uiControl & ~AC97RXCR_REN), AC97RXCR1);
++              uiControl = inl(AC97RXCR1);
++      }
++      //DPRINTK("ep93xx_audio_disable - EXIT\n");
++}
++
++/*
++ * ep93xx_setup_src
++ *
++ * Once the ac-link is up and all is good, we want to set the codec to a
++ * usable mode.
++ */
++static void ep93xx_setup_src(void)
++{
++      int iTemp;
++
++      /*
++       * Set the VRA bit to enable the SRC.
++       */
++      iTemp = peek(AC97_2A_EXT_AUDIO_POWER);
++      poke(AC97_2A_EXT_AUDIO_POWER, (iTemp | 0x1));
++
++      /*
++       * Set the DSRC/ASRC bits to enable the variable rate SRC.
++       */
++      iTemp = peek(AC97_60_MISC_CRYSTAL_CONTROL);
++      poke(AC97_60_MISC_CRYSTAL_CONTROL, (iTemp | 0x0300));
++}
++
++/*
++ * ep93xx_set_samplerate
++ *
++ *   lFrequency               - Sample Rate in Hz
++ *   bTx                      - 1 to set Tx sample rate
++ *   bRx                      - 1 to set Rx sample rate
++ */
++static void ep93xx_set_samplerate(struct audio_stream_t *stream,
++                                long lSampleRate)
++{
++#ifndef CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297
++      unsigned short usDivider, usPhase;
++
++      DPRINTK("ep93xx_set_samplerate - Fs = %d\n", (int)lSampleRate);
++
++      if ((lSampleRate < 7200) || (lSampleRate > 48000)) {
++              DPRINTK("ep93xx_set_samplerate - invalid Fs = %d\n",
++                      (int)lSampleRate);
++              return;
++      }
++
++      /*
++       * Calculate divider and phase increment.
++       *
++       * divider = round( 0x1770000 / lSampleRate )
++       *  Note that usually rounding is done by adding 0.5 to a floating
++       *  value and then truncating.  To do this without using floating
++       *  point, I multiply the fraction by two, do the division, then add one,
++       *  then divide the whole by 2 and then truncate.
++       *  Same effect, no floating point math.
++       *
++       * Ph incr = trunc( (0x1000000 / usDivider) + 1 )
++       */
++
++      usDivider = (unsigned short)(((2 * 0x1770000 / lSampleRate) + 1) / 2);
++
++      usPhase = (0x1000000 / usDivider) + 1;
++
++      /*
++       * Write them in the registers.  Spec says divider must be
++       * written after phase incr.
++       */
++      if (stream->dmachannel[0] == DMATx_AAC1) {
++              poke(AC97_2C_PCM_FRONT_DAC_RATE, usDivider);
++              poke(AC97_64_DAC_SRC_PHASE_INCR, usPhase);
++      }
++
++      if (stream->dmachannel[0] == DMARx_AAC1) {
++
++              poke(AC97_32_PCM_LR_ADC_RATE, usDivider);
++              poke(AC97_66_ADC_SRC_PHASE_INCR, usPhase);
++      }
++
++      DPRINTK("ep93xx_set_samplerate - phase = %d,  divider = %d\n",
++              (unsigned int)usPhase, (unsigned int)usDivider);
++
++      /*
++       * We sorta should report the actual samplerate back to the calling
++       * application.  But some applications freak out if they don't get
++       * exactly what they asked for.  So we fudge and tell them what
++       * they want to hear.
++       */
++      stream->sample_rate = lSampleRate;
++
++      DPRINTK("ep93xx_set_samplerate - EXIT\n");
++#else
++      stream->sample_rate = AUDIO_SAMPLE_RATE_DEFAULT;
++#endif
++}
++
++/*
++ * ep93xx_set_hw_format
++ *
++ * Sets up whether the controller is expecting 20 bit data in 32 bit words
++ * or 16 bit data compacted to have a stereo sample in each 32 bit word.
++ */
++static void ep93xx_set_hw_format(struct audio_stream_t *stream, long format)
++{
++      int bCompactMode, uiTemp, iWidth;
++      unsigned long ulRegValue;
++
++      switch (format) {
++              /*
++               * Here's all the <=16 bit formats.  We can squeeze both L and R
++               * into one 32 bit sample so use compact mode.
++               */
++      case AFMT_U8:
++      case AFMT_S8:
++      case AFMT_S16_LE:
++      case AFMT_U16_LE:
++              bCompactMode = 1;
++              ulRegValue = 0x00008018;
++              iWidth = 16;
++              break;
++
++              /*
++               * Add any other >16 bit formats here...
++               */
++      case AFMT_S32_BLOCKED:
++      default:
++              bCompactMode = 0;
++              ulRegValue = 0x00004018;
++              iWidth = 20;
++              break;
++      }
++
++      if (stream->dmachannel[0] == DMARx_AAC1) {
++              uiTemp = inl(AC97RXCR1);
++              if (ulRegValue != uiTemp) {
++                      outl(ulRegValue, AC97RXCR1);
++                      uiTemp = inl(AC97RXCR1);
++              }
++              stream->hw_bit_width = iWidth;
++              stream->bCompactMode = bCompactMode;
++      }
++
++      if (stream->dmachannel[0] == DMATx_AAC1) {
++              uiTemp = inl(AC97TXCR1);
++              if (ulRegValue != uiTemp) {
++                      outl(ulRegValue, AC97TXCR1);
++                      uiTemp = inl(AC97TXCR1);
++              }
++              stream->hw_bit_width = iWidth;
++              stream->bCompactMode = bCompactMode;
++      }
++
++}
++
++/*
++ * ep93xx_init_ac97_controller
++ *
++ * This routine sets up the Ac'97 Controller.
++ */
++static void ep93xx_init_ac97_controller(void)
++{
++      unsigned int uiDEVCFG, uiTemp;
++
++      DPRINTK("ep93xx_init_ac97_controller - enter\n");
++
++      /*
++       * Configure the multiplexed Ac'97 pins to be Ac97 not I2s.
++       * Configure the EGPIO4 and EGPIO6 to be GPIOS, not to be
++       * SDOUT's for the second and third I2S controller channels.
++       */
++      uiDEVCFG = inl(SYSCON_DEVCFG);
++
++      uiDEVCFG &= ~(SYSCON_DEVCFG_I2SonAC97 |
++                    SYSCON_DEVCFG_A1onG | SYSCON_DEVCFG_A2onG);
++
++      SysconSetLocked(SYSCON_DEVCFG, uiDEVCFG);
++
++      /*
++       * Disable the AC97 controller internal loopback.
++       * Disable Override codec ready.
++       */
++      outl(0, AC97GCR);
++
++      /*
++       * Enable the AC97 Link.
++       */
++      uiTemp = inl(AC97GCR);
++      outl((uiTemp | AC97GSR_IFE), AC97GCR);
++      uiTemp = inl(AC97GCR);  /* read to push write out the wrapper */
++
++      /*
++       * Set the TIMEDRESET bit.  Will cause a > 1uSec reset of the ac-link.
++       * This bit is self resetting.
++       */
++      outl(AC97RESET_TIMEDRESET, AC97RESET);
++      uiTemp = inl(AC97GCR);  /* read to push write out the wrapper */
++
++      /*
++       *  Delay briefly, but let's not hog the processor.
++       */
++      set_current_state(TASK_INTERRUPTIBLE);
++      schedule_timeout(5);    /* 50 mSec */
++
++      /*
++       * Read the AC97 status register to see if we've seen a CODECREADY
++       * signal from the AC97 codec.
++       */
++      if (!(inl(AC97RGIS) & AC97RGIS_CODECREADY)) {
++              DPRINTK("ep93xx-ac97 - FAIL: CODECREADY still low!\n");
++              return;
++      }
++
++      /*
++       *  Delay for a second, not hogging the processor
++       */
++      set_current_state(TASK_INTERRUPTIBLE);
++      schedule_timeout(HZ);   /* 1 Sec */
++
++      /*
++       * Now the Ac-link is up.  We can read and write codec registers.
++       */
++      ac_link_enabled = 1;
++
++      /*
++       * Set up the rx and tx channels
++       * Set the CM bit, data size=16 bits, enable tx slots 3 & 4.
++       */
++      ep93xx_set_hw_format(&ac97_output_stream0, EP93XX_DEFAULT_FORMAT);
++      ep93xx_set_hw_format(&ac97_input_stream0, EP93XX_DEFAULT_FORMAT);
++
++      DPRINTK("ep93xx-ac97 -- AC97RXCR1:  %08x\n", inl(AC97RXCR1));
++      DPRINTK("ep93xx-ac97 -- AC97TXCR1:  %08x\n", inl(AC97TXCR1));
++
++      DPRINTK("ep93xx_init_ac97_controller - EXIT - success\n");
++
++}
++
++/*
++ * ep93xx_init_ac97_codec
++ *
++ * Program up the external Ac97 codec.
++ *
++ */
++static void ep93xx_init_ac97_codec(void)
++{
++      DPRINTK("ep93xx_init_ac97_codec - enter\n");
++
++      ep93xx_setup_src();
++      ep93xx_set_samplerate(&ac97_output_stream0, AUDIO_SAMPLE_RATE_DEFAULT);
++      ep93xx_set_samplerate(&ac97_input_stream0, AUDIO_SAMPLE_RATE_DEFAULT);
++      ep93xx_init_mixer();
++
++      DPRINTK("ep93xx_init_ac97_codec - EXIT\n");
++
++}
++
++#ifdef DEBUG
++static void ep93xx_dump_ac97_regs(void)
++{
++      int i;
++      unsigned int reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7;
++
++      DPRINTK("---------------------------------------------\n");
++      DPRINTK("   :   0    2    4    6    8    A    C    E\n");
++
++      for (i = 0; i < 0x80; i += 0x10) {
++              reg0 = 0xffff & (unsigned int)peek(i);
++              reg1 = 0xffff & (unsigned int)peek(i + 0x2);
++              reg2 = 0xffff & (unsigned int)peek(i + 0x4);
++              reg3 = 0xffff & (unsigned int)peek(i + 0x6);
++              reg4 = 0xffff & (unsigned int)peek(i + 0x8);
++              reg5 = 0xffff & (unsigned int)peek(i + 0xa);
++              reg6 = 0xffff & (unsigned int)peek(i + 0xc);
++              reg7 = 0xffff & (unsigned int)peek(i + 0xe);
++
++              DPRINTK(" %02x : %04x %04x %04x %04x %04x %04x %04x %04x\n",
++                      i, reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7);
++      }
++}
++#endif
++
++static void ep93xx_set_volume(unsigned int oss_channel, unsigned int oss_val) {
++      unsigned int left, right;
++      u16 val = 0;
++      struct ac97_mixer_hw_t *mh = &ac97_hw[oss_channel];
++
++      if (!mh->scale) {
++              DPRINTK
++                  ("ep93xx-ac97.c: ep93xx_set_volume - not a valid OSS channel\n");
++              return;
++      }
++
++      /* cleanse input a little */
++      right = ((oss_val >> 8) & 0xff);
++      left = (oss_val & 0xff);
++
++      if (right > 100)
++              right = 100;
++      if (left > 100)
++              left = 100;
++
++      DPRINTK("ac97_codec: wrote OSS channel#%2d (ac97 reg 0x%02x), "
++              "l:%2d, r:%2d:", oss_channel, mh->offset, left, right);
++
++      if (AC97_STEREO_MASK & (1 << oss_channel)) {
++              /* stereo mixers */
++              if (oss_channel == SOUND_MIXER_IGAIN) {
++                      right = ((100 - right) * (mh->scale - 1)) / 100;
++                      left = ((100 - left) * (mh->scale - 1)) / 100;
++                      if (right >= mh->scale)
++                              right = mh->scale - 1;
++                      if (left >= mh->scale)
++                              left = mh->scale - 1;
++                      right = (mh->scale - 1) - right;
++                      left = (mh->scale - 1) - left;
++                      val = (left << 8) | right;
++              } else {
++                      if (left == 0 && right == 0) {
++                              val = 0x8000;
++                      } else {
++                              right = ((100 - right) * (mh->scale - 1)) / 100;
++                              left = ((100 - left) * (mh->scale - 1)) / 100;
++                              if (right >= mh->scale)
++                                      right = mh->scale - 1;
++                              if (left >= mh->scale)
++                                      left = mh->scale - 1;
++                              val = (left << 8) | right;
++                      }
++              }
++      } else if (left == 0) {
++              val = 0x8000;
++      } else if ((oss_channel == SOUND_MIXER_SPEAKER) ||
++                 (oss_channel == SOUND_MIXER_PHONEIN) ||
++                 (oss_channel == SOUND_MIXER_PHONEOUT)) {
++              left = ((100 - left) * (mh->scale - 1)) / 100;
++              if (left >= mh->scale)
++                      left = mh->scale - 1;
++              val = left;
++      } else if (oss_channel == SOUND_MIXER_MIC) {
++              val = peek(mh->offset) & ~0x801f;
++              left = ((100 - left) * (mh->scale - 1)) / 100;
++              if (left >= mh->scale)
++                      left = mh->scale - 1;
++              val |= left;
++      }
++      /*
++       * For bass and treble, the low bit is optional.  Masking it
++       * lets us avoid the 0xf 'bypass'.
++       * Do a read, modify, write as we have two contols in one reg.
++       */
++      else if (oss_channel == SOUND_MIXER_BASS) {
++              val = peek(mh->offset) & ~0x0f00;
++              left = ((100 - left) * (mh->scale - 1)) / 100;
++              if (left >= mh->scale)
++                      left = mh->scale - 1;
++              val |= (left << 8) & 0x0e00;
++      } else if (oss_channel == SOUND_MIXER_TREBLE) {
++              val = peek(mh->offset) & ~0x000f;
++              left = ((100 - left) * (mh->scale - 1)) / 100;
++              if (left >= mh->scale)
++                      left = mh->scale - 1;
++              val |= left & 0x000e;
++      }
++
++      DPRINTK(" 0x%04x", val);
++
++      poke(mh->offset, val);
++
++#ifdef DEBUG
++      val = peek(mh->offset);
++      DPRINTK(" (read back 0x%04x)\n", val);
++#endif
++
++      guiOSS_Volume[oss_channel] = oss_val;
++}
++
++static void ep93xx_init_mixer(void)
++{
++      u16 cap;
++      int i;
++
++      /* mixer masks */
++      codec_supported_mixers = AC97_SUPPORTED_MASK;
++
++      cap = peek(AC97_00_RESET);
++      if (!(cap & 0x04)) {
++              codec_supported_mixers &=
++                  ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE);
++      }
++      if (!(cap & 0x10)) {
++              codec_supported_mixers &= ~SOUND_MASK_ALTPCM;
++      }
++
++      /*
++       * Detect bit resolution of output volume controls by writing to the
++       * 6th bit (not unmuting yet)
++       */
++      poke(AC97_02_MASTER_VOL, 0xa020);
++      if (peek(AC97_02_MASTER_VOL) != 0xa020) {
++              ac97_hw[SOUND_MIXER_VOLUME].scale = 32;
++      }
++
++      poke(AC97_04_HEADPHONE_VOL, 0xa020);
++      if (peek(AC97_04_HEADPHONE_VOL) != 0xa020) {
++              ac97_hw[AC97_04_HEADPHONE_VOL].scale = 32;
++      }
++
++      poke(AC97_06_MONO_VOL, 0x8020);
++      if (peek(AC97_06_MONO_VOL) != 0x8020) {
++              ac97_hw[AC97_06_MONO_VOL].scale = 32;
++      }
++
++      /* initialize mixer channel volumes */
++      for (i = 0;
++           (i < SOUND_MIXER_NRDEVICES) && (mixer_defaults[i].mixer != -1);
++           i++) {
++              if (!supported_mixer(mixer_defaults[i].mixer)) {
++                      continue;
++              }
++
++              ep93xx_set_volume(mixer_defaults[i].mixer,
++                                mixer_defaults[i].value);
++      }
++
++}
++
++/*
++ * ac97_recmask_io
++ *
++ * Read or write the record source.
++ */
++static int ep93xx_read_recsource(void)
++{
++      unsigned int val;
++
++      /* read it from the card */
++      val = peek(AC97_1A_RECORD_SELECT);
++
++      DPRINTK("ac97_codec: ac97 recmask to set to 0x%04x\n", val);
++
++      return (1 << ac97_rm2oss[val & 0x07]);
++}
++
++static int ep93xx_set_recsource(int mask)
++{
++      unsigned int val;
++
++      /* Arg contains a bit for each recording source */
++      if (mask == 0) {
++              return 0;
++      }
++
++      mask &= AC97_RECORD_MASK;
++
++      if (mask == 0) {
++              return -EINVAL;
++      }
++
++      /*
++       * May have more than one bit set.  So clear out currently selected
++       * record source value first (AC97 supports only 1 input)
++       */
++      val = (1 << ac97_rm2oss[peek(AC97_1A_RECORD_SELECT) & 0x07]);
++      if (mask != val)
++              mask &= ~val;
++
++      val = ffs(mask);
++      val = ac97_oss_rm[val - 1];
++      val |= val << 8;        /* set both channels */
++
++      DPRINTK("ac97_codec: setting ac97 recmask to 0x%04x\n", val);
++
++      poke(AC97_1A_RECORD_SELECT, val);
++
++      return 0;
++}
++
++static int ep93xx_mixer_open(struct inode *inode, struct file *file)
++{
++      file->private_data = &ep93xx_ac97_hw;
++      return 0;
++}
++
++static int ep93xx_mixer_release(struct inode *inode, struct file *file)
++{
++      return 0;
++}
++
++static int
++ep93xx_mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
++{
++      int val, nr;
++
++      struct audio_hw_t *hw = (struct audio_hw_t *)file->private_data;
++
++      DPRINTK("ep93xx_mixer_ioctl - enter.  IOC_TYPE is %c \n",
++              _IOC_TYPE(cmd));
++
++      if (cmd == SOUND_MIXER_INFO) {
++              mixer_info info;
++              strncpy(info.id, "CS4202", sizeof(info.id));
++              strncpy(info.name, "Cirrus CS4202", sizeof(info.name));
++              info.modify_counter = hw->modcnt;
++              if (copy_to_user((void *)arg, &info, sizeof(info))) {
++                      return -EFAULT;
++              }
++              return 0;
++      }
++      if (cmd == SOUND_OLD_MIXER_INFO) {
++              _old_mixer_info info;
++              strncpy(info.id, "CS4202", sizeof(info.id));
++              strncpy(info.name, "Cirrus CS4202", sizeof(info.name));
++              if (copy_to_user((void *)arg, &info, sizeof(info))) {
++                      return -EFAULT;
++              }
++              return 0;
++      }
++
++      if ((_IOC_TYPE(cmd) != 'M') || (_SIOC_SIZE(cmd) != sizeof(int)))
++              return -EINVAL;
++
++      if (cmd == OSS_GETVERSION)
++              return put_user(SOUND_VERSION, (int *)arg);
++
++      nr = _IOC_NR(cmd);
++
++      if (_SIOC_DIR(cmd) == _SIOC_READ) {
++              switch (nr) {
++              case SOUND_MIXER_RECSRC:
++                      /* Read the current record source */
++                      val = ep93xx_read_recsource();
++                      break;
++
++              case SOUND_MIXER_DEVMASK:
++                      /* give them the supported mixers */
++                      val = codec_supported_mixers;
++                      break;
++
++              case SOUND_MIXER_RECMASK:
++                      /* Arg contains a bit for each supported recording source */
++                      val = AC97_RECORD_MASK;
++                      break;
++
++              case SOUND_MIXER_STEREODEVS:
++                      /* Mixer channels supporting stereo */
++                      val = AC97_STEREO_MASK;
++                      break;
++
++              case SOUND_MIXER_CAPS:
++                      val = SOUND_CAP_EXCL_INPUT;
++                      break;
++
++              default:
++                      if (!supported_mixer(nr))
++                              return -EINVAL;
++
++                      val = guiOSS_Volume[nr];
++                      break;
++
++              }               /* switch */
++
++              return put_user(val, (int *)arg);
++      }
++
++      if (_SIOC_DIR(cmd) == (_SIOC_WRITE | _SIOC_READ)) {
++              if (get_user(val, (int *)arg))
++                      return -EFAULT;
++
++              switch (nr) {
++              case SOUND_MIXER_RECSRC:
++                      return ep93xx_set_recsource(val);
++
++              default:
++                      if (!supported_mixer(nr))
++                              return -EINVAL;
++
++                      ep93xx_set_volume(nr, val);
++                      hw->modcnt++;
++                      return 0;
++              }
++      }
++
++      return -EINVAL;
++}
++
++static struct file_operations ep93xx_mixer_fops = {
++      owner:THIS_MODULE,
++      llseek:no_llseek,
++      ioctl:ep93xx_mixer_ioctl,
++      open:ep93xx_mixer_open,
++      release:ep93xx_mixer_release,
++};
++
++/*
++ * Audio interface
++ */
++static void ep93xx_audio_init(void *dummy)
++{
++      DPRINTK("ep93xx_audio_init - enter\n");
++
++      /*
++       * Init the controller, enable the ac-link.
++       * Initialize the codec.
++       */
++      ep93xx_init_ac97_controller();
++      ep93xx_init_ac97_codec();
++
++#ifdef DEBUG
++      ep93xx_dump_ac97_regs();
++#endif
++
++      DPRINTK("ep93xx_audio_init - EXIT\n");
++}
++
++static int ep93xx_audio_ioctl(struct inode *inode, struct file *file,
++                            uint cmd, ulong arg)
++{
++      struct audio_state_t *state =
++          (struct audio_state_t *)file->private_data;
++      struct audio_stream_t *os = state->output_stream;
++      struct audio_stream_t *is = state->input_stream;
++      long val;
++      int ret = 0;
++
++      /*
++       * These are platform dependent ioctls which are not handled by the
++       * generic ep93xx-audio module.
++       */
++      switch (cmd) {
++      case SNDCTL_DSP_SPEED:
++
++              DPRINTK("ep93xx_audio_ioctl - SNDCTL_DSP_SPEED\n");
++
++              if (get_user(val, (int *)arg)) {
++                      return -EFAULT;
++              }
++
++              if ((file->f_mode & FMODE_WRITE) && (val != os->sample_rate)) {
++                      ep93xx_set_samplerate(os, val);
++              }
++              if ((file->f_mode & FMODE_READ) && (val != is->sample_rate)) {
++                      ep93xx_set_samplerate(is, val);
++              }
++
++              return put_user(val, (long *)arg);
++
++      case SOUND_PCM_READ_RATE:
++              DPRINTK("ep93xx_audio_ioctl - SOUND_PCM_READ_RATE\n");
++              if (file->f_mode & FMODE_WRITE) {
++                      return put_user(os->sample_rate, (long *)arg);
++              }
++              return put_user(is->sample_rate, (long *)arg);
++
++      default:
++              DPRINTK("ep93xx_audio_ioctl-->ep93xx_mixer_ioctl\n");
++              /* Maybe this is meant for the mixer (As per OSS Docs) */
++              return ep93xx_mixer_ioctl(inode, file, cmd, arg);
++      }
++
++      return ret;
++}
++
++static int ep93xx_audio_open(struct inode *inode, struct file *file)
++{
++      DPRINTK("ep93xx_audio_open\n");
++      return ep93xx_audio_attach(inode, file, &ac97_audio_state0);
++}
++
++/*
++ * Missing fields of this structure will be patched with the call
++ * to ep93xx_audio_attach().
++ */
++static struct file_operations ep93xx_audio_fops = {
++      open:ep93xx_audio_open,
++      owner:THIS_MODULE
++};
++
++static int audio_dev_id, mixer_dev_id;
++
++static int __init ep93xx_ac97_init(void)
++{
++      DPRINTK("ep93xx_ac97_init - enter\n");
++
++      // KERNEL2.4
++      sema_init(&ac97_audio_state0.sem, 1);
++
++      /*
++       * Enable audio early on, give the DAC time to come up.
++       */
++      ep93xx_audio_init(0);
++
++      /*
++       * Register devices using sound_core.c's devfs stuff
++       */
++      audio_dev_id = register_sound_dsp(&ep93xx_audio_fops, -1);
++      if (audio_dev_id < 0) {
++              DPRINTK
++                  (" ep93xx_ac97_init: register_sound_dsp failed for dsp.\n");
++              return -ENODEV;
++      }
++
++      mixer_dev_id = register_sound_mixer(&ep93xx_mixer_fops, -1);
++      if (mixer_dev_id < 0) {
++              DPRINTK
++                  (" ep93xx_ac97_init: register_sound_dsp failed for mixer.\n");
++              return -ENODEV;
++      }
++
++      printk(KERN_INFO "EP93xx Ac97 audio support initialized.\n");
++      return 0;
++}
++
++static void __exit ep93xx_ac97_exit(void)
++{
++      unregister_sound_dsp(audio_dev_id);
++      unregister_sound_mixer(mixer_dev_id);
++}
++
++module_init(ep93xx_ac97_init);
++module_exit(ep93xx_ac97_exit);
++
++MODULE_DESCRIPTION("Audio driver for the Cirrus EP93xx Ac97 controller.");
++MODULE_LICENSE("GPL");
++/* EXPORT_NO_SYMBOLS; */
+diff --git a/sound/oss/ep93xx-audio.c b/sound/oss/ep93xx-audio.c
+new file mode 100644
+index 0000000..7e00d6d
+--- /dev/null
++++ b/sound/oss/ep93xx-audio.c
+@@ -0,0 +1,3821 @@
++/*
++ * ep93xx-audio.c
++ *
++ * Common audio handling for the Cirrus EP93xx processor.
++ *
++ * Copyright (c) 2003 Cirrus Logic Corp.
++ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License.
++ *
++ * Taken from sa1100-audio.c
++ *
++ * This module handles the generic buffering/DMA/mmap audio interface for
++ * codecs connected to the EP93xx chip.  All features depending on specific
++ * hardware implementations like supported audio formats or samplerates are
++ * relegated to separate specific modules.
++ *
++ *
++ * History:
++ *
++ * 2000-05-21 Nicolas Pitre   Initial release.
++ *
++ * 2000-06-10 Erik Bunce      Add initial poll support.
++ *
++ * 2000-08-22 Nicolas Pitre   Removed all DMA stuff. Now using the
++ *                            generic SA1100 DMA interface.
++ *
++ * 2000-11-30 Nicolas Pitre   - Validation of opened instances;
++ *                            - Power handling at open/release time instead
++ *                              of driver load/unload;
++ *
++ * 2001-06-03 Nicolas Pitre   Made this file a separate module, based on
++ *                            the former sa1100-uda1341.c driver.
++ *
++ * 2001-07-22 Nicolas Pitre   - added mmap() and realtime support
++ *                            - corrected many details to better comply
++ *                              with the OSS API
++ *
++ * 2001-10-19 Nicolas Pitre   - brought DMA registration processing
++ *                              into this module for better ressource
++ *                              management.  This also fixes a bug
++ *                              with the suspend/resume logic.
++ *
++ * 2003-04-04   Adapted for EP93xx I2S/Ac97 audio.
++ *
++ * 2004-04-23 Added support for multiple stereo streams.
++ *
++ * 2005-05-11 Manfred Gruber - Ported this from Cirrus Logic Virgo 1-4-3 release
++ *                             to Kernel 2.6.11.X
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/pm.h>
++#include <linux/errno.h>
++#include <linux/sound.h>
++#include <linux/soundcard.h>
++#include <linux/sysrq.h>
++#include <linux/delay.h>
++#include <linux/kernel_stat.h>
++#include <asm/arch/dma.h>
++#include <linux/dma-mapping.h>
++
++#include <asm/uaccess.h>
++//#include <asm/fiq.h>
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <asm/semaphore.h>
++#include <asm/arch/dma.h>
++#include <asm/arch/irqs.h>
++
++#include "ep93xx-audio.h"
++
++#undef DEBUG
++//#define DEBUG 1
++#ifdef DEBUG
++#define DPRINTK( fmt, arg... )  printk( fmt, ##arg )
++#else
++#define DPRINTK( fmt, arg... )
++#endif
++
++/* Mostly just prints what ioctls got called */
++//#define DEBUG 1
++#ifdef DEBUG
++#define DPRINTK_IOCTL( fmt, arg... )  printk( fmt, ##arg )
++#else
++#define DPRINTK_IOCTL( fmt, arg... )
++#endif
++
++/*
++ * Experiencing gaps in your audio?  Try upping the AUDIO_NBFRAGS_DEFAULT!
++ * Experiencing memory problems? Try lowering them. 
++ * DMA memory space is precious and rare on ARM.
++ * 
++ */
++
++//
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++#define AUDIO_NBFRAGS_DEFAULT 31
++#define AUDIO_FRAGSIZE_DEFAULT        65536
++#define AUDIO_NBFRAGS_MAX     31
++#else
++#ifdef CONFIG_SOUND_EP93XX_AC97
++// Values changed from KERNEL2.4
++#define AUDIO_NBFRAGS_DEFAULT 4
++#define AUDIO_FRAGSIZE_DEFAULT        8192    // max is 65536
++#define AUDIO_NBFRAGS_MAX     4
++#else
++#define AUDIO_NBFRAGS_DEFAULT 16
++#define AUDIO_FRAGSIZE_DEFAULT        32768   // max is 65536
++#define AUDIO_NBFRAGS_MAX     16
++#endif
++#endif
++
++/*
++ * NEXT_BUF
++ *
++ * Translates to:
++ *            stream->dma_buffer_index++;
++ *            stream->dma_buffer_index %= stream->nbfrags;
++ *            stream->dma_buffer = stream->buffers + stream->dma_buffer_index;
++ *
++ * So stream->dma_buffer always points to the stream->dma_buffer_index-nth element
++ * of stream->buffers.
++ */
++#define NEXT_BUF(_s_,_b_) { \
++      (_s_)->_b_##_index++; \
++      (_s_)->_b_##_index %= (_s_)->nbfrags; \
++      (_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_index; }
++
++#define AUDIO_ACTIVE(state)   ((state)->rd_ref || (state)->wr_ref)
++
++/* Function prototypes */
++static __inline__ int copy_to_user_with_conversion
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount);
++
++static __inline__ int copy_from_user_with_conversion
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount);
++
++static void audio_dma_start(struct audio_state_t *state,
++                          struct audio_stream_t *stream);
++static void audio_dma_pause(struct audio_state_t *state,
++                          struct audio_stream_t *stream);
++static void audio_prime_dma(struct audio_state_t *state,
++                          struct audio_stream_t *stream);
++
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++#define DMA_ADD_BUFFER                pio_add_buffer
++#define DMA_CONFIG            pio_config
++#define DMA_FLUSH             pio_flush
++#define DMA_FREE              pio_free
++#define DMA_GET_POSITION      pio_get_position
++#define DMA_PAUSE             pio_pause
++#define DMA_REMOVE_BUFFER     pio_remove_buffer
++#define DMA_REQUEST           pio_request
++#define DMA_START             pio_start
++#else
++#define DMA_ADD_BUFFER                ep93xx_dma_add_buffer
++#define DMA_CONFIG            ep93xx_dma_config
++#define DMA_FLUSH             ep93xx_dma_flush
++#define DMA_FREE              ep93xx_dma_free
++#define DMA_GET_POSITION      ep93xx_dma_get_position
++#define DMA_PAUSE             ep93xx_dma_pause
++#define DMA_REMOVE_BUFFER     ep93xx_dma_remove_buffer
++#define DMA_REQUEST           ep93xx_dma_request
++#define DMA_START             ep93xx_dma_start
++#endif
++
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++/*
++ * The maximum number of buffers accepted by the PIO interface.
++ */
++#define PIO_MAX_BUFFERS               32
++
++/*
++ * A convenienced macro to advance from one buffer to the next.
++ */
++#define PIO_NEXT(x)           (((x) + 1) % PIO_MAX_BUFFERS)
++
++/*
++ * A structure to remember information about a buffer.
++ */
++struct pio_buffer {
++      unsigned int source;
++      unsigned int pos;
++      unsigned int size;
++      int buf_id;
++};
++
++/*
++ * A structure to remember information about a stream.
++ */
++struct pio_stream {
++      int assigned;
++      struct pio_buffer queue[PIO_MAX_BUFFERS];
++      ep93xx_dma_dev_t device;
++      int first;
++      int cur;
++      int last;
++      int bytes;
++      int pause;
++      dma_callback callback;
++      unsigned int user_data;
++};
++
++/*
++ * The twelve streams that we can handle.
++ */
++static struct pio_stream pio_streams[12];
++
++/*
++ * Reference counts for the two interrupt handlers.
++ */
++static int pio_irq_ref_count[2];
++
++/*
++ * The registers that enable the three I2S transmitters.
++ */
++static const unsigned int i2s_txenable[3] = {
++      I2STX0En,
++      I2STX1En,
++      I2STX2En
++};
++
++/*
++ * The flag that indicates a FIFO full condition on the three I2S transmitters.
++ */
++static const unsigned int i2s_txflag[3] = {
++      TX0_FIFO_FULL,
++      TX1_FIFO_FULL,
++      TX2_FIFO_FULL
++};
++
++/*
++ * The register that contains the left channel data for the three I2S
++ * transmitters.
++ */
++static const unsigned int i2s_tx_lft[3] = {
++      I2STX0Lft,
++      I2STX1Lft,
++      I2STX2Lft
++};
++
++/*
++ * The register that contains the right channel data for the three I2S
++ * transmitters.
++ */
++static const unsigned int i2s_tx_rt[3] = {
++      I2STX0Rt,
++      I2STX1Rt,
++      I2STX2Rt
++};
++
++/*
++ * The registers that enable the three I2S receivers.
++ */
++static const unsigned int i2s_rxenable[3] = {
++      I2SRX0En,
++      I2SRX1En,
++      I2SRX2En
++};
++
++/*
++ * The flag that indicates a FIFO empty condition on the three I2S receivers.
++ */
++static const unsigned int i2s_rxflag[3] = {
++      RX0_FIFO_EMPTY,
++      RX1_FIFO_EMPTY,
++      RX2_FIFO_EMPTY
++};
++
++/*
++ * The register that contains the left channel data for the three I2S
++ * receivers.
++ */
++static const unsigned int i2s_rx_lft[3] = {
++      I2SRX0Lft,
++      I2SRX1Lft,
++      I2SRX2Lft
++};
++
++/*
++ * The register that contains the right channel data for the three I2S
++ * receivers.
++ */
++static const unsigned int i2s_rx_rt[3] = {
++      I2SRX0Rt,
++      I2SRX1Rt,
++      I2SRX2Rt
++};
++
++/*
++ * The registers that contain the status for the three AC'97 transceivers.
++ */
++static const unsigned int ac97_status[3] = {
++      AC97SR1,
++      AC97SR2,
++      AC97SR3
++};
++
++/*
++ * The registers that contain the audio data for the three AC'97 transceivers.
++ */
++static const unsigned int ac97_data[3] = {
++      AC97DR1,
++      AC97DR2,
++      AC97DR3
++};
++
++/*
++ * The registers that control the three AC'97 transmitters.
++ */
++static const unsigned int ac97_txctrl[3] = {
++      AC97TXCR1,
++      AC97TXCR2,
++      AC97TXCR3
++};
++
++/*
++ * The registers that control the three AC'97 receivers.
++ */
++static const unsigned int ac97_rxctrl[3] = {
++      AC97RXCR1,
++      AC97RXCR2,
++      AC97RXCR3
++};
++
++/*
++ * The descriptor for our FIQ handler.
++ */
++static struct fiq_handler fh = { NULL, "pio_audio", NULL, NULL };
++
++/*
++ * Stack space for our FIQ handler.
++ */
++static unsigned char fiq_stack[1024];
++
++/*
++ * References to the labels in the inline assembly.
++ */
++extern void i2s_fiq_begin;
++extern void i2s_fiq_end;
++extern void ac97_fiq_begin;
++extern void ac97_fiq_end;
++
++/*
++ * The FIQ handler for I2S audio.  This stub is copied into the vector area and
++ * simply calls the I2S interrupt handler.
++ */
++void pio_i2s_fiq_handler(void)
++{
++      __asm__ __volatile__("\n\
++i2s_fiq_begin:\n\
++              stmdb   r13!, {r0-r7, lr}\n\
++              ldr     r0, =pio_i2s_irq_handler\n\
++              mov     lr, pc\n\
++              mov     pc, r0\n\
++              ldmia   r13!, {r0-r7, lr}\n\
++              subs    pc, lr, #4\n\
++              .ltorg\n\
++i2s_fiq_end:");
++}
++
++/*
++ * The FIQ handler for AC'97 audio.  This stub is copied into the vector area
++ * and simply calls the AC'97 interrupt handler.
++ */
++void pio_ac97_fiq_handler(void)
++{
++      __asm__ __volatile__("\n\
++ac97_fiq_begin:\n\
++              stmdb   r13!, {r0-r7, lr}\n\
++              ldr     r0, =pio_ac97_irq_handler\n\
++              mov     lr, pc\n\
++              mov     pc, r0\n\
++              ldmia   r13!, {r0-r7, lr}\n\
++              subs    pc, lr, #4\n\
++              .ltorg\n\
++ac97_fiq_end:");
++}
++
++/*
++ * The interrupt handler for I2S audio.
++ */
++static void pio_i2s_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++{
++      struct pio_stream *p;
++      struct pio_buffer *b;
++      int idx;
++
++      /*
++       * Increment the count of interrupts.
++       */
++      kstat.irqs[smp_processor_id()][IRQ_SAI]++;
++
++      /*
++       * Loop through the three transmitters.
++       */
++      for (idx = 0; idx < 3; idx++) {
++              /*
++               * Do nothing if this transmitter is not enabled.
++               */
++              if (!inl(i2s_txenable[idx]))
++                      continue;
++
++              /*
++               * Get a pointer to this stream's structure.
++               */
++              p = &pio_streams[idx];
++
++              /*
++               * Loop while the transmit FIFO is not full.
++               */
++              while (!(inl(I2SGlSts) & i2s_txflag[idx])) {
++                      /*
++                       * If the stream is not assigned, is paused, or has no
++                       * data, then write out silence.
++                       */
++                      if (!p->assigned || p->pause || (p->cur == p->last)) {
++                              outl(0, i2s_tx_lft[idx]);
++                              outl(0, i2s_tx_rt[idx]);
++                      } else {
++                              /*
++                               * Get a pointer to the current buffer.
++                               */
++                              b = &p->queue[p->cur];
++
++                              /*
++                               * Write out the next sample.
++                               */
++                              outl(*(unsigned long *)b->source,
++                                   i2s_tx_lft[idx]);
++                              outl(*(unsigned long *)(b->source + 4),
++                                   i2s_tx_rt[idx]);
++
++                              /*
++                               * Increment past the next sample.
++                               */
++                              b->source += 8;
++                              b->pos += 8;
++
++                              /*
++                               * See if the buffer has been consumed.
++                               */
++                              if (b->pos == b->size) {
++                                      /*
++                                       * Increment the count of bytes
++                                       * transmitted.
++                                       */
++                                      p->bytes += b->size;
++
++                                      /*
++                                       * Go to the next buffer.
++                                       */
++                                      p->cur = PIO_NEXT(p->cur);
++
++                                      /*
++                                       * Call the callback if there is one.
++                                       */
++                                      if (p->callback)
++                                              p->callback(NFB, p->device,
++                                                          p->user_data);
++                              }
++                      }
++              }
++      }
++
++      /*
++       * Loop through the three receivers.
++       */
++      for (idx = 0; idx < 3; idx++) {
++              /*
++               * Do nothing if this receiver is not enabled.
++               */
++              if (!inl(i2s_rxenable[idx]))
++                      continue;
++
++              /*
++               * Get a pointer to this stream's structure.
++               */
++              p = &pio_streams[idx + 3];
++
++              /*
++               * Loop while the receive FIFO is not empty.
++               */
++              while (!(inl(I2SGlSts) & i2s_rxflag[idx])) {
++                      /*
++                       * If the stream is not assigned, is paused, or has no
++                       * buffer space, then throw away the data.
++                       */
++                      if (!p->assigned || p->pause || (p->cur == p->last)) {
++                              inl(i2s_rx_lft[idx]);
++                              inl(i2s_rx_rt[idx]);
++                      } else {
++                              /*
++                               * Get a pointer to the current buffer.
++                               */
++                              b = &p->queue[p->cur];
++
++                              /*
++                               * Read in the next sample.
++                               */
++                              *(unsigned long *)b->source =
++                                  inl(i2s_rx_lft[idx]);
++                              *(unsigned long *)(b->source + 4) =
++                                  inl(i2s_rx_rt[idx]);
++
++                              /*
++                               * Increment past the next sample.
++                               */
++                              b->source += 8;
++                              b->pos += 8;
++
++                              /*
++                               * See if the buffer has been consumed.
++                               */
++                              if (b->pos == b->size) {
++                                      /*
++                                       * Increment the count of bytes
++                                       * received.
++                                       */
++                                      p->bytes += b->size;
++
++                                      /*
++                                       * Go to the next buffer.
++                                       */
++                                      p->cur = PIO_NEXT(p->cur);
++
++                                      /*
++                                       * Call the callback if there is one.
++                                       */
++                                      if (p->callback)
++                                              p->callback(NFB, p->device,
++                                                          p->user_data);
++                              }
++                      }
++              }
++      }
++
++      /*
++       * Clear any overrun or underrun conditions that may exist.
++       */
++      outl(0, I2SGlSts);
++}
++
++/*
++ * The interrupt handler for AC'97 audio.
++*/
++static void pio_ac97_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++{
++      struct pio_stream *p;
++      struct pio_buffer *b;
++      int idx, cm;
++
++      /*
++       * Increment the count of interrupts.
++       */
++      kstat.irqs[smp_processor_id()][IRQ_AAC]++;
++
++      /*
++       * Loop through the three transmitters.
++       */
++      for (idx = 0; idx < 3; idx++) {
++              /*
++               * Do nothing if this transmitter is not enabled.
++               */
++              if (!(inl(ac97_txctrl[idx]) & AC97TXCR_TEN))
++                      continue;
++
++              /*
++               * Get a pointer to this stream's structure.
++               */
++              p = &pio_streams[idx + 6];
++
++              /*
++               * See if this transmitter is in compact mode.
++               */
++              cm = inl(ac97_txctrl[idx]) & AC97TXCR_CM;
++
++              /*
++               * Loop while the transmit FIFO is not full.
++               */
++              while (!(inl(ac97_status[idx]) & AC97SR_TXFF)) {
++                      /*
++                       * If the stream is not assigned, is paused, or has no
++                       * data, then write out silence.
++                       */
++                      if (!p->assigned || p->pause || (p->cur == p->last)) {
++                              outl(0, ac97_data[idx]);
++                              if (!cm)
++                                      outl(0, ac97_data[idx]);
++                      } else {
++                              /*
++                               * Get a pointer to the current buffer.
++                               */
++                              b = &p->queue[p->cur];
++
++                              /*
++                               * Write out the next sample.
++                               */
++                              outl(*(unsigned long *)b->source,
++                                   ac97_data[idx]);
++
++                              /*
++                               * Increment past the next sample.
++                               */
++                              b->source += 4;
++                              b->pos += 4;
++
++                              /*
++                               * Write another sample if we are not in
++                               * compact mode.
++                               */
++                              if (!cm) {
++                                      outl(*(unsigned long *)b->source,
++                                           ac97_data[idx]);
++                                      b->source += 4;
++                                      b->pos += 4;
++                              }
++
++                              /*
++                               * See if the buffer has been consumed.
++                               */
++                              if (b->pos == b->size) {
++                                      /*
++                                       * Increment the count of bytes
++                                       * transmitted.
++                                       */
++                                      p->bytes += b->size;
++
++                                      /*
++                                       * Go to the next buffer.
++                                       */
++                                      p->cur = PIO_NEXT(p->cur);
++
++                                      /*
++                                       * Call the callback if there is one.
++                                       */
++                                      if (p->callback)
++                                              p->callback(NFB, p->device,
++                                                          p->user_data);
++                              }
++                      }
++              }
++      }
++
++      /*
++       * Loop through the three receivers.
++       */
++      for (idx = 0; idx < 3; idx++) {
++              /*
++               * Do nothing if this receiver is not enabled.
++               */
++              if (!(inl(ac97_rxctrl[idx]) & AC97RXCR_REN))
++                      continue;
++
++              /*
++               * Get a pointer to this stream's structure.
++               */
++              p = &pio_streams[idx + 9];
++
++              /*
++               * See if this receiver is in compact mode.
++               */
++              cm = inl(ac97_rxctrl[idx]) & AC97RXCR_CM;
++
++              /*
++               * Loop while the receive FIFO is not empty.
++               */
++              while (!(inl(ac97_status[idx]) & AC97SR_RXFE)) {
++                      /*
++                       * If the stream is not assigned, is paused, or has no
++                       * buffer space, then throw away the data.
++                       */
++                      if (!p->assigned || p->pause || (p->cur == p->last)) {
++                              inl(ac97_data[idx]);
++                              if (!cm)
++                                      inl(ac97_data[idx]);
++                      } else {
++                              /*
++                               * Get a pointer to the current buffer.
++                               */
++                              b = &p->queue[p->cur];
++
++                              /*
++                               * Read in the next sample.
++                               */
++                              *(unsigned long *)b->source =
++                                  inl(ac97_data[idx]);
++
++                              /*
++                               * Increment past the next sample.
++                               */
++                              b->source += 4;
++                              b->pos += 4;
++
++                              /*
++                               * Read another sample if we are not in compact
++                               * mode.
++                               */
++                              if (!cm) {
++                                      *(unsigned long *)b->source =
++                                          inl(ac97_data[idx]);
++                                      b->source += 4;
++                                      b->pos += 4;
++                              }
++
++                              /*
++                               * See if the buffer has been consumed.
++                               */
++                              if (b->pos == b->size) {
++                                      /*
++                                       * Increment the count of bytes
++                                       * received.
++                                       */
++                                      p->bytes += b->size;
++
++                                      /*
++                                       * Go to the next buffer.
++                                       */
++                                      p->cur = PIO_NEXT(p->cur);
++
++                                      /*
++                                       * Call the callback if there is one.
++                                       */
++                                      if (p->callback)
++                                              p->callback(NFB, p->device,
++                                                          p->user_data);
++                              }
++                      }
++              }
++      }
++}
++
++/*
++ * Add a buffer to a PIO stream.
++ */
++static int
++pio_add_buffer(int handle, unsigned int source, unsigned int dest,
++             unsigned int size, unsigned int last, unsigned int buf_id)
++{
++      struct pio_stream *p;
++      struct pio_buffer *b;
++
++      /*
++       * Get a pointer to this stream's structure.
++       */
++      p = &pio_streams[handle];
++
++      /*
++       * Fail if there is not space for another buffer.
++       */
++      if (PIO_NEXT(p->last) == p->first)
++              return -1;
++
++      /*
++       * Get a pointer to the next buffer.
++       */
++      b = &p->queue[p->last];
++
++      /*
++       * Save the information about this buffer.
++       */
++      b->source = (unsigned int)phys_to_virt(source);
++      b->pos = 0;
++      b->size = size;
++      b->buf_id = buf_id;
++
++      /*
++       * Increment the last pointer.
++       */
++      p->last = PIO_NEXT(p->last);
++
++      /*
++       * Success.
++       */
++      return 0;
++}
++
++/*
++ * Configure a PIO stream.
++ */
++static int
++pio_config(int handle, unsigned int flags_m2p, unsigned int flags_m2m,
++         dma_callback callback, unsigned int user_data)
++{
++      struct pio_stream *p;
++
++      /*
++       * Get a pointer to this stream's structure.
++       */
++      p = &pio_streams[handle];
++
++      /*
++       * This puts the stream into pause mode.
++       */
++      p->pause = 1;
++
++      /*
++       * Save the callback function information.
++       */
++      p->callback = callback;
++      p->user_data = user_data;
++
++      /*
++       * Success.
++       */
++      return 0;
++}
++
++/*
++ * Flush all data from a PIO stream.
++ */
++static int pio_flush(int handle)
++{
++      struct pio_stream *p;
++
++      /*
++       * Get a pointer to this stream's structure.
++       */
++      p = &pio_streams[handle];
++
++      /*
++       * Disable interrupts.
++       */
++      clf();
++
++      /*
++       * Blast all buffer information from this stream.
++       */
++      p->first = 0;
++      p->cur = 0;
++      p->last = 0;
++      p->bytes = 0;
++
++      /*
++       * Enable interrupts.
++       */
++      stf();
++
++      /*
++       * Success.
++       */
++      return 0;
++}
++
++/*
++ * Free a PIO stream.
++ */
++static int pio_free(int handle)
++{
++      /*
++       * See if this is a I2S or AC'97 stream.
++       */
++      if (handle < 6) {
++              /*
++               * Decrement the I2S reference count.
++               */
++              pio_irq_ref_count[0]--;
++
++              /*
++               * See if the reference count is now zero.
++               */
++              if (pio_irq_ref_count[0] == 0) {
++                      /*
++                       * Make the I2S interrupt an IRQ instead of a FIQ.
++                       */
++                      outl(inl(VIC1INTSELECT) & ~(1 << (IRQ_SAI - 32)),
++                           VIC1INTSELECT);
++
++                      /*
++                       * Disable I2S interrupts in the I2S block.
++                       */
++                      outl(0, I2STXCtrl);
++                      outl(0, I2SRXCtrl);
++
++                      /*
++                       * Release the I2S interrupt.
++                       */
++                      free_irq(IRQ_SAI, (void *)&pio_i2s_irq_handler);
++
++                      /*
++                       * Release the FIQ.
++                       */
++                      release_fiq(&fh);
++              }
++      } else {
++              /*
++               * Decrement the AC'97 reference count.
++               */
++              pio_irq_ref_count[1]--;
++
++              /*
++               * See if the reference count is now zero.
++               */
++              if (pio_irq_ref_count[1] == 0) {
++                      /*
++                       * Make the AC'97 interrupt an IRQ instead of a FIQ.
++                       */
++                      outl(inl(VIC0INTSELECT) & ~(1 << IRQ_AAC),
++                           VIC0INTSELECT);
++
++                      /*
++                       * Release the AC'97 interrupt.
++                       */
++                      free_irq(IRQ_AAC, (void *)&pio_ac97_irq_handler);
++
++                      /*
++                       * Release the FIQ.
++                       */
++                      release_fiq(&fh);
++              }
++      }
++
++      /*
++       * Mark this stream as unassigned.
++       */
++      pio_streams[handle].assigned = 0;
++
++      /*
++       * Success.
++       */
++      return 0;
++}
++
++/*
++ * Get the current position in a PIO stream.
++ */
++static int
++pio_get_position(int handle, unsigned int *buf_id, unsigned int *total,
++               unsigned int *current_frac)
++{
++      struct pio_stream *p;
++      struct pio_buffer *b;
++
++      /*
++       * Get a pointer to this stream's structure.
++       */
++      p = &pio_streams[handle];
++
++      /*
++       * Disable interrupts.
++       */
++      clf();
++
++      /*
++       * Get a pointer to the current buffer.
++       */
++      b = &p->queue[p->cur];
++
++      /*
++       * If the buffer is is being requested, then return it.
++       */
++      if (buf_id)
++              *buf_id = b->buf_id;
++
++      /*
++       * If the total bytes transferred is being requested, then return it.
++       */
++      if (total)
++              *total = p->bytes;
++
++      /*
++       * If the bytes transferred from the current buffer is being requested,
++       * then return it.
++       */
++      if (current_frac)
++              *current_frac = b->size - b->pos;
++
++      /*
++       * Enable interrupts.
++       */
++      stf();
++
++      /*
++       * Success.
++       */
++      return 0;
++}
++
++/*
++ * Pause a PIO stream.
++ */
++static int pio_pause(int handle, unsigned int channels, unsigned int *handles)
++{
++      struct pio_stream *p;
++
++      /*
++       * Get a pointer to this stream's structure.
++       */
++      p = &pio_streams[handle];
++
++      /*
++       * Pause the stream.
++       */
++      p->pause = 1;
++
++      /*
++       * Success.
++       */
++      return 0;
++}
++
++/*
++ * Remove a consumed buffer from a PIO stream.
++ */
++static int pio_remove_buffer(int handle, unsigned int *buf_id)
++{
++      struct pio_stream *p;
++
++      /*
++       * Get a pointer to this stream's structure.
++       */
++      p = &pio_streams[handle];
++
++      /*
++       * Fail if there are not consumed buffers.
++       */
++      if (p->first == p->cur)
++              return -1;
++
++      /*
++       * Return the ID of the next fully consumed buffer.
++       */
++      *buf_id = p->queue[p->first].buf_id;
++
++      /*
++       * Increment the first pointer.
++       */
++      p->first = PIO_NEXT(p->first);
++
++      /*
++       * Success.
++       */
++      return 0;
++}
++
++/*
++ * Request a PIO stream.
++ */
++static int
++pio_request(int *handle, const char *device_id, ep93xx_dma_dev_t device)
++{
++      struct pio_stream *p;
++      struct pt_regs regs;
++      int idx, error;
++
++      /*
++       * Get the stream index from the DMA device we are emulating.
++       */
++      switch (device) {
++      case DMATx_I2S1:
++              idx = 0;
++              break;
++      case DMATx_I2S2:
++              idx = 1;
++              break;
++      case DMATx_I2S3:
++              idx = 2;
++              break;
++      case DMARx_I2S1:
++              idx = 3;
++              break;
++      case DMARx_I2S2:
++              idx = 4;
++              break;
++      case DMARx_I2S3:
++              idx = 5;
++              break;
++      case DMATx_AAC1:
++              idx = 6;
++              break;
++      case DMATx_AAC2:
++              idx = 7;
++              break;
++      case DMATx_AAC3:
++              idx = 8;
++              break;
++      case DMARx_AAC1:
++              idx = 9;
++              break;
++      case DMARx_AAC2:
++              idx = 10;
++              break;
++      case DMARx_AAC3:
++              idx = 11;
++              break;
++      default:
++              return -ENODEV;
++      }
++
++      /*
++       * Get a pointer to this stream's structure.
++       */
++      p = &pio_streams[idx];
++
++      /*
++       * Fail if this stream is already assigned.
++       */
++      if (p->assigned)
++              return -EBUSY;
++
++      /*
++       * Initialize this stream.
++       */
++      memset(p->queue, 0, sizeof(p->queue));
++      p->device = device;
++      p->first = 0;
++      p->cur = 0;
++      p->last = 0;
++      p->bytes = 0;
++      p->pause = 0;
++      p->callback = 0;
++      p->user_data = 0;
++
++      /*
++       * Mark this stream as assigned.
++       */
++      p->assigned = 1;
++
++      /*
++       * See if this is a I2S or AC'97 stream.
++       */
++      if (idx < 6) {
++              /*
++               * If there is already a AC'97 stream in use, then do not allow
++               * I2S streams.
++               */
++              if (pio_irq_ref_count[1])
++                      return -EBUSY;
++
++              /*
++               * See if there is another I2S stream.
++               */
++              if (pio_irq_ref_count[0] == 0) {
++                      /*
++                       * Claim the FIQ handler.
++                       */
++                      if (claim_fiq(&fh))
++                              return -EBUSY;
++
++                      /*
++                       * Request the I2S interrupt.
++                       */
++                      error = request_irq(IRQ_SAI, pio_i2s_irq_handler,
++                                          SA_INTERRUPT, "i2s",
++                                          (void *)&pio_i2s_irq_handler);
++                      if (error) {
++                              release_fiq(&fh);
++                              return error;
++                      }
++
++                      /*
++                       * Set the FIQ mode registers.
++                       */
++                      regs.ARM_sp = (long)fiq_stack + sizeof(fiq_stack);
++                      set_fiq_regs(&regs);
++
++                      /*
++                       * Set the FIQ handler.
++                       */
++                      set_fiq_handler(&i2s_fiq_begin,
++                                      &i2s_fiq_end - &i2s_fiq_begin);
++
++                      /*
++                       * Make the I2S interrupt a FIQ instead of an IRQ.
++                       */
++                      outl(inl(VIC1INTSELECT) | (1 << (IRQ_SAI - 32)),
++                           VIC1INTSELECT);
++
++                      /*
++                       * Enable transmit half empty and receive half full
++                       * interrupts in the I2S block.
++                       */
++                      outl(2, I2STXCtrl);
++                      outl(2, I2SRXCtrl);
++              }
++
++              /*
++               * Increment the I2S interrupt reference count.
++               */
++              pio_irq_ref_count[0]++;
++      } else {
++              /*
++               * If there is already a I2S stream in use, then do not allow
++               * AC'97 streams.
++               */
++              if (pio_irq_ref_count[0])
++                      return -EBUSY;
++
++              /*
++               * See if there is another AC'97 stream.
++               */
++              if (pio_irq_ref_count[1] == 0) {
++                      /*
++                       * Claim the FIQ handler.
++                       */
++                      if (claim_fiq(&fh))
++                              return -EBUSY;
++
++                      /*
++                       * Request the AC'97 interrupt.
++                       */
++                      error = request_irq(IRQ_AAC, pio_ac97_irq_handler,
++                                          SA_INTERRUPT, "ac-97",
++                                          (void *)&pio_ac97_irq_handler);
++                      if (error) {
++                              release_fiq(&fh);
++                              return error;
++                      }
++
++                      /*
++                       * Set the FIQ mode registers.
++                       */
++                      regs.ARM_sp = (long)fiq_stack + sizeof(fiq_stack);
++                      set_fiq_regs(&regs);
++
++                      /*
++                       * Set the FIQ handler.
++                       */
++                      set_fiq_handler(&ac97_fiq_begin,
++                                      &ac97_fiq_end - &ac97_fiq_begin);
++
++                      /*
++                       * Make the AC'97 interrupt a FIQ instead of an IRQ.
++                       */
++                      outl(inl(VIC0INTSELECT) | (1 << IRQ_AAC),
++                           VIC0INTSELECT);
++              }
++
++              /*
++               * Increment the AC'97 interrupt reference count.
++               */
++              pio_irq_ref_count[1]++;
++      }
++
++      /*
++       * Return a handle to this stream.
++       */
++      *handle = idx;
++
++      /*
++       * Success.
++       */
++      return 0;
++}
++
++/*
++ * Start a PIO stream.
++ */
++static int pio_start(int handle, unsigned int channels, unsigned int *handles)
++{
++      struct pio_stream *p;
++
++      /*
++       * Get a pointer to this stream's structure.
++       */
++      p = &pio_streams[handle];
++
++      /*
++       * Start the stream.
++       */
++      p->pause = 0;
++
++      /*
++       * Success.
++       */
++      return 0;
++}
++#endif
++
++/*
++ *  calculate_dma2usr_ratio_etc()
++ *
++ *  For audio playback, we convert samples of arbitrary format to be 32 bit
++ *  for our hardware. We're scaling a user buffer to a dma buffer.  So when
++ *  report byte counts, we scale them acording to the ratio of DMA sample
++ *  size to user buffer sample size.  When we report # of DMA fragments,
++ *  we don't scale that.  So:
++ *   - The fragment size the app sees  = (stream->fragsize/stream->dma2usr_ratio)
++ *   - The # of fragments the app sees = stream->nbfrags
++ *
++ *    User sample type can be stereo/mono/8/16/32 bit.
++ *  DMA sample type will be either CM (compact mode) where two 16 bit
++ *  samples together in a 32 bit word become a stereo sample or non-CM
++ *  where each channel gets a 32 bit word.
++ *
++ *  Any time usr sample type changes, we need to call this function.
++ *
++ *  Also adjust the size and number of dma fragments if sample size changed.
++ *
++ *  Input format       Input sample     Output sample size    ratio (out:in)
++ *  bits   channels    size (bytes)   CM   non-CM          CM   non-CM
++ *   8       mono          1          4      8            4:1   8:1
++ *   8      stereo         2          4      8            2:1   4:1
++ *   16      mono          2          4      8            2:1   4:1
++ *   16     stereo         4          4      8            1:1   2:1
++ *
++ *   24      mono          3          4      8             X    8:3 not a real case
++ *   24     stereo         6          4      8             X    8:6 not a real case
++ *   32      mono          4          4      8             X    2:1
++ *   32     stereo         8          4      8             X    1:1
++ *
++ */
++static void calculate_dma2usr_ratio_etc(struct audio_stream_t *stream)
++{
++      unsigned int dma_sample_size, user_sample_size;
++
++      if (stream->bCompactMode)
++              dma_sample_size = 4;    /* each stereo sample is 2 * 16 bits */
++      else
++              dma_sample_size = 8;    /* each stereo sample is 2 * 32 bits */
++
++      if (stream->audio_num_channels != 1) {
++              // If stereo 16 bit, user sample is 4 bytes.
++              // If stereo  8 bit, user sample is 2 bytes.
++              user_sample_size = stream->audio_stream_bitwidth / 4;
++      } else {
++              // If mono 16 bit, user sample is 2 bytes.
++              // If mono  8 bit, user sample is 1 bytes.
++              user_sample_size = stream->audio_stream_bitwidth / 8;
++      }
++
++      /*
++       * dma2usr_ratio = (4 or 8) / (4, 2, or 1) = 8, 4, 2, or 1
++       */
++      stream->dma2usr_ratio = dma_sample_size / user_sample_size;
++
++      DPRINTK(" samplesize: dma %d  user %d  dma/usr ratio  %d\n",
++              dma_sample_size, user_sample_size, stream->dma2usr_ratio);
++      DPRINTK
++          (" requested: fragsize %d  num frags %d  total bytes %d  total samples %d\n",
++           stream->requested_fragsize, stream->requested_nbfrags,
++           stream->requested_fragsize * stream->requested_nbfrags,
++           (stream->requested_fragsize * stream->requested_nbfrags) /
++           user_sample_size);
++      DPRINTK
++          (" usr      : fragsize %d  num frags %d  total bytes %d  total samples %d\n",
++           (stream->fragsize / stream->dma2usr_ratio), stream->nbfrags,
++           stream->fragsize * stream->nbfrags / stream->dma2usr_ratio,
++           (stream->fragsize * stream->nbfrags) / (stream->dma2usr_ratio *
++                                                   user_sample_size));
++      DPRINTK
++          (" dma:       fragsize %d  num frags %d  total bytes %d  total samples %d\n",
++           stream->fragsize, stream->nbfrags,
++           stream->fragsize * stream->nbfrags,
++           (stream->fragsize * stream->nbfrags) / dma_sample_size);
++
++}
++
++/*
++ * audio_deallocate_buffers
++ *
++ * This function frees all buffers
++ */
++static void audio_deallocate_buffers(struct audio_state_t *state,
++                                   struct audio_stream_t *stream)
++{
++      int frag, i;
++
++      DPRINTK("EP93xx - audio_deallocate_buffers\n");
++
++      /* ensure DMA won't run anymore */
++      audio_dma_pause(state, stream);
++      stream->active = 0;
++      stream->stopped = 0;
++
++      for (i = 0; i < stream->NumDmaChannels; i++)
++              DMA_FLUSH(stream->dmahandles[i]);
++
++      if (stream->buffers) {
++              for (frag = 0; frag < stream->nbfrags; frag++) {
++                      if (!stream->buffers[frag].master) {
++                              continue;
++                      }
++                      // KERNEL2.4
++                      //consistent_free(stream->buffers[frag].start,
++                      //              stream->buffers[frag].master,
++                      //              stream->buffers[frag].dma_addr);
++                      dma_free_coherent(NULL, stream->buffers[frag].master,
++                                        stream->buffers[frag].start,
++                                        stream->buffers[frag].dma_addr);
++
++              }
++
++              /*
++               * Free the space allocated to the array of dma_buffer structs.
++               */
++              kfree(stream->buffers);
++              stream->buffers = NULL;
++      }
++
++      stream->buffered_bytes_to_play = 0;
++      stream->dma_buffer_index = 0;
++      stream->dma_buffer = NULL;
++      stream->bytecount = 0;
++      stream->getptrCount = 0;
++      stream->fragcount = 0;
++
++      DPRINTK("EP93xx - audio_deallocate_buffers - EXIT\n");
++}
++
++/*
++ * audio_allocate_buffers
++ *
++ * This function allocates the buffer structure array and buffer data space
++ * according to the current number of fragments and fragment size.
++ * Note that the output_stream and input_stream structs are allocated
++ * in ep93xx-ac97.c or ep93xx-i2s.c.
++ */
++static int audio_allocate_buffers(struct audio_state_t *state,
++                                struct audio_stream_t *stream)
++{
++      int frag;
++      int dmasize = 0;
++      char *dmabuf = NULL;
++      dma_addr_t dmaphys = 0;
++      int buf_num = 0;
++
++      if (stream->buffers)
++              return -EBUSY;
++
++      DPRINTK("EP93xx audio_allocate_buffers\n");
++
++      /*
++       * Allocate space for the array of struct audio_buf_t structs.
++       */
++      stream->buffers = (struct audio_buf_t *)
++          kmalloc(sizeof(struct audio_buf_t) * stream->nbfrags, GFP_KERNEL);
++
++      if (!stream->buffers) {
++              DPRINTK("ep93xx-audio: unable to allocate audio memory\n ");
++              audio_deallocate_buffers(state, stream);
++              return -ENOMEM;
++      }
++
++      /*
++       * If the audio app hasn't requested a specific fragsize and nbfrags,
++       * we stay with our default.
++       */
++      if ((stream->requested_fragsize != 0)
++          && (stream->requested_nbfrags != 0)) {
++              /*
++               * Adjust the fragsize to take into account how big actual samples in
++               * the dma buffer are.  Max dma buf size is 64K.
++               */
++              stream->fragsize =
++                  stream->requested_fragsize * stream->dma2usr_ratio;
++      }
++
++      if (stream->fragsize > 65536)
++              stream->fragsize = 65536;
++      if (stream->fragsize < 8192)
++              stream->fragsize = 8192;
++
++      /*
++       * Adjust num of frags so we have as many samples of buffer as were requested
++       * even if the fragment size changed.
++       */
++      if ((stream->requested_fragsize != 0)
++          && (stream->requested_nbfrags != 0)) {
++              stream->nbfrags =
++                  (stream->requested_fragsize * stream->requested_nbfrags *
++                   stream->dma2usr_ratio)
++                  / stream->fragsize;
++      }
++
++      if (stream->nbfrags < 2)
++              stream->nbfrags = 2;
++      if (stream->nbfrags > AUDIO_NBFRAGS_MAX)
++              stream->nbfrags = AUDIO_NBFRAGS_MAX;
++
++      memset(stream->buffers, 0,
++             sizeof(struct audio_buf_t) * stream->nbfrags);
++
++      /*
++       * Let's allocate non-cached memory for DMA buffers.
++       * We try to allocate all memory at once.
++       * If this fails (a common reason is memory fragmentation),
++       * then we allocate more smaller buffers.
++       */
++      for (frag = 0; frag < stream->nbfrags; frag++) {
++              struct audio_buf_t *dma_buffer = &stream->buffers[frag];
++
++              if (!dmasize) {
++                      /*
++                       * First try to allocate enough for all the frags that
++                       * don't yet have memory allocated.
++                       */
++                      dmasize = (stream->nbfrags - frag) * stream->fragsize;
++                      do {
++                              // GRM
++                              //dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,
++                              //                        dmasize, &dmaphys);
++                              dmabuf = dma_alloc_coherent(NULL,
++                                                          dmasize, &dmaphys,
++                                                          GFP_KERNEL |
++                                                          GFP_DMA);
++
++                              /*
++                               * If that fails, try to allocate a chunk of memory
++                               * that is one less fragment is size.
++                               */
++                              if (!dmabuf)
++                                      dmasize -= stream->fragsize;
++
++                              /*
++                               * Keep trying but the minimum we'll attempt is one
++                               * fragment.  If we can't even get that, give up.
++                               */
++                      } while (!dmabuf && dmasize);
++
++                      /*
++                       * If we do fail to allocate enough for all the frags,
++                       * deallocate whatever we did get and quit.
++                       */
++                      if (!dmabuf) {
++                              DPRINTK
++                                  ("ep93xx-audio: unable to allocate audio memory\n ");
++                              audio_deallocate_buffers(state, stream);
++                              return -ENOMEM;
++                      }
++
++                      DPRINTK
++                          ("EP93xx allocated %d bytes:  dmabuf=0x%08x  dmaphys=0x%08x\n",
++                           dmasize, (int)dmabuf, (int)dmaphys);
++
++                      /*
++                       * Success!      Save the size of this chunk to use when we deallocate it.
++                       */
++                      dma_buffer->master = dmasize;
++                      memzero(dmabuf, dmasize);
++              }
++
++              /*
++               * Save the start address of the dma_buffer fragment.
++               * We know the size of the fragment is fragsize.
++               */
++              dma_buffer->start = dmabuf;
++              dma_buffer->dma_addr = dmaphys;
++              dma_buffer->stream = stream;
++              dma_buffer->size = 0;
++              dma_buffer->sent = 0;
++              dma_buffer->num = buf_num++;
++
++              dma_buffer->owner = 0;
++
++              /*
++               * Now if we only allocated the minimal one frag of space, the
++               * dmasize will be ==0 after this subtraction so it will allocate more
++               * for the next frag.  Otherwise, the next time(s) thru this for loop
++               * will dole out frag sized pieces of this big master chunk.
++               */
++              dmabuf += stream->fragsize;
++              dmaphys += stream->fragsize;
++              dmasize -= stream->fragsize;
++      }
++
++      /*
++       * Initialize the stream.
++       */
++      stream->buffered_bytes_to_play = 0;
++      stream->dma_buffer_index = 0;   /* Init the current buffer index.                       */
++      stream->dma_buffer = &stream->buffers[0];       /* Point dma_buffer to the current buffer struct.       */
++      stream->bytecount = 0;
++      stream->getptrCount = 0;
++      stream->fragcount = 0;
++
++      DPRINTK("EP93xx audio_allocate_buffers -- exit SUCCESS\n");
++      return 0;
++
++}
++
++/*
++ * audio_reset_buffers
++ *
++ * This function stops and flushes the dma, gets all buffers back
++ * from the DMA driver and resets them ready to be used again.
++ */
++static void audio_reset_buffers(struct audio_state_t *state,
++                              struct audio_stream_t *stream)
++{
++      int frag, i;
++
++      audio_dma_pause(state, stream);
++      stream->active = 0;
++      stream->stopped = 0;
++
++      for (i = 0; i < stream->NumDmaChannels; i++)
++              DMA_FLUSH(stream->dmahandles[i]);
++
++      if (stream->buffers) {
++              for (frag = 0; frag < stream->nbfrags; frag++) {
++                      struct audio_buf_t *dma_buffer = &stream->buffers[frag];
++                      dma_buffer->size = 0;
++                      dma_buffer->sent = 0;
++                      dma_buffer->owner = 0;
++              }
++      }
++
++      stream->buffered_bytes_to_play = 0;
++      stream->bytecount = 0;
++      stream->getptrCount = 0;
++      stream->fragcount = 0;
++}
++
++/*
++ * DMA callback functions
++ */
++static void audio_dma_tx_callback
++    (ep93xx_dma_int_t DMAInt, ep93xx_dma_dev_t device, unsigned int user_data) {
++      unsigned int buf_id;
++      int handle, i;
++
++      struct audio_state_t *state = (struct audio_state_t *)user_data;
++      struct audio_stream_t *stream = state->output_stream;
++
++      /* DPRINTK( "audio_dma_tx_callback - %s\n", stream->devicename ); */
++
++      /*
++       * Get the DMA handle that corresponds to the dma channel
++       * that needs servicing.  A multichannel audio stream will
++       * have a DMA handle for each stereo pair that it uses.
++       */
++      for (i = 0;
++           (i < stream->NumDmaChannels) && (stream->dmachannel[i] != device);
++           i++) ;
++      handle = stream->dmahandles[i];
++
++      if (stream->mapped) {
++              /*
++               * If we are mapped, get one dma buffer back and recycle it.
++               */
++              if (DMA_REMOVE_BUFFER(handle, &buf_id) >= 0) {
++                      struct audio_buf_t *dma_buffer =
++                          (struct audio_buf_t *)buf_id;
++
++                      /*      DPRINTK( "audio_dma_tx_callback  - got dma buffer index=%d\n", buf_id); */
++
++                      /* Accounting */
++                      stream->buffered_bytes_to_play -= dma_buffer->size;
++
++                      /* bytecount and fragcount will overflow */
++                      stream->bytecount += dma_buffer->size;
++                      if (stream->bytecount < 0)
++                              stream->bytecount = 0;
++
++                      stream->fragcount++;
++                      if (stream->fragcount < 0)
++                              stream->fragcount = 0;
++
++                      dma_buffer->size = 0;
++
++                      /* Recycle dma buffer */
++                      dma_buffer->size = stream->fragsize;
++
++                      DMA_ADD_BUFFER(handle,  /* dma instance                 */
++                                     (unsigned int)dma_buffer->dma_addr,      /* source           */
++                                     0,       /* dest                                 */
++                                     stream->fragsize,        /* size                                 */
++                                     0,       /* is the last chunk?   */
++                                     (unsigned int)dma_buffer);       /* buf id                          */
++
++                      dma_buffer->sent = 1;
++              }
++      } else {
++              /*
++               * Get all buffers that are free'ed back and clear their semephores.
++               */
++              while (DMA_REMOVE_BUFFER(handle, &buf_id) >= 0) {
++                      struct audio_buf_t *dma_buffer =
++                          (struct audio_buf_t *)buf_id;
++
++                      /*      DPRINTK( "audio_dma_tx_callback  - got dma buffer index=%d\n", buf_id); */
++
++                      /* Accounting */
++                      stream->buffered_bytes_to_play -= dma_buffer->size;
++
++                      stream->bytecount += dma_buffer->size;
++                      if (stream->bytecount < 0)
++                              stream->bytecount = 0;
++
++                      stream->fragcount++;
++                      if (stream->fragcount < 0)
++                              stream->fragcount = 0;
++
++                      dma_buffer->size = 0;
++                      dma_buffer->sent = 0;
++
++                      /*
++                       * Release the semaphore on this dma_buffer.
++                       * If write is waiting on this dma_buffer then it can go
++                       * ahead and fill it and send it to the dma.
++                       */
++                      dma_buffer->owner = 0;
++              }
++      }
++
++      /* And any process polling on write. */
++      wake_up(&stream->wq);
++}
++
++static void audio_dma_rx_callback
++    (ep93xx_dma_int_t DMAInt, ep93xx_dma_dev_t device, unsigned int user_data) {
++      unsigned int buf_id;
++      int handle, i;
++
++      struct audio_state_t *state = (struct audio_state_t *)user_data;
++      struct audio_stream_t *stream = state->input_stream;
++
++      //DPRINTK("audio_dma_rx_callback\n");
++
++      /*
++       * Get the DMA handle that corresponds to the dma channel
++       * that needs servicing.  A multichannel audio stream will
++       * have a DMA handle for each stereo pair that it uses.
++       */
++      for (i = 0;
++           (i < stream->NumDmaChannels) && (stream->dmachannel[i] != device);
++           i++) ;
++      handle = stream->dmahandles[i];
++
++      /*
++       * Keep removing and recycling buffers as long as there are buffers
++       * to remove.
++       */
++      while (!DMA_REMOVE_BUFFER(handle, &buf_id)) {
++              struct audio_buf_t *dma_buffer = (struct audio_buf_t *)buf_id;
++
++              /* Accounting */
++              stream->bytecount += stream->fragsize;
++              if (stream->bytecount < 0)
++                      stream->bytecount = 0;
++
++              stream->fragcount++;
++              if (stream->fragcount < 0)
++                      stream->fragcount = 0;
++
++              /* Recycle dma buffer */
++              if (stream->mapped) {
++                      DMA_ADD_BUFFER(handle,  /* dma instance                 */
++                                     (unsigned int)dma_buffer->dma_addr,      /* source          */
++                                     0,       /* dest                                 */
++                                     stream->fragsize,        /* size                                 */
++                                     0,       /* is the last chunk?   */
++                                     (unsigned int)dma_buffer);       /* buf id                          */
++              } else {
++                      dma_buffer->size = stream->fragsize;
++                      dma_buffer->owner = 0;
++              }
++
++              /* And any process polling on write. */
++              wake_up(&stream->wq);
++      }
++}
++
++/*
++ * audio_sync
++ *
++ * Wait until the last byte written to this device has been played.
++ */
++static int audio_sync(struct file *file)
++{
++      struct audio_state_t *state =
++          (struct audio_state_t *)file->private_data;
++      struct audio_stream_t *stream = state->output_stream;
++      struct audio_buf_t *dma_buffer;
++      int buf_wait_index;
++
++      DPRINTK("audio_sync - enter\n");
++
++      if (!(file->f_mode & FMODE_WRITE) || !stream->buffers || stream->mapped) {
++              DPRINTK("audio_sync - exit immediately.\n");
++              return 0;
++      }
++
++      /*
++       * Send current dma buffer if it contains data and hasn't been sent.
++       */
++      dma_buffer = stream->dma_buffer;
++
++      if (dma_buffer->size && !dma_buffer->sent) {
++              DPRINTK("audio_sync -- SENDING BUFFER index=%d size=%d\n",
++                      stream->dma_buffer_index, dma_buffer->size);
++
++              while (dma_buffer->owner == 1)
++                      schedule();
++              dma_buffer->owner = 1;
++              DMA_ADD_BUFFER(stream->dmahandles[0],   /* dma instance                 */
++                             (unsigned int)dma_buffer->dma_addr,      /* source               */
++                             0,       /* dest                                 */
++                             dma_buffer->size,        /* size                                 */
++                             0,       /* is the last chunk?   */
++                             (unsigned int)dma_buffer);       /* dma_buffer id                                */
++              dma_buffer->sent = 1;
++              NEXT_BUF(stream, dma_buffer);
++      }
++
++      /*
++       * Let's wait for the last dma buffer we sent i.e. the one before the
++       * current dma_buffer_index.  When we acquire the semaphore, this means either:
++       * - DMA on the buffer completed or
++       * - the buffer was already free thus nothing else to sync.
++       */
++      buf_wait_index =
++          ((stream->nbfrags + stream->dma_buffer_index -
++            1) % stream->nbfrags);
++      dma_buffer = stream->buffers + buf_wait_index;
++
++      DPRINTK("audio_sync - waiting on down_interruptible\n");
++      while (dma_buffer->owner == 1) {
++              if (signal_pending(current))
++                      return -ERESTARTSYS;
++              schedule();
++      }
++
++      DPRINTK("audio_sync - EXIT\n");
++      return 0;
++}
++
++//static int iWriteCount = 0;
++
++/*
++ * Need to convert to 32 bit stereo format:
++ * 16 bit signed
++ * 16 bit unsigned
++ *  8 bit signed
++ *  8 bit unsigned
++ */
++static int audio_write
++    (struct file *file,
++     const char *user_buffer, size_t src_count, loff_t * ppos) {
++      const char *user_buffer_start = user_buffer;
++      struct audio_state_t *state =
++          (struct audio_state_t *)file->private_data;
++      struct audio_stream_t *stream = state->output_stream;
++      unsigned int dma_xfer_count, src_xfer_count, expanded_count;
++      int ret = 0;
++//      int i,j;
++
++      /* DPRINTK_IOCTL( "EP93xx - audio_write: count=%d\n", src_count ); */
++
++      // KERNEL2.4
++      /*if (ppos != &file->f_pos)
++         return -ESPIPE; */
++
++      if (stream->mapped)
++              return -ENXIO;
++
++      if (!access_ok(VERIFY_READ, user_buffer, src_count)) {
++              DPRINTK("access_ok failed for audio_write!!!!\n");
++              return -EFAULT;
++      }
++
++      /*
++       * Allocate dma buffers if we haven't already done so.
++       */
++      if (!stream->buffers && audio_allocate_buffers(state, stream))
++              return -ENOMEM;
++
++//      if( iWriteCount > 40 )
++//      {
++//              for( i=0; i<4 ; i++ )
++//              {
++//                      for( j=0; j<8 ; j++ )
++//                      {
++//                              printk("%02x ", user_buffer[(i*8)+j] );
++//                      }
++//                      printk("\n");
++//              }
++//              iWriteCount = 0;
++//      }
++//      iWriteCount++;
++
++      /*
++       * Stay in this loop until we have copied all of the file
++       * into user memory.
++       */
++      while (src_count > 0) {
++              struct audio_buf_t *dma_buffer = stream->dma_buffer;
++
++              /* Wait for a dma buffer to become free */
++              if (file->f_flags & O_NONBLOCK) {
++                      ret = -EAGAIN;
++                      if (dma_buffer->owner != 0)
++                              break;
++              } else {
++                      while (dma_buffer->owner == 1) {
++                              if (signal_pending(current))
++                                      return -ERESTARTSYS;
++                              schedule();
++                      }
++              }
++
++              /*
++               * Feed the current dma buffer (stream->dma_buffer)
++               * This involves expanding sample size from the user_buffer
++               * to be 32 bit stereo for our dma.
++               */
++
++              /*
++               * How much space is left in the current dma buffer?
++               *
++               * dma_xfer_count is # of bytes placed into the dma buffer
++               * where each sample is 8 bytes (4 bytes left, 4 bytes right)
++               * because that's what the I2S is set up for - 32 bit samples.
++               */
++              dma_xfer_count = stream->fragsize - dma_buffer->size;
++
++              /*
++               * user_buffer is src_count (bytes) of whatever format.
++               * How big will src_count be when sample size is expanded
++               * to 32 bit samples for our hardware?
++               */
++              expanded_count = src_count * stream->dma2usr_ratio;
++
++              /*
++               * See if we can fit all the remaining user_buffer in
++               * the current dma buffer...
++               */
++              if (dma_xfer_count > expanded_count)
++                      dma_xfer_count = expanded_count;
++
++              //DPRINTK( "EP93xx - audio_write: %d to dma_buffer # %d\n", dma_xfer_count, stream->dma_buffer_index );
++
++              src_xfer_count = copy_from_user_with_conversion(state,
++                                                              dma_buffer->
++                                                              start +
++                                                              dma_buffer->
++                                                              size,
++                                                              user_buffer,
++                                                              dma_xfer_count);
++              if (src_xfer_count <= 0)
++                      return -EFAULT;
++
++              /*
++               * Increment dma buffer pointer.
++               */
++              dma_buffer->size += dma_xfer_count;
++
++              /*
++               * Increment user_buffer pointer.
++               * Decrement the user_buffer size count.
++               */
++              user_buffer += src_xfer_count;
++              src_count -= src_xfer_count;
++
++              /*
++               * If we haven't already started the DMA start it.
++               * But don't start it if we are waiting on a trigger.
++               */
++              if (!stream->active && !stream->stopped) {
++                      stream->active = 1;
++                      audio_dma_start(state, stream);
++              }
++
++              /*
++               * Note that we've 'downed' the semiphore for this buffer.  But the
++               * dma driver doesn't know about it until we've added it to the DMA
++               * driver's buffer queue.  So let's do that now.
++               */
++              dma_buffer->owner = 1;
++              DMA_ADD_BUFFER(stream->dmahandles[0],   /* dma instance                 */
++                             (unsigned int)dma_buffer->dma_addr,      /* source           */
++                             0,       /* dest                                 */
++                             dma_buffer->size,        /* size                                 */
++                             0,       /* is the last chunk?   */
++                             (unsigned int)dma_buffer);       /* buf id                          */
++
++              /*
++               * Note that we added a buffer to play for the benefit of calculating
++               * ODELAY.
++               */
++              stream->buffered_bytes_to_play += dma_buffer->size;
++
++              /*
++               * Indicate that the dma buffer has been sent.  Not the same as the
++               * buffer's semiphore.
++               */
++              dma_buffer->sent = 1;
++
++              NEXT_BUF(stream, dma_buffer);
++      }
++
++      /*
++       * Return the number of bytes transferred.
++       */
++      if ((int)user_buffer - (int)user_buffer_start)
++              ret = (int)user_buffer - (int)user_buffer_start;
++
++/*    DPRINTK( "EP93xx - audio_write: return=%d\n", ret );*/
++      return ret;
++}
++
++/*
++ * audio_dma_start
++ *
++ * Our Ac97 has a specific start order that it likes.  Enable the
++ * Ac97 channel AFTER enabling DMA.  Our I2S is not so picky.
++ */
++void audio_dma_start(struct audio_state_t *state, struct audio_stream_t *stream)
++{
++      DMA_START(stream->dmahandles[0],
++                stream->NumDmaChannels, stream->dmahandles);
++
++      if (state->hw->hw_enable)
++              state->hw->hw_enable(stream);
++
++}
++
++/*
++ * audio_dma_pause
++ */
++void audio_dma_pause(struct audio_state_t *state, struct audio_stream_t *stream)
++{
++      DPRINTK("audio_dma_pause - enter\n");
++
++      DMA_PAUSE(stream->dmahandles[0],
++                stream->NumDmaChannels, stream->dmahandles);
++
++      if (state->hw->hw_disable)
++              state->hw->hw_disable(stream);
++
++      if (state->hw->hw_clear_fifo)
++              state->hw->hw_clear_fifo(stream);
++
++      DPRINTK("audio_dma_pause - EXIT\n");
++}
++
++static void audio_prime_dma(struct audio_state_t *state,
++                          struct audio_stream_t *stream)
++{
++      int i;
++
++      DPRINTK("audio_prime_dma\n");
++
++      /*
++       * If we haven't already started the DMA start it.
++       * But don't start it if we are waiting on a trigger.
++       */
++      if (!stream->active && !stream->stopped) {
++              stream->active = 1;
++              audio_dma_start(state, stream);
++      }
++
++      for (i = 0; i < stream->nbfrags; i++) {
++              struct audio_buf_t *dma_buffer = stream->dma_buffer;
++
++              dma_buffer->owner = 1;
++              DMA_ADD_BUFFER(stream->dmahandles[0],   /* dma instance                 */
++                             (unsigned int)dma_buffer->dma_addr,      /* source           */
++                             0,       /* dest                                 */
++                             stream->fragsize,        /* size                                 */
++                             0,       /* is the last chunk?   */
++                             (unsigned int)dma_buffer);       /* buf id                          */
++              NEXT_BUF(stream, dma_buffer);
++      }
++}
++
++/*
++ * audio_read
++ *
++ * Audio capture function.
++ */
++static int audio_read
++    (struct file *file, char *user_buffer, size_t count, loff_t * ppos) {
++      char *user_buffer_start = user_buffer;
++      struct audio_state_t *state =
++          (struct audio_state_t *)file->private_data;
++      struct audio_stream_t *stream = state->input_stream;
++      unsigned int user_buffer_xfer_count = 0, dma_buffer_xfer_count = 0;
++      int ret = 0;
++
++      DPRINTK("EP93xx - audio_read: count=%d\n", count);
++
++      // KERNEL2.4
++      /*if (ppos != &file->f_pos)
++         return -ESPIPE; */
++
++      if (stream->mapped)
++              return -ENXIO;
++
++      if (!access_ok(VERIFY_WRITE, user_buffer, count)) {
++              DPRINTK("access_ok failed for audio_read!!!!\n");
++              return -EFAULT;
++      }
++
++      if (!stream->active) {
++              if (!stream->buffers && audio_allocate_buffers(state, stream))
++                      return -ENOMEM;
++
++              audio_prime_dma(state, stream);
++      }
++
++      while (count > 0) {
++              /*
++               * Get the current buffer.
++               */
++              struct audio_buf_t *dma_buffer = stream->dma_buffer;
++
++              /*
++               * Wait for a dma buffer to become full
++               */
++              if (file->f_flags & O_NONBLOCK) {
++                      //DPRINTK("file->f_flags & O_NONBLOCK\n");
++                      ret = -EAGAIN;
++                      if (dma_buffer->owner != 0)
++                              break;
++              } else {
++                      while (dma_buffer->owner == 1) {
++                              if (signal_pending(current))
++                                      return -ERESTARTSYS;
++                              schedule();
++                      }
++              }
++
++              /*
++               * If this is the first buffer captured,
++               * dump the first 8 samples of the dma buffer.
++               */
++              if (stream->bFirstCaptureBuffer) {
++                      dma_buffer->size -= 64;
++                      stream->bFirstCaptureBuffer = 0;
++              }
++
++              /*
++               * How much user buffer would a whole DMA buffer fill?
++               */
++              user_buffer_xfer_count =
++                  dma_buffer->size / stream->dma2usr_ratio;
++
++              if (user_buffer_xfer_count > count)
++                      user_buffer_xfer_count = count;
++
++              dma_buffer_xfer_count =
++                  user_buffer_xfer_count * stream->dma2usr_ratio;
++
++              DPRINTK("dma_buffer: start=0x%08x fragsz=%d size=%d\n",
++                      (int)dma_buffer->start, (int)stream->fragsize,
++                      dma_buffer->size);
++
++              DPRINTK
++                  ("user_buffer=0x%08x  from=0x%08x  user_count=%d  dma_count=%d\n",
++                   (int)user_buffer,
++                   (int)dma_buffer->start + stream->fragsize -
++                   dma_buffer->size, user_buffer_xfer_count,
++                   dma_buffer_xfer_count);
++
++              if (copy_to_user_with_conversion(state,
++                                               user_buffer,
++                                               dma_buffer->start +
++                                               stream->fragsize -
++                                               dma_buffer->size,
++                                               user_buffer_xfer_count) <= 0)
++                      return -EFAULT;
++
++              dma_buffer->size -= dma_buffer_xfer_count;
++
++              user_buffer += user_buffer_xfer_count;
++              count -= user_buffer_xfer_count;
++
++              /*
++               * Grab data from the current dma buffer
++               */
++              //DPRINTK("Read: read %d bytes from %d.  dmabufsize=%d.  count=%d\n",
++              //                      user_buffer_xfer_count, stream->dma_buffer_index,
++              //                      dma_buffer->size, count);
++
++              /*
++               * If there's still data in this buffer to be read, release
++               * the semiphore and don't give it back yet.  We may come back
++               * and read from it in a minute when the app calls for another read.
++               */
++              if (dma_buffer->size > 0)
++                      break;
++
++              /* Make current dma buffer available for DMA again */
++              dma_buffer->owner = 1;
++              DMA_ADD_BUFFER(stream->dmahandles[0],   /* dma instance  */
++                             (unsigned int)dma_buffer->dma_addr,      /* source */
++                             0,       /* dest  */
++                             stream->fragsize,        /* size  */
++                             0,       /* the last chunk? */
++                             (unsigned int)dma_buffer);       /* buf id */
++
++              NEXT_BUF(stream, dma_buffer);
++      }
++
++      if ((int)user_buffer - (int)user_buffer_start)
++              ret = (int)user_buffer - (int)user_buffer_start;
++
++      //DPRINTK("EP93xx - audio_read: return=%d\n", ret);
++
++      return ret;
++}
++
++static int audio_mmap(struct file *file, struct vm_area_struct *vma)
++{
++      struct audio_state_t *state =
++          (struct audio_state_t *)file->private_data;
++      struct audio_stream_t *stream = 0;
++      unsigned long size, vma_addr;
++      int i, ret;
++
++      if (vma->vm_pgoff != 0)
++              return -EINVAL;
++
++      if (vma->vm_flags & VM_WRITE) {
++              if (!state->wr_ref)
++                      return -EINVAL;
++
++              stream = state->output_stream;
++      } else if (vma->vm_flags & VM_READ) {
++              if (!state->rd_ref)
++                      return -EINVAL;
++
++              stream = state->input_stream;
++      } else {
++              return -EINVAL;
++      }
++
++      if (stream->mapped)
++              return -EINVAL;
++
++      size = vma->vm_end - vma->vm_start;
++
++      if (size != stream->fragsize * stream->nbfrags)
++              return -EINVAL;
++
++      if (!stream->buffers && audio_allocate_buffers(state, stream))
++              return -ENOMEM;
++
++      vma_addr = vma->vm_start;
++
++      for (i = 0; i < stream->nbfrags; i++) {
++              struct audio_buf_t *dma_buffer = &stream->buffers[i];
++
++              if (!dma_buffer->master) {
++                      continue;
++              }
++              // KERNEL2.4
++              //ret = remap_page_range(vma_addr, dma_buffer->dma_addr, dma_buffer->master, vma->vm_page_prot);
++              ret =
++                  remap_pfn_range(vma, vma_addr, dma_buffer->dma_addr,
++                                  dma_buffer->master, vma->vm_page_prot);
++
++              if (ret)
++                      return ret;
++
++              vma_addr += dma_buffer->master;
++      }
++
++      stream->mapped = 1;
++
++      return 0;
++}
++
++static unsigned int audio_poll(struct file *file,
++                             struct poll_table_struct *wait)
++{
++      struct audio_state_t *state =
++          (struct audio_state_t *)file->private_data;
++      struct audio_stream_t *is = state->input_stream;
++      struct audio_stream_t *os = state->output_stream;
++      unsigned int mask = 0;
++      int i;
++
++      DPRINTK("EP93xx - audio_poll(): mode=%s%s\n",
++              (file->f_mode & FMODE_READ) ? "r" : "",
++              (file->f_mode & FMODE_WRITE) ? "w" : "");
++
++      if (file->f_mode & FMODE_READ) {
++              /* Start audio input if not already active */
++              if (!is->active) {
++                      if (!is->buffers && audio_allocate_buffers(state, is))
++                              return -ENOMEM;
++
++                      audio_prime_dma(state, is);
++              }
++
++              poll_wait(file, &is->wq, wait);
++      }
++
++      if (file->f_mode & FMODE_WRITE) {
++              if (!os->buffers && audio_allocate_buffers(state, os))
++                      return -ENOMEM;
++
++              poll_wait(file, &os->wq, wait);
++      }
++
++      if (file->f_mode & FMODE_READ) {
++              if (is->mapped) {
++                      /*
++                       * if the buffer is mapped assume we care that there are
++                       * more bytes available than when we last asked using
++                       * SNDCTL_DSP_GETxPTR
++                       */
++                      if (is->bytecount != is->getptrCount)
++                              mask |= POLLIN | POLLRDNORM;
++              } else {
++                      for (i = 0; i < is->nbfrags; i++) {
++                              if (is->buffers[i].owner != 0) {
++                                      mask |= POLLIN | POLLRDNORM;
++                                      break;
++                              }
++                      }
++              }
++      }
++
++      if (file->f_mode & FMODE_WRITE) {
++              if (os->mapped) {
++                      if (os->bytecount != os->getptrCount)
++                              mask |= POLLOUT | POLLWRNORM;
++              } else {
++                      for (i = 0; i < os->nbfrags; i++) {
++                              if (os->buffers[i].owner != 0) {
++                                      mask |= POLLOUT | POLLWRNORM;
++                                      break;
++                              }
++                      }
++              }
++      }
++
++      DPRINTK("EP93xx - audio_poll() returned mask of %s%s\n",
++              (mask & POLLIN) ? "r" : "", (mask & POLLOUT) ? "w" : "");
++
++      return mask;
++}
++
++/*
++ * audio_set_fragments
++ *
++ * Used to process SNDCTL_DSP_SETFRAGMENT.
++ *
++ * Argument is 0xMMMMSSSS where:
++ *            MMMM sets number of fragments.
++ *            SSSS sets dma fragment (dma_buffer) size.  size = 2^SSSS bytes
++ */
++static int audio_set_fragments(struct audio_state_t *state,
++                             struct audio_stream_t *stream, int val)
++{
++      if (stream->active)
++              return -EBUSY;
++
++      stream->requested_fragsize = 1 << (val & 0x000ffff);
++      stream->requested_nbfrags = (val >> 16) & 0x7FFF;
++
++      return 0;
++}
++
++static void print_audio_format(long format)
++{
++      switch (format) {
++      case AFMT_U8:
++              DPRINTK_IOCTL("AFMT_U8\n");
++              break;
++
++      case AFMT_S8:
++              DPRINTK_IOCTL("AFMT_S8\n");
++              break;
++
++      case AFMT_S32_BLOCKED:
++              DPRINTK_IOCTL("AFMT_S32_BLOCKED\n");
++              break;
++
++      case AFMT_S16_LE:
++              DPRINTK_IOCTL("AFMT_S16_LE\n");
++              break;
++
++      case AFMT_S16_BE:
++              DPRINTK_IOCTL("AFMT_S16_BE\n");
++              break;
++
++      case AFMT_U16_LE:
++              DPRINTK_IOCTL("AFMT_U16_LE\n");
++              break;
++
++      case AFMT_U16_BE:
++      default:
++              DPRINTK_IOCTL("AFMT_U16_BE\n");
++              break;
++      }
++}
++
++/*
++ * We convert to 24 bit samples that occupy 32 bits each.
++ * Formats we support:
++ *
++ * AFMT_U8
++ * AFMT_S16_LE                Little endian signed 16
++ * AFMT_S8
++ * AFMT_U16_LE                Little endian U16
++ * AFMT_S32_BLOCKED   32 bit little endian format, taken from the rme96xx driver.
++ *
++ */
++static long audio_set_format(struct audio_stream_t *stream, long val)
++{
++      DPRINTK_IOCTL("audio_set_format enter.  Format requested (%d) ",
++                    (int)val);
++      print_audio_format(val);
++
++      switch (val) {
++      case AFMT_QUERY:
++              break;
++
++      case AFMT_U8:
++              stream->audio_format = val;
++              stream->audio_stream_bitwidth = 8;
++              break;
++
++      case AFMT_S8:
++              stream->audio_format = val;
++              stream->audio_stream_bitwidth = 8;
++              break;
++
++      case AFMT_S32_BLOCKED:
++              stream->audio_format = val;
++              stream->audio_stream_bitwidth = 32;
++              break;
++
++      case AFMT_S16_LE:
++      case AFMT_S16_BE:
++              stream->audio_format = AFMT_S16_LE;
++              stream->audio_stream_bitwidth = 16;
++              break;
++
++      case AFMT_U16_LE:
++      case AFMT_U16_BE:
++      default:
++              stream->audio_format = AFMT_U16_LE;
++              stream->audio_stream_bitwidth = 16;
++              break;
++      }
++
++      DPRINTK_IOCTL("audio_set_format EXIT format set to be (%d) ",
++                    (int)stream->audio_format);
++      print_audio_format((long)stream->audio_format);
++
++      return stream->audio_format;
++}
++
++static __inline__ unsigned long copy_to_user_U16_LE_CM
++    (struct audio_state_t *state,
++     const char *to, const char *from, unsigned long to_count) {
++      int total_to_count = to_count;
++      unsigned short *user_ptr = (unsigned short *)to;        /* 16 bit user buffer */
++      short *dma_ptr = (short *)from;
++      short right, left;
++
++      /*
++       * Compact mode - left is the lower 16 bits.  right is the upper 16 bits.
++       */
++
++      if (state->input_stream->audio_num_channels != 1) {
++              while (to_count > 0) {
++                      right = *dma_ptr++;
++                      left = *dma_ptr++;
++                      __put_user(left ^ 0x8000, user_ptr++);
++                      __put_user(right ^ 0x8000, user_ptr++);
++                      to_count -= 4;
++              }
++      } else {
++              while (to_count > 0) {
++                      dma_ptr++;      /* skip right channel sample */
++                      left = *dma_ptr++;
++                      __put_user(left ^ 0x8000, user_ptr++);
++                      to_count -= 2;
++              }
++      }
++
++      return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U16_LE
++    (struct audio_state_t *state,
++     const char *to, const char *from, unsigned long to_count) {
++      int total_to_count = to_count;
++      short *user_ptr = (short *)to;  /* 16 bit user buffer */
++      int *dma_ptr = (int *)from;     /* 32 bit dma buffer  */
++
++      int shift = state->input_stream->hw_bit_width - 16;
++
++      if (state->input_stream->audio_num_channels != 1) {
++              while (to_count > 0) {
++                      __put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000,
++                                 user_ptr++);
++                      __put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000,
++                                 user_ptr++);
++                      to_count -= 4;
++              }
++      } else {
++              while (to_count > 0) {
++                      __put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000,
++                                 user_ptr++);
++                      dma_ptr++;      /* skip right channel sample */
++                      to_count -= 2;
++              }
++      }
++
++      return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_S16_LE_CM
++    (struct audio_state_t *state,
++     const char *to, const char *from, unsigned long to_count) {
++      int total_to_count = to_count;
++      short *user_ptr = (short *)to;  /* 16 bit user buffer */
++      short *dma_ptr = (short *)from;
++      short left, right;
++
++      /*
++       * Compact mode - left is the lower 16 bits.  right is the upper 16 bits.
++       */
++
++      if (state->input_stream->audio_num_channels != 1) {
++              while (to_count > 0) {
++                      right = *dma_ptr++;
++                      left = *dma_ptr++;
++                      __put_user(left, user_ptr++);
++                      __put_user(right, user_ptr++);
++                      to_count -= 4;
++              }
++      } else {
++              while (to_count > 0) {
++                      dma_ptr++;      /* skip right sample */
++                      left = *dma_ptr++;
++                      __put_user(left, user_ptr++);
++                      to_count -= 2;
++              }
++      }
++
++      return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_S16_LE
++    (struct audio_state_t *state,
++     const char *to, const char *from, unsigned long to_count) {
++      int total_to_count = to_count;
++      short *user_ptr = (short *)to;  /* 16 bit user buffer */
++      int *dma_ptr = (int *)from;     /* 32 bit dma buffer  */
++
++      int shift = state->input_stream->hw_bit_width - 16;
++
++      if (state->input_stream->audio_num_channels != 1) {
++              while (to_count > 0) {
++                      __put_user((short)((*dma_ptr++) >> shift), user_ptr++);
++                      __put_user((short)((*dma_ptr++) >> shift), user_ptr++);
++                      to_count -= 4;
++              }
++      } else {
++              while (to_count > 0) {
++                      __put_user((short)((*dma_ptr++) >> shift), user_ptr++);
++                      dma_ptr++;      /* skip right channel sample */
++                      to_count -= 2;
++              }
++      }
++
++      return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_S8_CM
++    (struct audio_state_t *state,
++     const char *to, const char *from, unsigned long to_count) {
++      int total_to_count = to_count;
++      char *user_ptr = (char *)to;    /*  8 bit user buffer */
++      unsigned short *dma_ptr = (unsigned short *)from;       /* 16 bit dma buffer  */
++      char right, left;
++
++      if (state->input_stream->audio_num_channels != 1) {
++              while (to_count > 0) {
++                      right = ((char)(*dma_ptr++ >> 8));
++                      left = ((char)(*dma_ptr++ >> 8));
++                      __put_user(left, user_ptr++);
++                      __put_user(right, user_ptr++);
++                      to_count -= 2;
++              }
++      } else {
++              while (to_count > 0) {
++                      dma_ptr++;      /* skip right channel sample */
++                      left = ((char)(*dma_ptr++ >> 8));
++                      __put_user(left, user_ptr++);
++                      to_count--;
++              }
++      }
++
++      return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_S8
++    (struct audio_state_t *state,
++     const char *to, const char *from, unsigned long to_count) {
++      int total_to_count = to_count;
++      char *user_ptr = (char *)to;    /*  8 bit user buffer */
++      int *dma_ptr = (int *)from;     /* 32 bit dma buffer  */
++
++      int shift = state->input_stream->hw_bit_width - 8;
++
++      if (state->input_stream->audio_num_channels != 1) {
++              while (to_count > 0) {
++                      __put_user((char)((*dma_ptr++) >> shift), user_ptr++);
++                      __put_user((char)((*dma_ptr++) >> shift), user_ptr++);
++                      to_count -= 2;
++              }
++      } else {
++              while (to_count > 0) {
++                      __put_user((char)((*dma_ptr++) >> shift), user_ptr++);
++                      dma_ptr++;      /* skip right channel sample */
++                      to_count--;
++              }
++      }
++
++      return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U8_CM
++    (struct audio_state_t *state,
++     const char *to, const char *from, unsigned long to_count) {
++      int total_to_count = to_count;
++      char *user_ptr = (char *)to;    /*  8 bit user buffer */
++      unsigned short *dma_ptr = (unsigned short *)from;       /* 16 bit dma buffer  */
++      char right, left;
++
++      if (state->input_stream->audio_num_channels != 1) {
++              while (to_count > 0) {
++                      right = ((char)(*dma_ptr++ >> 8)) ^ 0x80;
++                      left = ((char)(*dma_ptr++ >> 8)) ^ 0x80;
++                      __put_user(left, user_ptr++);
++                      __put_user(right, user_ptr++);
++                      to_count -= 2;
++              }
++      } else {
++              while (to_count > 0) {
++                      dma_ptr++;      /* skip right channel sample */
++                      left = ((char)(*dma_ptr++ >> 8)) ^ 0x80;
++                      __put_user(left, user_ptr++);
++                      to_count--;
++              }
++      }
++
++      return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U8
++    (struct audio_state_t *state,
++     const char *to, const char *from, unsigned long to_count) {
++      int total_to_count = to_count;
++      char *user_ptr = (char *)to;    /*  8 bit user buffer */
++      int *dma_ptr = (int *)from;     /* 32 bit dma buffer  */
++
++      int shift = state->input_stream->hw_bit_width - 8;
++
++      if (state->input_stream->audio_num_channels != 1) {
++              while (to_count > 0) {
++                      __put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80,
++                                 user_ptr++);
++                      __put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80,
++                                 user_ptr++);
++                      to_count -= 2;
++              }
++      } else {
++              while (to_count > 0) {
++                      __put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80,
++                                 user_ptr++);
++                      dma_ptr++;      /* skip right channel sample */
++                      to_count--;
++              }
++      }
++
++      return total_to_count;
++}
++
++/*
++ * Returns negative for error
++ * Returns # of bytes transferred out of the from buffer
++ * for success.
++ */
++static __inline__ int copy_to_user_with_conversion
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount) {
++      int ret = 0;
++
++      if (toCount == 0) {
++              DPRINTK("copy_to_user_with_conversion - nothing to copy!\n");
++      }
++
++      /*
++       * Compact Mode means that each 32 bit word has both the
++       * left and right sample in it.
++       */
++      if (state->input_stream->bCompactMode) {
++              switch (state->input_stream->audio_format) {
++              case AFMT_U8:
++                      ret = copy_to_user_U8_CM(state, to, from, toCount);
++                      break;
++
++              case AFMT_S16_LE:
++                      ret = copy_to_user_S16_LE_CM(state, to, from, toCount);
++                      break;
++
++              case AFMT_S8:
++                      ret = copy_to_user_S8_CM(state, to, from, toCount);
++                      break;
++
++              case AFMT_U16_LE:
++                      ret = copy_to_user_U16_LE_CM(state, to, from, toCount);
++                      break;
++
++              case AFMT_S32_BLOCKED:
++              default:
++                      break;
++              }
++      } else {
++              switch (state->input_stream->audio_format) {
++              case AFMT_U8:
++                      ret = copy_to_user_U8(state, to, from, toCount);
++                      break;
++
++              case AFMT_S16_LE:
++                      ret = copy_to_user_S16_LE(state, to, from, toCount);
++                      break;
++
++              case AFMT_S8:
++                      ret = copy_to_user_S8(state, to, from, toCount);
++                      break;
++
++              case AFMT_U16_LE:
++                      ret = copy_to_user_U16_LE(state, to, from, toCount);
++                      break;
++
++              case AFMT_S32_BLOCKED:
++              default:
++                      __copy_to_user((char *)to, from, toCount);
++                      ret = toCount;
++                      break;
++              }
++      }
++
++      return ret;
++}
++
++static __inline__ int copy_from_user_U16_LE_CM
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount) {
++      unsigned short *dma_buffer = (unsigned short *)to;
++      unsigned short *user_buffer = (unsigned short *)from;
++      unsigned short data;
++
++      int toCount0 = toCount;
++      int mono = (state->output_stream->audio_num_channels == 1);
++
++      /*
++       * Compact mode - left is the lower 16 bits.  right is the upper 16 bits.
++       */
++
++      if (!mono) {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = data ^ 0x8000;
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = data ^ 0x8000;
++                      toCount -= 4;
++              }
++      } else {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      data = data ^ 0x8000;
++                      *dma_buffer++ = data;
++                      *dma_buffer++ = data;
++                      toCount -= 4;
++              }
++      }
++
++      /*
++       * Each mono or stereo 16 bit sample going in results
++       * in one stereo 32 bit sample going out.  So
++       * mono   = (2 bytes in)/(4 bytes out)
++       * stereo = (4 bytes in)/(4 bytes out)
++       */
++      if (mono) {
++              return toCount0 / 2;
++      }
++
++      return toCount0;
++}
++
++static __inline__ int copy_from_user_U16_LE
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount) {
++      int *dma_buffer = (int *)to;
++      int val;
++      unsigned short *user_buffer = (unsigned short *)from;
++      unsigned short data;
++
++      int toCount0 = toCount;
++      int mono = (state->output_stream->audio_num_channels == 1);
++      int shift = state->output_stream->hw_bit_width - 16;
++
++      if (!mono) {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = ((unsigned int)data ^ 0x8000) << shift;
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = ((unsigned int)data ^ 0x8000) << shift;
++                      toCount -= 8;
++              }
++      } else {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      val = ((unsigned int)data ^ 0x8000) << shift;
++                      *dma_buffer++ = val;
++                      *dma_buffer++ = val;
++                      toCount -= 8;
++              }
++      }
++
++      /*
++       * Each mono or stereo 16 bit sample going in results
++       * in a two 32 bit (left & right) samples going out.  So
++       * mono   = (2 bytes in)/(8 bytes out)
++       * stereo = (4 bytes in)/(8 bytes out)
++       */
++      if (mono)
++              return toCount0 / 4;
++
++      return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_S16_LE_CM
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount) {
++      short *dma_buffer = (short *)to;
++      unsigned short *user_buffer = (unsigned short *)from;
++      unsigned short data;
++
++      int toCount0 = toCount;
++      int mono = (state->output_stream->audio_num_channels == 1);
++
++      /*
++       * Compact mode - left is the lower 16 bits.  right is the upper 16 bits.
++       */
++
++      if (!mono) {
++              __copy_from_user((char *)to, from, toCount);
++      } else {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = data;
++                      *dma_buffer++ = data;
++                      toCount -= 4;
++              }
++      }
++
++      /*
++       * Each mono or stereo 16 bit sample going in results
++       * in one stereo 32 bit sample going out.  So
++       * mono   = (2 bytes in)/(4 bytes out)
++       * stereo = (4 bytes in)/(4 bytes out)
++       */
++      if (mono)
++              return toCount0 / 2;
++
++      return toCount0;
++}
++
++static __inline__ int copy_from_user_S16_LE
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount) {
++      int *dma_buffer = (int *)to;
++      int val;
++      unsigned short *user_buffer = (unsigned short *)from;
++      unsigned short data;
++
++      int toCount0 = toCount;
++      int mono = (state->output_stream->audio_num_channels == 1);
++      int shift = state->output_stream->hw_bit_width - 16;
++
++      if (!mono) {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = (unsigned int)data << shift;
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = (unsigned int)data << shift;
++                      toCount -= 8;
++              }
++      } else {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      val = (unsigned int)data << shift;
++                      *dma_buffer++ = val;
++                      *dma_buffer++ = val;
++                      toCount -= 8;
++              }
++      }
++
++      /*
++       * Each mono or stereo 16 bit sample going in results
++       * in a two 32 bit samples (left & right) going out.  So
++       * mono   = (2 bytes in)/(8 bytes out)
++       * stereo = (4 bytes in)/(8 bytes out)
++       */
++      if (mono)
++              return toCount0 / 4;
++
++      return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_S8_CM
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount) {
++      short *dma_buffer = (short *)to;
++      short val;
++      unsigned char *user_buffer = (unsigned char *)from;
++      unsigned char data;
++
++      int toCount0 = toCount;
++      int mono = (state->output_stream->audio_num_channels == 1);
++
++      /*
++       * Compact mode - left is the lower 16 bits.  right is the upper 16 bits.
++       */
++
++      if (!mono) {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = (unsigned short)data << 8;
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = (unsigned short)data << 8;
++                      toCount -= 4;
++              }
++      } else {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      val = (unsigned short)data << 8;
++                      *dma_buffer++ = val;
++                      *dma_buffer++ = val;
++                      toCount -= 4;
++              }
++      }
++
++      /*
++       * Each mono or stereo 8 bit sample going in results
++       * in one stereo 32 bit sample going out.  So
++       * mono   = (1 byte  in)/(4 bytes out)
++       * stereo = (2 bytes in)/(4 bytes out)
++       */
++      if (mono)
++              return toCount0 / 4;
++
++      return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_S8
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount) {
++      int *dma_buffer = (int *)to;
++      int val;
++      unsigned char *user_buffer = (unsigned char *)from;
++      unsigned char data;
++
++      int toCount0 = toCount;
++      int mono = (state->output_stream->audio_num_channels == 1);
++      int shift = state->output_stream->hw_bit_width - 8;
++
++      if (!mono) {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = (unsigned int)data << shift;
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = (unsigned int)data << shift;
++                      toCount -= 8;
++              }
++      } else {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      val = (unsigned int)data << shift;
++                      *dma_buffer++ = val;
++                      *dma_buffer++ = val;
++                      toCount -= 8;
++              }
++      }
++
++      /*
++       * Each mono or stereo 8 bit sample going in results
++       * in a two 32 bit samples (left & right) going out.  So
++       * mono   = (1 byte  in)/(8 bytes out)
++       * stereo = (2 bytes in)/(8 bytes out)
++       */
++      if (mono)
++              return toCount0 / 8;
++
++      return toCount0 / 4;
++}
++
++static __inline__ int copy_from_user_U8_CM
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount) {
++      unsigned short *dma_buffer = (unsigned short *)to;
++      unsigned short val;
++      unsigned char *user_buffer = (unsigned char *)from;
++      unsigned char data;
++
++      int toCount0 = toCount;
++      int mono = (state->output_stream->audio_num_channels == 1);
++
++      if (!mono) {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = ((unsigned short)data ^ 0x80) << 8;
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = ((unsigned short)data ^ 0x80) << 8;
++                      toCount -= 4;
++              }
++      } else {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      val = ((unsigned short)data ^ 0x80) << 8;
++                      *dma_buffer++ = val;
++                      *dma_buffer++ = val;
++                      toCount -= 4;
++              }
++      }
++
++      /*
++       * Each mono or stereo 8 bit sample going in results
++       * in one stereo 32 bit sample going out.  So
++       * mono   = (1 byte  in)/(4 bytes out)
++       * stereo = (2 bytes in)/(4 bytes out)
++       */
++      if (mono)
++              return toCount0 / 4;
++
++      return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_U8
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount) {
++      unsigned int *dma_buffer = (unsigned int *)to;
++      unsigned int val;
++      unsigned char *user_buffer = (unsigned char *)from;
++      unsigned char data;
++
++      int toCount0 = toCount;
++      int mono = (state->output_stream->audio_num_channels == 1);
++      int shift = state->output_stream->hw_bit_width - 8;
++
++      if (!mono) {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = ((unsigned int)data ^ 0x80) << shift;
++                      __get_user(data, user_buffer++);
++                      *dma_buffer++ = ((unsigned int)data ^ 0x80) << shift;
++                      toCount -= 8;
++              }
++      } else {
++              while (toCount > 0) {
++                      __get_user(data, user_buffer++);
++                      val = ((unsigned int)data ^ 0x80) << shift;
++                      *dma_buffer++ = val;
++                      *dma_buffer++ = val;
++                      toCount -= 8;
++              }
++      }
++
++      /*
++       * Each mono or stereo 8 bit sample going in results
++       * in a two 32 bit samples (left & right) going out.  So
++       * mono   = (1 byte  in)/(8 bytes out)
++       * stereo = (2 bytes in)/(8 bytes out)
++       */
++      if (mono)
++              return toCount0 / 8;
++
++      return toCount0 / 4;
++}
++
++/*
++ * Returns negative for error
++ * Returns # of bytes transferred out of the from buffer
++ * for success.
++ */
++static __inline__ int copy_from_user_with_conversion
++    (struct audio_state_t *state,
++     const char *to, const char *from, int toCount) {
++      int ret = 0;
++
++      if (toCount == 0) {
++              DPRINTK("copy_from_user_with_conversion - nothing to copy!\n");
++      }
++
++      /*
++       * Compact Mode means that each 32 bit word has both the
++       * left and right sample in it.
++       */
++      if (state->output_stream->bCompactMode) {
++              switch (state->output_stream->audio_format) {
++              case AFMT_U8:
++                      ret = copy_from_user_U8_CM(state, to, from, toCount);
++                      break;
++
++              case AFMT_S16_LE:
++                      ret =
++                          copy_from_user_S16_LE_CM(state, to, from, toCount);
++                      break;
++
++              case AFMT_S8:
++                      ret = copy_from_user_S8_CM(state, to, from, toCount);
++                      break;
++
++              case AFMT_U16_LE:
++                      ret =
++                          copy_from_user_U16_LE_CM(state, to, from, toCount);
++                      break;
++
++              case AFMT_S32_BLOCKED:
++              default:
++                      break;
++              }
++      } else {
++              switch (state->output_stream->audio_format) {
++              case AFMT_U8:
++                      ret = copy_from_user_U8(state, to, from, toCount);
++                      break;
++
++              case AFMT_S16_LE:
++                      ret = copy_from_user_S16_LE(state, to, from, toCount);
++                      break;
++
++              case AFMT_S8:
++                      ret = copy_from_user_S8(state, to, from, toCount);
++                      break;
++
++              case AFMT_U16_LE:
++                      ret = copy_from_user_U16_LE(state, to, from, toCount);
++                      break;
++
++              case AFMT_S32_BLOCKED:
++              default:
++                      __copy_from_user((char *)to, from, toCount);
++                      ret = toCount;
++                      break;
++              }
++      }
++
++      return ret;
++}
++
++static int audio_ioctl(struct inode *inode, struct file *file,
++                     uint cmd, ulong arg)
++{
++      struct audio_state_t *state =
++          (struct audio_state_t *)file->private_data;
++      struct audio_stream_t *os = state->output_stream;
++      struct audio_stream_t *is = state->input_stream;
++      long val = 0;
++
++      switch (cmd) {
++      case SNDCTL_DSP_STEREO:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_STEREO\n");
++              if (get_user(val, (int *)arg) || (val > 1) || (val < 0))
++                      return -EFAULT;
++
++              if (file->f_mode & FMODE_WRITE) {
++                      if (os->audio_num_channels != (val + 1)) {
++                              os->audio_num_channels = val + 1;
++                              calculate_dma2usr_ratio_etc(os);
++                      }
++              }
++
++              if (file->f_mode & FMODE_READ) {
++                      if (is->audio_num_channels != (val + 1)) {
++                              is->audio_num_channels = val + 1;
++                              calculate_dma2usr_ratio_etc(is);
++                      }
++              }
++
++              return put_user(val, (long *)arg);
++
++      case SNDCTL_DSP_CHANNELS:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_CHANNELS\n");
++              if (get_user(val, (int *)arg) || (val > 2) || (val < 0))
++                      return -EFAULT;
++
++              // Calling with value of 0 is a query.
++              if (val == 0) {
++                      if (file->f_mode & FMODE_WRITE)
++                              val = os->audio_num_channels;
++                      else
++                              val = is->audio_num_channels;
++              } else {
++                      if (file->f_mode & FMODE_WRITE) {
++                              if (os->audio_num_channels != val) {
++                                      os->audio_num_channels = val;
++                                      calculate_dma2usr_ratio_etc(os);
++                              }
++                      }
++                      if (file->f_mode & FMODE_READ) {
++                              if (is->audio_num_channels != val) {
++                                      is->audio_num_channels = val;
++                                      calculate_dma2usr_ratio_etc(is);
++                              }
++                      }
++              }
++
++              return put_user(val, (long *)arg);
++
++      case SOUND_PCM_READ_CHANNELS:
++              DPRINTK_IOCTL("audio_ioctl - SOUND_PCM_READ_CHANNELS\n");
++              if (file->f_mode & FMODE_WRITE)
++                      val = os->audio_num_channels;
++              else
++                      val = is->audio_num_channels;
++              return put_user(val, (long *)arg);
++
++      case SNDCTL_DSP_SETFMT:
++              {
++                      DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETFMT\n");
++
++                      if (get_user(val, (int *)arg))
++                              return -EFAULT;
++
++                      if (val != AFMT_QUERY) {
++                              if ((file->f_mode & FMODE_WRITE)
++                                  && (val != os->audio_format)) {
++                                      audio_set_format(os, val);
++                                      calculate_dma2usr_ratio_etc(os);
++                                      if (state->hw->set_hw_serial_format)
++                                              state->hw->
++                                                  set_hw_serial_format(os,
++                                                                       val);
++                              }
++                              if ((file->f_mode & FMODE_READ)
++                                  && (val != is->audio_format)) {
++                                      audio_set_format(is, val);
++                                      calculate_dma2usr_ratio_etc(is);
++                                      if (state->hw->set_hw_serial_format)
++                                              state->hw->
++                                                  set_hw_serial_format(is,
++                                                                       val);
++                              }
++                      }
++
++                      if (file->f_mode & FMODE_WRITE)
++                              return put_user(os->audio_format, (long *)arg);
++                      return put_user(is->audio_format, (long *)arg);
++              }
++
++      case SNDCTL_DSP_GETFMTS:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETFMTS\n");
++              return put_user((AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_U16_LE),
++                              (long *)arg);
++
++      case OSS_GETVERSION:
++              DPRINTK_IOCTL("audio_ioctl - OSS_GETVERSION\n");
++              return put_user(SOUND_VERSION, (int *)arg);
++
++      case SNDCTL_DSP_GETBLKSIZE:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETBLKSIZE\n");
++              if (file->f_mode & FMODE_WRITE)
++                      return put_user(os->fragsize, (int *)arg);
++              return put_user(is->fragsize, (int *)arg);
++
++      case SNDCTL_DSP_GETCAPS:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETCAPS\n");
++              val = DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP;
++              if (is && os)
++                      val |= DSP_CAP_DUPLEX;
++              return put_user(val, (int *)arg);
++
++      case SNDCTL_DSP_SETFRAGMENT:
++              {
++                      int ret;
++                      DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETFRAGMENT\n");
++                      if (get_user(val, (long *)arg))
++                              return -EFAULT;
++
++                      if (file->f_mode & FMODE_READ) {
++                              ret = audio_set_fragments(state, is, val);
++                              if (ret < 0)
++                                      return ret;
++                      }
++
++                      if (file->f_mode & FMODE_WRITE) {
++                              ret = audio_set_fragments(state, os, val);
++                              if (ret < 0)
++                                      return ret;
++                      }
++
++                      return 0;
++              }
++
++      case SNDCTL_DSP_SYNC:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SYNC\n");
++              return audio_sync(file);
++
++      case SNDCTL_DSP_SETDUPLEX:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETDUPLEX\n");
++              return 0;
++
++      case SNDCTL_DSP_POST:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_POST\n");
++              return 0;
++
++      case SNDCTL_DSP_GETTRIGGER:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETTRIGGER\n");
++              val = 0;
++
++              if (file->f_mode & FMODE_READ && is->active && !is->stopped)
++                      val |= PCM_ENABLE_INPUT;
++
++              if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
++                      val |= PCM_ENABLE_OUTPUT;
++
++              return put_user(val, (int *)arg);
++
++      case SNDCTL_DSP_SETTRIGGER:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETTRIGGER\n");
++              if (get_user(val, (int *)arg))
++                      return -EFAULT;
++
++              if (file->f_mode & FMODE_READ) {
++                      if (val & PCM_ENABLE_INPUT) {
++                              if (!is->active) {
++                                      if (!is->buffers
++                                          && audio_allocate_buffers(state,
++                                                                    is))
++                                              return -ENOMEM;
++                                      audio_prime_dma(state, is);
++                              }
++
++                              if (is->stopped) {
++                                      is->stopped = 0;
++                                      os->active = 1;
++                                      audio_dma_start(state, is);
++                              }
++                      } else {
++                              audio_dma_pause(state, is);
++                              is->stopped = 1;
++                              is->active = 0;
++                      }
++              }
++
++              if (file->f_mode & FMODE_WRITE) {
++                      if (val & PCM_ENABLE_OUTPUT) {
++                              if (!os->active) {
++                                      if (!os->buffers
++                                          && audio_allocate_buffers(state,
++                                                                    os))
++                                              return -ENOMEM;
++
++                                      if (os->mapped)
++                                              audio_prime_dma(state, os);
++                              }
++
++                              if (os->stopped) {
++                                      os->stopped = 0;
++                                      os->active = 1;
++                                      audio_dma_start(state, os);
++                              }
++                      } else {
++                              audio_dma_pause(state, os);
++                              os->stopped = 1;
++                              os->active = 0;
++                      }
++              }
++              return 0;
++
++      case SNDCTL_DSP_GETOPTR:
++      case SNDCTL_DSP_GETIPTR:
++              {
++                      count_info inf = { 0, };
++                      struct audio_stream_t *stream =
++                          (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
++                      int bytecount, fragcount, buf_num = 0;
++                      unsigned int current_frac, buf_id;
++                      // KERNEL2.4 SNIP
++                      unsigned long flags;
++                      unsigned int total = 0;
++                      // KERNEL2.4 SNAP
++
++                      DPRINTK_IOCTL
++                          ("audio_ioctl - called SNDCTL_DSP_GETOPTR.\n");
++
++                      if ((stream == is && !(file->f_mode & FMODE_READ)) ||
++                          (stream == os && !(file->f_mode & FMODE_WRITE)))
++                              return -EINVAL;
++
++                      if (!stream->active)
++                              return copy_to_user((void *)arg, &inf,
++                                                  sizeof(inf));
++
++                      // KERNEL2.4
++                      //save_flags_cli(flags);
++                      local_irq_save(flags);
++
++                      // KERNEL2.4
++                      //DMA_GET_POSITION( stream->dmahandles[0], &buf_id, 0,
++                      //                &current_frac );
++                      DMA_GET_POSITION(stream->dmahandles[0], &buf_id, &total,
++                                       &current_frac);
++
++                      /*
++                       * Out of a set of nbfrags buffers, which one is the current one?
++                       */
++                      if (buf_id)
++                              buf_num = ((struct audio_buf_t *)buf_id)->num;
++
++                      /*
++                       * The ep93xx-audio ISRs keep track of bytecount and fragcount.
++                       * This bytecount isn't cleared except when the driver is opened
++                       * or when it overflows.
++                       */
++                      bytecount = stream->bytecount;
++
++                      /* so poll can tell if it changes */
++                      stream->getptrCount = stream->bytecount;
++
++                      /*
++                       * Return the number of fragment transitions counted in our dma ISR
++                       * since the previous call to this ioctl, then clear that counter.
++                       */
++                      fragcount = stream->fragcount;
++                      stream->fragcount = 0;
++
++                      // KERNEL2.4
++                      //restore_flags(flags);
++                      local_irq_restore(flags);
++
++                      /*
++                       * When reporting position to user app, scale byte counts and the
++                       * ptr to reflect the difference in sample size between dma samples
++                       * and user samples.  But don't scale the # of fragments.
++                       */
++                      inf.blocks = fragcount;
++                      inf.bytes =
++                          (bytecount + current_frac) / stream->dma2usr_ratio;
++                      inf.ptr =
++                          ((buf_num * stream->fragsize) +
++                           current_frac) / stream->dma2usr_ratio;
++
++                      return copy_to_user((void *)arg, &inf, sizeof(inf));
++              }
++
++      case SNDCTL_DSP_GETODELAY:
++              {
++                      int buffered_bytes_left, count;
++                      //unsigned int current_frac;
++                      // KERNEL2.4 SNIP
++                      unsigned int current_frac = 0;
++                      unsigned long flags;
++                      unsigned int total = 0, buf_id = 0;
++                      // KERNEL2.4SNAP
++
++                      if (!(file->f_mode & FMODE_WRITE))
++                              return -EINVAL;
++
++                      DPRINTK_IOCTL
++                          ("audio_ioctl - called SNDCTL_DSP_GETODELAY.\n");
++
++                      // KERNEL2.4
++                      //save_flags_cli(flags);
++                      local_irq_save(flags);
++
++                      // KERNEL2.4
++                      //DMA_GET_POSITION( os->dmahandles[0], 0, 0, &current_frac );
++                      DMA_GET_POSITION(os->dmahandles[0], &buf_id, &total,
++                                       &current_frac);
++
++                      buffered_bytes_left = os->buffered_bytes_to_play;
++
++                      // KERNEL2.4
++                      //restore_flags(flags);
++                      local_irq_restore(flags);
++
++                      count =
++                          (buffered_bytes_left -
++                           current_frac) / os->dma2usr_ratio;
++
++                      return put_user(count, (int *)arg);
++              }
++
++      case SNDCTL_DSP_GETOSPACE:
++              {
++                      /*
++                       * It looks like this code is assuming that nobody
++                       * is writing the device while calling this ioctl
++                       * which may be a reasonable assumption.  I hope.
++                       * Maybe.
++                       */
++                      audio_buf_info inf = { 0, };
++                      int i;
++
++                      DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETOSPACE\n");
++
++                      if (!(file->f_mode & FMODE_WRITE))
++                              return -EINVAL;
++                      if (!os->buffers && audio_allocate_buffers(state, os))
++                              return -ENOMEM;
++
++                      for (i = 0; i < os->nbfrags; i++) {
++                              /*
++                               * If the semaphore is 1, the buffer is available.
++                               */
++                              if (os->buffers[i].owner != 0) {
++                                      if (os->buffers[i].size == 0)
++                                              inf.fragments++;
++
++                                      inf.bytes +=
++                                          os->fragsize - os->buffers[i].size;
++                              }
++                      }
++
++                      inf.fragsize = os->fragsize / os->dma2usr_ratio;
++                      inf.fragstotal = os->nbfrags;
++                      inf.bytes = inf.bytes / os->dma2usr_ratio;
++
++                      return copy_to_user((void *)arg, &inf, sizeof(inf));
++              }
++
++      case SNDCTL_DSP_GETISPACE:
++              {
++                      audio_buf_info inf = { 0, };
++                      int i;
++
++                      DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETISPACE\n");
++
++                      if (!(file->f_mode & FMODE_READ))
++                              return -EINVAL;
++                      if (!is->buffers && audio_allocate_buffers(state, is))
++                              return -ENOMEM;
++
++                      for (i = 0; i < is->nbfrags; i++) {
++                              if (is->buffers[i].owner != 0) {
++                                      if (is->buffers[i].size == is->fragsize)
++                                              inf.fragments++;
++
++                                      inf.bytes += is->buffers[i].size;
++                              }
++                      }
++
++                      inf.fragsize = is->fragsize / is->dma2usr_ratio;
++                      inf.fragstotal = is->nbfrags;
++                      inf.bytes = inf.bytes / is->dma2usr_ratio;
++
++                      return copy_to_user((void *)arg, &inf, sizeof(inf));
++              }
++
++      case SNDCTL_DSP_NONBLOCK:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_NONBLOCK\n");
++              file->f_flags |= O_NONBLOCK;
++              return 0;
++
++      case SNDCTL_DSP_RESET:
++              DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_RESET\n");
++              if (file->f_mode & FMODE_READ)
++                      audio_reset_buffers(state, is);
++              if (file->f_mode & FMODE_WRITE)
++                      audio_reset_buffers(state, os);
++              return 0;
++
++      default:
++              /*
++               * Let the client of this module handle the
++               * non generic ioctls
++               */
++              return state->hw->client_ioctl(inode, file, cmd, arg);
++      }
++
++      return 0;
++}
++
++static int audio_release(struct inode *inode, struct file *file)
++{
++      struct audio_state_t *state =
++          (struct audio_state_t *)file->private_data;
++      int i;
++
++      DPRINTK("EP93xx - audio_release -- enter.  Write=%d  Read=%d\n",
++              ((file->f_mode & FMODE_WRITE) != 0),
++              ((file->f_mode & FMODE_READ) != 0));
++
++      down(&state->sem);
++
++      if (file->f_mode & FMODE_READ) {
++              audio_deallocate_buffers(state, state->input_stream);
++
++              for (i = 0; i < state->input_stream->NumDmaChannels; i++)
++                      DMA_FREE(state->input_stream->dmahandles[i]);
++
++              state->rd_ref = 0;
++      }
++
++      if (file->f_mode & FMODE_WRITE) {
++              /*
++               * Wait for all our buffers to play.
++               */
++              audio_sync(file);
++
++              /*
++               * audio_deallocate_buffers will pause and flush the dma
++               * then deallocate the buffers.
++               */
++              audio_deallocate_buffers(state, state->output_stream);
++              for (i = 0; i < state->output_stream->NumDmaChannels; i++)
++                      DMA_FREE(state->output_stream->dmahandles[i]);
++
++              state->wr_ref = 0;
++      }
++
++      up(&state->sem);
++
++      DPRINTK("EP93xx - audio_release -- EXIT\n");
++
++      return 0;
++}
++
++/*
++ *  ep93xx_clear_stream_struct
++ *
++ *  Initialize stuff or at least clear it to zero for a stream structure.
++ */
++static void ep93xx_clear_stream_struct(struct audio_stream_t *stream)
++{
++
++      stream->dmahandles[0] = 0;      /* handles for dma driver instances */
++      stream->dmahandles[1] = 0;      /* handles for dma driver instances */
++      stream->dmahandles[2] = 0;      /* handles for dma driver instances */
++      stream->NumDmaChannels = 0;     /* 1, 2, or 3 DMA channels */
++      stream->TX_dma_ch_bitfield = 0; /* which dma channels used for strm */
++      stream->RX_dma_ch_bitfield = 0; /* which dma channels used for strm */
++      stream->buffers = 0;    /* array of audio buffer structures */
++      stream->dma_buffer = 0; /* current buffer used by read/write */
++      stream->dma_buffer_index = 0;   /* index for the pointer above... */
++      stream->fragsize = AUDIO_FRAGSIZE_DEFAULT;      /* fragment i.e. buffer size */
++      stream->nbfrags = AUDIO_NBFRAGS_DEFAULT;        /* nbr of fragments i.e. buffers */
++      stream->requested_fragsize = 0; /* This is ignored if 0 */
++      stream->requested_nbfrags = 0;  /* This is ignored if 0 */
++      stream->bytecount = 0;  /* nbr of processed bytes */
++      stream->getptrCount = 0;        /* value of bytecount last time */
++      /* anyone asked via GETxPTR */
++      stream->fragcount = 0;  /* nbr of fragment transitions */
++      stream->mapped = 0;     /* mmap()'ed buffers */
++      stream->active = 0;     /* actually in progress */
++      stream->stopped = 0;    /* might be active but stopped */
++      stream->bFirstCaptureBuffer = 1;        /* flag meaning there is junk in rx fifo */
++      stream->buffered_bytes_to_play = 0;
++
++      calculate_dma2usr_ratio_etc(stream);
++}
++
++/*
++ *    ep93xx_audio_attach
++ *
++ *  Initialize the state structure for read or write.  Allocate dma channels.
++ *  Currently each s is a stereo s (one dma channel).
++ *
++ */
++int ep93xx_audio_attach
++    (struct inode *inode, struct file *file, struct audio_state_t *state) {
++      int err, i;
++      struct audio_stream_t *os = state->output_stream;
++      struct audio_stream_t *is = state->input_stream;
++
++      DPRINTK("ep93xx_audio_attach -- enter.  Write=%d  Read=%d\n",
++              ((file->f_mode & FMODE_WRITE) != 0),
++              ((file->f_mode & FMODE_READ) != 0));
++
++      down(&state->sem);
++
++      /* access control */
++      if (((file->f_mode & FMODE_WRITE) && !os) ||
++          ((file->f_mode & FMODE_READ) && !is)) {
++              up(&state->sem);
++              return -ENODEV;
++      }
++
++      if (((file->f_mode & FMODE_WRITE) && state->wr_ref) ||
++          ((file->f_mode & FMODE_READ) && state->rd_ref)) {
++              up(&state->sem);
++              return -EBUSY;
++      }
++
++      /*
++       * Request DMA channels
++       */
++      if (file->f_mode & FMODE_WRITE) {
++              DPRINTK("ep93xx_audio_attach -- FMODE_WRITE\n");
++
++              state->wr_ref = 1;
++
++              ep93xx_clear_stream_struct(os);
++
++              err = DMA_REQUEST(&os->dmahandles[0],
++                                os->devicename, os->dmachannel[0]);
++              if (err) {
++                      up(&state->sem);
++                      DPRINTK
++                          ("ep93xx_audio_attach -- EXIT ERROR dma request failed\n");
++                      return err;
++              }
++
++              err = DMA_CONFIG(os->dmahandles[0],
++                               IGNORE_CHANNEL_ERROR,
++                               0, audio_dma_tx_callback, (unsigned int)state);
++              if (err) {
++                      DMA_FREE(os->dmahandles[0]);
++                      up(&state->sem);
++                      DPRINTK
++                          ("ep93xx_audio_attach -- EXIT ERROR dma config failed\n");
++                      return err;
++              }
++
++              /*
++               * Assuming each audio stream is mono or stereo.
++               */
++              os->NumDmaChannels = 1;
++
++              /*
++               * Automatically set up the bit field of dma channels used for
++               * this stream.
++               */
++              for (i = 0; (i < state->hw->MaxTxDmaChannels); i++) {
++                      if (os->dmachannel[i] == state->hw->txdmachannels[0])
++                              os->TX_dma_ch_bitfield |= 1;
++
++                      if (os->dmachannel[i] == state->hw->txdmachannels[1])
++                              os->TX_dma_ch_bitfield |= 2;
++
++                      if (os->dmachannel[i] == state->hw->txdmachannels[2])
++                              os->TX_dma_ch_bitfield |= 4;
++              }
++
++              DPRINTK("DMA Tx channel bitfield = %x\n",
++                      os->TX_dma_ch_bitfield);
++
++              if (state->hw->hw_clear_fifo)
++                      state->hw->hw_clear_fifo(os);
++
++              init_waitqueue_head(&os->wq);
++      }
++
++      if (file->f_mode & FMODE_READ) {
++              state->rd_ref = 1;
++
++              ep93xx_clear_stream_struct(is);
++
++              err = DMA_REQUEST(&is->dmahandles[0],
++                                is->devicename, is->dmachannel[0]);
++              if (err) {
++                      up(&state->sem);
++                      DPRINTK
++                          ("ep93xx_audio_attach -- EXIT ERROR dma request failed\n");
++                      return err;
++              }
++
++              err = DMA_CONFIG(is->dmahandles[0],
++                               IGNORE_CHANNEL_ERROR,
++                               0, audio_dma_rx_callback, (unsigned int)state);
++              if (err) {
++                      DMA_FREE(is->dmahandles[0]);
++                      up(&state->sem);
++                      DPRINTK
++                          ("ep93xx_audio_attach -- EXIT ERROR dma config failed\n");
++                      return err;
++              }
++
++              is->NumDmaChannels = 1;
++
++              /*
++               * Automatically set up the bit field of dma channels used for
++               * this stream.
++               */
++              for (i = 0; (i < state->hw->MaxRxDmaChannels); i++) {
++                      if (is->dmachannel[i] == state->hw->rxdmachannels[0])
++                              is->RX_dma_ch_bitfield |= 1;
++
++                      if (is->dmachannel[i] == state->hw->rxdmachannels[1])
++                              is->RX_dma_ch_bitfield |= 2;
++
++                      if (is->dmachannel[i] == state->hw->rxdmachannels[2])
++                              is->RX_dma_ch_bitfield |= 4;
++              }
++
++              DPRINTK("DMA Rx channel bitfield = %x\n",
++                      is->RX_dma_ch_bitfield);
++
++              init_waitqueue_head(&is->wq);
++      }
++
++      /*
++       * Fill out the rest of the file_operations struct.
++       */
++      file->private_data = state;
++      file->f_op->release = audio_release;
++      file->f_op->write = audio_write;
++      file->f_op->read = audio_read;
++      file->f_op->mmap = audio_mmap;
++      file->f_op->poll = audio_poll;
++      file->f_op->ioctl = audio_ioctl;
++      file->f_op->llseek = no_llseek;
++
++      up(&state->sem);
++
++      DPRINTK("ep93xx_audio_attach -- EXIT\n");
++
++      return 0;
++}
++
++EXPORT_SYMBOL(ep93xx_audio_attach);
++
++MODULE_DESCRIPTION("Common audio handling for the Cirrus EP93xx processor");
++MODULE_LICENSE("GPL");
+diff --git a/sound/oss/ep93xx-audio.h b/sound/oss/ep93xx-audio.h
+new file mode 100644
+index 0000000..04a0581
+--- /dev/null
++++ b/sound/oss/ep93xx-audio.h
+@@ -0,0 +1,149 @@
++/*
++ * ep93xx-audio.h
++ *
++ * Common audio handling for the Cirrus Logic EP93xx
++ *
++ * Copyright (c) 2003 Cirrus Logic Corp.
++ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
++ *
++ * Taken from sa1100-audio.h
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License.
++ */
++
++/*
++ *  Getting this from the rme96xx driver.  Has same numerical value
++ *  as AC3.  Hmmmm.
++ */
++#ifndef AFMT_S32_BLOCKED
++#define AFMT_S32_BLOCKED 0x0000400
++#endif
++
++#define EP93XX_DEFAULT_NUM_CHANNELS      2
++#define EP93XX_DEFAULT_FORMAT            AFMT_S16_LE
++#define EP93XX_DEFAULT_BIT_WIDTH         16
++
++/*
++ * Buffer Management
++ */
++
++struct audio_buf_t {
++
++      int size;               /* buffer size                                  */
++      int sent;               /* indicates that dma has the dma_buffer        */
++      char *start;            /* points to actual buffer                      */
++      dma_addr_t dma_addr;    /* physical buffer address                      */
++      int owner;
++      struct semaphore sem;   /* down before touching the buffer              */
++      int master;             /* owner for buffer allocation,                 */
++      /* contains size when true                      */
++      int num;                /* which out of nbfrags buffers is this?        */
++      struct audio_stream_t *stream;  /* owning stream                                */
++
++};
++
++#define MAX_DEVICE_NAME 20
++
++struct audio_stream_t {
++
++      /* dma stuff */
++      int dmahandles[3];      /* handles for dma driver instances     */
++      char devicename[MAX_DEVICE_NAME];       /* string - name of device              */
++      int NumDmaChannels;     /* 1, 2, or 3 DMA channels              */
++      ep93xx_dma_dev_t dmachannel[3]; /* dma channel numbers                  */
++
++      struct audio_buf_t *buffers;    /* array of audio buffer structures     */
++      struct audio_buf_t *dma_buffer; /* current buffer used by read/write    */
++      u_int dma_buffer_index; /* index for the pointer above...       */
++
++      u_int fragsize;         /* fragment i.e. buffer size            */
++      u_int nbfrags;          /* nbr of fragments i.e. buffers        */
++      u_int requested_fragsize;
++      u_int requested_nbfrags;
++
++      int bytecount;          /* nbr of processed bytes               */
++      int getptrCount;        /* value of bytecount last time         */
++      /* anyone asked via GETxPTR             */
++      int fragcount;          /* nbr of fragment transitions          */
++      wait_queue_head_t wq;   /* for poll                             */
++      int mapped:1;           /* mmap()'ed buffers                    */
++      int active:1;           /* actually in progress                 */
++      int stopped:1;          /* might be active but stopped          */
++      u_int TX_dma_ch_bitfield;       /* bit0 = txdma1, bit1= txdma2, etc     */
++      u_int RX_dma_ch_bitfield;       /* bit0 = rxdma1, bit1= rxdma2, etc     */
++      int bFirstCaptureBuffer;        /* flag meaning there is junk in rx fifo */
++
++      /*
++       * Data about the file format that we are configured to play.
++       */
++      long audio_num_channels;        /* Range: 1 to 6 */
++      long audio_format;
++      long audio_stream_bitwidth;     /* Range: 8, 16, 24, 32 */
++
++      long sample_rate;       /* Fs in Hz. */
++
++      /*
++       * Data about how the audio controller and codec are set up.
++       */
++      int hw_bit_width;       /* width of dac or adc */
++      int bCompactMode;       /* set if 32bits == a stereo sample */
++
++      /*
++       * dma2usr_ratio = dma sample size (8 or 4 bytes) / usr sample size (8,4,2,1)
++       */
++      int dma2usr_ratio;
++
++      /*
++       * This provides a way of determining audio playback position that will not
++       * overflow.  This is (size of buffers written) - (buffers we've gotten back)
++       */
++      int buffered_bytes_to_play;
++
++};
++
++/*
++ * No matter how many streams are going, we are using one hardware device.
++ * This struct describes that hardware.
++ */
++struct audio_hw_t {
++
++      ep93xx_dma_dev_t txdmachannels[3];      /* all dma channels available for */
++      ep93xx_dma_dev_t rxdmachannels[3];      /* this audio ctrlr */
++
++      int MaxTxDmaChannels;   /* number of tx and rx channels */
++      int MaxRxDmaChannels;   /* number of tx and rx channels */
++
++      /*
++       * Pointers to init, shutdown, and ioctl functions.
++       */
++      void (*hw_enable) (struct audio_stream_t * stream);
++      void (*hw_disable) (struct audio_stream_t * stream);
++      void (*hw_clear_fifo) (struct audio_stream_t * stream);
++      int (*client_ioctl) (struct inode *, struct file *, uint, ulong);
++      void (*set_hw_serial_format) (struct audio_stream_t *, long);
++
++      unsigned int modcnt;    /* count the # of volume writes */
++
++};
++
++/*
++ * State structure for one instance
++ */
++struct audio_state_t {
++      struct audio_stream_t *output_stream;
++      struct audio_stream_t *input_stream;
++
++      struct audio_hw_t *hw;  /* hw info */
++
++      int rd_ref:1;           /* open reference for recording */
++      int wr_ref:1;           /* open reference for playback */
++
++      struct semaphore sem;   /* to protect against races in attach() */
++
++};
++
++/*
++ * Functions exported by this module
++ */
++extern int ep93xx_audio_attach(struct inode *inode, struct file *file,
++                             struct audio_state_t *state);
diff --git a/packages/linux/ep93xx-kernel_2.6.15.bb b/packages/linux/ep93xx-kernel_2.6.15.bb
new file mode 100644 (file)
index 0000000..4af3c65
--- /dev/null
@@ -0,0 +1,19 @@
+DESCRIPTION = "Linux Kernel for Cirrus Logic ep39xxcompatible machines"
+SECTION = "kernel"
+LICENSE = "GPL"
+PR = "r0"
+
+SRC_URI = "ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-${PV}.tar.bz2 \
+                  file://linux-2.6.15-ep93xx-gao19.diff;patch=1 \
+           file://defconfig"
+
+S = "${WORKDIR}/linux-${PV}"
+
+inherit kernel
+
+KERNEL_IMAGETYPE = "zImage"
+
+do_configure_prepend() {
+       install -m 0644 ${WORKDIR}/defconfig ${S}/.config
+}
+