aboutsummaryrefslogtreecommitdiffstats
path: root/recipes/linux/linux-2.6.29+2.6.30-rc4/tx25/linux-2.6.30-rc4-karo3.diff
diff options
context:
space:
mode:
Diffstat (limited to 'recipes/linux/linux-2.6.29+2.6.30-rc4/tx25/linux-2.6.30-rc4-karo3.diff')
-rw-r--r--recipes/linux/linux-2.6.29+2.6.30-rc4/tx25/linux-2.6.30-rc4-karo3.diff18663
1 files changed, 18663 insertions, 0 deletions
diff --git a/recipes/linux/linux-2.6.29+2.6.30-rc4/tx25/linux-2.6.30-rc4-karo3.diff b/recipes/linux/linux-2.6.29+2.6.30-rc4/tx25/linux-2.6.30-rc4-karo3.diff
new file mode 100644
index 0000000000..dad744a629
--- /dev/null
+++ b/recipes/linux/linux-2.6.29+2.6.30-rc4/tx25/linux-2.6.30-rc4-karo3.diff
@@ -0,0 +1,18663 @@
+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);
+