[oe] [PATCH v2] kernel: added support for vmx25 into recipe 2.6.35 kernel

Marek Sujak sujak.marek at gmail.com
Fri Jan 28 13:54:50 UTC 2011


* 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 at gmail.com>
---
 recipes/linux/linux-2.6.35/vmx25/defconfig         | 1771 ++
 .../vmx25/linux-2.6.35-vmx25-20110112.patch        |28459 ++++++++++++++++++++
 recipes/linux/linux_2.6.35.bb                      |    3 +
 3 files changed, 30233 insertions(+), 0 deletions(-)
 create mode 100644 recipes/linux/linux-2.6.35/vmx25/defconfig
 create mode 100644 recipes/linux/linux-2.6.35/vmx25/linux-2.6.35-vmx25-20110112.patch

diff --git a/recipes/linux/linux-2.6.35/vmx25/defconfig b/recipes/linux/linux-2.6.35/vmx25/defconfig
new file mode 100644
index 0000000..cbd23c5
--- /dev/null
+++ b/recipes/linux/linux-2.6.35/vmx25/defconfig
@@ -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 at 0x80000000 mem=32M at 0x90000000 ip=dhcp ubi.mtd=3 root=ubi0:rootfs rootfstype=ubifs otg_mode=host video=imxfb:VGA-16 at 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
index 0000000..f9aafd6
--- /dev/null
+++ b/recipes/linux/linux-2.6.35/vmx25/linux-2.6.35-vmx25-20110112.patch
@@ -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 at 0x80000000 mem=32M at 0x90000000 ip=dhcp ubi.mtd=3 root=ubi0:rootfs rootfstype=ubifs otg_mode=host video=imxfb:VGA-16 at 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 at 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 at voipac.com>
++ *
++ * Based on arch/arm/mach-mx25/karo-tx25.c 
++ * Copyright (C) 2009  Lothar Wassmann <LW at 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 at 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 at voipac.com>
++ *
++ * Based on arch/arm/mach-mx25/stk5-baseboard.c
++ * Copyright (C) 2009  Lothar Wassmann <LW at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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 at 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) 2^13*1000 > 2^22,
++	 * (2) host->timeout_clk < 2^16
++	 *     =>
++	 *     (1) / (2) > 2^6
++	 */
++	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 at 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 at pengutronix.de>, "
++	      "Marc Kleine-Budde <kernel at 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 at 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
diff --git a/recipes/linux/linux_2.6.35.bb b/recipes/linux/linux_2.6.35.bb
index 98edfaa..5060c02 100644
--- a/recipes/linux/linux_2.6.35.bb
+++ b/recipes/linux/linux_2.6.35.bb
@@ -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"
-- 
1.7.0.4





More information about the Openembedded-devel mailing list