Merge ../../omap/pristine into omap-merge
diff --git a/Makefile b/Makefile
index 49ed72e..79b3571 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,7 @@
 MAKEFLAGS += -rR --no-print-directory
 
 # Add custom flags here to avoid conflict with updates
-EXTRAVERSION := $(EXTRAVERSION)-omap1
+EXTRAVERSION := $(EXTRAVERSION)-davinci1
 
 # We are using a recursive build, so we need to do a little thinking
 # to get the ordering right.
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 2d9ae43..8e2c3dd 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -723,7 +723,8 @@
 config LEDS_TIMER
 	bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
 			    OMAP_OSK_MISTRAL || MACH_OMAP_H2 \
-			    || MACH_OMAP_PERSEUS2
+			    || MACH_OMAP_PERSEUS2 || MACH_DAVINCI_EVM
+
 	depends on LEDS
 	depends on !GENERIC_CLOCKEVENTS
 	default y if ARCH_EBSA110
@@ -1010,7 +1011,7 @@
 if PCMCIA || ARCH_CLPS7500 || ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX \
 	|| ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
 	|| ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE \
-	|| ARCH_IXP23XX
+	|| ARCH_IXP23XX || ARCH_DAVINCI
 source "drivers/ide/Kconfig"
 endif
 
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 830816a..587b029 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -130,6 +130,10 @@
  machine-$(CONFIG_ARCH_H720X)	   := h720x
  machine-$(CONFIG_ARCH_AAEC2000)   := aaec2000
  machine-$(CONFIG_ARCH_REALVIEW)   := realview
+ machine-$(CONFIG_ARCH_AT91)       := at91rm9200
+ machine-$(CONFIG_ARCH_EP93XX)     := ep93xx
+ machine-$(CONFIG_ARCH_PNX4008)    := pnx4008
+ machine-$(CONFIG_ARCH_NETX)       := netx
  machine-$(CONFIG_ARCH_AT91)	   := at91
  machine-$(CONFIG_ARCH_EP93XX)	   := ep93xx
  machine-$(CONFIG_ARCH_PNX4008)	   := pnx4008
diff --git a/arch/arm/configs/davinci_evm_dm644x_defconfig b/arch/arm/configs/davinci_evm_dm644x_defconfig
new file mode 100644
index 0000000..e64431a
--- /dev/null
+++ b/arch/arm/configs/davinci_evm_dm644x_defconfig
@@ -0,0 +1,1354 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.23-rc2-davinci1
+# Fri Aug 17 20:43:45 2007
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_USER_NS is not set
+# CONFIG_AUDIT is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_SYSFS_DEPRECATED=y
+# CONFIG_RELAY is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=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_ANON_INODES=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLAB=y
+# CONFIG_SLUB is not set
+# CONFIG_SLOB is not set
+CONFIG_RT_MUTEXES=y
+# CONFIG_TINY_SHMEM is not set
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_KMOD=y
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_LSF is not set
+# CONFIG_BLK_DEV_BSG is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX 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_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_DAVINCI=y
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_MACH_OMAP_APOLLON_PLUS is not set
+
+#
+# Boot options
+#
+
+#
+# Power management
+#
+
+#
+# TI DaVinci Implementations
+#
+
+#
+# DaVinci Core Type
+#
+CONFIG_ARCH_DAVINCI644x=y
+
+#
+# DaVinci Board Type
+#
+CONFIG_MACH_DAVINCI_EVM=y
+CONFIG_DAVINCI_I2C_EXPANDER=y
+CONFIG_DAVINCI_MCBSP=y
+
+#
+# DaVinci Options
+#
+# CONFIG_DAVINCI_BLK_DEV_CF is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+
+#
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+# CONFIG_TICK_ONESHOT is not set
+# CONFIG_NO_HZ is not set
+# CONFIG_HIGH_RES_TIMERS is not set
+# CONFIG_PREEMPT is not set
+CONFIG_HZ=100
+# CONFIG_AEABI is not set
+# CONFIG_ARCH_DISCONTIGMEM_ENABLE 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_SPARSEMEM_STATIC is not set
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_RESOURCES_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_LEDS=y
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_FPE_NWFPE is not set
+# CONFIG_FPE_FASTFPE is not set
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+# CONFIG_ARTHUR is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+
+#
+# Networking
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# 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=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+# CONFIG_IP_VS is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK is not set
+# CONFIG_NF_CONNTRACK_ENABLED is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_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
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+
+#
+# Wireless
+#
+# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_EXT is not set
+# CONFIG_MAC80211 is not set
+# CONFIG_IEEE80211 is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_REDBOOT_PARTS is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLKDEVS=y
+CONFIG_MTD_BLOCK=y
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=y
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=y
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=y
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x8000000
+CONFIG_MTD_PHYSMAP_LEN=0x0
+CONFIG_MTD_PHYSMAP_BANKWIDTH=2
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=y
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS 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_ONENAND is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_IDE=y
+CONFIG_IDE_MAX_HWIFS=4
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+# CONFIG_IDEDISK_MULTI_MODE is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+CONFIG_IDE_TASK_IOCTL=y
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+# CONFIG_IDEPCI_PCIBUS_ORDER is not set
+CONFIG_BLK_DEV_IDEDMA_PCI=y
+# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+# CONFIG_IDEDMA_ONLYDISK is not set
+# CONFIG_BLK_DEV_AEC62XX is not set
+# CONFIG_BLK_DEV_ALI15X3 is not set
+# CONFIG_BLK_DEV_AMD74XX is not set
+# CONFIG_BLK_DEV_CMD64X is not set
+# CONFIG_BLK_DEV_TRIFLEX is not set
+# CONFIG_BLK_DEV_CY82C693 is not set
+# CONFIG_BLK_DEV_CS5520 is not set
+# CONFIG_BLK_DEV_CS5530 is not set
+# CONFIG_BLK_DEV_HPT34X is not set
+# CONFIG_BLK_DEV_HPT366 is not set
+# CONFIG_BLK_DEV_JMICRON is not set
+# CONFIG_BLK_DEV_SC1200 is not set
+# CONFIG_BLK_DEV_PIIX is not set
+# CONFIG_BLK_DEV_IT8213 is not set
+# CONFIG_BLK_DEV_IT821X is not set
+# CONFIG_BLK_DEV_NS87415 is not set
+# CONFIG_BLK_DEV_PDC202XX_OLD is not set
+# CONFIG_BLK_DEV_PDC202XX_NEW is not set
+# CONFIG_BLK_DEV_SVWKS is not set
+# CONFIG_BLK_DEV_SIIMAGE is not set
+# CONFIG_BLK_DEV_SL82C105 is not set
+# CONFIG_BLK_DEV_SLC90E66 is not set
+# CONFIG_BLK_DEV_TRM290 is not set
+# CONFIG_BLK_DEV_VIA82CXXX is not set
+# CONFIG_BLK_DEV_TC86C001 is not set
+# CONFIG_IDE_ARM is not set
+CONFIG_BLK_DEV_DAVINCI=y
+CONFIG_BLK_DEV_IDEDMA=y
+# CONFIG_IDEDMA_IVB is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+# CONFIG_NETDEVICES_MULTIQUEUE is not set
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_PHYLIB is not set
+CONFIG_NET_ETHERNET=y
+# CONFIG_MII is not set
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+CONFIG_TI_DAVINCI_EMAC=y
+# CONFIG_DM9000 is not set
+CONFIG_NETDEV_1000=y
+CONFIG_NETDEV_10000=y
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# 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_MII is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=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_TSDEV is not set
+CONFIG_INPUT_EVDEV=m
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=y
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_GPIO 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=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=2
+CONFIG_SERIAL_8250_RUNTIME_UARTS=2
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+# CONFIG_WATCHDOG is not set
+CONFIG_HW_RANDOM=y
+# CONFIG_NVRAM is not set
+CONFIG_DAVINCI_RTC=y
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+# CONFIG_I2C_ALGOBIT is not set
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_STUB is not set
+# CONFIG_I2C_TINY_USB is not set
+CONFIG_I2C_DAVINCI=y
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_SENSORS_DS1337 is not set
+# CONFIG_SENSORS_DS1374 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_EEPROM is not set
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+CONFIG_SENSORS_TLV320AIC23=y
+CONFIG_SENSORS_TLV320AIC33=y
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+CONFIG_GPIOEXPANDER_DAVINCI=y
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# SPI support
+#
+# CONFIG_SPI is not set
+# CONFIG_SPI_MASTER is not set
+# CONFIG_W1 is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_ABITUGURU is not set
+# CONFIG_SENSORS_ABITUGURU3 is not set
+# CONFIG_SENSORS_AD7418 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_ASB100 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_FSCPOS is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 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_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_THMC50 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_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_EEPROM_93CX6 is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_SM501 is not set
+# CONFIG_NEW_LEDS is not set
+
+#
+# Multimedia devices
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_TVP5146 is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_TUNER_3036 is not set
+# CONFIG_TUNER_TEA5761 is not set
+CONFIG_V4L_USB_DRIVERS=y
+# CONFIG_VIDEO_PVRUSB2 is not set
+# CONFIG_VIDEO_EM28XX is not set
+# CONFIG_VIDEO_USBVISION is not set
+# CONFIG_USB_VICAM is not set
+# CONFIG_USB_IBMCAM is not set
+# CONFIG_USB_KONICAWC is not set
+# CONFIG_USB_QUICKCAM_MESSENGER is not set
+# CONFIG_USB_ET61X251 is not set
+# CONFIG_VIDEO_OVCAMCHIP is not set
+# CONFIG_USB_W9968CF is not set
+# CONFIG_USB_OV511 is not set
+# CONFIG_USB_SE401 is not set
+# CONFIG_USB_SN9C102 is not set
+# CONFIG_USB_STV680 is not set
+# CONFIG_USB_ZC0301 is not set
+# CONFIG_USB_PWC is not set
+# CONFIG_USB_ZR364XX is not set
+CONFIG_RADIO_ADAPTERS=y
+# CONFIG_RADIO_TEA5761 is not set
+# CONFIG_USB_DSBR is not set
+# CONFIG_DVB_CORE is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT 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_SYS_FOPS is not set
+CONFIG_FB_DEFERRED_IO=y
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+CONFIG_FB_DAVINCI=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+CONFIG_SOUND_DAVINCI=y
+CONFIG_SOUND_DAVINCI_AIC33=y
+
+#
+# DaVinci Audio Options
+#
+# CONFIG_MONOSTEREO_DIFFJACK is not set
+CONFIG_MONOSTEREO_SAMEJACK=y
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HID_DEBUG is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_USB_HIDINPUT_POWERBOOK is not set
+# CONFIG_HID_FF is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE 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 is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+CONFIG_USB_MUSB_HDRC=m
+CONFIG_USB_MUSB_SOC=y
+
+#
+# DaVinci 644x USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+CONFIG_USB_MUSB_PERIPHERAL=y
+# CONFIG_USB_MUSB_OTG is not set
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_USB_INVENTRA_FIFO=y
+CONFIG_USB_INVENTRA_HCD_LOGGING=0
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+
+#
+# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+#
+
+#
+# may also be needed; see USB_STORAGE Help for more information
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_DPCM is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+CONFIG_USB_MON=y
+
+#
+# USB port drivers
+#
+
+#
+# USB Serial Converter support
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_PHIDGET is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY 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
+
+#
+# USB DSL modem support
+#
+
+#
+# USB Gadget Support
+#
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG_FILES is not set
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_PXA2XX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_MMC=y
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD Card Drivers
+#
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_BOUNCE=y
+
+#
+# MMC/SD Host Controller Drivers
+#
+# CONFIG_MMC_DAVINCI is not set
+CONFIG_RTC_LIB=y
+# CONFIG_RTC_CLASS is not set
+
+#
+# DMA Engine support
+#
+# CONFIG_DMA_ENGINE is not set
+
+#
+# DMA Clients
+#
+
+#
+# DMA Devices
+#
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4DEV_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_SECURITY is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_ROMFS_FS is not set
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+CONFIG_DNOTIFY=y
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+# CONFIG_CONFIGFS_FS is not set
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_NFSD_TCP=y
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_SUNRPC_BIND34 is not set
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+
+#
+# Distributed Lock Manager
+#
+# CONFIG_DLM is not set
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_MUST_CHECK=y
+# CONFIG_MAGIC_SYSRQ 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 is not set
+CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_USER is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 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_PLIST=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
diff --git a/arch/arm/mach-davinci/Kconfig b/arch/arm/mach-davinci/Kconfig
index bac988e..0514c85 100644
--- a/arch/arm/mach-davinci/Kconfig
+++ b/arch/arm/mach-davinci/Kconfig
@@ -14,10 +14,36 @@
 	bool "TI DaVinci EVM"
 	default y
 	depends on ARCH_DAVINCI644x
+	select GPIOEXPANDER_DAVINCI
 	help
 	  Configure this option to specify the whether the board used
 	  for development is a DaVinci EVM
 
+config DAVINCI_I2C_EXPANDER
+	bool "TI DaVinci I2C Expander"
+	default y
+	depends on I2C && ARCH_DAVINCI644x
+	help
+	  Configure this option to specify whether the board used
+	  has I2C exapnder with ATA, USB, CF.
+
+config DAVINCI_MCBSP
+	bool
+        prompt "DaVinci McBSP Driver" if SOUND_DAVINCI=n
+	depends on ARCH_DAVINCI
+	default SOUND_DAVINCI
+	---help---
+	DaVinci McBSP driver.  Auto-enabled by DaVinci sound driver.
+
+comment "DaVinci Options"
+
+config DAVINCI_BLK_DEV_CF
+	bool "TI DaVinci CF Card Support"
+	default Y
+	depends on BLK_DEV_DAVINCI
+	help
+	  Configure this option to enable CF Card support.
+
 endmenu
 
 endif
diff --git a/arch/arm/mach-davinci/Makefile b/arch/arm/mach-davinci/Makefile
index 99ac2e5..666b323 100644
--- a/arch/arm/mach-davinci/Makefile
+++ b/arch/arm/mach-davinci/Makefile
@@ -5,7 +5,13 @@
 
 # Common objects
 obj-y 			:= time.o irq.o clock.o serial.o io.o id.o psc.o \
-			   gpio.o mux.o
+			   gpio.o mux.o dma.o devices.o
 
 # Board specific
-obj-$(CONFIG_MACH_DAVINCI_EVM)  += board-evm.o
+obj-$(CONFIG_MACH_DAVINCI_EVM)  	+= board-evm.o i2c-emac.o
+obj-$(CONFIG_DAVINCI_MCBSP)		+= mcbsp.o
+obj-$(CONFIG_DAVINCI_I2C_EXPANDER)	+= i2c-client.o
+
+ifeq ($(CONFIG_LEDS),y)
+obj-$(CONFIG_MACH_DAVINCI_EVM)	+= leds-evm.o
+endif
diff --git a/arch/arm/mach-davinci/board-evm.c b/arch/arm/mach-davinci/board-evm.c
index 9e4024c..8db3411 100644
--- a/arch/arm/mach-davinci/board-evm.c
+++ b/arch/arm/mach-davinci/board-evm.c
@@ -27,6 +27,7 @@
 #include <asm/mach/flash.h>
 
 #include <asm/arch/common.h>
+#include <asm/arch/psc.h>
 
 /* other misc. init functions */
 void __init davinci_psc_init(void);
@@ -92,8 +93,89 @@
 	.resource	= &davinci_evm_flash_resource,
 };
 
+#if defined(CONFIG_FB_DAVINCI) || defined(CONFIG_FB_DAVINCI_MODULE)
+
+static u64 davinci_fb_dma_mask = DMA_32BIT_MASK;
+
+static struct platform_device davinci_fb_device = {
+	.name		= "davincifb",
+	.id		= -1,
+	.dev = {
+		.dma_mask		= &davinci_fb_dma_mask,
+		.coherent_dma_mask      = DMA_32BIT_MASK,
+	},
+	.num_resources = 0,
+};
+#endif
+
+/*
+ * USB
+ */
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+
+#include <linux/usb/musb.h>
+
+static struct musb_hdrc_platform_data usb_data = {
+#if     defined(CONFIG_USB_MUSB_OTG)
+	/* OTG requires a Mini-AB connector */
+	.mode           = MUSB_OTG,
+#elif   defined(CONFIG_USB_MUSB_PERIPHERAL)
+	.mode           = MUSB_PERIPHERAL,
+#elif   defined(CONFIG_USB_MUSB_HOST)
+	.mode           = MUSB_HOST,
+#endif
+	/* irlml6401 switches 5V */
+	.power          = 250,          /* sustains 3.0+ Amps (!) */
+	.potpgt         = 4,            /* ~8 msec */
+
+	/* REVISIT multipoint is a _chip_ capability; not board specific */
+	.multipoint     = 1,
+};
+
+static struct resource usb_resources [] = {
+	{
+		/* physical address */
+		.start          = DAVINCI_USB_OTG_BASE,
+		.end            = DAVINCI_USB_OTG_BASE + 0x5ff,
+		.flags          = IORESOURCE_MEM,
+	},
+	{
+		.start          = IRQ_USBINT,
+		.flags          = IORESOURCE_IRQ,
+	},
+};
+
+static u64 usb_dmamask = DMA_32BIT_MASK;
+
+static struct platform_device usb_dev = {
+	.name           = "musb_hdrc",
+	.id             = -1,
+	.dev = {
+		.platform_data		= &usb_data,
+		.dma_mask		= &usb_dmamask,
+		.coherent_dma_mask      = DMA_32BIT_MASK,
+        },
+	.resource       = usb_resources,
+	.num_resources  = ARRAY_SIZE(usb_resources),
+};
+
+#define setup_usb(void)	do {} while(0)
+#endif  /* CONFIG_USB_MUSB_HDRC */
+
+static struct platform_device rtc_dev = {
+	.name           = "rtc_davinci_evm",
+	.id             = -1,
+};
+
 static struct platform_device *davinci_evm_devices[] __initdata = {
 	&davinci_evm_flash_device,
+#if defined(CONFIG_FB_DAVINCI) || defined(CONFIG_FB_DAVINCI_MODULE)
+	&davinci_fb_device,
+#endif
+#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
+	&usb_dev,
+#endif
+	&rtc_dev,
 };
 
 static void __init
@@ -113,6 +195,8 @@
 
 	platform_add_devices(davinci_evm_devices,
 			     ARRAY_SIZE(davinci_evm_devices));
+
+	setup_usb();
 }
 
 static __init void davinci_evm_irq_init(void)
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index 139ceaa..275e5cf 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -59,7 +59,7 @@
 			goto found;
 		}
 	}
-
+	
 	list_for_each_entry(p, &clocks, node) {
 		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
 			clk = p;
@@ -102,7 +102,7 @@
 {
 	unsigned long flags;
 	int ret = 0;
-
+	
 	if (clk == NULL || IS_ERR(clk))
 		return -EINVAL;
 
@@ -291,10 +291,10 @@
 }
 
 static struct seq_operations davinci_ck_op = {
-	.start	= davinci_ck_start,
-	.next	= davinci_ck_next,
-	.stop	= davinci_ck_stop,
-	.show	= davinci_ck_show
+	.start =	davinci_ck_start,
+	.next =		davinci_ck_next,
+	.stop =		davinci_ck_stop,
+	.show =		davinci_ck_show
 };
 
 static int davinci_ck_open(struct inode *inode, struct file *file)
@@ -320,4 +320,4 @@
 
 }
 __initcall(davinci_ck_proc_init);
-#endif	/* CONFIG_DEBUG_PROC_FS */
+#endif /* CONFIG_DEBUG_PROC_FS */
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index ed47079..f0061f5 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -1,7 +1,7 @@
 /*
  * TI DaVinci clock definitions
  *
- * Copyright (C) 2006 Texas Instruments.
+ *  Copyright (C) 2006 Texas Instruments.
  *
  * 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
diff --git a/arch/arm/mach-davinci/devices.c b/arch/arm/mach-davinci/devices.c
new file mode 100644
index 0000000..ad26dcd
--- /dev/null
+++ b/arch/arm/mach-davinci/devices.c
@@ -0,0 +1,66 @@
+/*
+ * linux/arch/arm/mach-davinci/devices.c
+ *
+ * DaVinci platform device setup/initialization
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+#include <asm/mach/map.h>
+
+#if 	defined(CONFIG_I2C_DAVINCI) || defined(CONFIG_I2C_DAVINCI_MODULE)
+
+static struct resource i2c_resources[] = {
+	{
+		.start		= IO_ADDRESS(DAVINCI_I2C_BASE),
+		.end		= IO_ADDRESS(DAVINCI_I2C_BASE) + 0x40,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= IRQ_I2C,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device davinci_i2c_device = {
+	.name           = "i2c_davinci",
+	.id             = 1,
+	.num_resources	= ARRAY_SIZE(i2c_resources),
+	.resource	= i2c_resources,
+};
+
+static void davinci_init_i2c(void)
+{
+	(void) platform_device_register(&davinci_i2c_device);
+}
+
+#else
+
+static void davinci_init_i2c(void) {}
+
+#endif
+
+/*-------------------------------------------------------------------------*/
+
+static int __init davinci_init_devices(void)
+{
+	/* please keep these calls, and their implementations above,
+	 * in alphabetical order so they're easier to sort through.
+	 */
+	davinci_init_i2c();
+
+	return 0;
+}
+arch_initcall(davinci_init_devices);
+
diff --git a/arch/arm/mach-davinci/dma.c b/arch/arm/mach-davinci/dma.c
new file mode 100644
index 0000000..b6e2dfa
--- /dev/null
+++ b/arch/arm/mach-davinci/dma.c
@@ -0,0 +1,1731 @@
+/*
+ * linux/arch/arm/mach-davinci/dma.c
+ *
+ * TI DaVinci DMA file
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ *
+ */
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <asm/io.h>
+#include <asm/arch/memory.h>
+#include <linux/kernel.h>
+#include <asm/arch/hardware.h>
+#include <asm/arch/irqs.h>
+
+#include <asm/arch/edma.h>
+
+static spinlock_t dma_chan_lock;
+static struct device_driver edma_driver;
+static struct platform_device edma_dev;
+
+#define LOCK_INIT     spin_lock_init(&dma_chan_lock)
+#define LOCK          spin_lock(&dma_chan_lock)
+#define UNLOCK        spin_unlock(&dma_chan_lock)
+
+typedef void (*intr_callback) (void);
+static int register_dma_interrupts(intr_callback, intr_callback, intr_callback,
+				   intr_callback);
+
+#define DAVINCI_DMA_REGISTER_BASE DAVINCI_DMA_3PCC_BASE
+
+static edmacc_regs *get_edma_base(void)
+{
+	return ((edmacc_regs *) IO_ADDRESS(DAVINCI_DMA_REGISTER_BASE));
+}
+
+static intr_callback cb[4];
+
+/* Structure containing the dma channel parameters */
+static struct davinci_dma_lch {
+	int dev_id;
+	int in_use;		/* 1-used 0-unused */
+	int link_lch;
+	int dma_running;
+	int param_no;
+	int tcc;
+} dma_chan[DAVINCI_EDMA_NUM_PARAMENTRY];
+
+static struct dma_interrupt_data {
+	void (*callback) (int lch, unsigned short ch_status, void *data);
+	void *data;
+} intr_data[64];
+
+/*
+  Each bit field of the elements bellow indicate the corresponding EDMA channel
+  availability  on arm side events
+*/
+static unsigned long edma_channels_arm[] = {
+	0xffffffff,
+	0xffffffff
+};
+
+/*
+  Each bit field of the elements bellow indicate the corresponding QDMA channel
+  availability  on arm side events
+*/
+static unsigned char qdma_channels_arm[] = {
+	0x00
+};
+
+/*
+   Each bit field of the elements bellow indicate corresponding PARAM entry
+   availibility on arm side events
+*/
+static unsigned long param_entry_arm[] = {
+	0xffffffff, 0xffffffff, 0x0000ffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff
+};
+
+/*
+   Each bit field of the elements bellow indicate whether a PARAM entry
+   is free or in use
+   1 - free
+   0 - in use
+*/
+static unsigned long param_entry_use_status[] = {
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
+	0xffffffff
+};
+
+/*
+   Each bit field of the elements bellow indicate whether a intrerrupt
+   is free or in use
+   1 - free
+   0 - in use
+*/
+static unsigned long dma_intr_use_status[] = {
+	0xffffffff,
+	0xffffffff
+};
+
+/*
+    This lists the DMA channel numbers which does not have any events
+    associated with it
+*/
+static int dma_chan_no_event[] = {
+	0, 1, 12, 13, 14, 15, 25, 30, 31, 45, 46, 47, 55, 56, 57, 58, 59, 60,
+	61, 62, 63, -1
+};
+
+static int channel_queue_mapping[][2] = {
+/* {channel no, event queue no } */
+	{0, 0}, {1, 1}, {2, 0}, {3, 1}, {4, 0}, {5, 1}, {6, 0}, {7, 1},
+	{8, 0}, {9, 1}, {10, 0}, {11, 1}, {12, 0}, {13, 1}, {14, 0},
+	{15, 1}, {16, 0}, {17, 1}, {18, 0}, {19, 1}, {20, 0}, {21, 1},
+	{22, 0}, {23, 1}, {24, 0}, {25, 1}, {26, 0}, {27, 1}, {28, 0},
+	{29, 1}, {30, 0}, {31, 1}, {32, 0}, {33, 1}, {34, 0}, {35, 1},
+	{36, 0}, {37, 1}, {38, 0}, {39, 1}, {40, 0}, {41, 1}, {42, 0},
+	{43, 1}, {44, 0}, {45, 1}, {46, 0}, {47, 1}, {48, 0}, {49, 1},
+	{50, 0}, {51, 1}, {52, 0}, {53, 1}, {54, 0}, {55, 1}, {56, 0},
+	{57, 1}, {58, 0}, {59, 1}, {60, 0}, {61, 1}, {62, 0}, {63, 1},
+	{64, 0}, {65, 1}, {66, 0}, {67, 1}, {68, 0}, {69, 1}, {70, 0},
+	{71, 1}, {-1, -1}
+};
+
+static int queue_tc_mapping[DAVINCI_EDMA_NUM_EVQUE + 1][2] = {
+/* {event queue no, TC no} */
+	{0, 0},
+	{1, 1},
+	{-1, -1}
+};
+
+static int queue_priority_mapping[DAVINCI_EDMA_NUM_EVQUE + 1][2] = {
+	/* {event queue no, Priority} */
+	{0, 0},
+	{1, 1},
+	{-1, -1}
+};
+
+static int qdam_to_param_mapping[8] = { 0 };
+
+volatile edmacc_regs *ptr_edmacc_regs = NULL;
+
+/*****************************************************************************/
+
+static void map_dmach_queue(int ch_no, int queue_no)
+{
+	if (ch_no < DAVINCI_EDMA_NUM_DMACH) {
+		int bit_start = (ch_no % 8) * 4;
+		ptr_edmacc_regs->dmaqnum[ch_no >> 3] &= (~(0x7 << bit_start));
+		ptr_edmacc_regs->dmaqnum[ch_no >> 3] |=
+		    ((queue_no & 0x7) << bit_start);
+	} else if (ch_no >= DAVINCI_EDMA_NUM_DMACH
+		   &&
+		   ch_no < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		int bit_start = (ch_no - DAVINCI_EDMA_NUM_DMACH) * 4;
+		ptr_edmacc_regs->qdmaqnum &= (~(0x7 << bit_start));
+		ptr_edmacc_regs->qdmaqnum |= ((queue_no & 0x7) << bit_start);
+	}
+}
+
+/* For Davinci this Macro supports mapping only for QDMA channels and PaRam
+   entry */
+static void map_dmach_param(int ch_no, int param_no)
+{
+	if (ch_no >= DAVINCI_EDMA_NUM_DMACH
+	    && ch_no < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		ptr_edmacc_regs->qchmap[ch_no - DAVINCI_EDMA_NUM_DMACH] &=
+		    ~(PAENTRY | TRWORD);
+		ptr_edmacc_regs->qchmap[ch_no - DAVINCI_EDMA_NUM_DMACH] |=
+		    (((param_no & 0x1ff) << 5) | (QDMA_TRWORD << 2));
+	}
+}
+
+static void map_queue_tc(int queue_no, int tc_no)
+{
+	int bit_start = queue_no * 4;
+	ptr_edmacc_regs->quetcmap &= ~(0x7 << bit_start);
+	ptr_edmacc_regs->quetcmap |= ((tc_no & 0x7) << bit_start);
+}
+
+static void assign_priority_to_queue(int queue_no, int priority)
+{
+	int bit_start = queue_no * 4;
+	ptr_edmacc_regs->quepri &= ~(0x7 << bit_start);
+	ptr_edmacc_regs->quepri |= ((priority & 0x7) << bit_start);
+}
+
+/******************************************************************************
+ *
+ * DMA Param entry requests: Requests for the param structure entry for the dma
+ *                          channel passed
+ * Arguments:
+ *      lch  - logical channel for which param entry is being requested.
+ *
+ * Return: param number on success, or negative error number on failure
+ *
+ *****************************************************************************/
+static int request_param(int lch, int dev_id)
+{
+	int i = 0, j = 0, is_break = 0;
+	if (lch >= 0 && lch < DAVINCI_EDMA_NUM_DMACH) {
+		/*
+		   In davinci there is 1:1 mapping between edma channels
+		   and param sets
+		 */
+		LOCK;
+		/* It maintains param entry availability bitmap which
+		   could be updated by several thread  same channel
+		   and so requires protection
+		 */
+		param_entry_use_status[lch / 32] &= (~(1 << (lch % 32)));
+		UNLOCK;
+		return lch;
+	} else {
+		if (dev_id >= DAVINCI_DMA_QDMA0 &&
+		    dev_id <= DAVINCI_DMA_QDMA7) {
+			i = 0;
+		} else if (dev_id == DAVINCI_EDMA_PARAM_ANY) {
+			i = DAVINCI_EDMA_NUM_DMACH;
+		}
+
+		/* This allocation alogrithm requires complete lock because
+		   availabilty of param entry is checked from structure
+		   param_entry_use_status and same struct is updated back also
+		   once allocated
+		 */
+
+		LOCK;
+		while (i < DAVINCI_EDMA_NUM_PARAMENTRY) {
+			j = 0, is_break = 1;
+			if ((param_entry_arm[i / 32] & (1 << (i % 32))) &&
+			    (param_entry_use_status[i / 32] & (1 << (i % 32))))
+			{
+				if (dev_id != DAVINCI_EDMA_PARAM_ANY) {
+					while (dma_chan_no_event[j] != -1) {
+						if (dma_chan_no_event[j] == i) {
+							is_break = 0;
+						}
+						j++;
+					}
+					if (!is_break) {
+						break;
+					}
+				} else {
+					break;
+				}
+				i++;
+			} else {
+				i++;
+			}
+		}
+		if (i < DAVINCI_EDMA_NUM_PARAMENTRY) {
+			param_entry_use_status[i / 32] &= (~(1 << (i % 32)));
+			UNLOCK;
+			dev_dbg(&edma_dev.dev, "param no=%d\r\n", i);
+			return i;
+		} else {
+			UNLOCK;
+			return -1;	/* no free param */
+		}
+	}
+}
+
+/******************************************************************************
+ *
+ * Free dma param entry: Freethe param entry number passed
+ * Arguments:
+ *      param_no - Param entry to be released or freed out
+ *
+ * Return: N/A
+ *
+ *****************************************************************************/
+static void free_param(int param_no)
+{
+	if (param_no >= 0 && param_no < DAVINCI_EDMA_NUM_PARAMENTRY) {
+		LOCK;
+		/* This is global data structure and could be accessed
+		   by several thread
+		 */
+		param_entry_use_status[param_no / 32] |= (1 << (param_no % 32));
+		UNLOCK;
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA interrupt requests: Requests for the interrupt on the free channel
+ *
+ * Arguments:
+ *      lch - logical channel number for which the interrupt is to be requested
+ *            for the free channel.
+ *      callback - callback function registered for the requested interrupt
+ *                 channel
+ *      data - channel private data.
+ *
+ * Return: free interrupt channel number on success, or negative error number
+ *              on failure
+ *
+ *****************************************************************************/
+static int request_dma_interrupt(int lch,
+				 void (*callback) (int lch,
+						   unsigned short ch_status,
+						   void *data),
+				 void *data, int param_no, int requested_tcc)
+{
+	signed int free_intr_no = -1;
+	int i = 0, j = 0, is_break = 0;
+	/* edma channels */
+	if (lch >= 0 && lch < DAVINCI_EDMA_NUM_DMACH) {
+		/* Bitmap dma_intr_use_status is used to identify availabe tcc
+		   for interrupt purpose. This could be modified by several
+		   thread and same structure is checked availabilty as well as
+		   updated once it's found that resource is avialable */
+		LOCK;
+		if (dma_intr_use_status[lch / 32] & (1 << (lch % 32))) {
+			/* in use */
+			dma_intr_use_status[lch / 32] &= (~(1 << (lch % 32)));
+			UNLOCK;
+			free_intr_no = lch;
+			dev_dbg(&edma_dev.dev, "interrupt no=%d\r\n", free_intr_no);
+		} else {
+			UNLOCK;
+			dev_dbg(&edma_dev.dev, "EDMA:Error\r\n");
+			return -1;
+		}
+	}
+
+	/* qdma channels */
+	else if (lch >= DAVINCI_EDMA_NUM_DMACH
+		 && lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		if (requested_tcc != TCC_ANY) {
+			/* Complete allocation algo requires lock and as it's
+			   shared resources could be invoked by several thread.
+			   Structure dma_intr_use_status is used to check
+			   whether resource is availabe or not and latter marked
+			   as not available in the same structure */
+			LOCK;
+			if (dma_intr_use_status[requested_tcc / 32] &
+			    (1 << (requested_tcc % 32))) {
+				j = 0;
+				is_break = 1;
+				while (dma_chan_no_event[j] != -1) {
+					if (dma_chan_no_event[j] ==
+					    requested_tcc) {
+						is_break = 0;
+						break;
+					}
+					j++;
+				}
+				if (!is_break) {
+					dma_intr_use_status[requested_tcc / 32]
+					    &= (~(1 << (requested_tcc % 32)));
+					free_intr_no = requested_tcc;
+					dev_dbg(&edma_dev.dev,
+						"interrupt no=%d\r\n",
+						free_intr_no);
+				} else {
+					UNLOCK;
+					dev_dbg(&edma_dev.dev,
+						"Error - wrong tcc passed\r\n");
+					return -1;
+				}
+				UNLOCK;
+			} else {
+				UNLOCK;
+				dev_dbg(&edma_dev.dev,
+					"Error - wrong tcc passed\r\n");
+				return -1;
+			}
+		} else {
+			i = 0;
+			LOCK;
+			while (i < DAVINCI_EDMA_NUM_DMACH) {
+				j = 0;
+				is_break = 1;
+				if (dma_intr_use_status[i / 32] &
+				    (1 << (i % 32))) {
+					while (dma_chan_no_event[j] != -1) {
+						if (dma_chan_no_event[j] == i) {
+							is_break = 0;
+							break;
+						}
+						j++;
+					}
+					if (!is_break) {
+						dma_intr_use_status[i / 32] &=
+						    (~(1 << (i % 32)));
+						free_intr_no = i;
+
+						dev_dbg(&edma_dev.dev,
+							"interrupt no=%d\r\n",
+							free_intr_no);
+						break;
+					}
+					i++;
+				} else {
+					i++;
+				}
+			}
+			UNLOCK;
+		}
+	} else {
+		dev_dbg(&edma_dev.dev, "ERROR lch = %d\r\n", lch);
+	}
+	if (is_break) {
+		dev_dbg(&edma_dev.dev, "While allocating EDMA channel for QDMA");
+	}
+	if (lch >= DAVINCI_EDMA_NUM_DMACH && lch <
+	    (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		if (free_intr_no < 32) {
+			ptr_edmacc_regs->dra[0].drae =
+			    ptr_edmacc_regs->dra[0].drae | (1 << free_intr_no);
+		} else {
+			ptr_edmacc_regs->dra[0].draeh =
+			    ptr_edmacc_regs->dra[0].
+			    draeh | (1 << (free_intr_no - 32));
+		}
+	}
+	if (free_intr_no >= 0 && free_intr_no < 64) {
+		(free_intr_no < 32) ?
+		    (ptr_edmacc_regs->shadow[0].iesr |= (1UL << free_intr_no))
+		    : (ptr_edmacc_regs->shadow[0].iesrh |=
+		       (1UL << (free_intr_no - 32)));
+		intr_data[free_intr_no].callback = callback;
+		intr_data[free_intr_no].data = data;
+	}
+	return free_intr_no;
+}
+
+/******************************************************************************
+ *
+ * Free the dma interrupt: Releases the dma interrupt on the channel
+ *
+ * Arguments:
+ *      intr_no - interrupt number on the channel to be released or freed out
+ *
+ * Return: N/A
+ *
+ *****************************************************************************/
+static void free_dma_interrupt(int intr_no)
+{
+	if (intr_no >= 0 && intr_no < 64) {
+		(intr_no < 32) ? (ptr_edmacc_regs->shadow[0].icr |=
+				  (1UL << (intr_no))) : (ptr_edmacc_regs->
+							 shadow[0].icrh |=
+							 (1UL <<
+							  (intr_no - 32)));
+		LOCK;
+		/* Global structure and could be modified by several task */
+		dma_intr_use_status[intr_no / 32] |= (1 << (intr_no % 32));
+		UNLOCK;
+		intr_data[intr_no].callback = NULL;
+		intr_data[intr_no].data = NULL;
+
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA interrupt handler
+ *
+ *****************************************************************************/
+static void dma_irq_handler(void)
+{
+	int i;
+	unsigned int cnt;
+	cnt = 0;
+	if ((ptr_edmacc_regs->shadow[0].ipr == 0)
+	    && (ptr_edmacc_regs->shadow[0].iprh == 0))
+		return;
+	while (1) {
+		if (ptr_edmacc_regs->shadow[0].ipr) {
+			dev_dbg(&edma_dev.dev, "IPR =%d\r\n",
+				ptr_edmacc_regs->shadow[0].ipr);
+			for (i = 0; i < 32; i++) {
+				if (ptr_edmacc_regs->shadow[0].ipr & (1 << i)) {
+					/* Clear the corresponding IPR bits */
+					ptr_edmacc_regs->shadow[0].icr |=
+					    (1 << i);
+					if (intr_data[i].callback) {
+						intr_data[i].callback(i,
+								      DMA_COMPLETE,
+								      intr_data
+								      [i].data);
+
+					}
+				}
+			}
+		} else if (ptr_edmacc_regs->shadow[0].iprh) {
+			dev_dbg(&edma_dev.dev, "IPRH =%d\r\n",
+				ptr_edmacc_regs->shadow[0].iprh);
+			for (i = 0; i < 32; i++) {
+				if (ptr_edmacc_regs->shadow[0].iprh & (1 << i)) {
+					/* Clear the corresponding IPR bits */
+					ptr_edmacc_regs->shadow[0].icrh |=
+					    (1 << i);
+					if (intr_data[32 + i].callback) {
+						intr_data[32 + i].callback(32 +
+									   i,
+									   DMA_COMPLETE,
+									   intr_data
+									   [32 +
+									    i].
+									   data);
+					}
+				}
+			}
+		}
+		if ((ptr_edmacc_regs->shadow[0].ipr == 0)
+		    && (ptr_edmacc_regs->shadow[0].iprh == 0)) {
+			break;
+		}
+		cnt++;
+		if (cnt > 10) {
+			break;
+		}
+	}
+	ptr_edmacc_regs->shadow[0].ieval = 0x1;
+}
+
+/******************************************************************************
+ *
+ * DMA error interrupt handler
+ *
+ *****************************************************************************/
+static void dma_ccerr_handler(void)
+{
+	int i;
+	unsigned int cnt;
+	cnt = 0;
+	if ((ptr_edmacc_regs->emr == 0) && (ptr_edmacc_regs->emr == 0) &&
+	    (ptr_edmacc_regs->qemr == 0) && (ptr_edmacc_regs->ccerr == 0))
+		return;
+	while (1) {
+		if (ptr_edmacc_regs->emr) {
+			dev_dbg(&edma_dev.dev, "EMR =%d\r\n", ptr_edmacc_regs->emr);
+			for (i = 0; i < 32; i++) {
+				if (ptr_edmacc_regs->emr & (1 << i)) {
+					/* Clear the corresponding EMR bits */
+					ptr_edmacc_regs->emcr |= (1 << i);
+					/* Clear any SER */
+					ptr_edmacc_regs->shadow[0].secr |=
+					    (1 << i);
+					if (intr_data[i].callback) {
+						intr_data[i].callback(i,
+								      DMA_CC_ERROR,
+								      intr_data
+								      [i].data);
+					}
+				}
+			}
+		} else if (ptr_edmacc_regs->emrh) {
+			dev_dbg(&edma_dev.dev, "EMRH =%d\r\n",
+				ptr_edmacc_regs->emrh);
+			for (i = 0; i < 32; i++) {
+				if (ptr_edmacc_regs->emrh & (1 << i)) {
+					/* Clear the corresponding IPR bits */
+					ptr_edmacc_regs->emcrh |= (1 << i);
+					/* Clear any SER */
+					ptr_edmacc_regs->shadow[0].secrh |=
+					    (1 << i);
+					if (intr_data[i].callback) {
+						intr_data[i].callback(i,
+								      DMA_CC_ERROR,
+								      intr_data
+								      [i].data);
+					}
+				}
+			}
+		} else if (ptr_edmacc_regs->qemr) {
+			dev_dbg(&edma_dev.dev, "QEMR =%d\r\n",
+				ptr_edmacc_regs->qemr);
+			for (i = 0; i < 8; i++) {
+				if (ptr_edmacc_regs->qemr & (1 << i)) {
+					/* Clear the corresponding IPR bits */
+					ptr_edmacc_regs->qemcr |= (1 << i);
+					ptr_edmacc_regs->shadow[0].qsecr |=
+					    (1 << i);
+				}
+			}
+		} else if (ptr_edmacc_regs->ccerr) {
+			dev_dbg(&edma_dev.dev, "CCERR =%d\r\n",
+				ptr_edmacc_regs->ccerr);
+			for (i = 0; i < 8; i++) {
+				if (ptr_edmacc_regs->ccerr & (1 << i)) {
+					/* Clear the corresponding IPR bits */
+					ptr_edmacc_regs->ccerrclr |= (1 << i);
+				}
+			}
+		}
+		if ((ptr_edmacc_regs->emr == 0)
+		    && (ptr_edmacc_regs->emrh == 0)
+		    && (ptr_edmacc_regs->qemr == 0)
+		    && (ptr_edmacc_regs->ccerr == 0)) {
+			break;
+		}
+		cnt++;
+		if (cnt > 10) {
+			break;
+		}
+	}
+	ptr_edmacc_regs->eeval = 0x1;
+}
+
+/******************************************************************************
+ *
+ * DMA error interrupt handler
+ *
+ *****************************************************************************/
+static void dma_tc1err_handler(void)
+{
+
+}
+
+/******************************************************************************
+ *
+ * DMA error interrupt handler
+ *
+ *****************************************************************************/
+static void dma_tc2err_handler(void)
+{
+
+}
+
+/******************************************************************************
+ *
+ * DMA initialisation on davinci
+ *
+ *****************************************************************************/
+int __init arch_dma_init(void)
+{
+	int i;
+	edma_driver.name = "edma";
+	edma_dev.name = "dma";
+	edma_dev.id = -1;
+	edma_dev.dev.driver = &edma_driver;
+
+	ptr_edmacc_regs = get_edma_base();
+	dev_dbg(&edma_dev.dev, "DMA REG BASE ADDR=%x\n", 
+	       (unsigned int)ptr_edmacc_regs);
+	memset(dma_chan, 0x00, sizeof(dma_chan));
+	memset((void *)&(ptr_edmacc_regs->paramentry[0]), 0x00,
+	       sizeof(ptr_edmacc_regs->paramentry));
+	i = 0;
+	/* Channel to queue mapping */
+	while (channel_queue_mapping[i][0] != -1) {
+		map_dmach_queue(channel_queue_mapping[i][0],
+				channel_queue_mapping[i][1]);
+		i++;
+	}
+	i = 0;
+	/* Event queue to TC mapping */
+	while (queue_tc_mapping[i][0] != -1) {
+		map_queue_tc(queue_tc_mapping[i][0], queue_tc_mapping[i][1]);
+		i++;
+	}
+	i = 0;
+	/* Event queue priority mapping */
+	while (queue_priority_mapping[i][0] != -1) {
+		assign_priority_to_queue(queue_priority_mapping[i][0],
+					 queue_priority_mapping[i][1]);
+		i++;
+	}
+	for (i = 0; i < DAVINCI_EDMA_NUM_REGIONS; i++) {
+		ptr_edmacc_regs->dra[i].drae = 0x0;
+		ptr_edmacc_regs->dra[i].draeh = 0x0;
+		ptr_edmacc_regs->qrae[i] = 0x0;
+	}
+	LOCK_INIT;
+	return 0;
+}
+
+/******************************************************************************
+ *
+ * DMA channel requests: Requests for the dma device passed if it is free
+ *
+ * Arguments:
+ *      dev_id     - request for the param entry device id
+ *      dev_name   - device name
+ *      callback   - pointer to the channel callback.
+ *      Arguments:
+ *          lch  - channel no, which is the IPR bit position,
+ *		   indicating from which channel the interrupt arised.
+ *          data - channel private data, which is received as one of the
+ *		   arguments in davinci_request_dma.
+ *      data - private data for the channel to be requested, which is used to
+ *                   pass as a parameter in the callback function
+ *		     in irq handler.
+ *      lch - contains the device id allocated
+ *  tcc        - Transfer Completion Code, used to set the IPR register bit
+ *                   after transfer completion on that channel.
+ *  eventq_no  - Event Queue no to which the channel will be associated with
+ *               (valied only if you are requesting for a DMA MasterChannel)
+ *               Values : 0 to 7
+ *                       -1 for Default queue
+ * INPUT:   dev_id
+ * OUTPUT:  *dma_ch_out
+ *
+ * Return: zero on success, or corresponding error no on failure
+ *
+ *****************************************************************************/
+int davinci_request_dma(int dev_id, const char *dev_name,
+			void (*callback) (int lch, unsigned short ch_status,
+					  void *data),
+			void *data, int *lch,
+			int *tcc, enum dma_event_q eventq_no)
+{
+
+	int ret_val = 0, i = 0;
+	static int req_flag = 0;
+	int temp_ch = 0;
+	/* checking the ARM side events */
+	if (dev_id >= 0 && (dev_id < DAVINCI_EDMA_NUM_DMACH)) {
+		if (!(edma_channels_arm[dev_id / 32] & (0x1 << (dev_id % 32)))) {
+			dev_dbg(&edma_dev.dev,
+				"dev_id = %d not supported on ARM side\r\n",
+				dev_id);
+			return -EINVAL;
+		}
+	} else if (dev_id >= DAVINCI_EDMA_NUM_DMACH
+		   && dev_id <=
+		   (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		if (!(qdma_channels_arm[0] &
+		      (0x1 << (dev_id - DAVINCI_EDMA_NUM_DMACH)))) {
+
+			dev_dbg(&edma_dev.dev,
+				"dev_id = %d not supported on ARM side\r\n",
+				dev_id);
+			return -EINVAL;
+		}
+	}
+
+	if ((dev_id != DAVINCI_DMA_CHANNEL_ANY)
+	    && (dev_id != DAVINCI_EDMA_PARAM_ANY)) {
+		if (dev_id >= DAVINCI_EDMA_NUM_DMACH
+		    &&
+		    dev_id < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)
+		    ) {
+			ptr_edmacc_regs->qrae[0] =
+			    ptr_edmacc_regs->qrae[0] |
+			    (1 << (dev_id - DAVINCI_EDMA_NUM_DMACH));
+		} else {
+			if (dev_id < 32) {
+				ptr_edmacc_regs->dra[0].drae =
+				    ptr_edmacc_regs->dra[0].drae |
+				    (1 << dev_id);
+			} else {
+				ptr_edmacc_regs->dra[0].draeh =
+				    ptr_edmacc_regs->dra[0].draeh |
+				    (1 << (dev_id - 32));
+			}
+		}
+	}
+
+	if (!req_flag) {
+		if (register_dma_interrupts
+		    (dma_irq_handler, dma_ccerr_handler,
+		     dma_tc1err_handler, dma_tc2err_handler)) {
+			dev_dbg(&edma_dev.dev,
+				"register_dma_interrupts failed\r\n");
+			return -EINVAL;
+		} else
+			req_flag = 1;
+	}
+
+	if (dev_id >= 0 && dev_id < (DAVINCI_EDMA_NUM_DMACH)) {
+		/* The 64 Channels are mapped to the first 64 PARAM entries */
+		if (!dma_chan[dev_id].in_use) {
+			*lch = dev_id;
+			dma_chan[*lch].param_no = request_param(*lch, dev_id);
+			if (dma_chan[*lch].param_no == -1) {
+				return -EINVAL;
+			} else
+				dev_dbg(&edma_dev.dev, "param_no=%d\r\n",
+					dma_chan[*lch].param_no);
+			if (callback) {
+				dma_chan[*lch].tcc =
+				    request_dma_interrupt(*lch, callback, data,
+							  dma_chan[*lch].
+							  param_no, *tcc);
+				if (dma_chan[*lch].tcc == -1) {
+					return -EINVAL;
+				} else {
+					*tcc = dma_chan[*lch].tcc;
+					dev_dbg(&edma_dev.dev, "tcc_no=%d\r\n",
+						dma_chan[*lch].tcc);
+				}
+			} else
+				dma_chan[*lch].tcc = -1;
+
+			map_dmach_queue(dev_id, eventq_no);
+			ret_val = 0;
+		} else
+			ret_val = -EINVAL;
+	}
+
+	else if (dev_id >= DAVINCI_EDMA_NUM_DMACH && dev_id <
+		 (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		if ((qdam_to_param_mapping[dev_id - DAVINCI_EDMA_NUM_DMACH] !=
+		     -1)
+		    &&
+		    (dma_chan
+		     [qdam_to_param_mapping[dev_id - DAVINCI_EDMA_NUM_DMACH]].
+		     in_use)
+		    ) {
+			ret_val = -EINVAL;
+		} else {
+			*lch = dev_id;
+			dma_chan[*lch].param_no = request_param(*lch, dev_id);
+			if (dma_chan[*lch].param_no == -1) {
+				dev_dbg(&edma_dev.dev, "request_param failed\r\n");
+				return -EINVAL;
+			} else {
+				dev_dbg(&edma_dev.dev, "param_no=%d\r\n",
+					dma_chan[*lch].param_no);
+				map_dmach_param(*lch, dma_chan[*lch].param_no);
+			}
+			if (callback) {
+				dma_chan[*lch].tcc =
+				    request_dma_interrupt(*lch, callback, data,
+							  dma_chan[*lch].
+							  param_no, *tcc);
+				if (dma_chan[*lch].tcc == -1) {
+					return -EINVAL;
+				} else {
+					*tcc = dma_chan[*lch].tcc;
+					dev_dbg(&edma_dev.dev, "tcc_no=%d\r\n",
+						dma_chan[*lch].tcc);
+				}
+			} else
+				dma_chan[*lch].tcc = -1;
+			map_dmach_queue(dev_id, eventq_no);
+			ret_val = 0;
+		}
+	} else if (dev_id == DAVINCI_DMA_CHANNEL_ANY) {
+		i = 0;
+		ret_val = 0;
+		while (dma_chan_no_event[i] != -1) {
+			if (!dma_chan[dma_chan_no_event[i]].in_use) {
+				*lch = dma_chan_no_event[i];
+				dma_chan[*lch].param_no =
+				    request_param(*lch, dev_id);
+				if (dma_chan[*lch].param_no == -1) {
+					return -EINVAL;
+				}
+				dev_dbg(&edma_dev.dev, "param_no=%d\r\n",
+					dma_chan[*lch].param_no);
+				if (dma_chan[*lch].param_no >=
+				    DAVINCI_EDMA_NUM_DMACH
+				    &&
+				    dma_chan[*lch].param_no <
+				    (DAVINCI_EDMA_NUM_DMACH +
+				     DAVINCI_EDMA_NUM_QDMACH)
+				    ) {
+
+					ptr_edmacc_regs->qrae[0] =
+					    ptr_edmacc_regs->qrae[0] |
+					    (1 << (dma_chan[*lch].param_no -
+						   DAVINCI_EDMA_NUM_DMACH));
+
+				} else {
+					if (dma_chan[*lch].param_no < 32) {
+						ptr_edmacc_regs->dra[0].drae =
+						    ptr_edmacc_regs->dra[0].drae
+						    |
+						    (1 << dma_chan[*lch].
+						     param_no);
+					} else {
+						ptr_edmacc_regs->dra[0].draeh =
+						    ptr_edmacc_regs->dra[0].
+						    draeh | (1 <<
+							     (dma_chan[*lch].
+							      param_no - 32));
+					}
+				}
+				if (callback) {
+					dma_chan[*lch].tcc =
+					    request_dma_interrupt(*lch,
+								  callback,
+								  data,
+								  dma_chan
+								  [*lch].
+								  param_no,
+								  *tcc);
+					if (dma_chan[*lch].tcc == -1) {
+						return -EINVAL;
+					} else {
+						*tcc = dma_chan[*lch].tcc;
+					}
+				} else {
+					dma_chan[*lch].tcc = -1;
+				}
+				map_dmach_queue(dev_id, eventq_no);
+				ret_val = 0;
+				break;
+			}
+			i++;
+		}
+	}
+
+	else if (dev_id == DAVINCI_EDMA_PARAM_ANY) {
+		ret_val = 0;
+		for (i = (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH);
+		     i < DAVINCI_EDMA_NUM_PARAMENTRY; i++) {
+			if (!dma_chan[i].in_use) {
+				dev_dbg(&edma_dev.dev, "any link = %d\r\n", i);
+				*lch = i;
+				dma_chan[*lch].param_no =
+				    request_param(*lch, dev_id);
+				if (dma_chan[*lch].param_no == -1) {
+					dev_dbg(&edma_dev.dev,
+						"request_param failed\r\n");
+					return -EINVAL;
+				} else {
+					dev_dbg(&edma_dev.dev, "param_no=%d\r\n",
+						dma_chan[*lch].param_no);
+				}
+				if (*tcc != -1)
+					dma_chan[*lch].tcc = *tcc;
+				else
+					dma_chan[*lch].tcc = -1;
+				ret_val = 0;
+				break;
+			}
+		}
+	} else {
+		ret_val = -EINVAL;
+	}
+	if (!ret_val) {
+		if (dev_id >= DAVINCI_EDMA_NUM_DMACH && dev_id <
+		    (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+			/* Master Channel */
+			qdam_to_param_mapping[dev_id -
+					      DAVINCI_EDMA_NUM_DMACH] =
+			    dma_chan[*lch].param_no;
+			LOCK;
+			/* It's used global data structure and used to find out
+			   whether channel is available or not */
+			dma_chan[qdam_to_param_mapping
+				 [dev_id - DAVINCI_EDMA_NUM_DMACH]].in_use = 1;
+			UNLOCK;
+			dma_chan[qdam_to_param_mapping
+				 [dev_id - DAVINCI_EDMA_NUM_DMACH]].dev_id =
+			    *lch;
+			dma_chan[qdam_to_param_mapping
+				 [dev_id - DAVINCI_EDMA_NUM_DMACH]].tcc =
+			    dma_chan[*lch].tcc;
+			temp_ch =
+			    qdam_to_param_mapping[dev_id -
+						  DAVINCI_EDMA_NUM_DMACH];
+			dma_chan[temp_ch].param_no = dma_chan[*lch].param_no;
+			if (dma_chan[*lch].tcc != -1) {
+				ptr_edmacc_regs->paramentry[dma_chan[temp_ch].
+							    param_no].opt &=
+				    (~TCC);
+				ptr_edmacc_regs->paramentry[dma_chan[temp_ch].
+							    param_no].opt |=
+				    ((0x3f & dma_chan[*lch].tcc) << 12);
+				/* set TCINTEN bit in PARAM entry */
+				ptr_edmacc_regs->
+				    paramentry[dma_chan[temp_ch].param_no].
+				    opt |= TCINTEN;
+			} else {
+				ptr_edmacc_regs->paramentry[dma_chan[temp_ch].
+							    param_no].opt &=
+				    ~TCINTEN;
+			}
+			/* assign the link field to no link. i.e 0xffff */
+			ptr_edmacc_regs->paramentry[dma_chan[temp_ch].
+						    param_no].
+			    link_bcntrld |= 0xffff;
+		} else {
+			/* Slave Channel */
+			LOCK;
+			/* Global structure to identify whether resoures is
+			   available or not */
+			dma_chan[*lch].in_use = 1;
+			UNLOCK;
+			dma_chan[*lch].dev_id = *lch;
+			if (dma_chan[*lch].tcc != -1) {
+				ptr_edmacc_regs->paramentry[dma_chan[*lch].
+							    param_no].opt &=
+				    (~TCC);
+				ptr_edmacc_regs->paramentry[dma_chan[*lch].
+							    param_no].opt |=
+				    ((0x3f & dma_chan[*lch].tcc) << 12);
+				/* set TCINTEN bit in PARAM entry */
+				ptr_edmacc_regs->paramentry[dma_chan[*lch].
+							    param_no].opt |=
+				    TCINTEN;
+			} else {
+				ptr_edmacc_regs->paramentry[dma_chan[*lch].
+							    param_no].opt &=
+				    ~TCINTEN;
+			}
+			/* assign the link field to no link. i.e 0xffff */
+			ptr_edmacc_regs->paramentry[dma_chan[*lch].
+						    param_no].
+			    link_bcntrld |= 0xffff;
+		}
+	}
+	return ret_val;
+}
+
+/******************************************************************************
+ *
+ * DMA channel free: Free dma channle
+ * Arguments:
+ *      dev_id     - request for the param entry device id
+ *
+ * Return: zero on success, or corresponding error no on failure
+ *
+ *****************************************************************************/
+void davinci_free_dma(int lch)
+{
+	int temp_ch = 0;
+	if (lch >= DAVINCI_EDMA_NUM_DMACH && lch <
+	    (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH];
+		lch = temp_ch;
+	}
+	LOCK;
+	dma_chan[lch].in_use = 0;
+	UNLOCK;
+	free_param(dma_chan[lch].param_no);
+
+	if (lch >= 0
+	    && lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		free_dma_interrupt(dma_chan[lch].tcc);
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA source parameters setup
+ * ARGUMENTS:
+ *      lch         - channel for which the source parameters to be configured
+ *      src_port    - Source port address
+ *      addressMode - indicates wether addressing mode is fifo.
+ *
+ *****************************************************************************/
+void davinci_set_dma_src_params(int lch, unsigned long src_port,
+				enum address_mode mode, enum fifo_width width)
+{
+	int temp_ch = 0;
+	if (lch >= DAVINCI_EDMA_NUM_DMACH && lch <
+	    (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH];
+		lch = temp_ch;
+	}
+	if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) {
+		/* set the source port address
+		   in source register of param structure */
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src =
+		    src_port;
+		/* set the fifo addressing mode */
+		if (mode) {	/* reset SAM and FWID */
+			ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt
+			    &= (~(SAM | EDMA_FWID));
+			/* set SAM and program FWID */
+			ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt
+			    |= (mode | ((width & 0x7) << 8));
+		}
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA destination parameters setup
+ * ARGUMENTS:
+ *    lch - channel or param device for destination parameters to be configured
+ *    dest_port    - Destination port address
+ *    addressMode  - indicates wether addressing mode is fifo.
+ *
+ *****************************************************************************/
+void davinci_set_dma_dest_params(int lch, unsigned long dest_port,
+				 enum address_mode mode, enum fifo_width width)
+{
+	int temp_ch = 0;
+	if (lch >= DAVINCI_EDMA_NUM_DMACH && lch <
+	    (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH];
+		lch = temp_ch;
+	}
+	if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) {
+		/* set the destination port address
+		   in dest register of param structure */
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].dst =
+		    dest_port;
+		/* set the fifo addressing mode */
+		if (mode) {	/* reset DAM and FWID */
+
+			ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt
+			    &= (~(DAM | EDMA_FWID));
+			/* set DAM and program FWID */
+			ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt
+			    |= ((mode << 1) | ((width & 0x7) << 8));
+		}
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA source index setup
+ * ARGUMENTS:
+ *      lch     - channel or param device for configuration of source index
+ *      srcbidx - source B-register index
+ *      srccidx - source C-register index
+ *
+ *****************************************************************************/
+void davinci_set_dma_src_index(int lch, short src_bidx, short src_cidx)
+{
+	int temp_ch = 0;
+	if (lch >= DAVINCI_EDMA_NUM_DMACH && lch <
+	    (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH];
+		lch = temp_ch;
+	}
+
+	if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) {
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_bidx
+		    &= 0xffff0000;
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_bidx
+		    |= src_bidx;
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_cidx
+		    &= 0xffff0000;
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_cidx
+		    |= src_cidx;
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA destination index setup
+ * ARGUMENTS:
+ *      lch    - channel or param device for configuration of destination index
+ *      srcbidx - dest B-register index
+ *      srccidx - dest C-register index
+ *
+ *****************************************************************************/
+void davinci_set_dma_dest_index(int lch, short dest_bidx, short dest_cidx)
+{
+	int temp_ch = 0;
+	if (lch >= DAVINCI_EDMA_NUM_DMACH && lch <
+	    (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH];
+		lch = temp_ch;
+	}
+	if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) {
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_bidx
+		    &= 0x0000ffff;
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_bidx
+		    |= ((unsigned long)dest_bidx << 16);
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_cidx
+		    &= 0x0000ffff;
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].src_dst_cidx
+		    |= ((unsigned long)dest_cidx << 16);
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA transfer parameters setup
+ * ARGUMENTS:
+ *      lch  - channel or param device for configuration of aCount, bCount and
+ *         cCount regs.
+ *      acnt - acnt register value to be configured
+ *      bcnt - bcnt register value to be configured
+ *      ccnt - ccnt register value to be configured
+ *
+ *****************************************************************************/
+void davinci_set_dma_transfer_params(int lch, unsigned short acnt,
+				     unsigned short bcnt, unsigned short ccnt,
+				     unsigned short bcntrld,
+				     enum sync_dimension sync_mode)
+{
+	int temp_ch = 0;
+	if (lch >= DAVINCI_EDMA_NUM_DMACH && lch <
+	    (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH];
+		lch = temp_ch;
+	}
+	if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) {
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].link_bcntrld
+		    &= 0x0000ffff;
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].link_bcntrld
+		    |= (bcntrld << 16);
+		if (sync_mode == ASYNC)
+			ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt
+			    &= (~SYNCDIM);
+		else
+			ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].opt
+			    |= SYNCDIM;
+		/* Set the acount, bcount, ccount registers */
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].a_b_cnt =
+		    (bcnt << 16) | acnt;
+		ptr_edmacc_regs->paramentry[dma_chan[lch].param_no].ccnt = ccnt;
+	}
+}
+
+/******************************************************************************
+ *
+ * davinci_set_dma_params -
+ * ARGUMENTS:
+ *      lch - logical channel number
+ *
+ *****************************************************************************/
+void davinci_set_dma_params(int lch, edmacc_paramentry_regs * temp)
+{
+	int temp_ch = 0;
+	if (lch >= DAVINCI_EDMA_NUM_DMACH && lch <
+	    (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH];
+		lch = temp_ch;
+	}
+	if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) {
+		memcpy((void *)
+		       &(ptr_edmacc_regs->
+			 paramentry[dma_chan[lch].param_no].opt),
+		       (void *)temp, sizeof(edmacc_paramentry_regs));
+	}
+}
+
+/******************************************************************************
+ *
+ * davinci_get_dma_params -
+ * ARGUMENTS:
+ *      lch - logical channel number
+ *
+ *****************************************************************************/
+void davinci_get_dma_params(int lch, edmacc_paramentry_regs * temp)
+{
+	int temp_ch = 0;
+	if (lch >= DAVINCI_EDMA_NUM_DMACH && lch <
+	    (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch = qdam_to_param_mapping[lch - DAVINCI_EDMA_NUM_DMACH];
+		lch = temp_ch;
+	}
+	if (lch >= 0 && lch < DAVINCI_EDMA_NUM_PARAMENTRY) {
+		memcpy((void *)temp,
+		       (void *)&(ptr_edmacc_regs->
+				 paramentry[dma_chan[lch].param_no].opt),
+		       sizeof(edmacc_paramentry_regs));
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA Strat - Starts the dma on the channel passed
+ * ARGUMENTS:
+ *      lch - logical channel number
+ *
+ *****************************************************************************/
+int davinci_start_dma(int lch)
+{
+	int ret_val;
+	if (lch >= 0 && (lch < DAVINCI_EDMA_NUM_DMACH)) {
+		int i = 0;
+		int flag = 0;
+		/* If the dma start request is for the unused events */
+		while (dma_chan_no_event[i] != -1) {
+			if (dma_chan_no_event[i] == lch) {
+				/* EDMA channels without event association */
+				dev_dbg(&edma_dev.dev, "ESR=%x\r\n",
+					ptr_edmacc_regs->shadow[0].esr);
+
+				(lch < 32) ?
+				    (ptr_edmacc_regs->shadow[0].esr |=
+				     (1UL << lch)) : (ptr_edmacc_regs->
+						      shadow[0].esrh |=
+						      (1UL << (lch - 32)));
+				flag = 1;
+				ret_val = 0;
+				break;
+			}
+			i++;
+		}
+		if (!flag) {
+			/* EDMA channel with event association */
+			dev_dbg(&edma_dev.dev, "ER=%d\r\n",
+				ptr_edmacc_regs->shadow[0].er);
+			/* Clear any pedning error */
+			(lch < 32) ?
+			    (ptr_edmacc_regs->emcr |=
+			     (1UL << lch)) :
+			    (ptr_edmacc_regs->emcrh |= (1UL << (lch - 32)));
+			/* Clear any SER */
+			(lch < 32) ?
+			    (ptr_edmacc_regs->shadow[0].secr |=
+			     (1UL << lch)) :
+			    (ptr_edmacc_regs->shadow[0].secrh |=
+			     (1UL << (lch - 32)));
+
+			(lch < 32) ?
+			    (ptr_edmacc_regs->shadow[0].eesr |=
+			     (1UL << lch)) :
+			    (ptr_edmacc_regs->shadow[0].eesrh |=
+			     (1UL << (lch - 32)));
+
+			dev_dbg(&edma_dev.dev, "EER=%d\r\n",
+				ptr_edmacc_regs->shadow[0].eer);
+			ret_val = 0;
+		}
+	} else if ((lch >= DAVINCI_EDMA_NUM_DMACH)
+		   && (lch <
+		       (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))) {
+		ptr_edmacc_regs->shadow[0].qeesr |=
+		    (1 << (lch - DAVINCI_EDMA_NUM_DMACH));
+		ret_val = 0;
+	} else {		/* for slaveChannels */
+		ret_val = EINVAL;
+	}
+	return ret_val;
+}
+
+/******************************************************************************
+ *
+ * DMA Stop - Stops the dma on the channel passed
+ * ARGUMENTS:
+ *      lch - logical channel number
+ *
+ *****************************************************************************/
+void davinci_stop_dma(int lch)
+{
+	if (lch < DAVINCI_EDMA_NUM_DMACH) {
+		int flag = 0;
+		int i = 0;
+		/* If the dma stop request is for the unused events */
+		while (dma_chan_no_event[i] != -1) {
+			if (dma_chan_no_event[i] == lch) {
+				/* EDMA channels without event association */
+				/* if the requested channel is one of the
+				   unused channels then reset the coresponding
+				   bit of ESR-Event Set Register */
+				flag = 1;
+				break;
+			}
+			i++;
+		}
+		if (!flag) {
+			/* EDMA channel with event association */
+			(lch < 32) ? (ptr_edmacc_regs->shadow[0].eecr |=
+				      (1UL << lch)) :
+			    (ptr_edmacc_regs->shadow[0].eecrh |=
+			     (1UL << (lch - 32)));
+			if (lch < 32) {
+				if (ptr_edmacc_regs->shadow[0].er & (1 << lch)) {
+					dev_dbg(&edma_dev.dev, "ER=%x\n",
+						ptr_edmacc_regs->shadow[0].er);
+					ptr_edmacc_regs->shadow[0].ecr |=
+					    (1 << lch);
+				}
+			} else {
+				if (ptr_edmacc_regs->shadow[0].erh
+				    & (1 << (lch - 32))) {
+					dev_dbg(&edma_dev.dev, "ERH=%x\n",
+						ptr_edmacc_regs->shadow[0].erh);
+					ptr_edmacc_regs->shadow[0].ecrh |=
+					    (1 << (lch - 32));
+				}
+			}
+			if (lch < 32) {
+				if (ptr_edmacc_regs->shadow[0].ser & (1 << lch)) {
+					dev_dbg(&edma_dev.dev, "SER=%x\n",
+						ptr_edmacc_regs->shadow[0].ser);
+					ptr_edmacc_regs->shadow[0].secr |=
+					    (1 << lch);
+				} else {
+				}
+			} else {
+				if (ptr_edmacc_regs->
+				    shadow[0].serh & (1 << (lch - 32))) {
+					dev_dbg(&edma_dev.dev, "SERH=%x\n",
+						ptr_edmacc_regs->shadow[0].
+						serh);
+					ptr_edmacc_regs->shadow[0].secrh |=
+					    (1 << (lch - 32));
+				}
+			}
+			if (lch < 32) {
+				if (ptr_edmacc_regs->emr & (1 << lch)) {
+					dev_dbg(&edma_dev.dev, "EMR=%x\n",
+						ptr_edmacc_regs->emr);
+					ptr_edmacc_regs->emcr |= (1 << lch);
+				}
+			} else {
+				if (ptr_edmacc_regs->emrh & (1 << (lch - 32))) {
+					dev_dbg(&edma_dev.dev, "EMRH=%x\n",
+						ptr_edmacc_regs->emrh);
+					ptr_edmacc_regs->emcrh |=
+					    (1 << (lch - 32));
+				}
+			}
+			dev_dbg(&edma_dev.dev, "EER=%d\r\n",
+				ptr_edmacc_regs->shadow[0].eer);
+			/* if the requested channel is one of the event channels
+			   then just set the link field of the corresponding
+			   param entry to 0xffff */
+		}
+	} else if ((lch >= DAVINCI_EDMA_NUM_DMACH)
+		   &&
+		   (lch < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))) {
+		/* for QDMA channels */
+		ptr_edmacc_regs->qeecr |= (1 << (lch - DAVINCI_EDMA_NUM_DMACH));
+		dev_dbg(&edma_dev.dev, "QER=%d\r\n", ptr_edmacc_regs->qer);
+		dev_dbg(&edma_dev.dev, "QEER=%d\r\n", ptr_edmacc_regs->qeer);
+	} else if ((lch >= (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))
+		   && lch < DAVINCI_EDMA_NUM_PARAMENTRY) {
+		/* for slaveChannels */
+		ptr_edmacc_regs->paramentry[lch].link_bcntrld &= 0xffff0000;
+		ptr_edmacc_regs->paramentry[lch].link_bcntrld |= 0xffff;
+	} else {
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA channel link - link the two logical channels passed through by linking
+ *                    the link field of head to the param pointed by the lch_queue.
+ * ARGUMENTS:
+ *      lch_head  - logical channel number, in which the link field is linked
+ *                  to the param pointed to by lch_queue
+ * lch_queue - logical channel number or the param entry number, which is to be
+ *                  linked to the lch_head
+ *
+ *****************************************************************************/
+void davinci_dma_link_lch(int lch_head, int lch_queue)
+{
+	unsigned long link;
+	int temp_ch = 0;
+	if (lch_head >=
+	    DAVINCI_EDMA_NUM_DMACH
+	    && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch =
+		    qdam_to_param_mapping[lch_head - DAVINCI_EDMA_NUM_DMACH];
+		lch_head = temp_ch;
+	}
+	if (lch_queue >=
+	    DAVINCI_EDMA_NUM_DMACH
+	    && lch_queue < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch =
+		    qdam_to_param_mapping[lch_queue - DAVINCI_EDMA_NUM_DMACH];
+		lch_queue = temp_ch;
+	}
+	if ((lch_head >= 0 && lch_head < DAVINCI_EDMA_NUM_PARAMENTRY)
+	    && (lch_queue >= 0 && lch_queue < DAVINCI_EDMA_NUM_PARAMENTRY)) {
+		/* program LINK */
+		link =
+		    (unsigned
+		     long)(&
+			   (ptr_edmacc_regs->
+			    paramentry[dma_chan[lch_queue].param_no].opt));
+		ptr_edmacc_regs->
+		    paramentry[dma_chan
+			       [lch_head].param_no].link_bcntrld &= 0xffff0000;
+		ptr_edmacc_regs->
+		    paramentry[dma_chan
+			       [lch_head].
+			       param_no].link_bcntrld |= ((unsigned short)
+							  link);
+		dma_chan[lch_head].link_lch = lch_queue;
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA channel unlink - unlink the two logical channels passed through by
+ *                   setting the link field of head to 0xffff.
+ * ARGUMENTS:
+ * lch_head - logical channel number, from which the link field is to be removed
+ * lch_queue - logical channel number or the param entry number, which is to be
+ *             unlinked from lch_head
+ *
+ *****************************************************************************/
+void davinci_dma_unlink_lch(int lch_head, int lch_queue)
+{
+	int temp_ch = 0;
+	if (lch_head >=
+	    DAVINCI_EDMA_NUM_DMACH
+	    && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch =
+		    qdam_to_param_mapping[lch_head - DAVINCI_EDMA_NUM_DMACH];
+		lch_head = temp_ch;
+	}
+	if (lch_queue >=
+	    DAVINCI_EDMA_NUM_DMACH
+	    && lch_queue < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch =
+		    qdam_to_param_mapping[lch_queue - DAVINCI_EDMA_NUM_DMACH];
+		lch_queue = temp_ch;
+	}
+	if ((lch_head >= 0 && lch_head < DAVINCI_EDMA_NUM_PARAMENTRY)
+	    && (lch_queue >= 0 && lch_queue < DAVINCI_EDMA_NUM_PARAMENTRY)) {
+		ptr_edmacc_regs->
+		    paramentry[dma_chan
+			       [lch_head].param_no].link_bcntrld |= 0xffff;
+		dma_chan[lch_head].link_lch = -1;
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA channel chain - chains the two logical channels passed through by
+ * ARGUMENTS:
+ * lch_head - logical channel number, from which the link field is to be removed
+ * lch_queue - logical channel number or the param entry number, which is to be
+ *             unlinked from lch_head
+ *
+ *****************************************************************************/
+void davinci_dma_chain_lch(int lch_head, int lch_queue)
+{
+	int temp_ch = 0;
+	if (lch_head >=
+	    DAVINCI_EDMA_NUM_DMACH
+	    && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch =
+		    qdam_to_param_mapping[lch_head - DAVINCI_EDMA_NUM_DMACH];
+		lch_head = temp_ch;
+	}
+	if (lch_queue >=
+	    DAVINCI_EDMA_NUM_DMACH
+	    && lch_queue < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch =
+		    qdam_to_param_mapping[lch_queue - DAVINCI_EDMA_NUM_DMACH];
+		lch_queue = temp_ch;
+	}
+	if ((lch_head >= 0
+	     && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))
+	    &&
+	    (lch_queue >= 0
+	     && lch_queue < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))
+	    ) {			/* set TCCHEN */
+		/* set TCCHEN */
+		ptr_edmacc_regs->paramentry[lch_head].opt |= TCCHEN;
+		/* program tcc */
+		ptr_edmacc_regs->paramentry[lch_head].opt &= (~TCC);
+		ptr_edmacc_regs->
+		    paramentry[lch_head].opt |= (lch_queue & 0x3f) << 12;
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA channel unchain - unchain the two logical channels passed through by
+ * ARGUMENTS:
+ * lch_head - logical channel number, from which the link field is to be removed
+ * lch_queue - logical channel number or the param entry number, which is to be
+ *             unlinked from lch_head
+ *
+ *****************************************************************************/
+void davinci_dma_unchain_lch(int lch_head, int lch_queue)
+{
+	int temp_ch = 0;
+	if (lch_head >=
+	    DAVINCI_EDMA_NUM_DMACH
+	    && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch =
+		    qdam_to_param_mapping[lch_head - DAVINCI_EDMA_NUM_DMACH];
+		lch_head = temp_ch;
+	}
+	if (lch_queue >=
+	    DAVINCI_EDMA_NUM_DMACH
+	    && lch_queue < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH)) {
+		temp_ch =
+		    qdam_to_param_mapping[lch_queue - DAVINCI_EDMA_NUM_DMACH];
+		lch_queue = temp_ch;
+	}
+	if ((lch_head >= 0
+	     && lch_head < (DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))
+	    && (lch_queue >= 0
+		&& lch_queue <
+		(DAVINCI_EDMA_NUM_DMACH + DAVINCI_EDMA_NUM_QDMACH))) {
+		/* reset TCCHEN */
+		ptr_edmacc_regs->paramentry[lch_head].opt &= ~TCCHEN;
+	}
+}
+
+/******************************************************************************
+ *
+ * It cleans ParamEntry qand bring back EDMA to initial state if media has
+ * been removed before EDMA has finished.It is usedful for removable media.
+ * Arguments:
+ *      ch_no     - channel no
+ *
+ * Return: zero on success, or corresponding error no on failure
+ *
+ *****************************************************************************/
+
+void davinci_clean_channel(int ch_no)
+{
+	int i;
+	dev_dbg(&edma_dev.dev, "EMR =%d\r\n", ptr_edmacc_regs->emr);
+	if (ch_no < 32) {
+		for (i = 0; i < 32; i++) {
+			if (ch_no == i) {
+				ptr_edmacc_regs->shadow[0].ecr |= (1 << i);
+				/* Clear the corresponding EMR bits */
+				ptr_edmacc_regs->emcr |= (1 << i);
+				/* Clear any SER */
+				ptr_edmacc_regs->shadow[0].secr |= (1 << i);
+				ptr_edmacc_regs->ccerrclr |= ((1 << 16) | 0x3);
+			}
+		}
+	}
+
+	if (ch_no > 32) {
+		dev_dbg(&edma_dev.dev, "EMRH =%d\r\n", ptr_edmacc_regs->emrh);
+		for (i = 0; i < 32; i++) {
+			if (ch_no == (i + 32)) {
+				ptr_edmacc_regs->shadow[0].ecrh |= (1 << i);
+				/* Clear the corresponding IPR bits */
+				ptr_edmacc_regs->emcrh |= (1 << i);
+				/* Clear any SER */
+				ptr_edmacc_regs->shadow[0].secrh |= (1 << i);
+				ptr_edmacc_regs->ccerrclr |= ((1 << 16) | 0x3);
+			}
+		}
+	}
+}
+
+/******************************************************************************
+ *
+ * DMA interrupt handlers
+ *
+ *****************************************************************************/
+static int dma_irq_handler_l(int sound_curr_lch, void *ch_status)
+{
+	dev_dbg(&edma_dev.dev, "dma_irq_handler\n");
+	(*cb[0]) ();
+	return IRQ_HANDLED;
+}
+
+static int dma_ccerr_handler_l(int sound_curr_lch, void *ch_status)
+{
+	dev_dbg(&edma_dev.dev, "dma_ccerr_handler\n");
+	(*cb[1]) ();
+	return IRQ_HANDLED;
+}
+
+static int dma_tc1err_handler_l (int sound_curr_lch, void *ch_status)
+{
+	dev_dbg(&edma_dev.dev, "dma_tc1err_handler\n");
+	(*cb[2]) ();
+	return IRQ_HANDLED;
+}
+
+static int dma_tc2err_handler_l(int sound_curr_lch, void *ch_status)
+{
+	dev_dbg(&edma_dev.dev, "dma_tc2err_handler\n");
+	(*cb[3]) ();
+	return IRQ_HANDLED;
+}
+
+int register_dma_interrupts(intr_callback cb1, intr_callback cb2,
+			intr_callback cb3, intr_callback cb4)
+{
+	cb[0] = cb1;
+	cb[1] = cb2;
+	cb[2] = cb3;
+	cb[3] = cb4;
+	if (!cb1 || !cb2 || !cb3 || !cb4) {
+		dev_dbg(&edma_dev.dev, "NULL callback\n");
+		return -1;
+	}
+
+	if (request_irq(IRQ_CCINT0, dma_irq_handler_l, 0, "EDMA", NULL)) {
+		dev_dbg(&edma_dev.dev, "request_irq failed\n");
+		return -1;
+	}
+	if (request_irq
+	    (IRQ_CCERRINT, dma_ccerr_handler_l, 0, "EDMA CC Err", NULL)) {
+		dev_dbg(&edma_dev.dev, "request_irq failed\n");
+		return -1;
+	}
+	if (request_irq
+	    (IRQ_TCERRINT0, dma_tc1err_handler_l, 0, "EDMA TC1 Err", NULL)) {
+		dev_dbg(&edma_dev.dev, "request_irq failed\n");
+		return -1;
+	}
+	if (request_irq
+	    (IRQ_TCERRINT, dma_tc2err_handler_l, 0, "EDMA TC2 Err", NULL)) {
+		dev_dbg(&edma_dev.dev, "request_irq failed\n");
+		return -1;
+	}
+	return 0;
+}
+
+arch_initcall(arch_dma_init);
+EXPORT_SYMBOL(davinci_start_dma);
+EXPORT_SYMBOL(davinci_dma_link_lch);
+EXPORT_SYMBOL(davinci_set_dma_params);
+EXPORT_SYMBOL(davinci_get_dma_params);
+EXPORT_SYMBOL(davinci_set_dma_transfer_params);
+EXPORT_SYMBOL(davinci_set_dma_dest_index);
+EXPORT_SYMBOL(davinci_set_dma_src_index);
+EXPORT_SYMBOL(davinci_set_dma_dest_params);
+EXPORT_SYMBOL(davinci_set_dma_src_params);
+EXPORT_SYMBOL(davinci_request_dma);
+EXPORT_SYMBOL(davinci_stop_dma);
+EXPORT_SYMBOL(davinci_clean_channel);
+EXPORT_SYMBOL(davinci_free_dma);
+EXPORT_SYMBOL(davinci_dma_chain_lch);
+EXPORT_SYMBOL(davinci_dma_unchain_lch);
+EXPORT_SYMBOL(davinci_dma_unlink_lch);
diff --git a/arch/arm/mach-davinci/gpio.c b/arch/arm/mach-davinci/gpio.c
index 9c67886..cb7b607 100644
--- a/arch/arm/mach-davinci/gpio.c
+++ b/arch/arm/mach-davinci/gpio.c
@@ -77,7 +77,7 @@
  */
 int __gpio_get(unsigned gpio)
 {
-	struct gpio_controller *__iomem g = gpio2controller(gpio);
+	struct gpio_controller	*__iomem g = gpio2controller(gpio);
 
 	return !!(__gpio_mask(gpio) & __raw_readl(&g->in_data));
 }
@@ -93,9 +93,9 @@
 
 int gpio_direction_input(unsigned gpio)
 {
-	struct gpio_controller *__iomem g = gpio2controller(gpio);
-	u32 temp;
-	u32 mask;
+	struct gpio_controller	*__iomem g = gpio2controller(gpio);
+	u32			temp;
+	u32			mask;
 
 	if (!g)
 		return -EINVAL;
diff --git a/arch/arm/mach-davinci/i2c-client.c b/arch/arm/mach-davinci/i2c-client.c
new file mode 100644
index 0000000..c506ef6
--- /dev/null
+++ b/arch/arm/mach-davinci/i2c-client.c
@@ -0,0 +1,166 @@
+/*
+ *  linux/drivers/davinci/i2c-davinci-client.c
+ *
+ * Copyright (C) 2006 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+
+#include <asm/semaphore.h>
+#include <asm/arch/i2c-client.h>
+
+static DEFINE_MUTEX(expander_lock);
+static struct i2c_client *client_handle;
+
+/* This function is used for internal initialization */
+int davinci_i2c_read(u8 size, u8 * val, u16 client_addr)
+{
+	int err;
+	struct i2c_client *client = client_handle;
+
+	struct i2c_msg msg[1];
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	msg->addr = client_addr;
+	msg->flags = I2C_M_RD;
+	msg->len = size;
+	msg->buf = val;
+
+	err = i2c_transfer(client->adapter, msg, 1);
+
+	if (err >= 0) {
+		return 0;
+	}
+
+	return err;
+}
+
+EXPORT_SYMBOL(davinci_i2c_read);
+
+/* This function is used for internal initialization */
+int davinci_i2c_write(u8 size, u8 * val, u16 client_addr)
+{
+	int err;
+	struct i2c_client *client = client_handle;
+
+	struct i2c_msg msg[1];
+
+	if (!client->adapter)
+		return -ENODEV;
+
+	msg->addr = client_addr;
+	msg->flags = 0;
+	msg->len = size;
+	msg->buf = val;
+
+	err = i2c_transfer(client->adapter, msg, 1);
+	if (err >= 0)
+		return 0;
+
+	return err;
+}
+
+EXPORT_SYMBOL(davinci_i2c_write);
+
+static struct i2c_driver davinci_i2c_client_driver;
+
+static int davinci_i2c_attach_client(struct i2c_adapter *adap, int addr)
+{
+	struct i2c_client *client;
+	int err;
+	u8 data_to_u35 = 0xf6;
+
+	if (!(client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+	client_handle = client;
+
+	if (client->adapter)
+		return -EBUSY;	/* our client is already attached */
+
+	client->addr = addr;
+	client->flags = 0;
+	client->driver = &davinci_i2c_client_driver;
+	client->adapter = adap;
+	strlcpy(client->name, client->driver->driver.name, I2C_NAME_SIZE);
+
+	err = i2c_attach_client(client);
+	if (err) {
+		client->adapter = NULL;
+		goto exit_kfree;
+	}
+
+	err = davinci_i2c_write(1, &data_to_u35, 0x3A);
+
+	return 0;
+
+ exit_kfree:
+	kfree(client);
+ exit:
+	return err;
+}
+
+static int davinci_i2c_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if (!client->adapter)
+		return -ENODEV;	/* our client isn't attached */
+
+	err = i2c_detach_client(client);
+	client->adapter = NULL;
+	return err;
+}
+
+static int davinci_i2c_probe_adapter(struct i2c_adapter *adap)
+{
+	return davinci_i2c_attach_client(adap, 0x3A);
+}
+
+/* This is the driver that will be inserted */
+static struct i2c_driver davinci_i2c_client_driver = {
+	.driver = {
+		/* there are 3 expanders, one is leds-only ... */
+		.name	= "davinci_evm_expander1",
+	},
+	.attach_adapter	= davinci_i2c_probe_adapter,
+	.detach_client	= davinci_i2c_detach_client,
+};
+
+static int __init davinci_i2c_client_init(void)
+{
+	return i2c_add_driver(&davinci_i2c_client_driver);
+}
+
+static void __exit davinci_i2c_client_exit(void)
+{
+	i2c_del_driver(&davinci_i2c_client_driver);
+}
+
+module_init(davinci_i2c_client_init);
+module_exit(davinci_i2c_client_exit);
diff --git a/arch/arm/mach-davinci/i2c-emac.c b/arch/arm/mach-davinci/i2c-emac.c
new file mode 100644
index 0000000..5753e0f
--- /dev/null
+++ b/arch/arm/mach-davinci/i2c-emac.c
@@ -0,0 +1,104 @@
+/*
+ * <arch/arm/mach-davinci/i2c-emac.c
+ *
+ * Read MAC address from i2c-attached EEPROM
+ * FIXME: Move into network driver once stabilized
+ *
+ * Author: Texas Instruments
+ *
+ * 2006 (c) Texas Instruments, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+
+#include <asm/arch/i2c-client.h>
+
+/* Get Ethernet address from kernel boot params */
+static unsigned char cpmac_eth_string[20] = "deadbeaf";
+
+/* This function gets the Ethernet MAC address from EEPROM
+ * Input buffer to be of atlease 20 bytes in length
+ */
+int davinci_get_macaddr (char *ptr)
+{
+#ifndef CONFIG_I2C_DAVINCI
+	printk(KERN_INFO "DaVinci EMAC: Unable to read MAC from EEPROM, "
+	       "no i2c support in kernel.\n");
+#else
+	char data[2] = { 0x7f, 0 };
+        char temp[20];
+        int  i = 0;
+
+	if (ptr == NULL) {
+		return -EFAULT;
+	}
+
+	davinci_i2c_write (2, data, 0x50);
+	davinci_i2c_read (8, temp, 0x50);
+
+	/* check whether MAC address is available in ERPROM else try to
+	 * to get it from bootparams for now.  From Delta EVM MAC address
+	 * should be available from I2C EEPROM.
+	 */
+	if ((temp [0] != 0xFF) |
+	    (temp [1] != 0xFF) |
+	    (temp [2] != 0xFF) |
+	    (temp [3] != 0xFF) |
+	    (temp [4] != 0xFF) |
+	    (temp [5] != 0xFF) |
+	    (temp [6] != 0xFF) )
+	{
+		ptr[0] = (*(temp+0) & 0xF0) >> 4;
+		ptr[1] = (*(temp+0) & 0x0F);
+		ptr[2] = ':';
+		ptr[3] = (*(temp+1) & 0xF0) >> 4;
+		ptr[4] = (*(temp+1) & 0x0F);
+		ptr[5] = ':';
+		ptr[6] = (*(temp+2) & 0xF0) >> 4;
+		ptr[7] = (*(temp+2) & 0x0F);
+		ptr[8] = ':';
+		ptr[9] = (*(temp+3) & 0xF0) >> 4;
+		ptr[10]= (*(temp+3) & 0x0F);
+		ptr[11]= ':';
+		ptr[12]= (*(temp+4) & 0xF0) >> 4;
+		ptr[13]= (*(temp+4) & 0x0F);
+		ptr[14]= ':';
+		ptr[15]= (*(temp+5) & 0xF0) >> 4;
+		ptr[16]= (*(temp+5) & 0x0F);
+
+		for (i = 0; i < 17; i++)
+		{
+			if (ptr[i] == ':')
+				continue;
+			else if (ptr[i] <= 9)
+				ptr[i] = ptr[i] + 48;
+			else
+				ptr[i] = ptr[i] + 87;
+		}
+	} else
+#endif
+	{
+		strcpy (ptr, cpmac_eth_string);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(davinci_get_macaddr);
+
+static int davinci_cpmac_eth_setup(char *str)
+{
+	/* The first char passed from the bootloader is '=', so ignore it */
+        strcpy(&cpmac_eth_string[0], &str[1]);
+
+        printk("TI DaVinci EMAC: Kernel Boot params Eth address: %s\n",
+               cpmac_eth_string);
+
+        return (1);
+}
+__setup("eth", davinci_cpmac_eth_setup);
+
diff --git a/arch/arm/mach-davinci/irq.c b/arch/arm/mach-davinci/irq.c
index 1333d84..51371f1 100644
--- a/arch/arm/mach-davinci/irq.c
+++ b/arch/arm/mach-davinci/irq.c
@@ -218,9 +218,9 @@
 	for (i = 0; i < DAVINCI_N_AINTC_IRQ; i++) {
 		set_irq_chip(i, &davinci_irq_chip_0);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-		if (i != IRQ_TINT1_TINT34)
-			set_irq_handler(i, handle_edge_irq);
-		else
-			set_irq_handler(i, handle_level_irq);
+                if (i != IRQ_TINT1_TINT34)
+                        set_irq_handler(i, handle_edge_irq);
+                else
+                        set_irq_handler(i, handle_level_irq);
 	}
 }
diff --git a/arch/arm/mach-davinci/leds-evm.c b/arch/arm/mach-davinci/leds-evm.c
new file mode 100644
index 0000000..15245ec
--- /dev/null
+++ b/arch/arm/mach-davinci/leds-evm.c
@@ -0,0 +1,200 @@
+/*
+ * <arch/arm/mach-davinci/leds-evm.c>
+ *
+ * LED support for TI DaVinci EVM
+ *
+ * 2006 (c) Texas Instruments, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+
+#include <asm/mach-types.h>
+#include <asm/hardware.h>
+#include <asm/leds.h>
+#include <asm/system.h>
+
+
+/* eight leds on a pcf8574a I2C gpio expander; 0 == ON, 1 == OFF
+ *  - drivers can use leds_event(led_{green,amber,red,blue}_{on,off})
+ *  - userspace can do the same with /sys/devices/leds/leds0/event
+ */
+#define	LED_DS8			(1 << 0)
+#define	LED_DS7			(1 << 1)
+#define	LED_DS6			(1 << 2)
+#define	LED_DS5			(1 << 3)
+#define	LED_DS4			(1 << 4)
+#define	LED_DS3			(1 << 5)
+#define	LED_DS2			(1 << 6)
+#define	LED_DS1			(1 << 7)
+
+#define LED_STATE_ENABLED	(1 << 8)
+#define LED_STATE_CLAIMED	(1 << 9)
+
+static u16	hw_led_state;
+static u8	leds_change;
+
+
+/* these leds use I2C not GPIO, so we can't change values
+ * and remain "idle" ... so there's no "idle" LED.
+ */
+#define	TIMER_LED		LED_DS8
+
+#define	GREEN_LED		LED_DS1
+#define	AMBER_LED		LED_DS2
+#define	RED_LED			LED_DS3
+#define	BLUE_LED		LED_DS4
+
+#define	APP_LEDS	(GREEN_LED | AMBER_LED | RED_LED | BLUE_LED)
+
+static DEFINE_SPINLOCK(lock);
+
+
+#define	EVM_I2C_ADDR	0x38
+
+static void pcf_work(struct work_struct *unused)
+{
+	struct i2c_adapter	*adap;
+	int			err;
+	struct i2c_msg		msg;
+
+	adap = i2c_get_adapter(0);
+	if (!adap)
+		return;
+
+	for (;;) {
+		static u8	leds;
+
+		spin_lock_irq(&lock);
+		leds = (u8) hw_led_state;
+		err= leds_change;
+		leds_change = 0;
+		spin_unlock_irq(&lock);
+
+		if (!err)
+			break;
+
+		msg.addr = EVM_I2C_ADDR;
+		msg.flags = 0;
+		msg.len = 1;
+		msg.buf = &leds;
+		err = i2c_transfer(adap, &msg, 1);
+		if (err < 0)
+			pr_debug("LED: set to %02x, err %d\n", leds, err);
+	}
+
+}
+
+static DECLARE_WORK(work, pcf_work);
+
+static void evm_leds_event(led_event_t evt)
+{
+	unsigned long	flags;
+	u16		leds;
+
+	spin_lock_irqsave(&lock, flags);
+
+	if (!(hw_led_state & LED_STATE_ENABLED) && evt != led_start)
+		goto done;
+
+	leds = hw_led_state;
+	switch (evt) {
+	case led_start:
+		hw_led_state = LED_STATE_ENABLED | 0xff;
+		leds = 0;
+		break;
+
+	case led_halted:
+	case led_stop:
+		hw_led_state = 0xff;
+		// NOTE:  work may still be pending!!
+		break;
+
+	case led_claim:
+		hw_led_state |= LED_STATE_CLAIMED;
+		hw_led_state |= APP_LEDS;
+		break;
+
+	case led_release:
+		hw_led_state &= ~LED_STATE_CLAIMED;
+		hw_led_state |= APP_LEDS;
+		break;
+
+#ifdef	CONFIG_LEDS_TIMER
+	case led_timer:
+		hw_led_state ^= TIMER_LED;
+		break;
+#endif
+
+	/* actually all the LEDs are green */
+
+	case led_green_on:
+		if (leds & LED_STATE_CLAIMED)
+			hw_led_state &= ~GREEN_LED;
+		break;
+	case led_green_off:
+		if (leds & LED_STATE_CLAIMED)
+			hw_led_state |= GREEN_LED;
+		break;
+
+	case led_amber_on:
+		if (leds & LED_STATE_CLAIMED)
+			hw_led_state &= ~AMBER_LED;
+		break;
+	case led_amber_off:
+		if (leds & LED_STATE_CLAIMED)
+			hw_led_state |= AMBER_LED;
+		break;
+
+	case led_red_on:
+		if (leds & LED_STATE_CLAIMED)
+			hw_led_state &= ~RED_LED;
+		break;
+	case led_red_off:
+		if (leds & LED_STATE_CLAIMED)
+			hw_led_state |= RED_LED;
+		break;
+
+	case led_blue_on:
+		if (leds & LED_STATE_CLAIMED)
+			hw_led_state &= ~BLUE_LED;
+		break;
+	case led_blue_off:
+		if (leds & LED_STATE_CLAIMED)
+			hw_led_state |= BLUE_LED;
+		break;
+
+	default:
+		break;
+	}
+
+	leds ^= hw_led_state;
+	if (leds & 0xff) {
+		leds_change = (u8) leds;
+		schedule_work(&work);
+	}
+
+done:
+	spin_unlock_irqrestore(&lock, flags);
+}
+
+static int __init evm_leds_init(void)
+{
+	if (!machine_is_davinci_evm())
+		return 0;
+
+	leds_event = evm_leds_event;
+	leds_event(led_start);
+	return 0;
+}
+
+/* i2c is subsys_initcall, davinci i2c is device_initcall;
+ * this needs to follow both of them (sigh)
+ */
+late_initcall(evm_leds_init);
diff --git a/arch/arm/mach-davinci/mcbsp.c b/arch/arm/mach-davinci/mcbsp.c
new file mode 100644
index 0000000..95531e3
--- /dev/null
+++ b/arch/arm/mach-davinci/mcbsp.c
@@ -0,0 +1,519 @@
+/*
+ * arch/arm/mach-davinci/mcbsp.c
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
+ *
+ * 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.
+ *
+ * Multichannel mode not supported.
+ *
+ * 2005-10-01   Rishi Bhattacharya / Sharath Kumar - Modified to support TI
+ *		Davinci DM644x processor
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/wait.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/irq.h>
+
+#include <asm/arch/memory.h>
+#include <asm/arch/edma.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/mcbsp.h>
+
+struct clk *mbspclk = NULL;
+
+/* #define CONFIG_MCBSP_DEBUG */
+
+#ifdef CONFIG_MCBSP_DEBUG
+#define DBG(x...)       printk(KERN_INFO x)
+#else
+#define DBG(x...)       do { } while (0)
+#endif
+
+struct davinci_mcbsp {
+	u32 io_base;
+	u8 id;
+	u8 free;
+	davinci_mcbsp_word_length rx_word_length;
+	davinci_mcbsp_word_length tx_word_length;
+
+	/* IRQ based TX/RX */
+	int rx_irq;
+	int tx_irq;
+
+	/* DMA stuff */
+	u8 dma_rx_sync;
+	short dma_rx_lch;
+	u8 dma_tx_sync;
+	short dma_tx_lch;
+
+	/* Completion queues */
+	struct completion tx_irq_completion;
+	struct completion rx_irq_completion;
+	struct completion tx_dma_completion;
+	struct completion rx_dma_completion;
+
+	spinlock_t lock;
+};
+
+static struct davinci_mcbsp mcbsp[DAVINCI_MAX_MCBSP_COUNT];
+
+unsigned short DAVINCI_MCBSP_READ(int base, int reg)
+{
+	unsigned long data, temp, *p = (unsigned long *)(base + reg);
+
+	temp = (unsigned long)p;
+
+	if (temp & 0x2) {
+		/*non word offset */
+		temp &= 0xfffffffc;
+		p = (unsigned long *)temp;
+		data = inl(p);
+		return (unsigned short)(data >> 16);
+	} else {
+		/*word offset */
+		return ((unsigned short)inl(p));
+	}
+}
+
+void DAVINCI_MCBSP_WRITE(int base, int reg, unsigned short val)
+{
+	unsigned long data, temp, *p = (unsigned long *)(base + reg);
+
+	temp = (unsigned long)p;
+
+	if (temp & 0x2) {
+		/*non word offset */
+		temp &= 0xfffffffc;
+		p = (unsigned long *)temp;
+		data = inl(p);
+		data &= 0x0000ffff;
+		data |= ((unsigned long)val << 16);
+		outl(data, p);
+	} else {
+		/*word offset */
+		data = inl(p);
+		data &= 0xffff0000;
+		data |= val;
+		outl(data, p);
+	}
+}
+
+static void davinci_mcbsp_dump_reg(u8 id)
+{
+	DBG("**** MCBSP%d regs ****\n", mcbsp[id].id);
+
+	DBG("SPCR2: 0x%04x\n", DAVINCI_MCBSP_READ(mcbsp[id].io_base, SPCR2));
+	DBG("SPCR1: 0x%04x\n",	DAVINCI_MCBSP_READ(mcbsp[id].io_base, SPCR1));
+	DBG("RCR2:  0x%04x\n",	DAVINCI_MCBSP_READ(mcbsp[id].io_base, RCR2));
+	DBG("RCR1:  0x%04x\n",	DAVINCI_MCBSP_READ(mcbsp[id].io_base, RCR1));
+	DBG("XCR2:  0x%04x\n",	DAVINCI_MCBSP_READ(mcbsp[id].io_base, XCR2));
+	DBG("XCR1:  0x%04x\n",	DAVINCI_MCBSP_READ(mcbsp[id].io_base, XCR1));
+	DBG("SRGR2: 0x%04x\n",	DAVINCI_MCBSP_READ(mcbsp[id].io_base, SRGR2));
+	DBG("SRGR1: 0x%04x\n",	DAVINCI_MCBSP_READ(mcbsp[id].io_base, SRGR1));
+	DBG("PCR0:  0x%04x\n",	DAVINCI_MCBSP_READ(mcbsp[id].io_base, PCR0));
+	DBG("***********************\n");
+}
+
+static void davinci_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
+{
+	struct davinci_mcbsp *mcbsp_dma_tx = (struct davinci_mcbsp *)(data);
+
+	DBG("TX DMA callback : 0x%x\n",
+	    DAVINCI_MCBSP_READ(mcbsp_dma_tx->io_base, SPCR2));
+
+	/* We can free the channels */
+	DBG("mcbsp_dma_tx->dma_tx_lch = %d\n",
+	       mcbsp_dma_tx->dma_tx_lch);
+	davinci_stop_dma(mcbsp_dma_tx->dma_tx_lch);
+	davinci_free_dma(mcbsp_dma_tx->dma_tx_lch);
+	mcbsp_dma_tx->dma_tx_lch = -1;
+	complete(&mcbsp_dma_tx->tx_dma_completion);
+}
+
+static void davinci_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
+{
+	struct davinci_mcbsp *mcbsp_dma_rx = (struct davinci_mcbsp *)(data);
+
+	DBG("RX DMA callback : 0x%x\n",
+	    DAVINCI_MCBSP_READ(mcbsp_dma_rx->io_base, SPCR2));
+
+	/* We can free the channels */
+	davinci_free_dma(mcbsp_dma_rx->dma_rx_lch);
+	mcbsp_dma_rx->dma_rx_lch = -1;
+
+	complete(&mcbsp_dma_rx->rx_dma_completion);
+}
+
+/*
+ * davinci_mcbsp_config simply write a config to the
+ * appropriate McBSP.
+ * You either call this function or set the McBSP registers
+ * by yourself before calling davinci_mcbsp_start().
+ */
+
+void davinci_mcbsp_config(unsigned int id,
+			  const struct davinci_mcbsp_reg_cfg *config)
+{
+	u32 io_base = mcbsp[id].io_base;
+
+	DBG("davinci-McBSP: McBSP%d  io_base: 0x%8x\n", id + 1, io_base);
+
+	DAVINCI_MCBSP_WRITE(io_base, PCR0, config->pcr0);
+
+	DAVINCI_MCBSP_WRITE(io_base, RCR2, config->rcr2);
+	DAVINCI_MCBSP_WRITE(io_base, RCR1, config->rcr1);
+
+	DAVINCI_MCBSP_WRITE(io_base, XCR2, config->xcr2);
+	DAVINCI_MCBSP_WRITE(io_base, XCR1, config->xcr1);
+
+	DAVINCI_MCBSP_WRITE(io_base, SRGR2, config->srgr2);
+	DAVINCI_MCBSP_WRITE(io_base, SRGR1, config->srgr1);
+
+	/* We write the given config */
+	DAVINCI_MCBSP_WRITE(io_base, SPCR2, config->spcr2);
+	DAVINCI_MCBSP_WRITE(io_base, SPCR1, config->spcr1);
+}
+
+static int davinci_mcbsp_check(unsigned int id)
+{
+	if (id > DAVINCI_MAX_MCBSP_COUNT - 1) {
+		DBG("DAVINCI-McBSP: McBSP%d doesn't exist\n", id + 1);
+		return -1;
+	}
+	return 0;
+}
+
+int davinci_mcbsp_request(unsigned int id)
+{
+	if (davinci_mcbsp_check(id) < 0)
+		return -EINVAL;
+
+	spin_lock(&mcbsp[id].lock);
+	if (!mcbsp[id].free) {
+		DBG("DAVINCI-McBSP: McBSP%d is currently in use\n", id + 1);
+		spin_unlock(&mcbsp[id].lock);
+		return -1;
+	}
+
+	mcbsp[id].free = 0;
+	spin_unlock(&mcbsp[id].lock);
+
+	return 0;
+}
+
+void davinci_mcbsp_free(unsigned int id)
+{
+	if (davinci_mcbsp_check(id) < 0)
+		return;
+
+	spin_lock(&mcbsp[id].lock);
+	if (mcbsp[id].free) {
+		DBG("DAVINCI-McBSP: McBSP%d was not reserved\n", id + 1);
+		spin_unlock(&mcbsp[id].lock);
+		return;
+	}
+
+	mcbsp[id].free = 1;
+	spin_unlock(&mcbsp[id].lock);
+
+	return;
+}
+
+/*
+ * Here we start the McBSP, by enabling the sample
+ * generator, both transmitter and receivers,
+ * and the frame sync.
+ */
+void davinci_mcbsp_start(unsigned int id)
+{
+	u32 io_base;
+	u16 w;
+
+	if (davinci_mcbsp_check(id) < 0)
+		return;
+
+	io_base = mcbsp[id].io_base;
+
+	mcbsp[id].rx_word_length =
+	    ((DAVINCI_MCBSP_READ(io_base, RCR1) >> 5) & 0x7);
+	mcbsp[id].tx_word_length =
+	    ((DAVINCI_MCBSP_READ(io_base, XCR1) >> 5) & 0x7);
+
+	/* Start the sample generator */
+	w = DAVINCI_MCBSP_READ(io_base, SPCR2);
+	DAVINCI_MCBSP_WRITE(io_base, SPCR2, w | (1 << 6));
+
+	/* Enable transmitter and receiver */
+	w = DAVINCI_MCBSP_READ(io_base, SPCR2);
+	DAVINCI_MCBSP_WRITE(io_base, SPCR2, w | 1);
+
+	w = DAVINCI_MCBSP_READ(io_base, SPCR1);
+	DAVINCI_MCBSP_WRITE(io_base, SPCR1, w | 1);
+
+	udelay(100);
+
+	/* Start frame sync */
+	w = DAVINCI_MCBSP_READ(io_base, SPCR2);
+	DAVINCI_MCBSP_WRITE(io_base, SPCR2, w | (1 << 7));
+
+	/* Dump mcbsp reg */
+	davinci_mcbsp_dump_reg(id);
+}
+
+void davinci_mcbsp_stop(unsigned int id)
+{
+	u32 io_base;
+	u16 w;
+
+	if (davinci_mcbsp_check(id) < 0)
+		return;
+
+	io_base = mcbsp[id].io_base;
+
+	/* Reset transmitter */
+	w = DAVINCI_MCBSP_READ(io_base, SPCR2);
+	DAVINCI_MCBSP_WRITE(io_base, SPCR2, w & ~(1));
+
+	/* Reset receiver */
+	w = DAVINCI_MCBSP_READ(io_base, SPCR1);
+	DAVINCI_MCBSP_WRITE(io_base, SPCR1, w & ~(1));
+
+	/* Reset the sample rate generator */
+	w = DAVINCI_MCBSP_READ(io_base, SPCR2);
+	DAVINCI_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 6));
+
+	/* Reset the frame sync generator */
+	w = DAVINCI_MCBSP_READ(io_base, SPCR2);
+	DAVINCI_MCBSP_WRITE(io_base, SPCR2, w & ~(1 << 7));
+}
+
+/*
+ * IRQ based word transmission.
+ */
+void davinci_mcbsp_xmit_word(unsigned int id, u32 word)
+{
+
+	u32 io_base;
+	davinci_mcbsp_word_length word_length = mcbsp[id].tx_word_length;
+
+	if (davinci_mcbsp_check(id) < 0)
+		return;
+
+	io_base = mcbsp[id].io_base;
+
+	if (word_length > DAVINCI_MCBSP_WORD_16)
+		DAVINCI_MCBSP_WRITE(io_base, DXR2, word >> 16);
+	DAVINCI_MCBSP_WRITE(io_base, DXR1, word & 0xffff);
+}
+
+u32 davinci_mcbsp_recv_word(unsigned int id)
+{
+
+	u32 io_base;
+	u16 word_lsb, word_msb = 0;
+
+	davinci_mcbsp_word_length word_length = mcbsp[id].rx_word_length;
+
+	if (davinci_mcbsp_check(id) < 0)
+		return -EINVAL;
+
+	io_base = mcbsp[id].io_base;
+
+	if (word_length > DAVINCI_MCBSP_WORD_16)
+		word_msb = DAVINCI_MCBSP_READ(io_base, DRR2);
+	word_lsb = DAVINCI_MCBSP_READ(io_base, DRR1);
+
+	return (word_lsb | (word_msb << 16));
+}
+
+/*
+ * Simple DMA based buffer rx/tx routines.
+ * Nothing fancy, just a single buffer tx/rx through DMA.
+ * The DMA resources are released once the transfer is done.
+ * For anything fancier, you should use your own customized DMA
+ * routines and callbacks.
+ */
+int davinci_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
+			      unsigned int length)
+{
+	int dma_tx_ch;
+	int tcc;
+
+	if (davinci_mcbsp_check(id) < 0)
+		return -EINVAL;
+
+	if (davinci_request_dma
+	    (mcbsp[id].dma_tx_sync, "McBSP TX", davinci_mcbsp_tx_dma_callback,
+	     &mcbsp[id], &dma_tx_ch, &tcc, EVENTQ_0)) {
+		DBG("DAVINCI-McBSP: Unable to request DMA channel for McBSP%d TX."
+		    "Trying IRQ based TX\n", id + 1);
+		return -EAGAIN;
+	}
+
+	mcbsp[id].dma_tx_lch = dma_tx_ch;
+
+	DBG("TX DMA on channel %d\n", dma_tx_ch);
+
+	init_completion(&(mcbsp[id].tx_dma_completion));
+
+	davinci_set_dma_transfer_params(mcbsp[id].dma_tx_lch, 2, length / 2, 1,
+					0, ASYNC);
+
+	davinci_set_dma_dest_params(mcbsp[id].dma_tx_lch,
+				    (unsigned long)0x01E02004, 0, 0);
+
+	davinci_set_dma_src_params(mcbsp[id].dma_tx_lch, (buffer), 0, 0);
+	davinci_set_dma_src_index(mcbsp[id].dma_tx_lch, 2, 0);
+	davinci_set_dma_dest_index(mcbsp[id].dma_tx_lch, 0, 0);
+
+	davinci_start_dma(mcbsp[id].dma_tx_lch);
+	wait_for_completion(&(mcbsp[id].tx_dma_completion));
+	return 0;
+}
+
+int davinci_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,
+			      unsigned int length)
+{
+	int dma_rx_ch;
+	int tcc;
+
+	if (davinci_mcbsp_check(id) < 0)
+		return -EINVAL;
+
+	if (davinci_request_dma
+	    (mcbsp[id].dma_rx_sync, "McBSP RX", davinci_mcbsp_rx_dma_callback,
+	     &mcbsp[id], &dma_rx_ch, &tcc, EVENTQ_0)) {
+		DBG("Unable to request DMA channel for McBSP%d RX."
+		    "Trying IRQ based RX\n",  id + 1);
+		return -EAGAIN;
+	}
+	mcbsp[id].dma_rx_lch = dma_rx_ch;
+
+	DBG("RX DMA on channel %d\n", dma_rx_ch);
+
+	init_completion(&(mcbsp[id].rx_dma_completion));
+
+	davinci_set_dma_transfer_params(mcbsp[id].dma_rx_lch, 2, length / 2, 1,
+					0, ASYNC);
+
+	davinci_set_dma_src_params(mcbsp[id].dma_rx_lch,
+				   (unsigned long)0x01E02000, 0, 0);
+
+	davinci_set_dma_dest_params(mcbsp[id].dma_rx_lch,
+				    (unsigned long)virt_to_phys((void *)buffer),
+				    0, 0);
+	davinci_set_dma_src_index(mcbsp[id].dma_rx_lch, 0, 0);
+	davinci_set_dma_dest_index(mcbsp[id].dma_rx_lch, 2, 0);
+
+	davinci_start_dma(mcbsp[id].dma_rx_lch);
+
+	wait_for_completion(&(mcbsp[id].rx_dma_completion));
+	return 0;
+}
+
+struct clk * davinci_mcbsp_get_clock(void)
+{
+	return mbspclk;
+}
+
+struct davinci_mcbsp_info {
+	u32 virt_base;
+	u8 dma_rx_sync, dma_tx_sync;
+	u16 rx_irq, tx_irq;
+};
+
+static const struct davinci_mcbsp_info mcbsp_davinci[] = {
+	[0] = { .virt_base = IO_ADDRESS(DAVINCI_MCBSP1_BASE),
+		.dma_rx_sync = DAVINCI_DMA_MCBSP1_RX,
+		.dma_tx_sync = DAVINCI_DMA_MCBSP1_TX,
+		.rx_irq = DAVINCI_McBSP1RX,
+		.tx_irq = DAVINCI_McBSP1TX},
+};
+
+static int __init davinci_mcbsp_init(void)
+{
+	int mcbsp_count = 0, i;
+	static const struct davinci_mcbsp_info *mcbsp_info;
+	struct clk *clkp;
+
+	printk(KERN_INFO "Initializing DaVinci McBSP system\n");
+
+	clkp = clk_get (NULL, "McBSPCLK");
+	if (IS_ERR(clkp)) {
+		printk(KERN_ERR "mcbsp: could not acquire McBSP clk\n");
+		return PTR_ERR(clkp);
+	}
+	else {
+		mbspclk = clkp;
+		clk_enable(mbspclk);
+
+		mcbsp_info = mcbsp_davinci;
+		mcbsp_count = ARRAY_SIZE(mcbsp_davinci);
+
+		for (i = 0; i < DAVINCI_MAX_MCBSP_COUNT; i++) {
+			if (i >= mcbsp_count) {
+				mcbsp[i].io_base = 0;
+				mcbsp[i].free = 0;
+				continue;
+			}
+			mcbsp[i].id = i + 1;
+			mcbsp[i].free = 1;
+			mcbsp[i].dma_tx_lch = -1;
+			mcbsp[i].dma_rx_lch = -1;
+
+			mcbsp[i].io_base = mcbsp_info[i].virt_base;
+			mcbsp[i].tx_irq = mcbsp_info[i].tx_irq;
+			mcbsp[i].rx_irq = mcbsp_info[i].rx_irq;
+			mcbsp[i].dma_rx_sync = mcbsp_info[i].dma_rx_sync;
+			mcbsp[i].dma_tx_sync = mcbsp_info[i].dma_tx_sync;
+			spin_lock_init(&mcbsp[i].lock);
+		}
+	}
+	return 0;
+}
+
+static void __exit davinci_mcbsp_exit(void)
+{
+	int i;
+
+	for (i = 0; i < DAVINCI_MAX_MCBSP_COUNT; i++) {
+		mcbsp[i].free = 0;
+		mcbsp[i].dma_tx_lch = -1;
+		mcbsp[i].dma_rx_lch = -1;
+	}
+
+	clk_disable (mbspclk);
+
+	return;
+}
+
+module_init(davinci_mcbsp_init);
+module_exit(davinci_mcbsp_exit);
+
+EXPORT_SYMBOL(davinci_mcbsp_config);
+EXPORT_SYMBOL(davinci_mcbsp_request);
+EXPORT_SYMBOL(davinci_mcbsp_free);
+EXPORT_SYMBOL(davinci_mcbsp_start);
+EXPORT_SYMBOL(davinci_mcbsp_stop);
+EXPORT_SYMBOL(davinci_mcbsp_xmit_word);
+EXPORT_SYMBOL(davinci_mcbsp_recv_word);
+EXPORT_SYMBOL(davinci_mcbsp_xmit_buffer);
+EXPORT_SYMBOL(davinci_mcbsp_recv_buffer);
+EXPORT_SYMBOL(davinci_mcbsp_get_clock);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("McBSP driver for DaVinci.");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index 1334416..0b4d6e7 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -134,6 +134,7 @@
 	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1);
 	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1);
 	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1);
+	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_USB, 1);
 
 	/* Turn on WatchDog timer LPSC.	 Needed for RESET to work */
 	davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1);
diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c
index 8368c93..d0e7c52 100644
--- a/arch/arm/mach-davinci/serial.c
+++ b/arch/arm/mach-davinci/serial.c
@@ -42,7 +42,7 @@
 	return (unsigned int)__raw_readb(up->membase + offset);
 }
 
-static inline void davinci_serial_outp(struct plat_serial8250_port *p,
+static inline void davinci_serial_outp(struct plat_serial8250_port *p, 
 				       int offset, int value)
 {
 	offset <<= p->regshift;
@@ -71,7 +71,7 @@
 		.platform_data	= serial_platform_data,
 	},
 };
-
+  
 static void __init davinci_serial_reset(struct plat_serial8250_port *p)
 {
 	/* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */
@@ -89,6 +89,16 @@
 
 static int __init davinci_init(void)
 {
+	struct clk *uart_clk;
+	struct device *dev = &serial_device.dev;
+
+	uart_clk = clk_get(dev, "UART");
+	if (IS_ERR(uart_clk))
+		printk(KERN_ERR "%s:%d: failed to get UART clock\n",
+		       __FUNCTION__, __LINE__);
+	else
+		clk_enable(uart_clk);
+
 	davinci_serial_reset(&serial_platform_data[0]);
 	return platform_device_register(&serial_device);
 }
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index b391776..35f8296 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -833,6 +833,12 @@
 	  will get access to the real time clock (or hardware clock) built
 	  into your computer.
 
+config DAVINCI_RTC
+	bool "TI DaVinci Real Time Clock"
+	depends on ARCH_DAVINCI && MACH_DAVINCI_EVM && I2C_DAVINCI
+	help
+	  Support for TI DaVinci RTC
+
 config COBALT_LCD
 	bool "Support for Cobalt LCD"
 	depends on MIPS_COBALT
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index c78ff26..e08d6c5 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -105,6 +105,7 @@
 
 obj-$(CONFIG_HANGCHECK_TIMER)	+= hangcheck-timer.o
 obj-$(CONFIG_TCG_TPM)		+= tpm/
+obj-$(CONFIG_DAVINCI_RTC)	+= davinci-rtc.o
 
 obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
 
diff --git a/drivers/char/davinci-rtc.c b/drivers/char/davinci-rtc.c
new file mode 100644
index 0000000..f138363
--- /dev/null
+++ b/drivers/char/davinci-rtc.c
@@ -0,0 +1,252 @@
+/*
+ *  linux/drivers/char/rtc.c
+ *
+ * Copyright (C) 2004 Texas Instruments Inc
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * ----------------------------------------------------------------------------
+ Modifications:
+ ver. 1.0: Jan 2006, Swaminathan S
+ -
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <asm/rtc.h>
+#include <asm/arch/i2c-client.h>
+
+static unsigned char am;
+
+static int _rtc_read_time(struct rtc_time *tm);
+static int _rtc_set_time(struct rtc_time *tm);
+static void am_or_pm (void);
+
+static struct rtc_ops davinci_rtc_ops = {
+        .owner          = THIS_MODULE,
+        .read_time      = _rtc_read_time,
+        .set_time       = _rtc_set_time,
+};
+
+static unsigned long epoch = 1900;      /* year corresponding to 0x00   */
+
+static const unsigned char days_in_mo[] =
+{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+static int _rtc_read_time(struct rtc_time *tm)
+{
+	char rtcdata [9] = { 2, 1, 0, 0, 0, 0,
+			     0, 0, 0 };
+
+	davinci_i2c_write (2, rtcdata, 0x23);
+	udelay (1000);
+	davinci_i2c_read (9, rtcdata, 0x23);
+	udelay (1000);
+
+	tm->tm_year = BCD_TO_BIN (rtcdata[3]) * 100 + BCD_TO_BIN (rtcdata[2]) - 1900;
+	tm->tm_mon = BCD_TO_BIN (rtcdata[4]);
+	tm->tm_mday = BCD_TO_BIN (rtcdata[5]);
+	tm->tm_hour = BCD_TO_BIN (rtcdata[6]);
+	tm->tm_min = BCD_TO_BIN (rtcdata[7]);
+	tm->tm_sec = BCD_TO_BIN (rtcdata[8]);
+
+	return 0;
+}
+
+static int _rtc_set_time(struct rtc_time *tm)
+{
+	char rtcdata [9];
+	char ampmdata [9];
+	struct timespec tv;
+	unsigned char mon, day, hrs = 0, min, sec, leap_yr;
+	unsigned char yr_low, yr_high;
+	unsigned int yrs;
+
+	am_or_pm ();
+
+	yrs = tm->tm_year + 1900;
+	yr_high = yrs/100;
+	yr_low = (yrs) % 100;
+
+	mon = tm->tm_mon;
+	hrs = tm->tm_hour;
+	day = tm->tm_mday;
+	min = tm->tm_min;
+	sec = tm->tm_sec;
+
+	if (yrs < 1970 || yrs > 2037)
+                return -EINVAL;
+
+        leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
+
+	if ((mon > 11) || (day == 0))
+                return -EINVAL;
+
+        if (day > (days_in_mo[mon] + ((mon == 1) && leap_yr)))
+                return -EINVAL;
+
+        if ((hrs >= 24) || (min >= 60) || (sec >= 60))
+                return -EINVAL;
+
+        if ((yrs -= epoch) > 255) {    /* They are unsigned */
+                return -EINVAL;
+        }
+
+	if (am == 1 && tm->tm_hour <= 12) {
+		hrs = tm->tm_hour;
+		if (tm->tm_hour == 0)
+			hrs = tm->tm_hour + 12;
+	}
+
+	else if ((am == 1 && tm->tm_hour > 12) ||
+	    	 (am == 0 && tm->tm_hour < 12)) {
+		unsigned char mon1 = mon, day1 = day, hrs1 = 11, min1 = 59, sec1 = 59;
+		unsigned char yr_low1 = yr_low, yr_high1 = yr_high;
+
+		ampmdata [0] = 9;
+		ampmdata [1] = 0;
+		ampmdata [2] = BIN_TO_BCD(yr_low1);
+		ampmdata [3] = BIN_TO_BCD(yr_high1);
+		ampmdata [4] = BIN_TO_BCD(mon1);
+		ampmdata [5] = BIN_TO_BCD(day1);
+		ampmdata [6] = BIN_TO_BCD(hrs1);
+		ampmdata [7] = BIN_TO_BCD(min1);
+		ampmdata [8] = BIN_TO_BCD(sec1);
+		davinci_i2c_write (9, ampmdata, 0x23);
+		udelay (1000);
+		mdelay (1000);
+		am = (am == 1) ? 0 : 1;
+
+		if (!am)
+			hrs = tm->tm_hour - 12;
+		else if (tm->tm_hour == 0)
+			hrs = tm->tm_hour + 12;
+	}
+
+	else if (am == 0 && tm->tm_hour > 12) {
+		hrs = tm->tm_hour - 12;
+	}
+
+	rtcdata [0] = 9;
+	rtcdata [1] = 0;
+	rtcdata [2] = BIN_TO_BCD(yr_low);
+	rtcdata [3] = BIN_TO_BCD(yr_high);
+	rtcdata [4] = BIN_TO_BCD(mon);
+	rtcdata [5] = BIN_TO_BCD(day);
+	rtcdata [6] = BIN_TO_BCD(hrs);
+	rtcdata [7] = BIN_TO_BCD(min);
+	rtcdata [8] = BIN_TO_BCD(sec);
+	davinci_i2c_write (9, rtcdata, 0x23);
+	udelay (1000);
+
+	tv.tv_nsec = 0;
+        tv.tv_sec = mktime (tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+				tm->tm_hour, tm->tm_min, tm->tm_sec+2);
+        do_settimeofday (&tv);
+
+	return 0;
+}
+
+static void am_or_pm (void)
+{
+	char rtcdata [9];
+	struct rtc_time tm, time, temp;
+	unsigned char mon, day, hrs, min, sec;
+	unsigned char yr_low, yr_high;
+	unsigned int yrs;
+
+	_rtc_read_time (&tm);
+
+	temp = tm;
+
+	yrs = temp.tm_year + 1900;
+	yr_high = yrs/100;
+	yr_low = (yrs) % 100;
+
+	mon = temp.tm_mon + 1;
+	day = temp.tm_mday;
+	min = 59;
+	sec = 59;
+	hrs = 11;
+
+	rtcdata [0] = 9;
+	rtcdata [1] = 0;
+	rtcdata [2] = BIN_TO_BCD(yr_low);
+	rtcdata [3] = BIN_TO_BCD(yr_high);
+	mon--;
+	rtcdata [4] = BIN_TO_BCD(mon);
+	rtcdata [5] = BIN_TO_BCD(day);
+	rtcdata [6] = BIN_TO_BCD(hrs);
+	rtcdata [7] = BIN_TO_BCD(min);
+	rtcdata [8] = BIN_TO_BCD(sec);
+	davinci_i2c_write (9, rtcdata, 0x23);
+	udelay (1000);
+	mdelay (1000);
+	_rtc_read_time (&time);
+
+	if (time.tm_mday == temp.tm_mday)
+		am = 1;
+	else
+		am = 0;
+
+	davinci_i2c_write (9, rtcdata, 0x23);
+	udelay (1000);
+	mdelay (1000);
+
+	yrs = tm.tm_year + 1900;
+	yr_high = yrs/100;
+	yr_low = (yrs) % 100;
+
+	mon = tm.tm_mon + 1;
+	day = tm.tm_mday;
+	min = tm.tm_min;
+	hrs = tm.tm_hour;
+	if (tm.tm_sec < 58)
+	{
+		sec = tm.tm_sec + 2;
+	} else {
+		sec = 59;
+	}
+
+	davinci_i2c_write (9, rtcdata, 0x23);
+	udelay (1000);
+}
+
+static int __init davinci_rtc_init(void)
+{
+	struct timespec tv;
+	struct rtc_time tm;
+        register_rtc (&davinci_rtc_ops);
+
+	am_or_pm ();
+
+	_rtc_read_time (&tm);
+
+        tv.tv_nsec = 0;
+        tv.tv_sec = mktime (tm.tm_year + 1900, tm.tm_mon + 1 , tm.tm_mday,
+				tm.tm_hour, tm.tm_min, tm.tm_sec);
+        do_settimeofday (&tv);
+
+	return 0;
+}
+
+module_init(davinci_rtc_init);
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 9f3a4cd..6906436 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -654,4 +654,8 @@
 	  This driver can also be built as module. If so, the module
 	  will be called i2c-pmcmsp.
 
+config I2C_DAVINCI
+        tristate "Davinci i2c driver"
+        depends on I2C && ARCH_DAVINCI
+
 endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 0e4c170..e55051d 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -53,6 +53,7 @@
 obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)	+= scx200_i2c.o
 obj-$(CONFIG_I2C_OMAP)          += i2c-omap.o
+obj-$(CONFIG_I2C_DAVINCI)       += i2c-davinci.o
 
 ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c
new file mode 100644
index 0000000..1c2eef4
--- /dev/null
+++ b/drivers/i2c/busses/i2c-davinci.c
@@ -0,0 +1,599 @@
+/*
+ * linux/drivers/i2c/i2c-davinci.c
+ *
+ * TI DAVINCI I2C unified algorith+adapter driver
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ Modifications:
+ ver. 1.0: Feb 2005, Vinod/Sudhakar
+ -
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/version.h>
+#include <linux/i2c.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <asm/arch/hardware.h>
+#include <linux/interrupt.h>
+#include <linux/moduleparam.h>
+#include <linux/err.h>
+#include <linux/proc_fs.h>
+#include <linux/sysctl.h>
+#include <linux/wait.h>
+#include <asm/arch/irqs.h>
+#include <asm/mach-types.h>
+#include "i2c-davinci.h"
+
+MODULE_AUTHOR("Texas Instruments India");
+MODULE_DESCRIPTION("TI DaVinci I2C bus adapter");
+MODULE_LICENSE("GPL");
+
+static int bus_freq;
+module_param(bus_freq, int, 0);
+MODULE_PARM_DESC(bus_freq,
+  "Set I2C bus frequency in KHz: 100 (Standard Mode) or 400 (Fast Mode)");
+
+/* ----- global defines ----------------------------------------------- */
+static const char driver_name[] = "i2c_davinci";
+
+#define DAVINCI_I2C_TIMEOUT (1*HZ)
+#define MAX_MESSAGES    65536	/* max number of messages */
+#define I2C_DAVINCI_INTR_ALL    (DAVINCI_I2C_ICIMR_AAS_MASK | \
+				 DAVINCI_I2C_ICIMR_SCD_MASK | \
+				 /*DAVINCI_I2C_ICIMR_ICXRDY_MASK | */\
+				 /*DAVINCI_I2C_ICIMR_ICRRDY_MASK | */\
+				 DAVINCI_I2C_ICIMR_ARDY_MASK | \
+				 DAVINCI_I2C_ICIMR_NACK_MASK | \
+				 DAVINCI_I2C_ICIMR_AL_MASK)
+
+/* Following are the default values for the module parameters */
+
+
+static int bus_freq = 400; /* Default: Fast Mode = 400 KHz, Standard Mode = 100 KHz */
+
+static int own_addr = 0x1;	/* Randomly assigned own address */
+
+/* Instance of the private I2C device structure */
+static struct i2c_davinci_device i2c_davinci_dev;
+
+#define PINMUX1		__REG(0x01c40004)
+#define GPIO		__REG(0x01C67000)
+#define GPIO23_DIR	__REG(0x01C67038)
+#define GPIO23_SET	__REG(0x01C67040)
+#define GPIO23_CLR	__REG(0x01C67044)
+
+/*
+ * This functions configures I2C and brings I2C out of reset.
+ * This function is called during I2C init function. This function
+ * also gets called if I2C encounetrs any errors. Clock calculation portion
+ * of this function has been taken from some other driver.
+ */
+static int i2c_davinci_reset(struct i2c_davinci_device *dev)
+{
+	u16 psc;
+	u32 clk;
+	u32 input_clock = clk_get_rate(dev->clk);
+
+	/* put I2C into reset */
+	dev->regs->icmdr &= ~DAVINCI_I2C_ICMDR_IRS_MASK;
+
+        /* NOTE: I2C Clock divider programming info
+	 * As per I2C specs the following formulas provide prescalar
+         * and low/high divider values
+	 *
+	 * input clk --> PSC Div -----------> ICCL/H Div --> output clock
+	 *                       module clk
+	 *
+	 * output clk = module clk / (PSC + 1) [ (ICCL + d) + (ICCH + d) ]
+	 *
+	 * Thus,
+	 * (ICCL + ICCH) = clk = (input clk / ((psc +1) * output clk)) - 2d;
+	 *
+	 * where if PSC == 0, d = 7,
+	 *       if PSC == 1, d = 6
+	 *       if PSC > 1 , d = 5
+	 */
+
+	psc = 26; /* To get 1MHz clock */
+
+        clk = ((input_clock/(psc + 1)) / (bus_freq * 1000)) - 10;
+
+	dev->regs->icpsc = psc;
+	dev->regs->icclkh = (50 * clk) / 100; /* duty cycle should be 27% */
+	dev->regs->icclkl = (clk - dev->regs->icclkh);
+
+	dev_dbg(dev->dev, "CLK  = %d\n", clk);
+	dev_dbg(dev->dev, "PSC  = %d\n", dev->regs->icpsc);
+	dev_dbg(dev->dev, "CLKL = %d\n", dev->regs->icclkl);
+	dev_dbg(dev->dev, "CLKH = %d\n", dev->regs->icclkh);
+
+	/* Set Own Address: */
+	dev->regs->icoar = own_addr;
+
+	/* Enable interrupts */
+	dev->regs->icimr = I2C_DAVINCI_INTR_ALL;
+
+	/* Take the I2C module out of reset: */
+	dev->regs->icmdr |= DAVINCI_I2C_ICMDR_IRS_MASK;
+
+	return 0;
+}
+
+/*
+ * Waiting on Bus Busy
+ */
+static int i2c_davinci_wait_for_bb(struct i2c_davinci_device *dev,
+				   char allow_sleep)
+{
+	unsigned long timeout;
+	int i;
+	static	char to_cnt = 0;
+
+	timeout = jiffies + DAVINCI_I2C_TIMEOUT;
+	while ((i2c_davinci_dev.regs->icstr) & DAVINCI_I2C_ICSTR_BB_MASK) {
+		if (to_cnt <= 2) {
+			if (time_after(jiffies, timeout)) {
+				dev_warn(dev->dev,
+					 "timeout waiting for bus ready");
+				to_cnt ++;
+				return -ETIMEDOUT;
+			}
+		}
+		else {
+			to_cnt = 0;
+			/* Send the NACK to the slave */
+			dev->regs->icmdr |= DAVINCI_I2C_ICMDR_NACKMOD_MASK;
+			/* Disable I2C */
+			PINMUX1 &= (~(1 << 7));
+
+			/* Set the GPIO direction register */
+			GPIO23_DIR &= ~0x0800;
+
+			/* Send high and low on the SCL line */
+			for (i = 0; i < 10; i++) {
+				GPIO23_SET |= 0x0800;
+				udelay(25);
+				GPIO23_CLR |= 0x0800;
+				udelay(25);
+			}
+			/* Re-enable I2C */
+			PINMUX1 |= (1 << 7);
+
+			i2c_davinci_reset(dev);
+			init_completion(&dev->cmd_complete);
+		}
+		if (allow_sleep)
+			schedule_timeout(1);
+	}
+
+	return 0;
+}
+
+/*
+ * Low level master read/write transaction. This function is called
+ * from i2c_davinci_xfer.
+ */
+static int
+i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
+{
+	struct i2c_davinci_device *dev = i2c_get_adapdata(adap);
+	u8 zero_byte = 0;
+	int r;
+
+	u32 flag = 0, stat = 0;
+	int i;
+
+	/* Introduce a 100musec delay.  Required for Davinci EVM board only */
+	if (machine_is_davinci_evm())
+		udelay(100);
+
+	/* set the slave address */
+	dev->regs->icsar = msg->addr;
+
+	/* Sigh, seems we can't do zero length transactions. Thus, we
+	 * can't probe for devices w/o actually sending/receiving at least
+	 * a single byte. So we'll set count to 1 for the zero length
+	 * transaction case and hope we don't cause grief for some
+	 * arbitrary device due to random byte write/read during
+	 * probes.
+	 */
+	if (msg->len == 0) {
+		dev->buf = &zero_byte;
+		dev->buf_len = 1;
+	} else {
+		dev->buf = msg->buf;
+		dev->buf_len = msg->len;
+	}
+
+	dev->regs->iccnt = dev->buf_len;
+	init_completion(&dev->cmd_complete);
+	dev->cmd_err = 0;
+
+	/* Clear any pending interrupts by reading the IVR */
+	stat = dev->regs->icivr;
+
+	/* Take I2C out of reset, configure it as master and set the
+	 * start bit */
+	flag =
+	    DAVINCI_I2C_ICMDR_IRS_MASK | DAVINCI_I2C_ICMDR_MST_MASK |
+	    DAVINCI_I2C_ICMDR_STT_MASK;
+
+	/* if the slave address is ten bit address, enable XA bit */
+	if (msg->flags & I2C_M_TEN)
+		flag |= DAVINCI_I2C_ICMDR_XA_MASK;
+	if (!(msg->flags & I2C_M_RD))
+		flag |= DAVINCI_I2C_ICMDR_TRX_MASK;
+	if (stop)
+		flag |= DAVINCI_I2C_ICMDR_STP_MASK;
+
+	/* Enable receive and transmit interrupts */
+	if (msg->flags & I2C_M_RD)
+		dev->regs->icimr |= DAVINCI_I2C_ICIMR_ICRRDY_MASK;
+	else
+		dev->regs->icimr |= DAVINCI_I2C_ICIMR_ICXRDY_MASK;
+
+	/* write the data into mode register */
+	dev->regs->icmdr = flag;
+
+	r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
+						      DAVINCI_I2C_TIMEOUT);
+	dev->buf_len = 0;
+	if (r < 0)
+		return r;
+	if (r == 0) {
+		dev_err(dev->dev, "controller timed out\n");
+
+		/* Send the NACK to the slave */
+		dev->regs->icmdr |= DAVINCI_I2C_ICMDR_NACKMOD_MASK;
+		/* Disable I2C */
+		PINMUX1 &= (~(1 << 7));
+
+		/* Set the GPIO direction register */
+		GPIO23_DIR &= ~0x0800;
+
+		/* Send high and low on the SCL line */
+		for (i = 0; i < 10; i++) {
+			GPIO23_SET |= 0x0800;
+			udelay(25);
+			GPIO23_CLR |= 0x0800;
+			udelay(25);
+		}
+		/* Re-enable I2C */
+		PINMUX1 |= (1 << 7);
+
+		i2c_davinci_reset(dev);
+		return -ETIMEDOUT;
+	}
+
+	/* no error */
+	if (!dev->cmd_err)
+		return msg->len;
+
+	/* We have an error */
+	if (dev->cmd_err & DAVINCI_I2C_ICSTR_NACK_MASK) {
+		if (msg->flags & I2C_M_IGNORE_NAK)
+			return msg->len;
+		if (stop)
+			dev->regs->icmdr |= DAVINCI_I2C_ICMDR_STP_MASK;
+		return -EREMOTEIO;
+	}
+	if (dev->cmd_err & DAVINCI_I2C_ICSTR_AL_MASK) {
+		i2c_davinci_reset(dev);
+		return -EIO;
+	}
+	return msg->len;
+}
+
+/*
+ * Prepare controller for a transaction and call i2c_davinci_xfer_msg
+
+ */
+static int
+i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+	struct i2c_davinci_device *dev = i2c_get_adapdata(adap);
+	int count;
+	int ret = 0;
+	char retries = 5;
+
+	dev_dbg(dev->dev, "%s: msgs: %d\n", __FUNCTION__, num);
+
+	if (num < 1 || num > MAX_MESSAGES)
+		return -EINVAL;
+
+	/* Check for valid parameters in messages */
+	for (count = 0; count < num; count++)
+		if (msgs[count].buf == NULL)
+			return -EINVAL;
+
+	if ((ret = i2c_davinci_wait_for_bb(dev, 1)) < 0) {
+		dev_warn(dev->dev, "timeout waiting for bus ready");
+		return ret;
+	}
+
+	for (count = 0; count < num; count++) {
+		dev_dbg(dev->dev,
+			"%s: %d, addr: 0x%04x, len: %d, flags: 0x%x\n",
+			__FUNCTION__,
+			count, msgs[count].addr, msgs[count].len,
+			msgs[count].flags);
+
+		do {
+			ret = i2c_davinci_xfer_msg(adap, &msgs[count],
+						   (count == (num - 1)));
+
+			if (ret < 0) {
+				dev_dbg(dev->dev, "Retrying ...\n");
+				mdelay (1);
+				retries--;
+			} else
+				break;
+		} while (retries);
+
+		dev_dbg(dev->dev, "%s:%d ret: %d\n",
+			__FUNCTION__, __LINE__, ret);
+
+		if (ret != msgs[count].len)
+			break;
+	}
+
+	if (ret >= 0 && num >= 1)
+		ret = num;
+
+	dev_dbg(dev->dev, "%s:%d ret: %d\n",
+		__FUNCTION__, __LINE__, ret);
+
+	return ret;
+}
+
+static u32 i2c_davinci_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+/*
+ * This function marks a transaction as complete.
+ */
+static inline void i2c_davinci_complete_cmd(struct i2c_davinci_device *dev)
+{
+	complete(&dev->cmd_complete);
+	wake_up(&dev->cmd_wait);
+}
+
+/*
+ * Interrupt service routine. This gets called whenever an I2C interrupt
+ * occurs.
+ */
+static irqreturn_t
+i2c_davinci_isr(int this_irq, void *dev_id)
+{
+	struct i2c_davinci_device *dev = dev_id;
+	u32 stat;
+
+	while ((stat = dev->regs->icivr) != 0) {
+		dev_dbg(dev->dev, "%s: stat=0x%x\n", __FUNCTION__, stat);
+
+		switch (stat) {
+		case DAVINCI_I2C_ICIVR_INTCODE_AL:
+			dev->cmd_err |= DAVINCI_I2C_ICSTR_AL_MASK;
+			i2c_davinci_complete_cmd(dev);
+			break;
+
+		case DAVINCI_I2C_ICIVR_INTCODE_NACK:
+			dev->cmd_err |= DAVINCI_I2C_ICSTR_NACK_MASK;
+			i2c_davinci_complete_cmd(dev);
+			break;
+
+		case DAVINCI_I2C_ICIVR_INTCODE_RAR:
+                        dev->regs->icstr |= DAVINCI_I2C_ICSTR_ARDY_MASK;
+			i2c_davinci_complete_cmd(dev);
+                        break;
+
+		case DAVINCI_I2C_ICIVR_INTCODE_RDR:
+			if (dev->buf_len) {
+				*dev->buf++ = dev->regs->icdrr;
+				dev->buf_len--;
+				if (dev->buf_len) {
+					continue;
+				} else {
+					dev->regs->icimr &=
+					    ~DAVINCI_I2C_ICIMR_ICRRDY_MASK;
+				}
+			}
+			break;
+
+		case DAVINCI_I2C_ICIVR_INTCODE_TDR:
+			if (dev->buf_len) {
+				dev->regs->icdxr = *dev->buf++;
+				dev->buf_len--;
+				if (dev->buf_len)
+					continue;
+				else {
+					dev->regs->icimr &=
+					    ~DAVINCI_I2C_ICIMR_ICXRDY_MASK;
+				}
+			}
+			break;
+
+		case DAVINCI_I2C_ICIVR_INTCODE_SCD:
+                        dev->regs->icstr |= DAVINCI_I2C_ICSTR_SCD_MASK;
+                        i2c_davinci_complete_cmd(dev);
+                        break;
+
+		case DAVINCI_I2C_ICIVR_INTCODE_AAS:
+			dev_warn(dev->dev, "Address as slave interrupt");
+			break;
+
+		default:
+			break;
+		}		/* switch */
+	}			/* while */
+	return IRQ_HANDLED;
+}
+
+static struct i2c_algorithm i2c_davinci_algo = {
+	.master_xfer = i2c_davinci_xfer,
+	.functionality = i2c_davinci_func,
+};
+
+static int
+davinci_i2c_probe(struct platform_device *pdev)
+{
+	struct i2c_davinci_device *dev = &i2c_davinci_dev;
+	struct i2c_adapter	*adap;
+	struct resource		*mem, *irq;
+	int r;
+
+	/* NOTE: driver uses the static register mapping */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource?\n");
+		return -ENODEV;
+	}
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		return -ENODEV;
+	}
+
+	r = (int) request_mem_region(mem->start, (mem->end - mem->start) + 1,
+			driver_name);
+	if (!r) {
+		dev_err(&pdev->dev, "I2C region already claimed\n");
+		return -EBUSY;
+	}
+
+	memset(dev, 0, sizeof(struct i2c_davinci_device));
+	init_waitqueue_head(&dev->cmd_wait);
+	dev->dev = &pdev->dev;
+
+	/*
+	 * NOTE: On DaVinci EVM, the i2c bus frequency is set to 20kHz
+	 *	 so that the MSP430, which is doing software i2c, has
+	 *	 some extra processing time
+	 */
+	if (machine_is_davinci_evm())
+		bus_freq = 20;
+
+	else if (bus_freq > 200)
+		bus_freq = 400;	/* Fast mode */
+	else
+		bus_freq = 100;	/* Standard mode */
+
+	dev->clk = clk_get (&pdev->dev, "I2CCLK");
+	if (IS_ERR(dev->clk))
+		return -1;
+	clk_enable(dev->clk);
+
+	dev->regs = (davinci_i2cregsovly)mem->start;
+	i2c_davinci_reset(dev);
+
+	dev->irq = irq->start;
+	platform_set_drvdata(pdev, dev);
+
+	r = request_irq(dev->irq, i2c_davinci_isr, 0, driver_name, dev);
+	if (r) {
+		dev_err(&pdev->dev, "failure requesting irq %i\n", dev->irq);
+		goto do_unuse_clocks;
+	}
+
+	adap = &dev->adapter;
+	i2c_set_adapdata(adap, dev);
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_HWMON;
+	strncpy(adap->name, "DaVinci I2C adapter", sizeof(adap->name));
+	adap->algo = &i2c_davinci_algo;
+	adap->dev.parent = &pdev->dev;
+	adap->client_register = NULL;
+	adap->client_unregister = NULL;
+	adap->timeout = 1;
+	adap->retries = 1;
+
+	/* i2c device drivers may be active on return from add_adapter() */
+	r = i2c_add_adapter(adap);
+	if (r) {
+		dev_err(&pdev->dev, "failure adding adapter\n");
+		goto do_free_irq;
+	}
+
+	return 0;
+
+do_free_irq:
+	free_irq(dev->irq, dev);
+do_unuse_clocks:
+	clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+
+	return r;
+}
+
+static int
+davinci_i2c_remove(struct platform_device *pdev)
+{
+	struct i2c_davinci_device *dev = platform_get_drvdata(pdev);
+	struct resource		*mem;
+
+        clk_disable(dev->clk);
+	clk_put(dev->clk);
+	dev->clk = NULL;
+
+	i2c_davinci_dev.regs->icmdr = 0;
+	free_irq(IRQ_I2C, &i2c_davinci_dev);
+
+	i2c_del_adapter(&dev->adapter);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	return 0;
+}
+
+static struct platform_driver davinci_i2c_driver = {
+	.probe		= davinci_i2c_probe,
+	.remove		= davinci_i2c_remove,
+	.driver		= {
+		.name	= (char *)driver_name,
+	},
+};
+
+/* I2C may be needed to bring up other drivers */
+static int __init
+davinci_i2c_init_driver(void)
+{
+	return platform_driver_register(&davinci_i2c_driver);
+}
+subsys_initcall(davinci_i2c_init_driver);
+
+static void __exit davinci_i2c_exit_driver(void)
+{
+	platform_driver_unregister(&davinci_i2c_driver);
+}
+module_exit(davinci_i2c_exit_driver);
diff --git a/drivers/i2c/busses/i2c-davinci.h b/drivers/i2c/busses/i2c-davinci.h
new file mode 100644
index 0000000..7360077
--- /dev/null
+++ b/drivers/i2c/busses/i2c-davinci.h
@@ -0,0 +1,156 @@
+/*
+ * linux/drivers/i2c/busses/davinci/i2c_davinci.h
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ Modifications:
+ ver. 1.0: Feb 2005, Vinod/Sudhakar
+ -
+ *
+ */
+
+#define DAVINCI_I2C_ICOAR_OADDR_MASK        (0x03FFu)
+#define DAVINCI_I2C_ICIMR_AAS_MASK          (0x0040u)
+#define DAVINCI_I2C_ICIMR_SCD_MASK          (0x0020u)
+#define DAVINCI_I2C_ICIMR_ICXRDY_MASK       (0x0010u)
+#define DAVINCI_I2C_ICIMR_ICRRDY_MASK       (0x0008u)
+#define DAVINCI_I2C_ICIMR_ARDY_MASK         (0x0004u)
+#define DAVINCI_I2C_ICIMR_NACK_MASK         (0x0002u)
+#define DAVINCI_I2C_ICIMR_AL_MASK           (0x0001u)
+#define DAVINCI_I2C_ICSTR_SDIR_MASK         (0x4000u)
+#define DAVINCI_I2C_ICSTR_NACKSNT_MASK      (0x2000u)
+#define DAVINCI_I2C_ICSTR_BB_MASK           (0x1000u)
+#define DAVINCI_I2C_ICSTR_RSFULL_MASK       (0x0800u)
+#define DAVINCI_I2C_ICSTR_XSMT_MASK         (0x0400u)
+#define DAVINCI_I2C_ICSTR_AAS_MASK          (0x0200u)
+#define DAVINCI_I2C_ICSTR_AD0_MASK          (0x0100u)
+#define DAVINCI_I2C_ICSTR_SCD_MASK          (0x0020u)
+#define DAVINCI_I2C_ICSTR_ICXRDY_MASK       (0x0010u)
+#define DAVINCI_I2C_ICSTR_ICRRDY_MASK       (0x0008u)
+#define DAVINCI_I2C_ICSTR_ARDY_MASK         (0x0004u)
+#define DAVINCI_I2C_ICSTR_NACK_MASK         (0x0002u)
+#define DAVINCI_I2C_ICSTR_AL_MASK           (0x0001u)
+#define DAVINCI_I2C_ICCLKL_ICCL_MASK        (0xFFFFu)
+#define DAVINCI_I2C_ICCLKH_ICCH_MASK        (0xFFFFu)
+#define DAVINCI_I2C_ICCNT_ICDC_MASK         (0xFFFFu)
+#define DAVINCI_I2C_ICDRR_D_MASK            (0x00FFu)
+#define DAVINCI_I2C_ICSAR_SADDR_MASK        (0x03FFu)
+#define DAVINCI_I2C_ICDXR_D_MASK            (0x00FFu)
+#define DAVINCI_I2C_ICMDR_NACKMOD_MASK      (0x8000u)
+#define DAVINCI_I2C_ICMDR_FREE_MASK         (0x4000u)
+#define DAVINCI_I2C_ICMDR_STT_MASK          (0x2000u)
+#define DAVINCI_I2C_ICMDR_STP_MASK          (0x0800u)
+#define DAVINCI_I2C_ICMDR_MST_MASK          (0x0400u)
+#define DAVINCI_I2C_ICMDR_TRX_MASK          (0x0200u)
+#define DAVINCI_I2C_ICMDR_XA_MASK           (0x0100u)
+#define DAVINCI_I2C_ICMDR_RM_MASK           (0x0080u)
+#define DAVINCI_I2C_ICMDR_DLB_MASK          (0x0040u)
+#define DAVINCI_I2C_ICMDR_IRS_MASK          (0x0020u)
+#define DAVINCI_I2C_ICMDR_STB_MASK          (0x0010u)
+#define DAVINCI_I2C_ICMDR_FDF_MASK          (0x0008u)
+#define DAVINCI_I2C_ICMDR_BC_MASK           (0x0007u)
+#define DAVINCI_I2C_ICIVR_TESTMD_MASK       (0x0F00u)
+#define DAVINCI_I2C_ICIVR_INTCODE_MASK      (0x0007u)
+
+#define DAVINCI_I2C_ICIVR_INTCODE_NONE      (0x0000u)
+#define DAVINCI_I2C_ICIVR_INTCODE_AL        (0x0001u)
+#define DAVINCI_I2C_ICIVR_INTCODE_NACK      (0x0002u)
+#define DAVINCI_I2C_ICIVR_INTCODE_RAR       (0x0003u)
+#define DAVINCI_I2C_ICIVR_INTCODE_RDR       (0x0004u)
+#define DAVINCI_I2C_ICIVR_INTCODE_TDR       (0x0005u)
+#define DAVINCI_I2C_ICIVR_INTCODE_SCD       (0x0006u)
+#define DAVINCI_I2C_ICIVR_INTCODE_AAS       (0x0007u)
+
+#define DAVINCI_I2C_ICEMDR_BCM_MASK         (0x0001u)
+#define DAVINCI_I2C_ICPSC_IPSC_MASK         (0x00FFu)
+#define DAVINCI_I2C_ICPID1_CLASS_MASK       (0xFF00u)
+#define DAVINCI_I2C_ICPID1_REVISION_MASK    (0x00FFu)
+#define DAVINCI_I2C_ICPID2_TYPE_MASK        (0x00FFu)
+#define DAVINCI_I2C_ICPFUNC_PFUNC_MASK      (0x00000001u)
+#define DAVINCI_I2C_ICPDIR_PDIR1_MASK       (0x00000002u)
+#define DAVINCI_I2C_ICPDIR_PDIR0_MASK       (0x00000001u)
+#define DAVINCI_I2C_ICPDIN_PDIN1_MASK       (0x00000002u)
+#define DAVINCI_I2C_ICPDIN_PDIN0_MASK       (0x00000001u)
+#define DAVINCI_I2C_ICPDOUT_PDOUT1_MASK     (0x00000002u)
+#define DAVINCI_I2C_ICPDOUT_PDOUT0_MASK     (0x00000001u)
+#define DAVINCI_I2C_ICPDSET_PDSET1_MASK     (0x00000002u)
+#define DAVINCI_I2C_ICPDSET_PDSET0_MASK     (0x00000001u)
+#define DAVINCI_I2C_ICPDCLR_PDCLR1_MASK     (0x00000002u)
+#define DAVINCI_I2C_ICPDCLR_PDCLR0_MASK     (0x00000001u)
+
+/**************************************************************************\
+* Register Overlay Structure
+\**************************************************************************/
+typedef struct {
+	u16 icoar;
+	u8 rsvd0[2];
+	u16 icimr;
+	u8 rsvd1[2];
+	u16 icstr;
+	u8 rsvd2[2];
+	u16 icclkl;
+	u8 rsvd3[2];
+	u16 icclkh;
+	u8 rsvd4[2];
+	u16 iccnt;
+	u8 rsvd5[2];
+	u16 icdrr;
+	u8 rsvd6[2];
+	u16 icsar;
+	u8 rsvd7[2];
+	u16 icdxr;
+	u8 rsvd8[2];
+	u16 icmdr;
+	u8 rsvd9[2];
+	u16 icivr;
+	u8 rsvd10[2];
+	u16 icemdr;
+	u8 rsvd11[2];
+	u16 icpsc;
+	u8 rsvd12[2];
+	u16 icpid1;
+	u8 rsvd13[2];
+	u16 icpid2;
+	u8 rsvd14[14];
+	u32 ipcfunc;
+	u32 icpdir;
+	u32 icpdin;
+	u32 icpdout;
+	u32 icpdset;
+	u32 icpdclr;
+} davinci_i2cregs;
+
+/**************************************************************************\
+* Overlay structure typedef definition
+\**************************************************************************/
+typedef volatile davinci_i2cregs *davinci_i2cregsovly;
+
+struct i2c_davinci_device {
+	int cmd_err;
+	struct completion cmd_complete;
+	wait_queue_head_t cmd_wait;
+	u8 *buf;
+	size_t buf_len;
+	davinci_i2cregsovly regs;
+
+	int irq;
+	struct i2c_adapter	adapter;
+	struct clk              *clk;
+	struct device           *dev;
+};
diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index f6b492b..04edab7 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -123,6 +123,11 @@
 	  If you say yes here you get support for the I2C control
 	  interface for Texas Instruments TLV320AIC23 audio codec.
 
+config SENSORS_TLV320AIC33
+	tristate "Texas Instruments TLV320AIC33 Codec"
+	depends on I2C && I2C_DAVINCI
+	select SENSORS_TLV320AIC23
+
 config GPIOEXPANDER_OMAP
 	bool "GPIO Expander PCF8574PWR for OMAP"
 	depends on I2C && (ARCH_OMAP16XX || ARCH_OMAP24XX)
@@ -187,4 +192,10 @@
 	  and other features that are often used in portable devices like
 	  cell phones and PDAs.
 
+config GPIOEXPANDER_DAVINCI
+        bool "GPIO Expander for DaVinci"
+        depends on I2C && ARCH_DAVINCI
+        help
+          If you say yes here you get support for I/O expander calls
+
 endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 116fe15..f1afec2 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -20,6 +20,7 @@
 obj-$(CONFIG_TWL4030_CORE)      += twl4030_core.o
 obj-$(CONFIG_TWL4030_GPIO)	+= twl4030_gpio.o
 obj-$(CONFIG_RTC_X1205_I2C)	+= x1205.o
+obj-$(CONFIG_GPIOEXPANDER_DAVINCI) += gpio_expander_davinci.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/gpio_expander_davinci.c b/drivers/i2c/chips/gpio_expander_davinci.c
new file mode 100644
index 0000000..33b7c8d
--- /dev/null
+++ b/drivers/i2c/chips/gpio_expander_davinci.c
@@ -0,0 +1,142 @@
+/*
+ * drivers/i2c/chips/gpio_expander_davinci.c
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * Copyright (C) 2006 Texas Instruments Inc
+ *
+ * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/errno.h>
+#include <linux/mutex.h>
+
+#include <asm/arch/i2c-client.h>
+
+static DEFINE_MUTEX(expander_lock);
+
+static int davinci_i2c_expander_read(u8 size, u8 * val, u16 addr)
+{
+	struct i2c_adapter *adap;
+	int err;
+	struct i2c_msg msg[1];
+
+        adap = i2c_get_adapter(0);
+        if (!adap)
+		return -ENODEV;
+
+	msg->addr = addr;
+	msg->flags = I2C_M_RD;
+	msg->len = size;
+	msg->buf = val;
+
+	err = i2c_transfer(adap, msg, 1);
+	if (err >= 0)
+		return 0;
+
+	return err;
+}
+
+static int davinci_i2c_expander_write(u8 size, u8 * val, u16 addr)
+{
+	struct i2c_adapter *adap;
+	int err;
+	struct i2c_msg msg[1];
+
+        adap = i2c_get_adapter(0);
+        if (!adap)
+		return -ENODEV;
+
+	msg->addr = addr;
+	msg->flags = 0;
+	msg->len = size;
+	msg->buf = val;
+
+	err = i2c_transfer(adap, msg, 1);
+	if (err >= 0)
+		return 0;
+
+	return err;
+}
+
+int davinci_i2c_expander_op(u16 client_addr, u35_expander_ops pin, u8 val)
+{
+	int err = 0;
+	char cmd[4] = { 4, 6, 0x00, 0x09 };
+	u8 data_to_u35 = 0;
+
+	if (val > 1)
+		return -1;
+
+	mutex_lock(&expander_lock);
+
+	err = davinci_i2c_expander_read(1, &data_to_u35, 0x3A);
+	if (err < 0)
+		return err;
+
+	if (client_addr == 0x3A) {
+		switch (pin) {
+		case USB_DRVVBUS:
+			if (val)
+				data_to_u35 |= val;
+			else
+				data_to_u35 &= (val | 0xFE);
+			break;
+		case VDDIMX_EN:
+			if (val)
+				data_to_u35 |= (val << 1);
+			else
+				data_to_u35 &= (val | 0xFD);
+			break;
+		case VLYNQ_ON:
+			if (val)
+				data_to_u35 |= (val << 2);
+			else
+				data_to_u35 &= (val | 0xFB);
+			break;
+		case CF_RESET:
+			if (val)
+				data_to_u35 |= (val << 3);
+			else
+				data_to_u35 &= (val | 0xF7);
+			break;
+		case WLAN_RESET:
+			if (val)
+				data_to_u35 |= (val << 5);
+			else
+				data_to_u35 &= (val | 0xDF);
+			break;
+		case ATA_SEL:
+			if (val)
+				data_to_u35 |= (val << 6);
+			else
+				data_to_u35 &= (val | 0xBF);
+			break;
+		case CF_SEL:
+			davinci_i2c_expander_write(4, cmd, 0x23);
+			if (val)
+				data_to_u35 |= (val << 7);
+			else
+				data_to_u35 &= (val | 0x7F);
+			break;
+		default:
+			break;
+		}
+	} else {
+		printk("Only IO Expander at address 0x3A is suuported\n");
+		mutex_unlock(&expander_lock);
+		return -EINVAL;
+	}
+
+	err = davinci_i2c_expander_write(1, &data_to_u35, 0x3A);
+
+	mutex_unlock(&expander_lock);
+
+	return err;
+}
+EXPORT_SYMBOL(davinci_i2c_expander_op);
diff --git a/drivers/i2c/chips/tlv320aic23.c b/drivers/i2c/chips/tlv320aic23.c
index a2ec4bc..64946ab 100644
--- a/drivers/i2c/chips/tlv320aic23.c
+++ b/drivers/i2c/chips/tlv320aic23.c
@@ -95,6 +95,18 @@
 	return 0;
 }
 
+#ifdef CONFIG_SENSORS_TLV320AIC33
+int tlv320aic33_write_value(u8 reg, u16 value)
+{
+	static struct i2c_client *client;
+	u8 val = value & 0xff;
+
+	client = new_client;
+
+	return i2c_smbus_write_byte_data(client, reg, val);
+}
+#endif /* CONFIG_SENSORS_TLV320AIC33 */
+
 static int aic23_detect_client(struct i2c_adapter *adapter, int address,
 				     int kind)
 {
@@ -162,6 +174,7 @@
 	.detach_client	= aic23_detach_client,
 };
 
+#ifdef CONFIG_ARCH_OMAP
 /*
  * Configures the McBSP3 which is used to send clock to the AIC23 codec.
  * The input clock rate from DSP is 12MHz.
@@ -193,6 +206,7 @@
 
 	return 0;
 }
+#endif
 
 static void update_volume_left(int volume)
 {
@@ -639,10 +653,12 @@
 		selftest = -ENODEV;
 		return selftest;
 	}
+#ifdef CONFIG_ARCH_OMAP
 	/* FIXME: Do in board-specific file */
 	omap_mcbsp3_aic23_clock_init();
 	if (!aic23_info_l.power_down)
 		aic23_power_up();
+#endif
 	aic23_info_l.initialized = 1;
 	printk("TLV320AIC23 I2C version %s (%s)\n",
 	       TLV320AIC23_VERSION, TLV320AIC23_DATE);
diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
index 4200251..19eee75 100644
--- a/drivers/ide/Kconfig
+++ b/drivers/ide/Kconfig
@@ -944,6 +944,15 @@
 	  normally be on; disable it only if you are running a custom hard
 	  drive subsystem through an expansion card.
 
+config BLK_DEV_DAVINCI
+	tristate "Davinci IDE interface support "
+	depends on ARCH_DAVINCI && DAVINCI_I2C_EXPANDER
+	select BLK_DEV_IDEDMA
+	select BLK_DEV_IDEDMA_PCI
+	help
+	  This is the IDE driver for Davinci platform with Palmchip 3710 IDE
+	  controller
+
 config BLK_DEV_MPC8xx_IDE
 	bool "MPC8xx IDE support"
 	depends on 8xx && IDE=y && BLK_DEV_IDE=y && !PPC_MERGE
diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile
index 75dc696..fda7308 100644
--- a/drivers/ide/Makefile
+++ b/drivers/ide/Makefile
@@ -52,3 +52,4 @@
 obj-$(CONFIG_BLK_DEV_IDE)		+= legacy/ arm/ mips/
 obj-$(CONFIG_BLK_DEV_HD)		+= legacy/
 obj-$(CONFIG_ETRAX_IDE)		+= cris/
+obj-$(CONFIG_BLK_DEV_DAVINCI)		+= davinci/
diff --git a/drivers/ide/davinci/Makefile b/drivers/ide/davinci/Makefile
new file mode 100644
index 0000000..12be3bb
--- /dev/null
+++ b/drivers/ide/davinci/Makefile
@@ -0,0 +1,4 @@
+
+obj-$(CONFIG_BLK_DEV_DAVINCI)       += palm_bk3710.o
+
+EXTRA_CFLAGS	:= -Idrivers/ide
diff --git a/drivers/ide/davinci/palm_bk3710.c b/drivers/ide/davinci/palm_bk3710.c
new file mode 100644
index 0000000..07081e5
--- /dev/null
+++ b/drivers/ide/davinci/palm_bk3710.c
@@ -0,0 +1,622 @@
+/*
+ * linux/drivers/ide/davinci/palm_bk3710.c
+ *
+ * TI DaVinci Palm Chip 3710 IDE driver file
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ Modifications:
+ ver. 1.0: Oct 2005, Swaminathan S
+ -
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/hdreg.h>
+#include <linux/ide.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/i2c-client.h>
+#include "palm_bk3710.h"
+#include "../ide-timing.h"
+
+
+static ide_hwif_t *palm_bk3710_hwif = NULL;
+struct ide_pci_device_s palm_bk3710_dummydata;
+palm_bk3710_ideregs *palm_bk3710_base = NULL;
+long    ide_palm_clk = 0;
+/*
+ *
+ *  Standard (generic) timings for Taskfile modes, from ATA2 specification.
+ *        Some drives may specify a mode, while also specifying a different
+ *        value for cycle_time (from drive identification data).
+ */
+const palm_bk3710_piotiming palm_bk3710_tasktimings[6] = {
+	{290, 600},		/* PIO Mode 0 */
+	{290, 383},		/* PIO Mode 1 */
+	{290, 240},		/* PIO Mode 2 */
+	{80, 180},		/* PIO Mode 3 with IORDY */
+	{70, 120}		/* PIO Mode 4 with IORDY */
+};
+
+/*
+ *
+ *  Standard (generic) timings for PIO modes, from ATA2 specification.
+ *        Some drives may specify a mode, while also specifying a different
+ *        value for cycle_time (from drive identification data).
+ */
+const palm_bk3710_piotiming palm_bk3710_piotimings[6] = {
+	{165, 600},		/* PIO Mode 0 */
+	{125, 383},		/* PIO Mode 1 */
+	{100, 240},		/* PIO Mode 2 */
+	{80, 180},		/* PIO Mode 3 with IORDY */
+	{70, 120}		/* PIO Mode 4 with IORDY */
+};
+
+/*
+ *
+ *  Standard (generic) timings for DMA modes, from ATA2 specification.
+ *        Some drives may specify a mode, while also specifying a different
+ *        value for cycle_time (from drive identification data).
+ */
+const palm_bk3710_dmatiming palm_bk3710_dmatimings[3] = {
+	{215, 215, 480},	/* DMA Mode 0 */
+	{80, 50, 150},		/* DMA Mode 1 */
+	{70, 25, 120}		/* DMA Mode 2 */
+};
+
+/*
+ *
+ *  Standard (generic) timings for UDMA modes, from ATA2 specification.
+ *        Some drives may specify a mode, while also specifying a different
+ *        value for cycle_time (from drive identification data).
+ */
+const palm_bk3710_udmatiming palm_bk3710_udmatimings[7] = {
+        {20, 160, 240},         /* UDMA Mode 0 */
+        {20, 125, 160},         /* UDMA Mode 1 */
+        {20, 100, 120},         /* UDMA Mode 2 */
+        {20, 100, 90},          /* UDMA Mode 3 */
+        {20, 85,  60},          /* UDMA Mode 4 */
+        {20, 85,  40}           /* UDMA Mode 5 */
+};
+
+struct clk *ideclkp = NULL;
+int palm_bk3710_chipinit(void);
+int palm_bk3710_setdmamode(palm_bk3710_ideregs *, unsigned int, unsigned int,
+			   unsigned int);
+u8  palm_bk3710_setpiomode(palm_bk3710_ideregs *, unsigned int, unsigned int, u8);
+
+static void palm_bk3710_tune_drive(ide_drive_t *, u8);
+
+#ifndef CONFIG_DAVINCI_BLK_DEV_CF
+#ifdef  CONFIG_BLK_DEV_IDEDMA
+/**
+ *	palm_bk3710_setudmamode		: Set the device UDMA mode on Palm Chip 3710
+ *
+ *  Handle [IN]                  : IDE Controller info
+ *	Dev [IN]                     : drive to tune
+ *	level [IN]                   : desired level
+ *  int                         : level in UDMA Mode
+ ******************************************************************************/
+int palm_bk3710_setudmamode(palm_bk3710_ideregs * handle, unsigned int dev,
+			    unsigned int level)
+{
+	char is_slave = (dev == 1) ? 1 : 0;
+	char ide_tenv, ide_trp, ide_t0;
+
+	/* DMA Data Setup */
+	ide_t0 = (palm_bk3710_udmatimings[level].cycletime / ide_palm_clk) - 1;
+	ide_tenv = (palm_bk3710_udmatimings[level].envtime / ide_palm_clk) - 1;
+	ide_trp = (palm_bk3710_udmatimings[level].rptime / ide_palm_clk) - 1;
+
+	if (!is_slave) {
+		/* setup master device parameters */
+		/* udmatim Register */
+		palm_bk3710_base->config.udmatim &= 0xFFF0;
+		palm_bk3710_base->config.udmatim |= level;
+		/* udmastb Ultra DMA Access Strobe Width */
+		palm_bk3710_base->config.udmastb &= 0xFF00;
+		palm_bk3710_base->config.udmastb |= ide_t0;
+		/* udmatrp Ultra DMA Ready to Pause Time */
+		palm_bk3710_base->config.udmatrp &= 0xFF00;
+		palm_bk3710_base->config.udmatrp |= ide_trp;
+		/* udmaenv Ultra DMA envelop Time */
+		palm_bk3710_base->config.udmaenv &= 0xFF00;
+		palm_bk3710_base->config.udmaenv |= ide_tenv;
+		/* Enable UDMA for Device 0 */
+		palm_bk3710_base->config.udmactl |= 1;
+	} else {
+		/* setup slave device parameters */
+		/* udmatim Register */
+		palm_bk3710_base->config.udmatim &= 0xFF0F;
+		palm_bk3710_base->config.udmatim |= (level << 4);
+		/* udmastb Ultra DMA Access Strobe Width */
+		palm_bk3710_base->config.udmastb &= 0xFF;
+		palm_bk3710_base->config.udmastb |= (ide_t0 << 8);
+		/* udmatrp Ultra DMA Ready to Pause Time */
+		palm_bk3710_base->config.udmatrp &= 0xFF;
+		palm_bk3710_base->config.udmatrp |= (ide_trp << 8);
+		/* udmaenv Ultra DMA envelop Time */
+		palm_bk3710_base->config.udmaenv &= 0xFF;
+		palm_bk3710_base->config.udmaenv |= (ide_tenv << 8);
+		/* Enable UDMA for Device 0 */
+		palm_bk3710_base->config.udmactl |= (1 << 1);
+	}
+
+	return level;
+}
+
+/**
+ *	palm_bk3710_setdmamode		: Set the device DMA mode on Palm Chip 3710.
+ *
+ *  	Handle [IN]                  : IDE Controller info
+ *	Dev [IN]                     : drive to tune
+ *	level [IN]                   : desired level
+ *  	int                         : level in DMA Mode
+ ******************************************************************************/
+int palm_bk3710_setdmamode(palm_bk3710_ideregs * handle, unsigned int dev,
+			   unsigned int cycletime, unsigned int mode)
+{
+	char is_slave = (dev == 1) ? 1 : 0;
+	char ide_td, ide_tkw, ide_t0;
+
+	if (cycletime < palm_bk3710_dmatimings[mode].cycletime) {
+		cycletime = palm_bk3710_dmatimings[mode].cycletime;
+	}
+
+	/* DMA Data Setup */
+	ide_t0 = cycletime / ide_palm_clk;
+	ide_td = palm_bk3710_dmatimings[mode].activetime / ide_palm_clk;
+	ide_tkw = ide_t0 - ide_td - 1;
+	ide_td -= 1;
+
+	if (!is_slave) {
+		/* setup master device parameters */
+		palm_bk3710_base->config.dmastb &= 0xFF00;
+		palm_bk3710_base->config.dmastb |= ide_td;
+		palm_bk3710_base->config.dmarcvr &= 0xFF00;
+		palm_bk3710_base->config.dmarcvr |= ide_tkw;
+		palm_bk3710_base->dmaengine.bmisp |= 0x20;
+		palm_bk3710_base->config.udmactl &= 0xFF02;
+	} else {
+		/* setup slave device parameters */
+		palm_bk3710_base->config.dmastb &= 0xFF;
+		palm_bk3710_base->config.dmastb |= (ide_td << 8);
+		palm_bk3710_base->config.dmarcvr &= 0xFF;
+		palm_bk3710_base->config.dmarcvr |= (ide_tkw << 8);
+		palm_bk3710_base->dmaengine.bmisp |= 0x40;
+		/* Disable UDMA for Device 1 */
+		palm_bk3710_base->config.udmactl &= 0xFF01;
+	}
+
+	return mode;
+}
+#endif
+#endif
+
+/**
+ *	palm_bk3710_setpiomode		: Set the device PIO mode on Palm Chip 3710.
+ *
+ *  	Handle [IN]                  : IDE Controller info
+ *	Dev [IN]                     : drive to tune
+ *	level [IN]                   : desired level
+ *  	u8                           : level in PIO mode
+ ******************************************************************************/
+u8 palm_bk3710_setpiomode(palm_bk3710_ideregs * handle, unsigned int dev,
+			   unsigned int cycletime, u8 mode)
+{
+	int is_slave = (dev == 1) ? 1 : 0;
+	char ide_t2, ide_t2i, ide_t0;
+
+	if (cycletime < palm_bk3710_piotimings[mode].cycletime) {
+		cycletime = palm_bk3710_piotimings[mode].cycletime;
+	}
+	/* PIO Data Setup */
+	ide_t0 = cycletime / ide_palm_clk;
+	ide_t2 = palm_bk3710_piotimings[mode].activetime / ide_palm_clk;
+	ide_t2i = ide_t0 - ide_t2 - 1;
+	ide_t2 -= 1;
+
+	if (!is_slave) {
+		/* setup master device parameters */
+		palm_bk3710_base->config.datstb &= 0xFF00;
+		palm_bk3710_base->config.datstb |= ide_t2;
+		palm_bk3710_base->config.datrcvr &= 0xFF00;
+		palm_bk3710_base->config.datrcvr |= ide_t2i;
+		/* Disable UDMA for Device 0 */
+	} else {
+		/* setup slave device parameters */
+		palm_bk3710_base->config.datstb &= 0xFF;
+		palm_bk3710_base->config.datstb |= (ide_t2 << 8);
+		palm_bk3710_base->config.datrcvr &= 0xFF;
+		palm_bk3710_base->config.datrcvr |= (ide_t2i << 8);
+		/* Disable UDMA for Device 1 */
+	}
+
+	/* TASKFILE Setup */
+	ide_t2 = palm_bk3710_tasktimings[mode].activetime / ide_palm_clk;
+	ide_t2i = ide_t0 - ide_t2 - 1;
+	ide_t2 -= 1;
+
+	if (!is_slave) {
+		/* setup master device parameters */
+		palm_bk3710_base->config.regstb &= 0xFF00;
+		palm_bk3710_base->config.regstb |= ide_t2;
+		palm_bk3710_base->config.regrcvr &= 0xFF00;
+		palm_bk3710_base->config.regrcvr |= ide_t2i;
+	} else {
+		/* setup slave device parameters */
+		palm_bk3710_base->config.regstb &= 0xFF;
+		palm_bk3710_base->config.regstb |= (ide_t2 << 8);
+		palm_bk3710_base->config.regrcvr &= 0xFF;
+		palm_bk3710_base->config.regrcvr |= (ide_t2i << 8);
+	}
+
+	return mode;
+}
+
+#ifndef CONFIG_DAVINCI_BLK_DEV_CF
+#ifdef  CONFIG_BLK_DEV_IDEDMA
+/**
+ *	palm_bk3710_hostdma	-
+ *	@drive: IDE drive to tune
+ *	@xferspeed: speed to configure
+ *
+ *	Set a Palm Chip 3710 interface channel to the desired speeds. This involves
+ *	requires the right timing data into the 3710 timing override registers.
+ */
+
+static int palm_bk3710_hostdma(ide_drive_t * drive, u8 xferspeed)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	u8 speed = (XFER_UDMA_4 < xferspeed) ? XFER_UDMA_4 : xferspeed;
+	int is_slave = (&hwif->drives[1] == drive);
+	char ide_cycle;
+	struct hd_driveid *id = drive->id;
+	int nspeed = -1;
+
+	switch (speed) {
+	case XFER_UDMA_4:
+		nspeed = 2;
+		break;
+	case XFER_UDMA_3:
+		nspeed = 3;
+		break;
+	case XFER_UDMA_2:
+		nspeed = 4;
+		break;
+	case XFER_UDMA_1:
+		nspeed = 5;
+		break;
+	case XFER_UDMA_0:
+		nspeed = 6;
+		break;
+	case XFER_MW_DMA_2:
+		nspeed = 8;
+		break;
+	case XFER_MW_DMA_1:
+		nspeed = 9;
+		break;
+	case XFER_MW_DMA_0:
+		nspeed = 10;
+		break;
+	default:
+		return -1;
+	}
+
+	if (nspeed != -1) {
+		ide_cycle = (ide_timing[nspeed].cycle < id->eide_dma_min) ?
+		    id->eide_dma_min : ide_timing[nspeed].cycle;
+		if ((speed <= XFER_UDMA_4) && (speed >= XFER_UDMA_0)) {
+			palm_bk3710_setudmamode(NULL, is_slave, 6 - nspeed);
+		} else {
+			palm_bk3710_setdmamode(NULL, is_slave, ide_cycle,
+					       10 - nspeed);
+		}
+
+		return (ide_config_drive_speed(drive, speed));
+	} else {
+		return 0;
+	}
+}
+
+/**
+ *	palm_bk3710_drivedma	-	configure drive for DMA
+ *	@drive: IDE drive to configure
+ *
+ *	Set up a Palm Chip 3710 interface channel for the best available speed.
+ *	We prefer UDMA if it is available and then MWDMA. If DMA is
+ *	not available we switch to PIO and return 0.
+ */
+
+static inline int palm_bk3710_drivedma(ide_drive_t * pDrive)
+{
+	u8 speed = ide_rate_filter(pDrive, 2);	/* We have a 76.5 MHz clock hence only UDMA66 is possible */
+
+	/* If no DMA/single word DMA was available or the chipset has DMA bugs
+	   then disable DMA and use PIO */
+	if (!speed) {
+		palm_bk3710_tune_drive(pDrive, 255);
+	} else {
+		palm_bk3710_hostdma(pDrive, speed);
+		ide_tune_dma(pDrive);
+	}
+
+	return 0;
+}
+
+/**
+ *	palm_bk3710_checkdma	-	set up an IDE device
+ *	@drive: IDE drive to configure
+ *
+ *	Set up the Palm Chip 3710 interface for the best available speed on this
+ *	interface, preferring DMA to PIO.
+ */
+
+static int palm_bk3710_checkdma(ide_drive_t * drive)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+	struct hd_driveid *id = drive->id;
+
+	drive->init_speed = 0;
+
+	if ((id->capability & 1) && drive->autodma) {
+		if (id->field_valid & 4) {
+			if (id->dma_ultra & hwif->ultra_mask) {
+				/* Force if Capable UltraDMA */
+				if ((id->field_valid & 2) &&
+				    (!palm_bk3710_drivedma(drive)))
+					goto try_dma_modes;
+			}
+		} else if (id->field_valid & 2) {
+		      try_dma_modes:
+			if (id->dma_mword & hwif->mwdma_mask) {
+				/* Force if Capable regular DMA modes */
+				if (!palm_bk3710_drivedma(drive))
+					goto no_dma_set;
+			}
+		} else {
+			goto fast_ata_pio;
+		}
+		return hwif->ide_dma_on(drive);
+	} else if ((id->capability & 8) || (id->field_valid & 2)) {
+	      fast_ata_pio:
+	      no_dma_set:
+		hwif->tuneproc(drive, 255);
+		hwif->dma_off_quietly(drive);
+	}
+
+	return 0;
+}
+#endif
+#endif
+
+/**
+ *	palm_bk3710_tune_drive		-	tune a drive attached to a Palm Chip 3710
+ *	@drive: drive to tune
+ *	@pio: desired PIO mode
+ *
+ *	Set the interface and device PIO mode
+ *
+ */
+static void palm_bk3710_tune_drive(ide_drive_t * drive, u8 pio)
+{
+	ide_hwif_t *hwif = HWIF(drive);
+        unsigned int cycle_time;
+	int is_slave = (&hwif->drives[1] == drive);
+
+	/* Get the best PIO Mode supported by the drive
+	 * Obtain the drive PIO data for tuning the Palm Chip registers
+	 */
+	pio = ide_get_best_pio_mode(drive, pio, 5);
+        cycle_time = ide_pio_cycle_time(drive, pio);
+	/* Check for IORDY here */
+	if (cycle_time < ide_pio_timings[pio].cycle_time) {
+		cycle_time = ide_pio_timings[pio].cycle_time;
+	}
+	palm_bk3710_setpiomode(NULL, is_slave, cycle_time, pio);
+}
+
+/**
+ *	palm_bk3710_init		-	Init Palm Chip 3710
+ *
+ *	Initialize the Palm Chip 3710 IDE controller to default conditions.
+ *
+ */
+int palm_bk3710_init(void)
+{
+	int ret = 0;
+	hw_regs_t ide_ctlr_info;
+	int index = 0;
+	int pribase = IO_ADDRESS(IDE_PALM_REG_MMAP_BASE) +
+	    		IDE_PALM_ATA_PRI_REG_OFFSET;
+	struct clk *clkp;
+
+	clkp = clk_get (NULL, "IDECLK");
+	if (!IS_ERR(clkp))
+	{
+		ideclkp = clkp;
+		clk_enable (ideclkp);
+		ide_palm_clk = clk_get_rate(ideclkp)/100000;
+		ide_palm_clk = (10000/ide_palm_clk) + 1;
+		/* ATA_SEL is 1 -> Disable 0 -> Enable
+		 * CF_SEL  is 1 -> Disable 0 -> Enable
+		 *
+		 * Ensure both are not Enabled.
+		 */
+#ifdef CONFIG_DAVINCI_BLK_DEV_CF
+		davinci_i2c_expander_op (0x3A, ATA_SEL, 1);
+		davinci_i2c_expander_op (0x3A, CF_RESET, 1);
+		davinci_i2c_expander_op (0x3A, CF_SEL, 0);
+#else
+		davinci_i2c_expander_op (0x3A, CF_SEL, 1);
+		davinci_i2c_expander_op (0x3A, ATA_SEL, 0);
+#endif
+		/* Register the IDE interface with Linux ATA Interface */
+		memset(&ide_ctlr_info, 0, sizeof(ide_ctlr_info));
+
+		palm_bk3710_base =
+		    (palm_bk3710_ideregs *) IO_ADDRESS(IDE_PALM_REG_MMAP_BASE);
+		/* Configure the Palm Chip controller */
+		palm_bk3710_chipinit();
+
+		for (index = 0; index < IDE_NR_PORTS - 2; index++) {
+			ide_ctlr_info.io_ports[index] = pribase + index;
+		}
+		ide_ctlr_info.io_ports[IDE_CONTROL_OFFSET] =
+		    IO_ADDRESS(IDE_PALM_REG_MMAP_BASE)
+		    + IDE_PALM_ATA_PRI_CTL_OFFSET;
+		ide_ctlr_info.irq = IRQ_IDE;
+		ide_ctlr_info.chipset = ide_palm3710;
+		ide_ctlr_info.ack_intr = NULL;
+		if (ide_register_hw(&ide_ctlr_info, 0, &palm_bk3710_hwif) < 0) {
+			printk("Palm Chip BK3710 IDE Register Fail\n");
+			return -1;
+		}
+
+		palm_bk3710_hwif->tuneproc = &palm_bk3710_tune_drive;
+
+		palm_bk3710_hwif->noprobe = 0;
+#ifndef CONFIG_DAVINCI_BLK_DEV_CF
+#ifdef  CONFIG_BLK_DEV_IDEDMA
+                palm_bk3710_hwif->speedproc = &palm_bk3710_hostdma;
+		/* Just put this for using the ide-dma.c init code */
+		palm_bk3710_dummydata.extra = 0;
+		palm_bk3710_hwif->cds = &palm_bk3710_dummydata;
+
+		/* Setup up the memory map base for this instance of hwif */
+		palm_bk3710_hwif->mmio = 0;
+		palm_bk3710_hwif->ide_dma_check = palm_bk3710_checkdma;
+		palm_bk3710_hwif->ultra_mask = 0x1f;	/* Ultra DMA Mode 4 Max
+						 (input clk 99MHz) */
+		palm_bk3710_hwif->mwdma_mask = 0x7;
+		palm_bk3710_hwif->swdma_mask = 0;
+		palm_bk3710_hwif->dma_command =
+		    IO_ADDRESS(IDE_PALM_REG_MMAP_BASE);
+		palm_bk3710_hwif->dma_status =
+		    IO_ADDRESS(IDE_PALM_REG_MMAP_BASE) + 2;
+		palm_bk3710_hwif->dma_prdtable =
+		    IO_ADDRESS(IDE_PALM_REG_MMAP_BASE) + 4;
+		palm_bk3710_hwif->drives[0].autodma = 1;
+		palm_bk3710_hwif->drives[1].autodma = 1;
+		ide_setup_dma(palm_bk3710_hwif,
+			      IO_ADDRESS(IDE_PALM_REG_MMAP_BASE), 8);
+		palm_bk3710_checkdma (&palm_bk3710_hwif->drives[0]);
+		palm_bk3710_checkdma (&palm_bk3710_hwif->drives[1]);
+#endif
+#endif
+		ret = 0;
+	} else {
+		ret = -ENODEV;
+	}
+
+	return ret;
+}
+
+/*
+ *
+ * palm_bk3710_chipinit ()  : Configures the Palm Chip Controller in the
+ *                            desired default operating mode
+ *
+ ******************************************************************************/
+int palm_bk3710_chipinit(void)
+{
+	/* enable the reset_en of ATA controller so that when ata signals are brought
+	 * out , by writing into device config. at that time por_n signal should not be
+	 * 'Z' and have a stable value.
+	 */
+	palm_bk3710_base->config.miscctl = 0x0300;
+
+	/* wait for some time and deassert the reset of ATA Device. */
+	mdelay (100);
+
+	/* Deassert the Reset */
+	palm_bk3710_base->config.miscctl = 0x0200;
+
+	/* Program the IDETIMP Register Value based on the following assumptions
+	 *
+	 * (ATA_IDETIMP_IDEEN      ,ENABLE )  |
+	 * (ATA_IDETIMP_SLVTIMEN   , DISABLE) |
+	 * (ATA_IDETIMP_RDYSMPL    , 70NS) |
+	 * (ATA_IDETIMP_RDYRCVRY   , 50NS) |
+	 * (ATA_IDETIMP_DMAFTIM1   , PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST1   , DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN1    , DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM1   , DISABLE) |
+	 * (ATA_IDETIMP_DMAFTIM0   , PIOCOMP) |
+	 * (ATA_IDETIMP_PREPOST0   , DISABLE) |
+	 * (ATA_IDETIMP_RDYSEN0    , DISABLE) |
+	 * (ATA_IDETIMP_PIOFTIM0   , DISABLE)
+	 */
+
+	palm_bk3710_base->config.idetimp = 0xb388;
+
+	/* Configure  SIDETIM  Register
+	 * (ATA_SIDETIM_RDYSMPS1     ,120NS ) |
+	 * (ATA_SIDETIM_RDYRCYS1     ,120NS )
+	 */
+	palm_bk3710_base->config.sidetim = 0;
+
+	/* UDMACTL Ultra-ATA DMA Control
+	 * (ATA_UDMACTL_UDMAP1      , 0 ) |
+	 * (ATA_UDMACTL_UDMAP0      , 0 )
+	 *
+	 */
+	palm_bk3710_base->config.udmactl = 0;
+
+	/* MISCCTL Miscellaneous Conrol Register
+	 * (ATA_MISCCTL_RSTMODEP    , 1) |
+	 * (ATA_MISCCTL_RESETP        , 0) |
+	 * (ATA_MISCCTL_TIMORIDE      , 1)
+	 */
+	palm_bk3710_base->config.miscctl = 0x201;
+
+	/* IORDYTMP IORDY Timer for Primary Register
+	 * (ATA_IORDYTMP_IORDYTMP     , 0xffff  )
+	 */
+
+	palm_bk3710_base->config.iordytmp = 0xffff;
+
+	/*Configure BMISP Register
+	 * (ATA_BMISP_DMAEN1        , DISABLE  ) |
+	 * (ATA_BMISP_DMAEN0     , DISABLE  ) |
+	 * (ATA_BMISP_IORDYINT   , CLEAR) |
+	 * (ATA_BMISP_INTRSTAT   , CLEAR) |
+	 * (ATA_BMISP_DMAERROR   , CLEAR)
+	 */
+
+	palm_bk3710_base->dmaengine.bmisp = 0;
+
+	palm_bk3710_setpiomode(NULL, 0, 0, 0);
+	palm_bk3710_setpiomode(NULL, 1, 0, 0);
+
+	return 1;
+}
+
+
+module_init(palm_bk3710_init);
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/ide/davinci/palm_bk3710.h b/drivers/ide/davinci/palm_bk3710.h
new file mode 100644
index 0000000..995c45b
--- /dev/null
+++ b/drivers/ide/davinci/palm_bk3710.h
@@ -0,0 +1,131 @@
+/*
+ *  linux/drivers/ide/davinci/palm_bk3710.h
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *      DAVINCI Virtual memory definitions
+ *
+ *  Copyright (C) 2006 Texas Instruments.
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ *
+ */
+
+#ifndef PALM_BK3710_H
+#define PALM_BK3710_H
+
+#include <asm/arch/hardware.h>
+
+/*
+ *
+ *  PalmChip 3710 IDE Controller Driver Definitions
+ *
+ */
+
+/*
+ *
+ *  PalmChip 3710 IDE Controller config Definitions
+ *
+ */
+
+#define IDE_PALM_FREQ           76	/* Palm Chip operating freq (MHZ) */
+#define IDE_PALM_CLK            ((3000000/clk_get_rate (ideclkp)) - 1)	/* In ns */
+#define IDE_PALM_REG_MMAP_BASE  DAVINCI_CFC_ATA_BASE /* Register Memory map address */
+#define IDE_PALM_ATA_PRI_REG_OFFSET 0x1F0  /**< Offset of the primary interface
+registers */
+#define IDE_PALM_ATA_PRI_CTL_OFFSET 0x3F6  /**< Primary Control Offset */
+
+/*
+ *
+ *  PalmChip 3710 IDE Controller PIO cycle timing structure Definition
+ */
+typedef struct {
+	unsigned int activetime;	/* Active Time  */
+	unsigned int cycletime;	/* Cycle Time   */
+} palm_bk3710_piotiming;
+
+/*
+ *
+ * PalmChip 3710 IDE Controller DMA cycle timing structure Definition
+ */
+typedef struct {
+	unsigned int activetime;	/* Active Time     */
+	unsigned int recoverytime;	/* Recovery Time   */
+	unsigned int cycletime;	/* Cycle Time      */
+} palm_bk3710_dmatiming;
+
+/*
+ *
+ * PalmChip 3710 IDE Controller UDMA timing structure Definition
+ */
+typedef struct {
+	unsigned int envtime;	/* Envelope Time        */
+	unsigned int rptime;	/* Ready to pause time  */
+	unsigned int cycletime;	/* Cycle Time           */
+} palm_bk3710_udmatiming;
+
+/**************************************************************************\
+* Register Overlay Structure for DmaEngine
+\**************************************************************************/
+typedef struct {
+	unsigned short bmpcp;
+	unsigned short bmisp;
+	unsigned int bmidtp;
+	unsigned short bmics;
+	unsigned short bmiss;
+	unsigned int bmidtps;
+} palm_bk3710_dmaengineregs;
+
+/**************************************************************************\
+* Register Overlay Structure for Config
+\**************************************************************************/
+typedef struct {
+	unsigned short idetimp __attribute__ ((packed));
+	unsigned short idetims __attribute__ ((packed));
+	unsigned char sidetim;
+	unsigned short slewctl __attribute__ ((packed));
+	unsigned char idestatus;
+	unsigned short udmactl __attribute__ ((packed));
+	unsigned short udmatim __attribute__ ((packed));
+	unsigned char rsvd0[4];
+	unsigned int miscctl __attribute__ ((packed));
+	unsigned int regstb __attribute__ ((packed));
+	unsigned int regrcvr __attribute__ ((packed));
+	unsigned int datstb __attribute__ ((packed));
+	unsigned int datrcvr __attribute__ ((packed));
+	unsigned int dmastb __attribute__ ((packed));
+	unsigned int dmarcvr __attribute__ ((packed));
+	unsigned int udmastb __attribute__ ((packed));
+	unsigned int udmatrp __attribute__ ((packed));
+	unsigned int udmaenv __attribute__ ((packed));
+	unsigned int iordytmp __attribute__ ((packed));
+	unsigned int iordytms __attribute__ ((packed));
+} palm_bk3710_ideconfigregs;
+
+/**************************************************************************\
+* Register Overlay Structure
+\**************************************************************************/
+typedef struct {
+	palm_bk3710_dmaengineregs dmaengine;
+	unsigned char rsvd0[48];
+	palm_bk3710_ideconfigregs config;
+} palm_bk3710_ideregs;
+
+#endif				/* DDC_BK3710_H */
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index fc1d8ae..278d713 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -69,6 +69,7 @@
 		case ide_au1xxx:	name = "au1xxx";	break;
 		case ide_etrax100:	name = "etrax100";	break;
 		case ide_acorn:		name = "acorn";		break;
+		case ide_palm3710:	name = "palm3710";	break;
 		default:		name = "(unknown)";	break;
 	}
 	len = sprintf(page, "%s\n", name);
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
index c374a9b..172df23 100644
--- a/drivers/media/video/Kconfig
+++ b/drivers/media/video/Kconfig
@@ -372,6 +372,25 @@
 	  Say Y here if you want to test video apps or debug V4L devices.
 	  In doubt, say N.
 
+config VIDEO_TVP5146
+	tristate "TVP5146 video decoder"
+	depends on I2C && ARCH_DAVINCI
+	help
+	  Support for I2C bus based TVP5146 configuration.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tvp5146.
+
+config VIDEO_DAVINCI
+	tristate "Davinci Video Capture"
+	depends on VIDEO_DEV && VIDEO_TVP5146 && ARCH_DAVINCI
+	select VIDEO_BUF
+	help
+	  Support for Davinci based frame grabber through CCDC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vpfe.
+
 source "drivers/media/video/bt8xx/Kconfig"
 
 config VIDEO_SAA6588
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
index cbf9812..cabb25f 100644
--- a/drivers/media/video/Makefile
+++ b/drivers/media/video/Makefile
@@ -11,6 +11,8 @@
 
 msp3400-objs	:=	msp3400-driver.o msp3400-kthreads.o
 
+davinci-vpfe-objs   :=  ccdc_davinci.o davinci_vpfe.o
+
 obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o \
 			   v4l2-int-device.o
 
@@ -120,6 +122,9 @@
 obj-$(CONFIG_USB_VICAM)         += usbvideo/
 obj-$(CONFIG_USB_QUICKCAM_MESSENGER)	+= usbvideo/
 
+obj-$(CONFIG_VIDEO_DAVINCI)     += davinci-vpfe.o
+obj-$(CONFIG_VIDEO_TVP5146)     += tvp5146.o
+
 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
 
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/video/ccdc_davinci.c b/drivers/media/video/ccdc_davinci.c
new file mode 100644
index 0000000..d3cd333
--- /dev/null
+++ b/drivers/media/video/ccdc_davinci.c
@@ -0,0 +1,124 @@
+/*
+ *
+ *
+ * Copyright (C) 2006 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* ccdc_davinci.c */
+
+#include <media/ccdc_davinci.h>
+#define debug_print(x...)	//printk(x)
+void ccdc_reset()
+{
+	int i;
+	/* disable CCDC */
+	ccdc_enable(0);
+	/* set all registers to default value */
+	for (i = 0; i <= 0x94; i += 4) {
+		regw(0, i);
+	}
+	regw(0, PCR);
+	regw(0, SYN_MODE);
+	regw(0, HD_VD_WID);
+	regw(0, PIX_LINES);
+	regw(0, HORZ_INFO);
+	regw(0, VERT_START);
+	regw(0, VERT_LINES);
+	regw(0xffff00ff, CULLING);
+	regw(0, HSIZE_OFF);
+	regw(0, SDOFST);
+	regw(0, SDR_ADDR);
+	regw(0, VDINT);
+	regw(0, REC656IF);
+	regw(0, CCDCFG);
+	regw(0, FMTCFG);
+	regw(0, VP_OUT);
+}
+
+void ccdc_setwin(ccdc_params_ycbcr * params)
+{
+	int horz_start, horz_nr_pixels;
+	int vert_start, vert_nr_lines;
+
+	/* configure horizonal and vertical starts and sizes */
+	horz_start = params->win.left << 1;
+	horz_nr_pixels = (params->win.width <<1) - 1;
+	regw((horz_start << 16) | horz_nr_pixels, HORZ_INFO);
+
+	vert_start = params->win.top;
+
+	if (params->frm_fmt == CCDC_FRMFMT_INTERLACED) {
+		vert_nr_lines = (params->win.height >> 1) - 1;
+		vert_start >>= 1;
+	} else {
+		vert_nr_lines = params->win.height - 1;
+	}
+	regw((vert_start << 16) | vert_start, VERT_START);
+	regw(vert_nr_lines, VERT_LINES);
+}
+
+void ccdc_config_ycbcr(ccdc_params_ycbcr * params)
+{
+	u32 syn_mode;
+
+	/* first reset the CCDC                                          */
+	/* all registers have default values after reset                 */
+	/* This is important since we assume default values to be set in */
+	/* a lot of registers that we didn't touch                       */
+	ccdc_reset();
+
+	/* configure pixel format */
+	syn_mode = (params->pix_fmt & 0x3) << 12;
+
+	/* configure video frame format */
+	syn_mode |= (params->frm_fmt & 0x1) << 7;
+
+	/* setup BT.656 sync mode */
+	if (params->bt656_enable) {
+		regw(3, REC656IF);
+
+		/* configure the FID, VD, HD pin polarity */
+		/* fld,hd pol positive, vd negative, 8-bit pack mode */
+		syn_mode |= 0x00000F04;
+	} else {/* y/c external sync mode */
+		syn_mode |= ((params->fid_pol & 0x1) << 4);
+		syn_mode |= ((params->hd_pol & 0x1) << 3);
+		syn_mode |= ((params->vd_pol & 0x1) << 2);
+	}
+
+	/* configure video window */
+	ccdc_setwin(params);
+
+	/* configure the order of y cb cr in SD-RAM */
+	regw((params->pix_order << 11) | 0x8000, CCDCFG);
+
+	/* configure the horizontal line offset */
+	/* this is done by rounding up width to a multiple of 16 pixels */
+	/* and multiply by two to account for y:cb:cr 4:2:2 data */
+	regw(((params->win.width * 2) + 31) & 0xffffffe0, HSIZE_OFF);
+
+	/* configure the memory line offset */
+	if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) {
+		/* two fields are interleaved in memory */
+		regw(0x00000249, SDOFST);
+	}
+	/* enable output to SDRAM */
+	syn_mode |= (0x1 << 17);
+	/* enable internal timing generator */
+	syn_mode |= (0x1 << 16);
+
+	regw(syn_mode, SYN_MODE);
+}
diff --git a/drivers/media/video/davinci_vpfe.c b/drivers/media/video/davinci_vpfe.c
new file mode 100644
index 0000000..1128eb5
--- /dev/null
+++ b/drivers/media/video/davinci_vpfe.c
@@ -0,0 +1,1136 @@
+/*
+ *
+ *
+ * Copyright (C) 2006 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* davinci_vpfe.c */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/kdev_t.h>
+#include <linux/string.h>
+#include <linux/videodev.h>
+#include <linux/wait.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <asm/page.h>
+#include <asm/io.h>
+#include <asm/dma-mapping.h>
+
+#include <media/davinci_vpfe.h>
+
+#define debug_print(x...)	//printk(x)
+
+MODULE_LICENSE("GPL");
+
+static struct v4l2_rect ntsc_bounds = VPFE_WIN_NTSC;
+static struct v4l2_rect pal_bounds = VPFE_WIN_PAL;
+static struct v4l2_fract ntsc_aspect = VPFE_PIXELASPECT_NTSC;
+static struct v4l2_fract pal_aspect = VPFE_PIXELASPECT_PAL;
+static struct v4l2_rect ntscsp_bounds = VPFE_WIN_NTSC_SP;
+static struct v4l2_rect palsp_bounds = VPFE_WIN_PAL_SP;
+static struct v4l2_fract sp_aspect = VPFE_PIXELASPECT_NTSC_SP;
+
+static vpfe_obj vpfe_device = {	/* the default format is NTSC */
+	.usrs = 0,
+	.io_usrs = 0,
+	.std = VPFE_STD_AUTO,
+	.vwin = VPFE_WIN_PAL,
+	.bounds = VPFE_WIN_PAL,
+	.pixelaspect = VPFE_PIXELASPECT_NTSC,
+	.pixelfmt = V4L2_PIX_FMT_UYVY,
+	.field = V4L2_FIELD_INTERLACED,
+	.numbuffers = VPFE_DEFNUM_FBUFS,
+	.ccdc_params = {
+		.pix_fmt = CCDC_PIXFMT_YCBCR_8BIT,
+		.frm_fmt = CCDC_FRMFMT_INTERLACED,
+		.win = VPFE_WIN_PAL,
+		.fid_pol = CCDC_PINPOL_POSITIVE,
+		.vd_pol = CCDC_PINPOL_POSITIVE,
+		.hd_pol = CCDC_PINPOL_POSITIVE,
+		.bt656_enable = TRUE,
+		.pix_order = CCDC_PIXORDER_CBYCRY,
+		.buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED
+	},
+	.tvp5146_params = {
+		.mode = TVP5146_MODE_AUTO,
+		.amuxmode = TVP5146_AMUX_COMPOSITE,
+		.enablebt656sync = TRUE
+	},
+        .irqlock = SPIN_LOCK_UNLOCKED
+};
+
+struct v4l2_capability vpfe_drvcap = {
+	.driver = "vpfe driver",
+	.card = "DaVinci EVM",
+	.bus_info = "Platform",
+	.version = VPFE_VERSION_CODE,
+	.capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING
+};
+
+static int sense_std(v4l2_std_id* std_id)
+{
+	v4l2_std_id id = 0;
+	tvp5146_mode mode;
+	int ret;
+	ret = tvp5146_ctrl(TVP5146_GET_STD, &mode);
+	if(ret < 0)
+		return ret;
+	switch (mode & 0x7) {
+	case TVP5146_MODE_NTSC:
+		id = V4L2_STD_NTSC;
+		break;
+	case TVP5146_MODE_PAL:
+		id = V4L2_STD_PAL;
+		break;
+	case TVP5146_MODE_PAL_M:
+		id = V4L2_STD_PAL_M;
+		break;
+	case TVP5146_MODE_PAL_CN:
+		id = V4L2_STD_PAL_N;
+		break;
+	case TVP5146_MODE_SECAM:
+		id = V4L2_STD_SECAM;
+		break;
+	case TVP5146_MODE_PAL_60:
+		id = V4L2_STD_PAL_60;
+		break;
+	}
+	if (mode & 0x8) {	/* square pixel mode */
+		id <<= 32;
+	}
+	if (mode == TVP5146_MODE_AUTO) {
+		id = VPFE_STD_AUTO;	/* auto-detection for all other modes */
+	} else if (mode == TVP5146_MODE_AUTO_SQP) {
+		id = VPFE_STD_AUTO_SQP;
+	}
+	if(id == 0)
+		return -EINVAL;
+	*std_id =  id;
+	return 0;
+}
+
+static irqreturn_t vpfe_isr(int irq, void *dev_id)
+{
+	vpfe_obj *vpfe = &vpfe_device;
+	int fid;
+
+	/* check which field we are in hardware */
+	fid = ccdc_getfid();
+	vpfe->field_id ^= 1;	/* switch the software maintained field id */
+	debug_print(KERN_INFO "field id = %x:%x.\n", fid, vpfe->field_id);
+	if (fid == vpfe->field_id) {	/* we are in-sync here, continue */
+		if (fid == 0) {
+			/*  One frame is just being captured. If the next frame
+			is available, release the current frame and move on */
+			if (vpfe->curFrm != vpfe->nextFrm) {
+				vpfe->curFrm->state = STATE_DONE;
+				wake_up_interruptible(&vpfe->curFrm->done);
+				vpfe->curFrm = vpfe->nextFrm;
+			}
+			/* based on whether the two fields are stored interleavely      */
+			/* or separately in memory, reconfigure the CCDC memory address */
+			if (vpfe->field == V4L2_FIELD_SEQ_TB) {
+				u32 addr =
+				    vpfe->curFrm->boff + vpfe->field_offset;
+				ccdc_setfbaddr((unsigned long)addr);
+			}
+	} else if (fid == 1) {
+			/* if one field is just being captured */
+			/* configure the next frame */
+			/* get the next frame from the empty queue */
+			/* if no frame is available, hold on to the current buffer */
+			if (!list_empty(&vpfe->dma_queue)
+			    && vpfe->curFrm == vpfe->nextFrm) {
+				vpfe->nextFrm = list_entry(vpfe->dma_queue.next,
+					struct videobuf_buffer, queue);
+				list_del(&vpfe->nextFrm->queue);
+				vpfe->nextFrm->state = STATE_ACTIVE;
+				ccdc_setfbaddr(
+					(unsigned long)vpfe->nextFrm->boff);
+			}
+			if (vpfe->mode_changed) {
+				ccdc_setwin(&vpfe->ccdc_params);
+				/* update the field offset */
+				vpfe->field_offset =
+				    (vpfe->vwin.height - 2) * vpfe->vwin.width;
+				vpfe->mode_changed = FALSE;
+			}
+		}
+	} else if (fid == 0) {
+		/* recover from any hardware out-of-sync due to */
+		/* possible switch of video source              */
+		/* for fid == 0, sync up the two fids           */
+		/* for fid == 1, no action, one bad frame will  */
+		/* go out, but it is not a big deal             */
+		vpfe->field_id = fid;
+	}
+	debug_print(KERN_INFO "interrupt returned.\n");
+	return IRQ_RETVAL(1);
+}
+
+/* this is the callback function called from videobuf_qbuf() function */
+/* the buffer is prepared and queued into the dma queue */
+static int buffer_prepare(struct videobuf_queue *q,
+			  struct videobuf_buffer *vb,
+			  enum v4l2_field field)
+{
+	vpfe_obj *vpfe = &vpfe_device;
+
+
+	if (vb->state == STATE_NEEDS_INIT) {
+		vb->width  = vpfe->vwin.width;
+		vb->height = vpfe->vwin.height;
+		vb->size   = VPFE_MAX_FBUF_SIZE;
+		vb->field  = field;
+	}
+	vb->state = STATE_PREPARED;
+
+	return 0;
+
+}
+static void
+buffer_config(struct videobuf_queue *q, unsigned int count)
+{
+	vpfe_obj *vpfe = &vpfe_device;
+	int i;
+	for(i = 0; i < count; i++) {
+		q->bufs[i]->boff = virt_to_phys(vpfe->fbuffers[i]);
+		debug_print(KERN_INFO "buffer address: %x\n", q->bufs[i]->boff);
+	}
+}
+
+static int
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
+{
+	vpfe_obj *vpfe = &vpfe_device;
+	int i;
+	*size = VPFE_MAX_FBUF_SIZE;
+
+
+	for (i = VPFE_DEFNUM_FBUFS; i < *count; i++) {
+		u32 size = PAGE_SIZE << VPFE_MAX_FBUF_ORDER;
+		void *mem = (void *)__get_free_pages(GFP_KERNEL |GFP_DMA,
+						     VPFE_MAX_FBUF_ORDER);
+		if (mem) {
+			unsigned long adr = (unsigned long)mem;
+			while (size > 0) {
+				/* make sure the frame buffers are never
+				   swapped out of memory */
+				SetPageReserved(virt_to_page(adr));
+				adr += PAGE_SIZE;
+				size -= PAGE_SIZE;
+			}
+			vpfe->fbuffers[i] = mem;
+		} else {
+			break;
+		}
+	}
+	*count = vpfe->numbuffers = i;
+
+	return 0;
+}
+
+static void buffer_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	vpfe_obj *vpfe = &vpfe_device;
+        /* add the buffer to the DMA queue */
+	list_add_tail(&vb->queue, &vpfe->dma_queue);
+	vb->state = STATE_QUEUED;
+}
+
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+	/* free the buffer if it is not one of the 3 allocated at initializaiton time */
+	if(vb->i < vpfe_device.numbuffers
+	 && vb->i >= VPFE_DEFNUM_FBUFS
+	 && vpfe_device.fbuffers[vb->i]){
+		free_pages((unsigned long)vpfe_device.fbuffers[vb->i],
+			   VPFE_MAX_FBUF_ORDER);
+		vpfe_device.fbuffers[vb->i] = NULL;
+	}
+}
+
+
+static struct videobuf_queue_ops video_qops = {
+	.buf_setup    = buffer_setup,
+	.buf_prepare  = buffer_prepare,
+	.buf_queue    = buffer_queue,
+	.buf_release  = buffer_release,
+	.buf_config   = buffer_config,
+};
+
+
+
+
+static int vpfe_doioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, void *arg)
+{
+	vpfe_obj *vpfe = &vpfe_device;
+	vpfe_fh *fh = file->private_data;
+	int ret = 0;
+	switch (cmd) {
+	case VIDIOC_S_CTRL:
+	case VIDIOC_S_FMT:
+	case VIDIOC_S_STD:
+	case VIDIOC_S_CROP:
+		ret = v4l2_prio_check(&vpfe->prio, &fh->prio);
+		if (0 != ret) {
+			return ret;
+		}
+		break;
+	}
+
+	switch (cmd) {
+	case VIDIOC_QUERYCAP:
+	{
+		struct v4l2_capability *cap =
+		    (struct v4l2_capability *)arg;
+		memset(cap, 0, sizeof(*cap));
+		*cap = vpfe_drvcap;
+		break;
+	}
+	case VIDIOC_ENUM_FMT:
+	{
+		struct v4l2_fmtdesc *fmt = (struct v4l2_fmtdesc *)arg;
+		u32 index = fmt->index;
+		memset(fmt, 0, sizeof(*fmt));
+		fmt->index = index;
+		if (index == 0) {
+			/* only yuv4:2:2 format is supported at this point */
+			fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			strcpy(fmt->description,
+			       "YCbCr4:2:2 Interleaved UYUV");
+			fmt->pixelformat = V4L2_PIX_FMT_UYVY;
+		} else if (index == 1) {
+			fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+			strcpy(fmt->description,
+			       "YCbCr4:2:2 Interleaved YUYV");
+			fmt->pixelformat = V4L2_PIX_FMT_YUYV;
+		} else {
+			ret = -EINVAL;
+		}
+		break;
+	}
+	case VIDIOC_G_FMT:
+	{
+		struct v4l2_format *fmt = (struct v4l2_format *)arg;
+		if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			ret = -EINVAL;
+		} else {
+			struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+			down_interruptible(&vpfe->lock);
+			pixfmt->width = vpfe->vwin.width;
+			pixfmt->height = vpfe->vwin.height;
+			pixfmt->field = vpfe->field;
+			pixfmt->pixelformat = vpfe->pixelfmt;
+			pixfmt->bytesperline = pixfmt->width * 2;
+			pixfmt->sizeimage =
+			    pixfmt->bytesperline * pixfmt->height;
+			pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
+			up(&vpfe->lock);
+		}
+		break;
+	}
+	case VIDIOC_S_FMT:
+	{
+		struct v4l2_format *fmt = (struct v4l2_format *)arg;
+		struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+		ccdc_params_ycbcr *params = &vpfe->ccdc_params;
+		if (vpfe->started) {	/* make sure streaming is not started */
+			ret = -EBUSY;
+			break;
+		}
+
+		down_interruptible(&vpfe->lock);
+		if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			ret = -EINVAL;
+			up(&vpfe->lock);
+			break;
+		}
+		if ((pixfmt->width + vpfe->vwin.left <=
+		     vpfe->bounds.width)
+		    & (pixfmt->height + vpfe->vwin.top <=
+		       vpfe->bounds.height)) {
+			/* this is the case when no scaling is supported */
+			/* crop window is directed modified */
+			vpfe->vwin.height = pixfmt->height;
+			vpfe->vwin.width = pixfmt->width;
+			params->win.width = pixfmt->width;
+			params->win.height = pixfmt->height;
+		} else {
+			ret = -EINVAL;
+			up(&vpfe->lock);
+			break;
+		}
+		/* setup the CCDC parameters accordingly */
+		if (pixfmt->pixelformat == V4L2_PIX_FMT_YUYV) {
+			params->pix_order = CCDC_PIXORDER_YCBYCR;
+			vpfe->pixelfmt = pixfmt->pixelformat;
+		} else if (pixfmt->pixelformat == V4L2_PIX_FMT_UYVY) {
+			params->pix_order = CCDC_PIXORDER_CBYCRY;
+			vpfe->pixelfmt = pixfmt->pixelformat;
+		} else {
+			ret = -EINVAL;	/* not supported format */
+			up(&vpfe->lock);
+			break;
+		}
+		if (pixfmt->field == V4L2_FIELD_NONE
+		    || pixfmt->field == V4L2_FIELD_INTERLACED) {
+			params->buf_type = CCDC_BUFTYPE_FLD_INTERLEAVED;
+			vpfe->field = pixfmt->field;
+		} else if (pixfmt->field == V4L2_FIELD_SEQ_TB) {
+			params->buf_type = CCDC_BUFTYPE_FLD_SEPARATED;
+			vpfe->field = pixfmt->field;
+		} else {
+			ret = -EINVAL;
+		}
+		up(&vpfe->lock);
+		break;
+	}
+	case VIDIOC_TRY_FMT:
+	{
+		struct v4l2_format *fmt = (struct v4l2_format *)arg;
+		if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			ret = -EINVAL;
+		} else {
+			struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+			if (pixfmt->width > vpfe->bounds.width
+			    || pixfmt->height > vpfe->bounds.height
+			    || (pixfmt->pixelformat != V4L2_PIX_FMT_UYVY
+				&& pixfmt->pixelformat !=
+				V4L2_PIX_FMT_YUYV)) {
+				ret = -EINVAL;
+			}
+		}
+		break;
+	}
+	case VIDIOC_G_STD:
+	{
+		v4l2_std_id *id = (v4l2_std_id *) arg;
+		*id = vpfe->std;
+		break;
+	}
+	case VIDIOC_S_STD:
+	{
+		v4l2_std_id id = *(v4l2_std_id *) arg;
+		tvp5146_mode mode = TVP5146_MODE_INV;
+		int sqp = 0;
+
+		if (vpfe->started) {	/* make sure streaming is not started */
+			ret = -EBUSY;
+			break;
+		}
+		down_interruptible(&vpfe->lock);
+		if (id & V4L2_STD_625_50) {
+			vpfe->std = id;
+			vpfe->bounds = vpfe->vwin = pal_bounds;
+			vpfe->pixelaspect = pal_aspect;
+			vpfe->ccdc_params.win = pal_bounds;
+
+		} else if (id & V4L2_STD_525_60) {
+			vpfe->std = id;
+			vpfe->bounds = vpfe->vwin = ntsc_bounds;
+			vpfe->pixelaspect = ntsc_aspect;
+			vpfe->ccdc_params.win = ntsc_bounds;
+		} else if (id & VPFE_STD_625_50_SQP) {
+			vpfe->std = id;
+			vpfe->bounds = vpfe->vwin = palsp_bounds;
+			vpfe->pixelaspect = sp_aspect;
+			sqp = 1;
+			id >>= 32;
+		} else if (id & VPFE_STD_525_60_SQP) {
+			vpfe->std = id;
+			sqp = 1;
+			vpfe->std = id;
+			id >>= 32;
+			vpfe->bounds = vpfe->vwin = ntscsp_bounds;
+			vpfe->pixelaspect = sp_aspect;
+			vpfe->ccdc_params.win = ntscsp_bounds;
+		} else if (id & VPFE_STD_AUTO) {
+			mode = TVP5146_MODE_AUTO;
+			vpfe->bounds = vpfe->vwin = pal_bounds;
+			vpfe->pixelaspect = pal_aspect;
+			vpfe->ccdc_params.win = pal_bounds;
+			vpfe->std = id;
+		} else if (id & VPFE_STD_AUTO_SQP) {
+			vpfe->std = id;
+			vpfe->bounds = vpfe->vwin = palsp_bounds;
+			vpfe->pixelaspect = sp_aspect;
+			sqp = 1;
+			mode = TVP5146_MODE_AUTO_SQP;
+			vpfe->pixelaspect = sp_aspect;
+		} else {
+			ret = -EINVAL;
+		}
+		if (id == V4L2_STD_PAL_60) {
+			mode = TVP5146_MODE_PAL_60;
+		} else if (id == V4L2_STD_PAL_M) {
+			mode = TVP5146_MODE_PAL_M;
+		} else if (id == V4L2_STD_PAL_Nc
+			   || id == V4L2_STD_PAL_N) {
+			mode = TVP5146_MODE_PAL_CN;
+		} else if (id & V4L2_STD_PAL) {
+			mode = TVP5146_MODE_PAL;
+		} else if (id & V4L2_STD_NTSC) {
+			mode = TVP5146_MODE_NTSC;
+		} else if (id & V4L2_STD_SECAM) {
+			mode = TVP5146_MODE_SECAM;
+		}
+		vpfe->tvp5146_params.mode = mode | (sqp << 3);
+		tvp5146_ctrl(TVP5146_CONFIG, &vpfe->tvp5146_params);
+
+		up(&vpfe->lock);
+		break;
+	}
+	case VIDIOC_ENUMSTD:
+	{
+		struct v4l2_standard *std = (struct v4l2_standard *)arg;
+		u32 index = std->index;
+		memset(std, 0, sizeof(*std));
+		std->index = index;
+		if (index == 0) {
+			std->id = V4L2_STD_525_60;
+			strcpy(std->name, "SD-525line-30fps");
+			std->framelines = 525;
+			std->frameperiod.numerator = 1001;
+			std->frameperiod.denominator = 30000;
+		} else if (index == 1) {
+			std->id = V4L2_STD_625_50;
+			strcpy(std->name, "SD-625line-25fps");
+			std->framelines = 625;
+			std->frameperiod.numerator = 1;
+			std->frameperiod.denominator = 25;
+		} else if (index == 2) {
+			std->id = VPFE_STD_625_50_SQP;
+			strcpy(std->name,
+			       "SD-625line-25fps square pixel");
+			std->framelines = 625;
+			std->frameperiod.numerator = 1;
+			std->frameperiod.denominator = 25;
+		} else if (index == 3) {
+			std->id = VPFE_STD_525_60_SQP;
+			strcpy(std->name,
+			       "SD-525line-25fps square pixel");
+			std->framelines = 525;
+			std->frameperiod.numerator = 1001;
+			std->frameperiod.denominator = 30000;
+		} else if (index == 4) {
+			std->id = VPFE_STD_AUTO;
+			strcpy(std->name, "automatic detect");
+			std->framelines = 625;
+			std->frameperiod.numerator = 1;
+			std->frameperiod.denominator = 1;
+		} else if (index == 5) {
+			std->id = VPFE_STD_AUTO_SQP;
+			strcpy(std->name,
+			       "automatic detect square pixel");
+			std->framelines = 625;
+			std->frameperiod.numerator = 1;
+			std->frameperiod.denominator = 1;
+		} else {
+			ret = -EINVAL;
+		}
+		break;
+	}
+	case VIDIOC_ENUMINPUT:
+	{
+		u32 index=0;
+		struct v4l2_input *input = (struct v4l2_input *)arg;
+		if (input->index > 1) 	/* only two inputs are available */
+			ret = -EINVAL;
+		index = input->index;
+		memset(input, 0, sizeof(*input));
+                input->index = index;
+		input->type = V4L2_INPUT_TYPE_CAMERA;
+		input->std = V4L2_STD_ALL;
+		if(input->index == 0){
+			sprintf(input->name, "COMPOSITE");
+		}else if(input->index == 1) {
+			sprintf(input->name, "S-VIDEO");
+		}
+		break;
+	}
+	case VIDIOC_G_INPUT:
+	{
+		int *index = (int *)arg;
+		*index = vpfe->tvp5146_params.amuxmode;
+		break;
+	}
+	case VIDIOC_S_INPUT:
+	{
+		int *index = (int *)arg;
+		if (*index > 1 || *index < 0) {
+			ret = -EINVAL;
+		}
+		vpfe->tvp5146_params.amuxmode = *index;
+		tvp5146_ctrl(TVP5146_SET_AMUXMODE, index);
+		break;
+	}
+	case VIDIOC_CROPCAP:
+	{
+		struct v4l2_cropcap *cropcap =
+		    (struct v4l2_cropcap *)arg;
+		cropcap->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+		down_interruptible(&vpfe->lock);
+		cropcap->bounds = cropcap->defrect = vpfe->vwin;
+		cropcap->pixelaspect = vpfe->pixelaspect;
+		up(&vpfe->lock);
+		break;
+	}
+	case VIDIOC_G_PARM:
+	{
+		struct v4l2_streamparm *parm =
+		    (struct v4l2_streamparm *)arg;
+		if (parm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			/* only capture is supported */
+			ret = -EINVAL;
+		} else {
+			struct v4l2_captureparm *capparm =
+			    &parm->parm.capture;
+			memset(capparm, 0,
+			       sizeof(struct v4l2_captureparm));
+			down_interruptible(&vpfe->lock);
+			if (vpfe->std & V4L2_STD_625_50) {
+				capparm->timeperframe.numerator = 1;
+				capparm->timeperframe.denominator = 25;	/* PAL 25fps */
+			} else {
+				capparm->timeperframe.numerator = 1001;
+				capparm->timeperframe.denominator = 30000;	/*NTSC 29.97fps */
+			}
+			capparm->readbuffers = vpfe->numbuffers;
+			up(&vpfe->lock);
+		}
+		break;
+	}
+	case VIDIOC_G_CTRL:
+		down_interruptible(&vpfe->lock);
+		tvp5146_ctrl(VIDIOC_G_CTRL, arg);
+		up(&vpfe->lock);
+		break;
+	case VIDIOC_S_CTRL:
+		down_interruptible(&vpfe->lock);
+		tvp5146_ctrl(VIDIOC_S_CTRL, arg);
+		up(&vpfe->lock);
+		break;
+	case VIDIOC_QUERYCTRL:
+		down_interruptible(&vpfe->lock);
+		tvp5146_ctrl(VIDIOC_QUERYCTRL, arg);
+		up(&vpfe->lock);
+		break;
+	case VIDIOC_G_CROP:
+	{
+		struct v4l2_crop *crop = arg;
+		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+			ret = -EINVAL;
+		} else {
+			crop->c = vpfe->vwin;
+		}
+		break;
+	}
+	case VIDIOC_S_CROP:
+	{
+		struct v4l2_crop *crop = arg;
+		ccdc_params_ycbcr *params = &vpfe->ccdc_params;
+		if (vpfe->started) {	/* make sure streaming is not started */
+			ret = -EBUSY;
+			break;
+		}
+		/*adjust the width to 16 pixel boundry */
+                crop->c.width = ((crop->c.width + 15 )/16 ) * 16;
+
+		/* make sure parameters are valid */
+		if (crop->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+		    && (crop->c.left + crop->c.width
+			<= vpfe->bounds.left + vpfe->bounds.width)
+		    && (crop->c.top + crop->c.height
+			<= vpfe->bounds.top + vpfe->bounds.height)) {
+
+			down_interruptible(&vpfe->lock);
+			vpfe->vwin = crop->c;
+			params->win = vpfe->vwin;
+			up(&vpfe->lock);
+		} else {
+			ret = -EINVAL;
+		}
+		break;
+	}
+	case VIDIOC_QUERYSTD:
+	{
+		v4l2_std_id *id = (v4l2_std_id *) arg;
+		down_interruptible(&vpfe->lock);
+		ret = sense_std(id);
+		up(&vpfe->lock);
+		break;
+	}
+	case VIDIOC_G_PRIORITY:
+	{
+		enum v4l2_priority *p = arg;
+		*p = v4l2_prio_max(&vpfe->prio);
+		break;
+	}
+	case VIDIOC_S_PRIORITY:
+	{
+		enum v4l2_priority *p = arg;
+		ret = v4l2_prio_change(&vpfe->prio, &fh->prio, *p);
+		break;
+	}
+
+	case VIDIOC_REQBUFS:
+		if (vpfe->io_usrs != 0) {
+			ret = -EBUSY;
+			break;
+		}
+		down_interruptible(&vpfe->lock);
+		videobuf_queue_init(&vpfe->bufqueue, &video_qops, NULL,
+		&vpfe->irqlock, V4L2_BUF_TYPE_VIDEO_CAPTURE, vpfe->field,
+		sizeof(struct videobuf_buffer), fh);
+
+		videobuf_set_buftype(&vpfe->bufqueue, VIDEOBUF_BUF_LINEAR);
+
+		fh->io_allowed = TRUE;
+		vpfe->io_usrs = 1;
+		INIT_LIST_HEAD(&vpfe->dma_queue);
+		ret = videobuf_reqbufs(&vpfe->bufqueue, arg);
+		up(&vpfe->lock);
+		break;
+	case VIDIOC_QUERYBUF:
+		ret = videobuf_querybuf(&vpfe->bufqueue, arg);
+		break;
+	case VIDIOC_QBUF:
+		if (!fh->io_allowed)
+			ret = -EACCES;
+		else
+			ret = videobuf_qbuf(&vpfe->bufqueue, arg);
+		break;
+	case VIDIOC_DQBUF:
+		if (!fh->io_allowed)
+			ret = -EACCES;
+		else
+			ret =  videobuf_dqbuf(&vpfe->bufqueue, arg, 0);
+		break;
+	case VIDIOC_STREAMON:
+		if (!fh->io_allowed) {
+			ret = -EACCES;
+			break;
+		}
+		if(vpfe->started){
+			ret = -EBUSY;
+			break;
+		}
+		ret = videobuf_streamon(&vpfe->bufqueue);
+		if(ret) break;
+
+		down_interruptible(&vpfe->lock);
+		/* get the current and next frame buffers */
+		/* we expect at least one buffer is in driver at this point */
+		/* if not, error is returned */
+		if (list_empty(&vpfe->dma_queue)) {
+			ret = -EIO;
+			break;
+		}
+		debug_print(KERN_INFO "cur frame %x.\n",
+			    vpfe->dma_queue.next);
+		vpfe->nextFrm = vpfe->curFrm =
+		    list_entry(vpfe->dma_queue.next,
+			       struct videobuf_buffer, queue);
+		/* remove the buffer from the queue */
+		list_del(&vpfe->curFrm->queue);
+		vpfe->curFrm->state = STATE_ACTIVE;
+
+		/* sense the current video input standard */
+		tvp5146_ctrl(TVP5146_CONFIG, &vpfe->tvp5146_params);
+		/* configure the ccdc and resizer as needed   */
+		/* start capture by enabling CCDC and resizer */
+		ccdc_config_ycbcr(&vpfe->ccdc_params);
+		/* setup the memory address for the frame buffer */
+		ccdc_setfbaddr(((unsigned long)(vpfe->curFrm->boff)));
+		/* enable CCDC */
+		vpfe->field_id = 0;
+		vpfe->started = TRUE;
+		vpfe->mode_changed = FALSE;
+		vpfe->field_offset =
+		    (vpfe->vwin.height - 2) * vpfe->vwin.width;
+		ccdc_enable(TRUE);
+		up(&vpfe->lock);
+		debug_print(KERN_INFO "started video streaming.\n");
+		break;
+	case VIDIOC_STREAMOFF:
+	{
+		if (!fh->io_allowed) {
+			ret = -EACCES;
+			break;
+		}
+		if(!vpfe->started){
+			ret = -EINVAL;
+			break;
+		}
+		/* disable CCDC */
+		down_interruptible(&vpfe->lock);
+		ccdc_enable(FALSE);
+		vpfe->started = FALSE;
+		up(&vpfe->lock);
+		ret = videobuf_streamoff(&vpfe->bufqueue);
+		break;
+	}
+	case VPFE_CMD_CONFIG_CCDC:
+	{
+		/* this can be used directly and bypass the V4L2 APIs */
+		ccdc_params_ycbcr *params = &vpfe->ccdc_params;
+		if(vpfe->started){
+		/* only allowed if streaming is not started */
+			ret = -EBUSY;
+			break;
+		}
+		down_interruptible(&vpfe->lock);
+		/* make sure the other v4l2 related fields
+		   have consistant settings */
+		*params = (*(ccdc_params_ycbcr *) arg);
+		vpfe->vwin = params->win;
+		if (params->buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) {
+			vpfe->field = V4L2_FIELD_INTERLACED;
+		} else if (params->buf_type ==
+		   CCDC_BUFTYPE_FLD_SEPARATED) {
+			vpfe->field = V4L2_FIELD_SEQ_TB;
+		}
+		if (params->pix_order == CCDC_PIXORDER_YCBYCR) {
+			vpfe->pixelfmt = V4L2_PIX_FMT_YUYV;
+		} else if (params->pix_order == CCDC_PIXORDER_CBYCRY) {
+			vpfe->pixelfmt = V4L2_PIX_FMT_UYVY;
+		}
+		up(&vpfe->lock);
+		break;
+	}
+	case VPFE_CMD_CONFIG_TVP5146:
+	/* this can be used directly and bypass the V4L2 APIs */
+	{
+		/* the settings here must be consistant with that of the CCDC's,
+		   driver does not check the consistancy */
+		tvp5146_params *params = (tvp5146_params *) arg;
+		v4l2_std_id std = 0;
+		if(vpfe->started){
+		/* only allowed if streaming is not started */
+			ret = -EBUSY;
+			break;
+		}
+		down_interruptible(&vpfe->lock);
+		/*make sure the other v4l2 related fields have consistant settings */
+		switch (params->mode & 0x7) {
+		case TVP5146_MODE_NTSC:
+			std = V4L2_STD_NTSC;
+			break;
+		case TVP5146_MODE_PAL:
+			std = V4L2_STD_PAL;
+			break;
+		case TVP5146_MODE_PAL_M:
+			std = V4L2_STD_PAL_M;
+			break;
+		case TVP5146_MODE_PAL_CN:
+			std = V4L2_STD_PAL_N;
+			break;
+		case TVP5146_MODE_SECAM:
+			std = V4L2_STD_SECAM;
+			break;
+		case TVP5146_MODE_PAL_60:
+			std = V4L2_STD_PAL_60;
+			break;
+		}
+
+		if (params->mode & 0x8) {	/* square pixel mode */
+			std <<= 32;
+		}
+
+		if (params->mode == TVP5146_MODE_AUTO) {	/* auto-detection modes */
+			std = VPFE_STD_AUTO;
+		} else if (params->mode == TVP5146_MODE_AUTO_SQP) {
+			std = VPFE_STD_AUTO_SQP;
+		}
+
+		if (std & V4L2_STD_625_50) {
+			vpfe->bounds = pal_bounds;
+			vpfe->pixelaspect = pal_aspect;
+		} else if (std & V4L2_STD_525_60) {
+			vpfe->bounds = ntsc_bounds;
+			vpfe->pixelaspect = ntsc_aspect;
+		} else if (std & VPFE_STD_625_50_SQP) {
+			vpfe->bounds = palsp_bounds;
+			vpfe->pixelaspect = sp_aspect;
+		} else if (std & VPFE_STD_525_60_SQP) {
+			vpfe->bounds = ntscsp_bounds;
+			vpfe->pixelaspect = sp_aspect;
+		}
+		vpfe->std = std;
+		tvp5146_ctrl(TVP5146_CONFIG, params);
+		vpfe->tvp5146_params = *params;
+		up(&vpfe->lock);
+		break;
+	}
+	default:
+		ret = -ENOIOCTLCMD;
+		break;
+	}			/* end switch(cmd) */
+	return ret;
+}
+
+static int vpfe_ioctl(struct inode *inode, struct file *file,
+		      unsigned int cmd, unsigned long arg)
+{
+	int ret;
+	ret =  video_usercopy(inode, file, cmd, arg, vpfe_doioctl);
+	if( cmd == VIDIOC_S_FMT || cmd == VIDIOC_TRY_FMT ){
+		ret = video_usercopy(inode, file, VIDIOC_G_FMT,
+			arg, vpfe_doioctl);
+	}
+	return ret;
+}
+
+static int vpfe_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	return videobuf_mmap_mapper(&vpfe_device.bufqueue, vma);
+}
+
+static int vpfe_open(struct inode *inode, struct file *filep)
+{
+	int minor = iminor(inode);
+	vpfe_obj *vpfe = NULL;
+	vpfe_fh *fh = NULL;
+
+	debug_print(KERN_INFO "vpfe: open minor=%d\n", minor);
+
+	/* check to make sure the minor numbers match */
+	if (vpfe_device.video_dev && vpfe_device.video_dev->minor == minor) {
+		vpfe = &vpfe_device;
+	} else {		/* device not found here */
+		return -ENODEV;
+	}
+
+	/* allocate per filehandle data */
+	if ((fh = kmalloc(sizeof(*fh), GFP_KERNEL)) == NULL) {
+		return -ENOMEM;
+	}
+	filep->private_data = fh;
+	fh->dev = vpfe;
+	fh->io_allowed = FALSE;
+	fh->prio = V4L2_PRIORITY_UNSET;
+	v4l2_prio_open(&vpfe->prio, &fh->prio);
+	vpfe->usrs++;
+
+	return 0;
+}
+
+static int vpfe_release(struct inode *inode, struct file *filep)
+{
+	vpfe_fh *fh = filep->private_data;
+	vpfe_obj *vpfe = fh->dev;
+
+	down_interruptible(&vpfe->lock);
+	if (fh->io_allowed) {
+		vpfe->io_usrs = 0;
+		ccdc_enable(FALSE);
+		vpfe->started = FALSE;
+		videobuf_queue_cancel(&vpfe->bufqueue);
+		vpfe->numbuffers = VPFE_DEFNUM_FBUFS;
+	}
+	vpfe->usrs--;
+	v4l2_prio_close(&vpfe->prio, &fh->prio);
+	filep->private_data = NULL;
+	kfree(fh);
+	up(&vpfe->lock);
+
+	return 0;
+}
+
+static struct file_operations vpfe_fops = {
+	.owner = THIS_MODULE,
+	.open = vpfe_open,
+	.release = vpfe_release,
+	.ioctl = vpfe_ioctl,
+	.mmap = vpfe_mmap
+};
+
+static struct video_device vpfe_video_template = {
+	.name = "vpfe",
+	.type = VID_TYPE_CAPTURE | VID_TYPE_CLIPPING | VID_TYPE_SCALES,
+	.hardware = 0,
+	.fops = &vpfe_fops,
+	.minor = -1,
+};
+
+static void vpfe_platform_release(struct device *device)
+{
+	/* This is called when the reference count goes to zero. */
+}
+
+static int __init vpfe_probe(struct device *device)
+{
+	struct video_device *vfd;
+	vpfe_obj *vpfe = &vpfe_device;
+
+	/* alloc video device */
+	if ((vfd = video_device_alloc()) == NULL) {
+		return -ENOMEM;
+	}
+	*vfd = vpfe_video_template;
+	vfd->dev = device;
+	vfd->release = video_device_release;
+	snprintf(vfd->name, sizeof(vfd->name), "DM644X_VPFE_DRIVER_V%d.%d.%d",
+		 (VPFE_VERSION_CODE >> 16) & 0xff,
+		 (VPFE_VERSION_CODE >> 8) & 0xff, (VPFE_VERSION_CODE) & 0xff);
+
+	vpfe->video_dev = vfd;
+	vpfe->usrs = 0;
+	vpfe->io_usrs = 0;
+	vpfe->started = FALSE;
+	vpfe->latest_only = TRUE;
+
+	v4l2_prio_init(&vpfe->prio);
+	init_MUTEX(&vpfe->lock);
+	/* register video device */
+	debug_print(KERN_INFO "trying to register vpfe device.\n");
+	debug_print(KERN_INFO "vpfe=%x,vpfe->video_dev=%x\n", (int)vpfe,
+		    (int)&vpfe->video_dev);
+	if (video_register_device(vpfe->video_dev, VFL_TYPE_GRABBER, -1) < 0) {
+		video_device_release(vpfe->video_dev);
+		vpfe->video_dev = NULL;
+		return -1;
+	}
+
+	debug_print(KERN_INFO "DM644X vpfe: driver version V%d.%d.%d loaded\n",
+		    (VPFE_VERSION_CODE >> 16) & 0xff,
+		    (VPFE_VERSION_CODE >> 8) & 0xff,
+		    (VPFE_VERSION_CODE) & 0xff);
+
+	debug_print(KERN_INFO "vpfe: registered device video%d\n",
+		    vpfe->video_dev->minor & 0x1f);
+
+	/* all done */
+	return 0;
+}
+
+static int vpfe_remove(struct device *device)
+{
+	/* un-register device */
+	video_unregister_device(vpfe_device.video_dev);
+
+	return 0;
+}
+
+#ifdef NEW
+static struct platform_driver vpfe_driver = {
+	.driver = {
+		.name		= "VPFE",
+		.owner		= THIS_MODULE,
+	},
+	.probe			= vpfe_probe,
+	.remove			= vpfe_remove,
+};
+
+#else
+static struct device_driver vpfe_driver = {
+	.name = "vpfe",
+	.bus = &platform_bus_type,
+	.probe = vpfe_probe,
+	.remove = vpfe_remove,
+};
+#endif
+
+static struct platform_device _vpfe_device = {
+	.name = "vpfe",
+	.id = 1,
+	.dev = {
+		.release = vpfe_platform_release,
+		}
+};
+
+static int vpfe_init(void)
+{
+	int i = 0;
+	void *mem;
+	/* allocate memory at initialization time to guarentee availability */
+	for (i = 0; i < VPFE_DEFNUM_FBUFS; i++) {
+		mem = (void *)__get_free_pages(GFP_KERNEL | GFP_DMA,
+					       VPFE_MAX_FBUF_ORDER);
+		if (mem) {
+			unsigned long adr = (unsigned long)mem;
+			u32 size = PAGE_SIZE << VPFE_MAX_FBUF_ORDER;
+			while (size > 0) {
+				/* make sure the frame buffers
+				   are never swapped out of memory */
+				SetPageReserved(virt_to_page(adr));
+				adr += PAGE_SIZE;
+				size -= PAGE_SIZE;
+			}
+			vpfe_device.fbuffers[i] = (u8 *) mem;
+			debug_print(KERN_INFO "memory address %d\t%x\n", i,
+				    mem);
+		} else {
+			while (--i >= 0) {
+				free_pages((unsigned long)vpfe_device.fbuffers[i],
+					   VPFE_MAX_FBUF_ORDER);
+			}
+			debug_print(KERN_INFO
+				    "frame buffer memory allocation failed.\n");
+			return -ENOMEM;
+		}
+	}
+	if (driver_register(&vpfe_driver) != 0) {
+		debug_print(KERN_INFO "driver registration failed\n");
+		return -1;
+	}
+	if (platform_device_register(&_vpfe_device) != 0) {
+		driver_unregister(&vpfe_driver);
+		debug_print(KERN_INFO "device registration failed\n");
+		return -1;
+	}
+
+	ccdc_reset();
+	tvp5146_ctrl(TVP5146_RESET, NULL);
+	/* configure the tvp5146 to default parameters */
+	tvp5146_ctrl(TVP5146_CONFIG, &vpfe_device.tvp5146_params);
+	/* setup interrupt handling */
+	request_irq(IRQ_VDINT0, vpfe_isr, SA_INTERRUPT,
+		    "dm644xv4l2", (void *)&vpfe_device);
+
+	printk(KERN_INFO "DaVinci v4l2 capture driver V1.0 loaded\n");
+	return 0;
+}
+
+static void vpfe_cleanup(void)
+{
+	int i = vpfe_device.numbuffers;
+	platform_device_unregister(&_vpfe_device);
+	driver_unregister(&vpfe_driver);
+	/* disable interrupt */
+	free_irq(IRQ_VDINT0, &vpfe_device);
+
+	while (--i >= 0) {
+		free_pages((unsigned long)vpfe_device.fbuffers[i],
+			   VPFE_MAX_FBUF_ORDER);
+	}
+	debug_print(KERN_INFO "vpfe: un-registered device video.\n");
+}
+
+module_init(vpfe_init);
+module_exit(vpfe_cleanup);
diff --git a/drivers/media/video/tvp5146.c b/drivers/media/video/tvp5146.c
new file mode 100644
index 0000000..2ba47eb
--- /dev/null
+++ b/drivers/media/video/tvp5146.c
@@ -0,0 +1,649 @@
+/*
+ *
+ *
+ * Copyright (C) 2006 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* tvp5146.c */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/videodev.h>
+#include <media/tvp5146.h>
+
+#define debug_print(x...)	//printk(x)
+
+static struct i2c_client tvp5146_i2c_client;
+static struct i2c_driver tvp5146_i2c_driver;
+
+static int i2c_read_reg(struct i2c_client *client, u8 reg, u8 * val);
+static int i2c_write_reg(struct i2c_client *client, u8 reg, u8 val);
+
+static int configtvp5146(void *arg);
+static int clrtvp5146lostlock(void);
+static int enabletvp5146agc(int arg);
+static int getctrl(void *arg);
+static int gettvp5146status(void *arg);
+static int powerdowntvp5146(int powerdownenable);
+static int queryctrl(void *arg);
+static int resettvp5146(void);
+static int setctrl(void *arg);
+static int settvp5146amuxmode(int mode);
+static int settvp5146brightness(int arg);
+static int settvp5146contrast(int arg);
+static int settvp5146hue(int arg);
+static int settvp5146saturation(int arg);
+static int settvp5146std(int arg);
+static int setup656sync(int enable);
+
+/*
+ * ======== configtvp5146 ========
+ */
+static int configtvp5146(void *arg)
+{
+	tvp5146_params *tvp5146params = (tvp5146_params *) arg;
+	int ret = 0;
+
+	ret |= setup656sync(tvp5146params->enablebt656sync);
+	ret |= settvp5146amuxmode(tvp5146params->amuxmode);
+	ret |= settvp5146std(tvp5146params->mode);
+
+	return ret;
+}
+
+/*
+ * ======== clrtvp5146lostlock  ========
+ */
+static int clrtvp5146lostlock(void)
+{
+	int ret = 0;
+	u8 clr = 1;
+	ret = i2c_write_reg(&tvp5146_i2c_client, 0x39, clr);
+	return ret;
+}
+
+/*
+ * ========  enabletvp5146agc ========
+ */
+static int enabletvp5146agc(int arg)
+{
+	int ret = 0;
+	int agc;
+	if (arg == TRUE) {
+		agc = 0xF;
+	} else {
+		agc = 0xC;
+	}
+	ret = i2c_write_reg(&tvp5146_i2c_client, 0x01, agc);
+	return ret;
+}
+
+/*
+ * ========  gettvpctrl ========
+ */
+static int getctrl(void *arg)
+{
+	struct v4l2_control *ctrl = arg;
+	int ret = 0;
+	u8 value;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ret = i2c_read_reg(&tvp5146_i2c_client, 0x09, &value);
+		ctrl->value = value;
+		break;
+	case V4L2_CID_CONTRAST:
+		ret = i2c_read_reg(&tvp5146_i2c_client, 0x0A, &value);
+		ctrl->value = value;
+		break;
+	case V4L2_CID_SATURATION:
+		ret = i2c_read_reg(&tvp5146_i2c_client, 0x0B, &value);
+		ctrl->value = value;
+		break;
+	case V4L2_CID_HUE:
+		ret = i2c_read_reg(&tvp5146_i2c_client, 0x0C, &value);
+		ctrl->value = value;
+		break;
+	case V4L2_CID_AUTOGAIN:
+		ret = i2c_read_reg(&tvp5146_i2c_client, 0x01, &value);
+		if ((value & 0x3) == 3) {
+			ctrl->value = TRUE;
+		} else {
+			ctrl->value = FALSE;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+/*
+ * ========  gettvp5146std ========
+ */
+static int gettvp5146std(tvp5146_mode * mode)
+{
+	int ret = 0;
+	u8 output1;
+	u8 std;
+	u8 lock_status;
+
+	ret |= i2c_read_reg(&tvp5146_i2c_client, 0x2, &std);
+	std &= 0x7;
+	if(std == TVP5146_MODE_AUTO){
+		ret |= i2c_read_reg(&tvp5146_i2c_client, 0x3F, &std);
+	}
+	std &= 0x7;
+	ret |= i2c_read_reg(&tvp5146_i2c_client, 0x33, &output1);
+	*mode = std  | ((output1 & 0x80) >> 4);	/* square pixel status */
+	ret |= i2c_read_reg(&tvp5146_i2c_client, 0x3A, &lock_status);
+	if ((lock_status & 0xe) != 0xe) {
+		/* not quite locked */
+		ret = -EAGAIN;
+	}
+
+	return ret;
+}
+
+/*
+ * ========  gettvp5146status ========
+ */
+static int gettvp5146status(void *arg)
+{
+	int ret = 0;
+	tvp5146_status *status = (tvp5146_status *) arg;
+	u8 agc, brightness, contrast, hue, saturation;
+	u8 status_byte;
+	u8 std;
+	u8 output1;
+
+	ret = i2c_read_reg(&tvp5146_i2c_client, 0x01, &agc);
+	if ((agc & 0x3) == 3) {
+		status->agc_enable = TRUE;
+	} else {
+		status->agc_enable = FALSE;
+	}
+	ret |= i2c_read_reg(&tvp5146_i2c_client, 0x09, &brightness);
+	status->brightness = brightness;
+
+	ret |= i2c_read_reg(&tvp5146_i2c_client, 0x0A, &contrast);
+	status->contrast = contrast;
+
+	ret |= i2c_read_reg(&tvp5146_i2c_client, 0x0B, &saturation);
+	status->saturation = saturation;
+
+	ret |= i2c_read_reg(&tvp5146_i2c_client, 0x0C, &hue);
+	status->hue = hue;
+
+	ret |= i2c_read_reg(&tvp5146_i2c_client, 0x3A, &status_byte);
+	status->field_rate = (status_byte & 0x20) ? 50 : 60;
+	status->lost_lock = (status_byte & 0x10) >> 4;
+	status->csubc_lock = (status_byte & 0x8) >> 3;
+	status->v_lock = (status_byte & 0x4) >> 2;
+	status->h_lock = (status_byte & 0x2) >> 1;
+
+	ret |= i2c_read_reg(&tvp5146_i2c_client, 0x3F, &std);
+	ret |= i2c_read_reg(&tvp5146_i2c_client, 0x33, &output1);
+	if (std | 0x80) {	/* auto switch mode */
+		status->video_std = TVP5146_MODE_AUTO;
+	} else {
+		status->video_std = std;
+	}
+	status->video_std |= ((output1 & 0x80) >> 4);	/* square pixel status */
+	return ret;
+}
+
+/*
+ * ======== powerdowntvp5146 ========
+ */
+static int powerdowntvp5146(int powerdownenable)
+{
+	u8 powerdownsettings = 0x01;
+
+	/*Put _tvp5146 in power down mode */
+	if (!powerdownenable) {
+		powerdownsettings = 0x00;
+	}
+	return i2c_write_reg(&tvp5146_i2c_client, 0x03, powerdownsettings);
+}
+
+/*
+ * ======== resettvp5146========
+ */
+static int resettvp5146(void)
+{
+	setup656sync(TRUE);
+	settvp5146amuxmode(TVP5146_AMUX_COMPOSITE);
+	return powerdowntvp5146(FALSE);
+}
+
+/*
+ * ======== queryctrl ========
+ */
+static int queryctrl(void *arg)
+{
+	struct v4l2_queryctrl *queryctrl = arg;
+	int ret = 0;
+	int id = queryctrl->id;
+
+	memset(queryctrl, 0, sizeof(*queryctrl));
+	queryctrl->id = id;
+	switch (id) {
+	case V4L2_CID_BRIGHTNESS:
+		strcpy(queryctrl->name, "BRIGHTNESS");
+		queryctrl->type = V4L2_CTRL_TYPE_INTEGER;
+		queryctrl->minimum = 0;
+		queryctrl->maximum = 255;
+		queryctrl->step = 1;
+		queryctrl->default_value = 128;
+		break;
+	case V4L2_CID_CONTRAST:
+		strcpy(queryctrl->name, "CONTRAST");
+		queryctrl->type = V4L2_CTRL_TYPE_INTEGER;
+		queryctrl->minimum = 0;
+		queryctrl->maximum = 255;
+		queryctrl->step = 1;
+		queryctrl->default_value = 128;
+		break;
+
+	case V4L2_CID_SATURATION:
+		strcpy(queryctrl->name, "SATURATION");
+		queryctrl->type = V4L2_CTRL_TYPE_INTEGER;
+		queryctrl->minimum = 0;
+		queryctrl->maximum = 255;
+		queryctrl->step = 1;
+		queryctrl->default_value = 128;
+		break;
+	case V4L2_CID_HUE:
+		strcpy(queryctrl->name, "HUE");
+		queryctrl->type = V4L2_CTRL_TYPE_INTEGER;
+		queryctrl->minimum = -128;	/* -180 DEGREE */
+		queryctrl->maximum = 127;	/* 180  DEGREE */
+		queryctrl->step = 1;
+		queryctrl->default_value = 0;	/* 0 DEGREE */
+		break;
+
+	case V4L2_CID_AUTOGAIN:
+		strcpy(queryctrl->name, "Automatic Gain Control");
+		queryctrl->type = V4L2_CTRL_TYPE_BOOLEAN;
+		queryctrl->minimum = 0;
+		queryctrl->maximum = 1;
+		queryctrl->step = 1;
+		queryctrl->default_value = 1;
+		break;
+	default:
+		if (id < V4L2_CID_LASTP1)
+			queryctrl->flags = V4L2_CTRL_FLAG_DISABLED;
+		else
+			ret = -EINVAL;
+		break;
+	}			/* end switch (id) */
+	return ret;
+}
+
+/*
+ * ======== setctrl ========
+ */
+static int setctrl(void *arg)
+{
+	struct v4l2_control *ctrl = arg;
+	int ret = 0;
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		ret = settvp5146brightness(ctrl->value);
+		break;
+	case V4L2_CID_CONTRAST:
+		ret = settvp5146contrast(ctrl->value);
+		break;
+	case V4L2_CID_SATURATION:
+		ret = settvp5146saturation(ctrl->value);
+		break;
+	case V4L2_CID_HUE:
+		ret = settvp5146hue(ctrl->value);
+		break;
+	case V4L2_CID_AUTOGAIN:
+		ret = enabletvp5146agc(ctrl->value);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	return ret;
+}
+
+/*
+ * ======== settvp5146amuxmode ========
+ */
+static int settvp5146amuxmode(int arg)
+{
+	u8 input_sel;
+
+	if (arg == TVP5146_AMUX_COMPOSITE) {	/* composite */
+		input_sel = 0x05;
+	} else if (arg == TVP5146_AMUX_SVIDEO) {	/* s-video */
+		input_sel = 0x46;
+	} else {
+		return -EINVAL;
+	}
+	return i2c_write_reg(&tvp5146_i2c_client, 0x00, input_sel);
+}
+
+/*
+ * ======== settvp5146brightness ========
+ */
+static int settvp5146brightness(int arg)
+{
+	int ret = 0;
+	u8 brightness = (u8) arg;
+	ret = i2c_write_reg(&tvp5146_i2c_client, 0x09, brightness);
+	return ret;
+}
+
+/*
+* ======== settvp5146contrast ========
+*/
+static int settvp5146contrast(int arg)
+{
+	int ret = 0;
+	u8 contrast = (u8) arg;
+	ret = i2c_write_reg(&tvp5146_i2c_client, 0x0A, contrast);
+	return ret;
+}
+
+/*
+* ======== settvp5146hue ========
+*/
+static int settvp5146hue(int arg)
+{
+	int ret = 0;
+	u8 hue = (u8) arg;
+	ret = i2c_write_reg(&tvp5146_i2c_client, 0x0C, hue);
+	return ret;
+}
+
+static int settvp5146saturation(int arg)
+{
+	int ret = 0;
+	u8 saturation = (u8) arg;
+	ret = i2c_write_reg(&tvp5146_i2c_client, 0x0B, saturation);
+	return ret;
+}
+
+static int settvp5146std(int arg)
+{
+	int ret = 0;
+	u8 std = (u8) arg & 0x7;	/* the 4th-bit is for squre pixel sampling */
+	u8 output1;
+
+	/* setup the sampling rate: 601 or square pixel */
+	debug_print(KERN_INFO "reading i2c registers.\n");
+	ret = i2c_read_reg(&tvp5146_i2c_client, 0x33, &output1);
+	output1 |= ((arg & 0x8) << 4);
+	ret = i2c_write_reg(&tvp5146_i2c_client, 0x33, output1);
+
+	/* setup the video standard */
+	ret |= i2c_write_reg(&tvp5146_i2c_client, 0x02, std);
+	/* if autoswitch mode, enable all modes for autoswitch */
+	if (std == TVP5146_MODE_AUTO) {
+		u8 mask = 0x3F;	/* enable autoswitch for  all standards */
+		ret = i2c_write_reg(&tvp5146_i2c_client, 0x04, mask);
+	}
+
+	return ret;
+}
+
+/*
+ * ======== setup656sync ========
+ */
+static int setup656sync(int enable)
+{
+	int output1, output2, output3, output4;
+	int output5, output6;
+	int ret = 0;
+
+	if (enable) {
+		output1 = 0x40;
+		output4 = 0xFF;
+		output6 = 0;
+	} else {
+		output1 = 0x43;
+		output4 = 0xAF;
+		output6 = 0x1E;
+	}
+
+	output2 = 0x11;		/* enable clock, enable Y[9:0] */
+	output3 = 0x0;
+	output5 = 0x4;
+
+	ret |= i2c_write_reg(&tvp5146_i2c_client, 0x33, output1);
+	ret |= i2c_write_reg(&tvp5146_i2c_client, 0x34, output2);
+	ret |= i2c_write_reg(&tvp5146_i2c_client, 0x36, output4);
+	ret |= i2c_write_reg(&tvp5146_i2c_client, 0x08, output3);
+	ret |= i2c_write_reg(&tvp5146_i2c_client, 0x0e, output5);
+	ret |= i2c_write_reg(&tvp5146_i2c_client, 0x32, output6);
+	return ret;
+}
+
+/*
+ * ======== tvp5146_ctrl ========
+ */
+int tvp5146_ctrl(tvp5146_cmd cmd, void *arg)
+{
+	int ret = 0;
+	switch (cmd) {
+	case TVP5146_CONFIG:
+		ret = configtvp5146(arg);
+		break;
+	case TVP5146_RESET:
+		ret = resettvp5146();
+		break;
+	case TVP5146_POWERDOWN:
+		ret = powerdowntvp5146(*(int *)arg);
+		break;
+	case TVP5146_SET_AMUXMODE:
+		ret = settvp5146amuxmode(*(int *)arg);
+		break;
+	case TVP5146_SET_BRIGHTNESS:
+		ret = settvp5146brightness(*(int *)arg);
+		break;
+	case TVP5146_SET_CONTRAST:
+		ret = settvp5146contrast(*(int *)arg);
+		break;
+	case TVP5146_SET_HUE:
+		ret = settvp5146hue(*(int *)arg);
+		break;
+	case TVP5146_SET_SATURATION:
+		ret = settvp5146saturation(*(int *)arg);
+		break;
+	case TVP5146_SET_AGC:
+		ret = enabletvp5146agc(*(int *)arg);
+		break;
+	case TVP5146_SET_VIDEOSTD:
+		ret = settvp5146std(*(int *)arg);
+		break;
+	case TVP5146_CLR_LOSTLOCK:
+		ret = clrtvp5146lostlock();
+		break;
+	case TVP5146_GET_STATUS:
+		ret = gettvp5146status(arg);
+		break;
+	case TVP5146_GET_STD:
+		ret = gettvp5146std(arg);
+		break;
+	case VIDIOC_QUERYCTRL:
+		ret = queryctrl(arg);
+		break;
+	case VIDIOC_G_CTRL:
+		ret = getctrl(arg);
+		break;
+	case VIDIOC_S_CTRL:
+		ret = setctrl(arg);
+		break;
+	default:
+		ret = -EINVAL;
+	}
+	return ret;
+}
+
+static int i2c_read_reg(struct i2c_client *client, u8 reg, u8 * val)
+{
+	int err = 0;
+
+	struct i2c_msg msg[1];
+	unsigned char data[1];
+
+	if (!client->adapter) {
+		err = -ENODEV;
+	} else {
+		msg->addr = client->addr;
+		msg->flags = 0;
+		msg->len = 1;
+		msg->buf = data;
+		data[0] = reg;
+		err = i2c_transfer(client->adapter, msg, 1);
+		if (err >= 0) {
+			msg->flags = I2C_M_RD;
+			err = i2c_transfer(client->adapter, msg, 1);
+			if (err >= 0) {
+				*val = data[0];
+			}
+		}
+	}
+	return err;
+}
+
+static int i2c_write_reg(struct i2c_client *client, u8 reg, u8 val)
+{
+	int err = 0;
+
+	struct i2c_msg msg[1];
+	unsigned char data[2];
+
+	if (!client->adapter) {
+		err = -ENODEV;
+	} else {
+		msg->addr = client->addr;
+		msg->flags = 0;
+		msg->len = 2;
+		msg->buf = data;
+		data[0] = reg;
+		data[1] = val;
+		err = i2c_transfer(client->adapter, msg, 1);
+	}
+	debug_print(KERN_INFO " i2c data write \n");
+
+	return err;
+}
+
+static int _i2c_attach_client(struct i2c_client *client,
+			      struct i2c_driver *driver,
+			      struct i2c_adapter *adap, int addr)
+{
+	int err = 0;
+
+	if (client->adapter) {
+		err = -EBUSY;	/* our client is already attached */
+	} else {
+		client->addr = addr;
+/* 		client->flags = I2C_CLIENT_ALLOW_USE; */
+		client->driver = driver;
+		client->adapter = adap;
+
+		err = i2c_attach_client(client);
+		if (err) {
+			client->adapter = NULL;
+		}
+	}
+	return err;
+}
+
+static int _i2c_detach_client(struct i2c_client *client)
+{
+	int err = 0;
+
+	if (!client->adapter) {
+		return -ENODEV;	/* our client isn't attached */
+	} else {
+		err = i2c_detach_client(client);
+		client->adapter = NULL;
+	}
+	return err;
+}
+
+static int tvp5146_i2c_probe_adapter(struct i2c_adapter *adap)
+{
+	return _i2c_attach_client(&tvp5146_i2c_client, &tvp5146_i2c_driver,
+				  adap, TVP5146_I2C_ADDR);
+}
+
+static struct i2c_driver tvp5146_i2c_driver = {
+	.driver = {
+		.name = "tvp5146",
+	},
+	.id = I2C_DRIVERID_TVP5150,
+
+	.attach_adapter = tvp5146_i2c_probe_adapter,
+	.detach_client = _i2c_detach_client,
+};
+
+static int tvp5146_i2c_init(void)
+{
+	int err;
+	struct i2c_driver *driver = &tvp5146_i2c_driver;
+
+/* 	driver->owner = THIS_MODULE; */
+/* 	strlcpy(driver->name, "TVP5146 Video Decoder I2C driver", */
+/* 		sizeof(driver->name)); */
+/* 	driver->id = I2C_DRIVERID_EXP0; */
+/* 	driver->flags = I2C_DF_NOTIFY; */
+/* 	driver->attach_adapter = tvp5146_i2c_probe_adapter; */
+/* 	driver->detach_client = _i2c_detach_client; */
+
+	err = i2c_add_driver(driver);
+	if (err) {
+		debug_print(KERN_ERR
+			"Failed to register TVP5146 I2C client.\n");
+	}
+	debug_print(KERN_INFO "tvp5146 driver registered.\n");
+	return err;
+}
+
+static void tvp5146_i2c_cleanup(void)
+{
+	struct i2c_driver *driver = &tvp5146_i2c_driver;
+
+	i2c_detach_client(&tvp5146_i2c_client);
+	i2c_del_driver(driver);
+	tvp5146_i2c_client.adapter = NULL;
+}
+
+module_init(tvp5146_i2c_init);
+module_exit(tvp5146_i2c_cleanup);
+
+EXPORT_SYMBOL(tvp5146_ctrl);
+MODULE_LICENSE("GPL");
+
+/**************************************************************************/
+/* End of file                                                                            */
+/**************************************************************************/
diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c
index a32dfbe..1c83997 100644
--- a/drivers/media/video/video-buf.c
+++ b/drivers/media/video/video-buf.c
@@ -246,7 +246,8 @@
 	void                   *dev=q->dev;
 
 	MAGIC_CHECK(dma->magic,MAGIC_DMABUF);
-	BUG_ON(!dma->sglen);
+	if(q->buf_type == VIDEOBUF_BUF_FRAGMENTED)
+		BUG_ON(!dma->sglen);
 
 	if (!dma->bus_addr && q->ops->vb_dma_sync_sg)
 		q->ops->vb_dma_sync_sg(dev,dma->sglist,dma->nr_pages,
@@ -448,6 +449,9 @@
 	q->ops     = ops;
 	q->priv_data = priv;
 
+	/* The default buffer type is fragmented */
+	q->buf_type = VIDEOBUF_BUF_FRAGMENTED;
+
 	videobuf_queue_pci(q);
 
 	mutex_init(&q->lock);
@@ -642,6 +646,10 @@
 		goto done;
 	}
 
+	if(q->buf_type == VIDEOBUF_BUF_LINEAR){
+		q->ops->buf_config(q, count);
+	}
+
 	req->count = count;
 
  done:
@@ -1362,9 +1370,23 @@
 	map->start    = vma->vm_start;
 	map->end      = vma->vm_end;
 	map->q        = q;
-	vma->vm_ops   = &videobuf_vm_ops;
-	vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
-	vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
+	if(q->buf_type == VIDEOBUF_BUF_LINEAR){
+#ifdef CONFIG_ARM
+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+#else
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+#endif
+		if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+				       (vma->vm_end - vma->vm_start),
+				       vma->vm_page_prot)){
+			return -EAGAIN;
+		}
+		vma->vm_flags |= VM_RESERVED | VM_IO;
+	} else {
+		vma->vm_ops   = &videobuf_vm_ops;
+		vma->vm_flags |= VM_DONTEXPAND | VM_RESERVED;
+		vma->vm_flags &= ~VM_IO; /* using shared anonymous pages */
+	}
 	vma->vm_private_data = map;
 	dprintk(1,"mmap %p: q=%p %08lx-%08lx pgoff %08lx bufs %d-%d\n",
 		map,q,vma->vm_start,vma->vm_end,vma->vm_pgoff,first,last);
@@ -1375,6 +1397,12 @@
 	return retval;
 }
 
+int videobuf_set_buftype(struct videobuf_queue *q, enum videobuf_buf_type type)
+{
+	q->buf_type = type;
+	return 0;
+}
+
 /* --------------------------------------------------------------------- */
 
 EXPORT_SYMBOL_GPL(videobuf_vmalloc_to_sg);
@@ -1418,6 +1446,8 @@
 EXPORT_SYMBOL_GPL(videobuf_mmap_free);
 EXPORT_SYMBOL_GPL(videobuf_mmap_mapper);
 
+EXPORT_SYMBOL_GPL(videobuf_set_buftype);
+
 /*
  * Local variables:
  * c-basic-offset: 8
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig
index 671b9a4..a2327ab 100644
--- a/drivers/mmc/host/Kconfig
+++ b/drivers/mmc/host/Kconfig
@@ -101,3 +101,11 @@
           To compile this driver as a module, choose M here: the
 	  module will be called tifm_sd.
 
+config MMC_DAVINCI
+	tristate "TI DAVINCI Multimedia Card Interface support"
+	depends on MMC
+	help
+	  This selects the TI DAVINCI Multimedia card Interface.
+	  If you have an DAVINCI board with a Multimedia Card slot,
+	  say Y or M here.  If unsure, say N.
+
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index 6685f64..dc99bd6 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -15,4 +15,5 @@
 obj-$(CONFIG_MMC_OMAP)		+= omap.o
 obj-$(CONFIG_MMC_AT91)		+= at91_mci.o
 obj-$(CONFIG_MMC_TIFM_SD)	+= tifm_sd.o
+obj-$(CONFIG_MMC_DAVINCI) 	+= davinci_mmc.o
 
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
new file mode 100644
index 0000000..5d8e79f
--- /dev/null
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -0,0 +1,1239 @@
+/*
+ * linux/drivers/mmc/davinci.c
+ *
+ * TI DaVinci MMC controller file
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ Modifications:
+ ver. 1.0: Oct 2005, Purushotam Kumar   Initial version
+ ver 1.1:  Nov  2005, Purushotam Kumar  Solved bugs
+ ver 1.2:  Jan  2066, Purushotam Kumar   Added card remove insert support
+ -
+ *
+
+ */
+
+#include <linux/module.h>
+#include <linux/tty.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/blkdev.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/mmc.h>
+
+#include <asm/io.h>
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/arch/irqs.h>
+#include <asm/arch/hardware.h>
+
+#include "davinci_mmc.h"
+#include <asm/arch/edma.h>
+
+/* FIXME: old defines  from old mmc.h */
+/* #define MMC_RSP_NONE	(0 << 0) */
+/* #define MMC_RSP_SHORT	(1 << 0) */
+/* #define MMC_RSP_LONG	(2 << 0) */
+/* #define MMC_RSP_MASK	(3 << 0) */
+/* #define MMC_RSP_CRC	(1 << 3)		/\* expect valid crc *\/ */
+/* #define MMC_RSP_BUSY	(1 << 4)		/\* card may send busy *\/ */
+#define MMC_RSP_SHORT	MMC_RSP_PRESENT
+#define MMC_RSP_LONG    MMC_RSP_136
+#define MMC_RSP_MASK    (MMC_RSP_PRESENT | MMC_RSP_136)
+
+extern void davinci_clean_channel(int ch_no);
+
+/* MMCSD Init clock in Hz in opendain mode */
+#define MMCSD_INIT_CLOCK		200000
+#define DRIVER_NAME			"mmc0"
+#define MMCINT_INTERRUPT		IRQ_MMCINT
+#define MMCSD_REGS_BASE_ADDR		DAVINCI_MMC_SD_BASE
+#define TCINTEN				(0x1<<20)
+
+/* This macro could not be defined to 0 (ZERO) or -ve value.
+ * This value is multiplied to "HZ"
+ * while requesting for timer interrupt every time for probing card.
+ */
+#define MULTIPILER_TO_HZ 1
+
+struct device mmc_dev;
+struct clk *mmc_clkp = NULL;
+mmcsd_config_def mmcsd_cfg = {
+/* read write thresholds (in bytes) can be any power of 2 from 2 to 64 */
+	32,
+/* To use the DMA or not-- 1- Use DMA, 0-Interrupt mode */
+	1
+};
+
+volatile mmcsd_regs_base *mmcsd_regs;
+static unsigned int mmc_input_clk = 0;
+
+/* Used to identify whether card being used currently by linux core or not */
+static unsigned int is_card_busy = 0;
+/* used to identify whether card probe(detection) is currently in progress */
+static unsigned int is_card_detect_progress = 0;
+/* used to identify whether core is icurrently initilizing the card or not */
+static unsigned int is_init_progress = 0;
+/* used to identify whether core request has been queue up or
+ * not because request has come when card detection/probe was in progress
+ */
+static unsigned int is_req_queued_up = 0;
+/* data struture to queue one request */
+static struct mmc_host *que_mmc_host = NULL;
+/* data structure to queue one request */
+static struct mmc_request *que_mmc_request = NULL;
+
+/* tells whether card is initizlzed or not */
+static unsigned int is_card_initialized = 0;
+static unsigned int new_card_state = 0;	/* tells current state of card */
+
+static DEFINE_SPINLOCK(mmc_lock);
+
+static void mmc_davinci_start_command(struct mmc_davinci_host *host,
+		struct mmc_command *cmd)
+{
+	u32 cmd_reg = 0;
+	u32 resp_type = 0;
+	u32 cmd_type = 0;
+	int byte_cnt = 0, i = 0;
+	unsigned long flags;
+
+	dev_dbg(&mmc_dev, "\nMMCSD : CMD%d, argument 0x%08x",
+		cmd->opcode, cmd->arg);
+	if (cmd->flags & MMC_RSP_SHORT)
+		dev_dbg(&mmc_dev, ", 32-bit response");
+	if (cmd->flags & MMC_RSP_LONG)
+		dev_dbg(&mmc_dev, ", 128-bit response");
+	if (cmd->flags & MMC_RSP_CRC)
+		dev_dbg(&mmc_dev, ", CRC");
+	if (cmd->flags & MMC_RSP_BUSY)
+		dev_dbg(&mmc_dev, ", busy notification");
+	else
+		dev_dbg(&mmc_dev, ", No busy notification");
+	dev_dbg(&mmc_dev, "\n");
+	host->cmd = cmd;
+
+	/* Protocol layer does not provide response type,
+	 * but our hardware needs to know exact type, not just size!
+	 */
+	switch (cmd->flags & MMC_RSP_MASK) {
+	case MMC_RSP_NONE:
+		/* resp 0 */
+		break;
+	case MMC_RSP_SHORT:
+		/* resp 1, resp 1b */
+		/* OR resp 3!! (assume this if bus is set opendrain) */
+		if (host->bus_mode == MMC_BUSMODE_OPENDRAIN) {
+			resp_type = 3;
+			if (cmd->opcode == 3)
+				resp_type = 1;
+		} else
+			resp_type = 1;
+		break;
+	case MMC_RSP_LONG:
+		/* resp 2 */
+		resp_type = 2;
+		break;
+	}
+
+	/* Protocol layer does not provide command type, but our hardware
+	 * needs it!
+	 * any data transfer means adtc type (but that information is not
+	 * in command structure, so we flagged it into host struct.)
+	 * However, telling bc, bcr and ac apart based on response is
+	 * not foolproof:
+	 * CMD0  = bc  = resp0  CMD15 = ac  = resp0
+	 * CMD2  = bcr = resp2  CMD10 = ac  = resp2
+	 *
+	 * Resolve to best guess with some exception testing:
+	 * resp0 -> bc, except CMD15 = ac
+	 * rest are ac, except if opendrain
+	 */
+
+	if (host->data_dir)
+		cmd_type = DAVINCI_MMC_CMDTYPE_ADTC;
+	else if (resp_type == 0 && cmd->opcode != 15)
+		cmd_type = DAVINCI_MMC_CMDTYPE_BC;
+	else if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
+		cmd_type = DAVINCI_MMC_CMDTYPE_BCR;
+	else
+		cmd_type = DAVINCI_MMC_CMDTYPE_AC;
+
+	/* Set command Busy or not */
+	if (cmd->flags & MMC_RSP_BUSY) {
+		/*
+		 * Linux core sending BUSY which is not defined for cmd 24
+		 * as per mmc standard
+		 */
+		if (cmd->opcode != 24)
+			cmd_reg = cmd_reg | (1 << 8);
+	}
+
+	/* Set command index */
+	cmd_reg |= cmd->opcode;
+
+	/* Setting initialize clock */
+	if (cmd->opcode == 0)
+		cmd_reg = cmd_reg | (1 << 14);
+
+	/* Set for generating DMA Xfer event */
+	if ((host->use_dma == 1) && (host->data != NULL)
+			&& ((cmd->opcode == 18) || (cmd->opcode == 25)
+				|| (cmd->opcode == 24)
+				|| (cmd->opcode == 17)))
+		cmd_reg = cmd_reg | (1 << 16);
+
+	/* Setting whether command involves data transfer or not */
+	if (cmd_type == DAVINCI_MMC_CMDTYPE_ADTC)
+		cmd_reg = cmd_reg | (1 << 13);
+
+	/* Setting whether stream or block transfer */
+	if (cmd->flags & MMC_DATA_STREAM)
+		cmd_reg = cmd_reg | (1 << 12);
+
+	/* Setting whether data read or write */
+	if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE)
+		cmd_reg = cmd_reg | (1 << 11);
+
+	/* Setting response type */
+	cmd_reg = cmd_reg | (resp_type << 9);
+
+	if (host->bus_mode == MMC_BUSMODE_PUSHPULL)
+		cmd_reg = cmd_reg | (1 << 7);
+
+	/* set Command timeout */
+	mmcsd_regs->mmc_tor = 0xFFFF;
+
+	/* Enable interrupt */
+	if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
+		if (host->use_dma != 1)
+			mmcsd_regs->mmc_im = MMCSD_EVENT_EOFCMD
+					| MMCSD_EVENT_WRITE
+					| MMCSD_EVENT_ERROR_CMDCRC
+					| MMCSD_EVENT_ERROR_DATACRC
+					| MMCSD_EVENT_ERROR_CMDTIMEOUT
+					| MMCSD_EVENT_ERROR_DATATIMEOUT
+					| MMCSD_EVENT_BLOCK_XFERRED;
+		else
+			mmcsd_regs->mmc_im = MMCSD_EVENT_EOFCMD
+					| MMCSD_EVENT_ERROR_CMDCRC
+					| MMCSD_EVENT_ERROR_DATACRC
+					| MMCSD_EVENT_ERROR_CMDTIMEOUT
+					| MMCSD_EVENT_ERROR_DATATIMEOUT
+					| MMCSD_EVENT_BLOCK_XFERRED;
+	} else if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
+		if (host->use_dma != 1)
+			mmcsd_regs->mmc_im = MMCSD_EVENT_EOFCMD
+					| MMCSD_EVENT_READ
+					| MMCSD_EVENT_ERROR_CMDCRC
+					| MMCSD_EVENT_ERROR_DATACRC
+					| MMCSD_EVENT_ERROR_CMDTIMEOUT
+					| MMCSD_EVENT_ERROR_DATATIMEOUT
+					| MMCSD_EVENT_BLOCK_XFERRED;
+		else
+			mmcsd_regs->mmc_im = MMCSD_EVENT_EOFCMD
+					| MMCSD_EVENT_ERROR_CMDCRC
+					| MMCSD_EVENT_ERROR_DATACRC
+					| MMCSD_EVENT_ERROR_CMDTIMEOUT
+					| MMCSD_EVENT_ERROR_DATATIMEOUT
+					| MMCSD_EVENT_BLOCK_XFERRED;
+	} else
+		mmcsd_regs->mmc_im = MMCSD_EVENT_EOFCMD
+				| MMCSD_EVENT_ERROR_CMDCRC
+				| MMCSD_EVENT_ERROR_DATACRC
+				| MMCSD_EVENT_ERROR_CMDTIMEOUT
+				| MMCSD_EVENT_ERROR_DATATIMEOUT;
+
+	/*
+	 * It is required by controoler b4 WRITE command that
+	 * FIFO should be populated with 32 bytes
+	 */
+	if ((host->data_dir == DAVINCI_MMC_DATADIR_WRITE)
+			&& (cmd_type == DAVINCI_MMC_CMDTYPE_ADTC)
+			&& (host->use_dma != 1)) {
+		byte_cnt = mmcsd_cfg.rw_threshold;
+		host->bytes_left -= mmcsd_cfg.rw_threshold;
+		for (i = 0; i < (byte_cnt / 4); i++) {
+			mmcsd_regs->mmc_dxr = *host->buffer;
+			host->buffer++;
+		}
+	}
+
+	if (cmd->opcode == 7) {
+		spin_lock_irqsave(&mmc_lock, flags);
+		new_card_state = 1;
+		is_card_initialized = 1;
+		host->old_card_state = new_card_state;
+		is_init_progress = 0;
+		spin_unlock_irqrestore(&mmc_lock, flags);
+	}
+	if (cmd->opcode == 1) {
+		spin_lock_irqsave(&mmc_lock, flags);
+		is_init_progress = 1;
+		spin_unlock_irqrestore(&mmc_lock, flags);
+	}
+
+	host->is_core_command = 1;
+	mmcsd_regs->mmc_arghl = cmd->arg;
+	mmcsd_regs->mmc_cmd = cmd_reg;
+
+}
+
+static void mmc_davinci_dma_cb(int lch, u16 ch_status, void *data)
+{
+	int sync_dev = 0;
+	struct mmc_davinci_host *host = (struct mmc_davinci_host *)data;
+
+	if (DMA_COMPLETE == ch_status) {
+
+		if (host->cmd == NULL && host->data == NULL) {
+			if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
+				sync_dev = DAVINCI_DMA_MMCTXEVT;
+			} else {
+				sync_dev = DAVINCI_DMA_MMCRXEVT;
+			}
+			dev_dbg(&mmc_dev,
+				"Interrupt from DMA when no request has been made\n");
+			davinci_stop_dma(sync_dev);
+			return;
+		}
+
+		if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
+			sync_dev = DAVINCI_DMA_MMCTXEVT;	/* Write */
+		} else {
+			sync_dev = DAVINCI_DMA_MMCRXEVT;	/* Read */
+		}
+		davinci_stop_dma(sync_dev);
+	} else {
+		/* Handing of Event missed interreupt from DMA */
+		dev_dbg(&mmc_dev,
+			"Event miss interrupt has been generated by DMA\n");
+		if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
+			sync_dev = DAVINCI_DMA_MMCTXEVT;	/* Write */
+		} else {
+			sync_dev = DAVINCI_DMA_MMCRXEVT;	/* Read */
+		}
+		davinci_clean_channel(sync_dev);
+	}
+}
+
+static int mmc_davinci_start_dma_transfer(struct mmc_davinci_host *host,
+		struct mmc_request *req)
+{
+	const char *dev_name;
+	int sync_dev, r, edma_ch = 0, tcc = 0;
+	unsigned char i, j;
+	unsigned short acnt, bcnt, ccnt;
+	unsigned int src_port, dst_port, temp_ccnt;
+	enum address_mode mode_src, mode_dst;
+	enum fifo_width fifo_width_src, fifo_width_dst;
+	unsigned short src_bidx, dst_bidx;
+	unsigned short src_cidx, dst_cidx;
+	unsigned short bcntrld;
+	enum sync_dimension sync_mode;
+	edmacc_paramentry_regs temp;
+	enum dma_event_q queue_no = EVENTQ_0;
+	int edma_chan_num;
+	unsigned int num_eight_words = (req->data->blocks * 512) / 32;
+	static unsigned int option_read = 0;
+	static unsigned int option_write = 0;
+	static unsigned char dma_read_req = 1;
+	static unsigned char dma_write_req = 1;
+
+#define MAX_C_CNT		64000
+
+	if ((req->data->flags & MMC_DATA_WRITE)) {
+		sync_dev = DAVINCI_DMA_MMCTXEVT;	/* Write */
+		dev_name = "MMC_WRITE";
+
+		if (dma_write_req) {
+			r = davinci_request_dma(sync_dev, dev_name,
+						mmc_davinci_dma_cb, host,
+						&edma_ch, &tcc, queue_no);
+			if (r != 0) {
+				dev_dbg(&mmc_dev,
+					"MMC: davinci_request_dma() failed with %d\n",
+r);
+				return r;
+			}
+			dma_write_req = 0;
+		}
+	} else {
+		sync_dev = DAVINCI_DMA_MMCRXEVT;	/* Read */
+		dev_name = "MMC_READ";
+		if (dma_read_req) {
+			r = davinci_request_dma(sync_dev, dev_name,
+						mmc_davinci_dma_cb, host,
+						&edma_ch, &tcc, queue_no);
+			if (r != 0) {
+				dev_dbg(&mmc_dev,
+					"MMC: davinci_request_dma() failed with %d\n",
+					r);
+				return r;
+			}
+			dma_read_req = 0;
+		}
+	}
+
+	if ((req->data->flags & MMC_DATA_WRITE)) {
+		/* AB Sync Transfer */
+		/* Acnt =32, Bcnt= , Cnt=1 */
+
+		sync_dev = DAVINCI_DMA_MMCTXEVT;	/* Write */
+		acnt = 4;
+		bcnt = 8;
+		if (num_eight_words > MAX_C_CNT) {
+			temp_ccnt = MAX_C_CNT;
+			ccnt = temp_ccnt;
+		} else {
+			ccnt = num_eight_words;
+			temp_ccnt = ccnt;
+		}
+
+		src_port = (unsigned int)virt_to_phys(req->data->mrq->buffer);
+		mode_src = INCR;
+		fifo_width_src = W8BIT;	/* It's not cared as modeDsr is INCR */
+		src_bidx = 4;
+		src_cidx = 32;
+		dst_port = MMCSD_REGS_BASE_ADDR + 0x2C;
+		mode_dst = INCR;
+		fifo_width_dst = W8BIT;	/* It's not cared as modeDsr is INCR */
+		dst_bidx = 0;
+		dst_cidx = 0;
+		bcntrld = 8;
+		sync_mode = ABSYNC;
+
+	} else {
+		sync_dev = DAVINCI_DMA_MMCRXEVT;	/* Read */
+		acnt = 4;
+		bcnt = 8;
+		if (num_eight_words > MAX_C_CNT) {
+			temp_ccnt = MAX_C_CNT;
+			ccnt = temp_ccnt;
+		} else {
+			ccnt = num_eight_words;
+			temp_ccnt = ccnt;
+		}
+
+		src_port = MMCSD_REGS_BASE_ADDR + 0x28;
+		mode_src = INCR;
+		fifo_width_src = W8BIT;
+		src_bidx = 0;
+		src_cidx = 0;
+		dst_port = (unsigned int)virt_to_phys(req->data->mrq->buffer);
+		mode_dst = INCR;
+		fifo_width_dst = W8BIT;	/* It's not cared as modeDsr is INCR */
+		dst_bidx = 4;
+		dst_cidx = 32;
+		bcntrld = 8;
+		sync_mode = ABSYNC;
+	}
+
+	davinci_set_dma_src_params(sync_dev, src_port, mode_src,
+			fifo_width_src);
+	davinci_set_dma_dest_params(sync_dev, dst_port, mode_dst,
+			fifo_width_dst);
+	davinci_set_dma_src_index(sync_dev, src_bidx, src_cidx);
+	davinci_set_dma_dest_index(sync_dev, dst_bidx, dst_cidx);
+	davinci_set_dma_transfer_params(sync_dev, acnt, bcnt, ccnt, bcntrld,
+					sync_mode);
+
+	host->edma_ch_details.cnt_chanel = 0;
+	davinci_get_dma_params(sync_dev, &temp);
+	if (sync_dev == DAVINCI_DMA_MMCTXEVT) {
+		if (option_write == 0) {
+			option_write = temp.opt;
+		} else {
+			temp.opt = option_write;
+			davinci_set_dma_params(sync_dev, &temp);
+		}
+	}
+	if (sync_dev == DAVINCI_DMA_MMCRXEVT) {
+		if (option_read == 0) {
+			option_read = temp.opt;
+		} else {
+			temp.opt = option_read;
+			davinci_set_dma_params(sync_dev, &temp);
+		}
+	}
+
+	if (num_eight_words > MAX_C_CNT) {	/* Linking will be performed */
+		davinci_get_dma_params(sync_dev, &temp);
+		temp.opt &= ~TCINTEN;
+		davinci_set_dma_params(sync_dev, &temp);
+
+		for (i = 0; i < EDMA_MAX_LOGICAL_CHA_ALLOWED; i++) {
+			if (i != 0) {
+				j = i - 1;
+				davinci_get_dma_params(
+					host->edma_ch_details.chanel_num[j],
+					&temp);
+				temp.opt &= ~TCINTEN;
+				davinci_set_dma_params(
+					host->edma_ch_details.chanel_num[j],
+					&temp);
+			}
+
+			host->edma_ch_details.cnt_chanel++;
+			davinci_request_dma(DAVINCI_EDMA_PARAM_ANY, "LINK",
+					NULL, NULL, &edma_chan_num,
+					&sync_dev, queue_no);
+			host->edma_ch_details.chanel_num[i] = edma_chan_num;
+			ccnt = temp.ccnt & 0x0000FFFF;
+			if (sync_dev == DAVINCI_DMA_MMCTXEVT) {
+				temp.src = temp.src + (acnt * bcnt * ccnt);
+			} else {
+				temp.dst = temp.dst + (acnt * bcnt * ccnt);
+			}
+			temp.opt |= TCINTEN;
+
+			if ((num_eight_words - temp_ccnt) > MAX_C_CNT) {
+				temp.ccnt = (temp.ccnt & 0xFFFF0000)
+					| MAX_C_CNT;
+				ccnt = temp.ccnt & 0x0000FFFF;
+				temp_ccnt = temp_ccnt + ccnt;
+			} else {
+				temp.ccnt = (temp.ccnt & 0xFFFF0000)
+					| (num_eight_words -temp_ccnt);
+				ccnt = temp.ccnt & 0x0000FFFF;
+				temp_ccnt = temp_ccnt + ccnt;
+			}
+			davinci_set_dma_params(edma_chan_num, &temp);
+			if (i != 0) {
+				j = i - 1;
+				davinci_dma_link_lch(host->edma_ch_details.
+						chanel_num[j],
+						edma_chan_num);
+			}
+			if (temp_ccnt == num_eight_words)
+				break;
+		}
+		davinci_dma_link_lch(sync_dev,
+				host->edma_ch_details.chanel_num[0]);
+	}
+
+	davinci_start_dma(sync_dev);
+	return 0;
+}
+
+static void
+mmc_davinci_prepare_data(struct mmc_davinci_host *host, struct mmc_request *req)
+{
+	int timeout;
+
+	host->data = req->data;
+	if (req->data == NULL) {
+		host->data_dir = DAVINCI_MMC_DATADIR_NONE;
+		mmcsd_regs->mmc_blen = 0;
+		mmcsd_regs->mmc_nblk = 0;
+		return;
+	}
+	dev_dbg(&mmc_dev,
+		"MMCSD : Data xfer (%s %s), "
+		"DTO %d cycles + %d ns, %d blocks of %d bytes\r\n",
+		(req->data->flags & MMC_DATA_STREAM) ? "stream" : "block",
+		(req->data->flags & MMC_DATA_WRITE) ? "write" : "read",
+		req->data->timeout_clks, req->data->timeout_ns,
+		req->data->blocks, req->data->blksz);
+
+	/* Convert ns to clock cycles by assuming 20MHz frequency
+	 * 1 cycle at 20MHz = 500 ns
+	 */
+	timeout = req->data->timeout_clks + req->data->timeout_ns / 500;
+	if (timeout > 0xffff)
+		timeout = 0xffff;
+
+	mmcsd_regs->mmc_tod = timeout;
+	mmcsd_regs->mmc_nblk = req->data->blocks;
+	mmcsd_regs->mmc_blen = req->data->blksz;
+	host->data_dir = (req->data->flags & MMC_DATA_WRITE)
+			? DAVINCI_MMC_DATADIR_WRITE
+			: DAVINCI_MMC_DATADIR_READ;
+
+	/* Configure the FIFO */
+	switch (host->data_dir) {
+	case DAVINCI_MMC_DATADIR_WRITE:
+		mmcsd_regs->mmc_fifo_ctl = mmcsd_regs->mmc_fifo_ctl | 0x1;
+		mmcsd_regs->mmc_fifo_ctl = 0x0;
+		mmcsd_regs->mmc_fifo_ctl = mmcsd_regs->mmc_fifo_ctl | (1 << 1);
+		mmcsd_regs->mmc_fifo_ctl = mmcsd_regs->mmc_fifo_ctl | (1 << 2);
+		break;
+
+	case DAVINCI_MMC_DATADIR_READ:
+		mmcsd_regs->mmc_fifo_ctl = mmcsd_regs->mmc_fifo_ctl | 0x1;
+		mmcsd_regs->mmc_fifo_ctl = 0x0;
+		mmcsd_regs->mmc_fifo_ctl = mmcsd_regs->mmc_fifo_ctl | (1 << 2);
+		break;
+	default:
+		break;
+	}
+
+	if ((host->use_dma == 1)
+			&& (mmc_davinci_start_dma_transfer(host, req) == 0)) {
+		host->buffer = NULL;
+		host->bytes_left = 0;
+	} else {
+		/* Revert to CPU Copy */
+		host->buffer = (u32 *) (req->data->mrq->buffer);
+		host->bytes_left = req->data->blocks * req->data->blksz;
+		host->use_dma = 0;
+	}
+}
+
+static void mmc_davinci_request(struct mmc_host *mmc, struct mmc_request *req)
+{
+	struct mmc_davinci_host *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	if (!is_card_detect_progress) {
+		spin_lock_irqsave(&mmc_lock, flags);
+		is_card_busy = 1;
+		spin_unlock_irqrestore(&mmc_lock, flags);
+		mmc_davinci_prepare_data(host, req);
+		mmc_davinci_start_command(host, req->cmd);
+	} else {
+		/* Queu up the request as card dectection is being excuted */
+		que_mmc_host = mmc;
+		que_mmc_request = req;
+		spin_lock_irqsave(&mmc_lock, flags);
+		is_req_queued_up = 1;
+		spin_unlock_irqrestore(&mmc_lock, flags);
+	}
+}
+
+static unsigned int calculate_freq_for_card(unsigned int mmc_req_freq)
+{
+	unsigned int mmc_freq = 0, cpu_arm_clk = 0, mmc_push_pull = 0;
+
+	cpu_arm_clk = mmc_input_clk;
+	if (cpu_arm_clk > (2 * mmc_req_freq))
+		mmc_push_pull = ((unsigned int)cpu_arm_clk
+				/ (2 * mmc_req_freq)) - 1;
+	else
+		mmc_push_pull = 0;
+
+	mmc_freq = (unsigned int)cpu_arm_clk / (2 * (mmc_push_pull + 1));
+
+	if (mmc_freq > mmc_req_freq)
+		mmc_push_pull = mmc_push_pull + 1;
+
+	return mmc_push_pull;
+}
+
+static void mmc_davinci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	unsigned short status;
+	unsigned int open_drain_freq = 0, cpu_arm_clk = 0;
+	unsigned int mmc_push_pull_freq = 0;
+	struct mmc_davinci_host *host = mmc_priv(mmc);
+
+	cpu_arm_clk = mmc_input_clk;
+	dev_dbg(&mmc_dev, "clock %dHz busmode %d powermode %d Vdd %d.%02d\r\n",
+		ios->clock, ios->bus_mode, ios->power_mode,
+		ios->vdd / 100, ios->vdd % 100);
+
+	if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) {
+		open_drain_freq = ((unsigned int)cpu_arm_clk
+				/ (2 * MMCSD_INIT_CLOCK)) - 1;
+		mmcsd_regs->mmc_clk = (mmcsd_regs->mmc_clk & ~(0xFF))
+				| open_drain_freq;
+	} else {
+		mmc_push_pull_freq = calculate_freq_for_card(ios->clock);
+		mmcsd_regs->mmc_clk = (mmcsd_regs->mmc_clk & ~(0xFF))
+				| mmc_push_pull_freq;
+	}
+	host->bus_mode = ios->bus_mode;
+	if (ios->power_mode == MMC_POWER_UP) {
+		/* Send clock cycles, poll completion */
+		mmcsd_regs->mmc_arghl = 0x0;
+		mmcsd_regs->mmc_cmd = 0x4000;
+		status = 0;
+		while (!(status & (MMCSD_EVENT_EOFCMD))) {
+			status = mmcsd_regs->mmc_st0;
+		}
+	}
+}
+
+static void
+mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data)
+{
+	unsigned long flags;
+
+	host->data = NULL;
+	host->data_dir = DAVINCI_MMC_DATADIR_NONE;
+	if (data->error == MMC_ERR_NONE)
+		data->bytes_xfered += data->blocks * data->blksz;
+
+	if (data->error == MMC_ERR_TIMEOUT) {
+		spin_lock_irqsave(&mmc_lock, flags);
+		is_card_busy = 0;
+		spin_unlock_irqrestore(&mmc_lock, flags);
+		mmc_request_done(host->mmc, data->mrq);
+		return;
+	}
+
+	if (!data->stop) {
+		host->req = NULL;
+		spin_lock_irqsave(&mmc_lock, flags);
+		is_card_busy = 0;
+		spin_unlock_irqrestore(&mmc_lock, flags);
+		mmc_request_done(host->mmc, data->mrq);
+		return;
+	}
+	mmc_davinci_start_command(host, data->stop);
+}
+
+static void mmc_davinci_cmd_done(struct mmc_davinci_host *host,
+				 struct mmc_command *cmd)
+{
+	unsigned long flags;
+
+	host->cmd = NULL;
+	switch (cmd->flags & MMC_RSP_MASK) {
+	case MMC_RSP_NONE:
+		/* resp 0 */
+		break;
+
+	case MMC_RSP_SHORT:
+		/* response types 1, 1b, 3, 4, 5, 6 */
+		cmd->resp[0] = mmcsd_regs->mmc_rsp67;
+		break;
+
+	case MMC_RSP_LONG:
+		/* response type 2 */
+		cmd->resp[3] = mmcsd_regs->mmc_rsp01;
+		cmd->resp[2] = mmcsd_regs->mmc_rsp23;
+		cmd->resp[1] = mmcsd_regs->mmc_rsp45;
+		cmd->resp[0] = mmcsd_regs->mmc_rsp67;
+		break;
+	}
+
+	if (host->data == NULL || cmd->error != MMC_ERR_NONE) {
+		host->req = NULL;
+		if (cmd->error == MMC_ERR_TIMEOUT)
+			cmd->mrq->cmd->retries = 0;
+		spin_lock_irqsave(&mmc_lock, flags);
+		is_card_busy = 0;
+		spin_unlock_irqrestore(&mmc_lock, flags);
+		mmc_request_done(host->mmc, cmd->mrq);
+	}
+}
+
+static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
+{
+	struct mmc_davinci_host *host = (struct mmc_davinci_host *)dev_id;
+	u16 status;
+	int end_command;
+	int end_transfer;
+	int byte_cnt = 0, i = 0;
+	unsigned long flags;
+
+	if (host->is_core_command) {
+		if (host->cmd == NULL && host->data == NULL) {
+			status = mmcsd_regs->mmc_st0;
+			dev_dbg(&mmc_dev, "Spurious interrupt 0x%04x\r\n",
+				status);
+			/* Disable the interrupt from mmcsd */
+			mmcsd_regs->mmc_im = 0;
+			return IRQ_HANDLED;
+		}
+	}
+	end_command = 0;
+	end_transfer = 0;
+
+	status = mmcsd_regs->mmc_st0;
+	if (status == 0)
+		return IRQ_HANDLED;
+
+	if (host->is_core_command) {
+		if (is_card_initialized) {
+			if (new_card_state == 0) {
+				if (host->cmd) {
+					host->cmd->error |= MMC_ERR_TIMEOUT;
+					mmc_davinci_cmd_done(host, host->cmd);
+				}
+				dev_dbg(&mmc_dev,
+					"From code segment excuted when card removed\n");
+				return IRQ_HANDLED;
+			}
+		}
+
+		while (status != 0) {
+			if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
+				if (status & MMCSD_EVENT_WRITE) {
+					/* Buffer almost empty */
+					if (host->bytes_left > 0) {
+						byte_cnt =
+							mmcsd_cfg.rw_threshold;
+						host->bytes_left -=
+							mmcsd_cfg.rw_threshold;
+						for (i = 0; i < (byte_cnt / 4);
+								i++) {
+							mmcsd_regs->mmc_dxr =
+								*host->buffer;
+							host->buffer++;
+						}
+					}
+				}
+			}
+
+			if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
+				if (status & MMCSD_EVENT_READ) {
+					/* Buffer almost empty */
+					if (host->bytes_left > 0) {
+						byte_cnt =
+							mmcsd_cfg.rw_threshold;
+						host->bytes_left -=
+							mmcsd_cfg.rw_threshold;
+						for (i = 0; i < (byte_cnt / 4);
+								i++) {
+							*host->buffer =
+								mmcsd_regs->
+									mmc_drr;
+							host->buffer++;
+						}
+					}
+				}
+			}
+
+			if (status & MMCSD_EVENT_BLOCK_XFERRED) {
+				/* Block sent/received */
+				if (host->data != NULL) {
+					end_transfer = 1;
+				}
+			}
+
+			if (status & MMCSD_EVENT_ERROR_DATATIMEOUT) {
+				/* Data timeout */
+				if ((host->data) && (new_card_state != 0)) {
+					host->data->error |= MMC_ERR_TIMEOUT;
+					spin_lock_irqsave(&mmc_lock, flags);
+					new_card_state = 0;
+					is_card_initialized = 0;
+					spin_unlock_irqrestore(&mmc_lock,
+						flags);
+					dev_dbg(&mmc_dev,
+						"MMCSD: Data timeout, CMD%d and status is %x\r\n",
+						host->cmd->opcode, status);
+					end_transfer = 1;
+					host->cmd->error |= MMC_ERR_TIMEOUT;
+				}
+				dev_dbg(&mmc_dev,
+					"MMCSD: Data timeout, CMD%d and status is %x\r\n",
+					host->cmd->opcode, status);
+			}
+
+			if (status & MMCSD_EVENT_ERROR_DATACRC) {
+				/* Data CRC error */
+				if (host->data) {
+					host->data->error |= MMC_ERR_BADCRC;
+					dev_dbg(&mmc_dev,
+						"MMCSD: Data CRC error, bytes left %d\r\n",
+						host->bytes_left);
+					end_transfer = 1;
+				} else {
+					dev_dbg(&mmc_dev,
+						"MMCSD: Data CRC error\r\n");
+				}
+			}
+
+			if (status & MMCSD_EVENT_ERROR_CMDTIMEOUT) {
+				/* Command timeout */
+				if (host->cmd) {
+					/* Timeouts are normal in case of
+					 * MMC_SEND_STATUS
+					 */
+					if (host->cmd->opcode !=
+							MMC_ALL_SEND_CID) {
+						dev_dbg(&mmc_dev,
+							"MMCSD: CMD%d timeout,"
+							" status %x\r\n",
+							host->cmd->opcode,
+							status);
+						spin_lock_irqsave(&mmc_lock,
+							flags);
+						new_card_state = 0;
+						is_card_initialized = 0;
+						spin_unlock_irqrestore(
+							&mmc_lock, flags);
+					}
+					host->cmd->error |= MMC_ERR_TIMEOUT;
+					end_command = 1;
+
+				}
+			}
+
+			if (status & MMCSD_EVENT_ERROR_CMDCRC) {
+				/* Command CRC error */
+				dev_dbg(&mmc_dev, "Command CRC error\r\n");
+				if (host->cmd) {
+					host->cmd->error |= MMC_ERR_BADCRC;
+					end_command = 1;
+				}
+			}
+
+			if (status & MMCSD_EVENT_EOFCMD) {
+				/* End of command phase */
+				end_command = 1;
+			}
+
+			if (host->data == NULL) {
+				status = mmcsd_regs->mmc_st0;
+				if (status != 0) {
+					dev_dbg(&mmc_dev,
+						"Status is %x at end of ISR when host->data is NULL",
+						status);
+					status = 0;
+
+				}
+			} else {
+				status = mmcsd_regs->mmc_st0;
+			}
+		}
+
+		if (end_command)
+			mmc_davinci_cmd_done(host, host->cmd);
+		if (end_transfer)
+			mmc_davinci_xfer_done(host, host->data);
+
+	} else {
+		if (host->cmd_code == 13) {
+			if (status & MMCSD_EVENT_EOFCMD) {
+				spin_lock_irqsave(&mmc_lock, flags);
+				new_card_state = 1;
+				spin_unlock_irqrestore(&mmc_lock, flags);
+
+			} else {
+				spin_lock_irqsave(&mmc_lock, flags);
+				new_card_state = 0;
+				is_card_initialized = 0;
+				spin_unlock_irqrestore(&mmc_lock, flags);
+			}
+
+			spin_lock_irqsave(&mmc_lock, flags);
+			is_card_detect_progress = 0;
+			spin_unlock_irqrestore(&mmc_lock, flags);
+
+			if (is_req_queued_up) {
+				mmc_davinci_request(que_mmc_host,
+						que_mmc_request);
+				spin_lock_irqsave(&mmc_lock, flags);
+				is_req_queued_up = 0;
+				spin_unlock_irqrestore(&mmc_lock, flags);
+			}
+
+		}
+
+		if (host->cmd_code == 1) {
+			if (status & MMCSD_EVENT_EOFCMD) {
+				spin_lock_irqsave(&mmc_lock, flags);
+				new_card_state = 1;
+				is_card_initialized = 0;
+				spin_unlock_irqrestore(&mmc_lock, flags);
+			} else {
+
+				spin_lock_irqsave(&mmc_lock, flags);
+				new_card_state = 0;
+				is_card_initialized = 0;
+				spin_unlock_irqrestore(&mmc_lock, flags);
+			}
+
+			spin_lock_irqsave(&mmc_lock, flags);
+			is_card_detect_progress = 0;
+			spin_unlock_irqrestore(&mmc_lock, flags);
+
+			if (is_req_queued_up) {
+				mmc_davinci_request(que_mmc_host,
+						que_mmc_request);
+				spin_lock_irqsave(&mmc_lock, flags);
+				is_req_queued_up = 0;
+				spin_unlock_irqrestore(&mmc_lock, flags);
+			}
+
+		}
+
+		if (host->cmd_code == 0) {
+			if (status & MMCSD_EVENT_EOFCMD) {
+				host->is_core_command = 0;
+				host->cmd_code = 1;
+				dev_dbg(&mmc_dev,
+					"MMC-Probing mmc with cmd1\n");
+				/* Issue cmd1 */
+				mmcsd_regs->mmc_arghl = 0x80300000;
+				mmcsd_regs->mmc_cmd = 0x00000601;
+
+			} else {
+				spin_lock_irqsave(&mmc_lock, flags);
+				new_card_state = 0;
+				is_card_initialized = 0;
+				is_card_detect_progress = 0;
+				spin_unlock_irqrestore(&mmc_lock, flags);
+			}
+		}
+
+	}
+	return IRQ_HANDLED;
+}
+
+static struct mmc_host_ops mmc_davinci_ops = {
+	.request = mmc_davinci_request,
+	.set_ios = mmc_davinci_set_ios,
+};
+
+void mmc_check_card(unsigned long data)
+{
+	struct mmc_davinci_host *host = (struct mmc_davinci_host *)data;
+	unsigned long flags;
+
+	if ((!is_card_detect_progress) || (!is_init_progress)) {
+		if (is_card_initialized) {
+			host->is_core_command = 0;
+			host->cmd_code = 13;
+			spin_lock_irqsave(&mmc_lock, flags);
+			is_card_detect_progress = 1;
+			spin_unlock_irqrestore(&mmc_lock, flags);
+			/* Issue cmd13 */
+			mmcsd_regs->mmc_arghl = 0x10000;
+			mmcsd_regs->mmc_cmd = 0x0000028D;
+		} else {
+			host->is_core_command = 0;
+			host->cmd_code = 0;
+			spin_lock_irqsave(&mmc_lock, flags);
+			is_card_detect_progress = 1;
+			spin_unlock_irqrestore(&mmc_lock, flags);
+			/* Issue cmd0 */
+			mmcsd_regs->mmc_arghl = 0;
+			mmcsd_regs->mmc_cmd = 0x4000;
+		}
+		mmcsd_regs->mmc_im = MMCSD_EVENT_EOFCMD
+				| MMCSD_EVENT_ERROR_CMDCRC
+				| MMCSD_EVENT_ERROR_DATACRC
+				| MMCSD_EVENT_ERROR_CMDTIMEOUT
+				| MMCSD_EVENT_ERROR_DATATIMEOUT;
+	}
+}
+
+static void davinci_mmc_check_status(unsigned long data)
+{
+	unsigned long flags;
+	struct mmc_davinci_host *host = (struct mmc_davinci_host *)data;
+
+	if (!is_card_busy) {
+		if (host->old_card_state ^ new_card_state) {
+			mmc_detect_change(host->mmc, 0);
+			spin_lock_irqsave(&mmc_lock, flags);
+			host->old_card_state = new_card_state;
+			spin_unlock_irqrestore(&mmc_lock, flags);
+		} else
+			mmc_check_card(data);
+	}
+	mod_timer(&host->timer, jiffies + MULTIPILER_TO_HZ * HZ);
+}
+
+static void init_mmcsd_host(void)
+{
+	/* CMD line portion is diabled and in reset state */
+	mmcsd_regs->mmc_ctl = mmcsd_regs->mmc_ctl | 0x1;
+	/* DAT line portion is diabled and in reset state */
+	mmcsd_regs->mmc_ctl = mmcsd_regs->mmc_ctl | (1 << 1);
+
+	mmcsd_regs->mmc_clk = 0x0;
+	mmcsd_regs->mmc_clk = mmcsd_regs->mmc_clk | (1 << 8);
+
+	mmcsd_regs->mmc_tor = 0xFFFF;
+	mmcsd_regs->mmc_tod = 0xFFFF;
+
+	mmcsd_regs->mmc_ctl = mmcsd_regs->mmc_ctl & ~(0x1);
+	mmcsd_regs->mmc_ctl = mmcsd_regs->mmc_ctl & ~(1 << 1);
+}
+
+static int davinci_mmcsd_probe(struct platform_device *pdev)
+{
+	struct mmc_davinci_host *host;
+	struct mmc_host *mmc;
+	int ret;
+
+	mmc = mmc_alloc_host(sizeof(struct mmc_davinci_host), &pdev->dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	mmcsd_regs =
+		(volatile mmcsd_regs_base *)IO_ADDRESS(MMCSD_REGS_BASE_ADDR);
+
+	init_mmcsd_host();
+
+	mmc->ops = &mmc_davinci_ops;
+	mmc->f_min = 312500;
+	mmc->f_max = 20000000;
+	mmc->ocr_avail = MMC_VDD_32_33;
+
+	host = mmc_priv(mmc);
+	host->mmc = mmc;	/* Important */
+
+	host->use_dma = mmcsd_cfg.use_dma;
+	host->irq = MMCINT_INTERRUPT;
+	host->sd_support = 1;
+	ret = request_irq(MMCINT_INTERRUPT, mmc_davinci_irq, 0, DRIVER_NAME,
+			host);
+
+	if (ret)
+		goto out;
+
+	platform_set_drvdata(pdev, host);
+	mmc_add_host(mmc);
+
+	init_timer(&host->timer);
+	host->timer.data = (unsigned long)host;
+	host->timer.function = davinci_mmc_check_status;
+	host->timer.expires = jiffies + MULTIPILER_TO_HZ * HZ;
+	add_timer(&host->timer);
+
+	return 0;
+
+out:
+	/* TBD: Free other resources too. */
+
+	return ret;
+}
+
+static int davinci_mmcsd_remove(struct platform_device *pdev)
+{
+	struct mmc_davinci_host *host = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	mmc_remove_host(host->mmc);
+	free_irq(host->irq, host);
+	del_timer(&host->timer);
+	davinci_free_dma(DAVINCI_DMA_MMCTXEVT);
+	davinci_free_dma(DAVINCI_DMA_MMCRXEVT);
+	return 0;
+
+}
+
+#ifdef CONFIG_PM
+static int davinci_mmcsd_suspend(struct platform_device *pdev, pm_message_t msg)
+{
+	struct mmc_davinci_host *host = platform_get_drvdata(pdev);
+
+	return mmc_suspend_host(host->mmc, msg);
+}
+
+static int davinci_mmcsd_resume(struct platform_device *pdev)
+{
+	struct mmc_davinci_host *host = platform_get_drvdata(pdev);
+
+	return mmc_resume_host(host->mmc);
+}
+
+#else
+
+#define davinci_mmcsd_suspend	NULL
+#define davinci_mmcsd_resume	NULL
+
+#endif
+
+static struct platform_driver davinci_mmcsd_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = davinci_mmcsd_probe,
+	.remove = davinci_mmcsd_remove,
+	.suspend = davinci_mmcsd_suspend,
+	.resume = davinci_mmcsd_resume,
+};
+
+/* FIXME don't be a legacy driver ... register the device as part
+ * of cpu-specific board setup.
+ */
+static void mmc_release(struct device *dev)
+{
+	/* Nothing to release? */
+}
+
+static u64 mmc_dma_mask = 0xffffffff;
+
+static struct resource mmc_resources[] = {
+	{
+		.start = IO_ADDRESS(MMCSD_REGS_BASE_ADDR),
+		.end = IO_ADDRESS((MMCSD_REGS_BASE_ADDR) + 0x74),
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = MMCINT_INTERRUPT,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device mmc_davinci_device = {
+	.name = DRIVER_NAME,
+	.id = 1,
+	.dev = {
+		.release = mmc_release,
+		.dma_mask = &mmc_dma_mask,
+	},
+	.num_resources = ARRAY_SIZE(mmc_resources),
+	.resource = mmc_resources,
+};
+
+static int davinci_mmcsd_init(void)
+{
+	int ret = 0;
+	struct clk *clkp = NULL;
+
+	clkp = clk_get(NULL, "MMCSDCLK");
+	if (clkp != NULL) {
+		mmc_clkp = clkp;
+		clk_enable(mmc_clkp);
+		mmc_input_clk = clk_get_rate(mmc_clkp);
+
+		ret = platform_device_register(&mmc_davinci_device);
+		if (ret != 0)
+			goto free1;
+
+		ret = platform_driver_register(&davinci_mmcsd_driver);
+		if (ret == 0)
+			return 0;
+
+free1:
+		platform_device_unregister(&mmc_davinci_device);
+	}
+
+	return -ENODEV;
+}
+
+static void __exit davinci_mmcsd_exit(void)
+{
+	platform_driver_unregister(&davinci_mmcsd_driver);
+	platform_device_unregister(&mmc_davinci_device);
+	clk_disable(mmc_clkp);
+}
+
+module_init(davinci_mmcsd_init);
+module_exit(davinci_mmcsd_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MMCSD driver for Davinci MMC controller");
diff --git a/drivers/mmc/host/davinci_mmc.h b/drivers/mmc/host/davinci_mmc.h
new file mode 100644
index 0000000..a6c4557
--- /dev/null
+++ b/drivers/mmc/host/davinci_mmc.h
@@ -0,0 +1,171 @@
+/*
+ *  linux/drivers/mmc/davinci.h
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *      DAVINCI MMC register and other definitions
+ *
+ *  Copyright (C) 2006 Texas Instruments.
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ * ----------------------------------------------------------------------------
+ Modifications:
+ ver. 1.0: Oct 2005, Purushotam Kumar   Initial version
+ ver  1.2: Jan  2006, Purushotam Kumar   Added hot card remove insert support
+
+ *
+ */
+
+#ifndef DAVINCI_MMC_H_
+#define DAVINCI_MMC_H_
+
+/**************************************************************************\
+* Register Overlay Structure
+\**************************************************************************/
+
+typedef struct {
+	unsigned short mmc_ctl;
+	unsigned char rsvd0[2];
+	unsigned short mmc_clk;
+	unsigned char rsvd1[2];
+	unsigned short mmc_st0;
+	unsigned char rsvd2[2];
+	unsigned short mmc_st1;
+	unsigned char rsvd3[2];
+	unsigned short mmc_im;
+	unsigned char rsvd4[2];
+	unsigned short mmc_tor;
+	unsigned char rsvd5[2];
+	unsigned short mmc_tod;
+	unsigned char rsvd6[2];
+	unsigned short mmc_blen;
+	unsigned char rsvd7[2];
+	unsigned short mmc_nblk;
+	unsigned char rsvd8[2];
+	unsigned short mmc_nblc;
+	unsigned char rsvd9[2];
+	unsigned int mmc_drr;
+	unsigned int mmc_dxr;
+	unsigned int mmc_cmd;
+	unsigned int mmc_arghl;
+	unsigned int mmc_rsp01;
+	unsigned int mmc_rsp23;
+	unsigned int mmc_rsp45;
+	unsigned int mmc_rsp67;
+	unsigned short mmc_drsp;
+	unsigned char rsvd10[2];
+	unsigned short mmc_etok;
+	unsigned char rsvd11[2];
+	unsigned short mmc_cidx;
+	unsigned char rsvd12[2];
+	unsigned short mmc_ckc;
+	unsigned char rsvd13[2];
+	unsigned short mmc_torc;
+	unsigned char rsvd14[2];
+	unsigned short mmc_todc;
+	unsigned char rsvd15[2];
+	unsigned short mmc_blnc;
+	unsigned char rsvd16[2];
+	unsigned short sdio_ctl;
+	unsigned char rsvd17[2];
+	unsigned short sdio_st0;
+	unsigned char rsvd18[2];
+	unsigned short sdio_en;
+	unsigned char rsvd19[2];
+	unsigned short sdio_st;
+	unsigned char rsvd20[2];
+	unsigned short mmc_fifo_ctl;
+} mmcsd_regs_base;
+
+/*
+ * Command types
+ */
+#define DAVINCI_MMC_CMDTYPE_BC	0
+#define DAVINCI_MMC_CMDTYPE_BCR	1
+#define DAVINCI_MMC_CMDTYPE_AC	2
+#define DAVINCI_MMC_CMDTYPE_ADTC	3
+#define EDMA_MAX_LOGICAL_CHA_ALLOWED 1
+
+typedef struct {
+	unsigned char cnt_chanel;
+	unsigned int chanel_num[EDMA_MAX_LOGICAL_CHA_ALLOWED];
+} edma_ch_mmcsd;
+
+struct mmc_davinci_host {
+
+	int initialized;
+	int suspended;
+	struct mmc_request *req;
+	struct mmc_command *cmd;
+	struct mmc_data *data;
+	struct mmc_host *mmc;
+	struct device *dev;
+	unsigned char id;
+	struct clk *clk;
+	u32 base;
+	int irq;
+	unsigned char bus_mode;
+
+#define DAVINCI_MMC_DATADIR_NONE	0
+#define DAVINCI_MMC_DATADIR_READ	1
+#define DAVINCI_MMC_DATADIR_WRITE	2
+	unsigned char data_dir;
+	u32 *buffer;
+	u32 bytes_left;
+	int power_pin;
+
+	int use_dma;
+	struct completion dma_completion;
+
+	struct timer_list timer;
+	unsigned int is_core_command;
+	unsigned int cmd_code;
+	unsigned int old_card_state;
+
+	unsigned char sd_support;
+
+	edma_ch_mmcsd edma_ch_details;
+
+};
+typedef struct {
+	unsigned short rw_threshold;
+	unsigned short use_dma;
+} mmcsd_config_def;
+
+typedef enum {
+	MMCSD_EVENT_EOFCMD = (1 << 2),
+	MMCSD_EVENT_READ = (1 << 10),
+	MMCSD_EVENT_WRITE = (1 << 9),
+	MMCSD_EVENT_ERROR_CMDCRC = (1 << 7),
+	MMCSD_EVENT_ERROR_DATACRC = ((1 << 6) | (1 << 5)),
+	MMCSD_EVENT_ERROR_CMDTIMEOUT = (1 << 4),
+	MMCSD_EVENT_ERROR_DATATIMEOUT = (1 << 3),
+	MMCSD_EVENT_CARD_EXITBUSY = (1 << 1),
+	MMCSD_EVENT_BLOCK_XFERRED = (1 << 0)
+} mmcsdevent;
+
+#define MMCSD_EVENT_TIMEOUT_ERROR \
+ (MMCSD_EVENT_ERROR_DATATIMEOUT | MMCSD_EVENT_ERROR_CMDTIMEOUT )
+#define MMCSD_EVENT_CRC_ERROR \
+ (MMCSD_EVENT_ERROR_DATACRC | MMCSD_EVENT_ERROR_CMDCRC)
+#define MMCSD_EVENT_ERROR \
+ (MMCSD_EVENT_TIMEOUT_ERROR | MMCSD_EVENT_CRC_ERROR)
+
+#endif /* DAVINCI_MMC_H_ */
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index c5519250e..8dd9a86 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -917,6 +917,15 @@
 	  module, say M here and read <file:Documentation/kbuild/modules.txt>
 	  as well as <file:Documentation/networking/net-modules.txt>.
 
+config TI_DAVINCI_EMAC
+	tristate "TI DaVinci EMAC Support"
+	depends on NETDEVICES && MACH_DAVINCI_EVM
+	help
+	  This driver supports TI's DaVinci Ethernet .
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called ti_davinci_emac.  This is recommended.
+
 config NET_NETX
 	tristate "NetX Ethernet support"
 	select MII
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 9c928a8..32cc79a 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -2,6 +2,9 @@
 # Makefile for the Linux network (ethercard) device drivers.
 #
 
+davinci_emac_driver-objs := davinci_emac.o davinci_emac_phy.o
+obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac_driver.o
+
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_IBM_EMAC) += ibm_emac/
 obj-$(CONFIG_IXGB) += ixgb/
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
new file mode 100644
index 0000000..d1b6787
--- /dev/null
+++ b/drivers/net/davinci_emac.c
@@ -0,0 +1,6959 @@
+/*
+ * linux/drivers/net/davinci_emac.c
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ Modifications:
+ ver. 0.0 Suraj Iyer - Original Linux drive
+      0.1 Anant Gole - Recoded as per TI PSPF architecture (converted to DDA)
+      2.0 Suraj Iyer, Sharath Kumar, Ajay Singh - Completed for TI BCG
+      3.0 Anant Gole - Modified and ported for DaVinci
+      4.0 Kevin Hilman, Anant Gole - Linuxification of the driver
+      4.? Paul Bartholomew - Use PHY_DUPLEX_* constants instead
+                             of hard-coded numbers.  Also, fixed
+                             EMAC_IOCTL_READ_PHY_REG in emac_control() -
+                             the phy_num and reg_addr args were swapped
+                             in call to emac_mdio_read().
+ */
+
+/*
+    Driver Features:
+
+    The following flags should be defined by the make file for support
+    of the features:
+
+    (1) EMAC_CACHE_WRITEBACK_MODE to support write back cache mode.
+
+    (2) EMAC_MULTIPACKET_TX_COMPLETE_NOTIFY - to support of multiple
+        Tx complete notifications. If this is defined the Tx complete
+        DDA callback function contains multiple packet Tx complete
+        events.  Note: BY DEFAULT THIS DRIVER HANDLES MULTIPLE TX
+        COMPLETE VIA ITS CALLBACK IN THE SAME FUNCTION FOR SINGLE
+        PACKET COMPLETE NOTIFY.
+
+
+    (3) CONFIG_EMAC_INIT_BUF_MALLOC - Not required for DaVinci driver
+        - feature was added for another TI platform
+
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/in.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/skbuff.h>
+#include <linux/ethtool.h>
+#include <linux/highmem.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <asm/bitops.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/semaphore.h>
+#include <asm/page.h>
+#include <asm/arch/memory.h>
+#include <asm/arch/hardware.h>
+
+#include "davinci_emac_phy.h"
+
+/* ---------------------------------------------------------------
+ * linux module options
+ * --------------------------------------------------------------- */
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Davinci EMAC Maintainer: Anant Gole <anantgole@ti.com>");
+MODULE_DESCRIPTION("DaVinci Ethernet driver - EMAC (EMAC)");
+
+static int cfg_link_speed = 0;
+module_param(cfg_link_speed, int, 0);
+MODULE_PARM_DESC(cfg_link_speed, "Fixed speed of the Link: <100/10>");
+
+static char *cfg_link_mode = "auto";
+module_param(cfg_link_mode, charp, 0);
+MODULE_PARM_DESC(cfg_link_mode, "Fixed mode of the Link: <fd/hd>");
+
+static int debug_mode = 0;
+module_param(debug_mode, int, 0);
+MODULE_PARM_DESC(debug_mode,
+		 "Turn on the debug info: <0/1>. Default is 0 (off)");
+
+/* version info */
+#define EMAC_MAJOR_VERSION         4
+#define EMAC_MINOR_VERSION         0
+#define EMAC_MODULE_VERSION "4.0"
+MODULE_VERSION(EMAC_MODULE_VERSION);
+const char emac_version_string[] = "TI DaVinci EMAC Linux version updated 4.0";
+
+/* Debug options */
+#define EMAC_DEBUG
+#define EMAC_CACHE_WRITEBACK_MODE
+#define EMAC_CACHE_INVALIDATE_FIX
+
+/* ---------------------------------------------------------------
+ * types
+ * --------------------------------------------------------------- */
+#define TRUE		((bool) 1)
+#define FALSE		((bool) 0)
+
+typedef void *emac_net_data_token;
+
+/* ---------------------------------------------------------------
+ * defines
+ * --------------------------------------------------------------- */
+#define EMAC_MULTIPACKET_TX_COMPLETE_NOTIFY
+
+/* NO PHY used in case of external ethernet switches */
+#define CONFIG_EMAC_NOPHY              9999
+
+/* DaVinci specific configuration */
+#define EMAC_BASE_ADDR         IO_ADDRESS(DAVINCI_EMAC_CNTRL_REGS_BASE)
+#define EMAC_WRAPPER_REGS_ADDR IO_ADDRESS(DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE)
+#define EMAC_WRAPPER_RAM_ADDR  IO_ADDRESS(DAVINCI_EMAC_WRAPPER_RAM_BASE)
+#define EMAC_WRAPPER_RAM_SIZE  (8 << 10)
+#define EMAC_MDIO_BASE_ADDR    IO_ADDRESS(DAVINCI_MDIO_CNTRL_REGS_BASE)
+
+#define EMAC_INTERRUPT         13
+#define EMAC_BUS_FREQUENCY     76500000	/* PLL/6 i.e 76.5 MHz */
+#define EMAC_MDIO_FREQUENCY    2200000	/* PHY bus frequency */
+#define EMAC_PHY_MASK          0x2	/* PHY chip is located at address 1 */
+
+/* Note: For DaVinci, Buffer Descriptors are located in Wrapper RAM
+ * (4K).  Half of the Wrapper memory is for RX BD's and other half for
+ * TX BD's
+ */
+#define EMAC_TX_BD_MEM  EMAC_WRAPPER_RAM_ADDR
+#define EMAC_RX_BD_MEM (EMAC_WRAPPER_RAM_ADDR + (EMAC_WRAPPER_RAM_SIZE >> 1))
+
+/* feature macros here */
+
+/* If multi packet Tx complete notifications is enabled (via
+   EMAC_MULTIPACKET_TX_COMPLETE_NOTIFY), Max number of Tx packets that
+   can be notified - the actual number will depend upon user
+   configuration for parameter "maxPktsToProcess" */
+#define EMAC_MAX_TX_COMPLETE_PKTS_TO_NOTIFY    8
+
+
+/* config macros */
+#define EMAC_MAX_INSTANCES                     1
+#define EMAC_MIN_ETHERNET_PKT_SIZE             60
+
+/* max RX fragments calculation - 1500 byte packet and 64 byte
+   buffer. fragments=1500/64=24 */
+#define EMAC_MAX_RX_FRAGMENTS                  24
+
+/* theoratically TX max fragments are equal to 24 */
+#define EMAC_MAX_TX_FRAGMENTS                  8
+
+/* EMAC hardware specific */
+#define EMAC_RESET_CLOCKS_WAIT                 64
+#define EMAC_MAX_TX_CHANNELS                   8
+#define EMAC_MAX_RX_CHANNELS                   8
+#define EMAC_MIN_FREQUENCY_FOR_10MBPS          5500000
+#define EMAC_MIN_FREQUENCY_FOR_100MBPS         55000000
+#define EMAC_MIN_FREQUENCY_FOR_1000MBPS        125000000
+
+/*
+ * The following are EMAC registers which have been removed from the
+ * CPGMAC register map. Thus we access them using macros to avoid
+ * having more CSL register overlay structures for older EMAC register
+ * map.
+ */
+
+/* statistics clear value */
+#define EMAC_NUM_STAT_REGS                     36
+#define EMAC_STAT_CLEAR                        0xFFFFFFFF
+
+/* EMAC all multicast set register value */
+#define EMAC_ALL_MULTI_REG_VALUE               0xFFFFFFFF
+
+/* EMAC number of multicast bits that can be set/cleared - currently
+   64 bits - hash1/2 regs */
+#define EMAC_NUM_MULTICAST_BITS                64
+
+/* EMAC teardown value */
+#define EMAC_TEARDOWN_VALUE                    0xFFFFFFFC
+
+/* TX / RX control bits */
+#define EMAC_TX_CONTROL_TX_ENABLE_VAL          0x1
+#define EMAC_RX_CONTROL_RX_ENABLE_VAL          0x1
+
+/* host interrupt bits */
+#define EMAC_MAC_HOST_ERR_INTMASK_VAL          0x2
+#define EMAC_MAC_STAT_INT_INTMASK_VAL          0x1
+
+/* rx config masks */
+#define EMAC_RX_UNICAST_CLEAR_ALL              0xFF
+
+/* type 0 address filtering macros */
+#define EMAC_TYPE_0_MACSRCADDR0_MASK           (0xFF)
+#define EMAC_TYPE_0_MACSRCADDR0_SHIFT          0
+#define EMAC_TYPE_0_MACSRCADDR1_MASK           (0xFF)
+#define EMAC_TYPE_0_MACSRCADDR1_SHIFT          0
+
+#define EMAC_TYPE_0_MACSRCADDR2_MASK           (0xFF<<24)
+#define EMAC_TYPE_0_MACSRCADDR2_SHIFT          24
+#define EMAC_TYPE_0_MACSRCADDR3_MASK           (0xFF<<16)
+#define EMAC_TYPE_0_MACSRCADDR3_SHIFT          16
+#define EMAC_TYPE_0_MACSRCADDR4_MASK           (0xFF<<8)
+#define EMAC_TYPE_0_MACSRCADDR4_SHIFT          8
+#define EMAC_TYPE_0_MACSRCADDR5_MASK           (0xFF)
+#define EMAC_TYPE_0_MACSRCADDR5_SHIFT          0
+
+/* type 1 address filtering macros */
+#define EMAC_TYPE_1_MACSRCADDR0_MASK           (0xFF<<8)
+#define EMAC_TYPE_1_MACSRCADDR0_SHIFT          8
+#define EMAC_TYPE_1_MACSRCADDR1_MASK           (0xFF)
+#define EMAC_TYPE_1_MACSRCADDR1_SHIFT          0
+
+#define EMAC_TYPE_1_MACSRCADDR2_MASK           (0xFF<<24)
+#define EMAC_TYPE_1_MACSRCADDR2_SHIFT          24
+#define EMAC_TYPE_1_MACSRCADDR3_MASK           (0xFF<<16)
+#define EMAC_TYPE_1_MACSRCADDR3_SHIFT          16
+#define EMAC_TYPE_1_MACSRCADDR4_MASK           (0xFF<<8)
+#define EMAC_TYPE_1_MACSRCADDR4_SHIFT          8
+#define EMAC_TYPE_1_MACSRCADDR5_MASK           (0xFF)
+#define EMAC_TYPE_1_MACSRCADDR5_SHIFT          0
+
+/* CP(G)MAC address filtering bit macros */
+#define CPGMAC_VALID_MASK                      (0x1<<20)
+#define CPGMAC_VALID_SHIFT                     20
+#define CPGMAC_MATCH_FILTER_MASK               (0x1<<19)
+#define CPGMAC_MATCH_FILTER_SHIFT              19
+#define CPGMAC_CHANNEL_MASK                    (0x7<<16)
+#define CPGMAC_CHANNEL_SHIFT                   16
+#define CPGMAC_TYPE_2_3_MACSRCADDR0_MASK       (0xFF<<8)
+#define CPGMAC_TYPE_2_3_MACSRCADDR0_SHIFT      8
+#define CPGMAC_TYPE_2_3_MACSRCADDR1_MASK       (0xFF)
+#define CPGMAC_TYPE_2_3_MACSRCADDR1_SHIFT      0
+
+#define CPGMAC_TYPE_2_3_MACSRCADDR2_MASK       (0xFF<<24)
+#define CPGMAC_TYPE_2_3_MACSRCADDR2_SHIFT      24
+#define CPGMAC_TYPE_2_3_MACSRCADDR3_MASK       (0xFF<<16)
+#define CPGMAC_TYPE_2_3_MACSRCADDR3_SHIFT      16
+#define CPGMAC_TYPE_2_3_MACSRCADDR4_MASK       (0xFF<<8)
+#define CPGMAC_TYPE_2_3_MACSRCADDR4_SHIFT      8
+#define CPGMAC_TYPE_2_3_MACSRCADDR5_MASK       (0xFF)
+#define CPGMAC_TYPE_2_3_MACSRCADDR5_SHIFT      0
+
+/* RX MBP register bit positions */
+#define EMAC_RXMBP_PASSCRC_SHIFT               30
+#define EMAC_RXMBP_PASSCRC_MASK                (0x1 << 30)
+#define EMAC_RXMBP_QOSEN_SHIFT                 29
+#define EMAC_RXMBP_QOSEN_MASK                  (0x1 << 29)
+#define EMAC_RXMBP_NOCHAIN_SHIFT               28
+#define EMAC_RXMBP_NOCHAIN_MASK                (0x1 << 28)
+#define EMAC_RXMBP_CMFEN_SHIFT                 24
+#define EMAC_RXMBP_CMFEN_MASK                  (0x1 << 24)
+#define EMAC_RXMBP_CSFEN_SHIFT                 23
+#define EMAC_RXMBP_CSFEN_MASK                  (0x1 << 23)
+#define EMAC_RXMBP_CEFEN_SHIFT                 22
+#define EMAC_RXMBP_CEFEN_MASK                  (0x1 << 22)
+#define EMAC_RXMBP_CAFEN_SHIFT                 21
+#define EMAC_RXMBP_CAFEN_MASK                  (0x1 << 21)
+#define EMAC_RXMBP_PROMCH_SHIFT                16
+#define EMAC_RXMBP_PROMCH_MASK                 (0x7 << 16)
+#define EMAC_RXMBP_BROADEN_SHIFT               13
+#define EMAC_RXMBP_BROADEN_MASK                (0x1 << 13)
+#define EMAC_RXMBP_BROADCH_SHIFT               8
+#define EMAC_RXMBP_BROADCH_MASK                (0x7 << 8)
+#define EMAC_RXMBP_MULTIEN_SHIFT               5
+#define EMAC_RXMBP_MULTIEN_MASK                (0x1 << 5)
+#define EMAC_RXMBP_MULTICH_SHIFT               0
+#define EMAC_RXMBP_MULTICH_MASK                0x7
+
+#define EMAC_RXMBP_CHMASK                      0x7
+
+/* mac control register bit fields */
+#define EMAC_MACCONTROL_TXSHORTGAPEN_SHIFT     10
+#define EMAC_MACCONTROL_TXSHORTGAPEN_MASK      (0x1 << 10)
+#define EMAC_MACCONTROL_TXPTYPE_SHIFT          9
+#define EMAC_MACCONTROL_TXPTYPE_MASK           (0x1 << 9)
+#define EMAC_MACCONTROL_GIGABITEN_SHIFT        7
+#define EMAC_MACCONTROL_GIGABITEN_MASK         (0x1 << 7)
+#define EMAC_MACCONTROL_TXPACEEN_SHIFT         6
+#define EMAC_MACCONTROL_TXPACEEN_MASK          (0x1 << 6)
+#define EMAC_MACCONTROL_MIIEN_SHIFT            5
+#define EMAC_MACCONTROL_MIIEN_MASK             (0x1 << 5)
+#define EMAC_MACCONTROL_TXFLOWEN_SHIFT         4
+#define EMAC_MACCONTROL_TXFLOWEN_MASK          (0x1 << 4)
+#define EMAC_MACCONTROL_RXFLOWEN_SHIFT         3
+#define EMAC_MACCONTROL_RXFLOWEN_MASK          (0x1 << 3)
+#define EMAC_MACCONTROL_LOOPBKEN_SHIFT         1
+#define EMAC_MACCONTROL_LOOPBKEN_MASK          (0x1 << 1)
+#define EMAC_MACCONTROL_FULLDUPLEXEN_SHIFT     0
+#define EMAC_MACCONTROL_FULLDUPLEXEN_MASK      (0x1)
+
+/* mac_status register */
+#define EMAC_MACSTATUS_TXERRCODE_MASK          0xF00000
+#define EMAC_MACSTATUS_TXERRCODE_SHIFT         20
+#define EMAC_MACSTATUS_TXERRCH_MASK            0x7
+#define EMAC_MACSTATUS_TXERRCH_SHIFT           16
+#define EMAC_MACSTATUS_RXERRCODE_MASK          0xF000
+#define EMAC_MACSTATUS_RXERRCODE_SHIFT         12
+#define EMAC_MACSTATUS_RXERRCH_MASK            0x7
+#define EMAC_MACSTATUS_RXERRCH_SHIFT           8
+
+/* EMAC RX max packet length mask */
+#define EMAC_RX_MAX_LEN_SHIFT                  0
+#define EMAC_RX_MAX_LEN_MASK                   0xFFFF
+
+/* EMAC RX max packet length mask */
+#define EMAC_RX_BUFFER_OFFSET_SHIFT            0
+#define EMAC_RX_BUFFER_OFFSET_MASK             0xFFFF
+
+/* MAC_IN_VECTOR (0x180) register bit fields */
+#define EMAC_MAC_IN_VECTOR_HOST_INT            (0x20000)
+#define EMAC_MAC_IN_VECTOR_STATPEND_INT        (0x10000)
+#define EMAC_MAC_IN_VECTOR_RX_INT_VEC          (0xFF00)
+#define EMAC_MAC_IN_VECTOR_TX_INT_VEC          (0xFF)
+
+/* CPPI bit positions */
+#define EMAC_CPPI_SOP_BIT                      (1 << 31)
+#define EMAC_CPPI_EOP_BIT                      (1 << 30)
+#define EMAC_CPPI_OWNERSHIP_BIT                (1 << 29)
+#define EMAC_CPPI_EOQ_BIT                      (1 << 28)
+#define EMAC_CPPI_TEARDOWN_COMPLETE_BIT        (1 << 27)
+#define EMAC_CPPI_PASS_CRC_BIT                 (1 << 26)
+
+/* defining the macro EMAC_INSTANCE_CODE to 0 so that it can be usable in DDA */
+#define EMAC_INSTANCE_CODE                     0
+#define EMAC_ERROR_CODE                        (EMAC_INSTANCE_CODE << 16)
+#define EMAC_ERROR_INFO                        (EMAC_ERROR_CODE)
+#define EMAC_ERROR_WARNING                     (EMAC_ERROR_CODE | 0x10000000)
+#define EMAC_ERROR_MINOR                       (EMAC_ERROR_CODE | 0x20000000)
+#define EMAC_ERROR_MAJOR                       (EMAC_ERROR_CODE | 0x30000000)
+#define EMAC_ERROR_CRITICAL                    (EMAC_ERROR_CODE | 0x40000000)
+
+/* EMAC success code */
+#define EMAC_SUCCESS                           0
+
+/* EMAC error codes */
+#define EMAC_ERR_DEV_ALREADY_INSTANTIATED(inst_id) \
+  (0x30000000 + ((inst_id) << 16))
+#define EMAC_ERR_DEV_NOT_INSTANTIATED          (EMAC_ERROR_MAJOR + 1)
+#define EMAC_INVALID_PARAM                     (EMAC_ERROR_MAJOR + 2)
+#define EMAC_ERR_TX_CH_INVALID                 (EMAC_ERROR_CRITICAL + 3)
+#define EMAC_ERR_TX_CH_ALREADY_INIT            (EMAC_ERROR_MAJOR + 4)
+#define EMAC_ERR_TX_CH_ALREADY_CLOSED          (EMAC_ERROR_MAJOR + 5)
+#define EMAC_ERR_TX_CH_NOT_OPEN                (EMAC_ERROR_MAJOR + 6)
+#define EMAC_ERR_TX_NO_LINK                    (EMAC_ERROR_MAJOR + 7)
+#define EMAC_ERR_TX_OUT_OF_BD                  (EMAC_ERROR_MAJOR + 8)
+#define EMAC_ERR_RX_CH_INVALID                 (EMAC_ERROR_CRITICAL + 9)
+#define EMAC_ERR_RX_CH_ALREADY_INIT            (EMAC_ERROR_MAJOR + 10)
+#define EMAC_ERR_RX_CH_ALREADY_CLOSED          (EMAC_ERROR_MAJOR + 11)
+#define EMAC_ERR_RX_CH_NOT_OPEN                (EMAC_ERROR_MAJOR + 12)
+#define EMAC_ERR_DEV_ALREADY_CREATED           (EMAC_ERROR_MAJOR + 13)
+#define EMAC_ERR_DEV_NOT_OPEN                  (EMAC_ERROR_MAJOR + 14)
+#define EMAC_ERR_DEV_ALREADY_CLOSED            (EMAC_ERROR_MAJOR + 15)
+#define EMAC_ERR_DEV_ALREADY_OPEN              (EMAC_ERROR_MAJOR + 16)
+#define EMAC_ERR_RX_BUFFER_ALLOC_FAIL          (EMAC_ERROR_CRITICAL + 17)
+
+/*
+ * ioctls
+ */
+#define EMAC_IOCTL_BASE            0
+
+#define EMAC_IOCTL_GET_STATISTICS        (EMAC_IOCTL_BASE + 0)
+#define EMAC_IOCTL_CLR_STATISTICS        (EMAC_IOCTL_BASE + 1)
+#define EMAC_IOCTL_GET_SWVER             (EMAC_IOCTL_BASE + 2)
+#define EMAC_IOCTL_GET_HWVER             (EMAC_IOCTL_BASE + 3)
+#define EMAC_IOCTL_SET_RXCFG             (EMAC_IOCTL_BASE + 4)
+#define EMAC_IOCTL_SET_MACCFG            (EMAC_IOCTL_BASE + 5)
+#define EMAC_IOCTL_GET_STATUS            (EMAC_IOCTL_BASE + 6)
+#define EMAC_IOCTL_READ_PHY_REG          (EMAC_IOCTL_BASE + 7)
+#define EMAC_IOCTL_WRITE_PHY_REG         (EMAC_IOCTL_BASE + 8)
+#define EMAC_IOCTL_MULTICAST_ADDR        (EMAC_IOCTL_BASE + 9)	/* add/delete */
+#define EMAC_IOCTL_ALL_MULTI             (EMAC_IOCTL_BASE + 10)	/* set/clear */
+#define EMAC_IOCTL_TYPE2_3_FILTERING     (EMAC_IOCTL_BASE + 11)
+#define EMAC_IOCTL_SET_MAC_ADDRESS       (EMAC_IOCTL_BASE + 12)
+#define EMAC_IOCTL_IF_COUNTERS		 (EMAC_IOCTL_BASE + 13)
+#define EMAC_IOCTL_ETHER_COUNTERS     	 (EMAC_IOCTL_BASE + 14)
+#define EMAC_IOCTL_IF_PARAMS_UPDT   	 (EMAC_IOCTL_BASE + 15)
+
+#define EMAC_IOCTL_TIMER_START           (EMAC_IOCTL_BASE + 16)
+#define EMAC_IOCTL_TIMER_STOP            (EMAC_IOCTL_BASE + 17)
+#define EMAC_IOCTL_STATUS_UPDATE         (EMAC_IOCTL_BASE + 18)
+#define EMAC_IOCTL_MIB64_CNT_TIMER_START (EMAC_IOCTL_BASE + 19)
+#define EMAC_IOCTL_MIB64_CNT_TIMER_STOP  (EMAC_IOCTL_BASE + 20)
+
+#define EMAC_PRIV_FILTERING              (EMAC_IOCTL_BASE + 21)
+#define EMAC_PRIV_MII_READ               (EMAC_IOCTL_BASE + 22)
+#define EMAC_PRIV_MII_WRITE              (EMAC_IOCTL_BASE + 23)
+#define EMAC_PRIV_GET_STATS              (EMAC_IOCTL_BASE + 24)
+#define EMAC_PRIV_CLR_STATS              (EMAC_IOCTL_BASE + 25)
+#define EMAC_EXTERNAL_SWITCH             (EMAC_IOCTL_BASE + 26)
+
+/*
+ *  MII module port settings
+ *
+ * DDA sets the Phy mode as a combination of the following in "phyMode" parameter
+ * in the init configuration structure
+ */
+#define SNWAY_AUTOMDIX      (1<<16)	/* bit 16 and above not used by MII register */
+#define SNWAY_FD1000        (1<<13)
+#define SNWAY_HD1000        (1<<12)
+#define SNWAY_NOPHY         (1<<10)
+#define SNWAY_LPBK          (1<<9)
+#define SNWAY_FD100         (1<<8)
+#define SNWAY_HD100         (1<<7)
+#define SNWAY_FD10          (1<<6)
+#define SNWAY_HD10          (1<<5)
+#define SNWAY_AUTO          (1<<0)
+#define SNWAY_AUTOALL       (SNWAY_AUTO|SNWAY_FD100|SNWAY_FD10|SNWAY_HD100|SNWAY_HD10)
+
+/**
+ *  DDC Status Ioctl - Error status
+ *
+ *  Note that each error code is a bit position so that multiple
+ *  errors can be clubbed together and passed in a integer value
+ */
+#define EMAC_NO_ERROR          0
+#define EMAC_TX_HOST_ERROR     0x1	/* MSB 8 bits: err code, channel no */
+#define EMAC_RX_HOST_ERROR     0x8	/* LSB 8 bits: err code, channel no */
+
+#define EGRESS_TRAILOR_LEN                  0
+
+#define CFG_START_LINK_SPEED                (SNWAY_AUTOALL)	/* auto nego */
+
+/* defaut configuration values required for passing on to DDC */
+#define EMAC_DEFAULT_MLINK_MASK                        0
+#define EMAC_DEFAULT_PASS_CRC                          FALSE
+#define EMAC_DEFAULT_QOS_ENABLE                        FALSE
+#define EMAC_DEFAULT_NO_BUFFER_CHAINING                FALSE
+#define EMAC_DEFAULT_COPY_MAC_CONTROL_FRAMES_ENABLE    FALSE
+#define EMAC_DEFAULT_COPY_SHORT_FRAMES_ENABLE          FALSE
+#define EMAC_DEFAULT_COPY_ERROR_FRAMES_ENABLE          FALSE
+#define EMAC_DEFAULT_PROMISCOUS_CHANNEL                0
+#define EMAC_DEFAULT_BROADCAST_CHANNEL                 0
+#define EMAC_DEFAULT_MULTICAST_CHANNEL                 0
+#define EMAC_DEFAULT_BUFFER_OFFSET                     0
+#define EMAC_DEFAULT_TX_PRIO_TYPE                      EMAC_TXPRIO_FIXED
+#define EMAC_DEFAULT_TX_SHORT_GAP_ENABLE               FALSE
+#define EMAC_DEFAULT_TX_PACING_ENABLE                  FALSE
+#define EMAC_DEFAULT_MII_ENABLE                        TRUE
+#define EMAC_DEFAULT_TX_FLOW_ENABLE                    FALSE
+#define EMAC_DEFAULT_RX_FLOW_ENABLE                    FALSE
+#define EMAC_DEFAULT_LOOPBACK_ENABLE                   FALSE
+#define EMAC_DEFAULT_FULL_DUPLEX_ENABLE                TRUE
+#define EMAC_DEFAULT_TX_INTERRUPT_DISABLE              TRUE
+#define CONFIG_EMAC_MIB_TIMER_TIMEOUT                  5000	/* 5 seconds */
+
+#define EMAC_DEFAULT_PROMISCOUS_ENABLE                 0
+#define EMAC_DEFAULT_BROADCAST_ENABLE                  1
+#define EMAC_DEFAULT_MULTICAST_ENABLE                  1
+
+/* NOT EXPLICIT SUPPORT PROVIDED AS OF NOW - vlan support in the driver */
+#define EMAC_DEFAULT_VLAN_ENABLE       FALSE
+
+/* system value for ticks per seconds */
+#define EMAC_TICKS_PER_SEC             HZ
+
+/* Extra bytes for Cache alignment of skbuf - should be equal to
+ * processor cache line size - in case of ARM926 its 32 bytes
+ */
+#define EMAC_DEFAULT_EXTRA_RXBUF_SIZE  32
+
+/* default max frame size = 1522 = 1500 byte data + 14 byte eth header
+   + 4 byte checksum + 4 byte vlan tag + 32 bytes for cache
+   alignment */
+#define EMAC_DEFAULT_MAX_FRAME_SIZE    (1500 + 14 + 4 + 4 + EGRESS_TRAILOR_LEN + EMAC_DEFAULT_EXTRA_RXBUF_SIZE)
+
+/* default number of TX channels */
+#define EMAC_DEFAULT_NUM_TX_CHANNELS   1
+
+/* default TX channel number */
+#define EMAC_DEFAULT_TX_CHANNEL        0
+
+/* default TX number of BD's/buffers */
+#define EMAC_DEFAULT_TX_NUM_BD         128
+
+/* default TX max service BD's */
+#define EMAC_DEFAULT_TX_MAX_SERVICE    32
+
+/* default number of RX channels */
+#define EMAC_DEFAULT_NUM_RX_CHANNELS   1
+
+/* default RX channel number */
+#define EMAC_DEFAULT_RX_CHANNEL        0
+
+#define EMAC_DEFAULT_RX_NUM_BD         128
+
+/* default RX max service BD's */
+#define EMAC_DEFAULT_RX_MAX_SERVICE    32	/* should = netdev->weight */
+
+#if ((EMAC_DEFAULT_TX_NUM_BD +EMAC_DEFAULT_RX_NUM_BD)  > 256)
+#error "Error. DaVinci has space for no more than 256 TX+RX BD's"
+#endif
+
+/*
+ * Size of EMAC peripheral footprint in memory that needs to be
+ * reserved in Linux Note that this value is actually a hardware
+ * memory footprint value taken from the specs and ideally should have
+ * been in the csl files. Keeping it for convinience since EMAC
+ * peripheral footprint will not change unless the peripheral itself
+ * changes drastically and it will be called with a different name and
+ * will have a different driver anyway
+ *
+ * For Davinci size = control regs (4k) + wrapper regs (4k) + wrapper
+ * RAM (8k) + mdio regs (2k)
+ */
+#define EMAC_DEFAULT_EMAC_SIZE        0x4800
+
+/* ENV variable names for obtaining MAC addresses */
+#define EMAC_MAC_ADDR_A    "maca"
+#define EMAC_MAC_ADDR_B    "macb"
+#define EMAC_MAC_ADDR_C    "macc"
+#define EMAC_MAC_ADDR_D    "macd"
+#define EMAC_MAC_ADDR_E    "mace"
+#define EMAC_MAC_ADDR_F    "macf"
+
+/* Maximum multicast addresses list to be handled by the driver - If
+ * this is not restricted then the driver will spend considerable time
+ * in handling multicast lists
+ */
+#define EMAC_DEFAULT_MAX_MULTICAST_ADDRESSES   64
+
+#define NETDEV_PRIV(net_dev)  netdev_priv(net_dev)
+#define FREE_NETDEV(net_dev)  free_netdev(net_dev)
+
+#define dbg_print if (emac_debug_mode) printk
+#define err_print printk
+
+/* misc error codes */
+#define EMAC_INTERNAL_FAILURE  -1
+
+/* LED codes required for controlling LED's */
+#define EMAC_LINK_OFF          0
+#define EMAC_LINK_ON           1
+#define EMAC_SPEED_100         2
+#define EMAC_SPEED_10          3
+#define EMAC_FULL_DPLX         4
+#define EMAC_HALF_DPLX         5
+#define EMAC_TX_ACTIVITY       6
+#define EMAC_RX_ACTIVITY       7
+
+/*
+ * L3 Alignment mechanism: The below given macro returns the number of
+ * bytes required to align the given size to a L3 frame 4 byte
+ * boundry. This is typically required to add 2 bytes to the ethernet
+ * frame start to make sure the IP header (L3) is aligned on a 4 byte
+ * boundry
+ */
+static char emac_L3_align[] = { 0x02, 0x01, 0x00, 0x03 };
+
+#define EMAC_L3_ALIGN(size)    emac_L3_align[(size) & 0x3]
+
+/* 4 Byte alignment for skb's:
+ *
+ * Currently Skb's dont need to be on a 4 byte boundry, but other OS's
+ * have such requirements Just to make sure we comply if there is any
+ * such requirement on SKB's in future, we align it on a 4 byte
+ * boundry.
+ */
+char emac_4byte_align[] = { 0x0, 0x03, 0x02, 0x1 };
+
+#define EMAC_4BYTE_ALIGN(size) emac_4byte_align[(size) & 0x3]
+
+#define EMAC_DEBUG_FUNCTION_ENTRY          (0x1 << 1)
+#define EMAC_DEBUG_FUNCTION_EXIT           (0x1 << 2)
+#define EMAC_DEBUG_BUSY_FUNCTION_ENTRY     (0x1 << 3)
+#define EMAC_DEBUG_BUSY_FUNCTION_EXIT      (0x1 << 4)
+#define EMAC_DEBUG_TX                      (0x1 << 6)
+#define EMAC_DEBUG_RX                      (0x1 << 7)
+#define EMAC_DEBUG_PORT_UPDATE             (0x1 << 8)
+#define EMAC_DEBUG_MII                     (0x1 << 9)
+#define EMAC_DEBUG_TEARDOWN                (0x1 << 10)
+
+/* Debug flags
+ *
+ * IMPORTANT NOTE: The debug flags need to be enabled carefully as it
+ * could flood the console/sink point of the debug traces and also
+ * affect the functionality of the overall system
+ */
+#ifdef EMAC_DEBUG
+#define LOG(lvl, format, args...) \
+  printk(lvl "%s:%d[%d]" format, __FUNCTION__, __LINE__, \
+         dev->init_cfg.inst_id, ##args)
+#define LOGERR(format, args...) LOG(KERN_ERR, format, ##args)
+#define LOGMSG(flag, format, args... )	\
+  do { if (flag & emac_debug) LOG(KERN_DEBUG, #flag format, ##args); } while(0)
+#define DBG(format, args...) \
+  if (emac_debug_mode) printk(KERN_DEBUG "davinci_emac: " format, ##args)
+#define ERR(format, args...) \
+  printk(KERN_ERR "ERROR: davinci_emac: " format, ##args)
+
+#else
+#define LOGERR(format, args...)
+#define LOGMSG(flag, format, args... )
+#endif
+
+/* DDC internal macros */
+#define EMAC_RX_BD_BUF_SIZE                    0xFFFF;
+#define EMAC_BD_LENGTH_FOR_CACHE               16	/* only CPPI bytes */
+#define EMAC_RX_BD_PKT_LENGTH_MASK             0xFFFF
+
+#define CFG_START_LINK_SPEED                   (SNWAY_AUTOALL)	/* auto nego */
+
+/* defaut configuration values required for passing on to DDC */
+#define EMAC_DEFAULT_MLINK_MASK                        0
+#define EMAC_DEFAULT_PASS_CRC                          FALSE
+#define EMAC_DEFAULT_QOS_ENABLE                        FALSE
+#define EMAC_DEFAULT_NO_BUFFER_CHAINING                FALSE
+#define EMAC_DEFAULT_COPY_MAC_CONTROL_FRAMES_ENABLE    FALSE
+#define EMAC_DEFAULT_COPY_SHORT_FRAMES_ENABLE          FALSE
+#define EMAC_DEFAULT_COPY_ERROR_FRAMES_ENABLE          FALSE
+#define EMAC_DEFAULT_PROMISCOUS_CHANNEL                0
+#define EMAC_DEFAULT_BROADCAST_CHANNEL                 0
+#define EMAC_DEFAULT_MULTICAST_CHANNEL                 0
+#define EMAC_DEFAULT_BUFFER_OFFSET                     0
+#define EMAC_DEFAULT_TX_PRIO_TYPE                      EMAC_TXPRIO_FIXED
+#define EMAC_DEFAULT_TX_SHORT_GAP_ENABLE               FALSE
+#define EMAC_DEFAULT_TX_PACING_ENABLE                  FALSE
+#define EMAC_DEFAULT_MII_ENABLE                        TRUE
+#define EMAC_DEFAULT_TX_FLOW_ENABLE                    FALSE
+#define EMAC_DEFAULT_RX_FLOW_ENABLE                    FALSE
+#define EMAC_DEFAULT_LOOPBACK_ENABLE                   FALSE
+#define EMAC_DEFAULT_FULL_DUPLEX_ENABLE                TRUE
+#define EMAC_DEFAULT_TX_INTERRUPT_DISABLE              TRUE
+#define CONFIG_EMAC_MIB_TIMER_TIMEOUT                  5000	/* 5 sec */
+
+#define EMAC_DEFAULT_PROMISCOUS_ENABLE                 0
+#define EMAC_DEFAULT_BROADCAST_ENABLE                  1
+#define EMAC_DEFAULT_MULTICAST_ENABLE                  1
+
+/* ---------------------------------------------------------------
+ * structs, enums
+ * --------------------------------------------------------------- */
+typedef enum {
+	DRV_CREATED,
+	DRV_INITIALIZED,
+	DRV_OPENED,
+	DRV_CLOSED,
+	DRV_DEINITIALIZED,
+	DRV_POWERED_DOWN,
+} emac_drv_state;
+
+/**
+ *  Network Buffer Object
+ *
+ *  Holds attributes of a buffer/fragment
+ *
+ *  Send: Usually when the buffers are allocated by DDA, the
+ *  Start of Packet token will be the handle to the whole packet. This
+ *  token/handle should be good enough to free the packet or return to
+ *  its pool. When the buffers are allocated by DDC, typically token
+ *  for each buffer needs to be indicated (TxComplete) rather than
+ *  only the Start of Packet token.
+ *
+ *  Receive: For each buffer the token will be a handle to the buffer
+ *  that can be used by the allocater (DDA or DDC) of the buffer to
+ *  free it or return to a pool.
+ */
+typedef struct {
+	emac_net_data_token buf_token;
+	char *data_ptr;
+	int length;
+} net_buf_obj;
+
+/**
+ *  Network Packet Object
+ *
+ *  Holds attributes of a network packet (NetBufObjs and packet size).
+ */
+typedef struct {
+	emac_net_data_token pkt_token;	/* data token may hold tx/rx chan id */
+	net_buf_obj *buf_list;	/* array of network buffer objects */
+	int num_bufs;		/* number of network buffer objects */
+	int pkt_length;		/* packet length (number of bytes) */
+} net_pkt_obj;
+
+/**
+ *  Net Channel State
+ *
+ *  State of the channel (initialized, about to be closed, closed etc
+ */
+typedef enum {
+	NET_CH_DIR_TX = 0,	/* transmit only */
+	NET_CH_DIR_RX,		/* receive only */
+	NET_CH_DIR_BIDIRECTIONAL,	/* bidirectonaly - TX/RX  */
+	NET_CH_DIR_UNDEFINED	/* not defined */
+} net_ch_dir;
+
+/**
+ *  Net Channel State
+ *
+ *  State of the channel (initialized, about to be closed, closed etc
+ */
+typedef enum {
+	NET_CH_UNINITIALIZED = 0,
+	NET_CH_INITIALIZED,
+	NET_CH_OPENED,
+	NET_CH_CLOSE_IN_PROGRESS,
+	NET_CH_CLOSED
+} net_ch_state;
+
+/**
+ * EMAC Peripheral Device Register Memory Layout structure
+ *
+ * The structure instance variable points to CP(G)MAC register space in
+ * SOC memory map directly.
+ * This is a template only, no memory is ever allocated for this!
+ */
+typedef struct {
+	u32 tx_id_ver;
+	u32 tx_control;
+	u32 tx_teardown;
+	u32 reserved1;
+	u32 rx_id_ver;
+	u32 rx_control;
+	u32 rx_teardown;
+	u32 pad2[25];
+	u32 tx_int_stat_raw;
+	u32 tx_int_stat_masked;
+	u32 tx_int_mask_set;
+	u32 tx_int_mask_clear;
+	u32 mac_in_vector;
+	u32 mac_EOI_vector;
+	u32 pad3[2];
+	u32 rx_int_stat_raw;
+	u32 rx_int_stat_masked;
+	u32 rx_int_mask_set;
+	u32 rx_int_mask_clear;
+	u32 mac_int_stat_raw;
+	u32 mac_int_stat_masked;
+	u32 mac_int_mask_set;
+	u32 mac_int_mask_clear;
+	u32 pad4[16];
+	u32 rx_MBP_enable;
+	u32 rx_unicast_set;
+	u32 rx_unicast_clear;
+	u32 rx_maxlen;
+	u32 rx_buffer_offset;
+	u32 rx_filter_low_thresh;
+	u32 pad5[2];
+	u32 rx_flow_thresh[8];
+	u32 rx_free_buffer[8];
+	u32 mac_control;
+	u32 mac_status;
+	u32 EMControl;
+	u32 fifo_control;	/* CP(G)MAC added register */
+	u32 mac_cfig;		/* CP(G)MAC added register */
+	u32 soft_reset;		/* CP(G)MAC 2.6 added register */
+	u32 pad6[22];
+	u32 mac_src_addr_lo;	/* CP(G)MAC modified register */
+	u32 mac_src_addr_hi;	/* CP(G)MAC modified register */
+	u32 mac_hash1;
+	u32 mac_hash2;
+	u32 boff_test;
+	u32 tpace_test;		/* CP(G)MAC modified register */
+	u32 rx_pause;
+	u32 tx_pause;
+	u32 pad7[4];
+	u32 rx_good_frames;
+	u32 rx_broadcast_frames;
+	u32 rx_multicast_frames;
+	u32 rx_pause_frames;
+	u32 rx_crcerrors;
+	u32 rx_align_code_errors;
+	u32 rx_oversized_frames;
+	u32 rx_jabber_frames;
+	u32 rx_undersized_frames;
+	u32 rx_fragments;
+	u32 rx_filtered_frames;
+	u32 rx_qos_filtered_frames;
+	u32 rx_octets;
+	u32 tx_good_frames;
+	u32 tx_broadcast_frames;
+	u32 tx_multicast_frames;
+	u32 tx_pause_frames;
+	u32 tx_deferred_frames;
+	u32 tx_collision_frames;
+	u32 tx_single_coll_frames;
+	u32 tx_mult_coll_frames;
+	u32 tx_excessive_collisions;
+	u32 tx_late_collisions;
+	u32 tx_underrun;
+	u32 tx_carrier_sense_errors;
+	u32 tx_octets;
+	u32 reg64octet_frames;
+	u32 reg65t127octet_frames;
+	u32 reg128t255octet_frames;
+	u32 reg256t511octet_frames;
+	u32 reg512t1023octet_frames;
+	u32 reg1024t_upoctet_frames;
+	u32 net_octets;
+	u32 rx_sof_overruns;
+	u32 rx_mof_overruns;
+	u32 rx_dma_overruns;
+	u32 pad8[156];		/* CP(G)MAC modified register */
+	u32 mac_addr_lo;	/* CP(G)MAC added register */
+	u32 mac_addr_hi;	/* CP(G)MAC added register */
+	u32 mac_index;		/* CP(G)MAC added register */
+	u32 pad9[61];		/* CP(G)MAC modified register */
+	u32 tx_HDP[8];
+	u32 rx_HDP[8];
+	u32 tx_CP[8];
+	u32 rx_CP[8];
+} emac_regs;
+typedef volatile emac_regs *emac_regs_ovly;
+
+/**
+ *  EMAC Peripheral Device Register Enumerations
+ */
+typedef enum {
+	tx_id_ver = 0,
+	tx_control,
+	tx_teardown,
+	rx_id_ver = 4,
+	rx_control,
+	rx_teardown,
+	rx_MBP_enable = 64,
+	rx_unicast_set,
+	rx_unicast_clear,
+	rx_maxlen,
+	rx_buffer_offset,
+
+	rx_filter_low_thresh,
+	rx0_flow_thresh = 72,
+	rx1_flow_thresh,
+	rx2_flow_thresh,
+	rx3_flow_thresh,
+	rx4_flow_thresh,
+
+	rx5_flow_thresh,
+	rx6_flow_thresh,
+	rx7_flow_thresh,
+	rx0_free_buffer,
+
+	rx1_free_buffer,
+	rx2_free_buffer,
+	rx3_free_buffer,
+	rx4_free_buffer,
+
+	rx5_free_buffer,
+	rx6_free_buffer,
+	rx7_free_buffer,
+	mac_control,
+	mac_status,
+
+	EMControl,
+	tx_fifo_control,
+	tx_int_stat_raw,
+	tx_int_stat_masked,
+
+	tx_int_mask_set,
+	tx_int_mask_clear,
+	mac_in_vector,
+	mac_EOI_vector,
+	mac_cfig,
+
+	rx_int_stat_raw = 100,
+	rx_int_stat_masked,
+	rx_int_mask_set,
+	rx_int_mask_clear,
+	mac_int_stat_raw,
+
+	mac_int_stat_masked,
+	mac_int_mask_set,
+	mac_int_mask_clear,
+	mac_src_addr_lo = 116,
+	mac_src_addr_hi,
+	mac_hash1,
+	mac_hash2,
+	boff_test,
+	tpace_test,
+	rx_pause,
+
+	tx_pause,
+	rx_good_frames = 128,
+	rx_broadcast_frames,
+	rx_multicast_frames,
+	rx_pause_frames,
+	rx_crcerrors,
+
+	rx_align_code_errors,
+	rx_oversized_frames,
+	rx_jabber_frames,
+	rx_undersized_frames,
+
+	rx_fragments,
+	rx_filtered_frames,
+	rx_qos_filtered_frames,
+	rx_octets,
+
+	tx_good_frames,
+	tx_broadcast_frames,
+	tx_multicast_frames,
+	tx_pause_frames,
+
+	tx_deferred_frames,
+	tx_collision_frames,
+	tx_single_coll_frames,
+	tx_mult_coll_frames,
+
+	tx_excessive_collisions,
+	tx_late_collisions,
+	tx_underrun,
+	tx_carrier_sense_errors,
+
+	tx_octets,
+	reg64octet_frames,
+	reg65t127octet_frames,
+	reg128t255octet_frames,
+
+	reg256t511octet_frames,
+	reg512t1023octet_frames,
+	reg1024t_upoctet_frames,
+
+	net_octets,
+	rx_sof_overruns,
+	rx_mof_overruns,
+	rx_dma_overruns,
+
+	RX_FIFO_processor_test_access = 192,	/* first word of RX FIFO */
+	TX_FIFO_processor_test_access = 256,	/* first word of TX FIFO */
+	mac_addr_lo = 320,
+	mac_addr_hi,
+	mac_index,
+	tx0_HDP = 384,
+	tx1_HDP,
+	tx2_HDP,
+	tx3_HDP,
+	tx4_HDP,
+	tx5_HDP,
+	tx6_HDP,
+
+	tx7_HDP,
+	rx0_HDP,
+	rx1_HDP,
+	rx2_HDP,
+	rx3_HDP,
+	rx4_HDP,
+
+	rx5_HDP,
+	rx6_HDP,
+	rx7_HDP,
+	tx0_CP,
+	tx1_CP,
+	tx2_CP,
+	tx3_CP,
+
+	tx4_CP,
+	tx5_CP,
+	tx6_CP,
+	tx7_CP,
+	rx0_CP,
+	rx1_CP,
+	rx2_CP,
+
+	rx3_CP,
+	rx4_CP,
+	rx5_CP,
+	rx6_CP,
+	rx7_CP,
+	stateram_test_access = 448	/* first word of state RAM */
+} emac_reg_ids;
+
+/**
+ *  EMAC Addressing Type
+ *
+ *  Addressing type based upon cfig register. For EMAC peripheral cfig
+ *  register reads a value of 0 i.e Type 0 addressing
+ */
+typedef enum {
+	RX_ADDR_TYPE0 = 0,	/* old style used in (EMAC) */
+	RX_ADDR_TYPE1 = 1,	/* new CPGMAC style */
+	RX_ADDR_TYPE2 = 2,	/* new CPGMAC "filtering" style */
+	RX_ADDR_TYPE3 = 3	/* new CPGMAC "filtering" style */
+} emac_rx_addr_type;
+
+/**
+ *  EMAC Single Multicast Ioctl - EMAC_IOCTL_MULTICAST_ADDR operations
+ *
+ *  Add/Del operations for adding/deleting a single multicast address
+ */
+typedef enum {
+	EMAC_MULTICAST_ADD = 0,
+	EMAC_MULTICAST_DEL
+} emac_single_multi_oper;
+
+/**
+ *  EMAC All Multicast Ioctl - EMAC_IOCTL_ALL_MULTI operations
+ *
+ *  Set/Clear all multicast operation
+ */
+typedef enum {
+	EMAC_ALL_MULTI_SET = 0,
+	EMAC_ALL_MULTI_CLR
+} emac_all_multi_oper;
+
+/**
+ * MII Read/Write PHY register
+ *
+ * Parameters to read/write a PHY register via MII interface
+ */
+typedef struct {
+	u32 phy_num;		/* phy number to be read/written */
+	u32 reg_addr;		/* register to be read/written */
+	u32 data;		/* data to be read/written */
+} emac_phy_params;
+
+/**
+ * MAC  Address params
+ *
+ * Parameters for Configuring Mac address
+ */
+typedef struct {
+	u32 channel;
+	char *mac_address;
+} emac_address_params;
+
+/**
+ * Type 2/3 Addressing
+ *
+ * Parameters for programming CFIG 2/3 addressing mode
+ *
+ */
+typedef struct {
+	u32 channel;		/* channel to which this filtering params apply */
+	char *mac_address;	/* mac address for filtering */
+	int index;		/* index of filtering list to update */
+	bool valid;		/* entry valid */
+	int match;		/* entry matching  */
+} emac_type2_3_addr_filter_params;
+
+/**
+ * EMAC Hardware Statistics
+ *
+ * Statistics counters provided by EMAC Hardware. The names of the
+ * counters in this structure are of "MIB style" and corrospond
+ * directly to the hardware counters provided by EMAC
+ */
+typedef struct {
+	u32 if_in_good_frames;
+	u32 if_in_broadcasts;
+	u32 if_in_multicasts;
+	u32 if_in_pause_frames;
+	u32 if_in_crcerrors;
+	u32 if_in_align_code_errors;
+	u32 if_in_oversized_frames;
+	u32 if_in_jabber_frames;
+	u32 if_in_undersized_frames;
+	u32 if_in_fragments;
+	u32 if_in_filtered_frames;
+	u32 if_in_qos_filtered_frames;
+	u32 if_in_octets;
+	u32 if_out_good_frames;
+	u32 if_out_broadcasts;
+	u32 if_out_multicasts;
+	u32 if_out_pause_frames;
+	u32 if_deferred_transmissions;
+	u32 if_collision_frames;
+	u32 if_single_collision_frames;
+	u32 if_multiple_collision_frames;
+	u32 if_excessive_collision_frames;
+	u32 if_late_collisions;
+	u32 if_out_underrun;
+	u32 if_carrier_sense_errors;
+	u32 if_out_octets;
+	u32 if64octet_frames;
+	u32 if65to127octet_frames;
+	u32 if128to255octet_frames;
+	u32 if256to511octet_frames;
+	u32 if512to1023octet_frames;
+	u32 if1024to_upoctet_frames;
+	u32 if_net_octets;
+	u32 if_rx_sof_overruns;
+	u32 if_rx_mof_overruns;
+	u32 if_rx_dmaoverruns;
+} emac_hw_statistics;
+
+/**************************************************************************
+ *                 MIB-2 Common MIB Constants                             *
+ **************************************************************************/
+#define MIB2_TRUTH_VALUE_TRUE  		1
+#define MIB2_TRUTH_VALUE_FALSE  	2
+
+/* MIB-2 interface admin/oper status values  */
+/* device is in operational status unless status is down. */
+#define MIB2_STATUS_UP     	   1
+#define MIB2_STATUS_DOWN   	   2
+#define MIB2_STATUS_TEST   	   3
+#define MIB2_STATUS_UNKNOWN	   4
+#define MIB2_STATUS_DORMANT	   5
+
+#define TI_SIOC_OFFSET 0
+
+/* definitions for interface group MIB variables: GET */
+#define TI_SIOCGINTFCOUNTERS     (TI_SIOC_OFFSET) + 0x01
+#define TI_SIOCGINTFPARAMS       (TI_SIOC_OFFSET) + 0x02
+
+/* SET command definitions */
+#define TI_SIOCSINTFADMINSTATUS  (TI_SIOC_OFFSET) + 0x03
+
+/* definitions for ether-like group MIB variables: GET  */
+#define TI_SIOCGETHERCOUNTERS    (TI_SIOC_OFFSET) + 0x04
+#define TI_SIOCGETHERPARAMS      (TI_SIOC_OFFSET) + 0x05
+
+/* defines MIB II INTERFACE objects */
+struct mib2_if_counters {
+	unsigned long in_bytes_low;
+	unsigned long in_bytes_high;
+	unsigned long in_unicast_pkts_low;
+	unsigned long in_unicast_pkts_high;
+	unsigned long in_multicast_pkts_low;
+	unsigned long in_multicast_pkts_high;
+	unsigned long in_broadcast_pkts_low;
+	unsigned long in_broadcast_pkts_high;
+	unsigned long in_discard_pkts;
+	unsigned long in_error_pkts;
+	unsigned long in_unknown_prot_pkts;
+	unsigned long out_bytes_low;
+	unsigned long out_bytes_high;
+	unsigned long out_unicast_pkts_low;
+	unsigned long out_unicast_pkts_high;
+	unsigned long out_multicast_pkts_low;
+	unsigned long out_multicast_pkts_high;
+	unsigned long out_broadcast_pkts_low;
+	unsigned long out_broadcast_pkts_high;
+	unsigned long out_discard_pkts;
+	unsigned long out_error_pkts;
+};
+
+struct mib2_if_hccounters {
+	struct mib2_if_counters mib2if_counter;
+	unsigned long long in_bytes_hc;
+	unsigned long long in_unicast_pkts_hc;
+	unsigned long long in_multicast_pkts_hc;
+	unsigned long long in_broadcast_pkts_hc;
+	unsigned long long out_bytes_hc;
+	unsigned long long out_unicast_pkts_hc;
+	unsigned long long out_multicast_pkts_hc;
+	unsigned long long out_broadcast_pkts_hc;
+	unsigned long long in_bytes;
+	unsigned long long in_unicast_pkts;
+	unsigned long long in_multicast_pkts;
+	unsigned long long in_broadcast_pkts;
+	unsigned long long out_bytes;
+	unsigned long long out_unicast_pkts;
+	unsigned long long out_multicast_pkts;
+	unsigned long long out_broadcast_pkts;
+};
+
+struct mib2_if_params {
+	unsigned long if_speed;	/* speed in bits per second */
+	unsigned long if_high_speed;	/* speed in mega-bits per second */
+	long if_oper_status;
+	long if_promiscuous_mode;
+};
+
+struct mib2_if_command {
+	long if_admin_status;	/* desired interface state */
+};
+
+/* ether_like-MIB constants */
+#define	MIB2_UNKNOWN_DUPLEX     1
+#define	MIB2_HALF_DUPLEX 	2
+#define	MIB2_FULL_DUPLEX	3
+
+/* ioctl/cmd value to be used by snmpd like applications */
+#define SIOTIMIB2   SIOCDEVPRIVATE + 1
+
+/* defines MIB II ether_like-MIB  objects */
+struct mib2_phy_counters {
+	unsigned long eth_alignment_errors;
+	unsigned long eth_fcserrors;
+	unsigned long eth_single_collisions;
+	unsigned long eth_multiple_collisions;
+	unsigned long eth_sqetest_errors;
+	unsigned long eth_deferred_tx_frames;
+	unsigned long eth_late_collisions;
+	unsigned long eth_excessive_collisions;
+	unsigned long eth_internal_mac_tx_errors;
+	unsigned long eth_carrier_sense_errors;
+	unsigned long eth_too_long_rx_frames;
+	unsigned long eth_internal_mac_rx_errors;
+	unsigned long eth_symbol_errors;
+};
+
+struct mib2_eth_params {
+	long eth_duplex_status;	/* current emac duplex status */
+};
+
+typedef struct {
+	unsigned long cmd;
+	unsigned long port;
+	void *data;
+} TI_SNMP_CMD_T;
+
+/**
+ *  DDC Status values
+ *
+ * Provides status of the device - error status, phy status etc
+ *
+ */
+typedef struct {
+	u32 hw_status;
+	u32 hw_err_info;
+	u32 phy_linked;		/* link status: 1=linked, 0=no link */
+	u32 phy_duplex;		/* duplex status: 3=full duplex, 2=half duplex */
+
+	u32 phy_speed;		/* link speed = 10, 100, 1000 */
+	u32 phy_num;		/* phy number - useful if phy number is discovered */
+} emac_status;
+
+/**
+ *  EMAC Channel Config Info
+ *
+ *  Common to both TX/RX
+ * Used to pass channel config info from DDA to DDC for EMAC channels
+ */
+typedef struct {
+	int ch_num;		/* DDC_net_ch_info: channel number */
+	net_ch_dir ch_dir;	/* DDC_net_ch_info: channel direction */
+	net_ch_state ch_state;	/* DDC_net_ch_info: channel state */
+	int num_bd;		/* number of BD (& buffers for RX) */
+	int service_max;	/* maximum BD's processed in one go */
+	int buf_size;		/* buffer size (applicable for RX only) */
+} emac_ch_info;
+
+/**
+ *  EMAC RX configuration
+ *
+ *  This data structure configures the RX module of the device
+ */
+typedef struct {
+	bool pass_crc;		/* pass CRC bytes to packet memory */
+	bool qos_enable;	/* receive qo_s enable ? */
+	bool no_buffer_chaining;	/* DEBUG ONLY - ALWAYS SET TO FALSE */
+	bool copy_maccontrol_frames_enable;
+	bool copy_short_frames_enable;
+	bool copy_error_frames_enable;
+	bool promiscous_enable;
+	u32 promiscous_channel;	/* promiscous receive channel */
+	bool broadcast_enable;	/* receive broadcast frames ? */
+	u32 broadcast_channel;	/* broadcast receive channel */
+	bool multicast_enable;	/* receive multicast frames ? */
+	u32 multicast_channel;	/* multicast receive channel */
+	u32 max_rx_pkt_length;	/* max receive packet length */
+	u32 buffer_offset;	/* buffer offset for all RX channels */
+} emac_rx_config;
+
+/**
+ *  Transmit Queue priority type
+ *
+ *  Enums for transmit queue priority type - fixed/round robin
+ *  available in hardware
+ */
+typedef enum {
+	EMAC_TXPRIO_ROUND_ROBIN = 0,
+	EMAC_TXPRIO_FIXED = 1
+} emac_tx_queue_priority_type;
+
+/**
+ *  EMAC MAC configuration
+ *
+ *  This data structure configures the MAC module parameters of the device
+ */
+typedef struct {
+	emac_tx_queue_priority_type p_type;
+	bool tx_short_gap_enable;
+	bool giga_bit_enable;
+	bool tx_pacing_enable;
+	bool mii_enable;	/* DEBUG ONLY - ALWAYS SET TO TRUE */
+	bool tx_flow_enable;
+	bool rx_flow_enable;
+	bool loopback_enable;
+	bool full_duplex_enable;	/* DEBUG ONLY - based upon phy_mode */
+	bool tx_interrupt_disable;
+} emac_mac_config;
+
+/**
+ *  EMAC Init Configuration
+ *
+ *  Configuration information provided to DDC layer during
+ *  initialization.  DDA gets the config information from the OS/PAL
+ *  layer and passes the relevant config to the DDC during
+ *  initialization. The config info can come from various sources -
+ *  static compiled in info, boot time (ENV, Flash) info etc.
+ */
+typedef struct {
+	u32 inst_id;
+	u32 num_tx_channels;
+	u32 num_rx_channels;
+	u32 emac_bus_frequency;
+	u32 base_address;
+	u32 e_wrap_base_address;
+	u32 intr_line;
+	u32 reset_line;
+	u32 mdio_base_address;
+	u32 mdio_reset_line;
+	u32 mdio_intr_line;
+	u32 phy_mask;
+	u32 MLink_mask;
+	u32 mdio_bus_frequency;
+	u32 mdio_clock_frequency;
+	u32 mdio_tick_msec;
+	u32 mib64cnt_msec;
+	u32 phy_mode;
+	emac_rx_config rx_cfg;
+	emac_mac_config mac_cfg;
+} emac_init_config;
+
+typedef struct {
+	u32 rx_pkts;		/* number of rx pkts to be processed */
+	u32 tx_pkts;		/* number of tx pkts to be processed */
+	u32 ret_rx_pkts;	/* number of rx pkts processed */
+	u32 ret_tx_pkts;	/* number of tx pkts processed */
+} rx_tx_params;
+
+/*
+ *  EMAC Private Ioctl Structure
+ *
+ * Private Ioctl commands provided by the EMAC Linux Driver use this
+ * structure
+ */
+typedef struct {
+	unsigned int cmd;
+	void *data;
+} emac_drv_priv_ioctl;
+
+/*
+ *  EMAC DDA maintained statistics
+ *
+ * Driver maintained statistics (apart from Hardware statistics)
+ */
+typedef struct {
+	unsigned long tx_discards;
+	unsigned long rx_discards;
+	unsigned long start_tick;
+} emac_drv_stats;
+
+/**************************************************************************
+ * Register Overlay Structure
+ **************************************************************************/
+typedef struct {
+	u32 RSVD0;
+	u32 EWCTL;
+	u32 EWINTTCNT;
+} ewrap_regs;
+
+/*
+ *  TX Buffer Descriptor
+ *
+ *  CPPI 3.0 TX BD structure specific to EMAC.
+ */
+typedef struct {
+	int h_next;		/* next buffer descriptor pointer */
+	int buff_ptr;		/* data buffer pointer */
+	int off_b_len;		/* (buffer_offset_16)(buffer_length_16) */
+	int mode;		/* SOP, EOP, ownership, EOQ, teardown,
+				 * Qstarv, length */
+	void *next;		/* next TX buffer descriptor (linked list) */
+	emac_net_data_token buf_token;
+	void *eop_bd;		/* pointer to end of packet BD */
+} emac_tx_bd;
+
+/* forward declaration */
+typedef struct _emac_rx_cppi_ch_t emac_rx_cppi_ch;
+
+/**
+ *  RX Buffer Descriptor
+ *
+ *  CPPI 3.0 RX BD structure specific to EMAC.
+ */
+typedef struct {
+	int h_next;		/* next (hardware) buffer descriptor pointer */
+	int buff_ptr;		/* data buffer pointer */
+	int off_b_len;		/* (buffer_offset_16)(buffer_length_16) */
+	int mode;		/* SOP, EOP, ownership, EOQ, teardown,
+				 * Q starv, length */
+	void *next;		/* pointer to the next RX buffer in BD queue */
+	void *data_ptr;		/* virtual address of the buffer allocated */
+	emac_net_data_token buf_token;
+	emac_rx_cppi_ch *rx_cppi;
+} emac_rx_bd;
+
+/**
+ *  TX Channel Control Structure
+ *
+ *  Used by EMAC DDC code to process TX Buffer Descriptors
+ */
+typedef struct {
+	/** configuration info */
+	emac_ch_info ch_info;	/* channel config/info */
+
+	/* CPPI specific */
+	u32 alloc_size;		/* BD pool allocated memory size */
+	char *bd_mem;		/* buffer descriptor memory pointer */
+	emac_tx_bd *bd_pool_head;	/* free BD pool head */
+	emac_tx_bd *active_queue_head;	/* head of active packet queue */
+	emac_tx_bd *active_queue_tail;	/* last hardware BD written */
+
+	emac_tx_bd *last_hw_bdprocessed;	/* last HW BD processed */
+	bool queue_active;	/* queue active ? TRUE/FALSE */
+#ifdef EMAC_MULTIPACKET_TX_COMPLETE_NOTIFY
+	u32 *tx_complete;	/* tx complete notification queue */
+#endif
+	/** statistics */
+	u32 proc_count;		/* TX: # of times emac_tx_bdproc is called */
+	u32 mis_queued_packets;	/* misqueued packets */
+	u32 queue_reinit;	/* queue reinit - head ptr reinit */
+	u32 end_of_queue_add;	/* packet added to end of queue in send */
+	u32 out_of_tx_bd;	/* out of tx bd errors */
+	u32 no_active_pkts;	/* IRQ when there were no packets to process */
+	u32 active_queue_count;	/* active tx bd count */
+	u32 num_multi_frag_pkts;
+} emac_tx_cppi_ch;
+
+/**
+ *  RX Channel Control Structure
+ *
+ *  Used by EMAC DDC code to process RX Buffer Descriptors
+ */
+typedef struct _emac_rx_cppi_ch_t {
+	/* configuration info */
+	emac_ch_info ch_info;	/* channel config/info */
+
+	/* EMAC (ethernet) specific configuration info */
+	char mac_addr[6];	/* ethernet MAC address */
+
+	/** CPPI specific */
+	u32 alloc_size;		/* BD pool allocated memory size */
+	char *bd_mem;		/* buffer descriptor memory pointer */
+	emac_rx_bd *bd_pool_head;
+	emac_rx_bd *active_queue_head;
+	emac_rx_bd *active_queue_tail;
+	bool queue_active;
+
+	/* packet and buffer objects required for passing up to DDA
+	 * layer for the given instance */
+	net_pkt_obj pkt_queue;
+	net_buf_obj buf_queue[EMAC_MAX_RX_FRAGMENTS];
+#ifdef EMAC_MULTIFRAGMENT
+	u32 rx_buffer_ptr[EMAC_MAX_RX_FRAGMENTS];
+	u32 rx_data_token[EMAC_MAX_RX_FRAGMENTS];
+#endif
+	/** statistics */
+	u32 proc_count;		/* number of times emac_rx_bdproc is called */
+	u32 processed_bd;	/* number of BD's processed */
+	u32 recycled_bd;	/* number of recycled BD's */
+	u32 out_of_rx_bd;	/* NO BD's available */
+	u32 out_of_rx_buffers;	/* NO buffers available */
+	u32 queue_reinit;	/* condition when recycling buffers */
+	u32 end_of_queue_add;	/* when adding BD at end */
+	u32 end_of_queue;	/* end of queue condition */
+	u32 mis_queued_packets;	/* mis-queued packet condition */
+	u32 num_multi_frag_pkts;
+} _emac_rx_cppi_ch;
+
+/* data structures and header files required for MII-MDIO module  */
+/* typedef struct _phy_device PHY_DEVICE; */
+
+/**
+ * EMAC Private data structure
+ *
+ * Each EMAC device maintains its own private data structure and has a
+ * pointer to the net_device data structure representing the instance
+ * with the kernel.  The private data structure contains a "owner"
+ * member pointing to the net_device structure and the net_device data
+ * structure's "priv" member points back to this data structure.
+ */
+typedef struct emac_dev_s {
+	void *owner;		/* pointer to the net_device struct */
+	unsigned int instance_num;	/* instance number of the device */
+	struct net_device *next_device;
+	unsigned int link_speed;
+	unsigned int link_mode;
+	unsigned long set_to_close;
+	void *led_handle;
+
+	/* DDC related parameters */
+	emac_status ddc_status;
+
+	/* configuration parameters */
+	unsigned char mac_addr[6];
+	emac_init_config init_cfg;
+	unsigned int rx_buf_size;
+	unsigned int rx_buf_offset;
+
+	/* TODO: VLAN TX not supported as of now */
+	bool vlan_enable;
+
+	/* channel configuration - though only 1 TX/RX channel is
+	 * supported, provision is made for max */
+	emac_ch_info tx_ch_info[EMAC_MAX_TX_CHANNELS];
+	emac_ch_info rx_ch_info[EMAC_MAX_RX_CHANNELS];
+
+	/* periodic timer required for MDIO polling */
+	struct timer_list periodic_timer;
+	u32 periodic_ticks;	/* ticks for this timer */
+	bool timer_active;	/* periodic timer active ??? */
+	struct timer_list mib_timer;	/* for 64 bit MIB counter  */
+	u32 mib_ticks;		/* ticks for this timer */
+	bool mib_timer_active;	/* periodic timer active ??? */
+
+	/* statistics */
+	emac_hw_statistics device_mib;	/* hardware statistics counters */
+	emac_drv_stats device_stats;	/* device statstics */
+	struct net_device_stats net_dev_stats;
+
+	/* statistics counters for debugging */
+	u32 isr_count;
+
+	/* tx_rx_param struct added */
+	rx_tx_params napi_rx_tx;
+
+	/* TX/RX locks */
+	spinlock_t tx_lock;
+	spinlock_t rx_lock;
+
+	emac_drv_state drv_state;
+
+	/** EMAC specific parameters - DDC device specifics */
+	emac_tx_cppi_ch *tx_cppi[EMAC_MAX_TX_CHANNELS];
+	emac_rx_cppi_ch *rx_cppi[EMAC_MAX_RX_CHANNELS];
+	bool tx_is_created[EMAC_MAX_TX_CHANNELS];
+	bool rx_is_created[EMAC_MAX_RX_CHANNELS];
+	bool tx_is_open[EMAC_MAX_TX_CHANNELS];
+	bool rx_is_open[EMAC_MAX_RX_CHANNELS];
+	bool tx_teardown_pending[EMAC_MAX_TX_CHANNELS];
+	bool rx_teardown_pending[EMAC_MAX_RX_CHANNELS];
+	int tx_int_threshold[EMAC_MAX_TX_CHANNELS];
+	bool tx_interrupt_disable;
+
+	/* register mirror values - maintained to avoid costly
+	 * register access for reads */
+	u32 rx_unicast_set;
+	u32 rx_unicast_clear;
+	u32 rx_MBP_enable;
+	u32 mac_hash1;
+	u32 mac_hash2;
+	u32 mac_control;
+	emac_status status;
+
+	/* number of multicast hash bits used in hardware */
+	u32 multicast_hash_cnt[EMAC_NUM_MULTICAST_BITS];
+
+	/* EMAC/CPGMAC addressing mechanism */
+	u32 rx_addr_type;	/* 0 (EMAC), 1 or 2 (CPGMAC) */
+
+	emac_regs_ovly regs;
+	ewrap_regs *e_wrap_regs;
+
+	struct mib2_if_hccounters mib2if_hccounter;
+} emac_dev_t;
+
+/* ---------------------------------------------------------------
+ * globals
+ * --------------------------------------------------------------- */
+
+/* debug tracing */
+static int emac_link_status = 1;
+static int emac_debug_mode = 0;
+
+/* global variables required during initialization */
+static int g_link_speed = 0;	/* 0=auto negotiate, 100=100mbps, 10=10mbps */
+static int g_link_mode = 0;	/* 0=Auto Negotiate, Full Duplex = 3;
+				 * Half Duplex = 2 Unknown = 1 */
+static int g_init_enable_flag = 0;
+
+/* global device array */
+static struct net_device *emac_net_dev[EMAC_MAX_INSTANCES] = { NULL };
+
+static struct net_device *last_emac_device = NULL;
+static int emac_devices_installed = 0;	/* number of EMAC instances */
+
+static struct proc_dir_entry *gp_stats_file = NULL;	/* proc entries */
+
+static char emac_cfg[EMAC_MAX_INSTANCES][200];
+
+/* clock frequency for EMAC */
+static struct clk *emac_clk;
+static unsigned long emac_bus_frequency;
+
+/* MAC ethernet address string in 00:00:00:00:00:00 format */
+static unsigned char emac_eth_string[20] = "deadbeaf";
+
+static const char emac_ddcversion_string[] = "EMAC DDC version 0.5";
+
+static u32 emac_debug = 0x0;	/* no debug flags by default */
+static u32 emac_wrapper_ptr = EMAC_WRAPPER_RAM_ADDR;
+
+/* ---------------------------------------------------------------
+ * prototypes
+ * --------------------------------------------------------------- */
+extern int davinci_get_macaddr(char *ptr);
+
+static int emac_dev_tx(struct sk_buff *skb, struct net_device *netdev);
+
+static irqreturn_t emac_hal_isr(int irq, void *dev_id);
+
+static void *emac_net_alloc_rx_buf(emac_dev_t * dev, int buf_size,
+				   emac_net_data_token * data_token,
+				   u32 channel, void *alloc_args);
+
+static int emac_net_free_rx_buf(emac_dev_t * dev, void *buffer,
+				emac_net_data_token data_token,
+				u32 channel, void *free_args);
+
+static int emac_net_tx_complete(emac_dev_t * dev,
+				emac_net_data_token * net_data_tokens,
+				int num_tokens, u32 channel);
+
+static int emac_net_rx_cb(emac_dev_t * dev,
+		   	  net_pkt_obj * net_pkt_list,
+			  void *rx_args);
+
+
+static int emac_poll(struct net_device *netdev, int *budget);
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static void emac_poll_controller(struct net_device *dev);
+#endif
+
+/* net device related private function prototypes */
+static int emac_dev_init(struct net_device *netdev);
+
+static int emac_dev_open(struct net_device *dev);
+
+static int emac_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd);
+
+static int emac_dev_close(struct net_device *netdev);
+
+static void emac_dev_mcast_set(struct net_device *netdev);
+
+static void emac_tx_timeout(struct net_device *netdev);
+
+static struct net_device_stats *emac_dev_get_net_stats(struct net_device
+						       *dev);
+
+/* internal function prototypes */
+static int __init emac_p_detect_manual_cfg(int, char *, int);
+
+static int emac_p_read_stats(char *buf, char **start, off_t offset, int count,
+			     int *eof, void *data);
+
+static int emac_p_write_stats(struct file *fp, const char *buf,
+			      unsigned long count, void *data);
+
+static int emac_p_read_link(char *buf, char **start, off_t offset, int count,
+			    int *eof, void *data);
+
+static int emac_dump_config(char *buf, char **start, off_t offset, int count,
+			    int *eof, void *data);
+
+static int emac_p_get_version(char *buf, char **start, off_t offset,
+			      int count, int *eof, void *data);
+
+static int emac_p_update_statistics(struct net_device *netdev, char *buf,
+				    int limit, int *p_len);
+
+static int emac_p_reset_statistics(struct net_device *netdev);
+
+static int emac_p_read_rfc2665_stats(char *buf, char **start, off_t offset,
+				     int count, int *eof, void *data);
+
+static int emac_p_dev_enable(emac_dev_t * dev);
+
+static int emac_p_dev_disable(emac_dev_t * dev);
+
+static void emac_p_tick_timer_expiry(emac_dev_t * dev);
+
+static int emac_dev_set_mac_addr(struct net_device *netdev, void *addr);
+
+/* function prototype for emac_p_tick_timer_expiry() function as per
+ * linux timer API */
+typedef void (*timer_tick_func) (unsigned long);
+
+/* DDA function table */
+static int emac_control_cb(emac_dev_t * dev, int cmd,
+			   void *cmd_arg, void *param);
+
+/* function prototypes */
+static int emac_send(emac_dev_t * dev, net_pkt_obj * pkt,
+		     int channel, bool send_args);
+
+static int emac_tick(emac_dev_t * dev, void *tick_args);
+
+static int emac_pkt_process(emac_dev_t * dev, int *pkts_pending,
+			    void *pkt_args);
+
+static int emac_pkt_process_end(emac_dev_t * dev, void *proc_args);
+
+static int emac_tx_bdproc(emac_dev_t * dev, u32 channel, u32 * more_pkts,
+			  bool * is_eoq);
+
+static int emac_rx_bdproc(emac_dev_t * dev, u32 channel, int *more_pkts);
+
+#ifdef EMAC_MULTIFRAGMENT
+static void emac_add_bdto_rx_queue(emac_dev_t * dev, emac_rx_cppi_ch * rx_cppi,
+				   emac_rx_bd * sop_bd, emac_rx_bd * eop_bd,
+				   u32 * buffer,
+				   emac_net_data_token * buf_token, u32 num_bd);
+
+#else
+static void emac_add_bdto_rx_queue(emac_dev_t * dev, emac_rx_cppi_ch * rx_cppi,
+				   emac_rx_bd * curr_bd, char *buffer,
+				   emac_net_data_token buf_token);
+#endif
+
+static int emac_update_phy_status(emac_dev_t * dev);
+
+static int emac_init(emac_dev_t * dev, emac_init_config * init_cfg);
+
+static int emac_de_init(emac_dev_t * dev, void *param);
+
+static int emac_open(emac_dev_t * dev, void *param);
+
+static int emac_close(emac_dev_t * dev, void *param);
+
+static int emac_control(emac_dev_t * dev, int cmd, void *cmd_arg, void *param);
+
+static int emac_ch_open(emac_dev_t * dev, emac_ch_info * ch_info,
+			void *ch_open_args);
+
+static int emac_ch_close(emac_dev_t * dev, int channel,
+			 int direction, void *ch_close_args);
+
+static int emac_wait_for_teardown_complete(emac_dev_t * dev,
+					   u32 channel,
+					   net_ch_dir direction, bool blocking);
+
+static int emac_enable_channel(emac_dev_t * dev, u32 channel, u32 direction);
+
+static int emac_disable_channel(emac_dev_t * dev, u32 channel,
+				net_ch_dir direction);
+
+static int emac_init_tx_channel(emac_dev_t * dev, emac_ch_info * ch_info,
+				void *ch_open_args);
+
+static int emac_init_rx_channel(emac_dev_t * dev, emac_ch_info * ch_info,
+				void *ch_open_args);
+
+static int emac_un_init_tx_channel(emac_dev_t * dev, u32 channel,
+				   void *ch_close_args);
+
+static int emac_un_init_rx_channel(emac_dev_t * dev, u32 channel,
+				   void *ch_close_args);
+
+static void emac_set_mac_address(emac_dev_t * dev, u32 channel, char *mac_addr);
+
+static void emac_ddcifcnt_clear(emac_dev_t * dev);
+
+static void emac_ddcifcnt_updt(emac_dev_t * dev);
+
+static void emac_ddcphycnt(emac_dev_t * dev, u32 * cmd_arg);
+
+/* ---------------------------------------------------------------
+ * internal utility functions
+ * --------------------------------------------------------------- */
+static inline u32 emac_virt_to_phys(u32 addr)
+{
+	/* NOTE: must handle memory and IO addresses */
+	if ((addr & 0xFFFF0000) == EMAC_BASE_ADDR) {
+		addr = io_v2p(addr);
+	} else {
+		addr = virt_to_phys((void *)addr);
+	}
+
+	return addr;
+}
+
+#define EMAC_VIRT_TO_PHYS(x) emac_virt_to_phys((u32)x)
+#define EMAC_VIRT_NOCACHE(addr)(addr)
+
+/* alloc and zero memoy */
+static inline int emac_malloc(u32 n, void **buf)
+{
+	void *tmp = kcalloc(n, 1, GFP_KERNEL);
+
+	if (!tmp) {
+		printk(KERN_ERR "emac_malloc(): kmalloc() failed.\n");
+		dump_stack();
+		return -1;
+	}
+
+	*buf = tmp;
+	return 0;
+}
+
+static inline void emac_free(void *ptr)
+{
+	kfree(ptr);
+}
+
+#define EMAC_CACHE_INVALIDATE(addr, size) consistent_sync((void *)addr, size, DMA_FROM_DEVICE)
+#define EMAC_CACHE_WRITEBACK(addr, size) consistent_sync((void *)addr, size, DMA_TO_DEVICE)
+#define EMAC_CACHE_WRITEBACK_INVALIDATE(addr, size) consistent_sync((void *)addr,size, DMA_BIDIRECTIONAL)
+
+/* buffer-descriptors in IO space.  No cache invalidation needed */
+#define BD_CACHE_INVALIDATE(addr, size)
+#define BD_CACHE_WRITEBACK(addr, size)
+#define BD_CACHE_WRITEBACK_INVALIDATE(addr, size)
+
+/* string to hex conversion */
+static unsigned char emac_str_to_hexnum(unsigned char c)
+{
+	if (c >= '0' && c <= '9')
+		return c - '0';
+	if (c >= 'a' && c <= 'f')
+		return c - 'a' + 10;
+	if (c >= 'A' && c <= 'F')
+		return c - 'A' + 10;
+	return 0;
+}
+
+/* string to ethernet address conversion */
+static void emac_str_to_ethaddr(unsigned char *ea, unsigned char *str)
+{
+	int i;
+	unsigned char num;
+
+	for (i = 0; i < 6; i++) {
+		if ((*str == '.') || (*str == ':')) {
+			str++;
+		}
+		num = emac_str_to_hexnum(*str) << 4;
+		++str;
+		num |= (emac_str_to_hexnum(*str));
+		++str;
+		ea[i] = num;
+	}
+}
+
+static int emac_cfg_build(int connect, int external_switch)
+{
+
+	static int cfg_instance = 0;
+
+	unsigned int speed = 0;
+
+	speed = (external_switch) ? CONFIG_EMAC_NOPHY : 0;
+
+	sprintf(emac_cfg[cfg_instance],
+		"%d:%x:%d:%d:%u:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%d:%x:%d:%d:%u:%u:%x:%d",
+		cfg_instance, EMAC_BASE_ADDR,
+		EMAC_INTERRUPT, 0, EMAC_BUS_FREQUENCY,
+		g_link_speed, g_link_mode, EMAC_DEFAULT_PROMISCOUS_ENABLE,
+		EMAC_DEFAULT_BROADCAST_ENABLE,
+		EMAC_DEFAULT_MULTICAST_ENABLE,
+		EMAC_DEFAULT_MAX_FRAME_SIZE,
+		EMAC_DEFAULT_TX_NUM_BD,
+		EMAC_DEFAULT_TX_MAX_SERVICE, EMAC_DEFAULT_RX_NUM_BD,
+		EMAC_DEFAULT_RX_MAX_SERVICE, 0,
+		EMAC_MDIO_BASE_ADDR, 0, 0,
+		EMAC_BUS_FREQUENCY, EMAC_MDIO_FREQUENCY, EMAC_PHY_MASK, 10);
+
+	DBG("Driver Config:\n%s\n", emac_cfg[cfg_instance]);
+
+	cfg_instance++;
+
+	return (0);
+
+}
+
+/* emac_eth_setup() invokes a board specific function that provides
+ * MAC address for this adapter. For DaVinci EVM, the function invoked
+ * is davinci_get_macaddr();
+ */
+static int emac_eth_setup(void)
+{
+	if (davinci_get_macaddr(&emac_eth_string[0]) != 0) {
+		printk("TI DaVinci EMAC: Error getting board specific "
+		       "MAC address\n");
+		printk("Assuming default MAC address\n");
+		return (-1);
+	} else {
+		printk("TI DaVinci EMAC: MAC address is %s\n", emac_eth_string);
+	}
+
+	return (0);
+}
+
+static int emac_cfg_probe(void)
+{
+
+	/* for DaVinci there is only 1 EMAC instance */
+	if (emac_cfg_build(0, 0))
+		return (-1);
+	else
+		return (0);
+}
+
+/******************************************************************************
+ *  DDA Callback functions
+ *****************************************************************************/
+
+/* emac_control_cb - ioctl function to be called by the DDC */
+static int emac_control_cb(emac_dev_t * dev, int cmd,
+			   void *cmd_arg, void *param)
+{
+	switch (cmd) {
+	case EMAC_IOCTL_TIMER_START:
+		{
+			/* cmd will directly have the timer period
+			 * of the periodic timer, param not used */
+
+			/* asks for milliSecs. So calculate ticks
+			 * from ticks per 1000 mSec
+			 */
+			struct timer_list *p_timer = &dev->periodic_timer;
+
+			dev->periodic_ticks =
+			    (EMAC_TICKS_PER_SEC * (int)cmd_arg) / 1000;
+			p_timer->expires = jiffies + dev->periodic_ticks;
+			add_timer(&dev->periodic_timer);
+			dev->timer_active = TRUE;
+
+		}
+		break;
+
+	case EMAC_IOCTL_TIMER_STOP:
+		/* cmd and param not used */
+		if (dev->timer_active == TRUE) {
+			del_timer_sync(&dev->periodic_timer);
+			dev->timer_active = FALSE;
+		}
+		break;
+
+	case EMAC_IOCTL_STATUS_UPDATE:
+		{
+			/* cmd_arg will point to status structure,
+			 * param not used  */
+			struct net_device *netdev = dev->owner;
+
+			emac_status *status = &dev->ddc_status;
+			dev->ddc_status = *((emac_status *) cmd_arg);
+			if ((status->hw_status & EMAC_TX_HOST_ERROR) ==
+			    EMAC_TX_HOST_ERROR) {
+				ERR("TX Host Error. "
+				    "Transmit Stopped %s\n", netdev->name);
+			}
+			if ((status->hw_status & EMAC_RX_HOST_ERROR) ==
+			    EMAC_RX_HOST_ERROR) {
+				ERR("RX Host Error. "
+				    "Receive Stopped %s\n", netdev->name);
+			}
+			if (status->phy_linked) {
+				/* link ON */
+				if (!netif_carrier_ok(netdev)) {
+					netif_carrier_on(netdev);
+				}
+				dev->link_speed =
+				    ((status->
+				      phy_speed == 100) ? 100000000 : 10000000);
+				dev->link_mode =
+				    ((status->phy_duplex == PHY_DUPLEX_FULL) ?
+					PHY_DUPLEX_FULL : PHY_DUPLEX_HALF);
+
+				/* reactivate the transmit queue if it
+				 * is stopped */
+				if (netif_running(netdev)
+				    && netif_queue_stopped(netdev)) {
+					netif_wake_queue(netdev);
+				}
+			} else {
+				/* link OFF */
+				if (netif_carrier_ok(netdev)) {
+					/* do we need to register
+					 * synchronization issues with
+					 * stats here. */
+					dev->link_speed = 100000000;
+					dev->link_mode = 1;
+					netif_carrier_off(netdev);
+				}
+				if (!netif_queue_stopped(netdev)) {
+					/* so that kernel does not
+					 * keep on xmiting pkts. */
+					netif_stop_queue(netdev);
+				}
+			}
+
+			if (emac_link_status)
+				DBG("%s, PhyNum %d,  %s, %s, %s\n",
+				    ((struct net_device *)dev->owner)->name,
+				    status->phy_num,
+				    ((status->phy_duplex == PHY_DUPLEX_FULL) ?
+				     "Full Duplex" : "Half Duplex"),
+				    ((status->phy_speed == 100) ?
+				     "100 Mbps" : "10 Mbps"),
+				    ((status->phy_linked) ?
+				     "Linked" : "NO LINK"));
+		}
+		break;
+
+	case EMAC_IOCTL_MIB64_CNT_TIMER_START:
+		{
+			/* cmd will directly have the timer period of the
+			 * periodic timer, param not used */
+
+			/* asks for milli_secs. so calculate ticks
+			 * from ticks per 1000 m_sec */
+			struct timer_list *p_timer = &dev->mib_timer;
+
+			dev->mib_ticks =
+			    (EMAC_TICKS_PER_SEC * (int)cmd_arg) / 1000;
+			p_timer->expires = jiffies + dev->mib_ticks;
+			add_timer(p_timer);
+			dev->mib_timer_active = TRUE;
+		}
+		break;
+
+	case EMAC_IOCTL_MIB64_CNT_TIMER_STOP:
+		{
+			/* cmd_arg and param not used */
+			if (dev->mib_timer_active == TRUE) {
+				del_timer_sync(&dev->mib_timer);
+				dev->mib_timer_active = FALSE;
+			}
+		}
+		break;
+
+	default:
+		DBG("Unhandled ioctl code %d\n", cmd);
+		break;
+	}
+
+	return (EMAC_SUCCESS);
+}
+
+/*****************************************************************************
+ *
+ * emacEndGetConfig - Extract configuration for given unit number/instance
+ *
+ * This function gets the configuration information from the
+ * configuration service or by some means for the given unit
+ * number/emac instance
+ *
+ * Note: For debug/default, static information is obtained from the
+ * header file
+ *
+ * RETURNS: OK or ERROR.
+ */
+static int emac_net_get_config(emac_dev_t * dev)
+{
+#define EMAC_TOKEN_PARSE(str) \
+  { if ((tok = (char *)strsep ((str), ":")) == NULL) return -1; }
+#define EMAC_TOKEN_GET_INTEGER simple_strtoul (tok, NULL, 10)
+#define EMAC_TOKEN_GET_HEX     simple_strtoul (tok, NULL, 16)
+	emac_init_config *i_cfg = &dev->init_cfg;
+	emac_ch_info *tx_ch_cfg = &dev->tx_ch_info[0];
+	emac_ch_info *rx_ch_cfg = &dev->rx_ch_info[0];
+	int speed, duplex, extra;
+	char local_string_val[200];
+	char *local_string = NULL;
+	char *tok;
+	char *p_holder = NULL;
+
+	/* use static config string */
+	switch (dev->instance_num) {
+	case 0:
+		local_string = emac_cfg[0];
+		break;
+	case 1:
+		local_string = emac_cfg[1];
+		break;
+	default:
+		local_string = emac_cfg[0];
+		break;
+	}
+
+	strcpy(&local_string_val[0], local_string);
+	local_string = &local_string_val[0];
+	p_holder = NULL;
+	tok = (char *)strsep(&local_string, ":");
+	if (tok == NULL)
+		return (-1);
+
+	i_cfg->inst_id = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("i_cfg->instId=%d", i_cfg->inst_id);
+
+	i_cfg->base_address = EMAC_TOKEN_GET_HEX;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->baseAddress=%08X", i_cfg->base_address);
+
+	i_cfg->intr_line = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->intrLine=%d", i_cfg->intr_line);
+
+	i_cfg->reset_line = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->resetLine=%d", i_cfg->reset_line);
+
+	i_cfg->emac_bus_frequency = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->emacBusFrequency=%d", i_cfg->emac_bus_frequency);
+
+	speed = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\nspeed=%d", speed);
+
+	duplex = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\nduplex=%d", duplex);
+
+	i_cfg->rx_cfg.promiscous_enable = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->rxCfg.promiscousEnable=%d",
+	    i_cfg->rx_cfg.promiscous_enable);
+
+	i_cfg->rx_cfg.broadcast_enable = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->rxCfg.broadcastEnable=%d",
+	    i_cfg->rx_cfg.broadcast_enable);
+
+	i_cfg->rx_cfg.multicast_enable = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->rxCfg.multicastEnable=%d",
+	    i_cfg->rx_cfg.multicast_enable);
+
+	i_cfg->rx_cfg.max_rx_pkt_length = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->rxCfg.maxRxPktLength=%d",
+	    i_cfg->rx_cfg.max_rx_pkt_length);
+
+	tx_ch_cfg->num_bd = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ntx_ch_cfg->num_bd=%d", tx_ch_cfg->num_bd);
+
+	tx_ch_cfg->service_max = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ntx_ch_cfg->service_max=%d", tx_ch_cfg->service_max);
+
+	rx_ch_cfg->num_bd = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\nrx_ch_cfg->num_bd=%d", rx_ch_cfg->num_bd);
+
+	rx_ch_cfg->service_max = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\nrx_ch_cfg->service_max=%d", rx_ch_cfg->service_max);
+
+	extra = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\nextra=%d", extra);
+
+	i_cfg->mdio_base_address = EMAC_TOKEN_GET_HEX;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->mdioBaseAddress=%08X", i_cfg->mdio_base_address);
+
+	i_cfg->mdio_intr_line = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->mdioIntrLine=%d", i_cfg->mdio_intr_line);
+
+	i_cfg->mdio_reset_line = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->mdioResetLine=%d", i_cfg->mdio_reset_line);
+
+	i_cfg->mdio_bus_frequency = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->MdioBusFrequency=%d", i_cfg->mdio_bus_frequency);
+
+	i_cfg->mdio_clock_frequency = EMAC_TOKEN_GET_INTEGER;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->MdioClockFrequency=%d", i_cfg->mdio_clock_frequency);
+
+	i_cfg->phy_mask = EMAC_TOKEN_GET_HEX;
+	EMAC_TOKEN_PARSE(&local_string);
+	DBG("\ni_cfg->PhyMask=%08X", i_cfg->phy_mask);
+
+	i_cfg->mdio_tick_msec = EMAC_TOKEN_GET_INTEGER;
+	DBG("\ni_cfg->MdioTickMSec=%d", i_cfg->mdio_tick_msec);
+	DBG("\n");
+
+	i_cfg->mib64cnt_msec = CONFIG_EMAC_MIB_TIMER_TIMEOUT;
+	rx_ch_cfg->buf_size = i_cfg->rx_cfg.max_rx_pkt_length;
+	dev->rx_buf_offset =
+	    EMAC_L3_ALIGN(extra) + EMAC_DEFAULT_EXTRA_RXBUF_SIZE;
+	dev->rx_buf_size = (rx_ch_cfg->buf_size + dev->rx_buf_offset);
+
+	/* align skb's on 4 byte boundry - no hard requirement currently - done for future use */
+	dev->rx_buf_size += EMAC_4BYTE_ALIGN(dev->rx_buf_size);
+
+	/* determine phy speed/duplex mode - to be built as per MDIO
+	 * module requirements */
+	if (speed == CONFIG_EMAC_NOPHY) {
+		i_cfg->phy_mode = SNWAY_NOPHY;
+	} else {
+		if ((speed == 0) && (duplex == PHY_DUPLEX_AUTO)) {
+			i_cfg->phy_mode = SNWAY_AUTOALL;
+		} else if (speed == 10) {
+			if (duplex == PHY_DUPLEX_HALF) {
+				i_cfg->phy_mode = SNWAY_HD10;
+			} else if (duplex == PHY_DUPLEX_FULL) {
+				i_cfg->phy_mode = SNWAY_FD10;
+			} else {
+				i_cfg->phy_mode = SNWAY_HD10 | SNWAY_FD10;
+			}
+		} else if (speed == 100) {
+			if (duplex == PHY_DUPLEX_HALF) {
+				i_cfg->phy_mode = SNWAY_HD100;
+			} else if (duplex == PHY_DUPLEX_FULL) {
+				i_cfg->phy_mode = SNWAY_FD100;
+			} else {
+				i_cfg->phy_mode = SNWAY_HD100 | SNWAY_FD100;
+			}
+		} else {
+			if (duplex == PHY_DUPLEX_FULL) {
+				i_cfg->phy_mode = SNWAY_FD10 | SNWAY_FD100;
+			} else {
+				i_cfg->phy_mode = SNWAY_HD10 | SNWAY_HD100;
+			}
+		}
+	}
+
+	dev->vlan_enable = EMAC_DEFAULT_VLAN_ENABLE;
+	i_cfg->num_tx_channels = EMAC_DEFAULT_NUM_TX_CHANNELS;
+	i_cfg->num_rx_channels = EMAC_DEFAULT_NUM_RX_CHANNELS;
+	i_cfg->MLink_mask = EMAC_DEFAULT_MLINK_MASK;
+	i_cfg->rx_cfg.pass_crc = EMAC_DEFAULT_PASS_CRC;
+	i_cfg->rx_cfg.qos_enable = EMAC_DEFAULT_QOS_ENABLE;
+	i_cfg->rx_cfg.no_buffer_chaining = EMAC_DEFAULT_NO_BUFFER_CHAINING;
+	i_cfg->rx_cfg.copy_maccontrol_frames_enable =
+	    EMAC_DEFAULT_COPY_MAC_CONTROL_FRAMES_ENABLE;
+	i_cfg->rx_cfg.copy_short_frames_enable =
+	    EMAC_DEFAULT_COPY_SHORT_FRAMES_ENABLE;
+	i_cfg->rx_cfg.copy_error_frames_enable =
+	    EMAC_DEFAULT_COPY_ERROR_FRAMES_ENABLE;
+	i_cfg->rx_cfg.promiscous_channel = EMAC_DEFAULT_PROMISCOUS_CHANNEL;
+	i_cfg->rx_cfg.broadcast_channel = EMAC_DEFAULT_BROADCAST_CHANNEL;
+	i_cfg->rx_cfg.multicast_channel = EMAC_DEFAULT_MULTICAST_CHANNEL;
+	i_cfg->rx_cfg.buffer_offset = EMAC_DEFAULT_BUFFER_OFFSET;
+	i_cfg->mac_cfg.p_type = EMAC_TXPRIO_FIXED;
+	i_cfg->mac_cfg.tx_short_gap_enable = FALSE;
+
+	if (speed == 1000)
+		i_cfg->mac_cfg.giga_bit_enable = TRUE;
+	else
+		i_cfg->mac_cfg.giga_bit_enable = FALSE;
+
+	i_cfg->mac_cfg.tx_pacing_enable = EMAC_DEFAULT_TX_PACING_ENABLE;
+	i_cfg->mac_cfg.mii_enable = EMAC_DEFAULT_MII_ENABLE;
+	i_cfg->mac_cfg.tx_flow_enable = EMAC_DEFAULT_TX_FLOW_ENABLE;
+	i_cfg->mac_cfg.rx_flow_enable = EMAC_DEFAULT_RX_FLOW_ENABLE;
+	i_cfg->mac_cfg.loopback_enable = EMAC_DEFAULT_LOOPBACK_ENABLE;
+	i_cfg->mac_cfg.full_duplex_enable = EMAC_DEFAULT_FULL_DUPLEX_ENABLE;
+	i_cfg->mac_cfg.tx_interrupt_disable = EMAC_DEFAULT_TX_INTERRUPT_DISABLE;
+	tx_ch_cfg->ch_num = EMAC_DEFAULT_TX_CHANNEL;
+	tx_ch_cfg->ch_dir = NET_CH_DIR_TX;
+	tx_ch_cfg->ch_state = NET_CH_UNINITIALIZED;
+	rx_ch_cfg->ch_num = EMAC_DEFAULT_RX_CHANNEL;
+	rx_ch_cfg->ch_dir = NET_CH_DIR_RX;
+	rx_ch_cfg->ch_state = NET_CH_UNINITIALIZED;
+
+	/* module control EWrap base address for DaVinci */
+	i_cfg->e_wrap_base_address = EMAC_WRAPPER_REGS_ADDR;
+
+	DBG("\n");
+	return (0);
+}
+
+/* detect manual config */
+static int __init emac_p_detect_manual_cfg(int link_speed, char *link_mode,
+					   int debug)
+{
+	if (debug == 1) {
+		emac_debug_mode = 1;
+		DBG("Enabled debug print.\n");
+	}
+
+	if ((link_speed == 0) && (!strcmp(link_mode, "auto"))) {
+		/* Auto negotiation */
+		g_link_speed = 0;
+		g_link_mode = 0;
+		DBG("auto negotiation selected\n");
+	}
+
+	if (!link_speed || (link_speed != 10 && link_speed != 100)) {
+		g_link_speed = 0;
+		g_link_mode = 0;
+		DBG("Invalid or No value of link speed specified,"
+		    "defaulting to auto negotiation .\n");
+	}
+
+	if (!link_mode
+	    || (!strcmp(link_mode, "fd") && !strcmp(link_mode, "hd"))) {
+		g_link_speed = 0;
+		g_link_mode = 0;
+		DBG("Invalid or No value of link mode specified,"
+		    "defaulting to auto mode.\n");
+	}
+
+	if ((link_speed == 10) && (!strcmp(link_mode, "fd"))) {
+		g_link_speed = 10;
+		g_link_mode = 3;
+	} else if ((link_speed == 10) && (!strcmp(link_mode, "hd"))) {
+		g_link_speed = 10;
+		g_link_mode = 2;
+	} else if ((link_speed == 100) && (!strcmp(link_mode, "fd"))) {
+		g_link_speed = 100;
+		g_link_mode = 3;
+	} else if ((link_speed == 100) && (!strcmp(link_mode, "hd"))) {
+		g_link_speed = 100;
+		g_link_mode = 2;
+	} else {
+		g_link_speed = 0;
+		g_link_mode = 0;
+	}
+
+	DBG("Link is set to the speed of"
+	    "%s speed and %s mode.\n",
+	    ((g_link_speed ==
+	      0) ? "auto" : ((g_link_speed == 100) ? "100" : "10")),
+	    ((g_link_mode ==
+	      0) ? "auto" : ((g_link_mode == 2) ? "half" : "full")));
+
+	return (0);
+}
+
+/* link read support */
+static int emac_p_read_link(char *buf, char **start, off_t offset, int count,
+			    int *eof, void *data)
+{
+	int len = 0;
+	struct net_device *netdev;
+	emac_dev_t *dev;
+	struct net_device *emac_dev_list[emac_devices_installed];
+	int i;
+
+	len +=
+	    sprintf(buf + len, "EMAC devices = %d\n", emac_devices_installed);
+	netdev = last_emac_device;
+
+	/* reverse the the device link list to list eth0,eth1...in correct order */
+	for (i = 0; i < emac_devices_installed; i++) {
+		emac_dev_list[emac_devices_installed - (i + 1)] = netdev;
+		dev = NETDEV_PRIV(netdev);
+		netdev = dev->next_device;
+	}
+
+	for (i = 0; i < emac_devices_installed; i++) {
+		netdev = emac_dev_list[i];
+		dev = NETDEV_PRIV(netdev);
+
+		/*  this prints them out from high to low because of
+		    how the devices are linked */
+		if (netif_carrier_ok(netdev)) {
+			len +=
+			    sprintf(buf + len,
+				    "eth%d: Link State: %s    "
+				    "Phy %d, Speed = %s, Duplex = %s\n",
+				    dev->instance_num, "UP",
+				    dev->ddc_status.phy_num,
+				    (dev->link_speed ==
+				     100000000) ? "100" : "10",
+				    (dev->link_mode == 2) ? "Half" : "Full");
+
+		} else {
+			len +=
+			    sprintf(buf + len, "eth%d: Link State: DOWN\n",
+				    dev->instance_num);
+		}
+		netdev = dev->next_device;
+	}
+
+	return len;
+}
+
+/* dump configuration information for debug purposes */
+static int emac_dump_config(char *buf, char **start, off_t offset, int count,
+			    int *eof, void *data)
+{
+	int len = 0;
+	struct net_device *netdev;
+	struct net_device *emac_dev_list[emac_devices_installed];
+	int i;
+	emac_dev_t *dev;
+
+	len +=
+	    sprintf(buf + len, "EMAC devices = %d\n", emac_devices_installed);
+
+	netdev = last_emac_device;
+
+	/* reverse the the device link list to list eth0,eth1...in
+	   correct order */
+	for (i = 0; i < emac_devices_installed; i++) {
+		emac_dev_list[emac_devices_installed - (i + 1)] = netdev;
+		dev = NETDEV_PRIV(netdev);
+		netdev = dev->next_device;
+	}
+
+	for (i = 0; i < emac_devices_installed; i++) {
+		netdev = emac_dev_list[i];
+		dev = NETDEV_PRIV(netdev);
+
+		len +=
+		    sprintf(buf + len,
+			    "\nEMAC Driver Internal Config Info for Unit %d\n",
+			    dev->instance_num);
+		len +=
+		    sprintf(buf + len, "vlanEnable         = %d\n",
+			    dev->vlan_enable);
+		len +=
+		    sprintf(buf + len, "rxBufSize          = %d\n",
+			    dev->rx_buf_size);
+		len +=
+		    sprintf(buf + len, "rxBufOffset        = %d\n",
+			    dev->rx_buf_offset);
+		len +=
+		    sprintf(buf + len, "instId             = %d\n",
+			    dev->init_cfg.inst_id);
+		len +=
+		    sprintf(buf + len, "numTxChannels      = %d\n",
+			    dev->init_cfg.num_tx_channels);
+		len +=
+		    sprintf(buf + len, "numRxChannels      = %d\n",
+			    dev->init_cfg.num_rx_channels);
+		len +=
+		    sprintf(buf + len, "emacBusFrequency  = %d\n",
+			    dev->init_cfg.emac_bus_frequency);
+		len +=
+		    sprintf(buf + len, "baseAddress        = %08X\n",
+			    dev->init_cfg.base_address);
+		len +=
+		    sprintf(buf + len, "intrLine           = %d\n",
+			    dev->init_cfg.intr_line);
+		len +=
+		    sprintf(buf + len, "resetLine          = %d\n",
+			    dev->init_cfg.reset_line);
+		len +=
+		    sprintf(buf + len, "mdioBaseAddress    = %08X\n",
+			    dev->init_cfg.mdio_base_address);
+		len +=
+		    sprintf(buf + len, "mdioResetLine      = %d\n",
+			    dev->init_cfg.mdio_reset_line);
+		len +=
+		    sprintf(buf + len, "mdioIntrLine       = %d\n",
+			    dev->init_cfg.mdio_intr_line);
+		len +=
+		    sprintf(buf + len, "PhyMask            = %08X\n",
+			    dev->init_cfg.phy_mask);
+		len +=
+		    sprintf(buf + len, "MLinkMask          = %08X\n",
+			    dev->init_cfg.MLink_mask);
+		len +=
+		    sprintf(buf + len, "MdioBusFrequency   = %d\n",
+			    dev->init_cfg.mdio_bus_frequency);
+		len +=
+		    sprintf(buf + len, "MdioClockFrequency = %d\n",
+			    dev->init_cfg.mdio_clock_frequency);
+		len +=
+		    sprintf(buf + len, "MdioTickMSec       = %d\n",
+			    dev->init_cfg.mdio_tick_msec);
+		len +=
+		    sprintf(buf + len, "phyMode            = %d\n",
+			    dev->init_cfg.phy_mode);
+		len +=
+		    sprintf(buf + len, "passCRC            = %d\n",
+			    dev->init_cfg.rx_cfg.pass_crc);
+		len +=
+		    sprintf(buf + len, "qosEnable          = %d\n",
+			    dev->init_cfg.rx_cfg.qos_enable);
+		len +=
+		    sprintf(buf + len, "noBufferChaining   = %d\n",
+			    dev->init_cfg.rx_cfg.no_buffer_chaining);
+		len +=
+		    sprintf(buf + len, "copyMACCntrlFrsEne = %d\n",
+			    dev->init_cfg.rx_cfg.copy_maccontrol_frames_enable);
+		len +=
+		    sprintf(buf + len, "copyShortFramesEn  = %d\n",
+			    dev->init_cfg.rx_cfg.copy_short_frames_enable);
+		len +=
+		    sprintf(buf + len, "copyErrorFramesEn  = %d\n",
+			    dev->init_cfg.rx_cfg.copy_error_frames_enable);
+		len +=
+		    sprintf(buf + len, "promiscousEnable   = %d\n",
+			    dev->init_cfg.rx_cfg.promiscous_enable);
+		len +=
+		    sprintf(buf + len, "promiscousChannel  = %d\n",
+			    dev->init_cfg.rx_cfg.promiscous_channel);
+		len +=
+		    sprintf(buf + len, "broadcastEnable    = %d\n",
+			    dev->init_cfg.rx_cfg.broadcast_enable);
+		len +=
+		    sprintf(buf + len, "broadcastChannel   = %d\n",
+			    dev->init_cfg.rx_cfg.broadcast_channel);
+		len +=
+		    sprintf(buf + len, "multicastEnable    = %d\n",
+			    dev->init_cfg.rx_cfg.multicast_enable);
+		len +=
+		    sprintf(buf + len, "multicastChannel   = %d\n",
+			    dev->init_cfg.rx_cfg.multicast_channel);
+		len +=
+		    sprintf(buf + len, "maxRxPktLength     = %d\n",
+			    dev->init_cfg.rx_cfg.max_rx_pkt_length);
+		len +=
+		    sprintf(buf + len, "bufferOffset       = %d\n",
+			    dev->init_cfg.rx_cfg.buffer_offset);
+		len +=
+		    sprintf(buf + len, "pType              = %d\n",
+			    dev->init_cfg.mac_cfg.p_type);
+		len +=
+		    sprintf(buf + len, "txShortGapEnable   = %d\n",
+			    dev->init_cfg.mac_cfg.tx_short_gap_enable);
+		len +=
+		    sprintf(buf + len, "gigaBitEnable      = %d\n",
+			    dev->init_cfg.mac_cfg.giga_bit_enable);
+		len +=
+		    sprintf(buf + len, "txPacingEnable     = %d\n",
+			    dev->init_cfg.mac_cfg.tx_pacing_enable);
+		len +=
+		    sprintf(buf + len, "miiEnable          = %d\n",
+			    dev->init_cfg.mac_cfg.mii_enable);
+		len +=
+		    sprintf(buf + len, "txFlowEnable       = %d\n",
+			    dev->init_cfg.mac_cfg.tx_flow_enable);
+		len +=
+		    sprintf(buf + len, "rxFlowEnable       = %d\n",
+			    dev->init_cfg.mac_cfg.rx_flow_enable);
+		len +=
+		    sprintf(buf + len, "loopbackEnable     = %d\n",
+			    dev->init_cfg.mac_cfg.loopback_enable);
+		len +=
+		    sprintf(buf + len, "fullDuplexEnable   = %d\n",
+			    dev->init_cfg.mac_cfg.full_duplex_enable);
+		netdev = dev->next_device;
+	}
+
+	return len;
+}
+
+/* read stats */
+static int emac_p_read_stats(char *buf, char **start, off_t offset, int count,
+			     int *eof, void *data)
+{
+	struct net_device *netdev = last_emac_device;
+	int len = 0;
+	int limit = count - 80;
+	int i;
+	struct net_device *emac_dev_list[emac_devices_installed];
+	emac_dev_t *dev;
+	emac_hw_statistics *p_device_mib;
+
+	/* reverse the the device link list to list eth0,eth1...in
+	   correct order */
+	for (i = 0; i < emac_devices_installed; i++) {
+		emac_dev_list[emac_devices_installed - (i + 1)] = netdev;
+		dev = NETDEV_PRIV(netdev);
+		netdev = dev->next_device;
+	}
+
+	for (i = 0; i < emac_devices_installed; i++) {
+		netdev = emac_dev_list[i];
+		if (!netdev)
+			goto proc_error;
+
+		/* get stats */
+		emac_p_update_statistics(netdev, NULL, 0, NULL);
+		dev = NETDEV_PRIV(netdev);
+		p_device_mib = &dev->device_mib;
+
+		/* transmit stats */
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len, "\nCpmac %d, Address %lx\n",
+				    i + 1, netdev->base_addr);
+		if (len <= limit)
+			len += sprintf(buf + len, " Transmit Stats\n");
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Tx Valid Bytes Sent        :%u\n",
+				    p_device_mib->if_out_octets);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Good Tx Frames (Hardware)  :%u\n",
+				    p_device_mib->if_out_good_frames);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Good Tx Frames (Software)  :%lu\n",
+				    dev->net_dev_stats.tx_packets);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Good Tx Broadcast Frames   :%u\n",
+				    p_device_mib->if_out_broadcasts);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Good Tx Multicast Frames   :%u\n",
+				    p_device_mib->if_out_multicasts);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Pause Frames Sent          :%u\n",
+				    p_device_mib->if_out_pause_frames);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Collisions                 :%u\n",
+				    p_device_mib->if_collision_frames);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Tx Error Frames            :%lu\n",
+				    dev->net_dev_stats.tx_errors);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Carrier Sense Errors       :%u\n",
+				    p_device_mib->if_carrier_sense_errors);
+		if (len <= limit)
+			len += sprintf(buf + len, "\n");
+
+		/* receive stats */
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len, "\nCpmac %d, Address %lx\n",
+				    i + 1, netdev->base_addr);
+		if (len <= limit)
+			len += sprintf(buf + len, " Receive Stats\n");
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Rx Valid Bytes Received    :%u\n",
+				    p_device_mib->if_in_octets);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Good Rx Frames (Hardware)  :%u\n",
+				    p_device_mib->if_in_good_frames);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Good Rx Frames (Software)  :%lu\n",
+				    dev->net_dev_stats.rx_packets);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Good Rx Broadcast Frames   :%u\n",
+				    p_device_mib->if_in_broadcasts);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Good Rx Multicast Frames   :%u\n",
+				    p_device_mib->if_in_multicasts);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Pause Frames Received      :%u\n",
+				    p_device_mib->if_in_pause_frames);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Rx CRC Errors              :%u\n",
+				    p_device_mib->if_in_crcerrors);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Rx Align/Code Errors       :%u\n",
+				    p_device_mib->if_in_align_code_errors);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Rx Jabbers                 :%u\n",
+				    p_device_mib->if_in_oversized_frames);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Rx Filtered Frames         :%u\n",
+				    p_device_mib->if_in_filtered_frames);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Rx Fragments               :%u\n",
+				    p_device_mib->if_in_fragments);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Rx Undersized Frames       :%u\n",
+				    p_device_mib->if_in_undersized_frames);
+		if (len <= limit)
+			len +=
+			    sprintf(buf + len,
+				    "   Rx Overruns                :%u\n",
+				    p_device_mib->if_rx_dmaoverruns);
+	}
+
+	return len;
+
+      proc_error:
+	*eof = 1;
+
+	return len;
+}
+
+/* write stats */
+static int emac_p_write_stats(struct file *fp, const char *buf,
+			      unsigned long count, void *data)
+{
+	char local_buf[31];
+	int ret_val = 0;
+
+	if (count > 30) {
+		printk("Error : Buffer Overflow\n");
+		printk("Use \"echo 0 > emac_stat\" to reset the statistics\n");
+		return -EFAULT;
+	}
+
+	ret_val = copy_from_user(local_buf, buf, count);
+	if(ret_val)
+		return ret_val;
+	local_buf[count - 1] = '\0';	/* ignoring last \n char */
+	ret_val = count;
+	if (strcmp("0", local_buf) == 0) {
+		struct net_device *netdev = last_emac_device;
+		int i;
+		struct net_device *emac_dev_list[emac_devices_installed];
+		emac_dev_t *dev;
+
+		/* valid command */
+		printk("Resetting statistics for EMAC interface.\n");
+
+		/* reverse the the device link list to list
+		   eth0,eth1...in correct order */
+		for (i = 0; i < emac_devices_installed; i++) {
+			emac_dev_list[emac_devices_installed - (i + 1)] =
+			    netdev;
+
+			dev = NETDEV_PRIV(netdev);
+			netdev = dev->next_device;
+		}
+
+		for (i = 0; i < emac_devices_installed; i++) {
+			netdev = emac_dev_list[i];
+
+			if (!netdev) {
+				ret_val = -EFAULT;
+				break;
+			}
+
+			emac_p_reset_statistics(netdev);
+		}
+	} else {
+		printk("Error: Unknown operation on emac statistics\n");
+		printk("Use \"echo 0 > emac_stats\" to reset the statistics\n");
+		return -EFAULT;
+	}
+
+	return ret_val;
+}
+
+/* update RFC2665 statistics */
+static int emac_p_read_rfc2665_stats(char *buf, char **start, off_t offset,
+				     int count, int *eof, void *data)
+{
+	int limit = count - 80;
+	int len = 0;
+	struct net_device *netdev = (struct net_device *)data;
+
+	emac_p_update_statistics(netdev, buf, limit, &len);
+	*eof = 1;
+
+	return len;
+}
+
+/* reset statistics */
+static int emac_p_reset_statistics(struct net_device *netdev)
+{
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+
+	memset(&dev->device_mib, 0, sizeof(emac_hw_statistics));
+	memset(&dev->device_stats, 0, sizeof(emac_drv_stats));
+	memset(&dev->net_dev_stats, 0, sizeof(struct net_device_stats));
+
+	/* clear statistics */
+	if (emac_control(dev, EMAC_IOCTL_CLR_STATISTICS, NULL, NULL)
+	    != EMAC_SUCCESS) {
+		ERR("Error clearing statistics in DDC for %s\n", netdev->name);
+
+		return (-1);
+	}
+
+	return (0);
+}
+
+/* update statistics */
+static int emac_p_update_statistics(struct net_device *netdev, char *buf,
+				    int limit, int *p_len)
+{
+	unsigned long rx_hal_errors = 0;
+	unsigned long rx_hal_discards = 0;
+	unsigned long tx_hal_errors = 0;
+	unsigned long if_out_discards = 0;
+	unsigned long if_in_discards = 0;
+	unsigned long if_out_errors = 0;
+	unsigned long if_in_errors = 0;
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+	emac_hw_statistics *p_device_mib = &dev->device_mib;
+	emac_drv_stats *p_stats = &dev->device_stats;
+	emac_hw_statistics local_mib;
+	emac_hw_statistics *p_local_mib = &local_mib;
+	struct net_device_stats *p_net_dev_stats = &dev->net_dev_stats;
+	int len = 0;
+	int dev_mib_elem_count = 0;
+
+	/* do not access the hardware if it is in the reset state. */
+	if (!test_bit(0, &dev->set_to_close)) {
+		/* get hardware statistics from DDC */
+		if (emac_control
+		    (dev, EMAC_IOCTL_GET_STATISTICS, (void *)p_local_mib, NULL)
+		    != EMAC_SUCCESS) {
+			ERR("Error getting statistics for %s\n", netdev->name);
+
+			return (-1);
+		}
+
+		dev_mib_elem_count =
+		    sizeof(emac_hw_statistics) / sizeof(unsigned long);
+
+		/* Update the history of the stats. This takes care of
+		 * any reset of the device and stats that might have
+		 * taken place during the life time of the driver.
+		 */
+		while (dev_mib_elem_count--) {
+			*((unsigned long *)p_device_mib + dev_mib_elem_count) =
+			    *((unsigned long *)p_local_mib +
+			      dev_mib_elem_count);
+		}
+	}
+
+	/* RFC2665, section 3.2.7, page 9 */
+	rx_hal_errors =
+	    p_device_mib->if_in_fragments +
+	    p_device_mib->if_in_crcerrors +
+	    p_device_mib->if_in_align_code_errors +
+	    p_device_mib->if_in_jabber_frames;
+
+	/* RFC2233 */
+	rx_hal_discards = p_device_mib->if_rx_dmaoverruns;
+
+	/* RFC2665, section 3.2.7, page 9 */
+	tx_hal_errors =
+	    p_device_mib->if_excessive_collision_frames +
+	    p_device_mib->if_late_collisions +
+	    p_device_mib->if_carrier_sense_errors +
+	    p_device_mib->if_out_underrun;
+
+	/* if not set, the short frames (< 64 bytes) are considered as
+	   errors */
+	if (dev->init_cfg.rx_cfg.copy_short_frames_enable == FALSE)
+		rx_hal_errors += p_device_mib->if_in_undersized_frames;
+
+	/* All frames greater than max rx frame length set in hardware
+	 * should be considered error frames RFC2665, section 3.2.7,
+	 * page 9. */
+	rx_hal_errors += p_device_mib->if_in_oversized_frames;
+
+	/* if not in promiscous, then non addr matching frames are discarded */
+	/* EMAC 2.0 manual section 2.8.1.14 */
+	if (dev->init_cfg.rx_cfg.promiscous_enable == FALSE) {
+		if_in_discards += p_device_mib->if_in_filtered_frames;
+	}
+
+	/* total rx discards = hal discards */
+	if_in_discards = rx_hal_discards;
+	p_net_dev_stats->rx_dropped = rx_hal_discards;
+	p_net_dev_stats->rx_crc_errors = p_device_mib->if_in_crcerrors;
+	p_net_dev_stats->rx_frame_errors =
+	    p_device_mib->if_in_align_code_errors;
+	p_net_dev_stats->multicast = p_device_mib->if_in_multicasts;
+	if_in_errors = rx_hal_errors;
+	if_out_errors = tx_hal_errors;
+	if_out_discards = p_net_dev_stats->tx_dropped;
+
+	/* let us update the net device stats struct. to be updated in
+	   the later releases. */
+	dev->net_dev_stats.rx_errors = if_in_errors;
+	dev->net_dev_stats.collisions = p_device_mib->if_collision_frames;
+	dev->net_dev_stats.tx_carrier_errors =
+	    p_device_mib->if_carrier_sense_errors;
+
+	if (buf == NULL || limit == 0) {
+		return (0);
+	}
+
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifSpeed",
+			    dev->link_speed);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "dot3StatsDuplexStatus",
+			    dev->link_mode);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifAdminStatus",
+			    (netdev->flags & IFF_UP ? 1 : 2));
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifOperStatus",
+			    (((netdev->flags & IFF_UP)
+			      && netif_carrier_ok(netdev)) ? 1 : 2));
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %lu\n", "ifLastChange",
+			    p_stats->start_tick);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %lu\n", "ifInDiscards",
+			    if_in_discards);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %lu\n", "ifInErrors",
+			    if_in_errors);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %lu\n", "ifOutDiscards",
+			    if_out_discards);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %lu\n", "ifOutErrors",
+			    if_out_errors);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInGoodFrames",
+			    p_device_mib->if_in_good_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInBroadcasts",
+			    p_device_mib->if_in_broadcasts);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInMulticasts",
+			    p_device_mib->if_in_multicasts);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInPauseFrames",
+			    p_device_mib->if_in_pause_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInCRCErrors",
+			    p_device_mib->if_in_crcerrors);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInAlignCodeErrors",
+			    p_device_mib->if_in_align_code_errors);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInOversizedFrames",
+			    p_device_mib->if_in_oversized_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInJabberFrames",
+			    p_device_mib->if_in_jabber_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInUndersizedFrames",
+			    p_device_mib->if_in_undersized_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInFragments",
+			    p_device_mib->if_in_fragments);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInFilteredFrames",
+			    p_device_mib->if_in_filtered_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInQosFilteredFrames",
+			    p_device_mib->if_in_qos_filtered_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifInOctets",
+			    p_device_mib->if_in_octets);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifOutGoodFrames",
+			    p_device_mib->if_out_good_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifOutBroadcasts",
+			    p_device_mib->if_out_broadcasts);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifOutMulticasts",
+			    p_device_mib->if_out_multicasts);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifOutPauseFrames",
+			    p_device_mib->if_out_pause_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifDeferredTransmissions",
+			    p_device_mib->if_deferred_transmissions);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifCollisionFrames",
+			    p_device_mib->if_collision_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifSingleCollisionFrames",
+			    p_device_mib->if_single_collision_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n",
+			    "ifMultipleCollisionFrames",
+			    p_device_mib->if_multiple_collision_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n",
+			    "ifExcessiveCollisionFrames",
+			    p_device_mib->if_excessive_collision_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifLateCollisions",
+			    p_device_mib->if_late_collisions);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifOutUnderrun",
+			    p_device_mib->if_out_underrun);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifCarrierSenseErrors",
+			    p_device_mib->if_carrier_sense_errors);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifOutOctets",
+			    p_device_mib->if_out_octets);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "if64OctetFrames",
+			    p_device_mib->if64octet_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "if65To127POctetFrames",
+			    p_device_mib->if65to127octet_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "if128To255OctetFrames",
+			    p_device_mib->if128to255octet_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "if256To511OctetFrames",
+			    p_device_mib->if256to511octet_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "if512To1023OctetFrames",
+			    p_device_mib->if512to1023octet_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "if1024ToUpOctetFrames",
+			    p_device_mib->if1024to_upoctet_frames);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifNetOctets",
+			    p_device_mib->if_net_octets);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifRxSofOverruns",
+			    p_device_mib->if_rx_sof_overruns);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifRxMofOverruns",
+			    p_device_mib->if_rx_mof_overruns);
+	if (len <= limit)
+		len +=
+		    sprintf(buf + len, "%-35s: %u\n", "ifRxDMAOverruns",
+			    p_device_mib->if_rx_dmaoverruns);
+	*p_len = len;
+
+	return (0);
+}
+
+/* version info */
+static int emac_p_get_version(char *buf, char **start, off_t offset, int count,
+			      int *eof, void *data)
+{
+	int len = 0;
+
+	len += sprintf(buf + len, "Texas Instruments : %s\n",
+		       emac_version_string);
+	return len;
+}
+
+/* tick timer */
+static void emac_p_tick_timer_expiry(emac_dev_t * dev)
+{
+	struct timer_list *p_timer = &dev->periodic_timer;
+
+	if (test_bit(0, &dev->set_to_close)) {
+		return;
+	}
+
+	if (dev->timer_active == TRUE) {
+		emac_tick(dev, NULL);
+
+		/* restart the timer */
+		p_timer->expires = jiffies + dev->periodic_ticks;
+		add_timer(p_timer);
+	}
+}
+
+/* mib timer */
+static void emac_p_mib_timer_expiry(emac_dev_t * dev)
+{
+	struct timer_list *p_timer = &dev->mib_timer;
+
+	if (test_bit(0, &dev->set_to_close)) {
+		return;
+	}
+
+	if (dev->mib_timer_active == TRUE) {
+		emac_control(dev, EMAC_IOCTL_IF_PARAMS_UPDT, NULL, NULL);
+
+		/* restart the timer */
+		p_timer->expires = jiffies + dev->mib_ticks;
+		add_timer(p_timer);
+	}
+}
+
+/******************************************************************************
+ *  Device enable/disable functions
+ *****************************************************************************/
+
+/* enable the device - init TX/RX channels and open DDC */
+static int emac_p_dev_enable(emac_dev_t * dev)
+{
+	int ret_code;
+	struct net_device *netdev = dev->owner;
+
+	dev->set_to_close = 0;
+
+	/* create a TX channel */
+	ret_code = emac_ch_open(dev, &dev->tx_ch_info[0], NULL);
+
+	if (ret_code != EMAC_SUCCESS) {
+		ERR("%s error: Error %08X from EMAC TX Channel Open()\n",
+		    netdev->name, ret_code);
+
+		return (-1);
+	}
+
+	/* create a RX channel - note that last param contains mac address */
+	ret_code =
+	    emac_ch_open(dev, &dev->rx_ch_info[0], (void *)&dev->mac_addr[0]);
+	if (ret_code != EMAC_SUCCESS) {
+		ERR("%s error: Error %08X from EMAC RX Channel Open()\n",
+		    netdev->name, ret_code);
+
+		return (-1);
+	}
+
+	/* open DDC instance */
+	ret_code = emac_open(dev, NULL);
+	if (ret_code != EMAC_SUCCESS) {
+		ERR("%s error: Error %08X from EMAC Open()\n",
+		    netdev->name, ret_code);
+
+		return (-1);
+	}
+
+	return (0);
+}
+
+/* disable the device - teardown chanels and close DDC */
+static int emac_p_dev_disable(emac_dev_t * dev)
+{
+	int ret_code;
+	struct net_device *netdev = dev->owner;
+
+	/* inform the upper layers. */
+	netif_stop_queue(dev->owner);
+
+	/* prepare to close */
+	set_bit(0, &dev->set_to_close);
+
+	/* closing the DDC instance will close all channels also */
+	ret_code = emac_close(dev, NULL);
+
+	if (ret_code != EMAC_SUCCESS) {
+		ERR("%s error: Error %08X from EMAC Close()\n",
+		    netdev->name, ret_code);
+		return (-1);
+	} else {
+		/* DDC should turn off the timer, but just in case */
+		if (dev->timer_active != FALSE) {
+			del_timer_sync(&dev->periodic_timer);
+			dev->timer_active = FALSE;
+		}
+
+		DBG("Device %s Closed.\n", netdev->name);
+		dev->device_stats.start_tick = jiffies;
+		dev->link_speed = 100000000;
+		dev->link_mode = 1;
+		netif_carrier_off(netdev);
+	}
+
+	return (0);
+}
+
+/******************************************************************************
+ *  Net Device functions
+ *****************************************************************************/
+
+/* get statistics */
+static struct net_device_stats *emac_dev_get_net_stats(struct net_device
+						       *netdev)
+{
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+
+	emac_p_update_statistics(netdev, NULL, 0, NULL);
+	return &dev->net_dev_stats;
+}
+
+/* set multicast address in the driver */
+static void emac_dev_mcast_set(struct net_device *netdev)
+{
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+
+	if (netdev->flags & IFF_PROMISC) {
+		/* enable promiscous mode */
+		dev->init_cfg.rx_cfg.promiscous_enable = TRUE;
+
+		emac_control(dev,
+			     EMAC_IOCTL_SET_RXCFG,
+			     (void *)&dev->init_cfg.rx_cfg, NULL);
+	} else if ((netdev->flags & IFF_ALLMULTI) ||
+		   (netdev->mc_count > EMAC_DEFAULT_MAX_MULTICAST_ADDRESSES)) {
+		/* enable multicast - disable promiscous */
+		dev->init_cfg.rx_cfg.promiscous_enable = FALSE;
+		dev->init_cfg.rx_cfg.multicast_enable = TRUE;
+		emac_control(dev,
+			     EMAC_IOCTL_SET_RXCFG,
+			     (void *)&dev->init_cfg.rx_cfg, NULL);
+
+		/* enable all multicast addresses */
+		emac_control(dev, EMAC_IOCTL_ALL_MULTI, (void *)
+			     EMAC_ALL_MULTI_SET, NULL);
+	} else if (netdev->mc_count == 0) {
+		/* only unicast mode to be set - clear promiscous and
+		   clear multicast modes */
+		emac_control(dev, EMAC_IOCTL_ALL_MULTI, (void *)
+			     EMAC_ALL_MULTI_CLR, NULL);
+
+		/* disable promiscous and multicast modes */
+		dev->init_cfg.rx_cfg.promiscous_enable = FALSE;
+		dev->init_cfg.rx_cfg.multicast_enable = FALSE;
+		emac_control(dev,
+			     EMAC_IOCTL_SET_RXCFG,
+			     (void *)&dev->init_cfg.rx_cfg, NULL);
+	} else if (netdev->mc_count) {
+		struct dev_mc_list *mc_ptr;
+
+		/* clear multicast list first */
+		emac_control(dev, EMAC_IOCTL_ALL_MULTI, (void *)
+			     EMAC_ALL_MULTI_CLR, NULL);
+
+		/* enable multicast - disable promiscous */
+		dev->init_cfg.rx_cfg.promiscous_enable = FALSE;
+		dev->init_cfg.rx_cfg.multicast_enable = TRUE;
+		emac_control(dev,
+			     EMAC_IOCTL_SET_RXCFG,
+			     (void *)&dev->init_cfg.rx_cfg, NULL);
+
+		/* program multicast address list into EMAC hardware */
+		for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) {
+			emac_control(dev, EMAC_IOCTL_MULTICAST_ADDR, (void *)
+				     EMAC_MULTICAST_ADD, (void *)
+				     mc_ptr->dmi_addr);
+		}
+	} else {
+		DBG("%s:No Multicast address to set.\n", netdev->name);
+	}
+}
+
+static int emac_dev_set_mac_addr(struct net_device *netdev, void *addr)
+{
+	int ret_code;
+	emac_address_params address_params;
+	struct sockaddr *sa = addr;
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+
+	address_params.channel = EMAC_DEFAULT_RX_CHANNEL;
+	address_params.mac_address = sa->sa_data;
+
+	ret_code =
+	    emac_control(dev,
+			 EMAC_IOCTL_SET_MAC_ADDRESS,
+			 (emac_address_params *) & address_params, NULL);
+
+	if (ret_code != EMAC_SUCCESS) {
+		ERR("%s error: Error %08X from EMAC TX Channel Open()\n",
+		    netdev->name, ret_code);
+
+		return -EIO;
+	}
+	memcpy(dev->mac_addr, sa->sa_data, netdev->addr_len);
+	memcpy(netdev->dev_addr, sa->sa_data, netdev->addr_len);
+	return 0;
+}
+
+static void emac_tx_timeout(struct net_device *netdev)
+{
+	int ret_code;
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+
+	printk("EMAC Tx Timeout: Closing TX channel\n");
+	emac_ch_close(dev,
+		      dev->tx_ch_info[0].ch_num, dev->tx_ch_info[0].ch_dir, 0);
+
+	printk("EMAC Tx Timeout: Opening TX channel\n");
+	ret_code = emac_ch_open(dev, &dev->tx_ch_info[0], NULL);
+
+	if (ret_code != EMAC_SUCCESS) {
+		ERR("%s error: Error %08X from EMAC TX Channel Open()\n",
+		    netdev->name, ret_code);
+	} else {
+		ERR("EMAC Tx Timeout: "
+		    "successfully closed and opened channels\n");
+	}
+
+	/* update interface statistics */
+	dev->net_dev_stats.tx_errors++;
+}
+
+/***************************************************************
+ *  emac_dev_init
+ *
+ *  Returns:
+ *      0 on success, error code otherwise.
+ *  Parms:
+ *      dev The structure of the device to be
+ *          init'ed.
+ *
+ *  This function completes the initialization of the
+ *  device structure and driver.  It reserves the IO
+ *  addresses and assignes the device's methods.
+ *
+ **************************************************************/
+static int emac_dev_init(struct net_device *netdev)
+{
+	int cnt, init_status = 0;
+	int ret_code;
+	char *mac_name = NULL;
+	char *mac_string = NULL;
+	char *default_mac_string = NULL;
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+	int instance_num = dev->instance_num;
+
+	/* create mac name */
+	switch (instance_num) {
+	case 0:
+		mac_name = EMAC_MAC_ADDR_A;
+		emac_eth_setup();
+
+		/* we are getting default MAC address from bootloader */
+		if (strcmp(emac_eth_string, "deadbeaf") == 0) {
+			default_mac_string = "08.00.28.32.06.08";
+		} else {
+			default_mac_string = &emac_eth_string[0];
+		}
+		break;
+	default:
+		mac_name = "";
+		default_mac_string = "08.00.28.32.06.08";
+		break;
+	}
+
+	mac_string = default_mac_string;
+	emac_str_to_ethaddr(dev->mac_addr, mac_string);
+	for (cnt = 0; cnt <= ETH_ALEN; cnt++) {
+		netdev->dev_addr[cnt] = dev->mac_addr[cnt];
+	}
+
+	dev->set_to_close = 1;
+
+	/* get configuration information for this instance */
+	/* when config service is available, use it */
+	if (emac_net_get_config(dev) != 0) {
+		ERR("Could not fetch configuration information\n");
+		goto emac_dev_init_exit;
+	}
+
+	dev->init_cfg.inst_id = instance_num;
+	dev->drv_state = DRV_CREATED;
+	init_status = 1;	/* instance created */
+
+	/* initialize instance by passing initial configuration struct */
+	ret_code = emac_init(dev, &dev->init_cfg);
+
+	if (ret_code != EMAC_SUCCESS) {
+		ERR("Error %08X from Init()\n", ret_code);
+		goto emac_dev_init_exit;
+	}
+
+	init_status = 2;	/* instance initialized */
+
+	/* init spin lock */
+	spin_lock_init(&dev->tx_lock);
+	spin_lock_init(&dev->rx_lock);
+
+	/* set as per RFC 2665 */
+	dev->link_speed = 100000000;
+	dev->link_mode = 1;
+
+	/* initialize the timers for the net device - the timer will
+	   be started by DDC calling the ioctl on DDA */
+	init_timer(&dev->periodic_timer);
+	dev->periodic_ticks = 0;
+	dev->periodic_timer.expires = 0;
+	dev->timer_active = FALSE;
+	dev->periodic_timer.data = (unsigned long)dev;
+	dev->periodic_timer.function =
+	    (timer_tick_func) emac_p_tick_timer_expiry;
+	init_timer(&dev->mib_timer);
+	dev->mib_timer_active = FALSE;
+	dev->mib_timer.data = (unsigned long)dev;
+	dev->mib_timer.function = (timer_tick_func) emac_p_mib_timer_expiry;
+
+	/* populate the device structure */
+	netdev->addr_len = 6;
+	netdev->open = emac_dev_open;	/*  i.e. start device  */
+	netdev->do_ioctl = emac_ioctl;
+	netdev->hard_start_xmit = emac_dev_tx;
+	netdev->stop = emac_dev_close;
+	netdev->get_stats = emac_dev_get_net_stats;
+	netdev->set_multicast_list = emac_dev_mcast_set;
+	netdev->tx_timeout = emac_tx_timeout;
+	netdev->set_mac_address = emac_dev_set_mac_addr;
+	netdev->poll = emac_poll;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	netdev->poll_controller = emac_poll_controller;
+#endif
+	netdev->weight = EMAC_DEFAULT_RX_MAX_SERVICE;
+
+	/* reset the broadcast and multicast flags and enable them
+	   based upon configuration of driver */
+	netdev->flags &= ~(IFF_PROMISC | IFF_BROADCAST | IFF_MULTICAST);
+	if (dev->init_cfg.rx_cfg.broadcast_enable == TRUE)
+		netdev->flags |= IFF_BROADCAST;
+	if (dev->init_cfg.rx_cfg.multicast_enable == TRUE)
+		netdev->flags |= IFF_MULTICAST;
+
+	netif_carrier_off(netdev);
+	netdev->irq = dev->init_cfg.intr_line;
+
+	/* request memory region from the kernel */
+	netdev->base_addr = dev->init_cfg.base_address;
+	request_mem_region(netdev->base_addr, EMAC_DEFAULT_EMAC_SIZE,
+			   netdev->name);
+
+	/* if following flag ON then open DDC */
+	if (g_init_enable_flag) {
+		if (emac_p_dev_enable(dev)) {
+			ERR("device could not OPEN\n");
+			goto emac_dev_init_exit;
+		}
+	}
+
+	return (0);
+
+      emac_dev_init_exit:
+	/* all resources allocated are freed - call the un-init
+	   sequence on DDC */
+	switch (init_status) {
+
+	case 2:
+		ret_code = emac_de_init(dev, NULL);
+
+		if (ret_code != EMAC_SUCCESS)
+			ERR("%s: Error %08X from Deinit()\n",
+			    netdev->name, ret_code);
+	default:
+		break;
+	}
+
+	return (-1);
+}
+
+/******************************************************************************
+ *  Device Open/Close functions
+ *****************************************************************************/
+
+/* open the adapter */
+static int emac_dev_open(struct net_device *netdev)
+{
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+
+	if (!g_init_enable_flag) {
+		if (emac_p_dev_enable(dev)) {
+			ERR("%s error: device could not OPEN\n", netdev->name);
+			return (-1);
+		}
+	}
+
+	if (request_irq(dev->init_cfg.intr_line, emac_hal_isr, IRQF_DISABLED,
+			"EMAC", dev)) {
+		ERR("Failed to register the irq %d for TI DaVinci EMAC %s.\n",
+		    dev->init_cfg.intr_line, netdev->name);
+
+		return (-1);
+	}
+	if (netif_carrier_ok(netdev))
+		netif_start_queue(netdev);
+	else
+		netif_stop_queue(netdev);
+
+	dev->device_stats.start_tick = jiffies;
+	DBG("Started the network queue for %s.\n", netdev->name);
+	return (0);
+}
+
+/* close the adapter */
+static int emac_dev_close(struct net_device *netdev)
+{
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+
+	if (!g_init_enable_flag)
+		emac_p_dev_disable(dev);
+
+	/* free ISR */
+	free_irq(dev->init_cfg.intr_line, dev);
+
+	return (0);
+}
+
+/* ioctl function */
+static int emac_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd)
+{
+	emac_drv_priv_ioctl priv_ioctl;
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+
+	if (cmd == SIOCDEVPRIVATE) {
+		/* copy user data */
+		if (copy_from_user
+		    ((char *)&priv_ioctl, (char *)rq->ifr_data,
+		     sizeof(emac_drv_priv_ioctl)))
+			return -EFAULT;
+
+		switch (priv_ioctl.cmd) {
+			/* program type 2/3 address filter */
+		case EMAC_PRIV_FILTERING:
+			{
+				emac_type2_3_addr_filter_params filter_params;
+
+				if (copy_from_user
+				    ((char *)&filter_params,
+				     (char *)priv_ioctl.data,
+				     sizeof(emac_type2_3_addr_filter_params)))
+
+					return -EFAULT;
+
+				if (emac_control(dev,
+						 EMAC_IOCTL_TYPE2_3_FILTERING,
+						 (emac_type2_3_addr_filter_params
+						  *) & filter_params, NULL)
+				    != EMAC_SUCCESS) {
+					ERR("Failed to read params");
+					return -EFAULT;
+				}
+				break;
+			}
+
+			/* read PHY register via MII interface */
+		case EMAC_PRIV_MII_READ:
+			{
+				emac_phy_params phy_params;
+				unsigned long irq_flags;
+
+				/* copy user data into local variable */
+				if (copy_from_user
+				    ((char *)&phy_params,
+				     (char *)priv_ioctl.data,
+				     sizeof(emac_phy_params)))
+					return -EFAULT;
+
+				/* make sure this function does not
+				 * clash with mii access during tick
+				 * function */
+				local_irq_save(irq_flags);
+
+				if (emac_control(dev,
+						 EMAC_IOCTL_READ_PHY_REG,
+						 (void *)&phy_params,
+						 NULL) != EMAC_SUCCESS) {
+					ERR("Failed to read params");
+					return -EFAULT;
+				}
+
+				/* copy the local data to user space */
+				if (copy_to_user
+				    ((char *)priv_ioctl.data,
+				     (char *)&phy_params,
+				     sizeof(emac_phy_params)))
+					return -EFAULT;
+
+				/* enable tick timer to access phy now
+				   if required */
+				local_irq_restore(irq_flags);
+			}
+
+			break;
+
+			/* write PHY register via MII interface */
+		case EMAC_PRIV_MII_WRITE:
+			{
+				emac_phy_params phy_params;
+				unsigned long irq_flags;
+
+				/* copy user data into local variable */
+				if (copy_from_user
+				    ((char *)&phy_params,
+				     (char *)priv_ioctl.data,
+				     sizeof(emac_phy_params)))
+					return -EFAULT;
+
+				/* make sure this function does not
+				   clash with mii access during tick
+				   function */
+				local_irq_save(irq_flags);
+
+				if (emac_control(dev,
+						 EMAC_IOCTL_WRITE_PHY_REG,
+						 (void *)&phy_params,
+						 NULL) != EMAC_SUCCESS) {
+					ERR("Failed to read params");
+					return -EFAULT;
+				}
+
+				/* enable tick timer to access phy now
+				   if required */
+				local_irq_restore(irq_flags);
+			}
+			break;
+
+			/* get statistics */
+		case EMAC_PRIV_GET_STATS:
+			{
+				emac_hw_statistics stats;
+
+				/* Caller provides memory for HW stats
+				   structure via "data" pointer */
+				if (emac_control(dev,
+						 EMAC_IOCTL_GET_STATISTICS,
+						 (void *)&stats, NULL)
+				    != EMAC_SUCCESS) {
+					ERR("Failed to get statistics");
+					return (EMAC_INTERNAL_FAILURE);
+				}
+
+				/* copy the local data to user space */
+				if (copy_to_user
+				    ((char *)priv_ioctl.data, (char *)&stats,
+				     sizeof(emac_hw_statistics)))
+					return -EFAULT;
+				break;
+			}
+
+			/* clear statistics */
+		case EMAC_PRIV_CLR_STATS:
+			{
+				if (emac_control(dev,
+						 EMAC_IOCTL_CLR_STATISTICS,
+						 NULL, NULL)
+				    != EMAC_SUCCESS) {
+					ERR("Failed to clear statistics");
+					return (EMAC_INTERNAL_FAILURE);
+				}
+				break;
+			}
+		default:
+			return -EFAULT;
+			break;
+		}
+	}
+
+	else if (cmd == SIOTIMIB2) {
+		TI_SNMP_CMD_T ti_snmp_cmd;
+
+		/* now copy the user data */
+		if (copy_from_user
+		    ((char *)&ti_snmp_cmd, (char *)rq->ifr_data,
+		     sizeof(TI_SNMP_CMD_T)))
+			return -EFAULT;
+
+		switch (ti_snmp_cmd.cmd) {
+		case TI_SIOCGINTFCOUNTERS:
+			{
+				struct mib2_if_counters mib_counter;
+
+				/* Caller provides memory for HW stats
+				   structure via "data" pointer */
+				if (emac_control(dev,
+						 EMAC_IOCTL_IF_COUNTERS,
+						 (void *)&mib_counter, NULL)
+				    != EMAC_SUCCESS) {
+					ERR("Failed to get statistics");
+					return (EMAC_INTERNAL_FAILURE);
+				}
+
+				/* copy the local data to user space */
+				if (copy_to_user
+				    ((char *)ti_snmp_cmd.data,
+				     (char *)&mib_counter,
+				     sizeof(struct mib2_if_counters)))
+					return -EFAULT;
+				break;
+			}
+		case TI_SIOCGINTFPARAMS:
+			{
+				struct mib2_if_params local_params;
+
+				local_params.if_speed = dev->link_speed;
+				local_params.if_high_speed =
+				    (local_params.if_speed) / 1000000;
+				local_params.if_oper_status =
+				    ((netdev->
+				      flags & IFF_UP) ? MIB2_STATUS_UP :
+				     MIB2_STATUS_DOWN);
+				local_params.if_promiscuous_mode =
+				    ((netdev->
+				      flags & IFF_PROMISC) ? TRUE : FALSE);
+
+				/* now copy the counters to the user data */
+				if (copy_to_user
+				    ((char *)ti_snmp_cmd.data,
+				     (char *)&local_params,
+				     sizeof(struct mib2_if_params)))
+					return -EFAULT;
+			}
+			break;
+
+		case TI_SIOCGETHERCOUNTERS:
+			{
+				struct mib2_phy_counters phy_counter;
+
+				/* Caller provides memory for HW stats
+				   structure via "data" pointer */
+				if (emac_control(dev,
+						 EMAC_IOCTL_ETHER_COUNTERS,
+						 (void *)&phy_counter, NULL)
+				    != EMAC_SUCCESS) {
+					ERR("Failed to get statistics");
+
+					return (EMAC_INTERNAL_FAILURE);
+				}
+
+				/* copy the local data to user space */
+				if (copy_to_user
+				    ((char *)ti_snmp_cmd.data,
+				     (char *)&phy_counter,
+				     sizeof(struct mib2_phy_counters)))
+					return -EFAULT;
+				break;
+			}
+
+		case TI_SIOCGETHERPARAMS:
+			{
+				struct mib2_eth_params local_params;
+
+				local_params.eth_duplex_status =
+				    ((dev->link_mode ==
+				      PHY_DUPLEX_FULL) ?
+					MIB2_FULL_DUPLEX : MIB2_HALF_DUPLEX);
+
+				/* now copy the counters to the user data */
+				if (copy_to_user
+				    ((char *)ti_snmp_cmd.data,
+				     (char *)&local_params,
+				     sizeof(struct mib2_eth_params)))
+					return -EFAULT;
+				break;
+			}
+
+		default:
+			return -EFAULT;
+		}
+	} else {
+		return -EFAULT;
+	}
+
+	return (0);
+}
+
+/* PHY related interface below */
+#include "davinci_emac_phy.h"
+
+/************************ HASH SUPPORT FUNCTIONS ************************/
+
+/* get hash value using mechainsm in specs */
+static u32 hash_get(u8 * addr)
+{
+	u32 hash;
+	u8 tmpval;
+	int cnt;
+	hash = 0;
+
+	for (cnt = 0; cnt < 2; cnt++) {
+		tmpval = *addr++;
+		hash ^= (tmpval >> 2) ^ (tmpval << 4);
+		tmpval = *addr++;
+		hash ^= (tmpval >> 4) ^ (tmpval << 2);
+		tmpval = *addr++;
+		hash ^= (tmpval >> 6) ^ (tmpval);
+	}
+
+	return (hash & 0x3F);
+}
+
+/**
+ * Hash Table Add
+ * - Adds mac address to hash table and upates hash bits in hardware
+ * - Returns negative if error, 0 if no change to registers, >0 if
+ *   hash registers need to change
+ */
+static int hash_add(emac_dev_t * _dev, u8 * mac_address)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	u32 hash_value;
+	u32 hash_bit;
+	u32 status = 0;
+	hash_value = hash_get(mac_address);
+
+	if (hash_value >= EMAC_NUM_MULTICAST_BITS) {
+		LOGERR("Invalid Hash Value=%d. Should not be greater than %d",
+		       hash_value, (EMAC_NUM_MULTICAST_BITS - 1));
+		return (EMAC_INVALID_PARAM);
+	}
+
+	/* set the hash bit only if not previously set */
+	if (dev->multicast_hash_cnt[hash_value] == 0) {
+		status = 1;
+		if (hash_value < 32) {
+			hash_bit = (1 << hash_value);
+			dev->mac_hash1 |= hash_bit;
+		} else {
+			hash_bit = (1 << (hash_value - 32));
+			dev->mac_hash2 |= hash_bit;
+		}
+	}
+
+	/* increment counter to maintain number of multicast address
+	   that map to this hash bit  */
+	++dev->multicast_hash_cnt[hash_value];
+
+	return (status);
+}
+
+/**
+ * Hash Table Del
+ * - Deletes a mac address from hash table and updates hash register bits
+ * - Returns negative if error, 0 if no change to registers, >0 if
+ *   hash registers need to change
+ */
+static int hash_del(emac_dev_t * _dev, u8 * mac_address)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	u32 hash_value;
+	u32 hash_bit;
+
+	hash_value = hash_get(mac_address);
+	if (dev->multicast_hash_cnt[hash_value] > 0) {
+		/* decrement counter to reduce number of multicast
+		 * address that map to this hash bit  */
+		--dev->multicast_hash_cnt[hash_value];
+	}
+
+	/* if counter still > 0, at least one multicast address refers
+	 * to this hash bit. so return 0 */
+	if (dev->multicast_hash_cnt[hash_value] > 0) {
+		return (0);
+	}
+
+	if (hash_value < 32) {
+		hash_bit = (1 << hash_value);
+		dev->mac_hash1 &= ~hash_bit;
+	} else {
+		hash_bit = (1 << (hash_value - 32));
+		dev->mac_hash2 &= ~hash_bit;
+	}
+
+	/* return 1 to indicate change in mac_hash registers reqd */
+	return (1);
+}
+
+/* updates hash register bits with single multicast address add/delete
+ * operation */
+static void emac_single_multi(emac_dev_t * _dev, emac_single_multi_oper oper,
+			      u8 * addr)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	int status = -1;
+
+	switch (oper) {
+	case EMAC_MULTICAST_ADD:
+		status = hash_add(_dev, addr);
+		break;
+
+	case EMAC_MULTICAST_DEL:
+		status = hash_del(_dev, addr);
+		break;
+
+	default:
+		LOGERR("Unhandled Single Multicast operation %d", oper);
+		break;
+	}
+
+	/* write to the hardware only if the register status chances */
+	if (status > 0) {
+		dev->regs->mac_hash1 = dev->mac_hash1;
+		dev->regs->mac_hash2 = dev->mac_hash2;
+	}
+}
+
+/* updates hash register bits for all multi operation (set/clear) */
+static void emac_all_multi(emac_dev_t * _dev, emac_all_multi_oper oper)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	switch (oper) {
+	case EMAC_ALL_MULTI_SET:
+		dev->mac_hash1 = EMAC_ALL_MULTI_REG_VALUE;
+		dev->mac_hash2 = EMAC_ALL_MULTI_REG_VALUE;
+		break;
+	case EMAC_ALL_MULTI_CLR:
+		dev->mac_hash1 = 0;
+		dev->mac_hash2 = 0;
+		memset(&(dev->multicast_hash_cnt[0]), 0 ,
+		sizeof(dev->multicast_hash_cnt[0]) * EMAC_NUM_MULTICAST_BITS);
+		break;
+	default:
+		LOGERR("Unhandled All multi operation %d", oper);
+		break;
+	}
+
+	dev->regs->mac_hash1 = dev->mac_hash1;
+	dev->regs->mac_hash2 = dev->mac_hash2;
+}
+
+/************************ PHY related functions ************************/
+
+/* Cpmac Update Phy Status - updates phy status variables in hDDC->status "CpmacDDCStatus" structure */
+static int emac_update_phy_status(emac_dev_t * _dev)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	u32 set_phy_mode;
+
+	LOGMSG(EMAC_DEBUG_BUSY_FUNCTION_ENTRY, "");
+
+	/* verify proper device state */
+	if (dev->drv_state != DRV_OPENED) {
+		LOGERR("Device NOT Open");
+		return (EMAC_ERR_DEV_NOT_OPEN);
+	}
+
+	set_phy_mode = dev->init_cfg.phy_mode;
+
+	/* no phy condition */
+	if (set_phy_mode & SNWAY_NOPHY) {
+		/*  no phy condition, always linked */
+		dev->status.phy_linked = 1;
+		dev->status.phy_speed = 100;
+		dev->status.phy_duplex = PHY_DUPLEX_FULL;
+		dev->status.phy_num = 0xFFFFFFFF;	/* no phy */
+		dev->mac_control |= (1 << EMAC_MACCONTROL_FULLDUPLEXEN_SHIFT);
+
+		/* write mac control register from stored value */
+		dev->regs->mac_control = dev->mac_control;
+		goto emac_update_phy_status_exit;
+	}
+
+	/* if loopback set in hardware, set link to ON */
+	if (dev->mac_control & EMAC_MACCONTROL_LOOPBKEN_MASK) {
+		dev->status.phy_linked = 1;
+		goto emac_update_phy_status_exit;
+	}
+	if (set_phy_mode & SNWAY_LPBK) {
+		dev->status.phy_linked = emac_mdio_is_loopback();
+	} else {
+		dev->status.phy_linked = emac_mdio_is_linked();
+	}
+
+	if (dev->status.phy_linked) {
+		/*  retreive duplex and speed and the phy number  */
+		if (set_phy_mode & SNWAY_LPBK) {
+			dev->status.phy_duplex = PHY_DUPLEX_FULL;
+		} else {
+			dev->status.phy_duplex = emac_mdio_get_duplex();
+		}
+		dev->status.phy_speed = emac_mdio_get_speed();
+		dev->status.phy_num = emac_mdio_get_phy_num();
+
+		/* set the duplex bit in maccontrol */
+		if (dev->status.phy_duplex == PHY_DUPLEX_FULL) {
+			dev->mac_control |=
+			    (1 << EMAC_MACCONTROL_FULLDUPLEXEN_SHIFT);
+		} else {
+			dev->mac_control &=
+			    ~(1 << EMAC_MACCONTROL_FULLDUPLEXEN_SHIFT);
+		}
+
+	}
+
+	/* write mac control register from stored value */
+	dev->regs->mac_control = dev->mac_control;
+
+      emac_update_phy_status_exit:
+	LOGMSG(EMAC_DEBUG_PORT_UPDATE,
+	       "MacControl=%08X, Status: Phy=%d, Speed=%s, Duplex=%s",
+	       dev->mac_control, dev->status.phy_num,
+	       (dev->status.phy_speed == 100) ? "100" : "10",
+	       (dev->status.phy_duplex == PHY_DUPLEX_FULL) ? "Full" : "Half");
+	LOGMSG(EMAC_DEBUG_BUSY_FUNCTION_EXIT, "");
+
+	return (EMAC_SUCCESS);
+}
+
+/* set phy mode */
+static int emac_set_phy_mode(emac_dev_t * _dev)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	u32 set_phy_mode;
+	u32 phy_mode;
+
+	LOGMSG(EMAC_DEBUG_BUSY_FUNCTION_ENTRY, "");
+
+	/* verify proper device state */
+	if (dev->drv_state != DRV_OPENED) {
+		LOGERR("Device NOT Open");
+		return (EMAC_ERR_DEV_NOT_OPEN);
+	}
+
+	set_phy_mode = dev->init_cfg.phy_mode;
+	phy_mode = 0;
+	if (set_phy_mode & SNWAY_AUTO)
+		phy_mode |= NWAY_AUTO;
+	if (set_phy_mode & SNWAY_FD10)
+		phy_mode |= NWAY_FD10;
+	if (set_phy_mode & SNWAY_FD100)
+		phy_mode |= NWAY_FD100;
+	if (set_phy_mode & SNWAY_HD10)
+		phy_mode |= NWAY_HD10;
+	if (set_phy_mode & SNWAY_HD100)
+		phy_mode |= NWAY_HD100;
+	if (set_phy_mode & SNWAY_LPBK)
+		phy_mode |= NWAY_LPBK;
+	if (set_phy_mode & SNWAY_AUTOMDIX)
+		phy_mode |= NWAY_AUTOMDIX;
+	/* check for EMAC bus frequency for correct speed operation */
+	if ((set_phy_mode & SNWAY_FD10) || (set_phy_mode & SNWAY_HD10)) {
+		if (dev->init_cfg.emac_bus_frequency <=
+		    EMAC_MIN_FREQUENCY_FOR_10MBPS)
+			LOGERR("Bus speedemacSetPhyMode: CpmacFreq(%d) "
+			       "is less than required %d freq for "
+			       "10Mbps support. CANNOT SUPPORT 10Mbps",
+			       dev->init_cfg.emac_bus_frequency,
+			       EMAC_MIN_FREQUENCY_FOR_10MBPS);
+	}
+
+	else if ((set_phy_mode & SNWAY_FD100) || (set_phy_mode & SNWAY_HD100)) {
+		if (dev->init_cfg.emac_bus_frequency <=
+		    EMAC_MIN_FREQUENCY_FOR_100MBPS)
+
+			LOGERR("freq(%d) is less than required %d freq for "
+			       "100Mbps support. CANNOT SUPPORT 100Mbps",
+			       dev->init_cfg.emac_bus_frequency,
+			       EMAC_MIN_FREQUENCY_FOR_100MBPS);
+	}
+
+	/* TODO: check for gigabit mode when PHY mode defines for
+	 * gigabit are available */
+	LOGMSG(EMAC_DEBUG_PORT_UPDATE,
+	       "MdioPhyMode=%08X, PhyMode=%08d, Auto:%d, FD10:%d, "
+	       "HD10:%d, FD100:%d, HD100:%d",
+	       set_phy_mode, phy_mode,
+	       (phy_mode & NWAY_AUTO), (phy_mode & NWAY_FD10),
+	       (phy_mode & NWAY_HD10),
+	       (phy_mode & NWAY_FD100), (phy_mode & NWAY_HD100));
+	emac_mdio_set_phy_mode(phy_mode);
+	emac_update_phy_status(_dev);
+	LOGMSG(EMAC_DEBUG_BUSY_FUNCTION_EXIT, "");
+
+	return (EMAC_SUCCESS);
+}
+
+/***************** MAC ADDRESSING MODE SUPPORT FUNCTIONS ********************/
+
+/* this function sets / clears the unicast flag in hardware */
+static void emac_rx_uni_cast(emac_dev_t * _dev, u32 channel, bool enable)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	/* update local copy of register to save cycles in reading the
+	 * register */
+	if (enable == TRUE) {
+		dev->rx_unicast_set |= (1 << channel);
+		dev->rx_unicast_clear &= ~(1 << channel);
+	} else {
+		/* disable unicast channel setting */
+		dev->rx_unicast_clear |= (1 << channel);
+		dev->rx_unicast_set &= ~(1 << channel);
+	}
+
+	/* write to hardware if device is open */
+	if (dev->drv_state == DRV_OPENED) {
+		dev->regs->rx_unicast_set = dev->rx_unicast_set;
+		dev->regs->rx_unicast_clear = dev->rx_unicast_clear;
+	}
+}
+
+/**
+ * EMAC Add Type 0 Address
+ *  - set mac address for type 0 addressing (EMAC)
+ *
+ * This is an internal function of the DDC called from channel
+ * enable API which does channel number range checking and hence its
+ * not required.  It is assumed that this function will get the
+ * correct channel number always
+ */
+static void emac_add_type0addr(emac_dev_t * _dev, u32 channel,
+			       char *mac_address)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	dev->regs->mac_src_addr_lo = (mac_address[0] << 8) | (mac_address[1]);
+	dev->regs->mac_src_addr_hi = (mac_address[2] << 24) |
+		(mac_address[3] << 16) | (mac_address[4] << 8) |
+		(mac_address[5]);
+
+	/* enable unicast */
+	emac_rx_uni_cast(_dev, channel, TRUE);
+}
+
+/**
+ * EMAC Add Type 1 Address
+ *  - set mac address for type 1 addressing (EMAC)
+ *
+ * This is an internal function of the DDC called from channel enable
+ * API which does channel number range checking and hence its not required.
+ * It is assumed that this function will get the correct channel number always
+ */
+static void emac_add_type1addr(emac_dev_t * _dev, u32 channel,
+			       char *mac_address)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	/* set mac_index register with channel number */
+	dev->regs->mac_index = channel;
+
+	/* set mac_addr_hi register */
+	dev->regs->mac_addr_hi =
+	    (mac_address[3] << 24) | (mac_address[2] << 16) |
+	    (mac_address[1] << 8) | (mac_address[0]);
+
+	/* set mac_addr_lo register */
+	dev->regs->mac_addr_lo = ((mac_address[5] << 8) | mac_address[4]);
+
+	/* set mac hash */
+	dev->regs->mac_hash1 = 0;
+	dev->regs->mac_hash2 = 0;
+
+	/* As per discussion with hardware folks, it is mandatory to
+	   set the source address of the mac, else correct behaviour
+	   is not guaranteed */
+	emac_add_type0addr(_dev, channel, mac_address);
+
+	/* enable unicast */
+	emac_rx_uni_cast(_dev, channel, TRUE);
+}
+
+/* CPGMAC CFIG 2/3 type addressing - filtering */
+static void emac_add_type2addr(emac_dev_t * _dev, u32 channel,
+			       char *mac_address,
+			       int index, bool valid, int match)
+{
+	/* not supported in DaVinci */
+}
+
+/************************ HARDWARE CONFIGURATION SUPPORT FUNCTIONS ************************/
+
+/* set RX hardware configuration */
+void emac_set_rx_hw_cfg(emac_dev_t * _dev)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	emac_rx_config *rx_cfg;
+	u32 rx_mbp_enable;
+
+	if (dev->drv_state != DRV_OPENED) {
+		LOGERR("Function called when device is NOT in open state");
+		return;
+	}
+
+	rx_cfg = &dev->init_cfg.rx_cfg;
+
+	/* set RX MBP enable register */
+	rx_mbp_enable =
+	    ((rx_cfg->pass_crc & 0x1) << EMAC_RXMBP_PASSCRC_SHIFT) |
+	    ((rx_cfg->qos_enable & 0x1) << EMAC_RXMBP_QOSEN_SHIFT) |
+	    ((rx_cfg->no_buffer_chaining & 0x1) << EMAC_RXMBP_NOCHAIN_SHIFT) |
+	    ((rx_cfg->
+	      copy_maccontrol_frames_enable & 0x1) << EMAC_RXMBP_CMFEN_SHIFT) |
+	    ((rx_cfg->
+	      copy_short_frames_enable & 0x1) << EMAC_RXMBP_CSFEN_SHIFT) |
+	    ((rx_cfg->
+	      copy_error_frames_enable & 0x1) << EMAC_RXMBP_CEFEN_SHIFT) |
+	    ((rx_cfg->
+	      promiscous_enable & 0x1) << EMAC_RXMBP_CAFEN_SHIFT) |
+		((rx_cfg->promiscous_channel & EMAC_RXMBP_CHMASK)
+		 << EMAC_RXMBP_PROMCH_SHIFT) |
+		((rx_cfg->broadcast_enable & 0x1) << EMAC_RXMBP_BROADEN_SHIFT)|
+		((rx_cfg->broadcast_channel & EMAC_RXMBP_CHMASK) <<
+		 EMAC_RXMBP_BROADCH_SHIFT) |
+		((rx_cfg->multicast_enable & 0x1) << EMAC_RXMBP_MULTIEN_SHIFT)|
+		((rx_cfg-> multicast_channel & EMAC_RXMBP_CHMASK) <<
+		 EMAC_RXMBP_MULTICH_SHIFT);
+
+	if (rx_cfg->promiscous_enable) {
+		/* disable mcast bcast and unicast:  H/W limitation */
+		rx_mbp_enable &= ~(0x1 << EMAC_RXMBP_BROADEN_SHIFT);
+		rx_mbp_enable &= ~(0x1 << EMAC_RXMBP_MULTIEN_SHIFT);
+
+		/* disable unicast - warning!! assuming only one
+		 * channel open */
+		emac_rx_uni_cast(_dev, (dev->rx_cppi[0])->ch_info.ch_num,
+				 FALSE);
+	} else {
+		/* enable unicast - warning!! assuming only one
+		 * channel open */
+		emac_rx_uni_cast(_dev, (dev->rx_cppi[0])->ch_info.ch_num, TRUE);
+	}
+
+	if (dev->rx_MBP_enable != rx_mbp_enable) {
+		dev->rx_MBP_enable = rx_mbp_enable;
+		dev->regs->rx_MBP_enable = rx_mbp_enable;
+	}
+
+	/* set max rx packet length */
+	dev->regs->rx_maxlen =
+	    (rx_cfg->max_rx_pkt_length & EMAC_RX_MAX_LEN_MASK);
+
+	/* set rx buffer offset */
+	dev->regs->rx_buffer_offset =
+	    (rx_cfg->buffer_offset & EMAC_RX_BUFFER_OFFSET_MASK);
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT,
+	       "Rx_MBP_Enable = 0x%08x\n", rx_mbp_enable);
+}
+
+/* set MAC configuration - MACControl register */
+static void emac_set_mac_hw_cfg(emac_dev_t * _dev)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	emac_mac_config *mac_cfg;
+	u32 mac_control;
+
+	if (dev->drv_state != DRV_OPENED) {
+		LOGERR("Function called when device is NOT in open state");
+		return;
+	}
+
+	mac_cfg = &dev->init_cfg.mac_cfg;
+	mac_control =
+	    ((mac_cfg->
+	      tx_short_gap_enable & 0x1) << EMAC_MACCONTROL_TXSHORTGAPEN_SHIFT)
+	    | (((mac_cfg->p_type == EMAC_TXPRIO_FIXED) ? 0x1 : 0) <<
+	       EMAC_MACCONTROL_TXPTYPE_SHIFT)
+	    | ((mac_cfg->giga_bit_enable & 0x1) <<
+	       EMAC_MACCONTROL_GIGABITEN_SHIFT) | ((mac_cfg->
+						    tx_pacing_enable & 0x1) <<
+						   EMAC_MACCONTROL_TXPACEEN_SHIFT)
+	    |
+	    /* THIS LINE FOR REFERENCE ONLY ((mac_cfg->mii_enable & 0x1) << EMAC_MACCONTROL_MIIEN_SHIFT) | */
+	    (dev->mac_control & EMAC_MACCONTROL_MIIEN_MASK) |
+	    ((mac_cfg->
+	      tx_flow_enable & 0x1) << EMAC_MACCONTROL_TXFLOWEN_SHIFT) |
+	    ((mac_cfg->
+	      rx_flow_enable & 0x1) << EMAC_MACCONTROL_RXFLOWEN_SHIFT) |
+	    ((mac_cfg->
+	      loopback_enable & 0x1) << EMAC_MACCONTROL_LOOPBKEN_SHIFT) |
+	    (dev->mac_control & EMAC_MACCONTROL_FULLDUPLEXEN_MASK);
+
+	if (dev->mac_control != mac_control) {
+		dev->mac_control = mac_control;
+		dev->regs->mac_control = mac_control;
+	}
+}
+
+/**
+ * EMAC Init
+ *  - validates max TX/RX channels and stores initial configuration
+ *
+ * Initial configuration passed by via the "init_cfg" parameter
+ */
+static int emac_init(emac_dev_t * _dev, emac_init_config * init_cfg)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY, "");
+
+	/* validate num_tx and num_rx channels */
+	if ((init_cfg->num_tx_channels > EMAC_MAX_TX_CHANNELS) ||
+	    (init_cfg->num_rx_channels > EMAC_MAX_RX_CHANNELS)) {
+		LOGERR("Invalid number of TX/RX channels");
+		return (EMAC_INVALID_PARAM);
+	}
+
+	/* save config info for later use */
+	dev->init_cfg = *init_cfg;	/* structure copy */
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT, "");
+	return (EMAC_SUCCESS);
+}
+
+/* EMAC DDC DeInit
+ * Stub function - no functionality required as per this implementation
+ */
+static int emac_de_init(emac_dev_t * _dev, void *param)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY, "");
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT, "");
+
+	return (EMAC_SUCCESS);
+}
+
+/**
+ * EMAC DDC Open
+ *  - Brings module out of reset
+ *  - Open's CSL, programs mandatory hardware init registers
+ *  - Open's MII_MDIO module and enable poll timer via DDA
+ *  - Enables earlier created TX/RX channels
+ *  - Enables TX/RX operation in hardware
+ *
+ * "param" not used in this implementation
+ */
+static int emac_open(emac_dev_t * _dev, void *param)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	u32 channel;
+	u32 mii_mod_id, mii_rev_maj, mii_rev_min;
+	int ret_val;
+	emac_init_config *init_cfg;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY, "");
+
+	if (dev->drv_state == DRV_OPENED) {
+		LOGERR("Device already open");
+		return (EMAC_ERR_DEV_ALREADY_OPEN);
+	}
+
+	/* get init config info structure pointer for easy access */
+	init_cfg = &dev->init_cfg;
+	dev->regs = (emac_regs_ovly) init_cfg->base_address;
+	dev->e_wrap_regs = (ewrap_regs *) init_cfg->e_wrap_base_address;
+
+	/* set the BD memory pointer */
+	emac_wrapper_ptr = EMAC_WRAPPER_RAM_ADDR;
+
+	/* bring EMAC out of reset - for clean implementation, reset
+	 * and then unreset the module */
+	/* for EMAC 2.6 and beyond, reset is internal to the module */
+	dev->regs->soft_reset = 1;
+
+	while (dev->regs->soft_reset) {
+		/* wait for reset to complete - do nothing */
+	}
+
+	/* program TX/RX HDP's to 0 */
+	for (channel = 0; channel < EMAC_MAX_TX_CHANNELS; channel++) {
+		dev->regs->tx_HDP[channel] = 0;
+
+		/* initialize the completion pointers to 0 */
+		dev->regs->tx_CP[channel] = 0;
+	}
+
+	for (channel = 0; channel < EMAC_MAX_RX_CHANNELS; channel++) {
+		dev->regs->rx_HDP[channel] = 0;
+
+		/* initialize the completion pointers to 0 */
+		dev->regs->rx_CP[channel] = 0;
+	}
+
+	/* enable TX/RX DMA */
+	dev->regs->tx_control |= EMAC_TX_CONTROL_TX_ENABLE_VAL;
+	dev->regs->rx_control |= EMAC_RX_CONTROL_RX_ENABLE_VAL;
+
+	/* enable adapter check interrupts - disable stats interupt */
+	dev->regs->mac_int_mask_set = EMAC_MAC_HOST_ERR_INTMASK_VAL;
+
+	/* set device state - opened - useful when opening channels */
+	dev->drv_state = DRV_OPENED;
+
+	/* set the mac_control register */
+	emac_set_mac_hw_cfg(_dev);
+
+	/* start MDIO autonegotiation and set phy mode */
+	emac_mdio_get_ver(init_cfg->mdio_base_address,
+			  &mii_mod_id, &mii_rev_maj, &mii_rev_min);
+
+	LOGMSG(EMAC_DEBUG_PORT_UPDATE,
+	       "MII Module Id=%d, MII Base Address=%08X, Major Rev=%d, "
+	       "Minor Rev=%d",
+	       mii_mod_id, init_cfg->mdio_base_address,
+	       mii_rev_maj, mii_rev_min);
+
+	/* no failure code returned from this function */
+	emac_mdio_init(init_cfg->mdio_base_address,
+		       dev->init_cfg.inst_id,
+		       init_cfg->phy_mask,
+		       init_cfg->MLink_mask,
+		       init_cfg->mdio_bus_frequency,
+		       init_cfg->mdio_clock_frequency,
+		       (emac_debug & EMAC_DEBUG_MII)
+	    );
+
+	/* set the PHY to a given mode - as per config parameters and
+	 * update DDA layer */
+	emac_set_phy_mode(_dev);
+
+	emac_control_cb(dev,
+			EMAC_IOCTL_STATUS_UPDATE, (void *)&dev->status, NULL);
+
+	/* start the tick timer via DDA */
+	emac_control_cb(dev,
+			EMAC_IOCTL_TIMER_START,
+			(void *)init_cfg->mdio_tick_msec, NULL);
+
+	/* enable opened TX channels */
+	for (channel = 0; channel < EMAC_MAX_TX_CHANNELS; channel++) {
+		if (dev->tx_cppi[channel] != NULL) {
+			ret_val =
+			    emac_enable_channel(_dev, channel, NET_CH_DIR_TX);
+			if (ret_val != EMAC_SUCCESS) {
+				LOGERR("Error enabling TX channel %d", channel);
+
+				/* TODECIDE: should we return from
+				 * here or continue enabling other
+				 * channels */
+				return (ret_val);
+			}
+		}
+	}
+
+	/* set filter low threshold - not supported, hence set to 0 */
+	dev->regs->rx_filter_low_thresh = 0;
+
+	/* disable unicast on all channels first - enabled if channel
+	 * is configured & enabled below */
+	dev->regs->rx_unicast_clear = EMAC_RX_UNICAST_CLEAR_ALL;
+
+	/* set MAC hash register */
+	dev->regs->mac_hash1 = dev->mac_hash1;
+	dev->regs->mac_hash2 = dev->mac_hash2;
+
+	/* RX MBP, RX pkt length and RX buffer offset registers taken
+	 * care by this function */
+	emac_set_rx_hw_cfg(_dev);
+
+	/* read RX address matching/filtering type (0/1/2) */
+	dev->rx_addr_type = (dev->regs->mac_cfig >> 8) & 0xFF;
+
+	/* enable opened RX channels */
+	for (channel = 0; channel < EMAC_MAX_RX_CHANNELS; channel++) {
+		if (dev->rx_cppi[channel] != NULL) {
+			ret_val =
+			    emac_enable_channel(_dev, channel, NET_CH_DIR_RX);
+			if (ret_val != EMAC_SUCCESS) {
+				LOGERR("Error enabling RX channel %d", channel);
+
+				/* TODECIDE: should we return from
+				 * here or continue enabling other
+				 * channels */
+				return (ret_val);
+			}
+		}
+
+		/* since flow threshold and free buffer feature is not
+		 * supported, set it to 0 */
+		dev->regs->rx_flow_thresh[channel] = 0;
+		dev->regs->rx_free_buffer[channel] = 0;
+	}
+
+	/* finally set MAC control register, enable MII */
+	dev->mac_control |= (1 << EMAC_MACCONTROL_MIIEN_SHIFT);
+	dev->regs->mac_control = dev->mac_control;
+
+	/* start the MIB cnt tick timer via DDA */
+	emac_control_cb(dev,
+			EMAC_IOCTL_MIB64_CNT_TIMER_START,
+			(void *)init_cfg->mib64cnt_msec, NULL);
+
+	/* enable interrupts via module control (wrapper) */
+	((volatile ewrap_regs *)dev->e_wrap_regs)->EWCTL = 0x1;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT, "");
+
+	return (EMAC_SUCCESS);
+
+}
+
+/**
+ * EMAC DDC Close
+ *  - Disables poll timer via DDA
+ *  - Disable and Close all open TX/RX channels
+ *  - Closes CSL
+ *  - Puts module in reset
+ *
+ * "param" not used in this implementation
+ */
+static int emac_close(emac_dev_t * _dev, void *param)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	int ret_val;
+	int err_val = EMAC_SUCCESS;
+	u32 channel;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY, "");
+
+	if (dev->drv_state == DRV_CLOSED) {
+		LOGERR("Device already closed");
+		return (EMAC_ERR_DEV_ALREADY_CLOSED);
+	}
+
+	/* stop the tick timer via DDA */
+	emac_control_cb(dev, EMAC_IOCTL_TIMER_STOP, NULL, NULL);
+
+	/* stop the mib timer via DDA */
+	emac_control_cb(dev, EMAC_IOCTL_MIB64_CNT_TIMER_STOP, NULL, NULL);
+	/* close TX channels */
+	for (channel = 0; channel < EMAC_MAX_TX_CHANNELS; channel++) {
+		if (dev->tx_cppi[channel] != NULL) {
+			ret_val =
+			    emac_ch_close(_dev, channel, NET_CH_DIR_TX, NULL);
+			if (ret_val != EMAC_SUCCESS) {
+				LOGERR("Error closing TX channel %d", channel);
+
+				/* instead of returning immediatley on
+				 * error, we close all possible
+				 * channels */
+				err_val = ret_val;
+			}
+		}
+	}
+
+	/* close RX channels */
+	for (channel = 0; channel < EMAC_MAX_RX_CHANNELS; channel++) {
+		if (dev->rx_cppi[channel] != NULL) {
+			ret_val =
+			    emac_ch_close(_dev, channel, NET_CH_DIR_RX, NULL);
+
+			if (ret_val != EMAC_SUCCESS) {
+				LOGERR("Error closing RX channel %d", channel);
+
+				/* instead of returning immediatley on
+				 * error, we close all possible
+				 * channels */
+				err_val = ret_val;	/* return (ret_val); */
+			}
+		}
+	}
+
+	/* disable interrupts via module control (wrapper) */
+	((volatile ewrap_regs *)dev->e_wrap_regs)->EWCTL = 0x0;
+
+	/* put EMAC in reset */
+	dev->regs->soft_reset = 1;
+
+	/* put MDIO in reset - not required for davinci */
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT, "");
+
+	if (err_val == EMAC_SUCCESS) {	/* closed all channels successfully. mark the DDC as closed */
+		dev->drv_state = DRV_CLOSED;
+	}
+
+	return (err_val);
+}
+
+/**
+ * EMAC DDC Ioctl
+ *  - Get Software (DDC) and Hardware Versions
+ *  - Set/Modify RX and MAC configuration
+ *  - Get DDC/module status
+ *  - Read/Write MII registers (via PHY)
+ *  - Get/Clr Statistics (hardware counters)
+ *  - Add/Del/ Multicast operations AllMulti Set/Clear operations
+ *  - Type2/3 Filtering operation
+ *
+ * "param" not used in this implementation
+ */
+static int emac_control(emac_dev_t * _dev, int cmd, void *cmd_arg, void *param)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	/* sanity check */
+	if (dev->drv_state != DRV_OPENED) {
+		LOGERR("ioctl called when device is NOT open");
+		return (EMAC_ERR_DEV_NOT_OPEN);
+	}
+
+	switch (cmd) {
+	case EMAC_IOCTL_GET_HWVER:
+		/* read hardware versions only if device is in open
+		 * state */
+		/* cmd is a ptr to an integer that will contain Tx Id
+		   ver and param is a pointer to an integer that will
+		   contain rx id ver after this call */
+		if (dev->drv_state == DRV_OPENED) {
+			*((u32 *) cmd_arg) = dev->regs->tx_id_ver;
+			*((u32 *) param) = dev->regs->rx_id_ver;
+		} else {
+			return (EMAC_ERR_DEV_NOT_OPEN);
+		}
+		break;
+
+	case EMAC_IOCTL_SET_RXCFG:
+		/* rx configuration structure passed in structure
+		 * pointed by cmd_arg, params not used */
+		if (cmd_arg != NULL) {
+			dev->init_cfg.rx_cfg = *((emac_rx_config *) cmd_arg);
+			emac_set_rx_hw_cfg(_dev);
+		} else {
+			return (EMAC_INVALID_PARAM);
+		}
+		break;
+
+	case EMAC_IOCTL_SET_MACCFG:
+		/* mac configuration structure passed in a structure
+		 * pointed by cmd_arg, params not used */
+		if (cmd_arg != NULL) {
+			dev->init_cfg.mac_cfg = *((emac_mac_config *) cmd_arg);
+			emac_set_mac_hw_cfg(_dev);
+		} else {
+			return (EMAC_INVALID_PARAM);
+		}
+		break;
+
+	case EMAC_IOCTL_GET_STATUS:
+		/* returns emac_status structure back in cmd_arg
+		 * pointer pointed structure */
+		{
+			emac_status *status = (emac_status *) cmd_arg;
+			*status = dev->status;	/* structure copy */
+		}
+		break;
+
+	case EMAC_IOCTL_READ_PHY_REG:
+		/* cmd = pointer to CpmacPhyParams struct. data read
+		 * back into "data" parameter in the structure */
+		{
+			/* \warning: Read to the phy registers - Note
+			   that this code loops on a completion bit in
+			   the phy so there are chances of hanging" */
+			emac_phy_params *phy_params =
+			    (emac_phy_params *) cmd_arg;
+
+			phy_params->data = emac_mdio_read(phy_params->phy_num,
+							  phy_params->reg_addr);
+		}
+		break;
+
+	case EMAC_IOCTL_WRITE_PHY_REG:
+		/* cmd = pointer to CpmacPhyParams struct. data to be
+		 * written is in "data" parameter in the structure */
+		{
+			emac_phy_params *phy_params =
+			    (emac_phy_params *) cmd_arg;
+
+			/* \warning: Write to the phy registers - Note
+			   that this code loops on a completion bit in
+			   the phy so there are chances of hanging" */
+			emac_mdio_write(phy_params->reg_addr,
+					phy_params->phy_num, phy_params->data);
+		}
+		break;
+
+	case EMAC_IOCTL_GET_STATISTICS:
+		/* cmd_arg points to the user provided structure for
+		 * statistics which match with hardware 36 regs, param
+		 * is not used */
+		{
+			u32 cnt;
+			u32 *user_stats = (u32 *) cmd_arg;
+			volatile u32 *addr =
+			    (u32 *) & dev->regs->rx_good_frames;
+
+			for (cnt = 0; cnt < EMAC_NUM_STAT_REGS;
+			     cnt++, user_stats++, addr++) {
+				*user_stats = *addr;
+			}
+		}
+
+		break;
+
+	case EMAC_IOCTL_CLR_STATISTICS:
+		/* cmd_arg or param is not used */
+		{
+			u32 cnt;
+			volatile u32 *addr =
+			    (u32 *) & dev->regs->rx_good_frames;
+
+			for (cnt = 0; cnt < EMAC_NUM_STAT_REGS; cnt++, addr++) {
+				*addr = EMAC_STAT_CLEAR;	/* 0xFFFFFFFF value */
+			}
+			emac_ddcifcnt_clear(_dev);
+		}
+		break;
+
+	case EMAC_IOCTL_MULTICAST_ADDR:
+		/* cmd_arg= emac_multicast_oper enum, param = pointer
+		 * to multicast address - u8 */
+		{
+			u8 *addr = (u8 *) param;
+			emac_single_multi(_dev,
+					  (emac_single_multi_oper) cmd_arg,
+					  addr);
+		}
+		break;
+
+	case EMAC_IOCTL_ALL_MULTI:
+		/* cmd_arg= emac_all_multi_oper enum, param=not used */
+		emac_all_multi(_dev, (emac_all_multi_oper) cmd_arg);
+		break;
+
+	case EMAC_IOCTL_TYPE2_3_FILTERING:
+		{
+			/* cmd_arg = pointer to
+			 * emac_type2_3_addr_filter_params structure,
+			 * param=not used */
+			emac_type2_3_addr_filter_params *addr_params;
+
+			addr_params =
+			    (emac_type2_3_addr_filter_params *) cmd_arg;
+			emac_add_type2addr(_dev, addr_params->channel,
+					   addr_params->mac_address,
+					   addr_params->index,
+					   addr_params->valid,
+					   addr_params->match);
+		}
+		break;
+
+	case EMAC_IOCTL_SET_MAC_ADDRESS:
+		{
+			/* cmd_arg = pointer to
+			 * emac_type2_3_addr_filter_params structure,
+			 * param=not used */
+			emac_address_params *addr_params;
+			emac_rx_cppi_ch *rx_cppi;
+			int cnt;
+
+			if (dev->drv_state != DRV_OPENED) {
+				LOGERR
+				    ("EMAC_IOCTL_TYPE2_3_FILTERING Ioctl called when device is NOT in open state");
+				return (EMAC_ERR_DEV_NOT_OPEN);
+			}
+
+			addr_params = (emac_address_params *) cmd_arg;
+			rx_cppi = dev->rx_cppi[addr_params->channel];
+			if (rx_cppi == NULL) {
+				LOGERR
+				    ("Invalid Channel %d. RX CPPI structure NULL",
+				     addr_params->channel);
+				return (EMAC_ERR_RX_CH_INVALID);
+			}
+
+			for (cnt = 0; cnt < 6; cnt++)
+				rx_cppi->mac_addr[cnt] =
+				    addr_params->mac_address[cnt];
+
+			/* set interface MAC address */
+			emac_set_mac_address(_dev, addr_params->channel,
+					     addr_params->mac_address);
+		}
+		break;
+
+	case EMAC_IOCTL_IF_COUNTERS:
+		emac_ddcifcnt_updt(_dev);
+
+		memcpy(cmd_arg, &dev->mib2if_hccounter.mib2if_counter,
+		       sizeof(struct mib2_if_counters));
+		break;
+
+	case EMAC_IOCTL_ETHER_COUNTERS:
+		emac_ddcphycnt(_dev, cmd_arg);
+		break;
+
+	case EMAC_IOCTL_IF_PARAMS_UPDT:
+		emac_ddcifcnt_updt(_dev);
+		break;
+
+	default:
+		LOGERR("Unhandled ioctl code %d", cmd);
+		break;
+	}
+
+	return (EMAC_SUCCESS);
+}
+
+/**
+ * EMAC DDC Channel Open
+ *  - Verify channel info (range checking etc)
+ *  - Allocate memory for the channel
+ *  - Book-keep operations for the channel - ready to be enabled in hardware
+ *
+ * 1. If DDC instance is in "Opened" state, the channel is enabled in hardware
+ *       2. "chOpenArgs" is used only for opening RX channel
+ */
+static int emac_ch_open(emac_dev_t * _dev, emac_ch_info * ch_info,
+			void *ch_open_args)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	int ret_val;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY,
+	       "ChannelNo=%d, Dir=%s",
+	       ch_info->ch_num,
+	       ((ch_info->ch_dir == NET_CH_DIR_TX) ? "TX" : "RX"));
+
+	/* if the channel state is not NET_CH_UNINITIALIZED, return error */
+	if (ch_info->ch_state != NET_CH_UNINITIALIZED) {
+		LOGERR
+		    ("%s channel %d  should be in NET_CH_UNINITIALIZED state",
+		     ((ch_info->ch_dir == NET_CH_DIR_TX) ? "TX" : "RX"),
+		     ch_info->ch_num);
+		return (EMAC_INVALID_PARAM);
+	}
+
+	/* init channel */
+	if (ch_info->ch_dir == NET_CH_DIR_TX) {
+		if (ch_info->ch_num >= dev->init_cfg.num_tx_channels) {
+			LOGERR
+			    ("Invalid TX Channel=%d specified",
+			     ch_info->ch_num);
+			return (EMAC_ERR_TX_CH_INVALID);
+		}
+
+		if (dev->tx_is_created[ch_info->ch_num] == TRUE) {
+			LOGERR("TX Channel %d already open", ch_info->ch_num);
+			return (EMAC_ERR_TX_CH_ALREADY_INIT);
+		}
+
+		/* allocate channel memory and perform other book-keep
+		 * functions for the channel */
+		ret_val = emac_init_tx_channel(_dev, ch_info, ch_open_args);
+		if (ret_val != EMAC_SUCCESS) {
+			LOGERR
+			    ("Error in initializing TX channel %d",
+			     ch_info->ch_num);
+			return (ret_val);
+		}
+	} else if (ch_info->ch_dir == NET_CH_DIR_RX) {
+		if (ch_info->ch_num >= dev->init_cfg.num_rx_channels) {
+			LOGERR
+			    ("Invalid RX Channel=%d specified",
+			     ch_info->ch_num);
+			return (EMAC_ERR_RX_CH_INVALID);
+		}
+
+		if (dev->rx_is_created[ch_info->ch_num] == TRUE) {
+			LOGERR("RX Channel %d already open", ch_info->ch_num);
+			return (EMAC_ERR_RX_CH_ALREADY_INIT);
+		}
+
+		/* allocate channel memory and perform other book-keep
+		 * functions for the channel */
+		ret_val = emac_init_rx_channel(_dev, ch_info, ch_open_args);
+
+		if (ret_val != EMAC_SUCCESS) {
+			LOGERR
+			    ("Error in initializing RX channel %d",
+			     ch_info->ch_num);
+			return (ret_val);
+		}
+	}
+
+	/* if device is opened already, enable this channel for use */
+	if (dev->drv_state == DRV_OPENED) {
+		ret_val =
+		    emac_enable_channel(_dev, ch_info->ch_num, ch_info->ch_dir);
+		if (ret_val != EMAC_SUCCESS) {
+			LOGERR
+			    ("Error enabling channel %d in %d direction",
+			     ch_info->ch_num, ch_info->ch_dir);
+			return (ret_val);
+		}
+	}
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT,
+	       "ChannelNo=%d, Dir=%s",
+	       ch_info->ch_num,
+	       ((ch_info->ch_dir == NET_CH_DIR_TX) ? "TX" : "RX"));
+
+	return (EMAC_SUCCESS);
+}
+
+/**
+ * EMAC DDC Channel Close
+ *  - If DDC instance is in "Opened" state, disable the channel in hardware
+ *  - Un-initialize the channel (free memory previously allocated)
+ */
+static int emac_ch_close(emac_dev_t * _dev, int channel,
+			 int direction, void *ch_close_args)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	int ret_val;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY,
+	       "ChannelNo=%d, Dir=%s",
+	       channel, ((direction == NET_CH_DIR_TX) ? "TX" : "RX"));
+
+	/* disable this channel */
+	if (dev->drv_state == DRV_OPENED) {
+		ret_val = emac_disable_channel(_dev, channel, direction);
+		if (ret_val != EMAC_SUCCESS) {
+			LOGERR
+			    ("Error disabling channel %d in %s direction",
+			     channel,
+			     ((direction == NET_CH_DIR_TX) ? "TX" : "RX"));
+			return (ret_val);
+		}
+	}
+
+	/* un_init channel */
+	if (direction == NET_CH_DIR_TX) {
+		ret_val = emac_un_init_tx_channel(_dev, channel, ch_close_args);
+		if (ret_val != EMAC_SUCCESS) {
+			LOGERR("Error in UnInit of TX channel %d", channel);
+			return (ret_val);
+		}
+	}
+
+	else if (direction == NET_CH_DIR_RX) {
+		ret_val = emac_un_init_rx_channel(_dev, channel, ch_close_args);
+		if (ret_val != EMAC_SUCCESS) {
+			LOGERR("Error in UnInit of TX channel %d", channel);
+			return (ret_val);
+		}
+	}
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT,
+	       "ChannelNo=%d, Dir=%s",
+	       channel, ((direction == NET_CH_DIR_TX) ? "TX" : "RX"));
+
+	return (EMAC_SUCCESS);
+}
+
+/**
+ * Init Tx Channel
+ *  - Allocates memory for TX Ch Control structure, Buffer descriptors
+ *  - Initialize the above data structures as per channel configuration
+ *  - Chain the TX BD list ready to be given to hardware
+ *
+ * 1. "chOpenArgs" not used in this implementation
+ *
+ * 2. This function assumes that the channel number passed is valid
+ * and the hDDC->txCppi[channel] pointer is NULL. This function will
+ * not do any error check on these parameters to avoid duplicate error
+ * checks (done in caller function).
+ */
+static int emac_init_tx_channel(emac_dev_t * _dev,
+				emac_ch_info * ch_info, void *ch_open_args)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	u32 cnt, bd_size;
+	char *alloc_mem;
+	emac_tx_bd *curr_bd;
+	emac_tx_cppi_ch *tx_cppi = NULL;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY, "ChannelNo=%d", ch_info->ch_num);
+
+	/* allocate memory for TX CPPI channel and set to 0 */
+	emac_malloc(sizeof(emac_tx_cppi_ch), (void **)&tx_cppi);
+
+	/* update the channel control structure in DDC */
+	dev->tx_cppi[ch_info->ch_num] = tx_cppi;
+
+	/* populate channel info */
+	tx_cppi->ch_info = *ch_info;	/* structure copy */
+	tx_cppi->ch_info.ch_state = NET_CH_INITIALIZED;
+	tx_cppi->active_queue_head = 0;
+	tx_cppi->active_queue_tail = 0;
+	tx_cppi->queue_active = FALSE;
+	dev->tx_teardown_pending[ch_info->ch_num] = FALSE;
+
+#ifdef EMAC_MULTIPACKET_TX_COMPLETE_NOTIFY
+	/* allocate memory for TX CPPI channel on a 4 byte boundry */
+	emac_malloc((ch_info->service_max * sizeof(u32)),
+		    (void **)&tx_cppi->tx_complete);
+#endif
+
+	/* allocate buffer descriptor pool align every BD on four word
+	 * boundry for future requirements */
+	bd_size = (sizeof(emac_tx_bd) + 0xF) & ~0xF;
+	tx_cppi->alloc_size = (((bd_size * ch_info->num_bd) + 0xF) & ~0xF);
+
+	/* alloc TX BD memory */
+	tx_cppi->bd_mem = (char *)EMAC_TX_BD_MEM;
+	memzero(tx_cppi->bd_mem, tx_cppi->alloc_size);
+
+	/* initialize the BD linked list */
+	alloc_mem = (char *)(((u32) tx_cppi->bd_mem + 0xF) & ~0xF);
+
+	tx_cppi->bd_pool_head = 0;
+	for (cnt = 0; cnt < ch_info->num_bd; cnt++) {
+		curr_bd = (emac_tx_bd *) (alloc_mem + (cnt * bd_size));
+		curr_bd->next = tx_cppi->bd_pool_head;
+		tx_cppi->bd_pool_head = curr_bd;
+	}
+
+	/* reset statistics counters */
+	tx_cppi->out_of_tx_bd = 0;
+	tx_cppi->no_active_pkts = 0;
+	tx_cppi->active_queue_count = 0;
+	dev->tx_is_created[ch_info->ch_num] = TRUE;
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT, "ChannelNo=%d", ch_info->ch_num);
+
+	return (EMAC_SUCCESS);
+}
+
+/**
+ * Un-Init Tx Channel
+ *
+ * - Frees memory previously allocated for Ch Control structure,
+ *     Buffer descriptors
+ *
+ * 1. "chCloseArgs" not used in this implementation
+ * 2. This function assumes that the channel number passed is valid
+ * and this function will not do any error check to avoid duplicate
+ * error checks (done in caller function).
+ */
+static int emac_un_init_tx_channel(emac_dev_t * _dev, u32 channel,
+				   void *ch_close_args)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	emac_tx_cppi_ch *tx_cppi;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY, "ChannelNo=%d", channel);
+
+	/* check if channel structure is already de-allocated */
+	if (dev->tx_is_created[channel] == FALSE) {
+		LOGERR("TX CPPI Channel %d structure already freed", channel);
+		return (EMAC_ERR_TX_CH_ALREADY_CLOSED);
+	}
+
+	tx_cppi = dev->tx_cppi[channel];
+
+	/* free the buffer descriptors memory */
+	if (tx_cppi->bd_mem != NULL) {
+		tx_cppi->bd_mem = NULL;
+	}
+#ifdef EMAC_MULTIPACKET_TX_COMPLETE_NOTIFY
+	/* free the TX complete queue */
+	emac_free(tx_cppi->tx_complete);
+#endif
+
+	/* free the TX channel structure */
+	emac_free(tx_cppi);
+	dev->tx_cppi[channel] = NULL;
+	dev->tx_is_created[channel] = FALSE;
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT, "ChannelNo=%d", channel);
+
+	return (EMAC_SUCCESS);
+}
+
+/**
+ * Init Rx Channel
+ *  - Allocates memory for RX Ch Control structure, Buffer descriptors
+ *  - Initialize the above data structures as per channel configuration
+ * - Allocate receive buffers from DDA and chain the RX BD list ready
+ *     to be given to hardware
+ *
+ * 1. "chOpenArgs" Points to MAC address for this channel
+ * 2. This function assumes that the channel number passed is valid
+ * and the hDDC->rxCppi[channel] pointer is NULL. This function will
+ * not do any error check on these parameters to avoid duplicate error
+ * checks (done in caller function).
+ */
+static int emac_init_rx_channel(emac_dev_t * _dev,
+				emac_ch_info * ch_info, void *ch_open_args)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	u32 cnt, bd_size;
+	char *alloc_mem;
+	emac_rx_bd *curr_bd;
+	emac_rx_cppi_ch *rx_cppi = NULL;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY, "ChannelNo=%d", ch_info->ch_num);
+
+	/* allocate memory for RX CPPI channel */
+	emac_malloc(sizeof(emac_rx_cppi_ch), (void **)&rx_cppi);
+	/* update the channel control structure in DDC */
+	dev->rx_cppi[ch_info->ch_num] = rx_cppi;
+
+	rx_cppi->ch_info = *ch_info;	/* structure copy */
+	rx_cppi->ch_info.ch_state = NET_CH_INITIALIZED;
+	dev->rx_teardown_pending[ch_info->ch_num] = FALSE;
+
+	/* save mac address */
+	alloc_mem = (char *)ch_open_args;
+	for (cnt = 0; cnt < 6; cnt++)
+		rx_cppi->mac_addr[cnt] = alloc_mem[cnt];
+
+	/* allocate buffer descriptor pool align every BD on four word
+	 * boundry for future requirements */
+	bd_size = (sizeof(emac_rx_bd) + 0xF) & ~0xF;
+	rx_cppi->alloc_size = (((bd_size * ch_info->num_bd) + 0xF) & ~0xF);
+
+	/* alloc RX BD memory */
+	rx_cppi->bd_mem = (char *)EMAC_RX_BD_MEM;
+	memzero(rx_cppi->bd_mem, rx_cppi->alloc_size);
+
+	rx_cppi->pkt_queue.buf_list = &rx_cppi->buf_queue[0];
+
+	/* allocate RX buffer and initialize the BD linked list */
+	alloc_mem = (char *)(((u32) rx_cppi->bd_mem + 0xF) & ~0xF);
+	rx_cppi->active_queue_head = 0;
+	rx_cppi->active_queue_tail = (emac_rx_bd *) alloc_mem;
+	for (cnt = 0; cnt < ch_info->num_bd; cnt++) {
+		curr_bd = (emac_rx_bd *) (alloc_mem + (cnt * bd_size));
+
+		/* for potential future use the last parameter
+		 * contains the BD ptr */
+		curr_bd->data_ptr =
+		    (void *)(emac_net_alloc_rx_buf(dev,
+						   ch_info->buf_size,
+						   (emac_net_data_token *) &
+						   curr_bd->buf_token, 0,
+						   (void *)curr_bd));
+		if (curr_bd->data_ptr == NULL) {
+			LOGERR
+			    ("Error in RX Buffer allocation for channel %d",
+			     ch_info->ch_num);
+			return (EMAC_ERR_RX_BUFFER_ALLOC_FAIL);
+		}
+
+		/* populate the hardware descriptor */
+		curr_bd->h_next = EMAC_VIRT_TO_PHYS(rx_cppi->active_queue_head);
+		curr_bd->buff_ptr = EMAC_VIRT_TO_PHYS(curr_bd->data_ptr);
+		curr_bd->off_b_len = ch_info->buf_size;
+		curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
+
+		/* write back to hardware memory */
+		BD_CACHE_WRITEBACK_INVALIDATE((u32) curr_bd,
+					      EMAC_BD_LENGTH_FOR_CACHE);
+		curr_bd->next = (void *)rx_cppi->active_queue_head;
+		rx_cppi->active_queue_head = curr_bd;
+	}
+
+	/* At this point rxCppi->activeQueueHead points to the first
+	   RX BD ready to be given to RX HDP and
+	   rx_cppi->active_queue_tail points to the last RX BD */
+	dev->rx_is_created[ch_info->ch_num] = TRUE;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT, "ChannelNo=%d", ch_info->ch_num);
+
+	return (EMAC_SUCCESS);
+}
+
+/**
+ * Un-Init Rx Channel
+ * - Frees memory previously allocated for Ch Control structure,
+ *     Buffer descriptors
+ * - Returns (Frees) back receive buffers to DDA layer
+ *
+ * 1. "chCloseArgs" not used in this implementation
+ * 2. This function assumes that the channel number passed is valid
+ * and this function will not do any error check to avoid duplicate
+ * error checks (done in caller function).
+ */
+static int emac_un_init_rx_channel(emac_dev_t * _dev, u32 channel,
+				   void *ch_close_args)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	emac_rx_cppi_ch *rx_cppi;
+	emac_rx_bd *curr_bd;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY, "ChannelNo=%d", channel);
+
+	/* check if channel structure is already de-allocated */
+	if (dev->rx_is_created[channel] == FALSE) {
+		LOGERR("RX CPPI Channel %d structure already freed", channel);
+		return (EMAC_ERR_RX_CH_ALREADY_CLOSED);
+	}
+
+	rx_cppi = dev->rx_cppi[channel];
+
+	/* free the receive buffers previously allocated */
+	curr_bd = rx_cppi->active_queue_head;
+	while (curr_bd) {
+		if (emac_net_free_rx_buf(dev,
+					 curr_bd->data_ptr,
+					 (emac_net_data_token) curr_bd->
+					 buf_token, 0, NULL) != EMAC_SUCCESS) {
+			LOGERR("Failed to free RX buffer Ch %d", channel);
+		}
+		curr_bd = curr_bd->next;
+	}
+
+	/* free the buffer descriptors memory */
+	if (rx_cppi->bd_mem != NULL) {
+		rx_cppi->bd_mem = NULL;
+	}
+
+	/* free the RX channel structure */
+	emac_free(rx_cppi);
+	dev->rx_cppi[channel] = NULL;
+	dev->rx_is_created[channel] = FALSE;
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT, "ChannelNo=%d", channel);
+
+	return (EMAC_SUCCESS);
+}
+
+/**
+ * Set EMAC Mac address
+ * Functionality provided:
+ *  - EMAC address is set in the hardware based on the address type
+ *
+ * 1. It is assumed that the channel is already "initialized"
+ */
+static void emac_set_mac_address(emac_dev_t * _dev, u32 channel, char *mac_addr)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	/* enable unicast on this channel */
+	dev->regs->rx_unicast_set = (1 << channel);
+
+	/* program MAC address for the channel depending upon emac/cpgmac */
+	if (dev->rx_addr_type == RX_ADDR_TYPE0)
+		emac_add_type0addr(_dev, channel, mac_addr);
+	else if (dev->rx_addr_type == RX_ADDR_TYPE1)
+		emac_add_type1addr(_dev, channel, mac_addr);
+	else if (dev->rx_addr_type == RX_ADDR_TYPE2)
+		emac_add_type2addr(_dev, channel, mac_addr, 0, 1, 1);
+	else
+		LOGERR
+		    ("Wrong Rx Addressing Type - (Type2) detected in hardware");
+}
+
+/**
+ * Enable TX/RX Channel
+ * Functionality provided:
+ * - Channel is enabled in hardware. Data transfer can occur on this
+ *     channel after this.
+ *
+ * 1. It is assumed that the channel is already "initialized"
+ * 2. To enable a channel after its disabled, it needs to be initialized again
+ */
+static int emac_enable_channel(emac_dev_t * _dev, u32 channel, u32 direction)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY,
+	       "ChannelNo=%d, Direction=%s",
+	       channel, ((direction == NET_CH_DIR_TX) ? "TX" : "RX"));
+
+	if (direction == NET_CH_DIR_TX) {
+		emac_tx_cppi_ch *tx_cppi;
+
+		tx_cppi = dev->tx_cppi[channel];
+		if (tx_cppi == NULL) {
+			LOGERR
+			    ("Invalid Channel %d. TX CPPI structure NULL",
+			     channel);
+
+			return (EMAC_ERR_TX_CH_INVALID);
+		}
+
+		/* init head descriptor pointer */
+		dev->regs->tx_HDP[channel] = 0;
+		{
+			emac_mac_config *mac_cfg;
+
+			mac_cfg = &dev->init_cfg.mac_cfg;
+			if (mac_cfg->tx_interrupt_disable == TRUE) {
+				/* disable channel interrupt */
+				dev->regs->tx_int_mask_clear = (1 << channel);
+				dev->tx_interrupt_disable = TRUE;
+				dev->tx_int_threshold[channel] =
+				    dev->tx_cppi[channel]->ch_info.service_max;
+			} else {
+				/* enable channel interrupt */
+				dev->regs->tx_int_mask_set = (1 << channel);
+				dev->tx_interrupt_disable = FALSE;
+			}
+		}
+
+		/* mark channel open */
+		dev->tx_is_open[channel] = TRUE;
+		tx_cppi->ch_info.ch_state = NET_CH_OPENED;
+	}
+
+	else if (direction == NET_CH_DIR_RX) {
+		emac_rx_cppi_ch *rx_cppi;
+
+		rx_cppi = dev->rx_cppi[channel];
+		if (rx_cppi == NULL) {
+			LOGERR
+			    ("Invalid Channel %d. RX CPPI structure NULL",
+			     channel);
+
+			return (EMAC_ERR_RX_CH_INVALID);
+		}
+
+		/* set interface MAC address */
+		emac_set_mac_address(_dev, channel, rx_cppi->mac_addr);
+
+		/* enable channel interrupt */
+		dev->regs->rx_int_mask_set = (1 << channel);
+
+		/* mark queue active */
+		rx_cppi->queue_active = TRUE;
+
+		/* enable DMA */
+		dev->regs->rx_HDP[channel] =
+		    EMAC_VIRT_TO_PHYS(rx_cppi->active_queue_head);
+
+		/* mark channel open */
+		dev->rx_is_open[channel] = TRUE;
+
+		rx_cppi->ch_info.ch_state = NET_CH_OPENED;
+
+	}
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT,
+	       "ChannelNo=%d, Direction=%s",
+	       channel, ((direction == NET_CH_DIR_TX) ? "TX" : "RX"));
+
+	return (EMAC_SUCCESS);
+
+}
+
+/**
+ * Disable TX/RX Channel
+ * Functionality provided:
+ * - Channel is disabled in hardware. No data transfer can occur on
+ *    this channel after this.
+ *
+ * 1. It is assumed that the channel number passed is valid
+ * 2. Resources for the channel will be released only when its closed
+ */
+static int emac_disable_channel(emac_dev_t * _dev, u32 channel,
+				net_ch_dir direction)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY,
+	       "ChannelNo=%d, Direction=%s",
+	       channel, ((direction == NET_CH_DIR_TX) ? "TX" : "RX"));
+
+	if (direction == NET_CH_DIR_TX) {
+
+		dev->tx_teardown_pending[channel] = TRUE;	/* set the TX teardown pending flag */
+
+		/* initiate teardown of TX channel */
+		dev->regs->tx_teardown = channel;
+
+		/* wait for teardown complete */
+		if (emac_wait_for_teardown_complete
+		    (_dev, channel, direction, TRUE) != EMAC_SUCCESS) {
+
+			LOGERR("Failed to teardown TX channel %d", channel);
+
+			/* instead of quitting on error immediately,
+			 * we continue so as to cleanup the channel */
+		}
+
+		dev->tx_teardown_pending[channel] = FALSE;
+
+		/* disable interrupt */
+		dev->regs->tx_int_mask_clear = (1 << channel);
+
+		/* disable DMA */
+
+		/* mark channel closed */
+		dev->tx_is_open[channel] = FALSE;
+	}
+
+	else if (direction == NET_CH_DIR_RX) {
+		dev->rx_teardown_pending[channel] = TRUE;
+
+		/* initiate teardown of TX channel */
+		dev->regs->rx_teardown = channel;
+
+		/* wait for teardown complete */
+		if (emac_wait_for_teardown_complete
+		    (_dev, channel, direction, TRUE) != EMAC_SUCCESS) {
+			LOGERR("Failed to teardown RX channel %d", channel);
+		}
+		dev->rx_teardown_pending[channel] = FALSE;
+
+		/* disable interrupt */
+		dev->regs->rx_int_mask_clear = (1 << channel);
+
+		/* mark channel closed */
+		dev->rx_is_open[channel] = FALSE;
+	}
+
+	LOGMSG(EMAC_DEBUG_FUNCTION_EXIT,
+	       "ChannelNo=%d, Direction=%s",
+	       channel, ((direction == NET_CH_DIR_TX) ? "TX" : "RX"));
+
+	return (EMAC_SUCCESS);
+}
+
+/**
+ * Wait for Teardown Complete
+ *  - This function waits (blocking mode) for teardown completion.
+ *  - blocking = TRUE ( waits on OS timer wait untill teardown complete),
+ *             = FALSE (returns immediately) - NOT SUPPORTED
+ * As of now this function supports blocking mode in polled mode only
+ */
+static int emac_wait_for_teardown_complete(emac_dev_t * _dev,
+					   u32 channel,
+					   net_ch_dir direction, bool blocking)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	volatile unsigned int teardown_cnt = 0xFFFFFFF0;
+
+	if (direction == NET_CH_DIR_TX) {
+		emac_tx_bd *curr_bd;
+		emac_tx_cppi_ch *tx_cppi;
+
+		LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY,
+		       "ChannelNo=%d, Direction=%s",
+		       channel, ((direction == NET_CH_DIR_TX) ? "TX" : "RX"));
+
+		while ((dev->regs->tx_CP[channel] & EMAC_TEARDOWN_VALUE) !=
+		       EMAC_TEARDOWN_VALUE) {
+			/* wait here for tx teardown completion
+			 * interrupt to occur */
+
+			/* A task delay can be called here to pend
+			 * rather than occupying CPU cycles - anyway
+			 * it has been found that the teardown takes
+			 * very few cpu cycles and does not affect
+			 * functionality
+			 */
+			--teardown_cnt;
+			if (teardown_cnt) {
+				printk("Tx teardown aborted\n");
+				break;
+			}
+		}
+
+		/* write to the completion pointer */
+		dev->regs->tx_CP[channel] = EMAC_TEARDOWN_VALUE;
+
+		/* TX teardown complete - process sent packets and
+		 * return sent packets to DDA */
+		tx_cppi = dev->tx_cppi[channel];
+		if (tx_cppi->queue_active == TRUE) {
+			curr_bd = tx_cppi->active_queue_head;
+			while (curr_bd != NULL) {
+				emac_net_tx_complete(dev,
+						     &(curr_bd->buf_token),
+						     1, channel);
+
+				if (curr_bd != tx_cppi->active_queue_tail) {
+					curr_bd = curr_bd->next;
+				} else {
+					break;
+				}
+			}
+			tx_cppi->bd_pool_head = tx_cppi->active_queue_head;
+			tx_cppi->active_queue_head =
+			    tx_cppi->active_queue_tail = 0;
+		}
+
+		/* At this stage all TX BD's are available linked with
+		 * "bdPoolHead" and can be freed */
+		LOGMSG(EMAC_DEBUG_FUNCTION_EXIT,
+		       "ChannelNo=%d, Direction=%s",
+		       channel, ((direction == NET_CH_DIR_TX) ? "TX" : "RX"));
+	} else if (direction == NET_CH_DIR_RX) {
+		LOGMSG(EMAC_DEBUG_FUNCTION_ENTRY,
+		       "ChannelNo=%d, Direction=%s",
+		       channel, ((direction == NET_CH_DIR_TX) ? "TX" : "RX"));
+
+		while ((dev->regs->rx_CP[channel] & EMAC_TEARDOWN_VALUE) !=
+		       EMAC_TEARDOWN_VALUE) {
+
+			/* wait here for rx teardown completion
+			 * interrupt to occur */
+
+			/* A task delay can be called here to pend
+			 * rather than occupying CPU cycles - anyway
+			 * it has been found that the teardown takes
+			 * very few cpu cycles and does not affect
+			 * functionality
+			 */
+			--teardown_cnt;
+			if (teardown_cnt) {
+				printk("Rx teardown aborted\n");
+				break;
+			}
+		}
+
+		/* write to the completion pointer */
+		dev->regs->rx_CP[channel] = EMAC_TEARDOWN_VALUE;
+
+		/* At this stage all TX BD's are available linked with
+		 * "activeQueueHead" and can be freed */
+		LOGMSG(EMAC_DEBUG_FUNCTION_EXIT,
+		       "ChannelNo=%d, Direction=%s",
+		       channel, ((direction == NET_CH_DIR_TX) ? "TX" : "RX"));
+
+	}
+
+	return (EMAC_SUCCESS);
+}
+
+static void emac_ddcphycnt(emac_dev_t * dev, u32 * cmd_arg)
+{
+	int result;
+	emac_hw_statistics stats;
+	struct mib2_phy_counters *mib2phy_counters =
+	    (struct mib2_phy_counters *)cmd_arg;
+
+	result =
+	    emac_control(dev, EMAC_IOCTL_GET_STATISTICS, (u32 *) & stats, NULL);
+
+	if (result != 0) {
+		LOGERR("Error from ioctl for EMAC_IOCTL_GET_STATISTICS \n");
+		return;
+	}
+
+	mib2phy_counters->eth_alignment_errors = stats.if_in_align_code_errors;
+	mib2phy_counters->eth_fcserrors = stats.if_in_crcerrors;
+	mib2phy_counters->eth_single_collisions =
+	    stats.if_single_collision_frames;
+	mib2phy_counters->eth_multiple_collisions =
+	    stats.if_multiple_collision_frames;
+	mib2phy_counters->eth_sqetest_errors = 0;
+	mib2phy_counters->eth_deferred_tx_frames =
+	    stats.if_deferred_transmissions;
+	mib2phy_counters->eth_late_collisions = stats.if_late_collisions;
+	mib2phy_counters->eth_excessive_collisions =
+	    stats.if_excessive_collision_frames;
+	mib2phy_counters->eth_internal_mac_tx_errors = 0;
+	mib2phy_counters->eth_carrier_sense_errors =
+	    stats.if_carrier_sense_errors;
+	mib2phy_counters->eth_too_long_rx_frames = stats.if_in_oversized_frames;
+	mib2phy_counters->eth_internal_mac_rx_errors = 0;
+	mib2phy_counters->eth_symbol_errors = 0;
+
+	return;
+}
+
+static void emac_ddcifcnt_clear(emac_dev_t * _dev)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	memzero((char *)&dev->mib2if_hccounter, sizeof(dev->mib2if_hccounter));
+}
+
+static void emac_ddcifcnt_updt(emac_dev_t * _dev)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	int result;
+	emac_hw_statistics stats;
+
+	result =
+	    emac_control(_dev, EMAC_IOCTL_GET_STATISTICS,
+			 (u32 *) & stats, NULL);
+
+	if (result != 0) {
+		LOGERR("Error from ioctl for DDC EMAC_IOCTL_GET_STATISTICS \n");
+		return;
+	}
+
+	if (stats.if_in_octets >= dev->mib2if_hccounter.in_bytes) {
+		dev->mib2if_hccounter.in_bytes_hc +=
+		    (stats.if_in_octets - dev->mib2if_hccounter.in_bytes);
+	} else {
+		dev->mib2if_hccounter.in_bytes_hc +=
+		    0xffffffff - (dev->mib2if_hccounter.in_bytes -
+				  stats.if_in_octets);
+	}
+
+	dev->mib2if_hccounter.in_bytes = stats.if_in_octets;
+	if (stats.if_in_good_frames >=
+	    dev->mib2if_hccounter.in_multicast_pkts +
+	    dev->mib2if_hccounter.in_broadcast_pkts +
+	    dev->mib2if_hccounter.in_unicast_pkts) {
+		dev->mib2if_hccounter.in_unicast_pkts_hc +=
+		    ((stats.if_in_good_frames -
+		      (stats.if_in_broadcasts + stats.if_in_multicasts))
+		     - dev->mib2if_hccounter.in_unicast_pkts);
+	} else {
+		dev->mib2if_hccounter.in_unicast_pkts_hc +=
+		    0xffffffff - (dev->mib2if_hccounter.in_unicast_pkts -
+				  (stats.if_in_good_frames -
+				   (stats.if_in_broadcasts +
+				    stats.if_in_multicasts)));
+	}
+	dev->mib2if_hccounter.in_unicast_pkts = (stats.if_in_good_frames -
+						 (stats.if_in_broadcasts +
+						  stats.if_in_multicasts));
+	if (stats.if_in_multicasts >= dev->mib2if_hccounter.in_multicast_pkts) {
+		dev->mib2if_hccounter.in_multicast_pkts_hc +=
+		    (stats.if_in_multicasts -
+		     dev->mib2if_hccounter.in_multicast_pkts);
+	} else {
+		dev->mib2if_hccounter.in_multicast_pkts_hc +=
+		    0xffffffff - (dev->mib2if_hccounter.in_multicast_pkts -
+				  stats.if_in_multicasts);
+	}
+
+	dev->mib2if_hccounter.in_multicast_pkts = stats.if_in_multicasts;
+	if (stats.if_in_broadcasts >= dev->mib2if_hccounter.in_broadcast_pkts) {
+		dev->mib2if_hccounter.in_broadcast_pkts_hc +=
+		    (stats.if_in_broadcasts -
+		     dev->mib2if_hccounter.in_broadcast_pkts);
+
+	} else {
+		dev->mib2if_hccounter.in_broadcast_pkts_hc +=
+		    0xffffffff - (dev->mib2if_hccounter.in_broadcast_pkts -
+				  stats.if_in_broadcasts);
+	}
+
+	dev->mib2if_hccounter.in_broadcast_pkts = stats.if_in_broadcasts;
+	if (stats.if_out_octets >= dev->mib2if_hccounter.out_bytes) {
+		dev->mib2if_hccounter.out_bytes_hc +=
+		    (stats.if_out_octets - dev->mib2if_hccounter.out_bytes);
+	} else {
+		dev->mib2if_hccounter.out_bytes_hc +=
+		    0xffffffff - (dev->mib2if_hccounter.out_bytes -
+				  stats.if_out_octets);
+	}
+
+	dev->mib2if_hccounter.out_bytes = stats.if_out_octets;
+	if (stats.if_out_good_frames >=
+	    dev->mib2if_hccounter.out_multicast_pkts +
+	    dev->mib2if_hccounter.out_broadcast_pkts +
+	    dev->mib2if_hccounter.out_unicast_pkts) {
+		dev->mib2if_hccounter.out_unicast_pkts_hc +=
+		    ((stats.if_out_good_frames -
+		      (stats.if_out_broadcasts + stats.if_out_multicasts))
+		     - dev->mib2if_hccounter.out_unicast_pkts);
+	}
+
+	else {
+		dev->mib2if_hccounter.out_unicast_pkts_hc +=
+		    0xffffffff - (dev->mib2if_hccounter.out_unicast_pkts -
+				  (stats.if_out_good_frames -
+				   (stats.if_out_broadcasts +
+				    stats.if_out_multicasts)));
+	}
+
+	dev->mib2if_hccounter.out_unicast_pkts = (stats.if_out_good_frames -
+						  (stats.if_out_broadcasts +
+						   stats.if_out_multicasts));
+
+	if (stats.if_out_multicasts >= dev->mib2if_hccounter.out_multicast_pkts) {
+		dev->mib2if_hccounter.out_multicast_pkts_hc +=
+		    (stats.if_out_multicasts -
+		     dev->mib2if_hccounter.out_multicast_pkts);
+	} else {
+		dev->mib2if_hccounter.out_multicast_pkts_hc +=
+		    0xffffffff - (dev->mib2if_hccounter.out_multicast_pkts -
+				  stats.if_out_multicasts);
+	}
+
+	dev->mib2if_hccounter.out_multicast_pkts = stats.if_out_multicasts;
+	if (stats.if_out_broadcasts >= dev->mib2if_hccounter.out_broadcast_pkts) {
+		dev->mib2if_hccounter.out_broadcast_pkts_hc +=
+		    (stats.if_out_broadcasts -
+		     dev->mib2if_hccounter.out_broadcast_pkts);
+	} else {
+		dev->mib2if_hccounter.out_broadcast_pkts_hc +=
+		    0xffffffff - (dev->mib2if_hccounter.out_broadcast_pkts -
+				  stats.if_out_broadcasts);
+	}
+	dev->mib2if_hccounter.out_broadcast_pkts = stats.if_out_broadcasts;
+
+	/* low 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.in_bytes_low =
+	    (unsigned long)dev->mib2if_hccounter.in_bytes_hc;
+
+	/* high 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.in_bytes_high =
+	    (dev->mib2if_hccounter.in_bytes_hc >> 32);
+
+	/* low 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.in_unicast_pkts_low =
+	    (unsigned long)dev->mib2if_hccounter.in_unicast_pkts_hc;
+
+	/* high 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.in_unicast_pkts_high =
+	    (dev->mib2if_hccounter.in_unicast_pkts_hc >> 32);
+
+	/* low 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.in_multicast_pkts_low =
+	    (unsigned long)dev->mib2if_hccounter.in_multicast_pkts_hc;
+
+	/* high 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.in_multicast_pkts_high =
+	    dev->mib2if_hccounter.in_multicast_pkts_hc >> 32;
+
+	/* low 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.in_broadcast_pkts_low =
+	    (unsigned long)dev->mib2if_hccounter.in_broadcast_pkts_hc;
+
+	/* high 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.in_broadcast_pkts_high =
+	    dev->mib2if_hccounter.in_broadcast_pkts_hc >> 32;
+
+	/* packets discarded due to resource limit */
+	dev->mib2if_hccounter.mib2if_counter.in_discard_pkts =
+	    stats.if_rx_dmaoverruns
+	    + stats.if_rx_mof_overruns
+	    + stats.
+	    if_rx_sof_overruns
+	    + stats.if_in_crcerrors
+	    + stats.
+	    if_in_align_code_errors
+	    + stats.if_in_jabber_frames
+	    + stats.
+	    if_in_fragments
+	    + stats.if_in_oversized_frames
+	    + stats.
+	    if_in_undersized_frames
+	    + stats.if_in_filtered_frames + stats.if_in_qos_filtered_frames;
+
+	/* packets discarded due to format errors */
+	dev->mib2if_hccounter.mib2if_counter.in_error_pkts =
+	    stats.if_in_crcerrors
+	    + stats.if_in_align_code_errors
+	    + stats.if_in_jabber_frames + stats.if_in_fragments;
+
+	dev->mib2if_hccounter.mib2if_counter.in_unknown_prot_pkts = 0;
+
+	/* low 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.out_bytes_low =
+	    (unsigned long)dev->mib2if_hccounter.out_bytes_hc;
+
+	/* high 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.out_bytes_high =
+	    dev->mib2if_hccounter.out_bytes_hc >> 32;
+
+	/* low 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.out_unicast_pkts_low =
+	    (unsigned long)dev->mib2if_hccounter.out_unicast_pkts_hc;
+
+	/* high 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.out_unicast_pkts_high =
+	    dev->mib2if_hccounter.out_unicast_pkts_hc >> 32;
+
+	/* low 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.out_multicast_pkts_low =
+	    (unsigned long)dev->mib2if_hccounter.out_multicast_pkts_hc;
+
+	/* high 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.out_multicast_pkts_high =
+	    dev->mib2if_hccounter.out_multicast_pkts_hc >> 32;
+
+	/* low 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.out_broadcast_pkts_low =
+	    (unsigned long)dev->mib2if_hccounter.out_broadcast_pkts_hc;
+
+	/* high 32-bit of total octets received from media */
+	dev->mib2if_hccounter.mib2if_counter.out_broadcast_pkts_high =
+	    dev->mib2if_hccounter.out_broadcast_pkts_hc >> 32;
+
+	/* packets discarded due to format errors */
+	dev->mib2if_hccounter.mib2if_counter.out_error_pkts =
+	    (stats.if_excessive_collision_frames
+	     + stats.if_late_collisions + stats.if_carrier_sense_errors);
+
+	/* packets discarded due to resource limit */
+	dev->mib2if_hccounter.mib2if_counter.out_discard_pkts =
+	    stats.if_out_underrun +
+	    dev->mib2if_hccounter.mib2if_counter.out_error_pkts;
+
+	return;
+}
+
+#define emac_min_val(a,b) ((a > b) ? b : a)
+
+#ifdef EMAC_DEBUG		/*  used only for debug printing  */
+/* static global strings */
+static char *emac_tx_host_error_codes[16] = {
+	/* 0000 */ "No error",
+	/* 0001 */ "SOP error",
+	/* 0010 */ "Ownership bit not set in SOP buffer",
+	/* 0011 */ "Zero Next Buffer Descriptor Pointer Without EOP",
+	/* 0100 */ "Zero Buffer Pointer",
+	/* 0101 */ "Zero Buffer Length",
+	/* 0110 */ "Packet Length Error",
+	/* 0111 */ "Reserved",
+	/* 1000 */ "Reserved",
+	/* 1001 */ "Reserved",
+	/* 1010 */ "Reserved",
+	/* 1011 */ "Reserved",
+	/* 1100 */ "Reserved",
+	/* 1101 */ "Reserved",
+	/* 1110 */ "Reserved",
+	/* 1111 */ "Reserved"
+};
+
+static char *emac_rx_host_error_codes[16] = {
+	/* 0000 */ "No error",
+	/* 0001 */ "Reserved",
+	/* 0010 */ "Ownership bit not set in input buffer",
+	/* 0011 */ "Reserved",
+	/* 0100 */ "Zero Buffer Pointer",
+	/* 0101 */ "Reserved",
+	/* 0110 */ "Reserved",
+	/* 0111 */ "Reserved",
+	/* 1000 */ "Reserved",
+	/* 1001 */ "Reserved",
+	/* 1010 */ "Reserved",
+	/* 1011 */ "Reserved",
+	/* 1100 */ "Reserved",
+	/* 1101 */ "Reserved",
+	/* 1110 */ "Reserved",
+	/* 1111 */ "Reserved"
+};
+
+#endif				/* EMAC_DEBUG */
+
+/**
+ * EMAC DDC Periodic Timer (Tick) Function
+ *  - calls PHY polling function
+ *  - If status changed, invokes DDA callback to propogate PHY / Devicestatus
+ *
+ * "tickArgs" is not used in this implementation
+ */
+static int emac_tick(emac_dev_t * _dev, void *tick_args)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	/* verify proper device state */
+	if (dev->drv_state != DRV_OPENED) {
+		return (EMAC_ERR_DEV_NOT_OPEN);
+	}
+
+	if (!(dev->init_cfg.phy_mode & SNWAY_NOPHY)) {
+		/* opened and phy available */
+		int tick_change;
+
+		tick_change = emac_mdio_tick();
+		if (tick_change == 1) {	/*  MDIO indicated a change  */
+			emac_update_phy_status((emac_dev_t *) dev);
+			emac_control_cb(dev,
+					EMAC_IOCTL_STATUS_UPDATE,
+					(void *)&dev->status, NULL);
+		} else if ((dev->init_cfg.phy_mode & SNWAY_AUTOMDIX)
+			   && (tick_change & _MIIMDIO_MDIXFLIP)) {
+			/* DaVinci does not have MDI/MDIX on chip facility */
+		}
+	}
+
+	return (EMAC_SUCCESS);
+}
+
+/**
+ * EMAC DDC Packet processing function
+ *  - Detects if there are host errors and invokes the DDA callback to inform
+ *    the DDA layer about the hardware error.
+ *
+ */
+static void emac_process_host_error(emac_dev_t * _dev)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	u32 channel = 0;
+	u32 vector = 0;
+	u32 status = 0;
+
+	/* the mac_status register bits starting from rx error channel
+	 * have been mapped to hw_err_info LSB 16 bits */
+	status = dev->regs->mac_status;
+
+	/* TX: reading the channel and cause */
+	channel =
+	    ((status & EMAC_MACSTATUS_TXERRCH_MASK) >>
+	     EMAC_MACSTATUS_TXERRCH_SHIFT);
+
+	dev->status.hw_err_info = channel << 16;
+
+	vector =
+	    (status & EMAC_MACSTATUS_TXERRCODE_MASK) >>
+	    EMAC_MACSTATUS_TXERRCODE_SHIFT;
+
+	if (vector) {
+		dev->status.hw_status = EMAC_TX_HOST_ERROR;
+		LOGERR
+		    ("Ch=%d, EMAC_TX_HOST_ERROR. Cause=%s",
+		     dev->status.hw_err_info,
+		     &emac_tx_host_error_codes[vector][0]);
+	}
+
+	/* RX: reading the channel and cause (vector variable being
+	 * re-used) */
+	channel =
+	    ((status & EMAC_MACSTATUS_RXERRCH_MASK) >>
+	     EMAC_MACSTATUS_RXERRCH_SHIFT);
+
+	dev->status.hw_err_info |= channel;
+	vector =
+	    (status & EMAC_MACSTATUS_RXERRCODE_MASK) >>
+	    EMAC_MACSTATUS_RXERRCODE_SHIFT;
+	if (vector) {
+		dev->status.hw_status = EMAC_RX_HOST_ERROR;
+		LOGERR
+		    ("Ch=%d, EMAC_RX_HOST_ERROR. Cause=%s",
+		     dev->status.hw_err_info,
+		     &emac_rx_host_error_codes[vector][0]);
+	}
+
+	/* inform DDA layer about this critical failure */
+	emac_control_cb(dev,
+			EMAC_IOCTL_STATUS_UPDATE, (void *)&dev->status, NULL);
+}
+
+/**
+ * EMAC DDC Packet processing function
+
+ * - Reads the device interrupt status and invokes TX/RX BD processing
+ *   function
+ * - Also detects if there are host errors and invokes the
+ *   callback to inform  about the hardware error.
+ *
+ * "pkts_pending" will contain number of packets still to be processed
+ * (TX + RX)
+ */
+static int emac_pkt_process(emac_dev_t * _dev, int *pkts_pending,
+			    void *pkt_args)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	u32 channel = 0;
+	u32 vector = 0;
+	u32 handle_pkts_and_status = 0;
+	u32 vector_channel = 0;
+	int pkts_processed = 0;
+
+	/* disable interrupts via module control (wrapper) */
+	((volatile ewrap_regs *)dev->e_wrap_regs)->EWCTL = 0x0;
+	vector = dev->regs->mac_in_vector;
+
+	/* handle packet transmit completion */
+	if (vector & EMAC_MAC_IN_VECTOR_TX_INT_VEC) {
+		bool is_eoq;
+
+		vector_channel = (vector & EMAC_MAC_IN_VECTOR_TX_INT_VEC);
+		for (channel = 0; channel < 8; channel++) {
+			if (vector_channel & 0x1)
+				break;
+
+			vector_channel >>= 1;
+		}
+
+		handle_pkts_and_status =
+		    dev->tx_cppi[channel]->ch_info.service_max;
+		if (pkt_args)
+			handle_pkts_and_status =
+			    emac_min_val(((rx_tx_params *) pkt_args)->tx_pkts,
+					 handle_pkts_and_status);
+
+		pkts_processed =
+		    emac_tx_bdproc(_dev, channel, &handle_pkts_and_status,
+				   &is_eoq);
+		if (pkt_args)
+			((rx_tx_params *) pkt_args)->ret_tx_pkts =
+			    pkts_processed;
+
+		if (dev->tx_interrupt_disable == TRUE) {
+			/* status */
+			if (!handle_pkts_and_status && is_eoq)
+				/* disable channel interrupt */
+				dev->regs->tx_int_mask_clear = (1 << channel);
+		}
+		*pkts_pending = handle_pkts_and_status;	/* status. */
+	}
+
+	/* Handle RX packets first - the thought process in this is
+	 * that the received packets will be handled immediately
+	 * reducing the latency (- but an equally opposite argument
+	 * can also be made)
+	 */
+	if (vector & EMAC_MAC_IN_VECTOR_RX_INT_VEC) {
+		vector_channel = (vector & EMAC_MAC_IN_VECTOR_RX_INT_VEC);
+		vector_channel >>= 8;
+		for (channel = 0; channel < 8; channel++) {
+			if (vector_channel & 0x1)
+				break;
+			vector_channel >>= 1;
+		}
+
+		handle_pkts_and_status =
+		    dev->rx_cppi[channel]->ch_info.service_max;
+		if (pkt_args)
+			handle_pkts_and_status =
+			    emac_min_val(((rx_tx_params *) pkt_args)->rx_pkts,
+					 handle_pkts_and_status);
+
+		pkts_processed =
+		    emac_rx_bdproc(_dev, channel, &handle_pkts_and_status);
+
+		if (pkt_args)
+			((rx_tx_params *) pkt_args)->ret_rx_pkts =
+			    pkts_processed;
+
+		*pkts_pending |= handle_pkts_and_status;	/* status */
+	}
+
+	/* handle host errors - being handled last does not mean its
+	 * of least priority */
+	if (vector & EMAC_MAC_IN_VECTOR_HOST_INT) {
+		emac_process_host_error(_dev);
+	}
+
+	return (EMAC_SUCCESS);
+}
+
+/**
+ * EMAC DDC Signal Packet processing end to hardware
+ * - programs the EOI vector register so that if there are pending
+ *   packets in hardware queue * an interrupt can be generated by the
+ *   hardware
+ */
+/* packet processing end */
+static int emac_pkt_process_end(emac_dev_t * _dev, void *proc_args)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	/* enable interrupts via module control (wrapper) */
+	((volatile ewrap_regs *)dev->e_wrap_regs)->EWCTL = 0x1;
+
+	return (EMAC_SUCCESS);
+}
+
+#ifdef EMAC_MULTIFRAGMENT
+
+#error "EMAC Multi fragment Not supported"
+
+#else
+
+/*************************************
+ * SINGLE-FRAGMENT SUPPORT HERE
+ *************************************/
+
+/**
+ * EMAC DDC Send/Transmit function
+ *  - Queues the packet provided by DDA into hardware queue
+ *  - If the queue is stalled due to sync issues, re-trigger the hardware
+ *
+ * If "sendArgs" is TRUE (non zero) CRC is calculated by DDA or upper
+ * layer and not by hardware and is part of the packet data send to
+ * this function
+ */
+
+static int emac_send(emac_dev_t * _dev, net_pkt_obj * pkt,
+		     int channel, bool send_args)
+{
+	unsigned long flags;
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	int ret_val = EMAC_SUCCESS;
+	emac_tx_bd *curr_bd;
+	emac_tx_cppi_ch *tx_cppi;
+	net_buf_obj *buf_list;
+
+	/* verify proper device state */
+	if (dev->drv_state != DRV_OPENED)
+		return (EMAC_ERR_DEV_NOT_OPEN);
+
+	/* validate channel number and get channel control structure */
+	if (channel > EMAC_MAX_TX_CHANNELS)
+		return (EMAC_ERR_TX_CH_INVALID);
+
+	if (dev->tx_is_open[channel] != TRUE)
+		return (EMAC_ERR_TX_CH_NOT_OPEN);
+
+	/* check ethernet link state. if not linked, return error */
+	if (!dev->status.phy_linked)
+		return (EMAC_ERR_TX_NO_LINK);
+
+	tx_cppi = dev->tx_cppi[channel];
+	buf_list = pkt->buf_list;	/* get handle to the buffer array */
+
+	/* check packet size and if < EMAC_MIN_ETHERNET_PKT_SIZE, pad it up */
+	if (pkt->pkt_length < EMAC_MIN_ETHERNET_PKT_SIZE) {
+		buf_list->length +=
+		    (EMAC_MIN_ETHERNET_PKT_SIZE - pkt->pkt_length);
+		pkt->pkt_length = EMAC_MIN_ETHERNET_PKT_SIZE;
+	}
+	spin_lock_irqsave(&dev->tx_lock, flags);
+
+	/* only one tx BD for the packet to be sent */
+	curr_bd = tx_cppi->bd_pool_head;
+	if (curr_bd == NULL) {
+#ifdef EMAC_GETSTATS
+		tx_cppi->out_of_tx_bd++;
+#endif
+		ret_val = EMAC_ERR_TX_OUT_OF_BD;
+		goto exit_emac_send;
+	}
+
+	tx_cppi->bd_pool_head = curr_bd->next;
+
+	/* populate the BD contents to be added to the TX list */
+	curr_bd->buf_token = buf_list->buf_token;
+	curr_bd->buff_ptr = EMAC_VIRT_TO_PHYS((int *)buf_list->data_ptr);
+	curr_bd->off_b_len = buf_list->length;
+	curr_bd->h_next = 0;
+	curr_bd->next = 0;
+	curr_bd->mode =
+	    (EMAC_CPPI_SOP_BIT | EMAC_CPPI_OWNERSHIP_BIT | EMAC_CPPI_EOP_BIT
+	     | pkt->pkt_length);
+
+	if ((bool) send_args == TRUE)
+		curr_bd->mode |= EMAC_CPPI_PASS_CRC_BIT;
+
+	/* flush the packet from cache if write back cache is present */
+	BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+
+	/* send the packet */
+	if (tx_cppi->active_queue_head == 0) {
+		tx_cppi->active_queue_head = curr_bd;
+		tx_cppi->active_queue_tail = curr_bd;
+		if (tx_cppi->queue_active != TRUE) {
+			dev->regs->tx_HDP[channel] = EMAC_VIRT_TO_PHYS(curr_bd);
+			tx_cppi->queue_active = TRUE;
+		}
+#ifdef EMAC_GETSTATS
+		++tx_cppi->queue_reinit;
+#endif
+	} else {
+		register volatile emac_tx_bd *tail_bd;
+		register u32 frame_status;
+
+		tail_bd = tx_cppi->active_queue_tail;
+		tail_bd->next = curr_bd;
+		tx_cppi->active_queue_tail = curr_bd;
+		tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
+		tail_bd->h_next = (int)EMAC_VIRT_TO_PHYS(curr_bd);
+		frame_status = tail_bd->mode;
+		if (frame_status & EMAC_CPPI_EOQ_BIT) {
+			dev->regs->tx_HDP[channel] = EMAC_VIRT_TO_PHYS(curr_bd);
+			frame_status &= ~(EMAC_CPPI_EOQ_BIT);
+			tail_bd->mode = frame_status;
+#ifdef EMAC_GETSTATS
+			++tx_cppi->end_of_queue_add;
+#endif
+		} else {
+			if (dev->tx_interrupt_disable == TRUE) {
+				/* enable channel interrupt */
+				dev->regs->tx_int_mask_set = (1 << channel);
+			}
+		}
+	}
+#ifdef EMAC_GETSTATS
+	tx_cppi->active_queue_count++;
+#endif
+
+      exit_emac_send:
+	spin_unlock_irqrestore(&dev->tx_lock, flags);
+
+	if (dev->tx_interrupt_disable == TRUE) {
+		if (--dev->tx_int_threshold[channel] <= 0) {
+			bool is_eoq;
+			u32 handle_pkts_and_status;
+
+			handle_pkts_and_status =
+			    dev->tx_cppi[channel]->ch_info.service_max;
+			emac_tx_bdproc(_dev, channel, &handle_pkts_and_status,
+				       &is_eoq);
+			dev->tx_int_threshold[channel] =
+			    dev->tx_cppi[channel]->ch_info.service_max;
+		}
+	}
+
+	return (ret_val);
+}
+
+/**
+ * EMAC DDC TX Buffer Descriptor processing
+ *  - processes transmit completed packets and returns the handles to DDA layer
+ *  - If the queue is stalled due to sync issues, re-trigger the hardware
+ *
+ * returns number of pkts processed and 1 in morePkts if pkt
+ * completion processing pending
+ */
+static int emac_tx_bdproc(emac_dev_t * _dev, u32 channel,
+			  u32 * handle_pkts_and_status, bool * is_eoq)
+{
+	unsigned long flags;
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	emac_tx_bd *curr_bd;
+	emac_tx_cppi_ch *tx_cppi;
+	volatile u32 frame_status;
+	u32 pkts_processed = 0;
+	u32 pkts_to_process = *handle_pkts_and_status;
+#ifdef EMAC_MULTIPACKET_TX_COMPLETE_NOTIFY
+	u32 tx_complete_cnt = 0;
+	u32 *tx_complete_ptr;
+#endif
+
+	*handle_pkts_and_status = 0;	/* status. */
+	*is_eoq = TRUE;
+
+	/* Here no need to validate channel number, since it is taken
+	   from the interrupt register instead channel structure
+	   should be validated */
+	if (dev->tx_is_open[channel] == FALSE)
+		return (EMAC_ERR_TX_CH_NOT_OPEN);
+
+	if (dev->tx_teardown_pending[channel] == TRUE) {
+		return (EMAC_SUCCESS);	/* dont handle any pkt completions */
+	}
+
+	tx_cppi = dev->tx_cppi[channel];
+#ifdef EMAC_MULTIPACKET_TX_COMPLETE_NOTIFY
+	tx_complete_ptr = &tx_cppi->tx_complete[0];
+#endif
+#ifdef EMAC_GETSTATS
+	++tx_cppi->proc_count;
+#endif
+	spin_lock_irqsave(&dev->tx_lock, flags);
+
+	/* get first BD to process */
+	curr_bd = tx_cppi->active_queue_head;
+	if (curr_bd == 0) {
+		dev->regs->tx_CP[channel] =
+		    EMAC_VIRT_TO_PHYS(tx_cppi->last_hw_bdprocessed);
+#ifdef EMAC_GETSTATS
+		tx_cppi->no_active_pkts++;
+#endif
+		spin_unlock_irqrestore(&dev->tx_lock, flags);
+
+		return (EMAC_SUCCESS);
+	}
+
+	/* invalidate BD */
+	BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+
+	frame_status = curr_bd->mode;
+	while ((curr_bd) &&
+	       ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
+	       (pkts_processed < pkts_to_process)) {
+
+		dev->regs->tx_CP[channel] = EMAC_VIRT_TO_PHYS(curr_bd);
+		tx_cppi->active_queue_head = curr_bd->next;
+		if (frame_status & EMAC_CPPI_EOQ_BIT) {
+			if (curr_bd->next) {	/* misqueued packet */
+				dev->regs->tx_HDP[channel] = curr_bd->h_next;
+#ifdef EMAC_GETSTATS
+				++tx_cppi->mis_queued_packets;
+#endif
+			} else {	/* end of queue */
+				tx_cppi->queue_active = FALSE;
+			}
+		}
+#ifdef EMAC_MULTIPACKET_TX_COMPLETE_NOTIFY
+		*tx_complete_ptr = (u32) curr_bd->buf_token;
+		++tx_complete_ptr;
+		++tx_complete_cnt;
+#else
+		/* single packet TX complete notify - this function is
+		 * called in the send critical section context */
+		emac_net_tx_complete(dev,
+				     &curr_bd->buf_token, 1, (void *)channel);
+#endif
+		curr_bd->next = tx_cppi->bd_pool_head;
+		tx_cppi->bd_pool_head = curr_bd;
+#ifdef EMAC_GETSTATS
+		--tx_cppi->active_queue_count;
+#endif
+		pkts_processed++;
+		tx_cppi->last_hw_bdprocessed = curr_bd;
+		curr_bd = tx_cppi->active_queue_head;
+		if (curr_bd) {
+			BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+			frame_status = curr_bd->mode;
+		}
+	}			/* end of while loop */
+
+	if ((curr_bd) && ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) {
+		*handle_pkts_and_status = 1;
+	}
+        /* this check is same as check for EOQ i.e framestatus and
+         * EMAC_CPPI_EOQ_BIT */
+	if (curr_bd) {
+		*is_eoq = FALSE;
+	}
+
+#ifdef EMAC_MULTIPACKET_TX_COMPLETE_NOTIFY
+	/* multiple packet TX complete notify - this function is NOT
+	 * called in the send critical section context */
+	emac_net_tx_complete(dev,
+			     (emac_net_data_token *) & tx_cppi->
+			     tx_complete[0], tx_complete_cnt, channel);
+#endif
+	spin_unlock_irqrestore(&dev->tx_lock, flags);
+
+	return (pkts_processed);
+}
+
+/**
+ * EMAC DDC Add Buffer to RX queue function
+ *  - returns the BD to the Receive queue
+ *  - If the queue is stalled due to sync issues, re-trigger the hardware
+ */
+static void emac_add_bdto_rx_queue(emac_dev_t * _dev, emac_rx_cppi_ch * rx_cppi,
+				   emac_rx_bd * curr_bd, char *buffer,
+				   emac_net_data_token buf_token)
+{
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+
+	/* populate the hardware descriptor */
+	curr_bd->h_next = 0;
+	curr_bd->buff_ptr = EMAC_VIRT_TO_PHYS(buffer);
+	curr_bd->off_b_len = rx_cppi->ch_info.buf_size;
+	curr_bd->mode = EMAC_CPPI_OWNERSHIP_BIT;
+	curr_bd->next = 0;
+	curr_bd->data_ptr = buffer;
+	curr_bd->buf_token = buf_token;
+
+	/* write back  */
+	BD_CACHE_WRITEBACK_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+	if (rx_cppi->active_queue_head == 0) {
+		rx_cppi->active_queue_head = curr_bd;
+		rx_cppi->active_queue_tail = curr_bd;
+		if (rx_cppi->queue_active != FALSE) {
+			dev->regs->rx_HDP[rx_cppi->ch_info.ch_num] =
+			    EMAC_VIRT_TO_PHYS(rx_cppi->active_queue_head);
+			rx_cppi->queue_active = TRUE;
+		}
+	} else {
+		emac_rx_bd *tail_bd;
+		u32 frame_status;
+
+		tail_bd = rx_cppi->active_queue_tail;
+		rx_cppi->active_queue_tail = curr_bd;
+		tail_bd->next = (void *)curr_bd;
+		tail_bd = EMAC_VIRT_NOCACHE(tail_bd);
+		tail_bd->h_next = EMAC_VIRT_TO_PHYS(curr_bd);
+		frame_status = tail_bd->mode;
+		if (frame_status & EMAC_CPPI_EOQ_BIT) {
+			dev->regs->rx_HDP[rx_cppi->ch_info.ch_num] =
+			    EMAC_VIRT_TO_PHYS(curr_bd);
+			frame_status &= ~(EMAC_CPPI_EOQ_BIT);
+			tail_bd->mode = frame_status;
+#ifdef EMAC_GETSTATS
+			++rx_cppi->end_of_queue_add;
+#endif
+		}
+
+	}
+
+#ifdef EMAC_GETSTATS
+	++rx_cppi->recycled_bd;	/* maintain statistics of how many BD's were queued back - recycled */
+#endif
+}
+
+/**
+ * EMAC DDC RX Buffer Descriptor processing
+ *  - processes received packets and passes them to DDA layer
+ *  - requeues the buffer descriptor to the receive pool
+ *  - If the queue is stalled due to sync issues, re-trigger the hardware
+ */
+static int emac_rx_bdproc(emac_dev_t * _dev, u32 channel,
+			  int *handle_pkts_and_status)
+{
+	unsigned long flags;
+	emac_dev_t *dev = (emac_dev_t *) _dev;
+	emac_rx_cppi_ch *rx_cppi;
+	emac_rx_bd *curr_bd, *last_bd;
+	u32 frame_status;
+	char *new_buffer;
+	emac_net_data_token new_buf_token;
+	net_buf_obj *rx_buf_obj;
+	u32 pkts_processed;
+	net_pkt_obj *curr_pkt,pkt_obj;
+	net_buf_obj buf_obj;
+	u32 pkts_to_be_processed = *handle_pkts_and_status;
+
+	/* Here no need to validate channel number, since it is taken
+	   from the interrupt register instead channel structure
+	   should be validated */
+	if (dev->rx_is_open[channel] == FALSE) {
+		*handle_pkts_and_status = 0;
+		return (EMAC_ERR_RX_CH_NOT_OPEN);
+	}
+
+	/* check if channel teardown pending */
+	rx_cppi = dev->rx_cppi[channel];
+	if (dev->rx_teardown_pending[channel] == TRUE) {
+		*handle_pkts_and_status = 0;
+		return (0);
+	}
+#ifdef EMAC_GETSTATS
+	++rx_cppi->proc_count;
+#endif
+	*handle_pkts_and_status = 0;
+	pkts_processed = 0;
+
+	spin_lock_irqsave(&dev->rx_lock, flags);
+
+	pkt_obj.buf_list = &buf_obj;
+	curr_pkt = &pkt_obj;
+	curr_bd = rx_cppi->active_queue_head;
+	BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+	frame_status = curr_bd->mode;
+
+	while ((curr_bd) &&
+	       ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0) &&
+	       (pkts_processed < pkts_to_be_processed)) {
+
+		/* allocate new buffer */
+		new_buffer =
+		    (void *)(emac_net_alloc_rx_buf(dev,
+						   rx_cppi->ch_info.buf_size,
+						   &new_buf_token, 0, NULL));
+		if (new_buffer == NULL) {
+			/* no buffer available. return error with packets pending */
+#ifdef EMAC_GETSTATS
+			++rx_cppi->out_of_rx_buffers;
+#endif
+			goto end_emac_rx_bdproc;
+		}
+
+		/* populate received packet data structure */
+		rx_buf_obj = &curr_pkt->buf_list[0];
+		rx_buf_obj->data_ptr = (char *)curr_bd->data_ptr;
+		rx_buf_obj->length = curr_bd->off_b_len & EMAC_RX_BD_BUF_SIZE;
+		rx_buf_obj->buf_token = curr_bd->buf_token;
+		curr_pkt->pkt_token = curr_pkt->buf_list->buf_token;
+		curr_pkt->num_bufs = 1;
+		curr_pkt->pkt_length =
+		    (frame_status & EMAC_RX_BD_PKT_LENGTH_MASK);
+		/* acknowledge RX interrupt for the channel */
+		dev->regs->rx_CP[channel] = EMAC_VIRT_TO_PHYS(curr_bd);
+#ifdef EMAC_GETSTATS
+		++rx_cppi->processed_bd;
+#endif
+		last_bd = curr_bd;
+		curr_bd = last_bd->next;
+		rx_cppi->active_queue_head = curr_bd;
+
+		/* check if end of RX queue ? */
+		if (frame_status & EMAC_CPPI_EOQ_BIT) {
+			if (curr_bd) {	/* misqueued packet */
+#ifdef EMAC_GETSTATS
+				++rx_cppi->mis_queued_packets;
+#endif
+				dev->regs->rx_HDP[channel] =
+				    EMAC_VIRT_TO_PHYS(curr_bd);
+			} else {	/* end of queue */
+#ifdef EMAC_GETSTATS
+				++rx_cppi->end_of_queue;
+#endif
+				rx_cppi->queue_active = FALSE;	/* clear software RX queue */
+			}
+		}
+
+		/* recycle BD */
+		emac_add_bdto_rx_queue(_dev, rx_cppi, last_bd, new_buffer,
+				       new_buf_token);
+
+		/* return the packet to the user - BD ptr passed in
+		 * last parameter for potential *future* use */
+		spin_unlock_irqrestore(&dev->rx_lock, flags);
+		emac_net_rx_cb(dev,curr_pkt,(void*)channel);
+		spin_lock_irqsave(&dev->rx_lock, flags);
+
+		curr_bd = rx_cppi->active_queue_head;
+		if (curr_bd) {
+			BD_CACHE_INVALIDATE(curr_bd, EMAC_BD_LENGTH_FOR_CACHE);
+			frame_status = curr_bd->mode;
+		}
+		++pkts_processed;
+	}
+
+	if ((curr_bd) && ((frame_status & EMAC_CPPI_OWNERSHIP_BIT) == 0)) {
+		*handle_pkts_and_status = 1;
+	}
+
+      end_emac_rx_bdproc:
+	spin_unlock_irqrestore(&dev->rx_lock, flags);
+	return (pkts_processed);
+}
+
+#endif				/* !EMAC_MULTIFRAGMENT */
+
+/* Linux 2.6 Kernel Ethernet Poll function Call only RX processing in
+ * the poll function - TX is taken care of in interrupt context
+ */
+static int emac_poll(struct net_device *netdev, int *budget)
+{
+	emac_dev_t *dev = netdev_priv(netdev);
+	unsigned int work = min(netdev->quota, *budget);
+	unsigned int pkts_pending = 0;
+	/* this is used to pass the rx packets to be processed and
+	 * return the number of rx packets processed */
+	rx_tx_params *napi_params = &dev->napi_rx_tx;
+
+	if (!dev->set_to_close) {
+		napi_params->rx_pkts = work;
+		napi_params->tx_pkts = EMAC_DEFAULT_TX_MAX_SERVICE;
+
+		/* process packets - call the DDC packet processing function */
+		emac_pkt_process(dev, &pkts_pending, napi_params);
+
+		/* if more packets reschedule the tasklet or call
+		 * pkt_process_end */
+		if (!pkts_pending) {
+			if (test_bit(__LINK_STATE_RX_SCHED, &netdev->state)) {
+				netif_rx_complete(netdev);
+			}
+			emac_pkt_process_end(dev, NULL);
+			return 0;
+		} else if (!test_bit(0, &dev->set_to_close)) {
+			*budget -= napi_params->ret_rx_pkts;
+			netdev->quota -= napi_params->ret_rx_pkts;
+			return 1;
+		}
+	}
+
+        /* we are closing down, so dont process anything */
+	return 0;
+}
+
+#ifdef CONFIG_NET_POLL_CONTROLLER
+/*
+ * Polling receive - used by netconsole and other diagnostic tools
+ * to allow network i/o with interrupts disabled.
+ */
+void emac_poll_controller(struct net_device *netdev)
+{
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+
+	disable_irq(netdev->irq);
+	emac_hal_isr(netdev->irq, dev);
+	enable_irq(netdev->irq);
+}
+#endif
+
+/* allocate RX buffer */
+void *emac_net_alloc_rx_buf(emac_dev_t * dev, int buf_size,
+			    emac_net_data_token * data_token,
+			    u32 channel, void *alloc_args)
+{
+	struct net_device *netdev = dev->owner;
+	struct sk_buff *p_skb;
+
+	p_skb = dev_alloc_skb(dev->rx_buf_size);
+	if (p_skb == NULL) {
+#ifdef EMAC_DEBUG
+		ERR("emac_net_alloc_rx_buf:Failed to allocate skb for %s.\n",
+		    netdev->name);
+#endif
+		return (NULL);
+	}
+
+	/* set device pointer in skb and reserve space for extra bytes */
+	p_skb->dev = netdev;
+	skb_reserve(p_skb, dev->rx_buf_offset);
+
+	/* set the data token */
+	*data_token = (emac_net_data_token) p_skb;
+#ifdef EMAC_CACHE_INVALIDATE_FIX
+	/* invalidate buffer */
+	EMAC_CACHE_INVALIDATE((unsigned long)p_skb->data, buf_size);
+#endif
+
+	return p_skb->data;
+}
+
+/* free RX buffer */
+static int emac_net_free_rx_buf(emac_dev_t * dev, void *buffer,
+				emac_net_data_token data_token,
+				u32 channel, void *free_args)
+{
+	dev_kfree_skb_any((struct sk_buff *)data_token);
+	return (EMAC_SUCCESS);
+}
+
+
+/*
+ * Packet receive notification
+ *
+ * This function gets received packet via the netPktList and
+ * it queues the packet into the higher layer queue
+ *
+ * Note that rxArgs contains "channel" and is ignored for this
+ * implementation
+*/
+static int emac_net_rx_cb(emac_dev_t * dev,
+		          net_pkt_obj * net_pkt_list,
+			  void *rx_args)
+{
+
+	struct sk_buff *p_skb;
+
+	p_skb = (struct sk_buff *)net_pkt_list->pkt_token;
+
+	/* set length of packet */
+	skb_put(p_skb, net_pkt_list->pkt_length);
+#ifndef EMAC_CACHE_INVALIDATE_FIX
+	/* invalidate cache */
+	EMAC_CACHE_INVALIDATE((unsigned long)p_skb->data, p_skb->len);
+#endif
+	p_skb->protocol = eth_type_trans(p_skb, dev->owner);
+	p_skb->dev->last_rx = jiffies;
+	netif_receive_skb(p_skb);
+	dev->net_dev_stats.rx_bytes += net_pkt_list->pkt_length;
+	dev->net_dev_stats.rx_packets++;
+
+	return (0);
+}
+
+
+/* transmit complete callback */
+static int emac_net_tx_complete(emac_dev_t * dev,
+				emac_net_data_token * net_data_tokens,
+				int num_tokens, u32 channel)
+{
+	u32 cnt;
+
+	if (num_tokens && netif_queue_stopped(dev->owner)) {
+		printk("EMAC: TX Complete: Starting queue\n");
+		netif_start_queue(dev->owner);
+	}
+
+	for (cnt = 0; cnt < num_tokens; cnt++) {
+		struct sk_buff *skb = (struct sk_buff *)net_data_tokens[cnt];
+		if (skb == NULL)
+			continue;
+
+		dev->net_dev_stats.tx_packets++;
+		dev->net_dev_stats.tx_bytes += skb->len;
+		dev_kfree_skb_any(skb);
+	}
+
+	return (0);
+}
+
+/******************************************************************************
+ *  Interrupt functions
+ *****************************************************************************/
+
+irqreturn_t emac_hal_isr(int irq, void *dev_id)
+{
+	emac_dev_t *dev = (emac_dev_t *) dev_id;
+
+	++dev->isr_count;
+	if (!dev->set_to_close) {
+		/* NAPI support */
+		netif_rx_schedule(dev->owner);
+	} else {
+		/* we are closing down, so dont process anything */
+	}
+
+	return IRQ_HANDLED;
+}
+
+/* transmit function - only single fragment supported */
+static int emac_dev_tx(struct sk_buff *skb, struct net_device *netdev)
+{
+	int ret_code;
+	net_buf_obj tx_buf;	/* buffer object - only single frame support */
+	net_pkt_obj tx_packet;	/* packet object */
+	emac_dev_t *dev = NETDEV_PRIV(netdev);
+	/* ANANT HACK: unsigned long flags; */
+
+	/* Build the buffer and packet objects - Since only single fragment is
+	 * supported, need not set length and token in both packet & object.
+	 * Doing so for completeness sake & to show that this needs to be done
+	 * in multifragment case
+	 */
+	tx_packet.buf_list = &tx_buf;
+	tx_packet.num_bufs = 1;	/* only single fragment supported */
+	tx_packet.pkt_length = skb->len;
+	tx_packet.pkt_token = (emac_net_data_token) skb;
+	tx_buf.length = skb->len;
+	tx_buf.buf_token = (emac_net_data_token) skb;
+	tx_buf.data_ptr = skb->data;
+
+	/* flush data buffer if write back mode */
+	EMAC_CACHE_WRITEBACK((unsigned long)skb->data, skb->len);
+	netdev->trans_start = jiffies;
+
+	/* ANANT_HACK: Need to lock TX so that there is no contention
+	   spin_lock_irqsave(&hDDA->lock, flags);
+	 */
+
+	/* DDC send : last param FALSE so that hardware calculates CRC */
+	ret_code = emac_send(dev, &tx_packet, EMAC_DEFAULT_TX_CHANNEL, FALSE);
+
+	/* ANANT_HACK: Need to un-lock TX so that there is no contention
+	   between two processes
+	   spin_unlock_irqrestore(&hDDA->lock, flags);
+	 */
+
+	if (ret_code != EMAC_SUCCESS) {
+		if (ret_code == EMAC_ERR_TX_OUT_OF_BD) {
+			ERR("WARN: emac_dev_tx: Out of TX BD's\n");
+			netif_stop_queue(dev->owner);
+		}
+		dev->net_dev_stats.tx_dropped++;
+		goto emac_dev_tx_drop_pkt;
+	}
+	return (0);
+
+      emac_dev_tx_drop_pkt:
+	dev->net_dev_stats.tx_dropped++;
+
+	return (-1);
+}
+
+/******************************************************************************
+ *  Linux Driver Model
+ *****************************************************************************/
+
+/* The real device and driver matching will be done by the
+ * match routine of the platform bus. It is necessary
+ * for the probe function to be non null though.
+ * We have a function that just returns zero. "All matched."
+ */
+static int __devinit emac_probe(struct device *dev)
+{
+	return 0;
+}
+
+/* structure describing the EMAC driver */
+static struct device_driver emac_driver = {
+	.name = "emac",
+	.bus = &platform_bus_type,
+	.probe = emac_probe,
+	.remove = NULL,		/* TODO: findout when probe would be called. */
+	.suspend = NULL,
+	.resume = NULL,
+};
+
+/******************************************************************************
+ *  Linux Module Init/Exit
+ *****************************************************************************/
+
+static struct platform_device *emac_dev;
+
+static ssize_t emac_show_version(struct device_driver *drv, char *buf)
+{
+	return emac_p_get_version(buf, NULL, 0, 4096, NULL, NULL);
+}
+
+static DRIVER_ATTR(version, S_IRUGO, emac_show_version, NULL);
+
+/* probe number of EMAC instances and register net_device structure */
+static int __init emac_dev_probe(void)
+{
+	int ret_val = 0;
+	int unit;
+	int instance_count = EMAC_MAX_INSTANCES;
+
+	/* obtain clock rate from kernel clock API's */
+	emac_clk = clk_get(0, "EMACCLK");
+	if (IS_ERR(emac_clk)) {
+		printk("TI DAVINCI EMAC: Failed to get clock. Exiting\n");
+		return (-1);
+	}
+	clk_enable(emac_clk);
+	emac_bus_frequency = clk_get_rate(emac_clk);
+
+	emac_dev =
+	    platform_device_register_simple("ti_davinci_emac", -1, NULL, 0);
+
+	if (IS_ERR(emac_dev)) {
+		/* if error, free EMAC clock */
+		clk_disable(emac_clk);
+		return -1;
+	}
+
+	if (driver_register(&emac_driver)) {
+		platform_device_unregister(emac_dev);
+
+		/* if error, free EMAC clock */
+		clk_disable(emac_clk);
+		return -1;
+	}
+
+	ret_val = driver_create_file(&emac_driver, &driver_attr_version);
+	if(ret_val)
+		return ret_val;
+	for (unit = 0; unit < instance_count; unit++) {
+		struct net_device *netdev;
+		emac_dev_t *dev;
+		int failed;
+
+		if (!(netdev = alloc_etherdev(sizeof(emac_dev_t)))) {
+			printk
+			    ("TI DaVinci EMAC: Etherdev alloc failed for device inst %d.\n",
+			     unit);
+
+			ret_val = -ENOMEM;
+			/* if error, free EMAC clock */
+			clk_disable(emac_clk);
+			break;
+		}
+		dev = NETDEV_PRIV(netdev);
+		dev->owner = netdev;
+		dev->instance_num = unit;
+		netdev->init = emac_dev_init;
+		SET_NETDEV_DEV(netdev, &(emac_dev->dev));
+		emac_net_dev[dev->instance_num] = netdev;
+#if defined CONFIG_EMAC_INIT_BUF_MALLOC
+		g_init_enable_flag = 1;
+#endif
+		emac_p_detect_manual_cfg(cfg_link_speed, cfg_link_mode,
+					 debug_mode);
+		if (emac_cfg_probe()) {
+			printk("TI DAVINCI EMAC: Error in configuration.\n");
+			return (-1);
+		}
+
+		/* register the network device with linux */
+		failed = register_netdev(netdev);
+
+		if (failed) {
+			ERR("Could not register device: %d\n", failed);
+
+			ret_val = -1;
+
+			clk_disable(emac_clk);
+
+			FREE_NETDEV(netdev);
+			break;
+		} else {
+			dev->next_device = last_emac_device;
+			last_emac_device = netdev;
+			DBG("%s irq=%2d io=%04x\n",
+			    netdev->name, (int)netdev->irq,
+			    (int)netdev->base_addr);
+			create_proc_read_entry("net/emac_rfc2665_stats", 0,
+					       NULL, emac_p_read_rfc2665_stats,
+					       netdev);
+		}
+	}
+
+	if (ret_val == 0) {
+		/* to maintain backward compatibility with NSP. */
+		gp_stats_file = create_proc_entry("net/emac_stats", 0644, NULL);
+		if (gp_stats_file) {
+			gp_stats_file->read_proc = emac_p_read_stats;
+			gp_stats_file->write_proc = emac_p_write_stats;
+		}
+		create_proc_read_entry("net/emac_link", 0, NULL,
+				       emac_p_read_link, NULL);
+		create_proc_read_entry("net/emac_ver", 0, NULL,
+				       emac_p_get_version, NULL);
+		create_proc_read_entry("net/emac_config", 0, NULL,
+				       emac_dump_config, NULL);
+	}
+	emac_devices_installed = unit;
+
+	printk("%s\n", emac_version_string);
+	printk("TI DaVinci EMAC: Installed %d instances.\n", unit);
+#if defined CONFIG_EMAC_INIT_BUF_MALLOC
+	printk
+	    ("TI DAVINCI EMAC driver is allocating buffer memory at init time.\n");
+#endif
+
+	return ((unit >= 0) ? 0 : -ENODEV);
+}
+
+/* frees the EMAC device structures */
+static void emac_exit(void)
+{
+	struct net_device *netdev;
+	emac_dev_t *dev;
+	int ret_code;
+
+	while (emac_devices_installed) {
+		char proc_name[100];
+		int proc_category_name_len = 0;
+
+		netdev = last_emac_device;
+		dev = NETDEV_PRIV(netdev);
+
+		DBG("Unloading %s irq=%2d io=%04x\n",
+		    netdev->name, (int)netdev->irq, (int)netdev->base_addr);
+
+		/* free EMAC clock */
+		clk_disable(emac_clk);
+
+		if (g_init_enable_flag) {
+			emac_p_dev_disable(dev);
+		}
+
+		/* deinit DDC */
+		ret_code = emac_de_init(dev, NULL);
+
+		if (ret_code != EMAC_SUCCESS) {
+			ERR("Error %08X from Deinit()\n", ret_code);
+
+			/* we dont want to quit from here, lets delete
+			 * the instance also */
+		}
+
+		/* delete the proc entry */
+		strcpy(proc_name, "davinci/");
+		strcat(proc_name, netdev->name);
+		proc_category_name_len = strlen(proc_name);
+		strcpy(proc_name + proc_category_name_len, "_rfc2665_stats");
+		remove_proc_entry(proc_name, NULL);
+
+		/* release memory region and unregister the device */
+		release_mem_region(netdev->base_addr, EMAC_DEFAULT_EMAC_SIZE);
+		unregister_netdev(netdev);
+
+		last_emac_device = dev->next_device;
+		if (netdev)
+			FREE_NETDEV(netdev);
+
+		emac_devices_installed--;
+	}
+
+	if (gp_stats_file)
+		remove_proc_entry("net/emac_stats", NULL);
+
+	remove_proc_entry("net/emac_link", NULL);
+	remove_proc_entry("net/emac_ver", NULL);
+	remove_proc_entry("net/emac_config", NULL);
+
+	platform_device_unregister(emac_dev);
+
+	printk("TI DAVINCI EMAC: platform device unregistered.\n");
+	driver_remove_file(&emac_driver, &driver_attr_version);
+	printk("TI DAVINCI EMAC: driver file removed.\n");
+	driver_unregister(&emac_driver);
+	printk("TI DAVINCI EMAC: driver unregistered.\n");
+}
+
+module_init(emac_dev_probe);
+module_exit(emac_exit);
diff --git a/drivers/net/davinci_emac_phy.c b/drivers/net/davinci_emac_phy.c
new file mode 100644
index 0000000..61c0917
--- /dev/null
+++ b/drivers/net/davinci_emac_phy.c
@@ -0,0 +1,745 @@
+/*
+ * linux/drivers/net/davinci_emac_phy.c
+ *
+ * EMAC MII-MDIO Module - Polling State Machine.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ Modifications:
+ *  HISTORY:
+ *  Date      	Modifier         		Notes
+ *  2001/02 	Denis, Bill, Michael		Original
+ *  14Feb2006	Anant Gole 			Re-written for linux
+ *  07Dec2006	Paul Bartholomew		Fix half-duplex,
+ *           					use PHY_DUPLEX_* constants
+ */
+#include <linux/kernel.h>
+
+#include "davinci_emac_phy.h"
+
+#define EMAC_PHY_DEBUG
+
+#ifdef EMAC_PHY_DEBUG
+/* note: prints function name for you */
+#define DPRINTK(fmt, args...) if (emac_phy->debug_mode) printk(KERN_ERR "\n%s: " fmt, __FUNCTION__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+/* Phy Registers */
+#define PHY_CONTROL_REG       	0
+#define MII_PHY_RESET           (1<<15)
+#define MII_PHY_LOOP            (1<<14)
+#define MII_PHY_100             (1<<13)
+#define MII_AUTO_NEGOTIATE_EN   (1<<12)
+#define MII_PHY_PDOWN           (1<<11)
+#define MII_PHY_ISOLATE         (1<<10)
+#define MII_RENEGOTIATE         (1<<9)
+#define MII_PHY_FD              (1<<8)
+
+#define PHY_STATUS_REG        	1
+#define MII_NWAY_COMPLETE       (1<<5)
+#define MII_NWAY_CAPABLE        (1<<3)
+#define MII_PHY_LINKED          (1<<2)
+
+#define NWAY_ADVERTIZE_REG    	4
+#define NWAY_REMADVERTISE_REG 	5
+#define MII_NWAY_FD100          (1<<8)
+#define MII_NWAY_HD100          (1<<7)
+#define MII_NWAY_FD10           (1<<6)
+#define MII_NWAY_HD10           (1<<5)
+#define MII_NWAY_SEL            (1<<0)
+
+/* Timeout values - since timer tikc is expected to be 10 mSecs fixed these
+ * values are in (value * 10 mSecs) */
+#define PHY_FIND_TIMEOUT (2)
+#define PHY_RECK_TIMEOUT (200)
+#define PHY_LINK_TIMEOUT (500)
+#define PHY_NWST_TIMEOUT (500)
+#define PHY_NWDN_TIMEOUT (800)
+#define PHY_MDIX_TIMEOUT (274)	/* 2.74 Seconds <--Spec and empirical */
+
+/* Mask & Control defines */
+#define MDIO_CONTROL_CLKDIV           	(0xFF)
+#define MDIO_CONTROL_ENABLE           	(1 << 30)
+#define MDIO_USERACCESS_GO     			(1 << 31)
+#define MDIO_USERACCESS_WRITE  			(1 << 30)
+#define MDIO_USERACCESS_READ   			(0 << 30)
+#define MDIO_USERACCESS_WRITE  			(1 << 30)
+#define MDIO_USERACCESS_REGADR 			(0x1F << 21)
+#define MDIO_USERACCESS_PHYADR 			(0x1F << 16)
+#define MDIO_USERACCESS_DATA   			(0xFFFF)
+#define MDIO_USERPHYSEL_LINKSEL         (1 << 7)
+#define MDIO_VER_MODID         			(0xFFFF << 16)
+#define MDIO_VER_REVMAJ        			(0xFF   << 8)
+#define MDIO_VER_REVMIN        			(0xFF)
+
+/* PHY Registers */
+#define MDIO_VER						(0x00)
+#define MDIO_CONTROL					(0x04)
+#define MDIO_ALIVE						(0x08)
+#define MDIO_LINK						(0x0C)
+#define MDIO_LINKINTRAW					(0x10)
+#define MDIO_LINKINTMASKED				(0x14)
+#define MDIO_USERINTRAW					(0x20)
+#define MDIO_USERINTMASKED				(0x24)
+#define MDIO_USERINTMASKED_SET			(0x28)
+#define MDIO_USERINTMASKED_CLR			(0x2C)
+#define MDIO_USERACCESS(inst)			(0x80+(inst*8))
+#define MDIO_USERPHYSEL(inst) 			(0x84+(inst*8))
+
+#define MDIO_REG(reg)					(*((volatile unsigned int *)(emac_phy->base + (reg))))
+
+#define MDIO_REG_VER					MDIO_REG(MDIO_VER)
+#define MDIO_REG_CONTROL				MDIO_REG(MDIO_CONTROL)
+#define MDIO_REG_ALIVE					MDIO_REG(MDIO_ALIVE)
+#define MDIO_REG_LINK					MDIO_REG(MDIO_LINK)
+#define MDIO_REG_LINKINTRAW				MDIO_REG(MDIO_LINKINTRAW)
+#define MDIO_REG_LINKINTMASKED			MDIO_REG(MDIO_LINKINTMASKED)
+#define MDIO_REG_USERINTMASKED			MDIO_REG(MDIO_USERINTMASKED)
+#define MDIO_REG_USERINTMASKED_SET		MDIO_REG(MDIO_USERINTMASKED_SET)
+#define MDIO_REG_USERINTMASKED_CLR		MDIO_REG(MDIO_USERINTMASKED_CLR)
+#define MDIO_REG_USERACCESS				MDIO_REG(MDIO_USERACCESS(emac_phy->inst))
+#define MDIO_REG_USERPHYSEL				MDIO_REG(MDIO_USERPHYSEL(emac_phy->inst))
+
+/* Phy State */
+#define PHY_NULL       (0)
+#define PHY_INIT       (1)
+#define PHY_FINDING    (2)
+#define PHY_FOUND      (3)
+#define PHY_NWAY_START (4)
+#define PHY_NWAY_WAIT  (5)
+#define PHY_LINK_WAIT  (6)
+#define PHY_LINKED     (7)
+#define PHY_LOOPBACK   (8)
+
+static char *phy_state_str[] = {
+	"NULL", "INIT", "FINDING", "FOUND", "NWAY_START", "NWAY_WAIT",
+	"LINK_WAIT", "LINKED", "LOOPBACK"
+};
+
+#define PHY_NOT_FOUND  0xFFFF	/*  Used in Phy Detection */
+
+struct phy_info {
+	int inst;		/* Instance of PHY - for user sel register */
+	unsigned int base;	/* Base address of mdio module */
+	int state;		/* state of phy */
+	int state_change;	/* phy state change ? */
+	unsigned int timeout;	/* Timeout counter */
+	unsigned int phy_mode;	/* requested phy mode */
+	unsigned int speed;	/* current Speed - 10 / 100 */
+	unsigned int duplex;	/* 0=Auto Negotiate, Full=3; Half=2, Unknown=1 */
+	unsigned int phy_addr;	/* phy address */
+	unsigned int phy_mask;	/* phy mask */
+	unsigned int mlink_mask;/* mlink mask */
+	int debug_mode;		/* debug mode */
+};
+
+/* Global phy structure instance */
+struct phy_info emac_phy_info;
+struct phy_info *emac_phy = &emac_phy_info;
+
+void emac_mdio_get_ver(unsigned int mdio_base, unsigned int *module_id,
+		       unsigned int *rev_major, unsigned int *rev_minor)
+{
+	unsigned int ver;
+
+	emac_phy->base = mdio_base;
+	ver = MDIO_REG_VER;
+
+	*module_id = (ver & MDIO_VER_MODID) >> 16;
+	*rev_major = (ver & MDIO_VER_REVMAJ) >> 8;
+	*rev_minor = (ver & MDIO_VER_REVMIN);
+}
+
+/* Initialize mdio module */
+int emac_mdio_init(unsigned int mdio_base,
+		   unsigned int inst,
+		   unsigned int phy_mask,
+		   unsigned int mlink_mask,
+		   unsigned int mdio_bus_freq,
+		   unsigned int mdio_clock_freq, unsigned int verbose)
+{
+	unsigned int clk_div;
+
+	/* Set base addr and init phy state */
+	emac_phy->inst = inst;
+	emac_phy->base = mdio_base;
+	emac_phy->phy_mask = phy_mask;
+	emac_phy->mlink_mask = mlink_mask;
+	emac_phy->state = PHY_INIT;
+	emac_phy->debug_mode = verbose;
+	emac_phy->speed = 10;
+	emac_phy->duplex = PHY_DUPLEX_HALF;	/* Half duplex */
+
+	if (mdio_clock_freq & mdio_bus_freq) {
+		clk_div = ((mdio_bus_freq / mdio_clock_freq) - 1);
+	} else {
+		clk_div = 0xFF;
+	}
+	clk_div &= MDIO_CONTROL_CLKDIV;
+
+	/* Set enable and clock divider in MDIOControl */
+	MDIO_REG_CONTROL = (clk_div | MDIO_CONTROL_ENABLE);
+
+	return (0);
+}
+
+/* Set PHY mode - autonegotiation or any other */
+void emac_mdio_set_phy_mode(unsigned int phy_mode)
+{
+	emac_phy->phy_mode = phy_mode;
+
+	if ((emac_phy->state == PHY_NWAY_START) ||
+	    (emac_phy->state == PHY_NWAY_WAIT) ||
+	    (emac_phy->state == PHY_LINK_WAIT) ||
+	    (emac_phy->state == PHY_LINKED) ||
+	    (emac_phy->state == PHY_LOOPBACK)) {
+		emac_phy->state = PHY_FOUND;
+		emac_phy->state_change = 1;
+	}
+
+	DPRINTK("PhyMode:%08X Auto:%d, FD10:%d, HD10:%d, FD100:%d, HD100:%d\n",
+		phy_mode,
+		phy_mode & NWAY_AUTO, phy_mode & MII_NWAY_FD10,
+		phy_mode & MII_NWAY_HD10, phy_mode & MII_NWAY_FD100,
+		phy_mode & MII_NWAY_HD100);
+}
+
+/* Get linked status - check if link is on - 1=link on, 0=link off */
+int emac_mdio_is_linked(void)
+{
+	return ((emac_phy->state == PHY_LINKED) ? 1 : 0);
+}
+
+/* Get speed - 10 / 100 Mbps */
+int emac_mdio_get_speed(void)
+{
+	return (emac_phy->speed);
+}
+
+/* Get duplex - 0=Auto Negotiate, Full Duplex = 3; Half Duplex = 2 Unknown = 1 */
+int emac_mdio_get_duplex(void)
+{
+	return (emac_phy->duplex);
+}
+
+/* Get Phy number/address */
+int emac_mdio_get_phy_num(void)
+{
+	return (emac_phy->phy_addr);
+}
+
+/* Check if loopback enabled on phy */
+int emac_mdio_is_loopback(void)
+{
+	return ((emac_phy->state == PHY_LOOPBACK) ? 1 : 0);
+}
+
+/* Wait until mdio is ready for next command */
+#define MDIO_WAIT_FOR_USER_ACCESS while ((MDIO_REG_USERACCESS & MDIO_USERACCESS_GO) != 0) {}
+
+/* Read from a phy register via mdio interface */
+unsigned int emac_mdio_read(unsigned int phy_addr, unsigned int phy_reg)
+{
+	unsigned int phy_data = 0;
+	unsigned int phy_control;
+
+	/* Wait until mdio is ready for next command */
+	MDIO_WAIT_FOR_USER_ACCESS;
+
+	phy_control = (MDIO_USERACCESS_GO |
+		       MDIO_USERACCESS_READ |
+		       ((phy_reg << 21) & MDIO_USERACCESS_REGADR) |
+		       ((phy_addr << 16) & MDIO_USERACCESS_PHYADR) |
+		       (phy_data & MDIO_USERACCESS_DATA));
+	MDIO_REG_USERACCESS = phy_control;
+
+	/* Wait until mdio is ready for next command */
+	MDIO_WAIT_FOR_USER_ACCESS;
+
+	return (MDIO_REG_USERACCESS & MDIO_USERACCESS_DATA);
+}
+
+/* Write to a phy register via mdio interface */
+void emac_mdio_write(unsigned int phy_addr, unsigned int phy_reg,
+		     unsigned int phy_data)
+{
+	unsigned int control;
+
+	/* Wait until mdio is ready for next command */
+	MDIO_WAIT_FOR_USER_ACCESS;
+
+	control = (MDIO_USERACCESS_GO |
+		   MDIO_USERACCESS_WRITE |
+		   ((phy_reg << 21) & MDIO_USERACCESS_REGADR) |
+		   ((phy_addr << 16) & MDIO_USERACCESS_PHYADR) |
+		   (phy_data & MDIO_USERACCESS_DATA));
+	MDIO_REG_USERACCESS = control;
+
+}
+
+/* Reset the selected phy */
+void emac_mdio_phy_reset(unsigned int phy_addr)
+{
+	unsigned int control;
+
+	emac_mdio_write(phy_addr, PHY_CONTROL_REG, MII_PHY_RESET);
+
+	do {
+		control = emac_mdio_read(phy_addr, PHY_CONTROL_REG);
+	} while (control & MII_PHY_RESET);
+
+	/* CRITICAL: Fix for increasing PHY signal drive strength for
+	 * TX lockup issue. On DaVinci EVM, the Intel LXT971 PHY
+  	 * signal strength was low causing  TX to fail randomly. The
+	 * fix is to Set bit 11 (Increased MII drive strength) of PHY
+         * register 26 (Digital Config register) on this phy. */
+	control = emac_mdio_read(phy_addr, 26);
+	emac_mdio_write(phy_addr, 26, (control | 0x800));
+	control = emac_mdio_read(phy_addr, 26);
+}
+
+/* Timeout condition handler in PHY state machine */
+void emac_mdio_phy_timeout(void)
+{
+	emac_phy->state = PHY_FOUND;
+	emac_phy->state_change = 1;
+
+	/* If MDI/MDIX is supported then switch MDIX state */
+}
+
+/* PHY state machine : Init state handler */
+void emac_mdio_init_state(void)
+{
+	emac_phy->state = PHY_FINDING;
+	emac_phy->state_change = 1;
+	emac_phy->timeout = PHY_FIND_TIMEOUT;
+}
+
+/* PHY state machine : Finding state handler */
+void emac_mdio_finding_state(void)
+{
+	unsigned int phy_alive_status;
+	int i, j;
+
+	emac_phy->phy_addr = PHY_NOT_FOUND;
+
+	/* Find if timeout complete */
+	if (emac_phy->timeout) {
+		/* Allow some time for phy to show up in alive register */
+		--emac_phy->timeout;
+	} else {
+
+		phy_alive_status = MDIO_REG_LINK;
+		/* Check phys based upon user mask */
+		phy_alive_status &= emac_phy->phy_mask;
+
+		/* Find the first interesting alive phy */
+		for (i = 0, j = 1;
+		     (i < 32) && ((j & phy_alive_status) == 0); i++, j <<= 1) ;
+
+		if ((phy_alive_status) && (i < 32)) {
+			emac_phy->phy_addr = i;
+		}
+
+		if (emac_phy->phy_addr != PHY_NOT_FOUND) {
+			DPRINTK("PHY Found. Phy Number=%d\n",
+				emac_phy->phy_addr);
+			emac_phy->state = PHY_FOUND;
+			emac_phy->state_change = 1;
+		} else {
+			/* Set Timer for finding timeout */
+			DPRINTK("PHY NOT Found. Starting timeout\n");
+			emac_phy->timeout = PHY_RECK_TIMEOUT;
+		}
+	}
+}
+
+/* PHY state machine : Found state handler */
+void emac_mdio_found_state(void)
+{
+	unsigned int phy_status;
+	unsigned int phy_num;
+	unsigned int cnt;
+	unsigned int nway_advertise;
+
+	/* Check if there is any phy mode requested by the user */
+	if (emac_phy->phy_mode == 0) {
+		return;
+	}
+
+	/* Check alive phy's */
+	phy_status = MDIO_REG_LINK;
+	phy_status &= emac_phy->phy_mask;	/* Check phys based upon user mask */
+
+	/* we will now isolate all our phys, except the one we have decided to use */
+	for (phy_num = 0, cnt = 1; phy_num < 32; phy_num++, cnt <<= 1) {
+		if (phy_status & cnt) {
+			if (phy_num != emac_phy->phy_addr) {
+				/* Disable a phy that we are not using */
+				/* CRITICAL: Note that this code assums that there is only 1 phy connected
+				 * if this is not the case then the next statement should be commented
+				 */
+				emac_mdio_write(emac_phy->phy_addr,
+						PHY_CONTROL_REG,
+						(MII_PHY_ISOLATE |
+						 MII_PHY_PDOWN));
+			}
+		}
+	}
+
+	/*  Reset the Phy and proceed with auto-negotiation */
+	emac_mdio_phy_reset(emac_phy->phy_addr);
+
+	/*  Set the way Link will be Monitored, Check the Link Selection Method */
+	if ((1 << emac_phy->phy_addr) & emac_phy->mlink_mask) {
+		MDIO_REG_USERPHYSEL =
+		    (emac_phy->phy_addr | MDIO_USERPHYSEL_LINKSEL);
+	}
+
+	/* For Phy Internal loopback , need to wait until Phy found */
+	if (emac_phy->phy_mode & NWAY_LPBK) {
+		/* Set Phy in Loopback and read mdio to confirm */
+		emac_mdio_write(emac_phy->phy_addr, PHY_CONTROL_REG,
+				(MII_PHY_LOOP | MII_PHY_FD));
+		emac_mdio_read(emac_phy->phy_addr, PHY_STATUS_REG);
+		emac_phy->state = PHY_LOOPBACK;
+		emac_phy->state_change = 1;
+		return;
+	}
+
+	/* Start negotiation */
+	nway_advertise = MII_NWAY_SEL;
+	if (emac_phy->phy_mode & NWAY_FD100)
+		nway_advertise |= MII_NWAY_FD100;
+	if (emac_phy->phy_mode & NWAY_HD100)
+		nway_advertise |= MII_NWAY_HD100;
+	if (emac_phy->phy_mode & NWAY_FD10)
+		nway_advertise |= MII_NWAY_FD10;
+	if (emac_phy->phy_mode & NWAY_HD10)
+		nway_advertise |= MII_NWAY_HD10;
+
+	phy_status = emac_mdio_read(emac_phy->phy_addr, PHY_STATUS_REG);
+
+	if ((phy_status & MII_NWAY_CAPABLE) && (emac_phy->phy_mode & NWAY_AUTO)) {
+
+		/* NWAY Phy Detected - following procedure for NWAY compliant Phys */
+		emac_mdio_write(emac_phy->phy_addr, NWAY_ADVERTIZE_REG,
+				nway_advertise);
+		if (emac_phy->debug_mode) {
+			DPRINTK("NWAY Advertising: ");
+			if (nway_advertise & MII_NWAY_FD100)
+				DPRINTK("100 Mbps FullDuplex");
+			if (nway_advertise & MII_NWAY_HD100)
+				DPRINTK("100 Mbps HalfDuplex");
+			if (nway_advertise & MII_NWAY_FD10)
+				DPRINTK("10 Mbps FullDuplex");
+			if (nway_advertise & MII_NWAY_HD10)
+				DPRINTK("10 Mbps HalfDuplex");
+			DPRINTK("\n");
+		}
+
+		/* Start/Restart autonegotiation */
+		emac_mdio_write(emac_phy->phy_addr, PHY_CONTROL_REG,
+				MII_AUTO_NEGOTIATE_EN);
+		emac_mdio_write(emac_phy->phy_addr, PHY_CONTROL_REG,
+				(MII_AUTO_NEGOTIATE_EN | MII_RENEGOTIATE));
+		emac_phy->state = PHY_NWAY_START;
+		emac_phy->state_change = 1;
+		emac_phy->timeout = PHY_NWST_TIMEOUT;
+
+	} else {
+		/* Phy cannot do auto negotiation */
+		emac_phy->phy_mode &= ~NWAY_AUTO;
+		nway_advertise &= ~MII_NWAY_SEL;
+		phy_status = 0;
+
+		if (nway_advertise & (MII_NWAY_FD100 | MII_NWAY_HD100)) {
+			phy_status = MII_PHY_100;	/* Set 100 Mbps if requested */
+			nway_advertise &= (MII_NWAY_FD100 | MII_NWAY_HD100);
+		} else {
+			nway_advertise &= (MII_NWAY_FD10 | MII_NWAY_HD10);
+		}
+
+		if (nway_advertise & (MII_NWAY_FD100 | MII_NWAY_FD10)) {
+			phy_status |= MII_PHY_FD;	/* Set Full duplex if requested */
+		}
+
+		/* Set requested speed and duplex mode on phy */
+		emac_mdio_write(emac_phy->phy_addr, PHY_CONTROL_REG,
+				phy_status);
+
+		/* Set the phy speed and duplex mode */
+		emac_phy->speed = (phy_status & MII_PHY_100) ? 100 : 10;
+		emac_phy->duplex = (phy_status & MII_PHY_FD) ? 3 : 2;
+
+		emac_phy->state = PHY_LINK_WAIT;
+		emac_phy->state_change = 1;
+		emac_phy->timeout = PHY_LINK_TIMEOUT;
+	}
+
+	/* TODO: When Auto MDIX is supported, add delay here
+	   emac_mdio_mdix_delay();
+	 */
+}
+
+/* PHY state machine : NWAY Start state handler */
+void emac_mdio_nwaystart_state(void)
+{
+	unsigned int status;
+
+	status = emac_mdio_read(emac_phy->phy_addr, PHY_CONTROL_REG);
+	if ((status & MII_RENEGOTIATE) == 0) {
+		/* Flush pending latched bits */
+		status = emac_mdio_read(emac_phy->phy_addr, PHY_STATUS_REG);
+		emac_phy->state = PHY_NWAY_WAIT;
+		emac_phy->state_change = 1;
+		emac_phy->timeout = PHY_NWDN_TIMEOUT;
+	} else {
+		if (emac_phy->timeout) {
+			--emac_phy->timeout;
+		} else {
+			/* Timed Out for NWAY to start - very unlikely condition, back to Found */
+			emac_mdio_phy_timeout();
+		}
+	}
+}
+
+/* PHY state machine : NWAY Wait state handler */
+void emac_mdio_nwaywait_state(void)
+{
+	unsigned int status;
+	unsigned int my_cap, partner_cap, neg_mode;
+
+	/* Check if nway negotiation complete */
+	status = emac_mdio_read(emac_phy->phy_addr, PHY_STATUS_REG);
+
+	if (status & MII_NWAY_COMPLETE) {
+		/* negotiation complete, check for partner capabilities */
+		emac_phy->state_change = 1;
+		my_cap = emac_mdio_read(emac_phy->phy_addr, NWAY_ADVERTIZE_REG);
+		partner_cap =
+		    emac_mdio_read(emac_phy->phy_addr, NWAY_REMADVERTISE_REG);
+
+		/* Negotiated mode is what we and partnet have in common */
+		neg_mode = my_cap & partner_cap;
+		if (emac_phy->debug_mode) {
+			DPRINTK
+			    ("Phy %d, neg_mode %04X, my_cap %04X, partner_cap %04X\n",
+			     emac_phy->phy_addr, neg_mode, my_cap, partner_cap);
+		}
+
+		/* Limit negotiation to fields below */
+		neg_mode &=
+		    (MII_NWAY_FD100 | MII_NWAY_HD100 | MII_NWAY_FD10 |
+		     MII_NWAY_HD10);
+		if (neg_mode == 0)
+			DPRINTK
+			    ("WARNING: Negotiation complete but NO agreement, default is 10HD\n");
+
+		if (neg_mode & MII_NWAY_FD100)
+			DPRINTK("100 Mbps FullDuplex");
+		if (neg_mode & MII_NWAY_HD100)
+			DPRINTK("100 Mbps HalfDuplex");
+		if (neg_mode & MII_NWAY_FD10)
+			DPRINTK("10 Mbps FullDuplex");
+		if (neg_mode & MII_NWAY_HD10)
+			DPRINTK("10 Mbps HalfDuplex");
+		DPRINTK("\n");
+
+		if (neg_mode != 0) {
+			if (status & MII_PHY_LINKED) {
+				emac_phy->state = PHY_LINKED;
+			} else {
+				emac_phy->state = PHY_LINK_WAIT;
+			}
+		}
+
+		/* Set the phy speed and duplex mode */
+		emac_phy->speed =
+		    (neg_mode & (MII_NWAY_FD100 | MII_NWAY_HD100)) ? 100 : 10;
+		emac_phy->duplex =
+		    (neg_mode & (MII_NWAY_FD100 | MII_NWAY_FD10)) ?
+				PHY_DUPLEX_FULL : PHY_DUPLEX_HALF;
+
+	} else {
+
+		if (emac_phy->timeout) {
+			--emac_phy->timeout;
+		} else {
+			/* Timed Out for NWAY to start - very unlikely condition, back to Found */
+			emac_mdio_phy_timeout();
+		}
+	}
+}
+
+/* PHY state machine : Link Wait state handler */
+void emac_mdio_linkwait_state(void)
+{
+	unsigned int status;
+
+	/* Check if nway negotiation complete */
+	status = emac_mdio_read(emac_phy->phy_addr, PHY_STATUS_REG);
+	if (status & MII_PHY_LINKED) {
+		emac_phy->state = PHY_LINKED;
+		emac_phy->state_change = 1;
+	} else {
+		if (emac_phy->timeout) {
+			--emac_phy->timeout;
+		} else {
+			/* Timed Out for link - very unlikely condition, back to Found */
+			emac_mdio_phy_timeout();
+		}
+	}
+}
+
+/* PHY state machine : Linked handler */
+void emac_mdio_linked_state(void)
+{
+	if (MDIO_REG_LINK & (1 << emac_phy->phy_addr)) {
+		return;		/* do nothing if already linked */
+	}
+
+	/* If not linked, move mode to nway down or waiting for link */
+	emac_phy->state_change = 1;
+	if (emac_phy->phy_mode & NWAY_AUTO) {
+		emac_phy->state = PHY_NWAY_WAIT;
+		emac_phy->timeout = PHY_NWDN_TIMEOUT;
+	} else {
+		emac_phy->state = PHY_LINK_WAIT;
+		emac_phy->timeout = PHY_LINK_TIMEOUT;
+	}
+
+	/* TODO: When Auto MDIX is supported, add delay here
+	   emac_mdio_mdix_delay();
+	 */
+}
+
+/* PHY state machine : Loopback handler */
+void emac_mdio_loopback_state(void)
+{
+	return;
+}
+
+/* PHY state machine : Default handler */
+void emac_mdio_default_state(void)
+{
+	/* Awaiting a init call */
+	emac_phy->state_change = 1;
+}
+
+/* Detailed PHY dump for debug */
+void emac_mdio_phy_dump(void)
+{
+	unsigned int status;
+
+	DPRINTK("\n");
+	DPRINTK("PHY Addr/Num=%d, PHY State=%s, Speed=%d, Duplex=%d\n",
+		emac_phy->phy_addr, phy_state_str[emac_phy->state],
+		emac_phy->speed, emac_phy->duplex);
+
+	/* 0: Control register */
+	status = emac_mdio_read(emac_phy->phy_addr, PHY_CONTROL_REG);
+	DPRINTK("PhyControl: %04X, Loopback=%s, Speed=%s, Duplex=%s\n",
+		status,
+		status & MII_PHY_LOOP ? "On" : "Off",
+		status & MII_PHY_100 ? "100" : "10",
+		status & MII_PHY_FD ? "Full" : "Half");
+
+	/* 1: Status register */
+	status = emac_mdio_read(emac_phy->phy_addr, PHY_STATUS_REG);
+	DPRINTK("PhyStatus: %04X, AutoNeg=%s, Link=%s\n",
+		status,
+		status & MII_NWAY_COMPLETE ? "Complete" : "NotComplete",
+		status & MII_PHY_LINKED ? "Up" : "Down");
+
+	/* 4: Auto Negotiation Advertisement register */
+	status = emac_mdio_read(emac_phy->phy_addr, NWAY_ADVERTIZE_REG);
+	DPRINTK("PhyMyCapability: %04X, 100FD=%s, 100HD=%s, 10FD=%s, 10HD=%s\n",
+		status,
+		status & MII_NWAY_FD100 ? "Yes" : "No",
+		status & MII_NWAY_HD100 ? "Yes" : "No",
+		status & MII_NWAY_FD10 ? "Yes" : "No",
+		status & MII_NWAY_HD10 ? "Yes" : "No");
+
+	/* 5: Auto Negotiation Advertisement register */
+	status = emac_mdio_read(emac_phy->phy_addr, NWAY_REMADVERTISE_REG);
+	DPRINTK
+	    ("PhyPartnerCapability: %04X, 100FD=%s, 100HD=%s, 10FD=%s, 10HD=%s\n",
+	     status, status & MII_NWAY_FD100 ? "Yes" : "No",
+	     status & MII_NWAY_HD100 ? "Yes" : "No",
+	     status & MII_NWAY_FD10 ? "Yes" : "No",
+	     status & MII_NWAY_HD10 ? "Yes" : "No");
+}
+
+/* emac_mdio_tick is called every 10 mili seconds to process Phy states */
+int emac_mdio_tick(void)
+{
+
+	switch (emac_phy->state) {
+
+	case PHY_INIT:
+		emac_mdio_init_state();
+		break;
+
+	case PHY_FINDING:
+		emac_mdio_finding_state();
+		break;
+
+	case PHY_FOUND:
+		emac_mdio_found_state();
+		break;
+
+	case PHY_NWAY_START:
+		emac_mdio_nwaystart_state();
+		break;
+
+	case PHY_NWAY_WAIT:
+		emac_mdio_nwaywait_state();
+		break;
+
+	case PHY_LINK_WAIT:
+		emac_mdio_linkwait_state();
+		break;
+
+	case PHY_LINKED:
+		emac_mdio_linked_state();
+		break;
+
+	case PHY_LOOPBACK:
+		emac_mdio_loopback_state();
+		break;
+
+	default:
+		emac_mdio_default_state();
+		break;
+	}
+
+	/* Check is MDI/MDIX mode switch is needed - not supported in DaVinci hardware */
+
+	/* Return state change to user */
+	if (emac_phy->state_change) {
+		emac_mdio_phy_dump();
+		emac_phy->state_change = 0;
+		return (1);
+	} else {
+		return (0);
+	}
+}
diff --git a/drivers/net/davinci_emac_phy.h b/drivers/net/davinci_emac_phy.h
new file mode 100644
index 0000000..3d5ba73
--- /dev/null
+++ b/drivers/net/davinci_emac_phy.h
@@ -0,0 +1,103 @@
+/*
+ * linux/drivers/net/davinci_emac_phy.h
+ *
+ * MDIO Polling State Machine API. Functions will enable mii-Phy
+ * negotiation.
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ *
+ * ----------------------------------------------------------------------------
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ----------------------------------------------------------------------------
+ * Modifications:
+ *  HISTORY:
+ *  Date      Modifier         Ver    Notes
+ *  01Jan01 Denis, Bill             Original
+ *  27Mar02 Michael Hanrahan Original (modified from emacmdio.h)
+ *  04Apr02 Michael Hanrahan Added Interrupt Support
+ *  07Dec06 Paul Bartholomew Added PHY_DUPLEX_* defines
+ */
+#ifndef _DAVINCI_EMAC_PHY_H_
+#define _DAVINCI_EMAC_PHY_H_
+
+/* phy mode values  */
+#define NWAY_AUTOMDIX       (1<<16)
+#define NWAY_FD1000         (1<<13)
+#define NWAY_HD1000         (1<<12)
+#define NWAY_NOPHY          (1<<10)
+#define NWAY_LPBK           (1<<9)
+#define NWAY_FD100          (1<<8)
+#define NWAY_HD100          (1<<7)
+#define NWAY_FD10           (1<<6)
+#define NWAY_HD10           (1<<5)
+#define NWAY_AUTO           (1<<0)
+
+/* phy duplex values */
+#define	PHY_DUPLEX_AUTO		0	/* Auto Negotiate */
+#define	PHY_DUPLEX_UNKNOWN	1	/* Unknown */
+#define	PHY_DUPLEX_HALF		2	/* Half Duplex */
+#define	PHY_DUPLEX_FULL		3	/* Full Duplex */
+
+/*
+ *    Tic() return values
+ */
+
+#define _MIIMDIO_MDIXFLIP (1<<28)
+
+#define _AUTOMDIX_DELAY_MIN  80	/* milli-seconds */
+#define _AUTOMDIX_DELAY_MAX 200	/* milli-seconds */
+
+/* Get module version */
+void emac_mdio_get_ver(unsigned int mdio_base, unsigned int *module_id,
+		       unsigned int *rev_major, unsigned int *rev_minor);
+
+/* Initialize mdio module */
+int emac_mdio_init(unsigned int mdio_base,
+		   unsigned int inst,
+		   unsigned int phy_mask,
+		   unsigned int mlink_mask,
+		   unsigned int mdio_bus_freq,
+		   unsigned int mdio_clock_freq, unsigned int verbose);
+
+/* Set PHY mode - autonegotiation or any other */
+void emac_mdio_set_phy_mode(unsigned int phy_mode);
+
+/* Get linked status - check if link is on - 1=link on, 0=link off */
+int emac_mdio_is_linked(void);
+
+/* Get speed - 10 / 100 Mbps */
+int emac_mdio_get_speed(void);
+
+/* Get duplex - 2=full duplex, 1=half duplex */
+int emac_mdio_get_duplex(void);
+
+/* Get Phy number/address */
+int emac_mdio_get_phy_num(void);
+
+/* Check if loopback enabled on phy */
+int emac_mdio_is_loopback(void);
+
+/* Read from a phy register via mdio interface */
+unsigned int emac_mdio_read(unsigned int phy_addr, unsigned int phy_reg);
+
+/* Write to a phy register via mdio interface */
+void emac_mdio_write(unsigned int phy_addr, unsigned int phy_reg,
+		     unsigned int phy_data);
+
+/* MDIO tick function - to be called every 10 mSecs */
+int emac_mdio_tick(void);
+
+#endif				/* _DAVINIC_EMAC_PHY_H_ */
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index c0d86bb..26d7026 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -122,6 +122,15 @@
 
 if I2C
 
+config RTC_DRV_DAVINCI_EVM
+	tristate "TI DaVinci EVM RTC"
+	depends on RTC_CLASS && I2C_DAVINCI && MACH_DAVINCI_EVM
+	help
+	  Supports the RTC firmware in the MSP430 on the DaVinci EVM.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called rtc-davinci-evm.
+
 config RTC_DRV_DS1307
 	tristate "Dallas/Maxim DS1307/37/38/39/40, ST M41T00"
 	help
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index 544fe4d..40c575f 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -21,6 +21,7 @@
 obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o
 obj-$(CONFIG_RTC_DRV_BFIN)	+= rtc-bfin.o
 obj-$(CONFIG_RTC_DRV_CMOS)	+= rtc-cmos.o
+obj-$(CONFIG_RTC_DRV_DAVINCI_EVM) += rtc-davinci-evm.o
 obj-$(CONFIG_RTC_DRV_DS1216)	+= rtc-ds1216.o
 obj-$(CONFIG_RTC_DRV_DS1307)	+= rtc-ds1307.o
 obj-$(CONFIG_RTC_DRV_DS1553)	+= rtc-ds1553.o
diff --git a/drivers/rtc/rtc-davinci-evm.c b/drivers/rtc/rtc-davinci-evm.c
new file mode 100644
index 0000000..c825308
--- /dev/null
+++ b/drivers/rtc/rtc-davinci-evm.c
@@ -0,0 +1,270 @@
+/*
+ * rtc-davinci-evm.c
+ *
+ * Copyright (C) 2004 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+
+#include <asm/mach-types.h>
+#include <asm/arch/i2c-client.h>
+
+
+/* REVISIT
+ *  - the firmware expects no I2C writes at all, not just no RTC-via-I2C
+ *    writes, for 100 usec after i2c read or write... that can't be
+ *    assured here.
+ *
+ *  - this am vs pm thing is bizarre ... firmware should just do a 24 hour
+ *    clock, rather than 12 hour with hidden am/pm (we must guess).
+ *    similarly with it trying to handle DST for us...
+ *
+ *  - better (and simpler!!) firmware would support an RTC alarm, and just
+ *    count seconds since some UTC instant, letting Linux handle calendar
+ *    issues (leapyear, day of week, etc) and DST.
+ */
+static unsigned char am;
+
+
+static int evm_read_time(struct device *dev, struct rtc_time *tm)
+{
+	char rtcdata [9];
+
+	rtcdata[0] = 2;
+	rtcdata[1] = 1;
+	davinci_i2c_write(2, rtcdata, 0x23);
+
+	msleep(1);
+	davinci_i2c_read(9, rtcdata, 0x23);
+	msleep(1);
+
+	/* FIXME the RTC reports 12-hour time, without an AM/PM indicator,
+	 * but Linux requires that we report 24 hour time...
+	 */
+
+	tm->tm_year = BCD_TO_BIN(rtcdata[3]) * 100
+			+ BCD_TO_BIN(rtcdata[2])
+			- 1900;
+	tm->tm_mon = BCD_TO_BIN(rtcdata[4]);
+	tm->tm_mday = BCD_TO_BIN(rtcdata[5]);
+	tm->tm_hour = BCD_TO_BIN(rtcdata[6]);
+	tm->tm_min = BCD_TO_BIN(rtcdata[7]);
+	tm->tm_sec = BCD_TO_BIN(rtcdata[8]);
+
+	return 0;
+}
+
+static void am_or_pm(struct device *dev)
+{
+	char rtcdata [9];
+	struct rtc_time tm, time, temp;
+	unsigned char mon, day, hrs, min, sec;
+	unsigned char yr_low, yr_high;
+	unsigned int yrs;
+
+	evm_read_time(dev, &tm);
+
+	temp = tm;
+
+	yrs = temp.tm_year + 1900;
+	yr_high = yrs / 100;
+	yr_low = yrs % 100;
+
+	mon = temp.tm_mon + 1;
+	day = temp.tm_mday;
+	min = 59;
+	sec = 59;
+	hrs = 11;
+
+	rtcdata [0] = 9;
+	rtcdata [1] = 0;
+	rtcdata [2] = BIN_TO_BCD(yr_low);
+	rtcdata [3] = BIN_TO_BCD(yr_high);
+	mon--;
+	rtcdata [4] = BIN_TO_BCD(mon);
+	rtcdata [5] = BIN_TO_BCD(day);
+	rtcdata [6] = BIN_TO_BCD(hrs);
+	rtcdata [7] = BIN_TO_BCD(min);
+	rtcdata [8] = BIN_TO_BCD(sec);
+	davinci_i2c_write(9, rtcdata, 0x23);
+	msleep(1);
+	msleep(1000);
+	evm_read_time(dev, &time);
+
+	if (time.tm_mday == temp.tm_mday)
+		am = 1;
+	else
+		am = 0;
+
+	davinci_i2c_write(9, rtcdata, 0x23);
+	msleep(1);
+	msleep(1000);
+
+	yrs = tm.tm_year + 1900;
+	yr_high = yrs / 100;
+	yr_low = yrs % 100;
+
+	mon = tm.tm_mon + 1;
+	day = tm.tm_mday;
+	min = tm.tm_min;
+	hrs = tm.tm_hour;
+
+	if (tm.tm_sec < 58)
+		sec = tm.tm_sec + 2;
+	else
+		sec = 59;
+
+	davinci_i2c_write(9, rtcdata, 0x23);
+	msleep(1);
+}
+
+static int evm_set_time(struct device *dev, struct rtc_time *tm)
+{
+	char rtcdata [9];
+	char ampmdata [9];
+	unsigned char mon, day, hrs = 0, min, sec, leap_yr;
+	unsigned char yr_low, yr_high;
+	unsigned int yrs;
+
+	am_or_pm(dev);
+
+	yrs = tm->tm_year + 1900;
+	yr_high = yrs / 100;
+	yr_low = yrs % 100;
+
+	mon = tm->tm_mon;
+	hrs = tm->tm_hour;
+	day = tm->tm_mday;
+	min = tm->tm_min;
+	sec = tm->tm_sec;
+
+        leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
+
+	if (am == 1 && tm->tm_hour <= 12) {
+		hrs = tm->tm_hour;
+		if (tm->tm_hour == 0)
+			hrs = tm->tm_hour + 12;
+
+	} else if ((am == 1 && tm->tm_hour > 12)
+			|| (am == 0 && tm->tm_hour < 12)) {
+		unsigned char mon1 = mon, day1 = day, hrs1 = 11;
+		unsigned char min1 = 59, sec1 = 59;
+		unsigned char yr_low1 = yr_low, yr_high1 = yr_high;
+
+		ampmdata [0] = 9;
+		ampmdata [1] = 0;
+		ampmdata [2] = BIN_TO_BCD(yr_low1);
+		ampmdata [3] = BIN_TO_BCD(yr_high1);
+		ampmdata [4] = BIN_TO_BCD(mon1);
+		ampmdata [5] = BIN_TO_BCD(day1);
+		ampmdata [6] = BIN_TO_BCD(hrs1);
+		ampmdata [7] = BIN_TO_BCD(min1);
+		ampmdata [8] = BIN_TO_BCD(sec1);
+		davinci_i2c_write(9, ampmdata, 0x23);
+		msleep(1);
+		msleep(1000);
+		am = (am == 1) ? 0 : 1;
+
+		if (!am)
+			hrs = tm->tm_hour - 12;
+		else if (tm->tm_hour == 0)
+			hrs = tm->tm_hour + 12;
+
+	} else if (am == 0 && tm->tm_hour > 12)
+		hrs = tm->tm_hour - 12;
+
+	rtcdata [0] = 9;
+	rtcdata [1] = 0;
+	rtcdata [2] = BIN_TO_BCD(yr_low);
+	rtcdata [3] = BIN_TO_BCD(yr_high);
+	rtcdata [4] = BIN_TO_BCD(mon);
+	rtcdata [5] = BIN_TO_BCD(day);
+	rtcdata [6] = BIN_TO_BCD(hrs);
+	rtcdata [7] = BIN_TO_BCD(min);
+	rtcdata [8] = BIN_TO_BCD(sec);
+
+	davinci_i2c_write(9, rtcdata, 0x23);
+	msleep(1);
+
+	return 0;
+}
+
+static struct rtc_class_ops evm_rtc_ops = {
+	.read_time	= evm_read_time,
+	.set_time	= evm_set_time,
+};
+
+static int __devinit evm_rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device	*rtc;
+
+	/* the 2005-12-05 firmware doesn't issue RTC alarms on GPIO(7);
+	 * it only uses IRQ for card detect irqs with removable media.
+	 * plus it also hides the am/pm indicator and does magic DST...
+	 */
+	rtc = rtc_device_register(pdev->name, &pdev->dev,
+			&evm_rtc_ops, THIS_MODULE);
+	if (IS_ERR(rtc))
+		return PTR_ERR(rtc);
+
+	dev_warn(&pdev->dev, "WARNING: hours 12-23 are misreported as "
+			"duplicate hours 00-11\n");
+
+	platform_set_drvdata(pdev, rtc);
+	return 0;
+}
+
+static int __devexit evm_rtc_remove(struct platform_device *pdev)
+{
+	rtc_device_unregister(platform_get_drvdata(pdev));
+	return 0;
+}
+
+static struct platform_driver evm_rtc_driver = {
+	.driver = {
+		.name		= "rtc_davinci_evm",
+	},
+	.probe		= evm_rtc_probe,
+	.remove		= __devexit_p(evm_rtc_remove),
+};
+
+static int evm_rtc_init(void)
+{
+	if (!machine_is_davinci_evm())
+		return -ENODEV;
+
+	return platform_driver_register(&evm_rtc_driver);
+}
+module_init(evm_rtc_init);
+
+static void evm_rtc_exit(void)
+{
+	platform_driver_unregister(&evm_rtc_driver);
+}
+module_exit(evm_rtc_exit);
+
+MODULE_DESCRIPTION("RTC driver for TI DaVinci EVM");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 5216c11..0dfea58 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -1801,6 +1801,18 @@
 	  Say Y here to enable support for the IBM GXT4500P display
 	  adaptor, found on some IBM System P (pSeries) machines.
 
+config FB_DAVINCI
+	bool "Davinci Framebuffer support"
+	depends on FB && ARCH_DAVINCI
+	help
+	  This is the frame buffer device driver for the DaVinci video
+	  hardware found on the TI DaVinci EVM.	 If
+	  unsure, say N.
+
+config FB_VIRTUAL
+	tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)"
+	depends on FB
+
 config FB_PS3
 	tristate "PS3 GPU framebuffer driver"
 	depends on FB && PS3_PS3AV
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index b4668d7..5f2aeb4 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -120,6 +120,7 @@
 obj-$(CONFIG_FB_VGA16)            += vga16fb.o
 obj-$(CONFIG_FB_OF)               += offb.o
 obj-$(CONFIG_FB_OMAP)             += omap/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o
+obj-$(CONFIG_FB_DAVINCI)	  += davincifb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
diff --git a/drivers/video/davincifb.c b/drivers/video/davincifb.c
new file mode 100644
index 0000000..49f86cc
--- /dev/null
+++ b/drivers/video/davincifb.c
@@ -0,0 +1,1734 @@
+/*
+ * drivers/video/davincifb.c
+ *
+ * Framebuffer driver for Texas Instruments DaVinci display controller.
+ *
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ * Rishi Bhattacharya <support@ti.com>
+ *
+ * Leveraged from the framebuffer driver for OMAP24xx
+ * written by Andy Lowe (source@mvista.com)
+ * Copyright (C) 2004 MontaVista Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/tty.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/fb.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+
+#include <asm/irq.h>
+#include <asm/uaccess.h>
+
+#include <video/davincifb.h>
+#include <asm/system.h>
+
+#define MODULE_NAME "davincifb"
+
+/* Output Format Selection  */
+#define MULTIPLE_BUFFERING	1
+
+#ifdef MULTIPLE_BUFFERING
+#define DOUBLE_BUF	2
+#define TRIPLE_BUF	3
+#else
+#define DOUBLE_BUF	1
+#define TRIPLE_BUF	1
+#endif
+
+/*
+ * display controller register I/O routines
+ */
+static __inline__ u32 dispc_reg_in(u32 offset)
+{
+	return (inl(offset));
+}
+static __inline__ u32 dispc_reg_out(u32 offset, u32 val)
+{
+	outl(val, offset);
+	return (val);
+}
+static __inline__ u32 dispc_reg_merge(u32 offset, u32 val, u32 mask)
+{
+	u32 addr = offset;
+	u32 new_val = (inl(addr) & ~mask) | (val & mask);
+	outl(new_val, addr);
+	return (new_val);
+}
+
+/* There are 4 framebuffers, each represented by an fb_info and
+ * a dm_win_info structure */
+#define OSD0_FBNAME	"dm_osd0_fb"
+#define OSD1_FBNAME	"dm_osd1_fb"
+#define VID0_FBNAME	"dm_vid0_fb"
+#define VID1_FBNAME	"dm_vid1_fb"
+
+/* usage:	if (is_win(info->fix.id, OSD0)) ... */
+#define is_win(name, x) ((strcmp(name, x ## _FBNAME) == 0) ? 1 : 0)
+
+struct dm_win_info {
+	struct fb_info info;
+
+	/* X and Y position */
+	unsigned int x, y;
+
+	/* framebuffer area */
+	dma_addr_t fb_base_phys;
+	unsigned long fb_base;
+	unsigned long fb_size;
+
+	u32 pseudo_palette[17];
+
+	/* flag to identify if framebuffer area is fixed already or not */
+	int alloc_fb_mem;
+	unsigned long sdram_address;
+	struct dm_info *dm;
+};
+
+static struct dm_info {
+	struct dm_win_info *osd0;
+	struct dm_win_info *osd1;
+	struct dm_win_info *vid0;
+	struct dm_win_info *vid1;
+
+	/* to map the registers */
+	dma_addr_t mmio_base_phys;
+	unsigned long mmio_base;
+	unsigned long mmio_size;
+
+	wait_queue_head_t vsync_wait;
+	unsigned long vsync_cnt;
+	int timeout;
+
+	/* this is the function that configures the output device (NTSC/PAL/LCD)
+	 * for the required output format (composite/s-video/component/rgb)
+	 */
+	void (*output_device_config) (int on);
+
+	struct device *dev;
+} dm_static;
+static struct dm_info *dm = &dm_static;
+
+static struct fb_ops davincifb_ops;
+
+#define BASEX		0x80
+#define BASEY		0x12
+
+#define DISP_XRES	720
+#define DISP_YRES	480
+#define DISP_MEMY	576
+
+/* Random value chosen for now. Should be within the panel's supported range */
+#define LCD_PANEL_CLOCK	180000
+
+/* All window widths have to be rounded up to a multiple of 32 bytes */
+
+/* The OSD0 window has to be always within VID0. Plus, since it is in RGB565
+ * mode, it _cannot_ overlap with VID1.
+ * For defaults, we are setting the OSD0 window to be displayed in the top
+ * left quadrant of the screen, and the VID1 in the bottom right quadrant.
+ * So the default 'xres' and 'yres' are set to  half of the screen width and
+ * height respectively. Note however that the framebuffer size is allocated
+ * for the full screen size so the user can change the 'xres' and 'yres' by
+ * using the FBIOPUT_VSCREENINFO ioctl within the limits of the screen size.
+ */
+#define round_32(width)	((((width) + 31) / 32) * 32 )
+
+#define OSD0_XRES	round_32((DISP_XRES)*16/8) * 8/16	/* pixels */
+#define OSD0_YRES	DISP_YRES
+#define OSD0_FB_PHY	0
+#define OSD0_FB_SIZE	(round_32((DISP_XRES)*16/8) * DISP_MEMY * DOUBLE_BUF)
+
+			/* 16 bpp, Double buffered */
+static struct fb_var_screeninfo osd0_default_var = {
+	.xres = OSD0_XRES,
+	.yres = OSD0_YRES,
+	.xres_virtual = OSD0_XRES,
+	.yres_virtual = OSD0_YRES * DOUBLE_BUF,
+	.xoffset = 0,
+	.yoffset = 0,
+	.bits_per_pixel = 16,
+	.grayscale = 0,
+	.red = {11, 5, 0},
+	.green = {5, 6, 0},
+	.blue = {0, 5, 0},
+	.transp = {0, 0, 0},
+	.nonstd = 0,
+	.activate = FB_ACTIVATE_NOW,
+	.height = -1,
+	.width = -1,
+	.accel_flags = 0,
+	.pixclock = LCD_PANEL_CLOCK,	/* picoseconds */
+	.left_margin = 40,	/* pixclocks */
+	.right_margin = 4,	/* pixclocks */
+	.upper_margin = 8,	/* line clocks */
+	.lower_margin = 2,	/* line clocks */
+	.hsync_len = 4,		/* pixclocks */
+	.vsync_len = 2,		/* line clocks */
+	.sync = 0,
+	.vmode = FB_VMODE_INTERLACED,
+};
+
+/* Using the full screen for OSD1 by default */
+#define OSD1_XRES	round_32(DISP_XRES*4/8) * 8/4	/* pixels */
+#define OSD1_YRES	DISP_YRES
+#define OSD1_FB_PHY	0
+#define OSD1_FB_SIZE	(round_32(DISP_XRES*4/8) * DISP_MEMY * DOUBLE_BUF)
+
+static struct fb_var_screeninfo osd1_default_var = {
+	.xres = DISP_XRES,
+	.yres = OSD1_YRES,
+	.xres_virtual = OSD1_XRES,
+	.yres_virtual = OSD1_YRES * DOUBLE_BUF,
+	.xoffset = 0,
+	.yoffset = 0,
+	.bits_per_pixel = 4,
+	.activate = FB_ACTIVATE_NOW,
+	.accel_flags = 0,
+	.pixclock = LCD_PANEL_CLOCK,	/* picoseconds */
+	.vmode = FB_VMODE_INTERLACED,
+};
+
+/* Using the full screen for OSD0 by default */
+#define VID0_XRES	round_32(DISP_XRES*16/8) * 8/16	/* pixels */
+#define VID0_YRES	DISP_YRES
+#define VID0_FB_PHY	0
+#define VID0_FB_SIZE	(round_32(DISP_XRES*16/8) * DISP_MEMY * TRIPLE_BUF)
+static struct fb_var_screeninfo vid0_default_var = {
+	.xres = VID0_XRES,
+	.yres = VID0_YRES,
+	.xres_virtual = VID0_XRES,
+	.yres_virtual = VID0_YRES * TRIPLE_BUF,
+	.xoffset = 0,
+	.yoffset = 0,
+	.bits_per_pixel = 16,
+	.activate = FB_ACTIVATE_NOW,
+	.accel_flags = 0,
+	.pixclock = LCD_PANEL_CLOCK,	/* picoseconds */
+	.vmode = FB_VMODE_INTERLACED,
+};
+
+/* Using the bottom right quadrant of the screen screen for VID1 by default,
+ * but keeping the framebuffer allocated for the full screen, so the user can
+ * change the 'xres' and 'yres' later using the FBIOPUT_VSCREENINFO ioctl.
+ */
+#define VID1_BPP	16	/* Video1 can be in YUV or RGB888 format */
+#define VID1_XRES round_32(DISP_XRES*16/8) * 8/16	/* pixels */
+#define VID1_YRES DISP_YRES
+#define VID1_FB_PHY	0
+#define VID1_FB_SIZE (round_32(DISP_XRES*16/8) * DISP_MEMY * TRIPLE_BUF)
+static struct fb_var_screeninfo vid1_default_var = {
+	.xres = VID1_XRES,
+	.yres = VID1_YRES,
+	.xres_virtual = VID1_XRES,
+	.yres_virtual = VID1_YRES * TRIPLE_BUF,
+	.xoffset = 0,
+	.yoffset = 0,
+	.bits_per_pixel = VID1_BPP,
+	.activate = FB_ACTIVATE_NOW,
+	.accel_flags = 0,
+	.pixclock = LCD_PANEL_CLOCK,	/* picoseconds */
+	.vmode = FB_VMODE_INTERLACED,
+};
+
+#define	x_pos(w)	((w)->x)
+#define	y_pos(w)	((w)->y)
+
+static struct dmparams_t {
+	u8 output;
+	u8 format;
+	u8 windows;		/* bitmap flag based on VID0, VID1, OSD0, OSD1
+				 * definitions in header file */
+	u32 vid0_xres;
+	u32 vid0_yres;
+	u32 vid0_xpos;
+	u32 vid0_ypos;
+
+	u32 vid1_xres;
+	u32 vid1_yres;
+	u32 vid1_xpos;
+	u32 vid1_ypos;
+
+	u32 osd0_xres;
+	u32 osd0_yres;
+	u32 osd0_xpos;
+	u32 osd0_ypos;
+
+	u32 osd1_xres;
+	u32 osd1_yres;
+	u32 osd1_xpos;
+	u32 osd1_ypos;
+} dmparams = {
+	NTSC,		/* output */
+	    COMPOSITE,		/* format */
+	    (1 << VID0) | (1 << VID1) | (1 << OSD0) | (1 << OSD1),
+	    /* windows registered */
+	    720, 480, 0, 0,	/* vid0 size and position */
+	    720, 480, 0, 0,	/* vid1 size and position */
+	    720, 480, 0, 0,	/* osd0 size and position */
+	    720, 480, 0, 0,	/* osd1 size and position */
+};
+
+/* Must do checks against the limits of the output device */
+static int davincifb_venc_check_mode(const struct dm_win_info *w,
+				     const struct fb_var_screeninfo *var)
+{
+	return 0;
+}
+
+static void set_sdram_params(char *id, u32 addr, u32 line_length);
+static irqreturn_t davincifb_isr(int irq, void *arg)
+{
+	struct dm_info *dm = (struct dm_info *)arg;
+	unsigned long addr=0;
+
+	if ((dispc_reg_in(VENC_VSTAT) & 0x00000010) == 0x10) {
+		xchg(&addr, dm->osd0->sdram_address);
+		if (addr) {
+			set_sdram_params(dm->osd0->info.fix.id,
+					 dm->osd0->sdram_address,
+					 dm->osd0->info.fix.line_length);
+			dm->osd0->sdram_address = 0;
+		}
+		addr = 0;
+		xchg(&addr, dm->osd1->sdram_address);
+		if (addr) {
+			set_sdram_params(dm->osd1->info.fix.id,
+					 dm->osd1->sdram_address,
+					 dm->osd1->info.fix.line_length);
+			dm->osd1->sdram_address = 0;
+		}
+		addr = 0;
+		xchg(&addr, dm->vid0->sdram_address);
+		if (addr) {
+			set_sdram_params(dm->vid0->info.fix.id,
+					 dm->vid0->sdram_address,
+					 dm->vid0->info.fix.line_length);
+			dm->vid0->sdram_address = 0;
+		}
+		addr = 0;
+		xchg(&addr, dm->vid1->sdram_address);
+		if (addr) {
+			set_sdram_params(dm->vid1->info.fix.id,
+					 dm->vid1->sdram_address,
+					 dm->vid1->info.fix.line_length);
+			dm->vid1->sdram_address = 0;
+		}
+		return IRQ_HANDLED;
+	} else {
+		++dm->vsync_cnt;
+		wake_up_interruptible(&dm->vsync_wait);
+		return IRQ_HANDLED;
+  	}
+
+	return IRQ_HANDLED;
+}
+
+/* Wait for a vsync interrupt.  This routine sleeps so it can only be called
+ * from process context.
+ */
+static int davincifb_wait_for_vsync(struct dm_win_info *w)
+{
+	struct dm_info *dm = w->dm;
+	wait_queue_t wq;
+	unsigned long cnt;
+	int ret;
+
+	init_waitqueue_entry(&wq, current);
+
+	cnt = dm->vsync_cnt;
+	ret = wait_event_interruptible_timeout(dm->vsync_wait,
+					       cnt != dm->vsync_cnt,
+					       dm->timeout);
+	if (ret < 0)
+		return (ret);
+	if (ret == 0)
+		return (-ETIMEDOUT);
+
+	return (0);
+}
+
+/* Sets a uniform attribute value over a rectangular area on the attribute
+ * window. The attribute value (0 to 7) is passed through the fb_fillrect's
+ * color parameter.
+ */
+static int davincifb_set_attr_blend(struct fb_fillrect *r)
+{
+	struct fb_info *info = &dm->osd1->info;
+	struct fb_var_screeninfo *var = &dm->osd1->info.var;
+	unsigned long start = 0;
+	u8 blend;
+	u32 width_bytes;
+
+	if (r->dx + r->width > var->xres_virtual)
+		return -EINVAL;
+	if (r->dy + r->height > var->yres_virtual)
+		return -EINVAL;
+	if (r->color < 0 || r->color > 7)
+		return -EINVAL;
+
+	/* since bits_per_pixel = 4, this will truncate the width if it is
+	 * not even. Similarly r->dx will be rounded down to an even pixel.
+	 * ... Do we want to return an error otherwise?
+	 */
+	width_bytes = r->width * var->bits_per_pixel / 8;
+	start = dm->osd1->fb_base + r->dy * info->fix.line_length
+	    + r->dx * var->bits_per_pixel / 8;
+
+	blend = (((u8) r->color & 0xf) << 4) | ((u8) r->color);
+	while (r->height--) {
+		start += info->fix.line_length;
+		memset((void *)start, blend, width_bytes);
+	}
+
+	return 0;
+}
+
+/* These position parameters are given through fb_var_screeninfo.
+ * xp = var.reserved[0], yp = var.reserved[1],
+ * xl = var.xres, yl = var.yres
+ */
+static void set_win_position(char *id, u32 xp, u32 yp, u32 xl, u32 yl)
+{
+	int i = 0;
+
+	if (is_win(id, VID0)) {
+		i = 0;
+	} else if (is_win(id, VID1)) {
+		i = 1;
+	} else if (is_win(id, OSD0)) {
+		i = 2;
+	} else if (is_win(id, OSD1)) {
+		i = 3;
+	}
+
+	dispc_reg_out(OSD_WINXP(i), xp);
+	dispc_reg_out(OSD_WINYP(i), yp);
+	dispc_reg_out(OSD_WINXL(i), xl);
+	dispc_reg_out(OSD_WINYL(i), yl);
+}
+
+static inline void get_win_position(struct dm_win_info *w,
+				    u32 * xp, u32 * yp, u32 * xl, u32 * yl)
+{
+	struct fb_var_screeninfo *v = &w->info.var;
+
+	*xp = x_pos(w);
+	*yp = y_pos(w);
+	*xl = v->xres;
+	*yl = v->yres;
+}
+
+/* Returns 1 if the windows overlap, 0 otherwise */
+static int window_overlap(struct dm_win_info *w, u32 xp, u32 yp, u32 xl, u32 yl)
+{
+	u32 _xp = 0, _yp = 0, _xl = 0, _yl = 0;
+
+#define OVERLAP(x1, y1, x2, y2, x3, y3, x4, y4)		\
+(!(	((x1)<(x3) && (x2)<(x3)) || ((x1)>(x4) && (x2)>(x4)) ||	\
+	((y1)<(y3) && (y2)<(y3)) || ((y1)>(y4) && (y2)>(y4)) )	\
+)
+
+	if (!w)
+		return (0);
+
+	get_win_position(w, &_xp, &_yp, &_xl, &_yl);
+
+	return (OVERLAP(xp, yp, xp + xl, yp + yl,
+		       _xp, _yp, _xp + _xl, _yp + _yl));
+#undef OVERLAP
+}
+
+/* Returns 1 if the window parameters are within VID0, 0 otherwise */
+static int within_vid0_limits(u32 xp, u32 yp, u32 xl, u32 yl)
+{
+	u32 vid0_xp = 0, vid0_yp = 0, vid0_xl = 0, vid0_yl = 0;
+
+	if (!dm->vid0)
+		return (1);
+	get_win_position(dm->vid0, &vid0_xp, &vid0_yp, &vid0_xl, &vid0_yl);
+	if ((xp >= vid0_xp) && (yp >= vid0_yp) &&
+	    (xp + xl <= vid0_xp + vid0_xl) && (yp + yl <= vid0_yp + vid0_yl))
+		return (1);
+	return (0);
+}
+
+/* VID0 must be large enough to hold all other windows */
+static int check_new_vid0_size(u32 xp0, u32 yp0, u32 xl0, u32 yl0)
+{
+	u32 _xp = 0, _yp = 0, _xl = 0, _yl = 0;
+#define WITHIN_LIMITS 				\
+	((_xp >= xp0) && (_yp >= yp0) &&	\
+	(_xp + _xl <= xp0 + xl0) && (_yp + _yl <= yp0 + yl0))
+
+	if (dm->osd0) {
+		get_win_position(dm->osd0, &_xp, &_yp, &_xl, &_yl);
+		if (!WITHIN_LIMITS)
+			return (-EINVAL);
+	}
+	if (dm->osd1) {
+		get_win_position(dm->osd1, &_xp, &_yp, &_xl, &_yl);
+		if (!WITHIN_LIMITS)
+			return (-EINVAL);
+	}
+	if (dm->vid1) {
+		get_win_position(dm->vid1, &_xp, &_yp, &_xl, &_yl);
+		if (!WITHIN_LIMITS)
+			return (-EINVAL);
+	}
+	return (0);
+
+#undef WITHIN_LIMITS
+}
+
+/**
+ *      davincifb_check_var - Validates a var passed in.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Checks to see if the hardware supports the state requested by
+ *	var passed in. This function does not alter the hardware state!!!
+ *	This means the data stored in struct fb_info and struct xxx_par do
+ *      not change. This includes the var inside of struct fb_info.
+ *	Do NOT change these. This function can be called on its own if we
+ *	intent to only test a mode and not actually set it.
+ *	If the var passed in is slightly off by what the hardware can support
+ *	then we alter the var PASSED in to what we can do.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int davincifb_check_var(struct fb_var_screeninfo *var,
+			       struct fb_info *info)
+{
+	const struct dm_win_info *w = (const struct dm_win_info *)info->par;
+	struct fb_var_screeninfo v;
+
+/* Rules:
+ * 1) Vid1, OSD0, OSD1 and Cursor must be fully contained inside of Vid0.
+ * 2) Vid0 and Vid1 are both set to accept YUV 4:2:2 (for now).
+ * 3) OSD window data is always packed into 32-bit words and left justified.
+ * 4) Each horizontal line of window data must be a multiple of 32 bytes.
+ *    32 bytes = 32 bytes / 2 bytes per pixel = 16 pixels.
+ *    This implies that 'xres' must be a multiple of 32 bytes.
+ * 5) The offset registers hold the distance between the start of one line and
+ *    the start of the next. This offset value must be a multiple of 32 bytes.
+ *    This implies that 'xres_virtual' is also a multiple of 32 bytes. Note
+ *    that 'xoffset' needn't be a multiple of 32 bytes.
+ * 6) OSD0 is set to accept RGB565.
+ * 	dispc_reg_merge(OSD_OSDWIN0ND, OSD_OSDWIN0ND_RGB0E, OSD_OSDWIN0ND_RGB0E)
+ * 7) OSD1 is set to be the attribute window.
+ * 8) Vid1 startX = Vid0 startX + N * 16 pixels (32 bytes)
+ * 9) Vid1 width = (16*N - 8) pixels
+ * 10) When one of the OSD windows is in RGB565, it cannot overlap with Vid1.
+ * 11) Vid1 start X position must be offset a multiple of 16 pixels from the
+ * left edge of Vid0.
+ */
+
+	memcpy(&v, var, sizeof(v));
+	return (0);
+
+	/* do board-specific checks on the var */
+	if (davincifb_venc_check_mode(w, &v))
+		return (-EINVAL);
+
+	if (v.xres_virtual < v.xres || v.yres_virtual < v.yres)
+		return (-EINVAL);
+	if (v.xoffset > v.xres_virtual - v.xres)
+		return (-EINVAL);
+	if (v.yoffset > v.yres_virtual - v.yres)
+		return (-EINVAL);
+	if ((v.xres * v.bits_per_pixel / 8) % 32 || (v.xres_virtual * v.bits_per_pixel / 8) % 32)	/* Rules 4, 5 */
+		return (-EINVAL);
+	if (v.xres_virtual * v.yres_virtual * v.bits_per_pixel / 8 > w->fb_size)
+		return (-EINVAL);
+
+	if (!is_win(info->fix.id, VID0)) {
+		/* Rule 1 */
+		if (!within_vid0_limits(x_pos(w), y_pos(w), v.xres, v.yres))
+			return (-EINVAL);
+	}
+	if (is_win(info->fix.id, OSD0)) {
+		/* Rule 10 */
+		if (window_overlap(w->dm->vid1,
+				   x_pos(w), y_pos(w), v.xres, v.yres))
+			return (-EINVAL);
+		/* Rule 5 */
+		v.bits_per_pixel = 16;
+		v.red.offset = 11;
+		v.green.offset = 5;
+		v.blue.offset = 0;
+		v.red.length = 5;
+		v.green.length = 6;
+		v.blue.length = 5;
+		v.transp.offset = v.transp.length = 0;
+		v.red.msb_right = v.green.msb_right = v.blue.msb_right
+		    = v.transp.msb_right = 0;
+		v.nonstd = 0;
+		v.accel_flags = 0;
+	} else if (is_win(info->fix.id, OSD1)) {
+		v.bits_per_pixel = 4;
+	} else if (is_win(info->fix.id, VID0)) {
+		if (check_new_vid0_size(x_pos(w), y_pos(w), v.xres, v.yres))
+			return (-EINVAL);
+		v.bits_per_pixel = 16;
+	} else if (is_win(info->fix.id, VID1)) {
+		/* Rule 11 */
+		if ((x_pos(w->dm->vid0) - x_pos(w)) % 16)
+			return (-EINVAL);
+		/* Video1 may be in YUV or RGB888 format */
+		if ((v.bits_per_pixel != 16) && (v.bits_per_pixel != 32))
+			return (-EINVAL);
+	} else
+		return (-EINVAL);
+
+	memcpy(var, &v, sizeof(v));
+	return (0);
+}
+
+/* Interlaced = Frame mode, Non-interlaced = Field mode */
+static void set_interlaced(char *id, unsigned int on)
+{
+	on = (on == 0) ? 0 : ~0;
+
+	if (is_win(id, VID0))
+		dispc_reg_merge(OSD_VIDWINMD, on, OSD_VIDWINMD_VFF0);
+	else if (is_win(id, VID1))
+		dispc_reg_merge(OSD_VIDWINMD, on, OSD_VIDWINMD_VFF1);
+	else if (is_win(id, OSD0))
+		dispc_reg_merge(OSD_OSDWIN0MD, on, OSD_OSDWIN0MD_OFF0);
+	else if (is_win(id, OSD1))
+		dispc_reg_merge(OSD_OSDWIN1MD, on, OSD_OSDWIN1MD_OFF1);
+}
+
+/* For zooming, we just have to set the start of framebuffer, the zoom factors
+ * and the display size. The hardware will then read only
+ * (display size / zoom factor) area of the framebuffer and  zoom and
+ * display it. In the following function, we assume that the start of
+ * framebuffer and the display size parameters are set already.
+ */
+static void set_zoom(int WinID, int h_factor, int v_factor)
+{
+	switch (WinID) {
+	case 0:		//VID0
+		dispc_reg_merge(OSD_VIDWINMD,
+				h_factor << OSD_VIDWINMD_VHZ0_SHIFT,
+				OSD_VIDWINMD_VHZ0);
+		dispc_reg_merge(OSD_VIDWINMD,
+				v_factor << OSD_VIDWINMD_VVZ0_SHIFT,
+				OSD_VIDWINMD_VVZ0);
+		break;
+	case 1:		//VID1
+		dispc_reg_merge(OSD_VIDWINMD,
+				h_factor << OSD_VIDWINMD_VHZ1_SHIFT,
+				OSD_VIDWINMD_VHZ1);
+		dispc_reg_merge(OSD_VIDWINMD,
+				v_factor << OSD_VIDWINMD_VVZ1_SHIFT,
+				OSD_VIDWINMD_VVZ1);
+		break;
+	case 2:		//OSD0
+		dispc_reg_merge(OSD_OSDWIN0MD,
+				h_factor << OSD_OSDWIN0MD_OHZ0_SHIFT,
+				OSD_OSDWIN0MD_OHZ0);
+		dispc_reg_merge(OSD_OSDWIN0MD,
+				v_factor << OSD_OSDWIN0MD_OVZ0_SHIFT,
+				OSD_OSDWIN0MD_OVZ0);
+		break;
+	case 3:
+		dispc_reg_merge(OSD_OSDWIN1MD,
+				h_factor << OSD_OSDWIN1MD_OHZ1_SHIFT,
+				OSD_OSDWIN1MD_OHZ1);
+		dispc_reg_merge(OSD_OSDWIN1MD,
+				v_factor << OSD_OSDWIN1MD_OVZ1_SHIFT,
+				OSD_OSDWIN1MD_OVZ1);
+		break;
+	}
+}
+
+/* Chooses the ROM CLUT for now. Can be extended later. */
+static void set_bg_color(u8 clut, u8 color_offset)
+{
+	clut = 0;		/* 0 = ROM, 1 = RAM */
+
+	dispc_reg_merge(OSD_MODE, OSD_MODE_BCLUT & clut, OSD_MODE_BCLUT);
+	dispc_reg_merge(OSD_MODE, color_offset << OSD_MODE_CABG_SHIFT,
+			OSD_MODE_CABG);
+}
+
+static void set_sdram_params(char *id, u32 addr, u32 line_length)
+{
+	/* The parameters to be written to the registers should be in
+	 * multiple of 32 bytes
+	 */
+	addr = addr;		/* div by 32 */
+	line_length = line_length / 32;
+
+	if (is_win(id, VID0)) {
+		dispc_reg_out(OSD_VIDWIN0ADR, addr);
+		dispc_reg_out(OSD_VIDWIN0OFST, line_length);
+	} else if (is_win(id, VID1)) {
+		dispc_reg_out(OSD_VIDWIN1ADR, addr);
+		dispc_reg_out(OSD_VIDWIN1OFST, line_length);
+	} else if (is_win(id, OSD0)) {
+		dispc_reg_out(OSD_OSDWIN0ADR, addr);
+		dispc_reg_out(OSD_OSDWIN0OFST, line_length);
+	} else if (is_win(id, OSD1)) {
+		dispc_reg_out(OSD_OSDWIN1ADR, addr);
+		dispc_reg_out(OSD_OSDWIN1OFST, line_length);
+	}
+}
+
+static void set_win_enable(char *id, unsigned int on)
+{
+	on = (on == 0) ? 0 : ~0;
+
+	if (is_win(id, VID0))
+		/* Turning off VID0 use due to field inversion issue */
+		dispc_reg_merge(OSD_VIDWINMD, 0, OSD_VIDWINMD_ACT0);
+	else if (is_win(id, VID1))
+		dispc_reg_merge(OSD_VIDWINMD, on, OSD_VIDWINMD_ACT1);
+	else if (is_win(id, OSD0))
+		dispc_reg_merge(OSD_OSDWIN0MD, on, OSD_OSDWIN0MD_OACT0);
+	else if (is_win(id, OSD1)) {
+		/* The OACT1 bit is applicable only if OSD1 is not used as
+		 * the attribute window
+		 */
+		if (!(dispc_reg_in(OSD_OSDWIN1MD) & OSD_OSDWIN1MD_OASW))
+			dispc_reg_merge(OSD_OSDWIN1MD, on, OSD_OSDWIN1MD_OACT1);
+	}
+}
+
+static void set_win_mode(char *id)
+{
+	if (is_win(id, VID0)) ;
+	else if (is_win(id, VID1)) {
+		if (dm->vid1->info.var.bits_per_pixel == 32)
+			dispc_reg_merge(OSD_MISCCT, ~0,
+					OSD_MISCCT_RGBWIN | OSD_MISCCT_RGBEN);
+	} else if (is_win(id, OSD0))
+		/* Set RGB565 mode */
+		dispc_reg_merge(OSD_OSDWIN0MD, OSD_OSDWIN0MD_RGB0E,
+				OSD_OSDWIN0MD_RGB0E);
+	else if (is_win(id, OSD1)) {
+		/* Set as attribute window */
+		dispc_reg_merge(OSD_OSDWIN1MD, OSD_OSDWIN1MD_OASW,
+				OSD_OSDWIN1MD_OASW);
+	}
+
+}
+
+/**
+ *      davincifb_set_par - Optional function. Alters the hardware state.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Using the fb_var_screeninfo in fb_info we set the resolution of the
+ *	this particular framebuffer. This function alters the par AND the
+ *	fb_fix_screeninfo stored in fb_info. It doesn't not alter var in
+ *	fb_info since we are using that data. This means we depend on the
+ *	data in var inside fb_info to be supported by the hardware.
+ *	davincifb_check_var is always called before dmfb_set_par to ensure this.
+ *	Again if you can't can't the resolution you don't need this function.
+ *
+ */
+static int davincifb_set_par(struct fb_info *info)
+{
+	struct dm_win_info *w = (struct dm_win_info *)info->par;
+	struct fb_var_screeninfo *v = &info->var;
+	u32 start = 0, offset = 0;
+
+	info->fix.line_length = v->xres_virtual * v->bits_per_pixel / 8;
+
+	offset = v->yoffset * info->fix.line_length +
+	    v->xoffset * v->bits_per_pixel / 8;
+	start = (u32) w->fb_base_phys + offset;
+	set_sdram_params(info->fix.id, start, info->fix.line_length);
+
+	set_interlaced(info->fix.id, 1);
+	set_win_position(info->fix.id,
+			 x_pos(w), y_pos(w), v->xres, v->yres / 2);
+	set_win_mode(info->fix.id);
+	set_win_enable(info->fix.id, 1);
+
+	return (0);
+}
+
+/**
+ *	davincifb_ioctl - handler for private ioctls.
+ */
+static int davincifb_ioctl(struct fb_info *info, unsigned int cmd,
+			   unsigned long arg)
+{
+	struct dm_win_info *w = (struct dm_win_info *)info->par;
+	void __user *argp = (void __user *)arg;
+	struct fb_fillrect rect;
+	struct zoom_params zoom;
+	long std = 0;
+
+	switch (cmd) {
+	case FBIO_WAITFORVSYNC:
+		/* This ioctl accepts an integer argument to specify a
+		 * display.  We only support one display, so we will
+		 * simply ignore the argument.
+		 */
+		return (davincifb_wait_for_vsync(w));
+		break;
+	case FBIO_SETATTRIBUTE:
+		if (copy_from_user(&rect, argp, sizeof(rect)))
+			return -EFAULT;
+		return (davincifb_set_attr_blend(&rect));
+		break;
+	case FBIO_SETPOSX:
+		if (arg >= 0 && arg <= DISP_XRES) {
+			w->x = arg;
+			davincifb_check_var(&w->info.var, &w->info);
+			davincifb_set_par(&w->info);
+			return 0;
+		} else
+			return -EINVAL;
+		break;
+	case FBIO_SETPOSY:
+		if (arg >= 0 && arg <= DISP_YRES) {
+			w->y = arg;
+			davincifb_check_var(&w->info.var, &w->info);
+			davincifb_set_par(&w->info);
+			return 0;
+		} else
+			return -EINVAL;
+		break;
+	case FBIO_SETZOOM:
+		if (copy_from_user(&zoom, argp, sizeof(zoom)))
+			return -EFAULT;
+		if ((zoom.zoom_h == 2) || (zoom.zoom_h == 0)
+		    || (zoom.zoom_h == 1) || (zoom.zoom_v == 2)
+		    || (zoom.zoom_v == 0) || (zoom.zoom_v == 1)) {
+			set_zoom(zoom.window_id, zoom.zoom_h, zoom.zoom_v);
+			return 0;
+		} else {
+			return -EINVAL;
+		}
+		break;
+	case FBIO_GETSTD:
+		std = ((dmparams.output << 16) | (dmparams.format));	//(NTSC <<16) | (COPOSITE);
+		if (copy_to_user(argp, &std, sizeof(u_int32_t)))
+			return -EFAULT;
+		return 0;
+		break;
+	}
+	return (-EINVAL);
+}
+
+/**
+ *  	davincifb_setcolreg - Optional function. Sets a color register.
+ *      @regno: Which register in the CLUT we are programming
+ *      @red: The red value which can be up to 16 bits wide
+ *	@green: The green value which can be up to 16 bits wide
+ *	@blue:  The blue value which can be up to 16 bits wide.
+ *	@transp: If supported the alpha value which can be up to 16 bits wide.
+ *      @info: frame buffer info structure
+ *
+ *  	Set a single color register. The values supplied have a 16 bit
+ *  	magnitude which needs to be scaled in this function for the hardware.
+ *	Things to take into consideration are how many color registers, if
+ *	any, are supported with the current color visual. With truecolor mode
+ *	no color palettes are supported. Here a psuedo palette is created
+ *	which we store the value in pseudo_palette in struct fb_info. For
+ *	pseudocolor mode we have a limited color palette. To deal with this
+ *	we can program what color is displayed for a particular pixel value.
+ *	DirectColor is similar in that we can program each color field. If
+ *	we have a static colormap we don't need to implement this function.
+ *
+ *	Returns negative errno on error, or zero on success.
+ */
+static int davincifb_setcolreg(unsigned regno, unsigned red, unsigned green,
+			       unsigned blue, unsigned transp,
+			       struct fb_info *info)
+{
+	/* only pseudo-palette (16 bpp) allowed */
+	if (regno >= 16)	/* maximum number of palette entries */
+		return (1);
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/* Truecolor has hardware-independent 16-entry pseudo-palette */
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+		u32 v;
+
+		if (regno >= 16)
+			return (1);
+
+		red >>= (16 - info->var.red.length);
+		green >>= (16 - info->var.green.length);
+		blue >>= (16 - info->var.blue.length);
+
+		v = (red << info->var.red.offset) |
+		    (green << info->var.green.offset) |
+		    (blue << info->var.blue.offset);
+
+		switch (info->var.bits_per_pixel) {
+		case 16:
+			((u16 *) (info->pseudo_palette))[regno] = v;
+			break;
+		default:
+			return (1);
+		}
+		return (0);
+	}
+	return (0);
+}
+
+/**
+ *      davincifb_pan_display - NOT a required function. Pans the display.
+ *      @var: frame buffer variable screen structure
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *	Pan (or wrap, depending on the `vmode' field) the display using the
+ *  	`xoffset' and `yoffset' fields of the `var' structure.
+ *  	If the values don't fit, return -EINVAL.
+ *
+ *      Returns negative errno on error, or zero on success.
+ */
+static int davincifb_pan_display(struct fb_var_screeninfo *var,
+				 struct fb_info *info)
+{
+	struct dm_win_info *w = (struct dm_win_info *)info->par;
+	u32 start = 0, offset = 0;
+
+	if (var->xoffset > var->xres_virtual - var->xres)
+		return (-EINVAL);
+	if (var->yoffset > var->yres_virtual - var->yres)
+		return (-EINVAL);
+	if ((var->xres_virtual * var->bits_per_pixel / 8) % 32)
+		return (-EINVAL);
+
+	offset = var->yoffset * info->fix.line_length +
+	    var->xoffset * var->bits_per_pixel / 8;
+	start = (u32) w->fb_base_phys + offset;
+
+	if ((dispc_reg_in(VENC_VSTAT) & 0x00000010)==0x10)
+		set_sdram_params(info->fix.id, start, info->fix.line_length);
+	else
+		w->sdram_address = start;
+
+	return (0);
+}
+
+/**
+ *      davincifb_blank - NOT a required function. Blanks the display.
+ *      @blank_mode: the blank mode we want.
+ *      @info: frame buffer structure that represents a single frame buffer
+ *
+ *      Blank the screen if blank_mode != 0, else unblank. Return 0 if
+ *      blanking succeeded, != 0 if un-/blanking failed due to e.g. a
+ *      video mode which doesn't support it. Implements VESA suspend
+ *      and powerdown modes on hardware that supports disabling hsync/vsync:
+ *      blank_mode == 2: suspend vsync
+ *      blank_mode == 3: suspend hsync
+ *      blank_mode == 4: powerdown
+ *
+ *      Returns negative errno on error, or zero on success.
+ *
+ */
+static int davincifb_blank(int blank_mode, struct fb_info *info)
+{
+	return 0;
+}
+
+static int parse_win_params(char *wp,
+			    int *xres, int *yres, int *xpos, int *ypos)
+{
+	char *s;
+
+	if ((s = strsep(&wp, "x")) == NULL)
+		return -EINVAL;
+	*xres = simple_strtoul(s, NULL, 0);
+
+	if ((s = strsep(&wp, "@")) == NULL)
+		return -EINVAL;
+	*yres = simple_strtoul(s, NULL, 0);
+
+	if ((s = strsep(&wp, ",")) == NULL)
+		return -EINVAL;
+	*xpos = simple_strtoul(s, NULL, 0);
+
+	if ((s = strsep(&wp, ":")) == NULL)
+		return -EINVAL;
+	*ypos = simple_strtoul(s, NULL, 0);
+
+	return 0;
+}
+
+/*
+ * Pass boot-time options by adding the following string to the boot params:
+ * 	video=davincifb:[option[:option]]
+ * Valid options:
+ * 	output=[lcd|ntsc|pal]
+ * 	format=[composite|s-video|component|rgb]
+ * 	vid0=[off|MxN@X,Y]
+ * 	vid1=[off|MxN@X,Y]
+ * 	osd0=[off|MxN@X,Y]
+ * 	osd1=[off|MxN@X,Y]
+ * 		MxN specify the window resolution (displayed size)
+ * 		X,Y specify the window position
+ * 		M, N, X, Y are integers
+ * 		M, X should be multiples of 16
+ */
+
+#ifndef MODULE
+int __init davincifb_setup(char *options)
+{
+	char *this_opt;
+	u32 xres, yres, xpos, ypos;
+	int format_yres = 480;
+
+	pr_debug("davincifb: Options \"%s\"\n", options);
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ":")) != NULL) {
+
+		if (!*this_opt)
+			continue;
+
+		if (!strncmp(this_opt, "output=", 7)) {
+			if (!strncmp(this_opt + 7, "lcd", 3)) {
+				dmparams.output = LCD;
+				dmparams.format = 0;
+			} else if (!strncmp(this_opt + 7, "ntsc", 4))
+				dmparams.output = NTSC;
+			else if (!strncmp(this_opt + 7, "pal", 3))
+				dmparams.output = PAL;
+		} else if (!strncmp(this_opt, "format=", 7)) {
+			if (dmparams.output == LCD)
+				continue;
+			if (!strncmp(this_opt + 7, "composite", 9))
+				dmparams.format = COMPOSITE;
+			else if (!strncmp(this_opt + 7, "s-video", 7))
+				dmparams.format = SVIDEO;
+			else if (!strncmp(this_opt + 7, "component", 9))
+				dmparams.format = COMPONENT;
+			else if (!strncmp(this_opt + 7, "rgb", 3))
+				dmparams.format = RGB;
+		} else if (!strncmp(this_opt, "vid0=", 5)) {
+			if (!strncmp(this_opt + 5, "off", 3))
+				dmparams.windows &= ~(1 << VID0);
+			else if (!parse_win_params(this_opt + 5,
+						   &xres, &yres, &xpos,
+						   &ypos)) {
+				dmparams.vid0_xres = xres;
+				dmparams.vid0_yres = yres;
+				dmparams.vid0_xpos = xpos;
+				dmparams.vid0_ypos = ypos;
+			}
+		} else if (!strncmp(this_opt, "vid1=", 5)) {
+			if (!strncmp(this_opt + 5, "off", 3))
+				dmparams.windows &= ~(1 << VID1);
+			else if (!parse_win_params(this_opt + 5,
+						   &xres, &yres, &xpos,
+						   &ypos)) {
+				dmparams.vid1_xres = xres;
+				dmparams.vid1_yres = yres;
+				dmparams.vid1_xpos = xpos;
+				dmparams.vid1_ypos = ypos;
+			}
+		} else if (!strncmp(this_opt, "osd0=", 5)) {
+			if (!strncmp(this_opt + 5, "off", 3))
+				dmparams.windows &= ~(1 << OSD0);
+			else if (!parse_win_params(this_opt + 5,
+						   &xres, &yres, &xpos,
+						   &ypos)) {
+				dmparams.osd0_xres = xres;
+				dmparams.osd0_yres = yres;
+				dmparams.osd0_xpos = xpos;
+				dmparams.osd0_ypos = ypos;
+			}
+		} else if (!strncmp(this_opt, "osd1=", 5)) {
+			if (!strncmp(this_opt + 5, "off", 3))
+				dmparams.windows &= ~(1 << OSD1);
+			else if (!parse_win_params(this_opt + 5,
+						   &xres, &yres, &xpos,
+						   &ypos)) {
+				dmparams.osd1_xres = xres;
+				dmparams.osd1_yres = yres;
+				dmparams.osd1_xpos = xpos;
+				dmparams.osd1_ypos = ypos;
+			}
+		}
+	}
+	printk(KERN_INFO "DaVinci: "
+	       "Output on %s%s, Enabled windows: %s %s %s %s\n",
+	       (dmparams.output == LCD) ? "LCD" :
+	       (dmparams.output == NTSC) ? "NTSC" :
+	       (dmparams.output == PAL) ? "PAL" : "unknown device!",
+	       (dmparams.format == 0) ? "" :
+	       (dmparams.format == COMPOSITE) ? " in COMPOSITE format" :
+	       (dmparams.format == SVIDEO) ? " in SVIDEO format" :
+	       (dmparams.format == COMPONENT) ? " in COMPONENT format" :
+	       (dmparams.format == RGB) ? " in RGB format" : "",
+	       (dmparams.windows & (1 << VID0)) ? "Video0" : "",
+	       (dmparams.windows & (1 << VID1)) ? "Video1" : "",
+	       (dmparams.windows & (1 << OSD0)) ? "OSD0" : "",
+	       (dmparams.windows & (1 << OSD1)) ? "OSD1" : "");
+	if (dmparams.output == NTSC) {
+		format_yres = 480;
+	} else if (dmparams.output == PAL) {
+		format_yres = 576;
+	} else {
+		printk(KERN_INFO
+		       "DaVinci:invalid format..defaulting width to 480\n");
+	}
+	dmparams.osd0_yres = osd0_default_var.yres = format_yres;
+	dmparams.osd1_yres = osd1_default_var.yres = format_yres;
+	dmparams.vid0_yres = vid0_default_var.yres = format_yres;
+	dmparams.vid1_yres = vid1_default_var.yres = format_yres;
+
+	osd0_default_var.yres_virtual = format_yres * DOUBLE_BUF;
+	osd1_default_var.yres_virtual = format_yres * DOUBLE_BUF;
+	vid0_default_var.yres_virtual = format_yres * TRIPLE_BUF;
+	vid1_default_var.yres_virtual = format_yres * TRIPLE_BUF;
+
+	if (dmparams.windows & (1 << VID0))
+		printk(KERN_INFO "Setting Video0 size %dx%d, "
+		       "position (%d,%d)\n",
+		       dmparams.vid0_xres, dmparams.vid0_yres,
+		       dmparams.vid0_xpos, dmparams.vid0_ypos);
+	if (dmparams.windows & (1 << VID1))
+		printk(KERN_INFO "Setting Video1 size %dx%d, "
+		       "position (%d,%d)\n",
+		       dmparams.vid1_xres, dmparams.vid1_yres,
+		       dmparams.vid1_xpos, dmparams.vid1_ypos);
+	if (dmparams.windows & (1 << OSD0))
+		printk(KERN_INFO "Setting OSD0 size %dx%d, "
+		       "position (%d,%d)\n",
+		       dmparams.osd0_xres, dmparams.osd0_yres,
+		       dmparams.osd0_xpos, dmparams.osd0_ypos);
+	if (dmparams.windows & (1 << OSD1))
+		printk(KERN_INFO "Setting OSD1 size %dx%d, "
+		       "position (%d,%d)\n",
+		       dmparams.osd1_xres, dmparams.osd1_yres,
+		       dmparams.osd1_xpos, dmparams.osd1_ypos);
+	return (0);
+}
+#endif
+
+static int mem_release(struct dm_win_info *w)
+{
+	if (!w->alloc_fb_mem) {
+		iounmap((void *)w->fb_base);
+		release_mem_region(w->fb_base_phys, w->fb_size);
+	} else
+		dma_free_coherent(NULL, w->fb_size, (void *)w->fb_base,
+				  w->fb_base_phys);
+	kfree(w);
+	return (0);
+}
+
+static int mem_alloc(struct dm_win_info **win, dma_addr_t fb_base_phys,
+		     unsigned long fb_size, char *fbname)
+{
+	struct dm_win_info *w;
+	struct device *dev = dm->dev;
+
+	w = kmalloc(sizeof(struct dm_win_info), GFP_KERNEL);
+	if (!w) {
+		dev_err(dev, "%s: could not allocate memory\n", fbname);
+		return (-ENOMEM);
+	}
+	memset(w, 0, sizeof(struct dm_win_info));
+
+	w->fb_base_phys = fb_base_phys;
+	w->fb_size = fb_size;
+
+	/* A null base address indicates that the framebuffer memory should be
+	 * dynamically allocated.
+	 */
+	if (!w->fb_base_phys)
+		w->alloc_fb_mem = 1;
+
+	if (!w->alloc_fb_mem) {
+		if (!request_mem_region(w->fb_base_phys, w->fb_size, fbname)) {
+			dev_err(dev, "%s: cannot reserve FB region\n", fbname);
+			goto free_par;
+		}
+		w->fb_base =
+		    (unsigned long)ioremap(w->fb_base_phys, w->fb_size);
+		if (!w->fb_base) {
+			dev_err(dev, "%s: cannot map framebuffer\n", fbname);
+			goto release_fb;
+		}
+	} else {
+		/* allocate coherent memory for the framebuffer */
+		w->fb_base = (unsigned long)dma_alloc_coherent(dev,
+							       w->fb_size,
+							       &w->fb_base_phys,
+							       GFP_KERNEL |
+							       GFP_DMA);
+		if (!w->fb_base) {
+			dev_err(dev, "%s: cannot allocate framebuffer\n",
+				fbname);
+			goto free_par;
+		}
+
+		dev_dbg(dev, "Framebuffer allocated at 0x%x "
+			"mapped to 0x%x, size %dk\n",
+			(unsigned)w->fb_base_phys, (unsigned)w->fb_base,
+			(unsigned)w->fb_size / 1024);
+	}
+
+	*win = w;
+	return (0);
+
+      release_fb:
+	if (!w->alloc_fb_mem)
+		release_mem_region(w->fb_base_phys, w->fb_size);
+      free_par:
+	kfree(w);
+	return (-ENOMEM);
+}
+
+static struct fb_info *init_fb_info(struct dm_win_info *w,
+				    struct fb_var_screeninfo *var, char *id)
+{
+	struct fb_info *info = &(w->info);
+	struct dm_info *dm = w->dm;
+
+	/* initialize the fb_info structure */
+	info->flags = FBINFO_DEFAULT;
+	info->fbops = &davincifb_ops;
+	info->screen_base = (char *)(w->fb_base);
+	info->pseudo_palette = w->pseudo_palette;
+	info->par = w;
+
+	/* Initialize variable screeninfo.
+	 * The variable screeninfo can be directly specified by the user
+	 * via an ioctl.
+	 */
+	memcpy(&info->var, var, sizeof(info->var));
+	info->var.activate = FB_ACTIVATE_NOW;
+
+	/* Initialize fixed screeninfo.
+	 * The fixed screeninfo cannot be directly specified by the user, but
+	 * it may change to reflect changes to the var info.
+	 */
+	strlcpy(info->fix.id, id, sizeof(info->fix.id));
+	info->fix.smem_start = w->fb_base_phys;
+	info->fix.line_length =
+	    (info->var.xres_virtual * info->var.bits_per_pixel) / 8;
+	info->fix.smem_len = w->fb_size;
+	info->fix.type = FB_TYPE_PACKED_PIXELS;
+	info->fix.visual = (info->var.bits_per_pixel <= 8) ?
+	    FB_VISUAL_PSEUDOCOLOR : FB_VISUAL_TRUECOLOR;
+	info->fix.xpanstep = 0;
+	info->fix.ypanstep = 1;
+	info->fix.ywrapstep = 0;
+	info->fix.type_aux = 0;
+	info->fix.mmio_start = dm->mmio_base_phys;
+	info->fix.mmio_len = dm->mmio_size;
+	info->fix.accel = FB_ACCEL_NONE;
+	w->sdram_address = 0;
+
+	return info;
+}
+
+static void davincifb_ntsc_composite_config(int on)
+{
+	if (on) {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+
+		/* Enable Composite output and start video encoder */
+		dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC));
+
+		/* Set REC656 Mode */
+		dispc_reg_out(VENC_YCCCTL, 0x1);
+
+		/* Enable output mode and NTSC  */
+		dispc_reg_out(VENC_VMOD, 0x1003);
+
+		/* Enable all DACs  */
+		dispc_reg_out(VENC_DACTST, 0);
+	} else {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+	}
+}
+
+static void davincifb_ntsc_svideo_config(int on)
+{
+	if (on) {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+
+		/* Enable Composite output and start video encoder */
+		dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC));
+
+		/* Set REC656 Mode */
+		dispc_reg_out(VENC_YCCCTL, 0x1);
+
+		/* Enable output mode and NTSC  */
+		dispc_reg_out(VENC_VMOD, 0x1003);
+
+		/* Enable S-Video Output; DAC B: S-Video Y, DAC C: S-Video C  */
+		dispc_reg_out(VENC_DACSEL, 0x210);
+
+		/* Enable all DACs  */
+		dispc_reg_out(VENC_DACTST, 0);
+	} else {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+	}
+}
+
+static void davincifb_ntsc_component_config(int on)
+{
+	if (on) {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+
+		/* Enable Composite output and start video encoder */
+		dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC));
+
+		/* Set REC656 Mode */
+		dispc_reg_out(VENC_YCCCTL, 0x1);
+
+		/* Enable output mode and NTSC  */
+		dispc_reg_out(VENC_VMOD, 0x1003);
+
+		/* Enable Component output; DAC A: Y, DAC B: Pb, DAC C: Pr  */
+		dispc_reg_out(VENC_DACSEL, 0x543);
+
+		/* Enable all DACs  */
+		dispc_reg_out(VENC_DACTST, 0);
+	} else {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+	}
+}
+
+static void davincifb_pal_composite_config(int on)
+{
+	if (on) {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+
+		/* Enable Composite output and start video encoder */
+		dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC));
+
+		/* Set REC656 Mode */
+		dispc_reg_out(VENC_YCCCTL, 0x1);
+
+		/* Enable output mode and PAL  */
+		dispc_reg_out(VENC_VMOD, 0x1043);
+
+		/* Enable all DACs  */
+		dispc_reg_out(VENC_DACTST, 0);
+	} else {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+	}
+}
+
+static void davincifb_pal_svideo_config(int on)
+{
+	if (on) {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+
+		/* Enable Composite output and start video encoder */
+		dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC));
+
+		/* Set REC656 Mode */
+		dispc_reg_out(VENC_YCCCTL, 0x1);
+
+		/* Enable output mode and PAL  */
+		dispc_reg_out(VENC_VMOD, 0x1043);
+
+		/* Enable S-Video Output; DAC B: S-Video Y, DAC C: S-Video C  */
+		dispc_reg_out(VENC_DACSEL, 0x210);
+
+		/* Enable all DACs  */
+		dispc_reg_out(VENC_DACTST, 0);
+	} else {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+	}
+}
+
+static void davincifb_pal_component_config(int on)
+{
+	if (on) {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+
+		/* Enable Composite output and start video encoder */
+		dispc_reg_out(VENC_VMOD, (VENC_VMOD_VIE | VENC_VMOD_VENC));
+
+		/* Set REC656 Mode */
+		dispc_reg_out(VENC_YCCCTL, 0x1);
+
+		/* Enable output mode and PAL  */
+		dispc_reg_out(VENC_VMOD, 0x1043);
+
+		/* Enable Component output; DAC A: Y, DAC B: Pb, DAC C: Pr  */
+		dispc_reg_out(VENC_DACSEL, 0x543);
+
+		/* Enable all DACs  */
+		dispc_reg_out(VENC_DACTST, 0);
+	} else {
+		/* Reset video encoder module */
+		dispc_reg_out(VENC_VMOD, 0);
+	}
+}
+
+static inline void fix_default_var(struct dm_win_info *w,
+				   u32 xres, u32 yres, u32 xpos, u32 ypos,
+				   int n_buf)
+{
+	struct fb_var_screeninfo *v = &w->info.var;
+
+	v->xres = xres;
+	v->yres = yres;
+	v->xres_virtual = v->xres;
+	v->yres_virtual = v->yres * n_buf;
+	x_pos(w) = xpos;
+	y_pos(w) = ypos;
+}
+
+/*
+ *  Cleanup
+ */
+static int davincifb_remove(struct platform_device *pdev)
+{
+	free_irq(IRQ_VENCINT, &dm);
+
+	/* Cleanup all framebuffers */
+	if (dm->osd0) {
+		unregister_framebuffer(&dm->osd0->info);
+		mem_release(dm->osd0);
+	}
+	if (dm->osd1) {
+		unregister_framebuffer(&dm->osd1->info);
+		mem_release(dm->osd1);
+	}
+	if (dm->vid0) {
+		unregister_framebuffer(&dm->vid0->info);
+		mem_release(dm->vid0);
+	}
+	if (dm->vid1) {
+		unregister_framebuffer(&dm->vid1->info);
+		mem_release(dm->vid1);
+	}
+
+	/* Turn OFF the output device */
+	dm->output_device_config(0);
+
+	if (dm->mmio_base)
+		iounmap((void *)dm->mmio_base);
+	release_mem_region(dm->mmio_base_phys, dm->mmio_size);
+
+	return 0;
+}
+
+/*
+ *  Initialization
+ */
+static int davincifb_probe(struct platform_device *pdev)
+{
+	struct fb_info *info;
+
+	if (dmparams.windows == 0)
+		return 0;	/* user disabled all windows through bootargs */
+	dm->dev = &pdev->dev;
+	dm->mmio_base_phys = OSD_REG_BASE;
+	dm->mmio_size = OSD_REG_SIZE;
+
+	if (!request_mem_region
+	    (dm->mmio_base_phys, dm->mmio_size, MODULE_NAME)) {
+		dev_err(dm->dev, ": cannot reserve MMIO region\n");
+		return (-ENODEV);
+	}
+
+	/* map the regions */
+	dm->mmio_base =
+	    (unsigned long)ioremap(dm->mmio_base_phys, dm->mmio_size);
+	if (!dm->mmio_base) {
+		dev_err(dm->dev, ": cannot map MMIO\n");
+		goto release_mmio;
+	}
+
+	/* initialize the vsync wait queue */
+	init_waitqueue_head(&dm->vsync_wait);
+	dm->timeout = HZ / 5;
+
+	if ((dmparams.output == NTSC) && (dmparams.format == COMPOSITE))
+		dm->output_device_config = davincifb_ntsc_composite_config;
+	else if ((dmparams.output == NTSC) && (dmparams.format == SVIDEO))
+		dm->output_device_config = davincifb_ntsc_svideo_config;
+	else if ((dmparams.output == NTSC) && (dmparams.format == COMPONENT))
+		dm->output_device_config = davincifb_ntsc_component_config;
+	else if ((dmparams.output == PAL) && (dmparams.format == COMPOSITE))
+		dm->output_device_config = davincifb_pal_composite_config;
+	else if ((dmparams.output == PAL) && (dmparams.format == SVIDEO))
+		dm->output_device_config = davincifb_pal_svideo_config;
+	else if ((dmparams.output == PAL) && (dmparams.format == COMPONENT))
+		dm->output_device_config = davincifb_pal_component_config;
+	/* Add support for other displays here */
+	else {
+		printk(KERN_WARNING "Unsupported output device!\n");
+		dm->output_device_config = NULL;
+	}
+
+	printk("Setting Up Clocks for DM420 OSD\n");
+
+	/* Initialize the VPSS Clock Control register */
+	dispc_reg_out(VPSS_CLKCTL, 0x18);
+
+	/* Set Base Pixel X and Base Pixel Y */
+	dispc_reg_out(OSD_BASEPX, BASEX);
+	dispc_reg_out(OSD_BASEPY, BASEY);
+
+	/* Reset OSD registers to default. */
+	dispc_reg_out(OSD_MODE, 0);
+	dispc_reg_out(OSD_OSDWIN0MD, 0);
+
+	/* Set blue background color */
+	set_bg_color(0, 162);
+
+	/* Field Inversion Workaround */
+	dispc_reg_out(OSD_MODE, 0x200);
+
+	/* Setup VID0 framebuffer */
+	if (!(dmparams.windows & (1 << VID0))) {
+		printk(KERN_WARNING "No video/osd windows will be enabled "
+		       "because Video0 is disabled\n");
+		return 0;	/* background will still be shown */
+	}
+	/* Setup VID0 framebuffer */
+	if (!mem_alloc(&dm->vid0, VID0_FB_PHY, VID0_FB_SIZE, VID0_FBNAME)) {
+		dm->vid0->dm = dm;
+		fix_default_var(dm->vid0,
+				dmparams.vid0_xres, dmparams.vid0_yres,
+				dmparams.vid0_xpos, dmparams.vid0_ypos,
+				TRIPLE_BUF);
+		info = init_fb_info(dm->vid0, &vid0_default_var, VID0_FBNAME);
+		if (davincifb_check_var(&info->var, info)) {
+			dev_err(dm->dev, ": invalid default video mode\n");
+			goto exit;
+		}
+		memset((void *)dm->vid0->fb_base, 0x88, dm->vid0->fb_size);
+	} else
+		goto exit;
+
+	/* Setup OSD0 framebuffer */
+	if ((dmparams.windows & (1 << OSD0)) &&
+	    (!mem_alloc(&dm->osd0, OSD0_FB_PHY, OSD0_FB_SIZE, OSD0_FBNAME))) {
+		dm->osd0->dm = dm;
+		fix_default_var(dm->osd0,
+				dmparams.osd0_xres, dmparams.osd0_yres,
+				dmparams.osd0_xpos, dmparams.osd0_ypos,
+				DOUBLE_BUF);
+		info = init_fb_info(dm->osd0, &osd0_default_var, OSD0_FBNAME);
+		if (davincifb_check_var(&info->var, info)) {
+			dev_err(dm->dev, ": invalid default video mode\n");
+			mem_release(dm->osd0);
+		} else
+			memset((void *)dm->osd0->fb_base, 0, dm->osd0->fb_size);
+	}
+
+	/* Setup OSD1 framebuffer */
+	if ((dmparams.windows & (1 << OSD1)) &&
+	    (!mem_alloc(&dm->osd1, OSD1_FB_PHY, OSD1_FB_SIZE, OSD1_FBNAME))) {
+		dm->osd1->dm = dm;
+		fix_default_var(dm->osd1,
+				dmparams.osd1_xres, dmparams.osd1_yres,
+				dmparams.osd1_xpos, dmparams.osd1_ypos,
+				DOUBLE_BUF);
+		info = init_fb_info(dm->osd1, &osd1_default_var, OSD1_FBNAME);
+		if (davincifb_check_var(&info->var, info)) {
+			dev_err(dm->dev, ": invalid default video mode\n");
+			mem_release(dm->osd1);
+		} else
+			/* Set blend factor to show OSD windows */
+			memset((void *)dm->osd1->fb_base, 0xff,
+			       dm->osd1->fb_size);
+	}
+
+	/* Setup VID1 framebuffer */
+	if ((dmparams.windows & (1 << VID1)) &&
+	    (!mem_alloc(&dm->vid1, VID1_FB_PHY, VID1_FB_SIZE, VID1_FBNAME))) {
+		dm->vid1->dm = dm;
+		fix_default_var(dm->vid1,
+				dmparams.vid1_xres, dmparams.vid1_yres,
+				dmparams.vid1_xpos, dmparams.vid1_ypos,
+				TRIPLE_BUF);
+		info = init_fb_info(dm->vid1, &vid1_default_var, VID1_FBNAME);
+		if (davincifb_check_var(&info->var, info)) {
+			dev_err(dm->dev,
+				VID1_FBNAME ": invalid default video mode\n");
+			mem_release(dm->vid1);
+		} else
+			memset((void *)dm->vid1->fb_base, 0x88,
+			       dm->vid1->fb_size);
+	}
+
+	/* Register OSD0 framebuffer */
+	if (dm->osd0) {
+		info = &dm->osd0->info;
+		if (register_framebuffer(info) < 0) {
+			dev_err(dm->dev, OSD0_FBNAME
+				"Unable to register OSD0 framebuffer\n");
+			mem_release(dm->osd0);
+		} else {
+			printk(KERN_INFO "fb%d: %s frame buffer device\n",
+			       info->node, info->fix.id);
+			davincifb_set_par(info);
+		}
+	}
+
+	/* Register VID0 framebuffer */
+	info = &dm->vid0->info;
+	if (register_framebuffer(info) < 0) {
+		dev_err(dm->dev,
+			VID0_FBNAME "Unable to register VID0 framebuffer\n");
+		goto exit;
+	} else {
+		printk(KERN_INFO "fb%d: %s frame buffer device\n",
+		       info->node, info->fix.id);
+		davincifb_set_par(info);
+	}
+
+	/* Register OSD1 framebuffer */
+	if (dm->osd1) {
+		info = &dm->osd1->info;
+		if (register_framebuffer(info) < 0) {
+			dev_err(dm->dev, OSD1_FBNAME
+				"Unable to register OSD1 framebuffer\n");
+			mem_release(dm->osd1);
+		} else {
+			printk(KERN_INFO "fb%d: %s frame buffer device\n",
+			       info->node, info->fix.id);
+			davincifb_set_par(info);
+		}
+	}
+
+	/* Register VID1 framebuffer */
+	if (dm->vid1) {
+		info = &dm->vid1->info;
+		if (register_framebuffer(info) < 0) {
+			mem_release(dm->vid1);
+			dev_err(dm->dev, VID1_FBNAME
+				"Unable to register VID1 framebuffer\n");
+			mem_release(dm->vid1);
+		} else {
+			printk(KERN_INFO "fb%d: %s frame buffer device\n",
+			       info->node, info->fix.id);
+			davincifb_set_par(info);
+		}
+	}
+
+	/* install our interrupt service routine */
+	if (request_irq(IRQ_VENCINT, davincifb_isr, IRQF_SHARED, MODULE_NAME,
+			dm)) {
+		dev_err(dm->dev, MODULE_NAME
+			": could not install interrupt service routine\n");
+		goto exit;
+	}
+
+	/* Turn ON the output device */
+	dm->output_device_config(1);
+
+	return (0);
+
+      exit:
+	davincifb_remove(pdev);
+	iounmap((void *)dm->mmio_base);
+      release_mmio:
+	release_mem_region(dm->mmio_base_phys, dm->mmio_size);
+	return (-ENODEV);
+}
+
+/* ------------------------------------------------------------------------- */
+
+    /*
+     *  Frame buffer operations
+     */
+static struct fb_ops davincifb_ops = {
+	.owner = THIS_MODULE,
+	.fb_check_var = davincifb_check_var,
+	.fb_set_par = davincifb_set_par,
+	.fb_setcolreg = davincifb_setcolreg,
+	.fb_blank = davincifb_blank,
+	.fb_pan_display = davincifb_pan_display,
+	.fb_fillrect = cfb_fillrect,
+	.fb_copyarea = cfb_copyarea,
+	.fb_imageblit = cfb_imageblit,
+	.fb_rotate = NULL,
+	.fb_sync = NULL,
+	.fb_ioctl = davincifb_ioctl,
+};
+
+static struct platform_driver davincifb_driver = {
+	.probe		= davincifb_probe,
+	.remove		= davincifb_remove,
+	.driver		= {
+		.name	= MODULE_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+/* Register both the driver and the device */
+int __init davincifb_init(void)
+{
+#ifndef MODULE
+	/* boot-line options */
+	/* handle options for "dm64xxfb" for backwards compatability */
+	char *option;
+	char *names[] = { "davincifb", "dm64xxfb" };
+	int i, num_names = 2, done = 0;
+
+	for (i = 0; i < num_names && !done; i++) {
+		if (fb_get_options(names[i], &option)) {
+			printk(MODULE_NAME
+			       ": Disabled on command-line.\n");
+			return -ENODEV;
+		} else if (option) {
+			davincifb_setup(option);
+				done = 1;
+		}
+	}
+#endif
+
+	/* Register the driver with LDM */
+	if (platform_driver_register(&davincifb_driver)) {
+		pr_debug("failed to register omapfb driver\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit davincifb_cleanup(void)
+{
+	platform_driver_unregister(&davincifb_driver);
+}
+
+module_init(davincifb_init);
+module_exit(davincifb_cleanup);
+
+MODULE_DESCRIPTION("Framebuffer driver for TI DaVinci");
+MODULE_AUTHOR("Texas Instruments");
+MODULE_LICENSE("GPL");
diff --git a/include/asm-arm/arch-davinci/aic23.h b/include/asm-arm/arch-davinci/aic23.h
new file mode 100644
index 0000000..6513065
--- /dev/null
+++ b/include/asm-arm/arch-davinci/aic23.h
@@ -0,0 +1,116 @@
+/*
+ * linux/include/asm-arm/arch-omap/aic23.h
+ *
+ * Hardware definitions for TI TLV320AIC23 audio codec
+ *
+ * Copyright (C) 2002 RidgeRun, Inc.
+ * Author: Steve Johnson
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.
+ */
+
+#ifndef __ASM_ARCH_AIC23_H
+#define __ASM_ARCH_AIC23_H
+
+// Codec TLV320AIC23
+#define LEFT_LINE_VOLUME_ADDR		0x00
+#define RIGHT_LINE_VOLUME_ADDR		0x01
+#define LEFT_CHANNEL_VOLUME_ADDR	0x02
+#define RIGHT_CHANNEL_VOLUME_ADDR	0x03
+#define ANALOG_AUDIO_CONTROL_ADDR	0x04
+#define DIGITAL_AUDIO_CONTROL_ADDR	0x05
+#define POWER_DOWN_CONTROL_ADDR		0x06
+#define DIGITAL_AUDIO_FORMAT_ADDR	0x07
+#define SAMPLE_RATE_CONTROL_ADDR	0x08
+#define DIGITAL_INTERFACE_ACT_ADDR	0x09
+#define RESET_CONTROL_ADDR		0x0F
+
+// Left (right) line input volume control register
+#define LRS_ENABLED			0x0100
+#define LIM_MUTED			0x0080
+#define LIV_DEFAULT			0x0017
+#define LIV_MAX				0x001f
+#define LIV_MIN				0x0000
+
+// Left (right) channel headphone volume control register
+#define LZC_ON				0x0080
+#define LHV_DEFAULT			0x0079
+#define LHV_MAX				0x007f
+#define LHV_MIN				0x0000
+
+// Analog audio path control register
+#define STA_REG(x)			((x)<<6)
+#define STE_ENABLED			0x0020
+#define DAC_SELECTED			0x0010
+#define BYPASS_ON			0x0008
+#define INSEL_MIC			0x0004
+#define MICM_MUTED			0x0002
+#define MICB_20DB			0x0001
+
+// Digital audio path control register
+#define DACM_MUTE			0x0008
+#define DEEMP_32K			0x0002
+#define DEEMP_44K			0x0004
+#define DEEMP_48K			0x0006
+#define ADCHP_ON			0x0001
+
+// Power control down register
+#define DEVICE_POWER_OFF	  	0x0080
+#define CLK_OFF				0x0040
+#define OSC_OFF				0x0020
+#define OUT_OFF				0x0010
+#define DAC_OFF				0x0008
+#define ADC_OFF				0x0004
+#define MIC_OFF				0x0002
+#define LINE_OFF			0x0001
+
+// Digital audio interface register
+#define MS_MASTER			0x0040
+#define LRSWAP_ON			0x0020
+#define LRP_ON				0x0010
+#define IWL_16				0x0000
+#define IWL_20				0x0004
+#define IWL_24				0x0008
+#define IWL_32				0x000C
+#define FOR_I2S				0x0002
+#define FOR_DSP				0x0003
+
+// Sample rate control register
+#define CLKOUT_HALF			0x0080
+#define CLKIN_HALF			0x0040
+#define BOSR_384fs			0x0002 // BOSR_272fs when in USB mode
+#define USB_CLK_ON			0x0001
+#define SR_MASK                         0xf
+#define CLKOUT_SHIFT                    7
+#define CLKIN_SHIFT                     6
+#define SR_SHIFT                        2
+#define BOSR_SHIFT                      1
+
+// Digital interface register
+#define ACT_ON				0x0001
+
+#define TLV320AIC23ID1                  (0x1a)	// cs low
+#define TLV320AIC23ID2                  (0x1b)	// cs high
+
+void tlv320aic23_power_up(void);
+void tlv320aic23_power_down(void);
+
+#endif /* __ASM_ARCH_AIC23_H */
diff --git a/include/asm-arm/arch-davinci/cpu.h b/include/asm-arm/arch-davinci/cpu.h
new file mode 100644
index 0000000..c7d190b
--- /dev/null
+++ b/include/asm-arm/arch-davinci/cpu.h
@@ -0,0 +1,32 @@
+/*
+ * linux/include/asm-arm/arch-davinci/cpu.h
+ *
+ * Davinci cpu type detection
+ *
+ * Author: Steve Chen <schen@mvista.com>
+ *
+ * 2007 (c) MontaVista Software, Inc. 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 _ASM_ARCH_CPU_H
+#define _ASM_ARCH_CPU_H
+
+extern unsigned int system_rev;
+
+#define GET_DAVINCI_CPU_TYPE	((system_rev >> 16) & 0xffff)
+
+#define IS_DAVINCI_CPU(type, id)			\
+static inline int cpu_is_davinci_dm ##type (void)	\
+{							\
+        return (GET_DAVINCI_CPU_TYPE == (id)) ? 1 : 0;	\
+}
+
+/* following generates the cpu_is_davinci_dmxxx */
+IS_DAVINCI_CPU(6443, 0x6443)	/* cpu_is_davinci_dm6443() */
+IS_DAVINCI_CPU(6467, 0x6467)	/* cpu_is_davinci_dm6467() */
+IS_DAVINCI_CPU(350, 0x350)	/* cpu_is_davinci_dm350() */
+
+#endif
diff --git a/include/asm-arm/arch-davinci/dma.h b/include/asm-arm/arch-davinci/dma.h
index 8e2f2d0..ac325c5 100644
--- a/include/asm-arm/arch-davinci/dma.h
+++ b/include/asm-arm/arch-davinci/dma.h
@@ -11,6 +11,6 @@
 #ifndef __ASM_ARCH_DMA_H
 #define __ASM_ARCH_DMA_H
 
-#define MAX_DMA_ADDRESS			0xffffffff
+#define MAX_DMA_ADDRESS                 0xffffffff
 
 #endif /* __ASM_ARCH_DMA_H */
diff --git a/include/asm-arm/arch-davinci/edma.h b/include/asm-arm/arch-davinci/edma.h
new file mode 100644
index 0000000..804282d
--- /dev/null
+++ b/include/asm-arm/arch-davinci/edma.h
@@ -0,0 +1,555 @@
+/*
+ *  linux/include/asm-arm/arch-davinci/edma.h
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *      TI DAVINCI dma definitions
+ *
+ *  Copyright (C) 2006 Texas Instruments.
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ *
+ */
+/******************************************************************************
+ * DMA driver for DaVinci
+ * DMA driver for Davinci abstractes each ParamEntry as a Logical DMA channel
+ * for the user.So on Davinci the user can request 128 DAM channels
+ *
+ * Actual Physical DMA channels = 64 EDMA channels + 8 QDMA channels
+ *
+ * On davinci user can request for two kinds of Logical DMA channels
+ * DMA MasterChannel -> ParamEntry which is associated with a DMA channel.
+ *                      On Davinci there are (64 + 8) MasterChanneles
+ *                      MasterChannel can be triggered by an event or manually
+ *
+ * DMA SlaveChannel  -> ParamEntry which is not associated with DMA cahnnel but
+ *                      which can be used to associate with MasterChannel.
+ *                      On Davinci there are (128-(64 + 8)) SlaveChannels
+ *                      SlaveChannel can only be triggered by a MasterChannel
+ *
+ */
+
+#ifndef EDMA_H_
+#define EDMA_H_
+
+/*Used by driver*/
+
+/**************************************************************************\
+* Register Overlay Structure for DRA
+\**************************************************************************/
+typedef struct {
+	unsigned int drae;
+	unsigned int draeh;
+} edmacc_dra_regs;
+
+/**************************************************************************\
+* Register Overlay Structure for QUEEVTENTRY
+\**************************************************************************/
+typedef struct {
+	unsigned int evt_entry;
+} edmacc_que_evtentry_regs;
+
+/**************************************************************************\
+* Register Overlay Structure for SHADOW
+\**************************************************************************/
+typedef struct {
+	unsigned int er;
+	unsigned int erh;
+	unsigned int ecr;
+	unsigned int ecrh;
+	unsigned int esr;
+	unsigned int esrh;
+	unsigned int cer;
+	unsigned int cerh;
+	unsigned int eer;
+	unsigned int eerh;
+	unsigned int eecr;
+	unsigned int eecrh;
+	unsigned int eesr;
+	unsigned int eesrh;
+	unsigned int ser;
+	unsigned int serh;
+	unsigned int secr;
+	unsigned int secrh;
+	unsigned char rsvd0[8];
+	unsigned int ier;
+	unsigned int ierh;
+	unsigned int iecr;
+	unsigned int iecrh;
+	unsigned int iesr;
+	unsigned int iesrh;
+	unsigned int ipr;
+	unsigned int iprh;
+	unsigned int icr;
+	unsigned int icrh;
+	unsigned int ieval;
+	unsigned char rsvd1[4];
+	unsigned int qer;
+	unsigned int qeer;
+	unsigned int qeecr;
+	unsigned int qeesr;
+	unsigned int qser;
+	unsigned int qsecr;
+	unsigned char rsvd2[360];
+} edmacc_shadow_regs;
+
+/**************************************************************************\
+* Register Overlay Structure for PARAMENTRY
+\**************************************************************************/
+typedef struct {
+	unsigned int opt;
+	unsigned int src;
+	unsigned int a_b_cnt;
+	unsigned int dst;
+	unsigned int src_dst_bidx;
+	unsigned int link_bcntrld;
+	unsigned int src_dst_cidx;
+	unsigned int ccnt;
+} edmacc_paramentry_regs;
+
+/**************************************************************************\
+* Register Overlay Structure
+\**************************************************************************/
+typedef struct {
+	unsigned int rev;
+	unsigned int cccfg;
+	unsigned char rsvd0[504];
+	unsigned int qchmap[8];
+	unsigned char rsvd1[32];
+	unsigned int dmaqnum[8];
+	unsigned int qdmaqnum;
+	unsigned char rsvd2[28];
+	unsigned int quetcmap;
+	unsigned int quepri;
+	unsigned char rsvd3[120];
+	unsigned int emr;
+	unsigned int emrh;
+	unsigned int emcr;
+	unsigned int emcrh;
+	unsigned int qemr;
+	unsigned int qemcr;
+	unsigned int ccerr;
+	unsigned int ccerrclr;
+	unsigned int eeval;
+	unsigned char rsvd4[28];
+	edmacc_dra_regs dra[4];
+	unsigned char rsvd5[32];
+	unsigned int qrae[4];
+	unsigned char rsvd6[112];
+	edmacc_que_evtentry_regs queevtentry[2][16];
+	unsigned char rsvd7[384];
+	unsigned int qstat[2];
+	unsigned char rsvd8[24];
+	unsigned int qwmthra;
+	unsigned int qwmthrb;
+	unsigned char rsvd9[24];
+	unsigned int ccstat;
+	unsigned char rsvd10[188];
+	unsigned int aetctl;
+	unsigned int aetstat;
+	unsigned int aetcmd;
+	unsigned char rsvd11[2292];
+	unsigned int er;
+	unsigned int erh;
+	unsigned int ecr;
+	unsigned int ecrh;
+	unsigned int esr;
+	unsigned int esrh;
+	unsigned int cer;
+	unsigned int cerh;
+	unsigned int eer;
+	unsigned int eerh;
+	unsigned int eecr;
+	unsigned int eecrh;
+	unsigned int eesr;
+	unsigned int eesrh;
+	unsigned int ser;
+	unsigned int serh;
+	unsigned int secr;
+	unsigned int secrh;
+	unsigned char rsvd12[8];
+	unsigned int ier;
+	unsigned int ierh;
+	unsigned int iecr;
+	unsigned int iecrh;
+	unsigned int iesr;
+	unsigned int iesrh;
+	unsigned int ipr;
+	unsigned int iprh;
+	unsigned int icr;
+	unsigned int icrh;
+	unsigned int ieval;
+	unsigned char rsvd13[4];
+	unsigned int qer;
+	unsigned int qeer;
+	unsigned int qeecr;
+	unsigned int qeesr;
+	unsigned int qser;
+	unsigned int qsecr;
+	unsigned char rsvd14[3944];
+	edmacc_shadow_regs shadow[4];
+	unsigned char rsvd15[6144];
+	edmacc_paramentry_regs paramentry[128];
+} edmacc_regs;
+
+#define CCINT0_INTERRUPT     16
+#define CCERRINT_INTERRUPT   17
+#define TCERRINT0_INTERRUPT   18
+#define TCERRINT1_INTERRUPT   19
+
+#define SAM (1)
+#define DAM (1<<1)
+#define SYNCDIM (1<<2)
+#define STATIC (1<<3)
+#define EDMA_FWID (0x7<<8)
+#define TCCMODE (0x1<<11)
+#define TCC (0x3f<<12)
+#define WIMODE (0x1<<19)
+#define TCINTEN (0x1<<20)
+#define ITCINTEN (0x1<<21)
+#define TCCHEN (0x1<<22)
+#define ITCCHEN (0x1<<23)
+#define SECURE (0x1<<30)
+#define PRIV (0x1<<31)
+
+#define TRWORD (0x7<<2)
+#define PAENTRY (0x1ff<<5)
+/*if changing the QDMA_TRWORD do appropriate change in davinci_start_dma */
+#define QDMA_TRWORD (7 & 0x7)
+
+/*Used by driver*/
+
+#define DAVINCI_EDMA_NUM_DMACH           64
+#define DAVINCI_EDMA_NUM_QDMACH           8
+#define DAVINCI_EDMA_NUM_PARAMENTRY     128
+#define DAVINCI_EDMA_NUM_EVQUE            2
+#define DAVINCI_EDMA_CHMAPEXIST           0
+#define DAVINCI_EDMA_NUM_REGIONS          4
+#define DAVINCI_EDMA_MEMPROTECT           0
+
+#define DAVINCI_NUM_UNUSEDCH             21
+
+#define TCC_ANY    -1
+
+#define DAVINCI_EDMA_PARAM_ANY            -2
+#define DAVINCI_DMA_CHANNEL_ANY           -1
+#define DAVINCI_DMA_MCBSP_TX              2
+#define DAVINCI_DMA_MCBSP_RX              3
+#define DAVINCI_DMA_VPSS_HIST             4
+#define DAVINCI_DMA_VPSS_H3A              5
+#define DAVINCI_DMA_VPSS_PRVU             6
+#define DAVINCI_DMA_VPSS_RSZ              7
+#define DAVINCI_DMA_IMCOP_IMXINT          8
+#define DAVINCI_DMA_IMCOP_VLCDINT         9
+#define DAVINCI_DMA_IMCO_PASQINT         10
+#define DAVINCI_DMA_IMCOP_DSQINT         11
+#define DAVINCI_DMA_SPI_SPIX             16
+#define DAVINCI_DMA_SPI_SPIR             17
+#define DAVINCI_DMA_UART0_URXEVT0        18
+#define DAVINCI_DMA_UART0_UTXEVT0        19
+#define DAVINCI_DMA_UART1_URXEVT1        20
+#define DAVINCI_DMA_UART1_UTXEVT1        21
+#define DAVINCI_DMA_UART2_URXEVT2        22
+#define DAVINCI_DMA_UART2_UTXEVT2        23
+#define DAVINCI_DMA_MEMSTK_MSEVT         24
+#define DAVINCI_DMA_MMCRXEVT             26
+#define DAVINCI_DMA_MMCTXEVT             27
+#define DAVINCI_DMA_I2C_ICREVT           28
+#define DAVINCI_DMA_I2C_ICXEVT           29
+#define DAVINCI_DMA_GPIO_GPINT0          32
+#define DAVINCI_DMA_GPIO_GPINT1          33
+#define DAVINCI_DMA_GPIO_GPINT2          34
+#define DAVINCI_DMA_GPIO_GPINT3          35
+#define DAVINCI_DMA_GPIO_GPINT4          36
+#define DAVINCI_DMA_GPIO_GPINT5          37
+#define DAVINCI_DMA_GPIO_GPINT6          38
+#define DAVINCI_DMA_GPIO_GPINT7          39
+#define DAVINCI_DMA_GPIO_GPBNKINT0       40
+#define DAVINCI_DMA_GPIO_GPBNKINT1       41
+#define DAVINCI_DMA_GPIO_GPBNKINT2       42
+#define DAVINCI_DMA_GPIO_GPBNKINT3       43
+#define DAVINCI_DMA_GPIO_GPBNKINT4       44
+#define DAVINCI_DMA_TIMER0_TINT0         48
+#define DAVINCI_DMA_TIMER1_TINT1         49
+#define DAVINCI_DMA_TIMER2_TINT2         50
+#define DAVINCI_DMA_TIMER3_TINT3         51
+#define DAVINCI_DMA_PWM0                 52
+#define DAVINCI_DMA_PWM1                 53
+#define DAVINCI_DMA_PWM2                 54
+#define DAVINCI_DMA_QDMA0                64
+#define DAVINCI_DMA_QDMA1                65
+#define DAVINCI_DMA_QDMA2                66
+#define DAVINCI_DMA_QDMA3                67
+#define DAVINCI_DMA_QDMA4                68
+#define DAVINCI_DMA_QDMA5                69
+#define DAVINCI_DMA_QDMA6                71
+#define DAVINCI_DMA_QDMA7                72
+
+/*ch_status paramater of callback function possible values*/
+#define DMA_COMPLETE 1
+#define DMA_CC_ERROR 2
+#define DMA_TC1_ERROR 3
+#define DMA_TC2_ERROR 4
+
+enum address_mode {
+	INCR = 0,
+	FIFO = 1
+};
+
+enum fifo_width {
+	W8BIT = 0,
+	W16BIT = 1,
+	W32BIT = 2,
+	W64BIT = 3,
+	W128BIT = 4,
+	W256BIT = 5
+};
+
+enum dma_event_q {
+	EVENTQ_0 = 0,
+	EVENTQ_1 = 1,
+	EVENTQ_DEFAULT = -1
+};
+
+enum sync_dimension {
+	ASYNC = 0,
+	ABSYNC = 1
+};
+
+/******************************************************************************
+ * davinci_request_dma - request for the Davinci DMA channel
+ *
+ * dev_id - DMA channel number
+ *
+ * EX: DAVINCI_DMA_MCBSP_TX - For requesting a DMA MasterChannel with MCBSP_TX
+ *     event association
+ *
+ *     DAVINCI_DMA_ANY - For requesting a DMA Masterchannel which does not has
+ *     event association
+ *
+ *     DAVINCI_DMA_LINK - for requesting a DMA SlaveChannel
+ *
+ * dev_name   - name of the dma channel in human readable format
+ * callback   - channel callback function (valied only if you are requesting
+ *              for a DMA MasterChannel)
+ * data       - private data for the channel to be requested
+ * lch        - contains the device id allocated
+ * tcc        - specifies the channel number on which the interrupt is
+ *              generated
+ *              Valied for QDMA and PARAM channes
+ * eventq_no  - Event Queue no to which the channel will be associated with
+ *              (valied only if you are requesting for a DMA MasterChannel)
+ *              Values : EVENTQ_0/EVENTQ_1 for event queue 0/1.
+ *                       EVENTQ_DEFAULT for Default queue
+ *
+ * Return: zero on success,
+ *         -EINVAL - if the requested channel is not supported on the ARM side events
+ *         -EBUSY - if the requested channel is already in use
+ *          EREQDMA - if failed to request the dma channel
+ *
+ *****************************************************************************/
+int davinci_request_dma(int dev_id,
+			const char *dev_name,
+			void (*callback) (int lch, unsigned short ch_status,
+					  void *data), void *data, int *lch,
+			int *tcc, enum dma_event_q
+    );
+
+/******************************************************************************
+ * davinci_set_dma_src_params - DMA source parameters setup
+ *
+ * lch         - channel for which the source parameters to be configured
+ * src_port    - Source port address
+ * addressMode - indicates whether the address mode is FIFO or not
+ * fifoWidth   - valied only if addressMode is FIFO, indicates the vidth of
+ *                FIFO
+ *             0 - 8 bit
+ *             1 - 16 bit
+ *             2 - 32 bit
+ *             3 - 64 bit
+ *             4 - 128 bit
+ *             5 - 256 bit
+ *****************************************************************************/
+void davinci_set_dma_src_params(int lch, unsigned long src_port,
+				enum address_mode mode, enum fifo_width);
+
+/******************************************************************************
+ * davinci_set_dma_dest_params - DMA destination parameters setup
+ *
+ * lch         - channel or param device for destination parameters to be
+ *               configured
+ * dest_port   - Destination port address
+ * addressMode - indicates whether the address mode is FIFO or not
+ * fifoWidth   - valied only if addressMode is FIFO,indicates the vidth of FIFO
+ *             0 - 8 bit
+ *             1 - 16 bit
+ *             2 - 32 bit
+ *             3 - 64 bit
+ *             4 - 128 bit
+ *             5 - 256 bit
+ *
+ *****************************************************************************/
+void davinci_set_dma_dest_params(int lch, unsigned long dest_port,
+				 enum address_mode mode, enum fifo_width);
+
+/******************************************************************************
+ * davinci_set_dma_src_index - DMA source index setup
+ *
+ * lch     - channel or param device for configuration of source index
+ * srcbidx - source B-register index
+ * srccidx - source C-register index
+ *
+ *****************************************************************************/
+void davinci_set_dma_src_index(int lch, short srcbidx, short srccidx);
+
+/******************************************************************************
+ * davinci_set_dma_dest_index - DMA destination index setup
+ *
+ * lch      - channel or param device for configuration of destination index
+ * destbidx - dest B-register index
+ * destcidx - dest C-register index
+ *
+ *****************************************************************************/
+void davinci_set_dma_dest_index(int lch, short destbidx, short destcidx);
+
+/******************************************************************************
+ * davinci_set_dma_transfer_params -  DMA transfer parameters setup
+ *
+ * lch  - channel or param device for configuration of aCount, bCount and
+ *        cCount regs.
+ * aCnt - aCnt register value to be configured
+ * bCnt - bCnt register value to be configured
+ * cCnt - cCnt register value to be configured
+ *
+ *****************************************************************************/
+void davinci_set_dma_transfer_params(int lch, unsigned short acnt,
+				     unsigned short bcnt, unsigned short ccnt,
+				     unsigned short bcntrld,
+				     enum sync_dimension sync_mode);
+
+/******************************************************************************
+ *
+ * davinci_set_dma_params -
+ * ARGUMENTS:
+ *      lch - logical channel number
+ *
+ *****************************************************************************/
+void davinci_set_dma_params(int lch, edmacc_paramentry_regs * temp);
+
+/******************************************************************************
+ *
+ * davinci_get_dma_params -
+ * ARGUMENTS:
+ *      lch - logical channel number
+ *
+ *****************************************************************************/
+void davinci_get_dma_params(int lch, edmacc_paramentry_regs * temp);
+
+/******************************************************************************
+ * davinci_start_dma -  Starts the dma on the channel passed
+ *
+ * lch - logical channel number
+ *
+ * Note:    This API can be used only on DMA MasterChannel
+ *
+ * Return: zero on success
+ *        -EINVAL on failure, i.e if requested for the slave channels
+ *
+ *****************************************************************************/
+int davinci_start_dma(int lch);
+
+/******************************************************************************
+ * davinci_stop_dma -  Stops the dma on the channel passed
+ *
+ * lch - logical channel number
+ *
+ * Note:    This API can be used on MasterChannel and SlaveChannel
+ *****************************************************************************/
+void davinci_stop_dma(int lch);
+
+/******************************************************************************
+ * davinci_dma_link_lch - Link two Logical channels
+ *
+ * lch_head  - logical channel number, in which the link field is linked to the
+ *             the param pointed to by lch_queue
+ *             Can be a MasterChannel or SlaveChannel
+ * lch_queue - logical channel number or the param entry number, which is to be
+ *             linked to the lch_head
+ *             Must be a SlaveChannel
+ *
+ *                     |---------------|
+ *                     v               |
+ *      Ex:    ch1--> ch2-->ch3-->ch4--|
+ *
+ *             ch1 must be a MasterChannel
+ *
+ *             ch2, ch3, ch4 must be SlaveChannels
+ *
+ * Note:       After channel linking,the user should not update any PaRam entry
+ *             of MasterChannel ( In the above example ch1 )
+ *
+ *****************************************************************************/
+void davinci_dma_link_lch(int lch_head, int lch_queue);
+
+/******************************************************************************
+ * davinci_dma_unlink_lch - unlink the two logical channels passed through by
+ *                          setting the link field of head to 0xffff.
+ *
+ * lch_head  - logical channel number, from which the link field is to be
+ *             removed
+ * lch_queue - logical channel number or the param entry number,which is to be
+ *             unlinked from lch_head
+ *
+ *****************************************************************************/
+void davinci_dma_unlink_lch(int lch_head, int lch_queue);
+
+/******************************************************************************
+ *
+ * DMA channel chain - chains the two logical channels passed through by
+ * ARGUMENTS:
+ * lch_head - logical channel number, from which the link field is to be removed
+ * lch_queue - logical channel number or the param entry number, which is to be
+ *             unlinked from lch_head
+ *
+ *****************************************************************************/
+void davinci_dma_chain_lch(int lch_head, int lch_queue);
+
+/******************************************************************************
+ *
+ * DMA channel unchain - unchain the two logical channels passed through by
+ * ARGUMENTS:
+ * lch_head - logical channel number, from which the link field is to be removed
+ * lch_queue - logical channel number or the param entry number, which is to be
+ *             unlinked from lch_head
+ *
+ *****************************************************************************/
+void davinci_dma_unchain_lch(int lch_head, int lch_queue);
+
+/******************************************************************************
+ *
+ * Free DMA channel - Free the dma channel number passed
+ *
+ * ARGUMENTS:
+ * lch - dma channel number to get free
+ *
+ *****************************************************************************/
+void davinci_free_dma(int lch);
+
+#endif
diff --git a/include/asm-arm/arch-davinci/gpio.h b/include/asm-arm/arch-davinci/gpio.h
index ea24a0e..2e35d8c 100644
--- a/include/asm-arm/arch-davinci/gpio.h
+++ b/include/asm-arm/arch-davinci/gpio.h
@@ -64,11 +64,11 @@
 	void *__iomem ptr;
 
 	if (gpio < 32)
-		ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
+		ptr = (void *__iomem) IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
 	else if (gpio < 64)
-		ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
+		ptr = (void *__iomem) IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
 	else if (gpio < DAVINCI_N_GPIO)
-		ptr = (void *__iomem)IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
+		ptr = (void *__iomem) IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
 	else
 		ptr = NULL;
 	return ptr;
@@ -122,7 +122,7 @@
 
 static inline int gpio_get_value(unsigned gpio)
 {
-	struct gpio_controller *__iomem g;
+	struct gpio_controller	*__iomem g;
 
 	if (!__builtin_constant_p(gpio))
 		return __gpio_get(gpio);
diff --git a/include/asm-arm/arch-davinci/hdrc_cnf.h b/include/asm-arm/arch-davinci/hdrc_cnf.h
new file mode 100644
index 0000000..3811ce4
--- /dev/null
+++ b/include/asm-arm/arch-davinci/hdrc_cnf.h
@@ -0,0 +1,165 @@
+/*
+ * USB High-Speed Multi-Point Dual-Role Controller Configuration
+ *
+ * Copyright Mentor Graphics Corporation and Licensors 2004
+ * Copyright (C) 2005 by Texas Instruments
+ *
+ * This file contains configuration constants for the (m)hdrc
+ * silicon as integrated into DaVinci CPUs.
+ */
+
+#ifndef	__ARCH_MUSB_HDRC_CNF
+#define	__ARCH_MUSB_HDRC_CNF
+
+/* ** Number of Tx endpoints ** */
+/* Legal values are 1 - 16 (this value includes EP0) */
+#define MUSB_C_NUM_EPT 5
+
+/* ** Number of Rx endpoints ** */
+/* Legal values are 1 - 16 (this value includes EP0) */
+#define MUSB_C_NUM_EPR 5
+
+/* ** Endpoint 1 to 15 direction types ** */
+/* C_EP1_DEF is defined if either Tx endpoint 1 or Rx endpoint 1 are used */
+#define MUSB_C_EP1_DEF
+
+/* C_EP1_TX_DEF is defined if Tx endpoint 1 is used */
+#define MUSB_C_EP1_TX_DEF
+
+/* C_EP1_RX_DEF is defined if Rx endpoint 1 is used */
+#define MUSB_C_EP1_RX_DEF
+
+/* C_EP1_TOR_DEF is defined if Tx endpoint 1 and Rx endpoint 1 share a FIFO */
+/*`define C_EP1_TOR_DEF */
+
+/* C_EP1_TAR_DEF is defined if both Tx endpoint 1 and Rx endpoint 1 are used */
+/* and do not share a FIFO */
+#define MUSB_C_EP1_TAR_DEF
+
+/* Similarly for all other used endpoints */
+#define MUSB_C_EP2_DEF
+#define MUSB_C_EP2_TX_DEF
+#define MUSB_C_EP2_RX_DEF
+#define MUSB_C_EP2_TAR_DEF
+#define MUSB_C_EP3_DEF
+#define MUSB_C_EP3_TX_DEF
+#define MUSB_C_EP3_RX_DEF
+#define MUSB_C_EP3_TAR_DEF
+#define MUSB_C_EP4_DEF
+#define MUSB_C_EP4_TX_DEF
+#define MUSB_C_EP4_RX_DEF
+#define MUSB_C_EP4_TAR_DEF
+
+/* ** Endpoint 1 to 15 FIFO address bits ** */
+/* Legal values are 3 to 13 - corresponding to FIFO sizes of 8 to 8192 bytes. */
+/* If an Tx endpoint shares a FIFO with an Rx endpoint then the Rx FIFO size */
+/* must be the same as the Tx FIFO size. */
+/* All endpoints 1 to 15 must be defined, unused endpoints should be set to 2. */
+#define MUSB_C_EP1T_BITS 5
+#define MUSB_C_EP1R_BITS 5
+#define MUSB_C_EP2T_BITS 5
+#define MUSB_C_EP2R_BITS 5
+#define MUSB_C_EP3T_BITS 3
+#define MUSB_C_EP3R_BITS 3
+#define MUSB_C_EP4T_BITS 3
+#define MUSB_C_EP4R_BITS 3
+
+#define MUSB_C_EP5T_BITS 2
+#define MUSB_C_EP5R_BITS 2
+#define MUSB_C_EP6T_BITS 2
+#define MUSB_C_EP6R_BITS 2
+#define MUSB_C_EP7T_BITS 2
+#define MUSB_C_EP7R_BITS 2
+#define MUSB_C_EP8T_BITS 2
+#define MUSB_C_EP8R_BITS 2
+#define MUSB_C_EP9T_BITS 2
+#define MUSB_C_EP9R_BITS 2
+#define MUSB_C_EP10T_BITS 2
+#define MUSB_C_EP10R_BITS 2
+#define MUSB_C_EP11T_BITS 2
+#define MUSB_C_EP11R_BITS 2
+#define MUSB_C_EP12T_BITS 2
+#define MUSB_C_EP12R_BITS 2
+#define MUSB_C_EP13T_BITS 2
+#define MUSB_C_EP13R_BITS 2
+#define MUSB_C_EP14T_BITS 2
+#define MUSB_C_EP14R_BITS 2
+#define MUSB_C_EP15T_BITS 2
+#define MUSB_C_EP15R_BITS 2
+
+/* Define the following constant if the USB2.0 Transceiver Macrocell data width is 16-bits. */
+/* `define C_UTM_16 */
+
+/* Define this constant if the CPU uses big-endian byte ordering. */
+/*`define C_BIGEND */
+
+/* Define the following constant if any Tx endpoint is required to support multiple bulk packets. */
+/* `define C_MP_TX */
+
+/* Define the following constant if any Rx endpoint is required to support multiple bulk packets. */
+/* `define C_MP_RX */
+
+/* Define the following constant if any Tx endpoint is required to support high bandwidth ISO. */
+/* `define C_HB_TX */
+
+/* Define the following constant if any Rx endpoint is required to support high bandwidth ISO. */
+/* `define C_HB_RX */
+
+/* Define the following constant if software connect/disconnect control is required. */
+#define MUSB_C_SOFT_CON
+
+/* Define the following constant if Vendor Control Registers are required. */
+/* `define C_VEND_REG */
+
+/* Vendor control register widths. */
+#define MUSB_C_VCTL_BITS 4
+#define MUSB_C_VSTAT_BITS 8
+
+
+/* Define the following constant to include a DMA controller. */
+/*`define C_DMA */
+
+/* Define the following constant if 2 or more DMA channels are required. */
+/*`define C_DMA2 */
+
+/* Define the following constant if 3 or more DMA channels are required. */
+/*`define C_DMA3 */
+
+/* Define the following constant if 4 or more DMA channels are required. */
+/*`define C_DMA4 */
+
+/* Define the following constant if 5 or more DMA channels are required. */
+/*`define C_DMA5 */
+
+/* Define the following constant if 6 or more DMA channels are required. */
+/*`define C_DMA6 */
+
+/* Define the following constant if 7 or more DMA channels are required. */
+/*`define C_DMA7 */
+
+/* Define the following constant if 8 or more DMA channels are required. */
+/*`define C_DMA8 */
+
+
+/* ** Enable Dynamic FIFO Sizing ** */
+#define MUSB_C_DYNFIFO_DEF
+
+/* ** Derived constants ** */
+/* The following constants are derived from the previous configuration constants */
+
+/* Total number of endpoints
+ * Legal values are 2 - 16
+ * This must be equal to the larger of C_NUM_EPT, C_NUM_EPR
+ */
+#define MUSB_C_NUM_EPS 5
+
+/* C_EPMAX_BITS is equal to the largest endpoint FIFO word address bits */
+#define MUSB_C_EPMAX_BITS 11
+
+/* C_RAM_BITS is the number of address bits required to address the RAM (32-bit
+ * addresses).  It is defined as log2 of the sum of 2** of all the endpoint FIFO
+ * dword address bits (rounded up).
+ */
+#define MUSB_C_RAM_BITS 10
+
+#endif	/* __ARCH_MUSB_HDRC_CNF */
diff --git a/include/asm-arm/arch-davinci/i2c-client.h b/include/asm-arm/arch-davinci/i2c-client.h
new file mode 100644
index 0000000..3619546
--- /dev/null
+++ b/include/asm-arm/arch-davinci/i2c-client.h
@@ -0,0 +1,34 @@
+/*
+ *  include/asm-arm/arch-davinci/i2c-client.h
+ *
+ * Copyright (C) 2006 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* i2c-client.h */
+
+typedef enum {
+        USB_DRVVBUS = 0,
+        VDDIMX_EN = 1,
+        VLYNQ_ON = 2,
+        CF_RESET = 3,
+        WLAN_RESET = 4,
+        ATA_SEL = 5,
+        CF_SEL = 6
+} u35_expander_ops;
+
+int davinci_i2c_expander_op (u16 client_addr, u35_expander_ops pin, u8 val);
+int davinci_i2c_write(u8 size, u8 * val, u16 client_addr);
+int davinci_i2c_read(u8 size, u8 * val, u16 client_addr);
diff --git a/include/asm-arm/arch-davinci/mcbsp.h b/include/asm-arm/arch-davinci/mcbsp.h
new file mode 100644
index 0000000..603f2da
--- /dev/null
+++ b/include/asm-arm/arch-davinci/mcbsp.h
@@ -0,0 +1,255 @@
+/*
+ *  include/asm-arm/arch-davinci/mcbsp.h
+ *
+ *  BRIEF MODULE DESCRIPTION
+ *      DAVINCI McBSP driver Info
+ *
+ *  Copyright (C) 2006 Texas Instruments.
+ *
+ *  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  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
+ *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
+ *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
+ *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  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.
+ *
+ */
+#ifndef __ASM_ARCH_DAVINCI_MCBSP_H
+#define __ASM_ARCH_DAVINCI_MCBSP_H
+
+#include <asm/hardware.h>
+#include <asm/arch/irqs.h>
+
+#define DAVINCI_MCBSP1_BASE	 DAVINCI_MCBSP_BASE
+#define DAVINCI_DMA_MCBSP1_RX 3
+#define DAVINCI_DMA_MCBSP1_TX 2
+
+#define DAVINCI_McBSP1RX IRQ_MBRINT
+#define DAVINCI_McBSP1TX IRQ_MBXINT
+
+#define DRR1	0x00
+#define DRR2	0x02
+#define DXR1	0x04
+#define DXR2	0x06
+#define SPCR1	0x08
+#define SPCR2	0x0a
+#define RCR1	0x0c
+#define RCR2	0x0e
+#define XCR1	0x10
+#define XCR2	0x12
+#define SRGR1	0x14
+#define SRGR2	0x16
+#define MCR1	0x18
+#define MCR2	0x1a
+#define RCERA	0x1c
+#define RCERB	0x1e
+#define XCERA	0x20
+#define XCERB	0x22
+#define PCR0	0x24
+#define PCR1	0x26
+#define RCERC	0x28
+#define RCERD	0x2a
+#define XCERC	0x2c
+#define XCERD	0x2e
+#define RCERE	0x30
+#define RCERF	0x32
+#define XCERE	0x34
+#define XCERF	0x36
+#define RCERG	0x38
+#define RCERH	0x3a
+#define XCERG	0x3c
+#define XCERH	0x3e
+
+#define DAVINCI_MAX_MCBSP_COUNT 1
+
+/********************** McBSP SPCR1 bit definitions ***********************/
+#define RRST			0x0001
+#define RRDY			0x0002
+#define RFULL			0x0004
+#define RSYNC_ERR		0x0008
+#define RINTM(value)		((value)<<4)	/* bits 4:5 */
+#define ABIS			0x0040
+#define DXENA			0x0080
+#define CLKSTP(value)		((value)<<11)	/* bits 11:12 */
+#define RJUST(value)		((value)<<13)	/* bits 13:14 */
+#define DLB			0x8000
+
+/********************** McBSP SPCR2 bit definitions ***********************/
+#define XRST		0x0001
+#define XRDY		0x0002
+#define XEMPTY		0x0004
+#define XSYNC_ERR	0x0008
+#define XINTM(value)	((value)<<4)	/* bits 4:5 */
+#define GRST		0x0040
+#define FRST		0x0080
+#define SOFT		0x0100
+#define FREE		0x0200
+
+/********************** McBSP PCR bit definitions *************************/
+#define CLKRP		0x0001
+#define CLKXP		0x0002
+#define FSRP		0x0004
+#define FSXP		0x0008
+#define DR_STAT		0x0010
+#define DX_STAT		0x0020
+#define CLKS_STAT	0x0040
+#define SCLKME		0x0080
+#define CLKRM		0x0100
+#define CLKXM		0x0200
+#define FSRM		0x0400
+#define FSXM		0x0800
+#define RIOEN		0x1000
+#define XIOEN		0x2000
+#define IDLE_EN		0x4000
+
+/********************** McBSP RCR1 bit definitions ************************/
+#define RWDLEN1(value)		((value)<<5)	/* Bits 5:7 */
+#define RFRLEN1(value)		((value)<<8)	/* Bits 8:14 */
+
+/********************** McBSP XCR1 bit definitions ************************/
+#define XWDLEN1(value)		((value)<<5)	/* Bits 5:7 */
+#define XFRLEN1(value)		((value)<<8)	/* Bits 8:14 */
+
+/*********************** McBSP RCR2 bit definitions ***********************/
+#define RDATDLY(value)		(value)	/* Bits 0:1 */
+#define RFIG			0x0004
+#define RCOMPAND(value)		((value)<<3)	/* Bits 3:4 */
+#define RWDLEN2(value)		((value)<<5)	/* Bits 5:7 */
+#define RFRLEN2(value)		((value)<<8)	/* Bits 8:14 */
+#define RPHASE			0x8000
+
+/*********************** McBSP XCR2 bit definitions ***********************/
+#define XDATDLY(value)		(value)	/* Bits 0:1 */
+#define XFIG			0x0004
+#define XCOMPAND(value)		((value)<<3)	/* Bits 3:4 */
+#define XWDLEN2(value)		((value)<<5)	/* Bits 5:7 */
+#define XFRLEN2(value)		((value)<<8)	/* Bits 8:14 */
+#define XPHASE			0x8000
+
+/********************* McBSP SRGR1 bit definitions ************************/
+#define CLKGDV(value)		(value)	/* Bits 0:7 */
+#define FWID(value)		((value)<<8)	/* Bits 8:15 */
+
+/********************* McBSP SRGR2 bit definitions ************************/
+#define FPER(value)		(value)	/* Bits 0:11 */
+#define FSGM			0x1000
+#define CLKSM			0x2000
+#define CLKSP			0x4000
+#define GSYNC			0x8000
+
+/********************* McBSP MCR1 bit definitions *************************/
+#define RMCM			0x0001
+#define RCBLK(value)		((value)<<2)	/* Bits 2:4 */
+#define RPABLK(value)		((value)<<5)	/* Bits 5:6 */
+#define RPBBLK(value)		((value)<<7)	/* Bits 7:8 */
+
+/********************* McBSP MCR2 bit definitions *************************/
+#define XMCM(value)		(value)	/* Bits 0:1 */
+#define XCBLK(value)		((value)<<2)	/* Bits 2:4 */
+#define XPABLK(value)		((value)<<5)	/* Bits 5:6 */
+#define XPBBLK(value)		((value)<<7)	/* Bits 7:8 */
+
+/* we don't do multichannel for now */
+struct davinci_mcbsp_reg_cfg {
+	u16 spcr2;
+	u16 spcr1;
+	u16 rcr2;
+	u16 rcr1;
+	u16 xcr2;
+	u16 xcr1;
+	u16 srgr2;
+	u16 srgr1;
+	u16 mcr2;
+	u16 mcr1;
+	u16 pcr2;
+	u16 pcr0;
+	u16 rcerc;
+	u16 rcerd;
+	u16 xcerc;
+	u16 xcerd;
+	u16 rcere;
+	u16 rcerf;
+	u16 xcere;
+	u16 xcerf;
+	u16 rcerg;
+	u16 rcerh;
+	u16 xcerg;
+	u16 xcerh;
+};
+
+typedef enum {
+	DAVINCI_MCBSP1 = 0,
+} davinci_mcbsp_id;
+
+typedef enum {
+	DAVINCI_MCBSP_WORD_8 = 0,
+	DAVINCI_MCBSP_WORD_12,
+	DAVINCI_MCBSP_WORD_16,
+	DAVINCI_MCBSP_WORD_20,
+	DAVINCI_MCBSP_WORD_24,
+	DAVINCI_MCBSP_WORD_32,
+} davinci_mcbsp_word_length;
+
+typedef enum {
+	DAVINCI_MCBSP_CLK_RISING = 0,
+	DAVINCI_MCBSP_CLK_FALLING,
+} davinci_mcbsp_clk_polarity;
+
+typedef enum {
+	DAVINCI_MCBSP_FS_ACTIVE_HIGH = 0,
+	DAVINCI_MCBSP_FS_ACTIVE_LOW,
+} davinci_mcbsp_fs_polarity;
+
+typedef enum {
+	DAVINCI_MCBSP_CLK_STP_MODE_NO_DELAY = 0,
+	DAVINCI_MCBSP_CLK_STP_MODE_DELAY,
+} davinci_mcbsp_clk_stp_mode;
+
+/******* SPI specific mode **********/
+typedef enum {
+	DAVINCI_MCBSP_SPI_MASTER = 0,
+	DAVINCI_MCBSP_SPI_SLAVE,
+} davinci_mcbsp_spi_mode;
+
+struct davinci_mcbsp_spi_cfg {
+	davinci_mcbsp_spi_mode spi_mode;
+	davinci_mcbsp_clk_polarity rx_clock_polarity;
+	davinci_mcbsp_clk_polarity tx_clock_polarity;
+	davinci_mcbsp_fs_polarity fsx_polarity;
+	u8 clk_div;
+	davinci_mcbsp_clk_stp_mode clk_stp_mode;
+	davinci_mcbsp_word_length word_length;
+};
+
+void davinci_mcbsp_config(unsigned int id,
+			  const struct davinci_mcbsp_reg_cfg *config);
+int davinci_mcbsp_request(unsigned int id);
+void davinci_mcbsp_free(unsigned int id);
+void davinci_mcbsp_start(unsigned int id);
+void davinci_mcbsp_stop(unsigned int id);
+void davinci_mcbsp_xmit_word(unsigned int id, u32 word);
+u32 davinci_mcbsp_recv_word(unsigned int id);
+
+int davinci_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
+			      unsigned int length);
+int davinci_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,
+			      unsigned int length);
+
+/* SPI specific API */
+void davinci_mcbsp_set_spi_mode(unsigned int id,
+				const struct davinci_mcbsp_spi_cfg *spi_cfg);
+
+#endif
diff --git a/include/asm-arm/arch-davinci/system.h b/include/asm-arm/arch-davinci/system.h
index 440ac51..851d341 100644
--- a/include/asm-arm/arch-davinci/system.h
+++ b/include/asm-arm/arch-davinci/system.h
@@ -18,7 +18,7 @@
 
 static void arch_idle(void)
 {
-	cpu_do_idle();
+			cpu_do_idle();
 }
 
 static void arch_reset(char mode)
@@ -26,4 +26,4 @@
 	davinci_watchdog_reset();
 }
 
-#endif /* __ASM_ARCH_SYSTEM_H */
+#endif				/* __ASM_ARCH_SYSTEM_H */
diff --git a/include/asm-arm/arch-davinci/timex.h b/include/asm-arm/arch-davinci/timex.h
index 5282756..e4ec97f 100644
--- a/include/asm-arm/arch-davinci/timex.h
+++ b/include/asm-arm/arch-davinci/timex.h
@@ -12,6 +12,6 @@
 #define __ASM_ARCH_TIMEX_H
 
 /* The source frequency for the timers is the 27MHz clock */
-#define CLOCK_TICK_RATE 27000000
+#define CLOCK_TICK_RATE	        27000000
 
-#endif /* __ASM_ARCH_TIMEX_H__ */
+#endif				/* __ASM_ARCH_TIMEX_H__ */
diff --git a/include/asm-arm/memory.h b/include/asm-arm/memory.h
index d9bfb39..6a779f0 100644
--- a/include/asm-arm/memory.h
+++ b/include/asm-arm/memory.h
@@ -27,6 +27,8 @@
 #include <asm/arch/memory.h>
 #include <asm/sizes.h>
 
+#ifdef __KERNEL__
+
 #ifdef CONFIG_MMU
 
 #ifndef TASK_SIZE
@@ -328,4 +330,6 @@
 
 #include <asm-generic/memory_model.h>
 
+#endif // __KERNEL__
+
 #endif
diff --git a/include/linux/ide.h b/include/linux/ide.h
index b9f66c1..0cd8b9d 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -206,7 +206,7 @@
 		ide_rz1000,	ide_trm290,
 		ide_cmd646,	ide_cy82c693,	ide_4drives,
 		ide_pmac,	ide_etrax100,	ide_acorn,
-		ide_au1xxx, ide_forced
+		ide_au1xxx,	ide_palm3710,	ide_forced
 } hwif_chipset_t;
 
 /*
diff --git a/include/media/ccdc_davinci.h b/include/media/ccdc_davinci.h
new file mode 100644
index 0000000..9f0a08d
--- /dev/null
+++ b/include/media/ccdc_davinci.h
@@ -0,0 +1,144 @@
+/*
+ *
+ * Copyright (C) 2006 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* ccdc_davinci.h */
+
+#ifndef CCDC_DAVINCI_H
+#define CCDC_DAVINCI_H
+#include <linux/types.h>
+
+#ifdef __KERNEL__
+#include <asm/arch/hardware.h>
+#include <asm/io.h>
+#endif
+
+#include <linux/videodev.h>
+
+typedef enum ccdc_pixfmt {
+	CCDC_PIXFMT_RAW = 0,
+	CCDC_PIXFMT_YCBCR_16BIT = 1,
+	CCDC_PIXFMT_YCBCR_8BIT = 2
+} ccdc_pixfmt;
+
+typedef enum ccdc_frmfmt {
+	CCDC_FRMFMT_PROGRESSIVE = 0,
+	CCDC_FRMFMT_INTERLACED = 1
+} ccdc_frmfmt;
+
+typedef enum ccdc_pinpol {
+	CCDC_PINPOL_POSITIVE = 0,
+	CCDC_PINPOL_NEGATIVE = 1
+} ccdc_pinpol;
+
+/* PIXEL ORDER IN MEMORY from LSB to MSB */
+/* only applicable for 8-bit input mode  */
+typedef enum ccdc_pixorder {
+	CCDC_PIXORDER_CBYCRY = 1,
+	CCDC_PIXORDER_YCBYCR = 0
+} ccdc_pixorder;
+
+typedef enum ccdc_buftype {
+	CCDC_BUFTYPE_FLD_INTERLEAVED,
+	CCDC_BUFTYPE_FLD_SEPARATED
+} ccdc_buftype;
+
+typedef struct v4l2_rect ccdc_imgwin;
+
+typedef struct ccdc_params_ycbcr {
+	ccdc_pixfmt pix_fmt;	/* pixel format                     */
+	ccdc_frmfmt frm_fmt;	/* progressive or interlaced frame  */
+	ccdc_imgwin win;	/* video window                     */
+	ccdc_pinpol fid_pol;	/* field id polarity                */
+	ccdc_pinpol vd_pol;	/* vertical sync polarity           */
+	ccdc_pinpol hd_pol;	/* horizontal sync polarity         */
+	int bt656_enable;	/* enable BT.656 embedded sync mode */
+	ccdc_pixorder pix_order;/* cb:y:cr:y or y:cb:y:cr in memory */
+	ccdc_buftype buf_type;	/* interleaved or separated fields  */
+} ccdc_params_ycbcr;
+
+#ifdef __KERNEL__
+/**************************************************************************\
+* Register OFFSET Definitions
+\**************************************************************************/
+#define PID                             0x0
+#define PCR                             0x4
+#define SYN_MODE                        0x8
+#define HD_VD_WID                       0xc
+#define PIX_LINES                       0x10
+#define HORZ_INFO                       0x14
+#define VERT_START                      0x18
+#define VERT_LINES                      0x1c
+#define CULLING                         0x20
+#define HSIZE_OFF                       0x24
+#define SDOFST                          0x28
+#define SDR_ADDR                        0x2c
+#define CLAMP                           0x30
+#define DCSUB                           0x34
+#define COLPTN                          0x38
+#define BLKCMP                          0x3c
+#define FPC                             0x40
+#define FPC_ADDR                        0x44
+#define VDINT                           0x48
+#define ALAW                            0x4c
+#define REC656IF                        0x50
+#define CCDCFG                          0x54
+#define FMTCFG                          0x58
+#define FMT_HORZ                        0x5c
+#define FMT_VERT                        0x50
+#define FMT_ADDR0                       0x64
+#define FMT_ADDR1                       0x68
+#define FMT_ADDR2                       0x6c
+#define FMT_ADDR3                       0x70
+#define FMT_ADDR4                       0x74
+#define FMT_ADDR5                       0x78
+#define FMT_ADDR6                       0x7c
+#define FMT_ADDR7                       0x80
+#define PRGEVEN_0                       0x84
+#define PRGEVEN_1                       0x88
+#define PRGODD_0                        0x8c
+#define PRGODD_1                        0x90
+#define VP_OUT                          0x94
+
+#define CCDC_IOBASE                     (0x01c70400)
+
+#define regw(val, reg)    davinci_writel(val, (reg)+CCDC_IOBASE)
+#define regr(reg)         davinci_readl((reg)+CCDC_IOBASE)
+
+extern void ccdc_reset(void);
+extern void ccdc_config_ycbcr(ccdc_params_ycbcr * params);
+extern void ccdc_setwin(ccdc_params_ycbcr * params);
+
+/* inline functions that must be fast because they are called frequently */
+static inline void ccdc_enable(int flag)
+{
+	regw(flag, PCR);
+}
+
+static inline void ccdc_setfbaddr(unsigned long paddr)
+{
+	regw(paddr & 0xffffffe0, SDR_ADDR);
+}
+
+static inline int ccdc_getfid(void)
+{
+	int fid = (regr(SYN_MODE) >> 15) & 0x1;
+	return fid;
+}
+#endif
+
+#endif /* CCDC_DAVINCI_H */
diff --git a/include/media/davinci_vpfe.h b/include/media/davinci_vpfe.h
new file mode 100644
index 0000000..26e7b2c
--- /dev/null
+++ b/include/media/davinci_vpfe.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2006 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* davinci_vpfe.h */
+
+#ifndef DAVINCI_VPFE_H
+#define DAVINCI_VPFE_H
+#ifdef __KERNEL__
+#include <media/v4l2-dev.h>
+#endif
+
+#include <media/ccdc_davinci.h>
+#include <media/tvp5146.h>
+
+#define TRUE 1
+#define FALSE 0
+
+/* vpfe specific video standards */
+#define VPFE_STD_625_50_SQP ((V4L2_STD_625_50)<<32)
+#define VPFE_STD_525_60_SQP ((V4L2_STD_525_60)<<32)
+#define VPFE_STD_AUTO ((v4l2_std_id)(0x1000000000000000ULL))
+#define VPFE_STD_AUTO_SQP ((v4l2_std_id)(0x2000000000000000ULL))
+
+#define VPFE_CMD_CONFIG_CCDC _IOW('V',BASE_VIDIOC_PRIVATE + 1,ccdc_params_ycbcr)
+#define VPFE_CMD_LATEST_FRM_ONLY   _IOW('V',BASE_VIDIOC_PRIVATE + 2,int)
+#define VPFE_CMD_CONFIG_TVP5146 _IOW('V',BASE_VIDIOC_PRIVATE + 3,tvp5146_params)
+
+/* settings for commonly used video formats */
+#define VPFE_WIN_NTSC    {0,0,720,480}
+#define VPFE_WIN_PAL     {0,0,720,576}
+#define VPFE_WIN_NTSC_SP {0,0,640,480}	/* ntsc square pixel */
+#define VPFE_WIN_PAL_SP  {0,0,768,576}	/* pal square pixel */
+#define VPFE_WIN_CIF     {0,0,352,288}
+#define VPFE_WIN_QCIF    {0,0,176,144}
+#define VPFE_WIN_QVGA    {0,0,320,240}
+#define VPFE_WIN_SIF     {0,0,352,240}
+
+
+#ifdef __KERNEL__
+
+#include <media/video-buf.h>
+
+#define VPFE_MAJOR_RELEASE 0
+#define VPFE_MINOR_RELEASE 0
+#define VPFE_BUILD         1
+
+#define VPFE_VERSION_CODE \
+     (VPFE_MAJOR_RELEASE<<16)  | (VPFE_MINOR_RELEASE<<8) | VPFE_BUILD
+
+/* By default, the driver is setup for auto-swich mode */
+#define VPFE_DEFAULT_STD VPFE_STD_AUTO
+
+#define VPFE_PIXELASPECT_NTSC {11, 10}
+#define VPFE_PIXELASPECT_PAL  {54, 59}
+#define VPFE_PIXELASPECT_NTSC_SP    {1, 1}
+#define VPFE_PIXELASPECT_PAL_SP     {1, 1}
+#define VPFE_PIXELASPECT_DEFAULT    {1, 1}
+
+#define VPFE_MAX_FRAME_WIDTH      768	/* account for PAL Square pixel mode */
+#define VPFE_MAX_FRAME_HEIGHT     576	/* account for PAL                   */
+/* 4:2:2 data */
+#define VPFE_MAX_FBUF_SIZE       (VPFE_MAX_FRAME_WIDTH*VPFE_MAX_FRAME_HEIGHT*2)
+/* frame buffers allocate at driver initialization time */
+#define VPFE_DEFNUM_FBUFS             3
+
+#define VPFE_MAX_FBUF_ORDER \
+   get_order(roundup_pow_of_two(VPFE_MAX_FBUF_SIZE))
+
+/* device object */
+typedef struct vpfe_obj {
+	struct video_device *video_dev;
+	struct videobuf_queue bufqueue;/* queue with frame buffers      */
+	struct list_head dma_queue;
+	u32 latest_only;		/* indicate whether to return the most */
+					/* recent captured buffers only        */
+	u32 usrs;
+	u32 io_usrs;
+	struct v4l2_prio_state prio;
+	v4l2_std_id std;
+	struct v4l2_rect vwin;
+	struct v4l2_rect bounds;
+	struct v4l2_fract pixelaspect;
+       	spinlock_t irqlock;
+	struct semaphore lock;
+	enum v4l2_field field;
+	u32 pixelfmt;
+	u32 numbuffers;
+	u8* fbuffers[VIDEO_MAX_FRAME];
+	struct videobuf_buffer *curFrm;
+	struct videobuf_buffer *nextFrm;
+	int field_id;
+	int mode_changed;
+	int started;
+	int field_offset;
+	tvp5146_params tvp5146_params;
+	ccdc_params_ycbcr ccdc_params;
+} vpfe_obj;
+
+/* file handle */
+typedef struct vpfe_fh {
+	struct vpfe_obj *dev;
+	int io_allowed;
+	enum v4l2_priority prio;
+} vpfe_fh;
+#endif
+
+#endif /* DAVINCI_VPFE_H */
diff --git a/include/media/tvp5146.h b/include/media/tvp5146.h
new file mode 100644
index 0000000..c82935f
--- /dev/null
+++ b/include/media/tvp5146.h
@@ -0,0 +1,104 @@
+/*
+ *
+ *
+ * Copyright (C) 2006 Texas Instruments Inc
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+/* tvp5146.h file */
+
+#ifndef TVP5146_H
+#define TVP5146_H
+
+#ifdef TRUE
+#undef TRUE
+#endif
+#ifdef FALSE
+#undef FALSE
+#endif
+
+#define TRUE 1
+#define FALSE 0
+
+/* analog muxing mode */
+#define    TVP5146_AMUX_COMPOSITE  0
+#define    TVP5146_AMUX_SVIDEO     1
+
+typedef enum {
+	TVP5146_MODE_INV = -1,
+	TVP5146_MODE_AUTO = 0,	        /* autoswitch mode (default)   */
+	TVP5146_MODE_NTSC = 1,	        /* (M, J) NTSC      525-line   */
+	TVP5146_MODE_PAL = 2,	        /* (B, D, G, H, I, N) PAL      */
+	TVP5146_MODE_PAL_M = 3,	        /* (M) PAL          525-line   */
+	TVP5146_MODE_PAL_CN = 4,	/* (Combination-N) PAL         */
+	TVP5146_MODE_NTSC_443 = 5,	/* NTSC 4.43        525-line   */
+	TVP5146_MODE_SECAM = 6,	        /* SECAM                       */
+	TVP5146_MODE_PAL_60 = 7,	/* PAL 60          525-line    */
+	TVP5146_MODE_AUTO_SQP = 8,	/* autoswitch mode (default)   */
+	TVP5146_MODE_NTSC_SQP = 9,	/* (M, J) NTSC      525-line   */
+	TVP5146_MODE_PAL_SQP = 0xA,	/* (B, D, G, H, I, N) PAL      */
+	TVP5146_MODE_PAL_M_SQP = 0xB,	/* (M) PAL          525-line   */
+	TVP5146_MODE_PAL_CN_SQP = 0xC,	/* (Combination-N) PAL         */
+	TVP5146_MODE_NTSC_443_SQP = 0xD,/* NTSC 4.43        525-line   */
+	TVP5146_MODE_SECAM_SQP = 0xE,	/* SECAM                       */
+	TVP5146_MODE_PAL_60_SQP = 0xF,	/* PAL 60          525-line    */
+} tvp5146_mode;
+
+typedef struct {
+	tvp5146_mode mode;
+	int amuxmode;
+	int enablebt656sync;
+} tvp5146_params;
+
+#ifdef __KERNEL__
+
+typedef struct {
+	int agc_enable;
+	tvp5146_mode video_std;
+	int brightness;
+	int contrast;
+	int saturation;
+	int hue;
+	int field_rate;		/* 50 or 60 in Hz */
+	int lost_lock;
+	int csubc_lock;
+	int v_lock;
+	int h_lock;
+} tvp5146_status;
+
+typedef unsigned int tvp5146_cmd;
+
+/* commands for setup the decoder */
+#define TVP5146_SET_AMUXMODE        4
+#define TVP5146_SET_BRIGHTNESS      5
+#define TVP5146_SET_CONTRAST        6
+#define TVP5146_SET_HUE             7
+#define TVP5146_SET_SATURATION      8
+#define TVP5146_SET_AGC             9
+#define TVP5146_SET_VIDEOSTD        10
+#define TVP5146_CLR_LOSTLOCK        11
+#define TVP5146_CONFIG              12
+#define TVP5146_RESET               13
+#define TVP5146_POWERDOWN           14
+
+#define TVP5146_GET_STATUS          15
+#define TVP5146_GET_STD             16
+
+#define TVP5146_I2C_ADDR (0xBA >> 1)
+
+extern int tvp5146_ctrl(tvp5146_cmd cmd, void *arg);
+
+#endif
+#endif
diff --git a/include/media/video-buf.h b/include/media/video-buf.h
index d6f0794..079845b 100644
--- a/include/media/video-buf.h
+++ b/include/media/video-buf.h
@@ -193,6 +193,8 @@
 			  struct videobuf_buffer *vb);
 	void (*buf_release)(struct videobuf_queue *q,
 			    struct videobuf_buffer *vb);
+	void (*buf_config)(struct videobuf_queue *q,
+			unsigned int count);
 
 	/* Helper operations - device dependent.
 	 * If null, videobuf_init defaults all to PCI handling
@@ -203,6 +205,11 @@
 	vb_map_sg_t	*vb_unmap_sg;
 };
 
+enum videobuf_buf_type {
+	VIDEOBUF_BUF_LINEAR = 1,
+	VIDEOBUF_BUF_FRAGMENTED = 2,
+};
+
 struct videobuf_queue {
 	struct mutex               lock;
 	spinlock_t                 *irqlock;
@@ -219,6 +226,7 @@
 	/* capture via mmap() + ioctl(QBUF/DQBUF) */
 	unsigned int               streaming;
 	struct list_head           stream;
+	enum videobuf_buf_type     buf_type;
 
 	/* capture via read() */
 	unsigned int               reading;
@@ -232,7 +240,8 @@
 void* videobuf_alloc(unsigned int size);
 int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr);
 int videobuf_iolock(struct videobuf_queue* q, struct videobuf_buffer *vb,
-		struct v4l2_framebuffer *fbuf);
+		    struct v4l2_framebuffer *fbuf);
+int videobuf_set_buftype(struct videobuf_queue *q, enum videobuf_buf_type type);
 
 /* Maps fops to PCI stuff */
 void videobuf_queue_pci(struct videobuf_queue* q);
diff --git a/include/sound/davincisound.h b/include/sound/davincisound.h
new file mode 100644
index 0000000..442a6fa
--- /dev/null
+++ b/include/sound/davincisound.h
@@ -0,0 +1,23 @@
+/*
+ * include/sound/davincisound.h
+ *
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ * --------
+ *  2006-03-29 Sudhakar - Created
+ */
+
+#include <linux/soundcard.h>
+
+#define SOUND_MIXER_MICBIAS		_IOC_NR(SOUND_MIXER_PRIVATE1)
+#define SOUND_MIXER_READ_MICBIAS	_SIOR ('M', SOUND_MIXER_MICBIAS, int)
+#define SOUND_MIXER_WRITE_MICBIAS	SOUND_MIXER_PRIVATE1
diff --git a/include/video/davincifb.h b/include/video/davincifb.h
new file mode 100644
index 0000000..f464004
--- /dev/null
+++ b/include/video/davincifb.h
@@ -0,0 +1,442 @@
+/*
+ * include/video/davincifb.h
+ *
+ * Framebuffer driver for Texas Instruments DM644x display controller.
+ *
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ * Rishi Bhattacharya <support@ti.com>
+ *
+ * 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 _DAVINCIFB_H_
+#define _DAVINCIFB_H_
+
+#include <asm/arch/io.h>
+
+/* Base registers */
+#define	VPBE_REG_BASE				IO_ADDRESS(0x01c72780)
+#define	VENC_REG_BASE				IO_ADDRESS(0x01c72400)
+#define	OSD_REG_BASE				IO_ADDRESS(0x01c72600)
+#define OSD_REG_SIZE				0x00000180
+
+/* VPBE Global Registers */
+#define	VPBE_PID				(VPBE_BASE + 0x0)
+#define	VPBE_PCR				(VPBE_BASE + 0x4)
+
+/* VPSS Clock Control Register */
+#define	VPSS_CLKCTL				IO_ADDRESS(0x01c40044)
+
+/* VPBE Video Encoder / Digital LCD Subsystem Registers (VENC) */
+#define	VENC_VMOD				(VENC_REG_BASE + 0x00)
+#define	VENC_VIDCTL				(VENC_REG_BASE + 0x04)
+#define	VENC_VDPRO				(VENC_REG_BASE + 0x08)
+#define	VENC_SYNCCTL				(VENC_REG_BASE + 0x0C)
+#define	VENC_HSPLS				(VENC_REG_BASE + 0x10)
+#define	VENC_VSPLS				(VENC_REG_BASE + 0x14)
+#define	VENC_HINT				(VENC_REG_BASE + 0x18)
+#define	VENC_HSTART				(VENC_REG_BASE + 0x1C)
+#define	VENC_HVALID				(VENC_REG_BASE + 0x20)
+#define	VENC_VINT				(VENC_REG_BASE + 0x24)
+#define	VENC_VSTART				(VENC_REG_BASE + 0x28)
+#define	VENC_VVALID				(VENC_REG_BASE + 0x2C)
+#define	VENC_HSDLY				(VENC_REG_BASE + 0x30)
+#define	VENC_VSDLY				(VENC_REG_BASE + 0x34)
+#define	VENC_YCCCTL				(VENC_REG_BASE + 0x38)
+#define	VENC_RGBCTL				(VENC_REG_BASE + 0x3C)
+#define	VENC_RGBCLP				(VENC_REG_BASE + 0x40)
+#define	VENC_LINECTL				(VENC_REG_BASE + 0x44)
+#define	VENC_CULLLINE				(VENC_REG_BASE + 0x48)
+#define	VENC_LCDOUT				(VENC_REG_BASE + 0x4C)
+#define	VENC_BRTS				(VENC_REG_BASE + 0x50)
+#define	VENC_BRTW				(VENC_REG_BASE + 0x54)
+#define	VENC_ACCTL				(VENC_REG_BASE + 0x58)
+#define	VENC_PWMP				(VENC_REG_BASE + 0x5C)
+#define	VENC_PWMW				(VENC_REG_BASE + 0x60)
+#define	VENC_DCLKCTL				(VENC_REG_BASE + 0x64)
+#define	VENC_DCLKPTN0				(VENC_REG_BASE + 0x68)
+#define	VENC_DCLKPTN1				(VENC_REG_BASE + 0x6C)
+#define	VENC_DCLKPTN2				(VENC_REG_BASE + 0x70)
+#define	VENC_DCLKPTN3				(VENC_REG_BASE + 0x74)
+#define	VENC_DCLKPTN0A				(VENC_REG_BASE + 0x78)
+#define	VENC_DCLKPTN1A				(VENC_REG_BASE + 0x7C)
+#define	VENC_DCLKPTN2A				(VENC_REG_BASE + 0x80)
+#define	VENC_DCLKPTN3A				(VENC_REG_BASE + 0x84)
+#define	VENC_DCLKHS				(VENC_REG_BASE + 0x88)
+#define	VENC_DCLKHSA				(VENC_REG_BASE + 0x8C)
+#define	VENC_DCLKHR				(VENC_REG_BASE + 0x90)
+#define	VENC_DCLKVS				(VENC_REG_BASE + 0x94)
+#define	VENC_DCLKVR				(VENC_REG_BASE + 0x98)
+#define	VENC_CAPCTL				(VENC_REG_BASE + 0x9C)
+#define	VENC_CAPDO				(VENC_REG_BASE + 0xA0)
+#define	VENC_CAPDE				(VENC_REG_BASE + 0xA4)
+#define	VENC_ATR0				(VENC_REG_BASE + 0xA8)
+#define	VENC_ATR1				(VENC_REG_BASE + 0xAC)
+#define	VENC_ATR2				(VENC_REG_BASE + 0xB0)
+#define	VENC_EPSON_LCDCTL			(VENC_REG_BASE + 0xB4)
+#define	VENC_CASIO_LCDCTL			(VENC_REG_BASE + 0xB4)
+#define	VENC_UDISP_LCDCT			(VENC_REG_BASE + 0xB4)
+#define	VENC_STN_LCDCT				(VENC_REG_BASE + 0xB4)
+#define	VENC_VSTAT				(VENC_REG_BASE + 0xB8)
+#define	VENC_RAMADR				(VENC_REG_BASE + 0xBC)
+#define	VENC_RAMPORT				(VENC_REG_BASE + 0xC0)
+#define	VENC_DACTST				(VENC_REG_BASE + 0xC4)
+#define	VENC_YCOLVL				(VENC_REG_BASE + 0xC8)
+#define	VENC_SCPROG				(VENC_REG_BASE + 0xCC)
+#define	VENC_CVBS				(VENC_REG_BASE + 0xDC)
+#define	VENC_CMPNT				(VENC_REG_BASE + 0xE0)
+#define	VENC_ETMG0				(VENC_REG_BASE + 0xE4)
+#define	VENC_ETMG1				(VENC_REG_BASE + 0xE8)
+#define	VENC_ETMG2				(VENC_REG_BASE + 0xEC)
+#define	VENC_ETMG3				(VENC_REG_BASE + 0xF0)
+#define	VENC_DACSEL				(VENC_REG_BASE + 0xF4)
+#define	VENC_ARGBX0				(VENC_REG_BASE + 0x100)
+#define	VENC_ARGBX1				(VENC_REG_BASE + 0x104)
+#define	VENC_ARGBX2				(VENC_REG_BASE + 0x108)
+#define	VENC_ARGBX3				(VENC_REG_BASE + 0x10C)
+#define	VENC_ARGBX4				(VENC_REG_BASE + 0x110)
+#define	VENC_DRGBX0				(VENC_REG_BASE + 0x114)
+#define	VENC_DRGBX1				(VENC_REG_BASE + 0x118)
+#define	VENC_DRGBX2				(VENC_REG_BASE + 0x11C)
+#define	VENC_DRGBX3				(VENC_REG_BASE + 0x120)
+#define	VENC_DRGBX4				(VENC_REG_BASE + 0x124)
+#define	VENC_VSTARTA				(VENC_REG_BASE + 0x128)
+#define	VENC_OSDCLK0				(VENC_REG_BASE + 0x12C)
+#define	VENC_OSDCLK1				(VENC_REG_BASE + 0x130)
+#define	VENC_HVLDCL0				(VENC_REG_BASE + 0x134)
+#define	VENC_HVLDCL1				(VENC_REG_BASE + 0x138)
+#define	VENC_OSDHAD				(VENC_REG_BASE + 0x13C)
+
+#define VID0	0
+#define VID1	1
+#define OSD0	3
+#define OSD1	4
+
+/* VPBE On-Screen Display Subsystem Registers (OSD) */
+#define	OSD_MODE				(OSD_REG_BASE + 0x00)
+#define	OSD_VIDWINMD				(OSD_REG_BASE + 0x04)
+#define	OSD_OSDWIN0MD				(OSD_REG_BASE + 0x08)
+#define	OSD_OSDWIN1MD				(OSD_REG_BASE + 0x0C)
+#define	OSD_OSDATRMD				(OSD_REG_BASE + 0x0C)
+#define	OSD_RECTCUR				(OSD_REG_BASE + 0x10)
+#define		OSD_WINOFST(i)			(OSD_REG_BASE + 0x18 + (i)*0x4)
+#define	OSD_VIDWIN0OFST				(OSD_REG_BASE + 0x18)
+#define	OSD_VIDWIN1OFST				(OSD_REG_BASE + 0x1C)
+#define	OSD_OSDWIN0OFST				(OSD_REG_BASE + 0x20)
+#define	OSD_OSDWIN1OFST				(OSD_REG_BASE + 0x24)
+#define		OSD_WINADR(i)			(OSD_REG_BASE + 0x2C + (i)*0x4)
+#define	OSD_VIDWIN0ADR				(OSD_REG_BASE + 0x2C)
+#define	OSD_VIDWIN1ADR				(OSD_REG_BASE + 0x30)
+#define	OSD_OSDWIN0ADR				(OSD_REG_BASE + 0x38)
+#define	OSD_OSDWIN1ADR				(OSD_REG_BASE + 0x3C)
+#define	OSD_BASEPX				(OSD_REG_BASE + 0x40)
+#define	OSD_BASEPY				(OSD_REG_BASE + 0x44)
+#define	OSD_WINXP(i)				(OSD_REG_BASE + 0x48 + (i)*0x10)
+#define	OSD_WINYP(i)				(OSD_REG_BASE + 0x4C + (i)*0x10)
+#define	OSD_WINXL(i)				(OSD_REG_BASE + 0x50 + (i)*0x10)
+#define	OSD_WINYL(i)				(OSD_REG_BASE + 0x54 + (i)*0x10)
+#define	OSD_VIDWIN0XP				(OSD_REG_BASE + 0x48)
+#define	OSD_VIDWIN0YP				(OSD_REG_BASE + 0x4C)
+#define	OSD_VIDWIN0XL				(OSD_REG_BASE + 0x50)
+#define	OSD_VIDWIN0YL				(OSD_REG_BASE + 0x54)
+#define	OSD_VIDWIN1XP				(OSD_REG_BASE + 0x58)
+#define	OSD_VIDWIN1YP				(OSD_REG_BASE + 0x5C)
+#define	OSD_VIDWIN1XL				(OSD_REG_BASE + 0x60)
+#define	OSD_VIDWIN1YL				(OSD_REG_BASE + 0x64)
+#define	OSD_OSDWIN0XP				(OSD_REG_BASE + 0x68)
+#define	OSD_OSDWIN0YP				(OSD_REG_BASE + 0x6C)
+#define	OSD_OSDWIN0XL				(OSD_REG_BASE + 0x70)
+#define	OSD_OSDWIN0YL				(OSD_REG_BASE + 0x74)
+#define	OSD_OSDWIN1XP				(OSD_REG_BASE + 0x78)
+#define	OSD_OSDWIN1YP				(OSD_REG_BASE + 0x7C)
+#define	OSD_OSDWIN1XL				(OSD_REG_BASE + 0x80)
+#define	OSD_OSDWIN1YL				(OSD_REG_BASE + 0x84)
+#define	OSD_CURXP				(OSD_REG_BASE + 0x88)
+#define	OSD_CURYP				(OSD_REG_BASE + 0x8C)
+#define	OSD_CURXL				(OSD_REG_BASE + 0x90)
+#define	OSD_CURYL				(OSD_REG_BASE + 0x94)
+#define	OSD_W0BMP01				(OSD_REG_BASE + 0xA0)
+#define	OSD_W0BMP23				(OSD_REG_BASE + 0xA4)
+#define	OSD_W0BMP45				(OSD_REG_BASE + 0xA8)
+#define	OSD_W0BMP67				(OSD_REG_BASE + 0xAC)
+#define	OSD_W0BMP89				(OSD_REG_BASE + 0xB0)
+#define	OSD_W0BMPAB				(OSD_REG_BASE + 0xB4)
+#define	OSD_W0BMPCD				(OSD_REG_BASE + 0xB8)
+#define	OSD_W0BMPEF				(OSD_REG_BASE + 0xBC)
+#define	OSD_W1BMP0				(OSD_REG_BASE + 0xC0)
+#define	OSD_W1BMP2				(OSD_REG_BASE + 0xC4)
+#define	OSD_W1BMP4				(OSD_REG_BASE + 0xC8)
+#define	OSD_W1BMP6				(OSD_REG_BASE + 0xCC)
+#define	OSD_W1BMP8				(OSD_REG_BASE + 0xD0)
+#define	OSD_W1BMPA				(OSD_REG_BASE + 0xD4)
+#define	OSD_W1BMPC				(OSD_REG_BASE + 0xD8)
+#define	OSD_W1BMPE				(OSD_REG_BASE + 0xDC)
+#define	OSD_TI_TES				(OSD_REG_BASE + 0xE0)
+#define	OSD_MISCCT				(OSD_REG_BASE + 0xE8)
+#define	OSD_CLUTRAMYC				(OSD_REG_BASE + 0xEC)
+#define	OSD_CLUTRAMC				(OSD_REG_BASE + 0xF0)
+#define	OSD_TRANSPVA				(OSD_REG_BASE + 0xF0)
+#define	OSD_PPVWIN0AD				(OSD_REG_BASE + 0xFC)
+
+/* bit definitions */
+#define VPBE_PCR_VENC_DIV			(1 << 1)
+#define VPBE_PCR_CLK_OFF			(1 << 0)
+#define VENC_VMOD_VDMD_SHIFT			12
+#define VENC_VMOD_VDMD_YCBCR16			0
+#define VENC_VMOD_VDMD_YCBCR8			1
+#define VENC_VMOD_VDMD_RGB666			2
+#define VENC_VMOD_VDMD_RGB8			3
+#define VENC_VMOD_VDMD_EPSON			4
+#define VENC_VMOD_VDMD_CASIO			5
+#define VENC_VMOD_VDMD_UDISPQVGA		6
+#define VENC_VMOD_VDMD_STNLCD			7
+#define VENC_VMOD_VDMD				(7 << 12)
+#define VENC_VMOD_ITLCL				(1 << 11)
+#define VENC_VMOD_ITLC				(1 << 10)
+#define VENC_VMOD_NSIT				(1 << 9)
+#define VENC_VMOD_HDMD				(1 << 8)
+#define VENC_VMOD_TVTYP				(3 << 6)
+#define VENC_VMOD_SLAVE				(1 << 5)
+#define VENC_VMOD_VMD				(1 << 4)
+#define VENC_VMOD_BLNK				(1 << 3)
+#define VENC_VMOD_VIE				(1 << 1)
+#define VENC_VMOD_VENC				(1 << 0)
+/* other VENC registers' bit positions not defined yet */
+
+#define	OSD_MODE_CS				(1 << 15)
+#define	OSD_MODE_OVRSZ				(1 << 14)
+#define	OSD_MODE_OHRSZ				(1 << 13)
+#define	OSD_MODE_EF				(1 << 12)
+#define	OSD_MODE_VVRSZ				(1 << 11)
+#define	OSD_MODE_VHRSZ				(1 << 10)
+#define	OSD_MODE_FSINV				(1 << 9)
+#define	OSD_MODE_BCLUT				(1 << 8)
+#define	OSD_MODE_CABG				(0xff << 0)
+#define	OSD_MODE_CABG_SHIFT			0
+
+#define	OSD_VIDWINMD_VFINV			(1 << 15)
+#define	OSD_VIDWINMD_V1EFC			(1 << 14)
+#define	OSD_VIDWINMD_VHZ1			(3 << 12)
+#define	OSD_VIDWINMD_VHZ1_SHIFT			12
+#define	OSD_VIDWINMD_VVZ1			(3 << 10)
+#define	OSD_VIDWINMD_VVZ1_SHIFT			10
+#define	OSD_VIDWINMD_VFF1			(1 << 9)
+#define	OSD_VIDWINMD_ACT1			(1 << 8)
+#define	OSD_VIDWINMD_V0EFC			(1 << 6)
+#define	OSD_VIDWINMD_VHZ0			(3 << 4)
+#define	OSD_VIDWINMD_VHZ0_SHIFT			4
+#define	OSD_VIDWINMD_VVZ0			(3 << 2)
+#define	OSD_VIDWINMD_VVZ0_SHIFT			2
+#define	OSD_VIDWINMD_VFF0			(1 << 1)
+#define	OSD_VIDWINMD_ACT0			(1 << 0)
+
+#define	OSD_OSDWIN0MD_ATN0E			(1 << 14)
+#define	OSD_OSDWIN0MD_RGB0E			(1 << 13)
+#define	OSD_OSDWIN0MD_CLUTS0			(1 << 12)
+#define	OSD_OSDWIN0MD_OHZ0			(3 << 10)
+#define	OSD_OSDWIN0MD_OHZ0_SHIFT		10
+#define	OSD_OSDWIN0MD_OVZ0			(3 << 8)
+#define	OSD_OSDWIN0MD_OVZ0_SHIFT		8
+#define	OSD_OSDWIN0MD_BMW0			(3 << 6)
+#define	OSD_OSDWIN0MD_BMW0_SHIFT		6
+#define	OSD_OSDWIN0MD_BLND0			(3 << 3)
+#define	OSD_OSDWIN0MD_BLND0_SHIFT		3
+#define	OSD_OSDWIN0MD_TE0			(1 << 2)
+#define	OSD_OSDWIN0MD_OFF0			(1 << 1)
+#define	OSD_OSDWIN0MD_OACT0			(1 << 0)
+
+#define	OSD_OSDWIN1MD_OASW			(1 << 15)
+#define	OSD_OSDWIN1MD_ATN1E			(1 << 14)
+#define	OSD_OSDWIN1MD_RGB1E			(1 << 13)
+#define	OSD_OSDWIN1MD_CLUTS1			(1 << 12)
+#define	OSD_OSDWIN1MD_OHZ1			(3 << 10)
+#define	OSD_OSDWIN1MD_OHZ1_SHIFT		10
+#define	OSD_OSDWIN1MD_OVZ1			(3 << 8)
+#define	OSD_OSDWIN1MD_OVZ1_SHIFT		8
+#define	OSD_OSDWIN1MD_BMW1			(3 << 6)
+#define	OSD_OSDWIN1MD_BMW1_SHIFT		6
+#define	OSD_OSDWIN1MD_BLND1			(3 << 3)
+#define	OSD_OSDWIN1MD_BLND1_SHIFT		3
+#define	OSD_OSDWIN1MD_TE1			(1 << 2)
+#define	OSD_OSDWIN1MD_OFF1			(1 << 1)
+#define	OSD_OSDWIN1MD_OACT1			(1 << 0)
+
+
+#define	OSD_OSDATRMD_OASW			(1 << 15)
+#define	OSD_OSDATRMD_OHZA			(3 << 10)
+#define	OSD_OSDATRMD_OHZA_SHIFT			10
+#define	OSD_OSDATRMD_OVZA			(3 << 8)
+#define	OSD_OSDATRMD_OVZA_SHIFT			8
+#define	OSD_OSDATRMD_BLNKINT			(3 << 6)
+#define	OSD_OSDATRMD_BLNKINT_SHIFT		6
+#define	OSD_OSDATRMD_OFFA			(1 << 1)
+#define	OSD_OSDATRMD_BLNK			(1 << 0)
+
+#define	OSD_RECTCUR_RCAD			(0xff << 8)
+#define	OSD_RECTCUR_RCAD_SHIFT			8
+#define	OSD_RECTCUR_CLUTSR			(1 << 7)
+#define	OSD_RECTCUR_RCHW			(3 << 4)
+#define	OSD_RECTCUR_RCHW_SHIFT			4
+#define	OSD_RECTCUR_RCVW			(3 << 1)
+#define	OSD_RECTCUR_RCVW_SHIFT			1
+#define	OSD_RECTCUR_RCACT			(1 << 0)
+
+#define	OSD_VIDWIN0OFST_V0LO			(0x1ff << 0)
+#define	OSD_VIDWIN0OFST_V0LO_SHIFT		0
+#define	OSD_VIDWIN1OFST_V1LO			(0x1ff << 0)
+#define	OSD_VIDWIN1OFST_V1LO_SHIFT		0
+#define	OSD_OSDWIN0OFST_O0LO			(0x1ff << 0)
+#define	OSD_OSDWIN0OFST_O0LO_SHIFT		0
+#define	OSD_OSDWIN1OFST_O1LO			(0x1ff << 0)
+#define	OSD_OSDWIN1OFST_O1LO_SHIFT		0
+#define	OSD_BASEPX_BPX				(0x3ff << 0)
+#define	OSD_BASEPX_BPX_SHIFT			0
+#define	OSD_BASEPY_BPY				(0x1ff << 0)
+#define	OSD_BASEPY_BPY_SHIFT			0
+#define	OSD_VIDWIN0XP_V0X			(0x3ff << 0)
+#define	OSD_VIDWIN0XP_V0X_SHIFT			0
+#define	OSD_VIDWIN0YP_V0Y			(0x1ff << 0)
+#define	OSD_VIDWIN0YP_V0Y_SHIFT			0
+#define	OSD_VIDWIN0XL_V0W			(0xfff << 0)
+#define	OSD_VIDWIN0XL_V0W_SHIFT			0
+#define	OSD_VIDWIN0YL_V0H			(0x7ff << 0)
+#define	OSD_VIDWIN0YL_V0H_SHIFT			0
+#define	OSD_VIDWIN1XP_V1X			(0x3ff << 0)
+#define	OSD_VIDWIN1XP_V1X_SHIFT			0
+#define	OSD_VIDWIN1YP_V1Y			(0x1ff << 0)
+#define	OSD_VIDWIN1YP_V1Y_SHIFT			0
+#define	OSD_VIDWIN1XL_V1W			(0xfff << 0)
+#define	OSD_VIDWIN1XL_V1W_SHIFT			0
+#define	OSD_VIDWIN1YL_V1H			(0x7ff << 0)
+#define	OSD_VIDWIN1YL_V1H_SHIFT			0
+#define	OSD_OSDWIN0XP_W0X			(0x3ff << 0)
+#define	OSD_OSDWIN0XP_W0X_SHIFT			0
+#define	OSD_OSDWIN0YP_W0Y			(0x1ff << 0)
+#define	OSD_OSDWIN0YP_W0Y_SHIFT			0
+#define	OSD_OSDWIN0XL_W0W			(0xfff << 0)
+#define	OSD_OSDWIN0XL_W0W_SHIFT			0
+#define	OSD_OSDWIN0YL_W0H			(0x7ff << 0)
+#define	OSD_OSDWIN0YL_W0H_SHIFT			0
+#define	OSD_OSDWIN1XP_W1X			(0x3ff << 0)
+#define	OSD_OSDWIN1XP_W1X_SHIFT			0
+#define	OSD_OSDWIN1YP_W1Y			(0x1ff << 0)
+#define	OSD_OSDWIN1YP_W1Y_SHIFT			0
+#define	OSD_OSDWIN1XL_W1W			(0xfff << 0)
+#define	OSD_OSDWIN1XL_W1W_SHIFT			0
+#define	OSD_OSDWIN1YL_W1H			(0x7ff << 0)
+#define	OSD_OSDWIN1YL_W1H_SHIFT			0
+#define	OSD_CURXP_RCSX				(0x3ff << 0)
+#define	OSD_CURXP_RCSX_SHIFT			0
+#define	OSD_CURYP_RCSY				(0x1ff << 0)
+#define	OSD_CURYP_RCSY_SHIFT			0
+#define	OSD_CURYL_RCSH				(0x7ff << 0)
+#define	OSD_CURYL_RCSH_SHIFT			0
+#define	OSD_W0BMP01_PAL01			(0xff << 8)
+#define	OSD_W0BMP01_PAL01_SHIFT			8
+#define	OSD_W0BMP01_PAL00			(0xff << 0)
+#define	OSD_W0BMP01_PAL00_SHIFT			0
+#define	OSD_W0BMP23_PAL03			(0xff << 8)
+#define	OSD_W0BMP23_PAL03_SHIFT			8
+#define	OSD_W0BMP23_PAL02			(0xff << 0)
+#define	OSD_W0BMP23_PAL02_SHIFT			0
+#define	OSD_W0BMP45_PAL05			(0xff << 8)
+#define	OSD_W0BMP45_PAL05_SHIFT			8
+#define	OSD_W0BMP45_PAL04			(0xff << 0)
+#define	OSD_W0BMP45_PAL04_SHIFT			0
+#define	OSD_W0BMP67_PAL07			(0xff << 8)
+#define	OSD_W0BMP67_PAL07_SHIFT			8
+#define	OSD_W0BMP67_PAL06			(0xff << 0)
+#define	OSD_W0BMP67_PAL06_SHIFT			0
+#define	OSD_W0BMP89_PAL09			(0xff << 8)
+#define	OSD_W0BMP89_PAL09_SHIFT			8
+#define	OSD_W0BMP89_PAL08			(0xff << 0)
+#define	OSD_W0BMP89_PAL08_SHIFT			0
+#define	OSD_W0BMPAB_PAL11			(0xff << 8)
+#define	OSD_W0BMPAB_PAL11_SHIFT			8
+#define	OSD_W0BMPAB_PAL10			(0xff << 0)
+#define	OSD_W0BMPAB_PAL10_SHIFT			0
+#define	OSD_W0BMPCD_PAL13			(0xff << 8)
+#define	OSD_W0BMPCD_PAL13_SHIFT			8
+#define	OSD_W0BMPCD_PAL12			(0xff << 0)
+#define	OSD_W0BMPCD_PAL12_SHIFT			0
+#define	OSD_W0BMPEF_PAL15			(0xff << 8)
+#define	OSD_W0BMPEF_PAL15_SHIFT			8
+#define	OSD_W0BMPEF_PAL14			(0xff << 0)
+#define	OSD_W0BMPEF_PAL14_SHIFT			0
+#define	OSD_W1BMP0_PAL01			(0xff << 8)
+#define	OSD_W1BMP0_PAL01_SHIFT			8
+#define	OSD_W1BMP0_PAL00			(0xff << 0)
+#define	OSD_W1BMP0_PAL00_SHIFT			0
+#define	OSD_W1BMP2_PAL03			(0xff << 8)
+#define	OSD_W1BMP2_PAL03_SHIFT			8
+#define	OSD_W1BMP2_PAL02			(0xff << 0)
+#define	OSD_W1BMP2_PAL02_SHIFT			0
+#define	OSD_W1BMP4_PAL05			(0xff << 8)
+#define	OSD_W1BMP4_PAL05_SHIFT			8
+#define	OSD_W1BMP4_PAL04			(0xff << 0)
+#define	OSD_W1BMP4_PAL04_SHIFT			0
+#define	OSD_W1BMP6_PAL07			(0xff << 8)
+#define	OSD_W1BMP6_PAL07_SHIFT			8
+#define	OSD_W1BMP6_PAL06			(0xff << 0)
+#define	OSD_W1BMP6_PAL06_SHIFT			0
+#define	OSD_W1BMP8_PAL09			(0xff << 8)
+#define	OSD_W1BMP8_PAL09_SHIFT			8
+#define	OSD_W1BMP8_PAL08			(0xff << 0)
+#define	OSD_W1BMP8_PAL08_SHIFT			0
+#define	OSD_W1BMPA_PAL11			(0xff << 8)
+#define	OSD_W1BMPA_PAL11_SHIFT			8
+#define	OSD_W1BMPA_PAL10			(0xff << 0)
+#define	OSD_W1BMPA_PAL10_SHIFT			0
+#define	OSD_W1BMPC_PAL13			(0xff << 8)
+#define	OSD_W1BMPC_PAL13_SHIFT			8
+#define	OSD_W1BMPC_PAL12			(0xff << 0)
+#define	OSD_W1BMPC_PAL12_SHIFT			0
+#define	OSD_W1BMPE_PAL15			(0xff << 8)
+#define	OSD_W1BMPE_PAL15_SHIFT			8
+#define	OSD_W1BMPE_PAL14			(0xff << 0)
+#define	OSD_W1BMPE_PAL14_SHIFT			0
+
+#define	OSD_MISCCT_RGBEN			(1 << 7)
+#define	OSD_MISCCT_RGBWIN			(1 << 6)
+#define	OSD_MISCCT_TMON				(1 << 5)
+#define	OSD_MISCCT_RSEL				(1 << 4)
+#define	OSD_MISCCT_CPBSY			(1 << 3)
+#define	OSD_MISCCT_PPSW				(1 << 2)
+#define	OSD_MISCCT_PPRV				(1 << 1)
+
+#define	OSD_CLUTRAMY_Y				(0xff << 8)
+#define	OSD_CLUTRAMY_Y_SHIFT			8
+#define	OSD_CLUTRAMY_CB				(0xff << 0)
+#define	OSD_CLUTRAMY_CB_SHIFT			0
+#define	OSD_CLUTRAM_CR				(0xff << 8)
+#define	OSD_CLUTRAM_CR_SHIFT			8
+#define	OSD_CLUTRAM_CADDR			(0xff << 0)
+#define	OSD_CLUTRAM_CADDR_SHIFT			0
+#define	OSD_TRANSPVA_RGBTRANS			(0xff << 0)
+#define	OSD_TRANSPVA_RGBTRANS_SHIFT		0
+
+
+#define LCD             0
+#define NTSC            1
+#define PAL             2
+
+#define COMPOSITE       1
+#define SVIDEO          2
+#define COMPONENT       3
+#define RGB             4
+
+/* define the custom FBIO_WAITFORVSYNC ioctl */
+#define FBIO_WAITFORVSYNC	_IOW('F', 0x20, u_int32_t)
+#define FBIO_SETATTRIBUTE       _IOW('F', 0x21, struct fb_fillrect)
+#define FBIO_SETPOSX		_IOW('F', 0x22, u_int32_t)
+#define FBIO_SETPOSY		_IOW('F', 0x23, u_int32_t)
+struct zoom_params
+{
+	u_int32_t window_id;
+	u_int32_t zoom_h;
+	u_int32_t zoom_v;
+};
+#define FBIO_SETZOOM		_IOW('F', 0x24, struct zoom_params)
+#define FBIO_GETSTD		_IOR('F', 0x25, u_int32_t)
+#endif /* _DAVINCIFB_H_ */
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index af37cd0..a8f2055 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -654,3 +654,35 @@
 	int "DAC channel"
 	default "1"
 	depends on SOUND_SH_DAC_AUDIO
+
+config SOUND_DAVINCI
+	tristate "DaVinci Sound Driver"
+	depends on ARCH_DAVINCI && SOUND_PRIME!=n && SOUND
+	---help---
+	DaVinci Sound driver
+
+config SOUND_DAVINCI_AIC33
+       tristate "AIC33 Stereo Codec"
+       depends on SOUND_DAVINCI
+       select SENSORS_TLV320AIC33
+       ---help---
+         If you say yes here you get support for the I2C control
+         interface for Texas Instruments TLV320AIC33 audio codec.
+
+menu "DaVinci Audio Options"
+	depends on SOUND_DAVINCI
+
+choice
+	prompt "Mono/Stereo Jack Support"
+	default MONOSTEREO_SAMEJACK
+
+config MONOSTEREO_DIFFJACK
+	bool "Mono and Stereo on different jacks"
+
+config MONOSTEREO_SAMEJACK
+	bool "Mono and Stereo on same jacks"
+
+endchoice
+
+endmenu
+
diff --git a/sound/oss/Makefile b/sound/oss/Makefile
index 1f81a2f..9914451 100644
--- a/sound/oss/Makefile
+++ b/sound/oss/Makefile
@@ -12,6 +12,9 @@
 obj-$(CONFIG_SOUND_OMAP_TSC2101)+= omap-audio-tsc2101.o
 obj-$(CONFIG_SOUND_OMAP_AIC23)  += omap-audio-aic23.o
 
+obj-$(CONFIG_SOUND_DAVINCI)	+= davinci-audio-dma-intfc.o davinci-audio.o
+obj-$(CONFIG_SOUND_DAVINCI_AIC33) += davinci-audio-aic33.o
+
 # Please leave it as is, cause the link order is significant !
 
 obj-$(CONFIG_SOUND_SH_DAC_AUDIO)	+= sh_dac_audio.o
diff --git a/sound/oss/davinci-aic33.h b/sound/oss/davinci-aic33.h
new file mode 100644
index 0000000..768469b
--- /dev/null
+++ b/sound/oss/davinci-aic33.h
@@ -0,0 +1,246 @@
+/*
+ * linux/sound/oss/davinci-aic33.h
+ *
+ * Glue driver for AIC33 for Davinci processors
+ *
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *  -------
+ *  2005-10-18 Rishi Bhattacharya - Support for AIC33 codec and Davinci DM644x Processor
+ */
+
+#ifndef __ASM_ARCH_AIC33_H
+#define __ASM_ARCH_AIC33_H
+
+/* Codec TLV320AIC33 */
+#define REGISTER_ADDR0  0x00
+#define REGISTER_ADDR1          0x01
+#define REGISTER_ADDR2          0x02
+#define REGISTER_ADDR3          0x03
+#define REGISTER_ADDR4          0x04
+#define REGISTER_ADDR5          0x05
+#define REGISTER_ADDR6          0x06
+#define REGISTER_ADDR7          0x07
+#define REGISTER_ADDR8          0x08
+#define REGISTER_ADDR9          0x09
+#define REGISTER_ADDR10         0x0A
+#define REGISTER_ADDR11         0x0B
+#define REGISTER_ADDR12         0x0C
+#define REGISTER_ADDR15         0x0F
+#define REGISTER_ADDR16         0x10
+#define REGISTER_ADDR17         0x11
+#define REGISTER_ADDR18         0x12
+#define REGISTER_ADDR19         0x13
+#define REGISTER_ADDR20         0x14
+#define REGISTER_ADDR21         0x15
+#define REGISTER_ADDR22         0x16
+#define REGISTER_ADDR23         0x17
+#define REGISTER_ADDR24         0x18
+#define REGISTER_ADDR25         0x19
+#define REGISTER_ADDR26         0x1A
+#define REGISTER_ADDR27         0x1B
+#define REGISTER_ADDR28         0x1C
+#define REGISTER_ADDR29         0x1D
+#define REGISTER_ADDR30         0x1E
+#define REGISTER_ADDR31         0x1F
+#define REGISTER_ADDR32         0x20
+#define REGISTER_ADDR33         0x21
+#define REGISTER_ADDR37         0x25
+#define REGISTER_ADDR38         0x26
+#define REGISTER_ADDR40         0x28
+#define REGISTER_ADDR41         0x29
+#define REGISTER_ADDR43         0x2B
+#define REGISTER_ADDR44         0x2C
+#define REGISTER_ADDR45         0x2D
+#define REGISTER_ADDR46         0x2E
+#define REGISTER_ADDR47         0x2F
+#define REGISTER_ADDR51         0x33
+#define REGISTER_ADDR58         0x3A
+#define REGISTER_ADDR64         0x40
+#define REGISTER_ADDR65         0x41
+#define REGISTER_ADDR73         0x49
+#define REGISTER_ADDR74         0x4A
+#define REGISTER_ADDR75         0x4B
+#define REGISTER_ADDR76         0x4C
+#define REGISTER_ADDR77         0x4D
+#define REGISTER_ADDR78         0x4E
+#define REGISTER_ADDR79         0x4F
+#define REGISTER_ADDR80         0x50
+#define REGISTER_ADDR81         0x51
+#define REGISTER_ADDR82         0x52
+#define REGISTER_ADDR83         0x53
+#define REGISTER_ADDR84         0x54
+#define REGISTER_ADDR85         0x55
+#define REGISTER_ADDR86         0x56
+#define REGISTER_ADDR87         0x57
+#define REGISTER_ADDR88         0x58
+#define REGISTER_ADDR89         0x59
+#define REGISTER_ADDR90         0x5A
+#define REGISTER_ADDR91         0x5B
+#define REGISTER_ADDR92         0x5C
+#define REGISTER_ADDR93         0x5D
+#define REGISTER_ADDR94         0x5E
+
+// Page Select register 0
+#define PAGE_SELECT0            0
+#define PAGE_SELECT1            1
+
+// Software reset register 1
+#define SOFT_RESET              0x80
+
+// Codec sample rate select register 2
+#define ADC_FS_MAX              0xA0
+#define ADC_FS_MIN              0x00
+
+#define DAC_FS_MAX              0x0A
+#define DAC_FS_MIN              0x00
+
+// PLL Programming registerA 3
+#define PLL_ENABLE              0x80
+
+// Codec Datapath setup register 7
+#define FS_REF_44_1             0x80
+#define FS_REF_DEFAULT_48       0x00
+#define ADC_DUAL_RATE_MODE      0x40
+#define DAC_DUAL_RATE_MODE      0x20
+#define LDAC_LCHAN              0x08
+#define LDAC_RCHAN              0x10
+#define LDAC_MONO_MIX           0x18
+
+#define RDAC_RCHAN              0x02
+#define RDAC_LCHAN              0x04
+#define RDAC_MONO_MIX           0x06
+
+//Audio serial data interface control registerA 8
+#define BIT_CLK_MASTER          0x80
+#define WORD_CLK_MASTER         0x40
+#define DOUT_TRI_STATE          0x20
+#define CLK_TRANS_MASTER        0x10
+#define ENABLE_3D               0x04
+#define DM_ENABLE_128           0x01
+#define DM_ENABLE_64            0x02
+#define DM_ENABLE_32            0x03
+
+//Audio serial data interface control registerB 9
+#define DSP_MODE                0x40
+#define RJ_MODE                 0x80
+#define LJ_MODE                 0xC0
+#define WORD_LENGTH20           0x10
+#define WORD_LENGTH24           0x20
+#define WORD_LENGTH32           0x30
+#define BITCLOCK_256CLK_FRAME   0x08
+
+//Left/Right ADC PGA gain control register 15 & 16
+#define ADC_PGA_MUTE            0x80
+#define ADC_PGA_GAIN_MAX        0x78
+#define ADC_PGA_GAIN_MIN        0x00
+
+// MIC3L/R to left/right ADC control register 17 & 18
+#define ADCPGA_GAIN_MAX         0x00
+#define MIC3L_ADCPGA_GAIN_MIN   0x80
+#define MIC3L_ADCPGA_DISCONNECT 0xF0
+
+#define MIC3R_ADCPGA_GAIN_MIN   0x08
+#define MIC3R_ADCPGA_DISCONNECT 0x0F
+
+//LINE1L to left ADC Control Register 19
+#define DIFF_MODE               0x80
+#define LINE_ADCPGA_GAIN_MIN    0x40
+#define LINE_ADCPGA_DISCONNECT  0x78
+#define ADC_CHAN_ON             0x04
+#define ADCPGA_SOFT_STEP2FS     0x01
+#define ADCPGA_SOFT_STEP_OFF    0x03
+
+//LINE2L to left ADC Control Register 20
+#define ADC_WEAK_INPUT_BIAS     0x04
+
+//MICBIAS control register 25
+#define MICBIAS_OUTPUT_2_0V     0x40
+#define MICBIAS_OUTPUT_2_5V     0x80
+#define MICBIAS_OUTPUT_AVDD     0xC0
+
+//LEFT/RIGHT AGC Control registerA 26 & 29
+#define AGC_ENABLE              0x80
+#define AGC_TARGET_GAIN_MAX     0x00
+#define AGC_TARGET_GAIN_MIN     0x70
+#define AGC_ATTACK_TIME_11      0x04
+#define AGC_ATTACK_TIME_16      0x08
+#define AGC_ATTACK_TIME_20      0x0C
+#define AGC_DECAY_TIME_200      0x01
+#define AGC_DECAY_TIME_400      0x02
+#define AGC_DECAY_TIME_500      0x03
+
+//LEFT AGC Control registerB 27 & 30
+#define AGC_GAIN_ALLOWED_MAX    0xEE
+#define AGC_GAIN_ALLOWED_MIN    0x00
+
+//DAC Power and output driver control register 37
+#define LEFT_DAC_POWER_ON       0x80
+#define RIGHT_DAC_POWER_ON      0x40
+
+//High Power Output Stage Control Register 40
+#define LINE2L_BYPASS_DISABLE_DEFAULT    0x00
+#define LINE2LP_BYPASS_SINGLE            0x10
+#define LINE2LM_BYPASS_SINGLE            0x20
+#define LINE2LPM_BYPASS_DIFFERENTIAL     0x30
+
+#define LINE2R_BYPASS_DISABLE_DEFAULT    0x00
+#define LINE2RP_BYPASS_SINGLE            0x04
+#define LINE2RM_BYPASS_SINGLE            0x08
+#define LINE2RPM_BYPASS_DIFFERENTIAL     0x0C
+
+//DAC Output Switching Control Register 41
+#define LEFT_DAC_DEFAULT_L1     0x00
+#define LEFT_DAC_L2             0x80
+#define LEFT_DAC_L3             0x40
+#define RIGHT_DAC_DEFAULT_R1    0x00
+#define RIGHT_DAC_R2            0x08
+#define RIGHT_DAC_R3            0x04
+
+//LEFT/RIGHT DAC Digital volume control register 43 & 44
+#define DAC_CHAN_MUTE            0x80
+#define DAC_DIG_VOL_GAIN_MAX     0x00	// 0.0db
+#define DAC_DIG_VOL_GAIN_MIN     0x7F	// -63.5db
+
+//LINE2L to HPLOUT Volume Control Register 45
+#define LINE2L_HPLOUT_ROUTED              0x80
+
+//PGA_L to HPLOUT Volume Control Register 46
+#define PGAL_HPLOUT_ROUTED                0x80
+
+//any to LOP/M Volume control
+#define LOPM_ON                 0x80
+#define LOPM_VOL_GAIN_MAX       0x00	//0 db
+#define LOPM_VOL_GAIN_MIN       0x76	//-78.3 db is MUTE
+
+//MONO_LOP/M output level volume control register 79
+#define LOPM_POWER_ON            0x01
+#define LOPM_MUTE_OFF            0x08
+#define LOPM_OUTPUT_LEVEL_MIN    0x00
+#define LOPM_OUTPUT_LEVEL_MAX    0x90
+
+//Module Power Status Register 94
+#define HPROUT_DRIVER_POWER_ON           0x02
+
+#define LIV_MAX                         0x0077
+#define LIV_MIN                         0x0000
+
+#define LHV_MAX                         0x0077
+#define LHV_MIN                         0x0000
+
+#define LIG_MAX							0x0077
+#define LIG_MIN							0x0000
+
+#define LOG_MAX							0x007f
+#define LOG_MIN							0x0000
+
+#endif				/* __ASM_ARCH_AIC33_H */
diff --git a/sound/oss/davinci-audio-aic33.c b/sound/oss/davinci-audio-aic33.c
new file mode 100644
index 0000000..0a4a7c9
--- /dev/null
+++ b/sound/oss/davinci-audio-aic33.c
@@ -0,0 +1,1066 @@
+/*
+ * linux/sound/oss/davinci-audio-aic33.c
+ *
+ * Glue driver for AIC33 for Davinci processors
+ *
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *  -------
+ *  2005-10-18 Rishi Bhattacharya - Support for AIC33 codec and Davinci DM644x Processor
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/clk.h>
+#include <sound/davincisound.h>
+
+#include <asm/uaccess.h>
+#include <asm/hardware.h>
+#include <asm/io.h>
+#include <asm/mach-types.h>
+
+#include <asm/arch/mcbsp.h>
+#include "davinci-aic33.h"
+
+#include "davinci-audio.h"
+#include "davinci-audio-dma-intfc.h"
+
+#ifdef CONFIG_PROC_FS
+#include <linux/proc_fs.h>
+#define PROC_START_FILE "driver/aic33-audio-start"
+#define PROC_STOP_FILE  "driver/aic33-audio-stop"
+#endif
+
+//#define DEBUG
+
+#ifdef DEBUG
+#define DPRINTK(ARGS...)        do { \
+                                        printk("<%s>: ",__FUNCTION__);printk(ARGS); \
+                                } while (0)
+#else
+#define DPRINTK( x... )
+#endif
+
+#define CODEC_NAME               "AIC33"
+#define PLATFORM_NAME            "DAVINCI"
+
+/* Define to set the AIC33 as the master w.r.t McBSP */
+#define AIC33_MASTER
+
+/* codec clock frequency */
+#define MCLK  22
+
+/*
+ * AUDIO related MACROS
+ */
+#define DEFAULT_BITPERSAMPLE          16
+#define AUDIO_RATE_DEFAULT            48000
+#define DEFAULT_MCBSP_CLOCK           81000000
+
+/* Select the McBSP For Audio */
+#define AUDIO_MCBSP                   DAVINCI_MCBSP1
+
+#define REC_MASK                      (SOUND_MASK_LINE | SOUND_MASK_MIC)
+#define DEV_MASK                      (REC_MASK | SOUND_MASK_VOLUME)
+
+#define MONO			      1
+#define STEREO			      2
+
+#define SET_VOLUME                    1
+#define SET_LINE                      2
+#define SET_MIC                       3
+#define SET_RECSRC		      4
+#define SET_IGAIN		      5
+#define SET_OGAIN		      6
+#define SET_BASS                      7
+#define SET_TREBLE                    8
+#define SET_MICBIAS		      9
+
+#define DEFAULT_OUTPUT_VOLUME         50
+#define DEFAULT_INPUT_VOLUME          20	/* 0 ==> mute line in */
+#define DEFAULT_INPUT_IGAIN	      20
+#define DEFAULT_INPUT_OGAIN	      100
+
+#define OUTPUT_VOLUME_MIN             LHV_MIN
+#define OUTPUT_VOLUME_MAX             LHV_MAX
+#define OUTPUT_VOLUME_RANGE           (OUTPUT_VOLUME_MAX - OUTPUT_VOLUME_MIN)
+
+#define INPUT_VOLUME_MIN              LIV_MIN
+#define INPUT_VOLUME_MAX              LIV_MAX
+#define INPUT_VOLUME_RANGE            (INPUT_VOLUME_MAX - INPUT_VOLUME_MIN)
+
+#define INPUT_GAIN_MIN		      LIG_MIN
+#define INPUT_GAIN_MAX		      LIG_MAX
+#define INPUT_GAIN_RANGE	      (INPUT_GAIN_MAX - INPUT_GAIN_MIN)
+
+#define OUTPUT_GAIN_MIN		      LOG_MIN
+#define OUTPUT_GAIN_MAX		      LOG_MAX
+#define OUTPUT_GAIN_RANGE	      (INPUT_GAIN_MAX - INPUT_GAIN_MIN)
+
+#define NUMBER_SAMPLE_RATES_SUPPORTED 11
+
+static audio_stream_t output_stream = {
+	.id = "AIC33 out",
+	.dma_dev = DAVINCI_DMA_MCBSP1_TX,
+	.input_or_output = FMODE_WRITE
+};
+
+static audio_stream_t input_stream = {
+	.id = "AIC33 in",
+	.dma_dev = DAVINCI_DMA_MCBSP1_RX,
+	.input_or_output = FMODE_READ
+};
+
+static int audio_dev_id, mixer_dev_id;
+
+static struct aic33_local_info {
+	u8 volume;
+	u16 volume_reg;
+	u8 line;
+	u8 mic;
+	int recsrc;
+	int nochan;
+	u8 igain;
+	u8 ogain;
+	u8 micbias;
+	u8 bass;
+	u8 treble;
+	u16 input_volume_reg;
+	int mod_cnt;
+} aic33_local;
+
+struct sample_rate_reg_info {
+	u32 sample_rate;
+	u32 Fsref;
+	float divider;
+	u8 data;
+};
+
+/* To Store the default sample rate */
+static long audio_samplerate = AUDIO_RATE_DEFAULT;
+
+extern struct clk *davinci_mcbsp_get_clock(void);
+
+/* DAC USB-mode sampling rates*/
+static const struct sample_rate_reg_info
+ reg_info[NUMBER_SAMPLE_RATES_SUPPORTED] = {
+/*  {sample_rate, Fsref, divider, data}*/
+	{96000, 96000, 1, 0x00},
+	{88200, 88200, 1, 0x00},
+	{48000, 48000, 1, 0x00},
+	{44100, 44100, 1, 0x00},
+	{32000, 48000, 1.5, 0x11},
+	{24000, 96000, 4, 0x66},
+	{22050, 44100, 2, 0x22},
+	{16000, 48000, 3, 0x44},
+	{12000, 48000, 4, 0x66},
+	{11025, 44100, 4, 0x66},
+	{8000, 48000, 6, 0xAA},
+};
+
+static struct davinci_mcbsp_reg_cfg initial_config = {
+	.spcr2 = FREE | XINTM(3),
+	.spcr1 = RINTM(3),
+	.rcr2 = RWDLEN2(DAVINCI_MCBSP_WORD_16) | RDATDLY(1),
+	.rcr1 = RFRLEN1(1) | RWDLEN1(DAVINCI_MCBSP_WORD_16),
+	.xcr2 = XWDLEN2(DAVINCI_MCBSP_WORD_16) | XDATDLY(1) | XFIG,
+	.xcr1 = XFRLEN1(1) | XWDLEN1(DAVINCI_MCBSP_WORD_16),
+	.srgr1 = FWID(DEFAULT_BITPERSAMPLE - 1),
+	.srgr2 = FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1),
+#ifndef AIC33_MASTER
+	/* configure McBSP to be the I2S master */
+	.pcr0 = FSXM | FSRM | CLKXM | CLKRM | CLKXP | CLKRP,
+#else
+	/* configure McBSP to be the I2S slave */
+	.pcr0 = CLKXP | CLKRP,
+#endif				/* AIC33_MASTER */
+};
+
+static void davinci_aic33_initialize(void *dummy);
+static void davinci_aic33_shutdown(void *dummy);
+static int davinci_aic33_ioctl(struct inode *inode, struct file *file,
+			       uint cmd, ulong arg);
+static int davinci_aic33_probe(void);
+
+#ifdef MODULE
+static void davinci_aic33_remove(void);
+#endif
+
+static int davinci_aic33_suspend(void);
+static int davinci_aic33_resume(void);
+static inline void aic33_configure(void);
+static int mixer_open(struct inode *inode, struct file *file);
+static int mixer_release(struct inode *inode, struct file *file);
+static int mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
+		       ulong arg);
+
+#ifdef CONFIG_PROC_FS
+static int codec_start(char *buf, char **start, off_t offset, int count,
+		       int *eof, void *data);
+static int codec_stop(char *buf, char **start, off_t offset, int count,
+		      int *eof, void *data);
+#endif
+
+/* File Op structure for mixer */
+static struct file_operations davinci_mixer_fops = {
+	.open = mixer_open,
+	.release = mixer_release,
+	.ioctl = mixer_ioctl,
+	.owner = THIS_MODULE
+};
+
+/* To store characteristic info regarding the codec for the audio driver */
+static audio_state_t aic33_state = {
+	.owner = THIS_MODULE,
+	.output_stream = &output_stream,
+	.input_stream = &input_stream,
+/*    .need_tx_for_rx = 1, //Once the Full Duplex works  */
+	.need_tx_for_rx = 0,
+	.hw_init = davinci_aic33_initialize,
+	.hw_shutdown = davinci_aic33_shutdown,
+	.client_ioctl = davinci_aic33_ioctl,
+	.hw_probe = davinci_aic33_probe,
+	.hw_remove = __exit_p(davinci_aic33_remove),
+	.hw_suspend = davinci_aic33_suspend,
+	.hw_resume = davinci_aic33_resume,
+	.sem = __SEMAPHORE_INIT(aic33_state.sem, 1),
+};
+
+/* This will be defined in the audio.h */
+static struct file_operations *davinci_audio_fops;
+
+extern int tlv320aic33_write_value(u8 reg, u16 value);
+
+/* TLV320AIC33 write */
+static __inline__ void audio_aic33_write(u8 address, u16 data)
+{
+	if (tlv320aic33_write_value(address, data) < 0)
+		printk(KERN_INFO "aic33 write failed for reg = %d\n", address);
+}
+
+static int aic33_update(int flag, int val)
+{
+	u16 volume;
+	u16 gain;
+
+	/* Ignore separate left/right channel for now,
+	   even the codec does support it. */
+	val &= 0xff;
+
+	switch (flag) {
+	case SET_VOLUME:
+
+		if (val < 0 || val > 100) {
+			DPRINTK("Trying a bad volume value(%d)!\n", val);
+			return -EPERM;
+		}
+		// Convert 0 -> 100 volume to 0x77 (LHV_MIN) -> 0x00 (LHV_MAX)
+		volume =
+		    ((val * OUTPUT_VOLUME_RANGE) / 100) + OUTPUT_VOLUME_MIN;
+
+		aic33_local.volume_reg = OUTPUT_VOLUME_MAX - volume;
+
+		if (aic33_local.nochan == STEREO) {
+			audio_aic33_write(47, LOPM_ON | aic33_local.volume_reg);
+			audio_aic33_write(64, LOPM_ON | aic33_local.volume_reg);
+			audio_aic33_write(82, LOPM_ON | aic33_local.volume_reg);
+			audio_aic33_write(92, LOPM_ON | aic33_local.volume_reg);
+		} else if (aic33_local.nochan == MONO) {
+#ifdef CONFIG_MONOSTEREO_DIFFJACK
+			/* DACL1 to MONO_LOP/M routing and volume control */
+			audio_aic33_write(75, LOPM_ON | aic33_local.volume_reg);
+
+			/* DACR1 to MONO_LOP/M routing and volume control */
+			audio_aic33_write(78, LOPM_ON | aic33_local.volume_reg);
+#else
+			audio_aic33_write(47, LOPM_ON | aic33_local.volume_reg);
+			audio_aic33_write(64, LOPM_ON | aic33_local.volume_reg);
+			audio_aic33_write(82, LOPM_ON | aic33_local.volume_reg);
+			audio_aic33_write(92, LOPM_ON | aic33_local.volume_reg);
+#endif
+		}
+
+		break;
+
+	case SET_LINE:
+	case SET_MIC:
+
+		if (val < 0 || val > 100) {
+			DPRINTK("Trying a bad volume value(%d)!\n", val);
+			return -EPERM;
+		}
+
+		volume = ((val * INPUT_VOLUME_RANGE) / 100) + INPUT_VOLUME_MIN;
+
+		aic33_local.input_volume_reg = volume;
+
+		audio_aic33_write(15, aic33_local.input_volume_reg);
+		audio_aic33_write(16, aic33_local.input_volume_reg);
+
+		break;
+
+	case SET_RECSRC:
+		if (hweight32(val) > 1)
+			val &= ~aic33_local.recsrc;
+
+		if (val == SOUND_MASK_MIC) {
+			/* enable the mic input*/
+			DPRINTK("Enabling mic\n");
+			audio_aic33_write(17, 0x0);
+			audio_aic33_write(18, 0x0);
+
+			/* enable ADC's and disable the line input*/
+			audio_aic33_write(19, 0x7C);
+			audio_aic33_write(22, 0x7C);
+
+		}
+		else if (val == SOUND_MASK_LINE) {
+			/* enable ADC's, enable line iput */
+			DPRINTK(" Enabling line in\n");
+			audio_aic33_write(19, 0x4);
+			audio_aic33_write(22, 0x4);
+
+			/* disable the mic input */
+			audio_aic33_write(17, 0xff);
+			audio_aic33_write(18, 0xff);
+		}
+		else {
+			/* do nothing */
+		}
+		aic33_local.recsrc = val;
+		break;
+
+	case SET_IGAIN:
+
+		if (val < 0 || val > 100) {
+			DPRINTK("Trying a bad igain value(%d)!\n", val);
+			return -EPERM;
+		}
+
+		gain = ((val * INPUT_GAIN_RANGE) / 100) + INPUT_GAIN_MIN;
+
+		DPRINTK("gain reg val = 0x%x", gain << 1);
+
+		/* Left AGC control */
+		audio_aic33_write(26, 0x80);
+		audio_aic33_write(27, gain << 1);
+		audio_aic33_write(28, 0x0);
+
+		/* Right AGC control */
+		audio_aic33_write(29, 0x80);
+		audio_aic33_write(30, gain << 1);
+		audio_aic33_write(31, 0x0);
+
+		break;
+
+	case SET_OGAIN:
+
+		if (val < 0 || val > 100) {
+			DPRINTK("Trying a bad igain value(%d)!\n", val);
+			return -EPERM;
+		}
+
+		gain = ((val * OUTPUT_GAIN_RANGE) / 100) + OUTPUT_GAIN_MIN;
+		gain = OUTPUT_GAIN_MAX - gain;
+
+		/* Left/Right DAC digital volume gain */
+		audio_aic33_write(43, gain);
+		audio_aic33_write(44, gain);
+		break;
+
+	case SET_MICBIAS:
+
+		if (val < 0 || val > 3) {
+			DPRINTK
+			    ("Request for non supported mic bias level(%d)!\n",
+			     val);
+			return -EPERM;
+		}
+
+		if (val == 0)
+			audio_aic33_write(25, 0x00);
+
+		else if (val == 1)
+			audio_aic33_write(25, MICBIAS_OUTPUT_2_0V);
+
+		else if (val == 2)
+			audio_aic33_write(25, MICBIAS_OUTPUT_2_5V);
+
+		else if (val == 3)
+			audio_aic33_write(25, MICBIAS_OUTPUT_AVDD);
+
+		break;
+
+	case SET_BASS:
+		break;
+
+	case SET_TREBLE:
+		break;
+	}
+	return 0;
+}
+
+static int mixer_open(struct inode *inode, struct file *file)
+{
+	/* Any mixer specific initialization */
+	return 0;
+}
+
+static int mixer_release(struct inode *inode, struct file *file)
+{
+	/* Any mixer specific Un-initialization */
+	return 0;
+}
+
+static int
+mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+	int val;
+	int ret = 0;
+	int nr = _IOC_NR(cmd);
+
+	/*
+	 * We only accept mixer (type 'M') ioctls.
+	 */
+	if (_IOC_TYPE(cmd) != 'M')
+		return -EINVAL;
+
+	DPRINTK(" 0x%08x\n", cmd);
+
+	if (cmd == SOUND_MIXER_INFO) {
+		struct mixer_info mi;
+
+		strncpy(mi.id, "AIC33", sizeof(mi.id));
+		strncpy(mi.name, "TI AIC33", sizeof(mi.name));
+		mi.modify_counter = aic33_local.mod_cnt;
+
+		return copy_to_user((void *)arg, &mi, sizeof(mi));
+	}
+
+	if (_IOC_DIR(cmd) & _IOC_WRITE) {
+		ret = get_user(val, (int *)arg);
+		if (ret)
+			goto out;
+
+		switch (nr) {
+		case SOUND_MIXER_VOLUME:
+			aic33_local.mod_cnt++;
+			ret = aic33_update(SET_VOLUME, val);
+			if (!ret)
+				aic33_local.volume = val;
+			break;
+
+		case SOUND_MIXER_LINE:
+			aic33_local.mod_cnt++;
+			ret = aic33_update(SET_LINE, val);
+			if (!ret)
+				aic33_local.line = val;
+			break;
+
+		case SOUND_MIXER_MIC:
+			aic33_local.mod_cnt++;
+			ret = aic33_update(SET_MIC, val);
+			if (!ret)
+				aic33_local.mic = val;
+			break;
+
+		case SOUND_MIXER_RECSRC:
+			if ((val & SOUND_MASK_LINE) ||
+			    (val & SOUND_MASK_MIC)) {
+				if (aic33_local.recsrc != val) {
+					aic33_local.mod_cnt++;
+					aic33_update(SET_RECSRC, val);
+				}
+			}
+			else {
+				ret = -EINVAL;
+			}
+			break;
+
+		case SOUND_MIXER_BASS:
+			aic33_local.mod_cnt++;
+			ret = aic33_update(SET_BASS, val);
+			if (!ret)
+				aic33_local.bass = val;
+			break;
+
+		case SOUND_MIXER_TREBLE:
+			aic33_local.mod_cnt++;
+			ret = aic33_update(SET_TREBLE, val);
+			if (!ret)
+				aic33_local.treble = val;
+			break;
+
+		case SOUND_MIXER_IGAIN:
+			aic33_local.mod_cnt++;
+			ret = aic33_update(SET_IGAIN, val);
+			if (!ret)
+				aic33_local.igain = val;
+			break;
+
+		case SOUND_MIXER_OGAIN:
+			aic33_local.mod_cnt++;
+			ret = aic33_update(SET_OGAIN, val);
+			if (!ret)
+				aic33_local.ogain = val;
+			break;
+
+		case SOUND_MIXER_MICBIAS:
+			aic33_local.mod_cnt++;
+			ret = aic33_update(SET_MICBIAS, val);
+			if (!ret)
+				aic33_local.micbias = val;
+			break;
+
+		default:
+			ret = -EINVAL;
+		}
+	}
+
+	if (ret == 0 && _IOC_DIR(cmd) & _IOC_READ) {
+		ret = 0;
+
+		switch (nr) {
+		case SOUND_MIXER_VOLUME:
+			val = aic33_local.volume;
+			break;
+		case SOUND_MIXER_LINE:
+			val = aic33_local.line;
+			break;
+		case SOUND_MIXER_MIC:
+			val = aic33_local.mic;
+			break;
+		case SOUND_MIXER_RECSRC:
+			val = aic33_local.recsrc;
+			break;
+		case SOUND_MIXER_RECMASK:
+			val = REC_MASK;
+			break;
+		case SOUND_MIXER_IGAIN:
+			val = aic33_local.igain;
+			break;
+		case SOUND_MIXER_OGAIN:
+			val = aic33_local.ogain;
+			break;
+		case SOUND_MIXER_DEVMASK:
+			val = DEV_MASK;
+			break;
+		case SOUND_MIXER_BASS:
+			val = aic33_local.bass;
+			break;
+		case SOUND_MIXER_TREBLE:
+			val = aic33_local.treble;
+			break;
+		case SOUND_MIXER_CAPS:
+			val = 0;
+			break;
+		case SOUND_MIXER_STEREODEVS:
+			val = SOUND_MASK_VOLUME;
+			break;
+		case SOUND_MIXER_MICBIAS:
+			val = aic33_local.micbias;
+			break;
+		default:
+			val = 0;
+			ret = -EINVAL;
+			break;
+		}
+
+		if (ret == 0)
+			ret = put_user(val, (int *)arg);
+	}
+      out:
+	return ret;
+}
+
+int davinci_set_samplerate(long sample_rate)
+{
+	u8 count = 0;
+
+	/* wait for any frame to complete */
+	udelay(125);
+
+	/* Search for the right sample rate */
+	while ((reg_info[count].sample_rate != sample_rate) &&
+	       (count < NUMBER_SAMPLE_RATES_SUPPORTED)) {
+		count++;
+	}
+
+	if (count == NUMBER_SAMPLE_RATES_SUPPORTED) {
+		DPRINTK("Invalid Sample Rate %d requested\n", (int)sample_rate);
+		return -EPERM;
+	}
+
+	/*   CODEC DATAPATH SETUP  */
+
+	/* Fsref to 48kHz, dual rate mode upto 96kHz */
+	if (reg_info[count].Fsref == 96000)
+		audio_aic33_write(7,
+				  FS_REF_DEFAULT_48 | ADC_DUAL_RATE_MODE |
+				  DAC_DUAL_RATE_MODE | LDAC_LCHAN | RDAC_RCHAN);
+
+	/* Fsref to 44.1kHz, dual rate mode upto 88.2kHz */
+	else if (reg_info[count].Fsref == 88200)
+		audio_aic33_write(7,
+				  FS_REF_44_1 | ADC_DUAL_RATE_MODE |
+			  	  DAC_DUAL_RATE_MODE | LDAC_LCHAN | RDAC_RCHAN);
+
+	/* Fsref to 48kHz */
+	else if (reg_info[count].Fsref == 48000)
+		audio_aic33_write(7,
+				  FS_REF_DEFAULT_48 | LDAC_LCHAN | RDAC_RCHAN);
+
+	/* Fsref to 44.1kHz */
+	else if (reg_info[count].Fsref == 44100)
+		audio_aic33_write(7, FS_REF_44_1 | LDAC_LCHAN | RDAC_RCHAN);
+
+
+	/* Codec sample rate select */
+	audio_aic33_write(2, reg_info[count].data);
+
+	/* If PLL is to be used for generation of Fsref
+	   Generate the Fsref using the PLL */
+#if(MCLK==33)
+
+	if ((reg_info[count].Fsref == 96000) | (reg_info[count].Fsref == 48000)) {
+		/* For MCLK = 33.8688 MHz and to get Fsref = 48kHz
+		   Fsref = (MCLK * k * R)/(2048 * p);
+		   Select P = 2, R= 1, K = 5.8049, which results in J = 5, D = 8049 */
+
+		/*Enable the PLL | Q-value | P-value */
+		audio_aic33_write(3, PLL_ENABLE | 0x10 | 0x02);
+		audio_aic33_write(4, 0x14);	/* J-value */
+		audio_aic33_write(5, 0x7D);	/* D-value 8-MSB's */
+		audio_aic33_write(6, 0x04);	/* D-value 6-LSB's */
+
+	}
+
+	else if ((reg_info[count].Fsref == 88200) | (reg_info[count].Fsref ==
+						     44100)) {
+
+		/* MCLK = 33.8688 MHz and to get Fsref = 44.1kHz
+		   Fsref = (MCLK * k * R)/(2048 * p);
+		   Select P = 2, R =1, K = 5.3333, which results in J = 5, D = 3333 */
+
+		/*Enable the PLL | Q-value | P-value */
+		audio_aic33_write(3, PLL_ENABLE | 0x10 | 0x02);
+		audio_aic33_write(4, 0x14);	/* J-value */
+		audio_aic33_write(5, 0x34);	/* D-value 8-MSB's */
+		audio_aic33_write(6, 0x14);	/* D-value 6-LSB's */
+	}
+#elif(MCLK==22)
+
+	if ((reg_info[count].Fsref == 96000) | (reg_info[count].Fsref == 48000)) {
+		/* For MCLK = 22.5792 MHz and to get Fsref = 48kHz
+		   Fsref = (MCLK * k * R)/(2048 * p);
+		   Select P = 2, R= 1, K = 8.7075, which results in J = 8, D = 7075 */
+
+		/*Enable the PLL | Q-value | P-value */
+		audio_aic33_write(3, PLL_ENABLE | 0x10 | 0x02);
+		audio_aic33_write(4, (8 << 2));	/* J-value */
+		audio_aic33_write(5, (unsigned char)(7075 >> 6));	/* D-value 8-MSB's */
+		audio_aic33_write(6, (unsigned char)(7075 << 2));	/* D-value 6-LSB's */
+
+	}
+
+	else if ((reg_info[count].Fsref == 88200) | (reg_info[count].Fsref ==
+						     44100)) {
+
+		/* MCLK = 22.5792 MHz and to get Fsref = 44.1kHz
+		   Fsref = (MCLK * k * R)/(2048 * p);
+		   Select P = 2, R =1, K = 8.0000, which results in J = 8, D = 0000 */
+
+		/*Enable the PLL | Q-value | P-value */
+		audio_aic33_write(3, PLL_ENABLE | 0x10 | 0x02);
+		audio_aic33_write(4, (8 << 2));	/* J-value */
+		audio_aic33_write(5, 0x00);	/* D-value 8-MSB's */
+		audio_aic33_write(6, 0x00);	/* D-value 6-LSB's */
+	}
+#else
+#error "unknown audio codec frequency"
+#endif
+
+	audio_samplerate = sample_rate;
+
+#ifndef AIC33_MASTER
+	{
+		int clkgdv = 0;
+		unsigned long clkval = 0;
+		struct clk *mbspclk;
+
+		/*
+		   Set Sample Rate at McBSP
+
+		   Formula :
+		   Codec System Clock = Input clock to McBSP;
+		   clkgdv = ((Codec System Clock / (SampleRate * BitsPerSample * 2)) - 1);
+
+		   FWID = BitsPerSample - 1;
+		   FPER = (BitsPerSample * 2) - 1;
+		 */
+
+		mbspclk = davinci_mcbsp_get_clock();
+		if (mbspclk == NULL) {
+			DPRINTK(" Failed to get internal clock to MCBSP");
+			return -EPERM;
+		}
+
+		clkval = clk_get_rate(mbspclk);
+		DPRINTK("mcbsp_clk = %ld\n", clkval);
+
+		if (clkval)
+			clkgdv =
+			    (clkval /
+			     (sample_rate * DEFAULT_BITPERSAMPLE * 2)) - 1;
+		else {
+			DPRINTK(" Failed to get the MCBSP clock\n");
+			return -EPERM;
+		}
+
+		DPRINTK("clkgdv = %d\n", clkgdv);
+
+		if (clkgdv > 255 || clkgdv < 0) {
+
+			/* For requested sampling rate, the input clock to MCBSP cant be devided
+			   down to get the in range clock devider value for 16 bits sample */
+			DPRINTK("Invalid Sample Rate %d requested\n",
+				(int)sample_rate);
+			return -EPERM;
+		}
+
+		initial_config.srgr1 =
+		    (FWID(DEFAULT_BITPERSAMPLE - 1) | CLKGDV(clkgdv));
+
+		initial_config.srgr2 =
+		    (CLKSM | FSGM | FPER(DEFAULT_BITPERSAMPLE * 2 - 1));
+
+		davinci_mcbsp_stop(AUDIO_MCBSP);
+		davinci_mcbsp_config(AUDIO_MCBSP, &initial_config);
+	}
+#endif				/* AIC33_MASTER */
+
+	return 0;
+}
+
+static void davinci_aic33_shutdown(void *dummy)
+{
+	/*
+	   Turn off codec after it is done.
+	   Can't do it immediately, since it may still have
+	   buffered data.
+
+	   Wait 20ms (arbitrary value) and then turn it off.
+	 */
+
+	set_current_state(TASK_INTERRUPTIBLE);
+	schedule_timeout(2);
+
+	davinci_mcbsp_stop(AUDIO_MCBSP);
+	davinci_mcbsp_free(AUDIO_MCBSP);
+
+	/* Self clearing aic33 software reset */
+	audio_aic33_write(1, 0x80);
+}
+
+static void davinci_set_mono_stereo(int mode)
+{
+	if (mode == MONO) {
+
+#ifdef CONFIG_MONOSTEREO_DIFFJACK
+		/* MONO_LOP/M Output level control register */
+		audio_aic33_write(79, 0x99);
+#else
+		/* Driver power ON pop control */
+		audio_aic33_write(42, 0x6C);
+
+		/* LEFT_LOP/M, RIGHT_LOP/M output level control */
+		audio_aic33_write(86, 0x99);
+		audio_aic33_write(93, 0x99);
+#endif
+		/* Left DAC power up, Right DAC power down */
+		audio_aic33_write(37, 0xa0);
+	} else if (mode == STEREO) {
+		/* Driver power ON pop control */
+		audio_aic33_write(42, 0x6C);
+
+		/* HPLOUT/HPROUT output level control */
+		audio_aic33_write(51, 0x99);
+		audio_aic33_write(65, 0x99);
+
+		/* LEFT_LOP/M, RIGHT_LOP/M output level control */
+		audio_aic33_write(86, 0x99);
+		audio_aic33_write(93, 0x99);
+
+		/* Left/Right DAC power up */
+		audio_aic33_write(37, 0xe0);
+	} else
+		DPRINTK(" REQUEST FOR INVALID MODE\n");
+}
+
+static inline void aic33_configure()
+{
+	DPRINTK(" CONFIGURING AIC33\n");
+
+	/* Page select register */
+	audio_aic33_write(0, 0x0);
+
+	//audio_aic33_write(38, 0x10);
+
+	davinci_set_mono_stereo(aic33_local.nochan);
+
+#ifdef AIC33_MASTER
+	/* Enable bit and word clock as Master mode, 3-d disabled */
+	audio_aic33_write(8, 0xc0 /*0xc4 */ );
+#endif
+
+	aic33_update(SET_LINE, aic33_local.line);
+	aic33_update(SET_VOLUME, aic33_local.volume);
+	aic33_update(SET_RECSRC, aic33_local.recsrc);
+	aic33_update(SET_IGAIN, aic33_local.igain);
+	aic33_update(SET_OGAIN, aic33_local.ogain);
+	aic33_update(SET_MICBIAS, aic33_local.micbias);
+}
+
+static void davinci_aic33_initialize(void *dummy)
+{
+	DPRINTK("entry\n");
+
+	/* initialize with default sample rate */
+	audio_samplerate = AUDIO_RATE_DEFAULT;
+
+	if (davinci_mcbsp_request(AUDIO_MCBSP) < 0) {
+		DPRINTK("MCBSP request failed\n");
+		return;
+	}
+
+	/* if configured, then stop mcbsp */
+	davinci_mcbsp_stop(AUDIO_MCBSP);
+
+	/* set initial (default) sample rate */
+	davinci_set_samplerate(audio_samplerate);
+
+	davinci_mcbsp_config(AUDIO_MCBSP, &initial_config);
+
+	DPRINTK("exit\n");
+}
+
+static int
+davinci_aic33_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+	long val;
+	int ret = 0;
+
+	DPRINTK(" 0x%08x\n", cmd);
+
+	/*
+	 * These are platform dependent ioctls which are not handled by the
+	 * generic davinci-audio module.
+	 */
+	switch (cmd) {
+	case SNDCTL_DSP_STEREO:
+		ret = get_user(val, (int *)arg);
+		if (ret)
+			return ret;
+		/* the Davinci supports AIC33 as stereo, mono on stereo jack */
+		ret = (val == 0) ? -EINVAL : 1;
+		return put_user(ret, (int *)arg);
+
+	case SNDCTL_DSP_CHANNELS:
+
+		ret = get_user(val, (long *)arg);
+		if (ret) {
+			DPRINTK("get_user failed\n");
+			break;
+		}
+		if (val == STEREO) {
+			DPRINTK("Driver support for AIC33 as stereo\n");
+			aic33_local.nochan = STEREO;
+			davinci_set_mono_stereo(aic33_local.nochan);
+		} else if (val == MONO) {
+			DPRINTK("Driver support for AIC33 as mono\n");
+			aic33_local.nochan = MONO;
+			davinci_set_mono_stereo(aic33_local.nochan);
+		} else {
+			DPRINTK
+			    ("Driver support for AIC33 as stereo/mono mode\n");
+			return -EPERM;
+		}
+
+	case SOUND_PCM_READ_CHANNELS:
+		/* the Davinci supports AIC33 as stereo, mono on stereo jack */
+		if (aic33_local.nochan == MONO)
+			return put_user(MONO, (long *)arg);
+		else
+			return put_user(STEREO, (long *)arg);
+
+	case SNDCTL_DSP_SPEED:
+		ret = get_user(val, (long *)arg);
+		if (ret) {
+			DPRINTK("get_user failed\n");
+			break;
+		}
+		ret = davinci_set_samplerate(val);
+		if (ret) {
+			DPRINTK("davinci_set_samplerate failed\n");
+			break;
+		}
+		/* fall through */
+
+	case SOUND_PCM_READ_RATE:
+		return put_user(audio_samplerate, (long *)arg);
+
+	case SNDCTL_DSP_SETFMT:	/* set Format */
+		ret = get_user(val, (long *)arg);
+		if (ret) {
+			DPRINTK("get_user failed\n");
+			break;
+		}
+		if (val != AFMT_S16_LE) {
+			DPRINTK
+			    ("Driver supports only AFMT_S16_LE audio format\n");
+			return -EPERM;
+		}
+
+	case SOUND_PCM_READ_BITS:
+	case SNDCTL_DSP_GETFMTS:
+		/* we can do 16-bit only */
+		return put_user(AFMT_S16_LE, (long *)arg);
+
+	default:
+		/* Maybe this is meant for the mixer (As per OSS Docs) */
+		return mixer_ioctl(inode, file, cmd, arg);
+	}
+
+	return ret;
+}
+
+static int davinci_aic33_probe(void)
+{
+	/* Get the fops from audio oss driver */
+	if (!(davinci_audio_fops = audio_get_fops())) {
+		DPRINTK
+		    ("Unable to get the file operations for AIC33 OSS driver\n");
+		audio_unregister_codec(&aic33_state);
+		return -EPERM;
+	}
+
+	aic33_local.volume = DEFAULT_OUTPUT_VOLUME;
+	aic33_local.line = DEFAULT_INPUT_VOLUME;
+	aic33_local.recsrc = SOUND_MASK_LINE;	/* either of SOUND_MASK_LINE/SOUND_MASK_MIC */
+	aic33_local.igain = DEFAULT_INPUT_IGAIN;
+	aic33_local.ogain = DEFAULT_INPUT_OGAIN;
+	aic33_local.nochan = STEREO;
+	aic33_local.micbias = 1;
+	aic33_local.mod_cnt = 0;
+
+	/* register devices */
+	audio_dev_id = register_sound_dsp(davinci_audio_fops, -1);
+	mixer_dev_id = register_sound_mixer(&davinci_mixer_fops, -1);
+
+#ifdef CONFIG_PROC_FS
+	create_proc_read_entry(PROC_START_FILE, 0 /* default mode */ ,
+			       NULL /* parent dir */ ,
+			       codec_start, NULL /* client data */ );
+
+	create_proc_read_entry(PROC_STOP_FILE, 0 /* default mode */ ,
+			       NULL /* parent dir */ ,
+			       codec_stop, NULL /* client data */ );
+#endif
+
+	/* Announcement Time */
+	DPRINTK(PLATFORM_NAME " " CODEC_NAME " audio support initialized\n");
+	return 0;
+}
+
+#ifdef MODULE
+static void __exit davinci_aic33_remove(void)
+{
+	/* Un-Register the codec with the audio driver */
+	unregister_sound_dsp(audio_dev_id);
+	unregister_sound_mixer(mixer_dev_id);
+
+#ifdef CONFIG_PROC_FS
+	remove_proc_entry(PROC_START_FILE, NULL);
+	remove_proc_entry(PROC_STOP_FILE, NULL);
+#endif
+}
+#endif				/* MODULE */
+
+static int davinci_aic33_suspend(void)
+{
+	/* Empty for the moment */
+	return 0;
+}
+
+static int davinci_aic33_resume(void)
+{
+	/* Empty for the moment */
+	return 0;
+}
+
+static int __init audio_aic33_init(void)
+{
+	int err = 0;
+
+	/* register the codec with the audio driver */
+	if ((err = audio_register_codec(&aic33_state))) {
+		DPRINTK
+		    ("Failed to register AIC33 driver with Audio OSS Driver\n");
+	} else {
+		DPRINTK("codec driver register success\n");
+	}
+
+	/* configure aic33 with default params */
+	aic33_configure();
+
+	return err;
+}
+
+static void __exit audio_aic33_exit(void)
+{
+	davinci_aic33_shutdown(NULL);
+	(void)audio_unregister_codec(&aic33_state);
+	return;
+}
+
+#ifdef CONFIG_PROC_FS
+static int codec_start(char *buf, char **start, off_t offset, int count,
+		       int *eof, void *data)
+{
+	davinci_aic33_initialize(NULL);
+
+	DPRINTK("AIC33 codec initialization done.\n");
+	return 0;
+}
+
+static int codec_stop(char *buf, char **start, off_t offset, int count,
+		      int *eof, void *data)
+{
+	davinci_aic33_shutdown(NULL);
+
+	DPRINTK("AIC33 codec shutdown.\n");
+	return 0;
+}
+#endif				/* CONFIG_PROC_FS */
+
+module_init(audio_aic33_init);
+module_exit(audio_aic33_exit);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("Glue audio driver for the TI AIC33 codec.");
+MODULE_LICENSE("GPL");
diff --git a/sound/oss/davinci-audio-dma-intfc.c b/sound/oss/davinci-audio-dma-intfc.c
new file mode 100644
index 0000000..e505014
--- /dev/null
+++ b/sound/oss/davinci-audio-dma-intfc.c
@@ -0,0 +1,1018 @@
+
+/*
+ * linux/sound/oss/davinci-audio-dma-intfc.c
+ *
+ * Common audio DMA handling for the Davinci processors
+ *
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ *
+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *
+ * 2004-06-07   Sriram Kannan   - Created new file from omap_audio_dma_intfc.c. This file
+ *                                will contain only the DMA interface and buffer handling of OMAP
+ *                                audio driver.
+ *
+ * 2004-06-22   Sriram Kannan   - removed legacy code (auto-init). Self-linking of DMA logical channel.
+ *
+ * 2004-08-12   Nishanth Menon  - Modified to integrate Audio requirements on 1610,1710 platforms
+ *
+ * 2004-11-01   Nishanth Menon  - 16xx platform code base modified to support multi channel chaining.
+ *
+ * 2004-12-15   Nishanth Menon  - Improved 16xx platform channel logic introduced - tasklets, queue handling updated
+ *
+ * 2005-10-01   Rishi Bhattacharya / Sharath Kumar - Added support for TI Davinci DM644x processor
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/sysrq.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/semaphore.h>
+#include <asm/delay.h>
+
+#include <asm/arch/mcbsp.h>
+#include <asm/arch/edma.h>
+#include <asm/arch/memory.h>
+
+#include "davinci-audio-dma-intfc.h"
+#include "davinci-audio.h"
+
+#undef DEBUG
+//#define DEBUG
+#ifdef DEBUG
+#define DPRINTK(ARGS...)  printk(KERN_INFO "<%s>: ",__FUNCTION__);printk(ARGS)
+#define FN_IN printk(KERN_INFO "[%s]: start\n", __FUNCTION__)
+#define FN_OUT(n) printk(KERN_INFO "[%s]: end(%u)\n",__FUNCTION__, n)
+#else
+
+#define DPRINTK( x... )
+#define FN_IN
+#define FN_OUT(x)
+#endif
+
+#define ERR(ARGS...) printk(KERN_ERR "{%s}-ERROR: ", __FUNCTION__);printk(ARGS);
+
+#define AUDIO_NAME                  "davinci-audio"
+#define MCBSP_DXR   0x01E02004
+#define MCBSP_DRR   0x01E02000
+
+#define AUDIO_ACTIVE(state)     ((state)->rd_ref || (state)->wr_ref)
+
+#define SPIN_ADDR                    (dma_addr_t)0
+#define SPIN_SIZE                    2048
+
+#define NUMBER_OF_CHANNELS_TO_LINK  2
+
+/* Channel Queue Handling macros
+ * tail always points to the current free entry
+ * Head always points to the current entry being used
+ * end is either head or tail
+ */
+#define AUDIO_QUEUE_INIT(s) s->dma_q_head = s->dma_q_tail = s->dma_q_count = 0;
+#define AUDIO_QUEUE_FULL(s) (NUMBER_OF_CHANNELS_TO_LINK == s->dma_q_count)
+#define AUDIO_QUEUE_LAST(s) (1 == s->dma_q_count)
+#define AUDIO_QUEUE_EMPTY(s) (0 == s->dma_q_count)
+#define __AUDIO_INCREMENT_QUEUE(end) ((end)=((end)+1)%NUMBER_OF_CHANNELS_TO_LINK)
+#define AUDIO_INCREMENT_HEAD(s) __AUDIO_INCREMENT_QUEUE(s->dma_q_head);\
+                                                      s->dma_q_count--;
+#define AUDIO_INCREMENT_TAIL(s) __AUDIO_INCREMENT_QUEUE(s->dma_q_tail);\
+                                                      s->dma_q_count++;
+
+/* DMA buffer fragmentation sizes */
+#define MAX_DMA_SIZE         (0xffff*2)
+#define CUT_DMA_SIZE         MAX_DMA_SIZE
+
+/**************************** DATA STRUCTURES *********************************/
+
+struct audio_isr_work_item {
+	int current_lch;
+	u16 ch_status;
+	audio_stream_t *s;
+};
+
+static char work_item_running = 0;
+static struct audio_isr_work_item work1, work2;
+
+/*********************** MODULE SPECIFIC FUNCTIONS PROTOTYPES ****************/
+
+static void audio_dsr_handler(unsigned long);
+DECLARE_TASKLET(audio_isr_work1, audio_dsr_handler, (unsigned long)&work1);
+DECLARE_TASKLET(audio_isr_work2, audio_dsr_handler, (unsigned long)&work2);
+
+static void sound_dma_irq_handler(int lch, u16 ch_status, void *data);
+static void audio_dma_callback(int lch, u16 ch_status, void *data);
+static int davinci_start_sound_dma(audio_stream_t * s, dma_addr_t dma_ptr,
+				   u_int size);
+static int audio_set_dma_params_play(int channel, dma_addr_t dma_ptr,
+				     u_int dma_size);
+static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr,
+					u_int dma_size);
+static int audio_start_dma_chain(audio_stream_t * s);
+
+/************************** GLOBAL FUNCTIONS DEFINTIONS ***********************/
+
+/*******************************************************************************
+ *
+ * Buffer creation/destruction
+ *
+ ******************************************************************************/
+int audio_setup_buf(audio_stream_t * s)
+{
+	int frag;
+	int dmasize = 0;
+	char *dmabuf = NULL;
+	dma_addr_t dmaphys = 0;
+	FN_IN;
+
+	if (s->buffers) {
+		FN_OUT(1);
+		return -EBUSY;
+	}
+
+	/* Allocate memory for all buffer fragments */
+	s->buffers = kmalloc(sizeof(audio_buf_t) * s->nbfrags, GFP_KERNEL);
+	if (!s->buffers)
+		goto err;
+
+	/* Initialise all the memory to 0 */
+	memset(s->buffers, 0, sizeof(audio_buf_t) * s->nbfrags);
+
+	for (frag = 0; frag < s->nbfrags; frag++) {
+		audio_buf_t *b = &s->buffers[frag];
+
+		/*
+		 * Let's allocate non-cached memory for DMA buffers.
+		 * We try to allocate all memory at once.
+		 * If this fails (a common reason is memory fragmentation),
+		 * then we allocate more smaller buffers.
+		 */
+		if (!dmasize) {
+			dmasize = (s->nbfrags - frag) * s->fragsize;
+			do {
+				/* allocate consistent memory for DMA
+				   dmaphys(handle)= device viewed address.
+				   dmabuf = CPU-viewed address */
+				dmabuf =
+				    dma_alloc_coherent(NULL, dmasize, &dmaphys,
+						       0);
+
+				/* For allocating the IRAM memory */
+				//dmaphys = (dma_addr_t)(DAVINCI_IRAM_BASE + 0x1000);
+				//dmabuf = (DAVINCI_IRAM_VIRT + 0x1000);
+				if (!dmabuf)
+					dmasize -= s->fragsize;
+			}
+			while (!dmabuf && dmasize);
+
+			if (!dmabuf)
+				goto err;
+
+			b->master = dmasize;
+			memzero(dmabuf, dmasize);
+		}
+		b->data = dmabuf;
+		b->dma_addr = dmaphys;
+		dmabuf += s->fragsize;
+		dmaphys += s->fragsize;
+		dmasize -= s->fragsize;
+	}
+	s->usr_head = s->dma_head = s->dma_tail = 0;
+	AUDIO_QUEUE_INIT(s);
+	s->started = 0;
+
+	s->dma_started = 0;
+	s->bytecount = 0;
+	s->fragcount = 0;
+	s->prevbuf = 0;
+
+	init_completion(&s->wfc);
+	s->wfc.done = s->nbfrags;
+
+	FN_OUT(0);
+	return 0;
+      err:
+	audio_discard_buf(s);
+	FN_OUT(1);
+	return -ENOMEM;
+}
+
+void audio_discard_buf(audio_stream_t * s)
+{
+	FN_IN;
+	/* ensure DMA isn't using those buffers */
+	audio_reset(s);
+	if (s->buffers) {
+		int frag;
+		for (frag = 0; frag < s->nbfrags; frag++) {
+			if (!s->buffers[frag].master)
+				continue;
+
+			dma_free_coherent(NULL,
+					  s->buffers[frag].master,
+					  s->buffers[frag].data,
+					  s->buffers[frag].dma_addr);
+
+		}
+		kfree(s->buffers);
+		s->buffers = NULL;
+	}
+	FN_OUT(0);
+}
+
+/*******************************************************************************
+ *
+ * DMA channel requests
+ *
+ ******************************************************************************/
+int
+davinci_request_sound_dma(int device_id, const char *device_name, void *data,
+			  int *master_ch, int **channels)
+{
+	int i, err = 0;
+	int *chan = NULL;
+	int tcc;
+
+	FN_IN;
+	if (unlikely((NULL == channels) || (NULL == device_name))) {
+		BUG();
+		return -EPERM;
+	}
+	/* Try allocate memory for the num channels */
+	*channels = (int *)kmalloc(sizeof(int) * NUMBER_OF_CHANNELS_TO_LINK,
+				   GFP_KERNEL);
+	chan = *channels;
+	if (NULL == chan) {
+		ERR("No Memory for channel allocs!\n");
+		FN_OUT(-ENOMEM);
+		return -ENOMEM;
+	}
+
+	/* request for the Master channel and setup the params */
+	i = 0;
+	err = davinci_request_dma(device_id, device_name,
+				  sound_dma_irq_handler, data, master_ch, &tcc,
+				  EVENTQ_0);
+
+	/* Handle Failure condition here */
+	if (err < 0) {
+		ERR("Error in requesting Master channel %d = 0x%x\n", device_id,
+		    err);
+
+		FN_OUT(err);
+		return err;
+
+	}
+
+	DPRINTK("Master chan = %d\n", *master_ch);
+
+	for (i = 0; i < NUMBER_OF_CHANNELS_TO_LINK; i++) {
+		err = davinci_request_dma(DAVINCI_EDMA_PARAM_ANY, device_name,
+					  sound_dma_irq_handler, data, &chan[i],
+					  &tcc, EVENTQ_0);
+
+		/* Handle Failure condition here */
+		if (err < 0) {
+			int j;
+
+			for (j = 0; j < i; j++)
+				davinci_free_dma(chan[j]);
+
+			kfree(chan);
+			*channels = NULL;
+			ERR("Error in requesting channel %d=0x%x\n", i, err);
+			FN_OUT(err);
+			return err;
+		}
+	}
+
+	/* Chain the channels together */
+	for (i = 0; i < NUMBER_OF_CHANNELS_TO_LINK; i++) {
+		int cur_chan = chan[i];
+		int nex_chan = ((NUMBER_OF_CHANNELS_TO_LINK - 1 ==
+				 i) ? chan[0] : chan[i + 1]);
+		davinci_dma_link_lch(cur_chan, nex_chan);
+	}
+
+	FN_OUT(0);
+	return 0;
+}
+
+/******************************************************************************
+ *
+ * DMA channel requests Freeing
+ *
+ ******************************************************************************/
+int davinci_free_sound_dma(int master_ch, int **channels)
+{
+	int i;
+	int *chan = NULL;
+	FN_IN;
+	if (unlikely(NULL == channels)) {
+		BUG();
+		return -EPERM;
+	}
+	if (unlikely(NULL == *channels)) {
+		BUG();
+		return -EPERM;
+	}
+	chan = (*channels);
+
+	/* release the Master channel */
+	davinci_free_dma(master_ch);
+
+	for (i = 0; i < NUMBER_OF_CHANNELS_TO_LINK; i++) {
+		int cur_chan = chan[i];
+		int nex_chan = ((NUMBER_OF_CHANNELS_TO_LINK - 1 == i) ?
+				chan[0] : chan[i + 1]);
+
+		davinci_dma_unlink_lch(cur_chan, nex_chan);
+		davinci_free_dma(cur_chan);
+	}
+	kfree(*channels);
+	*channels = NULL;
+	FN_OUT(0);
+	return 0;
+}
+
+/*******************************************************************************
+ *
+ * Process DMA requests - This will end up starting the transfer.
+ * Proper fragments of Transfers will be initiated.
+ *
+ ******************************************************************************/
+int audio_process_dma(audio_stream_t * s)
+{
+	int ret = 0;
+	unsigned long flags;
+	FN_IN;
+
+	/* Dont let the ISR over ride touching the in_use flag */
+	local_irq_save(flags);
+	if (1 == s->in_use) {
+		local_irq_restore(flags);
+		DPRINTK("Called again while In Use\n");
+		return 0;
+	}
+	s->in_use = 1;
+	local_irq_restore(flags);
+
+	if (s->stopped)
+		goto spin;
+
+	if (s->dma_spinref > 0 && s->pending_frags) {
+		s->dma_spinref = 0;
+		DMA_CLEAR(s);
+	}
+
+	while (s->pending_frags) {
+		audio_buf_t *b = &s->buffers[s->dma_head];
+		u_int dma_size = s->fragsize - b->offset;
+
+		if (dma_size > MAX_DMA_SIZE) {
+			DPRINTK("dma_size > MAX_DMA_SIZE\n");
+			dma_size = CUT_DMA_SIZE;
+		}
+
+		ret = davinci_start_sound_dma(s, b->dma_addr + b->offset,
+					      dma_size);
+		if (ret) {
+			DPRINTK("error\n");
+			goto process_out;
+		}
+
+		b->dma_ref++;
+		b->offset += dma_size;
+		if (b->offset >= s->fragsize) {
+			s->pending_frags--;
+			if (++s->dma_head >= s->nbfrags)
+				s->dma_head = 0;
+		}
+	}
+      spin:
+	if (s->spin_idle) {
+		int spincnt = 0;
+		DPRINTK("we are spinning\n");
+		while (davinci_start_sound_dma(s, SPIN_ADDR, SPIN_SIZE) == 0)
+			spincnt++;
+		/*
+		 * Note: if there is still a data buffer being
+		 * processed then the ref count is negative.  This
+		 * allows for the DMA termination to be accounted in
+		 * the proper order.  Of course dma_spinref can't be
+		 * greater than 0 if dma_ref is not 0 since we kill
+		 * the spinning above as soon as there is real data to process.
+		 */
+		if (s->buffers && s->buffers[s->dma_tail].dma_ref)
+			spincnt = -spincnt;
+		s->dma_spinref += spincnt;
+	}
+
+      process_out:
+	s->in_use = 0;
+
+	FN_OUT(ret);
+	return ret;
+}
+
+/*******************************************************************************
+ *
+ * Prime Rx - Since the recieve buffer has no time limit as to when it would
+ *            arrive, we need to prime it
+ *
+ ******************************************************************************/
+void audio_prime_rx(audio_state_t * state)
+{
+	audio_stream_t *is = state->input_stream;
+
+	FN_IN;
+	if (state->need_tx_for_rx) {
+		/*
+		 * With some codecs like the Philips UDA1341 we must ensure
+		 * there is an output stream at any time while recording since
+		 * this is how the UDA1341 gets its clock from the SA1100.
+		 * So while there is no playback data to send, the output DMA
+		 * will spin with all zeroes.  We use the cache flush special
+		 * area for that.
+		 */
+		state->output_stream->spin_idle = 1;
+		audio_process_dma(state->output_stream);
+	}
+	is->pending_frags = is->nbfrags;
+
+	init_completion(&is->wfc);
+	is->wfc.done = 0;
+
+	is->active = 1;
+	audio_process_dma(is);
+
+	FN_OUT(0);
+	return;
+}
+
+/*******************************************************************************
+ *
+ * set the fragment size
+ *
+ ******************************************************************************/
+int audio_set_fragments(audio_stream_t * s, int val)
+{
+	FN_IN;
+	if (s->active)
+		return -EBUSY;
+	if (s->buffers)
+		audio_discard_buf(s);
+	s->nbfrags = (val >> 16) & 0x7FFF;
+	val &= 0xFFFF;
+	if (val < 4)
+		val = 4;
+	if (val > 15)
+		val = 15;
+	s->fragsize = 1 << val;
+	if (s->nbfrags < 2)
+		s->nbfrags = 2;
+	if (s->nbfrags * s->fragsize > 128 * 1024)
+		s->nbfrags = 128 * 1024 / s->fragsize;
+	FN_OUT(0);
+	if (audio_setup_buf(s))
+		return -ENOMEM;
+	return val | (s->nbfrags << 16);
+
+}
+
+/*******************************************************************************
+ *
+ * Sync up the buffers before we shutdown, else under-run errors will happen
+ *
+ ******************************************************************************/
+int audio_sync(struct file *file)
+{
+	audio_state_t *state = file->private_data;
+	audio_stream_t *s = state->output_stream;
+	audio_buf_t *b;
+	u_int shiftval = 0;
+	unsigned long flags;
+
+	DECLARE_WAITQUEUE(wait, current);
+
+	FN_IN;
+
+	if (!(file->f_mode & FMODE_WRITE) || !s->buffers || s->mapped) {
+		FN_OUT(1);
+		return 0;
+	}
+
+	/*
+	 * Send current buffer if it contains data.  Be sure to send
+	 * a full sample count.
+	 */
+	b = &s->buffers[s->usr_head];
+	mdelay(20);
+	if (b->offset &= ~3) {
+		/*wait for a buffer to become free */
+		if (wait_for_completion_interruptible(&s->wfc))
+			return 0;
+		/*
+		 * HACK ALERT !
+		 * To avoid increased complexity in the rest of the code
+		 * where full fragment sizes are assumed, we cheat a little
+		 * with the start pointer here and don't forget to restore
+		 * it later.
+		 */
+		shiftval = s->fragsize - b->offset;
+		b->offset = shiftval;
+		b->dma_addr -= shiftval;
+		b->data -= shiftval;
+		local_irq_save(flags);
+		s->bytecount -= shiftval;
+		if (++s->usr_head >= s->nbfrags)
+			s->usr_head = 0;
+
+		s->pending_frags++;
+		audio_process_dma(s);
+		local_irq_restore(flags);
+	}
+
+	/* Let's wait for all buffers to complete */
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&s->wq, &wait);
+
+	while ((s->pending_frags || (s->wfc.done < s->nbfrags))
+	       && !signal_pending(current)) {
+		schedule();
+		set_current_state(TASK_INTERRUPTIBLE);
+	}
+	set_current_state(TASK_RUNNING);
+	remove_wait_queue(&s->wq, &wait);
+
+	/* undo the pointer hack above */
+	if (shiftval) {
+		local_irq_save(flags);
+		b->dma_addr += shiftval;
+		b->data += shiftval;
+		/* ensure sane DMA code behavior if not yet processed */
+		if (b->offset != 0)
+			b->offset = s->fragsize;
+		local_irq_restore(flags);
+	}
+
+	FN_OUT(0);
+	return 0;
+}
+
+/*******************************************************************************
+ *
+ * Stop all the DMA channels of the stream
+ *
+ ******************************************************************************/
+void audio_stop_dma(audio_stream_t * s)
+{
+
+	unsigned long flags;
+	FN_IN;
+	DPRINTK("audio_stop_dma\n");
+
+	if (s->dma_spinref > 0 || !s->buffers)
+		return;
+
+	local_irq_save(flags);
+
+	davinci_stop_dma(s->master_ch);
+	s->dma_started = 0;
+
+	if (s->spin_idle) {
+#if 0
+		DMA_START(s, SPIN_ADDR, SPIN_SIZE);
+		DMA_START(s, SPIN_ADDR, SPIN_SIZE);
+#endif
+		s->dma_spinref = 2;
+	} else
+		s->dma_spinref = 0;
+
+	local_irq_restore(flags);
+
+	FN_OUT(0);
+	return;
+}
+
+/*******************************************************************************
+ *
+ * Get the dma posn
+ *
+ ******************************************************************************/
+u_int audio_get_dma_pos(audio_stream_t * s)
+{
+	audio_buf_t *b = &s->buffers[s->dma_tail];
+	u_int offset = 0;
+
+	FN_IN;
+	if (b->dma_ref) {
+		edmacc_paramentry_regs temp;
+
+		davinci_get_dma_params(s->master_ch, &temp);
+
+		if (s->input_or_output == FMODE_WRITE)
+			offset = temp.src - b->dma_addr;
+		else if (s->input_or_output == FMODE_READ)
+			offset = temp.dst - b->dma_addr;
+		if (offset >= s->fragsize)
+			offset = s->fragsize - 4;
+	} else if (s->pending_frags) {
+		offset = b->offset;
+	} else {
+		offset = 0;
+	}
+	FN_OUT(offset);
+	return offset;
+}
+
+/*******************************************************************************
+ *
+ * Reset the audio buffers
+ *
+ ******************************************************************************/
+void audio_reset(audio_stream_t * s)
+{
+	audio_buf_t *b;
+	FN_IN;
+	if (s->buffers) {
+
+		davinci_mcbsp_stop(0);
+		s->started = 0;
+		audio_stop_dma(s);
+		/* back up pointers to be ready to restart from the same spot */
+		while (s->dma_head != s->dma_tail) {
+			b = &s->buffers[s->dma_head];
+			if (b->dma_ref) {
+				b->dma_ref = 0;
+				b->offset = 0;
+			}
+			s->pending_frags++;
+			if (s->dma_head == 0)
+				s->dma_head = s->nbfrags;
+			s->dma_head--;
+		}
+		b = &s->buffers[s->dma_head];
+		if (b->dma_ref) {
+			b->offset = 0;
+			b->dma_ref = 0;
+		}
+
+		s->buffers[s->dma_head].offset = 0;
+		s->buffers[s->usr_head].offset = 0;
+		s->usr_head = s->dma_head;
+		s->pending_frags = 0;
+		init_completion(&s->wfc);
+		s->wfc.done = s->nbfrags;
+	}
+	AUDIO_QUEUE_INIT(s);
+	s->active = 0;
+	s->stopped = 0;
+
+	FN_OUT(0);
+	return;
+}
+
+/*******************************************************************************
+ *
+ * Clear any pending transfers
+ *
+ ******************************************************************************/
+void davinci_clear_sound_dma(audio_stream_t * s)
+{
+#if 0
+	FN_IN;
+	davinci_clear_dma(s->lch[s->dma_q_head]);
+	FN_OUT(0);
+#endif
+	return;
+}
+
+/*******************************************************************************
+ *
+ * DMA related functions
+ *
+ ******************************************************************************/
+static int audio_set_dma_params_play(int channel, dma_addr_t dma_ptr,
+				     u_int dma_size)
+{
+	FN_IN;
+	DPRINTK("audio_set_dma_params_play channel = %d dma_ptr = %x \
+                       dma_size=%x\n", channel, dma_ptr, dma_size);
+
+	davinci_set_dma_src_params(channel, (unsigned long)(dma_ptr), 0, 0);
+	davinci_set_dma_dest_params(channel, (unsigned long)MCBSP_DXR, 0, 0);
+	davinci_set_dma_src_index(channel, 2, 0);
+	davinci_set_dma_dest_index(channel, 0, 0);
+	davinci_set_dma_transfer_params(channel, 2, dma_size / 2, 1, 0, ASYNC);
+
+	FN_OUT(0);
+	return 0;
+}
+
+static int audio_set_dma_params_capture(int channel, dma_addr_t dma_ptr,
+					u_int dma_size)
+{
+	FN_IN;
+	DPRINTK("audio_set_dma_params_capture channel = %d dma_ptr = %x \
+                      dma_size=%x\n", channel, dma_ptr, dma_size);
+
+	davinci_set_dma_src_params(channel, (unsigned long)MCBSP_DRR, 0, 0);
+	davinci_set_dma_dest_params(channel, (unsigned long)(dma_ptr), 0, 0);
+	davinci_set_dma_src_index(channel, 0, 0);
+	davinci_set_dma_dest_index(channel, 2, 0);
+	davinci_set_dma_transfer_params(channel, 2, dma_size / 2, 1, 0, ASYNC);
+
+	FN_OUT(0);
+	return 0;
+}
+
+static int audio_start_dma_chain(audio_stream_t * s)
+{
+	int channel = s->lch[s->dma_q_head];
+	FN_IN;
+
+	if (!s->dma_started) {
+		edmacc_paramentry_regs temp;
+		davinci_get_dma_params(channel, &temp);
+		davinci_set_dma_params(s->master_ch, &temp);
+
+		davinci_start_dma(s->master_ch);
+		s->dma_started = 1;
+	}
+
+	if (!s->started) {
+		davinci_mcbsp_start(0);
+		s->started = 1;
+	}
+
+	/* else the dma itself will progress forward with out our help */
+	FN_OUT(0);
+	return 0;
+}
+
+/* Start DMA -
+ * Do the initial set of work to initialize all the channels as required.
+ * We shall then initate a transfer
+ */
+
+static int davinci_start_sound_dma(audio_stream_t * s, dma_addr_t dma_ptr,
+				   u_int dma_size)
+{
+	int ret = -EPERM;
+
+	FN_IN;
+	if (unlikely(dma_size > MAX_DMA_SIZE)) {
+		ERR("DmaSoundDma: Start: overflowed %d-%d\n", dma_size,
+		    MAX_DMA_SIZE);
+		return -EOVERFLOW;
+	}
+
+	if (AUDIO_QUEUE_FULL(s)) {
+		DPRINTK("queue full\n");
+		ret = -2;
+		goto sound_out;
+	}
+	if (s->input_or_output == FMODE_WRITE)
+		/*playback */
+	{
+		ret = audio_set_dma_params_play(s->lch[s->dma_q_tail],
+						dma_ptr, dma_size);
+	} else {
+		ret = audio_set_dma_params_capture(s->lch[s->dma_q_tail],
+						   dma_ptr, dma_size);
+	}
+	if (ret != 0) {
+		ret = -2;	/* indicate queue full */
+		goto sound_out;
+	}
+	AUDIO_INCREMENT_TAIL(s);
+	ret = audio_start_dma_chain(s);
+	if (ret) {
+		ERR("dma start failed");
+	}
+      sound_out:
+	FN_OUT(ret);
+	return ret;
+}
+
+/*******************************************************************************
+ *
+ * ISR related functions
+ *
+ ******************************************************************************/
+/* The work item handler */
+static void audio_dsr_handler(unsigned long inData)
+{
+	void *data = (void *)inData;
+	struct audio_isr_work_item *work = data;
+	audio_stream_t *s = (work->s);
+	int sound_curr_lch = work->current_lch;
+	u16 ch_status = work->ch_status;
+
+	FN_IN;
+	DPRINTK("lch=%d,status=0x%x, data=%p as=%p\n", sound_curr_lch,
+		ch_status, data, s);
+	if (AUDIO_QUEUE_EMPTY(s)) {
+		DPRINTK("Interrupt(%d)  for empty queue(h=%d, T=%d)???\n",
+			sound_curr_lch, s->dma_q_head, s->dma_q_tail);
+		DPRINTK("nbfrag=%d,pendfrags=%d,USR-H=%d, QH-%d QT-%d\n",
+			s->nbfrags, s->pending_frags, s->usr_head, s->dma_head,
+			s->dma_tail);
+		AUDIO_INCREMENT_HEAD(s);	/* Empty the queue */
+		FN_OUT(-1);
+		return;
+	}
+
+	AUDIO_INCREMENT_HEAD(s);	/* Empty the queue */
+
+	/* Try to fill again */
+	audio_dma_callback(sound_curr_lch, ch_status, s);
+	FN_OUT(0);
+
+}
+
+/* Macro to trace the IRQ calls - checks for multi-channel irqs */
+//#define IRQ_TRACE
+#ifdef IRQ_TRACE
+#define MAX_UP 10
+static char xyz[MAX_UP] = { 0 };
+static int h = 0;
+#endif
+
+/* ISRs have to be short and smart.. So we transfer every heavy duty stuff to
+ * the work item
+ */
+static void sound_dma_irq_handler(int sound_curr_lch, u16 ch_status, void *data)
+{
+	audio_stream_t *s = (audio_stream_t *) data;
+	FN_IN;
+
+	if (ch_status == DMA_COMPLETE) {
+
+#ifdef IRQ_TRACE
+		xyz[h++] = '0' + sound_curr_lch;
+		if (h == MAX_UP - 1) {
+			DPRINTK("%s-", xyz);
+			h = 0;
+		}
+#endif
+
+		sound_curr_lch = s->lch[s->dma_q_head];
+
+		DPRINTK("lch=%d,status=0x%x, data=%p\n", sound_curr_lch,
+			ch_status, data);
+
+		if (AUDIO_QUEUE_LAST(s)) {
+			audio_stream_t *s = data;
+			audio_buf_t *b = &s->buffers[s->dma_tail];
+
+			if (s->dma_spinref > 0) {
+				s->dma_spinref--;
+			} else if (!s->buffers) {
+				DPRINTK
+				    ("davinci_audio: received DMA IRQ for non\
+                              existent buffers!\n");
+				return;
+			} else if (b->dma_ref && --b->dma_ref == 0 &&
+				   b->offset >= s->fragsize) {
+				/* This fragment is done */
+				b->offset = 0;
+				s->bytecount += s->fragsize;
+				s->fragcount++;
+				s->dma_spinref = -s->dma_spinref;
+
+				if (++s->dma_tail >= s->nbfrags)
+					s->dma_tail = 0;
+
+				if (!s->mapped) {
+					complete(&s->wfc);
+				} else
+					s->pending_frags++;
+
+				wake_up(&s->wq);
+			}
+
+			AUDIO_INCREMENT_HEAD(s);
+			audio_stop_dma(s);
+			return;
+		}
+
+		/* Start the work item  - we ping pong the work items */
+		if (!work_item_running) {
+			work1.current_lch = sound_curr_lch;
+			work1.ch_status = ch_status;
+			work1.s = s;
+			/* schedule tasklet 1 */
+			tasklet_schedule(&audio_isr_work1);
+			work_item_running = 1;
+		} else {
+			work2.current_lch = sound_curr_lch;
+			work2.ch_status = ch_status;
+			work2.s = s;
+			/* schedule tasklet 2 */
+			tasklet_schedule(&audio_isr_work2);
+			work_item_running = 0;
+		}
+	} else {
+		DPRINTK("Error in DMA \n");
+	}
+
+	FN_OUT(0);
+	return;
+}
+
+/* The call back that handles buffer stuff */
+static void audio_dma_callback(int lch, u16 ch_status, void *data)
+{
+	audio_stream_t *s = data;
+	audio_buf_t *b = &s->buffers[s->dma_tail];
+	FN_IN;
+
+	if (s->dma_spinref > 0) {
+		s->dma_spinref--;
+	} else if (!s->buffers) {
+		DPRINTK
+		    ("davinci_audio: received DMA IRQ for non existent buffers!\n");
+		return;
+	} else if (b->dma_ref && --b->dma_ref == 0 && b->offset >= s->fragsize) {
+		/* This fragment is done */
+		b->offset = 0;
+		s->bytecount += s->fragsize;
+		s->fragcount++;
+		s->dma_spinref = -s->dma_spinref;
+
+		if (++s->dma_tail >= s->nbfrags)
+			s->dma_tail = 0;
+
+		if (!s->mapped) {
+			complete(&s->wfc);
+		} else
+			s->pending_frags++;
+
+		wake_up(&s->wq);
+	}
+
+	audio_process_dma(s);
+
+	FN_OUT(0);
+	return;
+}
+
+/*******************************************************************************
+ *
+ * audio_get_dma_callback(): return the dma interface call back function
+ *
+ ******************************************************************************/
+dma_callback_t audio_get_dma_callback(void)
+{
+	FN_IN;
+	FN_OUT(0);
+	return audio_dma_callback;
+}
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION
+    ("Common DMA handling for Audio driver on DAVINCI processors");
+MODULE_LICENSE("GPL");
+
+EXPORT_SYMBOL(davinci_clear_sound_dma);
+EXPORT_SYMBOL(davinci_request_sound_dma);
+EXPORT_SYMBOL(davinci_free_sound_dma);
+
+EXPORT_SYMBOL(audio_get_dma_callback);
+EXPORT_SYMBOL(audio_setup_buf);
+EXPORT_SYMBOL(audio_process_dma);
+EXPORT_SYMBOL(audio_prime_rx);
+EXPORT_SYMBOL(audio_set_fragments);
+EXPORT_SYMBOL(audio_sync);
+EXPORT_SYMBOL(audio_stop_dma);
+EXPORT_SYMBOL(audio_get_dma_pos);
+EXPORT_SYMBOL(audio_reset);
+EXPORT_SYMBOL(audio_discard_buf);
diff --git a/sound/oss/davinci-audio-dma-intfc.h b/sound/oss/davinci-audio-dma-intfc.h
new file mode 100644
index 0000000..2d48cd9a
--- /dev/null
+++ b/sound/oss/davinci-audio-dma-intfc.h
@@ -0,0 +1,63 @@
+/*
+ * linux/sound/oss/davinci-audio-dma-intfc.h
+ *
+ * Common audio DMA handling for the Davinci processors
+ *
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ *
+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *
+ * 2005-10-01   Rishi Bhattacharya / Sharath Kumar - Added support for TI Davinci DM644x processor
+ */
+
+#ifndef __DAVINCI_AUDIO_DMA_INTFC_H
+#define __DAVINCI_AUDIO_DMA_INTFC_H
+
+/******************************* INCLUDES *************************************/
+
+/* Requires davinci-audio.h */
+#include "davinci-audio.h"
+
+/************************** GLOBAL MACROS *************************************/
+
+/* Provide the Macro interfaces common across platforms */
+#define DMA_REQUEST(e,s, cb)   {e=davinci_request_sound_dma(s->dma_dev, s->id, s, &s->master_ch, &s->lch);}
+#define DMA_FREE(s)             davinci_free_sound_dma(s->master_ch,&s->lch)
+#define DMA_CLEAR(s)            davinci_clear_sound_dma(s)
+
+/************************** GLOBAL DATA STRUCTURES ****************************/
+
+typedef void (*dma_callback_t) (int lch, u16 ch_status, void *data);
+
+/************************** GLOBAL FUNCTIONS **********************************/
+
+dma_callback_t audio_get_dma_callback(void);
+int audio_setup_buf(audio_stream_t * s);
+int audio_process_dma(audio_stream_t * s);
+void audio_prime_rx(audio_state_t * state);
+int audio_set_fragments(audio_stream_t * s, int val);
+int audio_sync(struct file *file);
+void audio_stop_dma(audio_stream_t * s);
+u_int audio_get_dma_pos(audio_stream_t * s);
+void audio_reset(audio_stream_t * s);
+void audio_discard_buf(audio_stream_t * s);
+
+/**************** ARCH SPECIFIC FUNCIONS **************************************/
+
+void davinci_clear_sound_dma(audio_stream_t * s);
+
+int davinci_request_sound_dma(int device_id, const char *device_name,
+			      void *data, int *master_ch, int **channels);
+int davinci_free_sound_dma(int master_ch, int **channels);
+
+#endif				/* #ifndef __DAVINCI_AUDIO_DMA_INTFC_H */
diff --git a/sound/oss/davinci-audio.c b/sound/oss/davinci-audio.c
new file mode 100644
index 0000000..b8b2fbc
--- /dev/null
+++ b/sound/oss/davinci-audio.c
@@ -0,0 +1,1176 @@
+/*
+ * linux/sound/oss/davinci-audio.c
+ *
+ * Common audio handling for the Davinci processors
+ *
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ *
+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *
+ * 2004/08/12   Nishanth Menon - Modified to integrate Audio requirements on 1610,1710 platforms
+ *
+ * 2004-11-01   Nishanth Menon - modified to support 16xx and 17xx
+ *                platform multi channel chaining.
+ *
+ * 2004-11-04   Nishanth Menon - Added support for power management
+ *
+ * 2004-12-17   Nishanth Menon - Provided proper module handling support
+ *
+ * 2005-10-01   Rishi Bhattacharya - Adapted to TI Davinci Family of processors
+ */
+
+/***************************** INCLUDES ************************************/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/poll.h>
+#include <linux/pm.h>
+#include <linux/errno.h>
+#include <linux/sound.h>
+#include <linux/soundcard.h>
+#include <linux/sysrq.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+
+#include <asm/uaccess.h>
+#include <asm/io.h>
+#include <asm/hardware.h>
+#include <asm/semaphore.h>
+
+#include "davinci-audio-dma-intfc.h"
+#include "davinci-audio.h"
+
+/***************************** MACROS ************************************/
+
+#undef DEBUG
+//#define DEBUG
+#ifdef DEBUG
+#define DPRINTK  printk
+#define FN_IN printk("[davinci_audio.c:[%s] start\n", __FUNCTION__)
+#define FN_OUT(n) printk("[davinci_audio.c:[%s] end(%d)\n", __FUNCTION__ , n)
+#else
+#define DPRINTK( x... )
+#define FN_IN
+#define FN_OUT(x)
+#endif
+
+#define DAVINCI_AUDIO_NAME              "davinci-audio"
+
+#define AUDIO_NBFRAGS_DEFAULT   4
+#define AUDIO_FRAGSIZE_DEFAULT   3072
+
+/*************/
+
+/* HACK ALERT!: These values will bave to be tuned as this is a trade off b/w
+ * Sampling Rate vs buffer size and delay we are prepared to do before giving up
+ */
+#define MAX_QUEUE_FULL_RETRIES 1000000
+#define QUEUE_WAIT_TIME        10
+
+#define AUDIO_ACTIVE(state)     ((state)->rd_ref || (state)->wr_ref)
+
+#define SPIN_ADDR               (dma_addr_t)0
+#define SPIN_SIZE               2048
+
+/********************** MODULES SPECIFIC FUNCTION PROTOTYPES ***************/
+
+static int audio_write(struct file *file, const char *buffer,
+		       size_t count, loff_t * ppos);
+
+static int audio_read(struct file *file, char *buffer, size_t count,
+		      loff_t * ppos);
+
+static int audio_mmap(struct file *file, struct vm_area_struct *vma);
+
+static unsigned int audio_poll(struct file *file,
+			       struct poll_table_struct *wait);
+
+static loff_t audio_llseek(struct file *file, loff_t offset, int origin);
+
+static int audio_ioctl(struct inode *inode, struct file *file, uint cmd,
+		       ulong arg);
+
+static int audio_open(struct inode *inode, struct file *file);
+
+static int audio_release(struct inode *inode, struct file *file);
+
+static int audio_probe(struct device *dev);
+
+static int audio_remove(struct device *dev);
+
+static void audio_shutdown(struct device *dev);
+
+static int audio_suspend(struct device *dev, pm_message_t state);
+
+static int audio_resume(struct device *dev);
+
+static void audio_free(struct device *dev);
+
+/***************************** Data Structures ********************************/
+
+/*
+ * The function pointer set to be registered by the codec.
+ */
+static audio_state_t audio_state = { 0 };
+
+/* DMA Call back function */
+static dma_callback_t audio_dma_callback = 0;
+
+/* File Ops structure */
+static struct file_operations davinci_audio_fops = {
+	.open = audio_open,
+	.release = audio_release,
+	.write = audio_write,
+	.read = audio_read,
+	.mmap = audio_mmap,
+	.poll = audio_poll,
+	.ioctl = audio_ioctl,
+	.llseek = audio_llseek,
+	.owner = THIS_MODULE
+};
+
+/* Driver information */
+static struct device_driver davinci_audio_driver = {
+	.name = DAVINCI_AUDIO_NAME,
+	.bus = &platform_bus_type,
+	.probe = audio_probe,
+	.remove = audio_remove,
+	.suspend = audio_suspend,
+	.resume = audio_resume,
+	.shutdown = audio_shutdown,
+};
+
+/* Device Information */
+static struct platform_device davinci_audio_device = {
+	.name = DAVINCI_AUDIO_NAME,
+	.dev = {
+		.driver_data = &audio_state,
+		.release = audio_free,
+		},
+	.id = 0,
+};
+
+/***************************** GLOBAL FUNCTIONs *******************************/
+
+/* Power Management Functions for Linux Device Model  */
+/* DEBUG PUPOSES ONLY! */
+#ifdef CONFIG_PM
+//#undef CONFIG_PM
+#endif
+
+#ifdef CONFIG_PM
+/*******************************************************************************
+ *
+ * audio_ldm_suspend(): Suspend operation
+ *
+ ******************************************************************************/
+static int audio_ldm_suspend(void *data)
+{
+	audio_state_t *state = data;
+
+	FN_IN;
+
+	/*
+	 * Reject the suspend request if we are already actively transmitting data
+	 * Rationale: We dont want to be suspended while in the middle of a call!
+	 */
+	if (AUDIO_ACTIVE(state) && state->hw_init) {
+		DPRINTK("Audio device Active, Cannot Suspend");
+		return -EPERM;
+#if 0
+		/* NOTE:
+		 * This Piece of code is commented out in hope
+		 * That one day we would need to suspend the device while
+		 * audio operations are in progress and resume the operations
+		 * once the resume is done.
+		 * This is just a sample implementation of how it could be done.
+		 * Currently NOT SUPPORTED
+		 */
+		audio_stream_t *is = state->input_stream;
+		audio_stream_t *os = state->output_stream;
+		int stopstate;
+		if (is && is->buffers) {
+			DPRINTK("IS Suspend\n");
+			stopstate = is->stopped;
+			audio_stop_dma(is);
+			DMA_CLEAR(is);
+			is->dma_spinref = 0;
+			is->stopped = stopstate;
+		}
+		if (os && os->buffers) {
+			DPRINTK("OS Suspend\n");
+			stopstate = os->stopped;
+			audio_stop_dma(os);
+			DMA_CLEAR(os);
+			os->dma_spinref = 0;
+			os->stopped = stopstate;
+		}
+#endif
+	}
+
+	FN_OUT(0);
+	return 0;
+}
+
+/*******************************************************************************
+ *
+ * audio_ldm_resume(): Resume Operations
+ *
+ ******************************************************************************/
+static int audio_ldm_resume(void *data)
+{
+	audio_state_t *state = data;
+
+	FN_IN;
+	if (AUDIO_ACTIVE(state) && state->hw_init) {
+		/* Should never occur - since we never suspend with active state */
+		BUG();
+		return -EPERM;
+#if 0
+		/* NOTE:
+		 * This Piece of code is commented out in hope
+		 * That one day we would need to suspend the device while
+		 * audio operations are in progress and resume the operations
+		 * once the resume is done.
+		 * This is just a sample implementation of how it could be done.
+		 * Currently NOT SUPPORTED
+		 */
+		audio_stream_t *is = state->input_stream;
+		audio_stream_t *os = state->output_stream;
+		if (os && os->buffers) {
+			DPRINTK("OS Resume\n");
+			audio_reset(os);
+			audio_process_dma(os);
+		}
+		if (is && is->buffers) {
+			DPRINTK("IS Resume\n");
+			audio_reset(is);
+			audio_process_dma(is);
+		}
+#endif
+	}
+	FN_OUT(0);
+	return 0;
+}
+#endif				/* End of #ifdef CONFIG_PM */
+
+/*******************************************************************************
+ *
+ * audio_free(): The Audio driver release function
+ * This is a dummy function required by the platform driver
+ *
+ ******************************************************************************/
+static void audio_free(struct device *dev)
+{
+	/* Nothing to Release! */
+}
+
+/*******************************************************************************
+ *
+ * audio_probe(): The Audio driver probe function
+ * WARNING!!!!  : It is expected that the codec would have registered with us by now
+ *
+ ******************************************************************************/
+static int audio_probe(struct device *dev)
+{
+	int ret;
+	FN_IN;
+	if (!audio_state.hw_probe) {
+		DPRINTK("Probe Function Not Registered\n");
+		return -ENODEV;
+	}
+	ret = audio_state.hw_probe();
+	FN_OUT(ret);
+	return ret;
+}
+
+/*******************************************************************************
+ *
+ * audio_remove() Function to handle removal operations
+ *
+ ******************************************************************************/
+static int audio_remove(struct device *dev)
+{
+	FN_IN;
+	if (audio_state.hw_remove) {
+		audio_state.hw_remove();
+	}
+	FN_OUT(0);
+	return 0;
+}
+
+/*******************************************************************************
+ *
+ * audio_shutdown(): Function to handle shutdown operations
+ *
+ ******************************************************************************/
+static void audio_shutdown(struct device *dev)
+{
+	FN_IN;
+	if (audio_state.hw_cleanup) {
+		audio_state.hw_cleanup();
+	}
+	FN_OUT(0);
+	return;
+}
+
+/*******************************************************************************
+ *
+ * audio_suspend(): Function to handle suspend operations
+ *
+ ******************************************************************************/
+static int audio_suspend(struct device *dev, pm_message_t state)
+{
+	int ret = 0;
+
+#ifdef CONFIG_PM
+	void *data = dev->driver_data;
+	FN_IN;
+	if (audio_state.hw_suspend) {
+		ret = audio_ldm_suspend(data);
+		if (ret == 0)
+			ret = audio_state.hw_suspend();
+	}
+	if (ret) {
+		DPRINTK("Audio Suspend Failed \n");
+	} else {
+		DPRINTK("Audio Suspend Success \n");
+	}
+#endif				/* CONFIG_PM */
+
+	FN_OUT(ret);
+	return ret;
+}
+
+/*******************************************************************************
+ *
+ * audio_resume(): Function to handle resume operations
+ *
+ ******************************************************************************/
+static int audio_resume(struct device *dev)
+{
+	int ret = 0;
+
+#ifdef  CONFIG_PM
+	void *data = dev->driver_data;
+	FN_IN;
+	if (audio_state.hw_resume) {
+		ret = audio_ldm_resume(data);
+		if (ret == 0)
+			ret = audio_state.hw_resume();
+	}
+	if (ret) {
+		DPRINTK(" Audio Resume Failed \n");
+	} else {
+		DPRINTK(" Audio Resume Success \n");
+	}
+#endif				/* CONFIG_PM */
+
+	FN_OUT(ret);
+	return ret;
+}
+
+/*******************************************************************************
+ *
+ * audio_get_fops(): Return the fops required to get the function pointers of
+ *                   DAVINCI Audio Driver
+ *
+ ******************************************************************************/
+struct file_operations *audio_get_fops(void)
+{
+	FN_IN;
+	FN_OUT(0);
+	return &davinci_audio_fops;
+}
+
+/*******************************************************************************
+ *
+ * audio_register_codec(): Register a Codec fn points using this function
+ * WARNING!!!!!          : Codecs should ensure that they do so! no sanity checks
+ *                         during runtime is done due to obvious performance
+ *                         penalties.
+ *
+ ******************************************************************************/
+int audio_register_codec(audio_state_t * codec_state)
+{
+	int ret;
+	FN_IN;
+
+	/* We dont handle multiple codecs now */
+	if (audio_state.hw_init) {
+		DPRINTK(" Codec Already registered\n");
+		return -EPERM;
+	}
+
+	/* Grab the dma Callback */
+	audio_dma_callback = audio_get_dma_callback();
+	if (!audio_dma_callback) {
+		DPRINTK("Unable to get call back function\n");
+		return -EPERM;
+	}
+
+	/* Sanity checks */
+	if (!codec_state) {
+		DPRINTK("NULL ARGUMENT!\n");
+		return -EPERM;
+	}
+
+	if (!codec_state->hw_probe || !codec_state->hw_init
+	    || !codec_state->hw_shutdown || !codec_state->client_ioctl) {
+		DPRINTK
+		    ("Required Fn Entry point Missing probe=%p init=%p,down=%p,ioctl=%p!\n",
+		     codec_state->hw_probe, codec_state->hw_init,
+		     codec_state->hw_shutdown, codec_state->client_ioctl);
+		return -EPERM;
+	}
+
+	memcpy(&audio_state, codec_state, sizeof(audio_state_t));
+	sema_init(&audio_state.sem, 1);
+
+	ret = platform_device_register(&davinci_audio_device);
+	if (ret != 0) {
+		DPRINTK("Platform dev_register failed =%d\n", ret);
+		ret = -ENODEV;
+		goto register_out;
+	}
+
+	ret = driver_register(&davinci_audio_driver);
+	if (ret != 0) {
+		DPRINTK("Device Register failed =%d\n", ret);
+		ret = -ENODEV;
+		platform_device_unregister(&davinci_audio_device);
+		goto register_out;
+	}
+
+	DPRINTK("audio driver register success\n");
+
+      register_out:
+
+	FN_OUT(ret);
+	return ret;
+}
+
+/*******************************************************************************
+ *
+ * audio_unregister_codec(): Un-Register a Codec using this function
+ *
+ ******************************************************************************/
+int audio_unregister_codec(audio_state_t * codec_state)
+{
+	FN_IN;
+
+	/* We dont handle multiple codecs now */
+	if (!audio_state.hw_init) {
+		DPRINTK(" No Codec registered\n");
+		return -EPERM;
+	}
+	/* Security check */
+	if (audio_state.hw_init != codec_state->hw_init) {
+		DPRINTK
+		    ("Attempt to unregister codec which was not registered with us\n");
+		return -EPERM;
+	}
+
+	driver_unregister(&davinci_audio_driver);
+	platform_device_unregister(&davinci_audio_device);
+
+	memset(&audio_state, 0, sizeof(audio_state_t));
+
+	FN_OUT(0);
+	return 0;
+}
+
+/***************************** MODULES SPECIFIC FUNCTION **********************/
+
+/*******************************************************************************
+ *
+ * audio_write(): Exposed to write() call
+ *
+ ******************************************************************************/
+static int
+audio_write(struct file *file, const char *buffer, size_t count, loff_t * ppos)
+{
+	const char *buffer0 = buffer;
+	audio_state_t *state = file->private_data;
+	audio_stream_t *s = state->output_stream;
+	int chunksize, ret = 0;
+
+	DPRINTK("audio_write: count=%d\n", count);
+	if (*ppos != file->f_pos) {
+		DPRINTK("FPOS not ppos ppos=0x%x fpos =0x%x\n", (u32) * ppos,
+			(u32) file->f_pos);
+		return -ESPIPE;
+	}
+	if (s->mapped) {
+		DPRINTK("s already mapped\n");
+		return -ENXIO;
+	}
+	if (!s->buffers && audio_setup_buf(s)) {
+		DPRINTK("NO MEMORY\n");
+		return -ENOMEM;
+	}
+
+	while (count > 0) {
+		audio_buf_t *b = &s->buffers[s->usr_head];
+
+		/* Wait for a buffer to become free */
+		if (file->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			if (!s->wfc.done)
+				break;
+		} else {
+			ret = -ERESTARTSYS;
+			if (wait_for_completion_interruptible(&s->wfc))
+				break;
+		}
+
+		/* Feed the current buffer */
+		chunksize = s->fragsize - b->offset;
+		if (chunksize > count)
+			chunksize = count;
+		DPRINTK("write %d to %d\n", chunksize, s->usr_head);
+		if (copy_from_user(b->data + b->offset, buffer, chunksize)) {
+			DPRINTK("Audio: CopyFrom User failed \n");
+			complete(&s->wfc);
+			return -EFAULT;
+		}
+
+		buffer += chunksize;
+		count -= chunksize;
+		b->offset += chunksize;
+
+		if (b->offset < s->fragsize) {
+			complete(&s->wfc);
+			break;
+		}
+
+		/* Update pointers and send current fragment to DMA */
+		b->offset = 0;
+		if (++s->usr_head >= s->nbfrags)
+			s->usr_head = 0;
+		/* Add the num of frags pending */
+		s->pending_frags++;
+		s->active = 1;
+
+		audio_process_dma(s);
+	}
+
+	if ((buffer - buffer0))
+		ret = buffer - buffer0;
+
+	DPRINTK("audio_write: return=%d\n", ret);
+	return ret;
+}
+
+/*******************************************************************************
+ *
+ * audio_read(): Exposed as read() function
+ *
+ ******************************************************************************/
+static int
+audio_read(struct file *file, char *buffer, size_t count, loff_t * ppos)
+{
+	char *buffer0 = buffer;
+	audio_state_t *state = file->private_data;
+	audio_stream_t *s = state->input_stream;
+	int chunksize, ret = 0;
+	unsigned long flags;
+
+	DPRINTK("audio_read: count=%d\n", count);
+
+	if (*ppos != file->f_pos) {
+		DPRINTK("AudioRead - FPOS not ppos ppos=0x%x fpos =0x%x\n",
+			(u32) * ppos, (u32) file->f_pos);
+		return -ESPIPE;
+	}
+	if (s->mapped) {
+		DPRINTK("AudioRead - s already mapped\n");
+		return -ENXIO;
+	}
+
+	if (!s->active) {
+		if (!s->buffers && audio_setup_buf(s)) {
+			DPRINTK("AudioRead - No Memory\n");
+			return -ENOMEM;
+		}
+		audio_prime_rx(state);
+	}
+
+	while (count > 0) {
+		audio_buf_t *b = &s->buffers[s->usr_head];
+
+		/* Wait for a buffer to become full */
+		if (file->f_flags & O_NONBLOCK) {
+			ret = -EAGAIN;
+			if (!s->wfc.done)
+				break;
+		} else {
+			ret = -ERESTARTSYS;
+			if (wait_for_completion_interruptible(&s->wfc))
+				break;
+		}
+
+		/* Grab data from the current buffer */
+		chunksize = s->fragsize - b->offset;
+		if (chunksize > count)
+			chunksize = count;
+
+		DPRINTK("read %d from %d\n", chunksize, s->usr_head);
+		if (copy_to_user(buffer, b->data + b->offset, chunksize)) {
+			complete(&s->wfc);
+			return -EFAULT;
+		}
+		buffer += chunksize;
+		count -= chunksize;
+		b->offset += chunksize;
+		if (b->offset < s->fragsize) {
+			complete(&s->wfc);
+			break;
+		}
+
+		/* Update pointers and return current fragment to DMA */
+		local_irq_save(flags);
+		b->offset = 0;
+		if (++s->usr_head >= s->nbfrags)
+			s->usr_head = 0;
+
+		s->pending_frags++;
+		local_irq_restore(flags);
+		DPRINTK(KERN_INFO
+			"calling audio_process_dma from audio_read\n");
+		audio_process_dma(s);
+	}
+
+	if ((buffer - buffer0))
+		ret = buffer - buffer0;
+	DPRINTK("audio_read: return=%d\n", ret);
+	return ret;
+}
+
+/*******************************************************************************
+ *
+ * audio_mmap(): Exposed as mmap Function
+ * !!WARNING: Still under development
+ *
+ ******************************************************************************/
+static int audio_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	audio_state_t *state = file->private_data;
+	audio_stream_t *s;
+	unsigned long size, vma_addr;
+	int i, ret = 0;
+
+	FN_IN;
+	if (vma->vm_pgoff != 0)
+		return -EINVAL;
+
+	if (vma->vm_flags & VM_WRITE) {
+		if (!state->wr_ref)
+			return -EINVAL;;
+		s = state->output_stream;
+	} else if (vma->vm_flags & VM_READ) {
+		if (!state->rd_ref)
+			return -EINVAL;
+		s = state->input_stream;
+	} else
+		return -EINVAL;
+
+	if (s->mapped)
+		return -EINVAL;
+	size = vma->vm_end - vma->vm_start;
+	if (size != s->fragsize * s->nbfrags)
+		return -EINVAL;
+	if (!s->buffers && audio_setup_buf(s))
+		return -ENOMEM;
+	vma_addr = vma->vm_start;
+	for (i = 0; i < s->nbfrags; i++) {
+		audio_buf_t *buf = &s->buffers[i];
+		if (!buf->master)
+			continue;
+#if 0
+		ret =
+		    remap_pfn_range(vma, vma_addr, buf->dma_addr >> PAGE_SHIFT,
+				    buf->master, vma->vm_page_prot);
+#endif
+		if (ret)
+			return ret;
+		vma_addr += buf->master;
+	}
+	s->mapped = 1;
+
+	FN_OUT(0);
+	return 0;
+}
+
+/*******************************************************************************
+ *
+ * audio_poll(): Exposed as poll function
+ *
+ ******************************************************************************/
+static unsigned int
+audio_poll(struct file *file, struct poll_table_struct *wait)
+{
+	audio_state_t *state = file->private_data;
+	audio_stream_t *is = state->input_stream;
+	audio_stream_t *os = state->output_stream;
+	unsigned int mask = 0;
+
+	DPRINTK("audio_poll(): mode=%s%s\n",
+		(file->f_mode & FMODE_READ) ? "r" : "",
+		(file->f_mode & FMODE_WRITE) ? "w" : "");
+
+	if (file->f_mode & FMODE_READ) {
+		/* Start audio input if not already active */
+		if (!is->active) {
+			if (!is->buffers && audio_setup_buf(is))
+				return -ENOMEM;
+			audio_prime_rx(state);
+		}
+		poll_wait(file, &is->wq, wait);
+	}
+
+	if (file->f_mode & FMODE_WRITE) {
+		if (!os->buffers && audio_setup_buf(os))
+			return -ENOMEM;
+		poll_wait(file, &os->wq, wait);
+	}
+
+	if (file->f_mode & FMODE_READ)
+		if ((is->mapped && is->bytecount > 0) ||
+		    (!is->mapped && is->wfc.done > 0))
+			mask |= POLLIN | POLLRDNORM;
+
+	if (file->f_mode & FMODE_WRITE)
+		if ((os->mapped && os->bytecount > 0) ||
+		    (!os->mapped && os->wfc.done > 0))
+			mask |= POLLOUT | POLLWRNORM;
+
+	DPRINTK("audio_poll() returned mask of %s%s\n",
+		(mask & POLLIN) ? "r" : "", (mask & POLLOUT) ? "w" : "");
+
+	FN_OUT(mask);
+	return mask;
+}
+
+/*******************************************************************************
+ *
+ * audio_llseek(): Exposed as lseek() function.
+ *
+ ******************************************************************************/
+static loff_t audio_llseek(struct file *file, loff_t offset, int origin)
+{
+	FN_IN;
+	FN_OUT(0);
+	return -ESPIPE;
+}
+
+/*******************************************************************************
+ *
+ * audio_ioctl(): Handles generic ioctls. If there is a request for something this
+ * fn cannot handle, its then given to client specific ioctl routine, that will take
+ * up platform specific requests
+ *
+ ******************************************************************************/
+static int
+audio_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
+{
+	audio_state_t *state = file->private_data;
+	audio_stream_t *os = state->output_stream;
+	audio_stream_t *is = state->input_stream;
+	long val;
+
+	DPRINTK(__FILE__ " audio_ioctl 0x%08x\n", cmd);
+
+	/* dispatch based on command */
+	switch (cmd) {
+	case OSS_GETVERSION:
+		return put_user(SOUND_VERSION, (int *)arg);
+
+	case SNDCTL_DSP_GETBLKSIZE:
+		if (file->f_mode & FMODE_WRITE)
+			return put_user(os->fragsize, (int *)arg);
+		else
+			return put_user(is->fragsize, (int *)arg);
+
+	case SNDCTL_DSP_GETCAPS:
+		val = DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP;
+		if (is && os)
+			val |= DSP_CAP_DUPLEX;
+		FN_OUT(1);
+		return put_user(val, (int *)arg);
+
+	case SNDCTL_DSP_SETFRAGMENT:
+		if (get_user(val, (long *)arg)) {
+			FN_OUT(2);
+			return -EFAULT;
+		}
+		if (file->f_mode & FMODE_READ) {
+			int ret = audio_set_fragments(is, val);
+			if (ret < 0) {
+				FN_OUT(3);
+				return ret;
+			}
+			ret = put_user(ret, (int *)arg);
+			if (ret) {
+				FN_OUT(4);
+				return ret;
+			}
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			int ret = audio_set_fragments(os, val);
+			if (ret < 0) {
+				FN_OUT(5);
+				return ret;
+			}
+			ret = put_user(ret, (int *)arg);
+			if (ret) {
+				FN_OUT(6);
+				return ret;
+			}
+		}
+		FN_OUT(7);
+		return 0;
+
+	case SNDCTL_DSP_SYNC:
+		FN_OUT(8);
+		return audio_sync(file);
+
+	case SNDCTL_DSP_SETDUPLEX:
+		FN_OUT(9);
+		return 0;
+
+	case SNDCTL_DSP_POST:
+		FN_OUT(10);
+		return 0;
+
+	case SNDCTL_DSP_GETTRIGGER:
+		val = 0;
+		if (file->f_mode & FMODE_READ && is->active && !is->stopped)
+			val |= PCM_ENABLE_INPUT;
+		if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
+			val |= PCM_ENABLE_OUTPUT;
+		FN_OUT(11);
+		return put_user(val, (int *)arg);
+
+	case SNDCTL_DSP_SETTRIGGER:
+		if (get_user(val, (int *)arg)) {
+			FN_OUT(12);
+			return -EFAULT;
+		}
+		if (file->f_mode & FMODE_READ) {
+			if (val & PCM_ENABLE_INPUT) {
+				unsigned long flags;
+				if (!is->active) {
+					if (!is->buffers && audio_setup_buf(is)) {
+						FN_OUT(13);
+						return -ENOMEM;
+					}
+					audio_prime_rx(state);
+				}
+				local_irq_save(flags);
+				is->stopped = 0;
+				local_irq_restore(flags);
+				audio_process_dma(is);
+
+			} else {
+				is->stopped = 1;
+				audio_stop_dma(is);
+			}
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			if (val & PCM_ENABLE_OUTPUT) {
+				unsigned long flags;
+				if (!os->buffers && audio_setup_buf(os)) {
+					FN_OUT(14);
+					return -ENOMEM;
+				}
+				local_irq_save(flags);
+				if (os->mapped && !os->pending_frags) {
+					os->pending_frags = os->nbfrags;
+					init_completion(&os->wfc);
+					os->wfc.done = 0;
+					os->active = 1;
+				}
+				os->stopped = 0;
+				local_irq_restore(flags);
+				audio_process_dma(os);
+			} else {
+				os->stopped = 1;
+				audio_stop_dma(os);
+			}
+		}
+		FN_OUT(15);
+		return 0;
+
+	case SNDCTL_DSP_GETOPTR:
+	case SNDCTL_DSP_GETIPTR:
+		{
+			count_info inf = { 0, };
+			audio_stream_t *s =
+			    (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
+			int bytecount, offset;
+			unsigned long flags;
+
+			if ((s == is && !(file->f_mode & FMODE_READ)) ||
+			    (s == os && !(file->f_mode & FMODE_WRITE))) {
+				FN_OUT(16);
+				return -EINVAL;
+			}
+			if (s->active) {
+				local_irq_save(flags);
+				offset = audio_get_dma_pos(s);
+				inf.ptr = s->dma_tail * s->fragsize + offset;
+				bytecount = s->bytecount + offset;
+				s->bytecount = -offset;
+				inf.blocks = s->fragcount;
+				s->fragcount = 0;
+				local_irq_restore(flags);
+				if (bytecount < 0)
+					bytecount = 0;
+				inf.bytes = bytecount;
+			}
+			FN_OUT(17);
+			return copy_to_user((void *)arg, &inf, sizeof(inf));
+		}
+
+	case SNDCTL_DSP_GETOSPACE:
+	case SNDCTL_DSP_GETISPACE:
+		{
+			audio_buf_info inf = { 0, };
+			audio_stream_t *s =
+			    (cmd == SNDCTL_DSP_GETOSPACE) ? os : is;
+			audio_buf_t *b = NULL;
+
+			if ((s == is && !(file->f_mode & FMODE_READ)) ||
+			    (s == os && !(file->f_mode & FMODE_WRITE))) {
+				FN_OUT(18);
+				return -EINVAL;
+			}
+			if (!s->buffers && audio_setup_buf(s)) {
+				FN_OUT(19);
+				return -ENOMEM;
+			}
+			b = &s->buffers[s->usr_head];
+			inf.bytes = s->wfc.done * s->fragsize;
+			inf.bytes -= b->offset;
+			if(inf.bytes < 0)
+				inf.bytes = 0;
+
+			inf.fragments = inf.bytes / s->fragsize;
+			inf.fragsize = s->fragsize;
+			inf.fragstotal = s->nbfrags;
+			FN_OUT(20);
+			return copy_to_user((void *)arg, &inf, sizeof(inf));
+		}
+
+	case SNDCTL_DSP_NONBLOCK:
+		file->f_flags |= O_NONBLOCK;
+		FN_OUT(21);
+		return 0;
+
+	case SNDCTL_DSP_RESET:
+		if (file->f_mode & FMODE_READ) {
+			audio_reset(is);
+			if (state->need_tx_for_rx) {
+				unsigned long flags;
+				local_irq_save(flags);
+				os->spin_idle = 0;
+				local_irq_restore(flags);
+			}
+		}
+		if (file->f_mode & FMODE_WRITE) {
+			audio_reset(os);
+		}
+		FN_OUT(22);
+		return 0;
+
+	default:
+		/*
+		 * Let the client of this module handle the
+		 * non generic ioctls
+		 */
+		FN_OUT(23);
+		return state->client_ioctl(inode, file, cmd, arg);
+	}
+
+	FN_OUT(0);
+	return 0;
+}
+
+/*******************************************************************************
+ *
+ * audio_open(): Exposed as open() function
+ *
+ ******************************************************************************/
+static int audio_open(struct inode *inode, struct file *file)
+{
+	audio_state_t *state = (&audio_state);
+	audio_stream_t *os = state->output_stream;
+	audio_stream_t *is = state->input_stream;
+	int err, need_tx_dma;
+	static unsigned char aic33_init_flag = 0;
+
+	FN_IN;
+
+	/* Lock the module */
+	if (!try_module_get(THIS_MODULE)) {
+		DPRINTK("Failed to get module\n");
+		return -ESTALE;
+	}
+	/* Lock the codec module */
+	if (!try_module_get(state->owner)) {
+		DPRINTK("Failed to get codec module\n");
+		module_put(THIS_MODULE);
+		return -ESTALE;
+	}
+
+	down(&state->sem);
+
+	/* access control */
+	err = -ENODEV;
+	if ((file->f_mode & FMODE_WRITE) && !os)
+		goto out;
+	if ((file->f_mode & FMODE_READ) && !is)
+		goto out;
+	err = -EBUSY;
+	if ((file->f_mode & FMODE_WRITE) && state->wr_ref)
+		goto out;
+	if ((file->f_mode & FMODE_READ) && state->rd_ref)
+		goto out;
+	err = -EINVAL;
+	if ((file->f_mode & FMODE_READ) && state->need_tx_for_rx && !os)
+		goto out;
+
+	/* request DMA channels */
+	need_tx_dma = ((file->f_mode & FMODE_WRITE) ||
+		       ((file->f_mode & FMODE_READ) && state->need_tx_for_rx));
+	if (state->wr_ref || (state->rd_ref && state->need_tx_for_rx))
+		need_tx_dma = 0;
+	if (need_tx_dma) {
+		DPRINTK("DMA REQUEST FOR playback\n");
+		DMA_REQUEST(err, os, audio_dma_callback);
+		if (err < 0)
+			goto out;
+	}
+	if (file->f_mode & FMODE_READ) {
+		DPRINTK("DMA REQUEST FOR record\n");
+		DMA_REQUEST(err, is, audio_dma_callback);
+		if (err < 0) {
+			if (need_tx_dma)
+				DMA_FREE(os);
+			goto out;
+		}
+	}
+
+	/* now complete initialisation */
+	if (!AUDIO_ACTIVE(state)) {
+		if (state->hw_init && !aic33_init_flag) {
+			state->hw_init(state->data);
+			aic33_init_flag = 0;
+		}
+	}
+
+	if ((file->f_mode & FMODE_WRITE)) {
+		DPRINTK("SETUP FOR PLAYBACK\n");
+		state->wr_ref = 1;
+		audio_reset(os);
+		os->fragsize = AUDIO_FRAGSIZE_DEFAULT;
+		os->nbfrags = AUDIO_NBFRAGS_DEFAULT;
+		os->mapped = 0;
+		init_waitqueue_head(&os->wq);
+	}
+
+	if (file->f_mode & FMODE_READ) {
+		DPRINTK("SETUP FOR RECORD\n");
+		state->rd_ref = 1;
+		audio_reset(is);
+		is->fragsize = AUDIO_FRAGSIZE_DEFAULT;
+		is->nbfrags = AUDIO_NBFRAGS_DEFAULT;
+		is->mapped = 0;
+		init_waitqueue_head(&is->wq);
+	}
+
+	file->private_data = state;
+	err = 0;
+
+      out:
+	up(&state->sem);
+	if (err) {
+		module_put(state->owner);
+		module_put(THIS_MODULE);
+	}
+	FN_OUT(err);
+	return err;
+}
+
+/*******************************************************************************
+ *
+ * audio_release(): Exposed as release function()
+ *
+ ******************************************************************************/
+static int audio_release(struct inode *inode, struct file *file)
+{
+	audio_state_t *state = file->private_data;
+	audio_stream_t *os = state->output_stream;
+	audio_stream_t *is = state->input_stream;
+
+	FN_IN;
+
+	down(&state->sem);
+
+	if (file->f_mode & FMODE_READ) {
+		audio_discard_buf(is);
+		DMA_FREE(is);
+		is->dma_spinref = 0;
+		if (state->need_tx_for_rx) {
+			os->spin_idle = 0;
+			if (!state->wr_ref) {
+				DMA_FREE(os);
+				os->dma_spinref = 0;
+			}
+		}
+		state->rd_ref = 0;
+	}
+
+	if (file->f_mode & FMODE_WRITE) {
+		audio_sync(file);
+		audio_discard_buf(os);
+		if (!state->need_tx_for_rx || !state->rd_ref) {
+			DMA_FREE(os);
+			os->dma_spinref = 0;
+		}
+		state->wr_ref = 0;
+	}
+
+	up(&state->sem);
+
+	module_put(state->owner);
+	module_put(THIS_MODULE);
+
+	FN_OUT(0);
+	return 0;
+}
+
+EXPORT_SYMBOL(audio_register_codec);
+EXPORT_SYMBOL(audio_unregister_codec);
+EXPORT_SYMBOL(audio_get_fops);
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_DESCRIPTION("Common audio handling for DAVINCI processors");
+MODULE_LICENSE("GPL");
diff --git a/sound/oss/davinci-audio.h b/sound/oss/davinci-audio.h
new file mode 100644
index 0000000..a37f635
--- /dev/null
+++ b/sound/oss/davinci-audio.h
@@ -0,0 +1,115 @@
+/*
+ * linux/sound/oss/davinci-audio.h
+ *
+ * Common audio handling for the Davinci processors
+ *
+ * Copyright (C) 2006 Texas Instruments, Inc.
+ *
+ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
+ *
+ * This package 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 PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * History:
+ *
+ * 2005-10-01   Rishi Bhattacharya - Adapted to TI Davinci Family of processors
+ */
+
+#ifndef __DAVINCI_AUDIO_H
+#define __DAVINCI_AUDIO_H
+
+/* Requires dma.h */
+#include <asm/arch/dma.h>
+
+/*
+ * Buffer Management
+ */
+typedef struct {
+	int offset;		/* current offset */
+	char *data;		/* points to actual buffer */
+	dma_addr_t dma_addr;	/* physical buffer address */
+	int dma_ref;		/* DMA refcount */
+	int master;		/* owner for buffer allocation, contain size when true */
+} audio_buf_t;
+
+/*
+ * Structure describing the data stream related information
+ */
+typedef struct {
+	char *id;		/* identification string */
+	audio_buf_t *buffers;	/* pointer to audio buffer structures */
+	u_int usr_head;		/* user fragment index */
+	u_int dma_head;		/* DMA fragment index to go */
+	u_int dma_tail;		/* DMA fragment index to complete */
+	u_int fragsize;		/* fragment i.e. buffer size */
+	u_int nbfrags;		/* nbr of fragments i.e. buffers */
+	u_int pending_frags;	/* Fragments sent to DMA */
+	int dma_dev;		/* device identifier for DMA */
+	u_int prevbuf;		/* Prev pending frag size sent to DMA */
+	char started;		/* to store if the chain was started or not */
+	int dma_q_head;		/* DMA Channel Q Head */
+	int dma_q_tail;		/* DMA Channel Q Tail */
+	char dma_q_count;	/* DMA Channel Q Count */
+	char in_use;		/*  Is this is use? */
+	int master_ch;
+	int *lch;		/*  Chain of channels this stream is linked to */
+	int input_or_output;	/* Direction of this data stream */
+	int bytecount;		/* nbr of processed bytes */
+	int fragcount;		/* nbr of fragment transitions */
+	struct completion wfc;	/* wait for "nbfrags" fragment completion */
+	wait_queue_head_t wq;	/* for poll */
+	int dma_spinref;	/* DMA is spinning */
+	int mapped:1;		/* mmap()'ed buffers */
+	int active:1;		/* actually in progress */
+	int stopped:1;		/* might be active but stopped */
+	int spin_idle:1;	/* have DMA spin on zeros when idle */
+	int dma_started;	/* to store if DMA was started or not */
+} audio_stream_t;
+
+/*
+ * State structure for one instance
+ */
+typedef struct {
+	struct module *owner;	/* Codec module ID */
+	audio_stream_t *output_stream;
+	audio_stream_t *input_stream;
+	int rd_ref:1;		/* open reference for recording */
+	int wr_ref:1;		/* open reference for playback */
+	int need_tx_for_rx:1;	/* if data must be sent while receiving */
+	void *data;
+	void (*hw_init) (void *);
+	void (*hw_shutdown) (void *);
+	int (*client_ioctl) (struct inode *, struct file *, uint, ulong);
+	int (*hw_probe) (void);
+	void (*hw_remove) (void);
+	void (*hw_cleanup) (void);
+	int (*hw_suspend) (void);
+	int (*hw_resume) (void);
+	struct pm_dev *pm_dev;
+	struct semaphore sem;	/* to protect against races in attach() */
+} audio_state_t;
+
+#ifdef AUDIO_PM
+void audio_ldm_suspend(void *data);
+
+void audio_ldm_resume(void *data);
+
+#endif
+
+/* Register a Codec using this function */
+extern int audio_register_codec(audio_state_t * codec_state);
+/* Un-Register a Codec using this function */
+extern int audio_unregister_codec(audio_state_t * codec_state);
+/* Function to provide fops of davinci audio driver */
+extern struct file_operations *audio_get_fops(void);
+/* Function to initialize the device info for audio driver */
+extern int audio_dev_init(void);
+/* Function to un-initialize the device info for audio driver */
+void audio_dev_uninit(void);
+
+#endif				/* End of #ifndef __DAVINCI_AUDIO_H */