diff -purN linux-2.6.30-rc4-git/arch/arm/configs/karo_tx25_defconfig linux-2.6.30-rc4-karo3/arch/arm/configs/karo_tx25_defconfig
--- linux-2.6.30-rc4-git/arch/arm/configs/karo_tx25_defconfig	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/configs/karo_tx25_defconfig	2009-07-14 13:49:57.000000000 +0200
@@ -0,0 +1,1442 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc4
+# Tue Jul 14 13:40:27 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ARCH_MTD_XIP=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=17
+# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+# CONFIG_SYSFS_DEPRECATED_V2 is not set
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+CONFIG_KALLSYMS_ALL=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+# CONFIG_ELF_CORE is not set
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+# CONFIG_AIO is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+CONFIG_LBD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# 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"
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+CONFIG_ARCH_MXC=y
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# Freescale MXC Implementations
+#
+# CONFIG_ARCH_MX1 is not set
+CONFIG_ARCH_MX2=y
+# CONFIG_ARCH_MX3 is not set
+# CONFIG_MACH_MX21 is not set
+# CONFIG_MACH_MX27 is not set
+CONFIG_MACH_MX25=y
+
+#
+# MX2 platforms:
+#
+CONFIG_MACH_TX25=y
+# CONFIG_KARO_DEBUG is not set
+CONFIG_MACH_STK5_BASEBOARD=y
+# CONFIG_MXC_IRQ_PRIOR is not set
+# CONFIG_MXC_PWM is not set
+CONFIG_ARCH_MXC_IOMUX_V3=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=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
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+# CONFIG_HIGH_RES_TIMERS is not set
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+CONFIG_OABI_COMPAT=y
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0
+CONFIG_ZBOOT_ROM_BSS=0
+CONFIG_CMDLINE="init=/linuxrc root=1f01 rootfstype=jffs2 ro console=ttymxc0,115200 panic=1"
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
+
+#
+# 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
+CONFIG_VFP=y
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+CONFIG_PM=y
+CONFIG_PM_DEBUG=y
+# CONFIG_PM_VERBOSE is not set
+CONFIG_CAN_PM_TRACE=y
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_APM_EMULATION=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+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 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_XFRM_TUNNEL is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETFILTER is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA 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_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_TESTS=m
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-5
+# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
+CONFIG_MTD_REDBOOT_PARTS_READONLY=y
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=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
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+# CONFIG_MTD_CFI is not set
+# CONFIG_MTD_JEDECPROBE 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_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS 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_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
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_NAND_MXC=y
+CONFIG_MTD_NAND_MXC_FLASH_BBT=y
+CONFIG_ARCH_MXC_HAS_NFC_V1=y
+CONFIG_ARCH_MXC_HAS_NFC_V1_1=y
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# 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=8192
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# 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=m
+# 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
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+# CONFIG_SCSI_LOWLEVEL is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+CONFIG_SMSC_PHY=y
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+CONFIG_FEC=y
+# CONFIG_FEC2 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# 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_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+CONFIG_NETCONSOLE=y
+CONFIG_NETCONSOLE_DYNAMIC=y
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+# CONFIG_INPUT_APMPOWER 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_STOWAWAY is not set
+CONFIG_KEYBOARD_GPIO=m
+CONFIG_INPUT_MOUSE=y
+# CONFIG_MOUSE_PS2 is not set
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+CONFIG_TOUCHSCREEN_MXC_TSADCC=m
+CONFIG_TOUCHSCREEN_USB_COMPOSITE=m
+CONFIG_TOUCHSCREEN_USB_EGALAX=y
+# CONFIG_TOUCHSCREEN_USB_PANJIT is not set
+# CONFIG_TOUCHSCREEN_USB_3M is not set
+# CONFIG_TOUCHSCREEN_USB_ITM is not set
+# CONFIG_TOUCHSCREEN_USB_ETURBO is not set
+# CONFIG_TOUCHSCREEN_USB_GUNZE is not set
+# CONFIG_TOUCHSCREEN_USB_DMC_TSC10 is not set
+# CONFIG_TOUCHSCREEN_USB_IRTOUCH is not set
+# CONFIG_TOUCHSCREEN_USB_IDEALTEK is not set
+# CONFIG_TOUCHSCREEN_USB_GENERAL_TOUCH is not set
+# CONFIG_TOUCHSCREEN_USB_GOTOP is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_DEBUG_GPIO=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+# CONFIG_HWMON is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+# CONFIG_VIDEO_DEV is not set
+# CONFIG_DVB_CORE is not set
+# CONFIG_VIDEO_MEDIA is not set
+
+#
+# Multimedia drivers
+#
+# CONFIG_DAB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+# CONFIG_VIDEO_OUTPUT_CONTROL is not set
+CONFIG_FB=y
+# CONFIG_FIRMWARE_EDID is not set
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_IMX=y
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y
+CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+# CONFIG_SOUND is not set
+# CONFIG_HID_SUPPORT is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+CONFIG_USB_EHCI_HCD=m
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+CONFIG_USB_EHCI_MXC=y
+CONFIG_ARCH_MXC_EHCI_USBH2=y
+# CONFIG_ARCH_MXC_EHCI_USBOTG is not set
+CONFIG_ARCH_MXC_HAS_USBH2=y
+CONFIG_ARCH_MXC_HAS_USBOTG=y
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+
+#
+# Enable Host or Gadget support to see Inventra options
+#
+# CONFIG_USB_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_DATAFAB=m
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+# CONFIG_USB_EZUSB is not set
+# CONFIG_USB_SERIAL_GENERIC is not set
+# CONFIG_USB_SERIAL_AIRCABLE is not set
+# CONFIG_USB_SERIAL_ARK3116 is not set
+CONFIG_USB_SERIAL_BELKIN=m
+# CONFIG_USB_SERIAL_CH341 is not set
+# CONFIG_USB_SERIAL_WHITEHEAT is not set
+# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
+# CONFIG_USB_SERIAL_CP210X 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_FUNSOFT 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_IUU 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_MOS7720 is not set
+# CONFIG_USB_SERIAL_MOS7840 is not set
+# CONFIG_USB_SERIAL_MOTOROLA is not set
+# CONFIG_USB_SERIAL_NAVMAN is not set
+# CONFIG_USB_SERIAL_PL2303 is not set
+# CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QUALCOMM is not set
+# CONFIG_USB_SERIAL_SPCP8X5 is not set
+# CONFIG_USB_SERIAL_HP4X is not set
+# CONFIG_USB_SERIAL_SAFE is not set
+# CONFIG_USB_SERIAL_SIEMENS_MPI is not set
+# CONFIG_USB_SERIAL_SIERRAWIRELESS is not set
+# CONFIG_USB_SERIAL_SYMBOL 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_OPTION is not set
+# CONFIG_USB_SERIAL_OMNINET is not set
+# CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING 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=m
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+CONFIG_EXT3_FS_POSIX_ACL=y
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=m
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=m
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+# CONFIG_AUTOFS4_FS is not set
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+CONFIG_NTFS_FS=m
+# CONFIG_NTFS_DEBUG is not set
+CONFIG_NTFS_RW=y
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_CONFIGFS_FS=y
+CONFIG_MISC_FILESYSTEMS=y
+# 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_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+CONFIG_JFFS2_SUMMARY=y
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+CONFIG_NFS_V4=y
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+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_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="cp437"
+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=m
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+# 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
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC=y
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=1
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC=y
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=1
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_TIMER_STATS is not set
+# CONFIG_DEBUG_OBJECTS is not set
+CONFIG_DEBUG_SLAB=y
+CONFIG_DEBUG_SLAB_LEAK=y
+# CONFIG_DEBUG_PREEMPT is not set
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_RT_MUTEX_TESTER is not set
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+# CONFIG_PROVE_LOCKING is not set
+CONFIG_LOCKDEP=y
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_LOCKDEP is not set
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=y
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+CONFIG_CRYPTO_ECB=y
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_HMAC=y
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+CONFIG_CRYPTO_MD5=y
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+# CONFIG_CRYPTO_ANUBIS is not set
+CONFIG_CRYPTO_ARC4=y
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRYPTO_HW=y
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+# CONFIG_CRC16 is not set
+# CONFIG_CRC_T10DIF is not set
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/Kconfig linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/Kconfig
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/Kconfig	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/Kconfig	2009-07-01 11:09:09.000000000 +0200
@@ -6,14 +6,32 @@ choice
 
 config MACH_MX21
 	bool "i.MX21 support"
+	select ARCH_MXC_IOMUX_V2
+	select ARCH_MXC_HAS_NFC_V1
 	help
 	  This enables support for Freescale's MX2 based i.MX21 processor.
 
 config MACH_MX27
 	bool "i.MX27 support"
+	select ARCH_MXC_IOMUX_V2
+	select ARCH_MXC_HAS_NFC_V1
+	select USB_ARCH_HAS_EHCI
+	select ARCH_MXC_HAS_USBH2
+	select ARCH_MXC_HAS_USBOTG
 	help
 	  This enables support for Freescale's MX2 based i.MX27 processor.
 
+config MACH_MX25
+	bool "i.MX25 support"
+	select ARCH_MXC_IOMUX_V3
+	select ARCH_MXC_HAS_NFC_V1_1
+	select USB_ARCH_HAS_EHCI
+	select ARCH_MXC_HAS_USBH2
+	select ARCH_MXC_HAS_USBOTG
+	select PHYLIB if FEC
+	help
+	  This enables support for Freescale's MX2 based i.MX25 processor.
+
 endchoice
 
 comment "MX2 platforms:"
@@ -39,6 +57,26 @@ config MACH_PCM038
 	  Include support for phyCORE-i.MX27 (aka pcm038) platform. This
 	  includes specific configurations for the module and its peripherals.
 
+config MACH_TX25
+	bool "Support Ka-Ro electronics TX25 module"
+	depends on MACH_MX25
+	help
+	  Include support for Ka-Ro TX25 processor module
+
+config KARO_DEBUG
+	bool "Enable Ka-Ro specific debug messages"
+	depends on MACH_TX25 || MACH_TX27
+	help
+	  Compile the architecture specific files with -DDEBUG to enable
+	  additional debug messages
+
+config MACH_STK5_BASEBOARD
+	bool "Ka-Ro Starterkit-5 (STK5) development board"
+	depends on MACH_TX27 || MACH_TX25
+	help
+	  This adds board specific devices that can be found on Ka-Ro's
+	  STK5 evaluation board.
+
 choice
 	prompt "Baseboard"
 	depends on MACH_PCM038
@@ -60,3 +98,4 @@ config MACH_MX27_3DS
 	  Include support for MX27PDK platform. This includes specific
 	  configurations for the board and its peripherals.
 endif
+
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/Makefile linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/Makefile
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/Makefile	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/Makefile	2009-06-02 17:59:14.000000000 +0200
@@ -2,17 +2,31 @@
 # Makefile for the linux kernel.
 #
 
+ifeq ($(CONFIG_KARO_DEBUG),y)
+	EXTRA_CFLAGS += -DDEBUG
+endif
+
 # Object file lists.
 
-obj-y	:=  generic.o devices.o serial.o
+obj-y	:=  generic.o serial.o
+obj-$(CONFIG_MACH_MX25)	+=  devices_mx25.o
+ifeq ($(CONFIG_MACH_MX25),)
+obj-y	+=  devices.o
+endif
+
+obj-$(CONFIG_MACH_MX21)			+= clock_imx21.o
 
-obj-$(CONFIG_MACH_MX21) += clock_imx21.o
+obj-$(CONFIG_MACH_MX25)			+= clock_imx25.o
+obj-$(CONFIG_MACH_MX25)			+= cpu_imx25.o
 
-obj-$(CONFIG_MACH_MX27) += cpu_imx27.o
-obj-$(CONFIG_MACH_MX27) += clock_imx27.o
+obj-$(CONFIG_MACH_MX27)			+= cpu_imx27.o
+obj-$(CONFIG_MACH_MX27)			+= clock_imx27.o
 
-obj-$(CONFIG_MACH_MX21ADS) += mx21ads.o
-obj-$(CONFIG_MACH_MX27ADS) += mx27ads.o
-obj-$(CONFIG_MACH_PCM038) += pcm038.o
-obj-$(CONFIG_MACH_PCM970_BASEBOARD) += pcm970-baseboard.o
-obj-$(CONFIG_MACH_MX27_3DS) += mx27pdk.o
+obj-$(CONFIG_MACH_MX21ADS)		+= mx21ads.o
+obj-$(CONFIG_MACH_MX27ADS)		+= mx27ads.o
+obj-$(CONFIG_MACH_PCM038)		+= pcm038.o
+obj-$(CONFIG_MACH_PCM970_BASEBOARD)	+= pcm970-baseboard.o
+obj-$(CONFIG_MACH_MX27_3DS)		+= mx27pdk.o
+obj-$(CONFIG_MACH_TX27)			+= karo-tx27.o tx27_gpio.o
+obj-$(CONFIG_MACH_TX25)			+= karo-tx25.o
+obj-$(CONFIG_MACH_STK5_BASEBOARD)	+= stk5-baseboard.o
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/Makefile.boot linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/Makefile.boot
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/Makefile.boot	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/Makefile.boot	2009-06-02 17:59:15.000000000 +0200
@@ -5,3 +5,7 @@ initrd_phys-$(CONFIG_MACH_MX21)	:= 0xC08
 zreladdr-$(CONFIG_MACH_MX27)	:= 0xA0008000
 params_phys-$(CONFIG_MACH_MX27)	:= 0xA0000100
 initrd_phys-$(CONFIG_MACH_MX27)	:= 0xA0800000
+
+zreladdr-$(CONFIG_MACH_MX25)	:= 0x80008000
+params_phys-$(CONFIG_MACH_MX25)	:= 0x80000100
+initrd_phys-$(CONFIG_MACH_MX25)	:= 0x80800000
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/clock_imx21.c linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/clock_imx21.c
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/clock_imx21.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/clock_imx21.c	2009-06-02 17:59:15.000000000 +0200
@@ -890,7 +890,7 @@ static struct clk clko_clk = {
 		.con_id = n, \
 		.clk = &c, \
 	},
-static struct clk_lookup lookups[] __initdata = {
+static struct clk_lookup lookups[] = {
 /* It's unlikely that any driver wants one of them directly:
 	_REGISTER_CLOCK(NULL, "ckih", ckih_clk)
 	_REGISTER_CLOCK(NULL, "ckil", ckil_clk)
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/clock_imx25.c linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/clock_imx25.c
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/clock_imx25.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/clock_imx25.c	2009-07-06 14:10:59.000000000 +0200
@@ -0,0 +1,1861 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/* based on mach-mx27/clock.c */
+
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/module.h>
+//#include <linux/spinlock.h>
+
+#include <asm/clkdev.h>
+//#include <asm/div64.h>
+
+#include <mach/clock.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+
+/* Register offsets */
+#define MXC_CCM_MPCTL				(IO_ADDRESS(CCM_BASE_ADDR) + 0x00)
+#define MXC_CCM_UPCTL				(IO_ADDRESS(CCM_BASE_ADDR) + 0x04)
+#define MXC_CCM_CCTL				(IO_ADDRESS(CCM_BASE_ADDR) + 0x08)
+#define MXC_CCM_CGCR0				(IO_ADDRESS(CCM_BASE_ADDR) + 0x0C)
+#define MXC_CCM_CGCR1				(IO_ADDRESS(CCM_BASE_ADDR) + 0x10)
+#define MXC_CCM_CGCR2				(IO_ADDRESS(CCM_BASE_ADDR) + 0x14)
+#define MXC_CCM_PCDR0				(IO_ADDRESS(CCM_BASE_ADDR) + 0x18)
+#define MXC_CCM_PCDR1				(IO_ADDRESS(CCM_BASE_ADDR) + 0x1C)
+#define MXC_CCM_PCDR2				(IO_ADDRESS(CCM_BASE_ADDR) + 0x20)
+#define MXC_CCM_PCDR3				(IO_ADDRESS(CCM_BASE_ADDR) + 0x24)
+#define MXC_CCM_RCSR				(IO_ADDRESS(CCM_BASE_ADDR) + 0x28)
+#define MXC_CCM_CRDR				(IO_ADDRESS(CCM_BASE_ADDR) + 0x2C)
+#define MXC_CCM_DCVR0				(IO_ADDRESS(CCM_BASE_ADDR) + 0x30)
+#define MXC_CCM_DCVR1				(IO_ADDRESS(CCM_BASE_ADDR) + 0x34)
+#define MXC_CCM_DCVR2				(IO_ADDRESS(CCM_BASE_ADDR) + 0x38)
+#define MXC_CCM_DCVR3				(IO_ADDRESS(CCM_BASE_ADDR) + 0x3C)
+#define MXC_CCM_LTR0				(IO_ADDRESS(CCM_BASE_ADDR) + 0x40)
+#define MXC_CCM_LTR1				(IO_ADDRESS(CCM_BASE_ADDR) + 0x44)
+#define MXC_CCM_LTR2				(IO_ADDRESS(CCM_BASE_ADDR) + 0x48)
+#define MXC_CCM_LTR3				(IO_ADDRESS(CCM_BASE_ADDR) + 0x4C)
+#define MXC_CCM_LTBR0				(IO_ADDRESS(CCM_BASE_ADDR) + 0x50)
+#define MXC_CCM_LTBR1				(IO_ADDRESS(CCM_BASE_ADDR) + 0x54)
+#define MXC_CCM_PMCR0				(IO_ADDRESS(CCM_BASE_ADDR) + 0x58)
+#define MXC_CCM_PMCR1				(IO_ADDRESS(CCM_BASE_ADDR) + 0x5C)
+#define MXC_CCM_PMCR2				(IO_ADDRESS(CCM_BASE_ADDR) + 0x60)
+#define MXC_CCM_MCR				(IO_ADDRESS(CCM_BASE_ADDR) + 0x64)
+
+#define MXC_CCM_MPCTL_BRMO			(1 << 31)
+#define MXC_CCM_MPCTL_PD_OFFSET			26
+#define MXC_CCM_MPCTL_PD_MASK			(0xf << 26)
+#define MXC_CCM_MPCTL_MFD_OFFSET		16
+#define MXC_CCM_MPCTL_MFD_MASK			(0x3ff << 16)
+#define MXC_CCM_MPCTL_MFI_OFFSET		10
+#define MXC_CCM_MPCTL_MFI_MASK			(0xf << 10)
+#define MXC_CCM_MPCTL_MFN_OFFSET		0
+#define MXC_CCM_MPCTL_MFN_MASK			0x3ff
+#define MXC_CCM_MPCTL_LF			(1 << 15)
+
+#define MXC_CCM_UPCTL_BRMO			(1 << 31)
+#define MXC_CCM_UPCTL_PD_OFFSET			26
+#define MXC_CCM_UPCTL_PD_MASK			(0xf << 26)
+#define MXC_CCM_UPCTL_MFD_OFFSET		16
+#define MXC_CCM_UPCTL_MFD_MASK			(0x3ff << 16)
+#define MXC_CCM_UPCTL_MFI_OFFSET		10
+#define MXC_CCM_UPCTL_MFI_MASK			(0xf << 10)
+#define MXC_CCM_UPCTL_MFN_OFFSET		0
+#define MXC_CCM_UPCTL_MFN_MASK			0x3ff
+#define MXC_CCM_UPCTL_LF			(1 << 15)
+
+#define MXC_CCM_CCTL_ARM_OFFSET			30
+#define MXC_CCM_CCTL_ARM_MASK			(0x3 << 30)
+#define MXC_CCM_CCTL_AHB_OFFSET			28
+#define MXC_CCM_CCTL_AHB_MASK			(0x3 << 28)
+#define MXC_CCM_CCTL_MPLL_RST			(1 << 27)
+#define MXC_CCM_CCTL_UPLL_RST			(1 << 26)
+#define MXC_CCM_CCTL_LP_CTL_OFFSET		24
+#define MXC_CCM_CCTL_LP_CTL_MASK		(0x3 << 24)
+#define MXC_CCM_CCTL_LP_MODE_RUN		(0x0 << 24)
+#define MXC_CCM_CCTL_LP_MODE_WAIT		(0x1 << 24)
+#define MXC_CCM_CCTL_LP_MODE_DOZE		(0x2 << 24)
+#define MXC_CCM_CCTL_LP_MODE_STOP		(0x3 << 24)
+#define MXC_CCM_CCTL_UPLL_DISABLE		(1 << 23)
+#define MXC_CCM_CCTL_MPLL_BYPASS		(1 << 22)
+#define MXC_CCM_CCTL_USB_DIV_OFFSET		16
+#define MXC_CCM_CCTL_USB_DIV_MASK		(0x3 << 16)
+#define MXC_CCM_CCTL_CG_CTRL			(1 << 15)
+#define MXC_CCM_CCTL_ARM_SRC			(1 << 14)
+
+#define MXC_CCM_CGCR0_HCLK_ATA_OFFSET		(16 + 0)
+#define MXC_CCM_CGCR0_HCLK_BROM_OFFSET		(16 + 1)
+#define MXC_CCM_CGCR0_HCLK_CSI_OFFSET		(16 + 2)
+#define MXC_CCM_CGCR0_HCLK_EMI_OFFSET		(16 + 3)
+#define MXC_CCM_CGCR0_HCLK_ESAI_OFFSET		(16 + 4)
+#define MXC_CCM_CGCR0_HCLK_ESDHC1_OFFSET	(16 + 5)
+#define MXC_CCM_CGCR0_HCLK_ESDHC2_OFFSET	(16 + 6)
+#define MXC_CCM_CGCR0_HCLK_FEC_OFFSET		(16 + 7)
+#define MXC_CCM_CGCR0_HCLK_LCDC_OFFSET		(16 + 8)
+#define MXC_CCM_CGCR0_HCLK_RTIC_OFFSET		(16 + 9)
+#define MXC_CCM_CGCR0_HCLK_SDMA_OFFSET		(16 + 10)
+#define MXC_CCM_CGCR0_HCLK_SLCDC_OFFSET		(16 + 11)
+#define MXC_CCM_CGCR0_HCLK_USBOTG_OFFSET	(16 + 12)
+
+#define MXC_CCM_CGCR0_PER_CSI_OFFSET		 0
+#define MXC_CCM_CGCR0_PER_EPIT_OFFSET		 1
+#define MXC_CCM_CGCR0_PER_ESAI_OFFSET		 2
+#define MXC_CCM_CGCR0_PER_ESDHC1_OFFSET		 3
+#define MXC_CCM_CGCR0_PER_ESDHC2_OFFSET		 4
+#define MXC_CCM_CGCR0_PER_GPT_OFFSET		 5
+#define MXC_CCM_CGCR0_PER_I2C_OFFSET		 6
+#define MXC_CCM_CGCR0_PER_LCDC_OFFSET		 7
+#define MXC_CCM_CGCR0_PER_NFC_OFFSET		 8
+#define MXC_CCM_CGCR0_PER_OWIRE_OFFSET		 9
+#define MXC_CCM_CGCR0_PER_PWM_OFFSET		10
+#define MXC_CCM_CGCR0_PER_SIM1_OFFSET		11
+#define MXC_CCM_CGCR0_PER_SIM2_OFFSET		12
+#define MXC_CCM_CGCR0_PER_SSI1_OFFSET		13
+#define MXC_CCM_CGCR0_PER_SSI2_OFFSET		14
+#define MXC_CCM_CGCR0_PER_UART_OFFSET		15
+
+#define MXC_CCM_CGCR1_AUDMUX_OFFSET		 0
+#define MXC_CCM_CGCR1_ATA_OFFSET		 1
+#define MXC_CCM_CGCR1_CAN1_OFFSET		 2
+#define MXC_CCM_CGCR1_CAN2_OFFSET		 3
+#define MXC_CCM_CGCR1_CSI_OFFSET		 4
+#define MXC_CCM_CGCR1_CSPI1_OFFSET		 5
+#define MXC_CCM_CGCR1_CSPI2_OFFSET		 6
+#define MXC_CCM_CGCR1_CSPI3_OFFSET		 7
+#define MXC_CCM_CGCR1_DRYICE_OFFSET		 8
+#define MXC_CCM_CGCR1_ECT_OFFSET		 9
+#define MXC_CCM_CGCR1_EPIT1_OFFSET		10
+#define MXC_CCM_CGCR1_EPIT2_OFFSET		11
+#define MXC_CCM_CGCR1_ESAI_OFFSET		12
+#define MXC_CCM_CGCR1_ESDHC1_OFFSET		13
+#define MXC_CCM_CGCR1_ESDHC2_OFFSET		14
+#define MXC_CCM_CGCR1_FEC_OFFSET		15
+#define MXC_CCM_CGCR1_GPIO1_OFFSET		16
+#define MXC_CCM_CGCR1_GPIO2_OFFSET		17
+#define MXC_CCM_CGCR1_GPIO3_OFFSET		18
+#define MXC_CCM_CGCR1_GPT1_OFFSET		19
+#define MXC_CCM_CGCR1_GPT2_OFFSET		20
+#define MXC_CCM_CGCR1_GPT3_OFFSET		21
+#define MXC_CCM_CGCR1_GPT4_OFFSET		22
+#define MXC_CCM_CGCR1_I2C1_OFFSET		23
+#define MXC_CCM_CGCR1_I2C2_OFFSET		24
+#define MXC_CCM_CGCR1_I2C3_OFFSET		25
+#define MXC_CCM_CGCR1_IIM_OFFSET		26
+#define MXC_CCM_CGCR1_IOMUXC_OFFSET		27
+#define MXC_CCM_CGCR1_KPP_OFFSET		28
+#define MXC_CCM_CGCR1_LCDC_OFFSET		29
+#define MXC_CCM_CGCR1_OWIRE_OFFSET		30
+#define MXC_CCM_CGCR1_PWM1_OFFSET		31
+
+#define MXC_CCM_CGCR2_PWM2_OFFSET		(32 - 32)
+#define MXC_CCM_CGCR2_PWM3_OFFSET		(33 - 32)
+#define MXC_CCM_CGCR2_PWM4_OFFSET		(34 - 32)
+#define MXC_CCM_CGCR2_RNGB_OFFSET		(35 - 32)
+#define MXC_CCM_CGCR2_RTIC_OFFSET		(36 - 32)
+#define MXC_CCM_CGCR2_SCC_OFFSET		(37 - 32)
+#define MXC_CCM_CGCR2_SDMA_OFFSET		(38 - 32)
+#define MXC_CCM_CGCR2_SIM1_OFFSET		(39 - 32)
+#define MXC_CCM_CGCR2_SIM2_OFFSET		(40 - 32)
+#define MXC_CCM_CGCR2_SLCDC_OFFSET		(41 - 32)
+#define MXC_CCM_CGCR2_SPBA_OFFSET		(42 - 32)
+#define MXC_CCM_CGCR2_SSI1_OFFSET		(43 - 32)
+#define MXC_CCM_CGCR2_SSI2_OFFSET		(44 - 32)
+#define MXC_CCM_CGCR2_TSC_OFFSET		(45 - 32)
+#define MXC_CCM_CGCR2_UART1_OFFSET		(46 - 32)
+#define MXC_CCM_CGCR2_UART2_OFFSET		(47 - 32)
+#define MXC_CCM_CGCR2_UART3_OFFSET		(48 - 32)
+#define MXC_CCM_CGCR2_UART4_OFFSET		(49 - 32)
+#define MXC_CCM_CGCR2_UART5_OFFSET		(50 - 32)
+#define MXC_CCM_CGCR2_WDOG_OFFSET		(51 - 32)
+
+#define MXC_CCM_PCDR1_PERDIV1_MASK		0x3f
+
+#define MXC_CCM_MCR_USB_XTAL_MUX_OFFSET		31
+#define MXC_CCM_MCR_CLKO_EN_OFFSET		30
+#define MXC_CCM_MCR_CLKO_DIV_OFFSET		24
+#define MXC_CCM_MCR_CLKO_DIV_MASK		(0x3F << 24)
+#define MXC_CCM_MCR_CLKO_SEL_OFFSET		20
+#define MXC_CCM_MCR_CLKO_SEL_MASK		(0xF << 20)
+#define MXC_CCM_MCR_ESAI_CLK_MUX_OFFSET		19
+#define MXC_CCM_MCR_SSI2_CLK_MUX_OFFSET		18
+#define MXC_CCM_MCR_SSI1_CLK_MUX_OFFSET		17
+#define MXC_CCM_MCR_USB_CLK_MUX_OFFSET		16
+
+#define MXC_CCM_MCR_PER_CLK_MUX_MASK		(0xFFFF << 0)
+
+#define OSC24M_CLK_FREQ		24000000 /* 24MHz reference clk */
+#define OSC32K_CLK_FREQ		32768	/* 32.768kHz oscillator in */
+
+static struct clk mpll_clk;
+static struct clk upll_clk;
+static struct clk ahb_clk;
+static struct clk upll_24610k_clk;
+
+static int _clk_enable(struct clk *clk)
+{
+	unsigned long reg;
+
+	if (!clk->enable_reg)
+		return 0;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg |= 1 << clk->enable_shift;
+	__raw_writel(reg, clk->enable_reg);
+
+	return 0;
+}
+
+static void _clk_disable(struct clk *clk)
+{
+	unsigned long reg;
+
+	if (!clk->enable_reg)
+		return;
+
+	reg = __raw_readl(clk->enable_reg);
+	reg &= ~(1 << clk->enable_shift);
+	__raw_writel(reg, clk->enable_reg);
+}
+
+static int _clk_upll_enable(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(MXC_CCM_CCTL);
+	reg &= ~MXC_CCM_CCTL_UPLL_DISABLE;
+	__raw_writel(reg, MXC_CCM_CCTL);
+
+	while (!(__raw_readl(MXC_CCM_UPCTL) & MXC_CCM_UPCTL_LF))
+		cpu_relax();
+
+	return 0;
+}
+
+static void _clk_upll_disable(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(MXC_CCM_CCTL);
+	reg |= MXC_CCM_CCTL_UPLL_DISABLE;
+	__raw_writel(reg, MXC_CCM_CCTL);
+}
+
+static int _perclk_enable(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(MXC_CCM_CGCR0);
+	reg |= 1 << clk->id;
+	__raw_writel(reg, MXC_CCM_CGCR0);
+
+	return 0;
+}
+
+static void _perclk_disable(struct clk *clk)
+{
+	unsigned long reg;
+
+	reg = __raw_readl(MXC_CCM_CGCR0);
+	reg &= ~(1 << clk->id);
+	__raw_writel(reg, MXC_CCM_CGCR0);
+}
+
+static int _clk_pll_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long reg;
+	unsigned int pd = 1;	/* Pre-divider */
+	unsigned long mfi;	/* Multiplication Factor (Integer part) */
+	signed long mfn;	/* Multiplication Factor (Integer part) */
+	unsigned long mfd;	/* Multiplication Factor (Denominator Part) */
+	signed long tmp;
+	unsigned long ref_freq = clk_get_rate(clk->parent);
+	unsigned long err = ~0;
+	int best_mfn = -1;
+	int best_mfd = -1;
+
+	while (((ref_freq / pd) * 10) > rate)
+		pd++;
+
+	mfi = ((rate / 2) * pd) / ref_freq;
+	if (mfi < 5 || mfi > 15)
+		return -EINVAL;
+
+	tmp = ref_freq / 10000;
+	for (mfd = 1; mfd <= 1024; mfd++) {
+		unsigned long act_freq;
+
+		mfn = ((((((rate / 2) + (tmp - 1)) / tmp) * pd) * mfd) / 10000) -
+			(mfi * mfd);
+
+		act_freq = (2 * ref_freq * mfi + (2 * ref_freq * mfn / mfd)) / pd;
+		act_freq -= rate;
+		if (abs(act_freq) < err) {
+			best_mfn = mfn;
+			best_mfd = mfd;
+			err = abs(act_freq);
+			if (err == 0)
+				break;
+		}
+	}
+	mfn = best_mfn;
+	mfd = best_mfd;
+
+	mfn = (mfn + ((mfn < 0) ? 1024 : 0)) & 0x3ff;
+	pd--;
+	mfd--;
+
+	/* Change the Pll value */
+	reg = (mfi << MXC_CCM_MPCTL_MFI_OFFSET) |
+		(mfn << MXC_CCM_MPCTL_MFN_OFFSET) |
+		(mfd << MXC_CCM_MPCTL_MFD_OFFSET) |
+		(pd << MXC_CCM_MPCTL_PD_OFFSET);
+
+	if (clk == &mpll_clk) {
+		printk(KERN_DEBUG "Changing MPCTL from %08x to %08lx\n",
+		       __raw_readl(MXC_CCM_MPCTL), reg);
+	} else if (clk == &upll_clk) {
+		printk(KERN_DEBUG "Changing UPCTL from %08x to %08lx\n",
+		       __raw_readl(MXC_CCM_UPCTL), reg);
+	}
+	if (clk == &mpll_clk)
+		__raw_writel(reg, MXC_CCM_MPCTL);
+	else if (clk == &upll_clk)
+		__raw_writel(reg, MXC_CCM_UPCTL);
+	return 0;
+}
+
+static unsigned long _clk_pll_getrate(struct clk *clk)
+{
+	unsigned long rate;
+	unsigned int mfi, mfd, pdf;
+	int mfn;
+	unsigned long ref_clk;
+	unsigned long reg;
+
+	ref_clk = clk_get_rate(clk->parent);
+
+	if (clk == &mpll_clk) {
+		reg = __raw_readl(MXC_CCM_MPCTL);
+		pdf = (reg & MXC_CCM_MPCTL_PD_MASK) >> MXC_CCM_MPCTL_PD_OFFSET;
+		mfd = (reg & MXC_CCM_MPCTL_MFD_MASK) >> MXC_CCM_MPCTL_MFD_OFFSET;
+		mfi = (reg & MXC_CCM_MPCTL_MFI_MASK) >> MXC_CCM_MPCTL_MFI_OFFSET;
+		mfn = (reg & MXC_CCM_MPCTL_MFN_MASK) >> MXC_CCM_MPCTL_MFN_OFFSET;
+	} else if (clk == &upll_clk) {
+		reg = __raw_readl(MXC_CCM_UPCTL);
+		pdf = (reg & MXC_CCM_UPCTL_PD_MASK) >> MXC_CCM_UPCTL_PD_OFFSET;
+		mfd = (reg & MXC_CCM_UPCTL_MFD_MASK) >> MXC_CCM_UPCTL_MFD_OFFSET;
+		mfi = (reg & MXC_CCM_UPCTL_MFI_MASK) >> MXC_CCM_UPCTL_MFI_OFFSET;
+		mfn = (reg & MXC_CCM_UPCTL_MFN_MASK) >> MXC_CCM_UPCTL_MFN_OFFSET;
+	} else {
+		BUG();		/* oops */
+	}
+
+	if (mfn >= 512)
+		mfn = 1024 - mfn;
+
+	mfi = (mfi < 5) ? 5 : mfi;
+	rate = 2LL * ref_clk * mfn;
+	do_div(rate, mfd + 1);
+	rate = 2LL * ref_clk * mfi + rate;
+	do_div(rate, pdf + 1);
+
+	return rate;
+}
+
+static unsigned long _clk_cpu_round_rate(struct clk *clk, unsigned long rate)
+{
+	int div = clk_get_rate(clk->parent) / rate;
+
+	if (clk_get_rate(clk->parent) % rate)
+		div++;
+
+	if (div > 4)
+		div = 4;
+
+	return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_cpu_set_rate(struct clk *clk, unsigned long rate)
+{
+	int div, reg;
+	unsigned long cctl = __raw_readl(MXC_CCM_CCTL);
+
+	div = clk_get_rate(clk->parent) / rate;
+
+	if (div > 4 || div < 1 || ((clk_get_rate(clk->parent) / div) != rate))
+		return -EINVAL;
+	div--;
+
+	reg = (cctl & ~MXC_CCM_CCTL_ARM_MASK) |
+		(div << MXC_CCM_CCTL_ARM_OFFSET);
+	__raw_writel(reg, MXC_CCM_CCTL);
+
+	return 0;
+}
+
+static unsigned long _clk_cpu_getrate(struct clk *clk)
+{
+	unsigned long div;
+	unsigned long cctl = __raw_readl(MXC_CCM_CCTL);
+	unsigned long rate;
+
+	div = (cctl & MXC_CCM_CCTL_ARM_MASK) >> MXC_CCM_CCTL_ARM_OFFSET;
+
+	rate = clk_get_rate(clk->parent) / (div + 1);
+
+	if (cctl & MXC_CCM_CCTL_ARM_SRC) {
+		rate *= 3;
+		rate /= 4;
+	}
+	return rate;
+}
+
+static unsigned long _clk_ahb_getrate(struct clk *clk)
+{
+	unsigned long div;
+	unsigned long cctl = __raw_readl(MXC_CCM_CCTL);
+
+	div = (cctl & MXC_CCM_CCTL_AHB_MASK) >> MXC_CCM_CCTL_AHB_OFFSET;
+
+	return clk_get_rate(clk->parent) / (div + 1);
+}
+
+static void __iomem *pcdr_a[4] = {
+	MXC_CCM_PCDR0, MXC_CCM_PCDR1, MXC_CCM_PCDR2, MXC_CCM_PCDR3
+};
+
+static unsigned long _clk_perclkx_getrate(struct clk *clk)
+{
+	unsigned long perclk_pdf;
+	unsigned long pcdr;
+
+	if (clk->id < 0 || clk->id > 15)
+		return 0;
+
+	pcdr = __raw_readl(pcdr_a[clk->id >> 2]);
+
+	perclk_pdf = (pcdr >> ((clk->id & 3) << 3)) &
+		MXC_CCM_PCDR1_PERDIV1_MASK;
+
+	return clk_get_rate(clk->parent) / (perclk_pdf + 1);
+}
+
+static unsigned long _clk_perclkx_round_rate(struct clk *clk,
+					     unsigned long rate)
+{
+	unsigned long div;
+
+	div = clk_get_rate(clk->parent) / rate;
+	if (clk_get_rate(clk->parent) % rate)
+		div++;
+
+	if (div > 64)
+		div = 64;
+
+	return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_perclkx_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long reg;
+	unsigned long div;
+
+	if (clk->id < 0 || clk->id > 15)
+		return -EINVAL;
+
+	div = clk_get_rate(clk->parent) / rate;
+	if (div > 64 || div < 1 || ((clk_get_rate(clk->parent) / div) != rate))
+		return -EINVAL;
+	div--;
+
+	reg =
+	    __raw_readl(pcdr_a[clk->id >> 2]) & ~(MXC_CCM_PCDR1_PERDIV1_MASK <<
+						  ((clk->id & 3) << 3));
+	reg |= div << ((clk->id & 3) << 3);
+	__raw_writel(reg, pcdr_a[clk->id >> 2]);
+
+	return 0;
+}
+
+static int _clk_perclkx_set_parent(struct clk *clk, struct clk *parent)
+{
+	unsigned long mcr;
+
+	if (clk->parent == parent)
+		return 0;
+	if (parent != &upll_clk && parent != &ahb_clk)
+		return -EINVAL;
+
+	clk->parent = parent;
+	mcr = __raw_readl(MXC_CCM_MCR);
+	if (parent == &upll_clk)
+		mcr |= (1 << clk->id);
+	else
+		mcr &= ~(1 << clk->id);
+
+	__raw_writel(mcr, MXC_CCM_MCR);
+
+	return 0;
+}
+
+static int _clk_perclkx_set_parent3(struct clk *clk, struct clk *parent)
+{
+	unsigned long mcr = __raw_readl(MXC_CCM_MCR);
+	int bit;
+
+	if (clk->parent == parent)
+		return 0;
+	if (parent != &upll_clk && parent != &ahb_clk &&
+	    parent != &upll_24610k_clk)
+		return -EINVAL;
+
+	switch (clk->id) {
+	case 2:
+		bit = MXC_CCM_MCR_ESAI_CLK_MUX_OFFSET;
+		break;
+	case 13:
+		bit = MXC_CCM_MCR_SSI1_CLK_MUX_OFFSET;
+		break;
+	case 14:
+		bit = MXC_CCM_MCR_SSI2_CLK_MUX_OFFSET;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (parent == &upll_24610k_clk) {
+		mcr |= bit;
+		__raw_writel(mcr, MXC_CCM_MCR);
+		clk->parent = parent;
+	} else {
+		mcr &= ~bit;
+		__raw_writel(mcr, MXC_CCM_MCR);
+		return _clk_perclkx_set_parent(clk, parent);
+	}
+
+	return 0;
+}
+
+static unsigned long _clk_ipg_getrate(struct clk *clk)
+{
+	unsigned long rate = clk_get_rate(clk->parent) / 2;	/* Always AHB / 2 */
+	return rate;
+}
+
+/* Top-level clocks */
+static unsigned long ckih_rate = OSC24M_CLK_FREQ;
+
+static unsigned long clk_ckih_get_rate(struct clk *clk)
+{
+	return ckih_rate;
+}
+
+static unsigned long clk_ckil_get_rate(struct clk *clk)
+{
+	return OSC32K_CLK_FREQ;
+}
+
+static struct clk osc24m_clk = {
+	.get_rate = clk_ckih_get_rate,
+};
+
+static struct clk osc32k_clk = {
+	.get_rate = clk_ckil_get_rate,
+};
+
+static struct clk mpll_clk = {
+	.parent = &osc24m_clk,
+	.get_rate = _clk_pll_getrate,
+	.set_rate = _clk_pll_set_rate,
+};
+
+static struct clk upll_clk = {
+	.parent = &osc24m_clk,
+	.get_rate = _clk_pll_getrate,
+	.set_rate = _clk_pll_set_rate,
+	.enable = _clk_upll_enable,
+	.disable = _clk_upll_disable,
+};
+
+static unsigned long _clk_24610k_getrate(struct clk *clk)
+{
+	long long rate = clk_get_rate(clk->parent) * 2461LL;
+
+	do_div(rate, 24000);
+
+	return rate;	/* Always (UPLL * 24.61 / 240) */
+}
+
+static struct clk upll_24610k_clk = {
+	.parent = &upll_clk,
+	.get_rate = _clk_24610k_getrate,
+};
+
+/* Mid-level clocks */
+
+static struct clk cpu_clk = {	/* ARM clock */
+	.parent = &mpll_clk,
+	.set_rate = _clk_cpu_set_rate,
+	.get_rate = _clk_cpu_getrate,
+	.round_rate = _clk_cpu_round_rate,
+};
+
+static struct clk ahb_clk = {	/* a.k.a. HCLK */
+	.parent = &cpu_clk,
+	.get_rate = _clk_ahb_getrate,
+};
+
+static struct clk ipg_clk = {
+	.parent = &ahb_clk,
+	.get_rate = _clk_ipg_getrate,
+};
+
+/* Bottom-level clocks */
+
+static struct clk usbotg_clk = {
+	.id = 0,
+	.parent = &ahb_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR0,
+	.enable_shift = MXC_CCM_CGCR0_HCLK_USBOTG_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk rtic_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_RTIC_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &rtic_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ahb_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR0,
+		.enable_shift = MXC_CCM_CGCR0_HCLK_RTIC_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk emi_clk = {
+	.id = 0,
+	.parent = &ahb_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR0,
+	.enable_shift = MXC_CCM_CGCR0_HCLK_EMI_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk brom_clk = {
+	.id = 0,
+	.parent = &ahb_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR0,
+	.enable_shift = MXC_CCM_CGCR0_HCLK_BROM_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk per_clk[] = {
+	{
+		.id = 0,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 1,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 2,
+		.parent = &ahb_clk,	/* can be AHB or UPLL or 24.61MHz */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent3,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 3,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+	},
+	{
+		.id = 4,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 5,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 6,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 7,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 8,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 9,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 10,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 11,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 12,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 13,
+		.parent = &ahb_clk,	/* can be AHB or UPLL or 24.61MHz */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent3,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 14,
+		.parent = &ahb_clk,	/* can be AHB or UPLL or 24.61MHz */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent3,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+	{
+		.id = 15,
+		.parent = &ahb_clk,	/* can be AHB or UPLL */
+		.round_rate = _clk_perclkx_round_rate,
+		.set_rate = _clk_perclkx_set_rate,
+		.set_parent = _clk_perclkx_set_parent,
+		.get_rate = _clk_perclkx_getrate,
+		.enable = _perclk_enable,
+		.disable = _perclk_disable,
+	},
+};
+
+static struct clk nfc_clk = {
+	.id = 0,
+	.parent = &per_clk[8],
+};
+
+static struct clk audmux_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR1,
+	.enable_shift = MXC_CCM_CGCR1_AUDMUX_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk ata_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_ATA_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &ata_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ahb_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR0,
+		.enable_shift = MXC_CCM_CGCR0_HCLK_ATA_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk can_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_CAN1_OFFSET,
+		.disable = _clk_disable,
+	},
+	{
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_CAN2_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk csi_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[0],
+		.secondary = &csi_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_CSI_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &csi_clk[2],
+	},
+	{
+		.id = 0,
+		.parent = &ahb_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR0,
+		.enable_shift = MXC_CCM_CGCR0_HCLK_CSI_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk cspi_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_CSPI1_OFFSET,
+		.disable = _clk_disable,
+	},
+	{
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_CSPI2_OFFSET,
+		.disable = _clk_disable,
+	},
+	{
+		.id = 2,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_CSPI3_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk dryice_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR1,
+	.enable_shift = MXC_CCM_CGCR1_DRYICE_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk ect_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR1,
+	.enable_shift = MXC_CCM_CGCR1_ECT_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk epit1_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[1],
+		.secondary = &epit1_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_EPIT1_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk epit2_clk[] = {
+	{
+		.id = 1,
+		.parent = &per_clk[1],
+		.secondary = &epit2_clk[1],
+	},
+	{
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_EPIT2_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk esai_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[2],
+		.secondary = &esai_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_ESAI_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &esai_clk[2],
+	},
+	{
+		.id = 0,
+		.parent = &ahb_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR0,
+		.enable_shift = MXC_CCM_CGCR0_HCLK_ESAI_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk esdhc1_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[3],
+		.secondary = &esdhc1_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_ESDHC1_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &esdhc1_clk[2],
+	},
+	{
+		.id = 0,
+		.parent = &ahb_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR0,
+		.enable_shift = MXC_CCM_CGCR0_HCLK_ESDHC1_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk esdhc2_clk[] = {
+	{
+		.id = 1,
+		.parent = &per_clk[4],
+		.secondary = &esdhc2_clk[1],
+	},
+	{
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_ESDHC2_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &esdhc2_clk[2],
+	},
+	{
+		.id = 1,
+		.parent = &ahb_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR0,
+		.enable_shift = MXC_CCM_CGCR0_HCLK_ESDHC2_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk fec_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_FEC_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &fec_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ahb_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR0,
+		.enable_shift = MXC_CCM_CGCR0_HCLK_FEC_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk gpio_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_GPIO1_OFFSET,
+		.disable = _clk_disable,
+	},
+	{
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_GPIO2_OFFSET,
+		.disable = _clk_disable,
+	},
+	{
+		.id = 2,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_GPIO3_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk gpt1_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[5],
+		.secondary = &gpt1_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_GPT1_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk gpt2_clk[] = {
+	{
+		.id = 1,
+		.parent = &per_clk[5],
+		.secondary = &gpt2_clk[1],
+	},
+	{
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_GPT2_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk gpt3_clk[] = {
+	{
+		.id = 2,
+		.parent = &per_clk[5],
+		.secondary = &gpt3_clk[1],
+	},
+	{
+		.id = 2,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_GPT3_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk gpt4_clk[] = {
+	{
+		.id = 3,
+		.parent = &per_clk[5],
+		.secondary = &gpt4_clk[1],
+	},
+	{
+		.id = 3,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_GPT4_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk i2c_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[6],
+	},
+	{
+		.id = 1,
+		.parent = &per_clk[6],
+	},
+	{
+		.id = 2,
+		.parent = &per_clk[6],
+	},
+};
+
+static struct clk iim_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR1,
+	.enable_shift = MXC_CCM_CGCR1_IIM_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk iomuxc_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR1,
+	.enable_shift = MXC_CCM_CGCR1_IOMUXC_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk kpp_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR1,
+	.enable_shift = MXC_CCM_CGCR1_KPP_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk lcdc_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[7],
+		.secondary = &lcdc_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_LCDC_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &lcdc_clk[2],
+	},
+	{
+		.id = 0,
+		.parent = &ahb_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR0,
+		.enable_shift = MXC_CCM_CGCR0_HCLK_LCDC_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk owire_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[9],
+		.secondary = &owire_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_OWIRE_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk pwm1_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[10],
+		.secondary = &pwm1_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR1,
+		.enable_shift = MXC_CCM_CGCR1_PWM1_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk pwm2_clk[] = {
+	{
+		.id = 1,
+		.parent = &per_clk[10],
+		.secondary = &pwm2_clk[1],
+	},
+	{
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_PWM2_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk pwm3_clk[] = {
+	{
+		.id = 2,
+		.parent = &per_clk[10],
+		.secondary = &pwm3_clk[1],
+	},
+	{
+		.id = 2,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_PWM3_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk pwm4_clk[] = {
+	{
+		.id = 3,
+		.parent = &per_clk[10],
+		.secondary = &pwm4_clk[1],
+	},
+	{
+		.id = 3,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_PWM3_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk rngb_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR2,
+	.enable_shift = MXC_CCM_CGCR2_RNGB_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk scc_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR2,
+	.enable_shift = MXC_CCM_CGCR2_SCC_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk sdma_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_SDMA_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &sdma_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ahb_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR0,
+		.enable_shift = MXC_CCM_CGCR0_HCLK_SDMA_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk sim1_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[11],
+		.secondary = &sim1_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_SIM1_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk sim2_clk[] = {
+	{
+		.id = 1,
+		.parent = &per_clk[12],
+		.secondary = &sim2_clk[1],
+	},
+	{
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_SIM2_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk slcdc_clk[] = {
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_SLCDC_OFFSET,
+		.disable = _clk_disable,
+		.secondary = &slcdc_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ahb_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR0,
+		.enable_shift = MXC_CCM_CGCR0_HCLK_SLCDC_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk spba_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR2,
+	.enable_shift = MXC_CCM_CGCR2_SPBA_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk ssi1_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[13],
+		.secondary = &ssi1_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_SSI1_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk ssi2_clk[] = {
+	{
+		.id = 1,
+		.parent = &per_clk[14],
+		.secondary = &ssi2_clk[1],
+	},
+	{
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_SSI2_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk tsc_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR2,
+	.enable_shift = MXC_CCM_CGCR2_TSC_OFFSET,
+	.disable = _clk_disable,
+};
+
+static struct clk uart1_clk[] = {
+	{
+		.id = 0,
+		.parent = &per_clk[15],
+		.secondary = &uart1_clk[1],
+	},
+	{
+		.id = 0,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_UART1_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk uart2_clk[] = {
+	{
+		.id = 1,
+		.parent = &per_clk[15],
+		.secondary = &uart2_clk[1],
+	},
+	{
+		.id = 1,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_UART2_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk uart3_clk[] = {
+	{
+		.id = 2,
+		.parent = &per_clk[15],
+		.secondary = &uart3_clk[1],
+	},
+	{
+		.id = 2,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_UART3_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk uart4_clk[] = {
+	{
+		.id = 3,
+		.parent = &per_clk[15],
+		.secondary = &uart4_clk[1],
+	},
+	{
+		.id = 3,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_UART4_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk uart5_clk[] = {
+	{
+		.id = 4,
+		.parent = &per_clk[15],
+		.secondary = &uart5_clk[1],
+	},
+	{
+		.id = 4,
+		.parent = &ipg_clk,
+		.enable = _clk_enable,
+		.enable_reg = MXC_CCM_CGCR2,
+		.enable_shift = MXC_CCM_CGCR2_UART5_OFFSET,
+		.disable = _clk_disable,
+	},
+};
+
+static struct clk wdog_clk = {
+	.id = 0,
+	.parent = &ipg_clk,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_CGCR2,
+	.enable_shift = MXC_CCM_CGCR2_WDOG_OFFSET,
+	.disable = _clk_disable,
+};
+
+static unsigned long _clk_usb_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long div;
+
+	div = clk_get_rate(clk->parent) / rate;
+	if (clk_get_rate(clk->parent) % rate)
+		div++;
+
+	if (div > 64)
+		return -EINVAL;
+
+	return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_usb_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long reg;
+	unsigned long div;
+
+	div = clk_get_rate(clk->parent) / rate;
+
+	if (clk_get_rate(clk->parent) / div != rate)
+		return -EINVAL;
+	if (div > 64)
+		return -EINVAL;
+
+	reg = __raw_readl(MXC_CCM_CCTL) & ~MXC_CCM_CCTL_USB_DIV_MASK;
+	reg |= (div - 1) << MXC_CCM_CCTL_USB_DIV_OFFSET;
+	__raw_writel(reg, MXC_CCM_MCR);
+
+	return 0;
+}
+
+static unsigned long _clk_usb_getrate(struct clk *clk)
+{
+	unsigned long div;
+
+	div = __raw_readl(MXC_CCM_MCR) & MXC_CCM_CCTL_USB_DIV_MASK;
+	div >>= MXC_CCM_CCTL_USB_DIV_OFFSET;
+
+	return clk_get_rate(clk->parent) / (div + 1);
+}
+
+static int _clk_usb_set_parent(struct clk *clk, struct clk *parent)
+{
+	unsigned long mcr;
+
+	if (clk->parent == parent)
+		return 0;
+	if (parent != &upll_clk && parent != &ahb_clk)
+		return -EINVAL;
+
+	clk->parent = parent;
+	mcr = __raw_readl(MXC_CCM_MCR);
+	if (parent == &ahb_clk)
+		mcr |= (1 << MXC_CCM_MCR_USB_CLK_MUX_OFFSET);
+	else
+		mcr &= ~(1 << MXC_CCM_MCR_USB_CLK_MUX_OFFSET);
+
+	__raw_writel(mcr, MXC_CCM_MCR);
+
+	return 0;
+}
+
+static struct clk usb_clk = {
+	.parent = &upll_clk,
+	.get_rate = _clk_usb_getrate,
+	.set_rate = _clk_usb_set_rate,
+	.round_rate = _clk_usb_round_rate,
+	.set_parent = _clk_usb_set_parent,
+	.secondary = &usbotg_clk,
+};
+
+/* CLKO */
+
+static unsigned long _clk_clko_round_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long div;
+
+	div = clk_get_rate(clk->parent) / rate;
+	if (clk_get_rate(clk->parent) % rate)
+		div++;
+
+	if (div > 64)
+		return -EINVAL;
+
+	return clk_get_rate(clk->parent) / div;
+}
+
+static int _clk_clko_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long reg;
+	unsigned long div;
+
+	div = clk_get_rate(clk->parent) / rate;
+
+	if ((clk_get_rate(clk->parent) / div) != rate)
+		return -EINVAL;
+	if (div > 64)
+		return -EINVAL;
+
+	reg = __raw_readl(MXC_CCM_MCR) & ~MXC_CCM_MCR_CLKO_DIV_MASK;
+	reg |= (div - 1) << MXC_CCM_MCR_CLKO_DIV_OFFSET;
+	__raw_writel(reg, MXC_CCM_MCR);
+
+	return 0;
+}
+
+static unsigned long _clk_clko_getrate(struct clk *clk)
+{
+	unsigned long div = __raw_readl(MXC_CCM_MCR);
+
+	div &= MXC_CCM_MCR_CLKO_DIV_MASK;
+	div >>= MXC_CCM_MCR_CLKO_DIV_OFFSET;
+
+	return clk_get_rate(clk->parent) / (div + 1);
+}
+
+static struct clk *clko_sources[] = {
+	&osc32k_clk,		/* 0x0 */
+	&osc24m_clk,		/* 0x1 */
+	&cpu_clk,		/* 0x2 */
+	&ahb_clk,		/* 0x3 */
+	&ipg_clk,		/* 0x4 */
+	NULL,			/* 0x5 */
+	NULL,			/* 0x6 */
+	NULL,			/* 0x7 */
+	NULL,			/* 0x8 */
+	NULL,			/* 0x9 */
+	&per_clk[0],		/* 0xA */
+	&per_clk[2],		/* 0xB */
+	&per_clk[13],		/* 0xC */
+	&per_clk[14],		/* 0xD */
+	&usb_clk,		/* 0xE */
+	NULL,			/* 0xF */
+};
+
+#define NR_CLKO_SOURCES (sizeof(clko_sources) / sizeof(struct clk *))
+
+static int _clk_clko_set_parent(struct clk *clk, struct clk *parent)
+{
+	unsigned long reg;
+	struct clk **src;
+	int i;
+
+	if (clk->parent == parent)
+		return 0;
+	for (i = 0, src = clko_sources; i < NR_CLKO_SOURCES; i++, src++)
+		if (*src == parent)
+			break;
+
+	if (i == NR_CLKO_SOURCES)
+		return -EINVAL;
+
+	clk->parent = parent;
+
+	reg = __raw_readl(MXC_CCM_MCR) & ~MXC_CCM_MCR_CLKO_SEL_MASK;
+	reg |= i << MXC_CCM_MCR_CLKO_SEL_OFFSET;
+	__raw_writel(reg, MXC_CCM_MCR);
+
+	return 0;
+}
+
+static struct clk clko_clk = {
+	.set_rate = _clk_clko_set_rate,
+	.round_rate = _clk_clko_round_rate,
+	.set_parent = _clk_clko_set_parent,
+	.get_rate = _clk_clko_getrate,
+	.enable = _clk_enable,
+	.enable_reg = MXC_CCM_MCR,
+	.enable_shift = MXC_CCM_MCR_CLKO_EN_OFFSET,
+	.disable = _clk_disable,
+};
+
+#define _REGISTER_CLOCK(d, n, c) \
+	{ \
+		.dev_id = d, \
+		.con_id = n, \
+		.clk = &c, \
+	},
+
+static struct clk_lookup lookups[] = {
+	_REGISTER_CLOCK("mxc_nand.0", NULL, nfc_clk)
+	_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
+	_REGISTER_CLOCK(NULL, "ata", ata_clk[0])
+	_REGISTER_CLOCK("mxc-flexcan.0", NULL, can_clk[0])
+	_REGISTER_CLOCK("mxc-flexcan.1", NULL, can_clk[1])
+	_REGISTER_CLOCK(NULL, "csi", csi_clk[0])
+	_REGISTER_CLOCK(NULL, "cspi.0", cspi_clk[0])
+	_REGISTER_CLOCK(NULL, "cspi.1", cspi_clk[1])
+	_REGISTER_CLOCK(NULL, "cspi.2", cspi_clk[2])
+	_REGISTER_CLOCK(NULL, "dryice", dryice_clk)
+	_REGISTER_CLOCK(NULL, "ect", ect_clk)
+	_REGISTER_CLOCK(NULL, "epit1", epit1_clk[0])
+	_REGISTER_CLOCK(NULL, "epit2", epit2_clk[0])
+	_REGISTER_CLOCK(NULL, "esai", esai_clk[0])
+	_REGISTER_CLOCK("mxc-mmc.0", NULL, esdhc1_clk[0])
+	_REGISTER_CLOCK("mxc-mmc.1", NULL, esdhc2_clk[0])
+	_REGISTER_CLOCK("fec.0", NULL, fec_clk[0])
+	_REGISTER_CLOCK(NULL, "gpio0", gpio_clk[0])
+	_REGISTER_CLOCK(NULL, "gpio1", gpio_clk[1])
+	_REGISTER_CLOCK(NULL, "gpio2", gpio_clk[2])
+	_REGISTER_CLOCK(NULL, "gpt1", gpt1_clk[0])
+	_REGISTER_CLOCK(NULL, "gpt2", gpt2_clk[0])
+	_REGISTER_CLOCK(NULL, "gpt3", gpt3_clk[0])
+	_REGISTER_CLOCK(NULL, "gpt4", gpt4_clk[0])
+	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk[0])
+	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk[1])
+	_REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk[2])
+	_REGISTER_CLOCK(NULL, "iim", iim_clk)
+	_REGISTER_CLOCK(NULL, "iomuxc", iomuxc_clk)
+	_REGISTER_CLOCK(NULL, "kpp", kpp_clk)
+	_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk[0])
+	_REGISTER_CLOCK(NULL, "owire", owire_clk[0])
+	_REGISTER_CLOCK("mxc_pwm.0", NULL, pwm1_clk[0])
+	_REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk[0])
+	_REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk[0])
+	_REGISTER_CLOCK("mxc_pwm.3", NULL, pwm4_clk[0])
+	_REGISTER_CLOCK(NULL, "rngb", rngb_clk)
+	_REGISTER_CLOCK(NULL, "scc", scc_clk)
+	_REGISTER_CLOCK(NULL, "sdma", sdma_clk[0])
+	_REGISTER_CLOCK(NULL, "sim1", sim1_clk[0])
+	_REGISTER_CLOCK(NULL, "sim2", sim2_clk[0])
+	_REGISTER_CLOCK(NULL, "slcdc", slcdc_clk[0])
+	_REGISTER_CLOCK(NULL, "spba", spba_clk)
+	_REGISTER_CLOCK(NULL, "ssi1", ssi1_clk[0])
+	_REGISTER_CLOCK(NULL, "ssi2", ssi2_clk[0])
+	_REGISTER_CLOCK("mxc-tsadcc.0", NULL, tsc_clk)
+	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk[0])
+	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk[0])
+	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk[0])
+	_REGISTER_CLOCK("imx-uart.3", NULL, uart4_clk[0])
+	_REGISTER_CLOCK("imx-uart.4", NULL, uart5_clk[0])
+	_REGISTER_CLOCK("imx-wdt.0", NULL, wdog_clk)
+	_REGISTER_CLOCK(NULL, "usb", usb_clk)
+	_REGISTER_CLOCK(NULL, "clko", clko_clk)
+	_REGISTER_CLOCK(NULL, "brom", brom_clk)
+};
+
+int __init mx25_clocks_init(unsigned long fref)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(lookups); i++)
+		clkdev_add(&lookups[i]);
+
+	ckih_rate = fref;
+#ifndef CONFIG_DEBUG_LL
+	/* Turn off all possible clocks */
+	__raw_writel((1 << MXC_CCM_CGCR0_HCLK_EMI_OFFSET), MXC_CCM_CGCR0);
+
+	__raw_writel((1 << MXC_CCM_CGCR1_GPT1_OFFSET) |
+		     (1 << MXC_CCM_CGCR1_IIM_OFFSET), MXC_CCM_CGCR1);
+	__raw_writel(1 << MXC_CCM_CGCR2_SCC_OFFSET, MXC_CCM_CGCR2);
+#endif
+#if 1
+	/* Set all perclk sources to upll */
+	for (i = 0; i < ARRAY_SIZE(per_clk); i++) {
+		int ret;
+		unsigned long rate = per_clk[i].get_rate(&per_clk[i]);
+
+#ifdef CONFIG_DEBUG_LL
+		if (i == 15) {
+			printk(KERN_DEBUG "skipping per_clk[%d] rate=%lu\n", i, rate);
+			continue;
+		}
+#endif
+		{
+			unsigned long new_rate;
+
+			per_clk[i].set_parent(&per_clk[i], &upll_clk);
+			new_rate = per_clk[i].round_rate(&per_clk[i], rate);
+			if (rate == new_rate)
+				break;
+			if ((ret = per_clk[i].set_rate(&per_clk[i], new_rate)) < 0) {
+				printk(KERN_ERR "Error %d setting clk[%d] rate to %lu\n",
+				       ret, i, new_rate);
+			}
+		}
+	}
+
+	/* the NFC clock must be derived from AHB clock */
+	clk_set_parent(&per_clk[8], &ahb_clk);
+#endif
+	clk_set_rate(&per_clk[8], clk_get_rate(&ahb_clk) / 6);
+	clk_set_rate(&per_clk[7], clk_get_rate(per_clk[7].parent));
+
+	/* This will propagate to all children and init all the clock rates */
+#ifdef CONFIG_DEBUG_LL
+	clk_enable(&uart1_clk[0]);
+#endif
+	clk_enable(&emi_clk);
+	clk_enable(&iim_clk);
+
+	pr_info("Clock input source is %ld\n", clk_get_rate(&osc24m_clk));
+
+	pr_info("CPU: %lu.%03luMHz\n",
+		clk_get_rate(&cpu_clk) / 1000000, clk_get_rate(&cpu_clk) / 1000 % 1000);
+	pr_info("AHB: %lu.%03luMHz\n",
+		clk_get_rate(&ahb_clk) / 1000000, clk_get_rate(&ahb_clk) / 1000 % 1000);
+	pr_info("MPLL: %lu.%03luMHz\n",
+		clk_get_rate(&mpll_clk) / 1000000, clk_get_rate(&mpll_clk) / 1000 % 1000);
+	pr_info("UPLL: %lu.%03luMHz\n",
+		clk_get_rate(&upll_clk) / 1000000, clk_get_rate(&upll_clk) / 1000 % 1000);
+	clk_set_rate(&mpll_clk, clk_get_rate(&mpll_clk));
+	clk_set_rate(&upll_clk, clk_get_rate(&upll_clk));
+
+	mxc_timer_init(&gpt1_clk[1]);
+	return 0;
+}
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/clock_imx27.c linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/clock_imx27.c
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/clock_imx27.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/clock_imx27.c	2009-06-02 17:59:15.000000000 +0200
@@ -621,7 +621,7 @@ DEFINE_CLOCK1(csi_clk,     0, 0,      0,
 		.clk = &c, \
 	},
 
-static struct clk_lookup lookups[] __initdata = {
+static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
 	_REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
 	_REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/cpu_imx25.c linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/cpu_imx25.c
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/cpu_imx25.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/cpu_imx25.c	2009-06-02 17:59:17.000000000 +0200
@@ -0,0 +1,65 @@
+/*
+ * arch/arm/mach-mx2/cpu_mx25.c
+ *
+ * Copyright 2009 Lothar Wassmann <LW@KARO-electronics.de>
+ * derived from: cpu_mx27.c
+ *   Copyright 2007 Freescale Semiconductor, 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., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ */
+
+/*
+ * i.MX25 specific CPU detection code
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+
+#include <mach/hardware.h>
+
+static int cpu_silicon_rev = -1;
+static int cpu_partnumber;
+
+#define IIM_PREV_REG			IO_ADDRESS(IIM_BASE_ADDR + 0x20)
+#define IIM_SREV_REG			IO_ADDRESS(IIM_BASE_ADDR + 0x24)
+
+static void query_silicon_parameter(void)
+{
+	cpu_partnumber = __raw_readl(IIM_PREV_REG) >> 3;
+	cpu_silicon_rev = __raw_readl(IIM_SREV_REG);
+
+	printk(KERN_DEBUG "CPU rev: 0x%02x chip_rev: 0x%02x\n",
+	       cpu_partnumber, cpu_silicon_rev);
+	if (WARN_ON(cpu_partnumber != 0x1f)) {
+		printk(KERN_WARNING "Unsupported CPU rev: 0x%02x\n", cpu_partnumber);
+	}
+}
+
+/*
+ * Returns:
+ *	the silicon revision of the cpu
+ *	-EINVAL - not a mx25
+ */
+int mx25_revision(void)
+{
+	if (cpu_silicon_rev == -1)
+		query_silicon_parameter();
+
+	if (cpu_partnumber != 0x1f)
+		return -EINVAL;
+
+	return cpu_silicon_rev;
+}
+EXPORT_SYMBOL(mx25_revision);
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/crm_regs_mx25.h linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/crm_regs_mx25.h
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/crm_regs_mx25.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/crm_regs_mx25.h	2009-06-02 17:59:17.000000000 +0200
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __ARCH_ARM_MACH_MX25_CRM_REGS_H__
+#define __ARCH_ARM_MACH_MX25_CRM_REGS_H__
+
+#include <mach/hardware.h>
+
+/* Register offsets */
+#define MXC_CCM_MPCTL               (IO_ADDRESS(CCM_BASE_ADDR) + 0x00)
+#define MXC_CCM_UPCTL               (IO_ADDRESS(CCM_BASE_ADDR) + 0x04)
+#define MXC_CCM_CCTL                (IO_ADDRESS(CCM_BASE_ADDR) + 0x08)
+#define MXC_CCM_CGCR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x0C)
+#define MXC_CCM_CGCR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x10)
+#define MXC_CCM_CGCR2               (IO_ADDRESS(CCM_BASE_ADDR) + 0x14)
+#define MXC_CCM_PCDR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x18)
+#define MXC_CCM_PCDR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x1C)
+#define MXC_CCM_PCDR2               (IO_ADDRESS(CCM_BASE_ADDR) + 0x20)
+#define MXC_CCM_PCDR3               (IO_ADDRESS(CCM_BASE_ADDR) + 0x24)
+#define MXC_CCM_RCSR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x28)
+#define MXC_CCM_CRDR                (IO_ADDRESS(CCM_BASE_ADDR) + 0x2C)
+#define MXC_CCM_DCVR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x30)
+#define MXC_CCM_DCVR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x34)
+#define MXC_CCM_DCVR2               (IO_ADDRESS(CCM_BASE_ADDR) + 0x38)
+#define MXC_CCM_DCVR3               (IO_ADDRESS(CCM_BASE_ADDR) + 0x3C)
+#define MXC_CCM_LTR0                (IO_ADDRESS(CCM_BASE_ADDR) + 0x40)
+#define MXC_CCM_LTR1                (IO_ADDRESS(CCM_BASE_ADDR) + 0x44)
+#define MXC_CCM_LTR2                (IO_ADDRESS(CCM_BASE_ADDR) + 0x48)
+#define MXC_CCM_LTR3                (IO_ADDRESS(CCM_BASE_ADDR) + 0x4C)
+#define MXC_CCM_LTBR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x50)
+#define MXC_CCM_LTBR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x54)
+#define MXC_CCM_PMCR0               (IO_ADDRESS(CCM_BASE_ADDR) + 0x58)
+#define MXC_CCM_PMCR1               (IO_ADDRESS(CCM_BASE_ADDR) + 0x5C)
+#define MXC_CCM_PMCR2               (IO_ADDRESS(CCM_BASE_ADDR) + 0x60)
+#define MXC_CCM_MCR                 (IO_ADDRESS(CCM_BASE_ADDR) + 0x64)
+
+#define MXC_CCM_MPCTL_BRMO          (1 << 31)
+#define MXC_CCM_MPCTL_PD_OFFSET     26
+#define MXC_CCM_MPCTL_PD_MASK       (0xf << 26)
+#define MXC_CCM_MPCTL_MFD_OFFSET    16
+#define MXC_CCM_MPCTL_MFD_MASK      (0x3ff << 16)
+#define MXC_CCM_MPCTL_MFI_OFFSET    10
+#define MXC_CCM_MPCTL_MFI_MASK      (0xf << 10)
+#define MXC_CCM_MPCTL_MFN_OFFSET    0
+#define MXC_CCM_MPCTL_MFN_MASK      0x3ff
+#define MXC_CCM_MPCTL_LF            (1 << 15)
+
+#define MXC_CCM_UPCTL_BRMO          (1 << 31)
+#define MXC_CCM_UPCTL_PD_OFFSET     26
+#define MXC_CCM_UPCTL_PD_MASK       (0xf << 26)
+#define MXC_CCM_UPCTL_MFD_OFFSET    16
+#define MXC_CCM_UPCTL_MFD_MASK      (0x3ff << 16)
+#define MXC_CCM_UPCTL_MFI_OFFSET    10
+#define MXC_CCM_UPCTL_MFI_MASK      (0xf << 10)
+#define MXC_CCM_UPCTL_MFN_OFFSET    0
+#define MXC_CCM_UPCTL_MFN_MASK      0x3ff
+#define MXC_CCM_UPCTL_LF            (1 << 15)
+
+#define MXC_CCM_CCTL_ARM_OFFSET     30
+#define MXC_CCM_CCTL_ARM_MASK       (0x3 << 30)
+#define MXC_CCM_CCTL_AHB_OFFSET     28
+#define MXC_CCM_CCTL_AHB_MASK       (0x3 << 28)
+#define MXC_CCM_CCTL_MPLL_RST       (1 << 27)
+#define MXC_CCM_CCTL_UPLL_RST       (1 << 26)
+#define MXC_CCM_CCTL_LP_CTL_OFFSET  24
+#define MXC_CCM_CCTL_LP_CTL_MASK    (0x3 << 24)
+#define MXC_CCM_CCTL_LP_MODE_RUN    (0x0 << 24)
+#define MXC_CCM_CCTL_LP_MODE_WAIT   (0x1 << 24)
+#define MXC_CCM_CCTL_LP_MODE_DOZE   (0x2 << 24)
+#define MXC_CCM_CCTL_LP_MODE_STOP   (0x3 << 24)
+#define MXC_CCM_CCTL_UPLL_DISABLE   (1 << 23)
+#define MXC_CCM_CCTL_MPLL_BYPASS    (1 << 22)
+#define MXC_CCM_CCTL_USB_DIV_OFFSET 16
+#define MXC_CCM_CCTL_USB_DIV_MASK   (0x3 << 16)
+#define MXC_CCM_CCTL_CG_CTRL        (1 << 15)
+#define MXC_CCM_CCTL_ARM_SRC        (1 << 14)
+
+#define MXC_CCM_CGCR0_HCLK_ATA_OFFSET    16
+#define MXC_CCM_CGCR0_HCLK_BROM_OFFSET   17
+#define MXC_CCM_CGCR0_HCLK_CSI_OFFSET    18
+#define MXC_CCM_CGCR0_HCLK_EMI_OFFSET    19
+#define MXC_CCM_CGCR0_HCLK_ESAI_OFFSET   20
+#define MXC_CCM_CGCR0_HCLK_ESDHC1_OFFSET 21
+#define MXC_CCM_CGCR0_HCLK_ESDHC2_OFFSET 22
+#define MXC_CCM_CGCR0_HCLK_FEC_OFFSET    23
+#define MXC_CCM_CGCR0_HCLK_LCDC_OFFSET   24
+#define MXC_CCM_CGCR0_HCLK_RTIC_OFFSET   25
+#define MXC_CCM_CGCR0_HCLK_SDMA_OFFSET   26
+#define MXC_CCM_CGCR0_HCLK_SLCDC_OFFSET  27
+#define MXC_CCM_CGCR0_HCLK_USBOTG_OFFSET 28
+
+#define MXC_CCM_CGCR0_PER_CSI_OFFSET     0
+#define MXC_CCM_CGCR0_PER_EPIT_OFFSET    1
+#define MXC_CCM_CGCR0_PER_ESAI_OFFSET    2
+#define MXC_CCM_CGCR0_PER_ESDHC1_OFFSET  3
+#define MXC_CCM_CGCR0_PER_ESDHC2_OFFSET  4
+#define MXC_CCM_CGCR0_PER_GPT_OFFSET     5
+#define MXC_CCM_CGCR0_PER_I2C_OFFSET     6
+#define MXC_CCM_CGCR0_PER_LCDC_OFFSET    7
+#define MXC_CCM_CGCR0_PER_NFC_OFFSET     8
+#define MXC_CCM_CGCR0_PER_OWIRE_OFFSET   9
+#define MXC_CCM_CGCR0_PER_PWM_OFFSET     10
+#define MXC_CCM_CGCR0_PER_SIM1_OFFSET    11
+#define MXC_CCM_CGCR0_PER_SIM2_OFFSET    12
+#define MXC_CCM_CGCR0_PER_SSI1_OFFSET    13
+#define MXC_CCM_CGCR0_PER_SSI2_OFFSET    14
+#define MXC_CCM_CGCR0_PER_UART_OFFSET    15
+
+#define MXC_CCM_CGCR1_AUDMUX_OFFSET      0
+#define MXC_CCM_CGCR1_ATA_OFFSET         1
+#define MXC_CCM_CGCR1_CAN1_OFFSET        2
+#define MXC_CCM_CGCR1_CAN2_OFFSET        3
+#define MXC_CCM_CGCR1_CSI_OFFSET         4
+#define MXC_CCM_CGCR1_CSPI1_OFFSET       5
+#define MXC_CCM_CGCR1_CSPI2_OFFSET       6
+#define MXC_CCM_CGCR1_CSPI3_OFFSET       7
+#define MXC_CCM_CGCR1_DRYICE_OFFSET      8
+#define MXC_CCM_CGCR1_ECT_OFFSET         9
+#define MXC_CCM_CGCR1_EPIT1_OFFSET       10
+#define MXC_CCM_CGCR1_EPIT2_OFFSET       11
+#define MXC_CCM_CGCR1_ESAI_OFFSET        12
+#define MXC_CCM_CGCR1_ESDHC1_OFFSET      13
+#define MXC_CCM_CGCR1_ESDHC2_OFFSET      14
+#define MXC_CCM_CGCR1_FEC_OFFSET         15
+#define MXC_CCM_CGCR1_GPIO1_OFFSET       16
+#define MXC_CCM_CGCR1_GPIO2_OFFSET       17
+#define MXC_CCM_CGCR1_GPIO3_OFFSET       18
+#define MXC_CCM_CGCR1_GPT1_OFFSET        19
+#define MXC_CCM_CGCR1_GPT2_OFFSET        20
+#define MXC_CCM_CGCR1_GPT3_OFFSET        21
+#define MXC_CCM_CGCR1_GPT4_OFFSET        22
+#define MXC_CCM_CGCR1_I2C1_OFFSET        23
+#define MXC_CCM_CGCR1_I2C2_OFFSET        24
+#define MXC_CCM_CGCR1_I2C3_OFFSET        25
+#define MXC_CCM_CGCR1_IIM_OFFSET         26
+#define MXC_CCM_CGCR1_IOMUXC_OFFSET      27
+#define MXC_CCM_CGCR1_KPP_OFFSET         28
+#define MXC_CCM_CGCR1_LCDC_OFFSET        29
+#define MXC_CCM_CGCR1_OWIRE_OFFSET       30
+#define MXC_CCM_CGCR1_PWM1_OFFSET        31
+
+#define MXC_CCM_CGCR2_PWM2_OFFSET        (32-32)
+#define MXC_CCM_CGCR2_PWM3_OFFSET        (33-32)
+#define MXC_CCM_CGCR2_PWM4_OFFSET        (34-32)
+#define MXC_CCM_CGCR2_RNGB_OFFSET        (35-32)
+#define MXC_CCM_CGCR2_RTIC_OFFSET        (36-32)
+#define MXC_CCM_CGCR2_SCC_OFFSET         (37-32)
+#define MXC_CCM_CGCR2_SDMA_OFFSET        (38-32)
+#define MXC_CCM_CGCR2_SIM1_OFFSET        (39-32)
+#define MXC_CCM_CGCR2_SIM2_OFFSET        (40-32)
+#define MXC_CCM_CGCR2_SLCDC_OFFSET       (41-32)
+#define MXC_CCM_CGCR2_SPBA_OFFSET        (42-32)
+#define MXC_CCM_CGCR2_SSI1_OFFSET        (43-32)
+#define MXC_CCM_CGCR2_SSI2_OFFSET        (44-32)
+#define MXC_CCM_CGCR2_TCHSCRN_OFFSET     (45-32)
+#define MXC_CCM_CGCR2_UART1_OFFSET       (46-32)
+#define MXC_CCM_CGCR2_UART2_OFFSET       (47-32)
+#define MXC_CCM_CGCR2_UART3_OFFSET       (48-32)
+#define MXC_CCM_CGCR2_UART4_OFFSET       (49-32)
+#define MXC_CCM_CGCR2_UART5_OFFSET       (50-32)
+#define MXC_CCM_CGCR2_WDOG_OFFSET        (51-32)
+
+#define MXC_CCM_PCDR1_PERDIV1_MASK       0x3f
+
+#define MXC_CCM_RCSR_NF16B               (1 << 14)
+
+#define MXC_CCM_MCR_USB_XTAL_MUX_OFFSET  31
+#define MXC_CCM_MCR_CLKO_EN_OFFSET       30
+#define MXC_CCM_MCR_CLKO_DIV_OFFSET      24
+#define MXC_CCM_MCR_CLKO_DIV_MASK        (0x3F << 24)
+#define MXC_CCM_MCR_CLKO_SEL_OFFSET      20
+#define MXC_CCM_MCR_CLKO_SEL_MASK        (0xF << 20)
+#define MXC_CCM_MCR_ESAI_CLK_MUX_OFFSET  19
+#define MXC_CCM_MCR_SSI2_CLK_MUX_OFFSET  18
+#define MXC_CCM_MCR_SSI1_CLK_MUX_OFFSET  17
+#define MXC_CCM_MCR_USB_CLK_MUX_OFFSET   16
+
+#define MXC_CCM_MCR_PER_CLK_MUX_MASK     (0xFFFF << 0)
+
+#endif				/* __ARCH_ARM_MACH_MX25_CRM_REGS_H__ */
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/devices.h linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/devices.h
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/devices.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/devices.h	2009-07-01 11:10:15.000000000 +0200
@@ -20,3 +20,12 @@ extern struct platform_device mxc_i2c_de
 extern struct platform_device mxc_i2c_device1;
 extern struct platform_device mxc_sdhc_device0;
 extern struct platform_device mxc_sdhc_device1;
+extern struct platform_device mxc_usbh1_device;
+extern struct platform_device mxc_usbh2_device;
+extern struct platform_device mxc_usbotg_device;
+#ifdef CONFIG_MACH_MX25
+extern struct platform_device mx25_i2c_device0;
+extern struct platform_device mx25_i2c_device1;
+extern struct platform_device mx25_i2c_device2;
+extern struct platform_device mxc_sdhc_device2;
+#endif
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/devices_mx25.c linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/devices_mx25.c
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/devices_mx25.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/devices_mx25.c	2009-06-29 10:48:40.000000000 +0200
@@ -0,0 +1,452 @@
+/*
+ * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/spi/spi.h>
+
+#include <mach/hardware.h>
+#include <mach/mmc.h>
+#include <mach/spba.h>
+#include <mach/sdma.h>
+#include <mach/iomux.h>
+
+#include "sdma_script_code.h"
+
+#include "karo.h"
+
+void mx25_sdma_get_script_info(sdma_script_start_addrs * sdma_script_addr)
+{
+	sdma_script_addr->mxc_sdma_ap_2_ap_addr = ap_2_ap_ADDR;
+	sdma_script_addr->mxc_sdma_ap_2_bp_addr = -1;
+	sdma_script_addr->mxc_sdma_bp_2_ap_addr = -1;
+	sdma_script_addr->mxc_sdma_loopback_on_dsp_side_addr = -1;
+	sdma_script_addr->mxc_sdma_mcu_interrupt_only_addr = -1;
+
+	sdma_script_addr->mxc_sdma_firi_2_per_addr = -1;
+	sdma_script_addr->mxc_sdma_firi_2_mcu_addr = -1;
+	sdma_script_addr->mxc_sdma_per_2_firi_addr = -1;
+	sdma_script_addr->mxc_sdma_mcu_2_firi_addr = -1;
+
+	sdma_script_addr->mxc_sdma_uart_2_per_addr = uart_2_per_ADDR;
+	sdma_script_addr->mxc_sdma_uart_2_mcu_addr = uart_2_mcu_ADDR;
+	sdma_script_addr->mxc_sdma_per_2_app_addr = per_2_app_ADDR;
+	sdma_script_addr->mxc_sdma_mcu_2_app_addr = mcu_2_app_ADDR;
+
+	sdma_script_addr->mxc_sdma_per_2_per_addr = -1;
+
+	sdma_script_addr->mxc_sdma_uartsh_2_per_addr = uartsh_2_per_ADDR;
+	sdma_script_addr->mxc_sdma_uartsh_2_mcu_addr = uartsh_2_mcu_ADDR;
+	sdma_script_addr->mxc_sdma_per_2_shp_addr = per_2_shp_ADDR;
+	sdma_script_addr->mxc_sdma_mcu_2_shp_addr = mcu_2_shp_ADDR;
+
+	sdma_script_addr->mxc_sdma_ata_2_mcu_addr = ata_2_mcu_ADDR;
+	sdma_script_addr->mxc_sdma_mcu_2_ata_addr = mcu_2_ata_ADDR;
+
+	sdma_script_addr->mxc_sdma_app_2_per_addr = app_2_per_ADDR;
+	sdma_script_addr->mxc_sdma_app_2_mcu_addr = app_2_mcu_ADDR;
+	sdma_script_addr->mxc_sdma_shp_2_per_addr = shp_2_per_ADDR;
+	sdma_script_addr->mxc_sdma_shp_2_mcu_addr = shp_2_mcu_ADDR;
+
+	sdma_script_addr->mxc_sdma_mshc_2_mcu_addr = -1;
+	sdma_script_addr->mxc_sdma_mcu_2_mshc_addr = -1;
+
+	sdma_script_addr->mxc_sdma_spdif_2_mcu_addr = -1;
+	sdma_script_addr->mxc_sdma_mcu_2_spdif_addr = -1;
+
+	sdma_script_addr->mxc_sdma_asrc_2_mcu_addr = -1;
+
+	sdma_script_addr->mxc_sdma_dptc_dvfs_addr = -1;
+	sdma_script_addr->mxc_sdma_ext_mem_2_ipu_addr = ext_mem__ipu_ram_ADDR;
+	sdma_script_addr->mxc_sdma_descrambler_addr = -1;
+
+	sdma_script_addr->mxc_sdma_start_addr = (unsigned short *)sdma_code;
+	sdma_script_addr->mxc_sdma_ram_code_size = RAM_CODE_SIZE;
+	sdma_script_addr->mxc_sdma_ram_code_start_addr = RAM_CODE_START_ADDR;
+}
+
+#if defined(CONFIG_MXC_WATCHDOG) || defined(CONFIG_MXC_WATCHDOG_MODULE)
+static struct resource wdt_resources[] = {
+	{
+		.start = WDOG_BASE_ADDR,
+		.end = WDOG_BASE_ADDR + 0x2f,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device mx25_wdt_device = {
+	.name = "mxc_wdt",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(wdt_resources),
+	.resource = wdt_resources,
+};
+
+static void mx25_init_wdt(void)
+{
+	(void)platform_device_register(&mx25_wdt_device);
+}
+#else
+static inline void mx25_init_wdt(void)
+{
+}
+#endif
+
+/*
+ * lcdc:
+ * - i.MX1: the basic controller
+ * - i.MX21: to be checked
+ * - i.MX27: like i.MX1, with slightly variations
+ */
+static struct resource mxc_fb[] = {
+	{
+		.start = LCDC_BASE_ADDR,
+		.end   = LCDC_BASE_ADDR + 0xFFF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MXC_INT_LCDC,
+		.end   = MXC_INT_LCDC,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+/* mxc lcd driver */
+struct platform_device mxc_fb_device = {
+	.name = "imx-fb",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mxc_fb),
+	.resource = mxc_fb,
+	.dev = {
+		.coherent_dma_mask = 0xFFFFFFFF,
+	},
+};
+
+/* SPI controller and device data */
+#if defined(CONFIG_SPI_MXC) || defined(CONFIG_SPI_MXC_MODULE)
+
+#ifdef CONFIG_SPI_MXC_SELECT1
+/*!
+ * Resource definition for the CSPI1
+ */
+static struct resource mx25_spi1_resources[] = {
+	{
+	       .start = CSPI1_BASE_ADDR,
+	       .end = CSPI1_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	},
+	{
+	       .start = MXC_INT_CSPI1,
+	       .end = MXC_INT_CSPI1,
+	       .flags = IORESOURCE_IRQ,
+	},
+};
+
+/*! Platform Data for MXC CSPI1 */
+static struct mxc_spi_master mx25_spi1_data = {
+	.maxchipselect = 4,
+	.spi_version = 7,
+};
+
+/*! Device Definition for MXC CSPI1 */
+static struct platform_device mx25_spi1_device = {
+	.name = "mxc_spi",
+	.id = 0,
+	.dev = {
+		.platform_data = &mx25_spi1_data,
+	},
+	.num_resources = ARRAY_SIZE(mx25_spi1_resources),
+	.resource = mx25_spi1_resources,
+};
+
+#endif /* CONFIG_SPI_MXC_SELECT1 */
+
+#ifdef CONFIG_SPI_MXC_SELECT2
+/*!
+ * Resource definition for the CSPI2
+ */
+static struct resource mx25_spi2_resources[] = {
+	{
+	       .start = CSPI2_BASE_ADDR,
+	       .end = CSPI2_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	},
+	{
+	       .start = MXC_INT_CSPI2,
+	       .end = MXC_INT_CSPI2,
+	       .flags = IORESOURCE_IRQ,
+	},
+};
+
+/*! Platform Data for MXC CSPI2 */
+static struct mxc_spi_master mx25_spi2_data = {
+	.maxchipselect = 4,
+	.spi_version = 7,
+};
+
+/*! Device Definition for MXC CSPI2 */
+static struct platform_device mx25_spi2_device = {
+	.name = "mxc_spi",
+	.id = 1,
+	.dev = {
+		.platform_data = &mx25_spi2_data,
+	},
+	.num_resources = ARRAY_SIZE(mx25_spi2_resources),
+	.resource = mx25_spi2_resources,
+};
+#endif /* CONFIG_SPI_MXC_SELECT2 */
+
+#ifdef CONFIG_SPI_MXC_SELECT3
+/*!
+ * Resource definition for the CSPI3
+ */
+static struct resource mx25_spi3_resources[] = {
+	{
+	       .start = CSPI3_BASE_ADDR,
+	       .end = CSPI3_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	},
+	{
+	       .start = MXC_INT_CSPI3,
+	       .end = MXC_INT_CSPI3,
+	       .flags = IORESOURCE_IRQ,
+	},
+};
+
+/*! Platform Data for MXC CSPI3 */
+static struct mxc_spi_master mx25_spi3_data = {
+	.maxchipselect = 4,
+	.spi_version = 7,
+};
+
+/*! Device Definition for MXC CSPI3 */
+static struct platform_device mx25_spi3_device = {
+	.name = "mxc_spi",
+	.id = 2,
+	.dev = {
+		.platform_data = &mx25_spi3_data,
+	},
+	.num_resources = ARRAY_SIZE(mx25_spi3_resources),
+	.resource = mx25_spi3_resources,
+};
+#endif /* CONFIG_SPI_MXC_SELECT3 */
+
+static inline void mx25_init_spi(void)
+{
+	spba_take_ownership(SPBA_CSPI2, SPBA_MASTER_A);
+	spba_take_ownership(SPBA_CSPI3, SPBA_MASTER_A);
+
+#ifdef CONFIG_SPI_MXC_SELECT1
+	if (platform_device_register(&mx25_spi1_device) < 0)
+		printk(KERN_ERR "Error: Registering the SPI Controller_1\n");
+#endif				/* CONFIG_SPI_MXC_SELECT1 */
+#ifdef CONFIG_SPI_MXC_SELECT2
+	if (platform_device_register(&mx25_spi2_device) < 0)
+		printk(KERN_ERR "Error: Registering the SPI Controller_2\n");
+#endif				/* CONFIG_SPI_MXC_SELECT2 */
+#ifdef CONFIG_SPI_MXC_SELECT3
+	if (platform_device_register(&mx25_spi3_device) < 0)
+		printk(KERN_ERR "Error: Registering the SPI Controller_3\n");
+#endif				/* CONFIG_SPI_MXC_SELECT3 */
+}
+#else
+static inline void mx25_init_spi(void)
+{
+}
+#endif
+
+#if defined(CONFIG_USB_EHCI_MXC) || defined(CONFIG_USB_EHCI_MXC_MODULE)
+static struct resource mxc_usbotg_resources[] = {
+	{
+		.start = OTG_BASE_ADDR,
+		.end   = OTG_BASE_ADDR + 0x1ff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = MXC_INT_USB_OTG,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static u64 usbotg_dmamask = (u32)~0;
+
+struct platform_device mxc_usbotg_device = {
+	.name = "mxc-ehci",
+	.id = 0,
+	.dev = {
+		.coherent_dma_mask = 0xffffffff,
+		.dma_mask = &usbotg_dmamask,
+	},
+	.num_resources = ARRAY_SIZE(mxc_usbotg_resources),
+	.resource = mxc_usbotg_resources,
+};
+
+static struct resource mxc_usbh2_resources[] = {
+	{
+		.start = USBH2_BASE_ADDR,
+		.end   = USBH2_BASE_ADDR + 0x1ff,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = MXC_INT_USB_H2,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static u64 usbh2_dmamask = (u32)~0;
+
+struct platform_device mxc_usbh2_device = {
+	.name = "mxc-ehci",
+	.id = 1,
+	.dev = {
+		.coherent_dma_mask = 0xffffffff,
+		.dma_mask = &usbh2_dmamask,
+	},
+	.num_resources = ARRAY_SIZE(mxc_usbh2_resources),
+	.resource = mxc_usbh2_resources,
+};
+#endif
+
+/* I2C controller and device data */
+#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
+
+/*!
+ * Resource definition for the I2C1
+ */
+static struct resource mx25_i2c1_resources[] = {
+	{
+		.start = I2C_BASE_ADDR,
+		.end = I2C_BASE_ADDR + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MXC_INT_I2C,
+		.end = MXC_INT_I2C,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+/*!
+ * Resource definition for the I2C2
+ */
+static struct resource mx25_i2c2_resources[] = {
+	{
+		.start = I2C2_BASE_ADDR,
+		.end = I2C2_BASE_ADDR + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MXC_INT_I2C2,
+		.end = MXC_INT_I2C2,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+/*!
+ * Resource definition for the I2C3
+ */
+static struct resource mx25_i2c3_resources[] = {
+	{
+		.start = I2C3_BASE_ADDR,
+		.end = I2C3_BASE_ADDR + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MXC_INT_I2C3,
+		.end = MXC_INT_I2C3,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+/*! Device Definition for MXC I2C1 */
+struct platform_device mx25_i2c_device0 = {
+	.name = "imx-i2c",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(mx25_i2c1_resources),
+	.resource = mx25_i2c1_resources,
+};
+
+struct platform_device mx25_i2c_device1 = {
+	.name = "imx-i2c",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(mx25_i2c2_resources),
+	.resource = mx25_i2c2_resources,
+};
+
+struct platform_device mx25_i2c_device2 = {
+	.name = "imx-i2c",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(mx25_i2c3_resources),
+	.resource = mx25_i2c3_resources,
+};
+#endif
+
+static struct mxc_gpio_port mx25_gpio_ports[] = {
+	{
+		.chip.label = "gpio-1",
+		.base = IO_ADDRESS(GPIO1_BASE_ADDR),
+		.irq = MXC_INT_GPIO1,
+		.virtual_irq_start = MXC_GPIO_IRQ_START,
+	},
+	{
+		.chip.label = "gpio-2",
+		.base = IO_ADDRESS(GPIO2_BASE_ADDR),
+		.irq = MXC_INT_GPIO2,
+		.virtual_irq_start = MXC_GPIO_IRQ_START + 1 * 32,
+	},
+	{
+		.chip.label = "gpio-3",
+		.base = IO_ADDRESS(GPIO3_BASE_ADDR),
+		.irq = MXC_INT_GPIO3,
+		.virtual_irq_start = MXC_GPIO_IRQ_START + 2 * 32,
+	},
+	{
+		.chip.label = "gpio-4",
+		.base = IO_ADDRESS(GPIO4_BASE_ADDR),
+		.irq = MXC_INT_GPIO4,
+		.virtual_irq_start = MXC_GPIO_IRQ_START + 3 * 32,
+	},
+};
+
+static inline void mx25_init_ssi(void)
+{
+	/* SPBA configuration for SSI - SDMA and MCU are set */
+	spba_take_ownership(SPBA_SSI1, SPBA_MASTER_A | SPBA_MASTER_C);
+	spba_take_ownership(SPBA_SSI2, SPBA_MASTER_A | SPBA_MASTER_C);
+}
+
+static struct platform_device mx25_dma_device = {
+	.name = "mxc_dma",
+	.id = 0,
+};
+
+static inline void mx25_init_dma(void)
+{
+	(void)platform_device_register(&mx25_dma_device);
+}
+
+static int __init mx25_init_devices(void)
+{
+	mx25_init_wdt();
+	mx25_init_spi();
+	mx25_init_dma();
+	mx25_init_ssi();
+
+	return 0;
+}
+arch_initcall(mx25_init_devices);
+
+int __init mxc_register_gpios(void)
+{
+	return mxc_gpio_init(mx25_gpio_ports, ARRAY_SIZE(mx25_gpio_ports));
+}
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/generic.c linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/generic.c
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/generic.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/generic.c	2009-06-02 17:59:16.000000000 +0200
@@ -26,6 +26,7 @@
 #include <asm/mach/map.h>
 
 /* MX27 memory map definition */
+#if defined(CONFIG_MACH_MX27) || defined(CONFIG_MACH_MX21)
 static struct map_desc mxc_io_desc[] __initdata = {
 	/*
 	 * this fixed mapping covers:
@@ -61,7 +62,7 @@ static struct map_desc mxc_io_desc[] __i
 		.pfn = __phys_to_pfn(X_MEMC_BASE_ADDR),
 		.length = X_MEMC_SIZE,
 		.type = MT_DEVICE
-	}
+	},
 };
 
 /*
@@ -82,4 +83,46 @@ void __init mx27_map_io(void)
 
 	iotable_init(mxc_io_desc, ARRAY_SIZE(mxc_io_desc));
 }
+#endif
+
+#ifdef CONFIG_MACH_MX25
+static struct map_desc mx25_io_desc[] __initdata = {
+	{
+		.virtual	= (unsigned long)X_MEMC_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(X_MEMC_BASE_ADDR),
+		.length		= X_MEMC_SIZE,
+		.type		= MT_DEVICE
+	},
+	{
+		.virtual	= (unsigned long)ASIC_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(ASIC_BASE_ADDR),
+		.length		= ASIC_SIZE,
+		.type		= MT_DEVICE_NONSHARED
+	},
+	{
+		.virtual	= (unsigned long)AIPS1_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(AIPS1_BASE_ADDR),
+		.length		= AIPS1_SIZE,
+		.type		= MT_DEVICE_NONSHARED
+	},
+	{
+		.virtual	= (unsigned long)AIPS2_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(AIPS2_BASE_ADDR),
+		.length		= AIPS2_SIZE,
+		.type		= MT_DEVICE_NONSHARED
+	},
+	{
+		.virtual	= (unsigned long)SPBA0_BASE_ADDR_VIRT,
+		.pfn		= __phys_to_pfn(SPBA0_BASE_ADDR),
+		.length		= SPBA0_SIZE,
+		.type		= MT_DEVICE_NONSHARED
+	},
+};
+
+void __init mx25_map_io(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MX25);
 
+	iotable_init(mx25_io_desc, ARRAY_SIZE(mx25_io_desc));
+}
+#endif
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/karo-tx25.c linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/karo-tx25.c
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/karo-tx25.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/karo-tx25.c	2009-07-14 13:50:45.000000000 +0200
@@ -0,0 +1,981 @@
+/*
+ * arch/arm/mach-mx2/karo-tx25.c
+ *
+ * Copyright (C) 2008  Lothar Wassmann <LW@KARO-electronics.de>
+ *
+ * based on: arch/arm/mach-mx27ads.c (C) Freescale Semiconductor, 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
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ *
+ * This file adds support for the Ka-Ro electronics TX25 processor modules
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/spi/spi.h>
+#include <linux/serial_8250.h>
+#include <linux/fec_enet.h>
+#if defined(CONFIG_MTD) || defined(CONFIG_MTD_MODULE)
+#include <mtd/mtd-abi.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <asm/mach/flash.h>
+#endif
+
+#include <linux/serial.h>
+#include <linux/fsl_devices.h>
+#include <linux/irq.h>
+#include <linux/mmc/host.h>
+#include <linux/leds.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/iomux.h>
+#include <mach/irqs.h>
+#include <mach/clock.h>
+#include <mach/imxfb.h>
+#include <mach/mmc.h>
+#include <mach/imx-uart.h>
+#include <mach/mxc_nand.h>
+#include <mach/mxc_ehci.h>
+#include <mach/mxc_tsadcc.h>
+#include <mach/mxc_can.h>
+
+#include "crm_regs.h"
+#include "devices.h"
+#include "karo.h"
+
+#ifdef DEBUG
+int tx25_debug = 1;
+module_param(tx25_debug, int, S_IRUGO | S_IWUSR);
+#else
+static int tx25_debug;
+module_param(tx25_debug, int, 0);
+#endif
+
+int karo_board_type = 0;
+int karo_mod_type = -1;
+
+
+static int karo_tx25_gpio_config(struct pad_desc *pd, int num)
+{
+	int ret;
+	int i;
+	int count = 0;
+
+	for (i = 0; i < num; i++) {
+		ret = mxc_iomux_v3_setup_pad(&pd[i]);
+		if (ret == 0) {
+			DBG(0, "%s: PAD[%d] %s set up as GPIO\n", __FUNCTION__, i,
+			    MXC_PAD_NAME(&pd[i]));
+			count++;
+			mxc_iomux_v3_release_pad(&pd[i]);
+		} else {
+			DBG(0, "%s: PAD[%d] %s skipped\n", __FUNCTION__, i,
+			    MXC_PAD_NAME(&pd[i]));
+		}
+	}
+	return count;
+}
+
+//#define FEC_MII_IRQ		IRQ_GPIOD(8)
+
+#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE)
+static struct resource fec_resources[] = {
+	{
+		.start	= FEC_BASE_ADDR,
+		.end	= FEC_BASE_ADDR + 0x18f,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= FEC_BASE_ADDR + 0x200,
+		.end	= FEC_BASE_ADDR + 0x30b,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= MXC_INT_FEC,
+		.end	= MXC_INT_FEC,
+		.flags	= IORESOURCE_IRQ,
+#ifdef FEC_MII_IRQ
+	}, {
+		.start	= FEC_MII_IRQ,
+		.end	= FEC_MII_IRQ,
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+#endif
+	},
+};
+
+/*
+ * Setup GPIO for FEC device to be active
+ *
+ */
+static struct pad_desc karo_tx25_fec_gpios_off[] = {
+	MX25_PAD_FEC_MDC__GPIO_3_5,
+	MX25_PAD_FEC_MDIO__GPIO_3_6,
+	MX25_PAD_FEC_TDATA0__GPIO_3_7,
+	MX25_PAD_FEC_TDATA1__GPIO_3_8,
+	MX25_PAD_FEC_TX_EN__GPIO_3_9,
+	MX25_PAD_FEC_RDATA0__GPIO_3_10,
+	MX25_PAD_FEC_RDATA1__GPIO_3_11,
+	MX25_PAD_FEC_RX_DV__GPIO_3_12,
+	MX25_PAD_FEC_TX_CLK__GPIO_3_13,
+	MX25_PAD_D12__GPIO_4_8,
+	MX25_PAD_D10__GPIO_4_10,
+};
+
+static struct pad_desc karo_tx25_fec_pwr_gpios[] = {
+	MX25_PAD_D11__GPIO_4_9,		/* FEC PHY power on pin */
+	MX25_PAD_D13__GPIO_4_7,		/* FEC reset */
+};
+
+static struct pad_desc karo_tx25_fec_gpios_on[] = {
+	MX25_PAD_FEC_MDC__FEC_MDC,
+	MX25_PAD_FEC_MDIO__FEC_MDIO,
+	MX25_PAD_FEC_TDATA0__FEC_TDATA0,
+	MX25_PAD_FEC_TDATA1__FEC_TDATA1,
+	MX25_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX25_PAD_FEC_RDATA0__FEC_RDATA0,
+	MX25_PAD_FEC_RDATA1__FEC_RDATA1,
+	MX25_PAD_FEC_RX_DV__FEC_RX_DV,
+	MX25_PAD_FEC_TX_CLK__FEC_TX_CLK,
+	MX25_PAD_D12__GPIO_4_8,
+	MX25_PAD_D10__GPIO_4_10,
+};
+
+static struct gpio_desc {
+	unsigned int gpio:7;
+	unsigned int dir:1;
+	unsigned int level:1;
+} karo_tx25_fec_strap_gpios[] = {
+	/* configure the PHY strap pins to the correct values */
+	{ GPIO_PORTC |  5, 1, 0, },
+	{ GPIO_PORTC |  6, 1, 0, },
+	{ GPIO_PORTC |  7, 1, 0, },
+	{ GPIO_PORTC |  8, 1, 0, },
+	{ GPIO_PORTC |  9, 1, 0, },
+	{ GPIO_PORTC | 10, 1, 1, },
+	{ GPIO_PORTC | 11, 1, 1, },
+	{ GPIO_PORTC | 12, 0, 1, },
+	{ GPIO_PORTC | 13, 1, 0, },
+
+	{ GPIO_PORTD |  8, 0, 0, },
+	{ GPIO_PORTD | 10, 0, 0, },
+	{ GPIO_PORTD |  9, 1, 1, },
+	{ GPIO_PORTD |  7, 1, 0, },
+};
+
+#define TX25_FEC_PWR_GPIO	(GPIO_PORTD | 9)
+#define TX25_FEC_RST_GPIO	(GPIO_PORTD | 7)
+
+static int gpio_fec_active(void)
+{
+	int ret;
+	int i;
+
+#ifdef FEC_MII_IRQ
+	DBG(0, "%s: Using IRQ %d (GPIO %d) for MII\n", __FUNCTION__,
+	    FEC_MII_IRQ, irq_to_gpio(FEC_MII_IRQ));
+
+	set_irq_type(FEC_MII_IRQ, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING);
+#endif
+	ret = mxc_iomux_v3_setup_multiple_pads(karo_tx25_fec_pwr_gpios,
+					       ARRAY_SIZE(karo_tx25_fec_pwr_gpios));
+	if (ret) {
+		return ret;
+	}
+	/*
+	 * If the PHY is already powered on, assume it has been
+	 * correctly configured (by the boot loader)
+	*/
+	if (0 && gpio_get_value(TX25_FEC_PWR_GPIO) &&
+	    gpio_get_value(TX25_FEC_RST_GPIO)) {
+		ret = mxc_iomux_v3_setup_multiple_pads(karo_tx25_fec_gpios_on,
+						       ARRAY_SIZE(karo_tx25_fec_gpios_on));
+		if (ret) {
+			mxc_iomux_v3_release_multiple_pads(karo_tx25_fec_pwr_gpios,
+							   ARRAY_SIZE(karo_tx25_fec_pwr_gpios));
+			return ret;
+		}
+	} else {
+		/* switch PHY strap pins into required state */
+		ret = mxc_iomux_v3_setup_multiple_pads(karo_tx25_fec_gpios_off,
+						       ARRAY_SIZE(karo_tx25_fec_gpios_off));
+		if (ret) {
+			mxc_iomux_v3_release_multiple_pads(karo_tx25_fec_pwr_gpios,
+							   ARRAY_SIZE(karo_tx25_fec_pwr_gpios));
+			return ret;
+		}
+		DBG(0, "%s: Switching FEC PHY power on\n", __FUNCTION__);
+		DBG(0, "%s: Asserting FEC PHY reset\n", __FUNCTION__);
+		for (i = 0; i < ARRAY_SIZE(karo_tx25_fec_strap_gpios); i++) {
+			struct gpio_desc *pd = &karo_tx25_fec_strap_gpios[i];
+
+			ret = gpio_request(pd->gpio, "FEC");
+			if (ret < 0) {
+				DBG(0, "%s: Failed to request GPIO%d_%d: %d\n",
+				    __FUNCTION__, pd->gpio / 32 + 1, pd->gpio % 32, ret);
+				goto rel_mux;
+			}
+			if (pd->dir) {
+				gpio_direction_output(pd->gpio,
+						      pd->level);
+			} else {
+				gpio_direction_input(pd->gpio);
+			}
+		}
+#ifdef DEBUG
+		for (i = 0; i < ARRAY_SIZE(karo_tx25_fec_strap_gpios); i++) {
+			struct gpio_desc *pd = &karo_tx25_fec_strap_gpios[i];
+			int grp = pd->gpio / 32 + 1;
+			int ofs = pd->gpio % 32;
+
+			if (pd->dir && pd->level != gpio_get_value(pd->gpio)) {
+				DBG(0, "%s: GPIO%d_%d is %d instead of %d\n", __FUNCTION__,
+				    grp, ofs, gpio_get_value(pd->gpio),
+				    pd->level);
+			}
+		}
+#endif
+		DBG(0, "%s: Delaying for 22ms\n", __FUNCTION__);
+		mdelay(22);
+		DBG(0, "%s: Deasserting FEC PHY reset\n", __FUNCTION__);
+		gpio_set_value(TX25_FEC_RST_GPIO, 1);
+#ifdef DEBUG
+		for (i = 0; i < ARRAY_SIZE(karo_tx25_fec_strap_gpios); i++) {
+			struct gpio_desc *pd = &karo_tx25_fec_strap_gpios[i];
+			int grp = pd->gpio / 32 + 1;
+			int ofs = pd->gpio % 32;
+
+			DBG(0, "%s: GPIO%d_%d is %d\n", __FUNCTION__,
+			    grp, ofs, gpio_get_value(pd->gpio));
+		}
+#endif
+		mxc_iomux_v3_release_multiple_pads(karo_tx25_fec_gpios_off,
+						   ARRAY_SIZE(karo_tx25_fec_gpios_off));
+		ret = mxc_iomux_v3_setup_multiple_pads(karo_tx25_fec_gpios_on,
+						       ARRAY_SIZE(karo_tx25_fec_gpios_on));
+		if (ret) {
+			goto rel_gpio;
+		}
+#ifdef DEBUG
+		for (i = 0; i < ARRAY_SIZE(karo_tx25_fec_strap_gpios); i++) {
+			struct gpio_desc *pd = &karo_tx25_fec_strap_gpios[i];
+			int grp = pd->gpio / 32 + 1;
+			int ofs = pd->gpio % 32;
+
+			DBG(0, "%s: GPIO%d_%d is %d\n", __FUNCTION__,
+			    grp, ofs, gpio_get_value(pd->gpio));
+		}
+#endif
+	}
+	return ret;
+
+ rel_mux:
+	mxc_iomux_v3_release_multiple_pads(karo_tx25_fec_gpios_off,
+					   ARRAY_SIZE(karo_tx25_fec_gpios_off));
+ rel_gpio:
+	while (--i >= 0) {
+		struct gpio_desc *pd = &karo_tx25_fec_strap_gpios[i];
+		gpio_free(pd->gpio);
+	}
+	mxc_iomux_v3_release_multiple_pads(karo_tx25_fec_pwr_gpios,
+					   ARRAY_SIZE(karo_tx25_fec_pwr_gpios));
+	return ret;
+}
+
+/*
+ * Setup GPIO for FEC device to be inactive
+ *
+ */
+static void gpio_fec_inactive(void)
+{
+	int i;
+
+	mxc_iomux_v3_release_multiple_pads(karo_tx25_fec_gpios_on,
+					   ARRAY_SIZE(karo_tx25_fec_gpios_on));
+	mxc_iomux_v3_setup_multiple_pads(karo_tx25_fec_gpios_off,
+					 ARRAY_SIZE(karo_tx25_fec_gpios_off));
+	DBG(0, "%s: Asserting FEC PHY reset\n", __FUNCTION__);
+	gpio_set_value(TX25_FEC_RST_GPIO, 0);
+	DBG(0, "%s: Switching FEC PHY power off\n", __FUNCTION__);
+	gpio_set_value(TX25_FEC_PWR_GPIO, 0);
+
+	mxc_iomux_v3_release_multiple_pads(karo_tx25_fec_gpios_off,
+					   ARRAY_SIZE(karo_tx25_fec_gpios_off));
+	mxc_iomux_v3_release_multiple_pads(karo_tx25_fec_pwr_gpios,
+					   ARRAY_SIZE(karo_tx25_fec_pwr_gpios));
+	for (i = 0; i < ARRAY_SIZE(karo_tx25_fec_strap_gpios); i++) {
+		struct gpio_desc *pd = &karo_tx25_fec_strap_gpios[i];
+		gpio_free(pd->gpio);
+	}
+}
+
+static struct clk *tx25_fec_clk;
+
+static int tx25_fec_suspend(struct platform_device *pdev)
+{
+	BUG_ON(tx25_fec_clk == NULL);
+	DBG(1, "%s: Switching FEC PHY off\n", __FUNCTION__);
+	gpio_fec_inactive();
+	clk_disable(tx25_fec_clk);
+	return 0;
+}
+
+static int tx25_fec_resume(struct platform_device *pdev)
+{
+	BUG_ON(tx25_fec_clk == NULL);
+	DBG(1, "%s: Switching FEC PHY on\n", __FUNCTION__);
+	clk_enable(tx25_fec_clk);
+	gpio_fec_active();
+	return 0;
+}
+
+static int fec_arch_init(struct platform_device *pdev)
+{
+	int ret;
+
+	DBG(0, "%s: Activating FEC GPIOs\n", __FUNCTION__);
+	dump_regs();
+
+	ret = gpio_fec_active();
+	if (ret) {
+		printk(KERN_ERR "%s: could not enable FEC gpios: %d\n", __FUNCTION__, ret);
+		return ret;
+	}
+
+	BUG_ON(tx25_fec_clk != NULL);
+	tx25_fec_clk = clk_get(&pdev->dev, NULL);
+	if (unlikely(IS_ERR(tx25_fec_clk))) {
+		printk(KERN_ERR "Failed to get fec_clk\n");
+		return PTR_ERR(tx25_fec_clk);
+	}
+	DBG(0, "%s: Enabling FEC clock\n", __FUNCTION__);
+	clk_enable(tx25_fec_clk);
+	dump_regs();
+	return 0;
+}
+
+static void fec_arch_exit(struct platform_device *pdev)
+{
+	BUG_ON(tx25_fec_clk == NULL);
+	if (unlikely(IS_ERR(tx25_fec_clk))) {
+		printk(KERN_ERR "Failed to get fec_clk\n");
+		return;
+	}
+	DBG(0, "%s: Disabling FEC clock\n", __FUNCTION__);
+	clk_disable(tx25_fec_clk);
+	clk_put(tx25_fec_clk);
+	tx25_fec_clk = NULL;
+	DBG(0, "%s: Deactivating FEC GPIOs\n", __FUNCTION__);
+	gpio_fec_inactive();
+}
+
+static struct fec_enet_platform_data fec_data = {
+	.arch_init = fec_arch_init,
+	.arch_exit = fec_arch_exit,
+	.suspend = tx25_fec_suspend,
+	.resume = tx25_fec_resume,
+};
+
+static struct platform_device fec_device = {
+	.name		= "fec",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(fec_resources),
+	.resource	= fec_resources,
+	.dev = {
+		.platform_data = &fec_data,
+		.coherent_dma_mask = 0xFFFFFFFF,
+	},
+};
+#endif
+
+/* MTD NAND flash */
+#if defined(CONFIG_MTD_NAND_MXC) || defined(CONFIG_MTD_NAND_MXC_MODULE)
+static struct pad_desc karo_tx25_nand_pads[] = {
+	MX25_PAD_NF_CE0__NF_CE0,
+	MX25_PAD_NFWE_B__NFWE_B,
+	MX25_PAD_NFRE_B__NFRE_B,
+	MX25_PAD_NFALE__NFALE,
+	MX25_PAD_NFCLE__NFCLE,
+	MX25_PAD_NFWP_B__NFWP_B,
+	MX25_PAD_NFRB__NFRB,
+	MX25_PAD_D7__D7,
+	MX25_PAD_D6__D6,
+	MX25_PAD_D5__D5,
+	MX25_PAD_D4__D4,
+	MX25_PAD_D3__D3,
+	MX25_PAD_D2__D2,
+	MX25_PAD_D1__D1,
+	MX25_PAD_D0__D0,
+};
+
+static struct mxc_nand_platform_data tx25_nand_data = {
+	.hw_ecc = 1,
+	.width = 1,
+};
+
+static int tx25_nand_init(void)
+{
+	int ret;
+
+	DBG(0, "%s: Configuring NAND pins\n", __FUNCTION__);
+	ret = mxc_iomux_v3_setup_multiple_pads(karo_tx25_nand_pads,
+					       ARRAY_SIZE(karo_tx25_nand_pads));
+	if (ret) {
+		return ret;
+	}
+	return 0;
+}
+arch_initcall(tx25_nand_init);
+
+static struct resource tx25_nand_resources[] = {
+	{
+		.start	= NFC_BASE_ADDR + 0x1e00,
+		.end	= NFC_BASE_ADDR + 0x1e2f,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= NFC_BASE_ADDR,
+		.end	= NFC_BASE_ADDR + 0x11ff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= MXC_INT_NANDFC,
+		.end	= MXC_INT_NANDFC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tx25_nand_mtd_device = {
+	.name = "mxc_nand",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(tx25_nand_resources),
+	.resource = tx25_nand_resources,
+	.dev = {
+		.platform_data = &tx25_nand_data,
+	},
+};
+#endif
+
+#if defined(CONFIG_VIDEO_MXC_EMMA_OUTPUT) || defined(CONFIG_VIDEO_MXC_EMMA_OUTPUT_MODULE)
+static u64 mxc_emma_dmamask = 0xffffffffUL;
+
+static struct platform_device tx25_v4l2out_device = {
+	.name = "MXC Video Output",
+	.id = 0,
+	.dev = {
+		.dma_mask = &mxc_emma_dmamask,
+		.coherent_dma_mask = ~0UL,
+	},
+};
+#endif
+
+#if 0
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static struct pad_desc mxc_i2c0_pins[] = {
+	MX25_PAD_I2C1_CLK__I2C1_CLK,
+	MX25_PAD_I2C1_DAT__I2C1_DAT,
+};
+
+static int karo_tx25_i2c_0_init(struct device *dev)
+{
+	DBG(-1, "%s: \n", __FUNCTION__);
+	return mxc_iomux_v3_setup_multiple_pads(mxc_i2c0_pins,
+						ARRAY_SIZE(mxc_i2c0_pins));
+}
+
+static void karo_tx25_i2c_0_exit(struct device *dev)
+{
+	DBG(-1, "%s: \n", __FUNCTION__);
+	mxc_iomux_v3_release_multiple_pads(mxc_i2c0_pins,
+					   ARRAY_SIZE(mxc_i2c0_pins));
+}
+
+static struct imxi2c_platform_data karo_tx25_i2c_0_data = {
+	.bitrate = 100000,
+	.init = karo_tx25_i2c_0_init,
+	.exit = karo_tx25_i2c_0_exit,
+};
+
+static struct at24_platform_data karo_tx25_eeprom = {
+	.byte_len = 2048,
+	.page_size = 32,
+	.flags = AT24_FLAG_ADDR16 | AT24_FLAG_TAKE8ADDR,
+};
+
+static struct i2c_board_info karo_i2c_0_boardinfo[] __initdata = {
+	{
+		I2C_BOARD_INFO("24c16", 0x50),
+		.platform_data = &karo_tx25_eeprom,
+		.type = "24c16",
+	},
+};
+
+int __init karo_i2c_init(void)
+{
+	int ret;
+
+	DBG(0, "%s: Registering I2C bus 0\n", __FUNCTION__);
+	ret = mxc_register_device(&mx25_i2c_device0, &karo_tx25_i2c_0_data);
+	if (ret != 0) {
+		printk(KERN_ERR "Failed to register I2C device: %d\n", ret);
+		return ret;
+	}
+	ret = i2c_register_board_info(0, karo_i2c_0_boardinfo,
+				      ARRAY_SIZE(karo_i2c_0_boardinfo));
+	if (ret != 0) {
+		printk(KERN_ERR "Failed to register I2C board info: %d\n", ret);
+	}
+	return ret;
+}
+device_initcall(karo_i2c_init);
+#endif
+#endif
+
+#if defined(CONFIG_TOUCHSCREEN_MXC_TSADCC) || defined(CONFIG_TOUCHSCREEN_MXC_TSADCC_MODULE)
+static struct resource mxc_tsadcc_resources[] = {
+	{
+		.start = TSC_BASE_ADDR,
+		.end = TSC_BASE_ADDR + 0x85f,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MXC_INT_TSC,
+		.end = MXC_INT_TSC,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct mxc_tsadcc_pdata mxc_tsadcc_pdata = {
+	.pen_debounce_time = 32,
+	.intref = 1,
+	.adc_clk = 1750000,
+	.tsc_mode = MXC_TSC_4WIRE,
+	.hsyncen = 0,
+};
+
+static struct platform_device mxc_tsadcc_device = {
+	.id = 0,
+	.name = "mxc-tsadcc",
+	.num_resources = ARRAY_SIZE(mxc_tsadcc_resources),
+	.resource = mxc_tsadcc_resources,
+	.dev = {
+		.platform_data = &mxc_tsadcc_pdata,
+	},
+};
+#endif
+
+#if defined(CONFIG_CAN_FLEXCAN) || defined(CONFIG_CAN_FLEXCAN_MODULE)
+
+#ifdef CONFIG_CAN_FLEXCAN_CAN1
+static struct pad_desc tx25_flexcan1_pads[] = {
+	MX25_PAD_GPIO_A__CAN1_TX,
+	MX25_PAD_GPIO_B__CAN1_RX,
+};
+
+static struct resource tx25_flexcan1_resources[] = {
+	{
+		.start = CAN1_BASE_ADDR,
+		.end = CAN1_BASE_ADDR + 0x97f,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MXC_INT_CAN1,
+		.end = MXC_INT_CAN1,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static int tx25_flexcan1_active(struct platform_device *pdev)
+{
+	return mxc_iomux_v3_setup_multiple_pads(tx25_flexcan1_pads,
+					       ARRAY_SIZE(tx25_flexcan1_pads));
+}
+
+static void tx25_flexcan1_inactive(struct platform_device *pdev)
+{
+	mxc_iomux_v3_release_multiple_pads(tx25_flexcan1_pads,
+					   ARRAY_SIZE(tx25_flexcan1_pads));
+	karo_tx25_gpio_config(tx25_flexcan1_pads,
+			      ARRAY_SIZE(tx25_flexcan1_pads));
+}
+
+static struct flexcan_platform_data tx25_flexcan1_pdata = {
+	//.core_reg = NULL;
+	//.io_reg = NULL;
+	//.xcvr_enable = NULL,
+	.active = tx25_flexcan1_active,
+	.inactive = tx25_flexcan1_inactive,
+};
+
+static struct platform_device tx25_flexcan1_device = {
+	.id = 0,
+	.name = "mxc-flexcan",
+	.num_resources = ARRAY_SIZE(tx25_flexcan1_resources),
+	.resource = tx25_flexcan1_resources,
+	.dev = {
+		.platform_data = &tx25_flexcan1_pdata,
+	},
+};
+#endif // CONFIG_CAN_FLEXCAN_CAN1
+
+#ifdef CONFIG_CAN_FLEXCAN_CAN2
+static struct pad_desc tx25_flexcan2_pads[] = {
+	MX25_PAD_GPIO_C__CAN2_TX,
+	MX25_PAD_GPIO_D__CAN2_RX,
+};
+
+static struct resource tx25_flexcan2_resources[] = {
+	{
+		.start = CAN2_BASE_ADDR,
+		.end = CAN2_BASE_ADDR + 0x97f,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MXC_INT_CAN2,
+		.end = MXC_INT_CAN2,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static int tx25_flexcan2_active(struct platform_device *pdev)
+{
+	return mxc_iomux_v3_setup_multiple_pads(tx25_flexcan2_pads,
+					       ARRAY_SIZE(tx25_flexcan2_pads));
+}
+
+static void tx25_flexcan2_inactive(struct platform_device *pdev)
+{
+	mxc_iomux_v3_release_multiple_pads(tx25_flexcan2_pads,
+					   ARRAY_SIZE(tx25_flexcan2_pads));
+	karo_tx25_gpio_config(tx25_flexcan2_pads,
+			      ARRAY_SIZE(tx25_flexcan2_pads));
+}
+
+static struct flexcan_platform_data tx25_flexcan2_pdata = {
+	//.core_reg = NULL;
+	//.io_reg = NULL;
+	//.xcvr_enable = NULL,
+	.active = tx25_flexcan2_active,
+	.inactive = tx25_flexcan2_inactive,
+};
+
+static struct platform_device tx25_flexcan2_device = {
+	.id = 1,
+	.name = "mxc-flexcan",
+	.num_resources = ARRAY_SIZE(tx25_flexcan2_resources),
+	.resource = tx25_flexcan2_resources,
+	.dev = {
+		.platform_data = &tx25_flexcan2_pdata,
+	},
+};
+#endif // CONFIG_CAN_FLEXCAN_CAN2
+#endif // CONFIG_CAN_FLEXCAN || CONFIG_CAN_FLEXCAN_MODULE
+
+struct platform_dev_list {
+	struct platform_device *pdev;
+	int flag;
+} tx25_devices[] __initdata = {
+#if defined(CONFIG_RTC_MXC) || defined(CONFIG_RTC_MXC_MODULE)
+	{ .pdev = &mxc_rtc_device, .flag = -1, },
+#endif
+#if defined(CONFIG_MTD_NAND_MXC) || defined(CONFIG_MTD_NAND_MXC_MODULE)
+	{ .pdev = &tx25_nand_mtd_device, .flag = -1, },
+#endif
+#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE)
+	{ .pdev = &fec_device, .flag = -1, },
+#endif
+#if defined(CONFIG_SPI_MXC) || defined(CONFIG_SPI_MXC_MODULE)
+	{ .pdev = &mxcspi1_device, .flag = -1, },
+#endif
+#if defined(CONFIG_VIDEO_MXC_EMMA_OUTPUT) || defined(CONFIG_VIDEO_MXC_EMMA_OUTPUT_MODULE)
+	{ .pdev = &tx25_v4l2out_device, .flag = -1, },
+#endif
+#if defined(CONFIG_MXC_VPU) || defined(CONFIG_MXC_VPU_MODULE)
+	{ .pdev = &mxc_vpu_device, .flag = -1, },
+#endif
+#if defined(CONFIG_TOUCHSCREEN_MXC_TSADCC) || defined(CONFIG_TOUCHSCREEN_MXC_TSADCC_MODULE)
+	{ .pdev = &mxc_tsadcc_device, .flag = -1, },
+#endif
+#ifdef CONFIG_CAN_FLEXCAN_CAN1
+	{ .pdev = &tx25_flexcan1_device, .flag = -1, },
+#endif
+#ifdef CONFIG_CAN_FLEXCAN_CAN2
+	{ .pdev = &tx25_flexcan2_device, .flag = -1, },
+#endif
+};
+#define TX25_NUM_DEVICES		ARRAY_SIZE(tx25_devices)
+
+static __init void karo_tx25_board_init(void)
+{
+	int i;
+
+	DBG(0, "%s: \n", __FUNCTION__);
+
+	dump_regs();
+
+	for (i = 0; i < TX25_NUM_DEVICES; i++) {
+		int ret;
+
+		if (tx25_devices[i].pdev == NULL) continue;
+		if (!tx25_devices[i].flag) {
+			DBG(0, "%s: Skipping platform device[%d] @ %p dev %p: %s\n",
+			    __FUNCTION__, i, tx25_devices[i].pdev, &tx25_devices[i].pdev->dev,
+			    tx25_devices[i].pdev->name);
+			continue;
+		}
+		DBG(0, "%s: Registering platform device[%d] @ %p dev %p: %s\n",
+		    __FUNCTION__, i, tx25_devices[i].pdev, &tx25_devices[i].pdev->dev,
+		    tx25_devices[i].pdev->name);
+		ret = platform_device_register(tx25_devices[i].pdev);
+		if (ret) {
+			printk(KERN_WARNING "%s: Failed to register platform_device[%d]: %s: %d\n",
+			       __FUNCTION__, i, tx25_devices[i].pdev->name, ret);
+		}
+	}
+	DBG(0, "%s: Done\n", __FUNCTION__);
+}
+
+static struct pad_desc karo_tx25_gpios[] __initdata = {
+	MX25_PAD_GPIO_A__GPIO_A,
+	MX25_PAD_GPIO_B__GPIO_B,
+	MX25_PAD_GPIO_C__GPIO_C,
+	MX25_PAD_GPIO_D__GPIO_D,
+	MX25_PAD_GPIO_E__GPIO_E,
+	MX25_PAD_GPIO_F__GPIO_F,
+	MX25_PAD_CSI_D7__GPIO_1_6,
+	MX25_PAD_CSI_D8__GPIO_1_7,
+	MX25_PAD_CSI_MCLK__GPIO_1_8,
+	MX25_PAD_CSI_VSYNC__GPIO_1_9,
+	MX25_PAD_CSI_HSYNC__GPIO_1_10,
+	MX25_PAD_CSI_PIXCLK__GPIO_1_11,
+	MX25_PAD_I2C1_CLK__GPIO_1_12,
+	MX25_PAD_I2C1_DAT__GPIO_1_13,
+	MX25_PAD_CSPI1_MOSI__GPIO_1_14,
+	MX25_PAD_CSPI1_MISO__GPIO_1_15,
+	MX25_PAD_CSPI1_SS0__GPIO_1_16,
+	MX25_PAD_CSPI1_SS1__GPIO_1_17,
+	MX25_PAD_CSPI1_SCLK__GPIO_1_18,
+	MX25_PAD_LD5__GPIO_1_19,
+	MX25_PAD_LD6__GPIO_1_20,
+	MX25_PAD_LD7__GPIO_1_21,
+	MX25_PAD_HSYNC__GPIO_1_22,
+	MX25_PAD_VSYNC__GPIO_1_23,
+	MX25_PAD_LSCLK__GPIO_1_24,
+	MX25_PAD_OE_ACD__GPIO_1_25,
+	MX25_PAD_PWM__GPIO_1_26,
+	MX25_PAD_CSI_D2__GPIO_1_27,
+	MX25_PAD_CSI_D3__GPIO_1_28,
+	MX25_PAD_CSI_D4__GPIO_1_29,
+	MX25_PAD_CSI_D5__GPIO_1_30,
+	MX25_PAD_CSI_D6__GPIO_1_31,
+
+	MX25_PAD_A14__GPIO_2_0,
+	MX25_PAD_A15__GPIO_2_1,
+	MX25_PAD_A16__GPIO_2_2,
+	MX25_PAD_A17__GPIO_2_3,
+	MX25_PAD_A18__GPIO_2_4,
+	MX25_PAD_A19__GPIO_2_5,
+	MX25_PAD_A20__GPIO_2_6,
+	MX25_PAD_A21__GPIO_2_7,
+	MX25_PAD_A22__GPIO_2_8,
+	MX25_PAD_A23__GPIO_2_9,
+	MX25_PAD_A24__GPIO_2_10,
+	MX25_PAD_A25__GPIO_2_11,
+	MX25_PAD_EB0__GPIO_2_12,
+	MX25_PAD_EB1__GPIO_2_13,
+	MX25_PAD_OE__GPIO_2_14,
+	MX25_PAD_LD0__GPIO_2_15,
+	MX25_PAD_LD1__GPIO_2_16,
+	MX25_PAD_LD2__GPIO_2_17,
+	MX25_PAD_LD3__GPIO_2_18,
+	MX25_PAD_LD4__GPIO_2_19,
+	MX25_PAD_DE_B__GPIO_2_20,
+	MX25_PAD_CLKO__GPIO_2_21,
+	MX25_PAD_CSPI1_RDY__GPIO_2_22,
+	MX25_PAD_SD1_CMD__GPIO_2_23,
+	MX25_PAD_SD1_CLK__GPIO_2_24,
+	MX25_PAD_SD1_DATA0__GPIO_2_25,
+	MX25_PAD_SD1_DATA1__GPIO_2_26,
+	MX25_PAD_SD1_DATA2__GPIO_2_27,
+	MX25_PAD_SD1_DATA3__GPIO_2_28,
+	MX25_PAD_KPP_ROW0__GPIO_2_29,
+	MX25_PAD_KPP_ROW1__GPIO_2_30,
+	MX25_PAD_KPP_ROW2__GPIO_2_31,
+
+	MX25_PAD_KPP_ROW3__GPIO_3_0,
+	MX25_PAD_KPP_COL0__GPIO_3_1,
+	MX25_PAD_KPP_COL1__GPIO_3_2,
+	MX25_PAD_KPP_COL2__GPIO_3_3,
+	MX25_PAD_KPP_COL3__GPIO_3_4,
+	MX25_PAD_FEC_MDC__GPIO_3_5,
+	MX25_PAD_FEC_MDIO__GPIO_3_6,
+	MX25_PAD_FEC_TDATA0__GPIO_3_7,
+	MX25_PAD_FEC_TDATA1__GPIO_3_8,
+	MX25_PAD_FEC_TX_EN__GPIO_3_9,
+	MX25_PAD_FEC_RDATA0__GPIO_3_10,
+	MX25_PAD_FEC_RDATA1__GPIO_3_11,
+	MX25_PAD_FEC_RX_DV__GPIO_3_12,
+	MX25_PAD_FEC_TX_CLK__GPIO_3_13,
+	MX25_PAD_RTCK__GPIO_3_14,
+	MX25_PAD_EXT_ARMCLK__GPIO_3_15,
+	MX25_PAD_UPLL_BYPCLK__GPIO_3_16,
+	MX25_PAD_VSTBY_REQ__GPIO_3_17,
+	MX25_PAD_VSTBY_ACK__GPIO_3_18,
+	MX25_PAD_POWER_FAIL__GPIO_3_19,
+	MX25_PAD_CS4__GPIO_3_20,
+	MX25_PAD_CS5__GPIO_3_21,
+	MX25_PAD_NF_CE0__GPIO_3_22,
+	MX25_PAD_ECB__GPIO_3_23,
+	MX25_PAD_LBA__GPIO_3_24,
+	MX25_PAD_RW__GPIO_3_25,
+	MX25_PAD_NFWE_B__GPIO_3_26,
+	MX25_PAD_NFRE_B__GPIO_3_27,
+	MX25_PAD_NFALE__GPIO_3_28,
+	MX25_PAD_NFCLE__GPIO_3_29,
+	MX25_PAD_NFWP_B__GPIO_3_30,
+	MX25_PAD_NFRB__GPIO_3_31,
+
+	MX25_PAD_A10__GPIO_4_0,
+	MX25_PAD_A13__GPIO_4_1,
+	MX25_PAD_CS0__GPIO_4_2,
+	MX25_PAD_CS1__GPIO_4_3,
+	MX25_PAD_BCLK__GPIO_4_4,
+	MX25_PAD_D15__GPIO_4_5,
+	MX25_PAD_D14__GPIO_4_6,
+	MX25_PAD_D13__GPIO_4_7,
+	MX25_PAD_D12__GPIO_4_8,
+	MX25_PAD_D11__GPIO_4_9,
+	MX25_PAD_D10__GPIO_4_10,
+	MX25_PAD_D9__GPIO_4_11,
+	MX25_PAD_D8__GPIO_4_12,
+	MX25_PAD_D7__GPIO_4_13,
+	MX25_PAD_D6__GPIO_4_14,
+	MX25_PAD_D5__GPIO_4_15,
+	MX25_PAD_D4__GPIO_4_16,
+	MX25_PAD_D3__GPIO_4_17,
+	MX25_PAD_D2__GPIO_4_18,
+	MX25_PAD_D1__GPIO_4_19,
+	MX25_PAD_D0__GPIO_4_20,
+	MX25_PAD_CSI_D9__GPIO_4_21,
+	MX25_PAD_UART1_RXD__GPIO_4_22,
+	MX25_PAD_UART1_TXD__GPIO_4_23,
+	MX25_PAD_UART1_RTS__GPIO_4_24,
+	MX25_PAD_UART1_CTS__GPIO_4_25,
+	MX25_PAD_UART2_RXD__GPIO_4_26,
+	MX25_PAD_UART2_TXD__GPIO_4_27,
+	MX25_PAD_UART2_RTS__GPIO_4_28,
+	MX25_PAD_UART2_CTS__GPIO_4_29,
+	MX25_PAD_BOOT_MODE0__GPIO_4_30,
+	MX25_PAD_BOOT_MODE1__GPIO_4_31,
+};
+
+static int __init karo_tx25_setup_gpios(void)
+{
+#if 1
+	int count;
+
+	count = karo_tx25_gpio_config(karo_tx25_gpios, ARRAY_SIZE(karo_tx25_gpios));
+	DBG(0, "%s: %d out of %d pins set up as GPIO\n", __FUNCTION__,
+	    count, ARRAY_SIZE(karo_tx25_gpios));
+#else
+	int i;
+	int ret;
+	int count = 0;
+
+	for (i = 0; i < ARRAY_SIZE(karo_tx25_gpios); i++) {
+		struct pad_desc *pd = &karo_tx25_gpios[i];
+
+		ret = mxc_iomux_v3_setup_pad(pd);
+		if (ret == 0) {
+#ifdef IOMUX_DEBUG
+			DBG(0, "%s: PAD[%d] %s set up as GPIO\n", __FUNCTION__, i, pd->name);
+#else
+			DBG(0, "%s: PAD[%d] set up as GPIO\n", __FUNCTION__, i);
+#endif
+			count++;
+			mxc_iomux_v3_release_pad(pd);
+		} else {
+#ifdef IOMUX_DEBUG
+			DBG(0, "%s: PAD[%d] %s skipped\n", __FUNCTION__, i, pd->name);
+#else
+			DBG(0, "%s: PAD[%d] skipped\n", __FUNCTION__, i);
+#endif
+		}
+	}
+	DBG(0, "%s: %d out of %d pins set up as GPIO\n", __FUNCTION__, count, i);
+#endif
+	return 0;
+}
+late_initcall(karo_tx25_setup_gpios);
+
+static void __init karo_tx25_map_io(void)
+{
+	mx25_map_io();
+}
+
+static void __init karo_tx25_fixup(struct machine_desc *desc, struct tag *tags,
+				   char **cmdline, struct meminfo *mi)
+{
+}
+
+static void __init karo_tx25_timer_init(void)
+{
+	DBG(0, "%s: \n", __FUNCTION__);
+	mx25_clocks_init(24000000);
+	DBG(0, "%s: Done\n", __FUNCTION__);
+}
+
+struct sys_timer karo_tx25_timer = {
+	.init	= karo_tx25_timer_init,
+};
+
+static int __init karo_mod_type_setup(char *line)
+{
+	get_option(&line, &karo_mod_type);
+	DBG(0, "%s: Module type set to 0x%02x by kernel cmd line\n", __FUNCTION__, karo_mod_type);
+
+	return 1;
+}
+__setup("module_type=", karo_mod_type_setup);
+
+static int __init karo_board_type_setup(char *line)
+{
+	get_option(&line, &karo_board_type);
+	DBG(0, "%s: Board type set to 0x%02x by kernel cmd line\n", __FUNCTION__, karo_board_type);
+
+	return 1;
+}
+__setup("board_type=", karo_board_type_setup);
+
+MACHINE_START(TX25, "Ka-Ro electronics TX25 module (Freescale i.MX25)")
+	/* Maintainer: <LW@KARO-electronics.de> */
+	.phys_io        = AIPS1_BASE_ADDR,
+	.io_pg_offst    = ((unsigned long)AIPS1_BASE_ADDR_VIRT >> 18) & 0xfffc,
+	.fixup          = karo_tx25_fixup,
+	.map_io         = karo_tx25_map_io,
+	.init_irq       = mxc_init_irq,
+	.init_machine   = karo_tx25_board_init,
+	.timer          = &karo_tx25_timer,
+MACHINE_END
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/karo.h linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/karo.h
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/karo.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/karo.h	2009-06-02 17:59:18.000000000 +0200
@@ -0,0 +1,99 @@
+/*
+ * arch/arm/mach-mx2/karo.h
+ *
+ * Copyright (C) 2009  Lothar Wassmann <LW@KARO-electronics.de>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ *
+ * This file provides platform specific definitions for the
+ * Ka-Ro electronics TX25 processor modules
+ */
+
+#include <linux/io.h>
+#include "crm_regs_mx25.h"
+
+enum {
+	BOARD_KARO_STK5,
+};
+
+extern int karo_board_type;
+extern int karo_mod_type;
+
+#ifdef DEBUG
+extern int tx25_debug;
+#define dbg_lvl(n)	((n) < tx25_debug)
+#define DBG(lvl, fmt...)	do { if (dbg_lvl(lvl)) printk(KERN_DEBUG fmt); } while (0)
+#else
+#define dbg_lvl(n)	0
+#define DBG(lvl, fmt...)	do { } while (0)
+#endif
+
+static inline int karo_get_board_type(void)
+{
+	return karo_board_type;
+}
+
+static inline int karo_get_module_type(void)
+{
+	return karo_mod_type;
+}
+
+#define SHOW_REG(reg) DBG(0, "%s[%08lx]=%08x\n", #reg, MXC_PHYS_ADDRESS(reg), __raw_readl(reg))
+
+#define SHOW_GPIO_REG(port, reg)					\
+	DBG(0, "GPIO%d_%s[%08lx]=%08x\n", port, #reg,			\
+	    GPIO_BASE_ADDR(port) + GPIO_##reg,				\
+	    __raw_readl(IO_ADDRESS(GPIO_BASE_ADDR(port) + GPIO_##reg)))
+
+static inline void dump_regs(void)
+{
+	int i;
+
+	SHOW_REG(MXC_CCM_MPCTL);
+	SHOW_REG(MXC_CCM_UPCTL);
+	SHOW_REG(MXC_CCM_CCTL);
+	SHOW_REG(MXC_CCM_RCSR);
+	SHOW_REG(MXC_CCM_CRDR);
+	SHOW_REG(MXC_CCM_PCDR0);
+	SHOW_REG(MXC_CCM_PCDR1);
+	SHOW_REG(MXC_CCM_PCDR2);
+	SHOW_REG(MXC_CCM_PCDR3);
+	SHOW_REG(MXC_CCM_CGCR0);
+	SHOW_REG(MXC_CCM_CGCR1);
+	SHOW_REG(MXC_CCM_CGCR2);
+	SHOW_REG(MXC_CCM_MCR);
+	SHOW_REG(MXC_CCM_PMCR0);
+	SHOW_REG(MXC_CCM_PMCR1);
+	SHOW_REG(MXC_CCM_PMCR2);
+	SHOW_REG(MXC_CCM_LTBR0);
+	SHOW_REG(MXC_CCM_LTBR1);
+	SHOW_REG(MXC_CCM_LTR0);
+	SHOW_REG(MXC_CCM_LTR1);
+	SHOW_REG(MXC_CCM_LTR2);
+	SHOW_REG(MXC_CCM_LTR3);
+	SHOW_REG(MXC_CCM_DCVR0);
+	SHOW_REG(MXC_CCM_DCVR1);
+	SHOW_REG(MXC_CCM_DCVR2);
+	SHOW_REG(MXC_CCM_DCVR3);
+
+	for (i = 1; i <= 4; i++) {
+		SHOW_GPIO_REG(i, DR);
+		SHOW_GPIO_REG(i, GDIR);
+		SHOW_GPIO_REG(i, PSR);
+		SHOW_GPIO_REG(i, ICR1);
+		SHOW_GPIO_REG(i, ICR2);
+		SHOW_GPIO_REG(i, IMR);
+		SHOW_GPIO_REG(i, ISR);
+	}
+}
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/sdma_script_code.h linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/sdma_script_code.h
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/sdma_script_code.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/sdma_script_code.h	2009-06-02 17:59:18.000000000 +0200
@@ -0,0 +1,159 @@
+
+/*
+ * Copyright 2008 Freescale Semiconductor, 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
+ */
+
+/*!
+ * @file sdma_script_code.h
+ * @brief This file contains functions of SDMA scripts code initialization
+ *
+ * The file was generated automatically. Based on sdma scripts library.
+ *
+ * @ingroup SDMA
+ */
+/************************************************************************
+
+			SDMA RELEASE LABEL: 	"SS15_SENNA"
+
+************************************************************************/
+
+#ifndef SDMA_SCRIPT_CODE_H
+#define SDMA_SCRIPT_CODE_H
+
+/*!
+ * SDMA ROM scripts start addresses and sizes
+ */
+#define start_ADDR	0
+#define start_SIZE	22
+
+#define core_ADDR	80
+#define core_SIZE	233
+
+#define common_ADDR	313
+#define common_SIZE	416
+
+#define ap_2_ap_ADDR	729
+#define ap_2_ap_SIZE	41
+
+#define app_2_mcu_ADDR	770
+#define app_2_mcu_SIZE	64
+
+#define mcu_2_app_ADDR	834
+#define mcu_2_app_SIZE	70
+
+#define uart_2_mcu_ADDR	904
+#define uart_2_mcu_SIZE	75
+
+#define shp_2_mcu_ADDR	979
+#define shp_2_mcu_SIZE	69
+
+#define mcu_2_shp_ADDR	1048
+#define mcu_2_shp_SIZE	72
+
+#define uartsh_2_mcu_ADDR	1120
+#define uartsh_2_mcu_SIZE	69
+
+#define app_2_per_ADDR	1189
+#define app_2_per_SIZE	66
+
+#define per_2_app_ADDR	1255
+#define per_2_app_SIZE	74
+
+#define per_2_shp_ADDR	1329
+#define per_2_shp_SIZE	78
+
+#define shp_2_per_ADDR	1407
+#define shp_2_per_SIZE	72
+
+#define mcu_2_ata_ADDR	1479
+#define mcu_2_ata_SIZE	81
+
+#define ata_2_mcu_ADDR	1560
+#define ata_2_mcu_SIZE	96
+
+#define loop_DMAs_routines_ADDR	1656
+#define loop_DMAs_routines_SIZE	227
+
+#define test_ADDR	1883
+#define test_SIZE	63
+
+#define signature_ADDR	1022
+#define signature_SIZE	1
+
+/*!
+ * SDMA RAM scripts start addresses and sizes
+ */
+#define ext_mem__ipu_ram_ADDR	6144
+#define ext_mem__ipu_ram_SIZE	123
+
+#define uart_2_per_ADDR	6267
+#define uart_2_per_SIZE	73
+
+#define uartsh_2_per_ADDR	6340
+#define uartsh_2_per_SIZE	67
+
+/*!
+ * SDMA RAM image start address and size
+ */
+#define RAM_CODE_START_ADDR		6144
+#define RAM_CODE_SIZE			263
+
+/*!
+ * Buffer that holds the SDMA RAM image
+ */
+__attribute__ ((__aligned__(4)))
+#ifndef CONFIG_XIP_KERNEL
+const
+#endif
+static const short sdma_code[] = {
+	0x0e70, 0x0611, 0x5616, 0xc18a, 0x7d2a, 0x5ade, 0x008e, 0xc19c,
+	0x7c26, 0x5be0, 0x5ef0, 0x5ce8, 0x0688, 0x08ff, 0x0011, 0x28ff,
+	0x00bc, 0x53f6, 0x05df, 0x7d0b, 0x6dc5, 0x03df, 0x7d03, 0x6bd5,
+	0xd84f, 0x982b, 0x6b05, 0xc6d8, 0x7e27, 0x7f29, 0x982b, 0x6d01,
+	0x03df, 0x7d05, 0x6bd5, 0xc702, 0x7e18, 0x7f1a, 0x982b, 0x6b05,
+	0xc678, 0x7e07, 0x7f06, 0x52de, 0x53e6, 0xc1a8, 0x7dd7, 0x0200,
+	0x9803, 0x0007, 0x6004, 0x680c, 0x53f6, 0x028e, 0x00a3, 0xc2ad,
+	0x048b, 0x0498, 0x0454, 0x068a, 0x982b, 0x0207, 0x680c, 0x6ddf,
+	0x0107, 0x68ff, 0x60d0, 0x9834, 0x0207, 0x68ff, 0x6d28, 0x0107,
+	0x6004, 0x680c, 0x9834, 0x0007, 0x68ff, 0x60d0, 0x9834, 0x0288,
+	0x03a5, 0x3b03, 0x3d03, 0x4d00, 0x7d0a, 0x0804, 0x00a5, 0x00da,
+	0x7d1a, 0x02a0, 0x7b01, 0x65d8, 0x7eee, 0x65ff, 0x7eec, 0x0804,
+	0x02d0, 0x7d11, 0x4b00, 0x7c0f, 0x008a, 0x3003, 0x6dcf, 0x6bdf,
+	0x0015, 0x0015, 0x7b02, 0x65d8, 0x0000, 0x7edd, 0x63ff, 0x7edb,
+	0x3a03, 0x6dcd, 0x6bdd, 0x008a, 0x7b02, 0x65d8, 0x0000, 0x7ed3,
+	0x65ff, 0x7ed1, 0x0006, 0xc23a, 0x57db, 0x52f3, 0x6ad5, 0x56fb,
+	0x028e, 0x1a94, 0x6ac3, 0x62c8, 0x0269, 0x7d1e, 0x1e94, 0x6ee3,
+	0x62d0, 0x5aeb, 0x62c8, 0x0248, 0x6ed3, 0x6ac8, 0x2694, 0x52eb,
+	0x6ad5, 0x6ee3, 0x62c8, 0x026e, 0x7d27, 0x6ac8, 0x7f23, 0x2501,
+	0x4d00, 0x7d26, 0x028e, 0x1a98, 0x6ac3, 0x62c8, 0x6ec3, 0x0260,
+	0x7df1, 0x62d0, 0xc2d1, 0x98c0, 0x6ee3, 0x008f, 0x2001, 0x00d5,
+	0x7d01, 0x008d, 0x05a0, 0x62c8, 0x026e, 0x7d0e, 0x6ac8, 0x7f0a,
+	0x2001, 0x7cf9, 0x6add, 0x7f06, 0x0000, 0x4d00, 0x7d09, 0xc251,
+	0x57db, 0x987f, 0x0007, 0x6aff, 0x62d0, 0xc2d1, 0x0458, 0x0454,
+	0x6add, 0x7ff8, 0xc261, 0x987c, 0xc230, 0xc23a, 0x57db, 0x52f3,
+	0x6ad5, 0x56fb, 0x028e, 0x1a94, 0x5202, 0x0269, 0x7d17, 0x1e94,
+	0x5206, 0x0248, 0x5a06, 0x2694, 0x5206, 0x026e, 0x7d26, 0x6ac8,
+	0x7f22, 0x2501, 0x4d00, 0x7d27, 0x028e, 0x1a98, 0x5202, 0x0260,
+	0x7df3, 0x6add, 0x7f18, 0x62d0, 0xc2d1, 0x9903, 0x008f, 0x2001,
+	0x00d5, 0x7d01, 0x008d, 0x05a0, 0x5206, 0x026e, 0x7d0e, 0x6ac8,
+	0x7f0a, 0x2001, 0x7cf9, 0x6add, 0x7f06, 0x0000, 0x4d00, 0x7d0b,
+	0xc251, 0x57db, 0x98c9, 0x0007, 0x6aff, 0x6add, 0x7ffc, 0x62d0,
+	0xc2d1, 0x0458, 0x0454, 0x6add, 0x7ff6, 0xc261, 0x98c6
+};
+#endif
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx2/stk5-baseboard.c linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/stk5-baseboard.c
--- linux-2.6.30-rc4-git/arch/arm/mach-mx2/stk5-baseboard.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx2/stk5-baseboard.c	2009-07-14 13:51:43.000000000 +0200
@@ -0,0 +1,1187 @@
+/*
+ * arch/arm/mach-mx2/stk5-baseboard.c
+ *
+ * Copyright (C) 2009  Lothar Wassmann <LW@KARO-electronics.de>
+ *
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ *
+ * This file adds support for devices found on Ka-Ro electronics
+ * Starterkit-5 (STK5) baseboard
+ */
+
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/spi/spi.h>
+
+#include <linux/serial.h>
+#include <linux/fsl_devices.h>
+#include <linux/irq.h>
+#include <linux/mmc/host.h>
+#include <linux/gpio_keys.h>
+#include <linux/leds.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/iomux.h>
+#include <mach/irqs.h>
+#include <mach/clock.h>
+#include <mach/imxfb.h>
+//#include <mach/imx_spi.h>
+#include <mach/i2c.h>
+#include <mach/mmc.h>
+#include <mach/imx-uart.h>
+#include <mach/mxc_ehci.h>
+#include <mach/board-stk5.h>
+
+#include "crm_regs.h"
+#include "devices.h"
+#include "karo.h"
+
+#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
+static struct pad_desc stk5_uart_pads[][4] = {
+	{
+		MX25_PAD_UART1_TXD__UART1_TXD,
+		MX25_PAD_UART1_RXD__UART1_RXD,
+		MX25_PAD_UART1_CTS__UART1_CTS,
+		MX25_PAD_UART1_RTS__UART1_RTS,
+	}, {
+		MX25_PAD_UART2_TXD__UART2_TXD,
+		MX25_PAD_UART2_RXD__UART2_RXD,
+		MX25_PAD_UART2_CTS__UART2_CTS,
+		MX25_PAD_UART2_RTS__UART2_RTS,
+	}, {
+		MX25_PAD_ECB__UART5_TXD_MUX,
+		MX25_PAD_LBA__UART5_RXD_MUX,
+		MX25_PAD_CS4__UART5_CTS,
+		MX25_PAD_CS5__UART5_RTS,
+#if 0
+	}, {
+		MX25_PAD_UART4_TXD__UART4_TXD,
+		MX25_PAD_UART4_RXD__UART4_RXD,
+		MX25_PAD_UART4_CTS__UART4_CTS,
+		MX25_PAD_UART4_RTS__UART4_RTS,
+	}, {
+		MX25_PAD_UART5_TXD__UART5_TXD,
+		MX25_PAD_UART5_RXD__UART5_RXD,
+		MX25_PAD_UART5_CTS__UART5_CTS,
+		MX25_PAD_UART5_RTS__UART5_RTS,
+#endif
+	},
+};
+
+static int stk5_uart_init(struct platform_device *pdev)
+{
+	DBG(0, "%s: \n", __FUNCTION__);
+	return mxc_iomux_v3_setup_multiple_pads(stk5_uart_pads[pdev->id],
+						ARRAY_SIZE(stk5_uart_pads[pdev->id]));
+}
+
+static void stk5_uart_exit(struct platform_device *pdev)
+{
+	DBG(0, "%s: \n", __FUNCTION__);
+	mxc_iomux_v3_release_multiple_pads(stk5_uart_pads[pdev->id],
+					   ARRAY_SIZE(stk5_uart_pads[pdev->id]));
+}
+
+static struct imxuart_platform_data stk5_uart_ports[] = {
+	{
+		.init = stk5_uart_init,
+		.exit = stk5_uart_exit,
+		.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+	  	.init = stk5_uart_init,
+	  	.exit = stk5_uart_exit,
+	  	.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+	  	.init = stk5_uart_init,
+	  	.exit = stk5_uart_exit,
+	  	.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+	  	.init = stk5_uart_init,
+	  	.exit = stk5_uart_exit,
+	  	.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+	  	.init = stk5_uart_init,
+	  	.exit = stk5_uart_exit,
+	  	.flags = IMXUART_HAVE_RTSCTS,
+	}, {
+		.init = stk5_uart_init,
+		.exit = stk5_uart_exit,
+		.flags = IMXUART_HAVE_RTSCTS,
+	},
+};
+
+#ifdef CONFIG_USB_EHCI_MXC
+
+/* USB register offsets */
+#define REG_USBCTRL		0x600
+#define REG_PHY_CTRL		0x608
+
+#define PHY_CTRL_USBEN		(1 << 24)
+
+/* USB Host/OTG register offsets */
+#define REG_USBCMD		0x140
+#define REG_USBSTS		0x144
+#define REG_PORTSC1		0x184
+#define REG_USBMODE		0x1a8
+
+#define USBCMD_RST		(1 << 1)
+#define USBCMD_RUN		(1 << 0)
+
+#define USBSTS_HCH		(1 << 12)
+
+/* USB_CTRL register bits */
+#define USBCTRL_OCPOL_HST	(1 << 2)
+#define USBCTRL_OCPOL_OTG	(1 << 3)
+#define USBCTRL_USBTE		(1 << 4)
+#define USBCTRL_HSDT		(1 << 5)
+#define USBCTRL_PUE_DWN		(1 << 6)
+#define USBCTRL_XCSH		(1 << 9)
+#define USBCTRL_XCSO		(1 << 10)
+#define USBCTRL_PP_OTG		(1 << 11)
+#define USBCTRL_HLKEN		(1 << 12)
+#define USBCTRL_OLKEN		(1 << 13)
+#define USBCTRL_HPM		(1 << 16)
+#define USBCTRL_PP_HST		(1 << 18)
+#define USBCTRL_HWIE		(1 << 19)
+#define USBCTRL_HUIE		(1 << 20)
+#define USBCTRL_OPM		(1 << 24)
+#define USBCTRL_OEXTEN		(1 << 25)
+#define USBCTRL_HEXTEN		(1 << 26)
+#define USBCTRL_OWIE		(1 << 27)
+#define USBCTRL_OUIE		(1 << 28)
+
+#ifdef DEBUG
+#define usb_reg_write(v,b,r)	_usb_reg_write(v,b,r,#r)
+static inline void _usb_reg_write(unsigned long val, void __iomem *base, int reg,
+				  const char *name)
+{
+	DBG(0, "%s: Writing %08lx to %s[%03x]\n", __FUNCTION__, val, name, reg);
+	__raw_writel(val, base + reg);
+}
+
+#define usb_reg_read(b,r)	_usb_reg_read(b,r,#r)
+static inline unsigned long _usb_reg_read(void __iomem *base, int reg, const char *name)
+{
+	unsigned long val;
+
+	val = __raw_readl(base + reg);
+	DBG(0, "%s: Read %08lx from %s[%03x]\n", __FUNCTION__, val, name, reg);
+	return val;
+}
+#else
+static inline void usb_reg_write(unsigned long val, void __iomem *base, int reg)
+{
+	__raw_writel(val, base + reg);
+}
+
+static inline unsigned long usb_reg_read(void __iomem *base, int reg)
+{
+	return __raw_readl(base + reg);
+}
+#endif
+
+static int tx25_usb_init(struct platform_device *pdev, void __iomem *base, int host_mode)
+{
+	unsigned long val;
+	unsigned long flags;
+	const char __maybe_unused *name = pdev->id ? "USBH2" : "USBOTG";
+	unsigned int loops = 0;
+	void __iomem *otg_base = IO_ADDRESS(OTG_BASE_ADDR);
+	int ll = console_loglevel;
+
+	console_loglevel = 8;
+
+	if (!(usb_reg_read(base, REG_USBSTS) & USBSTS_HCH)) {
+		unsigned int loops = 0;
+
+		DBG(0, "%s: %s[%p] is busy: %08lx\n", __FUNCTION__, name,
+		    base + REG_USBSTS, usb_reg_read(base, REG_USBSTS));
+		usb_reg_write(usb_reg_read(base, REG_USBCTRL) & ~USBCMD_RUN,
+			      base, REG_USBCTRL);
+		while (usb_reg_read(base, REG_USBCTRL) & USBCMD_RUN) {
+			usb_reg_write(usb_reg_read(base, REG_USBCTRL) & ~USBCMD_RUN,
+				      base, REG_USBCTRL);
+			cpu_relax();
+			loops++;
+			if (loops > 100)
+				break;
+		}
+		if (usb_reg_read(base, REG_USBSTS) & USBSTS_HCH) {
+			DBG(0, "USB controller idle after %u loops\n", loops);
+		} else {
+			DBG(0, "USB controller NOT idle after %u loops\n", loops);
+		}
+	}
+	DBG(0, "%s: PHY_CTRL[%p]=%08lx\n", __FUNCTION__, otg_base + REG_PHY_CTRL,
+	    usb_reg_read(otg_base, REG_PHY_CTRL));
+	DBG(0, "%s: USBCMD[%p]=%08lx\n", __FUNCTION__, base + REG_USBCMD,
+	    usb_reg_read(base, REG_USBCMD));
+	DBG(0, "%s: USBSTS[%p]=%08lx\n", __FUNCTION__, base + REG_USBSTS,
+	    usb_reg_read(base, REG_USBSTS));
+
+	/* reset USB Host controller */
+	usb_reg_write(USBCMD_RST, base, REG_USBCMD);
+	while (usb_reg_read(base, REG_USBCMD) & USBCMD_RST) {
+		cpu_relax();
+		loops++;
+	}
+	DBG(0, "USB controller reset finished after %u loops\n", loops);
+
+	/* Switch to Host mode */
+	val = usb_reg_read(base, REG_USBMODE);
+	DBG(0, "%s: Changing %s_USBMODE from %08lx to %08lx\n", __FUNCTION__, name,
+	    val, val | (host_mode ? 0x3 : 0x02));
+	usb_reg_write(val | (host_mode ? 0x3 : 0x02), base, REG_USBMODE);
+
+	local_irq_save(flags);
+	val = usb_reg_read(otg_base, REG_USBCTRL);
+	if (pdev->id == 1) {
+		val &= ~(USBCTRL_OCPOL_HST | USBCTRL_HPM |
+			 USBCTRL_HEXTEN | USBCTRL_HWIE);
+		val |= USBCTRL_PP_HST | USBCTRL_HSDT | USBCTRL_USBTE |
+			USBCTRL_XCSH | USBCTRL_PUE_DWN;
+	} else {
+		val &= ~(USBCTRL_OCPOL_OTG | USBCTRL_OPM |
+			 USBCTRL_OEXTEN | USBCTRL_OWIE);
+		val |= USBCTRL_PP_OTG | USBCTRL_XCSO;
+	}
+	DBG(0, "%s: Changing %s_USBCTRL from %08lx to %08lx\n", __FUNCTION__, name,
+	    usb_reg_read(otg_base, REG_USBCTRL), val);
+	usb_reg_write(val, otg_base, REG_USBCTRL);
+	local_irq_restore(flags);
+
+	val = usb_reg_read(base, REG_PORTSC1);
+	if (pdev->id == 1) {
+		/* select serial transceiver */
+		val = (val & ~(3 << 30)) | (3 << 30);
+	} else {
+		/* select UTMI transceiver */
+		val = (val & ~((3 << 30) | (0 << 28))) | (0 << 30);
+	}
+	DBG(0, "%s: Changing %s_PORTSC1 from %08lx to %08lx\n", __FUNCTION__, name,
+	    usb_reg_read(base, REG_PORTSC1), val);
+	usb_reg_write(val, base, REG_PORTSC1);
+
+	console_loglevel = ll;
+	return 0;
+}
+
+#ifdef CONFIG_ARCH_MXC_EHCI_USBH2
+/*
+ * The USB power switch (MAX893L) used on the STK5 base board
+ * produces a pulse (~100us) on the OC output whenever
+ * the ON input is activated. This disturbs the USB controller.
+ * As a workaround don't use USB power switching.
+ * If you have a hardware that works cleanly you may
+ * #define USE_USB_PWR to enable port power control for
+ * the EHCI controller.
+ */
+static struct pad_desc karo_tx25_usbh2_pads[] = {
+#ifdef USE_USB_PWR
+	MX25_PAD_D9__USBH2_PWR,
+#endif
+	MX25_PAD_D8__USBH2_OC,
+};
+
+static int tx25_usbh2_init(struct platform_device *pdev)
+{
+	int ret;
+	void __iomem *base = IO_ADDRESS(OTG_BASE_ADDR + 0x400);
+#ifndef USE_USB_PWR
+	const int pwr_gpio = 3 * 32 + 11;
+#endif
+	ret = mxc_iomux_v3_setup_multiple_pads(karo_tx25_usbh2_pads,
+					       ARRAY_SIZE(karo_tx25_usbh2_pads));
+#ifdef USE_USB_PWR
+	if (ret) {
+		return ret;
+	}
+#else
+	ret = gpio_request(pwr_gpio, "USBH2_PWR");
+	if (ret) {
+		DBG(0, "%s: Failed to request GPIO %d\n", __FUNCTION__,
+		    pwr_gpio);
+		mxc_iomux_v3_release_multiple_pads(karo_tx25_usbh2_pads,
+						   ARRAY_SIZE(karo_tx25_usbh2_pads));
+		return ret;
+	}
+
+	gpio_direction_output(pwr_gpio, 1);
+#endif
+	if (ret != 0) {
+		mxc_iomux_v3_release_multiple_pads(karo_tx25_usbh2_pads,
+						   ARRAY_SIZE(karo_tx25_usbh2_pads));
+		goto exit;
+	}
+	ret = tx25_usb_init(pdev, base, 1);
+
+ exit:
+#ifndef USE_USB_PWR
+	gpio_free(pwr_gpio);
+#endif
+	return ret;
+}
+
+static int tx25_usbh2_exit(struct platform_device *pdev)
+{
+	mxc_iomux_v3_release_multiple_pads(karo_tx25_usbh2_pads,
+					   ARRAY_SIZE(karo_tx25_usbh2_pads));
+	return 0;
+}
+
+static struct mxc_usbh_platform_data tx25_usbh2_data = {
+	.init = tx25_usbh2_init,
+	.exit = tx25_usbh2_exit,
+};
+
+int tx25_usbh2_register(void)
+{
+	int ret;
+
+	ret = mxc_register_device(&mxc_usbh2_device, &tx25_usbh2_data);
+	return ret;
+}
+device_initcall(tx25_usbh2_register);
+#endif // CONFIG_ARCH_MXC_EHCI_USBH2
+
+#ifdef CONFIG_ARCH_MXC_EHCI_USBOTG
+static struct pad_desc karo_tx25_usbotg_pads[] = {
+#ifdef USE_USB_PWR
+	MX25_PAD_GPIO_A__USBOTG_PWR,
+#endif
+	MX25_PAD_GPIO_B__USBOTG_OC,
+};
+
+static int tx25_usbotg_init(struct platform_device *pdev)
+{
+	int ret;
+	void __iomem *base = IO_ADDRESS(OTG_BASE_ADDR + 0x000);
+#ifndef USE_USB_PWR
+	const int pwr_gpio = 0 * 32 + 0;
+#endif
+	DBG(0, "%s: \n", __FUNCTION__);
+
+	ret = mxc_iomux_v3_setup_multiple_pads(karo_tx25_usbotg_pads,
+					       ARRAY_SIZE(karo_tx25_usbotg_pads));
+#ifdef USE_USB_PWR
+	if (ret) {
+		return ret;
+	}
+#else
+	ret = gpio_request(pwr_gpio, "USBOTG_PWR");
+	if (ret) {
+		DBG(0, "%s: Failed to request GPIO %d\n", __FUNCTION__,
+		    pwr_gpio);
+		mxc_iomux_v3_release_multiple_pads(karo_tx25_usbh2_pads,
+						   ARRAY_SIZE(karo_tx25_usbh2_pads));
+		return ret;
+	}
+
+	gpio_direction_output(pwr_gpio, 1);
+#endif
+	if (ret != 0) {
+		mxc_iomux_v3_release_multiple_pads(karo_tx25_usbotg_pads,
+						   ARRAY_SIZE(karo_tx25_usbotg_pads));
+		goto exit;
+	}
+	ret = tx25_usb_init(pdev, base, 1);
+
+ exit:
+#ifndef USE_USB_PWR
+	gpio_free(pwr_gpio);
+#endif
+	return ret;
+}
+
+static int tx25_usbotg_exit(struct platform_device *pdev)
+{
+	mxc_iomux_v3_release_multiple_pads(karo_tx25_usbotg_pads,
+					   ARRAY_SIZE(karo_tx25_usbotg_pads));
+	return 0;
+}
+
+static struct mxc_usbh_platform_data tx25_usbotg_data = {
+	.init = tx25_usbotg_init,
+	.exit = tx25_usbotg_exit,
+};
+
+int tx25_usbotg_register(void)
+{
+	int ret;
+
+	ret = mxc_register_device(&mxc_usbotg_device, &tx25_usbotg_data);
+	return ret;
+}
+device_initcall(tx25_usbotg_register);
+#endif // CONFIG_ARCH_MXC_EHCI_USBOTG
+#endif // CONFIG_USB_EHCI_MXC
+
+static struct platform_device *stk5_uart_devices[] = {
+#if UART1_ENABLED
+	&mxc_uart_device0,
+#endif
+#if UART2_ENABLED
+	&mxc_uart_device1,
+#endif
+#if UART3_ENABLED
+	&mxc_uart_device2,
+#endif
+#if UART4_ENABLED
+	&mxc_uart_device3,
+#endif
+#if UART5_ENABLED
+	&mxc_uart_device4,
+#endif
+};
+
+static void __init karo_stk5_serial_init(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(stk5_uart_devices); i++) {
+		int ret;
+		int port = stk5_uart_devices[i]->id;
+
+		DBG(0, "%s: Registering platform device[%d] @ %p dev %p: %s\n",
+		    __FUNCTION__, i, stk5_uart_devices[i],
+		    &stk5_uart_devices[i]->dev, stk5_uart_devices[i]->name);
+		ret = mxc_register_device(stk5_uart_devices[i],
+					  &stk5_uart_ports[port]);
+		if (ret != 0) {
+			printk(KERN_WARNING "%s: Failed to register platform_device[%d]: %s: %d\n",
+			       __FUNCTION__, i, stk5_uart_devices[i]->name, ret);
+		}
+	}
+}
+#else
+static void __init karo_stk5_serial_init(void)
+{
+}
+#endif
+
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+static struct gpio_led stk5_leds[] = {
+	{
+		.name = "GPIO-LED",
+		.default_trigger = "heartbeat",
+		.gpio = GPIO_PORTB | 7,
+	},
+};
+
+static struct gpio_led_platform_data stk5_led_data = {
+	.leds = stk5_leds,
+	.num_leds = ARRAY_SIZE(stk5_leds),
+};
+
+static struct platform_device stk5_led_device = {
+	.name = "leds-gpio",
+	.id = -1,
+	.dev = {
+		.platform_data = &stk5_led_data,
+	},
+};
+#endif
+
+#if defined(CONFIG_KEYBOARD_MXC) || defined(CONFIG_KEYBOARD_MXC_MODULE)
+/*!
+ * This array is used for mapping mx25 ADS keypad scancodes to input keyboard
+ * keycodes.
+ */
+static u16 stk5_kpd_keycodes[] = {
+	KEY_POWER,
+};
+
+static struct keypad_data stk5_keypad = {
+	.rowmax = 1,
+	.colmax = 1,
+	.irq = MXC_INT_KPP,
+	.learning = 0,
+	//.delay = 2, /* unused in the driver! */
+	.matrix = stk5_kpd_keycodes,
+};
+
+static struct resource stk5_kpp_resources[] = {
+	{
+		.start = MXC_INT_KPP,
+		.end = MXC_INT_KPP,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+/* stk5 keypad driver */
+static struct platform_device stk5_keypad_device = {
+	.name = "mxc_keypad",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(stk5_kpp_resources),
+	.resource = stk5_kpp_resources,
+	.dev = {
+		.platform_data = &stk5_keypad,
+	},
+};
+#endif
+
+#if defined(CONFIG_FB_IMX) || defined(CONFIG_FB_IMX_MODULE)
+/*
+ * Setup GPIO for LCDC device to be active
+ *
+ */
+static struct pad_desc mx25_lcdc_gpios[] = {
+#if 0
+	MXC_PIN(A, 30, GPIO, GPIO_OUT | GPIO_DFLT_LOW),	/* PA30 */
+	MXC_PIN(A, 25, GPIO, GPIO_OUT | GPIO_DFLT_LOW),	/* PA25 */
+	MXC_PIN(A, 26, GPIO, GPIO_OUT | GPIO_DFLT_LOW),	/* PA26 */
+	MXC_PIN(A, 24, GPIO, GPIO_OUT | GPIO_DFLT_LOW),	/* PA24 */
+	MXC_PIN(A, 27, GPIO, GPIO_OUT | GPIO_DFLT_LOW),	/* PA27 */
+#endif
+	MX25_PAD_LSCLK__LSCLK,
+	MX25_PAD_LD0__LD0,
+	MX25_PAD_LD1__LD1,
+	MX25_PAD_LD2__LD2,
+	MX25_PAD_LD3__LD3,
+	MX25_PAD_LD4__LD4,
+	MX25_PAD_LD5__LD5,
+	MX25_PAD_LD6__LD6,
+	MX25_PAD_LD7__LD7,
+	MX25_PAD_LD8__LD8,
+	MX25_PAD_LD9__LD9,
+	MX25_PAD_LD10__LD10,
+	MX25_PAD_LD11__LD11,
+	MX25_PAD_LD12__LD12,
+	MX25_PAD_LD13__LD13,
+	MX25_PAD_LD14__LD14,
+	MX25_PAD_LD15__LD15,
+	MX25_PAD_D15__LD16,
+	MX25_PAD_D14__LD17,
+	MX25_PAD_HSYNC__HSYNC,
+	MX25_PAD_VSYNC__VSYNC,
+	MX25_PAD_OE_ACD__OE_ACD,
+};
+
+static int stk5_gpio_lcdc_active(struct platform_device *dev)
+{
+	int ret;
+
+	DBG(0, "%s: Setting up GPIO pins for LCD\n", __FUNCTION__);
+	ret = mxc_iomux_v3_setup_multiple_pads(mx25_lcdc_gpios,
+					       ARRAY_SIZE(mx25_lcdc_gpios));
+	if (ret) {
+		DBG(0, "%s: Failed to setup GPIO pins for LCD: %d\n",
+		    __FUNCTION__, ret);
+		return ret;
+	}
+	return 0;
+}
+
+/*
+ * Setup GPIO for LCDC device to be inactive
+ *
+ */
+static void stk5_gpio_lcdc_inactive(struct platform_device *dev)
+{
+	mxc_iomux_v3_release_multiple_pads(mx25_lcdc_gpios,
+					   ARRAY_SIZE(mx25_lcdc_gpios));
+}
+
+static struct imx_fb_platform_data stk5_fb_data[] __initdata = {
+	{
+#if 1
+		//.fb_mode = "Xenarc_700_Y-18",
+		.init = stk5_gpio_lcdc_active,
+		.exit = stk5_gpio_lcdc_inactive,
+		.lcd_power = NULL,
+		.backlight_power = NULL,
+
+		.pixclock	= 45833,
+
+		.xres		= 640,
+		.yres		= 480,
+
+		.bpp		= 8,
+
+		.hsync_len	= 64,
+		.right_margin	= 28 + 1,
+		.left_margin	= 20 + 3,
+
+		.vsync_len	= 1,
+		.lower_margin	= 0,
+		.upper_margin	= 16,
+
+		.pcr		= PCR_TFT | PCR_COLOR | PCR_END_BYTE_SWAP |
+		PCR_BPIX_8 | PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL,
+		.dmacr		= 0x80040060,
+
+		.cmap_greyscale	= 0,
+		.cmap_inverse	= 0,
+		.cmap_static	= 0,
+
+		.fixed_screen_cpu = NULL,
+	}, {
+#endif
+		//.fb_mode = "Xenarc_700_Y-18",
+		.init = stk5_gpio_lcdc_active,
+		.exit = stk5_gpio_lcdc_inactive,
+		.lcd_power = NULL,
+		.backlight_power = NULL,
+#if 1
+		.pixclock	= 34576,
+#else
+		.pixclock	= 38033,
+#endif
+		.xres		= 640,
+		.yres		= 480,
+
+		.bpp		= 32,
+#if 1
+		.hsync_len	= 64,
+		.right_margin	= 60 + 1,
+		.left_margin	= 80 + 3,
+#else
+		.hsync_len	= 64,
+		.right_margin	= 79 + 1,
+		.left_margin	= 57 + 3,
+#endif
+#if 1
+		.vsync_len	= 2,
+		.lower_margin	= 54,
+		.upper_margin	= 54,
+#else
+		.vsync_len	= 4,
+		.lower_margin	= 54,
+		.upper_margin	= 54,
+#endif
+#if 0
+		/* currently not used by driver! */
+		.sync		= ((0*FB_SYNC_HOR_HIGH_ACT) |
+				   (0*FB_SYNC_VERT_HIGH_ACT) |
+				   (1*FB_SYNC_OE_ACT_HIGH)),
+#else
+		.pcr		= PCR_TFT | PCR_COLOR | PCR_PBSIZ_8 |
+		PCR_BPIX_18 | PCR_END_SEL | PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL,
+		.dmacr		= 0x80040060,
+#endif
+		.cmap_greyscale	= 0,
+		.cmap_inverse	= 0,
+		.cmap_static	= 0,
+
+		.fixed_screen_cpu = NULL,
+	}, {
+		//.fb_mode = "Xenarc_700_Y-16",
+		.init = stk5_gpio_lcdc_active,
+		.exit = stk5_gpio_lcdc_inactive,
+		.lcd_power = NULL,
+		.backlight_power = NULL,
+
+		.pixclock	= 34576,
+		.xres		= 640,
+		.yres		= 480,
+
+		.bpp		= 16,
+
+		.hsync_len	= 64,
+		.right_margin	= 138 + 1,
+		.left_margin	= 118 + 3,
+
+		.vsync_len	= 7,
+		.lower_margin	= 44,
+		.upper_margin	= 44,
+#if 0
+		/* currently not used by driver! */
+		.sync		= ((0*FB_SYNC_HOR_HIGH_ACT) |
+				   (0*FB_SYNC_VERT_HIGH_ACT) |
+				   (1*FB_SYNC_OE_ACT_HIGH)),
+#else
+		.pcr		= PCR_TFT | PCR_COLOR | PCR_PBSIZ_8 |
+		PCR_BPIX_16 | PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL,
+		.dmacr		= 0x80040060,
+#endif
+		.cmap_greyscale	= 0,
+		.cmap_inverse	= 0,
+		.cmap_static	= 0,
+
+		.fixed_screen_cpu = NULL,
+	}, {
+		//.fb_mode = "SHARP LQ10D42-16",
+		.init = stk5_gpio_lcdc_active,
+		.exit = stk5_gpio_lcdc_inactive,
+		.lcd_power = NULL,
+		.backlight_power = NULL,
+
+		.pixclock	= 34576,
+		.xres		= 640,
+		.yres		= 480,
+
+#ifdef USE_18BPP
+		.bpp		= 32,
+#else
+		.bpp		= 16,
+#endif
+		.hsync_len	= 64,
+		.right_margin	= 138 + 1,
+		.left_margin	= 118 + 3,
+
+		.vsync_len	= 7,
+		.lower_margin	= 60,
+		.upper_margin	= 28,
+#if 0
+		/* currently not used by driver! */
+		.sync		= ((0*FB_SYNC_HOR_HIGH_ACT) |
+				   (0*FB_SYNC_VERT_HIGH_ACT) |
+				   (1*FB_SYNC_OE_ACT_HIGH)),
+#else
+		.pcr		= PCR_TFT | PCR_COLOR | PCR_PBSIZ_8 |
+#ifdef USE_18BPP
+		PCR_BPIX_18 | PCR_END_SEL | PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL,
+#else
+		PCR_BPIX_16 | PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL,
+#endif
+		.dmacr		= 0x80040060,
+#endif
+		.cmap_greyscale	= 0,
+		.cmap_inverse	= 0,
+		.cmap_static	= 0,
+
+		.fixed_screen_cpu = NULL,
+	}, {
+		//.fb_mode = "SHARP LQ104V1DG61-16",
+		.init = stk5_gpio_lcdc_active,
+		.exit = stk5_gpio_lcdc_inactive,
+		.lcd_power = NULL,
+		.backlight_power = NULL,
+
+		.pixclock	= 40000,
+		.xres		= 640,
+		.yres		= 480,
+
+#ifdef USE_18BPP
+		.bpp		= 32,
+#else
+		.bpp		= 16,
+#endif
+		.hsync_len	= 32,
+		.right_margin	= 32 + 1,
+		.left_margin	= 0 + 3,
+
+		.vsync_len	= 35,
+		.lower_margin	= 0,
+		.upper_margin	= 0,
+#if 0
+		/* currently not used by driver! */
+		.sync		= ((0*FB_SYNC_HOR_HIGH_ACT) |
+				   (0*FB_SYNC_VERT_HIGH_ACT) |
+				   (1*FB_SYNC_OE_ACT_HIGH)),
+#else
+		.pcr		= PCR_TFT | PCR_COLOR | PCR_PBSIZ_8 |
+#ifdef USE_18BPP
+		PCR_BPIX_18 | PCR_END_SEL | PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL,
+#else
+		PCR_BPIX_16 | PCR_FLMPOL | PCR_LPPOL | PCR_CLKPOL | PCR_SCLK_SEL,
+#endif
+		.dmacr		= 0x80040060,
+#endif
+		.cmap_greyscale	= 0,
+		.cmap_inverse	= 0,
+		.cmap_static	= 0,
+
+		.fixed_screen_cpu = NULL,
+	},
+};
+
+static int __init karo_stk5_fb_register(void)
+{
+	int ret;
+
+	ret = mxc_register_device(&mxc_fb_device, &stk5_fb_data[0]);
+	if (ret != 0) {
+		DBG(0, "%s: Failed to register FB device: %d\n", __FUNCTION__, ret);
+	}
+	return ret;
+}
+#else
+static inline int karo_stk5_fb_register(void)
+{
+	return 0;
+}
+#endif
+
+#if defined(CONFIG_MMC_MXC) || defined(CONFIG_MMC_MXC_MODULE)
+/*!
+ * Resource definition for the SDHC1
+ */
+static struct resource stk5_sdhc1_resources[] = {
+	{
+		.start = MMC_SDHC1_BASE_ADDR,
+		.end = MMC_SDHC1_BASE_ADDR + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	}, {
+		.start = MXC_INT_SDHC1,
+		.end = MXC_INT_SDHC1,
+		.flags = IORESOURCE_IRQ,
+	}, {
+		.start = gpio_to_irq(4 * 32 + 4),
+		.end = gpio_to_irq(4 * 32 + 4),
+		.flags = IORESOURCE_IRQ,
+#if 0
+	}, {
+		.name   = "sdhc1",
+		.start  = DMA_REQ_SDHC1,
+		.end    = DMA_REQ_SDHC1,
+		.flags  = IORESOURCE_DMA
+#endif
+	},
+};
+
+static inline int stk5_mmc_get_irq(int id)
+{
+	int irq;
+
+	switch (id) {
+	case 0:
+		irq = stk5_sdhc1_resources[2].start;
+		break;
+	default:
+		BUG();
+	}
+	return irq;
+}
+
+static const char *stk5_mmc_irqdesc[] = {
+	"MMC card 0 detect",
+};
+
+static struct pad_desc stk5_sdhc_pads[] = {
+};
+
+static int stk5_mmc_init(struct device *dev, irqreturn_t (*mmc_detect_irq)(int, void *),
+			 void *data)
+{
+	int err;
+	int id = to_platform_device(dev)->id;
+	struct mmc_host *host = data;
+	int irq = stk5_mmc_get_irq(id);
+
+	err = mxc_iomux_v3_setup_multiple_pads(stk5_sdhc_pads,
+					       ARRAY_SIZE(stk5_sdhc_pads));
+	if (err) {
+		return err;
+	}
+
+	host->caps |= MMC_CAP_4_BIT_DATA;
+
+	err = request_irq(irq, mmc_detect_irq,
+			  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			  stk5_mmc_irqdesc[id], data);
+	if (err) {
+		printk(KERN_ERR "%s: MMC/SD: can't request MMC card detect IRQ %d\n",
+		       __FUNCTION__, irq);
+		return err;
+	}
+	device_set_wakeup_capable(dev, 1);
+
+	return 0;
+}
+
+static void stk5_mmc_exit(struct device *dev, void *data)
+{
+	int id = to_platform_device(dev)->id;
+	int irq = stk5_mmc_get_irq(id);
+
+	free_irq(irq, data);
+	mxc_iomux_v3_release_multiple_pads(stk5_sdhc_pads,
+					   ARRAY_SIZE(stk5_sdhc_pads));
+}
+
+#if 0
+static int stk5_mmc_suspend(struct device *dev, pm_message_t state)
+{
+	int id = to_platform_device(dev)->id;
+	int irq = stk5_mmc_get_irq(id);
+
+	if (device_may_wakeup(dev)) {
+		DBG(0, "%s: Enabling IRQ %d wakeup\n", __FUNCTION__, irq);
+		return enable_irq_wake(irq);
+	}
+	return 0;
+}
+
+static int stk5_mmc_resume(struct device *dev)
+{
+	int id = to_platform_device(dev)->id;
+	int irq = stk5_mmc_get_irq(id);
+
+	if (device_may_wakeup(dev)) {
+		DBG(0, "%s: Disabling IRQ %d wakeup\n", __FUNCTION__, irq);
+		return disable_irq_wake(irq);
+	}
+	return 0;
+}
+#endif
+
+static struct imxmmc_platform_data stk5_sdhc1_data = {
+	//.ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
+	//.min_clk = 150000,
+	//.max_clk = 25000000,
+	//.detect_delay = 20,
+	.init = stk5_mmc_init,
+	.exit = stk5_mmc_exit,
+//	.suspend = stk5_mmc_suspend,
+//	.resume = stk5_mmc_resume,
+};
+
+static struct platform_device stk5_sdhc1_device = {
+	.name = "imx-mmc",
+	.id = 0,
+	.dev = {
+		.platform_data = &stk5_sdhc1_data,
+	},
+	.num_resources = ARRAY_SIZE(stk5_sdhc1_resources),
+	.resource = stk5_sdhc1_resources,
+};
+#endif
+
+#if defined(CONFIG_SPI_MXC) || defined(CONFIG_SPI_MXC_MODULE)
+static struct resource mxcspi1_resources[] = {
+	{
+	       .start = CSPI1_BASE_ADDR,
+	       .end = CSPI1_BASE_ADDR + SZ_4K - 1,
+	       .flags = IORESOURCE_MEM,
+	}, {
+	       .start = MXC_INT_CSPI1,
+	       .end = MXC_INT_CSPI1,
+	       .flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct mxc_spi_master mxcspi1_data = {
+	.maxchipselect = 2,
+	.spi_version = 0,
+};
+
+static struct platform_device mxcspi1_device = {
+	.name = "mxc_spi",
+	.id = 0,
+	.dev = {
+		.platform_data = &mxcspi1_data,
+	},
+	.num_resources = ARRAY_SIZE(mxcspi1_resources),
+	.resource = mxcspi1_resources,
+};
+#endif // defined(CONFIG_SPI_MXC) || defined(CONFIG_SPI_MXC_MODULE)
+
+#if defined(CONFIG_AC97_BUS) || defined(CONFIG_AC97_BUS_MODULE)
+static u64 stk5_dma_mask = ~0UL;
+
+static struct pad_desc stk5_ac97_pads_on[] = {
+	MX25_PAD_VSTBY_ACK__GPIO_3_18, /* UCB1400 Reset */
+	MX25_PAD_RW__AUD4_TXFS,
+	MX25_PAD_EB0__AUD4_TXD,
+	MX25_PAD_EB1__AUD4_RXD,
+	MX25_PAD_OE__AUD4_TXC,
+};
+
+static struct pad_desc stk5_ac97_pads_off[] = {
+	MX25_PAD_VSTBY_ACK__GPIO_3_18, /* UCB1400 Reset */
+	MX25_PAD_RW__GPIO_3_25,
+	MX25_PAD_EB0__GPIO_2_12,
+	MX25_PAD_EB1__AUD4_RXD,
+	MX25_PAD_OE__AUD4_TXC,
+};
+
+static struct gpio_desc {
+	unsigned int gpio:7;
+	unsigned int dir:1;
+	unsigned int level:1;
+} stk5_ac97_gpios[] = {
+	/* configure the PHY strap pins to the correct values */
+	{ GPIO_PORTC | 18, 1, 0, },
+	{ GPIO_PORTC | 25, 1, 0, },
+	{ GPIO_PORTB | 12, 1, 0, },
+};
+
+static int stk5_ac97_init(struct platform_device *dev)
+{
+	int ret;
+	int i;
+
+	DBG(0, "%s: \n", __FUNCTION__);
+
+	ret = mxc_iomux_v3_setup_multiple_pads(stk5_ac97_pads_off,
+					       ARRAY_SIZE(stk5_ac97_pads_off));
+	if (ret == 0) {
+		for (i = 0; i < ARRAY_SIZE(stk5_ac97_gpios); i++) {
+			struct gpio_desc *pd = &stk5_ac97_gpios[i];
+
+			ret = gpio_request(pd->gpio, "AC97");
+			if (ret < 0) {
+				DBG(0, "%s: Failed to request GPIO%d_%d: %d\n",
+				    __FUNCTION__, pd->gpio / 32 + 1, pd->gpio % 32, ret);
+				goto rel_mux;
+			}
+			if (pd->dir) {
+				gpio_direction_output(pd->gpio,
+						      pd->level);
+			} else {
+				gpio_direction_input(pd->gpio);
+			}
+		}
+
+		ret = mxc_iomux_v3_setup_multiple_pads(stk5_ac97_pads_on,
+						       ARRAY_SIZE(stk5_ac97_pads_on));
+		if (ret != 0) {
+			goto rel_gpio;
+		}
+		udelay(1);
+		gpio_set_value(stk5_ac97_gpios[0].gpio, !stk5_ac97_gpios[0].level);
+	}
+	return ret;
+
+ rel_mux:
+	mxc_iomux_v3_release_multiple_pads(stk5_ac97_gpios_off,
+					   ARRAY_SIZE(stk5_ac97_gpios_off));
+ rel_gpio:
+	while (--i >= 0) {
+		struct gpio_desc *pd = &stk5_ac97_gpios[i];
+		int grp = pd->gpio / 32 + 1;
+		int ofs = pd->gpio % 32;
+
+		DBG(0, "%s: Freeing GPIO%d_%d\n", __FUNCTION__,
+		    grp, ofs);
+		gpio_free(pd->gpio);
+	}
+	return ret;
+}
+
+static void stk5_ac97_exit(struct platform_device *dev)
+{
+	int i;
+
+	DBG(0, "%s: Releasing AC97 GPIO pins\n", __FUNCTION__);
+
+	mxc_iomux_v3_release_multiple_pads(stk5_ac97_pads_on,
+					   ARRAY_SIZE(stk5_ac97_pads_on));
+	for (i = 0; i < ARRAY_SIZE(stk5_ac97_gpios); i++) {
+		struct gpio_desc *pd = &stk5_ac97_gpios[i];
+		int grp = pd->gpio / 32 + 1;
+		int ofs = pd->gpio % 32;
+
+		DBG(0, "%s: Freeing GPIO%d_%d\n", __FUNCTION__,
+		    grp, ofs);
+		gpio_free(pd->gpio);
+	}
+}
+
+static struct mxc_ac97_audio_ops stk5_ac97_ops = {
+	.init = stk5_ac97_init,
+	.exit = stk5_ac97_exit,
+	.startup = NULL,
+	.shutdown = NULL,
+	.suspend = NULL,
+	.resume = NULL,
+	.priv = NULL,
+};
+
+static struct platform_device ac97_device = {
+	.name		= "mx25-ac97",
+	.id		= -1,
+	.dev = {
+		.dma_mask = &stk5_dma_mask,
+		.coherent_dma_mask = ~0UL,
+		.platform_data = &stk5_ac97_ops,
+	},
+};
+#endif
+
+static struct platform_dev_list {
+	struct platform_device *pdev;
+	int flag;
+} stk5_devices[] __initdata = {
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+	{ .pdev = &stk5_led_device, .flag = -1, },
+#endif
+#if defined(CONFIG_KEYBOARD_MXC) || defined(CONFIG_KEYBOARD_MXC_MODULE)
+	{ .pdev = &stk5_keypad_device, .flag = 1, },
+#endif
+#if defined(CONFIG_SPI_MXC) || defined(CONFIG_SPI_MXC_MODULE)
+	{ .pdev = &mxcspi1_device, .flag = 1, },
+#endif
+#if defined(CONFIG_AC97_BUS) || defined(CONFIG_AC97_BUS_MODULE)
+	{ .pdev = &ac97_device, .flag = 1, },
+#endif
+#if defined(CONFIG_MMC_MXC) || defined(CONFIG_MMC_MXC_MODULE)
+	{ .pdev = &stk5_sdhc1_device, .flag = 1, },
+#endif
+};
+#define STK5_NUM_DEVICES		ARRAY_SIZE(stk5_devices)
+
+static __init int karo_stk5_board_init(void)
+{
+	int ret;
+	int i;
+
+	if (karo_get_board_type() != BOARD_KARO_STK5) {
+		return -ENODEV;
+	}
+	DBG(0, "%s: \n", __FUNCTION__);
+
+	karo_stk5_serial_init();
+
+	dump_regs();
+
+	/* enable SSI1_INT (GPIO_3_15) for IRQ probing */
+	set_irq_flags(gpio_to_irq(GPIO_PORTC | 15), IRQF_VALID | IRQF_PROBE);
+
+	ret = karo_stk5_fb_register();
+	if (ret) {
+		printk(KERN_WARNING "%s: karo_stk5_fb_register() failed: %d\n",
+		       __FUNCTION__, ret);
+	}
+
+	for (i = 0; i < STK5_NUM_DEVICES; i++) {
+		if (stk5_devices[i].pdev == NULL) continue;
+		if (!stk5_devices[i].flag) {
+			DBG(0, "%s: Skipping platform device[%d] @ %p dev %p: %s\n",
+			    __FUNCTION__, i, stk5_devices[i].pdev, &stk5_devices[i].pdev->dev,
+			    stk5_devices[i].pdev->name);
+			continue;
+		}
+		DBG(0, "%s: Registering platform device[%d] @ %p dev %p: %s\n",
+		    __FUNCTION__, i, stk5_devices[i].pdev, &stk5_devices[i].pdev->dev,
+		    stk5_devices[i].pdev->name);
+		ret = platform_device_register(stk5_devices[i].pdev);
+		if (ret) {
+			printk(KERN_WARNING "%s: Failed to register platform_device[%d]: %s: %d\n",
+			       __FUNCTION__, i, stk5_devices[i].pdev->name, ret);
+		}
+	}
+	DBG(0, "%s: Done\n", __FUNCTION__);
+	return 0;
+}
+subsys_initcall(karo_stk5_board_init);
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx3/clock-imx35.c linux-2.6.30-rc4-karo3/arch/arm/mach-mx3/clock-imx35.c
--- linux-2.6.30-rc4-git/arch/arm/mach-mx3/clock-imx35.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx3/clock-imx35.c	2009-06-02 17:59:19.000000000 +0200
@@ -381,7 +381,7 @@ DEFINE_CLOCK(gpu2d_clk,  0, CCM_CGR3,  4
 		.clk = &c,		\
 	},
 
-static struct clk_lookup lookups[] __initdata = {
+static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "asrc", asrc_clk)
 	_REGISTER_CLOCK(NULL, "ata", ata_clk)
 	_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
diff -purN linux-2.6.30-rc4-git/arch/arm/mach-mx3/clock.c linux-2.6.30-rc4-karo3/arch/arm/mach-mx3/clock.c
--- linux-2.6.30-rc4-git/arch/arm/mach-mx3/clock.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/mach-mx3/clock.c	2009-06-02 17:59:19.000000000 +0200
@@ -516,7 +516,7 @@ DEFINE_CLOCK(ipg_clk,     0, NULL,      
 		.clk = &c, \
 	},
 
-static struct clk_lookup lookups[] __initdata = {
+static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK(NULL, "emi", emi_clk)
 	_REGISTER_CLOCK(NULL, "cspi", cspi1_clk)
 	_REGISTER_CLOCK(NULL, "cspi", cspi2_clk)
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/Kconfig linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/Kconfig
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/Kconfig	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/Kconfig	2009-06-02 18:01:59.000000000 +0200
@@ -56,6 +56,9 @@ config ARCH_HAS_RNGA
 	bool
 	depends on ARCH_MXC
 
+config ARCH_MXC_IOMUX_V2
+	bool
+
 config ARCH_MXC_IOMUX_V3
 	bool
 endif
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/Makefile linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/Makefile
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/Makefile	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/Makefile	2009-06-02 18:02:00.000000000 +0200
@@ -5,7 +5,7 @@
 # Common support
 obj-y := irq.o clock.o gpio.o time.o devices.o cpu.o system.o
 
-obj-$(CONFIG_ARCH_MX1) += iomux-mx1-mx2.o dma-mx1-mx2.o
-obj-$(CONFIG_ARCH_MX2) += iomux-mx1-mx2.o dma-mx1-mx2.o
-obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
-obj-$(CONFIG_MXC_PWM)  += pwm.o
+obj-$(CONFIG_ARCH_MXC_IOMUX_V2)	+= iomux-mx1-mx2.o dma-mx1-mx2.o
+obj-$(CONFIG_ARCH_MXC_IOMUX_V3)	+= iomux-v3.o
+obj-$(CONFIG_MXC_PWM)		+= pwm.o
+obj-$(CONFIG_MACH_MX25)		+= spba.o
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/board-stk5.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/board-stk5.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/board-stk5.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/board-stk5.h	2009-06-02 18:02:13.000000000 +0200
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2009 <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#define UART1_ENABLED		1
+#define UART2_ENABLED		1
+#define UART3_ENABLED		1
+/* Not available on TX25 */
+#define UART4_ENABLED		0
+#define UART5_ENABLED		0
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/board-tx25.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/board-tx25.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/board-tx25.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/board-tx25.h	2009-06-02 18:02:13.000000000 +0200
@@ -0,0 +1,13 @@
+/*
+ * Copyright 2009 <LW@KARO-electronics.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#define MXC_LL_UART_PADDR	UART1_BASE_ADDR
+#define MXC_LL_UART_VADDR	AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/common.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/common.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/common.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/common.h	2009-06-02 18:02:05.000000000 +0200
@@ -17,6 +17,7 @@ struct clk;
 extern void mx1_map_io(void);
 extern void mx21_map_io(void);
 extern void mx27_map_io(void);
+extern void mx25_map_io(void);
 extern void mx31_map_io(void);
 extern void mx35_map_io(void);
 extern void mxc_init_irq(void);
@@ -24,6 +25,7 @@ extern void mxc_timer_init(struct clk *t
 extern int mx1_clocks_init(unsigned long fref);
 extern int mx21_clocks_init(unsigned long lref, unsigned long fref);
 extern int mx27_clocks_init(unsigned long fref);
+extern int mx25_clocks_init(unsigned long fref);
 extern int mx31_clocks_init(unsigned long fref);
 extern int mx35_clocks_init(void);
 extern int mxc_register_gpios(void);
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/dma.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/dma.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/dma.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/dma.h	2009-06-02 18:02:13.000000000 +0200
@@ -0,0 +1,259 @@
+/*
+ * Copyright 2004-2008 Freescale Semiconductor, 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 __ASM_ARCH_MXC_DMA_H__
+#define __ASM_ARCH_MXC_DMA_H__
+
+#include <mach/sdma.h>
+
+#define MXC_DMA_DYNAMIC_CHANNEL   255
+
+#define MXC_DMA_DONE		  0x0
+#define MXC_DMA_REQUEST_TIMEOUT   0x1
+#define MXC_DMA_TRANSFER_ERROR    0x2
+
+/*! This defines the list of device ID's for DMA */
+typedef enum mxc_dma_device {
+	MXC_DMA_UART1_RX,
+	MXC_DMA_UART1_TX,
+	MXC_DMA_UART2_RX,
+	MXC_DMA_UART2_TX,
+	MXC_DMA_UART3_RX,
+	MXC_DMA_UART3_TX,
+	MXC_DMA_UART4_RX,
+	MXC_DMA_UART4_TX,
+	MXC_DMA_UART5_RX,
+	MXC_DMA_UART5_TX,
+	MXC_DMA_UART6_RX,
+	MXC_DMA_UART6_TX,
+	MXC_DMA_MMC1_WIDTH_1,
+	MXC_DMA_MMC1_WIDTH_4,
+	MXC_DMA_MMC2_WIDTH_1,
+	MXC_DMA_MMC2_WIDTH_4,
+	MXC_DMA_SSI1_8BIT_RX0,
+	MXC_DMA_SSI1_8BIT_TX0,
+	MXC_DMA_SSI1_16BIT_RX0,
+	MXC_DMA_SSI1_16BIT_TX0,
+	MXC_DMA_SSI1_24BIT_RX0,
+	MXC_DMA_SSI1_24BIT_TX0,
+	MXC_DMA_SSI1_8BIT_RX1,
+	MXC_DMA_SSI1_8BIT_TX1,
+	MXC_DMA_SSI1_16BIT_RX1,
+	MXC_DMA_SSI1_16BIT_TX1,
+	MXC_DMA_SSI1_24BIT_RX1,
+	MXC_DMA_SSI1_24BIT_TX1,
+	MXC_DMA_SSI2_8BIT_RX0,
+	MXC_DMA_SSI2_8BIT_TX0,
+	MXC_DMA_SSI2_16BIT_RX0,
+	MXC_DMA_SSI2_16BIT_TX0,
+	MXC_DMA_SSI2_24BIT_RX0,
+	MXC_DMA_SSI2_24BIT_TX0,
+	MXC_DMA_SSI2_8BIT_RX1,
+	MXC_DMA_SSI2_8BIT_TX1,
+	MXC_DMA_SSI2_16BIT_RX1,
+	MXC_DMA_SSI2_16BIT_TX1,
+	MXC_DMA_SSI2_24BIT_RX1,
+	MXC_DMA_SSI2_24BIT_TX1,
+	MXC_DMA_FIR_RX,
+	MXC_DMA_FIR_TX,
+	MXC_DMA_CSPI1_RX,
+	MXC_DMA_CSPI1_TX,
+	MXC_DMA_CSPI2_RX,
+	MXC_DMA_CSPI2_TX,
+	MXC_DMA_CSPI3_RX,
+	MXC_DMA_CSPI3_TX,
+	MXC_DMA_ATA_RX,
+	MXC_DMA_ATA_TX,
+	MXC_DMA_MEMORY,
+	MXC_DMA_FIFO_MEMORY,
+	MXC_DMA_DSP_PACKET_DATA0_RD,
+	MXC_DMA_DSP_PACKET_DATA0_WR,
+	MXC_DMA_DSP_PACKET_DATA1_RD,
+	MXC_DMA_DSP_PACKET_DATA1_WR,
+	MXC_DMA_DSP_LOG0_CHNL,
+	MXC_DMA_DSP_LOG1_CHNL,
+	MXC_DMA_DSP_LOG2_CHNL,
+	MXC_DMA_DSP_LOG3_CHNL,
+	MXC_DMA_CSI_RX,
+	MXC_DMA_SPDIF_16BIT_TX,
+	MXC_DMA_SPDIF_16BIT_RX,
+	MXC_DMA_SPDIF_32BIT_TX,
+	MXC_DMA_SPDIF_32BIT_RX,
+	MXC_DMA_ASRC_A_RX,
+	MXC_DMA_ASRC_A_TX,
+	MXC_DMA_ASRC_B_RX,
+	MXC_DMA_ASRC_B_TX,
+	MXC_DMA_ASRC_C_RX,
+	MXC_DMA_ASRC_C_TX,
+	MXC_DMA_ESAI_16BIT_RX,
+	MXC_DMA_ESAI_16BIT_TX,
+	MXC_DMA_ESAI_24BIT_RX,
+	MXC_DMA_ESAI_24BIT_TX,
+	MXC_DMA_TEST_RAM2D2RAM,
+	MXC_DMA_TEST_RAM2RAM2D,
+	MXC_DMA_TEST_RAM2D2RAM2D,
+	MXC_DMA_TEST_RAM2RAM,
+	MXC_DMA_TEST_HW_CHAINING,
+	MXC_DMA_TEST_SW_CHAINING
+} mxc_dma_device_t;
+
+/*! This defines the prototype of callback funtion registered by the drivers */
+typedef void (*mxc_dma_callback_t) (void *arg, int error_status,
+				    unsigned int count);
+
+/*! This defines the type of DMA transfer requested */
+typedef enum mxc_dma_mode {
+	MXC_DMA_MODE_READ,
+	MXC_DMA_MODE_WRITE,
+} mxc_dma_mode_t;
+
+/*! This defines the DMA channel parameters */
+typedef struct mxc_dma_channel {
+	unsigned int active:1;	/*!< When there has a active tranfer, it is set to 1 */
+	unsigned int lock;	/*!< Defines the channel is allocated or not */
+	int curr_buf;		/*!< Current buffer */
+	mxc_dma_mode_t mode;	/*!< Read or Write */
+	unsigned int channel;	/*!< Channel info */
+	unsigned int dynamic:1;	/*!< Channel not statically allocated when 1 */
+	char *dev_name;		/*!< Device name */
+	void *private;		/*!< Private structure for platform */
+	mxc_dma_callback_t cb_fn;	/*!< The callback function */
+	void *cb_args;		/*!< The argument of callback function */
+} mxc_dma_channel_t;
+
+/*! This structure contains the information about a dma transfer */
+typedef struct mxc_dma_requestbuf {
+	dma_addr_t src_addr;	/*!< source address */
+	dma_addr_t dst_addr;	/*!< destination address */
+	int num_of_bytes;	/*!< the length of this transfer : bytes */
+} mxc_dma_requestbuf_t;
+
+/*!
+ * This function is generally called by the driver at open time.
+ * The DMA driver would do any initialization steps that is required
+ * to get the channel ready for data transfer.
+ *
+ * @param channel_id   a pre-defined id. The peripheral driver would specify
+ *                     the id associated with its peripheral. This would be
+ *                     used by the DMA driver to identify the peripheral
+ *                     requesting DMA and do the necessary setup on the
+ *                     channel associated with the particular peripheral.
+ *                     The DMA driver could use static or dynamic DMA channel
+ *                     allocation.
+ * @param dev_name     module name or device name
+ * @return returns a negative number on error if request for a DMA channel did not
+ *         succeed, returns the channel number to be used on success.
+ */
+extern int mxc_dma_request(mxc_dma_device_t channel_id, char *dev_name);
+
+/*!
+ * This function is generally called by the driver at close time. The DMA
+ * driver would do any cleanup associated with this channel.
+ *
+ * @param channel_num  the channel number returned at request time. This
+ *                     would be used by the DMA driver to identify the calling
+ *                     driver and do the necessary cleanup on the channel
+ *                     associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+extern int mxc_dma_free(int channel_num);
+
+/*!
+ * This function would just configure the buffers specified by the user into
+ * dma channel. The caller must call mxc_dma_enable to start this transfer.
+ *
+ * @param channel_num  the channel number returned at request time. This
+ *                     would be used by the DMA driver to identify the calling
+ *                     driver and do the necessary cleanup on the channel
+ *                     associated with the particular peripheral
+ * @param dma_buf      an array of physical addresses to the user defined
+ *                     buffers. The caller must guarantee the dma_buf is
+ *                     available until the transfer is completed.
+ * @param num_buf      number of buffers in the array
+ * @param mode         specifies whether this is READ or WRITE operation
+ * @return This function returns a negative number on error if buffer could not be
+ *         added with DMA for transfer. On Success, it returns 0
+ */
+extern int mxc_dma_config(int channel_num, mxc_dma_requestbuf_t * dma_buf,
+			  int num_buf, mxc_dma_mode_t mode);
+
+/*!
+ * This function would just configure the scatterlist specified by the
+ * user into dma channel. This is a slight variation of mxc_dma_config(),
+ * it is provided for the convenience of drivers that have a scatterlist
+ * passed into them. It is the calling driver's responsibility to have the
+ * correct physical address filled in the "dma_address" field of the
+ * scatterlist.
+ *
+ * @param channel_num  the channel number returned at request time. This
+ *                     would be used by the DMA driver to identify the calling
+ *                     driver and do the necessary cleanup on the channel
+ *                     associated with the particular peripheral
+ * @param sg           a scatterlist of buffers. The caller must guarantee
+ *                     the dma_buf is available until the transfer is
+ *                     completed.
+ * @param num_buf      number of buffers in the array
+ * @param num_of_bytes total number of bytes to transfer. If set to 0, this
+ *                     would imply to use the length field of the scatterlist
+ *                     for each DMA transfer. Else it would calculate the size
+ *                     for each DMA transfer.
+ * @param mode         specifies whether this is READ or WRITE operation
+ * @return This function returns a negative number on error if buffer could not
+ *         be added with DMA for transfer. On Success, it returns 0
+ */
+extern int mxc_dma_sg_config(int channel_num, struct scatterlist *sg,
+			     int num_buf, int num_of_bytes,
+			     mxc_dma_mode_t mode);
+
+/*!
+ * This function is provided if the driver would like to set/change its
+ * callback function.
+ *
+ * @param channel_num  the channel number returned at request time. This
+ *                     would be used by the DMA driver to identify the calling
+ *                     driver and do the necessary cleanup on the channel
+ *                     associated with the particular peripheral
+ * @param callback     a callback function to provide notification on transfer
+ *                     completion, user could specify NULL if he does not wish
+ *                     to be notified
+ * @param arg          an argument that gets passed in to the callback
+ *                     function, used by the user to do any driver specific
+ *                     operations.
+ * @return this function returns a negative number on error if the callback
+ *         could not be set for the channel or 0 on success
+ */
+extern int mxc_dma_callback_set(int channel_num, mxc_dma_callback_t callback,
+				void *arg);
+
+/*!
+ * This stops the DMA channel and any ongoing transfers. Subsequent use of
+ * mxc_dma_enable() will restart the channel and restart the transfer.
+ *
+ * @param channel_num  the channel number returned at request time. This
+ *                     would be used by the DMA driver to identify the calling
+ *                     driver and do the necessary cleanup on the channel
+ *                     associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+extern int mxc_dma_disable(int channel_num);
+
+/*!
+ * This starts DMA transfer. Or it restarts DMA on a stopped channel
+ * previously stopped with mxc_dma_disable().
+ *
+ * @param channel_num  the channel number returned at request time. This
+ *                     would be used by the DMA driver to identify the calling
+ *                     driver and do the necessary cleanup on the channel
+ *                     associated with the particular peripheral
+ * @return returns a negative number on error or 0 on success
+ */
+extern int mxc_dma_enable(int channel_num);
+
+#endif
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/hardware.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/hardware.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/hardware.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/hardware.h	2009-06-02 18:02:06.000000000 +0200
@@ -29,13 +29,18 @@
 #endif
 
 #ifdef CONFIG_ARCH_MX2
+#ifndef CONFIG_MACH_MX25
 # include <mach/mx2x.h>
+#endif
 # ifdef CONFIG_MACH_MX21
 #  include <mach/mx21.h>
 # endif
 # ifdef CONFIG_MACH_MX27
 #  include <mach/mx27.h>
 # endif
+# ifdef CONFIG_MACH_MX25
+#  include <mach/mx25.h>
+# endif
 #endif
 
 #ifdef CONFIG_ARCH_MX1
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/imxfb.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/imxfb.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/imxfb.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/imxfb.h	2009-06-02 18:02:06.000000000 +0200
@@ -13,7 +13,8 @@
 #define PCR_BPIX_4	(2 << 25)
 #define PCR_BPIX_8	(3 << 25)
 #define PCR_BPIX_12	(4 << 25)
-#define PCR_BPIX_16	(4 << 25)
+#define PCR_BPIX_16	(5 << 25)
+#define PCR_BPIX_18	(6 << 25)
 #define PCR_PIXPOL	(1 << 24)
 #define PCR_FLMPOL	(1 << 23)
 #define PCR_LPPOL	(1 << 22)
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/iomux-mx25.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/iomux-mx25.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/iomux-mx25.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/iomux-mx25.h	2009-07-01 11:50:13.000000000 +0200
@@ -0,0 +1,774 @@
+/*
+ * arch/arm/plat-mxc/include/mach/iomux-mx25.h
+ *
+ * Copyright (C) 2009 by Lothar Wassmann <LW@KARO-electronics.de>
+ *
+ * based on arch/arm/mach-mx25/mx25_pins.h
+ *    Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ * and
+ * arch/arm/plat-mxc/include/mach/iomux-mx35.h
+ *    Copyright (C, NO_PAD_CTRL) 2009 by Jan Weitzel Phytec Messtechnik GmbH <armlinux@phytec.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+#ifndef __IOMUX_MX25_H__
+#define __IOMUX_MX25_H__
+
+#include <mach/iomux-v3.h>
+
+/*
+ *
+ * @brief MX25 I/O Pin List
+ *
+ * @ingroup GPIO_MX25
+ */
+
+#ifndef __ASSEMBLY__
+
+/*
+ * IOMUX/PAD Bit field definitions
+ */
+
+#define MX25_PAD_A10__A10		IOMUX_PAD(A10, A10, 0x000, 0x008, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A10__GPIO_4_0		IOMUX_PAD(A10, GPIO_4_0, 0x000, 0x008, 0x05, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A13__A13		IOMUX_PAD(A13, A13, 0x22C, 0x00c, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A13__GPIO_4_1		IOMUX_PAD(A13, GPIO_4_1, 0x22C, 0x00c, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A14__A14		IOMUX_PAD(A14, A14, 0x230, 0x010, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A14__GPIO_2_0		IOMUX_PAD(A14, GPIO_2_0, 0x230, 0x010, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A15__A15		IOMUX_PAD(A15, A15, 0x234, 0x014, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A15__GPIO_2_1		IOMUX_PAD(A15, GPIO_2_1, 0x234, 0x014, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A16__A16		IOMUX_PAD(A16, A16, 0x000, 0x018, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A16__GPIO_2_2		IOMUX_PAD(A16, GPIO_2_2, 0x000, 0x018, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_A17__A17		IOMUX_PAD(A17, A17, 0x238, 0x01c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A17__GPIO_2_3		IOMUX_PAD(A17, GPIO_2_3, 0x238, 0x01c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A18__A18		IOMUX_PAD(A18, A18, 0x23c, 0x020, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A18__GPIO_2_4		IOMUX_PAD(A18, GPIO_2_4, 0x23c, 0x020, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A18__FEC_COL		IOMUX_PAD(A18, FEC_COL, 0x23c, 0x020, 0x17, 0x504, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_A19__A19		IOMUX_PAD(A19, A19, 0x240, 0x024, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A19__FEC_RX_ER		IOMUX_PAD(A19, FEC_RX_ER, 0x240, 0x024, 0x17, 0x518, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_A19__GPIO_2_5		IOMUX_PAD(A19, GPIO_2_5, 0x240, 0x024, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A20__A20		IOMUX_PAD(A20, A20, 0x244, 0x028, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A20__GPIO_2_6		IOMUX_PAD(A20, GPIO_2_6, 0x244, 0x028, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A20__FEC_RDATA2	IOMUX_PAD(A20, FEC_RDATA2, 0x244, 0x028, 0x17, 0x50c, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_A21__A21		IOMUX_PAD(A21, A21, 0x248, 0x02c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A21__GPIO_2_7		IOMUX_PAD(A21, GPIO_2_7, 0x248, 0x02c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A21__FEC_RDATA3	IOMUX_PAD(A21, FEC_RDATA3, 0x248, 0x02c, 0x17, 0x510, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_A22__A22		IOMUX_PAD(A22, A22, 0x000, 0x030, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A22__GPIO_2_8		IOMUX_PAD(A22, GPIO_2_8, 0x000, 0x030, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A23__A23		IOMUX_PAD(A23, A23, 0x24c, 0x034, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A23__GPIO_2_9		IOMUX_PAD(A23, GPIO_2_9, 0x24c, 0x034, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A24__A24		IOMUX_PAD(A24, A24, 0x250, 0x038, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A24__GPIO_2_10		IOMUX_PAD(A24, GPIO_2_10, 0x250, 0x038, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A24__FEC_RX_CLK	IOMUX_PAD(A24, FEC_RX_CLK, 0x250, 0x038, 0x17, 0x514, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_A25__A25		IOMUX_PAD(A25, A25, 0x254, 0x03c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A25__GPIO_2_11		IOMUX_PAD(A25, GPIO_2_11, 0x254, 0x03c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_A25__FEC_CRS		IOMUX_PAD(A25, FEC_CRS, 0x254, 0x03c, 0x17, 0x508, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_EB0__EB0		IOMUX_PAD(EB0, EB0, 0x258, 0x040, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_EB0__AUD4_TXD		IOMUX_PAD(EB0, AUD4_TXD, 0x258, 0x040, 0x14, 0x464, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_EB0__GPIO_2_12		IOMUX_PAD(EB0, GPIO_2_12, 0x258, 0x040, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_EB1__EB1		IOMUX_PAD(EB1, EB1, 0x25c, 0x044, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_EB1__AUD4_RXD		IOMUX_PAD(EB1, AUD4_RXD, 0x25c, 0x044, 0x14, 0x460, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_EB1__GPIO_2_13		IOMUX_PAD(EB1, GPIO_2_13, 0x25c, 0x044, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_OE__OE			IOMUX_PAD(OE, OE, 0x260, 0x048, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_OE__AUD4_TXC		IOMUX_PAD(OE, AUD4_TXC, 0x260, 0x048, 0x14, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_OE__GPIO_2_14		IOMUX_PAD(OE, GPIO_2_14, 0x260, 0x048, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CS0__CS0		IOMUX_PAD(CS0, CS0, 0x000, 0x04c, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS0__GPIO_4_2		IOMUX_PAD(CS0, GPIO_4_2, 0x000, 0x04c, 0x05, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS1__CS1		IOMUX_PAD(CS1, CS1, 0x000, 0x050, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS1__GPIO_4_3		IOMUX_PAD(CS1, GPIO_4_3, 0x000, 0x050, 0x05, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CS4__CS4		IOMUX_PAD(CS4, CS4, 0x264, 0x054, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CS4__UART5_CTS		IOMUX_PAD(CS4, UART5_CTS, 0x264, 0x054, 0x13, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CS4__GPIO_3_20		IOMUX_PAD(CS4, GPIO_3_20, 0x264, 0x054, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CS5__CS5		IOMUX_PAD(CS5, CS5, 0x268, 0x058, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CS5__UART5_RTS		IOMUX_PAD(CS5, UART5_RTS, 0x268, 0x058, 0x13, 0x574, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CS5__GPIO_3_21		IOMUX_PAD(CS5, GPIO_3_21, 0x268, 0x058, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_NF_CE0__NF_CE0		IOMUX_PAD(NF_CE0, NF_CE0, 0x26c, 0x05c, 0x10, 0, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_NF_CE0__GPIO_3_22	IOMUX_PAD(NF_CE0, GPIO_3_22, 0x26c, 0x05c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_ECB__ECB		IOMUX_PAD(ECB, ECB, 0x270, 0x060, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_ECB__UART5_TXD_MUX	IOMUX_PAD(ECB, UART5_TXD_MUX, 0x270, 0x060, 0x13, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_ECB__GPIO_3_23		IOMUX_PAD(ECB, GPIO_3_23, 0x270, 0x060, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LBA__LBA		IOMUX_PAD(LBA, LBA, 0x274, 0x064, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LBA__UART5_RXD_MUX	IOMUX_PAD(LBA, UART5_RXD_MUX, 0x274, 0x064, 0x13, 0x578, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LBA__GPIO_3_24		IOMUX_PAD(LBA, GPIO_3_24, 0x274, 0x064, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_BCLK__BCLK		IOMUX_PAD(BCLK, BCLK, 0x000, 0x068, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_BCLK__GPIO_4_4		IOMUX_PAD(BCLK, GPIO_4_4, 0x000, 0x068, 0x05, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_RW__RW			IOMUX_PAD(RW, RW, 0x278, 0x06c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_RW__AUD4_TXFS		IOMUX_PAD(RW, AUD4_TXFS, 0x278, 0x06c, 0x14, 0x474, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_RW__GPIO_3_25		IOMUX_PAD(RW, GPIO_3_25, 0x278, 0x06c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_NFWE_B__NFWE_B		IOMUX_PAD(NFWE_B, NFWE_B, 0x000, 0x070, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFWE_B__GPIO_3_26	IOMUX_PAD(NFWE_B, GPIO_3_26, 0x000, 0x070, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFRE_B__NFRE_B		IOMUX_PAD(NFRE_B, NFRE_B, 0x000, 0x074, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFRE_B__GPIO_3_27	IOMUX_PAD(NFRE_B, GPIO_3_27, 0x000, 0x074, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFALE__NFALE		IOMUX_PAD(NFALE, NFALE, 0x000, 0x078, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFALE__GPIO_3_28	IOMUX_PAD(NFALE, GPIO_3_28, 0x000, 0x078, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFCLE__NFCLE		IOMUX_PAD(NFCLE, NFCLE, 0x000, 0x07c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFCLE__GPIO_3_29	IOMUX_PAD(NFCLE, GPIO_3_29, 0x000, 0x07c, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFWP_B__NFWP_B		IOMUX_PAD(NFWP_B, NFWP_B, 0x000, 0x080, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFWP_B__GPIO_3_30	IOMUX_PAD(NFWP_B, GPIO_3_30, 0x000, 0x080, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_NFRB__NFRB		IOMUX_PAD(NFRB, NFRB, 0x27c, 0x084, 0x10, 0, 0, PAD_CTL_PULL_KEEPER)
+#define MX25_PAD_NFRB__GPIO_3_31	IOMUX_PAD(NFRB, GPIO_3_31, 0x27c, 0x084, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D15__D15		IOMUX_PAD(D15, D15, 0x280, 0x088, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D15__LD16		IOMUX_PAD(D15, LD16, 0x280, 0x088, 0x01, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D15__GPIO_4_5		IOMUX_PAD(D15, GPIO_4_5, 0x280, 0x088, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D14__D14		IOMUX_PAD(D14, D14, 0x284, 0x08c, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D14__LD17		IOMUX_PAD(D14, LD17, 0x284, 0x08c, 0x01, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D14__GPIO_4_6		IOMUX_PAD(D14, GPIO_4_6, 0x284, 0x08c, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D13__D13		IOMUX_PAD(D13, D13, 0x288, 0x090, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D13__LD18		IOMUX_PAD(D13, LD18, 0x288, 0x090, 0x01, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D13__GPIO_4_7		IOMUX_PAD(D13, GPIO_4_7, 0x288, 0x090, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D12__D12		IOMUX_PAD(D12, D12, 0x28c, 0x094, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D12__GPIO_4_8		IOMUX_PAD(D12, GPIO_4_8, 0x28c, 0x094, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D11__D11		IOMUX_PAD(D11, D11, 0x290, 0x098, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D11__GPIO_4_9		IOMUX_PAD(D11, GPIO_4_9, 0x290, 0x098, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D10__D10		IOMUX_PAD(D10, D10, 0x294, 0x09c, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D10__GPIO_4_10		IOMUX_PAD(D10, GPIO_4_10, 0x294, 0x09c, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D10__USBOTG_OC		IOMUX_PAD(D10, USBOTG_OC, 0x294, 0x09c, 0x06, 0x57c, 0, PAD_CTL_PULL_UP_100K)
+#define MX25_PAD_D9__D9			IOMUX_PAD(D9, D9, 0x298, 0x0a0, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D9__GPIO_4_11		IOMUX_PAD(D9, GPIO_4_11, 0x298, 0x0a0, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D9__USBH2_PWR		IOMUX_PAD(D9, USBH2_PWR, 0x298, 0x0a0, 0x06, 0, 0, PAD_CTL_PULL_KEEPER)
+#define MX25_PAD_D8__D8			IOMUX_PAD(D8, D8, 0x29c, 0x0a4, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D8__GPIO_4_12		IOMUX_PAD(D8, GPIO_4_12, 0x29c, 0x0a4, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D8__USBH2_OC		IOMUX_PAD(D8, USBH2_OC, 0x29c, 0x0a4, 0x06, 0x580, 0, PAD_CTL_PULL_UP_100K)
+#define MX25_PAD_D7__D7			IOMUX_PAD(D7, D7, 0x2a0, 0x0a8, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D7__GPIO_4_13		IOMUX_PAD(D7, GPIO_4_13, 0x2a0, 0x0a8, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D6__D6			IOMUX_PAD(D6, D6, 0x2a4, 0x0ac, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D6__GPIO_4_14		IOMUX_PAD(D6, GPIO_4_14, 0x2a4, 0x0ac, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D5__D5			IOMUX_PAD(D5, D5, 0x2a8, 0x0b0, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D5__GPIO_4_15		IOMUX_PAD(D5, GPIO_4_15, 0x2a8, 0x0b0, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D4__D4			IOMUX_PAD(D4, D4, 0x2ac, 0x0b4, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D4__GPIO_4_16		IOMUX_PAD(D4, GPIO_4_16, 0x2ac, 0x0b4, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D3__D3			IOMUX_PAD(D3, D3, 0x2b0, 0x0b8, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D3__GPIO_4_17		IOMUX_PAD(D3, GPIO_4_17, 0x2b0, 0x0b8, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D2__D2			IOMUX_PAD(D2, D2, 0x2b4, 0x0bc, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D2__GPIO_4_18		IOMUX_PAD(D2, GPIO_4_18, 0x2b4, 0x0bc, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D1__D1			IOMUX_PAD(D1, D1, 0x2b8, 0x0c0, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D1__GPIO_4_19		IOMUX_PAD(D1, GPIO_4_19, 0x2b8, 0x0c0, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D0__D0			IOMUX_PAD(D0, D0, 0x2bc, 0x0c4, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_D0__GPIO_4_20		IOMUX_PAD(D0, GPIO_4_20, 0x2bc, 0x0c4, 0x05, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD0__LD0		IOMUX_PAD(LD0, LD0, 0x2c0, 0x0c8, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD0__CSI_D0		IOMUX_PAD(LD0, CSI_D0, 0x2c0, 0x0c8, 0x12, 0x488, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD0__GPIO_2_15		IOMUX_PAD(LD0, GPIO_2_15, 0x2c0, 0x0c8, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD1__LD1		IOMUX_PAD(LD1, LD1, 0x2c4, 0x0cc, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD1__CSI_D1		IOMUX_PAD(LD1, CSI_D1, 0x2c4, 0x0cc, 0x12, 0x48c, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD1__GPIO_2_16		IOMUX_PAD(LD1, GPIO_2_16, 0x2c4, 0x0cc, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD2__LD2		IOMUX_PAD(LD2, LD2, 0x2c8, 0x0d0, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD2__GPIO_2_17		IOMUX_PAD(LD2, GPIO_2_17, 0x2c8, 0x0d0, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD3__LD3		IOMUX_PAD(LD3, LD3, 0x2cc, 0x0d4, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD3__GPIO_2_18		IOMUX_PAD(LD3, GPIO_2_18, 0x2cc, 0x0d4, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD4__LD4		IOMUX_PAD(LD4, LD4, 0x2d0, 0x0d8, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD4__GPIO_2_19		IOMUX_PAD(LD4, GPIO_2_19, 0x2d0, 0x0d8, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD5__LD5		IOMUX_PAD(LD5, LD5, 0x2d4, 0x0dc, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD5__GPIO_1_19		IOMUX_PAD(LD5, GPIO_1_19, 0x2d4, 0x0dc, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD6__LD6		IOMUX_PAD(LD6, LD6, 0x2d8, 0x0e0, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD6__GPIO_1_20		IOMUX_PAD(LD6, GPIO_1_20, 0x2d8, 0x0e0, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD7__LD7		IOMUX_PAD(LD7, LD7, 0x2dc, 0x0e4, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD7__GPIO_1_21		IOMUX_PAD(LD7, GPIO_1_21, 0x2dc, 0x0e4, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD8__LD8		IOMUX_PAD(LD8, LD8, 0x2e0, 0x0e8, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD8__FEC_TX_ERR	IOMUX_PAD(LD8, FEC_TX_ERR, 0x2e0, 0x0e8, 0x15, 0, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_LD9__LD9		IOMUX_PAD(LD9, LD9, 0x2e4, 0x0ec, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD9__FEC_COL		IOMUX_PAD(LD9, FEC_COL, 0x2e4, 0x0ec, 0x15, 0x504, 1, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_LD10__LD10		IOMUX_PAD(LD10, LD10, 0x2e8, 0x0f0, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD10__FEC_RX_ER	IOMUX_PAD(LD10, FEC_RX_ER, 0x2e8, 0x0f0, 0x15, 0x518, 1, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_LD11__LD11		IOMUX_PAD(LD11, LD11, 0x2ec, 0x0f4, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD11__FEC_RDATA2	IOMUX_PAD(LD11, FEC_RDATA2, 0x2ec, 0x0f4, 0x15, 0x50c, 1, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_LD12__LD12		IOMUX_PAD(LD12, LD12, 0x2f0, 0x0f8, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD12__FEC_RDATA3	IOMUX_PAD(LD12, FEC_RDATA3, 0x2f0, 0x0f8, 0x15, 0x510, 1, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_LD13__LD13		IOMUX_PAD(LD13, LD13, 0x2f4, 0x0fc, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD13__FEC_TDATA2	IOMUX_PAD(LD13, FEC_TDATA2, 0x2f4, 0x0fc, 0x15, 0, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_LD14__LD14		IOMUX_PAD(LD14, LD14, 0x2f8, 0x100, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD14__FEC_TDATA3	IOMUX_PAD(LD14, FEC_TDATA3, 0x2f8, 0x100, 0x15, 0, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_LD15__LD15		IOMUX_PAD(LD15, LD15, 0x2fc, 0x104, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LD15__FEC_RX_CLK	IOMUX_PAD(LD15, FEC_RX_CLK, 0x2fc, 0x104, 0x15, 0x514, 1, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_HSYNC__HSYNC		IOMUX_PAD(HSYNC, HSYNC, 0x300, 0x108, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_HSYNC__GPIO_1_22	IOMUX_PAD(HSYNC, GPIO_1_22, 0x300, 0x108, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_VSYNC__VSYNC		IOMUX_PAD(VSYNC, VSYNC, 0x304, 0x10c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_VSYNC__GPIO_1_23	IOMUX_PAD(VSYNC, GPIO_1_23, 0x304, 0x10c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LSCLK__LSCLK		IOMUX_PAD(LSCLK, LSCLK, 0x308, 0x110, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_LSCLK__GPIO_1_24	IOMUX_PAD(LSCLK, GPIO_1_24, 0x308, 0x110, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_OE_ACD__OE_ACD		IOMUX_PAD(OE_ACD, OE_ACD, 0x30c, 0x114, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_OE_ACD__GPIO_1_25	IOMUX_PAD(OE_ACD, GPIO_1_25, 0x30c, 0x114, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CONTRAST__CONTRAST	IOMUX_PAD(CONTRAST, CONTRAST, 0x310, 0x118, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CONTRAST__FEC_CRS	IOMUX_PAD(CONTRAST, FEC_CRS, 0x310, 0x118, 0x15, 0x508, 1, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_PWM__PWM		IOMUX_PAD(PWM, PWM, 0x314, 0x11c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_PWM__GPIO_1_26		IOMUX_PAD(PWM, GPIO_1_26, 0x314, 0x11c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_PWM__USBH2_OC		IOMUX_PAD(PWM, USBH2_OC, 0x314, 0x11c, 0x16, 0x580, 1, PAD_CTL_PULL_UP_100K)
+#define MX25_PAD_CSI_D2__CSI_D2		IOMUX_PAD(CSI_D2, CSI_D2, 0x318, 0x120, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D2__UART5_RXD_MUX	IOMUX_PAD(CSI_D2, UART5_RXD_MUX, 0x318, 0x120, 0x11, 0x578, 1, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D2__GPIO_1_27	IOMUX_PAD(CSI_D2, GPIO_1_27, 0x318, 0x120, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D3__CSI_D3		IOMUX_PAD(CSI_D3, CSI_D3, 0x31c, 0x124, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D3__GPIO_1_28	IOMUX_PAD(CSI_D3, GPIO_1_28, 0x31c, 0x124, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D4__CSI_D4		IOMUX_PAD(CSI_D4, CSI_D4, 0x320, 0x128, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D4__UART5_RTS	IOMUX_PAD(CSI_D4, UART5_RTS, 0x320, 0x128, 0x11, 0x574, 1, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D4__GPIO_1_29	IOMUX_PAD(CSI_D4, GPIO_1_29, 0x320, 0x128, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D5__CSI_D5		IOMUX_PAD(CSI_D5, CSI_D5, 0x324, 0x12c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D5__GPIO_1_30	IOMUX_PAD(CSI_D5, GPIO_1_30, 0x324, 0x12c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D6__CSI_D6		IOMUX_PAD(CSI_D6, CSI_D6, 0x328, 0x130, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D6__GPIO_1_31	IOMUX_PAD(CSI_D6, GPIO_1_31, 0x328, 0x130, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D7__CSI_D7		IOMUX_PAD(CSI_D7, CSI_D7, 0x32c, 0x134, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D7__GPIO_1_6	IOMUX_PAD(CSI_D7, GPIO_1_6, 0x32c, 0x134, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D8__CSI_D8		IOMUX_PAD(CSI_D8, CSI_D8, 0x330, 0x138, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D8__GPIO_1_7	IOMUX_PAD(CSI_D8, GPIO_1_7, 0x330, 0x138, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D9__CSI_D9		IOMUX_PAD(CSI_D9, CSI_D9, 0x334, 0x13c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_D9__GPIO_4_21	IOMUX_PAD(CSI_D9, GPIO_4_21, 0x334, 0x13c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_MCLK__CSI_MCLK	IOMUX_PAD(CSI_MCLK, CSI_MCLK, 0x338, 0x140, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_MCLK__GPIO_1_8	IOMUX_PAD(CSI_MCLK, GPIO_1_8, 0x338, 0x140, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_VSYNC__CSI_VSYNC	IOMUX_PAD(CSI_VSYNC, CSI_VSYNC, 0x33c, 0x144, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_VSYNC__GPIO_1_9	IOMUX_PAD(CSI_VSYNC, GPIO_1_9, 0x33c, 0x144, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_HSYNC__CSI_HSYNC	IOMUX_PAD(CSI_HSYNC, CSI_HSYNC, 0x340, 0x148, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_HSYNC__GPIO_1_10	IOMUX_PAD(CSI_HSYNC, GPIO_1_10, 0x340, 0x148, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_PIXCLK__CSI_PIXCLK	IOMUX_PAD(CSI_PIXCLK, CSI_PIXCLK, 0x344, 0x14c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSI_PIXCLK__GPIO_1_11	IOMUX_PAD(CSI_PIXCLK, GPIO_1_11, 0x344, 0x14c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_I2C1_CLK__I2C1_CLK	IOMUX_PAD(I2C1_CLK, I2C1_CLK, 0x348, 0x150, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_I2C1_CLK__GPIO_1_12	IOMUX_PAD(I2C1_CLK, GPIO_1_12, 0x348, 0x150, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_I2C1_DAT__I2C1_DAT	IOMUX_PAD(I2C1_DAT, I2C1_DAT, 0x34c, 0x154, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_I2C1_DAT__GPIO_1_13	IOMUX_PAD(I2C1_DAT, GPIO_1_13, 0x34c, 0x154, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_MOSI__CSPI1_MOSI	IOMUX_PAD(CSPI1_MOSI, CSPI1_MOSI, 0x350, 0x158, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_MOSI__GPIO_1_14	IOMUX_PAD(CSPI1_MOSI, GPIO_1_14, 0x350, 0x158, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_MISO__CSPI1_MISO	IOMUX_PAD(CSPI1_MISO, CSPI1_MISO, 0x354, 0x15c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_MISO__GPIO_1_15	IOMUX_PAD(CSPI1_MISO, GPIO_1_15, 0x354, 0x15c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_SS0__CSPI1_SS0	IOMUX_PAD(CSPI1_SS0, CSPI1_SS0, 0x358, 0x160, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_SS0__GPIO_1_16	IOMUX_PAD(CSPI1_SS0, GPIO_1_16, 0x358, 0x160, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_SS1__CSPI1_SS1	IOMUX_PAD(CSPI1_SS1, CSPI1_SS1, 0x35c, 0x164, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_SS1__GPIO_1_17	IOMUX_PAD(CSPI1_SS1, GPIO_1_17, 0x35c, 0x164, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_SCLK__CSPI1_SCLK	IOMUX_PAD(CSPI1_SCLK, CSPI1_SCLK, 0x360, 0x168, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_SCLK__GPIO_1_18	IOMUX_PAD(CSPI1_SCLK, GPIO_1_18, 0x360, 0x168, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CSPI1_RDY__CSPI1_RDY	IOMUX_PAD(CSPI1_RDY, CSPI1_RDY, 0x364, 0x16c, 0x10, 0, 0, PAD_CTL_PULL_KEEPER)
+#define MX25_PAD_CSPI1_RDY__GPIO_2_22	IOMUX_PAD(CSPI1_RDY, GPIO_2_22, 0x364, 0x16c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART1_RXD__UART1_RXD	IOMUX_PAD(UART1_RXD, UART1_RXD, 0x368, 0x170, 0x10, 0, 0, PAD_CTL_PULL_DOWN_100K)
+#define MX25_PAD_UART1_RXD__GPIO_4_22	IOMUX_PAD(UART1_RXD, GPIO_4_22, 0x368, 0x170, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(UART1_TXD, UART1_TXD, 0x36c, 0x174, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART1_TXD__GPIO_4_23	IOMUX_PAD(UART1_TXD, GPIO_4_23, 0x36c, 0x174, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART1_RTS__UART1_RTS	IOMUX_PAD(UART1_RTS, UART1_RTS, 0x370, 0x178, 0x10, 0, 0, PAD_CTL_PULL_UP_100K)
+#define MX25_PAD_UART1_RTS__CSI_D0	IOMUX_PAD(UART1_RTS, CSI_D0, 0x370, 0x178, 0x11, 0x488, 1, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART1_RTS__GPIO_4_24	IOMUX_PAD(UART1_RTS, GPIO_4_24, 0x370, 0x178, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(UART1_CTS, UART1_CTS, 0x374, 0x17c, 0x10, 0, 0, PAD_CTL_PULL_UP_100K)
+#define MX25_PAD_UART1_CTS__CSI_D1	IOMUX_PAD(UART1_CTS, CSI_D1, 0x374, 0x17c, 0x11, 0x48c, 1, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART1_CTS__GPIO_4_25	IOMUX_PAD(UART1_CTS, GPIO_4_25, 0x374, 0x17c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART2_RXD__UART2_RXD	IOMUX_PAD(UART2_RXD, UART2_RXD, 0x378, 0x180, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART2_RXD__GPIO_4_26	IOMUX_PAD(UART2_RXD, GPIO_4_26, 0x378, 0x180, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(UART2_TXD, UART2_TXD, 0x37c, 0x184, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART2_TXD__GPIO_4_27	IOMUX_PAD(UART2_TXD, GPIO_4_27, 0x37c, 0x184, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART2_RTS__UART2_RTS	IOMUX_PAD(UART2_RTS, UART2_RTS, 0x380, 0x188, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART2_RTS__FEC_COL	IOMUX_PAD(UART2_RTS, FEC_COL, 0x380, 0x188, 0x12, 0x504, 2, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_UART2_RTS__GPIO_4_28	IOMUX_PAD(UART2_RTS, GPIO_4_28, 0x380, 0x188, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART2_CTS__FEC_RX_ER	IOMUX_PAD(UART2_CTS, FEC_RX_ER, 0x384, 0x18c, 0x12, 0x518, 2, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_UART2_CTS__UART2_CTS	IOMUX_PAD(UART2_CTS, UART2_CTS, 0x384, 0x18c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_UART2_CTS__GPIO_4_29	IOMUX_PAD(UART2_CTS, GPIO_4_29, 0x384, 0x18c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_SD1_CMD__SD1_CMD	IOMUX_PAD(SD1_CMD, SD1_CMD, 0x388, 0x190, 0x10, 0, 0, PAD_CTL_PULL_UP_47K | PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_SD1_CMD__FEC_RDATA2	IOMUX_PAD(SD1_CMD, FEC_RDATA2, 0x388, 0x190, 0x12, 0x50c, 2, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_SD1_CMD__GPIO_2_23	IOMUX_PAD(SD1_CMD, GPIO_2_23, 0x388, 0x190, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_SD1_CLK__SD1_CLK	IOMUX_PAD(SD1_CLK, SD1_CLK, 0x38c, 0x194, 0x10, 0, 0, PAD_CTL_PULL_UP_47K | PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_SD1_CLK__FEC_RDATA3	IOMUX_PAD(SD1_CLK, FEC_RDATA3, 0x38c, 0x194, 0x12, 0x510, 2, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_SD1_CLK__GPIO_2_24	IOMUX_PAD(SD1_CLK, GPIO_2_24, 0x38c, 0x194, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_SD1_DATA0__SD1_DATA0	IOMUX_PAD(SD1_DATA0, SD1_DATA0, 0x390, 0x198, 0x10, 0, 0, PAD_CTL_PULL_UP_47K | PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_SD1_DATA0__GPIO_2_25	IOMUX_PAD(SD1_DATA0, GPIO_2_25, 0x390, 0x198, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_SD1_DATA1__SD1_DATA1	IOMUX_PAD(SD1_DATA1, SD1_DATA1, 0x394, 0x19c, 0x10, 0, 0, PAD_CTL_PULL_UP_47K | PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_SD1_DATA1__AUD7_RXD	IOMUX_PAD(SD1_DATA1, AUD7_RXD, 0x394, 0x19c, 0x13, 0x478, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_SD1_DATA1__GPIO_2_26	IOMUX_PAD(SD1_DATA1, GPIO_2_26, 0x394, 0x19c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_SD1_DATA2__SD1_DATA2	IOMUX_PAD(SD1_DATA2, SD1_DATA2, 0x398, 0x1a0, 0x10, 0, 0, PAD_CTL_PULL_UP_47K | PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_SD1_DATA2__FEC_RX_CLK	IOMUX_PAD(SD1_DATA2, FEC_RX_CLK, 0x398, 0x1a0, 0x15, 0x514, 2, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_SD1_DATA2__GPIO_2_27	IOMUX_PAD(SD1_DATA2, GPIO_2_27, 0x398, 0x1a0, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_SD1_DATA3__SD1_DATA3	IOMUX_PAD(SD1_DATA3, SD1_DATA3, 0x39c, 0x1a4, 0x10, 0, 0, PAD_CTL_PULL_UP_47K | PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_SD1_DATA3__FEC_CRS	IOMUX_PAD(SD1_DATA3, FEC_CRS, 0x39c, 0x1a4, 0x10, 0x508, 2, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_SD1_DATA3__GPIO_2_28	IOMUX_PAD(SD1_DATA3, GPIO_2_28, 0x39c, 0x1a4, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_KPP_ROW0__KPP_ROW0	IOMUX_PAD(KPP_ROW0, KPP_ROW0, 0x3a0, 0x1a8, 0x10, 0, 0, PAD_CTL_PULL_KEEPER)
+#define MX25_PAD_KPP_ROW0__GPIO_2_29	IOMUX_PAD(KPP_ROW0, GPIO_2_29, 0x3a0, 0x1a8, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_KPP_ROW1__KPP_ROW1	IOMUX_PAD(KPP_ROW1, KPP_ROW1, 0x3a4, 0x1ac, 0x10, 0, 0, PAD_CTL_PULL_KEEPER)
+#define MX25_PAD_KPP_ROW1__GPIO_2_30	IOMUX_PAD(KPP_ROW1, GPIO_2_30, 0x3a4, 0x1ac, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_KPP_ROW2__KPP_ROW2	IOMUX_PAD(KPP_ROW2, KPP_ROW2, 0x3a8, 0x1b0, 0x10, 0, 0, PAD_CTL_PULL_KEEPER)
+#define MX25_PAD_KPP_ROW2__CSI_D0	IOMUX_PAD(KPP_ROW2, CSI_D0, 0x3a8, 0x1b0, 0x13, 0x488, 2, 0 | NO_PAD_CTRL)
+#define MX25_PAD_KPP_ROW2__GPIO_2_31	IOMUX_PAD(KPP_ROW2, GPIO_2_31, 0x3a8, 0x1b0, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_KPP_ROW3__KPP_ROW3	IOMUX_PAD(KPP_ROW3, KPP_ROW3, 0x3ac, 0x1b4, 0x10, 0, 0, PAD_CTL_PULL_KEEPER)
+#define MX25_PAD_KPP_ROW3__CSI_LD1	IOMUX_PAD(KPP_ROW3, CSI_LD1, 0x3ac, 0x1b4, 0x13, 0x48c, 2, 0 | NO_PAD_CTRL)
+#define MX25_PAD_KPP_ROW3__GPIO_3_0	IOMUX_PAD(KPP_ROW3, GPIO_3_0, 0x3ac, 0x1b4, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_KPP_COL0__KPP_COL0	IOMUX_PAD(KPP_COL0, KPP_COL0, 0x3b0, 0x1b8, 0x10, 0, 0, PAD_CTL_PULL_KEEPER | PAD_CTL_OUTPUT_OPEN_DRAIN)
+#define MX25_PAD_KPP_COL0__GPIO_3_1	IOMUX_PAD(KPP_COL0, GPIO_3_1, 0x3b0, 0x1b8, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_KPP_COL1__KPP_COL1	IOMUX_PAD(KPP_COL1, KPP_COL1, 0x3b4, 0x1bc, 0x10, 0, 0, PAD_CTL_PULL_KEEPER | PAD_CTL_OUTPUT_OPEN_DRAIN)
+#define MX25_PAD_KPP_COL1__GPIO_3_2	IOMUX_PAD(KPP_COL1, GPIO_3_2, 0x3b4, 0x1bc, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_KPP_COL2__KPP_COL2	IOMUX_PAD(KPP_COL2, KPP_COL2, 0x3b8, 0x1c0, 0x10, 0, 0, PAD_CTL_PULL_KEEPER | PAD_CTL_OUTPUT_OPEN_DRAIN)
+#define MX25_PAD_KPP_COL2__GPIO_3_3	IOMUX_PAD(KPP_COL2, GPIO_3_3, 0x3b8, 0x1c0, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_KPP_COL3__KPP_COL3	IOMUX_PAD(KPP_COL3, KPP_COL3, 0x3bc, 0x1c4, 0x10, 0, 0, PAD_CTL_PULL_KEEPER | PAD_CTL_OUTPUT_OPEN_DRAIN)
+#define MX25_PAD_KPP_COL3__GPIO_3_4	IOMUX_PAD(KPP_COL3, GPIO_3_4, 0x3bc, 0x1c4, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_MDC__FEC_MDC	IOMUX_PAD(FEC_MDC, FEC_MDC, 0x3c0, 0x1c8, 0x10, 0, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_FEC_MDC__AUD4_TXD	IOMUX_PAD(FEC_MDC, AUD4_TXD, 0x3c0, 0x1c8, 0x12, 0x464, 1, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_MDC__GPIO_3_5	IOMUX_PAD(FEC_MDC, GPIO_3_5, 0x3c0, 0x1c8, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_MDIO__FEC_MDIO	IOMUX_PAD(FEC_MDIO, FEC_MDIO, 0x3c4, 0x1cc, 0x10, 0, 0, PAD_CTL_HYSTERESIS | PAD_CTL_PULL_UP_22K | PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_FEC_MDIO__AUD4_RXD	IOMUX_PAD(FEC_MDIO, AUD4_RXD, 0x3c4, 0x1cc, 0x12, 0x460, 1, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_MDIO__GPIO_3_6	IOMUX_PAD(FEC_MDIO, GPIO_3_6, 0x3c4, 0x1cc, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_TDATA0__FEC_TDATA0	IOMUX_PAD(FEC_TDATA0, FEC_TDATA0, 0x3c8, 0x1d0, 0x10, 0, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_FEC_TDATA0__GPIO_3_7	IOMUX_PAD(FEC_TDATA0, GPIO_3_7, 0x3c8, 0x1d0, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_TDATA1__FEC_TDATA1	IOMUX_PAD(FEC_TDATA1, FEC_TDATA1, 0x3cc, 0x1d4, 0x10, 0, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_FEC_TDATA1__AUD4_TXFS	IOMUX_PAD(FEC_TDATA1, AUD4_TXFS, 0x3cc, 0x1d4, 0x12, 0x474, 1, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_TDATA1__GPIO_3_8	IOMUX_PAD(FEC_TDATA1, GPIO_3_8, 0x3cc, 0x1d4, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_TX_EN__FEC_TX_EN	IOMUX_PAD(FEC_TX_EN, FEC_TX_EN, 0x3d0, 0x1d8, 0x10, 0, 0, PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_FEC_TX_EN__GPIO_3_9   	IOMUX_PAD(FEC_TX_EN, GPIO_3_9   , 0x3d0, 0x1d8, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_RDATA0__FEC_RDATA0	IOMUX_PAD(FEC_RDATA0, FEC_RDATA0, 0x3d4, 0x1dc, 0x10, 0, 0, PAD_CTL_PULL_DOWN_100K | PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_FEC_RDATA0__GPIO_3_10	IOMUX_PAD(FEC_RDATA0, GPIO_3_10, 0x3d4, 0x1dc, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_RDATA1__FEC_RDATA1	IOMUX_PAD(FEC_RDATA1, FEC_RDATA1, 0x3d8, 0x1e0, 0x10, 0, 0, PAD_CTL_PULL_DOWN_100K | PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_FEC_RDATA1__GPIO_3_11	IOMUX_PAD(FEC_RDATA1, GPIO_3_11, 0x3d8, 0x1e0, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_RX_DV__FEC_RX_DV	IOMUX_PAD(FEC_RX_DV, FEC_RX_DV, 0x3dc, 0x1e4, 0x10, 0, 0, PAD_CTL_PULL_DOWN_100K | PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_FEC_RX_DV__CAN2_RX	IOMUX_PAD(FEC_RX_DV, CAN2_RX, 0x3dc, 0x1e4, 0x14, 0x484, 0, PAD_CTL_PULL_UP_22K)
+#define MX25_PAD_FEC_RX_DV__GPIO_3_12	IOMUX_PAD(FEC_RX_DV, GPIO_3_12, 0x3dc, 0x1e4, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_FEC_TX_CLK__FEC_TX_CLK	IOMUX_PAD(FEC_TX_CLK, FEC_TX_CLK, 0x3e0, 0x1e8, 0x10, 0, 0, PAD_CTL_HYSTERESIS | PAD_CTL_PULL_DOWN_100K | PAD_CTL_SLEW_RATE_FAST)
+#define MX25_PAD_FEC_TX_CLK__GPIO_3_13	IOMUX_PAD(FEC_TX_CLK, GPIO_3_13, 0x3e0, 0x1e8, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_RTCK__RTCK		IOMUX_PAD(RTCK, RTCK, 0x3e4, 0x1ec, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_RTCK__OWIRE		IOMUX_PAD(RTCK, OWIRE, 0x3e4, 0x1ec, 0x11, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_RTCK__GPIO_3_14	IOMUX_PAD(RTCK, GPIO_3_14, 0x3e4, 0x1ec, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_DE_B__DE_B		IOMUX_PAD(DE_B, DE_B, 0x3ec, 0x1f0, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_DE_B__GPIO_2_20	IOMUX_PAD(DE_B, GPIO_2_20, 0x3ec, 0x1f0, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_TDO__TDO		IOMUX_PAD(TDO, TDO, 0x3e8, 0x000, 0x00, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_GPIO_A__GPIO_A		IOMUX_PAD(GPIO_A, GPIO_A, 0x3f0, 0x1f4, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_GPIO_A__CAN1_TX	IOMUX_PAD(GPIO_A, CAN1_TX, 0x3f0, 0x1f4, 0x16, 0, 0, PAD_CTL_PULL_UP_22K | PAD_CTL_OUTPUT_OPEN_DRAIN | PAD_CTL_DRIVE_STRENGTH_MAX)
+#define MX25_PAD_GPIO_A__USBOTG_PWR	IOMUX_PAD(GPIO_A, USBOTG_PWR, 0x3f0, 0x1f4, 0x12, 0, 0, PAD_CTL_PULL_KEEPER)
+#define MX25_PAD_GPIO_B__GPIO_B		IOMUX_PAD(GPIO_B, GPIO_B, 0x3f4, 0x1f8, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_GPIO_B__CAN1_RX	IOMUX_PAD(GPIO_B, CAN1_RX, 0x3f4, 0x1f8, 0x16, 0x480, 1, PAD_CTL_PULL_UP_22K | PAD_CTL_OUTPUT_OPEN_DRAIN)
+#define MX25_PAD_GPIO_B__USBOTG_OC	IOMUX_PAD(GPIO_B, USBOTG_OC, 0x3f4, 0x1f8, 0x12, 0x57c, 1, PAD_CTL_PULL_UP_100K)
+#define MX25_PAD_GPIO_C__GPIO_C		IOMUX_PAD(GPIO_C, GPIO_C, 0x3f8, 0x1fc, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_GPIO_C__CAN2_TX	IOMUX_PAD(GPIO_C, CAN2_TX, 0x3f8, 0x1fc, 0x16, 0, 0, PAD_CTL_PULL_UP_22K | PAD_CTL_OUTPUT_OPEN_DRAIN | PAD_CTL_DRIVE_STRENGTH_MAX)
+#define MX25_PAD_GPIO_D__GPIO_D		IOMUX_PAD(GPIO_D, GPIO_D, 0x3fc, 0x200, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_GPIO_D__CAN2_RX	IOMUX_PAD(GPIO_D, CAN2_RX, 0x3fc, 0x200, 0x16, 0x484, 1, PAD_CTL_PULL_UP_22K)
+#define MX25_PAD_GPIO_E__GPIO_E		IOMUX_PAD(GPIO_E, GPIO_E, 0x400, 0x204, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_GPIO_E__AUD7_TXD	IOMUX_PAD(GPIO_E, AUD7_TXD, 0x400, 0x204, 0x14, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_GPIO_F__GPIO_F		IOMUX_PAD(GPIO_F, GPIO_F, 0x404, 0x208, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_GPIO_F__AUD7_TXC	IOMUX_PAD(GPIO_F, AUD7_TXC, 0x404, 0x208, 0x14, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_EXT_ARMCLK__EXT_ARMCLK	IOMUX_PAD(EXT_ARMCLK, EXT_ARMCLK, 0x000, 0x20c, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_EXT_ARMCLK__GPIO_3_15	IOMUX_PAD(EXT_ARMCLK, GPIO_3_15, 0x000, 0x20c, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_UPLL_BYPCLK__UPLL_BYPCLK IOMUX_PAD(UPLL_BYPCLK, UPLL_BYPCLK, 0x000, 0x210, 0x10, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_UPLL_BYPCLK__GPIO_3_16	IOMUX_PAD(UPLL_BYPCLK, GPIO_3_16, 0x000, 0x210, 0x15, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_VSTBY_REQ__VSTBY_REQ	IOMUX_PAD(VSTBY_REQ, VSTBY_REQ, 0x408, 0x214, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_VSTBY_REQ__AUD7_TXFS	IOMUX_PAD(VSTBY_REQ, AUD7_TXFS, 0x408, 0x214, 0x14, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_VSTBY_REQ__GPIO_3_17	IOMUX_PAD(VSTBY_REQ, GPIO_3_17, 0x408, 0x214, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_VSTBY_ACK__VSTBY_ACK	IOMUX_PAD(VSTBY_ACK, VSTBY_ACK, 0x40c, 0x218, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_VSTBY_ACK__GPIO_3_18	IOMUX_PAD(VSTBY_ACK, GPIO_3_18, 0x40c, 0x218, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_POWER_FAIL__POWER_FAIL	IOMUX_PAD(POWER_FAIL, POWER_FAIL, 0x410, 0x21c, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_POWER_FAIL__AUD7_RXD	IOMUX_PAD(POWER_FAIL, AUD7_RXD, 0x410, 0x21c, 0x14, 0x478, 1, 0 | NO_PAD_CTRL)
+#define MX25_PAD_POWER_FAIL__GPIO_3_19	IOMUX_PAD(POWER_FAIL, GPIO_3_19, 0x410, 0x21c, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CLKO__CLKO		IOMUX_PAD(CLKO, CLKO, 0x414, 0x220, 0x10, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_CLKO__GPIO_2_21	IOMUX_PAD(CLKO, GPIO_2_21, 0x414, 0x220, 0x15, 0, 0, 0 | NO_PAD_CTRL)
+#define MX25_PAD_BOOT_MODE0__BOOT_MODE0	IOMUX_PAD(BOOT_MODE0, BOOT_MODE0, 0x000, 0x224, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_BOOT_MODE0__GPIO_4_30	IOMUX_PAD(BOOT_MODE0, GPIO_4_30, 0x000, 0x224, 0x05, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_BOOT_MODE1__BOOT_MODE1	IOMUX_PAD(BOOT_MODE1, BOOT_MODE1, 0x000, 0x228, 0x00, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_BOOT_MODE1__GPIO_4_31	IOMUX_PAD(BOOT_MODE1, GPIO_4_31, 0x000, 0x228, 0x05, 0, 0, NO_PAD_CTRL)
+
+#define MX25_PAD_CTL_GRP_DVS_MISC	IOMUX_PAD(0x418, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_FEC	IOMUX_PAD(0x41c, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_JTAG	IOMUX_PAD(0x420, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_NFC	IOMUX_PAD(0x424, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_CSI	IOMUX_PAD(0x428, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_WEIM	IOMUX_PAD(0x42c, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_DDR	IOMUX_PAD(0x430, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_CRM	IOMUX_PAD(0x434, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_KPP	IOMUX_PAD(0x438, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_SDHC1	IOMUX_PAD(0x43c, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_LCD	IOMUX_PAD(0x440, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_UART	IOMUX_PAD(0x444, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_NFC	IOMUX_PAD(0x448, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_CSI	IOMUX_PAD(0x44c, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DSE_CSPI1	IOMUX_PAD(0x450, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DDRTYPE	IOMUX_PAD(0x454, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_SDHC1	IOMUX_PAD(0x458, 0x000, 0, 0, 0, NO_PAD_CTRL)
+#define MX25_PAD_CTL_GRP_DVS_LCD	IOMUX_PAD(0x45c, 0x000, 0, 0, 0, NO_PAD_CTRL)
+
+#define IOMUX_TO_GPIO(__pad_desc) ({		\
+	int __gpio = -1;			\
+	struct pad_desc *__pd = __pad_desc;	\
+						\
+	switch (__pd->mux_ctrl_ofs) {		\
+	case MX25_PAD_GPIO_A__GPIO_A:		\
+	__gpio = GPIO_A;			\
+	break;					\
+	case MX25_PAD_GPIO_B__GPIO_B:		\
+	__gpio = GPIO_B;			\
+	break;					\
+	case MX25_PAD_GPIO_C__GPIO_C:		\
+	__gpio = GPIO_C;			\
+	break;					\
+	case MX25_PAD_GPIO_D__GPIO_D:		\
+	__gpio = GPIO_D;			\
+	break;					\
+	case MX25_PAD_GPIO_E__GPIO_E:		\
+	__gpio = GPIO_E;			\
+	break;					\
+	case MX25_PAD_GPIO_F__GPIO_F:		\
+	__gpio = GPIO_F;			\
+	break;					\
+	case MX25_PAD_CSI_D7__GPIO_1_6:		\
+	__gpio = GPIO_1_6;			\
+	break;					\
+	case MX25_PAD_CSI_D8__GPIO_1_7:		\
+	__gpio = GPIO_1_7;			\
+	break;					\
+	case MX25_PAD_CSI_MCLK__GPIO_1_8:	\
+	__gpio = GPIO_1_8;			\
+	break;					\
+	case MX25_PAD_CSI_VSYNC__GPIO_1_9:	\
+	__gpio = GPIO_1_9;			\
+	break;					\
+	case MX25_PAD_CSI_HSYNC__GPIO_1_10:	\
+	__gpio = GPIO_1_10;			\
+	break;					\
+	case MX25_PAD_CSI_PIXCLK__GPIO_1_11:	\
+	__gpio = GPIO_1_11;			\
+	break;					\
+	case MX25_PAD_I2C1_CLK__GPIO_1_12:	\
+	__gpio = GPIO_1_12;			\
+	break;					\
+	case MX25_PAD_I2C1_DAT__GPIO_1_13:	\
+	__gpio = GPIO_1_13;			\
+	break;					\
+	case MX25_PAD_CSPI1_MOSI__GPIO_1_14:	\
+	__gpio = GPIO_1_14;			\
+	break;					\
+	case MX25_PAD_CSPI1_MISO__GPIO_1_15:	\
+	__gpio = GPIO_1_15;			\
+	break;					\
+	case MX25_PAD_CSPI1_SS0__GPIO_1_16:	\
+	__gpio = GPIO_1_16;			\
+	break;					\
+	case MX25_PAD_CSPI1_SS1__GPIO_1_17:	\
+	__gpio = GPIO_1_17;			\
+	break;					\
+	case MX25_PAD_CSPI1_SCLK__GPIO_1_18:	\
+	__gpio = GPIO_1_18;			\
+	break;					\
+	case MX25_PAD_LD5__GPIO_1_19:		\
+	__gpio = GPIO_1_19;			\
+	break;					\
+	case MX25_PAD_LD6__GPIO_1_20:		\
+	__gpio = GPIO_1_20;			\
+	break;					\
+	case MX25_PAD_LD7__GPIO_1_21:		\
+	__gpio = GPIO_1_21;			\
+	break;					\
+	case MX25_PAD_HSYNC__GPIO_1_22:		\
+	__gpio = GPIO_1_22;			\
+	break;					\
+	case MX25_PAD_VSYNC__GPIO_1_23:		\
+	__gpio = GPIO_1_23;			\
+	break;					\
+	case MX25_PAD_LSCLK__GPIO_1_24:		\
+	__gpio = GPIO_1_24;			\
+	break;					\
+	case MX25_PAD_OE_ACD__GPIO_1_25:	\
+	__gpio = GPIO_1_25;			\
+	break;					\
+	case MX25_PAD_PWM__GPIO_1_26:		\
+	__gpio = GPIO_1_26;			\
+	break;					\
+	case MX25_PAD_CSI_D2__GPIO_1_27:	\
+	__gpio = GPIO_1_27;			\
+	break;					\
+	case MX25_PAD_CSI_D3__GPIO_1_28:	\
+	__gpio = GPIO_1_28;			\
+	break;					\
+	case MX25_PAD_CSI_D4__GPIO_1_29:	\
+	__gpio = GPIO_1_29;			\
+	break;					\
+	case MX25_PAD_CSI_D5__GPIO_1_30:	\
+	__gpio = GPIO_1_30;			\
+	break;					\
+	case MX25_PAD_CSI_D6__GPIO_1_31:	\
+	__gpio = GPIO_1_31;			\
+	break;					\
+						\
+	case MX25_PAD_A14__GPIO_2_0:		\
+	__gpio = GPIO_2_0;			\
+	break;					\
+	case MX25_PAD_A15__GPIO_2_1:		\
+	__gpio = GPIO_2_1;			\
+	break;					\
+	case MX25_PAD_A16__GPIO_2_2:		\
+	__gpio = GPIO_2_2;			\
+	break;					\
+	case MX25_PAD_A17__GPIO_2_3:		\
+	__gpio = GPIO_2_3;			\
+	break;					\
+	case MX25_PAD_A18__GPIO_2_4:		\
+	__gpio = GPIO_2_4;			\
+	break;					\
+	case MX25_PAD_A19__GPIO_2_5:		\
+	__gpio = GPIO_2_5;			\
+	break;					\
+	case MX25_PAD_A20__GPIO_2_6:		\
+	__gpio = GPIO_2_6;			\
+	break;					\
+	case MX25_PAD_A21__GPIO_2_7:		\
+	__gpio = GPIO_2_7;			\
+	break;					\
+	case MX25_PAD_A22__GPIO_2_8:		\
+	__gpio = GPIO_2_8;			\
+	break;					\
+	case MX25_PAD_A23__GPIO_2_9:		\
+	__gpio = GPIO_2_9;			\
+	break;					\
+	case MX25_PAD_A24__GPIO_2_10:		\
+	__gpio = GPIO_2_10;			\
+	break;					\
+	case MX25_PAD_A25__GPIO_2_11:		\
+	__gpio = GPIO_2_11;			\
+	break;					\
+	case MX25_PAD_EB0__GPIO_2_12:		\
+	__gpio = GPIO_2_12;			\
+	break;					\
+	case MX25_PAD_EB1__GPIO_2_13:		\
+	__gpio = GPIO_2_13;			\
+	break;					\
+	case MX25_PAD_OE__GPIO_2_14:		\
+	__gpio = GPIO_2_14;			\
+	break;					\
+	case MX25_PAD_LD0__GPIO_2_15:		\
+	__gpio = GPIO_2_15;			\
+	break;					\
+	case MX25_PAD_LD1__GPIO_2_16:		\
+	__gpio = GPIO_2_16;			\
+	break;					\
+	case MX25_PAD_LD2__GPIO_2_17:		\
+	__gpio = GPIO_2_17;			\
+	break;					\
+	case MX25_PAD_LD3__GPIO_2_18:		\
+	__gpio = GPIO_2_18;			\
+	break;					\
+	case MX25_PAD_LD4__GPIO_2_19:		\
+	__gpio = GPIO_2_19;			\
+	break;					\
+	case MX25_PAD_DE_B__GPIO_2_20:		\
+	__gpio = GPIO_2_20;			\
+	break;					\
+	case MX25_PAD_CLKO__GPIO_2_21:		\
+	__gpio = GPIO_2_21;			\
+	break;					\
+	case MX25_PAD_CSPI1_RDY__GPIO_2_22:	\
+	__gpio = GPIO_2_22;			\
+	break;					\
+	case MX25_PAD_SD1_CMD__GPIO_2_23:	\
+	__gpio = GPIO_2_23;			\
+	break;					\
+	case MX25_PAD_SD1_CLK__GPIO_2_24:	\
+	__gpio = GPIO_2_24;			\
+	break;					\
+	case MX25_PAD_SD1_DATA0__GPIO_2_25:	\
+	__gpio = GPIO_2_25;			\
+	break;					\
+	case MX25_PAD_SD1_DATA1__GPIO_2_26:	\
+	__gpio = GPIO_2_26;			\
+	break;					\
+	case MX25_PAD_SD1_DATA2__GPIO_2_27:	\
+	__gpio = GPIO_2_27;			\
+	break;					\
+	case MX25_PAD_SD1_DATA3__GPIO_2_28:	\
+	__gpio = GPIO_2_28;			\
+	break;					\
+	case MX25_PAD_KPP_ROW0__GPIO_2_29:	\
+	__gpio = GPIO_2_29;			\
+	break;					\
+	case MX25_PAD_KPP_ROW1__GPIO_2_30:	\
+	__gpio = GPIO_2_30;			\
+	break;					\
+	case MX25_PAD_KPP_ROW2__GPIO_2_31:	\
+	__gpio = GPIO_2_31;			\
+	break;					\
+						\
+	case MX25_PAD_KPP_ROW3__GPIO_3_0:	\
+	__gpio = GPIO_3_0;			\
+	break;					\
+	case MX25_PAD_KPP_COL0__GPIO_3_1:	\
+	__gpio = GPIO_3_1;			\
+	break;					\
+	case MX25_PAD_KPP_COL1__GPIO_3_2:	\
+	__gpio = GPIO_3_2;			\
+	break;					\
+	case MX25_PAD_KPP_COL2__GPIO_3_3:	\
+	__gpio = GPIO_3_3;			\
+	break;					\
+	case MX25_PAD_KPP_COL3__GPIO_3_4:	\
+	__gpio = GPIO_3_4;			\
+	break;					\
+	case MX25_PAD_FEC_MDC__GPIO_3_5:	\
+	__gpio = GPIO_3_5;			\
+	break;					\
+	case MX25_PAD_FEC_MDIO__GPIO_3_6:	\
+	__gpio = GPIO_3_6;			\
+	break;					\
+	case MX25_PAD_FEC_TDATA0__GPIO_3_7:	\
+	__gpio = GPIO_3_7;			\
+	break;					\
+	case MX25_PAD_FEC_TDATA1__GPIO_3_8:	\
+	__gpio = GPIO_3_8;			\
+	break;					\
+	case MX25_PAD_FEC_TX_EN__GPIO_3_9:	\
+	__gpio = GPIO_3_9;			\
+	break;					\
+	case MX25_PAD_FEC_RDATA0__GPIO_3_10:	\
+	__gpio = GPIO_3_10;			\
+	break;					\
+	case MX25_PAD_FEC_RDATA1__GPIO_3_11:	\
+	__gpio = GPIO_3_11;			\
+	break;					\
+	case MX25_PAD_FEC_RX_DV__GPIO_3_12:	\
+	__gpio = GPIO_3_12;			\
+	break;					\
+	case MX25_PAD_FEC_TX_CLK__GPIO_3_13:	\
+	__gpio = GPIO_3_13;			\
+	break;					\
+	case MX25_PAD_RTCK__GPIO_3_14:		\
+	__gpio = GPIO_3_14;			\
+	break;					\
+	case MX25_PAD_EXT_ARMCLK__GPIO_3_15:	\
+	__gpio = GPIO_3_15;			\
+	break;					\
+	case MX25_PAD_UPLL_BYPCLK__GPIO_3_16:	\
+	__gpio = GPIO_3_16;			\
+	break;					\
+	case MX25_PAD_VSTBY_REQ__GPIO_3_17:	\
+	__gpio = GPIO_3_17;			\
+	break;					\
+	case MX25_PAD_VSTBY_ACK__GPIO_3_18:	\
+	__gpio = GPIO_3_18;			\
+	break;					\
+	case MX25_PAD_POWER_FAIL__GPIO_3_19:	\
+	__gpio = GPIO_3_19;			\
+	break;					\
+	case MX25_PAD_CS4__GPIO_3_20:		\
+	__gpio = GPIO_3_20;			\
+	break;					\
+	case MX25_PAD_CS5__GPIO_3_21:		\
+	__gpio = GPIO_3_21;			\
+	break;					\
+	case MX25_PAD_NF_CE0__GPIO_3_22:	\
+	__gpio = GPIO_3_22;			\
+	break;					\
+	case MX25_PAD_ECB__GPIO_3_23:		\
+	__gpio = GPIO_3_23;			\
+	break;					\
+	case MX25_PAD_LBA__GPIO_3_24:		\
+	__gpio = GPIO_3_24;			\
+	break;					\
+	case MX25_PAD_RW__GPIO_3_25:		\
+	__gpio = GPIO_3_25;			\
+	break;					\
+	case MX25_PAD_NFWE_B__GPIO_3_26:	\
+	__gpio = GPIO_3_26;			\
+	break;					\
+	case MX25_PAD_NFRE_B__GPIO_3_27:	\
+	__gpio = GPIO_3_27;			\
+	break;					\
+	case MX25_PAD_NFALE__GPIO_3_28:		\
+	__gpio = GPIO_3_28;			\
+	break;					\
+	case MX25_PAD_NFCLE__GPIO_3_29:		\
+	__gpio = GPIO_3_29;			\
+	break;					\
+	case MX25_PAD_NFWP_B__GPIO_3_30:	\
+	__gpio = GPIO_3_30;			\
+	break;					\
+	case MX25_PAD_NFRB__GPIO_3_31:		\
+	__gpio = GPIO_3_31;			\
+	break;					\
+						\
+	case MX25_PAD_A10__GPIO_4_0:		\
+	__gpio = GPIO_4_0;			\
+	break;					\
+	case MX25_PAD_A13__GPIO_4_1:		\
+	__gpio = GPIO_4_1;			\
+	break;					\
+	case MX25_PAD_CS0__GPIO_4_2:		\
+	__gpio = GPIO_4_2;			\
+	break;					\
+	case MX25_PAD_CS1__GPIO_4_3:		\
+	__gpio = GPIO_4_3;			\
+	break;					\
+	case MX25_PAD_BCLK__GPIO_4_4:		\
+	__gpio = GPIO_4_4;			\
+	break;					\
+	case MX25_PAD_D15__GPIO_4_5:		\
+	__gpio = GPIO_4_5;			\
+	break;					\
+	case MX25_PAD_D14__GPIO_4_6:		\
+	__gpio = GPIO_4_6;			\
+	break;					\
+	case MX25_PAD_D13__GPIO_4_7:		\
+	__gpio = GPIO_4_7;			\
+	break;					\
+	case MX25_PAD_D12__GPIO_4_8:		\
+	__gpio = GPIO_4_8;			\
+	break;					\
+	case MX25_PAD_D11__GPIO_4_9:		\
+	__gpio = GPIO_4_9;			\
+	break;					\
+	case MX25_PAD_D10__GPIO_4_10:		\
+	__gpio = GPIO_4_10;			\
+	break;					\
+	case MX25_PAD_D9__GPIO_4_11:		\
+	__gpio = GPIO_4_11;			\
+	break;					\
+	case MX25_PAD_D8__GPIO_4_12:		\
+	__gpio = GPIO_4_12;			\
+	break;					\
+	case MX25_PAD_D7__GPIO_4_13:		\
+	__gpio = GPIO_4_13;			\
+	break;					\
+	case MX25_PAD_D6__GPIO_4_14:		\
+	__gpio = GPIO_4_14;			\
+	break;					\
+	case MX25_PAD_D5__GPIO_4_15:		\
+	__gpio = GPIO_4_15;			\
+	break;					\
+	case MX25_PAD_D4__GPIO_4_16:		\
+	__gpio = GPIO_4_16;			\
+	break;					\
+	case MX25_PAD_D3__GPIO_4_17:		\
+	__gpio = GPIO_4_17;			\
+	break;					\
+	case MX25_PAD_D2__GPIO_4_18:		\
+	__gpio = GPIO_4_18;			\
+	break;					\
+	case MX25_PAD_D1__GPIO_4_19:		\
+	__gpio = GPIO_4_19;			\
+	break;					\
+	case MX25_PAD_D0__GPIO_4_20:		\
+	__gpio = GPIO_4_20;			\
+	break;					\
+	case MX25_PAD_CSI_D9__GPIO_4_21:	\
+	__gpio = GPIO_4_21;			\
+	break;					\
+	case MX25_PAD_UART1_RXD__GPIO_4_22:	\
+	__gpio = GPIO_4_22;			\
+	break;					\
+	case MX25_PAD_UART1_TXD__GPIO_4_23:	\
+	__gpio = GPIO_4_23;			\
+	break;					\
+	case MX25_PAD_UART1_RTS__GPIO_4_24:	\
+	__gpio = GPIO_4_24;			\
+	break;					\
+	case MX25_PAD_UART1_CTS__GPIO_4_25:	\
+	__gpio = GPIO_4_25;			\
+	break;					\
+	case MX25_PAD_UART2_RXD__GPIO_4_26:	\
+	__gpio = GPIO_4_26;			\
+	break;					\
+	case MX25_PAD_UART2_TXD__GPIO_4_27:	\
+	__gpio = GPIO_4_27;			\
+	break;					\
+	case MX25_PAD_UART2_RTS__GPIO_4_28:	\
+	__gpio = GPIO_4_28;			\
+	break;					\
+	case MX25_PAD_UART2_CTS__GPIO_4_29:	\
+	__gpio = GPIO_4_29;			\
+	break;					\
+	case MX25_PAD_BOOT_MODE0__GPIO_4_30:	\
+	__gpio = GPIO_4_30;			\
+	break;					\
+	case MX25_PAD_BOOT_MODE1__GPIO_4_31:	\
+	__gpio = GPIO_4_31;			\
+	break;					\
+	}					\
+	__gpio;					\
+})
+
+#endif // __ASSEMBLY__
+#endif // __IOMUX_MX25_H__
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/iomux-v3.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/iomux-v3.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/iomux-v3.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/iomux-v3.h	2009-06-25 15:27:32.000000000 +0200
@@ -52,44 +52,63 @@ struct pad_desc {
 	unsigned pad_ctrl:17;
 	unsigned select_input_ofs:12; /* IOMUXC_SELECT_INPUT offset */
 	unsigned select_input:3;
+#ifdef IOMUX_DEBUG
+	char *name;
+#endif
 };
 
-#define IOMUX_PAD(_pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _select_input_ofs, \
-		_select_input, _pad_ctrl)				\
-		{							\
-			.mux_ctrl_ofs     = _mux_ctrl_ofs,		\
-			.mux_mode         = _mux_mode,			\
-			.pad_ctrl_ofs     = _pad_ctrl_ofs,		\
-			.pad_ctrl         = _pad_ctrl,			\
-			.select_input_ofs = _select_input_ofs,		\
-			.select_input     = _select_input,		\
+#ifdef IOMUX_DEBUG
+#define MXC_PAD_NAME(pd)	(pd)->name
+#define IOMUX_PAD(_pad, _func, _pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _select_input_ofs,	\
+		_select_input, _pad_ctrl)							\
+		{										\
+			.mux_ctrl_ofs     = _mux_ctrl_ofs,					\
+			.mux_mode         = _mux_mode,						\
+			.pad_ctrl_ofs     = _pad_ctrl_ofs,					\
+			.pad_ctrl         = _pad_ctrl,						\
+			.select_input_ofs = _select_input_ofs,					\
+			.select_input     = _select_input,					\
+			.name		  = #_pad"__"#_func,					\
 		}
+#else
+#define MXC_PAD_NAME(pd)	""
+#define IOMUX_PAD(_pad, _func, _pad_ctrl_ofs, _mux_ctrl_ofs, _mux_mode, _select_input_ofs,	\
+		_select_input, _pad_ctrl)							\
+		{										\
+			.mux_ctrl_ofs     = _mux_ctrl_ofs,					\
+			.mux_mode         = _mux_mode,						\
+			.pad_ctrl_ofs     = _pad_ctrl_ofs,					\
+			.pad_ctrl         = _pad_ctrl,						\
+			.select_input_ofs = _select_input_ofs,					\
+			.select_input     = _select_input,					\
+		}
+#endif
 
 /*
  * Use to set PAD control
  */
-#define PAD_CTL_DRIVE_VOLTAGE_3_3_V	0
-#define PAD_CTL_DRIVE_VOLTAGE_1_8_V	1
+#define PAD_CTL_DRIVE_VOLTAGE_3_3_V	(0 << 13)
+#define PAD_CTL_DRIVE_VOLTAGE_1_8_V	(1 << 13)
 
-#define PAD_CTL_NO_HYSTERESIS		0
-#define PAD_CTL_HYSTERESIS		1
+#define PAD_CTL_NO_HYSTERESIS		(0 << 8)
+#define PAD_CTL_HYSTERESIS		(1 << 8)
 
-#define PAD_CTL_PULL_DISABLED		0x0
-#define PAD_CTL_PULL_KEEPER		0xa
-#define PAD_CTL_PULL_DOWN_100K		0xc
-#define PAD_CTL_PULL_UP_47K		0xd
-#define PAD_CTL_PULL_UP_100K		0xe
-#define PAD_CTL_PULL_UP_22K		0xf
-
-#define PAD_CTL_OUTPUT_CMOS		0
-#define PAD_CTL_OUTPUT_OPEN_DRAIN	1
-
-#define PAD_CTL_DRIVE_STRENGTH_NORM	0
-#define PAD_CTL_DRIVE_STRENGTH_HIGH	1
-#define PAD_CTL_DRIVE_STRENGTH_MAX	2
+#define PAD_CTL_PULL_DISABLED		(0x0 << 4)
+#define PAD_CTL_PULL_KEEPER		(0x8 << 4)
+#define PAD_CTL_PULL_DOWN_100K		(0xc << 4)
+#define PAD_CTL_PULL_UP_47K		(0xd << 4)
+#define PAD_CTL_PULL_UP_100K		(0xe << 4)
+#define PAD_CTL_PULL_UP_22K		(0xf << 4)
+
+#define PAD_CTL_OUTPUT_CMOS		(0 << 3)
+#define PAD_CTL_OUTPUT_OPEN_DRAIN	(1 << 3)
+
+#define PAD_CTL_DRIVE_STRENGTH_NORM	(0 << 1)
+#define PAD_CTL_DRIVE_STRENGTH_HIGH	(1 << 1)
+#define PAD_CTL_DRIVE_STRENGTH_MAX	(2 << 1)
 
-#define PAD_CTL_SLEW_RATE_SLOW		0
-#define PAD_CTL_SLEW_RATE_FAST		1
+#define PAD_CTL_SLEW_RATE_SLOW		(0 << 0)
+#define PAD_CTL_SLEW_RATE_FAST		(1 << 0)
 
 /*
  * setups a single pad:
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/iomux.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/iomux.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/iomux.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/iomux.h	2009-06-02 18:02:08.000000000 +0200
@@ -24,10 +24,14 @@
 *  GPIO Module and I/O Multiplexer
 *  x = 0..3 for reg_A, reg_B, reg_C, reg_D
 */
+#ifndef CONFIG_MACH_MX25
 #define VA_GPIO_BASE	IO_ADDRESS(GPIO_BASE_ADDR)
+#endif
 #define MXC_DDIR(x)    (0x00 + ((x) << 8))
+#ifndef CONFIG_MACH_MX25
 #define MXC_OCR1(x)    (0x04 + ((x) << 8))
 #define MXC_OCR2(x)    (0x08 + ((x) << 8))
+#endif
 #define MXC_ICONFA1(x) (0x0c + ((x) << 8))
 #define MXC_ICONFA2(x) (0x10 + ((x) << 8))
 #define MXC_ICONFB1(x) (0x14 + ((x) << 8))
@@ -96,16 +100,20 @@
 
 
 #ifdef CONFIG_ARCH_MX1
-#include <mach/iomux-mx1.h>
+# include <mach/iomux-mx1.h>
 #endif
 #ifdef CONFIG_ARCH_MX2
-#include <mach/iomux-mx2x.h>
-#ifdef CONFIG_MACH_MX21
-#include <mach/iomux-mx21.h>
-#endif
-#ifdef CONFIG_MACH_MX27
-#include <mach/iomux-mx27.h>
-#endif
+# ifndef CONFIG_MACH_MX25
+#  include <mach/iomux-mx2x.h>
+#  ifdef CONFIG_MACH_MX21
+#   include <mach/iomux-mx21.h>
+#  endif
+# endif
+# ifdef CONFIG_MACH_MX27
+#  include <mach/iomux-mx27.h>
+# else
+#  include <mach/iomux-mx25.h>
+# endif
 #endif
 
 
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/irqs.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/irqs.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/irqs.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/irqs.h	2009-06-02 18:02:09.000000000 +0200
@@ -21,7 +21,11 @@
 #if defined CONFIG_ARCH_MX1
 #define MXC_GPIO_IRQS		(32 * 4)
 #elif defined CONFIG_ARCH_MX2
+#ifndef CONFIG_MACH_MX25
 #define MXC_GPIO_IRQS		(32 * 6)
+#else
+#define MXC_GPIO_IRQS		(32 * 4)
+#endif
 #elif defined CONFIG_ARCH_MX3
 #define MXC_GPIO_IRQS		(32 * 3)
 #endif
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/memory.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/memory.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/memory.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/memory.h	2009-06-02 18:02:09.000000000 +0200
@@ -14,12 +14,13 @@
 #if defined CONFIG_ARCH_MX1
 #define PHYS_OFFSET		UL(0x08000000)
 #elif defined CONFIG_ARCH_MX2
-#ifdef CONFIG_MACH_MX21
+# if defined(CONFIG_MACH_MX21)
 #define PHYS_OFFSET		UL(0xC0000000)
-#endif
-#ifdef CONFIG_MACH_MX27
+# elif defined(CONFIG_MACH_MX27)
 #define PHYS_OFFSET		UL(0xA0000000)
-#endif
+# elif defined(CONFIG_MACH_MX25)
+#define PHYS_OFFSET		UL(0x80000000)
+# endif
 #elif defined CONFIG_ARCH_MX3
 #define PHYS_OFFSET		UL(0x80000000)
 #endif
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mx25.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mx25.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mx25.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mx25.h	2009-07-01 11:21:51.000000000 +0200
@@ -0,0 +1,483 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @file arch-mxc/mx25.h
+ * @brief This file contains register definitions.
+ *
+ * @ingroup MSL_MX25
+ */
+
+#ifndef __ASM_ARCH_MXC_MX25_H__
+#define __ASM_ARCH_MXC_MX25_H__
+
+#ifndef __ASM_ARCH_MXC_HARDWARE_H__
+#error "Do not include directly."
+#endif
+
+#ifdef CONFIG_DEBUG_LL
+#ifdef CONFIG_MACH_TX25
+#include <mach/board-tx25.h>
+#endif
+#endif // CONFIG_DEBUG_LL
+
+/*
+ * MX25 memory map:
+ *
+ * Virt     Phys        Size    What
+ * ---------------------------------------------------------------------------
+ * FC000000 43F00000    1M      AIPS 1
+ * FC100000 50000000    1M      SPBA
+ * FC200000 53F00000    1M      AIPS 2
+ * FC300000 60000000    1M      ROMPATCH (128M)
+ * FC400000 68000000    1M      ASIC (128M)
+ * FC500000 78000000    128K    FBC RAM (IRAM)
+ *          80000000    256M    SDRAM0
+ *          90000000    256M    SDRAM1
+ *          A0000000    128M    CS0 Flash
+ *          A8000000    128M    CS1 Flash
+ *          B0000000    32M     CS2 SRAM
+ *          B2000000    32M     CS3
+ *          B4000000    32M     CS4
+ *          B6000000    32M     CS5
+ * FC520000 B8000000    64K     SDRAM, WEIM, M3IF, EMI controllers
+ * FC530000 BB000000    8K      NFC
+ */
+
+#include <asm/memory.h>
+#define VA(x) _AT(void __force __iomem *,x)
+
+/*
+ * IRAM
+ */
+#define IRAM_BASE_ADDR		UL(0x78000000)	/* internal ram */
+#define IRAM_BASE_ADDR_VIRT	VA(0xFC500000)
+#define IRAM_SIZE		SZ_128K
+
+/*
+ * AIPS 1
+ */
+#define AIPS1_BASE_ADDR		UL(0x43F00000)
+#define AIPS1_BASE_ADDR_VIRT	VA(0xFC000000)
+#define AIPS1_SIZE		SZ_1M
+
+#define MAX_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00004000)
+#define CLKCTL_BASE_ADDR	(AIPS1_BASE_ADDR + 0x00008000)
+#define ETB_SLOT4_BASE_ADDR	(AIPS1_BASE_ADDR + 0x0000C000)
+#define ETB_SLOT5_BASE_ADDR	(AIPS1_BASE_ADDR + 0x00010000)
+#define AAPE_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00014000)
+#define I2C_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00080000)
+#define I2C3_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00084000)
+#define CAN1_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00088000)
+#define CAN2_BASE_ADDR		(AIPS1_BASE_ADDR + 0x0008C000)
+#define UART1_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00090000)
+#define UART2_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00094000)
+#define I2C2_BASE_ADDR		(AIPS1_BASE_ADDR + 0x00098000)
+#define OWIRE_BASE_ADDR		(AIPS1_BASE_ADDR + 0x0009C000)
+#define ATA_BASE_ADDR		(AIPS1_BASE_ADDR + 0x000A0000)
+#define CSPI1_BASE_ADDR		(AIPS1_BASE_ADDR + 0x000A4000)
+#define KPP_BASE_ADDR		(AIPS1_BASE_ADDR + 0x000A8000)
+#define IOMUXC_BASE_ADDR	(AIPS1_BASE_ADDR + 0x000AC000)
+#define AUDMUX_BASE_ADDR	(AIPS1_BASE_ADDR + 0x000B0000)
+#define ECT_A_BASE_ADDR		(AIPS1_BASE_ADDR + 0x000B8000)
+#define ECT_B_BASE_ADDR		(AIPS1_BASE_ADDR + 0x000BC000)
+
+/*
+ * SPBA global module enabled #0
+ */
+#define SPBA0_BASE_ADDR		UL(0x50000000)
+#define SPBA0_BASE_ADDR_VIRT	VA(0xFC100000)
+#define SPBA0_SIZE		SZ_1M
+
+#define CSPI3_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00004000)
+#define UART4_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00008000)
+#define UART3_BASE_ADDR		(SPBA0_BASE_ADDR + 0x0000C000)
+#define CSPI2_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00010000)
+#define SSI2_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00014000)
+#define ESAI_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00018000)
+#define ATA_DMA_BASE_ADDR	(SPBA0_BASE_ADDR + 0x00020000)
+#define SIM1_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00024000)
+#define SIM2_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00028000)
+#define UART5_BASE_ADDR		(SPBA0_BASE_ADDR + 0x0002C000)
+#define TSC_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00030000)
+#define SSI1_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00034000)
+#define FEC_BASE_ADDR		(SPBA0_BASE_ADDR + 0x00038000)
+#define SPBA_CTRL_BASE_ADDR	(SPBA0_BASE_ADDR + 0x0003C000)
+
+/*!
+ * defines for SPBA modules
+ */
+#define SPBA_CSPI3		(0x1 << 2)
+#define SPBA_UART4		(0x2 << 2)
+#define SPBA_UART3		(0x3 << 2)
+#define SPBA_CSPI2		(0x4 << 2)
+#define SPBA_SSI2		(0x5 << 2)
+#define SPBA_ESAI		(0x6 << 2)
+#define SPBA_ATA		(0x8 << 2)
+#define SPBA_SIM1		(0x9 << 2)
+#define SPBA_SIM2		(0xA << 2)
+#define SPBA_UART5		(0xB << 2)
+#define SPBA_ANALOG		(0xC << 2)
+#define SPBA_SSI1		(0xD << 2)
+#define SPBA_FEC		(0xE << 2)
+
+/*!
+ * Defines for modules using static and dynamic DMA channels
+ */
+#define MXC_DMA_CHANNEL_IRAM		30
+#define MXC_DMA_CHANNEL_UART1_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART1_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART2_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART3_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART4_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART4_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART5_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_UART5_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MMC1		MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI1_RX		MXC_DMA_DYNAMIC_CHANNEL
+#ifdef CONFIG_SDMA_IRAM
+#define MXC_DMA_CHANNEL_SSI1_TX		(MXC_DMA_CHANNEL_IRAM + 1)
+#else
+#define MXC_DMA_CHANNEL_SSI1_TX		MXC_DMA_DYNAMIC_CHANNEL
+#endif
+#define MXC_DMA_CHANNEL_SSI2_RX		MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_SSI2_TX		MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI1_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI1_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI2_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI3_RX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_CSPI3_TX	MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_RX		MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ATA_TX		MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_MEMORY		MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ESAI_RX		MXC_DMA_DYNAMIC_CHANNEL
+#define MXC_DMA_CHANNEL_ESAI_TX		MXC_DMA_DYNAMIC_CHANNEL
+
+/*
+ * AIPS 2
+ */
+#define AIPS2_BASE_ADDR			UL(0x53F00000)
+#define AIPS2_BASE_ADDR_VIRT		VA(0xFC200000)
+#define AIPS2_SIZE			SZ_1M
+
+#define CCM_BASE_ADDR			(AIPS2_BASE_ADDR + 0x00080000)
+#define GPT4_BASE_ADDR			(AIPS2_BASE_ADDR + 0x00084000)
+#define GPT3_BASE_ADDR			(AIPS2_BASE_ADDR + 0x00088000)
+#define GPT2_BASE_ADDR			(AIPS2_BASE_ADDR + 0x0008C000)
+#define GPT1_BASE_ADDR			(AIPS2_BASE_ADDR + 0x00090000)
+#define EPIT1_BASE_ADDR			(AIPS2_BASE_ADDR + 0x00094000)
+#define EPIT2_BASE_ADDR			(AIPS2_BASE_ADDR + 0x00098000)
+#define GPIO4_BASE_ADDR			(AIPS2_BASE_ADDR + 0x0009C000)
+#define PWM2_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000A0000)
+#define GPIO3_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000A4000)
+#define PWM3_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000A8000)
+#define SCC_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000AC000)
+#define RNGD_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000B0000)
+#define MMC_SDHC1_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000B4000)
+#define MMC_SDHC2_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000B8000)
+#define LCDC_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000BC000)
+#define SLCDC_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000C0000)
+#define PWM4_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000C8000)
+#define GPIO1_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000CC000)
+#define GPIO2_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000D0000)
+#define SDMA_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000D4000)
+#define WDOG_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000DC000)
+#define PWM1_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000E0000)
+#define RTIC_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000EC000)
+#define IIM_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000F0000)
+#define USBOTG_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000F4000)
+#define OTG_BASE_ADDR			(USBOTG_BASE_ADDR + 0x000)
+#define USBH2_BASE_ADDR			(USBOTG_BASE_ADDR + 0x400)
+#define CSI_BASE_ADDR			(AIPS2_BASE_ADDR + 0x000F8000)
+#define DRYICE_BASE_ADDR		(AIPS2_BASE_ADDR + 0x000FC000)
+
+/*
+ * ROMP and ASIC
+ */
+#define ROMP_BASE_ADDR			UL(0x60000000)
+#define ROMP_BASE_ADDR_VIRT		VA(0xFC300000)
+#define ROMP_SIZE			SZ_1M
+
+#define ASIC_BASE_ADDR			UL(0x68000000)
+#define ASIC_BASE_ADDR_VIRT		VA(0xFC400000)
+#define ASIC_SIZE			SZ_1M
+#define AVIC_BASE_ADDR			ASIC_BASE_ADDR
+#define AVIC_BASE_ADDR_VIRT		ASIC_BASE_ADDR_VIRT
+#define AVIC_SIZE			ASIC_SIZE
+
+/*
+ * SDRAM, WEIM, M3IF, EMI controllers
+ */
+#define X_MEMC_BASE_ADDR		UL(0xB8000000)
+#define X_MEMC_BASE_ADDR_VIRT		VA(0xFC520000)
+#define X_MEMC_SIZE			SZ_64K
+
+#define SDRAMC_BASE_ADDR		(X_MEMC_BASE_ADDR + 0x1000)
+#define WEIM_BASE_ADDR			(X_MEMC_BASE_ADDR + 0x2000)
+#define M3IF_BASE_ADDR			(X_MEMC_BASE_ADDR + 0x3000)
+#define EMI_CTL_BASE_ADDR		(X_MEMC_BASE_ADDR + 0x4000)
+
+/*
+ * NFC controller
+ */
+#define NFC_BASE_ADDR			UL(0xBB000000)
+#define NFC_BASE_ADDR_VIRT		VA(0xFC530000)
+#define NFC_SIZE			SZ_8K
+
+/*
+ * Memory regions and CS
+ */
+#define CSD0_BASE_ADDR			UL(0x80000000)
+#define CSD1_BASE_ADDR			UL(0x90000000)
+
+#define SDRAM_BASE_ADDR			CSD0_BASE_ADDR
+
+#define CS0_BASE_ADDR			UL(0xA0000000)
+#define CS1_BASE_ADDR			UL(0xA8000000)
+#define CS2_BASE_ADDR			UL(0xB0000000)
+#define CS3_BASE_ADDR			UL(0xB2000000)
+#define CS4_BASE_ADDR			UL(0xB4000000)
+#define CS4_SIZE			SZ_32M
+#define CS5_BASE_ADDR			UL(0xB6000000)
+#define CS5_SIZE			SZ_32M
+
+/*!
+ * This macro defines the physical to virtual address mapping for all the
+ * peripheral modules. It is used by passing in the physical address as x
+ * and returning the virtual address. If the physical address is not mapped,
+ * it returns 0
+ */
+#define IO_ADDRESS(x)											\
+	VA((((x) >= AIPS1_BASE_ADDR) && ((x) < (AIPS1_BASE_ADDR + AIPS1_SIZE))) ? AIPS1_IO_ADDRESS(x):	\
+	(((x) >= SPBA0_BASE_ADDR) && ((x) < (SPBA0_BASE_ADDR + SPBA0_SIZE))) ? SPBA0_IO_ADDRESS(x):	\
+	(((x) >= AIPS2_BASE_ADDR) && ((x) < (AIPS2_BASE_ADDR + AIPS2_SIZE))) ? AIPS2_IO_ADDRESS(x):	\
+	(((x) >= ROMP_BASE_ADDR) && ((x) < (ROMP_BASE_ADDR + ROMP_SIZE))) ? ROMP_IO_ADDRESS(x):		\
+	(((x) >= ASIC_BASE_ADDR) && ((x) < (ASIC_BASE_ADDR + AVIC_SIZE))) ? ASIC_IO_ADDRESS(x):		\
+	(((x) >= IRAM_BASE_ADDR) && ((x) < (IRAM_BASE_ADDR + IRAM_SIZE))) ? IRAM_IO_ADDRESS(x):		\
+	(((x) >= X_MEMC_BASE_ADDR) && ((x) < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? X_MEMC_IO_ADDRESS(x):	\
+	(((x) >= NFC_BASE_ADDR) && ((x) < (NFC_BASE_ADDR + NFC_SIZE))) ? NFC_IO_ADDRESS(x):		\
+	0)
+
+#define MXC_VADDR_RANGE(v,n)				\
+	(((v)) >= n##_BASE_ADDR_VIRT) &&		\
+	(((v)) < n##_BASE_ADDR_VIRT + n##_SIZE) ?	\
+	((v)-n##_BASE_ADDR_VIRT + n##_BASE_ADDR) :
+
+#define MXC_PHYS_ADDRESS(v)			\
+	UL(MXC_VADDR_RANGE(v,AIPS1)		\
+	MXC_VADDR_RANGE(v,AIPS2)		\
+	MXC_VADDR_RANGE(v,SPBA0)		\
+	MXC_VADDR_RANGE(v,ROMP)			\
+	MXC_VADDR_RANGE(v,ASIC)			\
+	MXC_VADDR_RANGE(v,IRAM)			\
+	MXC_VADDR_RANGE(v,X_MEMC)		\
+	MXC_VADDR_RANGE(v,NFC)			\
+	0)
+
+#define GPIO_BASE_ADDR(port)				\
+	((port == 1 ? GPIO1_BASE_ADDR :			\
+	  (port == 2 ? GPIO2_BASE_ADDR :		\
+	   (port == 3 ? GPIO3_BASE_ADDR :		\
+	    (port == 4 ? GPIO4_BASE_ADDR : 0)))))
+
+/*
+ * define the address mapping macros: in physical address order
+ */
+
+#define AIPS1_IO_ADDRESS(x)  \
+	(((x) - AIPS1_BASE_ADDR) + AIPS1_BASE_ADDR_VIRT)
+
+#define SPBA0_IO_ADDRESS(x)  \
+	(((x) - SPBA0_BASE_ADDR) + SPBA0_BASE_ADDR_VIRT)
+
+#define AIPS2_IO_ADDRESS(x)  \
+	(((x) - AIPS2_BASE_ADDR) + AIPS2_BASE_ADDR_VIRT)
+
+#define ROMP_IO_ADDRESS(x)  \
+	(((x) - ROMP_BASE_ADDR) + ROMP_BASE_ADDR_VIRT)
+
+#define ASIC_IO_ADDRESS(x)  \
+	(((x) - ASIC_BASE_ADDR) + ASIC_BASE_ADDR_VIRT)
+
+/* for entry-macro.S */
+#define AVIC_IO_ADDRESS(x)	ASIC_IO_ADDRESS(x)
+
+#define IRAM_IO_ADDRESS(x)  \
+	(((x) - IRAM_BASE_ADDR) + IRAM_BASE_ADDR_VIRT)
+
+#define X_MEMC_IO_ADDRESS(x)  \
+	(((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
+
+#define NFC_IO_ADDRESS(x)  \
+	(((x) - NFC_BASE_ADDR) + NFC_BASE_ADDR_VIRT)
+
+/*
+ * DMA request assignments
+ */
+#define DMA_REQ_EXTREQ0			 0
+#define DMA_REQ_CCM			 1
+#define DMA_REQ_ATA_TX_END		 2
+#define DMA_REQ_ATA_TX			 3
+#define DMA_REQ_ATA_RX			 4
+#define DMA_REQ_CSPI2_RX		 6
+#define DMA_REQ_CSPI2_TX		 7
+#define DMA_REQ_CSPI1_RX		 8
+#define DMA_REQ_CSPI1_TX		 9
+#define DMA_REQ_UART3_RX		10
+#define DMA_REQ_UART3_TX		11
+#define DMA_REQ_UART4_RX		12
+#define DMA_REQ_UART4_TX		13
+#define DMA_REQ_EXTREQ1			14
+#define DMA_REQ_EXTREQ2			15
+#define DMA_REQ_UART2_RX		16
+#define DMA_REQ_UART2_TX		17
+#define DMA_REQ_UART1_RX		18
+#define DMA_REQ_UART1_TX		19
+#define DMA_REQ_SSI2_RX1		22
+#define DMA_REQ_SSI2_TX1		23
+#define DMA_REQ_SSI2_RX0		24
+#define DMA_REQ_SSI2_TX0		25
+#define DMA_REQ_SSI1_RX1		26
+#define DMA_REQ_SSI1_TX1		27
+#define DMA_REQ_SSI1_RX0		28
+#define DMA_REQ_SSI1_TX0		29
+#define DMA_REQ_NFC			30
+#define DMA_REQ_ECT			31
+#define DMA_REQ_ESAI_RX			32
+#define DMA_REQ_ESAI_TX			33
+#define DMA_REQ_CSPI3_RX		34
+#define DMA_REQ_CSPI3_TX		35
+#define DMA_REQ_SIM2_RX			36
+#define DMA_REQ_SIM2_TX			37
+#define DMA_REQ_SIM1_RX			38
+#define DMA_REQ_SIM1_TX			39
+#define DMA_REQ_TSC_GCQ			44
+#define DMA_REQ_TSC_TCQ			45
+#define DMA_REQ_UART5_RX		46
+#define DMA_REQ_UART5_TX		47
+
+/*
+ *  Interrupt numbers
+ */
+#define MXC_INT_CSPI3			 0
+#define MXC_INT_GPT4			 1
+#define MXC_INT_OWIRE			 2
+#define MXC_INT_I2C			 3
+#define MXC_INT_I2C2			 4
+#define MXC_INT_UART4			 5
+#define MXC_INT_RTIC			 6
+#define MXC_INT_ESAI			 7
+#define MXC_INT_SDHC2			 8
+#define MXC_INT_SDHC1			 9
+#define MXC_INT_I2C3			10
+#define MXC_INT_SSI2			11
+#define MXC_INT_SSI1			12
+#define MXC_INT_CSPI2			13
+#define MXC_INT_CSPI1			14
+#define MXC_INT_ATA			15
+#define MXC_INT_GPIO3			16
+#define MXC_INT_CSI			17
+#define MXC_INT_UART3			18
+#define MXC_INT_IIM			19
+#define MXC_INT_SIM1			20
+#define MXC_INT_SIM2			21
+#define MXC_INT_RNGD			22
+#define MXC_INT_GPIO4			23
+#define MXC_INT_KPP			24
+#define MXC_INT_DRYICE_RTC		25
+#define MXC_INT_PWM			26
+#define MXC_INT_EPIT2			27
+#define MXC_INT_EPIT1			28
+#define MXC_INT_GPT3			29
+#define MXC_INT_POWER_FAIL		30
+#define MXC_INT_CRM			31
+#define MXC_INT_UART2			32
+#define MXC_INT_NANDFC			33
+#define MXC_INT_SDMA			34
+#define MXC_INT_USB_H2			35
+#define MXC_INT_PWM2			36
+#define MXC_INT_USB_OTG			37
+#define MXC_INT_SLCDC			38
+#define MXC_INT_LCDC			39
+#define MXC_INT_UART5			40
+#define MXC_INT_PWM3			41
+#define MXC_INT_PWM4			42
+#define MXC_INT_CAN1			43
+#define MXC_INT_CAN2			44
+#define MXC_INT_UART1			45
+#define MXC_INT_TSC			46
+#define MXC_INT_ECT			48
+#define MXC_INT_SCC_SCM			49
+#define MXC_INT_SCC_SMN			50
+#define MXC_INT_GPIO2			51
+#define MXC_INT_GPIO1			52
+#define MXC_INT_GPT2			53
+#define MXC_INT_GPT1			54
+#define MXC_INT_WDOG			55
+#define MXC_INT_DRYICE			56
+#define MXC_INT_FEC			57
+#define MXC_INT_EXT_INT5		58
+#define MXC_INT_EXT_INT4		59
+#define MXC_INT_EXT_INT3		60
+#define MXC_INT_EXT_INT2		61
+#define MXC_INT_EXT_INT1		62
+#define MXC_INT_EXT_INT0		63
+
+#define MXC_INT_GPT			MXC_INT_GPT1
+
+/* silicon revisions specific to i.MX25 */
+#define CHIP_REV_1_0			0x00
+#define CHIP_REV_1_1			0x01
+
+/* gpio and gpio based interrupt handling */
+#define GPIO_DR				0x00
+#define GPIO_GDIR			0x04
+#define GPIO_PSR			0x08
+#define GPIO_ICR1			0x0C
+#define GPIO_ICR2			0x10
+#define GPIO_IMR			0x14
+#define GPIO_ISR			0x18
+#define GPIO_INT_LOW_LEV		0x0
+#define GPIO_INT_HIGH_LEV		0x1
+#define GPIO_INT_RISE_EDGE		0x2
+#define GPIO_INT_FALL_EDGE		0x3
+#define GPIO_INT_NONE			0x4
+
+/* Mandatory defines used globally */
+
+/* this CPU supports up to 96 GPIOs */
+#define ARCH_NR_GPIOS			128
+
+#define MXC_TIMER_GPT1			1
+#define MXC_TIMER_GPT2			2
+#define MXC_TIMER_GPT3			3
+#define MXC_TIMER_GPT4			4
+
+/*!
+ * NFMS bit in RCSR register for pagesize of nandflash
+ */
+#define NFMS_REG			IO_ADDRESS(CCM_BASE_ADDR + 0x28)
+#define NFMS_NF_DWIDTH			14
+#define NFMS_NF_PG_SZ			8
+
+#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
+#include <linux/io.h>
+
+extern int mx25_revision(void);
+
+#endif
+
+#endif /* __ASM_ARCH_MXC_MX25_H__ */
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mx2x.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mx2x.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mx2x.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mx2x.h	2009-06-02 18:02:11.000000000 +0200
@@ -79,7 +79,7 @@
  * This macro defines the physical to virtual address mapping for all the
  * peripheral modules. It is used by passing in the physical address as x
  * and returning the virtual address. If the physical address is not mapped,
- * it returns 0xDEADBEEF
+ * it returns 0
  */
 #define IO_ADDRESS(x)   \
 	(void __force __iomem *) \
@@ -88,7 +88,7 @@
 	((x >= SAHB1_BASE_ADDR) && (x < (SAHB1_BASE_ADDR + SAHB1_SIZE))) ? \
 		SAHB1_IO_ADDRESS(x) : \
 	((x >= X_MEMC_BASE_ADDR) && (x < (X_MEMC_BASE_ADDR + X_MEMC_SIZE))) ? \
-		X_MEMC_IO_ADDRESS(x) : 0xDEADBEEF)
+		X_MEMC_IO_ADDRESS(x) : 0)
 
 /* define the address mapping macros: in physical address order */
 #define AIPI_IO_ADDRESS(x)  \
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mxc.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mxc.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mxc.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mxc.h	2009-06-02 18:02:12.000000000 +0200
@@ -27,6 +27,7 @@
 #define MXC_CPU_MX1		1
 #define MXC_CPU_MX21		21
 #define MXC_CPU_MX27		27
+#define MXC_CPU_MX25		25
 #define MXC_CPU_MX31		31
 #define MXC_CPU_MX35		35
 
@@ -70,6 +71,18 @@ extern unsigned int __mxc_cpu_type;
 # define cpu_is_mx27()		(0)
 #endif
 
+#ifdef CONFIG_MACH_MX25
+# ifdef mxc_cpu_type
+#  undef mxc_cpu_type
+#  define mxc_cpu_type __mxc_cpu_type
+# else
+#  define mxc_cpu_type MXC_CPU_MX25
+# endif
+# define cpu_is_mx25()		(mxc_cpu_type == MXC_CPU_MX25)
+#else
+# define cpu_is_mx25()		(0)
+#endif
+
 #ifdef CONFIG_ARCH_MX31
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
@@ -101,6 +114,6 @@ extern unsigned int __mxc_cpu_type;
 #endif
 
 #define cpu_is_mx3()	(cpu_is_mx31() || cpu_is_mx35())
-#define cpu_is_mx2()	(cpu_is_mx21() || cpu_is_mx27())
+#define cpu_is_mx2()	(cpu_is_mx21() || cpu_is_mx25() || cpu_is_mx27())
 
 #endif /*  __ASM_ARCH_MXC_H__ */
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mxc_can.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mxc_can.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mxc_can.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mxc_can.h	2009-07-01 11:31:19.000000000 +0200
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2009  Lothar Wassmann <LW@KARO-electronics.de>
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ */
+
+#include <linux/platform_device.h>
+
+struct flexcan_platform_data {
+	char *core_reg;
+	char *io_reg;
+	int (*xcvr_enable)(struct platform_device *pdev, int en);
+	int (*active)(struct platform_device *pdev);
+	void (*inactive)(struct platform_device *pdev);
+};
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mxc_ehci.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mxc_ehci.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mxc_ehci.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mxc_ehci.h	2009-07-01 11:31:34.000000000 +0200
@@ -0,0 +1,9 @@
+#ifndef __INCLUDE_ASM_ARCH_MXC_EHCI_H
+#define __INCLUDE_ASM_ARCH_MXC_EHCI_H
+
+struct mxc_usbh_platform_data {
+	int (*init)(struct platform_device *pdev);
+	int (*exit)(struct platform_device *pdev);
+};
+#endif /* __INCLUDE_ASM_ARCH_MXC_EHCI_H */
+
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mxc_tsadcc.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mxc_tsadcc.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/mxc_tsadcc.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/mxc_tsadcc.h	2009-07-01 11:23:07.000000000 +0200
@@ -0,0 +1,28 @@
+/*
+ *  Freescale i.MX25 Touch Screen Driver
+ *
+ *  Copyright (c) 2009 Lothar Wassmann <LW@KARO-electronics.de>
+ *
+ * Based on code from Freescale BSP
+ *
+ *  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.
+ */
+
+typedef enum {
+	MXC_TSC_4WIRE,
+	MXC_TSC_5WIRE,
+} mxc_tsc_mode;
+
+struct mxc_tsadcc_pdata {
+	int pen_debounce_time;	/* 0: disable debounce;
+				 * 1..128: # of ADC clock cycles / 8 */
+	unsigned int intref:1,	/* 0|1: internal reference disabled|enabled */
+		     hsyncen:1;	/* synchronize measurements with LCD HSYNC */
+	unsigned int r_xplate;	/* resistance (in Ohms) of X plate
+				 * (required for pressure measurement */
+	int adc_clk;		/* ADC clock frequency in Hz (max. 1750000);
+				 * <= 0: use default (1666667) */
+	mxc_tsc_mode tsc_mode;	/* select 4 wire or 5 wire mode */
+};
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/sdma.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/sdma.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/sdma.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/sdma.h	2009-06-02 18:02:13.000000000 +0200
@@ -0,0 +1,504 @@
+
+/*
+ * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#ifndef __ASM_ARCH_MXC_SDMA_H__
+#define __ASM_ARCH_MXC_SDMA_H__
+
+/*!
+ * @defgroup SDMA Smart Direct Memory Access (SDMA) Driver
+ */
+
+/*!
+ * @file arch-mxc/sdma.h
+ *
+ * @brief This file contains the SDMA API declarations.
+ *
+ * SDMA is responsible on moving data between peripherals and memories (MCU, EMI and DSP).
+ *
+ * @ingroup SDMA
+ */
+
+#include <stdarg.h>
+#include <linux/interrupt.h>
+#include <mach/dma.h>
+#include <mach/hardware.h>
+
+/*!
+ * This defines maximum DMA address
+ */
+#define MAX_DMA_ADDRESS 0xffffffff
+
+/*!
+ * This defines maximum number of DMA channels
+ */
+#ifdef CONFIG_MXC_SDMA_API
+#define MAX_DMA_CHANNELS 32
+#define MAX_BD_NUMBER    16
+#define MXC_SDMA_DEFAULT_PRIORITY 1
+#define MXC_SDMA_MIN_PRIORITY 1
+#define MXC_SDMA_MAX_PRIORITY 7
+#else
+#define MAX_DMA_CHANNELS 0
+#endif
+
+#define MXC_FIFO_MEM_DEST_FIXED   0x1
+#define MXC_FIFO_MEM_SRC_FIXED    0x2
+/*!
+ * This enumerates  transfer types
+ */
+typedef enum {
+	emi_2_per = 0,		/*!< EMI memory to peripheral */
+	emi_2_int,		/*!< EMI memory to internal RAM */
+	emi_2_emi,		/*!< EMI memory to EMI memory */
+	emi_2_dsp,		/*!< EMI memory to DSP memory */
+	per_2_int,		/*!< Peripheral to internal RAM */
+	per_2_emi,		/*!< Peripheral to internal EMI memory */
+	per_2_dsp,		/*!< Peripheral to DSP memory */
+	per_2_per,		/*!< Peripheral to Peripheral */
+	int_2_per,		/*!< Internal RAM to peripheral */
+	int_2_int,		/*!< Internal RAM to Internal RAM */
+	int_2_emi,		/*!< Internal RAM to EMI memory */
+	int_2_dsp,		/*!< Internal RAM to DSP memory */
+	dsp_2_per,		/*!< DSP memory to peripheral */
+	dsp_2_int,		/*!< DSP memory to internal RAM */
+	dsp_2_emi,		/*!< DSP memory to EMI memory */
+	dsp_2_dsp,		/*!< DSP memory to DSP memory */
+	emi_2_dsp_loop,		/*!< EMI memory to DSP memory loopback */
+	dsp_2_emi_loop,		/*!< DSP memory to EMI memory loopback */
+	dvfs_pll,		/*!< DVFS script with PLL change       */
+	dvfs_pdr		/*!< DVFS script without PLL change    */
+} sdma_transferT;
+
+/*!
+ * This enumerates peripheral types
+ */
+typedef enum {
+	SSI,			/*!< MCU domain SSI */
+	SSI_SP,			/*!< Shared SSI */
+	MMC,			/*!< MMC */
+	SDHC,			/*!< SDHC */
+	UART,			/*!< MCU domain UART */
+	UART_SP,		/*!< Shared UART */
+	FIRI,			/*!< FIRI */
+	CSPI,			/*!< MCU domain CSPI */
+	CSPI_SP,		/*!< Shared CSPI */
+	SIM,			/*!< SIM */
+	ATA,			/*!< ATA */
+	CCM,			/*!< CCM */
+	EXT,			/*!< External peripheral */
+	MSHC,			/*!< Memory Stick Host Controller */
+	MSHC_SP,		/*!< Shared Memory Stick Host Controller */
+	DSP,			/*!< DSP */
+	MEMORY,			/*!< Memory */
+	FIFO_MEMORY,		/*!< FIFO type Memory */
+	SPDIF,			/*!< SPDIF */
+	IPU_MEMORY,		/*!< IPU Memory */
+	ASRC,			/*!< ASRC */
+	ESAI,			/*!< ESAI */
+} sdma_periphT;
+
+#ifndef TRANSFER_32BIT
+/*!
+ * This defines SDMA access data size
+ */
+#define TRANSFER_32BIT      0x00
+#define TRANSFER_8BIT       0x01
+#define TRANSFER_16BIT      0x02
+#define TRANSFER_24BIT      0x03
+
+#endif
+
+/*!
+ * This defines maximum device name length passed during mxc_request_dma().
+ */
+#define MAX_DEVNAME_LENGTH 32
+
+/*!
+ * This defines SDMA interrupt callback function prototype.
+ */
+typedef void (*dma_callback_t) (void *arg);
+
+/*!
+ * Structure containing sdma channel parameters.
+ */
+typedef struct {
+	__u32 watermark_level;	/*!< Lower/upper threshold that
+				 *   triggers SDMA event
+				 */
+	__u32 per_address;	/*!< Peripheral source/destination
+				 *   physical address
+				 */
+	sdma_periphT peripheral_type;	/*!< Peripheral type */
+	sdma_transferT transfer_type;	/*!< Transfer type   */
+	int event_id;		/*!< Event number,
+				 *   needed by all channels
+				 *   that started by peripherals dma
+				 *   request (per_2_*,*_2_per)
+				 *   Not used for memory and DSP
+				 *   transfers.
+				 */
+	int event_id2;		/*!< Second event number,
+				 *   used in ATA scripts only.
+				 */
+	int bd_number;		/*!< Buffer descriptors number.
+				 *   If not set, single buffer
+				 *   descriptor will be used.
+				 */
+	dma_callback_t callback;	/*!   callback function            */
+	void *arg;		/*!   callback argument            */
+	unsigned long word_size:8;	/*!< SDMA data access word size    */
+} dma_channel_params;
+
+/*!
+ * Structure containing sdma request  parameters.
+ */
+typedef struct {
+	/*!   physical source memory address        */
+	__u8 *sourceAddr;
+	/*!   physical destination memory address   */
+	__u8 *destAddr;
+	/*!   amount of data to transfer,
+	 * updated during mxc_dma_get_config
+	 */
+	__u16 count;
+	/*!< DONE bit of the buffer descriptor,
+	 * updated during mxc_dma_get_config
+	 * 0 - means the BD is done and closed by SDMA
+	 * 1 - means the BD is still being processed by SDMA
+	 */
+	int bd_done;
+	/*!< CONT bit of the buffer descriptor,
+	 * set it if full multi-buffer descriptor mechanism
+	 * required.
+	 */
+	int bd_cont;
+	/*!< ERROR bit of the buffer descriptor,
+	 * updated during mxc_dma_get_config.
+	 * If it is set - there was an error during BD processing.
+	 */
+	int bd_error;
+} dma_request_t;
+
+/*!
+ * Structure containing sdma request  parameters.
+ */
+typedef struct {
+	/*! address of ap_2_ap script */
+	int mxc_sdma_ap_2_ap_addr;
+	/*! address of ap_2_bp script */
+	int mxc_sdma_ap_2_bp_addr;
+	/*! address of ap_2_ap_fixed script */
+	int mxc_sdma_ap_2_ap_fixed_addr;
+	/*! address of bp_2_ap script */
+	int mxc_sdma_bp_2_ap_addr;
+	/*! address of loopback_on_dsp_side script */
+	int mxc_sdma_loopback_on_dsp_side_addr;
+	/*! address of mcu_interrupt_only script */
+	int mxc_sdma_mcu_interrupt_only_addr;
+
+	/*! address of firi_2_per script */
+	int mxc_sdma_firi_2_per_addr;
+	/*! address of firi_2_mcu script */
+	int mxc_sdma_firi_2_mcu_addr;
+	/*! address of per_2_firi script */
+	int mxc_sdma_per_2_firi_addr;
+	/*! address of mcu_2_firi script */
+	int mxc_sdma_mcu_2_firi_addr;
+
+	/*! address of uart_2_per script */
+	int mxc_sdma_uart_2_per_addr;
+	/*! address of uart_2_mcu script */
+	int mxc_sdma_uart_2_mcu_addr;
+	/*! address of per_2_app script */
+	int mxc_sdma_per_2_app_addr;
+	/*! address of mcu_2_app script */
+	int mxc_sdma_mcu_2_app_addr;
+	/*! address of per_2_per script */
+	int mxc_sdma_per_2_per_addr;
+
+	/*! address of uartsh_2_per script */
+	int mxc_sdma_uartsh_2_per_addr;
+	/*! address of uartsh_2_mcu script */
+	int mxc_sdma_uartsh_2_mcu_addr;
+	/*! address of per_2_shp script */
+	int mxc_sdma_per_2_shp_addr;
+	/*! address of mcu_2_shp script */
+	int mxc_sdma_mcu_2_shp_addr;
+
+	/*! address of ata_2_mcu script */
+	int mxc_sdma_ata_2_mcu_addr;
+	/*! address of mcu_2_ata script */
+	int mxc_sdma_mcu_2_ata_addr;
+
+	/*! address of app_2_per script */
+	int mxc_sdma_app_2_per_addr;
+	/*! address of app_2_mcu script */
+	int mxc_sdma_app_2_mcu_addr;
+	/*! address of shp_2_per script */
+	int mxc_sdma_shp_2_per_addr;
+	/*! address of shp_2_mcu script */
+	int mxc_sdma_shp_2_mcu_addr;
+
+	/*! address of mshc_2_mcu script */
+	int mxc_sdma_mshc_2_mcu_addr;
+	/*! address of mcu_2_mshc script */
+	int mxc_sdma_mcu_2_mshc_addr;
+
+	/*! address of spdif_2_mcu script */
+	int mxc_sdma_spdif_2_mcu_addr;
+	/*! address of mcu_2_spdif script */
+	int mxc_sdma_mcu_2_spdif_addr;
+
+	/*! address of asrc_2_mcu script */
+	int mxc_sdma_asrc_2_mcu_addr;
+
+	/*! address of ext_mem_2_ipu script */
+	int mxc_sdma_ext_mem_2_ipu_addr;
+
+	/*! address of descrambler script */
+	int mxc_sdma_descrambler_addr;
+
+	/*! address of dptc_dvfs script */
+	int mxc_sdma_dptc_dvfs_addr;
+
+	int mxc_sdma_utra_addr;
+
+	/*! address where ram code starts */
+	int mxc_sdma_ram_code_start_addr;
+	/*! size of the ram code */
+	int mxc_sdma_ram_code_size;
+	/*! RAM image address */
+	unsigned short *mxc_sdma_start_addr;
+} sdma_script_start_addrs;
+
+/*! Structure to store the initialized dma_channel parameters */
+typedef struct mxc_sdma_channel_params {
+	/*! Channel params */
+	dma_channel_params chnl_params;
+	/*! Channel type (static channel number or dynamic channel) */
+	unsigned int channel_num;
+	/*! Channel priority [0x1(lowest) - 0x7(highest)] */
+	unsigned int chnl_priority;
+} mxc_sdma_channel_params_t;
+
+/*! Private SDMA data structure */
+typedef struct mxc_dma_channel_private {
+	/*! ID of the buffer that was processed */
+	unsigned int buf_tail;
+	/*! Tasklet for the channel */
+	struct tasklet_struct chnl_tasklet;
+	/*! Flag indicates if interrupt is required after every BD transfer */
+	int intr_after_every_bd;
+} mxc_dma_channel_private_t;
+
+/*!
+ * Setup channel according to parameters.
+ * Must be called once after mxc_request_dma()
+ *
+ * @param   channel           channel number
+ * @param   p                 channel parameters pointer
+ * @return  0 on success, error code on fail
+ */
+int mxc_dma_setup_channel(int channel, dma_channel_params * p);
+
+/*!
+ * Setup the channel priority. This can be used to change the default priority
+ * for the channel.
+ *
+ * @param   channel           channel number
+ * @param   priority          priority to be set for the channel
+ *
+ * @return  0 on success, error code on failure
+ */
+int mxc_dma_set_channel_priority(unsigned int channel, unsigned int priority);
+
+/*!
+ * Allocates dma channel.
+ * If channel's value is 0, then the function allocates a free channel
+ * dynamically and sets its value to channel.
+ * Else allocates requested channel if it is free.
+ * If the channel is busy or no free channels (in dynamic allocation) -EBUSY returned.
+ *
+ * @param   channel           pointer to channel number
+ * @param   devicename        device name
+ * @return  0 on success, error code on fail
+ */
+int mxc_request_dma(int *channel, const char *devicename);
+
+/*!
+ * Configures request parameters. Can be called multiple times after
+ * mxc_request_dma() and mxc_dma_setup_channel().
+ *
+ *
+ * @param   channel           channel number
+ * @param   p                 request parameters pointer
+ * @param   bd_index          index of buffer descriptor to set
+ * @return  0 on success, error code on fail
+ */
+/* int mxc_dma_set_config(int channel, dma_request_t *p, int bd_index); */
+int mxc_dma_set_config(int channel, dma_request_t * p, int bd_index);
+
+/*!
+ * Returns request parameters.
+ *
+ * @param   channel           channel number
+ * @param   p                 request parameters pointer
+ * @param   bd_index          index of buffer descriptor to get
+ * @return  0 on success, error code on fail
+ */
+/* int mxc_dma_get_config(int channel, dma_request_t *p, int bd_index); */
+int mxc_dma_get_config(int channel, dma_request_t * p, int bd_index);
+
+/*!
+ * This function is used by MXC IPC's write_ex2. It passes the a pointer to the
+ * data control structure to iapi_write_ipcv2()
+ *
+ * @param channel  SDMA channel number
+ * @param ctrl_ptr Data Control structure pointer
+ */
+int mxc_sdma_write_ipcv2(int channel, void *ctrl_ptr);
+
+/*!
+ * This function is used by MXC IPC's read_ex2. It passes the a pointer to the
+ * data control structure to iapi_read_ipcv2()
+ *
+ * @param channel   SDMA channel number
+ * @param ctrl_ptr  Data Control structure pointer
+ */
+int mxc_sdma_read_ipcv2(int channel, void *ctrl_ptr);
+
+/*!
+ * Starts dma channel.
+ *
+ * @param   channel           channel number
+ */
+int mxc_dma_start(int channel);
+
+/*!
+ * Stops dma channel.
+ *
+ * @param   channel           channel number
+ */
+int mxc_dma_stop(int channel);
+
+/*!
+ * Frees dma channel.
+ *
+ * @param   channel           channel number
+ */
+void mxc_free_dma(int channel);
+
+/*!
+ * Sets callback function. Used with standard dma api
+ *  for supporting interrupts
+ *
+ * @param   channel           channel number
+ * @param   callback          callback function pointer
+ * @param   arg               argument for callback function
+ */
+void mxc_dma_set_callback(int channel, dma_callback_t callback, void *arg);
+
+/*!
+ * Allocates uncachable buffer. Uses hash table.
+ *
+ * @param   size    size of allocated buffer
+ * @return  pointer to buffer
+ */
+void *sdma_malloc(size_t size);
+
+#ifdef CONFIG_SDMA_IRAM
+/*!
+ * Allocates uncachable buffer from IRAM..
+ *
+ * @param   size    size of allocated buffer
+ * @return  pointer to buffer
+ */
+void *sdma_iram_malloc(size_t size);
+#endif				/*CONFIG_SDMA_IRAM */
+
+/*!
+ * Frees uncachable buffer. Uses hash table.
+ */
+void sdma_free(void *buf);
+
+/*!
+ * Converts virtual to physical address. Uses hash table.
+ *
+ * @param   buf  virtual address pointer
+ * @return  physical address value
+ */
+unsigned long sdma_virt_to_phys(void *buf);
+
+/*!
+ * Converts physical to virtual address. Uses hash table.
+ *
+ * @param   buf  physical address value
+ * @return  virtual address pointer
+ */
+void *sdma_phys_to_virt(unsigned long buf);
+
+/*!
+ * Configures the BD_INTR bit on a buffer descriptor parameters.
+ *
+ *
+ * @param   channel           channel number
+ * @param   bd_index          index of buffer descriptor to set
+ * @param   bd_intr           flag to set or clear the BD_INTR bit
+ */
+void mxc_dma_set_bd_intr(int channel, int bd_index, int bd_intr);
+
+/*!
+ * Gets the BD_INTR bit on a buffer descriptor.
+ *
+ *
+ * @param   channel           channel number
+ * @param   bd_index          index of buffer descriptor to set
+ *
+ * @return returns the BD_INTR bit status
+ */
+int mxc_dma_get_bd_intr(int channel, int bd_index);
+
+/*!
+ * Stop the current transfer
+ *
+ * @param   channel           channel number
+ * @param   buffer_number     number of buffers (beginning with 0),
+ *                            whose done bits should be reset to 0
+ */
+int mxc_dma_reset(int channel, int buffer_number);
+
+/*!
+ * This functions Returns the SDMA paramaters associated for a module
+ *
+ * @param channel_id the ID of the module requesting DMA
+ * @return returns the sdma parameters structure for the device
+ */
+mxc_sdma_channel_params_t *mxc_sdma_get_channel_params(mxc_dma_device_t
+						       channel_id);
+
+/*!
+ * This functions marks the SDMA channels that are statically allocated
+ *
+ * @param chnl the channel array used to store channel information
+ */
+void mxc_get_static_channels(mxc_dma_channel_t * chnl);
+
+/*!
+ * Initializes SDMA driver
+ */
+int __init sdma_init(void);
+
+#define DEFAULT_ERR     1
+
+#endif
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/spba.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/spba.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/spba.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/spba.h	2009-06-02 18:02:13.000000000 +0200
@@ -0,0 +1,66 @@
+
+/*
+ * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @defgroup SPBA Shared Peripheral Bus Arbiter (SPBA)
+ * @ingroup MSL_MX31 MSL_MX35 MSL_MX37 MSL_MX51 MSL_MXC91321
+ */
+
+/*!
+ * @file arch-mxc/spba.h
+ * @brief This file contains the Shared Peripheral Bus Arbiter (spba) API.
+ *
+ * @ingroup SPBA
+ */
+
+#ifndef __ASM_ARCH_MXC_SPBA_H__
+#define __ASM_ARCH_MXC_SPBA_H__
+
+#ifdef __KERNEL__
+
+#define MXC_SPBA_RAR_MASK       0x7
+
+/*!
+ * Defines three SPBA masters: A - ARM, C - SDMA (no master B for MX31)
+ */
+enum spba_masters {
+	SPBA_MASTER_A = 1,
+	SPBA_MASTER_B = 2,
+	SPBA_MASTER_C = 4,
+};
+
+/*!
+ * This function allows the three masters (A, B, C) to take ownership of a
+ * shared peripheral.
+ *
+ * @param  mod          specified module as defined in \b enum \b #spba_module
+ * @param  master       one of more (or-ed together) masters as defined in \b enum \b #spba_masters
+ *
+ * @return 0 if successful; -1 otherwise.
+ */
+int spba_take_ownership(int mod, int master);
+
+/*!
+ * This function releases the ownership for a shared peripheral.
+ *
+ * @param  mod          specified module as defined in \b enum \b #spba_module
+ * @param  master       one of more (or-ed together) masters as defined in \b enum \b #spba_masters
+ *
+ * @return 0 if successful; -1 otherwise.
+ */
+int spba_rel_ownership(int mod, int master);
+
+#endif				/* __KERNEL__ */
+
+#endif				/* __ASM_ARCH_MXC_SPBA_H__ */
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/timex.h linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/timex.h
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/include/mach/timex.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/include/mach/timex.h	2009-07-02 16:20:37.000000000 +0200
@@ -23,7 +23,11 @@
 #if defined CONFIG_ARCH_MX1
 #define CLOCK_TICK_RATE		16000000
 #elif defined CONFIG_ARCH_MX2
+#ifndef CONFIG_MACH_MX25
 #define CLOCK_TICK_RATE		13300000
+#else
+#define CLOCK_TICK_RATE		66500000
+#endif
 #elif defined CONFIG_ARCH_MX3
 #define CLOCK_TICK_RATE		16625000
 #endif
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/iomux-mx1-mx2.c linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/iomux-mx1-mx2.c
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/iomux-mx1-mx2.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/iomux-mx1-mx2.c	2009-06-02 18:02:01.000000000 +0200
@@ -74,11 +74,12 @@ void mxc_gpio_mode(int gpio_mode)
 	__raw_writel(tmp, VA_GPIO_BASE + MXC_GIUS(port));
 
 	if (pin < 16) {
+#ifndef CONFIG_MACH_MX25
 		tmp = __raw_readl(VA_GPIO_BASE + MXC_OCR1(port));
 		tmp &= ~(3 << (pin * 2));
 		tmp |= (ocr << (pin * 2));
 		__raw_writel(tmp, VA_GPIO_BASE + MXC_OCR1(port));
-
+#endif
 		tmp = __raw_readl(VA_GPIO_BASE + MXC_ICONFA1(port));
 		tmp &= ~(3 << (pin * 2));
 		tmp |= ((gpio_mode >> GPIO_AOUT_SHIFT) & 3) << (pin * 2);
@@ -90,12 +91,12 @@ void mxc_gpio_mode(int gpio_mode)
 		__raw_writel(tmp, VA_GPIO_BASE + MXC_ICONFB1(port));
 	} else {
 		pin -= 16;
-
+#ifndef CONFIG_MACH_MX25
 		tmp = __raw_readl(VA_GPIO_BASE + MXC_OCR2(port));
 		tmp &= ~(3 << (pin * 2));
 		tmp |= (ocr << (pin * 2));
 		__raw_writel(tmp, VA_GPIO_BASE + MXC_OCR2(port));
-
+#endif
 		tmp = __raw_readl(VA_GPIO_BASE + MXC_ICONFA2(port));
 		tmp &= ~(3 << (pin * 2));
 		tmp |= ((gpio_mode >> GPIO_AOUT_SHIFT) & 3) << (pin * 2);
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/iomux-v3.c linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/iomux-v3.c
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/iomux-v3.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/iomux-v3.c	2009-06-02 18:02:02.000000000 +0200
@@ -31,7 +31,24 @@
 
 #define IOMUX_BASE	IO_ADDRESS(IOMUXC_BASE_ADDR)
 
-static unsigned long iomux_v3_pad_alloc_map[0x200 / BITS_PER_LONG];
+#ifdef CONFIG_MACH_MX25
+#define NUM_PADS	0x228
+#else
+#define NUM_PADS	0x200
+#endif
+
+static unsigned long iomux_v3_pad_alloc_map[NUM_PADS / BITS_PER_LONG];
+
+static inline int mxc_iomux_v3_pad_offset(struct pad_desc *pad)
+{
+	int pad_ofs;
+	if (cpu_is_mx25())
+		pad_ofs = pad->mux_ctrl_ofs;
+	else
+		pad_ofs = pad->pad_ctrl_ofs;
+	BUG_ON((pad_ofs >> 7) >= ARRAY_SIZE(iomux_v3_pad_alloc_map));
+	return pad_ofs;
+}
 
 /*
  * setups a single pin:
@@ -40,7 +57,7 @@ static unsigned long iomux_v3_pad_alloc_
  */
 int mxc_iomux_v3_setup_pad(struct pad_desc *pad)
 {
-	unsigned int pad_ofs = pad->pad_ctrl_ofs;
+	unsigned int pad_ofs = mxc_iomux_v3_pad_offset(pad);
 
 	if (test_and_set_bit(pad_ofs >> 2, iomux_v3_pad_alloc_map))
 		return -EBUSY;
@@ -65,8 +82,10 @@ int mxc_iomux_v3_setup_multiple_pads(str
 
 	for (i = 0; i < count; i++) {
 		ret = mxc_iomux_v3_setup_pad(p);
-		if (ret)
+		if (ret) {
+			printk(KERN_ERR "Failed to setup PAD[%d]: %d\n", i, ret);
 			goto setup_error;
+		}
 		p++;
 	}
 	return 0;
@@ -79,7 +98,7 @@ EXPORT_SYMBOL(mxc_iomux_v3_setup_multipl
 
 void mxc_iomux_v3_release_pad(struct pad_desc *pad)
 {
-	unsigned int pad_ofs = pad->pad_ctrl_ofs;
+	unsigned int pad_ofs = mxc_iomux_v3_pad_offset(pad);
 
 	clear_bit(pad_ofs >> 2, iomux_v3_pad_alloc_map);
 }
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/pwm.c linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/pwm.c
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/pwm.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/pwm.c	2009-06-02 18:02:02.000000000 +0200
@@ -55,7 +55,7 @@ int pwm_config(struct pwm_device *pwm, i
 	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
 		return -EINVAL;
 
-	if (cpu_is_mx27() || cpu_is_mx3()) {
+	if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25()) {
 		unsigned long long c;
 		unsigned long period_cycles, duty_cycles, prescale;
 		c = clk_get_rate(pwm->clk);
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/spba.c linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/spba.c
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/spba.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/spba.c	2009-06-02 18:02:03.000000000 +0200
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm/io.h>
+#include <mach/hardware.h>
+#include <mach/spba.h>
+
+/*!
+ * @file plat-mxc/spba.c
+ *
+ * @brief This file contains the SPBA API implementation details.
+ *
+ * @ingroup SPBA
+ */
+
+static DEFINE_SPINLOCK(spba_lock);
+
+#define SPBA_MASTER_MIN                 1
+#define SPBA_MASTER_MAX                 7
+
+/*!
+ * the base addresses for the SPBA modules
+ */
+static unsigned long spba_base = (unsigned long)IO_ADDRESS(SPBA_CTRL_BASE_ADDR);
+
+/*!
+ * SPBA clock
+ */
+static struct clk *spba_clk;
+/*!
+ * This function allows the three masters (A, B, C) to take ownership of a
+ * shared peripheral.
+ *
+ * @param  mod          specified module as defined in \b enum \b #spba_module
+ * @param  master       one of more (or-ed together) masters as defined in \b enum \b #spba_masters
+ *
+ * @return 0 if successful; a negative errno value otherwise.
+ */
+int spba_take_ownership(int mod, int master)
+{
+	unsigned long spba_flags;
+	int rtn_val = -EIO;
+
+	if (master < SPBA_MASTER_MIN || master > SPBA_MASTER_MAX) {
+		printk("%s() invalid master %d\n", __FUNCTION__, master);
+		return -EINVAL;
+	}
+
+	if (spba_clk == NULL) {
+		spba_clk = clk_get(NULL, "spba");
+		if (IS_ERR(spba_clk)) {
+			int ret = PTR_ERR(spba_clk);
+
+			spba_clk = NULL;
+			return ret;
+		}
+	}
+	clk_enable(spba_clk);
+
+	spin_lock_irqsave(&spba_lock, spba_flags);
+	__raw_writel(master, spba_base + mod);
+
+	if ((__raw_readl(spba_base + mod) & MXC_SPBA_RAR_MASK) == master) {
+		rtn_val = 0;
+	}
+
+	spin_unlock_irqrestore(&spba_lock, spba_flags);
+
+	clk_disable(spba_clk);
+	return rtn_val;
+}
+
+/*!
+ * This function releases the ownership for a shared peripheral.
+ *
+ * @param  mod          specified module as defined in \b enum \b #spba_module
+ * @param  master       one of more (or-ed together) masters as defined in \b enum \b #spba_masters
+ *
+ * @return 0 if successful; a negativ errno value otherwise.
+ */
+int spba_rel_ownership(int mod, int master)
+{
+	unsigned long spba_flags;
+	volatile unsigned long rar;
+
+	if (master < SPBA_MASTER_MIN || master > SPBA_MASTER_MAX) {
+		printk("%s() invalid master %d\n", __FUNCTION__, master);
+		return -EINVAL;
+	}
+
+	if (spba_clk == NULL) {
+		spba_clk = clk_get(NULL, "spba");
+		if (IS_ERR(spba_clk)) {
+			int ret = PTR_ERR(spba_clk);
+			spba_clk = NULL;
+			return ret;
+		}
+	}
+	clk_enable(spba_clk);
+
+	if ((__raw_readl(spba_base + mod) & master) == 0) {
+		clk_disable(spba_clk);
+		return -EBUSY;	/* does not own it */
+	}
+
+	spin_lock_irqsave(&spba_lock, spba_flags);
+
+	/* Since only the last 3 bits are writeable, doesn't need to mask off
+	   bits 31-3 */
+	rar = __raw_readl(spba_base + mod) & (~master);
+	__raw_writel(rar, spba_base + mod);
+
+	if ((__raw_readl(spba_base + mod) & master) != 0) {
+		spin_unlock_irqrestore(&spba_lock, spba_flags);
+		clk_disable(spba_clk);
+		return -EIO;
+	}
+	spin_unlock_irqrestore(&spba_lock, spba_flags);
+
+	clk_disable(spba_clk);
+	return 0;
+}
+
+EXPORT_SYMBOL(spba_take_ownership);
+EXPORT_SYMBOL(spba_rel_ownership);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("SPBA");
+MODULE_LICENSE("GPL");
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/system.c linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/system.c
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/system.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/system.c	2009-06-29 10:49:32.000000000 +0200
@@ -21,6 +21,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/err.h>
@@ -43,14 +44,6 @@
  */
 void arch_reset(char mode, const char *cmd)
 {
-	if (!cpu_is_mx1()) {
-		struct clk *clk;
-
-		clk = clk_get_sys("imx-wdt.0", NULL);
-		if (!IS_ERR(clk))
-			clk_enable(clk);
-	}
-
 	/* Assert SRS signal */
 	__raw_writew(WDOG_WCR_ENABLE, WDOG_WCR_REG);
 
@@ -65,3 +58,22 @@ void arch_reset(char mode, const char *c
 	/* we'll take a jump through zero as a poor second */
 	cpu_reset(0);
 }
+
+static int mxc_wdt_init(void)
+{
+	struct clk *wdt_clk;
+
+	if (cpu_is_mx1())
+		return 0;
+
+	wdt_clk = clk_get_sys("imx-wdt.0", NULL);
+	if (IS_ERR(wdt_clk)) {
+		printk(KERN_ERR "%s: Failed to get imx-wdt.0 clk: %ld\n",
+		       __FUNCTION__, PTR_ERR(wdt_clk));
+		return PTR_ERR(wdt_clk);
+	}
+	clk_enable(wdt_clk);
+	clk_put(wdt_clk);
+	return 0;
+}
+arch_initcall(mxc_wdt_init);
diff -purN linux-2.6.30-rc4-git/arch/arm/plat-mxc/time.c linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/time.c
--- linux-2.6.30-rc4-git/arch/arm/plat-mxc/time.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/plat-mxc/time.c	2009-07-06 14:12:36.000000000 +0200
@@ -66,7 +66,7 @@ static inline void gpt_irq_disable(void)
 {
 	unsigned int tmp;
 
-	if (cpu_is_mx3())
+	if (cpu_is_mx3() || cpu_is_mx25())
 		__raw_writel(0, timer_base + MX3_IR);
 	else {
 		tmp = __raw_readl(timer_base + MXC_TCTL);
@@ -76,7 +76,7 @@ static inline void gpt_irq_disable(void)
 
 static inline void gpt_irq_enable(void)
 {
-	if (cpu_is_mx3())
+	if (cpu_is_mx3() || cpu_is_mx25())
 		__raw_writel(1<<0, timer_base + MX3_IR);
 	else {
 		__raw_writel(__raw_readl(timer_base + MXC_TCTL) | MX1_2_TCTL_IRQEN,
@@ -88,9 +88,9 @@ static void gpt_irq_acknowledge(void)
 {
 	if (cpu_is_mx1())
 		__raw_writel(0, timer_base + MX1_2_TSTAT);
-	if (cpu_is_mx2())
+	if (cpu_is_mx2() && !cpu_is_mx25())
 		__raw_writel(MX2_TSTAT_CAPT | MX2_TSTAT_COMP, timer_base + MX1_2_TSTAT);
-	if (cpu_is_mx3())
+	if (cpu_is_mx3() || cpu_is_mx25())
 		__raw_writel(MX3_TSTAT_OF1, timer_base + MX3_TSTAT);
 }
 
@@ -117,7 +117,7 @@ static int __init mxc_clocksource_init(s
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
-	if (cpu_is_mx3())
+	if (cpu_is_mx3() || cpu_is_mx25())
 		clocksource_mxc.read = mx3_get_cycles;
 
 	clocksource_mxc.mult = clocksource_hz2mult(c,
@@ -180,7 +180,7 @@ static void mxc_set_mode(enum clock_even
 
 	if (mode != clockevent_mode) {
 		/* Set event time into far-far future */
-		if (cpu_is_mx3())
+		if (cpu_is_mx3() || cpu_is_mx25())
 			__raw_writel(__raw_readl(timer_base + MX3_TCN) - 3,
 					timer_base + MX3_TCMP);
 		else
@@ -233,7 +233,7 @@ static irqreturn_t mxc_timer_interrupt(i
 	struct clock_event_device *evt = &clockevent_mxc;
 	uint32_t tstat;
 
-	if (cpu_is_mx3())
+	if (cpu_is_mx3() || cpu_is_mx25())
 		tstat = __raw_readl(timer_base + MX3_TSTAT);
 	else
 		tstat = __raw_readl(timer_base + MX1_2_TSTAT);
@@ -264,7 +264,7 @@ static int __init mxc_clockevent_init(st
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
-	if (cpu_is_mx3())
+	if (cpu_is_mx3() || cpu_is_mx25())
 		clockevent_mxc.set_next_event = mx3_set_next_event;
 
 	clockevent_mxc.mult = div_sc(c, NSEC_PER_SEC,
@@ -313,7 +313,7 @@ void __init mxc_timer_init(struct clk *t
 	__raw_writel(0, timer_base + MXC_TCTL);
 	__raw_writel(0, timer_base + MXC_TPRER); /* see datasheet note */
 
-	if (cpu_is_mx3())
+	if (cpu_is_mx3() || cpu_is_mx25())
 		tctl_val = MX3_TCTL_CLK_IPG | MX3_TCTL_FRR | MX3_TCTL_WAITEN | MXC_TCTL_TEN;
 	else
 		tctl_val = MX1_2_TCTL_FRR | MX1_2_TCTL_CLK_PCLK1 | MXC_TCTL_TEN;
diff -purN linux-2.6.30-rc4-git/arch/arm/tools/mach-types linux-2.6.30-rc4-karo3/arch/arm/tools/mach-types
--- linux-2.6.30-rc4-git/arch/arm/tools/mach-types	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/arch/arm/tools/mach-types	2009-06-02 18:02:54.000000000 +0200
@@ -12,7 +12,7 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Mon Mar 23 20:09:01 2009
+# Last update: Mon Apr 20 10:31:38 2009
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
@@ -1721,7 +1721,7 @@ sapphire		MACH_SAPPHIRE		SAPPHIRE		1729
 csb637xo		MACH_CSB637XO		CSB637XO		1730
 evisiong		MACH_EVISIONG		EVISIONG		1731
 stmp37xx		MACH_STMP37XX		STMP37XX		1732
-stmp378x		MACH_STMP38XX		STMP38XX		1733
+stmp378x		MACH_STMP378X		STMP378X		1733
 tnt			MACH_TNT		TNT			1734
 tbxt			MACH_TBXT		TBXT			1735
 playmate		MACH_PLAYMATE		PLAYMATE		1736
@@ -2132,3 +2132,41 @@ apollo			MACH_APOLLO		APOLLO			2141
 at91cap9stk		MACH_AT91CAP9STK	AT91CAP9STK		2142
 spc300			MACH_SPC300		SPC300			2143
 eko			MACH_EKO		EKO			2144
+ccw9m2443		MACH_CCW9M2443		CCW9M2443		2145
+ccw9m2443js		MACH_CCW9M2443JS	CCW9M2443JS		2146
+m2m_router_device	MACH_M2M_ROUTER_DEVICE	M2M_ROUTER_DEVICE	2147
+str9104nas		MACH_STAR9104NAS	STAR9104NAS		2148
+pca100			MACH_PCA100		PCA100			2149
+z3_dm365_mod_01		MACH_Z3_DM365_MOD_01	Z3_DM365_MOD_01		2150
+hipox			MACH_HIPOX		HIPOX			2151
+omap3_piteds		MACH_OMAP3_PITEDS	OMAP3_PITEDS		2152
+bm150r			MACH_BM150R		BM150R			2153
+tbone			MACH_TBONE		TBONE			2154
+merlin			MACH_MERLIN		MERLIN			2155
+falcon			MACH_FALCON		FALCON			2156
+davinci_da850_evm	MACH_DAVINCI_DA850_EVM	DAVINCI_DA850_EVM	2157
+s5p6440			MACH_S5P6440		S5P6440			2158
+at91sam9g10ek		MACH_AT91SAM9G10EK	AT91SAM9G10EK		2159
+omap_4430sdp		MACH_OMAP_4430SDP	OMAP_4430SDP		2160
+lpc313x			MACH_LPC313X		LPC313X			2161
+magx_zn5		MACH_MAGX_ZN5		MAGX_ZN5		2162
+magx_em30		MACH_MAGX_EM30		MAGX_EM30		2163
+magx_ve66		MACH_MAGX_VE66		MAGX_VE66		2164
+meesc			MACH_MEESC		MEESC			2165
+otc570			MACH_OTC570		OTC570			2166
+bcu2412			MACH_BCU2412		BCU2412			2167
+beacon			MACH_BEACON		BEACON			2168
+actia_tgw		MACH_ACTIA_TGW		ACTIA_TGW		2169
+e4430			MACH_E4430		E4430			2170
+ql300			MACH_QL300		QL300			2171
+btmavb101		MACH_BTMAVB101		BTMAVB101		2172
+btmawb101		MACH_BTMAWB101		BTMAWB101		2173
+sq201			MACH_SQ201		SQ201			2174
+quatro45xx		MACH_QUATRO45XX		QUATRO45XX		2175
+openpad			MACH_OPENPAD		OPENPAD			2176
+tx25			MACH_TX25		TX25			2177
+omap3_torpedo		MACH_OMAP3_TORPEDO	OMAP3_TORPEDO		2178
+htcraphael_k		MACH_HTCRAPHAEL_K	HTCRAPHAEL_K		2179
+pxa255			MACH_PXA255		PXA255			2180
+lal43			MACH_LAL43		LAL43			2181
+htcraphael_cdma500	MACH_HTCRAPHAEL_CDMA500	HTCRAPHAEL_CDMA500	2182
diff -purN linux-2.6.30-rc4-git/drivers/input/touchscreen/Kconfig linux-2.6.30-rc4-karo3/drivers/input/touchscreen/Kconfig
--- linux-2.6.30-rc4-git/drivers/input/touchscreen/Kconfig	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/input/touchscreen/Kconfig	2009-06-23 13:33:58.000000000 +0200
@@ -287,6 +287,18 @@ config TOUCHSCREEN_ATMEL_TSADCC
 	  To compile this driver as a module, choose M here: the
 	  module will be called atmel_tsadcc.
 
+config TOUCHSCREEN_MXC_TSADCC
+	tristate "i.MX25 Touchscreen Interface"
+	depends on MACH_MX25
+	help
+	  Say Y here if you have a 4-wire touchscreen connected to the
+          ADC Controller on your Freescale i.MX25 SoC.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atmel_tsadcc.
+
 config TOUCHSCREEN_UCB1400
 	tristate "Philips UCB1400 touchscreen"
 	depends on AC97_BUS
diff -purN linux-2.6.30-rc4-git/drivers/input/touchscreen/Makefile linux-2.6.30-rc4-karo3/drivers/input/touchscreen/Makefile
--- linux-2.6.30-rc4-git/drivers/input/touchscreen/Makefile	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/input/touchscreen/Makefile	2009-06-23 13:33:59.000000000 +0200
@@ -16,19 +16,20 @@ obj-$(CONFIG_TOUCHSCREEN_GUNZE)		+= gunz
 obj-$(CONFIG_TOUCHSCREEN_ELO)		+= elo.o
 obj-$(CONFIG_TOUCHSCREEN_FUJITSU)	+= fujitsu_ts.o
 obj-$(CONFIG_TOUCHSCREEN_INEXIO)	+= inexio.o
-obj-$(CONFIG_TOUCHSCREEN_MIGOR)		+= migor_ts.o
-obj-$(CONFIG_TOUCHSCREEN_MTOUCH)	+= mtouch.o
-obj-$(CONFIG_TOUCHSCREEN_MK712)		+= mk712.o
 obj-$(CONFIG_TOUCHSCREEN_HP600)		+= hp680_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_HP7XX)		+= jornada720_ts.o
 obj-$(CONFIG_TOUCHSCREEN_HTCPEN)	+= htcpen.o
-obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
+obj-$(CONFIG_TOUCHSCREEN_MIGOR)		+= migor_ts.o
+obj-$(CONFIG_TOUCHSCREEN_MTOUCH)	+= mtouch.o
+obj-$(CONFIG_TOUCHSCREEN_MK712)		+= mk712.o
+obj-$(CONFIG_TOUCHSCREEN_MXC_TSADCC)	+= mxc_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o
 obj-$(CONFIG_TOUCHSCREEN_TSC2007)	+= tsc2007.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)	+= ucb1400_ts.o
+obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001)	+= wacom_w8001.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX)	+= wm97xx-ts.o
 obj-$(CONFIG_TOUCHSCREEN_DA9034)	+= da9034-ts.o
diff -purN linux-2.6.30-rc4-git/drivers/input/touchscreen/mxc_tsadcc.c linux-2.6.30-rc4-karo3/drivers/input/touchscreen/mxc_tsadcc.c
--- linux-2.6.30-rc4-git/drivers/input/touchscreen/mxc_tsadcc.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/drivers/input/touchscreen/mxc_tsadcc.c	2009-07-01 11:27:20.000000000 +0200
@@ -0,0 +1,897 @@
+/*
+ *  Freescale i.MX25 Touch Screen Driver
+ *
+ *  Copyright (c) 2009 Lothar Wassmann <LW@KARO-electronics.de>
+ *
+ * Based on atmel_tsadcc.c
+ *  Copyright (c) 2008 ATMEL et. al.
+ * and code from Freescale BSP
+ *
+ *  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/err.h>
+#include <linux/input.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <mach/mxc_tsadcc.h>
+
+#include "mxc_tsadcc.h"
+
+#define TSC_NUM_SAMPLES		1
+#define ADC_NUM_SAMPLES		1
+
+#ifdef DEBUG
+static int debug = 4;
+#define dbg_lvl(n)	((n) < debug)
+module_param(debug, int, S_IRUGO | S_IWUSR);
+
+#define DBG(lvl, fmt...)	do { if (dbg_lvl(lvl)) printk(KERN_DEBUG fmt); } while (0)
+#else
+static int debug;
+#define dbg_lvl(n)	0
+module_param(debug, int, 0);
+
+#define DBG(lvl, fmt...)	do { } while (0)
+#endif
+
+#define DEFAULT_ADC_CLOCK	1666667
+#define DEFAULT_RX_VALUE	360
+
+//#define REPORT_PRESSURE
+
+struct mxc_tsadcc_fifo_data {
+	unsigned int id:4,
+		data:12;
+};
+
+/* The layout of this structure depends on the setup created by mxc_tsadcc_config() */
+struct mxc_tsadcc_tsc_data {
+	struct mxc_tsadcc_fifo_data pendown[TSC_NUM_SAMPLES];
+	struct mxc_tsadcc_fifo_data pos_x[TSC_NUM_SAMPLES];
+	struct mxc_tsadcc_fifo_data pos_y[TSC_NUM_SAMPLES];
+#ifdef REPORT_PRESSURE
+	struct mxc_tsadcc_fifo_data yn[TSC_NUM_SAMPLES];
+	struct mxc_tsadcc_fifo_data xp[TSC_NUM_SAMPLES];
+#endif
+	struct mxc_tsadcc_fifo_data pendown2[TSC_NUM_SAMPLES];
+};
+
+struct mxc_tsadcc_adc_data {
+	struct mxc_tsadcc_fifo_data data[ADC_NUM_SAMPLES];
+};
+
+struct mxc_tsadcc {
+	struct input_dev	*input;
+	char			phys[32];
+	void __iomem		*reg_base;
+	struct clk		*clk;
+	int			irq;
+	struct work_struct	work;
+	struct timer_list	timer;
+	wait_queue_head_t	wq;
+	unsigned int		pendown:1,
+				clk_enabled:1,
+				attrs:1,
+				valid_measure:1;
+	mxc_tsc_mode		tsc_mode;
+	struct mxc_tsadcc_tsc_data *tsc_data;
+	struct mxc_tsadcc_adc_data *adc_data;
+	unsigned int		r_xplate;
+
+	struct mutex		convert_mutex;
+	unsigned short		pressure;
+	unsigned short		prev_absx;
+	unsigned short		prev_absy;
+};
+
+#ifdef DEBUG
+#define mxc_tsadcc_read(s,reg)		_mxc_tsadcc_read(s,reg,#reg,__FUNCTION__)
+#define mxc_tsadcc_write(s,reg,val)	_mxc_tsadcc_write(s,reg,val,#reg,__FUNCTION__)
+
+static inline unsigned long _mxc_tsadcc_read(struct mxc_tsadcc *ts_dev, int reg,
+				   const char *name, const char *fn)
+{
+	unsigned long val = __raw_readl(ts_dev->reg_base + reg);
+	DBG(3, "%s: Read %08lx from %s\n", fn, val, name);
+	return val;
+}
+
+static inline void _mxc_tsadcc_write(struct mxc_tsadcc *ts_dev, int reg, unsigned long val,
+				     const char *name, const char *fn)
+{
+	__raw_writel(val, ts_dev->reg_base + reg);
+	DBG(3, "%s: Wrote %08lx to %s\n", fn, val, name);
+}
+#else
+static inline unsigned long mxc_tsadcc_read(struct mxc_tsadcc *ts_dev, int reg)
+{
+	return __raw_readl(ts_dev->reg_base + reg);
+}
+static inline void mxc_tsadcc_write(struct mxc_tsadcc *ts_dev, int reg, unsigned long val)
+{
+	__raw_writel(val, ts_dev->reg_base + reg);
+}
+#endif
+
+static void tsc_clk_enable(struct mxc_tsadcc *ts_dev)
+{
+	if (!ts_dev->clk_enabled) {
+		unsigned long reg;
+		clk_enable(ts_dev->clk);
+
+		reg = mxc_tsadcc_read(ts_dev, TGCR);
+		reg |= TGCR_IPG_CLK_EN;
+		mxc_tsadcc_write(ts_dev, TGCR, reg);
+		ts_dev->clk_enabled = 1;
+	}
+}
+
+static void tsc_clk_disable(struct mxc_tsadcc *ts_dev)
+{
+	if (ts_dev->clk_enabled) {
+		unsigned long reg;
+
+		reg = mxc_tsadcc_read(ts_dev, TGCR);
+		reg &= ~TGCR_IPG_CLK_EN;
+		mxc_tsadcc_write(ts_dev, TGCR, reg);
+
+		clk_disable(ts_dev->clk);
+		ts_dev->clk_enabled = 0;
+	}
+}
+
+static inline int mxc_tsadcc_pendown(struct mxc_tsadcc *ts_dev)
+{
+	return ts_dev->pendown;
+}
+
+static int mxc_tsadcc_read_adc(struct mxc_tsadcc *ts_dev, int chan)
+{
+	int ret = 1;
+	unsigned long reg;
+	unsigned int data_num = 0;
+	int i;
+	union {
+		unsigned int fifo[sizeof(struct mxc_tsadcc_tsc_data) / sizeof(int)];
+		struct mxc_tsadcc_tsc_data data;
+	} *fifo_data = (void *)ts_dev->adc_data;
+	struct mxc_tsadcc_adc_data *adc_data = ts_dev->adc_data;
+	int lastitemid = 0;
+	struct input_dev *input_dev = ts_dev->input;
+	long timeout = msecs_to_jiffies(1 * ADC_NUM_SAMPLES);
+
+	mutex_lock(&ts_dev->convert_mutex);
+	reg = (0xf << CQCR_FIFOWATERMARK_SHIFT) |
+		(lastitemid << CQCR_LAST_ITEM_ID_SHIFT) | CQCR_QSM_FQS;
+	mxc_tsadcc_write(ts_dev, GCQCR, reg);
+
+	reg = ((ADC_NUM_SAMPLES - 1) << CC_NOS_SHIFT) |
+		(16 << CC_SETTLING_TIME_SHIFT) |
+		CC_YPLLSW_OFF | CC_XNURSW_OFF | CC_XPULSW |
+		CC_SELREFP_INT | chan | CC_SEL_REFN_AGND;
+	mxc_tsadcc_write(ts_dev, GCC0, reg);
+
+	memset(adc_data, 0, sizeof(*adc_data));
+
+	reg = mxc_tsadcc_read(ts_dev, GCQCR);
+	reg |= CQCR_FQS;
+	mxc_tsadcc_write(ts_dev, GCQCR, reg);
+
+	/* enable end of conversion interrupt */
+	reg = mxc_tsadcc_read(ts_dev, GCQMR);
+	reg &= ~CQMR_EOQ_IRQ_MSK;
+	mxc_tsadcc_write(ts_dev, GCQMR, reg);
+
+	timeout = wait_event_timeout(ts_dev->wq,
+				     mxc_tsadcc_read(ts_dev, GCQSR) &
+				     CQSR_EOQ, timeout);
+	if (timeout == 0 &&
+	    !(mxc_tsadcc_read(ts_dev, GCQSR) & CQSR_EOQ)) {
+		dev_err(&input_dev->dev,
+			"Timeout waiting for data on channel %d\n",
+			chan);
+		ret = -ETIME;
+		goto exit;
+	}
+
+	reg = mxc_tsadcc_read(ts_dev, GCQCR);
+	reg &= ~CQCR_FQS;
+	mxc_tsadcc_write(ts_dev, GCQCR, reg);
+	reg = mxc_tsadcc_read(ts_dev, GCQSR);
+
+	/* clear interrupt status bit */
+	reg = CQSR_EOQ;
+	mxc_tsadcc_write(ts_dev, GCQSR, reg);
+
+	while (!(mxc_tsadcc_read(ts_dev, GCQSR) & CQSR_EMPT)) {
+		BUG_ON(data_num >= ARRAY_SIZE(fifo_data->fifo));
+		reg = mxc_tsadcc_read(ts_dev, GCQFIFO);
+		fifo_data->fifo[data_num] = reg;
+		data_num++;
+	}
+	DBG(0, "%s: Read %u words from fifo\n", __FUNCTION__, data_num);
+	for (i = 0; i < data_num; i++) {
+		DBG(0, "%s: data[%d]=%03x ID %d\n", __FUNCTION__, i,
+		    adc_data->data[i].data, adc_data->data[i].id);
+	}
+ exit:
+	mutex_unlock(&ts_dev->convert_mutex);
+
+	return ret;
+}
+
+struct mxc_tsadcc_attr {
+	struct device_attribute attr;
+	unsigned int reg;
+};
+
+#define to_mxc_tsadcc_attr(a)		container_of(a, struct mxc_tsadcc_attr, attr)
+
+#define MXC_TSADCC_DEV_ATTR(_name, _mode, _reg, _read, _write)	\
+	struct mxc_tsadcc_attr mxc_tsadcc_attr_##_name = {	\
+		.attr = __ATTR(_name,_mode,_read,_write),	\
+		.reg = _reg,					\
+	}
+
+static ssize_t mxc_tsadcc_attr_get(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	ssize_t ret = -EIO;
+	struct mxc_tsadcc *ts_dev = dev_get_drvdata(dev);
+	struct mxc_tsadcc_attr *mxc_tsadcc_attr = to_mxc_tsadcc_attr(attr);
+
+	if (mxc_tsadcc_read_adc(ts_dev, mxc_tsadcc_attr->reg)) {
+		ret = sprintf(buf, "0x%04x\n", ts_dev->adc_data->data[0].data);
+	}
+	return ret;
+}
+
+#if 0
+static ssize_t mxc_tsadcc_attr_set(struct device *dev, struct device_attribute *attr,
+			       const char *buf, size_t count)
+{
+	ssize_t ret;
+	struct mxc_tsadcc *ts_dev = dev_get_drvdata(dev);
+	struct mxc_tsadcc_attr *mxc_tsadcc_attr = to_mxc_tsadcc_attr(attr);
+	unsigned long val = simple_strtoul(buf, NULL, 0);
+
+	mxc_tsadcc_write(ts_dev, mxc_tsadcc_attr->reg, val);
+	return count;
+}
+#endif
+
+MXC_TSADCC_DEV_ATTR(inaux0, S_IRUGO, CC_SELIN_INAUX0, mxc_tsadcc_attr_get, NULL);
+MXC_TSADCC_DEV_ATTR(inaux1, S_IRUGO, CC_SELIN_INAUX1, mxc_tsadcc_attr_get, NULL);
+MXC_TSADCC_DEV_ATTR(inaux2, S_IRUGO, CC_SELIN_INAUX2, mxc_tsadcc_attr_get, NULL);
+
+static struct attribute *mxc_tsadcc_attrs[] = {
+	&mxc_tsadcc_attr_inaux0.attr.attr,
+	&mxc_tsadcc_attr_inaux1.attr.attr,
+	&mxc_tsadcc_attr_inaux2.attr.attr,
+	NULL
+};
+
+static const struct attribute_group mxc_tsadcc_attr_group = {
+	.attrs = mxc_tsadcc_attrs,
+};
+
+static int mxc_tsadcc_read_ts(struct mxc_tsadcc *ts_dev, int force)
+{
+	int ret;
+	unsigned long reg;
+	unsigned int data_num = 0;
+	union {
+		unsigned int fifo[sizeof(struct mxc_tsadcc_tsc_data) / sizeof(int)];
+		struct mxc_tsadcc_tsc_data data;
+	} *fifo_data = (void *)ts_dev->tsc_data;
+	struct mxc_tsadcc_tsc_data *tsc_data = ts_dev->tsc_data;
+	struct input_dev *input_dev = ts_dev->input;
+	long timeout = msecs_to_jiffies(1 * TSC_NUM_SAMPLES);
+
+	mutex_lock(&ts_dev->convert_mutex);
+	memset(tsc_data, 0, sizeof(*tsc_data));
+	if (force) {
+		reg = (0x1 << CC_YPLLSW_SHIFT) | (0x1 << CC_XNURSW_SHIFT) |
+		      CC_XPULSW;
+		mxc_tsadcc_write(ts_dev, TICR, reg);
+
+		/* FQS */
+		reg = mxc_tsadcc_read(ts_dev, TCQCR);
+		reg &= ~CQCR_QSM_MASK;
+		reg |= CQCR_QSM_FQS;
+		mxc_tsadcc_write(ts_dev, TCQCR, reg);
+		reg = mxc_tsadcc_read(ts_dev, TCQCR);
+		reg |= CQCR_FQS;
+		mxc_tsadcc_write(ts_dev, TCQCR, reg);
+
+		timeout = wait_event_timeout(ts_dev->wq,
+					     mxc_tsadcc_read(ts_dev, TCQSR) &
+					     CQSR_EOQ, timeout);
+		if (timeout == 0 &&
+		    !(mxc_tsadcc_read(ts_dev, TCQSR) & CQSR_EOQ)) {
+			dev_err(&input_dev->dev,
+				"Timeout waiting for TSC data\n");
+			ret = -ETIME;
+			goto exit;
+		}
+
+		/* stop FQS */
+		reg = mxc_tsadcc_read(ts_dev, TCQCR);
+		reg &= ~CQCR_QSM_MASK;
+		mxc_tsadcc_write(ts_dev, TCQCR, reg);
+		reg = mxc_tsadcc_read(ts_dev, TCQCR);
+		reg &= ~CQCR_FQS;
+		mxc_tsadcc_write(ts_dev, TCQCR, reg);
+
+		/* clear status bit */
+		reg = mxc_tsadcc_read(ts_dev, TCQSR);
+		reg = CQSR_EOQ;
+		mxc_tsadcc_write(ts_dev, TCQSR, reg);
+	} else {
+		/* Config idle for 4-wire */
+		reg = TSC_4WIRE_TOUCH_DETECT;
+		mxc_tsadcc_write(ts_dev, TICR, reg);
+
+		/* Pen interrupt starts new conversion queue */
+		reg = mxc_tsadcc_read(ts_dev, TCQCR);
+		reg &= ~CQCR_QSM_MASK;
+		reg |= CQCR_QSM_PEN;
+		mxc_tsadcc_write(ts_dev, TCQCR, reg);
+
+		/* PDEN and PDBEN */
+		reg = mxc_tsadcc_read(ts_dev, TGCR);
+		reg |= (TGCR_PDB_EN | TGCR_PD_EN);
+		mxc_tsadcc_write(ts_dev, TGCR, reg);
+
+		wait_event_timeout(ts_dev->wq,
+				   mxc_tsadcc_read(ts_dev, TCQSR) &
+				   CQSR_EOQ, timeout);
+		if (timeout == 0 &&
+		    !(mxc_tsadcc_read(ts_dev, TCQSR) & CQSR_EOQ)) {
+			dev_err(&input_dev->dev,
+				"Timeout waiting for TSC data\n");
+			ret = -ETIME;
+			goto exit;
+		}
+
+		/* stop the conversion */
+		reg = mxc_tsadcc_read(ts_dev, TCQCR);
+		reg &= ~CQCR_QSM_MASK;
+		mxc_tsadcc_write(ts_dev, TCQCR, reg);
+
+		/* clear interrupt status flags */
+		reg = CQSR_PD | CQSR_EOQ;
+		mxc_tsadcc_write(ts_dev, TCQSR, reg);
+
+		/* change configuration for FQS mode */
+		reg = (0x1 << CC_YPLLSW_SHIFT) | (0x1 << CC_XNURSW_SHIFT) |
+		      CC_XPULSW;
+		mxc_tsadcc_write(ts_dev, TICR, reg);
+	}
+
+	while (!(mxc_tsadcc_read(ts_dev, TCQSR) & CQSR_EMPT)) {
+		BUG_ON(data_num >= ARRAY_SIZE(fifo_data->fifo));
+		reg = mxc_tsadcc_read(ts_dev, TCQFIFO);
+		fifo_data->fifo[data_num] = reg;
+		data_num++;
+	}
+	DBG(0, "%s: Read %u words from fifo\n", __FUNCTION__, data_num);
+
+	ret = tsc_data->pendown[0].data <= 0x600 &&
+		tsc_data->pendown2[0].data <= 0x600;
+
+	if (ret) {
+		DBG(0, "%s: pos_x=%03x pos_y=%03x\n",
+		    __FUNCTION__, tsc_data->pos_x[0].data,
+		    tsc_data->pos_y[0].data);
+#ifdef REPORT_PRESSURE
+		DBG(0, "%s: pos_x=%03x pos_y=%03x xp=%03x yn=%03x\n",
+		    __FUNCTION__, tsc_data->xp[0].data,
+		    tsc_data->yn[0].data);
+#endif
+		if (/*(mxc_tsadcc_read(ts_dev, TCQSR) & CQSR_PD) && */
+		    tsc_data->pos_x[0].data &&
+		    tsc_data->pos_x[1].data &&
+		    tsc_data->pos_x[2].data) {
+#ifdef REPORT_PRESSURE
+			ts_dev->pressure = ts_dev->r_xplate *
+				(tsc_data->pos_x[0].data / 4096) *
+				((tsc_data->yn[0].data - tsc_data->xp[0].data) /
+				 tsc_data->xp[0].data);
+#else
+			ts_dev->pressure = 4095;
+#endif
+			DBG(0, "%s: Detected PEN DOWN with pressure %03x\n",
+			    __FUNCTION__, ts_dev->pressure);
+			ts_dev->pendown = 1;
+		} else {
+			DBG(0, "%s: Detected PEN UP\n", __FUNCTION__);
+			ts_dev->pendown = 0;
+		}
+	} else {
+		DBG(0, "%s: Discarding measurement\n", __FUNCTION__);
+		ts_dev->pendown = 0;
+	}
+ exit:
+	mutex_unlock(&ts_dev->convert_mutex);
+
+	return ret;
+}
+
+static inline void mxc_tsadcc_enable_pendown(struct mxc_tsadcc *ts_dev)
+{
+	unsigned long reg;
+
+	/* Config idle for 4-wire */
+	reg = TSC_4WIRE_TOUCH_DETECT;
+	mxc_tsadcc_write(ts_dev, TICR, reg);
+
+	DBG(0, "%s: Enable PD detect\n", __FUNCTION__);
+	reg = mxc_tsadcc_read(ts_dev, TGCR);
+	reg |= TGCR_PD_EN;
+	mxc_tsadcc_write(ts_dev, TGCR, reg);
+}
+
+static void mxc_tsadcc_work(struct work_struct *w)
+{
+	struct mxc_tsadcc *ts_dev = container_of(w, struct mxc_tsadcc, work);
+	struct input_dev *input_dev = ts_dev->input;
+
+	if (mxc_tsadcc_read_ts(ts_dev, 1)) {
+		DBG(0, "%s: Got sample %d\n", __FUNCTION__, ts_dev->pendown);
+		if (mxc_tsadcc_pendown(ts_dev)) {
+			if (!ts_dev->valid_measure) {
+				ts_dev->valid_measure = 1;
+			} else {
+				DBG(0, "%s: Reporting PD event %03x @ %03x,%03x\n",
+				    __FUNCTION__, ts_dev->pressure,
+				    ts_dev->tsc_data->pos_x[0].data,
+				    ts_dev->tsc_data->pos_y[0].data);
+
+				input_report_abs(input_dev, ABS_X,
+						 ts_dev->tsc_data->pos_x[0].data);
+				input_report_abs(input_dev, ABS_Y,
+						 ts_dev->tsc_data->pos_y[0].data);
+#ifdef REPORT_PRESSURE
+				input_report_abs(input_dev, ABS_PRESSURE,
+						 ts_dev->pressure);
+#endif
+				input_report_key(input_dev, BTN_TOUCH, 1);
+				input_sync(input_dev);
+			}
+			ts_dev->prev_absx = ts_dev->tsc_data->pos_x[0].data;
+			ts_dev->prev_absy = ts_dev->tsc_data->pos_y[0].data;
+			DBG(0, "%s: Enabling timer\n", __FUNCTION__);
+			mod_timer(&ts_dev->timer, jiffies +
+				  msecs_to_jiffies(10));
+			return;
+		}
+	}
+	if (ts_dev->valid_measure) {
+		DBG(0, "%s: Reporting PU event: %03x,%03x\n", __FUNCTION__,
+		    ts_dev->prev_absx, ts_dev->prev_absy);
+		input_report_abs(input_dev, ABS_X,
+				 ts_dev->prev_absx);
+		input_report_abs(input_dev, ABS_Y,
+				 ts_dev->prev_absy);
+#ifdef REPORT_PRESSURE
+		input_report_abs(input_dev, ABS_PRESSURE, 0);
+#endif
+		input_report_key(input_dev, BTN_TOUCH, 0);
+		input_sync(input_dev);
+	}
+	ts_dev->valid_measure = 0;
+	mxc_tsadcc_enable_pendown(ts_dev);
+}
+
+static void mxc_tsadcc_timer(unsigned long data)
+{
+	struct mxc_tsadcc *ts_dev = (void *)data;
+	schedule_work(&ts_dev->work);
+}
+
+static irqreturn_t mxc_tsadcc_interrupt(int irq, void *dev)
+{
+	struct mxc_tsadcc *ts_dev = dev;
+	//struct input_dev *input_dev = ts_dev->input;
+	unsigned long reg;
+	unsigned long status = mxc_tsadcc_read(ts_dev, TGSR);
+
+	DBG(0, "%s: TCSR= %08lx\n", __FUNCTION__, status);
+
+	if (status & TGSR_TCQ_INT) {
+		DBG(0, "%s: TCQSR=%08lx\n", __FUNCTION__,
+		    mxc_tsadcc_read(ts_dev, TCQSR));
+		reg = mxc_tsadcc_read(ts_dev, TCQSR);
+		if (reg & CQSR_PD) {
+			/* disable pen down detect */
+			DBG(0, "%s: Disable PD detect\n", __FUNCTION__);
+			reg = mxc_tsadcc_read(ts_dev, TGCR);
+			reg &= ~TGCR_PD_EN;
+			mxc_tsadcc_write(ts_dev, TGCR, reg);
+
+			/* Now schedule new measurement */
+			schedule_work(&ts_dev->work);
+		}
+	}
+	if (status & TGSR_GCQ_INT) {
+		DBG(0, "%s: GCQSR=%08lx\n", __FUNCTION__,
+		    mxc_tsadcc_read(ts_dev, GCQSR));
+		reg = mxc_tsadcc_read(ts_dev, GCQSR);
+		if (reg & CQSR_EOQ) {
+			reg = mxc_tsadcc_read(ts_dev, GCQMR);
+			reg |= CQMR_EOQ_IRQ_MSK;
+			mxc_tsadcc_write(ts_dev, GCQMR, reg);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static void mxc_tsadcc_4wire_config(struct mxc_tsadcc *ts_dev)
+{
+	unsigned long reg;
+	int lastitemid;
+
+	/* Level sense */
+	reg = mxc_tsadcc_read(ts_dev, TCQCR);
+	reg |= CQCR_PD_CFG;
+	reg |= (0xf << CQCR_FIFOWATERMARK_SHIFT);  /* watermark */
+	mxc_tsadcc_write(ts_dev, TCQCR, reg);
+
+	/* Configure 4-wire */
+	reg = TSC_4WIRE_PRECHARGE;
+	reg |= CC_IGS;
+	mxc_tsadcc_write(ts_dev, TCC0, reg);
+
+	reg = TSC_4WIRE_TOUCH_DETECT;
+	reg |= (TSC_NUM_SAMPLES - 1) << CC_NOS_SHIFT;	/* 4 samples */
+	reg |= 32 << CC_SETTLING_TIME_SHIFT;	/* it's important! */
+	mxc_tsadcc_write(ts_dev, TCC1, reg);
+
+	reg = TSC_4WIRE_X_MEASURE;
+	reg |= (TSC_NUM_SAMPLES - 1) << CC_NOS_SHIFT;	/* 4 samples */
+	reg |= 16 << CC_SETTLING_TIME_SHIFT;	/* settling time */
+	mxc_tsadcc_write(ts_dev, TCC2, reg);
+
+	reg = TSC_4WIRE_Y_MEASURE;
+	reg |= (TSC_NUM_SAMPLES - 1) << CC_NOS_SHIFT;	/* 4 samples */
+	reg |= 16 << CC_SETTLING_TIME_SHIFT;	/* settling time */
+	mxc_tsadcc_write(ts_dev, TCC3, reg);
+
+	reg = TSC_4WIRE_YN_MEASURE;
+	reg |= (TSC_NUM_SAMPLES - 1) << CC_NOS_SHIFT;	/* 4 samples */
+	reg |= 16 << CC_SETTLING_TIME_SHIFT;	/* settling time */
+	mxc_tsadcc_write(ts_dev, TCC4, reg);
+
+	reg = TSC_4WIRE_XP_MEASURE;
+	reg |= (TSC_NUM_SAMPLES - 1) << CC_NOS_SHIFT;	/* 4 samples */
+	reg |= 16 << CC_SETTLING_TIME_SHIFT;	/* settling time */
+	mxc_tsadcc_write(ts_dev, TCC5, reg);
+
+	reg = (TCQ_ITEM_TCC0 << CQ_ITEM0_SHIFT) |
+		(TCQ_ITEM_TCC1 << CQ_ITEM1_SHIFT) |
+		(TCQ_ITEM_TCC2 << CQ_ITEM2_SHIFT) |
+		(TCQ_ITEM_TCC3 << CQ_ITEM3_SHIFT) |
+		(TCQ_ITEM_TCC0 << CQ_ITEM4_SHIFT) |
+		(TCQ_ITEM_TCC1 << CQ_ITEM5_SHIFT);
+	mxc_tsadcc_write(ts_dev, TCQ_ITEM_7_0, reg);
+
+	lastitemid = 5;
+	reg = mxc_tsadcc_read(ts_dev, TCQCR);
+	reg = (reg & ~CQCR_LAST_ITEM_ID_MASK) |
+	      (lastitemid << CQCR_LAST_ITEM_ID_SHIFT);
+	mxc_tsadcc_write(ts_dev, TCQCR, reg);
+
+	/* pen down enable */
+	reg = mxc_tsadcc_read(ts_dev, TCQCR);
+	reg &= ~CQCR_PD_MSK;
+	mxc_tsadcc_write(ts_dev, TCQCR, reg);
+	reg = mxc_tsadcc_read(ts_dev, TCQMR);
+	reg &= ~CQMR_PD_IRQ_MSK;
+	mxc_tsadcc_write(ts_dev, TCQMR, reg);
+
+	/* Config idle for 4-wire */
+	reg = TSC_4WIRE_TOUCH_DETECT;
+	mxc_tsadcc_write(ts_dev, TICR, reg);
+
+	/* Pen interrupt starts new conversion queue */
+	reg = mxc_tsadcc_read(ts_dev, TCQCR);
+	reg &= ~CQCR_QSM_MASK;
+	reg |= CQCR_QSM_PEN;
+	mxc_tsadcc_write(ts_dev, TCQCR, reg);
+}
+
+static void mxc_tsadcc_config(struct platform_device *pdev)
+{
+	struct mxc_tsadcc *ts_dev = platform_get_drvdata(pdev);
+	struct mxc_tsadcc_pdata *pdata = pdev->dev.platform_data;
+	unsigned int tgcr;
+	unsigned int pdbt;
+	unsigned int pdben;
+	unsigned int intref;
+	unsigned int adc_clk = DEFAULT_ADC_CLOCK;
+	unsigned long ipg_clk;
+	unsigned int clkdiv;
+
+	if (pdata) {
+		pdbt = pdata->pen_debounce_time - 1;
+		pdben = pdata->pen_debounce_time > 0;
+		intref = !!pdata->intref;
+		if (pdata->adc_clk > 0) {
+			adc_clk = pdata->adc_clk;
+		}
+		ts_dev->r_xplate = pdata->r_xplate;
+	} else {
+		dev_dbg(&pdev->dev, "No platform_data; using defaults\n");
+		pdbt = TGCR_PDBTIME128;
+		pdben = 1;
+		intref = 1;
+	}
+	if (ts_dev->r_xplate == 0) {
+		ts_dev->r_xplate = DEFAULT_RX_VALUE;
+		DBG(0, "%s: Assuming default Rx value of %u Ohms\n",
+		    __FUNCTION__, ts_dev->r_xplate);
+	}
+	ipg_clk = clk_get_rate(ts_dev->clk);
+	dev_info(&pdev->dev, "Master clock is: %lu.%06luMHz requested ADC clock: %u.%06uMHz\n",
+		 ipg_clk / 1000000, ipg_clk % 1000000,
+		 adc_clk / 1000000, adc_clk % 1000000);
+	/*
+	 * adc_clk = ipg_clk / (2 * clkdiv + 2)
+	 * The exact formula for the clock divider would be:
+	 * clkdiv = ipg_clk / (2 * adc_clk) - 1
+	 * but we drop the '- 1' due to integer truncation
+	 * and to make sure the actual clock is always less or equal
+	 * to the designated clock.
+	*/
+	clkdiv = ipg_clk / (2 * adc_clk + 1);
+	if (clkdiv > 31) {
+		clkdiv = 31;
+		dev_warn(&pdev->dev,
+			 "cannot accomodate designated clock of %u.%06uMHz; using %lu.%06luMHz\n",
+			 adc_clk / 1000000, adc_clk % 1000000,
+			 ipg_clk / (2 * clkdiv + 2) / 1000000,
+			 ipg_clk / (2 * clkdiv + 2) % 1000000);
+	} else {
+		dev_dbg(&pdev->dev,
+			"clkdiv=%u actual ADC clock: %lu.%06luMHz\n",
+			clkdiv, ipg_clk / (2 * (clkdiv + 1)) / 1000000,
+			ipg_clk / (2 * clkdiv + 2) % 1000000);
+	}
+
+	tgcr = ((pdbt << TGCR_PDBTIME_SHIFT) & TGCR_PDBTIME_MASK) | /* pen debounce time */
+		(pdben * TGCR_PDB_EN) | /* pen debounce enable */
+		(intref * TGCR_INTREFEN) | /* pen debounce enable */
+		TGCR_POWER_SAVE | /* Switch TSC on */
+		TGCR_PD_EN |	/* Enable Pen Detect */
+		((clkdiv << TGCR_ADCCLKCFG_SHIFT) & TGCR_ADCCLKCFG_MASK);
+
+	/* reset TSC */
+	mxc_tsadcc_write(ts_dev, TGCR, TGCR_TSC_RST);
+	while (mxc_tsadcc_read(ts_dev, TGCR) & TGCR_TSC_RST) {
+		cpu_relax();
+	}
+	mxc_tsadcc_write(ts_dev, TGCR, tgcr);
+
+	mxc_tsadcc_4wire_config(ts_dev);
+	tsc_clk_enable(ts_dev);
+}
+
+static int __devinit mxc_tsadcc_probe(struct platform_device *pdev)
+{
+	int err;
+	struct mxc_tsadcc *ts_dev;
+	struct input_dev *input_dev;
+	struct resource	*res;
+	int irq;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "No mmio resource defined\n");
+		return -ENODEV;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "No IRQ assigned\n");
+		return -ENODEV;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res),
+				"mxc tsadcc regs")) {
+		return -EBUSY;
+	}
+
+	/* Allocate memory for device */
+	ts_dev = kzalloc(sizeof(struct mxc_tsadcc), GFP_KERNEL);
+	if (!ts_dev) {
+		dev_err(&pdev->dev, "Failed to allocate memory\n");
+		err = -ENOMEM;
+		goto err_release_mem;
+	}
+
+	/* allocate conversion buffers separately to prevent
+	 * cacheline alignment issues when using DMA */
+	ts_dev->tsc_data = kzalloc(sizeof(struct mxc_tsadcc_tsc_data), GFP_KERNEL);
+	ts_dev->adc_data = kzalloc(sizeof(struct mxc_tsadcc_adc_data), GFP_KERNEL);
+	if (ts_dev->tsc_data == NULL || ts_dev->adc_data == NULL) {
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+	ts_dev->irq = irq;
+	INIT_WORK(&ts_dev->work, mxc_tsadcc_work);
+	mutex_init(&ts_dev->convert_mutex);
+	setup_timer(&ts_dev->timer, mxc_tsadcc_timer, (unsigned long)ts_dev);
+	init_waitqueue_head(&ts_dev->wq);
+
+	platform_set_drvdata(pdev, ts_dev);
+
+	input_dev = input_allocate_device();
+	if (!input_dev) {
+		dev_err(&pdev->dev, "Failed to allocate input device\n");
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	ts_dev->reg_base = ioremap(res->start, resource_size(res));
+	if (!ts_dev->reg_base) {
+		dev_err(&pdev->dev, "Failed to map registers\n");
+		err = -ENOMEM;
+		goto err_free_dev;
+	}
+
+	err = request_irq(ts_dev->irq, mxc_tsadcc_interrupt, 0,
+			pdev->dev.driver->name, ts_dev);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to install irq handler: %d\n", err);
+		goto err_unmap_regs;
+	}
+
+	ts_dev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(ts_dev->clk)) {
+		dev_err(&pdev->dev, "Failed to get ts_clk\n");
+		err = PTR_ERR(ts_dev->clk);
+		goto err_free_irq;
+	}
+
+	ts_dev->input = input_dev;
+
+	snprintf(ts_dev->phys, sizeof(ts_dev->phys),
+		 "%s/input0", dev_name(&pdev->dev));
+
+	input_dev->name = "mxc touch screen controller";
+	input_dev->phys = ts_dev->phys;
+	input_dev->dev.parent = &pdev->dev;
+
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+	input_dev->absbit[0] = BIT_MASK(ABS_X) |
+		BIT_MASK(ABS_Y) |
+		BIT_MASK(ABS_PRESSURE);
+
+	input_set_abs_params(input_dev, ABS_X, 0, 0xFFF, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, 0xFFF, 0, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFFF, 0, 0);
+
+	mxc_tsadcc_config(pdev);
+
+	/* All went ok, so register to the input system */
+	err = input_register_device(input_dev);
+	if (err)
+		goto err_fail;
+
+	err = sysfs_create_group(&pdev->dev.kobj, &mxc_tsadcc_attr_group);
+	if (err) {
+		dev_warn(&pdev->dev, "Failed to create sysfs attributes: %d\n",
+			 err);
+	}
+	ts_dev->attrs = !err;
+
+	return 0;
+
+err_fail:
+	clk_disable(ts_dev->clk);
+	clk_put(ts_dev->clk);
+err_free_irq:
+	free_irq(ts_dev->irq, ts_dev);
+err_unmap_regs:
+	iounmap(ts_dev->reg_base);
+err_free_dev:
+	input_free_device(ts_dev->input);
+err_free_mem:
+	kfree(ts_dev->tsc_data);
+	kfree(ts_dev->adc_data);
+	kfree(ts_dev);
+err_release_mem:
+	release_mem_region(res->start, resource_size(res));
+	return err;
+}
+
+static int __devexit mxc_tsadcc_remove(struct platform_device *pdev)
+{
+	struct mxc_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev);
+	struct resource *res;
+
+	if (ts_dev->attrs) {
+		DBG(0, "%s: Removing sysfs attributes\n", __FUNCTION__);
+		sysfs_remove_group(&pdev->dev.kobj, &mxc_tsadcc_attr_group);
+	}
+	del_timer_sync(&ts_dev->timer);
+	input_unregister_device(ts_dev->input);
+
+	clk_disable(ts_dev->clk);
+	clk_put(ts_dev->clk);
+
+	free_irq(ts_dev->irq, ts_dev);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	iounmap(ts_dev->reg_base);
+	release_mem_region(res->start, resource_size(res));
+
+	kfree(ts_dev->tsc_data);
+	kfree(ts_dev->adc_data);
+	kfree(ts_dev);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxc_tsadcc_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+	struct mxc_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev);
+
+	if (ts_dev->clk_enabled) {
+		tsc_clk_disable(ts_dev);
+		ts_dev->clk_enabled = 1;
+	}
+	return 0;
+}
+
+static int mxc_tsadcc_resume(struct platform_device *pdev)
+{
+	struct mxc_tsadcc *ts_dev = dev_get_drvdata(&pdev->dev);
+
+	if (ts_dev->clk_enabled) {
+		ts_dev->clk_enabled = 0;
+		tsc_clk_enable(ts_dev);
+	}
+	return 0;
+}
+#else
+#define mxc_tsadcc_suspend	NULL
+#define mxc_tsadcc_resume	NULL
+#endif
+
+static struct platform_driver mxc_tsadcc_driver = {
+	.probe		= mxc_tsadcc_probe,
+	.remove		= __devexit_p(mxc_tsadcc_remove),
+	.suspend	= mxc_tsadcc_suspend,
+	.resume		= mxc_tsadcc_resume,
+	.driver		= {
+		.name	= "mxc-tsadcc",
+	},
+};
+
+static int __init mxc_tsadcc_init(void)
+{
+	return platform_driver_register(&mxc_tsadcc_driver);
+}
+
+static void __exit mxc_tsadcc_exit(void)
+{
+	platform_driver_unregister(&mxc_tsadcc_driver);
+}
+
+module_init(mxc_tsadcc_init);
+module_exit(mxc_tsadcc_exit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("i.MX25 TouchScreen Driver");
+MODULE_AUTHOR("Lothar Wassmann <LW@KARO-electronics.de>");
+
diff -purN linux-2.6.30-rc4-git/drivers/input/touchscreen/mxc_tsadcc.h linux-2.6.30-rc4-karo3/drivers/input/touchscreen/mxc_tsadcc.h
--- linux-2.6.30-rc4-git/drivers/input/touchscreen/mxc_tsadcc.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/drivers/input/touchscreen/mxc_tsadcc.h	2009-07-01 11:27:51.000000000 +0200
@@ -0,0 +1,243 @@
+/*
+ *  Freescale i.MX25 Touch Screen Driver
+ *
+ *  Copyright (c) 2009 Lothar Wassmann <LW@KARO-electronics.de>
+ *
+ * Based on code from Freescale BSP
+ *
+ *  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.
+ */
+
+/* TSC General Config Register */
+#define TGCR			0x000
+#define TGCR_IPG_CLK_EN		(1 << 0)
+#define TGCR_TSC_RST		(1 << 1)
+#define TGCR_FUNC_RST		(1 << 2)
+#define TGCR_SLPC		(1 << 4)
+#define TGCR_STLC		(1 << 5)
+#define TGCR_HSYNC_EN		(1 << 6)
+#define TGCR_HSYNC_POL		(1 << 7)
+#define TGCR_POWERMODE_SHIFT	8
+#define TGCR_POWER_OFF		(0x0 << TGCR_POWERMODE_SHIFT)
+#define TGCR_POWER_SAVE		(0x1 << TGCR_POWERMODE_SHIFT)
+#define TGCR_POWER_ON		(0x3 << TGCR_POWERMODE_SHIFT)
+#define TGCR_POWER_MASK		(0x3 << TGCR_POWERMODE_SHIFT)
+#define TGCR_INTREFEN		(1 << 10)
+#define TGCR_ADCCLKCFG_SHIFT	16
+#define TGCR_ADCCLKCFG_MASK	(0x1f << TGCR_ADCCLKCFG_SHIFT)
+#define TGCR_PD_EN		(1 << 23)
+#define TGCR_PDB_EN		(1 << 24)
+#define TGCR_PDBTIME_SHIFT	25
+#define TGCR_PDBTIME128		(0x3f << TGCR_PDBTIME_SHIFT)
+#define TGCR_PDBTIME_MASK	(0x7f << TGCR_PDBTIME_SHIFT)
+
+/* TSC General Status Register */
+#define TGSR			0x004
+#define TGSR_TCQ_INT		(1 << 0)
+#define TGSR_GCQ_INT		(1 << 1)
+#define TGSR_SLP_INT		(1 << 2)
+#define TGSR_TCQ_DMA		(1 << 16)
+#define TGSR_GCQ_DMA		(1 << 17)
+
+/* TSC IDLE Config Register */
+#define TICR			0x008
+
+/* TouchScreen Convert Queue FIFO Register */
+#define TCQFIFO			0x400
+/* TouchScreen Convert Queue Control Register */
+#define TCQCR			0x404
+#define CQCR_QSM_SHIFT		0
+#define CQCR_QSM_STOP		(0x0 << CQCR_QSM_SHIFT)
+#define CQCR_QSM_PEN		(0x1 << CQCR_QSM_SHIFT)
+#define CQCR_QSM_FQS		(0x2 << CQCR_QSM_SHIFT)
+#define CQCR_QSM_FQS_PEN	(0x3 << CQCR_QSM_SHIFT)
+#define CQCR_QSM_MASK		(0x3 << CQCR_QSM_SHIFT)
+#define CQCR_FQS		(1 << 2)
+#define CQCR_RPT		(1 << 3)
+#define CQCR_LAST_ITEM_ID_SHIFT 4
+#define CQCR_LAST_ITEM_ID_MASK	(0xf << CQCR_LAST_ITEM_ID_SHIFT)
+#define CQCR_FIFOWATERMARK_SHIFT 8
+#define CQCR_FIFOWATERMARK_MASK (0xf << CQCR_FIFOWATERMARK_SHIFT)
+#define CQCR_REPEATWAIT_SHIFT	12
+#define CQCR_REPEATWAIT_MASK	(0xf << CQCR_REPEATWAIT_SHIFT)
+#define CQCR_QRST		(1 << 16)
+#define CQCR_FRST		(1 << 17)
+#define CQCR_PD_MSK		(1 << 18)
+#define CQCR_PD_CFG		(1 << 19)
+
+/* TouchScreen Convert Queue Status Register */
+#define TCQSR			0x408
+#define CQSR_PD			(1 << 0)
+#define CQSR_EOQ		(1 << 1)
+#define CQSR_FOR		(1 << 4)
+#define CQSR_FUR		(1 << 5)
+#define CQSR_FER		(1 << 6)
+#define CQSR_EMPT		(1 << 13)
+#define CQSR_FULL		(1 << 14)
+#define CQSR_FDRY		(1 << 15)
+
+/* TouchScreen Convert Queue Mask Register */
+#define TCQMR			0x40c
+#define CQMR_PD_IRQ_MSK		(1 << 0)
+#define CQMR_EOQ_IRQ_MSK	(1 << 1)
+#define CQMR_FOR_IRQ_MSK	(1 << 4)
+#define CQMR_FUR_IRQ_MSK	(1 << 5)
+#define CQMR_FER_IRQ_MSK	(1 << 6)
+#define CQMR_PD_DMA_MSK		(1 << 16)
+#define CQMR_EOQ_DMA_MSK	(1 << 17)
+#define CQMR_FOR_DMA_MSK	(1 << 20)
+#define CQMR_FUR_DMA_MSK	(1 << 21)
+#define CQMR_FER_DMA_MSK	(1 << 22)
+#define CQMR_FDRY_DMA_MSK	(1 << 31)
+
+/* TouchScreen Convert Queue ITEM 7~0 */
+#define TCQ_ITEM_7_0		0x420
+
+/* TouchScreen Convert Queue ITEM 15~8 */
+#define TCQ_ITEM_15_8		0x424
+
+#define TCQ_ITEM_TCC0		0x0
+#define TCQ_ITEM_TCC1		0x1
+#define TCQ_ITEM_TCC2		0x2
+#define TCQ_ITEM_TCC3		0x3
+#define TCQ_ITEM_TCC4		0x4
+#define TCQ_ITEM_TCC5		0x5
+#define TCQ_ITEM_TCC6		0x6
+#define TCQ_ITEM_TCC7		0x7
+#define TCQ_ITEM_GCC7		0x8
+#define TCQ_ITEM_GCC6		0x9
+#define TCQ_ITEM_GCC5		0xa
+#define TCQ_ITEM_GCC4		0xb
+#define TCQ_ITEM_GCC3		0xc
+#define TCQ_ITEM_GCC2		0xd
+#define TCQ_ITEM_GCC1		0xe
+#define TCQ_ITEM_GCC0		0xf
+
+/* TouchScreen Convert Config 0-7 */
+#define TCC0			0x440
+#define TCC1			0x444
+#define TCC2			0x448
+#define TCC3			0x44c
+#define TCC4			0x450
+#define TCC5			0x454
+#define TCC6			0x458
+#define TCC7			0x45c
+#define CC_PEN_IACK		(1 << 1)
+#define CC_SEL_REFN_SHIFT	2
+#define CC_SEL_REFN_YNLR	(0x1 << CC_SEL_REFN_SHIFT)
+#define CC_SEL_REFN_AGND	(0x2 << CC_SEL_REFN_SHIFT)
+#define CC_SEL_REFN_MASK	(0x3 << CC_SEL_REFN_SHIFT)
+#define CC_SELIN_SHIFT		4
+#define CC_SELIN_XPUL		(0x0 << CC_SELIN_SHIFT)
+#define CC_SELIN_YPLL		(0x1 << CC_SELIN_SHIFT)
+#define CC_SELIN_XNUR		(0x2 << CC_SELIN_SHIFT)
+#define CC_SELIN_YNLR		(0x3 << CC_SELIN_SHIFT)
+#define CC_SELIN_WIPER		(0x4 << CC_SELIN_SHIFT)
+#define CC_SELIN_INAUX0		(0x5 << CC_SELIN_SHIFT)
+#define CC_SELIN_INAUX1		(0x6 << CC_SELIN_SHIFT)
+#define CC_SELIN_INAUX2		(0x7 << CC_SELIN_SHIFT)
+#define CC_SELIN_MASK		(0x7 << CC_SELIN_SHIFT)
+#define CC_SELREFP_SHIFT	7
+#define CC_SELREFP_YPLL		(0x0 << CC_SELREFP_SHIFT)
+#define CC_SELREFP_XPUL		(0x1 << CC_SELREFP_SHIFT)
+#define CC_SELREFP_EXT		(0x2 << CC_SELREFP_SHIFT)
+#define CC_SELREFP_INT		(0x3 << CC_SELREFP_SHIFT)
+#define CC_SELREFP_MASK		(0x3 << CC_SELREFP_SHIFT)
+#define CC_XPULSW		(1 << 9)
+#define CC_XNURSW_SHIFT		10
+#define CC_XNURSW_HIGH		(0x0 << CC_XNURSW_SHIFT)
+#define CC_XNURSW_OFF		(0x1 << CC_XNURSW_SHIFT)
+#define CC_XNURSW_LOW		(0x3 << CC_XNURSW_SHIFT)
+#define CC_XNURSW_MASK		(0x3 << CC_XNURSW_SHIFT)
+#define CC_YPLLSW_SHIFT		12
+#define CC_YPLLSW_HIGH		(0x0 << CC_YPLLSW_SHIFT)
+#define CC_YPLLSW_OFF		(0x1 << CC_YPLLSW_SHIFT)
+#define CC_YPLLSW_LOW		(0x3 << CC_YPLLSW_SHIFT)
+#define CC_YPLLSW_MASK		(0x3 << CC_YPLLSW_SHIFT)
+#define CC_YNLRSW		(1 << 14)
+#define CC_WIPERSW		(1 << 15)
+#define CC_NOS_SHIFT		16
+#define CC_NOS_MASK		(0xf << CC_NOS_SHIFT)
+#define CC_IGS			(1 << 20)
+#define CC_SETTLING_TIME_SHIFT	24
+#define CC_SETTLING_TIME_MASK	(0xff << CC_SETTLING_TIME_SHIFT)
+
+#define TSC_4WIRE_PRECHARGE	0x158c
+#define TSC_4WIRE_TOUCH_DETECT	0x578e
+
+#define TSC_4WIRE_X_MEASURE	0x1c90
+#define TSC_4WIRE_Y_MEASURE	0x4604
+#define TSC_4WIRE_XP_MEASURE	0x0f8c
+#define TSC_4WIRE_YN_MEASURE	0x0fbc
+
+#define TSC_GENERAL_ADC_GCC0	0x17dc
+#define TSC_GENERAL_ADC_GCC1	0x17ec
+#define TSC_GENERAL_ADC_GCC2	0x17fc
+
+/* GeneralADC Convert Queue FIFO Register */
+#define GCQFIFO			0x800
+#define GCQFIFO_ADCOUT_SHIFT	4
+#define GCQFIFO_ADCOUT_MASK	(0xfff << GCQFIFO_ADCOUT_SHIFT)
+
+/* GeneralADC Convert Queue Control Register */
+#define GCQCR			0x804
+
+/* GeneralADC Convert Queue Status Register */
+#define GCQSR			0x808
+
+/* GeneralADC Convert Queue Mask Register */
+#define GCQMR			0x80c
+
+/* GeneralADC Convert Queue ITEM 7~0 */
+#define GCQ_ITEM_7_0		0x820
+
+/* GeneralADC Convert Queue ITEM 15~8 */
+#define GCQ_ITEM_15_8		0x824
+
+#define CQ_ITEM7_SHIFT		28
+#define CQ_ITEM6_SHIFT		24
+#define CQ_ITEM5_SHIFT		20
+#define CQ_ITEM4_SHIFT		16
+#define CQ_ITEM3_SHIFT		12
+#define CQ_ITEM2_SHIFT		 8
+#define CQ_ITEM1_SHIFT		 4
+#define CQ_ITEM0_SHIFT		 0
+
+#define CQ_ITEM8_SHIFT		28
+#define CQ_ITEM9_SHIFT		24
+#define CQ_ITEM10_SHIFT		20
+#define CQ_ITEM11_SHIFT		16
+#define CQ_ITEM12_SHIFT		12
+#define CQ_ITEM13_SHIFT		 8
+#define CQ_ITEM14_SHIFT		 4
+#define CQ_ITEM15_SHIFT		 0
+
+#define GCQ_ITEM_GCC0		0x0
+#define GCQ_ITEM_GCC1		0x1
+#define GCQ_ITEM_GCC2		0x2
+#define GCQ_ITEM_GCC3		0x3
+
+/* GeneralADC Convert Config 0-7 */
+#define GCC0			0x840
+#define GCC1			0x844
+#define GCC2			0x848
+#define GCC3			0x84c
+#define GCC4			0x850
+#define GCC5			0x854
+#define GCC6			0x858
+#define GCC7			0x85c
+
+/* TSC Test Register R/W */
+#define TTR			0xc00
+/* TSC Monitor Register 1, 2 */
+#define MNT1			0xc04
+#define MNT2			0xc04
+
+#define DETECT_ITEM_ID_1	1
+#define DETECT_ITEM_ID_2	5
+#define TS_X_ITEM_ID		2
+#define TS_Y_ITEM_ID		3
+#define TSI_DATA		1
+#define FQS_DATA		0
diff -purN linux-2.6.30-rc4-git/drivers/leds/leds-gpio.c linux-2.6.30-rc4-karo3/drivers/leds/leds-gpio.c
--- linux-2.6.30-rc4-git/drivers/leds/leds-gpio.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/leds/leds-gpio.c	2009-06-02 18:36:36.000000000 +0200
@@ -82,7 +82,7 @@ static int __devinit create_gpio_led(con
 	if (!gpio_is_valid(template->gpio)) {
 		printk(KERN_INFO "Skipping unavilable LED gpio %d (%s)\n", 
 				template->gpio, template->name);
-		return 0;
+		return -EINVAL;
 	}
 
 	ret = gpio_request(template->gpio, template->name);
diff -purN linux-2.6.30-rc4-git/drivers/mtd/nand/Kconfig linux-2.6.30-rc4-karo3/drivers/mtd/nand/Kconfig
--- linux-2.6.30-rc4-git/drivers/mtd/nand/Kconfig	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/mtd/nand/Kconfig	2009-06-02 18:42:05.000000000 +0200
@@ -420,6 +420,27 @@ config MTD_NAND_MXC
 	  This enables the driver for the NAND flash controller on the
 	  MXC processors.
 
+config MTD_NAND_MXC_FLASH_BBT
+	bool "Support a flash based bad block table"
+	depends on MTD_NAND_MXC
+
+config	ARCH_MXC_HAS_NFC_V1
+	bool
+
+config	ARCH_MXC_HAS_NFC_V1_1
+	select ARCH_MXC_HAS_NFC_V1
+	bool
+
+config	ARCH_MXC_HAS_NFC_V2
+	bool
+
+config	ARCH_MXC_HAS_NFC_V2_1
+	bool
+	select ARCH_MXC_HAS_NFC_V2
+
+config	ARCH_MXC_HAS_NFC_V3
+	bool
+
 config MTD_NAND_SH_FLCTL
 	tristate "Support for NAND on Renesas SuperH FLCTL"
 	depends on MTD_NAND && SUPERH && CPU_SUBTYPE_SH7723
diff -purN linux-2.6.30-rc4-git/drivers/mtd/nand/mxc_nand.c linux-2.6.30-rc4-karo3/drivers/mtd/nand/mxc_nand.c
--- linux-2.6.30-rc4-git/drivers/mtd/nand/mxc_nand.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/mtd/nand/mxc_nand.c	2009-07-14 14:10:27.000000000 +0200
@@ -32,25 +32,58 @@
 #include <linux/io.h>
 
 #include <asm/mach/flash.h>
+#include <mach/hardware.h>
 #include <mach/mxc_nand.h>
 
+#ifdef CONFIG_MTD_DEBUG
+static int debug;
+module_param(debug, int, S_IRUGO | S_IWUSR);
+
+#define dbg_lvl(n)	((n) < debug)
+#define DBG(lvl, fmt...)	do { if (dbg_lvl(lvl)) printk(KERN_DEBUG fmt); } while (0)
+#undef DEBUG
+#define DEBUG(l, fmt...) DBG(l, fmt)
+#else
+static int debug;
+module_param(debug, int, 0);
+
+#define dbg_lvl(n)	0
+#define DBG(lvl, fmt...)	do { } while (0)
+#endif
+
+
 #define DRIVER_NAME "mxc_nand"
 
 /* Addresses for NFC registers */
-#define NFC_BUF_SIZE		0xE00
-#define NFC_BUF_ADDR		0xE04
-#define NFC_FLASH_ADDR		0xE06
-#define NFC_FLASH_CMD		0xE08
-#define NFC_CONFIG		0xE0A
-#define NFC_ECC_STATUS_RESULT	0xE0C
-#define NFC_RSLTMAIN_AREA	0xE0E
-#define NFC_RSLTSPARE_AREA	0xE10
-#define NFC_WRPROT		0xE12
-#define NFC_UNLOCKSTART_BLKADDR	0xE14
-#define NFC_UNLOCKEND_BLKADDR	0xE16
-#define NFC_NF_WRPRST		0xE18
-#define NFC_CONFIG1		0xE1A
-#define NFC_CONFIG2		0xE1C
+#define NFC_BUF_SIZE		0x000
+#define NFC_BUF_ADDR		0x004
+#define NFC_FLASH_ADDR		0x006
+#define NFC_FLASH_CMD		0x008
+#define NFC_CONFIG		0x00A
+#define NFC_ECC_STATUS_RESULT	0x00C
+#define NFC_WRPROT		0x012
+#ifndef CONFIG_ARCH_MXC_HAS_NFC_V1_1
+#define NFC_RSLTMAIN_AREA	0x00E
+#define NFC_RSLTSPARE_AREA	0x010
+#define NFC_UNLOCKSTART_BLKADDR	0x014
+#define NFC_UNLOCKEND_BLKADDR	0x016
+#else
+#define NFC_ECC_STATUS_RESULT2	0x00E
+#define NFC_SPAS		0x010
+#endif
+#define NFC_NF_WRPRST		0x018
+#define NFC_CONFIG1		0x01A
+#define NFC_CONFIG2		0x01C
+#ifdef CONFIG_ARCH_MXC_HAS_NFC_V1_1
+#define NFC_UNLOCKSTART_BLKADDR 0x020
+#define NFC_UNLOCKEND_BLKADDR	0x022
+#define NFC_UNLOCKSTART_BLKADDR1 0x024
+#define NFC_UNLOCKEND_BLKADDR1	0x026
+#define NFC_UNLOCKSTART_BLKADDR2 0x028
+#define NFC_UNLOCKEND_BLKADDR2	0x02a
+#define NFC_UNLOCKSTART_BLKADDR3 0x02c
+#define NFC_UNLOCKEND_BLKADDR3	0x02e
+#endif
 
 /* Addresses for NFC RAM BUFFER Main area 0 */
 #define MAIN_AREA0		0x000
@@ -59,10 +92,27 @@
 #define MAIN_AREA3		0x600
 
 /* Addresses for NFC SPARE BUFFER Spare area 0 */
+#ifndef CONFIG_ARCH_MXC_HAS_NFC_V1_1
+#define SPARE_AREA_SIZE		16
 #define SPARE_AREA0		0x800
 #define SPARE_AREA1		0x810
 #define SPARE_AREA2		0x820
 #define SPARE_AREA3		0x830
+#else
+#define SPARE_AREA_SIZE		64
+#define MAIN_AREA4		0x800
+#define MAIN_AREA5		0xa00
+#define MAIN_AREA6		0xc00
+#define MAIN_AREA7		0xe00
+#define SPARE_AREA0		0x1000
+#define SPARE_AREA1		0x1040
+#define SPARE_AREA2		0x1080
+#define SPARE_AREA3		0x10c0
+#define SPARE_AREA4		0x1100
+#define SPARE_AREA5		0x1140
+#define SPARE_AREA6		0x1180
+#define SPARE_AREA7		0x11c0
+#endif
 
 /* Set INT to 0, FCMD to 1, rest to 0 in NFC_CONFIG2 Register
  * for Command operation */
@@ -107,10 +157,12 @@ struct mxc_nand_host {
 	struct device		*dev;
 
 	void __iomem		*regs;
+	void __iomem		*nfc_buf;
 	int			spare_only;
 	int			status_request;
 	int			pagesize_2k;
 	uint16_t		col_addr;
+	unsigned int		page_addr;
 	struct clk		*clk;
 	int			clk_act;
 	int			irq;
@@ -120,40 +172,134 @@ struct mxc_nand_host {
 
 /* Define delays in microsec for NAND device operations */
 #define TROP_US_DELAY   2000
-/* Macros to get byte and bit positions of ECC */
-#define COLPOS(x)  ((x) >> 3)
-#define BITPOS(x) ((x) & 0xf)
-
-/* Define single bit Error positions in Main & Spare area */
-#define MAIN_SINGLEBIT_ERROR 0x4
-#define SPARE_SINGLEBIT_ERROR 0x1
 
+#ifndef CONFIG_ARCH_MXC_HAS_NFC_V1_1
 /* OOB placement block for use with hardware ecc generation */
+static struct nand_ecclayout nand_hw_eccoob2k_8 = {
+	.eccbytes = 20,
+	.eccpos = {
+		6, 7, 8, 9, 10,
+		22, 23, 24, 25, 26,
+		38, 39, 40, 41, 42,
+		54, 55, 56, 57, 58,
+	},
+	.oobfree = {{2, 4}, {11, 11}, {27, 11}, {43, 11}, {59, 5}},
+};
+
 static struct nand_ecclayout nand_hw_eccoob_8 = {
 	.eccbytes = 5,
-	.eccpos = {6, 7, 8, 9, 10},
-	.oobfree = {{0, 5}, {11, 5}, }
+	.eccpos = { 6, 7, 8, 9, 10 },
+	.oobfree = {{0, 6}, {11, 5}}
+};
+#ifdef CONFIG_MTD_NAND_MXC_FLASH_BBT
+static u8 bbt_pattern[] = {'B', 'b', 't', '0' };
+static u8 mirror_pattern[] = {'1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+	.options = (NAND_BBT_LASTBLOCK | NAND_BBT_WRITE |
+		    NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP),
+	.offs =	12,
+	.len = 4,
+	.veroffs = 11,
+	.maxblocks = 4,
+	.pattern = bbt_pattern,
 };
 
-static struct nand_ecclayout nand_hw_eccoob_16 = {
-	.eccbytes = 5,
-	.eccpos = {6, 7, 8, 9, 10},
-	.oobfree = {{0, 6}, {12, 4}, }
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.options = (NAND_BBT_LASTBLOCK | NAND_BBT_WRITE |
+		    NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP),
+	.offs =	12,
+	.len = 4,
+	.veroffs = 11,
+	.maxblocks = 4,
+	.pattern = mirror_pattern,
+};
+#endif
+#else
+/*
+ * OOB placement block for use with hardware ecc generation
+ */
+static struct nand_ecclayout nand_hw_eccoob2k_8 = {
+	.eccbytes = 36,
+	.eccpos = {
+		7, 8, 9, 10, 11, 12, 13, 14, 15,
+		23, 24, 25, 26, 27, 28, 29, 30, 31,
+		39, 40, 41, 42, 43, 44, 45, 46, 47,
+		55, 56, 57, 58, 59, 60, 61, 62, 63,
+	},
+	.oobfree = {{2, 5}, {16, 7}, {32, 7}, {48, 7}},
+};
+
+static struct nand_ecclayout nand_hw_eccoob_8 = {
+	.eccbytes = 9,
+	.eccpos = { 7, 8, 9, 10, 11, 12, 13, 14, 15, },
+	.oobfree = {{0, 4}},
+};
+
+#ifdef CONFIG_MTD_NAND_MXC_FLASH_BBT
+/* Generic flash bbt decriptors
+*/
+static u8 bbt_pattern[] = { 'B', 'b', 't', '0' };
+static u8 mirror_pattern[] = { '1', 't', 'b', 'B' };
+
+static struct nand_bbt_descr bbt_main_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+	NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs = 0,
+	.len = 4,
+	.veroffs = 4,
+	.maxblocks = 4,
+	.pattern = bbt_pattern
 };
 
+static struct nand_bbt_descr bbt_mirror_descr = {
+	.options = NAND_BBT_LASTBLOCK | NAND_BBT_CREATE | NAND_BBT_WRITE |
+	NAND_BBT_2BIT | NAND_BBT_VERSION | NAND_BBT_PERCHIP,
+	.offs = 0,
+	.len = 4,
+	.veroffs = 4,
+	.maxblocks = 4,
+	.pattern = mirror_pattern
+};
+#endif
+#endif
+
 #ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
 #endif
 
+#ifdef CONFIG_MTD_DEBUG
+#define nfc_read_reg(b, r)	__nfc_read_reg(b, r, #r, __FUNCTION__)
+static inline u16 __nfc_read_reg(void __iomem *base, unsigned int reg,
+				 const char *name, const char *fn)
+{
+	u16 val = readw(base + reg);
+	DBG(3, "%s: Read %04x from %s[%02x]\n", fn, val, name, reg);
+	return val;
+}
+
+#define nfc_write_reg(v, b, r)	__nfc_write_reg(v, b, r, #r, __FUNCTION__)
+static inline void __nfc_write_reg(u16 val, void __iomem *base, unsigned int reg,
+				   const char *name, const char *fn)
+{
+	DBG(3, "%s: Writing %04x to %s[%02x]\n", fn, val, name, reg);
+	writew(val, base + reg);
+}
+#else
+#define nfc_read_reg(b, r)	readw(b + r)
+#define nfc_write_reg(v, b, r)	writew(v, b + r)
+#endif
+
 static irqreturn_t mxc_nfc_irq(int irq, void *dev_id)
 {
 	struct mxc_nand_host *host = dev_id;
-
 	uint16_t tmp;
 
-	tmp = readw(host->regs + NFC_CONFIG1);
+	DEBUG(MTD_DEBUG_LEVEL3, "%s(%d)\n", __FUNCTION__, irq);
+
+	tmp = nfc_read_reg(host->regs, NFC_CONFIG1);
 	tmp |= NFC_INT_MSK; /* Disable interrupt */
-	writew(tmp, host->regs + NFC_CONFIG1);
+	nfc_write_reg(tmp, host->regs, NFC_CONFIG1);
 
 	wake_up(&host->irq_waitq);
 
@@ -166,35 +312,29 @@ static irqreturn_t mxc_nfc_irq(int irq, 
 static void wait_op_done(struct mxc_nand_host *host, int max_retries,
 				uint16_t param, int useirq)
 {
-	uint32_t tmp;
-
 	if (useirq) {
-		if ((readw(host->regs + NFC_CONFIG2) & NFC_INT) == 0) {
-
-			tmp = readw(host->regs + NFC_CONFIG1);
-			tmp  &= ~NFC_INT_MSK;	/* Enable interrupt */
-			writew(tmp, host->regs + NFC_CONFIG1);
-
-			wait_event(host->irq_waitq,
-				readw(host->regs + NFC_CONFIG2) & NFC_INT);
-
-			tmp = readw(host->regs + NFC_CONFIG2);
-			tmp  &= ~NFC_INT;
-			writew(tmp, host->regs + NFC_CONFIG2);
+		if (!(nfc_read_reg(host->regs, NFC_CONFIG2) & NFC_INT)) {
+			uint32_t cfg1;
+			const unsigned long timeout = max_retries;
+
+			cfg1 = nfc_read_reg(host->regs, NFC_CONFIG1);
+			cfg1 &= ~NFC_INT_MSK;	/* Enable interrupt */
+			nfc_write_reg(cfg1, host->regs, NFC_CONFIG1);
+
+			max_retries = wait_event_timeout(host->irq_waitq,
+				nfc_read_reg(host->regs, NFC_CONFIG2) &
+					NFC_INT, timeout);
 		}
 	} else {
-		while (max_retries-- > 0) {
-			if (readw(host->regs + NFC_CONFIG2) & NFC_INT) {
-				tmp = readw(host->regs + NFC_CONFIG2);
-				tmp  &= ~NFC_INT;
-				writew(tmp, host->regs + NFC_CONFIG2);
-				break;
-			}
+		while (!(nfc_read_reg(host->regs, NFC_CONFIG2) & NFC_INT) &&
+			max_retries-- > 0) {
 			udelay(1);
 		}
-		if (max_retries <= 0)
-			DEBUG(MTD_DEBUG_LEVEL0, "%s(%d): INT not set\n",
-			      __func__, param);
+	}
+	WARN_ON(nfc_read_reg(host->regs, NFC_CONFIG2) & ~NFC_INT);
+	nfc_write_reg(0, host->regs, NFC_CONFIG2);
+	if (WARN_ON(max_retries <= 0)) {
+		printk(KERN_ERR "%s(%d): INT not set\n", __func__, param);
 	}
 }
 
@@ -204,8 +344,9 @@ static void send_cmd(struct mxc_nand_hos
 {
 	DEBUG(MTD_DEBUG_LEVEL3, "send_cmd(host, 0x%x, %d)\n", cmd, useirq);
 
-	writew(cmd, host->regs + NFC_FLASH_CMD);
-	writew(NFC_CMD, host->regs + NFC_CONFIG2);
+	nfc_write_reg(cmd, host->regs, NFC_FLASH_CMD);
+	WARN_ON(nfc_read_reg(host->regs, NFC_CONFIG2));
+	nfc_write_reg(NFC_CMD, host->regs, NFC_CONFIG2);
 
 	/* Wait for operation to complete */
 	wait_op_done(host, TROP_US_DELAY, cmd, useirq);
@@ -218,34 +359,72 @@ static void send_addr(struct mxc_nand_ho
 {
 	DEBUG(MTD_DEBUG_LEVEL3, "send_addr(host, 0x%x %d)\n", addr, islast);
 
-	writew(addr, host->regs + NFC_FLASH_ADDR);
-	writew(NFC_ADDR, host->regs + NFC_CONFIG2);
+	nfc_write_reg(addr, host->regs, NFC_FLASH_ADDR);
+	WARN_ON(nfc_read_reg(host->regs, NFC_CONFIG2));
+	nfc_write_reg(NFC_ADDR, host->regs, NFC_CONFIG2);
 
 	/* Wait for operation to complete */
 	wait_op_done(host, TROP_US_DELAY, addr, islast);
 }
 
+static inline void nfc_buf_read(const void __iomem *nfc, void *buf, int len)
+{
+	u32 *wp = buf;
+	int i;
+
+	BUG_ON((unsigned long)nfc & 3);
+	BUG_ON((unsigned long)buf & 3);
+
+	for (i = 0; i < len; i += sizeof(long)) {
+		wp[i >> 2] = readl(nfc + i);
+	}
+}
+
+static inline void nfc_buf_write(void __iomem *nfc, const void *buf, int len)
+{
+	const u32 *rp = buf;
+	int i;
+
+	BUG_ON((unsigned long)nfc & 3);
+	BUG_ON((unsigned long)buf & 3);
+
+	for (i = 0; i < len; i += sizeof(long)) {
+		writel(rp[i >> 2], nfc + i);
+	}
+}
+
 /* This function requests the NANDFC to initate the transfer
  * of data currently in the NANDFC RAM buffer to the NAND device. */
 static void send_prog_page(struct mxc_nand_host *host, uint8_t buf_id,
 			int spare_only)
 {
-	DEBUG(MTD_DEBUG_LEVEL3, "send_prog_page (%d)\n", spare_only);
+	int i;
+
+	if (spare_only)
+		DEBUG(MTD_DEBUG_LEVEL1, "send_prog_page (%d)\n", spare_only);
+	if (cpu_is_mx25()) {
+		for (i = 0; i < 4; i++) {
+			void __iomem *src = host->nfc_buf + SPARE_AREA0 + i * 16;
+			void __iomem *dst = host->nfc_buf + SPARE_AREA0 + i * 64;
+
+			memcpy(dst, src, 16);
+		}
+	}
 
 	/* NANDFC buffer 0 is used for page read/write */
-	writew(buf_id, host->regs + NFC_BUF_ADDR);
+	nfc_write_reg(buf_id, host->regs, NFC_BUF_ADDR);
 
 	/* Configure spare or page+spare access */
 	if (!host->pagesize_2k) {
-		uint16_t config1 = readw(host->regs + NFC_CONFIG1);
+		uint16_t config1 = nfc_read_reg(host->regs, NFC_CONFIG1);
 		if (spare_only)
 			config1 |= NFC_SP_EN;
 		else
-			config1 &= ~(NFC_SP_EN);
-		writew(config1, host->regs + NFC_CONFIG1);
+			config1 &= ~NFC_SP_EN;
+		nfc_write_reg(config1, host->regs, NFC_CONFIG1);
 	}
-
-	writew(NFC_INPUT, host->regs + NFC_CONFIG2);
+	WARN_ON(nfc_read_reg(host->regs, NFC_CONFIG2));
+	nfc_write_reg(NFC_INPUT, host->regs, NFC_CONFIG2);
 
 	/* Wait for operation to complete */
 	wait_op_done(host, TROP_US_DELAY, spare_only, true);
@@ -256,25 +435,37 @@ static void send_prog_page(struct mxc_na
 static void send_read_page(struct mxc_nand_host *host, uint8_t buf_id,
 		int spare_only)
 {
+	int i;
+
 	DEBUG(MTD_DEBUG_LEVEL3, "send_read_page (%d)\n", spare_only);
 
 	/* NANDFC buffer 0 is used for page read/write */
-	writew(buf_id, host->regs + NFC_BUF_ADDR);
+	nfc_write_reg(buf_id, host->regs, NFC_BUF_ADDR);
 
 	/* Configure spare or page+spare access */
 	if (!host->pagesize_2k) {
-		uint32_t config1 = readw(host->regs + NFC_CONFIG1);
+		uint32_t config1 = nfc_read_reg(host->regs, NFC_CONFIG1);
 		if (spare_only)
 			config1 |= NFC_SP_EN;
 		else
 			config1 &= ~NFC_SP_EN;
-		writew(config1, host->regs + NFC_CONFIG1);
+		nfc_write_reg(config1, host->regs, NFC_CONFIG1);
 	}
 
-	writew(NFC_OUTPUT, host->regs + NFC_CONFIG2);
+	WARN_ON(nfc_read_reg(host->regs, NFC_CONFIG2));
+	nfc_write_reg(NFC_OUTPUT, host->regs, NFC_CONFIG2);
 
 	/* Wait for operation to complete */
 	wait_op_done(host, TROP_US_DELAY, spare_only, true);
+	if (!cpu_is_mx25())
+		return;
+
+	for (i = 0; i < 4; i++) {
+		void __iomem *src = host->nfc_buf + SPARE_AREA0 + i * 64;
+		void __iomem *dst = host->nfc_buf + SPARE_AREA0 + i * 16;
+
+		memcpy(dst, src, 16);
+	}
 }
 
 /* Request the NANDFC to perform a read of the NAND device ID. */
@@ -284,20 +475,23 @@ static void send_read_id(struct mxc_nand
 	uint16_t tmp;
 
 	/* NANDFC buffer 0 is used for device ID output */
-	writew(0x0, host->regs + NFC_BUF_ADDR);
+	nfc_write_reg(0x0, host->regs, NFC_BUF_ADDR);
 
-	/* Read ID into main buffer */
-	tmp = readw(host->regs + NFC_CONFIG1);
+	tmp = nfc_read_reg(host->regs, NFC_CONFIG1);
 	tmp &= ~NFC_SP_EN;
-	writew(tmp, host->regs + NFC_CONFIG1);
+	nfc_write_reg(tmp, host->regs, NFC_CONFIG1);
 
-	writew(NFC_ID, host->regs + NFC_CONFIG2);
+	WARN_ON(nfc_read_reg(host->regs, NFC_CONFIG2));
+	/* Read ID into main buffer */
+	nfc_write_reg(NFC_ID, host->regs, NFC_CONFIG2);
 
 	/* Wait for operation to complete */
 	wait_op_done(host, TROP_US_DELAY, 0, true);
 
 	if (this->options & NAND_BUSWIDTH_16) {
-		void __iomem *main_buf = host->regs + MAIN_AREA0;
+		/* FIXME: This cannot work, because the NFC buffer
+		 * cannot be accessed with byte accesses! */
+		void __iomem *main_buf = host->nfc_buf + MAIN_AREA0;
 		/* compress the ID info */
 		writeb(readb(main_buf + 2), main_buf + 1);
 		writeb(readb(main_buf + 4), main_buf + 2);
@@ -311,32 +505,35 @@ static void send_read_id(struct mxc_nand
  * NAND device status and returns the current status. */
 static uint16_t get_dev_status(struct mxc_nand_host *host)
 {
-	void __iomem *main_buf = host->regs + MAIN_AREA1;
+	void __iomem *main_buf = host->nfc_buf + MAIN_AREA1;
 	uint32_t store;
 	uint16_t ret, tmp;
-	/* Issue status request to NAND device */
 
-	/* store the main area1 first word, later do recovery */
+	/* store the main area first word, later do recovery */
 	store = readl(main_buf);
 	/* NANDFC buffer 1 is used for device status to prevent
 	 * corruption of read/write buffer on status requests. */
-	writew(1, host->regs + NFC_BUF_ADDR);
+	nfc_write_reg(1, host->regs, NFC_BUF_ADDR);
 
 	/* Read status into main buffer */
-	tmp = readw(host->regs + NFC_CONFIG1);
+	tmp = nfc_read_reg(host->regs, NFC_CONFIG1);
 	tmp &= ~NFC_SP_EN;
-	writew(tmp, host->regs + NFC_CONFIG1);
+	nfc_write_reg(tmp, host->regs, NFC_CONFIG1);
 
-	writew(NFC_STATUS, host->regs + NFC_CONFIG2);
+	/* Issue status request to NAND device */
+	WARN_ON(nfc_read_reg(host->regs, NFC_CONFIG2));
+	nfc_write_reg(NFC_STATUS, host->regs, NFC_CONFIG2);
 
 	/* Wait for operation to complete */
 	wait_op_done(host, TROP_US_DELAY, 0, true);
 
 	/* Status is placed in first word of main buffer */
-	/* get status, then recovery area 1 data */
+	/* get status, then recover area 1 data */
 	ret = readw(main_buf);
 	writel(store, main_buf);
 
+	DEBUG(MTD_DEBUG_LEVEL2, "%s: status=%02x\n", __FUNCTION__, ret);
+
 	return ret;
 }
 
@@ -352,10 +549,290 @@ static int mxc_nand_dev_ready(struct mtd
 
 static void mxc_nand_enable_hwecc(struct mtd_info *mtd, int mode)
 {
-	/*
-	 * If HW ECC is enabled, we turn it on during init. There is
-	 * no need to enable again here.
-	 */
+	switch (mode) {
+	case NAND_ECC_WRITE:
+		DBG(0, "ECC_MODE=NAND_ECC_WRITE\n");
+		break;
+	case NAND_ECC_READSYN:
+		DBG(0, "ECC_MODE=NAND_ECC_READSYN\n");
+		break;
+	case NAND_ECC_READ:
+		DBG(0, "ECC_MODE=NAND_ECC_READ\n");
+		break;
+	default:
+		DBG(-1, "%s: Unknown ECC_MODE: %d\n", __FUNCTION__, mode);
+	}
+}
+
+static void _mxc_nand_enable_hwecc(struct mtd_info *mtd, int on)
+{
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	uint16_t ecc = nfc_read_reg(host->regs, NFC_CONFIG1);
+
+	if (on) {
+		ecc |= NFC_ECC_EN;
+	} else {
+		ecc &= ~NFC_ECC_EN;
+	}
+	nfc_write_reg(ecc, host->regs, NFC_CONFIG1);
+}
+
+static int mxc_nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+				      int page, int sndcmd)
+{
+	struct mxc_nand_host *host = chip->priv;
+	uint8_t *buf = chip->oob_poi;
+	int length = mtd->oobsize;
+	int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
+	uint8_t *bufpoi = buf;
+	int i, toread;
+
+	DEBUG(MTD_DEBUG_LEVEL0, "%s: Reading OOB area of page %u to oob %p\n",
+	      __FUNCTION__, host->page_addr, buf);
+
+	chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, page);
+	for (i = 0; i < chip->ecc.steps; i++) {
+		toread = min_t(int, length, chip->ecc.prepad);
+		if (toread) {
+			chip->read_buf(mtd, bufpoi, toread);
+			bufpoi += toread;
+			length -= toread;
+		}
+		bufpoi += chip->ecc.bytes;
+		host->col_addr += chip->ecc.bytes;
+		length -= chip->ecc.bytes;
+
+		toread = min_t(int, length, chip->ecc.postpad);
+		if (toread) {
+			chip->read_buf(mtd, bufpoi, toread);
+			bufpoi += toread;
+			length -= toread;
+		}
+	}
+	if (length > 0)
+		chip->read_buf(mtd, bufpoi, length);
+
+	_mxc_nand_enable_hwecc(mtd, 0);
+	chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize + chip->ecc.prepad, page);
+	bufpoi = buf + chip->ecc.prepad;
+	length = mtd->oobsize - chip->ecc.prepad;
+	for (i = 0; i < chip->ecc.steps; i++) {
+		toread = min_t(int, length, chip->ecc.bytes);
+		chip->read_buf(mtd, bufpoi, toread);
+		bufpoi += eccpitch;
+		length -= eccpitch;
+		host->col_addr += chip->ecc.postpad + chip->ecc.prepad;
+	}
+	_mxc_nand_enable_hwecc(mtd, 1);
+	return 1;
+}
+
+static int mxc_nand_read_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+					   uint8_t *buf)
+{
+	struct mxc_nand_host *host = chip->priv;
+	int eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
+	uint8_t *oob = chip->oob_poi;
+	int steps, size;
+	int n;
+
+	_mxc_nand_enable_hwecc(mtd, 0);
+	chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, host->page_addr);
+
+	for (n = 0, steps = chip->ecc.steps; steps > 0; n++, steps--) {
+		host->col_addr = n * eccsize;
+		chip->read_buf(mtd, buf, eccsize);
+		buf += eccsize;
+
+		host->col_addr = mtd->writesize + n * eccpitch;
+		if (chip->ecc.prepad) {
+			chip->read_buf(mtd, oob, chip->ecc.prepad);
+			oob += chip->ecc.prepad;
+		}
+
+		chip->read_buf(mtd, oob, eccbytes);
+		oob += eccbytes;
+
+		if (chip->ecc.postpad) {
+			chip->read_buf(mtd, oob, chip->ecc.postpad);
+			oob += chip->ecc.postpad;
+		}
+	}
+
+	size = mtd->oobsize - (oob - chip->oob_poi);
+	if (size)
+		chip->read_buf(mtd, oob, size);
+	_mxc_nand_enable_hwecc(mtd, 0);
+
+	return 0;
+}
+
+static int mxc_nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+				       uint8_t *buf)
+{
+	struct mxc_nand_host *host = chip->priv;
+	int n, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
+	int eccsteps = chip->ecc.steps;
+	uint8_t *p = buf;
+	uint8_t *oob = chip->oob_poi;
+
+	DEBUG(MTD_DEBUG_LEVEL1, "%s: Reading page %u to buf %p oob %p\n", __FUNCTION__,
+	      host->page_addr, buf, oob);
+
+	/* first read out the data area and the available portion of OOB */
+	for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) {
+		int stat;
+
+		host->col_addr = n * eccsize;
+
+		chip->read_buf(mtd, p, eccsize);
+
+		host->col_addr = mtd->writesize + n * eccpitch;
+
+		if (chip->ecc.prepad) {
+			chip->read_buf(mtd, oob, chip->ecc.prepad);
+			oob += chip->ecc.prepad;
+		}
+
+		stat = chip->ecc.correct(mtd, p, oob, NULL);
+
+		if (stat < 0)
+			mtd->ecc_stats.failed++;
+		else
+			mtd->ecc_stats.corrected += stat;
+		oob += eccbytes;
+
+		if (chip->ecc.postpad) {
+			chip->read_buf(mtd, oob, chip->ecc.postpad);
+			oob += chip->ecc.postpad;
+		}
+	}
+
+	/* Calculate remaining oob bytes */
+	n = mtd->oobsize - (oob - chip->oob_poi);
+	if (n)
+		chip->read_buf(mtd, oob, n);
+
+	/* Then switch ECC off and read the OOB area to get the ECC code */
+	_mxc_nand_enable_hwecc(mtd, 0);
+	chip->cmdfunc(mtd, NAND_CMD_READOOB, mtd->writesize, host->page_addr);
+	eccsteps = chip->ecc.steps;
+	oob = chip->oob_poi + chip->ecc.prepad;
+	for (n = 0; eccsteps; n++, eccsteps--, p += eccsize) {
+		host->col_addr = mtd->writesize + n * eccpitch + chip->ecc.prepad;
+		chip->read_buf(mtd, oob, eccbytes);
+		oob += eccbytes + chip->ecc.postpad;
+	}
+	_mxc_nand_enable_hwecc(mtd, 1);
+	return 0;
+}
+
+static int mxc_nand_write_oob_syndrome(struct mtd_info *mtd,
+				       struct nand_chip *chip, int page)
+{
+	struct mxc_nand_host *host = chip->priv;
+	int eccpitch = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
+	int length = mtd->oobsize;
+	int i, len, status, steps = chip->ecc.steps;
+	const uint8_t *bufpoi = chip->oob_poi;
+
+	chip->cmdfunc(mtd, NAND_CMD_SEQIN, mtd->writesize, page);
+	for (i = 0; i < steps; i++) {
+		len = min_t(int, length, eccpitch);
+
+		chip->write_buf(mtd, bufpoi, len);
+		bufpoi += len;
+		length -= len;
+		host->col_addr += chip->ecc.prepad + chip->ecc.postpad;
+	}
+	if (length > 0)
+		chip->write_buf(mtd, bufpoi, length);
+
+	chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+	status = chip->waitfunc(mtd, chip);
+	return status & NAND_STATUS_FAIL ? -EIO : 0;
+}
+
+static void mxc_nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
+					     const uint8_t *buf)
+{
+	struct mxc_nand_host *host = chip->priv;
+	int eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
+	uint8_t *oob = chip->oob_poi;
+	int steps, size;
+	int n;
+
+	for (n = 0, steps = chip->ecc.steps; steps > 0; n++, steps--) {
+		host->col_addr = n * eccsize;
+		chip->write_buf(mtd, buf, eccsize);
+		buf += eccsize;
+
+		host->col_addr = mtd->writesize + n * eccpitch;
+
+		if (chip->ecc.prepad) {
+			chip->write_buf(mtd, oob, chip->ecc.prepad);
+			oob += chip->ecc.prepad;
+		}
+
+		host->col_addr += eccbytes;
+		oob += eccbytes;
+
+		if (chip->ecc.postpad) {
+			chip->write_buf(mtd, oob, chip->ecc.postpad);
+			oob += chip->ecc.postpad;
+		}
+	}
+
+	size = mtd->oobsize - (oob - chip->oob_poi);
+	if (size)
+		chip->write_buf(mtd, oob, size);
+}
+
+static void mxc_nand_write_page_syndrome(struct mtd_info *mtd,
+					 struct nand_chip *chip, const uint8_t *buf)
+{
+	struct mxc_nand_host *host = chip->priv;
+	int i, n, eccsize = chip->ecc.size;
+	int eccbytes = chip->ecc.bytes;
+	int eccpitch = eccbytes + chip->ecc.prepad + chip->ecc.postpad;
+	int eccsteps = chip->ecc.steps;
+	const uint8_t *p = buf;
+	uint8_t *oob = chip->oob_poi;
+
+	chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
+
+	for (i = n = 0; eccsteps; n++, eccsteps--, i += eccbytes, p += eccsize) {
+		host->col_addr = n * eccsize;
+
+		chip->write_buf(mtd, p, eccsize);
+
+		host->col_addr = mtd->writesize + n * eccpitch;
+
+		if (chip->ecc.prepad) {
+			chip->write_buf(mtd, oob, chip->ecc.prepad);
+			oob += chip->ecc.prepad;
+		}
+
+		chip->write_buf(mtd, oob, eccbytes);
+		oob += eccbytes;
+
+		if (chip->ecc.postpad) {
+			chip->write_buf(mtd, oob, chip->ecc.postpad);
+			oob += chip->ecc.postpad;
+		}
+	}
+
+	/* Calculate remaining oob bytes */
+	i = mtd->oobsize - (oob - chip->oob_poi);
+	if (i)
+		chip->write_buf(mtd, oob, i);
 }
 
 static int mxc_nand_correct_data(struct mtd_info *mtd, u_char *dat,
@@ -363,18 +840,41 @@ static int mxc_nand_correct_data(struct 
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
+	uint16_t ecc_status = nfc_read_reg(host->regs, NFC_ECC_STATUS_RESULT);
 
 	/*
 	 * 1-Bit errors are automatically corrected in HW.  No need for
 	 * additional correction.  2-Bit errors cannot be corrected by
 	 * HW ECC, so we need to return failure
 	 */
-	uint16_t ecc_status = readw(host->regs + NFC_ECC_STATUS_RESULT);
-
-	if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
-		DEBUG(MTD_DEBUG_LEVEL0,
-		      "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
-		return -1;
+	if (!(nfc_read_reg(host->regs, NFC_CONFIG1) & NFC_ECC_EN)) {
+		DEBUG(MTD_DEBUG_LEVEL1, "%s: ECC turned off\n", __FUNCTION__);
+		return 0;
+	}
+
+	if (ecc_status)
+		DBG(ecc_status ? -1 : 0, "%s: ECC_STATUS=%04x\n", __FUNCTION__, ecc_status);
+
+	if (cpu_is_mx25()) {
+		int subpages = mtd->writesize / nand_chip->subpagesize;
+
+		do {
+			if ((ecc_status & 0xf) > 4) {
+				printk(KERN_ERR
+				       "MXC_NAND: HWECC uncorrectable ECC error in page %u subpage %d\n",
+				       host->page_addr,
+				       mtd->writesize / nand_chip->subpagesize - subpages);
+				return -1;
+			}
+			ecc_status >>= 4;
+			subpages--;
+		} while (subpages > 0);
+	} else {
+		if (((ecc_status & 0x3) == 2) || ((ecc_status >> 2) == 2)) {
+			DEBUG(MTD_DEBUG_LEVEL0,
+			      "MXC_NAND: HWECC uncorrectable 2-bit ECC error\n");
+			return -1;
+		}
 	}
 
 	return 0;
@@ -383,6 +883,7 @@ static int mxc_nand_correct_data(struct 
 static int mxc_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat,
 				  u_char *ecc_code)
 {
+	/* HW ECC calculation is done transparently by the controller */
 	return 0;
 }
 
@@ -392,8 +893,13 @@ static u_char mxc_nand_read_byte(struct 
 	struct mxc_nand_host *host = nand_chip->priv;
 	uint8_t ret = 0;
 	uint16_t col, rd_word;
-	uint16_t __iomem *main_buf = host->regs + MAIN_AREA0;
-	uint16_t __iomem *spare_buf = host->regs + SPARE_AREA0;
+	uint16_t __iomem *main_buf = host->nfc_buf + MAIN_AREA0;
+	uint16_t __iomem *spare_buf = host->nfc_buf + SPARE_AREA0;
+
+	DEBUG(MTD_DEBUG_LEVEL3,
+	      "%s(col = %d)\n", __FUNCTION__, host->col_addr);
+
+	BUG_ON(host->spare_only && host->col_addr >= 16);
 
 	/* Check for status request */
 	if (host->status_request)
@@ -424,28 +930,27 @@ static uint16_t mxc_nand_read_word(struc
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
-	uint16_t col, rd_word, ret;
+	uint16_t col, ret;
 	uint16_t __iomem *p;
 
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "mxc_nand_read_word(col = %d)\n", host->col_addr);
+	DEBUG(MTD_DEBUG_LEVEL1,
+	      "%s(col = %d)\n", __FUNCTION__, host->col_addr);
 
 	col = host->col_addr;
+
 	/* Adjust saved column address */
 	if (col < mtd->writesize && host->spare_only)
 		col += mtd->writesize;
+	BUG_ON(col >= mtd->writesize + 16);
 
 	if (col < mtd->writesize)
-		p = (host->regs + MAIN_AREA0) + (col >> 1);
+		p = (host->nfc_buf + MAIN_AREA0) + (col >> 1);
 	else
-		p = (host->regs + SPARE_AREA0) + ((col - mtd->writesize) >> 1);
+		p = (host->nfc_buf + SPARE_AREA0) + ((col - mtd->writesize) >> 1);
 
 	if (col & 1) {
-		rd_word = readw(p);
-		ret = (rd_word >> 8) & 0xff;
-		rd_word = readw(&p[1]);
-		ret |= (rd_word << 8) & 0xff00;
-
+		ret = readw(p++) >> 8;
+		ret |= readw(p) << 8;
 	} else
 		ret = readw(p);
 
@@ -466,31 +971,32 @@ static void mxc_nand_write_buf(struct mt
 	int n, col, i = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL3,
-	      "mxc_nand_write_buf(col = %d, len = %d)\n", host->col_addr,
-	      len);
-
+	      "%s(buf=%p col=%03x, len=%03x)\n", __FUNCTION__,
+	      buf, host->col_addr, len);
 	col = host->col_addr;
 
 	/* Adjust saved column address */
 	if (col < mtd->writesize && host->spare_only)
 		col += mtd->writesize;
 
-	n = mtd->writesize + mtd->oobsize - col;
-	n = min(len, n);
+	/* If more data is requested to be written than free space in
+	 * the flash buffer this is clearly a BUG! */
+	BUG_ON(len > mtd->writesize + mtd->oobsize - col);
+	n = len;
 
 	DEBUG(MTD_DEBUG_LEVEL3,
-	      "%s:%d: col = %d, n = %d\n", __func__, __LINE__, col, n);
+	      "%s:%d: col=%03x, n=%03x\n", __func__, __LINE__, col, n);
 
 	while (n) {
 		void __iomem *p;
 
 		if (col < mtd->writesize)
-			p = host->regs + MAIN_AREA0 + (col & ~3);
+			p = host->nfc_buf + MAIN_AREA0 + (col & ~3);
 		else
-			p = host->regs + SPARE_AREA0 -
-						mtd->writesize + (col & ~3);
+			p = host->nfc_buf + SPARE_AREA0 +
+				(col & ~3) - mtd->writesize;
 
-		DEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p = %p\n", __func__,
+		DEBUG(MTD_DEBUG_LEVEL3, "%s:%d: p=%p\n", __func__,
 		      __LINE__, p);
 
 		if (((col | (int)&buf[i]) & 3) || n < 16) {
@@ -538,11 +1044,6 @@ static void mxc_nand_write_buf(struct mt
 				m += mtd->oobsize;
 
 			m = min(n, m) & ~3;
-
-			DEBUG(MTD_DEBUG_LEVEL3,
-			      "%s:%d: n = %d, m = %d, i = %d, col = %d\n",
-			      __func__,  __LINE__, n, m, i, col);
-
 			memcpy(p, &buf[i], m);
 			col += m;
 			i += m;
@@ -563,26 +1064,28 @@ static void mxc_nand_read_buf(struct mtd
 	struct mxc_nand_host *host = nand_chip->priv;
 	int n, col, i = 0;
 
-	DEBUG(MTD_DEBUG_LEVEL3,
-	      "mxc_nand_read_buf(col = %d, len = %d)\n", host->col_addr, len);
-
 	col = host->col_addr;
 
+	DEBUG(MTD_DEBUG_LEVEL1,
+	      "%s(col=%03x len=%03x)\n", __FUNCTION__, col, len);
+
 	/* Adjust saved column address */
 	if (col < mtd->writesize && host->spare_only)
 		col += mtd->writesize;
 
-	n = mtd->writesize + mtd->oobsize - col;
-	n = min(len, n);
+	/* If more data is requested to be read than is available in
+	 * the flash buffer this is clearly a BUG! */
+	BUG_ON(len > mtd->writesize + mtd->oobsize - col);
+	n = len;
 
 	while (n) {
-		void __iomem *p;
+		const void __iomem *p;
 
 		if (col < mtd->writesize)
-			p = host->regs + MAIN_AREA0 + (col & ~3);
+			p = host->nfc_buf + MAIN_AREA0 + (col & ~3);
 		else
-			p = host->regs + SPARE_AREA0 -
-					mtd->writesize + (col & ~3);
+			p = host->nfc_buf + SPARE_AREA0 +
+				(col & ~3) - mtd->writesize;
 
 		if (((col | (int)&buf[i]) & 3) || n < 16) {
 			uint32_t data;
@@ -629,7 +1132,6 @@ static void mxc_nand_read_buf(struct mtd
 	}
 	/* Update saved column address */
 	host->col_addr = col;
-
 }
 
 /* Used by the upper layer to verify the data in NAND Flash
@@ -637,7 +1139,38 @@ static void mxc_nand_read_buf(struct mtd
 static int mxc_nand_verify_buf(struct mtd_info *mtd,
 				const u_char *buf, int len)
 {
-	return -EFAULT;
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
+	int i;
+	u16 *wp = host->nfc_buf + MAIN_AREA0;
+	const u_char *b = buf;
+
+	for (i = 0; i < len >> 1; i++) {
+		u16 w = *wp++;
+		u16 data = *buf++;
+
+		if (len - i > 1)
+			data |= (*buf++) << 8;
+		else
+			data |= 0xff << 8;
+
+		/* This is crappy! The upper layer always sends us a
+		 * whole page buffer to verify, even if only a partial page
+		 * was written. So, ignore all 0xff bytes in the reference buffer.
+		 */
+		if ((data & w) != w) {
+			printk(KERN_ERR
+			       "%s: verify error @ %03x: read: %02x %02x expected: %02x %02x\n",
+			       __FUNCTION__, i, w & 0xff, w >> 8, data & 0xff, data >> 8);
+			print_hex_dump(KERN_DEBUG, "ver: ", DUMP_PREFIX_ADDRESS,
+				       16, 2, b + ((i << 1) & ~0xf), min(len - i, 64), 0);
+			print_hex_dump(KERN_DEBUG, "ref: ", DUMP_PREFIX_ADDRESS,
+				       16, 2, host->nfc_buf + MAIN_AREA0 + ((i << 1) & ~0xf),
+				       min(len - i, 64), 0);
+			return -EFAULT;
+		}
+	}
+	return 0;
 }
 
 /* This function is used by upper layer for select and
@@ -655,13 +1188,13 @@ static void mxc_nand_select_chip(struct 
 	}
 
 	if (chip == -1) {
-		writew(readw(host->regs + NFC_CONFIG1) & ~NFC_CE,
-				host->regs + NFC_CONFIG1);
+		nfc_write_reg(nfc_read_reg(host->regs, NFC_CONFIG1) & ~NFC_CE,
+			      host->regs, NFC_CONFIG1);
 		return;
 	}
 
-	writew(readw(host->regs + NFC_CONFIG1) | NFC_CE,
-			host->regs + NFC_CONFIG1);
+	nfc_write_reg(nfc_read_reg(host->regs, NFC_CONFIG1) | NFC_CE,
+		      host->regs, NFC_CONFIG1);
 #endif
 
 	switch (chip) {
@@ -679,9 +1212,6 @@ static void mxc_nand_select_chip(struct 
 			host->clk_act = 1;
 		}
 		break;
-
-	default:
-		break;
 	}
 }
 
@@ -692,10 +1222,10 @@ static void mxc_nand_command(struct mtd_
 {
 	struct nand_chip *nand_chip = mtd->priv;
 	struct mxc_nand_host *host = nand_chip->priv;
-	int useirq = true;
+	int useirq = false;
 
 	DEBUG(MTD_DEBUG_LEVEL3,
-	      "mxc_nand_command (cmd = 0x%x, col = 0x%x, page = 0x%x)\n",
+	      "%s: cmd 0x%08x, col 0x%03x, page 0x%04x\n", __FUNCTION__,
 	      command, column, page_addr);
 
 	/* Reset command state information */
@@ -710,15 +1240,14 @@ static void mxc_nand_command(struct mtd_
 		break;
 
 	case NAND_CMD_READ0:
+		host->page_addr = page_addr;
 		host->col_addr = column;
 		host->spare_only = false;
-		useirq = false;
 		break;
 
 	case NAND_CMD_READOOB:
 		host->col_addr = column;
 		host->spare_only = true;
-		useirq = false;
 		if (host->pagesize_2k)
 			command = NAND_CMD_READ0; /* only READ0 is valid */
 		break;
@@ -726,9 +1255,9 @@ static void mxc_nand_command(struct mtd_
 	case NAND_CMD_SEQIN:
 		if (column >= mtd->writesize) {
 			/*
-			 * FIXME: before send SEQIN command for write OOB,
-			 * We must read one page out.
-			 * For K9F1GXX has no READ1 command to set current HW
+			 * Before sending the SEQIN command for writing OOB
+			 * we must read one page out.
+			 * Because K9F1GXX has no READ1 command to set current HW
 			 * pointer to spare area, we must write the whole page
 			 * including OOB together.
 			 */
@@ -751,23 +1280,23 @@ static void mxc_nand_command(struct mtd_
 			if (!host->pagesize_2k)
 				send_cmd(host, NAND_CMD_READ0, false);
 		}
-		useirq = false;
 		break;
 
 	case NAND_CMD_PAGEPROG:
 		send_prog_page(host, 0, host->spare_only);
-
-		if (host->pagesize_2k) {
+		if (host->pagesize_2k && !cpu_is_mx25()) {
 			/* data in 4 areas datas */
 			send_prog_page(host, 1, host->spare_only);
 			send_prog_page(host, 2, host->spare_only);
 			send_prog_page(host, 3, host->spare_only);
 		}
-
+		useirq = true;
 		break;
 
 	case NAND_CMD_ERASE1:
-		useirq = false;
+		break;
+	case NAND_CMD_ERASE2:
+		useirq = true;
 		break;
 	}
 
@@ -791,23 +1320,13 @@ static void mxc_nand_command(struct mtd_
 
 	/* Write out page address, if necessary */
 	if (page_addr != -1) {
-		/* paddr_0 - p_addr_7 */
-		send_addr(host, (page_addr & 0xff), false);
+		u32 page_mask = nand_chip->pagemask;
 
-		if (host->pagesize_2k) {
-			send_addr(host, (page_addr >> 8) & 0xFF, false);
-			if (mtd->size >= 0x40000000)
-				send_addr(host, (page_addr >> 16) & 0xff, true);
-		} else {
-			/* One more address cycle for higher density devices */
-			if (mtd->size >= 0x4000000) {
-				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff, false);
-				send_addr(host, (page_addr >> 16) & 0xff, true);
-			} else
-				/* paddr_8 - paddr_15 */
-				send_addr(host, (page_addr >> 8) & 0xff, true);
-		}
+		do {
+			send_addr(host, (page_addr & 0xff), false);
+			page_mask >>= 8;
+			page_addr >>= 8;
+		} while (page_mask != 0);
 	}
 
 	/* Command post-processing step */
@@ -823,14 +1342,17 @@ static void mxc_nand_command(struct mtd_
 			send_cmd(host, NAND_CMD_READSTART, true);
 			/* read for each AREA */
 			send_read_page(host, 0, host->spare_only);
-			send_read_page(host, 1, host->spare_only);
-			send_read_page(host, 2, host->spare_only);
-			send_read_page(host, 3, host->spare_only);
+			if (!cpu_is_mx25()) {
+				send_read_page(host, 1, host->spare_only);
+				send_read_page(host, 2, host->spare_only);
+				send_read_page(host, 3, host->spare_only);
+			}
 		} else
 			send_read_page(host, 0, host->spare_only);
 		break;
 
 	case NAND_CMD_READID:
+		host->col_addr = 0;
 		send_read_id(host);
 		break;
 
@@ -851,9 +1373,9 @@ static int __init mxcnd_probe(struct pla
 	struct mtd_info *mtd;
 	struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct mxc_nand_host *host;
-	struct resource *res;
+	struct resource *res1, *res2;
 	uint16_t tmp;
-	int err = 0, nr_parts = 0;
+	int err, nr_parts;
 
 	/* Allocate memory for MTD device structure and private data */
 	host = kzalloc(sizeof(struct mxc_nand_host), GFP_KERNEL);
@@ -868,9 +1390,6 @@ static int __init mxcnd_probe(struct pla
 	mtd->owner = THIS_MODULE;
 	mtd->dev.parent = &pdev->dev;
 
-	/* 50 us command delay time */
-	this->chip_delay = 5;
-
 	this->priv = host;
 	this->dev_ready = mxc_nand_dev_ready;
 	this->cmdfunc = mxc_nand_command;
@@ -880,29 +1399,54 @@ static int __init mxcnd_probe(struct pla
 	this->write_buf = mxc_nand_write_buf;
 	this->read_buf = mxc_nand_read_buf;
 	this->verify_buf = mxc_nand_verify_buf;
+#ifdef CONFIG_MTD_NAND_MXC_FLASH_BBT
+	this->bbt_td = &bbt_main_descr;
+	this->bbt_md = &bbt_mirror_descr;
+	this->options |= NAND_USE_FLASH_BBT;
+#endif
 
-	host->clk = clk_get(&pdev->dev, "nfc");
-	if (IS_ERR(host->clk))
+	host->clk = clk_get(&pdev->dev, "nfc_clk");
+	if (IS_ERR(host->clk)) {
+		err = PTR_ERR(host->clk);
 		goto eclk;
+	}
 
 	clk_enable(host->clk);
 	host->clk_act = 1;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
+	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res1 || !res2) {
 		err = -ENODEV;
 		goto eres;
 	}
 
-	host->regs = ioremap(res->start, res->end - res->start + 1);
+	if (!request_mem_region(res1->start, resource_size(res1), "mxc_nand regs")) {
+		err = -EBUSY;
+		goto ereq1;
+	}
+
+	if (!request_mem_region(res2->start, resource_size(res2), "mxc_nand buffer")) {
+		err = -EBUSY;
+		goto ereq2;
+	}
+
+	host->regs = ioremap(res1->start, resource_size(res1));
 	if (!host->regs) {
-		err = -EIO;
-		goto eres;
+		err = -ENOMEM;
+		goto eunmap1;
 	}
 
-	tmp = readw(host->regs + NFC_CONFIG1);
+	host->nfc_buf = ioremap(res2->start, resource_size(res2));
+	if (!host->nfc_buf) {
+			err = -ENOMEM;
+			goto eunmap2;
+	}
+
+	tmp = nfc_read_reg(host->regs, NFC_CONFIG1);
 	tmp |= NFC_INT_MSK;
-	writew(tmp, host->regs + NFC_CONFIG1);
+	nfc_write_reg(tmp, host->regs, NFC_CONFIG1);
+	nfc_write_reg(0, host->regs, NFC_CONFIG2);
 
 	init_waitqueue_head(&host->irq_waitq);
 
@@ -912,57 +1456,89 @@ static int __init mxcnd_probe(struct pla
 	if (err)
 		goto eirq;
 
-	if (pdata->hw_ecc) {
-		this->ecc.calculate = mxc_nand_calculate_ecc;
-		this->ecc.hwctl = mxc_nand_enable_hwecc;
-		this->ecc.correct = mxc_nand_correct_data;
-		this->ecc.mode = NAND_ECC_HW;
-		this->ecc.size = 512;
-		this->ecc.bytes = 3;
-		this->ecc.layout = &nand_hw_eccoob_8;
-		tmp = readw(host->regs + NFC_CONFIG1);
-		tmp |= NFC_ECC_EN;
-		writew(tmp, host->regs + NFC_CONFIG1);
-	} else {
-		this->ecc.size = 512;
-		this->ecc.bytes = 3;
-		this->ecc.layout = &nand_hw_eccoob_8;
-		this->ecc.mode = NAND_ECC_SOFT;
-		tmp = readw(host->regs + NFC_CONFIG1);
-		tmp &= ~NFC_ECC_EN;
-		writew(tmp, host->regs + NFC_CONFIG1);
-	}
-
 	/* Reset NAND */
 	this->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
 
 	/* preset operation */
 	/* Unlock the internal RAM Buffer */
-	writew(0x2, host->regs + NFC_CONFIG);
+	nfc_write_reg(0x2, host->regs, NFC_CONFIG);
 
 	/* Blocks to be unlocked */
-	writew(0x0, host->regs + NFC_UNLOCKSTART_BLKADDR);
-	writew(0x4000, host->regs + NFC_UNLOCKEND_BLKADDR);
+	nfc_write_reg(0x0, host->regs, NFC_UNLOCKSTART_BLKADDR);
+	nfc_write_reg(0x4000, host->regs, NFC_UNLOCKEND_BLKADDR);
 
 	/* Unlock Block Command for given address range */
-	writew(0x4, host->regs + NFC_WRPROT);
+	nfc_write_reg(0x4, host->regs, NFC_WRPROT);
 
 	/* NAND bus width determines access funtions used by upper layer */
 	if (pdata->width == 2) {
 		this->options |= NAND_BUSWIDTH_16;
-		this->ecc.layout = &nand_hw_eccoob_16;
 	}
 
-	host->pagesize_2k = 0;
-
 	/* Scan to find existence of the device */
-	if (nand_scan(mtd, 1)) {
+	err = nand_scan_ident(mtd, 1);
+	if (err) {
 		DEBUG(MTD_DEBUG_LEVEL0,
 		      "MXC_ND: Unable to find any NAND device.\n");
-		err = -ENXIO;
 		goto escan;
 	}
 
+	/* this is required before completing the scan */
+	host->pagesize_2k = (mtd->writesize == 2048);
+	tmp = nfc_read_reg(host->regs, NFC_CONFIG1);
+	if (cpu_is_mx25())
+		tmp |= NFC_ONE_CYCLE;
+
+	tmp &= ~(3 << 9); /* clear PPB mask */
+	/* set PPB (pages per block) */
+	tmp |= (ffs(mtd->erasesize / mtd->writesize) - 6) << 9;
+	nfc_write_reg(tmp, host->regs, NFC_CONFIG1);
+
+	if (pdata->hw_ecc) {
+		this->ecc.calculate = mxc_nand_calculate_ecc;
+		this->ecc.hwctl = mxc_nand_enable_hwecc;
+		this->ecc.correct = mxc_nand_correct_data;
+		if (cpu_is_mx25()) {
+			this->ecc.mode = NAND_ECC_HW_SYNDROME;
+			this->ecc.read_page = mxc_nand_read_page_syndrome;
+			this->ecc.read_page_raw = mxc_nand_read_page_raw_syndrome;
+			this->ecc.read_oob = mxc_nand_read_oob_syndrome;
+			this->ecc.write_page = mxc_nand_write_page_syndrome;
+			this->ecc.write_page_raw = mxc_nand_write_page_raw_syndrome;
+			this->ecc.write_oob = mxc_nand_write_oob_syndrome;
+			this->ecc.bytes = 9;
+			this->ecc.prepad = 7;
+		} else {
+			this->ecc.mode = NAND_ECC_HW;
+		}
+		if (host->pagesize_2k) {
+			this->ecc.layout = &nand_hw_eccoob2k_8;
+		} else {
+			this->ecc.layout = &nand_hw_eccoob_8;
+		}
+		this->ecc.size = 512;
+		tmp = nfc_read_reg(host->regs, NFC_CONFIG1);
+		tmp |= NFC_ECC_EN;
+		nfc_write_reg(tmp, host->regs, NFC_CONFIG1);
+	} else {
+		this->ecc.mode = NAND_ECC_SOFT;
+		tmp = nfc_read_reg(host->regs, NFC_CONFIG1);
+		tmp &= ~NFC_ECC_EN;
+		nfc_write_reg(tmp, host->regs, NFC_CONFIG1);
+	}
+
+	err = nand_scan_tail(mtd);
+	if (err) {
+		goto escan;
+	}
+	if (cpu_is_mx25()) {
+		mtd->flags &= ~MTD_OOB_WRITEABLE;
+	}
+
+	pr_info("MXC MTD nand Driver IRQ %d bus width: %u bit %s ECC IO: %08lx\n",
+		host->irq, pdata->width * 8, pdata->hw_ecc ? "HW" : "SW",
+		(unsigned long)res1->start);
+
 	/* Register the partitions */
 #ifdef CONFIG_MTD_PARTITIONS
 	nr_parts =
@@ -981,10 +1557,19 @@ static int __init mxcnd_probe(struct pla
 	return 0;
 
 escan:
-	free_irq(host->irq, NULL);
+	free_irq(host->irq, host);
 eirq:
+	if (res2)
+		iounmap(host->nfc_buf);
+eunmap2:
 	iounmap(host->regs);
+eunmap1:
+	release_mem_region(res2->start, resource_size(res2));
+ereq2:
+	release_mem_region(res1->start, resource_size(res1));
+ereq1:
 eres:
+	clk_disable(host->clk);
 	clk_put(host->clk);
 eclk:
 	kfree(host);
@@ -995,46 +1580,63 @@ eclk:
 static int __devexit mxcnd_remove(struct platform_device *pdev)
 {
 	struct mxc_nand_host *host = platform_get_drvdata(pdev);
+	struct resource *res;
 
+	if (host->clk_act)
+		clk_disable(host->clk);
 	clk_put(host->clk);
 
-	platform_set_drvdata(pdev, NULL);
-
 	nand_release(&host->mtd);
-	free_irq(host->irq, NULL);
+	free_irq(host->irq, host);
 	iounmap(host->regs);
 	kfree(host);
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res) {
+		release_mem_region(res->start, resource_size(res));
+	}
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res) {
+		release_mem_region(res->start, resource_size(res));
+	}
 	return 0;
 }
 
 #ifdef CONFIG_PM
 static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	struct mtd_info *info = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = platform_get_drvdata(pdev);
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
 	int ret = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n");
-	if (info)
-		ret = info->suspend(info);
+	if (mtd)
+		ret = mtd->suspend(mtd);
 
-	/* Disable the NFC clock */
-	clk_disable(nfc_clk);	/* FIXME */
+	if (host->clk_act) {
+		/* Disable the NFC clock */
+		clk_disable(host->clk);
+	}
 
 	return ret;
 }
 
 static int mxcnd_resume(struct platform_device *pdev)
 {
-	struct mtd_info *info = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = platform_get_drvdata(pdev);
+	struct nand_chip *nand_chip = mtd->priv;
+	struct mxc_nand_host *host = nand_chip->priv;
 	int ret = 0;
 
 	DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n");
-	/* Enable the NFC clock */
-	clk_enable(nfc_clk);	/* FIXME */
 
-	if (info)
-		info->resume(info);
+	if (host->clk_act) {
+		/* Enable the NFC clock */
+		clk_enable(host->clk);
+	}
+	if (mtd)
+		mtd->resume(mtd);
 
 	return ret;
 }
@@ -1047,7 +1649,7 @@ static int mxcnd_resume(struct platform_
 static struct platform_driver mxcnd_driver = {
 	.driver = {
 		   .name = DRIVER_NAME,
-		   },
+	},
 	.remove = __exit_p(mxcnd_remove),
 	.suspend = mxcnd_suspend,
 	.resume = mxcnd_resume,
@@ -1055,13 +1657,14 @@ static struct platform_driver mxcnd_driv
 
 static int __init mxc_nd_init(void)
 {
+	int ret;
+
 	/* Register the device driver structure. */
-	pr_info("MXC MTD nand Driver\n");
-	if (platform_driver_probe(&mxcnd_driver, mxcnd_probe) != 0) {
+	ret = platform_driver_probe(&mxcnd_driver, mxcnd_probe);
+	if (ret != 0) {
 		printk(KERN_ERR "Driver register failed for mxcnd_driver\n");
-		return -ENODEV;
 	}
-	return 0;
+	return ret;
 }
 
 static void __exit mxc_nd_cleanup(void)
diff -purN linux-2.6.30-rc4-git/drivers/net/Kconfig linux-2.6.30-rc4-karo3/drivers/net/Kconfig
--- linux-2.6.30-rc4-git/drivers/net/Kconfig	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/net/Kconfig	2009-06-02 18:42:32.000000000 +0200
@@ -1859,7 +1859,7 @@ config 68360_ENET
 
 config FEC
 	bool "FEC ethernet controller (of ColdFire CPUs)"
-	depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27
+	depends on M523x || M527x || M5272 || M528x || M520x || M532x || MACH_MX27 || MACH_TX25
 	help
 	  Say Y here if you want to use the built-in 10/100 Fast ethernet
 	  controller on some Motorola ColdFire and Freescale i.MX processors.
diff -purN linux-2.6.30-rc4-git/drivers/net/can/Kconfig linux-2.6.30-rc4-karo3/drivers/net/can/Kconfig
--- linux-2.6.30-rc4-git/drivers/net/can/Kconfig	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/net/can/Kconfig	2009-07-01 11:28:55.000000000 +0200
@@ -22,4 +22,21 @@ config CAN_DEBUG_DEVICES
 	  a problem with CAN support and want to see more of what is going
 	  on.
 
+config CAN_FLEXCAN
+        tristate "Freescale FlexCAN"
+        depends on CAN && (MACH_MX25 || ARCH_MX35)
+        default m
+        ---help---
+          This select the support of Freescale CAN(FlexCAN).
+          This driver can also be built as a module.
+          If unsure, say N.
+
+config CAN_FLEXCAN_CAN1
+	bool "Enable CAN1 interface on i.MX25/i.MX35"
+	depends on CAN_FLEXCAN && (MACH_MX25 && !ARCH_MXC_EHCI_USBOTG)
+
+config CAN_FLEXCAN_CAN2
+	bool "Enable CAN2 interface on i.MX25/i.MX35"
+	depends on CAN_FLEXCAN
+
 endmenu
diff -purN linux-2.6.30-rc4-git/drivers/net/can/Makefile linux-2.6.30-rc4-karo3/drivers/net/can/Makefile
--- linux-2.6.30-rc4-git/drivers/net/can/Makefile	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/net/can/Makefile	2009-07-01 11:29:31.000000000 +0200
@@ -1,5 +1,9 @@
 #
 #  Makefile for the Linux Controller Area Network drivers.
 #
+ifneq ($(CONFIG_CAN_DEBUG_DEVICES),)
+	EXTRA_CFLAGS += -DDEBUG
+endif
 
 obj-$(CONFIG_CAN_VCAN)		+= vcan.o
+obj-$(CONFIG_CAN_FLEXCAN)	+= flexcan.o
diff -purN linux-2.6.30-rc4-git/drivers/net/can/flexcan.c linux-2.6.30-rc4-karo3/drivers/net/can/flexcan.c
--- linux-2.6.30-rc4-git/drivers/net/can/flexcan.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/drivers/net/can/flexcan.c	2009-07-06 15:17:41.000000000 +0200
@@ -0,0 +1,1784 @@
+/*
+ * drivers/net/can/flexcan.c
+ *
+ * Copyright (C) 2009  Lothar Wassmann <LW@KARO-electronics.de>
+ *
+ * based on: drivers/net/can/flexcan/
+ *   Copyright 2008-2009 Freescale Semiconductor, 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
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ */
+
+/*
+ * Driver for Freescale CAN Controller FlexCAN.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <mach/mxc_can.h>
+
+#include "flexcan.h"
+
+#ifdef DEBUG
+static int debug = 0;
+#define dbg_lvl(n)	((n) < debug)
+module_param(debug, int, S_IRUGO | S_IWUSR);
+
+#define DBG(lvl, fmt...)	do { if (dbg_lvl(lvl)) printk(KERN_DEBUG fmt); } while (0)
+#else
+static int debug;
+#define dbg_lvl(n)	0
+module_param(debug, int, 0);
+
+#define DBG(lvl, fmt...)	do { } while (0)
+#endif
+
+#define ndev_dbg(d, l, fmt...)		do { if (dbg_lvl(l)) dev_dbg(&(d)->dev, fmt); } while (0)
+#define pdev_dbg(p, l, fmt...)		do { if (dbg_lvl(l)) dev_dbg(&(p)->dev, fmt); } while (0)
+#define flexcan_dbg(f, l, fmt...)	do { if (dbg_lvl(l)) dev_dbg(&(f)->dev->dev, fmt); } while (0)
+
+#define ndev_err(d, fmt...)	dev_err(&(d)->dev, fmt)
+#define pdev_err(p, fmt...)	dev_err(&(p)->dev, fmt)
+
+enum {
+	FLEXCAN_ATTR_STATE = 0,
+	FLEXCAN_ATTR_BITRATE,
+	FLEXCAN_ATTR_BR_PRESDIV,
+	FLEXCAN_ATTR_BR_RJW,
+	FLEXCAN_ATTR_BR_PROPSEG,
+	FLEXCAN_ATTR_BR_PSEG1,
+	FLEXCAN_ATTR_BR_PSEG2,
+	FLEXCAN_ATTR_BR_CLKSRC,
+	FLEXCAN_ATTR_MAXMB,
+	FLEXCAN_ATTR_XMIT_MAXMB,
+	FLEXCAN_ATTR_FIFO,
+	FLEXCAN_ATTR_WAKEUP,
+	FLEXCAN_ATTR_SRX_DIS,
+	FLEXCAN_ATTR_WAK_SRC,
+	FLEXCAN_ATTR_BCC,
+	FLEXCAN_ATTR_LOCAL_PRIORITY,
+	FLEXCAN_ATTR_ABORT,
+	FLEXCAN_ATTR_LOOPBACK,
+	FLEXCAN_ATTR_SMP,
+	FLEXCAN_ATTR_BOFF_REC,
+	FLEXCAN_ATTR_TSYN,
+	FLEXCAN_ATTR_LISTEN,
+	FLEXCAN_ATTR_EXTEND_MSG,
+	FLEXCAN_ATTR_STANDARD_MSG,
+#ifdef CONFIG_CAN_DEBUG_DEVICES
+	FLEXCAN_ATTR_DUMP_REG,
+	FLEXCAN_ATTR_DUMP_XMIT_MB,
+	FLEXCAN_ATTR_DUMP_RX_MB,
+#endif
+	FLEXCAN_ATTR_MAX
+};
+
+#ifdef DEBUG
+#define flexcan_reg_read(f,r)	_flexcan_reg_read(f, r, #r, __FUNCTION__)
+static inline unsigned long _flexcan_reg_read(struct flexcan_device *flexcan, int reg,
+					      const char *name, const char *fn)
+{
+	unsigned long val;
+	val = __raw_readl(flexcan->io_base + reg);
+	DBG(2, "%s: Read %08lx from %s[%p]\n", fn, val, name,
+	    flexcan->io_base + reg);
+	return val;
+}
+
+#define flexcan_reg_write(f,r,v)	_flexcan_reg_write(f, r, v, #r, __FUNCTION__)
+static inline void _flexcan_reg_write(struct flexcan_device *flexcan, int reg, unsigned long val,
+				      const char *name, const char *fn)
+{
+	DBG(2, "%s: Writing %08lx to %s[%p]\n", fn, val, name, flexcan->io_base + reg);
+	__raw_writel(val, flexcan->io_base + reg);
+}
+#else
+static inline unsigned long flexcan_reg_read(struct flexcan_device *flexcan, int reg)
+{
+	return __raw_readl(flexcan->io_base + reg);
+}
+
+static inline void flexcan_reg_write(struct flexcan_device *flexcan, int reg, unsigned long val)
+{
+	__raw_writel(val, flexcan->io_base + reg);
+}
+#endif
+
+static ssize_t flexcan_show_attr(struct device *dev,
+				 struct device_attribute *attr, char *buf);
+static ssize_t flexcan_set_attr(struct device *dev,
+				struct device_attribute *attr, const char *buf,
+				size_t count);
+
+static struct device_attribute flexcan_dev_attr[FLEXCAN_ATTR_MAX] = {
+	[FLEXCAN_ATTR_STATE] = __ATTR(state, 0444, flexcan_show_attr, NULL),
+	[FLEXCAN_ATTR_BITRATE] =
+	    __ATTR(bitrate, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_BR_PRESDIV] =
+	    __ATTR(br_presdiv, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_BR_RJW] =
+	    __ATTR(br_rjw, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_BR_PROPSEG] =
+	    __ATTR(br_propseg, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_BR_PSEG1] =
+	    __ATTR(br_pseg1, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_BR_PSEG2] =
+	    __ATTR(br_pseg2, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_BR_CLKSRC] =
+	    __ATTR(br_clksrc, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_MAXMB] =
+	    __ATTR(maxmb, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_XMIT_MAXMB] =
+	    __ATTR(xmit_maxmb, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_FIFO] =
+	    __ATTR(fifo, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_WAKEUP] =
+	    __ATTR(wakeup, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_SRX_DIS] =
+	    __ATTR(srx_dis, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_WAK_SRC] =
+	    __ATTR(wak_src, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_BCC] =
+	    __ATTR(bcc, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_LOCAL_PRIORITY] =
+	    __ATTR(local_priority, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_ABORT] =
+	    __ATTR(abort, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_LOOPBACK] =
+	    __ATTR(loopback, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_SMP] =
+	    __ATTR(smp, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_BOFF_REC] =
+	    __ATTR(boff_rec, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_TSYN] =
+	    __ATTR(tsyn, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_LISTEN] =
+	    __ATTR(listen, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_EXTEND_MSG] =
+	    __ATTR(ext_msg, 0644, flexcan_show_attr, flexcan_set_attr),
+	[FLEXCAN_ATTR_STANDARD_MSG] =
+	    __ATTR(std_msg, 0644, flexcan_show_attr, flexcan_set_attr),
+#ifdef CONFIG_CAN_DEBUG_DEVICES
+	[FLEXCAN_ATTR_DUMP_REG] =
+	    __ATTR(dump_reg, 0444, flexcan_show_attr, NULL),
+	[FLEXCAN_ATTR_DUMP_XMIT_MB] =
+	    __ATTR(dump_xmit_mb, 0444, flexcan_show_attr, NULL),
+	[FLEXCAN_ATTR_DUMP_RX_MB] =
+	    __ATTR(dump_rx_mb, 0444, flexcan_show_attr, NULL),
+#endif
+};
+
+static void flexcan_set_bitrate(struct flexcan_device *flexcan, int bitrate)
+{
+	/* TODO:: implement in future
+	 * based on the bitrate to get the timing of
+	 * presdiv, pseg1, pseg2, propseg
+	 */
+}
+
+static void flexcan_update_bitrate(struct flexcan_device *flexcan)
+{
+	int rate, div;
+
+	if (flexcan->br_clksrc)
+		rate = clk_get_rate(flexcan->clk);
+	else {
+		struct clk *clk;
+		clk = clk_get_sys(NULL, "ckih");
+		if (IS_ERR(clk))
+			return;
+		rate = clk_get_rate(clk);
+		clk_put(clk);
+	}
+	if (!rate)
+		return;
+
+	flexcan_dbg(flexcan, 0, "%s: master clock rate %u from %s\n",
+		    __FUNCTION__, rate, flexcan->br_clksrc ? "osc" : "pll");
+
+	div = flexcan->br_presdiv + 1;
+	div *= flexcan->br_propseg + flexcan->br_pseg1 + flexcan->br_pseg2 + 4;
+	flexcan->bitrate = (rate + div - 1) / div;
+
+	flexcan_dbg(flexcan, 0, "%s: flexcan bitrate %u time quantum %uns\n",
+		    __FUNCTION__, flexcan->bitrate,
+		    1000000000 / (flexcan->bitrate *
+				  (flexcan->br_propseg + flexcan->br_pseg1 +
+				   flexcan->br_pseg2 + 4)));
+}
+
+static inline void flexcan_read_hw_mb(struct flexcan_device *flexcan, struct can_hw_mb *mb,
+				      int buf_no)
+{
+	__raw_readsl(mb, flexcan->hwmb + buf_no * sizeof(*mb), sizeof(*mb));
+}
+
+static inline void flexcan_write_hw_mb(struct flexcan_device *flexcan, struct can_hw_mb *mb,
+				       int buf_no)
+{
+	__raw_writesl(flexcan->hwmb + buf_no * sizeof(*mb), mb, sizeof(*mb));
+}
+
+#ifdef CONFIG_CAN_DEBUG_DEVICES
+static int flexcan_dump_reg(struct flexcan_device *flexcan, char *buf)
+{
+	int ret = 0;
+	unsigned int reg;
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_MCR);
+	ret += sprintf(buf + ret, "MCR::0x%08x\n", reg);
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_CTRL);
+	ret += sprintf(buf + ret, "CTRL::0x%08x\n", reg);
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_RXGMASK);
+	ret += sprintf(buf + ret, "RXGMASK::0x%08x\n", reg);
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_RX14MASK);
+	ret += sprintf(buf + ret, "RX14MASK::0x%08x\n", reg);
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_RX15MASK);
+	ret += sprintf(buf + ret, "RX15MASK::0x%08x\n", reg);
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_ECR);
+	ret += sprintf(buf + ret, "ECR::0x%08x\n", reg);
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_ESR);
+	ret += sprintf(buf + ret, "ESR::0x%08x\n", reg);
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_IMASK2);
+	ret += sprintf(buf + ret, "IMASK2::0x%08x\n", reg);
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_IMASK1);
+	ret += sprintf(buf + ret, "IMASK1::0x%08x\n", reg);
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_IFLAG2);
+	ret += sprintf(buf + ret, "IFLAG2::0x%08x\n", reg);
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_IFLAG1);
+	ret += sprintf(buf + ret, "IFLAG1::0x%08x\n", reg);
+	return ret;
+}
+
+static int flexcan_dump_xmit_mb(struct flexcan_device *flexcan, char *buf)
+{
+	int ret = 0, i;
+
+	clk_enable(flexcan->clk);
+	for (i = flexcan->xmit_maxmb + 1; i <= flexcan->maxmb; i++) {
+		int j;
+
+		ret += sprintf(buf + ret,
+			       "mb[%d]::CS:0x%08x ID:0x%08x DATA",
+			       i, flexcan->hwmb[i].mb_cs.data,
+			       flexcan->hwmb[i].mb_id);
+		for (j = 0; j < sizeof(flexcan->hwmb[i].mb_data); j++) {
+			ret += sprintf(buf + ret, ":%02x",
+				       flexcan->hwmb[i].mb_data[j]);
+		}
+		ret += sprintf(buf + ret, "\n");
+	}
+	clk_disable(flexcan->clk);
+	return ret;
+}
+
+static int flexcan_dump_rx_mb(struct flexcan_device *flexcan, char *buf)
+{
+	int ret = 0, i;
+
+	clk_enable(flexcan->clk);
+	for (i = 0; i <= flexcan->xmit_maxmb; i++) {
+		int j;
+
+		ret += sprintf(buf + ret,
+			       "mb[%d]::CS:0x%08x ID:0x%08x DATA",
+			       i, flexcan->hwmb[i].mb_cs.data,
+			       flexcan->hwmb[i].mb_id);
+		for (j = 0; j < sizeof(flexcan->hwmb[i].mb_data); j++) {
+			ret += sprintf(buf + ret, ":%02x",
+				       flexcan->hwmb[i].mb_data[j]);
+		}
+		ret += sprintf(buf + ret, "\n");
+	}
+	clk_disable(flexcan->clk);
+	return ret;
+}
+#endif
+
+static ssize_t flexcan_show_state(struct net_device *net, char *buf)
+{
+	int ret, esr;
+	struct flexcan_device *flexcan = netdev_priv(net);
+
+	ret = sprintf(buf, "%s::", netif_running(net) ? "Start" : "Stop");
+	if (netif_carrier_ok(net)) {
+		esr = flexcan_reg_read(flexcan, CAN_HW_REG_ESR);
+		switch ((esr & __ESR_FLT_CONF_MASK) >> __ESR_FLT_CONF_OFF) {
+		case 0:
+			ret += sprintf(buf + ret, "normal\n");
+			break;
+		case 1:
+			ret += sprintf(buf + ret, "error passive\n");
+			break;
+		default:
+			ret += sprintf(buf + ret, "bus off\n");
+		}
+	} else
+		ret += sprintf(buf + ret, "bus off\n");
+	return ret;
+}
+
+static ssize_t flexcan_show_attr(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	int attr_id;
+	struct net_device *net = dev_get_drvdata(dev);
+	struct flexcan_device *flexcan = netdev_priv(net);
+
+	attr_id = attr - flexcan_dev_attr;
+	switch (attr_id) {
+	case FLEXCAN_ATTR_STATE:
+		return flexcan_show_state(net, buf);
+	case FLEXCAN_ATTR_BITRATE:
+		return sprintf(buf, "%d\n", flexcan->bitrate);
+	case FLEXCAN_ATTR_BR_PRESDIV:
+		return sprintf(buf, "%d\n", flexcan->br_presdiv + 1);
+	case FLEXCAN_ATTR_BR_RJW:
+		return sprintf(buf, "%d\n", flexcan->br_rjw);
+	case FLEXCAN_ATTR_BR_PROPSEG:
+		return sprintf(buf, "%d\n", flexcan->br_propseg + 1);
+	case FLEXCAN_ATTR_BR_PSEG1:
+		return sprintf(buf, "%d\n", flexcan->br_pseg1 + 1);
+	case FLEXCAN_ATTR_BR_PSEG2:
+		return sprintf(buf, "%d\n", flexcan->br_pseg2 + 1);
+	case FLEXCAN_ATTR_BR_CLKSRC:
+		return sprintf(buf, "%s\n", flexcan->br_clksrc ? "bus" : "osc");
+	case FLEXCAN_ATTR_MAXMB:
+		return sprintf(buf, "%d\n", flexcan->maxmb + 1);
+	case FLEXCAN_ATTR_XMIT_MAXMB:
+		return sprintf(buf, "%d\n", flexcan->xmit_maxmb + 1);
+	case FLEXCAN_ATTR_FIFO:
+		return sprintf(buf, "%d\n", flexcan->fifo);
+	case FLEXCAN_ATTR_WAKEUP:
+		return sprintf(buf, "%d\n", flexcan->wakeup);
+	case FLEXCAN_ATTR_SRX_DIS:
+		return sprintf(buf, "%d\n", flexcan->srx_dis);
+	case FLEXCAN_ATTR_WAK_SRC:
+		return sprintf(buf, "%d\n", flexcan->wak_src);
+	case FLEXCAN_ATTR_BCC:
+		return sprintf(buf, "%d\n", flexcan->bcc);
+	case FLEXCAN_ATTR_LOCAL_PRIORITY:
+		return sprintf(buf, "%d\n", flexcan->lprio);
+	case FLEXCAN_ATTR_ABORT:
+		return sprintf(buf, "%d\n", flexcan->abort);
+	case FLEXCAN_ATTR_LOOPBACK:
+		return sprintf(buf, "%d\n", flexcan->loopback);
+	case FLEXCAN_ATTR_SMP:
+		return sprintf(buf, "%d\n", flexcan->smp);
+	case FLEXCAN_ATTR_BOFF_REC:
+		return sprintf(buf, "%d\n", flexcan->boff_rec);
+	case FLEXCAN_ATTR_TSYN:
+		return sprintf(buf, "%d\n", flexcan->tsyn);
+	case FLEXCAN_ATTR_LISTEN:
+		return sprintf(buf, "%d\n", flexcan->listen);
+	case FLEXCAN_ATTR_EXTEND_MSG:
+		return sprintf(buf, "%d\n", flexcan->ext_msg);
+	case FLEXCAN_ATTR_STANDARD_MSG:
+		return sprintf(buf, "%d\n", flexcan->std_msg);
+#ifdef CONFIG_CAN_DEBUG_DEVICES
+	case FLEXCAN_ATTR_DUMP_REG:
+		return flexcan_dump_reg(flexcan, buf);
+	case FLEXCAN_ATTR_DUMP_XMIT_MB:
+		return flexcan_dump_xmit_mb(flexcan, buf);
+	case FLEXCAN_ATTR_DUMP_RX_MB:
+		return flexcan_dump_rx_mb(flexcan, buf);
+#endif
+	default:
+		return sprintf(buf, "%s:%p->%p\n", __func__, flexcan_dev_attr,
+			       attr);
+	}
+}
+
+static ssize_t flexcan_set_attr(struct device *dev,
+				struct device_attribute *attr, const char *buf,
+				size_t count)
+{
+	int attr_id, tmp;
+	struct net_device *net = dev_get_drvdata(dev);
+	struct flexcan_device *flexcan = netdev_priv(net);
+
+	attr_id = attr - flexcan_dev_attr;
+
+	mutex_lock(&flexcan->mutex);
+
+	if (netif_running(net))
+		goto set_finish;
+
+	if (attr_id == FLEXCAN_ATTR_BR_CLKSRC) {
+		if (!strcasecmp(buf, "bus"))
+			flexcan->br_clksrc = 1;
+		else if (!strcasecmp(buf, "osc"))
+			flexcan->br_clksrc = 0;
+		goto set_finish;
+	}
+
+	tmp = simple_strtoul(buf, NULL, 0);
+	switch (attr_id) {
+	case FLEXCAN_ATTR_BITRATE:
+		flexcan_set_bitrate(flexcan, tmp);
+		break;
+	case FLEXCAN_ATTR_BR_PRESDIV:
+		if ((tmp > 0) && (tmp <= FLEXCAN_MAX_PRESDIV)) {
+			flexcan->br_presdiv = tmp - 1;
+			flexcan_update_bitrate(flexcan);
+		}
+		break;
+	case FLEXCAN_ATTR_BR_RJW:
+		if ((tmp > 0) && (tmp <= FLEXCAN_MAX_RJW))
+			flexcan->br_rjw = tmp - 1;
+		break;
+	case FLEXCAN_ATTR_BR_PROPSEG:
+		if ((tmp > 0) && (tmp <= FLEXCAN_MAX_PROPSEG)) {
+			flexcan->br_propseg = tmp - 1;
+			flexcan_update_bitrate(flexcan);
+		}
+		break;
+	case FLEXCAN_ATTR_BR_PSEG1:
+		if ((tmp > 0) && (tmp <= FLEXCAN_MAX_PSEG1)) {
+			flexcan->br_pseg1 = tmp - 1;
+			flexcan_update_bitrate(flexcan);
+		}
+		break;
+	case FLEXCAN_ATTR_BR_PSEG2:
+		if ((tmp > 0) && (tmp <= FLEXCAN_MAX_PSEG2)) {
+			flexcan->br_pseg2 = tmp - 1;
+			flexcan_update_bitrate(flexcan);
+		}
+		break;
+	case FLEXCAN_ATTR_MAXMB:
+		if ((tmp > 0) && (tmp <= FLEXCAN_MAX_MB)) {
+			if (flexcan->maxmb != (tmp - 1)) {
+				flexcan->maxmb = tmp - 1;
+				if (flexcan->xmit_maxmb < flexcan->maxmb)
+					flexcan->xmit_maxmb = flexcan->maxmb;
+			}
+		}
+		break;
+	case FLEXCAN_ATTR_XMIT_MAXMB:
+		if ((tmp > 0) && (tmp <= (flexcan->maxmb + 1))) {
+			if (flexcan->xmit_maxmb != (tmp - 1))
+				flexcan->xmit_maxmb = tmp - 1;
+		}
+		break;
+	case FLEXCAN_ATTR_FIFO:
+		flexcan->fifo = !!tmp;
+		break;
+	case FLEXCAN_ATTR_WAKEUP:
+		flexcan->wakeup = !!tmp;
+		break;
+	case FLEXCAN_ATTR_SRX_DIS:
+		flexcan->srx_dis = !!tmp;
+		break;
+	case FLEXCAN_ATTR_WAK_SRC:
+		flexcan->wak_src = !!tmp;
+		break;
+	case FLEXCAN_ATTR_BCC:
+		flexcan->bcc = !!tmp;
+		break;
+	case FLEXCAN_ATTR_LOCAL_PRIORITY:
+		flexcan->lprio = !!tmp;
+		break;
+	case FLEXCAN_ATTR_ABORT:
+		flexcan->abort = !!tmp;
+		break;
+	case FLEXCAN_ATTR_LOOPBACK:
+		flexcan->loopback = !!tmp;
+		break;
+	case FLEXCAN_ATTR_SMP:
+		flexcan->smp = !!tmp;
+		break;
+	case FLEXCAN_ATTR_BOFF_REC:
+		flexcan->boff_rec = !!tmp;
+		break;
+	case FLEXCAN_ATTR_TSYN:
+		flexcan->tsyn = !!tmp;
+		break;
+	case FLEXCAN_ATTR_LISTEN:
+		flexcan->listen = !!tmp;
+		break;
+	case FLEXCAN_ATTR_EXTEND_MSG:
+		flexcan->ext_msg = !!tmp;
+		break;
+	case FLEXCAN_ATTR_STANDARD_MSG:
+		flexcan->std_msg = !!tmp;
+		break;
+	}
+ set_finish:
+	mutex_unlock(&flexcan->mutex);
+	return count;
+}
+
+static void flexcan_device_default(struct flexcan_device *dev)
+{
+	dev->br_clksrc = 1;
+	dev->br_rjw = 2;
+	dev->br_presdiv = 6;
+	dev->br_propseg = 4;
+	dev->br_pseg1 = 4;
+	dev->br_pseg2 = 7;
+
+	dev->bcc = 1;
+	dev->srx_dis = 1;
+	dev->smp = 1;
+	dev->abort = 1;
+
+	dev->maxmb = FLEXCAN_MAX_MB - 1;
+	dev->xmit_maxmb = (FLEXCAN_MAX_MB >> 1) - 1;
+	dev->xmit_mb = dev->maxmb - dev->xmit_maxmb;
+
+	dev->ext_msg = 1;
+	dev->std_msg = 1;
+}
+
+static int flexcan_device_attach(struct flexcan_device *flexcan)
+{
+	int ret;
+	struct resource *res;
+	struct platform_device *pdev = flexcan->dev;
+	struct flexcan_platform_data *plat_data = pdev->dev.platform_data;
+	int irq;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return -ENODEV;
+
+	if (!request_mem_region(res->start, resource_size(res), "flexcan")) {
+		return -EBUSY;
+	}
+
+	flexcan->irq = irq;
+	flexcan->io_base = ioremap_nocache(res->start, resource_size(res));
+	if (!flexcan->io_base) {
+		ret = -ENOMEM;
+		goto release;
+	}
+	pdev_dbg(pdev, 0, "controller registers %08lx remapped to %p\n",
+		 (unsigned long)res->start, flexcan->io_base);
+
+	flexcan->hwmb = flexcan->io_base + CAN_MB_BASE;
+	flexcan->rx_mask = flexcan->io_base + CAN_RXMASK_BASE;
+
+	flexcan->clk = clk_get(&pdev->dev, "can_clk");
+	if (IS_ERR(flexcan->clk)) {
+		ret = PTR_ERR(flexcan->clk);
+		dev_err(&pdev->dev, "Failed to get clock: %d\n", ret);
+		goto unmap;
+	}
+
+	if (plat_data) {
+		if (plat_data->active) {
+			ret = plat_data->active(pdev);
+			if (ret)
+				goto put_clk;
+		}
+		if (plat_data->core_reg) {
+			flexcan->core_reg = regulator_get(&pdev->dev,
+							  plat_data->core_reg);
+			if (IS_ERR(flexcan->core_reg)) {
+				ret = PTR_ERR(flexcan->core_reg);
+				goto deactivate;
+			}
+		}
+
+		if (plat_data->io_reg) {
+			flexcan->io_reg = regulator_get(&pdev->dev,
+							plat_data->io_reg);
+			if (IS_ERR(flexcan->core_reg)) {
+				ret = PTR_ERR(flexcan->io_reg);
+				goto put_reg;
+			}
+		}
+	}
+	return 0;
+
+ put_reg:
+	regulator_put(flexcan->core_reg);
+ deactivate:
+	if (plat_data->inactive)
+		plat_data->inactive(pdev);
+ put_clk:
+	clk_put(flexcan->clk);
+ unmap:
+	iounmap(flexcan->io_base);
+ release:
+	release_mem_region(res->start, resource_size(res));
+	return ret;
+}
+
+static void flexcan_device_detach(struct flexcan_device *flexcan)
+{
+	struct platform_device *pdev = flexcan->dev;
+	struct flexcan_platform_data *plat_data = pdev->dev.platform_data;
+	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	BUG_ON(!res);
+
+	clk_put(flexcan->clk);
+
+	if (flexcan->io_reg) {
+		regulator_put(flexcan->io_reg);
+	}
+
+	if (flexcan->core_reg) {
+		regulator_put(flexcan->core_reg);
+	}
+
+	if (plat_data && plat_data->inactive)
+		plat_data->inactive(pdev);
+
+	iounmap(flexcan->io_base);
+	release_mem_region(res->start, resource_size(res));
+}
+
+static void flexcan_mbm_isr(struct work_struct *work);
+static void flexcan_err_handler(struct work_struct *work);
+
+static struct net_device *flexcan_device_alloc(struct platform_device *pdev,
+					       void (*setup)(struct net_device *dev))
+{
+	struct flexcan_device *flexcan;
+	struct net_device *net;
+	int i, num;
+	int ret;
+
+	net = alloc_netdev(sizeof(*flexcan), "can%d", setup);
+	if (net == NULL) {
+		pdev_err(pdev, "Failed to allocate netdevice\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	flexcan = netdev_priv(net);
+
+	init_timer(&flexcan->timer);
+	mutex_init(&flexcan->mutex);
+	INIT_WORK(&flexcan->mb_work, flexcan_mbm_isr);
+	INIT_WORK(&flexcan->err_work, flexcan_err_handler);
+
+	flexcan->dev = pdev;
+	ret = flexcan_device_attach(flexcan);
+	if (ret) {
+		free_netdev(net);
+		return ERR_PTR(ret);
+	}
+	flexcan_device_default(flexcan);
+	flexcan_update_bitrate(flexcan);
+
+	num = ARRAY_SIZE(flexcan_dev_attr);
+
+	for (i = 0; i < num; i++) {
+		ret = device_create_file(&pdev->dev, flexcan_dev_attr + i);
+		if (ret) {
+			pdev_err(pdev, "Failed to create attribute file %s: %d\n",
+				(flexcan_dev_attr + i)->attr.name, ret);
+			for (i--; i >= 0; i--)
+				device_remove_file(&pdev->dev, flexcan_dev_attr + i);
+			flexcan_device_detach(flexcan);
+			free_netdev(net);
+			return ERR_PTR(ret);
+		}
+	}
+	platform_set_drvdata(pdev, net);
+	return net;
+}
+
+static void flexcan_device_free(struct net_device *dev)
+{
+	struct flexcan_device *flexcan = netdev_priv(dev);
+	struct platform_device *pdev = flexcan->dev;
+	int i;
+
+	ndev_dbg(dev, 0, "%s: Deleting timer\n", __FUNCTION__);
+	del_timer_sync(&flexcan->timer);
+
+	ndev_dbg(dev, 0, "%s: Removing sysfs files\n", __FUNCTION__);
+	for (i = 0; i < ARRAY_SIZE(flexcan_dev_attr); i++)
+		device_remove_file(&pdev->dev, flexcan_dev_attr + i);
+
+	ndev_dbg(dev, 0, "%s: Detaching can device\n", __FUNCTION__);
+	flexcan_device_detach(flexcan);
+	ndev_dbg(dev, 0, "%s: Freeing net_device\n", __FUNCTION__);
+	free_netdev(dev);
+}
+
+#define flexcan_swab32(x)				\
+	(((x) << 24) | ((x) >> 24) |			\
+		(((x) & (__u32)0x0000ff00UL) << 8) |	\
+		(((x) & (__u32)0x00ff0000UL) >> 8))
+
+static inline void flexcan_mb_write(struct can_frame *frame, struct can_hw_mb __iomem *hwmb,
+				    int code)
+{
+	int i;
+	unsigned long __iomem *s = (unsigned long *)&frame->data[0];
+	unsigned long __iomem *d = (unsigned long *)&hwmb->mb_data[0];
+	struct can_hw_mb mb;
+	unsigned int can_id;
+	int n_words = (frame->can_dlc + 3) / sizeof(unsigned int);
+
+	mb.mb_cs.data = 0;
+	mb.mb_cs.cs.code = code;
+	mb.mb_cs.cs.length = frame->can_dlc;
+
+	mb.mb_cs.cs.rtr = !!(frame->can_id & CAN_RTR_FLAG);
+
+	if (frame->can_id & CAN_EFF_FLAG) {
+		mb.mb_cs.cs.ide = 1;
+		mb.mb_cs.cs.srr = 1;
+		can_id = frame->can_id & CAN_EFF_MASK;
+	} else {
+		mb.mb_cs.cs.ide = 0;
+		can_id = (frame->can_id & CAN_SFF_MASK) << 18;
+	}
+
+	DBG(0, "%s: writing can_id %08x to mb_id %p\n", __FUNCTION__, can_id, &hwmb->mb_id);
+	__raw_writel(can_id, &hwmb->mb_id);
+	for (i = 0; i < n_words; i++, s++, d++) {
+		DBG(0, "%s: writing data %08lx to mb_data %p\n", __FUNCTION__,
+		    flexcan_swab32(*s), d);
+		__raw_writel(flexcan_swab32(*s), d);
+	}
+	DBG(0, "%s: Writing CS %08x to mb_cs %p\n", __FUNCTION__, mb.mb_cs.data, &hwmb->mb_cs);
+	__raw_writel(mb.mb_cs.data, &hwmb->mb_cs.data);
+}
+
+static inline void flexcan_mb_read(struct can_frame *frame, struct can_hw_mb __iomem *hwmb)
+{
+	int i;
+	unsigned long __iomem *s = (unsigned long *)&hwmb->mb_data[0];
+	unsigned long __iomem *d = (unsigned long *)&frame->data[0];
+	struct can_hw_mb mb;
+	unsigned int can_id;
+	int n_words;
+
+	mb.mb_cs.data = __raw_readl(&hwmb->mb_cs);
+	BUG_ON(mb.mb_cs.cs.code & CAN_MB_RX_BUSY);
+
+	can_id = __raw_readl(&hwmb->mb_id);
+
+	if (mb.mb_cs.cs.ide)
+		frame->can_id = (can_id & CAN_EFF_MASK) | CAN_EFF_FLAG;
+	else
+		frame->can_id = (can_id >> 18) & CAN_SFF_MASK;
+	if (mb.mb_cs.cs.rtr)
+		frame->can_id |= CAN_RTR_FLAG;
+
+	frame->can_dlc = mb.mb_cs.cs.length;
+	if (frame->can_dlc == 0 || frame->can_dlc > 8)
+		return;
+
+	n_words = (frame->can_dlc + 3) / sizeof(unsigned int);
+	for (i = 0; i < n_words; i++, s++, d++)
+		*d = flexcan_swab32(__raw_readl(s));
+}
+
+static inline void flexcan_memcpy(void *dst, void *src, int len)
+{
+	int i;
+	unsigned int __iomem *d = dst, *s = src;
+
+	DBG(2, "%s: Copying %u byte from %p to %p\n", __FUNCTION__, len, s, d);
+	WARN_ON(len & 3);
+	len = (len + 3) >> 2;
+	for (i = 0; i < len; i++, s++, d++)
+		__raw_writel(flexcan_swab32(*s), d);
+	if (dbg_lvl(1)) {
+		print_hex_dump(KERN_DEBUG, "swdat: ", DUMP_PREFIX_OFFSET, 16, 4,
+			       src, len << 2, 0);
+		print_hex_dump(KERN_DEBUG, "hwdat: ", DUMP_PREFIX_OFFSET, 16, 4,
+			       dst, len << 2, 0);
+	}
+}
+
+static inline struct can_frame *flexcan_skb_put(struct sk_buff *skb, unsigned int len)
+{
+	return (struct can_frame *)skb_put(skb, len);
+}
+
+static inline struct can_frame *flexcan_skb_data(struct sk_buff *skb)
+{
+	BUG_ON(skb == NULL);
+	return (struct can_frame *)skb->data;
+}
+
+static struct net_device_stats *flexcan_get_stats(struct net_device *dev)
+{
+	ndev_dbg(dev, 3, "%s@%d: \n", __FUNCTION__, __LINE__);
+	if (!netif_running(dev))
+		return &dev->stats;
+	ndev_dbg(dev, 3, "%s@%d: \n", __FUNCTION__, __LINE__);
+	return &dev->stats;
+}
+
+static void flexcan_mb_bottom(struct net_device *dev, int index)
+{
+	struct flexcan_device *flexcan = netdev_priv(dev);
+	struct net_device_stats *stats = flexcan_get_stats(dev);
+	struct can_hw_mb __iomem *hwmb;
+	struct can_frame *frame;
+	struct sk_buff *skb;
+	struct can_hw_mb mb;
+
+	ndev_dbg(dev, 1, "%s: index: %d\n", __FUNCTION__, index);
+
+	hwmb = flexcan->hwmb + index;
+	mb.mb_cs.data = __raw_readl(&hwmb->mb_cs.data);
+	if (flexcan->fifo ||
+	    index >= flexcan->maxmb - flexcan->xmit_maxmb) {
+		/* handle transmit MBs */
+
+		if (mb.mb_cs.cs.code == CAN_MB_TX_ABORT) {
+			mb.mb_cs.cs.code = CAN_MB_TX_INACTIVE;
+			__raw_writel(mb.mb_cs.data, &hwmb->mb_cs.data);
+		}
+		if (mb.mb_cs.cs.code & CAN_MB_TX_INACTIVE) {
+			if (flexcan->xmit_buffers++ == 0) {
+				ndev_dbg(dev, 1, "%s: Starting netif queue\n", __FUNCTION__);
+				netif_start_queue(dev);
+			}
+			BUG_ON(flexcan->xmit_buffers > flexcan->maxmb - flexcan->xmit_maxmb);
+			return;
+		}
+		/* if fifo is enabled all RX MBs should be handled in the fifo_isr */
+		BUG();
+	}
+	if (dbg_lvl(1))
+		print_hex_dump(KERN_DEBUG, "rx_mb: ", DUMP_PREFIX_OFFSET, 16, 4,
+			       hwmb, sizeof(*hwmb), 0);
+	/* handle RX MB in case fifo is not used */
+	BUG_ON(flexcan->fifo);
+	if (mb.mb_cs.cs.code & CAN_MB_RX_BUSY) {
+		ndev_dbg(dev, -1, "%s: MB[%02x] is busy: %x\n", __FUNCTION__,
+			 index, mb.mb_cs.cs.code);
+		/* unlock buffer */
+		(void)flexcan_reg_read(flexcan, CAN_HW_REG_TIMER);
+		return;
+	}
+
+	skb = dev_alloc_skb(sizeof(struct can_frame));
+	if (skb) {
+		frame = flexcan_skb_put(skb, sizeof(*frame));
+		flexcan_mb_read(frame, hwmb);
+		/* unlock buffer */
+		(void)flexcan_reg_read(flexcan, CAN_HW_REG_TIMER);
+
+		dev->last_rx = jiffies;
+		stats->rx_packets++;
+		stats->rx_bytes += frame->can_dlc;
+
+		skb->dev = dev;
+		skb->protocol = __constant_htons(ETH_P_CAN);
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
+		netif_receive_skb(skb);
+	} else {
+		flexcan_dbg(flexcan, 0, "%s: Could not allocate SKB; dropping packet\n",
+			    __FUNCTION__);
+
+		stats->rx_dropped++;
+	}
+}
+
+static void flexcan_fifo_isr(struct net_device *dev, unsigned int iflag1)
+{
+	struct flexcan_device *flexcan = netdev_priv(dev);
+	struct net_device_stats *stats = flexcan_get_stats(dev);
+	struct sk_buff *skb;
+	struct can_hw_mb __iomem *hwmb = flexcan->hwmb;
+	struct can_frame *frame;
+
+	ndev_dbg(dev, 2, "%s: \n", __FUNCTION__);
+	if (dbg_lvl(1))
+		print_hex_dump(KERN_DEBUG, "rx_mb: ", DUMP_PREFIX_OFFSET, 16, 4,
+			       hwmb, sizeof(*hwmb), 0);
+	if (iflag1 & __FIFO_RDY_INT) {
+		skb = dev_alloc_skb(sizeof(struct can_frame));
+		if (skb) {
+			frame = flexcan_skb_put(skb, sizeof(*frame));
+			flexcan_mb_read(frame, hwmb);
+			/* unlock mb */
+			(void) flexcan_reg_read(flexcan, CAN_HW_REG_TIMER);
+
+			dev->last_rx = jiffies;
+
+			stats->rx_packets++;
+			stats->rx_bytes += frame->can_dlc;
+
+			skb->dev = dev;
+			skb->protocol = __constant_htons(ETH_P_CAN);
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			netif_receive_skb(skb);
+		} else {
+			(void)__raw_readl(&hwmb->mb_cs.data);
+			/* unlock mb */
+			(void) flexcan_reg_read(flexcan, CAN_HW_REG_TIMER);
+		}
+	}
+
+	if (iflag1 & (__FIFO_OV_INT | __FIFO_WARN_INT)) {
+		skb = dev_alloc_skb(sizeof(struct can_frame));
+		if (skb) {
+			frame = flexcan_skb_put(skb, sizeof(*frame));
+			frame->can_id = CAN_ERR_FLAG | CAN_ERR_CRTL;
+			frame->can_dlc = CAN_ERR_DLC;
+			if (iflag1 & __FIFO_WARN_INT)
+				frame->data[1] |=
+				    CAN_ERR_CRTL_TX_WARNING |
+				    CAN_ERR_CRTL_RX_WARNING;
+			if (iflag1 & __FIFO_OV_INT)
+				frame->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
+			if (dbg_lvl(1))
+				print_hex_dump(KERN_DEBUG, "err_mb: ", DUMP_PREFIX_OFFSET, 16, 4,
+					       frame, sizeof(*frame), 0);
+
+			skb->dev = dev;
+			skb->protocol = __constant_htons(ETH_P_CAN);
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			netif_receive_skb(skb);
+		}
+	}
+}
+
+/*
+ * called by CAN ISR to handle mb events.
+ */
+static void flexcan_mbm_isr(struct work_struct *work)
+{
+	struct flexcan_device *flexcan = container_of(work, struct flexcan_device, mb_work);
+	struct net_device *dev = platform_get_drvdata(flexcan->dev);
+	int i, iflag1, iflag2, maxmb;
+
+	i = 0;
+
+	ndev_dbg(dev, 2, "%s: \n", __FUNCTION__);
+
+	iflag1 = flexcan_reg_read(flexcan, CAN_HW_REG_IFLAG1) &
+		flexcan_reg_read(flexcan, CAN_HW_REG_IMASK1);
+	if (flexcan->maxmb > 31) {
+		maxmb = flexcan->maxmb + 1 - 32;
+		iflag2 = flexcan_reg_read(flexcan, CAN_HW_REG_IFLAG2) &
+		    flexcan_reg_read(flexcan, CAN_HW_REG_IMASK2);
+		iflag2 &= (1 << maxmb) - 1;
+		maxmb = 32;
+	} else {
+		maxmb = flexcan->maxmb + 1;
+		iflag1 &= (1 << maxmb) - 1;
+		iflag2 = 0;
+	}
+
+	ndev_dbg(dev, 2, "%s: loop=%d iflag1=%08x\n", __FUNCTION__, i, iflag1);
+
+	flexcan_reg_write(flexcan, CAN_HW_REG_IFLAG1, iflag1);
+	flexcan_reg_write(flexcan, CAN_HW_REG_IFLAG2, iflag2);
+
+	if (flexcan->fifo) {
+		flexcan_fifo_isr(dev, iflag1);
+		iflag1 &= ~0xFF;
+	}
+	for (i = 0; iflag1 && (i < maxmb); i++) {
+		if (iflag1 & (1 << i)) {
+			iflag1 &= ~(1 << i);
+			flexcan_mb_bottom(dev, i);
+		}
+	}
+
+	for (i = maxmb; iflag2 && (i <= flexcan->maxmb); i++) {
+		if (iflag2 & (1 << (i - 32))) {
+			iflag2 &= ~(1 << (i - 32));
+			flexcan_mb_bottom(dev, i);
+		}
+	}
+	enable_irq(flexcan->irq);
+}
+
+static int flexcan_mbm_xmit(struct flexcan_device *flexcan, struct can_frame *frame)
+{
+	int i = flexcan->xmit_mb;
+	struct can_hw_mb __iomem *hwmb = flexcan->hwmb;
+	static int last;
+
+	if (flexcan->xmit_buffers != last) {
+		flexcan_dbg(flexcan, 1, "%s: %d free buffers\n", __FUNCTION__,
+			    flexcan->xmit_buffers);
+		last = flexcan->xmit_buffers;
+	}
+	do {
+		struct can_hw_mb mb;
+
+		mb.mb_cs.data = __raw_readl(&hwmb[i].mb_cs);
+
+		if (mb.mb_cs.cs.code == CAN_MB_TX_INACTIVE)
+			break;
+		if (++i > flexcan->maxmb) {
+			if (flexcan->fifo)
+				i = FLEXCAN_MAX_FIFO_MB;
+			else
+				i = flexcan->xmit_maxmb + 1;
+		}
+		if (i == flexcan->xmit_mb) {
+			flexcan_dbg(flexcan, 0, "%s: no free xmit buffer\n", __FUNCTION__);
+			return 0;
+		}
+	} while (1);
+
+	flexcan->xmit_mb = i + 1;
+	if (flexcan->xmit_mb > flexcan->maxmb) {
+		if (flexcan->fifo)
+			flexcan->xmit_mb = FLEXCAN_MAX_FIFO_MB;
+		else
+			flexcan->xmit_mb = flexcan->xmit_maxmb + 1;
+	}
+
+	flexcan_dbg(flexcan, 1, "%s: Enabling transmission of buffer %d\n", __FUNCTION__, i);
+	flexcan_mb_write(frame, &hwmb[i], CAN_MB_TX_ONCE);
+
+	if (dbg_lvl(1))
+		print_hex_dump(KERN_DEBUG, "tx_mb: ", DUMP_PREFIX_OFFSET, 16, 4,
+			       &hwmb[i], sizeof(*hwmb), 0);
+	return 1;
+}
+
+static void flexcan_mbm_init(struct flexcan_device *flexcan)
+{
+	struct can_hw_mb __iomem *hwmb;
+	int rx_mb, i;
+
+	flexcan_dbg(flexcan, 0, "%s@%d: \n", __FUNCTION__, __LINE__);
+
+	/* Set global mask to receive all messages */
+	flexcan_reg_write(flexcan, CAN_HW_REG_RXGMASK, 0);
+	flexcan_reg_write(flexcan, CAN_HW_REG_RX14MASK, 0);
+	flexcan_reg_write(flexcan, CAN_HW_REG_RX15MASK, 0);
+
+	for (i = 0; i < FLEXCAN_MAX_MB; i++) {
+		int j;
+		void __iomem *mb = &flexcan->hwmb[i];
+		void __iomem *rxm = &flexcan->rx_mask[i];
+
+		__raw_writel(0, rxm);
+		for (j = 0; j < sizeof(*flexcan->hwmb); j += 4) {
+			__raw_writel(0, mb + j);
+		}
+	}
+
+	if (flexcan->fifo)
+		rx_mb = FLEXCAN_MAX_FIFO_MB;
+	else
+		rx_mb = flexcan->maxmb - flexcan->xmit_maxmb;
+
+	hwmb = flexcan->hwmb;
+	if (flexcan->fifo) {
+		unsigned long *id_table = flexcan->io_base + CAN_FIFO_BASE;
+		for (i = 0; i < rx_mb; i++)
+			__raw_writel(0, &id_table[i]);
+	} else {
+		for (i = 0; i < rx_mb; i++) {
+			struct can_hw_mb mb;
+
+			mb.mb_cs.data = 0;
+			mb.mb_cs.cs.code = CAN_MB_RX_EMPTY;
+			if (flexcan->ext_msg && flexcan->std_msg)
+				mb.mb_cs.cs.ide = i & 1;
+			else if (flexcan->ext_msg)
+				mb.mb_cs.cs.ide = 1;
+
+			__raw_writel(mb.mb_cs.data, &hwmb[i]);
+		}
+	}
+
+	for (; i <= flexcan->maxmb; i++) {
+		struct can_hw_mb mb;
+
+		mb.mb_cs.data = 0;
+		mb.mb_cs.cs.code = CAN_MB_TX_INACTIVE;
+		__raw_writel(mb.mb_cs.data, &hwmb[i]);
+	}
+
+	flexcan->xmit_mb = rx_mb;
+	flexcan->xmit_buffers = flexcan->maxmb - flexcan->xmit_maxmb;
+}
+
+static void flexcan_hw_start(struct flexcan_device *flexcan)
+{
+	unsigned int reg;
+
+	flexcan_dbg(flexcan, 0, "%s: \n", __FUNCTION__);
+
+	if ((flexcan->maxmb + 1) > 32) {
+		flexcan_reg_write(flexcan, CAN_HW_REG_IMASK1, ~0);
+		reg = (1 << (flexcan->maxmb - 31)) - 1;
+		flexcan_reg_write(flexcan, CAN_HW_REG_IMASK2, reg);
+	} else {
+		reg = (1 << (flexcan->maxmb + 1)) - 1;
+		flexcan_reg_write(flexcan, CAN_HW_REG_IMASK1, reg);
+		flexcan_reg_write(flexcan, CAN_HW_REG_IMASK2, 0);
+	}
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_MCR);
+	flexcan_reg_write(flexcan, CAN_HW_REG_MCR, reg & ~__MCR_HALT);
+}
+
+static void flexcan_hw_stop(struct flexcan_device *flexcan)
+{
+	unsigned int reg;
+
+	flexcan_dbg(flexcan, 0, "%s: \n", __FUNCTION__);
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_MCR);
+	flexcan_reg_write(flexcan, CAN_HW_REG_MCR, reg | __MCR_HALT);
+}
+
+static int flexcan_hw_reset(struct flexcan_device *flexcan)
+{
+	struct platform_device *pdev __attribute__((unused)) = flexcan->dev;
+	unsigned int reg;
+	int timeout = 100000;
+
+	flexcan_dbg(flexcan, 0, "%s: \n", __FUNCTION__);
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_MCR);
+	flexcan_reg_write(flexcan, CAN_HW_REG_MCR, reg | __MCR_MDIS);
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_CTRL);
+	if (flexcan->br_clksrc)
+		reg |= __CTRL_CLK_SRC;
+	else
+		reg &= ~__CTRL_CLK_SRC;
+	flexcan_reg_write(flexcan, CAN_HW_REG_CTRL, reg);
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_MCR) & ~__MCR_MDIS;
+	flexcan_reg_write(flexcan, CAN_HW_REG_MCR, reg);
+	reg |= __MCR_SOFT_RST;
+	flexcan_reg_write(flexcan, CAN_HW_REG_MCR, reg);
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_MCR);
+	while (reg & __MCR_SOFT_RST) {
+		if (--timeout <= 0) {
+			dev_err(&pdev->dev, "Flexcan software Reset Timeout\n");
+			return -ETIME;
+		}
+		udelay(10);
+		reg = flexcan_reg_read(flexcan, CAN_HW_REG_MCR);
+	}
+	return 0;
+}
+
+static void flexcan_mcr_setup(struct flexcan_device *flexcan)
+{
+	unsigned int reg;
+
+	flexcan_dbg(flexcan, 0, "%s: \n", __FUNCTION__);
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_MCR);
+	reg &= ~(__MCR_MAX_MB_MASK | __MCR_WAK_MSK | __MCR_MAX_IDAM_MASK);
+
+	if (flexcan->fifo)
+		reg |= __MCR_FEN;
+	else
+		reg &= ~__MCR_FEN;
+
+	if (flexcan->wakeup)
+		reg |= __MCR_SLF_WAK | __MCR_WAK_MSK;
+	else
+		reg &= ~(__MCR_SLF_WAK | __MCR_WAK_MSK);
+
+	if (flexcan->wak_src)
+		reg |= __MCR_WAK_SRC;
+	else
+		reg &= ~__MCR_WAK_SRC;
+
+	if (flexcan->srx_dis)
+		reg |= __MCR_SRX_DIS;
+	else
+		reg &= ~__MCR_SRX_DIS;
+
+	if (flexcan->bcc)
+		reg |= __MCR_BCC;
+	else
+		reg &= ~__MCR_BCC;
+
+	if (flexcan->lprio)
+		reg |= __MCR_LPRIO_EN;
+	else
+		reg &= ~__MCR_LPRIO_EN;
+
+	if (flexcan->abort)
+		reg |= __MCR_AEN;
+	else
+		reg &= ~__MCR_AEN;
+
+	reg |= (flexcan->maxmb << __MCR_MAX_MB_OFFSET);
+	reg |= __MCR_DOZE | __MCR_MAX_IDAM_C;
+	flexcan_reg_write(flexcan, CAN_HW_REG_MCR, reg);
+}
+
+static void flexcan_ctrl_setup(struct flexcan_device *flexcan)
+{
+	unsigned int reg;
+
+	flexcan_dbg(flexcan, 0, "%s: \n", __FUNCTION__);
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_CTRL);
+	reg &= ~(__CTRL_PRESDIV_MASK | __CTRL_RJW_MASK | __CTRL_PSEG1_MASK |
+		 __CTRL_PSEG2_MASK | __CTRL_PROPSEG_MASK);
+
+	if (flexcan->loopback)
+		reg |= __CTRL_LPB;
+	else
+		reg &= ~__CTRL_LPB;
+
+	if (flexcan->smp)
+		reg |= __CTRL_SMP;
+	else
+		reg &= ~__CTRL_SMP;
+
+	if (flexcan->boff_rec)
+		reg |= __CTRL_BOFF_REC;
+	else
+		reg &= ~__CTRL_BOFF_REC;
+
+	if (flexcan->tsyn)
+		reg |= __CTRL_TSYN;
+	else
+		reg &= ~__CTRL_TSYN;
+
+	if (flexcan->listen)
+		reg |= __CTRL_LOM;
+	else
+		reg &= ~__CTRL_LOM;
+
+	reg |= (flexcan->br_presdiv << __CTRL_PRESDIV_OFFSET) |
+	    (flexcan->br_rjw << __CTRL_RJW_OFFSET) |
+	    (flexcan->br_pseg1 << __CTRL_PSEG1_OFFSET) |
+	    (flexcan->br_pseg2 << __CTRL_PSEG2_OFFSET) |
+	    (flexcan->br_propseg << __CTRL_PROPSEG_OFFSET);
+
+	reg &= ~__CTRL_LBUF;
+
+	reg |= __CTRL_TWRN_MSK | __CTRL_RWRN_MSK | __CTRL_BOFF_MSK |
+	    __CTRL_ERR_MSK;
+
+	flexcan_reg_write(flexcan, CAN_HW_REG_CTRL, reg);
+}
+
+static int flexcan_hw_restart(struct net_device *dev)
+{
+	unsigned int reg;
+	struct flexcan_device *flexcan = netdev_priv(dev);
+
+	ndev_dbg(dev, 0, "%s: \n", __FUNCTION__);
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_MCR);
+	if (reg & __MCR_SOFT_RST)
+		return 1;
+
+	flexcan_mcr_setup(flexcan);
+
+	flexcan_reg_write(flexcan, CAN_HW_REG_IMASK2, 0);
+	flexcan_reg_write(flexcan, CAN_HW_REG_IMASK1, 0);
+
+	flexcan_reg_write(flexcan, CAN_HW_REG_IFLAG2, 0xFFFFFFFF);
+	flexcan_reg_write(flexcan, CAN_HW_REG_IFLAG1, 0xFFFFFFFF);
+
+	flexcan_reg_write(flexcan, CAN_HW_REG_ECR, 0);
+
+	flexcan_mbm_init(flexcan);
+	netif_carrier_on(dev);
+	flexcan_hw_start(flexcan);
+
+	if (netif_queue_stopped(dev)) {
+		ndev_dbg(dev, 1, "%s@%d: Starting netif queue\n",
+			 __FUNCTION__, __LINE__);
+		netif_start_queue(dev);
+	}
+	return 0;
+}
+
+static void flexcan_hw_watch(unsigned long data)
+{
+	unsigned int reg, ecr;
+	struct net_device *dev = (struct net_device *)data;
+	struct flexcan_device *flexcan = netdev_priv(dev);
+
+	ndev_dbg(dev, 1, "%s: \n", __FUNCTION__);
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_MCR);
+	if (reg & __MCR_MDIS) {
+		if (flexcan_hw_restart(dev))
+			mod_timer(&flexcan->timer, HZ / 20);
+		return;
+	}
+	ecr = flexcan_reg_read(flexcan, CAN_HW_REG_ECR);
+	if (flexcan->boff_rec) {
+		if (((reg & __ESR_FLT_CONF_MASK) >> __ESR_FLT_CONF_OFF) > 1) {
+			reg |= __MCR_SOFT_RST;
+			ndev_dbg(dev, 1, "%s: Initiating soft reset\n", __FUNCTION__);
+			flexcan_reg_write(flexcan, CAN_HW_REG_MCR, reg);
+			mod_timer(&flexcan->timer, HZ / 20);
+			return;
+		}
+		netif_carrier_on(dev);
+	}
+	ndev_dbg(dev, 1, "%s: Done\n", __FUNCTION__);
+}
+
+static void flexcan_hw_busoff(struct net_device *dev)
+{
+	struct flexcan_device *flexcan = netdev_priv(dev);
+	unsigned int reg;
+
+	netif_carrier_off(dev);
+
+	flexcan->timer.function = flexcan_hw_watch;
+	flexcan->timer.data = (unsigned long)dev;
+
+	if (flexcan->boff_rec) {
+		mod_timer(&flexcan->timer, HZ / 10);
+		return;
+	}
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_MCR);
+	flexcan_reg_write(flexcan, CAN_HW_REG_MCR, reg | __MCR_SOFT_RST);
+	mod_timer(&flexcan->timer, HZ / 20);
+}
+
+static int flexcan_hw_open(struct flexcan_device *flexcan)
+{
+	int ret;
+
+	if ((ret = flexcan_hw_reset(flexcan)) != 0)
+		return ret;
+
+	flexcan_mcr_setup(flexcan);
+	flexcan_ctrl_setup(flexcan);
+
+	flexcan_reg_write(flexcan, CAN_HW_REG_IMASK2, 0);
+	flexcan_reg_write(flexcan, CAN_HW_REG_IMASK1, 0);
+
+	flexcan_reg_write(flexcan, CAN_HW_REG_IFLAG2, 0xFFFFFFFF);
+	flexcan_reg_write(flexcan, CAN_HW_REG_IFLAG1, 0xFFFFFFFF);
+
+	flexcan_reg_write(flexcan, CAN_HW_REG_ECR, 0);
+	return 0;
+}
+
+static void flexcan_err_handler(struct work_struct *work)
+{
+	struct flexcan_device *flexcan = container_of(work, struct flexcan_device, err_work);
+	struct net_device *dev = platform_get_drvdata(flexcan->dev);
+	struct sk_buff *skb;
+	struct can_frame *frame;
+	unsigned int esr, ecr;
+
+	ndev_dbg(dev, 1, "%s@%d: \n", __FUNCTION__, __LINE__);
+
+	esr = flexcan_reg_read(flexcan, CAN_HW_REG_ESR);
+	flexcan_reg_write(flexcan, CAN_HW_REG_ESR, esr & __ESR_INTERRUPTS);
+	enable_irq(flexcan->irq);
+
+	if (esr & __ESR_WAK_INT) {
+		ndev_dbg(dev, 0, "%s@%d: \n", __FUNCTION__, __LINE__);
+		return;
+	}
+
+	skb = dev_alloc_skb(sizeof(struct can_frame));
+	if (!skb) {
+		ndev_err(dev, "%s: Failed to allocate skb\n", __func__);
+		return;
+	}
+	frame = flexcan_skb_put(skb, sizeof(*frame));
+	frame->can_id = CAN_ERR_FLAG | CAN_ERR_CRTL;
+	frame->can_dlc = CAN_ERR_DLC;
+
+	if (esr & __ESR_TWRN_INT) {
+		ndev_err(dev, "%s: TX_WARNING\n", __FUNCTION__);
+		frame->data[1] |= CAN_ERR_CRTL_TX_WARNING;
+	}
+	if (esr & __ESR_RWRN_INT) {
+		ndev_err(dev, "%s: RX_WARNING\n", __FUNCTION__);
+		frame->data[1] |= CAN_ERR_CRTL_RX_WARNING;
+	}
+	if (esr & __ESR_BOFF_INT) {
+		ndev_err(dev, "%s: BUS_OFF\n", __FUNCTION__);
+		frame->can_id |= CAN_ERR_BUSOFF;
+	}
+	if (esr & __ESR_ERR_INT) {
+		ndev_dbg(dev, 1, "%s@%d: \n", __FUNCTION__, __LINE__);
+		if (esr & __ESR_BIT1_ERR) {
+			ndev_err(dev, "%s: BIT1_ERR\n", __FUNCTION__);
+			frame->data[2] |= CAN_ERR_PROT_BIT1;
+		}
+
+		if (esr & __ESR_BIT0_ERR) {
+			ndev_err(dev, "%s: BIT0_ERR\n", __FUNCTION__);
+			frame->data[2] |= CAN_ERR_PROT_BIT0;
+		}
+
+		if (esr & __ESR_ACK_ERR) {
+			ndev_err(dev, "%s: ACK_ERR\n", __FUNCTION__);
+			frame->can_id |= CAN_ERR_ACK;
+		}
+
+		/*TODO:// if (esr & __ESR_CRC_ERR) */
+
+		if (esr & __ESR_FRM_ERR) {
+			ndev_err(dev, "%s: FRM_ERR\n", __FUNCTION__);
+			frame->data[2] |= CAN_ERR_PROT_FORM;
+		}
+
+		if (esr & __ESR_STF_ERR) {
+			ndev_err(dev, "%s: STF_ERR\n", __FUNCTION__);
+			frame->data[2] |= CAN_ERR_PROT_STUFF;
+		}
+
+		ecr = flexcan_reg_read(flexcan, CAN_HW_REG_ECR);
+		switch ((esr & __ESR_FLT_CONF_MASK) >> __ESR_FLT_CONF_OFF) {
+		case 0:
+			ndev_dbg(dev, 0, "%s@%d: \n", __FUNCTION__, __LINE__);
+			if (__ECR_TX_ERR_COUNTER(ecr) >= __ECR_ACTIVE_THRESHOLD)
+				frame->data[1] |= CAN_ERR_CRTL_TX_WARNING;
+			if (__ECR_RX_ERR_COUNTER(ecr) >= __ECR_ACTIVE_THRESHOLD)
+				frame->data[1] |= CAN_ERR_CRTL_RX_WARNING;
+			break;
+		case 1:
+			ndev_dbg(dev, 0, "%s@%d: \n", __FUNCTION__, __LINE__);
+			if (__ECR_TX_ERR_COUNTER(ecr) >=
+			    __ECR_PASSIVE_THRESHOLD)
+				frame->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+
+			if (__ECR_RX_ERR_COUNTER(ecr) >=
+			    __ECR_PASSIVE_THRESHOLD)
+				frame->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+			break;
+		default:
+			ndev_dbg(dev, 0, "%s@%d: \n", __FUNCTION__, __LINE__);
+			frame->can_id |= CAN_ERR_BUSOFF;
+		}
+	}
+
+	if (frame->can_id & CAN_ERR_BUSOFF) {
+		ndev_dbg(dev, 0, "%s: switchung bus off\n", __FUNCTION__);
+		flexcan_hw_busoff(dev);
+	}
+	skb->dev = dev;
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+	netif_receive_skb(skb);
+}
+
+static irqreturn_t flexcan_irq_handler(int irq, void *data)
+{
+	struct net_device *dev = data;
+	struct flexcan_device *flexcan = netdev_priv(dev);
+	unsigned int reg;
+
+	ndev_dbg(dev, 1, "%s: \n", __FUNCTION__);
+	disable_irq_nosync(irq);
+
+	reg = flexcan_reg_read(flexcan, CAN_HW_REG_ESR);
+	if (reg & __ESR_INTERRUPTS) {
+		ndev_dbg(dev, 1, "%s: Scheduling err handler\n", __FUNCTION__);
+		schedule_work(&flexcan->err_work);
+		return IRQ_HANDLED;
+	}
+
+	ndev_dbg(dev, 1, "%s: Scheduling mbm handler\n", __FUNCTION__);
+	schedule_work(&flexcan->mb_work);
+	return IRQ_HANDLED;
+}
+
+static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct can_frame *frame = flexcan_skb_data(skb);
+	struct flexcan_device *flexcan = netdev_priv(dev);
+	struct net_device_stats *stats = flexcan_get_stats(dev);
+
+	ndev_dbg(dev, 1, "%s: \n", __FUNCTION__);
+
+	if (frame->can_dlc > 8)
+		return -EINVAL;
+
+	if (flexcan_mbm_xmit(flexcan, frame)) {
+		dev_kfree_skb(skb);
+		stats->tx_bytes += frame->can_dlc;
+		stats->tx_packets++;
+		dev->trans_start = jiffies;
+		if (--flexcan->xmit_buffers == 0) {
+			ndev_dbg(dev, 1, "%s: Stopping netif queue\n", __FUNCTION__);
+			netif_stop_queue(dev);
+		}
+		BUG_ON(flexcan->xmit_buffers < 0);
+		return NETDEV_TX_OK;
+	}
+	ndev_dbg(dev, 1, "%s: could not transmit message\n", __FUNCTION__);
+	return NETDEV_TX_BUSY;
+}
+
+static int flexcan_open(struct net_device *dev)
+{
+	int ret;
+	struct flexcan_device *flexcan = netdev_priv(dev);
+	struct platform_device *pdev = flexcan->dev;
+	struct flexcan_platform_data *plat_data = pdev->dev.platform_data;
+
+	ndev_dbg(dev, 0, "%s: \n", __FUNCTION__);
+
+	ret = clk_enable(flexcan->clk);
+	if (ret)
+		goto clk_err;
+
+	if (flexcan->core_reg) {
+		ret = regulator_enable(flexcan->core_reg);
+		if (ret)
+			goto core_reg_err;
+	}
+
+	if (flexcan->io_reg) {
+		ret = regulator_enable(flexcan->io_reg);
+		if (ret)
+			goto io_reg_err;
+	}
+
+	if (plat_data && plat_data->xcvr_enable) {
+		ret = plat_data->xcvr_enable(pdev, 1);
+		if (ret)
+			goto enable_err;
+	}
+
+	ret = request_irq(flexcan->irq, flexcan_irq_handler, IRQF_SAMPLE_RANDOM,
+			  dev->name, dev);
+	if (ret)
+		goto irq_err;
+
+	ret = flexcan_hw_open(flexcan);
+	if (ret)
+		goto open_err;
+
+	flexcan_mbm_init(flexcan);
+	netif_carrier_on(dev);
+	flexcan_hw_start(flexcan);
+	return 0;
+
+ open_err:
+	free_irq(flexcan->irq, dev);
+ irq_err:
+	if (plat_data && plat_data->xcvr_enable)
+		plat_data->xcvr_enable(pdev, 0);
+ enable_err:
+	if (flexcan->io_reg)
+		regulator_disable(flexcan->io_reg);
+ io_reg_err:
+	if (flexcan->core_reg)
+		regulator_disable(flexcan->core_reg);
+ core_reg_err:
+	if (flexcan->clk)
+		clk_disable(flexcan->clk);
+ clk_err:
+	return ret;
+}
+
+static int flexcan_stop(struct net_device *dev)
+{
+	struct flexcan_device *flexcan = netdev_priv(dev);
+	struct platform_device *pdev = flexcan->dev;
+	struct flexcan_platform_data *plat_data = pdev->dev.platform_data;
+
+	flexcan_hw_stop(flexcan);
+
+	free_irq(flexcan->irq, dev);
+
+	if (plat_data && plat_data->xcvr_enable)
+		plat_data->xcvr_enable(pdev, 0);
+
+	if (flexcan->io_reg)
+		regulator_disable(flexcan->io_reg);
+	if (flexcan->core_reg)
+		regulator_disable(flexcan->core_reg);
+	clk_disable(flexcan->clk);
+	return 0;
+}
+
+static const struct net_device_ops flexcan_netdev_ops = {
+	.ndo_open	= flexcan_open,
+	.ndo_stop	= flexcan_stop,
+	.ndo_start_xmit = flexcan_start_xmit,
+	.ndo_get_stats	= flexcan_get_stats,
+};
+
+static void flexcan_setup(struct net_device *dev)
+{
+	dev->type = ARPHRD_CAN;
+	dev->mtu = sizeof(struct can_frame);
+	dev->hard_header_len = 0;
+	dev->addr_len = 0;
+	dev->tx_queue_len = FLEXCAN_MAX_MB;
+	dev->flags = IFF_NOARP;
+	dev->features = NETIF_F_NO_CSUM;
+
+	dev->netdev_ops = &flexcan_netdev_ops;
+	dev->destructor = flexcan_device_free;
+}
+
+static int flexcan_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct net_device *net;
+
+	net = flexcan_device_alloc(pdev, flexcan_setup);
+	if (IS_ERR(net))
+		return PTR_ERR(net);
+
+	ret = register_netdev(net);
+	if (ret) {
+		flexcan_device_free(net);
+	}
+	return ret;
+}
+
+static int flexcan_remove(struct platform_device *pdev)
+{
+	struct net_device *net = platform_get_drvdata(pdev);
+
+	unregister_netdev(net);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int flexcan_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct net_device *net = platform_get_drvdata(pdev);
+	struct flexcan_device *flexcan = netdev_priv(net);
+	struct flexcan_platform_data *plat_data;
+
+	if (!(net->flags & IFF_UP))
+		return 0;
+
+	if (flexcan->wakeup)
+		set_irq_wake(flexcan->irq, 1);
+	else {
+		int ret;
+
+		plat_data = pdev->dev.platform_data;
+
+		if (plat_data && plat_data->xcvr_enable) {
+			ret = plat_data->xcvr_enable(pdev, 0);
+			if (ret)
+				return ret;
+		}
+		if (flexcan->io_reg) {
+			ret = regulator_disable(flexcan->io_reg);
+			if (ret)
+				return ret;
+		}
+		if (flexcan->core_reg) {
+			ret = regulator_disable(flexcan->core_reg);
+			if (ret)
+				return ret;
+		}
+		clk_disable(flexcan->clk);
+		if (plat_data && plat_data->inactive) {
+			plat_data->inactive(pdev);
+		}
+	}
+	return 0;
+}
+
+static int flexcan_resume(struct platform_device *pdev)
+{
+	int ret;
+	struct net_device *net = platform_get_drvdata(pdev);
+	struct flexcan_device *flexcan = netdev_priv(net);
+	struct flexcan_platform_data *plat_data;
+
+	if (!(net->flags & IFF_UP))
+		return 0;
+
+	if (flexcan->wakeup)
+		set_irq_wake(flexcan->irq, 0);
+	else {
+		plat_data = pdev->dev.platform_data;
+		if (plat_data && plat_data->active) {
+			ret = plat_data->active(pdev);
+			if (ret)
+				printk(KERN_ERR "%s: Failed activate hardware: %d\n",
+				       __func__, ret);
+		}
+		ret = clk_enable(flexcan->clk);
+		if (ret)
+			printk(KERN_ERR "%s: Failed to enable clock: %d\n",
+			       __func__, ret);
+
+		if (flexcan->core_reg) {
+			ret = regulator_enable(flexcan->core_reg);
+			if (ret)
+				printk(KERN_ERR "%s: Failed to enable core voltage: %d\n",
+				       __func__, ret);
+		}
+		if (flexcan->io_reg) {
+			ret = regulator_enable(flexcan->io_reg);
+			if (ret)
+				printk(KERN_ERR "%s: Failed to enable io voltage: %d\n",
+				       __func__, ret);
+		}
+
+		if (plat_data && plat_data->xcvr_enable) {
+			ret = plat_data->xcvr_enable(pdev, 1);
+			if (ret)
+				printk(KERN_ERR "%s: Failed to enable transceiver: %d\n",
+				       __func__, ret);
+		}
+	}
+	return 0;
+}
+#else
+#define flexcan_suspend		NULL
+#define flexcan_resume		NULL
+#endif
+
+static struct platform_driver flexcan_driver = {
+	.driver = {
+		.name = "mxc-flexcan",
+	},
+	.probe = flexcan_probe,
+	.remove = flexcan_remove,
+	.suspend = flexcan_suspend,
+	.resume = flexcan_resume,
+};
+
+static __init int flexcan_init(void)
+{
+	pr_info("Freescale FlexCAN Driver \n");
+	return platform_driver_register(&flexcan_driver);
+}
+
+static __exit void flexcan_exit(void)
+{
+	return platform_driver_unregister(&flexcan_driver);
+}
+
+module_init(flexcan_init);
+module_exit(flexcan_exit);
+
+MODULE_LICENSE("GPL");
diff -purN linux-2.6.30-rc4-git/drivers/net/can/flexcan.h linux-2.6.30-rc4-karo3/drivers/net/can/flexcan.h
--- linux-2.6.30-rc4-git/drivers/net/can/flexcan.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/drivers/net/can/flexcan.h	2009-07-06 15:17:55.000000000 +0200
@@ -0,0 +1,214 @@
+/*
+ * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
+
+/*
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/*!
+ * @file flexcan.h
+ *
+ * @brief FlexCan definitions.
+ *
+ * @ingroup can
+ */
+
+#ifndef __CAN_FLEXCAN_H__
+#define __CAN_FLEXCAN_H__
+
+#include <linux/list.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/clk.h>
+#include <linux/can.h>
+#include <linux/can/core.h>
+#include <linux/can/error.h>
+
+struct can_mb_cs {
+	unsigned int time_stamp:16;
+	unsigned int length:4;
+	unsigned int rtr:1;
+	unsigned int ide:1;
+	unsigned int srr:1;
+	unsigned int nouse1:1;
+	unsigned int code:4;
+	unsigned int nouse2:4;
+};
+
+#define CAN_MB_RX_INACTIVE	0x0
+#define CAN_MB_RX_EMPTY		0x4
+#define CAN_MB_RX_FULL		0x2
+#define CAN_MB_RX_OVERRUN	0x6
+#define CAN_MB_RX_BUSY		0x1
+
+#define CAN_MB_TX_INACTIVE	0x8
+#define CAN_MB_TX_ABORT		0x9
+#define CAN_MB_TX_ONCE		0xC
+#define CAN_MB_TX_REMOTE	0xA
+
+struct can_hw_mb {
+	union {
+		struct can_mb_cs cs;
+		unsigned int data;
+	} mb_cs;
+	unsigned int mb_id;
+	unsigned char mb_data[8];
+};
+
+#define CAN_HW_REG_MCR		0x00
+#define CAN_HW_REG_CTRL		0x04
+#define CAN_HW_REG_TIMER	0x08
+#define CAN_HW_REG_RXGMASK	0x10
+#define CAN_HW_REG_RX14MASK	0x14
+#define CAN_HW_REG_RX15MASK	0x18
+#define CAN_HW_REG_ECR		0x1C
+#define CAN_HW_REG_ESR		0x20
+#define CAN_HW_REG_IMASK2	0x24
+#define CAN_HW_REG_IMASK1	0x28
+#define CAN_HW_REG_IFLAG2	0x2C
+#define CAN_HW_REG_IFLAG1	0x30
+
+#define CAN_MB_BASE	0x0080
+#define CAN_RXMASK_BASE	0x0880
+#define CAN_FIFO_BASE	0xE0
+
+#define __MCR_MDIS		(1 << 31)
+#define __MCR_FRZ		(1 << 30)
+#define __MCR_FEN		(1 << 29)
+#define __MCR_HALT		(1 << 28)
+#define __MCR_NOTRDY		(1 << 27)
+#define __MCR_WAK_MSK		(1 << 26)
+#define __MCR_SOFT_RST		(1 << 25)
+#define __MCR_FRZ_ACK		(1 << 24)
+#define __MCR_SLF_WAK		(1 << 22)
+#define __MCR_WRN_EN		(1 << 21)
+#define __MCR_LPM_ACK		(1 << 20)
+#define __MCR_WAK_SRC		(1 << 19)
+#define __MCR_DOZE		(1 << 18)
+#define __MCR_SRX_DIS		(1 << 17)
+#define __MCR_BCC		(1 << 16)
+#define __MCR_LPRIO_EN		(1 << 13)
+#define __MCR_AEN		(1 << 12)
+#define __MCR_MAX_IDAM_OFFSET 	8
+#define __MCR_MAX_IDAM_MASK 	(0x3 << __MCR_MAX_IDAM_OFFSET)
+#define __MCR_MAX_IDAM_A	(0x0 << __MCR_MAX_IDAM_OFFSET)
+#define __MCR_MAX_IDAM_B	(0x1 << __MCR_MAX_IDAM_OFFSET)
+#define __MCR_MAX_IDAM_C	(0x2 << __MCR_MAX_IDAM_OFFSET)
+#define __MCR_MAX_IDAM_D	(0x3 << __MCR_MAX_IDAM_OFFSET)
+#define __MCR_MAX_MB_OFFSET 	0
+#define __MCR_MAX_MB_MASK 	(0x3F)
+
+#define __CTRL_PRESDIV_OFFSET	24
+#define __CTRL_PRESDIV_MASK	(0xFF << __CTRL_PRESDIV_OFFSET)
+#define __CTRL_RJW_OFFSET	22
+#define __CTRL_RJW_MASK		(0x3 << __CTRL_RJW_OFFSET)
+#define __CTRL_PSEG1_OFFSET	19
+#define __CTRL_PSEG1_MASK	(0x7 << __CTRL_PSEG1_OFFSET)
+#define __CTRL_PSEG2_OFFSET	16
+#define __CTRL_PSEG2_MASK	(0x7 << __CTRL_PSEG2_OFFSET)
+#define __CTRL_BOFF_MSK		(0x1 << 15)
+#define __CTRL_ERR_MSK		(0x1 << 14)
+#define __CTRL_CLK_SRC		(0x1 << 13)
+#define __CTRL_LPB		(0x1 << 12)
+#define __CTRL_TWRN_MSK		(0x1 << 11)
+#define __CTRL_RWRN_MSK		(0x1 << 10)
+#define __CTRL_SMP		(0x1 << 7)
+#define __CTRL_BOFF_REC		(0x1 << 6)
+#define __CTRL_TSYN		(0x1 << 5)
+#define __CTRL_LBUF		(0x1 << 4)
+#define __CTRL_LOM		(0x1 << 3)
+#define __CTRL_PROPSEG_OFFSET	0
+#define __CTRL_PROPSEG_MASK	(0x7)
+
+#define __ECR_TX_ERR_COUNTER(x) ((x) & 0xFF)
+#define __ECR_RX_ERR_COUNTER(x) (((x) >> 8) & 0xFF)
+#define __ECR_PASSIVE_THRESHOLD	128
+#define __ECR_ACTIVE_THRESHOLD	96
+
+#define __ESR_TWRN_INT		(0x1 << 17)
+#define __ESR_RWRN_INT		(0x1 << 16)
+#define __ESR_BIT1_ERR		(0x1 << 15)
+#define __ESR_BIT0_ERR		(0x1 << 14)
+#define __ESR_ACK_ERR		(0x1 << 13)
+#define __ESR_CRC_ERR		(0x1 << 12)
+#define __ESR_FRM_ERR		(0x1 << 11)
+#define __ESR_STF_ERR		(0x1 << 10)
+#define __ESR_TX_WRN		(0x1 << 9)
+#define __ESR_RX_WRN		(0x1 << 8)
+#define __ESR_IDLE		(0x1 << 7)
+#define __ESR_TXRX		(0x1 << 6)
+#define __ESR_FLT_CONF_OFF	4
+#define __ESR_FLT_CONF_MASK	(0x3 << __ESR_FLT_CONF_OFF)
+#define __ESR_BOFF_INT		(0x1 << 2)
+#define __ESR_ERR_INT		(0x1 << 1)
+#define __ESR_WAK_INT		(0x1)
+
+#define __ESR_INTERRUPTS	(__ESR_WAK_INT | __ESR_ERR_INT | \
+				__ESR_BOFF_INT | __ESR_TWRN_INT | \
+				__ESR_RWRN_INT)
+
+#define __FIFO_OV_INT		(1 << 7)
+#define __FIFO_WARN_INT		(1 << 6)
+#define __FIFO_RDY_INT		(1 << 5)
+
+#define FLEXCAN_MAX_FIFO_MB	8
+#define FLEXCAN_MAX_MB		64
+#define FLEXCAN_MAX_PRESDIV	256
+#define FLEXCAN_MAX_RJW		4
+#define FLEXCAN_MAX_PSEG1	8
+#define FLEXCAN_MAX_PSEG2	8
+#define FLEXCAN_MAX_PROPSEG	8
+#define FLEXCAN_MAX_BITRATE	1000000
+
+struct flexcan_device {
+	struct mutex mutex;
+	struct work_struct err_work;
+	struct work_struct mb_work;
+	void __iomem *io_base;
+	struct can_hw_mb __iomem *hwmb;
+	unsigned int __iomem *rx_mask;
+	int xmit_buffers;
+	unsigned int xmit_mb;
+	unsigned int bitrate;
+	/* word 1 */
+	unsigned int br_presdiv:8;
+	unsigned int br_rjw:2;
+	unsigned int br_propseg:3;
+	unsigned int br_pseg1:3;
+	unsigned int br_pseg2:3;
+	unsigned int maxmb:6;
+	unsigned int xmit_maxmb:6;
+	unsigned int rsrvd:1;
+
+	/* word 2 */
+	unsigned int fifo:1;
+	unsigned int wakeup:1;
+	unsigned int srx_dis:1;
+	unsigned int wak_src:1;
+	unsigned int bcc:1;
+	unsigned int lprio:1;
+	unsigned int abort:1;
+	unsigned int br_clksrc:1;
+	unsigned int loopback:1;
+	unsigned int smp:1;
+	unsigned int boff_rec:1;
+	unsigned int tsyn:1;
+	unsigned int listen:1;
+
+	unsigned int ext_msg:1;
+	unsigned int std_msg:1;
+
+	struct timer_list timer;
+	struct platform_device *dev;
+	struct regulator *core_reg;
+	struct regulator *io_reg;
+	struct clk *clk;
+	int irq;
+};
+#endif /* __CAN_FLEXCAN_H__ */
diff -purN linux-2.6.30-rc4-git/drivers/net/fec.c linux-2.6.30-rc4-karo3/drivers/net/fec.c
--- linux-2.6.30-rc4-git/drivers/net/fec.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/net/fec.c	2009-07-01 12:59:40.000000000 +0200
@@ -2,6 +2,12 @@
  * Fast Ethernet Controller (FEC) driver for Motorola MPC8xx.
  * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
  *
+ * This version of the driver is specific to the FADS implementation,
+ * since the board contains control registers external to the processor
+ * for the control of the LevelOne LXT970 transceiver.  The MPC860T manual
+ * describes connections using the internal parallel port I/O, which
+ * is basically all of Port D.
+ *
  * Right now, I am very wasteful with the buffers.  I allocate memory
  * pages and then divide them into 2K frame buffers.  This way I know I
  * have buffers large enough to hold one frame within one buffer descriptor.
@@ -18,77 +24,123 @@
  * Bug fixes and cleanup by Philippe De Muyter (phdm@macqel.be)
  * Copyright (c) 2004-2006 Macq Electronique SA.
  */
+/*
+ * Copyright 2006-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ */
 
 #include <linux/module.h>
 #include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/ptrace.h>
+#include <linux/resource.h>
 #include <linux/errno.h>
 #include <linux/ioport.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/init.h>
+#include <linux/wait.h>
 #include <linux/delay.h>
+#include <linux/platform_device.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <linux/spinlock.h>
-#include <linux/workqueue.h>
-#include <linux/bitops.h>
-#include <linux/io.h>
-#include <linux/irq.h>
+#include <linux/dma-mapping.h>
 #include <linux/clk.h>
-#include <linux/platform_device.h>
+#include <linux/fec_enet.h>
+#include <linux/phy.h>
 
-#include <asm/cacheflush.h>
+#include <asm/irq.h>
+#include <asm/io.h>
 
-#ifndef CONFIG_ARCH_MXC
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
+#define DRV_NAME		"fec"
+#define DEBUG
+
+#ifdef DEBUG
+static int debug = 0;
+#define dbg_lvl(n)	((n) < debug)
+module_param(debug, int, S_IRUGO | S_IWUSR);
+
+#define DBG(lvl, fmt...)	do { if (dbg_lvl(lvl)) printk(KERN_DEBUG fmt); } while (0)
+#else
+static int debug;
+#define dbg_lvl(n)	0
+module_param(debug, int, 0);
+
+#define DBG(lvl, fmt...)	do { } while (0)
 #endif
 
+#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || \
+    defined(CONFIG_M5272) || defined(CONFIG_M528x) || \
+    defined(CONFIG_M520x) || defined(CONFIG_M532x)
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
 #include "fec.h"
-
-#ifdef CONFIG_ARCH_MXC
+#define FEC_ALIGNMENT  (0x03)          /*FEC needs 4bytes alignment*/
+#elif defined(CONFIG_ARCH_MXC)
 #include <mach/hardware.h>
-#define FEC_ALIGNMENT	0xf
+#include <mach/iim.h>
+#include "fec.h"
+#define FEC_ALIGNMENT  (0x0F)          /*FEC needs 128bits(16bytes) alignment*/
 #else
-#define FEC_ALIGNMENT	0x3
+#include <asm/8xx_immap.h>
+#include <asm/mpc8xx.h>
+#include "commproc.h"
+#define FEC_ALIGNMENT  (0x03)          /*FEC needs 4bytes alignment */
 #endif
 
+#define FEC_ADDR_ALIGNMENT(x) ((unsigned char *)(((unsigned long)(x) + (FEC_ALIGNMENT)) & (~FEC_ALIGNMENT)))
+
+#if 0
 /*
  * Define the fixed address of the FEC hardware.
  */
+/* USE resources provided by platform_device! */
+static unsigned int fec_hw[] = {
 #if defined(CONFIG_M5272)
-#define HAVE_mii_link_interrupt
-
-static unsigned char	fec_mac_default[] = {
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	(MCF_MBAR + 0x840),
+#elif defined(CONFIG_M527x)
+	(MCF_MBAR + 0x1000),
+	(MCF_MBAR + 0x1800),
+#elif defined(CONFIG_M523x) || defined(CONFIG_M528x)
+	(MCF_MBAR + 0x1000),
+#elif defined(CONFIG_M520x)
+	(MCF_MBAR+0x30000),
+#elif defined(CONFIG_M532x)
+	(MCF_MBAR+0xfc030000),
+#elif defined(CONFIG_ARCH_MXC)
+	(IO_ADDRESS(FEC_BASE_ADDR)),
+#else
+	&(((immap_t *)IMAP_ADDR)->im_cpm.cp_fec),
+#endif
 };
+#endif
 
+#if 0
 /*
  * Some hardware gets it MAC address out of local flash memory.
  * if this is non-zero then assume it is the address to get MAC from.
  */
+/* implemented using platform_data! */
 #if defined(CONFIG_NETtel)
 #define	FEC_FLASHMAC	0xf0006006
 #elif defined(CONFIG_GILBARCONAP) || defined(CONFIG_SCALES)
 #define	FEC_FLASHMAC	0xf0006000
+#elif defined (CONFIG_MTD_KeyTechnology)
+#define	FEC_FLASHMAC	0xffe04000
 #elif defined(CONFIG_CANCam)
 #define	FEC_FLASHMAC	0xf0020000
 #elif defined (CONFIG_M5272C3)
 #define	FEC_FLASHMAC	(0xffe04000 + 4)
 #elif defined(CONFIG_MOD5272)
-#define FEC_FLASHMAC 	0xffc0406b
+#define FEC_FLASHMAC	0xffc0406b
 #else
 #define	FEC_FLASHMAC	0
 #endif
-#endif /* CONFIG_M5272 */
+#endif
+
+#define platform_func(p, args...)	((p) ? (p)(args) : 0)
 
 /* Forward declarations of some structures to support different PHYs
 */
-
+#ifndef CONFIG_PHYLIB
 typedef struct {
 	uint mii_data;
 	void (*funct)(uint mii_reg, struct net_device *dev);
@@ -103,6 +155,7 @@ typedef struct {
 	const phy_cmd_t *ack_int;
 	const phy_cmd_t *shutdown;
 } phy_info_t;
+#endif
 
 /* The number of Tx and Rx buffers.  These are allocated from the page
  * pool.  The code may assume these are power of two, so it it best
@@ -116,12 +169,13 @@ typedef struct {
 #define RX_RING_SIZE		(FEC_ENET_RX_FRPPG * FEC_ENET_RX_PAGES)
 #define FEC_ENET_TX_FRSIZE	2048
 #define FEC_ENET_TX_FRPPG	(PAGE_SIZE / FEC_ENET_TX_FRSIZE)
-#define TX_RING_SIZE		16	/* Must be power of two */
-#define TX_RING_MOD_MASK	15	/*   for this to work */
+#define TX_RING_SIZE		16			/* Must be power of two */
+#define TX_RING_MOD_MASK	(TX_RING_SIZE - 1)	/*   for this to work */
 
 #if (((RX_RING_SIZE + TX_RING_SIZE) * 8) > PAGE_SIZE)
 #error "FEC: descriptor ring size constants too large"
 #endif
+#define CBD_BUF_SIZE		((RX_RING_SIZE + TX_RING_SIZE) * sizeof(cbd_t))
 
 /* Interrupt events/masks.
 */
@@ -136,6 +190,17 @@ typedef struct {
 #define FEC_ENET_MII	((uint)0x00800000)	/* MII interrupt */
 #define FEC_ENET_EBERR	((uint)0x00400000)	/* SDMA bus error */
 
+/* MXC arch interrupt bits */
+#define FEC_ENET_LC	((uint)0x00200000)	/* Late collision */
+#define FEC_ENET_RL	((uint)0x00100000)	/* Collision retry limit exceeded */
+#define FEC_ENET_UN	((uint)0x00080000)	/* TX Fifo underrun */
+
+#ifndef CONFIG_ARCH_MXC
+#define FEC_ENET_MASK   ((uint)0xffc00000)
+#else
+#define FEC_ENET_MASK   ((uint)0xfff80000)
+#endif
+
 /* The FEC stores dest/src/type, data, and checksum for receive packets.
  */
 #define PKT_MAXBUF_SIZE		1518
@@ -150,7 +215,7 @@ typedef struct {
  */
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
     defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARCH_MXC)
-#define	OPT_FRAME_SIZE	(PKT_MAXBUF_SIZE << 16)
+#define	OPT_FRAME_SIZE	(RCR_MAX_FL_set(PKT_MAXBUF_SIZE))
 #else
 #define	OPT_FRAME_SIZE	0
 #endif
@@ -165,31 +230,45 @@ typedef struct {
  */
 struct fec_enet_private {
 	/* Hardware registers of the FEC device */
-	volatile fec_t	*hwp;
-
-	struct net_device *netdev;
-
-	struct clk *clk;
+	void __iomem *reg_base;
+	void __iomem *mib_base;
+	struct resource *res_mem1;
+	struct resource *res_mem2;
+	int	etn_irq;
+	int	mii_irq;
+#ifndef CONFIG_PHYLIB
+	struct timer_list *phy_timer;
+#else
+	struct mii_bus *mii;
+	int mii_complete;
+#endif
+	u32 msg_enable;
 
 	/* The saved address of a sent-in-place packet/buffer, for skfree(). */
-	unsigned char *tx_bounce[TX_RING_SIZE];
+	void	*tx_bounce[TX_RING_SIZE];
 	struct	sk_buff* tx_skbuff[TX_RING_SIZE];
+	struct  sk_buff* rx_skbuff[RX_RING_SIZE];
 	ushort	skb_cur;
 	ushort	skb_dirty;
 
 	/* CPM dual port RAM relative addresses.
 	*/
-	dma_addr_t	bd_dma;
+	struct device *dma_dev;		/* pointer to (platform_)device for dma_sync*() functions */
+	void	*cbd_mem_base;          /* save the virtual base address of rx&tx buffer descriptor */
+	dma_addr_t cbd_phys_base;	/* physical address of buffer descriptor memory for access by FEC HW */
+
 	cbd_t	*rx_bd_base;		/* Address of Rx and Tx buffers. */
 	cbd_t	*tx_bd_base;
-	cbd_t	*cur_rx, *cur_tx;		/* The next free ring entry */
-	cbd_t	*dirty_tx;	/* The ring entries to be free()ed. */
+	cbd_t	*cur_rx, *cur_tx;	/* The next free ring entry */
+	cbd_t	*dirty_tx;		/* The ring entries to be free()ed. */
+	struct	net_device_stats stats;
 	uint	tx_full;
-	/* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
-	spinlock_t hw_lock;
-	/* hold while accessing the mii_list_t() elements */
-	spinlock_t mii_lock;
+	spinlock_t lock;
 
+#ifdef CONFIG_PHYLIB
+	struct	phy_device *phy;
+	uint	phy_speed;
+#else
 	uint	phy_id;
 	uint	phy_id_done;
 	uint	phy_status;
@@ -199,28 +278,41 @@ struct fec_enet_private {
 
 	uint	sequence_done;
 	uint	mii_phy_task_queued;
-
+#endif
 	uint	phy_addr;
 
-	int	index;
-	int	opened;
-	int	link;
-	int	old_link;
-	int	full_duplex;
+	unsigned int opened:1;
+	unsigned int phy_int_enabled:1;
+	unsigned int linkstatus:1;
+#ifndef CONFIG_PHYLIB
+	unsigned int old_linkstatus:1;
+#endif
+	unsigned int full_duplex:1;
+
+	struct clk *clk;
 };
 
-static int fec_enet_open(struct net_device *dev);
-static int fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev);
-static void fec_enet_mii(struct net_device *dev);
-static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
+#ifdef CONFIG_PHYLIB
+static int fec_connect_phy(struct net_device *dev, struct fec_enet_private *fep);
+#else
+static irqreturn_t mii_link_interrupt(int irq, void *dev_id);
+#endif
+static void fec_restart(struct net_device *dev, int duplex);
 static void fec_enet_tx(struct net_device *dev);
 static void fec_enet_rx(struct net_device *dev);
-static int fec_enet_close(struct net_device *dev);
-static void set_multicast_list(struct net_device *dev);
-static void fec_restart(struct net_device *dev, int duplex);
+static void fec_enet_mii(struct net_device *dev);
 static void fec_stop(struct net_device *dev);
-static void fec_set_mac_address(struct net_device *dev);
+static void _fec_set_mac_address(struct net_device *dev);
 
+/*
+ *  fec_copy_threshold controls the copy when receiving ethernet frame.
+ *     If ethernet header is aligned on a 4byte boundary, the ip header and
+ *     higher level header will not be aligned.
+ *     The reason is, that an ethernet header is 14bytes long.
+ *     And the max size of tcp & ip header is 128bytes. Normally it is 40bytes.
+ *     So I set the default value between 128 to 256.
+ */
+static int fec_copy_threshold = 192;
 
 /* MII processing.  We keep this as simple as possible.  Requests are
  * placed on the list (if there is room).  When the request is finished
@@ -232,14 +324,16 @@ typedef struct mii_list {
 	struct	mii_list *mii_next;
 } mii_list_t;
 
+#ifndef CONFIG_PHYLIB
 #define		NMII	20
 static mii_list_t	mii_cmds[NMII];
 static mii_list_t	*mii_free;
 static mii_list_t	*mii_head;
 static mii_list_t	*mii_tail;
 
-static int	mii_queue(struct net_device *dev, int request,
-				void (*func)(uint, struct net_device *));
+static int mii_queue(struct net_device *dev, int request,
+		     void (*func)(uint, struct net_device *));
+#endif
 
 /* Make MII read/write commands for the FEC.
 */
@@ -284,47 +378,160 @@ static int	mii_queue(struct net_device *
 #define PHY_STAT_100HDX	0x4000  /* 100 Mbit half duplex selected */
 #define PHY_STAT_100FDX	0x8000  /* 100 Mbit full duplex selected */
 
+#ifndef DEBUG
+static inline unsigned long fec_reg_read(struct fec_enet_private *fep, unsigned int reg)
+{
+	return readl(fep->reg_base + reg);
+}
+
+static inline void fec_reg_write(struct fec_enet_private *fep, unsigned int reg, unsigned long val)
+{
+	writel(val, fep->reg_base + reg);
+}
+#else
+#define fec_reg_read(fep, reg)		__fec_reg_read(fep, reg, __FUNCTION__, #reg)
+#define fec_reg_write(fep, reg, val)	__fec_reg_write(fep, reg, val, __FUNCTION__, #reg)
+
+static inline unsigned long __fec_reg_read(struct fec_enet_private *fep, unsigned int reg,
+					   const char *func, const char *reg_name)
+{
+	unsigned long val = readl(fep->reg_base + reg);
+	DBG(3, "%s: Read %08lx from %s(%03x)\n", func, val, reg_name, reg);
+	return val;
+}
+
+static inline void __fec_reg_write(struct fec_enet_private *fep, unsigned int reg,
+				   unsigned long val, const char *func, const char *reg_name)
+{
+	DBG(3, "%s: Writing %08lx to %s(%03x)\n", func, val, reg_name, reg);
+	writel(val, fep->reg_base + reg);
+}
+#endif
+
+static inline void fec_enet_cbd_get(struct fec_enet_private *fep)
+{
+	DBG(2, "%s: Requesting cbd area: %08lx\n", __FUNCTION__,
+	    (unsigned long)fep->cbd_phys_base);
+	dma_sync_single_for_cpu(fep->dma_dev, fep->cbd_phys_base,
+				CBD_BUF_SIZE, DMA_BIDIRECTIONAL);
+}
+
+static inline void fec_enet_cbd_put(struct fec_enet_private *fep)
+{
+	DBG(2, "%s: Flushing changes to cbd area\n", __FUNCTION__);
+	dma_sync_single_for_device(fep->dma_dev, fep->cbd_phys_base,
+				   CBD_BUF_SIZE, DMA_BIDIRECTIONAL);
+}
+
+static inline void fec_enet_rxbuf_get(struct fec_enet_private *fep, cbd_t *bdp, ushort len)
+{
+	DBG(2, "%s: Requesting RX buffer %08lx(%u)\n", __FUNCTION__,
+	    (unsigned long)bdp->cbd_bufaddr, len);
+	dma_sync_single_for_cpu(fep->dma_dev, bdp->cbd_bufaddr,
+				len, DMA_FROM_DEVICE);
+}
+
+static inline void fec_enet_rxbuf_put(struct fec_enet_private *fep, cbd_t *bdp, ushort len)
+{
+	DBG(2, "%s: Releasing RX buffer %08lx(%u)\n", __FUNCTION__, (ulong)bdp->cbd_bufaddr, len);
+	dma_sync_single_for_device(fep->dma_dev, bdp->cbd_bufaddr, len, DMA_FROM_DEVICE);
+}
+
+static inline void fec_enet_rxbuf_map(struct fec_enet_private *fep, cbd_t *bdp,
+				      void *buf, ushort len)
+{
+	BUG_ON(!dma_mapping_error(fep->dma_dev, bdp->cbd_bufaddr));
+	bdp->cbd_bufaddr = dma_map_single(fep->dma_dev, buf,
+					  len, DMA_FROM_DEVICE);
+	DBG(2, "%s: RX buffer %p(%u) mapped to %08lx\n", __FUNCTION__,
+	    buf, len, (unsigned long)bdp->cbd_bufaddr);
+}
+
+static inline void fec_enet_rxbuf_unmap(struct fec_enet_private *fep, cbd_t *bdp, ushort len)
+{
+	DBG(2, "%s: Unmapping RX buffer %08lx(%u)\n", __FUNCTION__,
+	    (unsigned long)bdp->cbd_bufaddr, len);
+	BUG_ON(dma_mapping_error(fep->dma_dev, bdp->cbd_bufaddr));
+	dma_unmap_single(fep->dma_dev, bdp->cbd_bufaddr,
+			 len, DMA_FROM_DEVICE);
+	bdp->cbd_bufaddr = ~0;
+}
+
+static inline void fec_enet_txbuf_map(struct fec_enet_private *fep, cbd_t *bdp,
+				      void *buf, ushort len)
+{
+	BUG_ON(!dma_mapping_error(fep->dma_dev, bdp->cbd_bufaddr));
+	bdp->cbd_bufaddr = dma_map_single(fep->dma_dev, buf,
+					  len, DMA_TO_DEVICE);
+	DBG(2, "%s: TX buffer %p(%u) mapped to %08lx\n", __FUNCTION__,
+	    buf, len, (unsigned long)bdp->cbd_bufaddr);
+}
+
+static inline void fec_enet_txbuf_unmap(struct fec_enet_private *fep, cbd_t *bdp, ushort len)
+{
+	DBG(2, "%s: Unmapping TX buffer %08lx(%u)\n", __FUNCTION__,
+	    (unsigned long)bdp->cbd_bufaddr, len);
+	BUG_ON(dma_mapping_error(fep->dma_dev, bdp->cbd_bufaddr));
+	dma_unmap_single(fep->dma_dev, bdp->cbd_bufaddr,
+			 len, DMA_TO_DEVICE);
+	bdp->cbd_bufaddr = ~0;
+}
+
+static inline void fec_enet_txbuf_get(struct fec_enet_private *fep, cbd_t *bdp, ushort len)
+{
+	DBG(2, "%s: Requesting TX buffer %08lx(%u)\n", __FUNCTION__,
+	    (unsigned long)bdp->cbd_bufaddr, len);
+	dma_sync_single_for_cpu(fep->dma_dev, bdp->cbd_bufaddr,
+				len, DMA_TO_DEVICE);
+}
+
+static inline void fec_enet_txbuf_put(struct fec_enet_private *fep, cbd_t *bdp, ushort len)
+{
+	DBG(2, "%s: Releasing TX buffer %08lx(%u)\n", __FUNCTION__,
+	    (unsigned long)bdp->cbd_bufaddr, len);
+	dma_sync_single_for_device(fep->dma_dev, bdp->cbd_bufaddr,
+				   len, DMA_TO_DEVICE);
+}
 
 static int
 fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-	struct fec_enet_private *fep;
-	volatile fec_t	*fecp;
-	volatile cbd_t	*bdp;
-	unsigned short	status;
+	struct fec_enet_private *fep = netdev_priv(dev);
+	cbd_t *bdp;
+	unsigned short status;
 	unsigned long flags;
 
-	fep = netdev_priv(dev);
-	fecp = (volatile fec_t*)dev->base_addr;
-
-	if (!fep->link) {
+	if (!fep->linkstatus) {
+		DBG(0, "%s: Cannot send packet; link is down\n", __FUNCTION__);
 		/* Link is down or autonegotiation is in progress. */
-		return 1;
+		return NETDEV_TX_BUSY;
 	}
 
-	spin_lock_irqsave(&fep->hw_lock, flags);
+	spin_lock_irqsave(&fep->lock, flags);
+
+	fec_enet_cbd_get(fep);
+
 	/* Fill in a Tx ring entry */
 	bdp = fep->cur_tx;
 
 	status = bdp->cbd_sc;
-#ifndef final_version
+#ifdef DEBUG
 	if (status & BD_ENET_TX_READY) {
 		/* Ooops.  All transmit buffers are full.  Bail out.
 		 * This should not happen, since dev->tbusy should be set.
 		 */
 		printk("%s: tx queue full!.\n", dev->name);
-		spin_unlock_irqrestore(&fep->hw_lock, flags);
-		return 1;
+		fec_enet_cbd_put(fep);
+		spin_unlock_irqrestore(&fep->lock, flags);
+		return NETDEV_TX_BUSY;
 	}
 #endif
-
 	/* Clear all of the status flags.
 	 */
 	status &= ~BD_ENET_TX_STATS;
 
 	/* Set buffer length and buffer pointer.
 	*/
-	bdp->cbd_bufaddr = __pa(skb->data);
 	bdp->cbd_datlen = skb->len;
 
 	/*
@@ -332,39 +539,31 @@ fec_enet_start_xmit(struct sk_buff *skb,
 	 *	4-byte boundaries. Use bounce buffers to copy data
 	 *	and get it aligned. Ugh.
 	 */
-	if (bdp->cbd_bufaddr & FEC_ALIGNMENT) {
+	if (unlikely((bdp->cbd_bufaddr) & FEC_ALIGNMENT)) {
 		unsigned int index;
 		index = bdp - fep->tx_bd_base;
-		memcpy(fep->tx_bounce[index], (void *)skb->data, skb->len);
-		bdp->cbd_bufaddr = __pa(fep->tx_bounce[index]);
+		memcpy(fep->tx_bounce[index], skb->data, skb->len);
+		fec_enet_txbuf_map(fep, bdp, fep->tx_bounce[index], skb->len);
+	} else {
+		fec_enet_txbuf_map(fep, bdp, skb->data, skb->len);
 	}
 
 	/* Save skb pointer.
 	*/
 	fep->tx_skbuff[fep->skb_cur] = skb;
 
-	dev->stats.tx_bytes += skb->len;
-	fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK;
-
-	/* Push the data cache so the CPM does not get stale memory
-	 * data.
-	 */
-	dma_sync_single(NULL, bdp->cbd_bufaddr,
-			bdp->cbd_datlen, DMA_TO_DEVICE);
+	fep->stats.tx_bytes += skb->len;
+	fep->skb_cur = (fep->skb_cur + 1) & TX_RING_MOD_MASK;
 
 	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
 	 * it's the last BD of the frame, and to put the CRC on the end.
 	 */
-
 	status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR
 			| BD_ENET_TX_LAST | BD_ENET_TX_TC);
 	bdp->cbd_sc = status;
 
 	dev->trans_start = jiffies;
 
-	/* Trigger transmission start */
-	fecp->fec_x_des_active = 0;
-
 	/* If this was the last BD in the ring, start at the beginning again.
 	*/
 	if (status & BD_ENET_TX_WRAP) {
@@ -375,14 +574,19 @@ fec_enet_start_xmit(struct sk_buff *skb,
 
 	if (bdp == fep->dirty_tx) {
 		fep->tx_full = 1;
+		DBG(0, "TX ring full, stopping netif queue\n");
 		netif_stop_queue(dev);
 	}
 
-	fep->cur_tx = (cbd_t *)bdp;
+	fep->cur_tx = bdp;
+	fec_enet_cbd_put(fep);
+
+	/* Trigger transmission start */
+	fec_reg_write(fep, FEC_TDAR, DONT_CARE);
 
-	spin_unlock_irqrestore(&fep->hw_lock, flags);
+	spin_unlock_irqrestore(&fep->lock, flags);
 
-	return 0;
+	return NETDEV_TX_OK;
 }
 
 static void
@@ -390,101 +594,125 @@ fec_timeout(struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 
-	printk("%s: transmit timed out.\n", dev->name);
-	dev->stats.tx_errors++;
-#ifndef final_version
+	printk(KERN_WARNING "%s: transmit timed out.\n", dev->name);
+	fep->stats.tx_errors++;
+#ifdef DEBUG
 	{
-	int	i;
-	cbd_t	*bdp;
+		int i;
+		cbd_t *bdp;
 
-	printk("Ring data dump: cur_tx %lx%s, dirty_tx %lx cur_rx: %lx\n",
-	       (unsigned long)fep->cur_tx, fep->tx_full ? " (full)" : "",
-	       (unsigned long)fep->dirty_tx,
-	       (unsigned long)fep->cur_rx);
+		fec_enet_cbd_get(fep);
 
-	bdp = fep->tx_bd_base;
-	printk(" tx: %u buffers\n",  TX_RING_SIZE);
-	for (i = 0 ; i < TX_RING_SIZE; i++) {
-		printk("  %08x: %04x %04x %08x\n",
-		       (uint) bdp,
-		       bdp->cbd_sc,
-		       bdp->cbd_datlen,
-		       (int) bdp->cbd_bufaddr);
-		bdp++;
-	}
+		printk(KERN_DEBUG "%s: Ring data dump: cur_tx %p%s, dirty_tx %p cur_rx: %p\n",
+		       __FUNCTION__,
+		       fep->cur_tx, fep->tx_full ? " (full)" : "",
+		       fep->dirty_tx,
+		       fep->cur_rx);
 
-	bdp = fep->rx_bd_base;
-	printk(" rx: %lu buffers\n",  (unsigned long) RX_RING_SIZE);
-	for (i = 0 ; i < RX_RING_SIZE; i++) {
-		printk("  %08x: %04x %04x %08x\n",
-		       (uint) bdp,
-		       bdp->cbd_sc,
-		       bdp->cbd_datlen,
-		       (int) bdp->cbd_bufaddr);
-		bdp++;
-	}
+		bdp = fep->tx_bd_base;
+		printk(" tx: %u buffers\n", TX_RING_SIZE);
+		for (i = 0; i < TX_RING_SIZE; i++) {
+			printk("  %p: %04x %04x %08x\n",
+			       bdp,
+			       bdp->cbd_sc,
+			       bdp->cbd_datlen,
+			       bdp->cbd_bufaddr);
+			bdp++;
+		}
+
+		bdp = fep->rx_bd_base;
+		printk(" rx: %lu buffers\n", RX_RING_SIZE);
+		for (i = 0; i < RX_RING_SIZE; i++) {
+			printk("  %p: %04x %04x %08x\n",
+			       bdp,
+			       bdp->cbd_sc,
+			       bdp->cbd_datlen,
+			       bdp->cbd_bufaddr);
+			bdp++;
+		}
+		fec_enet_cbd_put(fep);
 	}
 #endif
 	fec_restart(dev, fep->full_duplex);
-	netif_wake_queue(dev);
+	DBG(0, "%s: Scheduling netif queue\n", __FUNCTION__);
+	//netif_schedule(dev);
 }
 
 /* The interrupt handler.
  * This is called from the MPC core interrupt.
  */
 static irqreturn_t
-fec_enet_interrupt(int irq, void * dev_id)
+fec_enet_interrupt(int irq, void *dev_id)
 {
-	struct	net_device *dev = dev_id;
-	volatile fec_t	*fecp;
-	uint	int_events;
-	irqreturn_t ret = IRQ_NONE;
-
-	fecp = (volatile fec_t*)dev->base_addr;
+	struct net_device *dev = dev_id;
+	struct fec_enet_private *fep = netdev_priv(dev);
+	uint int_events;
+	int handled = 0;
+	unsigned int eimr = fec_reg_read(fep, FEC_EIMR);
 
+	DBG(2, "%s: %08lx:%08lx\n", __FUNCTION__,
+	    fec_reg_read(fep, FEC_EIR), fec_reg_read(fep, FEC_EIMR));
 	/* Get the interrupt events that caused us to be here.
 	*/
-	do {
-		int_events = fecp->fec_ievent;
-		fecp->fec_ievent = int_events;
+	while ((int_events = fec_reg_read(fep, FEC_EIR) & FEC_ENET_MASK) != 0) {
+		if (int_events & ~eimr) {
+			printk(KERN_WARNING "%s: masked interrupt condition: %08x\n",
+			       __FUNCTION__, int_events & ~eimr);
+		}
+
+		fec_reg_write(fep, FEC_EIR, int_events);
 
 		/* Handle receive event in its own function.
 		 */
-		if (int_events & FEC_ENET_RXF) {
-			ret = IRQ_HANDLED;
+		if (int_events & (FEC_ENET_RXF | FEC_ENET_RXB)) {
+			DBG(2, "%s: Handling RX Interrupt\n", __FUNCTION__);
+			handled = 1;
 			fec_enet_rx(dev);
 		}
 
+		if (int_events & FEC_ENET_UN) {
+			printk(KERN_WARNING "TX fifo underrun");
+		}
 		/* Transmit OK, or non-fatal error. Update the buffer
 		   descriptors. FEC handles all errors, we just discover
 		   them as part of the transmit process.
 		*/
-		if (int_events & FEC_ENET_TXF) {
-			ret = IRQ_HANDLED;
+		if (int_events & (FEC_ENET_TXF | FEC_ENET_TXB)) {
+			DBG(2, "%s: Handling TX Interrupt\n", __FUNCTION__);
+			handled = 1;
 			fec_enet_tx(dev);
 		}
 
-		if (int_events & FEC_ENET_MII) {
-			ret = IRQ_HANDLED;
+		if (int_events & (FEC_ENET_MII | FEC_ENET_HBERR)) {
+			DBG(2, "%s: Handling MII Interrupt\n", __FUNCTION__);
+			handled = 1;
 			fec_enet_mii(dev);
 		}
-
-	} while (int_events);
-
-	return ret;
+	}
+	return IRQ_RETVAL(handled);
 }
 
+static void fec_free_skb(struct fec_enet_private *fep, cbd_t *bdp, struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	if (!dma_mapping_error(fep->dma_dev, bdp->cbd_bufaddr)) {
+		fec_enet_txbuf_unmap(fep, bdp, skb->len);
+	}
+	dev_kfree_skb_any(skb);
+	*pskb = NULL;
+}
 
 static void
 fec_enet_tx(struct net_device *dev)
 {
-	struct	fec_enet_private *fep;
-	volatile cbd_t	*bdp;
+	struct fec_enet_private *fep = netdev_priv(dev);
+	cbd_t *bdp;
 	unsigned short status;
-	struct	sk_buff	*skb;
+	struct sk_buff *skb;
 
-	fep = netdev_priv(dev);
-	spin_lock_irq(&fep->hw_lock);
+	spin_lock(&fep->lock);
+
+	fec_enet_cbd_get(fep);
 	bdp = fep->dirty_tx;
 
 	while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) {
@@ -495,22 +723,22 @@ fec_enet_tx(struct net_device *dev)
 		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
 				   BD_ENET_TX_RL | BD_ENET_TX_UN |
 				   BD_ENET_TX_CSL)) {
-			dev->stats.tx_errors++;
+			fep->stats.tx_errors++;
 			if (status & BD_ENET_TX_HB)  /* No heartbeat */
-				dev->stats.tx_heartbeat_errors++;
+				fep->stats.tx_heartbeat_errors++;
 			if (status & BD_ENET_TX_LC)  /* Late collision */
-				dev->stats.tx_window_errors++;
+				fep->stats.tx_window_errors++;
 			if (status & BD_ENET_TX_RL)  /* Retrans limit */
-				dev->stats.tx_aborted_errors++;
+				fep->stats.tx_aborted_errors++;
 			if (status & BD_ENET_TX_UN)  /* Underrun */
-				dev->stats.tx_fifo_errors++;
+				fep->stats.tx_fifo_errors++;
 			if (status & BD_ENET_TX_CSL) /* Carrier lost */
-				dev->stats.tx_carrier_errors++;
+				fep->stats.tx_carrier_errors++;
 		} else {
-			dev->stats.tx_packets++;
+			fep->stats.tx_packets++;
 		}
 
-#ifndef final_version
+#ifdef DEBUG
 		if (status & BD_ENET_TX_READY)
 			printk("HEY! Enet xmit interrupt and TX_READY.\n");
 #endif
@@ -518,12 +746,11 @@ fec_enet_tx(struct net_device *dev)
 		 * but we eventually sent the packet OK.
 		 */
 		if (status & BD_ENET_TX_DEF)
-			dev->stats.collisions++;
+			fep->stats.collisions++;
 
 		/* Free the sk buffer associated with this last transmit.
 		 */
-		dev_kfree_skb_any(skb);
-		fep->tx_skbuff[fep->skb_dirty] = NULL;
+		fec_free_skb(fep, bdp, &fep->tx_skbuff[fep->skb_dirty]);
 		fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK;
 
 		/* Update pointer to next buffer descriptor to be transmitted.
@@ -538,12 +765,15 @@ fec_enet_tx(struct net_device *dev)
 		 */
 		if (fep->tx_full) {
 			fep->tx_full = 0;
-			if (netif_queue_stopped(dev))
+			if (netif_queue_stopped(dev)) {
+				DBG(0, "%s: Waking up netif queue\n", __FUNCTION__);
 				netif_wake_queue(dev);
+			}
 		}
 	}
-	fep->dirty_tx = (cbd_t *)bdp;
-	spin_unlock_irq(&fep->hw_lock);
+	fec_enet_cbd_put(fep);
+	fep->dirty_tx = bdp;
+	spin_unlock(&fep->lock);
 }
 
 
@@ -555,22 +785,22 @@ fec_enet_tx(struct net_device *dev)
 static void
 fec_enet_rx(struct net_device *dev)
 {
-	struct	fec_enet_private *fep;
-	volatile fec_t	*fecp;
-	volatile cbd_t *bdp;
+	struct fec_enet_private *fep = netdev_priv(dev);
+	cbd_t *bdp;
 	unsigned short status;
-	struct	sk_buff	*skb;
-	ushort	pkt_len;
-	__u8 *data;
+	struct sk_buff *skb;
+	ushort pkt_len;
+	int rx_index;
 
 #ifdef CONFIG_M532x
+	/* This is probably nonsense
+	   Proper use of dma-mapping functions should make this obsolete
+	*/
 	flush_cache_all();
 #endif
-
-	fep = netdev_priv(dev);
-	fecp = (volatile fec_t*)dev->base_addr;
-
-	spin_lock_irq(&fep->hw_lock);
+	/* reserve the dual port memory area for our use */
+	//WARN_ON(fec_reg_read(fep, FEC_RDAR) & RDAR_BUSY);
+	fec_enet_cbd_get(fep);
 
 	/* First, grab all of the stats for the incoming packet.
 	 * These get messed up if we get called due to a busy condition.
@@ -578,32 +808,34 @@ fec_enet_rx(struct net_device *dev)
 	bdp = fep->cur_rx;
 
 while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) {
-
-#ifndef final_version
+	rx_index = bdp - fep->rx_bd_base;
+#ifdef DEBUG
 	/* Since we have allocated space to hold a complete frame,
 	 * the last indicator should be set.
 	 */
-	if ((status & BD_ENET_RX_LAST) == 0)
-		printk("FEC ENET: rcv is not +last\n");
+	WARN_ON(!(status & BD_ENET_RX_LAST));
 #endif
 
-	if (!fep->opened)
+	if (WARN_ON(!fep->opened)) {
+		DBG(0, "%s: Driver not opened; ignoring packet\n", __FUNCTION__);
+#if 0
 		goto rx_processing_done;
-
+#endif
+	}
 	/* Check for errors. */
 	if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH | BD_ENET_RX_NO |
 			   BD_ENET_RX_CR | BD_ENET_RX_OV)) {
-		dev->stats.rx_errors++;
+		fep->stats.rx_errors++;
 		if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
 		/* Frame too long or too short. */
-			dev->stats.rx_length_errors++;
+			fep->stats.rx_length_errors++;
 		}
 		if (status & BD_ENET_RX_NO)	/* Frame alignment */
-			dev->stats.rx_frame_errors++;
+			fep->stats.rx_frame_errors++;
 		if (status & BD_ENET_RX_CR)	/* CRC Error */
-			dev->stats.rx_crc_errors++;
+			fep->stats.rx_crc_errors++;
 		if (status & BD_ENET_RX_OV)	/* FIFO overrun */
-			dev->stats.rx_fifo_errors++;
+			fep->stats.rx_fifo_errors++;
 	}
 
 	/* Report late collisions as a frame error.
@@ -611,39 +843,67 @@ while (!((status = bdp->cbd_sc) & BD_ENE
 	 * have in the buffer.  So, just drop this frame on the floor.
 	 */
 	if (status & BD_ENET_RX_CL) {
-		dev->stats.rx_errors++;
-		dev->stats.rx_frame_errors++;
+		fep->stats.rx_errors++;
+		fep->stats.rx_frame_errors++;
+		DBG(0, "%s: Collision detected; dropping packet\n", __FUNCTION__);
+		goto rx_processing_done;
+	}
+
+	if (!fep->opened) {
+		DBG(0, "%s: Driver not opened; ignoring packet\n", __FUNCTION__);
 		goto rx_processing_done;
 	}
 
 	/* Process the incoming frame.
 	 */
-	dev->stats.rx_packets++;
+	fep->stats.rx_packets++;
 	pkt_len = bdp->cbd_datlen;
-	dev->stats.rx_bytes += pkt_len;
-	data = (__u8*)__va(bdp->cbd_bufaddr);
-
-	dma_sync_single(NULL, (unsigned long)__pa(data),
-			pkt_len - 4, DMA_FROM_DEVICE);
+	fep->stats.rx_bytes += pkt_len;
 
 	/* This does 16 byte alignment, exactly what we need.
 	 * The packet length includes FCS, but we don't want to
 	 * include that when passing upstream as it messes up
 	 * bridging applications.
 	 */
-	skb = dev_alloc_skb(pkt_len-4);
+	if ((pkt_len - 4) < fec_copy_threshold) {
+		skb = dev_alloc_skb(pkt_len);
+	} else {
+		skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE);
+	}
 
 	if (skb == NULL) {
 		printk("%s: Memory squeeze, dropping packet.\n", dev->name);
-		dev->stats.rx_dropped++;
+		fep->stats.rx_dropped++;
 	} else {
-		skb_put(skb,pkt_len-4);	/* Make room */
-		skb_copy_to_linear_data(skb, data, pkt_len-4);
-		skb->protocol=eth_type_trans(skb,dev);
+		if ((pkt_len - 4) < fec_copy_threshold) {
+			/* skip 2 bytes, so IP header is on a 4 bytes boundary */
+			skb_reserve(skb, 2);
+			skb_put(skb, pkt_len - 4); /* Make room */
+			fec_enet_rxbuf_get(fep, bdp, pkt_len - 4);
+			skb_copy_to_linear_data(skb,
+						fep->rx_skbuff[rx_index]->data,
+						pkt_len - 4);
+			fec_enet_rxbuf_put(fep, bdp, pkt_len - 4);
+		} else {
+			struct sk_buff *pskb = fep->rx_skbuff[rx_index];
+
+			/* unmap the skb we are going to hand down to the network layer */
+			fec_enet_rxbuf_unmap(fep, bdp, FEC_ENET_RX_FRSIZE);
+
+			/* init the newly allocated skb */
+			fep->rx_skbuff[rx_index] = skb;
+			skb->data = FEC_ADDR_ALIGNMENT(skb->data);
+			/* map the newly allocated skb's data buffer for DMA */
+			fec_enet_rxbuf_map(fep, bdp, skb->data, FEC_ENET_RX_FRSIZE);
+
+			skb_put(pskb, pkt_len - 4);        /* Make room */
+			skb = pskb;
+		}
+		skb->dev = dev;
+		skb->protocol = eth_type_trans(skb, dev);
 		netif_rx(skb);
 	}
   rx_processing_done:
-
 	/* Clear the status flags for this buffer.
 	*/
 	status &= ~BD_ENET_RX_STATS;
@@ -653,6 +913,9 @@ while (!((status = bdp->cbd_sc) & BD_ENE
 	status |= BD_ENET_RX_EMPTY;
 	bdp->cbd_sc = status;
 
+	/* release the dual port memory area for use by the FEC hardware */
+	fec_enet_cbd_put(fep);
+
 	/* Update BD pointer to next entry.
 	*/
 	if (status & BD_ENET_RX_WRAP)
@@ -665,10 +928,10 @@ while (!((status = bdp->cbd_sc) & BD_ENE
 	 * incoming frames.  On a heavily loaded network, we should be
 	 * able to keep up at the expense of system resources.
 	 */
-	fecp->fec_r_des_active = 0;
+	fec_reg_write(fep, FEC_RDAR, DONT_CARE);
 #endif
    } /* while (!((status = bdp->cbd_sc) & BD_ENET_RX_EMPTY)) */
-	fep->cur_rx = (cbd_t *)bdp;
+	fep->cur_rx = bdp;
 
 #if 0
 	/* Doing this here will allow us to process all frames in the
@@ -678,27 +941,28 @@ while (!((status = bdp->cbd_sc) & BD_ENE
 	 * our way back to the interrupt return only to come right back
 	 * here.
 	 */
-	fecp->fec_r_des_active = 0;
+	fec_reg_write(fep, FEC_RDAR, DONT_CARE);
 #endif
-
-	spin_unlock_irq(&fep->hw_lock);
 }
 
-
+#ifdef CONFIG_PHYLIB
 /* called from interrupt context */
+static void fec_enet_mii(struct net_device *dev)
+{
+	struct fec_enet_private *fep = netdev_priv(dev);
+	fep->mii_complete = 1;
+}
+#else
 static void
 fec_enet_mii(struct net_device *dev)
 {
-	struct	fec_enet_private *fep;
-	volatile fec_t	*ep;
+	struct fec_enet_private *fep = netdev_priv(dev);
 	mii_list_t	*mip;
 	uint		mii_reg;
 
-	fep = netdev_priv(dev);
-	spin_lock_irq(&fep->mii_lock);
+	mii_reg = fec_reg_read(fep, FEC_MMFR);
 
-	ep = fep->hwp;
-	mii_reg = ep->fec_mii_data;
+	spin_lock(&fep->lock);
 
 	if ((mip = mii_head) == NULL) {
 		printk("MII and no head!\n");
@@ -713,27 +977,27 @@ fec_enet_mii(struct net_device *dev)
 	mii_free = mip;
 
 	if ((mip = mii_head) != NULL)
-		ep->fec_mii_data = mip->mii_regval;
+		fec_reg_write(fep, FEC_MMFR, mip->mii_regval);
 
 unlock:
-	spin_unlock_irq(&fep->mii_lock);
+	spin_unlock(&fep->lock);
 }
 
 static int
 mii_queue(struct net_device *dev, int regval, void (*func)(uint, struct net_device *))
 {
-	struct fec_enet_private *fep;
+	struct fec_enet_private *fep = netdev_priv(dev);
 	unsigned long	flags;
 	mii_list_t	*mip;
 	int		retval;
 
+	retval = 0;
+
+	spin_lock_irqsave(&fep->lock,flags);
+
 	/* Add PHY address to register command.
 	*/
-	fep = netdev_priv(dev);
-	spin_lock_irqsave(&fep->mii_lock, flags);
-
 	regval |= fep->phy_addr << 23;
-	retval = 0;
 
 	if ((mip = mii_free) != NULL) {
 		mii_free = mip->mii_next;
@@ -745,32 +1009,32 @@ mii_queue(struct net_device *dev, int re
 			mii_tail = mip;
 		} else {
 			mii_head = mii_tail = mip;
-			fep->hwp->fec_mii_data = regval;
+			fec_reg_write(fep, FEC_MMFR, regval);
 		}
 	} else {
 		retval = 1;
 	}
 
-	spin_unlock_irqrestore(&fep->mii_lock, flags);
-	return retval;
+	spin_unlock_irqrestore(&fep->lock,flags);
+
+	return(retval);
 }
 
 static void mii_do_cmd(struct net_device *dev, const phy_cmd_t *c)
 {
-	if(!c)
-		return;
+	int k;
 
-	for (; c->mii_data != mk_mii_end; c++)
-		mii_queue(dev, c->mii_data, c->funct);
+	for (k = 0; c != NULL && c[k].mii_data != mk_mii_end; k++) {
+		mii_queue(dev, c[k].mii_data, c[k].funct);
+	}
 }
 
 static void mii_parse_sr(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile uint *s = &(fep->phy_status);
 	uint status;
 
-	status = *s & ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
+	status = fep->phy_status & ~(PHY_STAT_LINK | PHY_STAT_FAULT | PHY_STAT_ANC);
 
 	if (mii_reg & 0x0004)
 		status |= PHY_STAT_LINK;
@@ -778,31 +1042,30 @@ static void mii_parse_sr(uint mii_reg, s
 		status |= PHY_STAT_FAULT;
 	if (mii_reg & 0x0020)
 		status |= PHY_STAT_ANC;
-	*s = status;
+
+	fep->phy_status = status;
 }
 
 static void mii_parse_cr(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile uint *s = &(fep->phy_status);
 	uint status;
 
-	status = *s & ~(PHY_CONF_ANE | PHY_CONF_LOOP);
+	status = fep->phy_status & ~(PHY_CONF_ANE | PHY_CONF_LOOP);
 
 	if (mii_reg & 0x1000)
 		status |= PHY_CONF_ANE;
 	if (mii_reg & 0x4000)
 		status |= PHY_CONF_LOOP;
-	*s = status;
+	fep->phy_status = status;
 }
 
 static void mii_parse_anar(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile uint *s = &(fep->phy_status);
 	uint status;
 
-	status = *s & ~(PHY_CONF_SPMASK);
+	status = fep->phy_status & ~(PHY_CONF_SPMASK);
 
 	if (mii_reg & 0x0020)
 		status |= PHY_CONF_10HDX;
@@ -812,7 +1075,7 @@ static void mii_parse_anar(uint mii_reg,
 		status |= PHY_CONF_100HDX;
 	if (mii_reg & 0x00100)
 		status |= PHY_CONF_100FDX;
-	*s = status;
+	fep->phy_status = status;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -827,10 +1090,9 @@ static void mii_parse_anar(uint mii_reg,
 static void mii_parse_lxt970_csr(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile uint *s = &(fep->phy_status);
 	uint status;
 
-	status = *s & ~(PHY_STAT_SPMASK);
+	status = fep->phy_status & ~(PHY_STAT_SPMASK);
 	if (mii_reg & 0x0800) {
 		if (mii_reg & 0x1000)
 			status |= PHY_STAT_100FDX;
@@ -842,7 +1104,7 @@ static void mii_parse_lxt970_csr(uint mi
 		else
 			status |= PHY_STAT_10HDX;
 	}
-	*s = status;
+	fep->phy_status = status;
 }
 
 static phy_cmd_t const phy_cmd_lxt970_config[] = {
@@ -898,16 +1160,15 @@ static phy_info_t const phy_info_lxt970 
 static void mii_parse_lxt971_sr2(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile uint *s = &(fep->phy_status);
 	uint status;
 
-	status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
+	status = fep->phy_status & ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
 
 	if (mii_reg & 0x0400) {
-		fep->link = 1;
+		fep->linkstatus = 1;
 		status |= PHY_STAT_LINK;
 	} else {
-		fep->link = 0;
+		fep->linkstatus = 0;
 	}
 	if (mii_reg & 0x0080)
 		status |= PHY_STAT_ANC;
@@ -925,7 +1186,7 @@ static void mii_parse_lxt971_sr2(uint mi
 	if (mii_reg & 0x0008)
 		status |= PHY_STAT_FAULT;
 
-	*s = status;
+	fep->phy_status = status;
 }
 
 static phy_cmd_t const phy_cmd_lxt971_config[] = {
@@ -982,10 +1243,9 @@ static phy_info_t const phy_info_lxt971 
 static void mii_parse_qs6612_pcr(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile uint *s = &(fep->phy_status);
 	uint status;
 
-	status = *s & ~(PHY_STAT_SPMASK);
+	status = fep->phy_status & ~(PHY_STAT_SPMASK);
 
 	switch((mii_reg >> 2) & 7) {
 	case 1: status |= PHY_STAT_10HDX; break;
@@ -994,7 +1254,7 @@ static void mii_parse_qs6612_pcr(uint mi
 	case 6: status |= PHY_STAT_100FDX; break;
 }
 
-	*s = status;
+	fep->phy_status = status;
 }
 
 static phy_cmd_t const phy_cmd_qs6612_config[] = {
@@ -1052,10 +1312,9 @@ static phy_info_t const phy_info_qs6612 
 static void mii_parse_am79c874_dr(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile uint *s = &(fep->phy_status);
 	uint status;
 
-	status = *s & ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
+	status = fep->phy_status & ~(PHY_STAT_SPMASK | PHY_STAT_ANC);
 
 	if (mii_reg & 0x0080)
 		status |= PHY_STAT_ANC;
@@ -1064,7 +1323,7 @@ static void mii_parse_am79c874_dr(uint m
 	else
 		status |= ((mii_reg & 0x0800) ? PHY_STAT_10FDX : PHY_STAT_10HDX);
 
-	*s = status;
+	fep->phy_status = status;
 }
 
 static phy_cmd_t const phy_cmd_am79c874_config[] = {
@@ -1107,7 +1366,7 @@ static phy_info_t const phy_info_am79c87
 /* register definitions for the 8721 */
 
 #define MII_KS8721BL_RXERCR	21
-#define MII_KS8721BL_ICSR	27
+#define MII_KS8721BL_ICSR	22
 #define	MII_KS8721BL_PHYCR	31
 
 static phy_cmd_t const phy_cmd_ks8721bl_config[] = {
@@ -1149,32 +1408,31 @@ static phy_info_t const phy_info_ks8721b
 static void mii_parse_dp8384x_sr2(uint mii_reg, struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile uint *s = &(fep->phy_status);
 
-	*s &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
+	fep->phy_status &= ~(PHY_STAT_SPMASK | PHY_STAT_LINK | PHY_STAT_ANC);
 
 	/* Link up */
 	if (mii_reg & 0x0001) {
-		fep->link = 1;
-		*s |= PHY_STAT_LINK;
+		fep->linkstatus = 1;
+		fep->phy_status |= PHY_STAT_LINK;
 	} else
-		fep->link = 0;
+		fep->linkstatus = 0;
 	/* Status of link */
 	if (mii_reg & 0x0010)   /* Autonegotioation complete */
-		*s |= PHY_STAT_ANC;
+		fep->phy_status |= PHY_STAT_ANC;
 	if (mii_reg & 0x0002) {   /* 10MBps? */
 		if (mii_reg & 0x0004)   /* Full Duplex? */
-			*s |= PHY_STAT_10FDX;
+			fep->phy_status |= PHY_STAT_10FDX;
 		else
-			*s |= PHY_STAT_10HDX;
+			fep->phy_status |= PHY_STAT_10HDX;
 	} else {                  /* 100 Mbps? */
 		if (mii_reg & 0x0004)   /* Full Duplex? */
-			*s |= PHY_STAT_100FDX;
+			fep->phy_status |= PHY_STAT_100FDX;
 		else
-			*s |= PHY_STAT_100HDX;
+			fep->phy_status |= PHY_STAT_100HDX;
 	}
 	if (mii_reg & 0x0008)
-		*s |= PHY_STAT_FAULT;
+		fep->phy_status |= PHY_STAT_FAULT;
 }
 
 static phy_info_t phy_info_dp83848= {
@@ -1211,122 +1469,391 @@ static phy_info_t const * const phy_info
 	&phy_info_dp83848,
 	NULL
 };
-
-/* ------------------------------------------------------------------------- */
-#ifdef HAVE_mii_link_interrupt
-static irqreturn_t
-mii_link_interrupt(int irq, void * dev_id);
+#endif
 
 /*
- *	This is specific to the MII interrupt setup of the M5272EVB.
+ * do some initializtion based architecture of this chip
+MOVED to platform_data hooks!
  */
-static void __inline__ fec_request_mii_intr(struct net_device *dev)
+
+#define PHY_POLL_LINK_ON	(1 * HZ)
+#define PHY_POLL_LINK_OFF	(HZ / 5)
+
+static int fec_mii_read(struct mii_bus *bus, int phy_id, int regnum);
+
+#ifdef CONFIG_PHYLIB
+static void fec_link_change(struct net_device *dev)
 {
-	if (request_irq(66, mii_link_interrupt, IRQF_DISABLED, "fec(MII)", dev) != 0)
-		printk("FEC: Could not allocate fec(MII) IRQ(66)!\n");
-}
+	struct fec_enet_private *fep = netdev_priv(dev);
+	struct phy_device *phydev = fep->phy;
 
-static void __inline__ fec_disable_phy_intr(void)
+	if (phydev->link != fep->linkstatus ||
+	    phydev->duplex != fep->full_duplex) {
+		DBG(0, "%s: link status changed from %d to %d %s -> %s duplex\n", __FUNCTION__,
+		    fep->linkstatus, phydev->link, fep->full_duplex ? "full" : "half",
+		    phydev->duplex ? "full" : "half");
+		if (phydev->link) {
+			fec_restart(dev, phydev->duplex);
+		} else {
+			fec_stop(dev);
+		}
+		if (fep->linkstatus != phydev->link && netif_msg_link(fep)) {
+			phy_print_status(phydev);
+		}
+		fep->linkstatus = phydev->link;
+#if 0
+		int i;
+		for (i = 0; i < 32; i++) {
+			DBG(0, "%s: PHY reg[%02x]=%04x\n", __FUNCTION__, i,
+			    fec_mii_read(fep->mii, fep->phy_addr, i));
+		}
+#endif
+	}
+}
+#else
+static void fec_link_change(struct net_device *dev)
 {
-	volatile unsigned long *icrp;
-	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	*icrp = 0x08000000;
+	struct fec_enet_private *fep = netdev_priv(dev);
+
+	DBG(0, "%s: link status changed from %d to %d\n", __FUNCTION__,
+	    fep->old_linkstatus, fep->linkstatus);
+	if (fep->linkstatus) {
+		int duplex;
+
+		duplex = 0;
+		if (fep->phy_status & (PHY_STAT_100FDX | PHY_STAT_10FDX)) {
+			duplex = 1;
+		}
+		fec_restart(dev, duplex);
+		if (fep->phy_timer) {
+			mod_timer(fep->phy_timer, jiffies + PHY_POLL_LINK_ON);
+		}
+	} else {
+		fec_stop(dev);
+		if (fep->phy_timer) {
+			mod_timer(fep->phy_timer, jiffies + PHY_POLL_LINK_OFF);
+		}
+	}
+
+	fep->old_linkstatus = fep->linkstatus;
 }
 
-static void __inline__ fec_phy_ack_intr(void)
+static void fec_phy_timer(unsigned long data)
 {
-	volatile unsigned long *icrp;
-	/* Acknowledge the interrupt */
-	icrp = (volatile unsigned long *) (MCF_MBAR + MCFSIM_ICR1);
-	*icrp = 0x0d000000;
+	struct net_device *dev = (struct net_device *)data;
+	struct fec_enet_private *fep = netdev_priv(dev);
+	int link_poll_interval = fep->linkstatus ? PHY_POLL_LINK_ON : PHY_POLL_LINK_OFF;
+
+	if (fep->old_linkstatus != fep->linkstatus) {
+		fec_link_change(dev);
+	}
+	mod_timer(fep->phy_timer, link_poll_interval);
 }
 #endif
 
-#ifdef CONFIG_M5272
-static void __inline__ fec_get_mac(struct net_device *dev)
+/*
+ * Code specific to Freescale i.MXC
+ */
+static int fec_request_intrs(struct platform_device *pdev, struct net_device *dev)
 {
+	int ret;
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile fec_t *fecp;
-	unsigned char *iap, tmpaddr[ETH_ALEN];
 
-	fecp = fep->hwp;
+	fep->etn_irq = platform_get_irq(pdev, 0);
+	fep->mii_irq = platform_get_irq(pdev, 1);
 
-	if (FEC_FLASHMAC) {
+	/* Setup interrupt handlers. */
+	ret = request_irq(fep->etn_irq, fec_enet_interrupt, 0, "fec", dev);
+	if (ret != 0) {
+		printk(KERN_ERR "FEC: Could not allocate FEC IRQ(%d)!\n", fep->etn_irq);
+		return ret;
+	}
+#ifndef CONFIG_PHYLIB
+	if (fep->mii_irq >= 0) {
+		/* TODO: disable now due to CPLD issue */
+		ret = request_irq(fep->mii_irq, mii_link_interrupt, 0, "fec(MII)", dev);
+		if (ret != 0) {
+			printk(KERN_ERR "FEC: Could not allocate FEC(MII) IRQ(%d)!\n",
+			       fep->mii_irq);
+			free_irq(fep->etn_irq, dev);
+			return ret;
+		}
 		/*
-		 * Get MAC address from FLASH.
-		 * If it is all 1's or 0's, use the default.
+		 * board specific workaround should be done in board specific code
+		 * This is unsafe anyway. An interrupt might have been asserted
+		 * already. Use IRQ_NOAUTOEN with request_irq() to have irq initially disabled.
 		 */
-		iap = (unsigned char *)FEC_FLASHMAC;
-		if ((iap[0] == 0) && (iap[1] == 0) && (iap[2] == 0) &&
-		    (iap[3] == 0) && (iap[4] == 0) && (iap[5] == 0))
-			iap = fec_mac_default;
-		if ((iap[0] == 0xff) && (iap[1] == 0xff) && (iap[2] == 0xff) &&
-		    (iap[3] == 0xff) && (iap[4] == 0xff) && (iap[5] == 0xff))
-			iap = fec_mac_default;
+		fep->phy_int_enabled = 1;
 	} else {
-		*((unsigned long *) &tmpaddr[0]) = fecp->fec_addr_low;
-		*((unsigned short *) &tmpaddr[4]) = (fecp->fec_addr_high >> 16);
-		iap = &tmpaddr[0];
+		fep->phy_timer = kzalloc(sizeof(struct timer_list), GFP_KERNEL);
+		if (fep->phy_timer == NULL) {
+			free_irq(fep->etn_irq, dev);
+			return -ENOMEM;
+		}
+		init_timer(fep->phy_timer);
+		fep->phy_timer->function = fec_phy_timer;
+		fep->phy_timer->data = (unsigned long)dev;
+		fec_link_change(dev);
 	}
-
-	memcpy(dev->dev_addr, iap, ETH_ALEN);
-
-	/* Adjust MAC if using default MAC address */
-	if (iap == fec_mac_default)
-		 dev->dev_addr[ETH_ALEN-1] = fec_mac_default[ETH_ALEN-1] + fep->index;
-}
 #endif
 
-/* ------------------------------------------------------------------------- */
+	return 0;
+}
 
-static void mii_display_status(struct net_device *dev)
+static void fec_release_intrs(struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
-	volatile uint *s = &(fep->phy_status);
 
-	if (!fep->link && !fep->old_link) {
-		/* Link is still down - don't print anything */
-		return;
+	free_irq(fep->etn_irq, dev);
+#ifndef CONFIG_PHYLIB
+	if (fep->mii_irq >= 0) {
+		free_irq(fep->mii_irq, dev);
 	}
+#endif
+}
 
-	printk("%s: status: ", dev->name);
-
-	if (!fep->link) {
-		printk("link down");
-	} else {
-		printk("link up");
-
-		switch(*s & PHY_STAT_SPMASK) {
-		case PHY_STAT_100FDX: printk(", 100MBit Full Duplex"); break;
-		case PHY_STAT_100HDX: printk(", 100MBit Half Duplex"); break;
-		case PHY_STAT_10FDX: printk(", 10MBit Full Duplex"); break;
-		case PHY_STAT_10HDX: printk(", 10MBit Half Duplex"); break;
-		default:
-			printk(", Unknown speed/duplex");
-		}
+#ifdef CONFIG_MACH_MX25
+/*
+ * i.MX25 allows RMII mode to be configured via a gasket
+ */
+#define FEC_MIIGSK_CFGR			0x300
+#define FEC_MIIGSK_ENR			0x308
 
-		if (*s & PHY_STAT_ANC)
-			printk(", auto-negotiation complete");
-	}
+#define FEC_MIIGSK_CFGR_FRCONT		(1 << 6)
+#define FEC_MIIGSK_CFGR_LBMODE		(1 << 4)
+#define FEC_MIIGSK_CFGR_EMODE		(1 << 3)
+#define FEC_MIIGSK_CFGR_IF_MODE_MASK	(3 << 0)
+#define FEC_MIIGSK_CFGR_IF_MODE_MII	(0 << 0)
+#define FEC_MIIGSK_CFGR_IF_MODE_RMII	(1 << 0)
 
-	if (*s & PHY_STAT_FAULT)
-		printk(", remote fault");
+#define FEC_MIIGSK_ENR_READY		(1 << 2)
+#define FEC_MIIGSK_ENR_EN		(1 << 1)
 
-	printk(".\n");
+#ifndef DEBUG
+static inline unsigned long fec_reg_read16(struct fec_enet_private *fep, unsigned int reg)
+{
+	return readw(fep->reg_base + reg);
 }
 
-static void mii_display_config(struct work_struct *work)
+static inline void fec_reg_write(struct fec_enet_private *fep, unsigned int reg, unsigned long val)
 {
-	struct fec_enet_private *fep = container_of(work, struct fec_enet_private, phy_task);
-	struct net_device *dev = fep->netdev;
-	uint status = fep->phy_status;
+	writew(val, fep->reg_base + reg);
+}
+#else
+#define fec_reg_read16(fep, reg)	__fec_reg_read16(fep, reg, __FUNCTION__, #reg)
+#define fec_reg_write16(fep, reg, val)	__fec_reg_write16(fep, reg, val, __FUNCTION__, #reg)
+
+static inline u16 __fec_reg_read16(struct fec_enet_private *fep, unsigned int reg,
+					   const char *func, const char *reg_name)
+{
+	u16 val = readw(fep->reg_base + reg);
+	DBG(0, "%s: Read %04x from %s(%03x)\n", func, val, reg_name, reg);
+	return val;
+}
+
+static inline void __fec_reg_write16(struct fec_enet_private *fep, unsigned int reg,
+				   u16 val, const char *func, const char *reg_name)
+{
+	DBG(0, "%s: Writing %04x to %s(%03x)\n", func, val, reg_name, reg);
+	writew(val, fep->reg_base + reg);
+}
+#endif
+
+static void fec_localhw_setup(struct net_device *dev)
+{
+	struct fec_enet_private *fep = netdev_priv(dev);
+	int loops;
+	const int max_loops = 10000;
+
+	/*
+	 * Set up the MII gasket for RMII mode
+	 */
+	dev_dbg(&dev->dev, "enable RMII gasket\n");
+
+	/* disable the gasket and wait */
+	fec_reg_write16(fep, FEC_MIIGSK_ENR, 0);
+	DBG(0, "%s: Waiting for RMII gasket idle\n", __FUNCTION__);
+	while (fec_reg_read16(fep, FEC_MIIGSK_ENR) & FEC_MIIGSK_ENR_READY)
+		udelay(1);
+	DBG(0, "%s: RMII gasket idle\n", __FUNCTION__);
+
+	/* configure the gasket for RMII, 50 MHz, no loopback, no echo */
+	fec_reg_write16(fep, FEC_MIIGSK_CFGR, FEC_MIIGSK_CFGR_IF_MODE_RMII);
+
+	/* re-enable the gasket */
+	fec_reg_write16(fep, FEC_MIIGSK_ENR, FEC_MIIGSK_ENR_EN);
+	fec_reg_read16(fep, FEC_MIIGSK_CFGR);
+	fec_reg_read16(fep, FEC_MIIGSK_ENR);
+
+#if 1
+	DBG(0, "%s: Waiting for RMII gasket ready\n", __FUNCTION__);
+	for (loops = 0; loops < max_loops; loops++) {
+		if (readw(fep->reg_base + FEC_MIIGSK_ENR) & FEC_MIIGSK_ENR_READY)
+			break;
+		udelay(1);
+	}
+	if (fec_reg_read16(fep, FEC_MIIGSK_ENR) & FEC_MIIGSK_ENR_READY) {
+		DBG(0, "%s: RMII gasket ready after %u loops\n", __FUNCTION__, loops);
+	} else {
+		DBG(0, "%s: RMII gasket NOT ready after %u loops\n", __FUNCTION__, loops);
+	}
+#endif
+}
+#else
+static inline void fec_localhw_setup(struct net_device *dev)
+{
+}
+#endif
+
+static int fec_set_mii(struct net_device *dev, struct fec_enet_private *fep)
+{
+	unsigned long rate;
+	struct clk *clk;
+
+	DBG(0, "%s: \n", __FUNCTION__);
+
+	fec_reg_write(fep, FEC_RCR, OPT_FRAME_SIZE | RCR_MII_MODE);
+	fec_reg_write(fep, FEC_TCR, 0x00);
+
+	/*
+	 * Set MII speed to 2.5 MHz
+	 */
+	clk = clk_get(fep->dma_dev, NULL);
+	if (!IS_ERR(clk)) {
+	rate = clk_get_rate(clk);
+	clk_put(clk);
+	} else {
+		printk(KERN_ERR "Failed to get fec clock: %ld\n", PTR_ERR(clk));
+		return PTR_ERR(clk);
+	}
+	fep->phy_speed = ((((rate + 4999999) / 2500000) / 2) & 0x3F) << 1;
+	fec_reg_write(fep, FEC_MSCR, fep->phy_speed);
+	DBG(0, "%s: clkdiv set to %u for MII clock %u at base clock %lu\n",
+	    __FUNCTION__, fep->phy_speed >> 1, 2500000, rate);
+	DBG(0, "%s: actual MII clock is: %lu\n", __FUNCTION__, rate / (fep->phy_speed));
+
+	return 0;
+}
+
+static const unsigned char default_mac[ETH_ALEN] = {
+	0x00, 0x04, 0x9f, 0x00, 0x74, 0x4a,
+};
+
+#define FEC_IIM_BASE    IO_ADDRESS(IIM_BASE_ADDR)
+static void fec_get_mac(struct net_device *dev)
+{
+#if 1
+	// keep bootloader assigned MAC address
+	struct fec_enet_private *fep = netdev_priv(dev);
+	unsigned long eth_addr = fec_reg_read(fep, FEC_PALR);
+	dev->dev_addr[0] = eth_addr >> 24;
+	dev->dev_addr[1] = eth_addr >> 16;
+	dev->dev_addr[2] = eth_addr >> 8;
+	dev->dev_addr[3] = eth_addr >> 0;
+	eth_addr = fec_reg_read(fep, FEC_PAUR);
+	dev->dev_addr[5] = eth_addr >> 16;
+	dev->dev_addr[4] = eth_addr >> 24;
+#else
+	int i;
+	unsigned long fec_mac_base = FEC_IIM_BASE + MXC_IIMKEY0;
+
+	if (cpu_is_mx27_rev(CHIP_REV_2_0) > 0) {
+		fec_mac_base = FEC_IIM_BASE + MXC_IIMMAC;
+	}
+
+	DBG(0, "%s: Reading MAC address from %08lx\n", __FUNCTION__, fec_mac_base);
+	for (i = 0; i < ETH_ALEN; i++) {
+		dev->dev_addr[ETH_ALEN - 1 - i] = __raw_readb(fec_mac_base + i * 4);
+	}
+	//memcpy(dev->dev_addr, default_mac, ETH_ALEN);
+#endif
+}
+
+#ifdef CONFIG_PHYLIB
+static inline void fec_enable_phy_intr(struct fec_enet_private *fep)
+{
+}
+static inline void fec_disable_phy_intr(struct fec_enet_private *fep)
+{
+}
+static inline void fec_phy_ack_intr(struct fec_enet_private *fep)
+{
+}
+#else
+static inline void fec_enable_phy_intr(struct fec_enet_private *fep)
+{
+	if (!fep->phy_int_enabled) {
+		fep->phy_int_enabled = 1;
+		enable_irq(fep->mii_irq);
+	}
+}
+
+static inline void fec_disable_phy_intr(struct fec_enet_private *fep)
+{
+	if (fep->phy_int_enabled) {
+		disable_irq(fep->mii_irq);
+		fep->phy_int_enabled = 0;
+	}
+}
+
+static inline void fec_phy_ack_intr(struct fec_enet_private *fep)
+{
+	if (fep->phy_int_enabled) {
+		disable_irq(fep->mii_irq);
+		fep->phy_int_enabled = 0;
+	}
+}
+#endif
+
+/* ------------------------------------------------------------------------- */
+
+#ifndef CONFIG_PHYLIB
+static void mii_display_status(struct net_device *dev)
+{
+	struct fec_enet_private *fep = netdev_priv(dev);
+
+	if (!fep->linkstatus && !fep->old_linkstatus) {
+		/* Link is still down - don't print anything */
+		return;
+	}
+
+	printk("%s: status: ", dev->name);
+
+	if (!fep->linkstatus) {
+		printk("link down");
+	} else {
+		printk("link up");
+
+		switch(fep->phy_status & PHY_STAT_SPMASK) {
+		case PHY_STAT_100FDX: printk(", 100MBit Full Duplex"); break;
+		case PHY_STAT_100HDX: printk(", 100MBit Half Duplex"); break;
+		case PHY_STAT_10FDX: printk(", 10MBit Full Duplex"); break;
+		case PHY_STAT_10HDX: printk(", 10MBit Half Duplex"); break;
+		default:
+			printk(", Unknown speed/duplex");
+		}
+
+		if (fep->phy_status & PHY_STAT_ANC)
+			printk(", auto-negotiation complete");
+	}
+
+	if (fep->phy_status & PHY_STAT_FAULT)
+		printk(", remote fault");
+
+	printk(".\n");
+}
+
+static void mii_display_config(struct work_struct *w)
+{
+	struct fec_enet_private *fep = container_of(w, struct fec_enet_private, phy_task);
+	uint status = fep->phy_status;
 
 	/*
 	** When we get here, phy_task is already removed from
 	** the workqueue.  It is thus safe to allow to reuse it.
 	*/
 	fep->mii_phy_task_queued = 0;
-	printk("%s: config: auto-negotiation ", dev->name);
+	//printk("%s: config: auto-negotiation ", dev->name);
 
 	if (status & PHY_CONF_ANE)
 		printk("on");
@@ -1351,11 +1878,21 @@ static void mii_display_config(struct wo
 
 	fep->sequence_done = 1;
 }
+#endif
 
-static void mii_relink(struct work_struct *work)
+#ifndef CONFIG_PHYLIB
+static inline void *priv_netdev(struct fec_enet_private  *fep)
 {
-	struct fec_enet_private *fep = container_of(work, struct fec_enet_private, phy_task);
-	struct net_device *dev = fep->netdev;
+	/* ugly hack, stolen from include linux/netdevice.h */
+	return (char *)fep - ((sizeof(struct net_device)
+			       + NETDEV_ALIGN_CONST)
+			      & ~NETDEV_ALIGN_CONST);
+}
+
+static void mii_relink(struct work_struct *w)
+{
+	struct fec_enet_private *fep = container_of(w, struct fec_enet_private, phy_task);
+	struct net_device *dev = priv_netdev(fep);
 	int duplex;
 
 	/*
@@ -1363,23 +1900,19 @@ static void mii_relink(struct work_struc
 	** the workqueue.  It is thus safe to allow to reuse it.
 	*/
 	fep->mii_phy_task_queued = 0;
-	fep->link = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0;
+	fep->linkstatus = (fep->phy_status & PHY_STAT_LINK) ? 1 : 0;
 	mii_display_status(dev);
-	fep->old_link = fep->link;
+	fep->old_linkstatus = fep->linkstatus;
 
-	if (fep->link) {
+	if (fep->linkstatus) {
 		duplex = 0;
-		if (fep->phy_status
-		    & (PHY_STAT_100FDX | PHY_STAT_10FDX))
+		if (fep->phy_status & (PHY_STAT_100FDX | PHY_STAT_10FDX)) {
 			duplex = 1;
+		}
 		fec_restart(dev, duplex);
-	} else
+	} else {
 		fec_stop(dev);
-
-#if 0
-	enable_irq(fep->mii_irq);
-#endif
-
+	}
 }
 
 /* mii_queue_relink is called in interrupt context from mii_link_interrupt */
@@ -1429,15 +1962,14 @@ phy_cmd_t const phy_cmd_config[] = {
 static void
 mii_discover_phy3(uint mii_reg, struct net_device *dev)
 {
-	struct fec_enet_private *fep;
+	struct fec_enet_private *fep = netdev_priv(dev);
 	int i;
 
-	fep = netdev_priv(dev);
 	fep->phy_id |= (mii_reg & 0xffff);
 	printk("fec: PHY @ 0x%x, ID 0x%08x", fep->phy_addr, fep->phy_id);
 
-	for(i = 0; phy_info[i]; i++) {
-		if(phy_info[i]->id == (fep->phy_id >> 4))
+	for (i = 0; phy_info[i]; i++) {
+		if (phy_info[i]->id == (fep->phy_id >> 4))
 			break;
 	}
 
@@ -1456,13 +1988,9 @@ mii_discover_phy3(uint mii_reg, struct n
 static void
 mii_discover_phy(uint mii_reg, struct net_device *dev)
 {
-	struct fec_enet_private *fep;
-	volatile fec_t *fecp;
+	struct fec_enet_private *fep = netdev_priv(dev);
 	uint phytype;
 
-	fep = netdev_priv(dev);
-	fecp = fep->hwp;
-
 	if (fep->phy_addr < 32) {
 		if ((phytype = (mii_reg & 0xffff)) != 0xffff && phytype != 0) {
 
@@ -1470,39 +1998,40 @@ mii_discover_phy(uint mii_reg, struct ne
 			*/
 			fep->phy_id = phytype << 16;
 			mii_queue(dev, mk_mii_read(MII_REG_PHYIR2),
-							mii_discover_phy3);
+				  mii_discover_phy3);
 		} else {
 			fep->phy_addr++;
 			mii_queue(dev, mk_mii_read(MII_REG_PHYIR1),
-							mii_discover_phy);
+				  mii_discover_phy);
 		}
 	} else {
 		printk("FEC: No PHY device found.\n");
 		/* Disable external MII interface */
-		fecp->fec_mii_speed = fep->phy_speed = 0;
-#ifdef HAVE_mii_link_interrupt
-		fec_disable_phy_intr();
-#endif
+		fec_disable_phy_intr(fep);
+		fec_reg_write(fep, FEC_MSCR, 0);
 	}
 }
+#endif
 
-/* This interrupt occurs when the PHY detects a link change.
-*/
-#ifdef HAVE_mii_link_interrupt
+#ifndef CONFIG_PHYLIB
 static irqreturn_t
-mii_link_interrupt(int irq, void * dev_id)
+mii_link_interrupt(int irq, void *dev_id)
 {
-	struct	net_device *dev = dev_id;
+	struct net_device *dev = dev_id;
 	struct fec_enet_private *fep = netdev_priv(dev);
 
-	fec_phy_ack_intr();
+	DBG(0, "%s: \n", __FUNCTION__);
 
-#if 0
-	disable_irq(fep->mii_irq);  /* disable now, enable later */
-#endif
+	fec_phy_ack_intr(fep);
 
-	mii_do_cmd(dev, fep->phy->ack_int);
-	mii_do_cmd(dev, phy_cmd_relink);  /* restart and display status */
+	/*
+	 * Some board will trigger phy interrupt before phy enable.
+	 * And at that moment , fep->phy is not initialized.
+	 */
+	if (fep->phy) {
+		mii_do_cmd(dev, fep->phy->ack_int);
+		mii_do_cmd(dev, phy_cmd_relink);  /* restart and display status */
+	}
 
 	return IRQ_HANDLED;
 }
@@ -1511,16 +2040,31 @@ mii_link_interrupt(int irq, void * dev_i
 static int
 fec_enet_open(struct net_device *dev)
 {
+	int ret = 0;
 	struct fec_enet_private *fep = netdev_priv(dev);
 
 	/* I should reset the ring buffers here, but I don't yet know
 	 * a simple way to do that.
 	 */
-	fec_set_mac_address(dev);
+	DBG(0, "%s: \n", __FUNCTION__);
+	_fec_set_mac_address(dev);
 
-	fep->sequence_done = 0;
-	fep->link = 0;
+#ifdef CONFIG_PHYLIB
+	fec_restart(dev, 0);
 
+	ret = fec_connect_phy(dev, fep);
+	if (ret != 0) {
+		DBG(0, "%s: Failed to connect to PHY: %d\n", __FUNCTION__, ret);
+		return ret;
+	}
+	phy_start(fep->phy);
+
+	fep->linkstatus = fep->phy->link;
+	//fec_restart(dev, 0);
+	DBG(0, "%s: Link status is: %d\n", __FUNCTION__, fep->linkstatus);
+#else
+	fep->linkstatus = 0;
+	fep->sequence_done = 0;
 	if (fep->phy) {
 		mii_do_cmd(dev, fep->phy->ack_int);
 		mii_do_cmd(dev, fep->phy->config);
@@ -1542,16 +2086,20 @@ fec_enet_open(struct net_device *dev)
 		 * based on this device does not implement a PHY interrupt,
 		 * so we are never notified of link change.
 		 */
-		fep->link = 1;
+		fep->linkstatus = 1;
 	} else {
-		fep->link = 1; /* lets just try it and see */
+		fep->linkstatus = 1; /* lets just try it and see */
 		/* no phy,  go full duplex,  it's most likely a hub chip */
 		fec_restart(dev, 1);
 	}
-
-	netif_start_queue(dev);
+	fep->old_linkstatus = fep->linkstatus;
+#endif
 	fep->opened = 1;
-	return 0;		/* Success */
+#if 1
+	/* enable receiver */
+	fec_reg_write(fep, FEC_RDAR, DONT_CARE);
+#endif
+	return ret;
 }
 
 static int
@@ -1559,15 +2107,46 @@ fec_enet_close(struct net_device *dev)
 {
 	struct fec_enet_private *fep = netdev_priv(dev);
 
-	/* Don't know what to do yet.
-	*/
+	DBG(0, "%s: \n", __FUNCTION__);
+
 	fep->opened = 0;
-	netif_stop_queue(dev);
-	fec_stop(dev);
+	if (fep->linkstatus) {
+		fec_stop(dev);
+	}
+#ifdef CONFIG_PHYLIB
+	if (fep->phy) {
+		DBG(0, "%s: Stopping PHY %p\n", __FUNCTION__, fep->phy);
+		phy_stop(fep->phy);
 
+		DBG(0, "%s: Disconnecting PHY %p\n", __FUNCTION__, fep->phy);
+		phy_disconnect(fep->phy);
+		fep->phy = NULL;
+	}
+#endif
+#if 1
+	/* Whack a reset.  We should wait for this.
+	*/
+	fec_reg_write(fep, FEC_ECR, FEC_ECR_RESET);
+	udelay(10);
+
+	/* Mask and clear outstanding MII command interrupts.
+	*/
+	fec_reg_write(fep, FEC_EIMR, 0);
+	fec_reg_write(fep, FEC_EIR, FEC_ENET_MII);
+	fec_disable_phy_intr(fep);
+	/* Switch off MII */
+	fec_reg_write(fep, FEC_MSCR, 0);
+#endif
 	return 0;
 }
 
+static struct net_device_stats *fec_enet_get_stats(struct net_device *dev)
+{
+	struct fec_enet_private *fep = netdev_priv(dev);
+
+	return &fep->stats;
+}
+
 /* Set or clear the multicast filter for this adaptor.
  * Skeleton taken from sunlance driver.
  * The CPM Ethernet implementation allows Multicast as well as individual
@@ -1583,37 +2162,32 @@ fec_enet_close(struct net_device *dev)
 
 static void set_multicast_list(struct net_device *dev)
 {
-	struct fec_enet_private *fep;
-	volatile fec_t *ep;
+	struct fec_enet_private *fep = netdev_priv(dev);
 	struct dev_mc_list *dmi;
 	unsigned int i, j, bit, data, crc;
 	unsigned char hash;
 
-	fep = netdev_priv(dev);
-	ep = fep->hwp;
-
-	if (dev->flags&IFF_PROMISC) {
-		ep->fec_r_cntrl |= 0x0008;
+	if (dev->flags & IFF_PROMISC) {
+		fec_reg_write(fep, FEC_RCR, fec_reg_read(fep, FEC_RCR) | RCR_PROM);
 	} else {
 
-		ep->fec_r_cntrl &= ~0x0008;
+		fec_reg_write(fep, FEC_RCR, fec_reg_read(fep, FEC_RCR) & ~RCR_PROM);
 
 		if (dev->flags & IFF_ALLMULTI) {
 			/* Catch all multicast addresses, so set the
 			 * filter to all 1's.
 			 */
-			ep->fec_grp_hash_table_high = 0xffffffff;
-			ep->fec_grp_hash_table_low = 0xffffffff;
+			fec_reg_write(fep, FEC_IAUR, ~0);
+			fec_reg_write(fep, FEC_IALR, ~0);
 		} else {
 			/* Clear filter and add the addresses in hash register.
 			*/
-			ep->fec_grp_hash_table_high = 0;
-			ep->fec_grp_hash_table_low = 0;
+			fec_reg_write(fep, FEC_IAUR, 0);
+			fec_reg_write(fep, FEC_IALR, 0);
 
 			dmi = dev->mc_list;
 
-			for (j = 0; j < dev->mc_count; j++, dmi = dmi->next)
-			{
+			for (j = 0; j < dev->mc_count; j++, dmi = dmi->next) {
 				/* Only support group multicast for now.
 				*/
 				if (!(dmi->dmi_addr[0] & 1))
@@ -1621,13 +2195,11 @@ static void set_multicast_list(struct ne
 
 				/* calculate crc32 value of mac address
 				*/
-				crc = 0xffffffff;
+				crc = ~0;
 
-				for (i = 0; i < dmi->dmi_addrlen; i++)
-				{
+				for (i = 0; i < dmi->dmi_addrlen; i++) {
 					data = dmi->dmi_addr[i];
-					for (bit = 0; bit < 8; bit++, data >>= 1)
-					{
+					for (bit = 0; bit < 8; bit++, data >>= 1) {
 						crc = (crc >> 1) ^
 						(((crc ^ data) & 1) ? CRC32_POLY : 0);
 					}
@@ -1639,9 +2211,13 @@ static void set_multicast_list(struct ne
 				hash = (crc >> (32 - HASH_BITS)) & 0x3f;
 
 				if (hash > 31)
-					ep->fec_grp_hash_table_high |= 1 << (hash - 32);
+					fec_reg_write(fep, FEC_IAUR,
+						      fec_reg_read(fep, FEC_IAUR) |
+						      (1 << (hash - 32)));
 				else
-					ep->fec_grp_hash_table_low |= 1 << hash;
+					fec_reg_write(fep, FEC_IALR,
+						      fec_reg_read(fep, FEC_IALR) |
+						      (1 << hash));
 			}
 		}
 	}
@@ -1650,106 +2226,272 @@ static void set_multicast_list(struct ne
 /* Set a MAC change in hardware.
  */
 static void
-fec_set_mac_address(struct net_device *dev)
+_fec_set_mac_address(struct net_device *dev)
 {
-	volatile fec_t *fecp;
-
-	fecp = ((struct fec_enet_private *)netdev_priv(dev))->hwp;
+	struct fec_enet_private *fep = netdev_priv(dev);
 
 	/* Set station address. */
-	fecp->fec_addr_low = dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
-		(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24);
-	fecp->fec_addr_high = (dev->dev_addr[5] << 16) |
-		(dev->dev_addr[4] << 24);
+	fec_reg_write(fep, FEC_PALR, dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
+		(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24));
+	fec_reg_write(fep, FEC_PAUR, (dev->dev_addr[5] << 16) |
+		(dev->dev_addr[4] << 24));
+}
 
+static int
+fec_set_mac_address(struct net_device *dev, void *_addr)
+{
+	struct sockaddr *addr = _addr;
+
+	if (!is_valid_ether_addr((const char *)&addr->sa_data)) {
+		printk(KERN_WARNING "Bad ethernet address: %02x:%02x:%02x:%02x:%02x:%02x\n",
+		       addr->sa_data[0], addr->sa_data[1], addr->sa_data[2], addr->sa_data[3],
+		       addr->sa_data[4], addr->sa_data[5]);
+		return -EINVAL;
+	}
+	printk(KERN_DEBUG "Setting MAC address to %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       addr->sa_data[0], addr->sa_data[1], addr->sa_data[2], addr->sa_data[3],
+	       addr->sa_data[4], addr->sa_data[5]);
+
+	memcpy(&dev->dev_addr, &addr->sa_data, ETH_ALEN);
+
+	_fec_set_mac_address(dev);
+
+	return 0;
 }
 
- /*
-  * XXX:  We need to clean up on failure exits here.
-  *
-  * index is only used in legacy code
-  */
-int __init fec_enet_init(struct net_device *dev, int index)
+static void fec_enet_free_buffers(struct fec_enet_private *fep)
+{
+	cbd_t *bdp = fep->rx_bd_base;
+	int i;
+
+	DBG(0, "%s: Freeing TX bounce buffers %p\n", __FUNCTION__, fep->tx_bounce[0]);
+	kfree(fep->tx_bounce[0]);
+	memset(fep->tx_bounce, 0, TX_RING_SIZE * sizeof(void*));
+	for (i = 0; i < RX_RING_SIZE; i++, bdp++) {
+		if (fep->rx_skbuff[i] != NULL) {
+			DBG(0, "%s: Freeing RX skb %p\n", __FUNCTION__, fep->rx_skbuff[i]);
+			fec_enet_rxbuf_unmap(fep, bdp, FEC_ENET_RX_FRSIZE);
+			kfree_skb(fep->rx_skbuff[i]);
+			fep->rx_skbuff[i] = NULL;
+		}
+	}
+}
+
+#ifdef CONFIG_PHYLIB
+/* called by the generic PHY layer in interrupt context */
+static int phy_regs[32] = { [0 ... ARRAY_SIZE(phy_regs) - 1] = -1};
+static int fec_mii_read(struct mii_bus *bus, int phy_id, int regnum)
 {
+	int ret;
+	struct net_device *dev = bus->priv;
 	struct fec_enet_private *fep = netdev_priv(dev);
-	unsigned long	mem_addr;
-	volatile cbd_t	*bdp;
-	cbd_t		*cbd_base;
-	volatile fec_t	*fecp;
-	int 		i, j;
+	unsigned long regval = mk_mii_read(regnum) | phy_id << 23;
+	unsigned long flags;
+	int loops = 0;
 
-	/* Allocate memory for buffer descriptors.
-	*/
-	mem_addr = (unsigned long)dma_alloc_coherent(NULL, PAGE_SIZE,
-			&fep->bd_dma, GFP_KERNEL);
-	if (mem_addr == 0) {
-		printk("FEC: allocate descriptor memory failed?\n");
+	DBG(1, "%s: \n", __FUNCTION__);
+#if 0
+	DBG(0, "%s: ECR:  %08lx\n", __FUNCTION__, fec_reg_read(fep, FEC_ECR));
+	DBG(0, "%s: EIR:  %08lx\n", __FUNCTION__, fec_reg_read(fep, FEC_EIR));
+	DBG(0, "%s: EIMR: %08lx\n", __FUNCTION__, fec_reg_read(fep, FEC_EIMR));
+	DBG(0, "%s: RCR:  %08lx\n", __FUNCTION__, fec_reg_read(fep, FEC_RCR));
+	DBG(0, "%s: TCR:  %08lx\n", __FUNCTION__, fec_reg_read(fep, FEC_TCR));
+#endif
+	spin_lock_irqsave(&fep->lock, flags);
+	fep->mii_complete = 0;
+	fec_reg_write(fep, FEC_MMFR, regval);
+	spin_unlock_irqrestore(&fep->lock, flags);
+
+	while (!fep->mii_complete) {
+		if (loops++ == 1000) {
+			DBG(1, "%s: Waiting for MII completion\n", __FUNCTION__);
+		}
+		cpu_relax();
+	}
+	if (loops >= 1000) {
+		DBG(1, "%s: MII transaction completed\n", __FUNCTION__);
+	}
+	ret = fec_reg_read(fep, FEC_MMFR);
+	if (ret < 0) {
+		DBG(0, "%s: Failed to read PHY[%02x] reg %02x: %d\n", __FUNCTION__,
+		    phy_id, regnum, ret);
+		return ret;
+	}
+	ret &= 0xffff;
+	if (phy_regs[regnum] != ret) {
+		DBG(1, "%s: Read %04x from PHY[%02x] reg %02x\n", __FUNCTION__,
+		    ret, phy_id, regnum);
+		phy_regs[regnum] = ret;
+	}
+	return ret;
+}
+
+static int fec_mii_write(struct mii_bus *bus, int phy_id, int regnum, u16 val)
+{
+	struct net_device *dev = bus->priv;
+	struct fec_enet_private *fep = netdev_priv(dev);
+	unsigned long regval = mk_mii_write(regnum, val) | phy_id << 23;
+	unsigned long flags;
+
+	DBG(0, "%s: \n", __FUNCTION__);
+
+	spin_lock_irqsave(&fep->lock, flags);
+	fep->mii_complete = 0;
+	fec_reg_write(fep, FEC_MMFR, regval);
+	spin_unlock_irqrestore(&fep->lock, flags);
+
+	while (!fep->mii_complete) {
+		cpu_relax();
+	}
+	DBG(1, "%s: Wrote %04x to PHY[%02x] reg %02x\n", __FUNCTION__, val, phy_id, regnum);
+	return 0;
+}
+
+static int fec_mii_reset(struct mii_bus *bus)
+{
+	DBG(0, "%s: \n", __FUNCTION__);
+	memset(phy_regs, -1, sizeof(phy_regs));
+	return 0;
+}
+
+static int fec_init_phy(struct net_device *dev, struct fec_enet_private *fep)
+{
+	int ret;
+	int i;
+	struct mii_bus *mii;
+
+	mii = mdiobus_alloc();
+	if (mii == NULL) {
 		return -ENOMEM;
 	}
+	mii->name = "fec mii";
+	mii->read = fec_mii_read;
+	mii->write = fec_mii_write;
+	mii->reset = fec_mii_reset;
+	mii->priv = dev;
+	snprintf(mii->id, MII_BUS_ID_SIZE, "%x", 0);
+	mii->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+	for (i = 0; i < PHY_MAX_ADDR; i++) {
+		mii->irq[i] = fep->mii_irq >= 0 ? fep->mii_irq : PHY_POLL;
+	}
+
+	ret = mdiobus_register(mii);
+	if (ret != 0) {
+		DBG(0, "%s: Failed to register MII bus: %d\n", __FUNCTION__, ret);
+		kfree(mii->irq);
+		mdiobus_free(mii);
+		return ret;
+	}
+	fep->phy_addr = -1;
+	DBG(0, "%s: MII bus registered\n", __FUNCTION__);
+	for (i = 0; i < PHY_MAX_ADDR; i++) {
+		if (mii->phy_map[i] != NULL) {
+			fep->phy_addr = i;
+			break;
+		}
+	}
+	if (fep->phy_addr == -1) {
+		DBG(0, "%s: No PHY found\n", __FUNCTION__);
+		return -ENODEV;
+	}
+	DBG(0, "%s: Using PHY at addr %02x\n", __FUNCTION__, fep->phy_addr);
+	fep->mii = mii;
 
-	spin_lock_init(&fep->hw_lock);
-	spin_lock_init(&fep->mii_lock);
+	return 0;
+}
 
-	/* Create an Ethernet device instance.
-	*/
-	fecp = (volatile fec_t *)dev->base_addr;
+static int fec_connect_phy(struct net_device *dev, struct fec_enet_private *fep)
+{
+	struct mii_bus *mii = fep->mii;
 
-	fep->index = index;
-	fep->hwp = fecp;
-	fep->netdev = dev;
+	DBG(0, "%s: Connecting PHY at addr %02x\n", __FUNCTION__,
+	    fep->phy_addr);
 
-	/* Whack a reset.  We should wait for this.
-	*/
-	fecp->fec_ecntrl = 1;
-	udelay(10);
+	fep->phy = phy_connect(dev, dev_name(&mii->phy_map[fep->phy_addr]->dev),
+			       fec_link_change, 0, mii->phy_map[fep->phy_addr]->interface);
+	if (IS_ERR(fep->phy)) {
+		int ret = PTR_ERR(fep->phy);
+		printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+		fep->phy = NULL;
+		return ret;
+	}
+	DBG(0, "%s: Registered PHY %s[%02x] IRQ %d with %s\n", __FUNCTION__,
+	    dev_name(&fep->phy->dev), fep->phy_addr, fep->phy->irq, dev->name);
 
-	/* Set the Ethernet address */
-#ifdef CONFIG_M5272
-	fec_get_mac(dev);
+	return 0;
+}
 #else
-	{
-		unsigned long l;
-		l = fecp->fec_addr_low;
-		dev->dev_addr[0] = (unsigned char)((l & 0xFF000000) >> 24);
-		dev->dev_addr[1] = (unsigned char)((l & 0x00FF0000) >> 16);
-		dev->dev_addr[2] = (unsigned char)((l & 0x0000FF00) >> 8);
-		dev->dev_addr[3] = (unsigned char)((l & 0x000000FF) >> 0);
-		l = fecp->fec_addr_high;
-		dev->dev_addr[4] = (unsigned char)((l & 0xFF000000) >> 24);
-		dev->dev_addr[5] = (unsigned char)((l & 0x00FF0000) >> 16);
-	}
+static int fec_init_phy(struct net_device *dev, struct fec_enet_private *fep)
+{
+	/* Queue up command to detect the PHY and initialize the
+	 * remainder of the interface.
+	 */
+	fep->phy_id_done = 0;
+	fep->phy_addr = 0;
+	mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy);
+
+	return 0;
+}
 #endif
 
-	cbd_base = (cbd_t *)mem_addr;
+/* Initialize the FEC Ethernet on 860T (or ColdFire 5272).
+ */
+ /*
+  * XXX:  We need to clean up on failure exits here.
+  */
+
+int __devinit fec_enet_init(struct platform_device *pdev, struct net_device *dev)
+{
+	int ret;
+	struct fec_enet_private *fep = netdev_priv(dev);
+	cbd_t *bdp;
+	struct sk_buff *pskb;
+	int i;
+	void *mem;
 
-	/* Set receive and transmit descriptor base.
+	spin_lock_init(&fep->lock);
+
+	/* Whack a reset.  We should wait for this.
 	*/
-	fep->rx_bd_base = cbd_base;
-	fep->tx_bd_base = cbd_base + RX_RING_SIZE;
+	fec_reg_write(fep, FEC_ECR, FEC_ECR_RESET);
+	udelay(10);
+
+	/* Set the Ethernet address.  If using multiple Enets on the 8xx,
+	 * this needs some work to get unique addresses.
+	 *
+	 * This is our default MAC address unless the user changes
+	 * it via eth_mac_addr (our dev->set_mac_addr handler).
+	 */
+	fec_get_mac(dev);
 
 	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
 	fep->cur_rx = fep->rx_bd_base;
 
 	fep->skb_cur = fep->skb_dirty = 0;
 
-	/* Initialize the receive buffer descriptors.
+	/* allocate memory for TX bounce buffers */
+	mem = kzalloc(TX_RING_SIZE * FEC_ENET_TX_FRSIZE, GFP_KERNEL);
+	if (mem == NULL) {
+		return -ENOMEM;
+	}
+
+	fec_enet_cbd_get(fep);
+
+	/* Initialize the transmit buffer descriptors.
 	*/
-	bdp = fep->rx_bd_base;
-	for (i=0; i<FEC_ENET_RX_PAGES; i++) {
+	bdp = fep->tx_bd_base;
 
-		/* Allocate a page.
-		*/
-		mem_addr = __get_free_page(GFP_KERNEL);
-		/* XXX: missing check for allocation failure */
+	DBG(0, "%s: Allocated %d byte of TX buffer memory @ %p\n", __FUNCTION__,
+	    TX_RING_SIZE * FEC_ENET_TX_FRSIZE, mem);
+	for (i = 0; i < TX_RING_SIZE; i++) {
+		fep->tx_bounce[i] = mem;
+		DBG(0, "%s: TX bounce buffer[%d]=%p\n", __FUNCTION__, i, fep->tx_bounce[i]);
+		mem = (void *)((unsigned long)(mem + FEC_ENET_TX_FRSIZE));
 
 		/* Initialize the BD for every fragment in the page.
 		*/
-		for (j=0; j<FEC_ENET_RX_FRPPG; j++) {
-			bdp->cbd_sc = BD_ENET_RX_EMPTY;
-			bdp->cbd_bufaddr = __pa(mem_addr);
-			mem_addr += FEC_ENET_RX_FRSIZE;
-			bdp++;
-		}
+		bdp->cbd_bufaddr = ~0;
+		bdp++;
 	}
 
 	/* Set the last buffer to wrap.
@@ -1757,87 +2499,88 @@ int __init fec_enet_init(struct net_devi
 	bdp--;
 	bdp->cbd_sc |= BD_SC_WRAP;
 
-	/* ...and the same for transmmit.
+	/* ...and the same for receive.
 	*/
-	bdp = fep->tx_bd_base;
-	for (i=0, j=FEC_ENET_TX_FRPPG; i<TX_RING_SIZE; i++) {
-		if (j >= FEC_ENET_TX_FRPPG) {
-			mem_addr = __get_free_page(GFP_KERNEL);
-			j = 1;
-		} else {
-			mem_addr += FEC_ENET_TX_FRSIZE;
-			j++;
+	bdp = fep->rx_bd_base;
+	for (i = 0; i < RX_RING_SIZE; i++, bdp++) {
+		pskb = __dev_alloc_skb(FEC_ENET_RX_FRSIZE, GFP_KERNEL);
+		if (pskb == NULL) {
+			DBG(0, "%s: Failed to allocate RX skb; cleaning up\n", __FUNCTION__);
+			ret = -ENOMEM;
+			goto cleanup;
 		}
-		fep->tx_bounce[i] = (unsigned char *) mem_addr;
-
-		/* Initialize the BD for every fragment in the page.
-		*/
-		bdp->cbd_sc = 0;
-		bdp->cbd_bufaddr = 0;
-		bdp++;
+		DBG(0, "%s: RX skb allocated @ %p\n", __FUNCTION__, pskb);
+		fep->rx_skbuff[i] = pskb;
+		pskb->data = FEC_ADDR_ALIGNMENT(pskb->data);
+		bdp->cbd_sc = BD_ENET_RX_EMPTY;
+		bdp->cbd_bufaddr = ~0;
+		fec_enet_rxbuf_map(fep, bdp, pskb->data, FEC_ENET_RX_FRSIZE);
 	}
-
 	/* Set the last buffer to wrap.
 	*/
 	bdp--;
 	bdp->cbd_sc |= BD_SC_WRAP;
+	fec_enet_cbd_put(fep);
 
 	/* Set receive and transmit descriptor base.
 	*/
-	fecp->fec_r_des_start = fep->bd_dma;
-	fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t)
-				* RX_RING_SIZE;
-
-#ifdef HAVE_mii_link_interrupt
-	fec_request_mii_intr(dev);
-#endif
-
-	fecp->fec_grp_hash_table_high = 0;
-	fecp->fec_grp_hash_table_low = 0;
-	fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
-	fecp->fec_ecntrl = 2;
-	fecp->fec_r_des_active = 0;
-#ifndef CONFIG_M5272
-	fecp->fec_hash_table_high = 0;
-	fecp->fec_hash_table_low = 0;
-#endif
+	fec_reg_write(fep, FEC_ERDSR, fep->cbd_phys_base);
+	fec_reg_write(fep, FEC_ETDSR, fep->cbd_phys_base + RX_RING_SIZE * sizeof(cbd_t));
 
+	/* Install our interrupt handlers. This varies depending on
+	 * the architecture.
+	*/
+	ret = fec_request_intrs(pdev, dev);
+	if (ret != 0) {
+		goto cleanup;
+	}
+	/* Clear and enable interrupts */
+	fec_reg_write(fep, FEC_EIR, fec_reg_read(fep, FEC_EIR));
+	fec_reg_write(fep, FEC_EIMR, FEC_ENET_TXF | FEC_ENET_TXB |
+		      FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
+
+	fec_reg_write(fep, FEC_IAUR, 0);
+	fec_reg_write(fep, FEC_IALR, 0);
+	fec_reg_write(fep, FEC_EMRBR, PKT_MAXBLR_SIZE);
+	fec_reg_write(fep, FEC_ECR, FEC_ECR_ETHER_EN);
+	fec_localhw_setup(dev);
+#if 0
+	/* do this in enet_open()! */
+	fec_reg_write(fep, FEC_RDAR, DONT_CARE);
+#endif
 	/* The FEC Ethernet specific entries in the device structure. */
 	dev->open = fec_enet_open;
 	dev->hard_start_xmit = fec_enet_start_xmit;
 	dev->tx_timeout = fec_timeout;
 	dev->watchdog_timeo = TX_TIMEOUT;
 	dev->stop = fec_enet_close;
+	dev->get_stats = fec_enet_get_stats;
 	dev->set_multicast_list = set_multicast_list;
+	dev->set_mac_address = fec_set_mac_address;
 
-	for (i=0; i<NMII-1; i++)
-		mii_cmds[i].mii_next = &mii_cmds[i+1];
+#ifndef CONFIG_PHYLIB
+	for (i = 1; i < NMII; i++) {
+		mii_cmds[i - 1].mii_next = &mii_cmds[i];
+	}
 	mii_free = mii_cmds;
-
+#endif
 	/* setup MII interface */
-	fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;
-	fecp->fec_x_cntrl = 0x00;
-
-	/*
-	 * Set MII speed to 2.5 MHz
-	 */
-	fep->phy_speed = ((((clk_get_rate(fep->clk) / 2 + 4999999)
-					/ 2500000) / 2) & 0x3F) << 1;
-	fecp->fec_mii_speed = fep->phy_speed;
-	fec_restart(dev, 0);
-
-	/* Clear and enable interrupts */
-	fecp->fec_ievent = 0xffc00000;
-	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII);
-
-	/* Queue up command to detect the PHY and initialize the
-	 * remainder of the interface.
-	 */
-	fep->phy_id_done = 0;
-	fep->phy_addr = 0;
-	mii_queue(dev, mk_mii_read(MII_REG_PHYIR1), mii_discover_phy);
+	ret = fec_set_mii(dev, fep);
+	if (ret) {
+		DBG(0, "%s: Failed to initialize MII interface: %d\n", __FUNCTION__, ret);
+		goto cleanup;
+	}
 
+	ret = fec_init_phy(dev, fep);
+	if (ret) {
+		DBG(0, "%s: Failed to initialize PHY: %d\n", __FUNCTION__, ret);
+		goto cleanup;
+	}
 	return 0;
+ cleanup:
+	fec_enet_free_buffers(fep);
+	fec_enet_cbd_put(fep);
+	return ret;
 }
 
 /* This function is called to start or restart the FEC during a link
@@ -1847,60 +2590,67 @@ int __init fec_enet_init(struct net_devi
 static void
 fec_restart(struct net_device *dev, int duplex)
 {
-	struct fec_enet_private *fep;
-	volatile cbd_t *bdp;
-	volatile fec_t *fecp;
+	struct fec_enet_private *fep = netdev_priv(dev);
+	cbd_t *bdp;
 	int i;
+	u32 rcr = OPT_FRAME_SIZE | RCR_MII_MODE;	/* MII enable */
+	u32 tcr = TCR_HBC;
 
-	fep = netdev_priv(dev);
-	fecp = fep->hwp;
-
+	DBG(0, "%s: Restarting FEC in %s-duplex mode\n", __FUNCTION__,
+	    duplex ? "full" : "half");
 	/* Whack a reset.  We should wait for this.
-	*/
-	fecp->fec_ecntrl = 1;
+	 */
+	fec_reg_write(fep, FEC_ECR, FEC_ECR_RESET);
 	udelay(10);
 
+	/* Enable interrupts we wish to service.
+	 */
+	fec_reg_write(fep, FEC_EIMR, FEC_ENET_TXF | FEC_ENET_TXB |
+		      FEC_ENET_RXF | FEC_ENET_RXB | FEC_ENET_MII);
+
 	/* Clear any outstanding interrupt.
-	*/
-	fecp->fec_ievent = 0xffc00000;
+	 *
+	 */
+	fec_reg_write(fep, FEC_EIR, FEC_ENET_MASK);
+
+	fec_enable_phy_intr(fep);
 
 	/* Set station address.
-	*/
-	fec_set_mac_address(dev);
+	 */
+	_fec_set_mac_address(dev);
 
 	/* Reset all multicast.
-	*/
-	fecp->fec_grp_hash_table_high = 0;
-	fecp->fec_grp_hash_table_low = 0;
+	 */
+	fec_reg_write(fep, FEC_IAUR, 0);
+	fec_reg_write(fep, FEC_IALR, 0);
 
 	/* Set maximum receive buffer size.
-	*/
-	fecp->fec_r_buff_size = PKT_MAXBLR_SIZE;
+	 */
+	fec_reg_write(fep, FEC_EMRBR, PKT_MAXBLR_SIZE);
 
 	/* Set receive and transmit descriptor base.
-	*/
-	fecp->fec_r_des_start = fep->bd_dma;
-	fecp->fec_x_des_start = (unsigned long)fep->bd_dma + sizeof(cbd_t)
-				* RX_RING_SIZE;
+	 */
+	fec_reg_write(fep, FEC_ERDSR, fep->cbd_phys_base);
+	fec_reg_write(fep, FEC_ETDSR, fep->cbd_phys_base + RX_RING_SIZE * sizeof(cbd_t));
 
 	fep->dirty_tx = fep->cur_tx = fep->tx_bd_base;
 	fep->cur_rx = fep->rx_bd_base;
 
 	/* Reset SKB transmit buffers.
-	*/
+	 */
 	fep->skb_cur = fep->skb_dirty = 0;
-	for (i=0; i<=TX_RING_MOD_MASK; i++) {
+	bdp = fep->tx_bd_base;
+	for (i = 0; i <= TX_RING_MOD_MASK; i++) {
 		if (fep->tx_skbuff[i] != NULL) {
-			dev_kfree_skb_any(fep->tx_skbuff[i]);
-			fep->tx_skbuff[i] = NULL;
+			fec_free_skb(fep, bdp, &fep->tx_skbuff[i]);
+			bdp++;
 		}
 	}
 
 	/* Initialize the receive buffer descriptors.
-	*/
+	 */
 	bdp = fep->rx_bd_base;
-	for (i=0; i<RX_RING_SIZE; i++) {
-
+	for (i = 0; i < RX_RING_SIZE; i++) {
 		/* Initialize the BD for every fragment in the page.
 		*/
 		bdp->cbd_sc = BD_ENET_RX_EMPTY;
@@ -1908,246 +2658,365 @@ fec_restart(struct net_device *dev, int 
 	}
 
 	/* Set the last buffer to wrap.
-	*/
+	 */
 	bdp--;
 	bdp->cbd_sc |= BD_SC_WRAP;
 
 	/* ...and the same for transmmit.
-	*/
+	 */
 	bdp = fep->tx_bd_base;
-	for (i=0; i<TX_RING_SIZE; i++) {
-
+	for (i = 0; i < TX_RING_SIZE; i++) {
 		/* Initialize the BD for every fragment in the page.
 		*/
 		bdp->cbd_sc = 0;
-		bdp->cbd_bufaddr = 0;
+		bdp->cbd_bufaddr = ~0;
 		bdp++;
 	}
 
 	/* Set the last buffer to wrap.
-	*/
+	 */
 	bdp--;
 	bdp->cbd_sc |= BD_SC_WRAP;
 
 	/* Enable MII mode.
-	*/
+	 */
 	if (duplex) {
-		fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x04;/* MII enable */
-		fecp->fec_x_cntrl = 0x04;		  /* FD enable */
+		tcr |= TCR_FDEN;	/* FD enable */
 	} else {
-		/* MII enable|No Rcv on Xmit */
-		fecp->fec_r_cntrl = OPT_FRAME_SIZE | 0x06;
-		fecp->fec_x_cntrl = 0x00;
+		rcr |= RCR_DRT;		/* No Rcv on Xmit */
 	}
+	fec_reg_write(fep, FEC_RCR, rcr);
+	fec_reg_write(fep, FEC_TCR, tcr);
 	fep->full_duplex = duplex;
 
 	/* Set MII speed.
-	*/
-	fecp->fec_mii_speed = fep->phy_speed;
+	 */
+	fec_reg_write(fep, FEC_MSCR, fep->phy_speed);
 
 	/* And last, enable the transmit and receive processing.
-	*/
-	fecp->fec_ecntrl = 2;
-	fecp->fec_r_des_active = 0;
+	 */
+	fec_reg_write(fep, FEC_ECR, FEC_ECR_ETHER_EN);
+	fec_localhw_setup(dev);
+	fec_reg_write(fep, FEC_RDAR, DONT_CARE);
 
-	/* Enable interrupts we wish to service.
-	*/
-	fecp->fec_imask = (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII);
+	DBG(0, "%s: Starting netif queue\n", __FUNCTION__);
+	netif_start_queue(dev);
 }
 
 static void
 fec_stop(struct net_device *dev)
 {
-	volatile fec_t *fecp;
-	struct fec_enet_private *fep;
+	struct fec_enet_private *fep = netdev_priv(dev);
 
-	fep = netdev_priv(dev);
-	fecp = fep->hwp;
+	DBG(0, "%s: Stopping netif queue\n", __FUNCTION__);
+	netif_stop_queue(dev);
 
 	/*
-	** We cannot expect a graceful transmit stop without link !!!
-	*/
-	if (fep->link)
-		{
-		fecp->fec_x_cntrl = 0x01;	/* Graceful transmit stop */
+	 * We cannot expect a graceful transmit stop without link!
+	 */
+	if (fep->linkstatus) {
+		fec_reg_write(fep, FEC_TCR, 0x01);	/* Graceful transmit stop */
 		udelay(10);
-		if (!(fecp->fec_ievent & FEC_ENET_GRA))
-			printk("fec_stop : Graceful transmit stop did not complete !\n");
-		}
-
+		if (!(fec_reg_read(fep, FEC_EIR) & FEC_ENET_GRA))
+			dev_warn(&dev->dev, "Graceful transmit stop did not complete!\n");
+	}
+#if 0
 	/* Whack a reset.  We should wait for this.
-	*/
-	fecp->fec_ecntrl = 1;
+	 */
+	fec_reg_write(fep, FEC_ECR, FEC_ECR_RESET);
 	udelay(10);
-
-	/* Clear outstanding MII command interrupts.
-	*/
-	fecp->fec_ievent = FEC_ENET_MII;
-
-	fecp->fec_imask = FEC_ENET_MII;
-	fecp->fec_mii_speed = fep->phy_speed;
+	/* Mask and clear outstanding MII command interrupts.
+	 */
+	fec_reg_write(fep, FEC_EIMR, 0);
+	fec_reg_write(fep, FEC_EIR, FEC_ENET_MII);
+	fec_enable_phy_intr(fep);
+	fec_reg_write(fep, FEC_MSCR, fep->phy_speed);
+#endif
 }
 
-static int __devinit
-fec_probe(struct platform_device *pdev)
+static int __devinit fec_enet_probe(struct platform_device *pdev)
 {
+	int ret;
 	struct fec_enet_private *fep;
-	struct net_device *ndev;
-	int i, irq, ret = 0;
-	struct resource *r;
-
-	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!r)
-		return -ENXIO;
+	struct net_device *dev;
+	struct fec_enet_platform_data *pdata = pdev->dev.platform_data;
+	struct resource *res_mem1;
+	struct resource *res_mem2;
+
+	res_mem1 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res_mem1 == NULL) {
+		return -ENODEV;
+	}
 
-	r = request_mem_region(r->start, resource_size(r), pdev->name);
-	if (!r)
+	res_mem1 = request_mem_region(res_mem1->start,
+				      resource_size(res_mem1),
+				      DRV_NAME);
+	if (res_mem1 == NULL) {
 		return -EBUSY;
+	}
+	res_mem2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (res_mem2 != NULL) {
+		res_mem2 = request_mem_region(res_mem2->start,
+					      resource_size(res_mem2),
+					      DRV_NAME);
+		if (res_mem2 == NULL) {
+			ret = -EBUSY;
+			goto release1;
+		}
+	}
 
-	/* Init network device */
-	ndev = alloc_etherdev(sizeof(struct fec_enet_private));
-	if (!ndev)
-		return -ENOMEM;
-
-	SET_NETDEV_DEV(ndev, &pdev->dev);
-
-	/* setup board info structure */
-	fep = netdev_priv(ndev);
-	memset(fep, 0, sizeof(*fep));
+	dev = alloc_etherdev(sizeof(struct fec_enet_private));
+	if (dev == NULL) {
+		ret = -ENOMEM;
+		goto release2;
+	}
+	platform_set_drvdata(pdev, dev);
+	fep = netdev_priv(dev);
+	fep->res_mem1 = res_mem1;
+	fep->res_mem2 = res_mem2;
+	fep->dma_dev = &pdev->dev;
+
+	fep->reg_base = ioremap(res_mem1->start, resource_size(res_mem1));
+	if (fep->reg_base == NULL) {
+		printk("FEC: Mapping FEC registers failed\n");
+		ret = -ENOMEM;
+		goto free_netdev;
+	}
+	DBG(0, "%s: FEC registers @ %08lx mapped to %p\n", __FUNCTION__,
+	    (unsigned long)res_mem1->start, fep->reg_base);
 
-	ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r));
+	fep->mib_base = ioremap(res_mem2->start, resource_size(res_mem2));
+	if (fep->mib_base == NULL) {
+		printk("FEC: Mapping FEC registers failed\n");
+		ret = -ENOMEM;
+		goto unmap1;
+	}
+	DBG(0, "%s: FEC registers @ %08lx mapped to %p\n", __FUNCTION__,
+	    (unsigned long)res_mem2->start, fep->mib_base);
 
-	if (!ndev->base_addr) {
+	/* Allocate memory for buffer descriptors. */
+	fep->cbd_mem_base = dma_alloc_coherent(&pdev->dev, CBD_BUF_SIZE,
+					       &fep->cbd_phys_base,
+					       GFP_KERNEL);
+	if (fep->cbd_mem_base == NULL) {
+		printk("FEC: allocate descriptor memory failed\n");
 		ret = -ENOMEM;
-		goto failed_ioremap;
+		goto unmap2;
 	}
+	DBG(0, "%s: Allocated %lu [(%u + %lu) * %d] byte for CBD buffer @ %p[%08lx]\n",
+	    __FUNCTION__, CBD_BUF_SIZE, TX_RING_SIZE, RX_RING_SIZE,
+	    sizeof(cbd_t), fep->cbd_mem_base,
+	    (unsigned long)fep->cbd_phys_base);
 
-	platform_set_drvdata(pdev, ndev);
+	/* Set receive and transmit descriptor base.
+	*/
+	fep->rx_bd_base = fep->cbd_mem_base;
+	fep->tx_bd_base = fep->rx_bd_base + RX_RING_SIZE;
 
-	/* This device has up to three irqs on some platforms */
-	for (i = 0; i < 3; i++) {
-		irq = platform_get_irq(pdev, i);
-		if (i && irq < 0)
-			break;
-		ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev);
-		if (ret) {
-			while (i >= 0) {
-				irq = platform_get_irq(pdev, i);
-				free_irq(irq, ndev);
-				i--;
-			}
-			goto failed_irq;
-		}
+	printk("FEC ENET Driver\n");
+	ret = platform_func(pdata->arch_init, pdev);
+	if (ret != 0) {
+		dev_err(&pdev->dev, "platform init failed: %d\n", ret);
+		goto free_dma;
 	}
 
-	fep->clk = clk_get(&pdev->dev, "fec_clk");
-	if (IS_ERR(fep->clk)) {
-		ret = PTR_ERR(fep->clk);
-		goto failed_clk;
+	ret = fec_enet_init(pdev, dev);
+	if (ret != 0) {
+		goto fec_disable;
 	}
-	clk_enable(fep->clk);
 
-	ret = fec_enet_init(ndev, 0);
-	if (ret)
-		goto failed_init;
+	/* Enable most messages by default */
+	fep->msg_enable = (NETIF_MSG_IFUP << 1) - 1;
+	ret = register_netdev(dev);
+	if (ret != 0) {
+		/* XXX: missing cleanup here */
+		goto free_buffers;
+	}
 
-	ret = register_netdev(ndev);
-	if (ret)
-		goto failed_register;
+	printk(KERN_INFO "%s: ethernet %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name,
+	       dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
+	       dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
 
 	return 0;
 
-failed_register:
-failed_init:
-	clk_disable(fep->clk);
-	clk_put(fep->clk);
-failed_clk:
-	for (i = 0; i < 3; i++) {
-		irq = platform_get_irq(pdev, i);
-		if (irq > 0)
-			free_irq(irq, ndev);
-	}
-failed_irq:
-	iounmap((void __iomem *)ndev->base_addr);
-failed_ioremap:
-	free_netdev(ndev);
+ free_buffers:
+	fec_enet_free_buffers(fep);
+
+ fec_disable:
+	platform_func(pdata->arch_exit, pdev);
+
+ free_dma:
+	dma_free_coherent(&pdev->dev, CBD_BUF_SIZE, fep->cbd_mem_base, fep->cbd_phys_base);
+
+ unmap2:
+	if (fep->mib_base)
+		iounmap(fep->mib_base);
+
+ unmap1:
+	iounmap(fep->reg_base);
+
+ free_netdev:
+	free_netdev(dev);
+
+ release2:
+	if (res_mem2 != NULL) {
+		release_resource(res_mem2);
+	}
+
+ release1:
+	release_resource(res_mem1);
 
 	return ret;
 }
 
-static int __devexit
-fec_drv_remove(struct platform_device *pdev)
+static int __devexit fec_enet_remove(struct platform_device *pdev)
 {
-	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct fec_enet_private *fep = netdev_priv(ndev);
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct fec_enet_private *fep = netdev_priv(dev);
+
+	unregister_netdev(dev);
+#ifdef CONFIG_PHYLIB
+	if (fep->mii != NULL) {
+		kfree(fep->mii->irq);
+		mdiobus_unregister(fep->mii);
+	}
+	mdiobus_free(fep->mii);
+#endif
+	fec_release_intrs(dev);
+
+	DBG(0, "%s: Unmapping FEC registers %p\n", __FUNCTION__, fep->reg_base);
+	iounmap(fep->reg_base);
+	if (fep->mib_base)
+		iounmap(fep->mib_base);
+
+	fec_enet_free_buffers(fep);
 
-	platform_set_drvdata(pdev, NULL);
+	DBG(0, "%s: Freeing CBD buffer area %p[%08lx]\n", __FUNCTION__,
+	    fep->cbd_mem_base, (unsigned long)fep->cbd_phys_base);
+	dma_free_coherent(&pdev->dev, CBD_BUF_SIZE, fep->cbd_mem_base, fep->cbd_phys_base);
 
-	fec_stop(ndev);
-	clk_disable(fep->clk);
-	clk_put(fep->clk);
-	iounmap((void __iomem *)ndev->base_addr);
-	unregister_netdev(ndev);
-	free_netdev(ndev);
+	release_resource(fep->res_mem1);
+	if (fep->res_mem2 != NULL) {
+		release_resource(fep->res_mem2);
+	}
+	free_netdev(dev);
 	return 0;
 }
 
-static int
-fec_suspend(struct platform_device *dev, pm_message_t state)
+static void fec_enet_shutdown(struct platform_device *pdev)
 {
-	struct net_device *ndev = platform_get_drvdata(dev);
-	struct fec_enet_private *fep;
+	struct fec_enet_platform_data *pdata = pdev->dev.platform_data;
+
+	DBG(0, "%s: Shutting down FEC Hardware\n", __FUNCTION__);
+	platform_func(pdata->arch_exit, pdev);
+}
+
+#ifdef CONFIG_PM
+static int fec_enet_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	int ret;
+	struct fec_enet_platform_data *pdata = pdev->dev.platform_data;
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
-	if (ndev) {
-		fep = netdev_priv(ndev);
-		if (netif_running(ndev)) {
-			netif_device_detach(ndev);
-			fec_stop(ndev);
+	if (netif_running(ndev)) {
+		DBG(0, "%s: Detaching netif\n", __FUNCTION__);
+		netif_device_detach(ndev);
+#ifdef CONFIG_PHYLIB
+		DBG(0, "%s: Disconnecting PHY %p\n", __FUNCTION__, fep->phy);
+		phy_disconnect(fep->phy);
+		fep->phy = NULL;
+#endif
+	}
+#ifndef CONFIG_PHYLIB
+	if (fep->phy_timer) {
+		ret = del_timer_sync(fep->phy_timer);
+		if (ret != 0) {
+			DBG(0, "%s: Failed to delete PHY timer: %d\n", __FUNCTION__, ret);
+			return ret;
 		}
 	}
-	return 0;
+#endif
+	DBG(0, "%s: Shutting down FEC Hardware %d\n", __FUNCTION__,
+	    netif_running(ndev));
+	ret = platform_func(pdata->suspend, pdev);
+	if (ret != 0 && netif_running(ndev)) {
+		DBG(0, "%s: Failed to suspend: %d\n", __FUNCTION__, ret);
+		/* Undo suspend */
+#ifdef CONFIG_PHYLIB
+		DBG(0, "%s: Reconnecting PHY\n", __FUNCTION__);
+		if (fec_connect_phy(ndev, fep) != 0) {
+			DBG(0, "%s: Failed to connect to PHY\n", __FUNCTION__);
+			return ret;
+		}
+		phy_start(fep->phy);
+#endif
+		fec_link_change(ndev);
+		netif_device_attach(ndev);
+	}
+	return ret;
 }
 
-static int
-fec_resume(struct platform_device *dev)
+static int fec_enet_resume(struct platform_device *pdev)
 {
-	struct net_device *ndev = platform_get_drvdata(dev);
+	int ret;
+	struct fec_enet_platform_data *pdata = pdev->dev.platform_data;
+	struct net_device *ndev = platform_get_drvdata(pdev);
 
-	if (ndev) {
-		if (netif_running(ndev)) {
-			fec_enet_init(ndev, 0);
-			netif_device_attach(ndev);
+	DBG(0, "%s: Powering up FEC Hardware %d\n", __FUNCTION__,
+	    netif_running(ndev));
+	ret = platform_func(pdata->resume, pdev);
+	if (ret != 0) {
+		DBG(0, "%s: Failed to resume: %d\n", __FUNCTION__, ret);
+		return ret;
+	}
+	if (netif_running(ndev)) {
+#ifdef CONFIG_PHYLIB
+		struct fec_enet_private *fep = netdev_priv(ndev);
+
+		DBG(0, "%s: Reconnecting PHY\n", __FUNCTION__);
+		ret = fec_connect_phy(ndev, fep);
+		if (ret != 0) {
+			DBG(0, "%s: Failed to connect to PHY: %d\n", __FUNCTION__, ret);
+			return ret;
 		}
+		phy_start(fep->phy);
+#endif
+		fec_link_change(ndev);
+		netif_device_attach(ndev);
 	}
 	return 0;
 }
+#else
+#define fec_enet_suspend	NULL
+#define fec_enet_resume		NULL
+#endif
 
-static struct platform_driver fec_driver = {
-	.driver	= {
-		.name    = "fec",
-		.owner	 = THIS_MODULE,
+static struct platform_driver fec_enet_driver = {
+	.driver = {
+		.name = DRV_NAME,
 	},
-	.probe   = fec_probe,
-	.remove  = __devexit_p(fec_drv_remove),
-	.suspend = fec_suspend,
-	.resume  = fec_resume,
+	.probe = fec_enet_probe,
+	.remove = __devexit_p(fec_enet_remove),
+	.shutdown = fec_enet_shutdown,
+	.suspend = fec_enet_suspend,
+	.resume = fec_enet_resume,
 };
 
-static int __init
-fec_enet_module_init(void)
+static int __init fec_enet_module_init(void)
 {
-	printk(KERN_INFO "FEC Ethernet Driver\n");
+	int ret;
+
+	ret = platform_driver_register(&fec_enet_driver);
 
-	return platform_driver_register(&fec_driver);
+	return ret;
 }
+module_init(fec_enet_module_init);
 
-static void __exit
-fec_enet_cleanup(void)
+static void __exit fec_enet_module_cleanup(void)
 {
-	platform_driver_unregister(&fec_driver);
+	platform_driver_unregister(&fec_enet_driver);
 }
-
-module_exit(fec_enet_cleanup);
-module_init(fec_enet_module_init);
+module_exit(fec_enet_module_cleanup);
 
 MODULE_LICENSE("GPL");
diff -purN linux-2.6.30-rc4-git/drivers/net/fec.h linux-2.6.30-rc4-karo3/drivers/net/fec.h
--- linux-2.6.30-rc4-git/drivers/net/fec.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/net/fec.h	2009-06-02 18:43:03.000000000 +0200
@@ -13,6 +13,15 @@
 #define	FEC_H
 /****************************************************************************/
 
+/*
+ * dummy value to write into RDAR,TDAR. FEC hardware will scan the TX/RX
+ * descriptors in memory upon any write access to those registers.
+ * The actual value written to those registers does not matter.
+*/
+#define DONT_CARE		0
+#define RDAR_BUSY		(1 << 24)
+#define TDAR_BUSY		(1 << 24)
+
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
     defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARCH_MXC)
 /*
@@ -20,6 +29,36 @@
  *	registers in the same peripheral device on different models
  *	of the ColdFire!
  */
+// relying on structure alignment for hardware register is just evil
+#ifndef GARBAGE
+#define FEC_EIR			0x004
+#define FEC_EIMR		0x008
+#define	FEC_RDAR		0x010
+#define	FEC_TDAR		0x014
+#define	FEC_ECR			0x024
+#define	FEC_MMFR		0x040
+#define	FEC_MSCR		0x044
+#define	FEC_MIBC		0x064
+#define	FEC_RCR			0x084
+#define	FEC_TCR			0x0c4
+#define	FEC_PALR		0x0e4
+#define	FEC_PAUR		0x0e8
+#define	FEC_OPD			0x0ec
+#define	FEC_IAUR		0x118
+#define	FEC_IALR		0x11c
+#define	FEC_GAUR		0x120
+#define	FEC_GALR		0x124
+#define	FEC_TFWR		0x144
+#define	FEC_FRBR		0x14c
+#define	FEC_FRSR		0x150
+#define	FEC_ERDSR		0x180
+#define	FEC_ETDSR		0x184
+#define	FEC_EMRBR		0x188
+
+#define FEC_ECR_RESET		(1 << 0)
+#define FEC_ECR_ETHER_EN	(1 << 1)
+#else
+
 typedef struct fec {
 	unsigned long	fec_reserved0;
 	unsigned long	fec_ievent;		/* Interrupt event reg */
@@ -57,6 +96,7 @@ typedef struct fec {
 	unsigned long	fec_x_des_start;	/* Transmit descriptor ring */
 	unsigned long	fec_r_buff_size;	/* Maximum receive buff size */
 } fec_t;
+#endif
 
 #else
 
@@ -88,8 +128,8 @@ typedef struct fec {
 	unsigned long	fec_reserved7[158];
 	unsigned long	fec_addr_low;		/* Low 32bits MAC address */
 	unsigned long	fec_addr_high;		/* High 16bits MAC address */
-	unsigned long	fec_grp_hash_table_high;/* High 32bits hash table */
-	unsigned long	fec_grp_hash_table_low;	/* Low 32bits hash table */
+	unsigned long	fec_hash_table_high;	/* High 32bits hash table */
+	unsigned long	fec_hash_table_low;	/* Low 32bits hash table */
 	unsigned long	fec_r_des_start;	/* Receive descriptor ring */
 	unsigned long	fec_x_des_start;	/* Transmit descriptor ring */
 	unsigned long	fec_r_buff_size;	/* Maximum receive buff size */
@@ -103,17 +143,20 @@ typedef struct fec {
 /*
  *	Define the buffer descriptor structure.
  */
-#ifdef CONFIG_ARCH_MXC
+/* Please see "Receive Buffer Descriptor Field Definitions" in Specification.
+ * It's LE.
+ */
+#if defined(CONFIG_ARCH_MXC)
 typedef struct bufdesc {
-	unsigned short cbd_datlen;	/* Data length */
-	unsigned short cbd_sc;	/* Control and status info */
-	unsigned long cbd_bufaddr;	/* Buffer address */
+	unsigned short	cbd_datlen;             /* Data length */
+	unsigned short	cbd_sc;                 /* Control and status info */
+	dma_addr_t	cbd_bufaddr;            /* Buffer address as seen by FEC Hardware */
 } cbd_t;
 #else
 typedef struct bufdesc {
 	unsigned short	cbd_sc;			/* Control and status info */
 	unsigned short	cbd_datlen;		/* Data length */
-	unsigned long	cbd_bufaddr;		/* Buffer address */
+	dma_addr_t	cbd_bufaddr;		/* Buffer address */
 } cbd_t;
 #endif
 
@@ -121,7 +164,7 @@ typedef struct bufdesc {
  *	The following definitions courtesy of commproc.h, which where
  *	Copyright (c) 1997 Dan Malek (dmalek@jlc.net).
  */
-#define BD_SC_EMPTY     ((ushort)0x8000)        /* Recieve is empty */
+#define BD_SC_EMPTY     ((ushort)0x8000)        /* Receive is empty */
 #define BD_SC_READY     ((ushort)0x8000)        /* Transmit is ready */
 #define BD_SC_WRAP      ((ushort)0x2000)        /* Last buffer descriptor */
 #define BD_SC_INTRPT    ((ushort)0x1000)        /* Interrupt on change */
@@ -168,5 +211,22 @@ typedef struct bufdesc {
 #define BD_ENET_TX_STATS        ((ushort)0x03ff)        /* All status bits */
 
 
+#define RCR_LOOP		(1 << 0)
+#define RCR_DRT			(1 << 1)
+#define RCR_MII_MODE		(1 << 2)
+#define RCR_PROM		(1 << 3)
+#define RCR_BC_REJ		(1 << 4)
+#define RCR_FCE			(1 << 5)
+#define RCR_MAX_FL_SHIFT	16
+#define RCR_MAX_FL_MASK		(0x7ff << (RCR_MAX_FL_SHIFT))
+#define RCR_MAX_FL_set(n)	(((n) << (RCR_MAX_FL_SHIFT)) & (RCR_MAX_FL_MASK))
+#define RCR_MAX_FL_get(n)	(((n) & (RCR_MAX_FL_MASK)) >> (RCR_MAX_FL_SHIFT))
+
+#define TCR_GTS			(1 << 0)
+#define TCR_HBC			(1 << 1)
+#define TCR_FDEN		(1 << 2)
+#define TCR_TFCPAUSE		(1 << 3)
+#define TCR_RFCPAUSE		(1 << 4)
+
 /****************************************************************************/
 #endif /* FEC_H */
diff -purN linux-2.6.30-rc4-git/drivers/usb/Kconfig linux-2.6.30-rc4-karo3/drivers/usb/Kconfig
--- linux-2.6.30-rc4-git/drivers/usb/Kconfig	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/usb/Kconfig	2009-06-29 10:49:52.000000000 +0200
@@ -57,6 +57,7 @@ config USB_ARCH_HAS_EHCI
 	default y if PPC_83xx
 	default y if SOC_AU1200
 	default y if ARCH_IXP4XX
+	default y if ARCH_MXC
 	default PCI
 
 # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
diff -purN linux-2.6.30-rc4-git/drivers/usb/host/Kconfig linux-2.6.30-rc4-karo3/drivers/usb/host/Kconfig
--- linux-2.6.30-rc4-git/drivers/usb/host/Kconfig	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/usb/host/Kconfig	2009-07-06 15:37:48.000000000 +0200
@@ -106,6 +106,37 @@ config USB_OXU210HP_HCD
 	  To compile this driver as a module, choose M here: the
 	  module will be called oxu210hp-hcd.
 
+config USB_EHCI_MXC
+	bool "Support for Freescale on-chip EHCI USB controller"
+	depends on USB_EHCI_HCD && ARCH_MXC
+	select USB_EHCI_ROOT_HUB_TT
+	---help---
+	  Variation of ARC USB block used in some Freescale chips.
+
+config ARCH_MXC_EHCI_USBH1
+	bool "Enable USB on USBH1 port"
+	depends on USB_EHCI_MXC && ARCH_MXC_HAS_USBH1
+
+config ARCH_MXC_EHCI_USBH2
+	bool "Enable USB on USBH2 port"
+	depends on USB_EHCI_MXC && ARCH_MXC_HAS_USBH2
+
+config ARCH_MXC_EHCI_USBOTG
+	bool "Enable USB on USBOTG port"
+	depends on USB_EHCI_MXC && ARCH_MXC_HAS_USBOTG
+
+config ARCH_MXC_HAS_USBH1
+	bool
+	depends on USB_EHCI_MXC
+
+config ARCH_MXC_HAS_USBH2
+	bool
+	depends on USB_EHCI_MXC
+
+config ARCH_MXC_HAS_USBOTG
+	bool
+	depends on USB_EHCI_MXC
+
 config USB_ISP116X_HCD
 	tristate "ISP116X HCD support"
 	depends on USB
diff -purN linux-2.6.30-rc4-git/drivers/usb/host/ehci-hcd.c linux-2.6.30-rc4-karo3/drivers/usb/host/ehci-hcd.c
--- linux-2.6.30-rc4-git/drivers/usb/host/ehci-hcd.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/usb/host/ehci-hcd.c	2009-07-01 11:30:25.000000000 +0200
@@ -1047,6 +1047,11 @@ MODULE_LICENSE ("GPL");
 #define	PLATFORM_DRIVER		ehci_fsl_driver
 #endif
 
+#ifdef CONFIG_USB_EHCI_MXC
+#include "ehci-mxc.c"
+#define PLATFORM_DRIVER		ehci_mxc_driver
+#endif
+
 #ifdef CONFIG_SOC_AU1200
 #include "ehci-au1xxx.c"
 #define	PLATFORM_DRIVER		ehci_hcd_au1xxx_driver
diff -purN linux-2.6.30-rc4-git/drivers/usb/host/ehci-mxc.c linux-2.6.30-rc4-karo3/drivers/usb/host/ehci-mxc.c
--- linux-2.6.30-rc4-git/drivers/usb/host/ehci-mxc.c	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/drivers/usb/host/ehci-mxc.c	2009-07-01 11:31:58.000000000 +0200
@@ -0,0 +1,247 @@
+/*
+ * Copyright (c) 2008 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * 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/platform_device.h>
+#include <linux/clk.h>
+#include <mach/mxc_ehci.h>
+
+/* called during probe() after chip reset completes */
+static int ehci_mxc_setup(struct usb_hcd *hcd)
+{
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	int retval;
+
+	/* EHCI registers start at offset 0x100 */
+	ehci->caps = hcd->regs + 0x100;
+	ehci->regs = hcd->regs + 0x100 +
+	    HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase));
+	dbg_hcs_params(ehci, "reset");
+	dbg_hcc_params(ehci, "reset");
+
+	/* cache this readonly data; minimize chip reads */
+	ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
+
+	retval = ehci_halt(ehci);
+	if (retval)
+		return retval;
+
+	/* data structure init */
+	retval = ehci_init(hcd);
+	if (retval)
+		return retval;
+
+	hcd->has_tt = 1;
+
+	ehci->sbrn = 0x20;
+
+	ehci_reset(ehci);
+
+	ehci_port_power(ehci, 0);
+	return 0;
+}
+
+static const struct hc_driver ehci_mxc_hc_driver = {
+	.description = hcd_name,
+	.product_desc = "Freescale On-Chip EHCI Host Controller",
+	.hcd_priv_size = sizeof(struct ehci_hcd),
+
+	/*
+	 * generic hardware linkage
+	 */
+	.irq = ehci_irq,
+	.flags = HCD_USB2 | HCD_MEMORY,
+
+	/*
+	 * basic lifecycle operations
+	 */
+	.reset = ehci_mxc_setup,
+	.start = ehci_run,
+	.stop = ehci_stop,
+	.shutdown = ehci_shutdown,
+
+	/*
+	 * managing i/o requests and associated device resources
+	 */
+	.urb_enqueue = ehci_urb_enqueue,
+	.urb_dequeue = ehci_urb_dequeue,
+	.endpoint_disable = ehci_endpoint_disable,
+
+	/*
+	 * scheduling support
+	 */
+	.get_frame_number = ehci_get_frame,
+
+	/*
+	 * root hub support
+	 */
+	.hub_status_data = ehci_hub_status_data,
+	.hub_control = ehci_hub_control,
+	.bus_suspend = ehci_bus_suspend,
+	.bus_resume = ehci_bus_resume,
+	.relinquish_port = ehci_relinquish_port,
+	.port_handed_over = ehci_port_handed_over,
+};
+
+static int ehci_mxc_drv_probe(struct platform_device *pdev)
+{
+	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
+	struct usb_hcd *hcd;
+	struct resource *res;
+	int irq, ret, temp;
+	struct clk *usbclk, *ahbclk;
+
+	dev_info(&pdev->dev, "initializing i.MX USB Controller\n");
+
+	/* Need platform data for setup */
+	if (!pdata) {
+		dev_err(&pdev->dev,
+			"No platform data for %s.\n", dev_name(&pdev->dev));
+		return -ENODEV;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+
+	hcd = usb_create_hcd(&ehci_mxc_hc_driver, &pdev->dev, dev_name(&pdev->dev));
+	if (!hcd) {
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Found HC with no register addr. Check %s setup!\n",
+			dev_name(&pdev->dev));
+		ret = -ENODEV;
+		goto err1;
+	}
+
+	hcd->rsrc_start = res->start;
+	hcd->rsrc_len = resource_size(res);
+
+	if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+		dev_dbg(&pdev->dev, "controller already in use\n");
+		ret = -EBUSY;
+		goto err1;
+	}
+
+	hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+	if (!hcd->regs) {
+		dev_err(&pdev->dev, "error mapping memory\n");
+		ret = -EFAULT;
+		goto err2;
+	}
+
+#if 0
+	ahbclk = clk_get(NULL, "usb_ahb_clk");
+	if (IS_ERR(ahbclk)) {
+		ret = PTR_ERR(ahbclk);
+		printk(KERN_ERR "Failed to get usb_ahb_clk: %d\n", ret);
+		goto err3;
+	}
+	clk_enable(ahbclk);
+#endif
+	usbclk = clk_get(&pdev->dev, "usb");
+	if (IS_ERR(usbclk)) {
+		ret = PTR_ERR(usbclk);
+		printk(KERN_ERR "Failed to get usb_clk: %d\n", ret);
+		goto err4;
+	}
+	clk_enable(usbclk);
+
+	if (pdata->init) {
+		ret = pdata->init(pdev);
+		if (ret) {
+			dev_err(&pdev->dev, "platform init failed\n");
+			goto err5;
+		}
+	}
+
+	/* Set to Host mode */
+	temp = readl(hcd->regs + 0x1a8);
+	writel(temp | 0x3, hcd->regs + 0x1a8);
+
+	ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED);
+	if (ret)
+		goto err6;
+
+	platform_set_drvdata(pdev, hcd);
+	clk_put(usbclk);
+
+	return 0;
+err6:
+	if (pdata->exit)
+		pdata->exit(pdev);
+err5:
+	clk_disable(usbclk);
+	clk_put(usbclk);
+err4:
+#if 0
+	clk_disable(ahbclk);
+	clk_put(ahbclk);
+#endif
+err3:
+	iounmap(hcd->regs);
+err2:
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err1:
+	usb_put_hcd(hcd);
+	return ret;
+}
+
+static int ehci_mxc_drv_remove(struct platform_device *pdev)
+{
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
+	struct clk *usbclk;
+
+	usb_remove_hcd(hcd);
+	iounmap(hcd->regs);
+	release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+	usb_put_hcd(hcd);
+	platform_set_drvdata(pdev, NULL);
+
+	if (pdata->exit)
+		pdata->exit(pdev);
+
+	usbclk = clk_get(&pdev->dev, "usb");
+	if (!IS_ERR(usbclk)) {
+		clk_disable(usbclk);
+		clk_put(usbclk);
+	}
+#if 0
+	ahbclk = clk_get(NULL, "usb_ahb_clk");
+	if (!IS_ERR(ahbclk)) {
+		clk_disable(ahbclk);
+		clk_put(ahbclk);
+	}
+#endif
+	return 0;
+}
+
+MODULE_ALIAS("platform:mxc-ehci");
+
+static struct platform_driver ehci_mxc_driver = {
+	.probe = ehci_mxc_drv_probe,
+	.remove = ehci_mxc_drv_remove,
+	.shutdown = usb_hcd_platform_shutdown,
+	.driver = {
+		   .name = "mxc-ehci",
+	},
+};
diff -purN linux-2.6.30-rc4-git/drivers/video/imxfb.c linux-2.6.30-rc4-karo3/drivers/video/imxfb.c
--- linux-2.6.30-rc4-git/drivers/video/imxfb.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/drivers/video/imxfb.c	2009-07-02 16:21:35.000000000 +0200
@@ -56,9 +56,9 @@
 #define VPW_VPW(x)	((x) & 0x3ff)
 
 #define LCDC_CPOS	0x0C
-#define CPOS_CC1	(1<<31)
-#define CPOS_CC0	(1<<30)
-#define CPOS_OP		(1<<28)
+#define CPOS_CC1	(1 << 31)
+#define CPOS_CC0	(1 << 30)
+#define CPOS_OP		(1 << 28)
 #define CPOS_CXP(x)	(((x) & 3ff) << 16)
 
 #ifdef CONFIG_ARCH_MX1
@@ -68,7 +68,7 @@
 #endif
 
 #define LCDC_LCWHB	0x10
-#define LCWHB_BK_EN	(1<<31)
+#define LCWHB_BK_EN	(1 << 31)
 #define LCWHB_CW(w)	(((w) & 0x1f) << 24)
 #define LCWHB_CH(h)	(((h) & 0x1f) << 16)
 #define LCWHB_BD(x)	((x) & 0xff)
@@ -112,22 +112,22 @@
 #define LCDC_RMCR	0x34
 
 #ifdef CONFIG_ARCH_MX1
-#define RMCR_LCDC_EN	(1<<1)
+#define RMCR_LCDC_EN	(1 << 1)
 #else
 #define RMCR_LCDC_EN	0
 #endif
 
-#define RMCR_SELF_REF	(1<<0)
+#define RMCR_SELF_REF	(1 << 0)
 
 #define LCDC_LCDICR	0x38
-#define LCDICR_INT_SYN	(1<<2)
-#define LCDICR_INT_CON	(1)
+#define LCDICR_INT_SYN	(1 << 2)
+#define LCDICR_INT_CON	1
 
 #define LCDC_LCDISR	0x40
-#define LCDISR_UDR_ERR	(1<<3)
-#define LCDISR_ERR_RES	(1<<2)
-#define LCDISR_EOF	(1<<1)
-#define LCDISR_BOF	(1<<0)
+#define LCDISR_UDR_ERR	(1 << 3)
+#define LCDISR_ERR_RES	(1 << 2)
+#define LCDISR_EOF	(1 << 1)
+#define LCDISR_BOF	(1 << 0)
 
 /*
  * These are the bitfields for each
@@ -232,11 +232,11 @@ static int imxfb_setpalettereg(u_int reg
 	struct imxfb_info *fbi = info->par;
 	u_int val, ret = 1;
 
-#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
+#define CNVT_TOHW(val,width) ((((val) << (width)) + 0x7FFF - (val)) >> 16)
 	if (regno < fbi->palette_size) {
-		val = (CNVT_TOHW(red, 4) << 8) |
-		      (CNVT_TOHW(green,4) << 4) |
-		      CNVT_TOHW(blue,  4);
+		val = (CNVT_TOHW(red, 6) << 12) |
+			(CNVT_TOHW(green, 6) << 6) |
+			CNVT_TOHW(blue,  6);
 
 		writel(val, fbi->regs + 0x800 + (regno << 2));
 		ret = 0;
@@ -265,7 +265,7 @@ static int imxfb_setcolreg(u_int regno, 
 
 	/*
 	 * If greyscale is true, then we convert the RGB value
-	 * to greyscale no mater what visual we are using.
+	 * to greyscale no matter what visual we are using.
 	 */
 	if (info->var.grayscale)
 		red = green = blue = (19595 * red + 38470 * green +
@@ -527,7 +527,7 @@ static int imxfb_activate_var(struct fb_
 	if (--pcr > 0x3F) {
 		pcr = 0x3F;
 		printk(KERN_WARNING "Must limit pixel clock to %uHz\n",
-				lcd_clk / pcr);
+				lcd_clk / pcr + 1);
 	}
 
 	/* add sync polarities */
@@ -570,7 +570,7 @@ static int imxfb_resume(struct platform_
 #define imxfb_resume	NULL
 #endif
 
-static int __init imxfb_init_fbinfo(struct platform_device *pdev)
+static int __devinit imxfb_init_fbinfo(struct platform_device *pdev)
 {
 	struct imx_fb_platform_data *pdata = pdev->dev.platform_data;
 	struct fb_info *info = dev_get_drvdata(&pdev->dev);
@@ -636,7 +636,7 @@ static int __init imxfb_init_fbinfo(stru
 	return 0;
 }
 
-static int __init imxfb_probe(struct platform_device *pdev)
+static int __devinit imxfb_probe(struct platform_device *pdev)
 {
 	struct imxfb_info *fbi;
 	struct fb_info *info;
@@ -754,7 +754,7 @@ failed_map:
 failed_getclock:
 	iounmap(fbi->regs);
 failed_ioremap:
-	release_mem_region(res->start, res->end - res->start);
+	release_mem_region(res->start, resource_size(res));
 failed_req:
 	kfree(info->pseudo_palette);
 failed_init:
@@ -763,7 +763,7 @@ failed_init:
 	return ret;
 }
 
-static int __devexit imxfb_remove(struct platform_device *pdev)
+static int imxfb_remove(struct platform_device *pdev)
 {
 	struct imx_fb_platform_data *pdata;
 	struct fb_info *info = platform_get_drvdata(pdev);
@@ -785,7 +785,7 @@ static int __devexit imxfb_remove(struct
 	framebuffer_release(info);
 
 	iounmap(fbi->regs);
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 	clk_disable(fbi->clk);
 	clk_put(fbi->clk);
 
@@ -794,7 +794,7 @@ static int __devexit imxfb_remove(struct
 	return 0;
 }
 
-void  imxfb_shutdown(struct platform_device * dev)
+void imxfb_shutdown(struct platform_device *dev)
 {
 	struct fb_info *info = platform_get_drvdata(dev);
 	struct imxfb_info *fbi = info->par;
@@ -804,7 +804,8 @@ void  imxfb_shutdown(struct platform_dev
 static struct platform_driver imxfb_driver = {
 	.suspend	= imxfb_suspend,
 	.resume		= imxfb_resume,
-	.remove		= __devexit_p(imxfb_remove),
+//	.remove		= __devexit_p(imxfb_remove),
+	.remove		= imxfb_remove,
 	.shutdown	= imxfb_shutdown,
 	.driver		= {
 		.name	= DRIVER_NAME,
diff -purN linux-2.6.30-rc4-git/fs/jffs2/erase.c linux-2.6.30-rc4-karo3/fs/jffs2/erase.c
--- linux-2.6.30-rc4-git/fs/jffs2/erase.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/fs/jffs2/erase.c	2009-07-14 14:12:12.000000000 +0200
@@ -422,6 +422,7 @@ static void jffs2_mark_erased_block(stru
 	/* Cleanmarker in oob area or no cleanmarker at all ? */
 	if (jffs2_cleanmarker_oob(c) || c->cleanmarker_size == 0) {
 
+		/* We only write cleanmarker in case of SLC NAND */
 		if (jffs2_cleanmarker_oob(c)) {
 			if (jffs2_write_nand_cleanmarker(c, jeb))
 				goto filebad;
diff -purN linux-2.6.30-rc4-git/fs/jffs2/fs.c linux-2.6.30-rc4-karo3/fs/jffs2/fs.c
--- linux-2.6.30-rc4-git/fs/jffs2/fs.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/fs/jffs2/fs.c	2009-07-14 14:12:28.000000000 +0200
@@ -680,7 +680,9 @@ void jffs2_gc_release_page(struct jffs2_
 static int jffs2_flash_setup(struct jffs2_sb_info *c) {
 	int ret = 0;
 
-	if (jffs2_cleanmarker_oob(c)) {
+	if (c->mtd->type == MTD_NANDFLASH) {
+		if (!(c->mtd->flags & MTD_OOB_WRITEABLE))
+			printk(KERN_DEBUG "JFFS2 doesn't use OOB.\n");
 		/* NAND flash... do setup accordingly */
 		ret = jffs2_nand_flash_setup(c);
 		if (ret)
@@ -713,7 +715,7 @@ static int jffs2_flash_setup(struct jffs
 
 void jffs2_flash_cleanup(struct jffs2_sb_info *c) {
 
-	if (jffs2_cleanmarker_oob(c)) {
+	if (c->mtd->type == MTD_NANDFLASH) {
 		jffs2_nand_flash_cleanup(c);
 	}
 
diff -purN linux-2.6.30-rc4-git/fs/jffs2/os-linux.h linux-2.6.30-rc4-karo3/fs/jffs2/os-linux.h
--- linux-2.6.30-rc4-git/fs/jffs2/os-linux.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/fs/jffs2/os-linux.h	2009-07-14 14:12:32.000000000 +0200
@@ -110,7 +110,7 @@ static inline void jffs2_init_inode_info
 #define jffs2_can_mark_obsolete(c) (c->mtd->flags & (MTD_BIT_WRITEABLE))
 #endif
 
-#define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH)
+#define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH && (c->mtd->flags & MTD_OOB_WRITEABLE))
 
 #define jffs2_flash_write_oob(c, ofs, len, retlen, buf) ((c)->mtd->write_oob((c)->mtd, ofs, len, retlen, buf))
 #define jffs2_flash_read_oob(c, ofs, len, retlen, buf) ((c)->mtd->read_oob((c)->mtd, ofs, len, retlen, buf))
diff -purN linux-2.6.30-rc4-git/include/linux/fec_enet.h linux-2.6.30-rc4-karo3/include/linux/fec_enet.h
--- linux-2.6.30-rc4-git/include/linux/fec_enet.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/include/linux/fec_enet.h	2009-03-16 12:49:03.000000000 +0100
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2007  Lothar Wassmann <LW@KARO-electronics.de>
+ *
+ * platform_data definitions for fec_enet device
+ *
+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
+ */
+
+struct fec_enet_platform_data {
+	/* callback for platform specific initialization */
+	int (*arch_init)(struct platform_device *dev);
+	void (*arch_exit)(struct platform_device *dev);
+	int (*suspend)(struct platform_device *dev);
+	int (*resume)(struct platform_device *dev);
+};
diff -purN linux-2.6.30-rc4-git/include/linux/usb/xcvr.h linux-2.6.30-rc4-karo3/include/linux/usb/xcvr.h
--- linux-2.6.30-rc4-git/include/linux/usb/xcvr.h	1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.30-rc4-karo3/include/linux/usb/xcvr.h	2009-07-01 11:32:10.000000000 +0200
@@ -0,0 +1,71 @@
+#ifndef __LINUX_USB_XCVR_H
+#define __LINUX_USB_XCVR_H
+
+struct usb_xcvr;
+
+struct usb_xcvr_access_ops {
+	int (*read)(struct usb_xcvr *xcvr, u32 reg);
+	int (*write)(struct usb_xcvr *xcvr, u32 val, u32 reg);
+};
+
+struct usb_xcvr_driver {
+	int  (*init)(struct usb_xcvr *xcvr);
+	void (*shutdown)(struct usb_xcvr *xcvr);
+	int  (*set_vbus)(struct usb_xcvr *xcvr, bool en);
+};
+
+struct usb_xcvr {
+	struct usb_xcvr_access_ops 	*access;
+	struct usb_xcvr_driver		*driver;
+	void __iomem			*access_priv;
+
+	/* only set this if you don't want the lowlevel driver to
+	 * handle this */
+	int (*set_vbus)(struct usb_xcvr *xcvr, bool en);
+};
+
+static inline int usb_xcvr_init(struct usb_xcvr *xcvr)
+{
+	if (xcvr->driver && xcvr->driver->init)
+		return xcvr->driver->init(xcvr);
+
+	return -EINVAL;
+}
+
+static inline void usb_xcvr_shutdown(struct usb_xcvr *xcvr)
+{
+	if (xcvr->driver && xcvr->driver->shutdown)
+		xcvr->driver->shutdown(xcvr);
+}
+
+static inline int usb_xcvr_set_vbus(struct usb_xcvr *xcvr, bool en)
+{
+	if (xcvr->set_vbus)
+		return xcvr->set_vbus(xcvr, en);
+
+	if (xcvr->driver && xcvr->driver->set_vbus)
+		return xcvr->driver->set_vbus(xcvr, en);
+
+	return -EINVAL;
+}
+
+/* lowlowel access helpers */
+
+static inline int usb_xcvr_read(struct usb_xcvr *xcvr, u32 reg)
+{
+	if (xcvr->access->read)
+		return xcvr->access->read(xcvr, reg);
+
+	return -EINVAL;
+}
+
+static inline int usb_xcvr_write(struct usb_xcvr *xcvr, u32 val, u32 reg)
+{
+	if (xcvr->access->write)
+		return xcvr->access->write(xcvr, val, reg);
+
+	return -EINVAL;
+}
+
+#endif /* __LINUX_USB_XCVR_H */
+
diff -purN linux-2.6.30-rc4-git/include/mtd/mtd-abi.h linux-2.6.30-rc4-karo3/include/mtd/mtd-abi.h
--- linux-2.6.30-rc4-git/include/mtd/mtd-abi.h	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/include/mtd/mtd-abi.h	2009-07-14 14:12:38.000000000 +0200
@@ -30,12 +30,14 @@ struct mtd_oob_buf {
 #define MTD_BIT_WRITEABLE	0x800	/* Single bits can be flipped */
 #define MTD_NO_ERASE		0x1000	/* No erase necessary */
 #define MTD_POWERUP_LOCK	0x2000	/* Always locked after reset */
+#define MTD_OOB_WRITEABLE	0x4000	/* Use Out-Of-Band area */
 
 // Some common devices / combinations of capabilities
 #define MTD_CAP_ROM		0
 #define MTD_CAP_RAM		(MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_NO_ERASE)
 #define MTD_CAP_NORFLASH	(MTD_WRITEABLE | MTD_BIT_WRITEABLE)
-#define MTD_CAP_NANDFLASH	(MTD_WRITEABLE)
+#define MTD_CAP_NANDFLASH	(MTD_WRITEABLE | MTD_OOB_WRITEABLE)
+#define MTD_CAP_MLC_NANDFLASH	(MTD_WRITEABLE)
 
 /* ECC byte placement */
 #define MTD_NANDECC_OFF		0	// Switch off ECC (Not recommended)
diff -purN linux-2.6.30-rc4-git/kernel/printk.c linux-2.6.30-rc4-karo3/kernel/printk.c
--- linux-2.6.30-rc4-git/kernel/printk.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/kernel/printk.c	2009-06-02 19:21:25.000000000 +0200
@@ -637,9 +637,12 @@ static int acquire_console_semaphore_for
 static const char recursion_bug_msg [] =
 		KERN_CRIT "BUG: recent printk recursion!\n";
 static int recursion_bug;
-static int new_text_line = 1;
+	static int new_text_line = 1;
 static char printk_buf[1024];
 
+#ifdef CONFIG_DEBUG_LL
+extern void asmlinkage printascii(const char *);
+#endif
 asmlinkage int vprintk(const char *fmt, va_list args)
 {
 	int printed_len = 0;
@@ -687,6 +690,9 @@ asmlinkage int vprintk(const char *fmt, 
 				  sizeof(printk_buf) - printed_len, fmt, args);
 
 
+#ifdef CONFIG_DEBUG_LL
+	printascii(printk_buf);
+#endif
 	/*
 	 * Copy the output into log_buf.  If the caller didn't provide
 	 * appropriate log level tags, we insert them here
diff -purN linux-2.6.30-rc4-git/net/can/bcm.c linux-2.6.30-rc4-karo3/net/can/bcm.c
--- linux-2.6.30-rc4-git/net/can/bcm.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/net/can/bcm.c	2009-07-14 14:13:01.000000000 +0200
@@ -75,6 +75,7 @@ static __initdata const char banner[] = 
 MODULE_DESCRIPTION("PF_CAN broadcast manager protocol");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Oliver Hartkopp <oliver.hartkopp@volkswagen.de>");
+MODULE_ALIAS("can-proto-2");
 
 /* easy access to can_frame payload */
 static inline u64 GET_U64(const struct can_frame *cp)
@@ -1469,6 +1470,9 @@ static int bcm_release(struct socket *so
 		bo->ifindex = 0;
 	}
 
+	sock_orphan(sk);
+	sock->sk = NULL;
+
 	release_sock(sk);
 	sock_put(sk);
 
diff -purN linux-2.6.30-rc4-git/net/can/raw.c linux-2.6.30-rc4-karo3/net/can/raw.c
--- linux-2.6.30-rc4-git/net/can/raw.c	2009-05-13 09:46:19.000000000 +0200
+++ linux-2.6.30-rc4-karo3/net/can/raw.c	2009-07-14 14:13:07.000000000 +0200
@@ -62,6 +62,7 @@ static __initdata const char banner[] =
 MODULE_DESCRIPTION("PF_CAN raw protocol");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_AUTHOR("Urs Thuermann <urs.thuermann@volkswagen.de>");
+MODULE_ALIAS("can-proto-1");
 
 #define MASK_ALL 0
 
@@ -306,6 +307,9 @@ static int raw_release(struct socket *so
 	ro->bound   = 0;
 	ro->count   = 0;
 
+	sock_orphan(sk);
+	sock->sk = NULL;
+
 	release_sock(sk);
 	sock_put(sk);