kernel: added support for vmx25 into recipe 2.6.35 kernel
authorMarek Sujak <sujak.marek@gmail.com>
Fri, 28 Jan 2011 13:54:50 +0000 (14:54 +0100)
committerEric Bénard <eric@eukrea.com>
Mon, 31 Jan 2011 21:01:03 +0000 (22:01 +0100)
* modified recipe linux_2.6.35.bb
* added kernel-2.6.35 defconfig for vmx25
* added kernel-2.6.35 patch for vmx25
** Most of significant pheripherals was tested on (x11-image, qt4e image)
** ethernet -> ok
** video -> 640x480, 800x480, 800x600
** sd -> ok
** audio -> ok

Signed-off-by: Marek Sujak <sujak.marek@gmail.com>
Signed-off-by: Eric Bénard <eric@eukrea.com>
recipes/linux/linux-2.6.35/vmx25/defconfig [new file with mode: 0644]
recipes/linux/linux-2.6.35/vmx25/linux-2.6.35-vmx25-20110112.patch [new file with mode: 0644]
recipes/linux/linux_2.6.35.bb

diff --git a/recipes/linux/linux-2.6.35/vmx25/defconfig b/recipes/linux/linux-2.6.35/vmx25/defconfig
new file mode 100644 (file)
index 0000000..cbd23c5
--- /dev/null
@@ -0,0 +1,1771 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.35
+# Thu Jan 27 12:12:40 2011
+#
+CONFIG_ARM=y
+CONFIG_HAVE_PWM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_HAVE_PROC_CPU=y
+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_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_FIQ=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_CONSTRUCTORS=y
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_KERNEL_GZIP=y
+# CONFIG_KERNEL_BZIP2 is not set
+# CONFIG_KERNEL_LZMA is not set
+# CONFIG_KERNEL_LZO is not set
+# 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_TREE_RCU is not set
+# CONFIG_TREE_PREEMPT_RCU is not set
+CONFIG_TINY_RCU=y
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=16
+# 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 is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+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_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+# CONFIG_SLUB is not set
+CONFIG_SLOB=y
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+# CONFIG_MODULES is not set
+CONFIG_BLOCK=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=y
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_DEADLINE=y
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="deadline"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
+CONFIG_FREEZER=y
+
+#
+# System Type
+#
+CONFIG_MMU=y
+# 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_VEXPRESS is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+CONFIG_ARCH_MXC=y
+# CONFIG_ARCH_STMP3XXX 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_DOVE is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_NUC93X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE 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_S5P6440 is not set
+# CONFIG_ARCH_S5P6442 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
+# CONFIG_ARCH_DAVINCI is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_PLAT_SPEAR is not set
+CONFIG_IMX_HAVE_PLATFORM_FLEXCAN=y
+CONFIG_IMX_HAVE_PLATFORM_IMX_I2C=y
+CONFIG_IMX_HAVE_PLATFORM_IMX_UART=y
+CONFIG_IMX_HAVE_PLATFORM_MXC_NAND=y
+CONFIG_IMX_HAVE_PLATFORM_SPI_IMX=y
+
+#
+# Freescale MXC Implementations
+#
+# CONFIG_ARCH_MX1 is not set
+# CONFIG_ARCH_MX2 is not set
+CONFIG_ARCH_MX25=y
+# CONFIG_ARCH_MX3 is not set
+# CONFIG_ARCH_MXC91231 is not set
+# CONFIG_ARCH_MX5 is not set
+
+#
+# MX25 platforms:
+#
+# CONFIG_MACH_MX25_3DS is not set
+CONFIG_MACH_VMX25=y
+CONFIG_MACH_VMX_BASEBOARD=y
+# CONFIG_VMX_SD_ON_MODULE is not set
+CONFIG_VMX_SD_ON_BOARD=y
+CONFIG_MXC_SDMA_API=y
+CONFIG_MXC_IRQ_PRIOR=y
+CONFIG_MXC_PWM=y
+CONFIG_ARCH_MXC_IOMUX_V3=y
+CONFIG_ARCH_MXC_AUDMUX_V2=y
+CONFIG_MXC_SSI_PORTS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_LEGACY=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_ARM_L1_CACHE_SHIFT=5
+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_NONE is not set
+# CONFIG_PREEMPT_VOLUNTARY is not set
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+# 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=999999
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
+CONFIG_ALIGNMENT_TRAP=y
+# CONFIG_UACCESS_WITH_MEMCPY is not set
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="console=ttymxc0,115200 mem=32M@0x80000000 mem=32M@0x90000000 ip=dhcp ubi.mtd=3 root=ubi0:rootfs rootfstype=ubifs otg_mode=host video=imxfb:VGA-16@60"
+# CONFIG_CMDLINE_FORCE is not set
+# 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_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+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 is not set
+CONFIG_PM_SLEEP=y
+CONFIG_SUSPEND_NVS=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_APM_EMULATION=y
+# CONFIG_PM_RUNTIME is not set
+CONFIG_PM_OPS=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=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 is not set
+# 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 is not set
+# 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_RDS is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_L2TP 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_IEEE802154 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=y
+CONFIG_CAN_RAW=y
+CONFIG_CAN_BCM=y
+
+#
+# CAN Device Drivers
+#
+# CONFIG_CAN_VCAN is not set
+CONFIG_CAN_DEV=y
+CONFIG_CAN_CALC_BITTIMING=y
+CONFIG_CAN_MCP251X=y
+CONFIG_HAVE_CAN_FLEXCAN=y
+CONFIG_CAN_FLEXCAN=y
+# CONFIG_CAN_SJA1000 is not set
+
+#
+# CAN USB interfaces
+#
+# CONFIG_CAN_EMS_USB is not set
+CONFIG_CAN_DEBUG_DEVICES=y
+# 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
+# CONFIG_CAIF is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+# CONFIG_DEVTMPFS_MOUNT is not set
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+
+#
+# MXC support drivers
+#
+
+#
+# i.MX ADC support
+#
+# CONFIG_IMX_ADC is not set
+CONFIG_CONNECTOR=y
+CONFIG_PROC_EVENTS=y
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=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 is not set
+# CONFIG_MTD_BLOCK is not set
+# CONFIG_MTD_BLOCK_RO is not set
+# 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_SM_FTL 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_DATAFLASH is not set
+CONFIG_MTD_M25P80=y
+# CONFIG_M25PXX_USE_FAST_READ is not set
+# CONFIG_MTD_SST25L is not set
+# 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_ECC=y
+# CONFIG_MTD_NAND_ECC_SMC is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_SM_COMMON is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018
+# 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_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MTD_UBI_BEB_RESERVE=1
+CONFIG_MTD_UBI_GLUEBI=y
+
+#
+# UBI debugging options
+#
+# CONFIG_MTD_UBI_DEBUG is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+# CONFIG_BLK_DEV_RAM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+# CONFIG_MG_DISK is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_AD525X_DPOT is not set
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_AT25 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_MAX6875 is not set
+# CONFIG_EEPROM_93CX6 is not set
+# CONFIG_IWMC3200TOP is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+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=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+CONFIG_CHR_DEV_SG=y
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_MULTI_LUN=y
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# 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_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_MICREL_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_ENC28J60 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_KS8842 is not set
+# CONFIG_KS8851 is not set
+# CONFIG_KS8851_MLL is not set
+CONFIG_FEC=y
+# CONFIG_FEC2 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN 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_USB_IPHETH is not set
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_NETCONSOLE is not set
+# CONFIG_NETPOLL is not set
+# CONFIG_NET_POLL_CONTROLLER is not set
+# CONFIG_ISDN is not set
+# CONFIG_PHONE is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+# CONFIG_INPUT_SPARSEKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+# CONFIG_INPUT_APMPOWER is not set
+
+#
+# Input Device Drivers
+#
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+# CONFIG_SERIO is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+# CONFIG_DEVKMEM is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_MAX3100 is not set
+CONFIG_SERIAL_IMX=y
+CONFIG_SERIAL_IMX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# 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_RAMOOPS is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+# CONFIG_I2C_HELPER_AUTO is not set
+# CONFIG_I2C_SMBUS is not set
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_IMX=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+CONFIG_SPI=y
+CONFIG_SPI_MASTER=y
+
+#
+# SPI Master Controller Drivers
+#
+CONFIG_SPI_BITBANG=y
+# CONFIG_SPI_GPIO is not set
+CONFIG_SPI_IMX=y
+# CONFIG_SPI_XILINX is not set
+# CONFIG_SPI_DESIGNWARE is not set
+
+#
+# SPI Protocol Masters
+#
+CONFIG_SPI_SPIDEV=y
+# CONFIG_SPI_TLE62X0 is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
+
+#
+# Memory mapped GPIO expanders:
+#
+# CONFIG_GPIO_IT8761E is not set
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX7300 is not set
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_ADP5588 is not set
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_GPIO_MAX7301 is not set
+# CONFIG_GPIO_MCP23S08 is not set
+# CONFIG_GPIO_MC33880 is not set
+
+#
+# AC97 GPIO expanders:
+#
+
+#
+# MODULbus GPIO expanders:
+#
+CONFIG_W1=y
+CONFIG_W1_CON=y
+
+#
+# 1-wire Bus Masters
+#
+# CONFIG_W1_MASTER_DS2490 is not set
+# CONFIG_W1_MASTER_DS2482 is not set
+CONFIG_W1_MASTER_MXC=y
+# CONFIG_W1_MASTER_DS1WM is not set
+# CONFIG_W1_MASTER_GPIO is not set
+
+#
+# 1-wire Slaves
+#
+# CONFIG_W1_SLAVE_THERM is not set
+CONFIG_W1_SLAVE_SMEM=y
+# CONFIG_W1_SLAVE_DS2431 is not set
+# CONFIG_W1_SLAVE_DS2433 is not set
+# CONFIG_W1_SLAVE_DS2760 is not set
+# CONFIG_W1_SLAVE_BQ27000 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADCXX is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7411 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ASC7621 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM70 is not set
+# CONFIG_SENSORS_LM73 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1111 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_EMC1403 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_ADS7871 is not set
+# CONFIG_SENSORS_AMC6821 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_TMP102 is not set
+# CONFIG_SENSORS_TMP401 is not set
+# CONFIG_SENSORS_TMP421 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
+# CONFIG_THERMAL is not set
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_NOWAYOUT=y
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+# CONFIG_MAX63XX_WATCHDOG is not set
+CONFIG_IMX2_WDT=y
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+CONFIG_HAVE_FB_IMX=y
+# 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 is not set
+
+#
+# Frame buffer hardware drivers
+#
+CONFIG_FB_IMX=y
+# CONFIG_FB_UVESA is not set
+# 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=y
+# CONFIG_LCD_CLASS_DEVICE is not set
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+CONFIG_BACKLIGHT_PWM=y
+# CONFIG_BACKLIGHT_ADP8860 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=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+# CONFIG_FONT_6x11 is not set
+# CONFIG_FONT_7x14 is not set
+# CONFIG_FONT_PEARL_8x8 is not set
+# CONFIG_FONT_ACORN_8x8 is not set
+# CONFIG_FONT_MINI_4x6 is not set
+# CONFIG_FONT_SUN8x16 is not set
+# CONFIG_FONT_SUN12x22 is not set
+# CONFIG_FONT_10x18 is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set
+CONFIG_SND=y
+CONFIG_SND_TIMER=y
+CONFIG_SND_PCM=y
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_DYNAMIC_MINORS=y
+CONFIG_SND_SUPPORT_OLD_API=y
+# CONFIG_SND_VERBOSE_PROCFS is not set
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+# CONFIG_SND_RAWMIDI_SEQ is not set
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+# CONFIG_SND_DRIVERS is not set
+# CONFIG_SND_ARM is not set
+# CONFIG_SND_SPI is not set
+# CONFIG_SND_USB is not set
+CONFIG_SND_SOC=y
+CONFIG_SND_SOC_AC97_BUS=y
+CONFIG_SND_IMX_SOC=y
+CONFIG_SND_SOC_IMX_3STACK_SGTL5000=y
+CONFIG_SND_SOC_I2C_AND_SPI=y
+# CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_SGTL5000=y
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=y
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_3M_PCT is not set
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CANDO is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EGALAX is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MOSART is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_QUANTA is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_ROCCAT_KONE is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_STANTUM is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON 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=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+# CONFIG_USB_DEVICE_CLASS is not set
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=y
+# 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=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+# CONFIG_USB_EHCI_TT_NEWSCHED is not set
+CONFIG_USB_EHCI_MXC=y
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_ISP1362_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
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_GADGET_MUSB_HDRC is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=y
+# 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=y
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# 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 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_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_GADGET=y
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_VBUS_DRAW=300
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+CONFIG_USB_GADGET_FSL_USB2=y
+CONFIG_USB_FSL_USB2=y
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_R8A66597 is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C_HSOTG is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LANGWELL is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+# CONFIG_USB_ZERO is not set
+# CONFIG_USB_AUDIO is not set
+CONFIG_USB_ETH=y
+CONFIG_USB_ETH_RNDIS=y
+# CONFIG_USB_ETH_EEM is not set
+# CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
+# CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_MASS_STORAGE is not set
+# CONFIG_USB_G_SERIAL is not set
+# CONFIG_USB_MIDI_GADGET is not set
+# CONFIG_USB_G_PRINTER is not set
+# CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_NOKIA is not set
+# CONFIG_USB_G_MULTI is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_WEBCAM is not set
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ULPI is not set
+CONFIG_NOP_USB_XCEIV=y
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+CONFIG_MMC_SDHCI=y
+# CONFIG_MMC_SDHCI_PLTFM is not set
+# CONFIG_MMC_MXC is not set
+# CONFIG_MMC_SPI is not set
+CONFIG_MMC_SDHCI_MXC=y
+# CONFIG_MMC_SDHCI_MXC_SELECT2 is not set
+# CONFIG_MMC_SDHCI_MXC_PIO_MODE is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP3944 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_PWM is not set
+# CONFIG_LEDS_BD2802 is not set
+# CONFIG_LEDS_LT3593 is not set
+CONFIG_LEDS_TRIGGERS=y
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+CONFIG_LEDS_TRIGGER_GPIO=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+CONFIG_RTC_DRV_DS1307=y
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+# CONFIG_RTC_DRV_RX8025 is not set
+
+#
+# SPI RTC drivers
+#
+# CONFIG_RTC_DRV_M41T94 is not set
+# CONFIG_RTC_DRV_DS1305 is not set
+# CONFIG_RTC_DRV_DS1390 is not set
+# CONFIG_RTC_DRV_MAX6902 is not set
+# CONFIG_RTC_DRV_R9701 is not set
+# CONFIG_RTC_DRV_RS5C348 is not set
+# CONFIG_RTC_DRV_DS3234 is not set
+# CONFIG_RTC_DRV_PCF2123 is not set
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_MXC is not set
+CONFIG_RTC_DRV_IMXDI=y
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY 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=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_EXT4_FS=y
+# CONFIG_EXT4_FS_XATTR is not set
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD=y
+CONFIG_JBD2=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+# CONFIG_DNOTIFY is not set
+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 is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_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 is not set
+CONFIG_UBIFS_FS=y
+# CONFIG_UBIFS_FS_XATTR is not set
+# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
+CONFIG_UBIFS_FS_LZO=y
+CONFIG_UBIFS_FS_ZLIB=y
+# CONFIG_UBIFS_FS_DEBUG is not set
+# CONFIG_LOGFS is not set
+# CONFIG_CRAMFS is not set
+# 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_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+# CONFIG_SMB_FS is not set
+# CONFIG_CEPH_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 is not set
+CONFIG_MSDOS_PARTITION=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-15"
+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=y
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_NLS_ISO8859_2=y
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=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 is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_DEBUG_FS is not set
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_KERNEL is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_ARM_UNWIND is not set
+CONFIG_DEBUG_USER=y
+# CONFIG_OC_ETM is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_DEFAULT_SECURITY_SELINUX is not set
+# CONFIG_DEFAULT_SECURITY_SMACK is not set
+# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC 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 is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_GHASH is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# 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 is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# 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 is not set
+# 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=y
+# CONFIG_CRYPTO_ZLIB is not set
+CONFIG_CRYPTO_LZO=y
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+# CONFIG_CRC_CCITT is not set
+CONFIG_CRC16=y
+# 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_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
+CONFIG_GENERIC_ATOMIC64=y
diff --git a/recipes/linux/linux-2.6.35/vmx25/linux-2.6.35-vmx25-20110112.patch b/recipes/linux/linux-2.6.35/vmx25/linux-2.6.35-vmx25-20110112.patch
new file mode 100644 (file)
index 0000000..edbde2d
--- /dev/null
@@ -0,0 +1,28459 @@
+diff -urN linux.35.old/arch/arm/configs/vmx25_defconfig linux.35.new/arch/arm/configs/vmx25_defconfig
+--- linux.35.old/arch/arm/configs/vmx25_defconfig      1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/configs/vmx25_defconfig      2010-12-21 12:20:30.725765123 +0100
+@@ -0,0 +1,1866 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.35
++# Tue Dec 21 12:20:04 2010
++#
++CONFIG_ARM=y
++CONFIG_HAVE_PWM=y
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_GENERIC_GPIO=y
++CONFIG_GENERIC_TIME=y
++# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_HAVE_PROC_CPU=y
++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_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_NEED_DMA_MAP_STATE=y
++CONFIG_FIQ=y
++CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
++CONFIG_VECTORS_BASE=0xffff0000
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++CONFIG_CONSTRUCTORS=y
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_LOCK_KERNEL=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_CROSS_COMPILE=""
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_HAVE_KERNEL_GZIP=y
++CONFIG_HAVE_KERNEL_LZMA=y
++CONFIG_HAVE_KERNEL_LZO=y
++CONFIG_KERNEL_GZIP=y
++# CONFIG_KERNEL_BZIP2 is not set
++# CONFIG_KERNEL_LZMA is not set
++# CONFIG_KERNEL_LZO is not set
++# 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_TREE_RCU is not set
++# CONFIG_TREE_PREEMPT_RCU is not set
++CONFIG_TINY_RCU=y
++# CONFIG_TREE_RCU_TRACE is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=16
++# 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 is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_HOTPLUG=y
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_ELF_CORE=y
++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_HAVE_PERF_EVENTS=y
++CONFIG_PERF_USE_VMALLOC=y
++
++#
++# Kernel Performance Events And Counters
++#
++# CONFIG_PERF_EVENTS is not set
++# CONFIG_PERF_COUNTERS is not set
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++# CONFIG_SLUB is not set
++CONFIG_SLOB=y
++# CONFIG_PROFILING is not set
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++CONFIG_HAVE_CLK=y
++
++#
++# GCOV-based kernel profiling
++#
++# CONFIG_SLOW_WORK is not set
++CONFIG_HAVE_GENERIC_DMA_COHERENT=y
++CONFIG_RT_MUTEXES=y
++CONFIG_BASE_SMALL=0
++# CONFIG_MODULES is not set
++CONFIG_BLOCK=y
++# CONFIG_LBDAF is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_DEADLINE=y
++# CONFIG_IOSCHED_CFQ is not set
++CONFIG_DEFAULT_DEADLINE=y
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="deadline"
++# CONFIG_INLINE_SPIN_TRYLOCK is not set
++# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
++# CONFIG_INLINE_SPIN_LOCK is not set
++# CONFIG_INLINE_SPIN_LOCK_BH is not set
++# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
++# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
++# CONFIG_INLINE_SPIN_UNLOCK is not set
++# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
++# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
++# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
++# CONFIG_INLINE_READ_TRYLOCK is not set
++# CONFIG_INLINE_READ_LOCK is not set
++# CONFIG_INLINE_READ_LOCK_BH is not set
++# CONFIG_INLINE_READ_LOCK_IRQ is not set
++# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
++# CONFIG_INLINE_READ_UNLOCK is not set
++# CONFIG_INLINE_READ_UNLOCK_BH is not set
++# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
++# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
++# CONFIG_INLINE_WRITE_TRYLOCK is not set
++# CONFIG_INLINE_WRITE_LOCK is not set
++# CONFIG_INLINE_WRITE_LOCK_BH is not set
++# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
++# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
++# CONFIG_INLINE_WRITE_UNLOCK is not set
++# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
++# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
++# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
++# CONFIG_MUTEX_SPIN_ON_OWNER is not set
++# CONFIG_FREEZER is not set
++
++#
++# System Type
++#
++CONFIG_MMU=y
++# 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_VEXPRESS is not set
++# CONFIG_ARCH_AT91 is not set
++# CONFIG_ARCH_BCMRING is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CNS3XXX is not set
++# CONFIG_ARCH_GEMINI is not set
++# CONFIG_ARCH_EBSA110 is not set
++# CONFIG_ARCH_EP93XX is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++CONFIG_ARCH_MXC=y
++# CONFIG_ARCH_STMP3XXX 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_DOVE is not set
++# CONFIG_ARCH_KIRKWOOD is not set
++# CONFIG_ARCH_LOKI is not set
++# CONFIG_ARCH_MV78XX0 is not set
++# CONFIG_ARCH_ORION5X is not set
++# CONFIG_ARCH_MMP is not set
++# CONFIG_ARCH_KS8695 is not set
++# CONFIG_ARCH_NS9XXX is not set
++# CONFIG_ARCH_W90X900 is not set
++# CONFIG_ARCH_NUC93X is not set
++# CONFIG_ARCH_PNX4008 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_MSM is not set
++# CONFIG_ARCH_SHMOBILE 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_S5P6440 is not set
++# CONFIG_ARCH_S5P6442 is not set
++# CONFIG_ARCH_S5PC100 is not set
++# CONFIG_ARCH_S5PV210 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_U300 is not set
++# CONFIG_ARCH_U8500 is not set
++# CONFIG_ARCH_NOMADIK is not set
++# CONFIG_ARCH_DAVINCI is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_PLAT_SPEAR is not set
++CONFIG_IMX_HAVE_PLATFORM_FLEXCAN=y
++CONFIG_IMX_HAVE_PLATFORM_IMX_I2C=y
++CONFIG_IMX_HAVE_PLATFORM_IMX_UART=y
++CONFIG_IMX_HAVE_PLATFORM_MXC_NAND=y
++CONFIG_IMX_HAVE_PLATFORM_SPI_IMX=y
++
++#
++# Freescale MXC Implementations
++#
++# CONFIG_ARCH_MX1 is not set
++# CONFIG_ARCH_MX2 is not set
++CONFIG_ARCH_MX25=y
++# CONFIG_ARCH_MX3 is not set
++# CONFIG_ARCH_MXC91231 is not set
++# CONFIG_ARCH_MX5 is not set
++
++#
++# MX25 platforms:
++#
++# CONFIG_MACH_MX25_3DS is not set
++CONFIG_MACH_VMX25=y
++CONFIG_MACH_VMX_BASEBOARD=y
++# CONFIG_VMX_SD_ON_MODULE is not set
++CONFIG_VMX_SD_ON_BOARD=y
++CONFIG_MXC_SDMA_API=y
++CONFIG_MXC_IRQ_PRIOR=y
++CONFIG_MXC_PWM=y
++CONFIG_ARCH_MXC_IOMUX_V3=y
++CONFIG_ARCH_MXC_AUDMUX_V2=y
++CONFIG_MXC_SSI_PORTS=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_ARM926T=y
++CONFIG_CPU_32v5=y
++CONFIG_CPU_ABRT_EV5TJ=y
++CONFIG_CPU_PABRT_LEGACY=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_ARM_L1_CACHE_SHIFT=5
++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_NONE is not set
++# CONFIG_PREEMPT_VOLUNTARY is not set
++CONFIG_PREEMPT=y
++CONFIG_HZ=100
++CONFIG_AEABI=y
++# CONFIG_OABI_COMPAT is not set
++# 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=999999
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++# CONFIG_KSM is not set
++CONFIG_DEFAULT_MMAP_MIN_ADDR=4096
++CONFIG_ALIGNMENT_TRAP=y
++# CONFIG_UACCESS_WITH_MEMCPY is not set
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="console=ttymxc0,115200 mem=32M@0x80000000 mem=32M@0x90000000 ip=dhcp ubi.mtd=3 root=ubi0:rootfs rootfstype=ubifs otg_mode=host video=imxfb:VGA-16@60"
++# CONFIG_CMDLINE_FORCE is not set
++# 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_VFP is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_HAVE_AOUT=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=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 is not set
++# 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 is not set
++# 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_RDS is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_L2TP 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_IEEE802154 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=y
++CONFIG_CAN_RAW=y
++CONFIG_CAN_BCM=y
++
++#
++# CAN Device Drivers
++#
++# CONFIG_CAN_VCAN is not set
++CONFIG_CAN_DEV=y
++CONFIG_CAN_CALC_BITTIMING=y
++CONFIG_CAN_MCP251X=y
++CONFIG_HAVE_CAN_FLEXCAN=y
++CONFIG_CAN_FLEXCAN=y
++# CONFIG_CAN_SJA1000 is not set
++
++#
++# CAN USB interfaces
++#
++# CONFIG_CAN_EMS_USB is not set
++CONFIG_CAN_DEBUG_DEVICES=y
++# 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
++# CONFIG_CAIF is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
++CONFIG_DEVTMPFS=y
++# CONFIG_DEVTMPFS_MOUNT is not set
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_SYS_HYPERVISOR is not set
++
++#
++# MXC support drivers
++#
++
++#
++# i.MX ADC support
++#
++# CONFIG_IMX_ADC is not set
++CONFIG_CONNECTOR=y
++CONFIG_PROC_EVENTS=y
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=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 is not set
++# CONFIG_MTD_BLOCK is not set
++# CONFIG_MTD_BLOCK_RO is not set
++# 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_SM_FTL 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_DATAFLASH is not set
++CONFIG_MTD_M25P80=y
++# CONFIG_M25PXX_USE_FAST_READ is not set
++# CONFIG_MTD_SST25L is not set
++# 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_ECC=y
++# CONFIG_MTD_NAND_ECC_SMC is not set
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++# CONFIG_MTD_SM_COMMON is not set
++# CONFIG_MTD_NAND_MUSEUM_IDS is not set
++CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR=0xFF108018
++# 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_ONENAND is not set
++
++#
++# LPDDR flash memory drivers
++#
++# CONFIG_MTD_LPDDR is not set
++
++#
++# UBI - Unsorted block images
++#
++CONFIG_MTD_UBI=y
++CONFIG_MTD_UBI_WL_THRESHOLD=4096
++CONFIG_MTD_UBI_BEB_RESERVE=1
++CONFIG_MTD_UBI_GLUEBI=y
++
++#
++# UBI debugging options
++#
++# CONFIG_MTD_UBI_DEBUG is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_DRBD is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_MG_DISK is not set
++CONFIG_MISC_DEVICES=y
++# CONFIG_AD525X_DPOT is not set
++# CONFIG_ICS932S401 is not set
++# CONFIG_ENCLOSURE_SERVICES is not set
++# CONFIG_ISL29003 is not set
++# CONFIG_SENSORS_TSL2550 is not set
++# CONFIG_DS1682 is not set
++# CONFIG_TI_DAC7512 is not set
++# CONFIG_C2PORT is not set
++
++#
++# EEPROM support
++#
++CONFIG_EEPROM_AT24=y
++# CONFIG_EEPROM_AT25 is not set
++# CONFIG_EEPROM_LEGACY is not set
++# CONFIG_EEPROM_MAX6875 is not set
++# CONFIG_EEPROM_93CX6 is not set
++# CONFIG_IWMC3200TOP is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI_MOD=y
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++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=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++CONFIG_SCSI_MULTI_LUN=y
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++# CONFIG_SCSI_SCAN_ASYNC is not set
++
++#
++# 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_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_MICREL_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_ENC28J60 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_KS8842 is not set
++# CONFIG_KS8851 is not set
++# CONFIG_KS8851_MLL is not set
++CONFIG_FEC=y
++# CONFIG_FEC2 is not set
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++# CONFIG_WLAN 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_USB_IPHETH is not set
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++# CONFIG_INPUT_SPARSEKMAP is not set
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ADP5588 is not set
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_QT2160 is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++CONFIG_KEYBOARD_GPIO=y
++# CONFIG_KEYBOARD_TCA6416 is not set
++# CONFIG_KEYBOARD_MATRIX is not set
++# CONFIG_KEYBOARD_LM8323 is not set
++# CONFIG_KEYBOARD_MAX7359 is not set
++CONFIG_KEYBOARD_IMX=y
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_OPENCORES is not set
++# CONFIG_KEYBOARD_STOWAWAY is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++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_MOUSE_SYNAPTICS_I2C is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_ADS7846=y
++# CONFIG_TOUCHSCREEN_AD7877 is not set
++# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
++# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
++# CONFIG_TOUCHSCREEN_AD7879 is not set
++# CONFIG_TOUCHSCREEN_DYNAPRO is not set
++# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
++# CONFIG_TOUCHSCREEN_EETI 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_MCS5000 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_TSC=y
++# CONFIG_TOUCHSCREEN_WM97XX is not set
++# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
++# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
++# CONFIG_TOUCHSCREEN_TSC2007 is not set
++# CONFIG_TOUCHSCREEN_W90X900 is not set
++# CONFIG_TOUCHSCREEN_TPS6507X 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 is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++# CONFIG_N_GSM is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_MAX3100 is not set
++CONFIG_SERIAL_IMX=y
++CONFIG_SERIAL_IMX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++# CONFIG_SERIAL_TIMBERDALE is not set
++# CONFIG_SERIAL_ALTERA_JTAGUART is not set
++# CONFIG_SERIAL_ALTERA_UART is not set
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++# CONFIG_LEGACY_PTYS is not set
++# 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_RAMOOPS is not set
++CONFIG_I2C=y
++CONFIG_I2C_BOARDINFO=y
++# CONFIG_I2C_COMPAT is not set
++CONFIG_I2C_CHARDEV=y
++# CONFIG_I2C_HELPER_AUTO is not set
++# CONFIG_I2C_SMBUS is not set
++
++#
++# I2C Algorithms
++#
++# CONFIG_I2C_ALGOBIT is not set
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++
++#
++# I2C system bus drivers (mostly embedded / system-on-chip)
++#
++# CONFIG_I2C_DESIGNWARE is not set
++# CONFIG_I2C_GPIO is not set
++CONFIG_I2C_IMX=y
++# CONFIG_I2C_OCORES is not set
++# CONFIG_I2C_PCA_PLATFORM is not set
++# CONFIG_I2C_SIMTEC is not set
++# CONFIG_I2C_XILINX is not set
++
++#
++# External I2C/SMBus adapter drivers
++#
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_TAOS_EVM is not set
++# CONFIG_I2C_TINY_USB is not set
++
++#
++# Other I2C/SMBus bus drivers
++#
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++CONFIG_SPI=y
++CONFIG_SPI_MASTER=y
++
++#
++# SPI Master Controller Drivers
++#
++CONFIG_SPI_BITBANG=y
++# CONFIG_SPI_GPIO is not set
++CONFIG_SPI_IMX=y
++# CONFIG_SPI_XILINX is not set
++# CONFIG_SPI_DESIGNWARE is not set
++
++#
++# SPI Protocol Masters
++#
++CONFIG_SPI_SPIDEV=y
++# CONFIG_SPI_TLE62X0 is not set
++
++#
++# PPS support
++#
++# CONFIG_PPS is not set
++CONFIG_ARCH_REQUIRE_GPIOLIB=y
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++
++#
++# Memory mapped GPIO expanders:
++#
++# CONFIG_GPIO_IT8761E is not set
++
++#
++# I2C GPIO expanders:
++#
++# CONFIG_GPIO_MAX7300 is not set
++# CONFIG_GPIO_MAX732X is not set
++# CONFIG_GPIO_PCA953X is not set
++# CONFIG_GPIO_PCF857X is not set
++# CONFIG_GPIO_ADP5588 is not set
++
++#
++# PCI GPIO expanders:
++#
++
++#
++# SPI GPIO expanders:
++#
++# CONFIG_GPIO_MAX7301 is not set
++# CONFIG_GPIO_MCP23S08 is not set
++# CONFIG_GPIO_MC33880 is not set
++
++#
++# AC97 GPIO expanders:
++#
++
++#
++# MODULbus GPIO expanders:
++#
++CONFIG_W1=y
++CONFIG_W1_CON=y
++
++#
++# 1-wire Bus Masters
++#
++# CONFIG_W1_MASTER_DS2490 is not set
++# CONFIG_W1_MASTER_DS2482 is not set
++CONFIG_W1_MASTER_MXC=y
++# CONFIG_W1_MASTER_DS1WM is not set
++# CONFIG_W1_MASTER_GPIO is not set
++
++#
++# 1-wire Slaves
++#
++# CONFIG_W1_SLAVE_THERM is not set
++CONFIG_W1_SLAVE_SMEM=y
++# CONFIG_W1_SLAVE_DS2431 is not set
++# CONFIG_W1_SLAVE_DS2433 is not set
++# CONFIG_W1_SLAVE_DS2760 is not set
++# CONFIG_W1_SLAVE_BQ27000 is not set
++# CONFIG_POWER_SUPPLY is not set
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Native drivers
++#
++# CONFIG_SENSORS_AD7414 is not set
++# CONFIG_SENSORS_AD7418 is not set
++# CONFIG_SENSORS_ADCXX is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1029 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ADT7411 is not set
++# CONFIG_SENSORS_ADT7462 is not set
++# CONFIG_SENSORS_ADT7470 is not set
++# CONFIG_SENSORS_ADT7475 is not set
++# CONFIG_SENSORS_ASC7621 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_F71805F is not set
++# CONFIG_SENSORS_F71882FG is not set
++# CONFIG_SENSORS_F75375S is not set
++# CONFIG_SENSORS_G760A is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM70 is not set
++# CONFIG_SENSORS_LM73 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_LM93 is not set
++# CONFIG_SENSORS_LTC4215 is not set
++# CONFIG_SENSORS_LTC4245 is not set
++# CONFIG_SENSORS_LM95241 is not set
++# CONFIG_SENSORS_MAX1111 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_MAX6650 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_PC87427 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_SHT15 is not set
++# CONFIG_SENSORS_DME1737 is not set
++# CONFIG_SENSORS_EMC1403 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47M192 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_ADS7828 is not set
++# CONFIG_SENSORS_ADS7871 is not set
++# CONFIG_SENSORS_AMC6821 is not set
++# CONFIG_SENSORS_THMC50 is not set
++# CONFIG_SENSORS_TMP102 is not set
++# CONFIG_SENSORS_TMP401 is not set
++# CONFIG_SENSORS_TMP421 is not set
++# CONFIG_SENSORS_VT1211 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83791D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83793 is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83L786NG is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_SENSORS_LIS3_SPI is not set
++# CONFIG_SENSORS_LIS3_I2C is not set
++# CONFIG_THERMAL is not set
++CONFIG_WATCHDOG=y
++CONFIG_WATCHDOG_NOWAYOUT=y
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++# CONFIG_MAX63XX_WATCHDOG is not set
++CONFIG_IMX2_WDT=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++# CONFIG_MFD_SUPPORT is not set
++# CONFIG_REGULATOR is not set
++CONFIG_MEDIA_SUPPORT=y
++
++#
++# Multimedia core support
++#
++CONFIG_VIDEO_DEV=y
++CONFIG_VIDEO_V4L2_COMMON=y
++# CONFIG_VIDEO_ALLOW_V4L1 is not set
++CONFIG_VIDEO_V4L1_COMPAT=y
++# CONFIG_DVB_CORE is not set
++CONFIG_VIDEO_MEDIA=y
++
++#
++# Multimedia drivers
++#
++CONFIG_IR_CORE=y
++CONFIG_VIDEO_IR=y
++# CONFIG_RC_MAP is not set
++# CONFIG_IR_NEC_DECODER is not set
++# CONFIG_IR_RC5_DECODER is not set
++# CONFIG_IR_RC6_DECODER is not set
++# CONFIG_IR_JVC_DECODER is not set
++# CONFIG_IR_SONY_DECODER is not set
++# CONFIG_IR_IMON is not set
++CONFIG_MEDIA_TUNER=y
++CONFIG_MEDIA_TUNER_CUSTOMISE=y
++# CONFIG_MEDIA_TUNER_SIMPLE is not set
++# CONFIG_MEDIA_TUNER_TDA8290 is not set
++# CONFIG_MEDIA_TUNER_TDA827X is not set
++# CONFIG_MEDIA_TUNER_TDA18271 is not set
++# CONFIG_MEDIA_TUNER_TDA9887 is not set
++# CONFIG_MEDIA_TUNER_TEA5761 is not set
++# CONFIG_MEDIA_TUNER_TEA5767 is not set
++# CONFIG_MEDIA_TUNER_MT20XX is not set
++# CONFIG_MEDIA_TUNER_MT2060 is not set
++# CONFIG_MEDIA_TUNER_MT2266 is not set
++# CONFIG_MEDIA_TUNER_MT2131 is not set
++# CONFIG_MEDIA_TUNER_QT1010 is not set
++# CONFIG_MEDIA_TUNER_XC2028 is not set
++# CONFIG_MEDIA_TUNER_XC5000 is not set
++# CONFIG_MEDIA_TUNER_MXL5005S is not set
++# CONFIG_MEDIA_TUNER_MXL5007T is not set
++# CONFIG_MEDIA_TUNER_MC44S803 is not set
++# CONFIG_MEDIA_TUNER_MAX2165 is not set
++CONFIG_VIDEO_V4L2=y
++# CONFIG_VIDEO_CAPTURE_DRIVERS is not set
++# CONFIG_V4L_MEM2MEM_DRIVERS is not set
++CONFIG_RADIO_ADAPTERS=y
++# CONFIG_I2C_SI4713 is not set
++# CONFIG_RADIO_SI4713 is not set
++# CONFIG_USB_DSBR is not set
++# CONFIG_RADIO_SI470X is not set
++# CONFIG_USB_MR800 is not set
++# CONFIG_RADIO_TEA5764 is not set
++# CONFIG_RADIO_SAA7706H is not set
++# CONFIG_RADIO_TEF6862 is not set
++CONFIG_RADIO_SI4705=y
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++CONFIG_HAVE_FB_IMX=y
++# 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 is not set
++
++#
++# Frame buffer hardware drivers
++#
++CONFIG_FB_IMX=y
++# CONFIG_FB_UVESA is not set
++# 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=y
++# CONFIG_LCD_CLASS_DEVICE is not set
++CONFIG_BACKLIGHT_CLASS_DEVICE=y
++# CONFIG_BACKLIGHT_GENERIC is not set
++CONFIG_BACKLIGHT_PWM=y
++# CONFIG_BACKLIGHT_ADP8860 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=y
++CONFIG_FONT_8x8=y
++# CONFIG_FONT_8x16 is not set
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_7x14 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++# CONFIG_FONT_MINI_4x6 is not set
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_10x18 is not set
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_LOGO_LINUX_CLUT224=y
++CONFIG_SOUND=y
++CONFIG_SOUND_OSS_CORE=y
++# CONFIG_SOUND_OSS_CORE_PRECLAIM is not set
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++CONFIG_SND_JACK=y
++# CONFIG_SND_SEQUENCER is not set
++CONFIG_SND_OSSEMUL=y
++CONFIG_SND_MIXER_OSS=y
++CONFIG_SND_PCM_OSS=y
++CONFIG_SND_PCM_OSS_PLUGINS=y
++CONFIG_SND_DYNAMIC_MINORS=y
++CONFIG_SND_SUPPORT_OLD_API=y
++# CONFIG_SND_VERBOSE_PROCFS is not set
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++# CONFIG_SND_RAWMIDI_SEQ is not set
++# CONFIG_SND_OPL3_LIB_SEQ is not set
++# CONFIG_SND_OPL4_LIB_SEQ is not set
++# CONFIG_SND_SBAWE_SEQ is not set
++# CONFIG_SND_EMU10K1_SEQ is not set
++# CONFIG_SND_DRIVERS is not set
++# CONFIG_SND_ARM is not set
++# CONFIG_SND_SPI is not set
++# CONFIG_SND_USB is not set
++CONFIG_SND_SOC=y
++CONFIG_SND_SOC_AC97_BUS=y
++CONFIG_SND_IMX_SOC=y
++CONFIG_SND_SOC_IMX_3STACK_SGTL5000=y
++CONFIG_SND_SOC_I2C_AND_SPI=y
++# CONFIG_SND_SOC_ALL_CODECS is not set
++CONFIG_SND_SOC_SGTL5000=y
++# CONFIG_SOUND_PRIME is not set
++CONFIG_AC97_BUS=y
++CONFIG_HID_SUPPORT=y
++CONFIG_HID=y
++# CONFIG_HIDRAW is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++# CONFIG_HID_PID is not set
++# CONFIG_USB_HIDDEV is not set
++
++#
++# Special HID drivers
++#
++# CONFIG_HID_3M_PCT is not set
++# CONFIG_HID_A4TECH is not set
++# CONFIG_HID_APPLE is not set
++# CONFIG_HID_BELKIN is not set
++# CONFIG_HID_CANDO is not set
++# CONFIG_HID_CHERRY is not set
++# CONFIG_HID_CHICONY is not set
++# CONFIG_HID_PRODIKEYS is not set
++# CONFIG_HID_CYPRESS is not set
++# CONFIG_HID_DRAGONRISE is not set
++# CONFIG_HID_EGALAX is not set
++# CONFIG_HID_EZKEY is not set
++# CONFIG_HID_KYE is not set
++# CONFIG_HID_GYRATION is not set
++# CONFIG_HID_TWINHAN is not set
++# CONFIG_HID_KENSINGTON is not set
++# CONFIG_HID_LOGITECH is not set
++# CONFIG_HID_MICROSOFT is not set
++# CONFIG_HID_MOSART is not set
++# CONFIG_HID_MONTEREY is not set
++# CONFIG_HID_NTRIG is not set
++# CONFIG_HID_ORTEK is not set
++# CONFIG_HID_PANTHERLORD is not set
++# CONFIG_HID_PETALYNX is not set
++# CONFIG_HID_PICOLCD is not set
++# CONFIG_HID_QUANTA is not set
++# CONFIG_HID_ROCCAT is not set
++# CONFIG_HID_ROCCAT_KONE is not set
++# CONFIG_HID_SAMSUNG is not set
++# CONFIG_HID_SONY is not set
++# CONFIG_HID_STANTUM is not set
++# CONFIG_HID_SUNPLUS is not set
++# CONFIG_HID_GREENASIA is not set
++# CONFIG_HID_SMARTJOYPLUS is not set
++# CONFIG_HID_TOPSEED is not set
++# CONFIG_HID_THRUSTMASTER is not set
++# CONFIG_HID_ZEROPLUS is not set
++# CONFIG_HID_ZYDACRON 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=y
++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_OTG_WHITELIST is not set
++# CONFIG_USB_OTG_BLACKLIST_HUB is not set
++# CONFIG_USB_MON is not set
++# 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=y
++CONFIG_USB_EHCI_ROOT_HUB_TT=y
++CONFIG_USB_EHCI_TT_NEWSCHED=y
++CONFIG_USB_EHCI_MXC=y
++# CONFIG_USB_OXU210HP_HCD is not set
++# CONFIG_USB_ISP116X_HCD is not set
++# CONFIG_USB_ISP1760_HCD is not set
++# CONFIG_USB_ISP1362_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
++# CONFIG_USB_MUSB_HDRC is not set
++# CONFIG_USB_GADGET_MUSB_HDRC is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_ACM is not set
++# 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=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++# 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 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_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_GADGET=y
++CONFIG_USB_GADGET_DEBUG_FILES=y
++CONFIG_USB_GADGET_VBUS_DRAW=300
++CONFIG_USB_GADGET_SELECTED=y
++# CONFIG_USB_GADGET_AT91 is not set
++# CONFIG_USB_GADGET_ATMEL_USBA is not set
++CONFIG_USB_GADGET_FSL_USB2=y
++CONFIG_USB_FSL_USB2=y
++# CONFIG_USB_GADGET_LH7A40X is not set
++# CONFIG_USB_GADGET_OMAP is not set
++# CONFIG_USB_GADGET_PXA25X is not set
++# CONFIG_USB_GADGET_R8A66597 is not set
++# CONFIG_USB_GADGET_PXA27X is not set
++# CONFIG_USB_GADGET_S3C_HSOTG is not set
++# CONFIG_USB_GADGET_IMX is not set
++# CONFIG_USB_GADGET_S3C2410 is not set
++# CONFIG_USB_GADGET_M66592 is not set
++# CONFIG_USB_GADGET_AMD5536UDC is not set
++# CONFIG_USB_GADGET_FSL_QE is not set
++# CONFIG_USB_GADGET_CI13XXX is not set
++# CONFIG_USB_GADGET_NET2280 is not set
++# CONFIG_USB_GADGET_GOKU is not set
++# CONFIG_USB_GADGET_LANGWELL is not set
++# CONFIG_USB_GADGET_DUMMY_HCD is not set
++CONFIG_USB_GADGET_DUALSPEED=y
++# CONFIG_USB_ZERO is not set
++# CONFIG_USB_AUDIO is not set
++CONFIG_USB_ETH=y
++CONFIG_USB_ETH_RNDIS=y
++# CONFIG_USB_ETH_EEM is not set
++# CONFIG_USB_GADGETFS is not set
++# CONFIG_USB_FUNCTIONFS is not set
++# CONFIG_USB_FILE_STORAGE is not set
++# CONFIG_USB_MASS_STORAGE is not set
++# CONFIG_USB_G_SERIAL is not set
++# CONFIG_USB_MIDI_GADGET is not set
++# CONFIG_USB_G_PRINTER is not set
++# CONFIG_USB_CDC_COMPOSITE is not set
++# CONFIG_USB_G_NOKIA is not set
++# CONFIG_USB_G_MULTI is not set
++# CONFIG_USB_G_HID is not set
++# CONFIG_USB_G_WEBCAM is not set
++
++#
++# OTG and related infrastructure
++#
++# CONFIG_USB_GPIO_VBUS is not set
++# CONFIG_USB_ULPI is not set
++# CONFIG_NOP_USB_XCEIV is not set
++CONFIG_MMC=y
++# CONFIG_MMC_DEBUG is not set
++# CONFIG_MMC_UNSAFE_RESUME is not set
++
++#
++# MMC/SD/SDIO Card Drivers
++#
++CONFIG_MMC_BLOCK=y
++CONFIG_MMC_BLOCK_BOUNCE=y
++# CONFIG_SDIO_UART is not set
++# CONFIG_MMC_TEST is not set
++
++#
++# MMC/SD/SDIO Host Controller Drivers
++#
++CONFIG_MMC_SDHCI=y
++# CONFIG_MMC_SDHCI_PLTFM is not set
++# CONFIG_MMC_MXC is not set
++# CONFIG_MMC_SPI is not set
++CONFIG_MMC_SDHCI_MXC=y
++# CONFIG_MMC_SDHCI_MXC_SELECT2 is not set
++# CONFIG_MMC_SDHCI_MXC_PIO_MODE is not set
++# CONFIG_MEMSTICK is not set
++CONFIG_NEW_LEDS=y
++CONFIG_LEDS_CLASS=y
++
++#
++# LED drivers
++#
++# CONFIG_LEDS_PCA9532 is not set
++CONFIG_LEDS_GPIO=y
++CONFIG_LEDS_GPIO_PLATFORM=y
++# CONFIG_LEDS_LP3944 is not set
++# CONFIG_LEDS_PCA955X is not set
++# CONFIG_LEDS_DAC124S085 is not set
++# CONFIG_LEDS_PWM is not set
++# CONFIG_LEDS_BD2802 is not set
++# CONFIG_LEDS_LT3593 is not set
++CONFIG_LEDS_TRIGGERS=y
++
++#
++# LED Triggers
++#
++CONFIG_LEDS_TRIGGER_TIMER=y
++CONFIG_LEDS_TRIGGER_HEARTBEAT=y
++# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
++CONFIG_LEDS_TRIGGER_GPIO=y
++CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
++
++#
++# iptables trigger is under Netfilter config (LED target)
++#
++# CONFIG_ACCESSIBILITY is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++CONFIG_RTC_HCTOSYS=y
++CONFIG_RTC_HCTOSYS_DEVICE="rtc1"
++# CONFIG_RTC_DEBUG is not set
++
++#
++# RTC interfaces
++#
++CONFIG_RTC_INTF_SYSFS=y
++CONFIG_RTC_INTF_PROC=y
++CONFIG_RTC_INTF_DEV=y
++# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
++# CONFIG_RTC_DRV_TEST is not set
++
++#
++# I2C RTC drivers
++#
++CONFIG_RTC_DRV_DS1307=y
++# CONFIG_RTC_DRV_DS1374 is not set
++# CONFIG_RTC_DRV_DS1672 is not set
++# CONFIG_RTC_DRV_MAX6900 is not set
++# CONFIG_RTC_DRV_RS5C372 is not set
++# CONFIG_RTC_DRV_ISL1208 is not set
++# CONFIG_RTC_DRV_X1205 is not set
++# CONFIG_RTC_DRV_PCF8563 is not set
++# CONFIG_RTC_DRV_PCF8583 is not set
++# CONFIG_RTC_DRV_M41T80 is not set
++# CONFIG_RTC_DRV_BQ32K is not set
++# CONFIG_RTC_DRV_S35390A is not set
++# CONFIG_RTC_DRV_FM3130 is not set
++# CONFIG_RTC_DRV_RX8581 is not set
++# CONFIG_RTC_DRV_RX8025 is not set
++
++#
++# SPI RTC drivers
++#
++# CONFIG_RTC_DRV_M41T94 is not set
++# CONFIG_RTC_DRV_DS1305 is not set
++# CONFIG_RTC_DRV_DS1390 is not set
++# CONFIG_RTC_DRV_MAX6902 is not set
++# CONFIG_RTC_DRV_R9701 is not set
++# CONFIG_RTC_DRV_RS5C348 is not set
++# CONFIG_RTC_DRV_DS3234 is not set
++# CONFIG_RTC_DRV_PCF2123 is not set
++
++#
++# Platform RTC drivers
++#
++# CONFIG_RTC_DRV_CMOS is not set
++# CONFIG_RTC_DRV_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_MSM6242 is not set
++# CONFIG_RTC_MXC is not set
++CONFIG_RTC_DRV_IMXDI=y
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_RP5C01 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++# CONFIG_DMADEVICES is not set
++# CONFIG_AUXDISPLAY 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=y
++# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
++# CONFIG_EXT3_FS_XATTR is not set
++CONFIG_EXT4_FS=y
++# CONFIG_EXT4_FS_XATTR is not set
++# CONFIG_EXT4_DEBUG is not set
++CONFIG_JBD=y
++CONFIG_JBD2=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_BTRFS_FS is not set
++# CONFIG_NILFS2_FS is not set
++CONFIG_FILE_LOCKING=y
++CONFIG_FSNOTIFY=y
++# CONFIG_DNOTIFY is not set
++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 is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_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 is not set
++CONFIG_UBIFS_FS=y
++# CONFIG_UBIFS_FS_XATTR is not set
++# CONFIG_UBIFS_FS_ADVANCED_COMPR is not set
++CONFIG_UBIFS_FS_LZO=y
++CONFIG_UBIFS_FS_ZLIB=y
++# CONFIG_UBIFS_FS_DEBUG is not set
++# CONFIG_LOGFS is not set
++# CONFIG_CRAMFS is not set
++# 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_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++CONFIG_ROOT_NFS=y
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CEPH_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 is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-15"
++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=y
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++CONFIG_NLS_ISO8859_1=y
++CONFIG_NLS_ISO8859_2=y
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=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 is not set
++# CONFIG_STRIP_ASM_SYMS is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++# CONFIG_DEBUG_FS is not set
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_MEMORY_INIT is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_LATENCYTOP is not set
++# CONFIG_SYSCTL_SYSCALL_CHECK is not set
++CONFIG_HAVE_FUNCTION_TRACER=y
++CONFIG_TRACING_SUPPORT=y
++# CONFIG_FTRACE is not set
++# CONFIG_ATOMIC64_SELFTEST is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_ARM_UNWIND is not set
++CONFIG_DEBUG_USER=y
++# CONFIG_OC_ETM is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_DEFAULT_SECURITY_SELINUX is not set
++# CONFIG_DEFAULT_SECURITY_SMACK is not set
++# CONFIG_DEFAULT_SECURITY_TOMOYO is not set
++CONFIG_DEFAULT_SECURITY_DAC=y
++CONFIG_DEFAULT_SECURITY=""
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++CONFIG_CRYPTO_ALGAPI=y
++CONFIG_CRYPTO_ALGAPI2=y
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_MANAGER2 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC 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 is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++# CONFIG_CRYPTO_VMAC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_GHASH is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# 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 is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# 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 is not set
++# 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=y
++# CONFIG_CRYPTO_ZLIB is not set
++CONFIG_CRYPTO_LZO=y
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++# CONFIG_BINARY_PRINTF is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_RATIONAL=y
++CONFIG_GENERIC_FIND_LAST_BIT=y
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC16=y
++# 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_LZO_COMPRESS=y
++CONFIG_LZO_DECOMPRESS=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_IOPORT=y
++CONFIG_HAS_DMA=y
++CONFIG_NLATTR=y
++CONFIG_GENERIC_ATOMIC64=y
+diff -urN linux.35.old/arch/arm/mach-mx25/clock.c linux.35.new/arch/arm/mach-mx25/clock.c
+--- linux.35.old/arch/arm/mach-mx25/clock.c    2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/mach-mx25/clock.c    2010-12-03 09:51:55.345346913 +0100
+@@ -51,6 +51,7 @@
+ #define CCM_LTR1      0x44
+ #define CCM_LTR2      0x48
+ #define CCM_LTR3      0x4c
++#define CCM_MCR               0x64
+ static unsigned long get_rate_mpll(void)
+ {
+@@ -72,7 +73,7 @@
+       unsigned long rate = get_rate_mpll();
+       if (cctl & (1 << 14))
+-              rate = (rate * 3) >> 1;
++              rate = (rate * 3) >> 2;
+       return rate / ((cctl >> 30) + 1);
+ }
+@@ -96,10 +97,10 @@
+       unsigned long val = (readl(CRM_BASE + CCM_PCDR0 + reg) >> ofs) & 0x3f;
+       unsigned long fref;
+-      if (readl(CRM_BASE + 0x64) & (1 << per))
++      if (readl(CRM_BASE + CCM_MCR) & (1 << per))
+               fref = get_rate_upll();
+       else
+-              fref = get_rate_ipg(NULL);
++              fref = get_rate_ahb(NULL);
+       return fref / (val + 1);
+ }
+@@ -109,11 +110,26 @@
+       return get_rate_per(15);
+ }
++static unsigned long get_rate_ssi2(struct clk *clk)
++{
++      return get_rate_per(14);
++}
++
++static unsigned long get_rate_ssi1(struct clk *clk)
++{
++      return get_rate_per(13);
++}
++
+ static unsigned long get_rate_i2c(struct clk *clk)
+ {
+       return get_rate_per(6);
+ }
++static unsigned long get_rate_owire(struct clk *clk)
++{
++      return get_rate_per(9);
++}
++
+ static unsigned long get_rate_nfc(struct clk *clk)
+ {
+       return get_rate_per(8);
+@@ -129,9 +145,41 @@
+       return get_rate_per(7);
+ }
++static unsigned long get_rate_esdhc1(struct clk *clk)
++{
++      return get_rate_per(3);
++}
++
++static unsigned long get_rate_esdhc2(struct clk *clk)
++{
++      return get_rate_per(4);
++}
++
++static unsigned long get_rate_csi(struct clk *clk)
++{
++      return get_rate_per(0);
++}
++
+ static unsigned long get_rate_otg(struct clk *clk)
+ {
+-      return 48000000; /* FIXME */
++      unsigned long cctl = readl(CRM_BASE + CCM_CCTL);
++      unsigned long rate = get_rate_upll();
++
++      return (cctl & (1 << 23)) ? 0 : rate / ((0x3F & (cctl >> 16)) + 1);
++}
++
++static int set_rate_otg(struct clk *clk, unsigned long rate)
++{
++      u32 cctl = __raw_readl(CRM_BASE+CCM_CCTL) & ~(0x3f << 16);
++      unsigned long fref = get_rate_upll();
++      u32 usbdiv = (fref / rate) - 1;
++
++      if (usbdiv > 0x3f) {
++              return -1;
++      }
++      cctl |= usbdiv << 16;
++      __raw_writel(cctl, CRM_BASE+CCM_CCTL);
++      return 0;
+ }
+ static int clk_cgcr_enable(struct clk *clk)
+@@ -154,6 +202,10 @@
+       __raw_writel(reg, clk->enable_reg);
+ }
++static struct clk ahb_clk = {
++      .get_rate       = get_rate_ahb,
++};
++
+ #define DEFINE_CLOCK(name, i, er, es, gr, sr, s)      \
+       static struct clk name = {                      \
+               .id             = i,                    \
+@@ -168,19 +220,23 @@
+ DEFINE_CLOCK(gpt_clk,    0, CCM_CGCR0,  5, get_rate_gpt, NULL, NULL);
+ DEFINE_CLOCK(uart_per_clk, 0, CCM_CGCR0, 15, get_rate_uart, NULL, NULL);
++DEFINE_CLOCK(ssi1_per_clk, 0, CCM_CGCR0, 13, get_rate_ipg, NULL, NULL);
++DEFINE_CLOCK(ssi2_per_clk, 0, CCM_CGCR0, 14, get_rate_ipg, NULL, NULL);
+ DEFINE_CLOCK(cspi1_clk,  0, CCM_CGCR1,  5, get_rate_ipg, NULL, NULL);
+ DEFINE_CLOCK(cspi2_clk,  0, CCM_CGCR1,  6, get_rate_ipg, NULL, NULL);
+ DEFINE_CLOCK(cspi3_clk,  0, CCM_CGCR1,  7, get_rate_ipg, NULL, NULL);
+ DEFINE_CLOCK(fec_ahb_clk, 0, CCM_CGCR0, 23, NULL,      NULL, NULL);
+ DEFINE_CLOCK(lcdc_ahb_clk, 0, CCM_CGCR0, 24, NULL,     NULL, NULL);
+ DEFINE_CLOCK(lcdc_per_clk, 0, CCM_CGCR0,  7, NULL,     NULL, &lcdc_ahb_clk);
++DEFINE_CLOCK(csi_ahb_clk, 0, CCM_CGCR0, 18, get_rate_csi, NULL, NULL);
++DEFINE_CLOCK(csi_per_clk, 0, CCM_CGCR0, 0, get_rate_csi, NULL, &csi_ahb_clk);
+ DEFINE_CLOCK(uart1_clk,  0, CCM_CGCR2, 14, get_rate_uart, NULL, &uart_per_clk);
+ DEFINE_CLOCK(uart2_clk,  0, CCM_CGCR2, 15, get_rate_uart, NULL, &uart_per_clk);
+ DEFINE_CLOCK(uart3_clk,  0, CCM_CGCR2, 16, get_rate_uart, NULL, &uart_per_clk);
+ DEFINE_CLOCK(uart4_clk,  0, CCM_CGCR2, 17, get_rate_uart, NULL, &uart_per_clk);
+ DEFINE_CLOCK(uart5_clk,  0, CCM_CGCR2, 18, get_rate_uart, NULL, &uart_per_clk);
+ DEFINE_CLOCK(nfc_clk,    0, CCM_CGCR0,  8, get_rate_nfc, NULL, NULL);
+-DEFINE_CLOCK(usbotg_clk, 0, CCM_CGCR0, 28, get_rate_otg, NULL, NULL);
++DEFINE_CLOCK(usbotg_clk, 0, CCM_CGCR0, 28, get_rate_otg, set_rate_otg, NULL);
+ DEFINE_CLOCK(pwm1_clk,         0, CCM_CGCR1, 31, get_rate_ipg, NULL, NULL);
+ DEFINE_CLOCK(pwm2_clk,         0, CCM_CGCR2,  0, get_rate_ipg, NULL, NULL);
+ DEFINE_CLOCK(pwm3_clk,         0, CCM_CGCR2,  1, get_rate_ipg, NULL, NULL);
+@@ -191,6 +247,23 @@
+ DEFINE_CLOCK(fec_clk,  0, CCM_CGCR1, 15, get_rate_ipg, NULL, &fec_ahb_clk);
+ DEFINE_CLOCK(dryice_clk, 0, CCM_CGCR1,  8, get_rate_ipg, NULL, NULL);
+ DEFINE_CLOCK(lcdc_clk,         0, CCM_CGCR1, 29, get_rate_lcdc, NULL, &lcdc_per_clk);
++DEFINE_CLOCK(wdt_clk,    0, CCM_CGCR2, 19, get_rate_ipg, NULL,  NULL);
++DEFINE_CLOCK(esdhc1_ahb_clk, 0, CCM_CGCR0, 21, NULL, NULL, NULL);
++DEFINE_CLOCK(esdhc1_per_clk, 0, CCM_CGCR0, 3, NULL, NULL, &esdhc1_ahb_clk);
++DEFINE_CLOCK(esdhc1_clk,     0, CCM_CGCR1, 13, get_rate_esdhc1, NULL, &esdhc1_per_clk);
++DEFINE_CLOCK(esdhc2_ahb_clk, 1, CCM_CGCR0, 22, NULL, NULL, NULL);
++DEFINE_CLOCK(esdhc2_per_clk, 1, CCM_CGCR0, 4, NULL, NULL, &esdhc2_ahb_clk);
++DEFINE_CLOCK(esdhc2_clk,     1, CCM_CGCR1, 14, get_rate_esdhc2, NULL, &esdhc2_per_clk);
++DEFINE_CLOCK(sdma_ahb_clk,   0, CCM_CGCR0, 26, NULL, NULL, NULL);
++DEFINE_CLOCK(sdma_clk,       0, CCM_CGCR2,  6, get_rate_ipg, NULL, &sdma_ahb_clk);
++DEFINE_CLOCK(ssi1_clk,  0, CCM_CGCR2, 11, get_rate_ssi1, NULL, &ssi1_per_clk);
++DEFINE_CLOCK(ssi2_clk,  1, CCM_CGCR2, 12, get_rate_ssi2, NULL, &ssi2_per_clk);
++DEFINE_CLOCK(audmux_clk, 0, CCM_CGCR1, 0, NULL, NULL, NULL);
++DEFINE_CLOCK(csi_clk,    0, CCM_CGCR1,  4, get_rate_csi, NULL,  &csi_per_clk);
++DEFINE_CLOCK(can1_clk,         0, CCM_CGCR1,  2, get_rate_ipg, NULL, NULL);
++DEFINE_CLOCK(can2_clk,         0, CCM_CGCR1,  3, get_rate_ipg, NULL, NULL);
++DEFINE_CLOCK(owire_clk,    0, CCM_CGCR0, 9, get_rate_owire, NULL, NULL);
++
+ #define _REGISTER_CLOCK(d, n, c)      \
+       {                               \
+@@ -200,6 +273,8 @@
+       },
+ static struct clk_lookup lookups[] = {
++      _REGISTER_CLOCK(NULL, "ahb", ahb_clk)
++      _REGISTER_CLOCK(NULL, "sdma", sdma_clk)
+       _REGISTER_CLOCK("imx-uart.0", NULL, uart1_clk)
+       _REGISTER_CLOCK("imx-uart.1", NULL, uart2_clk)
+       _REGISTER_CLOCK("imx-uart.2", NULL, uart3_clk)
+@@ -217,14 +292,25 @@
+       _REGISTER_CLOCK("mxc_pwm.1", NULL, pwm2_clk)
+       _REGISTER_CLOCK("mxc_pwm.2", NULL, pwm3_clk)
+       _REGISTER_CLOCK("mxc_pwm.3", NULL, pwm4_clk)
+-      _REGISTER_CLOCK("mxc-keypad", NULL, kpp_clk)
+-      _REGISTER_CLOCK("mx25-adc", NULL, tsc_clk)
++      _REGISTER_CLOCK("imx-keypad", NULL, kpp_clk)
++      _REGISTER_CLOCK("imx_adc.0", "tsc_clk", tsc_clk)
++      _REGISTER_CLOCK("imx-tsc.0", NULL, tsc_clk)
+       _REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
+       _REGISTER_CLOCK("imx-i2c.1", NULL, i2c_clk)
+       _REGISTER_CLOCK("imx-i2c.2", NULL, i2c_clk)
+       _REGISTER_CLOCK("fec.0", NULL, fec_clk)
+       _REGISTER_CLOCK("imxdi_rtc.0", NULL, dryice_clk)
+       _REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
++      _REGISTER_CLOCK("imx-wdt.0", NULL, wdt_clk)
++      _REGISTER_CLOCK("sdhci.0", NULL, esdhc1_clk)
++      _REGISTER_CLOCK("sdhci.1", NULL, esdhc2_clk)
++      _REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
++      _REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
++      _REGISTER_CLOCK("mx2-camera.0", NULL, csi_clk)
++      _REGISTER_CLOCK(NULL, "audmux", audmux_clk)
++      _REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
++      _REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
++      _REGISTER_CLOCK("mxc_w1.0", NULL, owire_clk)
+ };
+ int __init mx25_clocks_init(void)
+@@ -244,5 +330,25 @@
+       mxc_timer_init(&gpt_clk, MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
++      /* Debug info */
++      pr_info("Fin:  %3lu.%03luMHz\n", \
++              (unsigned long) (24000000 / 1000000),
++              (unsigned long) (24000000 / 1000 % 1000));
++      pr_info("MPLL: %3lu.%03luMHz\n", \
++              get_rate_mpll() / 1000000,
++              get_rate_mpll() / 1000 % 1000);
++      pr_info("UPLL: %3lu.%03luMHz\n", \
++              get_rate_upll() / 1000000,
++              get_rate_upll() / 1000 % 1000);
++      pr_info("CPU:  %3lu.%03luMHz\n", \
++              get_rate_arm(NULL) / 1000000,
++              get_rate_arm(NULL) / 1000 % 1000);
++      pr_info("AHB:  %3lu.%03luMHz\n", \
++              get_rate_ahb(NULL) / 1000000,
++              get_rate_ahb(NULL) / 1000 % 1000);
++      pr_info("IPG:  %3lu.%03luMHz\n", \
++              get_rate_ipg(NULL) / 1000000,
++              get_rate_ipg(NULL) / 1000 % 1000);
++
+       return 0;
+ }
+diff -urN linux.35.old/arch/arm/mach-mx25/devices.c linux.35.new/arch/arm/mach-mx25/devices.c
+--- linux.35.old/arch/arm/mach-mx25/devices.c  2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/mach-mx25/devices.c  2010-12-03 09:51:55.345346913 +0100
+@@ -21,103 +21,59 @@
+ #include <linux/gpio.h>
+ #include <mach/mx25.h>
+ #include <mach/irqs.h>
++#include <mach/sdma.h>
+-static struct resource uart0[] = {
+-      {
+-              .start = 0x43f90000,
+-              .end = 0x43f93fff,
+-              .flags = IORESOURCE_MEM,
+-      }, {
+-              .start = 45,
+-              .end = 45,
+-              .flags = IORESOURCE_IRQ,
+-      },
+-};
+-
+-struct platform_device mxc_uart_device0 = {
+-      .name = "imx-uart",
+-      .id = 0,
+-      .resource = uart0,
+-      .num_resources = ARRAY_SIZE(uart0),
+-};
+-
+-static struct resource uart1[] = {
+-      {
+-              .start = 0x43f94000,
+-              .end = 0x43f97fff,
+-              .flags = IORESOURCE_MEM,
+-      }, {
+-              .start = 32,
+-              .end = 32,
+-              .flags = IORESOURCE_IRQ,
+-      },
+-};
+-
+-struct platform_device mxc_uart_device1 = {
+-      .name = "imx-uart",
+-      .id = 1,
+-      .resource = uart1,
+-      .num_resources = ARRAY_SIZE(uart1),
+-};
+-
+-static struct resource uart2[] = {
+-      {
+-              .start = 0x5000c000,
+-              .end = 0x5000ffff,
+-              .flags = IORESOURCE_MEM,
+-      }, {
+-              .start = 18,
+-              .end = 18,
+-              .flags = IORESOURCE_IRQ,
+-      },
+-};
+-
+-struct platform_device mxc_uart_device2 = {
+-      .name = "imx-uart",
+-      .id = 2,
+-      .resource = uart2,
+-      .num_resources = ARRAY_SIZE(uart2),
+-};
+-
+-static struct resource uart3[] = {
+-      {
+-              .start = 0x50008000,
+-              .end = 0x5000bfff,
+-              .flags = IORESOURCE_MEM,
+-      }, {
+-              .start = 5,
+-              .end = 5,
+-              .flags = IORESOURCE_IRQ,
+-      },
+-};
+-
+-struct platform_device mxc_uart_device3 = {
+-      .name = "imx-uart",
+-      .id = 3,
+-      .resource = uart3,
+-      .num_resources = ARRAY_SIZE(uart3),
+-};
++#include "sdma_script_code.h"
+-static struct resource uart4[] = {
+-      {
+-              .start = 0x5002c000,
+-              .end = 0x5002ffff,
+-              .flags = IORESOURCE_MEM,
+-      }, {
+-              .start = 40,
+-              .end = 40,
+-              .flags = IORESOURCE_IRQ,
+-      },
+-};
+-
+-struct platform_device mxc_uart_device4 = {
+-      .name = "imx-uart",
+-      .id = 4,
+-      .resource = uart4,
+-      .num_resources = ARRAY_SIZE(uart4),
+-};
+-
+-#define MX25_OTG_BASE_ADDR 0x53FF4000
++void mxc_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;
++}
+ static u64 otg_dmamask = DMA_BIT_MASK(32);
+@@ -181,63 +137,6 @@
+       .num_resources = ARRAY_SIZE(mxc_usbh2_resources),
+ };
+-static struct resource mxc_spi_resources0[] = {
+-      {
+-             .start = 0x43fa4000,
+-             .end = 0x43fa7fff,
+-             .flags = IORESOURCE_MEM,
+-      }, {
+-             .start = 14,
+-             .end = 14,
+-             .flags = IORESOURCE_IRQ,
+-      },
+-};
+-
+-struct platform_device mxc_spi_device0 = {
+-      .name = "spi_imx",
+-      .id = 0,
+-      .num_resources = ARRAY_SIZE(mxc_spi_resources0),
+-      .resource = mxc_spi_resources0,
+-};
+-
+-static struct resource mxc_spi_resources1[] = {
+-      {
+-             .start = 0x50010000,
+-             .end = 0x50013fff,
+-             .flags = IORESOURCE_MEM,
+-      }, {
+-             .start = 13,
+-             .end = 13,
+-             .flags = IORESOURCE_IRQ,
+-      },
+-};
+-
+-struct platform_device mxc_spi_device1 = {
+-      .name = "spi_imx",
+-      .id = 1,
+-      .num_resources = ARRAY_SIZE(mxc_spi_resources1),
+-      .resource = mxc_spi_resources1,
+-};
+-
+-static struct resource mxc_spi_resources2[] = {
+-      {
+-             .start = 0x50004000,
+-             .end = 0x50007fff,
+-             .flags = IORESOURCE_MEM,
+-      }, {
+-             .start = 0,
+-             .end = 0,
+-             .flags = IORESOURCE_IRQ,
+-      },
+-};
+-
+-struct platform_device mxc_spi_device2 = {
+-      .name = "spi_imx",
+-      .id = 2,
+-      .num_resources = ARRAY_SIZE(mxc_spi_resources2),
+-      .resource = mxc_spi_resources2,
+-};
+-
+ static struct resource mxc_pwm_resources0[] = {
+       {
+               .start  = 0x53fe0000,
+@@ -308,7 +207,7 @@
+ };
+ struct platform_device mxc_keypad_device = {
+-      .name = "mxc-keypad",
++      .name = "imx-keypad",
+       .id = -1,
+       .num_resources = ARRAY_SIZE(mxc_keypad_resources),
+       .resource = mxc_keypad_resources,
+@@ -333,63 +232,6 @@
+       .resource = mxc_pwm_resources3,
+ };
+-static struct resource mxc_i2c_1_resources[] = {
+-      {
+-              .start  = 0x43f80000,
+-              .end    = 0x43f83fff,
+-              .flags  = IORESOURCE_MEM,
+-      }, {
+-              .start  = 3,
+-              .end    = 3,
+-              .flags  = IORESOURCE_IRQ,
+-      }
+-};
+-
+-struct platform_device mxc_i2c_device0 = {
+-      .name = "imx-i2c",
+-      .id = 0,
+-      .num_resources = ARRAY_SIZE(mxc_i2c_1_resources),
+-      .resource = mxc_i2c_1_resources,
+-};
+-
+-static struct resource mxc_i2c_2_resources[] = {
+-      {
+-              .start  = 0x43f98000,
+-              .end    = 0x43f9bfff,
+-              .flags  = IORESOURCE_MEM,
+-      }, {
+-              .start  = 4,
+-              .end    = 4,
+-              .flags  = IORESOURCE_IRQ,
+-      }
+-};
+-
+-struct platform_device mxc_i2c_device1 = {
+-      .name = "imx-i2c",
+-      .id = 1,
+-      .num_resources = ARRAY_SIZE(mxc_i2c_2_resources),
+-      .resource = mxc_i2c_2_resources,
+-};
+-
+-static struct resource mxc_i2c_3_resources[] = {
+-      {
+-              .start  = 0x43f84000,
+-              .end    = 0x43f87fff,
+-              .flags  = IORESOURCE_MEM,
+-      }, {
+-              .start  = 10,
+-              .end    = 10,
+-              .flags  = IORESOURCE_IRQ,
+-      }
+-};
+-
+-struct platform_device mxc_i2c_device2 = {
+-      .name = "imx-i2c",
+-      .id = 2,
+-      .num_resources = ARRAY_SIZE(mxc_i2c_3_resources),
+-      .resource = mxc_i2c_3_resources,
+-};
+-
+ static struct mxc_gpio_port imx_gpio_ports[] = {
+       {
+               .chip.label = "gpio-0",
+@@ -461,12 +303,12 @@
+ static struct resource mx25_rtc_resources[] = {
+       {
+-              .start  = MX25_DRYICE_BASE_ADDR,
+-              .end    = MX25_DRYICE_BASE_ADDR + 0x40,
++              .start  = DRYICE_BASE_ADDR,
++              .end    = DRYICE_BASE_ADDR + 0x40,
+               .flags  = IORESOURCE_MEM,
+       },
+       {
+-              .start  = MX25_INT_DRYICE,
++              .start  = MXC_INT_DRYICE_NORM,
+               .flags  = IORESOURCE_IRQ
+       },
+ };
+@@ -515,3 +357,100 @@
+       .num_resources = ARRAY_SIZE(mxc_wdt_resources),
+       .resource = mxc_wdt_resources,
+ };
++
++/* imx adc driver */
++static struct resource imx_adc_resources[] = {
++      {
++              .start = TSC_BASE_ADDR,
++              .end = TSC_BASE_ADDR + PAGE_SIZE,
++              .flags = IORESOURCE_MEM,
++      },
++      {
++              .start = MXC_INT_TSC,
++              .end = MXC_INT_TSC,
++              .flags = IORESOURCE_IRQ,
++      }
++};
++
++struct platform_device imx_adc_device = {
++      .name = "imx_adc",
++      .id = 0,
++      .num_resources = ARRAY_SIZE(imx_adc_resources),
++      .resource = imx_adc_resources,
++      .dev = {
++              .release = NULL,
++      },
++};
++
++
++static struct resource mx25_tsc_resources[] = {
++      {
++              .start  = TSC_BASE_ADDR,
++              .end    = TSC_BASE_ADDR + PAGE_SIZE,
++              .flags  = IORESOURCE_MEM,
++      }, {
++              .start  = MXC_INT_TSC,
++              .end    = MXC_INT_TSC,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++struct platform_device mx25_tsc_device = {
++      .name = "imx-tsc",
++      .id = 0,
++      .num_resources = ARRAY_SIZE(mx25_tsc_resources),
++      .resource = mx25_tsc_resources,
++};
++
++static struct resource mxc_w1_master_resources[] = {
++      {
++              .start = MX25_OWIRE_BASE_ADDR,
++              .end   = MX25_OWIRE_BASE_ADDR + SZ_4K - 1,
++              .flags = IORESOURCE_MEM,
++      },
++};
++
++struct platform_device mxc_w1_master_device = {
++      .name = "mxc_w1",
++      .id = 0,
++      .num_resources = ARRAY_SIZE(mxc_w1_master_resources),
++      .resource = mxc_w1_master_resources,
++};
++
++static struct resource imx_ssi_resources0[] = {
++      {
++              .start  = MX25_SSI1_BASE_ADDR,
++              .end    = MX25_SSI1_BASE_ADDR + 0x3fff,
++              .flags  = IORESOURCE_MEM,
++      }, {
++              .start  = MX25_INT_SSI1,
++              .end    = MX25_INT_SSI1,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++static struct resource imx_ssi_resources1[] = {
++      {
++              .start  = MX25_SSI2_BASE_ADDR,
++              .end    = MX25_SSI2_BASE_ADDR + 0x3fff,
++              .flags  = IORESOURCE_MEM
++      }, {
++              .start  = MX25_INT_SSI2,
++              .end    = MX25_INT_SSI2,
++              .flags  = IORESOURCE_IRQ,
++      },
++};
++
++struct platform_device imx_ssi_device0 = {
++      .name = "imx-ssi",
++      .id = 0,
++      .num_resources = ARRAY_SIZE(imx_ssi_resources0),
++      .resource = imx_ssi_resources0,
++};
++
++struct platform_device imx_ssi_device1 = {
++      .name = "imx-ssi",
++      .id = 1,
++      .num_resources = ARRAY_SIZE(imx_ssi_resources1),
++      .resource = imx_ssi_resources1,
++};
+\ No newline at end of file
+diff -urN linux.35.old/arch/arm/mach-mx25/devices.h linux.35.new/arch/arm/mach-mx25/devices.h
+--- linux.35.old/arch/arm/mach-mx25/devices.h  2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/mach-mx25/devices.h  2010-12-03 09:51:55.349345851 +0100
+@@ -22,3 +22,8 @@
+ extern struct platform_device mx25_rtc_device;
+ extern struct platform_device mx25_fb_device;
+ extern struct platform_device mxc_wdt;
++extern struct platform_device imx_adc_device;
++extern struct platform_device mx25_tsc_device;
++extern struct platform_device mxc_w1_master_device;
++extern struct platform_device imx_ssi_device0;
++extern struct platform_device imx_ssi_device1;
+\ No newline at end of file
+diff -urN linux.35.old/arch/arm/mach-mx25/devices-imx25.h linux.35.new/arch/arm/mach-mx25/devices-imx25.h
+--- linux.35.old/arch/arm/mach-mx25/devices-imx25.h    1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/mach-mx25/devices-imx25.h    2010-12-03 09:51:55.349345851 +0100
+@@ -0,0 +1,43 @@
++/*
++ * Copyright (C) 2010 Pengutronix
++ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.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.
++ */
++#include <mach/mx25.h>
++#include <mach/devices-common.h>
++
++#define imx25_add_flexcan0(pdata)     \
++      imx_add_flexcan(0, MX25_CAN1_BASE_ADDR, SZ_16K, MX25_INT_CAN1, pdata)
++#define imx25_add_flexcan1(pdata)     \
++      imx_add_flexcan(1, MX25_CAN2_BASE_ADDR, SZ_16K, MX25_INT_CAN2, pdata)
++
++#define imx25_add_imx_i2c0(pdata)     \
++      imx_add_imx_i2c(0, MX25_I2C1_BASE_ADDR, SZ_16K, MX25_INT_I2C1, pdata)
++#define imx25_add_imx_i2c1(pdata)     \
++      imx_add_imx_i2c(1, MX25_I2C2_BASE_ADDR, SZ_16K, MX25_INT_I2C2, pdata)
++#define imx25_add_imx_i2c2(pdata)     \
++      imx_add_imx_i2c(2, MX25_I2C3_BASE_ADDR, SZ_16K, MX25_INT_I2C3, pdata)
++
++#define imx25_add_imx_uart0(pdata)    \
++      imx_add_imx_uart_1irq(0, MX25_UART1_BASE_ADDR, SZ_16K, MX25_INT_UART1, pdata)
++#define imx25_add_imx_uart1(pdata)    \
++      imx_add_imx_uart_1irq(1, MX25_UART2_BASE_ADDR, SZ_16K, MX25_INT_UART2, pdata)
++#define imx25_add_imx_uart2(pdata)    \
++      imx_add_imx_uart_1irq(2, MX25_UART3_BASE_ADDR, SZ_16K, MX25_INT_UART3, pdata)
++#define imx25_add_imx_uart3(pdata)    \
++      imx_add_imx_uart_1irq(3, MX25_UART4_BASE_ADDR, SZ_16K, MX25_INT_UART4, pdata)
++#define imx25_add_imx_uart4(pdata)    \
++      imx_add_imx_uart_1irq(4, MX25_UART5_BASE_ADDR, SZ_16K, MX25_INT_UART5, pdata)
++
++#define imx25_add_mxc_nand(pdata)     \
++      imx_add_mxc_nand_v21(MX25_NFC_BASE_ADDR, MX25_INT_NANDFC, pdata)
++
++#define imx25_add_spi_imx0(pdata)     \
++      imx_add_spi_imx(0, MX25_CSPI1_BASE_ADDR, SZ_16K, MX25_INT_CSPI1, pdata)
++#define imx25_add_spi_imx1(pdata)     \
++      imx_add_spi_imx(1, MX25_CSPI2_BASE_ADDR, SZ_16K, MX25_INT_CSPI2, pdata)
++#define imx25_add_spi_imx2(pdata)     \
++      imx_add_spi_imx(2, MX25_CSPI3_BASE_ADDR, SZ_16K, MX25_INT_CSPI3, pdata)
+diff -urN linux.35.old/arch/arm/mach-mx25/dma.c linux.35.new/arch/arm/mach-mx25/dma.c
+--- linux.35.old/arch/arm/mach-mx25/dma.c      1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/mach-mx25/dma.c      2010-12-03 09:51:55.351854203 +0100
+@@ -0,0 +1,666 @@
++/*
++ *  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
++ */
++
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/scatterlist.h>
++#include <mach/hardware.h>
++#include <mach/dma.h>
++
++//#include "serial.h"
++
++#ifdef CONFIG_SND_MXC_SOC_IRAM
++#define soc_trans_type        int_2_per
++#else
++#define soc_trans_type        emi_2_per
++#endif
++
++#define MXC_SSI_TX0_REG                 0x0
++#define MXC_SSI_TX1_REG                 0x4
++#define MXC_SSI_RX0_REG                 0x8
++#define MXC_SSI_RX1_REG                 0xC
++#define MXC_SSI_TXFIFO_WML      0x4
++#define MXC_SSI_RXFIFO_WML      0x6
++
++#define MXC_ESAI_TX_REG       0x00
++#define MXC_ESAI_RX_REG       0x04
++#define MXC_ESAI_FIFO_WML 0x40
++
++struct mxc_sdma_info_entry_s {
++      mxc_dma_device_t device;
++      mxc_sdma_channel_params_t *chnl_info;
++};
++
++#if 0
++static mxc_sdma_channel_params_t mxc_sdma_uart1_rx_params = {
++      .chnl_params = {
++              .watermark_level = UART1_UFCR_RXTL,
++              .per_address = UART1_BASE_ADDR,
++              .peripheral_type = UART,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_UART1_RX,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_UART1_RX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_uart1_tx_params = {
++      .chnl_params = {
++              .watermark_level = UART1_UFCR_TXTL,
++              .per_address = UART1_BASE_ADDR + MXC_UARTUTXD,
++              .peripheral_type = UART,
++              .transfer_type = emi_2_per,
++              .event_id = DMA_REQ_UART1_TX,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_UART1_TX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_uart2_rx_params = {
++      .chnl_params = {
++              .watermark_level = UART2_UFCR_RXTL,
++              .per_address = UART2_BASE_ADDR,
++              .peripheral_type = UART,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_UART2_RX,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_UART2_RX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_uart2_tx_params = {
++      .chnl_params = {
++              .watermark_level = UART2_UFCR_TXTL,
++              .per_address = UART2_BASE_ADDR + MXC_UARTUTXD,
++              .peripheral_type = UART,
++              .transfer_type = emi_2_per,
++              .event_id = DMA_REQ_UART2_TX,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_UART2_TX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_uart3_rx_params = {
++      .chnl_params = {
++              .watermark_level = UART3_UFCR_RXTL,
++              .per_address = UART3_BASE_ADDR,
++              .peripheral_type = UART_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_UART3_RX,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_UART3_RX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_uart3_tx_params = {
++      .chnl_params = {
++              .watermark_level = UART3_UFCR_TXTL,
++              .per_address = UART3_BASE_ADDR + MXC_UARTUTXD,
++              .peripheral_type = UART_SP,
++              .transfer_type = emi_2_per,
++              .event_id = DMA_REQ_UART3_TX,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_UART3_TX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_uart4_rx_params = {
++      .chnl_params = {
++              .watermark_level = UART4_UFCR_RXTL,
++              .per_address = UART4_BASE_ADDR,
++              .peripheral_type = UART_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_UART4_RX,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_UART4_RX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_uart4_tx_params = {
++      .chnl_params = {
++              .watermark_level = UART4_UFCR_TXTL,
++              .per_address = UART4_BASE_ADDR + MXC_UARTUTXD,
++              .peripheral_type = UART_SP,
++              .transfer_type = emi_2_per,
++              .event_id = DMA_REQ_UART4_TX,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_UART4_TX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_uart5_rx_params = {
++      .chnl_params = {
++              .watermark_level = UART5_UFCR_RXTL,
++              .per_address = UART5_BASE_ADDR,
++              .peripheral_type = UART_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_UART5_RX,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_UART5_RX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_uart5_tx_params = {
++      .chnl_params = {
++              .watermark_level = UART5_UFCR_TXTL,
++              .per_address = UART5_BASE_ADDR + MXC_UARTUTXD,
++              .peripheral_type = UART_SP,
++              .transfer_type = emi_2_per,
++              .event_id = DMA_REQ_UART5_TX,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_UART5_TX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++#endif
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_rx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_RX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI1_RX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_tx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_TX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = soc_trans_type,
++              .event_id = DMA_REQ_SSI1_TX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_rx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_RX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI1_RX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_16BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_tx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_TX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = soc_trans_type,
++              .event_id = DMA_REQ_SSI1_TX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_16BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_rx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_RX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI1_RX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_32BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_tx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_TX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = soc_trans_type,
++              .event_id = DMA_REQ_SSI1_TX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_32BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_rx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_RX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI1_RX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_8bit_tx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_TX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = soc_trans_type,
++              .event_id = DMA_REQ_SSI1_TX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_rx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_RX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI1_RX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_16BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_16bit_tx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_TX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = soc_trans_type,
++              .event_id = DMA_REQ_SSI1_TX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_16BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_rx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_RX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI1_RX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_32BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi1_24bit_tx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI1_BASE_ADDR + MXC_SSI_TX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = soc_trans_type,
++              .event_id = DMA_REQ_SSI1_TX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_32BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI1_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_rx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_RX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI2_RX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_tx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_TX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = emi_2_per,
++              .event_id = DMA_REQ_SSI2_TX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_rx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_RX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI2_RX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_16BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_tx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_TX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = emi_2_per,
++              .event_id = DMA_REQ_SSI2_TX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_16BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_rx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_RX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI2_RX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_32BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_tx0_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_TX0_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = emi_2_per,
++              .event_id = DMA_REQ_SSI2_TX0,
++              .bd_number = 32,
++              .word_size = TRANSFER_32BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_rx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_RX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI2_RX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_8bit_tx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_TX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = emi_2_per,
++              .event_id = DMA_REQ_SSI2_TX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_8BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_rx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_RX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI2_RX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_16BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_16bit_tx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_TX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = emi_2_per,
++              .event_id = DMA_REQ_SSI2_TX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_16BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_rx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_RXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_RX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_SSI2_RX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_32BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_RX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_ssi2_24bit_tx1_params = {
++      .chnl_params = {
++              .watermark_level = MXC_SSI_TXFIFO_WML,
++              .per_address = SSI2_BASE_ADDR + MXC_SSI_TX1_REG,
++              .peripheral_type = SSI_SP,
++              .transfer_type = emi_2_per,
++              .event_id = DMA_REQ_SSI2_TX1,
++              .bd_number = 32,
++              .word_size = TRANSFER_32BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_SSI2_TX,
++      .chnl_priority = 2,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_memory_params = {
++      .chnl_params = {
++              .peripheral_type = MEMORY,
++              .transfer_type = emi_2_emi,
++              .bd_number = 32,
++              .word_size = TRANSFER_32BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_MEMORY,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_esai_16bit_rx_params = {
++      .chnl_params = {
++              .watermark_level = MXC_ESAI_FIFO_WML,
++              .per_address = ESAI_BASE_ADDR + MXC_ESAI_RX_REG,
++              .peripheral_type = ESAI,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_ESAI_RX,
++              .bd_number = 32,
++              .word_size = TRANSFER_16BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_ESAI_RX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_esai_16bit_tx_params = {
++      .chnl_params = {
++              .watermark_level = MXC_ESAI_FIFO_WML,
++              .per_address = ESAI_BASE_ADDR + MXC_ESAI_TX_REG,
++              .peripheral_type = ESAI,
++              .transfer_type = soc_trans_type,
++              .event_id = DMA_REQ_ESAI_TX,
++              .bd_number = 32,
++              .word_size = TRANSFER_16BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_ESAI_TX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_esai_24bit_rx_params = {
++      .chnl_params = {
++              .watermark_level = MXC_ESAI_FIFO_WML,
++              .per_address = ESAI_BASE_ADDR + MXC_ESAI_RX_REG,
++              .peripheral_type = ESAI,
++              .transfer_type = per_2_emi,
++              .event_id = DMA_REQ_ESAI_RX,
++              .bd_number = 32,
++              .word_size = TRANSFER_32BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_ESAI_RX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static mxc_sdma_channel_params_t mxc_sdma_esai_24bit_tx_params = {
++      .chnl_params = {
++              .watermark_level = MXC_ESAI_FIFO_WML,
++              .per_address = ESAI_BASE_ADDR + MXC_ESAI_TX_REG,
++              .peripheral_type = ESAI,
++              .transfer_type = soc_trans_type,
++              .event_id = DMA_REQ_ESAI_TX,
++              .bd_number = 32,
++              .word_size = TRANSFER_32BIT,
++      },
++      .channel_num = MXC_DMA_CHANNEL_ESAI_TX,
++      .chnl_priority = MXC_SDMA_DEFAULT_PRIORITY,
++};
++
++static struct mxc_sdma_info_entry_s mxc_sdma_active_dma_info[] = {
++#if 0
++      { MXC_DMA_UART1_RX, &mxc_sdma_uart1_rx_params, },
++      { MXC_DMA_UART1_TX, &mxc_sdma_uart1_tx_params, },
++      { MXC_DMA_UART2_RX, &mxc_sdma_uart2_rx_params, },
++      { MXC_DMA_UART2_TX, &mxc_sdma_uart2_tx_params, },
++      { MXC_DMA_UART3_RX, &mxc_sdma_uart3_rx_params, },
++      { MXC_DMA_UART3_TX, &mxc_sdma_uart3_tx_params, },
++      { MXC_DMA_UART4_RX, &mxc_sdma_uart4_rx_params, },
++      { MXC_DMA_UART4_TX, &mxc_sdma_uart4_tx_params, },
++      { MXC_DMA_UART5_RX, &mxc_sdma_uart5_rx_params, },
++      { MXC_DMA_UART5_TX, &mxc_sdma_uart5_tx_params, },
++#endif
++      { MXC_DMA_SSI1_8BIT_RX0, &mxc_sdma_ssi1_8bit_rx0_params, },
++      { MXC_DMA_SSI1_8BIT_TX0, &mxc_sdma_ssi1_8bit_tx0_params, },
++      { MXC_DMA_SSI1_16BIT_RX0, &mxc_sdma_ssi1_16bit_rx0_params, },
++      { MXC_DMA_SSI1_16BIT_TX0, &mxc_sdma_ssi1_16bit_tx0_params, },
++      { MXC_DMA_SSI1_24BIT_RX0, &mxc_sdma_ssi1_24bit_rx0_params, },
++      { MXC_DMA_SSI1_24BIT_TX0, &mxc_sdma_ssi1_24bit_tx0_params, },
++      { MXC_DMA_SSI1_8BIT_RX1, &mxc_sdma_ssi1_8bit_rx1_params, },
++      { MXC_DMA_SSI1_8BIT_TX1, &mxc_sdma_ssi1_8bit_tx1_params, },
++      { MXC_DMA_SSI1_16BIT_RX1, &mxc_sdma_ssi1_16bit_rx1_params, },
++      { MXC_DMA_SSI1_16BIT_TX1, &mxc_sdma_ssi1_16bit_tx1_params, },
++      { MXC_DMA_SSI1_24BIT_RX1, &mxc_sdma_ssi1_24bit_rx1_params, },
++      { MXC_DMA_SSI1_24BIT_TX1, &mxc_sdma_ssi1_24bit_tx1_params, },
++      { MXC_DMA_SSI2_8BIT_RX0, &mxc_sdma_ssi2_8bit_rx0_params, },
++      { MXC_DMA_SSI2_8BIT_TX0, &mxc_sdma_ssi2_8bit_tx0_params, },
++      { MXC_DMA_SSI2_16BIT_RX0, &mxc_sdma_ssi2_16bit_rx0_params, },
++      { MXC_DMA_SSI2_16BIT_TX0, &mxc_sdma_ssi2_16bit_tx0_params, },
++      { MXC_DMA_SSI2_24BIT_RX0, &mxc_sdma_ssi2_24bit_rx0_params, },
++      { MXC_DMA_SSI2_24BIT_TX0, &mxc_sdma_ssi2_24bit_tx0_params, },
++      { MXC_DMA_SSI2_8BIT_RX1, &mxc_sdma_ssi2_8bit_rx1_params, },
++      { MXC_DMA_SSI2_8BIT_TX1, &mxc_sdma_ssi2_8bit_tx1_params, },
++      { MXC_DMA_SSI2_16BIT_RX1, &mxc_sdma_ssi2_16bit_rx1_params, },
++      { MXC_DMA_SSI2_16BIT_TX1, &mxc_sdma_ssi2_16bit_tx1_params, },
++      { MXC_DMA_SSI2_24BIT_RX1, &mxc_sdma_ssi2_24bit_rx1_params, },
++      { MXC_DMA_SSI2_24BIT_TX1, &mxc_sdma_ssi2_24bit_tx1_params, },
++      { MXC_DMA_ESAI_16BIT_RX, &mxc_sdma_esai_16bit_rx_params, },
++      { MXC_DMA_ESAI_16BIT_TX, &mxc_sdma_esai_16bit_tx_params, },
++      { MXC_DMA_ESAI_24BIT_RX, &mxc_sdma_esai_24bit_rx_params, },
++      { MXC_DMA_ESAI_24BIT_TX, &mxc_sdma_esai_24bit_tx_params, },
++      { MXC_DMA_MEMORY, &mxc_sdma_memory_params, },
++};
++
++/*
++ * This functions Returns the SDMA paramaters associated for a module
++ *
++ * channel_id: the ID of the module requesting DMA
++ * returns the sdma parameters structure for the device
++ */
++mxc_sdma_channel_params_t *mxc_sdma_get_channel_params(mxc_dma_device_t
++                                              channel_id)
++{
++      struct mxc_sdma_info_entry_s *p = mxc_sdma_active_dma_info;
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(mxc_sdma_active_dma_info); i++, p++) {
++              if (p->device == channel_id)
++                      return p->chnl_info;
++      }
++      return NULL;
++}
++EXPORT_SYMBOL(mxc_sdma_get_channel_params);
++
++/*
++ * This functions marks the SDMA channels that are statically allocated
++ *
++ * chnl: the channel array used to store channel information
++ */
++void mxc_get_static_channels(mxc_dma_channel_t *chnl)
++{
++#ifdef CONFIG_SDMA_IRAM
++      int i;
++      for (i = MXC_DMA_CHANNEL_IRAM; i < MAX_DMA_CHANNELS; i++)
++              chnl[i].dynamic = 0;
++#endif
++}
++EXPORT_SYMBOL(mxc_get_static_channels);
+diff -urN linux.35.old/arch/arm/mach-mx25/Kconfig linux.35.new/arch/arm/mach-mx25/Kconfig
+--- linux.35.old/arch/arm/mach-mx25/Kconfig    2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/mach-mx25/Kconfig    2010-12-03 09:51:55.351854203 +0100
+@@ -4,5 +4,57 @@
+ config MACH_MX25_3DS
+       bool "Support MX25PDK (3DS) Platform"
++      select IMX_HAVE_PLATFORM_IMX_UART
++      select IMX_HAVE_PLATFORM_MXC_NAND
++
++config MACH_VMX25
++      bool "Support Voipac VMX25 module"
++      select IMX_HAVE_PLATFORM_IMX_I2C
++      select IMX_HAVE_PLATFORM_IMX_UART
++      select IMX_HAVE_PLATFORM_MXC_NAND
++      select IMX_HAVE_PLATFORM_SPI_IMX
++      select IMX_HAVE_PLATFORM_FLEXCAN
++      depends on ARCH_MX25
++      help
++        Include support for Voipac VMX25 processor module
++
++choice
++      prompt "Baseboard"
++      depends on MACH_VMX25
++      default MACH_VMX_BASEBOARD
++
++config MACH_VMX_BASEBOARD
++      bool "Voipac development baseboard"
++      help
++        This adds board specific devices that can be found on Voipac's
++        development baseboard.
++
++endchoice
++
++choice
++      prompt "SD slot selection"
++      depends on MACH_VMX25
++      default VMX_SD_ON_BOARD if MACH_VMX_BASEBOARD
++
++config VMX_SD_ON_MODULE
++      bool "Use integrated SD slot"
++      depends on MACH_VMX25
++      help
++        Provide SD CLK signal to vmx25 on module SD slot. 
++
++config VMX_SD_ON_BOARD
++      bool "Use external SD slot"
++      depends on MACH_VMX25
++      help
++        Provide SD CLK signal to vmx25 baseboard SD slot. 
++
++endchoice
++
++config MXC_SDMA_API
++        bool "Use SDMA API"
++        default y
++        help
++           This selects the Freescale MXC SDMA API.
++           If unsure, say N.
+ endif
+diff -urN linux.35.old/arch/arm/mach-mx25/mach-mx25pdk.c linux.35.new/arch/arm/mach-mx25/mach-mx25pdk.c
+--- linux.35.old/arch/arm/mach-mx25/mach-mx25pdk.c     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/mach-mx25/mach-mx25pdk.c     2010-12-03 09:51:55.351854203 +0100
+@@ -36,10 +36,12 @@
+ #include <mach/mx25.h>
+ #include <mach/mxc_nand.h>
+ #include <mach/imxfb.h>
+-#include "devices.h"
+ #include <mach/iomux-mx25.h>
+-static struct imxuart_platform_data uart_pdata = {
++#include "devices-imx25.h"
++#include "devices.h"
++
++static const struct imxuart_platform_data uart_pdata __initconst = {
+       .flags = IMXUART_HAVE_RTSCTS,
+ };
+@@ -142,7 +144,7 @@
+       mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
+                       ARRAY_SIZE(mx25pdk_pads));
+-      mxc_register_device(&mxc_uart_device0, &uart_pdata);
++      imx25_add_imx_uart0(&uart_pdata);
+       mxc_register_device(&mxc_usbh2, NULL);
+       mxc_register_device(&mxc_nand_device, &mx25pdk_nand_board_info);
+       mxc_register_device(&mx25_rtc_device, NULL);
+diff -urN linux.35.old/arch/arm/mach-mx25/mach-vmx25.c linux.35.new/arch/arm/mach-mx25/mach-vmx25.c
+--- linux.35.old/arch/arm/mach-mx25/mach-vmx25.c       1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/mach-mx25/mach-vmx25.c       2011-01-12 14:54:30.832513858 +0100
+@@ -0,0 +1,467 @@
++/*
++ * arch/arm/mach-mx25/mach-vmx25.c
++ *
++ * Copyright (C) 2010  Voipac <support@voipac.com>
++ *
++ * Based on arch/arm/mach-mx25/karo-tx25.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 the Voipac VMX25 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/serial_8250.h>
++#include <linux/fec.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 <linux/if_ether.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-v1.h>
++#include <mach/iomux-v3.h>
++#include <mach/iomux-mx25.h>
++#include <mach/irqs.h>
++#include <mach/clock.h>
++#include <mach/imxfb.h>
++#include <mach/mmc.h>
++#include <mach/mxc_nand.h>
++#if defined(CONFIG_TOUCHSCREEN_MXC_TSC) || defined(CONFIG_TOUCHSCREEN_MXC_TSC_MODULE)
++#include <mach/mxc_tsc.h>
++#endif
++
++#include "devices.h"
++
++int vmx_mod_type = -1;
++
++static void vmx25_gpio_config(struct pad_desc *pd, int num)
++{
++      int i;
++
++      for (i = 0; i < num; i++) {
++              if (mxc_iomux_v3_setup_pad(&pd[i]) == 0) {
++                      mxc_iomux_v3_release_pad(&pd[i]);
++              }
++      }
++}
++
++/* MTD NAND flash */
++#if defined(CONFIG_MTD_NAND_MXC) || defined(CONFIG_MTD_NAND_MXC_MODULE)
++static struct pad_desc vmx25_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 mtd_partition mxc_nand_partitions[] = {
++      {
++       .name = "nand.barebox",
++       .offset = 0,
++       .size = 256 * 1024},
++      {
++       .name = "nand.bareboxenv",
++       .offset = MTDPART_OFS_APPEND,
++       .size = 128 * 1024},
++      {
++       .name = "nand.kernel",
++       .offset = MTDPART_OFS_APPEND,
++       .size = 2688 * 1024},
++      {
++       .name = "nand.rootfs",
++       .offset = MTDPART_OFS_APPEND,
++       .size = MTDPART_SIZ_FULL},
++};
++
++static struct mxc_nand_platform_data vmx25_nand_pdata = {
++      .parts = mxc_nand_partitions,
++      .nr_parts = ARRAY_SIZE(mxc_nand_partitions),
++      .hw_ecc         = 1,
++      .width          = 1,
++      .flash_bbt      = 1,
++};
++
++static int vmx25_nand_init(void)
++{
++      int ret;
++
++      printk(KERN_INFO "%s: Configuring NAND pins\n", __FUNCTION__);
++      ret = mxc_iomux_v3_setup_multiple_pads(vmx25_nand_pads,
++                                             ARRAY_SIZE(vmx25_nand_pads));
++
++      return ret;
++}
++arch_initcall(vmx25_nand_init);
++#endif // CONFIG_MTD_NAND_MXC CONFIG_MTD_NAND_MXC_MODULE
++
++#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE)
++
++static struct fec_platform_data vmx25_fec_pdata = {
++        .phy    = PHY_INTERFACE_MODE_RMII,
++};
++
++/*
++ * Setup GPIO for FEC device
++ *
++ */
++
++static struct pad_desc vmx25_fec_pwr_gpios[] = {
++      MX25_PAD_D11__GPIO_4_9,         /* FEC PHY power on pin */
++      MX25_PAD_D13__GPIO_4_7,         /* FEC reset */
++};
++
++#define VMX25_FEC_PWR_GPIO    (GPIO_PORTD | 9)
++#define VMX25_FEC_RST_GPIO    (GPIO_PORTD | 7)
++
++static struct pad_desc vmx25_fec_gpios[] = {
++      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,
++};
++
++static int vmx25_fec_init(void)
++{
++      int ret;
++
++      printk(KERN_INFO "%s: Configuring FEC pins\n", __FUNCTION__);
++      ret = mxc_iomux_v3_setup_multiple_pads(vmx25_fec_pwr_gpios,
++                                             ARRAY_SIZE(vmx25_fec_pwr_gpios));
++      if (ret) {
++              return ret;
++      }
++
++      gpio_request(VMX25_FEC_PWR_GPIO, "FEC PHY enable");
++      gpio_request(VMX25_FEC_RST_GPIO, "FEC PHY reset");
++
++
++      /* turn off PHY power and lift reset */
++      gpio_direction_output(VMX25_FEC_PWR_GPIO, 0);  /* drop PHY power */
++      gpio_direction_output(VMX25_FEC_RST_GPIO, 0); /* assert reset */
++
++      ret = mxc_iomux_v3_setup_multiple_pads(vmx25_fec_gpios,
++                                                     ARRAY_SIZE(vmx25_fec_gpios));
++
++      udelay(100);
++
++      /* turn on PHY power and lift reset */
++      gpio_set_value(VMX25_FEC_PWR_GPIO, 1);
++      gpio_set_value(VMX25_FEC_RST_GPIO, 1);
++
++      return ret;
++}
++arch_initcall(vmx25_fec_init);
++
++#endif // CONFIG_FEC CONFIG_FEC_MODULE
++
++#if defined(CONFIG_TOUCHSCREEN_MXC_TSC) || defined(CONFIG_TOUCHSCREEN_MXC_TSC_MODULE)
++static struct mxc_tsc_pdata vmx25_tsc_pdata = {
++      .pen_debounce_time = 32,
++      .intref = 1,
++      .adc_clk = 1666667,
++      .tsc_mode = MXC_TSC_4WIRE,
++      .r_xplate = 660,
++      .hsyncen = 1,
++      .hsyncpol = 0,
++};
++#endif
++
++static struct platform_dev_list {
++      struct platform_device *pdev;
++      void *pdata;
++} vmx25_devices[] __initdata = {
++#if defined(CONFIG_IMX2_WDT) || defined(CONFIG_IMX2_WDT_MODULE)
++      { .pdev = &mxc_wdt, },
++#endif
++#if defined(CONFIG_RTC_DRV_IMXDI) || defined(CONFIG_RTC_DRV_IMXDI_MODULE)
++      { .pdev = &mx25_rtc_device, },
++#endif
++#if defined(CONFIG_MTD_NAND_MXC) || defined(CONFIG_MTD_NAND_MXC_MODULE)
++      { .pdev = &mxc_nand_device, &vmx25_nand_pdata},
++#endif
++#if defined(CONFIG_FEC) || defined(CONFIG_FEC_MODULE)
++      { .pdev = &mx25_fec_device, &vmx25_fec_pdata},
++#endif
++#if defined(CONFIG_IMX_ADC) || defined(CONFIG_IMX_ADC_MODULE)
++      { .pdev = &imx_adc_device, },
++#endif
++#if defined(CONFIG_TOUCHSCREEN_MXC_TSC) || defined(CONFIG_TOUCHSCREEN_MXC_TSC_MODULE)
++      { .pdev = &mx25_tsc_device, &vmx25_tsc_pdata, },
++#endif
++#if defined(CONFIG_W1_MASTER_MXC) || defined(CONFIG_W1_MASTER_MXC_MODULE)
++      { .pdev = &mxc_w1_master_device, },
++#endif
++};
++#define VMX25_NUM_DEVICES             ARRAY_SIZE(vmx25_devices)
++
++static __init void vmx25_board_init(void)
++{
++      int i;
++
++      printk(KERN_INFO "%s: \n", __FUNCTION__);
++
++      for (i = 0; i < VMX25_NUM_DEVICES; i++) {
++              int ret;
++
++              if (vmx25_devices[i].pdev == NULL) continue;
++
++              printk(KERN_INFO "%s: Registering platform device[%d] @ %p dev %p: %s\n",
++                  __FUNCTION__, i, vmx25_devices[i].pdev, &vmx25_devices[i].pdev->dev,
++                  vmx25_devices[i].pdev->name);
++              if (vmx25_devices[i].pdata) {
++                      ret = mxc_register_device(vmx25_devices[i].pdev,
++                                              vmx25_devices[i].pdata);
++              } else {
++                      ret = platform_device_register(vmx25_devices[i].pdev);
++              }
++              if (ret) {
++                      printk(KERN_WARNING "%s: Failed to register platform_device[%d]: %s: %d\n",
++                             __FUNCTION__, i, vmx25_devices[i].pdev->name, ret);
++              }
++      }
++#if defined(CONFIG_RTC_DRV_IMXDI) || defined(CONFIG_RTC_DRV_IMXDI_MODULE)
++      device_init_wakeup(&mx25_rtc_device.dev, 1);
++#endif
++
++      printk(KERN_INFO "%s: Done\n", __FUNCTION__);
++}
++
++static struct pad_desc vmx25_gpios[] __refdata = {
++      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,
++#if defined(CONFIG_W1_MASTER_MXC) || defined(CONFIG_W1_MASTER_MXC_MODULE)
++      MX25_PAD_RTCK__OWIRE,
++#else
++      MX25_PAD_RTCK__GPIO_3_14,
++#endif
++      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,
++#if 0 /* do not mess with these */
++      MX25_PAD_NF_CE0__GPIO_3_22,
++#endif
++      MX25_PAD_ECB__GPIO_3_23,
++      MX25_PAD_LBA__GPIO_3_24,
++      MX25_PAD_RW__GPIO_3_25,
++#if 0 /* do not mess with these */
++      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,
++#endif
++      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,
++#if 0 /* do not mess with these */
++      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,
++#endif
++      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 vmx25_setup_gpios(void)
++{
++      vmx25_gpio_config(vmx25_gpios, ARRAY_SIZE(vmx25_gpios));
++      return 0;
++}
++late_initcall(vmx25_setup_gpios);
++
++static void __init vmx25_fixup(struct machine_desc *desc, struct tag *tags,
++                                 char **cmdline, struct meminfo *mi)
++{
++}
++
++static void __init vmx25_timer_init(void)
++{
++      mx25_clocks_init();
++}
++
++static struct sys_timer vmx25_timer = {
++      .init   = vmx25_timer_init,
++};
++
++static int __init vmx_mod_type_setup(char *line)
++{
++      get_option(&line, &vmx_mod_type);
++      printk(KERN_INFO "%s: Module type set to 0x%02x by kernel cmd line\n",
++              __FUNCTION__, vmx_mod_type);
++      return 1;
++}
++__setup("module_type=", vmx_mod_type_setup);
++
++MACHINE_START(VMX25, "Voipac VMX25 module (Freescale i.MX25)")
++      /* Maintainer: <support@voipac.com> */
++      .phys_io        = MX25_AIPS1_BASE_ADDR,
++      .io_pg_offst    = ((MX25_AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
++      .fixup          = vmx25_fixup,
++      .boot_params    = MX25_PHYS_OFFSET + 0x100,
++      .map_io         = mx25_map_io,
++      .init_irq       = mx25_init_irq,
++      .init_machine   = vmx25_board_init,
++      .timer          = &vmx25_timer,
++MACHINE_END
++
+diff -urN linux.35.old/arch/arm/mach-mx25/Makefile linux.35.new/arch/arm/mach-mx25/Makefile
+--- linux.35.old/arch/arm/mach-mx25/Makefile   2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/mach-mx25/Makefile   2010-12-03 09:51:55.351854203 +0100
+@@ -1,3 +1,7 @@
+ obj-y                         := mm.o devices.o
+ obj-$(CONFIG_ARCH_MX25)               += clock.o
+ obj-$(CONFIG_MACH_MX25_3DS)   += mach-mx25pdk.o
++obj-$(CONFIG_MACH_VMX25)                      += mach-vmx25.o
++obj-$(CONFIG_MACH_VMX_BASEBOARD)      += vmx-baseboard.o
++
++obj-$(CONFIG_MXC_SDMA_API)            += dma.o
+\ No newline at end of file
+diff -urN linux.35.old/arch/arm/mach-mx25/mm.c linux.35.new/arch/arm/mach-mx25/mm.c
+--- linux.35.old/arch/arm/mach-mx25/mm.c       2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/mach-mx25/mm.c       2010-12-03 09:51:55.356349597 +0100
+@@ -14,10 +14,6 @@
+  * but WITHOUT ANY WARRANTY; without even the implied warranty of
+  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+  */
+ #include <linux/mm.h>
+diff -urN linux.35.old/arch/arm/mach-mx25/sdma_script_code.h linux.35.new/arch/arm/mach-mx25/sdma_script_code.h
+--- linux.35.old/arch/arm/mach-mx25/sdma_script_code.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/mach-mx25/sdma_script_code.h 2010-12-03 09:51:55.356349597 +0100
+@@ -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                 ARRAY_SIZE(sdma_code)
++
++/*!
++ * 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 -urN linux.35.old/arch/arm/mach-mx25/vmx-baseboard.c linux.35.new/arch/arm/mach-mx25/vmx-baseboard.c
+--- linux.35.old/arch/arm/mach-mx25/vmx-baseboard.c    1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/mach-mx25/vmx-baseboard.c    2011-01-12 14:24:20.076493613 +0100
+@@ -0,0 +1,1559 @@
++/*
++ * arch/arm/mach-mx25/vmx-baseboard.c
++ *
++ * Copyright (C) 2010  Voipac <support@voipac.com>
++ *
++ * Based on arch/arm/mach-mx25/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 Voipac 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/serial.h>
++#include <linux/fsl_devices.h>
++#include <linux/irq.h>
++#include <linux/mmc/host.h>
++#include <linux/leds.h>
++#include <linux/dma-mapping.h>
++#include <linux/pwm_backlight.h>
++#include <linux/i2c.h>
++#include <linux/spi/spi.h>
++#include <linux/spi/eeprom.h>
++#include <linux/spi/ads7846.h>
++#include <linux/can/platform/mcp251x.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/iomux-v1.h>
++#include <mach/iomux-mx25.h>
++#include <mach/irqs.h>
++#include <mach/clock.h>
++#include <mach/imxfb.h>
++#include <mach/mmc.h>
++#include <mach/mxc_ehci.h>
++#include <mach/board-vmx25.h>
++#include <mach/sdhci.h>
++#include <mach/i2c.h>
++
++#include <linux/input/matrix_keypad.h>
++
++#include <mach/ssi.h>
++#include <mach/audmux.h>
++
++#include "devices.h"
++#include "devices-imx25.h"
++
++/*
++ * 1.uart
++ * 2.usb
++ * 3.i2c
++ * 5.flexcan
++ * 6.spican
++ * 4.spi
++ * 7.keypad
++ * 8.leds
++ * 9.audio
++ * 10.radio
++ */
++
++#define UART1_ENABLED         1
++#define UART2_ENABLED         1
++#define UART3_ENABLED         0 /* conflicts with SPI */
++#define UART4_ENABLED         0 /* conflicts with SSI */
++#define UART5_ENABLED         1
++
++//#define USE_SPI_GPIO_B5_CS  1 /* spi flash not work with intergrated cs */ - conflict with LCD
++
++#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
++static struct pad_desc vmx_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,
++      },
++      {
++              /* UART 3 not useable on VMX25 */
++      },
++      {
++              /* UART 4 not useable on VMX25 */
++      },
++      {
++              MX25_PAD_ECB__UART5_TXD_MUX,
++              MX25_PAD_LBA__UART5_RXD_MUX,
++              MX25_PAD_CS4__UART5_CTS,
++              MX25_PAD_CS5__UART5_RTS,
++      },
++};
++
++static int vmx_uart_init(struct platform_device *pdev)
++{
++      if (pdev->id >= ARRAY_SIZE(vmx_uart_pads)) {
++              return -ENODEV;
++      }
++      return mxc_iomux_v3_setup_multiple_pads(vmx_uart_pads[pdev->id],
++                                              ARRAY_SIZE(vmx_uart_pads[pdev->id]));
++}
++
++static void vmx_uart_exit(struct platform_device *pdev)
++{
++      BUG_ON(pdev->id >= ARRAY_SIZE(vmx_uart_pads));
++      mxc_iomux_v3_release_multiple_pads(vmx_uart_pads[pdev->id],
++                                      ARRAY_SIZE(vmx_uart_pads[pdev->id]));
++}
++
++static const struct imxuart_platform_data vmx_uart_pdata[] __initconst = {
++      {
++              .init = vmx_uart_init,
++              .exit = vmx_uart_exit,
++              .flags = IMXUART_HAVE_RTSCTS,
++      }, {
++              .init = vmx_uart_init,
++              .exit = vmx_uart_exit,
++              .flags = IMXUART_HAVE_RTSCTS,
++      }, {
++              .init = vmx_uart_init,
++              .exit = vmx_uart_exit,
++              .flags = IMXUART_HAVE_RTSCTS,
++      }, {
++              .init = vmx_uart_init,
++              .exit = vmx_uart_exit,
++              .flags = IMXUART_HAVE_RTSCTS,
++      }, {
++              .init = vmx_uart_init,
++              .exit = vmx_uart_exit,
++              .flags = IMXUART_HAVE_RTSCTS,
++      }, {
++
++      },
++};
++#endif // CONFIG_SERIAL_IMX
++
++#if defined(CONFIG_USB_EHCI_MXC) || defined(CONFIG_USB_EHCI_MXC_MODULE) || \
++      defined(CONFIG_USB_FSL_USB2) || defined(CONFIG_USB_FSL_USB2_MODULE)
++/*
++ * 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 vmx_usbh2_pads[] = {
++#ifdef USE_USB_PWR
++      MX25_PAD_D9__USBH2_PWR,
++      MX25_PAD_D8__USBH2_OC,
++#else
++      MX25_PAD_D9__GPIO_4_11,
++      MX25_PAD_D8__GPIO_4_12,
++#endif
++};
++
++static int vmx_usbh2_init(struct platform_device *pdev)
++{
++      int ret;
++#ifndef USE_USB_PWR
++      const int pwr_gpio = 3 * 32 + 11;
++#endif
++
++      ret = mxc_iomux_v3_setup_multiple_pads(vmx_usbh2_pads,
++                                      ARRAY_SIZE(vmx_usbh2_pads));
++#ifdef USE_USB_PWR
++      if (ret) {
++              return ret;
++      }
++#else
++      ret = gpio_request(pwr_gpio, "USBH2_PWR");
++      if (ret) {
++              printk(KERN_INFO "%s: Failed to request GPIO %d\n", __FUNCTION__,
++                      pwr_gpio);
++              mxc_iomux_v3_release_multiple_pads(vmx_usbh2_pads,
++                                              ARRAY_SIZE(vmx_usbh2_pads));
++              return ret;
++      }
++
++      gpio_direction_output(pwr_gpio, 1);
++#endif
++      if (ret != 0) {
++              mxc_iomux_v3_release_multiple_pads(vmx_usbh2_pads,
++                                              ARRAY_SIZE(vmx_usbh2_pads));
++              goto exit;
++      }
++
++exit:
++#ifndef USE_USB_PWR
++      gpio_free(pwr_gpio);
++#endif
++      return ret;
++}
++
++static int vmx_usbh2_exit(struct platform_device *pdev)
++{
++      mxc_iomux_v3_release_multiple_pads(vmx_usbh2_pads,
++                                      ARRAY_SIZE(vmx_usbh2_pads));
++      return 0;
++}
++
++static struct pad_desc vmx_usbotg_pads[] = {
++#ifdef USE_USB_PWR
++      MX25_PAD_GPIO_A__USBOTG_PWR,
++      MX25_PAD_GPIO_B__USBOTG_OC,
++#else
++      MX25_PAD_GPIO_A__GPIO_A,
++      MX25_PAD_GPIO_B__GPIO_B,
++#endif
++};
++
++static int vmx_usbotg_init(struct platform_device *pdev)
++{
++      int ret;
++#ifndef USE_USB_PWR
++      const int pwr_gpio = 0 * 32 + 0;
++#endif
++      printk(KERN_INFO "%s: \n", __FUNCTION__);
++
++      ret = mxc_iomux_v3_setup_multiple_pads(vmx_usbotg_pads,
++                                      ARRAY_SIZE(vmx_usbotg_pads));
++#ifdef USE_USB_PWR
++      if (ret) {
++              return ret;
++      }
++#else
++
++      ret = gpio_request(pwr_gpio, "USBOTG_PWR");
++      if (ret) {
++              printk(KERN_INFO "%s: Failed to request GPIO %d\n", __FUNCTION__,
++                      pwr_gpio);
++              mxc_iomux_v3_release_multiple_pads(vmx_usbh2_pads,
++                                              ARRAY_SIZE(vmx_usbh2_pads));
++              return ret;
++      }
++
++      gpio_direction_output(pwr_gpio, 1);
++#endif
++      if (ret != 0) {
++              mxc_iomux_v3_release_multiple_pads(vmx_usbotg_pads,
++                                              ARRAY_SIZE(vmx_usbotg_pads));
++              goto exit;
++      }
++
++exit:
++#ifndef USE_USB_PWR
++      gpio_free(pwr_gpio);
++#endif
++
++      return ret;
++}
++
++static int vmx_usbotg_exit(struct platform_device *pdev)
++{
++      mxc_iomux_v3_release_multiple_pads(vmx_usbotg_pads,
++                                      ARRAY_SIZE(vmx_usbotg_pads));
++      return 0;
++}
++#endif // CONFIG_USB_EHCI_MXC || CONFIG_USB_FSL_USB2
++
++static int otg_mode_host = 1;
++
++static int __init vmx_otg_mode(char *options)
++{
++      if (!strcmp(options, "host"))
++              otg_mode_host = 1;
++      else if (!strcmp(options, "device"))
++              otg_mode_host = 0;
++      else
++              pr_info("otg_mode neither \"host\" nor \"device\". "
++                      "Defaulting to host\n");
++      return 0;
++}
++__setup("otg_mode=", vmx_otg_mode);
++
++#if defined(CONFIG_USB_EHCI_MXC) || defined(CONFIG_USB_EHCI_MXC_MODULE)
++static struct mxc_usbh_platform_data vmx_usbotg_pdata = {
++      .init   = vmx_usbotg_init,
++      .exit   = vmx_usbotg_exit,
++      .portsc = MXC_EHCI_MODE_UTMI | MXC_EHCI_UTMI_16BIT,
++      .flags  = MXC_EHCI_INTERFACE_DIFF_UNI   /* Differential/unidirectional (6-wire) */
++//              MXC_EHCI_INTERNAL_PHY         /* USB transceiver enable */ | \
++//              MXC_EHCI_POWER_PINS_ENABLED   /* assertion of the OC input is reported to the OTG core */
++};
++
++static struct mxc_usbh_platform_data vmx_usbh2_pdata = {
++      .init   = vmx_usbh2_init,
++      .exit   = vmx_usbh2_exit,
++      .portsc = MXC_EHCI_MODE_SERIAL,
++      .flags  = MXC_EHCI_INTERFACE_SINGLE_UNI /* Single-ended/unidirectional (6-wire) */ | \
++                MXC_EHCI_INTERNAL_PHY         /* USB transceiver enable */ | \
++                MXC_EHCI_IPPUE_DOWN           /* Software has control over ipp_pue_pulldwn_dpdm */
++//              MXC_EHCI_POWER_PINS_ENABLED   /* the assertion of the OC input is reported to the host core */
++
++};
++#endif // CONFIG_USB_EHCI_MXC
++
++#if defined(CONFIG_USB_FSL_USB2) || defined(CONFIG_USB_FSL_USB2_MODULE)
++static struct fsl_usb2_platform_data vmx_usb_pdata = {
++      .operating_mode = FSL_USB2_DR_DEVICE,
++      .phy_mode       = FSL_USB2_PHY_UTMI,
++};
++#endif // CONFIG_USB_FSL_USB2
++
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
++#include <linux/i2c/at24.h>
++#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
++static struct pad_desc mxc_i2c1_pads[] = {
++      MX25_PAD_I2C1_CLK__I2C1_CLK,
++      MX25_PAD_I2C1_DAT__I2C1_DAT,
++};
++#elif defined(CONFIG_I2C_GPIO) || defined(CONFIG_I2C_GPIO_MODULE)
++static struct pad_desc mxc_i2c1_pads[] = {
++      MX25_PAD_I2C1_CLK__GPIO_1_12,
++      MX25_PAD_I2C1_DAT__GPIO_1_13,
++};
++#else
++#error No suitable I2C bus driver configured
++#endif
++
++static int vmx_i2c1_init(struct device *dev)
++{
++      return mxc_iomux_v3_setup_multiple_pads(mxc_i2c1_pads,
++                                              ARRAY_SIZE(mxc_i2c1_pads));
++}
++
++static void vmx_i2c1_exit(struct device *dev)
++{
++      mxc_iomux_v3_release_multiple_pads(mxc_i2c1_pads,
++                                         ARRAY_SIZE(mxc_i2c1_pads));
++}
++
++static struct imxi2c_platform_data vmx_i2c1_data = {
++      .init = vmx_i2c1_init,
++      .exit = vmx_i2c1_exit,
++      .bitrate = 100000,
++};
++
++static struct at24_platform_data vmx_eeprom = {
++      .byte_len = SZ_512K / 8,
++      .page_size = 128,
++      .flags = AT24_FLAG_ADDR16,
++};
++
++#define RADIO_SI4705_IRQ      (GPIO_PORTC | 16)
++
++static struct i2c_board_info vmx_i2c1_boardinfo[] __initdata = {
++      {
++              I2C_BOARD_INFO("sgtl5000-i2c", 0x0a),
++      },
++      {
++              I2C_BOARD_INFO("radio-si4705", 0x63),
++              .irq = gpio_to_irq(RADIO_SI4705_IRQ),
++      },
++      {
++              I2C_BOARD_INFO("24c512", 0x56),
++              .platform_data = &vmx_eeprom,
++      },
++      {
++              I2C_BOARD_INFO("rtc-ds1307", 0x68),
++              .type = "ds1339",
++      },
++};
++#endif /* CONFIG_I2C */
++
++#if defined(CONFIG_CAN_FLEXCAN) || defined(CONFIG_CAN_FLEXCAN_MODULE)
++static struct pad_desc vmx_can2_pads[] = {
++      MX25_PAD_GPIO_C__CAN2_TX,
++      MX25_PAD_GPIO_D__CAN2_RX,
++};
++
++static int vmx_can2_init(struct device *dev)
++{
++      return mxc_iomux_v3_setup_multiple_pads(vmx_can2_pads,
++                                      ARRAY_SIZE(vmx_can2_pads));
++}
++
++static void vmx_can2_exit(struct device *dev)
++{
++      mxc_iomux_v3_release_multiple_pads(vmx_can2_pads,
++                                         ARRAY_SIZE(vmx_can2_pads));
++}
++#endif // CONFIG_CAN_FLEXCAN
++
++#if defined(CONFIG_CAN_MCP251X) || defined(CONFIG_CAN_MCP251X_MODULE)
++#define CAN_MCP251X_IRQ                       (GPIO_PORTB |  6)
++//#define CAN_MCP251X_RESET           TODO
++
++static struct pad_desc vmx_can_mcp251x_pads[] = {
++      MX25_PAD_A20__GPIO_2_6,
++};
++
++int mcp251x_setup(struct spi_device *spi)
++{
++      int ret;
++
++      ret = mxc_iomux_v3_setup_multiple_pads(vmx_can_mcp251x_pads,
++                                      ARRAY_SIZE(vmx_can_mcp251x_pads));
++      if (ret) 
++              return ret;
++
++      ret = gpio_request(CAN_MCP251X_IRQ, "MCP251X CS");
++      if (ret) {
++              printk(KERN_INFO "%s: Failed to request GPIO %d\n", __FUNCTION__,
++                      CAN_MCP251X_IRQ);
++              mxc_iomux_v3_release_multiple_pads(vmx_can_mcp251x_pads,
++                                              ARRAY_SIZE(vmx_can_mcp251x_pads));
++              return ret;
++      }
++
++      gpio_direction_input(CAN_MCP251X_IRQ);
++      gpio_free(CAN_MCP251X_IRQ);
++
++      return ret;
++}
++
++static struct mcp251x_platform_data mcp251x_info = {
++      .oscillator_frequency = 16000000,
++      .model = CAN_MCP251X_MCP2515,
++      .board_specific_setup = &mcp251x_setup,
++      .power_enable = NULL,
++      .transceiver_enable = NULL,
++};
++#endif // CONFIG_CAN_MCP251X
++
++#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
++#define TSC2046_PENDOWN (GPIO_PORTB | 7)
++
++static struct pad_desc vmx_touch_tsc2046_pads[] = {
++      MX25_PAD_A21__GPIO_2_7,
++};
++
++int tsc2046_setup(void)
++{
++      int ret;
++
++      ret = mxc_iomux_v3_setup_multiple_pads(vmx_touch_tsc2046_pads,
++                                      ARRAY_SIZE(vmx_touch_tsc2046_pads));
++      if (ret) 
++              return ret;
++
++      ret = gpio_request(TSC2046_PENDOWN, "TSC2046 pendown");
++      if (ret) {
++              printk(KERN_INFO "%s: Failed to request GPIO %d\n", __FUNCTION__,
++                      TSC2046_PENDOWN);
++              mxc_iomux_v3_release_multiple_pads(vmx_touch_tsc2046_pads,
++                                              ARRAY_SIZE(vmx_touch_tsc2046_pads));
++              return ret;
++      }
++
++      gpio_direction_input(TSC2046_PENDOWN);
++
++      return ret;
++}
++
++static int ads7846_get_pendown_state(void)
++{
++      return !gpio_get_value(TSC2046_PENDOWN);
++}
++
++static struct ads7846_platform_data ads7846_config __initdata = {
++      .get_pendown_state      = ads7846_get_pendown_state,
++      .keep_vref_on           = 1,
++      .x_min                  = 270,
++      .y_min                  = 650,
++      .x_max                  = 3915,
++      .y_max                  = 3660,
++      .swap_xy                = 1,
++};
++#endif // CONFIG_TOUCHSCREEN_ADS7846
++
++#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
++#define VMX_SPI_FLASH_CS_GPIO         (GPIO_PORTB |  5)
++#define VMX_SPI_CAN_CS_GPIO           (GPIO_PORTB | 10)
++#define VMX_SPI_TOUCH_CS_GPIO         (GPIO_PORTB | 11)
++static struct pad_desc vmx_cspi1_pads[] = {
++      MX25_PAD_CSPI1_MOSI__CSPI1_MOSI,
++      MX25_PAD_CSPI1_MISO__CSPI1_MISO,
++      MX25_PAD_CSPI1_SS0__CSPI1_SS0,
++      MX25_PAD_CSPI1_SS1__CSPI1_SS1,
++      MX25_PAD_CSPI1_SCLK__CSPI1_SCLK,
++      MX25_PAD_CSPI1_RDY__CSPI1_RDY,
++#if defined(USE_SPI_GPIO_B5_CS)
++      MX25_PAD_A19__GPIO_2_5,
++#endif // USE_SPI_GPIO_B5_CS
++#if defined(CONFIG_CAN_MCP251X) || defined(CONFIG_CAN_MCP251X_MODULE)
++      MX25_PAD_A24__GPIO_2_10,
++#endif // CONFIG_CAN_MCP251X
++#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
++      MX25_PAD_A25__GPIO_2_11,
++#endif // CONFIG_TOUCHSCREEN_ADS7846
++};
++
++static int vmx_spi_chipselect[] = {
++#if defined(USE_SPI_GPIO_B5_CS)
++      VMX_SPI_FLASH_CS_GPIO,
++#else
++      MXC_SPI_CS(0),
++#endif // USE_SPI_GPIO_B5_CS
++      MXC_SPI_CS(1),
++      VMX_SPI_CAN_CS_GPIO,
++      VMX_SPI_TOUCH_CS_GPIO,
++};
++
++static int vmx_cspi1_init(struct device *dev)
++{
++      int ret;
++      ret = mxc_iomux_v3_setup_multiple_pads(vmx_cspi1_pads,
++                                      ARRAY_SIZE(vmx_cspi1_pads));
++
++      if (ret)
++              return ret;
++
++#if defined(USE_SPI_GPIO_B5_CS)
++      ret = gpio_request(VMX_SPI_FLASH_CS_GPIO, "SPI FLASH CS");
++
++      if (ret == 0) {
++              gpio_direction_output(VMX_SPI_FLASH_CS_GPIO, 1);
++              /* Free the CS GPIO, to allow SPI driver to register it again */
++              gpio_free(VMX_SPI_FLASH_CS_GPIO);
++      } else {
++              printk(KERN_INFO "%s: Failed to request GPIO %d\n", __FUNCTION__,
++                      VMX_SPI_FLASH_CS_GPIO);
++      }
++#endif // USE_SPI_GPIO_B5_CS
++#if defined(CONFIG_CAN_MCP251X) || defined(CONFIG_CAN_MCP251X_MODULE)
++      ret = gpio_request(VMX_SPI_CAN_CS_GPIO, "MCP251X CS");
++
++      if (ret == 0) {
++              gpio_direction_output(VMX_SPI_CAN_CS_GPIO, 1);
++              /* Free the CS GPIO, to allow SPI driver to register it again */
++              gpio_free(VMX_SPI_CAN_CS_GPIO);
++      } else {
++              printk(KERN_INFO "%s: Failed to request GPIO %d\n", __FUNCTION__,
++                      VMX_SPI_CAN_CS_GPIO);
++      }
++
++#endif // CONFIG_CAN_MCP251X
++#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
++      ret = gpio_request(VMX_SPI_TOUCH_CS_GPIO, "TSC2046 CS");
++
++      if (ret == 0) {
++              gpio_direction_output(VMX_SPI_TOUCH_CS_GPIO, 1);
++              /* Free the CS GPIO, to allow SPI driver to register it again */
++              gpio_free(VMX_SPI_TOUCH_CS_GPIO);
++      } else {
++              printk(KERN_INFO "%s: Failed to request GPIO %d\n", __FUNCTION__,
++                      VMX_SPI_TOUCH_CS_GPIO);
++      }
++
++      tsc2046_setup();
++#endif
++
++      return 0;
++}
++
++static void vmx_cspi1_exit(struct device *dev)
++{
++      mxc_iomux_v3_release_multiple_pads(vmx_cspi1_pads,
++                                         ARRAY_SIZE(vmx_cspi1_pads));
++}
++
++static struct spi_imx_master vmx_spi1_data = {
++      .chipselect = vmx_spi_chipselect,
++      .num_chipselect = ARRAY_SIZE(vmx_spi_chipselect),
++};
++
++#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
++#include <linux/mtd/partitions.h>
++#include <mtd/mtd-abi.h>
++#include <linux/spi/flash.h>
++static struct mtd_partition spi_flash_partitions[] = {
++       {
++                .name = "vmx_rom(spi)",
++                .size = 0x00040000,
++                .offset = 0,
++                .mask_flags = MTD_CAP_ROM
++        }, {
++                .name = "vmx_rwm(spi)",
++                .size = MTDPART_SIZ_FULL,
++                .offset = MTDPART_OFS_APPEND,
++        }
++};
++
++static struct flash_platform_data spi_flash_data = {
++        .name = "m25p80",
++        .parts = spi_flash_partitions,
++        .nr_parts = ARRAY_SIZE(spi_flash_partitions),
++        .type = "sst25vf016b"
++};
++#endif // CONFIG_MTD_M25P80
++
++static struct spi_board_info vmx_spi_info[] __initdata = {
++#if defined(CONFIG_MTD_M25P80) || defined(CONFIG_MTD_M25P80_MODULE)
++      {
++              /* the modalias must be the same as spi device driver name */
++              .modalias = "m25p80", /* Name of spi_driver for this device */
++              .max_speed_hz = 25000000,     /* max spi clock (SCK) speed in HZ */
++              .bus_num = 0, /* Framework bus number */
++              .chip_select = 0, /* On vmx it's SPI0_SS0 */
++              .platform_data = &spi_flash_data,
++              .mode = SPI_MODE_3,
++      },
++#endif // CONFIG_MTD_M25P80
++#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
++      {
++              .modalias = "spidev",
++              .max_speed_hz = 2000000,
++              .bus_num = 0,
++              .chip_select = 1,
++      },
++#endif // CONFIG_SPI_SPIDEV
++#if defined(CONFIG_CAN_MCP251X) || defined(CONFIG_CAN_MCP251X_MODULE)
++      {
++              .modalias = "mcp251x",
++              .irq = gpio_to_irq(CAN_MCP251X_IRQ),
++              .max_speed_hz = 2000000,
++              .chip_select = 2,
++              .platform_data = &mcp251x_info,
++              .mode = SPI_MODE_0,
++      },
++#endif // CONFIG_CAN_MCP251X
++#if defined(CONFIG_TOUCHSCREEN_ADS7846) || defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
++      {
++              .modalias = "ads7846",
++              .irq = gpio_to_irq(TSC2046_PENDOWN),
++              .max_speed_hz = 1500000,
++              .chip_select = 3,
++              .platform_data = &ads7846_config,
++              .mode = SPI_MODE_2,
++      },
++#endif // CONFIG_TOUCHSCREEN_ADS7846
++};
++#endif // CONFIG_SPI_IMX
++
++#if defined(CONFIG_KEYBOARD_IMX) || defined(CONFIG_KEYBOARD_IMX_MODULE)
++/*
++ * This array is used for mapping keypad scancodes to keyboard keycodes.
++ */
++static const uint32_t vmx25_kpd_keycodes[] = {
++      /* specify your keymap with KEY(row, col, keycode), */
++//    KEY(0, 0, KEY_POWER),
++      KEY(0, 1, KEY_HOME),
++      KEY(0, 3, KEY_BACK),
++      KEY(2, 1, KEY_MENU),
++      KEY(2, 3, KEY_ZOOM),
++};
++
++static struct matrix_keymap_data vmx25_keypad_data = {
++        .keymap = vmx25_kpd_keycodes,
++        .keymap_size = ARRAY_SIZE(vmx25_kpd_keycodes),
++};
++
++static struct pad_desc vmx25_keypad_pads[] __initdata = {
++        MX25_PAD_KPP_ROW0__KPP_ROW0,
++        MX25_PAD_KPP_ROW1__KPP_ROW1,
++        MX25_PAD_KPP_ROW2__KPP_ROW2,
++        MX25_PAD_KPP_ROW3__KPP_ROW3,
++
++        MX25_PAD_KPP_COL0__KPP_COL0,
++        MX25_PAD_KPP_COL1__KPP_COL1,
++        MX25_PAD_KPP_COL2__KPP_COL2,
++        MX25_PAD_KPP_COL3__KPP_COL3,
++};
++
++static int vmx25_keypad_init(struct device *dev)
++{
++        return mxc_iomux_v3_setup_multiple_pads(vmx25_keypad_pads,
++                                               ARRAY_SIZE(vmx25_keypad_pads));
++}
++
++static void vmx25_keypad_exit(struct device *dev)
++{
++      mxc_iomux_v3_release_multiple_pads(vmx25_keypad_pads,
++                                         ARRAY_SIZE(vmx25_keypad_pads));
++}
++#endif // CONFIG_KEYBOARD_IMX
++
++#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
++#define VMX_GPIO_LED0         (GPIO_PORTB | 4)
++#define VMX_GPIO_LED1         (GPIO_PORTB | 5)
++
++static struct pad_desc vmx_led_pads[] = {
++      MX25_PAD_A18__GPIO_2_4,
++      MX25_PAD_A19__GPIO_2_5,
++};
++
++static struct gpio_led vmx_leds[] = {
++      {
++              .name = "red",
++              .default_trigger = "heartbeat",
++              .gpio = VMX_GPIO_LED0,
++      },
++      {
++              .name = "orange",
++              .default_trigger = "none",
++              .gpio = VMX_GPIO_LED1,
++      }
++};
++
++static struct gpio_led_platform_data vmx_led_data = {
++      .leds = vmx_leds,
++      .num_leds = ARRAY_SIZE(vmx_leds),
++};
++
++static struct platform_device vmx_led_device = {
++      .name = "leds-gpio",
++      .id = -1,
++      .dev = {
++              .platform_data = &vmx_led_data,
++      },
++};
++
++static int __init vmx_led_init(void)
++{
++      int ret;
++
++      ret = mxc_iomux_v3_setup_multiple_pads(vmx_led_pads,
++                                      ARRAY_SIZE(vmx_led_pads));
++      if (ret)
++              printk(KERN_INFO "%s: Failed to setup PADS for LED: %d\n",
++                      __FUNCTION__, ret);
++
++      ret = gpio_request(VMX_GPIO_LED0, "LED0");
++      if (ret)
++              printk(KERN_INFO "%s: Failed to request GPIO%d_%d for LED: %d\n",
++                      __FUNCTION__, VMX_GPIO_LED0 / 32,
++                      VMX_GPIO_LED0 % 32, ret);
++
++      ret = gpio_request(VMX_GPIO_LED1, "LED1");
++      if (ret)
++              printk(KERN_INFO "%s: Failed to request GPIO%d_%d for LED: %d\n",
++                      __FUNCTION__, VMX_GPIO_LED1 / 32,
++                      VMX_GPIO_LED1 % 32, ret);
++
++
++      gpio_direction_output(VMX_GPIO_LED0, 0);
++      gpio_direction_output(VMX_GPIO_LED1, 0);
++
++      /* free the GPIO, so that the LED driver can grab it */
++      gpio_free(VMX_GPIO_LED0);
++      gpio_free(VMX_GPIO_LED1);
++
++      return ret;
++}
++arch_initcall(vmx_led_init);
++#endif
++
++#if defined(CONFIG_SND_IMX_SOC) || defined(CONFIG_SND_IMX_SOC_MODULE)
++struct imx_ssi_platform_data vmx_ssi_pdata = {
++      .flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
++};
++#endif // CONFIG_SND_IMX_SOC
++
++#if defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000) || defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000_MODULE)
++static struct pad_desc vmx_aud4_pads[] = {
++      MX25_PAD_EB0__AUD4_TXD,
++      MX25_PAD_EB1__AUD4_RXD,
++      MX25_PAD_RW__AUD4_TXFS,
++      MX25_PAD_OE__AUD4_TXC,
++};
++
++/*!
++ * This function activates DAM port 4 to enable
++ * audio I/O.
++ */
++static int sgtl5000_plat_init(void)
++{
++      return mxc_iomux_v3_setup_multiple_pads(vmx_aud4_pads,
++                                      ARRAY_SIZE(vmx_aud4_pads));
++}
++
++/*!
++ * This function inactivates DAM port 4 for
++ * audio I/O
++ */
++static int sgtl5000_plat_exit(void)
++{
++      mxc_iomux_v3_release_multiple_pads(vmx_aud4_pads,
++                                         ARRAY_SIZE(vmx_aud4_pads));
++      return 0;
++}
++
++static struct mxc_audio_platform_data stk5_sgtl5000_data = {
++      .ssi_num = 0,                   // MASU fixme
++      .src_port = 1,
++      .ext_port = 4,
++      .init = sgtl5000_plat_init,     /* board specific init */
++      .finit = sgtl5000_plat_exit,    /* board specific finit */
++      .hp_irq = 0,
++      .hp_status = NULL,
++      .amp_enable = NULL,
++      .sysclk = 12288000,
++};
++
++static struct platform_device vmx_sgtl5000_device = {
++      .name = "imx-3stack-sgtl5000",
++      .dev = {
++              .platform_data = &stk5_sgtl5000_data,
++      },
++};
++#endif // CONFIG_SND_SOC_IMX_3STACK_SGTL5000
++
++#if defined(CONFIG_RADIO_SI4705) || defined(CONFIG_RADIO_SI4705_MODULE)
++static struct pad_desc vmx_radio_pads[] = {
++      MX25_PAD_VSTBY_ACK__GPIO_3_18,          /* RESET_OUT_3V3 */
++      MX25_PAD_UPLL_BYPCLK__GPIO_3_16,        /* SSI2_INT */
++};
++
++#define RADIO_GPIO82  (GPIO_PORTC | 18)               // Reset
++#define RADIO_GPIO80  RADIO_SI4705_IRQ                // IRQ
++
++static int radio_si4705_reset(void) {
++      int err = 0;
++
++      err |= mxc_iomux_v3_setup_multiple_pads(vmx_radio_pads,
++                                      ARRAY_SIZE(vmx_radio_pads));
++
++      err |= gpio_request(RADIO_GPIO82, "GPIO82");
++      err |= gpio_request(RADIO_GPIO80, "GPIO80");
++      if (err) {
++              return err;
++      }
++
++      gpio_direction_output(RADIO_GPIO82, 0);
++      gpio_direction_output(RADIO_GPIO80, 0);
++
++      gpio_set_value(RADIO_GPIO82, 0);
++      gpio_set_value(RADIO_GPIO80, 0);
++
++      err = 0;                                        // FIXME active delay
++      while (--err) ;
++
++      gpio_set_value(RADIO_GPIO82, 1);
++      gpio_direction_input(RADIO_GPIO80);
++
++      gpio_free(RADIO_GPIO80);
++
++      return 0;
++}
++#endif // CONFIG_RADIO_SI4705
++
++#if defined(CONFIG_FB_IMX) || defined(CONFIG_FB_IMX_MODULE)
++#define VMX_LCD_BACKLIGHT_GPIO                (GPIO_PORTA | 26)
++//#define VMX_LCD_RESET_GPIO          (GPIO_PORTB | 4)
++//#define VMX_LCD_POWER_GPIO          (GPIO_PORTB | 5)
++
++/*
++ * Setup GPIO for LCDC device to be active
++ *
++ */
++static struct pad_desc mx25_lcdc_gpios[] = {
++#ifdef VMX_LCD_BACKLIGHT_GPIO
++//    MX25_PAD_A18__GPIO_2_4,         /* LCD Reset (active LOW) */
++#if !defined(CONFIG_MXC_PWM) && !defined(CONFIG_MXC_PWM_MODULE)
++      MX25_PAD_PWM__GPIO_1_26,        /* LCD Backlight brightness 0: full 1: off */
++#endif
++//    MX25_PAD_A19__GPIO_2_5,         /* LCD Power Enable 0: off 1: on */
++#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 vmx_gpio_lcdc_active(struct platform_device *dev)
++{
++      int ret;
++
++      printk(KERN_INFO "%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) {
++              printk(KERN_INFO "%s: Failed to setup GPIO pins for LCD: %d\n",
++                      __FUNCTION__, ret);
++              return ret;
++      }
++#ifdef VMX_LCD_BACKLIGHT_GPIO
++//    ret = gpio_request(VMX_LCD_POWER_GPIO, "LCD POWER");
++//    if (ret) {
++//            printk(KERN_INFO "%s: Failed to request GPIO for LCD POWER: %d\n",
++//                    __FUNCTION__, ret);
++//            goto release_pins;
++//    }
++#if !defined(CONFIG_MXC_PWM) && !defined(CONFIG_MXC_PWM_MODULE)
++      ret = gpio_request(VMX_LCD_BACKLIGHT_GPIO, "LCD Backlight");
++      if (ret) {
++              printk(KERN_INFO "%s: Failed to request GPIO for backlight control: %d\n",
++                      __FUNCTION__, ret);
++              goto free_gpio1;
++      }
++#endif
++//    ret = gpio_request(VMX_LCD_RESET_GPIO, "LCD RESET");
++//    if (ret) {
++//            printk(KERN_INFO "%s: Failed to request GPIO for LCD RESET: %d\n",
++//                    __FUNCTION__, ret);
++//            goto free_gpio2;
++//    }
++
++//    gpio_direction_output(VMX_LCD_POWER_GPIO, 1);
++#if !defined(CONFIG_MXC_PWM) && !defined(CONFIG_MXC_PWM_MODULE)
++      gpio_direction_output(VMX_LCD_BACKLIGHT_GPIO, 1);
++#endif
++//    gpio_direction_output(VMX_LCD_RESET_GPIO, 0);
++#endif
++      return 0;
++
++//free_gpio2:
++#if !defined(CONFIG_MXC_PWM) && !defined(CONFIG_MXC_PWM_MODULE)
++      gpio_free(VMX_LCD_BACKLIGHT_GPIO);
++free_gpio1:
++#endif
++//    gpio_free(VMX_LCD_POWER_GPIO);
++//release_pins:
++      mxc_iomux_v3_release_multiple_pads(mx25_lcdc_gpios,
++                                      ARRAY_SIZE(mx25_lcdc_gpios));
++      return ret;
++}
++
++/*
++ * Setup GPIO for LCDC device to be inactive
++ *
++ */
++static void vmx_gpio_lcdc_inactive(struct platform_device *dev)
++{
++      mxc_iomux_v3_release_multiple_pads(mx25_lcdc_gpios,
++                                      ARRAY_SIZE(mx25_lcdc_gpios));
++}
++
++#ifdef VMX_LCD_BACKLIGHT_GPIO
++#if !defined(CONFIG_MXC_PWM) && !defined(CONFIG_MXC_PWM_MODULE)
++static void vmx_lcdc_backlight(int on)
++{
++      printk(KERN_INFO "%s: Switching LCD backlight %s\n", __FUNCTION__, on ? "on" : "off");
++      if (on) {
++              gpio_set_value(VMX_LCD_BACKLIGHT_GPIO, 0);
++      } else {
++              gpio_set_value(VMX_LCD_BACKLIGHT_GPIO, 1);
++      }
++}
++#else
++#define vmx_lcdc_backlight    NULL
++#endif
++
++static void vmx_lcdc_power(int on)
++{
++      printk(KERN_INFO "%s: Switching LCD reset %s\n", __FUNCTION__, on ? "off" : "on");
++//    if (on) {
++//            gpio_set_value(VMX_LCD_RESET_GPIO, 1);
++//    } else {
++//            gpio_set_value(VMX_LCD_RESET_GPIO, 0);
++//    }
++}
++#else
++#define vmx_lcdc_backlight    NULL
++#define vmx_lcdc_power                NULL
++#endif
++
++static struct imx_fb_videomode vmx_fb_modes[] = {
++      {
++              .bpp    = 16,
++              .mode = {
++                      .name           = "VGA-16@60",
++
++                      .pixclock       = KHZ2PICOS(24000),
++                      .xres           = 640,
++                      .yres           = 480,
++
++                      .hsync_len      = 44,
++                      .left_margin    = 66+8, /* Back porch */
++                      .right_margin   = 2,    /* Front porch */
++
++                      .vsync_len      = 2,
++                      .upper_margin   = 25+8, /* Back porch */
++                      .lower_margin   = 2+8,  /* Front porch */
++              },
++
++              .pcr    = PCR_TFT | PCR_COLOR | PCR_BPIX_16 |
++              PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL,
++      },
++      {
++              .bpp    = 32,
++              .mode = {
++                      .name           = "VGA-32@60",
++
++                      .pixclock       = KHZ2PICOS(24000),
++                      .xres           = 640,
++                      .yres           = 480,
++
++                      .hsync_len      = 44,
++                      .left_margin    = 66+8, /* Back porch */
++                      .right_margin   = 2,    /* Front porch */
++
++                      .vsync_len      = 2,
++                      .upper_margin   = 25+8, /* Back porch */
++                      .lower_margin   = 2+8,  /* Front porch */
++              },
++
++              .pcr    = PCR_TFT | PCR_COLOR | PCR_BPIX_18 |
++              PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL | PCR_END_SEL,
++      },
++      {
++              /* fH=30KHz HSYNC=1000px, fV=60Hz VSYNC=500lines, fCLK=30000*/
++              .bpp    = 16,
++              .mode = {
++                      .name           = "WVGA-LCD",
++                      .pixclock       = KHZ2PICOS(30000),
++
++                      .xres           = 800,
++                      .yres           = 480,
++
++                      .hsync_len      = 64,
++                      .left_margin    = 120,  /* Back porch */
++                      .right_margin   = 16,   /* Front porch */
++
++                      .vsync_len      = 2,
++                      .upper_margin   = 16,   /* Back porch */
++                      .lower_margin   = 2,    /* Front porch */
++
++              },
++
++              .pcr    = PCR_TFT | PCR_COLOR | PCR_PBSIZ_8 | PCR_BPIX_16 |
++              PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL, // -PCR_CLKPOL, +PCR_OEPOL
++      },
++      {
++              .bpp    = 16,
++              .mode = {
++                      .name           = "WVGA-16@60",
++                      .pixclock       = KHZ2PICOS(30000),
++
++                      .xres           = 800,
++                      .yres           = 480,
++
++                      .hsync_len      = 54,
++                      .left_margin    = 100,  /* Back porch */
++                      .right_margin   = 16,   /* Front porch */
++
++                      .vsync_len      = 4,
++                      .upper_margin   = 28,   /* Back porch */
++                      .lower_margin   = 4,    /* Front porch */
++
++              },
++
++              .pcr    = PCR_TFT | PCR_COLOR | PCR_PBSIZ_8 | PCR_BPIX_16 |
++              PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL,
++      },
++      {
++              .bpp    = 32,
++              .mode = {
++                      .name           = "WVGA-32@60",
++                      .pixclock       = KHZ2PICOS(30000),
++
++                      .xres           = 800,
++                      .yres           = 480,
++
++                      .hsync_len      = 54,
++                      .left_margin    = 100,  /* Back porch */
++                      .right_margin   = 16,   /* Front porch */
++
++                      .vsync_len      = 4,
++                      .upper_margin   = 28,   /* Back porch */
++                      .lower_margin   = 4,    /* Front porch */
++
++              },
++
++              .pcr    = PCR_TFT | PCR_COLOR | PCR_PBSIZ_8 | PCR_BPIX_18 |
++              PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL | PCR_END_SEL,
++
++      },
++      {
++              .bpp    = 16,
++              .mode = {
++                      .name           = "SVGA-16@60",
++                      .pixclock       = KHZ2PICOS(40000),
++
++                      .xres           = 800,
++                      .yres           = 600,
++
++                      .hsync_len      = 64,
++                      .left_margin    = 170,  /* Back porch */
++                      .right_margin   = 24,   /* Front porch */
++
++                      .vsync_len      = 5,
++                      .upper_margin   = 23,   /* Back porch */
++                      .lower_margin   = 2,    /* Front porch */
++
++              },
++
++              .pcr    = PCR_TFT | PCR_COLOR | PCR_PBSIZ_8 | PCR_BPIX_16 |
++              PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL,
++      },
++      {
++              .bpp    = 32,
++              .mode = {
++                      .name           = "SVGA-32@60",
++                      .pixclock       = KHZ2PICOS(40000),
++
++                      .xres           = 800,
++                      .yres           = 600,
++
++                      .hsync_len      = 64,
++                      .left_margin    = 170,  /* Back porch */
++                      .right_margin   = 24,   /* Front porch */
++
++                      .vsync_len      = 5,
++                      .upper_margin   = 23,   /* Back porch */
++                      .lower_margin   = 2,    /* Front porch */
++
++              },
++
++              .pcr    = PCR_TFT | PCR_COLOR | PCR_PBSIZ_8 | PCR_BPIX_18 |
++              PCR_FLMPOL | PCR_LPPOL | PCR_SCLK_SEL | PCR_END_SEL,
++
++      },
++};
++
++static struct imx_fb_platform_data vmx_fb_data = {
++      .init           = vmx_gpio_lcdc_active,
++      .exit           = vmx_gpio_lcdc_inactive,
++      .lcd_power      = vmx_lcdc_power,
++      .backlight_power = vmx_lcdc_backlight,
++
++      .mode           = vmx_fb_modes,
++      .num_modes      = ARRAY_SIZE(vmx_fb_modes),
++
++      .dmacr          = 0x00040060,
++
++      .cmap_greyscale = 0,
++      .cmap_inverse   = 0,
++      .cmap_static    = 0,
++
++      .fixed_screen_cpu = NULL,
++};
++#endif
++
++#if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
++static struct pad_desc vmx_pwm_pads[] = {
++      MX25_PAD_PWM__PWM,
++};
++
++static int vmx_backlight_init(struct device *dev)
++{
++      int ret;
++      ret = mxc_iomux_v3_setup_pad(&vmx_pwm_pads[0]);
++      return ret;
++}
++
++static int vmx_backlight_notify(struct device *dev, int brightness)
++{
++      printk(KERN_INFO "%s: brightness=%d\n", __FUNCTION__, brightness);
++      return brightness;
++}
++
++static void vmx_backlight_exit(struct device *dev)
++{
++      mxc_iomux_v3_release_pad(&vmx_pwm_pads[0]);
++}
++
++static struct platform_pwm_backlight_data vmx_backlight_data = {
++      .pwm_id = 0,
++      .max_brightness = 100,
++      .dft_brightness = 50,
++      .pwm_period_ns = KHZ2PICOS(20000), /* kHz -> ps is the same as Hz -> ns */
++      .init = vmx_backlight_init,
++      .notify = vmx_backlight_notify,
++      .exit = vmx_backlight_exit,
++};
++
++static struct platform_device vmx_backlight_pwm_device = {
++      .name = "pwm-backlight",
++      .dev = {
++              .platform_data = &vmx_backlight_data,
++      },
++};
++#endif /* CONFIG_BACKLIGHT_PWM || CONFIG_BACKLIGHT_PWM_MODULE */
++
++#if defined(CONFIG_MMC_SDHCI_MXC) || defined(CONFIG_MMC_SDHCI_MXC_MODULE)
++#define SDHC1_CD_GPIO (GPIO_PORTD | 4)
++#define SDHC1_SEL_SLOT        (GPIO_PORTD | 10)
++
++/*
++ * Resource definition for the SDHC1
++ */
++static struct resource vmx_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(SDHC1_CD_GPIO),
++              .end = gpio_to_irq(SDHC1_CD_GPIO),
++              .flags = IORESOURCE_IRQ,
++      },
++};
++
++static inline int vmx_esdhci_get_irq(int id)
++{
++      int irq;
++
++      switch (id) {
++      case 0:
++              irq = vmx_sdhc1_resources[2].start;
++              break;
++      default:
++              BUG();
++      }
++      return irq;
++}
++
++static const char *vmx_esdhci_irqdesc[] = {
++      "ESDHCI card 0 detect",
++};
++
++static struct pad_desc vmx_sdhc_pads[] = {
++      MX25_PAD_SD1_CMD__SD1_CMD,
++      MX25_PAD_SD1_CLK__SD1_CLK,
++      MX25_PAD_SD1_DATA0__SD1_DATA0,
++      MX25_PAD_SD1_DATA2__SD1_DATA2,
++      MX25_PAD_SD1_DATA3__SD1_DATA3,
++      /* card detect GPIO */
++      MX25_PAD_BCLK__GPIO_4_4,
++      /* SD CLK switch GPIO */
++      MX25_PAD_D10__GPIO_4_10,
++};
++
++static int vmx_esdhci_status(struct device *dev)
++{
++      return !!gpio_get_value(SDHC1_CD_GPIO);
++}
++
++static int vmx_esdhci_init(struct device *dev, irqreturn_t (*esdhci_detect_irq)(int, void *),
++                      void *data)
++{
++      int err;
++      struct mmc_host *host = data;
++      int id = to_platform_device(dev)->id;
++      int irq = vmx_esdhci_get_irq(id);
++
++      err = mxc_iomux_v3_setup_multiple_pads(vmx_sdhc_pads,
++                                      ARRAY_SIZE(vmx_sdhc_pads));
++      if (err) {
++              return err;
++      }
++
++      err = gpio_request(SDHC1_SEL_SLOT, "SD card slot select"); 
++//    if (err) {
++//            return err;
++//    }
++      gpio_direction_output(SDHC1_SEL_SLOT, 0);
++
++#if defined(CONFIG_VMX_SD_ON_MODULE)
++      gpio_set_value(SDHC1_SEL_SLOT, 1);
++#elif defined(CONFIG_VMX_SD_ON_BOARD)
++      gpio_set_value(SDHC1_SEL_SLOT, 0);
++#else
++#error "Choice active SD slot internal/external"
++#endif
++
++      host->caps |= MMC_CAP_4_BIT_DATA;
++
++      printk(KERN_INFO "%s: Requesting IRQ %d\n", __FUNCTION__, irq);
++      err = request_irq(irq, esdhci_detect_irq,
++                      IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
++                      vmx_esdhci_irqdesc[id], data);
++      if (err) {
++              dev_err(dev, "Error %d requesting ESDHCI card detect IRQ %d\n",
++                      err, irq);
++              return err;
++      }
++      device_set_wakeup_capable(dev, 1);
++
++      return 0;
++}
++
++static void vmx_esdhci_exit(struct device *dev, void *data)
++{
++      int id = to_platform_device(dev)->id;
++      int irq = vmx_esdhci_get_irq(id);
++
++      printk(KERN_INFO "%s: Freeing IRQ %d\n", __FUNCTION__, irq);
++      free_irq(irq, data);
++      gpio_free(SDHC1_SEL_SLOT);
++      mxc_iomux_v3_release_multiple_pads(vmx_sdhc_pads,
++                                      ARRAY_SIZE(vmx_sdhc_pads));
++}
++
++static int vmx_esdhci_suspend(struct device *dev)
++{
++      int id = to_platform_device(dev)->id;
++      int irq = vmx_esdhci_get_irq(id);
++
++      if (device_may_wakeup(dev)) {
++              printk(KERN_INFO "%s: Enabling IRQ %d wakeup\n", __FUNCTION__, irq);
++              return enable_irq_wake(irq);
++      }
++      return 0;
++}
++
++static int vmx_esdhci_resume(struct device *dev)
++{
++      int id = to_platform_device(dev)->id;
++      int irq = vmx_esdhci_get_irq(id);
++
++      if (device_may_wakeup(dev)) {
++              printk(KERN_INFO "%s: Disabling IRQ %d wakeup\n", __FUNCTION__, irq);
++              return disable_irq_wake(irq);
++      }
++      return 0;
++}
++
++static struct mxc_sdhci_platform_data vmx_sdhc1_data = {
++      .ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34,
++      .init = vmx_esdhci_init,
++      .exit = vmx_esdhci_exit,
++      .suspend = vmx_esdhci_suspend,
++      .resume = vmx_esdhci_resume,
++      .status = vmx_esdhci_status,
++      .min_clk = 150000,
++      .max_clk = 25000000,
++      .detect_delay = 100,
++#if defined(CONFIG_VMX_SD_ON_MODULE)
++      .force_sd_detect=1
++#else
++      .force_sd_detect=0
++#endif
++};
++
++static struct platform_device vmx_sdhc1_device = {
++      .name = "sdhci",
++      .id = 0,
++      .dev = {
++              .coherent_dma_mask = DMA_BIT_MASK(32),
++              .platform_data = &vmx_sdhc1_data,
++      },
++      .num_resources = ARRAY_SIZE(vmx_sdhc1_resources),
++      .resource = vmx_sdhc1_resources,
++};
++#endif
++
++static struct platform_dev_list {
++      struct platform_device *pdev;
++      void *pdata;
++} vmx_devices[] __initdata = {
++#if defined(CONFIG_FB_IMX) || defined(CONFIG_FB_IMX_MODULE)
++      { .pdev = &mx25_fb_device, .pdata = &vmx_fb_data, },
++#endif
++#if defined(CONFIG_MXC_PWM) || defined(CONFIG_MXC_PWM_MODULE)
++      { .pdev = &mxc_pwm_device0, },
++#endif
++#if defined(CONFIG_BACKLIGHT_PWM) || defined(CONFIG_BACKLIGHT_PWM_MODULE)
++      { .pdev = &vmx_backlight_pwm_device, .pdata = &vmx_backlight_data, },
++#endif
++#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
++      { .pdev = &vmx_led_device, },
++#endif
++#if defined(CONFIG_MMC_SDHCI_MXC) || defined(CONFIG_MMC_SDHCI_MXC_MODULE)
++      { .pdev = &vmx_sdhc1_device, },
++#endif
++#if defined(CONFIG_SND_IMX_SOC) || defined(CONFIG_SND_IMX_SOC_MODULE)
++      { .pdev = &imx_ssi_device0, .pdata = &vmx_ssi_pdata, },
++#endif
++#if defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000) || defined(CONFIG_SND_SOC_IMX_3STACK_SGTL5000_MODULE)
++      { .pdev = &vmx_sgtl5000_device, },
++#endif
++};
++#define VMX_NUM_DEVICES               ARRAY_SIZE(vmx_devices)
++
++static __init int vmx_board_init(void)
++{
++      int ret;
++      int i;
++
++      /* Do UART init */
++#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
++#if UART1_ENABLED
++      imx25_add_imx_uart0(&vmx_uart_pdata[0]);
++#endif
++#if UART2_ENABLED
++      imx25_add_imx_uart1(&vmx_uart_pdata[1]);
++#endif
++#if UART3_ENABLED
++      imx25_add_imx_uart2(&vmx_uart_pdata[2]);
++#endif
++#if UART4_ENABLED
++      imx25_add_imx_uart3(&vmx_uart_pdata[3]);
++#endif
++#if UART5_ENABLED
++      imx25_add_imx_uart4(&vmx_uart_pdata[4]);
++#endif
++#endif // CONFIG_SERIAL_IMX
++
++
++      // Do USB init
++#if defined(CONFIG_USB_EHCI_MXC) || defined(CONFIG_USB_EHCI_MXC_MODULE)
++      if (otg_mode_host) {            // HOST
++              mxc_register_device(&mxc_otg, &vmx_usbotg_pdata);
++      } else {                        // OTG
++  #if defined(CONFIG_USB_FSL_USB2) || defined(CONFIG_USB_FSL_USB2_MODULE)
++              mxc_register_device(&otg_udc_device, &vmx_usb_pdata);
++  #endif // CONFIG_USB_FSL_USB2
++      }
++
++      mxc_register_device(&mxc_usbh2, &vmx_usbh2_pdata);
++#endif // CONFIG_USB_EHCI_MXC
++
++
++      // Do I2C init
++#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
++      imx25_add_imx_i2c0(&vmx_i2c1_data);
++      ret = i2c_register_board_info(0, vmx_i2c1_boardinfo,
++                                    ARRAY_SIZE(vmx_i2c1_boardinfo));
++      if (ret)
++              printk(KERN_ERR "Failed to register I2C board info: %d\n", ret);
++#endif // CONFIG_I2C
++
++      // Do SPI init
++#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
++      ret = vmx_cspi1_init(NULL);
++      if (ret) {
++              printk(KERN_ERR "Failed to configure CSPI1 pads\n");
++      } else {
++              imx25_add_spi_imx0(&vmx_spi1_data);
++              ret = spi_register_board_info(vmx_spi_info,
++                                    ARRAY_SIZE(vmx_spi_info));
++              if (ret) {
++                      printk(KERN_ERR "Failed to register SPI board info: %d\n", ret);
++              } else {
++//                    vmx_cspi1_exit(NULL);
++              }
++      }
++#endif // CONFIG_SPI_IMX
++
++
++      // Do CAN1 init
++#if defined(CONFIG_CAN_FLEXCAN) || defined(CONFIG_CAN_FLEXCAN_MODULE)
++      ret = vmx_can2_init(NULL);
++      if (ret) {
++              printk(KERN_ERR "Failed to configure FLEXCAN2 pads\n");
++//            vmx_can2_exit(NULL);
++      } else {
++              imx25_add_flexcan1(NULL);
++      }
++#endif // CONFIG_CAN_FLEXCAN
++
++      // Do KEYPAD init
++#if defined(CONFIG_KEYBOARD_IMX) || defined(CONFIG_KEYBOARD_IMX_MODULE)
++      ret = vmx25_keypad_init(NULL);
++      if (ret) {
++              printk(KERN_ERR "Failed to configure Keypad pads\n");
++      } else {
++              ret = mxc_register_device(&mxc_keypad_device, &vmx25_keypad_data);
++                      if (ret) {
++                      printk(KERN_WARNING "%s: Failed to register platform_device: %s\n",
++                              __FUNCTION__, mxc_keypad_device.name);
++                      vmx25_keypad_exit(NULL);
++              }
++      }
++#endif // CONFIG_KEYBOARD_IMX
++
++      // Do audmux interconnection
++#if defined(CONFIG_SND_IMX_SOC) || defined(CONFIG_SND_IMX_SOC_MODULE)
++      /* SSI unit master I2S codec connected to SSI_AUD4*/
++      mxc_audmux_v2_configure_port(0, 0, 0);  // reset the ports
++      mxc_audmux_v2_configure_port(3, 0, 0);
++      mxc_audmux_v2_configure_port(0,
++                      MXC_AUDMUX_V2_PTCR_SYN |
++                      MXC_AUDMUX_V2_PTCR_TFSDIR |
++                      MXC_AUDMUX_V2_PTCR_TFSEL(3) |
++                      MXC_AUDMUX_V2_PTCR_TCLKDIR |
++                      MXC_AUDMUX_V2_PTCR_TCSEL(3),
++                      MXC_AUDMUX_V2_PDCR_RXDSEL(3)
++      );
++      mxc_audmux_v2_configure_port(3,
++                      MXC_AUDMUX_V2_PTCR_SYN,
++                      MXC_AUDMUX_V2_PDCR_RXDSEL(0)
++      );
++#endif // CONFIG_SND_IMX_SOC
++
++#if defined(CONFIG_RADIO_SI4705) || defined(CONFIG_RADIO_SI4705_MODULE)
++      radio_si4705_reset();
++#endif // CONFIG_RADIO_SI4705
++
++      for (i = 0; i < VMX_NUM_DEVICES; i++) {
++              if (vmx_devices[i].pdev == NULL) continue;
++              printk(KERN_INFO "%s: Registering platform device[%d] @ %p dev %p: %s\n",
++                      __FUNCTION__, i, vmx_devices[i].pdev, &vmx_devices[i].pdev->dev,
++                      vmx_devices[i].pdev->name);
++              if (vmx_devices[i].pdata) {
++                      ret = mxc_register_device(vmx_devices[i].pdev,
++                                              vmx_devices[i].pdata);
++              } else {
++                      ret = platform_device_register(vmx_devices[i].pdev);
++              }
++              if (ret) {
++                      printk(KERN_WARNING "%s: Failed to register platform_device[%d]: %s: %d\n",
++                              __FUNCTION__, i, vmx_devices[i].pdev->name, ret);
++              }
++      }
++      printk(KERN_INFO "%s: Done\n", __FUNCTION__);
++
++      return 0;
++}
++subsys_initcall(vmx_board_init);
+diff -urN linux.35.old/arch/arm/plat-mxc/audmux-v2.c linux.35.new/arch/arm/plat-mxc/audmux-v2.c
+--- linux.35.old/arch/arm/plat-mxc/audmux-v2.c 2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/audmux-v2.c 2010-12-03 09:51:55.360347257 +0100
+@@ -13,10 +13,6 @@
+  * 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/module.h>
+@@ -191,6 +187,7 @@
+ {
+       int ret;
++#if defined(CONFIG_ARCH_MX3)
+       if (cpu_is_mx31())
+               audmux_base = MX31_IO_ADDRESS(MX31_AUDMUX_BASE_ADDR);
+@@ -204,7 +201,19 @@
+               }
+               audmux_base = MX35_IO_ADDRESS(MX35_AUDMUX_BASE_ADDR);
+       }
+-
++#endif
++#if defined(CONFIG_ARCH_MX25)
++      if (cpu_is_mx25()) {
++              audmux_clk = clk_get(NULL, "audmux");
++              if (IS_ERR(audmux_clk)) {
++                      ret = PTR_ERR(audmux_clk);
++                      printk(KERN_ERR "%s: cannot get clock: %d\n", __func__,
++                                      ret);
++                      return ret;
++              }
++              audmux_base = MX25_IO_ADDRESS(MX25_AUDMUX_BASE_ADDR);
++      }
++#endif
+       audmux_debugfs_init();
+       return 0;
+diff -urN linux.35.old/arch/arm/plat-mxc/devices/Kconfig linux.35.new/arch/arm/plat-mxc/devices/Kconfig
+--- linux.35.old/arch/arm/plat-mxc/devices/Kconfig     1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/devices/Kconfig     2010-12-03 09:51:55.360347257 +0100
+@@ -0,0 +1,15 @@
++config IMX_HAVE_PLATFORM_FLEXCAN
++      select HAVE_CAN_FLEXCAN
++      bool
++
++config IMX_HAVE_PLATFORM_IMX_I2C
++      bool
++
++config IMX_HAVE_PLATFORM_IMX_UART
++      bool
++
++config IMX_HAVE_PLATFORM_MXC_NAND
++      bool
++
++config IMX_HAVE_PLATFORM_SPI_IMX
++      bool
+diff -urN linux.35.old/arch/arm/plat-mxc/devices/Makefile linux.35.new/arch/arm/plat-mxc/devices/Makefile
+--- linux.35.old/arch/arm/plat-mxc/devices/Makefile    1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/devices/Makefile    2010-12-03 09:51:55.364349489 +0100
+@@ -0,0 +1,8 @@
++ifdef CONFIG_CAN_FLEXCAN
++# the ifdef can be removed once the flexcan driver has been merged
++obj-$(CONFIG_IMX_HAVE_PLATFORM_FLEXCAN) +=  platform-flexcan.o
++endif
++obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_I2C) += platform-imx-i2c.o
++obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX_UART) += platform-imx-uart.o
++#obj-$(CONFIG_IMX_HAVE_PLATFORM_MXC_NAND) += platform-mxc_nand.o
++obj-$(CONFIG_IMX_HAVE_PLATFORM_SPI_IMX) +=  platform-spi_imx.o
+diff -urN linux.35.old/arch/arm/plat-mxc/devices/platform-flexcan.c linux.35.new/arch/arm/plat-mxc/devices/platform-flexcan.c
+--- linux.35.old/arch/arm/plat-mxc/devices/platform-flexcan.c  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/devices/platform-flexcan.c  2010-12-03 09:51:55.364349489 +0100
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (C) 2010 Pengutronix, Marc Kleine-Budde <kernel@pengutronix.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.
++ */
++
++#include <mach/devices-common.h>
++
++struct platform_device *__init imx_add_flexcan(int id,
++              resource_size_t iobase, resource_size_t iosize,
++              resource_size_t irq,
++              const struct flexcan_platform_data *pdata)
++{
++      struct resource res[] = {
++              {
++                      .start = iobase,
++                      .end = iobase + iosize - 1,
++                      .flags = IORESOURCE_MEM,
++              }, {
++                      .start = irq,
++                      .end = irq,
++                      .flags = IORESOURCE_IRQ,
++              },
++      };
++
++      return imx_add_platform_device("flexcan", id, res, ARRAY_SIZE(res),
++                      pdata, sizeof(*pdata));
++}
+diff -urN linux.35.old/arch/arm/plat-mxc/devices/platform-imx-i2c.c linux.35.new/arch/arm/plat-mxc/devices/platform-imx-i2c.c
+--- linux.35.old/arch/arm/plat-mxc/devices/platform-imx-i2c.c  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/devices/platform-imx-i2c.c  2010-12-03 09:51:55.364349489 +0100
+@@ -0,0 +1,29 @@
++/*
++ * Copyright (C) 2009-2010 Pengutronix
++ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.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.
++ */
++#include <mach/devices-common.h>
++
++struct platform_device *__init imx_add_imx_i2c(int id,
++              resource_size_t iobase, resource_size_t iosize, int irq,
++              const struct imxi2c_platform_data *pdata)
++{
++      struct resource res[] = {
++              {
++                      .start = iobase,
++                      .end = iobase + iosize - 1,
++                      .flags = IORESOURCE_MEM,
++              }, {
++                      .start = irq,
++                      .end = irq,
++                      .flags = IORESOURCE_IRQ,
++              },
++      };
++
++      return imx_add_platform_device("imx-i2c", id, res, ARRAY_SIZE(res),
++                      pdata, sizeof(*pdata));
++}
+diff -urN linux.35.old/arch/arm/plat-mxc/devices/platform-imx-uart.c linux.35.new/arch/arm/plat-mxc/devices/platform-imx-uart.c
+--- linux.35.old/arch/arm/plat-mxc/devices/platform-imx-uart.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/devices/platform-imx-uart.c 2010-12-03 09:51:55.364349489 +0100
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (C) 2009-2010 Pengutronix
++ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.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.
++ */
++#include <mach/devices-common.h>
++
++struct platform_device *__init imx_add_imx_uart_3irq(int id,
++              resource_size_t iobase, resource_size_t iosize,
++              resource_size_t irqrx, resource_size_t irqtx,
++              resource_size_t irqrts,
++              const struct imxuart_platform_data *pdata)
++{
++      struct resource res[] = {
++              {
++                      .start = iobase,
++                      .end = iobase + iosize - 1,
++                      .flags = IORESOURCE_MEM,
++              }, {
++                      .start = irqrx,
++                      .end = irqrx,
++                      .flags = IORESOURCE_IRQ,
++              }, {
++                      .start = irqtx,
++                      .end = irqtx,
++                      .flags = IORESOURCE_IRQ,
++              }, {
++                      .start = irqrts,
++                      .end = irqrx,
++                      .flags = IORESOURCE_IRQ,
++              },
++      };
++
++      return imx_add_platform_device("imx-uart", id, res, ARRAY_SIZE(res),
++                      pdata, sizeof(*pdata));
++}
++
++struct platform_device *__init imx_add_imx_uart_1irq(int id,
++              resource_size_t iobase, resource_size_t iosize,
++              resource_size_t irq,
++              const struct imxuart_platform_data *pdata)
++{
++      struct resource res[] = {
++              {
++                      .start = iobase,
++                      .end = iobase + iosize - 1,
++                      .flags = IORESOURCE_MEM,
++              }, {
++                      .start = irq,
++                      .end = irq,
++                      .flags = IORESOURCE_IRQ,
++              },
++      };
++
++      return imx_add_platform_device("imx-uart", id, res, ARRAY_SIZE(res),
++                      pdata, sizeof(*pdata));
++}
+diff -urN linux.35.old/arch/arm/plat-mxc/devices/platform-spi_imx.c linux.35.new/arch/arm/plat-mxc/devices/platform-spi_imx.c
+--- linux.35.old/arch/arm/plat-mxc/devices/platform-spi_imx.c  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/devices/platform-spi_imx.c  2010-12-03 09:51:55.364349489 +0100
+@@ -0,0 +1,30 @@
++/*
++ * Copyright (C) 2009-2010 Pengutronix
++ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.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.
++ */
++#include <asm/sizes.h>
++#include <mach/devices-common.h>
++
++struct platform_device *__init imx_add_spi_imx(int id,
++              resource_size_t iobase, resource_size_t iosize, int irq,
++              const struct spi_imx_master *pdata)
++{
++      struct resource res[] = {
++              {
++                      .start = iobase,
++                      .end = iobase + iosize - 1,
++                      .flags = IORESOURCE_MEM,
++              }, {
++                      .start = irq,
++                      .end = irq,
++                      .flags = IORESOURCE_IRQ,
++              },
++      };
++
++      return imx_add_platform_device("spi_imx", id, res, ARRAY_SIZE(res),
++                      pdata, sizeof(*pdata));
++}
+diff -urN linux.35.old/arch/arm/plat-mxc/devices.c linux.35.new/arch/arm/plat-mxc/devices.c
+--- linux.35.old/arch/arm/plat-mxc/devices.c   2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/devices.c   2010-12-03 09:51:55.364349489 +0100
+@@ -18,6 +18,7 @@
+ #include <linux/kernel.h>
+ #include <linux/init.h>
++#include <linux/err.h>
+ #include <linux/platform_device.h>
+ #include <mach/common.h>
+@@ -35,3 +36,35 @@
+       return ret;
+ }
++struct platform_device *__init imx_add_platform_device(const char *name, int id,
++              const struct resource *res, unsigned int num_resources,
++              const void *data, size_t size_data)
++{
++      int ret = -ENOMEM;
++      struct platform_device *pdev;
++
++      pdev = platform_device_alloc(name, id);
++      if (!pdev)
++              goto err;
++
++      if (res) {
++              ret = platform_device_add_resources(pdev, res, num_resources);
++              if (ret)
++                      goto err;
++      }
++
++      if (data) {
++              ret = platform_device_add_data(pdev, data, size_data);
++              if (ret)
++                      goto err;
++      }
++
++      ret = platform_device_add(pdev);
++      if (ret) {
++err:
++              platform_device_put(pdev);
++              return ERR_PTR(ret);
++      }
++
++      return pdev;
++}
+diff -urN linux.35.old/arch/arm/plat-mxc/ehci.c linux.35.new/arch/arm/plat-mxc/ehci.c
+--- linux.35.old/arch/arm/plat-mxc/ehci.c      2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/ehci.c      2010-12-03 09:51:55.364349489 +0100
+@@ -11,10 +11,6 @@
+  * 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>
+@@ -25,6 +21,19 @@
+ #define USBCTRL_OTGBASE_OFFSET        0x600
++
++#define MX25_OTG_SIC_SHIFT    29
++#define MX25_OTG_SIC_MASK     (0x3 << MX25_OTG_SIC_SHIFT)
++#define MX25_OTG_PM_BIT               (1 << 24)
++
++#define MX25_H1_SIC_SHIFT     21
++#define MX25_H1_SIC_MASK      (0x3 << MX25_H1_SIC_SHIFT)
++#define MX25_H1_PM_BIT                (1 << 16)
++#define MX25_H1_IPPUE_UP_BIT  (1 << 7)
++#define MX25_H1_IPPUE_DOWN_BIT        (1 << 6)
++#define MX25_H1_TLL_BIT               (1 << 5)
++#define MX25_H1_USBTE_BIT     (1 << 4)
++
+ #define MX31_OTG_SIC_SHIFT    29
+ #define MX31_OTG_SIC_MASK     (0x3 << MX31_OTG_SIC_SHIFT)
+ #define MX31_OTG_PM_BIT               (1 << 24)
+@@ -73,7 +82,51 @@
+ int mxc_initialize_usb_hw(int port, unsigned int flags)
+ {
+       unsigned int v;
+-#ifdef CONFIG_ARCH_MX3
++#if defined(CONFIG_ARCH_MX25)
++      if (cpu_is_mx25()) {
++              v = readl(MX25_IO_ADDRESS(MX25_OTG_BASE_ADDR +
++                                   USBCTRL_OTGBASE_OFFSET));
++
++              switch (port) {
++              case 0: /* OTG port */
++                      v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT);
++                      v |= (flags & MXC_EHCI_INTERFACE_MASK)
++                                      << MX25_OTG_SIC_SHIFT;
++                      if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
++                              v |= MX25_OTG_PM_BIT;
++
++                      break;
++              case 1: /* H1 port */
++                      v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_TLL_BIT |
++                              MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | MX25_H1_IPPUE_UP_BIT);
++                      v |= (flags & MXC_EHCI_INTERFACE_MASK)
++                                              << MX35_H1_SIC_SHIFT;
++                      if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
++                              v |= MX25_H1_PM_BIT;
++
++                      if (!(flags & MXC_EHCI_TTL_ENABLED))
++                              v |= MX25_H1_TLL_BIT;
++
++                      if (flags & MXC_EHCI_INTERNAL_PHY)
++                              v |= MX25_H1_USBTE_BIT;
++
++                      if (flags & MXC_EHCI_IPPUE_DOWN)
++                              v |= MX25_H1_IPPUE_DOWN_BIT;
++
++                      if (flags & MXC_EHCI_IPPUE_UP)
++                              v |= MX25_H1_IPPUE_UP_BIT;
++
++                      break;
++              default:
++                      return -EINVAL;
++              }
++
++              writel(v, MX25_IO_ADDRESS(MX25_OTG_BASE_ADDR +
++                                   USBCTRL_OTGBASE_OFFSET));
++              return 0;
++      }
++#endif /* CONFIG_ARCH_MX25 */
++#if defined(CONFIG_ARCH_MX3)
+       if (cpu_is_mx31()) {
+               v = readl(MX31_IO_ADDRESS(MX31_OTG_BASE_ADDR +
+                                    USBCTRL_OTGBASE_OFFSET));
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/board-vmx25.h linux.35.new/arch/arm/plat-mxc/include/mach/board-vmx25.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/board-vmx25.h  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/include/mach/board-vmx25.h  2010-12-03 09:51:55.364349489 +0100
+@@ -0,0 +1,15 @@
++/*
++ * Copyright 2010 <support@voipac.com>
++ *
++ * 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_BOARD_VMX25_H__
++#define __ASM_ARCH_MXC_BOARD_VMX25_H__
++
++#endif /* __ASM_ARCH_MXC_BOARD_VMX25_H__ */
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/devices-common.h linux.35.new/arch/arm/plat-mxc/include/mach/devices-common.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/devices-common.h       1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/include/mach/devices-common.h       2010-12-03 09:51:55.368349274 +0100
+@@ -0,0 +1,60 @@
++/*
++ * Copyright (C) 2009-2010 Pengutronix
++ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.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.
++ */
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/init.h>
++
++struct platform_device *imx_add_platform_device(const char *name, int id,
++              const struct resource *res, unsigned int num_resources,
++              const void *data, size_t size_data);
++
++#if defined (CONFIG_CAN_FLEXCAN) || defined (CONFIG_CAN_FLEXCAN_MODULE)
++#include <linux/can/platform/flexcan.h>
++struct platform_device *__init imx_add_flexcan(int id,
++              resource_size_t iobase, resource_size_t iosize,
++              resource_size_t irq,
++              const struct flexcan_platform_data *pdata);
++#else
++/* the ifdef can be removed once the flexcan driver has been merged */
++struct flexcan_platform_data;
++static inline struct platform_device *__init imx_add_flexcan(int id,
++              resource_size_t iobase, resource_size_t iosize,
++              resource_size_t irq,
++              const struct flexcan_platform_data *pdata)
++{
++      return NULL;
++}
++#endif
++
++#include <mach/i2c.h>
++struct platform_device *__init imx_add_imx_i2c(int id,
++              resource_size_t iobase, resource_size_t iosize, int irq,
++              const struct imxi2c_platform_data *pdata);
++
++#include <mach/imx-uart.h>
++struct platform_device *__init imx_add_imx_uart_3irq(int id,
++              resource_size_t iobase, resource_size_t iosize,
++              resource_size_t irqrx, resource_size_t irqtx,
++              resource_size_t irqrts,
++              const struct imxuart_platform_data *pdata);
++struct platform_device *__init imx_add_imx_uart_1irq(int id,
++              resource_size_t iobase, resource_size_t iosize,
++              resource_size_t irq,
++              const struct imxuart_platform_data *pdata);
++
++#include <mach/mxc_nand.h>
++struct platform_device *__init imx_add_mxc_nand_v1(resource_size_t iobase,
++              int irq, const struct mxc_nand_platform_data *pdata);
++struct platform_device *__init imx_add_mxc_nand_v21(resource_size_t iobase,
++              int irq, const struct mxc_nand_platform_data *pdata);
++
++#include <mach/spi.h>
++struct platform_device *__init imx_add_spi_imx(int id,
++              resource_size_t iobase, resource_size_t iosize, int irq,
++              const struct spi_imx_master *pdata);
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/dma.h linux.35.new/arch/arm/plat-mxc/include/mach/dma.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/dma.h  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/include/mach/dma.h  2010-12-03 09:51:55.368349274 +0100
+@@ -0,0 +1,293 @@
++/*
++ * Copyright 2004-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.
++ */
++
++#ifndef __ASM_ARCH_MXC_DMA_H__
++#define __ASM_ARCH_MXC_DMA_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_ASRCA_ESAI,
++      MXC_DMA_ASRCB_ESAI,
++      MXC_DMA_ASRCC_ESAI,
++      MXC_DMA_ASRCA_SSI1_TX0,
++      MXC_DMA_ASRCA_SSI1_TX1,
++      MXC_DMA_ASRCA_SSI2_TX0,
++      MXC_DMA_ASRCA_SSI2_TX1,
++      MXC_DMA_ASRCB_SSI1_TX0,
++      MXC_DMA_ASRCB_SSI1_TX1,
++      MXC_DMA_ASRCB_SSI2_TX0,
++      MXC_DMA_ASRCB_SSI2_TX1,
++      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 number */
++      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 struct contains the information for asrc special*/
++struct dma_channel_asrc_info {
++      u32 channs;             /* data channels in asrc */
++};
++
++/*! This struct contains  the information for device special*/
++struct dma_channel_info {
++      struct dma_channel_asrc_info asrc;      /* asrc special information */
++};
++
++#if defined(CONFIG_ARCH_MX27) || defined(CONFIG_ARCH_MX21)
++#include <mach/mx2_dma.h>
++#else
++#include <mach/sdma.h>
++#endif
++
++struct scatterlist;
++
++/*!
++ * 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
++ * @param data         the customized parameter for special channel.
++ * @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_ext(mxc_dma_device_t channel_id, char *dev_name,
++                             struct dma_channel_info *info);
++
++static inline int mxc_dma_request(mxc_dma_device_t channel_id, char *dev_name)
++{
++      return mxc_dma_request_ext(channel_id, dev_name, NULL);
++}
++
++/*!
++ * 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 -urN linux.35.old/arch/arm/plat-mxc/include/mach/imxfb.h linux.35.new/arch/arm/plat-mxc/include/mach/imxfb.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/imxfb.h        2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/include/mach/imxfb.h        2010-12-03 09:51:55.368349274 +0100
+@@ -17,6 +17,7 @@
+ #define PCR_BPIX_12   (4 << 25)
+ #define PCR_BPIX_16   (5 << 25)
+ #define PCR_BPIX_18   (6 << 25)
++#define PCR_BPIX_24   (7 << 25)
+ #define PCR_PIXPOL    (1 << 24)
+ #define PCR_FLMPOL    (1 << 23)
+ #define PCR_LPPOL     (1 << 22)
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/iomux-mx25.h linux.35.new/arch/arm/plat-mxc/include/mach/iomux-mx25.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/iomux-mx25.h   2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/include/mach/iomux-mx25.h   2010-12-03 09:51:55.368349274 +0100
+@@ -155,7 +155,7 @@
+ #define MX25_PAD_D10__D10             IOMUX_PAD(0x294, 0x09c, 0x00, 0, 0, NO_PAD_CTRL)
+ #define MX25_PAD_D10__GPIO_4_10               IOMUX_PAD(0x294, 0x09c, 0x05, 0, 0, NO_PAD_CTRL)
+-#define MX25_PAD_D10__USBOTG_OC               IOMUX_PAD(0x294, 0x09c, 0x06, 0x57c, 0, PAD_CTL_PUS_100K_UP)
++#define MX25_PAD_D10__USBOTG_OC               IOMUX_PAD(0x294, 0x09c, 0x06, 0x57c, 0, PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_22K_UP)
+ #define MX25_PAD_D9__D9                       IOMUX_PAD(0x298, 0x0a0, 0x00, 0, 0, NO_PAD_CTRL)
+ #define MX25_PAD_D9__GPIO_4_11                IOMUX_PAD(0x298, 0x0a0, 0x05, 0, 0, NO_PAD_CTRL)
+@@ -163,7 +163,7 @@
+ #define MX25_PAD_D8__D8                       IOMUX_PAD(0x29c, 0x0a4, 0x00, 0, 0, NO_PAD_CTRL)
+ #define MX25_PAD_D8__GPIO_4_12                IOMUX_PAD(0x29c, 0x0a4, 0x05, 0, 0, NO_PAD_CTRL)
+-#define MX25_PAD_D8__USBH2_OC         IOMUX_PAD(0x29c, 0x0a4, 0x06, 0x580, 0, PAD_CTL_PUS_100K_UP)
++#define MX25_PAD_D8__USBH2_OC         IOMUX_PAD(0x29c, 0x0a4, 0x06, 0x580, 0, PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_22K_UP)
+ #define MX25_PAD_D7__D7                       IOMUX_PAD(0x2a0, 0x0a8, 0x00, 0, 0, NO_PAD_CTRL)
+ #define MX25_PAD_D7__GPIO_4_13                IOMUX_PAD(0x2a0, 0x0a8, 0x05, 0, 0, NO_PAD_CTRL)
+@@ -371,31 +371,31 @@
+ #define MX25_PAD_SD1_DATA3__FEC_CRS   IOMUX_PAD(0x39c, 0x1a4, 0x10, 0x508, 2, NO_PAD_CTRL)
+ #define MX25_PAD_SD1_DATA3__GPIO_2_28 IOMUX_PAD(0x39c, 0x1a4, 0x15, 0, 0, NO_PAD_CTRL)
+-#define MX25_PAD_KPP_ROW0__KPP_ROW0   IOMUX_PAD(0x3a0, 0x1a8, 0x10, 0, 0, PAD_CTL_PKE)
+-#define MX25_PAD_KPP_ROW0__GPIO_2_29  IOMUX_PAD(0x3a0, 0x1a8, 0x15, 0, 0, NO_PAD_CTRL)
++#define MX25_PAD_KPP_ROW0__KPP_ROW0   IOMUX_PAD(0x3a0, 0x1a8, 0x00, 0, 0, PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
++#define MX25_PAD_KPP_ROW0__GPIO_2_29  IOMUX_PAD(0x3a0, 0x1a8, 0x05, 0, 0, NO_PAD_CTRL)
+-#define MX25_PAD_KPP_ROW1__KPP_ROW1   IOMUX_PAD(0x3a4, 0x1ac, 0x10, 0, 0, PAD_CTL_PKE)
+-#define MX25_PAD_KPP_ROW1__GPIO_2_30  IOMUX_PAD(0x3a4, 0x1ac, 0x15, 0, 0, NO_PAD_CTRL)
++#define MX25_PAD_KPP_ROW1__KPP_ROW1   IOMUX_PAD(0x3a4, 0x1ac, 0x00, 0, 0, PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
++#define MX25_PAD_KPP_ROW1__GPIO_2_30  IOMUX_PAD(0x3a4, 0x1ac, 0x05, 0, 0, NO_PAD_CTRL)
+-#define MX25_PAD_KPP_ROW2__KPP_ROW2   IOMUX_PAD(0x3a8, 0x1b0, 0x10, 0, 0, PAD_CTL_PKE)
+-#define MX25_PAD_KPP_ROW2__CSI_D0     IOMUX_PAD(0x3a8, 0x1b0, 0x13, 0x488, 2, NO_PAD_CTRL)
+-#define MX25_PAD_KPP_ROW2__GPIO_2_31  IOMUX_PAD(0x3a8, 0x1b0, 0x15, 0, 0, NO_PAD_CTRL)
++#define MX25_PAD_KPP_ROW2__KPP_ROW2   IOMUX_PAD(0x3a8, 0x1b0, 0x00, 0, 0, PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
++#define MX25_PAD_KPP_ROW2__CSI_D0     IOMUX_PAD(0x3a8, 0x1b0, 0x03, 0x488, 2, NO_PAD_CTRL)
++#define MX25_PAD_KPP_ROW2__GPIO_2_31  IOMUX_PAD(0x3a8, 0x1b0, 0x05, 0, 0, NO_PAD_CTRL)
+-#define MX25_PAD_KPP_ROW3__KPP_ROW3   IOMUX_PAD(0x3ac, 0x1b4, 0x10, 0, 0, PAD_CTL_PKE)
+-#define MX25_PAD_KPP_ROW3__CSI_LD1    IOMUX_PAD(0x3ac, 0x1b4, 0x13, 0x48c, 2, NO_PAD_CTRL)
+-#define MX25_PAD_KPP_ROW3__GPIO_3_0   IOMUX_PAD(0x3ac, 0x1b4, 0x15, 0, 0, NO_PAD_CTRL)
++#define MX25_PAD_KPP_ROW3__KPP_ROW3   IOMUX_PAD(0x3ac, 0x1b4, 0x00, 0, 0, PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
++#define MX25_PAD_KPP_ROW3__CSI_LD1    IOMUX_PAD(0x3ac, 0x1b4, 0x03, 0x48c, 2, NO_PAD_CTRL)
++#define MX25_PAD_KPP_ROW3__GPIO_3_0   IOMUX_PAD(0x3ac, 0x1b4, 0x05, 0, 0, NO_PAD_CTRL)
+-#define MX25_PAD_KPP_COL0__KPP_COL0   IOMUX_PAD(0x3b0, 0x1b8, 0x10, 0, 0, PAD_CTL_PKE | PAD_CTL_ODE)
+-#define MX25_PAD_KPP_COL0__GPIO_3_1   IOMUX_PAD(0x3b0, 0x1b8, 0x15, 0, 0, NO_PAD_CTRL)
++#define MX25_PAD_KPP_COL0__KPP_COL0   IOMUX_PAD(0x3b0, 0x1b8, 0x00, 0, 0, PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP | PAD_CTL_ODE)
++#define MX25_PAD_KPP_COL0__GPIO_3_1   IOMUX_PAD(0x3b0, 0x1b8, 0x05, 0, 0, NO_PAD_CTRL)
+-#define MX25_PAD_KPP_COL1__KPP_COL1   IOMUX_PAD(0x3b4, 0x1bc, 0x10, 0, 0, PAD_CTL_PKE | PAD_CTL_ODE)
+-#define MX25_PAD_KPP_COL1__GPIO_3_2   IOMUX_PAD(0x3b4, 0x1bc, 0x15, 0, 0, NO_PAD_CTRL)
++#define MX25_PAD_KPP_COL1__KPP_COL1   IOMUX_PAD(0x3b4, 0x1bc, 0x00, 0, 0, PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP | PAD_CTL_ODE)
++#define MX25_PAD_KPP_COL1__GPIO_3_2   IOMUX_PAD(0x3b4, 0x1bc, 0x05, 0, 0, NO_PAD_CTRL)
+-#define MX25_PAD_KPP_COL2__KPP_COL2   IOMUX_PAD(0x3b8, 0x1c0, 0x10, 0, 0, PAD_CTL_PKE | PAD_CTL_ODE)
+-#define MX25_PAD_KPP_COL2__GPIO_3_3   IOMUX_PAD(0x3b8, 0x1c0, 0x15, 0, 0, NO_PAD_CTRL)
++#define MX25_PAD_KPP_COL2__KPP_COL2   IOMUX_PAD(0x3b8, 0x1c0, 0x00, 0, 0, PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP | PAD_CTL_ODE)
++#define MX25_PAD_KPP_COL2__GPIO_3_3   IOMUX_PAD(0x3b8, 0x1c0, 0x05, 0, 0, NO_PAD_CTRL)
+-#define MX25_PAD_KPP_COL3__KPP_COL3   IOMUX_PAD(0x3bc, 0x1c4, 0x10, 0, 0, PAD_CTL_PKE | PAD_CTL_ODE)
+-#define MX25_PAD_KPP_COL3__GPIO_3_4   IOMUX_PAD(0x3bc, 0x1c4, 0x15, 0, 0, NO_PAD_CTRL)
++#define MX25_PAD_KPP_COL3__KPP_COL3   IOMUX_PAD(0x3bc, 0x1c4, 0x00, 0, 0, PAD_CTL_PKE | PAD_CTL_PUE | PAD_CTL_PUS_100K_UP | PAD_CTL_ODE)
++#define MX25_PAD_KPP_COL3__GPIO_3_4   IOMUX_PAD(0x3bc, 0x1c4, 0x05, 0, 0, NO_PAD_CTRL)
+ #define MX25_PAD_FEC_MDC__FEC_MDC     IOMUX_PAD(0x3c0, 0x1c8, 0x10, 0, 0, NO_PAD_CTRL)
+ #define MX25_PAD_FEC_MDC__AUD4_TXD    IOMUX_PAD(0x3c0, 0x1c8, 0x12, 0x464, 1, NO_PAD_CTRL)
+@@ -442,7 +442,7 @@
+ #define MX25_PAD_GPIO_A__USBOTG_PWR   IOMUX_PAD(0x3f0, 0x1f4, 0x12, 0, 0, PAD_CTL_PKE)
+ #define MX25_PAD_GPIO_B__GPIO_B               IOMUX_PAD(0x3f4, 0x1f8, 0x10, 0, 0, NO_PAD_CTRL)
+-#define MX25_PAD_GPIO_B__CAN1_RX      IOMUX_PAD(0x3f4, 0x1f8, 0x16, 0x480, 1, PAD_CTL_PUS_22K)
++#define MX25_PAD_GPIO_B__CAN1_RX      IOMUX_PAD(0x3f4, 0x1f8, 0x16, 0x480, 1, PAD_CTL_PUS_22K_UP)
+ #define MX25_PAD_GPIO_B__USBOTG_OC    IOMUX_PAD(0x3f4, 0x1f8, 0x12, 0x57c, 1, PAD_CTL_PUS_100K_UP)
+ #define MX25_PAD_GPIO_C__GPIO_C               IOMUX_PAD(0x3f8, 0x1fc, 0x10, 0, 0, NO_PAD_CTRL)
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/iomux-v3.h linux.35.new/arch/arm/plat-mxc/include/mach/iomux-v3.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/iomux-v3.h     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/include/mach/iomux-v3.h     2010-12-03 09:51:55.372348122 +0100
+@@ -101,6 +101,19 @@
+ int mxc_iomux_v3_setup_multiple_pads(struct pad_desc *pad_list, unsigned count);
+ /*
++ * releases a single pad:
++ *    - make it available for a future use by another driver
++ *    - DOES NOT reconfigure the IOMUX in its reset state
++ */
++void mxc_iomux_v3_release_pad(struct pad_desc *pad);
++
++/*
++ * releases multiple pads
++ * convenvient way to call the above function with tables
++ */
++void mxc_iomux_v3_release_multiple_pads(struct pad_desc *pad_list, int count);
++
++/*
+  * Initialise the iomux controller
+  */
+ void mxc_iomux_v3_init(void __iomem *iomux_v3_base);
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/memory.h linux.35.new/arch/arm/plat-mxc/include/mach/memory.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/memory.h       2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/include/mach/memory.h       2011-01-12 14:23:34.124489511 +0100
+@@ -50,6 +50,13 @@
+  * This is required for i.MX camera driver to capture at least four VGA frames.
+  */
+ #define CONSISTENT_DMA_SIZE SZ_4M
++
++#elif defined(CONFIG_ARCH_MX25)
++/*
++ * Increase size of DMA-consistent memory region.
++ * This is required for i.MX fb driver to support android on VGA screens at 32 bit.
++ */
++#define CONSISTENT_DMA_SIZE SZ_4M
+ #endif /* CONFIG_MX1_VIDEO */
+ #endif /* __ASM_ARCH_MXC_MEMORY_H__ */
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/mx25.h linux.35.new/arch/arm/plat-mxc/include/mach/mx25.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/mx25.h 2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/include/mach/mx25.h 2010-12-03 09:51:55.372348122 +0100
+@@ -1,6 +1,10 @@
+ #ifndef __MACH_MX25_H__
+ #define __MACH_MX25_H__
++#define SDMA_V2
++
++#define CSD0_BASE_ADDR                        0x80000000
++
+ #define MX25_AIPS1_BASE_ADDR          0x43f00000
+ #define MX25_AIPS1_BASE_ADDR_VIRT     0xfc000000
+ #define MX25_AIPS1_SIZE                       SZ_1M
+@@ -10,9 +14,19 @@
+ #define MX25_AVIC_BASE_ADDR           0x68000000
+ #define MX25_AVIC_BASE_ADDR_VIRT      0xfc400000
+ #define MX25_AVIC_SIZE                        SZ_1M
+-
++#define MX25_SPBA0_BASE_ADDR          UL(0x50000000)
++#define MX25_SPBA0_BASE_ADDR_VIRT     0xFC100000
++#define MX25_SPBA0_SIZE                       SZ_1M
++
++#define MX25_I2C1_BASE_ADDR           (MX25_AIPS1_BASE_ADDR + 0x80000)
++#define MX25_I2C3_BASE_ADDR           (MX25_AIPS1_BASE_ADDR + 0x84000)
++#define MX25_CAN1_BASE_ADDR           (MX25_AIPS1_BASE_ADDR + 0x88000)
++#define MX25_CAN2_BASE_ADDR           (MX25_AIPS1_BASE_ADDR + 0x8c000)
++#define MX25_I2C2_BASE_ADDR           (MX25_AIPS1_BASE_ADDR + 0x98000)
++#define MX25_OWIRE_BASE_ADDR          (MX25_AIPS1_BASE_ADDR + 0x9c000)
++#define MX25_CSPI1_BASE_ADDR          (MX25_AIPS1_BASE_ADDR + 0xa4000)
+ #define MX25_IOMUXC_BASE_ADDR         (MX25_AIPS1_BASE_ADDR + 0xac000)
+-
++#define AUDMUX_BASE_ADDR              (MX25_AIPS1_BASE_ADDR + 0xb0000)
+ #define MX25_CRM_BASE_ADDR            (MX25_AIPS2_BASE_ADDR + 0x80000)
+ #define MX25_GPT1_BASE_ADDR           (MX25_AIPS2_BASE_ADDR + 0x90000)
+ #define MX25_WDOG_BASE_ADDR           (MX25_AIPS2_BASE_ADDR + 0xdc000)
+@@ -27,22 +41,205 @@
+       IMX_IO_ADDRESS(x, MX25_AIPS2) ?:                        \
+       IMX_IO_ADDRESS(x, MX25_AVIC))
++#define MX25_AIPS1_IO_ADDRESS(x) \
++      (((x) - MX25_AIPS1_BASE_ADDR) + MX25_AIPS1_BASE_ADDR_VIRT)
++#define MX25_AIPS2_IO_ADDRESS(x)  \
++      (((x) - MX25_AIPS2_BASE_ADDR) + MX25_AIPS2_BASE_ADDR_VIRT)
++#define MX25_AVIC_IO_ADDRESS(x)  \
++      (((x) - MX25_AVIC_BASE_ADDR) + MX25_AVIC_BASE_ADDR_VIRT)
++
+ #define MX25_UART1_BASE_ADDR          0x43f90000
+ #define MX25_UART2_BASE_ADDR          0x43f94000
++#define MX25_AUDMUX_BASE_ADDR         0x43fb0000
++#define MX25_UART3_BASE_ADDR          0x5000c000
++#define MX25_UART4_BASE_ADDR          0x50008000
++#define MX25_UART5_BASE_ADDR          0x5002c000
++#define MX25_CSPI3_BASE_ADDR          0x50004000
++#define MX25_CSPI2_BASE_ADDR          0x50010000
+ #define MX25_FEC_BASE_ADDR            0x50038000
++#define MX25_SSI2_BASE_ADDR           0x50014000
++#define MX25_SSI1_BASE_ADDR           0x50034000
+ #define MX25_NFC_BASE_ADDR            0xbb000000
+-#define MX25_DRYICE_BASE_ADDR         0x53ffc000
+ #define MX25_LCDC_BASE_ADDR           0x53fbc000
++#define MX25_OTG_BASE_ADDR            0x53ff4000
+-#define MX25_INT_DRYICE       25
+-#define MX25_INT_FEC  57
+ #define MX25_INT_NANDFC       33
+ #define MX25_INT_LCDC 39
+-#if defined(IMX_NEEDS_DEPRECATED_SYMBOLS)
+-#define UART1_BASE_ADDR                       MX25_UART1_BASE_ADDR
+-#define UART2_BASE_ADDR                       MX25_UART2_BASE_ADDR
++#define IO_ADDRESS(x)         MX25_IO_ADDRESS(x)
++#define AVIC_IO_ADDRESS(x)    MX25_AVIC_IO_ADDRESS(x)
++#define AVIC_BASE_ADDR                MX25_AVIC_BASE_ADDR
++#define FEC_BASE_ADDR         (MX25_FEC_BASE_ADDR)
++#define IIM_BASE_ADDR         (MX25_AIPS2_BASE_ADDR + 0x000F0000)
++//MMC
++#define MMC_SDHC1_BASE_ADDR     (MX25_AIPS2_BASE_ADDR + 0x000B4000)
++#define MMC_SDHC2_BASE_ADDR     (MX25_AIPS2_BASE_ADDR + 0x000B8000)
++//SDMA(MMC) +  (audio)
++#define SSI1_BASE_ADDR                (MX25_SPBA0_BASE_ADDR + 0x00034000)
++#define SSI2_BASE_ADDR                (MX25_SPBA0_BASE_ADDR + 0x00014000)
++#define ESAI_BASE_ADDR                (MX25_SPBA0_BASE_ADDR + 0x00018000)
++#define SDMA_BASE_ADDR                (MX25_AIPS2_BASE_ADDR + 0x000D4000)
++//WTD
++#define WDOG_BASE_ADDR          (MX25_AIPS2_BASE_ADDR + 0x000DC000)
++//ADC
++#define SPBA0_BASE_ADDR               0x50000000
++#define TSC_BASE_ADDR           (SPBA0_BASE_ADDR + 0x00030000)
++//SCC
++#define SCC_BASE_ADDR       (MX25_AIPS2_BASE_ADDR + 0x000AC000)
++//RNG module
++#define RNGB_BASE_ADDR      (MX25_AIPS2_BASE_ADDR + 0x000B0000)
++//DRYICE
++#define DRYICE_BASE_ADDR    (MX25_AIPS2_BASE_ADDR + 0x000FC000)
++
++/*!
++ * 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
++
++/*
++ * 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 MX25_INT_CSPI3                 0
++#define MXC_INT_GPT4           1
++#define MXC_INT_OWIRE          2
++#define MX25_INT_I2C1          3
++#define MX25_INT_I2C2          4
++#define MX25_INT_UART4                 5
++#define MXC_INT_RTIC           6
++#define MXC_INT_ESAI           7
++#define MXC_INT_SDHC2          8
++#define MXC_INT_SDHC1          9
++#define MX25_INT_I2C3         10
++#define MX25_INT_SSI2         11
++#define MX25_INT_SSI1         12
++#define MX25_INT_CSPI2                13
++#define MX25_INT_CSPI1                14
++#define MXC_INT_ATA           15
++#define MXC_INT_GPIO3         16
++#define MXC_INT_CSI           17
++#define MX25_INT_UART3                18
++#define MXC_INT_IIM           19
++#define MXC_INT_SIM1          20
++#define MXC_INT_SIM2          21
++#define MXC_INT_RNG           22
++#define MXC_INT_GPIO4         23
++#define MXC_INT_KPP           24
++#define MXC_INT_DRYICE_NORM   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_CCM           31
++#define MX25_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 MX25_INT_UART5                40
++#define MXC_INT_PWM3          41
++#define MXC_INT_PWM4          42
++#define MX25_INT_CAN1         43
++#define MX25_INT_CAN2         44
++#define MX25_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_SEC    56
++#define MX25_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
++
+ #endif /* ifndef __MACH_MX25_H__ */
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/mxc.h linux.35.new/arch/arm/plat-mxc/include/mach/mxc.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/mxc.h  2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/include/mach/mxc.h  2010-12-03 09:51:55.372348122 +0100
+@@ -143,4 +143,35 @@
+ #define cpu_is_mx3()  (cpu_is_mx31() || cpu_is_mx35() || cpu_is_mxc91231())
+ #define cpu_is_mx2()  (cpu_is_mx21() || cpu_is_mx27())
++#ifndef __ASSEMBLY__
++
++#include <linux/types.h>
++
++/*
++ * This struct is to define the number of SSIs on a platform,
++ * DAM source port config, DAM external port config,
++ * regulator names, and other stuff audio needs.
++ */
++struct mxc_audio_platform_data {
++      int ssi_num;
++      int src_port;
++      int ext_port;
++
++      int intr_id_hp;
++      int ext_ram;
++      struct clk *ssi_clk[2];
++
++      int hp_irq;
++      int (*hp_status) (void);
++
++      int sysclk;
++
++      int (*init) (void);     /* board specific init */
++      int (*amp_enable) (int enable);
++      int (*finit) (void);    /* board specific finit */
++      void *priv;             /* used by board specific functions */
++};
++
++#endif //__ASSEMBLY__
++
+ #endif /*  __ASM_ARCH_MXC_H__ */
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/mxc_nand.h linux.35.new/arch/arm/plat-mxc/include/mach/mxc_nand.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/mxc_nand.h     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/include/mach/mxc_nand.h     2010-12-03 09:51:55.372348122 +0100
+@@ -20,9 +20,14 @@
+ #ifndef __ASM_ARCH_NAND_H
+ #define __ASM_ARCH_NAND_H
++struct mtd_partition;
++struct mtd_info;
++
+ struct mxc_nand_platform_data {
+       int width;      /* data bus width in bytes */
+       int hw_ecc:1;   /* 0 if supress hardware ECC */
+       int flash_bbt:1; /* set to 1 to use a flash based bbt */
++      struct mtd_partition *parts;    /* optional array of mtd_partitions for static partitioning */
++        unsigned int    nr_parts;     /* number of mtd_partitions for static partitoning */
+ };
+ #endif /* __ASM_ARCH_NAND_H */
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/mxc_tsc.h linux.35.new/arch/arm/plat-mxc/include/mach/mxc_tsc.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/mxc_tsc.h      1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/include/mach/mxc_tsc.h      2010-12-03 09:51:55.376350318 +0100
+@@ -0,0 +1,32 @@
++/*
++ *  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_tsc_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 */
++              hsyncpol:1;     /* select HSYNC polarity: 1 == active low */
++      unsigned int r_xplate;  /* resistance (in Ohms) of X plate
++                               * (required for pressure measurement */
++      unsigned int settle_detect; /* Settling time for touch detection (in ADC clock cycles) */
++      unsigned int settle_measure; /* Settling time for measurement (in ADC clock cycles) */
++      unsigned int settle_precharge; /* Settling time for precharge (in ADC clock cycles) */
++      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 -urN linux.35.old/arch/arm/plat-mxc/include/mach/sdhci.h linux.35.new/arch/arm/plat-mxc/include/mach/sdhci.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/sdhci.h        1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/include/mach/sdhci.h        2010-12-20 14:58:29.196000606 +0100
+@@ -0,0 +1,50 @@
++#ifndef __MACH_SDHCI_H
++#define __MACH_SDHCI_H
++
++#include <linux/mmc/host.h>
++struct device;
++
++struct mxc_sdhci_platform_data {
++      /* Return values for the get_ro callback should be:
++       *   0 for a read/write card
++       *   1 for a read-only card
++       *   -ENOSYS when not supported (equal to NULL callback)
++       *   or a negative errno value when something bad happened
++       */
++      int (*get_ro)(struct device *);
++
++      /* board specific hook to (de)initialize the SD slot.
++       * The board code can call 'handler' on a card detection
++       * change giving data as argument.
++       */
++      int (*init)(struct device *dev, irq_handler_t handler, void *data);
++      void (*exit)(struct device *dev, void *data);
++
++      /* delay in ms between card detect IRQ and scanning for
++       * card insertion/removal
++       */
++      int detect_delay;
++
++      /* available voltages. If not given, assume
++       * MMC_VDD_32_33 | MMC_VDD_33_34
++       */
++      unsigned int ocr_avail;
++      unsigned int caps;
++      unsigned int min_clk;
++      unsigned int max_clk;
++      unsigned int mxc_quirks;
++
++      /* adjust slot voltage */
++      int (*setpower)(struct device *dev, unsigned int vdd);
++#if 1
++      // FIXME: get rid of this
++      int (*status)(struct device *dev);
++#endif
++      int (*suspend)(struct device *dev);
++      int (*resume)(struct device *dev);
++
++      /* Set card detection state to 1 */
++      unsigned int force_sd_detect;
++};
++
++#endif /* __MACH_SDHCI_H */
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/sdma.h linux.35.new/arch/arm/plat-mxc/include/mach/sdma.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/sdma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/include/mach/sdma.h 2010-12-03 09:51:55.376350318 +0100
+@@ -0,0 +1,563 @@
++
++/*
++ * Copyright 2004-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
++ */
++
++#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
++
++#define DMA_ADDR_INVALID      ((dma_addr_t)0)
++
++/*!
++ * This defines maximum number of DMA channels
++ */
++#ifdef CONFIG_MXC_SDMA_API
++#define MAX_DMA_CHANNELS              32
++#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
++
++#define SDMA_ASRC_INFO_WML_OFF                0
++#define SDMA_ASRC_INFO_WML_MASK               ((1 << 10) - 1)
++#define SDMA_ASRC_INFO_PS             (1 << 10)
++#define SDMA_ASRC_INFO_PA             (1 << 11)
++#define SDMA_ASRC_INFO_TXFR_DIR               (1 << 14)
++#define SDMA_ASRC_INFO_N_OFF          24
++#define SDMA_ASRC_INFO_N_MASK         ((1 << 4) - 1)
++
++#define SDMA_ASRC_P2P_INFO_LWML_OFF   0
++#define SDMA_ASRC_P2P_INFO_LWML_MASK  ((1 << 8) - 1)
++#define SDMA_ASRC_P2P_INFO_PS         (1 << 8)
++#define SDMA_ASRC_P2P_INFO_PA         (1 << 9)
++#define SDMA_ASRC_P2P_INFO_SPDIF      (1 << 10)
++#define SDMA_ASRC_P2P_INFO_SP         (1 << 11)
++#define SDMA_ASRC_P2P_INFO_DP         (1 << 12)
++#define SDMA_ASRC_P2P_INFO_HWML_OFF   14
++#define SDMA_ASRC_P2P_INFO_HWML_MASK  ((1 << 10) - 1)
++#define SDMA_ASRC_P2P_INFO_LWE                (1 << 28)
++#define SDMA_ASRC_P2P_INFO_HWE                (1 << 29)
++#define SDMA_ASRC_P2P_INFO_CONT               (1 << 31)
++
++/*!
++ * 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
++                               * for p2p, this is event1 watermark level
++                               */
++      __u32 per_address;      /* Peripheral source/destination
++                               * physical address
++                               * for p2p, this is destination 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    */
++      unsigned long ext:1;    /* 1: extend parameter structure */
++} dma_channel_params;
++
++typedef struct {
++      dma_channel_params common;
++      unsigned long p2p_dir:1; /* 0: per2 to per.
++                                * the device of peripheral_type is per.
++                                * 1: per to per2
++                                * the device of peripheral_type is per2
++                                */
++      unsigned long info_bits; /* info field in context */
++      unsigned long info_mask; /* info field mask in context */
++      __u32 watermark_level2; /* event2 threshold that triggers SDMA event
++                               * just valid for per_2_per.
++                               */
++      __u32 per_address2;     /* Peripheral source physical address.
++                               * only valid for per_2_per.
++                               */
++      struct dma_channel_info info;   /* the channel special parameter */
++} dma_channel_ext_params;
++
++/*!
++ * Structure containing sdma request  parameters.
++ */
++typedef struct {
++      /*!   physical source memory address        */
++      dma_addr_t sourceAddr;
++      /*!   physical destination memory address   */
++      dma_addr_t 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
++       */
++      unsigned int bd_done:1,
++      /*!< CONT bit of the buffer descriptor,
++       * set it if full multi-buffer descriptor mechanism
++       * required.
++       */
++              bd_cont:1,
++      /*!< ERROR bit of the buffer descriptor,
++       * updated during mxc_dma_get_config.
++       * If it is set - there was an error during BD processing.
++       */
++              bd_error:1,
++              bd_wrap:1;
++} 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 type (static channel number or dynamic channel) */
++      unsigned int channel_num;
++      /*! Channel priority [0x1(lowest) - 0x7(highest)] */
++      unsigned int chnl_priority;
++      /*! Channel params */
++      dma_channel_params chnl_params;
++} mxc_sdma_channel_params_t;
++
++/*! Structure to store the initialized dma_channel extend parameters */
++typedef struct mxc_sdma_channel_ext_params {
++      /*! Channel type (static channel number or dynamic channel) */
++      unsigned int channel_num;
++      /*! Channel priority [0x1(lowest) - 0x7(highest)] */
++      unsigned int chnl_priority;
++      /*! Channel extend params */
++      dma_channel_ext_params chnl_ext_params;
++} mxc_sdma_channel_ext_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 */
++      unsigned int intr_after_every_bd:1,
++              circular:1;     /* circular BD chain */
++} 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
++ */
++extern 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
++ */
++extern 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
++ */
++extern 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); */
++extern 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); */
++extern 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
++ */
++extern 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
++ */
++extern int mxc_sdma_read_ipcv2(int channel, void *ctrl_ptr);
++
++/*!
++ * Starts dma channel.
++ *
++ * @param   channel           channel number
++ */
++extern int mxc_dma_start(int channel);
++
++/*!
++ * Stops dma channel.
++ *
++ * @param   channel           channel number
++ */
++extern int mxc_dma_stop(int channel);
++
++/*!
++ * Frees dma channel.
++ *
++ * @param   channel           channel number
++ */
++extern 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
++ */
++extern 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
++ */
++extern 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
++ */
++extern 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
++ */
++extern dma_addr_t sdma_virt_to_phys(void *buf);
++
++/*!
++ * Converts physical to virtual address. Uses hash table.
++ *
++ * @param   buf  physical address value
++ * @return  virtual address pointer
++ */
++extern void *sdma_phys_to_virt(dma_addr_t 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
++ */
++extern 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
++ */
++extern 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
++ */
++extern 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
++ */
++extern 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
++ */
++extern void mxc_get_static_channels(mxc_dma_channel_t * chnl);
++
++/*!
++ * Initializes SDMA driver
++ */
++extern int __init sdma_init(void);
++
++extern void mxc_sdma_get_script_info(sdma_script_start_addrs *sdma_script_addr);
++
++#define DEFAULT_ERR     1
++
++#endif
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/spba.h linux.35.new/arch/arm/plat-mxc/include/mach/spba.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/spba.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/include/mach/spba.h 2010-12-03 09:51:55.376350318 +0100
+@@ -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 -urN linux.35.old/arch/arm/plat-mxc/include/mach/ssi.h linux.35.new/arch/arm/plat-mxc/include/mach/ssi.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/ssi.h  2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/include/mach/ssi.h  2010-12-03 09:51:55.380349316 +0100
+@@ -10,6 +10,9 @@
+       unsigned int flags;
+ #define IMX_SSI_DMA            (1 << 0)
+ #define IMX_SSI_USE_AC97       (1 << 1)
++#define IMX_SSI_NET            (1 << 2)
++#define IMX_SSI_SYN            (1 << 3)
++#define IMX_SSI_USE_I2S_SLAVE  (1 << 4)
+       void (*ac97_reset) (struct snd_ac97 *ac97);
+       void (*ac97_warm_reset)(struct snd_ac97 *ac97);
+ };
+diff -urN linux.35.old/arch/arm/plat-mxc/include/mach/ssi_port.h linux.35.new/arch/arm/plat-mxc/include/mach/ssi_port.h
+--- linux.35.old/arch/arm/plat-mxc/include/mach/ssi_port.h     1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/include/mach/ssi_port.h     2010-12-03 09:51:55.380349316 +0100
+@@ -0,0 +1,31 @@
++/*
++ * include/asm-arm/arch-mxc/ssi_port.h
++ *
++ * Copyright (C) 2008  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
++ */
++
++struct mxc_ssi_port {
++      int num;
++      struct module *owner;
++      struct platform_device *parent;
++      struct resource *res;
++      struct clk *ssi_clk;
++      int in_use;
++};
++
++extern int mxc_ssi_request_port(int num, struct platform_device *parent,
++                              struct mxc_ssi_port **ssi_port);
++extern void mxc_ssi_release_port(struct mxc_ssi_port *ssi_port);
+diff -urN linux.35.old/arch/arm/plat-mxc/iomux-v3.c linux.35.new/arch/arm/plat-mxc/iomux-v3.c
+--- linux.35.old/arch/arm/plat-mxc/iomux-v3.c  2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/iomux-v3.c  2010-12-03 09:51:55.380349316 +0100
+@@ -30,12 +30,34 @@
+ #include <mach/iomux-v3.h>
+ static void __iomem *base;
++#ifdef CONFIG_ARCH_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 pad in the iomuxer
+  */
+ int mxc_iomux_v3_setup_pad(struct pad_desc *pad)
+ {
++      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;
+       if (pad->mux_ctrl_ofs)
+               __raw_writel(pad->mux_mode, base + pad->mux_ctrl_ofs);
+@@ -65,6 +87,26 @@
+ }
+ EXPORT_SYMBOL(mxc_iomux_v3_setup_multiple_pads);
++void mxc_iomux_v3_release_pad(struct pad_desc *pad)
++{
++      unsigned int pad_ofs = mxc_iomux_v3_pad_offset(pad);
++
++      clear_bit(pad_ofs >> 2, iomux_v3_pad_alloc_map);
++}
++EXPORT_SYMBOL(mxc_iomux_v3_release_pad);
++
++void mxc_iomux_v3_release_multiple_pads(struct pad_desc *pad_list, int count)
++{
++      struct pad_desc *p = pad_list;
++      int i;
++
++      for (i = 0; i < count; i++) {
++              mxc_iomux_v3_release_pad(p);
++              p++;
++      }
++}
++EXPORT_SYMBOL(mxc_iomux_v3_release_multiple_pads);
++
+ void mxc_iomux_v3_init(void __iomem *iomux_v3_base)
+ {
+       base = iomux_v3_base;
+diff -urN linux.35.old/arch/arm/plat-mxc/Kconfig linux.35.new/arch/arm/plat-mxc/Kconfig
+--- linux.35.old/arch/arm/plat-mxc/Kconfig     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/Kconfig     2010-12-03 09:51:55.380349316 +0100
+@@ -1,5 +1,7 @@
+ if ARCH_MXC
++source "arch/arm/plat-mxc/devices/Kconfig"
++
+ menu "Freescale MXC Implementations"
+ choice
+@@ -25,6 +27,7 @@
+       select CPU_ARM926T
+       select ARCH_MXC_IOMUX_V3
+       select HAVE_FB_IMX
++      select ARCH_MXC_AUDMUX_V2
+       help
+         This enables support for systems based on the Freescale i.MX25 family
+@@ -99,4 +102,14 @@
+ config ARCH_MXC_AUDMUX_V2
+       bool
++config MXC_SSI_PORTS
++      bool "Generic SSI Layer"
++      depends on ARCH_MXC
++      help
++        This option enables the generic SSI layer that makes it possible to
++        write drivers that decide at runtime which SSI port to use.
++        Since the SSI signals must be routed through the AUDMUX, there is no
++        reason to hardwire any driver that utilizes the SSI interface to a specific
++        SSI port.
++
+ endif
+diff -urN linux.35.old/arch/arm/plat-mxc/Makefile linux.35.new/arch/arm/plat-mxc/Makefile
+--- linux.35.old/arch/arm/plat-mxc/Makefile    2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/arch/arm/plat-mxc/Makefile    2010-12-03 09:51:55.380349316 +0100
+@@ -13,6 +13,7 @@
+ obj-$(CONFIG_IMX_HAVE_IOMUX_V1) += iomux-v1.o
+ obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
+ obj-$(CONFIG_MXC_PWM)  += pwm.o
++obj-$(CONFIG_MXC_SDMA_API)    += sdma/
+ obj-$(CONFIG_USB_EHCI_MXC) += ehci.o
+ obj-$(CONFIG_MXC_ULPI) += ulpi.o
+ obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o
+@@ -21,3 +22,8 @@
+ obj-y += ssi-fiq.o
+ obj-y += ssi-fiq-ksym.o
+ endif
++
++obj-y += devices/
++
++mxc-ssi-ports-objs            := ssi.o
++obj-$(CONFIG_MXC_SSI_PORTS)   += mxc-ssi-ports.o
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/dma_sdma.c linux.35.new/arch/arm/plat-mxc/sdma/dma_sdma.c
+--- linux.35.old/arch/arm/plat-mxc/sdma/dma_sdma.c     1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/dma_sdma.c     2010-12-03 09:51:55.384181534 +0100
+@@ -0,0 +1,763 @@
++/*
++ * Copyright 2004-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 plat-mxc/sdma/dma_sdma.c
++ * @brief Front-end to the DMA handling.  This handles the allocation/freeing
++ * of DMA channels, and provides a unified interface to the machines
++ * DMA facilities. This file contains functions for Smart DMA.
++ *
++ * @ingroup SDMA
++ */
++
++#include <linux/init.h>
++#include <linux/clk.h>
++#include <linux/dma-mapping.h>
++#include <mach/dma.h>
++#include <mach/hardware.h>
++#include <linux/slab.h>
++
++#include <epm.h>
++#include "sdma.h"
++
++#ifdef CONFIG_MXC_SDMA_API
++
++static mxc_dma_channel_t mxc_sdma_channels[MAX_DMA_CHANNELS];
++static mxc_dma_channel_private_t mxc_sdma_private[MAX_DMA_CHANNELS];
++
++/*!
++ * Tasket to handle processing the channel buffers
++ *
++ * @param arg channel id
++ */
++static void mxc_sdma_channeltasklet(unsigned long arg)
++{
++      dma_request_t req;
++      mxc_sdma_channel_params_t *chnl;
++      dma_channel_params *chnl_param;
++      mxc_dma_channel_t *chnl_info;
++      mxc_dma_channel_private_t *data_priv;
++      int ret;
++
++      chnl_info = &mxc_sdma_channels[arg];
++      data_priv = chnl_info->private;
++      chnl = mxc_sdma_get_channel_params(chnl_info->channel);
++      BUG_ON(chnl == NULL);
++      chnl_param = &chnl->chnl_params;
++
++      ret = mxc_dma_get_config(arg, &req, data_priv->buf_tail);
++      if (ret) {
++              DBG(0, "%s: Failed to get config for channel %ld buffer %u: %d\n",
++                      __FUNCTION__, arg, data_priv->buf_tail, ret);
++              return;
++      }
++
++      DBG(0, "%s: dma_request %u: src: %08x dst: %08x done=%d cont=%d wrap=%d\n",
++              __FUNCTION__, data_priv->buf_tail, req.sourceAddr, req.destAddr,
++              req.bd_done, req.bd_cont, req.bd_wrap);
++
++      while (!req.bd_done) {
++              int error = MXC_DMA_DONE;
++              int bd_intr = mxc_dma_get_bd_intr(arg, data_priv->buf_tail);
++
++              if (bd_intr < 0) {
++                      DBG(0, "%s: Failed to get bd_intr for channel %ld buffer %u: %d\n",
++                              __FUNCTION__, arg, data_priv->buf_tail, ret);
++                      return;
++              }
++
++              DBG(0, "%s: desc %u of %u\n", __FUNCTION__,
++                      data_priv->buf_tail, chnl_param->bd_number);
++
++              if (!data_priv->circular || req.bd_error) {
++                      DBG(0, "%s: Deactivating channel\n", __FUNCTION__);
++                      chnl_info->active = 0;
++              }
++              if (req.bd_error) {
++                      error = MXC_DMA_TRANSFER_ERROR;
++              }
++
++              DBG(0, "%s: bd_intr=%d\n", __FUNCTION__, bd_intr);
++              if (bd_intr) {
++                      chnl_info->cb_fn(chnl_info->cb_args, error,
++                                       req.count);
++              }
++
++              if (data_priv->buf_tail == chnl_info->curr_buf) {
++                      break;
++              }
++
++              ret = mxc_dma_set_config(arg, &req, data_priv->buf_tail);
++              if (ret) {
++                      DBG(0, "%s: Failed to set config for channel %ld buffer %u: %d\n",
++                              __FUNCTION__, arg, data_priv->buf_tail, ret);
++                      return;
++              }
++
++              data_priv->buf_tail++;
++              if (data_priv->buf_tail >= chnl_param->bd_number || req.bd_wrap)
++                      data_priv->buf_tail = 0;
++              memset(&req, 0, sizeof(req));
++              ret = mxc_dma_get_config(arg, &req, data_priv->buf_tail);
++              if (ret) {
++                      DBG(0, "%s: Failed to get config for channel %ld buffer %u: %d\n",
++                              __FUNCTION__, arg, data_priv->buf_tail, ret);
++                      return;
++              }
++              DBG(0, "%s: dma_request %u: src: %08x dst: %08x done=%d cont=%d wrap=%d\n",
++                      __FUNCTION__, data_priv->buf_tail, req.sourceAddr, req.destAddr,
++                      req.bd_done, req.bd_cont, req.bd_wrap);
++      }
++}
++
++/*!
++ * 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.
++ */
++int mxc_dma_request_ext(mxc_dma_device_t channel_id, char *dev_name,
++                      struct dma_channel_info *info)
++{
++      mxc_sdma_channel_params_t *chnl;
++      mxc_dma_channel_private_t *data_priv;
++      int ret, i, channel_num;
++      mxc_sdma_channel_ext_params_t *p;
++
++      chnl = mxc_sdma_get_channel_params(channel_id);
++      if (chnl == NULL) {
++              return -EINVAL;
++      }
++
++      if (info) {
++              if (!chnl->chnl_params.ext)
++                      return -EINVAL;
++              p = (mxc_sdma_channel_ext_params_t *)chnl;
++              memcpy(&p->chnl_ext_params.info, info, sizeof(info));
++      }
++
++      /* Enable the SDMA clock */
++      clk_enable(mxc_sdma_clk);
++
++      channel_num = chnl->channel_num;
++      if (chnl->channel_num == MXC_DMA_DYNAMIC_CHANNEL) {
++              ret = -EBUSY;
++              /* Get the first free channel */
++              for (i = MAX_DMA_CHANNELS - 1; i > 0; i--) {
++                      /* See if channel is available */
++                      if (!mxc_sdma_channels[i].dynamic ||
++                              mxc_sdma_channels[i].lock) {
++                              continue;
++                      }
++                      channel_num = i;
++                      /* Check to see if we can get this channel */
++                      ret = mxc_request_dma(&channel_num, dev_name);
++                      if (ret == 0) {
++                              break;
++                      } else {
++                              continue;
++                      }
++              }
++              if (ret != 0) {
++                      /* No free channel */
++                      goto err_ret;
++              }
++      } else {
++              if (mxc_sdma_channels[chnl->channel_num].lock) {
++                      ret = -EBUSY;
++                      goto err_ret;
++              }
++              ret = mxc_request_dma(&channel_num, dev_name);
++              if (ret != 0) {
++                      goto err_ret;
++              }
++      }
++
++      ret = mxc_dma_setup_channel(channel_num, &chnl->chnl_params);
++      if (ret != 0) {
++              DBG(0, "%s: Failed to setup DMA channel %d: %d\n", __FUNCTION__,
++                      channel_num, ret);
++              goto err_free;
++      }
++      if (chnl->chnl_priority != MXC_SDMA_DEFAULT_PRIORITY) {
++              ret = mxc_dma_set_channel_priority(channel_num,
++                                              chnl->chnl_priority);
++              if (ret != 0) {
++                      pr_info("Failed to set channel prority, continuing with the existing priority\n");
++              }
++      }
++      mxc_sdma_channels[channel_num].lock = 1;
++      if ((chnl->chnl_params.transfer_type == per_2_emi) ||
++              (chnl->chnl_params.transfer_type == dsp_2_emi)) {
++              mxc_sdma_channels[channel_num].mode =
++                      MXC_DMA_MODE_READ;
++      } else {
++              mxc_sdma_channels[channel_num].mode =
++                      MXC_DMA_MODE_WRITE;
++      }
++      mxc_sdma_channels[channel_num].channel = channel_id;
++      data_priv = mxc_sdma_channels[channel_num].private;
++      tasklet_init(&data_priv->chnl_tasklet,
++              mxc_sdma_channeltasklet, channel_num);
++      if ((channel_id == MXC_DMA_ATA_RX) ||
++              (channel_id == MXC_DMA_ATA_TX)) {
++              data_priv->intr_after_every_bd = 0;
++      } else {
++              data_priv->intr_after_every_bd = 1;
++      }
++      return channel_num;
++
++err_free:
++      mxc_free_dma(channel_num);
++err_ret:
++      clk_disable(mxc_sdma_clk);
++      return ret;
++}
++
++/*!
++ * 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
++ */
++int mxc_dma_free(int channel_num)
++{
++      mxc_dma_channel_private_t *data_priv;
++
++      if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
++              return -EINVAL;
++      }
++
++      if (!mxc_sdma_channels[channel_num].lock) {
++              return -EINVAL;
++      }
++
++      mxc_free_dma(channel_num);
++
++      /* Disable the SDMA clock */
++      clk_disable(mxc_sdma_clk);
++
++      mxc_sdma_channels[channel_num].lock = 0;
++      mxc_sdma_channels[channel_num].active = 0;
++      mxc_sdma_channels[channel_num].curr_buf = 0;
++      data_priv = mxc_sdma_channels[channel_num].private;
++      data_priv->buf_tail = 0;
++      tasklet_kill(&data_priv->chnl_tasklet);
++
++      return 0;
++}
++
++/*!
++ * Callback function called from the SDMA Interrupt routine
++ *
++ * @param arg driver specific argument that was registered
++ */
++static void mxc_dma_chnl_callback(void *arg)
++{
++      int channel;
++      mxc_dma_channel_private_t *data_priv;
++
++      channel = (int)arg;
++      DBG(0, "%s: channel %d\n", __FUNCTION__, channel);
++      data_priv = mxc_sdma_channels[channel].private;
++      /* Process the buffers in a tasklet */
++      tasklet_schedule(&data_priv->chnl_tasklet);
++}
++
++/*!
++ * 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
++ */
++int mxc_dma_config(int channel_num, mxc_dma_requestbuf_t *dma_buf,
++                 int num_buf, mxc_dma_mode_t mode)
++{
++      int ret, i, prev_buf;
++      mxc_dma_channel_t *chnl_info;
++      mxc_dma_channel_private_t *data_priv;
++      mxc_sdma_channel_params_t *chnl;
++      dma_channel_params chnl_param;
++      dma_request_t req;
++
++      if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0))
++              return -EINVAL;
++
++      if (num_buf <= 0)
++              return -EINVAL;
++
++      chnl_info = &mxc_sdma_channels[channel_num];
++      data_priv = chnl_info->private;
++      if (chnl_info->lock != 1)
++              return -ENODEV;
++
++      /* Check to see if all buffers are taken */
++      if (chnl_info->active)
++              return -EBUSY;
++
++      chnl = mxc_sdma_get_channel_params(chnl_info->channel);
++      chnl_param = chnl->chnl_params;
++
++      /* Re-setup the SDMA channel if the transfer direction or
++       * the number of assigned BDs is changed
++       */
++      if (chnl_param.peripheral_type != MEMORY &&
++              mode != chnl_info->mode) {
++
++              if (chnl_param.bd_number != num_buf)
++                      DBG(0, "%s: Changing number of BDs for channel %u from %u to %u\n", __FUNCTION__,
++                              channel_num, chnl_param.bd_number, num_buf);
++
++              chnl_param.bd_number = num_buf;
++              if (chnl_param.peripheral_type == DSP) {
++                      if (mode == MXC_DMA_MODE_READ)
++                              chnl_param.transfer_type = dsp_2_emi;
++                      else
++                              chnl_param.transfer_type = emi_2_dsp;
++              } else if (chnl_param.peripheral_type == FIFO_MEMORY) {
++                      if (mode == MXC_DMA_MODE_READ)
++                              chnl_param.per_address =
++                                      MXC_FIFO_MEM_SRC_FIXED;
++                      else
++                              chnl_param.per_address =
++                                      MXC_FIFO_MEM_DEST_FIXED;
++              } else {
++                      if (mode == MXC_DMA_MODE_READ)
++                              chnl_param.transfer_type = per_2_emi;
++                      else
++                              chnl_param.transfer_type = emi_2_per;
++              }
++              chnl_param.callback = mxc_dma_chnl_callback;
++              chnl_param.arg = (void *)channel_num;
++              ret = mxc_dma_setup_channel(channel_num, &chnl_param);
++              if (ret != 0)
++                      return ret;
++
++              if (chnl->chnl_priority != MXC_SDMA_DEFAULT_PRIORITY) {
++                      ret = mxc_dma_set_channel_priority(channel_num,
++                                                      chnl->chnl_priority);
++                      if (ret != 0) {
++                              pr_info("Failed to set channel prority, continuing with the existing priority\n");
++                      }
++              }
++              chnl_info->mode = mode;
++      }
++
++      for (i = 0; i < num_buf; i++, dma_buf++) {
++              memset(&req, 0, sizeof(req));
++              /* Check to see if all buffers are taken */
++              if (chnl_info->active) {
++                      DBG(0, "%s: bd %u is already active\n",
++                              __FUNCTION__, i);
++                      break;
++              }
++              req.destAddr = dma_buf->dst_addr;
++              req.sourceAddr = dma_buf->src_addr;
++              if (chnl_param.peripheral_type == ASRC)
++                      req.count = dma_buf->num_of_bytes / 4;
++              else
++                      req.count = dma_buf->num_of_bytes;
++              req.bd_cont = 1;
++              if (data_priv->circular && i == num_buf - 1) {
++                      DBG(0, "%s: Setting bd_wrap for desc[%d/%d]\n",
++                              __FUNCTION__, i, num_buf);
++                      req.bd_wrap = 1;
++              }
++              ret = mxc_dma_set_config(channel_num, &req,
++                                      chnl_info->curr_buf);
++              if (ret != 0) {
++                      DBG(0, "%s: Failed to configure DMA: %d\n",
++                              __FUNCTION__, ret);
++                      return ret;
++              }
++              if (data_priv->intr_after_every_bd ||
++                      (i == num_buf - 1)) {
++                      mxc_dma_set_bd_intr(channel_num,
++                                      chnl_info->curr_buf, 1);
++              } else {
++                      mxc_dma_set_bd_intr(channel_num,
++                                      chnl_info->curr_buf, 0);
++              }
++
++              prev_buf = chnl_info->curr_buf;
++              chnl_info->curr_buf++;
++              if (chnl_info->curr_buf >= chnl_param.bd_number) {
++                      chnl_info->curr_buf = 0;
++              }
++              if (chnl_info->curr_buf == data_priv->buf_tail) {
++                      if (!(data_priv->intr_after_every_bd) &&
++                              (i != num_buf - 1)) {
++                              /*
++                               * Set the BD_INTR flag on the last BD that
++                               * was queued
++                               */
++                              mxc_dma_set_bd_intr(channel_num, prev_buf, 1);
++                      }
++                      chnl_info->active = 1;
++              }
++      }
++
++      if (i == 0) {
++              return -EBUSY;
++      }
++      return 0;
++}
++
++/*!
++ * 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
++ */
++int mxc_dma_sg_config(int channel_num, struct scatterlist *sg,
++                    int num_buf, int num_of_bytes, mxc_dma_mode_t mode)
++{
++      int ret, i;
++      mxc_dma_requestbuf_t *dma_buf;
++      gfp_t gfp_flags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL;
++      mxc_dma_channel_t *chnl_info;
++      mxc_dma_channel_private_t *data_priv;
++
++      DBG(0, "%s: chan %d %u buffers with %u bytes\n", __FUNCTION__,
++              channel_num, num_buf, num_of_bytes);
++
++      if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
++              return -EINVAL;
++      }
++
++      if (!mxc_sdma_channels[channel_num].lock) {
++              return -EINVAL;
++      }
++
++      dma_buf = kmalloc(num_buf * sizeof(mxc_dma_requestbuf_t),
++                      gfp_flags);
++      if (dma_buf == NULL) {
++              return -ENOMEM;
++      }
++
++      chnl_info = &mxc_sdma_channels[channel_num];
++      data_priv = chnl_info->private;
++      data_priv->intr_after_every_bd = 1;
++      data_priv->circular = 1;
++
++      for (i = 0; i < num_buf; i++) {
++              if (mode == MXC_DMA_MODE_READ) {
++                      dma_buf[i].dst_addr = sg->dma_address;
++                      dma_buf[i].src_addr = DMA_ADDR_INVALID;
++              } else {
++                      dma_buf[i].dst_addr = DMA_ADDR_INVALID;
++                      dma_buf[i].src_addr = sg->dma_address;
++              }
++
++              if ((num_of_bytes > sg->length) || (num_of_bytes == 0)) {
++                      dma_buf[i].num_of_bytes = sg->length;
++              } else {
++                      dma_buf[i].num_of_bytes = num_of_bytes;
++              }
++              sg = sg_next(sg);
++              if (num_of_bytes != 0)
++                      num_of_bytes -= dma_buf[i].num_of_bytes;
++              DBG(0, "%s: desc[%d/%d] src: %08x dst: %08x len: %08x\n",
++                      __FUNCTION__, i, num_buf, dma_buf[i].src_addr, dma_buf[i].dst_addr,
++                      dma_buf[i].num_of_bytes);
++      }
++
++      ret = mxc_dma_config(channel_num, dma_buf, num_buf, mode);
++      kfree(dma_buf);
++      return ret;
++}
++
++/*!
++ * 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
++ */
++int mxc_dma_callback_set(int channel_num,
++                       mxc_dma_callback_t callback, void *arg)
++{
++      if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
++              return -EINVAL;
++      }
++
++      if (!mxc_sdma_channels[channel_num].lock) {
++              return -EINVAL;
++      }
++
++      mxc_sdma_channels[channel_num].cb_fn = callback;
++      mxc_sdma_channels[channel_num].cb_args = arg;
++
++      mxc_dma_set_callback(channel_num, mxc_dma_chnl_callback,
++                           (void *)channel_num);
++
++      return 0;
++}
++
++/*!
++ * 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
++ */
++int mxc_dma_disable(int channel_num)
++{
++      if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
++              return -EINVAL;
++      }
++
++      if (!mxc_sdma_channels[channel_num].lock) {
++              return -EINVAL;
++      }
++
++      mxc_dma_stop(channel_num);
++      return 0;
++}
++
++/*!
++ * 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
++ */
++int mxc_dma_enable(int channel_num)
++{
++      if ((channel_num >= MAX_DMA_CHANNELS) || (channel_num < 0)) {
++              return -EINVAL;
++      }
++
++      if (!mxc_sdma_channels[channel_num].lock) {
++              return -EINVAL;
++      }
++
++      mxc_dma_start(channel_num);
++      return 0;
++}
++
++/*!
++ * Initializes dma structure with dma_operations
++ *
++ * @param   dma           dma structure
++ * @return  returns 0 on success
++ */
++static int __init mxc_dma_init(void)
++{
++      int i;
++
++      for (i = 0; i < MAX_DMA_CHANNELS; i++) {
++              mxc_sdma_channels[i].active = 0;
++              mxc_sdma_channels[i].lock = 0;
++              mxc_sdma_channels[i].curr_buf = 0;
++              mxc_sdma_channels[i].dynamic = 1;
++              mxc_sdma_private[i].buf_tail = 0;
++              mxc_sdma_channels[i].private = &mxc_sdma_private[i];
++      }
++      /*
++       * Make statically allocated channels unavailable for dynamic channel
++       * requests
++       */
++      mxc_get_static_channels(mxc_sdma_channels);
++
++      return 0;
++}
++
++arch_initcall(mxc_dma_init);
++
++#else
++int mxc_request_dma(int *channel, const char *devicename)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_setup_channel(int channel, dma_channel_params * p)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_set_channel_priority(unsigned int channel, unsigned int priority)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_set_config(int channel, dma_request_t * p, int bd_index)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_get_config(int channel, dma_request_t * p, int bd_index)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_start(int channel)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_stop(int channel)
++{
++      return -ENODEV;
++}
++
++void mxc_free_dma(int channel)
++{
++}
++
++void mxc_dma_set_callback(int channel, dma_callback_t callback, void *arg)
++{
++}
++
++void *sdma_malloc(size_t size)
++{
++      return NULL;
++}
++
++void sdma_free(void *buf)
++{
++}
++
++void *sdma_phys_to_virt(dma_addr_t buf)
++{
++      return NULL;
++}
++
++dma_addr_t sdma_virt_to_phys(void *buf)
++{
++      return DMA_ADDR_INVALID;
++}
++
++int mxc_dma_request(mxc_dma_device_t channel_id, char *dev_name)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_free(int channel_num)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_config(int channel_num, mxc_dma_requestbuf_t * dma_buf,
++                 int num_buf, mxc_dma_mode_t mode)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_sg_config(int channel_num, struct scatterlist *sg,
++                    int num_buf, int num_of_bytes, mxc_dma_mode_t mode)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_callback_set(int channel_num, mxc_dma_callback_t callback,
++                       void *arg)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_disable(int channel_num)
++{
++      return -ENODEV;
++}
++
++int mxc_dma_enable(int channel_num)
++{
++      return -ENODEV;
++}
++
++EXPORT_SYMBOL(mxc_request_dma);
++EXPORT_SYMBOL(mxc_dma_setup_channel);
++EXPORT_SYMBOL(mxc_dma_set_channel_priority);
++EXPORT_SYMBOL(mxc_dma_set_config);
++EXPORT_SYMBOL(mxc_dma_get_config);
++EXPORT_SYMBOL(mxc_dma_start);
++EXPORT_SYMBOL(mxc_dma_stop);
++EXPORT_SYMBOL(mxc_free_dma);
++EXPORT_SYMBOL(mxc_dma_set_callback);
++EXPORT_SYMBOL(sdma_malloc);
++EXPORT_SYMBOL(sdma_free);
++EXPORT_SYMBOL(sdma_phys_to_virt);
++EXPORT_SYMBOL(sdma_virt_to_phys);
++
++#endif
++
++EXPORT_SYMBOL(mxc_dma_request_ext);
++EXPORT_SYMBOL(mxc_dma_free);
++EXPORT_SYMBOL(mxc_dma_config);
++EXPORT_SYMBOL(mxc_dma_sg_config);
++EXPORT_SYMBOL(mxc_dma_callback_set);
++EXPORT_SYMBOL(mxc_dma_disable);
++EXPORT_SYMBOL(mxc_dma_enable);
++
++MODULE_AUTHOR("Freescale Semiconductor, Inc.");
++MODULE_DESCRIPTION("MXC Linux SDMA API");
++MODULE_LICENSE("GPL");
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/epm.h linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/epm.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/epm.h     1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/epm.h     2010-12-03 09:51:55.384181534 +0100
+@@ -0,0 +1,254 @@
++/*
++ * Copyright 2007-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
++ */
++
++#ifndef __ASM_ARCH_MXC_SDMA_REGS_H__
++#define __ASM_ARCH_MXC_SDMA_REGS_H__
++
++#ifdef DEBUG
++#ifdef CONFIG_MACH_TX25
++extern int tx25_debug;
++#define dbg_lvl(n)    ((n) < tx25_debug)
++#elif defined(CONFIG_MACH_TX51)
++extern int tx51_debug;
++#define dbg_lvl(n)    ((n) < tx51_debug)
++#else
++#error No debug support for this machine
++#endif
++#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
++
++#ifdef __KERNEL__
++#include <linux/kernel.h>
++#include <linux/bug.h>
++#include <linux/io.h>
++#include <asm/memory.h>
++#endif
++
++#include <linux/compiler.h>
++#include <mach/hardware.h>
++
++/* SDMA Reg definition */
++extern void __iomem *sdma_base_addr;
++#define SDMA_BASE_IO_ADDR sdma_base_addr
++
++#ifdef DEBUG
++#define __sdma_pa(a)          ((a) - SDMA_BASE_IO_ADDR + SDMA_BASE_ADDR)
++
++static inline u32 iapi_raw_readl(void __iomem *addr,
++                              const char *name, const char *fn)
++{
++      u32 val;
++
++      DBG(1, "%s: Reading %s[%08lx]\n", fn,
++              name, __sdma_pa(addr));
++      val = __raw_readl(addr);
++      DBG(0, "%s: Read %08x from %s[%08lx]\n", fn,
++              val, name, __sdma_pa(addr));
++      return val;
++}
++
++static inline void iapi_raw_writel(u32 val, void __iomem *addr,
++                              const char *name, const char *fn)
++{
++      DBG(0, "%s: Writing %08x to %s[%08lx]\n", fn,
++              val, name, __sdma_pa(addr));
++      __raw_writel(val, addr);
++
++}
++
++#undef __raw_writel
++#undef __raw_readl
++
++#define __raw_readl(a)                iapi_raw_readl(a, #a, __func__)
++#define __raw_writel(v, a)    iapi_raw_writel(v, a, #a, __func__)
++#endif
++
++#define __REG32(base, offs)   ((base) + (offs))
++#define __REG_ARRAY(base, offs, num, index) ({        \
++      BUG_ON((unsigned int)(index) >= (num)); \
++      __REG32(base, (offs) + ((index) << 2)); \
++})
++
++#define SDMA_H_C0PTR          __REG32(SDMA_BASE_IO_ADDR, 0x000)
++#define SDMA_H_INTR           __REG32(SDMA_BASE_IO_ADDR, 0x004)
++#define SDMA_H_STATSTOP               __REG32(SDMA_BASE_IO_ADDR, 0x008)
++#define SDMA_H_START          __REG32(SDMA_BASE_IO_ADDR, 0x00C)
++#define SDMA_H_EVTOVR         __REG32(SDMA_BASE_IO_ADDR, 0x010)
++#define SDMA_H_DSPOVR         __REG32(SDMA_BASE_IO_ADDR, 0x014)
++#define SDMA_H_HOSTOVR                __REG32(SDMA_BASE_IO_ADDR, 0x018)
++#define SDMA_H_EVTPEND                __REG32(SDMA_BASE_IO_ADDR, 0x01C)
++#define SDMA_H_DSPENBL                __REG32(SDMA_BASE_IO_ADDR, 0x020)
++#define SDMA_H_RESET          __REG32(SDMA_BASE_IO_ADDR, 0x024)
++#define SDMA_H_EVTERR         __REG32(SDMA_BASE_IO_ADDR, 0x028)
++#define SDMA_H_INTRMSK                __REG32(SDMA_BASE_IO_ADDR, 0x02C)
++#define SDMA_H_PSW            __REG32(SDMA_BASE_IO_ADDR, 0x030)
++#define SDMA_H_EVTERRDBG      __REG32(SDMA_BASE_IO_ADDR, 0x034)
++#define SDMA_H_CONFIG         __REG32(SDMA_BASE_IO_ADDR, 0x038)
++#define SDMA_SDMA_LOCK                __REG32(SDMA_BASE_IO_ADDR, 0x03C)
++#define SDMA_ONCE_ENB         __REG32(SDMA_BASE_IO_ADDR, 0x040)
++#define SDMA_ONCE_DATA                __REG32(SDMA_BASE_IO_ADDR, 0x044)
++#define SDMA_ONCE_INSTR               __REG32(SDMA_BASE_IO_ADDR, 0x048)
++#define SDMA_ONCE_STAT                __REG32(SDMA_BASE_IO_ADDR, 0x04C)
++#define SDMA_ONCE_CMD         __REG32(SDMA_BASE_IO_ADDR, 0x050)
++#define SDMA_EVT_MIRROR               __REG32(SDMA_BASE_IO_ADDR, 0x054)
++#define SDMA_ILLINSTADDR      __REG32(SDMA_BASE_IO_ADDR, 0x058)
++#define SDMA_CHN0ADDR         __REG32(SDMA_BASE_IO_ADDR, 0x05C)
++#define SDMA_ONCE_RTB         __REG32(SDMA_BASE_IO_ADDR, 0x060)
++#define SDMA_XTRIG_CONF1      __REG32(SDMA_BASE_IO_ADDR, 0x070)
++#define SDMA_XTRIG_CONF2      __REG32(SDMA_BASE_IO_ADDR, 0x074)
++
++#ifdef SDMA_V2
++#define SDMA_CHNENBL(i)               __REG_ARRAY(SDMA_BASE_IO_ADDR, 0x200, 48, i)
++#define SDMA_CHNENBL_0                __REG32(SDMA_BASE_IO_ADDR, 0x200)
++#define SDMA_CHNENBL_1                __REG32(SDMA_BASE_IO_ADDR, 0x204)
++#define SDMA_CHNENBL_2                __REG32(SDMA_BASE_IO_ADDR, 0x208)
++#define SDMA_CHNENBL_3                __REG32(SDMA_BASE_IO_ADDR, 0x20C)
++#define SDMA_CHNENBL_4                __REG32(SDMA_BASE_IO_ADDR, 0x210)
++#define SDMA_CHNENBL_5                __REG32(SDMA_BASE_IO_ADDR, 0x214)
++#define SDMA_CHNENBL_6                __REG32(SDMA_BASE_IO_ADDR, 0x218)
++#define SDMA_CHNENBL_7                __REG32(SDMA_BASE_IO_ADDR, 0x21C)
++#define SDMA_CHNENBL_8                __REG32(SDMA_BASE_IO_ADDR, 0x220)
++#define SDMA_CHNENBL_9                __REG32(SDMA_BASE_IO_ADDR, 0x224)
++#define SDMA_CHNENBL_10               __REG32(SDMA_BASE_IO_ADDR, 0x228)
++#define SDMA_CHNENBL_11               __REG32(SDMA_BASE_IO_ADDR, 0x22C)
++#define SDMA_CHNENBL_12               __REG32(SDMA_BASE_IO_ADDR, 0x230)
++#define SDMA_CHNENBL_13               __REG32(SDMA_BASE_IO_ADDR, 0x234)
++#define SDMA_CHNENBL_14               __REG32(SDMA_BASE_IO_ADDR, 0x238)
++#define SDMA_CHNENBL_15               __REG32(SDMA_BASE_IO_ADDR, 0x23C)
++#define SDMA_CHNENBL_16               __REG32(SDMA_BASE_IO_ADDR, 0x240)
++#define SDMA_CHNENBL_17               __REG32(SDMA_BASE_IO_ADDR, 0x244)
++#define SDMA_CHNENBL_18               __REG32(SDMA_BASE_IO_ADDR, 0x248)
++#define SDMA_CHNENBL_19               __REG32(SDMA_BASE_IO_ADDR, 0x24C)
++#define SDMA_CHNENBL_20               __REG32(SDMA_BASE_IO_ADDR, 0x250)
++#define SDMA_CHNENBL_21               __REG32(SDMA_BASE_IO_ADDR, 0x254)
++#define SDMA_CHNENBL_22               __REG32(SDMA_BASE_IO_ADDR, 0x258)
++#define SDMA_CHNENBL_23               __REG32(SDMA_BASE_IO_ADDR, 0x25C)
++#define SDMA_CHNENBL_24               __REG32(SDMA_BASE_IO_ADDR, 0x260)
++#define SDMA_CHNENBL_25               __REG32(SDMA_BASE_IO_ADDR, 0x264)
++#define SDMA_CHNENBL_26               __REG32(SDMA_BASE_IO_ADDR, 0x268)
++#define SDMA_CHNENBL_27               __REG32(SDMA_BASE_IO_ADDR, 0x26C)
++#define SDMA_CHNENBL_28               __REG32(SDMA_BASE_IO_ADDR, 0x270)
++#define SDMA_CHNENBL_29               __REG32(SDMA_BASE_IO_ADDR, 0x274)
++#define SDMA_CHNENBL_30               __REG32(SDMA_BASE_IO_ADDR, 0x278)
++#define SDMA_CHNENBL_31               __REG32(SDMA_BASE_IO_ADDR, 0x27C)
++#define SDMA_CHNENBL_32               __REG32(SDMA_BASE_IO_ADDR, 0x280)
++#define SDMA_CHNENBL_33               __REG32(SDMA_BASE_IO_ADDR, 0x284)
++#define SDMA_CHNENBL_34               __REG32(SDMA_BASE_IO_ADDR, 0x288)
++#define SDMA_CHNENBL_35               __REG32(SDMA_BASE_IO_ADDR, 0x28C)
++#define SDMA_CHNENBL_36               __REG32(SDMA_BASE_IO_ADDR, 0x290)
++#define SDMA_CHNENBL_37               __REG32(SDMA_BASE_IO_ADDR, 0x294)
++#define SDMA_CHNENBL_38               __REG32(SDMA_BASE_IO_ADDR, 0x298)
++#define SDMA_CHNENBL_39               __REG32(SDMA_BASE_IO_ADDR, 0x29C)
++#define SDMA_CHNENBL_40               __REG32(SDMA_BASE_IO_ADDR, 0x2A0)
++#define SDMA_CHNENBL_41               __REG32(SDMA_BASE_IO_ADDR, 0x2A4)
++#define SDMA_CHNENBL_42               __REG32(SDMA_BASE_IO_ADDR, 0x2A8)
++#define SDMA_CHNENBL_43               __REG32(SDMA_BASE_IO_ADDR, 0x2AC)
++#define SDMA_CHNENBL_44               __REG32(SDMA_BASE_IO_ADDR, 0x2B0)
++#define SDMA_CHNENBL_45               __REG32(SDMA_BASE_IO_ADDR, 0x2B4)
++#define SDMA_CHNENBL_46               __REG32(SDMA_BASE_IO_ADDR, 0x2B8)
++#define SDMA_CHNENBL_47               __REG32(SDMA_BASE_IO_ADDR, 0x2BC)
++
++#define SDMA_ONCE_COUNT               __REG32(SDMA_BASE_IO_ADDR, 0x300)
++#define SDMA_ONCE_ECTL                __REG32(SDMA_BASE_IO_ADDR, 0x304)
++#define SDMA_ONCE_EAA         __REG32(SDMA_BASE_IO_ADDR, 0x308)
++#define SDMA_ONCE_EAB         __REG32(SDMA_BASE_IO_ADDR, 0x30C)
++#define SDMA_ONCE_EAM         __REG32(SDMA_BASE_IO_ADDR, 0x310)
++#define SDMA_ONCE_ED          __REG32(SDMA_BASE_IO_ADDR, 0x314)
++#define SDMA_ONCE_EDM         __REG32(SDMA_BASE_IO_ADDR, 0x318)
++#define SDMA_ONCE_PCMATCH     __REG32(SDMA_BASE_IO_ADDR, 0x31C)
++
++#else
++
++#define SDMA_CHNENBL(i)               __REG_ARRAY(SDMA_BASE_IO_ADDR, 0x80, 32, i)
++#define SDMA_CHNENBL_0                __REG32(SDMA_BASE_IO_ADDR, 0x080)
++#define SDMA_CHNENBL_1                __REG32(SDMA_BASE_IO_ADDR, 0x084)
++#define SDMA_CHNENBL_2                __REG32(SDMA_BASE_IO_ADDR, 0x088)
++#define SDMA_CHNENBL_3                __REG32(SDMA_BASE_IO_ADDR, 0x08C)
++#define SDMA_CHNENBL_4                __REG32(SDMA_BASE_IO_ADDR, 0x090)
++#define SDMA_CHNENBL_5                __REG32(SDMA_BASE_IO_ADDR, 0x094)
++#define SDMA_CHNENBL_6                __REG32(SDMA_BASE_IO_ADDR, 0x098)
++#define SDMA_CHNENBL_7                __REG32(SDMA_BASE_IO_ADDR, 0x09C)
++#define SDMA_CHNENBL_8                __REG32(SDMA_BASE_IO_ADDR, 0x0A0)
++#define SDMA_CHNENBL_9                __REG32(SDMA_BASE_IO_ADDR, 0x0A4)
++#define SDMA_CHNENBL_10               __REG32(SDMA_BASE_IO_ADDR, 0x0A8)
++#define SDMA_CHNENBL_11               __REG32(SDMA_BASE_IO_ADDR, 0x0AC)
++#define SDMA_CHNENBL_12               __REG32(SDMA_BASE_IO_ADDR, 0x0B0)
++#define SDMA_CHNENBL_13               __REG32(SDMA_BASE_IO_ADDR, 0x0B4)
++#define SDMA_CHNENBL_14               __REG32(SDMA_BASE_IO_ADDR, 0x0B8)
++#define SDMA_CHNENBL_15               __REG32(SDMA_BASE_IO_ADDR, 0x0BC)
++#define SDMA_CHNENBL_16               __REG32(SDMA_BASE_IO_ADDR, 0x0C0)
++#define SDMA_CHNENBL_17               __REG32(SDMA_BASE_IO_ADDR, 0x0C4)
++#define SDMA_CHNENBL_18               __REG32(SDMA_BASE_IO_ADDR, 0x0C8)
++#define SDMA_CHNENBL_19               __REG32(SDMA_BASE_IO_ADDR, 0x0CC)
++#define SDMA_CHNENBL_20               __REG32(SDMA_BASE_IO_ADDR, 0x0D0)
++#define SDMA_CHNENBL_21               __REG32(SDMA_BASE_IO_ADDR, 0x0D4)
++#define SDMA_CHNENBL_22               __REG32(SDMA_BASE_IO_ADDR, 0x0D8)
++#define SDMA_CHNENBL_23               __REG32(SDMA_BASE_IO_ADDR, 0x0DC)
++#define SDMA_CHNENBL_24               __REG32(SDMA_BASE_IO_ADDR, 0x0E0)
++#define SDMA_CHNENBL_25               __REG32(SDMA_BASE_IO_ADDR, 0x0E4)
++#define SDMA_CHNENBL_26               __REG32(SDMA_BASE_IO_ADDR, 0x0E8)
++#define SDMA_CHNENBL_27               __REG32(SDMA_BASE_IO_ADDR, 0x0EC)
++#define SDMA_CHNENBL_28               __REG32(SDMA_BASE_IO_ADDR, 0x0F0)
++#define SDMA_CHNENBL_29               __REG32(SDMA_BASE_IO_ADDR, 0x0F4)
++#define SDMA_CHNENBL_30               __REG32(SDMA_BASE_IO_ADDR, 0x0F8)
++#define SDMA_CHNENBL_31               __REG32(SDMA_BASE_IO_ADDR, 0x0FC)
++
++#define SDMA_ONCE_COUNT               __REG32(SDMA_BASE_IO_ADDR, 0x200)
++#define SDMA_ONCE_ECTL                __REG32(SDMA_BASE_IO_ADDR, 0x204)
++#define SDMA_ONCE_EAA         __REG32(SDMA_BASE_IO_ADDR, 0x208)
++#define SDMA_ONCE_EAB         __REG32(SDMA_BASE_IO_ADDR, 0x20C)
++#define SDMA_ONCE_EAM         __REG32(SDMA_BASE_IO_ADDR, 0x210)
++#define SDMA_ONCE_ED          __REG32(SDMA_BASE_IO_ADDR, 0x214)
++#define SDMA_ONCE_EDM         __REG32(SDMA_BASE_IO_ADDR, 0x218)
++#define SDMA_ONCE_PCMATCH     __REG32(SDMA_BASE_IO_ADDR, 0x21C)
++
++#endif /* SDMA_V2 */
++
++#define SDMA_CHNPRI(i)                __REG_ARRAY(SDMA_BASE_IO_ADDR, 0x100, 32, i)
++#define SDMA_CHNPRI_0         __REG32(SDMA_BASE_IO_ADDR, 0x100)
++#define SDMA_CHNPRI_1         __REG32(SDMA_BASE_IO_ADDR, 0x104)
++#define SDMA_CHNPRI_2         __REG32(SDMA_BASE_IO_ADDR, 0x108)
++#define SDMA_CHNPRI_3         __REG32(SDMA_BASE_IO_ADDR, 0x10C)
++#define SDMA_CHNPRI_4         __REG32(SDMA_BASE_IO_ADDR, 0x110)
++#define SDMA_CHNPRI_5         __REG32(SDMA_BASE_IO_ADDR, 0x114)
++#define SDMA_CHNPRI_6         __REG32(SDMA_BASE_IO_ADDR, 0x118)
++#define SDMA_CHNPRI_7         __REG32(SDMA_BASE_IO_ADDR, 0x11C)
++#define SDMA_CHNPRI_8         __REG32(SDMA_BASE_IO_ADDR, 0x120)
++#define SDMA_CHNPRI_9         __REG32(SDMA_BASE_IO_ADDR, 0x124)
++#define SDMA_CHNPRI_10                __REG32(SDMA_BASE_IO_ADDR, 0x128)
++#define SDMA_CHNPRI_11                __REG32(SDMA_BASE_IO_ADDR, 0x12C)
++#define SDMA_CHNPRI_12                __REG32(SDMA_BASE_IO_ADDR, 0x130)
++#define SDMA_CHNPRI_13                __REG32(SDMA_BASE_IO_ADDR, 0x134)
++#define SDMA_CHNPRI_14                __REG32(SDMA_BASE_IO_ADDR, 0x138)
++#define SDMA_CHNPRI_15                __REG32(SDMA_BASE_IO_ADDR, 0x13C)
++#define SDMA_CHNPRI_16                __REG32(SDMA_BASE_IO_ADDR, 0x140)
++#define SDMA_CHNPRI_17                __REG32(SDMA_BASE_IO_ADDR, 0x144)
++#define SDMA_CHNPRI_18                __REG32(SDMA_BASE_IO_ADDR, 0x148)
++#define SDMA_CHNPRI_19                __REG32(SDMA_BASE_IO_ADDR, 0x14C)
++#define SDMA_CHNPRI_20                __REG32(SDMA_BASE_IO_ADDR, 0x150)
++#define SDMA_CHNPRI_21                __REG32(SDMA_BASE_IO_ADDR, 0x154)
++#define SDMA_CHNPRI_22                __REG32(SDMA_BASE_IO_ADDR, 0x158)
++#define SDMA_CHNPRI_23                __REG32(SDMA_BASE_IO_ADDR, 0x15C)
++#define SDMA_CHNPRI_24                __REG32(SDMA_BASE_IO_ADDR, 0x160)
++#define SDMA_CHNPRI_25                __REG32(SDMA_BASE_IO_ADDR, 0x164)
++#define SDMA_CHNPRI_26                __REG32(SDMA_BASE_IO_ADDR, 0x168)
++#define SDMA_CHNPRI_27                __REG32(SDMA_BASE_IO_ADDR, 0x16C)
++#define SDMA_CHNPRI_28                __REG32(SDMA_BASE_IO_ADDR, 0x170)
++#define SDMA_CHNPRI_29                __REG32(SDMA_BASE_IO_ADDR, 0x174)
++#define SDMA_CHNPRI_30                __REG32(SDMA_BASE_IO_ADDR, 0x178)
++#define SDMA_CHNPRI_31                __REG32(SDMA_BASE_IO_ADDR, 0x17C)
++
++#endif /* _mcuEpm_h */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiDefaults.h linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiDefaults.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiDefaults.h    1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiDefaults.h    2010-12-03 09:51:55.388349760 +0100
+@@ -0,0 +1,131 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiDefaults.h
++ *
++ * $Id iapiDefaults.h $
++ *
++ * Description:
++ *  This library is written in C to guarantee functionality and integrity in
++ * the usage of SDMA virtual DMA channels. This API (Application Programming
++ * Interface)  allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
++ * fashion.
++ *
++ *
++ *
++ *
++ * $Log iapiDefaults.h $
++ *
++ *****************************************************************************/
++
++
++#ifndef _iapi_defaults_h
++#define _iapi_defaults_h
++
++/******************************************************************************
++ * Include File Section
++ *****************************************************************************/
++#include "sdmaStruct.h"
++
++/* ****************************************************************************
++ * Macro-command Section
++ * ***************************************************************************/
++
++/**
++ * Error codes
++ * lower 5 bits free to include channel number when available
++ * and bit number 6 must be set when channel number is available
++ *
++ * Note :
++ * 1) Abbreviations / naming convention :
++ *    - BD  : Buffer Descriptor
++ *    - CC  : Channel Context
++ *    - CCB : Channel Control Block
++ *    - CD  : Channel Descriptor
++ *    - B   : Buffer
++ *    - CH  : Channel
++ *
++ */
++#define IAPI_SUCCESS                  0
++#define IAPI_FAILURE                  (-1)
++#define IAPI_ERR_CH_AVAILABLE         0x00020
++#define IAPI_ERR_NO_ERROR             0x00000
++#define IAPI_ERR_NO_CCB_DEFINED               0x01000
++#define IAPI_ERR_BD_UNINITIALIZED     0x02000
++#define IAPI_ERR_BD_ALLOCATED         0x03000
++#define IAPI_ERR_BD_ALLOCATION                0x04000
++#define IAPI_ERR_CCB_ALLOC_FAILED     0x05000
++#define IAPI_ERR_CCB_UNINITIALIZED    0x06000
++#define IAPI_ERR_CC_ALREADY_DEFINED   0x07000
++#define IAPI_ERR_CC_ALLOC_FAILED      0x08000
++#define IAPI_ERR_CD_ALREADY_DEFINED   0x09000
++#define IAPI_ERR_CD_ALLOC_FAILED      0x0A000
++#define IAPI_ERR_CD_CHANGE_CH_NUMBER  0x0B000
++#define IAPI_ERR_CD_CHANGE_CCB_PTR    0x0C000
++#define IAPI_ERR_CD_CHANGE_UNKNOWN    0x0D000
++#define IAPI_ERR_CD_CHANGE            0x0E000
++#define IAPI_ERR_CD_UNINITIALIZED     0x0F000
++#define IAPI_ERR_CLOSE                        0x10000
++#define IAPI_ERR_B_ALLOC_FAILED               0x11000
++#define IAPI_ERR_CONFIG_OVERRIDE      0x12000
++#define IAPI_ERR_CH_IN_USE            0x13000
++#define IAPI_ERR_CALLBACKSYNCH_UNKNOWN        0x14000
++#define IAPI_ERR_INVALID_PARAMETER    0x15000
++#define IAPI_ERR_TRUST                        0x16000
++#define IAPI_ERR_CHANNEL_UNINITIALIZED        0x17000
++#define IAPI_ERR_RROR_BIT_READ                0x18000
++#define IAPI_ERR_RROR_BIT_WRITE               0x19000
++#define IAPI_ERR_NOT_ALLOWED          0x1A000
++#define IAPI_ERR_NO_OS_FN             0x1B000
++
++
++/*
++ * Global Variable Section
++ */
++
++/*
++ * Table to hold pointers to the callback functions registered by the users of
++ *I.API
++ */
++extern void (*callbackIsrTable[CH_NUM])(channelDescriptor *cd_p, void *arg);
++
++/*
++ * Table to hold user registered data pointers, to be privided in the callback
++ *function
++ */
++extern void *userArgTable[CH_NUM];
++
++/* channelDescriptor data structure filled with default data*/
++extern channelDescriptor iapi_ChannelDefaults;
++
++/* Global variable to hold the last error encountered in I.API operations*/
++extern int iapi_errno;
++
++/* Used in synchronization, to mark started channels*/
++extern volatile unsigned long iapi_SDMAIntr;
++
++/* Hold a pointer to the start of the CCB array, to be used in the IRQ routine
++ *to find the channel descriptor for the channed sending the interrupt to the
++ *core.
++ */
++extern channelControlBlock *iapi_CCBHead;
++
++/* configs_data structure filled with default data*/
++extern configs_data iapi_ConfigDefaults;
++
++#ifdef SDMA_V2
++extern sdmaState iapi_SdmaState;
++#endif
++
++#endif /* iapiDefaults_h */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapi.h linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapi.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapi.h    1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapi.h    2010-12-03 09:51:55.388349760 +0100
+@@ -0,0 +1,49 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapi.h
++ *
++ * $Id iapi.h $
++ *
++ * Description:
++ *  Unique include for the whole IAPI library.
++ *
++ *
++ *  http//compass.mot.com/go/115342679
++ *
++ * $Log iapi.h $
++ *
++ * ***************************************************************************/
++
++#ifndef _iapi_h
++#define _iapi_h
++
++/* ****************************************************************************
++ * Include File Section
++ * ***************************************************************************/
++#include <linux/types.h>
++#include <mach/hardware.h>
++
++#include <iapiOS.h>
++#include <iapiLow.h>
++#include <iapiMiddle.h>
++#include <iapiHigh.h>
++
++#ifdef MCU
++#include <iapiMiddleMcu.h>
++#endif /* MCU */
++
++
++
++#endif /* _iapi_h */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiHigh.h linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiHigh.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiHigh.h        1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiHigh.h        2010-12-03 09:51:55.388349760 +0100
+@@ -0,0 +1,142 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiHigh.h
++ *
++ * $Id iapiHigh.h $
++ *
++ * Description:
++ *  prototypes for high level function of I.API
++ *
++ *
++ *  http://venerque.sps.mot.com/pjt/sfs/www/iapi/softsim_api.pdf
++ *
++ * $Log iapiHigh.h
++ *
++ * ***************************************************************************/
++
++#ifndef _iapiHigh_h
++#define _iapiHigh_h
++
++/* ****************************************************************************
++ * Include File Section
++ *****************************************************************************/
++#include "sdmaStruct.h"
++
++/* ****************************************************************************
++ * Macro-command Section
++ *****************************************************************************/
++enum {
++      IAPI_CHANGE_CHANDESC,           /* 0x00 */
++      IAPI_CHANGE_BDNUM,              /* 0x01 */
++      IAPI_CHANGE_BUFFSIZE,           /* 0x02 */
++      IAPI_CHANGE_CHANBLOCK,          /* 0x03 */
++      IAPI_CHANGE_INSTANCE,           /* 0x04 */
++      IAPI_CHANGE_OWNERSHIP,          /* 0x05 */
++      IAPI_CHANGE_SYNCH,              /* 0x06 */
++      IAPI_CHANGE_TRUST,              /* 0x07 */
++      IAPI_CHANGE_CALLBACKFUNC,       /* 0x08 */
++      IAPI_CHANGE_CHANCCB,            /* 0x09 */
++      IAPI_CHANGE_PRIORITY,           /* 0x0a */
++      IAPI_CHANGE_BDWRAP,             /* 0x0b */
++      IAPI_CHANGE_WATERMARK,          /* 0x0c */
++      IAPI_CHANGE_SET_BDCONT,         /* 0x0d */
++      IAPI_CHANGE_UNSET_BDCONT,       /* 0x0e */
++      IAPI_CHANGE_SET_BDEXTD,         /* 0x0f */
++      IAPI_CHANGE_UNSET_BDEXTD,       /* 0x10 */
++      IAPI_CHANGE_EVTMASK1,           /* 0x11 */
++      IAPI_CHANGE_EVTMASK2,           /* 0x12 */
++      IAPI_CHANGE_PERIPHADDR,         /* 0x13 */
++      IAPI_CHANGE_SET_BDINTR,         /* 0x14 */
++      IAPI_CHANGE_UNSET_BDINTR,       /* 0x15 */
++      IAPI_CHANGE_SET_TRANSFER_CD,    /* 0x16 */
++      IAPI_CHANGE_FORCE_CLOSE,        /* 0x17 */
++      IAPI_CHANGE_SET_TRANSFER,       /* 0x18 */
++      IAPI_CHANGE_USER_ARG,           /* 0x19 */
++      IAPI_CHANGE_SET_BUFFERADDR,     /* 0x1a */
++      IAPI_CHANGE_SET_EXTDBUFFERADDR, /* 0x1b */
++      IAPI_CHANGE_SET_COMMAND,        /* 0x1c */
++      IAPI_CHANGE_SET_COUNT,          /* 0x1d */
++      IAPI_CHANGE_SET_STATUS,         /* 0x1e */
++      IAPI_CHANGE_GET_BUFFERADDR,     /* 0x1f */
++      IAPI_CHANGE_GET_EXTDBUFFERADDR, /* 0x20 */
++      IAPI_CHANGE_GET_COMMAND,        /* 0x21 */
++      IAPI_CHANGE_GET_COUNT,          /* 0x22 */
++      IAPI_CHANGE_GET_STATUS,         /* 0x23 */
++      IAPI_CHANGE_BUFFER_LOCATION,    /* 0x24 */
++      IAPI_CHANGE_SET_ENDIANNESS,     /* 0x25 */
++#ifdef SDMA_V2
++      IAPI_ENTER_LOCK_MODE,           /* 0x26 */
++#endif
++      IAPI_CHANGE_SET_INTR_MASK,      /* 0x27 */
++      IAPI_CHANGE_UNSET_INTR_MASK,    /* 0x28 */
++};
++
++
++/*
++ * Public Function Prototype Section
++ */
++int iapi_Open(channelDescriptor *cd_p, unsigned char channelNumber);
++int iapi_Close(channelDescriptor *cd_p);
++int iapi_Read(channelDescriptor *cd_p, void *buf, unsigned short nbyte);
++int iapi_Write(channelDescriptor *cd_p, void *buf, unsigned short nbyte);
++int iapi_MemCopy(channelDescriptor *cd_p, void* dest, void* src,
++              unsigned long size);
++int iapi_IoCtl(channelDescriptor *cd_p, unsigned long ctlRequest,
++                              unsigned long param);
++
++
++int iapi_Read_ipcv2(channelDescriptor *cd_p, void *data_control_struct_ipcv2);
++
++int iapi_Write_ipcv2(channelDescriptor *cd_p, void *data_control_struct_ipcv2);
++
++#ifdef MCU
++int iapi_Init(channelDescriptor *cd_p, configs_data *config_p,
++      unsigned short *ram_image, unsigned short code_size,
++      dma_addr_t start_addr, unsigned short channel0_addr);
++#endif /* MCU */
++#ifdef DSP
++int iapi_Init(channelDescriptor *cd_p);
++#endif /* DSP */
++
++int iapi_StartChannel(unsigned char channel);
++int iapi_StopChannel(unsigned char channel);
++int iapi_SynchChannel(unsigned char channel);
++
++int iapi_GetChannelNumber(channelDescriptor *cd_p);
++unsigned long iapi_GetError(channelDescriptor *cd_p);
++int iapi_GetCount(channelDescriptor *cd_p);
++int iapi_GetCountAll(channelDescriptor *cd_p);
++
++#ifndef IRQ_KEYWORD
++#define IRQ_KEYWORD
++#endif /* IRQ_KEYWORD */
++
++IRQ_KEYWORD void IRQ_Handler(void);
++
++#ifdef MCU
++int iapi_GetScript(channelDescriptor *cd_p, void *buf, unsigned short size,
++              dma_addr_t address);
++int iapi_GetContext(channelDescriptor *cd_p, void *buf,
++              unsigned char channel);
++int iapi_SetScript(channelDescriptor *cd_p, void *buf, unsigned short nbyte,
++              dma_addr_t destAddr);
++int iapi_SetContext(channelDescriptor *cd_p, void *buf,
++              unsigned char channel);
++int iapi_AssignScript(channelDescriptor *cd_p, script_data *data_p);
++
++int iapi_SetChannelEventMapping(unsigned char event, unsigned long channel_map);
++#endif /* MCU */
++
++#endif /* _iapiHigh_h */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiLowDsp.h linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiLowDsp.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiLowDsp.h      1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiLowDsp.h      2010-12-03 09:51:55.388349760 +0100
+@@ -0,0 +1,50 @@
++/*
++ * Copyright 2007 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: iapiLowDsp.h
++ *
++ * $Id iapiLowDsp.h $
++ *
++ * Description:
++ *  prototypes for low level function of I.API for DSP side only
++ *
++ *
++ *
++ *
++ * $Log iapiLowDsp.h
++ *
++ * ***************************************************************************/
++
++#ifndef _iapiLowDsp_h
++#define _iapiLowDsp_h
++
++/* ****************************************************************************
++ * Include File Section
++ *****************************************************************************/
++
++
++/* ****************************************************************************
++ * Public Function Prototype Section
++ *****************************************************************************/
++/* WARNING !!!!!
++ * This file is empty and it is normal, because there is no low level functions
++ * dedicated to the DSP but the file (iapi_LowDsp.h) must still exist because
++ * some project directly links the file. Previously, there were function
++ * iapi_EnableInterrupts,iapi_DisableInterrupts,iapi_WaitCore,iapi_StartChannel
++ * iapi_StopChannel but they are common to both MCU and DSP, so they have been
++ * moved to iapi_Low.h file.
++ */
++
++#endif /* _iapiLowDsp_h */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiLow.h linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiLow.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiLow.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiLow.h 2010-12-03 09:51:55.388349760 +0100
+@@ -0,0 +1,70 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiLow.h
++ *
++ * $Id iapiLow.h $
++ *
++ * Description:
++ *  prototypes for low level function of I.API
++ *
++ *
++ *
++ *
++ * $Log iapiLow.h
++ *
++ * ***************************************************************************/
++
++#ifndef _iapiLow_h
++#define _iapiLow_h
++
++/* ****************************************************************************
++ * Boolean identifiers
++ *****************************************************************************/
++
++/* ****************************************************************************
++ * Include File Section
++ *****************************************************************************/
++#include "iapiOS.h"
++#include <linux/types.h>
++#include <mach/dma.h>
++
++/* ****************************************************************************
++ * Macro-command Section
++ *****************************************************************************/
++enum
++{
++      OR_OP,
++      AND_OP
++};
++
++/* ****************************************************************************
++ * Public Function Prototype Section
++ *****************************************************************************/
++typedef void (*CallbackISR)(channelDescriptor *cd_p, void *arg);
++
++void iapi_lowStartChannel(unsigned char channel);
++void iapi_lowStopChannel(unsigned char channel);
++int iapi_lowChangeIntrMask(unsigned int param, unsigned char op);
++void iapi_AttachCallbackISR(channelDescriptor *cd_p,
++                          CallbackISR func_p);
++void iapi_DetachCallbackISR(channelDescriptor *cd_p);
++void iapi_ChangeCallbackISR(channelDescriptor *cd_p,
++                          CallbackISR func_p);
++void iapi_lowSynchChannel(unsigned char channel);
++void iapi_SetBufferDescriptor(bufferDescriptor *bd_p, unsigned char command,
++                            unsigned char status, unsigned short count,
++                            void *buffAddr, dma_addr_t extBufferAddr);
++
++#endif /* _iapiLow_h */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiLowMcu.h linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiLowMcu.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiLowMcu.h      1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiLowMcu.h      2010-12-03 09:51:55.388349760 +0100
+@@ -0,0 +1,58 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiLowMcu.h
++ *
++ * $Id iapiLowMcu.h $
++ *
++ * Description:
++ *  prototypes for low level function of I.API of MCU side only
++ *
++ *
++ *
++ *
++ * $Log iapiLowMcu.h $
++ *
++ * ***************************************************************************/
++
++#ifndef _iapiLowMcu_h
++#define _iapiLowMcu_h
++
++/******************************************************************************
++ * Include File Section
++ *****************************************************************************/
++
++/* ****************************************************************************
++ * Public Function Prototype Section
++ * ***************************************************************************/
++
++
++void iapi_InitChannelTables(void);
++int iapi_ChannelConfig(unsigned char channel, unsigned eventOverride,
++              unsigned mcuOverride, unsigned dspOverride);
++int iapi_Channel0Command(channelDescriptor *cd_p, void *buf,
++                      unsigned short nbyte, unsigned char command);
++void iapi_lowGetScript(channelDescriptor *cd_p, void *buf, unsigned short size,
++              dma_addr_t address);
++void iapi_lowGetContext(channelDescriptor *cd_p, void *buf,
++                      unsigned char channel);
++void iapi_lowSetScript(channelDescriptor *cd_p, void *buf, unsigned short nbyte,
++                      dma_addr_t destAddr);
++void iapi_lowSetContext(channelDescriptor *cd_p, void *buf,
++                      unsigned char channel);
++int iapi_lowAssignScript(channelDescriptor *cd_p, script_data *data_p);
++
++int iapi_lowSetChannelEventMapping(unsigned char event, unsigned long channel_map);
++
++#endif /* _iapiLowMcu_h */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddle.h linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddle.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddle.h      1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddle.h      2010-12-03 09:51:55.392354434 +0100
+@@ -0,0 +1,52 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiMiddle.h
++ *
++ * $Id iapiMiddle.h $
++ *
++ * Description:
++ *  prototypes for middle level function of I.API
++ *
++ *
++ *
++ *
++ * $Log iapiMiddle.h
++ *
++ * ***************************************************************************/
++
++#ifndef _iapiMiddle_h
++#define _iapiMiddle_h
++
++/* ****************************************************************************
++ * Include File Section
++ ******************************************************************************/
++#include "sdmaStruct.h"
++#ifdef MCU
++#include "iapiMiddleMcu.h"
++#endif /* MCU */
++
++/* ****************************************************************************
++ * Public Function Prototype Section
++ ******************************************************************************/
++bufferDescriptor *iapi_AllocBD(channelControlBlock *ccb_p);
++int  iapi_AllocContext(contextData **ctxd_p, unsigned char channel);
++int  iapi_AllocChannelDesc(channelDescriptor **cd_p, unsigned char channel);
++int  iapi_ChangeChannelDesc (channelDescriptor *cd_p,
++                      unsigned char whatToChange, unsigned long newval);
++void iapi_InitializeCallbackISR(void (*func_p)(channelDescriptor *cd_p,
++                                                                      void *arg));
++int iapi_InitializeMemory (channelControlBlock *ccb_p);
++
++#endif /* iapiMiddle_h */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddleMcu.h linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddleMcu.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddleMcu.h   1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiMiddleMcu.h   2010-12-03 09:51:55.392354434 +0100
+@@ -0,0 +1,41 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiMiddleMcu.h
++ *
++ * $Id iapiMiddleMcu.h $
++ *
++ * Description:
++ *  prototypes for middle level function of I.API
++ *
++ *
++ *
++ *
++ * $Log iapiMiddleMcu.h
++ *
++ * ***************************************************************************/
++
++#ifndef _iapiMiddleMcu_h
++#define _iapiMiddleMcu_h
++
++/* ****************************************************************************
++ * Include File Section
++ ******************************************************************************/
++#include "sdmaStruct.h"
++
++/* ****************************************************************************
++ * Public Function Prototype Section
++ ******************************************************************************/
++
++#endif /* iapiMiddleMcu_h */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiOS.h linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiOS.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/iapiOS.h  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/iapiOS.h  2010-12-03 09:51:55.392354434 +0100
+@@ -0,0 +1,95 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiOS.h
++ *
++ * $Id iapiOS.h $
++ *
++ * Description:
++ *  prototypes for OS level function of I.API
++ *
++ *
++ *
++ *
++ * $Log iapiOS.h
++ *
++ * ***************************************************************************/
++
++#ifndef _iapiOS_h
++#define _iapiOS_h
++
++/* ****************************************************************************
++ * Boolean identifiers
++ *****************************************************************************/
++#define NO_OS     0
++#define LINUX     1
++#define SYMBIAN   2
++#define WINCE     3
++
++/* ****************************************************************************
++ * Include File Section
++ *****************************************************************************/
++#if OS == NO_OS
++#include <stdlib.h>
++#elif OS == LINUX
++#include <linux/types.h>
++#endif
++
++#include "sdmaStruct.h"
++#include "iapiDefaults.h"
++#ifdef MCU
++#include "iapiLowMcu.h"
++#endif /* MCU */
++
++/* ****************************************************************************
++ * Macro-command Section
++ *****************************************************************************/
++#ifdef CONFIG_SDMA_IRAM
++#define IRAM_MALLOC(x) (*iapi_iram_Malloc)(x)
++#else
++#define IRAM_MALLOC(x) (*iapi_Malloc)(x)
++#endif
++#define MALLOC(x) (*iapi_Malloc)(x)
++#define FREE(x)   if ((x) != NULL) (*iapi_Free)(x)
++
++#define GOTO_SLEEP(x) (iapi_GotoSleep)(x)
++#define INIT_SLEEP(x) (iapi_InitSleep)(x)
++
++/* ****************************************************************************
++ * Public Function Prototype Section
++ *****************************************************************************/
++
++#ifdef CONFIG_SDMA_IRAM
++extern void *(*iapi_iram_Malloc)(size_t size);
++#endif
++extern void *(*iapi_Malloc)(size_t size);
++extern void (*iapi_Free)(void *ptr);
++
++extern dma_addr_t (*iapi_Virt2Phys)(void *ptr);
++extern void *(*iapi_Phys2Virt)(dma_addr_t);
++
++extern void (*iapi_WakeUp)(int);
++extern void (*iapi_GotoSleep)(int);
++extern void (*iapi_InitSleep)(int);
++
++extern void *(*iapi_memcpy)(void *dest, const void *src, size_t count);
++extern void *(*iapi_memset)(void *dest, int c, size_t count);
++
++extern void (*iapi_EnableInterrupts)(void);
++extern void (*iapi_DisableInterrupts)(void);
++
++extern int (*iapi_GetChannel)(int);
++extern int (*iapi_ReleaseChannel)(int);
++
++#endif /* _iapiOS_h */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/sdmaStruct.h linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/sdmaStruct.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/include/sdmaStruct.h      1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/include/sdmaStruct.h      2010-12-03 09:51:55.392354434 +0100
+@@ -0,0 +1,465 @@
++/******************************************************************************
++ *
++ * Copyright 2007-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: sdmaStruct.h
++ *
++ * $Id sdmaStruct.h $
++ *
++ * Description: provides necessary definitions and inclusion for ipcmStruct.c
++ *
++ * $Log $
++ *
++ *****************************************************************************/
++#ifndef _sdmaStruct_h
++#define _sdmaStruct_h
++
++/* ****************************************************************************
++ * Include File Section
++ ******************************************************************************/
++
++/* ****************************************************************************
++ * Macro-command Section
++ ******************************************************************************/
++
++/**
++ * Identifier NULL
++ */
++#ifndef NULL
++#define NULL 0
++#endif
++
++/**
++ * Boolean identifiers
++ */
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++/**
++ * Number of channels
++ */
++#define CH_NUM  32
++/**
++ * Number of events
++ */
++#ifdef SDMA_V2
++#define EVENTS_NUM   48
++#else
++#define EVENTS_NUM   32
++#endif
++/**
++ * Channel configuration
++ */
++#define DONT_OWN_CHANNEL   0
++#define OWN_CHANNEL      1
++
++/**
++ * Ownership (value defined to computed decimal value)
++ */
++#define CH_OWNSHP_OFFSET_EVT 0
++#define CH_OWNSHP_OFFSET_MCU 1
++#define CH_OWNSHP_OFFSET_DSP 2
++/**
++ * Indexof the greg which holds address to start a script from when channel
++ * becomes current.
++ */
++#define SDMA_NUMBER_GREGS 8
++
++/**
++ * Channel contexts management
++ */
++
++#define CHANNEL_CONTEXT_BASE_ADDRESS          0x800
++/**
++ * Buffer descriptor status values.
++ */
++#define BD_DONE  0x01
++#define BD_WRAP  0x02
++#define BD_CONT  0x04
++#define BD_INTR  0x08
++#define BD_RROR  0x10
++#define BD_LAST  0x20
++#define BD_EXTD  0x80
++
++
++/**
++ * Data Node descriptor status values.
++ */
++#define DND_END_OF_FRAME  0x80
++#define DND_END_OF_XFER         0x40
++#define DND_DONE        0x20
++#define DND_UNUSED      0x01
++
++/**
++ * IPCV2 descriptor status values.
++ */
++#define BD_IPCV2_END_OF_FRAME  0x40
++
++
++#define IPCV2_MAX_NODES              50
++/**
++ * Error bit set in the CCB status field by the SDMA,
++ * in setbd routine, in case of a transfer error
++ */
++#define DATA_ERROR  0x10000000
++
++/**
++ * Buffer descriptor commands.
++ */
++#define C0_ADDR                   0x01
++#define C0_LOAD                   0x02
++#define C0_DUMP                   0x03
++#define C0_SETCTX         0x07
++#define C0_GETCTX         0x03
++#define C0_SETDM          0x01
++#define C0_SETPM          0x04
++#define C0_GETDM          0x02
++#ifdef SDMA_V2
++#define C0_GETPM          0x06
++#else
++#define C0_GETPM          0x08
++#endif
++/**
++ * Transfer types, encoded in the BD command field
++ */
++#define TRANSFER_32BIT      0x00
++#define TRANSFER_8BIT       0x01
++#define TRANSFER_16BIT      0x02
++#define TRANSFER_24BIT      0x03
++
++#define TRANSFER_TYPE_MASK  0x03    /* MASK FOR BIT0 and BIT1 of BD Command Field*/
++/**
++ * Memory types, encoded in the BD command field
++ */
++#define EXTERNAL_MEM      0x04
++#define INTERNAL_MEM      ~0x04
++
++#define BUFFER_LOC_MASK     0x04  /* MASK FOR BIT2 of BD Command Field*/
++/**
++ * Change endianness indicator in the BD command field
++ */
++#define CHANGE_ENDIANNESS   0x80
++
++#define ENDIANNESS_MASK     0x80  /* MASK FOR BIT7 of BD Command Field*/
++/**
++ * Size in bytes
++ */
++#define SDMA_BD_SIZE  8
++#define SDMA_EXTENDED_BD_SIZE  12
++#define BD_NUMBER     4
++/**
++ * Channel interrupt policy
++ */
++#define DEFAULT_POLL 0
++#define CALLBACK_ISR 1
++/**
++ * Channel status
++ */
++#define UNINITIALIZED 0
++#define   INITIALIZED 1
++
++/**
++ * IoCtl particular values
++ */
++#define SET_BIT_ALL     0xFFFFFFFF
++#define BD_NUM_OFFSET   16
++#define BD_NUM_MASK     0xFFFF0000
++
++/**
++ * Maximum values for IoCtl calls, used in high or middle level calls
++ */
++#define MAX_BD_NUM       1024
++#define MAX_BD_SIZE      65536
++#define MAX_BLOCKING     2
++#define MAX_SYNCH        2
++#define MAX_OWNERSHIP    8
++#define MAX_CH_PRIORITY          8
++#define MAX_TRUST        2
++#define MAX_WML                  256
++
++
++/**
++ * Access to channelDescriptor fields
++ */
++enum {
++      IAPI_CHANNELNUMBER,     /* 0x00 */
++      IAPI_BUFFERDESCNUMBER,  /* 0x01 */
++      IAPI_BUFFERSIZE,        /* 0x02 */
++      IAPI_BLOCKING,          /* 0x03 */
++      IAPI_CALLBACKSYNCH,     /* 0x04 */
++      IAPI_OWNERSHIP,         /* 0x05 */
++      IAPI_PRIORITY,          /* 0x06 */
++      IAPI_TRUST,             /* 0x07 */
++      IAPI_UNUSED,            /* 0x08 */
++      IAPI_CALLBACKISR_PTR,   /* 0x09 */
++      IAPI_CCB_PTR,           /* 0x0a */
++      IAPI_BDWRAP,            /* 0x0b */
++      IAPI_WML,               /* 0x0c */
++};
++
++#ifdef SDMA_V2
++
++/**
++ * Enum for SDMA states
++ */
++typedef enum {
++      UNDEF,
++      OPEN,
++      LOCK,
++      CLOSED,
++      CLOSE_LOCK
++} sdmaState;
++
++/**
++ * LOCK Register Value
++ */
++ #define RESET_CLEAR_LOCK 0x03
++ #define RESET_NOCLEAR_LOCK 0x01
++
++#define RESET_CLR_BIT_OFFSET 1
++#define LOCK_BIT_OFFSET 0
++
++#endif
++
++/**
++ * Default values for channel descriptor - nobody ownes the channel
++ */
++#define CD_DEFAULT_OWNERSHIP  7
++
++
++/**
++ * User Type Section
++ */
++
++/**
++ * Command/Mode/Count of buffer descriptors
++ */
++
++#if (ENDIANNESS==B_I_G_ENDIAN)
++typedef struct iapi_modeCount_ipcv2 {
++      unsigned long  status   :  8; /* L, E , D bits stored here */
++      unsigned long  reserved :  8;
++      unsigned long  count    : 16; /* <size of the buffer pointed by this BD */
++} modeCount_ipcv2;
++#else
++typedef struct iapi_modeCount_ipcv2 {
++      unsigned long  count    : 16; /* size of the buffer pointed by this BD */
++      unsigned long  reserved :  8; /* Reserved*/
++      unsigned long  status   :  8; /* L, E , D bits stored here */
++} modeCount_ipcv2;
++#endif
++/**
++ * Data Node descriptor - IPCv2
++ * (differentiated between evolutions of SDMA)
++ */
++typedef struct iapi_dataNodeDescriptor {
++      modeCount_ipcv2 mode;           /* command, status and count */
++      dma_addr_t      bufferAddr;     /* address of the buffer described */
++} dataNodeDescriptor;
++
++#if (ENDIANNESS==B_I_G_ENDIAN)
++typedef struct iapi_modeCount_ipcv1_v2 {
++      unsigned long   endianness: 1;
++      unsigned long   reserved: 7;
++      unsigned long   status  :  8; /* E,R,I,C,W,D status bits stored here */
++      unsigned long   count   : 16; /* size of the buffer pointed by this BD */
++} modeCount_ipcv1_v2;
++#else
++typedef struct iapi_modeCount_ipcv1_v2 {
++      unsigned long  count   : 16; /* size of the buffer pointed by this BD */
++      unsigned long  status  :  8; /* E,R,I,C,W,D status bits stored here */
++      unsigned long   reserved: 7;
++      unsigned long   endianness: 1;
++} modeCount_ipcv1_v2;
++#endif
++/**
++ * Buffer descriptor
++ * (differentiated between evolutions of SDMA)
++ */
++typedef struct iapi_bufferDescriptor_ipcv1_v2 {
++      modeCount_ipcv1_v2  mode; /* command, status and count */
++      dma_addr_t      bufferAddr;    /* address of the buffer described */
++      dma_addr_t      extBufferAddr; /* extended buffer address */
++} bufferDescriptor_ipcv1_v2;
++
++
++/**
++ * Mode/Count of data node descriptors - IPCv2
++ */
++
++#if (ENDIANNESS==B_I_G_ENDIAN)
++typedef struct iapi_modeCount {
++      unsigned long  command :  8; /* command mostly used for channel 0 */
++      unsigned long  status  :  8; /* E,R,I,C,W,D status bits stored here */
++      unsigned long  count   : 16; /* size of the buffer pointed by this BD */
++} modeCount;
++#else
++typedef struct iapi_modeCount {
++      unsigned long  count   : 16; /* size of the buffer pointed by this BD */
++      unsigned long  status  :  8; /* E,R,I,C,W,D status bits stored here */
++      unsigned long  command :  8; /* command mostly used for channel 0 */
++} modeCount;
++#endif
++
++
++/**
++ * Buffer descriptor
++ * (differentiated between evolutions of SDMA)
++ */
++typedef struct iapi_bufferDescriptor {
++      modeCount       mode;           /* command, status and count */
++      dma_addr_t      bufferAddr;     /* address of the buffer described */
++      dma_addr_t      extBufferAddr;  /* extended buffer address */
++} bufferDescriptor;
++
++
++
++struct iapi_channelControlBlock;
++struct iapi_channelDescriptor;
++/**
++ * Channel Descriptor
++ */
++typedef struct iapi_channelDescriptor {
++      unsigned char   channelNumber   ;/* stores the channel number */
++      unsigned short  bufferSize      ;/* size (in bytes) of buffer descriptors */
++      unsigned short  bufferDescNumber;/* number of BD's automatically allocated for this channel */
++      unsigned long   blocking      :3;/* blocking / non blocking feature selection */
++      unsigned long   callbackSynch :1;/* polling/ callback method selection */
++      unsigned long   ownership     :3;/* ownership of the channel (host+dedicated+event)*/
++      unsigned long   priority      :3;/* reflects the SDMA channel priority register */
++      unsigned long   trust         :1;/* trusted buffers or kernel allocated */
++      unsigned long   useDataSize   :1;/* indicates if the dataSize field is meaningfull */
++      unsigned long   dataSize      :2;/* data transfer size - 8,16,24 or 32 bits*/
++      unsigned long   forceClose    :1;/* if TRUE, close channel even with BD owned by SDMA*/
++      unsigned long   scriptId      :7;/* number of the script */
++      unsigned long   watermarkLevel:10;/* Watermark level for the peripheral access*/
++      unsigned long   eventMask1;      /* First Event mask */
++      unsigned long   eventMask2;      /* Second  Event mask */
++      unsigned long   peripheralAddr;  /* Address of the peripheral or its fifo when needed */
++      void (*callbackISR_ptr)(struct iapi_channelDescriptor*, void*);   /* pointer to the callback function (or NULL) */
++      struct iapi_channelControlBlock *ccb_ptr; /* pointer to the channel control block associated to this channel */
++} channelDescriptor;
++
++/**
++ * Channel Status
++ */
++typedef struct iapi_channelStatus {
++      unsigned long  unused :27,
++              data_error    : 1,
++              even_more_unused: 1,
++              openedInit    : 1, /* channel is initialized */
++              stateDirection: 1, /* sdma is reading/writing (as seen from channel owner core) */
++              execute       : 1; /* channel is being processed (started) */
++} channelStatus;
++
++/**
++ * Channel control Block
++ */
++typedef struct iapi_channelControlBlock {
++      dma_addr_t      currentBDptr;      /* current buffer descriptor processed */
++      dma_addr_t      baseBDptr;            /* first element of buffer descriptor array */
++      channelDescriptor *channelDescriptor; /* pointer to the channel descriptor */
++      channelStatus   status;       /* open/close ; started/stopped ; read/write */
++} channelControlBlock;
++
++/**
++ * Context structure.
++ */
++#if (ENDIANNESS==B_I_G_ENDIAN)
++typedef struct iapi_stateRegisters {
++      unsigned long sf     : 1;/* source falut while loading data */
++      unsigned long unused0: 1;/* */
++      unsigned long rpc    :14;/* return program counter */
++      unsigned long t      : 1;/* test bit:status of arithmetic & test instruction*/
++      unsigned long unused1: 1;/* */
++      unsigned long pc     :14;/* program counter */
++      unsigned long lm     : 2;/* loop mode */
++      unsigned long epc    :14;/* loop end program counter */
++      unsigned long df     : 1;/* destiantion falut while storing data */
++      unsigned long unused2: 1;/* */
++      unsigned long spc    :14;/* loop start program counter */
++} stateRegiters;
++#else
++typedef struct iapi_stateRegisters {
++      unsigned long pc     :14;/* program counter */
++      unsigned long unused1: 1;/* */
++      unsigned long t      : 1;/* test bit: status of arithmetic & test instruction*/
++      unsigned long rpc    :14;/* return program counter */
++      unsigned long unused0: 1;/* */
++      unsigned long sf     : 1;/* source falut while loading data */
++      unsigned long spc    :14;/* loop start program counter */
++      unsigned long unused2: 1;/* */
++      unsigned long df     : 1;/* destiantion falut while storing data */
++      unsigned long epc    :14;/* loop end program counter */
++      unsigned long lm     : 2;/* loop mode */
++} stateRegiters;
++#endif
++
++/**
++ * This is SDMA version of SDMA
++ */
++typedef struct iapi_contextData {
++      stateRegiters  channelState;              /* channel state bits */
++      unsigned long  gReg[SDMA_NUMBER_GREGS]; /* general registers */
++      unsigned long  mda; /* burst dma destination address register */
++      unsigned long  msa; /* burst dma source address register */
++      unsigned long  ms;  /* burst dma status  register */
++      unsigned long  md;  /* burst dma data    register */
++      unsigned long  pda; /* peripheral dma destination address register */
++      unsigned long  psa; /* peripheral dma source address register */
++      unsigned long  ps;  /* peripheral dma  status  register */
++      unsigned long  pd;  /* peripheral dma  data    register */
++      unsigned long  ca;  /* CRC polynomial  register */
++      unsigned long  cs;  /* CRC accumulator register */
++      unsigned long  dda; /* dedicated core destination address register */
++      unsigned long  dsa; /* dedicated core source address register */
++      unsigned long  ds;  /* dedicated core status  register */
++      unsigned long  dd;  /* dedicated core data    register */
++      unsigned long  scratch0;  /* scratch */
++      unsigned long  scratch1;  /* scratch */
++      unsigned long  scratch2;  /* scratch */
++      unsigned long  scratch3;  /* scratch */
++      unsigned long  scratch4;  /* scratch */
++      unsigned long  scratch5;  /* scratch */
++      unsigned long  scratch6;  /* scratch */
++      unsigned long  scratch7;  /* scratch */
++} contextData;
++
++/**
++ *This structure holds the necessary data for the assignment in the
++ * dynamic channel-script association
++ */
++typedef struct iapi_script_data {
++      unsigned short load_address;/* start address of the script */
++      unsigned long  wml;         /* parameters for the channel descriptor */
++      unsigned long  shp_addr;    /* shared peripheral base address */
++      unsigned long  event_mask1; /* First Event mask */
++      unsigned long  event_mask2; /* Second Event mask */
++} script_data;
++
++/**
++ *This structure holds the the useful bits of the CONFIG register
++ */
++typedef struct iapi_configs_data {
++      unsigned long   dspdma   :1; /* indicates if the DSPDMA is used */
++      unsigned long   rtdobs   :1; /* indicates if Real-Time Debug pins are enabled */
++      unsigned long   acr   :1; /* indicates if AHB freq /core freq = 2 or 1 */
++      unsigned long   csm   :2; /* indicates which context switch mode is selected */
++} configs_data;
++
++#endif /* _sdmaStruct_h */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/Makefile linux.35.new/arch/arm/plat-mxc/sdma/iapi/Makefile
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/Makefile  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/Makefile  2010-12-03 09:51:55.392354434 +0100
+@@ -0,0 +1,5 @@
++#
++# Makefile for I.API sources.
++#
++
++obj-y := src/
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiDefaults.c linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiDefaults.c
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiDefaults.c        1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiDefaults.c        2010-12-03 09:51:55.396349340 +0100
+@@ -0,0 +1,128 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiDefaults.c
++ *
++ * $Id iapiDefaults.c $
++ *
++ * Description:
++ *  This library is written in C to guarantee functionality and integrity in
++ * the usage of SDMA virtual DMA channels. This API (Application Programming
++ * Interface)  allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
++ * fashion.
++ *
++ * Usage:
++ *
++ * Files:
++ *
++ *
++* /
++ *
++ * $Log iapiDefaults.c $
++ *
++ *****************************************************************************/
++
++/* ****************************************************************************
++ * Include File Section
++ ******************************************************************************/
++#include <iapi.h>
++
++/* ****************************************************************************
++ * Global Variable Section
++ ******************************************************************************/
++
++/**
++ * @brief System Call-back ISRs Table
++ */
++void (*callbackIsrTable[CH_NUM])(channelDescriptor *cd_p, void *arg);
++
++/**
++ * @brief User registered pointers table
++ */
++void *userArgTable[CH_NUM];
++
++/**
++ * @brief Pointer to the first CCB in the CCB array
++ */
++channelControlBlock *iapi_CCBHead = NULL;
++
++
++/**Default channel description.
++ *
++ * Initialization values are:\n
++ *  - channelNumber    = 0
++ *  - bufferDescNumber = 1
++ *  - bufferSize       = 8
++ *  - blocking         = 0
++ *  - callbackSynch    = DEFAULT_POLL
++ *  - ownership        = CD_DEFAULT_OWNERSHIP
++ *  - priority         = 1
++ *  - trust            = TRUE
++ *  - useDataSize      = 0
++ *  - dataSize         = 0
++ *  - forceClose       = 0
++ *  - scriptId         = 0
++ *  - watermarkLevel   = 0
++ *  - eventMask1       = 0
++ *  - eventMask2       = 0
++ *  - peripheralAddr   = NULL
++ *  - callbackISR_ptr  = NULL
++ *  - iapi_channelControlBlock = NULL
++ */
++channelDescriptor iapi_ChannelDefaults = {
++      0, 1, 8, 0, DEFAULT_POLL,
++      CD_DEFAULT_OWNERSHIP, 1, TRUE, 0, 0, 0, 0,
++      0, 0x00, 0x00, 0x00, NULL, NULL,
++};
++
++/**
++ * Integrated error management
++ */
++int iapi_errno = 0;
++volatile unsigned long iapi_SDMAIntr = 0;
++
++/* Default config register.
++ * Initialization values are:
++ * dspdma used
++ * Real-Time Debug pins disabled
++ * AHB freq / core freq = 2
++ * dynamic context switch
++*/
++
++/* DSPDMA (12th) bit of CONFIG Register should be zero when DSP DMA is not connected.
++ * Otherwise it can even lead to hang while doing the context switch.
++ * Hence for all MAD targets, iapi_ConfigDefaults should be updated to:
++ * { 0, 0, 0, 3 OR 0 } depending on whether context switching
++ * needs to be static or dynamic */
++configs_data iapi_ConfigDefaults = {
++      /* according to the i.MX25 reference manual this should be configured as 0 */
++#ifndef CONFIG_ARCH_MX25
++      1,
++#else
++      0,
++#endif
++      0,
++      0,
++      3,
++};
++
++#ifdef SDMA_V2
++/* Default sdma State : UNDEF
++ *possible value are UNDEF, OPEN, LOCK, CLOSED, CLOSE_LOCK
++ */
++
++sdmaState iapi_SdmaState = UNDEF;
++#endif
++
++/* ***************************************************************************/
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiHigh.c linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiHigh.c
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiHigh.c    1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiHigh.c    2010-12-03 09:51:55.404347330 +0100
+@@ -0,0 +1,2462 @@
++/******************************************************************************
++ *
++ * Copyright 2007-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
++ *
++ ******************************************************************************
++ *
++ * File: iapiHigh.c
++ *
++ * $Id iapiHigh.c $
++ *
++ * Description:
++ *  This library is written in C to guarantee functionality and integrity in
++ * the usage of SDMA virtual DMA channels. This API (Application Programming
++ * Interface)  allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
++ * fashion.
++ *  These are the HIGH level functions of the I.API.
++ *
++ *
++ * /
++ *
++ * $Log iapiHigh.c $
++ *
++ *****************************************************************************/
++
++/* ****************************************************************************
++ * Include File Section
++ *****************************************************************************/
++#include <stdarg.h>
++#include <string.h>
++#include <linux/err.h>
++#include <linux/io.h>
++
++#include <epm.h>
++#include <iapi.h>
++
++#ifdef DEBUG
++#include <mach/sdma.h>
++#if CH_NUM != MAX_DMA_CHANNELS
++#error BAD number of DMA channels!
++#endif
++#endif
++
++/* ****************************************************************************
++ * External Reference Section (for compatibility with already developed code)
++ *****************************************************************************/
++static void iapi_read_ipcv2_callback(struct iapi_channelDescriptor *cd_p, void *data);
++
++/* ****************************************************************************
++ * Global Variable Section
++ *****************************************************************************/
++#define               MAX_CHANNEL         32
++
++static dataNodeDescriptor *dnd_read_control_struct[MAX_CHANNEL];
++
++/* MASK to nullify all the bits of Status in Data Node descriptor apart from L, E and D */
++#define           GET_LED_MASK            0xE0
++
++/* Table defines mapping of Data Node Descriptor to Buffer Descriptor status */
++static unsigned char dnd_2_bd_status[] = {
++      [0x00] = 0x85, /* L = 0, E = 0,  D = 0 */
++      [0x20] = 0x84, /* L = 0, E = 0,  D = 1 */
++      [0x40] = 0xAB, /* L = 0, E = 1,  D = 0 */
++      [0x60] = 0xAA, /* L = 0, E = 1,  D = 1 */
++      [0x80] = 0xC5, /* L = 1, E = 0,  D = 0 */
++      [0xA0] = 0xC4, /* L = 1, E = 0,  D = 1 */
++      [0xC0] = 0xEB, /* L = 1, E = 1,  D = 0 */
++      [0xE0] = 0xEA, /* L = 1, E = 1,  D = 1 */
++};
++/* ****************************************************************************
++ * Function Section
++ *****************************************************************************/
++
++/* ***************************************************************************/
++/* Opens an SDMA channel to be used by the library.
++ *
++ * <b>Algorithm:</b>\n
++ *
++ * - Check if initialization is necessary.
++ *   - Check that user initialized OS dependant functions.
++ *   - Test validity of input parameters
++ *   - Check whole channel control block data structure
++ *   - Finish initializations (tables with default values)
++ *   - Initialize channel 0 is dedicated to communications with SDMA
++ * - Check channel control block definition
++ *   - if the channel descriptor is not initialized, initialize it with
++ * the default value
++ * - If buffer descriptor already allocated, exit with iapi_errno filled
++ * complete the lowest bits with the number of 'D' bits set
++ * - Buffer Descriptors allocation
++ * - Channel's configuration properties (mcu side only)
++ * - read/write direction => enable/disable channel setting
++ *
++ * @param  *cd_p If channelNumber is 0, it is pointer to channel descriptor
++ *            for the channnel 0 to be opened and
++ *            has default values.
++ *            For other channels, this function should be called after
++ *            channel 0 has been opened, and it's channel descriptor
++ *            has been allocated.
++ * @param  channelNumber channel to be opened
++ *
++ * @return
++ *     - IAPI_SUCCESS : OK
++ *     - -iapi_errno : close failed, return negated value of iapi_errno
++ */
++int
++iapi_Open(channelDescriptor *cd_p, unsigned char channelNumber)
++{
++      channelControlBlock *ccb_p;
++      channelControlBlock *local_ccb_p;
++      channelDescriptor   *local_cd_p;
++      bufferDescriptor    *bd_p;
++      int index;
++
++      DBG(0, "%s: cd_p=%p channel=%d\n", __FUNCTION__, cd_p, channelNumber);
++
++      /*
++       * 1. Check if initialization is necessary
++       */
++      if (cd_p == NULL) {
++              iapi_errno = IAPI_ERR_CD_UNINITIALIZED |
++                      IAPI_ERR_CH_AVAILABLE | channelNumber;
++              return -iapi_errno;
++      }
++
++      /* Verify these functions every time */
++      if ((iapi_GetChannel == NULL) || (iapi_ReleaseChannel == NULL)) {
++              iapi_errno = IAPI_ERR_NO_OS_FN | channelNumber;
++              return -iapi_errno;
++      }
++
++      /* Try to aquire channel */
++      if (iapi_GetChannel(channelNumber) != 0) {
++              iapi_errno = IAPI_ERR_CH_IN_USE | channelNumber;
++              return -iapi_errno;
++      }
++
++      DBG(0, "%s@%d: cd_p=%p ccb_ptr=%p\n", __FUNCTION__, __LINE__, cd_p,
++              cd_p->ccb_ptr);
++      if (channelNumber == 0 && cd_p->ccb_ptr == NULL) {
++              int i;
++
++              /* Verify that the user initialized all OS dependant functions required
++               * by the library.
++               */
++              if ((iapi_Malloc == NULL) ||
++                      (iapi_Free == NULL) ||
++                      (iapi_Virt2Phys == NULL) ||
++                      (iapi_Phys2Virt == NULL) ||
++                      (iapi_GotoSleep == NULL) ||
++                      (iapi_WakeUp == NULL) ||
++                      (iapi_InitSleep == NULL) ||
++                      (iapi_memset == NULL) ||
++                      (iapi_memcpy == NULL)) {
++                      iapi_errno = IAPI_ERR_NO_OS_FN | channelNumber;
++                      iapi_ReleaseChannel(channelNumber);
++                      return -iapi_errno;
++              }
++              DBG(0, "%s@%d: \n", __FUNCTION__, __LINE__);
++              /* Whole channel control block data structure */
++              ccb_p = MALLOC(CH_NUM * sizeof(channelControlBlock));
++              if (ccb_p == NULL) {
++                      iapi_errno = IAPI_ERR_CCB_ALLOC_FAILED |
++                              IAPI_ERR_CH_AVAILABLE | channelNumber;
++                      iapi_ReleaseChannel(channelNumber);
++                      return -iapi_errno;
++              }
++              DBG(0, "%s: ccb allocated at %p..%p\n", __FUNCTION__, ccb_p,
++                      (unsigned char *)(ccb_p + CH_NUM) - 1);
++
++              /* Zero-out the CCB structures array just allocated */
++              iapi_memset(ccb_p, 0x00, CH_NUM * sizeof(channelControlBlock));
++              for (i = 0; i < CH_NUM; i++) {
++                      ccb_p[i].baseBDptr = DMA_ADDR_INVALID;
++                      ccb_p[i].currentBDptr = DMA_ADDR_INVALID;
++              }
++              /* Save the address of the CCB structures array */
++              iapi_CCBHead = ccb_p;
++
++              cd_p->ccb_ptr = ccb_p;
++              ccb_p->channelDescriptor = cd_p;
++              DBG(0, "%s: channelDescriptor %p=%p\n", __FUNCTION__,
++                      &ccb_p->channelDescriptor, cd_p);
++#ifdef MCU
++              /* finish initializations */
++              iapi_InitChannelTables();
++#endif /* MCU */
++              /* Channel 0 is dedicated to communications with SDMA */
++              cd_p->ownership = ((DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
++                              (OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
++                              (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
++              cd_p->bufferDescNumber = 1;
++      }
++
++      DBG(0, "%s@%d: \n", __FUNCTION__, __LINE__);
++      /*
++       * 2. Check channel control block
++       */
++      ccb_p = cd_p->ccb_ptr;
++      if (ccb_p == NULL) {
++              iapi_errno = IAPI_ERR_NO_CCB_DEFINED |
++                      IAPI_ERR_CH_AVAILABLE |
++                      channelNumber;
++              iapi_ReleaseChannel(channelNumber);
++              return -iapi_errno;
++      }
++
++      DBG(0, "%s@%d: ccb_p=%p\n", __FUNCTION__, __LINE__, ccb_p);
++      /* Control block & Descriptor associated with the channel being worked on */
++      local_ccb_p = &ccb_p[channelNumber];
++      local_cd_p  =  ccb_p[channelNumber].channelDescriptor;
++
++      DBG(0, "%s@%d: local_ccb_p[%d]=%p local_cd_p[%p]=%p\n", __FUNCTION__, __LINE__,
++              channelNumber, local_ccb_p,
++              &ccb_p[channelNumber].channelDescriptor, local_cd_p);
++      /* If the channel is not initialized, initialize it with the default value */
++      if (local_cd_p == NULL) {
++              int result = iapi_AllocChannelDesc(&local_cd_p, channelNumber);
++              if (result!= IAPI_SUCCESS) {
++                      iapi_ReleaseChannel(channelNumber);
++                      return result; //is already negated from iapi_AllocChannelDesc
++              }
++
++              local_cd_p->ccb_ptr = (struct iapi_channelControlBlock *)local_ccb_p;
++              local_ccb_p->channelDescriptor = local_cd_p;
++      }
++
++      DBG(0, "%s@%d: \n", __FUNCTION__, __LINE__);
++      /*
++       * 3. If buffer descriptor already allocated, exit with iapi_errno filled
++       */
++      if (local_ccb_p->baseBDptr != DMA_ADDR_INVALID) {
++              int result = IAPI_ERR_BD_ALLOCATED;
++
++              bd_p = iapi_Phys2Virt(local_ccb_p->baseBDptr);
++              if (bd_p == NULL) {
++                      iapi_errno = IAPI_ERR_BD_ALLOCATION;
++                      return -iapi_errno;
++              }
++              DBG(0, "%s: bd_p=%p phys=%08x\n", __FUNCTION__, bd_p, local_ccb_p->baseBDptr);
++              for (index = 1; index < local_cd_p->bufferDescNumber; index++) {
++                      if ((bd_p->mode.status & BD_DONE) == BD_DONE) {
++                              /* complete the lowest bits with the number of 'D' bits set */
++                              result++;
++                      }
++                      bd_p++;
++              }
++              iapi_errno = result;
++              iapi_ReleaseChannel(channelNumber);
++              return -iapi_errno;
++      }
++
++      DBG(0, "%s@%d: \n", __FUNCTION__, __LINE__);
++      /*
++       * 4. Buffer Descriptors allocation
++       */
++      iapi_InitializeMemory(local_ccb_p);
++
++#ifdef MCU
++      /*
++       * 5. Channel's configuration properties (mcu side only)
++       */
++      iapi_ChannelConfig(channelNumber,
++                      (local_cd_p->ownership >> CH_OWNSHP_OFFSET_EVT) & 1,
++                      (local_cd_p->ownership >> CH_OWNSHP_OFFSET_MCU) & 1,
++                      (local_cd_p->ownership >> CH_OWNSHP_OFFSET_DSP) & 1);
++#endif /* MCU */
++
++      DBG(0, "%s@%d: \n", __FUNCTION__, __LINE__);
++      /* Setting interrupt handling */
++      iapi_ChangeCallbackISR(local_cd_p, local_cd_p->callbackISR_ptr);
++
++      DBG(0, "%s@%d: \n", __FUNCTION__, __LINE__);
++      /* Call initialization fn for polling synch on this channel */
++      INIT_SLEEP(channelNumber);
++
++      DBG(0, "%s@%d: \n", __FUNCTION__, __LINE__);
++      /* No user arg pointer yet */
++      userArgTable[cd_p->channelNumber] = NULL;
++
++      DBG(0, "%s@%d: \n", __FUNCTION__, __LINE__);
++      /*
++       * 6. read/write direction => enable/disable channel
++       */
++#ifdef MCU
++      DBG(0, "%s@%d: \n", __FUNCTION__, __LINE__);
++#if 1
++      __raw_writel(1, SDMA_CHNPRI(channelNumber));
++#else
++      channelPriorityMatx = &SDMA_CHNPRI_0;
++      channelPriorityMatx[channelNumber] = 1;
++#endif
++#endif /* MCU */
++
++      DBG(0, "%s@%d: \n", __FUNCTION__, __LINE__);
++      local_ccb_p->status.openedInit = TRUE;
++      iapi_ReleaseChannel(channelNumber);
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/** Attempts to read nbyte from the data buffer descriptor associated with the
++ * channel channelNumber, into the user's data buffer pointed to by buf.
++ *
++ * <b>Algorithm:</b>\n
++ * - Check data structures are properly initialized:
++ *   - Channel descriptor validity
++ *   - Control block & Descriptor associated with the channel being worked on
++ *   - Check initialization has been done for trusted channels
++ *   - If transfer data size is used, check validity of combination transfer
++ *     size/requested bytes
++ * - Set the 'D' done bits on all buffer descriptors
++ * - Starting of the channel
++ * - Synchronization mechanism handling:
++ *   - for callback: just exit function
++ *   - for polling: call the synchronization function then read data from
++ *     buffer until either nbyte parameter is reached or all buffer descriptors
++ *     have been processed.
++ *
++ * <b>Notes:</b>\n
++ *   1) Virtual DMA SDMA channels are unidirectional, an iapi_Read authorized
++ *       on a channel means that we are expecting to receive from the SDMA. The
++ *       meaning of an interrupt received from the SDMA is therefore that the
++ *       data has been copied from the SDMA to the host's data buffers and is
++ *       already passed on upper layers of the application.\n
++ *
++ * @param *cd_p chanenl descriptor for the channel to read from
++ * @param *buf buffer to receive the data
++ * @param nbyte number of bytes to read from channel
++ *
++ * @return
++ *       - number of bytes read
++ *       - -iapi_errno : in case of failure return negated value of iapi_errno
++ */
++int
++iapi_Read(channelDescriptor *cd_p, void *buf, unsigned short nbyte)
++{
++      int index;
++      int readBytes;
++      int toRead;
++      unsigned int copyFinished;
++      unsigned int bufsize;
++      bufferDescriptor *bd_p;
++      channelControlBlock *ccb_p;
++      unsigned char *local_buf;
++      unsigned char chNum;
++      unsigned char div;
++
++      iapi_errno = IAPI_ERR_NO_ERROR;
++
++      /*
++       * 1. Check data structures are properly initialized
++       */
++      /* Channel descriptor validity */
++      if (cd_p == NULL) {
++              iapi_errno = IAPI_ERR_CD_UNINITIALIZED;
++              return -iapi_errno;
++      }
++
++      /* Channel control block validity */
++      if (cd_p->ccb_ptr == NULL) {
++              iapi_errno = IAPI_ERR_CCB_UNINITIALIZED;
++              return -iapi_errno;
++      }
++
++      /* Control block & Descriptor associated with the channel being worked on */
++      chNum = cd_p->channelNumber;
++      ccb_p = cd_p->ccb_ptr;
++
++      /* Try to aquire channel */
++      if (iapi_GetChannel(chNum) != 0) {
++              iapi_errno = IAPI_ERR_CH_IN_USE | chNum;
++              return -iapi_errno;
++      }
++
++      /* Check if channel is already opened/initialized */
++      if (ccb_p->status.openedInit == FALSE) {
++              iapi_errno = IAPI_ERR_CHANNEL_UNINITIALIZED |
++                      IAPI_ERR_CH_AVAILABLE | chNum;
++              iapi_ReleaseChannel(chNum);
++              return -iapi_errno;
++      }
++
++      /* Buffer descriptor validity */
++      bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++      if (bd_p == NULL) {
++              iapi_errno = IAPI_ERR_BD_UNINITIALIZED |
++                      IAPI_ERR_CH_AVAILABLE | chNum;
++              iapi_ReleaseChannel(chNum);
++              return -iapi_errno;
++      }
++
++
++      /* Check initialization has been done for trusted channels */
++      if (cd_p->trust == TRUE) {
++              bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++              for (index = 0; index < cd_p->bufferDescNumber; index++) {
++                      if ((bd_p->bufferAddr == DMA_ADDR_INVALID) ||
++                              (bd_p->mode.count == 0)) {
++                              iapi_errno = IAPI_ERR_BD_UNINITIALIZED |
++                                      IAPI_ERR_CH_AVAILABLE | chNum;
++                              iapi_ReleaseChannel(chNum);
++                              return -iapi_errno;
++                      }
++                      bd_p++;
++              }
++      }
++
++      bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++      /* If transfer data size is used, check that the required read length is
++       * divisible by transfer data size expressed in bytes
++       */
++      if (cd_p->useDataSize) {
++              /* Check for divisibility only if data size different then 8bit */
++              if (cd_p->dataSize != TRANSFER_8BIT) {
++                      switch(cd_p->dataSize) {
++                      case TRANSFER_32BIT:
++                              div = 4;
++                              break;
++                      case TRANSFER_16BIT:
++                              div = 2;
++                              break;
++                      case TRANSFER_24BIT:
++                              div = 3;
++                              break;
++                              /* we should not get to default */
++                      default:
++                              iapi_errno = IAPI_ERR_INVALID_PARAMETER | chNum;
++                              iapi_ReleaseChannel(chNum);
++                              return -iapi_errno;
++                      }
++                      /* check the total number of bytes requested */
++                      if ((nbyte % div) != 0) {
++                              iapi_errno = IAPI_ERR_INVALID_PARAMETER | chNum;
++                              iapi_ReleaseChannel(chNum);
++                              return -iapi_errno;
++                      }
++                      /* now check the length of every BD */
++                      for (index = 0; index < cd_p->bufferDescNumber; index++) {
++                              if ((bd_p->mode.count % div) != 0) {
++                                      iapi_errno = IAPI_ERR_INVALID_PARAMETER | chNum;
++                                      iapi_ReleaseChannel(chNum);
++                                      return -iapi_errno;
++                              }
++                              bd_p++;
++                      }
++              }
++      }
++
++      /*
++       * 2. Set the 'D' done bits on all buffer descriptors
++       */
++      bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++      for (index = 0; index < cd_p->bufferDescNumber; index++) {
++              bd_p->mode.status |= BD_DONE;
++              bd_p++;
++      }
++
++      /*
++       * 3. Starting of the channel
++       */
++      iapi_lowStartChannel(chNum);
++      ccb_p->status.execute = TRUE;
++      readBytes = 0;
++
++      /*
++       * 4. Synchronization mechanism handling
++       */
++      if (cd_p->callbackSynch == DEFAULT_POLL) {
++              iapi_SynchChannel(chNum);
++
++              bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++              toRead = nbyte;
++              copyFinished = FALSE;
++              local_buf = buf;
++
++              /*
++               * Check the 'RROR' bit on all buffer descriptors, set error number
++               *    and return IAPI_FAILURE if set.
++               */
++              for (index = 0; index < cd_p->bufferDescNumber; index++) {
++                      if (bd_p->mode.status & BD_RROR) {
++                              iapi_errno = IAPI_ERR_RROR_BIT_READ | chNum;
++                              iapi_ReleaseChannel(chNum);
++                              return -iapi_errno;
++                      }
++                      bd_p++;
++              }
++
++
++              /*
++               * 5. Read loop
++               */
++
++              bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++              while (!copyFinished) {
++                      if (!(bd_p->mode.status & BD_DONE)) {
++                              if (cd_p->trust == FALSE) {
++                                      bufsize = cd_p->bufferSize;
++                              } else {
++                                      bufsize = bd_p->mode.count;
++                              }
++                              /* if L bit is set, read only "count" bytes and exit the loop */
++                              if (bd_p->mode.status & BD_LAST) {
++                                      bufsize = bd_p->mode.count;
++                                      copyFinished = TRUE;
++                              }
++                              if (toRead > bufsize) {
++                                      if (cd_p->trust == FALSE) {
++                                              iapi_memcpy(local_buf, iapi_Phys2Virt(bd_p->bufferAddr), bufsize);
++                                              local_buf += bufsize;
++                                      }
++                                      readBytes += bufsize;
++                                      toRead -= bufsize;
++                                      /* advance bd_p only if bit L is not set. The loop will exit anyway. */
++                                      if (!(bd_p->mode.status & BD_LAST)) {
++                                              if (bd_p->mode.status & BD_WRAP) {
++                                                      bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++                                              } else if ((iapi_Phys2Virt(ccb_p->baseBDptr +
++                                                                                      (cd_p->bufferDescNumber - 1) *
++                                                                                      sizeof(bufferDescriptor))) != bd_p) {
++                                                      bd_p++;
++                                              } else {
++                                                      /* finished here : end of buffer descriptors */
++                                                      copyFinished = TRUE;
++                                              }
++                                      }
++                              } else {
++                                      if (cd_p->trust == FALSE) {
++                                              iapi_memcpy(local_buf, iapi_Phys2Virt(bd_p->bufferAddr), toRead);
++                                              local_buf += toRead;
++                                      }
++                                      readBytes += toRead;
++                                      toRead = 0;
++                                      /* finished successfully : readBytes = nbytes */
++                                      copyFinished = TRUE;
++                              }
++                      } else {
++                              /* finished here : buffer not already done */
++                              copyFinished = TRUE;
++                      }
++              }
++              iapi_ReleaseChannel(chNum);
++      }
++
++      /*
++       *If synchronization type is callback, the user of I.API must
++       *release the channel
++       */
++      return readBytes;
++}
++
++/****************************************************************************
++ * Attempts to write nbyte from the buffer pointed to by buf to the channel
++ * data buffers associated with the opened channel number channelNumber
++ *
++ * <b>Algorithm:</b>\n
++ *
++ * - Check data structures are properly initialized:
++ *   - Channel descriptor validity
++ *   - Channel control block validity
++ *   - Buffer descriptor validity
++ *   - If transfer data size is used, check validity of combination transfer
++ *     size/requested bytes
++ * - Write loop\n
++ *  Write occurs in the buffer acceded form buffer descriptor and continues
++ *  to the "next" buffer which can be:\n
++ *    -# the last BD of the ring so re-start from beginning\n
++ *    -# the last BD  of the BD array but no ring so finish\n
++ *    -# (general case) the next BD in the BD array\n
++ *  And copy continues until data fit in the current buffer or the nbyte
++ *  parameter is reached.
++ * - Starting of the channel
++ *
++ * <b>Notes:</b>\n
++ *   1) Virtual DMA SDMA channels are unidirectionnal, an iapi_Write authorized
++ *      on a channel means that we are expecting to send to the SDMA. The
++ *      meaning of an interrupt received from the SDMA is therfore that the
++ *      data has been delivered to the SDMA.
++ *
++ * @param *cd_p chanenl descriptor for the channel to write to
++ * @param *buf buffer with data to be written
++ * @param nbyte number of bytes to write to channel
++ *
++ * @return
++ *       - number of bytes written
++ *       - -iapi_errno if failure
++ */
++int
++iapi_Write(channelDescriptor *cd_p, void *buf, unsigned short nbyte)
++{
++      int writtenBytes = 0;
++      unsigned int toWrite;
++      unsigned int copyFinished;
++      unsigned int buffsize;
++      unsigned int index = 0;
++      bufferDescriptor *bd_p;
++      channelControlBlock *ccb_p;
++      unsigned char *local_buf;
++      unsigned char chNum;
++      unsigned char div;
++
++      iapi_errno = IAPI_ERR_NO_ERROR;
++
++      /*
++       * 1. Check data structures are properly initialized
++       */
++      /* Channel descriptor validity */
++      if (cd_p == NULL) {
++              iapi_errno = IAPI_ERR_CD_UNINITIALIZED;
++              return -iapi_errno;
++      }
++
++      /* Channel control block validity */
++      if (cd_p->ccb_ptr == NULL) {
++              iapi_errno = IAPI_ERR_CCB_UNINITIALIZED;
++              return -iapi_errno;
++      }
++
++      /* Control block & Descriptpor associated with the channel being worked on */
++      chNum = cd_p->channelNumber;
++      ccb_p = cd_p->ccb_ptr;
++
++      /* Try to aquire channel */
++      if (iapi_GetChannel(chNum) != 0) {
++              iapi_errno = IAPI_ERR_CH_IN_USE | chNum;
++              return -iapi_errno;
++      }
++
++      /* Buffer descriptor validity */
++      bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++      if (bd_p == NULL) {
++              iapi_errno = IAPI_ERR_BD_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE | chNum;
++              iapi_ReleaseChannel(chNum);
++              return -iapi_errno;
++      }
++
++      /* Check initialization has been done for trusted channels */
++      if (cd_p->trust == TRUE) {
++              bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++              for (index = 0; index < cd_p->bufferDescNumber; index++) {
++                      if ((bd_p->bufferAddr == DMA_ADDR_INVALID) || (bd_p->mode.count == 0)) {
++                              iapi_errno = IAPI_ERR_BD_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE | chNum;
++                              iapi_ReleaseChannel(chNum);
++                              return -iapi_errno;
++                      }
++                      bd_p++;
++              }
++      }
++
++
++      bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++      /* If transfer data size is used, check that the required write length is
++       * divisible by transfer data size expressed in bytes
++       */
++      if (cd_p->useDataSize) {
++              /* Check for divisibility only if data size different then 8bit */
++              if (cd_p->dataSize != TRANSFER_8BIT) {
++                      switch(cd_p->dataSize) {
++                      case TRANSFER_32BIT:
++                              div = 4;
++                              break;
++                      case TRANSFER_16BIT:
++                              div = 2;
++                              break;
++                      case TRANSFER_24BIT:
++                              div = 3;
++                              break;
++                      default:
++                              iapi_errno = IAPI_ERR_INVALID_PARAMETER | chNum;
++                              iapi_ReleaseChannel(chNum);
++                              return -iapi_errno;
++                      }
++                      /* check the total number of bytes requested */
++                      if ((nbyte % div) != 0) {
++                              iapi_errno = IAPI_ERR_INVALID_PARAMETER | chNum;
++                              iapi_ReleaseChannel(chNum);
++                              return -iapi_errno;
++                      }
++                      /* now check the length of every BD */
++                      for (index = 0; index < cd_p->bufferDescNumber; index++) {
++                              if ((bd_p->mode.count % div) != 0) {
++                                      iapi_errno = IAPI_ERR_INVALID_PARAMETER | chNum;
++                                      iapi_ReleaseChannel(chNum);
++                                      return -iapi_errno;
++                              }
++                              bd_p++;
++                      }
++              }
++      }
++
++      /*
++       * 2. Write loop
++       */
++      local_buf = buf;
++      toWrite = nbyte;
++      copyFinished = FALSE;
++      bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++
++      while (!copyFinished) {
++              /* variable buffsize contains the number of bytes that the SDMA
++               * will transfer at each pass of the while loop */
++              /* in NON trusted mode, buffsize is copied from Channel
++               * descriptor bufferSize (same size for all transfers) */
++
++              if (cd_p->trust == FALSE) {
++                      buffsize = cd_p->bufferSize;
++              } else {
++                      /* in TRUSTED mode, it's up to the user to specify the size of each buffer thru an IoCtl call */
++                      /* This IoCtl has directly modified the bd_p->mode.count     */
++                      /* therefore, buffersize is copied from the bd_p->mode.count */
++                      buffsize = bd_p->mode.count;
++              }
++              DBG(-1, "%s: nbyte=%u towrite=%u buffsize=%u\n", __FUNCTION__,
++                      nbyte, toWrite, buffsize);
++
++              /* in any mode (trusted or non trusted), the transfer size must be overridden by */
++              /* "toWrite" when there is less remaining bytes to transfer than the current buffer size */
++              if (toWrite < buffsize) {
++                      buffsize = toWrite;
++              }
++
++              if (!(bd_p->mode.status & BD_DONE)) {
++                      /* More data to write than a single buffer can contain */
++                      if (cd_p->trust == FALSE) {
++                              iapi_memcpy(iapi_Phys2Virt(bd_p->bufferAddr),
++                                      local_buf, buffsize);
++                              local_buf += buffsize;
++                      }
++
++                      /* update the BD count that will be used by the SDMA to transfer the proper nb of bytes */
++                      bd_p->mode.count = buffsize;
++
++                      bd_p->mode.status |= BD_DONE;
++                      writtenBytes += buffsize;
++                      toWrite -= buffsize;
++                      /* Prepares access to the "next" buffer */
++                      if (toWrite == 0) {
++                              /* - case 1 - finished successfully : writtenBytes = nbytes */
++                              copyFinished = TRUE;
++                      } else if ((bd_p->mode.status & BD_WRAP)) {
++                              /* - case 2 - Last BD and WRAP bit set so re-start from beginning */
++                              bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++                      } else if ((iapi_Phys2Virt(
++                                              ccb_p->baseBDptr +
++                                              (cd_p->bufferDescNumber - 1) *
++                                              sizeof(bufferDescriptor))) ==
++                              bd_p) {
++                              /* - case 3 - Last BD of the BD but not ring */
++                              copyFinished = TRUE;
++                      } else {
++                              /* - case 4 - general : next BD in the BD array */
++                              bd_p++;
++                      }
++              } else {
++                      /* finished here : buffer not already done */
++                      copyFinished = TRUE;
++              }
++      }
++
++      ccb_p->currentBDptr = ccb_p->baseBDptr;
++
++      /*
++       * 3. Starting of the channel
++       */
++      iapi_lowStartChannel(chNum);
++      ccb_p->status.execute = TRUE;
++
++      if (cd_p->callbackSynch == DEFAULT_POLL) {
++              iapi_SynchChannel(chNum);
++              /*
++               * Check the 'RROR' bit on all buffer descriptors, set error number
++               *    and return IAPI_FAILURE if set.
++               */
++              bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++              for (index = 0; index < cd_p->bufferDescNumber; index++) {
++                      if (bd_p->mode.status & BD_RROR) {
++                              iapi_errno = IAPI_ERR_RROR_BIT_WRITE | chNum;
++                              iapi_ReleaseChannel(chNum);
++                              return -iapi_errno;
++                      }
++                      bd_p++;
++              }
++              iapi_ReleaseChannel(chNum);
++      }
++
++      /*
++       * If synchronization type is callback, the user of I.API must
++       * release the channel
++       */
++      return writtenBytes;
++}
++
++/* ***************************************************************************/
++/* This function is used to receive data from the SDMA.
++ *
++ * <b>Algorithm:</b>\n
++ *
++ * The data control structure would be copied to IPCv1 complied Buffer
++ * Descriptor Array. This array shall be allocated from non cacheable memory.
++ * It would then provide this buffer descriptor array as an input to SDMA using
++ * channel control block and then configure the Host Enable (HE) or
++ * DSP enable (DE) bit of SDMA for the channel used for this transfer depending
++ * on the source.
++ *
++ * <b>Notes:</b>\n
++ * Virtual DMA channels are unidirectional, an iapi_Write_ipcv2 authorized
++ * on a channel means that source processor is expecting to send to the destination
++ * processor. The meaning of an interrupt received from the SDMA notifies that the
++ * data has been delivered to the destination processor.
++ *
++ * @param *cd_p chanenl descriptor for the channel to receive from
++ * @param *data_control_struct_ipcv2
++
++ *   Data Control structure:
++ *   -------------------------
++ *   | Data Node Descriptor 1|
++ *   -------------------------
++ *   | Data Node Descriptor 2|
++ *   -------------------------
++ *   |           :           |
++ *   |           :           |
++ *   -------------------------
++ *   |Data Node Descriptor n |
++ *   -------------------------
++ *
++ *   Data Node Descriptor (Buffer Descriptor):
++ *------------------------------------------------------------------------------
++ *| 31        30      29      28      27      26      25      24      23      22      21      20      19      18      17      16      15       Â…    0|
++ *------------------------------------------------------------------------------
++ *| L E       D       R       R       R       R       R       |<---- Reserved          ---->  |<- Length-> |
++ *------------------------------------------------------------------------------
++ *| <---------------------------- Data Ptr ----------------------------------->|
++ *------------------------------------------------------------------------------
++ *
++ * L bit (LAST): If set, means that this buffer of data is the last buffer of the frame
++ * E bit (END): If set, we reached the end of the buffers passed to the function
++ * D bit (DONE): Only valid on the read callback. When set, means that the buffer has been
++ * filled by the SDMA.
++ * Length: Length of data pointed by this node in bytes
++ * Data Ptr: Pointer to the data pointed to by this node.
++ * The Function Shall not be called for the same channel unless the Read callback has been
++ * received for channel for which it has been called already.
++ *
++ * @return
++ *       - IAPI_SUCCESS on success, IAPI_ERROR otherwise
++ *
++ *- -iapi_errno if failure
++ */
++
++int iapi_Read_ipcv2(channelDescriptor *cd_p, void *data_control_struct_ipcv2)
++{
++      channelControlBlock *ccb_p;
++/* The Parameters passed are considered to be validated by the upper layers */
++      bufferDescriptor_ipcv1_v2 *bd_ipcv2_p;
++      dataNodeDescriptor    *dnd_p = data_control_struct_ipcv2;
++
++      ccb_p = cd_p->ccb_ptr;
++      iapi_errno = IAPI_ERR_NO_ERROR;
++
++      if (ccb_p->baseBDptr == DMA_ADDR_INVALID) {
++              iapi_errno = IAPI_ERR_BD_UNINITIALIZED;
++              return -iapi_errno;
++      }
++
++      ccb_p->currentBDptr = ccb_p->baseBDptr;
++
++      /* Copy the data Node descriptor information to new BDs */
++      bd_ipcv2_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++
++      while (1) {
++              bd_ipcv2_p->bufferAddr = dnd_p->bufferAddr;
++              bd_ipcv2_p->mode.count = dnd_p->mode.count;
++#ifdef MCU
++              bd_ipcv2_p->mode.endianness = 1;
++#endif
++#ifdef DSP
++              bd_ipcv2_p->mode.endianness = 0;
++#endif
++
++              bd_ipcv2_p->mode.status = dnd_2_bd_status[dnd_p->mode.status & GET_LED_MASK];
++
++              if ((dnd_p->mode.status & DND_END_OF_XFER) != 0) {
++                      /* Break the loop at End of Transfer */
++                      break;
++              }
++              bd_ipcv2_p++;
++              dnd_p++;
++      }
++      /*
++       * Store the buffer address
++       */
++      dnd_read_control_struct[cd_p->channelNumber] = data_control_struct_ipcv2;
++      /*
++       *  Register the Call Back
++       */
++
++      iapi_AttachCallbackISR(cd_p, iapi_read_ipcv2_callback);
++
++      /*
++       *  Starting of the channel
++       */
++      iapi_lowStartChannel(cd_p->channelNumber);
++      ccb_p->status.execute = TRUE;
++
++      return IAPI_SUCCESS;
++}
++
++
++/* ***************************************************************************/
++/*
++ * The function is used send a group of buffers to SDMA.
++ * <b>Algorithm:</b>\n
++ *
++ * The data control structure would be copied to IPCv1 complied Buffer
++ * Descriptor Array. This array shall be allocated from non cacheable memory.
++ * It would then provide this buffer descriptor array as an input to SDMA using
++ * channel control block and then configure the Host Enable (HE) or
++ * DSP enable (DE) bit of SDMA for the channel used for this transfer depending
++ * on the source.
++ * The Function Shall not be called for the same channel unless the Read callback has been
++ * received for channel for which it has been called already.
++ *
++ * <b>Notes:</b>\n
++ * Virtual DMA channels are unidirectional, an iapi_Write_ipcv2 authorized
++ * on a channel means that source processor is expecting to send to the destination
++ * processor. The meaning of an interrupt received from the SDMA notifies that the
++ * data has been delivered to the destination processor.
++ *
++ * @param *cd_p chanenl descriptor for the channel to write to
++ * @param *data_control_struct_ipcv2
++
++ *   Data Control structure:
++ *   -------------------------
++ *   | Data Node Descriptor 1|
++ *   -------------------------
++ *   | Data Node Descriptor 2|
++ *   -------------------------
++ *   |           :           |
++ *   |           :           |
++ *   -------------------------
++ *   |Data Node Descriptor n |
++ *   -------------------------
++ *
++ *   Data Node Descriptor (Buffer Descriptor):
++ *------------------------------------------------------------------------------
++ *| 31        30      29      28      27      26      25      24      23      22      21      20      19      18      17      16      15       Â…    0|
++ *------------------------------------------------------------------------------
++ *| L E       D       R       R       R       R       R       |<---- Reserved          ---->  |<- Length-> |
++ *------------------------------------------------------------------------------
++ *| <---------------------------- Data Ptr ----------------------------------->|
++ *------------------------------------------------------------------------------
++ *
++ * L bit (LAST): If set, means that this buffer of data is the last buffer of the frame
++ * E bit (END): If set, we reached the end of the buffers passed to the function
++ * D bit (DONE): Only valid on the read callback. When set, means that the buffer has been
++ * filled by the SDMA.
++ * Length: Length of data pointed by this node in bytes
++ * Data Ptr: Pointer to the data pointed to by this node.
++ *
++ *
++ * @return
++ *       - iapi sucess on success.
++ *       - -iapi_errno if failure
++ */
++
++int iapi_Write_ipcv2(channelDescriptor *cd_p, void *data_control_struct_ipcv2)
++{
++      channelControlBlock *ccb_p;
++/* The Parameters passed are considered to be validated by the upper layers */
++      bufferDescriptor_ipcv1_v2 *bd_ipcv2_p;
++      dataNodeDescriptor    *dnd_p = data_control_struct_ipcv2;
++      ccb_p = cd_p->ccb_ptr;
++      iapi_errno = IAPI_ERR_NO_ERROR;
++
++      if (ccb_p->baseBDptr == DMA_ADDR_INVALID) {
++              iapi_errno = IAPI_ERR_BD_UNINITIALIZED;
++              return -iapi_errno;
++      }
++
++      ccb_p->currentBDptr = ccb_p->baseBDptr;
++
++      bd_ipcv2_p = iapi_Phys2Virt(ccb_p->currentBDptr);
++      /* Copy the data Node descriptor information to new BDs */
++      while (1) {
++              bd_ipcv2_p->bufferAddr = dnd_p->bufferAddr;
++              bd_ipcv2_p->mode.count = dnd_p->mode.count;
++
++#ifdef MCU
++              bd_ipcv2_p->mode.endianness = 1;
++#endif
++#ifdef DSP
++              bd_ipcv2_p->mode.endianness = 0;
++#endif
++
++              bd_ipcv2_p->mode.status = dnd_2_bd_status[dnd_p->mode.status & GET_LED_MASK];
++
++              if ((dnd_p->mode.status & DND_END_OF_XFER) != 0) {
++                      /* Break the loop at End of Transfer */
++                      break;
++              }
++              bd_ipcv2_p++;
++              dnd_p++;
++      }
++
++      /*
++       *  Starting of the channel
++       */
++      iapi_lowStartChannel(cd_p->channelNumber);
++      ccb_p->status.execute = TRUE;
++
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/** Call back ISR for the IPCv2 Receive.
++ *
++ * <b>Algorithm:</b>\n
++ *    - This would copy back the informationfrom IPCv1 BD to IPCv2 BD on
++ * the receiving processor
++ *
++ * @return
++ *     - void
++ */
++
++static void iapi_read_ipcv2_callback(struct iapi_channelDescriptor *cd_p, void *data)
++{
++      dataNodeDescriptor    *dnd_p = dnd_read_control_struct[cd_p->channelNumber];//cd_p->ccb_ptr->channelDNDBuffer;
++      bufferDescriptor_ipcv1_v2 *bd_ipcv2_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++      int index;
++
++      for (index = MAX_BD_NUM - 1; index >= 0; index--) {
++              dnd_p->mode.status = 0;
++              dnd_p->mode.count = bd_ipcv2_p->mode.count;
++
++              dnd_p->mode.status |= bd_ipcv2_p->mode.status & BD_DONE ? 0x00 : DND_DONE;
++              dnd_p->mode.status |= bd_ipcv2_p->mode.status & BD_IPCV2_END_OF_FRAME ? DND_END_OF_FRAME : 0x00;
++              dnd_p->mode.status |= bd_ipcv2_p->mode.status & BD_LAST ? DND_END_OF_XFER : 0x00;
++              cd_p->ccb_ptr->currentBDptr = iapi_Virt2Phys(bd_ipcv2_p);
++
++              if ((bd_ipcv2_p->mode.status & BD_LAST) ||
++                      !(bd_ipcv2_p->mode.status & BD_CONT))
++                      break;
++              dnd_p++;
++              bd_ipcv2_p++;
++      }
++
++      /* Call back the Original ISR */
++      cd_p->callbackISR_ptr(cd_p, data);
++}
++
++/* ***************************************************************************/
++/**Terminates a channel.
++ *
++ * <b>Algorithm:</b>\n
++ *   - Check input parameters ans data structures
++ *   - Check that all buffes have been processed (test all 'D' bits)
++ *   - Stop the channel execution
++ *   - Free alocated memory structures
++ *   - Re-instantiate default interrupt handling
++ *
++ * @param *cd_p chanenl descriptor for the channel to close
++ *
++ * @return
++ *     - IAPI_SUCCESS : OK
++ *     - -iapi_errno : close failed
++ */
++int
++iapi_Close(channelDescriptor *cd_p)
++{
++      int index = 0;
++      unsigned char chNum;
++      channelControlBlock *ccb_p;
++
++      /*
++       * 1. Check input parameters ans data structures
++       */
++      if (cd_p != NULL) {
++              if (cd_p->ccb_ptr != NULL) {
++                      chNum = cd_p->channelNumber;
++                      ccb_p = cd_p->ccb_ptr;
++              } else {
++                      iapi_errno = IAPI_ERR_NO_CCB_DEFINED | IAPI_ERR_CH_AVAILABLE;
++                      return -iapi_errno;
++              }
++      } else {
++              iapi_errno = IAPI_ERR_CD_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE;
++              return -iapi_errno;
++      }
++      /* Try to aquire channel */
++      if (iapi_GetChannel(chNum) != 0) {
++              iapi_errno = IAPI_ERR_CH_IN_USE | chNum;
++              return -iapi_errno;
++      }
++
++      /*
++       * 2. Check that all buffes have been processed (test all 'D' bits),
++       * only if the forceClose bit in channel descriptor is set to FALSE
++       */
++      if (ccb_p->baseBDptr != DMA_ADDR_INVALID) {
++              bufferDescriptor *bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++
++              if (bd_p == NULL) {
++                      iapi_errno = IAPI_ERR_BD_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE | chNum;
++                      return -iapi_errno;
++              }
++              if (cd_p->forceClose == FALSE) {
++                      for (index = cd_p->bufferDescNumber; index > 0; index--) {
++                              if (bd_p->mode.status & BD_DONE) {
++                                      iapi_errno = IAPI_ERR_CLOSE | IAPI_ERR_CH_AVAILABLE | chNum;
++                                      iapi_ReleaseChannel(chNum);
++                                      return -iapi_errno;
++                              }
++                              bd_p++;
++                      }
++              } else {
++                      /* if the closing is forced, mark channel unused and
++                       * set BD ownership to processor
++                       */
++                      ccb_p->status.execute = FALSE;
++                      for (index = cd_p->bufferDescNumber; index > 0; index--) {
++                              bd_p->mode.status &= ~BD_DONE;
++                              bd_p++;
++                      }
++              }
++      }
++
++      /*
++       * 3. Stop the channel execution
++       */
++      iapi_lowStopChannel(chNum);
++
++      /*
++       * 4. Free alocated memory structures
++       */
++      if (cd_p->trust == FALSE && ccb_p->baseBDptr != DMA_ADDR_INVALID) {
++              bufferDescriptor *bd_p = iapi_Phys2Virt(ccb_p->baseBDptr);
++
++              for (index = cd_p->bufferDescNumber; index > 0; index--) {
++                      FREE(iapi_Phys2Virt(bd_p->bufferAddr));
++                      bd_p++;
++              }
++      }
++
++      /*
++       * 5. Re-instantiate default interrupt handling
++       */
++      iapi_DetachCallbackISR(cd_p);
++      if (ccb_p->baseBDptr != DMA_ADDR_INVALID) {
++              FREE(iapi_Phys2Virt(ccb_p->baseBDptr));
++              ccb_p->baseBDptr = DMA_ADDR_INVALID;
++              ccb_p->currentBDptr = DMA_ADDR_INVALID;
++      }
++      FREE(cd_p);
++      ccb_p->channelDescriptor = NULL;
++      ccb_p->status.openedInit = FALSE;
++
++      iapi_ReleaseChannel(chNum);
++
++      return IAPI_SUCCESS;
++}
++
++static inline int iapi_clr_status(channelDescriptor *cd_p, unsigned long param,
++                              unsigned long mask)
++{
++      int retvalue = IAPI_SUCCESS;
++      bufferDescriptor *bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++
++      if (param == SET_BIT_ALL) {
++              int j;
++
++              for (j = 0; j < cd_p->bufferDescNumber; j++) {
++                      bde_p->mode.status &= ~mask;
++                      bde_p++;
++              }
++      } else if (param < cd_p->bufferDescNumber) {
++              bde_p[param].mode.status &= ~mask;
++      } else {
++              retvalue = IAPI_FAILURE;
++      }
++      return retvalue;
++}
++
++static inline int iapi_set_status(channelDescriptor *cd_p, unsigned long param,
++                              unsigned long mask)
++{
++      int retvalue = IAPI_SUCCESS;
++      bufferDescriptor *bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++
++      if (param == SET_BIT_ALL) {
++              int j;
++
++              for (j = 0; j < cd_p->bufferDescNumber; j++) {
++                      bde_p->mode.status |= mask;
++                      bde_p++;
++              }
++      } else if (param < cd_p->bufferDescNumber) {
++              bde_p[param].mode.status |= mask;
++      } else {
++              retvalue = IAPI_FAILURE;
++      }
++      return retvalue;
++}
++
++static inline int iapi_set_command(channelDescriptor *cd_p, unsigned long param,
++                              unsigned long cmd)
++{
++      int retvalue = IAPI_SUCCESS;
++      bufferDescriptor *bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++
++      if (param == SET_BIT_ALL) {
++              int j;
++
++              for (j = 0; j < cd_p->bufferDescNumber; j++) {
++                      bde_p->mode.command = cmd;
++                      bde_p++;
++              }
++      } else if (param < cd_p->bufferDescNumber) {
++              bde_p[param].mode.command = cmd;
++      } else {
++              retvalue = IAPI_FAILURE;
++      }
++      return retvalue;
++}
++
++/* ***************************************************************************/
++/**The request argument selects the control function to be performed.
++ *
++ * <b>Algorithm:</b>\n
++ *
++ * - Check data structures are properly initialized:
++ *   - Channel descriptor validity
++ *   - Channel control block validity
++ * - The ctlRequest parameter contains in the lower 16 bits the control code of
++ *   the change to be performed, and in the upper 16 bits, the BD to be
++ *   modified if the change affects a BD od the channel.
++ * - Selection of the parameter to change and appropriate sanity checks:
++ *   - Channel Descriptor: changes the pointer to the channel descriptor
++ * structure, the pointer to the new channel descriptor is given in the third
++ * argument call
++ *   - Buffer Descriptor Number: changes the number of buffer descriptor for the
++ * channel
++ *   - Buffer size: changes the size of the data buffers pointed to by the
++ * buffer descriptor; note that all buffer descriptors are assumed to have the
++ * same size for a given buffer descripotr chain
++ *   - Blocking policy: changes the blocking policy for the read and write calls
++ *   - Ownership: changes direction: turnaround
++ *   - Synchronization method: changes the callback type, default or user. The *
++ * callback function table is set accordingly
++ *   - Trust property: trust can only be changed through ChangeChannelDesc first
++ * request, this guarantees the close/open sequence for the channel
++ *   - Callback Interrupt service routine pointer: changes the callback function
++ * pointer, when this method is used, to replace it with a new one
++ *   - Channel control block pointer: not available
++ *   - Priority: changes the channel priority directly in SDMA register
++ *   - Watermark level: changes the value of the peripheral watermark level that
++ * passed to the script. The new value is passed in the third parameter call.
++ *   - Wrap bit: changes to set to 1 the Wrap bit of the last buffer descriptor
++ *
++ * @param *cd_p channel descriptor for the channel to modify
++ * @param ctlRequest request control code and, if tha case, number of BD to be
++ *                   changed
++ * @param param parameter for the modification
++ *
++ * @return
++ *     - IAPI_SUCCESS : OK
++ *     - -iapi_errno : operation failed
++ */
++int
++iapi_IoCtl(channelDescriptor *cd_p, unsigned long ctlRequest,
++      unsigned long param)
++{
++      int result = IAPI_SUCCESS;
++      unsigned char chNum;
++      unsigned long clean_ctlRequest; /* lower 16 bits of the ctlRequest */
++      unsigned long bd_num; /* upper 16 bits of the ctlRequest */
++
++      DBG(0, "%s: cd=%p req=%08lx param=%08lx\n", __FUNCTION__,
++              cd_p, ctlRequest, param);
++      /*
++       * 1. Check data structures are properly initialized
++       */
++      /* Channel descriptor validity */
++      if (cd_p == NULL) {
++              iapi_errno = IAPI_ERR_CD_UNINITIALIZED;
++              return -iapi_errno;
++      }
++
++      /* Channel control block validity */
++      if (cd_p->ccb_ptr == NULL) {
++              iapi_errno = IAPI_ERR_CCB_UNINITIALIZED;
++              return -iapi_errno;
++      }
++
++      /* Control block & Descriptor associated with the channel being worked on */
++      chNum = cd_p->channelNumber;
++
++      /* Remove, if exists, BD number specified in upper bits of ctlRequest */
++      clean_ctlRequest = ctlRequest & ~BD_NUM_MASK;
++
++      /* Extract, if exists, BD number specified in upper bits of ctlRequest */
++      bd_num = (ctlRequest & BD_NUM_MASK) >> BD_NUM_OFFSET;
++
++      /* Check that the bd_num is valid */
++      if (bd_num >= cd_p->bufferDescNumber) {
++              DBG(0, "%s: BD number %lu out of range: %u\n", __FUNCTION__,
++                      bd_num, cd_p->bufferDescNumber);
++              iapi_errno = IAPI_ERR_INVALID_PARAMETER | chNum;
++              return -iapi_errno;
++      }
++
++      /* All checks OK, try to aquire channel */
++      if (iapi_GetChannel(chNum) != 0) {
++              iapi_errno = IAPI_ERR_CH_IN_USE | chNum;
++              return -iapi_errno;
++      }
++
++      /*
++       * 2. Selection of the parameter to change and appropriate sanity checks
++       */
++      switch (clean_ctlRequest) {
++      case IAPI_CHANGE_CHANDESC:
++              /*
++               * Channel Descriptor
++               * --- Changes the pointer to the channel descriptor structure: the pointer
++               * to the new channel descriptor is given in the third argument call.
++               */
++              if ((void *)param == NULL) {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER;
++                      result = -iapi_errno;
++              } else {
++                      channelDescriptor *chParam = (channelDescriptor *)param;
++
++                      if (chParam->channelNumber != chNum) {
++                              /* Release ch so it can be aquired by the Close fn */
++                              iapi_ReleaseChannel(chNum);
++                              result = iapi_Close(cd_p);
++                              if (result == IAPI_SUCCESS) {
++                                      FREE(cd_p);
++                                      iapi_AllocChannelDesc(&cd_p,
++                                                      chParam->channelNumber);
++                                      iapi_memcpy(cd_p, chParam,
++                                              sizeof(channelDescriptor));
++                                      /* Channel is released allready, so Open can get the channel */
++                                      result = iapi_Open(cd_p,
++                                                      chParam->channelNumber);
++                                      if (result != IAPI_SUCCESS) {
++                                              return result; /* error code already set in iapi_Open */
++                                      }
++                              } else {
++                                      return result; /* error code already set in iapi_Close */
++                              }
++                      } else {
++                              iapi_errno = IAPI_ERR_CD_CHANGE |
++                                      IAPI_ERR_CH_AVAILABLE |
++                                      cd_p->channelNumber;
++                              result = -iapi_errno;
++                              break;
++                      }
++              }
++              break;
++
++      case IAPI_CHANGE_BDNUM:
++              /*
++               * Buffer Descriptor Number
++               * --- Changes the number of buffer descriptor for the channel.
++               */
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_BUFFERDESCNUMBER, param);
++              break;
++
++      case IAPI_CHANGE_BUFFSIZE:
++              /*
++               * Buffer size
++               * --- Changes the size of the data buffers pointed to by the buffer
++               * descriptor; note that all buffer descriptors are assumed to have the
++               * same size for a given buffer descripotr chain.
++               */
++              result =  iapi_ChangeChannelDesc(cd_p, IAPI_BUFFERSIZE, param);
++              break;
++
++      case IAPI_CHANGE_CHANBLOCK:
++              /*
++               * Blocking policy
++               * --- Changes the blocking policy for the read and write calls.
++               */
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_BLOCKING, param);
++              break;
++
++      case IAPI_CHANGE_OWNERSHIP:
++              /*
++               * Ownership
++               * --- Changes direction: turnaround
++               */
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_OWNERSHIP, param);
++              break;
++
++      case IAPI_CHANGE_SYNCH:
++              /*
++               * Synchronization method
++               * --- Changes the callback type, default or user. The callback function
++               * table is set accordingly.
++               */
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_CALLBACKSYNCH, param);
++              break;
++
++      case IAPI_CHANGE_TRUST:
++              /*
++               * Trust property
++               * --- trust can only be changed through ChangeChannelDesc first request,
++               * this guarantees the close/open sequence for the channel.
++               */
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_TRUST, param);
++              break;
++
++      case IAPI_CHANGE_CALLBACKFUNC:
++              /*
++               * Callback Interrupt service routine pointer
++               * --- Cahnges the callback function pointer, when this method is used, to
++               * replace it with a new one.
++               */
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_CALLBACKISR_PTR, param);
++              break;
++
++      case IAPI_CHANGE_CHANCCB:
++              /*
++               * Channel control block pointer
++               * --- NA
++               */
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_CCB_PTR, param);
++              break;
++#ifdef MCU
++      case IAPI_CHANGE_PRIORITY:
++              /*
++               * Priority
++               * --- Changes the channel priority directly in SDMA register
++               */
++              if (param < MAX_CH_PRIORITY) {
++                      __raw_writel(param, SDMA_CHNPRI(cd_p->channelNumber));
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++#endif /* MCU */
++      case IAPI_CHANGE_BDWRAP:
++              /*
++               * Wrap
++               * --- Set to 1 the wrap bit of the last buffer descriptor of the array.
++               * it provides the possibility to have a circular buffer structure.
++               */
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_BDWRAP, param);
++              break;
++
++      case IAPI_CHANGE_WATERMARK:
++              /*
++               * Watermark
++               * --- Changes the value of the peripheral watermark level that triggers
++               * a DMA request. It impacts context of the channel, therefore channel 0
++               * must be started to update the context with this new value.
++               */
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_WML, param);
++              break;
++
++      case IAPI_CHANGE_SET_BDINTR:
++              /*
++               * INTR
++               * --- Set the INTR bit on specified BD or on all BD's if SET_BIT_ALL
++               * is passed as parameter.
++               */
++              result = iapi_set_status(cd_p, param, BD_INTR);
++              break;
++
++      case IAPI_CHANGE_UNSET_BDINTR:
++              /*
++               * INTR
++               * --- Unset the INTR bit on specified BD or on all BD's if SET_BIT_ALL
++               * is passed as parameter.
++               */
++              result = iapi_clr_status(cd_p, param, BD_INTR);
++              break;
++
++      case IAPI_CHANGE_EVTMASK1:
++              /*
++               * EventMask1
++               * --- Changes the value of the eventMask1
++               */
++              cd_p->eventMask1 = param;
++              break;
++
++      case IAPI_CHANGE_EVTMASK2:
++              /*
++               * EventMask2
++               * --- Changes the value of the eventMask2
++               */
++              cd_p->eventMask2 = param;
++              break;
++
++      case IAPI_CHANGE_PERIPHADDR:
++              /*
++               * Peripheral Address
++               * --- Changes the value of the peripheralAddr
++               */
++              cd_p->peripheralAddr = param;
++              break;
++
++      case IAPI_CHANGE_SET_BDCONT:
++              /*
++               * Cont
++               * --- Set the CONT bit on specified BD on all BD's if SET_BIT_ALL
++               * is passed as parameter.
++               */
++              result = iapi_set_status(cd_p, param, BD_CONT);
++              break;
++
++      case IAPI_CHANGE_UNSET_BDCONT:
++              /*
++               * Cont
++               * --- Unset the CONT bit on specified BD or on all BD's if SET_BIT_ALL
++               * is passed as parameter.
++               */
++              result = iapi_clr_status(cd_p, param, BD_CONT);
++              break;
++
++      case IAPI_CHANGE_SET_BDEXTD:
++              /*
++               * EXTD
++               * --- Set the EXTD bit on specified BD or on all BD's if SET_BIT_ALL
++               * is passed as parameter.
++               */
++              result = iapi_set_status(cd_p, param, BD_EXTD);
++              break;
++
++      case IAPI_CHANGE_UNSET_BDEXTD:
++              /*
++               * EXTD
++               * --- Unset the EXTD bit on specified BD or on all BD's if SET_BIT_ALL
++               * is passed as parameter.
++               */
++              result = iapi_clr_status(cd_p, param, BD_EXTD);
++              break;
++
++      case IAPI_CHANGE_SET_TRANSFER_CD:
++              /*
++               * TRANSFER SIZE to be used for this channel
++               * --- Set the transfer size used indicator and code for transfer size in
++               * the CD
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++                      int j;
++
++                      if ((param == TRANSFER_8BIT) || (param == TRANSFER_16BIT) ||
++                              (param == TRANSFER_24BIT) || (param == TRANSFER_32BIT)) {
++                              cd_p->useDataSize = TRUE;
++                              cd_p->dataSize = param;
++                              bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                              for (j = 0; j < cd_p->bufferDescNumber; j++) {
++                                      bde_p->mode.command = param;
++                                      bde_p++;
++                              }
++                      } else {
++                              result = IAPI_FAILURE;
++                      }
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      case IAPI_CHANGE_USER_ARG:
++              /*
++               * USER_ARG
++               * --- Set the user selectable pointer to be received by the callback
++               * function, if IRQ synch is used
++               */
++              userArgTable[cd_p->channelNumber]= (void *)param;
++              break;
++
++      case IAPI_CHANGE_FORCE_CLOSE:
++              /*
++               * FORCE_CLOSE
++               * --- Set the forceClose bit in channelDescriptor to value passed in param.
++               * If this bit is TRUE, the channel in closed even if some BD are still
++               * owned by the SDMA.
++               */
++              if ((param == TRUE) || (param == FALSE)) {
++                      cd_p->forceClose = param;
++              } else {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER | cd_p->channelNumber;
++                      result = -iapi_errno;
++              }
++              break;
++
++      case IAPI_CHANGE_SET_TRANSFER:
++              /*
++               * TRANSFER type
++               * --- Set the last 2 bits in the command field of the BD to specify the
++               * transfer type 8, 16, 24, or 32 bits on all BD's, allready set in the CD
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++
++                      if ((param == TRANSFER_8BIT) || (param == TRANSFER_16BIT) ||
++                              (param == TRANSFER_24BIT) || (param == TRANSFER_32BIT)) {
++                              int j;
++
++                              bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                              for (j = 0; j < cd_p->bufferDescNumber; j++) {
++                                      bde_p->mode.command = param;
++                                      bde_p++;
++                              }
++                      } else {
++                              result = IAPI_FAILURE;
++                      }
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      case IAPI_CHANGE_SET_BUFFERADDR:
++              /*
++               * BUFFER address
++               * --- Change buffer address in BD specified in the upper 16 bits of the
++               * ctlRequest.
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++
++                      /* Get pointer to the BD structure to change */
++                      bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      bde_p += bd_num;
++
++                      /* DO NOT translate address to physical */
++                      bde_p->bufferAddr = (dma_addr_t)param;
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      case IAPI_CHANGE_GET_BUFFERADDR:
++              /*
++               * BUFFER address
++               * --- Get the buffer address from the BD specified in the upper 16 bits of the
++               * ctlRequest.
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++                      dma_addr_t *retval = (dma_addr_t *)param;
++
++                      /* Get pointer to the BD structure to change */
++                      bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      bde_p += bd_num;
++                      /* DO NOT Translate to virtual */
++                      *retval = bde_p->bufferAddr;
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      case IAPI_CHANGE_SET_EXTDBUFFERADDR:
++              /*
++               * EXTENDED BUFFER address
++               * --- Change extended buffer address in BD specified in the upper 16 bits
++               * of the ctlRequest.
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++
++                      /* Get pointer to the BD structure to change */
++                      bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      bde_p += bd_num;
++
++                      /* DO NOT translate address to physical. The user might want something else
++                       * here
++                       */
++                      bde_p->extBufferAddr = (dma_addr_t)param;
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      case IAPI_CHANGE_GET_EXTDBUFFERADDR:
++              /*
++               * EXTENDED BUFFER address
++               * --- Get extended buffer address from the BD specified in the upper 16 bits
++               * of the ctlRequest.
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++                      dma_addr_t *retval = (dma_addr_t *)param;
++
++                      /* Get pointer to the BD structure to change */
++                      bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      bde_p += bd_num;
++
++                      /* DO NOT translate address to vitual - user knows what is here.
++                       */
++                      *retval = bde_p->extBufferAddr;
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      case IAPI_CHANGE_SET_COMMAND:
++              /*
++               * COMMAND field
++               * --- Change command field in BD specified in the upper 16 bits of the
++               * ctlRequest.
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++
++                      /* Get pointer to the BD structure to change */
++                      bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      bde_p += bd_num;
++                      /* Update command field */
++                      bde_p->mode.command = param;
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      case IAPI_CHANGE_GET_COMMAND:
++              /*
++               * COMMAND field
++               * --- Get the command field from the BD specified in the upper 16 bits
++               * of the ctlRequest.
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++
++                      /* Get pointer to the BD structure to change */
++                      bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      bde_p += bd_num;
++                      /* Get the command field */
++                      *((unsigned long *)param) = bde_p->mode.command;
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      case IAPI_CHANGE_SET_COUNT:
++              /*
++               * COUNT field
++               * --- Change count field in BD specified in the upper 16 bits of the
++               * ctlRequest.
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++
++                      /* Get pointer to the BD structure to change */
++                      bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      bde_p += bd_num;
++                      /* Update count field */
++                      bde_p->mode.count = param;
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      case IAPI_CHANGE_GET_COUNT:
++              /*
++               * COUNT field
++               * --- Get the count field of the BD specified in the upper 16 bits of the
++               * ctlRequest.
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++
++                      /* Get pointer to the BD structure to change */
++                      bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      bde_p += bd_num;
++                      /* Update count field */
++                      *((unsigned long *)param) = bde_p->mode.count;
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      case IAPI_CHANGE_SET_STATUS:
++              /*
++               * STATUS field
++               * --- Change status field in BD specified in the upper 16 bits of the
++               * ctlRequest.
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++
++                      /* Get pointer to the BD structure to change */
++                      bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      bde_p += bd_num;
++                      /* Update status field */
++                      DBG(1, "%s: BD[%ld] %08x->%08lx\n", __FUNCTION__,
++                              bd_num, bde_p->mode.status, param);
++                      bde_p->mode.status = param;
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      case IAPI_CHANGE_GET_STATUS:
++              /*
++               * STATUS field
++               * --- Get the status field of the BD specified in the upper 16 bits
++               * of the ctlRequest.
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++
++                      /* Get pointer to the BD structure to change */
++                      bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      bde_p += bd_num;
++                      /* Update status field */
++                      *((unsigned long *)param) = bde_p->mode.status;
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++#ifdef MCU
++      case IAPI_CHANGE_SET_ENDIANNESS:
++              /*
++               * Endianness
++               * --- Set the ENDIANNESS indicator in the command filed of the specified BD
++               * or on all BD's if SET_BIT_ALL is passed as parameter.
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++
++                      if (param == SET_BIT_ALL) {
++                              int j;
++
++                              for (j = 0; j < cd_p->bufferDescNumber; j++, bde_p++) {
++                                      /* Clear the respective bits in the command field
++                                       * and set the new parameter value
++                                       */
++                                      bde_p->mode.command &= ~ENDIANNESS_MASK;
++                                      bde_p->mode.command |= CHANGE_ENDIANNESS &
++                                              ENDIANNESS_MASK;
++                              }
++                      } else if (param < cd_p->bufferDescNumber) {
++                              bde_p[param].mode.command &= ~ENDIANNESS_MASK;
++                              bde_p[param].mode.command |= CHANGE_ENDIANNESS &
++                                      ENDIANNESS_MASK;
++                      } else {
++                              result = IAPI_FAILURE;
++                      }
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++#ifdef SDMA_V2
++      case IAPI_ENTER_LOCK_MODE:
++              /*
++               * SDMA State
++               * --- Enter the SDMA into LOCK Mode. No RAM update allowed except same Context
++               * update with same PC Value.
++               */
++              if (param == RESET_CLEAR_LOCK) {
++                      __raw_writel(1 << RESET_CLR_BIT_OFFSET, SDMA_SDMA_LOCK);
++                      __raw_writel(1 << LOCK_BIT_OFFSET, SDMA_SDMA_LOCK);
++                      iapi_SdmaState = LOCK;
++              } else if (param == RESET_NOCLEAR_LOCK) {
++                      __raw_writel(1 << LOCK_BIT_OFFSET, SDMA_SDMA_LOCK);
++                      iapi_SdmaState = LOCK;
++              }
++              break;
++#endif
++#endif
++      case IAPI_CHANGE_SET_INTR_MASK:
++              /*
++               * Interrupt Mask
++               * --- Sets the Interrupt Mask directly in SDMA register. Can be used  to set
++               * mask per channel or for all channels(SET_BIT_ALL)
++               * In case of error, the error reflects the channel number the error is received for.
++               */
++              if (param == SET_BIT_ALL) {
++                      result = iapi_lowChangeIntrMask(SET_BIT_ALL, OR_OP);
++              } else {
++                      /* chnum is Extracted earlier in iapi_Ioctl() and checked for validity */
++                      result = iapi_lowChangeIntrMask(1 << chNum, OR_OP);
++              }
++              /* iapi_errno has been set by iapi_lowChangeIntrMask() */
++              if (result != IAPI_SUCCESS)
++                      result |= IAPI_ERR_CH_AVAILABLE | chNum;
++              break;
++
++      case IAPI_CHANGE_UNSET_INTR_MASK:
++              /*
++               * Interrupt Mask
++               * --- Clears the Interrupt Mask directly in SDMA register. Can be used  to clear
++               * mask per channel or for all channels(SET_BIT_ALL)
++               * In case of error, the error reflects the channel number the error is received for.
++               */
++              if (param == SET_BIT_ALL) {
++                      result = iapi_lowChangeIntrMask(~SET_BIT_ALL, AND_OP);
++              } else {
++                      result = iapi_lowChangeIntrMask(~(1 << chNum), AND_OP);
++              }
++              /* iapi_errno has been set by iapi_lowChangeIntrMask() */
++              if (result != IAPI_SUCCESS)
++                      result |= IAPI_ERR_CH_AVAILABLE | chNum;
++              break;
++
++      case IAPI_CHANGE_BUFFER_LOCATION:
++              /* Buffer Location
++               * Set whether Buffer is located in External Memory or Internal Memory
++               */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      bufferDescriptor *bde_p;
++
++                      bde_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      bde_p += bd_num;
++                      if ((param == EXTERNAL_MEM) || (param == INTERNAL_MEM)) {
++                              /* Clear the respective bits in the command field
++                               * and set the new parameter value
++                               */
++                              bde_p->mode.command &= ~BUFFER_LOC_MASK;
++                              bde_p->mode.command |= param & BUFFER_LOC_MASK;
++                      } else {
++                              result = IAPI_FAILURE;
++                      }
++              } else {
++                      result = IAPI_FAILURE;
++              }
++              break;
++
++      default:
++              iapi_errno = IAPI_ERR_CD_CHANGE_UNKNOWN |
++                      IAPI_ERR_CH_AVAILABLE | chNum;
++              result = -iapi_errno;
++      }
++
++      iapi_ReleaseChannel(chNum);
++      return result;
++}
++
++/* ***************************************************************************/
++/**Initialization of the SDMA - opening of channel 0, download RAM image.
++ *
++ * <b>Algorithm:</b>\n
++ *     - open channel 0
++ *     - if ram_image pointer passed is not NULL, download RAM image to SDMA
++ *
++ * @param
++ *     - cd_p channel descriptor pointer for channel 0
++ *     - ram_image pointer to RAM image to download, or NULL if this operation
++ *                 is not required
++ *     - code_size size of the RAM image, in bytes
++ *     - start_addr start address for the RAM image
++ *
++ * @return
++ *     - IAPI_SUCCESS if all operations were successful
++ *     - negated I.API error code if any operation failed
++ */
++#ifdef MCU
++int
++iapi_Init(channelDescriptor *cd_p, configs_data *config_p, unsigned short *ram_image,
++      unsigned short code_size, dma_addr_t start_addr, unsigned short channel0_addr)
++{
++#endif
++#ifdef DSP
++int
++iapi_Init(channelDescriptor *cd_p)
++{
++#endif
++      int retvalue;  /* Variable to store the results from I.API calls */
++
++      /* Check initialization not allredy done */
++      if (iapi_CCBHead != NULL) {
++              iapi_errno = IAPI_ERR_NOT_ALLOWED;
++              return -iapi_errno;
++      }
++      /* Be sure SDMA has not started yet */
++#ifdef MCU
++      __raw_writel(0, SDMA_H_C0PTR);
++#endif
++#ifdef DSP
++      __raw_writel(0, SDMA_D_C0PTR);
++#endif
++
++      /* Try to open channel 0 */
++      retvalue = iapi_Open(cd_p, 0);
++      if (retvalue != IAPI_SUCCESS) {
++              return retvalue;
++      }
++#if 0
++      print_hex_dump(KERN_DEBUG, "sdma: ", DUMP_PREFIX_ADDRESS, 4, 4,
++              cd_p->ccb_ptr, CH_NUM * sizeof(channelControlBlock), 0);
++#endif
++#ifdef MCU
++      /* Set Command Channel (Channel Zero) */
++      __raw_writel(0x4000 | (channel0_addr & 0x3FFF), SDMA_CHN0ADDR);
++
++      /* Set bits of CONFIG register but with static context switching */
++      __raw_writel((config_p->dspdma << 12) | (config_p->rtdobs << 11) |
++                   (config_p->acr << 4), SDMA_H_CONFIG);
++
++      /* Send the address for the host channel table to the SDMA */
++      __raw_writel(iapi_Virt2Phys(iapi_CCBHead), SDMA_H_C0PTR);
++      /* If required, download the RAM image for SDMA */
++      if (ram_image != NULL) {
++              retvalue = iapi_SetScript(cd_p, ram_image, code_size,
++                                      start_addr);
++      }
++
++      /* Set bits of CONFIG register with given context switching mode */
++      __raw_writel((config_p->dspdma << 12) | (config_p->rtdobs << 11) |
++                   (config_p->acr << 4) | config_p->csm, SDMA_H_CONFIG);
++
++#endif
++#ifdef DSP
++      /* Send the address for the host channel table to the SDMA */
++      __raw_writel(iapi_Virt2Phys(iapi_CCBHead), SDMA_D_C0PTR);
++#endif
++
++#ifdef SDMA_V2
++      iapi_SdmaState = OPEN;
++#endif
++      return retvalue;
++}
++
++
++/* ***************************************************************************/
++/**High layer interface for starting a channel
++ *
++ * <b>Algorithm:</b>\n
++ *    - call low layer function for starting a channel
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ */
++int
++iapi_StartChannel(unsigned char channel)
++{
++      iapi_lowStartChannel(channel);
++      return IAPI_SUCCESS;
++}
++/* ***************************************************************************/
++/**High layer interface for stopping a channel
++ *
++ * <b>Algorithm:</b>\n
++ *    - call low layer function for stopping a channel
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ */
++int
++iapi_StopChannel(unsigned char channel)
++{
++      iapi_lowStopChannel(channel);
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/**High layer interface for synchronising a channel
++ *
++ * <b>Algorithm:</b>\n
++ *    - call low layer function for stopping a channel
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ */
++int iapi_SynchChannel(unsigned char channel)
++{
++      iapi_lowSynchChannel(channel);
++      return IAPI_SUCCESS;
++}
++
++#ifdef MCU
++/* ***************************************************************************/
++/**High layer interface for getting program memory data from SDMA
++ *
++ * <b>Algorithm:</b>\n
++ *    - call coresponding low layer function
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ */
++int
++iapi_GetScript(channelDescriptor *cd_p, void *buf, unsigned short size,
++      dma_addr_t address)
++{
++      iapi_lowGetScript(cd_p, buf, size, address);
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/**High layer interface for getting data memory from SDMA
++ *
++ * <b>Algorithm:</b>\n
++ *    - call coresponding low layer function
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ */
++int
++iapi_GetContext(channelDescriptor *cd_p, void *buf, unsigned char channel)
++{
++      iapi_lowGetContext(cd_p, buf, channel);
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/**High layer interface for set program memory data to SDMA - e.g. scripts
++ *
++ * <b>Algorithm:</b>\n
++ *    - call coresponding low layer function
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ */
++int
++iapi_SetScript(channelDescriptor *cd_p, void *buf, unsigned short nbyte,
++      dma_addr_t destAddr)
++{
++      iapi_lowSetScript(cd_p, buf, nbyte, destAddr);
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/**High layer interface for set data memory to SDMA - e.g. contexts.
++ *
++ * <b>Algorithm:</b>\n
++ *    - call coresponding low layer function
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ */
++int
++iapi_SetContext(channelDescriptor *cd_p, void *buf, unsigned char channel)
++{
++      iapi_lowSetContext(cd_p, buf, channel);
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/**High layer interface used to associate specified channel with a script.
++ *
++ * <b>Algorithm:</b>\n
++ *    - call coresponding low layer function
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ */
++int
++iapi_AssignScript(channelDescriptor *cd_p, script_data *data_p)
++{
++      /* VERIFY THAT THE CHANNEL IT IS OPENED !!!! */
++      return iapi_lowAssignScript(cd_p, data_p);
++}
++
++/* ***************************************************************************/
++/**High layer interface used to associate specified channel with a script.
++ *
++ * <b>Algorithm:</b>\n
++ *    - call coresponding low layer function
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ */
++int
++iapi_SetChannelEventMapping(unsigned char event, unsigned long channel_map)
++{
++      return iapi_lowSetChannelEventMapping(event, channel_map);
++}
++#endif
++
++
++
++#ifdef DSP
++#define SDMA_DI  SDMA_D_INTR
++void IRQ_Handler();
++#pragma interrupt IRQ_Handler
++#endif
++
++#ifdef MCU
++#define SDMA_DI  SDMA_H_INTR
++#endif
++
++#ifndef IRQ_KEYWORD
++#define IRQ_KEYWORD
++#endif /* IRQ_KEYWORD */
++
++/* ***************************************************************************/
++/**
++ *@brief  Find the first set bit in data parameter.
++ *
++ *       Find the first set bit in unsigned integer parameter data. Data is scanned
++ *  from MSB to LSB, searching for the set bit. The value returned is the
++ *  offset from the most significant bit of data. If bit 31 is set, the value
++ *  returned is zero. If no bits are set, a value of 32 is returned. This is compliant
++ *  with the MCore FF1 instruction.
++ *
++ *
++ *
++ * @param
++ *   - data: variable to check
++ *
++ * @return
++ *   - the offset of the most significant bit set from the MSB
++ */
++static unsigned int
++quartz_FF1(unsigned int data)
++{
++      register unsigned int result = 0;
++      while ((result <= 31) && !(data & 0x80000000U)) {
++              data <<= 1U;
++              result++;
++      }
++
++      return result;
++}
++#ifdef DEBUG
++static void dump_chan(channelControlBlock *ccb, int chan)
++{
++      dma_addr_t bd_phys = ccb[chan].baseBDptr;
++      int i;
++
++      if (bd_phys == DMA_ADDR_INVALID)
++              return;
++
++      while (1) {
++              bufferDescriptor *bd = iapi_Phys2Virt(bd_phys);
++
++              DBG(1, "BD[%2d]@%08x count=%d CONT=%d DONE=%d WRAP=%d LAST=%d INTR=%d ERR=%d EXTD=%d\n",
++                      i, iapi_Virt2Phys(bd), bd->mode.count,
++                      !!(bd->mode.status & BD_CONT),
++                      !!(bd->mode.status & BD_DONE),
++                      !!(bd->mode.status & BD_WRAP),
++                      !!(bd->mode.status & BD_LAST),
++                      !!(bd->mode.status & BD_INTR),
++                      !!(bd->mode.status & BD_RROR),
++                      !!(bd->mode.status & BD_EXTD));
++              if (bd->mode.status & (BD_LAST | BD_WRAP)) {
++                      break;
++              }
++              bd_phys += ((bd->mode.status & BD_EXTD) ?
++                      SDMA_EXTENDED_BD_SIZE : SDMA_BD_SIZE);
++              i++;
++      }
++}
++
++static void dump_dma(void)
++{
++      dma_addr_t reg;
++
++      reg = __raw_readl(SDMA_H_C0PTR);
++      if (reg != DMA_ADDR_INVALID) {
++              channelControlBlock *ccb = iapi_Phys2Virt(reg);
++              int chan;
++
++              for (chan = 0; chan < CH_NUM; chan++) {
++                      dump_chan(ccb, chan);
++              }
++      }
++}
++#endif // DEBUG
++
++IRQ_KEYWORD
++void
++IRQ_Handler(void)
++{
++      unsigned int intrReg;/* interrupt register mask for clearing the interrupt bit */
++      unsigned char chNum; /* SDMA channel number generating the IRQ */
++
++      /* Disable interrupts */
++      iapi_DisableInterrupts();
++      /*
++       * Clear interrupt in SDMA DI register => ACK to the SDMA the IT request.
++       * Get each interrupt number, clear them one after the other.
++       */
++      if (__raw_readl(SDMA_DI) != 0) {
++              chNum = CH_NUM - 1 - quartz_FF1(__raw_readl(SDMA_DI));
++              intrReg = 1 << chNum;
++      } else {
++              chNum = 32;
++              intrReg = 0;
++      }
++      DBG(0, "%s: SDMA_DI=%08x\n", __FUNCTION__, __raw_readl(SDMA_DI));
++#ifdef DEBUG
++      dump_dma();
++#endif
++      while (intrReg != 0) {
++              DBG(0, "%s: ACK %08x\n", __FUNCTION__, intrReg);
++              __raw_writel(intrReg, SDMA_DI);
++              iapi_SDMAIntr |= intrReg;
++              iapi_WakeUp(chNum);
++              if (callbackIsrTable[chNum] != NULL) {
++                      /* release channel before callback, so IoCtl's are available */
++                      iapi_ReleaseChannel(chNum);
++                      callbackIsrTable[chNum](iapi_CCBHead[chNum].channelDescriptor,
++                                              userArgTable[chNum]);
++              }
++
++              chNum = CH_NUM - 1 - quartz_FF1(__raw_readl(SDMA_DI));
++              intrReg = 1 << chNum;
++      }
++
++      /* Enable interrupts */
++      iapi_EnableInterrupts();
++      DBG(0, "%s: Done\n", __FUNCTION__);
++}
++
++/* ***************************************************************************/
++/**
++ *@brief  Perform a memory copy operation, in the memory of the same processor
++ *
++ *       Size bytes are copied from the src address to dest address. It is used
++ *    the channel pointed by cd_p, which must be configured prior to this call:
++ *    opened, associated with the script to perform the operation - DSP_2_DSP,
++ *    or MCU_2_MCU - and have the synchronization option set.
++ *
++ *
++ *
++ * @param
++ *   - cd_p: channel configured to perform DSP_2_DSP or MCU_2_MCU transfers
++ *   - dest: destination memory address
++ *   - src : source memory address
++ *   - size: number of bytes to copy from src to dest
++ *
++ * @return
++ *   - the offset of the most significant bit set from the MSB
++ */
++
++int iapi_MemCopy(channelDescriptor *cd_p, void *dest, void *src, unsigned long size)
++{
++      int result = IAPI_SUCCESS;
++      bufferDescriptor *bd_p;
++
++      /* Channel descriptor validity */
++      if (cd_p == NULL) {
++              iapi_errno = IAPI_ERR_CD_UNINITIALIZED;
++              return -iapi_errno;
++      }
++
++      /* Check and set correct parameter */
++      if (cd_p->trust != TRUE) {
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_TRUST, TRUE);
++      }
++
++      if (cd_p->bufferDescNumber != 1) {
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_BUFFERDESCNUMBER, 1);
++              if (result != IAPI_SUCCESS) {
++                      return result;
++              }
++      }
++
++      if (cd_p->bufferSize != size) {
++              result = iapi_ChangeChannelDesc(cd_p, IAPI_BUFFERSIZE, size);
++              if (result != IAPI_SUCCESS) {
++                      return result;
++              }
++      }
++      /* Set addresses */
++      bd_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++      bd_p->bufferAddr = iapi_Virt2Phys(src);
++      bd_p->extBufferAddr = iapi_Virt2Phys(dest);
++
++      /* Set mode */
++      bd_p->mode.count = size;
++      bd_p->mode.command = 0x00;
++      bd_p->mode.status = BD_INTR | BD_EXTD | BD_DONE | BD_WRAP;
++
++      /* Decide if we sleep or not */
++      if (cd_p->callbackSynch == DEFAULT_POLL) {
++              iapi_StartChannel(cd_p->channelNumber);
++              /* Call synchronization routine */
++              iapi_SynchChannel(cd_p->channelNumber);
++      } else {
++              /* Just start the channel */
++              iapi_StartChannel(cd_p->channelNumber);
++      }
++
++      return result;
++}
++
++/* ***************************************************************************/
++/**Return the channel number from the channel descriptor
++ *
++ * @param cd_p  pointer to channel descriptor to obtain the channel number
++ *
++ * @return
++ *     - the channel number
++ *
++ */
++int iapi_GetChannelNumber(channelDescriptor *cd_p)
++{
++      return cd_p->channelNumber;
++}
++
++/* ***************************************************************************/
++/**Return the error bit from the current BD of the channel
++ *
++ *
++ * @param cd_p  pointer to channel descriptor
++ *
++ * @return
++ *     - 0 if no error detected
++ *     - BD_RROR | DATA_ERROR if error detected
++ *
++ */
++unsigned long iapi_GetError(channelDescriptor *cd_p)
++{
++      bufferDescriptor *bd_p = iapi_Phys2Virt(cd_p->ccb_ptr->currentBDptr);
++
++      if (bd_p == NULL)
++              return -EINVAL;
++
++      return (bd_p->mode.status & BD_RROR) |
++              cd_p->ccb_ptr->status.data_error;
++}
++
++/* ***************************************************************************/
++/**Return the count from the current BD of the channel
++ *
++ *
++ * @param cd_p  pointer to channel descriptor
++ *
++ * @return
++ *     - count field of the current BD for the channel
++ *
++ */
++int iapi_GetCount(channelDescriptor *cd_p)
++{
++      bufferDescriptor *bd_p = iapi_Phys2Virt(cd_p->ccb_ptr->currentBDptr);
++
++      if (bd_p == NULL)
++              return -EINVAL;
++
++      return bd_p->mode.count;
++}
++
++/* ***************************************************************************/
++/**Return the sum of counts for all the BD's owned by the processor for
++ * the channel specified by the received parameter.
++ *
++ *
++ * @param cd_p  pointer to channel descriptor
++ *
++ * @return
++ *     - sum of count fields
++ *
++ */
++int iapi_GetCountAll(channelDescriptor *cd_p)
++{
++      int retval = 0;
++      int i;
++      bufferDescriptor *bd_p;
++
++      bd_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++
++      for (i = 0; i < cd_p->bufferDescNumber &&
++                   !(bd_p->mode.status & BD_DONE); i++, bd_p++) {
++              retval += bd_p->mode.count;
++      }
++      return retval;
++}
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c     1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiLow.c     2010-12-03 09:51:55.404347330 +0100
+@@ -0,0 +1,153 @@
++/******************************************************************************
++ *
++ * Copyright 2007-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
++ *
++ ******************************************************************************
++ *
++ * File: iapiLow.c
++ *
++ * $Id iapiLow.c $
++ *
++ * Description:
++ *  This library is written in C to guarantee functionality and integrity in
++ * the usage of SDMA virtual DMA channels. This API (Application Programming
++ * Interface)  allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
++ * fashion.
++ *  These are the LOW level functions of the I.API.
++ *
++ *
++ * /
++ *
++ * $Log iapiLow.c $
++ *
++ *****************************************************************************/
++
++/* ****************************************************************************
++ * Include File Section
++ *****************************************************************************/
++#include <linux/kernel.h>
++
++#include <epm.h>
++#include <iapiLow.h>
++
++/**
++ * Function Section
++ */
++
++
++/* ***************************************************************************/
++/**Records an ISR callback function pointer into the ISR callback
++ * function table
++ *
++ * @param cd_p channel descriptor to attach callback to
++ * @param func_p pointer to the callback function to be registered
++ *
++ * @return none
++ */
++void
++iapi_AttachCallbackISR(channelDescriptor *cd_p, CallbackISR func_p)
++{
++      if (cd_p->callbackSynch == CALLBACK_ISR) {
++              iapi_DisableInterrupts();
++              callbackIsrTable[cd_p->channelNumber] = func_p;
++              iapi_EnableInterrupts();
++      } else   if (cd_p->callbackSynch == DEFAULT_POLL) {
++              callbackIsrTable[cd_p->channelNumber] = NULL;
++      } else {
++              iapi_errno = IAPI_ERR_CALLBACKSYNCH_UNKNOWN |
++                      IAPI_ERR_CH_AVAILABLE |
++                      cd_p->channelNumber;
++              WARN_ON(1);
++      }
++}
++
++
++/* ***************************************************************************/
++/**Detaches (removes) an ISR callback function pointer from the ISR callback
++ * function table
++ *
++ * <b>Algorithm:</b>\n
++ *    - Attach a null function to replace the original one.
++ *
++ * @param cd_p channel descriptor to detach callback from
++ *
++ * @return none
++ */
++void
++iapi_DetachCallbackISR(channelDescriptor *cd_p)
++{
++      iapi_AttachCallbackISR(cd_p, NULL);
++}
++
++/* ***************************************************************************/
++/**Updates an ISR callback function pointer into the ISR callback function
++ * table
++ *
++ * <b>Algorithm:</b>\n
++ *    - Detach the old function pointer (if any) and attach the new one
++ *
++ * @param cd_p channel descriptor to attach callback to
++ * @param func_p pointer to the callback function to be registered
++ *
++ * @return none
++ */
++void
++iapi_ChangeCallbackISR(channelDescriptor *cd_p, CallbackISR func_p)
++{
++      iapi_DetachCallbackISR(cd_p);
++      iapi_AttachCallbackISR(cd_p, func_p);
++}
++
++/* ***************************************************************************/
++/**Loop while the channel is not done on the SDMA
++ *
++ * <b>Algorithm:</b>\n
++ *    - Loop doing nothing but checking the I.API global variable to indicate
++ * that the channel has been completed (interrupt from SDMA)
++ *
++ * <b>Notes:</b>\n
++ *    - The ISR must update the I.API global variable iapi_SDMAIntr.
++ *
++ * @param channel channel number to poll on
++ *
++ * @return none
++ */
++void
++iapi_lowSynchChannel(unsigned char channel)
++{
++      //while (!((1UL << channel) & iapi_SDMAIntr));
++      GOTO_SLEEP(channel);
++      DBG(0, "%s: Done: %08lx->%08lx\n", __FUNCTION__, iapi_SDMAIntr,
++              iapi_SDMAIntr & ~(1 << channel));
++      iapi_SDMAIntr &= ~(1 << channel);
++}
++
++/* ***************************************************************************/
++/**Fill the buffer descriptor with the values given in parameter.
++ *
++ * @return none
++ */
++void
++iapi_SetBufferDescriptor(bufferDescriptor *bd_p, unsigned char command,
++                      unsigned char status, unsigned short count,
++                      void *buffAddr, dma_addr_t extBufferAddr)
++{
++      bd_p->mode.command = command;
++      bd_p->mode.status = status;
++      bd_p->mode.count = count;
++      if (buffAddr != NULL) {
++              bd_p->bufferAddr = iapi_Virt2Phys(buffAddr);
++      } else {
++              bd_p->bufferAddr = DMA_ADDR_INVALID;
++      }
++      bd_p->extBufferAddr = extBufferAddr;
++}
++
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiLowDsp.c linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiLowDsp.c
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiLowDsp.c  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiLowDsp.c  2010-12-03 09:51:55.404347330 +0100
+@@ -0,0 +1,79 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiLowDsp.c
++ *
++ * $Id iapiLowDsp.c $
++ *
++ * Description:
++ *  This library is written in C to guarantee functionality and integrity in
++ * the usage of SDMA virtual DMA channels. This API (Application Programming
++ * Interface)  allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
++ * fashion.
++ *  These are the LOW level functions of the I.API specific to MCU.
++ *
++ *
++ *
++ *
++ * $Log iapiLowDsp.c $
++ *
++ *****************************************************************************/
++
++/* ****************************************************************************
++ * Include File Section
++ *****************************************************************************/
++#include "epm.h"
++#include "iapiLow.h"
++
++/* ****************************************************************************
++ * Function Section
++ *****************************************************************************/
++#ifdef DSP
++
++/* ***************************************************************************/
++/**Starts the channel (core specific register)
++ *
++ * <b>Algorithm:</b>\n
++ *   - Bit numbered "channel" of DspEnStartReg register is set
++ *
++ * @param channel channel to start
++ *
++ * @return none
++ */
++void
++iapi_lowStartChannel (unsigned char channel)
++{
++  SDMA_D_START |= (1 << channel);
++}
++
++/* ***************************************************************************/
++/**Stops the channel (core specific register)
++ *
++ * <b>Algorithm:</b>
++ *   - Bit numbered "channel" of DspEnStopReg register is cleared
++ *
++ * <b>Notes:</b>\n
++ *   - This is a write one to clear register
++ *
++ * @param channel channel to stop
++ *
++ * @return none
++ */
++void
++iapi_lowStopChannel (unsigned char channel)
++{
++  SDMA_D_STATSTOP &= (1 << channel);
++}
++
++#endif /* DSP */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiLowMcu.c  2010-12-03 09:51:55.408346904 +0100
+@@ -0,0 +1,545 @@
++/******************************************************************************
++ *
++ * Copyright 2007-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: iapiLowMcu.c
++ *
++ * $Id iapiLowMcu.c $
++ *
++ * Description:
++ *  This library is written in C to guarantee functionality and integrity in
++ * the usage of SDMA virtual DMA channels. This API (Application Programming
++ * Interface)  allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
++ * fashion.
++ *  These are the LOW level functions of the I.API specific to MCU.
++ *
++ *
++ *  http://compass/mot.com/go/115342679
++ *
++ * $Log iapiLowMcu.c $
++ *
++ *****************************************************************************/
++
++/* ****************************************************************************
++ * Include File Section
++ *****************************************************************************/
++#include <string.h>
++#include <linux/io.h>
++
++#include <epm.h>
++#include <iapiLow.h>
++
++/* ****************************************************************************
++ * Function Section
++ *****************************************************************************/
++#ifdef MCU
++
++/* ***************************************************************************/
++/**Send a command on SDMA's channel zero.
++ * Check if buffer descriptor is already used by the sdma, if yes return
++ * an error as c0BDNum is wrong.
++ *
++ * <b>Notes</b>\n
++ *  There is an upgrade in the script on the Context load command and
++ * the fact that the context structure has a fixed length of 20 or 24
++ * depending on SDMA versions.
++ *
++ * @return
++ *   - IAPI_SUCCESS
++ *   - -iapi_errno if failure
++ */
++int
++iapi_Channel0Command(channelDescriptor *cd_p, void *buf,
++              unsigned short nbyte, unsigned char command)
++{
++      channelControlBlock *ccb_p;
++      bufferDescriptor *bd_p;
++      int result = IAPI_SUCCESS;
++      unsigned char chNum;
++
++      /*
++       * Check data structures are properly initialized
++       */
++      /* Channel descriptor validity */
++      if (cd_p == NULL) {
++              result = IAPI_ERR_CD_UNINITIALIZED;
++              iapi_errno = result;
++              return -result;
++      }
++
++      /* Channel control block validity */
++      if (cd_p->ccb_ptr == NULL) {
++              result = IAPI_ERR_CCB_UNINITIALIZED;
++              iapi_errno = result;
++              return -result;
++      }
++
++      /* Control block & Descriptpor associated with the channel being worked on */
++      chNum = cd_p->channelNumber;
++      ccb_p = cd_p->ccb_ptr;
++
++      /* Is channel already in use ? */
++      if (ccb_p->baseBDptr != DMA_ADDR_INVALID) {
++              result = IAPI_ERR_BD_ALLOCATED | IAPI_ERR_CH_AVAILABLE | chNum;
++              iapi_errno = result;
++              return -result;
++      }
++
++      /* Allocation of buffer descriptors */
++      bd_p = MALLOC(sizeof(bufferDescriptor));
++      if (bd_p != NULL) {
++              ccb_p->baseBDptr = iapi_Virt2Phys(bd_p);
++      } else {
++              result = IAPI_ERR_BD_ALLOCATION | IAPI_ERR_CH_AVAILABLE | chNum;
++              iapi_errno = result;
++              return -result;
++      }
++
++      /* Buffer descriptor setting */
++      iapi_SetBufferDescriptor(bd_p, command, BD_WRAP | BD_DONE | BD_INTR,
++                              nbyte, buf, DMA_ADDR_INVALID);
++
++      /* Actually the transfer */
++      iapi_lowStartChannel(cd_p->channelNumber);
++      iapi_lowSynchChannel(cd_p->channelNumber);
++
++      /* Cleaning of allocation */
++      FREE(bd_p);
++      ccb_p->baseBDptr = DMA_ADDR_INVALID;
++
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/**Changes the interrupt Mask  (core specific register)
++ *
++ * Algorithm:
++ *   - Program value as per the passed in arguments to the core-specific Interrupt Mask Reg.
++ *
++ * @param
++ *   Value to be AND-ed or Or-ed with the interrupt Mask reg
++ * @op
++ *  Operation(AND or OR) to be performed on the Interrupt Mask Reg.
++ * @return
++ *   - IAPI_SUCCESS
++ *   - iapi_errno if failure
++ */
++int
++iapi_lowChangeIntrMask(unsigned int param, unsigned char op)
++{
++      switch (op) {
++      case OR_OP:
++              __raw_writel(__raw_readl(SDMA_H_INTRMSK) | param, SDMA_H_INTRMSK);
++              break;
++      case AND_OP:
++              __raw_writel(__raw_readl(SDMA_H_INTRMSK) & ~param, SDMA_H_INTRMSK);
++              break;
++      default:
++              iapi_errno = IAPI_ERR_NOT_ALLOWED;
++              return iapi_errno;
++      }
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/**Starts the channel (core specific register)
++ *
++ * <b>Algorithm:</b>\n
++ *   - Bit numbered "channel" of HostEnStartReg register is set
++ *
++ * @param channel channel to start
++ *
++ * @return none
++ */
++void
++iapi_lowStartChannel(unsigned char channel)
++{
++      DBG(0, "%s: %p: %08x->%08x\n", __FUNCTION__, SDMA_H_START,
++          __raw_readl(SDMA_H_START), __raw_readl(SDMA_H_START) | (1 << channel));
++      __raw_writel(__raw_readl(SDMA_H_START) | (1 << channel), SDMA_H_START);
++}
++
++/* ***************************************************************************/
++/**Stops the channel (core specific register)
++ *
++ * <b>Algorithm:</b>
++ *   - Bit numbered "channel" of HostEnStopReg register is cleared
++ *
++ * <b>Notes:</b>\n
++ *   - This is a write one to clear register
++ *
++ * @param channel channel to stop
++ *
++ * @return none
++ */
++void
++iapi_lowStopChannel(unsigned char channel)
++{
++      DBG(0, "%s: %p: %08x->%08x\n", __FUNCTION__, SDMA_H_STATSTOP,
++          __raw_readl(SDMA_H_STATSTOP), __raw_readl(SDMA_H_STATSTOP) & ~(1 << channel));
++      __raw_writel(1 << channel, SDMA_H_STATSTOP);
++}
++
++/* ***************************************************************************/
++/**Initialize the initial priority of registers and channel enable
++ * RAM from the MCU side. No channels are enabled, all priorities are set to 0.
++ *
++ * @return none
++ */
++void
++iapi_InitChannelTables(void)
++{
++      int i;
++
++      /* No channel is enabled */
++      for (i = 0; i < EVENTS_NUM; i++) {
++              __raw_writel(0, SDMA_CHNENBL_0 + (i << 2));
++      }
++      //iapi_memset((void *)&SDMA_CHNENBL_0, 0x00, sizeof(unsigned long) * EVENTS_NUM);
++
++      /* All channels have priority 0 */
++      for (i = 0; i < EVENTS_NUM; i++) {
++              __raw_writel(0, SDMA_CHNPRI_0 + (i << 2));
++      }
++      //iapi_memset((void *)&SDMA_CHNPRI_0, 0x00, sizeof(unsigned long) * CH_NUM);
++}
++
++/* ***************************************************************************/
++/** The host enable (HE), hosts override (HO), dsp enable (DE), dsp override
++ * (DO) registers are involved here.
++ * Host and Dsp enable registers are here to signify that the MCU or DSP side
++ * have prepared the appropriate buffers and are now ready. If the channel is
++ * owned by the MCU the override bit for that channel needs to be cleared :
++ * the host allows the channel to be used.\n
++ *
++ * Then the override bits can define (mcuOverride dspOverride):\n
++ *  - 0 0 channel is public: transfer to/from MCU to DSP
++ *  - 0 1 channel if owned by DSP
++ *  - 1 0 channel if owned by MCU
++ *  - 1 1 channel zero config
++ *
++ * See also :\n
++ *  IAPI Table 1.1 "Channel configuration properties"
++ *
++ * @param channel channel to configure
++ * @param eventOverride event ownership
++ * @param mcuOverride ARM ownership
++ * @param dspOverride DSP ownership
++ *
++ * @return
++ *   - -iapi_errno if the 3 override parameters are all set
++ *   - IAPI_SUCCESS in other cases (valid cases)
++ */
++int
++iapi_ChannelConfig(unsigned char channel, unsigned eventOverride,
++                 unsigned mcuOverride, unsigned dspOverride)
++{
++      int result = IAPI_SUCCESS;
++
++      if (eventOverride &&
++              mcuOverride &&
++              dspOverride) {
++              result = IAPI_ERR_CONFIG_OVERRIDE;
++              iapi_errno = result;
++              return -result;
++      } else {
++              /*
++               * DSP side
++               */
++              if (dspOverride) {
++                      __raw_writel(__raw_readl(SDMA_H_DSPOVR) &
++                                   ~(1 << channel), SDMA_H_DSPOVR);
++              } else {
++                      __raw_writel(__raw_readl(SDMA_H_DSPOVR) |
++                                   (1 << channel), SDMA_H_DSPOVR);
++              }
++              /*
++               * Event
++               */
++              if (eventOverride) {
++                      __raw_writel(__raw_readl(SDMA_H_EVTOVR) &
++                                   ~(1 << channel), SDMA_H_EVTOVR);
++              } else {
++                      __raw_writel(__raw_readl(SDMA_H_EVTOVR) |
++                                   (1 << channel), SDMA_H_EVTOVR);
++              }
++              /*
++               * MCU side
++               */
++              if  (mcuOverride) {
++                      __raw_writel(__raw_readl(SDMA_H_HOSTOVR) &
++                                   ~(1 << channel), SDMA_H_HOSTOVR);
++              } else {
++                      __raw_writel(__raw_readl(SDMA_H_HOSTOVR) |
++                                   (1 << channel), SDMA_H_HOSTOVR);
++              }
++      }
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/**Load the context data of a channel from SDMA
++ *
++ * <b>Algorithm:</b>\n
++ *    - Setup BD with appropiate parameters
++ *    - Start channel
++ *    - Poll for answer
++ *
++ * @param *cd_p  channel descriptor for channel 0
++ * @param *buf pointer to receive context data
++ * @param channel channel for which the context data is requested
++ *
++ * @return none
++ */
++void
++iapi_lowGetContext(channelDescriptor *cd_p, void *buf, unsigned char channel)
++{
++      bufferDescriptor *bd_p;
++
++      bd_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++
++      /* Setup buffer descriptor with channel 0 command */
++      iapi_SetBufferDescriptor(&bd_p[0],
++                              C0_GETDM,
++                              BD_DONE | BD_INTR | BD_WRAP | BD_EXTD,
++                              sizeof(contextData) / 4,
++                              buf,
++                              CHANNEL_CONTEXT_BASE_ADDRESS + sizeof(contextData) * channel / 4);
++      /* Receive, polling method */
++      iapi_lowStartChannel(cd_p->channelNumber);
++      iapi_lowSynchChannel(cd_p->channelNumber);
++}
++
++/* ***************************************************************************/
++/**Read "size" byte /2 at SDMA address (address) and write them in buf
++ *
++ * <b>Algorithm:</b>\n
++ *    - Setup BD with appropiate parameters (C0_GETPM)
++ *    - Start channel
++ *    - Poll for answer
++ *
++ * <b>Notes</b>\n
++ *   - Parameter "size" is in bytes, it represents the size of "buf", e.g.
++ * the size in bytes of the script to be loaded.
++ *   - Parameter "address" denotes the RAM address for the script in SDMA
++ *
++ * @param *cd_p  channel descriptor for channel 0
++ * @param *buf pointer to receive the data
++ * @param size number of bytes to read
++ * @param address address in SDMA RAM to start reading from
++ *
++ * @return none
++ */
++void
++iapi_lowGetScript(channelDescriptor *cd_p, void *buf, unsigned short size,
++              dma_addr_t address)
++{
++      bufferDescriptor *bd_p;
++
++      bd_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++
++      /* Setup buffer descriptor with channel 0 command */
++      iapi_SetBufferDescriptor(&bd_p[0],
++                              C0_GETPM,
++                              BD_DONE | BD_INTR | BD_WRAP | BD_EXTD,
++                              size / 2, /* count in shorts */
++                              buf,
++                              address);
++      /* Receive, polling method*/
++      iapi_lowStartChannel(cd_p->channelNumber);
++      iapi_lowSynchChannel(cd_p->channelNumber);
++}
++
++/* ***************************************************************************/
++/**Load a SDMA script to SDMA
++ *
++ * <b>Algorithm:</b>\n
++ *    - Setup BD with appropiate parameters (C0_SETPM)
++ *    - Start channel
++ *    - Poll for answer
++ *
++ * <b>Notes</b>\b
++ *    - Parameter "size" is in bytes, it represents the size of "buf", e.g.
++ *  the size in bytes of the script to be uploaded.
++ *    - Parameter "address" denotes the RAM address for the script in SDMA
++ *
++ * @param *cd_p  channel descriptor for channel 0
++ * @param *buf pointer to the script
++ * @param size size of the script, in bytes
++ * @param address address in SDMA RAM to place the script
++ *
++ * @return none
++ */
++void
++iapi_lowSetScript(channelDescriptor *cd_p, void *buf, unsigned short size,
++              dma_addr_t address)
++{
++      bufferDescriptor *bd_p;
++
++      bd_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++
++      /* Setup buffer descriptor with channel 0 command */
++      iapi_SetBufferDescriptor(&bd_p[0],
++                              C0_SETPM,
++                              BD_DONE | BD_INTR | BD_WRAP | BD_EXTD,
++                              size / 2, /* count in  shorts */
++                              buf,
++                              address);
++      /* Receive, polling method*/
++      iapi_lowStartChannel(cd_p->channelNumber);
++      iapi_lowSynchChannel(cd_p->channelNumber);
++}
++
++/* ***************************************************************************/
++/**Load the context for a channel to SDMA
++ *
++ * <b>Algorithm:</b>\n
++ *   - Send context and poll for answer.
++ *
++ * @param *cd_p  channel descriptor for channel 0
++ * @param *buf pointer to context data
++ * @param channel channel to place the context for
++ *
++ * @return none
++ */
++void
++iapi_lowSetContext(channelDescriptor *cd_p, void *buf, unsigned char channel)
++{
++
++      bufferDescriptor *local_bd_p;
++#ifdef SDMA_V2
++      local_bd_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++
++      iapi_SetBufferDescriptor(&local_bd_p[0],
++                              (channel << 3) | C0_SETCTX,
++                              BD_DONE | BD_INTR | BD_WRAP,
++                              sizeof(contextData) / 4,
++                              buf,
++                              DMA_ADDR_INVALID);
++#else
++
++      local_bd_p = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++
++      iapi_SetBufferDescriptor(&local_bd_p[0],
++                              C0_SETDM,
++                              BD_DONE | BD_INTR | BD_WRAP | BD_EXTD,
++                              sizeof(contextData) / 4,
++                              buf,
++                              (2048 + (sizeof(contextData) / 4) * channel));
++#endif
++      /* Send */
++      iapi_lowStartChannel(cd_p->channelNumber);
++      iapi_lowSynchChannel(cd_p->channelNumber);
++}
++
++/* ***************************************************************************/
++/**Associate specified channel with the script starting at the
++ * specified address. Channel 0 command is used to load the set-up context
++ * for the channel. The address used must be generated by the GUI tool
++ * used to create RAM images for SDMA.
++ *
++ * <b>Algorithm:</b>\n
++ *    - Set-up and load the context.
++ *
++ *  @param *cd_p  pointer to the channel descriptor of the channel
++ *  @param *data_p: pointer to the data identifying the script to be associated
++ *          with the channel
++ *
++ * @return
++ *     - IAPI_SUCCESS : OK
++ *     - -iapi_errno : operation failed, return negated value of iapi_errno
++ */
++
++int
++iapi_lowAssignScript(channelDescriptor *cd_p, script_data *data_p)
++{
++      contextData *chContext;    /* context to be loaded for the channel */
++      channelDescriptor *cd0_p;  /* pointer to channel descriptor of channel 0 */
++      int result = IAPI_SUCCESS;
++
++      /* Verify passed data */
++      if (cd_p == NULL || data_p == NULL) {
++              result = IAPI_ERR_INVALID_PARAMETER;
++              iapi_errno = result;
++              return -result;
++      }
++
++      /* Allocate context and initialize PC to required script start adress*/
++      chContext = MALLOC(sizeof(contextData));
++      if (chContext == NULL) {
++              result = IAPI_ERR_B_ALLOC_FAILED | cd_p->channelNumber;
++              iapi_errno = result;
++              return -result;
++      }
++
++      iapi_memset(chContext, 0x00, sizeof(contextData));
++      chContext->channelState.pc = data_p->load_address;
++
++      /* Send by context the event mask,base address for peripheral
++       * and watermark level
++       */
++      chContext->gReg[0] = data_p->event_mask2;
++      chContext->gReg[1] = data_p->event_mask1;
++      chContext->gReg[6] = data_p->shp_addr;
++      chContext->gReg[7] = data_p->wml;
++
++      /* Set transmited data to the CD */
++      cd_p->watermarkLevel = data_p->wml;
++      cd_p->eventMask1 = data_p->event_mask1;
++      cd_p->eventMask2 = data_p->event_mask2;
++
++      /* Get the cd0_p */
++      cd0_p = (cd_p->ccb_ptr - cd_p->channelNumber)->channelDescriptor;
++
++      /*load the context*/
++      iapi_lowSetContext(cd0_p, chContext, cd_p->channelNumber);
++
++      /* release allocated memory */
++      FREE(chContext);
++
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/**  Set the channels to be triggered by an event. The for every channel that
++ *must be triggered by the event, the corresponding bit from channel_map
++ *parameter must be set to 1. (e.g. for the event to trigger channels 31 and
++ *0 one must pass 0x80000001)
++ *
++ *
++ * <b>Algorithm:</b>\n
++ *   - Update the register from Channel Enable RAM with the channel_map
++ *
++ * @param event event for which to set the channel association
++ * @param channel_map channels to be triggered by event. Put the corresponding
++ *          bit from this 32-bit value to 1 for every channel that should be
++ *          triggered by the event.
++ *
++ * @return
++ *     - IAPI_SUCCESS : OK
++ *     - -iapi_errno : operation failed, return negated value of iapi_errno
++ */
++int
++iapi_lowSetChannelEventMapping(unsigned char event, unsigned long channel_map)
++{
++      /* Check validity of event*/
++      if (event < EVENTS_NUM) {
++              __raw_writel(channel_map, SDMA_CHNENBL(event));
++      } else {
++              iapi_errno = IAPI_ERR_INVALID_PARAMETER | event;
++              return -iapi_errno;
++      }
++      return IAPI_SUCCESS;
++}
++
++#endif /* MCU */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddle.c linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddle.c
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddle.c  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddle.c  2010-12-03 09:51:55.408346904 +0100
+@@ -0,0 +1,577 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiMiddle.c
++ *
++ * $Id iapiMiddle.c $
++ *
++ * Description:
++ *  This library is written in C to guarantee functionality and integrity in
++ * the usage of SDMA virtual DMA channels. This API (Application Programming
++ * Interface)  allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
++ * fashion.
++ *  These are the MIDDLE level functions of the I.API.
++ *
++ *
++ *
++ *
++ * $Log iapiMiddle.c $
++ *
++ *****************************************************************************/
++
++
++/* ****************************************************************************
++ * Include File Section
++ *****************************************************************************/
++#include <string.h>
++#include <linux/io.h>
++
++#include <epm.h>
++#include <iapiLow.h>
++#include <iapiMiddle.h>
++
++/* ****************************************************************************
++ * Global Variable Section
++ *****************************************************************************/
++
++
++/* ****************************************************************************
++ * Function Section
++ *****************************************************************************/
++
++/* ***************************************************************************/
++/**Allocates one Buffer Descriptor structure using information present in the
++ * channel descriptor.
++ *
++ * @param *ccb_p channel control block used to get the channel descriptor
++ *
++ * @return
++ *       - pointer on the new Buffer Descriptor
++ *       - NULL if allocation failed
++ *
++ */
++bufferDescriptor *
++iapi_AllocBD(channelControlBlock *ccb_p)
++{
++      bufferDescriptor *ptrBD = NULL;
++      int num_desc = ccb_p->channelDescriptor->bufferDescNumber;
++
++      if (num_desc == 0)
++              return NULL;
++
++      ptrBD = MALLOC(num_desc * sizeof(bufferDescriptor));
++      if (ptrBD == NULL) {
++              DBG(0, "%s: Failed to allocate %u byte for %u BDs\n",
++                      __FUNCTION__,
++                      num_desc * sizeof(bufferDescriptor),
++                      num_desc);
++              return NULL;
++      }
++      ptrBD->mode.command = 0;
++      ptrBD->mode.status = 0;
++      ptrBD->mode.count = 0;
++      ptrBD->bufferAddr = DMA_ADDR_INVALID;
++
++      return ptrBD;
++}
++
++/* ***************************************************************************/
++/**Allocate one channel context data structure.
++ *
++ * @param **ctxd_p  pointer to context data to be allocated
++ * @param channel channel number of context data structure
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ *     - -iapi_errno if allocation failed
++ */
++int
++iapi_AllocContext(contextData **ctxd_p, unsigned char channel)
++{
++      if (*ctxd_p != NULL) {
++              iapi_errno = IAPI_ERR_CC_ALREADY_DEFINED |
++                      IAPI_ERR_CH_AVAILABLE | channel;
++              return -iapi_errno;
++      }
++
++      *ctxd_p = MALLOC(sizeof(contextData));
++      if (*ctxd_p == NULL) {
++              iapi_errno = IAPI_ERR_CC_ALLOC_FAILED |
++                      IAPI_ERR_CH_AVAILABLE | channel;
++              return -iapi_errno;
++      }
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/**Allocates channel description and fill in with default values.
++ *
++ * <b>Algorithm:</b>\n
++ *  - Check channel properties.
++ *  - Then modifies the properties of the channel description with default
++ *
++ * @param **cd_p  pointer to channel descriptor to be allocated
++ * @param channel channel number of channel descriptor
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ *     - -iapi_errno if allocation failed
++ *
++ */
++int
++iapi_AllocChannelDesc(channelDescriptor **cd_p, unsigned char channel)
++{
++      unsigned int pri;
++
++      if (*cd_p != NULL) {
++              iapi_errno = IAPI_ERR_CD_ALREADY_DEFINED |
++                      IAPI_ERR_CH_AVAILABLE | channel;
++              return -iapi_errno;
++      }
++
++      *cd_p = MALLOC(sizeof(channelDescriptor));
++      if (*cd_p == NULL) {
++              iapi_errno = IAPI_ERR_CD_ALLOC_FAILED |
++                      IAPI_ERR_CH_AVAILABLE | channel;
++              return -iapi_errno;
++      }
++
++      iapi_memcpy(*cd_p, &iapi_ChannelDefaults, sizeof(channelDescriptor));
++      (*cd_p)->channelNumber = channel;
++#ifdef MCU
++      pri = __raw_readl(SDMA_CHNPRI(channel));
++      if (pri != 0) {
++              (*cd_p)->priority = pri;
++      } else {
++              __raw_writel((*cd_p)->priority, SDMA_CHNPRI(channel));
++      }
++#endif
++      return IAPI_SUCCESS;
++}
++
++/* ***************************************************************************/
++/**Changes channel description information after performing sanity checks.
++ *
++ * <b>Algorithm:</b>\n
++ *    - Check channel properties.
++ *    - Then modifies the properties of the channel description.
++ *
++ * @param *cd_p channel descriptor of the channel to change
++ * @param whatToChange control code indicating the desired change
++ * @param newval new value
++ *
++ * @return
++ *     - IAPI_SUCCESS
++ *     - IAPI_FAILURE if change failed
++ *
++ */
++int
++iapi_ChangeChannelDesc(channelDescriptor *cd_p, unsigned char whatToChange,
++              unsigned long newval)
++{
++      bufferDescriptor *tmpBDptr;
++      unsigned int index;
++
++      DBG(0, "%s: channel %d what=%08x newval=%08lx\n", __FUNCTION__,
++              cd_p->channelNumber, whatToChange, newval);
++      /* verify parameter validity */
++      if (cd_p == NULL) {
++              iapi_errno = IAPI_ERR_CD_UNINITIALIZED;
++              return -iapi_errno;
++      }
++
++      /* verify channel descriptor initialization */
++      if (cd_p->ccb_ptr == NULL) {
++              iapi_errno = IAPI_ERR_CCB_UNINITIALIZED | IAPI_ERR_CH_AVAILABLE |
++                      cd_p->channelNumber;
++              return -iapi_errno;
++      }
++
++      /* verify channel is not in use */
++      if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++              tmpBDptr = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++              for (index = cd_p->bufferDescNumber; index > 0; index--) {
++                      if (tmpBDptr->mode.status & BD_DONE) {
++                              iapi_errno = IAPI_ERR_CH_IN_USE | IAPI_ERR_CH_AVAILABLE |
++                                      cd_p->channelNumber;
++                              return -iapi_errno;
++                      }
++                      tmpBDptr++;
++              }
++      }
++
++      /* Select the change accorded to the selector given in parameter */
++      switch (whatToChange) {
++      case IAPI_CHANNELNUMBER:
++              /*
++               * Channel Number
++               */
++              /* Channel number can not be changed (description remains attached) */
++              iapi_errno = IAPI_ERR_CD_CHANGE_CH_NUMBER |
++                      IAPI_ERR_CH_AVAILABLE |
++                      cd_p->channelNumber;
++              return -iapi_errno;
++
++      case IAPI_BUFFERDESCNUMBER:
++              /*
++               * Buffer Descriptor Number
++               */
++              if (newval >= MAX_BD_NUM) {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER |
++                              IAPI_ERR_CH_AVAILABLE |
++                              cd_p->channelNumber;
++                      return -iapi_errno;
++              }
++              if (newval == cd_p->bufferDescNumber) {
++                      break;
++              }
++              /* Free memory used for previous data */
++              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                      tmpBDptr = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                      for (index = 0; index < cd_p->bufferDescNumber; index++) {
++                              if (tmpBDptr->bufferAddr != DMA_ADDR_INVALID) {
++                                      if (cd_p->trust == FALSE) {
++                                              FREE(iapi_Phys2Virt(tmpBDptr->bufferAddr));
++                                      }
++                              }
++                              tmpBDptr++;
++                      }
++                      FREE(iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr));
++                      cd_p->ccb_ptr->baseBDptr = DMA_ADDR_INVALID;
++                      cd_p->ccb_ptr->currentBDptr = DMA_ADDR_INVALID;
++              }
++              /* Allocate and initialize structures */
++              cd_p->bufferDescNumber = newval;
++              cd_p->ccb_ptr->status.openedInit = FALSE;
++              if (IAPI_SUCCESS != iapi_InitializeMemory(cd_p->ccb_ptr)) {
++                      iapi_errno = IAPI_ERR_BD_ALLOCATION | cd_p->channelNumber;
++                      return -iapi_errno;
++              }
++              cd_p->ccb_ptr->status.openedInit = TRUE;
++              break;
++
++      case IAPI_BUFFERSIZE:
++              /*
++               * Buffer size
++               */
++              if (newval < MAX_BD_SIZE) {
++                      if (newval != cd_p->bufferSize) {
++                              /* Free memory used for previous old data */
++                              if (cd_p->ccb_ptr->baseBDptr != DMA_ADDR_INVALID) {
++                                      tmpBDptr = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++                                      for (index = 0; index < cd_p->bufferDescNumber; index++) {
++                                              if (cd_p->trust == FALSE) {
++                                                      FREE(iapi_Phys2Virt(tmpBDptr->bufferAddr));
++                                              }
++                                              tmpBDptr++;
++                                      }
++                                      FREE(iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr));
++                              }
++                              cd_p->ccb_ptr->baseBDptr = DMA_ADDR_INVALID;
++                              cd_p->ccb_ptr->currentBDptr = DMA_ADDR_INVALID;
++                              /* Allocate and initialize structures */
++                              cd_p->bufferSize = newval;
++                              cd_p->ccb_ptr->status.openedInit = FALSE;
++                              if (IAPI_SUCCESS != iapi_InitializeMemory(cd_p->ccb_ptr)) {
++                                      iapi_errno = IAPI_ERR_BD_ALLOCATION | cd_p->channelNumber;
++                                      return -iapi_errno;
++                              }
++                              cd_p->ccb_ptr->status.openedInit = TRUE;
++                      }
++                      break;
++              } else {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
++                              cd_p->channelNumber;
++                      return -iapi_errno;
++              }
++
++      case IAPI_BLOCKING:
++              /*
++               * Blocking / non blocking feature
++               */
++              if (newval < MAX_BLOCKING) {
++                      cd_p->blocking = newval;
++                      break;
++              } else {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
++                              cd_p->channelNumber;
++                      return -iapi_errno;
++              }
++
++      case IAPI_CALLBACKSYNCH:
++              /*
++               * Synchronization method
++               */
++              if (newval < MAX_SYNCH) {
++                      cd_p->callbackSynch = newval;
++                      iapi_ChangeCallbackISR( cd_p, cd_p->callbackISR_ptr);
++                      break;
++              } else {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
++                              cd_p->channelNumber;
++                      return -iapi_errno;
++              }
++
++      case IAPI_OWNERSHIP:
++              /*
++               *  Ownership of the channel
++               */
++#ifdef DSP
++              iapi_errno = IAPI_ERR_NOT_ALLOWED | cd_p->channelNumber;
++              return -iapi_errno;
++#endif /* DSP */
++#ifdef MCU
++              if (newval < MAX_OWNERSHIP) {
++                      cd_p->ownership = newval;
++                      iapi_ChannelConfig(cd_p->channelNumber,
++                                      (newval >> CH_OWNSHP_OFFSET_EVT) & 1,
++                                      (newval >> CH_OWNSHP_OFFSET_MCU) & 1,
++                                      (newval >> CH_OWNSHP_OFFSET_DSP) & 1);
++                      break;
++              } else {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
++                              cd_p->channelNumber;
++                      return -iapi_errno;
++              }
++#endif /* MCU */
++      case IAPI_PRIORITY:
++              /*
++               * Priority
++               */
++#ifdef DSP
++              iapi_errno = IAPI_ERR_NOT_ALLOWED | cd_p->channelNumber;
++              return -iapi_errno;
++#endif /* DSP */
++
++#ifdef MCU
++              if (newval < MAX_CH_PRIORITY) {
++#if 1
++                      __raw_writel(newval, SDMA_CHNPRI(cd_p->channelNumber));
++#else
++                      volatile unsigned long *ChannelPriorities = &SDMA_CHNPRI_0;
++                      ChannelPriorities[cd_p->channelNumber] = newval;
++#endif
++                      break;
++              } else {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
++                              cd_p->channelNumber;
++                      return -iapi_errno;
++              }
++#endif /* MCU */
++      case IAPI_TRUST:
++              /*
++               * "Trust" property
++               */
++              if (newval < MAX_TRUST) {
++                      if (cd_p->trust != newval) {
++                              cd_p->trust = newval;
++                              if (newval == FALSE) {
++                                      if (IAPI_SUCCESS !=iapi_InitializeMemory(cd_p->ccb_ptr)) {
++                                              iapi_errno = IAPI_ERR_BD_ALLOCATION | cd_p->channelNumber;
++                                              return -iapi_errno;
++                                      }
++                              }
++                      }
++                      break;
++              } else {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER | IAPI_ERR_CH_AVAILABLE |
++                              cd_p->channelNumber;
++                      return -iapi_errno;
++              }
++
++      case IAPI_CALLBACKISR_PTR:
++              /*
++               * Callback function pointer
++               */
++              if ((void *)newval != NULL) {
++                      cd_p->callbackISR_ptr = (void *)newval;
++                      iapi_ChangeCallbackISR( cd_p, cd_p->callbackISR_ptr);
++              } else {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER |
++                              IAPI_ERR_CH_AVAILABLE |
++                              cd_p->channelNumber;
++                      return -iapi_errno;
++              }
++              break;
++
++      case IAPI_CCB_PTR:
++              /*
++               * Channel Control Block pointer
++               */
++              cd_p->ccb_ptr = (channelControlBlock *)newval;
++              cd_p->ccb_ptr->channelDescriptor = cd_p;
++              break;
++
++      case IAPI_BDWRAP:
++              /*
++               * WRAP/UNWRAP
++               */
++              /* pointer to first BD */
++              tmpBDptr = iapi_Phys2Virt(cd_p->ccb_ptr->baseBDptr);
++              /* pointer to last BD */
++              tmpBDptr += cd_p->bufferDescNumber - 1;
++              DBG(0, "%s: newval=%08lx\n", __FUNCTION__, newval);
++              if (newval == TRUE) {
++                      /* wrap last BD */
++                      DBG(0, "%s: Setting BD_WRAP for channel %d BD[%d/%d]\n",
++                              __FUNCTION__, cd_p->channelNumber,
++                              cd_p->bufferDescNumber - 1,
++                              cd_p->bufferDescNumber);
++                      tmpBDptr->mode.status |= BD_WRAP;
++              } else if (newval == FALSE) {
++                      /* unwrap last BD */
++                      DBG(0, "%s: Clearing BD_WRAP for channel %d BD[%d/%d]\n",
++                              __FUNCTION__, cd_p->channelNumber,
++                              cd_p->bufferDescNumber - 1,
++                              cd_p->bufferDescNumber);
++                      tmpBDptr->mode.status &= ~BD_WRAP;
++              } else {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER |
++                              IAPI_ERR_CH_AVAILABLE |
++                              cd_p->channelNumber;
++                      return -iapi_errno;
++              }
++              break;
++
++      case IAPI_WML:
++              /*
++               * Watermark level
++               */
++#ifdef DSP
++              iapi_errno = IAPI_ERR_NOT_ALLOWED | cd_p->channelNumber;
++              return -iapi_errno;
++#endif /* DSP */
++#ifdef MCU
++              if (newval >= MAX_WML) {
++                      iapi_errno = IAPI_ERR_INVALID_PARAMETER |
++                              IAPI_ERR_CH_AVAILABLE |
++                              cd_p->channelNumber;
++                      return -iapi_errno;
++              }
++              if (cd_p->watermarkLevel != newval) {
++                      cd_p->watermarkLevel = newval;
++              }
++              break;
++#endif /* MCU */
++      default:
++              /*
++               * Detect errors
++               */
++              iapi_errno = IAPI_ERR_CD_CHANGE_UNKNOWN |
++                      IAPI_ERR_CH_AVAILABLE |
++                      cd_p->channelNumber;
++              return -iapi_errno;
++      }
++      return IAPI_SUCCESS;
++}
++
++
++/* ***************************************************************************/
++/**Initialize a table of function pointers that contain the interrupt Service
++ * Routine callback pointers for the SDMA channels with a default value
++ *
++ * <b>Algorithm:</b>\n
++ *    - Loop on each element of the global IAPI variable callbackIsrTable
++ *
++ * @param *func_p default callback functon for all SDMA channels
++ *
++ * @return none
++ */
++void
++iapi_InitializeCallbackISR(void(* func_p)(channelDescriptor *cd_p, void *arg))
++{
++      unsigned long chCnt;
++
++      for (chCnt = 0; chCnt < CH_NUM; chCnt++) {
++              callbackIsrTable[chCnt] = func_p;
++      }
++}
++
++/* ***************************************************************************/
++/**For the specified  channel control block, attach the array of buffer
++ * descriptors, the channel description structure and initialize channel's
++ * status using information in the channel descriptor.
++ *
++ * @param *ccb_p pointer to channel control block
++ *
++ * @return none
++ *
++ */
++int
++iapi_InitializeMemory(channelControlBlock *ccb_p)
++{
++      bufferDescriptor *bd_p;
++      unsigned int index;
++      channelDescriptor *cd_p = ccb_p->channelDescriptor;
++
++      /* Attach the array of Buffer descriptors */
++      bd_p = iapi_AllocBD(ccb_p);
++      if (bd_p == NULL)
++              return -IAPI_ERR_BD_ALLOCATION;
++
++      ccb_p->baseBDptr = iapi_Virt2Phys(bd_p);
++      ccb_p->currentBDptr = ccb_p->baseBDptr;
++      DBG(0, "%s: BDptr[%p] of ccb %p set to %08x\n", __FUNCTION__,
++              &ccb_p->baseBDptr, ccb_p, ccb_p->baseBDptr);
++      for (index = 0; index < cd_p->bufferDescNumber - 1; index++) {
++              if (cd_p->trust == TRUE) {
++                      iapi_SetBufferDescriptor(bd_p,
++                                              cd_p->dataSize,
++                                              BD_CONT | BD_EXTD, cd_p->bufferSize,
++                                              NULL, DMA_ADDR_INVALID);
++              } else {
++                      if (cd_p->bufferSize != 0) {
++                              void *buf = MALLOC(cd_p->bufferSize);
++
++                              if (buf == NULL)
++                                      goto cleanup;
++
++                              iapi_SetBufferDescriptor(bd_p,
++                                                      cd_p->dataSize,
++                                                      BD_CONT | BD_EXTD,
++                                                      cd_p->bufferSize,
++                                                      buf, DMA_ADDR_INVALID);
++                      }
++              }
++              bd_p++;
++      }
++
++      if (cd_p->trust == TRUE) {
++              iapi_SetBufferDescriptor(bd_p,
++                                      cd_p->dataSize,
++                                      BD_EXTD | BD_WRAP | BD_INTR,
++                                      cd_p->bufferSize,
++                                      NULL, DMA_ADDR_INVALID);
++      } else {
++              if (cd_p->bufferSize != 0) {
++                      void *buf = MALLOC(cd_p->bufferSize);
++
++                      if (buf == NULL)
++                              goto cleanup;
++
++                      iapi_SetBufferDescriptor(bd_p,
++                                              cd_p->dataSize,
++                                              BD_EXTD | BD_WRAP | BD_INTR,
++                                              cd_p->bufferSize,
++                                              buf,
++                                              DMA_ADDR_INVALID);
++              }
++      }
++      return IAPI_SUCCESS;
++cleanup:
++      WARN_ON(1);
++      while (--index >= 0) {
++              
++      }
++}
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddleMcu.c linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddleMcu.c
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddleMcu.c       1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiMiddleMcu.c       2010-12-03 09:51:55.408346904 +0100
+@@ -0,0 +1,52 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiMiddleMcu.c
++ *
++ * $Id iapiMiddleMcu.c $
++ *
++ * Description:
++ *  This library is written in C to guarantee functionality and integrity in
++ * the usage of SDMA virtual DMA channels. This API (Application Programming
++ * Interface)  allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
++ * fashion.
++ *  These are the MIDDLE level functions of the I.API specific to MCU.
++ *
++ *
++ *
++ *
++ * $Log iapiMiddleMcu.c $
++ *
++ *****************************************************************************/
++
++/* ****************************************************************************
++ * Include File Section
++ *****************************************************************************/
++#include <epm.h>
++#include <string.h>
++
++#include <iapiLow.h>
++#include <iapiMiddle.h>
++
++/* ****************************************************************************
++ * Global Variable Section
++ *****************************************************************************/
++
++/*extern void * __HEAP_START;
++extern void * __HEAP_END;
++*/
++
++/* ****************************************************************************
++ * Function Section
++ *****************************************************************************/
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiOS.c linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiOS.c
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/iapiOS.c      1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/iapiOS.c      2010-12-03 09:51:55.408346904 +0100
+@@ -0,0 +1,64 @@
++/******************************************************************************
++ *
++ * Copyright 2007 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: iapiOS.c
++ *
++ * $Id iapiOS.c $
++ *
++ * Description:
++ *  This library is written in C to guarantee functionality and integrity in
++ * the usage of SDMA virtual DMA channels. This API (Application Programming
++ * Interface)  allow SDMA channels' access in an OPEN, READ, WRITE, CLOSE
++ * fashion.
++ *  These are the OS level functions of the I.API - are OS dependant and must
++ * be provided by the user of I.API.
++ *
++ *
++ * /
++ *
++ * $Log iapiOS.c $
++ *
++ *****************************************************************************/
++
++/* ****************************************************************************
++ * Include File Section
++ *****************************************************************************/
++#include <epm.h>
++#include <iapi.h>
++
++/**
++ * Function Section
++ */
++#ifdef CONFIG_SDMA_IRAM
++void* (*iapi_iram_Malloc)(size_t size);
++#endif /*CONFIG_SDMA_IRAM*/
++
++void* (*iapi_Malloc)(size_t size);
++void (*iapi_Free)(void *ptr);
++
++dma_addr_t (*iapi_Virt2Phys) (void *ptr);
++void* (*iapi_Phys2Virt) (dma_addr_t ptr);
++
++void (*iapi_WakeUp)(int);
++void (*iapi_GotoSleep)(int);
++void (*iapi_InitSleep)(int);
++
++void* (*iapi_memcpy)(void *dest, const void *src, size_t count);
++void* (*iapi_memset)(void *dest, int c, size_t count);
++
++void (*iapi_EnableInterrupts)(void);
++void (*iapi_DisableInterrupts)(void);
++
++int (*iapi_GetChannel)(int);
++int (*iapi_ReleaseChannel)(int);
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/Makefile linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/Makefile
+--- linux.35.old/arch/arm/plat-mxc/sdma/iapi/src/Makefile      1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/iapi/src/Makefile      2010-12-03 09:51:55.412348386 +0100
+@@ -0,0 +1,20 @@
++#
++# Makefile for I.API sources.
++#
++
++ifneq ($(KBUILD_SRC),)
++ccflags-y += -I$(KBUILD_SRC)/arch/arm/plat-mxc/sdma/iapi/include \
++                -I$(KBUILD_SRC)/include/linux \
++                -DMCU -DOS=LINUX \
++                -DL_I_T_T_L_E_ENDIAN=0 -DB_I_G_ENDIAN=1 \
++                -DENDIANNESS=L_I_T_T_L_E_ENDIAN
++else
++ccflags-y += -Iarch/arm/plat-mxc/sdma/iapi/include \
++                -Iinclude/linux \
++                -DMCU -DOS=LINUX \
++                -DL_I_T_T_L_E_ENDIAN=0 -DB_I_G_ENDIAN=1 \
++                -DENDIANNESS=L_I_T_T_L_E_ENDIAN
++endif
++
++#obj-y        += iapiLow.o iapiLowMcu.o iapiMiddle.o iapiMiddleMcu.o iapiHigh.o iapiDefaults.o iapiOS.o
++obj-y += iapiLow.o iapiLowMcu.o iapiMiddle.o iapiHigh.o iapiDefaults.o iapiOS.o
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/Makefile linux.35.new/arch/arm/plat-mxc/sdma/Makefile
+--- linux.35.old/arch/arm/plat-mxc/sdma/Makefile       1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/Makefile       2010-12-03 09:51:55.412348386 +0100
+@@ -0,0 +1,18 @@
++ifneq ($(KBUILD_SRC),)
++ccflags-y += -I$(KBUILD_SRC)/arch/arm/plat-mxc/sdma/iapi/include \
++                -I$(KBUILD_SRC)/include/linux \
++                -DMCU -DOS=LINUX \
++                -DL_I_T_T_L_E_ENDIAN=0 -DB_I_G_ENDIAN=1 \
++                -DENDIANNESS=L_I_T_T_L_E_ENDIAN
++else
++ccflags-y += -Iarch/arm/plat-mxc/sdma/iapi/include \
++                -Iinclude/linux \
++                -DMCU -DOS=LINUX \
++                -DL_I_T_T_L_E_ENDIAN=0 -DB_I_G_ENDIAN=1 \
++                -DENDIANNESS=L_I_T_T_L_E_ENDIAN
++endif
++
++obj-y += dma_sdma.o
++obj-$(CONFIG_MXC_SDMA_API)              += sdma.o
++obj-$(CONFIG_MXC_SDMA_API)              += iapi/
++obj-$(CONFIG_MXC_SDMA_API)              += sdma_malloc.o
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/sdma.c linux.35.new/arch/arm/plat-mxc/sdma/sdma.c
+--- linux.35.old/arch/arm/plat-mxc/sdma/sdma.c 1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/sdma.c 2010-12-03 09:51:55.416347546 +0100
+@@ -0,0 +1,1653 @@
++/*
++ * Copyright 2004-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 plat-mxc/sdma/sdma.c
++ * This file contains functions for Smart DMA  API
++ *
++ * SDMA (Smart DMA) is used for transferring data between MCU and peripherals
++ *
++ */
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/mm.h>
++#include <linux/interrupt.h>
++#include <linux/clk.h>
++#include <linux/semaphore.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/proc_fs.h>
++
++#include <asm/uaccess.h>
++#include <asm/irq.h>
++#include <mach/dma.h>
++#include <mach/hardware.h>
++
++#include <iapi.h>
++#include <epm.h>
++#include "sdma.h"
++
++#define M3_BASE_ADDRESS CSD0_BASE_ADDR
++#define CHAD(ch) sdma_data[0].cd->ccb_ptr[ch].channelDescriptor
++
++void __iomem *sdma_base_addr = NULL;
++
++/*
++ * SDMA status mutex
++ */
++static struct semaphore sdma_status_mutex;
++
++/*
++ * SDMA channel sleep queues
++ */
++//static struct semaphore sdma_sleep_mutex[MAX_DMA_CHANNELS];
++static wait_queue_head_t sdma_sleep_queue[MAX_DMA_CHANNELS];
++
++/*
++ * SDMA channel synchronization
++ */
++static struct semaphore sdma_synch_mutex[MAX_DMA_CHANNELS];
++
++struct clk *mxc_sdma_clk;
++
++/*
++ * Structure containing sdma channels information.
++ */
++typedef struct {
++      /* Channel number */
++      int channel;
++      /* Channel usage name */
++      int in_use;
++      /* Name of device using the channel */
++      char devicename[MAX_DEVNAME_LENGTH];
++      /* Transfer type. Needed for setting SDMA script */
++      sdma_transferT transfer_type;
++      /* Peripheral type. Needed for setting SDMA script */
++      sdma_periphT peripheral_type;
++      /* Watermark level of device's fifo */
++      __u32 watermark_level;
++      /* Peripheral event id */
++      int event_id;
++      /* Peripheral event id2 (for channels that use 2 events) */
++      int event_id2;
++      /* Running status (boolean)  */
++      int running;
++      /* buffer descriptors number */
++      int bd_number;
++      /*   callback function       */
++      dma_callback_t callback;
++      /*   callback argument       */
++      void *arg;
++      /* SDMA data access word size */
++      unsigned long word_size:8;
++      /* channel descriptor pointer */
++      channelDescriptor *cd;
++} sdma_struct;
++
++/*
++ * Used to save the status of channels.
++ */
++static sdma_struct sdma_data[MAX_DMA_CHANNELS];
++
++/*
++ * Stores the start address of the SDMA scripts
++ */
++static sdma_script_start_addrs sdma_script_addrs;
++
++extern void mxc_sdma_get_script_info(sdma_script_start_addrs *sdma_script_add);
++
++/*
++ * Init sleep mutex of the channel
++ *
++ * @param  channel  channel number
++ */
++static void sdma_init_sleep(int channel)
++{
++      init_waitqueue_head(&sdma_sleep_queue[channel]);
++}
++
++#ifdef DEBUG
++#define SHOW_REG(b, p, r)             __show_reg(b, p, r, #r)
++
++static inline void __show_reg(void __iomem *base, unsigned long phys,
++                      unsigned int reg, const char *name)
++{
++      DBG(0, "%-12s[%08lx]=%08x\n", name, phys + reg, __raw_readl(base + reg));
++}
++
++void dump_sdma_regs(void)
++{
++      unsigned int reg;
++
++      for (reg = 0; reg < 0x180; reg += 4) {
++              SHOW_REG(sdma_base_addr, SDMA_BASE_ADDR, reg);
++      }
++}
++#endif
++
++/*
++ * Puts channel to sleep
++ *
++ * @param  channel  channel number
++ */
++#include <linux/delay.h>
++
++static void sdma_sleep_channel(int channel)
++{
++      int ret;
++
++      DBG(1, "%s: Waiting for channel %d to drain\n",
++              __FUNCTION__, channel);
++      BUG_ON(irqs_disabled());
++
++      ret = wait_event_interruptible_timeout(sdma_sleep_queue[channel],
++                                      iapi_SDMAIntr & (1 << channel), HZ);
++      if (ret == 0 && !(iapi_SDMAIntr & (1 << channel))) {
++              DBG(-1, "%s: Wait for channel %d done timed out: %08lx\n",
++                      __FUNCTION__, channel, iapi_SDMAIntr);
++      } else if (ret < 0) {
++              DBG(-1, "%s: Wait for channel %d aborted: %08lx, %d\n",
++                      __FUNCTION__, channel, iapi_SDMAIntr, ret);
++      } else {
++              DBG(1, "%s: Wait for channel %d done finished after %u ticks: %08lx\n",
++                      __FUNCTION__, channel, HZ - ret, iapi_SDMAIntr);
++      }
++}
++
++/*
++ * Wake up channel from sleep
++ *
++ * @param  channel  channel number
++ */
++static void sdma_wakeup_channel(int channel)
++{
++      DBG(1, "%s: Waking up channel %d\n", __FUNCTION__, channel);
++      wake_up_interruptible(&sdma_sleep_queue[channel]);
++}
++
++/*
++ * Sdma interrupt handler routine.
++ * Calls channels callback function
++ *
++ * @param   irq    the interrupt number
++ * @param   dev_id driver private data
++ * @return the function returns \b IRQ_RETVAL(1) -  interrupt was handled
++ */
++static irqreturn_t sdma_int_handler(int irq, void *dev_id)
++{
++      DBG(2, "%s: IRQ %d\n", __FUNCTION__, irq);
++      IRQ_Handler();
++      DBG(2, "%s: Done\n", __FUNCTION__);
++      return IRQ_HANDLED;
++}
++
++/*
++ * I.API channel callback function
++ *
++ * @param   cd            channel descriptor structure
++ * @param   channel_data  SDMA struct of the current channel
++ */
++static void iapi_interrupt_callback(channelDescriptor *cd,
++                                  sdma_struct *channel_data)
++{
++      int channel;
++      dma_callback_t callback;
++      void *arg;
++
++      DBG(2, "%s: cd=%p\n", __FUNCTION__, cd);
++      channel = channel_data->channel;
++
++      channel_data->running = 0;
++
++      arg = channel_data->arg;
++
++      if (arg == NULL) {
++              arg = &channel;
++      }
++
++      callback = channel_data->callback;
++
++      if (callback != NULL) {
++              DBG(2, "%s: Calling %p\n", __FUNCTION__, callback);
++              callback(arg);
++      }
++}
++
++/*
++ * Returns pc of SDMA script according to peripheral and transfer type
++ *
++ * @param   peripheral_type   peripheral type
++ * @param   transfer_type     transfer type
++ *
++ * @return  PC of SDMA script
++*/
++static unsigned short sdma_get_pc(sdma_periphT peripheral_type,
++                                sdma_transferT transfer_type)
++{
++      int res = 0;
++
++      if (peripheral_type == MEMORY) {
++              switch (transfer_type) {
++              case emi_2_int:
++                      res = sdma_script_addrs.mxc_sdma_ap_2_ap_addr;
++                      break;
++              case emi_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_ap_2_ap_addr;
++                      break;
++              case int_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_ap_2_ap_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == DSP) {
++              switch (transfer_type) {
++              case emi_2_dsp:
++                      res = sdma_script_addrs.mxc_sdma_ap_2_bp_addr;
++                      break;
++              case dsp_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_bp_2_ap_addr;
++                      break;
++              case dsp_2_emi_loop:
++                      res =
++                          sdma_script_addrs.
++                          mxc_sdma_loopback_on_dsp_side_addr;
++                      break;
++              case emi_2_dsp_loop:
++                      res =
++                          sdma_script_addrs.mxc_sdma_mcu_interrupt_only_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == FIRI) {
++              switch (transfer_type) {
++              case per_2_int:
++                      res = sdma_script_addrs.mxc_sdma_firi_2_per_addr;
++                      break;
++              case per_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_firi_2_mcu_addr;
++                      break;
++              case int_2_per:
++                      res = sdma_script_addrs.mxc_sdma_per_2_firi_addr;
++                      break;
++              case emi_2_per:
++                      res = sdma_script_addrs.mxc_sdma_mcu_2_firi_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == UART) {
++              switch (transfer_type) {
++              case per_2_int:
++                      res = sdma_script_addrs.mxc_sdma_uart_2_per_addr;
++                      break;
++              case per_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_uart_2_mcu_addr;
++                      break;
++              case int_2_per:
++                      res = sdma_script_addrs.mxc_sdma_per_2_app_addr;
++                      break;
++              case emi_2_per:
++                      res = sdma_script_addrs.mxc_sdma_mcu_2_app_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == UART_SP) {
++              switch (transfer_type) {
++              case per_2_int:
++                      res = sdma_script_addrs.mxc_sdma_uartsh_2_per_addr;
++                      break;
++              case per_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_uartsh_2_mcu_addr;
++                      break;
++              case int_2_per:
++                      res = sdma_script_addrs.mxc_sdma_per_2_shp_addr;
++                      break;
++              case emi_2_per:
++                      res = sdma_script_addrs.mxc_sdma_mcu_2_shp_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == ATA) {
++              switch (transfer_type) {
++              case per_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_ata_2_mcu_addr;
++                      break;
++              case emi_2_per:
++                      res = sdma_script_addrs.mxc_sdma_mcu_2_ata_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == CSPI || peripheral_type == EXT ||
++                 peripheral_type == SSI) {
++              switch (transfer_type) {
++              case per_2_int:
++                      res = sdma_script_addrs.mxc_sdma_app_2_per_addr;
++                      break;
++              case per_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_app_2_mcu_addr;
++                      break;
++              case int_2_per:
++                      res = sdma_script_addrs.mxc_sdma_per_2_app_addr;
++                      break;
++              case emi_2_per:
++                      res = sdma_script_addrs.mxc_sdma_mcu_2_app_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == SSI_SP || peripheral_type == MMC ||
++                 peripheral_type == SDHC || peripheral_type == CSPI_SP ||
++                 peripheral_type == ESAI || peripheral_type == MSHC_SP) {
++              switch (transfer_type) {
++              case per_2_int:
++                      res = sdma_script_addrs.mxc_sdma_shp_2_per_addr;
++                      break;
++              case per_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_shp_2_mcu_addr;
++                      break;
++              case int_2_per:
++                      res = sdma_script_addrs.mxc_sdma_per_2_shp_addr;
++                      break;
++              case emi_2_per:
++                      res = sdma_script_addrs.mxc_sdma_mcu_2_shp_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == ASRC) {
++              switch (transfer_type) {
++              case per_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_asrc_2_mcu_addr;
++                      break;
++              case emi_2_per:
++                      res = sdma_script_addrs.mxc_sdma_asrc_2_mcu_addr;
++                      break;
++              case per_2_per:
++                      res = sdma_script_addrs.mxc_sdma_per_2_per_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == MSHC) {
++              switch (transfer_type) {
++              case per_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_mshc_2_mcu_addr;
++                      break;
++              case emi_2_per:
++                      res = sdma_script_addrs.mxc_sdma_mcu_2_mshc_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == CCM) {
++              switch (transfer_type) {
++              case per_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_dptc_dvfs_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == FIFO_MEMORY) {
++              res = sdma_script_addrs.mxc_sdma_ap_2_ap_fixed_addr;
++      } else if (peripheral_type == SPDIF) {
++              switch (transfer_type) {
++              case per_2_emi:
++                      res = sdma_script_addrs.mxc_sdma_spdif_2_mcu_addr;
++                      break;
++              case emi_2_per:
++                      res = sdma_script_addrs.mxc_sdma_mcu_2_spdif_addr;
++                      break;
++              default:
++                      res = -EINVAL;
++              }
++      } else if (peripheral_type == IPU_MEMORY) {
++              if (transfer_type == emi_2_per) {
++                      res = sdma_script_addrs.mxc_sdma_ext_mem_2_ipu_addr;
++              } else {
++                      res = -EINVAL;
++              }
++      }
++
++      if (res < 0) {
++              printk(KERN_ERR "SDMA script not found\n");
++      } else {
++              DBG(1, "%s: PC[%d,%d]=%04x\n", __FUNCTION__,
++                      peripheral_type, transfer_type, res);
++      }
++      return res;
++
++}
++
++static inline int sdma_asrc_set_info(dma_channel_params *p,
++                                   script_data *pcontext, int eflags)
++{
++      dma_channel_ext_params *ep = (dma_channel_ext_params *)p;
++      unsigned int wml, tmp, wml1, wml2;
++      struct dma_channel_asrc_info *info = &ep->info.asrc;
++
++      wml = 0;
++      if (p->transfer_type == per_2_per) {
++              if (!p->ext)
++                      return wml;
++              wml1 = p->watermark_level;
++              wml2 = ep->watermark_level2;
++              if (info->channs) {
++                      wml |= (info->channs & SDMA_ASRC_INFO_N_MASK) <<
++                          SDMA_ASRC_INFO_N_OFF;
++                      if (ep->p2p_dir)
++                              wml2 *= info->channs & SDMA_ASRC_INFO_N_MASK;
++                      else
++                              wml1 *= info->channs & SDMA_ASRC_INFO_N_MASK;
++              }
++              if (info->channs & 1) {
++                      if (ep->p2p_dir)
++                              wml |= SDMA_ASRC_P2P_INFO_PS;
++                      else
++                              wml |= SDMA_ASRC_P2P_INFO_PA;
++              }
++              if (wml1 > wml2) {
++                      tmp = wml2 & SDMA_ASRC_P2P_INFO_LWML_MASK;
++                      wml |= tmp << SDMA_ASRC_P2P_INFO_LWML_OFF;
++                      tmp = wml1 & SDMA_ASRC_P2P_INFO_HWML_MASK;
++                      wml |= tmp << SDMA_ASRC_P2P_INFO_HWML_OFF;
++                      if (eflags & (1 << 31))
++                              wml |= SDMA_ASRC_P2P_INFO_LWE;
++                      if (eflags & (1 << 30))
++                              wml |= SDMA_ASRC_P2P_INFO_HWE;
++              } else {
++                      tmp = wml1 & SDMA_ASRC_P2P_INFO_LWML_MASK;
++                      wml |= tmp << SDMA_ASRC_P2P_INFO_LWML_OFF;
++                      tmp = wml2 & SDMA_ASRC_P2P_INFO_HWML_MASK;
++                      wml |= tmp << SDMA_ASRC_P2P_INFO_HWML_OFF;
++                      wml |= eflags >> 2;
++                      tmp = pcontext->event_mask2;
++                      pcontext->event_mask2 = pcontext->event_mask1;
++                      pcontext->event_mask1 = tmp;
++              }
++      } else {
++              if (p->ext && info->channs) {
++                      wml |= (info->channs & SDMA_ASRC_INFO_N_MASK) <<
++                          SDMA_ASRC_INFO_N_OFF;
++                      tmp = (info->channs * p->watermark_level) &
++                          SDMA_ASRC_INFO_WML_MASK;
++                      wml |= tmp << SDMA_ASRC_INFO_WML_OFF;
++              } else {
++                      tmp = (p->watermark_level & SDMA_ASRC_INFO_WML_MASK);
++                      wml |= tmp << SDMA_ASRC_INFO_WML_OFF;
++              }
++
++              if (p->transfer_type == per_2_emi)
++                      wml |= SDMA_ASRC_INFO_TXFR_DIR;
++
++              if (p->ext && (info->channs & 1)) {
++                      if (p->transfer_type == per_2_emi)
++                              wml |= SDMA_ASRC_INFO_PS;
++                      else
++                              wml |= SDMA_ASRC_INFO_PA;
++              }
++              wml |= eflags;
++      }
++      return wml;
++}
++
++/*
++ * Downloads channel context according to channel parameters
++ *
++ * @param   channel           channel number
++ * @param   p                 channel parameters
++ */
++static int sdma_load_context(int channel, dma_channel_params *p)
++{
++      script_data context;
++      int res;
++      int event1_greater_than_32;
++      int event2_greater_than_32;
++      dma_channel_ext_params *ep = (dma_channel_ext_params *)p;
++
++      res = 0;
++
++      memset(&context, 0, sizeof(script_data));
++      context.load_address = sdma_get_pc(p->peripheral_type,
++                                         p->transfer_type);
++
++      if (context.load_address > 0) {
++              if ((p->peripheral_type != MEMORY) &&
++                      (p->peripheral_type != DSP)) {
++                      /* Handle multiple event channels differently */
++                      if (p->event_id2) {
++                              if (p->event_id2 < 32) {
++                                      context.event_mask2 =
++                                          0x1 << p->event_id2;
++                                      event2_greater_than_32 = 0;
++                              } else {
++                                      context.event_mask2 =
++                                          0x1 << (p->event_id2 - 32);
++                                      event2_greater_than_32 = 1 << 31;
++                              }
++                              if (p->event_id < 32) {
++                                      context.event_mask1 =
++                                          0x1 << p->event_id;
++                                      event1_greater_than_32 = 0;
++                              } else {
++                                      context.event_mask1 =
++                                          0x1 << (p->event_id - 32);
++                                      event1_greater_than_32 = 1 << 30;
++                              }
++                      } else {
++                              event1_greater_than_32 = 0;
++                              event2_greater_than_32 = 0;
++                              if (p->event_id < 32) {
++                                      context.event_mask1 =
++                                          0x1 << p->event_id;
++                                      context.event_mask2 = 0;
++                              } else {
++                                      context.event_mask1 = 0;
++                                      context.event_mask2 =
++                                          0x1 << (p->event_id - 32);
++                              }
++                      }
++
++                      if (p->ext)
++                              context.wml = ep->info_bits;
++                      /* Watermark Level */
++                      if (p->peripheral_type == ASRC) {
++                              context.wml |= sdma_asrc_set_info(p,
++                                                                &context,
++                                                                event2_greater_than_32
++                                                                |
++                                                                event1_greater_than_32);
++                      } else
++                              context.wml |= event2_greater_than_32 |
++                                      event1_greater_than_32 | p->watermark_level;
++
++                      /* Address */
++                      context.shp_addr = p->per_address;
++                      iapi_IoCtl(sdma_data[channel].cd,
++                                 IAPI_CHANGE_PERIPHADDR, p->per_address);
++              } else {
++                      context.wml = M3_BASE_ADDRESS;
++              }
++
++              sdma_data[channel].transfer_type = p->transfer_type;
++              sdma_data[channel].peripheral_type = p->peripheral_type;
++              sdma_data[channel].watermark_level = p->watermark_level;
++              iapi_AssignScript(sdma_data[channel].cd, &context);
++      } else {
++              res = context.load_address;
++      }
++
++      return res;
++}
++
++/*
++ * 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)
++{
++      int err = 0;
++      int i;
++
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++
++      mxc_dma_stop(channel);
++
++      for (i = 0; i < sdma_data[channel].bd_number; i++) {
++              iapi_IoCtl(sdma_data[channel].cd,
++                         (i << BD_NUM_OFFSET) |
++                         IAPI_CHANGE_SET_STATUS, 0);
++      }
++
++      DBG(0, "%s: Changing number of BDs for channel %d from %u to %u\n",
++              __FUNCTION__, channel, sdma_data[channel].bd_number,
++              p->bd_number <= 0 ? 1 : p->bd_number);
++      sdma_data[channel].bd_number = (p->bd_number <= 0) ? 1 : p->bd_number;
++
++      sdma_data[channel].word_size = p->word_size;
++
++      sdma_data[channel].event_id = p->event_id;
++      sdma_data[channel].event_id2 = p->event_id2;
++
++      sdma_data[channel].callback = p->callback;
++
++      sdma_data[channel].arg = p->arg;
++
++      err = iapi_IoCtl(sdma_data[channel].cd,
++                       IAPI_CHANGE_BDNUM, sdma_data[channel].bd_number);
++      if (err < 0) {
++              printk(KERN_ERR "Failed to allocate buffer descriptors: %d\n",
++                      err);
++              err = -ENOMEM;
++              goto setup_channel_fail;
++      }
++
++      if (channel != 0) {
++              switch (p->transfer_type) {
++              case dsp_2_per:
++                      break;
++              case emi_2_per:
++              case int_2_per:
++              case per_2_int:
++              case per_2_emi:
++              case per_2_per:
++                      /*
++                       * Peripheral <------> Memory
++                       * evtOvr = 0 dspOvr = 1
++                       */
++                      err = iapi_IoCtl(sdma_data[channel].cd,
++                              IAPI_CHANGE_OWNERSHIP,
++                              (OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
++                              (OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
++                              (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
++                      if (err)
++                              goto setup_channel_fail;
++                      if (p->event_id) {
++                              err = iapi_SetChannelEventMapping(p->event_id,
++                                                              1 << channel);
++                              if (err)
++                                      goto setup_channel_fail;
++                      }
++                      if (p->event_id2) {
++                              err = iapi_SetChannelEventMapping(p->event_id2,
++                                                              1 << channel);
++                      }
++                      break;
++              case emi_2_dsp:
++              case int_2_dsp:
++              case dsp_2_int:
++              case dsp_2_emi:
++              case dsp_2_dsp:
++                      /*
++                       * DSP <-----------> Memory
++                       * evtOvr = 1 dspOvr = 0
++                       */
++                      err = iapi_IoCtl(sdma_data[channel].cd,
++                                      IAPI_CHANGE_OWNERSHIP,
++                                      (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
++                                      (OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
++                                      (OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
++                      break;
++              case emi_2_int:
++              case emi_2_emi:
++              case int_2_int:
++              case int_2_emi:
++              case emi_2_dsp_loop:
++              case dsp_2_emi_loop:
++                      /* evtOvr = 1 dspOvr = 1 */
++                      err = iapi_IoCtl(sdma_data[channel].cd,
++                              IAPI_CHANGE_OWNERSHIP,
++                              (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
++                              (OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
++                              (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
++                      break;
++              case per_2_dsp:
++                      /* evtOvr = 0 dspOvr = 0 */
++                      err = iapi_IoCtl(sdma_data[channel].cd,
++                              IAPI_CHANGE_OWNERSHIP,
++                              (OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
++                              (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
++                              (OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
++                      if (err)
++                              goto setup_channel_fail;
++                      err = iapi_SetChannelEventMapping(p->event_id,
++                                                      1 << channel);
++                      break;
++              default:
++                      break;
++                      printk(KERN_ERR "Wrong SDMA transfer type\n");
++                      err = -EINVAL;
++              }
++              if (err)
++                      goto setup_channel_fail;
++
++              err = sdma_load_context(channel, p);
++              if (err)
++                      goto setup_channel_fail;
++
++              err = iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_PRIORITY,
++                              MXC_SDMA_DEFAULT_PRIORITY);
++      }
++setup_channel_fail:
++      return err;
++}
++EXPORT_SYMBOL(mxc_dma_setup_channel);
++
++/*
++ * 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)
++{
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++
++      if (priority < MXC_SDMA_MIN_PRIORITY
++          || priority > MXC_SDMA_MAX_PRIORITY) {
++              return -EINVAL;
++      }
++      return iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_PRIORITY,
++                        priority);
++}
++EXPORT_SYMBOL(mxc_dma_set_channel_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)
++{
++      int i, res = -EBUSY;
++
++      if (sdma_base_addr == NULL)
++              return -ENOSYS;
++
++      if (channel == NULL || *channel < 0 || *channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++
++      down(&sdma_status_mutex);
++
++      /* Dynamic allocation */
++      if (*channel == 0) {
++              for (i = MAX_DMA_CHANNELS - 1; i > 0; i--) {
++#ifdef CONFIG_SDMA_IRAM
++                      /*TODO:It will be removed after DPTC used UDMA interface */
++                      if (i >= MXC_DMA_CHANNEL_IRAM)
++                              continue;
++#endif /* CONFIG_SDMA_IRAM */
++                      if (!sdma_data[i].in_use) {
++                              *channel = i;
++                              res = 0;
++                              break;
++                      }
++              }
++      } else {
++              if (sdma_data[*channel].in_use)
++                      return -EBUSY;
++              res = 0;
++      }
++      if (res)
++              return res;
++
++      DBG(1, "%s: Opening channel %d\n", __FUNCTION__, *channel);
++
++      res = iapi_Open(sdma_data[0].cd, *channel);
++      if (res < 0) {
++              printk(KERN_ERR "Failed iapi_Open channel %d, 0x%x\n",
++                      *channel, res);
++      } else {
++              sdma_data[*channel].in_use = 1;
++              strlcpy(sdma_data[*channel].devicename, devicename,
++                      sizeof(sdma_data[*channel].devicename));
++              sdma_data[*channel].cd = CHAD(*channel);
++
++              iapi_IoCtl(sdma_data[*channel].cd, IAPI_CHANGE_SYNCH,
++                      CALLBACK_ISR);
++              iapi_IoCtl(sdma_data[*channel].cd,
++                      IAPI_CHANGE_CALLBACKFUNC,
++                      (unsigned long)iapi_interrupt_callback);
++              iapi_IoCtl(sdma_data[*channel].cd,
++                      IAPI_CHANGE_USER_ARG,
++                      (unsigned long)&sdma_data[*channel]);
++      }
++
++      up(&sdma_status_mutex);
++
++      return res;
++}
++EXPORT_SYMBOL(mxc_request_dma);
++
++/*
++ * 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 ret;
++      unsigned long param;
++
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++
++      if (!sdma_data[channel].in_use) {
++              return -EINVAL;
++      }
++      DBG(0, "%s: dma_request: src: %08x dst: %08x cont=%d wrap=%d\n",
++              __FUNCTION__, p->sourceAddr, p->destAddr,
++              p->bd_cont, p->bd_wrap);
++
++      ret = iapi_IoCtl(sdma_data[channel].cd,
++                      (bd_index << BD_NUM_OFFSET) |
++                      IAPI_CHANGE_SET_TRANSFER_CD, sdma_data[channel].word_size);
++      if (ret < 0)
++              return ret;
++
++      param = BD_DONE | BD_INTR | BD_EXTD;
++
++      if (sdma_data[channel].bd_number > 1 && p->bd_cont) {
++              param |= BD_CONT;
++      }
++
++      if (bd_index == sdma_data[channel].bd_number - 1 || p->bd_wrap) {
++              param |= BD_WRAP;
++      }
++
++      switch (sdma_data[channel].transfer_type) {
++      case emi_2_per:
++      case dsp_2_per:
++      case int_2_per:
++      case emi_2_dsp:
++      case int_2_dsp:
++      case emi_2_dsp_loop:
++              ret = iapi_IoCtl(sdma_data[channel].cd,
++                              (bd_index << BD_NUM_OFFSET) |
++                              IAPI_CHANGE_SET_BUFFERADDR,
++                              (unsigned long)p->sourceAddr);
++              break;
++      case per_2_int:
++      case per_2_emi:
++      case per_2_dsp:
++      case dsp_2_int:
++      case dsp_2_emi:
++      case dsp_2_dsp:
++      case dsp_2_emi_loop:
++              ret = iapi_IoCtl(sdma_data[channel].cd,
++                              (bd_index << BD_NUM_OFFSET) |
++                              IAPI_CHANGE_SET_BUFFERADDR,
++                              (unsigned long)p->destAddr);
++              break;
++      case emi_2_int:
++      case emi_2_emi:
++      case int_2_int:
++      case int_2_emi:
++              ret = iapi_IoCtl(sdma_data[channel].cd,
++                         (bd_index << BD_NUM_OFFSET) |
++                         IAPI_CHANGE_SET_BUFFERADDR,
++                         (unsigned long)p->sourceAddr);
++              if (ret < 0)
++                      return ret;
++              ret = iapi_IoCtl(sdma_data[channel].cd,
++                         (bd_index << BD_NUM_OFFSET) |
++                         IAPI_CHANGE_SET_EXTDBUFFERADDR,
++                         (unsigned long)p->destAddr);
++              break;
++      case per_2_per:
++      case dvfs_pll:
++      case dvfs_pdr:
++              return -EINVAL;
++      }
++      if (ret < 0)
++              return ret;
++
++      /* Change the endianness for DSP to MCU Data transfers */
++      if (sdma_data[channel].transfer_type == dsp_2_emi ||
++              sdma_data[channel].transfer_type == emi_2_dsp) {
++              ret = iapi_IoCtl(sdma_data[channel].cd,
++                              IAPI_CHANGE_SET_ENDIANNESS,
++                              SET_BIT_ALL);
++              if (ret < 0)
++                      return ret;
++      }
++
++      ret = iapi_IoCtl(sdma_data[channel].cd,
++                      (bd_index << BD_NUM_OFFSET) |
++                      IAPI_CHANGE_SET_COUNT, p->count);
++      if (ret < 0)
++              return ret;
++
++      ret = iapi_IoCtl(sdma_data[channel].cd,
++                      (bd_index << BD_NUM_OFFSET) | IAPI_CHANGE_SET_STATUS,
++                      param);
++      return ret;
++}
++EXPORT_SYMBOL(mxc_dma_set_config);
++
++/*
++ * 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
++ * @return  0 on success, error code on fail
++ */
++void mxc_dma_set_bd_intr(int channel, int bd_index, int bd_intr)
++{
++      unsigned long param;
++
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return;
++
++      iapi_IoCtl(sdma_data[channel].cd,
++                 (bd_index << BD_NUM_OFFSET) |
++                 IAPI_CHANGE_GET_STATUS, (unsigned long)&param);
++
++      if (bd_intr) {
++              param |= BD_INTR;
++      } else {
++              param &= ~BD_INTR;
++      }
++      iapi_IoCtl(sdma_data[channel].cd,
++                 (bd_index << BD_NUM_OFFSET) | IAPI_CHANGE_SET_STATUS, param);
++}
++EXPORT_SYMBOL(mxc_dma_set_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)
++{
++      int ret;
++      unsigned long bd_status = 0;
++
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++
++      ret = iapi_IoCtl(sdma_data[channel].cd,
++                      (bd_index << BD_NUM_OFFSET) |
++                      IAPI_CHANGE_GET_STATUS, (unsigned long)&bd_status);
++
++      return ret == 0 ? !!(bd_status & BD_INTR) : ret;
++}
++EXPORT_SYMBOL(mxc_dma_get_bd_intr);
++
++/*
++ * 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)
++{
++      unsigned char param = 0;
++      int i = 0;
++
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++
++      if (!sdma_data[channel].in_use) {
++              return -EINVAL;
++      }
++
++      /* clear the BD_DONE bits for all the necessary buffers */
++      for (i = 0; i < buffer_number; i++) {
++
++              iapi_IoCtl(sdma_data[channel].cd, (i << BD_NUM_OFFSET) |
++                         IAPI_CHANGE_GET_STATUS, (unsigned long)&param);
++
++              /* clear the BD_DONE bit of the buffer */
++              param &= ~BD_DONE;
++
++              iapi_IoCtl(sdma_data[channel].cd, (i << BD_NUM_OFFSET) |
++                         IAPI_CHANGE_SET_STATUS, param);
++      }
++
++      return 0;
++}
++EXPORT_SYMBOL(mxc_dma_reset);
++
++/*
++ * 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 err = 0;
++      unsigned long bd_status;
++      unsigned long bd_count;
++      dma_addr_t sourceAddr;
++      dma_addr_t destAddr;
++
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++
++      memset(p, 0, sizeof(*p));
++
++      err = iapi_IoCtl(sdma_data[channel].cd,
++                      (bd_index << BD_NUM_OFFSET) |
++                      IAPI_CHANGE_GET_STATUS, (unsigned long)&bd_status);
++      if (err)
++              return err;
++      err = iapi_IoCtl(sdma_data[channel].cd,
++                      (bd_index << BD_NUM_OFFSET) |
++                      IAPI_CHANGE_GET_COUNT, (unsigned long)&bd_count);
++      if (err)
++              return err;
++      err = iapi_IoCtl(sdma_data[channel].cd,
++                      (bd_index << BD_NUM_OFFSET) |
++                      IAPI_CHANGE_GET_BUFFERADDR, (unsigned long)&sourceAddr);
++      if (err)
++              return err;
++
++      switch (sdma_data[channel].transfer_type) {
++      case emi_2_per:
++      case dsp_2_per:
++      case int_2_per:
++      case emi_2_dsp:
++      case int_2_dsp:
++      case emi_2_dsp_loop:
++              p->sourceAddr = sourceAddr;
++              break;
++      case per_2_int:
++      case per_2_emi:
++      case per_2_dsp:
++      case dsp_2_int:
++      case dsp_2_emi:
++      case dsp_2_dsp:
++      case dsp_2_emi_loop:
++              p->destAddr = sourceAddr;
++              break;
++      case emi_2_int:
++      case emi_2_emi:
++      case int_2_int:
++      case int_2_emi:
++              p->sourceAddr = sourceAddr;
++              err = iapi_IoCtl(sdma_data[channel].cd,
++                              (bd_index << BD_NUM_OFFSET) |
++                              IAPI_CHANGE_GET_EXTDBUFFERADDR,
++                              (unsigned long)&destAddr);
++              if (err)
++                      return err;
++              p->destAddr = destAddr;
++              break;
++      default:
++              break;
++      }
++
++      p->count = bd_count;
++      p->bd_done = !!(bd_status & BD_DONE);
++      p->bd_cont = !!(bd_status & BD_CONT);
++      p->bd_error = !!(bd_status & BD_RROR);
++      p->bd_wrap = !!(bd_status & BD_WRAP);
++
++      return err;
++}
++EXPORT_SYMBOL(mxc_dma_get_config);
++
++/*
++ * This function is used by MXC IPC's write_ex2. It passes the 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)
++{
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++      return iapi_Write_ipcv2(sdma_data[channel].cd, ctrl_ptr);
++}
++EXPORT_SYMBOL(mxc_sdma_write_ipcv2);
++
++/*
++ * This function is used by MXC IPC's read_ex2. It passes the 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)
++{
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++      return iapi_Read_ipcv2(sdma_data[channel].cd, ctrl_ptr);
++}
++EXPORT_SYMBOL(mxc_sdma_read_ipcv2);
++
++/*
++ * Starts dma channel.
++ *
++ * @param   channel           channel number
++ */
++int mxc_dma_start(int channel)
++{
++      DBG(1, "%s: Starting DMA channel %d\n", __FUNCTION__, channel);
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++
++      if (!sdma_data[channel].running) {
++              sdma_data[channel].running = 1;
++              iapi_StartChannel(channel);
++      }
++
++      return 0;
++}
++EXPORT_SYMBOL(mxc_dma_start);
++
++/*
++ * Stops dma channel.
++ *
++ * @param   channel           channel number
++ */
++int mxc_dma_stop(int channel)
++{
++      DBG(1, "%s: Stopping DMA channel %d\n", __FUNCTION__, channel);
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++
++      iapi_StopChannel(channel);
++      sdma_data[channel].running = 0;
++
++      return 0;
++}
++EXPORT_SYMBOL(mxc_dma_stop);
++
++/*
++ * Frees dma channel.
++ *
++ * @param   channel           channel number
++ */
++void mxc_free_dma(int channel)
++{
++      int i;
++
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return;
++
++      mxc_dma_stop(channel);
++
++      if (sdma_data[channel].event_id != 0) {
++              iapi_SetChannelEventMapping(sdma_data[channel].event_id, 0x0);
++      }
++      if (sdma_data[channel].event_id2 != 0) {
++              iapi_SetChannelEventMapping(sdma_data[channel].event_id2, 0x0);
++      }
++
++      sdma_data[channel].event_id = 0;
++
++      iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_PRIORITY, 0x0);
++      iapi_IoCtl(sdma_data[channel].cd, IAPI_CHANGE_OWNERSHIP,
++                 (OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
++                 (OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
++                 (OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
++
++      for (i = 0; i < sdma_data[channel].bd_number; i++) {
++              iapi_IoCtl(sdma_data[channel].cd,
++                         (i << BD_NUM_OFFSET) |
++                         IAPI_CHANGE_SET_STATUS, 0);
++      }
++
++      iapi_Close(sdma_data[channel].cd);
++
++      strlcpy(sdma_data[channel].devicename, "not used",
++              sizeof(sdma_data[channel].devicename));
++
++      sdma_data[channel].in_use = 0;
++}
++EXPORT_SYMBOL(mxc_free_dma);
++
++/*
++ * Initializes channel's priorities
++ *
++ */
++static void __init init_priorities(void)
++{
++      iapi_IoCtl(sdma_data[0].cd, IAPI_CHANGE_PRIORITY, 0x7);
++}
++
++/*
++ * Initializes events table
++ */
++static void __init init_event_table(void)
++{
++      int channel;
++
++      for (channel = 0; channel < MAX_DMA_CHANNELS; channel++) {
++              iapi_SetChannelEventMapping(channel, 0);
++      }
++}
++
++/*
++ * 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)
++{
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return;
++
++      sdma_data[channel].callback = callback;
++      sdma_data[channel].arg = arg;
++}
++EXPORT_SYMBOL(mxc_dma_set_callback);
++
++/*
++ * Synchronization function used by I.API
++ *
++ * @param channel        channel number
++ */
++static int getChannel(int channel)
++{
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++
++      if (irqs_disabled() || in_atomic()) {
++              if (down_trylock(&sdma_synch_mutex[channel])) {
++                      return -EBUSY;
++              }
++      } else {
++              if (down_interruptible(&sdma_synch_mutex[channel])) {
++                      return -EBUSY;
++              }
++      }
++
++      return 0;
++}
++
++/*
++ * Synchronization function used by I.API
++ *
++ * @param channel        channel number
++ */
++static int releaseChannel(int channel)
++{
++      if (channel < 0 || channel >= MAX_DMA_CHANNELS)
++              return -EINVAL;
++      up(&sdma_synch_mutex[channel]);
++      return 0;
++}
++
++/*
++ * Unmask interrupt function. Used by I.API
++ *
++ */
++//static unsigned long flags;
++static void unmask_sdma_interrupt(void)
++{
++      /* Commented out to take care of the PREEMPT_RT option
++       * local_irq_restore(flags);
++       */
++}
++
++/*
++ * Mask interrupt function. Used by I.API
++ *
++ */
++static void mask_sdma_interrupt(void)
++{
++      /* Commented to take of the PREEMPT_RT option
++       * local_irq_save(flags);
++       */
++}
++
++#ifdef DEBUG
++static void *sdma_memcpy(void *dst, const void *src, size_t len)
++{
++      DBG(1, "%s: Copying %u byte from %p..%p to %p..%p\n", __FUNCTION__,
++              len, src, src + len - 1, dst, dst + len - 1);
++      memcpy(dst, src, len);
++      return dst;
++}
++#endif
++
++/*
++ * Initializes I.API
++ */
++static int __init init_iapi_struct(void)
++{
++      printk(KERN_INFO "Using SDMA I.API\n");
++
++      iapi_Malloc = &sdma_malloc;
++#ifdef CONFIG_SDMA_IRAM
++      iapi_iram_Malloc = &sdma_iram_malloc;
++#endif        /* CONFIG_SDMA_IRAM */
++
++      iapi_Free = &sdma_free;
++      iapi_Virt2Phys = sdma_virt_to_phys;
++      iapi_Phys2Virt = sdma_phys_to_virt;
++      iapi_memset = &memset;
++#ifndef DEBUG
++      iapi_memcpy = &memcpy;
++#else
++      iapi_memcpy = &sdma_memcpy;
++#endif
++      iapi_GotoSleep = &sdma_sleep_channel;
++      iapi_WakeUp = &sdma_wakeup_channel;
++      iapi_InitSleep = &sdma_init_sleep;
++      iapi_ReleaseChannel = &releaseChannel;
++      iapi_GetChannel = &getChannel;
++
++      iapi_EnableInterrupts = &unmask_sdma_interrupt;
++      iapi_DisableInterrupts = &mask_sdma_interrupt;
++
++      sdma_data[0].cd = kzalloc(sizeof(channelDescriptor), GFP_KERNEL);
++      if (sdma_data[0].cd == NULL)
++              return -ENOMEM;
++      return 0;
++}
++
++/*
++ * Initializes channel synchronization mutexes
++ */
++static void __init sdma_init_mutexes(void)
++{
++      int i;
++
++      for (i = 0; i < MAX_DMA_CHANNELS; i++) {
++              init_MUTEX(&sdma_synch_mutex[i]);
++      }
++
++      init_MUTEX(&sdma_status_mutex);
++}
++
++/*
++ * Channels status read proc file system function
++ *
++ * @param    buf      pointer to the buffer the data shuld be written to.
++ * @param    start    pointer to the pointer where the new data is
++ *                      written to.
++ *                    procedure should update the start pointer to point to
++ *                    where in the buffer the data was written.
++ * @param    offset   offset from start of the file
++ * @param    count    number of bytes to read.
++ * @param    eof      pointer to eof flag. sould be set to 1 when
++ *                      reaching eof.
++ * @param    data     driver specific data pointer.
++ *
++ * @return   number byte read from the log buffer.
++ */
++static int proc_read_channels(char *buf, char **start, off_t offset, int count,
++                            int *eof, void *data)
++{
++      char *log;
++      char *log_ptr;
++      char tmp[48];
++      int i;
++//#define LOG_BUF_SIZE 4096
++
++#ifdef LOG_BUF_SIZE
++      log = kzalloc(LOG_BUF_SIZE, GFP_KERNEL);
++      if (log == NULL) {
++              return -ENOMEM;
++      }
++#else
++      log = buf;
++#endif
++      log_ptr = log;
++
++      for (i = 0; i < MAX_DMA_CHANNELS; i++) {
++              if (sdma_data[i].in_use == 0) {
++                      continue;
++              }
++
++              memset(tmp, 0, sizeof(tmp));
++              snprintf(tmp, sizeof(tmp), "Channel %d: %s\n", i,
++                      sdma_data[i].devicename);
++#ifndef LOG_BUF_SIZE
++              strlcpy(log_ptr, tmp, PAGE_SIZE - (log_ptr - log));
++#else
++              strlcpy(log_ptr, tmp, LOG_BUF_SIZE - (log_ptr - log));
++#endif
++              log_ptr += strlen(tmp);
++              if (log_ptr - log >= PAGE_SIZE)
++                      break;
++      }
++
++      if (offset > (log_ptr - log)) {
++              *eof = 1;
++              count = 0;
++      } else {
++              if (offset + count > (log_ptr - log)) {
++                      count = (log_ptr - log) - offset;
++                      *eof = 1;
++              } else {
++                      *eof = 0;
++              }
++
++              memcpy(buf, log, count);
++              *start = buf;
++      }
++#ifdef LOG_BUF_SIZE
++      kfree(log);
++#endif
++      return count;
++}
++
++/*
++ * SDMA proc file system read function
++ */
++static int __init init_proc_fs(void)
++{
++      struct proc_dir_entry *sdma_proc_dir;
++      int res;
++
++      res = 0;
++
++      sdma_proc_dir = proc_mkdir("sdma", NULL);
++      create_proc_read_entry("channels", 0, sdma_proc_dir,
++                             proc_read_channels, NULL);
++
++      if (res < 0) {
++              printk(KERN_WARNING "Failed create SDMA proc entry\n");
++      }
++
++      return res;
++}
++
++/*
++ * Initializes SDMA private data
++ */
++static void __init init_sdma_data(void)
++{
++      int i;
++
++      sdma_data[0].in_use = 1;
++      strcpy(sdma_data[0].devicename, "MCU");
++
++      for (i = 0; i < MAX_DMA_CHANNELS; i++) {
++              sdma_data[i].channel = i;
++      }
++}
++
++#if defined(CONFIG_MXC_SUPER_GEM)
++/*
++ * Initialize the Super GEM SDMA channel
++ *
++ * @return returns NO FUCKING -1 on error, 0 on success.
++ */
++static int __init init_super_gem(void)
++{
++      channelDescriptor *cd;
++      script_data context;
++      int res = 0;
++
++      res = iapi_Open(sdma_data[0].cd, MXC_DMA_CHANNEL_GEM);
++      if (res < 0) {
++              return res;
++      }
++      sdma_data[MXC_DMA_CHANNEL_GEM].in_use = 1;
++      cd = CHAD(MXC_DMA_CHANNEL_GEM);
++      memset(&context, 0, sizeof(script_data));
++      context.load_address = sdma_script_addrs.mxc_sdma_utra_addr;
++      context.wml = M3_BASE_ADDRESS;
++      res = iapi_AssignScript(cd, &context);
++      if (res < 0) {
++              iapi_Close(cd);
++              sdma_data[MXC_DMA_CHANNEL_GEM].in_use = 0;
++              return res;
++      }
++      res = iapi_IoCtl(cd, IAPI_CHANGE_OWNERSHIP,
++                      (OWN_CHANNEL << CH_OWNSHP_OFFSET_EVT) |
++                      (DONT_OWN_CHANNEL << CH_OWNSHP_OFFSET_MCU) |
++                      (OWN_CHANNEL << CH_OWNSHP_OFFSET_DSP));
++      if (res < 0) {
++              iapi_Close(cd);
++              sdma_data[MXC_DMA_CHANNEL_GEM].in_use = 0;
++              return res;
++      }
++      /* Set EP=1, which is required to start SuperGem script the first time */
++      /* This can be done only on the AP side */
++      SDMA_H_EVTPEND |= 1 << MXC_DMA_CHANNEL_GEM;
++
++      res = iapi_SetChannelEventMapping(DMA_REQ_GEM,
++                                      1 << MXC_DMA_CHANNEL_GEM);
++      if (res < 0) {
++              iapi_Close(cd);
++              sdma_data[MXC_DMA_CHANNEL_GEM].in_use = 0;
++              return res;
++      }
++
++      return 0;
++}
++#endif
++
++/*
++ * Initializes dma
++ */
++int __init sdma_init(void)
++{
++      int res;
++      configs_data confreg_data;
++      struct clk *ahb_clk;
++
++      sdma_base_addr = ioremap(SDMA_BASE_ADDR, SZ_16K);
++      if (sdma_base_addr == NULL)
++              return -ENOMEM;
++
++      /* Initialize to the default values */
++      confreg_data = iapi_ConfigDefaults;
++
++#ifdef MXC_SDMA_DSPDMA
++      confreg_data.dspdma = MXC_SDMA_DSPDMA;
++#endif
++      /* Set ACR bit */
++      mxc_sdma_clk = clk_get_sys(NULL, "sdma");
++      if (IS_ERR(mxc_sdma_clk)) {
++              res = PTR_ERR(mxc_sdma_clk);
++              printk(KERN_EMERG "Failed to get SDMA clock: %d\n", res);
++              goto clk_fail;
++      }
++
++      ahb_clk = clk_get_sys(NULL, "ahb");
++      if (IS_ERR(ahb_clk)) {
++              res = PTR_ERR(ahb_clk);
++              printk(KERN_EMERG "Failed to get SDMA clock: %d\n", res);
++              goto clk_fail;
++      }
++      clk_enable(mxc_sdma_clk);
++      clk_enable(ahb_clk);
++      printk(KERN_INFO "AHB clock rate: %lu.%03luMHz SDMA clock rate: %lu.%03luMHz\n",
++              clk_get_rate(ahb_clk) / 1000000,
++              clk_get_rate(ahb_clk) / 1000 % 1000,
++              clk_get_rate(mxc_sdma_clk) / 1000000,
++              clk_get_rate(mxc_sdma_clk) / 1000 % 1000);
++      if (clk_get_rate(ahb_clk) / clk_get_rate(mxc_sdma_clk) != 2) {
++              printk(KERN_INFO "Setting SDMA ACR\n");
++              confreg_data.acr = 1;
++      }
++      clk_disable(ahb_clk);
++      clk_put(ahb_clk);
++
++      init_sdma_data();
++
++      init_sdma_pool();
++
++      res = request_irq(MXC_INT_SDMA, sdma_int_handler, 0, "mxc-sdma", NULL);
++      if (res) {
++              printk(KERN_EMERG "Failed to get SDMA clock: %d\n", res);
++              goto sdma_init_fail;
++      }
++
++      sdma_init_mutexes();
++
++      res = init_iapi_struct();
++      if (res)
++              goto free_irq;
++
++      mxc_sdma_get_script_info(&sdma_script_addrs);
++
++      res = iapi_Init(sdma_data[0].cd, &confreg_data,
++                      sdma_script_addrs.mxc_sdma_start_addr,
++                      sdma_script_addrs.mxc_sdma_ram_code_size * 2,
++                      sdma_script_addrs.mxc_sdma_ram_code_start_addr, 0x50);
++      if (res < 0) {
++              printk(KERN_EMERG "Failed to init SDMA API: %d\n", res);
++              goto free_mem;
++      }
++
++      init_priorities();
++
++      init_event_table();
++
++#if defined(CONFIG_MXC_SUPER_GEM)
++      res = init_super_gem();
++      if (res < 0) {
++              goto free_mem;
++      }
++#endif
++
++      init_proc_fs();
++
++      printk(KERN_INFO "MXC SDMA API initialized\n");
++
++      clk_disable(mxc_sdma_clk);
++      return res;
++free_mem:
++      kfree(sdma_data[0].cd);
++free_irq:
++      free_irq(MXC_INT_SDMA, NULL);
++sdma_init_fail:
++      clk_disable(mxc_sdma_clk);
++      clk_put(mxc_sdma_clk);
++clk_fail:
++      iounmap(sdma_base_addr);
++      sdma_base_addr = NULL;
++      printk(KERN_ERR "Error %d in sdma_init\n", res);
++      return res;
++}
++arch_initcall(sdma_init);
++
++MODULE_AUTHOR("Freescale Semiconductor, Inc.");
++MODULE_DESCRIPTION("MXC Linux SDMA API");
++MODULE_LICENSE("GPL");
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/sdma.h linux.35.new/arch/arm/plat-mxc/sdma/sdma.h
+--- linux.35.old/arch/arm/plat-mxc/sdma/sdma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/sdma.h 2010-12-03 09:51:55.416347546 +0100
+@@ -0,0 +1,13 @@
++#ifndef __SDMA_H
++#define __SDMA_H
++
++extern struct clk *mxc_sdma_clk;
++extern void __iomem *sdma_base_addr;
++
++/*
++ * SDMA buffers pool initialization function
++ */
++extern void init_sdma_pool(void);
++
++
++#endif /* __SDMA_H */
+diff -urN linux.35.old/arch/arm/plat-mxc/sdma/sdma_malloc.c linux.35.new/arch/arm/plat-mxc/sdma/sdma_malloc.c
+--- linux.35.old/arch/arm/plat-mxc/sdma/sdma_malloc.c  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/sdma/sdma_malloc.c  2010-12-03 09:51:55.416347546 +0100
+@@ -0,0 +1,404 @@
++/*
++ * Copyright 2004-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 plat-mxc/sdma/sdma_malloc.c
++ * @brief This file contains functions for SDMA non-cacheable buffers allocation
++ *
++ * SDMA (Smart DMA) is used for transferring data between MCU and peripherals
++ *
++ * @ingroup SDMA
++ */
++
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/slab.h>
++#include <linux/mm.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/dmapool.h>
++
++#include <asm/dma.h>
++#include <asm/mach/dma.h>
++#include <mach/hardware.h>
++#include <mach/sdma.h>
++
++#include <epm.h>
++#include "sdma.h"
++
++#ifdef CONFIG_SDMA_IRAM
++#define IRAM_VIRT_BASE  IRAM_BASE_ADDR_VIRT
++#define IRAM_PHYS_BASE  IRAM_BASE_ADDR
++#if (CONFIG_SDMA_IRAM_SIZE & 0x3FF)
++#error  "IRAM size of SDMA should be multiple of 1Kbytes"
++#else
++#define IRAM_SDMA_SIZE  CONFIG_SDMA_IRAM_SIZE /* 4K */
++#endif
++#define IRAM_UNIT_SIZE  512
++#define IRAM_POOL_SIZE  (IRAM_SDMA_SIZE/IRAM_UNIT_SIZE)
++
++#define IS_IRAM_VIRT(x) (((x) < IRAM_VIRT_BASE) ? 0 :                 \
++                              (((x) - IRAM_VIRT_BASE) > IRAM_SDMA_SIZE) ? 0 : 1)
++
++#define IS_IRAM_PHYS(x) (((x) < IRAM_PHYS_BASE) ? 0:                  \
++                              (((x) - IRAM_PHYS_BASE) > IRAM_SDMA_SIZE) ? 0 : 1)
++#endif                                /*CONFIG_SDMA_IRAM */
++
++/*!
++ * Defines SDMA non-cacheable buffers pool
++ */
++static struct dma_pool *pool;
++
++#ifdef CONFIG_SDMA_IRAM
++typedef struct iram_head_s {
++      struct list_head list;
++} iram_head_t;
++
++static spinlock_t iram_pool_lock = SPIN_LOCK_UNLOCKED;
++static struct list_head iram_free_list;
++static unsigned char iram_pool_flag[IRAM_POOL_SIZE];
++
++static void sdma_iram_free(void *buf);
++#endif                                /*CONFIG_SDMA_IRAM */
++
++/*!
++ * SDMA memory conversion hashing structure
++ */
++typedef struct {
++      struct list_head node;
++      int use_count;
++      /*! Virtual address */
++      void *virt;
++      /*! Physical address */
++      unsigned long phys;
++} virt_phys_struct;
++
++static struct list_head buf_map;
++
++/*!
++ * Defines the size of each buffer in SDMA pool.
++ * The size must be at least 512 bytes, because
++ * sdma channel control blocks array size is 512 bytes
++ */
++#define SDMA_POOL_SIZE 1024
++
++/*!
++ * Adds new buffer structure into conversion hash tables
++ *
++ * @param   vf   SDMA memory conversion hashing structure
++ *
++ * @return       1 on success, 0 on fail
++ */
++static int add_entry(virt_phys_struct *vf)
++{
++      virt_phys_struct *p;
++
++      BUG_ON(in_atomic());
++      vf->phys &= PAGE_MASK;
++      vf->virt = (void *)((unsigned long)vf->virt & PAGE_MASK);
++
++      list_for_each_entry(p, &buf_map, node) {
++              if (p->virt == vf->virt) {
++                      p->use_count++;
++                      return 0;
++              }
++      }
++
++      p = kzalloc(sizeof(virt_phys_struct), GFP_KERNEL);
++      if (p == NULL) {
++              return -ENOMEM;
++      }
++
++      p->phys = vf->phys & PAGE_MASK;
++      p->virt = (void *)((unsigned long)vf->virt & PAGE_MASK);
++      p->use_count = 1;
++      list_add_tail(&p->node, &buf_map);
++
++      DBG(2, "added vaddr 0x%p, paddr 0x%08lX to list\n", p->virt, p->phys);
++      return 0;
++}
++
++/*!
++ * Deletes buffer stracture from conversion hash tables
++ *
++ * @param   buf   SDMA memory buffer virtual addr
++ *
++ * @return       0 on success, -1 on fail
++ */
++static int delete_entry(void *buf)
++{
++      virt_phys_struct *p;
++
++      buf = (void *)((unsigned long)buf & PAGE_MASK);
++
++      list_for_each_entry(p, &buf_map, node) {
++              if (p->virt == buf) {
++                      p->use_count--;
++                      break;
++              }
++      }
++
++      if (p->use_count == 0) {
++              list_del(&p->node);
++              kfree(p);
++      }
++
++      return 0;
++}
++
++/*!
++ * Virtual to physical address conversion functio
++ *
++ * @param   buf  pointer to virtual address
++ *
++ * @return       physical address
++ */
++dma_addr_t sdma_virt_to_phys(void *buf)
++{
++      unsigned long offset = (unsigned long)buf & ~PAGE_MASK;
++      virt_phys_struct *p;
++
++      DBG(2, "searching for vaddr 0x%p offs=%08lx\n", buf, offset);
++
++#ifdef CONFIG_SDMA_IRAM
++      if (IS_IRAM_VIRT(buf)) {
++              if ((unsigned long)buf & (IRAM_UNIT_SIZE - 1)) {
++                      printk(KERN_WARNING "%s buffer offset = %ld\n",
++                             __FUNCTION__, (unsigned long)buf);
++              }
++              return (unsigned long)buf + IRAM_PHYS_BASE -
++                      (unsigned long)IRAM_VIRT_BASE;
++      }
++#endif /* CONFIG_SDMA_IRAM */
++
++      list_for_each_entry(p, &buf_map, node) {
++              if ((unsigned long)p->virt == ((unsigned long)buf & PAGE_MASK)) {
++                      return p->phys | offset;
++              }
++      }
++
++      if (virt_addr_valid(buf)) {
++              return virt_to_phys(buf);
++      }
++
++      printk(KERN_ERR "SDMA malloc: could not translate virt address 0x%p\n",
++              buf);
++      __backtrace();
++      return 0;
++}
++EXPORT_SYMBOL(sdma_virt_to_phys);
++
++/*!
++ * Physical to virtual address conversion function
++ *
++ * @param   buf  pointer to physical address
++ *
++ * @return       virtual address
++ */
++void *sdma_phys_to_virt(dma_addr_t buf)
++{
++      unsigned long offset = buf & ~PAGE_MASK;
++      virt_phys_struct *p;
++
++      DBG(1, "%s: phys=%08x\n", __FUNCTION__, buf);
++
++#ifdef CONFIG_SDMA_IRAM
++      if (IS_IRAM_PHYS(buf)) {
++              if (buf & (IRAM_UNIT_SIZE - 1)) {
++                      printk(KERN_WARNING "%s buffer offset = %ld\n",
++                             __FUNCTION__, (unsigned long)buf);
++              }
++              return buf + IRAM_VIRT_BASE - IRAM_PHYS_BASE;
++      }
++#endif                                /* CONFIG_SDMA_IRAM */
++
++      list_for_each_entry(p, &buf_map, node) {
++              if (p->phys == (buf & PAGE_MASK)) {
++                      void *ptr = (void *)((unsigned long)p->virt | offset);
++
++                      DBG(1, "%s: virt: %08lx phys: %08lx\n", __FUNCTION__,
++                              (unsigned long)p->virt | offset, p->phys);
++#if 0
++                      print_hex_dump(KERN_DEBUG, "sdma: ", DUMP_PREFIX_ADDRESS, 4, 4,
++                              ptr, 32 * 16, 0);
++#endif
++                      return ptr;
++              }
++      }
++
++      printk(KERN_ERR "SDMA malloc: could not translate phys address 0x%08x\n",
++              buf);
++      __backtrace();
++      return NULL;
++}
++EXPORT_SYMBOL(sdma_phys_to_virt);
++
++/*!
++ * Allocates uncacheable buffer
++ *
++ * @param   size    size of allocated buffer
++ * @return  pointer to buffer
++ */
++void *sdma_malloc(size_t size)
++{
++      void *buf;
++      dma_addr_t dma_addr;
++      virt_phys_struct vf;
++
++      if (size > SDMA_POOL_SIZE) {
++              printk(KERN_ERR "size in sdma_malloc is more than %d bytes\n",
++                      SDMA_POOL_SIZE);
++              return NULL;
++      } else {
++              buf = dma_pool_alloc(pool, GFP_KERNEL, &dma_addr);
++              if (buf != NULL) {
++                      vf.virt = buf;
++                      vf.phys = dma_addr;
++
++                      if (add_entry(&vf) < 0) {
++                              dma_pool_free(pool, buf, dma_addr);
++                              buf = NULL;
++                      }
++              }
++      }
++
++      DBG(2, "allocated vaddr 0x%p..%p phys: %08x..%08x\n",
++              buf, buf + size - 1, dma_addr, dma_addr + size - 1);
++      return buf;
++}
++EXPORT_SYMBOL(sdma_malloc);
++
++/*!
++ * Frees uncacheable buffer
++ *
++ * @param  buf    buffer pointer for deletion
++ */
++void sdma_free(void *buf)
++{
++#ifdef CONFIG_SDMA_IRAM
++      if (IS_IRAM_VIRT(buf)) {
++              sdma_iram_free(buf);
++              return;
++      }
++#endif        /* CONFIG_SDMA_IRAM */
++
++      dma_pool_free(pool, buf, sdma_virt_to_phys(buf));
++      delete_entry(buf);
++}
++EXPORT_SYMBOL(sdma_free);
++
++#ifdef CONFIG_SDMA_IRAM
++/*!
++ * Allocates uncacheable buffer from IRAM
++ */
++void *sdma_iram_malloc(size_t size)
++{
++      void *buf = NULL;
++      int index = -1;
++      unsigned long flags;
++
++      if (size > IRAM_UNIT_SIZE) {
++              printk(KERN_WARNING
++                     "size in sdma_iram_malloc is more than %d bytes\n",
++                     IRAM_UNIT_SIZE);
++      } else {
++              spin_lock_irqsave(&iram_pool_lock, flags);
++              if (!list_empty(&iram_free_list)) {
++                      buf =
++                          list_entry(iram_free_list.next, iram_head_t, list);
++                      list_del(iram_free_list.next);
++                      index = ((unsigned long)(buf - IRAM_VIRT_BASE)) /
++                              IRAM_UNIT_SIZE;
++                      if (index < 0 || index >= IRAM_POOL_SIZE) {
++                              spin_unlock_irqrestore(&iram_pool_lock, flags);
++                              printk(KERN_ERR "The iram pool has crashed\n");
++                              return NULL;
++                      }
++                      if (iram_pool_flag[index]) {
++                              spin_unlock_irqrestore(&iram_pool_lock, flags);
++                              printk(KERN_WARNING
++                                     "iram block %d  already has been allocated \n",
++                                     index);
++                      }
++                      iram_pool_flag[index] = 1;
++              }
++              spin_unlock_irqrestore(&iram_pool_lock, flags);
++              if ((unsigned long)buf & (IRAM_UNIT_SIZE - 1)) {
++                      printk(KERN_WARNING
++                             "the start address is not align of %d, buffer offset %ld\n",
++                             IRAM_UNIT_SIZE, (unsigned long)buf);
++
++                      buf = PTR_ALIGN(buf, IRAM_UNIT_SIZE);
++              }
++      }
++      return buf;
++}
++
++/*!
++ * Free uncacheable buffer into IRAM.
++ */
++static void sdma_iram_free(void *buf)
++{
++      iram_head_t *p;
++      int index;
++      unsigned long flags;
++
++      /* The check of parameter will be done in sdma_free */
++      index = ((unsigned long)(buf - IRAM_VIRT_BASE)) / IRAM_UNIT_SIZE;
++      spin_lock_irqsave(&iram_pool_lock, flags);
++      p = (iram_head_t *)((unsigned long)buf & ~(IRAM_UNIT_SIZE - 1));
++      list_add_tail(&(p->list), &iram_free_list);
++      if (iram_pool_flag[index]) {
++              iram_pool_flag[index] = 0;
++      } else {
++              printk(KERN_WARNING
++                     "Free %p which IRAM block %d is already freed\n", buf,
++                     index);
++      }
++      spin_unlock_irqrestore(&iram_pool_lock, flags);
++}
++
++/*!
++ * Initialized the free list of IRAM.
++ */
++static void iram_pool_init(void)
++{
++      int i;
++      iram_head_t *p;
++
++      memset(iram_pool_flag, 0, IRAM_POOL_SIZE);
++      INIT_LIST_HEAD(&iram_free_list);
++      for (i = 0; i < IRAM_POOL_SIZE; i++) {
++              p = (iram_head_t *)(IRAM_VIRT_BASE + i * IRAM_UNIT_SIZE);
++              list_add_tail(&(p->list), &iram_free_list);
++      }
++}
++#endif        /* CONFIG_SDMA_IRAM */
++
++/*!
++ * SDMA buffers pool initialization function
++ */
++void __init init_sdma_pool(void)
++{
++#ifdef CONFIG_SDMA_IRAM
++      iram_pool_init();
++#endif        /* CONFIG_SDMA_IRAM */
++
++      pool = dma_pool_create("SDMA", NULL, SDMA_POOL_SIZE, 0, 0);
++
++      INIT_LIST_HEAD(&buf_map);
++}
++
++MODULE_AUTHOR("Freescale Semiconductor, Inc.");
++MODULE_DESCRIPTION("MXC Linux SDMA API");
++MODULE_LICENSE("GPL");
+diff -urN linux.35.old/arch/arm/plat-mxc/ssi.c linux.35.new/arch/arm/plat-mxc/ssi.c
+--- linux.35.old/arch/arm/plat-mxc/ssi.c       1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/arch/arm/plat-mxc/ssi.c       2010-12-03 09:51:55.420348302 +0100
+@@ -0,0 +1,228 @@
++/*
++ * Copyright (C) 2008  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/kernel.h>
++#include <linux/mutex.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/err.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <linux/ioport.h>
++#include <mach/hardware.h>
++
++#include <mach/dma.h>
++#include <mach/ssi_port.h>
++
++#ifdef DEBUG
++static int debug = 1;
++#define dbg_lvl(n)    ((n) < debug)
++module_param(debug, int, S_IRUGO | S_IWUSR);
++#else
++#define dbg_lvl(n)    0
++static int debug;
++module_param(debug, int, 0);
++#endif
++
++#define DBG(lvl, fmt...)      do { if (dbg_lvl(lvl)) printk(KERN_DEBUG fmt); } while (0)
++
++static DEFINE_MUTEX(mxc_ssi_lock);
++
++static struct resource mxc_ssi_resources[][4] = {
++      {
++              {
++                      .start  = SSI1_BASE_ADDR,
++                      .end    = SSI1_BASE_ADDR + 0xff,
++                      .flags  = IORESOURCE_MEM,
++              },
++              {
++                      .start  = MX25_INT_SSI1,
++                      .end    = MX25_INT_SSI1,
++                      .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
++              },
++              {
++                      .start  = MXC_DMA_SSI1_16BIT_TX0,
++                      .end    = MXC_DMA_SSI1_16BIT_TX0,
++                      .flags  = IORESOURCE_DMA,
++              },
++              {
++                      .start  = MXC_DMA_SSI1_16BIT_RX0,
++                      .end    = MXC_DMA_SSI1_16BIT_RX0,
++                      .flags  = IORESOURCE_DMA,
++              },
++      },
++      {
++              {
++                      .start  = SSI2_BASE_ADDR,
++                      .end    = SSI2_BASE_ADDR + 0xff,
++                      .flags  = IORESOURCE_MEM,
++              },
++              {
++                      .start  = MX25_INT_SSI2,
++                      .end    = MX25_INT_SSI2,
++                      .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
++              },
++              {
++                      .start  = MXC_DMA_SSI2_16BIT_TX0,
++                      .end    = MXC_DMA_SSI2_16BIT_TX0,
++                      .flags  = IORESOURCE_DMA,
++              },
++              {
++                      .start  = MXC_DMA_SSI2_16BIT_RX0,
++                      .end    = MXC_DMA_SSI2_16BIT_RX0,
++                      .flags  = IORESOURCE_DMA,
++              },
++      },
++};
++#define NUM_SSI_PORTS ARRAY_SIZE(mxc_ssi_ports)
++
++static struct mxc_ssi_port mxc_ssi_ports[] = {
++      {
++              .num    = 0,
++              .owner  = THIS_MODULE,
++              .res    = mxc_ssi_resources[0],
++      },
++      {
++              .num    = 1,
++              .owner  = THIS_MODULE,
++              .res    = mxc_ssi_resources[1],
++      },
++};
++
++static int _mxc_ssi_init_port(int index, struct platform_device *parent,
++                           struct mxc_ssi_port **ssi_port)
++{
++      int ret = -EBUSY;
++      struct mxc_ssi_port *port = &mxc_ssi_ports[index];
++      struct platform_device *pdev;
++      struct resource *res;
++
++      BUG_ON(index < 0 || index >= NUM_SSI_PORTS);
++
++      pdev = platform_device_register_simple("mxc-ssi", index,
++                                      port->res,
++                                      ARRAY_SIZE(mxc_ssi_resources[index]));
++      if (pdev == NULL) {
++              return -ENOMEM;
++      }
++      DBG(0, "%s: Added platform_device %s\n", __FUNCTION__, pdev->name);
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (!res) {
++              ret = -ENODEV;
++              goto pdev_free;
++      }
++
++      DBG(0, "%s: Requesting mem region %08lx..%08lx\n", __FUNCTION__,
++              (unsigned long)res->start, (unsigned long)res->end);
++      if (!request_mem_region(res->start, resource_size(res), parent->name)) {
++              ret = -EBUSY;
++              goto pdev_free;
++      }
++
++      port->ssi_clk = clk_get(&pdev->dev, NULL);
++      if (IS_ERR(port->ssi_clk)) {
++              ret = PTR_ERR(port->ssi_clk);
++              dev_err(&pdev->dev, "Failed to get SSI clock: %d\n", ret);
++              goto pdev_free;
++      }
++      port->in_use = 1;
++      port->parent = pdev;
++      *ssi_port = port;
++      return 0;
++
++pdev_free:
++      DBG(0, "%s: Unregistering %s\n", __FUNCTION__, pdev->name);
++      platform_device_unregister(pdev);
++      return ret;
++}
++
++static inline void mxc_ssi_reserve_port(int index)
++{
++      mxc_ssi_ports[index].in_use++;
++      BUG_ON(mxc_ssi_ports[index].in_use != 1);
++}
++
++static inline void mxc_ssi_unreserve_port(int index)
++{
++      mxc_ssi_ports[index].in_use--;
++      BUG_ON(mxc_ssi_ports[index].in_use);
++}
++
++static inline int mxc_ssi_port_in_use(int index)
++{
++      return mxc_ssi_ports[index].in_use;
++}
++
++int mxc_ssi_request_port(int index, struct platform_device *parent,
++                       struct mxc_ssi_port **ssi_port)
++{
++      int ret = -EBUSY;
++
++      if (index > 0 && index >= NUM_SSI_PORTS) {
++              dev_err(&parent->dev, "Bad SSI port index %d; valid range: 0..%d or <0 for any port\n",
++                      index, NUM_SSI_PORTS - 1);
++              return -EINVAL;
++      }
++
++      if (ssi_port == NULL) {
++              dev_err(&parent->dev, "No pointer for return value\n");
++              return -EINVAL;
++      }
++
++      mutex_lock(&mxc_ssi_lock);
++      if (index >= 0 && !mxc_ssi_port_in_use(index)) {
++              ret = 0;
++      } else {
++              for (index = 0; index < NUM_SSI_PORTS; index++) {
++                      if (!mxc_ssi_port_in_use(index)) {
++                              ret = 0;
++                              break;
++                      }
++              }
++      }
++      if (ret != 0) {
++              dev_dbg(&parent->dev, "All SSI ports are in use\n");
++              goto unlock;
++      }
++      mxc_ssi_reserve_port(index);
++
++      ret = _mxc_ssi_init_port(index, parent, ssi_port);
++      if (ret)
++              goto err;
++
++      ret = index;
++      goto unlock;
++
++err:
++      mxc_ssi_unreserve_port(index);
++unlock:
++      mutex_unlock(&mxc_ssi_lock);
++      return ret;
++}
++EXPORT_SYMBOL(mxc_ssi_request_port);
++
++void mxc_ssi_release_port(struct mxc_ssi_port *ssi_port)
++{
++      if (ssi_port != NULL) {
++              WARN_ON(!ssi_port->in_use);
++              clk_put(ssi_port->ssi_clk);
++              ssi_port->in_use = 0;
++              platform_device_unregister(ssi_port->parent);
++      }
++}
++EXPORT_SYMBOL(mxc_ssi_release_port);
+diff -urN linux.35.old/drivers/input/touchscreen/ads7846.c linux.35.new/drivers/input/touchscreen/ads7846.c
+--- linux.35.old/drivers/input/touchscreen/ads7846.c   2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/input/touchscreen/ads7846.c   2011-01-12 08:13:18.592488310 +0100
+@@ -604,6 +604,9 @@
+               if (ts->swap_xy)
+                       swap(x, y);
++              if (1/*ts->mirror_x*/)
++                      x = 4096 - x;
++
+               input_report_abs(input, ABS_X, x);
+               input_report_abs(input, ABS_Y, y);
+               input_report_abs(input, ABS_PRESSURE, ts->pressure_max - Rt);
+diff -urN linux.35.old/drivers/input/touchscreen/imx_adc_ts.c linux.35.new/drivers/input/touchscreen/imx_adc_ts.c
+--- linux.35.old/drivers/input/touchscreen/imx_adc_ts.c        1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/input/touchscreen/imx_adc_ts.c        2010-12-03 09:51:55.420348302 +0100
+@@ -0,0 +1,162 @@
++/*
++ * Copyright 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 imx_adc_ts.c
++ *
++ * @brief Driver for the Freescale Semiconductor i.MX ADC touchscreen.
++ *
++ * This touchscreen driver is designed as a standard input driver.  It is a
++ * wrapper around the low level ADC driver. Much of the hardware configuration
++ * and touchscreen functionality is implemented in the low level ADC driver.
++ * During initialization, this driver creates a kernel thread.  This thread
++ * then calls the ADC driver to obtain touchscreen values continously. These
++ * values are then passed to the input susbsystem.
++ *
++ * @ingroup touchscreen
++ */
++
++#include <linux/kernel.h>
++#include <linux/kthread.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/input.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/freezer.h>
++#include <linux/imx_adc.h>
++
++#define IMX_ADC_TS_NAME       "imx_adc_ts"
++
++static struct input_dev *imx_inputdev;
++static u32 input_ts_installed;
++
++static int cal[7] = {1,0,0,0,1,0,1};
++module_param_array(cal, int, NULL, 0);
++MODULE_PARM_DESC(cal, "Touchscreen calibration values as reported by \
++ts_calibrate");
++
++static int dim[4] = { 190, 3960, 60, 4000};
++module_param_array(dim, int, NULL, 0);
++MODULE_PARM_DESC(dim, "Maximum touchscreen range (x-left, x-right, y-top, \
++y-bottom)");
++
++static int axis_swap = 0;
++module_param(axis_swap, int, 0);
++MODULE_PARM_DESC(axis_swap, "Swap X and Y axis");
++
++static void imx_adc_ts_calibrate(struct input_dev *idev, u32 *pressure,
++u32 *x, u32 *y)
++{
++       int xtemp,ytemp;
++
++       if (!cal[6])
++               cal[6] = 1;
++
++       xtemp = *x; ytemp = *y;
++       *x =    ( cal[2] +
++               cal[0]*xtemp +
++               cal[1]*ytemp ) / cal[6];
++       *y =    ( cal[5] +
++               cal[3]*xtemp +
++               cal[4]*ytemp ) / cal[6];
++
++}
++
++
++static int ts_thread(void *arg)
++{
++      struct t_touch_screen ts_sample;
++      int wait = 0;
++      daemonize("imx_adc_ts");
++      while (input_ts_installed) {
++              try_to_freeze();
++
++              memset(&ts_sample, 0, sizeof(ts_sample));
++              if (0 != imx_adc_get_touch_sample(&ts_sample, !wait))
++                      continue;
++
++              if (axis_swap)
++                      swap(ts_sample.x_position, ts_sample.y_position);
++
++              if (!(dim[0] || dim[1] || dim[2] || dim[3]))
++                      imx_adc_ts_calibrate(imx_inputdev, &ts_sample.contact_resistance, &ts_sample.x_position, &ts_sample.y_position);
++
++              input_report_abs(imx_inputdev, ABS_X, ts_sample.x_position);
++              input_report_abs(imx_inputdev, ABS_Y, ts_sample.y_position);
++              input_report_abs(imx_inputdev, ABS_PRESSURE,
++                               ts_sample.contact_resistance);
++              input_sync(imx_inputdev);
++              wait = ts_sample.contact_resistance;
++              msleep(10);
++      }
++
++      return 0;
++}
++
++static int __init imx_adc_ts_init(void)
++{
++      int retval;
++
++      if (!is_imx_adc_ready())
++              return -ENODEV;
++
++      imx_inputdev = input_allocate_device();
++      if (!imx_inputdev) {
++              pr_err("imx_ts_init: not enough memory for input device\n");
++              return -ENOMEM;
++      }
++
++      imx_inputdev->name = IMX_ADC_TS_NAME;
++      imx_inputdev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
++      imx_inputdev->keybit[BIT_WORD(BTN_TOUCH)] |= BIT_MASK(BTN_TOUCH);
++      imx_inputdev->absbit[0] =
++          BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) | BIT_MASK(ABS_PRESSURE);
++
++
++      if (axis_swap) {
++              swap(dim[0], dim[2]);
++              swap(dim[1], dim[3]);
++      }
++
++      input_set_abs_params(imx_inputdev, ABS_X, dim[0], dim[1], 0, 0);
++      input_set_abs_params(imx_inputdev, ABS_Y, dim[2], dim[3], 0, 0);
++
++      retval = input_register_device(imx_inputdev);
++      if (retval < 0) {
++              input_free_device(imx_inputdev);
++              return retval;
++      }
++
++      input_ts_installed = 1;
++      kthread_run(ts_thread, NULL, "ts_thread");
++      pr_info("i.MX ADC input touchscreen loaded.\n");
++      return 0;
++}
++
++static void __exit imx_adc_ts_exit(void)
++{
++      input_ts_installed = 0;
++      input_unregister_device(imx_inputdev);
++//    if (imx_inputdev) {                             // input_free_device() must not be used after calling input_unregister_device()
++//            input_free_device(imx_inputdev);
++              imx_inputdev = NULL;
++//    }
++}
++
++late_initcall(imx_adc_ts_init);
++module_exit(imx_adc_ts_exit);
++
++MODULE_DESCRIPTION("i.MX ADC input touchscreen driver");
++MODULE_AUTHOR("Freescale Semiconductor, Inc.");
++MODULE_LICENSE("GPL");
+diff -urN linux.35.old/drivers/input/touchscreen/Kconfig linux.35.new/drivers/input/touchscreen/Kconfig
+--- linux.35.old/drivers/input/touchscreen/Kconfig     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/input/touchscreen/Kconfig     2010-12-03 09:51:55.420348302 +0100
+@@ -268,6 +268,18 @@
+         To compile this driver as a module, choose M here: the
+         module will be called jornada720_ts.
++config TOUCHSCREEN_IMX_ADC
++      tristate "Freescale i.MX ADC touchscreen input driver"
++      depends on IMX_ADC
++      help
++        Say Y here if you have a Freescale i.MX based board with a
++        touchscreen interfaced to the processor's integrated ADC.
++
++        If unsure, say N.
++
++        To compile this driver as a module, choose M here: the
++        module will be called imx_adc_ts.
++
+ config TOUCHSCREEN_HTCPEN
+       tristate "HTC Shift X9500 touchscreen"
+       depends on ISA
+@@ -339,6 +351,13 @@
+         To compile this driver as a module, choose M here: the
+         module will be called atmel_tsadcc.
++config TOUCHSCREEN_MXC_TSC
++      tristate "i.MX25 Touchscreen Interface"
++      depends on ARCH_MX25
++      help
++        Say Y here if you have a 4-wire touchscreen connected to the
++          ADC Controller on your Freescale i.MX25 SoC.
++
+ config TOUCHSCREEN_UCB1400
+       tristate "Philips UCB1400 touchscreen"
+       depends on AC97_BUS
+diff -urN linux.35.old/drivers/input/touchscreen/Makefile linux.35.new/drivers/input/touchscreen/Makefile
+--- linux.35.old/drivers/input/touchscreen/Makefile    2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/input/touchscreen/Makefile    2010-12-03 09:51:55.420348302 +0100
+@@ -27,6 +27,8 @@
+ obj-$(CONFIG_TOUCHSCREEN_HP600)               += hp680_ts_input.o
+ obj-$(CONFIG_TOUCHSCREEN_HP7XX)               += jornada720_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_HTCPEN)      += htcpen.o
++obj-$(CONFIG_TOUCHSCREEN_MXC_TSC)     += mxc_tsc.o
++obj-$(CONFIG_TOUCHSCREEN_IMX_ADC)     += imx_adc_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)       += usbtouchscreen.o
+ obj-$(CONFIG_TOUCHSCREEN_PCAP)                += pcap_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)    += penmount.o
+diff -urN linux.35.old/drivers/input/touchscreen/mxc_tsc.c linux.35.new/drivers/input/touchscreen/mxc_tsc.c
+--- linux.35.old/drivers/input/touchscreen/mxc_tsc.c   1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/input/touchscreen/mxc_tsc.c   2010-12-03 09:51:55.424347282 +0100
+@@ -0,0 +1,1162 @@
++/*
++ *  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.
++ */
++#define DEBUG
++
++/* FIXME: pressure values, calculated according to the formula
++ * found in the i.MX25 Reference Manual, seem rather bogus
++ */
++#define REPORT_PRESSURE
++
++#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 <linux/slab.h>
++#include <mach/mxc_tsc.h>
++
++#include "mxc_tsc.h"
++
++#define TSC_NUM_SAMPLES               4       /* 1..16 */
++#define ADC_NUM_SAMPLES               16      /* 1..16 */
++
++/* Default settling times */
++#define SETTLE_PCHG   0       /* 0..255 */
++#define SETTLE_DET    16
++#define SETTLE_MEAS   32
++
++
++#if (TSC_NUM_SAMPLES <= 0) || (TSC_NUM_SAMPLES > 16)
++#error Invalid value for TSC_NUM_SAMPLES
++#endif
++
++#if (ADC_NUM_SAMPLES <= 0) || (ADC_NUM_SAMPLES > 16)
++#error Invalid value for ADC_NUM_SAMPLES
++#endif
++
++#ifdef DEBUG
++static int debug = 1;
++#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
++
++static unsigned int settle_detect;
++static unsigned int settle_measure;
++static unsigned int settle_precharge;
++module_param(settle_detect, int, S_IRUGO);
++module_param(settle_measure, int, S_IRUGO);
++module_param(settle_precharge, int, S_IRUGO);
++
++
++#define DEFAULT_ADC_CLOCK     1666667
++#define DEFAULT_RX_VALUE      360
++
++struct mxc_tsc_fifo_entry {
++      unsigned int id:4,
++              data:12;
++};
++
++/* The layout of this structure depends on the setup created by mxc_tsc_config() */
++struct mxc_tsc_ts_data {
++      struct mxc_tsc_fifo_entry pendown[TSC_NUM_SAMPLES];
++      struct mxc_tsc_fifo_entry pos_x[TSC_NUM_SAMPLES];
++      struct mxc_tsc_fifo_entry pos_y[TSC_NUM_SAMPLES];
++#ifdef REPORT_PRESSURE
++      struct mxc_tsc_fifo_entry yn[TSC_NUM_SAMPLES];
++      struct mxc_tsc_fifo_entry xp[TSC_NUM_SAMPLES];
++#endif
++      struct mxc_tsc_fifo_entry pendown2[TSC_NUM_SAMPLES];
++};
++
++struct mxc_tsc_adc_data {
++      struct mxc_tsc_fifo_entry data[ADC_NUM_SAMPLES];
++};
++
++typedef union {
++      unsigned int fifo[sizeof(struct mxc_tsc_adc_data) / sizeof(int)];
++      struct mxc_tsc_adc_data data;
++} mxc_tsc_adc_fifo;
++
++typedef union {
++      unsigned int fifo[sizeof(struct mxc_tsc_ts_data) / sizeof(int)];
++      struct mxc_tsc_ts_data data;
++      struct mxc_tsc_fifo_entry raw[sizeof(struct mxc_tsc_ts_data) / sizeof(int)];
++} mxc_tsc_ts_fifo;
++
++struct mxc_tsc_irqbuf {
++      wait_queue_head_t       wq;
++      long                    timeout;
++      unsigned long           reg_base;
++      unsigned int            *data;
++      unsigned short          reqcount;
++      unsigned short          irqcount;
++      unsigned short          chunk_size;
++};
++
++struct mxc_tsc {
++      struct input_dev        *input;
++      char                    phys[32];
++      void __iomem            *reg_base;
++      struct clk              *clk;
++      int                     irq;
++      struct work_struct      work;
++      struct timer_list       timer;
++      spinlock_t              irq_lock;
++      wait_queue_head_t       wq;
++      unsigned int            pendown:1,
++                              clk_enabled:1,
++                              attrs:1,
++                              active:1;
++      struct mxc_tsc_irqbuf   adc_buf;
++      struct mxc_tsc_irqbuf   tsc_buf;
++      mxc_tsc_ts_fifo         *tsc_data;
++      mxc_tsc_adc_fifo        *adc_data;
++      struct mutex            tsc_mutex;
++      struct mutex            adc_mutex;
++
++      /* parameters from platform_data or module_param */
++      mxc_tsc_mode            tsc_mode;
++      unsigned int            r_xplate;
++      unsigned int            settle_pchg;
++      unsigned int            settle_meas;
++      unsigned int            settle_det;
++
++      /* conversion clock rate in kHz */
++      unsigned long           clkrate;
++      unsigned short          pressure;
++      unsigned short          prev_absx;
++      unsigned short          prev_absy;
++};
++
++static inline u32 mxc_tsc_read(struct mxc_tsc *ts_dev, int reg)
++{
++      return __raw_readl(ts_dev->reg_base + reg);
++}
++
++static inline void mxc_tsc_write(struct mxc_tsc *ts_dev, int reg, u32 val)
++{
++      __raw_writel(val, ts_dev->reg_base + reg);
++}
++
++static inline void mxc_tsc_set_mask(struct mxc_tsc *ts_dev, int reg, u32 mask)
++{
++      u32 val = mxc_tsc_read(ts_dev, reg);
++      val |= mask;
++      mxc_tsc_write(ts_dev, reg, val);
++}
++
++static inline void mxc_tsc_clr_mask(struct mxc_tsc *ts_dev, int reg, u32 mask)
++{
++      u32 val = mxc_tsc_read(ts_dev, reg);
++      val &= ~mask;
++      mxc_tsc_write(ts_dev, reg, val);
++}
++
++static void tsc_clk_enable(struct mxc_tsc *ts_dev)
++{
++      if (!ts_dev->clk_enabled) {
++              clk_enable(ts_dev->clk);
++              mxc_tsc_set_mask(ts_dev, TGCR, TGCR_IPG_CLK_EN);
++              ts_dev->clk_enabled = 1;
++      }
++}
++
++static void tsc_clk_disable(struct mxc_tsc *ts_dev)
++{
++      if (ts_dev->clk_enabled) {
++              mxc_tsc_clr_mask(ts_dev, TGCR, TGCR_IPG_CLK_EN);
++              clk_disable(ts_dev->clk);
++              ts_dev->clk_enabled = 0;
++      }
++}
++
++static inline int mxc_tsc_pendown(struct mxc_tsc *ts_dev)
++{
++      return ts_dev->pendown;
++}
++
++static inline void mxc_tsc_read_fifo(struct mxc_tsc *ts_dev,
++                              struct mxc_tsc_irqbuf *irqbuf)
++{
++      int start = irqbuf->irqcount;
++      int cqsr = mxc_tsc_read(ts_dev, irqbuf->reg_base + CQSR);
++      int num_items = irqbuf->chunk_size;
++      int i;
++
++      for (i = 0; i < num_items && !(cqsr & CQSR_EMPT); i++) {
++              u32 reg = mxc_tsc_read(ts_dev, irqbuf->reg_base + CQFIFO);
++
++              BUG_ON(irqbuf->irqcount < 0);
++              if (likely(irqbuf->irqcount < irqbuf->reqcount)) {
++                      BUG_ON(irqbuf->data == NULL);
++                      irqbuf->data[irqbuf->irqcount] = reg;
++              } else {
++                      DBG(0, "%s: Dropping spurious data sample[%d/%d] on %s queue: %08x\n",
++                              __FUNCTION__, irqbuf->irqcount,
++                              irqbuf->reqcount,
++                              irqbuf == &ts_dev->adc_buf ? "ADC" : "TSC",
++                              reg);
++              }
++              irqbuf->irqcount++;
++              cqsr = mxc_tsc_read(ts_dev, irqbuf->reg_base + CQSR);
++      }
++
++      if (irqbuf->irqcount == irqbuf->reqcount) {
++              WARN_ON(!(mxc_tsc_read(ts_dev, irqbuf->reg_base + CQSR) &
++                              CQSR_EMPT));
++              wake_up(&irqbuf->wq);
++      }
++      DBG(1, "%s: Read %u items [%d..%d] from fifo\n", __FUNCTION__,
++              irqbuf->irqcount - start, start, irqbuf->irqcount - 1);
++}
++
++static int mxc_tsc_wait_data(struct mxc_tsc *ts_dev,
++                           struct mxc_tsc_irqbuf *irqbuf)
++{
++      int ret;
++
++      ret = wait_event_timeout(irqbuf->wq,
++                              irqbuf->irqcount >= irqbuf->reqcount,
++                              irqbuf->timeout);
++
++      if (ret == 0 && irqbuf->irqcount < irqbuf->reqcount) {
++              DBG(0, "%s: Timeout waiting for %s data: got %u of %u samples\n",
++                      __FUNCTION__, irqbuf == &ts_dev->adc_buf ?
++                      "ADC" : "TSC", irqbuf->irqcount, irqbuf->reqcount);
++
++              mxc_tsc_set_mask(ts_dev, irqbuf->reg_base + CQCR,
++                              CQCR_FRST | CQCR_QRST);
++              mxc_tsc_clr_mask(ts_dev, irqbuf->reg_base + CQCR,
++                              CQCR_FRST | CQCR_QRST);
++              return -ETIME;
++      }
++      return 0;
++}
++
++static int mxc_tsc_read_adc(struct mxc_tsc *ts_dev, int chan)
++{
++      int ret;
++      u32 reg;
++      int i;
++      struct mxc_tsc_irqbuf *irqbuf = &ts_dev->adc_buf;
++      struct mxc_tsc_adc_data *adc_data = &ts_dev->adc_data->data;
++
++      mutex_lock(&ts_dev->adc_mutex);
++
++      memset(adc_data, 0, sizeof(*adc_data));
++      if (WARN_ON(irqbuf->irqcount)) {
++              irqbuf->irqcount = 0;
++      }
++      irqbuf->reqcount = ADC_NUM_SAMPLES;
++
++      reg = mxc_tsc_read(ts_dev, GCC0);
++      reg = (reg & ~CC_SELIN_MASK) | chan;
++      mxc_tsc_write(ts_dev, GCC0, reg);
++
++      /* enable data ready and end of conversion interrupt */
++      mxc_tsc_clr_mask(ts_dev, GCQMR,
++                      CQMR_EOQ_IRQ_MSK |
++                      CQMR_FDRY_IRQ_MSK |
++                      CQMR_FOR_IRQ_MSK |
++                      CQMR_FER_IRQ_MSK);
++      /* start conversion */
++      mxc_tsc_set_mask(ts_dev, GCQCR, CQCR_FQS);
++
++      ret = mxc_tsc_wait_data(ts_dev, irqbuf);
++      if (ret) {
++              goto exit;
++      }
++      irqbuf->irqcount = 0;
++
++      DBG(2, "%s: Read %u words from fifo\n", __FUNCTION__, irqbuf->reqcount);
++      for (i = 0; i < irqbuf->reqcount; i++) {
++              DBG(2, "%s: data[0x%x]=%4d\n", __FUNCTION__, i,
++                  adc_data->data[i].data);
++      }
++exit:
++      mxc_tsc_set_mask(ts_dev, GCQMR, CQMR_EOQ_IRQ_MSK | CQMR_FDRY_IRQ_MSK);
++      mutex_unlock(&ts_dev->adc_mutex);
++
++      return ret;
++}
++
++static int mxc_tsc_data_valid(struct mxc_tsc_fifo_entry *data, int num_samples)
++{
++      int valid = 0;
++      int i;
++
++      for (i = 0; i < num_samples; i++) {
++              DBG(2, "%s: data[%d]=%d:%d\n", __FUNCTION__, i,
++                      data[i].id, data[i].data);
++              valid |= data[i].data != 0;
++      }
++      return valid;
++}
++
++static int mxc_tsc_get_data(struct mxc_tsc_fifo_entry *data, int num_samples)
++{
++      int value = 0;
++      int count = 0;
++      int i;
++
++      for (i = 0; i < num_samples; i++) {
++              DBG(3, "%s: data[%d]=%d:%d\n", __FUNCTION__, i,
++                      data[i].id, data[i].data);
++              if (data[i].data == 0) {
++                      DBG(2, "%s: Skipping value %d\n", __FUNCTION__, i);
++                      continue;
++              }
++              if (count == 0) {
++                      value = data[i].data;
++              } else {
++                      value = (value * count + data[i].data) / (count + 1);
++              }
++              count++;
++      }
++      data[0].data = value;
++      return value;
++}
++
++struct mxc_tsc_attr {
++      struct device_attribute attr;
++      unsigned int chan;
++};
++
++#define to_mxc_tsc_attr(a)            container_of(a, struct mxc_tsc_attr, attr)
++
++#define MXC_TSC_DEV_ATTR(_name, _mode, _chan, _read)          \
++      struct mxc_tsc_attr mxc_tsc_attr_##_name = {            \
++              .attr = __ATTR(_name,_mode,_read, NULL),        \
++              .chan = _chan,                                  \
++      }
++
++static ssize_t mxc_tsc_attr_get(struct device *dev, struct device_attribute *attr, char *buf)
++{
++      ssize_t ret;
++      struct mxc_tsc *ts_dev = dev_get_drvdata(dev);
++      struct mxc_tsc_attr *mxc_tsc_attr = to_mxc_tsc_attr(attr);
++      struct mxc_tsc_adc_data *adc_data = &ts_dev->adc_data->data;
++
++      ret = mxc_tsc_read_adc(ts_dev, mxc_tsc_attr->chan);
++      if (ret != 0) {
++              dev_err(dev, "%s: Failed to read ADC%d\n", __FUNCTION__,
++                      ((mxc_tsc_attr->chan & CC_SELIN_MASK) >>
++                              CC_SELIN_SHIFT) - 5);
++              return ret;
++      }
++      ret = sprintf(buf, "%d\n", mxc_tsc_get_data(adc_data->data,
++                      ADC_NUM_SAMPLES));
++      return ret;
++}
++
++MXC_TSC_DEV_ATTR(inaux0, S_IRUGO, CC_SELIN_INAUX0, mxc_tsc_attr_get);
++MXC_TSC_DEV_ATTR(inaux1, S_IRUGO, CC_SELIN_INAUX1, mxc_tsc_attr_get);
++MXC_TSC_DEV_ATTR(inaux2, S_IRUGO, CC_SELIN_INAUX2, mxc_tsc_attr_get);
++
++static struct attribute *mxc_tsc_attrs[] = {
++      &mxc_tsc_attr_inaux0.attr.attr,
++      &mxc_tsc_attr_inaux1.attr.attr,
++      &mxc_tsc_attr_inaux2.attr.attr,
++      NULL
++};
++
++static const struct attribute_group mxc_tsc_attr_group = {
++      .attrs = mxc_tsc_attrs,
++};
++
++static void mxc_tsc_start_measure(struct mxc_tsc *ts_dev)
++{
++      u32 reg;
++      struct mxc_tsc_ts_data *tsc_data = &ts_dev->tsc_data->data;
++      struct mxc_tsc_irqbuf *irqbuf = &ts_dev->tsc_buf;
++      mxc_tsc_ts_fifo *fifo_data = ts_dev->tsc_data;
++      unsigned long flags;
++
++      spin_lock_irqsave(&ts_dev->irq_lock, flags);
++      if (ts_dev->active) {
++              goto out;
++      }
++      ts_dev->active = 1;
++
++      memset(tsc_data, 0xee, sizeof(*tsc_data));
++      irqbuf->irqcount = 0;
++      irqbuf->reqcount = ARRAY_SIZE(fifo_data->fifo);
++
++      reg = mxc_tsc_read(ts_dev, TCQSR);
++      if (WARN_ON(!(reg & CQSR_EMPT))) {
++              DBG(0, "%s: Clearing TSC FIFO\n", __FUNCTION__);
++              mxc_tsc_set_mask(ts_dev, TCQCR, CQCR_FRST | CQCR_QRST);
++              mxc_tsc_clr_mask(ts_dev, TCQCR, CQCR_FRST | CQCR_QRST);
++      }
++      mxc_tsc_write(ts_dev, TCQSR, reg);
++
++      if (mxc_tsc_pendown(ts_dev)) {
++              /* change configuration for FQS mode */
++              reg = (0x1 << CC_YPLLSW_SHIFT) | (0x1 << CC_XNURSW_SHIFT) |
++                    CC_XPULSW;
++              mxc_tsc_write(ts_dev, TICR, reg);
++
++              /* FQS */
++              reg = mxc_tsc_read(ts_dev, TCQCR);
++              reg &= ~CQCR_QSM_MASK;
++              reg |= CQCR_QSM_FQS;
++              mxc_tsc_write(ts_dev, TCQCR, reg);
++              mxc_tsc_write(ts_dev, TCQCR, reg | CQCR_FQS);
++
++              /* enable end of conversion interrupt */
++              mxc_tsc_clr_mask(ts_dev, TCQMR, CQMR_EOQ_IRQ_MSK |
++                              CQMR_FDRY_IRQ_MSK);
++      } else {
++              /* Config idle for 4-wire */
++              mxc_tsc_write(ts_dev, TICR, TSC_4WIRE_TOUCH_DETECT);
++
++              /* Pen interrupt starts new conversion queue */
++              reg = mxc_tsc_read(ts_dev, TCQCR);
++              reg &= ~CQCR_QSM_MASK;
++              reg |= CQCR_QSM_PEN;
++              mxc_tsc_write(ts_dev, TCQCR, reg);
++
++              /* PDEN and PDBEN */
++              mxc_tsc_set_mask(ts_dev, TGCR, TGCR_PDB_EN | TGCR_PD_EN);
++
++              /* enable end of conversion interrupt */
++              mxc_tsc_clr_mask(ts_dev, TCQMR,
++                              CQMR_EOQ_IRQ_MSK |
++                              CQMR_FOR_IRQ_MSK |
++                              CQMR_FER_IRQ_MSK |
++                              CQMR_FDRY_IRQ_MSK);
++      }
++out:
++      spin_unlock_irqrestore(&ts_dev->irq_lock, flags);
++}
++
++#define LOCK_WORK
++static int mxc_tsc_read_ts(struct mxc_tsc *ts_dev, int force)
++{
++      int ret;
++      mxc_tsc_ts_fifo *fifo_data = ts_dev->tsc_data;
++      struct mxc_tsc_irqbuf *irqbuf = &ts_dev->tsc_buf;
++      struct mxc_tsc_ts_data *tsc_data = &ts_dev->tsc_data->data;
++
++#ifndef LOCK_WORK
++      mutex_lock(&ts_dev->tsc_mutex);
++#endif
++      ret = mxc_tsc_wait_data(ts_dev, irqbuf);
++      if (ret) {
++              DBG(1, "%s: Failed to get data\n", __FUNCTION__);
++              goto exit;
++      }
++
++      for (ret = 0; ret < irqbuf->reqcount; ret++) {
++              struct mxc_tsc_fifo_entry *data = &fifo_data->raw[ret];
++              DBG(2, "%s: data[%02x]@%p=%d:%03x (%08x)\n", __FUNCTION__, ret,
++                      data, data->id, data->data, fifo_data->fifo[ret]);
++      }
++
++      ret = tsc_data->pendown[0].data <= 0x600 &&
++              tsc_data->pendown2[0].data <= 0x600;
++      if (ret) {
++              int pos_x = mxc_tsc_get_data(tsc_data->pos_x, TSC_NUM_SAMPLES);
++              int pos_y = mxc_tsc_get_data(tsc_data->pos_y, TSC_NUM_SAMPLES);
++#ifdef REPORT_PRESSURE
++              int xp = mxc_tsc_get_data(tsc_data->xp, TSC_NUM_SAMPLES);
++              int yn = mxc_tsc_get_data(tsc_data->yn, TSC_NUM_SAMPLES);
++#endif
++
++              DBG(1, "%s: pos_x=%4d pos_y=%4d pd=%d\n",
++                      __FUNCTION__, pos_x, pos_y, ts_dev->pendown);
++              if (pos_x) {
++#ifdef REPORT_PRESSURE
++                      if (mxc_tsc_data_valid(tsc_data->xp, TSC_NUM_SAMPLES)) {
++                              ts_dev->pressure = ts_dev->r_xplate *
++                                      pos_x * (yn - xp) / xp / 4096;
++                              DBG(2, "%s: xp=%4d yn=%4d p=%d\n", __FUNCTION__,
++                                      xp, yn, ts_dev->pressure);
++                              if (ts_dev->pressure > 4095) {
++                                      ts_dev->pressure = 4095;
++                              }
++                      } else {
++                              DBG(0, "%s: Invalid pressure data\n",
++                                      __FUNCTION__);
++                              ret = -EINVAL;
++                      }
++#else
++                      ts_dev->pressure = 4095;
++#endif
++                      DBG(1, "%s: Detected PEN DOWN with pressure %4d\n",
++                          __FUNCTION__, ts_dev->pressure);
++              } else {
++                      DBG(0, "%s: Discarding measurement\n", __FUNCTION__);
++                      ret = -EINVAL;
++              }
++      } else {
++              DBG(1, "%s: Detected PEN UP\n", __FUNCTION__);
++              ts_dev->pendown = 0;
++      }
++exit:
++      ts_dev->active = 0;
++#ifndef LOCK_WORK
++      mutex_unlock(&ts_dev->tsc_mutex);
++#endif
++      return ret;
++}
++
++static void mxc_tsc_work(struct work_struct *w)
++{
++      struct mxc_tsc *ts_dev = container_of(w, struct mxc_tsc, work);
++      struct input_dev *input_dev = ts_dev->input;
++      struct mxc_tsc_ts_data *tsc_data = &ts_dev->tsc_data->data;
++      int ret;
++#ifdef LOCK_WORK
++      mutex_lock(&ts_dev->tsc_mutex);
++#endif
++      ret = mxc_tsc_read_ts(ts_dev, 0);
++      DBG(1, "%s: mxc_tsc_read_ts() returned %d\n", __FUNCTION__, ret);
++      if (ret > 0) {
++              DBG(1, "%s: Got sample pd=%d\n", __FUNCTION__,
++                      ts_dev->pendown);
++              if (mxc_tsc_pendown(ts_dev)) {
++                      DBG(2, "%s: Reporting PD event %4d @ %4d,%4d\n",
++                              __FUNCTION__, ts_dev->pressure,
++                              tsc_data->pos_x[0].data,
++                              tsc_data->pos_y[0].data);
++
++                      input_report_abs(input_dev, ABS_X,
++                                       tsc_data->pos_x[0].data);
++                      input_report_abs(input_dev, ABS_Y,
++                                       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 = tsc_data->pos_x[0].data;
++                      ts_dev->prev_absy = tsc_data->pos_y[0].data;
++
++                      mod_timer(&ts_dev->timer, jiffies +
++                                msecs_to_jiffies(5));
++#ifdef LOCK_WORK
++                      goto out;
++#endif
++                      return;
++              }
++      } else if (ret == 0) {
++              DBG(2, "%s: Reporting PU event: %4d,%4d\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);
++      }
++      mxc_tsc_start_measure(ts_dev);
++#ifdef LOCK_WORK
++out:
++      mutex_unlock(&ts_dev->tsc_mutex);
++#endif
++}
++
++static void mxc_tsc_timer(unsigned long data)
++{
++      struct mxc_tsc *ts_dev = (void *)data;
++      struct mxc_tsc_ts_data *tsc_data = &ts_dev->tsc_data->data;
++      struct mxc_tsc_irqbuf *irqbuf = &ts_dev->tsc_buf;
++
++      /* trigger a new conversion */
++      memset(tsc_data, 0xed, sizeof(*tsc_data));
++      irqbuf->irqcount = 0;
++
++      mxc_tsc_start_measure(ts_dev);
++}
++
++static irqreturn_t mxc_tsc_interrupt(int irq, void *dev)
++{
++      struct mxc_tsc *ts_dev = dev;
++      //struct input_dev *input_dev = ts_dev->input;
++      u32 reg;
++      u32 status = mxc_tsc_read(ts_dev, TGSR);
++
++      DBG(4, "%s: TGSR=%08x\n", __FUNCTION__, status);
++
++      if (status & TGSR_TCQ_INT) {
++              u32 mask = mxc_tsc_read(ts_dev, TCQMR);
++              u32 tcqsr;
++
++              reg = mxc_tsc_read(ts_dev, TCQSR);
++              tcqsr = reg;
++              DBG(3, "%s: TCQSR=%08x TCQMR=%08x:%08x\n", __FUNCTION__,
++                      reg, mask, reg & ~mask);
++              reg &= ~mask;
++              mxc_tsc_write(ts_dev, TCQSR, reg);
++              if (reg & (CQSR_FOR | CQSR_FER)) {
++                      DBG(-1, "%s: Fifo overrun on TSC queue\n",
++                              __FUNCTION__);
++                      mxc_tsc_set_mask(ts_dev, TCQCR, CQCR_FRST | CQCR_QRST);
++                      mxc_tsc_clr_mask(ts_dev, TCQCR, CQCR_FRST | CQCR_QRST);
++              } else if (reg & CQSR_FDRY) {
++                      struct mxc_tsc_irqbuf *irqbuf = &ts_dev->tsc_buf;
++
++                      mxc_tsc_clr_mask(ts_dev, TCQCR, CQCR_FQS);
++                      if (!(reg & CQSR_EMPT)) {
++                              mxc_tsc_read_fifo(ts_dev, irqbuf);
++                      }
++              }
++              if (reg & CQSR_PD) {
++                      ts_dev->pendown = 1;
++
++                      /* disable pen down detect */
++                      mxc_tsc_clr_mask(ts_dev, TGCR, TGCR_PD_EN);
++
++                      /* schedule new measurement */
++                      schedule_work(&ts_dev->work);
++              }
++              if (reg & CQSR_EOQ) {
++                      mxc_tsc_clr_mask(ts_dev, TCQCR, CQCR_FQS);
++
++                      /* disable end of conversion interrupt */
++                      mxc_tsc_set_mask(ts_dev, TCQMR, CQMR_EOQ_IRQ_MSK);
++
++                      DBG(1, "%s: Got EOQ interrupt TCQSR=%08x:%08x\n", __FUNCTION__,
++                              tcqsr, mxc_tsc_read(ts_dev, TCQSR));
++                      schedule_work(&ts_dev->work);
++              }
++      }
++      if (status & TGSR_GCQ_INT) {
++              u32 mask = mxc_tsc_read(ts_dev, GCQMR);
++
++              reg = mxc_tsc_read(ts_dev, GCQSR);
++              DBG(3, "%s: GCQSR=%08x GCQMR=%08x:%08x\n", __FUNCTION__,
++                      reg, mask, reg & ~mask);
++              reg &= ~mask;
++              mxc_tsc_write(ts_dev, GCQSR, reg);
++              if (reg & (CQSR_FOR | CQSR_FER)) {
++                      DBG(-1, "%s: Fifo overrun on ADC queue\n",
++                              __FUNCTION__);
++                      mxc_tsc_set_mask(ts_dev, GCQCR, CQCR_FRST | CQCR_QRST);
++                      mxc_tsc_clr_mask(ts_dev, GCQCR, CQCR_FRST | CQCR_QRST);
++              } else if (reg & CQSR_FDRY) {
++                      struct mxc_tsc_irqbuf *irqbuf = &ts_dev->adc_buf;
++
++                      mxc_tsc_clr_mask(ts_dev, GCQCR, CQCR_FQS);
++                      if (!(reg & CQSR_EMPT)) {
++                              mxc_tsc_read_fifo(ts_dev, irqbuf);
++                      }
++              }
++              if (reg & CQSR_EOQ) {
++                      mxc_tsc_clr_mask(ts_dev, GCQCR, CQCR_FQS);
++
++                      /* disable end of conversion interrupt */
++                      mxc_tsc_set_mask(ts_dev, GCQMR, CQMR_EOQ_IRQ_MSK);
++              }
++      }
++      return IRQ_HANDLED;
++}
++
++static void mxc_tsc_4wire_config(struct mxc_tsc *ts_dev)
++{
++      u32 reg;
++      int lastitemid;
++
++      /* Configure 4-wire */
++      reg = TSC_4WIRE_PRECHARGE;
++      reg |= CC_IGS;
++      mxc_tsc_write(ts_dev, TCC0, reg);
++
++      reg = TSC_4WIRE_TOUCH_DETECT;
++      reg |= (TSC_NUM_SAMPLES - 1) << CC_NOS_SHIFT;
++      reg |= ts_dev->settle_det << CC_SETTLING_TIME_SHIFT;
++      mxc_tsc_write(ts_dev, TCC1, reg);
++
++      reg = TSC_4WIRE_X_MEASURE;
++      reg |= (TSC_NUM_SAMPLES - 1) << CC_NOS_SHIFT;
++      reg |= ts_dev->settle_meas << CC_SETTLING_TIME_SHIFT;
++      mxc_tsc_write(ts_dev, TCC2, reg);
++
++      reg = TSC_4WIRE_Y_MEASURE;
++      reg |= (TSC_NUM_SAMPLES - 1) << CC_NOS_SHIFT;
++      reg |= ts_dev->settle_meas << CC_SETTLING_TIME_SHIFT;
++      mxc_tsc_write(ts_dev, TCC3, reg);
++
++      reg = TSC_4WIRE_YN_MEASURE;
++      reg |= (TSC_NUM_SAMPLES - 1) << CC_NOS_SHIFT;
++      reg |= ts_dev->settle_meas << CC_SETTLING_TIME_SHIFT;
++      mxc_tsc_write(ts_dev, TCC4, reg);
++
++      reg = TSC_4WIRE_XP_MEASURE;
++      reg |= (TSC_NUM_SAMPLES - 1) << CC_NOS_SHIFT;
++      reg |= ts_dev->settle_meas << CC_SETTLING_TIME_SHIFT;
++      mxc_tsc_write(ts_dev, TCC5, reg);
++
++#ifdef REPORT_PRESSURE
++      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_TCC4 << CQ_ITEM4_SHIFT) |
++              (TCQ_ITEM_TCC5 << CQ_ITEM5_SHIFT) |
++              (TCQ_ITEM_TCC0 << CQ_ITEM6_SHIFT) |
++              (TCQ_ITEM_TCC1 << CQ_ITEM7_SHIFT);
++      lastitemid = 7;
++      ts_dev->tsc_buf.chunk_size = 6;
++
++      /* ADC conversion requires 14 clock cycles per sample
++       * plus the settling time programmed in the TICR registers.
++       * Add 1 extra jiffy to make sure the timeout is > 0
++       */
++      ts_dev->tsc_buf.timeout = msecs_to_jiffies(
++              ((6 * TSC_NUM_SAMPLES * 14) +
++                      (2 * (ts_dev->settle_pchg * 8 + 1)) +
++                      (5 * (ts_dev->settle_meas * 8 + 1)) +
++                      (2 * (ts_dev->settle_det * 8 + 1))) /
++              ts_dev->clkrate) + 10;
++#else
++      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);
++      lastitemid = 5;
++      ts_dev->tsc_buf.chunk_size = 4;
++
++      /* ADC conversion requires 14 clock cycles per sample
++       * plus the settling time programmed in the TICR registers.
++       * Add 1 extra jiffy to make sure the timeout is > 0
++       */
++      ts_dev->tsc_buf.timeout = msecs_to_jiffies(
++              ((5 * TSC_NUM_SAMPLES * 14) +
++                      (2 * (ts_dev->settle_pchg * 8 + 1)) +
++                      (4 * (ts_dev->settle_meas * 8 + 1)) +
++                      (2 * (ts_dev->settle_det * 8 + 1))) /
++              ts_dev->clkrate + (1000 / HZ - 1)) + 1;
++#endif
++      DBG(0, "%s: TSC timeout set to %lu jiffies %lums (%u ADC clock cycles) clock: %lu\n",
++              __FUNCTION__, ts_dev->tsc_buf.timeout,
++              ((6 * TSC_NUM_SAMPLES * 14) +
++              (2 * (ts_dev->settle_pchg * 8 + 1)) +
++              (5 * (ts_dev->settle_meas * 8 + 1)) +
++              (2 * (ts_dev->settle_det * 8 + 1))) / ts_dev->clkrate + (1000 / HZ - 1),
++              (6 * TSC_NUM_SAMPLES * 14) +
++              (2 * (ts_dev->settle_pchg * 8 + 1)) +
++              (5 * (ts_dev->settle_meas * 8 + 1)) +
++              (2 * (ts_dev->settle_det * 8 + 1)), ts_dev->clkrate);
++      mxc_tsc_write(ts_dev, TCQ_ITEM_7_0, reg);
++
++      reg = mxc_tsc_read(ts_dev, TCQCR);
++      reg &= ~(CQCR_FIFOWATERMARK_MASK | CQCR_LAST_ITEM_ID_MASK);
++      reg |= (ts_dev->tsc_buf.chunk_size - 1) << CQCR_FIFOWATERMARK_SHIFT;
++      reg |= lastitemid << CQCR_LAST_ITEM_ID_SHIFT;
++      reg &= ~CQCR_PD_MSK;
++      mxc_tsc_write(ts_dev, TCQCR, reg);
++      DBG(0, "%s: TSC FIFO watermark set to %u\n", __FUNCTION__,
++              ((reg & CQCR_FIFOWATERMARK_MASK) >> CQCR_FIFOWATERMARK_SHIFT) + 1);
++
++      /* clear status bits */
++      reg = mxc_tsc_read(ts_dev, TCQSR);
++      mxc_tsc_write(ts_dev, TCQSR, reg);
++
++      mxc_tsc_clr_mask(ts_dev, TCQMR,
++                      CQMR_PD_IRQ_MSK |
++                      CQMR_EOQ_IRQ_MSK |
++                      CQMR_FDRY_IRQ_MSK |
++                      CQMR_FOR_IRQ_MSK |
++                      CQMR_FER_IRQ_MSK);
++
++      /* Config idle for 4-wire */
++      mxc_tsc_write(ts_dev, TICR, TSC_4WIRE_TOUCH_DETECT);
++}
++
++static void mxc_tsc_adc_config(struct mxc_tsc *ts_dev)
++{
++      u32 reg;
++
++      ts_dev->adc_buf.chunk_size = ADC_NUM_SAMPLES % 32;
++      reg = ((ts_dev->adc_buf.chunk_size - 1) << CQCR_FIFOWATERMARK_SHIFT) |
++              (0 << CQCR_LAST_ITEM_ID_SHIFT) |
++              CQCR_QSM_FQS;
++      mxc_tsc_write(ts_dev, GCQCR, reg);
++      DBG(0, "%s: ADC FIFO watermark set to %u\n", __FUNCTION__,
++              ((reg & CQCR_FIFOWATERMARK_MASK) >> CQCR_FIFOWATERMARK_SHIFT) + 1);
++
++      reg = ((ADC_NUM_SAMPLES - 1) << CC_NOS_SHIFT) |
++              (ts_dev->settle_meas << CC_SETTLING_TIME_SHIFT) |
++              CC_YPLLSW_OFF | CC_XNURSW_OFF | CC_XPULSW |
++              CC_SEL_REFP_INT | CC_SEL_REFN_AGND;
++      mxc_tsc_write(ts_dev, GCC0, reg);
++
++      /* ADC conversion requires 14 clock cycles per sample
++       * plus the settling time programmed in the TICR registers.
++       * Add 1 extra jiffy to make sure the timeout is > 0
++       */
++      ts_dev->adc_buf.timeout = msecs_to_jiffies(
++              ((ADC_NUM_SAMPLES * 14) +
++                      (ts_dev->settle_meas * 8 + 1)) /
++              ts_dev->clkrate) + 1;
++      DBG(0, "%s: ADC timeout set to %lu jiffies\n", __FUNCTION__,
++              ts_dev->adc_buf.timeout);
++}
++
++static void mxc_tsc_config(struct platform_device *pdev)
++{
++      struct mxc_tsc *ts_dev = platform_get_drvdata(pdev);
++      struct mxc_tsc_pdata *pdata = pdev->dev.platform_data;
++      unsigned int tgcr;
++      unsigned int pdbt = TGCR_PDBTIME128;
++      unsigned int pdben = 1;
++      unsigned int intref = 1;
++      unsigned int adc_clk = DEFAULT_ADC_CLOCK;
++      unsigned long ipg_clk;
++      unsigned int clkdiv;
++      unsigned int hsync_en = 0;
++      unsigned int hsync_pol = 0;
++
++      /* setup default settling times */
++      ts_dev->settle_det = SETTLE_DET;
++      ts_dev->settle_meas = SETTLE_MEAS;
++      ts_dev->settle_pchg = SETTLE_PCHG;
++
++      if (pdata) {
++              pdbt = pdata->pen_debounce_time - 1;
++              if (pdbt > 31) {
++                      dev_dbg(&pdev->dev, "Pen debounce time %d out of range[0..32]; using max. value\n",
++                              pdata->pen_debounce_time);
++              }
++              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;
++              hsync_en = pdata->hsyncen;
++              hsync_pol = pdata->hsyncpol;
++              if (pdata->settle_detect > 0 &&
++                      pdata->settle_detect < 256)
++                      ts_dev->settle_det = pdata->settle_detect;
++              if (pdata->settle_measure > 0 &&
++                      pdata->settle_measure < 256)
++                      ts_dev->settle_meas = pdata->settle_measure;
++              if (pdata->settle_precharge > 0 &&
++                      pdata->settle_precharge < 256)
++                      ts_dev->settle_pchg = pdata->settle_precharge;
++              DBG(0, "%s: pdbt=%d intref=%d r_xplate=%d hsync_en=%d hsync_pol=%d\n",
++                      __FUNCTION__, pdbt + 1, intref, ts_dev->r_xplate,
++                      hsync_en, hsync_pol);
++      } else {
++              dev_dbg(&pdev->dev, "No platform_data; using defaults\n");
++      }
++      if (settle_detect > 0 && settle_detect < 256)
++              ts_dev->settle_det = settle_detect;
++      if (settle_measure > 0 && settle_measure < 256)
++              ts_dev->settle_meas = settle_measure;
++      if (settle_precharge > 0 && settle_precharge < 256)
++              ts_dev->settle_pchg = settle_precharge;
++
++
++      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);
++      }
++      /* calculate the actual ADC clock rate in kHz */
++      if (clkdiv < 4)
++              ts_dev->clkrate = ipg_clk / 10000;
++      else
++              ts_dev->clkrate = ipg_clk / (2 * clkdiv + 2) / 1000;
++      dev_dbg(&pdev->dev, "clkdiv=%u actual ADC clock: %lukHz\n",
++              clkdiv, ts_dev->clkrate);
++
++      tgcr = ((pdbt << TGCR_PDBTIME_SHIFT) & TGCR_PDBTIME_MASK) | /* pen debounce time */
++              (pdben * TGCR_PDB_EN) | /* pen debounce enable */
++              (intref * TGCR_INTREFEN) | /* pen debounce enable */
++              (hsync_en * TGCR_HSYNC_EN) | /* sync conversion with hsync */
++              (hsync_pol * TGCR_HSYNC_POL) | /* HSYNC polarity */
++              TGCR_POWER_SAVE | /* Switch TSC on */
++              TGCR_PD_EN |    /* Enable Pen Detect */
++              ((clkdiv << TGCR_ADCCLKCFG_SHIFT) & TGCR_ADCCLKCFG_MASK);
++
++      /* reset TSC */
++      mxc_tsc_write(ts_dev, TGCR, TGCR_TSC_RST);
++      while (mxc_tsc_read(ts_dev, TGCR) & TGCR_TSC_RST) {
++              cpu_relax();
++      }
++      mxc_tsc_write(ts_dev, TGCR, tgcr);
++
++      tsc_clk_enable(ts_dev);
++      mxc_tsc_4wire_config(ts_dev);
++      mxc_tsc_adc_config(ts_dev);
++
++      mxc_tsc_start_measure(ts_dev);
++}
++
++static int __devinit mxc_tsc_probe(struct platform_device *pdev)
++{
++      int err;
++      struct mxc_tsc *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 tsc regs")) {
++              return -EBUSY;
++      }
++
++      /* Allocate memory for device */
++      ts_dev = kzalloc(sizeof(struct mxc_tsc), 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 if using DMA */
++      ts_dev->tsc_data = kzalloc(sizeof(mxc_tsc_ts_fifo), GFP_KERNEL);
++      ts_dev->adc_data = kzalloc(sizeof(mxc_tsc_adc_fifo), 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_tsc_work);
++      mutex_init(&ts_dev->tsc_mutex);
++      mutex_init(&ts_dev->adc_mutex);
++      spin_lock_init(&ts_dev->irq_lock);
++      setup_timer(&ts_dev->timer, mxc_tsc_timer, (unsigned long)ts_dev);
++      init_waitqueue_head(&ts_dev->wq);
++      init_waitqueue_head(&ts_dev->tsc_buf.wq);
++      init_waitqueue_head(&ts_dev->adc_buf.wq);
++
++      ts_dev->tsc_buf.reg_base = TCQ_REG_BASE;
++      ts_dev->adc_buf.reg_base = GCQ_REG_BASE;
++      ts_dev->tsc_buf.data = ts_dev->tsc_data->fifo;
++      ts_dev->adc_buf.data = ts_dev->adc_data->fifo;
++
++      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_tsc_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, "tsc_clk");
++      if (IS_ERR(ts_dev->clk)) {
++              dev_err(&pdev->dev, "Failed to get tsc_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;
++
++      __set_bit(EV_KEY, input_dev->evbit);
++      __set_bit(EV_ABS, input_dev->evbit);
++      __set_bit(BTN_TOUCH, input_dev->keybit);
++      __set_bit(ABS_X, input_dev->absbit);
++      __set_bit(ABS_Y, input_dev->absbit);
++      input_set_abs_params(input_dev, ABS_X, 0, 0xFFF, 0, 0);
++      input_set_abs_params(input_dev, ABS_Y, 0, 0xFFF, 0, 0);
++#ifdef REPORT_PRESSURE
++      __set_bit(ABS_PRESSURE, input_dev->absbit);
++      input_set_abs_params(input_dev, ABS_PRESSURE, 0, 0xFFF, 0, 0);
++#endif
++      mxc_tsc_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_tsc_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_tsc_remove(struct platform_device *pdev)
++{
++      struct mxc_tsc *ts_dev = platform_get_drvdata(pdev);
++      struct resource *res;
++
++      if (ts_dev->attrs) {
++              DBG(0, "%s: Removing sysfs attributes\n", __FUNCTION__);
++              sysfs_remove_group(&pdev->dev.kobj, &mxc_tsc_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_SUSPEND
++static int mxc_tsc_suspend(struct device *dev)
++{
++      struct mxc_tsc *ts_dev = dev_get_drvdata(dev);
++
++      if (ts_dev->clk_enabled) {
++              tsc_clk_disable(ts_dev);
++              ts_dev->clk_enabled = 1;
++      }
++      return 0;
++}
++
++static int mxc_tsc_resume(struct device *dev)
++{
++      struct mxc_tsc *ts_dev = dev_get_drvdata(dev);
++
++      if (ts_dev->clk_enabled) {
++              ts_dev->clk_enabled = 0;
++              tsc_clk_enable(ts_dev);
++      }
++      return 0;
++}
++
++static struct dev_pm_ops mxc_tsc_pm_ops = {
++      .suspend        = mxc_tsc_suspend,
++      .resume         = mxc_tsc_resume,
++};
++#endif
++
++static struct platform_driver mxc_tsc_driver = {
++      .driver         = {
++              .name   = "imx-tsc",
++//            .pm     = __dev_pm_ops_p(mxc_tsc_pm_ops),
++      },
++      .probe          = mxc_tsc_probe,
++      .remove         = __devexit_p(mxc_tsc_remove),
++};
++
++static int __init mxc_tsc_init(void)
++{
++      return platform_driver_register(&mxc_tsc_driver);
++}
++
++static void __exit mxc_tsc_exit(void)
++{
++      platform_driver_unregister(&mxc_tsc_driver);
++}
++
++module_init(mxc_tsc_init);
++module_exit(mxc_tsc_exit);
++
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("i.MX25 TouchScreen Driver");
++MODULE_AUTHOR("Lothar Wassmann <LW@KARO-electronics.de>");
++MODULE_ALIAS("platform:imx-tsc");
+diff -urN linux.35.old/drivers/input/touchscreen/mxc_tsc.h linux.35.new/drivers/input/touchscreen/mxc_tsc.h
+--- linux.35.old/drivers/input/touchscreen/mxc_tsc.h   1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/input/touchscreen/mxc_tsc.h   2010-12-03 09:51:55.428348260 +0100
+@@ -0,0 +1,327 @@
++/*
++ *  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
++
++/* queue dependent register offsets wrt *_REG_BASE */
++#define CQFIFO                        0x00
++#define CQCR                  0x04
++#define CQSR                  0x08
++#define CQMR                  0x0c
++#define CQ_ITEM_7_0           0x20
++#define CQ_ITEM_15_8          0x24
++
++/* TouchScreen Convert Queue FIFO Register */
++#define TCQ_REG_BASE          0x400
++#define TCQFIFO                       (TCQ_REG_BASE + CQFIFO)
++/* TouchScreen Convert Queue Control Register */
++#define TCQCR                 (TCQ_REG_BASE + CQCR)
++#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                 (TCQ_REG_BASE + CQSR)
++#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                 (TCQ_REG_BASE + CQMR)
++#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_FDRY_IRQ_MSK     (1 << 15)
++#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          (TCQ_REG_BASE + CQ_ITEM_7_0)
++
++/* TouchScreen Convert Queue ITEM 15~8 */
++#define TCQ_ITEM_15_8         (TCQ_REG_BASE + CQ_ITEM_15_8)
++
++#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                  (TCQ_REG_BASE + 0x40)
++#define TCC1                  (TCQ_REG_BASE + 0x44)
++#define TCC2                  (TCQ_REG_BASE + 0x48)
++#define TCC3                  (TCQ_REG_BASE + 0x4c)
++#define TCC4                  (TCQ_REG_BASE + 0x50)
++#define TCC5                  (TCQ_REG_BASE + 0x54)
++#define TCC6                  (TCQ_REG_BASE + 0x58)
++#define TCC7                  (TCQ_REG_BASE + 0x5c)
++#define CC_PEN_IACK           (1 << 1)
++#define CC_SEL_REFN_SHIFT     2
++#define CC_SEL_REFN_XNUR      (0x0 << CC_SEL_REFN_SHIFT)
++#define CC_SEL_REFN_YNLR      (0x1 << CC_SEL_REFN_SHIFT)
++#define CC_SEL_REFN_AGND      (0x3 << 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_SEL_REFP_SHIFT     7
++#define CC_SEL_REFP_YPLL      (0x0 << CC_SEL_REFP_SHIFT)
++#define CC_SEL_REFP_XPUL      (0x1 << CC_SEL_REFP_SHIFT)
++#define CC_SEL_REFP_EXT               (0x2 << CC_SEL_REFP_SHIFT)
++#define CC_SEL_REFP_INT               (0x3 << CC_SEL_REFP_SHIFT)
++#define CC_SEL_REFP_MASK              (0x3 << CC_SEL_REFP_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   (               \
++              CC_SEL_REFN_AGND |              \
++              CC_SELIN_XPUL |                 \
++              CC_SEL_REFP_INT |               \
++              CC_XNURSW_OFF |                 \
++              CC_YPLLSW_OFF |                 \
++              0)                              \
++/*0x158c*/
++#define TSC_4WIRE_TOUCH_DETECT        (               \
++              CC_PEN_IACK |                   \
++              CC_SEL_REFN_AGND |              \
++              CC_SELIN_XPUL |                 \
++              CC_SEL_REFP_INT |               \
++              CC_XPULSW |                     \
++              CC_XNURSW_OFF |                 \
++              CC_YPLLSW_OFF |                 \
++              CC_YNLRSW |                     \
++              0)                              \
++/*0x578e*/
++
++#define TSC_4WIRE_X_MEASURE   (               \
++              CC_SEL_REFN_XNUR |              \
++              CC_SELIN_YPLL |                 \
++              CC_SEL_REFP_XPUL |              \
++              CC_XNURSW_LOW |                 \
++              CC_YPLLSW_OFF |                 \
++              0)                              \
++/*0x1c90*/
++#define TSC_4WIRE_Y_MEASURE   (               \
++              CC_SEL_REFN_YNLR |              \
++              CC_SELIN_XPUL |                 \
++              CC_SEL_REFP_YPLL |              \
++              CC_XPULSW |                     \
++              CC_XNURSW_OFF |                 \
++              CC_YNLRSW |                     \
++              0)                              \
++/*0x4604*/
++#define TSC_4WIRE_XP_MEASURE  (               \
++              CC_SEL_REFN_AGND |              \
++              CC_SELIN_XPUL |                 \
++              CC_SEL_REFP_INT |               \
++              CC_XPULSW |                     \
++              CC_YPLLSW_HIGH |                \
++              CC_XNURSW_LOW |                 \
++              0)                              \
++/*0x0f8c*/
++#define TSC_4WIRE_YN_MEASURE  (               \
++              CC_SEL_REFN_AGND |              \
++              CC_SELIN_YNLR |                 \
++              CC_SEL_REFP_INT |               \
++              CC_XPULSW |                     \
++              CC_YPLLSW_HIGH |                \
++              CC_XNURSW_LOW |                 \
++              0)                              \
++/*0x0fbc*/
++
++#define TSC_GENERAL_ADC_GCC0  (               \
++              CC_SEL_REFN_AGND |              \
++              CC_SELIN_INAUX0 |               \
++              CC_SEL_REFP_INT |               \
++              CC_XPULSW |                     \
++              CC_XNURSW_OFF |                 \
++              CC_YPLLSW_OFF |                 \
++              0)                              \
++/*0x17dc*/
++#define TSC_GENERAL_ADC_GCC1  (               \
++              CC_SEL_REFN_AGND |              \
++              CC_SELIN_INAUX0 |               \
++              CC_SEL_REFP_INT |               \
++              CC_XPULSW |                     \
++              CC_XNURSW_OFF |                 \
++              CC_YPLLSW_OFF |                 \
++              0)                              \
++/*0x17ec*/
++#define TSC_GENERAL_ADC_GCC2  (               \
++              CC_SEL_REFN_AGND |              \
++              CC_SELIN_INAUX0 |               \
++              CC_SEL_REFP_INT |               \
++              CC_XPULSW |                     \
++              CC_XNURSW_OFF |                 \
++              CC_YPLLSW_OFF |                 \
++              0)                              \
++/*0x17fc*/
++
++/* GeneralADC Convert Queue FIFO Register */
++#define GCQ_REG_BASE          0x800
++#define GCQFIFO                       (GCQ_REG_BASE + CQFIFO)
++#define GCQFIFO_ADCOUT_SHIFT  4
++#define GCQFIFO_ADCOUT_MASK   (0xfff << GCQFIFO_ADCOUT_SHIFT)
++
++/* GeneralADC Convert Queue Control Register */
++#define GCQCR                 (GCQ_REG_BASE + CQCR)
++
++/* GeneralADC Convert Queue Status Register */
++#define GCQSR                 (GCQ_REG_BASE + CQSR)
++
++/* GeneralADC Convert Queue Mask Register */
++#define GCQMR                 (GCQ_REG_BASE + CQMR)
++
++/* GeneralADC Convert Queue ITEM 7~0 */
++#define GCQ_ITEM_7_0          (GCQ_REG_BASE + CQ_ITEM_7_0)
++
++/* GeneralADC Convert Queue ITEM 15~8 */
++#define GCQ_ITEM_15_8         (GCQ_REG_BASE + CQ_ITEM_15_8)
++
++#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                  (GCQ_REG_BASE + 0x40)
++#define GCC1                  (GCQ_REG_BASE + 0x44)
++#define GCC2                  (GCQ_REG_BASE + 0x48)
++#define GCC3                  (GCQ_REG_BASE + 0x4c)
++#define GCC4                  (GCQ_REG_BASE + 0x50)
++#define GCC5                  (GCQ_REG_BASE + 0x54)
++#define GCC6                  (GCQ_REG_BASE + 0x58)
++#define GCC7                  (GCQ_REG_BASE + 0x5c)
++
++/* 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 -urN linux.35.old/drivers/Kconfig linux.35.new/drivers/Kconfig
+--- linux.35.old/drivers/Kconfig       2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/Kconfig       2010-12-03 09:51:55.428348260 +0100
+@@ -2,6 +2,8 @@
+ source "drivers/base/Kconfig"
++source "drivers/mxc/Kconfig"
++
+ source "drivers/connector/Kconfig"
+ source "drivers/mtd/Kconfig"
+diff -urN linux.35.old/drivers/Makefile linux.35.new/drivers/Makefile
+--- linux.35.old/drivers/Makefile      2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/Makefile      2010-12-03 09:51:55.428348260 +0100
+@@ -92,6 +92,7 @@
+ obj-y                         += lguest/
+ obj-$(CONFIG_CPU_FREQ)                += cpufreq/
+ obj-$(CONFIG_CPU_IDLE)                += cpuidle/
++obj-$(CONFIG_ARCH_MXC)                += mxc/
+ obj-$(CONFIG_MMC)             += mmc/
+ obj-$(CONFIG_MEMSTICK)                += memstick/
+ obj-$(CONFIG_NEW_LEDS)                += leds/
+diff -urN linux.35.old/drivers/media/radio/Kconfig linux.35.new/drivers/media/radio/Kconfig
+--- linux.35.old/drivers/media/radio/Kconfig   2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/media/radio/Kconfig   2010-12-03 09:51:55.428348260 +0100
+@@ -452,4 +452,14 @@
+         found behind the Timberdale FPGA on the Russellville board.
+         Enabling this driver will automatically select the DSP and tuner.
++config RADIO_SI4705
++      tristate "SI4705 I2C FM radio support"
++      depends on I2C && VIDEO_V4L2
++      ---help---
++        Say Y here if you want to use the SI4705 FM chip found in
++        voipac dev kits. This FM chip is connected to I2C bus.
++
++        To compile this driver as a module, choose M here: the
++        module will be called radio-si4705.
++
+ endif # RADIO_ADAPTERS
+diff -urN linux.35.old/drivers/media/radio/Makefile linux.35.new/drivers/media/radio/Makefile
+--- linux.35.old/drivers/media/radio/Makefile  2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/media/radio/Makefile  2010-12-03 09:51:55.428348260 +0100
+@@ -26,5 +26,6 @@
+ obj-$(CONFIG_RADIO_SAA7706H) += saa7706h.o
+ obj-$(CONFIG_RADIO_TEF6862) += tef6862.o
+ obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o
++obj-$(CONFIG_RADIO_SI4705) += radio-si4705.o
+ EXTRA_CFLAGS += -Isound
+diff -urN linux.35.old/drivers/media/radio/radio-si4705.c linux.35.new/drivers/media/radio/radio-si4705.c
+--- linux.35.old/drivers/media/radio/radio-si4705.c    1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/media/radio/radio-si4705.c    2010-12-03 09:51:55.432349520 +0100
+@@ -0,0 +1,1008 @@
++/*
++ * driver/media/radio/radio-si4705.c
++ *
++ * Driver for SI4705 radio chip for linux 2.6.
++ * This driver is for SI4705 chip from Silicon Labs.
++ * The I2C protocol is used for communicate with chip.
++ *
++ * Based in radio-tea5764.c Copyright (C) 2008 Fabio Belavenuto
++ *
++ *
++ * 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
++ *
++ * History:
++ * 2010-11-10   masu <support@voipac.com>
++ *              initial code
++ *
++ * TODO:
++ *  add RDS support - partialy
++ *  add power on/off detection test in fuctions ?
++ */
++
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/init.h>                       /* Initdata                     */
++#include <linux/videodev2.h>          /* kernel radio structs         */
++#include <linux/i2c.h>                        /* I2C                          */
++#include <media/v4l2-common.h>
++#include <media/v4l2-ioctl.h>
++#include <linux/version.h>            /* for KERNEL_VERSION MACRO     */
++
++#include <linux/types.h>
++#include <linux/delay.h>
++#include <linux/jiffies.h>
++#include <linux/interrupt.h>
++
++#include "radio-si4705.h"
++
++/* Module Parameters */
++/* Radio Nr */
++static int radio_nr = -1;
++module_param(radio_nr, int, 0444);
++MODULE_PARM_DESC(radio_nr, "Video4linux device number to use");
++
++/* RDS buffer blocks */
++static unsigned int rds_buf = 80;
++module_param(rds_buf, uint, 0444);
++MODULE_PARM_DESC(rds_buf, "RDS buffer entries: *100*");
++
++/* RDS maximum block errors */
++static unsigned short max_rds_errors = 1;
++/* 0 means   0  errors requiring correction */
++/* 1 means 1-2  errors requiring correction (used by original USBRadio.exe) */
++/* 2 means 3-5  errors requiring correction */
++/* 3 means   6+ errors or errors in checkword, correction not possible */
++module_param(max_rds_errors, ushort, 0644);
++MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*");
++
++/* I2C code related */
++static unsigned i2c_timeout = 125;
++
++struct si4705_device {
++      struct i2c_client               *i2c_client;
++      struct video_device             *videodev;
++      struct si4705_reg               reg;
++      struct si4705_property          reg_property;
++      struct mutex                    mutex;
++      int                             users;
++
++      /* RDS receive buffer */
++      wait_queue_head_t               read_queue;
++      unsigned char                   *buffer;
++      unsigned int                    buf_size;
++      unsigned int                    rd_index;
++      unsigned int                    wr_index;
++
++      struct work_struct              radio_work;
++};
++
++/*
++ * si4705_do_i2c_cmd - read register
++ */
++int si4705_do_i2c_cmd(struct si4705_device *radio, u8 * txdata, u8 txsize, u8 * rxdata, u8 rxsize)
++{
++      int status = 0;
++      unsigned long timeout, read_time;
++//    struct i2c_msg msgs[2] = {
++//            { radio->i2c_client->addr, 0, txsize, (u8 *) txdata },
++//            { radio->i2c_client->addr, I2C_M_RD, rxsize, (u8 *) rxdata },
++//    };
++      struct i2c_msg tmsgs[1] = {
++              { radio->i2c_client->addr, 0, txsize, (u8 *) txdata },
++      };
++      struct i2c_msg rmsgs[1] = {
++              { radio->i2c_client->addr, I2C_M_RD, rxsize, (u8 *) rxdata },
++      };
++
++      // write
++      timeout = jiffies + msecs_to_jiffies(i2c_timeout);
++      do {
++              read_time = jiffies;
++              status = i2c_transfer(radio->i2c_client->adapter, tmsgs, 1);
++
++              // REVISIT: at HZ=100, this is sloooow
++              msleep(1);
++      } while (time_before(read_time, timeout) && status != 1);
++
++      if (status != 1)
++              return -EIO;
++
++      //read
++      timeout = jiffies + msecs_to_jiffies(i2c_timeout);
++      do {
++              read_time = jiffies;
++              status = i2c_transfer(radio->i2c_client->adapter, rmsgs, 1);
++
++              // REVISIT: at HZ=100, this is sloooow
++              msleep(1);
++      } while (time_before(read_time, timeout) && !(rxdata[0] & SI4705_STS_CTS));
++
++      if (status != 1)
++              return -EIO;
++
++      return 0;
++}
++
++int si4705_get_property(struct si4705_device * radio, u16 prop_cmd, u16 * property) {
++      u8 txdata[4];
++      u8 rxdata[4] = {0, 0, 0, 0};
++      u8 txsize = 0, rxsize = 4;
++      int ret;
++
++      txdata[txsize++] = si4705_cmd.GET_PROPERTY;
++      txdata[txsize++] = 0;
++      txdata[txsize++] = prop_cmd >> 8;
++      txdata[txsize++] = prop_cmd;
++
++      ret = si4705_do_i2c_cmd(radio, txdata, txsize, rxdata, rxsize);
++
++      *property = (rxdata[2] << 8) + rxdata[3];
++
++      return ret;
++}
++
++int si4705_set_property(struct si4705_device * radio, u16 prop_cmd, u16 property) {
++      u8 txdata[6];
++      u8 rxdata[1] = {0};
++      u8 txsize = 0, rxsize = 1;
++      int ret;
++
++      txdata[txsize++] = si4705_cmd.SET_PROPERTY;
++      txdata[txsize++] = 0;
++      txdata[txsize++] = prop_cmd >> 8;
++      txdata[txsize++] = prop_cmd;
++      txdata[txsize++] = property >> 8;
++      txdata[txsize++] = property;
++
++      ret = si4705_do_i2c_cmd(radio, txdata, txsize, rxdata, rxsize);
++
++      return ret;
++}
++
++int si4705_get_all_properties(struct si4705_device *radio) {
++      int ret = 0;
++
++      ret |= si4705_get_property(radio, si4705_prop_cmd.GPO_IEN, &(radio->reg_property.gpo_ien));
++      ret |= si4705_get_property(radio, si4705_prop_cmd.DIGITAL_OUTPUT_FORMAT, &(radio->reg_property.digital_output_format));
++      ret |= si4705_get_property(radio, si4705_prop_cmd.DIGITAL_OUTPUT_SAMPLE_RATE, &(radio->reg_property.digital_output_sample_rate));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.REFCLK_FREQ, &(radio->reg_property.refclk_freq));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.REFCLK_PRESCALE, &(radio->reg_property.refclk_prescale));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_DEEMPHASIS, &(radio->reg_property.fm_deemphasis));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_BLEND_STEREO_THRESHOLD, &(radio->reg_property.fm_blend_stereo_threshold));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_BLEND_MONO_THRESHOLD, &(radio->reg_property.fm_blend_mono_threshold));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_ANTENNA_INPUT, &(radio->reg_property.fm_antena_input));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_MAX_TUNE_ERROR, &(radio->reg_property.fm_max_tune_error));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_RSQ_INT_SOURCE, &(radio->reg_property.fm_rsq_int_source));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_RSQ_SNR_HI_THRESHOLD, &(radio->reg_property.fm_rsq_snr_hi_threshold));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_RSQ_SNR_LO_THRESHOLD, &(radio->reg_property.fm_rsq_snr_lo_threshold));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_RSQ_RSSI_HI_THRESHOLD, &(radio->reg_property.fm_rsq_rssi_hi_threshold));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_RSQ_RSSI_LO_THRESHOLD, &(radio->reg_property.fm_rsq_rssi_lo_threshold));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_RQS_BLEND_THRESHOLD, &(radio->reg_property.fm_rsq_blend_threshold));
++      ret |= si4705_get_property(radio, si4705_prop_cmd.FM_SOFT_MUTE_RATE, &(radio->reg_property.fm_soft_mute_rate));
++      ret |= si4705_get_property(radio, si4705_prop_cmd.FM_SOFT_MUTE_MAX_ATTENUATION, &(radio->reg_property.fm_soft_mute_max_attenuation));
++      ret |= si4705_get_property(radio, si4705_prop_cmd.FM_SOFT_MUTE_SNR_THRESHOLD, &(radio->reg_property.fm_soft_mute_snr_threshold));
++      ret |= si4705_get_property(radio, si4705_prop_cmd.FM_SEEK_BAND_BOTTOM, &(radio->reg_property.fm_seek_band_bottom));
++      ret |= si4705_get_property(radio, si4705_prop_cmd.FM_SEEK_BAND_TOP, &(radio->reg_property.fm_seek_band_top));
++      ret |= si4705_get_property(radio, si4705_prop_cmd.FM_SEEK_FREQ_SPACING, &(radio->reg_property.fm_seek_freq_spacing));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_SEEK_TUNE_SNR_THRESHOLD, &(radio->reg_property.fm_seek_tune_snr_threshold));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.FM_SEEK_TUNE_RSSI_TRESHOLD, &(radio->reg_property.fm_seek_tune_rssi_threshold));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.RDS_INT_SOURCE, &(radio->reg_property.rds_int_source));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.RDS_INT_FIFO_COUNT, &(radio->reg_property.rds_int_fifo_count));
++//    ret |= si4705_get_property(radio, si4705_prop_cmd.RDS_CONFIG, &(radio->reg_property.rds_config));
++      ret |= si4705_get_property(radio, si4705_prop_cmd.RX_VOLUME, &(radio->reg_property.rx_volume));
++      ret |= si4705_get_property(radio, si4705_prop_cmd.RX_HARD_MUTE, &(radio->reg_property.rx_hard_mute));
++
++      return ret;
++}
++
++/* V4L2 code related */
++static struct v4l2_queryctrl radio_qctrl[] = {
++      {
++              .id            = V4L2_CID_AUDIO_MUTE,
++              .name          = "Mute",
++              .minimum       = 0,
++              .maximum       = 1,
++              .default_value = 1,
++              .type          = V4L2_CTRL_TYPE_BOOLEAN,
++      },{
++              .id            = V4L2_CID_AUDIO_VOLUME,
++              .name          = "Volume",
++              .minimum       = 0,
++              .maximum       = 0x3f,
++              .step          = 1,
++              .default_value = 0x20,
++              .type          = V4L2_CTRL_TYPE_INTEGER,
++        }
++
++};
++
++static int si4705_power_up(struct si4705_device *radio)
++{
++      u8 txdata[3];
++      u8 rxdata[1] = {0};
++      u8 txsize = 0, rxsize = 1;
++
++      txdata[txsize++] = si4705_cmd.POWER_UP;
++      txdata[txsize++] = SI4705_PU_INT_ENABLE;
++      txdata[txsize++] = SI4705_PU_MODE_AN;
++
++      return si4705_do_i2c_cmd(radio, txdata, txsize, rxdata, rxsize);
++}
++
++static int si4705_power_down(struct si4705_device *radio)
++{
++      u8 txdata[1];
++      u8 rxdata[1] = {0};
++      u8 txsize = 0, rxsize = 1;
++
++      txdata[txsize++] = si4705_cmd.POWER_DOWN;
++
++      return si4705_do_i2c_cmd(radio, txdata, txsize, rxdata, rxsize);
++}
++
++/* tune an frequency, freq is defined by v4l's TUNER_LOW, i.e. 1/16th kHz */
++static void si4705_tune(struct si4705_device *radio, int freq)
++{
++      u8 txdata[5];
++      u8 rxdata[1] = {0};
++      u8 txsize = 0, rxsize = 1;
++
++      radio->reg.tunned_freq = freq / 10000;
++
++      txdata[txsize++] = si4705_cmd.FM_TUNE_FREQ;
++      txdata[txsize++] = 0x00;
++      txdata[txsize++] = radio->reg.tunned_freq >> 8;
++      txdata[txsize++] = radio->reg.tunned_freq;
++      txdata[txsize++] = 0x00;
++
++      if(si4705_do_i2c_cmd(radio, txdata, txsize, rxdata, rxsize)) {
++              printk(KERN_INFO "%s Error setting the frequency\n", __func__);
++      }
++}
++
++static void si4705_rds(struct si4705_device *radio, u8 cmd, u8 * data)
++{
++      u8 txdata[2];
++      u8 txsize = 0;
++
++      txdata[txsize++] = si4705_cmd.FM_RDS_STATUS;
++      txdata[txsize++] = cmd;
++
++      if(si4705_do_i2c_cmd(radio, txdata, txsize, data, 13)) {
++              printk(KERN_INFO "%s Error reading RDS data\n", __func__);
++      }
++
++//printk(KERN_INFO "Status  0x%02x '%c'\n", rxdata[0], rxdata[0]);
++//printk(KERN_INFO "Resp 1  0x%02x '%c'\n", rxdata[1], rxdata[1]);
++//printk(KERN_INFO "Resp 2  0x%02x '%c'\n", rxdata[2], rxdata[2]);
++//printk(KERN_INFO "Used    0x%02x '%c'\n", rxdata[3], rxdata[3]);
++//printk(KERN_INFO "BLOCKA  0x%02x '%c'\n", rxdata[4], rxdata[4]);
++//printk(KERN_INFO "BLOCKA  0x%02x '%c'\n", rxdata[5], rxdata[5]);
++//printk(KERN_INFO "BLOCKB  0x%02x '%c'\n", rxdata[6], rxdata[6]);
++//printk(KERN_INFO "BLOCKB  0x%02x '%c'\n", rxdata[7], rxdata[7]);
++//printk(KERN_INFO "BLOCKC  0x%02x '%c'\n", rxdata[8], rxdata[8]);
++//printk(KERN_INFO "BLOCKC  0x%02x '%c'\n", rxdata[9], rxdata[9]);
++//printk(KERN_INFO "BLOCKD  0x%02x '%c'\n", rxdata[10], rxdata[10]);
++//printk(KERN_INFO "BLOCKD  0x%02x '%c'\n", rxdata[11], rxdata[11]);
++//printk(KERN_INFO "Errors  0x%02x '%c'\n", rxdata[12], rxdata[12]);
++
++}
++
++static void si4705_status(struct si4705_device *radio, u8 * data)
++{
++      u8 txdata[1];
++      u8 rxdata[1] = {0};
++      u8 txsize = 0, rxsize = 1;
++
++      txdata[txsize++] = si4705_cmd.GET_INT_STATUS;
++
++      memset(rxdata, 0, sizeof(rxdata));
++
++      if(si4705_do_i2c_cmd(radio, txdata, txsize, rxdata, rxsize)) {
++              printk(KERN_INFO "%s Error reading RDS data\n", __func__);
++      }
++      *data = rxdata[0];
++}
++
++static void si4705_set_audout_mode(struct si4705_device *radio, int audmode)
++{
++//    struct si4705_regs *r = &radio->regs;
++//    int tnctrl = r->tnctrl;
++//
++//    if (audmode == V4L2_TUNER_MODE_MONO)
++//            r->tnctrl |= TEA5764_TNCTRL_MST;
++//    else
++//            r->tnctrl &= ~TEA5764_TNCTRL_MST;
++//    if (tnctrl != r->tnctrl)
++//            tea5764_i2c_write(radio);
++}
++
++static int si4705_get_audout_mode(struct si4705_device *radio)
++{
++//    struct tea5764_regs *r = &radio->regs;
++//
++//    if (r->tnctrl & TEA5764_TNCTRL_MST)
++//            return V4L2_TUNER_MODE_MONO;
++//    else
++              return V4L2_TUNER_MODE_STEREO;
++}
++
++/* V4L2 vidioc */
++static int vidioc_querycap(struct file *file, void  *priv,
++                                      struct v4l2_capability *v)
++{
++      struct si4705_device *radio = video_drvdata(file);
++      struct video_device *dev = radio->videodev;
++
++      strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver));
++      strlcpy(v->card, dev->name, sizeof(v->card));
++      snprintf(v->bus_info, sizeof(v->bus_info),
++               "I2C:%s", dev_name(&dev->dev));
++      v->version = RADIO_VERSION;
++      v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO | \
++                      V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_RDS_CAPTURE;
++      return 0;
++}
++
++static int vidioc_g_tuner(struct file *file, void *priv,
++                              struct v4l2_tuner *v)
++{
++      u8 txdata[2];
++      u8 rxdata[8] = {0};
++      u8 txsize = 0, rxsize = 8;
++      struct si4705_device *radio = video_drvdata(file);
++
++      if (v->index > 0)
++              return -EINVAL;
++
++      memset(v, 0, sizeof(*v));
++      strcpy(v->name, "FM");
++      v->type = V4L2_TUNER_RADIO;
++
++// MASU complete this
++//    si4705_get_property(radio, si4705_prop_cmd.FM_SEEK_BAND_BOTTOM, &(radio->reg_property.fm_seek_band_bottom));
++//    si4705_get_property(radio, si4705_prop_cmd.FM_SEEK_BAND_TOP, &(radio->reg_property.fm_seek_band_top));
++
++// MASU FIXME Get signal quality
++
++      txdata[txsize++] = si4705_cmd.FM_TUNE_STATUS;
++      txdata[txsize++] = 0x00;
++
++      si4705_do_i2c_cmd(radio, txdata, txsize, rxdata, rxsize);
++
++      v->rangelow   = FREQ_MIN * FREQ_MUL;
++      v->rangehigh  = FREQ_MAX * FREQ_MUL;
++      v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
++//    if (r->tunchk & TEA5764_TUNCHK_STEREO)
++              v->rxsubchans = V4L2_TUNER_SUB_STEREO;
++//    else
++//            v->rxsubchans = V4L2_TUNER_SUB_MONO;
++      v->audmode = si4705_get_audout_mode(radio);
++      v->signal = rxdata[5] * 0xffff / 0xf;           // MASU fix me
++//    v->afc = TEA5764_TUNCHK_IFCNT(r->tunchk);
++
++      return 0;
++}
++
++static int vidioc_s_tuner(struct file *file, void *priv,
++                              struct v4l2_tuner *v)
++{
++      struct si4705_device *radio = video_drvdata(file);
++
++      if (v->index > 0)
++              return -EINVAL;
++
++      si4705_set_audout_mode(radio, v->audmode);
++      return 0;
++}
++
++static int vidioc_s_frequency(struct file *file, void *priv,
++                              struct v4l2_frequency *f)
++{
++      struct si4705_device *radio = video_drvdata(file);
++
++      if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
++              return -EINVAL;
++      if (f->frequency == 0) {
++              /* We special case this as a power down control. */
++              si4705_power_down(radio);
++      }
++      if (f->frequency < (FREQ_MIN * FREQ_MUL))
++              return -EINVAL;
++      if (f->frequency > (FREQ_MAX * FREQ_MUL))
++              return -EINVAL;
++      si4705_power_up(radio);
++      si4705_tune(radio, (f->frequency * 125) / 2);
++
++      return 0;
++}
++
++static int vidioc_g_frequency(struct file *file, void *priv,
++                              struct v4l2_frequency *f)
++{
++      struct si4705_device *radio = video_drvdata(file);
++
++      if (f->tuner != 0)
++              return -EINVAL;
++
++      memset(f, 0, sizeof(*f));
++      f->type = V4L2_TUNER_RADIO;
++//    if (r->tnctrl & TEA5764_TNCTRL_PUPD0)
++              f->frequency = (radio->reg.tunned_freq * 10000 * 2) / 125;
++//    else
++//            f->frequency = 0;
++
++      return 0;
++}
++
++static int vidioc_queryctrl(struct file *file, void *priv,
++                          struct v4l2_queryctrl *qc)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(radio_qctrl); i++) {
++              if (qc->id && qc->id == radio_qctrl[i].id) {
++                      memcpy(qc, &(radio_qctrl[i]), sizeof(*qc));
++                      return 0;
++              }
++      }
++      return -EINVAL;
++}
++
++static int vidioc_g_ctrl(struct file *file, void *priv,
++                          struct v4l2_control *ctrl)
++{
++      struct si4705_device *radio = video_drvdata(file);
++
++      switch (ctrl->id) {
++      case V4L2_CID_AUDIO_VOLUME:
++              si4705_get_property(radio, si4705_prop_cmd.RX_VOLUME, &(radio->reg_property.rx_volume));
++              ctrl->value = radio->reg_property.rx_volume;
++              return 0;
++      case V4L2_CID_AUDIO_MUTE:
++              si4705_get_property(radio, si4705_prop_cmd.RX_HARD_MUTE, &(radio->reg_property.rx_hard_mute));
++              ctrl->value = (radio->reg_property.rx_hard_mute & SI4705_RHM_MUTE_ALL) ? 1 : 0;
++              return 0;
++      }
++      return -EINVAL;
++}
++
++static int vidioc_s_ctrl(struct file *file, void *priv,
++                          struct v4l2_control *ctrl)
++{
++      struct si4705_device *radio = video_drvdata(file);
++      switch (ctrl->id) {
++      case V4L2_CID_AUDIO_VOLUME:
++              si4705_set_property(radio, si4705_prop_cmd.RX_VOLUME, ctrl->value);
++              return 0;
++      case V4L2_CID_AUDIO_MUTE:
++              if (ctrl->value)
++                      si4705_set_property(radio, si4705_prop_cmd.RX_HARD_MUTE, SI4705_RHM_MUTE_ALL);
++              else
++                      si4705_set_property(radio, si4705_prop_cmd.RX_HARD_MUTE, SI4705_RHM_MUTE_NONE);
++              return 0;
++      }
++      return -EINVAL;
++}
++
++static int vidioc_g_input(struct file *filp, void *priv, unsigned int *i)
++{
++      *i = 0;
++      return 0;
++}
++
++static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
++{
++      if (i != 0)
++              return -EINVAL;
++      return 0;
++}
++
++static int vidioc_g_audio(struct file *file, void *priv,
++                         struct v4l2_audio *a)
++{
++      if (a->index > 1)
++              return -EINVAL;
++
++      strcpy(a->name, "Radio");
++      a->capability = V4L2_AUDCAP_STEREO;
++      return 0;
++}
++
++static int vidioc_s_audio(struct file *file, void *priv,
++                         struct v4l2_audio *a)
++{
++      if (a->index != 0)
++              return -EINVAL;
++
++      return 0;
++}
++
++static int si4705_open(struct file *file)
++{
++      struct si4705_device *radio = video_drvdata(file);
++      int ret = 0;
++      unsigned short cerr = 0x0000;
++
++      mutex_lock(&radio->mutex);
++      radio->users++;
++
++      if (radio->users == 1) {
++              /* start radio */
++#ifndef USE_LEGACY_ONOFF
++              ret = si4705_power_up(radio);
++
++              if (ret)
++                      goto done;
++#endif
++#ifdef DISSABLE_RDS
++              switch(max_rds_errors) {
++                      case 0: cerr = 0x0000; break;
++                      case 1: 
++                      case 2: cerr = 0x5500; break;
++                      case 3:
++                      case 4:
++                      case 5: cerr = 0xaa00; break;
++                      default : cerr = 0xff00; break;
++              }
++
++              /* enable RDS interrupt */
++              ret = si4705_set_property(radio, si4705_prop_cmd.GPO_IEN, SI4705_GI_RDSIEN);
++              // GPIO2 int configuret at power up
++              ret |= si4705_set_property(radio, si4705_prop_cmd.RDS_INT_SOURCE, 0x0001);      // enable fifo filled interrupts
++              ret |= si4705_set_property(radio, si4705_prop_cmd.RDS_INT_FIFO_COUNT, 0x0004);
++              ret |= si4705_set_property(radio, si4705_prop_cmd.RDS_CONFIG, cerr |0x0001);    // enable interrupt
++              if (ret)
++                      goto done;
++#endif
++      }
++
++done:
++      mutex_unlock(&radio->mutex);
++      return ret;
++}
++
++static int si4705_close(struct file *file)
++{
++      struct si4705_device *radio = video_drvdata(file);
++      int ret = 0;
++
++      if (!radio)
++              return -ENODEV;
++      mutex_lock(&radio->mutex);
++      radio->users--;
++      if (radio->users == 0)
++              /* stop radio */
++#ifndef USE_LEGACY_ONOFF
++              ret = si4705_power_down(radio);
++#endif
++      mutex_unlock(&radio->mutex);
++
++      return ret;
++}
++
++/*
++ * si4705_fops_read - read RDS data
++ */
++static ssize_t si4705_fops_read(struct file *file, char __user *buf,
++              size_t count, loff_t *ppos)
++{
++      struct si4705_device *radio = video_drvdata(file);
++      int retval = 0;
++      unsigned int block_count = 0;
++
++      /* switch on rds reception */
++//    if ((radio->registers[SYSCONFIG1] & SYSCONFIG1_RDS) == 0)
++//            si470x_rds_on(radio);
++
++      /* block if no new data available */
++/*    while (radio->wr_index == radio->rd_index) {
++              if (file->f_flags & O_NONBLOCK) {
++                      retval = -EWOULDBLOCK;
++                      goto done;
++              }
++              if (wait_event_interruptible(radio->read_queue,
++                      radio->wr_index != radio->rd_index) < 0) {
++                      retval = -EINTR;
++                      goto done;
++              }
++      }
++*/
++      /* calculate block count from byte count */
++      count /= 3;
++
++      /* copy RDS block out of internal buffer and to user buffer */
++      mutex_lock(&radio->mutex);
++/*    while (block_count < count) {
++              if (radio->rd_index == radio->wr_index)
++                      break;
++
++              // always transfer rds complete blocks
++              if (copy_to_user(buf, &radio->buffer[radio->rd_index], 3))
++                      // retval = -EFAULT;
++                      break;
++
++              // increment and wrap read pointer
++              radio->rd_index += 3;
++              if (radio->rd_index >= radio->buf_size)
++                      radio->rd_index = 0;
++
++              // increment counters
++              block_count++;
++              buf += 3;
++              retval += 3;
++      }
++*/
++      mutex_unlock(&radio->mutex);
++
++//done:
++      return retval;
++}
++
++/* File system interface */
++static const struct v4l2_file_operations si4705_fops = {
++      .owner          = THIS_MODULE,
++      .open           = si4705_open,
++      .release        = si4705_close,
++      .ioctl          = video_ioctl2,
++      .read           = si4705_fops_read,
++};
++
++static const struct v4l2_ioctl_ops si4705_ioctl_ops = {
++      .vidioc_querycap    = vidioc_querycap,
++      .vidioc_g_tuner     = vidioc_g_tuner,
++      .vidioc_s_tuner     = vidioc_s_tuner,
++      .vidioc_g_audio     = vidioc_g_audio,
++      .vidioc_s_audio     = vidioc_s_audio,
++      .vidioc_g_input     = vidioc_g_input,
++      .vidioc_s_input     = vidioc_s_input,
++      .vidioc_g_frequency = vidioc_g_frequency,
++      .vidioc_s_frequency = vidioc_s_frequency,
++      .vidioc_queryctrl   = vidioc_queryctrl,
++      .vidioc_g_ctrl      = vidioc_g_ctrl,
++      .vidioc_s_ctrl      = vidioc_s_ctrl,
++};
++
++/* V4L2 interface */
++static struct video_device si4705_radio_template = {
++      .name           = "SI4705 FM-Radio",
++      .fops           = &si4705_fops,
++      .ioctl_ops      = &si4705_ioctl_ops,
++      .release        = video_device_release,
++};
++
++
++/*
++ * si470x_i2c_interrupt_work - rds processing function
++ */
++#ifndef DISSABLE_RDS
++static void si4705_i2c_interrupt_work(struct work_struct *work)
++{
++      struct si4705_device *radio = container_of(work,
++              struct si4705_device, radio_work);
++//    unsigned char regnr;
++//    unsigned char blocknum;
++//    unsigned short bler; // rds block errors
++      unsigned char tmpbuf[13];
++//    unsigned char finbuf[13];
++//    int retval = 0;
++      u8 status;
++
++      // safety checks
++      si4705_status(radio, &status);
++      if ((status & SI4705_GIS_RDSINT) == 0)          // not a rds interrupt
++              return;
++
++      // Update RDS registers
++      do {
++              si4705_rds(radio, SI4705_FRS_INTACK, tmpbuf);
++      } while (tmpbuf[3] != 0x00);    
++
++
++
++//printk(KERN_INFO "Status  0x%02x '%c'\n", rxdata[0], rxdata[0]);
++//printk(KERN_INFO "Resp 1  0x%02x '%c'\n", rxdata[1], rxdata[1]);
++//printk(KERN_INFO "Resp 2  0x%02x '%c'\n", rxdata[2], rxdata[2]);
++//printk(KERN_INFO "Used    0x%02x '%c'\n", rxdata[3], rxdata[3]);
++//printk(KERN_INFO "BLOCKA  0x%02x '%c'\n", rxdata[4], rxdata[4]);
++//printk(KERN_INFO "BLOCKA  0x%02x '%c'\n", rxdata[5], rxdata[5]);
++//printk(KERN_INFO "BLOCKB  0x%02x '%c'\n", rxdata[6], rxdata[6]);
++//printk(KERN_INFO "BLOCKB  0x%02x '%c'\n", rxdata[7], rxdata[7]);
++//printk(KERN_INFO "BLOCKC  0x%02x '%c'\n", rxdata[8], rxdata[8]);
++//printk(KERN_INFO "BLOCKC  0x%02x '%c'\n", rxdata[9], rxdata[9]);
++//printk(KERN_INFO "BLOCKD  0x%02x '%c'\n", rxdata[10], rxdata[10]);
++//printk(KERN_INFO "BLOCKD  0x%02x '%c'\n", rxdata[11], rxdata[11]);
++//printk(KERN_INFO "Errors  0x%02x '%c'\n", rxdata[12], rxdata[12]);
++/*            switch (blocknum) {
++              default:
++                      bler = (radio->registers[STATUSRSSI] &
++                                      STATUSRSSI_BLERA) >> 9;
++                      rds = radio->registers[RDSA];
++                      break;
++              case 1:
++                      bler = (radio->registers[READCHAN] &
++                                      READCHAN_BLERB) >> 14;
++                      rds = radio->registers[RDSB];
++                      break;
++              case 2:
++                      bler = (radio->registers[READCHAN] &
++                                      READCHAN_BLERC) >> 12;
++                      rds = radio->registers[RDSC];
++                      break;
++              case 3:
++                      bler = (radio->registers[READCHAN] &
++                                      READCHAN_BLERD) >> 10;
++                      rds = radio->registers[RDSD];
++                      break;
++              };
++
++              // Fill the V4L2 RDS buffer
++              put_unaligned_le16(rds, &tmpbuf);
++              tmpbuf[2] = blocknum;           // offset name
++              tmpbuf[2] |= blocknum << 3;     // received offset
++              if (bler > max_rds_errors)
++                      tmpbuf[2] |= 0x80;      // uncorrectable errors
++              else if (bler > 0)
++                      tmpbuf[2] |= 0x40;      // corrected error(s)
++
++              // copy RDS block to internal buffer
++              memcpy(&radio->buffer[radio->wr_index], &tmpbuf, 3);
++              radio->wr_index += 3;
++
++              // wrap write pointer
++              if (radio->wr_index >= radio->buf_size)
++                      radio->wr_index = 0;
++
++              // check for overflow
++              if (radio->wr_index == radio->rd_index) {
++                      // increment and wrap read pointer
++                      radio->rd_index += 3;
++                      if (radio->rd_index >= radio->buf_size)
++                              radio->rd_index = 0;
++              }
++      }
++
++      if (radio->wr_index != radio->rd_index)
++             wake_up_interruptible(&radio->read_queue);
++*/
++}
++#else
++static void si4705_i2c_interrupt_work(struct work_struct *work) {
++      ;
++}
++#endif // DISSABLE_RDS
++
++/*
++ * si470x_i2c_interrupt - interrupt handler
++ */
++static irqreturn_t si4705_i2c_interrupt(int irq, void *dev_id)
++{
++      struct si4705_device *radio = dev_id;
++
++      if (!work_pending(&radio->radio_work))
++              schedule_work(&radio->radio_work);
++
++      return IRQ_HANDLED;
++}
++
++/* I2C probe: check if the device exists and register with v4l if it is */
++static int __devinit si4705_i2c_probe(struct i2c_client *client,
++                                      const struct i2c_device_id *id)
++{
++      struct si4705_device *radio;
++      u8 txdata[2];
++      u8 rxdata[8];
++      u8 txsize = 0, rxsize = 0;
++      int ret;
++
++      memset(txdata, 0, sizeof(txdata));
++      memset(rxdata, 0, sizeof(rxdata));
++
++      /* private data allocation and initialization */
++      radio = kzalloc(sizeof(struct si4705_device), GFP_KERNEL);
++      if (!radio) {
++              ret = -ENOMEM;
++              goto err_initial;
++      }
++
++      INIT_WORK(&radio->radio_work, si4705_i2c_interrupt_work);
++      radio->users = 0;
++      radio->i2c_client = client;
++      mutex_init(&radio->mutex);
++
++      /* video device allocation and initialization */
++      radio->videodev = video_device_alloc();
++      if (!(radio->videodev)) {
++              ret = -ENOMEM;
++              goto err_radio;
++      }
++      memcpy(radio->videodev, &si4705_radio_template,
++              sizeof(si4705_radio_template));
++      video_set_drvdata(radio->videodev, radio);
++
++      /* Detect the chip in power off mode */ 
++      txdata[txsize++] = si4705_cmd.POWER_UP; // Library ID
++      txdata[txsize++] = 0x0F;
++
++      rxsize = 8;
++      memset(rxdata, 0, sizeof(rxdata));
++
++      if (si4705_do_i2c_cmd(radio, txdata, txsize, rxdata, rxsize)) {
++              ret = -EIO;
++              goto errrel;
++      }
++
++      radio->reg.part_number = rxdata[1];
++      radio->reg.fw_major = rxdata[2];
++      radio->reg.fw_minor = rxdata[3];
++      radio->reg.revision = rxdata[6];
++
++
++      dev_info(&client->dev, "ChipID=si47%02d%c Firmware %c%c\n",
++                      radio->reg.part_number, radio->reg.revision, \
++                      radio->reg.fw_major, radio->reg.fw_minor);
++      if ((((radio->reg.fw_major - '0') * 10) + (radio->reg.fw_minor - '0')) \
++                      < RADIO_FW_VERSION) {
++              dev_warn(&client->dev,
++                      "This driver is known to work with "
++                      "firmware version %hu,\n", RADIO_FW_VERSION);
++              dev_warn(&client->dev,
++                      "but the device has older firmware version.\n");
++      }
++
++      /* Power on */
++      if (si4705_power_up(radio)) {
++              ret = -EIO;
++              goto errrel;
++      }
++
++      /* Get all properties */
++//    if (si4705_get_all_properties(radio)) {
++//            ret = -EIO;
++//            goto errrel;
++//    }
++
++      /* rds buffer allocation */
++      radio->buf_size = rds_buf;
++      radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
++      if (!radio->buffer) {
++              ret = -EIO;
++              goto errrel;
++      }
++
++      /* rds buffer configuration */
++      radio->wr_index = 0;
++      radio->rd_index = 0;
++      init_waitqueue_head(&radio->read_queue);
++
++      ret = request_irq(client->irq, si4705_i2c_interrupt,
++                      IRQF_TRIGGER_FALLING, DRIVER_NAME, radio);
++      if (ret) {
++              dev_err(&client->dev, "Failed to register interrupt\n");
++              goto err_rds;
++      }
++
++      ret = video_register_device(radio->videodev, VFL_TYPE_RADIO, radio_nr);
++      if (ret < 0) {
++              dev_warn(&client->dev, "Could not register video device!");
++              goto err_all;
++      }
++
++      i2c_set_clientdata(client, radio);
++
++      return 0;
++err_all:
++      free_irq(client->irq, radio);
++err_rds:
++      kfree(radio->buffer);
++errrel:
++      video_device_release(radio->videodev);
++err_radio:
++      kfree(radio);
++err_initial:
++      return ret;
++}
++
++static int __devexit si4705_i2c_remove(struct i2c_client *client)
++{
++      struct si4705_device *radio = i2c_get_clientdata(client);
++
++      free_irq(client->irq, radio);
++      cancel_work_sync(&radio->radio_work);
++#ifdef USE_LEGACY_ONOFF
++      si4705_power_down(radio);
++#endif
++      kfree(radio->buffer);
++      video_unregister_device(radio->videodev);
++      kfree(radio);
++
++      return 0;
++}
++
++/* I2C subsystem interface */
++static const struct i2c_device_id si4705_i2c_id[] = {
++      /* Generic Entry */
++      { "radio-si4705", 0 },
++      /* Terminating entry */
++      { }
++};
++MODULE_DEVICE_TABLE(i2c, si4705_i2c_id);
++
++#ifdef CONFIG_PM
++/*
++ * si470x_i2c_suspend - suspend the device
++ */
++static int si4705_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
++{
++      struct si4705_device *radio = i2c_get_clientdata(client);
++
++      if (si4705_power_down(radio))
++              return -EIO;
++
++      return 0;
++}
++
++
++/*
++ * si470x_i2c_resume - resume the device
++ */
++static int si4705_i2c_resume(struct i2c_client *client)
++{
++      struct si4705_device *radio = i2c_get_clientdata(client);
++
++      if (si4705_power_up(radio))
++              return -EIO;
++
++      return 0;
++}
++#else
++#define si4705_i2c_suspend    NULL
++#define si4705_i2c_resume     NULL
++#endif
++
++static struct i2c_driver si4705_i2c_driver = {
++      .driver = {
++              .name = DRIVER_NAME,
++              .owner = THIS_MODULE,
++      },
++      .probe = si4705_i2c_probe,
++      .remove = __devexit_p(si4705_i2c_remove),
++      .suspend = si4705_i2c_suspend,
++      .resume  = si4705_i2c_resume,
++      .id_table = si4705_i2c_id,
++};
++
++/* init the driver */
++static int __init si4705_init(void)
++{
++      printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ": "
++              DRIVER_DESC "\n");
++      return i2c_add_driver(&si4705_i2c_driver);
++}
++
++/* cleanup the driver */
++static void __exit si4705_exit(void)
++{
++      i2c_del_driver(&si4705_i2c_driver);
++}
++
++module_init(si4705_init);
++module_exit(si4705_exit);
++
++MODULE_DESCRIPTION(DRIVER_DESC);
++MODULE_AUTHOR(DRIVER_AUTHOR);
++MODULE_VERSION(DRIVER_VERSION);
++MODULE_LICENSE("GPL");
+diff -urN linux.35.old/drivers/media/radio/radio-si4705.h linux.35.new/drivers/media/radio/radio-si4705.h
+--- linux.35.old/drivers/media/radio/radio-si4705.h    1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/media/radio/radio-si4705.h    2010-12-03 09:51:55.436349742 +0100
+@@ -0,0 +1,217 @@
++/*
++ * drivers/media/radio/radio-si4705.h
++ *
++ * Property and commands definitions for Si4705 radio receiver chip.
++ *
++ * Copyright (c) 2010 Voipac
++ *
++ * This file is licensed under the terms of the GNU General Public License
++ * version 2. This program is licensed "as is" without any warranty of any
++ * kind, whether express or implied.
++ *
++ */
++
++#ifndef RADIO_SI4705_H
++#define RADIO_SI4705_H
++
++#include <linux/types.h>
++
++
++/* driver definitions */
++#define DRIVER_NAME "radio-si4705"
++
++#define DRIVER_VERSION        "v0.01"
++#define RADIO_VERSION KERNEL_VERSION(0, 0, 1)
++
++#define DRIVER_AUTHOR "Voipac <support@voipac.com>"
++#define DRIVER_DESC   "A driver for the SI4705 radio chip."
++
++/* Tunner will remain active until the driver is uloaded */
++#define USE_LEGACY_ONOFF
++#define DISSABLE_RDS
++
++/* Tunner will remain active only when fd is open */
++//#undef USE_LEGACY_ONOFF
++
++/* Frequency limits in MHz -- these are European values.  For Japanese
++devices, that would be 76000 and 91000.  */
++#define FREQ_MIN  87500
++#define FREQ_MAX 108000
++#define FREQ_MUL 16
++
++/* Firmware Versions */
++#define RADIO_FW_VERSION        20
++
++
++/* Status response mask */
++#define SI4705_STS_CTS                        0x80
++#define SI4705_STS_ERR                        0x40
++
++/* Power Up mask */
++#define SI4705_PU_INT_ENABLE          0xC0
++#define SI4705_PU_MODE_AN             0x05
++#define SI4705_PU_MODE_DI             0xB0
++#define SI4705_PU_MODE_ANDI           (SI4705_PU_MODE_AN | SI4705_PU_MODE_DI)
++
++/* Get int status mask */
++#define SI4705_GIS_RDSINT             0x04
++
++/* Fm rds starus mask */
++#define SI4705_FRS_MTFIFO             0x02
++#define SI4705_FRS_INTACK             0x01
++
++struct si4705_reg {
++      u8 part_number;         // hex - last two digits
++      u8 fw_major;            // ASCII
++      u8 fw_minor;            // ASCII
++      u8 revision;            // ASCII
++      u16 tunned_freq;        // hex 101.20MHz ~ 0x2788
++}  __attribute__ ((packed));
++
++typedef struct {
++      u8 POWER_UP;
++      u8 GET_REV;
++      u8 POWER_DOWN;
++      u8 SET_PROPERTY;
++      u8 GET_PROPERTY;
++      u8 GET_INT_STATUS;
++      u8 PATCH_ARGS;
++      u8 PATCH_DATA;
++      u8 FM_TUNE_FREQ;
++      u8 FM_SEEK_START;
++      u8 FM_TUNE_STATUS;
++      u8 FM_RSQ_STATUS;
++      u8 FM_RDS_STATUS;
++      u8 FM_AGC_STATUS;
++      u8 FM_AGC_OVERRIDE;
++      u8 GPIO_CTL;
++      u8 GPIO_SET;
++} SI4705_CMD;
++
++SI4705_CMD si4705_cmd = {
++      .POWER_UP = 0x01,
++      .GET_REV = 0x10,
++      .POWER_DOWN = 0x11,
++      .SET_PROPERTY = 0x12,
++      .GET_PROPERTY = 0x13,
++      .GET_INT_STATUS = 0x14,
++      .PATCH_ARGS = 0x15,
++      .PATCH_DATA = 0x16,
++      .FM_TUNE_FREQ = 0x20,
++      .FM_SEEK_START = 0x21,
++      .FM_TUNE_STATUS = 0x22,
++      .FM_RSQ_STATUS = 0x23,
++      .FM_RDS_STATUS = 0x24,
++      .FM_AGC_STATUS = 0x27,
++      .FM_AGC_OVERRIDE = 0x28,
++      .GPIO_CTL = 0x80,
++      .GPIO_SET = 0x81
++};
++
++/* gpo_ien */
++#define SI4705_GI_RDSREP      0x0400
++#define SI4705_GI_RDSIEN      0x0004
++
++/* rx_hard_mute */
++#define SI4705_RHM_MUTE_R     0x0001
++#define SI4705_RHM_MUTE_L     0x0002
++#define SI4705_RHM_MUTE_ALL   (SI4705_RHM_MUTE_R | SI4705_RHM_MUTE_L)
++#define SI4705_RHM_MUTE_NONE  0x0000
++
++struct si4705_property {
++      u16 gpo_ien;                    /* Enables interrupt sources */
++      u16 digital_output_format;      /* Configure digital audio outputs */
++      u16 digital_output_sample_rate;
++      u16 refclk_freq;
++      u16 refclk_prescale;
++      u16 fm_deemphasis;
++      u16 fm_blend_stereo_threshold;
++      u16 fm_blend_mono_threshold;
++      u16 fm_antena_input;
++      u16 fm_max_tune_error;
++      u16 fm_rsq_int_source;
++      u16 fm_rsq_snr_hi_threshold;
++      u16 fm_rsq_snr_lo_threshold;
++      u16 fm_rsq_rssi_hi_threshold;
++      u16 fm_rsq_rssi_lo_threshold;
++      u16 fm_rsq_blend_threshold;
++      u16 fm_soft_mute_rate;
++      u16 fm_soft_mute_max_attenuation;
++      u16 fm_soft_mute_snr_threshold;
++      u16 fm_seek_band_bottom;
++      u16 fm_seek_band_top;
++      u16 fm_seek_freq_spacing;
++      u16 fm_seek_tune_snr_threshold;
++      u16 fm_seek_tune_rssi_threshold;
++      u16 rds_int_source;
++      u16 rds_int_fifo_count;
++      u16 rds_config;
++      u16 rx_volume;
++      u16 rx_hard_mute;
++} __attribute__ ((packed));
++
++typedef struct {
++      u16 GPO_IEN;
++      u16 DIGITAL_OUTPUT_FORMAT;
++      u16 DIGITAL_OUTPUT_SAMPLE_RATE;
++      u16 REFCLK_FREQ;
++      u16 REFCLK_PRESCALE;
++      u16 FM_DEEMPHASIS;
++      u16 FM_BLEND_STEREO_THRESHOLD;
++      u16 FM_BLEND_MONO_THRESHOLD;
++      u16 FM_ANTENNA_INPUT;
++      u16 FM_MAX_TUNE_ERROR;
++      u16 FM_RSQ_INT_SOURCE;
++      u16 FM_RSQ_SNR_HI_THRESHOLD;
++      u16 FM_RSQ_SNR_LO_THRESHOLD;
++      u16 FM_RSQ_RSSI_HI_THRESHOLD;
++      u16 FM_RSQ_RSSI_LO_THRESHOLD;
++      u16 FM_RQS_BLEND_THRESHOLD;
++      u16 FM_SOFT_MUTE_RATE;
++      u16 FM_SOFT_MUTE_MAX_ATTENUATION;
++      u16 FM_SOFT_MUTE_SNR_THRESHOLD;
++      u16 FM_SEEK_BAND_BOTTOM;
++      u16 FM_SEEK_BAND_TOP;
++      u16 FM_SEEK_FREQ_SPACING;
++      u16 FM_SEEK_TUNE_SNR_THRESHOLD;
++      u16 FM_SEEK_TUNE_RSSI_TRESHOLD;
++      u16 RDS_INT_SOURCE;
++      u16 RDS_INT_FIFO_COUNT;
++      u16 RDS_CONFIG;
++      u16 RX_VOLUME;
++      u16 RX_HARD_MUTE;
++} SI4705_PROP_CMD;
++
++SI4705_PROP_CMD si4705_prop_cmd = {
++      .GPO_IEN = 0x0001,
++      .DIGITAL_OUTPUT_FORMAT = 0x0102,
++      .DIGITAL_OUTPUT_SAMPLE_RATE = 0x0104,
++      .REFCLK_FREQ = 0x0201,
++      .REFCLK_PRESCALE = 0x0202,
++      .FM_DEEMPHASIS = 0x1100,
++      .FM_BLEND_STEREO_THRESHOLD = 0x1105,
++      .FM_BLEND_MONO_THRESHOLD = 0x1106,
++      .FM_ANTENNA_INPUT = 0x1107,
++      .FM_MAX_TUNE_ERROR = 0x1108,
++      .FM_RSQ_INT_SOURCE = 0x1200,
++      .FM_RSQ_SNR_HI_THRESHOLD = 0x1201,
++      .FM_RSQ_SNR_LO_THRESHOLD = 0x1202,
++      .FM_RSQ_RSSI_HI_THRESHOLD = 0x1203,
++      .FM_RSQ_RSSI_LO_THRESHOLD = 0x1204,
++      .FM_RQS_BLEND_THRESHOLD = 0x1207,
++      .FM_SOFT_MUTE_RATE = 0x1300,
++      .FM_SOFT_MUTE_MAX_ATTENUATION = 0x1302,
++      .FM_SOFT_MUTE_SNR_THRESHOLD = 0x1303,
++      .FM_SEEK_BAND_BOTTOM = 0x1400,
++      .FM_SEEK_BAND_TOP = 0x1401,
++      .FM_SEEK_FREQ_SPACING = 0x1402,
++      .FM_SEEK_TUNE_SNR_THRESHOLD = 0x1403,
++      .FM_SEEK_TUNE_RSSI_TRESHOLD = 0x1404,
++      .RDS_INT_SOURCE = 0x1500,
++      .RDS_INT_FIFO_COUNT = 0x1501,
++      .RDS_CONFIG = 0x1502,
++      .RX_VOLUME = 0x4000,
++      .RX_HARD_MUTE = 0x4001
++};
++
++#endif /* ifndef RADIO_SI4705_H */
+diff -urN linux.35.old/drivers/mmc/host/Kconfig linux.35.new/drivers/mmc/host/Kconfig
+--- linux.35.old/drivers/mmc/host/Kconfig      2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/mmc/host/Kconfig      2010-12-03 09:51:55.436349742 +0100
+@@ -313,6 +313,34 @@
+         If unsure, or if your system has no SPI master driver, say N.
++config MMC_SDHCI_MXC
++      tristate "Freescale i.MX Secure Digital Host Controller Interface support"
++      depends on ARCH_MXC && MMC
++      help
++        This selects the Secure Digital Host Controller Interface (SDHCI)
++        on Freescale i.MX platforms.
++        If you have an i.MX platform with a Multimedia Card slot,
++        say Y or M here.
++
++        If unsure, say N.
++
++config MMC_SDHCI_MXC_SELECT2
++      bool "Enable second ESDHCI port"
++      depends on MMC_SDHCI_MXC && ARCH_MX25
++      help
++        Enable the second ESDHC port
++
++config MMC_SDHCI_MXC_PIO_MODE
++      bool "Freescale i.MX Secure Digital Host Controller Interface PIO mode"
++      depends on MMC_SDHCI_MXC
++      help
++        This set the Freescale i.MX Multimedia card Interface to PIO mode.
++        If you have a i.MX platform with a Multimedia Card slot,
++        and want test it with PIO mode.
++        say Y here.
++
++        If unsure, say N.
++
+ config MMC_S3C
+       tristate "Samsung S3C SD/MMC Card Interface support"
+       depends on ARCH_S3C2410
+diff -urN linux.35.old/drivers/mmc/host/Makefile linux.35.new/drivers/mmc/host/Makefile
+--- linux.35.old/drivers/mmc/host/Makefile     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/mmc/host/Makefile     2010-12-03 09:51:55.436349742 +0100
+@@ -14,6 +14,7 @@
+ obj-$(CONFIG_MMC_SDHCI_PCI)   += sdhci-pci.o
+ obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
+ obj-$(CONFIG_MMC_SDHCI_S3C)   += sdhci-s3c.o
++obj-$(CONFIG_MMC_SDHCI_MXC)   += sdhci-mxc.o
+ obj-$(CONFIG_MMC_SDHCI_SPEAR) += sdhci-spear.o
+ obj-$(CONFIG_MMC_WBSD)                += wbsd.o
+ obj-$(CONFIG_MMC_AU1X)                += au1xmmc.o
+diff -urN linux.35.old/drivers/mmc/host/sdhci-mxc.c linux.35.new/drivers/mmc/host/sdhci-mxc.c
+--- linux.35.old/drivers/mmc/host/sdhci-mxc.c  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/mmc/host/sdhci-mxc.c  2010-12-28 11:05:01.467488497 +0100
+@@ -0,0 +1,2183 @@
++/*
++ * Copyright (C) 2009  Lothar Wassmann <LW@KARO-electronics.de>
++ *
++ * based on: mx_sdhci.c 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 the Freescale Semiconductor MXC eSDHC controller
++ *
++ * This driver code is based on sdhci.c, by Pierre Ossman <drzeus@drzeus.cx>");
++ * This driver supports Enhanced Secure Digital Host Controller
++ * modules eSDHC of MXC. eSDHC is also referred as enhanced MMC/SD
++ * controller.
++ *
++ */
++
++#include <linux/delay.h>
++#include <linux/highmem.h>
++#include <linux/platform_device.h>
++#include <linux/dma-mapping.h>
++#include <linux/scatterlist.h>
++#include <linux/io.h>
++#include <linux/leds.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/mmc.h>
++#include <linux/mmc/card.h>
++#include <linux/clk.h>
++#include <linux/irq.h>
++#include <linux/slab.h>
++
++#include <mach/dma.h>
++#include <mach/hardware.h>
++#include <mach/sdhci.h>
++
++#include "sdhci-mxc.h"
++
++#ifdef DEBUG
++static int debug = 1;
++#define dbg_lvl(n)    ((n) < debug)
++#define DBG(lvl, fmt...)      do { if (dbg_lvl(lvl)) printk(KERN_DEBUG fmt); } while (0)
++module_param(debug, int, S_IWUSR | S_IRUGO);
++#else
++static int debug;
++#define dbg_lvl(n)    0
++#define DBG(lvl, fmt...)      do { } while (0)
++module_param(debug, int, 0);
++#endif
++
++#define DRIVER_NAME "sdhci"
++
++
++static unsigned int debug_quirks;
++module_param(debug_quirks, uint, S_IRUGO);
++MODULE_PARM_DESC(debug_quirks, "Force certain quirks");
++
++/*
++ * Different quirks to handle when the hardware deviates from a strict
++ * interpretation of the SDHCI specification.
++ */
++
++/* Controller doesn't honor resets unless we touch the clock register */
++#define SDHCI_QUIRK_CLOCK_BEFORE_RESET                        (1 << 0)
++/* Controller has bad caps bits, but really supports DMA */
++#define SDHCI_QUIRK_FORCE_DMA                         (1 << 1)
++/* Controller doesn't like to be reset when there is no card inserted. */
++#define SDHCI_QUIRK_NO_CARD_NO_RESET                  (1 << 2)
++/* Controller doesn't like clearing the power reg before a change */
++#define SDHCI_QUIRK_SINGLE_POWER_WRITE                        (1 << 3)
++/* Controller has flaky internal state so reset it on each ios change */
++#define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS             (1 << 4)
++/* Controller has an unusable DMA engine */
++#define SDHCI_QUIRK_BROKEN_DMA                                (1 << 5)
++/* Controller can only DMA from 32-bit aligned addresses */
++#define SDHCI_QUIRK_32BIT_DMA_ADDR                    (1 << 6)
++/* Controller can only DMA chunk sizes that are a multiple of 32 bits */
++#define SDHCI_QUIRK_32BIT_DMA_SIZE                    (1 << 7)
++/* Controller needs to be reset after each request to stay stable */
++#define SDHCI_QUIRK_RESET_AFTER_REQUEST                       (1 << 8)
++/* Controller needs voltage and power writes to happen separately */
++#define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER           (1 << 9)
++/* Controller has an off-by-one issue with timeout value */
++#define SDHCI_QUIRK_INCR_TIMEOUT_CONTROL              (1 << 10)
++/* Controller only support the PIO */
++#define SDHCI_QUIRK_ONLY_PIO                          (1 << 16)
++/* Controller support the External DMA */
++#define SDHCI_QUIRK_EXTERNAL_DMA_MODE                 (1 << 17)
++/* Controller support the Internal Simple DMA */
++#define SDHCI_QUIRK_INTERNAL_SIMPLE_DMA                       (1 << 18)
++/* Controller support the Internal Advanced DMA */
++#define SDHCI_QUIRK_INTERNAL_ADVANCED_DMA             (1 << 19)
++
++#define SDHCI_QUIRK_RESET_AFTER_READ                  (1 << 20)
++
++/*
++ * defines the mxc flags refer to the special hw pre-conditons and behavior
++ */
++#ifdef CONFIG_MMC_SDHCI_MXC_PIO_MODE
++static unsigned int debug_quirks = SDHCI_QUIRK_ONLY_PIO;
++#endif
++static unsigned int mxc_wml_value = 512;
++
++#ifndef MXC_SDHCI_NUM
++#define MXC_SDHCI_NUM 4
++#endif
++
++static struct sdhci_chip *mxc_fix_chips[MXC_SDHCI_NUM];
++
++static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *);
++static void sdhci_finish_data(struct sdhci_host *);
++
++static void sdhci_send_command(struct sdhci_host *, struct mmc_command *);
++static void sdhci_finish_command(struct sdhci_host *);
++static void sdhci_dma_irq(void *devid, int error, unsigned int cnt);
++
++#define platform_func(f, args...)     ((f) ? (f)(args) : 0)
++
++void mxc_mmc_force_detect(int id)
++{
++      struct sdhci_host *host;
++
++      if ((id < 0) || (id >= MXC_SDHCI_NUM))
++              return;
++      if (!mxc_fix_chips[id])
++              return;
++      host = mxc_fix_chips[id]->hosts[0];
++      if (host->detect_irq >= 0)
++              return;
++
++      schedule_work(&host->cd_wq);
++      return;
++}
++EXPORT_SYMBOL(mxc_mmc_force_detect);
++
++#ifdef DEBUG
++#undef readl
++#undef writel
++#define readl(a)      __readl(a, __FUNCTION__, __LINE__)
++#define writel(v,a)   __writel(v, a, __FUNCTION__, __LINE__)
++
++static u32 __readl(void __iomem *addr,
++              const char *fn, unsigned int ln)
++{
++      u32 val;
++
++      DBG(2, "%s@%d: Reading reg %p\n", fn, ln, addr);
++      BUG_ON(addr < (void __iomem *)4096);
++      val = __raw_readl(addr);
++      DBG(2, "%s@%d: read %08x from reg %p\n", fn, ln, val, addr);
++      return val;
++}
++
++static void __writel(u32 val, void __iomem *addr,
++              const char *fn, unsigned int ln)
++{
++      DBG(2, "%s@%d: writing %08x to reg %p\n", fn, ln, val, addr);
++      BUG_ON(addr < (void __iomem *)4096);
++      __raw_writel(val, addr);
++}
++#endif
++
++static inline void sdhci_clk_enable(struct sdhci_host *host)
++{
++      if (host->clk_enable++) {
++              BUG_ON(host->clk_enable < 0);
++              return;
++      }
++      clk_enable(host->clk);
++}
++
++static inline void sdhci_clk_disable(struct sdhci_host *host)
++{
++      if (--host->clk_enable) {
++              BUG_ON(host->clk_enable < 0);
++              return;
++      }
++      clk_disable(host->clk);
++}
++
++static void sdhci_dumpregs(struct sdhci_host *host)
++{
++      sdhci_clk_enable(host);
++      DBG(1, "============== REGISTER DUMP ==============\n");
++
++      DBG(1, "Sys addr: 0x%08x | Version:  0x%08x\n",
++             readl(host->ioaddr + SDHCI_DMA_ADDRESS),
++             readl(host->ioaddr + SDHCI_HOST_VERSION));
++      DBG(1, "Blk size: 0x%08x | Blk cnt:  0x%08x\n",
++             (readl(host->ioaddr + SDHCI_BLOCK_SIZE) & 0xFFFF),
++             (readl(host->ioaddr + SDHCI_BLOCK_COUNT) >> 16));
++      DBG(1, "Argument: 0x%08x | Trn mode: 0x%08x\n",
++             readl(host->ioaddr + SDHCI_ARGUMENT),
++             readl(host->ioaddr + SDHCI_TRANSFER_MODE));
++      DBG(1, "Present:  0x%08x | Host ctl: 0x%08x\n",
++             readl(host->ioaddr + SDHCI_PRESENT_STATE),
++             readl(host->ioaddr + SDHCI_HOST_CONTROL));
++      DBG(1, "Clock:    0x%08x\n",
++             readl(host->ioaddr + SDHCI_CLOCK_CONTROL));
++      DBG(1, "Int stat: 0x%08x\n",
++             readl(host->ioaddr + SDHCI_INT_STATUS));
++      DBG(1, "Int enab: 0x%08x | Sig enab: 0x%08x\n",
++             readl(host->ioaddr + SDHCI_INT_ENABLE),
++             readl(host->ioaddr + SDHCI_SIGNAL_ENABLE));
++      DBG(1, "Caps:     0x%08x\n",
++             readl(host->ioaddr + SDHCI_CAPABILITIES));
++
++      DBG(1, "===========================================\n");
++      sdhci_clk_disable(host);
++}
++
++/*****************************************************************************\
++ *                                                                           *
++ * Low level functions                                                       *
++ *                                                                           *
++\*****************************************************************************/
++
++static void sdhci_reset(struct sdhci_host *host, u8 mask)
++{
++      unsigned long tmp;
++      unsigned long mask_u32;
++      unsigned long reg_save = 0;
++
++      if (host->chip->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) {
++              if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) &
++                    SDHCI_CARD_PRESENT))
++                      return;
++      }
++
++      if (mask & SDHCI_RESET_ALL)
++              host->clock = 0;
++      else if (host->flags & SDHCI_CD_PRESENT)
++              reg_save = readl(host->ioaddr + SDHCI_HOST_CONTROL);
++
++      tmp = readl(host->ioaddr + SDHCI_CLOCK_CONTROL) | (mask << 24);
++      mask_u32 = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE);
++      writel(tmp, host->ioaddr + SDHCI_CLOCK_CONTROL);
++
++      /* Wait max 100 ms */
++      tmp = 5000;
++
++      /* hw clears the bit when it's done */
++      while ((readl(host->ioaddr + SDHCI_CLOCK_CONTROL) >> 24) & mask) {
++              if (tmp == 0) {
++                      printk(KERN_ERR "%s: Reset 0x%02x never completed\n",
++                             mmc_hostname(host->mmc), mask);
++                      sdhci_dumpregs(host);
++                      return;
++              }
++              tmp--;
++              udelay(20);
++      }
++      /*
++       * The INT_EN SIG_EN regs have been modified after reset.
++       * re-configure them ag.
++       */
++      if (!(mask & SDHCI_RESET_ALL) && (host->flags & SDHCI_CD_PRESENT))
++              writel(reg_save, host->ioaddr + SDHCI_HOST_CONTROL);
++      if (host->flags & SDHCI_USE_DMA)
++              mask_u32 &= ~(SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL);
++      if (mxc_wml_value == 512)
++              writel(SDHCI_WML_128_WORDS, host->ioaddr + SDHCI_WML);
++      else
++              writel(SDHCI_WML_16_WORDS, host->ioaddr + SDHCI_WML);
++      writel(mask_u32 | SDHCI_INT_CARD_INT, host->ioaddr + SDHCI_INT_ENABLE);
++      writel(mask_u32, host->ioaddr + SDHCI_SIGNAL_ENABLE);
++      host->last_op_dir = 0;
++}
++
++static void sdhci_init(struct sdhci_host *host)
++{
++      u32 intmask;
++
++      sdhci_reset(host, SDHCI_RESET_ALL);
++
++      intmask = SDHCI_INT_ADMA_ERROR |
++          SDHCI_INT_DATA_END_BIT | SDHCI_INT_DATA_CRC |
++          SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_INDEX |
++          SDHCI_INT_END_BIT | SDHCI_INT_CRC | SDHCI_INT_TIMEOUT |
++          SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL |
++          SDHCI_INT_DMA_END | SDHCI_INT_DATA_END | SDHCI_INT_RESPONSE;
++
++      if (host->flags & SDHCI_USE_DMA)
++              intmask &= ~(SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL);
++      /* Configure the WML reg */
++      if (mxc_wml_value == 512)
++              writel(SDHCI_WML_128_WORDS, host->ioaddr + SDHCI_WML);
++      else
++              writel(SDHCI_WML_16_WORDS, host->ioaddr + SDHCI_WML);
++      writel(intmask | SDHCI_INT_CARD_INT, host->ioaddr + SDHCI_INT_ENABLE);
++      writel(intmask, host->ioaddr + SDHCI_SIGNAL_ENABLE);
++}
++
++static void sdhci_activate_led(struct sdhci_host *host)
++{
++      u32 ctrl;
++
++      ctrl = readl(host->ioaddr + SDHCI_HOST_CONTROL);
++      ctrl |= SDHCI_CTRL_LED;
++      writel(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
++}
++
++static void sdhci_deactivate_led(struct sdhci_host *host)
++{
++      u32 ctrl;
++
++      ctrl = readl(host->ioaddr + SDHCI_HOST_CONTROL);
++      ctrl &= ~SDHCI_CTRL_LED;
++      writel(ctrl, host->ioaddr + SDHCI_HOST_CONTROL);
++}
++
++/*****************************************************************************\
++ *                                                                           *
++ * Core functions                                                            *
++ *                                                                           *
++\*****************************************************************************/
++
++static inline char *sdhci_sg_to_buffer(struct sdhci_host *host)
++{
++      return sg_virt(host->cur_sg);
++}
++
++static inline int sdhci_next_sg(struct sdhci_host *host)
++{
++      /*
++       * Skip to next SG entry.
++       */
++      host->cur_sg++;
++      host->num_sg--;
++
++      /*
++       * Any entries left?
++       */
++      if (host->num_sg > 0) {
++              host->offset = 0;
++              host->remain = host->cur_sg->length;
++      }
++
++      return host->num_sg;
++}
++
++static void sdhci_read_block_pio(struct sdhci_host *host)
++{
++      int blksize, chunk_remain;
++      u32 data;
++      char *buffer;
++      int size;
++
++      DBG(3, "PIO reading\n");
++
++      blksize = host->data->blksz;
++      chunk_remain = 0;
++      data = 0;
++
++      buffer = sdhci_sg_to_buffer(host) + host->offset;
++
++      while (blksize) {
++              if (chunk_remain == 0) {
++                      data = readl(host->ioaddr + SDHCI_BUFFER);
++                      chunk_remain = min(blksize, 4);
++              }
++
++              size = min(host->remain, chunk_remain);
++
++              chunk_remain -= size;
++              blksize -= size;
++              host->offset += size;
++              host->remain -= size;
++
++              while (size) {
++                      *buffer = data & 0xFF;
++                      buffer++;
++                      data >>= 8;
++                      size--;
++              }
++
++              if (host->remain == 0) {
++                      if (sdhci_next_sg(host) == 0) {
++                              BUG_ON(blksize != 0);
++                              return;
++                      }
++                      buffer = sdhci_sg_to_buffer(host);
++              }
++      }
++}
++
++static void sdhci_write_block_pio(struct sdhci_host *host)
++{
++      int blksize, chunk_remain;
++      u32 data;
++      char *buffer;
++      int bytes, size;
++
++      DBG(3, "PIO writing\n");
++
++      blksize = host->data->blksz;
++      chunk_remain = 4;
++      data = 0;
++
++      bytes = 0;
++      buffer = sdhci_sg_to_buffer(host) + host->offset;
++
++      while (blksize) {
++              size = min(host->remain, chunk_remain);
++
++              chunk_remain -= size;
++              blksize -= size;
++              host->offset += size;
++              host->remain -= size;
++
++              while (size) {
++                      data >>= 8;
++                      data |= (u32) *buffer << 24;
++                      buffer++;
++                      size--;
++              }
++
++              if (chunk_remain == 0) {
++                      writel(data, host->ioaddr + SDHCI_BUFFER);
++                      chunk_remain = min(blksize, 4);
++              }
++
++              if (host->remain == 0) {
++                      if (sdhci_next_sg(host) == 0) {
++                              BUG_ON(blksize != 0);
++                              return;
++                      }
++                      buffer = sdhci_sg_to_buffer(host);
++              }
++      }
++}
++
++static void sdhci_transfer_pio(struct sdhci_host *host)
++{
++      u32 mask;
++
++      BUG_ON(!host->data);
++
++      if (host->num_sg == 0)
++              return;
++
++      if (host->data->flags & MMC_DATA_READ)
++              mask = SDHCI_DATA_AVAILABLE;
++      else
++              mask = SDHCI_SPACE_AVAILABLE;
++
++      while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
++              if (host->data->flags & MMC_DATA_READ)
++                      sdhci_read_block_pio(host);
++              else
++                      sdhci_write_block_pio(host);
++
++              if (host->num_sg == 0)
++                      break;
++      }
++
++      DBG(3, "PIO transfer complete\n");
++}
++
++static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
++{
++      u32 count;
++      unsigned target_timeout;//, current_timeout;
++
++      WARN_ON(host->data);
++
++      if (data == NULL)
++              return;
++
++      /* Sanity checks */
++      BUG_ON(data->blksz * data->blocks > 524288);
++      BUG_ON(data->blksz > host->mmc->max_blk_size);
++      BUG_ON(data->blocks > 65535);
++
++      host->data = data;
++      host->data_early = 0;
++      if (host->data->flags & MMC_DATA_READ)
++              writel(readl(host->ioaddr + SDHCI_CLOCK_CONTROL) |
++                     SDHCI_CLOCK_HLK_EN, host->ioaddr + SDHCI_CLOCK_CONTROL);
++
++      /* timeout in us */
++      target_timeout = data->timeout_ns / 1000 +
++          data->timeout_clks / host->clock;
++#if 0
++      /*
++       * Figure out needed cycles.
++       * We do this in steps in order to fit inside a 32 bit int.
++       * The first step is the minimum timeout, which will have a
++       * minimum resolution of 6 bits:
++       * (1) 213*1000 > 222,
++       * (2) host->timeout_clk < 216
++       *     =>
++       *     (1) / (2) > 26
++       */
++      count = 0;
++      current_timeout = (1 << 13) * 1000 / host->timeout_clk;
++      while (current_timeout < target_timeout) {
++              count++;
++              current_timeout <<= 1;
++              if (count >= 0xF)
++                      break;
++      }
++
++      /*
++       * Compensate for an off-by-one error in the CaFe hardware; otherwise,
++       * a too-small count gives us interrupt timeouts.
++       */
++      if ((host->chip->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL))
++              count++;
++
++      if (count >= 0xF) {
++              DBG(0, KERN_WARNING "%s: Too large timeout requested!\n",
++                      mmc_hostname(host->mmc));
++              count = 0xE;
++      }
++#else
++      /* Set the max time-out value to level up the compatibility */
++      count = 0xE;
++#endif
++      count = (count << 16) | (readl(host->ioaddr + SDHCI_CLOCK_CONTROL) &
++                              0xFFF0FFFF);
++      writel(count, host->ioaddr + SDHCI_CLOCK_CONTROL);
++
++      if (unlikely((host->flags & SDHCI_USE_DMA) &&
++                   (host->chip->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) &&
++                   ((data->blksz * data->blocks) & 0x3))) {
++              DBG(0, "Reverting to PIO because of transfer size (%d)\n",
++                      data->blksz * data->blocks);
++              host->flags &= ~SDHCI_REQ_USE_DMA;
++      } else if (host->flags & SDHCI_USE_DMA) {
++              host->flags |= SDHCI_REQ_USE_DMA;
++      }
++
++      /*
++       * The assumption here being that alignment is the same after
++       * translation to device address space.
++       */
++      if (unlikely((host->flags & SDHCI_REQ_USE_DMA) &&
++                   (host->chip->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) &&
++                   (data->sg->offset & 0x3))) {
++              DBG(0, "Reverting to PIO because of bad alignment\n");
++              host->flags &= ~SDHCI_REQ_USE_DMA;
++      }
++
++      if (host->flags & SDHCI_REQ_USE_DMA) {
++              int i;
++              struct scatterlist *tsg;
++
++              host->dma_size = data->blocks * data->blksz;
++              count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
++                              (data->flags & MMC_DATA_READ) ? DMA_FROM_DEVICE :
++                              DMA_TO_DEVICE);
++              BUG_ON(count != data->sg_len);
++              DBG(2, "Configure the sg DMA, %s, len is 0x%08x, count is %d\n",
++                      (data->flags & MMC_DATA_READ) ?
++                      "DMA_FROM_DEVICE" : "DMA_TO_DEVICE", host->dma_size,
++                      count);
++
++              /* Make sure the ADMA mode is selected. */
++              if (host->caps & (SDHCI_CAN_DO_ADMA1 | SDHCI_CAN_DO_ADMA2)) {
++                      DBG(2, "%s: Enabling ADMA\n", __FUNCTION__);
++                      i = readl(host->ioaddr + SDHCI_HOST_CONTROL);
++                      i |= SDHCI_CTRL_ADMA;
++                      writel(i, host->ioaddr + SDHCI_HOST_CONTROL);
++              } else
++                      goto single_dma;
++
++              tsg = data->sg;
++              /* ADMA mode is used, create the descriptor table */
++              for (i = 0; i < count; i++, tsg++) {
++                      struct adma_desc *adma_desc = &host->adma_des_table[i];
++
++                      if (tsg->dma_address & 0xFFF) {
++                              printk(KERN_WARNING "ADMA addr isn't 4K aligned: 0x%08x\n",
++                                      tsg->dma_address);
++                              printk(KERN_WARNING "Changed to Single DMA mode\n");
++                              goto single_dma;
++                      }
++                      adma_desc->length = tsg->length;
++                      adma_desc->attr = FSL_ADMA_DES_ATTR_SET |
++                              FSL_ADMA_DES_ATTR_VALID;
++                      adma_desc->dma_addr = tsg->dma_address |
++                              FSL_ADMA_DES_ATTR_TRAN |
++                              FSL_ADMA_DES_ATTR_VALID |
++                              ((count == (i + 1)) ? FSL_ADMA_DES_ATTR_END : 0);
++              }
++
++              /* Write the physical address to ADMA address reg */
++              writel(virt_to_phys(host->adma_des_table),
++                     host->ioaddr + SDHCI_ADMA_ADDRESS);
++              DBG(-1, "%s: ADMA addr: %08x(%08x)\n", __FUNCTION__,
++                      readl(host->ioaddr + SDHCI_DMA_ADDRESS),
++                      sg_dma_address(data->sg));
++              goto skip;
++      single_dma:
++              /* Rollback to the Single DMA mode */
++              i = readl(host->ioaddr + SDHCI_HOST_CONTROL);
++              i &= ~SDHCI_CTRL_ADMA;
++              writel(i, host->ioaddr + SDHCI_HOST_CONTROL);
++              /* Single DMA mode is used */
++      skip:
++              writel(sg_dma_address(data->sg),
++                     host->ioaddr + SDHCI_DMA_ADDRESS);
++              DBG(0, "%s: DMA addr: %08x(%08x)\n", __FUNCTION__,
++                      readl(host->ioaddr + SDHCI_DMA_ADDRESS),
++                      sg_dma_address(data->sg));
++      } else if ((host->flags & SDHCI_USE_EXTERNAL_DMA) &&
++                 (data->blocks * data->blksz >= mxc_wml_value)) {
++              host->dma_size = data->blocks * data->blksz;
++              DBG(2, "Configure the External DMA, %s, len is 0x%08x\n",
++                      (data->flags & MMC_DATA_READ) ?
++                      "DMA_FROM_DEVICE" : "DMA_TO_DEVICE", host->dma_size);
++
++              if (data->blksz & 0x3) {
++                      dev_err(mmc_dev(host->mmc),
++                              "block size not multiple of 4 bytes\n");
++              }
++
++              if (data->flags & MMC_DATA_READ)
++                      host->dma_dir = DMA_FROM_DEVICE;
++              else
++                      host->dma_dir = DMA_TO_DEVICE;
++
++              host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg,
++                                         data->sg_len, host->dma_dir);
++
++              if (data->flags & MMC_DATA_READ) {
++                      mxc_dma_sg_config(host->dma, data->sg, data->sg_len,
++                                        host->dma_size, MXC_DMA_MODE_READ);
++              } else {
++                      mxc_dma_sg_config(host->dma, data->sg, data->sg_len,
++                                        host->dma_size, MXC_DMA_MODE_WRITE);
++              }
++      } else {
++              host->cur_sg = data->sg;
++              host->num_sg = data->sg_len;
++
++              host->offset = 0;
++              host->remain = host->cur_sg->length;
++      }
++
++      /* We do not handle DMA boundaries, so set it to max (512 KiB) */
++      writel((data->blocks << 16) | SDHCI_MAKE_BLKSZ(7, data->blksz),
++             host->ioaddr + SDHCI_BLOCK_SIZE);
++}
++
++static void sdhci_finish_data(struct sdhci_host *host)
++{
++      struct mmc_data *data;
++      u16 blocks;
++
++      BUG_ON(!host->data);
++
++      data = host->data;
++      host->data = NULL;
++
++      if (host->flags & SDHCI_REQ_USE_DMA) {
++              dma_unmap_sg(&(host->chip->pdev)->dev, data->sg, data->sg_len,
++                           (data->flags & MMC_DATA_READ) ? DMA_FROM_DEVICE :
++                           DMA_TO_DEVICE);
++      }
++      if ((host->flags & SDHCI_USE_EXTERNAL_DMA) &&
++          (host->dma_size >= mxc_wml_value) && (data != NULL)) {
++              dma_unmap_sg(mmc_dev(host->mmc), data->sg,
++                           host->dma_len, host->dma_dir);
++              host->dma_size = 0;
++      }
++
++      /*
++       * Controller doesn't count down when in single block mode.
++       */
++      if (data->blocks == 1)
++              blocks = (data->error == 0) ? 0 : 1;
++      else
++              blocks = readl(host->ioaddr + SDHCI_BLOCK_COUNT) >> 16;
++      data->bytes_xfered = data->blksz * data->blocks;
++
++      if (data->stop) {
++              /*
++               * The controller needs a reset of internal state machines
++               * upon error conditions.
++               */
++              if (data->error) {
++                      sdhci_reset(host, SDHCI_RESET_CMD);
++                      sdhci_reset(host, SDHCI_RESET_DATA);
++              }
++
++              sdhci_send_command(host, data->stop);
++      } else
++              tasklet_schedule(&host->finish_tasklet);
++}
++
++static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd)
++{
++      int flags;
++      u32 mask;
++      u32 mode = 0;
++      unsigned long timeout;
++
++      DBG(2, "sdhci_send_command 0x%08x is starting...\n", cmd->opcode);
++      WARN_ON(host->cmd);
++
++      /* Wait max 10 ms */
++      timeout = 5000;
++
++      mask = SDHCI_CMD_INHIBIT;
++      if ((cmd->data != NULL) || (cmd->flags & MMC_RSP_BUSY))
++              mask |= SDHCI_DATA_INHIBIT;
++
++      /* We shouldn't wait for data inihibit for stop commands, even
++         though they might use busy signaling */
++      if (host->mrq->data && (cmd == host->mrq->data->stop))
++              mask &= ~SDHCI_DATA_INHIBIT;
++
++      while (readl(host->ioaddr + SDHCI_PRESENT_STATE) & mask) {
++              if (timeout == 0) {
++                      printk(KERN_ERR "%s: Controller never released "
++                             "inhibit bit(s)\n", mmc_hostname(host->mmc));
++                      sdhci_dumpregs(host);
++                      cmd->error = -EIO;
++                      tasklet_schedule(&host->finish_tasklet);
++                      return;
++              }
++              timeout--;
++              udelay(20);
++      }
++
++      mod_timer(&host->timer, jiffies + 1 * HZ);
++
++      host->cmd = cmd;
++
++      sdhci_prepare_data(host, cmd->data);
++
++      writel(cmd->arg, host->ioaddr + SDHCI_ARGUMENT);
++
++      /* Set up the transfer mode */
++      if (cmd->data != NULL) {
++              mode = SDHCI_TRNS_BLK_CNT_EN | SDHCI_TRNS_DPSEL;
++              if (cmd->data->blocks > 1)
++                      mode |= SDHCI_TRNS_MULTI;
++              if (cmd->data->flags & MMC_DATA_READ)
++                      mode |= SDHCI_TRNS_READ;
++              else
++                      mode &= ~SDHCI_TRNS_READ;
++              if (host->flags & SDHCI_USE_DMA)
++                      mode |= SDHCI_TRNS_DMA;
++              if (host->flags & SDHCI_USE_EXTERNAL_DMA)
++                      DBG(2, "Prepare data complete in EXTERNAL DMA transfer mode\n");
++      }
++
++      if ((cmd->flags & MMC_RSP_136) && (cmd->flags & MMC_RSP_BUSY)) {
++              printk(KERN_ERR "%s: Unsupported response type!\n",
++                     mmc_hostname(host->mmc));
++              cmd->error = -EINVAL;
++              tasklet_schedule(&host->finish_tasklet);
++              return;
++      }
++
++      if (!(cmd->flags & MMC_RSP_PRESENT))
++              flags = SDHCI_CMD_RESP_NONE;
++      else if (cmd->flags & MMC_RSP_136)
++              flags = SDHCI_CMD_RESP_LONG;
++      else if (cmd->flags & MMC_RSP_BUSY)
++              flags = SDHCI_CMD_RESP_SHORT_BUSY;
++      else
++              flags = SDHCI_CMD_RESP_SHORT;
++
++      if (cmd->flags & MMC_RSP_CRC)
++              flags |= SDHCI_CMD_CRC;
++      if (cmd->flags & MMC_RSP_OPCODE)
++              flags |= SDHCI_CMD_INDEX;
++      if (cmd->data)
++              flags |= SDHCI_CMD_DATA;
++
++      mode |= SDHCI_MAKE_CMD(cmd->opcode, flags);
++      DBG(2, "Complete sending cmd, transfer mode 0x%08x\n", mode);
++      writel(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
++}
++
++static void sdhci_finish_command(struct sdhci_host *host)
++{
++      int i;
++
++      BUG_ON(host->cmd == NULL);
++
++      if (host->cmd->flags & MMC_RSP_PRESENT) {
++              if (host->cmd->flags & MMC_RSP_136) {
++                      /* CRC is stripped so we need to do some shifting. */
++                      for (i = 0; i < 4; i++) {
++                              host->cmd->resp[i] = readl(host->ioaddr +
++                                                         SDHCI_RESPONSE + (3 -
++                                                                           i)
++                                                         * 4) << 8;
++                              if (i != 3)
++                                      host->cmd->resp[i] |=
++                                          readb(host->ioaddr +
++                                                SDHCI_RESPONSE + (3 - i) * 4 -
++                                                1);
++                      }
++              } else {
++                      host->cmd->resp[0] =
++                          readl(host->ioaddr + SDHCI_RESPONSE);
++              }
++      }
++
++      host->cmd->error = 0;
++
++      if (host->data && host->data_early)
++              sdhci_finish_data(host);
++
++      if (!host->cmd->data)
++              tasklet_schedule(&host->finish_tasklet);
++
++      host->cmd = NULL;
++}
++
++static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
++{
++      /*This variable holds the value of clock divider, prescaler */
++      int div = 0, prescaler = 0;
++      int clk_rate;
++      u32 clk;
++
++      if (clock == 0) {
++              goto out;
++      } else {
++              sdhci_clk_enable(host);
++      }
++      if (clock == host->clock)
++              return;
++
++      clk_rate = clk_get_rate(host->clk);
++      clk = readl(host->ioaddr + SDHCI_CLOCK_CONTROL) & ~SDHCI_CLOCK_MASK;
++      writel(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
++
++      if (clock == host->min_clk)
++              prescaler = 16;
++      else
++              prescaler = 0;
++      while (prescaler <= 0x80) {
++              for (div = 0; div <= 0xF; div++) {
++                      int x;
++                      if (prescaler != 0)
++                              x = (clk_rate / (div + 1)) / (prescaler * 2);
++                      else
++                              x = clk_rate / (div + 1);
++
++                      DBG(2, "x=%d, clock=%d %d\n", x, clock, div);
++                      if (x <= clock)
++                              break;
++              }
++              if (div < 0x10)
++                      break;
++              if (prescaler == 0)
++                      prescaler = 1;
++              else
++                      prescaler <<= 1;
++      }
++      DBG(0, "prescaler = 0x%08x, divider = 0x%08x\n", prescaler, div);
++      clk |= (prescaler << 8) | (div << 4);
++
++      /* Configure the clock control register */
++      clk |= (readl(host->ioaddr + SDHCI_CLOCK_CONTROL) & ~SDHCI_CLOCK_MASK);
++      if (host->vendor_ver < ESDHC_VENDOR_V22)
++              writel(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
++      else
++              writel(clk | SDHCI_CLOCK_SD_EN,
++                      host->ioaddr + SDHCI_CLOCK_CONTROL);
++
++      /* Wait max 10 ms */
++#if 1
++      msleep(10);
++#else
++      {
++              unsigned long timeout;
++              timeout = 5000;
++              while (timeout > 0) {
++                      timeout--;
++                      udelay(20);
++              }
++      }
++#endif
++out:
++      host->clock = clock;
++}
++
++static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
++{
++      /* There is no PWR CTL REG */
++      if (host->power == power)
++              return;
++      if (platform_func(host->plat_data->setpower, host->mmc->parent, power) == 0)
++              host->power = power;
++}
++
++/*****************************************************************************\
++ *                                                                           *
++ * MMC callbacks                                                             *
++ *                                                                           *
++\*****************************************************************************/
++
++static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++      struct sdhci_host *host;
++      unsigned long flags;
++
++      host = mmc_priv(mmc);
++
++      /* Enable the clock */
++      sdhci_clk_enable(host);
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      WARN_ON(host->mrq != NULL);
++
++      sdhci_activate_led(host);
++
++      if (host->chip->quirks & SDHCI_QUIRK_RESET_AFTER_READ) {
++              if (mrq->cmd && mrq->data) {
++                      if (mrq->data->flags & MMC_DATA_READ)
++                              host->last_op_dir = 1;
++                      else {
++                              if (host->last_op_dir) {
++                                      DBG(0, "%s: Resetting SDHCI controller\n",
++                                              __FUNCTION__);
++                                      sdhci_reset(host,
++                                                  SDHCI_RESET_CMD |
++                                                  SDHCI_RESET_DATA);
++                              }
++                      }
++              }
++      }
++
++      if (host->flags & SDHCI_USE_EXTERNAL_DMA)
++              spin_unlock_irqrestore(&host->lock, flags);
++
++      host->mrq = mrq;
++      if (!(host->flags & SDHCI_CD_PRESENT)) {
++              host->mrq->cmd->error = -ENOMEDIUM;
++              tasklet_schedule(&host->finish_tasklet);
++      } else
++              sdhci_send_command(host, mrq->cmd);
++
++      if (!(host->flags & SDHCI_USE_EXTERNAL_DMA))
++              spin_unlock_irqrestore(&host->lock, flags);
++
++      mmiowb();
++}
++
++static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++      struct sdhci_host *host;
++      unsigned long flags;
++      u32 tmp;
++      mxc_dma_device_t dev_id = 0;
++
++      DBG(0, "%s: clock %u, bus %lu, power %u, vdd %u\n", __FUNCTION__,
++              ios->clock, 1UL << ios->bus_width, ios->power_mode, ios->vdd);
++
++      host = mmc_priv(mmc);
++
++      /* Configure the External DMA mode */
++      if (host->flags & SDHCI_USE_EXTERNAL_DMA) {
++              host->dma_dir = DMA_NONE;
++              if (mmc->ios.bus_width != host->mode) {
++                      mxc_dma_free(host->dma);
++                      if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
++                              if (host->id == 0)
++                                      dev_id = MXC_DMA_MMC1_WIDTH_4;
++                              else
++                                      dev_id = MXC_DMA_MMC2_WIDTH_4;
++                      } else {
++                              if (host->id == 0)
++                                      dev_id = MXC_DMA_MMC1_WIDTH_1;
++                              else
++                                      dev_id = MXC_DMA_MMC2_WIDTH_1;
++                      }
++                      host->dma = mxc_dma_request(dev_id, "MXC MMC");
++                      if (host->dma < 0) {
++                              printk(KERN_ERR "Cannot allocate MMC DMA channel\n");
++                              return;
++                      }
++                      mxc_dma_callback_set(host->dma, sdhci_dma_irq,
++                                      host);
++                      /* Configure the WML rege */
++                      if (mxc_wml_value == 512)
++                              writel(SDHCI_WML_128_WORDS,
++                                     host->ioaddr + SDHCI_WML);
++                      else
++                              writel(SDHCI_WML_16_WORDS,
++                                     host->ioaddr + SDHCI_WML);
++              }
++      }
++
++      host->mode = mmc->ios.bus_width;
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      /*
++       * Reset the chip on each power off.
++       * Should clear out any weird states.
++       */
++      if (ios->power_mode == MMC_POWER_OFF) {
++              writel(0, host->ioaddr + SDHCI_SIGNAL_ENABLE);
++              sdhci_init(host);
++      }
++
++      spin_unlock_irqrestore(&host->lock, flags);
++      sdhci_set_clock(host, ios->clock);
++      spin_lock_irqsave(&host->lock, flags);
++
++      if (ios->power_mode == MMC_POWER_OFF)
++              sdhci_set_power(host, -1);
++      else {
++              sdhci_set_power(host, ios->vdd);
++              if (!readl(host->ioaddr + SDHCI_SIGNAL_ENABLE)) {
++                      tmp = readl(host->ioaddr + SDHCI_INT_ENABLE);
++                      if (host->sdio_enable)
++                              writel(tmp, host->ioaddr + SDHCI_SIGNAL_ENABLE);
++                      else
++                              writel(tmp & ~SDHCI_INT_CARD_INT,
++                                     host->ioaddr + SDHCI_SIGNAL_ENABLE);
++              }
++      }
++
++      tmp = readl(host->ioaddr + SDHCI_HOST_CONTROL);
++
++      if (ios->bus_width == MMC_BUS_WIDTH_4) {
++              tmp &= ~SDHCI_CTRL_8BITBUS;
++              tmp |= SDHCI_CTRL_4BITBUS;
++      } else if (ios->bus_width == MMC_BUS_WIDTH_8) {
++              tmp &= ~SDHCI_CTRL_4BITBUS;
++              tmp |= SDHCI_CTRL_8BITBUS;
++      } else if (ios->bus_width == MMC_BUS_WIDTH_1) {
++              tmp &= ~SDHCI_CTRL_4BITBUS;
++              tmp &= ~SDHCI_CTRL_8BITBUS;
++      }
++
++      if (host->flags & SDHCI_USE_DMA)
++              tmp |= SDHCI_CTRL_ADMA;
++
++      writel(tmp, host->ioaddr + SDHCI_HOST_CONTROL);
++
++      /*
++       * Some (ENE) controllers go apeshit on some ios operation,
++       * signalling timeout and CRC errors even on CMD0. Resetting
++       * it on each ios seems to solve the problem.
++       */
++      if (host->chip->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS)
++              sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA);
++
++      mmiowb();
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static int sdhci_get_ro(struct mmc_host *mmc)
++{
++      struct sdhci_host *host = mmc_priv(mmc);
++      return platform_func(host->plat_data->get_ro, mmc->parent);
++}
++
++static void sdhci_enable_sdio_irq(struct mmc_host *mmc, int enable)
++{
++      struct sdhci_host *host = mmc_priv(mmc);
++      unsigned long flags;
++      u32 ier, prot, clk, present;
++
++      if (enable) {
++              if (host->sdio_enable++)
++                      return;
++      } else {
++              if (--(host->sdio_enable))
++                      return;
++      }
++      /* Enable the clock */
++      sdhci_clk_enable(host);
++      spin_lock_irqsave(&host->lock, flags);
++
++      ier = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE);
++      prot = readl(host->ioaddr + SDHCI_HOST_CONTROL);
++      clk = readl(host->ioaddr + SDHCI_CLOCK_CONTROL);
++
++      if (enable) {
++              ier |= SDHCI_INT_CARD_INT;
++              prot |= SDHCI_CTRL_D3CD;
++              clk |= SDHCI_CLOCK_PER_EN | SDHCI_CLOCK_IPG_EN;
++              present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
++              if ((present & SDHCI_CARD_INT_MASK) != SDHCI_CARD_INT_ID)
++                      writel(SDHCI_INT_CARD_INT,
++                             host->ioaddr + SDHCI_INT_STATUS);
++      } else {
++              ier &= ~SDHCI_INT_CARD_INT;
++              prot &= ~SDHCI_CTRL_D3CD;
++              clk &= ~(SDHCI_CLOCK_PER_EN | SDHCI_CLOCK_IPG_EN);
++      }
++
++      writel(prot, host->ioaddr + SDHCI_HOST_CONTROL);
++      writel(ier, host->ioaddr + SDHCI_SIGNAL_ENABLE);
++      writel(clk, host->ioaddr + SDHCI_CLOCK_CONTROL);
++
++      mmiowb();
++
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static const struct mmc_host_ops sdhci_ops = {
++      .request = sdhci_request,
++      .set_ios = sdhci_set_ios,
++      .get_ro = sdhci_get_ro,
++      .enable_sdio_irq = sdhci_enable_sdio_irq,
++};
++
++/*****************************************************************************\
++ *                                                                           *
++ * Tasklets                                                                  *
++ *                                                                           *
++\*****************************************************************************/
++
++static void sdhci_tasklet_card(unsigned long param)
++{
++      struct sdhci_host *host = (struct sdhci_host *)param;
++      unsigned long flags;
++
++      if (host->flags & SDHCI_CD_PRESENT)
++              host->flags &= ~SDHCI_CD_PRESENT;
++      else
++              host->flags |= SDHCI_CD_PRESENT;
++      /* Detect there is a card in slot or not */
++      DBG(0, "cd_status=%s\n", (host->flags & SDHCI_CD_PRESENT) ? "inserted" : "removed");
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      if (!(host->flags & SDHCI_CD_PRESENT)) {
++              if (host->mrq) {
++                      printk(KERN_ERR "%s: Card removed during transfer!\n",
++                             mmc_hostname(host->mmc));
++                      printk(KERN_ERR "%s: Resetting controller\n",
++                             mmc_hostname(host->mmc));
++
++                      sdhci_reset(host, SDHCI_RESET_CMD);
++                      sdhci_reset(host, SDHCI_RESET_DATA);
++
++                      host->mrq->cmd->error = -ENOMEDIUM;
++                      tasklet_schedule(&host->finish_tasklet);
++              }
++      }
++
++      spin_unlock_irqrestore(&host->lock, flags);
++
++      mmc_detect_change(host->mmc,
++                      msecs_to_jiffies(host->plat_data->detect_delay));
++}
++
++static void sdhci_tasklet_finish(unsigned long param)
++{
++      struct sdhci_host *host = (struct sdhci_host *)param;
++      unsigned long flags;
++      struct mmc_request *mrq;
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      del_timer(&host->timer);
++
++      mrq = host->mrq;
++
++      /*
++       * The controller needs a reset of internal state machines
++       * upon error conditions.
++       */
++      if (mrq->cmd->error ||
++              (mrq->data && (mrq->data->error ||
++                      (mrq->data->stop && mrq->data->stop->error))) ||
++              (host->chip->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) {
++              /* Some controllers need this kick or reset won't work here */
++              if (host->chip->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) {
++                      unsigned int clock;
++
++                      /* This is to force an update */
++                      clock = host->clock;
++                      host->clock = 0;
++                      spin_unlock_irqrestore(&host->lock, flags);
++                      sdhci_set_clock(host, clock);
++                      spin_lock_irqsave(&host->lock, flags);
++              }
++
++              /* Spec says we should do both at the same time, but Ricoh
++                 controllers do not like that. */
++              sdhci_reset(host, SDHCI_RESET_CMD);
++              sdhci_reset(host, SDHCI_RESET_DATA);
++      }
++
++      host->mrq = NULL;
++      host->cmd = NULL;
++      host->data = NULL;
++
++      sdhci_deactivate_led(host);
++
++      mmiowb();
++      spin_unlock_irqrestore(&host->lock, flags);
++
++      /* Stop the clock when the req is done */
++      flags = SDHCI_DATA_ACTIVE | SDHCI_DOING_WRITE | SDHCI_DOING_READ;
++      if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & flags)) {
++              sdhci_clk_disable(host);
++      }
++
++      mmc_request_done(host->mmc, mrq);
++}
++
++static void sdhci_timeout_timer(unsigned long data)
++{
++      struct sdhci_host *host = (struct sdhci_host *)data;
++      unsigned long tmp, flags;
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      if (host->mrq) {
++              printk(KERN_ERR "%s: Timeout waiting for hardware interrupt\n",
++                      mmc_hostname(host->mmc));
++              sdhci_dumpregs(host);
++
++              if (host->data) {
++                      host->data->error = -ETIMEDOUT;
++                      sdhci_finish_data(host);
++              } else {
++                      if (host->cmd)
++                              host->cmd->error = -ETIMEDOUT;
++                      else
++                              host->mrq->cmd->error = -ETIMEDOUT;
++
++                      tasklet_schedule(&host->finish_tasklet);
++              }
++
++              if (!readl(host->ioaddr + SDHCI_SIGNAL_ENABLE)) {
++                      printk(KERN_ERR "%s, ERROR SIG_INT is 0\n", __func__);
++                      tmp = readl(host->ioaddr + SDHCI_INT_ENABLE);
++                      if (host->sdio_enable)
++                              writel(tmp, host->ioaddr + SDHCI_SIGNAL_ENABLE);
++                      else
++                              writel(tmp & ~SDHCI_INT_CARD_INT,
++                                     host->ioaddr + SDHCI_SIGNAL_ENABLE);
++                      if (!host->plat_data->status(host->mmc->parent))
++                              schedule_work(&host->cd_wq);
++              }
++      }
++
++      mmiowb();
++      spin_unlock_irqrestore(&host->lock, flags);
++}
++
++static void sdhci_cd_timer(unsigned long data)
++{
++      struct sdhci_host *host = (struct sdhci_host *)data;
++      schedule_work(&host->cd_wq);
++}
++
++/*****************************************************************************\
++ *                                                                           *
++ * Interrupt handling                                                        *
++ *                                                                           *
++\*****************************************************************************/
++
++static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
++{
++      BUG_ON(intmask == 0);
++
++      if (!host->cmd) {
++              printk(KERN_ERR "%s: Got command interrupt 0x%08x even though no command operation was in progress\n",
++                     mmc_hostname(host->mmc), intmask);
++              sdhci_dumpregs(host);
++              return;
++      }
++
++      if (intmask & SDHCI_INT_TIMEOUT)
++              host->cmd->error = -ETIMEDOUT;
++      else if (intmask & (SDHCI_INT_CRC | SDHCI_INT_END_BIT |
++                          SDHCI_INT_INDEX))
++              host->cmd->error = -EILSEQ;
++
++      if (host->cmd->error)
++              tasklet_schedule(&host->finish_tasklet);
++      else if (intmask & SDHCI_INT_RESPONSE)
++              sdhci_finish_command(host);
++}
++
++static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
++{
++      u32 intsave = 0;
++
++      BUG_ON(intmask == 0);
++
++      if (!host->data) {
++              /*
++               * A data end interrupt is sent together with the response
++               * for the stop command.
++               */
++              if (intmask & SDHCI_INT_DATA_END)
++                      return;
++
++              printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
++                     "though no data operation was in progress\n",
++                     mmc_hostname(host->mmc), (unsigned)intmask);
++              sdhci_dumpregs(host);
++              sdhci_reset(host, SDHCI_RESET_CMD);
++              sdhci_reset(host, SDHCI_RESET_DATA);
++              return;
++      }
++
++      /* Mask the INT */
++      intsave = readl(host->ioaddr + SDHCI_INT_ENABLE);
++      writel(intsave & (~(intmask & SDHCI_INT_DATA_RE_MASK)),
++             host->ioaddr + SDHCI_INT_ENABLE);
++
++      if (intmask & SDHCI_INT_DATA_TIMEOUT)
++              host->data->error = -ETIMEDOUT;
++      else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT))
++              host->data->error = -EILSEQ;
++
++      if (host->data->error)
++              sdhci_finish_data(host);
++      else {
++              if ((host->flags & SDHCI_USE_EXTERNAL_DMA) &&
++                  (host->dma_size >= mxc_wml_value)) {
++                      /* Use DMA if transfer size is greater than fifo size */
++                      if (intmask & (SDHCI_INT_DATA_AVAIL |
++                                     SDHCI_INT_SPACE_AVAIL)) {
++                              intsave &= ~SDHCI_INT_DATA_RE_MASK;
++                              if (mxc_dma_enable(host->dma) < 0) {
++                                      printk(KERN_ERR "ENABLE SDMA ERR\n");
++                                      intsave |= SDHCI_INT_DATA_RE_MASK;
++                              }
++                      }
++              } else {
++                      if (intmask & (SDHCI_INT_DATA_AVAIL |
++                                     SDHCI_INT_SPACE_AVAIL))
++                              sdhci_transfer_pio(host);
++              }
++
++              /*
++               * We currently don't do anything fancy with DMA
++               * boundaries, but as we can't disable the feature
++               * we need to at least restart the transfer.
++               */
++              if ((intmask & SDHCI_INT_DMA_END) &&
++                  (!(intmask & SDHCI_INT_DATA_END)))
++                      writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS),
++                             host->ioaddr + SDHCI_DMA_ADDRESS);
++
++              if (intmask & SDHCI_INT_DATA_END) {
++                      if (host->data->flags & MMC_DATA_READ)
++                              writel(readl(host->ioaddr + SDHCI_CLOCK_CONTROL)
++                                     & ~SDHCI_CLOCK_HLK_EN,
++                                     host->ioaddr + SDHCI_CLOCK_CONTROL);
++                      if (host->cmd) {
++                              /*
++                               * Data managed to finish before the
++                               * command completed. Make sure we do
++                               * things in the proper order.
++                               */
++                              host->data_early = 1;
++                      } else {
++
++                              if (host->vendor_ver < ESDHC_VENDOR_V22) {
++                                      /*
++                                       * There are the DATA END INT when
++                                       * writing is not complete. Double
++                                       * check on it. TO2 has been fixed it.
++                                       */
++                                      intmask = readl(host->ioaddr +
++                                                      SDHCI_PRESENT_STATE);
++                                      if (intmask & SDHCI_DATA_ACTIVE)
++                                              goto data_irq_out;
++                              }
++                              sdhci_finish_data(host);
++                      }
++              }
++      }
++      data_irq_out:
++      /* Enable the INT */
++      writel(intsave, host->ioaddr + SDHCI_INT_ENABLE);
++}
++
++/*!
++* This function is called by DMA Interrupt Service Routine to indicate
++* requested DMA transfer is completed.
++*
++* @param   devid  pointer to device specific structure
++* @param   error any DMA error
++* @param   cnt   amount of data that was transferred
++*/
++static void sdhci_dma_irq(void *devid, int error, unsigned int cnt)
++{
++      u32 intsave = 0;
++      int ret;
++      struct sdhci_host *host = devid;
++
++      DBG(0, "%s: error: %d Transferred bytes: %d\n", __FUNCTION__, error, cnt);
++      if (host->flags & SDHCI_USE_EXTERNAL_DMA) {
++              /*
++               * Stop the DMA transfer here, the data_irq will be called
++               * to process the others
++               */
++              ret = mxc_dma_disable(host->dma);
++              if (ret < 0)
++                      printk(KERN_ERR "Disable dma channel err %d\n", ret);
++
++              if (error) {
++                      DBG(0, "Error in DMA transfer\n");
++                      return;
++              }
++              intsave = readl(host->ioaddr + SDHCI_INT_ENABLE);
++              intsave |= SDHCI_INT_DATA_RE_MASK;
++              writel(intsave, host->ioaddr + SDHCI_INT_ENABLE);
++      }
++}
++
++static void esdhc_cd_callback(struct work_struct *work)
++{
++      struct sdhci_host *host = container_of(work, struct sdhci_host, cd_wq);
++      unsigned long flags;
++      unsigned int cd_status = 0;
++
++      if(host->plat_data->force_sd_detect == 0) {     // bypass hw cd
++              cd_status = host->plat_data->status(host->mmc->parent);
++              if (cd_status)
++                      host->flags &= ~SDHCI_CD_PRESENT;
++              else
++                      host->flags |= SDHCI_CD_PRESENT;
++      } else {
++              host->flags |= SDHCI_CD_PRESENT;
++      }
++
++      /* Detect, if there is a card in slot or not */
++      DBG(0, "cd_status=%d %s\n", cd_status,
++              (host->flags & SDHCI_CD_PRESENT) ? "inserted" : "removed");
++
++      spin_lock_irqsave(&host->lock, flags);
++
++      if (!(host->flags & SDHCI_CD_PRESENT)) {
++              dev_info(mmc_dev(host->mmc),
++                      "Card removed and resetting controller\n");
++              if (host->mrq) {
++                      struct mmc_data *data;
++                      data = host->data;
++                      host->data = NULL;
++
++                      dev_err(mmc_dev(host->mmc),
++                              "Card removed during transfer!\n");
++
++                      if ((host->flags & SDHCI_USE_EXTERNAL_DMA) &&
++                          (data != NULL)) {
++                              dma_unmap_sg(mmc_dev(host->mmc), data->sg,
++                                           host->dma_len, host->dma_dir);
++                              host->dma_size = 0;
++                      }
++                      sdhci_reset(host, SDHCI_RESET_CMD);
++                      sdhci_reset(host, SDHCI_RESET_DATA);
++
++                      host->mrq->cmd->error = -ENOMEDIUM;
++                      tasklet_schedule(&host->finish_tasklet);
++              }
++
++              if (host->init_flag > 0)
++                      /* The initialization of sdhc controller has been
++                       * done in the resume func */
++                      host->init_flag--;
++              else
++                      sdhci_init(host);
++      }
++
++      spin_unlock_irqrestore(&host->lock, flags);
++
++      if (host->flags & SDHCI_CD_PRESENT) {
++              del_timer(&host->cd_timer);
++              mmc_detect_change(host->mmc,
++                              msecs_to_jiffies(host->plat_data->detect_delay));
++      } else
++              mmc_detect_change(host->mmc, 0);
++}
++
++/*!
++* Card detection interrupt service routine registered to handle
++* the SDHC interrupts. This interrupt routine handles card
++* insertion and card removal interrupts.
++*
++* @param   irq    the interrupt number
++* @param   devid  driver private data
++*
++* @return  The function returns \b IRQ_RETVAL(1)
++*/
++static irqreturn_t sdhci_cd_irq(int irq, void *dev_id)
++{
++      struct mmc_host *mmc = dev_id;
++      struct sdhci_host *host = mmc_priv(mmc);
++
++      dev_dbg(mmc_dev(mmc), "%s\n", __func__);
++
++      schedule_work(&host->cd_wq);
++      return IRQ_HANDLED;
++}
++
++static irqreturn_t sdhci_irq(int irq, void *dev_id)
++{
++      irqreturn_t result;
++      struct sdhci_host *host = dev_id;
++      u32 intmask;
++      int cardint = 0;
++
++      BUG_ON(!host);
++      BUG_ON(!host->ioaddr);
++      spin_lock(&host->lock);
++
++      intmask = readl(host->ioaddr + SDHCI_INT_STATUS);
++
++      if (!intmask || intmask == 0xffffffff) {
++              result = IRQ_NONE;
++              goto out;
++      }
++
++      DBG(3, "*** %s got interrupt: 0x%08x\n",
++              mmc_hostname(host->mmc), intmask);
++
++      if (intmask & (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE)) {
++              writel(intmask &
++                     (SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE),
++                     host->ioaddr + SDHCI_INT_STATUS);
++              tasklet_schedule(&host->card_tasklet);
++      }
++
++      intmask &= ~(SDHCI_INT_CARD_INSERT | SDHCI_INT_CARD_REMOVE);
++
++      if (intmask & SDHCI_INT_CMD_MASK) {
++              writel(intmask & SDHCI_INT_CMD_MASK,
++                     host->ioaddr + SDHCI_INT_STATUS);
++              sdhci_cmd_irq(host, intmask & SDHCI_INT_CMD_MASK);
++      }
++
++      if (intmask & SDHCI_INT_DATA_MASK) {
++              writel(intmask & SDHCI_INT_DATA_MASK,
++                     host->ioaddr + SDHCI_INT_STATUS);
++#ifdef CONFIG_ARCH_MX35
++              if (mx35_revision() < MX35_CHIP_REV_2_0) {
++                      if (!(readl(host->ioaddr + SDHCI_TRANSFER_MODE) &
++                                      SDHCI_TRNS_READ))
++                              intmask &= ~SDHCI_INT_DATA_END_BIT;
++              }
++#endif
++              if (intmask & SDHCI_INT_DATA_MASK)
++                      sdhci_data_irq(host, intmask & SDHCI_INT_DATA_MASK);
++      }
++
++      intmask &= ~(SDHCI_INT_CMD_MASK | SDHCI_INT_DATA_MASK);
++      intmask &= ~SDHCI_INT_ERROR;
++
++      if (intmask & SDHCI_INT_BUS_POWER) {
++              printk(KERN_ERR "%s: Card is consuming too much power!\n",
++                     mmc_hostname(host->mmc));
++              writel(SDHCI_INT_BUS_POWER, host->ioaddr + SDHCI_INT_STATUS);
++      }
++
++      intmask &= ~SDHCI_INT_BUS_POWER;
++
++      if (intmask & SDHCI_INT_CARD_INT)
++              cardint = readl(host->ioaddr + SDHCI_SIGNAL_ENABLE) &
++                  SDHCI_INT_CARD_INT;
++
++      intmask &= ~SDHCI_INT_CARD_INT;
++
++      if (intmask) {
++              printk(KERN_ERR "%s: Unexpected interrupt 0x%08x\n",
++                     mmc_hostname(host->mmc), intmask);
++              sdhci_dumpregs(host);
++
++              writel(intmask, host->ioaddr + SDHCI_INT_STATUS);
++      }
++
++      result = IRQ_HANDLED;
++
++      mmiowb();
++out:
++      spin_unlock(&host->lock);
++
++      /*
++       * We have to delay this as it calls back into the driver.
++       */
++      if (cardint)
++              mmc_signal_sdio_irq(host->mmc);
++
++      return result;
++}
++
++/*****************************************************************************\
++ *                                                                           *
++ * Suspend/resume                                                            *
++ *                                                                           *
++\*****************************************************************************/
++
++#ifdef CONFIG_PM
++static int sdhci_suspend(struct device *dev)
++{
++      struct sdhci_chip *chip;
++      int i, ret;
++
++      chip = dev_get_drvdata(dev);
++      if (!chip)
++              return 0;
++
++      DBG(0, "Suspending...\n");
++
++      for (i = 0; i < chip->num_slots; i++) {
++              if (!chip->hosts[i])
++                      continue;
++              ret = mmc_suspend_host(chip->hosts[i]->mmc);
++              if (ret) {
++                      for (i--; i >= 0; i--)
++                              mmc_resume_host(chip->hosts[i]->mmc);
++                      return ret;
++              }
++      }
++
++      for (i = 0; i < chip->num_slots; i++) {
++              struct sdhci_host *host = chip->hosts[i];
++
++              if (host == NULL)
++                      continue;
++              free_irq(host->irq, host);
++              ret = platform_func(host->plat_data->suspend, dev);
++      }
++
++      return ret;
++}
++
++static int sdhci_resume(struct device *dev)
++{
++      struct sdhci_chip *chip;
++      int i, ret;
++
++      chip = dev_get_drvdata(dev);
++      if (!chip)
++              return 0;
++
++      DBG(0, "Resuming...\n");
++
++      for (i = 0; i < chip->num_slots; i++) {
++              struct sdhci_host *host = chip->hosts[i];
++
++              if (host == NULL)
++                      continue;
++
++              ret = platform_func(host->plat_data->resume, dev);
++              if (ret) {
++                      return ret;
++              }
++              ret = request_irq(host->irq, sdhci_irq, 0,
++                              mmc_hostname(host->mmc),
++                              host);
++              if (ret)
++                      return ret;
++              sdhci_init(host);
++              host->init_flag = 2;
++              mmiowb();
++              ret = mmc_resume_host(host->mmc);
++              if (ret)
++                      return ret;
++      }
++
++      return 0;
++}
++#else /* CONFIG_PM */
++#define sdhci_suspend NULL
++#define sdhci_resume NULL
++#endif /* CONFIG_PM */
++
++static ssize_t
++mmc_mxc_show_force_cd(struct device *dev, struct device_attribute *attr,
++                      char *buf)
++{
++      struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
++      struct sdhci_host *host = mmc_priv(mmc);
++      struct mxc_sdhci_platform_data *pdata =  host->plat_data;
++
++      return sprintf(buf, "%d\n", pdata->force_sd_detect);
++}
++
++static ssize_t
++mmc_mxc_store_force_cd(struct device *dev, struct device_attribute *attr,
++                      const char *buf, size_t count)
++{
++      struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev);
++      struct sdhci_host *host = mmc_priv(mmc);
++      struct mxc_sdhci_platform_data *pdata =  host->plat_data;
++      
++      if(count != 2) return count;
++
++      switch(buf[0]) {
++      default :
++      case '0':       pdata->force_sd_detect = 0;
++                      break;
++      case '1':        pdata->force_sd_detect = 1;
++                      break;
++      };
++
++      schedule_work(&host->cd_wq);
++      return count;
++}
++
++static DEVICE_ATTR(force_cd, S_IRUGO | S_IWUGO, mmc_mxc_show_force_cd, mmc_mxc_store_force_cd);
++
++
++/*****************************************************************************\
++ *                                                                           *
++ * Device probing/removal                                                    *
++ *                                                                           *
++\*****************************************************************************/
++
++static int __devinit sdhci_probe_slot(struct platform_device *pdev,
++                              struct sdhci_chip *chip, int slot)
++{
++      struct mxc_sdhci_platform_data *mmc_plat = pdev->dev.platform_data;
++      int ret = 0;
++      unsigned int version;
++      struct mmc_host *mmc;
++      struct sdhci_host *host;
++      mxc_dma_device_t dev_id = 0;
++
++      dev_dbg(&pdev->dev, "%s: Init slot %d on chip %p\n",
++              __FUNCTION__, slot, chip);
++      if (!mmc_plat)
++              return -ENODEV;
++
++      mmc = mmc_alloc_host(sizeof(struct sdhci_host), &pdev->dev);
++      if (!mmc)
++              return -ENOMEM;
++
++      host = mmc_priv(mmc);
++      host->mmc = mmc;
++      host->id = pdev->id;
++      host->dma = -1;
++      host->plat_data = mmc_plat;
++
++      host->chip = chip;
++      chip->hosts[slot] = host;
++
++      /* Active the eSDHC bus */
++      ret = platform_func(mmc_plat->init, &pdev->dev, sdhci_cd_irq,
++                      host->mmc);
++      if (ret) {
++              DBG(0, "%s: Platform init failed: %d\n", __FUNCTION__, ret);
++              goto out1;
++      }
++
++      /* Get the SDHC clock from clock system APIs */
++      host->clk = clk_get(&pdev->dev, "esdhc_clk");
++      if (IS_ERR(host->clk)) {
++              dev_err(&pdev->dev, "failed to get clock esdhc_clk\n");
++              ret = PTR_ERR(host->clk);
++              goto out1a;
++      }
++      DBG(0, "SDHC: %d clock: %lu\n", pdev->id, clk_get_rate(host->clk));
++
++      host->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (!host->res) {
++              ret = -ENODEV;
++              goto out2;
++      }
++
++      host->irq = platform_get_irq(pdev, 0);
++      if (host->irq < 0) {
++              ret = -ENODEV;
++              goto out2;
++      }
++
++      host->detect_irq = platform_get_irq(pdev, 1);
++      if (host->detect_irq < 0) {
++              host->flags &= ~SDHCI_CD_PRESENT;
++              if ((pdev->id >= 0) && (pdev->id < MXC_SDHCI_NUM))
++                      mxc_fix_chips[pdev->id] = chip;
++              goto no_detect_irq;
++      }
++//    MASU FIXME THIS
++      if(mmc_plat->force_sd_detect == 0) {    // bypass hw cd
++              ret = mmc_plat->status(host->mmc->parent);
++              if (ret)
++                      host->flags &= ~SDHCI_CD_PRESENT;
++              else
++                      host->flags |= SDHCI_CD_PRESENT;
++      } else {
++              host->flags |= SDHCI_CD_PRESENT;
++      }
++//    MASU END FIXING
++
++no_detect_irq:
++      DBG(0, "slot %d at 0x%08x, irq %d\n", slot, host->res->start, host->irq);
++      if (!request_mem_region(host->res->start, resource_size(host->res),
++                                      pdev->name)) {
++              printk(KERN_ERR "request_mem_region failed\n");
++              ret = -EBUSY;
++              goto out2;
++      }
++      host->ioaddr = ioremap(host->res->start, resource_size(host->res));
++      if (!host->ioaddr) {
++              ret = -ENOMEM;
++              goto out3;
++      }
++
++      DBG(1, "%s: Resetting SDHCI controller\n", __FUNCTION__);
++      sdhci_reset(host, SDHCI_RESET_ALL);
++
++      version = readl(host->ioaddr + SDHCI_HOST_VERSION);
++      host->vendor_ver = (version & SDHCI_VENDOR_VER_MASK) >>
++              SDHCI_VENDOR_VER_SHIFT;
++      version = (version & SDHCI_SPEC_VER_MASK) >> SDHCI_SPEC_VER_SHIFT;
++      dev_dbg(&pdev->dev, "SDHCI controller version: %d vendor version %d.%d\n",
++              version, (host->vendor_ver >> 4) + 1, host->vendor_ver & 0xf);
++      if (version != 1) {
++              printk(KERN_ERR "%s: Unknown controller version (%d). You may experience problems\n",
++                      mmc_hostname(mmc), version);
++      }
++
++      host->caps = readl(host->ioaddr + SDHCI_CAPABILITIES);
++      if (!(chip->quirks & SDHCI_QUIRK_INTERNAL_ADVANCED_DMA)) {
++              host->caps &= ~(SDHCI_CAN_DO_ADMA1 | SDHCI_CAN_DO_ADMA2);
++      }
++      if (chip->quirks & SDHCI_QUIRK_FORCE_DMA)
++              host->flags |= SDHCI_USE_DMA;
++      else if (!(host->caps & SDHCI_CAN_DO_DMA))
++              DBG(0, "Controller doesn't have DMA capability\n");
++      else if (chip->quirks & (SDHCI_QUIRK_INTERNAL_ADVANCED_DMA |
++                                      SDHCI_QUIRK_INTERNAL_SIMPLE_DMA))
++              host->flags |= SDHCI_USE_DMA;
++      else if (chip->quirks & (SDHCI_QUIRK_EXTERNAL_DMA_MODE))
++              host->flags |= SDHCI_USE_EXTERNAL_DMA;
++      else
++              host->flags &= ~SDHCI_USE_DMA;
++
++      /*
++       * These definitions of eSDHC are not compatible with the SD Host
++       * Controller Spec v2.0
++       */
++      host->min_clk = mmc_plat->min_clk;
++      host->max_clk = mmc_plat->max_clk;
++      host->timeout_clk = 1024 * 1000;        /* Just set the value temporarily. */
++
++      /*
++       * Set host parameters.
++       */
++      mmc->ops = &sdhci_ops;
++      mmc->f_min = host->min_clk;
++      mmc->f_max = host->max_clk;
++      mmc->caps = MMC_CAP_SDIO_IRQ;
++      mmc->caps |= mmc_plat->caps;
++
++      if (host->caps & SDHCI_CAN_DO_HISPD)
++              mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED;
++
++      mmc->ocr_avail = mmc_plat->ocr_avail;
++      if (host->caps & SDHCI_CAN_VDD_330)
++              mmc->ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34;
++      if (host->caps & SDHCI_CAN_VDD_300)
++              mmc->ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31;
++      if (host->caps & SDHCI_CAN_VDD_180)
++              mmc->ocr_avail |= MMC_VDD_165_195;
++
++      if (mmc->ocr_avail == 0) {
++              printk(KERN_ERR "%s: Hardware doesn't report any supported voltages\n",
++                      mmc_hostname(mmc));
++              ret = -ENODEV;
++              goto out3;
++      }
++
++      spin_lock_init(&host->lock);
++
++      /*
++       * Maximum number of segments. Hardware cannot do scatter lists.
++       */
++      if (host->flags & SDHCI_USE_DMA)
++              mmc->max_hw_segs = 1;
++      else
++              mmc->max_hw_segs = 16;
++      mmc->max_phys_segs = 16;
++
++      /*
++       * Maximum number of sectors in one transfer. Limited by DMA boundary
++       * size (512KiB).
++       */
++      if (host->flags & SDHCI_USE_EXTERNAL_DMA)
++              mmc->max_req_size = SZ_32M;
++      else
++              mmc->max_req_size = SZ_512K;
++
++      /*
++       * Maximum segment size. Could be one segment with the maximum number
++       * of bytes.
++       */
++      mmc->max_seg_size = mmc->max_req_size;
++
++      /*
++       * Maximum block size. This varies from controller to controller and
++       * is specified in the capabilities register.
++       */
++      mmc->max_blk_size = (host->caps & SDHCI_MAX_BLOCK_MASK) >>
++              SDHCI_MAX_BLOCK_SHIFT;
++      if (mmc->max_blk_size > 3) {
++              printk(KERN_WARNING "%s: Invalid maximum block size, "
++                     "assuming 512 bytes\n", mmc_hostname(mmc));
++              mmc->max_blk_size = 512;
++      } else
++              mmc->max_blk_size = 512 << mmc->max_blk_size;
++
++      /*
++       * Maximum block count.
++       */
++      mmc->max_blk_count = 65535;
++
++      /*
++       * Allocate contiguous physical memory used for storing the ADMA
++       * descriptor table.
++       */
++      if (host->flags & SDHCI_USE_DMA) {
++              host->dma_desc_size = (2 * (mmc->max_phys_segs) + 1) *
++                      sizeof(unsigned int);
++              host->adma_des_table = dma_alloc_coherent(&pdev->dev,
++                                                      host->dma_desc_size,
++                                                      &host->dma_desc,
++                                                      GFP_DMA);
++              if (host->adma_des_table == NULL) {
++                      printk(KERN_ERR "Cannot allocate ADMA memory\n");
++                      ret = -ENOMEM;
++                      goto out3;
++              }
++      }
++
++      /*
++       * Init tasklets.
++       */
++      tasklet_init(&host->card_tasklet,
++                   sdhci_tasklet_card, (unsigned long)host);
++      tasklet_init(&host->finish_tasklet,
++                   sdhci_tasklet_finish, (unsigned long)host);
++
++      /* initialize the work queue */
++      INIT_WORK(&host->cd_wq, esdhc_cd_callback);
++
++      setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host);
++      setup_timer(&host->cd_timer, sdhci_cd_timer, (unsigned long)host);
++
++      ret = request_irq(host->irq, sdhci_irq, 0, pdev->name, host);
++      if (ret)
++              goto out5;
++
++      sdhci_init(host);
++
++      if (host->flags & SDHCI_USE_EXTERNAL_DMA) {
++              /* Apply the 1-bit SDMA channel. */
++              if (host->id == 0)
++                      dev_id = MXC_DMA_MMC1_WIDTH_1;
++              else
++                      dev_id = MXC_DMA_MMC2_WIDTH_1;
++              host->dma = mxc_dma_request(dev_id, "MXC MMC");
++              if (host->dma < 0) {
++                      DBG(0, "Cannot allocate MMC DMA channel\n");
++                      ret = host->dma;
++                      goto out6;
++              }
++              mxc_dma_callback_set(host->dma, sdhci_dma_irq, host);
++      }
++#ifdef CONFIG_MMC_DEBUG
++      sdhci_dumpregs(host);
++#endif
++      mmiowb();
++
++      ret = mmc_add_host(mmc);
++      if (ret)
++              goto out6;
++
++// MASU FIXME 
++      ret = device_create_file(&mmc->class_dev,
++                              &dev_attr_force_cd);
++      if (ret < 0)
++              goto out6;
++// MASU FIXME END
++
++      if (host->flags & SDHCI_USE_EXTERNAL_DMA)
++              dev_info(mmc_dev(mmc), "SDHCI detect irq %d irq %d %s\n",
++                      host->detect_irq, host->irq, "EXTERNAL DMA");
++      else
++              dev_info(mmc_dev(mmc), "SDHCI detect irq %d irq %d %s\n",
++                      host->detect_irq, host->irq,
++                      (host->flags & SDHCI_USE_DMA) ? "INTERNAL DMA" : "PIO");
++
++      return 0;
++
++out6:
++      free_irq(host->irq, host);
++out5:
++      if (host->detect_irq >= 0) {
++              if ((pdev->id >= 0) && (pdev->id < MXC_SDHCI_NUM))
++                      mxc_fix_chips[pdev->id] = NULL;
++      }
++      del_timer_sync(&host->timer);
++      del_timer_sync(&host->cd_timer);
++
++      tasklet_kill(&host->card_tasklet);
++      tasklet_kill(&host->finish_tasklet);
++
++      if (host->flags & SDHCI_USE_DMA)
++              dma_free_coherent(&pdev->dev, host->dma_desc_size,
++                              host->adma_des_table, host->dma_desc);
++out3:
++      release_mem_region(host->res->start, resource_size(host->res));
++out2:
++      clk_disable(host->clk);
++      clk_put(host->clk);
++out1a:
++      platform_func(mmc_plat->exit, &pdev->dev, mmc);
++out1:
++      mmc_free_host(mmc);
++      DBG(0, "%s: Failed to init SDHCI driver: %d\n", __FUNCTION__, ret);
++      return ret;
++}
++
++static void sdhci_remove_slot(struct platform_device *pdev, int slot)
++{
++      struct sdhci_chip *chip;
++      struct mmc_host *mmc;
++      struct sdhci_host *host;
++
++      DBG(0, "%s: Removing slot %d\n", __FUNCTION__, slot);
++
++      chip = dev_get_drvdata(&pdev->dev);
++      host = chip->hosts[slot];
++      mmc = host->mmc;
++
++      chip->hosts[slot] = NULL;
++// MASU FIXME START
++      device_remove_file(&mmc->class_dev, &dev_attr_force_cd);
++//MASU END
++      mmc_remove_host(mmc);
++
++      sdhci_reset(host, SDHCI_RESET_ALL);
++
++      if (host->detect_irq >= 0) {
++              if ((pdev->id >= 0) && (pdev->id < MXC_SDHCI_NUM))
++                      mxc_fix_chips[pdev->id] = NULL;
++      }
++      free_irq(host->irq, host);
++      if (chip->quirks & SDHCI_QUIRK_EXTERNAL_DMA_MODE) {
++              host->flags &= ~SDHCI_USE_EXTERNAL_DMA;
++              mxc_dma_free(host->dma);
++      }
++
++      del_timer_sync(&host->timer);
++
++      tasklet_kill(&host->card_tasklet);
++      tasklet_kill(&host->finish_tasklet);
++
++      if (host->flags & SDHCI_USE_DMA)
++              dma_free_coherent(&pdev->dev, host->dma_desc_size,
++                              host->adma_des_table, host->dma_desc);
++
++      release_mem_region(host->res->start, resource_size(host->res));
++      clk_disable(host->clk);
++      clk_put(host->clk);
++      platform_func(host->plat_data->exit, &pdev->dev, mmc);
++      mmc_free_host(mmc);
++}
++
++static void sdhci_enable_quirks(struct sdhci_chip *chip)
++{
++      if (cpu_is_mx25()) {
++              //chip->quirks |= SDHCI_QUIRK_INTERNAL_ADVANCED_DMA;
++              chip->quirks |= SDHCI_QUIRK_INTERNAL_SIMPLE_DMA;
++              //chip->quirks |= SDHCI_QUIRK_RESET_AFTER_READ;
++      }
++#ifdef CONFIG_ARCH_MX35
++      if (mx35_revision() < MX35_CHIP_REV_2_0) {
++              chip->quirks |= SDHCI_QUIRK_RESET_AFTER_READ;
++      }
++#endif
++}
++
++static int __devinit sdhci_probe(struct platform_device *pdev)
++{
++      int ret = 0, i;
++      u8 slots = 1;
++      struct sdhci_chip *chip;
++
++      printk(KERN_INFO "MXC SDHCI Controller Driver\n");
++
++      chip = kzalloc(sizeof(struct sdhci_chip) +
++                     sizeof(struct sdhci_host *) * slots, GFP_KERNEL);
++      if (!chip) {
++              ret = -ENOMEM;
++              goto err;
++      }
++      chip->pdev = pdev;
++
++      sdhci_enable_quirks(chip);
++      if (debug_quirks)
++              chip->quirks = debug_quirks;
++
++      chip->num_slots = slots;
++
++      for (i = 0; i < slots; i++) {
++              ret = sdhci_probe_slot(pdev, chip, i);
++              if (ret) {
++                      for (i--; i >= 0; i--)
++                              sdhci_remove_slot(pdev, i);
++                      goto free;
++              }
++      }
++      dev_set_drvdata(&pdev->dev, chip);
++      return 0;
++
++free:
++      kfree(chip);
++err:
++      return ret;
++}
++
++static int __devexit sdhci_remove(struct platform_device *pdev)
++{
++      int i;
++      struct sdhci_chip *chip;
++
++      chip = dev_get_drvdata(&pdev->dev);
++
++      if (chip) {
++              for (i = 0; i < chip->num_slots; i++)
++                      sdhci_remove_slot(pdev, i);
++
++              dev_set_drvdata(&pdev->dev, NULL);
++              kfree(chip);
++      }
++
++      return 0;
++}
++
++static struct dev_pm_ops sdhci_pm_ops = {
++      .suspend = sdhci_suspend,
++      .resume = sdhci_resume,
++};
++
++static struct platform_driver sdhci_driver = {
++      .driver = {
++              .name = DRIVER_NAME,
++              .pm = &sdhci_pm_ops,
++      },
++      .probe = sdhci_probe,
++      .remove = __devexit_p(sdhci_remove),
++};
++
++/*****************************************************************************\
++ *                                                                           *
++ * Driver init/exit                                                          *
++ *                                                                           *
++\*****************************************************************************/
++
++static int __init sdhci_drv_init(void)
++{
++      return platform_driver_register(&sdhci_driver);
++}
++module_init(sdhci_drv_init);
++
++static void __exit sdhci_drv_exit(void)
++{
++      platform_driver_unregister(&sdhci_driver);
++}
++module_exit(sdhci_drv_exit);
++
++MODULE_AUTHOR("Freescale Semiconductor, Inc.");
++MODULE_DESCRIPTION("MXC Secure Digital Host Controller Interface driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:sdhci");
+diff -urN linux.35.old/drivers/mmc/host/sdhci-mxc.h linux.35.new/drivers/mmc/host/sdhci-mxc.h
+--- linux.35.old/drivers/mmc/host/sdhci-mxc.h  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/mmc/host/sdhci-mxc.h  2010-12-20 14:51:10.320319327 +0100
+@@ -0,0 +1,290 @@
++/*
++ *  linux/drivers/mmc/host/sdhci-mxc.h - Secure Digital Host
++ *  Controller Interface driver
++ *
++ *  Copyright (C) 2005-2007 Pierre Ossman, All Rights Reserved.
++ *  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 as published by
++ * the Free Software Foundation; either version 2 of the License, or (at
++ * your option) any later version.
++ */
++
++/*
++ * Controller registers
++ */
++
++#define SDHCI_DMA_ADDRESS     0x00
++
++#define SDHCI_BLOCK_SIZE      0x04
++#define  SDHCI_MAKE_BLKSZ(dma, blksz) (((dma & 0x7) << 13) | (blksz & 0x1FFF))
++
++#define SDHCI_BLOCK_COUNT     0x04
++
++#define SDHCI_ARGUMENT                0x08
++
++#define SDHCI_TRANSFER_MODE   0x0C
++#define  SDHCI_TRNS_DMA               0x00000001
++#define  SDHCI_TRNS_BLK_CNT_EN        0x00000002
++#define  SDHCI_TRNS_ACMD12    0x00000004
++#define  SDHCI_TRNS_READ      0x00000010
++#define  SDHCI_TRNS_MULTI     0x00000020
++#define  SDHCI_TRNS_DPSEL     0x00200000
++#define  SDHCI_TRNS_MASK      0xFFFF0000
++
++#define SDHCI_COMMAND         0x0E
++#define  SDHCI_CMD_RESP_MASK  0x03
++#define  SDHCI_CMD_CRC                0x08
++#define  SDHCI_CMD_INDEX      0x10
++#define  SDHCI_CMD_DATA               0x20
++
++#define  SDHCI_CMD_RESP_NONE  0x00
++#define  SDHCI_CMD_RESP_LONG  0x01
++#define  SDHCI_CMD_RESP_SHORT 0x02
++#define  SDHCI_CMD_RESP_SHORT_BUSY 0x03
++
++#define SDHCI_MAKE_CMD(c, f) ((((c & 0xff) << 8) | (f & 0xff)) << 16)
++
++#define SDHCI_RESPONSE                0x10
++
++#define SDHCI_BUFFER          0x20
++
++#define SDHCI_PRESENT_STATE   0x24
++#define  SDHCI_CMD_INHIBIT    0x00000001
++#define  SDHCI_DATA_INHIBIT   0x00000002
++#define  SDHCI_DATA_ACTIVE    0x00000004
++#define  SDHCI_DOING_WRITE    0x00000100
++#define  SDHCI_DOING_READ     0x00000200
++#define  SDHCI_SPACE_AVAILABLE        0x00000400
++#define  SDHCI_DATA_AVAILABLE 0x00000800
++#define  SDHCI_CARD_PRESENT   0x00010000
++#define  SDHCI_WRITE_PROTECT  0x00080000
++#define  SDHCI_DAT0_IDLE      0x01000000
++#define  SDHCI_CARD_INT_MASK  0x0E000000
++#define  SDHCI_CARD_INT_ID    0x0C000000
++
++#define SDHCI_HOST_CONTROL    0x28
++#define  SDHCI_CTRL_LED               0x00000001
++#define  SDHCI_CTRL_4BITBUS   0x00000002
++#define  SDHCI_CTRL_8BITBUS   0x00000004
++#define  SDHCI_CTRL_HISPD     0x00000004
++#define  SDHCI_CTRL_DMA_MASK  0x18
++#define   SDHCI_CTRL_SDMA     0x00
++#define   SDHCI_CTRL_ADMA1    0x08
++#define   SDHCI_CTRL_ADMA32   0x10
++#define   SDHCI_CTRL_ADMA64   0x18
++#define  SDHCI_CTRL_D3CD      0x00000008
++#define  SDHCI_CTRL_ADMA      0x00000100
++/* wake up control */
++#define  SDHCI_CTRL_WECINS    0x04000000
++
++#define SDHCI_POWER_CONTROL   0x29
++#define  SDHCI_POWER_ON               0x01
++#define  SDHCI_POWER_180      0x0A
++#define  SDHCI_POWER_300      0x0C
++#define  SDHCI_POWER_330      0x0E
++
++#define SDHCI_BLOCK_GAP_CONTROL       0x2A
++
++#define SDHCI_WAKE_UP_CONTROL 0x2B
++
++#define SDHCI_CLOCK_CONTROL   0x2C
++#define  SDHCI_DIVIDER_SHIFT  8
++#define  SDHCI_CLOCK_SD_EN    0x00000008
++#define  SDHCI_CLOCK_PER_EN   0x00000004
++#define  SDHCI_CLOCK_HLK_EN   0x00000002
++#define  SDHCI_CLOCK_IPG_EN   0x00000001
++#define  SDHCI_CLOCK_MASK     0x0000FFFF
++
++#define SDHCI_TIMEOUT_CONTROL 0x2E
++
++#define SDHCI_SOFTWARE_RESET  0x2F
++#define  SDHCI_RESET_ALL      0x01
++#define  SDHCI_RESET_CMD      0x02
++#define  SDHCI_RESET_DATA     0x04
++
++#define SDHCI_INT_STATUS      0x30
++#define SDHCI_INT_ENABLE      0x34
++#define SDHCI_SIGNAL_ENABLE   0x38
++#define  SDHCI_INT_RESPONSE   0x00000001
++#define  SDHCI_INT_DATA_END   0x00000002
++#define  SDHCI_INT_DMA_END    0x00000008
++#define  SDHCI_INT_SPACE_AVAIL        0x00000010
++#define  SDHCI_INT_DATA_AVAIL 0x00000020
++#define  SDHCI_INT_CARD_INSERT        0x00000040
++#define  SDHCI_INT_CARD_REMOVE        0x00000080
++#define  SDHCI_INT_CARD_INT   0x00000100
++#define  SDHCI_INT_ERROR      0x00008000
++#define  SDHCI_INT_TIMEOUT    0x00010000
++#define  SDHCI_INT_CRC                0x00020000
++#define  SDHCI_INT_END_BIT    0x00040000
++#define  SDHCI_INT_INDEX      0x00080000
++#define  SDHCI_INT_DATA_TIMEOUT       0x00100000
++#define  SDHCI_INT_DATA_CRC   0x00200000
++#define  SDHCI_INT_DATA_END_BIT       0x00400000
++#define  SDHCI_INT_BUS_POWER  0x00800000
++#define  SDHCI_INT_ACMD12ERR  0x01000000
++#define  SDHCI_INT_ADMA_ERROR 0x10000000
++
++#define  SDHCI_INT_NORMAL_MASK        0x00007FFF
++#define  SDHCI_INT_ERROR_MASK 0xFFFF8000
++
++#define  SDHCI_INT_CMD_MASK   (SDHCI_INT_RESPONSE | SDHCI_INT_TIMEOUT | \
++              SDHCI_INT_CRC | SDHCI_INT_END_BIT | SDHCI_INT_INDEX)
++#define  SDHCI_INT_DATA_MASK  (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
++              SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
++              SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
++              SDHCI_INT_DATA_END_BIT | SDHCI_INT_ADMA_ERROR)
++#define  SDHCI_INT_DATA_RE_MASK       (SDHCI_INT_DMA_END | \
++              SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL)
++
++#define SDHCI_ACMD12_ERR      0x3C
++
++/* 3E-3F reserved */
++
++#define SDHCI_CAPABILITIES    0x40
++#define  SDHCI_TIMEOUT_CLK_MASK       0x0000003F
++#define  SDHCI_TIMEOUT_CLK_SHIFT 0
++#define  SDHCI_TIMEOUT_CLK_UNIT       0x00000080
++#define  SDHCI_CLOCK_BASE_MASK        0x00003F00
++#define  SDHCI_CLOCK_BASE_SHIFT       8
++#define  SDHCI_MAX_BLOCK_MASK 0x00030000
++#define  SDHCI_MAX_BLOCK_SHIFT  16
++#define  SDHCI_CAN_DO_ADMA2   0x00080000
++#define  SDHCI_CAN_DO_ADMA1   0x00100000
++#define  SDHCI_CAN_DO_HISPD   0x00200000
++#define  SDHCI_CAN_DO_DMA     0x00400000
++#define  SDHCI_CAN_VDD_330    0x01000000
++#define  SDHCI_CAN_VDD_300    0x02000000
++#define  SDHCI_CAN_VDD_180    0x04000000
++#define  SDHCI_CAN_64BIT      0x10000000
++
++/* 44-47 reserved for more caps */
++#define SDHCI_WML             0x44
++#define  SDHCI_WML_4_WORDS    0x00040004
++#define  SDHCI_WML_16_WORDS   0x00100010
++#define  SDHCI_WML_64_WORDS   0x00400040
++#define  SDHCI_WML_128_WORDS  0x00800080
++
++#define SDHCI_MAX_CURRENT     0x48
++
++/* 4C-4F reserved for more max current */
++
++#define SDHCI_SET_ACMD12_ERROR        0x50
++#define SDHCI_SET_INT_ERROR   0x52
++
++#define SDHCI_ADMA_ERROR      0x54
++
++/* 55-57 reserved */
++
++#define SDHCI_ADMA_ADDRESS    0x58
++
++/* 60-FB reserved */
++
++/* ADMA Addr Descriptor Attribute Field */
++enum {
++      FSL_ADMA_DES_ATTR_VALID = 0x01,
++      FSL_ADMA_DES_ATTR_END = 0x02,
++      FSL_ADMA_DES_ATTR_INT = 0x04,
++      FSL_ADMA_DES_ATTR_SET = 0x10,
++      FSL_ADMA_DES_ATTR_TRAN = 0x20,
++      FSL_ADMA_DES_ATTR_LINK = 0x30,
++};
++
++#define SDHCI_HOST_VERSION    0xFC
++#define  SDHCI_VENDOR_VER_MASK        0xFF00
++#define  SDHCI_VENDOR_VER_SHIFT       8
++#define  SDHCI_SPEC_VER_MASK  0x00FF
++#define  SDHCI_SPEC_VER_SHIFT 0
++#define   SDHCI_SPEC_100      0
++#define   SDHCI_SPEC_200      1
++#define   ESDHC_VENDOR_V22    0x12
++
++struct sdhci_chip;
++
++struct adma_desc {
++      unsigned long attr:12,
++              length:20;
++      unsigned long dma_addr;
++};
++
++struct sdhci_host {
++      unsigned int vendor_ver;
++      unsigned int caps;
++      struct sdhci_chip *chip;
++      struct mmc_host *mmc;   /* MMC structure */
++
++#ifdef CONFIG_LEDS_CLASS
++      struct led_classdev led;        /* LED control */
++#endif
++      spinlock_t lock;
++
++      int init_flag;          /* Host has been initialized */
++      int flags;              /* Host attributes */
++#define SDHCI_USE_DMA         (1 << 0)        /* Host is DMA capable */
++#define SDHCI_REQ_USE_DMA     (1 << 1)        /* Use DMA for this req. */
++#define SDHCI_USE_EXTERNAL_DMA        (1 << 2)        /* Use the External DMA */
++#define SDHCI_CD_PRESENT      (1 << 8)        /* CD present */
++#define SDHCI_WP_ENABLED      (1 << 9)        /* Write protect */
++
++      unsigned int max_clk;   /* Max possible freq (MHz) */
++      unsigned int min_clk;   /* Min possible freq (MHz) */
++      unsigned int timeout_clk;       /* Timeout freq (KHz) */
++
++      unsigned int clock;     /* Current clock (MHz) */
++      unsigned short power;   /* Current voltage */
++      struct regulator *regulator_mmc;        /*! Regulator */
++
++      struct mmc_request *mrq;        /* Current request */
++      struct mmc_command *cmd;        /* Current command */
++      struct mmc_data *data;          /* Current data request */
++      unsigned int data_early:1,      /* Data finished before cmd */
++              last_op_dir:1;          /* last CMD was read (for MX35 quirk) */
++
++      unsigned int id;        /* Id for SD/MMC block */
++      int mode;               /* SD/MMC mode */
++      int dma;                /* DMA channel number. */
++      unsigned int dma_size;  /* Number of Bytes in DMA */
++      unsigned int dma_len;   /* Length of the s-g list */
++      unsigned int dma_dir;   /* DMA transfer direction */
++#if 1
++      struct adma_desc *adma_des_table;       /* ADMA descriptor table */
++      dma_addr_t dma_desc;    /* physical address of ADMA descriptor table */
++      size_t dma_desc_size;   /* size of ADMA descriptor table */
++#else
++      unsigned int *adma_des_table;   /* ADMA descriptor table */
++#endif
++      struct scatterlist *cur_sg;     /* We're working on this */
++      int num_sg;             /* Entries left */
++      int offset;             /* Offset into current sg */
++      int remain;             /* Bytes left in current */
++
++      struct resource *res;   /* IO map memory */
++      int irq;                /* Device IRQ */
++      int detect_irq;         /* Card Detect IRQ number. */
++      int sdio_enable;        /* sdio interrupt enable number. */
++      struct clk *clk;        /* Clock id */
++      int clk_enable;         /* clk enable/disable count */
++      int bar;                /* PCI BAR index */
++      unsigned long addr;     /* Bus address */
++      void __iomem *ioaddr;   /* Mapped address */
++
++      struct tasklet_struct card_tasklet;     /* Tasklet structures */
++      struct tasklet_struct finish_tasklet;
++      struct work_struct cd_wq;       /* card detection work queue */
++      /* Platform specific data */
++      struct mxc_sdhci_platform_data *plat_data;
++
++      struct timer_list timer;        /* Timer for timeouts */
++      struct timer_list cd_timer;     /* Timer for cd */
++};
++
++struct sdhci_chip {
++      struct platform_device *pdev;
++
++      unsigned long quirks;
++
++      int num_slots;          /* Slots on controller */
++      struct sdhci_host *hosts[0];    /* Pointers to hosts */
++};
+diff -urN linux.35.old/drivers/mtd/nand/mxc_nand.c linux.35.new/drivers/mtd/nand/mxc_nand.c
+--- linux.35.old/drivers/mtd/nand/mxc_nand.c   2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/mtd/nand/mxc_nand.c   2010-12-03 09:51:55.444346316 +0100
+@@ -853,6 +853,8 @@
+           parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
+       if (nr_parts > 0)
+               add_mtd_partitions(mtd, host->parts, nr_parts);
++      else if (pdata->parts)
++              add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
+       else
+ #endif
+       {
+diff -urN linux.35.old/drivers/mxc/adc/imx_adc.c linux.35.new/drivers/mxc/adc/imx_adc.c
+--- linux.35.old/drivers/mxc/adc/imx_adc.c     1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/mxc/adc/imx_adc.c     2010-12-03 09:51:55.448348573 +0100
+@@ -0,0 +1,1134 @@
++/*
++ * Copyright 2009-2010 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 adc/imx_adc.c
++ * @brief This is the main file of i.MX ADC driver.
++ *
++ * @ingroup IMX_ADC
++ */
++
++/*
++ * Includes
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/platform_device.h>
++#include <linux/poll.h>
++#include <linux/sched.h>
++#include <linux/time.h>
++#include <linux/wait.h>
++#include <linux/slab.h>
++#include <linux/imx_adc.h>
++#include "imx_adc_reg.h"
++
++static int imx_adc_major;
++
++/*!
++ * Number of users waiting in suspendq
++ */
++static int swait;
++
++/*!
++ * To indicate whether any of the adc devices are suspending
++ */
++static int suspend_flag;
++
++/*!
++ * The suspendq is used by blocking application calls
++ */
++static wait_queue_head_t suspendq;
++static wait_queue_head_t tsq;
++
++static bool imx_adc_ready;
++static bool ts_data_ready;
++static int tsi_data = TSI_DATA;
++static unsigned short ts_data_buf[16];
++
++static struct class *imx_adc_class;
++static struct imx_adc_data *adc_data;
++
++static DECLARE_MUTEX(general_convert_mutex);
++static DECLARE_MUTEX(ts_convert_mutex);
++
++unsigned long tsc_base;
++
++int is_imx_adc_ready(void)
++{
++      return imx_adc_ready;
++}
++EXPORT_SYMBOL(is_imx_adc_ready);
++
++void tsc_clk_enable(void)
++{
++      unsigned long reg;
++
++      clk_enable(adc_data->adc_clk);
++
++      reg = __raw_readl(tsc_base + TGCR);
++      reg |= TGCR_IPG_CLK_EN;
++      __raw_writel(reg, tsc_base + TGCR);
++}
++
++void tsc_clk_disable(void)
++{
++      unsigned long reg;
++
++      clk_disable(adc_data->adc_clk);
++
++      reg = __raw_readl(tsc_base + TGCR);
++      reg &= ~TGCR_IPG_CLK_EN;
++      __raw_writel(reg, tsc_base + TGCR);
++}
++
++void tsc_self_reset(void)
++{
++      unsigned long reg;
++
++      reg = __raw_readl(tsc_base + TGCR);
++      reg |= TGCR_TSC_RST;
++      __raw_writel(reg, tsc_base + TGCR);
++
++      while (__raw_readl(tsc_base + TGCR) & TGCR_TSC_RST)
++              continue;
++}
++
++/* Internal reference */
++void tsc_intref_enable(void)
++{
++      unsigned long reg;
++
++      reg = __raw_readl(tsc_base + TGCR);
++      reg |= TGCR_INTREFEN;
++      __raw_writel(reg, tsc_base + TGCR);
++}
++
++/* initialize touchscreen */
++void imx_tsc_init(void)
++{
++      unsigned long reg;
++      int lastitemid;
++
++      /* Level sense */
++      reg = __raw_readl(tsc_base + TCQCR);
++      reg &= ~CQCR_PD_CFG;  /* edge sensitive */
++      reg |= (0xf << CQCR_FIFOWATERMARK_SHIFT);  /* watermark */
++      __raw_writel(reg, tsc_base + TCQCR);
++
++      /* Configure 4-wire */
++      reg = TSC_4WIRE_PRECHARGE;
++      reg |= CC_IGS;
++      __raw_writel(reg, tsc_base + TCC0);
++
++      reg = TSC_4WIRE_TOUCH_DETECT;
++      reg |= 3 << CC_NOS_SHIFT;       /* 4 samples */
++      reg |= 32 << CC_SETTLING_TIME_SHIFT;    /* it's important! */
++      __raw_writel(reg, tsc_base + TCC1);
++
++      reg = TSC_4WIRE_X_MEASUMENT;
++      reg |= 3 << CC_NOS_SHIFT;       /* 4 samples */
++      reg |= 16 << CC_SETTLING_TIME_SHIFT;    /* settling time */
++      __raw_writel(reg, tsc_base + TCC2);
++
++      reg = TSC_4WIRE_Y_MEASUMENT;
++      reg |= 3 << CC_NOS_SHIFT;       /* 4 samples */
++      reg |= 16 << CC_SETTLING_TIME_SHIFT;    /* settling time */
++      __raw_writel(reg, tsc_base + TCC3);
++
++      reg = (TCQ_ITEM_TCC0 << TCQ_ITEM7_SHIFT) |
++            (TCQ_ITEM_TCC0 << TCQ_ITEM6_SHIFT) |
++            (TCQ_ITEM_TCC1 << TCQ_ITEM5_SHIFT) |
++            (TCQ_ITEM_TCC0 << TCQ_ITEM4_SHIFT) |
++            (TCQ_ITEM_TCC3 << TCQ_ITEM3_SHIFT) |
++            (TCQ_ITEM_TCC2 << TCQ_ITEM2_SHIFT) |
++            (TCQ_ITEM_TCC1 << TCQ_ITEM1_SHIFT) |
++            (TCQ_ITEM_TCC0 << TCQ_ITEM0_SHIFT);
++      __raw_writel(reg, tsc_base + TCQ_ITEM_7_0);
++
++      lastitemid = 5;
++      reg = __raw_readl(tsc_base + TCQCR);
++      reg = (reg & ~CQCR_LAST_ITEM_ID_MASK) |
++            (lastitemid << CQCR_LAST_ITEM_ID_SHIFT);
++      __raw_writel(reg, tsc_base + TCQCR);
++
++      /* Config idle for 4-wire */
++      reg = TSC_4WIRE_PRECHARGE;
++      __raw_writel(reg, tsc_base + TICR);
++
++      reg = TSC_4WIRE_TOUCH_DETECT;
++      __raw_writel(reg, tsc_base + TICR);
++
++      /* pen down mask */
++      reg = __raw_readl(tsc_base + TCQCR);
++      reg &= ~CQCR_PD_MSK;
++      __raw_writel(reg, tsc_base + TCQCR);
++      reg = __raw_readl(tsc_base + TCQMR);
++      reg &= ~TCQMR_PD_IRQ_MSK;
++      __raw_writel(reg, tsc_base + TCQMR);
++
++      /* Debounce time = dbtime*8 adc clock cycles */
++      reg = __raw_readl(tsc_base + TGCR);
++      reg &= ~TGCR_PDBTIME_MASK;
++      reg |= TGCR_PDBTIME128 | TGCR_HSYNC_EN;
++      __raw_writel(reg, tsc_base + TGCR);
++
++      /* pen down enable */
++      reg = __raw_readl(tsc_base + TGCR);
++      reg |= TGCR_PDB_EN;
++      __raw_writel(reg, tsc_base + TGCR);
++      reg |= TGCR_PD_EN;
++      __raw_writel(reg, tsc_base + TGCR);
++}
++
++static irqreturn_t imx_adc_interrupt(int irq, void *dev_id)
++{
++      unsigned long reg;
++
++      if (__raw_readl(tsc_base + TGSR) & 0x4) {
++              /* deep sleep wakeup interrupt */
++              /* clear tgsr */
++              __raw_writel(0,  tsc_base + TGSR);
++              /* clear deep sleep wakeup irq */
++              reg = __raw_readl(tsc_base + TGCR);
++              reg &= ~TGCR_SLPC;
++              __raw_writel(reg, tsc_base + TGCR);
++              /* un-mask pen down and pen down irq */
++              reg = __raw_readl(tsc_base + TCQCR);
++              reg &= ~CQCR_PD_MSK;
++              __raw_writel(reg, tsc_base + TCQCR);
++              reg = __raw_readl(tsc_base + TCQMR);
++              reg &= ~TCQMR_PD_IRQ_MSK;
++              __raw_writel(reg, tsc_base + TCQMR);
++      } else if ((__raw_readl(tsc_base + TGSR) & 0x1) &&
++                 (__raw_readl(tsc_base + TCQSR) & 0x1)) {
++
++              /* mask pen down detect irq */
++              reg = __raw_readl(tsc_base + TCQMR);
++              reg |= TCQMR_PD_IRQ_MSK;
++              __raw_writel(reg, tsc_base + TCQMR);
++
++              ts_data_ready = 1;
++              wake_up_interruptible(&tsq);
++      }
++      return IRQ_HANDLED;
++}
++
++enum IMX_ADC_STATUS imx_adc_read_general(unsigned short *result)
++{
++      unsigned long reg;
++      unsigned int data_num = 0;
++
++      reg = __raw_readl(tsc_base + GCQCR);
++      reg |= CQCR_FQS;
++      __raw_writel(reg, tsc_base + GCQCR);
++
++      while (!(__raw_readl(tsc_base + GCQSR) & CQSR_EOQ))
++              continue;
++      reg = __raw_readl(tsc_base + GCQCR);
++      reg &= ~CQCR_FQS;
++      __raw_writel(reg, tsc_base + GCQCR);
++      reg = __raw_readl(tsc_base + GCQSR);
++      reg |= CQSR_EOQ;
++      __raw_writel(reg, tsc_base + GCQSR);
++
++      while (!(__raw_readl(tsc_base + GCQSR) & CQSR_EMPT)) {
++              result[data_num] = __raw_readl(tsc_base + GCQFIFO) >>
++                               GCQFIFO_ADCOUT_SHIFT;
++              data_num++;
++      }
++      return IMX_ADC_SUCCESS;
++}
++
++/*!
++ * This function will get raw (X,Y) value by converting the voltage
++ * @param        touch_sample Pointer to touch sample
++ *
++ * return        This funciton returns 0 if successful.
++ *
++ *
++ */
++enum IMX_ADC_STATUS imx_adc_read_ts(struct t_touch_screen *touch_sample,
++                                  int wait_tsi)
++{
++      unsigned long reg;
++      int data_num = 0;
++      int detect_sample1, detect_sample2;
++
++      memset(ts_data_buf, 0, sizeof ts_data_buf);
++      touch_sample->valid_flag = 1;
++
++      if (wait_tsi) {
++              /* Config idle for 4-wire */
++              reg = TSC_4WIRE_TOUCH_DETECT;
++              __raw_writel(reg, tsc_base + TICR);
++
++              /* Pen interrupt starts new conversion queue */
++              reg = __raw_readl(tsc_base + TCQCR);
++              reg &= ~CQCR_QSM_MASK;
++              reg |= CQCR_QSM_PEN;
++              __raw_writel(reg, tsc_base + TCQCR);
++
++              /* unmask pen down detect irq */
++              reg = __raw_readl(tsc_base + TCQMR);
++              reg &= ~TCQMR_PD_IRQ_MSK;
++              __raw_writel(reg, tsc_base + TCQMR);
++
++              wait_event_interruptible(tsq, ts_data_ready);
++              while (!(__raw_readl(tsc_base + TCQSR) & CQSR_EOQ))
++                      continue;
++
++              /* stop the conversion */
++              reg = __raw_readl(tsc_base + TCQCR);
++              reg &= ~CQCR_QSM_MASK;
++              __raw_writel(reg, tsc_base + TCQCR);
++              reg = CQSR_PD | CQSR_EOQ;
++              __raw_writel(reg, tsc_base + TCQSR);
++
++              /* change configuration for FQS mode */
++              tsi_data = TSI_DATA;
++              reg = (0x1 << CC_YPLLSW_SHIFT) | (0x1 << CC_XNURSW_SHIFT) |
++                    CC_XPULSW;
++              __raw_writel(reg, tsc_base + TICR);
++      } else {
++              /* FQS semaphore */
++              down(&ts_convert_mutex);
++
++              reg = (0x1 << CC_YPLLSW_SHIFT) | (0x1 << CC_XNURSW_SHIFT) |
++                    CC_XPULSW;
++              __raw_writel(reg, tsc_base + TICR);
++
++              /* FQS */
++              reg = __raw_readl(tsc_base + TCQCR);
++              reg &= ~CQCR_QSM_MASK;
++              reg |= CQCR_QSM_FQS;
++              __raw_writel(reg, tsc_base + TCQCR);
++              reg = __raw_readl(tsc_base + TCQCR);
++              reg |= CQCR_FQS;
++              __raw_writel(reg, tsc_base + TCQCR);
++              while (!(__raw_readl(tsc_base + TCQSR) & CQSR_EOQ))
++                      continue;
++
++              /* stop FQS */
++              reg = __raw_readl(tsc_base + TCQCR);
++              reg &= ~CQCR_QSM_MASK;
++              __raw_writel(reg, tsc_base + TCQCR);
++              reg = __raw_readl(tsc_base + TCQCR);
++              reg &= ~CQCR_FQS;
++              __raw_writel(reg, tsc_base + TCQCR);
++
++              /* clear status bit */
++              reg = __raw_readl(tsc_base + TCQSR);
++              reg |= CQSR_EOQ;
++              __raw_writel(reg, tsc_base + TCQSR);
++              tsi_data = FQS_DATA;
++
++              /* Config idle for 4-wire */
++              reg = TSC_4WIRE_PRECHARGE;
++              __raw_writel(reg, tsc_base + TICR);
++
++              reg = TSC_4WIRE_TOUCH_DETECT;
++              __raw_writel(reg, tsc_base + TICR);
++
++      }
++
++      while (!(__raw_readl(tsc_base + TCQSR) & CQSR_EMPT)) {
++              reg = __raw_readl(tsc_base + TCQFIFO);
++              ts_data_buf[data_num] = reg;
++              data_num++;
++      }
++
++      touch_sample->x_position1 = ts_data_buf[4] >> 4;
++      touch_sample->x_position2 = ts_data_buf[5] >> 4;
++      touch_sample->x_position3 = ts_data_buf[6] >> 4;
++      touch_sample->y_position1 = ts_data_buf[9] >> 4;
++      touch_sample->y_position2 = ts_data_buf[10] >> 4;
++      touch_sample->y_position3 = ts_data_buf[11] >> 4;
++
++      detect_sample1 = ts_data_buf[0];
++      detect_sample2 = ts_data_buf[12];
++
++      if ((detect_sample1 > 0x6000) || (detect_sample2 > 0x6000))
++              touch_sample->valid_flag = 0;
++
++      ts_data_ready = 0;
++
++      if (!(touch_sample->x_position1 ||
++            touch_sample->x_position2 || touch_sample->x_position3))
++              touch_sample->contact_resistance = 0;
++      else
++              touch_sample->contact_resistance = 1;
++
++      if (tsi_data == FQS_DATA)
++              up(&ts_convert_mutex);
++      return IMX_ADC_SUCCESS;
++}
++
++/*!
++ * This function performs filtering and rejection of excessive noise prone
++ * sampl.
++ *
++ * @param        ts_curr     Touch screen value
++ *
++ * @return       This function returns 0 on success, -1 otherwise.
++ */
++static int imx_adc_filter(struct t_touch_screen *ts_curr)
++{
++
++      unsigned int ydiff1, ydiff2, ydiff3, xdiff1, xdiff2, xdiff3;
++      unsigned int sample_sumx, sample_sumy;
++      static unsigned int prev_x[FILTLEN], prev_y[FILTLEN];
++      int index = 0;
++      unsigned int y_curr, x_curr;
++      static int filt_count;
++      /* Added a variable filt_type to decide filtering at run-time */
++      unsigned int filt_type = 0;
++
++      /* ignore the data converted when pen down and up */
++      if ((ts_curr->contact_resistance == 0) || tsi_data == TSI_DATA) {
++              ts_curr->x_position = 0;
++              ts_curr->y_position = 0;
++              filt_count = 0;
++              return 0;
++      }
++      /* ignore the data valid */
++      if (ts_curr->valid_flag == 0)
++              return -1;
++
++      ydiff1 = abs(ts_curr->y_position1 - ts_curr->y_position2);
++      ydiff2 = abs(ts_curr->y_position2 - ts_curr->y_position3);
++      ydiff3 = abs(ts_curr->y_position1 - ts_curr->y_position3);
++      if ((ydiff1 > DELTA_Y_MAX) ||
++          (ydiff2 > DELTA_Y_MAX) || (ydiff3 > DELTA_Y_MAX)) {
++              pr_debug("imx_adc_filter: Ret pos 1\n");
++              return -1;
++      }
++
++      xdiff1 = abs(ts_curr->x_position1 - ts_curr->x_position2);
++      xdiff2 = abs(ts_curr->x_position2 - ts_curr->x_position3);
++      xdiff3 = abs(ts_curr->x_position1 - ts_curr->x_position3);
++
++      if ((xdiff1 > DELTA_X_MAX) ||
++          (xdiff2 > DELTA_X_MAX) || (xdiff3 > DELTA_X_MAX)) {
++              pr_debug("imx_adc_filter: Ret pos 2\n");
++              return -1;
++      }
++      /* Compute two closer values among the three available Y readouts */
++
++      if (ydiff1 < ydiff2) {
++              if (ydiff1 < ydiff3) {
++                      /* Sample 0 & 1 closest together */
++                      sample_sumy = ts_curr->y_position1 +
++                          ts_curr->y_position2;
++              } else {
++                      /* Sample 0 & 2 closest together */
++                      sample_sumy = ts_curr->y_position1 +
++                          ts_curr->y_position3;
++              }
++      } else {
++              if (ydiff2 < ydiff3) {
++                      /* Sample 1 & 2 closest together */
++                      sample_sumy = ts_curr->y_position2 +
++                          ts_curr->y_position3;
++              } else {
++                      /* Sample 0 & 2 closest together */
++                      sample_sumy = ts_curr->y_position1 +
++                          ts_curr->y_position3;
++              }
++      }
++
++      /*
++       * Compute two closer values among the three available X
++       * readouts
++       */
++      if (xdiff1 < xdiff2) {
++              if (xdiff1 < xdiff3) {
++                      /* Sample 0 & 1 closest together */
++                      sample_sumx = ts_curr->x_position1 +
++                          ts_curr->x_position2;
++              } else {
++                      /* Sample 0 & 2 closest together */
++                      sample_sumx = ts_curr->x_position1 +
++                          ts_curr->x_position3;
++              }
++      } else {
++              if (xdiff2 < xdiff3) {
++                      /* Sample 1 & 2 closest together */
++                      sample_sumx = ts_curr->x_position2 +
++                          ts_curr->x_position3;
++              } else {
++                      /* Sample 0 & 2 closest together */
++                      sample_sumx = ts_curr->x_position1 +
++                          ts_curr->x_position3;
++              }
++      }
++
++      /*
++       * Wait FILTER_MIN_DELAY number of samples to restart
++       * filtering
++       */
++      if (filt_count < FILTER_MIN_DELAY) {
++              /*
++               * Current output is the average of the two closer
++               * values and no filtering is used
++               */
++              y_curr = (sample_sumy / 2);
++              x_curr = (sample_sumx / 2);
++              ts_curr->y_position = y_curr;
++              ts_curr->x_position = x_curr;
++              filt_count++;
++
++      } else {
++              if (abs(sample_sumx - (prev_x[0] + prev_x[1])) >
++                  (DELTA_X_MAX * 16)) {
++                      pr_debug("imx_adc_filter: : Ret pos 3\n");
++                      return -1;
++              }
++              if (abs(sample_sumy - (prev_y[0] + prev_y[1])) >
++                  (DELTA_Y_MAX * 16)) {
++                      pr_debug("imx_adc_filter: : Ret pos 4\n");
++                      return -1;
++              }
++              sample_sumy /= 2;
++              sample_sumx /= 2;
++              /* Use hard filtering if the sample difference < 10 */
++              if ((abs(sample_sumy - prev_y[0]) > 10) ||
++                  (abs(sample_sumx - prev_x[0]) > 10))
++                      filt_type = 1;
++
++              /*
++               * Current outputs are the average of three previous
++               * values and the present readout
++               */
++              y_curr = sample_sumy;
++              for (index = 0; index < FILTLEN; index++) {
++                      if (filt_type == 0)
++                              y_curr = y_curr + (prev_y[index]);
++                      else
++                              y_curr = y_curr + (prev_y[index] / 3);
++              }
++              if (filt_type == 0)
++                      y_curr = y_curr >> 2;
++              else
++                      y_curr = y_curr >> 1;
++              ts_curr->y_position = y_curr;
++
++              x_curr = sample_sumx;
++              for (index = 0; index < FILTLEN; index++) {
++                      if (filt_type == 0)
++                              x_curr = x_curr + (prev_x[index]);
++                      else
++                              x_curr = x_curr + (prev_x[index] / 3);
++              }
++              if (filt_type == 0)
++                      x_curr = x_curr >> 2;
++              else
++                      x_curr = x_curr >> 1;
++              ts_curr->x_position = x_curr;
++
++      }
++
++      /* Update previous X and Y values */
++      for (index = (FILTLEN - 1); index > 0; index--) {
++              prev_x[index] = prev_x[index - 1];
++              prev_y[index] = prev_y[index - 1];
++      }
++
++      /*
++       * Current output will be the most recent past for the
++       * next sample
++       */
++      prev_y[0] = y_curr;
++      prev_x[0] = x_curr;
++
++      return 0;
++
++}
++
++/*!
++ * This function retrieves the current touch screen (X,Y) coordinates.
++ *
++ * @param        touch_sample Pointer to touch sample.
++ *
++ * @return       This function returns IMX_ADC_SUCCESS if successful.
++ */
++enum IMX_ADC_STATUS imx_adc_get_touch_sample(struct t_touch_screen
++                                           *touch_sample, int wait_tsi)
++{
++      if (imx_adc_read_ts(touch_sample, wait_tsi))
++              return IMX_ADC_ERROR;
++      if (!imx_adc_filter(touch_sample))
++              return IMX_ADC_SUCCESS;
++      else
++              return IMX_ADC_ERROR;
++}
++EXPORT_SYMBOL(imx_adc_get_touch_sample);
++
++void imx_adc_set_hsync(int on)
++{
++      unsigned long reg;
++      if (imx_adc_ready) {
++              reg = __raw_readl(tsc_base + TGCR);
++              if (on)
++                      reg |= TGCR_HSYNC_EN;
++              else
++                      reg &= ~TGCR_HSYNC_EN;
++              __raw_writel(reg, tsc_base + TGCR);
++      }
++}
++EXPORT_SYMBOL(imx_adc_set_hsync);
++
++/*!
++ * This is the suspend of power management for the i.MX ADC API.
++ * It supports SAVE and POWER_DOWN state.
++ *
++ * @param        pdev           the device
++ * @param        state          the state
++ *
++ * @return       This function returns 0 if successful.
++ */
++static int imx_adc_suspend(struct platform_device *pdev, pm_message_t state)
++{
++      unsigned long reg;
++
++      /* Config idle for 4-wire */
++      reg = TSC_4WIRE_PRECHARGE;
++      __raw_writel(reg, tsc_base + TICR);
++
++      reg = TSC_4WIRE_TOUCH_DETECT;
++      __raw_writel(reg, tsc_base + TICR);
++
++      /* enable deep sleep wake up */
++      reg = __raw_readl(tsc_base + TGCR);
++      reg |= TGCR_SLPC;
++      __raw_writel(reg, tsc_base + TGCR);
++
++      /* mask pen down and pen down irq */
++      reg = __raw_readl(tsc_base + TCQCR);
++      reg |= CQCR_PD_MSK;
++      __raw_writel(reg, tsc_base + TCQCR);
++      reg = __raw_readl(tsc_base + TCQMR);
++      reg |= TCQMR_PD_IRQ_MSK;
++      __raw_writel(reg, tsc_base + TCQMR);
++
++      /* Set power mode to off */
++      reg = __raw_readl(tsc_base + TGCR) & ~TGCR_POWER_MASK;
++      reg |= TGCR_POWER_OFF;
++      __raw_writel(reg, tsc_base + TGCR);
++
++      if (device_may_wakeup(&pdev->dev)) {
++              enable_irq_wake(adc_data->irq);
++      } else {
++              suspend_flag = 1;
++              tsc_clk_disable();
++      }
++      return 0;
++};
++
++/*!
++ * This is the resume of power management for the i.MX adc API.
++ * It supports RESTORE state.
++ *
++ * @param        pdev           the device
++ *
++ * @return       This function returns 0 if successful.
++ */
++static int imx_adc_resume(struct platform_device *pdev)
++{
++      unsigned long reg;
++
++      if (device_may_wakeup(&pdev->dev)) {
++              disable_irq_wake(adc_data->irq);
++      } else {
++              suspend_flag = 0;
++              tsc_clk_enable();
++              while (swait > 0) {
++                      swait--;
++                      wake_up_interruptible(&suspendq);
++              }
++      }
++
++      /* recover power mode */
++      reg = __raw_readl(tsc_base + TGCR) & ~TGCR_POWER_MASK;
++      reg |= TGCR_POWER_SAVE;
++      __raw_writel(reg, tsc_base + TGCR);
++
++      return 0;
++}
++
++/*!
++ * This function implements the open method on an i.MX ADC device.
++ *
++ * @param        inode       pointer on the node
++ * @param        file        pointer on the file
++ * @return       This function returns 0.
++ */
++static int imx_adc_open(struct inode *inode, struct file *file)
++{
++      while (suspend_flag) {
++              swait++;
++              /* Block if the device is suspended */
++              if (wait_event_interruptible(suspendq, !suspend_flag))
++                      return -ERESTARTSYS;
++      }
++      pr_debug("imx_adc : imx_adc_open()\n");
++      return 0;
++}
++
++/*!
++ * This function implements the release method on an i.MX ADC device.
++ *
++ * @param        inode       pointer on the node
++ * @param        file        pointer on the file
++ * @return       This function returns 0.
++ */
++static int imx_adc_free(struct inode *inode, struct file *file)
++{
++      pr_debug("imx_adc : imx_adc_free()\n");
++      return 0;
++}
++
++/*!
++ * This function initializes all ADC registers with default values. This
++ * function also registers the interrupt events.
++ *
++ * @return       This function returns IMX_ADC_SUCCESS if successful.
++ */
++int imx_adc_init(void)
++{
++      unsigned long reg;
++
++      pr_debug("imx_adc_init()\n");
++
++      if (suspend_flag)
++              return -EBUSY;
++
++      tsc_clk_enable();
++
++      /* Reset */
++      tsc_self_reset();
++
++      /* Internal reference */
++      tsc_intref_enable();
++
++      /* Set power mode */
++      reg = __raw_readl(tsc_base + TGCR) & ~TGCR_POWER_MASK;
++      reg |= TGCR_POWER_SAVE;
++      __raw_writel(reg, tsc_base + TGCR);
++
++      imx_tsc_init();
++
++      return IMX_ADC_SUCCESS;
++}
++EXPORT_SYMBOL(imx_adc_init);
++
++/*!
++ * This function disables the ADC, de-registers the interrupt events.
++ *
++ * @return       This function returns IMX_ADC_SUCCESS if successful.
++ */
++enum IMX_ADC_STATUS imx_adc_deinit(void)
++{
++      pr_debug("imx_adc_deinit()\n");
++
++      return IMX_ADC_SUCCESS;
++}
++EXPORT_SYMBOL(imx_adc_deinit);
++
++/*!
++ * This function triggers a conversion and returns one sampling result of one
++ * channel.
++ *
++ * @param        channel   The channel to be sampled
++ * @param        result    The pointer to the conversion result. The memory
++ *                         should be allocated by the caller of this function.
++ *
++ * @return       This function returns IMX_ADC_SUCCESS if successful.
++ */
++enum IMX_ADC_STATUS imx_adc_convert(enum t_channel channel,
++                                  unsigned short *result)
++{
++      unsigned long reg;
++      int lastitemid;
++      struct t_touch_screen touch_sample;
++
++      switch (channel) {
++
++      case TS_X_POS:
++              imx_adc_get_touch_sample(&touch_sample, 0);
++              result[0] = touch_sample.x_position;
++
++              /* if no pen down ,recover the register configuration */
++              if (touch_sample.contact_resistance == 0) {
++                      reg = __raw_readl(tsc_base + TCQCR);
++                      reg &= ~CQCR_QSM_MASK;
++                      reg |= CQCR_QSM_PEN;
++                      __raw_writel(reg, tsc_base + TCQCR);
++
++                      reg = __raw_readl(tsc_base + TCQMR);
++                      reg &= ~TCQMR_PD_IRQ_MSK;
++                      __raw_writel(reg, tsc_base + TCQMR);
++              }
++              break;
++
++      case TS_Y_POS:
++              imx_adc_get_touch_sample(&touch_sample, 0);
++              result[1] = touch_sample.y_position;
++
++              /* if no pen down ,recover the register configuration */
++              if (touch_sample.contact_resistance == 0) {
++                      reg = __raw_readl(tsc_base + TCQCR);
++                      reg &= ~CQCR_QSM_MASK;
++                      reg |= CQCR_QSM_PEN;
++                      __raw_writel(reg, tsc_base + TCQCR);
++
++                      reg = __raw_readl(tsc_base + TCQMR);
++                      reg &= ~TCQMR_PD_IRQ_MSK;
++                      __raw_writel(reg, tsc_base + TCQMR);
++              }
++              break;
++
++      case GER_PURPOSE_ADC0:
++              down(&general_convert_mutex);
++
++              lastitemid = 0;
++              reg = (0xf << CQCR_FIFOWATERMARK_SHIFT) |
++                    (lastitemid << CQCR_LAST_ITEM_ID_SHIFT) | CQCR_QSM_FQS;
++              __raw_writel(reg, tsc_base + GCQCR);
++
++              reg = TSC_GENERAL_ADC_GCC0;
++              reg |= (3 << CC_NOS_SHIFT) | (16 << CC_SETTLING_TIME_SHIFT);
++              __raw_writel(reg, tsc_base + GCC0);
++
++              imx_adc_read_general(result);
++              up(&general_convert_mutex);
++              break;
++
++      case GER_PURPOSE_ADC1:
++              down(&general_convert_mutex);
++
++              lastitemid = 0;
++              reg = (0xf << CQCR_FIFOWATERMARK_SHIFT) |
++                    (lastitemid << CQCR_LAST_ITEM_ID_SHIFT) | CQCR_QSM_FQS;
++              __raw_writel(reg, tsc_base + GCQCR);
++
++              reg = TSC_GENERAL_ADC_GCC1;
++              reg |= (3 << CC_NOS_SHIFT) | (16 << CC_SETTLING_TIME_SHIFT);
++              __raw_writel(reg, tsc_base + GCC0);
++
++              imx_adc_read_general(result);
++              up(&general_convert_mutex);
++              break;
++
++      case GER_PURPOSE_ADC2:
++              down(&general_convert_mutex);
++
++              lastitemid = 0;
++              reg = (0xf << CQCR_FIFOWATERMARK_SHIFT) |
++                    (lastitemid << CQCR_LAST_ITEM_ID_SHIFT) | CQCR_QSM_FQS;
++              __raw_writel(reg, tsc_base + GCQCR);
++
++              reg = TSC_GENERAL_ADC_GCC2;
++              reg |= (3 << CC_NOS_SHIFT) | (16 << CC_SETTLING_TIME_SHIFT);
++              __raw_writel(reg, tsc_base + GCC0);
++
++              imx_adc_read_general(result);
++              up(&general_convert_mutex);
++              break;
++
++      case GER_PURPOSE_MULTICHNNEL:
++              down(&general_convert_mutex);
++
++              reg = TSC_GENERAL_ADC_GCC0;
++              reg |= (3 << CC_NOS_SHIFT) | (16 << CC_SETTLING_TIME_SHIFT);
++              __raw_writel(reg, tsc_base + GCC0);
++
++              reg = TSC_GENERAL_ADC_GCC1;
++              reg |= (3 << CC_NOS_SHIFT) | (16 << CC_SETTLING_TIME_SHIFT);
++              __raw_writel(reg, tsc_base + GCC1);
++
++              reg = TSC_GENERAL_ADC_GCC2;
++              reg |= (3 << CC_NOS_SHIFT) | (16 << CC_SETTLING_TIME_SHIFT);
++              __raw_writel(reg, tsc_base + GCC2);
++
++              reg = (GCQ_ITEM_GCC2 << GCQ_ITEM2_SHIFT) |
++                    (GCQ_ITEM_GCC1 << GCQ_ITEM1_SHIFT) |
++                    (GCQ_ITEM_GCC0 << GCQ_ITEM0_SHIFT);
++              __raw_writel(reg, tsc_base + GCQ_ITEM_7_0);
++
++              lastitemid = 2;
++              reg = (0xf << CQCR_FIFOWATERMARK_SHIFT) |
++                    (lastitemid << CQCR_LAST_ITEM_ID_SHIFT) | CQCR_QSM_FQS;
++              __raw_writel(reg, tsc_base + GCQCR);
++
++              imx_adc_read_general(result);
++              up(&general_convert_mutex);
++              break;
++      default:
++              pr_debug("%s: bad channel number\n", __func__);
++              return IMX_ADC_ERROR;
++      }
++
++      return IMX_ADC_SUCCESS;
++}
++EXPORT_SYMBOL(imx_adc_convert);
++
++/*!
++ * This function triggers a conversion and returns sampling results of each
++ * specified channel.
++ *
++ * @param        channels  This input parameter is bitmap to specify channels
++ *                         to be sampled.
++ * @param        result    The pointer to array to store sampling results.
++ *                         The memory should be allocated by the caller of this
++ *                         function.
++ *
++ * @return       This function returns IMX_ADC_SUCCESS if successful.
++ */
++enum IMX_ADC_STATUS imx_adc_convert_multichnnel(enum t_channel channels,
++                                              unsigned short *result)
++{
++      imx_adc_convert(GER_PURPOSE_MULTICHNNEL, result);
++      return IMX_ADC_SUCCESS;
++}
++EXPORT_SYMBOL(imx_adc_convert_multichnnel);
++
++/*!
++ * This function implements IOCTL controls on an i.MX ADC device.
++ *
++ * @param        inode       pointer on the node
++ * @param        file        pointer on the file
++ * @param        cmd         the command
++ * @param        arg         the parameter
++ * @return       This function returns 0 if successful.
++ */
++static int imx_adc_ioctl(struct inode *inode, struct file *file,
++                       unsigned int cmd, unsigned long arg)
++{
++      struct t_adc_convert_param *convert_param;
++
++      if ((_IOC_TYPE(cmd) != 'p') && (_IOC_TYPE(cmd) != 'D'))
++              return -ENOTTY;
++
++      while (suspend_flag) {
++              swait++;
++              /* Block if the device is suspended */
++              if (wait_event_interruptible(suspendq, !suspend_flag))
++                      return -ERESTARTSYS;
++      }
++
++      switch (cmd) {
++      case IMX_ADC_INIT:
++              pr_debug("init adc\n");
++              CHECK_ERROR(imx_adc_init());
++              break;
++
++      case IMX_ADC_DEINIT:
++              pr_debug("deinit adc\n");
++              CHECK_ERROR(imx_adc_deinit());
++              break;
++
++      case IMX_ADC_CONVERT:
++              convert_param = kmalloc(sizeof(*convert_param), GFP_KERNEL);
++              if (convert_param == NULL)
++                      return -ENOMEM;
++              if (copy_from_user(convert_param,
++                                 (struct t_adc_convert_param *)arg,
++                                 sizeof(*convert_param))) {
++                      kfree(convert_param);
++                      return -EFAULT;
++              }
++              CHECK_ERROR_KFREE(imx_adc_convert(convert_param->channel,
++                                                convert_param->result),
++                                (kfree(convert_param)));
++
++              if (copy_to_user((struct t_adc_convert_param *)arg,
++                               convert_param, sizeof(*convert_param))) {
++                      kfree(convert_param);
++                      return -EFAULT;
++              }
++              kfree(convert_param);
++              break;
++
++      case IMX_ADC_CONVERT_MULTICHANNEL:
++              convert_param = kmalloc(sizeof(*convert_param), GFP_KERNEL);
++              if (convert_param == NULL)
++                      return -ENOMEM;
++              if (copy_from_user(convert_param,
++                                 (struct t_adc_convert_param *)arg,
++                                 sizeof(*convert_param))) {
++                      kfree(convert_param);
++                      return -EFAULT;
++              }
++              CHECK_ERROR_KFREE(imx_adc_convert_multichnnel
++                                (convert_param->channel,
++                                 convert_param->result),
++                                (kfree(convert_param)));
++
++              if (copy_to_user((struct t_adc_convert_param *)arg,
++                               convert_param, sizeof(*convert_param))) {
++                      kfree(convert_param);
++                      return -EFAULT;
++              }
++              kfree(convert_param);
++              break;
++
++      default:
++              pr_debug("imx_adc_ioctl: unsupported ioctl command 0x%x\n",
++                       cmd);
++              return -EINVAL;
++      }
++      return 0;
++}
++
++static struct file_operations imx_adc_fops = {
++      .owner = THIS_MODULE,
++      .ioctl = imx_adc_ioctl,
++      .open = imx_adc_open,
++      .release = imx_adc_free,
++};
++
++static int imx_adc_module_probe(struct platform_device *pdev)
++{
++      int ret = 0;
++      int retval;
++      struct device *temp_class;
++      struct resource *res;
++      void __iomem *base;
++
++      /* ioremap the base address */
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (res == NULL) {
++              dev_err(&pdev->dev, "No TSC base address provided\n");
++              goto err_out0;
++      }
++      base = ioremap(res->start, res->end - res->start);
++      if (base == NULL) {
++              dev_err(&pdev->dev, "failed to rebase TSC base address\n");
++              goto err_out0;
++      }
++      tsc_base = (unsigned long)base;
++
++      /* create the chrdev */
++      imx_adc_major = register_chrdev(0, "imx_adc", &imx_adc_fops);
++
++      if (imx_adc_major < 0) {
++              dev_err(&pdev->dev, "Unable to get a major for imx_adc\n");
++              return imx_adc_major;
++      }
++      init_waitqueue_head(&suspendq);
++      init_waitqueue_head(&tsq);
++
++      imx_adc_class = class_create(THIS_MODULE, "imx_adc");
++      if (IS_ERR(imx_adc_class)) {
++              dev_err(&pdev->dev, "Error creating imx_adc class.\n");
++              ret = PTR_ERR(imx_adc_class);
++              goto err_out1;
++      }
++
++      temp_class = device_create(imx_adc_class, NULL,
++                                 MKDEV(imx_adc_major, 0), NULL, "imx_adc");
++      if (IS_ERR(temp_class)) {
++              dev_err(&pdev->dev, "Error creating imx_adc class device.\n");
++              ret = PTR_ERR(temp_class);
++              goto err_out2;
++      }
++
++      adc_data = kmalloc(sizeof(struct imx_adc_data), GFP_KERNEL);
++      if (adc_data == NULL)
++              return -ENOMEM;
++      adc_data->irq = platform_get_irq(pdev, 0);
++      retval = request_irq(adc_data->irq, imx_adc_interrupt,
++                           0, MOD_NAME, MOD_NAME);
++      if (retval) {
++              return retval;
++      }
++      adc_data->adc_clk = clk_get(&pdev->dev, "tsc_clk");
++
++      ret = imx_adc_init();
++
++      if (ret != IMX_ADC_SUCCESS) {
++              dev_err(&pdev->dev, "Error in imx_adc_init.\n");
++              goto err_out4;
++      }
++      imx_adc_ready = 1;
++
++      /* By default, devices should wakeup if they can */
++      /* So TouchScreen is set as "should wakeup" as it can */
++      device_init_wakeup(&pdev->dev, 1);
++
++      pr_info("i.MX ADC at 0x%x irq %d\n", (unsigned int)res->start,
++              adc_data->irq);
++      return ret;
++
++err_out4:
++      device_destroy(imx_adc_class, MKDEV(imx_adc_major, 0));
++err_out2:
++      class_destroy(imx_adc_class);
++err_out1:
++      unregister_chrdev(imx_adc_major, "imx_adc");
++err_out0:
++      return ret;
++}
++
++static int imx_adc_module_remove(struct platform_device *pdev)
++{
++      imx_adc_ready = 0;
++      imx_adc_deinit();
++      device_destroy(imx_adc_class, MKDEV(imx_adc_major, 0));
++      class_destroy(imx_adc_class);
++      unregister_chrdev(imx_adc_major, "imx_adc");
++      free_irq(adc_data->irq, MOD_NAME);
++      kfree(adc_data);
++      pr_debug("i.MX ADC successfully removed\n");
++      return 0;
++}
++
++static struct platform_driver imx_adc_driver = {
++      .driver = {
++                 .name = "imx_adc",
++                 },
++      .suspend = imx_adc_suspend,
++      .resume = imx_adc_resume,
++      .probe = imx_adc_module_probe,
++      .remove = imx_adc_module_remove,
++};
++
++/*
++ * Initialization and Exit
++ */
++static int __init imx_adc_module_init(void)
++{
++      printk(KERN_INFO "i.MX ADC driver loading...\n");
++      return platform_driver_register(&imx_adc_driver);
++}
++
++static void __exit imx_adc_module_exit(void)
++{
++      platform_driver_unregister(&imx_adc_driver);
++      printk(KERN_INFO "i.MX ADC driver successfully unloaded\n");
++}
++
++/*
++ * Module entry points
++ */
++
++module_init(imx_adc_module_init);
++module_exit(imx_adc_module_exit);
++
++MODULE_DESCRIPTION("i.MX ADC device driver");
++MODULE_AUTHOR("Freescale Semiconductor, Inc.");
++MODULE_LICENSE("GPL");
+diff -urN linux.35.old/drivers/mxc/adc/imx_adc_reg.h linux.35.new/drivers/mxc/adc/imx_adc_reg.h
+--- linux.35.old/drivers/mxc/adc/imx_adc_reg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/mxc/adc/imx_adc_reg.h 2010-12-03 09:51:55.452350145 +0100
+@@ -0,0 +1,242 @@
++/*
++ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
++ */
++
++/*
++ * The code contained herein is licensed under the GNU Lesser General
++ * Public License.  You may obtain a copy of the GNU Lesser General
++ * Public License Version 2.1 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/lgpl-license.html
++ * http://www.gnu.org/copyleft/lgpl.html
++ */
++
++#ifndef __IMX_ADC_H__
++#define __IMX_ADC_H__
++
++/* 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_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 TCQ_INT               (1 << 0)
++#define GCQ_INT               (1 << 1)
++#define SLP_INT               (1 << 2)
++#define TCQ_DMA               (1 << 16)
++#define 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 TCQMR_PD_IRQ_MSK      (1 << 0)
++#define TCQMR_EOQ_IRQ_MSK     (1 << 1)
++#define TCQMR_FOR_IRQ_MSK     (1 << 4)
++#define TCQMR_FUR_IRQ_MSK     (1 << 5)
++#define TCQMR_FER_IRQ_MSK     (1 << 6)
++#define TCQMR_PD_DMA_MSK      (1 << 16)
++#define TCQMR_EOQ_DMA_MSK     (1 << 17)
++#define TCQMR_FOR_DMA_MSK     (1 << 20)
++#define TCQMR_FUR_DMA_MSK     (1 << 21)
++#define TCQMR_FER_DMA_MSK     (1 << 22)
++#define TCQMR_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_ITEM7_SHIFT       28
++#define TCQ_ITEM6_SHIFT       24
++#define TCQ_ITEM5_SHIFT       20
++#define TCQ_ITEM4_SHIFT       16
++#define TCQ_ITEM3_SHIFT       12
++#define TCQ_ITEM2_SHIFT       8
++#define TCQ_ITEM1_SHIFT       4
++#define TCQ_ITEM0_SHIFT       0
++
++#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_MASK        (0x3 << CC_YPLLSW_SHIFT)
++#define CC_YNLRSW             (1 << 14)
++#define CC_WIPERSW            (1 << 15)
++#define CC_NOS_SHIFT          16
++#define CC_YPLLSW_HIGH        (0x0 << CC_NOS_SHIFT)
++#define CC_YPLLSW_OFF         (0x1 << CC_NOS_SHIFT)
++#define CC_YPLLSW_LOW         (0x3 << CC_NOS_SHIFT
++#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_MEASUMENT  0x1c90
++#define TSC_4WIRE_Y_MEASUMENT  0x4604
++
++#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 GCQ_ITEM7_SHIFT        28
++#define GCQ_ITEM6_SHIFT        24
++#define GCQ_ITEM5_SHIFT        20
++#define GCQ_ITEM4_SHIFT        16
++#define GCQ_ITEM3_SHIFT        12
++#define GCQ_ITEM2_SHIFT        8
++#define GCQ_ITEM1_SHIFT        4
++#define GCQ_ITEM0_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
++
++#endif                                /* __IMX_ADC_H__ */
+diff -urN linux.35.old/drivers/mxc/adc/Kconfig linux.35.new/drivers/mxc/adc/Kconfig
+--- linux.35.old/drivers/mxc/adc/Kconfig       1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/mxc/adc/Kconfig       2010-12-03 09:51:55.452350145 +0100
+@@ -0,0 +1,14 @@
++#
++# i.MX ADC devices
++#
++
++menu "i.MX ADC support"
++
++config IMX_ADC
++      tristate "i.MX ADC"
++      depends on ARCH_MXC
++      default n
++      help
++         This selects the Freescale i.MX on-chip ADC driver.
++
++endmenu
+diff -urN linux.35.old/drivers/mxc/adc/Makefile linux.35.new/drivers/mxc/adc/Makefile
+--- linux.35.old/drivers/mxc/adc/Makefile      1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/mxc/adc/Makefile      2010-12-03 09:51:55.452350145 +0100
+@@ -0,0 +1,4 @@
++#
++# Makefile for i.MX adc devices.
++#
++obj-$(CONFIG_IMX_ADC)         += imx_adc.o
+diff -urN linux.35.old/drivers/mxc/Kconfig linux.35.new/drivers/mxc/Kconfig
+--- linux.35.old/drivers/mxc/Kconfig   1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/mxc/Kconfig   2010-12-03 09:51:55.452350145 +0100
+@@ -0,0 +1,11 @@
++# drivers/video/mxc/Kconfig
++
++if ARCH_MXC
++
++menu "MXC support drivers"
++
++source "drivers/mxc/adc/Kconfig"
++
++endmenu
++
++endif
+diff -urN linux.35.old/drivers/mxc/Makefile linux.35.new/drivers/mxc/Makefile
+--- linux.35.old/drivers/mxc/Makefile  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/mxc/Makefile  2010-12-03 09:51:55.452350145 +0100
+@@ -0,0 +1 @@
++obj-y                  += adc/
+diff -urN linux.35.old/drivers/net/can/flexcan.c linux.35.new/drivers/net/can/flexcan.c
+--- linux.35.old/drivers/net/can/flexcan.c     1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/net/can/flexcan.c     2010-12-03 09:51:55.456347637 +0100
+@@ -0,0 +1,1030 @@
++/*
++ * flexcan.c - FLEXCAN CAN controller driver
++ *
++ * Copyright (c) 2005-2006 Varma Electronics Oy
++ * Copyright (c) 2009 Sascha Hauer, Pengutronix
++ * Copyright (c) 2010 Marc Kleine-Budde, Pengutronix
++ *
++ * Based on code originally by Andrey Volkov <avolkov@varma-el.com>
++ *
++ * LICENCE:
++ * 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 version 2.
++ *
++ * 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.
++ *
++ */
++
++#include <linux/netdevice.h>
++#include <linux/can.h>
++#include <linux/can/dev.h>
++#include <linux/can/error.h>
++#include <linux/can/platform/flexcan.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/if_arp.h>
++#include <linux/if_ether.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++
++#include <mach/clock.h>
++
++#define DRV_NAME                      "flexcan"
++
++/* 8 for RX fifo and 2 error handling */
++#define FLEXCAN_NAPI_WEIGHT           (8 + 2)
++
++/* FLEXCAN module configuration register (CANMCR) bits */
++#define FLEXCAN_MCR_MDIS              BIT(31)
++#define FLEXCAN_MCR_FRZ                       BIT(30)
++#define FLEXCAN_MCR_FEN                       BIT(29)
++#define FLEXCAN_MCR_HALT              BIT(28)
++#define FLEXCAN_MCR_NOT_RDY           BIT(27)
++#define FLEXCAN_MCR_WAK_MSK           BIT(26)
++#define FLEXCAN_MCR_SOFTRST           BIT(25)
++#define FLEXCAN_MCR_FRZ_ACK           BIT(24)
++#define FLEXCAN_MCR_SUPV              BIT(23)
++#define FLEXCAN_MCR_SLF_WAK           BIT(22)
++#define FLEXCAN_MCR_WRN_EN            BIT(21)
++#define FLEXCAN_MCR_LPM_ACK           BIT(20)
++#define FLEXCAN_MCR_WAK_SRC           BIT(19)
++#define FLEXCAN_MCR_DOZE              BIT(18)
++#define FLEXCAN_MCR_SRX_DIS           BIT(17)
++#define FLEXCAN_MCR_BCC                       BIT(16)
++#define FLEXCAN_MCR_LPRIO_EN          BIT(13)
++#define FLEXCAN_MCR_AEN                       BIT(12)
++#define FLEXCAN_MCR_MAXMB(x)          ((x) & 0xf)
++#define FLEXCAN_MCR_IDAM_A            (0 << 8)
++#define FLEXCAN_MCR_IDAM_B            (1 << 8)
++#define FLEXCAN_MCR_IDAM_C            (2 << 8)
++#define FLEXCAN_MCR_IDAM_D            (3 << 8)
++
++/* FLEXCAN control register (CANCTRL) bits */
++#define FLEXCAN_CTRL_PRESDIV(x)               (((x) & 0xff) << 24)
++#define FLEXCAN_CTRL_RJW(x)           (((x) & 0x03) << 22)
++#define FLEXCAN_CTRL_PSEG1(x)         (((x) & 0x07) << 19)
++#define FLEXCAN_CTRL_PSEG2(x)         (((x) & 0x07) << 16)
++#define FLEXCAN_CTRL_BOFF_MSK         BIT(15)
++#define FLEXCAN_CTRL_ERR_MSK          BIT(14)
++#define FLEXCAN_CTRL_CLK_SRC          BIT(13)
++#define FLEXCAN_CTRL_LPB              BIT(12)
++#define FLEXCAN_CTRL_TWRN_MSK         BIT(11)
++#define FLEXCAN_CTRL_RWRN_MSK         BIT(10)
++#define FLEXCAN_CTRL_SMP              BIT(7)
++#define FLEXCAN_CTRL_BOFF_REC         BIT(6)
++#define FLEXCAN_CTRL_TSYN             BIT(5)
++#define FLEXCAN_CTRL_LBUF             BIT(4)
++#define FLEXCAN_CTRL_LOM              BIT(3)
++#define FLEXCAN_CTRL_PROPSEG(x)               ((x) & 0x07)
++#define FLEXCAN_CTRL_ERR_BUS          (FLEXCAN_CTRL_ERR_MSK)
++#define FLEXCAN_CTRL_ERR_STATE \
++      (FLEXCAN_CTRL_TWRN_MSK | FLEXCAN_CTRL_RWRN_MSK | \
++       FLEXCAN_CTRL_BOFF_MSK)
++#define FLEXCAN_CTRL_ERR_ALL \
++      (FLEXCAN_CTRL_ERR_BUS | FLEXCAN_CTRL_ERR_STATE)
++
++/* FLEXCAN error and status register (ESR) bits */
++#define FLEXCAN_ESR_TWRN_INT          BIT(17)
++#define FLEXCAN_ESR_RWRN_INT          BIT(16)
++#define FLEXCAN_ESR_BIT1_ERR          BIT(15)
++#define FLEXCAN_ESR_BIT0_ERR          BIT(14)
++#define FLEXCAN_ESR_ACK_ERR           BIT(13)
++#define FLEXCAN_ESR_CRC_ERR           BIT(12)
++#define FLEXCAN_ESR_FRM_ERR           BIT(11)
++#define FLEXCAN_ESR_STF_ERR           BIT(10)
++#define FLEXCAN_ESR_TX_WRN            BIT(9)
++#define FLEXCAN_ESR_RX_WRN            BIT(8)
++#define FLEXCAN_ESR_IDLE              BIT(7)
++#define FLEXCAN_ESR_TXRX              BIT(6)
++#define FLEXCAN_EST_FLT_CONF_SHIFT    (4)
++#define FLEXCAN_ESR_FLT_CONF_MASK     (0x3 << FLEXCAN_EST_FLT_CONF_SHIFT)
++#define FLEXCAN_ESR_FLT_CONF_ACTIVE   (0x0 << FLEXCAN_EST_FLT_CONF_SHIFT)
++#define FLEXCAN_ESR_FLT_CONF_PASSIVE  (0x1 << FLEXCAN_EST_FLT_CONF_SHIFT)
++#define FLEXCAN_ESR_BOFF_INT          BIT(2)
++#define FLEXCAN_ESR_ERR_INT           BIT(1)
++#define FLEXCAN_ESR_WAK_INT           BIT(0)
++#define FLEXCAN_ESR_ERR_BUS \
++      (FLEXCAN_ESR_BIT1_ERR | FLEXCAN_ESR_BIT0_ERR | \
++       FLEXCAN_ESR_ACK_ERR | FLEXCAN_ESR_CRC_ERR | \
++       FLEXCAN_ESR_FRM_ERR | FLEXCAN_ESR_STF_ERR)
++#define FLEXCAN_ESR_ERR_STATE \
++      (FLEXCAN_ESR_TWRN_INT | FLEXCAN_ESR_RWRN_INT | FLEXCAN_ESR_BOFF_INT)
++#define FLEXCAN_ESR_ERR_ALL \
++      (FLEXCAN_ESR_ERR_BUS | FLEXCAN_ESR_ERR_STATE)
++
++/* FLEXCAN interrupt flag register (IFLAG) bits */
++#define FLEXCAN_TX_BUF_ID             8
++#define FLEXCAN_IFLAG_BUF(x)          BIT(x)
++#define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW        BIT(7)
++#define FLEXCAN_IFLAG_RX_FIFO_WARN    BIT(6)
++#define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE       BIT(5)
++#define FLEXCAN_IFLAG_DEFAULT \
++      (FLEXCAN_IFLAG_RX_FIFO_OVERFLOW | FLEXCAN_IFLAG_RX_FIFO_AVAILABLE | \
++       FLEXCAN_IFLAG_BUF(FLEXCAN_TX_BUF_ID))
++
++/* FLEXCAN message buffers */
++#define FLEXCAN_MB_CNT_CODE(x)                (((x) & 0xf) << 24)
++#define FLEXCAN_MB_CNT_SRR            BIT(22)
++#define FLEXCAN_MB_CNT_IDE            BIT(21)
++#define FLEXCAN_MB_CNT_RTR            BIT(20)
++#define FLEXCAN_MB_CNT_LENGTH(x)      (((x) & 0xf) << 16)
++#define FLEXCAN_MB_CNT_TIMESTAMP(x)   ((x) & 0xffff)
++
++#define FLEXCAN_MB_CODE_MASK          (0xf0ffffff)
++
++/* Structure of the message buffer */
++struct flexcan_mb {
++      u32 can_ctrl;
++      u32 can_id;
++      u32 data[2];
++};
++
++/* Structure of the hardware registers */
++struct flexcan_regs {
++      u32 mcr;                /* 0x00 */
++      u32 ctrl;               /* 0x04 */
++      u32 timer;              /* 0x08 */
++      u32 _reserved1;         /* 0x0c */
++      u32 rxgmask;            /* 0x10 */
++      u32 rx14mask;           /* 0x14 */
++      u32 rx15mask;           /* 0x18 */
++      u32 ecr;                /* 0x1c */
++      u32 esr;                /* 0x20 */
++      u32 imask2;             /* 0x24 */
++      u32 imask1;             /* 0x28 */
++      u32 iflag2;             /* 0x2c */
++      u32 iflag1;             /* 0x30 */
++      u32 _reserved2[19];
++      struct flexcan_mb cantxfg[64];
++};
++
++struct flexcan_priv {
++      struct can_priv can;
++      struct net_device *dev;
++      struct napi_struct napi;
++
++      void __iomem *base;
++      u32 reg_esr;
++      u32 reg_ctrl_default;
++
++      struct clk *clk;
++      struct flexcan_platform_data *pdata;
++};
++
++static struct can_bittiming_const flexcan_bittiming_const = {
++      .name = DRV_NAME,
++      .tseg1_min = 4,
++      .tseg1_max = 16,
++      .tseg2_min = 2,
++      .tseg2_max = 8,
++      .sjw_max = 4,
++      .brp_min = 1,
++      .brp_max = 256,
++      .brp_inc = 1,
++};
++
++/*
++ * Swtich transceiver on or off
++ */
++static void flexcan_transceiver_switch(const struct flexcan_priv *priv, int on)
++{
++      if (priv->pdata && priv->pdata->transceiver_switch)
++              priv->pdata->transceiver_switch(on);
++}
++
++static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv,
++                                            u32 reg_esr)
++{
++      return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) &&
++              (reg_esr & FLEXCAN_ESR_ERR_BUS);
++}
++
++static inline void flexcan_chip_enable(struct flexcan_priv *priv)
++{
++      struct flexcan_regs __iomem *regs = priv->base;
++      u32 reg;
++
++      reg = readl(&regs->mcr);
++      reg &= ~FLEXCAN_MCR_MDIS;
++      writel(reg, &regs->mcr);
++
++      udelay(10);
++}
++
++static inline void flexcan_chip_disable(struct flexcan_priv *priv)
++{
++      struct flexcan_regs __iomem *regs = priv->base;
++      u32 reg;
++
++      reg = readl(&regs->mcr);
++      reg |= FLEXCAN_MCR_MDIS;
++      writel(reg, &regs->mcr);
++}
++
++static int flexcan_get_berr_counter(const struct net_device *dev,
++                                  struct can_berr_counter *bec)
++{
++      const struct flexcan_priv *priv = netdev_priv(dev);
++      struct flexcan_regs __iomem *regs = priv->base;
++      u32 reg = readl(&regs->ecr);
++
++      bec->txerr = (reg >> 0) & 0xff;
++      bec->rxerr = (reg >> 8) & 0xff;
++
++      return 0;
++}
++
++static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++      const struct flexcan_priv *priv = netdev_priv(dev);
++      struct net_device_stats *stats = &dev->stats;
++      struct flexcan_regs __iomem *regs = priv->base;
++      struct can_frame *cf = (struct can_frame *)skb->data;
++      u32 can_id;
++      u32 ctrl = FLEXCAN_MB_CNT_CODE(0xc) | (cf->can_dlc << 16);
++
++      if (can_dropped_invalid_skb(dev, skb))
++              return NETDEV_TX_OK;
++
++      netif_stop_queue(dev);
++
++      if (cf->can_id & CAN_EFF_FLAG) {
++              can_id = cf->can_id & CAN_EFF_MASK;
++              ctrl |= FLEXCAN_MB_CNT_IDE | FLEXCAN_MB_CNT_SRR;
++      } else {
++              can_id = (cf->can_id & CAN_SFF_MASK) << 18;
++      }
++
++      if (cf->can_id & CAN_RTR_FLAG)
++              ctrl |= FLEXCAN_MB_CNT_RTR;
++
++      if (cf->can_dlc > 0) {
++              u32 data = be32_to_cpup((__be32 *)&cf->data[0]);
++              writel(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[0]);
++      }
++      if (cf->can_dlc > 3) {
++              u32 data = be32_to_cpup((__be32 *)&cf->data[4]);
++              writel(data, &regs->cantxfg[FLEXCAN_TX_BUF_ID].data[1]);
++      }
++
++      writel(can_id, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_id);
++      writel(ctrl, &regs->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl);
++
++      kfree_skb(skb);
++
++      /* tx_packets is incremented in flexcan_irq */
++      stats->tx_bytes += cf->can_dlc;
++
++      return NETDEV_TX_OK;
++}
++
++static void do_bus_err(struct net_device *dev,
++                     struct can_frame *cf, u32 reg_esr)
++{
++      struct flexcan_priv *priv = netdev_priv(dev);
++      int rx_errors = 0, tx_errors = 0;
++
++      cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
++
++      if (reg_esr & FLEXCAN_ESR_BIT1_ERR) {
++              dev_dbg(dev->dev.parent, "BIT1_ERR irq\n");
++              cf->data[2] |= CAN_ERR_PROT_BIT1;
++              tx_errors = 1;
++      }
++      if (reg_esr & FLEXCAN_ESR_BIT0_ERR) {
++              dev_dbg(dev->dev.parent, "BIT0_ERR irq\n");
++              cf->data[2] |= CAN_ERR_PROT_BIT0;
++              tx_errors = 1;
++      }
++      if (reg_esr & FLEXCAN_ESR_ACK_ERR) {
++              dev_dbg(dev->dev.parent, "ACK_ERR irq\n");
++              cf->can_id |= CAN_ERR_ACK;
++              cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
++              tx_errors = 1;
++      }
++      if (reg_esr & FLEXCAN_ESR_CRC_ERR) {
++              dev_dbg(dev->dev.parent, "CRC_ERR irq\n");
++              cf->data[2] |= CAN_ERR_PROT_BIT;
++              cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
++              rx_errors = 1;
++      }
++      if (reg_esr & FLEXCAN_ESR_FRM_ERR) {
++              dev_dbg(dev->dev.parent, "FRM_ERR irq\n");
++              cf->data[2] |= CAN_ERR_PROT_FORM;
++              rx_errors = 1;
++      }
++      if (reg_esr & FLEXCAN_ESR_STF_ERR) {
++              dev_dbg(dev->dev.parent, "STF_ERR irq\n");
++              cf->data[2] |= CAN_ERR_PROT_STUFF;
++              rx_errors = 1;
++      }
++
++      priv->can.can_stats.bus_error++;
++      if (rx_errors)
++              dev->stats.rx_errors++;
++      if (tx_errors)
++              dev->stats.tx_errors++;
++}
++
++static int flexcan_poll_bus_err(struct net_device *dev, u32 reg_esr)
++{
++      struct sk_buff *skb;
++      struct can_frame *cf;
++
++      skb = alloc_can_err_skb(dev, &cf);
++      if (unlikely(!skb))
++              return 0;
++
++      do_bus_err(dev, cf, reg_esr);
++      netif_receive_skb(skb);
++
++      dev->stats.rx_packets++;
++      dev->stats.rx_bytes += cf->can_dlc;
++
++      return 1;
++}
++
++static void do_state(struct net_device *dev,
++                   struct can_frame *cf, enum can_state new_state)
++{
++      struct flexcan_priv *priv = netdev_priv(dev);
++      struct can_berr_counter bec;
++
++      flexcan_get_berr_counter(dev, &bec);
++
++      switch (priv->can.state) {
++      case CAN_STATE_ERROR_ACTIVE:
++              /*
++               * from: ERROR_ACTIVE
++               * to  : ERROR_WARNING, ERROR_PASSIVE, BUS_OFF
++               * =>  : there was a warning int
++               */
++              if (new_state >= CAN_STATE_ERROR_WARNING &&
++                  new_state <= CAN_STATE_BUS_OFF) {
++                      dev_dbg(dev->dev.parent, "Error Warning IRQ\n");
++                      priv->can.can_stats.error_warning++;
++
++                      cf->can_id |= CAN_ERR_CRTL;
++                      cf->data[1] = (bec.txerr > bec.rxerr) ?
++                              CAN_ERR_CRTL_TX_WARNING :
++                              CAN_ERR_CRTL_RX_WARNING;
++              }
++      case CAN_STATE_ERROR_WARNING:   /* fallthrough */
++              /*
++               * from: ERROR_ACTIVE, ERROR_WARNING
++               * to  : ERROR_PASSIVE, BUS_OFF
++               * =>  : error passive int
++               */
++              if (new_state >= CAN_STATE_ERROR_PASSIVE &&
++                  new_state <= CAN_STATE_BUS_OFF) {
++                      dev_dbg(dev->dev.parent, "Error Passive IRQ\n");
++                      priv->can.can_stats.error_passive++;
++
++                      cf->can_id |= CAN_ERR_CRTL;
++                      cf->data[1] = (bec.txerr > bec.rxerr) ?
++                              CAN_ERR_CRTL_TX_PASSIVE :
++                              CAN_ERR_CRTL_RX_PASSIVE;
++              }
++              break;
++      case CAN_STATE_BUS_OFF:
++              dev_err(dev->dev.parent,
++                      "BUG! hardware recovered automatically from BUS_OFF\n");
++              break;
++      default:
++              break;
++      }
++
++      /* process state changes depending on the new state */
++      switch (new_state) {
++      case CAN_STATE_ERROR_ACTIVE:
++              dev_dbg(dev->dev.parent, "Error Active\n");
++              cf->can_id |= CAN_ERR_PROT;
++              cf->data[2] = CAN_ERR_PROT_ACTIVE;
++              break;
++      case CAN_STATE_BUS_OFF:
++              cf->can_id |= CAN_ERR_BUSOFF;
++              can_bus_off(dev);
++              break;
++      default:
++              break;
++      }
++}
++
++static int flexcan_poll_state(struct net_device *dev, u32 reg_esr)
++{
++      struct flexcan_priv *priv = netdev_priv(dev);
++      struct sk_buff *skb;
++      struct can_frame *cf;
++      enum can_state new_state;
++      int flt;
++
++      flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK;
++      if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) {
++              if (likely(!(reg_esr & (FLEXCAN_ESR_TX_WRN |
++                                      FLEXCAN_ESR_RX_WRN))))
++                      new_state = CAN_STATE_ERROR_ACTIVE;
++              else
++                      new_state = CAN_STATE_ERROR_WARNING;
++      } else if (unlikely(flt == FLEXCAN_ESR_FLT_CONF_PASSIVE))
++              new_state = CAN_STATE_ERROR_PASSIVE;
++      else
++              new_state = CAN_STATE_BUS_OFF;
++
++      /* state hasn't changed */
++      if (likely(new_state == priv->can.state))
++              return 0;
++
++      skb = alloc_can_err_skb(dev, &cf);
++      if (unlikely(!skb))
++              return 0;
++
++      do_state(dev, cf, new_state);
++      priv->can.state = new_state;
++      netif_receive_skb(skb);
++
++      dev->stats.rx_packets++;
++      dev->stats.rx_bytes += cf->can_dlc;
++
++      return 1;
++}
++
++static void flexcan_read_fifo(const struct net_device *dev,
++                            struct can_frame *cf)
++{
++      const struct flexcan_priv *priv = netdev_priv(dev);
++      struct flexcan_regs __iomem *regs = priv->base;
++      struct flexcan_mb __iomem *mb = &regs->cantxfg[0];
++      u32 reg_ctrl, reg_id;
++
++      reg_ctrl = readl(&mb->can_ctrl);
++      reg_id = readl(&mb->can_id);
++      if (reg_ctrl & FLEXCAN_MB_CNT_IDE)
++              cf->can_id = ((reg_id >> 0) & CAN_EFF_MASK) | CAN_EFF_FLAG;
++      else
++              cf->can_id = (reg_id >> 18) & CAN_SFF_MASK;
++
++      if (reg_ctrl & FLEXCAN_MB_CNT_RTR)
++              cf->can_id |= CAN_RTR_FLAG;
++      cf->can_dlc = get_can_dlc((reg_ctrl >> 16) & 0xf);
++
++      *(__be32 *)(cf->data + 0) = cpu_to_be32(readl(&mb->data[0]));
++      *(__be32 *)(cf->data + 4) = cpu_to_be32(readl(&mb->data[1]));
++
++      /* mark as read */
++      writel(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
++      readl(&regs->timer);
++}
++
++static int flexcan_read_frame(struct net_device *dev)
++{
++      struct net_device_stats *stats = &dev->stats;
++      struct can_frame *cf;
++      struct sk_buff *skb;
++
++      skb = alloc_can_skb(dev, &cf);
++      if (unlikely(!skb)) {
++              stats->rx_dropped++;
++              return 0;
++      }
++
++      flexcan_read_fifo(dev, cf);
++      netif_receive_skb(skb);
++
++      stats->rx_packets++;
++      stats->rx_bytes += cf->can_dlc;
++
++      return 1;
++}
++
++static int flexcan_poll(struct napi_struct *napi, int quota)
++{
++      struct net_device *dev = napi->dev;
++      const struct flexcan_priv *priv = netdev_priv(dev);
++      struct flexcan_regs __iomem *regs = priv->base;
++      u32 reg_iflag1, reg_esr;
++      int work_done = 0;
++
++      /*
++       * The error bits are cleared on read,
++       * use saved value from irq handler.
++       */
++      reg_esr = readl(&regs->esr) | priv->reg_esr;
++
++      /* handle state changes */
++      work_done += flexcan_poll_state(dev, reg_esr);
++
++      /* handle RX-FIFO */
++      reg_iflag1 = readl(&regs->iflag1);
++      while (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE &&
++             work_done < quota) {
++              work_done += flexcan_read_frame(dev);
++              reg_iflag1 = readl(&regs->iflag1);
++      }
++
++      /* report bus errors */
++      if (flexcan_has_and_handle_berr(priv, reg_esr) && work_done < quota)
++              work_done += flexcan_poll_bus_err(dev, reg_esr);
++
++      if (work_done < quota) {
++              napi_complete(napi);
++              /* enable IRQs */
++              writel(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
++              writel(priv->reg_ctrl_default, &regs->ctrl);
++      }
++
++      return work_done;
++}
++
++static irqreturn_t flexcan_irq(int irq, void *dev_id)
++{
++      struct net_device *dev = dev_id;
++      struct net_device_stats *stats = &dev->stats;
++      struct flexcan_priv *priv = netdev_priv(dev);
++      struct flexcan_regs __iomem *regs = priv->base;
++      u32 reg_iflag1, reg_esr;
++
++      reg_iflag1 = readl(&regs->iflag1);
++      reg_esr = readl(&regs->esr);
++      writel(FLEXCAN_ESR_ERR_INT, &regs->esr);        /* ACK err IRQ */
++
++      /*
++       * schedule NAPI in case of:
++       * - rx IRQ
++       * - state change IRQ
++       * - bus error IRQ and bus error reporting is activated
++       */
++      if ((reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) ||
++          (reg_esr & FLEXCAN_ESR_ERR_STATE) ||
++          flexcan_has_and_handle_berr(priv, reg_esr)) {
++              /*
++               * The error bits are cleared on read,
++               * save them for later use.
++               */
++              priv->reg_esr = reg_esr & FLEXCAN_ESR_ERR_BUS;
++              writel(FLEXCAN_IFLAG_DEFAULT & ~FLEXCAN_IFLAG_RX_FIFO_AVAILABLE,
++                     &regs->imask1);
++              writel(priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_ALL,
++                     &regs->ctrl);
++              napi_schedule(&priv->napi);
++      }
++
++      /* FIFO overflow */
++      if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_OVERFLOW) {
++              writel(FLEXCAN_IFLAG_RX_FIFO_OVERFLOW, &regs->iflag1);
++              dev->stats.rx_over_errors++;
++              dev->stats.rx_errors++;
++      }
++
++      /* transmission complete interrupt */
++      if (reg_iflag1 & (1 << FLEXCAN_TX_BUF_ID)) {
++              /* tx_bytes is incremented in flexcan_start_xmit */
++              stats->tx_packets++;
++              writel((1 << FLEXCAN_TX_BUF_ID), &regs->iflag1);
++              netif_wake_queue(dev);
++      }
++
++      return IRQ_HANDLED;
++}
++
++static void flexcan_set_bittiming(struct net_device *dev)
++{
++      const struct flexcan_priv *priv = netdev_priv(dev);
++      const struct can_bittiming *bt = &priv->can.bittiming;
++      struct flexcan_regs __iomem *regs = priv->base;
++      u32 reg;
++
++      reg = readl(&regs->ctrl);
++      reg &= ~(FLEXCAN_CTRL_PRESDIV(0xff) |
++               FLEXCAN_CTRL_RJW(0x3) |
++               FLEXCAN_CTRL_PSEG1(0x7) |
++               FLEXCAN_CTRL_PSEG2(0x7) |
++               FLEXCAN_CTRL_PROPSEG(0x7) |
++               FLEXCAN_CTRL_LPB |
++               FLEXCAN_CTRL_SMP |
++               FLEXCAN_CTRL_LOM);
++
++      reg |= FLEXCAN_CTRL_PRESDIV(bt->brp - 1) |
++              FLEXCAN_CTRL_PSEG1(bt->phase_seg1 - 1) |
++              FLEXCAN_CTRL_PSEG2(bt->phase_seg2 - 1) |
++              FLEXCAN_CTRL_RJW(bt->sjw - 1) |
++              FLEXCAN_CTRL_PROPSEG(bt->prop_seg - 1);
++
++      if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
++              reg |= FLEXCAN_CTRL_LPB;
++      if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
++              reg |= FLEXCAN_CTRL_LOM;
++      if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
++              reg |= FLEXCAN_CTRL_SMP;
++
++      dev_info(dev->dev.parent, "writing ctrl=0x%08x\n", reg);
++      writel(reg, &regs->ctrl);
++
++      /* print chip status */
++      dev_dbg(dev->dev.parent, "%s: mcr=0x%08x ctrl=0x%08x\n", __func__,
++              readl(&regs->mcr), readl(&regs->ctrl));
++}
++
++/*
++ * flexcan_chip_start
++ *
++ * this functions is entered with clocks enabled
++ *
++ */
++static int flexcan_chip_start(struct net_device *dev)
++{
++      struct flexcan_priv *priv = netdev_priv(dev);
++      struct flexcan_regs __iomem *regs = priv->base;
++      unsigned int i;
++      int err;
++      u32 reg_mcr, reg_ctrl;
++
++      /* enable module */
++      flexcan_chip_enable(priv);
++
++      /* soft reset */
++      writel(FLEXCAN_MCR_SOFTRST, &regs->mcr);
++      udelay(10);
++
++      reg_mcr = readl(&regs->mcr);
++      if (reg_mcr & FLEXCAN_MCR_SOFTRST) {
++              dev_err(dev->dev.parent,
++                      "Failed to softreset can module (mcr=0x%08x)\n",
++                      reg_mcr);
++              err = -ENODEV;
++              goto out;
++      }
++
++      flexcan_set_bittiming(dev);
++
++      /*
++       * MCR
++       *
++       * enable freeze
++       * enable fifo
++       * halt now
++       * only supervisor access
++       * enable warning int
++       * choose format C
++       *
++       */
++      reg_mcr = readl(&regs->mcr);
++      reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_FEN | FLEXCAN_MCR_HALT |
++              FLEXCAN_MCR_SUPV | FLEXCAN_MCR_WRN_EN |
++              FLEXCAN_MCR_IDAM_C;
++      dev_dbg(dev->dev.parent, "%s: writing mcr=0x%08x", __func__, reg_mcr);
++      writel(reg_mcr, &regs->mcr);
++
++      /*
++       * CTRL
++       *
++       * disable timer sync feature
++       *
++       * disable auto busoff recovery
++       * transmit lowest buffer first
++       *
++       * enable tx and rx warning interrupt
++       * enable bus off interrupt
++       * (== FLEXCAN_CTRL_ERR_STATE)
++       *
++       * _note_: we enable the "error interrupt"
++       * (FLEXCAN_CTRL_ERR_MSK), too. Otherwise we don't get any
++       * warning or bus passive interrupts.
++       */
++      reg_ctrl = readl(&regs->ctrl);
++      reg_ctrl &= ~FLEXCAN_CTRL_TSYN;
++      reg_ctrl |= FLEXCAN_CTRL_BOFF_REC | FLEXCAN_CTRL_LBUF |
++              FLEXCAN_CTRL_ERR_STATE | FLEXCAN_CTRL_ERR_MSK;
++
++      /* save for later use */
++      priv->reg_ctrl_default = reg_ctrl;
++      dev_dbg(dev->dev.parent, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
++      writel(reg_ctrl, &regs->ctrl);
++
++      for (i = 0; i < ARRAY_SIZE(regs->cantxfg); i++) {
++              writel(0, &regs->cantxfg[i].can_ctrl);
++              writel(0, &regs->cantxfg[i].can_id);
++              writel(0, &regs->cantxfg[i].data[0]);
++              writel(0, &regs->cantxfg[i].data[1]);
++
++              /* put MB into rx queue */
++              writel(FLEXCAN_MB_CNT_CODE(0x4), &regs->cantxfg[i].can_ctrl);
++      }
++
++      /* acceptance mask/acceptance code (accept everything) */
++      writel(0x0, &regs->rxgmask);
++      writel(0x0, &regs->rx14mask);
++      writel(0x0, &regs->rx15mask);
++
++      flexcan_transceiver_switch(priv, 1);
++
++      /* synchronize with the can bus */
++      reg_mcr = readl(&regs->mcr);
++      reg_mcr &= ~FLEXCAN_MCR_HALT;
++      writel(reg_mcr, &regs->mcr);
++
++      priv->can.state = CAN_STATE_ERROR_ACTIVE;
++
++      /* enable FIFO interrupts */
++      writel(FLEXCAN_IFLAG_DEFAULT, &regs->imask1);
++
++      /* print chip status */
++      dev_dbg(dev->dev.parent, "%s: reading mcr=0x%08x ctrl=0x%08x\n",
++              __func__, readl(&regs->mcr), readl(&regs->ctrl));
++
++      return 0;
++
++ out:
++      flexcan_chip_disable(priv);
++      return err;
++}
++
++/*
++ * flexcan_chip_stop
++ *
++ * this functions is entered with clocks enabled
++ *
++ */
++static void flexcan_chip_stop(struct net_device *dev)
++{
++      struct flexcan_priv *priv = netdev_priv(dev);
++      struct flexcan_regs __iomem *regs = priv->base;
++      u32 reg;
++
++      /* Disable all interrupts */
++      writel(0, &regs->imask1);
++
++      /* Disable + halt module */
++      reg = readl(&regs->mcr);
++      reg |= FLEXCAN_MCR_MDIS | FLEXCAN_MCR_HALT;
++      writel(reg, &regs->mcr);
++
++      flexcan_transceiver_switch(priv, 0);
++      priv->can.state = CAN_STATE_STOPPED;
++
++      return;
++}
++
++static int flexcan_open(struct net_device *dev)
++{
++      struct flexcan_priv *priv = netdev_priv(dev);
++      int err;
++
++      clk_enable(priv->clk);
++
++      err = open_candev(dev);
++      if (err)
++              goto out;
++
++      err = request_irq(dev->irq, flexcan_irq, IRQF_SHARED, dev->name, dev);
++      if (err)
++              goto out_close;
++
++      /* start chip and queuing */
++      err = flexcan_chip_start(dev);
++      if (err)
++              goto out_close;
++      napi_enable(&priv->napi);
++      netif_start_queue(dev);
++
++      return 0;
++
++ out_close:
++      close_candev(dev);
++ out:
++      clk_disable(priv->clk);
++
++      return err;
++}
++
++static int flexcan_close(struct net_device *dev)
++{
++      struct flexcan_priv *priv = netdev_priv(dev);
++
++      netif_stop_queue(dev);
++      napi_disable(&priv->napi);
++      flexcan_chip_stop(dev);
++
++      free_irq(dev->irq, dev);
++      clk_disable(priv->clk);
++
++      close_candev(dev);
++
++      return 0;
++}
++
++static int flexcan_set_mode(struct net_device *dev, enum can_mode mode)
++{
++      int err;
++
++      switch (mode) {
++      case CAN_MODE_START:
++              err = flexcan_chip_start(dev);
++              if (err)
++                      return err;
++
++              netif_wake_queue(dev);
++              break;
++
++      default:
++              return -EOPNOTSUPP;
++      }
++
++      return 0;
++}
++
++static const struct net_device_ops flexcan_netdev_ops = {
++      .ndo_open       = flexcan_open,
++      .ndo_stop       = flexcan_close,
++      .ndo_start_xmit = flexcan_start_xmit,
++};
++
++static int __devinit register_flexcandev(struct net_device *dev)
++{
++      struct flexcan_priv *priv = netdev_priv(dev);
++      struct flexcan_regs __iomem *regs = priv->base;
++      u32 reg, err;
++
++      clk_enable(priv->clk);
++
++      /* select "bus clock", chip must be disabled */
++      flexcan_chip_disable(priv);
++      reg = readl(&regs->ctrl);
++      reg |= FLEXCAN_CTRL_CLK_SRC;
++      writel(reg, &regs->ctrl);
++
++      flexcan_chip_enable(priv);
++
++      /* set freeze, halt and activate FIFO, restrict register access */
++      reg = readl(&regs->mcr);
++      reg |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT |
++              FLEXCAN_MCR_FEN | FLEXCAN_MCR_SUPV;
++      writel(reg, &regs->mcr);
++
++      /*
++       * Currently we only support newer versions of this core
++       * featuring a RX FIFO. Older cores found on some Coldfire
++       * derivates are not yet supported.
++       */
++      reg = readl(&regs->mcr);
++      if (!(reg & FLEXCAN_MCR_FEN)) {
++              dev_err(dev->dev.parent,
++                      "Could not enable RX FIFO, unsupported core\n");
++              err = -ENODEV;
++              goto out;
++      }
++
++      err = register_candev(dev);
++
++ out:
++      /* disable core and turn off clocks */
++      flexcan_chip_disable(priv);
++      clk_disable(priv->clk);
++
++      return err;
++}
++
++static void __devexit unregister_flexcandev(struct net_device *dev)
++{
++      unregister_candev(dev);
++}
++
++static int __devinit flexcan_probe(struct platform_device *pdev)
++{
++      struct net_device *dev;
++      struct flexcan_priv *priv;
++      struct resource *mem;
++      struct clk *clk;
++      void __iomem *base;
++      resource_size_t mem_size;
++      int err, irq;
++
++      clk = clk_get(&pdev->dev, NULL);
++      if (IS_ERR(clk)) {
++              dev_err(&pdev->dev, "no clock defined\n");
++              err = PTR_ERR(clk);
++              goto failed_clock;
++      }
++
++      mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      irq = platform_get_irq(pdev, 0);
++      if (!mem || irq <= 0) {
++              err = -ENODEV;
++              goto failed_get;
++      }
++
++      mem_size = resource_size(mem);
++      if (!request_mem_region(mem->start, mem_size, pdev->name)) {
++              err = -EBUSY;
++              goto failed_req;
++      }
++
++      base = ioremap(mem->start, mem_size);
++      if (!base) {
++              err = -ENOMEM;
++              goto failed_map;
++      }
++
++      dev = alloc_candev(sizeof(struct flexcan_priv), 0);
++      if (!dev) {
++              err = -ENOMEM;
++              goto failed_alloc;
++      }
++
++      dev->netdev_ops = &flexcan_netdev_ops;
++      dev->irq = irq;
++      dev->flags |= IFF_ECHO; /* we support local echo in hardware */
++
++      priv = netdev_priv(dev);
++      priv->can.clock.freq = clk_get_rate(clk);
++      priv->can.bittiming_const = &flexcan_bittiming_const;
++      priv->can.do_set_mode = flexcan_set_mode;
++      priv->can.do_get_berr_counter = flexcan_get_berr_counter;
++      priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
++              CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES |
++              CAN_CTRLMODE_BERR_REPORTING;
++      priv->base = base;
++      priv->dev = dev;
++      priv->clk = clk;
++      priv->pdata = pdev->dev.platform_data;
++
++      netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
++
++      dev_set_drvdata(&pdev->dev, dev);
++      SET_NETDEV_DEV(dev, &pdev->dev);
++
++      err = register_flexcandev(dev);
++      if (err) {
++              dev_err(&pdev->dev, "registering netdev failed\n");
++              goto failed_register;
++      }
++
++      dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%d)\n",
++               priv->base, dev->irq);
++
++      return 0;
++
++ failed_register:
++      free_candev(dev);
++ failed_alloc:
++      iounmap(base);
++ failed_map:
++      release_mem_region(mem->start, mem_size);
++ failed_req:
++      clk_put(clk);
++ failed_get:
++ failed_clock:
++      return err;
++}
++
++static int __devexit flexcan_remove(struct platform_device *pdev)
++{
++      struct net_device *dev = platform_get_drvdata(pdev);
++      struct flexcan_priv *priv = netdev_priv(dev);
++      struct resource *mem;
++
++      unregister_flexcandev(dev);
++      platform_set_drvdata(pdev, NULL);
++      free_candev(dev);
++      iounmap(priv->base);
++
++      mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      release_mem_region(mem->start, resource_size(mem));
++
++      clk_put(priv->clk);
++
++      return 0;
++}
++
++static struct platform_driver flexcan_driver = {
++      .driver.name = DRV_NAME,
++      .probe = flexcan_probe,
++      .remove = __devexit_p(flexcan_remove),
++};
++
++static int __init flexcan_init(void)
++{
++      pr_info("%s netdevice driver\n", DRV_NAME);
++      return platform_driver_register(&flexcan_driver);
++}
++
++static void __exit flexcan_exit(void)
++{
++      platform_driver_unregister(&flexcan_driver);
++      pr_info("%s: driver removed\n", DRV_NAME);
++}
++
++module_init(flexcan_init);
++module_exit(flexcan_exit);
++
++MODULE_AUTHOR("Sascha Hauer <kernel@pengutronix.de>, "
++            "Marc Kleine-Budde <kernel@pengutronix.de>");
++MODULE_LICENSE("GPL v2");
++MODULE_DESCRIPTION("CAN port driver for flexcan based chip");
+diff -urN linux.35.old/drivers/net/can/Kconfig linux.35.new/drivers/net/can/Kconfig
+--- linux.35.old/drivers/net/can/Kconfig       2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/net/can/Kconfig       2010-12-03 09:51:55.456347637 +0100
+@@ -73,6 +73,15 @@
+         This driver can also be built as a module. If so, the module will be
+         called janz-ican3.ko.
++config HAVE_CAN_FLEXCAN
++      bool
++
++config CAN_FLEXCAN
++      tristate "Support for Freescale FLEXCAN based chips"
++      depends on CAN_DEV && HAVE_CAN_FLEXCAN
++      ---help---
++        Say Y here if you want to support for Freescale FlexCAN.
++
+ source "drivers/net/can/mscan/Kconfig"
+ source "drivers/net/can/sja1000/Kconfig"
+diff -urN linux.35.old/drivers/net/can/Makefile linux.35.new/drivers/net/can/Makefile
+--- linux.35.old/drivers/net/can/Makefile      2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/net/can/Makefile      2010-12-03 09:51:55.456347637 +0100
+@@ -16,5 +16,6 @@
+ obj-$(CONFIG_CAN_MCP251X)     += mcp251x.o
+ obj-$(CONFIG_CAN_BFIN)                += bfin_can.o
+ obj-$(CONFIG_CAN_JANZ_ICAN3)  += janz-ican3.o
++obj-$(CONFIG_CAN_FLEXCAN)     += flexcan.o
+ ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
+diff -urN linux.35.old/drivers/net/fec.c linux.35.new/drivers/net/fec.c
+--- linux.35.old/drivers/net/fec.c     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/net/fec.c     2010-12-03 09:51:55.460348141 +0100
+@@ -118,6 +118,8 @@
+ #define FEC_ENET_MII  ((uint)0x00800000)      /* MII interrupt */
+ #define FEC_ENET_EBERR        ((uint)0x00400000)      /* SDMA bus error */
++#define FEC_DEFAULT_IMASK (FEC_ENET_TXF | FEC_ENET_RXF | FEC_ENET_MII)
++
+ /* The FEC stores dest/src/type, data, and checksum for receive packets.
+  */
+ #define PKT_MAXBUF_SIZE               1518
+@@ -187,6 +189,7 @@
+       int     index;
+       int     link;
+       int     full_duplex;
++      struct  completion mdio_done;
+ };
+ static irqreturn_t fec_enet_interrupt(int irq, void * dev_id);
+@@ -205,12 +208,12 @@
+ #define FEC_MMFR_TA           (2 << 16)
+ #define FEC_MMFR_DATA(v)      (v & 0xffff)
+-#define FEC_MII_TIMEOUT               10000
++#define FEC_MII_TIMEOUT               1000 /* us */
+ /* Transmitter timeout */
+ #define TX_TIMEOUT (2 * HZ)
+-static int
++static netdev_tx_t
+ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+ {
+       struct fec_enet_private *fep = netdev_priv(dev);
+@@ -334,6 +337,11 @@
+                       ret = IRQ_HANDLED;
+                       fec_enet_tx(dev);
+               }
++
++              if (int_events & FEC_ENET_MII) {
++                      ret = IRQ_HANDLED;
++                      complete(&fep->mdio_done);
++              }
+       } while (int_events);
+       return ret;
+@@ -608,18 +616,13 @@
+               phy_print_status(phy_dev);
+ }
+-/*
+- * NOTE: a MII transaction is during around 25 us, so polling it...
+- */
+ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
+ {
+       struct fec_enet_private *fep = bus->priv;
+-      int timeout = FEC_MII_TIMEOUT;
++      unsigned long time_left;
+       fep->mii_timeout = 0;
+-
+-      /* clear MII end of transfer bit*/
+-      writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
++      init_completion(&fep->mdio_done);
+       /* start a read op */
+       writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
+@@ -627,13 +630,12 @@
+               FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);
+       /* wait for end of transfer */
+-      while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) {
+-              cpu_relax();
+-              if (timeout-- < 0) {
+-                      fep->mii_timeout = 1;
+-                      printk(KERN_ERR "FEC: MDIO read timeout\n");
+-                      return -ETIMEDOUT;
+-              }
++      time_left = wait_for_completion_timeout(&fep->mdio_done,
++                      usecs_to_jiffies(FEC_MII_TIMEOUT));
++      if (time_left == 0) {
++              fep->mii_timeout = 1;
++              printk(KERN_ERR "FEC: MDIO read timeout\n");
++              return -ETIMEDOUT;
+       }
+       /* return value */
+@@ -644,12 +646,10 @@
+                          u16 value)
+ {
+       struct fec_enet_private *fep = bus->priv;
+-      int timeout = FEC_MII_TIMEOUT;
++      unsigned long time_left;
+       fep->mii_timeout = 0;
+-
+-      /* clear MII end of transfer bit*/
+-      writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
++      init_completion(&fep->mdio_done);
+       /* start a read op */
+       writel(FEC_MMFR_ST | FEC_MMFR_OP_READ |
+@@ -658,13 +658,12 @@
+               fep->hwp + FEC_MII_DATA);
+       /* wait for end of transfer */
+-      while (!(readl(fep->hwp + FEC_IEVENT) & FEC_ENET_MII)) {
+-              cpu_relax();
+-              if (timeout-- < 0) {
+-                      fep->mii_timeout = 1;
+-                      printk(KERN_ERR "FEC: MDIO write timeout\n");
+-                      return -ETIMEDOUT;
+-              }
++      time_left = wait_for_completion_timeout(&fep->mdio_done,
++                      usecs_to_jiffies(FEC_MII_TIMEOUT));
++      if (time_left == 0) {
++              fep->mii_timeout = 1;
++              printk(KERN_ERR "FEC: MDIO write timeout\n");
++              return -ETIMEDOUT;
+       }
+       return 0;
+@@ -679,30 +678,24 @@
+ {
+       struct fec_enet_private *fep = netdev_priv(dev);
+       struct phy_device *phy_dev = NULL;
+-      int phy_addr;
++      int ret;
+       fep->phy_dev = NULL;
+       /* find the first phy */
+-      for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+-              if (fep->mii_bus->phy_map[phy_addr]) {
+-                      phy_dev = fep->mii_bus->phy_map[phy_addr];
+-                      break;
+-              }
+-      }
+-
++      phy_dev = phy_find_first(fep->mii_bus);
+       if (!phy_dev) {
+               printk(KERN_ERR "%s: no PHY found\n", dev->name);
+               return -ENODEV;
+       }
+       /* attach the mac to the phy */
+-      phy_dev = phy_connect(dev, dev_name(&phy_dev->dev),
++      ret = phy_connect_direct(dev, phy_dev,
+                            &fec_enet_adjust_link, 0,
+                            PHY_INTERFACE_MODE_MII);
+-      if (IS_ERR(phy_dev)) {
++      if (ret) {
+               printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name);
+-              return PTR_ERR(phy_dev);
++              return ret;
+       }
+       /* mask with MAC supported features */
+@@ -834,7 +827,7 @@
+       if (!phydev)
+               return -ENODEV;
+-      return phy_mii_ioctl(phydev, if_mii(rq), cmd);
++      return phy_mii_ioctl(phydev, rq, cmd);
+ }
+ static void fec_enet_free_buffers(struct net_device *dev)
+@@ -1222,7 +1215,7 @@
+       writel(0, fep->hwp + FEC_R_DES_ACTIVE);
+       /* Enable interrupts we wish to service */
+-      writel(FEC_ENET_TXF | FEC_ENET_RXF, fep->hwp + FEC_IMASK);
++      writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+ }
+ static void
+@@ -1241,11 +1234,8 @@
+       /* Whack a reset.  We should wait for this. */
+       writel(1, fep->hwp + FEC_ECNTRL);
+       udelay(10);
+-
+-      /* Clear outstanding MII command interrupts. */
+-      writel(FEC_ENET_MII, fep->hwp + FEC_IEVENT);
+-
+       writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
++      writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+ }
+ static int __devinit
+@@ -1365,10 +1355,11 @@
+       return 0;
+ }
++#ifdef CONFIG_PM
+ static int
+-fec_suspend(struct platform_device *dev, pm_message_t state)
++fec_suspend(struct device *dev)
+ {
+-      struct net_device *ndev = platform_get_drvdata(dev);
++      struct net_device *ndev = dev_get_drvdata(dev);
+       struct fec_enet_private *fep;
+       if (ndev) {
+@@ -1381,9 +1372,9 @@
+ }
+ static int
+-fec_resume(struct platform_device *dev)
++fec_resume(struct device *dev)
+ {
+-      struct net_device *ndev = platform_get_drvdata(dev);
++      struct net_device *ndev = dev_get_drvdata(dev);
+       struct fec_enet_private *fep;
+       if (ndev) {
+@@ -1395,15 +1386,26 @@
+       return 0;
+ }
++static const struct dev_pm_ops fec_pm_ops = {
++      .suspend        = fec_suspend,
++      .resume         = fec_resume,
++      .freeze         = fec_suspend,
++      .thaw           = fec_resume,
++      .poweroff       = fec_suspend,
++      .restore        = fec_resume,
++};
++#endif
++
+ static struct platform_driver fec_driver = {
+       .driver = {
+-              .name    = "fec",
+-              .owner   = THIS_MODULE,
++              .name   = "fec",
++              .owner  = THIS_MODULE,
++#ifdef CONFIG_PM
++              .pm     = &fec_pm_ops,
++#endif
+       },
+-      .probe   = fec_probe,
+-      .remove  = __devexit_p(fec_drv_remove),
+-      .suspend = fec_suspend,
+-      .resume  = fec_resume,
++      .probe  = fec_probe,
++      .remove = __devexit_p(fec_drv_remove),
+ };
+ static int __init
+diff -urN linux.35.old/drivers/net/phy/phy.c linux.35.new/drivers/net/phy/phy.c
+--- linux.35.old/drivers/net/phy/phy.c 2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/net/phy/phy.c 2010-12-03 09:51:55.460348141 +0100
+@@ -309,8 +309,9 @@
+  * current state.  Use at own risk.
+  */
+ int phy_mii_ioctl(struct phy_device *phydev,
+-              struct mii_ioctl_data *mii_data, int cmd)
++              struct ifreq *ifr, int cmd)
+ {
++      struct mii_ioctl_data *mii_data = if_mii(ifr);
+       u16 val = mii_data->val_in;
+       switch (cmd) {
+@@ -360,6 +361,11 @@
+               }
+               break;
++      case SIOCSHWTSTAMP:
++              if (phydev->drv->hwtstamp)
++                      return phydev->drv->hwtstamp(phydev, ifr);
++              /* fall through */
++
+       default:
+               return -EOPNOTSUPP;
+       }
+diff -urN linux.35.old/drivers/net/phy/phy_device.c linux.35.new/drivers/net/phy/phy_device.c
+--- linux.35.old/drivers/net/phy/phy_device.c  2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/net/phy/phy_device.c  2010-12-03 09:51:55.460348141 +0100
+@@ -460,6 +460,7 @@
+       }
+       phydev->attached_dev = dev;
++      dev->phydev = phydev;
+       phydev->dev_flags = flags;
+@@ -513,6 +514,7 @@
+  */
+ void phy_detach(struct phy_device *phydev)
+ {
++      phydev->attached_dev->phydev = NULL;
+       phydev->attached_dev = NULL;
+       /* If the device had no specific driver before (i.e. - it
+diff -urN linux.35.old/drivers/rtc/Kconfig linux.35.new/drivers/rtc/Kconfig
+--- linux.35.old/drivers/rtc/Kconfig   2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/rtc/Kconfig   2010-12-03 09:51:55.464349671 +0100
+@@ -548,6 +548,13 @@
+          This driver can also be built as a module, if so, the module
+          will be called "rtc-mxc".
++config RTC_DRV_IMXDI
++      tristate "Freescale IMX DryIce Real Time Clock"
++      depends on ARCH_MXC
++      depends on RTC_CLASS
++      help
++        Support for Freescale IMX DryIce RTC
++
+ config RTC_DRV_BQ4802
+       tristate "TI BQ4802"
+       help
+diff -urN linux.35.old/drivers/rtc/Makefile linux.35.new/drivers/rtc/Makefile
+--- linux.35.old/drivers/rtc/Makefile  2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/rtc/Makefile  2010-12-03 09:51:55.464349671 +0100
+@@ -53,6 +53,7 @@
+ obj-$(CONFIG_RTC_DRV_M48T59)  += rtc-m48t59.o
+ obj-$(CONFIG_RTC_DRV_M48T86)  += rtc-m48t86.o
+ obj-$(CONFIG_RTC_MXC)         += rtc-mxc.o
++obj-$(CONFIG_RTC_DRV_IMXDI)   += rtc-imxdi.o
+ obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o
+ obj-$(CONFIG_RTC_DRV_MAX8925) += rtc-max8925.o
+ obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o
+diff -urN linux.35.old/drivers/rtc/rtc-imxdi.c linux.35.new/drivers/rtc/rtc-imxdi.c
+--- linux.35.old/drivers/rtc/rtc-imxdi.c       1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/drivers/rtc/rtc-imxdi.c       2010-12-03 09:51:55.468347409 +0100
+@@ -0,0 +1,658 @@
++/*
++ * 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
++ */
++
++/* based on rtc-mc13892.c */
++
++/*
++ * This driver uses the 47-bit 32 kHz counter in the Freescale DryIce block
++ * to implement a Linux RTC. Times and alarms are truncated to seconds.
++ * Since the RTC framework performs API locking via rtc->ops_lock the
++ * only simultaneous accesses we need to deal with is updating DryIce
++ * registers while servicing an alarm.
++ *
++ * Note that reading the DSR (DryIce Status Register) automatically clears
++ * the WCF (Write Complete Flag). All DryIce writes are synchronized to the
++ * LP (Low Power) domain and set the WCF upon completion. Writes to the
++ * DIER (DryIce Interrupt Enable Register) are the only exception. These
++ * occur at normal bus speeds and do not set WCF.  Periodic interrupts are
++ * not supported by the hardware.
++ */
++
++/* #define DEBUG */
++/* #define DI_DEBUG_REGIO */
++
++#include <linux/io.h>
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/rtc.h>
++#include <linux/workqueue.h>
++#include <linux/slab.h>
++
++/* DryIce Register Definitions */
++
++#define DTCMR     0x00           /* Time Counter MSB Reg */
++#define DTCLR     0x04           /* Time Counter LSB Reg */
++
++#define DCAMR     0x08           /* Clock Alarm MSB Reg */
++#define DCALR     0x0c           /* Clock Alarm LSB Reg */
++#define DCAMR_UNSET  0xFFFFFFFF  /* doomsday - 1 sec */
++
++#define DCR       0x10           /* Control Reg */
++#define DCR_TCE   (1 << 3)       /* Time Counter Enable */
++
++#define DSR       0x14           /* Status Reg */
++#define DSR_WBF   (1 << 10)      /* Write Busy Flag */
++#define DSR_WNF   (1 << 9)       /* Write Next Flag */
++#define DSR_WCF   (1 << 8)       /* Write Complete Flag */
++#define DSR_WEF   (1 << 7)       /* Write Error Flag */
++#define DSR_CAF   (1 << 4)       /* Clock Alarm Flag */
++#define DSR_NVF   (1 << 1)       /* Non-Valid Flag */
++#define DSR_SVF   (1 << 0)       /* Security Violation Flag */
++
++#define DIER      0x18           /* Interrupt Enable Reg */
++#define DIER_WNIE (1 << 9)       /* Write Next Interrupt Enable */
++#define DIER_WCIE (1 << 8)       /* Write Complete Interrupt Enable */
++#define DIER_WEIE (1 << 7)       /* Write Error Interrupt Enable */
++#define DIER_CAIE (1 << 4)       /* Clock Alarm Interrupt Enable */
++
++#ifndef DI_DEBUG_REGIO
++/* dryice read register */
++#define di_read(pdata, reg)  __raw_readl((pdata)->ioaddr + (reg))
++
++/* dryice write register */
++#define di_write(pdata, val, reg)  __raw_writel((val), (pdata)->ioaddr + (reg))
++#else
++/* dryice read register - debug version */
++static inline u32 di_read(struct rtc_drv_data *pdata, int reg)
++{
++      u32 val = __raw_readl(pdata->ioaddr + reg);
++      pr_info("di_read(0x%02x) = 0x%08x\n", reg, val);
++      return val;
++}
++
++/* dryice write register - debug version */
++static inline void di_write(struct rtc_drv_data *pdata, u32 val, int reg)
++{
++      printk(KERN_INFO "di_write(0x%08x, 0x%02x)\n", val, reg);
++      __raw_writel(val, pdata->ioaddr + reg);
++}
++#endif
++
++/*
++ * dryice write register with wait and error handling.
++ * all registers, except for DIER, should use this method.
++ */
++#define di_write_wait_err(pdata, val, reg, rc, label) \
++              do { \
++                      if (di_write_wait((pdata), (val), (reg))) { \
++                              rc = -EIO; \
++                              goto label; \
++                      } \
++              } while (0)
++
++struct rtc_drv_data {
++      struct platform_device *pdev;  /* pointer to platform dev */
++      struct rtc_device *rtc;        /* pointer to rtc struct */
++      unsigned long baseaddr;        /* physical bass address */
++      void __iomem *ioaddr;          /* virtual base address */
++      int size;                      /* size of register region */
++      int irq;                       /* dryice normal irq */
++      struct clk *clk;               /* dryice clock control */
++      u32 dsr;                       /* copy of dsr reg from isr */
++      wait_queue_head_t write_wait;  /* write-complete queue */
++      struct mutex write_mutex;      /* force reg writes to be sequential */
++      struct work_struct work;       /* schedule alarm work */
++};
++
++static spinlock_t irq_lock = SPIN_LOCK_UNLOCKED;           /* irq resource lock */
++
++/*
++ * enable a dryice interrupt
++ */
++static inline void di_int_enable(struct rtc_drv_data *pdata, u32 intr)
++{
++      unsigned long flags;
++
++      spin_lock_irqsave(&irq_lock, flags);
++      di_write(pdata, di_read(pdata, DIER) | intr, DIER);
++      spin_unlock_irqrestore(&irq_lock, flags);
++}
++
++/*
++ * disable a dryice interrupt
++ */
++static inline void di_int_disable(struct rtc_drv_data *pdata, u32 intr)
++{
++      unsigned long flags;
++
++      spin_lock_irqsave(&irq_lock, flags);
++      di_write(pdata, di_read(pdata, DIER) & ~intr, DIER);
++      spin_unlock_irqrestore(&irq_lock, flags);
++}
++
++/*
++ * This function attempts to clear the dryice write-error flag.
++ *
++ * A dryice write error is similar to a bus fault and should not occur in
++ * normal operation.  Clearing the flag requires another write, so the root
++ * cause of the problem may need to be fixed before the flag can be cleared.
++ */
++static void clear_write_error(struct rtc_drv_data *pdata)
++{
++      int cnt;
++
++      dev_warn(&pdata->pdev->dev, "WARNING: Register write error!\n");
++
++      for (;;) {
++              /* clear the write error flag */
++              di_write(pdata, DSR_WEF, DSR);
++
++              /* wait for it to take effect */
++              for (cnt = 0; cnt < 100; cnt++) {
++                      if ((di_read(pdata, DSR) & DSR_WEF) == 0)
++                              return;
++                      udelay(10);
++              }
++              dev_err(&pdata->pdev->dev,
++                      "ERROR: Cannot clear write-error flag!\n");
++      }
++}
++
++/*
++ * Write a dryice register and wait until it completes.
++ *
++ * This function uses interrupts to determine when the
++ * write has completed.
++ */
++static int di_write_wait(struct rtc_drv_data *pdata, u32 val, int reg)
++{
++      int ret;
++      int rc = 0;
++
++      /* serialize register writes */
++      mutex_lock(&pdata->write_mutex);
++
++      /* enable the write-complete interrupt */
++      di_int_enable(pdata, DIER_WCIE);
++
++      pdata->dsr = 0;
++
++      /* do the register write */
++      di_write(pdata, val, reg);
++
++      /* wait for the write to finish */
++      ret = wait_event_interruptible_timeout(pdata->write_wait,
++                                             pdata->dsr & (DSR_WCF | DSR_WEF),
++                                             1 * HZ);
++      if (ret == 0)
++              dev_warn(&pdata->pdev->dev, "Write-wait timeout\n");
++
++      /* check for write error */
++      if (pdata->dsr & DSR_WEF) {
++              clear_write_error(pdata);
++              rc = -EIO;
++      }
++      mutex_unlock(&pdata->write_mutex);
++      return rc;
++}
++
++/*
++ * rtc device ioctl
++ *
++ * The rtc framework handles the basic rtc ioctls on behalf
++ * of the driver by calling the functions registered in the
++ * rtc_ops structure.
++ */
++static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm);
++static int dryice_rtc_set_time(struct device *dev, struct rtc_time *tm);
++static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm);
++static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm);
++
++static int dryice_rtc_ioctl(struct device *dev, unsigned int cmd,
++                          unsigned long arg)
++{
++      struct rtc_drv_data *pdata = dev_get_drvdata(dev);
++
++      dev_dbg(dev, "%s(0x%x)\n", __func__, cmd);
++      switch (cmd) {
++      case RTC_RD_TIME:  /* alarm disable */
++                {
++                        struct rtc_time rtc_tm;
++                      int ret = 0;
++
++                        memset(&rtc_tm, 0, sizeof (struct rtc_time));
++                        ret = dryice_rtc_read_time(dev, &rtc_tm);
++                        if (copy_to_user((struct rtc_time*)arg, &rtc_tm, sizeof(struct rtc_time)))
++                                return -EFAULT;
++                        return ret;
++                }
++      case RTC_SET_TIME:  /* alarm enable */
++              {
++                      struct rtc_time rtc_tm;
++                      int ret = 0;
++
++                      if (copy_from_user(&rtc_tm, (struct rtc_time*)arg, sizeof(struct rtc_time)))
++                              return -EFAULT;
++
++                      ret = dryice_rtc_set_time(dev, &rtc_tm);
++                      return ret;
++              }
++      case RTC_ALM_READ:  /* Read the present alarm time */
++              {
++                      struct rtc_wkalrm rtc_wtm;
++                      int ret = 0;
++
++                        memset(&rtc_wtm, 0, sizeof(struct rtc_wkalrm));
++                      ret = dryice_rtc_read_alarm(dev, &rtc_wtm);
++
++                      if (copy_to_user((struct rtc_time*)arg, &(rtc_wtm.time), sizeof(struct rtc_time)))
++                              return -EFAULT;
++                      return ret;
++              }
++      case RTC_WKALM_RD:  /* Get wakeup alarm */
++              {
++                      struct rtc_wkalrm rtc_wtm;
++                      int ret = 0;
++
++                        memset(&rtc_wtm, 0, sizeof(struct rtc_wkalrm));
++                      ret = dryice_rtc_read_alarm(dev, &rtc_wtm);
++
++                      if (copy_to_user((struct rtc_wkalrm*)arg, &rtc_wtm, sizeof(struct rtc_wkalrm)))
++                              return -EFAULT;
++                      return ret;
++              }
++      case RTC_ALM_SET:  /* Set alarm time */
++              {
++                      struct rtc_wkalrm rtc_wtm;
++                      int ret = 0;
++
++                      memset(&rtc_wtm, 0, sizeof(struct rtc_wkalrm));
++                      if (copy_from_user(&(rtc_wtm.time), (struct rtc_time*)arg, sizeof(struct rtc_time)))
++                              return -EFAULT;
++
++                      ret = dryice_rtc_set_alarm(dev, &rtc_wtm);
++                      return ret;
++              }
++      case RTC_WKALM_SET:     /* Set wakeup alarm */  
++              {
++                      struct rtc_wkalrm rtc_wtm;
++                      int ret = 0;
++
++                      if (copy_from_user(&rtc_wtm, (struct rtc_wkalrm*)arg, sizeof(struct rtc_wkalrm)))
++                              return -EFAULT;
++
++                      ret = dryice_rtc_set_alarm(dev, &rtc_wtm);
++                      return ret;
++              }
++      case RTC_AIE_OFF:  /* alarm disable */
++              di_int_disable(pdata, DIER_CAIE);
++              return 0;
++
++      case RTC_AIE_ON:  /* alarm enable */
++              di_int_enable(pdata, DIER_CAIE);
++              return 0;
++      }
++      return -ENOIOCTLCMD;
++}
++
++/*
++ * read the seconds portion of the current time from the dryice time counter
++ */
++static int dryice_rtc_read_time(struct device *dev, struct rtc_time *tm)
++{
++      struct rtc_drv_data *pdata = dev_get_drvdata(dev);
++      unsigned long now;
++
++      dev_dbg(dev, "%s\n", __func__);
++      now = di_read(pdata, DTCMR);
++      rtc_time_to_tm(now, tm);
++
++      return 0;
++}
++
++/*
++ * set the seconds portion of dryice time counter and clear the
++ * fractional part.
++ */
++static int dryice_rtc_set_time(struct device *dev, struct rtc_time *tm)
++{
++      struct rtc_drv_data *pdata = dev_get_drvdata(dev);
++      unsigned long now;
++      int rc;
++
++      dev_dbg(dev, "%s\n", __func__);
++      rc = rtc_tm_to_time(tm, &now);
++      if (rc == 0) {
++              /* zero the fractional part first */
++              di_write_wait_err(pdata, 0, DTCLR, rc, err);
++              di_write_wait_err(pdata, now, DTCMR, rc, err);
++      }
++err:
++      return rc;
++}
++
++/*
++ * read the seconds portion of the alarm register.
++ * the fractional part of the alarm register is always zero.
++ */
++static int dryice_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
++{
++      struct rtc_drv_data *pdata = dev_get_drvdata(dev);
++      u32 dcamr;
++
++      dev_dbg(dev, "%s\n", __func__);
++      dcamr = di_read(pdata, DCAMR);
++      rtc_time_to_tm(dcamr, &alarm->time);
++
++      /* alarm is enabled if the interrupt is enabled */
++      alarm->enabled = (di_read(pdata, DIER) & DIER_CAIE) != 0;
++
++      /* don't allow the DSR read to mess up DSR_WCF */
++      mutex_lock(&pdata->write_mutex);
++
++      /* alarm is pending if the alarm flag is set */
++      alarm->pending = (di_read(pdata, DSR) & DSR_CAF) != 0;
++
++      mutex_unlock(&pdata->write_mutex);
++
++      return 0;
++}
++
++/*
++ * set the seconds portion of dryice alarm register
++ */
++static int dryice_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
++{
++      struct rtc_drv_data *pdata = dev_get_drvdata(dev);
++      unsigned long now;
++      unsigned long alarm_time;
++      int rc;
++
++      dev_dbg(dev, "%s\n", __func__);
++      rc = rtc_tm_to_time(&alarm->time, &alarm_time);
++      if (rc)
++              return rc;
++
++      /* don't allow setting alarm in the past */
++      now = di_read(pdata, DTCMR);
++      if (alarm_time < now)
++              return -EINVAL;
++
++      /* write the new alarm time */
++      di_write_wait_err(pdata, (u32)alarm_time, DCAMR, rc, err);
++
++      if (alarm->enabled)
++              di_int_enable(pdata, DIER_CAIE);  /* enable alarm intr */
++      else
++              di_int_disable(pdata, DIER_CAIE); /* disable alarm intr */
++err:
++      return rc;
++}
++
++static struct rtc_class_ops dryice_rtc_ops = {
++      .ioctl = dryice_rtc_ioctl,
++      .read_time = dryice_rtc_read_time,
++      .set_time = dryice_rtc_set_time,
++      .read_alarm = dryice_rtc_read_alarm,
++      .set_alarm = dryice_rtc_set_alarm,
++};
++
++/*
++ * dryice "normal" interrupt handler
++ */
++static irqreturn_t dryice_norm_irq(int irq, void *dev_id)
++{
++      struct rtc_drv_data *pdata = dev_id;
++      u32 dsr, dier;
++      irqreturn_t rc = IRQ_NONE;
++
++      dier = di_read(pdata, DIER);
++
++      /* handle write complete and write error cases */
++      if ((dier & DIER_WCIE)) {
++              /*If the write wait queue is empty then there is no pending
++                 operations. It means the interrupt is for DryIce -Security.
++                 IRQ must be returned as none.*/
++              if (list_empty_careful(&pdata->write_wait.task_list))
++                      return rc;
++
++              /* DSR_WCF clears itself on DSR read */
++          dsr = di_read(pdata, DSR);
++              if ((dsr & (DSR_WCF | DSR_WEF))) {
++                      /* mask the interrupt */
++                      di_int_disable(pdata, DIER_WCIE);
++
++                      /* save the dsr value for the wait queue */
++                      pdata->dsr |= dsr;
++
++                      wake_up_interruptible(&pdata->write_wait);
++                      rc = IRQ_HANDLED;
++              }
++      }
++
++      /* handle the alarm case */
++      if ((dier & DIER_CAIE)) {
++              /* DSR_WCF clears itself on DSR read */
++          dsr = di_read(pdata, DSR);
++              if (dsr & DSR_CAF) {
++                      /* mask the interrupt */
++                      di_int_disable(pdata, DIER_CAIE);
++
++                      /* finish alarm in user context */
++                      schedule_work(&pdata->work);
++                      rc = IRQ_HANDLED;
++              }
++      }
++      return rc;
++}
++
++/*
++ * post the alarm event from user context so it can sleep
++ * on the write completion.
++ */
++static void dryice_work(struct work_struct *work)
++{
++      struct rtc_drv_data *pdata = container_of(work, struct rtc_drv_data,
++                                                work);
++      int rc;
++
++      /* dismiss the interrupt (ignore error) */
++      di_write_wait_err(pdata, DSR_CAF, DSR, rc, err);
++err:
++      /*
++       * pass the alarm event to the rtc framework. note that
++       * rtc_update_irq expects to be called with interrupts off.
++       */
++      local_irq_disable();
++      rtc_update_irq(pdata->rtc, 1, RTC_AF | RTC_IRQF);
++      local_irq_enable();
++}
++
++/*
++ * probe for dryice rtc device
++ */
++static int dryice_rtc_probe(struct platform_device *pdev)
++{
++      struct rtc_device *rtc;
++      struct resource *res;
++      struct rtc_drv_data *pdata = NULL;
++      void __iomem *ioaddr = NULL;
++      int rc = 0;
++
++      dev_dbg(&pdev->dev, "%s\n", __func__);
++
++      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++      if (!res)
++              return -ENODEV;
++
++      pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
++      if (!pdata)
++              return -ENOMEM;
++
++      pdata->pdev = pdev;
++      pdata->irq = -1;
++      pdata->size = res->end - res->start + 1;
++
++      if (!request_mem_region(res->start, pdata->size, pdev->name)) {
++              rc = -EBUSY;
++              goto err;
++      }
++      pdata->baseaddr = res->start;
++      ioaddr = ioremap(pdata->baseaddr, pdata->size);
++      if (!ioaddr) {
++              rc = -ENOMEM;
++              goto err;
++      }
++      pdata->ioaddr = ioaddr;
++      pdata->irq = platform_get_irq(pdev, 0);
++
++      init_waitqueue_head(&pdata->write_wait);
++
++      INIT_WORK(&pdata->work, dryice_work);
++
++      mutex_init(&pdata->write_mutex);
++
++      pdata->clk = clk_get(&pdev->dev, "dryice_clk");
++      clk_enable(pdata->clk);
++
++      if (pdata->irq >= 0) {
++              if (request_irq(pdata->irq, dryice_norm_irq, IRQF_SHARED,
++                              pdev->name, pdata) < 0) {
++                      dev_warn(&pdev->dev, "interrupt not available.\n");
++                      pdata->irq = -1;
++                      goto err;
++              }
++      }
++
++      /*
++       * Initialize dryice hardware
++       */
++
++      /* put dryice into valid state */
++      if (di_read(pdata, DSR) & DSR_NVF)
++              di_write_wait_err(pdata, DSR_NVF | DSR_SVF, DSR, rc, err);
++
++      /* mask alarm interrupt */
++      di_int_disable(pdata, DIER_CAIE);
++
++      /* initialize alarm */
++      di_write_wait_err(pdata, DCAMR_UNSET, DCAMR, rc, err);
++      di_write_wait_err(pdata, 0, DCALR, rc, err);
++
++      /* clear alarm flag */
++      if (di_read(pdata, DSR) & DSR_CAF)
++              di_write_wait_err(pdata, DSR_CAF, DSR, rc, err);
++
++      /* the timer won't count if it has never been written to */
++      if (!di_read(pdata, DTCMR))
++              di_write_wait_err(pdata, 0, DTCMR, rc, err);
++
++      /* start keeping time */
++      if (!(di_read(pdata, DCR) & DCR_TCE))
++              di_write_wait_err(pdata, di_read(pdata, DCR) | DCR_TCE, DCR,
++                                rc, err);
++
++      rtc = rtc_device_register(pdev->name, &pdev->dev,
++                                &dryice_rtc_ops, THIS_MODULE);
++      if (IS_ERR(rtc)) {
++              rc = PTR_ERR(rtc);
++              goto err;
++      }
++      pdata->rtc = rtc;
++      platform_set_drvdata(pdev, pdata);
++
++      return 0;
++err:
++      if (pdata->rtc)
++              rtc_device_unregister(pdata->rtc);
++
++      if (pdata->irq >= 0)
++              free_irq(pdata->irq, pdata);
++
++      if (pdata->clk) {
++              clk_disable(pdata->clk);
++              clk_put(pdata->clk);
++      }
++
++      if (pdata->ioaddr)
++              iounmap(pdata->ioaddr);
++
++      if (pdata->baseaddr)
++              release_mem_region(pdata->baseaddr, pdata->size);
++
++      kfree(pdata);
++
++      return rc;
++}
++
++static int __exit dryice_rtc_remove(struct platform_device *pdev)
++{
++      struct rtc_drv_data *pdata = platform_get_drvdata(pdev);
++
++      flush_scheduled_work();
++
++       mutex_destroy(&pdata->write_mutex);
++
++      if (pdata->rtc)
++              rtc_device_unregister(pdata->rtc);
++
++      /* mask alarm interrupt */
++      di_int_disable(pdata, DIER_CAIE);
++
++      if (pdata->irq >= 0)
++              free_irq(pdata->irq, pdata);
++
++      if (pdata->clk) {
++              clk_disable(pdata->clk);
++              clk_put(pdata->clk);
++      }
++
++      if (pdata->ioaddr)
++              iounmap(pdata->ioaddr);
++
++      if (pdata->baseaddr)
++              release_mem_region(pdata->baseaddr, pdata->size);
++
++      kfree(pdata);
++
++      return 0;
++}
++
++static struct platform_driver dryice_rtc_driver = {
++      .driver = {
++                 .name = "imxdi_rtc",
++                 .owner = THIS_MODULE,
++                 },
++      .probe = dryice_rtc_probe,
++      .remove = __exit_p(dryice_rtc_remove),
++};
++
++static int __init dryice_rtc_init(void)
++{
++      pr_info("IMXDI Realtime Clock Driver (RTC)\n");
++      return platform_driver_register(&dryice_rtc_driver);
++}
++
++static void __exit dryice_rtc_exit(void)
++{
++      platform_driver_unregister(&dryice_rtc_driver);
++}
++
++module_init(dryice_rtc_init);
++module_exit(dryice_rtc_exit);
++
++MODULE_AUTHOR("Freescale Semiconductor, Inc.");
++MODULE_DESCRIPTION("IMXDI Realtime Clock Driver (RTC)");
++MODULE_LICENSE("GPL");
+diff -urN linux.35.old/drivers/usb/gadget/cdc2.c linux.35.new/drivers/usb/gadget/cdc2.c
+--- linux.35.old/drivers/usb/gadget/cdc2.c     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/usb/gadget/cdc2.c     2010-12-03 09:51:55.468347409 +0100
+@@ -129,7 +129,7 @@
+ /*
+  * We _always_ have both CDC ECM and CDC ACM functions.
+  */
+-static int __init cdc_do_config(struct usb_configuration *c)
++static int __ref cdc_do_config(struct usb_configuration *c)
+ {
+       int     status;
+@@ -159,7 +159,7 @@
+ /*-------------------------------------------------------------------------*/
+-static int __init cdc_bind(struct usb_composite_dev *cdev)
++static int __ref cdc_bind(struct usb_composite_dev *cdev)
+ {
+       int                     gcnum;
+       struct usb_gadget       *gadget = cdev->gadget;
+diff -urN linux.35.old/drivers/usb/gadget/ether.c linux.35.new/drivers/usb/gadget/ether.c
+--- linux.35.old/drivers/usb/gadget/ether.c    2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/usb/gadget/ether.c    2010-12-03 09:51:55.468347409 +0100
+@@ -237,7 +237,7 @@
+  * the first one present.  That's to make Microsoft's drivers happy,
+  * and to follow DOCSIS 1.0 (cable modem standard).
+  */
+-static int __init rndis_do_config(struct usb_configuration *c)
++static int __ref rndis_do_config(struct usb_configuration *c)
+ {
+       /* FIXME alloc iConfiguration string, set it in c->strings */
+@@ -270,7 +270,7 @@
+ /*
+  * We _always_ have an ECM, CDC Subset, or EEM configuration.
+  */
+-static int __init eth_do_config(struct usb_configuration *c)
++static int __ref eth_do_config(struct usb_configuration *c)
+ {
+       /* FIXME alloc iConfiguration string, set it in c->strings */
+@@ -297,7 +297,7 @@
+ /*-------------------------------------------------------------------------*/
+-static int __init eth_bind(struct usb_composite_dev *cdev)
++static int __ref eth_bind(struct usb_composite_dev *cdev)
+ {
+       int                     gcnum;
+       struct usb_gadget       *gadget = cdev->gadget;
+diff -urN linux.35.old/drivers/usb/gadget/file_storage.c linux.35.new/drivers/usb/gadget/file_storage.c
+--- linux.35.old/drivers/usb/gadget/file_storage.c     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/usb/gadget/file_storage.c     2010-12-03 09:51:55.472347889 +0100
+@@ -3278,7 +3278,7 @@
+ }
+-static int __init fsg_bind(struct usb_gadget *gadget)
++static int __ref fsg_bind(struct usb_gadget *gadget)
+ {
+       struct fsg_dev          *fsg = the_fsg;
+       int                     rc;
+diff -urN linux.35.old/drivers/usb/gadget/f_loopback.c linux.35.new/drivers/usb/gadget/f_loopback.c
+--- linux.35.old/drivers/usb/gadget/f_loopback.c       2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/usb/gadget/f_loopback.c       2010-12-03 09:51:55.472347889 +0100
+@@ -324,7 +324,7 @@
+ /*-------------------------------------------------------------------------*/
+-static int __init loopback_bind_config(struct usb_configuration *c)
++static int __ref loopback_bind_config(struct usb_configuration *c)
+ {
+       struct f_loopback       *loop;
+       int                     status;
+@@ -346,7 +346,7 @@
+       return status;
+ }
+-static struct usb_configuration loopback_driver = {
++static  struct usb_configuration loopback_driver = {
+       .label          = "loopback",
+       .strings        = loopback_strings,
+       .bind           = loopback_bind_config,
+diff -urN linux.35.old/drivers/usb/gadget/fsl_mxc_udc.c linux.35.new/drivers/usb/gadget/fsl_mxc_udc.c
+--- linux.35.old/drivers/usb/gadget/fsl_mxc_udc.c      2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/usb/gadget/fsl_mxc_udc.c      2010-12-03 09:51:55.472347889 +0100
+@@ -30,7 +30,7 @@
+       pdata = pdev->dev.platform_data;
+-      if (!cpu_is_mx35()) {
++      if (!cpu_is_mx35() && !cpu_is_mx25()) {
+               mxc_ahb_clk = clk_get(&pdev->dev, "usb_ahb");
+               if (IS_ERR(mxc_ahb_clk))
+                       return PTR_ERR(mxc_ahb_clk);
+diff -urN linux.35.old/drivers/usb/gadget/f_sourcesink.c linux.35.new/drivers/usb/gadget/f_sourcesink.c
+--- linux.35.old/drivers/usb/gadget/f_sourcesink.c     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/usb/gadget/f_sourcesink.c     2010-12-03 09:51:55.476349329 +0100
+@@ -404,7 +404,7 @@
+ /*-------------------------------------------------------------------------*/
+-static int __init sourcesink_bind_config(struct usb_configuration *c)
++static int __ref sourcesink_bind_config(struct usb_configuration *c)
+ {
+       struct f_sourcesink     *ss;
+       int                     status;
+diff -urN linux.35.old/drivers/usb/gadget/serial.c linux.35.new/drivers/usb/gadget/serial.c
+--- linux.35.old/drivers/usb/gadget/serial.c   2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/usb/gadget/serial.c   2010-12-03 09:51:55.476349329 +0100
+@@ -137,7 +137,7 @@
+ /*-------------------------------------------------------------------------*/
+-static int __init serial_bind_config(struct usb_configuration *c)
++static int __ref serial_bind_config(struct usb_configuration *c)
+ {
+       unsigned i;
+       int status = 0;
+@@ -161,7 +161,7 @@
+       .bmAttributes   = USB_CONFIG_ATT_SELFPOWER,
+ };
+-static int __init gs_bind(struct usb_composite_dev *cdev)
++static int __ref gs_bind(struct usb_composite_dev *cdev)
+ {
+       int                     gcnum;
+       struct usb_gadget       *gadget = cdev->gadget;
+diff -urN linux.35.old/drivers/usb/gadget/zero.c linux.35.new/drivers/usb/gadget/zero.c
+--- linux.35.old/drivers/usb/gadget/zero.c     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/usb/gadget/zero.c     2010-12-03 09:51:55.476349329 +0100
+@@ -264,7 +264,7 @@
+ /*-------------------------------------------------------------------------*/
+-static int __init zero_bind(struct usb_composite_dev *cdev)
++static int __ref zero_bind(struct usb_composite_dev *cdev)
+ {
+       int                     gcnum;
+       struct usb_gadget       *gadget = cdev->gadget;
+diff -urN linux.35.old/drivers/usb/host/ehci-mxc.c linux.35.new/drivers/usb/host/ehci-mxc.c
+--- linux.35.old/drivers/usb/host/ehci-mxc.c   2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/usb/host/ehci-mxc.c   2010-12-03 09:51:55.476349329 +0100
+@@ -182,7 +182,7 @@
+       }
+       clk_enable(priv->usbclk);
+-      if (!cpu_is_mx35()) {
++      if (!cpu_is_mx35() && !cpu_is_mx25()) {
+               priv->ahbclk = clk_get(dev, "usb_ahb");
+               if (IS_ERR(priv->ahbclk)) {
+                       ret = PTR_ERR(priv->ahbclk);
+diff -urN linux.35.old/drivers/video/imxfb.c linux.35.new/drivers/video/imxfb.c
+--- linux.35.old/drivers/video/imxfb.c 2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/drivers/video/imxfb.c 2011-01-12 13:27:37.613989923 +0100
+@@ -235,12 +235,13 @@
+ {
+       struct imxfb_info *fbi = info->par;
+       u_int val, ret = 1;
++      int bits = cpu_is_mx1() ? 4 : 6;
+ #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, bits) << 2 * bits) |
++                              (CNVT_TOHW(green, bits) << bits) |
++                              CNVT_TOHW(blue,  bits);
+               writel(val, fbi->regs + 0x800 + (regno << 2));
+               ret = 0;
+@@ -507,6 +508,19 @@
+       return 0;
+ }
++static int imxfb_pan_display(struct fb_var_screeninfo *var,
++                             struct fb_info *info)
++{
++      struct imxfb_info *fbi = info->par;
++
++      pr_debug("var: xoffset=%d, yoffset=%d, vmode=%d\n", 
++              var->xoffset, var->yoffset, var->vmode);
++      
++      writel( fbi->screen_dma + var->xres * var->yoffset * var->bits_per_pixel/8, fbi->regs + LCDC_SSA);
++
++      return 0;
++}
++
+ static struct fb_ops imxfb_ops = {
+       .owner          = THIS_MODULE,
+       .fb_check_var   = imxfb_check_var,
+@@ -516,6 +530,7 @@
+       .fb_copyarea    = cfb_copyarea,
+       .fb_imageblit   = cfb_imageblit,
+       .fb_blank       = imxfb_blank,
++      .fb_pan_display = imxfb_pan_display,
+ };
+ /*
+@@ -533,6 +548,8 @@
+       pr_debug("var: yres=%d vslen=%d um=%d bm=%d\n",
+               var->yres, var->vsync_len,
+               var->upper_margin, var->lower_margin);
++      pr_debug("var: xres_virtual=%d yres_virtual=%d\n",
++              var->xres_virtual, var->yres_virtual);
+ #if DEBUG_VAR
+       if (var->xres < 16        || var->xres > 1024)
+@@ -638,14 +655,14 @@
+       info->fix.type                  = FB_TYPE_PACKED_PIXELS;
+       info->fix.type_aux              = 0;
+       info->fix.xpanstep              = 0;
+-      info->fix.ypanstep              = 0;
++      info->fix.ypanstep              = 1;
+       info->fix.ywrapstep             = 0;
+       info->fix.accel                 = FB_ACCEL_NONE;
+       info->var.nonstd                = 0;
+       info->var.activate              = FB_ACTIVATE_NOW;
+       info->var.height                = -1;
+-      info->var.width = -1;
++      info->var.width                 = -1;
+       info->var.accel_flags           = 0;
+       info->var.vmode                 = FB_VMODE_NONINTERLACED;
+@@ -663,7 +680,7 @@
+       for (i = 0, m = &pdata->mode[0]; i < pdata->num_modes; i++, m++)
+               info->fix.smem_len = max_t(size_t, info->fix.smem_len,
+-                              m->mode.xres * m->mode.yres * m->bpp / 8);
++                              m->mode.xres * 2 * m->mode.yres * m->bpp / 8);
+       return 0;
+ }
+@@ -765,7 +782,11 @@
+        * This makes sure that our colour bitfield
+        * descriptors are correctly initialised.
+        */
+-      imxfb_check_var(&info->var, info);
++      ret = imxfb_check_var(&info->var, info);
++      if (ret < 0) {
++              dev_err(&pdev->dev, "failed to find framebuffer mode\n");
++              goto failed_cmap;
++      }
+       ret = fb_alloc_cmap(&info->cmap, 1 << info->var.bits_per_pixel, 0);
+       if (ret < 0)
+diff -urN linux.35.old/include/asm-generic/int-ll64.h linux.35.new/include/asm-generic/int-ll64.h
+--- linux.35.old/include/asm-generic/int-ll64.h        2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/include/asm-generic/int-ll64.h        2010-12-03 09:51:55.480350013 +0100
+@@ -8,7 +8,7 @@
+ #ifndef _ASM_GENERIC_INT_LL64_H
+ #define _ASM_GENERIC_INT_LL64_H
+-#include <asm/bitsperlong.h>
++#include <asm-generic/bitsperlong.h>
+ #ifndef __ASSEMBLY__
+ /*
+diff -urN linux.35.old/include/linux/can/platform/flexcan.h linux.35.new/include/linux/can/platform/flexcan.h
+--- linux.35.old/include/linux/can/platform/flexcan.h  1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/include/linux/can/platform/flexcan.h  2010-12-03 09:51:55.480350013 +0100
+@@ -0,0 +1,20 @@
++/*
++ * Copyright (C) 2010 Marc Kleine-Budde <kernel@pengutronix.de>
++ *
++ * This file is released under the GPLv2
++ *
++ */
++
++#ifndef __CAN_PLATFORM_FLEXCAN_H
++#define __CAN_PLATFORM_FLEXCAN_H
++
++/**
++ * struct flexcan_platform_data - flex CAN controller platform data
++ * @transceiver_enable:         - called to power on/off the transceiver
++ *
++ */
++struct flexcan_platform_data {
++      void (*transceiver_switch)(int enable);
++};
++
++#endif /* __CAN_PLATFORM_FLEXCAN_H */
+diff -urN linux.35.old/include/linux/imx_adc.h linux.35.new/include/linux/imx_adc.h
+--- linux.35.old/include/linux/imx_adc.h       1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/include/linux/imx_adc.h       2010-12-03 09:51:55.480350013 +0100
+@@ -0,0 +1,275 @@
++/*
++ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
++ */
++
++/*
++ * The code contained herein is licensed under the GNU Lesser General
++ * Public License.  You may obtain a copy of the GNU Lesser General
++ * Public License Version 2.1 or later at the following locations:
++ *
++ * http://www.opensource.org/licenses/lgpl-license.html
++ * http://www.gnu.org/copyleft/lgpl.html
++ */
++
++#ifndef __ASM_ARCH_IMX_ADC_H__
++#define __ASM_ARCH_IMX_ADC_H__
++
++/*!
++ * @defgroup IMX_ADC Digitizer Driver
++ * @ingroup IMX_DRVRS
++ */
++
++/*!
++ * @file arch-mxc/imx_adc.h
++ * @brief This is the header of IMX ADC driver.
++ *
++ * @ingroup IMX_ADC
++ */
++
++#include <linux/ioctl.h>
++
++/*!
++ * @enum IMX_ADC_STATUS
++ * @brief Define return values for all IMX_ADC APIs.
++ *
++ * These return values are used by all of the IMX_ADC APIs.
++ *
++ * @ingroup IMX_ADC
++ */
++enum IMX_ADC_STATUS {
++      /*! The requested operation was successfully completed. */
++      IMX_ADC_SUCCESS = 0,
++      /*! The requested operation could not be completed due to an error. */
++      IMX_ADC_ERROR = -1,
++      /*!
++       * The requested operation failed because one or more of the
++       * parameters was invalid.
++       */
++      IMX_ADC_PARAMETER_ERROR = -2,
++      /*!
++       * The requested operation could not be completed because the ADC
++       * hardware does not support it.
++       */
++      IMX_ADC_NOT_SUPPORTED = -3,
++      /*! Error in malloc function */
++      IMX_ADC_MALLOC_ERROR = -5,
++      /*! Error in un-subscribe event */
++      IMX_ADC_UNSUBSCRIBE_ERROR = -6,
++      /*! Event occur and not subscribed */
++      IMX_ADC_EVENT_NOT_SUBSCRIBED = -7,
++      /*! Error - bad call back */
++      IMX_ADC_EVENT_CALL_BACK = -8,
++      /*!
++       * The requested operation could not be completed because there
++       * are too many ADC client requests
++       */
++      IMX_ADC_CLIENT_NBOVERFLOW = -9,
++};
++
++/*
++ * Macros implementing error handling
++ */
++#define CHECK_ERROR(a)                        \
++do {                                  \
++              int ret = (a);                  \
++              if (ret != IMX_ADC_SUCCESS)     \
++      return ret;                     \
++} while (0)
++
++#define CHECK_ERROR_KFREE(func, freeptrs) \
++do { \
++      int ret = (func); \
++      if (ret != IMX_ADC_SUCCESS) { \
++              freeptrs;       \
++              return ret;     \
++      }       \
++} while (0)
++
++#define MOD_NAME  "mxcadc"
++
++/*!
++ * @name IOCTL user space interface
++ */
++
++/*!
++ * Initialize ADC.
++ * Argument type: none.
++ */
++#define IMX_ADC_INIT                   _IO('p', 0xb0)
++/*!
++ * De-initialize ADC.
++ * Argument type: none.
++ */
++#define IMX_ADC_DEINIT                 _IO('p', 0xb1)
++/*!
++ * Convert one channel.
++ * Argument type: pointer to t_adc_convert_param.
++ */
++#define IMX_ADC_CONVERT                _IOWR('p', 0xb2, int)
++/*!
++ * Convert multiple channels.
++ * Argument type: pointer to t_adc_convert_param.
++ */
++#define IMX_ADC_CONVERT_MULTICHANNEL   _IOWR('p', 0xb4, int)
++
++/*! @{ */
++/*!
++ * @name Touch Screen minimum and maximum values
++ */
++#define IMX_ADC_DEVICE "/dev/imx_adc"
++
++/*
++ * Maximun allowed variation in the three X/Y co-ordinates acquired from
++ * touch screen
++ */
++#define DELTA_Y_MAX             100
++#define DELTA_X_MAX             100
++
++/* Upon clearing the filter, this is the delay in restarting the filter */
++#define FILTER_MIN_DELAY        4
++
++/* Length of X and Y touch screen filters */
++#define FILTLEN                 3
++
++#define TS_X_MAX                1000
++#define TS_Y_MAX                1000
++
++#define TS_X_MIN                80
++#define TS_Y_MIN                80
++
++/*! @} */
++/*!
++ * This enumeration defines input channels for IMX ADC
++ */
++
++enum t_channel {
++      TS_X_POS,
++      TS_Y_POS,
++      GER_PURPOSE_ADC0,
++      GER_PURPOSE_ADC1,
++      GER_PURPOSE_ADC2,
++      GER_PURPOSE_MULTICHNNEL,
++};
++
++/*!
++ * This structure is used to report touch screen value.
++ */
++struct t_touch_screen {
++      /* Touch Screen X position */
++      unsigned int x_position;
++      /* Touch Screen X position1 */
++      unsigned int x_position1;
++      /* Touch Screen X position2 */
++      unsigned int x_position2;
++      /* Touch Screen X position3 */
++      unsigned int x_position3;
++      /* Touch Screen Y position */
++      unsigned int y_position;
++      /* Touch Screen Y position1 */
++      unsigned int y_position1;
++      /* Touch Screen Y position2 */
++      unsigned int y_position2;
++      /* Touch Screen Y position3 */
++      unsigned int y_position3;
++      /* Touch Screen contact value */
++      unsigned int contact_resistance;
++      /* Flag indicate the data usability */
++      unsigned int valid_flag;
++};
++
++/*!
++ * This structure is used with IOCTL code \a IMX_ADC_CONVERT,
++ * \a IMX_ADC_CONVERT_8X and \a IMX_ADC_CONVERT_MULTICHANNEL.
++ */
++
++struct t_adc_convert_param {
++      /* channel or channels to be sampled.  */
++      enum t_channel channel;
++      /* holds up to 16 sampling results */
++      unsigned short result[16];
++};
++
++/* EXPORTED FUNCTIONS */
++
++#ifdef __KERNEL__
++/* Driver data */
++struct imx_adc_data {
++      u32 irq;
++      struct clk *adc_clk;
++};
++
++/*!
++ * This function initializes all ADC registers with default values. This
++ * function also registers the interrupt events.
++ *
++ * @return       This function returns IMX_ADC_SUCCESS if successful.
++ */
++enum IMX_ADC_STATUS imx_adc_init(void);
++
++/*!
++ * This function disables the ADC, de-registers the interrupt events.
++ *
++ * @return       This function returns IMX_ADC_SUCCESS if successful.
++ */
++enum IMX_ADC_STATUS imx_adc_deinit(void);
++
++/*!
++ * This function triggers a conversion and returns one sampling result of one
++ * channel.
++ *
++ * @param        channel   The channel to be sampled
++ * @param        result    The pointer to the conversion result. The memory
++ *                         should be allocated by the caller of this function.
++ *
++ * @return       This function returns IMX_ADC_SUCCESS if successful.
++ */
++
++enum IMX_ADC_STATUS imx_adc_convert(enum t_channel channel,
++                                  unsigned short *result);
++
++/*!
++ * This function triggers a conversion and returns sampling results of each
++ * specified channel.
++ *
++ * @param        channels  This input parameter is bitmap to specify channels
++ *                         to be sampled.
++ * @param        result    The pointer to array to store sampling result.
++ *                         The order of the result in the array is from lowest
++ *                         channel number to highest channel number of the
++ *                         sampled channels.
++ *                         The memory should be allocated by the caller of this
++ *                         function.
++ *                       Note that the behavior of this function might differ
++ *                       from one platform to another regarding especially
++ *                       channels order.
++ *
++ * @return       This function returns IMX_ADC_SUCCESS if successful.
++ */
++
++enum IMX_ADC_STATUS imx_adc_convert_multichnnel(enum t_channel channels,
++                                              unsigned short *result);
++
++/*!
++ * This function retrieves the current touch screen operation mode.
++ *
++ * @param        touch_sample Pointer to touch sample.
++ * @param        wait_tsi     if true, we wait until interrupt occurs
++ * @return       This function returns IMX_ADC_SUCCESS if successful.
++ */
++enum IMX_ADC_STATUS imx_adc_get_touch_sample(struct t_touch_screen *ts_value,
++                                           int wait_tsi);
++
++/*!
++ * This function read the touch screen value.
++ *
++ * @param        touch_sample    return value of touch screen
++ * @param        wait_tsi        if true, we need wait until interrupt occurs
++ * @return       This function returns 0.
++ */
++enum IMX_ADC_STATUS imx_adc_read_ts(struct t_touch_screen *touch_sample,
++                                  int wait_tsi);
++
++int is_imx_adc_ready(void);
++
++#endif                                /* _KERNEL */
++#endif                                /* __ASM_ARCH_IMX_ADC_H__ */
+diff -urN linux.35.old/include/linux/netdevice.h linux.35.new/include/linux/netdevice.h
+--- linux.35.old/include/linux/netdevice.h     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/include/linux/netdevice.h     2010-12-03 09:51:55.484347691 +0100
+@@ -54,6 +54,7 @@
+ struct vlan_group;
+ struct netpoll_info;
++struct phy_device;
+ /* 802.11 specific */
+ struct wireless_dev;
+                                       /* source back-compat hooks */
+@@ -1057,6 +1058,9 @@
+ #endif
+       /* n-tuple filter list attached to this device */
+       struct ethtool_rx_ntuple_list ethtool_ntuple_list;
++
++      /* phy device may attach itself for hardware timestamping */
++      struct phy_device *phydev;
+ };
+ #define to_net_dev(d) container_of(d, struct net_device, dev)
+diff -urN linux.35.old/include/linux/phy.h linux.35.new/include/linux/phy.h
+--- linux.35.old/include/linux/phy.h   2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/include/linux/phy.h   2010-12-03 09:51:55.484347691 +0100
+@@ -234,6 +234,8 @@
+       PHY_RESUMING
+ };
++struct sk_buff;
++
+ /* phy_device: An instance of a PHY
+  *
+  * drv: Pointer to the driver for this PHY instance
+@@ -402,6 +404,26 @@
+       /* Clears up any memory if needed */
+       void (*remove)(struct phy_device *phydev);
++      /* Handles SIOCSHWTSTAMP ioctl for hardware time stamping. */
++      int  (*hwtstamp)(struct phy_device *phydev, struct ifreq *ifr);
++
++      /*
++       * Requests a Rx timestamp for 'skb'. If the skb is accepted,
++       * the phy driver promises to deliver it using netif_rx() as
++       * soon as a timestamp becomes available. One of the
++       * PTP_CLASS_ values is passed in 'type'. The function must
++       * return true if the skb is accepted for delivery.
++       */
++      bool (*rxtstamp)(struct phy_device *dev, struct sk_buff *skb, int type);
++
++      /*
++       * Requests a Tx timestamp for 'skb'. The phy driver promises
++       * to deliver it to the socket's error queue as soon as a
++       * timestamp becomes available. One of the PTP_CLASS_ values
++       * is passed in 'type'.
++       */
++      void (*txtstamp)(struct phy_device *dev, struct sk_buff *skb, int type);
++
+       struct device_driver driver;
+ };
+ #define to_phy_driver(d) container_of(d, struct phy_driver, driver)
+@@ -498,7 +520,7 @@
+ int phy_ethtool_sset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+ int phy_ethtool_gset(struct phy_device *phydev, struct ethtool_cmd *cmd);
+ int phy_mii_ioctl(struct phy_device *phydev,
+-              struct mii_ioctl_data *mii_data, int cmd);
++              struct ifreq *ifr, int cmd);
+ int phy_start_interrupts(struct phy_device *phydev);
+ void phy_print_status(struct phy_device *phydev);
+ struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id);
+diff -urN linux.35.old/sound/soc/codecs/Kconfig linux.35.new/sound/soc/codecs/Kconfig
+--- linux.35.old/sound/soc/codecs/Kconfig      2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/sound/soc/codecs/Kconfig      2010-12-03 09:51:55.484347691 +0100
+@@ -269,6 +269,10 @@
+ config SND_SOC_WM9713
+       tristate
++config SND_SOC_SGTL5000
++      tristate
++      depends on I2C
++
+ # Amp
+ config SND_SOC_MAX9877
+       tristate
+diff -urN linux.35.old/sound/soc/codecs/Makefile linux.35.new/sound/soc/codecs/Makefile
+--- linux.35.old/sound/soc/codecs/Makefile     2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/sound/soc/codecs/Makefile     2010-12-03 09:51:55.484347691 +0100
+@@ -56,6 +56,7 @@
+ snd-soc-wm9712-objs := wm9712.o
+ snd-soc-wm9713-objs := wm9713.o
+ snd-soc-wm-hubs-objs := wm_hubs.o
++snd-soc-sgtl5000-objs := sgtl5000.o
+ # Amp
+ snd-soc-max9877-objs := max9877.o
+@@ -121,6 +122,7 @@
+ obj-$(CONFIG_SND_SOC_WM9712)  += snd-soc-wm9712.o
+ obj-$(CONFIG_SND_SOC_WM9713)  += snd-soc-wm9713.o
+ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
++obj-$(CONFIG_SND_SOC_SGTL5000)        += snd-soc-sgtl5000.o
+ # Amp
+ obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
+diff -urN linux.35.old/sound/soc/codecs/sgtl5000.c linux.35.new/sound/soc/codecs/sgtl5000.c
+--- linux.35.old/sound/soc/codecs/sgtl5000.c   1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/sound/soc/codecs/sgtl5000.c   2011-01-05 09:37:51.655096053 +0100
+@@ -0,0 +1,1263 @@
++/*
++ * sgtl5000.c  --  SGTL5000 ALSA SoC Audio driver
++ *
++ * Copyright 2008-2010 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.
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/i2c.h>
++#include <linux/clk.h>
++#include <linux/platform_device.h>
++#include <linux/regulator/consumer.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++#include <sound/initval.h>
++#include <mach/hardware.h>
++#include <linux/slab.h>
++
++#include "sgtl5000.h"
++
++#include <linux/jiffies.h>
++/* I2C code related */
++static unsigned i2c_timeout = 250;
++
++struct sgtl5000_priv {
++      int sysclk;
++      int master;
++      int fmt;
++      int rev;
++      int lrclk;
++      int capture_channels;
++      int playback_active;
++      int capture_active;
++      struct snd_pcm_substream *master_substream;
++      struct snd_pcm_substream *slave_substream;
++};
++
++static int sgtl5000_set_bias_level(struct snd_soc_codec *codec,
++                                 enum snd_soc_bias_level level);
++
++#define SGTL5000_MAX_CACHED_REG SGTL5000_CHIP_SHORT_CTRL
++static u16 sgtl5000_regs[(SGTL5000_MAX_CACHED_REG >> 1) + 1];
++
++static unsigned int sgtl5000_read_reg_cache(struct snd_soc_codec *codec,
++                                          unsigned int reg)
++{
++      u16 *cache = codec->reg_cache;
++      unsigned int offset = reg >> 1;
++      if (offset >= ARRAY_SIZE(sgtl5000_regs))
++              return -EINVAL;
++      pr_debug("r r:%02x,v:%04x\n", reg, cache[offset]);
++      return cache[offset];
++}
++
++static unsigned int sgtl5000_hw_read(struct snd_soc_codec *codec,
++                                   unsigned int reg)
++{
++      struct i2c_client *client = codec->control_data;
++      int i2c_ret;
++      u16 value;
++      u8 buf0[2], buf1[2];
++      u16 addr = client->addr;
++      u16 flags = client->flags;
++      struct i2c_msg msg[2] = {
++              {addr, flags, 2, buf0},
++              {addr, flags | I2C_M_RD, 2, buf1},
++      };
++      unsigned long timeout, read_time;
++
++      buf0[0] = (reg & 0xff00) >> 8;
++      buf0[1] = reg & 0xff;
++
++      timeout = jiffies + msecs_to_jiffies(i2c_timeout);
++      do {
++              read_time = jiffies;
++              i2c_ret = i2c_transfer(client->adapter, msg, 2);
++              // REVISIT: at HZ=100, this is sloooow
++              msleep(1);
++      } while (time_before(read_time, timeout) && i2c_ret != 2);
++
++      if (i2c_ret < 0) {
++              pr_err("%s: read reg error : Reg 0x%02x\n", __func__, reg);
++              return 0;
++      }
++
++      value = buf1[0] << 8 | buf1[1];
++
++      pr_debug("r r:%02x,v:%04x\n", reg, value);
++      return value;
++}
++
++static unsigned int sgtl5000_read(struct snd_soc_codec *codec, unsigned int reg)
++{
++      if ((reg == SGTL5000_CHIP_ID) ||
++          (reg == SGTL5000_CHIP_ADCDAC_CTRL) ||
++          (reg == SGTL5000_CHIP_ANA_STATUS) ||
++          (reg > SGTL5000_MAX_CACHED_REG))
++              return sgtl5000_hw_read(codec, reg);
++      else
++              return sgtl5000_read_reg_cache(codec, reg);
++}
++
++static inline void sgtl5000_write_reg_cache(struct snd_soc_codec *codec,
++                                          u16 reg, unsigned int value)
++{
++      u16 *cache = codec->reg_cache;
++      unsigned int offset = reg >> 1;
++      if (offset < ARRAY_SIZE(sgtl5000_regs))
++              cache[offset] = value;
++}
++
++static int sgtl5000_write(struct snd_soc_codec *codec, unsigned int reg,
++                        unsigned int value)
++{
++      struct i2c_client *client = codec->control_data;
++      u16 addr = client->addr;
++      u16 flags = client->flags;
++      u8 buf[4];
++      int i2c_ret;
++      struct i2c_msg msg = { addr, flags, 4, buf };
++      unsigned long timeout, read_time;
++
++      sgtl5000_write_reg_cache(codec, reg, value);
++      pr_debug("w r:%02x,v:%04x\n", reg, value);
++      buf[0] = (reg & 0xff00) >> 8;
++      buf[1] = reg & 0xff;
++      buf[2] = (value & 0xff00) >> 8;
++      buf[3] = value & 0xff;
++
++      timeout = jiffies + msecs_to_jiffies(i2c_timeout);
++      do {
++              read_time = jiffies;
++              i2c_ret = i2c_transfer(client->adapter, &msg, 1);
++              // REVISIT: at HZ=100, this is sloooow
++              msleep(1);
++      } while (time_before(read_time, timeout) && i2c_ret != 1);
++
++      if (i2c_ret < 0) {
++              pr_err("%s: write reg error : Reg 0x%02x = 0x%04x\n",
++                     __func__, reg, value);
++              return -EIO;
++      }
++
++      return i2c_ret;
++}
++
++static void sgtl5000_sync_reg_cache(struct snd_soc_codec *codec)
++{
++      int reg;
++      for (reg = 0; reg <= SGTL5000_MAX_CACHED_REG; reg += 2)
++              sgtl5000_write_reg_cache(codec, reg,
++                                       sgtl5000_hw_read(codec, reg));
++}
++
++static int sgtl5000_restore_reg(struct snd_soc_codec *codec, unsigned int reg)
++{
++      unsigned int cached_val, hw_val;
++
++      cached_val = sgtl5000_read_reg_cache(codec, reg);
++      hw_val = sgtl5000_hw_read(codec, reg);
++
++      if (hw_val != cached_val)
++              return sgtl5000_write(codec, reg, cached_val);
++
++      return 0;
++}
++
++static int all_reg[] = {
++      SGTL5000_CHIP_ID,
++      SGTL5000_CHIP_DIG_POWER,
++      SGTL5000_CHIP_CLK_CTRL,
++      SGTL5000_CHIP_I2S_CTRL,
++      SGTL5000_CHIP_SSS_CTRL,
++      SGTL5000_CHIP_ADCDAC_CTRL,
++      SGTL5000_CHIP_DAC_VOL,
++      SGTL5000_CHIP_PAD_STRENGTH,
++      SGTL5000_CHIP_ANA_ADC_CTRL,
++      SGTL5000_CHIP_ANA_HP_CTRL,
++      SGTL5000_CHIP_ANA_CTRL,
++      SGTL5000_CHIP_LINREG_CTRL,
++      SGTL5000_CHIP_REF_CTRL,
++      SGTL5000_CHIP_MIC_CTRL,
++      SGTL5000_CHIP_LINE_OUT_CTRL,
++      SGTL5000_CHIP_LINE_OUT_VOL,
++      SGTL5000_CHIP_ANA_POWER,
++      SGTL5000_CHIP_PLL_CTRL,
++      SGTL5000_CHIP_CLK_TOP_CTRL,
++      SGTL5000_CHIP_ANA_STATUS,
++      SGTL5000_CHIP_SHORT_CTRL,
++};
++
++#ifdef DEBUG
++static void dump_reg(struct snd_soc_codec *codec)
++{
++      int i, reg;
++      printk(KERN_DEBUG "dump begin\n");
++      for (i = 0; i < 21; i++) {
++              reg = sgtl5000_read(codec, all_reg[i]);
++              printk(KERN_DEBUG "d r %04x, v %04x\n", all_reg[i], reg);
++      }
++      printk(KERN_DEBUG "dump end\n");
++}
++#else
++static void dump_reg(struct snd_soc_codec *codec)
++{
++}
++#endif
++
++static int dac_mux_put(struct snd_kcontrol *kcontrol,
++                     struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
++      struct snd_soc_codec *codec = widget->codec;
++      unsigned int reg;
++
++      if (ucontrol->value.enumerated.item[0]) {
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_CLK_TOP_CTRL);
++              reg |= SGTL5000_INT_OSC_EN;
++              sgtl5000_write(codec, SGTL5000_CHIP_CLK_TOP_CTRL, reg);
++
++              if (codec->bias_level != SND_SOC_BIAS_ON) {
++                      sgtl5000_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
++                      snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
++                      sgtl5000_set_bias_level(codec, SND_SOC_BIAS_ON);
++              } else
++                      snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
++
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_ANA_CTRL);
++              reg &= ~(SGTL5000_LINE_OUT_MUTE | SGTL5000_HP_MUTE);
++              sgtl5000_write(codec, SGTL5000_CHIP_ANA_CTRL, reg);
++      } else {
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_CLK_TOP_CTRL);
++              reg &= ~SGTL5000_INT_OSC_EN;
++              sgtl5000_write(codec, SGTL5000_CHIP_CLK_TOP_CTRL, reg);
++
++              snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
++              sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
++      }
++      return 0;
++}
++
++static const char *adc_mux_text[] = {
++      "MIC_IN", "LINE_IN"
++};
++
++static const char *dac_mux_text[] = {
++      "DAC", "LINE_IN"
++};
++
++static const struct soc_enum adc_enum =
++SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 2, 2, adc_mux_text);
++
++static const struct soc_enum dac_enum =
++SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_CTRL, 6, 2, dac_mux_text);
++
++static const struct snd_kcontrol_new adc_mux =
++SOC_DAPM_ENUM("ADC Mux", adc_enum);
++
++static const struct snd_kcontrol_new dac_mux = {
++      .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++      .name = "DAC Mux",
++      .access = SNDRV_CTL_ELEM_ACCESS_READWRITE
++          | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++      .info = snd_soc_info_enum_double,
++      .get = snd_soc_dapm_get_enum_double,
++      .put = dac_mux_put,
++      .private_value = (unsigned long)&dac_enum,
++};
++
++static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
++      SND_SOC_DAPM_INPUT("LINE_IN"),
++      SND_SOC_DAPM_INPUT("MIC_IN"),
++
++      SND_SOC_DAPM_OUTPUT("HP_OUT"),
++      SND_SOC_DAPM_OUTPUT("LINE_OUT"),
++
++      SND_SOC_DAPM_PGA("HP", SGTL5000_CHIP_ANA_CTRL, 4, 1, NULL, 0),
++      SND_SOC_DAPM_PGA("LO", SGTL5000_CHIP_ANA_CTRL, 8, 1, NULL, 0),
++
++      SND_SOC_DAPM_MUX("ADC Mux", SND_SOC_NOPM, 0, 0, &adc_mux),
++      SND_SOC_DAPM_MUX("DAC Mux", SND_SOC_NOPM, 0, 0, &dac_mux),
++
++      SND_SOC_DAPM_ADC("ADC", "Capture", SGTL5000_CHIP_DIG_POWER, 6, 0),
++      SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0),
++};
++
++static const struct snd_soc_dapm_route audio_map[] = {
++      {"ADC Mux", "LINE_IN", "LINE_IN"},
++      {"ADC Mux", "MIC_IN", "MIC_IN"},
++      {"ADC", NULL, "ADC Mux"},
++      {"DAC Mux", "DAC", "DAC"},
++      {"DAC Mux", "LINE_IN", "LINE_IN"},
++      {"LO", NULL, "DAC"},
++      {"HP", NULL, "DAC Mux"},
++      {"LINE_OUT", NULL, "LO"},
++      {"HP_OUT", NULL, "HP"},
++};
++
++static int sgtl5000_add_widgets(struct snd_soc_codec *codec)
++{
++      snd_soc_dapm_new_controls(codec, sgtl5000_dapm_widgets,
++                                ARRAY_SIZE(sgtl5000_dapm_widgets));
++
++      snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
++
++      snd_soc_dapm_new_widgets(codec);
++      return 0;
++}
++
++static int dac_info_volsw(struct snd_kcontrol *kcontrol,
++                        struct snd_ctl_elem_info *uinfo)
++{
++      uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
++      uinfo->count = 2;
++      uinfo->value.integer.min = 0;
++      uinfo->value.integer.max = 0xfc - 0x3c;
++      return 0;
++}
++
++static int dac_get_volsw(struct snd_kcontrol *kcontrol,
++                       struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++      int reg, l, r;
++
++      reg = sgtl5000_read(codec, SGTL5000_CHIP_DAC_VOL);
++      l = (reg & SGTL5000_DAC_VOL_LEFT_MASK) >> SGTL5000_DAC_VOL_LEFT_SHIFT;
++      r = (reg & SGTL5000_DAC_VOL_RIGHT_MASK) >> SGTL5000_DAC_VOL_RIGHT_SHIFT;
++      l = l < 0x3c ? 0x3c : l;
++      l = l > 0xfc ? 0xfc : l;
++      r = r < 0x3c ? 0x3c : r;
++      r = r > 0xfc ? 0xfc : r;
++      l = 0xfc - l;
++      r = 0xfc - r;
++
++      ucontrol->value.integer.value[0] = l;
++      ucontrol->value.integer.value[1] = r;
++
++      return 0;
++}
++
++static int dac_put_volsw(struct snd_kcontrol *kcontrol,
++                       struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++      int reg, l, r;
++
++      l = ucontrol->value.integer.value[0];
++      r = ucontrol->value.integer.value[1];
++
++      l = l < 0 ? 0 : l;
++      l = l > 0xfc - 0x3c ? 0xfc - 0x3c : l;
++      r = r < 0 ? 0 : r;
++      r = r > 0xfc - 0x3c ? 0xfc - 0x3c : r;
++      l = 0xfc - l;
++      r = 0xfc - r;
++
++      reg = l << SGTL5000_DAC_VOL_LEFT_SHIFT |
++          r << SGTL5000_DAC_VOL_RIGHT_SHIFT;
++
++      sgtl5000_write(codec, SGTL5000_CHIP_DAC_VOL, reg);
++
++      return 0;
++}
++
++static const char *mic_gain_text[] = {
++      "0dB", "20dB", "30dB", "40dB"
++};
++
++static const char *adc_m6db_text[] = {
++      "No Change", "Reduced by 6dB"
++};
++
++static const struct soc_enum mic_gain =
++SOC_ENUM_SINGLE(SGTL5000_CHIP_MIC_CTRL, 0, 4, mic_gain_text);
++
++static const struct soc_enum adc_m6db =
++SOC_ENUM_SINGLE(SGTL5000_CHIP_ANA_ADC_CTRL, 8, 2, adc_m6db_text);
++
++static const struct snd_kcontrol_new sgtl5000_snd_controls[] = {
++      SOC_ENUM("MIC GAIN", mic_gain),
++      SOC_DOUBLE("Capture Volume", SGTL5000_CHIP_ANA_ADC_CTRL, 0, 4, 0xf, 0),
++      SOC_ENUM("Capture Vol Reduction", adc_m6db),
++      {.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
++       .name = "Playback Volume",
++       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
++       SNDRV_CTL_ELEM_ACCESS_VOLATILE,
++       .info = dac_info_volsw,
++       .get = dac_get_volsw,
++       .put = dac_put_volsw,
++       },
++      SOC_DOUBLE("Headphone Volume", SGTL5000_CHIP_ANA_HP_CTRL, 0, 8, 0x7f,
++                 1),
++};
++
++static int sgtl5000_digital_mute(struct snd_soc_dai *codec_dai, int mute)
++{
++      struct snd_soc_codec *codec = codec_dai->codec;
++      u16 adcdac_ctrl;
++
++      adcdac_ctrl = sgtl5000_read(codec, SGTL5000_CHIP_ADCDAC_CTRL);
++
++      if (mute) {
++              adcdac_ctrl |= SGTL5000_DAC_MUTE_LEFT;
++              adcdac_ctrl |= SGTL5000_DAC_MUTE_RIGHT;
++      } else {
++              adcdac_ctrl &= ~SGTL5000_DAC_MUTE_LEFT;
++              adcdac_ctrl &= ~SGTL5000_DAC_MUTE_RIGHT;
++      }
++
++      sgtl5000_write(codec, SGTL5000_CHIP_ADCDAC_CTRL, adcdac_ctrl);
++      if (!mute)
++              dump_reg(codec);
++      return 0;
++}
++
++static int sgtl5000_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
++{
++      struct snd_soc_codec *codec = codec_dai->codec;
++      struct sgtl5000_priv *sgtl5000 = codec->drvdata;
++      u16 i2sctl = 0;
++      pr_debug("%s:fmt=%08x\n", __func__, fmt);
++      sgtl5000->master = 0;
++      switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
++      case SND_SOC_DAIFMT_CBS_CFS:
++              break;
++      case SND_SOC_DAIFMT_CBM_CFM:
++              i2sctl |= SGTL5000_I2S_MASTER;
++              sgtl5000->master = 1;
++              break;
++      case SND_SOC_DAIFMT_CBM_CFS:
++      case SND_SOC_DAIFMT_CBS_CFM:
++              return -EINVAL;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
++      case SND_SOC_DAIFMT_DSP_A:
++              i2sctl |= SGTL5000_I2S_MODE_PCM;
++              break;
++      case SND_SOC_DAIFMT_DSP_B:
++              i2sctl |= SGTL5000_I2S_MODE_PCM;
++              i2sctl |= SGTL5000_I2S_LRALIGN;
++              break;
++      case SND_SOC_DAIFMT_I2S:
++              i2sctl |= SGTL5000_I2S_MODE_I2S_LJ;
++              break;
++      case SND_SOC_DAIFMT_RIGHT_J:
++              i2sctl |= SGTL5000_I2S_MODE_RJ;
++              i2sctl |= SGTL5000_I2S_LRPOL;
++              break;
++      case SND_SOC_DAIFMT_LEFT_J:
++              i2sctl |= SGTL5000_I2S_MODE_I2S_LJ;
++              i2sctl |= SGTL5000_I2S_LRALIGN;
++              break;
++      default:
++              return -EINVAL;
++      }
++      sgtl5000->fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
++
++      /* Clock inversion */
++      switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
++      case SND_SOC_DAIFMT_NB_NF:
++      case SND_SOC_DAIFMT_NB_IF:
++              break;
++      case SND_SOC_DAIFMT_IB_IF:
++      case SND_SOC_DAIFMT_IB_NF:
++              i2sctl |= SGTL5000_I2S_SCLK_INV;
++              break;
++      default:
++              return -EINVAL;
++      }
++      sgtl5000_write(codec, SGTL5000_CHIP_I2S_CTRL, i2sctl);
++
++      return 0;
++}
++
++static int sgtl5000_set_dai_sysclk(struct snd_soc_dai *codec_dai,
++                                 int clk_id, unsigned int freq, int dir)
++{
++      struct snd_soc_codec *codec = codec_dai->codec;
++      struct sgtl5000_priv *sgtl5000 = codec->drvdata;
++
++      switch (clk_id) {
++      case SGTL5000_SYSCLK:
++              sgtl5000->sysclk = freq;
++              break;
++      case SGTL5000_LRCLK:
++              sgtl5000->lrclk = freq;
++              break;
++      default:
++              return -EINVAL;
++      }
++      return 0;
++}
++
++static int sgtl5000_pcm_prepare(struct snd_pcm_substream *substream,
++                              struct snd_soc_dai *dai)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_device *socdev = rtd->socdev;
++      struct snd_soc_codec *codec = socdev->card->codec;
++      struct sgtl5000_priv *sgtl5000 = codec->drvdata;
++      int reg;
++
++      reg = sgtl5000_read(codec, SGTL5000_CHIP_DIG_POWER);
++      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++              reg |= SGTL5000_I2S_IN_POWERUP;
++      else
++              reg |= SGTL5000_I2S_OUT_POWERUP;
++      sgtl5000_write(codec, SGTL5000_CHIP_DIG_POWER, reg);
++
++      if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_ANA_POWER);
++              reg |= SGTL5000_ADC_POWERUP;
++              if (sgtl5000->capture_channels == 1)
++                      reg &= ~SGTL5000_ADC_STEREO;
++              else
++                      reg |= SGTL5000_ADC_STEREO;
++              sgtl5000_write(codec, SGTL5000_CHIP_ANA_POWER, reg);
++      }
++
++      return 0;
++}
++
++static int sgtl5000_pcm_startup(struct snd_pcm_substream *substream,
++                              struct snd_soc_dai *dai)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_device *socdev = rtd->socdev;
++      struct snd_soc_codec *codec = socdev->card->codec;
++      struct sgtl5000_priv *sgtl5000 = codec->drvdata;
++      struct snd_pcm_runtime *master_runtime;
++
++      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++              sgtl5000->playback_active++;
++      else
++              sgtl5000->capture_active++;
++
++      /* The DAI has shared clocks so if we already have a playback or
++       * capture going then constrain this substream to match it.
++       */
++      if (sgtl5000->master_substream) {
++              master_runtime = sgtl5000->master_substream->runtime;
++
++              pr_debug("Constraining to %d bits\n",
++                       master_runtime->sample_bits);
++
++              snd_pcm_hw_constraint_minmax(substream->runtime,
++                                           SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
++                                           master_runtime->sample_bits,
++                                           master_runtime->sample_bits);
++
++              sgtl5000->slave_substream = substream;
++      } else
++              sgtl5000->master_substream = substream;
++
++      return 0;
++}
++
++static void sgtl5000_pcm_shutdown(struct snd_pcm_substream *substream,
++                                struct snd_soc_dai *dai)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_device *socdev = rtd->socdev;
++      struct snd_soc_codec *codec = socdev->card->codec;
++      struct sgtl5000_priv *sgtl5000 = codec->drvdata;
++      int reg, dig_pwr, ana_pwr;
++
++      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++              sgtl5000->playback_active--;
++      else
++              sgtl5000->capture_active--;
++
++      if (sgtl5000->master_substream == substream)
++              sgtl5000->master_substream = sgtl5000->slave_substream;
++
++      sgtl5000->slave_substream = NULL;
++
++      if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
++              ana_pwr = sgtl5000_read(codec, SGTL5000_CHIP_ANA_POWER);
++              ana_pwr &= ~(SGTL5000_ADC_POWERUP | SGTL5000_ADC_STEREO);
++              sgtl5000_write(codec, SGTL5000_CHIP_ANA_POWER, ana_pwr);
++      }
++
++      dig_pwr = sgtl5000_read(codec, SGTL5000_CHIP_DIG_POWER);
++      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
++              dig_pwr &= ~SGTL5000_I2S_IN_POWERUP;
++      else
++              dig_pwr &= ~SGTL5000_I2S_OUT_POWERUP;
++      sgtl5000_write(codec, SGTL5000_CHIP_DIG_POWER, dig_pwr);
++
++      if (!sgtl5000->playback_active && !sgtl5000->capture_active) {
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_I2S_CTRL);
++              reg &= ~SGTL5000_I2S_MASTER;
++              sgtl5000_write(codec, SGTL5000_CHIP_I2S_CTRL, reg);
++      }
++}
++
++/*
++ * Set PCM DAI bit size and sample rate.
++ * input: params_rate, params_fmt
++ */
++static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
++                                struct snd_pcm_hw_params *params,
++                                struct snd_soc_dai *dai)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_device *socdev = rtd->socdev;
++      struct snd_soc_codec *codec = socdev->card->codec;
++      struct sgtl5000_priv *sgtl5000 = codec->drvdata;
++      int channels = params_channels(params);
++      int clk_ctl = 0;
++      int pll_ctl = 0;
++      int i2s_ctl;
++      int div2 = 0;
++      int reg;
++      u32 fs;
++
++      pr_debug("%s channels=%d\n", __func__, channels);
++
++      if (!sgtl5000->sysclk) {
++              pr_err("%s: set sysclk first!\n", __func__);
++              return -EFAULT;
++      }
++
++      if (substream == sgtl5000->slave_substream) {
++              pr_debug("Ignoring hw_params for slave substream\n");
++              return 0;
++      }
++
++      if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
++              sgtl5000->capture_channels = channels;
++
++      switch (sgtl5000->lrclk) {
++      case 32000:
++              clk_ctl |= SGTL5000_SYS_FS_32k << SGTL5000_SYS_FS_SHIFT;
++              break;
++      case 44100:
++              clk_ctl |= SGTL5000_SYS_FS_44_1k << SGTL5000_SYS_FS_SHIFT;
++              break;
++      case 48000:
++              clk_ctl |= SGTL5000_SYS_FS_48k << SGTL5000_SYS_FS_SHIFT;
++              break;
++      case 96000:
++              clk_ctl |= SGTL5000_SYS_FS_96k << SGTL5000_SYS_FS_SHIFT;
++              break;
++      default:
++              pr_err("%s: sample rate %d not supported\n", __func__,
++                     sgtl5000->lrclk);
++              return -EFAULT;
++      }
++      fs = sgtl5000->lrclk;
++      /* SGTL5000 rev1 has a IC bug to prevent switching to MCLK from PLL. */
++      if (!sgtl5000->master) {
++              if (fs * 256 == sgtl5000->sysclk)
++                      clk_ctl |= SGTL5000_MCLK_FREQ_256FS << \
++                              SGTL5000_MCLK_FREQ_SHIFT;
++              else if (fs * 384 == sgtl5000->sysclk && fs != 96000)
++                      clk_ctl |= SGTL5000_MCLK_FREQ_384FS << \
++                              SGTL5000_MCLK_FREQ_SHIFT;
++              else if (fs * 512 == sgtl5000->sysclk && fs != 96000)
++                      clk_ctl |= SGTL5000_MCLK_FREQ_512FS << \
++                              SGTL5000_MCLK_FREQ_SHIFT;
++              else {
++                      pr_err("%s: PLL not supported in slave mode\n",
++                             __func__);
++                      return -EINVAL;
++              }
++      } else
++              clk_ctl |= SGTL5000_MCLK_FREQ_PLL << SGTL5000_MCLK_FREQ_SHIFT;
++
++      if ((clk_ctl & SGTL5000_MCLK_FREQ_MASK) == SGTL5000_MCLK_FREQ_PLL) {
++              u64 out, t;
++              unsigned int in, int_div, frac_div;
++              if (sgtl5000->sysclk > 17000000) {
++                      div2 = 1;
++                      in = sgtl5000->sysclk / 2;
++              } else {
++                      div2 = 0;
++                      in = sgtl5000->sysclk;
++              }
++              if (sgtl5000->lrclk == 44100)
++                      out = 180633600;
++              else
++                      out = 196608000;
++              t = do_div(out, in);
++              int_div = out;
++              t *= 2048;
++              do_div(t, in);
++              frac_div = t;
++              pll_ctl = int_div << SGTL5000_PLL_INT_DIV_SHIFT |
++                  frac_div << SGTL5000_PLL_FRAC_DIV_SHIFT;
++      }
++
++      i2s_ctl = sgtl5000_read(codec, SGTL5000_CHIP_I2S_CTRL);
++      switch (params_format(params)) {
++      case SNDRV_PCM_FORMAT_S16_LE:
++              if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J)
++                      return -EINVAL;
++              i2s_ctl |= SGTL5000_I2S_DLEN_16 << SGTL5000_I2S_DLEN_SHIFT;
++              i2s_ctl |= SGTL5000_I2S_SCLKFREQ_32FS <<
++                  SGTL5000_I2S_SCLKFREQ_SHIFT;
++              break;
++      case SNDRV_PCM_FORMAT_S20_3LE:
++              i2s_ctl |= SGTL5000_I2S_DLEN_20 << SGTL5000_I2S_DLEN_SHIFT;
++              i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS <<
++                  SGTL5000_I2S_SCLKFREQ_SHIFT;
++              break;
++      case SNDRV_PCM_FORMAT_S24_LE:
++              i2s_ctl |= SGTL5000_I2S_DLEN_24 << SGTL5000_I2S_DLEN_SHIFT;
++              i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS <<
++                  SGTL5000_I2S_SCLKFREQ_SHIFT;
++              break;
++      case SNDRV_PCM_FORMAT_S32_LE:
++              if (sgtl5000->fmt == SND_SOC_DAIFMT_RIGHT_J)
++                      return -EINVAL;
++              i2s_ctl |= SGTL5000_I2S_DLEN_32 << SGTL5000_I2S_DLEN_SHIFT;
++              i2s_ctl |= SGTL5000_I2S_SCLKFREQ_64FS <<
++                  SGTL5000_I2S_SCLKFREQ_SHIFT;
++              break;
++      default:
++              return -EINVAL;
++      }
++
++      pr_debug("fs=%d,clk_ctl=%d,pll_ctl=%d,i2s_ctl=%d,div2=%d\n",
++               sgtl5000->lrclk, clk_ctl, pll_ctl, i2s_ctl, div2);
++
++      if ((clk_ctl & SGTL5000_MCLK_FREQ_MASK) == SGTL5000_MCLK_FREQ_PLL) {
++              sgtl5000_write(codec, SGTL5000_CHIP_PLL_CTRL, pll_ctl);
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_CLK_TOP_CTRL);
++              if (div2)
++                      reg |= SGTL5000_INPUT_FREQ_DIV2;
++              else
++                      reg &= ~SGTL5000_INPUT_FREQ_DIV2;
++              sgtl5000_write(codec, SGTL5000_CHIP_CLK_TOP_CTRL, reg);
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_ANA_POWER);
++              reg |= SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP;
++              sgtl5000_write(codec, SGTL5000_CHIP_ANA_POWER, reg);
++      }
++      sgtl5000_write(codec, SGTL5000_CHIP_CLK_CTRL, clk_ctl);
++      sgtl5000_write(codec, SGTL5000_CHIP_I2S_CTRL, i2s_ctl);
++
++      return 0;
++}
++
++static void sgtl5000_mic_bias(struct snd_soc_codec *codec, int enable)
++{
++      int reg, bias_r = 0;
++      if (enable)
++              bias_r = SGTL5000_BIAS_R_4k << SGTL5000_BIAS_R_SHIFT;
++      reg = sgtl5000_read(codec, SGTL5000_CHIP_MIC_CTRL);
++      if ((reg & SGTL5000_BIAS_R_MASK) != bias_r) {
++              reg &= ~SGTL5000_BIAS_R_MASK;
++              reg |= bias_r;
++              sgtl5000_write(codec, SGTL5000_CHIP_MIC_CTRL, reg);
++      }
++}
++
++static int sgtl5000_set_bias_level(struct snd_soc_codec *codec,
++                                 enum snd_soc_bias_level level)
++{
++      u16 reg, ana_pwr;
++      int delay = 0;
++      pr_debug("dapm level %d\n", level);
++      switch (level) {
++      case SND_SOC_BIAS_ON:           /* full On */
++              if (codec->bias_level == SND_SOC_BIAS_ON)
++                      break;
++
++              sgtl5000_mic_bias(codec, 1);
++
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_ANA_POWER);
++              reg |= SGTL5000_VAG_POWERUP;
++              sgtl5000_write(codec, SGTL5000_CHIP_ANA_POWER, reg);
++              msleep(400);
++
++              break;
++
++      case SND_SOC_BIAS_PREPARE:      /* partial On */
++              if (codec->bias_level == SND_SOC_BIAS_PREPARE)
++                      break;
++
++              sgtl5000_mic_bias(codec, 0);
++
++              /* must power up hp/line out before vag & dac to
++                 avoid pops. */
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_ANA_POWER);
++              if (reg & SGTL5000_VAG_POWERUP)
++                      delay = 400;
++              reg &= ~SGTL5000_VAG_POWERUP;
++              reg |= SGTL5000_DAC_POWERUP;
++              reg |= SGTL5000_HP_POWERUP;
++              reg |= SGTL5000_LINE_OUT_POWERUP;
++              sgtl5000_write(codec, SGTL5000_CHIP_ANA_POWER, reg);
++              if (delay)
++                      msleep(delay);
++
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_DIG_POWER);
++              reg |= SGTL5000_DAC_EN;
++              sgtl5000_write(codec, SGTL5000_CHIP_DIG_POWER, reg);
++
++              break;
++
++      case SND_SOC_BIAS_STANDBY:      /* Off, with power */
++              /* soc doesn't do PREPARE state after record so make sure
++                 that anything that needs to be turned OFF gets turned off. */
++              if (codec->bias_level == SND_SOC_BIAS_STANDBY)
++                      break;
++
++              /* soc calls digital_mute to unmute before record but doesn't
++                 call digital_mute to mute after record. */
++              sgtl5000_digital_mute(&sgtl5000_dai, 1);
++
++              sgtl5000_mic_bias(codec, 0);
++
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_ANA_POWER);
++              if (reg & SGTL5000_VAG_POWERUP) {
++                      reg &= ~SGTL5000_VAG_POWERUP;
++                      sgtl5000_write(codec, SGTL5000_CHIP_ANA_POWER, reg);
++                      msleep(400);
++              }
++              reg &= ~SGTL5000_DAC_POWERUP;
++              reg &= ~SGTL5000_HP_POWERUP;
++              reg &= ~SGTL5000_LINE_OUT_POWERUP;
++              sgtl5000_write(codec, SGTL5000_CHIP_ANA_POWER, reg);
++
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_DIG_POWER);
++              reg &= ~SGTL5000_DAC_EN;
++              sgtl5000_write(codec, SGTL5000_CHIP_DIG_POWER, reg);
++
++              break;
++
++      case SND_SOC_BIAS_OFF:  /* Off, without power */
++              /* must power down hp/line out after vag & dac to
++                 avoid pops. */
++              reg = sgtl5000_read(codec, SGTL5000_CHIP_ANA_POWER);
++              ana_pwr = reg;
++              reg &= ~SGTL5000_VAG_POWERUP;
++
++              /* Workaround for sgtl5000 rev 0x11 chip audio suspend failure
++                 issue on mx25 */
++              reg &= ~SGTL5000_REFTOP_POWERUP;
++
++              sgtl5000_write(codec, SGTL5000_CHIP_ANA_POWER, reg);
++              msleep(600);
++
++              reg &= ~SGTL5000_HP_POWERUP;
++              reg &= ~SGTL5000_LINE_OUT_POWERUP;
++              reg &= ~SGTL5000_DAC_POWERUP;
++              reg &= ~SGTL5000_ADC_POWERUP;
++              sgtl5000_write(codec, SGTL5000_CHIP_ANA_POWER, reg);
++
++              /* save ANA POWER register value for resume */
++              sgtl5000_write_reg_cache(codec, SGTL5000_CHIP_ANA_POWER,
++                                       ana_pwr);
++              break;
++      }
++      codec->bias_level = level;
++      return 0;
++}
++
++#define SGTL5000_RATES (SNDRV_PCM_RATE_32000 |\
++                    SNDRV_PCM_RATE_44100 |\
++                    SNDRV_PCM_RATE_48000 |\
++                    SNDRV_PCM_RATE_96000)
++
++#define SGTL5000_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
++                      SNDRV_PCM_FMTBIT_S20_3LE |\
++                      SNDRV_PCM_FMTBIT_S24_LE)
++
++struct snd_soc_dai_ops sgtl5000_ops = {
++      .prepare = sgtl5000_pcm_prepare,
++      .startup = sgtl5000_pcm_startup,
++      .shutdown = sgtl5000_pcm_shutdown,
++      .hw_params = sgtl5000_pcm_hw_params,
++      .digital_mute = sgtl5000_digital_mute,
++      .set_fmt = sgtl5000_set_dai_fmt,
++      .set_sysclk = sgtl5000_set_dai_sysclk
++};
++
++struct snd_soc_dai sgtl5000_dai = {
++      .name = "SGTL5000",
++      .playback = {
++                   .stream_name = "Playback",
++                   .channels_min = 2,
++                   .channels_max = 2,
++                   .rates = SGTL5000_RATES,
++                   .formats = SGTL5000_FORMATS,
++                   },
++      .capture = {
++                  .stream_name = "Capture",
++                  .channels_min = 2,
++                  .channels_max = 2,
++                  .rates = SGTL5000_RATES,
++                  .formats = SGTL5000_FORMATS,
++                  },
++      .ops = &sgtl5000_ops,
++      .symmetric_rates = 1,
++};
++EXPORT_SYMBOL_GPL(sgtl5000_dai);
++
++static int sgtl5000_suspend(struct platform_device *pdev, pm_message_t state)
++{
++      struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++      struct snd_soc_codec *codec = socdev->card->codec;
++
++      sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF);
++
++      return 0;
++}
++
++static int sgtl5000_resume(struct platform_device *pdev)
++{
++      struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++      struct snd_soc_codec *codec = socdev->card->codec;
++      unsigned int i;
++
++      /* Restore refs first in same order as in sgtl5000_init */
++      sgtl5000_restore_reg(codec, SGTL5000_CHIP_LINREG_CTRL);
++      sgtl5000_restore_reg(codec, SGTL5000_CHIP_ANA_POWER);
++      msleep(10);
++      sgtl5000_restore_reg(codec, SGTL5000_CHIP_REF_CTRL);
++      sgtl5000_restore_reg(codec, SGTL5000_CHIP_LINE_OUT_CTRL);
++
++      /* Restore everythine else */
++      for (i = 1; i < sizeof(all_reg) / sizeof(int); i++)
++              sgtl5000_restore_reg(codec, all_reg[i]);
++
++      sgtl5000_write(codec, SGTL5000_DAP_CTRL, 0);
++
++      /* Bring the codec back up to standby first to minimise pop/clicks */
++      sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
++      if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
++              sgtl5000_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
++      sgtl5000_set_bias_level(codec, codec->suspend_bias_level);
++
++      return 0;
++}
++
++static struct snd_soc_codec *sgtl5000_codec;
++
++/*
++ * initialise the SGTL5000 driver
++ * register the mixer and dsp interfaces with the kernel
++ */
++static int sgtl5000_probe(struct platform_device *pdev)
++{
++      struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++      struct snd_soc_codec *codec = sgtl5000_codec;
++      struct sgtl5000_priv *sgtl5000 = codec->drvdata;
++      u16 reg, ana_pwr, lreg_ctrl, ref_ctrl, lo_ctrl, short_ctrl, sss;
++      int vag;
++      int ret = 0;
++
++      socdev->card->codec = sgtl5000_codec;
++
++      /* register pcms */
++      ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
++      if (ret < 0) {
++              dev_err(codec->dev, "failed to create pcms\n");
++              return ret;
++      }
++
++      /* reset value */
++      ana_pwr = SGTL5000_DAC_STEREO |
++          SGTL5000_LINREG_SIMPLE_POWERUP |
++          SGTL5000_STARTUP_POWERUP |
++          SGTL5000_ADC_STEREO | SGTL5000_REFTOP_POWERUP;
++      lreg_ctrl = 0;
++      ref_ctrl = 0;
++      lo_ctrl = 0;
++      short_ctrl = 0;
++      sss = SGTL5000_DAC_SEL_I2S_IN << SGTL5000_DAC_SEL_SHIFT;
++
++      /* workaround for rev 0x11: use vddd linear regulator */
++      if (sgtl5000->rev >= 0x11) {
++              /* set VDDD to 1.2v */
++              lreg_ctrl |= 0x8 << SGTL5000_LINREG_VDDD_SHIFT;
++              /* power internal linear regulator */
++              ana_pwr |= SGTL5000_LINEREG_D_POWERUP;
++      }
++
++      /* Enable VDDC charge pump (VDDIO || VDDA) > 3V */
++      ana_pwr |= SGTL5000_VDDC_CHRGPMP_POWERUP;
++
++      /* VDDC use VDDIO rail */
++      lreg_ctrl |= SGTL5000_VDDC_ASSN_OVRD;
++      /* (VDDIO || VDDA) > 3V  */
++      lreg_ctrl |= SGTL5000_VDDC_MAN_ASSN_VDDIO << SGTL5000_VDDC_MAN_ASSN_SHIFT;
++
++      /* If PLL is powered up (such as on power cycle) leave it on. */
++      reg = sgtl5000_read(codec, SGTL5000_CHIP_ANA_POWER);
++      ana_pwr |= reg & (SGTL5000_PLL_POWERUP | SGTL5000_VCOAMP_POWERUP);              // MASU FIXME
++
++      /* set ADC/DAC ref voltage to vdda/2 */
++      vag = 3300 / 2;
++      if (vag <= SGTL5000_ANA_GND_BASE)
++              vag = 0;
++      else if (vag >= SGTL5000_ANA_GND_BASE + SGTL5000_ANA_GND_STP *
++               (SGTL5000_ANA_GND_MASK >> SGTL5000_ANA_GND_SHIFT))
++              vag = SGTL5000_ANA_GND_MASK >> SGTL5000_ANA_GND_SHIFT;
++      else
++              vag = (vag - SGTL5000_ANA_GND_BASE) / SGTL5000_ANA_GND_STP;
++      ref_ctrl |= vag << SGTL5000_ANA_GND_SHIFT;
++
++      /* enable small pop */
++      ref_ctrl |= SGTL5000_SMALL_POP;
++
++      /* set line out ref voltage to vddio/2 */
++      vag = 3300 / 2;
++      if (vag <= SGTL5000_LINE_OUT_GND_BASE)
++              vag = 0;
++      else if (vag >= SGTL5000_LINE_OUT_GND_BASE + SGTL5000_LINE_OUT_GND_STP *
++               SGTL5000_LINE_OUT_GND_MAX)
++              vag = SGTL5000_LINE_OUT_GND_MAX;
++      else
++              vag = (vag - SGTL5000_LINE_OUT_GND_BASE) /
++                  SGTL5000_LINE_OUT_GND_STP;
++      lo_ctrl |= vag << SGTL5000_LINE_OUT_GND_SHIFT;
++
++      /* Controls the output bias current for the lineout */
++      lo_ctrl |=
++          (SGTL5000_LINE_OUT_CURRENT_360u << SGTL5000_LINE_OUT_CURRENT_SHIFT);
++
++      /* set short detect */
++      ana_pwr |= 0x0000;
++      /* keep default */
++
++      /* set routing */
++      /* keep default, bypass DAP */
++
++      sgtl5000_write(codec, SGTL5000_CHIP_LINREG_CTRL, lreg_ctrl);
++      sgtl5000_write(codec, SGTL5000_CHIP_ANA_POWER, ana_pwr);
++      msleep(10);
++
++      /* For rev 0x11, if vddd linear reg has been enabled, we have
++         to disable simple reg to get proper VDDD voltage.  */
++      if ((ana_pwr & SGTL5000_LINEREG_D_POWERUP) && (sgtl5000->rev >= 0x11)) {
++              ana_pwr &= ~SGTL5000_LINREG_SIMPLE_POWERUP;
++              sgtl5000_write(codec, SGTL5000_CHIP_ANA_POWER, ana_pwr);
++              msleep(10);
++      }
++
++      sgtl5000_write(codec, SGTL5000_CHIP_REF_CTRL, ref_ctrl);
++      sgtl5000_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL, lo_ctrl);
++      sgtl5000_write(codec, SGTL5000_CHIP_SHORT_CTRL, short_ctrl);
++      sgtl5000_write(codec, SGTL5000_CHIP_SSS_CTRL, sss);
++      sgtl5000_write(codec, SGTL5000_CHIP_DIG_POWER, 0);
++
++      reg = SGTL5000_DAC_VOL_RAMP_EN |
++          SGTL5000_DAC_MUTE_RIGHT | SGTL5000_DAC_MUTE_LEFT;
++      sgtl5000_write(codec, SGTL5000_CHIP_ADCDAC_CTRL, reg);
++
++#ifdef CONFIG_ARCH_MXC
++      if (cpu_is_mx25())
++              sgtl5000_write(codec, SGTL5000_CHIP_PAD_STRENGTH, 0x01df);
++      else
++#endif
++              sgtl5000_write(codec, SGTL5000_CHIP_PAD_STRENGTH, 0x015f);
++
++      reg = sgtl5000_read(codec, SGTL5000_CHIP_ANA_ADC_CTRL);
++      reg &= ~SGTL5000_ADC_VOL_M6DB;
++      reg &= ~(SGTL5000_ADC_VOL_LEFT_MASK | SGTL5000_ADC_VOL_RIGHT_MASK);
++      reg |= (0xf << SGTL5000_ADC_VOL_LEFT_SHIFT)
++          | (0xf << SGTL5000_ADC_VOL_RIGHT_SHIFT);
++      sgtl5000_write(codec, SGTL5000_CHIP_ANA_ADC_CTRL, reg);
++
++      reg = SGTL5000_LINE_OUT_MUTE | SGTL5000_HP_MUTE |
++          SGTL5000_HP_ZCD_EN | SGTL5000_ADC_ZCD_EN;
++      sgtl5000_write(codec, SGTL5000_CHIP_ANA_CTRL, reg);
++
++      sgtl5000_write(codec, SGTL5000_CHIP_MIC_CTRL, 0);
++      sgtl5000_write(codec, SGTL5000_CHIP_CLK_TOP_CTRL, 0);
++      /* disable DAP */
++      sgtl5000_write(codec, SGTL5000_DAP_CTRL, 0);
++      /* TODO: initialize DAP */
++
++      snd_soc_add_controls(codec, sgtl5000_snd_controls,
++                           ARRAY_SIZE(sgtl5000_snd_controls));
++      sgtl5000_add_widgets(codec);
++
++      sgtl5000_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
++
++// MASU Do we need this ?
++//    ret = snd_soc_init_card(socdev);
++//    if (ret < 0) {
++//            printk(KERN_ERR "sgtl5000: failed to register card\n");
++//            snd_soc_free_pcms(socdev);
++//            snd_soc_dapm_free(socdev);
++//            return ret;
++//    }
++
++      return 0;
++}
++
++/* power down chip */
++static int sgtl5000_remove(struct platform_device *pdev)
++{
++      struct snd_soc_device *socdev = platform_get_drvdata(pdev);
++      struct snd_soc_codec *codec = socdev->card->codec;
++
++      if (codec->control_data)
++              sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF);
++      snd_soc_free_pcms(socdev);
++      snd_soc_dapm_free(socdev);
++
++      return 0;
++}
++
++struct snd_soc_codec_device soc_codec_dev_sgtl5000 = {
++      .probe = sgtl5000_probe,
++      .remove = sgtl5000_remove,
++      .suspend = sgtl5000_suspend,
++      .resume = sgtl5000_resume,
++};
++EXPORT_SYMBOL_GPL(soc_codec_dev_sgtl5000);
++
++static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
++                                      const struct i2c_device_id *id)
++{
++      struct sgtl5000_priv *sgtl5000;
++      struct snd_soc_codec *codec;
++      struct regulator *reg;
++      int ret = 0;
++      u32 val;
++
++      if (sgtl5000_codec) {
++              dev_err(&client->dev,
++                      "Multiple SGTL5000 devices not supported\n");
++              return -ENOMEM;
++      }
++
++      codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
++      if (codec == NULL)
++              return -ENOMEM;
++
++      sgtl5000 = kzalloc(sizeof(struct sgtl5000_priv), GFP_KERNEL);
++      if (sgtl5000 == NULL) {
++              kfree(codec);
++              return -ENOMEM;
++      }
++
++      codec->drvdata = sgtl5000;
++      mutex_init(&codec->mutex);
++      INIT_LIST_HEAD(&codec->dapm_widgets);
++      INIT_LIST_HEAD(&codec->dapm_paths);
++
++      i2c_set_clientdata(client, codec);
++      codec->control_data = client;
++
++      msleep(1);
++
++      val = sgtl5000_read(codec, SGTL5000_CHIP_ID);
++      if (((val & SGTL5000_PARTID_MASK) >> SGTL5000_PARTID_SHIFT) !=
++          SGTL5000_PARTID_PART_ID) {
++              pr_err("Device with ID register %x is not a SGTL5000\n", val);
++              ret = -ENODEV;
++              goto err_codec_reg;
++      }
++
++      sgtl5000->rev = (val & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
++      dev_info(&client->dev, "SGTL5000 revision %d\n", sgtl5000->rev);
++
++      codec->dev = &client->dev;
++      codec->name = "SGTL5000";
++      codec->owner = THIS_MODULE;
++      codec->read = sgtl5000_read_reg_cache;
++      codec->write = sgtl5000_write;
++      codec->bias_level = SND_SOC_BIAS_OFF;
++      codec->set_bias_level = sgtl5000_set_bias_level;
++      codec->dai = &sgtl5000_dai;
++      codec->num_dai = 1;
++      codec->reg_cache_size = sizeof(sgtl5000_regs);
++      codec->reg_cache_step = 2;
++      codec->reg_cache = (void *)&sgtl5000_regs;
++
++      sgtl5000_sync_reg_cache(codec);
++
++      sgtl5000_codec = codec;
++      sgtl5000_dai.dev = &client->dev;
++
++      ret = snd_soc_register_codec(codec);
++      if (ret != 0) {
++              dev_err(codec->dev, "Failed to register codec: %d\n", ret);
++              goto err_codec_reg;
++      }
++
++      ret = snd_soc_register_dai(&sgtl5000_dai);
++      if (ret != 0) {
++              dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
++              goto err_codec_reg;
++      }
++
++      return 0;
++
++err_codec_reg:
++      kfree(sgtl5000);
++      kfree(codec);
++      return ret;
++}
++
++static __devexit int sgtl5000_i2c_remove(struct i2c_client *client)
++{
++      struct snd_soc_codec *codec = i2c_get_clientdata(client);
++      struct sgtl5000_priv *sgtl5000 = codec->drvdata;
++
++      if (client->dev.platform_data)
++              clk_disable((struct clk *)client->dev.platform_data);
++
++      snd_soc_unregister_dai(&sgtl5000_dai);
++      snd_soc_unregister_codec(codec);
++
++      kfree(codec);
++      kfree(sgtl5000);
++      sgtl5000_codec = NULL;
++      return 0;
++}
++
++static const struct i2c_device_id sgtl5000_id[] = {
++      {"sgtl5000-i2c", 0},
++      {},
++};
++
++MODULE_DEVICE_TABLE(i2c, sgtl5000_id);
++
++static struct i2c_driver sgtl5000_i2c_driver = {
++      .driver = {
++                 .name = "sgtl5000-i2c",
++                 .owner = THIS_MODULE,
++                 },
++      .probe = sgtl5000_i2c_probe,
++      .remove = __devexit_p(sgtl5000_i2c_remove),
++      .id_table = sgtl5000_id,
++};
++
++static int __init sgtl5000_modinit(void)
++{
++      return i2c_add_driver(&sgtl5000_i2c_driver);
++}
++module_init(sgtl5000_modinit);
++
++static void __exit sgtl5000_exit(void)
++{
++      i2c_del_driver(&sgtl5000_i2c_driver);
++}
++module_exit(sgtl5000_exit);
++
++MODULE_DESCRIPTION("ASoC SGTL5000 driver");
++MODULE_AUTHOR("Freescale Semiconductor, Inc.");
++MODULE_LICENSE("GPL");
+diff -urN linux.35.old/sound/soc/codecs/sgtl5000.h linux.35.new/sound/soc/codecs/sgtl5000.h
+--- linux.35.old/sound/soc/codecs/sgtl5000.h   1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/sound/soc/codecs/sgtl5000.h   2010-12-03 09:51:55.492348513 +0100
+@@ -0,0 +1,399 @@
++/*
++ * sgtl5000.h - SGTL5000 audio codec interface
++ *
++ * Copyright 2008-2009 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 as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ */
++
++#ifndef _SGTL5000_H
++#define _SGTL5000_H
++
++#include <linux/i2c.h>
++
++extern struct snd_soc_dai sgtl5000_dai;
++extern struct snd_soc_codec_device soc_codec_dev_sgtl5000;
++
++/*
++ * Register values.
++ */
++#define SGTL5000_CHIP_ID                      0x0000
++#define SGTL5000_CHIP_DIG_POWER                       0x0002
++#define SGTL5000_CHIP_CLK_CTRL                        0x0004
++#define SGTL5000_CHIP_I2S_CTRL                        0x0006
++#define SGTL5000_CHIP_SSS_CTRL                        0x000a
++#define SGTL5000_CHIP_ADCDAC_CTRL             0x000e
++#define SGTL5000_CHIP_DAC_VOL                 0x0010
++#define SGTL5000_CHIP_PAD_STRENGTH            0x0014
++#define SGTL5000_CHIP_ANA_ADC_CTRL            0x0020
++#define SGTL5000_CHIP_ANA_HP_CTRL             0x0022
++#define SGTL5000_CHIP_ANA_CTRL                        0x0024
++#define SGTL5000_CHIP_LINREG_CTRL             0x0026
++#define SGTL5000_CHIP_REF_CTRL                        0x0028
++#define SGTL5000_CHIP_MIC_CTRL                        0x002a
++#define SGTL5000_CHIP_LINE_OUT_CTRL           0x002c
++#define SGTL5000_CHIP_LINE_OUT_VOL            0x002e
++#define SGTL5000_CHIP_ANA_POWER                       0x0030
++#define SGTL5000_CHIP_PLL_CTRL                        0x0032
++#define SGTL5000_CHIP_CLK_TOP_CTRL            0x0034
++#define SGTL5000_CHIP_ANA_STATUS              0x0036
++#define SGTL5000_CHIP_SHORT_CTRL              0x003c
++#define SGTL5000_CHIP_ANA_TEST2                       0x003a
++#define SGTL5000_DAP_CTRL                     0x0100
++#define SGTL5000_DAP_PEQ                      0x0102
++#define SGTL5000_DAP_BASS_ENHANCE             0x0104
++#define SGTL5000_DAP_BASS_ENHANCE_CTRL                0x0106
++#define SGTL5000_DAP_AUDIO_EQ                 0x0108
++#define SGTL5000_DAP_SURROUND                 0x010a
++#define SGTL5000_DAP_FLT_COEF_ACCESS          0x010c
++#define SGTL5000_DAP_COEF_WR_B0_MSB           0x010e
++#define SGTL5000_DAP_COEF_WR_B0_LSB           0x0110
++#define SGTL5000_DAP_EQ_BASS_BAND0            0x0116
++#define SGTL5000_DAP_EQ_BASS_BAND1            0x0118
++#define SGTL5000_DAP_EQ_BASS_BAND2            0x011a
++#define SGTL5000_DAP_EQ_BASS_BAND3            0x011c
++#define SGTL5000_DAP_EQ_BASS_BAND4            0x011e
++#define SGTL5000_DAP_MAIN_CHAN                        0x0120
++#define SGTL5000_DAP_MIX_CHAN                 0x0122
++#define SGTL5000_DAP_AVC_CTRL                 0x0124
++#define SGTL5000_DAP_AVC_THRESHOLD            0x0126
++#define SGTL5000_DAP_AVC_ATTACK                       0x0128
++#define SGTL5000_DAP_AVC_DECAY                        0x012a
++#define SGTL5000_DAP_COEF_WR_B1_MSB           0x012c
++#define SGTL5000_DAP_COEF_WR_B1_LSB           0x012e
++#define SGTL5000_DAP_COEF_WR_B2_MSB           0x0130
++#define SGTL5000_DAP_COEF_WR_B2_LSB           0x0132
++#define SGTL5000_DAP_COEF_WR_A1_MSB           0x0134
++#define SGTL5000_DAP_COEF_WR_A1_LSB           0x0136
++#define SGTL5000_DAP_COEF_WR_A2_MSB           0x0138
++#define SGTL5000_DAP_COEF_WR_A2_LSB           0x013a
++
++/*
++ * Field Definitions.
++ */
++
++/*
++ * SGTL5000_CHIP_ID
++ */
++#define SGTL5000_PARTID_MASK                  0xff00
++#define SGTL5000_PARTID_SHIFT                 8
++#define SGTL5000_PARTID_WIDTH                 8
++#define SGTL5000_PARTID_PART_ID               0xa0
++#define SGTL5000_REVID_MASK                   0x00ff
++#define SGTL5000_REVID_SHIFT                  0
++#define SGTL5000_REVID_WIDTH                  8
++
++/*
++ * SGTL5000_CHIP_DIG_POWER
++ */
++#define SGTL5000_ADC_EN                               0x0040
++#define SGTL5000_DAC_EN                               0x0020
++#define SGTL5000_DAP_POWERUP                  0x0010
++#define SGTL5000_I2S_OUT_POWERUP              0x0002
++#define SGTL5000_I2S_IN_POWERUP                       0x0001
++
++/*
++ * SGTL5000_CHIP_CLK_CTRL
++ */
++#define SGTL5000_SYS_FS_MASK                  0x00c0
++#define SGTL5000_SYS_FS_SHIFT                 2
++#define SGTL5000_SYS_FS_WIDTH                 2
++#define SGTL5000_SYS_FS_32k                   0x0
++#define SGTL5000_SYS_FS_44_1k                 0x1
++#define SGTL5000_SYS_FS_48k                   0x2
++#define SGTL5000_SYS_FS_96k                   0x3
++#define SGTL5000_MCLK_FREQ_MASK                       0x0003
++#define SGTL5000_MCLK_FREQ_SHIFT              0
++#define SGTL5000_MCLK_FREQ_WIDTH              2
++#define SGTL5000_MCLK_FREQ_256FS              0x0
++#define SGTL5000_MCLK_FREQ_384FS              0x1
++#define SGTL5000_MCLK_FREQ_512FS              0x2
++#define SGTL5000_MCLK_FREQ_PLL                        0x3
++
++/*
++ * SGTL5000_CHIP_I2S_CTRL
++ */
++#define SGTL5000_I2S_SCLKFREQ_MASK            0x0100
++#define SGTL5000_I2S_SCLKFREQ_SHIFT           8
++#define SGTL5000_I2S_SCLKFREQ_WIDTH           1
++#define SGTL5000_I2S_SCLKFREQ_64FS            0x0
++#define SGTL5000_I2S_SCLKFREQ_32FS            0x1     /* Not for RJ mode */
++#define SGTL5000_I2S_MASTER                   0x0080
++#define SGTL5000_I2S_SCLK_INV                 0x0040
++#define SGTL5000_I2S_DLEN_MASK                        0x0030
++#define SGTL5000_I2S_DLEN_SHIFT                       4
++#define SGTL5000_I2S_DLEN_WIDTH                       2
++#define SGTL5000_I2S_DLEN_32                  0x0
++#define SGTL5000_I2S_DLEN_24                  0x1
++#define SGTL5000_I2S_DLEN_20                  0x2
++#define SGTL5000_I2S_DLEN_16                  0x3
++#define SGTL5000_I2S_MODE_MASK                        0x000c
++#define SGTL5000_I2S_MODE_SHIFT                       2
++#define SGTL5000_I2S_MODE_WIDTH                       2
++#define SGTL5000_I2S_MODE_I2S_LJ              0x0
++#define SGTL5000_I2S_MODE_RJ                  0x1
++#define SGTL5000_I2S_MODE_PCM                 0x2
++#define SGTL5000_I2S_LRALIGN                  0x0002
++#define SGTL5000_I2S_LRPOL                    0x0001  /* set for which mode */
++
++/*
++ * SGTL5000_CHIP_SSS_CTRL
++ */
++#define SGTL5000_DAP_MIX_LRSWAP                       0x4000
++#define SGTL5000_DAP_LRSWAP                   0x2000
++#define SGTL5000_DAC_LRSWAP                   0x1000
++#define SGTL5000_I2S_OUT_LRSWAP                       0x0400
++#define SGTL5000_DAP_MIX_SEL_MASK             0x0300
++#define SGTL5000_DAP_MIX_SEL_SHIFT            8
++#define SGTL5000_DAP_MIX_SEL_WIDTH            2
++#define SGTL5000_DAP_MIX_SEL_ADC              0x0
++#define SGTL5000_DAP_MIX_SEL_I2S_IN           0x1
++#define SGTL5000_DAP_SEL_MASK                 0x00c0
++#define SGTL5000_DAP_SEL_SHIFT                        6
++#define SGTL5000_DAP_SEL_WIDTH                        2
++#define SGTL5000_DAP_SEL_ADC                  0x0
++#define SGTL5000_DAP_SEL_I2S_IN                       0x1
++#define SGTL5000_DAC_SEL_MASK                 0x0030
++#define SGTL5000_DAC_SEL_SHIFT                        4
++#define SGTL5000_DAC_SEL_WIDTH                        2
++#define SGTL5000_DAC_SEL_ADC                  0x0
++#define SGTL5000_DAC_SEL_I2S_IN                       0x1
++#define SGTL5000_DAC_SEL_DAP                  0x3
++#define SGTL5000_I2S_OUT_SEL_MASK             0x0003
++#define SGTL5000_I2S_OUT_SEL_SHIFT            0
++#define SGTL5000_I2S_OUT_SEL_WIDTH            2
++#define SGTL5000_I2S_OUT_SEL_ADC              0x0
++#define SGTL5000_I2S_OUT_SEL_I2S_IN           0x1
++#define SGTL5000_I2S_OUT_SEL_DAP              0x3
++
++/*
++ * SGTL5000_CHIP_ADCDAC_CTRL
++ */
++#define SGTL5000_VOL_BUSY_DAC_RIGHT           0x2000
++#define SGTL5000_VOL_BUSY_DAC_LEFT            0x1000
++#define SGTL5000_DAC_VOL_RAMP_EN              0x0200
++#define SGTL5000_DAC_VOL_RAMP_EXPO            0x0100
++#define SGTL5000_DAC_MUTE_RIGHT                       0x0008
++#define SGTL5000_DAC_MUTE_LEFT                        0x0004
++#define SGTL5000_ADC_HPF_FREEZE                       0x0002
++#define SGTL5000_ADC_HPF_BYPASS                       0x0001
++
++/*
++ * SGTL5000_CHIP_DAC_VOL
++ */
++#define SGTL5000_DAC_VOL_RIGHT_MASK           0xff00
++#define SGTL5000_DAC_VOL_RIGHT_SHIFT          8
++#define SGTL5000_DAC_VOL_RIGHT_WIDTH          8
++#define SGTL5000_DAC_VOL_LEFT_MASK            0x00ff
++#define SGTL5000_DAC_VOL_LEFT_SHIFT           0
++#define SGTL5000_DAC_VOL_LEFT_WIDTH           8
++
++/*
++ * SGTL5000_CHIP_PAD_STRENGTH
++ */
++#define SGTL5000_PAD_I2S_LRCLK_MASK           0x0300
++#define SGTL5000_PAD_I2S_LRCLK_SHIFT          8
++#define SGTL5000_PAD_I2S_LRCLK_WIDTH          2
++#define SGTL5000_PAD_I2S_SCLK_MASK            0x00c0
++#define SGTL5000_PAD_I2S_SCLK_SHIFT           6
++#define SGTL5000_PAD_I2S_SCLK_WIDTH           2
++#define SGTL5000_PAD_I2S_DOUT_MASK            0x0030
++#define SGTL5000_PAD_I2S_DOUT_SHIFT           4
++#define SGTL5000_PAD_I2S_DOUT_WIDTH           2
++#define SGTL5000_PAD_I2C_SDA_MASK             0x000c
++#define SGTL5000_PAD_I2C_SDA_SHIFT            2
++#define SGTL5000_PAD_I2C_SDA_WIDTH            2
++#define SGTL5000_PAD_I2C_SCL_MASK             0x0003
++#define SGTL5000_PAD_I2C_SCL_SHIFT            0
++#define SGTL5000_PAD_I2C_SCL_WIDTH            2
++
++/*
++ * SGTL5000_CHIP_ANA_ADC_CTRL
++ */
++#define SGTL5000_ADC_VOL_M6DB                 0x0100
++#define SGTL5000_ADC_VOL_RIGHT_MASK           0x00f0
++#define SGTL5000_ADC_VOL_RIGHT_SHIFT          4
++#define SGTL5000_ADC_VOL_RIGHT_WIDTH          4
++#define SGTL5000_ADC_VOL_LEFT_MASK            0x000f
++#define SGTL5000_ADC_VOL_LEFT_SHIFT           0
++#define SGTL5000_ADC_VOL_LEFT_WIDTH           4
++
++/*
++ * SGTL5000_CHIP_ANA_HP_CTRL
++ */
++#define SGTL5000_HP_VOL_RIGHT_MASK            0x7f00
++#define SGTL5000_HP_VOL_RIGHT_SHIFT           8
++#define SGTL5000_HP_VOL_RIGHT_WIDTH           7
++#define SGTL5000_HP_VOL_LEFT_MASK             0x007f
++#define SGTL5000_HP_VOL_LEFT_SHIFT            0
++#define SGTL5000_HP_VOL_LEFT_WIDTH            7
++
++/*
++ * SGTL5000_CHIP_ANA_CTRL
++ */
++#define SGTL5000_LINE_OUT_MUTE                0x0100
++#define SGTL5000_HP_SEL_MASK                  0x0040
++#define SGTL5000_HP_SEL_SHIFT                 6
++#define SGTL5000_HP_SEL_WIDTH                 1
++#define SGTL5000_HP_SEL_DAC                   0x0
++#define SGTL5000_HP_SEL_LINE_IN                       0x1
++#define SGTL5000_HP_ZCD_EN                    0x0020
++#define SGTL5000_HP_MUTE                      0x0010
++#define SGTL5000_ADC_SEL_MASK                 0x0004
++#define SGTL5000_ADC_SEL_SHIFT                        2
++#define SGTL5000_ADC_SEL_WIDTH                        1
++#define SGTL5000_ADC_SEL_MIC                  0x0
++#define SGTL5000_ADC_SEL_LINE_IN              0x1
++#define SGTL5000_ADC_ZCD_EN                   0x0002
++#define SGTL5000_ADC_MUTE                     0x0001
++
++/*
++ * SGTL5000_CHIP_LINREG_CTRL
++ */
++#define SGTL5000_VDDC_MAN_ASSN_MASK           0x0040
++#define SGTL5000_VDDC_MAN_ASSN_SHIFT          6
++#define SGTL5000_VDDC_MAN_ASSN_WIDTH          1
++#define SGTL5000_VDDC_MAN_ASSN_VDDA           0x0
++#define SGTL5000_VDDC_MAN_ASSN_VDDIO          0x1
++#define SGTL5000_VDDC_ASSN_OVRD                       0x0020
++#define SGTL5000_LINREG_VDDD_MASK             0x000f
++#define SGTL5000_LINREG_VDDD_SHIFT            0
++#define SGTL5000_LINREG_VDDD_WIDTH            4
++
++/*
++ * SGTL5000_CHIP_REF_CTRL
++ */
++#define SGTL5000_ANA_GND_MASK                 0x01f0
++#define SGTL5000_ANA_GND_SHIFT                        4
++#define SGTL5000_ANA_GND_WIDTH                        5
++#define SGTL5000_ANA_GND_BASE                 800     /* mv */
++#define SGTL5000_ANA_GND_STP                  25      /*mv */
++#define SGTL5000_BIAS_CTRL_MASK                       0x000e
++#define SGTL5000_BIAS_CTRL_SHIFT              1
++#define SGTL5000_BIAS_CTRL_WIDTH              3
++#define SGTL5000_SMALL_POP                    0x0001
++
++/*
++ * SGTL5000_CHIP_MIC_CTRL
++ */
++#define SGTL5000_BIAS_R_MASK                  0x0200
++#define SGTL5000_BIAS_R_SHIFT                 8
++#define SGTL5000_BIAS_R_WIDTH                 2
++#define SGTL5000_BIAS_R_off                   0x0
++#define SGTL5000_BIAS_R_2K                    0x1
++#define SGTL5000_BIAS_R_4k                    0x2
++#define SGTL5000_BIAS_R_8k                    0x3
++#define SGTL5000_BIAS_VOLT_MASK                       0x0070
++#define SGTL5000_BIAS_VOLT_SHIFT              4
++#define SGTL5000_BIAS_VOLT_WIDTH              3
++#define SGTL5000_MIC_GAIN_MASK                        0x0003
++#define SGTL5000_MIC_GAIN_SHIFT                       0
++#define SGTL5000_MIC_GAIN_WIDTH                       2
++
++/*
++ * SGTL5000_CHIP_LINE_OUT_CTRL
++ */
++#define SGTL5000_LINE_OUT_CURRENT_MASK                0x0f00
++#define SGTL5000_LINE_OUT_CURRENT_SHIFT               8
++#define SGTL5000_LINE_OUT_CURRENT_WIDTH               4
++#define SGTL5000_LINE_OUT_CURRENT_180u                0x0
++#define SGTL5000_LINE_OUT_CURRENT_270u                0x1
++#define SGTL5000_LINE_OUT_CURRENT_360u                0x3
++#define SGTL5000_LINE_OUT_CURRENT_450u                0x7
++#define SGTL5000_LINE_OUT_CURRENT_540u                0xf
++#define SGTL5000_LINE_OUT_GND_MASK            0x003f
++#define SGTL5000_LINE_OUT_GND_SHIFT           0
++#define SGTL5000_LINE_OUT_GND_WIDTH           6
++#define SGTL5000_LINE_OUT_GND_BASE            800     /* mv */
++#define SGTL5000_LINE_OUT_GND_STP             25
++#define SGTL5000_LINE_OUT_GND_MAX             0x23
++
++/*
++ * SGTL5000_CHIP_LINE_OUT_VOL
++ */
++#define SGTL5000_LINE_OUT_VOL_RIGHT_MASK      0x1f00
++#define SGTL5000_LINE_OUT_VOL_RIGHT_SHIFT     8
++#define SGTL5000_LINE_OUT_VOL_RIGHT_WIDTH     5
++#define SGTL5000_LINE_OUT_VOL_LEFT_MASK               0x001f
++#define SGTL5000_LINE_OUT_VOL_LEFT_SHIFT      0
++#define SGTL5000_LINE_OUT_VOL_LEFT_WIDTH      5
++
++/*
++ * SGTL5000_CHIP_ANA_POWER
++ */
++#define SGTL5000_DAC_STEREO                   0x4000
++#define SGTL5000_LINREG_SIMPLE_POWERUP                0x2000
++#define SGTL5000_STARTUP_POWERUP              0x1000
++#define SGTL5000_VDDC_CHRGPMP_POWERUP         0x0800
++#define SGTL5000_PLL_POWERUP                  0x0400
++#define SGTL5000_LINEREG_D_POWERUP            0x0200
++#define SGTL5000_VCOAMP_POWERUP                       0x0100
++#define SGTL5000_VAG_POWERUP                  0x0080
++#define SGTL5000_ADC_STEREO                   0x0040
++#define SGTL5000_REFTOP_POWERUP                       0x0020
++#define SGTL5000_HP_POWERUP                   0x0010
++#define SGTL5000_DAC_POWERUP                  0x0008
++#define SGTL5000_CAPLESS_HP_POWERUP           0x0004
++#define SGTL5000_ADC_POWERUP                  0x0002
++#define SGTL5000_LINE_OUT_POWERUP             0x0001
++
++/*
++ * SGTL5000_CHIP_PLL_CTRL
++ */
++#define SGTL5000_PLL_INT_DIV_MASK             0xf800
++#define SGTL5000_PLL_INT_DIV_SHIFT            11
++#define SGTL5000_PLL_INT_DIV_WIDTH            5
++#define SGTL5000_PLL_FRAC_DIV_MASK            0x0700
++#define SGTL5000_PLL_FRAC_DIV_SHIFT           0
++#define SGTL5000_PLL_FRAC_DIV_WIDTH           11
++
++/*
++ * SGTL5000_CHIP_CLK_TOP_CTRL
++ */
++#define SGTL5000_INT_OSC_EN                   0x0800
++#define SGTL5000_INPUT_FREQ_DIV2              0x0008
++
++/*
++ * SGTL5000_CHIP_ANA_STATUS
++ */
++#define SGTL5000_HP_LRSHORT                   0x0200
++#define SGTL5000_CAPLESS_SHORT                        0x0100
++#define SGTL5000_PLL_LOCKED                   0x0010
++
++/*
++ * SGTL5000_CHIP_SHORT_CTRL
++ */
++#define SGTL5000_LVLADJR_MASK                 0x7000
++#define SGTL5000_LVLADJR_SHIFT                        12
++#define SGTL5000_LVLADJR_WIDTH                        3
++#define SGTL5000_LVLADJL_MASK                 0x0700
++#define SGTL5000_LVLADJL_SHIFT                        8
++#define SGTL5000_LVLADJL_WIDTH                        3
++#define SGTL5000_LVLADJC_MASK                 0x0070
++#define SGTL5000_LVLADJC_SHIFT                        4
++#define SGTL5000_LVLADJC_WIDTH                        3
++#define SGTL5000_LR_SHORT_MOD_MASK            0x000c
++#define SGTL5000_LR_SHORT_MOD_SHIFT           2
++#define SGTL5000_LR_SHORT_MOD_WIDTH           2
++#define SGTL5000_CM_SHORT_MOD_MASK            0x0003
++#define SGTL5000_CM_SHORT_MOD_SHIFT           0
++#define SGTL5000_CM_SHORT_MOD_WIDTH           2
++
++/*
++ *SGTL5000_CHIP_ANA_TEST2
++ */
++#define SGTL5000_MONO_DAC                     0x1000
++
++/*
++ * SGTL5000_DAP_CTRL
++ */
++#define SGTL5000_DAP_MIX_EN                   0x0010
++#define SGTL5000_DAP_EN                               0x0001
++
++#define SGTL5000_SYSCLK               0x00
++#define SGTL5000_LRCLK                0x01
++
++#endif
+diff -urN linux.35.old/sound/soc/imx/imx-3stack-sgtl5000.c linux.35.new/sound/soc/imx/imx-3stack-sgtl5000.c
+--- linux.35.old/sound/soc/imx/imx-3stack-sgtl5000.c   1970-01-01 01:00:00.000000000 +0100
++++ linux.35.new/sound/soc/imx/imx-3stack-sgtl5000.c   2010-12-03 09:51:55.492348513 +0100
+@@ -0,0 +1,654 @@
++/*
++ * imx-3stack-sgtl5000.c  --  i.MX 3Stack Driver for Freescale SGTL5000 Codec
++ *
++ * Copyright (C) 2008-2010 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.
++ *
++ *  Revision history
++ *    21th Oct 2008   Initial version.
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/bitops.h>
++#include <linux/platform_device.h>
++#include <linux/i2c.h>
++#include <linux/err.h>
++#include <linux/irq.h>
++#include <linux/io.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/pcm_params.h>
++#include <sound/soc.h>
++#include <sound/soc-dapm.h>
++#include <sound/initval.h>
++
++#include <mach/dma.h>
++#include <mach/clock.h>
++#include <mach/ssi.h>
++
++#include "../codecs/sgtl5000.h"
++#include "imx-ssi.h"
++//#include "imx-pcm.h"
++
++#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE)
++#include <linux/mxc_asrc.h>
++
++static unsigned int sgtl5000_rates[] = {
++      0,
++      32000,
++      44100,
++      48000,
++      96000,
++};
++
++struct asrc_esai {
++      unsigned int cpu_dai_rates;
++      unsigned int codec_dai_rates;
++      enum asrc_pair_index asrc_index;
++      unsigned int output_sample_rate;
++};
++
++static struct asrc_esai asrc_ssi_data;
++#endif
++
++/* SSI BCLK and LRC master */
++#define SGTL5000_SSI_MASTER   1
++
++struct imx_3stack_priv {
++      int sysclk;
++      int hw;
++      struct platform_device *pdev;
++};
++
++static struct imx_3stack_priv card_priv;
++
++static int imx_3stack_audio_hw_params(struct snd_pcm_substream *substream,
++                                    struct snd_pcm_hw_params *params)
++{
++      struct snd_soc_pcm_runtime *rtd = substream->private_data;
++      struct snd_soc_dai_link *machine = rtd->dai;
++      struct snd_soc_dai *cpu_dai = machine->cpu_dai;
++      struct snd_soc_dai *codec_dai = machine->codec_dai;
++      struct imx_3stack_priv *priv = &card_priv;
++      unsigned int rate = params_rate(params);
++      struct imx_ssi *ssi_mode = (struct imx_ssi *)cpu_dai->private_data;
++      int ret = 0;
++
++      unsigned int channels = params_channels(params);
++      u32 dai_format;
++
++      /* only need to do this once as capture and playback are sync */
++      if (priv->hw)
++              return 0;
++      priv->hw = 1;
++
++#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE)
++      if ((asrc_ssi_data.output_sample_rate != 0)
++          && (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) {
++              unsigned int asrc_input_rate = rate;
++              unsigned int channel = params_channels(params);
++              struct mxc_runtime_data *pcm_data =
++                  substream->runtime->private_data;
++              struct asrc_config config;
++              struct mxc_audio_platform_data *plat;
++              struct imx_3stack_priv *priv = &card_priv;
++              int retVal = 0;
++              retVal = asrc_req_pair(channel, &asrc_ssi_data.asrc_index);
++              if (retVal < 0) {
++                      pr_err("asrc_req_pair fail\n");
++                      return -1;
++              }
++              config.pair = asrc_ssi_data.asrc_index;
++              config.channel_num = channel;
++              config.input_sample_rate = asrc_input_rate;
++              config.output_sample_rate = asrc_ssi_data.output_sample_rate;
++              config.inclk = INCLK_NONE;
++              config.word_width = 32;
++              plat = priv->pdev->dev.platform_data;
++              if (plat->src_port == 1)
++                      config.outclk = OUTCLK_SSI1_TX;
++              else
++                      config.outclk = OUTCLK_SSI2_TX;
++              retVal = asrc_config_pair(&config);
++              if (retVal < 0) {
++                      pr_err("Fail to config asrc\n");
++                      asrc_release_pair(asrc_ssi_data.asrc_index);
++                      return retVal;
++              }
++              rate = asrc_ssi_data.output_sample_rate;
++              pcm_data->asrc_index = asrc_ssi_data.asrc_index;
++              pcm_data->asrc_enable = 1;
++      }
++#endif
++
++      snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, priv->sysclk, 0);
++      snd_soc_dai_set_sysclk(codec_dai, SGTL5000_LRCLK, rate, 0);
++
++#if SGTL5000_SSI_MASTER
++      dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++          SND_SOC_DAIFMT_CBM_CFM;
++#else
++      dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
++          SND_SOC_DAIFMT_CBS_CFS;
++#endif
++
++      ssi_mode->flags = IMX_SSI_SYN;
++      if (channels == 1)
++              ssi_mode->flags &= ~IMX_SSI_NET;
++      else
++              ssi_mode->flags |= IMX_SSI_NET;
++
++      /* set codec DAI configuration */
++      ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
++      if (ret < 0)
++              return ret;
++
++      /* set i.MX active slot mask */
++        switch (channels) {
++        case 2:
++                snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffc, 0xffffffc, 2, 0);
++                break;
++        case 1:
++                snd_soc_dai_set_tdm_slot(cpu_dai, 0xffffffe, 0xffffffe, 1, 0);
++                break;
++        default:
++                return -EINVAL;
++        }
++
++      /* set cpu DAI configuration */
++      ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
++      if (ret < 0)
++              return ret;
++
++      /* set the SSI system clock as input (unused) */
++      snd_soc_dai_set_sysclk(cpu_dai, IMX_SSP_SYS_CLK, 0, SND_SOC_CLOCK_IN);
++
++      return 0;
++}
++
++static int imx_3stack_startup(struct snd_pcm_substream *substream)
++{
++#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE)
++      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++              if (asrc_ssi_data.output_sample_rate != 0) {
++                      struct snd_soc_pcm_runtime *rtd =
++                          substream->private_data;
++                      struct snd_soc_dai_link *pcm_link = rtd->dai;
++                      struct snd_soc_dai *cpu_dai = pcm_link->cpu_dai;
++                      struct snd_soc_dai *codec_dai = pcm_link->codec_dai;
++                      asrc_ssi_data.cpu_dai_rates = cpu_dai->playback.rates;
++                      asrc_ssi_data.codec_dai_rates =
++                          codec_dai->playback.rates;
++                      cpu_dai->playback.rates =
++                          SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT;
++                      codec_dai->playback.rates =
++                          SNDRV_PCM_RATE_8000_192000 | SNDRV_PCM_RATE_KNOT;
++              }
++      }
++#endif
++      return 0;
++}
++
++static void imx_3stack_shutdown(struct snd_pcm_substream *substream)
++{
++      struct imx_3stack_priv *priv = &card_priv;
++
++#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE)
++      if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++              if (asrc_ssi_data.output_sample_rate != 0) {
++                      struct snd_soc_pcm_runtime *rtd =
++                          substream->private_data;
++                      struct snd_soc_dai_link *pcm_link = rtd->dai;
++                      struct snd_soc_dai *cpu_dai = pcm_link->cpu_dai;
++                      struct snd_soc_dai *codec_dai = pcm_link->codec_dai;
++                      codec_dai->playback.rates =
++                          asrc_ssi_data.codec_dai_rates;
++                      cpu_dai->playback.rates = asrc_ssi_data.cpu_dai_rates;
++                      asrc_release_pair(asrc_ssi_data.asrc_index);
++              }
++      }
++#endif
++
++      priv->hw = 0;
++}
++
++/*
++ * imx_3stack SGTL5000 audio DAI opserations.
++ */
++static struct snd_soc_ops imx_3stack_ops = {
++      .startup = imx_3stack_startup,
++      .shutdown = imx_3stack_shutdown,
++      .hw_params = imx_3stack_audio_hw_params,
++};
++
++/* imx_3stack machine connections to the codec pins */
++static const struct snd_soc_dapm_route audio_map[] = {
++
++      /* Mic Jack --> MIC_IN (with automatic bias) */
++      {"MIC_IN", NULL, "Mic Jack"},
++
++      /* Line in Jack --> LINE_IN */
++      {"LINE_IN", NULL, "Line In Jack"},
++
++      /* HP_OUT --> Headphone Jack */
++      {"Headphone Jack", NULL, "HP_OUT"},
++
++      /* LINE_OUT --> Ext Speaker */
++      {"Ext Spk", NULL, "LINE_OUT"},
++};
++
++static int sgtl5000_jack_func;
++static int sgtl5000_spk_func;
++static int sgtl5000_line_in_func;
++
++static void headphone_detect_handler(struct work_struct *work)
++{
++      struct imx_3stack_priv *priv = &card_priv;
++      struct platform_device *pdev = priv->pdev;
++      struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
++      int hp_status;
++
++      sysfs_notify(&pdev->dev.kobj, NULL, "headphone");
++      hp_status = plat->hp_status();
++      if (hp_status)
++              set_irq_type(plat->hp_irq, IRQ_TYPE_EDGE_FALLING);
++      else
++              set_irq_type(plat->hp_irq, IRQ_TYPE_EDGE_RISING);
++      enable_irq(plat->hp_irq);
++}
++
++static DECLARE_DELAYED_WORK(hp_event, headphone_detect_handler);
++
++static irqreturn_t imx_headphone_detect_handler(int irq, void *data)
++{
++      disable_irq_nosync(irq);
++      schedule_delayed_work(&hp_event, msecs_to_jiffies(200));
++      return IRQ_HANDLED;
++}
++
++static ssize_t show_headphone(struct device_driver *dev, char *buf)
++{
++      struct imx_3stack_priv *priv = &card_priv;
++      struct platform_device *pdev = priv->pdev;
++      struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
++      u16 hp_status;
++
++      /* determine whether hp is plugged in */
++      hp_status = plat->hp_status();
++
++      if (hp_status == 0)
++              strcpy(buf, "speaker\n");
++      else
++              strcpy(buf, "headphone\n");
++
++      return strlen(buf);
++}
++
++static DRIVER_ATTR(headphone, S_IRUGO | S_IWUSR, show_headphone, NULL);
++
++static const char *jack_function[] = { "off", "on"};
++
++static const char *spk_function[] = { "off", "on" };
++
++static const char *line_in_function[] = { "off", "on" };
++
++static const struct soc_enum sgtl5000_enum[] = {
++      SOC_ENUM_SINGLE_EXT(2, jack_function),
++      SOC_ENUM_SINGLE_EXT(2, spk_function),
++      SOC_ENUM_SINGLE_EXT(2, line_in_function),
++};
++
++static int sgtl5000_get_jack(struct snd_kcontrol *kcontrol,
++                           struct snd_ctl_elem_value *ucontrol)
++{
++      ucontrol->value.enumerated.item[0] = sgtl5000_jack_func;
++      return 0;
++}
++
++static int sgtl5000_set_jack(struct snd_kcontrol *kcontrol,
++                           struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++
++      if (sgtl5000_jack_func == ucontrol->value.enumerated.item[0])
++              return 0;
++
++      sgtl5000_jack_func = ucontrol->value.enumerated.item[0];
++      if (sgtl5000_jack_func)
++              snd_soc_dapm_enable_pin(codec, "Headphone Jack");
++      else
++              snd_soc_dapm_disable_pin(codec, "Headphone Jack");
++
++      snd_soc_dapm_sync(codec);
++      return 1;
++}
++
++static int sgtl5000_get_spk(struct snd_kcontrol *kcontrol,
++                          struct snd_ctl_elem_value *ucontrol)
++{
++      ucontrol->value.enumerated.item[0] = sgtl5000_spk_func;
++      return 0;
++}
++
++static int sgtl5000_set_spk(struct snd_kcontrol *kcontrol,
++                          struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++
++      if (sgtl5000_spk_func == ucontrol->value.enumerated.item[0])
++              return 0;
++
++      sgtl5000_spk_func = ucontrol->value.enumerated.item[0];
++      if (sgtl5000_spk_func)
++              snd_soc_dapm_enable_pin(codec, "Ext Spk");
++      else
++              snd_soc_dapm_disable_pin(codec, "Ext Spk");
++
++      snd_soc_dapm_sync(codec);
++      return 1;
++}
++
++static int sgtl5000_get_line_in(struct snd_kcontrol *kcontrol,
++                           struct snd_ctl_elem_value *ucontrol)
++{
++      ucontrol->value.enumerated.item[0] = sgtl5000_line_in_func;
++      return 0;
++}
++
++static int sgtl5000_set_line_in(struct snd_kcontrol *kcontrol,
++                           struct snd_ctl_elem_value *ucontrol)
++{
++      struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
++
++      if (sgtl5000_line_in_func == ucontrol->value.enumerated.item[0])
++              return 0;
++
++      sgtl5000_line_in_func = ucontrol->value.enumerated.item[0];
++      if (sgtl5000_line_in_func)
++              snd_soc_dapm_enable_pin(codec, "Line In Jack");
++      else
++              snd_soc_dapm_disable_pin(codec, "Line In Jack");
++
++      snd_soc_dapm_sync(codec);
++      return 1;
++}
++
++static int spk_amp_event(struct snd_soc_dapm_widget *w,
++                       struct snd_kcontrol *kcontrol, int event)
++{
++      struct imx_3stack_priv *priv = &card_priv;
++      struct platform_device *pdev = priv->pdev;
++      struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
++
++      if (plat->amp_enable == NULL)
++              return 0;
++
++      if (SND_SOC_DAPM_EVENT_ON(event))
++              plat->amp_enable(1);
++      else
++              plat->amp_enable(0);
++
++      return 0;
++}
++
++/* imx_3stack card dapm widgets */
++static const struct snd_soc_dapm_widget imx_3stack_dapm_widgets[] = {
++      SND_SOC_DAPM_MIC("Mic Jack", NULL),
++      SND_SOC_DAPM_LINE("Line In Jack", NULL),
++      SND_SOC_DAPM_SPK("Ext Spk", spk_amp_event),
++      SND_SOC_DAPM_HP("Headphone Jack", NULL),
++};
++
++static const struct snd_kcontrol_new sgtl5000_machine_controls[] = {
++      SOC_ENUM_EXT("Jack Function", sgtl5000_enum[0], sgtl5000_get_jack,
++                   sgtl5000_set_jack),
++      SOC_ENUM_EXT("Speaker Function", sgtl5000_enum[1], sgtl5000_get_spk,
++                   sgtl5000_set_spk),
++      SOC_ENUM_EXT("Line In Function", sgtl5000_enum[1], sgtl5000_get_line_in,
++                   sgtl5000_set_line_in),
++};
++
++#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE)
++static int asrc_func;
++
++static const char *asrc_function[] =
++    { "disable", "32KHz", "44.1KHz", "48KHz", "96KHz" };
++
++static const struct soc_enum asrc_enum[] = {
++      SOC_ENUM_SINGLE_EXT(5, asrc_function),
++};
++
++static int asrc_get_rate(struct snd_kcontrol *kcontrol,
++                       struct snd_ctl_elem_value *ucontrol)
++{
++      ucontrol->value.enumerated.item[0] = asrc_func;
++      return 0;
++}
++
++static int asrc_set_rate(struct snd_kcontrol *kcontrol,
++                       struct snd_ctl_elem_value *ucontrol)
++{
++      if (asrc_func == ucontrol->value.enumerated.item[0])
++              return 0;
++
++      asrc_func = ucontrol->value.enumerated.item[0];
++      asrc_ssi_data.output_sample_rate = sgtl5000_rates[asrc_func];
++
++      return 1;
++}
++
++static const struct snd_kcontrol_new asrc_controls[] = {
++      SOC_ENUM_EXT("ASRC", asrc_enum[0], asrc_get_rate,
++                   asrc_set_rate),
++};
++#endif
++
++static int imx_3stack_sgtl5000_init(struct snd_soc_codec *codec)
++{
++      int i, ret;
++
++#if defined(CONFIG_MXC_ASRC) || defined(CONFIG_MXC_ASRC_MODULE)
++      for (i = 0; i < ARRAY_SIZE(asrc_controls); i++) {
++              ret = snd_ctl_add(codec->card,
++                                snd_soc_cnew(&asrc_controls[i], codec, NULL));
++              if (ret < 0)
++                      return ret;
++      }
++      asrc_ssi_data.output_sample_rate = sgtl5000_rates[asrc_func];
++#endif
++
++      /* Add imx_3stack specific controls */
++      for (i = 0; i < ARRAY_SIZE(sgtl5000_machine_controls); i++) {
++              ret = snd_ctl_add(codec->card,
++                                snd_soc_cnew(&sgtl5000_machine_controls[i],
++                                             codec, NULL));
++              if (ret < 0)
++                      return ret;
++      }
++
++      /* Add imx_3stack specific widgets */
++      snd_soc_dapm_new_controls(codec, imx_3stack_dapm_widgets,
++                                ARRAY_SIZE(imx_3stack_dapm_widgets));
++
++      /* Set up imx_3stack specific audio path audio_map */
++      snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
++
++      snd_soc_dapm_disable_pin(codec, "Line In Jack");
++
++      snd_soc_dapm_sync(codec);
++
++      return 0;
++}
++
++/* imx_3stack digital audio interface glue - connects codec <--> CPU */
++static struct snd_soc_dai_link imx_3stack_dai = {
++      .name = "SGTL5000",
++      .stream_name = "SGTL5000",
++      .codec_dai = &sgtl5000_dai,
++      .init = imx_3stack_sgtl5000_init,
++      .ops = &imx_3stack_ops,
++};
++
++static int imx_3stack_card_remove(struct platform_device *pdev)
++{
++      struct imx_3stack_priv *priv = &card_priv;
++      struct mxc_audio_platform_data *plat;
++      if (priv->pdev) {
++              plat = priv->pdev->dev.platform_data;
++              if (plat->finit)
++                      plat->finit();
++      }
++
++      return 0;
++}
++
++static struct snd_soc_card snd_soc_card_imx_3stack = {
++      .name = "imx-3stack",
++      .platform = &imx_soc_platform,
++      .dai_link = &imx_3stack_dai,
++      .num_links = 1,
++      .remove = imx_3stack_card_remove,
++};
++
++static struct snd_soc_device imx_3stack_snd_devdata = {
++      .card = &snd_soc_card_imx_3stack,
++      .codec_dev = &soc_codec_dev_sgtl5000,
++};
++
++static int __devinit imx_3stack_sgtl5000_probe(struct platform_device *pdev)
++{
++      struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
++      struct imx_3stack_priv *priv = &card_priv;
++      struct snd_soc_dai *sgtl5000_cpu_dai;
++      int ret = 0;
++
++      priv->pdev = pdev;
++
++      //gpio_activate_audio_ports();
++
++//    if (plat->src_port == 2)                        // MASU S1
++//            sgtl5000_cpu_dai = &imx_ssi_dai[2];     // MASU S1
++//    else                                            // MASU S1
++//            sgtl5000_cpu_dai = &imx_ssi_dai[0];     // MASU S1
++sgtl5000_cpu_dai = &imx_ssi_pcm_dai[0];       // MASU S1
++
++      imx_3stack_dai.cpu_dai = sgtl5000_cpu_dai;
++
++      ret = driver_create_file(pdev->dev.driver, &driver_attr_headphone);
++      if (ret < 0) {
++              pr_err("%s:failed to create driver_attr_headphone\n", __func__);
++              goto sysfs_err;
++      }
++
++      if (plat->init) {
++              ret = plat->init();
++              if (ret)
++                      goto err_plat_init;
++      }
++
++      priv->sysclk = plat->sysclk;
++
++      /* The SGTL5000 has an internal reset that is deasserted 8 SYS_MCLK
++         cycles after all power rails have been brought up. After this time
++         communication can start */
++
++      if ((plat->hp_status != NULL)) {
++              if (plat->hp_status())
++                      ret = request_irq(plat->hp_irq,
++                                        imx_headphone_detect_handler,
++                                        IRQ_TYPE_EDGE_FALLING, pdev->name, priv);
++              else
++                      ret = request_irq(plat->hp_irq,
++                                        imx_headphone_detect_handler,
++                                        IRQ_TYPE_EDGE_RISING, pdev->name, priv);
++              if (ret < 0) {
++                      pr_err("%s: request irq failed\n", __func__);
++                      goto err_card_reg;
++              }
++              sgtl5000_jack_func = 1;
++      } else {
++              sgtl5000_jack_func = 0;
++      }
++      sgtl5000_spk_func = 1;
++      sgtl5000_line_in_func = 0;
++
++      return 0;
++
++err_card_reg:
++      if (plat->finit)
++              plat->finit();
++err_plat_init:
++      driver_remove_file(pdev->dev.driver, &driver_attr_headphone);
++sysfs_err:
++      return ret;
++}
++
++static int imx_3stack_sgtl5000_remove(struct platform_device *pdev)
++{
++      struct mxc_audio_platform_data *plat = pdev->dev.platform_data;
++      struct imx_3stack_priv *priv = &card_priv;
++
++      if (plat->hp_status != NULL)
++              free_irq(plat->hp_irq, priv);
++
++      if (plat->finit)
++              plat->finit();
++
++      driver_remove_file(pdev->dev.driver, &driver_attr_headphone);
++
++      return 0;
++}
++
++static struct platform_driver imx_3stack_sgtl5000_audio_driver = {
++      .probe = imx_3stack_sgtl5000_probe,
++      .remove = imx_3stack_sgtl5000_remove,
++      .driver = {
++                 .name = "imx-3stack-sgtl5000",
++                 },
++};
++
++static struct platform_device *imx_3stack_snd_device;
++
++static int __init imx_3stack_init(void)
++{
++      int ret;
++
++      ret = platform_driver_register(&imx_3stack_sgtl5000_audio_driver);
++      if (ret)
++              return -ENOMEM;
++
++      imx_3stack_snd_device = platform_device_alloc("soc-audio", 2);
++      if (!imx_3stack_snd_device)
++              return -ENOMEM;
++
++      platform_set_drvdata(imx_3stack_snd_device, &imx_3stack_snd_devdata);
++      imx_3stack_snd_devdata.dev = &imx_3stack_snd_device->dev;
++      ret = platform_device_add(imx_3stack_snd_device);
++
++      if (ret)
++              platform_device_put(imx_3stack_snd_device);
++
++      return ret;
++}
++
++static void __exit imx_3stack_exit(void)
++{
++      platform_driver_unregister(&imx_3stack_sgtl5000_audio_driver);
++      platform_device_unregister(imx_3stack_snd_device);
++}
++
++module_init(imx_3stack_init);
++module_exit(imx_3stack_exit);
++
++MODULE_AUTHOR("Freescale Semiconductor, Inc.");
++MODULE_DESCRIPTION("SGTL5000 Driver for i.MX 3STACK");
++MODULE_LICENSE("GPL");
+diff -urN linux.35.old/sound/soc/imx/imx-pcm-fiq.c linux.35.new/sound/soc/imx/imx-pcm-fiq.c
+--- linux.35.old/sound/soc/imx/imx-pcm-fiq.c   2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/sound/soc/imx/imx-pcm-fiq.c   2010-12-03 09:51:55.496348495 +0100
+@@ -192,6 +192,8 @@
+       int ret;
+       iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
++      if (iprtd == NULL)
++              return -ENOMEM;
+       runtime->private_data = iprtd;
+       iprtd->substream = substream;
+@@ -202,8 +204,10 @@
+       ret = snd_pcm_hw_constraint_integer(substream->runtime,
+                       SNDRV_PCM_HW_PARAM_PERIODS);
+-      if (ret < 0)
++      if (ret < 0) {
++              kfree(iprtd);
+               return ret;
++      }
+       snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
+       return 0;
+diff -urN linux.35.old/sound/soc/imx/imx-ssi.c linux.35.new/sound/soc/imx/imx-ssi.c
+--- linux.35.old/sound/soc/imx/imx-ssi.c       2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/sound/soc/imx/imx-ssi.c       2010-12-03 09:51:55.496348495 +0100
+@@ -23,7 +23,7 @@
+  * between pcm data and GPIO status data changes. Our FIQ handler is not
+  * able to handle this, hence this driver only works with 48000Hz sampling
+  * rate.
+- * Reading and writing AC97 registers is another challange. The core
++ * Reading and writing AC97 registers is another challenge. The core
+  * provides us status bits when the read register is updated with *another*
+  * value. When we read the same register two times (and the register still
+  * contains the same value) these status bits are not set. We work
+@@ -83,8 +83,6 @@
+ /*
+  * SSI DAI format configuration.
+  * Should only be called when port is inactive (i.e. SSIEN = 0).
+- * Note: We don't use the I2S modes but instead manually configure the
+- * SSI for I2S because the I2S mode is only a register preset.
+  */
+ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+ {
+@@ -99,6 +97,10 @@
+               /* data on rising edge of bclk, frame low 1clk before data */
+               strcr |= SSI_STCR_TFSI | SSI_STCR_TEFS | SSI_STCR_TXBIT0;
+               scr |= SSI_SCR_NET;
++              if (ssi->flags & IMX_SSI_USE_I2S_SLAVE) {
++                      scr &= ~SSI_I2S_MODE_MASK;
++                      scr |= SSI_SCR_I2S_MODE_SLAVE;
++              }
+               break;
+       case SND_SOC_DAIFMT_LEFT_J:
+               /* data on rising edge of bclk, frame high with data */
+@@ -143,6 +145,11 @@
+       strcr |= SSI_STCR_TFEN0;
++      if (ssi->flags & IMX_SSI_NET)
++              scr |= SSI_SCR_NET;
++      if (ssi->flags & IMX_SSI_SYN)
++              scr |= SSI_SCR_SYN;
++
+       writel(strcr, ssi->base + SSI_STCR);
+       writel(strcr, ssi->base + SSI_SRCR);
+       writel(scr, ssi->base + SSI_SCR);
+diff -urN linux.35.old/sound/soc/imx/Kconfig linux.35.new/sound/soc/imx/Kconfig
+--- linux.35.old/sound/soc/imx/Kconfig 2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/sound/soc/imx/Kconfig 2010-12-03 09:51:55.496348495 +0100
+@@ -1,4 +1,4 @@
+-config SND_IMX_SOC
++menuconfig SND_IMX_SOC
+       tristate "SoC Audio for Freescale i.MX CPUs"
+       depends on ARCH_MXC
+       select SND_PCM
+@@ -8,14 +8,12 @@
+         Say Y or M if you want to add support for codecs attached to
+         the i.MX SSI interface.
+-config SND_MXC_SOC_SSI
+-      tristate
++if SND_IMX_SOC
+ config SND_MXC_SOC_WM1133_EV1
+       tristate "Audio on the the i.MX31ADS with WM1133-EV1 fitted"
+-      depends on SND_IMX_SOC && MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
++      depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
+       select SND_SOC_WM8350
+-      select SND_MXC_SOC_SSI
+       help
+         Enable support for audio on the i.MX31ADS with the WM1133-EV1
+         PMIC board with WM8835x fitted.
+@@ -23,8 +21,16 @@
+ config SND_SOC_PHYCORE_AC97
+       tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
+       depends on MACH_PCM043 || MACH_PCA100
+-      select SND_MXC_SOC_SSI
+       select SND_SOC_WM9712
+       help
+         Say Y if you want to add support for SoC audio on Phytec phyCORE
+         and phyCARD boards in AC97 mode
++
++config SND_SOC_IMX_3STACK_SGTL5000
++      tristate "SoC Audio support for IMX - SGTL5000"
++      select SND_SOC_SGTL5000
++      help
++        Say Y if you want to add support for SoC audio on IMX 3STACK
++        with the SGTL5000.
++
++endif # SND_IMX_SOC
+diff -urN linux.35.old/sound/soc/imx/Makefile linux.35.new/sound/soc/imx/Makefile
+--- linux.35.old/sound/soc/imx/Makefile        2010-08-02 00:11:14.000000000 +0200
++++ linux.35.new/sound/soc/imx/Makefile        2010-12-03 09:51:55.496348495 +0100
+@@ -8,8 +8,10 @@
+ obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o
+ # i.MX Machine Support
++snd-soc-imx-3stack-sgtl5000-objs := imx-3stack-sgtl5000.o
+ snd-soc-phycore-ac97-objs := phycore-ac97.o
+ snd-soc-wm1133-ev1-objs := wm1133-ev1.o
++obj-$(CONFIG_SND_SOC_IMX_3STACK_SGTL5000) += snd-soc-imx-3stack-sgtl5000.o
+ obj-$(CONFIG_SND_SOC_PHYCORE_AC97) += snd-soc-phycore-ac97.o
+ obj-$(CONFIG_SND_MXC_SOC_WM1133_EV1) += snd-soc-wm1133-ev1.o
index 98edfaa..5060c02 100644 (file)
@@ -15,6 +15,7 @@ DEFAULT_PREFERENCE_qemumips64 = "1"
 DEFAULT_PREFERENCE_qemuppc = "1"
 DEFAULT_PREFERENCE_qemux86 = "1"
 DEFAULT_PREFERENCE_nokia900 = "1"
+DEFAULT_PREFERENCE_vmx25 = "1"
 
 SRC_URI = "${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/${P}.tar.bz2;name=kernel \
            ${KERNELORG_MIRROR}/pub/linux/kernel/v2.6/patch-${PV}.${STABLEV}.bz2;apply=yes;name=stablepatch \
@@ -116,6 +117,8 @@ SRC_URI_nokia900 = "\
        file://inconsistent-mmc-fix-2.6.35.patch \
        file://defconfig "
 
+SRC_URI_append_vmx25 = "file://linux-2.6.35-vmx25-20110112.patch"
+
 CMDLINE_nokia900_shr = "snd-soc-rx51.hp_lim=42 snd-soc-tlv320aic3x.hp_dac_lim=6 console=tty1 root=/dev/mmcblk1p1 rootwait panic=20 debug"
 
 SRC_URI[kernel.md5sum] = "091abeb4684ce03d1d936851618687b6"