add new mpu3050 driver support from manufacturing company
authorlw <lw@rock-chips.com>
Mon, 12 Dec 2011 11:15:50 +0000 (19:15 +0800)
committerlw <lw@rock-chips.com>
Mon, 12 Dec 2011 11:15:50 +0000 (19:15 +0800)
103 files changed:
arch/arm/configs/rk29_phonesdk_defconfig
arch/arm/mach-rk29/board-rk29-phonesdk.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/inv_mpu/Kconfig [new file with mode: 0644]
drivers/misc/inv_mpu/Makefile [new file with mode: 0644]
drivers/misc/inv_mpu/README [new file with mode: 0644]
drivers/misc/inv_mpu/accel/Kconfig [new file with mode: 0644]
drivers/misc/inv_mpu/accel/Makefile [new file with mode: 0644]
drivers/misc/inv_mpu/accel/adxl34x.c [new file with mode: 0644]
drivers/misc/inv_mpu/accel/bma150.c [new file with mode: 0644]
drivers/misc/inv_mpu/accel/bma222.c [new file with mode: 0644]
drivers/misc/inv_mpu/accel/bma250.c [new file with mode: 0644]
drivers/misc/inv_mpu/accel/cma3000.c [new file with mode: 0644]
drivers/misc/inv_mpu/accel/kxsd9.c [new file with mode: 0644]
drivers/misc/inv_mpu/accel/kxtf9.c [new file with mode: 0755]
drivers/misc/inv_mpu/accel/lis331.c [new file with mode: 0644]
drivers/misc/inv_mpu/accel/lis3dh.c [new file with mode: 0644]
drivers/misc/inv_mpu/accel/lsm303dlx_a.c [new file with mode: 0644]
drivers/misc/inv_mpu/accel/mma8450.c [new file with mode: 0644]
drivers/misc/inv_mpu/accel/mma845x.c [new file with mode: 0644]
drivers/misc/inv_mpu/accel/mpu6050.h [new file with mode: 0644]
drivers/misc/inv_mpu/compass/Kconfig [new file with mode: 0644]
drivers/misc/inv_mpu/compass/Makefile [new file with mode: 0644]
drivers/misc/inv_mpu/compass/ak8972.c [new file with mode: 0644]
drivers/misc/inv_mpu/compass/ak8975.c [new file with mode: 0755]
drivers/misc/inv_mpu/compass/ami306.c [new file with mode: 0644]
drivers/misc/inv_mpu/compass/ami30x.c [new file with mode: 0644]
drivers/misc/inv_mpu/compass/ami_hw.h [new file with mode: 0644]
drivers/misc/inv_mpu/compass/ami_sensor_def.h [new file with mode: 0644]
drivers/misc/inv_mpu/compass/hmc5883.c [new file with mode: 0644]
drivers/misc/inv_mpu/compass/hscdtd002b.c [new file with mode: 0644]
drivers/misc/inv_mpu/compass/hscdtd004a.c [new file with mode: 0644]
drivers/misc/inv_mpu/compass/lsm303dlx_m.c [new file with mode: 0644]
drivers/misc/inv_mpu/compass/mmc314x.c [new file with mode: 0644]
drivers/misc/inv_mpu/compass/yas529-kernel.c [new file with mode: 0644]
drivers/misc/inv_mpu/compass/yas530.c [new file with mode: 0644]
drivers/misc/inv_mpu/log.h [new file with mode: 0644]
drivers/misc/inv_mpu/mldl_cfg.c [new file with mode: 0755]
drivers/misc/inv_mpu/mldl_cfg.h [new file with mode: 0644]
drivers/misc/inv_mpu/mldl_print_cfg.c [new file with mode: 0644]
drivers/misc/inv_mpu/mldl_print_cfg.h [new file with mode: 0644]
drivers/misc/inv_mpu/mlsl-kernel.c [new file with mode: 0755]
drivers/misc/inv_mpu/mlsl.h [new file with mode: 0644]
drivers/misc/inv_mpu/mltypes.h [new file with mode: 0644]
drivers/misc/inv_mpu/mpu-dev.c [new file with mode: 0755]
drivers/misc/inv_mpu/mpu-dev.h [new file with mode: 0644]
drivers/misc/inv_mpu/mpu3050.h [new file with mode: 0644]
drivers/misc/inv_mpu/mpuirq.c [new file with mode: 0755]
drivers/misc/inv_mpu/mpuirq.h [new file with mode: 0644]
drivers/misc/inv_mpu/pressure/Kconfig [new file with mode: 0644]
drivers/misc/inv_mpu/pressure/Makefile [new file with mode: 0644]
drivers/misc/inv_mpu/pressure/bma085.c [new file with mode: 0644]
drivers/misc/inv_mpu/slaveirq.c [new file with mode: 0755]
drivers/misc/inv_mpu/slaveirq.h [new file with mode: 0644]
drivers/misc/inv_mpu/timerirq.c [new file with mode: 0755]
drivers/misc/inv_mpu/timerirq.h [new file with mode: 0644]
drivers/misc/mpu3050/Kconfig [deleted file]
drivers/misc/mpu3050/Makefile [deleted file]
drivers/misc/mpu3050/README [deleted file]
drivers/misc/mpu3050/accel/adxl346.c [deleted file]
drivers/misc/mpu3050/accel/bma150.c [deleted file]
drivers/misc/mpu3050/accel/bma222.c [deleted file]
drivers/misc/mpu3050/accel/cma3000.c [deleted file]
drivers/misc/mpu3050/accel/kxsd9.c [deleted file]
drivers/misc/mpu3050/accel/kxtf9.c [deleted file]
drivers/misc/mpu3050/accel/lis331.c [deleted file]
drivers/misc/mpu3050/accel/lis3dh.c [deleted file]
drivers/misc/mpu3050/accel/lsm303a.c [deleted file]
drivers/misc/mpu3050/accel/mantis.c [deleted file]
drivers/misc/mpu3050/accel/mma8450.c [deleted file]
drivers/misc/mpu3050/accel/mma8451.c [deleted file]
drivers/misc/mpu3050/accel/mma845x.c [deleted file]
drivers/misc/mpu3050/compass/ak8975.c [deleted file]
drivers/misc/mpu3050/compass/ami306.c [deleted file]
drivers/misc/mpu3050/compass/ami30x.c [deleted file]
drivers/misc/mpu3050/compass/hmc5883.c [deleted file]
drivers/misc/mpu3050/compass/hscdtd002b.c [deleted file]
drivers/misc/mpu3050/compass/hscdtd004a.c [deleted file]
drivers/misc/mpu3050/compass/hscdtd00xx.c [deleted file]
drivers/misc/mpu3050/compass/lsm303m.c [deleted file]
drivers/misc/mpu3050/compass/mmc314x.c [deleted file]
drivers/misc/mpu3050/compass/yas529-kernel.c [deleted file]
drivers/misc/mpu3050/compass/yas530-kernel.c [deleted file]
drivers/misc/mpu3050/compass/yas530.c [deleted file]
drivers/misc/mpu3050/log.h [deleted file]
drivers/misc/mpu3050/mldl_cfg.c [deleted file]
drivers/misc/mpu3050/mldl_cfg.h [deleted file]
drivers/misc/mpu3050/mlos-kernel.c [deleted file]
drivers/misc/mpu3050/mlos.h [deleted file]
drivers/misc/mpu3050/mlsl-kernel.c [deleted file]
drivers/misc/mpu3050/mlsl.h [deleted file]
drivers/misc/mpu3050/mltypes.h [deleted file]
drivers/misc/mpu3050/mpu-dev.c [deleted file]
drivers/misc/mpu3050/mpu-i2c.c [deleted file]
drivers/misc/mpu3050/mpu-i2c.h [deleted file]
drivers/misc/mpu3050/mpuirq.c [deleted file]
drivers/misc/mpu3050/mpuirq.h [deleted file]
drivers/misc/mpu3050/slaveirq.c [deleted file]
drivers/misc/mpu3050/slaveirq.h [deleted file]
drivers/misc/mpu3050/timerirq.c [deleted file]
drivers/misc/mpu3050/timerirq.h [deleted file]
include/linux/mpu.h

index 093edf254d381c4bbb4594367a321927dc624db8..61d129b9a4c6565e58c514869d0b0064e8020512 100755 (executable)
@@ -1,15 +1,15 @@
 #
 # Automatically generated make config: don't edit
-# Linux kernel version: 2.6.32.27
-# Mon Jun 27 20:36:24 2011
+# Linux/arm 3.0.8 Kernel Configuration
 #
 CONFIG_ARM=y
 CONFIG_SYS_SUPPORTS_APM_EMULATION=y
 CONFIG_HAVE_SCHED_CLOCK=y
 CONFIG_GENERIC_GPIO=y
-CONFIG_GENERIC_TIME=y
+# CONFIG_ARCH_USES_GETTIMEOFFSET is not set
 CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_GENERIC_HARDIRQS=y
+CONFIG_KTIME_SCALAR=y
+CONFIG_HAVE_PROC_CPU=y
 CONFIG_STACKTRACE_SUPPORT=y
 CONFIG_HAVE_LATENCYTOP_SUPPORT=y
 CONFIG_LOCKDEP_SUPPORT=y
@@ -18,43 +18,65 @@ CONFIG_HARDIRQS_SW_RESEND=y
 CONFIG_GENERIC_IRQ_PROBE=y
 CONFIG_RWSEM_GENERIC_SPINLOCK=y
 CONFIG_ARCH_HAS_CPUFREQ=y
+CONFIG_ARCH_HAS_CPU_IDLE_WAIT=y
 CONFIG_GENERIC_HWEIGHT=y
 CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_ZONE_DMA=y
+CONFIG_NEED_DMA_MAP_STATE=y
 CONFIG_VECTORS_BASE=0xffff0000
+# CONFIG_ARM_PATCH_PHYS_VIRT is not set
 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-CONFIG_CONSTRUCTORS=y
+CONFIG_HAVE_IRQ_WORK=y
 
 #
 # General setup
 #
 CONFIG_EXPERIMENTAL=y
 CONFIG_BROKEN_ON_SMP=y
-CONFIG_LOCK_KERNEL=y
 CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
 CONFIG_LOCALVERSION=""
 # CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_LZO=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_LZMA is not set
+CONFIG_KERNEL_LZO=y
+CONFIG_DEFAULT_HOSTNAME="(none)"
 # CONFIG_SWAP is not set
 # CONFIG_SYSVIPC is not set
 # CONFIG_POSIX_MQUEUE is not set
 # CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_FHANDLE is not set
 # CONFIG_TASKSTATS is not set
 # CONFIG_AUDIT is not set
+CONFIG_HAVE_GENERIC_HARDIRQS=y
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_HAVE_SPARSE_IRQ=y
+CONFIG_GENERIC_IRQ_SHOW=y
+# CONFIG_SPARSE_IRQ is not set
 
 #
 # RCU Subsystem
 #
-CONFIG_TREE_RCU=y
-# CONFIG_TREE_PREEMPT_RCU is not set
+CONFIG_TREE_PREEMPT_RCU=y
+# CONFIG_TINY_RCU is not set
+# CONFIG_TINY_PREEMPT_RCU is not set
+CONFIG_PREEMPT_RCU=y
 # CONFIG_RCU_TRACE is not set
 CONFIG_RCU_FANOUT=32
 # CONFIG_RCU_FANOUT_EXACT is not set
 # CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_RCU_BOOST is not set
 # CONFIG_IKCONFIG is not set
 CONFIG_LOG_BUF_SHIFT=19
 CONFIG_CGROUPS=y
 CONFIG_CGROUP_DEBUG=y
-# CONFIG_CGROUP_NS is not set
 CONFIG_CGROUP_FREEZER=y
 # CONFIG_CGROUP_DEVICE is not set
 # CONFIG_CPUSETS is not set
@@ -64,24 +86,27 @@ CONFIG_RESOURCE_COUNTERS=y
 CONFIG_CGROUP_SCHED=y
 CONFIG_FAIR_GROUP_SCHED=y
 CONFIG_RT_GROUP_SCHED=y
-# CONFIG_SYSFS_DEPRECATED_V2 is not set
-# CONFIG_RELAY is not set
+# CONFIG_BLK_CGROUP is not set
 # CONFIG_NAMESPACES is not set
+# CONFIG_SCHED_AUTOGROUP is not set
+# CONFIG_SYSFS_DEPRECATED is not set
+# CONFIG_RELAY is not set
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_INITRAMFS_SOURCE=""
 CONFIG_RD_GZIP=y
 # CONFIG_RD_BZIP2 is not set
 # CONFIG_RD_LZMA is not set
+# CONFIG_RD_XZ is not set
+# CONFIG_RD_LZO is not set
 CONFIG_CC_OPTIMIZE_FOR_SIZE=y
 CONFIG_SYSCTL=y
 CONFIG_ANON_INODES=y
 CONFIG_PANIC_TIMEOUT=5
-CONFIG_EMBEDDED=y
+CONFIG_EXPERT=y
 CONFIG_UID16=y
 # CONFIG_SYSCTL_SYSCALL is not set
 CONFIG_KALLSYMS=y
 # CONFIG_KALLSYMS_ALL is not set
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
 CONFIG_HOTPLUG=y
 CONFIG_PRINTK=y
 CONFIG_BUG=y
@@ -95,10 +120,15 @@ CONFIG_EVENTFD=y
 CONFIG_SHMEM=y
 CONFIG_ASHMEM=y
 CONFIG_AIO=y
+CONFIG_EMBEDDED=y
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
 
 #
 # Kernel Performance Events And Counters
 #
+# CONFIG_PERF_EVENTS is not set
+# CONFIG_PERF_COUNTERS is not set
 CONFIG_VM_EVENT_COUNTERS=y
 CONFIG_COMPAT_BRK=y
 CONFIG_SLAB=y
@@ -109,12 +139,13 @@ CONFIG_HAVE_OPROFILE=y
 # CONFIG_KPROBES is not set
 CONFIG_HAVE_KPROBES=y
 CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y
 CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
 
 #
 # GCOV-based kernel profiling
 #
-# CONFIG_SLOW_WORK is not set
 CONFIG_HAVE_GENERIC_DMA_COHERENT=y
 CONFIG_SLABINFO=y
 CONFIG_RT_MUTEXES=y
@@ -134,76 +165,116 @@ CONFIG_BLOCK=y
 # IO Schedulers
 #
 CONFIG_IOSCHED_NOOP=y
-# CONFIG_IOSCHED_AS is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
 CONFIG_DEFAULT_CFQ=y
 # CONFIG_DEFAULT_NOOP is not set
 CONFIG_DEFAULT_IOSCHED="cfq"
+# CONFIG_INLINE_SPIN_TRYLOCK is not set
+# CONFIG_INLINE_SPIN_TRYLOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK is not set
+# CONFIG_INLINE_SPIN_LOCK_BH is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_SPIN_UNLOCK is not set
+# CONFIG_INLINE_SPIN_UNLOCK_BH is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQ is not set
+# CONFIG_INLINE_SPIN_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_READ_TRYLOCK is not set
+# CONFIG_INLINE_READ_LOCK is not set
+# CONFIG_INLINE_READ_LOCK_BH is not set
+# CONFIG_INLINE_READ_LOCK_IRQ is not set
+# CONFIG_INLINE_READ_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_READ_UNLOCK is not set
+# CONFIG_INLINE_READ_UNLOCK_BH is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQ is not set
+# CONFIG_INLINE_READ_UNLOCK_IRQRESTORE is not set
+# CONFIG_INLINE_WRITE_TRYLOCK is not set
+# CONFIG_INLINE_WRITE_LOCK is not set
+# CONFIG_INLINE_WRITE_LOCK_BH is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_LOCK_IRQSAVE is not set
+# CONFIG_INLINE_WRITE_UNLOCK is not set
+# CONFIG_INLINE_WRITE_UNLOCK_BH is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQ is not set
+# CONFIG_INLINE_WRITE_UNLOCK_IRQRESTORE is not set
+# CONFIG_MUTEX_SPIN_ON_OWNER is not set
 CONFIG_FREEZER=y
 
 #
 # System Type
 #
 CONFIG_MMU=y
-# CONFIG_ARCH_AAEC2000 is not set
 # CONFIG_ARCH_INTEGRATOR is not set
 # CONFIG_ARCH_REALVIEW is not set
 # CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_VEXPRESS is not set
 # CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_BCMRING is not set
 # CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CNS3XXX is not set
 # CONFIG_ARCH_GEMINI is not set
 # CONFIG_ARCH_EBSA110 is not set
 # CONFIG_ARCH_EP93XX is not set
 # CONFIG_ARCH_FOOTBRIDGE is not set
 # CONFIG_ARCH_MXC is not set
-# CONFIG_ARCH_STMP3XXX is not set
+# CONFIG_ARCH_MXS is not set
 # CONFIG_ARCH_NETX is not set
 # CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_NOMADIK is not set
 # CONFIG_ARCH_IOP13XX is not set
 # CONFIG_ARCH_IOP32X is not set
 # CONFIG_ARCH_IOP33X is not set
 # CONFIG_ARCH_IXP23XX is not set
 # CONFIG_ARCH_IXP2000 is not set
 # CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_DOVE is not set
 # CONFIG_ARCH_KIRKWOOD is not set
 # CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_LPC32XX is not set
 # CONFIG_ARCH_MV78XX0 is not set
 # CONFIG_ARCH_ORION5X is not set
 # CONFIG_ARCH_MMP is not set
 # CONFIG_ARCH_KS8695 is not set
-# CONFIG_ARCH_NS9XXX is not set
 # CONFIG_ARCH_W90X900 is not set
+# CONFIG_ARCH_NUC93X is not set
+# CONFIG_ARCH_TEGRA is not set
 # CONFIG_ARCH_PNX4008 is not set
 # CONFIG_ARCH_PXA is not set
 # CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_SHMOBILE is not set
 # CONFIG_ARCH_RPC is not set
 # CONFIG_ARCH_SA1100 is not set
 # CONFIG_ARCH_S3C2410 is not set
 # CONFIG_ARCH_S3C64XX is not set
-# CONFIG_ARCH_S5PC1XX is not set
+# CONFIG_ARCH_S5P64X0 is not set
+# CONFIG_ARCH_S5PC100 is not set
+# CONFIG_ARCH_S5PV210 is not set
+# CONFIG_ARCH_EXYNOS4 is not set
 # CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_TCC_926 is not set
 # CONFIG_ARCH_U300 is not set
+# CONFIG_ARCH_U8500 is not set
+# CONFIG_ARCH_NOMADIK is not set
 # CONFIG_ARCH_DAVINCI is not set
 # CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_BCMRING is not set
-# CONFIG_ARCH_RK2818 is not set
 CONFIG_ARCH_RK29=y
-CONFIG_WIFI_CONTROL_FUNC=y
+# CONFIG_PLAT_SPEAR is not set
+# CONFIG_ARCH_VT8500 is not set
+# CONFIG_GPIO_PCA953X is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
 # CONFIG_MACH_RK29SDK is not set
 # CONFIG_MACH_RK29SDK_DDR3 is not set
 # CONFIG_MACH_RK29WINACCORD is not set
+# CONFIG_MACH_RK29_K97 is not set
 # CONFIG_MACH_RK29FIH is not set
 # CONFIG_MACH_RK29_MALATA is not set
 CONFIG_MACH_RK29_PHONESDK=y
 # CONFIG_MACH_RK29_A22 is not set
+# CONFIG_MACH_RK29_TD8801_V2 is not set
 # CONFIG_MACH_RK29_PHONEPADSDK is not set
 # CONFIG_MACH_RK29_newton is not set
+# CONFIG_MACH_RK29_PHONE_Z5 is not set
+# CONFIG_MACH_RK29_P91 is not set
 # CONFIG_DDR_TYPE_DDRII is not set
 CONFIG_DDR_TYPE_LPDDR=y
 # CONFIG_DDR_TYPE_DDR3_800D is not set
@@ -228,11 +299,11 @@ CONFIG_DDR_TYPE_LPDDR=y
 # CONFIG_DDR_TYPE_DDR3_2133M is not set
 # CONFIG_DDR_TYPE_DDR3_2133N is not set
 # CONFIG_DDR_TYPE_DDR3_DEFAULT is not set
-CONFIG_RK29_MEM_SIZE_512M=y
-# CONFIG_RK29_MEM_SIZE_1G is not set
 CONFIG_RK29_MEM_SIZE_M=512
 CONFIG_DDR_SDRAM_FREQ=192
 CONFIG_DDR_FREQ=y
+# CONFIG_DDR_RECONFIG is not set
+CONFIG_WIFI_CONTROL_FUNC=y
 
 #
 # RK29 VPU (Video Processing Unit) support
@@ -245,16 +316,21 @@ CONFIG_RK29_LAST_LOG=y
 #
 # support for RK29 power manage 
 #
+# CONFIG_RK29_WORKING_POWER_MANAGEMENT is not set
 CONFIG_RK29_CLK_SWITCH_TO_32K=y
 CONFIG_RK29_GPIO_SUSPEND=y
+# CONFIG_RK29_NEON_POWERDOMAIN_SET is not set
 CONFIG_RK29_SPI_INSRAM=y
 
+#
+# System MMU
+#
+
 #
 # Processor Type
 #
-CONFIG_CPU_32=y
-CONFIG_CPU_32v6K=y
 CONFIG_CPU_V7=y
+CONFIG_CPU_32v6K=y
 CONFIG_CPU_32v7=y
 CONFIG_CPU_ABRT_EV7=y
 CONFIG_CPU_PABRT_V7=y
@@ -271,17 +347,22 @@ CONFIG_CPU_CP15_MMU=y
 #
 CONFIG_ARM_THUMB=y
 CONFIG_ARM_THUMBEE=y
+# CONFIG_SWP_EMULATE is not set
 # CONFIG_CPU_ICACHE_DISABLE is not set
 # CONFIG_CPU_DCACHE_DISABLE is not set
 # CONFIG_CPU_BPREDICT_DISABLE is not set
-CONFIG_HAS_TLS_REG=y
+CONFIG_ARM_L1_CACHE_SHIFT_6=y
 CONFIG_ARM_L1_CACHE_SHIFT=6
+CONFIG_ARM_DMA_MEM_BUFFERABLE=y
+CONFIG_CPU_HAS_PMU=y
 # CONFIG_ARM_ERRATA_430973 is not set
 # CONFIG_ARM_ERRATA_458693 is not set
 # CONFIG_ARM_ERRATA_460075 is not set
+# CONFIG_ARM_ERRATA_743622 is not set
+# CONFIG_ARM_ERRATA_754322 is not set
 CONFIG_ARM_GIC=y
 CONFIG_PL330=y
-CONFIG_COMMON_CLKDEV=y
+# CONFIG_FIQ_DEBUGGER is not set
 
 #
 # Bus support
@@ -310,41 +391,55 @@ CONFIG_AEABI=y
 # CONFIG_OABI_COMPAT is not set
 # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
 # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
-# CONFIG_HIGHMEM is not set
+CONFIG_HAVE_ARCH_PFN_VALID=y
+CONFIG_HIGHMEM=y
+# CONFIG_HIGHPTE 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_HAVE_MEMBLOCK=y
 CONFIG_PAGEFLAGS_EXTENDED=y
 CONFIG_SPLIT_PTLOCK_CPUS=4
+# CONFIG_COMPACTION is not set
 # CONFIG_PHYS_ADDR_T_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=0
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
 CONFIG_VIRT_TO_BUS=y
-CONFIG_HAVE_MLOCK=y
-CONFIG_HAVE_MLOCKED_PAGE_BIT=y
 # CONFIG_KSM is not set
 CONFIG_DEFAULT_MMAP_MIN_ADDR=32768
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+CONFIG_FORCE_MAX_ZONEORDER=11
 CONFIG_ALIGNMENT_TRAP=y
 # CONFIG_UACCESS_WITH_MEMCPY is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_CC_STACKPROTECTOR is not set
+# CONFIG_DEPRECATED_PARAM_STRUCT is not set
+# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set
 
 #
 # Boot options
 #
+# CONFIG_USE_OF is not set
 CONFIG_ZBOOT_ROM_TEXT=0
 CONFIG_ZBOOT_ROM_BSS=0
 CONFIG_CMDLINE=""
 # CONFIG_XIP_KERNEL is not set
 CONFIG_KEXEC=y
 CONFIG_ATAGS_PROC=y
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_AUTO_ZRELADDR is not set
 
 #
 # CPU Power Management
 #
+
+#
+# CPU Frequency scaling
+#
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_TABLE=y
-# CONFIG_CPU_FREQ_DEBUG is not set
 CONFIG_CPU_FREQ_STAT=y
 CONFIG_CPU_FREQ_STAT_DETAILS=y
 # CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
@@ -352,10 +447,12 @@ CONFIG_CPU_FREQ_STAT_DETAILS=y
 # CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 # CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
+# CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE is not set
 CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_GOV_INTERACTIVE is not set
 CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
 # CONFIG_CPU_IDLE is not set
 
@@ -381,9 +478,6 @@ CONFIG_HAVE_AOUT=y
 #
 # Power management options
 #
-CONFIG_PM=y
-# CONFIG_PM_DEBUG is not set
-CONFIG_PM_SLEEP=y
 CONFIG_SUSPEND=y
 CONFIG_SUSPEND_FREEZER=y
 CONFIG_HAS_WAKELOCK=y
@@ -395,8 +489,12 @@ CONFIG_EARLYSUSPEND=y
 # CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set
 # CONFIG_CONSOLE_EARLYSUSPEND is not set
 CONFIG_FB_EARLYSUSPEND=y
-# CONFIG_APM_EMULATION is not set
+CONFIG_PM_SLEEP=y
 # CONFIG_PM_RUNTIME is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_APM_EMULATION is not set
+# CONFIG_SUSPEND_TIME is not set
 CONFIG_ARCH_SUSPEND_POSSIBLE=y
 CONFIG_NET=y
 
@@ -404,7 +502,6 @@ 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
@@ -415,13 +512,12 @@ CONFIG_XFRM=y
 CONFIG_INET=y
 # CONFIG_IP_MULTICAST is not set
 # CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
 CONFIG_IP_PNP=y
 CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 # CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
+# CONFIG_NET_IPGRE_DEMUX is not set
 # CONFIG_ARPD is not set
 # CONFIG_SYN_COOKIES is not set
 # CONFIG_INET_AH is not set
@@ -441,13 +537,16 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
 # CONFIG_TCP_MD5SIG is not set
 # CONFIG_IPV6 is not set
 CONFIG_ANDROID_PARANOID_NETWORK=y
+CONFIG_NET_ACTIVITY_STATS=y
 # CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
 # CONFIG_NETFILTER is not set
 # CONFIG_IP_DCCP is not set
 # CONFIG_IP_SCTP is not set
 # CONFIG_RDS is not set
 # CONFIG_TIPC is not set
 # CONFIG_ATM is not set
+# CONFIG_L2TP is not set
 # CONFIG_BRIDGE is not set
 # CONFIG_NET_DSA is not set
 # CONFIG_VLAN_8021Q is not set
@@ -463,6 +562,7 @@ CONFIG_ANDROID_PARANOID_NETWORK=y
 # CONFIG_IEEE802154 is not set
 # CONFIG_NET_SCHED is not set
 # CONFIG_DCB is not set
+# CONFIG_BATMAN_ADV is not set
 
 #
 # Network testing
@@ -477,33 +577,50 @@ CONFIG_BT_SCO=y
 CONFIG_BT_RFCOMM=y
 CONFIG_BT_RFCOMM_TTY=y
 CONFIG_BT_BNEP=y
+# CONFIG_BT_BNEP_MC_FILTER is not set
+# CONFIG_BT_BNEP_PROTO_FILTER is not set
 CONFIG_BT_HIDP=y
+
+#
+# Bluetooth device drivers
+#
+# CONFIG_BT_HCIBTUSB is not set
+# CONFIG_BT_HCIBTSDIO is not set
 CONFIG_BT_HCIUART=y
 CONFIG_BT_HCIUART_H4=y
+# CONFIG_BT_HCIUART_BCSP is not set
+# CONFIG_BT_HCIUART_ATH3K is not set
+# CONFIG_BT_HCIUART_LL is not set
+# CONFIG_BT_HCIBCM203X is not set
+# CONFIG_BT_HCIBPA10X is not set
+# CONFIG_BT_HCIBFUSB is not set
+# CONFIG_BT_HCIVHCI is not set
+# CONFIG_BT_MRVL is not set
 CONFIG_BT_HCIBCM4325=y
 CONFIG_IDBLOCK=y
 # CONFIG_WIFI_MAC is not set
 # CONFIG_AF_RXRPC is not set
 CONFIG_WIRELESS=y
-# CONFIG_CFG80211 is not set
-CONFIG_CFG80211_DEFAULT_PS_VALUE=0
-# CONFIG_WIRELESS_OLD_REGULATORY is not set
 CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_PRIV=y
+# CONFIG_CFG80211 is not set
 CONFIG_WIRELESS_EXT_SYSFS=y
 # CONFIG_LIB80211 is not set
 
 #
 # CFG80211 needs to be enabled for MAC80211
 #
-
-#
-# Some wireless drivers require a rate control algorithm
-#
 # CONFIG_WIMAX is not set
 CONFIG_RFKILL=y
 # CONFIG_RFKILL_PM is not set
 # CONFIG_RFKILL_INPUT is not set
+# CONFIG_RFKILL_REGULATOR is not set
+# CONFIG_RFKILL_GPIO is not set
 # CONFIG_NET_9P is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
 
 #
 # Device Drivers
@@ -527,8 +644,6 @@ CONFIG_EXTRA_FIRMWARE=""
 CONFIG_MTD=y
 # CONFIG_MTD_DEBUG is not set
 # CONFIG_MTD_TESTS 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
@@ -545,6 +660,7 @@ CONFIG_MTD_BLOCK=y
 # CONFIG_INFTL is not set
 # CONFIG_RFD_FTL is not set
 # CONFIG_SSFDC is not set
+# CONFIG_SM_FTL is not set
 # CONFIG_MTD_OOPS is not set
 
 #
@@ -594,6 +710,7 @@ CONFIG_MTD_NAND_IDS=y
 CONFIG_MTD_RKNAND=y
 CONFIG_MTD_NAND_RK29XX=y
 CONFIG_MTD_RKNAND_BUFFER=y
+# CONFIG_MTD_EMMC_CLK_POWER_SAVE is not set
 # CONFIG_MTD_NAND_RK29XX_DEBUG is not set
 # CONFIG_MTD_ONENAND is not set
 
@@ -601,29 +718,43 @@ CONFIG_MTD_RKNAND_BUFFER=y
 # LPDDR flash memory drivers
 #
 # CONFIG_MTD_LPDDR is not set
-
-#
-# UBI - Unsorted block images
-#
 # CONFIG_MTD_UBI is not set
 # CONFIG_PARPORT is not set
 CONFIG_BLK_DEV=y
 # CONFIG_BLK_DEV_COW_COMMON is not set
 CONFIG_BLK_DEV_LOOP=y
 # CONFIG_BLK_DEV_CRYPTOLOOP is not set
+
+#
+# DRBD disabled because PROC_FS, INET or CONNECTOR not selected
+#
 # CONFIG_BLK_DEV_NBD is not set
 # CONFIG_BLK_DEV_UB is not set
 # CONFIG_BLK_DEV_RAM is not set
 # CONFIG_CDROM_PKTCDVD is not set
 # CONFIG_ATA_OVER_ETH is not set
 # CONFIG_MG_DISK is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_SENSORS_LIS3LV02D is not set
 CONFIG_MISC_DEVICES=y
+# CONFIG_AD525X_DPOT is not set
 CONFIG_ANDROID_PMEM=y
+# CONFIG_INTEL_MID_PTI is not set
 # CONFIG_ICS932S401 is not set
 # CONFIG_ENCLOSURE_SERVICES is not set
-# CONFIG_KERNEL_DEBUGGER_CORE is not set
+# CONFIG_APDS9802ALS is not set
 # CONFIG_ISL29003 is not set
+# CONFIG_ISL29020 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_SENSORS_BH1780 is not set
+# CONFIG_SENSORS_BH1770 is not set
+# CONFIG_SENSORS_APDS990X is not set
+# CONFIG_HMC6352 is not set
+# CONFIG_SENSORS_AK8975 is not set
+# CONFIG_DS1682 is not set
+# CONFIG_TI_DAC7512 is not set
 # CONFIG_UID_STAT is not set
+# CONFIG_BMP085 is not set
 # CONFIG_WL127X_RFKILL is not set
 CONFIG_APANIC=y
 CONFIG_APANIC_PLABEL="kpanic"
@@ -631,6 +762,10 @@ CONFIG_APANIC_PLABEL="kpanic"
 CONFIG_MTK23D=y
 # CONFIG_FM580X is not set
 # CONFIG_MU509 is not set
+# CONFIG_MW100 is not set
+# CONFIG_RK29_NEWTON is not set
+# CONFIG_RK29_SC8800 is not set
+# CONFIG_TDSC8800 is not set
 # CONFIG_C2PORT is not set
 
 #
@@ -644,44 +779,53 @@ CONFIG_MTK23D=y
 # CONFIG_RK29_SUPPORT_MODEM is not set
 CONFIG_RK29_GPS=y
 CONFIG_GPS_GNS7560=y
-
-#
-# Motion Sensors Support
-#
-# CONFIG_MPU_NONE is not set
+CONFIG_MPU_SENSORS_TIMERIRQ=y
+CONFIG_INV_SENSORS=y
 CONFIG_MPU_SENSORS_MPU3050=y
-# CONFIG_MPU_SENSORS_MPU6000 is not set
-# CONFIG_MPU_SENSORS_ACCELEROMETER_NONE is not set
-# CONFIG_MPU_SENSORS_ADXL346 is not set
-# CONFIG_MPU_SENSORS_BMA150 is not set
+# CONFIG_MPU_SENSORS_MPU6050A2 is not set
+# CONFIG_MPU_SENSORS_MPU6050B1 is not set
+CONFIG_MPU_SENSORS_MPU3050_GYRO=y
+CONFIG_INV_SENSORS_ACCELEROMETERS=y
+# CONFIG_MPU_SENSORS_ADXL34X is not set
 # CONFIG_MPU_SENSORS_BMA222 is not set
+# CONFIG_MPU_SENSORS_BMA150 is not set
+# CONFIG_MPU_SENSORS_BMA250 is not set
 # CONFIG_MPU_SENSORS_KXSD9 is not set
 CONFIG_MPU_SENSORS_KXTF9=y
 # CONFIG_MPU_SENSORS_LIS331DLH is not set
 # CONFIG_MPU_SENSORS_LIS3DH is not set
-# CONFIG_MPU_SENSORS_LSM303DLHA is not set
+# CONFIG_MPU_SENSORS_LSM303DLX_A is not set
 # CONFIG_MPU_SENSORS_MMA8450 is not set
 # CONFIG_MPU_SENSORS_MMA845X is not set
-# CONFIG_MPU_SENSORS_COMPASS_NONE is not set
+CONFIG_INV_SENSORS_COMPASS=y
 CONFIG_MPU_SENSORS_AK8975=y
+# CONFIG_MPU_SENSORS_AK8972 is not set
 # CONFIG_MPU_SENSORS_MMC314X is not set
 # CONFIG_MPU_SENSORS_AMI30X is not set
 # CONFIG_MPU_SENSORS_AMI306 is not set
 # CONFIG_MPU_SENSORS_HMC5883 is not set
-# CONFIG_MPU_SENSORS_LSM303DLHM is not set
-# CONFIG_MPU_SENSORS_YAS529 is not set
+# CONFIG_MPU_SENSORS_LSM303DLX_M is not set
+# CONFIG_MPU_SENSORS_MMC314XMS is not set
 # CONFIG_MPU_SENSORS_YAS530 is not set
 # CONFIG_MPU_SENSORS_HSCDTD002B is not set
 # CONFIG_MPU_SENSORS_HSCDTD004A is not set
-CONFIG_MPU_SENSORS_PRESSURE_NONE=y
-# CONFIG_MPU_SENSORS_BMA085 is not set
-CONFIG_MPU_SENSORS_TIMERIRQ=y
+# CONFIG_INV_SENSORS_PRESSURE is not set
+# CONFIG_MPU_USERSPACE_DEBUG is not set
+# CONFIG_IWMC3200TOP is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+# CONFIG_SENSORS_LIS3_SPI is not set
+# CONFIG_SENSORS_LIS3_I2C is not set
 CONFIG_HAVE_IDE=y
 # CONFIG_IDE is not set
 
 #
 # SCSI device support
 #
+CONFIG_SCSI_MOD=y
 # CONFIG_RAID_ATTRS is not set
 CONFIG_SCSI=y
 CONFIG_SCSI_DMA=y
@@ -710,10 +854,12 @@ CONFIG_SCSI_WAIT_SCAN=m
 # CONFIG_SCSI_SPI_ATTRS is not set
 # CONFIG_SCSI_FC_ATTRS is not set
 # CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_ATTRS is not set
 # CONFIG_SCSI_SAS_LIBSAS is not set
 # CONFIG_SCSI_SRP_ATTRS is not set
 CONFIG_SCSI_LOWLEVEL=y
 # CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
 # CONFIG_LIBFC is not set
 # CONFIG_LIBFCOE is not set
 # CONFIG_SCSI_DEBUG is not set
@@ -727,10 +873,13 @@ CONFIG_BLK_DEV_DM=y
 CONFIG_DM_CRYPT=y
 # CONFIG_DM_SNAPSHOT is not set
 # CONFIG_DM_MIRROR is not set
+# CONFIG_DM_RAID is not set
 # CONFIG_DM_ZERO is not set
 # CONFIG_DM_MULTIPATH is not set
 # CONFIG_DM_DELAY is not set
 CONFIG_DM_UEVENT=y
+# CONFIG_DM_FLAKEY is not set
+# CONFIG_TARGET_CORE is not set
 CONFIG_NETDEVICES=y
 # CONFIG_DUMMY is not set
 # CONFIG_BONDING is not set
@@ -738,6 +887,7 @@ CONFIG_NETDEVICES=y
 # CONFIG_EQUALIZER is not set
 # CONFIG_TUN is not set
 # CONFIG_VETH is not set
+CONFIG_MII=y
 CONFIG_PHYLIB=y
 
 #
@@ -756,10 +906,10 @@ CONFIG_PHYLIB=y
 # CONFIG_NATIONAL_PHY is not set
 # CONFIG_STE10XP is not set
 # CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_MICREL_PHY is not set
 # CONFIG_FIXED_PHY is not set
 # CONFIG_MDIO_BITBANG is not set
 CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
 # CONFIG_AX88796 is not set
 # CONFIG_RK29_VMAC is not set
 # CONFIG_SMC91X is not set
@@ -777,17 +927,19 @@ CONFIG_MII=y
 # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
 # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
 # CONFIG_B44 is not set
-# CONFIG_KS8842 is not set
 # CONFIG_KS8851 is not set
 # CONFIG_KS8851_MLL is not set
+# CONFIG_FTMAC100 is not set
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
 CONFIG_WLAN=y
 CONFIG_WLAN_80211=y
 # CONFIG_WIFI_NONE is not set
 CONFIG_BCM4329=y
-# CONFIG_MV8686 is not set
 # CONFIG_BCM4319 is not set
+# CONFIG_MV8686 is not set
+# CONFIG_RTL8192CU is not set
+# CONFIG_AR6003 is not set
 
 #
 # Enable WiMAX (Networking options) to see the WiMAX drivers
@@ -802,7 +954,12 @@ CONFIG_BCM4329=y
 # CONFIG_USB_RTL8150 is not set
 # CONFIG_USB_USBNET is not set
 # CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
 # CONFIG_WAN is not set
+
+#
+# CAIF transport drivers
+#
 CONFIG_PPP=y
 CONFIG_PPP_MULTILINK=y
 CONFIG_PPP_FILTER=y
@@ -812,7 +969,6 @@ CONFIG_PPP_DEFLATE=y
 CONFIG_PPP_BSDCOMP=y
 # CONFIG_PPP_MPPE is not set
 # CONFIG_PPPOE is not set
-# CONFIG_PPPOL2TP is not set
 # CONFIG_PPPOLAC is not set
 # CONFIG_PPPOPNS is not set
 # CONFIG_SLIP is not set
@@ -829,6 +985,7 @@ CONFIG_SLHC=y
 CONFIG_INPUT=y
 # CONFIG_INPUT_FF_MEMLESS is not set
 CONFIG_INPUT_POLLDEV=y
+# CONFIG_INPUT_SPARSEKMAP is not set
 
 #
 # Userland interfaces
@@ -844,15 +1001,21 @@ CONFIG_INPUT_KEYRESET=y
 #
 CONFIG_INPUT_KEYBOARD=y
 CONFIG_KEYS_RK29=y
+# CONFIG_KEYS_RK29_NEWTON is not set
 # CONFIG_SYNAPTICS_SO340010 is not set
 # CONFIG_KEYBOARD_ADP5588 is not set
+# CONFIG_KEYBOARD_ADP5589 is not set
 # CONFIG_KEYBOARD_ATKBD is not set
-# CONFIG_QT2160 is not set
+# CONFIG_KEYBOARD_QT1070 is not set
+# CONFIG_KEYBOARD_QT2160 is not set
 # CONFIG_KEYBOARD_LKKBD is not set
 # CONFIG_KEYBOARD_GPIO is not set
 # CONFIG_KEYBOARD_WM831X_GPIO is not set
+# CONFIG_KEYBOARD_TCA6416 is not set
 # CONFIG_KEYBOARD_MATRIX is not set
 # CONFIG_KEYBOARD_MAX7359 is not set
+# CONFIG_KEYBOARD_MCS is not set
+# CONFIG_KEYBOARD_MPR121 is not set
 # CONFIG_KEYBOARD_NEWTON is not set
 # CONFIG_KEYBOARD_OPENCORES is not set
 # CONFIG_KEYBOARD_STOWAWAY is not set
@@ -866,15 +1029,20 @@ CONFIG_INPUT_TOUCHSCREEN=y
 # CONFIG_TOUCHSCREEN_ADS7846 is not set
 # CONFIG_TOUCHSCREEN_AD7877 is not set
 # CONFIG_TOUCHSCREEN_ILI2102_IIC is not set
+# CONFIG_TOUCHSCREEN_GT8XX is not set
 # CONFIG_TOUCHSCREEN_IT7250 is not set
-# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
-# CONFIG_TOUCHSCREEN_AD7879_SPI is not set
 # CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_ATMEL_MXT is not set
+# CONFIG_TOUCHSCREEN_BU21013 is not set
+# CONFIG_TOUCHSCREEN_CY8CTMG110 is not set
+# CONFIG_TOUCHSCREEN_DYNAPRO is not set
+# CONFIG_TOUCHSCREEN_HAMPSHIRE is not set
 # CONFIG_TOUCHSCREEN_EETI is not set
 # CONFIG_TOUCHSCREEN_FUJITSU is not set
 # CONFIG_TOUCHSCREEN_GUNZE is not set
 # CONFIG_TOUCHSCREEN_ELO is not set
 # CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MAX11801 is not set
 # CONFIG_TOUCHSCREEN_MCS5000 is not set
 # CONFIG_TOUCHSCREEN_MTOUCH is not set
 # CONFIG_TOUCHSCREEN_INEXIO is not set
@@ -883,22 +1051,35 @@ CONFIG_INPUT_TOUCHSCREEN=y
 # CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI is not set
 # CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
 # CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_WM831X is not set
 # CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
 # CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2005 is not set
 # CONFIG_TOUCHSCREEN_TSC2007 is not set
 # CONFIG_TOUCHSCREEN_W90X900 is not set
+# CONFIG_TOUCHSCREEN_ST1232 is not set
+# CONFIG_TOUCHSCREEN_TPS6507X is not set
 # CONFIG_HANNSTAR_P1003 is not set
 # CONFIG_ATMEL_MXT224 is not set
 # CONFIG_SINTEK_3FA16 is not set
 # CONFIG_EETI_EGALAX is not set
 # CONFIG_TOUCHSCREEN_IT7260 is not set
+# CONFIG_TOUCHSCREEN_IT7260_I2C is not set
+# CONFIG_TOUCHSCREEN_NAS is not set
+# CONFIG_LAIBAO_TS is not set
 # CONFIG_TOUCHSCREEN_GT801_IIC is not set
 CONFIG_TOUCHSCREEN_GT818_IIC=y
+# CONFIG_TOUCHSCREEN_PIXCIR is not set
 # CONFIG_D70_L3188A is not set
+# CONFIG_TOUCHSCREEN_GT819 is not set
+# CONFIG_TOUCHSCREEN_FT5306 is not set
 # CONFIG_TOUCHSCREEN_FT5406 is not set
+# CONFIG_ATMEL_MXT1386 is not set
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_LPSENSOR_ISL29028=y
 # CONFIG_INPUT_LPSENSOR_CM3602 is not set
+# CONFIG_INPUT_LPSENSOR_AL3006 is not set
+# CONFIG_INPUT_AD714X is not set
 # CONFIG_INPUT_ATI_REMOTE is not set
 # CONFIG_INPUT_ATI_REMOTE2 is not set
 # CONFIG_INPUT_KEYCHORD is not set
@@ -908,13 +1089,20 @@ CONFIG_INPUT_LPSENSOR_ISL29028=y
 # CONFIG_INPUT_CM109 is not set
 CONFIG_INPUT_UINPUT=y
 # CONFIG_INPUT_GPIO is not set
+# CONFIG_INPUT_PCF8574 is not set
 # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
 CONFIG_INPUT_WM831X_ON=y
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_CMA3000 is not set
 # CONFIG_MAG_SENSORS is not set
 CONFIG_G_SENSOR_DEVICE=y
 # CONFIG_GS_MMA7660 is not set
 # CONFIG_GS_MMA8452 is not set
+# CONFIG_GS_KXTF9 is not set
+# CONFIG_GS_LIS3DH is not set
 # CONFIG_GS_L3G4200D is not set
+# CONFIG_GS_BMA023 is not set
+# CONFIG_GYRO_SENSOR_DEVICE is not set
 # CONFIG_INPUT_JOGBALL is not set
 # CONFIG_LIGHT_SENSOR_DEVICE is not set
 
@@ -932,9 +1120,14 @@ CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 CONFIG_HW_CONSOLE=y
 # CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
 CONFIG_DEVMEM=y
 CONFIG_DEVKMEM=y
-# CONFIG_SERIAL_NONSTANDARD is not set
 
 #
 # Serial drivers
@@ -945,36 +1138,70 @@ CONFIG_DEVKMEM=y
 # Non-8250 serial port support
 #
 # CONFIG_SERIAL_MAX3100 is not set
+# CONFIG_SERIAL_MAX3107 is not set
 CONFIG_SERIAL_CORE=y
 CONFIG_SERIAL_CORE_CONSOLE=y
+# CONFIG_SERIAL_TIMBERDALE is not set
 CONFIG_SERIAL_RK29=y
 CONFIG_UART0_RK29=y
 CONFIG_UART0_CTS_RTS_RK29=y
+# CONFIG_UART0_DMA_RK29 is not set
 CONFIG_UART1_RK29=y
 CONFIG_UART2_RK29=y
 CONFIG_UART2_CTS_RTS_RK29=y
+# CONFIG_UART2_DMA_RK29 is not set
 CONFIG_UART3_RK29=y
 # CONFIG_UART3_CTS_RTS_RK29 is not set
+# CONFIG_UART3_DMA_RK29 is not set
 CONFIG_SERIAL_RK29_CONSOLE=y
 # CONFIG_SERIAL_SC8800 is not set
-CONFIG_UNIX98_PTYS=y
-# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
-# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_IFX6X60 is not set
+# CONFIG_SERIAL_XILINX_PS_UART is not set
+# CONFIG_TTY_PRINTK is not set
+# CONFIG_HVC_DCC is not set
 # CONFIG_IPMI_HANDLER is not set
 # CONFIG_HW_RANDOM is not set
 # CONFIG_R3964 is not set
 # CONFIG_RAW_DRIVER is not set
 # CONFIG_TCG_TPM is not set
 # CONFIG_DCC_TTY is not set
+# CONFIG_RAMOOPS is not set
 CONFIG_I2C=y
 CONFIG_I2C_BOARDINFO=y
 CONFIG_I2C_COMPAT=y
 # CONFIG_I2C_CHARDEV is not set
+# CONFIG_I2C_MUX is not set
 CONFIG_I2C_HELPER_AUTO=y
 
 #
 # I2C Hardware Bus support
 #
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_DESIGNWARE is not set
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_PXA_PCI is not set
+# CONFIG_I2C_SIMTEC is not set
+# CONFIG_I2C_XILINX is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_DIOLAN_U2C is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_STUB is not set
 CONFIG_I2C_RK29=y
 
 #
@@ -993,17 +1220,9 @@ CONFIG_I2C3_RK29=y
 CONFIG_RK29_I2C3_CONTROLLER=y
 # CONFIG_RK29_I2C3_GPIO is not set
 # CONFIG_I2C_DEV_RK29 is not set
-
-#
-# Miscellaneous I2C Chip support
-#
-# CONFIG_DS1682 is not set
-# CONFIG_SENSORS_TSL2550 is not set
-# CONFIG_SENSORS_PCA963X is not set
 # 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
 CONFIG_SPI=y
 # CONFIG_SPI_DEBUG is not set
 CONFIG_SPI_MASTER=y
@@ -1011,12 +1230,19 @@ CONFIG_SPI_MASTER=y
 #
 # SPI Master Controller Drivers
 #
+# CONFIG_SPI_ALTERA is not set
 # CONFIG_SPI_BITBANG is not set
 # CONFIG_SPI_GPIO is not set
+# CONFIG_SPI_OC_TINY is not set
+# CONFIG_SPI_PXA2XX_PCI is not set
+# CONFIG_SPI_XILINX is not set
 CONFIG_SPIM_RK29=y
 CONFIG_SPIM0_RK29=y
 CONFIG_SPIM1_RK29=y
 CONFIG_LCD_USE_SPIM_CONTROL=y
+# CONFIG_LCD_USE_SPI0 is not set
+CONFIG_LCD_USE_SPI1=y
+# CONFIG_SPI_DESIGNWARE is not set
 
 #
 # SPI Protocol Masters
@@ -1026,7 +1252,6 @@ CONFIG_LCD_USE_SPIM_CONTROL=y
 CONFIG_ADC=y
 # CONFIG_ADC_RK28 is not set
 CONFIG_ADC_RK29=y
-# CONFIG_SPI_FPGA is not set
 
 #
 # Headset device support
@@ -1037,23 +1262,39 @@ CONFIG_RK_HEADSET_DET=y
 # PPS support
 #
 # CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+
+#
+# Enable Device Drivers -> PPS to see the PTP clock options.
+#
 CONFIG_ARCH_REQUIRE_GPIOLIB=y
 CONFIG_GPIOLIB=y
 # CONFIG_DEBUG_GPIO is not set
 # CONFIG_GPIO_SYSFS is not set
 
 #
-# Memory mapped GPIO expanders:
+# Memory mapped GPIO drivers:
 #
+# CONFIG_GPIO_BASIC_MMIO is not set
+# CONFIG_GPIO_IT8761E is not set
 
 #
 # I2C GPIO expanders:
 #
+# CONFIG_GPIO_MAX7300 is not set
 # CONFIG_GPIO_MAX732X is not set
-# CONFIG_GPIO_PCA953X is not set
 # CONFIG_GPIO_PCF857X is not set
+# CONFIG_GPIO_SX150X is not set
 CONFIG_GPIO_WM831X=y
 CONFIG_GPIO_WM8994=y
+# CONFIG_GPIO_ADP5588 is not set
 
 #
 # PCI GPIO expanders:
@@ -1065,6 +1306,7 @@ CONFIG_GPIO_WM8994=y
 # CONFIG_GPIO_MAX7301 is not set
 # CONFIG_GPIO_MCP23S08 is not set
 # CONFIG_GPIO_MC33880 is not set
+# CONFIG_GPIO_74X164 is not set
 
 #
 # AC97 GPIO expanders:
@@ -1076,6 +1318,10 @@ CONFIG_EXPANDED_GPIO_IRQ_NUM=0
 # CONFIG_EXPAND_GPIO_SOFT_INTERRUPT is not set
 CONFIG_SPI_FPGA_GPIO_NUM=96
 CONFIG_SPI_FPGA_GPIO_IRQ_NUM=16
+
+#
+# MODULbus GPIO expanders:
+#
 # CONFIG_W1 is not set
 CONFIG_POWER_SUPPLY=y
 # CONFIG_POWER_SUPPLY_DEBUG is not set
@@ -1083,13 +1329,20 @@ CONFIG_POWER_SUPPLY=y
 CONFIG_WM831X_BACKUP=y
 CONFIG_WM831X_POWER=y
 CONFIG_WM831X_CHARGER_DISPLAY=y
-# CONFIG_BATTERY_DS2760 is not set
+# CONFIG_WM831X_WITH_BATTERY is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
 # CONFIG_BATTERY_DS2782 is not set
+# CONFIG_BATTERY_BQ20Z75 is not set
 # CONFIG_BATTERY_BQ27x00 is not set
 # CONFIG_BATTERY_MAX17040 is not set
+# CONFIG_BATTERY_MAX17042 is not set
 # CONFIG_BATTERY_STC3100 is not set
 # CONFIG_BATTERY_BQ27510 is not set
+# CONFIG_BATTERY_BQ27541 is not set
 # CONFIG_BATTERY_BQ3060 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_GPIO is not set
 # CONFIG_HWMON is not set
 # CONFIG_THERMAL is not set
 # CONFIG_WATCHDOG is not set
@@ -1099,23 +1352,36 @@ CONFIG_SSB_POSSIBLE=y
 # Sonics Silicon Backplane
 #
 # CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
 
 #
-# Multifunction device drivers
+# Broadcom specific AMBA
 #
+# CONFIG_BCMA is not set
+CONFIG_MFD_SUPPORT=y
 CONFIG_MFD_CORE=y
+# CONFIG_MFD_88PM860X is not set
 # CONFIG_MFD_SM501 is not set
 # CONFIG_MFD_ASIC3 is not set
 # CONFIG_HTC_EGPIO is not set
 # CONFIG_HTC_PASIC3 is not set
+# CONFIG_HTC_I2CPLD is not set
+# CONFIG_TPS6105X is not set
 # CONFIG_TPS65010 is not set
+# CONFIG_TPS6507X is not set
+# CONFIG_MFD_TPS6586X is not set
 # CONFIG_TWL4030_CORE is not set
-# CONFIG_TPS65910_CORE is not set
+# CONFIG_MFD_STMPE is not set
+# CONFIG_MFD_TC3589X is not set
 # CONFIG_MFD_TMIO is not set
 # CONFIG_MFD_T7L66XB is not set
 # CONFIG_MFD_TC6387XB is not set
 # CONFIG_MFD_TC6393XB is not set
 # CONFIG_PMIC_DA903X is not set
+# CONFIG_PMIC_ADP5520 is not set
+# CONFIG_MFD_MAX8925 is not set
+# CONFIG_MFD_MAX8997 is not set
+# CONFIG_MFD_MAX8998 is not set
 # CONFIG_MFD_WM8400 is not set
 CONFIG_MFD_WM831X=y
 # CONFIG_MFD_WM831X_I2C is not set
@@ -1124,44 +1390,71 @@ CONFIG_MFD_WM831X_SPI=y
 # CONFIG_MFD_WM8350_I2C is not set
 CONFIG_MFD_WM8994=y
 # CONFIG_MFD_PCF50633 is not set
-# CONFIG_MFD_MC13783 is not set
-# CONFIG_AB3100_CORE is not set
+# CONFIG_MFD_MC13XXX is not set
+# CONFIG_ABX500_CORE is not set
 # CONFIG_EZX_PCAP is not set
+# CONFIG_MFD_WL1273_CORE is not set
+# CONFIG_MFD_TPS65910 is not set
 CONFIG_REGULATOR=y
 # CONFIG_REGULATOR_DEBUG is not set
+# CONFIG_REGULATOR_DUMMY is not set
 # CONFIG_REGULATOR_FIXED_VOLTAGE is not set
 # CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
 # CONFIG_REGULATOR_USERSPACE_CONSUMER is not set
 # CONFIG_REGULATOR_BQ24022 is not set
 # CONFIG_REGULATOR_MAX1586 is not set
+# CONFIG_REGULATOR_MAX8649 is not set
+# CONFIG_REGULATOR_MAX8660 is not set
+# CONFIG_REGULATOR_MAX8952 is not set
 CONFIG_REGULATOR_WM831X=y
 CONFIG_REGULATOR_WM8994=y
 # CONFIG_REGULATOR_LP3971 is not set
+# CONFIG_REGULATOR_LP3972 is not set
 # CONFIG_REGULATOR_TPS65023 is not set
 # CONFIG_REGULATOR_TPS6507X is not set
 # CONFIG_RK2818_REGULATOR_CHARGE is not set
 # CONFIG_RK2818_REGULATOR_LP8725 is not set
+# CONFIG_REGULATOR_ACT8891 is not set
 # CONFIG_RK29_PWM_REGULATOR is not set
+# CONFIG_REGULATOR_ISL6271A is not set
+# CONFIG_REGULATOR_AD5398 is not set
+# CONFIG_REGULATOR_TPS6524X is not set
 CONFIG_MEDIA_SUPPORT=y
 
 #
 # Multimedia core support
 #
+# CONFIG_MEDIA_CONTROLLER is not set
 CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_V4L2_COMMON=y
-CONFIG_VIDEO_ALLOW_V4L1=y
-CONFIG_VIDEO_V4L1_COMPAT=y
 # CONFIG_DVB_CORE is not set
 CONFIG_VIDEO_MEDIA=y
 
 #
 # Multimedia drivers
 #
+CONFIG_RC_CORE=y
+CONFIG_LIRC=y
+CONFIG_RC_MAP=y
+CONFIG_IR_NEC_DECODER=y
+CONFIG_IR_RC5_DECODER=y
+CONFIG_IR_RC6_DECODER=y
+CONFIG_IR_JVC_DECODER=y
+CONFIG_IR_SONY_DECODER=y
+CONFIG_IR_RC5_SZ_DECODER=y
+CONFIG_IR_LIRC_CODEC=y
+# CONFIG_IR_IMON is not set
+# CONFIG_IR_MCEUSB is not set
+# CONFIG_IR_REDRAT3 is not set
+# CONFIG_IR_STREAMZAP is not set
+# CONFIG_RC_LOOPBACK is not set
 # CONFIG_MEDIA_ATTACH is not set
 CONFIG_MEDIA_TUNER=y
 # CONFIG_MEDIA_TUNER_CUSTOMISE is not set
 CONFIG_MEDIA_TUNER_SIMPLE=y
 CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA827X=y
+CONFIG_MEDIA_TUNER_TDA18271=y
 CONFIG_MEDIA_TUNER_TDA9887=y
 CONFIG_MEDIA_TUNER_TEA5761=y
 CONFIG_MEDIA_TUNER_TEA5767=y
@@ -1170,20 +1463,56 @@ CONFIG_MEDIA_TUNER_XC2028=y
 CONFIG_MEDIA_TUNER_XC5000=y
 CONFIG_MEDIA_TUNER_MC44S803=y
 CONFIG_VIDEO_V4L2=y
-CONFIG_VIDEO_V4L1=y
 CONFIG_VIDEOBUF_GEN=y
 CONFIG_VIDEOBUF_DMA_CONTIG=y
+CONFIG_VIDEOBUF2_CORE=y
 # CONFIG_VIDEO_RK29XX_VOUT is not set
 CONFIG_VIDEO_CAPTURE_DRIVERS=y
 # CONFIG_VIDEO_ADV_DEBUG is not set
 # CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
 CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
-# CONFIG_VIDEO_VIVI is not set
-# CONFIG_VIDEO_CPIA is not set
+CONFIG_VIDEO_IR_I2C=y
+
+#
+# Audio decoders, processors and mixers
+#
+
+#
+# RDS decoders
+#
+
+#
+# Video decoders
+#
+
+#
+# Video and audio decoders
+#
+
+#
+# MPEG video encoders
+#
+
+#
+# Video encoders
+#
+
+#
+# Camera sensor devices
+#
+
+#
+# Video improvement chips
+#
+
+#
+# Miscelaneous helper chips
+#
 # CONFIG_VIDEO_CPIA2 is not set
-# CONFIG_VIDEO_SAA5246A is not set
-# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_VIDEO_SR030PC30 is not set
+# CONFIG_VIDEO_NOON010PC30 is not set
 CONFIG_SOC_CAMERA=y
+# CONFIG_SOC_CAMERA_IMX074 is not set
 # CONFIG_SOC_CAMERA_MT9M001 is not set
 # CONFIG_SOC_CAMERA_MT9M111 is not set
 # CONFIG_SOC_CAMERA_MT9M112 is not set
@@ -1192,15 +1521,19 @@ CONFIG_SOC_CAMERA=y
 # CONFIG_SOC_CAMERA_MT9P111 is not set
 # CONFIG_SOC_CAMERA_MT9D112 is not set
 # CONFIG_SOC_CAMERA_MT9D113 is not set
+# CONFIG_SOC_CAMERA_MT9T112 is not set
 # CONFIG_SOC_CAMERA_MT9V022 is not set
+# CONFIG_SOC_CAMERA_RJ54N1 is not set
 # CONFIG_SOC_CAMERA_TW9910 is not set
 # CONFIG_SOC_CAMERA_PLATFORM is not set
+# CONFIG_SOC_CAMERA_OV2640 is not set
+# CONFIG_SOC_CAMERA_OV6650 is not set
 # CONFIG_SOC_CAMERA_OV772X is not set
 # CONFIG_SOC_CAMERA_OV7675 is not set
 # CONFIG_SOC_CAMERA_OV2655 is not set
 CONFIG_SOC_CAMERA_OV2659=y
+# CONFIG_SOC_CAMERA_OV7690 is not set
 # CONFIG_SOC_CAMERA_OV9650 is not set
-# CONFIG_SOC_CAMERA_OV2640 is not set
 # CONFIG_SOC_CAMERA_OV3640 is not set
 CONFIG_SOC_CAMERA_OV5642=y
 CONFIG_OV5642_AUTOFOCUS=y
@@ -1208,6 +1541,7 @@ CONFIG_OV5642_AUTOFOCUS=y
 # CONFIG_SOC_CAMERA_OV5640 is not set
 # CONFIG_SOC_CAMERA_S5K6AA is not set
 # CONFIG_SOC_CAMERA_GT2005 is not set
+# CONFIG_SOC_CAMERA_GC0307 is not set
 # CONFIG_SOC_CAMERA_GC0308 is not set
 # CONFIG_SOC_CAMERA_GC0309 is not set
 # CONFIG_SOC_CAMERA_GC2015 is not set
@@ -1216,12 +1550,17 @@ CONFIG_OV5642_AUTOFOCUS=y
 # CONFIG_SOC_CAMERA_SIV120B is not set
 # CONFIG_SOC_CAMERA_SID130B is not set
 # CONFIG_SOC_CAMERA_NT99250 is not set
+# CONFIG_SOC_CAMERA_OV9640 is not set
+# CONFIG_SOC_CAMERA_OV9740 is not set
+# CONFIG_VIDEO_SH_MOBILE_CSI2 is not set
 # CONFIG_VIDEO_SH_MOBILE_CEU is not set
 CONFIG_VIDEO_RK29=y
 CONFIG_VIDEO_RK29_WORK_ONEFRAME=y
 # CONFIG_VIDEO_RK29_WORK_PINGPONG is not set
 CONFIG_VIDEO_RK29_WORK_IPP=y
 # CONFIG_VIDEO_RK29_WORK_NOT_IPP is not set
+CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_ON=y
+# CONFIG_VIDEO_RK29_DIGITALZOOM_IPP_OFF is not set
 CONFIG_V4L_USB_DRIVERS=y
 # CONFIG_USB_VIDEO_CLASS is not set
 CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
@@ -1229,16 +1568,24 @@ CONFIG_USB_GSPCA=m
 # CONFIG_USB_M5602 is not set
 # CONFIG_USB_STV06XX is not set
 # CONFIG_USB_GL860 is not set
+# CONFIG_USB_GSPCA_BENQ is not set
 # CONFIG_USB_GSPCA_CONEX is not set
+# CONFIG_USB_GSPCA_CPIA1 is not set
 # CONFIG_USB_GSPCA_ETOMS is not set
 # CONFIG_USB_GSPCA_FINEPIX is not set
 # CONFIG_USB_GSPCA_JEILINJ is not set
+# CONFIG_USB_GSPCA_KINECT is not set
+# CONFIG_USB_GSPCA_KONICA is not set
 # CONFIG_USB_GSPCA_MARS is not set
 # CONFIG_USB_GSPCA_MR97310A is not set
+# CONFIG_USB_GSPCA_NW80X is not set
 # CONFIG_USB_GSPCA_OV519 is not set
 # CONFIG_USB_GSPCA_OV534 is not set
+# CONFIG_USB_GSPCA_OV534_9 is not set
 # CONFIG_USB_GSPCA_PAC207 is not set
+# CONFIG_USB_GSPCA_PAC7302 is not set
 # CONFIG_USB_GSPCA_PAC7311 is not set
+# CONFIG_USB_GSPCA_SN9C2028 is not set
 # CONFIG_USB_GSPCA_SN9C20X is not set
 # CONFIG_USB_GSPCA_SONIXB is not set
 # CONFIG_USB_GSPCA_SONIXJ is not set
@@ -1248,35 +1595,31 @@ CONFIG_USB_GSPCA=m
 # CONFIG_USB_GSPCA_SPCA506 is not set
 # CONFIG_USB_GSPCA_SPCA508 is not set
 # CONFIG_USB_GSPCA_SPCA561 is not set
+# CONFIG_USB_GSPCA_SPCA1528 is not set
 # CONFIG_USB_GSPCA_SQ905 is not set
 # CONFIG_USB_GSPCA_SQ905C is not set
+# CONFIG_USB_GSPCA_SQ930X is not set
 # CONFIG_USB_GSPCA_STK014 is not set
+# CONFIG_USB_GSPCA_STV0680 is not set
 # CONFIG_USB_GSPCA_SUNPLUS is not set
 # CONFIG_USB_GSPCA_T613 is not set
 # CONFIG_USB_GSPCA_TV8532 is not set
 # CONFIG_USB_GSPCA_VC032X is not set
+# CONFIG_USB_GSPCA_VICAM is not set
+# CONFIG_USB_GSPCA_XIRLINK_CIT is not set
 # CONFIG_USB_GSPCA_ZC3XX is not set
 # CONFIG_VIDEO_PVRUSB2 is not set
 # CONFIG_VIDEO_HDPVR is not set
 # CONFIG_VIDEO_EM28XX is not set
 # CONFIG_VIDEO_CX231XX 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_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_PWC_INPUT_EVDEV=y
 # CONFIG_USB_ZR364XX is not set
 # CONFIG_USB_STKWEBCAM is not set
 # CONFIG_USB_S2255 is not set
+# CONFIG_V4L_MEM2MEM_DRIVERS is not set
 CONFIG_RADIO_ADAPTERS=y
 # CONFIG_I2C_SI4713 is not set
 # CONFIG_RADIO_SI4713 is not set
@@ -1284,12 +1627,21 @@ CONFIG_RADIO_ADAPTERS=y
 # CONFIG_RADIO_SI470X is not set
 # CONFIG_USB_MR800 is not set
 # CONFIG_RADIO_TEA5764 is not set
+# CONFIG_RADIO_SAA7706H is not set
+# CONFIG_RADIO_TEF6862 is not set
+# CONFIG_RADIO_WL1273 is not set
+
+#
+# Texas Instruments WL128x FM driver (ST based)
+#
+# CONFIG_RADIO_WL128X is not set
 # CONFIG_SMS_SIANO_MDTV is not set
-# CONFIG_DAB is not set
 
 #
 # Graphics support
 #
+# CONFIG_DRM is not set
+# CONFIG_ION is not set
 # CONFIG_VGASTATE is not set
 # CONFIG_VIDEO_OUTPUT_CONTROL is not set
 CONFIG_FB=y
@@ -1305,6 +1657,7 @@ CONFIG_FB_CFB_IMAGEBLIT=y
 # CONFIG_FB_SYS_IMAGEBLIT is not set
 # CONFIG_FB_FOREIGN_ENDIAN is not set
 # CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_WMT_GE_ROPS is not set
 # CONFIG_FB_SVGALIB is not set
 # CONFIG_FB_MACMODES is not set
 # CONFIG_FB_BACKLIGHT is not set
@@ -1316,15 +1669,16 @@ CONFIG_FB_CFB_IMAGEBLIT=y
 #
 # CONFIG_FB_S1D13XXX is not set
 # CONFIG_FB_TMIO is not set
-# CONFIG_FB_RK2818 is not set
 CONFIG_FB_RK29=y
 CONFIG_FB_WORK_IPP=y
 # CONFIG_FB_SCALING_OSD is not set
 CONFIG_FB_ROTATE_VIDEO=y
+# CONFIG_FB_MIRROR_X_Y is not set
 CONFIG_CLOSE_WIN1_DYNAMIC=y
+# CONFIG_FB_WIMO is not set
+# CONFIG_FB_UDL is not set
 # CONFIG_FB_VIRTUAL is not set
 # CONFIG_FB_METRONOME is not set
-# CONFIG_FB_MB862XX is not set
 # CONFIG_FB_BROADSHEET is not set
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 # CONFIG_LCD_CLASS_DEVICE is not set
@@ -1332,9 +1686,12 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y
 # CONFIG_BACKLIGHT_GENERIC is not set
 CONFIG_BACKLIGHT_WM831X=y
 # CONFIG_BACKLIGHT_RK29_BL is not set
+# CONFIG_BACKLIGHT_RK29_NEWTON_BL is not set
 # CONFIG_FIH_TOUCHKEY_LED is not set
 # CONFIG_BACKLIGHT_AW9364 is not set
 # CONFIG_BUTTON_LIGHT is not set
+# CONFIG_BACKLIGHT_ADP8860 is not set
+# CONFIG_BACKLIGHT_ADP8870 is not set
 
 #
 # Display device support
@@ -1345,6 +1702,7 @@ CONFIG_DISPLAY_SUPPORT=y
 # Display hardware drivers
 #
 # CONFIG_LCD_NULL is not set
+# CONFIG_LCD_LG_LP097X02 is not set
 # CONFIG_LCD_TD043MGEA1 is not set
 # CONFIG_LCD_HX8357 is not set
 # CONFIG_LCD_TJ048NC01CA is not set
@@ -1353,8 +1711,10 @@ CONFIG_DISPLAY_SUPPORT=y
 # CONFIG_LCD_RGB_TFT480800_25_E is not set
 # CONFIG_LCD_HSD100PXN is not set
 # CONFIG_LCD_HSD07PFW1 is not set
+# CONFIG_LCD_BYD8688FTGF is not set
 # CONFIG_LCD_B101AW06 is not set
 CONFIG_LCD_LS035Y8DX02A=y
+# CONFIG_LCD_LS035Y8DX04A is not set
 # CONFIG_LCD_CPTCLAA038LA31XE is not set
 # CONFIG_LCD_A060SE02 is not set
 # CONFIG_LCD_S1D13521 is not set
@@ -1364,9 +1724,10 @@ CONFIG_LCD_LS035Y8DX02A=y
 # CONFIG_LCD_MCU_TFT480800_25_E is not set
 # CONFIG_LCD_NT35510 is not set
 # CONFIG_LCD_ILI9803_CPT4_3 is not set
-# CONFIG_DEFAULT_OUT_HDMI is not set
 # CONFIG_LCD_AT070TNA2 is not set
 # CONFIG_LCD_AT070TN93 is not set
+# CONFIG_LCD_TX23D88VM is not set
+# CONFIG_LCD_A050VL01 is not set
 
 #
 # HDMI
@@ -1376,7 +1737,6 @@ CONFIG_LCD_LS035Y8DX02A=y
 #
 # Console display driver support
 #
-# CONFIG_VGA_CONSOLE is not set
 CONFIG_DUMMY_CONSOLE=y
 # CONFIG_FRAMEBUFFER_CONSOLE is not set
 CONFIG_LOGO=y
@@ -1409,24 +1769,90 @@ CONFIG_SND_JACK=y
 # CONFIG_SND_SPI is not set
 # CONFIG_SND_USB is not set
 CONFIG_SND_SOC=y
+# CONFIG_SND_SOC_CACHE_LZO is not set
 CONFIG_SND_RK29_SOC=y
 CONFIG_SND_RK29_SOC_I2S=y
 # CONFIG_SND_RK29_SOC_I2S_2CH is not set
 CONFIG_SND_RK29_SOC_I2S_8CH=y
+# CONFIG_SND_I2S_DMA_EVENT_DYNAMIC is not set
+CONFIG_SND_I2S_DMA_EVENT_STATIC=y
 # CONFIG_SND_RK29_SOC_WM8988 is not set
 # CONFIG_SND_RK29_SOC_WM8900 is not set
-# CONFIG_SND_RK29_SOC_alc5621 is not set
-# CONFIG_SND_RK29_SOC_alc5631 is not set
+# CONFIG_SND_RK29_SOC_RT5621 is not set
+# CONFIG_SND_RK29_SOC_RT5631 is not set
 # CONFIG_SND_RK29_SOC_RT5625 is not set
 CONFIG_SND_RK29_SOC_WM8994=y
 # CONFIG_SND_RK29_SOC_CS42L52 is not set
+# CONFIG_SND_RK29_SOC_AIC3111 is not set
 # CONFIG_SND_RK29_CODEC_SOC_MASTER is not set
 CONFIG_SND_RK29_CODEC_SOC_SLAVE=y
+# CONFIG_ADJUST_VOL_BY_CODEC is not set
 CONFIG_SND_SOC_I2C_AND_SPI=y
 # CONFIG_SND_SOC_ALL_CODECS is not set
+CONFIG_SND_SOC_WM_HUBS=y
 CONFIG_SND_SOC_WM8994=y
 # CONFIG_SOUND_PRIME is not set
-CONFIG_HID_SUPPORT = y
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=y
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=y
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_ACRUX is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_PRODIKEYS is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KEYTOUCH is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_UCLOGIC is not set
+# CONFIG_HID_WALTOP is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_TWINHAN is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MAGICMOUSE is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_MULTITOUCH is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_ORTEK is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+# CONFIG_HID_QUANTA is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_ROCCAT_ARVO is not set
+# CONFIG_HID_ROCCAT_KONE is not set
+# CONFIG_HID_ROCCAT_KONEPLUS is not set
+# CONFIG_HID_ROCCAT_KOVAPLUS is not set
+# CONFIG_HID_ROCCAT_PYRA is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
 CONFIG_USB_SUPPORT=y
 CONFIG_USB_ARCH_HAS_HCD=y
 # CONFIG_USB_ARCH_HAS_OHCI is not set
@@ -1441,8 +1867,6 @@ CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
 # CONFIG_USB_DEVICEFS is not set
 CONFIG_USB_DEVICE_CLASS=y
 # CONFIG_USB_DYNAMIC_MINORS is not set
-# CONFIG_USB_SUSPEND is not set
-# CONFIG_USB_OTG is not set
 # CONFIG_USB_OTG_WHITELIST is not set
 CONFIG_USB_OTG_BLACKLIST_HUB=y
 # CONFIG_USB_MON is not set
@@ -1461,7 +1885,6 @@ CONFIG_USB_OTG_BLACKLIST_HUB=y
 # CONFIG_USB_R8A66597_HCD is not set
 # CONFIG_USB_HWA_HCD is not set
 # CONFIG_USB_MUSB_HDRC is not set
-# CONFIG_USB_GADGET_MUSB_HDRC is not set
 
 #
 # USB Device Class drivers
@@ -1480,6 +1903,7 @@ CONFIG_USB_OTG_BLACKLIST_HUB=y
 #
 CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_REALTEK is not set
 # CONFIG_USB_STORAGE_DATAFAB is not set
 # CONFIG_USB_STORAGE_FREECOM is not set
 # CONFIG_USB_STORAGE_ISD200 is not set
@@ -1491,6 +1915,8 @@ CONFIG_USB_STORAGE=y
 # CONFIG_USB_STORAGE_ONETOUCH is not set
 # CONFIG_USB_STORAGE_KARMA is not set
 # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_STORAGE_ENE_UB6250 is not set
+# CONFIG_USB_UAS is not set
 # CONFIG_USB_LIBUSUAL is not set
 
 #
@@ -1536,6 +1962,7 @@ CONFIG_USB_SERIAL_GENERIC=y
 # CONFIG_USB_SERIAL_NAVMAN is not set
 # CONFIG_USB_SERIAL_PL2303 is not set
 # CONFIG_USB_SERIAL_OTI6858 is not set
+# CONFIG_USB_SERIAL_QCAUX is not set
 # CONFIG_USB_SERIAL_QUALCOMM is not set
 # CONFIG_USB_SERIAL_SPCP8X5 is not set
 # CONFIG_USB_SERIAL_HP4X is not set
@@ -1546,9 +1973,13 @@ CONFIG_USB_SERIAL_GENERIC=y
 # CONFIG_USB_SERIAL_TI is not set
 # CONFIG_USB_SERIAL_CYBERJACK is not set
 # CONFIG_USB_SERIAL_XIRCOM is not set
+CONFIG_USB_SERIAL_WWAN=y
 CONFIG_USB_SERIAL_OPTION=y
 # CONFIG_USB_SERIAL_OMNINET is not set
 # CONFIG_USB_SERIAL_OPTICON is not set
+# CONFIG_USB_SERIAL_VIVOPAY_SERIAL is not set
+# CONFIG_USB_SERIAL_ZIO is not set
+# CONFIG_USB_SERIAL_SSU100 is not set
 # CONFIG_USB_SERIAL_DEBUG is not set
 
 #
@@ -1561,7 +1992,6 @@ CONFIG_USB_SERIAL_OPTION=y
 # 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
@@ -1573,30 +2003,16 @@ CONFIG_USB_SERIAL_OPTION=y
 # CONFIG_USB_IOWARRIOR is not set
 # CONFIG_USB_TEST is not set
 # CONFIG_USB_ISIGHTFW is not set
-# CONFIG_USB_VST is not set
+# CONFIG_USB_YUREX is not set
 CONFIG_USB_GADGET=y
 # CONFIG_USB_GADGET_DEBUG is not set
 # CONFIG_USB_GADGET_DEBUG_FILES is not set
 CONFIG_USB_GADGET_VBUS_DRAW=2
 CONFIG_USB_GADGET_SELECTED=y
-# CONFIG_USB_GADGET_AT91 is not set
-# CONFIG_USB_GADGET_ATMEL_USBA is not set
-# CONFIG_USB_GADGET_FSL_USB2 is not set
-# CONFIG_USB_GADGET_LH7A40X is not set
-# CONFIG_USB_GADGET_OMAP is not set
-# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_FUSB300 is not set
 # CONFIG_USB_GADGET_R8A66597 is not set
-# CONFIG_USB_GADGET_PXA27X is not set
-# CONFIG_USB_GADGET_S3C_HSOTG is not set
-# CONFIG_USB_GADGET_IMX is not set
-# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_PXA_U2O is not set
 # CONFIG_USB_GADGET_M66592 is not set
-# CONFIG_USB_GADGET_AMD5536UDC is not set
-# CONFIG_USB_GADGET_FSL_QE is not set
-# CONFIG_USB_GADGET_CI13XXX is not set
-# CONFIG_USB_GADGET_NET2280 is not set
-# CONFIG_USB_GADGET_GOKU is not set
-# CONFIG_USB_GADGET_LANGWELL is not set
 CONFIG_USB_GADGET_DWC_OTG=y
 CONFIG_USB_DWC_OTG=y
 # CONFIG_USB_GADGET_DUMMY_HCD is not set
@@ -1604,22 +2020,27 @@ CONFIG_USB_GADGET_DUALSPEED=y
 # CONFIG_USB_ZERO is not set
 # CONFIG_USB_AUDIO is not set
 # CONFIG_USB_ETH is not set
+# CONFIG_USB_G_NCM is not set
 # CONFIG_USB_GADGETFS is not set
+# CONFIG_USB_FUNCTIONFS is not set
 # CONFIG_USB_FILE_STORAGE is not set
+# CONFIG_USB_MASS_STORAGE is not set
 # CONFIG_USB_G_SERIAL is not set
 # CONFIG_USB_MIDI_GADGET is not set
 # CONFIG_USB_G_PRINTER is not set
-CONFIG_USB_ANDROID=y
-# CONFIG_USB_ANDROID_ACM is not set
-CONFIG_USB_ANDROID_ADB=y
-CONFIG_USB_ANDROID_MASS_STORAGE=y
-# CONFIG_USB_ANDROID_RNDIS is not set
+CONFIG_USB_G_ANDROID=y
 # CONFIG_USB_CDC_COMPOSITE is not set
+# CONFIG_USB_G_MULTI is not set
+# CONFIG_USB_G_HID is not set
+# CONFIG_USB_G_DBGP is not set
+# CONFIG_USB_G_WEBCAM is not set
 
 #
 # OTG and related infrastructure
 #
+# CONFIG_USB_OTG_WAKELOCK is not set
 # CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_ULPI is not set
 # CONFIG_NOP_USB_XCEIV is not set
 CONFIG_USB11_HOST=y
 CONFIG_USB11_HOST_EN=y
@@ -1630,10 +2051,12 @@ CONFIG_DWC_OTG_DEVICE_ONLY=y
 # CONFIG_DWC_OTG_BOTH_HOST_SLAVE is not set
 CONFIG_DWC_CONN_EN=y
 # CONFIG_DWC_OTG_DEBUG is not set
+# CONFIG_DWC_REMOTE_WAKEUP is not set
 CONFIG_DWC_OTG=y
 CONFIG_MMC=y
 # CONFIG_MMC_DEBUG is not set
 CONFIG_MMC_UNSAFE_RESUME=y
+# CONFIG_MMC_CLKGATE is not set
 CONFIG_MMC_EMBEDDED_SDIO=y
 CONFIG_MMC_PARANOID_SD_INIT=y
 
@@ -1641,6 +2064,7 @@ CONFIG_MMC_PARANOID_SD_INIT=y
 # MMC/SD/SDIO Card Drivers
 #
 CONFIG_MMC_BLOCK=y
+CONFIG_MMC_BLOCK_MINORS=8
 CONFIG_MMC_BLOCK_BOUNCE=y
 # CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set
 # CONFIG_SDIO_UART is not set
@@ -1649,21 +2073,23 @@ CONFIG_MMC_BLOCK_BOUNCE=y
 #
 # MMC/SD/SDIO Host Controller Drivers
 #
-# CONFIG_SDMMC_RK29_OLD=y
 CONFIG_SDMMC_RK29=y
 
 #
 # Now, there are two SDMMC controllers selected, SDMMC0 and SDMMC1.
 #
+# CONFIG_SDMMC_RK29_OLD is not set
 CONFIG_SDMMC0_RK29=y
-# CONFIG_EMMC_RK29 is not set
+# CONFIG_SDMMC0_RK29_WRITE_PROTECT is not set
 CONFIG_SDMMC1_RK29=y
+# CONFIG_SDMMC1_RK29_WRITE_PROTECT is not set
 # CONFIG_MMC_SDHCI is not set
-# CONFIG_MMC_AT91 is not set
-# CONFIG_MMC_ATMELMCI is not set
-# CONFIG_MMC_SPI is not set
+# CONFIG_MMC_DW is not set
+# CONFIG_MMC_VUB300 is not set
+# CONFIG_MMC_USHC is not set
 # CONFIG_MEMSTICK is not set
 # CONFIG_NEW_LEDS is not set
+# CONFIG_NFC_DEVICES is not set
 CONFIG_SWITCH=y
 CONFIG_SWITCH_GPIO=y
 # CONFIG_ACCESSIBILITY is not set
@@ -1692,22 +2118,28 @@ CONFIG_RTC_INTF_ALARM_DEV=y
 # CONFIG_RTC_DRV_DS1307 is not set
 # CONFIG_RTC_DRV_DS1374 is not set
 # CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_DS3232 is not set
 # CONFIG_RTC_DRV_MAX6900 is not set
 # CONFIG_RTC_DRV_RS5C372 is not set
 # CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_ISL12022 is not set
 # CONFIG_RTC_DRV_X1205 is not set
 # CONFIG_RTC_DRV_PCF8563 is not set
 # CONFIG_RTC_DRV_PCF8583 is not set
 # CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_BQ32K is not set
 # CONFIG_RTC_DRV_S35390A is not set
 # CONFIG_RTC_DRV_S35392A is not set
 # CONFIG_RTC_DRV_FM3130 is not set
 # CONFIG_RTC_DRV_RX8581 is not set
 # CONFIG_RTC_DRV_RX8025 is not set
+# CONFIG_RTC_DRV_EM3027 is not set
+# CONFIG_RTC_DRV_RV3029C2 is not set
 
 #
 # SPI RTC drivers
 #
+# CONFIG_RTC_DRV_M41T93 is not set
 # CONFIG_RTC_DRV_M41T94 is not set
 # CONFIG_RTC_DRV_DS1305 is not set
 # CONFIG_RTC_DRV_DS1390 is not set
@@ -1729,7 +2161,9 @@ CONFIG_RTC_INTF_ALARM_DEV=y
 # CONFIG_RTC_DRV_M48T86 is not set
 # CONFIG_RTC_DRV_M48T35 is not set
 # CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
 # CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
 # CONFIG_RTC_DRV_V3020 is not set
 CONFIG_RTC_DRV_WM831X=y
 
@@ -1739,17 +2173,13 @@ CONFIG_RTC_DRV_WM831X=y
 # CONFIG_DMADEVICES is not set
 # CONFIG_AUXDISPLAY is not set
 # CONFIG_UIO is not set
-
-#
-# TI VLYNQ
-#
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
-# CONFIG_USB_IP_COMMON is not set
-# CONFIG_PRISM2_USB is not set
+# CONFIG_VIDEO_TM6000 is not set
+# CONFIG_USBIP_CORE is not set
 # CONFIG_ECHO is not set
-# CONFIG_COMEDI is not set
+# CONFIG_BRCMUTIL is not set
 # CONFIG_ASUS_OLED is not set
+# CONFIG_R8712U is not set
 # CONFIG_TRANZPORT is not set
 
 #
@@ -1769,60 +2199,57 @@ CONFIG_ANDROID_RAM_CONSOLE_ERROR_CORRECTION_POLYNOMIAL=0x11d
 CONFIG_ANDROID_TIMED_OUTPUT=y
 CONFIG_ANDROID_TIMED_GPIO=y
 CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-
-#
-# Qualcomm MSM Camera And Video
-#
-
-#
-# Camera Sensor Selection
-#
-# CONFIG_DST is not set
 # CONFIG_POHMELFS is not set
-# CONFIG_PLAN9AUTH is not set
 # CONFIG_LINE6_USB is not set
 # CONFIG_USB_SERIAL_QUATECH2 is not set
 # CONFIG_USB_SERIAL_QUATECH_USB2 is not set
 # CONFIG_VT6656 is not set
-# CONFIG_FB_UDL is not set
-
-#
-# RAR Register Driver
-#
-# CONFIG_RAR_REGISTER is not set
 # CONFIG_IIO is not set
 
 #
-# DSP
-#
-# CONFIG_RK2818_DSP is not set
-
-#
-# RK1000 control
+# GPU Vivante
 #
-# CONFIG_RK1000_CONTROL is not set
+CONFIG_VIVANTE=y
 
 #
-# rk2818 POWER CONTROL
+# IPP
 #
-# CONFIG_RK2818_POWER is not set
+CONFIG_RK29_IPP=y
+# CONFIG_DEINTERLACE is not set
+# CONFIG_XVMALLOC is not set
+# CONFIG_ZRAM is not set
+# CONFIG_FB_SM7XX is not set
+# CONFIG_LIRC_STAGING is not set
+# CONFIG_EASYCAP is not set
+CONFIG_MACH_NO_WESTBRIDGE=y
+# CONFIG_USB_ENESTORAGE is not set
+# CONFIG_BCM_WIMAX is not set
+# CONFIG_FT1000 is not set
 
 #
-# GPU Vivante
+# Speakup console speech
 #
-CONFIG_VIVANTE=y
+# CONFIG_SPEAKUP is not set
+# CONFIG_TOUCHSCREEN_CLEARPAD_TM1217 is not set
+# CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4 is not set
 
 #
-# IPP
+# Altera FPGA firmware download module
 #
-CONFIG_RK29_IPP=y
-CONFIG_DEINTERLACE=n
+# CONFIG_ALTERA_STAPL is not set
+CONFIG_CLKDEV_LOOKUP=y
 
 #
 # CMMB
 #
 # CONFIG_CMMB is not set
 # CONFIG_TEST_CODE is not set
+# CONFIG_RK29_SMC is not set
+
+#
+# CIR support
+#
+# CONFIG_RK_CIR is not set
 
 #
 # File systems
@@ -1832,24 +2259,24 @@ CONFIG_EXT3_FS=y
 CONFIG_EXT3_DEFAULTS_TO_ORDERED=y
 # CONFIG_EXT3_FS_XATTR is not set
 CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT23=y
 # CONFIG_EXT4_FS_XATTR is not set
 # CONFIG_EXT4_DEBUG is not set
 CONFIG_JBD=y
 CONFIG_JBD2=y
 # CONFIG_REISERFS_FS is not set
 # CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
 # CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
 # CONFIG_BTRFS_FS is not set
 # CONFIG_NILFS2_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
 CONFIG_FILE_LOCKING=y
 CONFIG_FSNOTIFY=y
 # CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
 CONFIG_INOTIFY_USER=y
+# CONFIG_FANOTIFY is not set
 # CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
+# CONFIG_QUOTACTL is not set
 # CONFIG_AUTOFS4_FS is not set
 CONFIG_FUSE_FS=y
 # CONFIG_CUSE is not set
@@ -1884,6 +2311,7 @@ CONFIG_PROC_PAGE_MONITOR=y
 CONFIG_SYSFS=y
 CONFIG_TMPFS=y
 # CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_TMPFS_XATTR is not set
 # CONFIG_HUGETLB_PAGE is not set
 # CONFIG_CONFIGFS_FS is not set
 CONFIG_MISC_FILESYSTEMS=y
@@ -1896,6 +2324,7 @@ CONFIG_MISC_FILESYSTEMS=y
 # CONFIG_EFS_FS is not set
 # CONFIG_YAFFS_FS is not set
 # CONFIG_JFFS2_FS is not set
+# CONFIG_LOGFS is not set
 CONFIG_CRAMFS=y
 # CONFIG_SQUASHFS is not set
 # CONFIG_VXFS_FS is not set
@@ -1904,6 +2333,7 @@ CONFIG_CRAMFS=y
 # CONFIG_HPFS_FS is not set
 # CONFIG_QNX4FS_FS is not set
 # CONFIG_ROMFS_FS is not set
+# CONFIG_PSTORE is not set
 # CONFIG_SYSV_FS is not set
 # CONFIG_UFS_FS is not set
 # CONFIG_NETWORK_FILESYSTEMS is not set
@@ -1953,12 +2383,12 @@ CONFIG_NLS_ISO8859_15=y
 # CONFIG_NLS_KOI8_R is not set
 # CONFIG_NLS_KOI8_U is not set
 CONFIG_NLS_UTF8=y
-# CONFIG_DLM is not set
 
 #
 # Kernel hacking
 #
 CONFIG_PRINTK_TIME=y
+CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4
 CONFIG_ENABLE_WARN_DEPRECATED=y
 CONFIG_ENABLE_MUST_CHECK=y
 CONFIG_FRAME_WARN=1024
@@ -1967,12 +2397,13 @@ CONFIG_MAGIC_SYSRQ=y
 # CONFIG_UNUSED_SYMBOLS is not set
 # CONFIG_DEBUG_FS is not set
 # CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_DEBUG_SHIRQ is not set
-CONFIG_DETECT_SOFTLOCKUP=y
-# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
-CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+# CONFIG_LOCKUP_DETECTOR is not set
+# CONFIG_HARDLOCKUP_DETECTOR is not set
 CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEFAULT_HUNG_TASK_TIMEOUT=120
 # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
 CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
 # CONFIG_SCHED_DEBUG is not set
@@ -1988,47 +2419,63 @@ CONFIG_TIMER_STATS=y
 # CONFIG_DEBUG_MUTEXES is not set
 # CONFIG_DEBUG_LOCK_ALLOC is not set
 # CONFIG_PROVE_LOCKING is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
 # CONFIG_LOCK_STAT is not set
 # CONFIG_DEBUG_SPINLOCK_SLEEP is not set
 # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
+# CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
 CONFIG_DEBUG_BUGVERBOSE=y
 # CONFIG_DEBUG_INFO is not set
 # CONFIG_DEBUG_VM is not set
 # CONFIG_DEBUG_WRITECOUNT is not set
 # CONFIG_DEBUG_MEMORY_INIT is not set
 # CONFIG_DEBUG_LIST is not set
+# CONFIG_TEST_LIST_SORT is not set
 # CONFIG_DEBUG_SG is not set
 # CONFIG_DEBUG_NOTIFIERS is not set
 # CONFIG_DEBUG_CREDENTIALS is not set
 # CONFIG_BOOT_PRINTK_DELAY is not set
 # CONFIG_RCU_TORTURE_TEST is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_RCU_CPU_STALL_TIMEOUT=60
+CONFIG_RCU_CPU_STALL_VERBOSE=y
 # CONFIG_BACKTRACE_SELF_TEST is not set
 # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
 # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
 # CONFIG_FAULT_INJECTION is not set
 # CONFIG_LATENCYTOP is not set
-# CONFIG_PAGE_POISONING is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_DEBUG_PAGEALLOC is not set
 CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
+CONFIG_HAVE_DYNAMIC_FTRACE=y
+CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
 CONFIG_TRACING_SUPPORT=y
 # CONFIG_FTRACE is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
 # CONFIG_SAMPLES is not set
 CONFIG_HAVE_ARCH_KGDB=y
 # CONFIG_KGDB is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_STRICT_DEVMEM is not set
 CONFIG_ARM_UNWIND=y
 # CONFIG_DEBUG_USER is not set
-CONFIG_DEBUG_ERRORS=y
-# CONFIG_DEBUG_STACK_USAGE is not set
 # CONFIG_DEBUG_LL is not set
+# CONFIG_OC_ETM is not set
 
 #
 # Security options
 #
 # CONFIG_KEYS is not set
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
 # CONFIG_SECURITY is not set
 # CONFIG_SECURITYFS is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
 CONFIG_CRYPTO=y
 
 #
@@ -2042,9 +2489,10 @@ CONFIG_CRYPTO_BLKCIPHER2=y
 CONFIG_CRYPTO_HASH=y
 CONFIG_CRYPTO_HASH2=y
 CONFIG_CRYPTO_RNG2=y
-CONFIG_CRYPTO_PCOMP=y
+CONFIG_CRYPTO_PCOMP2=y
 CONFIG_CRYPTO_MANAGER=y
 CONFIG_CRYPTO_MANAGER2=y
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
 # CONFIG_CRYPTO_GF128MUL is not set
 # CONFIG_CRYPTO_NULL is not set
 CONFIG_CRYPTO_WORKQUEUE=y
@@ -2098,7 +2546,7 @@ CONFIG_CRYPTO_SHA1=y
 #
 # Ciphers
 #
-# CONFIG_CRYPTO_AES is not set
+CONFIG_CRYPTO_AES=y
 # CONFIG_CRYPTO_ANUBIS is not set
 CONFIG_CRYPTO_ARC4=y
 # CONFIG_CRYPTO_BLOWFISH is not set
@@ -2126,6 +2574,8 @@ CONFIG_CRYPTO_TWOFISH_COMMON=y
 # Random Number Generation
 #
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
 CONFIG_CRYPTO_HW=y
 # CONFIG_BINARY_PRINTF is not set
 
@@ -2133,7 +2583,6 @@ CONFIG_CRYPTO_HW=y
 # Library routines
 #
 CONFIG_BITREVERSE=y
-CONFIG_GENERIC_FIND_LAST_BIT=y
 CONFIG_CRC_CCITT=y
 CONFIG_CRC16=y
 # CONFIG_CRC_T10DIF is not set
@@ -2143,6 +2592,8 @@ CONFIG_CRC32=y
 # CONFIG_LIBCRC32C is not set
 CONFIG_ZLIB_INFLATE=y
 CONFIG_ZLIB_DEFLATE=y
+# CONFIG_XZ_DEC is not set
+# CONFIG_XZ_DEC_BCJ is not set
 CONFIG_DECOMPRESS_GZIP=y
 CONFIG_REED_SOLOMON=y
 CONFIG_REED_SOLOMON_ENC8=y
@@ -2151,3 +2602,4 @@ CONFIG_HAS_IOMEM=y
 CONFIG_HAS_IOPORT=y
 CONFIG_HAS_DMA=y
 CONFIG_NLATTR=y
+# CONFIG_AVERAGE is not set
index 247b2985610d134fae51ecd537e0700b959693fe..b72efe8bb629b088c0fe924e7b878bb9e3fd5cc9 100755 (executable)
@@ -599,57 +599,31 @@ static struct mma8452_platform_data mma8452_info = {
 };
 #endif
 
-#if defined (CONFIG_MPU_SENSORS_MPU3050)
 /*mpu3050*/
-static struct mpu3050_platform_data mpu3050_data = {
-               .int_config = 0x10,
-               //.orientation = { 1, 0, 0,0, -1, 0,0, 0, 1 },
-               //.orientation = { 0, 1, 0,-1, 0, 0,0, 0, -1 },
-               //.orientation = { -1, 0, 0,0, -1, 0,0, 0, -1 },
-               //.orientation = { 0, 1, 0, -1, 0, 0, 0, 0, 1 },
-               .orientation = { 1, 0, 0,0, 1, 0, 0, 0, 1 },
-               .level_shifter = 0,
+#if defined (CONFIG_MPU_SENSORS_MPU3050)
+static struct mpu_platform_data mpu3050_data = {
+       .int_config = 0x10,
+       .orientation = { 1, 0, 0,0, 1, 0, 0, 0, 1 },
+};
+#endif
+
+/* accel */
 #if defined (CONFIG_MPU_SENSORS_KXTF9)
-               .accel = {
-#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE
-                               .get_slave_descr = NULL ,
-#else
-                               .get_slave_descr = get_accel_slave_descr ,                      
-#endif
-                               .adapt_num = 0, // The i2c bus to which the mpu device is
-                               // connected
-                               //.irq = RK29_PIN6_PC4,
-                               .bus = EXT_SLAVE_BUS_SECONDARY,  //The secondary I2C of MPU
-                               .address = 0x0f,
-                               //.orientation = { 1, 0, 0,0, 1, 0,0, 0, 1 },
-                               //.orientation = { 0, -1, 0,-1, 0, 0,0, 0, -1 },
-                               //.orientation = { 0, 1, 0,1, 0, 0,0, 0, -1 },
-                               //.orientation = { 0, 1 ,0, -1 ,0, 0, 0, 0, 1 },
-                               .orientation = {1, 0, 0, 0, 1, 0, 0, 0, 1},
-               },
+static struct ext_slave_platform_data inv_mpu_kxtf9_data = {
+       .bus         = EXT_SLAVE_BUS_SECONDARY,
+       .adapt_num = 0,
+       .orientation = {1, 0, 0, 0, 1, 0, 0, 0, 1},
+};
 #endif
+
+/* compass */
 #if defined (CONFIG_MPU_SENSORS_AK8975)
-               .compass = {
-#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE
-                               .get_slave_descr = NULL,/*ak5883_get_slave_descr,*/
-#else
-                               .get_slave_descr = get_compass_slave_descr,
-#endif                                         
-                               .adapt_num = 0, // The i2c bus to which the compass device is. 
-                               // It can be difference with mpu
-                               // connected
-                               //.irq = RK29_PIN6_PC5,
-                               .bus = EXT_SLAVE_BUS_PRIMARY,
-                               .address = 0x0d,
-                               //.orientation = { -1, 0, 0,0, -1, 0,0, 0, 1 },
-                               //.orientation = { 0, -1, 0,-1, 0, 0,0, 0, -1 },
-                               //.orientation = { 0, 1, 0,1, 0, 0,0, 0, -1 },
-                               //.orientation = { 0, -1, 0, 1, 0, 0, 0, 0, 1 },
-                               .orientation = {0, 1, 0, -1, 0, 0, 0, 0, 1},
-               },
+static struct ext_slave_platform_data inv_mpu_ak8975_data = {
+       .bus         = EXT_SLAVE_BUS_PRIMARY,
+       .adapt_num = 0,
+       .orientation = {0, 1, 0, -1, 0, 0, 0, 0, 1},
 };
 #endif
-#endif
 
 #if defined(CONFIG_GPIO_WM831X)
 struct rk29_gpio_expander_info  wm831x_gpio_settinginfo[] = {
@@ -2125,6 +2099,25 @@ static struct i2c_board_info __initdata board_i2c0_devices[] = {
                .platform_data  = &mpu3050_data,
        },
 #endif
+#if defined (CONFIG_MPU_SENSORS_KXTF9)
+       {
+               .type                   = "kxtf9",
+               .addr           = 0x0f,
+               .flags                  = 0,    
+               //.irq                  = RK29_PIN6_PC4,
+               .platform_data = &inv_mpu_kxtf9_data,
+       },
+#endif
+#if defined (CONFIG_MPU_SENSORS_AK8975)
+       {
+               .type                   = "ak8975",
+               .addr                   = 0x0d,
+               .flags                  = 0,    
+               //.irq                  = RK29_PIN6_PC5,
+               .platform_data = &inv_mpu_ak8975_data,
+       },
+#endif
+
 };
 #endif
 
index 7b48ab90e592166dd8b45f0e58c77505dc8a9bb2..04505e6198251249841f8666e9a02cc4eac56790 100644 (file)
@@ -561,7 +561,7 @@ source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
 source "drivers/misc/rk29_modem/Kconfig"
 source "drivers/misc/gps/Kconfig"
-source "drivers/misc/mpu3050/Kconfig"
+source "drivers/misc/inv_mpu/Kconfig"
 source "drivers/misc/iwmc3200top/Kconfig"
 source "drivers/misc/ti-st/Kconfig"
 source "drivers/misc/lis3lv02d/Kconfig"
index 410e64d7103d990c52261a23b54e4321896a3673..dd3ff0b6fefa3c124a11333bd09ea76b91cfebc3 100644 (file)
@@ -58,7 +58,7 @@ obj-$(CONFIG_MW100)           += MW100.o
 obj-$(CONFIG_STE)              += ste.o
 obj-$(CONFIG_RK29_SUPPORT_MODEM)       += rk29_modem/
 obj-$(CONFIG_GPS_GNS7560)      += gps/
-obj-y += mpu3050/
+obj-y += inv_mpu/
 obj-$(CONFIG_RK29_NEWTON)      += newton.o
 obj-$(CONFIG_TDSC8800) += tdsc8800.o
 obj-$(CONFIG_RK29_SC8800)      +=      sc8800.o
diff --git a/drivers/misc/inv_mpu/Kconfig b/drivers/misc/inv_mpu/Kconfig
new file mode 100644 (file)
index 0000000..53c7c20
--- /dev/null
@@ -0,0 +1,77 @@
+config MPU_SENSORS_TIMERIRQ
+       tristate "MPU Timer IRQ"
+       help
+         If you say yes here you get access to the timerirq device handle which
+         can be used to select on.  This can be used instead of IRQ's, sleeping,
+         or timer threads.  Reading from this device returns the same type of
+         information as reading from the MPU and slave IRQ's.
+
+menuconfig: INV_SENSORS
+       tristate "Motion Processing Unit"
+       depends on I2C
+       default y
+
+if INV_SENSORS
+
+choice
+       prompt "MPU Master"
+       depends on I2C && INV_SENSORS
+       default MPU_SENSORS_MPU3050
+
+config MPU_SENSORS_MPU3050
+       bool "MPU3050"
+       depends on I2C
+       select MPU_SENSORS_MPU3050_GYRO
+       help
+         If you say yes here you get support for the MPU3050 Gyroscope driver
+         This driver can also be built as a module.  If so, the module
+         will be called mpu3050.
+
+config MPU_SENSORS_MPU6050A2
+       bool "MPU6050A2"
+       depends on I2C
+       select MPU_SENSORS_MPU6050_GYRO
+       help
+         If you say yes here you get support for the MPU6050A2 Gyroscope driver
+         This driver can also be built as a module.  If so, the module
+         will be called mpu6050a2.
+
+config MPU_SENSORS_MPU6050B1
+       bool "MPU6050B1"
+       select MPU_SENSORS_MPU6050_GYRO
+       depends on I2C
+       help
+         If you say yes here you get support for the MPU6050 Gyroscope driver
+         This driver can also be built as a module.  If so, the module
+         will be called mpu6050b1.
+
+endchoice
+
+choice
+       prompt "Gyroscope Type"
+       depends on I2C && INV_SENSORS
+       default MPU_SENSORS_MPU3050_GYRO
+
+config MPU_SENSORS_MPU3050_GYRO
+       bool "MPU3050 built in gyroscope"
+       depends on MPU_SENSORS_MPU3050
+
+config MPU_SENSORS_MPU6050_GYRO
+       bool "MPU6050 built in gyroscope"
+       depends on MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+
+endchoice
+
+source "drivers/misc/inv_mpu/accel/Kconfig"
+source "drivers/misc/inv_mpu/compass/Kconfig"
+source "drivers/misc/inv_mpu/pressure/Kconfig"
+
+config MPU_USERSPACE_DEBUG
+       bool "MPU Userspace debugging ioctls"
+       help
+         Allows the ioctls MPU_SET_MPU_PLATFORM_DATA and
+         MPU_SET_EXT_SLAVE_PLATFORM_DATA, which allows userspace applications
+         to override the slave address and orientation.  This is dangerous
+         and could cause the devices not to work.
+
+endif #INV_SENSORS
diff --git a/drivers/misc/inv_mpu/Makefile b/drivers/misc/inv_mpu/Makefile
new file mode 100644 (file)
index 0000000..248648f
--- /dev/null
@@ -0,0 +1,45 @@
+
+# Kernel makefile for motions sensors
+#
+#
+
+# MPU
+ifdef CONFIG_MPU_SENSORS_MPU3050
+INV_MODULE_NAME := mpu3050
+endif
+
+ifdef CONFIG_MPU_SENSORS_MPU6050A2
+INV_MODULE_NAME := mpu6050
+endif
+
+ifdef CONFIG_MPU_SENSORS_MPU6050B1
+INV_MODULE_NAME := mpu6050
+endif
+
+obj-$(CONFIG_INV_SENSORS)      += $(INV_MODULE_NAME).o
+
+$(INV_MODULE_NAME)-objs += mpuirq.o
+$(INV_MODULE_NAME)-objs += slaveirq.o
+$(INV_MODULE_NAME)-objs += mpu-dev.o
+$(INV_MODULE_NAME)-objs += mlsl-kernel.o
+$(INV_MODULE_NAME)-objs += mldl_cfg.o
+$(INV_MODULE_NAME)-objs += mldl_print_cfg.o
+
+ifdef CONFIG_MPU_SENSORS_MPU6050A2
+$(INV_MODULE_NAME)-objs += accel/mpu6050.o
+endif
+
+ifdef CONFIG_MPU_SENSORS_MPU6050B1
+$(INV_MODULE_NAME)-objs += accel/mpu6050.o
+endif
+
+EXTRA_CFLAGS += -Idrivers/misc/inv_mpu
+EXTRA_CFLAGS += -D__C99_DESIGNATED_INITIALIZER
+EXTRA_CFLAGS += -DINV_CACHE_DMP=1
+
+obj-$(CONFIG_MPU_SENSORS_TIMERIRQ)+= timerirq.o
+
+obj-y                  += accel/
+obj-y                  += compass/
+obj-y                  += pressure/
+
diff --git a/drivers/misc/inv_mpu/README b/drivers/misc/inv_mpu/README
new file mode 100644 (file)
index 0000000..ce592c8
--- /dev/null
@@ -0,0 +1,104 @@
+Kernel driver mpu
+=====================
+
+Supported chips:
+  * InvenSense IMU3050
+    Prefix: 'mpu3050'
+    Datasheet:
+        PS-MPU-3000A-00.2.4b.pdf
+
+Author: InvenSense <http://invensense.com>
+
+Description
+-----------
+The mpu is a motion processor unit that controls the mpu3050 gyroscope, a slave
+accelerometer, a compass and a pressure sensor.  This document describes how to
+install the driver into a Linux kernel.
+
+Sysfs entries
+-------------
+/dev/mpu
+/dev/mpuirq
+/dev/accelirq
+/dev/compassirq
+/dev/pressureirq
+
+General Remarks MPU3050
+-----------------------
+* Valid addresses for the MPU3050 is 0x68.
+* Accelerometer must be on the secondary I2C bus for MPU3050, the
+  magnetometer must be on the primary bus and pressure sensor must
+  be on the primary bus.
+
+Programming the chip using /dev/mpu
+----------------------------------
+Programming of MPU3050 is done by first opening the /dev/mpu file and
+then performing a series of IOCTLS on the handle returned.  The IOCTL codes can
+be found in mpu.h.  Typically this is done by the mllite library in user
+space.
+
+Board and Platform Data
+-----------------------
+
+In order for the driver to work, board and platform data specific to the device
+needs to be added to the board file.  A mpu_platform_data structure must
+be created and populated and set in the i2c_board_info_structure.  For details
+of each structure member see mpu.h.  All values below are simply an example and
+should be modified for your platform.
+
+#include <linux/mpu.h>
+
+static struct mpu_platform_data mpu3050_data = {
+       .int_config  = 0x10,
+       .orientation = {  -1,  0,  0,
+                          0,  1,  0,
+                          0,  0, -1 },
+};
+
+/* accel */
+static struct ext_slave_platform_data inv_mpu_kxtf9_data = {
+       .bus         = EXT_SLAVE_BUS_SECONDARY,
+       .orientation = {  -1,  0,  0,
+                         0,  1,  0,
+                         0,  0, -1 },
+};
+/* compass */
+static struct ext_slave_platform_data inv_mpu_ak8975_data = {
+       .bus         = EXT_SLAVE_BUS_PRIMARY,
+       .orientation = { 1, 0, 0,
+                        0, 1, 0,
+                        0, 0, 1 },
+};
+
+static struct i2c_board_info __initdata panda_inv_mpu_i2c4_boardinfo[] = {
+       {
+               I2C_BOARD_INFO("mpu3050", 0x68),
+               .irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
+               .platform_data = &mpu3050_data,
+       },
+       {
+               I2C_BOARD_INFO("kxtf9", 0x0F),
+               .irq = (IH_GPIO_BASE + ACCEL_IRQ_GPIO),
+               .platform_data = &inv_mpu_kxtf9_data
+       },
+       {
+               I2C_BOARD_INFO("ak8975", 0x0E),
+               .irq = (IH_GPIO_BASE + COMPASS_IRQ_GPIO),
+               .platform_data = &inv_mpu_ak8975_data,
+       },
+};
+
+Typically the IRQ is a GPIO input pin and needs to be configured properly.  If
+in the above example GPIO 168 corresponds to IRQ 299, the following should be
+done as well:
+
+#define MPU_GPIO_IRQ 168
+
+    gpio_request(MPU_GPIO_IRQ,"MPUIRQ");
+    gpio_direction_input(MPU_GPIO_IRQ)
+
+Dynamic Debug
+=============
+
+The mpu3050 makes use of dynamic debug.  For details on how to use this
+refer to Documentation/dynamic-debug-howto.txt
diff --git a/drivers/misc/inv_mpu/accel/Kconfig b/drivers/misc/inv_mpu/accel/Kconfig
new file mode 100644 (file)
index 0000000..4e280bd
--- /dev/null
@@ -0,0 +1,133 @@
+menuconfig INV_SENSORS_ACCELEROMETERS
+       bool "Accelerometer Slave Sensors"
+       default y
+       ---help---
+         Say Y here to get to see options for device drivers for various
+         accelerometrs for integration with the MPU3050 or MPU6050 driver.
+         This option alone does not add any kernel code.
+
+         If you say N, all options in this submenu will be skipped and disabled.
+
+if INV_SENSORS_ACCELEROMETERS
+
+config MPU_SENSORS_ADXL34X
+       tristate "ADI adxl34x"
+       depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the ADI adxl345 or adxl346 accelerometers.
+         This support is for integration with the MPU3050 gyroscope device
+         driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_BMA222
+       tristate "Bosch BMA222"
+       depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the Bosch BMA222 accelerometer
+         This support is for integration with the MPU3050 gyroscope device
+         driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_BMA150
+       tristate "Bosch BMA150"
+       depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the Bosch BMA150 accelerometer
+         This support is for integration with the MPU3050 gyroscope device
+         driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_BMA250
+       tristate "Bosch BMA250"
+       depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the Bosch BMA250 accelerometer
+         This support is for integration with the MPU3050 gyroscope device
+         driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_KXSD9
+       tristate "Kionix KXSD9"
+       depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the Kionix KXSD9 accelerometer
+         This support is for integration with the MPU3050 gyroscope device
+         driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_KXTF9
+       tristate "Kionix KXTF9"
+       depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the Kionix KXFT9 accelerometer
+         This support is for integration with the MPU3050 gyroscope device
+         driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_LIS331DLH
+       tristate "ST lis331dlh"
+       depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the ST lis331dlh accelerometer
+         This support is for integration with the MPU3050 gyroscope device
+         driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_LIS3DH
+       tristate "ST lis3dh"
+       depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the ST lis3dh accelerometer
+         This support is for integration with the MPU3050 gyroscope device
+         driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_LSM303DLX_A
+       tristate "ST lsm303dlx"
+       depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the ST lsm303dlh and lsm303dlm accelerometers
+         This support is for integration with the MPU3050 gyroscope device
+         driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_MMA8450
+       tristate "Freescale mma8450"
+       depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the Freescale mma8450 accelerometer
+         This support is for integration with the MPU3050 gyroscope device
+         driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_MMA845X
+       tristate "Freescale mma8451/8452/8453"
+       depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the Freescale mma8451/8452/8453 accelerometer
+         This support is for integration with the MPU3050 gyroscope device
+         driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_MPU6050_ACCEL
+       tristate "MPU6050 built in accelerometer"
+       depends on MPU_SENSORS_MPU6050B1 || MPU_SENSORS_MPU6050A2
+       help
+         This enables support for the MPU6050 built in accelerometer.
+         This the built in support for integration with the MPU6050 gyroscope
+         device driver.  This is the only accelerometer supported with the
+         MPU6050.  Specifying another accelerometer in the board file will
+         result in runtime errors.
+
+endif
diff --git a/drivers/misc/inv_mpu/accel/Makefile b/drivers/misc/inv_mpu/accel/Makefile
new file mode 100644 (file)
index 0000000..1f0f5be
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# Accel Slaves to MPUxxxx
+#
+obj-$(CONFIG_MPU_SENSORS_ADXL34X) += inv_mpu_adxl34x.o
+inv_mpu_adxl34x-objs += adxl34x.o
+
+obj-$(CONFIG_MPU_SENSORS_BMA150) += inv_mpu_bma150.o
+inv_mpu_bma150-objs += bma150.o
+
+obj-$(CONFIG_MPU_SENSORS_KXTF9) += inv_mpu_kxtf9.o
+inv_mpu_kxtf9-objs += kxtf9.o
+
+obj-$(CONFIG_MPU_SENSORS_BMA222) += inv_mpu_bma222.o
+inv_mpu_bma222-objs += bma222.o
+
+obj-$(CONFIG_MPU_SENSORS_BMA250) += inv_mpu_bma250.o
+inv_mpu_bma250-objs += bma250.o
+
+obj-$(CONFIG_MPU_SENSORS_KXSD9) += inv_mpu_kxsd9.o
+inv_mpu_kxsd9-objs += kxsd9.o
+
+obj-$(CONFIG_MPU_SENSORS_LIS331DLH) += inv_mpu_lis331.o
+inv_mpu_lis331-objs += lis331.o
+
+obj-$(CONFIG_MPU_SENSORS_LIS3DH) += inv_mpu_lis3dh.o
+inv_mpu_lis3dh-objs += lis3dh.o
+
+obj-$(CONFIG_MPU_SENSORS_LSM303DLX_A) += inv_mpu_lsm303dlx_a.o
+inv_mpu_lsm303dlx_a-objs += lsm303dlx_a.o
+
+obj-$(CONFIG_MPU_SENSORS_MMA8450) += inv_mpu_mma8450.o
+inv_mpu_mma8450-objs += mma8450.o
+
+obj-$(CONFIG_MPU_SENSORS_MMA845X) += inv_mpu_mma845x.o
+inv_mpu_mma845x-objs += mma845x.o
+
+EXTRA_CFLAGS += -Idrivers/misc/inv_mpu
+EXTRA_CFLAGS += -D__C99_DESIGNATED_INITIALIZER
diff --git a/drivers/misc/inv_mpu/accel/adxl34x.c b/drivers/misc/inv_mpu/accel/adxl34x.c
new file mode 100644 (file)
index 0000000..f2bff8a
--- /dev/null
@@ -0,0 +1,728 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup ACCELDL
+ *  @brief      Provides the interface to setup and handle an accelerometer.
+ *
+ *  @{
+ *      @file   adxl34x.c
+ *      @brief  Accelerometer setup and handling methods for AD adxl345 and
+ *              adxl346.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+/* -------------------------------------------------------------------------- */
+
+/* registers */
+#define ADXL34X_ODR_REG                        (0x2C)
+#define ADXL34X_PWR_REG                        (0x2D)
+#define ADXL34X_DATAFORMAT_REG         (0x31)
+
+/* masks */
+#define ADXL34X_ODR_MASK               (0x0F)
+#define ADXL34X_PWR_SLEEP_MASK         (0x04)
+#define ADXL34X_PWR_MEAS_MASK          (0x08)
+#define ADXL34X_DATAFORMAT_JUSTIFY_MASK        (0x04)
+#define ADXL34X_DATAFORMAT_FSR_MASK    (0x03)
+
+/* -------------------------------------------------------------------------- */
+
+struct adxl34x_config {
+       unsigned int odr;               /** < output data rate in mHz */
+       unsigned int fsr;               /** < full scale range mg */
+       unsigned int fsr_reg_mask;      /** < register setting for fsr */
+};
+
+struct adxl34x_private_data {
+       struct adxl34x_config suspend;  /** < suspend configuration */
+       struct adxl34x_config resume;   /** < resume configuration */
+};
+
+/**
+ *  @brief Set the output data rate for the particular configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             Config to modify with new ODR.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param odr
+ *             Output data rate in units of 1/1000Hz (mHz).
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int adxl34x_set_odr(void *mlsl_handle,
+                          struct ext_slave_platform_data *pdata,
+                          struct adxl34x_config *config,
+                          int apply,
+                          long odr)
+{
+       int result = INV_SUCCESS;
+       unsigned char new_odr_mask;
+
+       /* ADXL346 (Rev. A) pages 13, 24 */
+       if (odr >= 3200000) {
+               new_odr_mask = 0x0F;
+               config->odr = 3200000;
+       } else if (odr >= 1600000) {
+               new_odr_mask = 0x0E;
+               config->odr = 1600000;
+       } else if (odr >= 800000) {
+               new_odr_mask = 0x0D;
+               config->odr = 800000;
+       } else if (odr >= 400000) {
+               new_odr_mask = 0x0C;
+               config->odr = 400000;
+       } else if (odr >= 200000) {
+               new_odr_mask = 0x0B;
+               config->odr = 200000;
+       } else if (odr >= 100000) {
+               new_odr_mask = 0x0A;
+               config->odr = 100000;
+       } else if (odr >= 50000) {
+               new_odr_mask = 0x09;
+               config->odr = 50000;
+       } else if (odr >= 25000) {
+               new_odr_mask = 0x08;
+               config->odr = 25000;
+       } else if (odr >= 12500) {
+               new_odr_mask = 0x07;
+               config->odr = 12500;
+       } else if (odr >= 6250) {
+               new_odr_mask = 0x06;
+               config->odr = 6250;
+       } else if (odr >= 3130) {
+               new_odr_mask = 0x05;
+               config->odr = 3130;
+       } else if (odr >= 1560) {
+               new_odr_mask = 0x04;
+               config->odr = 1560;
+       } else if (odr >= 780) {
+               new_odr_mask = 0x03;
+               config->odr = 780;
+       } else if (odr >= 390) {
+               new_odr_mask = 0x02;
+               config->odr = 390;
+       } else if (odr >= 200) {
+               new_odr_mask = 0x01;
+               config->odr = 200;
+       } else {
+               new_odr_mask = 0x00;
+               config->odr = 100;
+       }
+
+       if (apply) {
+               unsigned char reg_odr;
+               result = inv_serial_read(mlsl_handle, pdata->address,
+                               ADXL34X_ODR_REG, 1, &reg_odr);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               reg_odr &= ~ADXL34X_ODR_MASK;
+               reg_odr |= new_odr_mask;
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               ADXL34X_ODR_REG, reg_odr);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               MPL_LOGV("ODR: %d mHz\n", config->odr);
+       }
+       return result;
+}
+
+/**
+ *  @brief Set the full scale range of the accels
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             pointer to configuration.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param fsr
+ *             requested full scale range in milli gees (mg).
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int adxl34x_set_fsr(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct adxl34x_config *config,
+                         int apply,
+                         long fsr)
+{
+       int result = INV_SUCCESS;
+
+       if (fsr <= 2000) {
+               config->fsr_reg_mask = 0x00;
+               config->fsr = 2000;
+       } else if (fsr <= 4000) {
+               config->fsr_reg_mask = 0x01;
+               config->fsr = 4000;
+       } else if (fsr <= 8000) {
+               config->fsr_reg_mask = 0x02;
+               config->fsr = 8000;
+       } else { /* 8001 -> oo */
+               config->fsr_reg_mask = 0x03;
+               config->fsr = 16000;
+       }
+
+       if (apply) {
+               unsigned char reg_df;
+               result = inv_serial_read(mlsl_handle, pdata->address,
+                               ADXL34X_DATAFORMAT_REG, 1, &reg_df);
+               reg_df &= ~ADXL34X_DATAFORMAT_FSR_MASK;
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               ADXL34X_DATAFORMAT_REG,
+                               reg_df | config->fsr_reg_mask);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               MPL_LOGV("FSR: %d mg\n", config->fsr);
+       }
+       return result;
+}
+
+/**
+ *  @brief facility to retrieve the device configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to store the returned configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int adxl34x_get_config(void *mlsl_handle,
+                   struct ext_slave_descr *slave,
+                               struct ext_slave_platform_data *pdata,
+                               struct ext_slave_config *data)
+{
+       struct adxl34x_private_data *private_data =
+                       (struct adxl34x_private_data *)(pdata->private_data);
+
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief device configuration facility.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to the configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int adxl34x_config(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata,
+                        struct ext_slave_config *data)
+{
+       struct adxl34x_private_data *private_data =
+                       (struct adxl34x_private_data *)(pdata->private_data);
+
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return adxl34x_set_odr(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return adxl34x_set_odr(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return adxl34x_set_fsr(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return adxl34x_set_fsr(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief suspends the device to put it in its lowest power mode.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int adxl34x_suspend(void *mlsl_handle,
+                          struct ext_slave_descr *slave,
+                          struct ext_slave_platform_data *pdata)
+{
+       int result;
+
+       /*
+       struct adxl34x_config *suspend_config =
+               &((struct adxl34x_private_data *)pdata->private_data)->suspend;
+
+       result = adxl34x_set_odr(mlsl_handle, pdata, suspend_config,
+                               true, suspend_config->odr);
+       if (result) {
+       LOG_RESULT_LOCATION(result);
+       return result;
+}
+       result = adxl34x_set_fsr(mlsl_handle, pdata, suspend_config,
+                               true, suspend_config->fsr);
+       if (result) {
+       LOG_RESULT_LOCATION(result);
+       return result;
+}
+       */
+
+       /*
+         Page 25
+         When clearing the sleep bit, it is recommended that the part
+         be placed into standby mode and then set back to measurement mode
+         with a subsequent write.
+         This is done to ensure that the device is properly biased if sleep
+         mode is manually disabled; otherwise, the first few samples of data
+         after the sleep bit is cleared may have additional noise,
+         especially if the device was asleep when the bit was cleared. */
+
+       /* go in standy-by mode (suspends measurements) */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       ADXL34X_PWR_REG, ADXL34X_PWR_MEAS_MASK);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* and then in sleep */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       ADXL34X_PWR_REG,
+                       ADXL34X_PWR_MEAS_MASK | ADXL34X_PWR_SLEEP_MASK);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+/**
+ *  @brief resume the device in the proper power state given the configuration
+ *         chosen.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int adxl34x_resume(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       struct adxl34x_config *resume_config =
+               &((struct adxl34x_private_data *)pdata->private_data)->resume;
+       unsigned char reg;
+
+       /*
+         Page 25
+         When clearing the sleep bit, it is recommended that the part
+         be placed into standby mode and then set back to measurement mode
+         with a subsequent write.
+         This is done to ensure that the device is properly biased if sleep
+         mode is manually disabled; otherwise, the first few samples of data
+         after the sleep bit is cleared may have additional noise,
+         especially if the device was asleep when the bit was cleared. */
+
+       /* remove sleep, but leave in stand-by */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       ADXL34X_PWR_REG, ADXL34X_PWR_MEAS_MASK);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = adxl34x_set_odr(mlsl_handle, pdata, resume_config,
+                               true, resume_config->odr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /*
+         -> FSR
+         -> Justiy bit for Big endianess
+         -> resulution to 10 bits
+       */
+       reg = ADXL34X_DATAFORMAT_JUSTIFY_MASK;
+       reg |= resume_config->fsr_reg_mask;
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       ADXL34X_DATAFORMAT_REG, reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* go in measurement mode */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       ADXL34X_PWR_REG, 0x00);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* DATA_FORMAT: full resolution of +/-2g; data is left justified */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        0x31, reg);
+
+       return result;
+}
+
+/**
+ *  @brief one-time device driver initialization function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is loaded in the kernel.
+ *         If the driver is built-in in the kernel, this function will be
+ *         called at boot time.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int adxl34x_init(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata)
+{
+       int result;
+       long range;
+
+       struct adxl34x_private_data *private_data;
+       private_data = (struct adxl34x_private_data *)
+           kzalloc(sizeof(struct adxl34x_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+
+       result = adxl34x_set_odr(mlsl_handle, pdata, &private_data->suspend,
+                               false, 0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = adxl34x_set_odr(mlsl_handle, pdata, &private_data->resume,
+                               false, 200000);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       range = range_fixedpoint_to_long_mg(slave->range);
+       result = adxl34x_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                               false, range);
+       result = adxl34x_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                               false, range);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = adxl34x_suspend(mlsl_handle, slave, pdata);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/**
+ *  @brief one-time device driver exit function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is removed from the kernel.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int adxl34x_exit(void *mlsl_handle,
+                struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief read the sensor data from the device.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a buffer to store the data read.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int adxl34x_read(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       unsigned char *data)
+{
+       int result;
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                slave->read_reg, slave->read_len, data);
+       return result;
+}
+
+static struct ext_slave_descr adxl34x_descr = {
+       .init             = adxl34x_init,
+       .exit             = adxl34x_exit,
+       .suspend          = adxl34x_suspend,
+       .resume           = adxl34x_resume,
+       .read             = adxl34x_read,
+       .config           = adxl34x_config,
+       .get_config       = adxl34x_get_config,
+       .name             = "adxl34x",  /* 5 or 6 */
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ACCEL_ID_ADXL34X,
+       .read_reg         = 0x32,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {2, 0},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *adxl34x_get_slave_descr(void)
+{
+       return &adxl34x_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct adxl34x_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int adxl34x_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct adxl34x_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       adxl34x_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int adxl34x_mod_remove(struct i2c_client *client)
+{
+       struct adxl34x_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               adxl34x_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id adxl34x_mod_id[] = {
+       { "adxl34x", ACCEL_ID_ADXL34X },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, adxl34x_mod_id);
+
+static struct i2c_driver adxl34x_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = adxl34x_mod_probe,
+       .remove = adxl34x_mod_remove,
+       .id_table = adxl34x_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "adxl34x_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init adxl34x_mod_init(void)
+{
+       int res = i2c_add_driver(&adxl34x_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "adxl34x_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit adxl34x_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&adxl34x_mod_driver);
+}
+
+module_init(adxl34x_mod_init);
+module_exit(adxl34x_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate ADXL34X sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("adxl34x_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/accel/bma150.c b/drivers/misc/inv_mpu/accel/bma150.c
new file mode 100644 (file)
index 0000000..fd2d7b5
--- /dev/null
@@ -0,0 +1,777 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup ACCELDL
+ *  @brief      Provides the interface to setup and handle an accelerometer.
+ *
+ *  @{
+ *      @file   bma150.c
+ *      @brief  Accelerometer setup and handling methods for Bosch BMA150.
+ */
+#define DEBUG
+/* -------------------------------------------------------------------------- */
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+
+/* -------------------------------------------------------------------------- */
+/* registers */
+#define BMA150_CTRL_REG                        (0x14)
+#define BMA150_INT_REG                 (0x15)
+#define BMA150_PWR_REG                 (0x0A)
+
+/* masks */
+#define BMA150_CTRL_MASK               (0x18)
+#define BMA150_CTRL_MASK_ODR           (0xF8)
+#define BMA150_CTRL_MASK_FSR           (0xE7)
+#define BMA150_INT_MASK_WUP            (0xF8)
+#define BMA150_INT_MASK_IRQ            (0xDF)
+#define BMA150_PWR_MASK_SLEEP          (0x01)
+#define BMA150_PWR_MASK_SOFT_RESET     (0x02)
+
+/* -------------------------------------------------------------------------- */
+struct bma150_config {
+       unsigned int odr;       /** < output data rate mHz */
+       unsigned int fsr;       /** < full scale range mgees */
+       unsigned int irq_type;  /** < type of IRQ, see bma150_set_irq */
+       unsigned char ctrl_reg; /** < control register value */
+       unsigned char int_reg;  /** < interrupt control register value */
+};
+
+struct bma150_private_data {
+       struct bma150_config suspend;   /** < suspend configuration */
+       struct bma150_config resume;    /** < resume configuration */
+};
+
+/**
+ *  @brief Simply disables the IRQ since it is not usable on BMA150 devices.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *              configuration to apply to, suspend or resume
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param irq_type
+ *              the type of IRQ.  Valid values are
+ *              - MPU_SLAVE_IRQ_TYPE_NONE
+ *              - MPU_SLAVE_IRQ_TYPE_MOTION
+ *              - MPU_SLAVE_IRQ_TYPE_DATA_READY
+ *              The only supported IRQ type is MPU_SLAVE_IRQ_TYPE_NONE which
+ *              corresponds to disabling the IRQ completely.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma150_set_irq(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct bma150_config *config,
+                         int apply,
+                         long irq_type)
+{
+       int result = INV_SUCCESS;
+
+       if (irq_type != MPU_SLAVE_IRQ_TYPE_NONE)
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+
+       config->irq_type = MPU_SLAVE_IRQ_TYPE_NONE;
+       config->int_reg = 0x00;
+
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                        BMA150_CTRL_REG, config->ctrl_reg);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                        BMA150_INT_REG, config->int_reg);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       return result;
+}
+
+/**
+ *  @brief Set the output data rate for the particular configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             Config to modify with new ODR.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param odr
+ *             Output data rate in units of 1/1000Hz (mHz).
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma150_set_odr(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct bma150_config *config,
+                       int apply,
+                       long odr)
+{
+       unsigned char odr_bits = 0;
+       unsigned char wup_bits = 0;
+       int result = INV_SUCCESS;
+
+       if (odr > 100000) {
+               config->odr = 190000;
+               odr_bits = 0x03;
+       } else if (odr > 50000) {
+               config->odr = 100000;
+               odr_bits = 0x02;
+       } else if (odr > 25000) {
+               config->odr = 50000;
+               odr_bits = 0x01;
+       } else if (odr > 0) {
+               config->odr = 25000;
+               odr_bits = 0x00;
+       } else {
+               config->odr = 0;
+               wup_bits = 0x00;
+       }
+
+       config->int_reg &= BMA150_INT_MASK_WUP;
+       config->ctrl_reg &= BMA150_CTRL_MASK_ODR;
+       config->ctrl_reg |= odr_bits;
+
+       MPL_LOGV("ODR: %d\n", config->odr);
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       BMA150_CTRL_REG, config->ctrl_reg);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       BMA150_INT_REG, config->int_reg);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       return result;
+}
+
+/**
+ *  @brief Set the full scale range of the accels
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             pointer to configuration.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param fsr
+ *             requested full scale range.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma150_set_fsr(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct bma150_config *config,
+                         int apply,
+                         long fsr)
+{
+       unsigned char fsr_bits;
+       int result = INV_SUCCESS;
+
+       if (fsr <= 2048) {
+               fsr_bits = 0x00;
+               config->fsr = 2048;
+       } else if (fsr <= 4096) {
+               fsr_bits = 0x08;
+               config->fsr = 4096;
+       } else {
+               fsr_bits = 0x10;
+               config->fsr = 8192;
+       }
+
+       config->ctrl_reg &= BMA150_CTRL_MASK_FSR;
+       config->ctrl_reg |= fsr_bits;
+
+       MPL_LOGV("FSR: %d\n", config->fsr);
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA150_CTRL_REG, config->ctrl_reg);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA150_CTRL_REG, config->ctrl_reg);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       return result;
+}
+
+/**
+ *  @brief one-time device driver initialization function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is loaded in the kernel.
+ *         If the driver is built-in in the kernel, this function will be
+ *         called at boot time.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma150_init(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char reg;
+       long range;
+
+       struct bma150_private_data *private_data;
+       private_data = (struct bma150_private_data *)
+           kzalloc(sizeof(struct bma150_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       BMA150_PWR_REG, BMA150_PWR_MASK_SOFT_RESET);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(1);
+
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                BMA150_CTRL_REG, 1, &reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       private_data->resume.ctrl_reg = reg;
+       private_data->suspend.ctrl_reg = reg;
+
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                BMA150_INT_REG, 1, &reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       private_data->resume.int_reg = reg;
+       private_data->suspend.int_reg = reg;
+
+       result = bma150_set_odr(mlsl_handle, pdata, &private_data->suspend,
+                               false, 0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = bma150_set_odr(mlsl_handle, pdata, &private_data->resume,
+                               false, 200000);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       range = range_fixedpoint_to_long_mg(slave->range);
+       result = bma150_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                               false, range);
+       result = bma150_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                               false, range);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = bma150_set_irq(mlsl_handle, pdata, &private_data->suspend,
+                               false, MPU_SLAVE_IRQ_TYPE_NONE);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = bma150_set_irq(mlsl_handle, pdata, &private_data->resume,
+                               false, MPU_SLAVE_IRQ_TYPE_NONE);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      BMA150_PWR_REG, BMA150_PWR_MASK_SLEEP);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/**
+ *  @brief one-time device driver exit function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is removed from the kernel.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma150_exit(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief device configuration facility.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to the configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma150_config(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata,
+                        struct ext_slave_config *data)
+{
+       struct bma150_private_data *private_data =
+                       (struct bma150_private_data *)(pdata->private_data);
+
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return bma150_set_odr(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return bma150_set_odr(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return bma150_set_fsr(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return bma150_set_fsr(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               return bma150_set_irq(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               return bma150_set_irq(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply,
+                                     *((long *)data->data));
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief facility to retrieve the device configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to store the returned configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma150_get_config(void *mlsl_handle,
+                               struct ext_slave_descr *slave,
+                               struct ext_slave_platform_data *pdata,
+                               struct ext_slave_config *data)
+{
+       struct bma150_private_data *private_data =
+                       (struct bma150_private_data *)(pdata->private_data);
+
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.irq_type;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.irq_type;
+               break;
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief suspends the device to put it in its lowest power mode.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma150_suspend(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char ctrl_reg;
+       unsigned char int_reg;
+
+       struct bma150_private_data *private_data =
+                       (struct bma150_private_data *)(pdata->private_data);
+
+       ctrl_reg = private_data->suspend.ctrl_reg;
+       int_reg = private_data->suspend.int_reg;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       BMA150_PWR_REG, BMA150_PWR_MASK_SOFT_RESET);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(1);
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       BMA150_CTRL_REG, ctrl_reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       BMA150_INT_REG, int_reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+               BMA150_PWR_REG, BMA150_PWR_MASK_SLEEP);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/**
+ *  @brief resume the device in the proper power state given the configuration
+ *         chosen.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma150_resume(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char ctrl_reg;
+       unsigned char int_reg;
+
+       struct bma150_private_data *private_data =
+                       (struct bma150_private_data *)(pdata->private_data);
+
+       ctrl_reg = private_data->resume.ctrl_reg;
+       int_reg = private_data->resume.int_reg;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA150_PWR_REG, BMA150_PWR_MASK_SOFT_RESET);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(1);
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA150_CTRL_REG, ctrl_reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA150_INT_REG, int_reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA150_PWR_REG, 0x00);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/**
+ *  @brief read the sensor data from the device.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a buffer to store the data read.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma150_read(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata,
+                      unsigned char *data)
+{
+       return inv_serial_read(mlsl_handle, pdata->address,
+                              slave->read_reg, slave->read_len, data);
+}
+
+static struct ext_slave_descr bma150_descr = {
+       .init             = bma150_init,
+       .exit             = bma150_exit,
+       .suspend          = bma150_suspend,
+       .resume           = bma150_resume,
+       .read             = bma150_read,
+       .config           = bma150_config,
+       .get_config       = bma150_get_config,
+       .name             = "bma150",
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ACCEL_ID_BMA150,
+       .read_reg         = 0x02,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {2, 0},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *bma150_get_slave_descr(void)
+{
+       return &bma150_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Platform data for the MPU */
+struct bma150_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int bma150_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct bma150_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s,0x%x\n", __func__, devid->name,(unsigned int)client);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       bma150_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int bma150_mod_remove(struct i2c_client *client)
+{
+       struct bma150_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               bma150_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id bma150_mod_id[] = {
+       { "bma150", ACCEL_ID_BMA150 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, bma150_mod_id);
+
+static struct i2c_driver bma150_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = bma150_mod_probe,
+       .remove = bma150_mod_remove,
+       .id_table = bma150_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "bma150_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init bma150_mod_init(void)
+{
+       int res = i2c_add_driver(&bma150_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "bma150_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit bma150_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&bma150_mod_driver);
+}
+
+module_init(bma150_mod_init);
+module_exit(bma150_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate BMA150 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("bma150_mod");
+
+/**
+ *  @}
+ */
+
diff --git a/drivers/misc/inv_mpu/accel/bma222.c b/drivers/misc/inv_mpu/accel/bma222.c
new file mode 100644 (file)
index 0000000..e9fc99b
--- /dev/null
@@ -0,0 +1,654 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/*
+ *  @addtogroup ACCELDL
+ *  @brief      Provides the interface to setup and handle an accelerometer.
+ *
+ *  @{
+ *      @file   bma222.c
+ *      @brief  Accelerometer setup and handling methods for Bosch BMA222.
+ */
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+
+/* -------------------------------------------------------------------------- */
+
+#define BMA222_STATUS_REG      (0x0A)
+#define BMA222_FSR_REG         (0x0F)
+#define ADXL34X_ODR_REG                (0x10)
+#define BMA222_PWR_REG         (0x11)
+#define BMA222_SOFTRESET_REG   (0x14)
+
+#define BMA222_STATUS_RDY_MASK (0x80)
+#define BMA222_FSR_MASK                (0x0F)
+#define BMA222_ODR_MASK                (0x1F)
+#define BMA222_PWR_SLEEP_MASK  (0x80)
+#define BMA222_PWR_AWAKE_MASK  (0x00)
+#define BMA222_SOFTRESET_MASK  (0xB6)
+#define BMA222_SOFTRESET_MASK  (0xB6)
+
+/* -------------------------------------------------------------------------- */
+
+struct bma222_config {
+       unsigned int odr;               /** < output data rate in mHz */
+       unsigned int fsr;               /** < full scale range mg */
+};
+
+struct bma222_private_data {
+       struct bma222_config suspend;   /** < suspend configuration */
+       struct bma222_config resume;    /** < resume configuration */
+};
+
+
+/* -------------------------------------------------------------------------- */
+
+/**
+ *  @brief Set the output data rate for the particular configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             Config to modify with new ODR.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param odr
+ *             Output data rate in units of 1/1000Hz (mHz).
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma222_set_odr(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct bma222_config *config,
+                         int apply,
+                         long odr)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg_odr;
+
+       if (odr >= 1000000) {
+               reg_odr = 0x0F;
+               config->odr = 1000000;
+       } else if (odr >= 500000) {
+               reg_odr = 0x0E;
+               config->odr = 500000;
+       } else if (odr >= 250000) {
+               reg_odr = 0x0D;
+               config->odr = 250000;
+       } else if (odr >= 125000) {
+               reg_odr = 0x0C;
+               config->odr = 125000;
+       } else if (odr >= 62500) {
+               reg_odr = 0x0B;
+               config->odr = 62500;
+       } else if (odr >= 32000) {
+               reg_odr = 0x0A;
+               config->odr = 32000;
+       } else if (odr >= 16000) {
+               reg_odr = 0x09;
+               config->odr = 16000;
+       } else {
+               reg_odr = 0x08;
+               config->odr = 8000;
+       }
+
+       if (apply) {
+               MPL_LOGV("ODR: %d\n", config->odr);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       ADXL34X_ODR_REG, reg_odr);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       return result;
+}
+
+/**
+ *  @brief Set the full scale range of the accels
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             pointer to configuration.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param fsr
+ *             requested full scale range.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma222_set_fsr(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct bma222_config *config,
+                         int apply,
+                         long fsr)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg_fsr_mask;
+
+       if (fsr <= 2000) {
+               reg_fsr_mask = 0x03;
+               config->fsr = 2000;
+       } else if (fsr <= 4000) {
+               reg_fsr_mask = 0x05;
+               config->fsr = 4000;
+       } else if (fsr <= 8000) {
+               reg_fsr_mask = 0x08;
+               config->fsr = 8000;
+       } else { /* 8001 -> oo */
+               reg_fsr_mask = 0x0C;
+               config->fsr = 16000;
+       }
+
+       if (apply) {
+               MPL_LOGV("FSR: %d\n", config->fsr);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA222_FSR_REG, reg_fsr_mask);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       return result;
+}
+
+/**
+ *  @brief one-time device driver initialization function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is loaded in the kernel.
+ *         If the driver is built-in in the kernel, this function will be
+ *         called at boot time.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma222_init(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       int result;
+
+       struct bma222_private_data *private_data;
+       private_data = (struct bma222_private_data *)
+           kzalloc(sizeof(struct bma222_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       BMA222_SOFTRESET_REG, BMA222_SOFTRESET_MASK);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(1);
+
+       result = bma222_set_odr(mlsl_handle, pdata, &private_data->suspend,
+                               false, 0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = bma222_set_odr(mlsl_handle, pdata, &private_data->resume,
+                               false, 200000);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = bma222_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                               false, 2000);
+       result = bma222_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                               false, 2000);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA222_PWR_REG, BMA222_PWR_SLEEP_MASK);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/**
+ *  @brief one-time device driver exit function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is removed from the kernel.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma222_exit(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+
+/**
+ *  @brief facility to retrieve the device configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to store the returned configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma222_get_config(void *mlsl_handle,
+                               struct ext_slave_descr *slave,
+                               struct ext_slave_platform_data *pdata,
+                               struct ext_slave_config *data)
+{
+       struct bma222_private_data *private_data =
+                       (struct bma222_private_data *)(pdata->private_data);
+
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief device configuration facility.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to the configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma222_config(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata,
+                        struct ext_slave_config *data)
+{
+       struct bma222_private_data *private_data =
+                       (struct bma222_private_data *)(pdata->private_data);
+
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return bma222_set_odr(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return bma222_set_odr(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return bma222_set_fsr(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return bma222_set_fsr(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief suspends the device to put it in its lowest power mode.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma222_suspend(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       int result;
+       struct bma222_config *suspend_config =
+               &((struct bma222_private_data *)pdata->private_data)->suspend;
+
+       result = bma222_set_odr(mlsl_handle, pdata, suspend_config,
+                               true, suspend_config->odr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = bma222_set_fsr(mlsl_handle, pdata, suspend_config,
+                               true, suspend_config->fsr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA222_PWR_REG, BMA222_PWR_SLEEP_MASK);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       msleep(3); /* 3 ms powerup time maximum */
+       return result;
+}
+
+/**
+ *  @brief resume the device in the proper power state given the configuration
+ *         chosen.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma222_resume(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result;
+       struct bma222_config *resume_config =
+               &((struct bma222_private_data *)pdata->private_data)->resume;
+
+       /* Soft reset */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       BMA222_SOFTRESET_REG, BMA222_SOFTRESET_MASK);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(10);
+
+       result = bma222_set_odr(mlsl_handle, pdata, resume_config,
+                               true, resume_config->odr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = bma222_set_fsr(mlsl_handle, pdata, resume_config,
+                               true, resume_config->fsr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/**
+ *  @brief read the sensor data from the device.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a buffer to store the data read.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma222_read(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata,
+                      unsigned char *data)
+{
+       int result = INV_SUCCESS;
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                               BMA222_STATUS_REG, 1, data);
+       if (data[0] & BMA222_STATUS_RDY_MASK) {
+               result = inv_serial_read(mlsl_handle, pdata->address,
+                                slave->read_reg, slave->read_len, data);
+       return result;
+       } else
+               return INV_ERROR_ACCEL_DATA_NOT_READY;
+}
+
+static struct ext_slave_descr bma222_descr = {
+       .init             = bma222_init,
+       .exit             = bma222_exit,
+       .suspend          = bma222_suspend,
+       .resume           = bma222_resume,
+       .read             = bma222_read,
+       .config           = bma222_config,
+       .get_config       = bma222_get_config,
+       .name             = "bma222",
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ACCEL_ID_BMA222,
+       .read_reg         = 0x02,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {2, 0},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *bma222_get_slave_descr(void)
+{
+       return &bma222_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+
+struct bma222_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int bma222_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct bma222_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       bma222_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int bma222_mod_remove(struct i2c_client *client)
+{
+       struct bma222_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               bma222_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id bma222_mod_id[] = {
+       { "bma222", ACCEL_ID_BMA222 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, bma222_mod_id);
+
+static struct i2c_driver bma222_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = bma222_mod_probe,
+       .remove = bma222_mod_remove,
+       .id_table = bma222_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "bma222_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init bma222_mod_init(void)
+{
+       int res = i2c_add_driver(&bma222_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "bma222_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit bma222_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&bma222_mod_driver);
+}
+
+module_init(bma222_mod_init);
+module_exit(bma222_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate BMA222 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("bma222_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/accel/bma250.c b/drivers/misc/inv_mpu/accel/bma250.c
new file mode 100644 (file)
index 0000000..6a245f4
--- /dev/null
@@ -0,0 +1,787 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup ACCELDL
+ *  @brief      Provides the interface to setup and handle an accelerometer.
+ *
+ *  @{
+ *      @file   bma250.c
+ *      @brief  Accelerometer setup and handling methods for Bosch BMA250.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+
+/* -------------------------------------------------------------------------- */
+
+/* registers */
+#define BMA250_STATUS_REG      (0x0A)
+#define BMA250_FSR_REG         (0x0F)
+#define BMA250_ODR_REG         (0x10)
+#define BMA250_PWR_REG         (0x11)
+#define BMA250_SOFTRESET_REG   (0x14)
+#define BMA250_INT_TYPE_REG    (0x17)
+#define BMA250_INT_DST_REG     (0x1A)
+#define BMA250_INT_SRC_REG     (0x1E)
+
+/* masks */
+#define BMA250_STATUS_RDY_MASK (0x80)
+#define BMA250_FSR_MASK                (0x0F)
+#define BMA250_ODR_MASK                (0x1F)
+#define BMA250_PWR_SLEEP_MASK  (0x80)
+#define BMA250_PWR_AWAKE_MASK  (0x00)
+#define BMA250_SOFTRESET_MASK   (0xB6)
+#define BMA250_INT_TYPE_MASK   (0x10)
+#define BMA250_INT_DST_1_MASK  (0x01)
+#define BMA250_INT_DST_2_MASK  (0x80)
+#define BMA250_INT_SRC_MASK    (0x00)
+
+/* -------------------------------------------------------------------------- */
+
+struct bma250_config {
+       unsigned int odr;               /** < output data rate in mHz */
+       unsigned int fsr;               /** < full scale range mg */
+       unsigned char irq_type;
+};
+
+struct bma250_private_data {
+       struct bma250_config suspend;   /** < suspend configuration */
+       struct bma250_config resume;    /** < resume configuration */
+};
+
+/* -------------------------------------------------------------------------- */
+/**
+ *  @brief Sets the IRQ to fire when one of the IRQ events occur.
+ *         Threshold and duration will not be used unless the type is MOT or
+ *         NMOT.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *              configuration to apply to, suspend or resume
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param irq_type
+ *              the type of IRQ.  Valid values are
+ * - MPU_SLAVE_IRQ_TYPE_NONE
+ * - MPU_SLAVE_IRQ_TYPE_MOTION
+ * - MPU_SLAVE_IRQ_TYPE_DATA_READY
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma250_set_irq(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct bma250_config *config,
+                         int apply, long irq_type)
+{
+       int result = INV_SUCCESS;
+       unsigned char irqtype_reg;
+       unsigned char irqdst_reg;
+       unsigned char irqsrc_reg;
+
+       switch (irq_type) {
+       case MPU_SLAVE_IRQ_TYPE_DATA_READY:
+               /* data ready int. */
+               irqtype_reg = BMA250_INT_TYPE_MASK;
+               /* routed to interrupt pin 1 */
+               irqdst_reg = BMA250_INT_DST_1_MASK;
+               /* from filtered data */
+               irqsrc_reg = BMA250_INT_SRC_MASK;
+               break;
+       /* unfinished
+       case MPU_SLAVE_IRQ_TYPE_MOTION:
+               reg1 = 0x00;
+               reg2 = config->mot_int1_cfg;
+               reg3 = ;
+               break;
+       */
+       case MPU_SLAVE_IRQ_TYPE_NONE:
+               irqtype_reg = 0x00;
+               irqdst_reg = 0x00;
+               irqsrc_reg = 0x00;
+               break;
+       default:
+               return INV_ERROR_INVALID_PARAMETER;
+               break;
+       }
+
+       config->irq_type = (unsigned char)irq_type;
+
+       if (apply) {
+               /* select the type of interrupt to use */
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA250_INT_TYPE_REG, irqtype_reg);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               /* select to which interrupt pin to route it to */
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA250_INT_DST_REG, irqdst_reg);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               /* select whether the interrupt works off filtered or
+                  unfiltered data */
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA250_INT_SRC_REG, irqsrc_reg);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       return result;
+}
+
+/**
+ *  @brief Set the output data rate for the particular configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             Config to modify with new ODR.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param odr
+ *             Output data rate in units of 1/1000Hz (mHz).
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma250_set_odr(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct bma250_config *config,
+                         int apply,
+                         long odr)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg_odr;
+
+       /* Table uses bandwidth which is half the sample rate */
+       odr = odr >> 1;
+       if (odr >= 1000000) {
+               reg_odr = 0x0F;
+               config->odr = 2000000;
+       } else if (odr >= 500000) {
+               reg_odr = 0x0E;
+               config->odr = 1000000;
+       } else if (odr >= 250000) {
+               reg_odr = 0x0D;
+               config->odr = 500000;
+       } else if (odr >= 125000) {
+               reg_odr = 0x0C;
+               config->odr = 250000;
+       } else if (odr >= 62500) {
+               reg_odr = 0x0B;
+               config->odr = 125000;
+       } else if (odr >= 31250) {
+               reg_odr = 0x0A;
+               config->odr = 62500;
+       } else if (odr >= 15630) {
+               reg_odr = 0x09;
+               config->odr = 31250;
+       } else {
+               reg_odr = 0x08;
+               config->odr = 15630;
+       }
+
+       if (apply) {
+               MPL_LOGV("ODR: %d\n", config->odr);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA250_ODR_REG, reg_odr);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       return result;
+}
+
+/**
+ *  @brief Set the full scale range of the accels
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             pointer to configuration.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param fsr
+ *             requested full scale range.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma250_set_fsr(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct bma250_config *config,
+                         int apply,
+                         long fsr)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg_fsr_mask;
+
+       if (fsr <= 2000) {
+               reg_fsr_mask = 0x03;
+               config->fsr = 2000;
+       } else if (fsr <= 4000) {
+               reg_fsr_mask = 0x05;
+               config->fsr = 4000;
+       } else if (fsr <= 8000) {
+               reg_fsr_mask = 0x08;
+               config->fsr = 8000;
+       } else { /* 8001 -> oo */
+               reg_fsr_mask = 0x0C;
+               config->fsr = 16000;
+       }
+
+       if (apply) {
+               MPL_LOGV("FSR: %d\n", config->fsr);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA250_FSR_REG, reg_fsr_mask);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       return result;
+}
+
+/**
+ *  @brief one-time device driver initialization function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is loaded in the kernel.
+ *         If the driver is built-in in the kernel, this function will be
+ *         called at boot time.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma250_init(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result;
+       long range;
+
+       struct bma250_private_data *private_data;
+       private_data = kzalloc(sizeof(struct bma250_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       BMA250_SOFTRESET_REG, BMA250_SOFTRESET_MASK);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(1);
+
+       result = bma250_set_odr(mlsl_handle, pdata, &private_data->suspend,
+                               false, 0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = bma250_set_odr(mlsl_handle, pdata, &private_data->resume,
+                               false, 200000);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       range = range_fixedpoint_to_long_mg(slave->range);
+       result = bma250_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                               false, range);
+       result = bma250_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                               false, range);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = bma250_set_irq(mlsl_handle, pdata, &private_data->suspend,
+                               false, MPU_SLAVE_IRQ_TYPE_NONE);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = bma250_set_irq(mlsl_handle, pdata, &private_data->resume,
+                               false, MPU_SLAVE_IRQ_TYPE_NONE);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA250_PWR_REG, BMA250_PWR_SLEEP_MASK);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/**
+ *  @brief one-time device driver exit function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is removed from the kernel.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma250_exit(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief device configuration facility.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to the configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma250_config(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata,
+                        struct ext_slave_config *data)
+{
+       struct bma250_private_data *private_data =
+                       (struct bma250_private_data *)(pdata->private_data);
+
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return bma250_set_odr(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return bma250_set_odr(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return bma250_set_fsr(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return bma250_set_fsr(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               return bma250_set_irq(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply,
+                                     *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               return bma250_set_irq(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply,
+                                     *((long *)data->data));
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief facility to retrieve the device configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to store the returned configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma250_get_config(void *mlsl_handle,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata,
+                            struct ext_slave_config *data)
+{
+       struct bma250_private_data *private_data =
+                       (struct bma250_private_data *)(pdata->private_data);
+
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.irq_type;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.irq_type;
+               break;
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief suspends the device to put it in its lowest power mode.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma250_suspend(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       int result;
+       struct bma250_config *suspend_config =
+               &((struct bma250_private_data *)pdata->private_data)->suspend;
+
+       result = bma250_set_odr(mlsl_handle, pdata, suspend_config,
+                               true, suspend_config->odr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = bma250_set_fsr(mlsl_handle, pdata, suspend_config,
+                               true, suspend_config->fsr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = bma250_set_irq(mlsl_handle, pdata, suspend_config,
+                               true, suspend_config->irq_type);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               BMA250_PWR_REG, BMA250_PWR_SLEEP_MASK);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       msleep(3); /* 3 ms powerup time maximum */
+       return result;
+}
+
+/**
+ *  @brief resume the device in the proper power state given the configuration
+ *         chosen.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma250_resume(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result;
+       struct bma250_config *resume_config =
+               &((struct bma250_private_data *)pdata->private_data)->resume;
+
+       result = bma250_set_odr(mlsl_handle, pdata, resume_config,
+                               true, resume_config->odr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = bma250_set_fsr(mlsl_handle, pdata, resume_config,
+                               true, resume_config->fsr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = bma250_set_irq(mlsl_handle, pdata, resume_config,
+                               true, resume_config->irq_type);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       BMA250_PWR_REG, BMA250_PWR_AWAKE_MASK);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/**
+ *  @brief read the sensor data from the device.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a buffer to store the data read.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int bma250_read(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata,
+                      unsigned char *data)
+{
+       int result = INV_SUCCESS;
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                               BMA250_STATUS_REG, 1, data);
+       if (1) { /* KLP - workaroud for small data ready window */
+               result = inv_serial_read(mlsl_handle, pdata->address,
+                               slave->read_reg, slave->read_len, data);
+               return result;
+       } else
+               return INV_ERROR_ACCEL_DATA_NOT_READY;
+}
+
+static struct ext_slave_descr bma250_descr = {
+       .init             = bma250_init,
+       .exit             = bma250_exit,
+       .suspend          = bma250_suspend,
+       .resume           = bma250_resume,
+       .read             = bma250_read,
+       .config           = bma250_config,
+       .get_config       = bma250_get_config,
+       .name             = "bma250",
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ACCEL_ID_BMA250,
+       .read_reg         = 0x02,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {2, 0},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *bma250_get_slave_descr(void)
+{
+       return &bma250_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+
+/* Platform data for the MPU */
+struct bma250_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int bma250_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct bma250_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       bma250_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int bma250_mod_remove(struct i2c_client *client)
+{
+       struct bma250_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               bma250_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id bma250_mod_id[] = {
+       { "bma250", ACCEL_ID_BMA250 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, bma250_mod_id);
+
+static struct i2c_driver bma250_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = bma250_mod_probe,
+       .remove = bma250_mod_remove,
+       .id_table = bma250_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "bma250_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init bma250_mod_init(void)
+{
+       int res = i2c_add_driver(&bma250_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "bma250_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit bma250_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&bma250_mod_driver);
+}
+
+module_init(bma250_mod_init);
+module_exit(bma250_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate BMA250 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("bma250_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/accel/cma3000.c b/drivers/misc/inv_mpu/accel/cma3000.c
new file mode 100644 (file)
index 0000000..496d1f2
--- /dev/null
@@ -0,0 +1,222 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/*
+ *  @addtogroup ACCELDL
+ *  @brief      Accelerometer setup and handling methods for VTI CMA3000.
+ *
+ *  @{
+ *      @file   cma3000.c
+ *      @brief  Accelerometer setup and handling methods for VTI CMA3000
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+/* -------------------------------------------------------------------------- */
+
+static int cma3000_suspend(void *mlsl_handle,
+                          struct ext_slave_descr *slave,
+                          struct ext_slave_platform_data *pdata)
+{
+       int result;
+       /* RAM reset */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address, 0x1d, 0xcd);
+       return result;
+}
+
+static int cma3000_resume(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+
+       return INV_SUCCESS;
+}
+
+static int cma3000_read(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       unsigned char *data)
+{
+       int result;
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                slave->reg, slave->len, data);
+       return result;
+}
+
+static struct ext_slave_descr cma3000_descr = {
+       .init             = NULL,
+       .exit             = NULL,
+       .suspend          = cma3000_suspend,
+       .resume           = cma3000_resume,
+       .read             = cma3000_read,
+       .config           = NULL,
+       .get_config       = NULL,
+       .name             = "cma3000",
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ID_INVALID,
+       .read_reg         = 0x06,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {2, 0},
+       .trigger          = NULL,
+
+};
+
+static
+struct ext_slave_descr *cma3000_get_slave_descr(void)
+{
+       return &cma3000_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+
+struct cma3000_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int cma3000_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct cma3000_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       cma3000_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int cma3000_mod_remove(struct i2c_client *client)
+{
+       struct cma3000_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               cma3000_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id cma3000_mod_id[] = {
+       { "cma3000", ACCEL_ID_CMA3000 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, cma3000_mod_id);
+
+static struct i2c_driver cma3000_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = cma3000_mod_probe,
+       .remove = cma3000_mod_remove,
+       .id_table = cma3000_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "cma3000_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init cma3000_mod_init(void)
+{
+       int res = i2c_add_driver(&cma3000_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "cma3000_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit cma3000_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&cma3000_mod_driver);
+}
+
+module_init(cma3000_mod_init);
+module_exit(cma3000_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate CMA3000 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("cma3000_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/accel/kxsd9.c b/drivers/misc/inv_mpu/accel/kxsd9.c
new file mode 100644 (file)
index 0000000..5cb4eaf
--- /dev/null
@@ -0,0 +1,264 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup ACCELDL
+ *  @brief      Accelerometer setup and handling methods for Kionix KXSD9.
+ *
+ *  @{
+ *      @file   kxsd9.c
+ *      @brief  Accelerometer setup and handling methods for Kionix KXSD9.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+/* -------------------------------------------------------------------------- */
+
+static int kxsd9_suspend(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result;
+       /* CTRL_REGB: low-power standby mode */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address, 0x0d, 0x0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+/* full scale setting - register and mask */
+#define ACCEL_KIONIX_CTRL_REG      (0x0C)
+#define ACCEL_KIONIX_CTRL_MASK     (0x3)
+
+static int kxsd9_resume(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg;
+
+       /* Full Scale */
+       reg = 0x0;
+       reg &= ~ACCEL_KIONIX_CTRL_MASK;
+       reg |= 0x00;
+       if (slave->range.mantissa == 4) {               /* 4g scale = 4.9951 */
+               reg |= 0x2;
+               slave->range.fraction = 9951;
+       } else if (slave->range.mantissa == 7) {        /* 6g scale = 7.5018 */
+               reg |= 0x1;
+               slave->range.fraction = 5018;
+       } else if (slave->range.mantissa == 9) {        /* 8g scale = 9.9902 */
+               reg |= 0x0;
+               slave->range.fraction = 9902;
+       } else {
+               slave->range.mantissa = 2;              /* 2g scale = 2.5006 */
+               slave->range.fraction = 5006;
+               reg |= 0x3;
+       }
+       reg |= 0xC0;            /* 100Hz LPF */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   ACCEL_KIONIX_CTRL_REG, reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* normal operation */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address, 0x0d, 0x40);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return INV_SUCCESS;
+}
+
+static int kxsd9_read(void *mlsl_handle,
+                     struct ext_slave_descr *slave,
+                     struct ext_slave_platform_data *pdata,
+                     unsigned char *data)
+{
+       int result;
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                slave->read_reg, slave->read_len, data);
+       return result;
+}
+
+static struct ext_slave_descr kxsd9_descr = {
+       .init             = NULL,
+       .exit             = NULL,
+       .suspend          = kxsd9_suspend,
+       .resume           = kxsd9_resume,
+       .read             = kxsd9_read,
+       .config           = NULL,
+       .get_config       = NULL,
+       .name             = "kxsd9",
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ACCEL_ID_KXSD9,
+       .read_reg         = 0x00,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_BIG_ENDIAN,
+       .range            = {2, 5006},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *kxsd9_get_slave_descr(void)
+{
+       return &kxsd9_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct kxsd9_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int kxsd9_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct kxsd9_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       kxsd9_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int kxsd9_mod_remove(struct i2c_client *client)
+{
+       struct kxsd9_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               kxsd9_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id kxsd9_mod_id[] = {
+       { "kxsd9", ACCEL_ID_KXSD9 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, kxsd9_mod_id);
+
+static struct i2c_driver kxsd9_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = kxsd9_mod_probe,
+       .remove = kxsd9_mod_remove,
+       .id_table = kxsd9_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "kxsd9_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init kxsd9_mod_init(void)
+{
+       int res = i2c_add_driver(&kxsd9_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "kxsd9_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit kxsd9_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&kxsd9_mod_driver);
+}
+
+module_init(kxsd9_mod_init);
+module_exit(kxsd9_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate KXSD9 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("kxsd9_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/accel/kxtf9.c b/drivers/misc/inv_mpu/accel/kxtf9.c
new file mode 100755 (executable)
index 0000000..80776f2
--- /dev/null
@@ -0,0 +1,841 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup ACCELDL
+ *  @brief      Accelerometer setup and handling methods for Kionix KXTF9.
+ *
+ *  @{
+ *      @file   kxtf9.c
+ *      @brief  Accelerometer setup and handling methods for Kionix KXTF9.
+*/
+
+/* -------------------------------------------------------------------------- */
+
+#undef MPL_LOG_NDEBUG
+#define MPL_LOG_NDEBUG 1
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+#define KXTF9_XOUT_HPF_L                (0x00) /* 0000 0000 */
+#define KXTF9_XOUT_HPF_H                (0x01) /* 0000 0001 */
+#define KXTF9_YOUT_HPF_L                (0x02) /* 0000 0010 */
+#define KXTF9_YOUT_HPF_H                (0x03) /* 0000 0011 */
+#define KXTF9_ZOUT_HPF_L                (0x04) /* 0001 0100 */
+#define KXTF9_ZOUT_HPF_H                (0x05) /* 0001 0101 */
+#define KXTF9_XOUT_L                    (0x06) /* 0000 0110 */
+#define KXTF9_XOUT_H                    (0x07) /* 0000 0111 */
+#define KXTF9_YOUT_L                    (0x08) /* 0000 1000 */
+#define KXTF9_YOUT_H                    (0x09) /* 0000 1001 */
+#define KXTF9_ZOUT_L                    (0x0A) /* 0001 1010 */
+#define KXTF9_ZOUT_H                    (0x0B) /* 0001 1011 */
+#define KXTF9_ST_RESP                   (0x0C) /* 0000 1100 */
+#define KXTF9_WHO_AM_I                  (0x0F) /* 0000 1111 */
+#define KXTF9_TILT_POS_CUR              (0x10) /* 0001 0000 */
+#define KXTF9_TILT_POS_PRE              (0x11) /* 0001 0001 */
+#define KXTF9_INT_SRC_REG1              (0x15) /* 0001 0101 */
+#define KXTF9_INT_SRC_REG2              (0x16) /* 0001 0110 */
+#define KXTF9_STATUS_REG                (0x18) /* 0001 1000 */
+#define KXTF9_INT_REL                   (0x1A) /* 0001 1010 */
+#define KXTF9_CTRL_REG1                 (0x1B) /* 0001 1011 */
+#define KXTF9_CTRL_REG2                 (0x1C) /* 0001 1100 */
+#define KXTF9_CTRL_REG3                 (0x1D) /* 0001 1101 */
+#define KXTF9_INT_CTRL_REG1             (0x1E) /* 0001 1110 */
+#define KXTF9_INT_CTRL_REG2             (0x1F) /* 0001 1111 */
+#define KXTF9_INT_CTRL_REG3             (0x20) /* 0010 0000 */
+#define KXTF9_DATA_CTRL_REG             (0x21) /* 0010 0001 */
+#define KXTF9_TILT_TIMER                (0x28) /* 0010 1000 */
+#define KXTF9_WUF_TIMER                 (0x29) /* 0010 1001 */
+#define KXTF9_TDT_TIMER                 (0x2B) /* 0010 1011 */
+#define KXTF9_TDT_H_THRESH              (0x2C) /* 0010 1100 */
+#define KXTF9_TDT_L_THRESH              (0x2D) /* 0010 1101 */
+#define KXTF9_TDT_TAP_TIMER             (0x2E) /* 0010 1110 */
+#define KXTF9_TDT_TOTAL_TIMER           (0x2F) /* 0010 1111 */
+#define KXTF9_TDT_LATENCY_TIMER         (0x30) /* 0011 0000 */
+#define KXTF9_TDT_WINDOW_TIMER          (0x31) /* 0011 0001 */
+#define KXTF9_WUF_THRESH                (0x5A) /* 0101 1010 */
+#define KXTF9_TILT_ANGLE                (0x5C) /* 0101 1100 */
+#define KXTF9_HYST_SET                  (0x5F) /* 0101 1111 */
+
+#define KXTF9_MAX_DUR (0xFF)
+#define KXTF9_MAX_THS (0xFF)
+#define KXTF9_THS_COUNTS_P_G (32)
+
+/* -------------------------------------------------------------------------- */
+
+struct kxtf9_config {
+       unsigned long odr;      /* Output data rate mHz */
+       unsigned int fsr;       /* full scale range mg */
+       unsigned int ths;       /* Motion no-motion thseshold mg */
+       unsigned int dur;       /* Motion no-motion duration ms */
+       unsigned int irq_type;
+       unsigned char reg_ths;
+       unsigned char reg_dur;
+       unsigned char reg_odr;
+       unsigned char reg_int_cfg1;
+       unsigned char reg_int_cfg2;
+       unsigned char ctrl_reg1;
+};
+
+struct kxtf9_private_data {
+       struct kxtf9_config suspend;
+       struct kxtf9_config resume;
+};
+
+static int kxtf9_set_ths(void *mlsl_handle,
+                        struct ext_slave_platform_data *pdata,
+                        struct kxtf9_config *config, int apply, long ths)
+{
+       int result = INV_SUCCESS;
+       if ((ths * KXTF9_THS_COUNTS_P_G / 1000) > KXTF9_MAX_THS)
+               ths = (long)(KXTF9_MAX_THS * 1000) / KXTF9_THS_COUNTS_P_G;
+
+       if (ths < 0)
+               ths = 0;
+
+       config->ths = ths;
+       config->reg_ths = (unsigned char)
+           ((long)(ths * KXTF9_THS_COUNTS_P_G) / 1000);
+       MPL_LOGV("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                KXTF9_WUF_THRESH,
+                                                config->reg_ths);
+       return result;
+}
+
+static int kxtf9_set_dur(void *mlsl_handle,
+                        struct ext_slave_platform_data *pdata,
+                        struct kxtf9_config *config, int apply, long dur)
+{
+       int result = INV_SUCCESS;
+       long reg_dur = (dur * config->odr) / 1000000L;
+       config->dur = dur;
+
+       if (reg_dur > KXTF9_MAX_DUR)
+               reg_dur = KXTF9_MAX_DUR;
+
+       config->reg_dur = (unsigned char)reg_dur;
+       MPL_LOGV("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                KXTF9_WUF_TIMER,
+                                                (unsigned char)reg_dur);
+       return result;
+}
+
+/**
+ * Sets the IRQ to fire when one of the IRQ events occur.  Threshold and
+ * duration will not be used uless the type is MOT or NMOT.
+ *
+ * @param config configuration to apply to, suspend or resume
+ * @param irq_type The type of IRQ.  Valid values are
+ * - MPU_SLAVE_IRQ_TYPE_NONE
+ * - MPU_SLAVE_IRQ_TYPE_MOTION
+ * - MPU_SLAVE_IRQ_TYPE_DATA_READY
+ */
+static int kxtf9_set_irq(void *mlsl_handle,
+                        struct ext_slave_platform_data *pdata,
+                        struct kxtf9_config *config, int apply, long irq_type)
+{
+       int result = INV_SUCCESS;
+       struct kxtf9_private_data *private_data = pdata->private_data;
+
+       config->irq_type = (unsigned char)irq_type;
+       config->ctrl_reg1 &= ~0x22;
+       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               config->ctrl_reg1 |= 0x20;
+               config->reg_int_cfg1 = 0x38;
+               config->reg_int_cfg2 = 0x00;
+       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
+               config->ctrl_reg1 |= 0x02;
+               if ((unsigned long)config ==
+                   (unsigned long)&private_data->suspend)
+                       config->reg_int_cfg1 = 0x34;
+               else
+                       config->reg_int_cfg1 = 0x24;
+               config->reg_int_cfg2 = 0xE0;
+       } else {
+               config->reg_int_cfg1 = 0x00;
+               config->reg_int_cfg2 = 0x00;
+       }
+
+       if (apply) {
+               /* Must clear bit 7 before writing new configuration */
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                KXTF9_CTRL_REG1, 0x40);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                KXTF9_INT_CTRL_REG1,
+                                                config->reg_int_cfg1);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                KXTF9_INT_CTRL_REG2,
+                                                config->reg_int_cfg2);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                KXTF9_CTRL_REG1,
+                                                config->ctrl_reg1);
+       }
+       MPL_LOGV("CTRL_REG1: %lx, INT_CFG1: %lx, INT_CFG2: %lx\n",
+                (unsigned long)config->ctrl_reg1,
+                (unsigned long)config->reg_int_cfg1,
+                (unsigned long)config->reg_int_cfg2);
+
+       return result;
+}
+
+/**
+ * Set the Output data rate for the particular configuration
+ *
+ * @param config Config to modify with new ODR
+ * @param odr Output data rate in units of 1/1000Hz
+ */
+static int kxtf9_set_odr(void *mlsl_handle,
+                        struct ext_slave_platform_data *pdata,
+                        struct kxtf9_config *config, int apply, long odr)
+{
+       unsigned char bits;
+       int result = INV_SUCCESS;
+
+       /* Data sheet says there is 12.5 hz, but that seems to produce a single
+        * correct data value, thus we remove it from the table */
+       if (odr > 400000L) {
+               config->odr = 800000L;
+               bits = 0x06;
+       } else if (odr > 200000L) {
+               config->odr = 400000L;
+               bits = 0x05;
+       } else if (odr > 100000L) {
+               config->odr = 200000L;
+               bits = 0x04;
+       } else if (odr > 50000) {
+               config->odr = 100000L;
+               bits = 0x03;
+       } else if (odr > 25000) {
+               config->odr = 50000;
+               bits = 0x02;
+       } else if (odr != 0) {
+               config->odr = 25000;
+               bits = 0x01;
+       } else {
+               config->odr = 0;
+               bits = 0;
+       }
+
+       if (odr != 0)
+               config->ctrl_reg1 |= 0x80;
+       else
+               config->ctrl_reg1 &= ~0x80;
+
+       config->reg_odr = bits;
+       kxtf9_set_dur(mlsl_handle, pdata, config, apply, config->dur);
+       MPL_LOGV("ODR: %ld, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                KXTF9_DATA_CTRL_REG,
+                                                config->reg_odr);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                KXTF9_CTRL_REG1, 0x40);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                KXTF9_CTRL_REG1,
+                                                config->ctrl_reg1);
+       }
+       return result;
+}
+
+/**
+ * Set the full scale range of the accels
+ *
+ * @param config pointer to configuration
+ * @param fsr requested full scale range
+ */
+static int kxtf9_set_fsr(void *mlsl_handle,
+                        struct ext_slave_platform_data *pdata,
+                        struct kxtf9_config *config, int apply, long fsr)
+{
+       int result = INV_SUCCESS;
+
+       config->ctrl_reg1 = (config->ctrl_reg1 & 0xE7);
+       if (fsr <= 2000) {
+               config->fsr = 2000;
+               config->ctrl_reg1 |= 0x00;
+       } else if (fsr <= 4000) {
+               config->fsr = 4000;
+               config->ctrl_reg1 |= 0x08;
+       } else {
+               config->fsr = 8000;
+               config->ctrl_reg1 |= 0x10;
+       }
+
+       MPL_LOGV("FSR: %d\n", config->fsr);
+       if (apply) {
+               /* Must clear bit 7 before writing new configuration */
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                KXTF9_CTRL_REG1, 0x40);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                KXTF9_CTRL_REG1,
+                                                config->ctrl_reg1);
+       }
+       return result;
+}
+
+static int kxtf9_suspend(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char data;
+       struct kxtf9_private_data *private_data = pdata->private_data;
+
+       /* Wake up */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_CTRL_REG1, 0x40);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* INT_CTRL_REG1: */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_INT_CTRL_REG1,
+                                        private_data->suspend.reg_int_cfg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* WUF_THRESH: */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_WUF_THRESH,
+                                        private_data->suspend.reg_ths);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* DATA_CTRL_REG */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_DATA_CTRL_REG,
+                                        private_data->suspend.reg_odr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* WUF_TIMER */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_WUF_TIMER,
+                                        private_data->suspend.reg_dur);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Normal operation  */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_CTRL_REG1,
+                                        private_data->suspend.ctrl_reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                KXTF9_INT_REL, 1, &data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/* full scale setting - register and mask */
+#define ACCEL_KIONIX_CTRL_REG      (0x1b)
+#define ACCEL_KIONIX_CTRL_MASK     (0x18)
+
+static int kxtf9_resume(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       unsigned char data;
+       struct kxtf9_private_data *private_data = pdata->private_data;
+
+       /* Wake up */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_CTRL_REG1, 0x40);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* INT_CTRL_REG1: */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_INT_CTRL_REG1,
+                                        private_data->resume.reg_int_cfg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* WUF_THRESH: */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_WUF_THRESH,
+                                        private_data->resume.reg_ths);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* DATA_CTRL_REG */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_DATA_CTRL_REG,
+                                        private_data->resume.reg_odr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* WUF_TIMER */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_WUF_TIMER,
+                                        private_data->resume.reg_dur);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Normal operation  */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_CTRL_REG1,
+                                        private_data->resume.ctrl_reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                KXTF9_INT_REL, 1, &data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return INV_SUCCESS;
+}
+
+static int kxtf9_init(void *mlsl_handle,
+                     struct ext_slave_descr *slave,
+                     struct ext_slave_platform_data *pdata)
+{
+
+       struct kxtf9_private_data *private_data;
+       int result = INV_SUCCESS;
+
+       private_data = (struct kxtf9_private_data *)
+           kzalloc(sizeof(struct kxtf9_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       /* RAM reset */
+       /* Fastest Reset */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_CTRL_REG1, 0x40);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Fastest Reset */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_DATA_CTRL_REG, 0x36);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Reset */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        KXTF9_CTRL_REG3, 0xcd);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(2);
+
+       pdata->private_data = private_data;
+
+       private_data->resume.ctrl_reg1 = 0xC0;
+       private_data->suspend.ctrl_reg1 = 0x40;
+
+       result = kxtf9_set_dur(mlsl_handle, pdata, &private_data->suspend,
+                              false, 1000);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = kxtf9_set_dur(mlsl_handle, pdata, &private_data->resume,
+                              false, 2540);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = kxtf9_set_odr(mlsl_handle, pdata, &private_data->suspend,
+                              false, 50000);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = kxtf9_set_odr(mlsl_handle, pdata, &private_data->resume,
+                              false, 200000L);
+
+       result = kxtf9_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                              false, 2000);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = kxtf9_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                              false, 2000);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = kxtf9_set_ths(mlsl_handle, pdata, &private_data->suspend,
+                              false, 80);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = kxtf9_set_ths(mlsl_handle, pdata, &private_data->resume,
+                              false, 40);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = kxtf9_set_irq(mlsl_handle, pdata, &private_data->suspend,
+                              false, MPU_SLAVE_IRQ_TYPE_NONE);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = kxtf9_set_irq(mlsl_handle, pdata, &private_data->resume,
+                              false, MPU_SLAVE_IRQ_TYPE_NONE);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+static int kxtf9_exit(void *mlsl_handle,
+                     struct ext_slave_descr *slave,
+                     struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+static int kxtf9_config(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_config *data)
+{
+       struct kxtf9_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return kxtf9_set_odr(mlsl_handle, pdata,
+                                    &private_data->suspend,
+                                    data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return kxtf9_set_odr(mlsl_handle, pdata,
+                                    &private_data->resume,
+                                    data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return kxtf9_set_fsr(mlsl_handle, pdata,
+                                    &private_data->suspend,
+                                    data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return kxtf9_set_fsr(mlsl_handle, pdata,
+                                    &private_data->resume,
+                                    data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               return kxtf9_set_ths(mlsl_handle, pdata,
+                                    &private_data->suspend,
+                                    data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               return kxtf9_set_ths(mlsl_handle, pdata,
+                                    &private_data->resume,
+                                    data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               return kxtf9_set_dur(mlsl_handle, pdata,
+                                    &private_data->suspend,
+                                    data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               return kxtf9_set_dur(mlsl_handle, pdata,
+                                    &private_data->resume,
+                                    data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               return kxtf9_set_irq(mlsl_handle, pdata,
+                                    &private_data->suspend,
+                                    data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               return kxtf9_set_irq(mlsl_handle, pdata,
+                                    &private_data->resume,
+                                    data->apply, *((long *)data->data));
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static int kxtf9_get_config(void *mlsl_handle,
+                           struct ext_slave_descr *slave,
+                           struct ext_slave_platform_data *pdata,
+                           struct ext_slave_config *data)
+{
+       struct kxtf9_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.ths;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.ths;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.dur;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.dur;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.irq_type;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.irq_type;
+               break;
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static int kxtf9_read(void *mlsl_handle,
+                     struct ext_slave_descr *slave,
+                     struct ext_slave_platform_data *pdata,
+                     unsigned char *data)
+{
+       int result;
+       unsigned char reg;
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                KXTF9_INT_SRC_REG2, 1, &reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       if (!(reg & 0x10))
+               return INV_ERROR_ACCEL_DATA_NOT_READY;
+
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                slave->read_reg, slave->read_len, data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+static struct ext_slave_descr kxtf9_descr = {
+       .init             = kxtf9_init,
+       .exit             = kxtf9_exit,
+       .suspend          = kxtf9_suspend,
+       .resume           = kxtf9_resume,
+       .read             = kxtf9_read,
+       .config           = kxtf9_config,
+       .get_config       = kxtf9_get_config,
+       .name             = "kxtf9",
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ACCEL_ID_KXTF9,
+       .read_reg         = 0x06,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {2, 0},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *kxtf9_get_slave_descr(void)
+{
+       return &kxtf9_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct kxtf9_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int kxtf9_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct kxtf9_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       kxtf9_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int kxtf9_mod_remove(struct i2c_client *client)
+{
+       struct kxtf9_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               kxtf9_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id kxtf9_mod_id[] = {
+       { "kxtf9", ACCEL_ID_KXTF9 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, kxtf9_mod_id);
+
+static struct i2c_driver kxtf9_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = kxtf9_mod_probe,
+       .remove = kxtf9_mod_remove,
+       .id_table = kxtf9_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "kxtf9_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init kxtf9_mod_init(void)
+{
+       int res = i2c_add_driver(&kxtf9_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "kxtf9_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit kxtf9_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&kxtf9_mod_driver);
+}
+
+module_init(kxtf9_mod_init);
+module_exit(kxtf9_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate KXTF9 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("kxtf9_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/accel/lis331.c b/drivers/misc/inv_mpu/accel/lis331.c
new file mode 100644 (file)
index 0000000..bcbec25
--- /dev/null
@@ -0,0 +1,745 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup ACCELDL
+ *  @brief      Provides the interface to setup and handle an accelerometer.
+ *
+ *  @{
+ *      @file   lis331.c
+ *      @brief  Accelerometer setup and handling methods for ST LIS331DLH.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#undef MPL_LOG_NDEBUG
+#define MPL_LOG_NDEBUG 1
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+/* full scale setting - register & mask */
+#define LIS331DLH_CTRL_REG1         (0x20)
+#define LIS331DLH_CTRL_REG2         (0x21)
+#define LIS331DLH_CTRL_REG3         (0x22)
+#define LIS331DLH_CTRL_REG4         (0x23)
+#define LIS331DLH_CTRL_REG5         (0x24)
+#define LIS331DLH_HP_FILTER_RESET   (0x25)
+#define LIS331DLH_REFERENCE         (0x26)
+#define LIS331DLH_STATUS_REG        (0x27)
+#define LIS331DLH_OUT_X_L           (0x28)
+#define LIS331DLH_OUT_X_H           (0x29)
+#define LIS331DLH_OUT_Y_L           (0x2a)
+#define LIS331DLH_OUT_Y_H           (0x2b)
+#define LIS331DLH_OUT_Z_L           (0x2b)
+#define LIS331DLH_OUT_Z_H           (0x2d)
+
+#define LIS331DLH_INT1_CFG          (0x30)
+#define LIS331DLH_INT1_SRC          (0x31)
+#define LIS331DLH_INT1_THS          (0x32)
+#define LIS331DLH_INT1_DURATION     (0x33)
+
+#define LIS331DLH_INT2_CFG          (0x34)
+#define LIS331DLH_INT2_SRC          (0x35)
+#define LIS331DLH_INT2_THS          (0x36)
+#define LIS331DLH_INT2_DURATION     (0x37)
+
+/* CTRL_REG1 */
+#define LIS331DLH_CTRL_MASK         (0x30)
+#define LIS331DLH_SLEEP_MASK        (0x20)
+#define LIS331DLH_PWR_MODE_NORMAL   (0x20)
+
+#define LIS331DLH_MAX_DUR           (0x7F)
+
+
+/* -------------------------------------------------------------------------- */
+
+struct lis331dlh_config {
+       unsigned int odr;
+       unsigned int fsr;       /* full scale range mg */
+       unsigned int ths;       /* Motion no-motion thseshold mg */
+       unsigned int dur;       /* Motion no-motion duration ms */
+       unsigned char reg_ths;
+       unsigned char reg_dur;
+       unsigned char ctrl_reg1;
+       unsigned char irq_type;
+       unsigned char mot_int1_cfg;
+};
+
+struct lis331dlh_private_data {
+       struct lis331dlh_config suspend;
+       struct lis331dlh_config resume;
+};
+
+/* -------------------------------------------------------------------------- */
+static int lis331dlh_set_ths(void *mlsl_handle,
+                            struct ext_slave_platform_data *pdata,
+                            struct lis331dlh_config *config,
+                            int apply, long ths)
+{
+       int result = INV_SUCCESS;
+       if ((unsigned int)ths >= config->fsr)
+               ths = (long)config->fsr - 1;
+
+       if (ths < 0)
+               ths = 0;
+
+       config->ths = ths;
+       config->reg_ths = (unsigned char)(long)((ths * 128L) / (config->fsr));
+       MPL_LOGV("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS331DLH_INT1_THS,
+                                                config->reg_ths);
+       return result;
+}
+
+static int lis331dlh_set_dur(void *mlsl_handle,
+                            struct ext_slave_platform_data *pdata,
+                            struct lis331dlh_config *config,
+                            int apply, long dur)
+{
+       int result = INV_SUCCESS;
+       long reg_dur = (dur * config->odr) / 1000000L;
+       config->dur = dur;
+
+       if (reg_dur > LIS331DLH_MAX_DUR)
+               reg_dur = LIS331DLH_MAX_DUR;
+
+       config->reg_dur = (unsigned char)reg_dur;
+       MPL_LOGV("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS331DLH_INT1_DURATION,
+                                                (unsigned char)reg_dur);
+       return result;
+}
+
+/**
+ * Sets the IRQ to fire when one of the IRQ events occur.  Threshold and
+ * duration will not be used uless the type is MOT or NMOT.
+ *
+ * @param config configuration to apply to, suspend or resume
+ * @param irq_type The type of IRQ.  Valid values are
+ * - MPU_SLAVE_IRQ_TYPE_NONE
+ * - MPU_SLAVE_IRQ_TYPE_MOTION
+ * - MPU_SLAVE_IRQ_TYPE_DATA_READY
+ */
+static int lis331dlh_set_irq(void *mlsl_handle,
+                            struct ext_slave_platform_data *pdata,
+                            struct lis331dlh_config *config,
+                            int apply, long irq_type)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+
+       config->irq_type = (unsigned char)irq_type;
+       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x02;
+               reg2 = 0x00;
+       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x00;
+               reg2 = config->mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS331DLH_CTRL_REG3, reg1);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS331DLH_INT1_CFG, reg2);
+       }
+
+       return result;
+}
+
+/**
+ * Set the Output data rate for the particular configuration
+ *
+ * @param config Config to modify with new ODR
+ * @param odr Output data rate in units of 1/1000Hz
+ */
+static int lis331dlh_set_odr(void *mlsl_handle,
+                            struct ext_slave_platform_data *pdata,
+                            struct lis331dlh_config *config,
+                            int apply, long odr)
+{
+       unsigned char bits;
+       int result = INV_SUCCESS;
+
+       /* normal power modes */
+       if (odr > 400000) {
+               config->odr = 1000000;
+               bits = LIS331DLH_PWR_MODE_NORMAL | 0x18;
+       } else if (odr > 100000) {
+               config->odr = 400000;
+               bits = LIS331DLH_PWR_MODE_NORMAL | 0x10;
+       } else if (odr > 50000) {
+               config->odr = 100000;
+               bits = LIS331DLH_PWR_MODE_NORMAL | 0x08;
+       } else if (odr > 10000) {
+               config->odr = 50000;
+               bits = LIS331DLH_PWR_MODE_NORMAL | 0x00;
+       /* low power modes */
+       } else if (odr > 5000) {
+               config->odr = 10000;
+               bits = 0xC0;
+       } else if (odr > 2000) {
+               config->odr = 5000;
+               bits = 0xA0;
+       } else if (odr > 1000) {
+               config->odr = 2000;
+               bits = 0x80;
+       } else if (odr > 500) {
+               config->odr = 1000;
+               bits = 0x60;
+       } else if (odr > 0) {
+               config->odr = 500;
+               bits = 0x40;
+       } else {
+               config->odr = 0;
+               bits = 0;
+       }
+
+       config->ctrl_reg1 = bits | (config->ctrl_reg1 & 0x7);
+       lis331dlh_set_dur(mlsl_handle, pdata, config, apply, config->dur);
+       MPL_LOGV("ODR: %d, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS331DLH_CTRL_REG1,
+                                                config->ctrl_reg1);
+       return result;
+}
+
+/**
+ * Set the full scale range of the accels
+ *
+ * @param config pointer to configuration
+ * @param fsr requested full scale range
+ */
+static int lis331dlh_set_fsr(void *mlsl_handle,
+                            struct ext_slave_platform_data *pdata,
+                            struct lis331dlh_config *config,
+                            int apply, long fsr)
+{
+       unsigned char reg1 = 0x40;
+       int result = INV_SUCCESS;
+
+       if (fsr <= 2048) {
+               config->fsr = 2048;
+       } else if (fsr <= 4096) {
+               reg1 |= 0x30;
+               config->fsr = 4096;
+       } else {
+               reg1 |= 0x10;
+               config->fsr = 8192;
+       }
+
+       lis331dlh_set_ths(mlsl_handle, pdata, config, apply, config->ths);
+       MPL_LOGV("FSR: %d\n", config->fsr);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS331DLH_CTRL_REG4, reg1);
+
+       return result;
+}
+
+static int lis331dlh_suspend(void *mlsl_handle,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+       struct lis331dlh_private_data *private_data =
+               (struct lis331dlh_private_data *)(pdata->private_data);
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_CTRL_REG1,
+                                        private_data->suspend.ctrl_reg1);
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_CTRL_REG2, 0x0f);
+       reg1 = 0x40;
+       if (private_data->suspend.fsr == 8192)
+               reg1 |= 0x30;
+       else if (private_data->suspend.fsr == 4096)
+               reg1 |= 0x10;
+       /* else bits [4..5] are already zero */
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_CTRL_REG4, reg1);
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_INT1_THS,
+                                        private_data->suspend.reg_ths);
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_INT1_DURATION,
+                                        private_data->suspend.reg_dur);
+
+       if (private_data->suspend.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x02;
+               reg2 = 0x00;
+       } else if (private_data->suspend.irq_type ==
+                  MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x00;
+               reg2 = private_data->suspend.mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_CTRL_REG3, reg1);
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_INT1_CFG, reg2);
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                LIS331DLH_HP_FILTER_RESET, 1, &reg1);
+       return result;
+}
+
+static int lis331dlh_resume(void *mlsl_handle,
+                           struct ext_slave_descr *slave,
+                           struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+       struct lis331dlh_private_data *private_data =
+               (struct lis331dlh_private_data *)(pdata->private_data);
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_CTRL_REG1,
+                                        private_data->resume.ctrl_reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(6);
+
+       /* Full Scale */
+       reg1 = 0x40;
+       if (private_data->resume.fsr == 8192)
+               reg1 |= 0x30;
+       else if (private_data->resume.fsr == 4096)
+               reg1 |= 0x10;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_CTRL_REG4, reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Configure high pass filter */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_CTRL_REG2, 0x0F);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       if (private_data->resume.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x02;
+               reg2 = 0x00;
+       } else if (private_data->resume.irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x00;
+               reg2 = private_data->resume.mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_CTRL_REG3, reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_INT1_THS,
+                                        private_data->resume.reg_ths);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_INT1_DURATION,
+                                        private_data->resume.reg_dur);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS331DLH_INT1_CFG, reg2);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                LIS331DLH_HP_FILTER_RESET, 1, &reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+static int lis331dlh_read(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata,
+                         unsigned char *data)
+{
+       int result = INV_SUCCESS;
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                LIS331DLH_STATUS_REG, 1, data);
+       if (data[0] & 0x0F) {
+               result = inv_serial_read(mlsl_handle, pdata->address,
+                                        slave->read_reg, slave->read_len,
+                                        data);
+               return result;
+       } else
+               return INV_ERROR_ACCEL_DATA_NOT_READY;
+}
+
+static int lis331dlh_init(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       struct lis331dlh_private_data *private_data;
+       long range;
+       private_data = (struct lis331dlh_private_data *)
+           kzalloc(sizeof(struct lis331dlh_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+
+       private_data->resume.ctrl_reg1 = 0x37;
+       private_data->suspend.ctrl_reg1 = 0x47;
+       private_data->resume.mot_int1_cfg = 0x95;
+       private_data->suspend.mot_int1_cfg = 0x2a;
+
+       lis331dlh_set_odr(mlsl_handle, pdata, &private_data->suspend, false, 0);
+       lis331dlh_set_odr(mlsl_handle, pdata, &private_data->resume,
+                         false, 200000);
+
+       range = range_fixedpoint_to_long_mg(slave->range);
+       lis331dlh_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                       false, range);
+       lis331dlh_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                       false, range);
+
+       lis331dlh_set_ths(mlsl_handle, pdata, &private_data->suspend,
+                         false, 80);
+       lis331dlh_set_ths(mlsl_handle, pdata, &private_data->resume, false, 40);
+
+
+       lis331dlh_set_dur(mlsl_handle, pdata, &private_data->suspend,
+                         false, 1000);
+       lis331dlh_set_dur(mlsl_handle, pdata, &private_data->resume,
+                         false, 2540);
+
+       lis331dlh_set_irq(mlsl_handle, pdata, &private_data->suspend,
+                         false, MPU_SLAVE_IRQ_TYPE_NONE);
+       lis331dlh_set_irq(mlsl_handle, pdata, &private_data->resume,
+                         false, MPU_SLAVE_IRQ_TYPE_NONE);
+       return INV_SUCCESS;
+}
+
+static int lis331dlh_exit(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+static int lis331dlh_config(void *mlsl_handle,
+                           struct ext_slave_descr *slave,
+                           struct ext_slave_platform_data *pdata,
+                           struct ext_slave_config *data)
+{
+       struct lis331dlh_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return lis331dlh_set_odr(mlsl_handle, pdata,
+                                        &private_data->suspend,
+                                        data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return lis331dlh_set_odr(mlsl_handle, pdata,
+                                        &private_data->resume,
+                                        data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return lis331dlh_set_fsr(mlsl_handle, pdata,
+                                        &private_data->suspend,
+                                        data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return lis331dlh_set_fsr(mlsl_handle, pdata,
+                                        &private_data->resume,
+                                        data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               return lis331dlh_set_ths(mlsl_handle, pdata,
+                                        &private_data->suspend,
+                                        data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               return lis331dlh_set_ths(mlsl_handle, pdata,
+                                        &private_data->resume,
+                                        data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               return lis331dlh_set_dur(mlsl_handle, pdata,
+                                        &private_data->suspend,
+                                        data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               return lis331dlh_set_dur(mlsl_handle, pdata,
+                                        &private_data->resume,
+                                        data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               return lis331dlh_set_irq(mlsl_handle, pdata,
+                                        &private_data->suspend,
+                                        data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               return lis331dlh_set_irq(mlsl_handle, pdata,
+                                        &private_data->resume,
+                                        data->apply, *((long *)data->data));
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static int lis331dlh_get_config(void *mlsl_handle,
+                               struct ext_slave_descr *slave,
+                               struct ext_slave_platform_data *pdata,
+                               struct ext_slave_config *data)
+{
+       struct lis331dlh_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.ths;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.ths;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.dur;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.dur;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.irq_type;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.irq_type;
+               break;
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static struct ext_slave_descr lis331dlh_descr = {
+       .init             = lis331dlh_init,
+       .exit             = lis331dlh_exit,
+       .suspend          = lis331dlh_suspend,
+       .resume           = lis331dlh_resume,
+       .read             = lis331dlh_read,
+       .config           = lis331dlh_config,
+       .get_config       = lis331dlh_get_config,
+       .name             = "lis331dlh",
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ACCEL_ID_LIS331,
+       .read_reg         = (0x28 | 0x80), /* 0x80 for burst reads */
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_BIG_ENDIAN,
+       .range            = {2, 480},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *lis331_get_slave_descr(void)
+{
+       return &lis331dlh_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct lis331_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int lis331_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct lis331_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       lis331_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int lis331_mod_remove(struct i2c_client *client)
+{
+       struct lis331_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               lis331_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id lis331_mod_id[] = {
+       { "lis331", ACCEL_ID_LIS331 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lis331_mod_id);
+
+static struct i2c_driver lis331_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = lis331_mod_probe,
+       .remove = lis331_mod_remove,
+       .id_table = lis331_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "lis331_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init lis331_mod_init(void)
+{
+       int res = i2c_add_driver(&lis331_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "lis331_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit lis331_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&lis331_mod_driver);
+}
+
+module_init(lis331_mod_init);
+module_exit(lis331_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate LIS331 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("lis331_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/accel/lis3dh.c b/drivers/misc/inv_mpu/accel/lis3dh.c
new file mode 100644 (file)
index 0000000..27206e4
--- /dev/null
@@ -0,0 +1,728 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup ACCELDL
+ *  @brief      Provides the interface to setup and handle an accelerometer.
+ *
+ *  @{
+ *      @file   lis3dh.c
+ *      @brief  Accelerometer setup and handling methods for ST LIS3DH.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#undef MPL_LOG_NDEBUG
+#define MPL_LOG_NDEBUG 0
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+/* full scale setting - register & mask */
+#define LIS3DH_CTRL_REG1         (0x20)
+#define LIS3DH_CTRL_REG2         (0x21)
+#define LIS3DH_CTRL_REG3         (0x22)
+#define LIS3DH_CTRL_REG4         (0x23)
+#define LIS3DH_CTRL_REG5         (0x24)
+#define LIS3DH_CTRL_REG6         (0x25)
+#define LIS3DH_REFERENCE         (0x26)
+#define LIS3DH_STATUS_REG        (0x27)
+#define LIS3DH_OUT_X_L           (0x28)
+#define LIS3DH_OUT_X_H           (0x29)
+#define LIS3DH_OUT_Y_L           (0x2a)
+#define LIS3DH_OUT_Y_H           (0x2b)
+#define LIS3DH_OUT_Z_L           (0x2c)
+#define LIS3DH_OUT_Z_H           (0x2d)
+
+#define LIS3DH_INT1_CFG          (0x30)
+#define LIS3DH_INT1_SRC          (0x31)
+#define LIS3DH_INT1_THS          (0x32)
+#define LIS3DH_INT1_DURATION     (0x33)
+
+#define LIS3DH_MAX_DUR (0x7F)
+
+/* -------------------------------------------------------------------------- */
+
+struct lis3dh_config {
+       unsigned long odr;
+       unsigned int fsr;       /* full scale range mg */
+       unsigned int ths;       /* Motion no-motion thseshold mg */
+       unsigned int dur;       /* Motion no-motion duration ms */
+       unsigned char reg_ths;
+       unsigned char reg_dur;
+       unsigned char ctrl_reg1;
+       unsigned char irq_type;
+       unsigned char mot_int1_cfg;
+};
+
+struct lis3dh_private_data {
+       struct lis3dh_config suspend;
+       struct lis3dh_config resume;
+};
+
+/* -------------------------------------------------------------------------- */
+
+static int lis3dh_set_ths(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct lis3dh_config *config, int apply, long ths)
+{
+       int result = INV_SUCCESS;
+       if ((unsigned int)ths > 1000 * config->fsr)
+               ths = (long)1000 * config->fsr;
+
+       if (ths < 0)
+               ths = 0;
+
+       config->ths = ths;
+       config->reg_ths = (unsigned char)(long)((ths * 128L) / (config->fsr));
+       MPL_LOGV("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS3DH_INT1_THS,
+                                                config->reg_ths);
+       return result;
+}
+
+static int lis3dh_set_dur(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct lis3dh_config *config, int apply, long dur)
+{
+       int result = INV_SUCCESS;
+       long reg_dur = (dur * config->odr) / 1000000L;
+       config->dur = dur;
+
+       if (reg_dur > LIS3DH_MAX_DUR)
+               reg_dur = LIS3DH_MAX_DUR;
+
+       config->reg_dur = (unsigned char)reg_dur;
+       MPL_LOGV("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS3DH_INT1_DURATION,
+                                                (unsigned char)reg_dur);
+       return result;
+}
+
+/**
+ * Sets the IRQ to fire when one of the IRQ events occur.  Threshold and
+ * duration will not be used uless the type is MOT or NMOT.
+ *
+ * @param config configuration to apply to, suspend or resume
+ * @param irq_type The type of IRQ.  Valid values are
+ * - MPU_SLAVE_IRQ_TYPE_NONE
+ * - MPU_SLAVE_IRQ_TYPE_MOTION
+ * - MPU_SLAVE_IRQ_TYPE_DATA_READY
+ */
+static int lis3dh_set_irq(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct lis3dh_config *config,
+                         int apply, long irq_type)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+
+       config->irq_type = (unsigned char)irq_type;
+       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x10;
+               reg2 = 0x00;
+       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x40;
+               reg2 = config->mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS3DH_CTRL_REG3, reg1);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS3DH_INT1_CFG, reg2);
+       }
+
+       return result;
+}
+
+/**
+ * Set the Output data rate for the particular configuration
+ *
+ * @param config Config to modify with new ODR
+ * @param odr Output data rate in units of 1/1000Hz
+ */
+static int lis3dh_set_odr(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct lis3dh_config *config, int apply, long odr)
+{
+       unsigned char bits;
+       int result = INV_SUCCESS;
+
+       if (odr > 400000L) {
+               config->odr = 1250000L;
+               bits = 0x90;
+       } else if (odr > 200000L) {
+               config->odr = 400000L;
+               bits = 0x70;
+       } else if (odr > 100000L) {
+               config->odr = 200000L;
+               bits = 0x60;
+       } else if (odr > 50000) {
+               config->odr = 100000L;
+               bits = 0x50;
+       } else if (odr > 25000) {
+               config->odr = 50000;
+               bits = 0x40;
+       } else if (odr > 10000) {
+               config->odr = 25000;
+               bits = 0x30;
+       } else if (odr > 1000) {
+               config->odr = 10000;
+               bits = 0x20;
+       } else if (odr > 500) {
+               config->odr = 1000;
+               bits = 0x10;
+       } else {
+               config->odr = 0;
+               bits = 0;
+       }
+
+       config->ctrl_reg1 = bits | (config->ctrl_reg1 & 0xf);
+       lis3dh_set_dur(mlsl_handle, pdata, config, apply, config->dur);
+       MPL_LOGV("ODR: %ld, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS3DH_CTRL_REG1,
+                                                config->ctrl_reg1);
+       return result;
+}
+
+/**
+ * Set the full scale range of the accels
+ *
+ * @param config pointer to configuration
+ * @param fsr requested full scale range
+ */
+static int lis3dh_set_fsr(void *mlsl_handle,
+                         struct ext_slave_platform_data *pdata,
+                         struct lis3dh_config *config, int apply, long fsr)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg1 = 0x48;
+
+       if (fsr <= 2048) {
+               config->fsr = 2048;
+       } else if (fsr <= 4096) {
+               reg1 |= 0x10;
+               config->fsr = 4096;
+       } else if (fsr <= 8192) {
+               reg1 |= 0x20;
+               config->fsr = 8192;
+       } else {
+               reg1 |= 0x30;
+               config->fsr = 16348;
+       }
+
+       lis3dh_set_ths(mlsl_handle, pdata, config, apply, config->ths);
+       MPL_LOGV("FSR: %d\n", config->fsr);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                                LIS3DH_CTRL_REG4, reg1);
+
+       return result;
+}
+
+static int lis3dh_suspend(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+       struct lis3dh_private_data *private_data = pdata->private_data;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_CTRL_REG1,
+                                        private_data->suspend.ctrl_reg1);
+
+       reg1 = 0x48;
+       if (private_data->suspend.fsr == 16384)
+               reg1 |= 0x30;
+       else if (private_data->suspend.fsr == 8192)
+               reg1 |= 0x20;
+       else if (private_data->suspend.fsr == 4096)
+               reg1 |= 0x10;
+       else if (private_data->suspend.fsr == 2048)
+               reg1 |= 0x00;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_CTRL_REG4, reg1);
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_INT1_THS,
+                                        private_data->suspend.reg_ths);
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_INT1_DURATION,
+                                        private_data->suspend.reg_dur);
+
+       if (private_data->suspend.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x10;
+               reg2 = 0x00;
+       } else if (private_data->suspend.irq_type ==
+                  MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x40;
+               reg2 = private_data->suspend.mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_CTRL_REG3, reg1);
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_INT1_CFG, reg2);
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                LIS3DH_CTRL_REG6, 1, &reg1);
+
+       return result;
+}
+
+static int lis3dh_resume(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char reg1;
+       unsigned char reg2;
+       struct lis3dh_private_data *private_data = pdata->private_data;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_CTRL_REG1,
+                                        private_data->resume.ctrl_reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(6);
+
+       /* Full Scale */
+       reg1 = 0x48;
+       if (private_data->suspend.fsr == 16384)
+               reg1 |= 0x30;
+       else if (private_data->suspend.fsr == 8192)
+               reg1 |= 0x20;
+       else if (private_data->suspend.fsr == 4096)
+               reg1 |= 0x10;
+       else if (private_data->suspend.fsr == 2048)
+               reg1 |= 0x00;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_CTRL_REG4, reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       if (private_data->resume.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x10;
+               reg2 = 0x00;
+       } else if (private_data->resume.irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x40;
+               reg2 = private_data->resume.mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_CTRL_REG3, reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_INT1_THS,
+                                        private_data->resume.reg_ths);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_INT1_DURATION,
+                                        private_data->resume.reg_dur);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_INT1_CFG, reg2);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                LIS3DH_CTRL_REG6, 1, &reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+static int lis3dh_read(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata,
+                      unsigned char *data)
+{
+       int result = INV_SUCCESS;
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                LIS3DH_STATUS_REG, 1, data);
+       if (data[0] & 0x0F) {
+               result = inv_serial_read(mlsl_handle, pdata->address,
+                                        slave->read_reg, slave->read_len,
+                                        data);
+               return result;
+       } else
+               return INV_ERROR_ACCEL_DATA_NOT_READY;
+}
+
+static int lis3dh_init(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       int result;
+       long range;
+       struct lis3dh_private_data *private_data;
+       private_data = (struct lis3dh_private_data *)
+           kzalloc(sizeof(struct lis3dh_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+
+       private_data->resume.ctrl_reg1 = 0x67;
+       private_data->suspend.ctrl_reg1 = 0x18;
+       private_data->resume.mot_int1_cfg = 0x95;
+       private_data->suspend.mot_int1_cfg = 0x2a;
+
+       lis3dh_set_odr(mlsl_handle, pdata, &private_data->suspend, false, 0);
+       lis3dh_set_odr(mlsl_handle, pdata, &private_data->resume,
+                      false, 200000L);
+
+       range = range_fixedpoint_to_long_mg(slave->range);
+       lis3dh_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                       false, range);
+       lis3dh_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                       false, range);
+
+       lis3dh_set_ths(mlsl_handle, pdata, &private_data->suspend,
+                       false, 80);
+       lis3dh_set_ths(mlsl_handle, pdata, &private_data->resume,
+                       false, 40);
+
+       lis3dh_set_dur(mlsl_handle, pdata, &private_data->suspend,
+                       false, 1000);
+       lis3dh_set_dur(mlsl_handle, pdata, &private_data->resume,
+                       false, 2540);
+
+       lis3dh_set_irq(mlsl_handle, pdata, &private_data->suspend,
+                       false, MPU_SLAVE_IRQ_TYPE_NONE);
+       lis3dh_set_irq(mlsl_handle, pdata, &private_data->resume,
+                       false, MPU_SLAVE_IRQ_TYPE_NONE);
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        LIS3DH_CTRL_REG1, 0x07);
+       msleep(6);
+
+       return INV_SUCCESS;
+}
+
+static int lis3dh_exit(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+static int lis3dh_config(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata,
+                        struct ext_slave_config *data)
+{
+       struct lis3dh_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return lis3dh_set_odr(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return lis3dh_set_odr(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return lis3dh_set_fsr(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return lis3dh_set_fsr(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               return lis3dh_set_ths(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               return lis3dh_set_ths(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               return lis3dh_set_dur(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               return lis3dh_set_dur(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               return lis3dh_set_irq(mlsl_handle, pdata,
+                                     &private_data->suspend,
+                                     data->apply, *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               return lis3dh_set_irq(mlsl_handle, pdata,
+                                     &private_data->resume,
+                                     data->apply, *((long *)data->data));
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+       return INV_SUCCESS;
+}
+
+static int lis3dh_get_config(void *mlsl_handle,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata,
+                            struct ext_slave_config *data)
+{
+       struct lis3dh_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.ths;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.ths;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.dur;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.dur;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->suspend.irq_type;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               (*(unsigned long *)data->data) =
+                   (unsigned long)private_data->resume.irq_type;
+               break;
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static struct ext_slave_descr lis3dh_descr = {
+       .init             = lis3dh_init,
+       .exit             = lis3dh_exit,
+       .suspend          = lis3dh_suspend,
+       .resume           = lis3dh_resume,
+       .read             = lis3dh_read,
+       .config           = lis3dh_config,
+       .get_config       = lis3dh_get_config,
+       .name             = "lis3dh",
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ACCEL_ID_LIS3DH,
+       .read_reg         = 0x28 | 0x80, /* 0x80 for burst reads */
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_BIG_ENDIAN,
+       .range            = {2, 480},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *lis3dh_get_slave_descr(void)
+{
+       return &lis3dh_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct lis3dh_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int lis3dh_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct lis3dh_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       lis3dh_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int lis3dh_mod_remove(struct i2c_client *client)
+{
+       struct lis3dh_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               lis3dh_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id lis3dh_mod_id[] = {
+       { "lis3dh", ACCEL_ID_LIS3DH },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lis3dh_mod_id);
+
+static struct i2c_driver lis3dh_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = lis3dh_mod_probe,
+       .remove = lis3dh_mod_remove,
+       .id_table = lis3dh_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "lis3dh_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init lis3dh_mod_init(void)
+{
+       int res = i2c_add_driver(&lis3dh_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "lis3dh_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit lis3dh_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&lis3dh_mod_driver);
+}
+
+module_init(lis3dh_mod_init);
+module_exit(lis3dh_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate LIS3DH sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("lis3dh_mod");
+
+/*
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/accel/lsm303dlx_a.c b/drivers/misc/inv_mpu/accel/lsm303dlx_a.c
new file mode 100644 (file)
index 0000000..576282a
--- /dev/null
@@ -0,0 +1,881 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup ACCELDL
+ *  @brief      Provides the interface to setup and handle an accelerometer.
+ *
+ *  @{
+ *      @file   lsm303dlx_a.c
+ *      @brief  Accelerometer setup and handling methods for ST LSM303DLH
+ *              or LSM303DLM accel.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+/* -------------------------------------------------------------------------- */
+
+/* full scale setting - register & mask */
+#define LSM303DLx_CTRL_REG1         (0x20)
+#define LSM303DLx_CTRL_REG2         (0x21)
+#define LSM303DLx_CTRL_REG3         (0x22)
+#define LSM303DLx_CTRL_REG4         (0x23)
+#define LSM303DLx_CTRL_REG5         (0x24)
+#define LSM303DLx_HP_FILTER_RESET   (0x25)
+#define LSM303DLx_REFERENCE         (0x26)
+#define LSM303DLx_STATUS_REG        (0x27)
+#define LSM303DLx_OUT_X_L           (0x28)
+#define LSM303DLx_OUT_X_H           (0x29)
+#define LSM303DLx_OUT_Y_L           (0x2a)
+#define LSM303DLx_OUT_Y_H           (0x2b)
+#define LSM303DLx_OUT_Z_L           (0x2b)
+#define LSM303DLx_OUT_Z_H           (0x2d)
+
+#define LSM303DLx_INT1_CFG          (0x30)
+#define LSM303DLx_INT1_SRC          (0x31)
+#define LSM303DLx_INT1_THS          (0x32)
+#define LSM303DLx_INT1_DURATION     (0x33)
+
+#define LSM303DLx_INT2_CFG          (0x34)
+#define LSM303DLx_INT2_SRC          (0x35)
+#define LSM303DLx_INT2_THS          (0x36)
+#define LSM303DLx_INT2_DURATION     (0x37)
+
+#define LSM303DLx_CTRL_MASK         (0x30)
+#define LSM303DLx_SLEEP_MASK        (0x20)
+#define LSM303DLx_PWR_MODE_NORMAL   (0x20)
+
+#define LSM303DLx_MAX_DUR           (0x7F)
+
+/* -------------------------------------------------------------------------- */
+
+struct lsm303dlx_a_config {
+       unsigned int odr;
+       unsigned int fsr; /** < full scale range mg */
+       unsigned int ths; /** < Motion no-motion thseshold mg */
+       unsigned int dur; /** < Motion no-motion duration ms */
+       unsigned char reg_ths;
+       unsigned char reg_dur;
+       unsigned char ctrl_reg1;
+       unsigned char irq_type;
+       unsigned char mot_int1_cfg;
+};
+
+struct lsm303dlx_a_private_data {
+       struct lsm303dlx_a_config suspend;
+       struct lsm303dlx_a_config resume;
+};
+
+/* -------------------------------------------------------------------------- */
+
+static int lsm303dlx_a_set_ths(void *mlsl_handle,
+                              struct ext_slave_platform_data *pdata,
+                              struct lsm303dlx_a_config *config,
+                              int apply,
+                              long ths)
+{
+       int result = INV_SUCCESS;
+       if ((unsigned int) ths >= config->fsr)
+               ths = (long) config->fsr - 1;
+
+       if (ths < 0)
+               ths = 0;
+
+       config->ths = ths;
+       config->reg_ths = (unsigned char)(long)((ths * 128L) / (config->fsr));
+       MPL_LOGV("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       LSM303DLx_INT1_THS,
+                                       config->reg_ths);
+       return result;
+}
+
+static int lsm303dlx_a_set_dur(void *mlsl_handle,
+                              struct ext_slave_platform_data *pdata,
+                              struct lsm303dlx_a_config *config,
+                              int apply,
+                              long dur)
+{
+       int result = INV_SUCCESS;
+       long reg_dur = (dur * config->odr) / 1000000L;
+       config->dur = dur;
+
+       if (reg_dur > LSM303DLx_MAX_DUR)
+               reg_dur = LSM303DLx_MAX_DUR;
+
+       config->reg_dur = (unsigned char) reg_dur;
+       MPL_LOGV("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       LSM303DLx_INT1_DURATION,
+                                       (unsigned char)reg_dur);
+       return result;
+}
+
+/**
+ * Sets the IRQ to fire when one of the IRQ events occur.  Threshold and
+ * duration will not be used uless the type is MOT or NMOT.
+ *
+ * @param config configuration to apply to, suspend or resume
+ * @param irq_type The type of IRQ.  Valid values are
+ * - MPU_SLAVE_IRQ_TYPE_NONE
+ * - MPU_SLAVE_IRQ_TYPE_MOTION
+ * - MPU_SLAVE_IRQ_TYPE_DATA_READY
+ */
+static int lsm303dlx_a_set_irq(void *mlsl_handle,
+                              struct ext_slave_platform_data *pdata,
+                              struct lsm303dlx_a_config *config,
+                              int apply,
+                              long irq_type)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+
+       config->irq_type = (unsigned char)irq_type;
+       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x02;
+               reg2 = 0x00;
+       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x00;
+               reg2 = config->mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       LSM303DLx_CTRL_REG3, reg1);
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       LSM303DLx_INT1_CFG, reg2);
+       }
+
+       return result;
+}
+
+/**
+ *  @brief Set the output data rate for the particular configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             Config to modify with new ODR.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param odr
+ *             Output data rate in units of 1/1000Hz (mHz).
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int lsm303dlx_a_set_odr(void *mlsl_handle,
+                              struct ext_slave_platform_data *pdata,
+                              struct lsm303dlx_a_config *config,
+                              int apply,
+                              long odr)
+{
+       unsigned char bits;
+       int result = INV_SUCCESS;
+
+       /* normal power modes */
+       if (odr > 400000) {
+               config->odr = 1000000;
+               bits = LSM303DLx_PWR_MODE_NORMAL | 0x18;
+       } else if (odr > 100000) {
+               config->odr = 400000;
+               bits = LSM303DLx_PWR_MODE_NORMAL | 0x10;
+       } else if (odr > 50000) {
+               config->odr = 100000;
+               bits = LSM303DLx_PWR_MODE_NORMAL | 0x08;
+       } else if (odr > 10000) {
+               config->odr = 50000;
+               bits = LSM303DLx_PWR_MODE_NORMAL | 0x00;
+       /* low power modes */
+       } else if (odr > 5000) {
+               config->odr = 10000;
+               bits = 0xC0;
+       } else if (odr > 2000) {
+               config->odr = 5000;
+               bits = 0xA0;
+       } else if (odr > 1000) {
+               config->odr = 2000;
+               bits = 0x80;
+       } else if (odr > 500) {
+               config->odr = 1000;
+               bits = 0x60;
+       } else if (odr > 0) {
+               config->odr = 500;
+               bits = 0x40;
+       } else {
+               config->odr = 0;
+               bits = 0;
+       }
+
+       config->ctrl_reg1 = bits | (config->ctrl_reg1 & 0x7);
+       lsm303dlx_a_set_dur(mlsl_handle, pdata, config, apply, config->dur);
+       MPL_LOGV("ODR: %d, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       LSM303DLx_CTRL_REG1,
+                                       config->ctrl_reg1);
+       return result;
+}
+
+/**
+ *  @brief Set the full scale range of the accels
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             pointer to configuration.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param fsr
+ *             requested full scale range.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int lsm303dlx_a_set_fsr(void *mlsl_handle,
+                              struct ext_slave_platform_data *pdata,
+                              struct lsm303dlx_a_config *config,
+                              int apply,
+                              long fsr)
+{
+       unsigned char reg1 = 0x40;
+       int result = INV_SUCCESS;
+
+       if (fsr <= 2048) {
+               config->fsr = 2048;
+       } else if (fsr <= 4096) {
+               reg1 |= 0x30;
+               config->fsr = 4096;
+       } else {
+               reg1 |= 0x10;
+               config->fsr = 8192;
+       }
+
+       lsm303dlx_a_set_ths(mlsl_handle, pdata,
+                       config, apply, config->ths);
+       MPL_LOGV("FSR: %d\n", config->fsr);
+       if (apply)
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       LSM303DLx_CTRL_REG4, reg1);
+
+       return result;
+}
+
+/**
+ *  @brief suspends the device to put it in its lowest power mode.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int lsm303dlx_a_suspend(void *mlsl_handle,
+                              struct ext_slave_descr *slave,
+                              struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+       struct lsm303dlx_a_private_data *private_data =
+               (struct lsm303dlx_a_private_data *)(pdata->private_data);
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_CTRL_REG1,
+                                      private_data->suspend.ctrl_reg1);
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_CTRL_REG2, 0x0f);
+       reg1 = 0x40;
+       if (private_data->suspend.fsr == 8192)
+               reg1 |= 0x30;
+       else if (private_data->suspend.fsr == 4096)
+               reg1 |= 0x10;
+       /* else bits [4..5] are already zero */
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_CTRL_REG4, reg1);
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_INT1_THS,
+                                      private_data->suspend.reg_ths);
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_INT1_DURATION,
+                                      private_data->suspend.reg_dur);
+
+       if (private_data->suspend.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x02;
+               reg2 = 0x00;
+       } else if (private_data->suspend.irq_type ==
+                  MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x00;
+               reg2 = private_data->suspend.mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_CTRL_REG3, reg1);
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_INT1_CFG, reg2);
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                               LSM303DLx_HP_FILTER_RESET, 1, &reg1);
+       return result;
+}
+
+/**
+ *  @brief resume the device in the proper power state given the configuration
+ *         chosen.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int lsm303dlx_a_resume(void *mlsl_handle,
+                             struct ext_slave_descr *slave,
+                             struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+       struct lsm303dlx_a_private_data *private_data =
+               (struct lsm303dlx_a_private_data *)(pdata->private_data);
+
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_CTRL_REG1,
+                                      private_data->resume.ctrl_reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(6);
+
+       /* Full Scale */
+       reg1 = 0x40;
+       if (private_data->resume.fsr == 8192)
+               reg1 |= 0x30;
+       else if (private_data->resume.fsr == 4096)
+               reg1 |= 0x10;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_CTRL_REG4, reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Configure high pass filter */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_CTRL_REG2, 0x0F);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       if (private_data->resume.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x02;
+               reg2 = 0x00;
+       } else if (private_data->resume.irq_type ==
+                  MPU_SLAVE_IRQ_TYPE_MOTION) {
+               reg1 = 0x00;
+               reg2 = private_data->resume.mot_int1_cfg;
+       } else {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_CTRL_REG3, reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_INT1_THS,
+                                      private_data->resume.reg_ths);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_INT1_DURATION,
+                                      private_data->resume.reg_dur);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      LSM303DLx_INT1_CFG, reg2);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                               LSM303DLx_HP_FILTER_RESET, 1, &reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+/**
+ *  @brief read the sensor data from the device.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a buffer to store the data read.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int lsm303dlx_a_read(void *mlsl_handle,
+                           struct ext_slave_descr *slave,
+                           struct ext_slave_platform_data *pdata,
+                           unsigned char *data)
+{
+       int result = INV_SUCCESS;
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                               LSM303DLx_STATUS_REG, 1, data);
+       if (data[0] & 0x0F) {
+               result = inv_serial_read(mlsl_handle, pdata->address,
+                                       slave->read_reg, slave->read_len, data);
+       return result;
+       } else
+               return INV_ERROR_ACCEL_DATA_NOT_READY;
+}
+
+/**
+ *  @brief one-time device driver initialization function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is loaded in the kernel.
+ *         If the driver is built-in in the kernel, this function will be
+ *         called at boot time.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int lsm303dlx_a_init(void *mlsl_handle,
+                           struct ext_slave_descr *slave,
+                           struct ext_slave_platform_data *pdata)
+{
+       long range;
+       struct lsm303dlx_a_private_data *private_data;
+       private_data = (struct lsm303dlx_a_private_data *)
+           kzalloc(sizeof(struct lsm303dlx_a_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+
+       private_data->resume.ctrl_reg1 = 0x37;
+       private_data->suspend.ctrl_reg1 = 0x47;
+       private_data->resume.mot_int1_cfg = 0x95;
+       private_data->suspend.mot_int1_cfg = 0x2a;
+
+       lsm303dlx_a_set_odr(mlsl_handle, pdata, &private_data->suspend,
+                       false, 0);
+       lsm303dlx_a_set_odr(mlsl_handle, pdata, &private_data->resume,
+                       false, 200000);
+
+       range = range_fixedpoint_to_long_mg(slave->range);
+       lsm303dlx_a_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                       false, range);
+       lsm303dlx_a_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                       false, range);
+
+       lsm303dlx_a_set_ths(mlsl_handle, pdata, &private_data->suspend,
+                       false, 80);
+       lsm303dlx_a_set_ths(mlsl_handle, pdata, &private_data->resume,
+                       false, 40);
+
+       lsm303dlx_a_set_dur(mlsl_handle, pdata, &private_data->suspend,
+                       false, 1000);
+       lsm303dlx_a_set_dur(mlsl_handle, pdata, &private_data->resume,
+                       false, 2540);
+
+       lsm303dlx_a_set_irq(mlsl_handle, pdata, &private_data->suspend,
+                       false, MPU_SLAVE_IRQ_TYPE_NONE);
+       lsm303dlx_a_set_irq(mlsl_handle, pdata, &private_data->resume,
+                       false, MPU_SLAVE_IRQ_TYPE_NONE);
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief one-time device driver exit function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is removed from the kernel.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int lsm303dlx_a_exit(void *mlsl_handle,
+                           struct ext_slave_descr *slave,
+                           struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief device configuration facility.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to the configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int lsm303dlx_a_config(void *mlsl_handle,
+                             struct ext_slave_descr *slave,
+                             struct ext_slave_platform_data *pdata,
+                             struct ext_slave_config *data)
+{
+       struct lsm303dlx_a_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return lsm303dlx_a_set_odr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return lsm303dlx_a_set_odr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return lsm303dlx_a_set_fsr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return lsm303dlx_a_set_fsr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               return lsm303dlx_a_set_ths(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               return lsm303dlx_a_set_ths(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               return lsm303dlx_a_set_dur(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               return lsm303dlx_a_set_dur(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               return lsm303dlx_a_set_irq(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               return lsm303dlx_a_set_irq(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief facility to retrieve the device configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to store the returned configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int lsm303dlx_a_get_config(void *mlsl_handle,
+                                 struct ext_slave_descr *slave,
+                                 struct ext_slave_platform_data *pdata,
+                                 struct ext_slave_config *data)
+{
+       struct lsm303dlx_a_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.ths;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.ths;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.dur;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.dur;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.irq_type;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.irq_type;
+               break;
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static struct ext_slave_descr lsm303dlx_a_descr = {
+       .init             = lsm303dlx_a_init,
+       .exit             = lsm303dlx_a_exit,
+       .suspend          = lsm303dlx_a_suspend,
+       .resume           = lsm303dlx_a_resume,
+       .read             = lsm303dlx_a_read,
+       .config           = lsm303dlx_a_config,
+       .get_config       = lsm303dlx_a_get_config,
+       .name             = "lsm303dlx_a",
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ACCEL_ID_LSM303DLX,
+       .read_reg         = (0x28 | 0x80), /* 0x80 for burst reads */
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_BIG_ENDIAN,
+       .range            = {2, 480},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *lsm303dlx_a_get_slave_descr(void)
+{
+       return &lsm303dlx_a_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct lsm303dlx_a_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int lsm303dlx_a_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct lsm303dlx_a_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       lsm303dlx_a_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int lsm303dlx_a_mod_remove(struct i2c_client *client)
+{
+       struct lsm303dlx_a_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               lsm303dlx_a_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id lsm303dlx_a_mod_id[] = {
+       { "lsm303dlx", ACCEL_ID_LSM303DLX },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, lsm303dlx_a_mod_id);
+
+static struct i2c_driver lsm303dlx_a_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = lsm303dlx_a_mod_probe,
+       .remove = lsm303dlx_a_mod_remove,
+       .id_table = lsm303dlx_a_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "lsm303dlx_a_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init lsm303dlx_a_mod_init(void)
+{
+       int res = i2c_add_driver(&lsm303dlx_a_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "lsm303dlx_a_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit lsm303dlx_a_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&lsm303dlx_a_mod_driver);
+}
+
+module_init(lsm303dlx_a_mod_init);
+module_exit(lsm303dlx_a_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate LSM303DLX_A sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("lsm303dlx_a_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/accel/mma8450.c b/drivers/misc/inv_mpu/accel/mma8450.c
new file mode 100644 (file)
index 0000000..f698ee9
--- /dev/null
@@ -0,0 +1,804 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup ACCELDL
+ *  @brief      Provides the interface to setup and handle an accelerometer.
+ *
+ *  @{
+ *      @file   mma8450.c
+ *      @brief  Accelerometer setup and handling methods for Freescale MMA8450.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+/* full scale setting - register & mask */
+#define ACCEL_MMA8450_XYZ_DATA_CFG     (0x16)
+
+#define ACCEL_MMA8450_CTRL_REG1                (0x38)
+#define ACCEL_MMA8450_CTRL_REG2     (0x39)
+#define ACCEL_MMA8450_CTRL_REG4                (0x3B)
+#define ACCEL_MMA8450_CTRL_REG5                (0x3C)
+
+#define ACCEL_MMA8450_CTRL_REG         (0x38)
+#define ACCEL_MMA8450_CTRL_MASK                (0x03)
+
+#define ACCEL_MMA8450_SLEEP_MASK       (0x03)
+
+/* -------------------------------------------------------------------------- */
+
+struct mma8450_config {
+       unsigned int odr;
+       unsigned int fsr;       /** < full scale range mg */
+       unsigned int ths;       /** < Motion no-motion thseshold mg */
+       unsigned int dur;       /** < Motion no-motion duration ms */
+       unsigned char reg_ths;
+       unsigned char reg_dur;
+       unsigned char ctrl_reg1;
+       unsigned char irq_type;
+       unsigned char mot_int1_cfg;
+};
+
+struct mma8450_private_data {
+       struct mma8450_config suspend;
+       struct mma8450_config resume;
+};
+
+
+/* -------------------------------------------------------------------------- */
+
+static int mma8450_set_ths(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct mma8450_config *config,
+                       int apply,
+                       long ths)
+{
+       return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+static int mma8450_set_dur(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct mma8450_config *config,
+                       int apply,
+                       long dur)
+{
+       return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+/**
+ *  @brief Sets the IRQ to fire when one of the IRQ events occur.
+ *         Threshold and duration will not be used unless the type is MOT or
+ *         NMOT.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *              configuration to apply to, suspend or resume
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param irq_type
+ *              the type of IRQ.  Valid values are
+ *              - MPU_SLAVE_IRQ_TYPE_NONE
+ *              - MPU_SLAVE_IRQ_TYPE_MOTION
+ *              - MPU_SLAVE_IRQ_TYPE_DATA_READY
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma8450_set_irq(void *mlsl_handle,
+               struct ext_slave_platform_data *pdata,
+               struct mma8450_config *config,
+               int apply,
+               long irq_type)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+       unsigned char reg3;
+
+       config->irq_type = (unsigned char)irq_type;
+       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x01;
+               reg2 = 0x01;
+               reg3 = 0x07;
+       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_NONE) {
+               reg1 = 0x00;
+               reg2 = 0x00;
+               reg3 = 0x00;
+       } else {
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       }
+
+       if (apply) {
+               /* XYZ_DATA_CFG: event flag enabled on Z axis */
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       ACCEL_MMA8450_XYZ_DATA_CFG, reg3);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       ACCEL_MMA8450_CTRL_REG4, reg1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       ACCEL_MMA8450_CTRL_REG5, reg2);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       return result;
+}
+
+/**
+ *  @brief Set the output data rate for the particular configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             Config to modify with new ODR.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param odr
+ *             Output data rate in units of 1/1000Hz (mHz).
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma8450_set_odr(void *mlsl_handle,
+               struct ext_slave_platform_data *pdata,
+               struct mma8450_config *config,
+               int apply,
+               long odr)
+{
+       unsigned char bits;
+       int result = INV_SUCCESS;
+
+       if (odr > 200000) {
+               config->odr = 400000;
+               bits = 0x00;
+       } else if (odr > 100000) {
+               config->odr = 200000;
+               bits = 0x04;
+       } else if (odr > 50000) {
+               config->odr = 100000;
+               bits = 0x08;
+       } else if (odr > 25000) {
+               config->odr = 50000;
+               bits = 0x0C;
+       } else if (odr > 12500) {
+               config->odr = 25000;
+               bits = 0x40; /* Sleep -> Auto wake mode */
+       } else if (odr > 1563) {
+               config->odr = 12500;
+               bits = 0x10;
+       } else if (odr > 0) {
+               config->odr = 1563;
+               bits = 0x14;
+       } else {
+               config->ctrl_reg1 = 0; /* Set FS1.FS2 to Standby */
+               config->odr = 0;
+               bits = 0;
+       }
+
+       config->ctrl_reg1 = bits | (config->ctrl_reg1 & 0x3);
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               ACCEL_MMA8450_CTRL_REG1, 0);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               ACCEL_MMA8450_CTRL_REG1, config->ctrl_reg1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               MPL_LOGV("ODR: %d mHz, 0x%02x\n",
+                       config->odr, (int)config->ctrl_reg1);
+       }
+       return result;
+}
+
+/**
+ *  @brief Set the full scale range of the accels
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             pointer to configuration.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param fsr
+ *             requested full scale range.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma8450_set_fsr(void *mlsl_handle,
+               struct ext_slave_platform_data *pdata,
+               struct mma8450_config *config,
+               int apply,
+               long fsr)
+{
+       unsigned char bits;
+       int result = INV_SUCCESS;
+
+       if (fsr <= 2000) {
+               bits = 0x01;
+               config->fsr = 2000;
+       } else if (fsr <= 4000) {
+               bits = 0x02;
+               config->fsr = 4000;
+       } else {
+               bits = 0x03;
+               config->fsr = 8000;
+       }
+
+       config->ctrl_reg1 = bits | (config->ctrl_reg1 & 0xFC);
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               ACCEL_MMA8450_CTRL_REG1, config->ctrl_reg1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               MPL_LOGV("FSR: %d mg\n", config->fsr);
+       }
+       return result;
+}
+
+/**
+ *  @brief suspends the device to put it in its lowest power mode.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma8450_suspend(void *mlsl_handle,
+                   struct ext_slave_descr *slave,
+                   struct ext_slave_platform_data *pdata)
+{
+       int result;
+       struct mma8450_private_data *private_data = pdata->private_data;
+
+       if (private_data->suspend.fsr == 4000)
+               slave->range.mantissa = 4;
+       else if (private_data->suspend.fsr == 8000)
+               slave->range.mantissa = 8;
+       else
+               slave->range.mantissa = 2;
+       slave->range.fraction = 0;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       ACCEL_MMA8450_CTRL_REG1, 0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       if (private_data->suspend.ctrl_reg1) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               ACCEL_MMA8450_CTRL_REG1,
+                               private_data->suspend.ctrl_reg1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       result = mma8450_set_irq(mlsl_handle, pdata,
+                               &private_data->suspend,
+                               true, private_data->suspend.irq_type);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+/**
+ *  @brief resume the device in the proper power state given the configuration
+ *         chosen.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma8450_resume(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       struct mma8450_private_data *private_data = pdata->private_data;
+
+       /* Full Scale */
+       if (private_data->resume.fsr == 4000)
+               slave->range.mantissa = 4;
+       else if (private_data->resume.fsr == 8000)
+               slave->range.mantissa = 8;
+       else
+               slave->range.mantissa = 2;
+       slave->range.fraction = 0;
+
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       ACCEL_MMA8450_CTRL_REG1, 0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       if (private_data->resume.ctrl_reg1) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               ACCEL_MMA8450_CTRL_REG1,
+                               private_data->resume.ctrl_reg1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       result = mma8450_set_irq(mlsl_handle, pdata,
+                       &private_data->resume,
+                       true, private_data->resume.irq_type);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/**
+ *  @brief read the sensor data from the device.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a buffer to store the data read.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma8450_read(void *mlsl_handle,
+                struct ext_slave_descr *slave,
+                struct ext_slave_platform_data *pdata, unsigned char *data)
+{
+       int result;
+       unsigned char local_data[4];    /* Status register + 3 bytes data */
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                               0x00, sizeof(local_data), local_data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       memcpy(data, &local_data[1], (slave->read_len) - 1);
+
+       MPL_LOGV("Data Not Ready: %02x %02x %02x %02x\n",
+                local_data[0], local_data[1],
+                local_data[2], local_data[3]);
+
+       return result;
+}
+
+/**
+ *  @brief one-time device driver initialization function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is loaded in the kernel.
+ *         If the driver is built-in in the kernel, this function will be
+ *         called at boot time.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma8450_init(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       struct mma8450_private_data *private_data;
+       private_data = (struct mma8450_private_data *)
+           kzalloc(sizeof(struct mma8450_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+
+       mma8450_set_odr(mlsl_handle, pdata, &private_data->suspend,
+                       false, 0);
+       mma8450_set_odr(mlsl_handle, pdata, &private_data->resume,
+                       false, 200000);
+       mma8450_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                       false, 2000);
+       mma8450_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                       false, 2000);
+       mma8450_set_irq(mlsl_handle, pdata, &private_data->suspend,
+                       false,
+                       MPU_SLAVE_IRQ_TYPE_NONE);
+       mma8450_set_irq(mlsl_handle, pdata, &private_data->resume,
+                       false,
+                       MPU_SLAVE_IRQ_TYPE_NONE);
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief one-time device driver exit function.
+ *         If the driver is built as a kernel module, this function will be
+ *         called when the module is removed from the kernel.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma8450_exit(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief device configuration facility.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to the configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma8450_config(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_config *data)
+{
+       struct mma8450_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return mma8450_set_odr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return mma8450_set_odr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return mma8450_set_fsr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return mma8450_set_fsr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               return mma8450_set_ths(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               return mma8450_set_ths(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               return mma8450_set_dur(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               return mma8450_set_dur(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               return mma8450_set_irq(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               return mma8450_set_irq(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+/**
+ *  @brief facility to retrieve the device configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a pointer to store the returned configuration data structure.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma8450_get_config(void *mlsl_handle,
+                               struct ext_slave_descr *slave,
+                               struct ext_slave_platform_data *pdata,
+                               struct ext_slave_config *data)
+{
+       struct mma8450_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.ths;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.ths;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.dur;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.dur;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.irq_type;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.irq_type;
+               break;
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static struct ext_slave_descr mma8450_descr = {
+       .init             = mma8450_init,
+       .exit             = mma8450_exit,
+       .suspend          = mma8450_suspend,
+       .resume           = mma8450_resume,
+       .read             = mma8450_read,
+       .config           = mma8450_config,
+       .get_config       = mma8450_get_config,
+       .name             = "mma8450",
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ACCEL_ID_MMA8450,
+       .read_reg         = 0x00,
+       .read_len         = 4,
+       .endian           = EXT_SLAVE_FS8_BIG_ENDIAN,
+       .range            = {2, 0},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *mma8450_get_slave_descr(void)
+{
+       return &mma8450_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct mma8450_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int mma8450_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct mma8450_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       mma8450_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int mma8450_mod_remove(struct i2c_client *client)
+{
+       struct mma8450_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               mma8450_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id mma8450_mod_id[] = {
+       { "mma8450", ACCEL_ID_MMA8450 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, mma8450_mod_id);
+
+static struct i2c_driver mma8450_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = mma8450_mod_probe,
+       .remove = mma8450_mod_remove,
+       .id_table = mma8450_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "mma8450_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init mma8450_mod_init(void)
+{
+       int res = i2c_add_driver(&mma8450_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "mma8450_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit mma8450_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&mma8450_mod_driver);
+}
+
+module_init(mma8450_mod_init);
+module_exit(mma8450_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate MMA8450 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("mma8450_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/accel/mma845x.c b/drivers/misc/inv_mpu/accel/mma845x.c
new file mode 100644 (file)
index 0000000..5f62b22
--- /dev/null
@@ -0,0 +1,713 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup ACCELDL
+ *  @brief      Provides the interface to setup and handle an accelerometer.
+ *
+ *  @{
+ *      @file   mma845x.c
+ *      @brief  Accelerometer setup and handling methods for Freescale MMA845X
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+#define ACCEL_MMA845X_XYZ_DATA_CFG     (0x0E)
+#define ACCEL_MMA845X_CTRL_REG1      (0x2A)
+#define ACCEL_MMA845X_CTRL_REG4                (0x2D)
+#define ACCEL_MMA845X_CTRL_REG5                (0x2E)
+
+#define ACCEL_MMA845X_SLEEP_MASK     (0x01)
+
+/* full scale setting - register & mask */
+#define ACCEL_MMA845X_CFG_REG       (0x0E)
+#define ACCEL_MMA845X_CTRL_MASK     (0x03)
+
+/* -------------------------------------------------------------------------- */
+
+struct mma845x_config {
+       unsigned int odr;
+       unsigned int fsr;               /** < full scale range mg */
+       unsigned int ths;               /** < Motion no-motion thseshold mg */
+       unsigned int dur;               /** < Motion no-motion duration ms */
+       unsigned char reg_ths;
+       unsigned char reg_dur;
+       unsigned char ctrl_reg1;
+       unsigned char irq_type;
+       unsigned char mot_int1_cfg;
+};
+
+struct mma845x_private_data {
+       struct mma845x_config suspend;
+       struct mma845x_config resume;
+};
+
+/* -------------------------------------------------------------------------- */
+
+static int mma845x_set_ths(void *mlsl_handle,
+               struct ext_slave_platform_data *pdata,
+               struct mma845x_config *config,
+               int apply,
+               long ths)
+{
+       return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+static int mma845x_set_dur(void *mlsl_handle,
+               struct ext_slave_platform_data *pdata,
+               struct mma845x_config *config,
+               int apply,
+               long dur)
+{
+       return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+}
+
+/**
+ *  @brief Sets the IRQ to fire when one of the IRQ events occur.
+ *         Threshold and duration will not be used unless the type is MOT or
+ *         NMOT.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *              configuration to apply to, suspend or resume
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param irq_type
+ *              the type of IRQ.  Valid values are
+ *              - MPU_SLAVE_IRQ_TYPE_NONE
+ *              - MPU_SLAVE_IRQ_TYPE_MOTION
+ *              - MPU_SLAVE_IRQ_TYPE_DATA_READY
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma845x_set_irq(void *mlsl_handle,
+               struct ext_slave_platform_data *pdata,
+               struct mma845x_config *config,
+               int apply,
+               long irq_type)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg1;
+       unsigned char reg2;
+
+       config->irq_type = (unsigned char)irq_type;
+       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
+               reg1 = 0x01;
+               reg2 = 0x01;
+       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_NONE) {
+               reg1 = 0x00;
+               reg2 = 0x00;
+       } else {
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       }
+
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       ACCEL_MMA845X_CTRL_REG4, reg1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       ACCEL_MMA845X_CTRL_REG5, reg2);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       return result;
+}
+
+/**
+ *  @brief Set the output data rate for the particular configuration.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             Config to modify with new ODR.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param odr
+ *             Output data rate in units of 1/1000Hz (mHz).
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma845x_set_odr(void *mlsl_handle,
+                       struct ext_slave_platform_data *pdata,
+                       struct mma845x_config *config,
+                       int apply,
+                       long odr)
+{
+       unsigned char bits;
+       int result = INV_SUCCESS;
+
+       if (odr > 400000) {
+               config->odr = 800000;
+               bits = 0x01;
+       } else if (odr > 200000) {
+               config->odr = 400000;
+               bits = 0x09;
+       } else if (odr > 100000) {
+               config->odr = 200000;
+               bits = 0x11;
+       } else if (odr > 50000) {
+               config->odr = 100000;
+               bits = 0x19;
+       } else if (odr > 12500) {
+               config->odr = 50000;
+               bits = 0x21;
+       } else if (odr > 6250) {
+               config->odr = 12500;
+               bits = 0x29;
+       } else if (odr > 1560) {
+               config->odr = 6250;
+               bits = 0x31;
+       } else if (odr > 0) {
+               config->odr = 1560;
+               bits = 0x39;
+       } else {
+               config->ctrl_reg1 = 0; /* Set FS1.FS2 to Standby */
+               config->odr = 0;
+               bits = 0;
+       }
+
+       config->ctrl_reg1 = bits;
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               ACCEL_MMA845X_CTRL_REG1,
+                               config->ctrl_reg1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               MPL_LOGV("ODR: %d mHz, 0x%02x\n", config->odr,
+                        (int)config->ctrl_reg1);
+       }
+       return result;
+}
+
+/**
+ *  @brief Set the full scale range of the accels
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param config
+ *             pointer to configuration.
+ *  @param apply
+ *             whether to apply immediately or save the settings to be applied
+ *             at the next resume.
+ *  @param fsr
+ *             requested full scale range.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma845x_set_fsr(void *mlsl_handle,
+               struct ext_slave_platform_data *pdata,
+               struct mma845x_config *config,
+               int apply,
+               long fsr)
+{
+       unsigned char bits;
+       int result = INV_SUCCESS;
+
+       if (fsr <= 2000) {
+               bits = 0x00;
+               config->fsr = 2000;
+       } else if (fsr <= 4000) {
+               bits = 0x01;
+               config->fsr = 4000;
+       } else {
+               bits = 0x02;
+               config->fsr = 8000;
+       }
+
+       if (apply) {
+               result = inv_serial_single_write(mlsl_handle, pdata->address,
+                               ACCEL_MMA845X_XYZ_DATA_CFG,
+                               bits);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               MPL_LOGV("FSR: %d mg\n", config->fsr);
+       }
+       return result;
+}
+
+/**
+ *  @brief suspends the device to put it in its lowest power mode.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma845x_suspend(void *mlsl_handle,
+                   struct ext_slave_descr *slave,
+                   struct ext_slave_platform_data *pdata)
+{
+       int result;
+       struct mma845x_private_data *private_data = pdata->private_data;
+
+       /* Full Scale */
+       if (private_data->suspend.fsr == 4000)
+               slave->range.mantissa = 4;
+       else if (private_data->suspend.fsr == 8000)
+               slave->range.mantissa = 8;
+       else
+               slave->range.mantissa = 2;
+
+       slave->range.fraction = 0;
+
+       result = mma845x_set_fsr(mlsl_handle, pdata,
+                               &private_data->suspend,
+                               true, private_data->suspend.fsr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                       ACCEL_MMA845X_CTRL_REG1,
+                                       private_data->suspend.ctrl_reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/**
+ *  @brief resume the device in the proper power state given the configuration
+ *         chosen.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma845x_resume(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       struct mma845x_private_data *private_data = pdata->private_data;
+
+       /* Full Scale */
+       if (private_data->resume.fsr == 4000)
+               slave->range.mantissa = 4;
+       else if (private_data->resume.fsr == 8000)
+               slave->range.mantissa = 8;
+       else
+               slave->range.mantissa = 2;
+
+       slave->range.fraction = 0;
+
+       result = mma845x_set_fsr(mlsl_handle, pdata,
+                       &private_data->resume,
+                       true, private_data->resume.fsr);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                       ACCEL_MMA845X_CTRL_REG1,
+                       private_data->resume.ctrl_reg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+/**
+ *  @brief read the sensor data from the device.
+ *
+ *  @param mlsl_handle
+ *             the handle to the serial channel the device is connected to.
+ *  @param slave
+ *             a pointer to the slave descriptor data structure.
+ *  @param pdata
+ *             a pointer to the slave platform data.
+ *  @param data
+ *             a buffer to store the data read.
+ *
+ *  @return INV_SUCCESS if successful or a non-zero error code.
+ */
+static int mma845x_read(void *mlsl_handle,
+                struct ext_slave_descr *slave,
+                struct ext_slave_platform_data *pdata, unsigned char *data)
+{
+       int result;
+       unsigned char local_data[7];    /* Status register + 6 bytes data */
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                slave->read_reg, sizeof(local_data),
+                                local_data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       memcpy(data, &local_data[1], slave->read_len);
+       return result;
+}
+
+static int mma845x_init(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       long range;
+       struct mma845x_private_data *private_data;
+       private_data = (struct mma845x_private_data *)
+           kzalloc(sizeof(struct mma845x_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+
+       mma845x_set_odr(mlsl_handle, pdata, &private_data->suspend,
+                       false, 0);
+       mma845x_set_odr(mlsl_handle, pdata, &private_data->resume,
+                       false, 200000);
+
+       range = range_fixedpoint_to_long_mg(slave->range);
+       mma845x_set_fsr(mlsl_handle, pdata, &private_data->suspend,
+                       false, range);
+       mma845x_set_fsr(mlsl_handle, pdata, &private_data->resume,
+                       false, range);
+
+       mma845x_set_irq(mlsl_handle, pdata, &private_data->suspend,
+                       false, MPU_SLAVE_IRQ_TYPE_NONE);
+       mma845x_set_irq(mlsl_handle, pdata, &private_data->resume,
+                       false, MPU_SLAVE_IRQ_TYPE_NONE);
+       return INV_SUCCESS;
+}
+
+static int mma845x_exit(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+static int mma845x_config(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_config *data)
+{
+       struct mma845x_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               return mma845x_set_odr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               return mma845x_set_odr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               return mma845x_set_fsr(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               return mma845x_set_fsr(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               return mma845x_set_ths(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               return mma845x_set_ths(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               return mma845x_set_dur(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               return mma845x_set_dur(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               return mma845x_set_irq(mlsl_handle, pdata,
+                                       &private_data->suspend,
+                                       data->apply,
+                                       *((long *)data->data));
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               return mma845x_set_irq(mlsl_handle, pdata,
+                                       &private_data->resume,
+                                       data->apply,
+                                       *((long *)data->data));
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static int mma845x_get_config(void *mlsl_handle,
+                               struct ext_slave_descr *slave,
+                               struct ext_slave_platform_data *pdata,
+                               struct ext_slave_config *data)
+{
+       struct mma845x_private_data *private_data = pdata->private_data;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.odr;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.odr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.fsr;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_THS:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.ths;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.ths;
+               break;
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.dur;
+               break;
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.dur;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->suspend.irq_type;
+               break;
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+               (*(unsigned long *)data->data) =
+                       (unsigned long) private_data->resume.irq_type;
+               break;
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static struct ext_slave_descr mma845x_descr = {
+       .init             = mma845x_init,
+       .exit             = mma845x_exit,
+       .suspend          = mma845x_suspend,
+       .resume           = mma845x_resume,
+       .read             = mma845x_read,
+       .config           = mma845x_config,
+       .get_config       = mma845x_get_config,
+       .name             = "mma845x",
+       .type             = EXT_SLAVE_TYPE_ACCEL,
+       .id               = ACCEL_ID_MMA845X,
+       .read_reg         = 0x00,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_FS16_BIG_ENDIAN,
+       .range            = {2, 0},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *mma845x_get_slave_descr(void)
+{
+       return &mma845x_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct mma845x_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int mma845x_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct mma845x_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       mma845x_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int mma845x_mod_remove(struct i2c_client *client)
+{
+       struct mma845x_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               mma845x_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id mma845x_mod_id[] = {
+       { "mma845x", ACCEL_ID_MMA845X },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, mma845x_mod_id);
+
+static struct i2c_driver mma845x_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = mma845x_mod_probe,
+       .remove = mma845x_mod_remove,
+       .id_table = mma845x_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "mma845x_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init mma845x_mod_init(void)
+{
+       int res = i2c_add_driver(&mma845x_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "mma845x_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit mma845x_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&mma845x_mod_driver);
+}
+
+module_init(mma845x_mod_init);
+module_exit(mma845x_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate MMA845X sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("mma845x_mod");
+
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/accel/mpu6050.h b/drivers/misc/inv_mpu/accel/mpu6050.h
new file mode 100644 (file)
index 0000000..c347bcb
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+
+#ifndef __MPU6050_H__
+#define __MPU6050_H__
+
+#include <linux/mpu.h>
+
+struct ext_slave_descr *mpu6050_get_slave_descr(void);
+
+#endif
diff --git a/drivers/misc/inv_mpu/compass/Kconfig b/drivers/misc/inv_mpu/compass/Kconfig
new file mode 100644 (file)
index 0000000..6c4c13a
--- /dev/null
@@ -0,0 +1,121 @@
+menuconfig INV_SENSORS_COMPASS
+       bool "Compass Slave Sensors"
+       default y
+       ---help---
+         Say Y here to get to see options for device drivers for various
+         compasses. This option alone does not add any kernel code.
+
+         If you say N, all options in this submenu will be skipped and disabled.
+
+if INV_SENSORS_COMPASS
+
+config MPU_SENSORS_AK8975
+       tristate "AKM ak8975"
+       help
+         This enables support for the AKM ak8975 compass
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_AK8972
+       tristate "AKM ak8972"
+       help
+         This enables support for the AKM ak8972 compass
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_MMC314X
+       tristate "MEMSIC mmc314x"
+       help
+         This enables support for the MEMSIC mmc314x compass
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_AMI30X
+       tristate "Aichi Steel ami30X"
+       help
+         This enables support for the Aichi Steel ami304/ami305 compass
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_AMI306
+       tristate "Aichi Steel ami306"
+       help
+         This enables support for the Aichi Steel ami306 compass
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_HMC5883
+       tristate "Honeywell hmc5883"
+       help
+         This enables support for the Honeywell hmc5883 compass
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_LSM303DLX_M
+       tristate "ST lsm303dlx"
+       help
+         This enables support for the ST lsm303dlh and lsm303dlm compasses
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_MMC314XMS
+       tristate "MEMSIC mmc314xMS"
+       help
+         This enables support for the MEMSIC mmc314xMS compass
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_YAS529
+       tristate "Yamaha yas529"
+       depends on INPUT_YAS_MAGNETOMETER
+       help
+         This enables support for the Yamaha yas529 compass
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_YAS530
+       tristate "Yamaha yas530"
+       help
+         This enables support for the Yamaha yas530 compass
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_HSCDTD002B
+       tristate "Alps hscdtd002b"
+       help
+         This enables support for the Alps hscdtd002b compass
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+config MPU_SENSORS_HSCDTD004A
+       tristate "Alps hscdtd004a"
+       help
+         This enables support for the Alps hscdtd004a compass
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+         device driver.  Only one compass can be registered at a time.
+         Specifying more that one compass in the board file will result
+         in runtime errors.
+
+endif
diff --git a/drivers/misc/inv_mpu/compass/Makefile b/drivers/misc/inv_mpu/compass/Makefile
new file mode 100644 (file)
index 0000000..aa8aa6a
--- /dev/null
@@ -0,0 +1,38 @@
+#
+# Compass Slaves MPUxxxx
+#
+obj-$(CONFIG_MPU_SENSORS_AMI30X) += inv_mpu_ami30x.o
+inv_mpu_ami30x-objs += ami30x.o
+
+obj-$(CONFIG_MPU_SENSORS_AMI306) += inv_mpu_ami306.o
+inv_mpu_ami306-objs += ami306.o
+
+obj-$(CONFIG_MPU_SENSORS_HMC5883) += inv_mpu_hmc5883.o
+inv_mpu_hmc5883-objs +=        hmc5883.o
+
+obj-$(CONFIG_MPU_SENSORS_LSM303DLX_M) += inv_mpu_lsm303dlx_m.o
+inv_mpu_lsm303dlx_m-objs +=    lsm303dlx_m.o
+
+obj-$(CONFIG_MPU_SENSORS_MMC314X) += inv_mpu_mmc314x.o
+inv_mpu_mmc314x-objs +=        mmc314x.o
+
+obj-$(CONFIG_MPU_SENSORS_YAS529) += inv_mpu_yas529.o
+inv_mpu_yas529-objs += yas529-kernel.o
+
+obj-$(CONFIG_MPU_SENSORS_YAS530) += inv_mpu_yas530.o
+inv_mpu_yas530-objs += yas530.o
+
+obj-$(CONFIG_MPU_SENSORS_HSCDTD002B) += inv_mpu_hscdtd002b.o
+inv_mpu_hscdtd002b-objs +=     hscdtd002b.o
+
+obj-$(CONFIG_MPU_SENSORS_HSCDTD004A) += inv_mpu_hscdtd004a.o
+inv_mpu_hscdtd004a-objs +=     hscdtd004a.o
+
+obj-$(CONFIG_MPU_SENSORS_AK8975) += inv_mpu_ak8975.o
+inv_mpu_ak8975-objs += ak8975.o
+
+obj-$(CONFIG_MPU_SENSORS_AK8972) += inv_mpu_ak8972.o
+inv_mpu_ak8972-objs += ak8972.o
+
+EXTRA_CFLAGS += -Idrivers/misc/inv_mpu
+EXTRA_CFLAGS += -D__C99_DESIGNATED_INITIALIZER
diff --git a/drivers/misc/inv_mpu/compass/ak8972.c b/drivers/misc/inv_mpu/compass/ak8972.c
new file mode 100644 (file)
index 0000000..7eb15b4
--- /dev/null
@@ -0,0 +1,499 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup COMPASSDL
+ *
+ *  @{
+ *      @file   ak8972.c
+ *      @brief  Magnetometer setup and handling methods for the AKM AK8972 compass device.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/* -------------------------------------------------------------------------- */
+#define AK8972_REG_ST1  (0x02)
+#define AK8972_REG_HXL  (0x03)
+#define AK8972_REG_ST2  (0x09)
+
+#define AK8972_REG_CNTL (0x0A)
+#define AK8972_REG_ASAX (0x10)
+#define AK8972_REG_ASAY (0x11)
+#define AK8972_REG_ASAZ (0x12)
+
+#define AK8972_CNTL_MODE_POWER_DOWN         (0x00)
+#define AK8972_CNTL_MODE_SINGLE_MEASUREMENT (0x01)
+#define AK8972_CNTL_MODE_FUSE_ROM_ACCESS    (0x0f)
+
+/* -------------------------------------------------------------------------- */
+struct ak8972_config {
+       char asa[COMPASS_NUM_AXES];     /* axis sensitivity adjustment */
+};
+
+struct ak8972_private_data {
+       struct ak8972_config init;
+};
+
+/* -------------------------------------------------------------------------- */
+static int ak8972_init(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char serial_data[COMPASS_NUM_AXES];
+
+       struct ak8972_private_data *private_data;
+       private_data = (struct ak8972_private_data *)
+           kzalloc(sizeof(struct ak8972_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        AK8972_REG_CNTL,
+                                        AK8972_CNTL_MODE_POWER_DOWN);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Wait at least 100us */
+       udelay(100);
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        AK8972_REG_CNTL,
+                                        AK8972_CNTL_MODE_FUSE_ROM_ACCESS);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Wait at least 200us */
+       udelay(200);
+
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AK8972_REG_ASAX,
+                                COMPASS_NUM_AXES, serial_data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       pdata->private_data = private_data;
+
+       private_data->init.asa[0] = serial_data[0];
+       private_data->init.asa[1] = serial_data[1];
+       private_data->init.asa[2] = serial_data[2];
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        AK8972_REG_CNTL,
+                                        AK8972_CNTL_MODE_POWER_DOWN);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       udelay(100);
+       return INV_SUCCESS;
+}
+
+static int ak8972_exit(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+static int ak8972_suspend(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   AK8972_REG_CNTL,
+                                   AK8972_CNTL_MODE_POWER_DOWN);
+       msleep(1);              /* wait at least 100us */
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+static int ak8972_resume(void *mlsl_handle,
+                 struct ext_slave_descr *slave,
+                 struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   AK8972_REG_CNTL,
+                                   AK8972_CNTL_MODE_SINGLE_MEASUREMENT);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+static int ak8972_read(void *mlsl_handle,
+               struct ext_slave_descr *slave,
+               struct ext_slave_platform_data *pdata, unsigned char *data)
+{
+       unsigned char regs[8];
+       unsigned char *stat = &regs[0];
+       unsigned char *stat2 = &regs[7];
+       int result = INV_SUCCESS;
+       int status = INV_SUCCESS;
+
+       result =
+           inv_serial_read(mlsl_handle, pdata->address, AK8972_REG_ST1,
+                           8, regs);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Always return the data and the status registers */
+       memcpy(data, &regs[1], 6);
+       data[6] = regs[0];
+       data[7] = regs[7];
+
+       /*
+        * ST : data ready -
+        * Measurement has been completed and data is ready to be read.
+        */
+       if (*stat & 0x01)
+               status = INV_SUCCESS;
+
+       /*
+        * ST2 : data error -
+        * occurs when data read is started outside of a readable period;
+        * data read would not be correct.
+        * Valid in continuous measurement mode only.
+        * In single measurement mode this error should not occour but we
+        * stil account for it and return an error, since the data would be
+        * corrupted.
+        * DERR bit is self-clearing when ST2 register is read.
+        */
+       if (*stat2 & 0x04)
+               status = INV_ERROR_COMPASS_DATA_ERROR;
+       /*
+        * ST2 : overflow -
+        * the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
+        * This is likely to happen in presence of an external magnetic
+        * disturbance; it indicates, the sensor data is incorrect and should
+        * be ignored.
+        * An error is returned.
+        * HOFL bit clears when a new measurement starts.
+        */
+       if (*stat2 & 0x08)
+               status = INV_ERROR_COMPASS_DATA_OVERFLOW;
+       /*
+        * ST : overrun -
+        * the previous sample was not fetched and lost.
+        * Valid in continuous measurement mode only.
+        * In single measurement mode this error should not occour and we
+        * don't consider this condition an error.
+        * DOR bit is self-clearing when ST2 or any meas. data register is
+        * read.
+        */
+       if (*stat & 0x02) {
+               /* status = INV_ERROR_COMPASS_DATA_UNDERFLOW; */
+               status = INV_SUCCESS;
+       }
+
+       /*
+        * trigger next measurement if:
+        *    - stat is non zero;
+        *    - if stat is zero and stat2 is non zero.
+        * Won't trigger if data is not ready and there was no error.
+        */
+       if (*stat != 0x00 || *stat2 != 0x00) {
+               result = inv_serial_single_write(
+                   mlsl_handle, pdata->address,
+                   AK8972_REG_CNTL, AK8972_CNTL_MODE_SINGLE_MEASUREMENT);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       return status;
+}
+
+static int ak8972_config(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata,
+                        struct ext_slave_config *data)
+{
+       int result;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_WRITE_REGISTERS:
+               result = inv_serial_write(mlsl_handle, pdata->address,
+                                         data->len,
+                                         (unsigned char *)data->data);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               break;
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+       case MPU_SLAVE_CONFIG_MOT_THS:
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static int ak8972_get_config(void *mlsl_handle,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata,
+                            struct ext_slave_config *data)
+{
+       struct ak8972_private_data *private_data = pdata->private_data;
+       int result;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_READ_REGISTERS:
+               {
+                       unsigned char *serial_data =
+                           (unsigned char *)data->data;
+                       result =
+                           inv_serial_read(mlsl_handle, pdata->address,
+                                           serial_data[0], data->len - 1,
+                                           &serial_data[1]);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       break;
+               }
+       case MPU_SLAVE_READ_SCALE:
+               {
+                       unsigned char *serial_data =
+                           (unsigned char *)data->data;
+                       serial_data[0] = private_data->init.asa[0];
+                       serial_data[1] = private_data->init.asa[1];
+                       serial_data[2] = private_data->init.asa[2];
+                       result = INV_SUCCESS;
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       break;
+               }
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) = 0;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) = 8000;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+       case MPU_SLAVE_CONFIG_MOT_THS:
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static struct ext_slave_read_trigger ak8972_read_trigger = {
+       /*.reg              = */ 0x0A,
+       /*.value            = */ 0x01
+};
+
+static struct ext_slave_descr ak8972_descr = {
+       .init             = ak8972_init,
+       .exit             = ak8972_exit,
+       .suspend          = ak8972_suspend,
+       .resume           = ak8972_resume,
+       .read             = ak8972_read,
+       .config           = ak8972_config,
+       .get_config       = ak8972_get_config,
+       .name             = "ak8972",
+       .type             = EXT_SLAVE_TYPE_COMPASS,
+       .id               = COMPASS_ID_AK8972,
+       .read_reg         = 0x01,
+       .read_len         = 9,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {39321, 6000},
+       .trigger          = &ak8972_read_trigger,
+};
+
+static
+struct ext_slave_descr *ak8972_get_slave_descr(void)
+{
+       return &ak8972_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct ak8972_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int ak8972_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct ak8972_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       ak8972_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int ak8972_mod_remove(struct i2c_client *client)
+{
+       struct ak8972_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               ak8972_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id ak8972_mod_id[] = {
+       { "ak8972", COMPASS_ID_AK8972 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ak8972_mod_id);
+
+static struct i2c_driver ak8972_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = ak8972_mod_probe,
+       .remove = ak8972_mod_remove,
+       .id_table = ak8972_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "ak8972_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init ak8972_mod_init(void)
+{
+       int res = i2c_add_driver(&ak8972_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "ak8972_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit ak8972_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&ak8972_mod_driver);
+}
+
+module_init(ak8972_mod_init);
+module_exit(ak8972_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate AK8972 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ak8972_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/compass/ak8975.c b/drivers/misc/inv_mpu/compass/ak8975.c
new file mode 100755 (executable)
index 0000000..9a67d7c
--- /dev/null
@@ -0,0 +1,501 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup COMPASSDL
+ *
+ *  @{
+ *      @file   ak8975.c
+ *      @brief  Magnetometer setup and handling methods for the AKM AK8975,
+ *              AKM AK8975B, and AKM AK8975C compass devices.
+ */
+
+/* -------------------------------------------------------------------------- */
+#define DEBUG
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/* -------------------------------------------------------------------------- */
+#define AK8975_REG_ST1  (0x02)
+#define AK8975_REG_HXL  (0x03)
+#define AK8975_REG_ST2  (0x09)
+
+#define AK8975_REG_CNTL (0x0A)
+#define AK8975_REG_ASAX (0x10)
+#define AK8975_REG_ASAY (0x11)
+#define AK8975_REG_ASAZ (0x12)
+
+#define AK8975_CNTL_MODE_POWER_DOWN         (0x00)
+#define AK8975_CNTL_MODE_SINGLE_MEASUREMENT (0x01)
+#define AK8975_CNTL_MODE_FUSE_ROM_ACCESS    (0x0f)
+
+/* -------------------------------------------------------------------------- */
+struct ak8975_config {
+       char asa[COMPASS_NUM_AXES];     /* axis sensitivity adjustment */
+};
+
+struct ak8975_private_data {
+       struct ak8975_config init;
+};
+
+/* -------------------------------------------------------------------------- */
+static int ak8975_init(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char serial_data[COMPASS_NUM_AXES];
+
+       struct ak8975_private_data *private_data;
+       private_data = (struct ak8975_private_data *)
+           kzalloc(sizeof(struct ak8975_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+#if 0
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        AK8975_REG_CNTL,
+                                        AK8975_CNTL_MODE_POWER_DOWN);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Wait at least 100us */
+       udelay(100);
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        AK8975_REG_CNTL,
+                                        AK8975_CNTL_MODE_FUSE_ROM_ACCESS);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+#endif
+       /* Wait at least 200us */
+       udelay(200);
+
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AK8975_REG_ASAX,
+                                COMPASS_NUM_AXES, serial_data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       pdata->private_data = private_data;
+
+       private_data->init.asa[0] = serial_data[0];
+       private_data->init.asa[1] = serial_data[1];
+       private_data->init.asa[2] = serial_data[2];
+#if 0
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        AK8975_REG_CNTL,
+                                        AK8975_CNTL_MODE_POWER_DOWN);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+#endif
+       udelay(100);
+       return INV_SUCCESS;
+}
+
+static int ak8975_exit(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+static int ak8975_suspend(void *mlsl_handle,
+                  struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   AK8975_REG_CNTL,
+                                   AK8975_CNTL_MODE_POWER_DOWN);
+       msleep(1);              /* wait at least 100us */
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+static int ak8975_resume(void *mlsl_handle,
+                 struct ext_slave_descr *slave,
+                 struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   AK8975_REG_CNTL,
+                                   AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+static int ak8975_read(void *mlsl_handle,
+               struct ext_slave_descr *slave,
+               struct ext_slave_platform_data *pdata, unsigned char *data)
+{
+       unsigned char regs[8];
+       unsigned char *stat = &regs[0];
+       unsigned char *stat2 = &regs[7];
+       int result = INV_SUCCESS;
+       int status = INV_SUCCESS;
+
+       result =
+           inv_serial_read(mlsl_handle, pdata->address, AK8975_REG_ST1,
+                           8, regs);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Always return the data and the status registers */
+       memcpy(data, &regs[1], 6);
+       data[6] = regs[0];
+       data[7] = regs[7];
+
+       /*
+        * ST : data ready -
+        * Measurement has been completed and data is ready to be read.
+        */
+       if (*stat & 0x01)
+               status = INV_SUCCESS;
+
+       /*
+        * ST2 : data error -
+        * occurs when data read is started outside of a readable period;
+        * data read would not be correct.
+        * Valid in continuous measurement mode only.
+        * In single measurement mode this error should not occour but we
+        * stil account for it and return an error, since the data would be
+        * corrupted.
+        * DERR bit is self-clearing when ST2 register is read.
+        */
+       if (*stat2 & 0x04)
+               status = INV_ERROR_COMPASS_DATA_ERROR;
+       /*
+        * ST2 : overflow -
+        * the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
+        * This is likely to happen in presence of an external magnetic
+        * disturbance; it indicates, the sensor data is incorrect and should
+        * be ignored.
+        * An error is returned.
+        * HOFL bit clears when a new measurement starts.
+        */
+       if (*stat2 & 0x08)
+               status = INV_ERROR_COMPASS_DATA_OVERFLOW;
+       /*
+        * ST : overrun -
+        * the previous sample was not fetched and lost.
+        * Valid in continuous measurement mode only.
+        * In single measurement mode this error should not occour and we
+        * don't consider this condition an error.
+        * DOR bit is self-clearing when ST2 or any meas. data register is
+        * read.
+        */
+       if (*stat & 0x02) {
+               /* status = INV_ERROR_COMPASS_DATA_UNDERFLOW; */
+               status = INV_SUCCESS;
+       }
+
+       /*
+        * trigger next measurement if:
+        *    - stat is non zero;
+        *    - if stat is zero and stat2 is non zero.
+        * Won't trigger if data is not ready and there was no error.
+        */
+       if (*stat != 0x00 || *stat2 != 0x00) {
+               result = inv_serial_single_write(
+                   mlsl_handle, pdata->address,
+                   AK8975_REG_CNTL, AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       return status;
+}
+
+static int ak8975_config(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata,
+                        struct ext_slave_config *data)
+{
+       int result;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_WRITE_REGISTERS:
+               result = inv_serial_write(mlsl_handle, pdata->address,
+                                         data->len,
+                                         (unsigned char *)data->data);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               break;
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+       case MPU_SLAVE_CONFIG_MOT_THS:
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static int ak8975_get_config(void *mlsl_handle,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata,
+                            struct ext_slave_config *data)
+{
+       struct ak8975_private_data *private_data = pdata->private_data;
+       int result;
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_READ_REGISTERS:
+               {
+                       unsigned char *serial_data =
+                           (unsigned char *)data->data;
+                       result =
+                           inv_serial_read(mlsl_handle, pdata->address,
+                                           serial_data[0], data->len - 1,
+                                           &serial_data[1]);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       break;
+               }
+       case MPU_SLAVE_READ_SCALE:
+               {
+                       unsigned char *serial_data =
+                           (unsigned char *)data->data;
+                       serial_data[0] = private_data->init.asa[0];
+                       serial_data[1] = private_data->init.asa[1];
+                       serial_data[2] = private_data->init.asa[2];
+                       result = INV_SUCCESS;
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       break;
+               }
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) = 0;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) = 8000;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+       case MPU_SLAVE_CONFIG_MOT_THS:
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       default:
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static struct ext_slave_read_trigger ak8975_read_trigger = {
+       /*.reg              = */ 0x0A,
+       /*.value            = */ 0x01
+};
+
+static struct ext_slave_descr ak8975_descr = {
+       .init             = ak8975_init,
+       .exit             = ak8975_exit,
+       .suspend          = ak8975_suspend,
+       .resume           = ak8975_resume,
+       .read             = ak8975_read,
+       .config           = ak8975_config,
+       .get_config       = ak8975_get_config,
+       .name             = "ak8975",
+       .type             = EXT_SLAVE_TYPE_COMPASS,
+       .id               = COMPASS_ID_AK8975,
+       .read_reg         = 0x01,
+       .read_len         = 10,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {9830, 4000},
+       .trigger          = &ak8975_read_trigger,
+};
+
+static
+struct ext_slave_descr *ak8975_get_slave_descr(void)
+{
+       return &ak8975_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct ak8975_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int ak8975_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct ak8975_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s,0x%x\n", __func__, devid->name,(unsigned int)client);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       ak8975_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int ak8975_mod_remove(struct i2c_client *client)
+{
+       struct ak8975_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               ak8975_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id ak8975_mod_id[] = {
+       { "ak8975", COMPASS_ID_AK8975 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ak8975_mod_id);
+
+static struct i2c_driver ak8975_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = ak8975_mod_probe,
+       .remove = ak8975_mod_remove,
+       .id_table = ak8975_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "ak8975_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init ak8975_mod_init(void)
+{
+       int res = i2c_add_driver(&ak8975_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "ak8975_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit ak8975_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&ak8975_mod_driver);
+}
+
+module_init(ak8975_mod_init);
+module_exit(ak8975_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate AK8975 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ak8975_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/compass/ami306.c b/drivers/misc/inv_mpu/compass/ami306.c
new file mode 100644 (file)
index 0000000..f645457
--- /dev/null
@@ -0,0 +1,1020 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup COMPASSDL
+ *
+ *  @{
+ *      @file   ami306.c
+ *      @brief  Magnetometer setup and handling methods for Aichi AMI306
+ *              compass.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include "ami_hw.h"
+#include "ami_sensor_def.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/* -------------------------------------------------------------------------- */
+#define AMI306_REG_DATAX               (0x10)
+#define AMI306_REG_STAT1               (0x18)
+#define AMI306_REG_CNTL1               (0x1B)
+#define AMI306_REG_CNTL2               (0x1C)
+#define AMI306_REG_CNTL3               (0x1D)
+#define AMI306_REG_CNTL4_1             (0x5C)
+#define AMI306_REG_CNTL4_2             (0x5D)
+
+#define AMI306_BIT_CNTL1_PC1           (0x80)
+#define AMI306_BIT_CNTL1_ODR1          (0x10)
+#define AMI306_BIT_CNTL1_FS1           (0x02)
+
+#define AMI306_BIT_CNTL2_IEN           (0x10)
+#define AMI306_BIT_CNTL2_DREN          (0x08)
+#define AMI306_BIT_CNTL2_DRP           (0x04)
+#define AMI306_BIT_CNTL3_F0RCE         (0x40)
+
+#define AMI_FINE_MAX                   (96)
+#define AMI_STANDARD_OFFSET            (0x800)
+#define AMI_GAIN_COR_DEFAULT           (1000)
+
+/* -------------------------------------------------------------------------- */
+struct ami306_private_data {
+       int isstandby;
+       unsigned char fine[3];
+       struct ami_sensor_parametor param;
+       struct ami_win_parameter win;
+};
+
+/* -------------------------------------------------------------------------- */
+static inline unsigned short little_u8_to_u16(unsigned char *p_u8)
+{
+       return p_u8[0] | (p_u8[1] << 8);
+}
+
+static int ami306_set_bits8(void *mlsl_handle,
+                           struct ext_slave_platform_data *pdata,
+                           unsigned char reg, unsigned char bits)
+{
+       int result;
+       unsigned char buf;
+
+       result = inv_serial_read(mlsl_handle, pdata->address, reg, 1, &buf);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       buf |= bits;
+       result = inv_serial_single_write(mlsl_handle, pdata->address, reg, buf);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+static int ami306_wait_data_ready(void *mlsl_handle,
+                                 struct ext_slave_platform_data *pdata,
+                                 unsigned long usecs, unsigned long times)
+{
+       int result = 0;
+       unsigned char buf;
+
+       for (; 0 < times; --times) {
+               udelay(usecs);
+               result = inv_serial_read(mlsl_handle, pdata->address,
+                                        AMI_REG_STA1, 1, &buf);
+               if (buf & AMI_STA1_DRDY_BIT)
+                       return 0;
+               else if (buf & AMI_STA1_DOR_BIT)
+                       return INV_ERROR_COMPASS_DATA_OVERFLOW;
+       }
+       return INV_ERROR_COMPASS_DATA_NOT_READY;
+}
+
+static int ami306_read_raw_data(void *mlsl_handle,
+                               struct ext_slave_platform_data *pdata,
+                               short dat[3])
+{
+       int result;
+       unsigned char buf[6];
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI_REG_DATAX, sizeof(buf), buf);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dat[0] = little_u8_to_u16(&buf[0]);
+       dat[1] = little_u8_to_u16(&buf[2]);
+       dat[2] = little_u8_to_u16(&buf[4]);
+       return result;
+}
+
+#define AMI_WAIT_DATAREADY_RETRY               3       /* retry times */
+#define AMI_DRDYWAIT                           800     /* u(micro) sec */
+static int ami306_force_mesurement(void *mlsl_handle,
+                                  struct ext_slave_platform_data *pdata,
+                                  short ver[3])
+{
+       int result;
+       int status;
+       result = ami306_set_bits8(mlsl_handle, pdata,
+                                 AMI_REG_CTRL3, AMI_CTRL3_FORCE_BIT);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = ami306_wait_data_ready(mlsl_handle, pdata,
+                                       AMI_DRDYWAIT, AMI_WAIT_DATAREADY_RETRY);
+       if (result && result != INV_ERROR_COMPASS_DATA_OVERFLOW) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /*  READ DATA X,Y,Z */
+       status = ami306_read_raw_data(mlsl_handle, pdata, ver);
+       if (status) {
+               LOG_RESULT_LOCATION(status);
+               return status;
+       }
+
+       return result;
+}
+
+static int ami306_mea(void *mlsl_handle,
+                     struct ext_slave_platform_data *pdata, short val[3])
+{
+       int result = ami306_force_mesurement(mlsl_handle, pdata, val);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       val[0] += AMI_STANDARD_OFFSET;
+       val[1] += AMI_STANDARD_OFFSET;
+       val[2] += AMI_STANDARD_OFFSET;
+       return result;
+}
+
+static int ami306_write_offset(void *mlsl_handle,
+                              struct ext_slave_platform_data *pdata,
+                              unsigned char *fine)
+{
+       int result = 0;
+       unsigned char dat[3];
+       dat[0] = AMI_REG_OFFX;
+       dat[1] = 0x7f & fine[0];
+       dat[2] = 0;
+       result = inv_serial_write(mlsl_handle, pdata->address,
+                                 sizeof(dat), dat);
+       dat[0] = AMI_REG_OFFY;
+       dat[1] = 0x7f & fine[1];
+       dat[2] = 0;
+       result = inv_serial_write(mlsl_handle, pdata->address,
+                                 sizeof(dat), dat);
+       dat[0] = AMI_REG_OFFZ;
+       dat[1] = 0x7f & fine[2];
+       dat[2] = 0;
+       result = inv_serial_write(mlsl_handle, pdata->address,
+                                 sizeof(dat), dat);
+       return result;
+}
+
+static int ami306_start_sensor(void *mlsl_handle,
+                              struct ext_slave_platform_data *pdata)
+{
+       int result = 0;
+       unsigned char buf[3];
+       struct ami306_private_data *private_data = pdata->private_data;
+
+       /* Step 1 */
+       result = ami306_set_bits8(mlsl_handle, pdata,
+                                 AMI_REG_CTRL1,
+                                 AMI_CTRL1_PC1 | AMI_CTRL1_FS1_FORCE);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Step 2 */
+       result = ami306_set_bits8(mlsl_handle, pdata,
+                                 AMI_REG_CTRL2, AMI_CTRL2_DREN);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Step 3 */
+       buf[0] = AMI_REG_CTRL4;
+       buf[1] = AMI_CTRL4_HS & 0xFF;
+       buf[2] = (AMI_CTRL4_HS >> 8) & 0xFF;
+       result = inv_serial_write(mlsl_handle, pdata->address,
+                                 sizeof(buf), buf);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Step 4 */
+       result = ami306_write_offset(mlsl_handle, pdata, private_data->fine);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+/**
+ * This function does this.
+ *
+ * @param mlsl_handle this param is this.
+ * @param slave
+ * @param pdata
+ *
+ * @return INV_SUCCESS or non-zero error code.
+ */
+static int ami306_read_param(void *mlsl_handle,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata)
+{
+       int result = 0;
+       unsigned char regs[12];
+       struct ami306_private_data *private_data = pdata->private_data;
+       struct ami_sensor_parametor *param = &private_data->param;
+
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI_REG_SENX, sizeof(regs), regs);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Little endian 16 bit registers */
+       param->m_gain.x = little_u8_to_u16(&regs[0]);
+       param->m_gain.y = little_u8_to_u16(&regs[2]);
+       param->m_gain.z = little_u8_to_u16(&regs[4]);
+
+       param->m_interference.xy = regs[7];
+       param->m_interference.xz = regs[6];
+       param->m_interference.yx = regs[9];
+       param->m_interference.yz = regs[8];
+       param->m_interference.zx = regs[11];
+       param->m_interference.zy = regs[10];
+
+       param->m_offset.x = AMI_STANDARD_OFFSET;
+       param->m_offset.y = AMI_STANDARD_OFFSET;
+       param->m_offset.z = AMI_STANDARD_OFFSET;
+
+       param->m_gain_cor.x = AMI_GAIN_COR_DEFAULT;
+       param->m_gain_cor.y = AMI_GAIN_COR_DEFAULT;
+       param->m_gain_cor.z = AMI_GAIN_COR_DEFAULT;
+
+       return result;
+}
+
+static int ami306_initial_b0_adjust(void *mlsl_handle,
+                                   struct ext_slave_descr *slave,
+                                   struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char fine[3] = { 0 };
+       short data[3];
+       int diff[3] = { 0x7fff, 0x7fff, 0x7fff };
+       int fn = 0;
+       int ax = 0;
+       unsigned char buf[3];
+       struct ami306_private_data *private_data = pdata->private_data;
+
+       result = ami306_set_bits8(mlsl_handle, pdata,
+                                 AMI_REG_CTRL2, AMI_CTRL2_DREN);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       buf[0] = AMI_REG_CTRL4;
+       buf[1] = AMI_CTRL4_HS & 0xFF;
+       buf[2] = (AMI_CTRL4_HS >> 8) & 0xFF;
+       result = inv_serial_write(mlsl_handle, pdata->address,
+                                 sizeof(buf), buf);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       for (fn = 0; fn < AMI_FINE_MAX; ++fn) { /* fine 0 -> 95 */
+               fine[0] = fine[1] = fine[2] = fn;
+               result = ami306_write_offset(mlsl_handle, pdata, fine);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+
+               result = ami306_force_mesurement(mlsl_handle, pdata, data);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               MPL_LOGV("[%d] x:%-5d y:%-5d z:%-5d\n",
+                        fn, data[0], data[1], data[2]);
+
+               for (ax = 0; ax < 3; ax++) {
+                       /* search point most close to zero. */
+                       if (diff[ax] > abs(data[ax])) {
+                               private_data->fine[ax] = fn;
+                               diff[ax] = abs(data[ax]);
+                       }
+               }
+       }
+       MPL_LOGV("fine x:%-5d y:%-5d z:%-5d\n",
+                private_data->fine[0], private_data->fine[1],
+                private_data->fine[2]);
+
+       result = ami306_write_offset(mlsl_handle, pdata, private_data->fine);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Software Reset */
+       result = ami306_set_bits8(mlsl_handle, pdata,
+                                 AMI_REG_CTRL3, AMI_CTRL3_SRST_BIT);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+}
+
+#define SEH_RANGE_MIN 100
+#define SEH_RANGE_MAX 3950
+static int ami306_search_offset(void *mlsl_handle,
+                               struct ext_slave_descr *slave,
+                               struct ext_slave_platform_data *pdata)
+{
+       int result;
+       int axis;
+       unsigned char regs[6];
+       unsigned char run_flg[3] = { 1, 1, 1 };
+       unsigned char fine[3];
+       unsigned char win_range_fine[3];
+       unsigned short fine_output[3];
+       short val[3];
+       unsigned short cnt[3] = { 0 };
+       struct ami306_private_data *private_data = pdata->private_data;
+
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI_FINEOUTPUT_X, sizeof(regs), regs);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       fine_output[0] = little_u8_to_u16(&regs[0]);
+       fine_output[1] = little_u8_to_u16(&regs[2]);
+       fine_output[2] = little_u8_to_u16(&regs[4]);
+
+       for (axis = 0; axis < 3; ++axis) {
+               if (fine_output[axis] == 0) {
+                       MPL_LOGV("error fine_output %d  axis:%d\n",
+                                __LINE__, axis);
+                       return -1;
+               }
+               /*  fines per a window */
+               win_range_fine[axis] = (SEH_RANGE_MAX - SEH_RANGE_MIN)
+                   / fine_output[axis];
+       }
+
+       /* get current fine */
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI_REG_OFFX, 2, &regs[0]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI_REG_OFFY, 2, &regs[2]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI_REG_OFFZ, 2, &regs[4]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       fine[0] = (unsigned char)(regs[0] & 0x7f);
+       fine[1] = (unsigned char)(regs[2] & 0x7f);
+       fine[2] = (unsigned char)(regs[4] & 0x7f);
+
+       while (run_flg[0] == 1 || run_flg[1] == 1 || run_flg[2] == 1) {
+
+               result = ami306_mea(mlsl_handle, pdata, val);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               MPL_LOGV("val  x:%-5d y:%-5d z:%-5d\n", val[0], val[1], val[2]);
+               MPL_LOGV("now fine x:%-5d y:%-5d z:%-5d\n",
+                        fine[0], fine[1], fine[2]);
+
+               for (axis = 0; axis < 3; ++axis) {
+                       if (axis == 0) {        /* X-axis is reversed */
+                               val[axis] = 0x0FFF & ~val[axis];
+                       }
+                       if (val[axis] < SEH_RANGE_MIN) {
+                               /* At the case of less low limmit. */
+                               fine[axis] -= win_range_fine[axis];
+                               MPL_LOGV("min : fine=%d diff=%d\n",
+                                        fine[axis], win_range_fine[axis]);
+                       }
+                       if (val[axis] > SEH_RANGE_MAX) {
+                               /* At the case of over high limmit. */
+                               fine[axis] += win_range_fine[axis];
+                               MPL_LOGV("max : fine=%d diff=%d\n",
+                                        fine[axis], win_range_fine[axis]);
+                       }
+                       if (SEH_RANGE_MIN <= val[axis] &&
+                           val[axis] <= SEH_RANGE_MAX) {
+                               /* In the current window. */
+                               int diff_fine =
+                                   (val[axis] - AMI_STANDARD_OFFSET) /
+                                   fine_output[axis];
+                               fine[axis] += diff_fine;
+                               run_flg[axis] = 0;
+                               MPL_LOGV("mid : fine=%d diff=%d\n",
+                                        fine[axis], diff_fine);
+                       }
+
+                       if (!(0 <= fine[axis] && fine[axis] < AMI_FINE_MAX)) {
+                               MPL_LOGE("fine err :%d\n", cnt[axis]);
+                               goto out;
+                       }
+                       if (cnt[axis] > 3) {
+                               MPL_LOGE("cnt err :%d\n", cnt[axis]);
+                               goto out;
+                       }
+                       cnt[axis]++;
+               }
+               MPL_LOGV("new fine x:%-5d y:%-5d z:%-5d\n",
+                        fine[0], fine[1], fine[2]);
+
+               /* set current fine */
+               result = ami306_write_offset(mlsl_handle, pdata, fine);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       memcpy(private_data->fine, fine, sizeof(fine));
+out:
+       result = ami306_set_bits8(mlsl_handle, pdata,
+                                 AMI_REG_CTRL3, AMI_CTRL3_SRST_BIT);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       udelay(250 + 50);
+       return 0;
+}
+
+static int ami306_read_win(void *mlsl_handle,
+                          struct ext_slave_descr *slave,
+                          struct ext_slave_platform_data *pdata)
+{
+       int result = 0;
+       unsigned char regs[6];
+       struct ami306_private_data *private_data = pdata->private_data;
+       struct ami_win_parameter *win = &private_data->win;
+
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI_REG_OFFOTPX, sizeof(regs), regs);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       win->m_0Gauss_fine.x = (unsigned char)(regs[0] & 0x7f);
+       win->m_0Gauss_fine.y = (unsigned char)(regs[2] & 0x7f);
+       win->m_0Gauss_fine.z = (unsigned char)(regs[4] & 0x7f);
+
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI_REG_OFFX, 2, &regs[0]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI_REG_OFFY, 2, &regs[2]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI_REG_OFFZ, 2, &regs[4]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       win->m_fine.x = (unsigned char)(regs[0] & 0x7f);
+       win->m_fine.y = (unsigned char)(regs[2] & 0x7f);
+       win->m_fine.z = (unsigned char)(regs[4] & 0x7f);
+
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI_FINEOUTPUT_X, sizeof(regs), regs);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       win->m_fine_output.x = little_u8_to_u16(&regs[0]);
+       win->m_fine_output.y = little_u8_to_u16(&regs[2]);
+       win->m_fine_output.z = little_u8_to_u16(&regs[4]);
+
+       return result;
+}
+
+static int ami306_suspend(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char reg;
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                AMI306_REG_CNTL1, 1, &reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       reg &= ~(AMI306_BIT_CNTL1_PC1 | AMI306_BIT_CNTL1_FS1);
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        AMI306_REG_CNTL1, reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+static int ami306_resume(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       unsigned char regs[] = {
+               AMI306_REG_CNTL4_1,
+               0x7E,
+               0xA0
+       };
+       /* Step1. Set CNTL1 reg to power model active (Write CNTL1:PC1=1) */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        AMI306_REG_CNTL1,
+                                        AMI306_BIT_CNTL1_PC1 |
+                                        AMI306_BIT_CNTL1_FS1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Step2. Set CNTL2 reg to DRDY active high and enabled
+          (Write CNTL2:DREN=1) */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        AMI306_REG_CNTL2,
+                                        AMI306_BIT_CNTL2_DREN |
+                                        AMI306_BIT_CNTL2_DRP);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Step3. Set CNTL4 reg to for measurement speed: Write CNTL4, 0xA07E */
+       result = inv_serial_write(mlsl_handle, pdata->address,
+                               ARRAY_SIZE(regs), regs);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Step4. skipped */
+
+       /* Step5. Set CNTL3 reg to forced measurement period
+          (Write CNTL3:FORCE=1) */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        AMI306_REG_CNTL3,
+                                        AMI306_BIT_CNTL3_F0RCE);
+
+       return result;
+}
+
+static int ami306_read(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata,
+                      unsigned char *data)
+{
+       int result = INV_SUCCESS;
+       int ii;
+       short val[COMPASS_NUM_AXES];
+
+       result = ami306_mea(mlsl_handle, pdata, val);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       for (ii = 0; ii < COMPASS_NUM_AXES; ii++) {
+               val[ii] -= AMI_STANDARD_OFFSET;
+               data[2 * ii] = val[ii] & 0xFF;
+               data[(2 * ii) + 1] = (val[ii] >> 8) & 0xFF;
+       }
+       return result;
+}
+
+static int ami306_init(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       int result;
+       struct ami306_private_data *private_data;
+       private_data = (struct ami306_private_data *)
+           kzalloc(sizeof(struct ami306_private_data), GFP_KERNEL);
+
+       if (!private_data)
+               return INV_ERROR_MEMORY_EXAUSTED;
+
+       pdata->private_data = private_data;
+       result = ami306_set_bits8(mlsl_handle, pdata,
+                                 AMI_REG_CTRL1,
+                                 AMI_CTRL1_PC1 | AMI_CTRL1_FS1_FORCE);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Read Parameters */
+       result = ami306_read_param(mlsl_handle, slave, pdata);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Read Window */
+       result = ami306_initial_b0_adjust(mlsl_handle, slave, pdata);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = ami306_start_sensor(mlsl_handle, pdata);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = ami306_read_win(mlsl_handle, slave, pdata);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        AMI306_REG_CNTL1, 0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return INV_SUCCESS;
+}
+
+static int ami306_exit(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata)
+{
+       kfree(pdata->private_data);
+       return INV_SUCCESS;
+}
+
+static int ami306_config(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata,
+                        struct ext_slave_config *data)
+{
+       if (!data->data) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       switch (data->key) {
+       case MPU_SLAVE_PARAM:
+       case MPU_SLAVE_WINDOW:
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+       case MPU_SLAVE_CONFIG_MOT_THS:
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static int ami306_get_config(void *mlsl_handle,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata,
+                            struct ext_slave_config *data)
+{
+       int result;
+       struct ami306_private_data *private_data = pdata->private_data;
+       if (!data->data) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       switch (data->key) {
+       case MPU_SLAVE_PARAM:
+               if (sizeof(struct ami_sensor_parametor) > data->len) {
+                       LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+                       return INV_ERROR_INVALID_PARAMETER;
+               }
+               if (data->apply) {
+                       result = ami306_read_param(mlsl_handle, slave, pdata);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+               }
+               memcpy(data->data, &private_data->param,
+                      sizeof(struct ami_sensor_parametor));
+               break;
+       case MPU_SLAVE_WINDOW:
+               if (sizeof(struct ami_win_parameter) > data->len) {
+                       LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+                       return INV_ERROR_INVALID_PARAMETER;
+               }
+               if (data->apply) {
+                       result = ami306_read_win(mlsl_handle, slave, pdata);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+               }
+               memcpy(data->data, &private_data->win,
+                      sizeof(struct ami_win_parameter));
+               break;
+       case MPU_SLAVE_SEARCHOFFSET:
+               if (sizeof(struct ami_win_parameter) > data->len) {
+                       LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+                       return INV_ERROR_INVALID_PARAMETER;
+               }
+               if (data->apply) {
+                       result = ami306_search_offset(mlsl_handle,
+                                                     slave, pdata);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       /* Start sensor */
+                       result = ami306_start_sensor(mlsl_handle, pdata);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       result = ami306_read_win(mlsl_handle, slave, pdata);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+               }
+               memcpy(data->data, &private_data->win,
+                      sizeof(struct ami_win_parameter));
+               break;
+       case MPU_SLAVE_READWINPARAMS:
+               if (sizeof(struct ami_win_parameter) > data->len) {
+                       LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+                       return INV_ERROR_INVALID_PARAMETER;
+               }
+               if (data->apply) {
+                       result = ami306_initial_b0_adjust(mlsl_handle,
+                                                         slave, pdata);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       /* Start sensor */
+                       result = ami306_start_sensor(mlsl_handle, pdata);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       result = ami306_read_win(mlsl_handle, slave, pdata);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+               }
+               memcpy(data->data, &private_data->win,
+                      sizeof(struct ami_win_parameter));
+               break;
+       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
+               (*(unsigned long *)data->data) = 0;
+               break;
+       case MPU_SLAVE_CONFIG_ODR_RESUME:
+               (*(unsigned long *)data->data) = 50000;
+               break;
+       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
+       case MPU_SLAVE_CONFIG_FSR_RESUME:
+       case MPU_SLAVE_CONFIG_MOT_THS:
+       case MPU_SLAVE_CONFIG_NMOT_THS:
+       case MPU_SLAVE_CONFIG_MOT_DUR:
+       case MPU_SLAVE_CONFIG_NMOT_DUR:
+       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
+       case MPU_SLAVE_CONFIG_IRQ_RESUME:
+       case MPU_SLAVE_READ_SCALE:
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+static struct ext_slave_read_trigger ami306_read_trigger = {
+       /*.reg              = */ AMI_REG_CTRL3,
+       /*.value            = */ AMI_CTRL3_FORCE_BIT
+};
+
+static struct ext_slave_descr ami306_descr = {
+       .init             = ami306_init,
+       .exit             = ami306_exit,
+       .suspend          = ami306_suspend,
+       .resume           = ami306_resume,
+       .read             = ami306_read,
+       .config           = ami306_config,
+       .get_config       = ami306_get_config,
+       .name             = "ami306",
+       .type             = EXT_SLAVE_TYPE_COMPASS,
+       .id               = COMPASS_ID_AMI306,
+       .read_reg         = 0x0E,
+       .read_len         = 13,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {5461, 3333},
+       .trigger          = &ami306_read_trigger,
+};
+
+static
+struct ext_slave_descr *ami306_get_slave_descr(void)
+{
+       return &ami306_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct ami306_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int ami306_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct ami306_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       ami306_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int ami306_mod_remove(struct i2c_client *client)
+{
+       struct ami306_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               ami306_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id ami306_mod_id[] = {
+       { "ami306", COMPASS_ID_AMI306 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ami306_mod_id);
+
+static struct i2c_driver ami306_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = ami306_mod_probe,
+       .remove = ami306_mod_remove,
+       .id_table = ami306_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "ami306_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init ami306_mod_init(void)
+{
+       int res = i2c_add_driver(&ami306_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "ami306_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit ami306_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&ami306_mod_driver);
+}
+
+module_init(ami306_mod_init);
+module_exit(ami306_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate AMI306 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ami306_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/compass/ami30x.c b/drivers/misc/inv_mpu/compass/ami30x.c
new file mode 100644 (file)
index 0000000..0c4937c
--- /dev/null
@@ -0,0 +1,308 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup COMPASSDL
+ *
+ *  @{
+ *      @file   ami30x.c
+ *      @brief  Magnetometer setup and handling methods for Aichi AMI304
+ *              and AMI305 compass devices.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/* -------------------------------------------------------------------------- */
+#define AMI30X_REG_DATAX (0x10)
+#define AMI30X_REG_STAT1 (0x18)
+#define AMI30X_REG_CNTL1 (0x1B)
+#define AMI30X_REG_CNTL2 (0x1C)
+#define AMI30X_REG_CNTL3 (0x1D)
+
+#define AMI30X_BIT_CNTL1_PC1  (0x80)
+#define AMI30X_BIT_CNTL1_ODR1 (0x10)
+#define AMI30X_BIT_CNTL1_FS1  (0x02)
+
+#define AMI30X_BIT_CNTL2_IEN  (0x10)
+#define AMI30X_BIT_CNTL2_DREN (0x08)
+#define AMI30X_BIT_CNTL2_DRP  (0x04)
+#define AMI30X_BIT_CNTL3_F0RCE (0x40)
+
+/* -------------------------------------------------------------------------- */
+static int ami30x_suspend(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char reg;
+       result =
+           inv_serial_read(mlsl_handle, pdata->address, AMI30X_REG_CNTL1,
+                           1, &reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       reg &= ~(AMI30X_BIT_CNTL1_PC1 | AMI30X_BIT_CNTL1_FS1);
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   AMI30X_REG_CNTL1, reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+static int ami30x_resume(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       /* Set CNTL1 reg to power model active */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   AMI30X_REG_CNTL1,
+                                   AMI30X_BIT_CNTL1_PC1 |
+                                   AMI30X_BIT_CNTL1_FS1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Set CNTL2 reg to DRDY active high and enabled */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   AMI30X_REG_CNTL2,
+                                   AMI30X_BIT_CNTL2_DREN |
+                                   AMI30X_BIT_CNTL2_DRP);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Set CNTL3 reg to forced measurement period */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   AMI30X_REG_CNTL3, AMI30X_BIT_CNTL3_F0RCE);
+
+       return result;
+}
+
+static int ami30x_read(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata,
+                      unsigned char *data)
+{
+       unsigned char stat;
+       int result = INV_SUCCESS;
+
+       /* Read status reg and check if data ready (DRDY) */
+       result =
+           inv_serial_read(mlsl_handle, pdata->address, AMI30X_REG_STAT1,
+                           1, &stat);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       if (stat & 0x40) {
+               result =
+                   inv_serial_read(mlsl_handle, pdata->address,
+                                   AMI30X_REG_DATAX, 6, (unsigned char *)data);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               /* start another measurement */
+               result =
+                   inv_serial_single_write(mlsl_handle, pdata->address,
+                                           AMI30X_REG_CNTL3,
+                                           AMI30X_BIT_CNTL3_F0RCE);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+
+               return INV_SUCCESS;
+       }
+
+       return INV_ERROR_COMPASS_DATA_NOT_READY;
+}
+
+
+/* For AMI305,the range field needs to be modified to {9830.4f} */
+static struct ext_slave_descr ami30x_descr = {
+       .init             = NULL,
+       .exit             = NULL,
+       .suspend          = ami30x_suspend,
+       .resume           = ami30x_resume,
+       .read             = ami30x_read,
+       .config           = NULL,
+       .get_config       = NULL,
+       .name             = "ami30x",
+       .type             = EXT_SLAVE_TYPE_COMPASS,
+       .id               = COMPASS_ID_AMI30X,
+       .read_reg         = 0x06,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {5461, 3333},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *ami30x_get_slave_descr(void)
+{
+       return &ami30x_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct ami30x_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int ami30x_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct ami30x_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       ami30x_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int ami30x_mod_remove(struct i2c_client *client)
+{
+       struct ami30x_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               ami30x_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id ami30x_mod_id[] = {
+       { "ami30x", COMPASS_ID_AMI30X },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, ami30x_mod_id);
+
+static struct i2c_driver ami30x_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = ami30x_mod_probe,
+       .remove = ami30x_mod_remove,
+       .id_table = ami30x_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "ami30x_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init ami30x_mod_init(void)
+{
+       int res = i2c_add_driver(&ami30x_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "ami30x_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit ami30x_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&ami30x_mod_driver);
+}
+
+module_init(ami30x_mod_init);
+module_exit(ami30x_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate AMI30X sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("ami30x_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/compass/ami_hw.h b/drivers/misc/inv_mpu/compass/ami_hw.h
new file mode 100644 (file)
index 0000000..32a04e9
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2010 Information System Products Co.,Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef AMI_HW_H
+#define AMI_HW_H
+
+#define        AMI_I2C_BUS_NUM                 2
+
+#ifdef AMI304_MODEL
+#define AMI_I2C_ADDRESS                        0x0F
+#else
+#define AMI_I2C_ADDRESS                        0x0E
+#endif
+
+#define AMI_GPIO_INT                   152
+#define AMI_GPIO_DRDY                  153
+
+/* AMI-Sensor Internal Register Address
+ *(Please refer to AMI-Sensor Specifications)
+ */
+#define AMI_MOREINFO_CMDCODE           0x0d
+#define AMI_WHOIAM_CMDCODE             0x0f
+#define AMI_REG_DATAX                  0x10
+#define AMI_REG_DATAY                  0x12
+#define AMI_REG_DATAZ                  0x14
+#define AMI_REG_STA1                   0x18
+#define AMI_REG_CTRL1                  0x1b
+#define AMI_REG_CTRL2                  0x1c
+#define AMI_REG_CTRL3                  0x1d
+#define AMI_REG_B0X                    0x20
+#define AMI_REG_B0Y                    0x22
+#define AMI_REG_B0Z                    0x24
+#define AMI_REG_CTRL5                  0x40
+#define AMI_REG_CTRL4                  0x5c
+#define AMI_REG_TEMP                   0x60
+#define AMI_REG_DELAYX                 0x68
+#define AMI_REG_DELAYY                 0x6e
+#define AMI_REG_DELAYZ                 0x74
+#define AMI_REG_OFFX                   0x6c
+#define AMI_REG_OFFY                   0x72
+#define AMI_REG_OFFZ                   0x78
+#define AMI_FINEOUTPUT_X               0x90
+#define AMI_FINEOUTPUT_Y               0x92
+#define AMI_FINEOUTPUT_Z               0x94
+#define AMI_REG_SENX                   0x96
+#define AMI_REG_SENY                   0x98
+#define AMI_REG_SENZ                   0x9a
+#define AMI_REG_GAINX                  0x9c
+#define AMI_REG_GAINY                  0x9e
+#define AMI_REG_GAINZ                  0xa0
+#define AMI_GETVERSION_CMDCODE         0xe8
+#define AMI_SERIALNUMBER_CMDCODE       0xea
+#define AMI_REG_B0OTPX                 0xa2
+#define AMI_REG_B0OTPY                 0xb8
+#define AMI_REG_B0OTPZ                 0xce
+#define AMI_REG_OFFOTPX                        0xf8
+#define AMI_REG_OFFOTPY                        0xfa
+#define AMI_REG_OFFOTPZ                        0xfc
+
+/* AMI-Sensor Control Bit  (Please refer to AMI-Sensor Specifications) */
+#define AMI_CTRL1_PC1                  0x80
+#define AMI_CTRL1_FS1_FORCE            0x02
+#define AMI_CTRL1_ODR1                 0x10
+#define AMI_CTRL2_DREN                 0x08
+#define AMI_CTRL2_DRP                  0x04
+#define AMI_CTRL3_FORCE_BIT            0x40
+#define AMI_CTRL3_B0_LO_BIT            0x10
+#define AMI_CTRL3_SRST_BIT             0x80
+#define AMI_CTRL4_HS                   0xa07e
+#define AMI_CTRL4_AB                   0x0001
+#define AMI_STA1_DRDY_BIT              0x40
+#define AMI_STA1_DOR_BIT               0x20
+
+#endif
diff --git a/drivers/misc/inv_mpu/compass/ami_sensor_def.h b/drivers/misc/inv_mpu/compass/ami_sensor_def.h
new file mode 100644 (file)
index 0000000..64032e2
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (C) 2010 Information System Products Co.,Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Definitions for ami306 compass chip.
+ */
+#ifndef AMI_SENSOR_DEF_H
+#define AMI_SENSOR_DEF_H
+
+/*********************************************************************
+ Constant
+ *********************************************************************/
+#define        AMI_OK          0x00                    /**< Normal */
+#define        AMI_PARAM_ERR   0x01                    /**< Parameter Error  */
+#define        AMI_SEQ_ERR     0x02                    /**< Squence Error  */
+#define        AMI_SYSTEM_ERR  0x10                    /**< System Error  */
+#define AMI_BLOCK_ERR  0x20                    /**< Block Error */
+#define        AMI_ERROR       0x99                    /**< other Error  */
+
+/*********************************************************************
+ Struct definition
+ *********************************************************************/
+/** axis sensitivity(gain) calibration parameter information  */
+struct ami_vector3d {
+       signed short x;                 /**< X-axis  */
+       signed short y;                 /**< Y-axis  */
+       signed short z;                 /**< Z-axis  */
+};
+
+/** axis interference information  */
+struct ami_interference {
+       /**< Y-axis magnetic field for X-axis correction value  */
+       signed short xy;
+       /**< Z-axis magnetic field for X-axis correction value  */
+       signed short xz;
+       /**< X-axis magnetic field for Y-axis correction value  */
+       signed short yx;
+       /**< Z-axis magnetic field for Y-axis correction value  */
+       signed short yz;
+       /**< X-axis magnetic field for Z-axis correction value  */
+       signed short zx;
+       /**< Y-axis magnetic field for Z-axis correction value  */
+       signed short zy;
+};
+
+/** sensor calibration Parameter information  */
+struct ami_sensor_parametor {
+       /**< geomagnetic field sensor gain  */
+       struct ami_vector3d m_gain;
+       /**< geomagnetic field sensor gain correction parameter  */
+       struct ami_vector3d m_gain_cor;
+       /**< geomagnetic field sensor offset  */
+       struct ami_vector3d m_offset;
+       /**< geomagnetic field sensor axis interference parameter */
+       struct ami_interference m_interference;
+#ifdef AMI_6AXIS
+       /**< acceleration sensor gain  */
+       struct ami_vector3d a_gain;
+       /**< acceleration sensor offset  */
+       struct ami_vector3d a_offset;
+       /**< acceleration sensor deviation  */
+       signed short a_deviation;
+#endif
+};
+
+/** G2-Sensor measurement value (voltage ADC value ) */
+struct ami_sensor_rawvalue {
+       /**< geomagnetic field sensor measurement X-axis value
+       (mounted position/direction reference) */
+       unsigned short mx;
+       /**< geomagnetic field sensor measurement Y-axis value
+       (mounted position/direction reference) */
+       unsigned short my;
+       /**< geomagnetic field sensor measurement Z-axis value
+       (mounted position/direction reference) */
+       unsigned short mz;
+#ifdef AMI_6AXIS
+       /**< acceleration sensor measurement X-axis value
+       (mounted position/direction reference) */
+       unsigned short ax;
+       /**< acceleration sensor measurement Y-axis value
+       (mounted position/direction reference) */
+       unsigned short ay;
+       /**< acceleration sensor measurement Z-axis value
+       (mounted position/direction reference) */
+       unsigned short az;
+#endif
+       /**< temperature sensor measurement value  */
+       unsigned short temperature;
+};
+
+/** Window function Parameter information  */
+struct ami_win_parameter {
+       /**< current fine value  */
+       struct ami_vector3d m_fine;
+       /**< change per 1coarse */
+       struct ami_vector3d m_fine_output;
+       /**< fine value at zero gauss */
+       struct ami_vector3d m_0Gauss_fine;
+#ifdef AMI304
+       /**< current b0 value  */
+       struct ami_vector3d m_b0;
+       /**< current coarse value  */
+       struct ami_vector3d m_coar;
+       /**< change per 1fine */
+       struct ami_vector3d m_coar_output;
+       /**< coarse value at zero gauss */
+       struct ami_vector3d m_0Gauss_coar;
+       /**< delay value  */
+       struct ami_vector3d m_delay;
+#endif
+};
+
+/** AMI chip information ex) 1)model 2)s/n 3)ver 4)more info in the chip */
+struct ami_chipinfo {
+       unsigned short info;    /* INFO 0x0d/0x0e reg.  */
+       unsigned short ver;     /* VER  0xe8/0xe9 reg.  */
+       unsigned short sn;      /* SN   0xea/0xeb reg.  */
+       unsigned char wia;      /* WIA  0x0f      reg.  */
+};
+
+/** AMI Driver Information  */
+struct ami_driverinfo {
+       unsigned char remarks[40];      /* Some Information   */
+       unsigned char datetime[30];     /* compiled date&time */
+       unsigned char ver_major;        /* major version */
+       unsigned char ver_middle;       /* middle.. */
+       unsigned char ver_minor;        /* minor .. */
+};
+
+#endif
diff --git a/drivers/misc/inv_mpu/compass/hmc5883.c b/drivers/misc/inv_mpu/compass/hmc5883.c
new file mode 100644 (file)
index 0000000..fdf2ac0
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup COMPASSDL
+ *
+ *  @{
+ *      @file   hmc5883.c
+ *      @brief  Magnetometer setup and handling methods for Honeywell
+ *              HMC5883 compass.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/* -------------------------------------------------------------------------- */
+enum HMC_REG {
+       HMC_REG_CONF_A = 0x0,
+       HMC_REG_CONF_B = 0x1,
+       HMC_REG_MODE = 0x2,
+       HMC_REG_X_M = 0x3,
+       HMC_REG_X_L = 0x4,
+       HMC_REG_Z_M = 0x5,
+       HMC_REG_Z_L = 0x6,
+       HMC_REG_Y_M = 0x7,
+       HMC_REG_Y_L = 0x8,
+       HMC_REG_STATUS = 0x9,
+       HMC_REG_ID_A = 0xA,
+       HMC_REG_ID_B = 0xB,
+       HMC_REG_ID_C = 0xC
+};
+
+enum HMC_CONF_A {
+       HMC_CONF_A_DRATE_MASK = 0x1C,
+       HMC_CONF_A_DRATE_0_75 = 0x00,
+       HMC_CONF_A_DRATE_1_5 = 0x04,
+       HMC_CONF_A_DRATE_3 = 0x08,
+       HMC_CONF_A_DRATE_7_5 = 0x0C,
+       HMC_CONF_A_DRATE_15 = 0x10,
+       HMC_CONF_A_DRATE_30 = 0x14,
+       HMC_CONF_A_DRATE_75 = 0x18,
+       HMC_CONF_A_MEAS_MASK = 0x3,
+       HMC_CONF_A_MEAS_NORM = 0x0,
+       HMC_CONF_A_MEAS_POS = 0x1,
+       HMC_CONF_A_MEAS_NEG = 0x2
+};
+
+enum HMC_CONF_B {
+       HMC_CONF_B_GAIN_MASK = 0xE0,
+       HMC_CONF_B_GAIN_0_9 = 0x00,
+       HMC_CONF_B_GAIN_1_2 = 0x20,
+       HMC_CONF_B_GAIN_1_9 = 0x40,
+       HMC_CONF_B_GAIN_2_5 = 0x60,
+       HMC_CONF_B_GAIN_4_0 = 0x80,
+       HMC_CONF_B_GAIN_4_6 = 0xA0,
+       HMC_CONF_B_GAIN_5_5 = 0xC0,
+       HMC_CONF_B_GAIN_7_9 = 0xE0
+};
+
+enum HMC_MODE {
+       HMC_MODE_MASK = 0x3,
+       HMC_MODE_CONT = 0x0,
+       HMC_MODE_SINGLE = 0x1,
+       HMC_MODE_IDLE = 0x2,
+       HMC_MODE_SLEEP = 0x3
+};
+
+/* -------------------------------------------------------------------------- */
+static int hmc5883_suspend(void *mlsl_handle,
+                          struct ext_slave_descr *slave,
+                          struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   HMC_REG_MODE, HMC_MODE_SLEEP);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(3);
+
+       return result;
+}
+
+static int hmc5883_resume(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       /* Use single measurement mode. Start at sleep state. */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   HMC_REG_MODE, HMC_MODE_SLEEP);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Config normal measurement */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   HMC_REG_CONF_A, 0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Adjust gain to 307 LSB/Gauss */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   HMC_REG_CONF_B, HMC_CONF_B_GAIN_5_5);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+static int hmc5883_read(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       unsigned char *data)
+{
+       unsigned char stat;
+       int result = INV_SUCCESS;
+       unsigned char tmp;
+       short axisFixed;
+
+       /* Read status reg. to check if data is ready */
+       result =
+           inv_serial_read(mlsl_handle, pdata->address, HMC_REG_STATUS, 1,
+                           &stat);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       if (stat & 0x01) {
+               result =
+                   inv_serial_read(mlsl_handle, pdata->address,
+                                   HMC_REG_X_M, 6, (unsigned char *)data);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+
+               /* switch YZ axis to proper position */
+               tmp = data[2];
+               data[2] = data[4];
+               data[4] = tmp;
+               tmp = data[3];
+               data[3] = data[5];
+               data[5] = tmp;
+
+               /*drop data if overflows */
+               if ((data[0] == 0xf0) || (data[2] == 0xf0)
+                   || (data[4] == 0xf0)) {
+                       /* trigger next measurement read */
+                       result =
+                           inv_serial_single_write(mlsl_handle,
+                                                   pdata->address,
+                                                   HMC_REG_MODE,
+                                                   HMC_MODE_SINGLE);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       return INV_ERROR_COMPASS_DATA_OVERFLOW;
+               }
+               /* convert to fixed point and apply sensitivity correction for
+                  Z-axis */
+               axisFixed =
+                   (short)((unsigned short)data[5] +
+                           (unsigned short)data[4] * 256);
+               /* scale up by 1.125 (36/32) */
+               axisFixed = (short)(axisFixed * 36);
+               data[4] = axisFixed >> 8;
+               data[5] = axisFixed & 0xFF;
+
+               axisFixed =
+                   (short)((unsigned short)data[3] +
+                           (unsigned short)data[2] * 256);
+               axisFixed = (short)(axisFixed * 32);
+               data[2] = axisFixed >> 8;
+               data[3] = axisFixed & 0xFF;
+
+               axisFixed =
+                   (short)((unsigned short)data[1] +
+                           (unsigned short)data[0] * 256);
+               axisFixed = (short)(axisFixed * 32);
+               data[0] = axisFixed >> 8;
+               data[1] = axisFixed & 0xFF;
+
+               /* trigger next measurement read */
+               result =
+                   inv_serial_single_write(mlsl_handle, pdata->address,
+                                           HMC_REG_MODE, HMC_MODE_SINGLE);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+
+               return INV_SUCCESS;
+       } else {
+               /* trigger next measurement read */
+               result =
+                   inv_serial_single_write(mlsl_handle, pdata->address,
+                                           HMC_REG_MODE, HMC_MODE_SINGLE);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+
+               return INV_ERROR_COMPASS_DATA_NOT_READY;
+       }
+}
+
+static struct ext_slave_descr hmc5883_descr = {
+       .init             = NULL,
+       .exit             = NULL,
+       .suspend          = hmc5883_suspend,
+       .resume           = hmc5883_resume,
+       .read             = hmc5883_read,
+       .config           = NULL,
+       .get_config       = NULL,
+       .name             = "hmc5883",
+       .type             = EXT_SLAVE_TYPE_COMPASS,
+       .id               = COMPASS_ID_HMC5883,
+       .read_reg         = 0x06,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_BIG_ENDIAN,
+       .range            = {10673, 6156},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *hmc5883_get_slave_descr(void)
+{
+       return &hmc5883_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct hmc5883_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int hmc5883_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct hmc5883_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       hmc5883_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int hmc5883_mod_remove(struct i2c_client *client)
+{
+       struct hmc5883_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               hmc5883_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id hmc5883_mod_id[] = {
+       { "hmc5883", COMPASS_ID_HMC5883 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, hmc5883_mod_id);
+
+static struct i2c_driver hmc5883_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = hmc5883_mod_probe,
+       .remove = hmc5883_mod_remove,
+       .id_table = hmc5883_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "hmc5883_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init hmc5883_mod_init(void)
+{
+       int res = i2c_add_driver(&hmc5883_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "hmc5883_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit hmc5883_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&hmc5883_mod_driver);
+}
+
+module_init(hmc5883_mod_init);
+module_exit(hmc5883_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate HMC5883 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("hmc5883_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/compass/hscdtd002b.c b/drivers/misc/inv_mpu/compass/hscdtd002b.c
new file mode 100644 (file)
index 0000000..4f6013c
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup COMPASSDL
+ *
+ *  @{
+ *      @file   hscdtd002b.c
+ *      @brief  Magnetometer setup and handling methods for Alps HSCDTD002B
+ *              compass.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/* -------------------------------------------------------------------------- */
+#define COMPASS_HSCDTD002B_STAT          (0x18)
+#define COMPASS_HSCDTD002B_CTRL1         (0x1B)
+#define COMPASS_HSCDTD002B_CTRL2         (0x1C)
+#define COMPASS_HSCDTD002B_CTRL3         (0x1D)
+#define COMPASS_HSCDTD002B_DATAX         (0x10)
+
+/* -------------------------------------------------------------------------- */
+static int hscdtd002b_suspend(void *mlsl_handle,
+                             struct ext_slave_descr *slave,
+                             struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       /* Power mode: stand-by */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD002B_CTRL1, 0x00);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(1);              /* turn-off time */
+
+       return result;
+}
+
+static int hscdtd002b_resume(void *mlsl_handle,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       /* Soft reset */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD002B_CTRL3, 0x80);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Force state; Power mode: active */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD002B_CTRL1, 0x82);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Data ready enable */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD002B_CTRL2, 0x08);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(1);              /* turn-on time */
+
+       return result;
+}
+
+static int hscdtd002b_read(void *mlsl_handle,
+                          struct ext_slave_descr *slave,
+                          struct ext_slave_platform_data *pdata,
+                          unsigned char *data)
+{
+       unsigned char stat;
+       int result = INV_SUCCESS;
+       int status = INV_SUCCESS;
+
+       /* Read status reg. to check if data is ready */
+       result =
+           inv_serial_read(mlsl_handle, pdata->address,
+                           COMPASS_HSCDTD002B_STAT, 1, &stat);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       if (stat & 0x40) {
+               result =
+                   inv_serial_read(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD002B_DATAX, 6,
+                                   (unsigned char *)data);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               status = INV_SUCCESS;
+       } else if (stat & 0x20) {
+               status = INV_ERROR_COMPASS_DATA_OVERFLOW;
+       } else {
+               status = INV_ERROR_COMPASS_DATA_NOT_READY;
+       }
+       /* trigger next measurement read */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD002B_CTRL3, 0x40);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return status;
+}
+
+static struct ext_slave_descr hscdtd002b_descr = {
+       .init             = NULL,
+       .exit             = NULL,
+       .suspend          = hscdtd002b_suspend,
+       .resume           = hscdtd002b_resume,
+       .read             = hscdtd002b_read,
+       .config           = NULL,
+       .get_config       = NULL,
+       .name             = "hscdtd002b",
+       .type             = EXT_SLAVE_TYPE_COMPASS,
+       .id               = COMPASS_ID_HSCDTD002B,
+       .read_reg         = 0x10,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {9830, 4000},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *hscdtd002b_get_slave_descr(void)
+{
+       return &hscdtd002b_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct hscdtd002b_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int hscdtd002b_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct hscdtd002b_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       hscdtd002b_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int hscdtd002b_mod_remove(struct i2c_client *client)
+{
+       struct hscdtd002b_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               hscdtd002b_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id hscdtd002b_mod_id[] = {
+       { "hscdtd002b", COMPASS_ID_HSCDTD002B },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, hscdtd002b_mod_id);
+
+static struct i2c_driver hscdtd002b_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = hscdtd002b_mod_probe,
+       .remove = hscdtd002b_mod_remove,
+       .id_table = hscdtd002b_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "hscdtd002b_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init hscdtd002b_mod_init(void)
+{
+       int res = i2c_add_driver(&hscdtd002b_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "hscdtd002b_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit hscdtd002b_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&hscdtd002b_mod_driver);
+}
+
+module_init(hscdtd002b_mod_init);
+module_exit(hscdtd002b_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate HSCDTD002B sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("hscdtd002b_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/compass/hscdtd004a.c b/drivers/misc/inv_mpu/compass/hscdtd004a.c
new file mode 100644 (file)
index 0000000..f091559
--- /dev/null
@@ -0,0 +1,318 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup COMPASSDL
+ *
+ *  @{
+ *      @file   hscdtd004a.c
+ *      @brief  Magnetometer setup and handling methods for Alps HSCDTD004A
+ *              compass.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/* -------------------------------------------------------------------------- */
+#define COMPASS_HSCDTD004A_STAT          (0x18)
+#define COMPASS_HSCDTD004A_CTRL1         (0x1B)
+#define COMPASS_HSCDTD004A_CTRL2         (0x1C)
+#define COMPASS_HSCDTD004A_CTRL3         (0x1D)
+#define COMPASS_HSCDTD004A_DATAX         (0x10)
+
+/* -------------------------------------------------------------------------- */
+
+static int hscdtd004a_suspend(void *mlsl_handle,
+                             struct ext_slave_descr *slave,
+                             struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       /* Power mode: stand-by */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD004A_CTRL1, 0x00);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(1);              /* turn-off time */
+
+       return result;
+}
+
+static int hscdtd004a_init(void *mlsl_handle,
+                          struct ext_slave_descr *slave,
+                          struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char data1, data2[2];
+
+       result = inv_serial_read(mlsl_handle, pdata->address, 0xf, 1, &data1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(mlsl_handle, pdata->address, 0xd, 2, data2);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       if (data1 != 0x49 || data2[0] != 0x45 || data2[1] != 0x54) {
+               LOG_RESULT_LOCATION(INV_ERROR_SERIAL_DEVICE_NOT_RECOGNIZED);
+               return INV_ERROR_SERIAL_DEVICE_NOT_RECOGNIZED;
+       }
+       return result;
+}
+
+static int hscdtd004a_resume(void *mlsl_handle,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       /* Soft reset */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD004A_CTRL3, 0x80);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Normal state; Power mode: active */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD004A_CTRL1, 0x82);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Data ready enable */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD004A_CTRL2, 0x7C);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(1);              /* turn-on time */
+       return result;
+}
+
+static int hscdtd004a_read(void *mlsl_handle,
+                          struct ext_slave_descr *slave,
+                          struct ext_slave_platform_data *pdata,
+                          unsigned char *data)
+{
+       unsigned char stat;
+       int result = INV_SUCCESS;
+       int status = INV_SUCCESS;
+
+       /* Read status reg. to check if data is ready */
+       result =
+           inv_serial_read(mlsl_handle, pdata->address,
+                           COMPASS_HSCDTD004A_STAT, 1, &stat);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       if (stat & 0x48) {
+               result =
+                   inv_serial_read(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD004A_DATAX, 6,
+                                   (unsigned char *)data);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               status = INV_SUCCESS;
+       } else if (stat & 0x68) {
+               status = INV_ERROR_COMPASS_DATA_OVERFLOW;
+       } else {
+               status = INV_ERROR_COMPASS_DATA_NOT_READY;
+       }
+       /* trigger next measurement read */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   COMPASS_HSCDTD004A_CTRL3, 0x40);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return status;
+
+}
+
+static struct ext_slave_descr hscdtd004a_descr = {
+       .init             = hscdtd004a_init,
+       .exit             = NULL,
+       .suspend          = hscdtd004a_suspend,
+       .resume           = hscdtd004a_resume,
+       .read             = hscdtd004a_read,
+       .config           = NULL,
+       .get_config       = NULL,
+       .name             = "hscdtd004a",
+       .type             = EXT_SLAVE_TYPE_COMPASS,
+       .id               = COMPASS_ID_HSCDTD004A,
+       .read_reg         = 0x10,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_LITTLE_ENDIAN,
+       .range            = {9830, 4000},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *hscdtd004a_get_slave_descr(void)
+{
+       return &hscdtd004a_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct hscdtd004a_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int hscdtd004a_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct hscdtd004a_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       hscdtd004a_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int hscdtd004a_mod_remove(struct i2c_client *client)
+{
+       struct hscdtd004a_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               hscdtd004a_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id hscdtd004a_mod_id[] = {
+       { "hscdtd004a", COMPASS_ID_HSCDTD004A },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, hscdtd004a_mod_id);
+
+static struct i2c_driver hscdtd004a_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = hscdtd004a_mod_probe,
+       .remove = hscdtd004a_mod_remove,
+       .id_table = hscdtd004a_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "hscdtd004a_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init hscdtd004a_mod_init(void)
+{
+       int res = i2c_add_driver(&hscdtd004a_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "hscdtd004a_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit hscdtd004a_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&hscdtd004a_mod_driver);
+}
+
+module_init(hscdtd004a_mod_init);
+module_exit(hscdtd004a_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate HSCDTD004A sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("hscdtd004a_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/compass/lsm303dlx_m.c b/drivers/misc/inv_mpu/compass/lsm303dlx_m.c
new file mode 100644 (file)
index 0000000..32f8cdd
--- /dev/null
@@ -0,0 +1,395 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup COMPASSDL
+ *
+ *  @{
+ *      @file   lsm303dlx_m.c
+ *      @brief  Magnetometer setup and handling methods for ST LSM303
+ *              compass.
+ *              This magnetometer device is part of a combo chip with the
+ *              ST LIS331DLH accelerometer and the logic in entirely based
+ *              on the Honeywell HMC5883 magnetometer.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/* -------------------------------------------------------------------------- */
+enum LSM_REG {
+       LSM_REG_CONF_A = 0x0,
+       LSM_REG_CONF_B = 0x1,
+       LSM_REG_MODE = 0x2,
+       LSM_REG_X_M = 0x3,
+       LSM_REG_X_L = 0x4,
+       LSM_REG_Z_M = 0x5,
+       LSM_REG_Z_L = 0x6,
+       LSM_REG_Y_M = 0x7,
+       LSM_REG_Y_L = 0x8,
+       LSM_REG_STATUS = 0x9,
+       LSM_REG_ID_A = 0xA,
+       LSM_REG_ID_B = 0xB,
+       LSM_REG_ID_C = 0xC
+};
+
+enum LSM_CONF_A {
+       LSM_CONF_A_DRATE_MASK = 0x1C,
+       LSM_CONF_A_DRATE_0_75 = 0x00,
+       LSM_CONF_A_DRATE_1_5 = 0x04,
+       LSM_CONF_A_DRATE_3 = 0x08,
+       LSM_CONF_A_DRATE_7_5 = 0x0C,
+       LSM_CONF_A_DRATE_15 = 0x10,
+       LSM_CONF_A_DRATE_30 = 0x14,
+       LSM_CONF_A_DRATE_75 = 0x18,
+       LSM_CONF_A_MEAS_MASK = 0x3,
+       LSM_CONF_A_MEAS_NORM = 0x0,
+       LSM_CONF_A_MEAS_POS = 0x1,
+       LSM_CONF_A_MEAS_NEG = 0x2
+};
+
+enum LSM_CONF_B {
+       LSM_CONF_B_GAIN_MASK = 0xE0,
+       LSM_CONF_B_GAIN_0_9 = 0x00,
+       LSM_CONF_B_GAIN_1_2 = 0x20,
+       LSM_CONF_B_GAIN_1_9 = 0x40,
+       LSM_CONF_B_GAIN_2_5 = 0x60,
+       LSM_CONF_B_GAIN_4_0 = 0x80,
+       LSM_CONF_B_GAIN_4_6 = 0xA0,
+       LSM_CONF_B_GAIN_5_5 = 0xC0,
+       LSM_CONF_B_GAIN_7_9 = 0xE0
+};
+
+enum LSM_MODE {
+       LSM_MODE_MASK = 0x3,
+       LSM_MODE_CONT = 0x0,
+       LSM_MODE_SINGLE = 0x1,
+       LSM_MODE_IDLE = 0x2,
+       LSM_MODE_SLEEP = 0x3
+};
+
+/* -------------------------------------------------------------------------- */
+
+static int lsm303dlx_m_suspend(void *mlsl_handle,
+                             struct ext_slave_descr *slave,
+                             struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   LSM_REG_MODE, LSM_MODE_SLEEP);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(3);
+
+       return result;
+}
+
+static int lsm303dlx_m_resume(void *mlsl_handle,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       /* Use single measurement mode. Start at sleep state. */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   LSM_REG_MODE, LSM_MODE_SLEEP);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Config normal measurement */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   LSM_REG_CONF_A, 0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Adjust gain to 320 LSB/Gauss */
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   LSM_REG_CONF_B, LSM_CONF_B_GAIN_5_5);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+static int lsm303dlx_m_read(void *mlsl_handle,
+                          struct ext_slave_descr *slave,
+                          struct ext_slave_platform_data *pdata,
+                          unsigned char *data)
+{
+       unsigned char stat;
+       int result = INV_SUCCESS;
+       short axis_fixed;
+
+       /* Read status reg. to check if data is ready */
+       result =
+           inv_serial_read(mlsl_handle, pdata->address, LSM_REG_STATUS, 1,
+                           &stat);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       if (stat & 0x01) {
+               result =
+                   inv_serial_read(mlsl_handle, pdata->address,
+                                   LSM_REG_X_M, 6, (unsigned char *)data);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+
+               /*drop data if overflows */
+               if ((data[0] == 0xf0) || (data[2] == 0xf0)
+                   || (data[4] == 0xf0)) {
+                       /* trigger next measurement read */
+                       result =
+                           inv_serial_single_write(mlsl_handle,
+                                                   pdata->address,
+                                                   LSM_REG_MODE,
+                                                   LSM_MODE_SINGLE);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       return INV_ERROR_COMPASS_DATA_OVERFLOW;
+               }
+               /* convert to fixed point and apply sensitivity correction for
+                  Z-axis */
+               axis_fixed =
+                   (short)((unsigned short)data[5] +
+                           (unsigned short)data[4] * 256);
+               /* scale up by 1.125 (36/32) approximate of 1.122 (320/285) */
+               if (slave->id == COMPASS_ID_LSM303DLM) {
+                       /* NOTE/IMPORTANT:
+                          lsm303dlm compass axis definition doesn't
+                          respect the right hand rule. We invert
+                          the sign of the Z axis to fix that. */
+                       axis_fixed = (short)(-1 * axis_fixed * 36);
+               } else {
+                       axis_fixed = (short)(axis_fixed * 36);
+               }
+               data[4] = axis_fixed >> 8;
+               data[5] = axis_fixed & 0xFF;
+
+               axis_fixed =
+                   (short)((unsigned short)data[3] +
+                           (unsigned short)data[2] * 256);
+               axis_fixed = (short)(axis_fixed * 32);
+               data[2] = axis_fixed >> 8;
+               data[3] = axis_fixed & 0xFF;
+
+               axis_fixed =
+                   (short)((unsigned short)data[1] +
+                           (unsigned short)data[0] * 256);
+               axis_fixed = (short)(axis_fixed * 32);
+               data[0] = axis_fixed >> 8;
+               data[1] = axis_fixed & 0xFF;
+
+               /* trigger next measurement read */
+               result =
+                   inv_serial_single_write(mlsl_handle, pdata->address,
+                                           LSM_REG_MODE, LSM_MODE_SINGLE);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+
+               return INV_SUCCESS;
+       } else {
+               /* trigger next measurement read */
+               result =
+                   inv_serial_single_write(mlsl_handle, pdata->address,
+                                           LSM_REG_MODE, LSM_MODE_SINGLE);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+
+               return INV_ERROR_COMPASS_DATA_NOT_READY;
+       }
+}
+
+static struct ext_slave_descr lsm303dlx_m_descr = {
+       .init             = NULL,
+       .exit             = NULL,
+       .suspend          = lsm303dlx_m_suspend,
+       .resume           = lsm303dlx_m_resume,
+       .read             = lsm303dlx_m_read,
+       .config           = NULL,
+       .get_config       = NULL,
+       .name             = "lsm303dlx_m",
+       .type             = EXT_SLAVE_TYPE_COMPASS,
+       .id               = ID_INVALID,
+       .read_reg         = 0x06,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_BIG_ENDIAN,
+       .range            = {10240, 0},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *lsm303dlx_m_get_slave_descr(void)
+{
+       return &lsm303dlx_m_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct lsm303dlx_m_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static const struct i2c_device_id lsm303dlx_m_mod_id[] = {
+       { "lsm303dlh", COMPASS_ID_LSM303DLH },
+       { "lsm303dlm", COMPASS_ID_LSM303DLM },
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, lsm303dlx_m_mod_id);
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int lsm303dlx_m_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct lsm303dlx_m_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+       lsm303dlx_m_descr.id = devid->driver_data;
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       lsm303dlx_m_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int lsm303dlx_m_mod_remove(struct i2c_client *client)
+{
+       struct lsm303dlx_m_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               lsm303dlx_m_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static struct i2c_driver lsm303dlx_m_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = lsm303dlx_m_mod_probe,
+       .remove = lsm303dlx_m_mod_remove,
+       .id_table = lsm303dlx_m_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "lsm303dlx_m_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init lsm303dlx_m_mod_init(void)
+{
+       int res = i2c_add_driver(&lsm303dlx_m_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "lsm303dlx_m_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit lsm303dlx_m_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&lsm303dlx_m_mod_driver);
+}
+
+module_init(lsm303dlx_m_mod_init);
+module_exit(lsm303dlx_m_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate lsm303dlx_m sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("lsm303dlx_m_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/compass/mmc314x.c b/drivers/misc/inv_mpu/compass/mmc314x.c
new file mode 100644 (file)
index 0000000..786fadc
--- /dev/null
@@ -0,0 +1,313 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup COMPASSDL
+ *
+ *  @{
+ *      @file   mmc314x.c
+ *      @brief  Magnetometer setup and handling methods for the
+ *              MEMSIC MMC314x compass.
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/* -------------------------------------------------------------------------- */
+
+static int reset_int = 1000;
+static int read_count = 1;
+static char reset_mode;                /* in Z-init section */
+
+/* -------------------------------------------------------------------------- */
+#define MMC314X_REG_ST (0x00)
+#define MMC314X_REG_X_MSB (0x01)
+
+#define MMC314X_CNTL_MODE_WAKE_UP (0x01)
+#define MMC314X_CNTL_MODE_SET (0x02)
+#define MMC314X_CNTL_MODE_RESET (0x04)
+
+/* -------------------------------------------------------------------------- */
+
+static int mmc314x_suspend(void *mlsl_handle,
+                          struct ext_slave_descr *slave,
+                          struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       return result;
+}
+
+static int mmc314x_resume(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+
+       int result;
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   MMC314X_REG_ST, MMC314X_CNTL_MODE_RESET);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(10);
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   MMC314X_REG_ST, MMC314X_CNTL_MODE_SET);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(10);
+       read_count = 1;
+       return INV_SUCCESS;
+}
+
+static int mmc314x_read(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       unsigned char *data)
+{
+       int result, ii;
+       short tmp[3];
+       unsigned char tmpdata[6];
+
+       if (read_count > 1000)
+               read_count = 1;
+
+       result =
+           inv_serial_read(mlsl_handle, pdata->address, MMC314X_REG_X_MSB,
+                           6, (unsigned char *)data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       for (ii = 0; ii < 6; ii++)
+               tmpdata[ii] = data[ii];
+
+       for (ii = 0; ii < 3; ii++) {
+               tmp[ii] = (short)((tmpdata[2 * ii] << 8) + tmpdata[2 * ii + 1]);
+               tmp[ii] = tmp[ii] - 4096;
+               tmp[ii] = tmp[ii] * 16;
+       }
+
+       for (ii = 0; ii < 3; ii++) {
+               data[2 * ii] = (unsigned char)(tmp[ii] >> 8);
+               data[2 * ii + 1] = (unsigned char)(tmp[ii]);
+       }
+
+       if (read_count % reset_int == 0) {
+               if (reset_mode) {
+                       result =
+                           inv_serial_single_write(mlsl_handle,
+                                                   pdata->address,
+                                                   MMC314X_REG_ST,
+                                                   MMC314X_CNTL_MODE_RESET);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       reset_mode = 0;
+                       return INV_ERROR_COMPASS_DATA_NOT_READY;
+               } else {
+                       result =
+                           inv_serial_single_write(mlsl_handle,
+                                                   pdata->address,
+                                                   MMC314X_REG_ST,
+                                                   MMC314X_CNTL_MODE_SET);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       reset_mode = 1;
+                       read_count++;
+                       return INV_ERROR_COMPASS_DATA_NOT_READY;
+               }
+       }
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   MMC314X_REG_ST, MMC314X_CNTL_MODE_WAKE_UP);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       read_count++;
+
+       return INV_SUCCESS;
+}
+
+static struct ext_slave_descr mmc314x_descr = {
+       .init             = NULL,
+       .exit             = NULL,
+       .suspend          = mmc314x_suspend,
+       .resume           = mmc314x_resume,
+       .read             = mmc314x_read,
+       .config           = NULL,
+       .get_config       = NULL,
+       .name             = "mmc314x",
+       .type             = EXT_SLAVE_TYPE_COMPASS,
+       .id               = COMPASS_ID_MMC314X,
+       .read_reg         = 0x01,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_BIG_ENDIAN,
+       .range            = {400, 0},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *mmc314x_get_slave_descr(void)
+{
+       return &mmc314x_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct mmc314x_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int mmc314x_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct mmc314x_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       mmc314x_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int mmc314x_mod_remove(struct i2c_client *client)
+{
+       struct mmc314x_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               mmc314x_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id mmc314x_mod_id[] = {
+       { "mmc314x", COMPASS_ID_MMC314X },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, mmc314x_mod_id);
+
+static struct i2c_driver mmc314x_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = mmc314x_mod_probe,
+       .remove = mmc314x_mod_remove,
+       .id_table = mmc314x_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "mmc314x_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init mmc314x_mod_init(void)
+{
+       int res = i2c_add_driver(&mmc314x_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "mmc314x_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit mmc314x_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&mmc314x_mod_driver);
+}
+
+module_init(mmc314x_mod_init);
+module_exit(mmc314x_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate MMC314X sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("mmc314x_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/compass/yas529-kernel.c b/drivers/misc/inv_mpu/compass/yas529-kernel.c
new file mode 100644 (file)
index 0000000..f53223f
--- /dev/null
@@ -0,0 +1,611 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <log.h>
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-acc"
+
+/*----- YAMAHA YAS529 Registers ------*/
+enum YAS_REG {
+       YAS_REG_CMDR            = 0x00, /* 000 < 5 */
+       YAS_REG_XOFFSETR        = 0x20, /* 001 < 5 */
+       YAS_REG_Y1OFFSETR       = 0x40, /* 010 < 5 */
+       YAS_REG_Y2OFFSETR       = 0x60, /* 011 < 5 */
+       YAS_REG_ICOILR          = 0x80, /* 100 < 5 */
+       YAS_REG_CAL             = 0xA0, /* 101 < 5 */
+       YAS_REG_CONFR           = 0xC0, /* 110 < 5 */
+       YAS_REG_DOUTR           = 0xE0  /* 111 < 5 */
+};
+
+/* -------------------------------------------------------------------------- */
+
+static long a1;
+static long a2;
+static long a3;
+static long a4;
+static long a5;
+static long a6;
+static long a7;
+static long a8;
+static long a9;
+
+/* -------------------------------------------------------------------------- */
+static int yas529_sensor_i2c_write(struct i2c_adapter *i2c_adap,
+                                  unsigned char address,
+                                  unsigned int len, unsigned char *data)
+{
+       struct i2c_msg msgs[1];
+       int res;
+
+       if (NULL == data || NULL == i2c_adap)
+               return -EINVAL;
+
+       msgs[0].addr = address;
+       msgs[0].flags = 0;      /* write */
+       msgs[0].buf = (unsigned char *)data;
+       msgs[0].len = len;
+
+       res = i2c_transfer(i2c_adap, msgs, 1);
+       if (res < 1)
+               return res;
+       else
+               return 0;
+}
+
+static int yas529_sensor_i2c_read(struct i2c_adapter *i2c_adap,
+                                 unsigned char address,
+                                 unsigned char reg,
+                                 unsigned int len, unsigned char *data)
+{
+       struct i2c_msg msgs[2];
+       int res;
+
+       if (NULL == data || NULL == i2c_adap)
+               return -EINVAL;
+
+       msgs[0].addr = address;
+       msgs[0].flags = I2C_M_RD;
+       msgs[0].buf = data;
+       msgs[0].len = len;
+
+       res = i2c_transfer(i2c_adap, msgs, 1);
+       if (res < 1)
+               return res;
+       else
+               return 0;
+}
+
+static int yas529_suspend(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       return result;
+}
+
+static int yas529_resume(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       unsigned char dummyData[1] = { 0 };
+       unsigned char dummyRegister = 0;
+       unsigned char rawData[6];
+       unsigned char calData[9];
+
+       short xoffset, y1offset, y2offset;
+       short d2, d3, d4, d5, d6, d7, d8, d9;
+
+       /* YAS529 Application Manual MS-3C - Section 4.4.5 */
+       /* =============================================== */
+       /* Step 1 - register initialization */
+       /* zero initialization coil register - "100 00 000" */
+       dummyData[0] = YAS_REG_ICOILR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* zero config register - "110 00 000" */
+       dummyData[0] = YAS_REG_CONFR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Step 2 - initialization coil operation */
+       dummyData[0] = YAS_REG_ICOILR | 0x11;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x01;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x12;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x02;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x13;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x03;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x14;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x04;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x15;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x05;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x16;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x06;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x17;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x07;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x10;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_ICOILR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Step 3 - rough offset measurement */
+       /* Config register - Measurements results - "110 00 000" */
+       dummyData[0] = YAS_REG_CONFR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Measurements command register - Rough offset measurement -
+          "000 00001" */
+       dummyData[0] = YAS_REG_CMDR | 0x01;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(2);              /* wait at least 1.5ms */
+
+       /* Measurement data read */
+       result =
+           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
+                                  dummyRegister, 6, rawData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       xoffset =
+           (short)((unsigned short)rawData[5] +
+                   ((unsigned short)rawData[4] & 0x7) * 256) - 5;
+       if (xoffset < 0)
+               xoffset = 0;
+       y1offset =
+           (short)((unsigned short)rawData[3] +
+                   ((unsigned short)rawData[2] & 0x7) * 256) - 5;
+       if (y1offset < 0)
+               y1offset = 0;
+       y2offset =
+           (short)((unsigned short)rawData[1] +
+                   ((unsigned short)rawData[0] & 0x7) * 256) - 5;
+       if (y2offset < 0)
+               y2offset = 0;
+
+       /* Step 4 - rough offset setting */
+       /* Set rough offset register values */
+       dummyData[0] = YAS_REG_XOFFSETR | xoffset;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_Y1OFFSETR | y1offset;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       dummyData[0] = YAS_REG_Y2OFFSETR | y2offset;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* CAL matrix read (first read is invalid) */
+       /* Config register - CAL register read - "110 01 000" */
+       dummyData[0] = YAS_REG_CONFR | 0x08;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* CAL data read */
+       result =
+           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
+                                  dummyRegister, 9, calData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Config register - CAL register read - "110 01 000" */
+       dummyData[0] = YAS_REG_CONFR | 0x08;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* CAL data read */
+       result =
+           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
+                                  dummyRegister, 9, calData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Calculate coefficients of the sensitivity correction matrix */
+       a1 = 100;
+       d2 = (calData[0] & 0xFC) >> 2;  /* [71..66] 6bit */
+       a2 = (short)(d2 - 32);
+       /* [65..62] 4bit */
+       d3 = ((calData[0] & 0x03) << 2) | ((calData[1] & 0xC0) >> 6);
+       a3 = (short)(d3 - 8);
+       d4 = (calData[1] & 0x3F);       /* [61..56] 6bit */
+       a4 = (short)(d4 - 32);
+       d5 = (calData[2] & 0xFC) >> 2;  /* [55..50] 6bit */
+       a5 = (short)(d5 - 32) + 70;
+       /* [49..44] 6bit */
+       d6 = ((calData[2] & 0x03) << 4) | ((calData[3] & 0xF0) >> 4);
+       a6 = (short)(d6 - 32);
+       /* [43..38] 6bit */
+       d7 = ((calData[3] & 0x0F) << 2) | ((calData[4] & 0xC0) >> 6);
+       a7 = (short)(d7 - 32);
+       d8 = (calData[4] & 0x3F);       /* [37..32] 6bit */
+       a8 = (short)(d8 - 32);
+       d9 = (calData[5] & 0xFE) >> 1;  /* [31..25] 7bit */
+       a9 = (short)(d9 - 64) + 130;
+
+       return result;
+}
+
+static int yas529_read(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata,
+                      unsigned char *data)
+{
+       unsigned char stat;
+       unsigned char rawData[6];
+       unsigned char dummyData[1] = { 0 };
+       unsigned char dummyRegister = 0;
+       int result = INV_SUCCESS;
+       short SX, SY1, SY2, SY, SZ;
+       short row1fixed, row2fixed, row3fixed;
+
+       /* Config register - Measurements results - "110 00 000" */
+       dummyData[0] = YAS_REG_CONFR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Measurements command register - Normal magnetic field measurement -
+          "000 00000" */
+       dummyData[0] = YAS_REG_CMDR | 0x00;
+       result =
+           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       msleep(10);
+       /* Measurement data read */
+       result =
+           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
+                                  dummyRegister, 6, (unsigned char *)&rawData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       stat = rawData[0] & 0x80;
+       if (stat == 0x00) {
+               /* Extract raw data */
+               SX = (short)((unsigned short)rawData[5] +
+                            ((unsigned short)rawData[4] & 0x7) * 256);
+               SY1 =
+                   (short)((unsigned short)rawData[3] +
+                           ((unsigned short)rawData[2] & 0x7) * 256);
+               SY2 =
+                   (short)((unsigned short)rawData[1] +
+                           ((unsigned short)rawData[0] & 0x7) * 256);
+               if ((SX <= 1) || (SY1 <= 1) || (SY2 <= 1))
+                       return INV_ERROR_COMPASS_DATA_UNDERFLOW;
+               if ((SX >= 1024) || (SY1 >= 1024) || (SY2 >= 1024))
+                       return INV_ERROR_COMPASS_DATA_OVERFLOW;
+               /* Convert to XYZ axis */
+               SX = -1 * SX;
+               SY = SY2 - SY1;
+               SZ = SY1 + SY2;
+
+               /* Apply sensitivity correction matrix */
+               row1fixed = (short)((a1 * SX + a2 * SY + a3 * SZ) >> 7) * 41;
+               row2fixed = (short)((a4 * SX + a5 * SY + a6 * SZ) >> 7) * 41;
+               row3fixed = (short)((a7 * SX + a8 * SY + a9 * SZ) >> 7) * 41;
+
+               data[0] = row1fixed >> 8;
+               data[1] = row1fixed & 0xFF;
+               data[2] = row2fixed >> 8;
+               data[3] = row2fixed & 0xFF;
+               data[4] = row3fixed >> 8;
+               data[5] = row3fixed & 0xFF;
+
+               return INV_SUCCESS;
+       } else {
+               return INV_ERROR_COMPASS_DATA_NOT_READY;
+       }
+}
+
+static struct ext_slave_descr yas529_descr = {
+       .init             = NULL,
+       .exit             = NULL,
+       .suspend          = yas529_suspend,
+       .resume           = yas529_resume,
+       .read             = yas529_read,
+       .config           = NULL,
+       .get_config       = NULL,
+       .name             = "yas529",
+       .type             = EXT_SLAVE_TYPE_COMPASS,
+       .id               = COMPASS_ID_YAS529,
+       .read_reg         = 0x06,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_BIG_ENDIAN,
+       .range            = {19660, 8000},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *yas529_get_slave_descr(void)
+{
+       return &yas529_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct yas529_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int yas529_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct yas529_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       yas529_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int yas529_mod_remove(struct i2c_client *client)
+{
+       struct yas529_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               yas529_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id yas529_mod_id[] = {
+       { "yas529", COMPASS_ID_YAS529 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, yas529_mod_id);
+
+static struct i2c_driver yas529_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = yas529_mod_probe,
+       .remove = yas529_mod_remove,
+       .id_table = yas529_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "yas529_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init yas529_mod_init(void)
+{
+       int res = i2c_add_driver(&yas529_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "yas529_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit yas529_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&yas529_mod_driver);
+}
+
+module_init(yas529_mod_init);
+module_exit(yas529_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate YAS529 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("yas529_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/compass/yas530.c b/drivers/misc/inv_mpu/compass/yas530.c
new file mode 100644 (file)
index 0000000..fdca05b
--- /dev/null
@@ -0,0 +1,580 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+  *  @addtogroup COMPASSDL
+  *
+  *  @{
+  *      @file   yas530.c
+  *      @brief  Magnetometer setup and handling methods for Yamaha YAS530
+  *              compass when used in a user-space solution (no kernel driver).
+  */
+
+/* -------------------------------------------------------------------------- */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include "log.h"
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "MPL-compass"
+
+/* -------------------------------------------------------------------------- */
+#define YAS530_REGADDR_DEVICE_ID          (0x80)
+#define YAS530_REGADDR_ACTUATE_INIT_COIL  (0x81)
+#define YAS530_REGADDR_MEASURE_COMMAND    (0x82)
+#define YAS530_REGADDR_CONFIG             (0x83)
+#define YAS530_REGADDR_MEASURE_INTERVAL   (0x84)
+#define YAS530_REGADDR_OFFSET_X           (0x85)
+#define YAS530_REGADDR_OFFSET_Y1          (0x86)
+#define YAS530_REGADDR_OFFSET_Y2          (0x87)
+#define YAS530_REGADDR_TEST1              (0x88)
+#define YAS530_REGADDR_TEST2              (0x89)
+#define YAS530_REGADDR_CAL                (0x90)
+#define YAS530_REGADDR_MEASURE_DATA       (0xb0)
+
+/* -------------------------------------------------------------------------- */
+static int Cx, Cy1, Cy2;
+static int /*a1, */ a2, a3, a4, a5, a6, a7, a8, a9;
+static int k;
+
+static unsigned char dx, dy1, dy2;
+static unsigned char d2, d3, d4, d5, d6, d7, d8, d9, d0;
+static unsigned char dck;
+
+/* -------------------------------------------------------------------------- */
+
+static int set_hardware_offset(void *mlsl_handle,
+                              struct ext_slave_descr *slave,
+                              struct ext_slave_platform_data *pdata,
+                              char offset_x, char offset_y1, char offset_y2)
+{
+       char data;
+       int result = INV_SUCCESS;
+
+       data = offset_x & 0x3f;
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        YAS530_REGADDR_OFFSET_X, data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       data = offset_y1 & 0x3f;
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        YAS530_REGADDR_OFFSET_Y1, data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       data = offset_y2 & 0x3f;
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        YAS530_REGADDR_OFFSET_Y2, data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+static int set_measure_command(void *mlsl_handle,
+                              struct ext_slave_descr *slave,
+                              struct ext_slave_platform_data *pdata,
+                              int ldtc, int fors, int dlymes)
+{
+       int result = INV_SUCCESS;
+
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        YAS530_REGADDR_MEASURE_COMMAND, 0x01);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+static int measure_normal(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata,
+                         int *busy, unsigned short *t,
+                         unsigned short *x, unsigned short *y1,
+                         unsigned short *y2)
+{
+       unsigned char data[8];
+       unsigned short b, to, xo, y1o, y2o;
+       int result;
+       ktime_t sleeptime;
+       result = set_measure_command(mlsl_handle, slave, pdata, 0, 0, 0);
+       sleeptime = ktime_set(0, 2 * NSEC_PER_MSEC);
+       set_current_state(TASK_UNINTERRUPTIBLE);
+       schedule_hrtimeout(&sleeptime, HRTIMER_MODE_REL);
+
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                YAS530_REGADDR_MEASURE_DATA, 8, data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       b = (data[0] >> 7) & 0x01;
+       to = ((data[0] << 2) & 0x1fc) | ((data[1] >> 6) & 0x03);
+       xo = ((data[2] << 5) & 0xfe0) | ((data[3] >> 3) & 0x1f);
+       y1o = ((data[4] << 5) & 0xfe0) | ((data[5] >> 3) & 0x1f);
+       y2o = ((data[6] << 5) & 0xfe0) | ((data[7] >> 3) & 0x1f);
+
+       *busy = b;
+       *t = to;
+       *x = xo;
+       *y1 = y1o;
+       *y2 = y2o;
+
+       return result;
+}
+
+static int check_offset(void *mlsl_handle,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       char offset_x, char offset_y1, char offset_y2,
+                       int *flag_x, int *flag_y1, int *flag_y2)
+{
+       int result;
+       int busy;
+       short t, x, y1, y2;
+
+       result = set_hardware_offset(mlsl_handle, slave, pdata,
+                                    offset_x, offset_y1, offset_y2);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = measure_normal(mlsl_handle, slave, pdata,
+                               &busy, &t, &x, &y1, &y2);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       *flag_x = 0;
+       *flag_y1 = 0;
+       *flag_y2 = 0;
+
+       if (x > 2048)
+               *flag_x = 1;
+       if (y1 > 2048)
+               *flag_y1 = 1;
+       if (y2 > 2048)
+               *flag_y2 = 1;
+       if (x < 2048)
+               *flag_x = -1;
+       if (y1 < 2048)
+               *flag_y1 = -1;
+       if (y2 < 2048)
+               *flag_y2 = -1;
+
+       return result;
+}
+
+static int measure_and_set_offset(void *mlsl_handle,
+                                 struct ext_slave_descr *slave,
+                                 struct ext_slave_platform_data *pdata,
+                                 char *offset)
+{
+       int i;
+       int result = INV_SUCCESS;
+       char offset_x = 0, offset_y1 = 0, offset_y2 = 0;
+       int flag_x = 0, flag_y1 = 0, flag_y2 = 0;
+       static const int correct[5] = { 16, 8, 4, 2, 1 };
+
+       for (i = 0; i < 5; i++) {
+               result = check_offset(mlsl_handle, slave, pdata,
+                                     offset_x, offset_y1, offset_y2,
+                                     &flag_x, &flag_y1, &flag_y2);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+
+               if (flag_x)
+                       offset_x += flag_x * correct[i];
+               if (flag_y1)
+                       offset_y1 += flag_y1 * correct[i];
+               if (flag_y2)
+                       offset_y2 += flag_y2 * correct[i];
+       }
+
+       result = set_hardware_offset(mlsl_handle, slave, pdata,
+                                    offset_x, offset_y1, offset_y2);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       offset[0] = offset_x;
+       offset[1] = offset_y1;
+       offset[2] = offset_y2;
+
+       return result;
+}
+
+static void coordinate_conversion(short x, short y1, short y2, short t,
+                                 int32_t *xo, int32_t *yo, int32_t *zo)
+{
+       int32_t sx, sy1, sy2, sy, sz;
+       int32_t hx, hy, hz;
+
+       sx = x - (Cx * t) / 100;
+       sy1 = y1 - (Cy1 * t) / 100;
+       sy2 = y2 - (Cy2 * t) / 100;
+
+       sy = sy1 - sy2;
+       sz = -sy1 - sy2;
+
+       hx = k * ((100 * sx + a2 * sy + a3 * sz) / 10);
+       hy = k * ((a4 * sx + a5 * sy + a6 * sz) / 10);
+       hz = k * ((a7 * sx + a8 * sy + a9 * sz) / 10);
+
+       *xo = hx;
+       *yo = hy;
+       *zo = hz;
+}
+
+static int yas530_suspend(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                  struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       return result;
+}
+
+static int yas530_resume(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+
+       unsigned char dummyData = 0x00;
+       char offset[3] = { 0, 0, 0 };
+       unsigned char data[16];
+       unsigned char read_reg[1];
+
+       /* =============================================== */
+
+       /* Step 1 - Test register initialization */
+       dummyData = 0x00;
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        YAS530_REGADDR_TEST1, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result =
+           inv_serial_single_write(mlsl_handle, pdata->address,
+                                   YAS530_REGADDR_TEST2, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Device ID read  */
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                YAS530_REGADDR_DEVICE_ID, 1, read_reg);
+
+       /*Step 2 Read the CAL register */
+       /* CAL data read */
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                YAS530_REGADDR_CAL, 16, data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* CAL data Second Read */
+       result = inv_serial_read(mlsl_handle, pdata->address,
+                                YAS530_REGADDR_CAL, 16, data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /*Cal data */
+       dx = data[0];
+       dy1 = data[1];
+       dy2 = data[2];
+       d2 = (data[3] >> 2) & 0x03f;
+       d3 = ((data[3] << 2) & 0x0c) | ((data[4] >> 6) & 0x03);
+       d4 = data[4] & 0x3f;
+       d5 = (data[5] >> 2) & 0x3f;
+       d6 = ((data[5] << 4) & 0x30) | ((data[6] >> 4) & 0x0f);
+       d7 = ((data[6] << 3) & 0x78) | ((data[7] >> 5) & 0x07);
+       d8 = ((data[7] << 1) & 0x3e) | ((data[8] >> 7) & 0x01);
+       d9 = ((data[8] << 1) & 0xfe) | ((data[9] >> 7) & 0x01);
+       d0 = (data[9] >> 2) & 0x1f;
+       dck = ((data[9] << 1) & 0x06) | ((data[10] >> 7) & 0x01);
+
+       /*Correction Data */
+       Cx = (int)dx * 6 - 768;
+       Cy1 = (int)dy1 * 6 - 768;
+       Cy2 = (int)dy2 * 6 - 768;
+       a2 = (int)d2 - 32;
+       a3 = (int)d3 - 8;
+       a4 = (int)d4 - 32;
+       a5 = (int)d5 + 38;
+       a6 = (int)d6 - 32;
+       a7 = (int)d7 - 64;
+       a8 = (int)d8 - 32;
+       a9 = (int)d9;
+       k = (int)d0 + 10;
+
+       /*Obtain the [49:47] bits */
+       dck &= 0x07;
+
+       /*Step 3 : Storing the CONFIG with the CLK value */
+       dummyData = 0x00 | (dck << 2);
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        YAS530_REGADDR_CONFIG, dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /*Step 4 : Set Acquisition Interval Register */
+       dummyData = 0x00;
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        YAS530_REGADDR_MEASURE_INTERVAL,
+                                        dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /*Step 5 : Reset Coil */
+       dummyData = 0x00;
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                        YAS530_REGADDR_ACTUATE_INIT_COIL,
+                                        dummyData);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Offset Measurement and Set */
+       result = measure_and_set_offset(mlsl_handle, slave, pdata, offset);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+static int yas530_read(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata,
+                      unsigned char *data)
+{
+       int result = INV_SUCCESS;
+
+       int busy;
+       short t, x, y1, y2;
+       int32_t xyz[3];
+       short rawfixed[3];
+
+       result = measure_normal(mlsl_handle, slave, pdata,
+                               &busy, &t, &x, &y1, &y2);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       coordinate_conversion(x, y1, y2, t, &xyz[0], &xyz[1], &xyz[2]);
+
+       rawfixed[0] = (short)(xyz[0] / 100);
+       rawfixed[1] = (short)(xyz[1] / 100);
+       rawfixed[2] = (short)(xyz[2] / 100);
+
+       data[0] = rawfixed[0] >> 8;
+       data[1] = rawfixed[0] & 0xFF;
+       data[2] = rawfixed[1] >> 8;
+       data[3] = rawfixed[1] & 0xFF;
+       data[4] = rawfixed[2] >> 8;
+       data[5] = rawfixed[2] & 0xFF;
+
+       if (busy)
+               return INV_ERROR_COMPASS_DATA_NOT_READY;
+       return result;
+}
+
+static struct ext_slave_descr yas530_descr = {
+       .init             = NULL,
+       .exit             = NULL,
+       .suspend          = yas530_suspend,
+       .resume           = yas530_resume,
+       .read             = yas530_read,
+       .config           = NULL,
+       .get_config       = NULL,
+       .name             = "yas530",
+       .type             = EXT_SLAVE_TYPE_COMPASS,
+       .id               = COMPASS_ID_YAS530,
+       .read_reg         = 0x06,
+       .read_len         = 6,
+       .endian           = EXT_SLAVE_BIG_ENDIAN,
+       .range            = {3276, 8001},
+       .trigger          = NULL,
+};
+
+static
+struct ext_slave_descr *yas530_get_slave_descr(void)
+{
+       return &yas530_descr;
+}
+
+/* -------------------------------------------------------------------------- */
+struct yas530_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int yas530_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct yas530_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       yas530_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int yas530_mod_remove(struct i2c_client *client)
+{
+       struct yas530_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               yas530_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id yas530_mod_id[] = {
+       { "yas530", COMPASS_ID_YAS530 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, yas530_mod_id);
+
+static struct i2c_driver yas530_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = yas530_mod_probe,
+       .remove = yas530_mod_remove,
+       .id_table = yas530_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "yas530_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init yas530_mod_init(void)
+{
+       int res = i2c_add_driver(&yas530_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "yas530_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit yas530_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&yas530_mod_driver);
+}
+
+module_init(yas530_mod_init);
+module_exit(yas530_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate YAS530 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("yas530_mod");
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/log.h b/drivers/misc/inv_mpu/log.h
new file mode 100644 (file)
index 0000000..5630602
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/*
+ * This file incorporates work covered by the following copyright and
+ * permission notice:
+ *
+ * Copyright (C) 2005 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * C/C++ logging functions.  See the logging documentation for API details.
+ *
+ * We'd like these to be available from C code (in case we import some from
+ * somewhere), so this has a C interface.
+ *
+ * The output will be correct when the log file is shared between multiple
+ * threads and/or multiple processes so long as the operating system
+ * supports O_APPEND.  These calls have mutex-protected data structures
+ * and so are NOT reentrant.  Do not use MPL_LOG in a signal handler.
+ */
+#ifndef _LIBS_CUTILS_MPL_LOG_H
+#define _LIBS_CUTILS_MPL_LOG_H
+
+#include "mltypes.h"
+#include <stdarg.h>
+
+
+#include <linux/kernel.h>
+
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Normally we strip MPL_LOGV (VERBOSE messages) from release builds.
+ * You can modify this (for example with "#define MPL_LOG_NDEBUG 0"
+ * at the top of your source file) to change that behavior.
+ */
+#ifndef MPL_LOG_NDEBUG
+#ifdef NDEBUG
+#define MPL_LOG_NDEBUG 1
+#else
+#define MPL_LOG_NDEBUG 0
+#endif
+#endif
+
+#define MPL_LOG_UNKNOWN MPL_LOG_VERBOSE
+#define MPL_LOG_DEFAULT KERN_DEFAULT
+#define MPL_LOG_VERBOSE KERN_CONT
+#define MPL_LOG_DEBUG   KERN_NOTICE
+#define MPL_LOG_INFO    KERN_INFO
+#define MPL_LOG_WARN    KERN_WARNING
+#define MPL_LOG_ERROR   KERN_ERR
+#define MPL_LOG_SILENT  MPL_LOG_VERBOSE
+
+
+
+/*
+ * This is the local tag used for the following simplified
+ * logging macros.  You can change this preprocessor definition
+ * before using the other macros to change the tag.
+ */
+#ifndef MPL_LOG_TAG
+#define MPL_LOG_TAG
+#endif
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Simplified macro to send a verbose log message using the current MPL_LOG_TAG.
+ */
+#ifndef MPL_LOGV
+#if MPL_LOG_NDEBUG
+#define MPL_LOGV(fmt, ...)                                             \
+       do {                                                            \
+               if (0)                                                  \
+                       MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, fmt, ##__VA_ARGS__);\
+       } while (0)
+#else
+#define MPL_LOGV(fmt, ...) MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
+#endif
+#endif
+
+#ifndef CONDITION
+#define CONDITION(cond)     ((cond) != 0)
+#endif
+
+#ifndef MPL_LOGV_IF
+#if MPL_LOG_NDEBUG
+#define MPL_LOGV_IF(cond, fmt, ...)  \
+       do { if (0) MPL_LOG(fmt, ##__VA_ARGS__); } while (0)
+#else
+#define MPL_LOGV_IF(cond, fmt, ...) \
+       ((CONDITION(cond))                                              \
+               ? MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, fmt, ##__VA_ARGS__) \
+               : (void)0)
+#endif
+#endif
+
+/*
+ * Simplified macro to send a debug log message using the current MPL_LOG_TAG.
+ */
+#ifndef MPL_LOGD
+#define MPL_LOGD(fmt, ...) MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
+#endif
+
+#ifndef MPL_LOGD_IF
+#define MPL_LOGD_IF(cond, fmt, ...) \
+       ((CONDITION(cond))                                             \
+               ? MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, fmt, ##__VA_ARGS__)  \
+               : (void)0)
+#endif
+
+/*
+ * Simplified macro to send an info log message using the current MPL_LOG_TAG.
+ */
+#ifndef MPL_LOGI
+#define MPL_LOGI(fmt, ...) pr_info(KERN_INFO MPL_LOG_TAG fmt, ##__VA_ARGS__)
+#endif
+
+#ifndef MPL_LOGI_IF
+#define MPL_LOGI_IF(cond, fmt, ...) \
+       ((CONDITION(cond))                                              \
+               ? MPL_LOG(LOG_INFO, MPL_LOG_TAG, fmt, ##__VA_ARGS__)   \
+               : (void)0)
+#endif
+
+/*
+ * Simplified macro to send a warning log message using the current MPL_LOG_TAG.
+ */
+#ifndef MPL_LOGW
+#define MPL_LOGW(fmt, ...) printk(KERN_WARNING MPL_LOG_TAG fmt, ##__VA_ARGS__)
+#endif
+
+#ifndef MPL_LOGW_IF
+#define MPL_LOGW_IF(cond, fmt, ...) \
+       ((CONDITION(cond))                                             \
+               ? MPL_LOG(LOG_WARN, MPL_LOG_TAG, fmt, ##__VA_ARGS__)   \
+               : (void)0)
+#endif
+
+/*
+ * Simplified macro to send an error log message using the current MPL_LOG_TAG.
+ */
+#ifndef MPL_LOGE
+#define MPL_LOGE(fmt, ...) printk(KERN_ERR MPL_LOG_TAG fmt, ##__VA_ARGS__)
+#endif
+
+#ifndef MPL_LOGE_IF
+#define MPL_LOGE_IF(cond, fmt, ...) \
+       ((CONDITION(cond))                                             \
+               ? MPL_LOG(LOG_ERROR, MPL_LOG_TAG, fmt, ##__VA_ARGS__)  \
+               : (void)0)
+#endif
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Log a fatal error.  If the given condition fails, this stops program
+ * execution like a normal assertion, but also generating the given message.
+ * It is NOT stripped from release builds.  Note that the condition test
+ * is -inverted- from the normal assert() semantics.
+ */
+#define MPL_LOG_ALWAYS_FATAL_IF(cond, fmt, ...) \
+       ((CONDITION(cond))                                         \
+               ? ((void)android_printAssert(#cond, MPL_LOG_TAG,   \
+                                               fmt, ##__VA_ARGS__))    \
+               : (void)0)
+
+#define MPL_LOG_ALWAYS_FATAL(fmt, ...) \
+       (((void)android_printAssert(NULL, MPL_LOG_TAG, fmt, ##__VA_ARGS__)))
+
+/*
+ * Versions of MPL_LOG_ALWAYS_FATAL_IF and MPL_LOG_ALWAYS_FATAL that
+ * are stripped out of release builds.
+ */
+#if MPL_LOG_NDEBUG
+#define MPL_LOG_FATAL_IF(cond, fmt, ...)                               \
+       do {                                                            \
+               if (0)                                                  \
+                       MPL_LOG_ALWAYS_FATAL_IF(cond, fmt, ##__VA_ARGS__); \
+       } while (0)
+#define MPL_LOG_FATAL(fmt, ...)                                                \
+       do {                                                            \
+               if (0)                                                  \
+                       MPL_LOG_ALWAYS_FATAL(fmt, ##__VA_ARGS__)        \
+       } while (0)
+#else
+#define MPL_LOG_FATAL_IF(cond, fmt, ...) \
+       MPL_LOG_ALWAYS_FATAL_IF(cond, fmt, ##__VA_ARGS__)
+#define MPL_LOG_FATAL(fmt, ...) \
+       MPL_LOG_ALWAYS_FATAL(fmt, ##__VA_ARGS__)
+#endif
+
+/*
+ * Assertion that generates a log message when the assertion fails.
+ * Stripped out of release builds.  Uses the current MPL_LOG_TAG.
+ */
+#define MPL_LOG_ASSERT(cond, fmt, ...)                 \
+       MPL_LOG_FATAL_IF(!(cond), fmt, ##__VA_ARGS__)
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * Basic log message macro.
+ *
+ * Example:
+ *  MPL_LOG(MPL_LOG_WARN, NULL, "Failed with error %d", errno);
+ *
+ * The second argument may be NULL or "" to indicate the "global" tag.
+ */
+#ifndef MPL_LOG
+#define MPL_LOG(priority, tag, fmt, ...)               \
+       MPL_LOG_PRI(priority, tag, fmt, ##__VA_ARGS__)
+#endif
+
+/*
+ * Log macro that allows you to specify a number for the priority.
+ */
+#ifndef MPL_LOG_PRI
+#define MPL_LOG_PRI(priority, tag, fmt, ...) \
+       pr_debug(MPL_##priority tag fmt, ##__VA_ARGS__)
+#endif
+
+/*
+ * Log macro that allows you to pass in a varargs ("args" is a va_list).
+ */
+#ifndef MPL_LOG_PRI_VA
+/* not allowed in the Kernel because there is no dev_dbg that takes a va_list */
+#endif
+
+/* --------------------------------------------------------------------- */
+
+/*
+ * ===========================================================================
+ *
+ * The stuff in the rest of this file should not be used directly.
+ */
+
+int _MLPrintLog(int priority, const char *tag, const char *fmt,        ...);
+int _MLPrintVaLog(int priority, const char *tag, const char *fmt, va_list args);
+/* Final implementation of actual writing to a character device */
+int _MLWriteLog(const char *buf, int buflen);
+
+static inline void __print_result_location(int result,
+                                          const char *file,
+                                          const char *func, int line)
+{
+       MPL_LOGE("%s|%s|%d returning %d\n", file, func, line, result);
+}
+
+#define LOG_RESULT_LOCATION(condition) \
+       do {                                                            \
+               __print_result_location((int)(condition), __FILE__,     \
+                                       __func__, __LINE__);            \
+       } while (0)
+
+
+#endif                         /* _LIBS_CUTILS_MPL_LOG_H */
diff --git a/drivers/misc/inv_mpu/mldl_cfg.c b/drivers/misc/inv_mpu/mldl_cfg.c
new file mode 100755 (executable)
index 0000000..ccacc8e
--- /dev/null
@@ -0,0 +1,1765 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup MLDL
+ *
+ *  @{
+ *      @file   mldl_cfg.c
+ *      @brief  The Motion Library Driver Layer.
+ */
+
+/* -------------------------------------------------------------------------- */
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include <stddef.h>
+
+#include "mldl_cfg.h"
+#include <linux/mpu.h>
+#include "mpu3050.h"
+
+#include "mlsl.h"
+#include "mldl_print_cfg.h"
+#include "log.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "mldl_cfg:"
+
+/* -------------------------------------------------------------------------- */
+
+#define SLEEP   1
+#define WAKE_UP 0
+#define RESET   1
+#define STANDBY 1
+
+/* -------------------------------------------------------------------------- */
+
+/**
+ * @brief Stop the DMP running
+ *
+ * @return INV_SUCCESS or non-zero error code
+ */
+static int dmp_stop(struct mldl_cfg *mldl_cfg, void *gyro_handle)
+{
+       unsigned char user_ctrl_reg;
+       int result;
+
+       if (mldl_cfg->inv_mpu_state->status & MPU_DMP_IS_SUSPENDED)
+               return INV_SUCCESS;
+
+       result = inv_serial_read(gyro_handle, mldl_cfg->mpu_chip_info->addr,
+                                MPUREG_USER_CTRL, 1, &user_ctrl_reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       user_ctrl_reg = (user_ctrl_reg & (~BIT_FIFO_EN)) | BIT_FIFO_RST;
+       user_ctrl_reg = (user_ctrl_reg & (~BIT_DMP_EN)) | BIT_DMP_RST;
+
+       result = inv_serial_single_write(gyro_handle,
+                                        mldl_cfg->mpu_chip_info->addr,
+                                        MPUREG_USER_CTRL, user_ctrl_reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       mldl_cfg->inv_mpu_state->status |= MPU_DMP_IS_SUSPENDED;
+
+       return result;
+}
+
+/**
+ * @brief Starts the DMP running
+ *
+ * @return INV_SUCCESS or non-zero error code
+ */
+static int dmp_start(struct mldl_cfg *mldl_cfg, void *mlsl_handle)
+{
+       unsigned char user_ctrl_reg;
+       int result;
+
+       if ((!(mldl_cfg->inv_mpu_state->status & MPU_DMP_IS_SUSPENDED) &&
+           mldl_cfg->mpu_gyro_cfg->dmp_enable)
+               ||
+          ((mldl_cfg->inv_mpu_state->status & MPU_DMP_IS_SUSPENDED) &&
+                  !mldl_cfg->mpu_gyro_cfg->dmp_enable))
+               return INV_SUCCESS;
+
+       result = inv_serial_read(mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                                MPUREG_USER_CTRL, 1, &user_ctrl_reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_single_write(
+               mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_USER_CTRL,
+               ((user_ctrl_reg & (~BIT_FIFO_EN))
+                       | BIT_FIFO_RST));
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_single_write(
+               mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_USER_CTRL, user_ctrl_reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_read(mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                                MPUREG_USER_CTRL, 1, &user_ctrl_reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       user_ctrl_reg |= BIT_DMP_EN;
+
+       if (mldl_cfg->mpu_gyro_cfg->fifo_enable)
+               user_ctrl_reg |= BIT_FIFO_EN;
+       else
+               user_ctrl_reg &= ~BIT_FIFO_EN;
+
+       user_ctrl_reg |= BIT_DMP_RST;
+
+       result = inv_serial_single_write(
+               mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_USER_CTRL, user_ctrl_reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       mldl_cfg->inv_mpu_state->status &= ~MPU_DMP_IS_SUSPENDED;
+
+       return result;
+}
+
+
+
+static int mpu3050_set_i2c_bypass(struct mldl_cfg *mldl_cfg,
+                                 void *mlsl_handle, unsigned char enable)
+{
+       unsigned char b;
+       int result;
+       unsigned char status = mldl_cfg->inv_mpu_state->status;
+
+       if ((status & MPU_GYRO_IS_BYPASSED && enable) ||
+           (!(status & MPU_GYRO_IS_BYPASSED) && !enable))
+               return INV_SUCCESS;
+
+       /*---- get current 'USER_CTRL' into b ----*/
+       result = inv_serial_read(
+               mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_USER_CTRL, 1, &b);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       b &= ~BIT_AUX_IF_EN;
+
+       if (!enable) {
+               result = inv_serial_single_write(
+                       mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                       MPUREG_USER_CTRL,
+                       (b | BIT_AUX_IF_EN));
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       } else {
+               /* Coming out of I2C is tricky due to several erratta.  Do not
+                * modify this algorithm
+                */
+               /*
+                * 1) wait for the right time and send the command to change
+                * the aux i2c slave address to an invalid address that will
+                * get nack'ed
+                *
+                * 0x00 is broadcast.  0x7F is unlikely to be used by any aux.
+                */
+               result = inv_serial_single_write(
+                       mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                       MPUREG_AUX_SLV_ADDR, 0x7F);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               /*
+                * 2) wait enough time for a nack to occur, then go into
+                *    bypass mode:
+                */
+               msleep(2);
+               result = inv_serial_single_write(
+                       mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                       MPUREG_USER_CTRL, (b));
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               /*
+                * 3) wait for up to one MPU cycle then restore the slave
+                *    address
+                */
+               msleep(inv_mpu_get_sampling_period_us(mldl_cfg->mpu_gyro_cfg)
+                       / 1000);
+               result = inv_serial_single_write(
+                       mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                       MPUREG_AUX_SLV_ADDR,
+                       mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_ACCEL]
+                               ->address);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+
+               /*
+                * 4) reset the ime interface
+                */
+
+               result = inv_serial_single_write(
+                       mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                       MPUREG_USER_CTRL,
+                       (b | BIT_AUX_IF_RST));
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               msleep(2);
+       }
+       if (enable)
+               mldl_cfg->inv_mpu_state->status |= MPU_GYRO_IS_BYPASSED;
+       else
+               mldl_cfg->inv_mpu_state->status &= ~MPU_GYRO_IS_BYPASSED;
+
+       return result;
+}
+
+
+/**
+ *  @brief  enables/disables the I2C bypass to an external device
+ *          connected to MPU's secondary I2C bus.
+ *  @param  enable
+ *              Non-zero to enable pass through.
+ *  @return INV_SUCCESS if successful, a non-zero error code otherwise.
+ */
+static int mpu_set_i2c_bypass(struct mldl_cfg *mldl_cfg, void *mlsl_handle,
+                             unsigned char enable)
+{
+       return mpu3050_set_i2c_bypass(mldl_cfg, mlsl_handle, enable);
+}
+
+
+#define NUM_OF_PROD_REVS (ARRAY_SIZE(prod_rev_map))
+
+/* NOTE : when not indicated, product revision
+         is considered an 'npp'; non production part */
+
+struct prod_rev_map_t {
+       unsigned char silicon_rev;
+       unsigned short gyro_trim;
+};
+
+#define OLDEST_PROD_REV_SUPPORTED      11
+static struct prod_rev_map_t prod_rev_map[] = {
+       {0, 0},
+       {MPU_SILICON_REV_A4, 131},      /* 1  A? OBSOLETED */
+       {MPU_SILICON_REV_A4, 131},      /* 2  |  */
+       {MPU_SILICON_REV_A4, 131},      /* 3  |  */
+       {MPU_SILICON_REV_A4, 131},      /* 4  |  */
+       {MPU_SILICON_REV_A4, 131},      /* 5  |  */
+       {MPU_SILICON_REV_A4, 131},      /* 6  |  */
+       {MPU_SILICON_REV_A4, 131},      /* 7  |  */
+       {MPU_SILICON_REV_A4, 131},      /* 8  |  */
+       {MPU_SILICON_REV_A4, 131},      /* 9  |  */
+       {MPU_SILICON_REV_A4, 131},      /* 10 V  */
+       {MPU_SILICON_REV_B1, 131},      /* 11 B1 */
+       {MPU_SILICON_REV_B1, 131},      /* 12 |  */
+       {MPU_SILICON_REV_B1, 131},      /* 13 |  */
+       {MPU_SILICON_REV_B1, 131},      /* 14 V  */
+       {MPU_SILICON_REV_B4, 131},      /* 15 B4 */
+       {MPU_SILICON_REV_B4, 131},      /* 16 |  */
+       {MPU_SILICON_REV_B4, 131},      /* 17 |  */
+       {MPU_SILICON_REV_B4, 131},      /* 18 |  */
+       {MPU_SILICON_REV_B4, 115},      /* 19 |  */
+       {MPU_SILICON_REV_B4, 115},      /* 20 V  */
+       {MPU_SILICON_REV_B6, 131},      /* 21 B6 (B6/A9)  */
+       {MPU_SILICON_REV_B4, 115},      /* 22 B4 (B7/A10) */
+       {MPU_SILICON_REV_B6, 0},        /* 23 B6 */
+       {MPU_SILICON_REV_B6, 0},        /* 24 |  */
+       {MPU_SILICON_REV_B6, 0},        /* 25 |  */
+       {MPU_SILICON_REV_B6, 131},      /* 26 V  (B6/A11) */
+};
+
+/**
+ *  @internal
+ *  @brief  Get the silicon revision ID from OTP for MPU3050.
+ *          The silicon revision number is in read from OTP bank 0,
+ *          ADDR6[7:2].  The corresponding ID is retrieved by lookup
+ *          in a map.
+ *
+ *  @param  mldl_cfg
+ *              a pointer to the mldl config data structure.
+ *  @param  mlsl_handle
+ *              an file handle to the serial communication device the
+ *              device is connected to.
+ *
+ *  @return 0 on success, a non-zero error code otherwise.
+ */
+static int inv_get_silicon_rev_mpu3050(
+               struct mldl_cfg *mldl_cfg, void *mlsl_handle)
+{
+       int result;
+       unsigned char index = 0x00;
+       unsigned char bank =
+           (BIT_PRFTCH_EN | BIT_CFG_USER_BANK | MPU_MEM_OTP_BANK_0);
+       unsigned short mem_addr = ((bank << 8) | 0x06);
+       struct mpu_chip_info *mpu_chip_info = mldl_cfg->mpu_chip_info;
+
+       result = inv_serial_read(mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                                MPUREG_PRODUCT_ID, 1,
+                                &mpu_chip_info->product_id);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_serial_read_mem(
+               mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+               mem_addr, 1, &index);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       index >>= 2;
+
+       /* clean the prefetch and cfg user bank bits */
+       result = inv_serial_single_write(
+               mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_BANK_SEL, 0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       if (index < OLDEST_PROD_REV_SUPPORTED || index >= NUM_OF_PROD_REVS) {
+               mpu_chip_info->silicon_revision = 0;
+               mpu_chip_info->gyro_sens_trim = 0;
+               MPL_LOGE("Unsupported Product Revision Detected : %d\n", index);
+               return INV_ERROR_INVALID_MODULE;
+       }
+
+       mpu_chip_info->product_revision = index;
+       mpu_chip_info->silicon_revision = prod_rev_map[index].silicon_rev;
+       mpu_chip_info->gyro_sens_trim = prod_rev_map[index].gyro_trim;
+       if (mpu_chip_info->gyro_sens_trim == 0) {
+               MPL_LOGE("gyro sensitivity trim is 0"
+                        " - unsupported non production part.\n");
+               return INV_ERROR_INVALID_MODULE;
+       }
+
+       return result;
+}
+#define inv_get_silicon_rev inv_get_silicon_rev_mpu3050
+
+
+/**
+ *  @brief  Enable / Disable the use MPU's secondary I2C interface level
+ *          shifters.
+ *          When enabled the secondary I2C interface to which the external
+ *          device is connected runs at VDD voltage (main supply).
+ *          When disabled the 2nd interface runs at VDDIO voltage.
+ *          See the device specification for more details.
+ *
+ *  @note   using this API may produce unpredictable results, depending on how
+ *          the MPU and slave device are setup on the target platform.
+ *          Use of this API should entirely be restricted to system
+ *          integrators. Once the correct value is found, there should be no
+ *          need to change the level shifter at runtime.
+ *
+ *  @pre    Must be called after inv_serial_start().
+ *  @note   Typically called before inv_dmp_open().
+ *
+ *  @param[in]  enable:
+ *                  0 to run at VDDIO (default),
+ *                  1 to run at VDD.
+ *
+ *  @return INV_SUCCESS if successfull, a non-zero error code otherwise.
+ */
+static int inv_mpu_set_level_shifter_bit(struct mldl_cfg *mldl_cfg,
+                                 void *mlsl_handle, unsigned char enable)
+{
+       int result;
+       unsigned char regval;
+
+       unsigned char reg;
+       unsigned char mask;
+
+       if (0 == mldl_cfg->mpu_chip_info->silicon_revision)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       /*-- on parts before B6 the VDDIO bit is bit 7 of ACCEL_BURST_ADDR --
+       NOTE: this is incompatible with ST accelerometers where the VDDIO
+       bit MUST be set to enable ST's internal logic to autoincrement
+       the register address on burst reads --*/
+       if ((mldl_cfg->mpu_chip_info->silicon_revision & 0xf)
+               < MPU_SILICON_REV_B6) {
+               reg = MPUREG_ACCEL_BURST_ADDR;
+               mask = 0x80;
+       } else {
+               /*-- on B6 parts the VDDIO bit was moved to FIFO_EN2 =>
+                 the mask is always 0x04 --*/
+               reg = MPUREG_FIFO_EN2;
+               mask = 0x04;
+       }
+
+       result = inv_serial_read(mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                                reg, 1, &regval);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       if (enable)
+               regval |= mask;
+       else
+               regval &= ~mask;
+
+       result = inv_serial_single_write(
+               mlsl_handle, mldl_cfg->mpu_chip_info->addr, reg, regval);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       return result;
+       return INV_SUCCESS;
+}
+
+
+/**
+ * @internal
+ * @brief   This function controls the power management on the MPU device.
+ *          The entire chip can be put to low power sleep mode, or individual
+ *          gyros can be turned on/off.
+ *
+ *          Putting the device into sleep mode depending upon the changing needs
+ *          of the associated applications is a recommended method for reducing
+ *          power consuption.  It is a safe opearation in that sleep/wake up of
+ *          gyros while running will not result in any interruption of data.
+ *
+ *          Although it is entirely allowed to put the device into full sleep
+ *          while running the DMP, it is not recomended because it will disrupt
+ *          the ongoing calculations carried on inside the DMP and consequently
+ *          the sensor fusion algorithm. Furthermore, while in sleep mode
+ *          read & write operation from the app processor on both registers and
+ *          memory are disabled and can only regained by restoring the MPU in
+ *          normal power mode.
+ *          Disabling any of the gyro axis will reduce the associated power
+ *          consuption from the PLL but will not stop the DMP from running
+ *          state.
+ *
+ * @param   reset
+ *              Non-zero to reset the device. Note that this setting
+ *              is volatile and the corresponding register bit will
+ *              clear itself right after being applied.
+ * @param   sleep
+ *              Non-zero to put device into full sleep.
+ * @param   disable_gx
+ *              Non-zero to disable gyro X.
+ * @param   disable_gy
+ *              Non-zero to disable gyro Y.
+ * @param   disable_gz
+ *              Non-zero to disable gyro Z.
+ *
+ * @return  INV_SUCCESS if successfull; a non-zero error code otherwise.
+ */
+static int mpu3050_pwr_mgmt(struct mldl_cfg *mldl_cfg,
+                           void *mlsl_handle,
+                           unsigned char reset,
+                           unsigned char sleep,
+                           unsigned char disable_gx,
+                           unsigned char disable_gy,
+                           unsigned char disable_gz)
+{
+       unsigned char b;
+       int result;
+
+       result =
+           inv_serial_read(mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                           MPUREG_PWR_MGM, 1, &b);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* If we are awake, we need to put it in bypass before resetting */
+       if ((!(b & BIT_SLEEP)) && reset)
+               result = mpu_set_i2c_bypass(mldl_cfg, mlsl_handle, 1);
+
+       /* Reset if requested */
+       if (reset) {
+               MPL_LOGV("Reset MPU3050\n");
+               result = inv_serial_single_write(
+                       mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                       MPUREG_PWR_MGM, b | BIT_H_RESET);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               msleep(5);
+               /* Some chips are awake after reset and some are asleep,
+                * check the status */
+               result = inv_serial_read(
+                       mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                       MPUREG_PWR_MGM, 1, &b);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       /* Update the suspended state just in case we return early */
+       if (b & BIT_SLEEP) {
+               mldl_cfg->inv_mpu_state->status |= MPU_GYRO_IS_SUSPENDED;
+               mldl_cfg->inv_mpu_state->status |= MPU_DEVICE_IS_SUSPENDED;
+       } else {
+               mldl_cfg->inv_mpu_state->status &= ~MPU_GYRO_IS_SUSPENDED;
+               mldl_cfg->inv_mpu_state->status &= ~MPU_DEVICE_IS_SUSPENDED;
+       }
+
+       /* if power status match requested, nothing else's left to do */
+       if ((b & (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)) ==
+           (((sleep != 0) * BIT_SLEEP) |
+            ((disable_gx != 0) * BIT_STBY_XG) |
+            ((disable_gy != 0) * BIT_STBY_YG) |
+            ((disable_gz != 0) * BIT_STBY_ZG))) {
+               return INV_SUCCESS;
+       }
+
+       /*
+        * This specific transition between states needs to be reinterpreted:
+        *    (1,1,1,1) -> (0,1,1,1) has to become
+        *    (1,1,1,1) -> (1,0,0,0) -> (0,1,1,1)
+        * where
+        *    (1,1,1,1) is (sleep=1,disable_gx=1,disable_gy=1,disable_gz=1)
+        */
+       if ((b & (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)) ==
+           (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)
+           && ((!sleep) && disable_gx && disable_gy && disable_gz)) {
+               result = mpu3050_pwr_mgmt(mldl_cfg, mlsl_handle, 0, 1, 0, 0, 0);
+               if (result)
+                       return result;
+               b |= BIT_SLEEP;
+               b &= ~(BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG);
+       }
+
+       if ((b & BIT_SLEEP) != ((sleep != 0) * BIT_SLEEP)) {
+               if (sleep) {
+                       result = mpu_set_i2c_bypass(mldl_cfg, mlsl_handle, 1);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       b |= BIT_SLEEP;
+                       result =
+                           inv_serial_single_write(
+                                   mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                                   MPUREG_PWR_MGM, b);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       mldl_cfg->inv_mpu_state->status |=
+                               MPU_GYRO_IS_SUSPENDED;
+                       mldl_cfg->inv_mpu_state->status |=
+                               MPU_DEVICE_IS_SUSPENDED;
+               } else {
+                       b &= ~BIT_SLEEP;
+                       result =
+                           inv_serial_single_write(
+                                   mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                                   MPUREG_PWR_MGM, b);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+                       mldl_cfg->inv_mpu_state->status &=
+                               ~MPU_GYRO_IS_SUSPENDED;
+                       mldl_cfg->inv_mpu_state->status &=
+                               ~MPU_DEVICE_IS_SUSPENDED;
+                       msleep(5);
+               }
+       }
+       /*---
+         WORKAROUND FOR PUTTING GYRO AXIS in STAND-BY MODE
+         1) put one axis at a time in stand-by
+         ---*/
+       if ((b & BIT_STBY_XG) != ((disable_gx != 0) * BIT_STBY_XG)) {
+               b ^= BIT_STBY_XG;
+               result = inv_serial_single_write(
+                       mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                       MPUREG_PWR_MGM, b);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       if ((b & BIT_STBY_YG) != ((disable_gy != 0) * BIT_STBY_YG)) {
+               b ^= BIT_STBY_YG;
+               result = inv_serial_single_write(
+                       mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                       MPUREG_PWR_MGM, b);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       if ((b & BIT_STBY_ZG) != ((disable_gz != 0) * BIT_STBY_ZG)) {
+               b ^= BIT_STBY_ZG;
+               result = inv_serial_single_write(
+                       mlsl_handle, mldl_cfg->mpu_chip_info->addr,
+                       MPUREG_PWR_MGM, b);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       return INV_SUCCESS;
+}
+
+
+/**
+ *  @brief  sets the clock source for the gyros.
+ *  @param  mldl_cfg
+ *              a pointer to the struct mldl_cfg data structure.
+ *  @param  gyro_handle
+ *              an handle to the serial device the gyro is assigned to.
+ *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
+ */
+static int mpu_set_clock_source(void *gyro_handle, struct mldl_cfg *mldl_cfg)
+{
+       int result;
+       unsigned char cur_clk_src;
+       unsigned char reg;
+
+       /* clock source selection */
+       result = inv_serial_read(gyro_handle, mldl_cfg->mpu_chip_info->addr,
+                                MPUREG_PWR_MGM, 1, &reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       cur_clk_src = reg & BITS_CLKSEL;
+       reg &= ~BITS_CLKSEL;
+
+
+       result = inv_serial_single_write(
+               gyro_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_PWR_MGM, mldl_cfg->mpu_gyro_cfg->clk_src | reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* TODO : workarounds to be determined and implemented */
+
+       return result;
+}
+
+/**
+ * Configures the MPU I2C Master
+ *
+ * @mldl_cfg Handle to the configuration data
+ * @gyro_handle handle to the gyro communictation interface
+ * @slave Can be Null if turning off the slave
+ * @slave_pdata Can be null if turning off the slave
+ * @slave_id enum ext_slave_type to determine which index to use
+ *
+ *
+ * This fucntion configures the slaves by:
+ * 1) Setting up the read
+ *    a) Read Register
+ *    b) Read Length
+ * 2) Set up the data trigger (MPU6050 only)
+ *    a) Set trigger write register
+ *    b) Set Trigger write value
+ * 3) Set up the divider (MPU6050 only)
+ * 4) Set the slave bypass mode depending on slave
+ *
+ * returns INV_SUCCESS or non-zero error code
+ */
+static int mpu_set_slave_mpu3050(struct mldl_cfg *mldl_cfg,
+                                void *gyro_handle,
+                                struct ext_slave_descr *slave,
+                                struct ext_slave_platform_data *slave_pdata,
+                                int slave_id)
+{
+       int result;
+       unsigned char reg;
+       unsigned char slave_reg;
+       unsigned char slave_len;
+       unsigned char slave_endian;
+       unsigned char slave_address;
+
+       if (slave_id != EXT_SLAVE_TYPE_ACCEL)
+               return 0;
+
+       result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle, true);
+
+       if (NULL == slave || NULL == slave_pdata) {
+               slave_reg = 0;
+               slave_len = 0;
+               slave_endian = 0;
+               slave_address = 0;
+               mldl_cfg->inv_mpu_state->i2c_slaves_enabled = 0;
+       } else {
+               slave_reg = slave->read_reg;
+               slave_len = slave->read_len;
+               slave_endian = slave->endian;
+               slave_address = slave_pdata->address;
+               mldl_cfg->inv_mpu_state->i2c_slaves_enabled = 1;
+       }
+
+       /* Address */
+       result = inv_serial_single_write(gyro_handle,
+                                        mldl_cfg->mpu_chip_info->addr,
+                                        MPUREG_AUX_SLV_ADDR, slave_address);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       /* Register */
+       result = inv_serial_read(gyro_handle, mldl_cfg->mpu_chip_info->addr,
+                                MPUREG_ACCEL_BURST_ADDR, 1, &reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       reg = ((reg & 0x80) | slave_reg);
+       result = inv_serial_single_write(gyro_handle,
+                                        mldl_cfg->mpu_chip_info->addr,
+                                        MPUREG_ACCEL_BURST_ADDR, reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Length */
+       result = inv_serial_read(gyro_handle, mldl_cfg->mpu_chip_info->addr,
+                                MPUREG_USER_CTRL, 1, &reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       reg = (reg & ~BIT_AUX_RD_LENG);
+       result = inv_serial_single_write(
+               gyro_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_USER_CTRL, reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       return result;
+}
+
+
+static int mpu_set_slave(struct mldl_cfg *mldl_cfg,
+                        void *gyro_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *slave_pdata,
+                        int slave_id)
+{
+       return mpu_set_slave_mpu3050(mldl_cfg, gyro_handle, slave,
+                                    slave_pdata, slave_id);
+}
+/**
+ * Check to see if the gyro was reset by testing a couple of registers known
+ * to change on reset.
+ *
+ * @mldl_cfg mldl configuration structure
+ * @gyro_handle handle used to communicate with the gyro
+ *
+ * @return INV_SUCCESS or non-zero error code
+ */
+static int mpu_was_reset(struct mldl_cfg *mldl_cfg, void *gyro_handle)
+{
+       int result = INV_SUCCESS;
+       unsigned char reg;
+
+       result = inv_serial_read(gyro_handle, mldl_cfg->mpu_chip_info->addr,
+                                MPUREG_DMP_CFG_2, 1, &reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       if (mldl_cfg->mpu_gyro_cfg->dmp_cfg2 != reg)
+               return true;
+
+       if (0 != mldl_cfg->mpu_gyro_cfg->dmp_cfg1)
+               return false;
+
+       /* Inconclusive assume it was reset */
+       return true;
+}
+
+
+int inv_mpu_set_firmware(struct mldl_cfg *mldl_cfg, void *mlsl_handle,
+                        const unsigned char *data, int size)
+{
+       int bank, offset, write_size;
+       int result;
+       unsigned char read[MPU_MEM_BANK_SIZE];
+
+       if (mldl_cfg->inv_mpu_state->status & MPU_DEVICE_IS_SUSPENDED) {
+#if INV_CACHE_DMP == 1
+               memcpy(mldl_cfg->mpu_ram->ram, data, size);
+               return INV_SUCCESS;
+#else
+               LOG_RESULT_LOCATION(INV_ERROR_MEMORY_SET);
+               return INV_ERROR_MEMORY_SET;
+#endif
+       }
+
+       if (!(mldl_cfg->inv_mpu_state->status & MPU_DMP_IS_SUSPENDED)) {
+               LOG_RESULT_LOCATION(INV_ERROR_MEMORY_SET);
+               return INV_ERROR_MEMORY_SET;
+       }
+       /* Write and verify memory */
+       for (bank = 0; size > 0; bank++,
+                       size -= write_size,
+                       data += write_size) {
+               if (size > MPU_MEM_BANK_SIZE)
+                       write_size = MPU_MEM_BANK_SIZE;
+               else
+                       write_size = size;
+
+               result = inv_serial_write_mem(mlsl_handle,
+                               mldl_cfg->mpu_chip_info->addr,
+                               ((bank << 8) | 0x00),
+                               write_size,
+                               data);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       MPL_LOGE("Write mem error in bank %d\n", bank);
+                       return result;
+               }
+               result = inv_serial_read_mem(mlsl_handle,
+                               mldl_cfg->mpu_chip_info->addr,
+                               ((bank << 8) | 0x00),
+                               write_size,
+                               read);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       MPL_LOGE("Read mem error in bank %d\n", bank);
+                       return result;
+               }
+
+#define ML_SKIP_CHECK 20
+               for (offset = 0; offset < write_size; offset++) {
+                       /* skip the register memory locations */
+                       if (bank == 0 && offset < ML_SKIP_CHECK)
+                               continue;
+                       if (data[offset] != read[offset]) {
+                               result = INV_ERROR_SERIAL_WRITE;
+                               break;
+                       }
+               }
+               if (result != INV_SUCCESS) {
+                       LOG_RESULT_LOCATION(result);
+                       MPL_LOGE("Read data mismatch at bank %d, offset %d\n",
+                               bank, offset);
+                       return result;
+               }
+       }
+       return INV_SUCCESS;
+}
+
+static int gyro_resume(struct mldl_cfg *mldl_cfg, void *gyro_handle,
+                      unsigned long sensors)
+{
+       int result;
+       int ii;
+       unsigned char reg;
+       unsigned char regs[7];
+
+       /* Wake up the part */
+       result = mpu3050_pwr_mgmt(mldl_cfg, gyro_handle, false, false,
+                                 !(sensors & INV_X_GYRO),
+                                 !(sensors & INV_Y_GYRO),
+                                 !(sensors & INV_Z_GYRO));
+
+       if (!(mldl_cfg->inv_mpu_state->status & MPU_GYRO_NEEDS_CONFIG) &&
+           !mpu_was_reset(mldl_cfg, gyro_handle)) {
+               return INV_SUCCESS;
+       }
+
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(
+               gyro_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_INT_CFG,
+               (mldl_cfg->mpu_gyro_cfg->int_config |
+                       mldl_cfg->pdata->int_config));
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(
+               gyro_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_SMPLRT_DIV, mldl_cfg->mpu_gyro_cfg->divider);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = mpu_set_clock_source(gyro_handle, mldl_cfg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       reg = DLPF_FS_SYNC_VALUE(mldl_cfg->mpu_gyro_cfg->ext_sync,
+                                mldl_cfg->mpu_gyro_cfg->full_scale,
+                                mldl_cfg->mpu_gyro_cfg->lpf);
+       result = inv_serial_single_write(
+               gyro_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_DLPF_FS_SYNC, reg);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(
+               gyro_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_DMP_CFG_1, mldl_cfg->mpu_gyro_cfg->dmp_cfg1);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(
+               gyro_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_DMP_CFG_2, mldl_cfg->mpu_gyro_cfg->dmp_cfg2);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Write and verify memory */
+#if INV_CACHE_DMP != 0
+       inv_mpu_set_firmware(mldl_cfg, gyro_handle,
+               mldl_cfg->mpu_ram->ram, mldl_cfg->mpu_ram->length);
+#endif
+
+       result = inv_serial_single_write(
+               gyro_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_XG_OFFS_TC, mldl_cfg->mpu_offsets->tc[0]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(
+               gyro_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_YG_OFFS_TC, mldl_cfg->mpu_offsets->tc[1]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_single_write(
+               gyro_handle, mldl_cfg->mpu_chip_info->addr,
+               MPUREG_ZG_OFFS_TC, mldl_cfg->mpu_offsets->tc[2]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       regs[0] = MPUREG_X_OFFS_USRH;
+       for (ii = 0; ii < ARRAY_SIZE(mldl_cfg->mpu_offsets->gyro); ii++) {
+               regs[1 + ii * 2] =
+                       (unsigned char)(mldl_cfg->mpu_offsets->gyro[ii] >> 8)
+                       & 0xff;
+               regs[1 + ii * 2 + 1] =
+                       (unsigned char)(mldl_cfg->mpu_offsets->gyro[ii] & 0xff);
+       }
+       result = inv_serial_write(gyro_handle, mldl_cfg->mpu_chip_info->addr,
+                                 7, regs);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Configure slaves */
+       result = inv_mpu_set_level_shifter_bit(mldl_cfg, gyro_handle,
+                                              mldl_cfg->pdata->level_shifter);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       mldl_cfg->inv_mpu_state->status &= ~MPU_GYRO_NEEDS_CONFIG;
+
+       return result;
+}
+
+int gyro_config(void *mlsl_handle,
+               struct mldl_cfg *mldl_cfg,
+               struct ext_slave_config *data)
+{
+       struct mpu_gyro_cfg *mpu_gyro_cfg = mldl_cfg->mpu_gyro_cfg;
+       struct mpu_chip_info *mpu_chip_info = mldl_cfg->mpu_chip_info;
+       struct mpu_offsets *mpu_offsets = mldl_cfg->mpu_offsets;
+       int ii;
+
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_INT_CONFIG:
+               mpu_gyro_cfg->int_config = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_EXT_SYNC:
+               mpu_gyro_cfg->ext_sync = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_FULL_SCALE:
+               mpu_gyro_cfg->full_scale = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_LPF:
+               mpu_gyro_cfg->lpf = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_CLK_SRC:
+               mpu_gyro_cfg->clk_src = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_DIVIDER:
+               mpu_gyro_cfg->divider = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_DMP_ENABLE:
+               mpu_gyro_cfg->dmp_enable = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_FIFO_ENABLE:
+               mpu_gyro_cfg->fifo_enable = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_DMP_CFG1:
+               mpu_gyro_cfg->dmp_cfg1 = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_DMP_CFG2:
+               mpu_gyro_cfg->dmp_cfg2 = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_TC:
+               for (ii = 0; ii < GYRO_NUM_AXES; ii++)
+                       mpu_offsets->tc[ii] = ((__u8 *)data->data)[ii];
+               break;
+       case MPU_SLAVE_GYRO:
+               for (ii = 0; ii < GYRO_NUM_AXES; ii++)
+                       mpu_offsets->gyro[ii] = ((__u16 *)data->data)[ii];
+               break;
+       case MPU_SLAVE_ADDR:
+               mpu_chip_info->addr = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_PRODUCT_REVISION:
+               mpu_chip_info->product_revision = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_SILICON_REVISION:
+               mpu_chip_info->silicon_revision = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_PRODUCT_ID:
+               mpu_chip_info->product_id = *((__u8 *)data->data);
+               break;
+       case MPU_SLAVE_GYRO_SENS_TRIM:
+               mpu_chip_info->gyro_sens_trim = *((__u16 *)data->data);
+               break;
+       case MPU_SLAVE_ACCEL_SENS_TRIM:
+               mpu_chip_info->accel_sens_trim = *((__u16 *)data->data);
+               break;
+       case MPU_SLAVE_RAM:
+               if (data->len != mldl_cfg->mpu_ram->length)
+                       return INV_ERROR_INVALID_PARAMETER;
+
+               memcpy(mldl_cfg->mpu_ram->ram, data->data, data->len);
+               break;
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+       mldl_cfg->inv_mpu_state->status |= MPU_GYRO_NEEDS_CONFIG;
+       return INV_SUCCESS;
+}
+
+int gyro_get_config(void *mlsl_handle,
+               struct mldl_cfg *mldl_cfg,
+               struct ext_slave_config *data)
+{
+       struct mpu_gyro_cfg *mpu_gyro_cfg = mldl_cfg->mpu_gyro_cfg;
+       struct mpu_chip_info *mpu_chip_info = mldl_cfg->mpu_chip_info;
+       struct mpu_offsets *mpu_offsets = mldl_cfg->mpu_offsets;
+       int ii;
+
+       if (!data->data)
+               return INV_ERROR_INVALID_PARAMETER;
+
+       switch (data->key) {
+       case MPU_SLAVE_INT_CONFIG:
+               *((__u8 *)data->data) = mpu_gyro_cfg->int_config;
+               break;
+       case MPU_SLAVE_EXT_SYNC:
+               *((__u8 *)data->data) = mpu_gyro_cfg->ext_sync;
+               break;
+       case MPU_SLAVE_FULL_SCALE:
+               *((__u8 *)data->data) = mpu_gyro_cfg->full_scale;
+               break;
+       case MPU_SLAVE_LPF:
+               *((__u8 *)data->data) = mpu_gyro_cfg->lpf;
+               break;
+       case MPU_SLAVE_CLK_SRC:
+               *((__u8 *)data->data) = mpu_gyro_cfg->clk_src;
+               break;
+       case MPU_SLAVE_DIVIDER:
+               *((__u8 *)data->data) = mpu_gyro_cfg->divider;
+               break;
+       case MPU_SLAVE_DMP_ENABLE:
+               *((__u8 *)data->data) = mpu_gyro_cfg->dmp_enable;
+               break;
+       case MPU_SLAVE_FIFO_ENABLE:
+               *((__u8 *)data->data) = mpu_gyro_cfg->fifo_enable;
+               break;
+       case MPU_SLAVE_DMP_CFG1:
+               *((__u8 *)data->data) = mpu_gyro_cfg->dmp_cfg1;
+               break;
+       case MPU_SLAVE_DMP_CFG2:
+               *((__u8 *)data->data) = mpu_gyro_cfg->dmp_cfg2;
+               break;
+       case MPU_SLAVE_TC:
+               for (ii = 0; ii < GYRO_NUM_AXES; ii++)
+                       ((__u8 *)data->data)[ii] = mpu_offsets->tc[ii];
+               break;
+       case MPU_SLAVE_GYRO:
+               for (ii = 0; ii < GYRO_NUM_AXES; ii++)
+                       ((__u16 *)data->data)[ii] = mpu_offsets->gyro[ii];
+               break;
+       case MPU_SLAVE_ADDR:
+               *((__u8 *)data->data) = mpu_chip_info->addr;
+               break;
+       case MPU_SLAVE_PRODUCT_REVISION:
+               *((__u8 *)data->data) = mpu_chip_info->product_revision;
+               break;
+       case MPU_SLAVE_SILICON_REVISION:
+               *((__u8 *)data->data) = mpu_chip_info->silicon_revision;
+               break;
+       case MPU_SLAVE_PRODUCT_ID:
+               *((__u8 *)data->data) = mpu_chip_info->product_id;
+               break;
+       case MPU_SLAVE_GYRO_SENS_TRIM:
+               *((__u16 *)data->data) = mpu_chip_info->gyro_sens_trim;
+               break;
+       case MPU_SLAVE_ACCEL_SENS_TRIM:
+               *((__u16 *)data->data) = mpu_chip_info->accel_sens_trim;
+               break;
+       case MPU_SLAVE_RAM:
+               if (data->len != mldl_cfg->mpu_ram->length)
+                       return INV_ERROR_INVALID_PARAMETER;
+
+               memcpy(data->data, mldl_cfg->mpu_ram->ram, data->len);
+               break;
+       default:
+               LOG_RESULT_LOCATION(INV_ERROR_FEATURE_NOT_IMPLEMENTED);
+               return INV_ERROR_FEATURE_NOT_IMPLEMENTED;
+       };
+
+       return INV_SUCCESS;
+}
+
+
+/*******************************************************************************
+ *******************************************************************************
+ * Exported functions
+ *******************************************************************************
+ ******************************************************************************/
+
+/**
+ * Initializes the pdata structure to defaults.
+ *
+ * Opens the device to read silicon revision, product id and whoami.
+ *
+ * @mldl_cfg
+ *          The internal device configuration data structure.
+ * @mlsl_handle
+ *          The serial communication handle.
+ *
+ * @return INV_SUCCESS if silicon revision, product id and woami are supported
+ *         by this software.
+ */
+int inv_mpu_open(struct mldl_cfg *mldl_cfg,
+                void *gyro_handle,
+                void *accel_handle,
+                void *compass_handle, void *pressure_handle)
+{
+       int result;
+       void *slave_handle[EXT_SLAVE_NUM_TYPES];
+       int ii;
+
+       /* Default is Logic HIGH, pushpull, latch disabled, anyread to clear */
+       ii = 0;
+       mldl_cfg->inv_mpu_cfg->ignore_system_suspend = false;
+       mldl_cfg->mpu_gyro_cfg->int_config = BIT_DMP_INT_EN;
+       mldl_cfg->mpu_gyro_cfg->clk_src = MPU_CLK_SEL_PLLGYROZ;
+       mldl_cfg->mpu_gyro_cfg->lpf = MPU_FILTER_42HZ;
+       mldl_cfg->mpu_gyro_cfg->full_scale = MPU_FS_2000DPS;
+       mldl_cfg->mpu_gyro_cfg->divider = 4;
+       mldl_cfg->mpu_gyro_cfg->dmp_enable = 1;
+       mldl_cfg->mpu_gyro_cfg->fifo_enable = 1;
+       mldl_cfg->mpu_gyro_cfg->ext_sync = 0;
+       mldl_cfg->mpu_gyro_cfg->dmp_cfg1 = 0;
+       mldl_cfg->mpu_gyro_cfg->dmp_cfg2 = 0;
+       mldl_cfg->inv_mpu_state->status =
+               MPU_DMP_IS_SUSPENDED |
+               MPU_GYRO_IS_SUSPENDED |
+               MPU_ACCEL_IS_SUSPENDED |
+               MPU_COMPASS_IS_SUSPENDED |
+               MPU_PRESSURE_IS_SUSPENDED |
+               MPU_DEVICE_IS_SUSPENDED;
+       mldl_cfg->inv_mpu_state->i2c_slaves_enabled = 0;
+
+       slave_handle[EXT_SLAVE_TYPE_GYROSCOPE] = gyro_handle;
+       slave_handle[EXT_SLAVE_TYPE_ACCEL] = accel_handle;
+       slave_handle[EXT_SLAVE_TYPE_COMPASS] = compass_handle;
+       slave_handle[EXT_SLAVE_TYPE_PRESSURE] = pressure_handle;
+
+       if (mldl_cfg->mpu_chip_info->addr == 0) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       /*
+        * Reset,
+        * Take the DMP out of sleep, and
+        * read the product_id, sillicon rev and whoami
+        */
+       mldl_cfg->inv_mpu_state->status |= MPU_GYRO_IS_BYPASSED;
+       result = mpu3050_pwr_mgmt(mldl_cfg, gyro_handle, RESET, 0, 0, 0, 0);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       result = inv_get_silicon_rev(mldl_cfg, gyro_handle);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Get the factory temperature compensation offsets */
+       result = inv_serial_read(gyro_handle, mldl_cfg->mpu_chip_info->addr,
+                                MPUREG_XG_OFFS_TC, 1,
+                                &mldl_cfg->mpu_offsets->tc[0]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(gyro_handle, mldl_cfg->mpu_chip_info->addr,
+                                MPUREG_YG_OFFS_TC, 1,
+                                &mldl_cfg->mpu_offsets->tc[1]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_serial_read(gyro_handle, mldl_cfg->mpu_chip_info->addr,
+                                MPUREG_ZG_OFFS_TC, 1,
+                                &mldl_cfg->mpu_offsets->tc[2]);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* Into bypass mode before sleeping and calling the slaves init */
+       result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle, true);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       result = inv_mpu_set_level_shifter_bit(mldl_cfg, gyro_handle,
+                       mldl_cfg->pdata->level_shifter);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+
+#if INV_CACHE_DMP != 0
+       result = mpu3050_pwr_mgmt(mldl_cfg, gyro_handle, 0, SLEEP, 0, 0, 0);
+#endif
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+
+       return result;
+
+}
+
+/**
+ * Close the mpu interface
+ *
+ * @mldl_cfg pointer to the configuration structure
+ * @mlsl_handle pointer to the serial layer handle
+ *
+ * @return INV_SUCCESS or non-zero error code
+ */
+int inv_mpu_close(struct mldl_cfg *mldl_cfg,
+                 void *gyro_handle,
+                 void *accel_handle,
+                 void *compass_handle,
+                 void *pressure_handle)
+{
+       return 0;
+}
+
+/**
+ *  @brief  resume the MPU device and all the other sensor
+ *          devices from their low power state.
+ *
+ *  @mldl_cfg
+ *              pointer to the configuration structure
+ *  @gyro_handle
+ *              the main file handle to the MPU device.
+ *  @accel_handle
+ *              an handle to the accelerometer device, if sitting
+ *              onto a separate bus. Can match mlsl_handle if
+ *              the accelerometer device operates on the same
+ *              primary bus of MPU.
+ *  @compass_handle
+ *              an handle to the compass device, if sitting
+ *              onto a separate bus. Can match mlsl_handle if
+ *              the compass device operates on the same
+ *              primary bus of MPU.
+ *  @pressure_handle
+ *              an handle to the pressure sensor device, if sitting
+ *              onto a separate bus. Can match mlsl_handle if
+ *              the pressure sensor device operates on the same
+ *              primary bus of MPU.
+ *  @resume_gyro
+ *              whether resuming the gyroscope device is
+ *              actually needed (if the device supports low power
+ *              mode of some sort).
+ *  @resume_accel
+ *              whether resuming the accelerometer device is
+ *              actually needed (if the device supports low power
+ *              mode of some sort).
+ *  @resume_compass
+ *              whether resuming the compass device is
+ *              actually needed (if the device supports low power
+ *              mode of some sort).
+ *  @resume_pressure
+ *              whether resuming the pressure sensor device is
+ *              actually needed (if the device supports low power
+ *              mode of some sort).
+ *  @return  INV_SUCCESS or a non-zero error code.
+ */
+int inv_mpu_resume(struct mldl_cfg *mldl_cfg,
+                  void *gyro_handle,
+                  void *accel_handle,
+                  void *compass_handle,
+                  void *pressure_handle,
+                  unsigned long sensors)
+{
+       int result = INV_SUCCESS;
+       int ii;
+       bool resume_slave[EXT_SLAVE_NUM_TYPES];
+       bool resume_dmp = sensors & INV_DMP_PROCESSOR;
+       void *slave_handle[EXT_SLAVE_NUM_TYPES];
+       resume_slave[EXT_SLAVE_TYPE_GYROSCOPE] =
+               (sensors & (INV_X_GYRO | INV_Y_GYRO | INV_Z_GYRO));
+       resume_slave[EXT_SLAVE_TYPE_ACCEL] =
+               sensors & INV_THREE_AXIS_ACCEL;
+       resume_slave[EXT_SLAVE_TYPE_COMPASS] =
+               sensors & INV_THREE_AXIS_COMPASS;
+       resume_slave[EXT_SLAVE_TYPE_PRESSURE] =
+               sensors & INV_THREE_AXIS_PRESSURE;
+
+       slave_handle[EXT_SLAVE_TYPE_GYROSCOPE] = gyro_handle;
+       slave_handle[EXT_SLAVE_TYPE_ACCEL] = accel_handle;
+       slave_handle[EXT_SLAVE_TYPE_COMPASS] = compass_handle;
+       slave_handle[EXT_SLAVE_TYPE_PRESSURE] = pressure_handle;
+
+
+       mldl_print_cfg(mldl_cfg);
+
+       /* Skip the Gyro since slave[EXT_SLAVE_TYPE_GYROSCOPE] is NULL */
+       for (ii = EXT_SLAVE_TYPE_ACCEL; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               if (resume_slave[ii] &&
+                   ((!mldl_cfg->slave[ii]) ||
+                       (!mldl_cfg->slave[ii]->resume))) {
+                       LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+                       return INV_ERROR_INVALID_PARAMETER;
+               }
+       }
+
+       if ((resume_slave[EXT_SLAVE_TYPE_GYROSCOPE] || resume_dmp)
+           && ((mldl_cfg->inv_mpu_state->status & MPU_GYRO_IS_SUSPENDED) ||
+               (mldl_cfg->inv_mpu_state->status & MPU_GYRO_NEEDS_CONFIG))) {
+               result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle, 1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               result = dmp_stop(mldl_cfg, gyro_handle);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               result = gyro_resume(mldl_cfg, gyro_handle, sensors);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               if (!mldl_cfg->slave[ii] ||
+                   !mldl_cfg->pdata_slave[ii] ||
+                   !resume_slave[ii] ||
+                   !(mldl_cfg->inv_mpu_state->status & (1 << ii)))
+                       continue;
+
+               if (EXT_SLAVE_BUS_SECONDARY ==
+                   mldl_cfg->pdata_slave[ii]->bus) {
+                       result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle,
+                                                   true);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+               }
+               result = mldl_cfg->slave[ii]->resume(slave_handle[ii],
+                                               mldl_cfg->slave[ii],
+                                               mldl_cfg->pdata_slave[ii]);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               mldl_cfg->inv_mpu_state->status &= ~(1 << ii);
+       }
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               if (resume_dmp &&
+                   !(mldl_cfg->inv_mpu_state->status & (1 << ii)) &&
+                   mldl_cfg->pdata_slave[ii] &&
+                   EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata_slave[ii]->bus) {
+                       result = mpu_set_slave(mldl_cfg,
+                                       gyro_handle,
+                                       mldl_cfg->slave[ii],
+                                       mldl_cfg->pdata_slave[ii],
+                                       mldl_cfg->slave[ii]->type);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+               }
+       }
+
+       /* Turn on the master i2c iterface if necessary */
+       if (resume_dmp) {
+               result = mpu_set_i2c_bypass(
+                       mldl_cfg, gyro_handle,
+                       !(mldl_cfg->inv_mpu_state->i2c_slaves_enabled));
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+
+               /* Now start */
+               result = dmp_start(mldl_cfg, gyro_handle);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       mldl_cfg->inv_mpu_cfg->requested_sensors = sensors;
+
+       return result;
+}
+
+/**
+ *  @brief  suspend the MPU device and all the other sensor
+ *          devices into their low power state.
+ *  @mldl_cfg
+ *              a pointer to the struct mldl_cfg internal data
+ *              structure.
+ *  @gyro_handle
+ *              the main file handle to the MPU device.
+ *  @accel_handle
+ *              an handle to the accelerometer device, if sitting
+ *              onto a separate bus. Can match gyro_handle if
+ *              the accelerometer device operates on the same
+ *              primary bus of MPU.
+ *  @compass_handle
+ *              an handle to the compass device, if sitting
+ *              onto a separate bus. Can match gyro_handle if
+ *              the compass device operates on the same
+ *              primary bus of MPU.
+ *  @pressure_handle
+ *              an handle to the pressure sensor device, if sitting
+ *              onto a separate bus. Can match gyro_handle if
+ *              the pressure sensor device operates on the same
+ *              primary bus of MPU.
+ *  @accel
+ *              whether suspending the accelerometer device is
+ *              actually needed (if the device supports low power
+ *              mode of some sort).
+ *  @compass
+ *              whether suspending the compass device is
+ *              actually needed (if the device supports low power
+ *              mode of some sort).
+ *  @pressure
+ *              whether suspending the pressure sensor device is
+ *              actually needed (if the device supports low power
+ *              mode of some sort).
+ *  @return  INV_SUCCESS or a non-zero error code.
+ */
+int inv_mpu_suspend(struct mldl_cfg *mldl_cfg,
+                   void *gyro_handle,
+                   void *accel_handle,
+                   void *compass_handle,
+                   void *pressure_handle,
+                   unsigned long sensors)
+{
+       int result = INV_SUCCESS;
+       int ii;
+       struct ext_slave_descr **slave = mldl_cfg->slave;
+       struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
+       bool suspend_dmp = ((sensors & INV_DMP_PROCESSOR) == INV_DMP_PROCESSOR);
+       bool suspend_slave[EXT_SLAVE_NUM_TYPES];
+       void *slave_handle[EXT_SLAVE_NUM_TYPES];
+
+       suspend_slave[EXT_SLAVE_TYPE_GYROSCOPE] =
+               ((sensors & (INV_X_GYRO | INV_Y_GYRO | INV_Z_GYRO))
+                       == (INV_X_GYRO | INV_Y_GYRO | INV_Z_GYRO));
+       suspend_slave[EXT_SLAVE_TYPE_ACCEL] =
+               ((sensors & INV_THREE_AXIS_ACCEL) == INV_THREE_AXIS_ACCEL);
+       suspend_slave[EXT_SLAVE_TYPE_COMPASS] =
+               ((sensors & INV_THREE_AXIS_COMPASS) == INV_THREE_AXIS_COMPASS);
+       suspend_slave[EXT_SLAVE_TYPE_PRESSURE] =
+               ((sensors & INV_THREE_AXIS_PRESSURE) ==
+                       INV_THREE_AXIS_PRESSURE);
+
+       slave_handle[EXT_SLAVE_TYPE_GYROSCOPE] = gyro_handle;
+       slave_handle[EXT_SLAVE_TYPE_ACCEL] = accel_handle;
+       slave_handle[EXT_SLAVE_TYPE_COMPASS] = compass_handle;
+       slave_handle[EXT_SLAVE_TYPE_PRESSURE] = pressure_handle;
+
+       if (suspend_dmp) {
+               result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle, 1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               result = dmp_stop(mldl_cfg, gyro_handle);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       /* Gyro */
+       if (suspend_slave[EXT_SLAVE_TYPE_GYROSCOPE] &&
+           !(mldl_cfg->inv_mpu_state->status & MPU_GYRO_IS_SUSPENDED)) {
+               result = mpu3050_pwr_mgmt(
+                       mldl_cfg, gyro_handle, 0,
+                       suspend_dmp && suspend_slave[EXT_SLAVE_TYPE_GYROSCOPE],
+                       (unsigned char)(sensors & INV_X_GYRO),
+                       (unsigned char)(sensors & INV_Y_GYRO),
+                       (unsigned char)(sensors & INV_Z_GYRO));
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               bool is_suspended = mldl_cfg->inv_mpu_state->status & (1 << ii);
+               if (!slave[ii]   || !pdata_slave[ii] ||
+                   is_suspended || !suspend_slave[ii])
+                       continue;
+
+               if (EXT_SLAVE_BUS_SECONDARY == pdata_slave[ii]->bus) {
+                       result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle, 1);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+               }
+               result = slave[ii]->suspend(slave_handle[ii],
+                                                 slave[ii],
+                                                 pdata_slave[ii]);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               if (EXT_SLAVE_BUS_SECONDARY == pdata_slave[ii]->bus) {
+                       result = mpu_set_slave(mldl_cfg, gyro_handle,
+                                              NULL, NULL,
+                                              slave[ii]->type);
+                       if (result) {
+                               LOG_RESULT_LOCATION(result);
+                               return result;
+                       }
+               }
+               mldl_cfg->inv_mpu_state->status |= (1 << ii);
+       }
+
+       /* Re-enable the i2c master if there are configured slaves and DMP */
+       if (!suspend_dmp) {
+               result = mpu_set_i2c_bypass(
+                       mldl_cfg, gyro_handle,
+                       !(mldl_cfg->inv_mpu_state->i2c_slaves_enabled));
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       mldl_cfg->inv_mpu_cfg->requested_sensors = (~sensors) & INV_ALL_SENSORS;
+
+       return result;
+}
+
+int inv_mpu_slave_read(struct mldl_cfg *mldl_cfg,
+                      void *gyro_handle,
+                      void *slave_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata,
+                      unsigned char *data)
+{
+       int result;
+       int bypass_result;
+       int remain_bypassed = true;
+
+       if (NULL == slave || NULL == slave->read) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_CONFIGURATION);
+               return INV_ERROR_INVALID_CONFIGURATION;
+       }
+
+       if ((EXT_SLAVE_BUS_SECONDARY == pdata->bus)
+           && (!(mldl_cfg->inv_mpu_state->status & MPU_GYRO_IS_BYPASSED))) {
+               remain_bypassed = false;
+               result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle, 1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       result = slave->read(slave_handle, slave, pdata, data);
+
+       if (!remain_bypassed) {
+               bypass_result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle, 0);
+               if (bypass_result) {
+                       LOG_RESULT_LOCATION(bypass_result);
+                       return bypass_result;
+               }
+       }
+       return result;
+}
+
+int inv_mpu_slave_config(struct mldl_cfg *mldl_cfg,
+                        void *gyro_handle,
+                        void *slave_handle,
+                        struct ext_slave_config *data,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result;
+       int remain_bypassed = true;
+
+       if (NULL == slave || NULL == slave->config) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_CONFIGURATION);
+               return INV_ERROR_INVALID_CONFIGURATION;
+       }
+
+       if (data->apply && (EXT_SLAVE_BUS_SECONDARY == pdata->bus)
+           && (!(mldl_cfg->inv_mpu_state->status & MPU_GYRO_IS_BYPASSED))) {
+               remain_bypassed = false;
+               result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle, 1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       result = slave->config(slave_handle, slave, pdata, data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       if (!remain_bypassed) {
+               result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle, 0);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       return result;
+}
+
+int inv_mpu_get_slave_config(struct mldl_cfg *mldl_cfg,
+                            void *gyro_handle,
+                            void *slave_handle,
+                            struct ext_slave_config *data,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata)
+{
+       int result;
+       int remain_bypassed = true;
+
+       if (NULL == slave || NULL == slave->get_config) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_CONFIGURATION);
+               return INV_ERROR_INVALID_CONFIGURATION;
+       }
+
+       if (data->apply && (EXT_SLAVE_BUS_SECONDARY == pdata->bus)
+           && (!(mldl_cfg->inv_mpu_state->status & MPU_GYRO_IS_BYPASSED))) {
+               remain_bypassed = false;
+               result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle, 1);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+
+       result = slave->get_config(slave_handle, slave, pdata, data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       if (!remain_bypassed) {
+               result = mpu_set_i2c_bypass(mldl_cfg, gyro_handle, 0);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+       }
+       return result;
+}
+
+/**
+ * @}
+ */
diff --git a/drivers/misc/inv_mpu/mldl_cfg.h b/drivers/misc/inv_mpu/mldl_cfg.h
new file mode 100644 (file)
index 0000000..1c23878
--- /dev/null
@@ -0,0 +1,380 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup MLDL
+ *
+ *  @{
+ *      @file   mldl_cfg.h
+ *      @brief  The Motion Library Driver Layer Configuration header file.
+ */
+
+#ifndef __MLDL_CFG_H__
+#define __MLDL_CFG_H__
+
+#include "mltypes.h"
+#include "mlsl.h"
+#include <linux/mpu.h>
+#include "mpu3050.h"
+
+#include "log.h"
+
+/*************************************************************************
+ *  Sensors Bit definitions
+ *************************************************************************/
+
+#define INV_X_GYRO                     (0x0001)
+#define INV_Y_GYRO                     (0x0002)
+#define INV_Z_GYRO                     (0x0004)
+#define INV_DMP_PROCESSOR              (0x0008)
+
+#define INV_X_ACCEL                    (0x0010)
+#define INV_Y_ACCEL                    (0x0020)
+#define INV_Z_ACCEL                    (0x0040)
+
+#define INV_X_COMPASS                  (0x0080)
+#define INV_Y_COMPASS                  (0x0100)
+#define INV_Z_COMPASS                  (0x0200)
+
+#define INV_X_PRESSURE                 (0x0300)
+#define INV_Y_PRESSURE                 (0x0800)
+#define INV_Z_PRESSURE                 (0x1000)
+
+#define INV_TEMPERATURE                        (0x2000)
+#define INV_TIME                       (0x4000)
+
+#define INV_THREE_AXIS_GYRO            (0x000F)
+#define INV_THREE_AXIS_ACCEL           (0x0070)
+#define INV_THREE_AXIS_COMPASS         (0x0380)
+#define INV_THREE_AXIS_PRESSURE                (0x1C00)
+
+#define INV_FIVE_AXIS                  (0x007B)
+#define INV_SIX_AXIS_GYRO_ACCEL                (0x007F)
+#define INV_SIX_AXIS_ACCEL_COMPASS     (0x03F0)
+#define INV_NINE_AXIS                  (0x03FF)
+#define INV_ALL_SENSORS                        (0x7FFF)
+
+#define MPL_PROD_KEY(ver, rev) (ver * 100 + rev)
+
+/* -------------------------------------------------------------------------- */
+struct mpu_ram {
+       __u16 length;
+       __u8 *ram;
+};
+
+struct mpu_gyro_cfg {
+       __u8 int_config;
+       __u8 ext_sync;
+       __u8 full_scale;
+       __u8 lpf;
+       __u8 clk_src;
+       __u8 divider;
+       __u8 dmp_enable;
+       __u8 fifo_enable;
+       __u8 dmp_cfg1;
+       __u8 dmp_cfg2;
+};
+
+/* Offset registers that can be calibrated */
+struct mpu_offsets {
+       __u8    tc[GYRO_NUM_AXES];
+       __u16   gyro[GYRO_NUM_AXES];
+};
+
+/* Chip related information that can be read and verified */
+struct mpu_chip_info {
+       __u8 addr;
+       __u8 product_revision;
+       __u8 silicon_revision;
+       __u8 product_id;
+       __u16 gyro_sens_trim;
+       /* Only used for MPU6050 */
+       __u16 accel_sens_trim;
+};
+
+
+struct inv_mpu_cfg {
+       __u32 requested_sensors;
+       __u8 ignore_system_suspend;
+};
+
+/* Driver related state information */
+struct inv_mpu_state {
+#define MPU_GYRO_IS_SUSPENDED          (0x01 << EXT_SLAVE_TYPE_GYROSCOPE)
+#define MPU_ACCEL_IS_SUSPENDED         (0x01 << EXT_SLAVE_TYPE_ACCEL)
+#define MPU_COMPASS_IS_SUSPENDED       (0x01 << EXT_SLAVE_TYPE_COMPASS)
+#define MPU_PRESSURE_IS_SUSPENDED      (0x01 << EXT_SLAVE_TYPE_PRESSURE)
+#define MPU_GYRO_IS_BYPASSED           (0x10)
+#define MPU_DMP_IS_SUSPENDED           (0x20)
+#define MPU_GYRO_NEEDS_CONFIG          (0x40)
+#define MPU_DEVICE_IS_SUSPENDED                (0x80)
+       __u8 status;
+       /* 0-1 for 3050, bitfield of BIT_SLVx_DLY_EN, x = [0..4] */
+       __u8 i2c_slaves_enabled;
+};
+
+/* Platform data for the MPU */
+struct mldl_cfg {
+       struct mpu_ram                  *mpu_ram;
+       struct mpu_gyro_cfg             *mpu_gyro_cfg;
+       struct mpu_offsets              *mpu_offsets;
+       struct mpu_chip_info            *mpu_chip_info;
+
+       /* MPU Related stored status and info */
+       struct inv_mpu_cfg              *inv_mpu_cfg;
+       struct inv_mpu_state            *inv_mpu_state;
+
+       /* Slave related information */
+       struct ext_slave_descr          *slave[EXT_SLAVE_NUM_TYPES];
+       /* Platform Data */
+       struct mpu_platform_data        *pdata;
+       struct ext_slave_platform_data  *pdata_slave[EXT_SLAVE_NUM_TYPES];
+};
+
+/* -------------------------------------------------------------------------- */
+
+int inv_mpu_open(struct mldl_cfg *mldl_cfg,
+                void *mlsl_handle,
+                void *accel_handle,
+                void *compass_handle,
+                void *pressure_handle);
+int inv_mpu_close(struct mldl_cfg *mldl_cfg,
+                 void *mlsl_handle,
+                 void *accel_handle,
+                 void *compass_handle,
+                 void *pressure_handle);
+int inv_mpu_resume(struct mldl_cfg *mldl_cfg,
+                  void *gyro_handle,
+                  void *accel_handle,
+                  void *compass_handle,
+                  void *pressure_handle,
+                  unsigned long sensors);
+int inv_mpu_suspend(struct mldl_cfg *mldl_cfg,
+                   void *gyro_handle,
+                   void *accel_handle,
+                   void *compass_handle,
+                   void *pressure_handle,
+                   unsigned long sensors);
+int inv_mpu_set_firmware(struct mldl_cfg *mldl_cfg,
+                        void *mlsl_handle,
+                        const unsigned char *data,
+                        int size);
+
+/* -------------------------------------------------------------------------- */
+/* Slave Read functions */
+int inv_mpu_slave_read(struct mldl_cfg *mldl_cfg,
+                      void *gyro_handle,
+                      void *slave_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata,
+                      unsigned char *data);
+static inline int inv_mpu_read_accel(struct mldl_cfg *mldl_cfg,
+                                    void *gyro_handle,
+                                    void *accel_handle, unsigned char *data)
+{
+       if (!mldl_cfg) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       return inv_mpu_slave_read(
+               mldl_cfg, gyro_handle, accel_handle,
+               mldl_cfg->slave[EXT_SLAVE_TYPE_ACCEL],
+               mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_ACCEL],
+               data);
+}
+
+static inline int inv_mpu_read_compass(struct mldl_cfg *mldl_cfg,
+                                      void *gyro_handle,
+                                      void *compass_handle,
+                                      unsigned char *data)
+{
+       if (!mldl_cfg) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       return inv_mpu_slave_read(
+               mldl_cfg, gyro_handle, compass_handle,
+               mldl_cfg->slave[EXT_SLAVE_TYPE_COMPASS],
+               mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_COMPASS],
+               data);
+}
+
+static inline int inv_mpu_read_pressure(struct mldl_cfg *mldl_cfg,
+                                       void *gyro_handle,
+                                       void *pressure_handle,
+                                       unsigned char *data)
+{
+       if (!mldl_cfg) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       return inv_mpu_slave_read(
+               mldl_cfg, gyro_handle, pressure_handle,
+               mldl_cfg->slave[EXT_SLAVE_TYPE_PRESSURE],
+               mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_PRESSURE],
+               data);
+}
+
+int gyro_config(void *mlsl_handle,
+               struct mldl_cfg *mldl_cfg,
+               struct ext_slave_config *data);
+
+/* Slave Config functions */
+int inv_mpu_slave_config(struct mldl_cfg *mldl_cfg,
+                        void *gyro_handle,
+                        void *slave_handle,
+                        struct ext_slave_config *data,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata);
+static inline int inv_mpu_config_accel(struct mldl_cfg *mldl_cfg,
+                                      void *gyro_handle,
+                                      void *accel_handle,
+                                      struct ext_slave_config *data)
+{
+       if (!mldl_cfg) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       return inv_mpu_slave_config(
+               mldl_cfg, gyro_handle, accel_handle, data,
+               mldl_cfg->slave[EXT_SLAVE_TYPE_ACCEL],
+               mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_ACCEL]);
+}
+
+static inline int inv_mpu_config_compass(struct mldl_cfg *mldl_cfg,
+                                        void *gyro_handle,
+                                        void *compass_handle,
+                                        struct ext_slave_config *data)
+{
+       if (!mldl_cfg) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       return inv_mpu_slave_config(
+               mldl_cfg, gyro_handle, compass_handle, data,
+               mldl_cfg->slave[EXT_SLAVE_TYPE_COMPASS],
+               mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_COMPASS]);
+}
+
+static inline int inv_mpu_config_pressure(struct mldl_cfg *mldl_cfg,
+                                         void *gyro_handle,
+                                         void *pressure_handle,
+                                         struct ext_slave_config *data)
+{
+       if (!mldl_cfg) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       return inv_mpu_slave_config(
+               mldl_cfg, gyro_handle, pressure_handle, data,
+               mldl_cfg->slave[EXT_SLAVE_TYPE_PRESSURE],
+               mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_PRESSURE]);
+}
+
+int gyro_get_config(void *mlsl_handle,
+               struct mldl_cfg *mldl_cfg,
+               struct ext_slave_config *data);
+
+/* Slave get config functions */
+int inv_mpu_get_slave_config(struct mldl_cfg *mldl_cfg,
+                            void *gyro_handle,
+                            void *slave_handle,
+                            struct ext_slave_config *data,
+                            struct ext_slave_descr *slave,
+                            struct ext_slave_platform_data *pdata);
+
+static inline int inv_mpu_get_accel_config(struct mldl_cfg *mldl_cfg,
+                                          void *gyro_handle,
+                                          void *accel_handle,
+                                          struct ext_slave_config *data)
+{
+       if (!mldl_cfg) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       return inv_mpu_get_slave_config(
+               mldl_cfg, gyro_handle, accel_handle, data,
+               mldl_cfg->slave[EXT_SLAVE_TYPE_ACCEL],
+               mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_ACCEL]);
+}
+
+static inline int inv_mpu_get_compass_config(struct mldl_cfg *mldl_cfg,
+                                            void *gyro_handle,
+                                            void *compass_handle,
+                                            struct ext_slave_config *data)
+{
+       if (!mldl_cfg || !(mldl_cfg->pdata)) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       return inv_mpu_get_slave_config(
+               mldl_cfg, gyro_handle, compass_handle, data,
+               mldl_cfg->slave[EXT_SLAVE_TYPE_COMPASS],
+               mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_COMPASS]);
+}
+
+static inline int inv_mpu_get_pressure_config(struct mldl_cfg *mldl_cfg,
+                                             void *gyro_handle,
+                                             void *pressure_handle,
+                                             struct ext_slave_config *data)
+{
+       if (!mldl_cfg || !(mldl_cfg->pdata)) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       return inv_mpu_get_slave_config(
+               mldl_cfg, gyro_handle, pressure_handle, data,
+               mldl_cfg->slave[EXT_SLAVE_TYPE_PRESSURE],
+               mldl_cfg->pdata_slave[EXT_SLAVE_TYPE_PRESSURE]);
+}
+
+/* -------------------------------------------------------------------------- */
+
+static inline
+long inv_mpu_get_sampling_rate_hz(struct mpu_gyro_cfg *gyro_cfg)
+{
+       if (((gyro_cfg->lpf) == 0) || ((gyro_cfg->lpf) == 7))
+               return 8000L / (gyro_cfg->divider + 1);
+       else
+               return 1000L / (gyro_cfg->divider + 1);
+}
+
+static inline
+long inv_mpu_get_sampling_period_us(struct mpu_gyro_cfg *gyro_cfg)
+{
+       if (((gyro_cfg->lpf) == 0) || ((gyro_cfg->lpf) == 7))
+               return (long) (1000000L * (gyro_cfg->divider + 1)) / 8000L;
+       else
+               return (long) (1000000L * (gyro_cfg->divider + 1)) / 1000L;
+}
+
+#endif                         /* __MLDL_CFG_H__ */
+
+/**
+ * @}
+ */
diff --git a/drivers/misc/inv_mpu/mldl_print_cfg.c b/drivers/misc/inv_mpu/mldl_print_cfg.c
new file mode 100644 (file)
index 0000000..5c6951b
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @addtogroup MLDL
+ *
+ *  @{
+ *      @file   mldl_print_cfg.c
+ *      @brief  The Motion Library Driver Layer.
+ */
+
+#include <stddef.h>
+#include "mldl_cfg.h"
+#include "mlsl.h"
+#include "linux/mpu.h"
+
+#include "log.h"
+#undef MPL_LOG_TAG
+#define MPL_LOG_TAG "mldl_print_cfg:"
+
+#undef MPL_LOG_NDEBUG
+#define MPL_LOG_NDEBUG 0
+
+void mldl_print_cfg(struct mldl_cfg *mldl_cfg)
+{
+       struct mpu_gyro_cfg     *mpu_gyro_cfg   = mldl_cfg->mpu_gyro_cfg;
+       struct mpu_offsets      *mpu_offsets    = mldl_cfg->mpu_offsets;
+       struct mpu_chip_info    *mpu_chip_info  = mldl_cfg->mpu_chip_info;
+       struct inv_mpu_cfg      *inv_mpu_cfg    = mldl_cfg->inv_mpu_cfg;
+       struct inv_mpu_state    *inv_mpu_state  = mldl_cfg->inv_mpu_state;
+       struct ext_slave_descr  **slave         = mldl_cfg->slave;
+       struct mpu_platform_data *pdata         = mldl_cfg->pdata;
+       struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
+       int ii;
+
+       /* mpu_gyro_cfg */
+       MPL_LOGI("int_config     = %02x\n", mpu_gyro_cfg->int_config);
+       MPL_LOGI("ext_sync       = %02x\n", mpu_gyro_cfg->ext_sync);
+       MPL_LOGI("full_scale     = %02x\n", mpu_gyro_cfg->full_scale);
+       MPL_LOGI("lpf            = %02x\n", mpu_gyro_cfg->lpf);
+       MPL_LOGI("clk_src        = %02x\n", mpu_gyro_cfg->clk_src);
+       MPL_LOGI("divider        = %02x\n", mpu_gyro_cfg->divider);
+       MPL_LOGI("dmp_enable     = %02x\n", mpu_gyro_cfg->dmp_enable);
+       MPL_LOGI("fifo_enable    = %02x\n", mpu_gyro_cfg->fifo_enable);
+       MPL_LOGI("dmp_cfg1       = %02x\n", mpu_gyro_cfg->dmp_cfg1);
+       MPL_LOGI("dmp_cfg2       = %02x\n", mpu_gyro_cfg->dmp_cfg2);
+       /* mpu_offsets */
+       MPL_LOGV("tc[0]      = %02x\n", mpu_offsets->tc[0]);
+       MPL_LOGV("tc[1]      = %02x\n", mpu_offsets->tc[1]);
+       MPL_LOGV("tc[2]      = %02x\n", mpu_offsets->tc[2]);
+       MPL_LOGV("gyro[0]    = %04x\n", mpu_offsets->gyro[0]);
+       MPL_LOGV("gyro[1]    = %04x\n", mpu_offsets->gyro[1]);
+       MPL_LOGV("gyro[2]    = %04x\n", mpu_offsets->gyro[2]);
+
+       /* mpu_chip_info */
+       MPL_LOGV("addr            = %02x\n", mldl_cfg->mpu_chip_info->addr);
+
+       MPL_LOGV("silicon_revision = %02x\n", mpu_chip_info->silicon_revision);
+       MPL_LOGV("product_revision = %02x\n", mpu_chip_info->product_revision);
+       MPL_LOGV("product_id       = %02x\n", mpu_chip_info->product_id);
+       MPL_LOGV("gyro_sens_trim   = %02x\n", mpu_chip_info->gyro_sens_trim);
+
+       MPL_LOGV("requested_sensors = %04x\n", inv_mpu_cfg->requested_sensors);
+       MPL_LOGV("ignore_system_suspend= %04x\n",
+               inv_mpu_cfg->ignore_system_suspend);
+       MPL_LOGV("status = %04x\n", inv_mpu_state->status);
+       MPL_LOGV("i2c_slaves_enabled= %04x\n",
+               inv_mpu_state->i2c_slaves_enabled);
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               if (!slave[ii])
+                       continue;
+               MPL_LOGV("SLAVE %d:\n", ii);
+               MPL_LOGV("    suspend  = %02x\n", (int)slave[ii]->suspend);
+               MPL_LOGV("    resume   = %02x\n", (int)slave[ii]->resume);
+               MPL_LOGV("    read     = %02x\n", (int)slave[ii]->read);
+               MPL_LOGV("    type     = %02x\n", slave[ii]->type);
+               MPL_LOGV("    reg      = %02x\n", slave[ii]->read_reg);
+               MPL_LOGV("    len      = %02x\n", slave[ii]->read_len);
+               MPL_LOGV("    endian   = %02x\n", slave[ii]->endian);
+               MPL_LOGV("    range.mantissa= %02x\n",
+                       slave[ii]->range.mantissa);
+               MPL_LOGV("    range.fraction= %02x\n",
+                       slave[ii]->range.fraction);
+       }
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               if (!pdata_slave[ii])
+                       continue;
+               MPL_LOGV("PDATA_SLAVE[%d]\n", ii);
+               MPL_LOGV("    irq        = %02x\n", pdata_slave[ii]->irq);
+               MPL_LOGV("    adapt_num  = %02x\n", pdata_slave[ii]->adapt_num);
+               MPL_LOGV("    bus        = %02x\n", pdata_slave[ii]->bus);
+               MPL_LOGV("    address    = %02x\n", pdata_slave[ii]->address);
+               MPL_LOGV("    orientation=\n"
+                       "                            %2d %2d %2d\n"
+                       "                            %2d %2d %2d\n"
+                       "                            %2d %2d %2d\n",
+                       pdata_slave[ii]->orientation[0],
+                       pdata_slave[ii]->orientation[1],
+                       pdata_slave[ii]->orientation[2],
+                       pdata_slave[ii]->orientation[3],
+                       pdata_slave[ii]->orientation[4],
+                       pdata_slave[ii]->orientation[5],
+                       pdata_slave[ii]->orientation[6],
+                       pdata_slave[ii]->orientation[7],
+                       pdata_slave[ii]->orientation[8]);
+       }
+
+       MPL_LOGV("pdata->int_config         = %02x\n", pdata->int_config);
+       MPL_LOGV("pdata->level_shifter      = %02x\n", pdata->level_shifter);
+       MPL_LOGV("pdata->orientation        =\n"
+                "                            %2d %2d %2d\n"
+                "                            %2d %2d %2d\n"
+                "                            %2d %2d %2d\n",
+                pdata->orientation[0], pdata->orientation[1],
+                pdata->orientation[2], pdata->orientation[3],
+                pdata->orientation[4], pdata->orientation[5],
+                pdata->orientation[6], pdata->orientation[7],
+                pdata->orientation[8]);
+}
diff --git a/drivers/misc/inv_mpu/mldl_print_cfg.h b/drivers/misc/inv_mpu/mldl_print_cfg.h
new file mode 100644 (file)
index 0000000..2e19114
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ * @defgroup
+ * @brief
+ *
+ * @{
+ * @file     mldl_print_cfg.h
+ * @brief
+ *
+ *
+ */
+#ifndef __MLDL_PRINT_CFG__
+#define __MLDL_PRINT_CFG__
+
+#include "mldl_cfg.h"
+
+
+void mldl_print_cfg(struct mldl_cfg *mldl_cfg);
+
+#endif /* __MLDL_PRINT_CFG__ */
diff --git a/drivers/misc/inv_mpu/mlsl-kernel.c b/drivers/misc/inv_mpu/mlsl-kernel.c
new file mode 100755 (executable)
index 0000000..25b5fb0
--- /dev/null
@@ -0,0 +1,440 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+#include "mlsl.h"
+#include <linux/i2c.h>
+#include "log.h"
+#include "mpu3050.h"
+
+#define MPU_I2C_RATE 200*1000
+static int inv_i2c_write(struct i2c_adapter *i2c_adap,
+                           unsigned char address,
+                           unsigned int len, unsigned char const *data)
+{
+       struct i2c_msg msgs[1];
+       int res;
+
+       if (!data || !i2c_adap) {
+               LOG_RESULT_LOCATION(-EINVAL);
+               return -EINVAL;
+       }
+
+       msgs[0].addr = address;
+       msgs[0].flags = 0;      /* write */
+       msgs[0].buf = (unsigned char *)data;
+       msgs[0].len = len;
+       msgs[0].scl_rate = MPU_I2C_RATE;
+       //msgs[0].udelay = 200;
+
+       res = i2c_transfer(i2c_adap, msgs, 1);
+       if (res == 1)
+               return 0;
+       else if(res == 0)
+               return -EBUSY;
+       else
+               return res;
+
+}
+
+static int inv_i2c_write_register(struct i2c_adapter *i2c_adap,
+                                    unsigned char address,
+                                    unsigned char reg, unsigned char value)
+{
+       unsigned char data[2];
+
+       data[0] = reg;
+       data[1] = value;
+       return inv_i2c_write(i2c_adap, address, 2, data);
+}
+
+static int inv_i2c_read(struct i2c_adapter *i2c_adap,
+                          unsigned char address, unsigned char reg,
+                          unsigned int len, unsigned char *data)
+{
+       struct i2c_msg msgs[2];
+       int res;
+
+       if (!data || !i2c_adap) {
+               LOG_RESULT_LOCATION(-EINVAL);
+               return -EINVAL;
+       }
+
+       msgs[0].addr = address;
+       msgs[0].flags = 0;      /* write */
+       msgs[0].buf = &reg;
+       msgs[0].len = 1;
+       msgs[0].scl_rate = MPU_I2C_RATE;
+       //msgs[0].udelay = 200;
+       
+       msgs[1].addr = address;
+       msgs[1].flags = I2C_M_RD;
+       msgs[1].buf = data;
+       msgs[1].len = len;
+       msgs[1].scl_rate = MPU_I2C_RATE;        
+       //msgs[1].udelay = 200;
+
+       res = i2c_transfer(i2c_adap, msgs, 2);
+       if (res == 2)
+               return 0;
+       else if(res == 0)
+               return -EBUSY;
+       else
+               return res;
+
+}
+
+static int mpu_memory_read(struct i2c_adapter *i2c_adap,
+                          unsigned char mpu_addr,
+                          unsigned short mem_addr,
+                          unsigned int len, unsigned char *data)
+{
+       unsigned char bank[2];
+       unsigned char addr[2];
+       unsigned char buf;
+
+       struct i2c_msg msgs[4];
+       int res;
+
+       if (!data || !i2c_adap) {
+               LOG_RESULT_LOCATION(-EINVAL);
+               return -EINVAL;
+       }
+
+       bank[0] = MPUREG_BANK_SEL;
+       bank[1] = mem_addr >> 8;
+
+       addr[0] = MPUREG_MEM_START_ADDR;
+       addr[1] = mem_addr & 0xFF;
+
+       buf = MPUREG_MEM_R_W;
+
+       /* write message */
+       msgs[0].addr = mpu_addr;
+       msgs[0].flags = 0;
+       msgs[0].buf = bank;
+       msgs[0].len = sizeof(bank);
+       msgs[0].scl_rate = MPU_I2C_RATE;
+       //msgs[0].udelay = 200;
+
+       msgs[1].addr = mpu_addr;
+       msgs[1].flags = 0;
+       msgs[1].buf = addr;
+       msgs[1].len = sizeof(addr);
+       msgs[1].scl_rate = MPU_I2C_RATE;
+       //msgs[1].udelay = 200;
+
+       msgs[2].addr = mpu_addr;
+       msgs[2].flags = 0;
+       msgs[2].buf = &buf;
+       msgs[2].len = 1;
+       msgs[2].scl_rate = MPU_I2C_RATE;
+       //msgs[2].udelay = 200;
+
+       msgs[3].addr = mpu_addr;
+       msgs[3].flags = I2C_M_RD;
+       msgs[3].buf = data;
+       msgs[3].len = len;
+       msgs[3].scl_rate = MPU_I2C_RATE;
+       //msgs[3].udelay = 200;
+
+       res = i2c_transfer(i2c_adap, msgs, 4);
+       if (res == 4)
+               return 0;
+       else if(res == 0)
+               return -EBUSY;
+       else
+               return res;
+}
+
+static int mpu_memory_write(struct i2c_adapter *i2c_adap,
+                           unsigned char mpu_addr,
+                           unsigned short mem_addr,
+                           unsigned int len, unsigned char const *data)
+{
+       unsigned char bank[2];
+       unsigned char addr[2];
+       unsigned char buf[513];
+
+       struct i2c_msg msgs[3];
+       int res;
+
+       if (!data || !i2c_adap) {
+               LOG_RESULT_LOCATION(-EINVAL);
+               return -EINVAL;
+       }
+       if (len >= (sizeof(buf) - 1)) {
+               LOG_RESULT_LOCATION(-ENOMEM);
+               return -ENOMEM;
+       }
+
+       bank[0] = MPUREG_BANK_SEL;
+       bank[1] = mem_addr >> 8;
+
+       addr[0] = MPUREG_MEM_START_ADDR;
+       addr[1] = mem_addr & 0xFF;
+
+       buf[0] = MPUREG_MEM_R_W;
+       memcpy(buf + 1, data, len);
+
+       /* write message */
+       msgs[0].addr = mpu_addr;
+       msgs[0].flags = 0;
+       msgs[0].buf = bank;
+       msgs[0].len = sizeof(bank);
+       msgs[0].scl_rate = MPU_I2C_RATE;
+       //msgs[0].udelay = 200; 
+
+       msgs[1].addr = mpu_addr;
+       msgs[1].flags = 0;
+       msgs[1].buf = addr;
+       msgs[1].len = sizeof(addr);
+       msgs[1].scl_rate = MPU_I2C_RATE;
+       //msgs[1].udelay = 200;
+
+       msgs[2].addr = mpu_addr;
+       msgs[2].flags = 0;
+       msgs[2].buf = (unsigned char *)buf;
+       msgs[2].len = len + 1;
+       msgs[2].scl_rate = MPU_I2C_RATE;
+       //msgs[2].udelay = 200;
+
+       res = i2c_transfer(i2c_adap, msgs, 3);
+       if (res == 3)
+               return 0;
+       else if(res == 0)
+               return -EBUSY;
+       else
+               return res;
+
+}
+
+int inv_serial_single_write(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned char register_addr,
+       unsigned char data)
+{
+       return inv_i2c_write_register((struct i2c_adapter *)sl_handle,
+                                     slave_addr, register_addr, data);
+}
+EXPORT_SYMBOL(inv_serial_single_write);
+
+int inv_serial_write(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned short length,
+       unsigned char const *data)
+{
+       int result;
+       const unsigned short data_length = length - 1;
+       const unsigned char start_reg_addr = data[0];
+       unsigned char i2c_write[SERIAL_MAX_TRANSFER_SIZE + 1];
+       unsigned short bytes_written = 0;
+
+       while (bytes_written < data_length) {
+               unsigned short this_len = min(SERIAL_MAX_TRANSFER_SIZE,
+                                            data_length - bytes_written);
+               if (bytes_written == 0) {
+                       result = inv_i2c_write((struct i2c_adapter *)
+                                              sl_handle, slave_addr,
+                                              1 + this_len, data);
+               } else {
+                       /* manually increment register addr between chunks */
+                       i2c_write[0] = start_reg_addr + bytes_written;
+                       memcpy(&i2c_write[1], &data[1 + bytes_written],
+                               this_len);
+                       result = inv_i2c_write((struct i2c_adapter *)
+                                              sl_handle, slave_addr,
+                                              1 + this_len, i2c_write);
+               }
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               bytes_written += this_len;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(inv_serial_write);
+
+int inv_serial_read(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned char register_addr,
+       unsigned short length,
+       unsigned char *data)
+{
+       int result;
+       unsigned short bytes_read = 0;
+
+       if ((slave_addr & 0x7E) == DEFAULT_MPU_SLAVEADDR
+               && (register_addr == MPUREG_FIFO_R_W ||
+                   register_addr == MPUREG_MEM_R_W)) {
+               LOG_RESULT_LOCATION(INV_ERROR_INVALID_PARAMETER);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+
+       while (bytes_read < length) {
+               unsigned short this_len =
+                   min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_read);
+               result = inv_i2c_read((struct i2c_adapter *)sl_handle,
+                                     slave_addr, register_addr + bytes_read,
+                                     this_len, &data[bytes_read]);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               bytes_read += this_len;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(inv_serial_read);
+
+int inv_serial_write_mem(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned short mem_addr,
+       unsigned short length,
+       unsigned char const *data)
+{
+       int result;
+       unsigned short bytes_written = 0;
+
+       if ((mem_addr & 0xFF) + length > MPU_MEM_BANK_SIZE) {
+               pr_err("memory read length (%d B) extends beyond its"
+                      " limits (%d) if started at location %d\n", length,
+                      MPU_MEM_BANK_SIZE, mem_addr & 0xFF);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+       while (bytes_written < length) {
+               unsigned short this_len =
+                   min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_written);
+               result = mpu_memory_write((struct i2c_adapter *)sl_handle,
+                                         slave_addr, mem_addr + bytes_written,
+                                         this_len, &data[bytes_written]);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               bytes_written += this_len;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(inv_serial_write_mem);
+
+int inv_serial_read_mem(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned short mem_addr,
+       unsigned short length,
+       unsigned char *data)
+{
+       int result;
+       unsigned short bytes_read = 0;
+
+       if ((mem_addr & 0xFF) + length > MPU_MEM_BANK_SIZE) {
+               printk
+                   ("memory read length (%d B) extends beyond its limits (%d) "
+                    "if started at location %d\n", length,
+                    MPU_MEM_BANK_SIZE, mem_addr & 0xFF);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+       while (bytes_read < length) {
+               unsigned short this_len =
+                   min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_read);
+               result =
+                   mpu_memory_read((struct i2c_adapter *)sl_handle,
+                                   slave_addr, mem_addr + bytes_read,
+                                   this_len, &data[bytes_read]);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               bytes_read += this_len;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(inv_serial_read_mem);
+
+int inv_serial_write_fifo(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned short length,
+       unsigned char const *data)
+{
+       int result;
+       unsigned char i2c_write[SERIAL_MAX_TRANSFER_SIZE + 1];
+       unsigned short bytes_written = 0;
+
+       if (length > FIFO_HW_SIZE) {
+               printk(KERN_ERR
+                      "maximum fifo write length is %d\n", FIFO_HW_SIZE);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+       while (bytes_written < length) {
+               unsigned short this_len =
+                   min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_written);
+               i2c_write[0] = MPUREG_FIFO_R_W;
+               memcpy(&i2c_write[1], &data[bytes_written], this_len);
+               result = inv_i2c_write((struct i2c_adapter *)sl_handle,
+                                      slave_addr, this_len + 1, i2c_write);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               bytes_written += this_len;
+       }
+       return 0;
+}
+EXPORT_SYMBOL(inv_serial_write_fifo);
+
+int inv_serial_read_fifo(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned short length,
+       unsigned char *data)
+{
+       int result;
+       unsigned short bytes_read = 0;
+
+       if (length > FIFO_HW_SIZE) {
+               printk(KERN_ERR
+                      "maximum fifo read length is %d\n", FIFO_HW_SIZE);
+               return INV_ERROR_INVALID_PARAMETER;
+       }
+       while (bytes_read < length) {
+               unsigned short this_len =
+                   min(SERIAL_MAX_TRANSFER_SIZE, length - bytes_read);
+               result = inv_i2c_read((struct i2c_adapter *)sl_handle,
+                                     slave_addr, MPUREG_FIFO_R_W, this_len,
+                                     &data[bytes_read]);
+               if (result) {
+                       LOG_RESULT_LOCATION(result);
+                       return result;
+               }
+               bytes_read += this_len;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(inv_serial_read_fifo);
+
+/**
+ *  @}
+ */
diff --git a/drivers/misc/inv_mpu/mlsl.h b/drivers/misc/inv_mpu/mlsl.h
new file mode 100644 (file)
index 0000000..204baed
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+#ifndef __MLSL_H__
+#define __MLSL_H__
+
+/**
+ *  @defgroup   MLSL
+ *  @brief      Motion Library - Serial Layer.
+ *              The Motion Library System Layer provides the Motion Library
+ *              with the communication interface to the hardware.
+ *
+ *              The communication interface is assumed to support serial
+ *              transfers in burst of variable length up to
+ *              SERIAL_MAX_TRANSFER_SIZE.
+ *              The default value for SERIAL_MAX_TRANSFER_SIZE is 128 bytes.
+ *              Transfers of length greater than SERIAL_MAX_TRANSFER_SIZE, will
+ *              be subdivided in smaller transfers of length <=
+ *              SERIAL_MAX_TRANSFER_SIZE.
+ *              The SERIAL_MAX_TRANSFER_SIZE definition can be modified to
+ *              overcome any host processor transfer size limitation down to
+ *              1 B, the minimum.
+ *              An higher value for SERIAL_MAX_TRANSFER_SIZE will favor
+ *              performance and efficiency while requiring higher resource usage
+ *              (mostly buffering). A smaller value will increase overhead and
+ *              decrease efficiency but allows to operate with more resource
+ *              constrained processor and master serial controllers.
+ *              The SERIAL_MAX_TRANSFER_SIZE definition can be found in the
+ *              mlsl.h header file and master serial controllers.
+ *              The SERIAL_MAX_TRANSFER_SIZE definition can be found in the
+ *              mlsl.h header file.
+ *
+ *  @{
+ *      @file   mlsl.h
+ *      @brief  The Motion Library System Layer.
+ *
+ */
+
+#include "mltypes.h"
+#include <linux/mpu.h>
+
+
+/*
+ * NOTE : to properly support Yamaha compass reads,
+ *       the max transfer size should be at least 9 B.
+ *       Length in bytes, typically a power of 2 >= 2
+ */
+#define SERIAL_MAX_TRANSFER_SIZE 128
+
+
+/**
+ *  inv_serial_single_write() - used to write a single byte of data.
+ *  @sl_handle         pointer to the serial device used for the communication.
+ *  @slave_addr                I2C slave address of device.
+ *  @register_addr     Register address to write.
+ *  @data              Single byte of data to write.
+ *
+ *     It is called by the MPL to write a single byte of data to the MPU.
+ *
+ *  returns INV_SUCCESS if successful, a non-zero error code otherwise.
+ */
+int inv_serial_single_write(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned char register_addr,
+       unsigned char data);
+
+/**
+ *  inv_serial_write() - used to write multiple bytes of data to registers.
+ *  @sl_handle a file handle to the serial device used for the communication.
+ *  @slave_addr        I2C slave address of device.
+ *  @register_addr     Register address to write.
+ *  @length    Length of burst of data.
+ *  @data      Pointer to block of data.
+ *
+ *  returns INV_SUCCESS if successful, a non-zero error code otherwise.
+ */
+int inv_serial_write(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned short length,
+       unsigned char const *data);
+
+/**
+ *  inv_serial_read() - used to read multiple bytes of data from registers.
+ *  @sl_handle a file handle to the serial device used for the communication.
+ *  @slave_addr        I2C slave address of device.
+ *  @register_addr     Register address to read.
+ *  @length    Length of burst of data.
+ *  @data      Pointer to block of data.
+ *
+ *  returns INV_SUCCESS == 0 if successful; a non-zero error code otherwise.
+ */
+int inv_serial_read(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned char register_addr,
+       unsigned short length,
+       unsigned char *data);
+
+/**
+ *  inv_serial_read_mem() - used to read multiple bytes of data from the memory.
+ *         This should be sent by I2C or SPI.
+ *
+ *  @sl_handle a file handle to the serial device used for the communication.
+ *  @slave_addr        I2C slave address of device.
+ *  @mem_addr  The location in the memory to read from.
+ *  @length    Length of burst data.
+ *  @data      Pointer to block of data.
+ *
+ *  returns INV_SUCCESS == 0 if successful; a non-zero error code otherwise.
+ */
+int inv_serial_read_mem(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned short mem_addr,
+       unsigned short length,
+       unsigned char *data);
+
+/**
+ *  inv_serial_write_mem() - used to write multiple bytes of data to the memory.
+ *  @sl_handle a file handle to the serial device used for the communication.
+ *  @slave_addr        I2C slave address of device.
+ *  @mem_addr  The location in the memory to write to.
+ *  @length    Length of burst data.
+ *  @data      Pointer to block of data.
+ *
+ *  returns INV_SUCCESS == 0 if successful; a non-zero error code otherwise.
+ */
+int inv_serial_write_mem(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned short mem_addr,
+       unsigned short length,
+       unsigned char const *data);
+
+/**
+ *  inv_serial_read_fifo() - used to read multiple bytes of data from the fifo.
+ *  @sl_handle a file handle to the serial device used for the communication.
+ *  @slave_addr        I2C slave address of device.
+ *  @length    Length of burst of data.
+ *  @data      Pointer to block of data.
+ *
+ *  returns INV_SUCCESS == 0 if successful; a non-zero error code otherwise.
+ */
+int inv_serial_read_fifo(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned short length,
+       unsigned char *data);
+
+/**
+ *  inv_serial_write_fifo() - used to write multiple bytes of data to the fifo.
+ *  @sl_handle a file handle to the serial device used for the communication.
+ *  @slave_addr        I2C slave address of device.
+ *  @length    Length of burst of data.
+ *  @data      Pointer to block of data.
+ *
+ *  returns INV_SUCCESS == 0 if successful; a non-zero error code otherwise.
+ */
+int inv_serial_write_fifo(
+       void *sl_handle,
+       unsigned char slave_addr,
+       unsigned short length,
+       unsigned char const *data);
+
+/**
+ * @}
+ */
+#endif                         /* __MLSL_H__ */
diff --git a/drivers/misc/inv_mpu/mltypes.h b/drivers/misc/inv_mpu/mltypes.h
new file mode 100644 (file)
index 0000000..a249f93
--- /dev/null
@@ -0,0 +1,234 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @defgroup MLERROR
+ *  @brief  Definition of the error codes used within the MPL and
+ *          returned to the user.
+ *          Every function tries to return a meaningful error code basing
+ *          on the occuring error condition. The error code is numeric.
+ *
+ *          The available error codes and their associated values are:
+ *          - (0)               INV_SUCCESS
+ *          - (32)              INV_ERROR
+ *          - (22 / EINVAL)     INV_ERROR_INVALID_PARAMETER
+ *          - (1  / EPERM)      INV_ERROR_FEATURE_NOT_ENABLED
+ *          - (36)              INV_ERROR_FEATURE_NOT_IMPLEMENTED
+ *          - (38)              INV_ERROR_DMP_NOT_STARTED
+ *          - (39)              INV_ERROR_DMP_STARTED
+ *          - (40)              INV_ERROR_NOT_OPENED
+ *          - (41)              INV_ERROR_OPENED
+ *          - (19 / ENODEV)     INV_ERROR_INVALID_MODULE
+ *          - (12 / ENOMEM)     INV_ERROR_MEMORY_EXAUSTED
+ *          - (44)              INV_ERROR_DIVIDE_BY_ZERO
+ *          - (45)              INV_ERROR_ASSERTION_FAILURE
+ *          - (46)              INV_ERROR_FILE_OPEN
+ *          - (47)              INV_ERROR_FILE_READ
+ *          - (48)              INV_ERROR_FILE_WRITE
+ *          - (49)              INV_ERROR_INVALID_CONFIGURATION
+ *          - (52)              INV_ERROR_SERIAL_CLOSED
+ *          - (53)              INV_ERROR_SERIAL_OPEN_ERROR
+ *          - (54)              INV_ERROR_SERIAL_READ
+ *          - (55)              INV_ERROR_SERIAL_WRITE
+ *          - (56)              INV_ERROR_SERIAL_DEVICE_NOT_RECOGNIZED
+ *          - (57)              INV_ERROR_SM_TRANSITION
+ *          - (58)              INV_ERROR_SM_IMPROPER_STATE
+ *          - (62)              INV_ERROR_FIFO_OVERFLOW
+ *          - (63)              INV_ERROR_FIFO_FOOTER
+ *          - (64)              INV_ERROR_FIFO_READ_COUNT
+ *          - (65)              INV_ERROR_FIFO_READ_DATA
+ *          - (72)              INV_ERROR_MEMORY_SET
+ *          - (82)              INV_ERROR_LOG_MEMORY_ERROR
+ *          - (83)              INV_ERROR_LOG_OUTPUT_ERROR
+ *          - (92)              INV_ERROR_OS_BAD_PTR
+ *          - (93)              INV_ERROR_OS_BAD_HANDLE
+ *          - (94)              INV_ERROR_OS_CREATE_FAILED
+ *          - (95)              INV_ERROR_OS_LOCK_FAILED
+ *          - (102)             INV_ERROR_COMPASS_DATA_OVERFLOW
+ *          - (103)             INV_ERROR_COMPASS_DATA_UNDERFLOW
+ *          - (104)             INV_ERROR_COMPASS_DATA_NOT_READY
+ *          - (105)             INV_ERROR_COMPASS_DATA_ERROR
+ *          - (107)             INV_ERROR_CALIBRATION_LOAD
+ *          - (108)             INV_ERROR_CALIBRATION_STORE
+ *          - (109)             INV_ERROR_CALIBRATION_LEN
+ *          - (110)             INV_ERROR_CALIBRATION_CHECKSUM
+ *          - (111)             INV_ERROR_ACCEL_DATA_OVERFLOW
+ *          - (112)             INV_ERROR_ACCEL_DATA_UNDERFLOW
+ *          - (113)             INV_ERROR_ACCEL_DATA_NOT_READY
+ *          - (114)             INV_ERROR_ACCEL_DATA_ERROR
+ *
+ *          The available warning codes and their associated values are:
+ *          - (115)             INV_WARNING_MOTION_RACE
+ *          - (116)             INV_WARNING_QUAT_TRASHED
+ *
+ *  @{
+ *      @file mltypes.h
+ *  @}
+ */
+
+#ifndef MLTYPES_H
+#define MLTYPES_H
+
+#include <linux/types.h>
+#include <asm-generic/errno-base.h>
+
+
+
+
+/*---------------------------
+ *    ML Defines
+ *--------------------------*/
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* - ML Errors. - */
+#define ERROR_NAME(x)   (#x)
+#define ERROR_CHECK_FIRST(first, x) \
+       { if (INV_SUCCESS == first) first = x; }
+
+#define INV_SUCCESS                       (0)
+/* Generic Error code.  Proprietary Error Codes only */
+#define INV_ERROR_BASE                    (0x20)
+#define INV_ERROR                         (INV_ERROR_BASE)
+
+/* Compatibility and other generic error codes */
+#define INV_ERROR_INVALID_PARAMETER             (EINVAL)
+#define INV_ERROR_FEATURE_NOT_ENABLED           (EPERM)
+#define INV_ERROR_FEATURE_NOT_IMPLEMENTED       (INV_ERROR_BASE + 4)
+#define INV_ERROR_DMP_NOT_STARTED               (INV_ERROR_BASE + 6)
+#define INV_ERROR_DMP_STARTED                   (INV_ERROR_BASE + 7)
+#define INV_ERROR_NOT_OPENED                    (INV_ERROR_BASE + 8)
+#define INV_ERROR_OPENED                        (INV_ERROR_BASE + 9)
+#define INV_ERROR_INVALID_MODULE                (ENODEV)
+#define INV_ERROR_MEMORY_EXAUSTED               (ENOMEM)
+#define INV_ERROR_DIVIDE_BY_ZERO                (INV_ERROR_BASE + 12)
+#define INV_ERROR_ASSERTION_FAILURE             (INV_ERROR_BASE + 13)
+#define INV_ERROR_FILE_OPEN                     (INV_ERROR_BASE + 14)
+#define INV_ERROR_FILE_READ                     (INV_ERROR_BASE + 15)
+#define INV_ERROR_FILE_WRITE                    (INV_ERROR_BASE + 16)
+#define INV_ERROR_INVALID_CONFIGURATION         (INV_ERROR_BASE + 17)
+
+/* Serial Communication */
+#define INV_ERROR_SERIAL_CLOSED                 (INV_ERROR_BASE + 20)
+#define INV_ERROR_SERIAL_OPEN_ERROR             (INV_ERROR_BASE + 21)
+#define INV_ERROR_SERIAL_READ                   (INV_ERROR_BASE + 22)
+#define INV_ERROR_SERIAL_WRITE                  (INV_ERROR_BASE + 23)
+#define INV_ERROR_SERIAL_DEVICE_NOT_RECOGNIZED  (INV_ERROR_BASE + 24)
+
+/* SM = State Machine */
+#define INV_ERROR_SM_TRANSITION                 (INV_ERROR_BASE + 25)
+#define INV_ERROR_SM_IMPROPER_STATE             (INV_ERROR_BASE + 26)
+
+/* Fifo */
+#define INV_ERROR_FIFO_OVERFLOW                 (INV_ERROR_BASE + 30)
+#define INV_ERROR_FIFO_FOOTER                   (INV_ERROR_BASE + 31)
+#define INV_ERROR_FIFO_READ_COUNT               (INV_ERROR_BASE + 32)
+#define INV_ERROR_FIFO_READ_DATA                (INV_ERROR_BASE + 33)
+
+/* Memory & Registers, Set & Get */
+#define INV_ERROR_MEMORY_SET                    (INV_ERROR_BASE + 40)
+
+#define INV_ERROR_LOG_MEMORY_ERROR              (INV_ERROR_BASE + 50)
+#define INV_ERROR_LOG_OUTPUT_ERROR              (INV_ERROR_BASE + 51)
+
+/* OS interface errors */
+#define INV_ERROR_OS_BAD_PTR                    (INV_ERROR_BASE + 60)
+#define INV_ERROR_OS_BAD_HANDLE                 (INV_ERROR_BASE + 61)
+#define INV_ERROR_OS_CREATE_FAILED              (INV_ERROR_BASE + 62)
+#define INV_ERROR_OS_LOCK_FAILED                (INV_ERROR_BASE + 63)
+
+/* Compass errors */
+#define INV_ERROR_COMPASS_DATA_OVERFLOW         (INV_ERROR_BASE + 70)
+#define INV_ERROR_COMPASS_DATA_UNDERFLOW        (INV_ERROR_BASE + 71)
+#define INV_ERROR_COMPASS_DATA_NOT_READY        (INV_ERROR_BASE + 72)
+#define INV_ERROR_COMPASS_DATA_ERROR            (INV_ERROR_BASE + 73)
+
+/* Load/Store calibration */
+#define INV_ERROR_CALIBRATION_LOAD              (INV_ERROR_BASE + 75)
+#define INV_ERROR_CALIBRATION_STORE             (INV_ERROR_BASE + 76)
+#define INV_ERROR_CALIBRATION_LEN               (INV_ERROR_BASE + 77)
+#define INV_ERROR_CALIBRATION_CHECKSUM          (INV_ERROR_BASE + 78)
+
+/* Accel errors */
+#define INV_ERROR_ACCEL_DATA_OVERFLOW           (INV_ERROR_BASE + 79)
+#define INV_ERROR_ACCEL_DATA_UNDERFLOW          (INV_ERROR_BASE + 80)
+#define INV_ERROR_ACCEL_DATA_NOT_READY          (INV_ERROR_BASE + 81)
+#define INV_ERROR_ACCEL_DATA_ERROR              (INV_ERROR_BASE + 82)
+
+/* No Motion Warning States */
+#define INV_WARNING_MOTION_RACE                 (INV_ERROR_BASE + 83)
+#define INV_WARNING_QUAT_TRASHED                (INV_ERROR_BASE + 84)
+#define INV_WARNING_GYRO_MAG                    (INV_ERROR_BASE + 85)
+
+#ifdef INV_USE_LEGACY_NAMES
+#define ML_SUCCESS                        INV_SUCCESS
+#define ML_ERROR                          INV_ERROR
+#define ML_ERROR_INVALID_PARAMETER        INV_ERROR_INVALID_PARAMETER
+#define ML_ERROR_FEATURE_NOT_ENABLED      INV_ERROR_FEATURE_NOT_ENABLED
+#define ML_ERROR_FEATURE_NOT_IMPLEMENTED  INV_ERROR_FEATURE_NOT_IMPLEMENTED
+#define ML_ERROR_DMP_NOT_STARTED          INV_ERROR_DMP_NOT_STARTED
+#define ML_ERROR_DMP_STARTED              INV_ERROR_DMP_STARTED
+#define ML_ERROR_NOT_OPENED               INV_ERROR_NOT_OPENED
+#define ML_ERROR_OPENED                   INV_ERROR_OPENED
+#define ML_ERROR_INVALID_MODULE           INV_ERROR_INVALID_MODULE
+#define ML_ERROR_MEMORY_EXAUSTED          INV_ERROR_MEMORY_EXAUSTED
+#define ML_ERROR_DIVIDE_BY_ZERO           INV_ERROR_DIVIDE_BY_ZERO
+#define ML_ERROR_ASSERTION_FAILURE        INV_ERROR_ASSERTION_FAILURE
+#define ML_ERROR_FILE_OPEN                INV_ERROR_FILE_OPEN
+#define ML_ERROR_FILE_READ                INV_ERROR_FILE_READ
+#define ML_ERROR_FILE_WRITE               INV_ERROR_FILE_WRITE
+#define ML_ERROR_INVALID_CONFIGURATION    INV_ERROR_INVALID_CONFIGURATION
+#define ML_ERROR_SERIAL_CLOSED            INV_ERROR_SERIAL_CLOSED
+#define ML_ERROR_SERIAL_OPEN_ERROR        INV_ERROR_SERIAL_OPEN_ERROR
+#define ML_ERROR_SERIAL_READ              INV_ERROR_SERIAL_READ
+#define ML_ERROR_SERIAL_WRITE             INV_ERROR_SERIAL_WRITE
+#define ML_ERROR_SERIAL_DEVICE_NOT_RECOGNIZED  \
+       INV_ERROR_SERIAL_DEVICE_NOT_RECOGNIZED
+#define ML_ERROR_SM_TRANSITION            INV_ERROR_SM_TRANSITION
+#define ML_ERROR_SM_IMPROPER_STATE        INV_ERROR_SM_IMPROPER_STATE
+#define ML_ERROR_FIFO_OVERFLOW            INV_ERROR_FIFO_OVERFLOW
+#define ML_ERROR_FIFO_FOOTER              INV_ERROR_FIFO_FOOTER
+#define ML_ERROR_FIFO_READ_COUNT          INV_ERROR_FIFO_READ_COUNT
+#define ML_ERROR_FIFO_READ_DATA           INV_ERROR_FIFO_READ_DATA
+#define ML_ERROR_MEMORY_SET               INV_ERROR_MEMORY_SET
+#define ML_ERROR_LOG_MEMORY_ERROR         INV_ERROR_LOG_MEMORY_ERROR
+#define ML_ERROR_LOG_OUTPUT_ERROR         INV_ERROR_LOG_OUTPUT_ERROR
+#define ML_ERROR_OS_BAD_PTR               INV_ERROR_OS_BAD_PTR
+#define ML_ERROR_OS_BAD_HANDLE            INV_ERROR_OS_BAD_HANDLE
+#define ML_ERROR_OS_CREATE_FAILED         INV_ERROR_OS_CREATE_FAILED
+#define ML_ERROR_OS_LOCK_FAILED           INV_ERROR_OS_LOCK_FAILED
+#define ML_ERROR_COMPASS_DATA_OVERFLOW    INV_ERROR_COMPASS_DATA_OVERFLOW
+#define ML_ERROR_COMPASS_DATA_UNDERFLOW   INV_ERROR_COMPASS_DATA_UNDERFLOW
+#define ML_ERROR_COMPASS_DATA_NOT_READY   INV_ERROR_COMPASS_DATA_NOT_READY
+#define ML_ERROR_COMPASS_DATA_ERROR       INV_ERROR_COMPASS_DATA_ERROR
+#define ML_ERROR_CALIBRATION_LOAD         INV_ERROR_CALIBRATION_LOAD
+#define ML_ERROR_CALIBRATION_STORE        INV_ERROR_CALIBRATION_STORE
+#define ML_ERROR_CALIBRATION_LEN          INV_ERROR_CALIBRATION_LEN
+#define ML_ERROR_CALIBRATION_CHECKSUM     INV_ERROR_CALIBRATION_CHECKSUM
+#define ML_ERROR_ACCEL_DATA_OVERFLOW      INV_ERROR_ACCEL_DATA_OVERFLOW
+#define ML_ERROR_ACCEL_DATA_UNDERFLOW     INV_ERROR_ACCEL_DATA_UNDERFLOW
+#define ML_ERROR_ACCEL_DATA_NOT_READY     INV_ERROR_ACCEL_DATA_NOT_READY
+#define ML_ERROR_ACCEL_DATA_ERROR         INV_ERROR_ACCEL_DATA_ERROR
+#endif
+
+/* For Linux coding compliance */
+
+#endif                         /* MLTYPES_H */
diff --git a/drivers/misc/inv_mpu/mpu-dev.c b/drivers/misc/inv_mpu/mpu-dev.c
new file mode 100755 (executable)
index 0000000..1ccbaa7
--- /dev/null
@@ -0,0 +1,1255 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+#define DEBUG
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/irq.h>
+#include <linux/gpio.h>
+#include <linux/signal.h>
+#include <linux/miscdevice.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <linux/pm.h>
+#include <linux/mutex.h>
+#include <linux/suspend.h>
+#include <linux/poll.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include "mpuirq.h"
+#include "slaveirq.h"
+#include "mlsl.h"
+#include "mldl_cfg.h"
+#include <linux/mpu.h>
+
+
+/* Platform data for the MPU */
+struct mpu_private_data {
+       struct miscdevice dev;
+       struct i2c_client *client;
+
+       /* mldl_cfg data */
+       struct mldl_cfg mldl_cfg;
+       struct mpu_ram          mpu_ram;
+       struct mpu_gyro_cfg     mpu_gyro_cfg;
+       struct mpu_offsets      mpu_offsets;
+       struct mpu_chip_info    mpu_chip_info;
+       struct inv_mpu_cfg      inv_mpu_cfg;
+       struct inv_mpu_state    inv_mpu_state;
+
+       struct mutex mutex;
+       wait_queue_head_t mpu_event_wait;
+       struct completion completion;
+       struct timer_list timeout;
+       struct notifier_block nb;
+       struct mpuirq_data mpu_pm_event;
+       int response_timeout;   /* In seconds */
+       unsigned long event;
+       int pid;
+       struct module *slave_modules[EXT_SLAVE_NUM_TYPES];
+};
+
+struct mpu_private_data *mpu_private_data;
+static struct i2c_client *this_client;
+
+static void mpu_pm_timeout(u_long data)
+{
+       struct mpu_private_data *mpu = (struct mpu_private_data *)data;
+       struct i2c_client *client = mpu->client;
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+       complete(&mpu->completion);
+}
+
+static int mpu_pm_notifier_callback(struct notifier_block *nb,
+                                   unsigned long event, void *unused)
+{
+       struct mpu_private_data *mpu =
+           container_of(nb, struct mpu_private_data, nb);
+       struct i2c_client *client = mpu->client;
+       struct timeval event_time;
+       dev_dbg(&client->adapter->dev, "%s: %ld\n", __func__, event);
+
+       /* Prevent the file handle from being closed before we initialize
+          the completion event */
+       mutex_lock(&mpu->mutex);
+       if (!(mpu->pid) ||
+           (event != PM_SUSPEND_PREPARE && event != PM_POST_SUSPEND)) {
+               mutex_unlock(&mpu->mutex);
+               return NOTIFY_OK;
+       }
+
+       if (event == PM_SUSPEND_PREPARE)
+               mpu->event = MPU_PM_EVENT_SUSPEND_PREPARE;
+       if (event == PM_POST_SUSPEND)
+               mpu->event = MPU_PM_EVENT_POST_SUSPEND;
+
+       do_gettimeofday(&event_time);
+       mpu->mpu_pm_event.interruptcount++;
+       mpu->mpu_pm_event.irqtime =
+           (((long long)event_time.tv_sec) << 32) + event_time.tv_usec;
+       mpu->mpu_pm_event.data_type = MPUIRQ_DATA_TYPE_PM_EVENT;
+       mpu->mpu_pm_event.data = mpu->event;
+
+       if (mpu->response_timeout > 0) {
+               mpu->timeout.expires = jiffies + mpu->response_timeout * HZ;
+               add_timer(&mpu->timeout);
+       }
+       INIT_COMPLETION(mpu->completion);
+       mutex_unlock(&mpu->mutex);
+
+       wake_up_interruptible(&mpu->mpu_event_wait);
+       wait_for_completion(&mpu->completion);
+       del_timer_sync(&mpu->timeout);
+       dev_dbg(&client->adapter->dev, "%s: %ld DONE\n", __func__, event);
+       return NOTIFY_OK;
+}
+
+static int mpu_dev_open(struct inode *inode, struct file *file)
+{
+       struct mpu_private_data *mpu =
+           (struct mpu_private_data *) i2c_get_clientdata(this_client);
+       struct i2c_client *client = mpu->client;
+       int result;
+       int ii;
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+       dev_dbg(&client->adapter->dev, "current->pid %d\n", current->pid);
+
+       result = mutex_lock_interruptible(&mpu->mutex);
+       if (mpu->pid) {
+               mutex_unlock(&mpu->mutex);
+               return -EBUSY;
+       }
+       mpu->pid = current->pid;
+       file->private_data = &mpu->dev;
+
+       /* Reset the sensors to the default */
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "%s: mutex_lock_interruptible returned %d\n",
+                       __func__, result);
+               return result;
+       }
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++)
+               __module_get(mpu->slave_modules[ii]);
+
+       mutex_unlock(&mpu->mutex);
+       return 0;
+}
+
+/* close function - called when the "file" /dev/mpu is closed in userspace   */
+static int mpu_release(struct inode *inode, struct file *file)
+{
+       struct mpu_private_data *mpu =
+           container_of(file->private_data, struct mpu_private_data, dev);
+       struct i2c_client *client = mpu->client;
+       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+       int result = 0;
+       int ii;
+       struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
+       struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               if (!pdata_slave[ii])
+                       slave_adapter[ii] = NULL;
+               else
+                       slave_adapter[ii] =
+                               i2c_get_adapter(pdata_slave[ii]->adapt_num);
+       }
+       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
+
+       mutex_lock(&mpu->mutex);
+       mldl_cfg->inv_mpu_cfg->requested_sensors = 0;
+       result = inv_mpu_suspend(mldl_cfg,
+                               slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                               slave_adapter[EXT_SLAVE_TYPE_ACCEL],
+                               slave_adapter[EXT_SLAVE_TYPE_COMPASS],
+                               slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
+                               INV_ALL_SENSORS);
+       mpu->pid = 0;
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++)
+               module_put(mpu->slave_modules[ii]);
+
+       mutex_unlock(&mpu->mutex);
+       complete(&mpu->completion);
+       dev_dbg(&client->adapter->dev, "mpu_release\n");
+
+       return result;
+}
+
+/* read function called when from /dev/mpu is read.  Read from the FIFO */
+static ssize_t mpu_read(struct file *file,
+                       char __user *buf, size_t count, loff_t *offset)
+{
+       struct mpu_private_data *mpu =
+           container_of(file->private_data, struct mpu_private_data, dev);
+       struct i2c_client *client = mpu->client;
+       size_t len = sizeof(mpu->mpu_pm_event) + sizeof(unsigned long);
+       int err;
+
+       if (!mpu->event && (!(file->f_flags & O_NONBLOCK)))
+               wait_event_interruptible(mpu->mpu_event_wait, mpu->event);
+
+       if (!mpu->event || !buf
+           || count < sizeof(mpu->mpu_pm_event))
+               return 0;
+
+       err = copy_to_user(buf, &mpu->mpu_pm_event, sizeof(mpu->mpu_pm_event));
+       if (err) {
+               dev_err(&client->adapter->dev,
+                       "Copy to user returned %d\n", err);
+               return -EFAULT;
+       }
+       mpu->event = 0;
+       return len;
+}
+
+static unsigned int mpu_poll(struct file *file, struct poll_table_struct *poll)
+{
+       struct mpu_private_data *mpu =
+           container_of(file->private_data, struct mpu_private_data, dev);
+       int mask = 0;
+
+       poll_wait(file, &mpu->mpu_event_wait, poll);
+       if (mpu->event)
+               mask |= POLLIN | POLLRDNORM;
+       return mask;
+}
+
+static int mpu_dev_ioctl_get_ext_slave_platform_data(
+       struct i2c_client *client,
+       struct ext_slave_platform_data __user *arg)
+{
+       struct mpu_private_data *mpu =
+           (struct mpu_private_data *)i2c_get_clientdata(client);
+       struct ext_slave_platform_data *pdata_slave;
+       struct ext_slave_platform_data local_pdata_slave;
+
+       if (copy_from_user(&local_pdata_slave, arg, sizeof(local_pdata_slave)))
+               return -EFAULT;
+
+       if (local_pdata_slave.type >= EXT_SLAVE_NUM_TYPES)
+               return -EINVAL;
+
+       pdata_slave = mpu->mldl_cfg.pdata_slave[local_pdata_slave.type];
+       /* All but private data and irq_data */
+       if (!pdata_slave)
+               return -ENODEV;
+       if (copy_to_user(arg, pdata_slave, sizeof(*pdata_slave)))
+               return -EFAULT;
+       return 0;
+}
+
+static int mpu_dev_ioctl_get_mpu_platform_data(
+       struct i2c_client *client,
+       struct mpu_platform_data __user *arg)
+{
+       struct mpu_private_data *mpu =
+           (struct mpu_private_data *)i2c_get_clientdata(client);
+       struct mpu_platform_data *pdata = mpu->mldl_cfg.pdata;
+
+       if (copy_to_user(arg, pdata, sizeof(*pdata)))
+               return -EFAULT;
+       return 0;
+}
+
+static int mpu_dev_ioctl_get_ext_slave_descr(
+       struct i2c_client *client,
+       struct ext_slave_descr __user *arg)
+{
+       struct mpu_private_data *mpu =
+           (struct mpu_private_data *)i2c_get_clientdata(client);
+       struct ext_slave_descr *slave;
+       struct ext_slave_descr local_slave;
+
+       if (copy_from_user(&local_slave, arg, sizeof(local_slave)))
+               return -EFAULT;
+
+       if (local_slave.type >= EXT_SLAVE_NUM_TYPES)
+               return -EINVAL;
+
+       slave = mpu->mldl_cfg.slave[local_slave.type];
+       /* All but private data and irq_data */
+       if (!slave)
+               return -ENODEV;
+       if (copy_to_user(arg, slave, sizeof(*slave)))
+               return -EFAULT;
+       return 0;
+}
+
+
+/**
+ * slave_config() - Pass a requested slave configuration to the slave sensor
+ *
+ * @adapter the adaptor to use to communicate with the slave
+ * @mldl_cfg the mldl configuration structuer
+ * @slave pointer to the slave descriptor
+ * @usr_config The configuration to pass to the slave sensor
+ *
+ * returns 0 or non-zero error code
+ */
+static int inv_mpu_config(struct mldl_cfg *mldl_cfg,
+                       void *gyro_adapter,
+                       struct ext_slave_config __user *usr_config)
+{
+       int retval = 0;
+       struct ext_slave_config config;
+
+       retval = copy_from_user(&config, usr_config, sizeof(config));
+       if (retval)
+               return -EFAULT;
+
+       if (config.len && config.data) {
+               void *data;
+               data = kmalloc(config.len, GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+
+               retval = copy_from_user(data,
+                                       (void __user *)config.data, config.len);
+               if (retval) {
+                       retval = -EFAULT;
+                       kfree(data);
+                       return retval;
+               }
+               config.data = data;
+       }
+       retval = gyro_config(gyro_adapter, mldl_cfg, &config);
+       kfree(config.data);
+       return retval;
+}
+
+static int inv_mpu_get_config(struct mldl_cfg *mldl_cfg,
+                           void *gyro_adapter,
+                           struct ext_slave_config __user *usr_config)
+{
+       int retval = 0;
+       struct ext_slave_config config;
+       void *user_data;
+
+       retval = copy_from_user(&config, usr_config, sizeof(config));
+       if (retval)
+               return -EFAULT;
+
+       user_data = config.data;
+       if (config.len && config.data) {
+               void *data;
+               data = kmalloc(config.len, GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+
+               retval = copy_from_user(data,
+                                       (void __user *)config.data, config.len);
+               if (retval) {
+                       retval = -EFAULT;
+                       kfree(data);
+                       return retval;
+               }
+               config.data = data;
+       }
+       retval = gyro_get_config(gyro_adapter, mldl_cfg, &config);
+       if (!retval)
+               retval = copy_to_user((unsigned char __user *)user_data,
+                               config.data, config.len);
+       kfree(config.data);
+       return retval;
+}
+
+static int slave_config(struct mldl_cfg *mldl_cfg,
+                       void *gyro_adapter,
+                       void *slave_adapter,
+                       struct ext_slave_descr *slave,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_config __user *usr_config)
+{
+       int retval = 0;
+       struct ext_slave_config config;
+       if ((!slave) || (!slave->config))
+               return -ENODEV;
+
+       retval = copy_from_user(&config, usr_config, sizeof(config));
+       if (retval)
+               return -EFAULT;
+
+       if (config.len && config.data) {
+               void *data;
+               data = kmalloc(config.len, GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+
+               retval = copy_from_user(data,
+                                       (void __user *)config.data, config.len);
+               if (retval) {
+                       retval = -EFAULT;
+                       kfree(data);
+                       return retval;
+               }
+               config.data = data;
+       }
+       retval = inv_mpu_slave_config(mldl_cfg, gyro_adapter, slave_adapter,
+                                     &config, slave, pdata);
+       kfree(config.data);
+       return retval;
+}
+
+static int slave_get_config(struct mldl_cfg *mldl_cfg,
+                           void *gyro_adapter,
+                           void *slave_adapter,
+                           struct ext_slave_descr *slave,
+                           struct ext_slave_platform_data *pdata,
+                           struct ext_slave_config __user *usr_config)
+{
+       int retval = 0;
+       struct ext_slave_config config;
+       void *user_data;
+       if (!(slave) || !(slave->get_config))
+               return -ENODEV;
+
+       retval = copy_from_user(&config, usr_config, sizeof(config));
+       if (retval)
+               return -EFAULT;
+
+       user_data = config.data;
+       if (config.len && config.data) {
+               void *data;
+               data = kmalloc(config.len, GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+
+               retval = copy_from_user(data,
+                                       (void __user *)config.data, config.len);
+               if (retval) {
+                       retval = -EFAULT;
+                       kfree(data);
+                       return retval;
+               }
+               config.data = data;
+       }
+       retval = inv_mpu_get_slave_config(mldl_cfg, gyro_adapter,
+                                         slave_adapter, &config, slave, pdata);
+       if (retval) {
+               kfree(config.data);
+               return retval;
+       }
+       retval = copy_to_user((unsigned char __user *)user_data,
+                             config.data, config.len);
+       kfree(config.data);
+       return retval;
+}
+
+static int inv_slave_read(struct mldl_cfg *mldl_cfg,
+                         void *gyro_adapter,
+                         void *slave_adapter,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata,
+                         void __user *usr_data)
+{
+       int retval;
+       unsigned char *data;
+       data = kzalloc(slave->read_len, GFP_KERNEL);
+       if (!data)
+               return -EFAULT;
+
+       retval = inv_mpu_slave_read(mldl_cfg, gyro_adapter, slave_adapter,
+                                   slave, pdata, data);
+
+       if ((!retval) &&
+           (copy_to_user((unsigned char __user *)usr_data,
+                         data, slave->read_len)))
+               retval = -EFAULT;
+
+       kfree(data);
+       return retval;
+}
+
+static int mpu_handle_mlsl(void *sl_handle,
+                          unsigned char addr,
+                          unsigned int cmd,
+                          struct mpu_read_write __user *usr_msg)
+{
+       int retval = 0;
+       struct mpu_read_write msg;
+       unsigned char *user_data;
+       retval = copy_from_user(&msg, usr_msg, sizeof(msg));
+       if (retval)
+               return -EFAULT;
+
+       user_data = msg.data;
+       if (msg.length && msg.data) {
+               unsigned char *data;
+               data = kmalloc(msg.length, GFP_KERNEL);
+               if (!data)
+                       return -ENOMEM;
+
+               retval = copy_from_user(data,
+                                       (void __user *)msg.data, msg.length);
+               if (retval) {
+                       retval = -EFAULT;
+                       kfree(data);
+                       return retval;
+               }
+               msg.data = data;
+       } else {
+               return -EPERM;
+       }
+
+       switch (cmd) {
+       case MPU_READ:
+               retval = inv_serial_read(sl_handle, addr,
+                                        msg.address, msg.length, msg.data);
+               break;
+       case MPU_WRITE:
+               retval = inv_serial_write(sl_handle, addr,
+                                         msg.length, msg.data);
+               break;
+       case MPU_READ_MEM:
+               retval = inv_serial_read_mem(sl_handle, addr,
+                                            msg.address, msg.length, msg.data);
+               break;
+       case MPU_WRITE_MEM:
+               retval = inv_serial_write_mem(sl_handle, addr,
+                                             msg.address, msg.length,
+                                             msg.data);
+               break;
+       case MPU_READ_FIFO:
+               retval = inv_serial_read_fifo(sl_handle, addr,
+                                             msg.length, msg.data);
+               break;
+       case MPU_WRITE_FIFO:
+               retval = inv_serial_write_fifo(sl_handle, addr,
+                                              msg.length, msg.data);
+               break;
+
+       };
+       if (retval) {
+               dev_err(&((struct i2c_adapter *)sl_handle)->dev,
+                       "%s: i2c %d error %d\n",
+                       __func__, cmd, retval);
+               kfree(msg.data);
+               return retval;
+       }
+       retval = copy_to_user((unsigned char __user *)user_data,
+                             msg.data, msg.length);
+       kfree(msg.data);
+       return retval;
+}
+
+/* ioctl - I/O control */
+static long mpu_dev_ioctl(struct file *file,
+                         unsigned int cmd, unsigned long arg)
+{
+       struct mpu_private_data *mpu =
+           container_of(file->private_data, struct mpu_private_data, dev);
+       struct i2c_client *client = mpu->client;
+       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+       int retval = 0;
+       struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
+       struct ext_slave_descr **slave = mldl_cfg->slave;
+       struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
+       int ii;
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               if (!pdata_slave[ii])
+                       slave_adapter[ii] = NULL;
+               else
+                       slave_adapter[ii] =
+                               i2c_get_adapter(pdata_slave[ii]->adapt_num);
+       }
+       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
+       
+       retval = mutex_lock_interruptible(&mpu->mutex);
+       if (retval) {
+               dev_err(&this_client->adapter->dev,
+                       "%s: mutex_lock_interruptible returned %d\n",
+                       __func__, retval);
+               return retval;
+       }
+
+       switch (cmd) {
+       case MPU_GET_EXT_SLAVE_PLATFORM_DATA:
+               retval = mpu_dev_ioctl_get_ext_slave_platform_data(
+                       client,
+                       (struct ext_slave_platform_data __user *)arg);
+               break;
+       case MPU_GET_MPU_PLATFORM_DATA:
+               retval = mpu_dev_ioctl_get_mpu_platform_data(
+                       client,
+                       (struct mpu_platform_data __user *)arg);
+               break;
+       case MPU_GET_EXT_SLAVE_DESCR:
+               retval = mpu_dev_ioctl_get_ext_slave_descr(
+                       client,
+                       (struct ext_slave_descr __user *)arg);
+               break;
+       case MPU_READ:
+       case MPU_WRITE:
+       case MPU_READ_MEM:
+       case MPU_WRITE_MEM:
+       case MPU_READ_FIFO:
+       case MPU_WRITE_FIFO:
+               retval = mpu_handle_mlsl(
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       mldl_cfg->mpu_chip_info->addr, cmd,
+                       (struct mpu_read_write __user *)arg);
+               break;
+       case MPU_CONFIG_GYRO:
+               retval = inv_mpu_config(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       (struct ext_slave_config __user *)arg);
+               break;
+       case MPU_CONFIG_ACCEL:
+               retval = slave_config(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_ACCEL],
+                       slave[EXT_SLAVE_TYPE_ACCEL],
+                       pdata_slave[EXT_SLAVE_TYPE_ACCEL],
+                       (struct ext_slave_config __user *)arg);
+               break;
+       case MPU_CONFIG_COMPASS:
+               retval = slave_config(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_COMPASS],
+                       slave[EXT_SLAVE_TYPE_COMPASS],
+                       pdata_slave[EXT_SLAVE_TYPE_COMPASS],
+                       (struct ext_slave_config __user *)arg);
+               break;
+       case MPU_CONFIG_PRESSURE:
+               retval = slave_config(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
+                       slave[EXT_SLAVE_TYPE_PRESSURE],
+                       pdata_slave[EXT_SLAVE_TYPE_PRESSURE],
+                       (struct ext_slave_config __user *)arg);
+               break;
+       case MPU_GET_CONFIG_GYRO:
+               retval = inv_mpu_get_config(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       (struct ext_slave_config __user *)arg);
+               break;
+       case MPU_GET_CONFIG_ACCEL:
+               retval = slave_get_config(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_ACCEL],
+                       slave[EXT_SLAVE_TYPE_ACCEL],
+                       pdata_slave[EXT_SLAVE_TYPE_ACCEL],
+                       (struct ext_slave_config __user *)arg);
+               break;
+       case MPU_GET_CONFIG_COMPASS:
+               retval = slave_get_config(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_COMPASS],
+                       slave[EXT_SLAVE_TYPE_COMPASS],
+                       pdata_slave[EXT_SLAVE_TYPE_COMPASS],
+                       (struct ext_slave_config __user *)arg);
+               break;
+       case MPU_GET_CONFIG_PRESSURE:
+               retval = slave_get_config(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
+                       slave[EXT_SLAVE_TYPE_PRESSURE],
+                       pdata_slave[EXT_SLAVE_TYPE_PRESSURE],
+                       (struct ext_slave_config __user *)arg);
+               break;
+       case MPU_SUSPEND:
+               retval = inv_mpu_suspend(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_ACCEL],
+                       slave_adapter[EXT_SLAVE_TYPE_COMPASS],
+                       slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
+                       arg);
+               break;
+       case MPU_RESUME:
+               retval = inv_mpu_resume(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_ACCEL],
+                       slave_adapter[EXT_SLAVE_TYPE_COMPASS],
+                       slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
+                       arg);
+               break;
+       case MPU_PM_EVENT_HANDLED:
+               dev_dbg(&client->adapter->dev, "%s: %d\n", __func__, cmd);
+               complete(&mpu->completion);
+               break;
+       case MPU_READ_ACCEL:
+               retval = inv_slave_read(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_ACCEL],
+                       slave[EXT_SLAVE_TYPE_ACCEL],
+                       pdata_slave[EXT_SLAVE_TYPE_ACCEL],
+                       (unsigned char __user *)arg);
+               break;
+       case MPU_READ_COMPASS:
+               retval = inv_slave_read(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_COMPASS],
+                       slave[EXT_SLAVE_TYPE_COMPASS],
+                       pdata_slave[EXT_SLAVE_TYPE_COMPASS],
+                       (unsigned char __user *)arg);
+               break;
+       case MPU_READ_PRESSURE:
+               retval = inv_slave_read(
+                       mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
+                       slave[EXT_SLAVE_TYPE_PRESSURE],
+                       pdata_slave[EXT_SLAVE_TYPE_PRESSURE],
+                       (unsigned char __user *)arg);
+               break;
+       case MPU_GET_REQUESTED_SENSORS:
+               if (copy_to_user(
+                          (__u32 __user *)arg,
+                          &mldl_cfg->inv_mpu_cfg->requested_sensors,
+                          sizeof(mldl_cfg->inv_mpu_cfg->requested_sensors)))
+                       retval = -EFAULT;
+               break;
+       case MPU_SET_REQUESTED_SENSORS:
+               mldl_cfg->inv_mpu_cfg->requested_sensors = arg;
+               break;
+       case MPU_GET_IGNORE_SYSTEM_SUSPEND:
+               if (copy_to_user(
+                       (unsigned char __user *)arg,
+                       &mldl_cfg->inv_mpu_cfg->ignore_system_suspend,
+                       sizeof(mldl_cfg->inv_mpu_cfg->ignore_system_suspend)))
+                       retval = -EFAULT;
+               break;
+       case MPU_SET_IGNORE_SYSTEM_SUSPEND:
+               mldl_cfg->inv_mpu_cfg->ignore_system_suspend = arg;
+               break;
+       case MPU_GET_MLDL_STATUS:
+               if (copy_to_user(
+                       (unsigned char __user *)arg,
+                       &mldl_cfg->inv_mpu_state->status,
+                       sizeof(mldl_cfg->inv_mpu_state->status)))
+                       retval = -EFAULT;
+               break;
+       case MPU_GET_I2C_SLAVES_ENABLED:
+               if (copy_to_user(
+                       (unsigned char __user *)arg,
+                       &mldl_cfg->inv_mpu_state->i2c_slaves_enabled,
+                       sizeof(mldl_cfg->inv_mpu_state->i2c_slaves_enabled)))
+                       retval = -EFAULT;
+               break;
+       default:
+               dev_err(&client->adapter->dev,
+                       "%s: Unknown cmd %x, arg %lu\n",
+                       __func__, cmd, arg);
+               retval = -EINVAL;
+       };
+
+       mutex_unlock(&mpu->mutex);
+
+       
+       //dev_dbg(&client->adapter->dev, "%s: %08x, %08lx, %d\n",__func__, cmd, arg, retval);   
+
+       if (retval > 0)
+               retval = -retval;
+
+       return retval;
+}
+
+void mpu_shutdown(struct i2c_client *client)
+{
+       struct mpu_private_data *mpu =
+           (struct mpu_private_data *)i2c_get_clientdata(client);
+       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+       struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
+       struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
+       int ii;
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               if (!pdata_slave[ii])
+                       slave_adapter[ii] = NULL;
+               else
+                       slave_adapter[ii] =
+                               i2c_get_adapter(pdata_slave[ii]->adapt_num);
+       }
+       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
+
+       mutex_lock(&mpu->mutex);
+       (void)inv_mpu_suspend(mldl_cfg,
+                       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                       slave_adapter[EXT_SLAVE_TYPE_ACCEL],
+                       slave_adapter[EXT_SLAVE_TYPE_COMPASS],
+                       slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
+                       INV_ALL_SENSORS);
+       mutex_unlock(&mpu->mutex);
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+}
+
+int mpu_dev_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+       struct mpu_private_data *mpu =
+           (struct mpu_private_data *)i2c_get_clientdata(client);
+       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+       struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
+       struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
+       int ii;
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               if (!pdata_slave[ii])
+                       slave_adapter[ii] = NULL;
+               else
+                       slave_adapter[ii] =
+                               i2c_get_adapter(pdata_slave[ii]->adapt_num);
+       }
+       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
+
+       mutex_lock(&mpu->mutex);
+       if (!mldl_cfg->inv_mpu_cfg->ignore_system_suspend) {
+               dev_dbg(&client->adapter->dev,
+                       "%s: suspending on event %d\n", __func__, mesg.event);
+               (void)inv_mpu_suspend(mldl_cfg,
+                               slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                               slave_adapter[EXT_SLAVE_TYPE_ACCEL],
+                               slave_adapter[EXT_SLAVE_TYPE_COMPASS],
+                               slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
+                               INV_ALL_SENSORS);
+       } else {
+               dev_dbg(&client->adapter->dev,
+                       "%s: Already suspended %d\n", __func__, mesg.event);
+       }
+       mutex_unlock(&mpu->mutex);
+       return 0;
+}
+
+int mpu_dev_resume(struct i2c_client *client)
+{
+       struct mpu_private_data *mpu =
+           (struct mpu_private_data *)i2c_get_clientdata(client);
+       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+       struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
+       struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
+       int ii;
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               if (!pdata_slave[ii])
+                       slave_adapter[ii] = NULL;
+               else
+                       slave_adapter[ii] =
+                               i2c_get_adapter(pdata_slave[ii]->adapt_num);
+       }
+       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
+
+       mutex_lock(&mpu->mutex);
+       if (mpu->pid && !mldl_cfg->inv_mpu_cfg->ignore_system_suspend) {
+               (void)inv_mpu_resume(mldl_cfg,
+                               slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+                               slave_adapter[EXT_SLAVE_TYPE_ACCEL],
+                               slave_adapter[EXT_SLAVE_TYPE_COMPASS],
+                               slave_adapter[EXT_SLAVE_TYPE_PRESSURE],
+                               mldl_cfg->inv_mpu_cfg->requested_sensors);
+               dev_dbg(&client->adapter->dev,
+                       "%s for pid %d\n", __func__, mpu->pid);
+       }
+       mutex_unlock(&mpu->mutex);
+       return 0;
+}
+
+/* define which file operations are supported */
+static const struct file_operations mpu_fops = {
+       .owner = THIS_MODULE,
+       .read = mpu_read,
+       .poll = mpu_poll,
+#if HAVE_COMPAT_IOCTL
+       .compat_ioctl = mpu_dev_ioctl,
+#endif
+#if HAVE_UNLOCKED_IOCTL
+       .unlocked_ioctl = mpu_dev_ioctl,
+#endif 
+       //.unlocked_ioctl = mpu_dev_ioctl,
+       .open = mpu_dev_open,
+       .release = mpu_release,
+};
+
+int inv_mpu_register_slave(struct module *slave_module,
+                       struct i2c_client *slave_client,
+                       struct ext_slave_platform_data *slave_pdata,
+                       struct ext_slave_descr *(*get_slave_descr)(void))
+{
+       struct mpu_private_data *mpu = mpu_private_data;
+       struct mldl_cfg *mldl_cfg;
+       struct ext_slave_descr *slave_descr;
+       struct ext_slave_platform_data **pdata_slave;
+       char *irq_name = NULL;
+       int result = 0;
+
+       if (!slave_client || !slave_pdata || !get_slave_descr)
+               return -EINVAL;
+
+       if (!mpu) {
+               dev_err(&slave_client->adapter->dev,
+                       "%s: Null mpu_private_data\n", __func__);
+               return -EINVAL;
+       }
+       mldl_cfg    = &mpu->mldl_cfg;
+       pdata_slave = mldl_cfg->pdata_slave;
+       slave_descr = get_slave_descr();
+
+       if (!slave_descr) {
+               dev_err(&slave_client->adapter->dev,
+                       "%s: Null ext_slave_descr\n", __func__);
+               return -EINVAL;
+       }
+
+       mutex_lock(&mpu->mutex);
+       if (mpu->pid) {
+               mutex_unlock(&mpu->mutex);
+               return -EBUSY;
+       }
+
+       if (pdata_slave[slave_descr->type]) {
+               result = -EBUSY;
+               goto out_unlock_mutex;
+       }
+
+       slave_pdata->address    = slave_client->addr;
+       slave_pdata->irq        = slave_client->irq;
+       slave_pdata->adapt_num  = i2c_adapter_id(slave_client->adapter);
+
+       dev_info(&slave_client->adapter->dev,
+               "%s: +%s Type %d: Addr: %2x IRQ: %2d, Adapt: %2d\n",
+               __func__,
+               slave_descr->name,
+               slave_descr->type,
+               slave_pdata->address,
+               slave_pdata->irq,
+               slave_pdata->adapt_num);
+
+       switch (slave_descr->type) {
+       case EXT_SLAVE_TYPE_ACCEL:
+               irq_name = "accelirq";
+               break;
+       case EXT_SLAVE_TYPE_COMPASS:
+               irq_name = "compassirq";
+               break;
+       case EXT_SLAVE_TYPE_PRESSURE:
+               irq_name = "pressureirq";
+               break;
+       default:
+               irq_name = "none";
+       };
+       if (slave_descr->init) {
+               result = slave_descr->init(slave_client->adapter,
+                                       slave_descr,
+                                       slave_pdata);
+               if (result) {
+                       dev_err(&slave_client->adapter->dev,
+                               "%s init failed %d\n",
+                               slave_descr->name, result);
+                       goto out_unlock_mutex;
+               }
+       }
+
+       pdata_slave[slave_descr->type] = slave_pdata;
+       mpu->slave_modules[slave_descr->type] = slave_module;
+       mldl_cfg->slave[slave_descr->type] = slave_descr;
+
+       goto out_unlock_mutex;
+
+out_unlock_mutex:
+       mutex_unlock(&mpu->mutex);
+
+       if (!result && irq_name && (slave_pdata->irq > 0)) {
+               int warn_result;
+               dev_info(&slave_client->adapter->dev,
+                       "Installing %s irq using %d\n",
+                       irq_name,
+                       slave_pdata->irq);
+               warn_result = slaveirq_init(slave_client->adapter,
+                                       slave_pdata, irq_name);
+               if (result)
+                       dev_err(&slave_client->adapter->dev,
+                               "%s irq assigned error: %d\n",
+                               slave_descr->name, warn_result);
+       } else {
+               dev_warn(&slave_client->adapter->dev,
+                       "%s irq not assigned: %d %d %d\n",
+                       slave_descr->name,
+                       result, (int)irq_name, slave_pdata->irq);
+       }
+
+       return result;
+}
+EXPORT_SYMBOL(inv_mpu_register_slave);
+
+void inv_mpu_unregister_slave(struct i2c_client *slave_client,
+                       struct ext_slave_platform_data *slave_pdata,
+                       struct ext_slave_descr *(*get_slave_descr)(void))
+{
+       struct mpu_private_data *mpu = mpu_private_data;
+       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+       struct ext_slave_descr *slave_descr;
+       int result;
+
+       dev_info(&slave_client->adapter->dev, "%s\n", __func__);
+
+       if (!slave_client || !slave_pdata || !get_slave_descr)
+               return;
+
+       if (slave_pdata->irq)
+               slaveirq_exit(slave_pdata);
+
+       slave_descr = get_slave_descr();
+       if (!slave_descr)
+               return;
+
+       mutex_lock(&mpu->mutex);
+
+       if (slave_descr->exit) {
+               result = slave_descr->exit(slave_client->adapter,
+                                       slave_descr,
+                                       slave_pdata);
+               if (result)
+                       dev_err(&slave_client->adapter->dev,
+                               "Accel exit failed %d\n", result);
+       }
+       mldl_cfg->slave[slave_descr->type] = NULL;
+       mldl_cfg->pdata_slave[slave_descr->type] = NULL;
+       mpu->slave_modules[slave_descr->type] = NULL;
+
+       mutex_unlock(&mpu->mutex);
+
+}
+EXPORT_SYMBOL(inv_mpu_unregister_slave);
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static const struct i2c_device_id mpu_id[] = {
+       {"mpu3050", 0},
+       {"mpu6050", 0},
+       {"mpu6050_no_accel", 0},
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, mpu_id);
+
+int mpu_probe(struct i2c_client *client, const struct i2c_device_id *devid)
+{
+       struct mpu_platform_data *pdata;
+       struct mpu_private_data *mpu;
+       struct mldl_cfg *mldl_cfg;
+       int res = 0;
+       int ii = 0;
+
+       dev_info(&client->adapter->dev, "%s: %d\n", __func__, ii++);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               res = -ENODEV;
+               goto out_check_functionality_failed;
+       }
+
+       mpu = kzalloc(sizeof(struct mpu_private_data), GFP_KERNEL);
+       if (!mpu) {
+               res = -ENOMEM;
+               goto out_alloc_data_failed;
+       }
+       mldl_cfg = &mpu->mldl_cfg;
+       mldl_cfg->mpu_ram       = &mpu->mpu_ram;
+       mldl_cfg->mpu_gyro_cfg  = &mpu->mpu_gyro_cfg;
+       mldl_cfg->mpu_offsets   = &mpu->mpu_offsets;
+       mldl_cfg->mpu_chip_info = &mpu->mpu_chip_info;
+       mldl_cfg->inv_mpu_cfg   = &mpu->inv_mpu_cfg;
+       mldl_cfg->inv_mpu_state = &mpu->inv_mpu_state;
+
+       mldl_cfg->mpu_ram->length = MPU_MEM_NUM_RAM_BANKS * MPU_MEM_BANK_SIZE;
+       mldl_cfg->mpu_ram->ram = kzalloc(mldl_cfg->mpu_ram->length, GFP_KERNEL);
+       if (!mldl_cfg->mpu_ram->ram) {
+               res = -ENOMEM;
+               goto out_alloc_ram_failed;
+       }
+       mpu_private_data = mpu;
+       i2c_set_clientdata(client, mpu);
+       this_client = client;   
+       mpu->client = client;
+
+       init_waitqueue_head(&mpu->mpu_event_wait);
+       mutex_init(&mpu->mutex);
+       init_completion(&mpu->completion);
+
+       mpu->response_timeout = 60;     /* Seconds */
+       mpu->timeout.function = mpu_pm_timeout;
+       mpu->timeout.data = (u_long) mpu;
+       init_timer(&mpu->timeout);
+
+       mpu->nb.notifier_call = mpu_pm_notifier_callback;
+       mpu->nb.priority = 0;
+       res = register_pm_notifier(&mpu->nb);
+       if (res) {
+               dev_err(&client->adapter->dev,
+                       "Unable to register pm_notifier %d\n", res);
+               goto out_register_pm_notifier_failed;
+       }
+
+       pdata = (struct mpu_platform_data *)client->dev.platform_data;
+       if (!pdata) {
+               dev_WARN(&client->adapter->dev,
+                        "Missing platform data for mpu\n");
+       }
+       mldl_cfg->pdata = pdata;
+
+       mldl_cfg->mpu_chip_info->addr = client->addr;
+       res = inv_mpu_open(&mpu->mldl_cfg, client->adapter, NULL, NULL, NULL);
+
+       if (res) {
+               dev_err(&client->adapter->dev,
+                       "Unable to open %s %d\n", MPU_NAME, res);
+               res = -ENODEV;
+               goto out_whoami_failed;
+       }
+
+       mpu->dev.minor = MISC_DYNAMIC_MINOR;
+       mpu->dev.name = "mpu";
+       mpu->dev.fops = &mpu_fops;
+       res = misc_register(&mpu->dev);
+       if (res < 0) {
+               dev_err(&client->adapter->dev,
+                       "ERROR: misc_register returned %d\n", res);
+               goto out_misc_register_failed;
+       }
+
+       if (client->irq) {
+               dev_info(&client->adapter->dev,
+                        "Installing irq using %d\n", client->irq);
+               res = mpuirq_init(client, mldl_cfg);
+               if (res)
+                       goto out_mpuirq_failed;
+       } else {
+               dev_WARN(&client->adapter->dev,
+                        "Missing %s IRQ\n", MPU_NAME);
+       }
+       return res;
+
+out_mpuirq_failed:
+       misc_deregister(&mpu->dev);
+out_misc_register_failed:
+       inv_mpu_close(&mpu->mldl_cfg, client->adapter, NULL, NULL, NULL);
+out_whoami_failed:
+       unregister_pm_notifier(&mpu->nb);
+out_register_pm_notifier_failed:
+       kfree(mldl_cfg->mpu_ram->ram);
+       mpu_private_data = NULL;
+out_alloc_ram_failed:
+       kfree(mpu);
+out_alloc_data_failed:
+out_check_functionality_failed:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, res);
+       return res;
+
+}
+
+static int mpu_remove(struct i2c_client *client)
+{
+       struct mpu_private_data *mpu = i2c_get_clientdata(client);
+       struct i2c_adapter *slave_adapter[EXT_SLAVE_NUM_TYPES];
+       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
+       struct ext_slave_platform_data **pdata_slave = mldl_cfg->pdata_slave;
+       int ii;
+
+       for (ii = 0; ii < EXT_SLAVE_NUM_TYPES; ii++) {
+               if (!pdata_slave[ii])
+                       slave_adapter[ii] = NULL;
+               else
+                       slave_adapter[ii] =
+                               i2c_get_adapter(pdata_slave[ii]->adapt_num);
+       }
+
+       slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE] = client->adapter;
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_close(mldl_cfg,
+               slave_adapter[EXT_SLAVE_TYPE_GYROSCOPE],
+               slave_adapter[EXT_SLAVE_TYPE_ACCEL],
+               slave_adapter[EXT_SLAVE_TYPE_COMPASS],
+               slave_adapter[EXT_SLAVE_TYPE_PRESSURE]);
+
+
+       if (client->irq)
+               mpuirq_exit();
+
+       misc_deregister(&mpu->dev);
+
+       unregister_pm_notifier(&mpu->nb);
+
+       kfree(mpu->mldl_cfg.mpu_ram->ram);
+       kfree(mpu);
+
+       return 0;
+}
+
+static struct i2c_driver mpu_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = mpu_probe,
+       .remove = mpu_remove,
+       .id_table = mpu_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = MPU_NAME,
+                  },
+       .address_list = normal_i2c,
+       .shutdown = mpu_shutdown,       /* optional */
+       .suspend = mpu_dev_suspend,     /* optional */
+       .resume = mpu_dev_resume,       /* optional */
+
+};
+
+static int __init mpu_init(void)
+{
+       int res = i2c_add_driver(&mpu_driver);
+       pr_info("%s: Probe name %s\n", __func__, MPU_NAME);
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit mpu_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&mpu_driver);
+}
+
+module_init(mpu_init);
+module_exit(mpu_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("User space character device interface for MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS(MPU_NAME);
diff --git a/drivers/misc/inv_mpu/mpu-dev.h b/drivers/misc/inv_mpu/mpu-dev.h
new file mode 100644 (file)
index 0000000..b6a4fcf
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+
+#ifndef __MPU_DEV_H__
+#define __MPU_DEV_H__
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/mpu.h>
+
+int inv_mpu_register_slave(struct module *slave_module,
+                       struct i2c_client *client,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_descr *(*slave_descr)(void));
+
+void inv_mpu_unregister_slave(struct i2c_client *client,
+                       struct ext_slave_platform_data *pdata,
+                       struct ext_slave_descr *(*slave_descr)(void));
+#endif
diff --git a/drivers/misc/inv_mpu/mpu3050.h b/drivers/misc/inv_mpu/mpu3050.h
new file mode 100644 (file)
index 0000000..02af16e
--- /dev/null
@@ -0,0 +1,251 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+#ifndef __MPU_H_
+#error Do not include this file directly.  Include mpu.h instead.
+#endif
+
+#ifndef __MPU3050_H_
+#define __MPU3050_H_
+
+#include <linux/types.h>
+
+
+#define MPU_NAME "mpu3050"
+#define DEFAULT_MPU_SLAVEADDR       0x68
+
+/*==== MPU REGISTER SET ====*/
+enum mpu_register {
+       MPUREG_WHO_AM_I = 0,    /* 00 0x00 */
+       MPUREG_PRODUCT_ID,      /* 01 0x01 */
+       MPUREG_02_RSVD,         /* 02 0x02 */
+       MPUREG_03_RSVD,         /* 03 0x03 */
+       MPUREG_04_RSVD,         /* 04 0x04 */
+       MPUREG_XG_OFFS_TC,      /* 05 0x05 */
+       MPUREG_06_RSVD,         /* 06 0x06 */
+       MPUREG_07_RSVD,         /* 07 0x07 */
+       MPUREG_YG_OFFS_TC,      /* 08 0x08 */
+       MPUREG_09_RSVD,         /* 09 0x09 */
+       MPUREG_0A_RSVD,         /* 10 0x0a */
+       MPUREG_ZG_OFFS_TC,      /* 11 0x0b */
+       MPUREG_X_OFFS_USRH,     /* 12 0x0c */
+       MPUREG_X_OFFS_USRL,     /* 13 0x0d */
+       MPUREG_Y_OFFS_USRH,     /* 14 0x0e */
+       MPUREG_Y_OFFS_USRL,     /* 15 0x0f */
+       MPUREG_Z_OFFS_USRH,     /* 16 0x10 */
+       MPUREG_Z_OFFS_USRL,     /* 17 0x11 */
+       MPUREG_FIFO_EN1,        /* 18 0x12 */
+       MPUREG_FIFO_EN2,        /* 19 0x13 */
+       MPUREG_AUX_SLV_ADDR,    /* 20 0x14 */
+       MPUREG_SMPLRT_DIV,      /* 21 0x15 */
+       MPUREG_DLPF_FS_SYNC,    /* 22 0x16 */
+       MPUREG_INT_CFG,         /* 23 0x17 */
+       MPUREG_ACCEL_BURST_ADDR,/* 24 0x18 */
+       MPUREG_19_RSVD,         /* 25 0x19 */
+       MPUREG_INT_STATUS,      /* 26 0x1a */
+       MPUREG_TEMP_OUT_H,      /* 27 0x1b */
+       MPUREG_TEMP_OUT_L,      /* 28 0x1c */
+       MPUREG_GYRO_XOUT_H,     /* 29 0x1d */
+       MPUREG_GYRO_XOUT_L,     /* 30 0x1e */
+       MPUREG_GYRO_YOUT_H,     /* 31 0x1f */
+       MPUREG_GYRO_YOUT_L,     /* 32 0x20 */
+       MPUREG_GYRO_ZOUT_H,     /* 33 0x21 */
+       MPUREG_GYRO_ZOUT_L,     /* 34 0x22 */
+       MPUREG_23_RSVD,         /* 35 0x23 */
+       MPUREG_24_RSVD,         /* 36 0x24 */
+       MPUREG_25_RSVD,         /* 37 0x25 */
+       MPUREG_26_RSVD,         /* 38 0x26 */
+       MPUREG_27_RSVD,         /* 39 0x27 */
+       MPUREG_28_RSVD,         /* 40 0x28 */
+       MPUREG_29_RSVD,         /* 41 0x29 */
+       MPUREG_2A_RSVD,         /* 42 0x2a */
+       MPUREG_2B_RSVD,         /* 43 0x2b */
+       MPUREG_2C_RSVD,         /* 44 0x2c */
+       MPUREG_2D_RSVD,         /* 45 0x2d */
+       MPUREG_2E_RSVD,         /* 46 0x2e */
+       MPUREG_2F_RSVD,         /* 47 0x2f */
+       MPUREG_30_RSVD,         /* 48 0x30 */
+       MPUREG_31_RSVD,         /* 49 0x31 */
+       MPUREG_32_RSVD,         /* 50 0x32 */
+       MPUREG_33_RSVD,         /* 51 0x33 */
+       MPUREG_34_RSVD,         /* 52 0x34 */
+       MPUREG_DMP_CFG_1,       /* 53 0x35 */
+       MPUREG_DMP_CFG_2,       /* 54 0x36 */
+       MPUREG_BANK_SEL,        /* 55 0x37 */
+       MPUREG_MEM_START_ADDR,  /* 56 0x38 */
+       MPUREG_MEM_R_W,         /* 57 0x39 */
+       MPUREG_FIFO_COUNTH,     /* 58 0x3a */
+       MPUREG_FIFO_COUNTL,     /* 59 0x3b */
+       MPUREG_FIFO_R_W,        /* 60 0x3c */
+       MPUREG_USER_CTRL,       /* 61 0x3d */
+       MPUREG_PWR_MGM,         /* 62 0x3e */
+       MPUREG_3F_RSVD,         /* 63 0x3f */
+       NUM_OF_MPU_REGISTERS    /* 64 0x40 */
+};
+
+/*==== BITS FOR MPU ====*/
+
+/*---- MPU 'FIFO_EN1' register (12) ----*/
+#define BIT_TEMP_OUT                0x80
+#define BIT_GYRO_XOUT               0x40
+#define BIT_GYRO_YOUT               0x20
+#define BIT_GYRO_ZOUT               0x10
+#define BIT_ACCEL_XOUT              0x08
+#define BIT_ACCEL_YOUT              0x04
+#define BIT_ACCEL_ZOUT              0x02
+#define BIT_AUX_1OUT                0x01
+/*---- MPU 'FIFO_EN2' register (13) ----*/
+#define BIT_AUX_2OUT                0x02
+#define BIT_AUX_3OUT                0x01
+/*---- MPU 'DLPF_FS_SYNC' register (16) ----*/
+#define BITS_EXT_SYNC_NONE          0x00
+#define BITS_EXT_SYNC_TEMP          0x20
+#define BITS_EXT_SYNC_GYROX         0x40
+#define BITS_EXT_SYNC_GYROY         0x60
+#define BITS_EXT_SYNC_GYROZ         0x80
+#define BITS_EXT_SYNC_ACCELX        0xA0
+#define BITS_EXT_SYNC_ACCELY        0xC0
+#define BITS_EXT_SYNC_ACCELZ        0xE0
+#define BITS_EXT_SYNC_MASK          0xE0
+#define BITS_FS_250DPS              0x00
+#define BITS_FS_500DPS              0x08
+#define BITS_FS_1000DPS             0x10
+#define BITS_FS_2000DPS             0x18
+#define BITS_FS_MASK                0x18
+#define BITS_DLPF_CFG_256HZ_NOLPF2  0x00
+#define BITS_DLPF_CFG_188HZ         0x01
+#define BITS_DLPF_CFG_98HZ          0x02
+#define BITS_DLPF_CFG_42HZ          0x03
+#define BITS_DLPF_CFG_20HZ          0x04
+#define BITS_DLPF_CFG_10HZ          0x05
+#define BITS_DLPF_CFG_5HZ           0x06
+#define BITS_DLPF_CFG_2100HZ_NOLPF  0x07
+#define BITS_DLPF_CFG_MASK          0x07
+/*---- MPU 'INT_CFG' register (17) ----*/
+#define BIT_ACTL                    0x80
+#define BIT_ACTL_LOW                0x80
+#define BIT_ACTL_HIGH               0x00
+#define BIT_OPEN                    0x40
+#define BIT_OPEN_DRAIN              0x40
+#define BIT_PUSH_PULL               0x00
+#define BIT_LATCH_INT_EN            0x20
+#define BIT_INT_PULSE_WIDTH_50US    0x00
+#define BIT_INT_ANYRD_2CLEAR        0x10
+#define BIT_INT_STAT_READ_2CLEAR    0x00
+#define BIT_MPU_RDY_EN              0x04
+#define BIT_DMP_INT_EN              0x02
+#define BIT_RAW_RDY_EN              0x01
+/*---- MPU 'INT_STATUS' register (1A) ----*/
+#define BIT_INT_STATUS_FIFO_OVERLOW 0x80
+#define BIT_MPU_RDY                 0x04
+#define BIT_DMP_INT                 0x02
+#define BIT_RAW_RDY                 0x01
+/*---- MPU 'BANK_SEL' register (37) ----*/
+#define BIT_PRFTCH_EN               0x20
+#define BIT_CFG_USER_BANK           0x10
+#define BITS_MEM_SEL                0x0f
+/*---- MPU 'USER_CTRL' register (3D) ----*/
+#define BIT_DMP_EN                  0x80
+#define BIT_FIFO_EN                 0x40
+#define BIT_AUX_IF_EN               0x20
+#define BIT_AUX_RD_LENG             0x10
+#define BIT_AUX_IF_RST              0x08
+#define BIT_DMP_RST                 0x04
+#define BIT_FIFO_RST                0x02
+#define BIT_GYRO_RST                0x01
+/*---- MPU 'PWR_MGM' register (3E) ----*/
+#define BIT_H_RESET                 0x80
+#define BIT_SLEEP                   0x40
+#define BIT_STBY_XG                 0x20
+#define BIT_STBY_YG                 0x10
+#define BIT_STBY_ZG                 0x08
+#define BITS_CLKSEL                 0x07
+
+/*---- MPU Silicon Revision ----*/
+#define MPU_SILICON_REV_A4           1 /* MPU A4 Device */
+#define MPU_SILICON_REV_B1           2 /* MPU B1 Device */
+#define MPU_SILICON_REV_B4           3 /* MPU B4 Device */
+#define MPU_SILICON_REV_B6           4 /* MPU B6 Device */
+
+/*---- MPU Memory ----*/
+#define MPU_MEM_BANK_SIZE           (256)
+#define FIFO_HW_SIZE                (512)
+
+enum MPU_MEMORY_BANKS {
+       MPU_MEM_RAM_BANK_0 = 0,
+       MPU_MEM_RAM_BANK_1,
+       MPU_MEM_RAM_BANK_2,
+       MPU_MEM_RAM_BANK_3,
+       MPU_MEM_NUM_RAM_BANKS,
+       MPU_MEM_OTP_BANK_0 = MPU_MEM_NUM_RAM_BANKS,
+       /* This one is always last */
+       MPU_MEM_NUM_BANKS
+};
+
+/*---- structure containing control variables used by MLDL ----*/
+/*---- MPU clock source settings ----*/
+/*---- MPU filter selections ----*/
+enum mpu_filter {
+       MPU_FILTER_256HZ_NOLPF2 = 0,
+       MPU_FILTER_188HZ,
+       MPU_FILTER_98HZ,
+       MPU_FILTER_42HZ,
+       MPU_FILTER_20HZ,
+       MPU_FILTER_10HZ,
+       MPU_FILTER_5HZ,
+       MPU_FILTER_2100HZ_NOLPF,
+       NUM_MPU_FILTER
+};
+
+enum mpu_fullscale {
+       MPU_FS_250DPS = 0,
+       MPU_FS_500DPS,
+       MPU_FS_1000DPS,
+       MPU_FS_2000DPS,
+       NUM_MPU_FS
+};
+
+enum mpu_clock_sel {
+       MPU_CLK_SEL_INTERNAL = 0,
+       MPU_CLK_SEL_PLLGYROX,
+       MPU_CLK_SEL_PLLGYROY,
+       MPU_CLK_SEL_PLLGYROZ,
+       MPU_CLK_SEL_PLLEXT32K,
+       MPU_CLK_SEL_PLLEXT19M,
+       MPU_CLK_SEL_RESERVED,
+       MPU_CLK_SEL_STOP,
+       NUM_CLK_SEL
+};
+
+enum mpu_ext_sync {
+       MPU_EXT_SYNC_NONE = 0,
+       MPU_EXT_SYNC_TEMP,
+       MPU_EXT_SYNC_GYROX,
+       MPU_EXT_SYNC_GYROY,
+       MPU_EXT_SYNC_GYROZ,
+       MPU_EXT_SYNC_ACCELX,
+       MPU_EXT_SYNC_ACCELY,
+       MPU_EXT_SYNC_ACCELZ,
+       NUM_MPU_EXT_SYNC
+};
+
+#define DLPF_FS_SYNC_VALUE(ext_sync, full_scale, lpf) \
+       ((ext_sync << 5) | (full_scale << 3) | lpf)
+
+#endif                         /* __MPU3050_H_ */
diff --git a/drivers/misc/inv_mpu/mpuirq.c b/drivers/misc/inv_mpu/mpuirq.c
new file mode 100755 (executable)
index 0000000..8bfddc8
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/irq.h>
+#include <linux/signal.h>
+#include <linux/miscdevice.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/poll.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/mpu.h>
+#include "mpuirq.h"
+#include "mldl_cfg.h"
+
+#define MPUIRQ_NAME "mpuirq"
+
+/* function which gets accel data and sends it to MPU */
+
+DECLARE_WAIT_QUEUE_HEAD(mpuirq_wait);
+
+struct mpuirq_dev_data {
+       struct i2c_client *mpu_client;
+       struct miscdevice *dev;
+       int irq;
+       int pid;
+       int accel_divider;
+       int data_ready;
+       int timeout;
+};
+
+static struct mpuirq_dev_data mpuirq_dev_data;
+static struct mpuirq_data mpuirq_data;
+static char *interface = MPUIRQ_NAME;
+
+static int mpuirq_open(struct inode *inode, struct file *file)
+{
+       dev_dbg(mpuirq_dev_data.dev->this_device,
+               "%s current->pid %d\n", __func__, current->pid);
+       mpuirq_dev_data.pid = current->pid;
+       file->private_data = &mpuirq_dev_data;
+       return 0;
+}
+
+/* close function - called when the "file" /dev/mpuirq is closed in userspace */
+static int mpuirq_release(struct inode *inode, struct file *file)
+{
+       dev_dbg(mpuirq_dev_data.dev->this_device, "mpuirq_release\n");
+       return 0;
+}
+
+/* read function called when from /dev/mpuirq is read */
+static ssize_t mpuirq_read(struct file *file,
+                          char *buf, size_t count, loff_t *ppos)
+{
+       int len, err;
+       struct mpuirq_dev_data *p_mpuirq_dev_data = file->private_data;
+
+       if (!mpuirq_dev_data.data_ready &&
+           mpuirq_dev_data.timeout && (!(file->f_flags & O_NONBLOCK))) {
+               wait_event_interruptible_timeout(mpuirq_wait,
+                                                mpuirq_dev_data.data_ready,
+                                                mpuirq_dev_data.timeout);
+       }
+
+       if (mpuirq_dev_data.data_ready && NULL != buf
+           && count >= sizeof(mpuirq_data)) {
+               err = copy_to_user(buf, &mpuirq_data, sizeof(mpuirq_data));
+               mpuirq_data.data_type = 0;
+       } else {
+               return 0;
+       }
+       if (err != 0) {
+               dev_err(p_mpuirq_dev_data->dev->this_device,
+                       "Copy to user returned %d\n", err);
+               return -EFAULT;
+       }
+       mpuirq_dev_data.data_ready = 0;
+       len = sizeof(mpuirq_data);
+       return len;
+}
+
+unsigned int mpuirq_poll(struct file *file, struct poll_table_struct *poll)
+{
+       int mask = 0;
+
+       poll_wait(file, &mpuirq_wait, poll);
+       if (mpuirq_dev_data.data_ready)
+               mask |= POLLIN | POLLRDNORM;
+       return mask;
+}
+
+/* ioctl - I/O control */
+static long mpuirq_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+       int retval = 0;
+       int data;
+
+       switch (cmd) {
+       case MPUIRQ_SET_TIMEOUT:
+               mpuirq_dev_data.timeout = arg;
+               break;
+
+       case MPUIRQ_GET_INTERRUPT_CNT:
+               data = mpuirq_data.interruptcount - 1;
+               if (mpuirq_data.interruptcount > 1)
+                       mpuirq_data.interruptcount = 1;
+
+               if (copy_to_user((int *)arg, &data, sizeof(int)))
+                       return -EFAULT;
+               break;
+       case MPUIRQ_GET_IRQ_TIME:
+               if (copy_to_user((int *)arg, &mpuirq_data.irqtime,
+                                sizeof(mpuirq_data.irqtime)))
+                       return -EFAULT;
+               mpuirq_data.irqtime = 0;
+               break;
+       case MPUIRQ_SET_FREQUENCY_DIVIDER:
+               mpuirq_dev_data.accel_divider = arg;
+               break;
+       default:
+               retval = -EINVAL;
+       }
+       return retval;
+}
+
+static irqreturn_t mpuirq_handler(int irq, void *dev_id)
+{
+       static int mycount;
+       struct timeval irqtime;
+       mycount++;
+
+       mpuirq_data.interruptcount++;
+
+       /* wake up (unblock) for reading data from userspace */
+       /* and ignore first interrupt generated in module init */
+       mpuirq_dev_data.data_ready = 1;
+
+       do_gettimeofday(&irqtime);
+       mpuirq_data.irqtime = (((long long)irqtime.tv_sec) << 32);
+       mpuirq_data.irqtime += irqtime.tv_usec;
+       mpuirq_data.data_type = MPUIRQ_DATA_TYPE_MPU_IRQ;
+       mpuirq_data.data = 0;
+
+       wake_up_interruptible(&mpuirq_wait);
+
+       return IRQ_HANDLED;
+
+}
+
+/* define which file operations are supported */
+const struct file_operations mpuirq_fops = {
+       .owner = THIS_MODULE,
+       .read = mpuirq_read,
+       .poll = mpuirq_poll,
+
+       .unlocked_ioctl = mpuirq_ioctl,
+       .open = mpuirq_open,
+       .release = mpuirq_release,
+};
+
+static struct miscdevice mpuirq_device = {
+       .minor = MISC_DYNAMIC_MINOR,
+       .name = MPUIRQ_NAME,
+       .fops = &mpuirq_fops,
+};
+
+int mpuirq_init(struct i2c_client *mpu_client, struct mldl_cfg *mldl_cfg)
+{
+
+       int res;
+
+       mpuirq_dev_data.mpu_client = mpu_client;
+
+       dev_info(&mpu_client->adapter->dev,
+                "Module Param interface = %s\n", interface);
+       
+       mpuirq_dev_data.irq = gpio_to_irq(mpu_client->irq);
+       mpuirq_dev_data.pid = 0;
+       mpuirq_dev_data.accel_divider = -1;
+       mpuirq_dev_data.data_ready = 0;
+       mpuirq_dev_data.timeout = 0;
+       mpuirq_dev_data.dev = &mpuirq_device;
+
+       if (mpuirq_dev_data.irq) {
+               unsigned long flags;
+               if (BIT_ACTL_LOW == ((mldl_cfg->pdata->int_config) & BIT_ACTL))
+                       flags = IRQF_TRIGGER_FALLING;
+               else
+                       flags = IRQF_TRIGGER_RISING;
+
+               flags |= IRQF_SHARED;
+               res =
+                   request_irq(mpuirq_dev_data.irq, mpuirq_handler, flags,
+                               interface, &mpuirq_dev_data.irq);
+               if (res) {
+                       dev_err(&mpu_client->adapter->dev,
+                               "myirqtest: cannot register IRQ %d\n",
+                               mpuirq_dev_data.irq);
+               } else {
+                       res = misc_register(&mpuirq_device);
+                       if (res < 0) {
+                               dev_err(&mpu_client->adapter->dev,
+                                       "misc_register returned %d\n", res);
+                               free_irq(mpuirq_dev_data.irq,
+                                        &mpuirq_dev_data.irq);
+                       }
+               }
+
+       } else {
+               res = 0;
+       }
+
+       return res;
+}
+
+void mpuirq_exit(void)
+{
+       if (mpuirq_dev_data.irq > 0)
+               free_irq(mpuirq_dev_data.irq, &mpuirq_dev_data.irq);
+
+       dev_info(mpuirq_device.this_device, "Unregistering %s\n", MPUIRQ_NAME);
+       misc_deregister(&mpuirq_device);
+
+       return;
+}
+
+module_param(interface, charp, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(interface, "The Interface name");
diff --git a/drivers/misc/inv_mpu/mpuirq.h b/drivers/misc/inv_mpu/mpuirq.h
new file mode 100644 (file)
index 0000000..3348071
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+#ifndef __MPUIRQ__
+#define __MPUIRQ__
+
+#include <linux/i2c-dev.h>
+#include <linux/time.h>
+#include <linux/ioctl.h>
+#include "mldl_cfg.h"
+
+#define MPUIRQ_SET_TIMEOUT           _IOW(MPU_IOCTL, 0x40, unsigned long)
+#define MPUIRQ_GET_INTERRUPT_CNT     _IOR(MPU_IOCTL, 0x41, unsigned long)
+#define MPUIRQ_GET_IRQ_TIME          _IOR(MPU_IOCTL, 0x42, struct timeval)
+#define MPUIRQ_SET_FREQUENCY_DIVIDER _IOW(MPU_IOCTL, 0x43, unsigned long)
+
+void mpuirq_exit(void);
+int mpuirq_init(struct i2c_client *mpu_client, struct mldl_cfg *mldl_cfg);
+
+#endif
diff --git a/drivers/misc/inv_mpu/pressure/Kconfig b/drivers/misc/inv_mpu/pressure/Kconfig
new file mode 100644 (file)
index 0000000..f1c021e
--- /dev/null
@@ -0,0 +1,20 @@
+menuconfig: INV_SENSORS_PRESSURE
+       bool "Pressure Sensor Slaves"
+       depends on INV_SENSORS
+       default y
+       help
+         Select y to see a list of supported pressure sensors that can be
+         integrated with the MPUxxxx set of motion processors.
+
+if INV_SENSORS_PRESSURE
+
+config MPU_SENSORS_BMA085
+       tristate "Bosch BMA085"
+       help
+         This enables support for the Bosch bma085 pressure sensor
+         This support is for integration with the MPU3050 or MPU6050 gyroscope
+          device driver.  Only one accelerometer can be registered at a time.
+         Specifying more that one accelerometer in the board file will result
+         in runtime errors.
+
+endif
diff --git a/drivers/misc/inv_mpu/pressure/Makefile b/drivers/misc/inv_mpu/pressure/Makefile
new file mode 100644 (file)
index 0000000..595923d
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# Pressure Slaves to MPUxxxx
+#
+obj-$(CONFIG_MPU_SENSORS_BMA085) += inv_mpu_bma085.o
+inv_mpu_bma085-objs += bma085.o
+
+EXTRA_CFLAGS += -Idrivers/misc/inv_mpu
+EXTRA_CFLAGS += -D__C99_DESIGNATED_INITIALIZER
diff --git a/drivers/misc/inv_mpu/pressure/bma085.c b/drivers/misc/inv_mpu/pressure/bma085.c
new file mode 100644 (file)
index 0000000..696d2b6
--- /dev/null
@@ -0,0 +1,367 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+/**
+ *  @defgroup   ACCELDL (Motion Library - Pressure Driver Layer)
+ *  @brief      Provides the interface to setup and handle a pressure
+ *              connected to the secondary I2C interface of the gyroscope.
+ *
+ *  @{
+ *      @file   bma085.c
+ *      @brief  Pressure setup and handling methods.
+ */
+
+/* ------------------ */
+/* - Include Files. - */
+/* ------------------ */
+
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include "mpu-dev.h"
+
+#include <linux/mpu.h>
+#include "mlsl.h"
+#include "log.h"
+
+/*
+ * this structure holds all device specific calibration parameters
+ */
+struct bmp085_calibration_param_t {
+       short ac1;
+       short ac2;
+       short ac3;
+       unsigned short ac4;
+       unsigned short ac5;
+       unsigned short ac6;
+       short b1;
+       short b2;
+       short mb;
+       short mc;
+       short md;
+       long param_b5;
+};
+
+struct bmp085_calibration_param_t cal_param;
+
+#define PRESSURE_BMA085_PARAM_MG      3038        /* calibration parameter */
+#define PRESSURE_BMA085_PARAM_MH     -7357        /* calibration parameter */
+#define PRESSURE_BMA085_PARAM_MI      3791        /* calibration parameter */
+
+/*********************************************
+ *    Pressure Initialization Functions
+ *********************************************/
+
+static int bma085_suspend(void *mlsl_handle,
+                         struct ext_slave_descr *slave,
+                         struct ext_slave_platform_data *pdata)
+{
+       int result = INV_SUCCESS;
+       return result;
+}
+
+#define PRESSURE_BMA085_PROM_START_ADDR  (0xAA)
+#define PRESSURE_BMA085_PROM_DATA_LEN    (22)
+#define PRESSURE_BMP085_CTRL_MEAS_REG    (0xF4)
+/* temperature measurent */
+#define PRESSURE_BMP085_T_MEAS           (0x2E)
+/* pressure measurement; oversampling_setting */
+#define PRESSURE_BMP085_P_MEAS_OSS_0     (0x34)
+#define PRESSURE_BMP085_P_MEAS_OSS_1     (0x74)
+#define PRESSURE_BMP085_P_MEAS_OSS_2     (0xB4)
+#define PRESSURE_BMP085_P_MEAS_OSS_3     (0xF4)
+#define PRESSURE_BMP085_ADC_OUT_MSB_REG  (0xF6)
+#define PRESSURE_BMP085_ADC_OUT_LSB_REG  (0xF7)
+
+static int bma085_resume(void *mlsl_handle,
+                        struct ext_slave_descr *slave,
+                        struct ext_slave_platform_data *pdata)
+{
+       int result;
+       unsigned char data[PRESSURE_BMA085_PROM_DATA_LEN];
+
+       result =
+           inv_serial_read(mlsl_handle, pdata->address,
+                          PRESSURE_BMA085_PROM_START_ADDR,
+                          PRESSURE_BMA085_PROM_DATA_LEN, data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+
+       /* parameters AC1-AC6 */
+       cal_param.ac1 = (data[0] << 8) | data[1];
+       cal_param.ac2 = (data[2] << 8) | data[3];
+       cal_param.ac3 = (data[4] << 8) | data[5];
+       cal_param.ac4 = (data[6] << 8) | data[7];
+       cal_param.ac5 = (data[8] << 8) | data[9];
+       cal_param.ac6 = (data[10] << 8) | data[11];
+
+       /* parameters B1,B2 */
+       cal_param.b1 = (data[12] << 8) | data[13];
+       cal_param.b2 = (data[14] << 8) | data[15];
+
+       /* parameters MB,MC,MD */
+       cal_param.mb = (data[16] << 8) | data[17];
+       cal_param.mc = (data[18] << 8) | data[19];
+       cal_param.md = (data[20] << 8) | data[21];
+
+       return result;
+}
+
+static int bma085_read(void *mlsl_handle,
+                      struct ext_slave_descr *slave,
+                      struct ext_slave_platform_data *pdata,
+                      unsigned char *data)
+{
+       int result;
+       long pressure, x1, x2, x3, b3, b6;
+       unsigned long b4, b7;
+       unsigned long up;
+       unsigned short ut;
+       short oversampling_setting = 0;
+       short temperature;
+       long divisor;
+
+       /* get temprature */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      PRESSURE_BMP085_CTRL_MEAS_REG,
+                                      PRESSURE_BMP085_T_MEAS);
+       msleep(5);
+       result =
+           inv_serial_read(mlsl_handle, pdata->address,
+                          PRESSURE_BMP085_ADC_OUT_MSB_REG, 2,
+                          (unsigned char *)data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       ut = (data[0] << 8) | data[1];
+
+       x1 = (((long) ut - (long)cal_param.ac6) * (long)cal_param.ac5) >> 15;
+       divisor = x1 + cal_param.md;
+       if (!divisor)
+               return INV_ERROR_DIVIDE_BY_ZERO;
+
+       x2 = ((long)cal_param.mc << 11) / (x1 + cal_param.md);
+       cal_param.param_b5 = x1 + x2;
+       /* temperature in 0.1 degree C */
+       temperature = (short)((cal_param.param_b5 + 8) >> 4);
+
+       /* get pressure */
+       result = inv_serial_single_write(mlsl_handle, pdata->address,
+                                      PRESSURE_BMP085_CTRL_MEAS_REG,
+                                      PRESSURE_BMP085_P_MEAS_OSS_0);
+       msleep(5);
+       result =
+           inv_serial_read(mlsl_handle, pdata->address,
+                          PRESSURE_BMP085_ADC_OUT_MSB_REG, 2,
+                          (unsigned char *)data);
+       if (result) {
+               LOG_RESULT_LOCATION(result);
+               return result;
+       }
+       up = (((unsigned long) data[0] << 8) | ((unsigned long) data[1]));
+
+       b6 = cal_param.param_b5 - 4000;
+       /* calculate B3 */
+       x1 = (b6*b6) >> 12;
+       x1 *= cal_param.b2;
+       x1 >>= 11;
+
+       x2 = (cal_param.ac2*b6);
+       x2 >>= 11;
+
+       x3 = x1 + x2;
+
+       b3 = (((((long)cal_param.ac1) * 4 + x3)
+           << oversampling_setting) + 2) >> 2;
+
+       /* calculate B4 */
+       x1 = (cal_param.ac3 * b6) >> 13;
+       x2 = (cal_param.b1 * ((b6*b6) >> 12)) >> 16;
+       x3 = ((x1 + x2) + 2) >> 2;
+       b4 = (cal_param.ac4 * (unsigned long) (x3 + 32768)) >> 15;
+       if (!b4)
+               return INV_ERROR;
+
+       b7 = ((unsigned long)(up - b3) * (50000>>oversampling_setting));
+       if (b7 < 0x80000000)
+               pressure = (b7 << 1) / b4;
+       else
+               pressure = (b7 / b4) << 1;
+
+       x1 = pressure >> 8;
+       x1 *= x1;
+       x1 = (x1 * PRESSURE_BMA085_PARAM_MG) >> 16;
+       x2 = (pressure * PRESSURE_BMA085_PARAM_MH) >> 16;
+       /* pressure in Pa */
+       pressure += (x1 + x2 + PRESSURE_BMA085_PARAM_MI) >> 4;
+
+       data[0] = (unsigned char)(pressure >> 16);
+       data[1] = (unsigned char)(pressure >> 8);
+       data[2] = (unsigned char)(pressure & 0xFF);
+
+       return result;
+}
+
+static struct ext_slave_descr bma085_descr = {
+       .init             = NULL,
+       .exit             = NULL,
+       .suspend          = bma085_suspend,
+       .resume           = bma085_resume,
+       .read             = bma085_read,
+       .config           = NULL,
+       .get_config       = NULL,
+       .name             = "bma085",
+       .type             = EXT_SLAVE_TYPE_PRESSURE,
+       .id               = PRESSURE_ID_BMA085,
+       .read_reg         = 0xF6,
+       .read_len         = 3,
+       .endian           = EXT_SLAVE_BIG_ENDIAN,
+       .range            = {0, 0},
+};
+
+static
+struct ext_slave_descr *bma085_get_slave_descr(void)
+{
+       return &bma085_descr;
+}
+
+/* Platform data for the MPU */
+struct bma085_mod_private_data {
+       struct i2c_client *client;
+       struct ext_slave_platform_data *pdata;
+};
+
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+
+static int bma085_mod_probe(struct i2c_client *client,
+                          const struct i2c_device_id *devid)
+{
+       struct ext_slave_platform_data *pdata;
+       struct bma085_mod_private_data *private_data;
+       int result = 0;
+
+       dev_info(&client->adapter->dev, "%s: %s\n", __func__, devid->name);
+
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               result = -ENODEV;
+               goto out_no_free;
+       }
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->adapter->dev,
+                       "Missing platform data for slave %s\n", devid->name);
+               result = -EFAULT;
+               goto out_no_free;
+       }
+
+       private_data = kzalloc(sizeof(*private_data), GFP_KERNEL);
+       if (!private_data) {
+               result = -ENOMEM;
+               goto out_no_free;
+       }
+
+       i2c_set_clientdata(client, private_data);
+       private_data->client = client;
+       private_data->pdata = pdata;
+
+       result = inv_mpu_register_slave(THIS_MODULE, client, pdata,
+                                       bma085_get_slave_descr);
+       if (result) {
+               dev_err(&client->adapter->dev,
+                       "Slave registration failed: %s, %d\n",
+                       devid->name, result);
+               goto out_free_memory;
+       }
+
+       return result;
+
+out_free_memory:
+       kfree(private_data);
+out_no_free:
+       dev_err(&client->adapter->dev, "%s failed %d\n", __func__, result);
+       return result;
+
+}
+
+static int bma085_mod_remove(struct i2c_client *client)
+{
+       struct bma085_mod_private_data *private_data =
+               i2c_get_clientdata(client);
+
+       dev_dbg(&client->adapter->dev, "%s\n", __func__);
+
+       inv_mpu_unregister_slave(client, private_data->pdata,
+                               bma085_get_slave_descr);
+
+       kfree(private_data);
+       return 0;
+}
+
+static const struct i2c_device_id bma085_mod_id[] = {
+       { "bma085", PRESSURE_ID_BMA085 },
+       {}
+};
+
+MODULE_DEVICE_TABLE(i2c, bma085_mod_id);
+
+static struct i2c_driver bma085_mod_driver = {
+       .class = I2C_CLASS_HWMON,
+       .probe = bma085_mod_probe,
+       .remove = bma085_mod_remove,
+       .id_table = bma085_mod_id,
+       .driver = {
+                  .owner = THIS_MODULE,
+                  .name = "bma085_mod",
+                  },
+       .address_list = normal_i2c,
+};
+
+static int __init bma085_mod_init(void)
+{
+       int res = i2c_add_driver(&bma085_mod_driver);
+       pr_info("%s: Probe name %s\n", __func__, "bma085_mod");
+       if (res)
+               pr_err("%s failed\n", __func__);
+       return res;
+}
+
+static void __exit bma085_mod_exit(void)
+{
+       pr_info("%s\n", __func__);
+       i2c_del_driver(&bma085_mod_driver);
+}
+
+module_init(bma085_mod_init);
+module_exit(bma085_mod_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Driver to integrate BMA085 sensor with the MPU");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("bma085_mod");
+/**
+ *  @}
+**/
diff --git a/drivers/misc/inv_mpu/slaveirq.c b/drivers/misc/inv_mpu/slaveirq.c
new file mode 100755 (executable)
index 0000000..95e690e
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/irq.h>
+#include <linux/signal.h>
+#include <linux/miscdevice.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/poll.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/slab.h>
+
+#include <linux/mpu.h>
+#include "slaveirq.h"
+#include "mldl_cfg.h"
+
+/* function which gets slave data and sends it to SLAVE */
+
+struct slaveirq_dev_data {
+       struct miscdevice dev;
+       struct i2c_client *slave_client;
+       struct mpuirq_data data;
+       wait_queue_head_t slaveirq_wait;
+       int irq;
+       int pid;
+       int data_ready;
+       int timeout;
+};
+
+/* The following depends on patch fa1f68db6ca7ebb6fc4487ac215bffba06c01c28
+ * drivers: misc: pass miscdevice pointer via file private data
+ */
+static int slaveirq_open(struct inode *inode, struct file *file)
+{
+       /* Device node is availabe in the file->private_data, this is
+        * exactly what we want so we leave it there */
+       struct slaveirq_dev_data *data =
+           container_of(file->private_data, struct slaveirq_dev_data, dev);
+
+       dev_dbg(data->dev.this_device,
+               "%s current->pid %d\n", __func__, current->pid);
+       data->pid = current->pid;
+       return 0;
+}
+
+static int slaveirq_release(struct inode *inode, struct file *file)
+{
+       struct slaveirq_dev_data *data =
+           container_of(file->private_data, struct slaveirq_dev_data, dev);
+       dev_dbg(data->dev.this_device, "slaveirq_release\n");
+       return 0;
+}
+
+/* read function called when from /dev/slaveirq is read */
+static ssize_t slaveirq_read(struct file *file,
+                            char *buf, size_t count, loff_t *ppos)
+{
+       int len, err;
+       struct slaveirq_dev_data *data =
+           container_of(file->private_data, struct slaveirq_dev_data, dev);
+
+       if (!data->data_ready && data->timeout &&
+           !(file->f_flags & O_NONBLOCK)) {
+               wait_event_interruptible_timeout(data->slaveirq_wait,
+                                                data->data_ready,
+                                                data->timeout);
+       }
+
+       if (data->data_ready && NULL != buf && count >= sizeof(data->data)) {
+               err = copy_to_user(buf, &data->data, sizeof(data->data));
+               data->data.data_type = 0;
+       } else {
+               return 0;
+       }
+       if (err != 0) {
+               dev_err(data->dev.this_device,
+                       "Copy to user returned %d\n", err);
+               return -EFAULT;
+       }
+       data->data_ready = 0;
+       len = sizeof(data->data);
+       return len;
+}
+
+static unsigned int slaveirq_poll(struct file *file,
+                                 struct poll_table_struct *poll)
+{
+       int mask = 0;
+       struct slaveirq_dev_data *data =
+           container_of(file->private_data, struct slaveirq_dev_data, dev);
+
+       poll_wait(file, &data->slaveirq_wait, poll);
+       if (data->data_ready)
+               mask |= POLLIN | POLLRDNORM;
+       return mask;
+}
+
+/* ioctl - I/O control */
+static long slaveirq_ioctl(struct file *file,
+                          unsigned int cmd, unsigned long arg)
+{
+       int retval = 0;
+       int tmp;
+       struct slaveirq_dev_data *data =
+           container_of(file->private_data, struct slaveirq_dev_data, dev);
+
+       switch (cmd) {
+       case SLAVEIRQ_SET_TIMEOUT:
+               data->timeout = arg;
+               break;
+
+       case SLAVEIRQ_GET_INTERRUPT_CNT:
+               tmp = data->data.interruptcount - 1;
+               if (data->data.interruptcount > 1)
+                       data->data.interruptcount = 1;
+
+               if (copy_to_user((int *)arg, &tmp, sizeof(int)))
+                       return -EFAULT;
+               break;
+       case SLAVEIRQ_GET_IRQ_TIME:
+               if (copy_to_user((int *)arg, &data->data.irqtime,
+                                sizeof(data->data.irqtime)))
+                       return -EFAULT;
+               data->data.irqtime = 0;
+               break;
+       default:
+               retval = -EINVAL;
+       }
+       return retval;
+}
+
+static irqreturn_t slaveirq_handler(int irq, void *dev_id)
+{
+       struct slaveirq_dev_data *data = (struct slaveirq_dev_data *)dev_id;
+       static int mycount;
+       struct timeval irqtime;
+       mycount++;
+
+       data->data.interruptcount++;
+
+       /* wake up (unblock) for reading data from userspace */
+       data->data_ready = 1;
+
+       do_gettimeofday(&irqtime);
+       data->data.irqtime = (((long long)irqtime.tv_sec) << 32);
+       data->data.irqtime += irqtime.tv_usec;
+       data->data.data_type |= 1;
+
+       wake_up_interruptible(&data->slaveirq_wait);
+
+       return IRQ_HANDLED;
+
+}
+
+/* define which file operations are supported */
+static const struct file_operations slaveirq_fops = {
+       .owner = THIS_MODULE,
+       .read = slaveirq_read,
+       .poll = slaveirq_poll,
+
+#if HAVE_COMPAT_IOCTL
+       .compat_ioctl = slaveirq_ioctl,
+#endif
+#if HAVE_UNLOCKED_IOCTL
+       .unlocked_ioctl = slaveirq_ioctl,
+#endif
+       .open = slaveirq_open,
+       .release = slaveirq_release,
+};
+
+int slaveirq_init(struct i2c_adapter *slave_adapter,
+                 struct ext_slave_platform_data *pdata, char *name)
+{
+
+       int res;
+       struct slaveirq_dev_data *data;
+
+       if (!pdata->irq)
+               return -EINVAL;
+
+       pdata->irq_data = kzalloc(sizeof(*data), GFP_KERNEL);
+       data = (struct slaveirq_dev_data *)pdata->irq_data;
+       if (!data)
+               return -ENOMEM;
+
+       data->dev.minor = MISC_DYNAMIC_MINOR;
+       data->dev.name = name;
+       data->dev.fops = &slaveirq_fops;
+       data->irq = pdata->irq;
+       data->pid = 0;
+       data->data_ready = 0;
+       data->timeout = 0;
+
+       init_waitqueue_head(&data->slaveirq_wait);
+
+       res = request_irq(data->irq, slaveirq_handler,
+                       IRQF_TRIGGER_RISING | IRQF_SHARED,
+                         data->dev.name, data);
+
+       if (res) {
+               dev_err(&slave_adapter->dev,
+                       "myirqtest: cannot register IRQ %d\n", data->irq);
+               goto out_request_irq;
+       }
+
+       res = misc_register(&data->dev);
+       if (res < 0) {
+               dev_err(&slave_adapter->dev,
+                       "misc_register returned %d\n", res);
+               goto out_misc_register;
+       }
+
+       return res;
+
+out_misc_register:
+       free_irq(data->irq, data);
+out_request_irq:
+       kfree(pdata->irq_data);
+       pdata->irq_data = NULL;
+
+       return res;
+}
+
+void slaveirq_exit(struct ext_slave_platform_data *pdata)
+{
+       struct slaveirq_dev_data *data = pdata->irq_data;
+
+       if (!pdata->irq_data || data->irq <= 0)
+               return;
+
+       dev_info(data->dev.this_device, "Unregistering %s\n", data->dev.name);
+
+       free_irq(data->irq, data);
+       misc_deregister(&data->dev);
+       kfree(pdata->irq_data);
+       pdata->irq_data = NULL;
+}
diff --git a/drivers/misc/inv_mpu/slaveirq.h b/drivers/misc/inv_mpu/slaveirq.h
new file mode 100644 (file)
index 0000000..6926634
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+#ifndef __SLAVEIRQ__
+#define __SLAVEIRQ__
+
+#include <linux/i2c-dev.h>
+
+#include <linux/mpu.h>
+#include "mpuirq.h"
+
+#define SLAVEIRQ_SET_TIMEOUT           _IOW(MPU_IOCTL, 0x50, unsigned long)
+#define SLAVEIRQ_GET_INTERRUPT_CNT     _IOR(MPU_IOCTL, 0x51, unsigned long)
+#define SLAVEIRQ_GET_IRQ_TIME          _IOR(MPU_IOCTL, 0x52, unsigned long)
+
+void slaveirq_exit(struct ext_slave_platform_data *pdata);
+int slaveirq_init(struct i2c_adapter *slave_adapter,
+                 struct ext_slave_platform_data *pdata, char *name);
+
+#endif
diff --git a/drivers/misc/inv_mpu/timerirq.c b/drivers/misc/inv_mpu/timerirq.c
new file mode 100755 (executable)
index 0000000..601858f
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/stat.h>
+#include <linux/signal.h>
+#include <linux/miscdevice.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/poll.h>
+
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+#include <linux/timer.h>
+#include <linux/slab.h>
+
+#include <linux/mpu.h>
+#include "mltypes.h"
+#include "timerirq.h"
+
+/* function which gets timer data and sends it to TIMER */
+struct timerirq_data {
+       int pid;
+       int data_ready;
+       int run;
+       int timeout;
+       unsigned long period;
+       struct mpuirq_data data;
+       struct completion timer_done;
+       wait_queue_head_t timerirq_wait;
+       struct timer_list timer;
+       struct miscdevice *dev;
+};
+
+static struct miscdevice *timerirq_dev_data;
+
+static void timerirq_handler(unsigned long arg)
+{
+       struct timerirq_data *data = (struct timerirq_data *)arg;
+       struct timeval irqtime;
+
+       data->data.interruptcount++;
+
+       data->data_ready = 1;
+
+       do_gettimeofday(&irqtime);
+       data->data.irqtime = (((long long)irqtime.tv_sec) << 32);
+       data->data.irqtime += irqtime.tv_usec;
+       data->data.data_type |= 1;
+
+       dev_dbg(data->dev->this_device,
+               "%s, %lld, %ld\n", __func__, data->data.irqtime,
+               (unsigned long)data);
+
+       wake_up_interruptible(&data->timerirq_wait);
+
+       if (data->run)
+               mod_timer(&data->timer,
+                         jiffies + msecs_to_jiffies(data->period));
+       else
+               complete(&data->timer_done);
+}
+
+static int start_timerirq(struct timerirq_data *data)
+{
+       dev_dbg(data->dev->this_device,
+               "%s current->pid %d\n", __func__, current->pid);
+
+       /* Timer already running... success */
+       if (data->run)
+               return 0;
+
+       /* Don't allow a period of 0 since this would fire constantly */
+       if (!data->period)
+               return -EINVAL;
+
+       data->run = true;
+       data->data_ready = false;
+
+       init_completion(&data->timer_done);
+       setup_timer(&data->timer, timerirq_handler, (unsigned long)data);
+
+       return mod_timer(&data->timer,
+                        jiffies + msecs_to_jiffies(data->period));
+}
+
+static int stop_timerirq(struct timerirq_data *data)
+{
+       dev_dbg(data->dev->this_device,
+               "%s current->pid %lx\n", __func__, (unsigned long)data);
+
+       if (data->run) {
+               data->run = false;
+               mod_timer(&data->timer, jiffies + 1);
+               wait_for_completion(&data->timer_done);
+       }
+       return 0;
+}
+
+/* The following depends on patch fa1f68db6ca7ebb6fc4487ac215bffba06c01c28
+ * drivers: misc: pass miscdevice pointer via file private data
+ */
+static int timerirq_open(struct inode *inode, struct file *file)
+{
+       /* Device node is availabe in the file->private_data, this is
+        * exactly what we want so we leave it there */
+       struct miscdevice *dev_data = file->private_data;
+       struct timerirq_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       data->dev = dev_data;
+       file->private_data = data;
+       data->pid = current->pid;
+       init_waitqueue_head(&data->timerirq_wait);
+
+       dev_dbg(data->dev->this_device,
+               "%s current->pid %d\n", __func__, current->pid);
+       return 0;
+}
+
+static int timerirq_release(struct inode *inode, struct file *file)
+{
+       struct timerirq_data *data = file->private_data;
+       dev_dbg(data->dev->this_device, "timerirq_release\n");
+       if (data->run)
+               stop_timerirq(data);
+       kfree(data);
+       return 0;
+}
+
+/* read function called when from /dev/timerirq is read */
+static ssize_t timerirq_read(struct file *file,
+                            char *buf, size_t count, loff_t *ppos)
+{
+       int len, err;
+       struct timerirq_data *data = file->private_data;
+
+       if (!data->data_ready && data->timeout &&
+           !(file->f_flags & O_NONBLOCK)) {
+               wait_event_interruptible_timeout(data->timerirq_wait,
+                                                data->data_ready,
+                                                data->timeout);
+       }
+
+       if (data->data_ready && NULL != buf && count >= sizeof(data->data)) {
+               err = copy_to_user(buf, &data->data, sizeof(data->data));
+               data->data.data_type = 0;
+       } else {
+               return 0;
+       }
+       if (err != 0) {
+               dev_err(data->dev->this_device,
+                       "Copy to user returned %d\n", err);
+               return -EFAULT;
+       }
+       data->data_ready = 0;
+       len = sizeof(data->data);
+       return len;
+}
+
+static unsigned int timerirq_poll(struct file *file,
+                                 struct poll_table_struct *poll)
+{
+       int mask = 0;
+       struct timerirq_data *data = file->private_data;
+
+       poll_wait(file, &data->timerirq_wait, poll);
+       if (data->data_ready)
+               mask |= POLLIN | POLLRDNORM;
+       return mask;
+}
+
+/* ioctl - I/O control */
+static long timerirq_ioctl(struct file *file,
+                          unsigned int cmd, unsigned long arg)
+{
+       int retval = 0;
+       int tmp;
+       struct timerirq_data *data = file->private_data;
+
+       dev_dbg(data->dev->this_device,
+               "%s current->pid %d, %d, %ld\n",
+               __func__, current->pid, cmd, arg);
+
+       if (!data)
+               return -EFAULT;
+
+       switch (cmd) {
+       case TIMERIRQ_SET_TIMEOUT:
+               data->timeout = arg;
+               break;
+       case TIMERIRQ_GET_INTERRUPT_CNT:
+               tmp = data->data.interruptcount - 1;
+               if (data->data.interruptcount > 1)
+                       data->data.interruptcount = 1;
+
+               if (copy_to_user((int *)arg, &tmp, sizeof(int)))
+                       return -EFAULT;
+               break;
+       case TIMERIRQ_START:
+               data->period = arg;
+               retval = start_timerirq(data);
+               break;
+       case TIMERIRQ_STOP:
+               retval = stop_timerirq(data);
+               break;
+       default:
+               retval = -EINVAL;
+       }
+       return retval;
+}
+
+/* define which file operations are supported */
+static const struct file_operations timerirq_fops = {
+       .owner = THIS_MODULE,
+       .read = timerirq_read,
+       .poll = timerirq_poll,
+
+#if HAVE_COMPAT_IOCTL
+       .compat_ioctl = timerirq_ioctl,
+#endif
+#if HAVE_UNLOCKED_IOCTL
+       .unlocked_ioctl = timerirq_ioctl,
+#endif
+       .open = timerirq_open,
+       .release = timerirq_release,
+};
+
+static int __init timerirq_init(void)
+{
+
+       int res;
+       static struct miscdevice *data;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+       timerirq_dev_data = data;
+       data->minor = MISC_DYNAMIC_MINOR;
+       data->name = "timerirq";
+       data->fops = &timerirq_fops;
+
+       res = misc_register(data);
+       if (res < 0) {
+               dev_err(data->this_device, "misc_register returned %d\n", res);
+               return res;
+       }
+
+       return res;
+}
+
+module_init(timerirq_init);
+
+static void __exit timerirq_exit(void)
+{
+       struct miscdevice *data = timerirq_dev_data;
+
+       dev_info(data->this_device, "Unregistering %s\n", data->name);
+
+       misc_deregister(data);
+       kfree(data);
+
+       timerirq_dev_data = NULL;
+}
+
+module_exit(timerirq_exit);
+
+MODULE_AUTHOR("Invensense Corporation");
+MODULE_DESCRIPTION("Timer IRQ device driver.");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("timerirq");
diff --git a/drivers/misc/inv_mpu/timerirq.h b/drivers/misc/inv_mpu/timerirq.h
new file mode 100644 (file)
index 0000000..f69f07a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+       $License:
+       Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+
+       This program is free software; you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation; either version 2 of the License, or
+       (at your option) any later version.
+
+       This program is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with this program.  If not, see <http://www.gnu.org/licenses/>.
+       $
+ */
+
+#ifndef __TIMERIRQ__
+#define __TIMERIRQ__
+
+#include <linux/mpu.h>
+
+#define TIMERIRQ_SET_TIMEOUT           _IOW(MPU_IOCTL, 0x60, unsigned long)
+#define TIMERIRQ_GET_INTERRUPT_CNT     _IOW(MPU_IOCTL, 0x61, unsigned long)
+#define TIMERIRQ_START                 _IOW(MPU_IOCTL, 0x62, unsigned long)
+#define TIMERIRQ_STOP                  _IO(MPU_IOCTL, 0x63)
+
+#endif
diff --git a/drivers/misc/mpu3050/Kconfig b/drivers/misc/mpu3050/Kconfig
deleted file mode 100755 (executable)
index 210953f..0000000
+++ /dev/null
@@ -1,213 +0,0 @@
-
-menu "Motion Sensors Support"
-
-choice
-    tristate "Motion Processing Unit"
-    depends on I2C
-    default MPU_NONE
-
-config MPU_NONE
-    bool "None"
-    help
-      This disables support for motion processing using the MPU family of 
-      motion processing units.
-
-config MPU_SENSORS_MPU3050
-    tristate "MPU3050"
-    depends on I2C
-    help
-      If you say yes here you get support for the MPU3050 Gyroscope driver
-      This driver can also be built as a module.  If so, the module
-      will be called mpu3050.
-
-config MPU_SENSORS_MPU6000
-    tristate "MPU6000"
-    depends on I2C
-    help
-      If you say yes here you get support for the MPU6000 Gyroscope driver
-      This driver can also be built as a module.  If so, the module
-      will be called mpu6000.
-
-endchoice
-
-choice
-    prompt "Accelerometer Type"
-    depends on MPU_SENSORS_MPU3050
-    default MPU_SENSORS_BMA150
-
-config MPU_SENSORS_ACCELEROMETER_NONE
-    bool "NONE"
-    depends on MPU_SENSORS_MPU3050 || MPU_SENSORS_MPU6000
-    help
-      This disables accelerometer support for the MPU3050
-
-config MPU_SENSORS_ADXL346
-    bool "ADI adxl346"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the ADI adxl346 accelerometer
-
-config MPU_SENSORS_BMA150
-    bool "Bosch BMA150"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Bosch BMA150 accelerometer
-config MPU_SENSORS_BMA222
-    bool "Bosch BMA222"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Bosch BMA222 accelerometer
-      
-config MPU_SENSORS_KXSD9
-    bool "Kionix KXSD9"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Kionix KXSD9 accelerometer
-
-config MPU_SENSORS_KXTF9
-    bool "Kionix KXTF9"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Kionix KXFT9 accelerometer
-
-config MPU_SENSORS_LIS331DLH
-    bool "ST lis331dlh"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the ST lis331dlh accelerometer
-
-config MPU_SENSORS_LIS3DH
-    bool "ST lis3dh"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the ST lis3dh accelerometer
-
-config MPU_SENSORS_LSM303DLHA
-    bool "ST lsm303dlh"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the ST lsm303dlh accelerometer
-
-config MPU_SENSORS_MMA8450
-    bool "Freescale mma8450"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Freescale mma8450 accelerometer
-
-config MPU_SENSORS_MMA845X
-    bool "Freescale mma8451/8452/8453"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Freescale mma8451/8452/8453 accelerometer
-
-endchoice
-
-choice
-    prompt "Compass Type"
-    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
-    default MPU_SENSORS_AK8975
-
-config MPU_SENSORS_COMPASS_NONE
-    bool "NONE"
-    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
-    help
-      This disables compass support for the MPU6000
-
-config MPU_SENSORS_AK8975
-    bool "AKM ak8975"
-    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
-    help
-      This enables support for the AKM ak8975 compass
-
-config MPU_SENSORS_MMC314X
-    bool "MEMSIC mmc314x"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the MEMSIC mmc314x compass
-
-config MPU_SENSORS_AMI30X
-    bool "Aichi Steel ami30X"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Aichi Steel ami304/ami305 compass
-
-config MPU_SENSORS_AMI306
-    bool "Aichi Steel ami306"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Aichi Steel ami306 compass
-
-config MPU_SENSORS_HMC5883
-    bool "Honeywell hmc5883"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Honeywell hmc5883 compass
-
-config MPU_SENSORS_LSM303DLHM
-    bool "ST lsm303dlh"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the ST lsm303dlh compass
-
-config MPU_SENSORS_MMC314X
-    bool "MEMSIC mmc314xMS"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the MEMSIC mmc314xMS compass
-
-config MPU_SENSORS_YAS529
-    bool "Yamaha yas529"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Yamaha yas529 compass
-
-config MPU_SENSORS_YAS530
-    bool "Yamaha yas530"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Yamaha yas530 compass
-
-config MPU_SENSORS_HSCDTD002B
-    bool "Alps hscdtd002b"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Alps hscdtd002b compass
-
-config MPU_SENSORS_HSCDTD004A
-    bool "Alps hscdtd004a"
-    depends on MPU_SENSORS_MPU3050
-    help
-      This enables support for the Alps hscdtd004a compass
-
-endchoice
-
-choice
-    prompt "Pressure Type"
-    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
-    default MPU_SENSORS_BMA085
-
-config MPU_SENSORS_PRESSURE_NONE
-    bool "NONE"
-    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
-    help
-      This disables pressure sensor support for the MPU6000
-
-config MPU_SENSORS_BMA085
-    bool "Bosch BMA085"
-    depends on MPU_SENSORS_MPU6000 || MPU_SENSORS_MPU3050
-    help
-      This enables support for the Bosch bma085 pressure sensor
-
-endchoice
-
-config MPU_SENSORS_TIMERIRQ
-    tristate "Timer IRQ"
-    help
-      If you say yes here you get access to the timerirq device handle which
-      can be used to select on.  This can be used instead of IRQ's, sleeping,
-      or timer threads.  Reading from this device returns the same type of
-      information as reading from the MPU and slave IRQ's.
-
-endmenu
-
diff --git a/drivers/misc/mpu3050/Makefile b/drivers/misc/mpu3050/Makefile
deleted file mode 100755 (executable)
index 935915a..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-
-# Kernel makefile for motions sensors
-#
-# 
-
-# MPU
-obj-$(CONFIG_MPU_SENSORS_MPU3050)      += mpu3050.o
-mpu3050-objs += mpuirq.o \
-       slaveirq.o \
-       mpu-dev.o \
-       mpu-i2c.o \
-       mlsl-kernel.o \
-       mlos-kernel.o \
-       $(MLLITE_DIR)mldl_cfg.o
-
-#
-# Accel options
-#
-ifdef CONFIG_MPU_SENSORS_ADXL346
-mpu3050-objs += $(MLLITE_DIR)accel/adxl346.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_BMA150
-mpu3050-objs += $(MLLITE_DIR)accel/bma150.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_BMA222
-mpu3050-objs += $(MLLITE_DIR)accel/bma222.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_KXSD9
-mpu3050-objs += $(MLLITE_DIR)accel/kxsd9.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_KXTF9
-mpu3050-objs += $(MLLITE_DIR)accel/kxtf9.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_LIS331DLH
-mpu3050-objs += $(MLLITE_DIR)accel/lis331.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_LIS3DH
-mpu3050-objs += $(MLLITE_DIR)accel/lis3dh.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_LSM303DLHA
-mpu3050-objs += $(MLLITE_DIR)accel/lsm303a.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_MMA8450
-mpu3050-objs += $(MLLITE_DIR)accel/mma8450.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_MMA845X
-mpu3050-objs += $(MLLITE_DIR)accel/mma845x.o
-endif
-
-#
-# Compass options
-#
-ifdef CONFIG_MPU_SENSORS_AK8975
-mpu3050-objs += $(MLLITE_DIR)compass/ak8975.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_AMI30X
-mpu3050-objs += $(MLLITE_DIR)compass/ami30x.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_AMI306
-mpu3050-objs += $(MLLITE_DIR)compass/ami306.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_HMC5883
-mpu3050-objs += $(MLLITE_DIR)compass/hmc5883.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_LSM303DLHM
-mpu3050-objs += $(MLLITE_DIR)compass/lsm303m.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_MMC314X
-mpu3050-objs += $(MLLITE_DIR)compass/mmc314x.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_YAS529
-mpu3050-objs += $(MLLITE_DIR)compass/yas529-kernel.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_YAS530
-mpu3050-objs += $(MLLITE_DIR)compass/yas530.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_HSCDTD002B
-mpu3050-objs += $(MLLITE_DIR)compass/hscdtd002b.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_HSCDTD004A
-mpu3050-objs += $(MLLITE_DIR)compass/hscdtd004a.o
-endif
-#
-# Pressure options
-#
-ifdef CONFIG_MPU_SENSORS_BMA085
-mpu3050-objs += $(MLLITE_DIR)pressure/bma085.o
-endif
-
-EXTRA_CFLAGS += -I$(M)/$(MLLITE_DIR) \
-                -I$(M)/../../include \
-                               -Idrivers/misc/mpu3050 \
-                -Iinclude/linux
-
-obj-$(CONFIG_MPU_SENSORS_MPU6000)+= mpu6000.o
-mpu6000-objs += mpuirq.o \
-       slaveirq.o \
-       mpu-dev.o \
-       mpu-i2c.o \
-       mlsl-kernel.o \
-       mlos-kernel.o \
-       $(MLLITE_DIR)mldl_cfg.o \
-       $(MLLITE_DIR)accel/mantis.o
-
-ifdef CONFIG_MPU_SENSORS_AK8975
-mpu6000-objs += $(MLLITE_DIR)compass/ak8975.o
-endif
-
-ifdef CONFIG_MPU_SENSORS_MPU6000
-EXTRA_CFLAGS += -DM_HW
-endif
-
-obj-$(CONFIG_MPU_SENSORS_TIMERIRQ)+= timerirq.o
-
diff --git a/drivers/misc/mpu3050/README b/drivers/misc/mpu3050/README
deleted file mode 100755 (executable)
index 047b6ba..0000000
+++ /dev/null
@@ -1,270 +0,0 @@
-Kernel driver mpu\r
-=====================\r
-\r
-Supported chips:\r
-  * InvenSense IMU3050\r
-    Prefix: 'mpu3050'\r
-    Datasheet:\r
-        PS-MPU-3000A-00.2.4b.pdf\r
-\r
-  * InvenSense IMU6000\r
-    Prefix: 'mpu6000'\r
-    Datasheet:\r
-        MPU-6000A-00 v1.0.pdf\r
-\r
-Author: InvenSense <http://invensense.com>\r
-\r
-Description\r
------------\r
-The mpu is a motion processor unit that controls the mpu3050 gyroscope, a slave\r
-accelerometer, a compass and a pressure sensor, or the mpu6000 and slave \r
-compass.  This document describes how to install the driver into a Linux kernel\r
-and a small note about how to set up the file permissions in an android file\r
-system.\r
-\r
-Sysfs entries\r
--------------\r
-/dev/mpu\r
-/dev/mpuirq\r
-/dev/accelirq\r
-/dev/compassirq\r
-/dev/pressureirq\r
-\r
-General Remarks MPU3050\r
------------------------\r
-* Valid addresses for the MPU3050 is 0x68.\r
-* Accelerometer must be on the secondary I2C bus for MPU3050, the \r
-  magnetometer must be on the primary bus and pressure sensor must\r
-  be on the primary bus.\r
-\r
-General Remarks MPU6000\r
------------------------\r
-* Valid addresses for the MPU6000 is 0x68.\r
-* Magnetometer must be on the secondary I2C bus for the MPU6000.\r
-* Accelerometer slave address must be set to 0x68\r
-* Gyro and Accel orientation matrices should be the same\r
-\r
-Programming the chip using /dev/mpu\r
-----------------------------------\r
-Programming of MPU3050 or MPU6000 is done by first opening the /dev/mpu file and\r
-then performing a series of IOCTLS on the handle returned.  The IOCTL codes can\r
-be found in mpu.h.  Typically this is done by the mllite library in user\r
-space.\r
-\r
-Adding to a Kernel\r
-==================\r
-\r
-The mpu driver is designed to be inserted in the drivers/misc part of the \r
-kernel.  Extracting the tarball from the root kernel dir will place the\r
-contents of the tarball here:\r
-\r
-    <kernel root dir>/drivers/misc/mpu3050\r
-    <kernel root dir>/include/linux/mpu.h\r
-    <kernel root dir>/include/linux/mpu3050.h\r
-    <kernel root dir>/include/linux/mpu6000.h\r
-\r
-After this is done the drivers/misc/Kconfig must be edited to add the line:\r
-\r
-    source "drivers/misc/mpu3050/Kconfig"\r
-\r
-Similarly drivers/misc/Makefile must be edited to add the line:\r
-\r
-    obj-y += mpu3050/\r
-\r
-Configuration can then be done as normal.\r
-\r
-NOTE: This driver depends on a kernel patch to drivers/char/char.c.  This patch\r
-started to be included in most 2.6.35 based kernels.\r
-drivers: misc: pass miscdevice pointer via file private data\r
-https://patchwork.kernel.org/patch/96412/\r
-\r
----\r
- drivers/char/misc.c |    1 +\r
- 1 files changed, 1 insertions(+), 0 deletions(-)\r
-\r
-\r
-diff --git a/drivers/char/misc.c b/drivers/char/misc.c\r
-index 92ab03d..cd650ca 100644\r
---- a/drivers/char/misc.c\r
-+++ b/drivers/char/misc.c\r
-@@ -144,6 +144,7 @@ static int misc_open(struct inode * inode, struct file * file)\r
-       old_fops = file->f_op;\r
-       file->f_op = new_fops;\r
-       if (file->f_op->open) {\r
-+              file->private_data = c;\r
-               err=file->f_op->open(inode,file);\r
-               if (err) {\r
-                       fops_put(file->f_op);\r
----\r
-\r
-Board and Platform Data\r
------------------------\r
-\r
-In order for the driver to work, board and platform data specific to the device\r
-needs to be added to the board file.  A mpu3050_platform_data structure must\r
-be created and populated and set in the i2c_board_info_structure.  For details\r
-of each structure member see mpu.h.  All values below are simply an example and\r
-should be modified for your platform.\r
-\r
-#include <linux/mpu.h>\r
-\r
-#if defined(CONFIG_MPU_SENSORS_MPU3050) || defined(CONFIG_MPU_SENSORS_MPU3050_MODULE)\r
-\r
-#define SENSOR_MPU_NAME "mpu3050"\r
-\r
-static struct mpu3050_platform_data mpu_data = {\r
-       .int_config  = 0x10,\r
-       .orientation = {  -1,  0,  0, \r
-                          0,  1,  0, \r
-                          0,  0, -1 },\r
-       /* accel */\r
-       .accel = {\r
-#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE\r
-                .get_slave_descr = NULL,\r
-#else\r
-                .get_slave_descr = get_accel_slave_descr,\r
-#endif\r
-                .adapt_num   = 2,\r
-                .bus         = EXT_SLAVE_BUS_SECONDARY,\r
-                .address     = 0x0F,\r
-                .orientation = {  -1,  0,  0, \r
-                                   0,  1,  0, \r
-                                   0,  0, -1 },\r
-        },\r
-       /* compass */\r
-       .compass = {\r
-#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE\r
-                .get_slave_descr = NULL,\r
-#else\r
-                .get_slave_descr = get_compass_slave_descr,\r
-#endif\r
-                .adapt_num   = 2,\r
-                .bus         = EXT_SLAVE_BUS_PRIMARY,\r
-                .address     = 0x0E,\r
-                .orientation = { 1, 0, 0, \r
-                                 0, 1, 0, \r
-                                 0, 0, 1 },\r
-        },\r
-       /* pressure */\r
-       .pressure = {\r
-#ifdef CONFIG_MPU_SENSORS_MPU3050_MODULE\r
-                .get_slave_descr = NULL,\r
-#else\r
-                .get_slave_descr = get_pressure_slave_descr,\r
-#endif\r
-                .adapt_num   = 2,\r
-                .bus         = EXT_SLAVE_BUS_PRIMARY,\r
-                .address     = 0x77,\r
-                .orientation = { 1, 0, 0, \r
-                                 0, 1, 0, \r
-                                 0, 0, 1 },\r
-        },\r
-};\r
-#endif\r
-\r
-#if defined(CONFIG_MPU_SENSORS_MPU6000) || defined(CONFIG_MPU_SENSORS_MPU6000_MODULE)\r
-\r
-#define SENSOR_MPU_NAME "mpu6000"\r
-\r
-static struct mpu3050_platform_data mpu_data = {\r
-       .int_config  = 0x10,\r
-       .orientation = {  -1,  0,  0,\r
-                          0,  1,  0,\r
-                          0,  0, -1 },\r
-       /* accel */\r
-       .accel = {\r
-#ifdef CONFIG_MPU_SENSORS_MPU6000_MODULE\r
-                .get_slave_descr = NULL,\r
-#else\r
-                .get_slave_descr = get_accel_slave_descr,\r
-#endif\r
-                .adapt_num   = 2,\r
-                .bus         = EXT_SLAVE_BUS_PRIMARY,\r
-                .address     = 0x68,\r
-                .orientation = {  -1,  0,  0,\r
-                                   0,  1,  0,\r
-                                   0,  0, -1 },\r
-        },\r
-       /* compass */\r
-       .compass = {\r
-#ifdef CONFIG_MPU_SENSORS_MPU6000_MODULE\r
-                .get_slave_descr = NULL,\r
-#else\r
-                .get_slave_descr = get_compass_slave_descr,\r
-#endif\r
-                .adapt_num   = 2,\r
-                .bus         = EXT_SLAVE_BUS_SECONDARY,\r
-                .address     = 0x0E,\r
-                .orientation = { 1, 0, 0,\r
-                                 0, 1, 0,\r
-                                 0, 0, 1 },\r
-        },\r
-       /* pressure */\r
-       .pressure = {\r
-#ifdef CONFIG_MPU_SENSORS_MPU6000_MODULE\r
-                .get_slave_descr = NULL,\r
-#else\r
-                .get_slave_descr = get_pressure_slave_descr,\r
-#endif\r
-                .adapt_num   = 2,\r
-                .bus         = EXT_SLAVE_BUS_PRIMARY,\r
-                .address     = 0x77,\r
-                .orientation = { 1, 0, 0, \r
-                                 0, 1, 0, \r
-                                 0, 0, 1 },\r
-        },\r
-\r
-};\r
-#endif\r
-\r
-static struct i2c_board_info __initdata beagle_i2c_2_boardinfo[] = {\r
-       {\r
-               I2C_BOARD_INFO(SENSOR_MPU_NAME, 0x68),\r
-               .irq = (IH_GPIO_BASE + MPU_GPIO_IRQ),\r
-               .platform_data = &mpu_data,\r
-       },\r
-};\r
-\r
-Typically the IRQ is a GPIO input pin and needs to be configured properly.  If\r
-in the above example GPIO 168 corresponds to IRQ 299, the following should be\r
-done as well:\r
-\r
-#define MPU_GPIO_IRQ 168\r
-\r
-    gpio_request(MPU_GPIO_IRQ,"MPUIRQ");\r
-    gpio_direction_input(MPU_GPIO_IRQ)\r
-\r
-NOTE:\r
-=====\r
-In previous releases, the sensors were defined using CONFIG_SENSORS_SENSORNAME convention. \r
-From this release onwards this convention will be changed to CONFIG_MPU_SENSORS_SENSORNAME. \r
-Please make note of this change.\r
-\r
-Dynamic Debug\r
-=============\r
-\r
-The mpu3050 makes use of dynamic debug.  For details on how to use this\r
-refer to Documentation/dynamic-debug-howto.txt\r
-\r
-Android File Permissions\r
-========================\r
-\r
-To set up the file permissions on an android system, the /dev/mpu and \r
-/dev/mpuirq files needs to be added to the system/core/init/devices.c file \r
-inside the perms_ structure.\r
-\r
-static struct perms_ devperms[] = {\r
-    { "/dev/mpu"           ,0660,   AID_SYSTEM,    AID_SYSTEM,     1 },\r
-};\r
-\r
-Sufficient file permissions need to be give to read and write it by the system.\r
-\r
-For gingerbread and later the system/core/rootdir/ueventd.rc file needs to be\r
-modified with the appripriate lines added.\r
-\r
-# MPU sensors and IRQ\r
-/dev/mpu                  0660   system     system\r
-/dev/mpuirq               0660   system     system\r
-/dev/accelirq             0660   system     system\r
-/dev/compassirq           0660   system     system\r
-/dev/pressureirq          0660   system     system\r
diff --git a/drivers/misc/mpu3050/accel/adxl346.c b/drivers/misc/mpu3050/accel/adxl346.c
deleted file mode 100755 (executable)
index 14cb38a..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   adxl346.c
- *      @brief  Accelerometer setup and handling methods for AD adxl346.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-#define ACCEL_ADI346_SLEEP_REG      (0x2D)
-#define ACCEL_ADI346_SLEEP_MASK     (0x04)
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-int adxl346_suspend(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata)
-{
-       int result;
-       unsigned char reg;
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address,
-                          ACCEL_ADI346_SLEEP_REG, 1, &reg);
-       ERROR_CHECK(result);
-       reg |= ACCEL_ADI346_SLEEP_MASK;
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_ADI346_SLEEP_REG, reg);
-       ERROR_CHECK(result);
-       return result;
-}
-
-/* full scale setting - register & mask */
-#define ACCEL_ADI346_CTRL_REG      (0x31)
-#define ACCEL_ADI346_CTRL_MASK     (0x03)
-
-int adxl346_resume(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg;
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address,
-                          ACCEL_ADI346_SLEEP_REG, 1, &reg);
-       ERROR_CHECK(result);
-       reg &= ~ACCEL_ADI346_SLEEP_MASK;
-       /*wake up if sleeping */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      ACCEL_ADI346_SLEEP_REG, reg);
-       ERROR_CHECK(result);
-       /*MLOSSleep(10) */
-
-       /* Full Scale */
-       reg = 0x04;
-       reg &= ~ACCEL_ADI346_CTRL_MASK;
-       if (slave->range.mantissa == 4)
-               reg |= 0x1;
-       else if (slave->range.mantissa == 8)
-               reg |= 0x2;
-       else if (slave->range.mantissa == 16)
-               reg |= 0x3;
-       else {
-               slave->range.mantissa = 2;
-               reg |= 0x0;
-       }
-       slave->range.fraction = 0;
-
-       /* DATA_FORMAT: full resolution of +/-2g; data is left justified */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x31, reg);
-       ERROR_CHECK(result);
-       /* BW_RATE: normal power operation with output data rate of 200Hz */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x2C, 0x0B);
-       ERROR_CHECK(result);
-       /* POWER_CTL: power on in measurement mode */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x2D, 0x28);
-       ERROR_CHECK(result);
-       /*--- after wake up, it takes at least [1/(data rate) + 1.1]ms ==>
-         6.1ms to get valid sensor data ---*/
-       MLOSSleep(10);
-
-       return result;
-}
-
-int adxl346_read(void *mlsl_handle,
-                struct ext_slave_descr *slave,
-                struct ext_slave_platform_data *pdata,
-                unsigned char *data)
-{
-       int result;
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               slave->reg, slave->len, data);
-       return result;
-}
-
-struct ext_slave_descr adxl346_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ adxl346_suspend,
-       /*.resume           = */ adxl346_resume,
-       /*.read             = */ adxl346_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "adx1346",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_ADI346,
-       /*.reg              = */ 0x32,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
-       /*.range            = */ {2, 0},
-};
-
-struct ext_slave_descr *adxl346_get_slave_descr(void)
-{
-       return &adxl346_descr;
-}
-EXPORT_SYMBOL(adxl346_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/accel/bma150.c b/drivers/misc/mpu3050/accel/bma150.c
deleted file mode 100755 (executable)
index 30fed15..0000000
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   bma150.c
- *      @brief  Accelerometer setup and handling methods.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlos.h"
-#include "mlsl.h"
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*********************************************
-    Accelerometer Initialization Functions
-**********************************************/
-
-static int bma150_suspend(void *mlsl_handle,
-                         struct ext_slave_descr *slave,
-                         struct ext_slave_platform_data *pdata)
-{
-       int result;
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x0a, 0x01);
-       MLOSSleep(3); /* 3 ms powerup time maximum */
-       ERROR_CHECK(result);
-       return result;
-}
-
-/* full scale setting - register and mask */
-#define ACCEL_BOSCH_CTRL_REG       (0x14)
-#define ACCEL_BOSCH_CTRL_MASK      (0x18)
-
-static int bma150_resume(void *mlsl_handle,
-                        struct ext_slave_descr *slave,
-                        struct ext_slave_platform_data *pdata)
-{
-       int result;
-       unsigned char reg = 0;
-
-       /* Soft reset */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x0a, 0x02);
-       ERROR_CHECK(result);
-       MLOSSleep(3);
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, 0x14, 1, &reg);
-       ERROR_CHECK(result);
-
-       /* Bandwidth */
-       reg &= 0xc0;
-       reg |= 3;               /* 3=190 Hz */
-
-       /* Full Scale */
-       reg &= ~ACCEL_BOSCH_CTRL_MASK;
-       if (slave->range.mantissa == 4)
-               reg |= 0x08;
-       else if (slave->range.mantissa == 8)
-               reg |= 0x10;
-       else {
-               slave->range.mantissa = 2;
-               reg |= 0x00;
-       }
-       slave->range.fraction = 0;
-
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x14, reg);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-static int bma150_read(void *mlsl_handle,
-                      struct ext_slave_descr *slave,
-                      struct ext_slave_platform_data *pdata,
-                      unsigned char *data)
-{
-       int result;
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               slave->reg, slave->len, data);
-       return result;
-}
-
-static struct ext_slave_descr bma150_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ bma150_suspend,
-       /*.resume           = */ bma150_resume,
-       /*.read             = */ bma150_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "bma150",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_BMA150,
-       /*.reg              = */ 0x02,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
-       /*.range            = */ {2, 0},
-};
-
-struct ext_slave_descr *bma150_get_slave_descr(void)
-{
-       return &bma150_descr;
-}
-EXPORT_SYMBOL(bma150_get_slave_descr);
-
-#ifdef __KERNEL__
-MODULE_AUTHOR("Invensense");
-MODULE_DESCRIPTION("User space IRQ handler for MPU3xxx devices");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("bma");
-#endif
-
-/**
- *  @}
- */
diff --git a/drivers/misc/mpu3050/accel/bma222.c b/drivers/misc/mpu3050/accel/bma222.c
deleted file mode 100755 (executable)
index 534a1e5..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/*
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   bma222.c
- *      @brief  Accelerometer setup and handling methods.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlos.h"
-#include "mlsl.h"
-
-#define ACCEL_BMA222_RANGE_REG          (0x0F)
-#define ACCEL_BMA222_BW_REG             (0x10)
-#define ACCEL_BMA222_SUSPEND_REG        (0x11)
-#define ACCEL_BMA222_SFT_RST_REG        (0x14)
-
-/*********************************************
-    Accelerometer Initialization Functions
-**********************************************/
-
-static int bma222_suspend(void *mlsl_handle,
-                         struct ext_slave_descr *slave,
-                         struct ext_slave_platform_data *pdata)
-{
-       int result;
-
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_BMA222_SUSPEND_REG, 0x80);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-static int bma222_resume(void *mlsl_handle,
-                        struct ext_slave_descr *slave,
-                        struct ext_slave_platform_data *pdata)
-{
-       int result;
-       unsigned char reg = 0;
-
-       /* Soft reset */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_BMA222_SFT_RST_REG, 0xB6);
-       ERROR_CHECK(result);
-       MLOSSleep(10);
-
-       /*Bandwidth */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_BMA222_BW_REG, 0x0C);
-       ERROR_CHECK(result);
-
-       /* Full Scale */
-       if (slave->range.mantissa == 4)
-               reg |= 0x05;
-       else if (slave->range.mantissa == 8)
-               reg |= 0x08;
-       else if (slave->range.mantissa == 16)
-               reg |= 0x0C;
-       else {
-               slave->range.mantissa = 2;
-               reg |= 0x03;
-       }
-       slave->range.fraction = 0;
-
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_BMA222_RANGE_REG, reg);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-static int bma222_read(void *mlsl_handle,
-                      struct ext_slave_descr *slave,
-                      struct ext_slave_platform_data *pdata,
-                      unsigned char *data)
-{
-       int result;
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               slave->reg, slave->len, data);
-       return result;
-}
-
-static struct ext_slave_descr bma222_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ bma222_suspend,
-       /*.resume           = */ bma222_resume,
-       /*.read             = */ bma222_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "bma222",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_BMA222,
-       /*.reg              = */ 0x02,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
-       /*.range            = */ {2, 0},
-};
-
-struct ext_slave_descr *bma222_get_slave_descr(void)
-{
-       return &bma222_descr;
-}
-EXPORT_SYMBOL(bma222_get_slave_descr);
-
-/*
- *  @}
- */
diff --git a/drivers/misc/mpu3050/accel/cma3000.c b/drivers/misc/mpu3050/accel/cma3000.c
deleted file mode 100755 (executable)
index 0592595..0000000
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   cma3000.c
- *      @brief  Accelerometer setup and handling methods for VTI CMA3000
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-#include "accel.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-int cma3000_suspend(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata)
-{
-       int result;
-       /* RAM reset */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x1d, 0xcd);
-       return result;
-}
-
-int cma3000_resume(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-
-
-       return ML_SUCCESS;
-}
-
-int cma3000_read(void *mlsl_handle,
-                struct ext_slave_descr *slave,
-                struct ext_slave_platform_data *pdata,
-                unsigned char *data)
-{
-       int result;
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               slave->reg, slave->len, data);
-       return result;
-}
-
-struct ext_slave_descr cma3000_descr = {
-       /*.suspend          = */ cma3000_suspend,
-       /*.resume           = */ cma3000_resume,
-       /*.read             = */ cma3000_read,
-       /*.name             = */ "cma3000",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ID_INVALID,
-       /* fixme - id to added when support becomes available */
-       /*.reg              = */ 0x06,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
-       /*.range            = */ 65536,
-};
-
-struct ext_slave_descr *cma3000_get_slave_descr(void)
-{
-       return &cma3000_descr;
-}
-EXPORT_SYMBOL(cma3000_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/accel/kxsd9.c b/drivers/misc/mpu3050/accel/kxsd9.c
deleted file mode 100755 (executable)
index 77bc52c..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   kxsd9.c
- *      @brief  Accelerometer setup and handling methods.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/kernel.h>
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-static int kxsd9_suspend(void *mlsl_handle,
-                        struct ext_slave_descr *slave,
-                        struct ext_slave_platform_data *pdata)
-{
-       int result;
-       /* CTRL_REGB: low-power standby mode */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x0d, 0x0);
-       ERROR_CHECK(result);
-       return result;
-}
-
-/* full scale setting - register and mask */
-#define ACCEL_KIONIX_CTRL_REG      (0x0C)
-#define ACCEL_KIONIX_CTRL_MASK     (0x3)
-
-static int kxsd9_resume(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg;
-
-       /* Full Scale */
-       reg = 0x0;
-       reg &= ~ACCEL_KIONIX_CTRL_MASK;
-       reg |= 0x00;
-       if (slave->range.mantissa == 4) {       /* 4g scale = 4.9951 */
-               reg |= 0x2;
-               slave->range.fraction = 9951;
-       } else if (slave->range.mantissa == 7) { /* 6g scale = 7.5018 */
-               reg |= 0x1;
-               slave->range.fraction = 5018;
-       } else if (slave->range.mantissa == 9) {        /* 8g scale = 9.9902 */
-               reg |= 0x0;
-               slave->range.fraction = 9902;
-       } else {
-               slave->range.mantissa = 2; /* 2g scale = 2.5006 */
-               slave->range.fraction = 5006;
-               reg |= 0x3;
-       }
-       reg |= 0xC0;            /* 100Hz LPF */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_KIONIX_CTRL_REG, reg);
-       ERROR_CHECK(result);
-       /* normal operation */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x0d, 0x40);
-       ERROR_CHECK(result);
-
-       return ML_SUCCESS;
-}
-
-static int kxsd9_read(void *mlsl_handle,
-                     struct ext_slave_descr *slave,
-                     struct ext_slave_platform_data *pdata,
-                     unsigned char *data)
-{
-       int result;
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               slave->reg, slave->len, data);
-       return result;
-}
-
-static struct ext_slave_descr kxsd9_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ kxsd9_suspend,
-       /*.resume           = */ kxsd9_resume,
-       /*.read             = */ kxsd9_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "kxsd9",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_KXSD9,
-       /*.reg              = */ 0x00,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
-       /*.range            = */ {2, 5006},
-};
-
-struct ext_slave_descr *kxsd9_get_slave_descr(void)
-{
-       return &kxsd9_descr;
-}
-EXPORT_SYMBOL(kxsd9_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/accel/kxtf9.c b/drivers/misc/mpu3050/accel/kxtf9.c
deleted file mode 100755 (executable)
index e2490af..0000000
+++ /dev/null
@@ -1,665 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   kxtf9.c
- *      @brief  Accelerometer setup and handling methods.
-*/
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#undef MPL_LOG_NDEBUG
-#define MPL_LOG_NDEBUG 1
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-#define KXTF9_XOUT_HPF_L                (0x00) /* 0000 0000 */
-#define KXTF9_XOUT_HPF_H                (0x01) /* 0000 0001 */
-#define KXTF9_YOUT_HPF_L                (0x02) /* 0000 0010 */
-#define KXTF9_YOUT_HPF_H                (0x03) /* 0000 0011 */
-#define KXTF9_ZOUT_HPF_L                (0x04) /* 0001 0100 */
-#define KXTF9_ZOUT_HPF_H                (0x05) /* 0001 0101 */
-#define KXTF9_XOUT_L                    (0x06) /* 0000 0110 */
-#define KXTF9_XOUT_H                    (0x07) /* 0000 0111 */
-#define KXTF9_YOUT_L                    (0x08) /* 0000 1000 */
-#define KXTF9_YOUT_H                    (0x09) /* 0000 1001 */
-#define KXTF9_ZOUT_L                    (0x0A) /* 0001 1010 */
-#define KXTF9_ZOUT_H                    (0x0B) /* 0001 1011 */
-#define KXTF9_ST_RESP                   (0x0C) /* 0000 1100 */
-#define KXTF9_WHO_AM_I                  (0x0F) /* 0000 1111 */
-#define KXTF9_TILT_POS_CUR              (0x10) /* 0001 0000 */
-#define KXTF9_TILT_POS_PRE              (0x11) /* 0001 0001 */
-#define KXTF9_INT_SRC_REG1              (0x15) /* 0001 0101 */
-#define KXTF9_INT_SRC_REG2              (0x16) /* 0001 0110 */
-#define KXTF9_STATUS_REG                (0x18) /* 0001 1000 */
-#define KXTF9_INT_REL                   (0x1A) /* 0001 1010 */
-#define KXTF9_CTRL_REG1                 (0x1B) /* 0001 1011 */
-#define KXTF9_CTRL_REG2                 (0x1C) /* 0001 1100 */
-#define KXTF9_CTRL_REG3                 (0x1D) /* 0001 1101 */
-#define KXTF9_INT_CTRL_REG1             (0x1E) /* 0001 1110 */
-#define KXTF9_INT_CTRL_REG2             (0x1F) /* 0001 1111 */
-#define KXTF9_INT_CTRL_REG3             (0x20) /* 0010 0000 */
-#define KXTF9_DATA_CTRL_REG             (0x21) /* 0010 0001 */
-#define KXTF9_TILT_TIMER                (0x28) /* 0010 1000 */
-#define KXTF9_WUF_TIMER                 (0x29) /* 0010 1001 */
-#define KXTF9_TDT_TIMER                 (0x2B) /* 0010 1011 */
-#define KXTF9_TDT_H_THRESH              (0x2C) /* 0010 1100 */
-#define KXTF9_TDT_L_THRESH              (0x2D) /* 0010 1101 */
-#define KXTF9_TDT_TAP_TIMER             (0x2E) /* 0010 1110 */
-#define KXTF9_TDT_TOTAL_TIMER           (0x2F) /* 0010 1111 */
-#define KXTF9_TDT_LATENCY_TIMER         (0x30) /* 0011 0000 */
-#define KXTF9_TDT_WINDOW_TIMER          (0x31) /* 0011 0001 */
-#define KXTF9_WUF_THRESH                (0x5A) /* 0101 1010 */
-#define KXTF9_TILT_ANGLE                (0x5C) /* 0101 1100 */
-#define KXTF9_HYST_SET                  (0x5F) /* 0101 1111 */
-
-#define KXTF9_MAX_DUR (0xFF)
-#define KXTF9_MAX_THS (0xFF)
-#define KXTF9_THS_COUNTS_P_G (32)
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-struct kxtf9_config {
-       unsigned int odr; /* Output data rate mHz */
-       unsigned int fsr; /* full scale range mg */
-       unsigned int ths; /* Motion no-motion thseshold mg */
-       unsigned int dur; /* Motion no-motion duration ms */
-       unsigned int irq_type;
-       unsigned char reg_ths;
-       unsigned char reg_dur;
-       unsigned char reg_odr;
-       unsigned char reg_int_cfg1;
-       unsigned char reg_int_cfg2;
-       unsigned char ctrl_reg1;
-};
-
-struct kxtf9_private_data {
-       struct kxtf9_config suspend;
-       struct kxtf9_config resume;
-};
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-static int kxtf9_set_ths(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct kxtf9_config *config,
-                       int apply,
-                       long ths)
-{
-       int result = ML_SUCCESS;
-       if ((ths * KXTF9_THS_COUNTS_P_G / 1000) > KXTF9_MAX_THS)
-               ths = (KXTF9_MAX_THS * 1000) / KXTF9_THS_COUNTS_P_G;
-
-       if (ths < 0)
-               ths = 0;
-
-       config->ths = ths;
-       config->reg_ths = (unsigned char)
-               ((long)(ths * KXTF9_THS_COUNTS_P_G) / 1000);
-       MPL_LOGV("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
-       if (apply)
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       KXTF9_WUF_THRESH,
-                                       config->reg_ths);
-       return result;
-}
-
-static int kxtf9_set_dur(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct kxtf9_config *config,
-                       int apply,
-                       long dur)
-{
-       int result = ML_SUCCESS;
-       long reg_dur = (dur * config->odr) / 1000000;
-       config->dur = dur;
-
-       if (reg_dur > KXTF9_MAX_DUR)
-               reg_dur = KXTF9_MAX_DUR;
-
-       config->reg_dur = (unsigned char) reg_dur;
-       MPL_LOGV("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
-       if (apply)
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       KXTF9_WUF_TIMER,
-                                       (unsigned char)reg_dur);
-       return result;
-}
-
-/**
- * Sets the IRQ to fire when one of the IRQ events occur.  Threshold and
- * duration will not be used uless the type is MOT or NMOT.
- *
- * @param config configuration to apply to, suspend or resume
- * @param irq_type The type of IRQ.  Valid values are
- * - MPU_SLAVE_IRQ_TYPE_NONE
- * - MPU_SLAVE_IRQ_TYPE_MOTION
- * - MPU_SLAVE_IRQ_TYPE_DATA_READY
- */
-static int kxtf9_set_irq(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct kxtf9_config *config,
-                       int apply,
-                       long irq_type)
-{
-       int result = ML_SUCCESS;
-       struct kxtf9_private_data *private_data = pdata->private_data;
-
-       config->irq_type = (unsigned char)irq_type;
-       config->ctrl_reg1 &= ~0x22;
-       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
-               config->ctrl_reg1 |= 0x20;
-               config->reg_int_cfg1 = 0x38;
-               config->reg_int_cfg2 = 0x00;
-       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
-               config->ctrl_reg1 |= 0x02;
-               if ((unsigned long) config ==
-                       (unsigned long) &private_data->suspend)
-                       config->reg_int_cfg1 = 0x34;
-               else
-                       config->reg_int_cfg1 = 0x24;
-               config->reg_int_cfg2 = 0xE0;
-       } else {
-               config->reg_int_cfg1 = 0x00;
-               config->reg_int_cfg2 = 0x00;
-       }
-
-       if (apply) {
-               /* Must clear bit 7 before writing new configuration */
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       KXTF9_CTRL_REG1, 0x40);
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       KXTF9_INT_CTRL_REG1,
-                                       config->reg_int_cfg1);
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       KXTF9_INT_CTRL_REG2,
-                                       config->reg_int_cfg2);
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       KXTF9_CTRL_REG1,
-                                       config->ctrl_reg1);
-       }
-       MPL_LOGV("CTRL_REG1: %lx, INT_CFG1: %lx, INT_CFG2: %lx\n",
-               (unsigned long)config->ctrl_reg1,
-               (unsigned long)config->reg_int_cfg1,
-               (unsigned long)config->reg_int_cfg2);
-
-       return result;
-}
-
-/**
- * Set the Output data rate for the particular configuration
- *
- * @param config Config to modify with new ODR
- * @param odr Output data rate in units of 1/1000Hz
- */
-static int kxtf9_set_odr(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct kxtf9_config *config,
-                       int apply,
-                       long odr)
-{
-       unsigned char bits;
-       int result = ML_SUCCESS;
-
-       /* Data sheet says there is 12.5 hz, but that seems to produce a single
-        * correct data value, thus we remove it from the table */
-       if (odr > 400000) {
-               config->odr = 800000;
-               bits = 0x06;
-       } else if (odr > 200000) {
-               config->odr = 400000;
-               bits = 0x05;
-       } else if (odr > 100000) {
-               config->odr = 200000;
-               bits = 0x04;
-       } else if (odr > 50000) {
-               config->odr = 100000;
-               bits = 0x03;
-       } else if (odr > 25000) {
-               config->odr = 50000;
-               bits = 0x02;
-       } else if (odr != 0) {
-               config->odr = 25000;
-               bits = 0x01;
-       } else {
-               config->odr = 0;
-               bits = 0;
-       }
-
-       if (odr != 0)
-               config->ctrl_reg1 |= 0x80;
-
-       config->reg_odr = bits;
-       kxtf9_set_dur(mlsl_handle, pdata,
-               config, apply, config->dur);
-       MPL_LOGV("ODR: %d, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
-       if (apply) {
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       KXTF9_DATA_CTRL_REG,
-                                       config->reg_odr);
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       KXTF9_CTRL_REG1,
-                                       0x40);
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       KXTF9_CTRL_REG1,
-                                       config->ctrl_reg1);
-       }
-       return result;
-}
-
-/**
- * Set the full scale range of the accels
- *
- * @param config pointer to configuration
- * @param fsr requested full scale range
- */
-static int kxtf9_set_fsr(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct kxtf9_config *config,
-                       int apply,
-                       long fsr)
-{
-       int result = ML_SUCCESS;
-
-       config->ctrl_reg1 = (config->ctrl_reg1 & 0xE7);
-       if (fsr <= 2000) {
-               config->fsr = 2000;
-               config->ctrl_reg1 |= 0x00;
-       } else if (fsr <= 4000) {
-               config->fsr = 4000;
-               config->ctrl_reg1 |= 0x08;
-       } else {
-               config->fsr = 8000;
-               config->ctrl_reg1 |= 0x10;
-       }
-
-       MPL_LOGV("FSR: %d\n", config->fsr);
-       if (apply) {
-               /* Must clear bit 7 before writing new configuration */
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       KXTF9_CTRL_REG1, 0x40);
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       KXTF9_CTRL_REG1, config->ctrl_reg1);
-       }
-       return result;
-}
-
-static int kxtf9_suspend(void *mlsl_handle,
-                        struct ext_slave_descr *slave,
-                        struct ext_slave_platform_data *pdata)
-{
-       int result;
-       unsigned char data;
-       struct kxtf9_private_data *private_data = pdata->private_data;
-
-       /* Wake up */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_CTRL_REG1, 0x40);
-       ERROR_CHECK(result);
-       /* INT_CTRL_REG1: */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_INT_CTRL_REG1,
-                               private_data->suspend.reg_int_cfg1);
-       ERROR_CHECK(result);
-       /* WUF_THRESH: */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_WUF_THRESH,
-                               private_data->suspend.reg_ths);
-       ERROR_CHECK(result);
-       /* DATA_CTRL_REG */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_DATA_CTRL_REG,
-                               private_data->suspend.reg_odr);
-       ERROR_CHECK(result);
-       /* WUF_TIMER */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_WUF_TIMER, private_data->suspend.reg_dur);
-       ERROR_CHECK(result);
-
-       /* Normal operation  */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_CTRL_REG1,
-                               private_data->suspend.ctrl_reg1);
-       ERROR_CHECK(result);
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               KXTF9_INT_REL, 1, &data);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-/* full scale setting - register and mask */
-#define ACCEL_KIONIX_CTRL_REG      (0x1b)
-#define ACCEL_KIONIX_CTRL_MASK     (0x18)
-
-static int kxtf9_resume(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char data;
-       struct kxtf9_private_data *private_data = pdata->private_data;
-
-       /* Wake up */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_CTRL_REG1, 0x40);
-       ERROR_CHECK(result);
-       /* INT_CTRL_REG1: */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_INT_CTRL_REG1,
-                               private_data->resume.reg_int_cfg1);
-       ERROR_CHECK(result);
-       /* WUF_THRESH: */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_WUF_THRESH, private_data->resume.reg_ths);
-       ERROR_CHECK(result);
-       /* DATA_CTRL_REG */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_DATA_CTRL_REG,
-                               private_data->resume.reg_odr);
-       ERROR_CHECK(result);
-       /* WUF_TIMER */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_WUF_TIMER, private_data->resume.reg_dur);
-       ERROR_CHECK(result);
-
-       /* Normal operation  */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_CTRL_REG1,
-                               private_data->resume.ctrl_reg1);
-       ERROR_CHECK(result);
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               KXTF9_INT_REL, 1, &data);
-       ERROR_CHECK(result);
-
-       return ML_SUCCESS;
-}
-
-static int kxtf9_init(void *mlsl_handle,
-               struct ext_slave_descr *slave,
-               struct ext_slave_platform_data *pdata)
-{
-
-       struct kxtf9_private_data *private_data;
-       int result = ML_SUCCESS;
-
-       private_data = (struct kxtf9_private_data *)
-               MLOSMalloc(sizeof(struct kxtf9_private_data));
-
-       if (!private_data)
-               return ML_ERROR_MEMORY_EXAUSTED;
-
-       /* RAM reset */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_CTRL_REG1,
-                               0x40); /* Fastest Reset */
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_DATA_CTRL_REG,
-                               0x36); /* Fastest Reset */
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               KXTF9_CTRL_REG3, 0xcd); /* Reset */
-       ERROR_CHECK(result);
-       MLOSSleep(2);
-
-       pdata->private_data = private_data;
-
-       private_data->resume.ctrl_reg1 = 0xC0;
-       private_data->suspend.ctrl_reg1 = 0x40;
-
-       result = kxtf9_set_dur(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 1000);
-       ERROR_CHECK(result);
-       result = kxtf9_set_dur(mlsl_handle, pdata, &private_data->resume,
-                       FALSE,  2540);
-       ERROR_CHECK(result);
-
-       result = kxtf9_set_odr(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 50000);
-       ERROR_CHECK(result);
-       result = kxtf9_set_odr(mlsl_handle, pdata, &private_data->resume,
-                       FALSE, 200000);
-
-       result = kxtf9_set_fsr(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 2000);
-       ERROR_CHECK(result);
-       result = kxtf9_set_fsr(mlsl_handle, pdata, &private_data->resume,
-                       FALSE, 2000);
-       ERROR_CHECK(result);
-
-       result = kxtf9_set_ths(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 80);
-       ERROR_CHECK(result);
-       result = kxtf9_set_ths(mlsl_handle, pdata, &private_data->resume,
-                       FALSE, 40);
-       ERROR_CHECK(result);
-
-       result = kxtf9_set_irq(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE,
-                       MPU_SLAVE_IRQ_TYPE_NONE);
-       ERROR_CHECK(result);
-       result = kxtf9_set_irq(mlsl_handle, pdata, &private_data->resume,
-                       FALSE,
-                       MPU_SLAVE_IRQ_TYPE_NONE);
-       ERROR_CHECK(result);
-       return result;
-}
-
-static int kxtf9_exit(void *mlsl_handle,
-                         struct ext_slave_descr *slave,
-                         struct ext_slave_platform_data *pdata)
-{
-       if (pdata->private_data)
-               return MLOSFree(pdata->private_data);
-       else
-               return ML_SUCCESS;
-}
-
-static int kxtf9_config(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata,
-                       struct ext_slave_config *data)
-{
-       struct kxtf9_private_data *private_data = pdata->private_data;
-       if (!data->data)
-               return ML_ERROR_INVALID_PARAMETER;
-
-       switch (data->key) {
-       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
-               return kxtf9_set_odr(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_ODR_RESUME:
-               return kxtf9_set_odr(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
-               return kxtf9_set_fsr(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_FSR_RESUME:
-               return kxtf9_set_fsr(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_MOT_THS:
-               return kxtf9_set_ths(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_NMOT_THS:
-               return kxtf9_set_ths(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_MOT_DUR:
-               return kxtf9_set_dur(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_NMOT_DUR:
-               return kxtf9_set_dur(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
-               return kxtf9_set_irq(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_IRQ_RESUME:
-               return kxtf9_set_irq(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       default:
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-       };
-
-       return ML_SUCCESS;
-}
-
-static int kxtf9_get_config(void *mlsl_handle,
-                               struct ext_slave_descr *slave,
-                               struct ext_slave_platform_data *pdata,
-                               struct ext_slave_config *data)
-{
-       struct kxtf9_private_data *private_data = pdata->private_data;
-       if (!data->data)
-               return ML_ERROR_INVALID_PARAMETER;
-
-       switch (data->key) {
-       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.odr;
-               break;
-       case MPU_SLAVE_CONFIG_ODR_RESUME:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.odr;
-               break;
-       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.fsr;
-               break;
-       case MPU_SLAVE_CONFIG_FSR_RESUME:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.fsr;
-               break;
-       case MPU_SLAVE_CONFIG_MOT_THS:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.ths;
-               break;
-       case MPU_SLAVE_CONFIG_NMOT_THS:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.ths;
-               break;
-       case MPU_SLAVE_CONFIG_MOT_DUR:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.dur;
-               break;
-       case MPU_SLAVE_CONFIG_NMOT_DUR:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.dur;
-               break;
-       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.irq_type;
-               break;
-       case MPU_SLAVE_CONFIG_IRQ_RESUME:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.irq_type;
-               break;
-       default:
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-       };
-
-       return ML_SUCCESS;
-}
-
-static int kxtf9_read(void *mlsl_handle,
-                     struct ext_slave_descr *slave,
-                     struct ext_slave_platform_data *pdata,
-                     unsigned char *data)
-{
-       int result;
-       unsigned char reg;
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               KXTF9_INT_SRC_REG2, 1, &reg);
-       ERROR_CHECK(result);
-
-       if (!(reg & 0x10))
-               return ML_ERROR_ACCEL_DATA_NOT_READY;
-
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               slave->reg, slave->len, data);
-       ERROR_CHECK(result);
-       return result;
-}
-
-static struct ext_slave_descr kxtf9_descr = {
-       /*.init             = */ kxtf9_init,
-       /*.exit             = */ kxtf9_exit,
-       /*.suspend          = */ kxtf9_suspend,
-       /*.resume           = */ kxtf9_resume,
-       /*.read             = */ kxtf9_read,
-       /*.config           = */ kxtf9_config,
-       /*.get_config       = */ kxtf9_get_config,
-       /*.name             = */ "kxtf9",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_KXTF9,
-       /*.reg              = */ 0x06,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
-       /*.range            = */ {2, 0},
-};
-
-struct ext_slave_descr *kxtf9_get_slave_descr(void)
-{
-       return &kxtf9_descr;
-}
-EXPORT_SYMBOL(kxtf9_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/accel/lis331.c b/drivers/misc/mpu3050/accel/lis331.c
deleted file mode 100755 (executable)
index 53c599b..0000000
+++ /dev/null
@@ -1,617 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   lis331.c
- *      @brief  Accelerometer setup and handling methods for ST LIS331
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#undef MPL_LOG_NDEBUG
-#define MPL_LOG_NDEBUG 1
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-/* full scale setting - register & mask */
-#define LIS331_CTRL_REG1         (0x20)
-#define LIS331_CTRL_REG2         (0x21)
-#define LIS331_CTRL_REG3         (0x22)
-#define LIS331_CTRL_REG4         (0x23)
-#define LIS331_CTRL_REG5         (0x24)
-#define LIS331_HP_FILTER_RESET   (0x25)
-#define LIS331_REFERENCE         (0x26)
-#define LIS331_STATUS_REG        (0x27)
-#define LIS331_OUT_X_L           (0x28)
-#define LIS331_OUT_X_H           (0x29)
-#define LIS331_OUT_Y_L           (0x2a)
-#define LIS331_OUT_Y_H           (0x2b)
-#define LIS331_OUT_Z_L           (0x2b)
-#define LIS331_OUT_Z_H           (0x2d)
-
-#define LIS331_INT1_CFG          (0x30)
-#define LIS331_INT1_SRC          (0x31)
-#define LIS331_INT1_THS          (0x32)
-#define LIS331_INT1_DURATION     (0x33)
-
-#define LIS331_INT2_CFG          (0x34)
-#define LIS331_INT2_SRC          (0x35)
-#define LIS331_INT2_THS          (0x36)
-#define LIS331_INT2_DURATION     (0x37)
-
-#define LIS331_CTRL_MASK         (0x30)
-#define LIS331_SLEEP_MASK        (0x20)
-
-#define LIS331_MAX_DUR (0x7F)
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-struct lis331dlh_config {
-       unsigned int odr;
-       unsigned int fsr; /* full scale range mg */
-       unsigned int ths; /* Motion no-motion thseshold mg */
-       unsigned int dur; /* Motion no-motion duration ms */
-       unsigned char reg_ths;
-       unsigned char reg_dur;
-       unsigned char ctrl_reg1;
-       unsigned char irq_type;
-       unsigned char mot_int1_cfg;
-};
-
-struct lis331dlh_private_data {
-       struct lis331dlh_config suspend;
-       struct lis331dlh_config resume;
-};
-
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-static int lis331dlh_set_ths(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct lis331dlh_config *config,
-                       int apply,
-                       long ths)
-{
-       int result = ML_SUCCESS;
-       if ((unsigned int) ths >= config->fsr)
-               ths = (long) config->fsr - 1;
-
-       if (ths < 0)
-               ths = 0;
-
-       config->ths = ths;
-       config->reg_ths = (unsigned char)(long)((ths * 128L) / (config->fsr));
-       MPL_LOGV("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
-       if (apply)
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS331_INT1_THS,
-                                       config->reg_ths);
-       return result;
-}
-
-static int lis331dlh_set_dur(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct lis331dlh_config *config,
-                       int apply,
-                       long dur)
-{
-       int result = ML_SUCCESS;
-       long reg_dur = (dur * config->odr) / 1000000L;
-       config->dur = dur;
-
-       if (reg_dur > LIS331_MAX_DUR)
-               reg_dur = LIS331_MAX_DUR;
-
-       config->reg_dur = (unsigned char) reg_dur;
-       MPL_LOGV("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
-       if (apply)
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS331_INT1_DURATION,
-                                       (unsigned char)reg_dur);
-       return result;
-}
-
-/**
- * Sets the IRQ to fire when one of the IRQ events occur.  Threshold and
- * duration will not be used uless the type is MOT or NMOT.
- *
- * @param config configuration to apply to, suspend or resume
- * @param irq_type The type of IRQ.  Valid values are
- * - MPU_SLAVE_IRQ_TYPE_NONE
- * - MPU_SLAVE_IRQ_TYPE_MOTION
- * - MPU_SLAVE_IRQ_TYPE_DATA_READY
- */
-static int lis331dlh_set_irq(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct lis331dlh_config *config,
-                       int apply,
-                       long irq_type)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg1;
-       unsigned char reg2;
-
-       config->irq_type = (unsigned char)irq_type;
-       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
-               reg1 = 0x02;
-               reg2 = 0x00;
-       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
-               reg1 = 0x00;
-               reg2 = config->mot_int1_cfg;
-       } else {
-               reg1 = 0x00;
-               reg2 = 0x00;
-       }
-
-       if (apply) {
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS331_CTRL_REG3, reg1);
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS331_INT1_CFG, reg2);
-       }
-
-       return result;
-}
-
-/**
- * Set the Output data rate for the particular configuration
- *
- * @param config Config to modify with new ODR
- * @param odr Output data rate in units of 1/1000Hz
- */
-static int lis331dlh_set_odr(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct lis331dlh_config *config,
-                       int apply,
-                       long odr)
-{
-       unsigned char bits;
-       int result = ML_SUCCESS;
-
-       if (odr > 400000) {
-               config->odr = 1000000;
-               bits = 0x38;
-       } else if (odr > 100000) {
-               config->odr = 400000;
-               bits = 0x30;
-       } else if (odr > 50000) {
-               config->odr = 100000;
-               bits = 0x28;
-       } else if (odr > 10000) {
-               config->odr = 50000;
-               bits = 0x20;
-       } else if (odr > 5000) {
-               config->odr = 10000;
-               bits = 0xC0;
-       } else if (odr > 2000) {
-               config->odr = 5000;
-               bits = 0xB0;
-       } else if (odr > 1000) {
-               config->odr = 2000;
-               bits = 0x80;
-       } else if (odr > 500) {
-               config->odr = 1000;
-               bits = 0x60;
-       } else if (odr > 0) {
-               config->odr = 500;
-               bits = 0x40;
-       } else {
-               config->odr = 0;
-               bits = 0;
-       }
-
-       config->ctrl_reg1 = bits | (config->ctrl_reg1 & 0x7);
-       lis331dlh_set_dur(mlsl_handle, pdata,
-                       config, apply, config->dur);
-       MPL_LOGV("ODR: %d, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
-       if (apply)
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS331_CTRL_REG1,
-                                       config->ctrl_reg1);
-       return result;
-}
-
-/**
- * Set the full scale range of the accels
- *
- * @param config pointer to configuration
- * @param fsr requested full scale range
- */
-static int lis331dlh_set_fsr(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct lis331dlh_config *config,
-                       int apply,
-                       long fsr)
-{
-       unsigned char reg1 = 0x40;
-       int result = ML_SUCCESS;
-
-       if (fsr <= 2048) {
-               config->fsr = 2048;
-       } else if (fsr <= 4096) {
-               reg1 |= 0x30;
-               config->fsr = 4096;
-       } else {
-               reg1 |= 0x10;
-               config->fsr = 8192;
-       }
-
-       lis331dlh_set_ths(mlsl_handle, pdata,
-                       config, apply, config->ths);
-       MPL_LOGV("FSR: %d\n", config->fsr);
-       if (apply)
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS331_CTRL_REG4, reg1);
-
-       return result;
-}
-
-static int lis331dlh_suspend(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg1;
-       unsigned char reg2;
-       struct lis331dlh_private_data *private_data = pdata->private_data;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG1,
-                                      private_data->suspend.ctrl_reg1);
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG2, 0x0f);
-       reg1 = 0x40;
-       if (private_data->suspend.fsr == 8192)
-               reg1 |= 0x30;
-       else if (private_data->suspend.fsr == 4096)
-               reg1 |= 0x10;
-       /* else bits [4..5] are already zero */
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG4, reg1);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_INT1_THS,
-                                      private_data->suspend.reg_ths);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_INT1_DURATION,
-                                      private_data->suspend.reg_dur);
-
-       if (private_data->suspend.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
-               reg1 = 0x02;
-               reg2 = 0x00;
-       } else if (private_data->suspend.irq_type ==
-                  MPU_SLAVE_IRQ_TYPE_MOTION) {
-               reg1 = 0x00;
-               reg2 = private_data->suspend.mot_int1_cfg;
-       } else {
-               reg1 = 0x00;
-               reg2 = 0x00;
-       }
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG3, reg1);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_INT1_CFG, reg2);
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               LIS331_HP_FILTER_RESET, 1, &reg1);
-       return result;
-}
-
-static int lis331dlh_resume(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg1;
-       unsigned char reg2;
-       struct lis331dlh_private_data *private_data = pdata->private_data;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG1,
-                                      private_data->resume.ctrl_reg1);
-       ERROR_CHECK(result);
-       MLOSSleep(6);
-
-       /* Full Scale */
-       reg1 = 0x40;
-       if (private_data->resume.fsr == 8192)
-               reg1 |= 0x30;
-       else if (private_data->resume.fsr == 4096)
-               reg1 |= 0x10;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG4, reg1);
-       ERROR_CHECK(result);
-
-       /* Configure high pass filter */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG2, 0x0F);
-       ERROR_CHECK(result);
-
-       if (private_data->resume.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
-               reg1 = 0x02;
-               reg2 = 0x00;
-       } else if (private_data->resume.irq_type ==
-                  MPU_SLAVE_IRQ_TYPE_MOTION) {
-               reg1 = 0x00;
-               reg2 = private_data->resume.mot_int1_cfg;
-       } else {
-               reg1 = 0x00;
-               reg2 = 0x00;
-       }
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_CTRL_REG3, reg1);
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_INT1_THS,
-                                      private_data->resume.reg_ths);
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_INT1_DURATION,
-                                      private_data->resume.reg_dur);
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS331_INT1_CFG, reg2);
-       ERROR_CHECK(result);
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               LIS331_HP_FILTER_RESET, 1, &reg1);
-       ERROR_CHECK(result);
-       return result;
-}
-
-static int lis331dlh_read(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata,
-                       unsigned char *data)
-{
-       int result = ML_SUCCESS;
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               LIS331_STATUS_REG, 1, data);
-       if (data[0] & 0x0F) {
-               result = MLSLSerialRead(mlsl_handle, pdata->address,
-                                       slave->reg, slave->len, data);
-               return result;
-       } else
-               return ML_ERROR_ACCEL_DATA_NOT_READY;
-}
-
-static int lis331dlh_init(void *mlsl_handle,
-                         struct ext_slave_descr *slave,
-                         struct ext_slave_platform_data *pdata)
-{
-       struct lis331dlh_private_data *private_data;
-       private_data = (struct lis331dlh_private_data *)
-               MLOSMalloc(sizeof(struct lis331dlh_private_data));
-
-       if (!private_data)
-               return ML_ERROR_MEMORY_EXAUSTED;
-
-       pdata->private_data = private_data;
-
-       private_data->resume.ctrl_reg1 = 0x37;
-       private_data->suspend.ctrl_reg1 = 0x47;
-       private_data->resume.mot_int1_cfg = 0x95;
-       private_data->suspend.mot_int1_cfg = 0x2a;
-
-       lis331dlh_set_odr(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 0);
-       lis331dlh_set_odr(mlsl_handle, pdata, &private_data->resume,
-                       FALSE, 200000);
-       lis331dlh_set_fsr(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 2048);
-       lis331dlh_set_fsr(mlsl_handle, pdata, &private_data->resume,
-                       FALSE, 2048);
-       lis331dlh_set_ths(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 80);
-       lis331dlh_set_ths(mlsl_handle, pdata, &private_data->resume,
-                       FALSE, 40);
-       lis331dlh_set_dur(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 1000);
-       lis331dlh_set_dur(mlsl_handle, pdata, &private_data->resume,
-                       FALSE,  2540);
-       lis331dlh_set_irq(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE,
-                       MPU_SLAVE_IRQ_TYPE_NONE);
-       lis331dlh_set_irq(mlsl_handle, pdata, &private_data->resume,
-                       FALSE,
-                       MPU_SLAVE_IRQ_TYPE_NONE);
-       return ML_SUCCESS;
-}
-
-static int lis331dlh_exit(void *mlsl_handle,
-                         struct ext_slave_descr *slave,
-                         struct ext_slave_platform_data *pdata)
-{
-       if (pdata->private_data)
-               return MLOSFree(pdata->private_data);
-       else
-               return ML_SUCCESS;
-}
-
-static int lis331dlh_config(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata,
-                       struct ext_slave_config *data)
-{
-       struct lis331dlh_private_data *private_data = pdata->private_data;
-       if (!data->data)
-               return ML_ERROR_INVALID_PARAMETER;
-
-       switch (data->key) {
-       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
-               return lis331dlh_set_odr(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_ODR_RESUME:
-               return lis331dlh_set_odr(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
-               return lis331dlh_set_fsr(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_FSR_RESUME:
-               return lis331dlh_set_fsr(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_MOT_THS:
-               return lis331dlh_set_ths(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_NMOT_THS:
-               return lis331dlh_set_ths(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_MOT_DUR:
-               return lis331dlh_set_dur(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_NMOT_DUR:
-               return lis331dlh_set_dur(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
-               return lis331dlh_set_irq(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_IRQ_RESUME:
-               return lis331dlh_set_irq(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       default:
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-       };
-
-       return ML_SUCCESS;
-}
-
-static int lis331dlh_get_config(void *mlsl_handle,
-                               struct ext_slave_descr *slave,
-                               struct ext_slave_platform_data *pdata,
-                               struct ext_slave_config *data)
-{
-       struct lis331dlh_private_data *private_data = pdata->private_data;
-       if (!data->data)
-               return ML_ERROR_INVALID_PARAMETER;
-
-       switch (data->key) {
-       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.odr;
-               break;
-       case MPU_SLAVE_CONFIG_ODR_RESUME:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.odr;
-               break;
-       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.fsr;
-               break;
-       case MPU_SLAVE_CONFIG_FSR_RESUME:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.fsr;
-               break;
-       case MPU_SLAVE_CONFIG_MOT_THS:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.ths;
-               break;
-       case MPU_SLAVE_CONFIG_NMOT_THS:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.ths;
-               break;
-       case MPU_SLAVE_CONFIG_MOT_DUR:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.dur;
-               break;
-       case MPU_SLAVE_CONFIG_NMOT_DUR:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.dur;
-               break;
-       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.irq_type;
-               break;
-       case MPU_SLAVE_CONFIG_IRQ_RESUME:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.irq_type;
-               break;
-       default:
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-       };
-
-       return ML_SUCCESS;
-}
-
-static struct ext_slave_descr lis331dlh_descr = {
-       /*.init             = */ lis331dlh_init,
-       /*.exit             = */ lis331dlh_exit,
-       /*.suspend          = */ lis331dlh_suspend,
-       /*.resume           = */ lis331dlh_resume,
-       /*.read             = */ lis331dlh_read,
-       /*.config           = */ lis331dlh_config,
-       /*.get_config       = */ lis331dlh_get_config,
-       /*.name             = */ "lis331dlh",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_LIS331,
-       /*.reg              = */ (0x28 | 0x80), /* 0x80 for burst reads */
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
-       /*.range            = */ {2, 480},
-};
-
-struct ext_slave_descr *lis331dlh_get_slave_descr(void)
-{
-       return &lis331dlh_descr;
-}
-EXPORT_SYMBOL(lis331dlh_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/accel/lis3dh.c b/drivers/misc/mpu3050/accel/lis3dh.c
deleted file mode 100755 (executable)
index ee5e353..0000000
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   lis3dh.c
- *      @brief  Accelerometer setup and handling methods for ST LIS3DH
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#undef MPL_LOG_NDEBUG
-#define MPL_LOG_NDEBUG 0
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-/* full scale setting - register & mask */
-#define LIS3DH_CTRL_REG1         (0x20)
-#define LIS3DH_CTRL_REG2         (0x21)
-#define LIS3DH_CTRL_REG3         (0x22)
-#define LIS3DH_CTRL_REG4         (0x23)
-#define LIS3DH_CTRL_REG5         (0x24)
-#define LIS3DH_CTRL_REG6         (0x25)
-#define LIS3DH_REFERENCE         (0x26)
-#define LIS3DH_STATUS_REG        (0x27)
-#define LIS3DH_OUT_X_L           (0x28)
-#define LIS3DH_OUT_X_H           (0x29)
-#define LIS3DH_OUT_Y_L           (0x2a)
-#define LIS3DH_OUT_Y_H           (0x2b)
-#define LIS3DH_OUT_Z_L           (0x2b)
-#define LIS3DH_OUT_Z_H           (0x2d)
-
-#define LIS3DH_INT1_CFG          (0x30)
-#define LIS3DH_INT1_SRC          (0x31)
-#define LIS3DH_INT1_THS          (0x32)
-#define LIS3DH_INT1_DURATION     (0x33)
-
-#define LIS3DH_MAX_DUR (0x7F)
-
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-struct lis3dh_config {
-       unsigned int odr;
-       unsigned int fsr; /* full scale range mg */
-       unsigned int ths; /* Motion no-motion thseshold mg */
-       unsigned int dur; /* Motion no-motion duration ms */
-       unsigned char reg_ths;
-       unsigned char reg_dur;
-       unsigned char ctrl_reg1;
-       unsigned char irq_type;
-       unsigned char mot_int1_cfg;
-};
-
-struct lis3dh_private_data {
-       struct lis3dh_config suspend;
-       struct lis3dh_config resume;
-};
-
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-static int lis3dh_set_ths(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct lis3dh_config *config,
-                       int apply,
-                       long ths)
-{
-       int result = ML_SUCCESS;
-       if ((unsigned int) ths > 1000 * config->fsr)
-               ths = (long) 1000 * config->fsr;
-
-       if (ths < 0)
-               ths = 0;
-
-       config->ths = ths;
-       config->reg_ths = (unsigned char)(long)((ths * 128L) / (config->fsr));
-       MPL_LOGV("THS: %d, 0x%02x\n", config->ths, (int)config->reg_ths);
-       if (apply)
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS3DH_INT1_THS,
-                                       config->reg_ths);
-       return result;
-}
-
-static int lis3dh_set_dur(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct lis3dh_config *config,
-                       int apply,
-                       long dur)
-{
-       int result = ML_SUCCESS;
-       long reg_dur = (dur * config->odr) / 1000000L;
-       config->dur = dur;
-
-       if (reg_dur > LIS3DH_MAX_DUR)
-               reg_dur = LIS3DH_MAX_DUR;
-
-       config->reg_dur = (unsigned char) reg_dur;
-       MPL_LOGV("DUR: %d, 0x%02x\n", config->dur, (int)config->reg_dur);
-       if (apply)
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS3DH_INT1_DURATION,
-                                       (unsigned char)reg_dur);
-       return result;
-}
-
-/**
- * Sets the IRQ to fire when one of the IRQ events occur.  Threshold and
- * duration will not be used uless the type is MOT or NMOT.
- *
- * @param config configuration to apply to, suspend or resume
- * @param irq_type The type of IRQ.  Valid values are
- * - MPU_SLAVE_IRQ_TYPE_NONE
- * - MPU_SLAVE_IRQ_TYPE_MOTION
- * - MPU_SLAVE_IRQ_TYPE_DATA_READY
- */
-static int lis3dh_set_irq(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct lis3dh_config *config,
-                       int apply,
-                       long irq_type)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg1;
-       unsigned char reg2;
-
-       config->irq_type = (unsigned char)irq_type;
-       if (irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
-               reg1 = 0x10;
-               reg2 = 0x00;
-       } else if (irq_type == MPU_SLAVE_IRQ_TYPE_MOTION) {
-               reg1 = 0x40;
-               reg2 = config->mot_int1_cfg;
-       } else {
-               reg1 = 0x00;
-               reg2 = 0x00;
-       }
-
-       if (apply) {
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS3DH_CTRL_REG3, reg1);
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS3DH_INT1_CFG, reg2);
-       }
-
-       return result;
-}
-
-/**
- * Set the Output data rate for the particular configuration
- *
- * @param config Config to modify with new ODR
- * @param odr Output data rate in units of 1/1000Hz
- */
-static int lis3dh_set_odr(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct lis3dh_config *config,
-                       int apply,
-                       long odr)
-{
-       unsigned char bits;
-       int result = ML_SUCCESS;
-
-       if (odr > 400000) {
-               config->odr = 1250000;
-               bits = 0x90;
-       } else if (odr > 200000) {
-               config->odr = 400000;
-               bits = 0x70;
-       } else if (odr > 100000) {
-               config->odr = 200000;
-               bits = 0x60;
-       } else if (odr > 50000) {
-               config->odr = 100000;
-               bits = 0x50;
-       } else if (odr > 25000) {
-               config->odr = 50000;
-               bits = 0x40;
-       } else if (odr > 10000) {
-               config->odr = 25000;
-               bits = 0x30;
-       } else if (odr > 1000) {
-               config->odr = 10000;
-               bits = 0x20;
-       } else if (odr > 500) {
-               config->odr = 1000;
-               bits = 0x10;
-       } else {
-               config->odr = 0;
-               bits = 0;
-       }
-
-       config->ctrl_reg1 = bits | (config->ctrl_reg1 & 0xf);
-       lis3dh_set_dur(mlsl_handle, pdata,
-                       config, apply, config->dur);
-       MPL_LOGV("ODR: %d, 0x%02x\n", config->odr, (int)config->ctrl_reg1);
-       if (apply)
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS3DH_CTRL_REG1,
-                                       config->ctrl_reg1);
-       return result;
-}
-
-/**
- * Set the full scale range of the accels
- *
- * @param config pointer to configuration
- * @param fsr requested full scale range
- */
-static int lis3dh_set_fsr(void *mlsl_handle,
-                       struct ext_slave_platform_data *pdata,
-                       struct lis3dh_config *config,
-                       int apply,
-                       long fsr)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg1 = 0x48;
-
-       if (fsr <= 2048) {
-               config->fsr = 2048;
-       } else if (fsr <= 4096) {
-               reg1 |= 0x10;
-               config->fsr = 4096;
-       } else if (fsr <= 8192) {
-               reg1 |= 0x20;
-               config->fsr = 8192;
-       } else {
-               reg1 |= 0x30;
-               config->fsr = 16348;
-       }
-
-       lis3dh_set_ths(mlsl_handle, pdata,
-                       config, apply, config->ths);
-       MPL_LOGV("FSR: %d\n", config->fsr);
-       if (apply)
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                       LIS3DH_CTRL_REG4, reg1);
-
-       return result;
-}
-
-static int lis3dh_suspend(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg1;
-       unsigned char reg2;
-       struct lis3dh_private_data *private_data = pdata->private_data;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_CTRL_REG1,
-                                      private_data->suspend.ctrl_reg1);
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_CTRL_REG2, 0x31);
-       reg1 = 0x48;
-       if (private_data->suspend.fsr == 16384)
-               reg1 |= 0x30;
-       else if (private_data->suspend.fsr == 8192)
-               reg1 |= 0x20;
-       else if (private_data->suspend.fsr == 4096)
-               reg1 |= 0x10;
-       else if (private_data->suspend.fsr == 2048)
-               reg1 |= 0x00;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_CTRL_REG4, reg1);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_INT1_THS,
-                                      private_data->suspend.reg_ths);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_INT1_DURATION,
-                                      private_data->suspend.reg_dur);
-
-       if (private_data->suspend.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
-               reg1 = 0x10;
-               reg2 = 0x00;
-       } else if (private_data->suspend.irq_type ==
-                  MPU_SLAVE_IRQ_TYPE_MOTION) {
-               reg1 = 0x40;
-               reg2 = private_data->suspend.mot_int1_cfg;
-       } else {
-               reg1 = 0x00;
-               reg2 = 0x00;
-       }
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_CTRL_REG3, reg1);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_INT1_CFG, reg2);
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               LIS3DH_CTRL_REG6, 1, &reg1);
-
-       return result;
-}
-
-static int lis3dh_resume(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata)
-{
-       tMLError result;
-       unsigned char reg1;
-       unsigned char reg2;
-       struct lis3dh_private_data *private_data = pdata->private_data;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_CTRL_REG1,
-                                      private_data->resume.ctrl_reg1);
-       ERROR_CHECK(result);
-       MLOSSleep(6);
-
-       /* Full Scale */
-       reg1 = 0x48;
-       if (private_data->suspend.fsr == 16384)
-               reg1 |= 0x30;
-       else if (private_data->suspend.fsr == 8192)
-               reg1 |= 0x20;
-       else if (private_data->suspend.fsr == 4096)
-               reg1 |= 0x10;
-       else if (private_data->suspend.fsr == 2048)
-               reg1 |= 0x00;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_CTRL_REG4, reg1);
-       ERROR_CHECK(result);
-
-       /* Configure high pass filter */
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_CTRL_REG2, 0x31);
-       ERROR_CHECK(result);
-
-       if (private_data->resume.irq_type == MPU_SLAVE_IRQ_TYPE_DATA_READY) {
-               reg1 = 0x10;
-               reg2 = 0x00;
-       } else if (private_data->resume.irq_type ==
-                  MPU_SLAVE_IRQ_TYPE_MOTION) {
-               reg1 = 0x40;
-               reg2 = private_data->resume.mot_int1_cfg;
-       } else {
-               reg1 = 0x00;
-               reg2 = 0x00;
-       }
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_CTRL_REG3, reg1);
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_INT1_THS,
-                                      private_data->resume.reg_ths);
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_INT1_DURATION,
-                                      private_data->resume.reg_dur);
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_INT1_CFG, reg2);
-       ERROR_CHECK(result);
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               LIS3DH_CTRL_REG6, 1, &reg1);
-       ERROR_CHECK(result);
-       return result;
-}
-
-static int lis3dh_read(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata,
-                       unsigned char *data)
-{
-       int result = ML_SUCCESS;
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               LIS3DH_STATUS_REG, 1, data);
-       if (data[0] & 0x0F) {
-               result = MLSLSerialRead(mlsl_handle, pdata->address,
-                                       slave->reg, slave->len, data);
-               return result;
-       } else
-               return ML_ERROR_ACCEL_DATA_NOT_READY;
-}
-
-static int lis3dh_init(void *mlsl_handle,
-                         struct ext_slave_descr *slave,
-                         struct ext_slave_platform_data *pdata)
-{
-       tMLError result;
-
-       struct lis3dh_private_data *private_data;
-       private_data = (struct lis3dh_private_data *)
-               MLOSMalloc(sizeof(struct lis3dh_private_data));
-
-       if (!private_data)
-               return ML_ERROR_MEMORY_EXAUSTED;
-
-       pdata->private_data = private_data;
-
-       private_data->resume.ctrl_reg1 = 0x67;
-       private_data->suspend.ctrl_reg1 = 0x18;
-       private_data->resume.mot_int1_cfg = 0x95;
-       private_data->suspend.mot_int1_cfg = 0x2a;
-
-       lis3dh_set_odr(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 0);
-       lis3dh_set_odr(mlsl_handle, pdata, &private_data->resume,
-                       FALSE, 200000);
-       lis3dh_set_fsr(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 2048);
-       lis3dh_set_fsr(mlsl_handle, pdata, &private_data->resume,
-                       FALSE, 2048);
-       lis3dh_set_ths(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 80);
-       lis3dh_set_ths(mlsl_handle, pdata, &private_data->resume,
-                       FALSE, 40);
-       lis3dh_set_dur(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE, 1000);
-       lis3dh_set_dur(mlsl_handle, pdata, &private_data->resume,
-                       FALSE,  2540);
-       lis3dh_set_irq(mlsl_handle, pdata, &private_data->suspend,
-                       FALSE,
-                       MPU_SLAVE_IRQ_TYPE_NONE);
-       lis3dh_set_irq(mlsl_handle, pdata, &private_data->resume,
-                       FALSE,
-                       MPU_SLAVE_IRQ_TYPE_NONE);
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      LIS3DH_CTRL_REG1, 0x07);
-       MLOSSleep(6);
-
-       return ML_SUCCESS;
-}
-
-static int lis3dh_exit(void *mlsl_handle,
-                         struct ext_slave_descr *slave,
-                         struct ext_slave_platform_data *pdata)
-{
-       if (pdata->private_data)
-               return MLOSFree(pdata->private_data);
-       else
-               return ML_SUCCESS;
-}
-
-static int lis3dh_config(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata,
-                       struct ext_slave_config *data)
-{
-       struct lis3dh_private_data *private_data = pdata->private_data;
-       if (!data->data)
-               return ML_ERROR_INVALID_PARAMETER;
-
-       switch (data->key) {
-       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
-               return lis3dh_set_odr(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_ODR_RESUME:
-               return lis3dh_set_odr(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
-               return lis3dh_set_fsr(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_FSR_RESUME:
-               return lis3dh_set_fsr(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_MOT_THS:
-               return lis3dh_set_ths(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_NMOT_THS:
-               return lis3dh_set_ths(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_MOT_DUR:
-               return lis3dh_set_dur(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_NMOT_DUR:
-               return lis3dh_set_dur(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
-               return lis3dh_set_irq(mlsl_handle, pdata,
-                                       &private_data->suspend,
-                                       data->apply,
-                                       *((long *)data->data));
-       case MPU_SLAVE_CONFIG_IRQ_RESUME:
-               return lis3dh_set_irq(mlsl_handle, pdata,
-                                       &private_data->resume,
-                                       data->apply,
-                                       *((long *)data->data));
-       default:
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-       };
-       return ML_SUCCESS;
-}
-
-static int lis3dh_get_config(void *mlsl_handle,
-                               struct ext_slave_descr *slave,
-                               struct ext_slave_platform_data *pdata,
-                               struct ext_slave_config *data)
-{
-       struct lis3dh_private_data *private_data = pdata->private_data;
-       if (!data->data)
-               return ML_ERROR_INVALID_PARAMETER;
-
-       switch (data->key) {
-       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.odr;
-               break;
-       case MPU_SLAVE_CONFIG_ODR_RESUME:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.odr;
-               break;
-       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.fsr;
-               break;
-       case MPU_SLAVE_CONFIG_FSR_RESUME:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.fsr;
-               break;
-       case MPU_SLAVE_CONFIG_MOT_THS:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.ths;
-               break;
-       case MPU_SLAVE_CONFIG_NMOT_THS:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.ths;
-               break;
-       case MPU_SLAVE_CONFIG_MOT_DUR:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.dur;
-               break;
-       case MPU_SLAVE_CONFIG_NMOT_DUR:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.dur;
-               break;
-       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->suspend.irq_type;
-               break;
-       case MPU_SLAVE_CONFIG_IRQ_RESUME:
-               (*(unsigned long *)data->data) =
-                       (unsigned long) private_data->resume.irq_type;
-               break;
-       default:
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-       };
-
-       return ML_SUCCESS;
-}
-
-static struct ext_slave_descr lis3dh_descr = {
-       /*.init             = */ lis3dh_init,
-       /*.exit             = */ lis3dh_exit,
-       /*.suspend          = */ lis3dh_suspend,
-       /*.resume           = */ lis3dh_resume,
-       /*.read             = */ lis3dh_read,
-       /*.config           = */ lis3dh_config,
-       /*.get_config       = */ lis3dh_get_config,
-       /*.name             = */ "lis3dh",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_LIS3DH,
-       /*.reg              = */ 0x28 | 0x80, /* 0x80 for burst reads */
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
-       /*.range            = */ {2, 480},
-};
-
-struct ext_slave_descr *lis3dh_get_slave_descr(void)
-{
-       return &lis3dh_descr;
-}
-EXPORT_SYMBOL(lis3dh_get_slave_descr);
-
-/*
- *  @}
-*/
diff --git a/drivers/misc/mpu3050/accel/lsm303a.c b/drivers/misc/mpu3050/accel/lsm303a.c
deleted file mode 100755 (executable)
index b849496..0000000
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   lsm303a.c
- *      @brief  Accelerometer setup and handling methods for ST LSM303
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-#define ACCEL_ST_SLEEP_REG          (0x20)
-#define ACCEL_ST_SLEEP_MASK         (0x20)
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-int lsm303dlha_suspend(void *mlsl_handle,
-                      struct ext_slave_descr *slave,
-                      struct ext_slave_platform_data *pdata)
-{
-       int result;
-       unsigned char reg;
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, ACCEL_ST_SLEEP_REG,
-                          1, &reg);
-       ERROR_CHECK(result);
-       reg &= ~(0x27);
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_ST_SLEEP_REG, reg);
-       ERROR_CHECK(result);
-       return result;
-}
-
-/* full scale setting - register & mask */
-#define ACCEL_ST_CTRL_REG          (0x23)
-#define ACCEL_ST_CTRL_MASK         (0x30)
-
-int lsm303dlha_resume(void *mlsl_handle,
-                     struct ext_slave_descr *slave,
-                     struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg;
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, ACCEL_ST_SLEEP_REG,
-                          1, &reg);
-       ERROR_CHECK(result);
-       reg |= 0x27;
-       /*wake up if sleeping */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_ST_SLEEP_REG, reg);
-       ERROR_CHECK(result);
-
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x20, 0x37);
-       ERROR_CHECK(result);
-       MLOSSleep(500);
-
-       reg = 0x40;
-
-       /* Full Scale */
-       reg &= ~ACCEL_ST_CTRL_MASK;
-       if (slave->range.mantissa == 4) {
-               slave->range.fraction = 960;
-               reg |= 0x10;
-       } else if (slave->range.mantissa == 8) {
-               slave->range.fraction = 1920;
-               reg |= 0x30;
-       } else {
-               slave->range.mantissa = 2;
-               slave->range.fraction = 480;
-               reg |= 0x00;
-       }
-
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x23, reg);
-       ERROR_CHECK(result);
-
-       /* Configure high pass filter */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x21, 0x0F);
-       ERROR_CHECK(result);
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x32, 0x00);
-       ERROR_CHECK(result);
-       /* Configure INT1_DURATION */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x33, 0x7F);
-       ERROR_CHECK(result);
-       /* Configure INT1_CFG */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x30, 0x95);
-       ERROR_CHECK(result);
-       MLOSSleep(50);
-       return result;
-}
-
-int lsm303dlha_read(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata,
-                   unsigned char *data)
-{
-       int result;
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               slave->reg, slave->len, data);
-       return result;
-}
-
-struct ext_slave_descr lsm303dlha_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ lsm303dlha_suspend,
-       /*.resume           = */ lsm303dlha_resume,
-       /*.read             = */ lsm303dlha_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "lsm303dlha",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_LSM303,
-       /*.reg              = */ (0x28 | 0x80), /* 0x80 for burst reads */
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
-       /*.range            = */ {2, 480},
-};
-
-struct ext_slave_descr *lsm303dlha_get_slave_descr(void)
-{
-       return &lsm303dlha_descr;
-}
-EXPORT_SYMBOL(lsm303dlha_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/accel/mantis.c b/drivers/misc/mpu3050/accel/mantis.c
deleted file mode 100755 (executable)
index 1cb9847..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   lis331.c
- *      @brief  Accelerometer setup and handling methods for Invensense MANTIS
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-struct mantis_config {
-       unsigned int odr; /* output data rate 1/1000 Hz*/
-       unsigned int fsr; /* full scale range mg */
-       unsigned int ths; /* Motion no-motion thseshold mg */
-       unsigned int dur; /* Motion no-motion duration ms */
-};
-
-struct mantis_private_data {
-       struct mantis_config suspend;
-       struct mantis_config resume;
-};
-
-
-/*****************************************
- *Accelerometer Initialization Functions
- *****************************************/
-/**
- * Record the odr for use in computing duration values.
- *
- * @param config Config to set, suspend or resume structure
- * @param odr output data rate in 1/1000 hz
- */
-void mantis_set_odr(struct mantis_config *config,
-               long odr)
-{
-       config->odr = odr;
-}
-
-void mantis_set_ths(struct mantis_config *config,
-               long ths)
-{
-       if (ths < 0)
-               ths = 0;
-
-       config->ths = ths;
-       MPL_LOGV("THS: %d\n", config->ths);
-}
-
-void mantis_set_dur(struct mantis_config *config,
-               long dur)
-{
-       if (dur < 0)
-               dur = 0;
-
-       config->dur = dur;
-       MPL_LOGV("DUR: %d\n", config->dur);
-}
-
-static void mantis_set_fsr(
-       struct mantis_config *config,
-       long fsr)
-{
-       if (fsr <= 2000)
-               config->fsr = 2000;
-       else if (fsr <= 4000)
-               config->fsr = 4000;
-       else
-               config->fsr = 8000;
-
-       MPL_LOGV("FSR: %d\n", config->fsr);
-}
-
-static int mantis_init(void *mlsl_handle,
-                      struct ext_slave_descr *slave,
-                      struct ext_slave_platform_data *pdata)
-{
-       struct mantis_private_data *private_data;
-       private_data = (struct mantis_private_data *)
-               MLOSMalloc(sizeof(struct mantis_private_data));
-
-       if (!private_data)
-               return ML_ERROR_MEMORY_EXAUSTED;
-
-       pdata->private_data = private_data;
-
-       mantis_set_odr(&private_data->suspend, 0);
-       mantis_set_odr(&private_data->resume, 200000);
-       mantis_set_fsr(&private_data->suspend, 2000);
-       mantis_set_fsr(&private_data->resume, 2000);
-       mantis_set_ths(&private_data->suspend, 80);
-       mantis_set_ths(&private_data->resume, 40);
-       mantis_set_dur(&private_data->suspend, 1000);
-       mantis_set_dur(&private_data->resume,  2540);
-       return ML_SUCCESS;
-}
-
-static int mantis_exit(void *mlsl_handle,
-                         struct ext_slave_descr *slave,
-                         struct ext_slave_platform_data *pdata)
-{
-       if (pdata->private_data)
-               return MLOSFree(pdata->private_data);
-       else
-               return ML_SUCCESS;
-}
-
-int mantis_suspend(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       unsigned char reg;
-       int result;
-
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               MPUREG_PWR_MGMT_2, 1, &reg);
-       ERROR_CHECK(result);
-       reg |= (BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA);
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               MPUREG_PWR_MGMT_2, reg);
-       ERROR_CHECK(result);
-
-       return ML_SUCCESS;
-}
-
-int mantis_resume(void *mlsl_handle,
-                 struct ext_slave_descr *slave,
-                 struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg;
-       struct mantis_private_data *private_data;
-
-       private_data = (struct mantis_private_data *) pdata->private_data;
-
-       MLSLSerialRead(mlsl_handle, pdata->address,
-               MPUREG_PWR_MGMT_2, 1, &reg);
-
-       reg &= ~(BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA);
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               MPUREG_PWR_MGMT_2, reg);
-       ERROR_CHECK(result);
-
-       if (slave->range.mantissa == 2)
-               reg = 0;
-       else if (slave->range.mantissa == 4)
-               reg = 1 << 3;
-       else if (slave->range.mantissa == 8)
-               reg = 2 << 3;
-       else if (slave->range.mantissa == 16)
-               reg = 3 << 3;
-       else
-               return ML_ERROR;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                      MPUREG_ACCEL_CONFIG, reg);
-       ERROR_CHECK(result);
-
-       reg = (unsigned char) private_data->suspend.ths / ACCEL_MOT_THR_LSB;
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               MPUREG_ACCEL_MOT_THR, reg);
-       ERROR_CHECK(result);
-
-       reg = (unsigned char)
-               ACCEL_ZRMOT_THR_LSB_CONVERSION(private_data->resume.ths);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               MPUREG_ACCEL_ZRMOT_THR, reg);
-       ERROR_CHECK(result);
-
-       reg = (unsigned char) private_data->suspend.ths / ACCEL_MOT_DUR_LSB;
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               MPUREG_ACCEL_MOT_DUR, reg);
-       ERROR_CHECK(result);
-
-       reg = (unsigned char) private_data->resume.ths / ACCEL_ZRMOT_DUR_LSB;
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               MPUREG_ACCEL_ZRMOT_DUR, reg);
-       ERROR_CHECK(result);
-       return result;
-}
-
-int mantis_read(void *mlsl_handle,
-               struct ext_slave_descr *slave,
-               struct ext_slave_platform_data *pdata, unsigned char *data)
-{
-       int result;
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               slave->reg, slave->len, data);
-       return result;
-}
-
-static int mantis_config(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata,
-                       struct ext_slave_config *data)
-{
-       struct mantis_private_data *private_data = pdata->private_data;
-       if (!data->data)
-               return ML_ERROR_INVALID_PARAMETER;
-
-       switch (data->key) {
-       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
-               mantis_set_odr(&private_data->suspend,
-                               *((long *)data->data));
-               break;
-       case MPU_SLAVE_CONFIG_ODR_RESUME:
-               mantis_set_odr(&private_data->resume,
-                               *((long *)data->data));
-               break;
-       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
-               mantis_set_fsr(&private_data->suspend,
-                               *((long *)data->data));
-               break;
-       case MPU_SLAVE_CONFIG_FSR_RESUME:
-               mantis_set_fsr(&private_data->resume,
-                               *((long *)data->data));
-               break;
-       case MPU_SLAVE_CONFIG_MOT_THS:
-               mantis_set_ths(&private_data->suspend,
-                              (*((long *)data->data)));
-               break;
-       case MPU_SLAVE_CONFIG_NMOT_THS:
-               mantis_set_ths(&private_data->resume,
-                              (*((long *)data->data)));
-               break;
-       case MPU_SLAVE_CONFIG_MOT_DUR:
-               mantis_set_dur(&private_data->suspend,
-                              (*((long *)data->data)));
-               break;
-       case MPU_SLAVE_CONFIG_NMOT_DUR:
-               mantis_set_dur(&private_data->resume,
-                              (*((long *)data->data)));
-               break;
-       default:
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-       };
-
-       return ML_SUCCESS;
-}
-
-struct ext_slave_descr mantis_descr = {
-       /*.init             = */ mantis_init,
-       /*.exit             = */ mantis_exit,
-       /*.suspend          = */ mantis_suspend,
-       /*.resume           = */ mantis_resume,
-       /*.read             = */ mantis_read,
-       /*.config           = */ mantis_config,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "mantis",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_MPU6000,
-       /*.reg              = */ 0xA8,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
-       /*.range            = */ {2, 0},
-};
-
-struct ext_slave_descr *mantis_get_slave_descr(void)
-{
-       return &mantis_descr;
-}
-EXPORT_SYMBOL(mantis_get_slave_descr);
-
-/**
- *  @}
- */
-
diff --git a/drivers/misc/mpu3050/accel/mma8450.c b/drivers/misc/mpu3050/accel/mma8450.c
deleted file mode 100755 (executable)
index ffc92fd..0000000
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   mma8450.c
- *      @brief  Accelerometer setup and handling methods for Freescale MMA8450
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#include <stdlib.h>
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-#include <string.h>
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-#define ACCEL_MMA8450_SLEEP_REG      (0x38)
-#define ACCEL_MMA8450_SLEEP_MASK     (0x3)
-
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-int mma8450_suspend(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata)
-{
-       int result;
-       unsigned char reg;
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address,
-                          ACCEL_MMA8450_SLEEP_REG, 1, &reg);
-       ERROR_CHECK(result);
-       reg &= ~ACCEL_MMA8450_SLEEP_MASK;
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_MMA8450_SLEEP_REG, reg);
-       ERROR_CHECK(result);
-       return result;
-}
-
-/* full scale setting - register & mask */
-#define ACCEL_MMA8450_CTRL_REG      (0x38)
-#define ACCEL_MMA8450_CTRL_MASK     (0x3)
-
-int mma8450_resume(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg;
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address,
-                          ACCEL_MMA8450_CTRL_REG, 1, &reg);
-       ERROR_CHECK(result);
-
-       /* data rate = 200Hz */
-       reg &= 0xE3;
-       reg |= 0x4;
-
-       /* Full Scale */
-       reg &= ~ACCEL_MMA8450_CTRL_MASK;
-       if (slave->range.mantissa == 4)
-               reg |= 0x2;
-       else if (slave->range.mantissa == 8)
-               reg |= 0x3;
-       else {
-               slave->range.mantissa = 2;
-               reg |= 0x1;
-       }
-       slave->range.fraction = 0;
-
-       /* XYZ_DATA_CFG: event flag enabled on all axis */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 0x16, 0x05);
-       ERROR_CHECK(result);
-       /* CTRL_REG1: rate + scale config + wakeup */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_MMA8450_CTRL_REG, reg);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-int mma8450_read(void *mlsl_handle,
-                struct ext_slave_descr *slave,
-                struct ext_slave_platform_data *pdata,
-                unsigned char *data)
-{
-       int result;
-       unsigned char local_data[4]; /* Status register + 3 bytes data */
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               slave->reg, sizeof(local_data), local_data);
-    ERROR_CHECK(result);
-    memcpy(data, &local_data[1], (slave->len)-1);
-    return result;
-}
-
-struct ext_slave_descr mma8450_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ mma8450_suspend,
-       /*.resume           = */ mma8450_resume,
-       /*.read             = */ mma8450_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "mma8450",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_MMA8450,
-       /*.reg              = */ 0x00,
-       /*.len              = */ 4,
-       /*.endian           = */ EXT_SLAVE_FS8_BIG_ENDIAN,
-       /*.range            = */ {2, 0},
-};
-
-struct ext_slave_descr *mma8450_get_slave_descr(void)
-{
-       return &mma8450_descr;
-}
-EXPORT_SYMBOL(mma8450_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/accel/mma8451.c b/drivers/misc/mpu3050/accel/mma8451.c
deleted file mode 100644 (file)
index 4acf449..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
- $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   mma8451.c
- *      @brief  Accelerometer setup and handling methods for Freescale MMA8451
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-#define ACCEL_MMA8451_SLEEP_REG      (0x2A)
-#define ACCEL_MMA8451_SLEEP_MASK     (0x01)
-
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-int mma8451_suspend(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata)
-{
-       int result;
-       unsigned char reg;
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address,
-                          ACCEL_MMA8451_SLEEP_REG, 1, &reg);
-       ERROR_CHECK(result);
-       reg &= ~ACCEL_MMA8451_SLEEP_MASK;
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_MMA8451_SLEEP_REG, reg);
-       ERROR_CHECK(result);
-       return result;
-}
-
-/* full scale setting - register & mask */
-#define ACCEL_MMA8451_CTRL_REG      (0x0E)
-#define ACCEL_MMA8451_CTRL_MASK     (0x03)
-
-int mma8451_resume(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg;
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, 0x0E, 1, &reg);
-       ERROR_CHECK(result);
-
-       /* data rate = 200Hz */
-
-       /* Full Scale */
-       reg &= ~ACCEL_MMA8451_CTRL_MASK;
-       if (slave->range.mantissa == 4)
-               reg |= 0x1;
-       else if (slave->range.mantissa == 8)
-               reg |= 0x2;
-       else {
-               slave->range.mantissa = 2;
-               reg |= 0x0;
-       }
-       slave->range.fraction = 0;
-
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x0E, reg);
-       ERROR_CHECK(result);
-       /* 200Hz + active mode */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address, 0x2A, 0x11);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-int mma8451_read(void *mlsl_handle,
-                struct ext_slave_descr *slave,
-                struct ext_slave_platform_data *pdata,
-                unsigned char *data)
-{
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-}
-
-struct ext_slave_descr mma8451_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ mma8451_suspend,
-       /*.resume           = */ mma8451_resume,
-       /*.read             = */ mma8451_read,
-       /*.config           = */ NULL,
-       /*.name             = */ "mma8451",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_MMA8451,
-       /*.reg              = */ 0x00,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_FS16_BIG_ENDIAN,
-       /*.range            = */ {2, 0},
-};
-
-struct ext_slave_descr *mma8451_get_slave_descr(void)
-{
-       return &mma8451_descr;
-}
-EXPORT_SYMBOL(mma8451_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/accel/mma845x.c b/drivers/misc/mpu3050/accel/mma845x.c
deleted file mode 100755 (executable)
index 648cddb..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   mma845x.c
- *      @brief  Accelerometer setup and handling methods for Freescale MMA845X
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-//#include <stdlib.h>
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-//#include <string.h>
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-#define ACCEL_MMA845X_CTRL_REG1      (0x2A)
-#define ACCEL_MMA845X_SLEEP_MASK     (0x01)
-
-/* full scale setting - register & mask */
-#define ACCEL_MMA845X_CFG_REG       (0x0E)
-#define ACCEL_MMA845X_CTRL_MASK     (0x03)
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-int mma845x_suspend(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata)
-{
-       int result;
-       unsigned char reg;
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address,
-                          ACCEL_MMA845X_CTRL_REG1, 1, &reg);
-       ERROR_CHECK(result);
-       reg &= ~ACCEL_MMA845X_SLEEP_MASK;
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 ACCEL_MMA845X_CTRL_REG1, reg);
-       ERROR_CHECK(result);
-       return result;
-}
-
-
-int mma845x_resume(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg;
-
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               ACCEL_MMA845X_CFG_REG, 1, &reg);
-       ERROR_CHECK(result);
-
-       /* data rate = 200Hz */
-
-       /* Full Scale */
-       reg &= ~ACCEL_MMA845X_CTRL_MASK;
-       if (slave->range.mantissa == 4)
-               reg |= 0x1;
-       else if (slave->range.mantissa == 8)
-               reg |= 0x2;
-       else {
-               slave->range.mantissa = 2;
-               reg |= 0x0;
-       }
-       slave->range.fraction = 0;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                               ACCEL_MMA845X_CFG_REG, reg);
-       ERROR_CHECK(result);
-       /* 200Hz + active mode */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                           ACCEL_MMA845X_CTRL_REG1, 0x11);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-int mma845x_read(void *mlsl_handle,
-                struct ext_slave_descr *slave,
-                struct ext_slave_platform_data *pdata,
-                unsigned char *data)
-{
-       int result;
-       unsigned char local_data[7]; /* Status register + 6 bytes data */
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-                               slave->reg, sizeof(local_data), local_data);
-       ERROR_CHECK(result);
-       memcpy(data, &local_data[1], slave->len);
-       return result;
-}
-
-struct ext_slave_descr mma845x_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ mma845x_suspend,
-       /*.resume           = */ mma845x_resume,
-       /*.read             = */ mma845x_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "mma845x",
-       /*.type             = */ EXT_SLAVE_TYPE_ACCELEROMETER,
-       /*.id               = */ ACCEL_ID_MMA845X,
-       /*.reg              = */ 0x00,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_FS16_BIG_ENDIAN,
-       /*.range            = */ {2, 0},
-};
-
-struct ext_slave_descr *mma845x_get_slave_descr(void)
-{
-       return &mma845x_descr;
-}
-EXPORT_SYMBOL(mma845x_get_slave_descr);
-
-/**
- *  @}
- */
diff --git a/drivers/misc/mpu3050/compass/ak8975.c b/drivers/misc/mpu3050/compass/ak8975.c
deleted file mode 100755 (executable)
index b8aed30..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   COMPASSDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   AK8975.c
- *      @brief  Magnetometer setup and handling methods for AKM 8975 compass.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#include <string.h>
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-compass"
-
-
-#define AK8975_REG_ST1  (0x02)
-#define AK8975_REG_HXL  (0x03)
-#define AK8975_REG_ST2  (0x09)
-
-#define AK8975_REG_CNTL (0x0A)
-
-#define AK8975_CNTL_MODE_POWER_DOWN         (0x00)
-#define AK8975_CNTL_MODE_SINGLE_MEASUREMENT (0x01)
-
-int ak8975_suspend(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 AK8975_REG_CNTL,
-                                 AK8975_CNTL_MODE_POWER_DOWN);
-       MLOSSleep(1);           /* wait at least 100us */
-       ERROR_CHECK(result);
-       return result;
-}
-
-int ak8975_resume(void *mlsl_handle,
-                 struct ext_slave_descr *slave,
-                 struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 AK8975_REG_CNTL,
-                                 AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
-       ERROR_CHECK(result);
-       return result;
-}
-
-int ak8975_read(void *mlsl_handle,
-               struct ext_slave_descr *slave,
-               struct ext_slave_platform_data *pdata, unsigned char *data)
-{
-       unsigned char regs[8];
-       unsigned char *stat = &regs[0];
-       unsigned char *stat2 = &regs[7];
-       int result = ML_SUCCESS;
-       int status = ML_SUCCESS;
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, AK8975_REG_ST1,
-                          8, regs);
-       ERROR_CHECK(result);
-
-       /*
-        * ST : data ready -
-        * Measurement has been completed and data is ready to be read.
-        */
-       if (*stat & 0x01) {
-               memcpy(data, &regs[1], 6);
-               status = ML_SUCCESS;
-       }
-
-       /*
-        * ST2 : data error -
-        * occurs when data read is started outside of a readable period;
-        * data read would not be correct.
-        * Valid in continuous measurement mode only.
-        * In single measurement mode this error should not occour but we
-        * stil account for it and return an error, since the data would be
-        * corrupted.
-        * DERR bit is self-clearing when ST2 register is read.
-        */
-       if (*stat2 & 0x04)
-               status = ML_ERROR_COMPASS_DATA_ERROR;
-       /*
-        * ST2 : overflow -
-        * the sum of the absolute values of all axis |X|+|Y|+|Z| < 2400uT.
-        * This is likely to happen in presence of an external magnetic
-        * disturbance; it indicates, the sensor data is incorrect and should
-        * be ignored.
-        * An error is returned.
-        * HOFL bit clears when a new measurement starts.
-        */
-       if (*stat2 & 0x08)
-               status = ML_ERROR_COMPASS_DATA_OVERFLOW;
-       /*
-        * ST : overrun -
-        * the previous sample was not fetched and lost.
-        * Valid in continuous measurement mode only.
-        * In single measurement mode this error should not occour and we
-        * don't consider this condition an error.
-        * DOR bit is self-clearing when ST2 or any meas. data register is
-        * read.
-        */
-       if (*stat & 0x02) {
-               /* status = ML_ERROR_COMPASS_DATA_UNDERFLOW; */
-               status = ML_SUCCESS;
-       }
-
-       /*
-        * trigger next measurement if:
-        *    - stat is non zero;
-        *    - if stat is zero and stat2 is non zero.
-        * Won't trigger if data is not ready and there was no error.
-        */
-       if (*stat != 0x00 || *stat2 != 0x00) {
-               result =
-                   MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                         AK8975_REG_CNTL,
-                                         AK8975_CNTL_MODE_SINGLE_MEASUREMENT);
-               ERROR_CHECK(result);
-       }
-
-       return status;
-}
-
-static int ak8975_config(void *mlsl_handle,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata,
-                       struct ext_slave_config *data)
-{
-       int result;
-       if (!data->data)
-               return ML_ERROR_INVALID_PARAMETER;
-
-       switch (data->key) {
-       case MPU_SLAVE_WRITE_REGISTERS:
-               result = MLSLSerialWrite(mlsl_handle, pdata->address,
-                                       data->len,
-                                       (unsigned char *)data->data);
-               ERROR_CHECK(result);
-               break;
-       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
-       case MPU_SLAVE_CONFIG_ODR_RESUME:
-       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
-       case MPU_SLAVE_CONFIG_FSR_RESUME:
-       case MPU_SLAVE_CONFIG_MOT_THS:
-       case MPU_SLAVE_CONFIG_NMOT_THS:
-       case MPU_SLAVE_CONFIG_MOT_DUR:
-       case MPU_SLAVE_CONFIG_NMOT_DUR:
-       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
-       case MPU_SLAVE_CONFIG_IRQ_RESUME:
-       default:
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-       };
-
-       return ML_SUCCESS;
-}
-
-static int ak8975_get_config(void *mlsl_handle,
-                               struct ext_slave_descr *slave,
-                               struct ext_slave_platform_data *pdata,
-                               struct ext_slave_config *data)
-{
-       int result;
-       if (!data->data)
-               return ML_ERROR_INVALID_PARAMETER;
-
-       switch (data->key) {
-       case MPU_SLAVE_READ_REGISTERS:
-       {
-               unsigned char *serial_data = (unsigned char *)data->data;
-               result = MLSLSerialRead(mlsl_handle, pdata->address,
-                                       serial_data[0],
-                                       data->len - 1,
-                                       &serial_data[1]);
-               ERROR_CHECK(result);
-               break;
-       }
-       case MPU_SLAVE_CONFIG_ODR_SUSPEND:
-       case MPU_SLAVE_CONFIG_ODR_RESUME:
-       case MPU_SLAVE_CONFIG_FSR_SUSPEND:
-       case MPU_SLAVE_CONFIG_FSR_RESUME:
-       case MPU_SLAVE_CONFIG_MOT_THS:
-       case MPU_SLAVE_CONFIG_NMOT_THS:
-       case MPU_SLAVE_CONFIG_MOT_DUR:
-       case MPU_SLAVE_CONFIG_NMOT_DUR:
-       case MPU_SLAVE_CONFIG_IRQ_SUSPEND:
-       case MPU_SLAVE_CONFIG_IRQ_RESUME:
-       default:
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-       };
-
-       return ML_SUCCESS;
-}
-
-struct ext_slave_descr ak8975_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ ak8975_suspend,
-       /*.resume           = */ ak8975_resume,
-       /*.read             = */ ak8975_read,
-       /*.config           = */ ak8975_config,
-       /*.get_config       = */ ak8975_get_config,
-       /*.name             = */ "ak8975",
-       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-       /*.id               = */ COMPASS_ID_AKM,
-       /*.reg              = */ 0x01,
-       /*.len              = */ 9,
-       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
-       /*.range            = */ {9830, 4000}
-};
-
-struct ext_slave_descr *ak8975_get_slave_descr(void)
-{
-       return &ak8975_descr;
-}
-EXPORT_SYMBOL(ak8975_get_slave_descr);
-
-/**
- *  @}
- */
diff --git a/drivers/misc/mpu3050/compass/ami306.c b/drivers/misc/mpu3050/compass/ami306.c
deleted file mode 100755 (executable)
index 75ca007..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   COMPASSDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *     @file   ami306.c
- *     @brief  Magnetometer setup and handling methods for Aichi AMI306
- *             compass.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include <delay.h>
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-compass"
-
-#define AMI306_REG_DATAX (0x10)
-#define AMI306_REG_STAT1 (0x18)
-#define AMI306_REG_CNTL1 (0x1B)
-#define AMI306_REG_CNTL2 (0x1C)
-#define AMI306_REG_CNTL3 (0x1D)
-#define AMI306_REG_CNTL4_1 (0x5C)
-#define AMI306_REG_CNTL4_2 (0x5D)
-
-#define AMI306_BIT_CNTL1_PC1  (0x80)
-#define AMI306_BIT_CNTL1_ODR1 (0x10)
-#define AMI306_BIT_CNTL1_FS1  (0x02)
-
-#define AMI306_BIT_CNTL2_IEN  (0x10)
-#define AMI306_BIT_CNTL2_DREN (0x08)
-#define AMI306_BIT_CNTL2_DRP  (0x04)
-#define AMI306_BIT_CNTL3_F0RCE (0x40)
-
-int ami306_suspend(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       int result;
-       unsigned char reg;
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, AMI306_REG_CNTL1,
-                          1, &reg);
-       ERROR_CHECK(result);
-
-       reg &= ~(AMI306_BIT_CNTL1_PC1|AMI306_BIT_CNTL1_FS1);
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 AMI306_REG_CNTL1, reg);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-int ami306_resume(void *mlsl_handle,
-                 struct ext_slave_descr *slave,
-                 struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-       unsigned char regs[] = {
-                AMI306_REG_CNTL4_1,
-                0x7E,
-                0xA0
-       };
-    /* Step1. Set CNTL1 reg to power model active (Write CNTL1:PC1=1) */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 AMI306_REG_CNTL1,
-                                 AMI306_BIT_CNTL1_PC1|AMI306_BIT_CNTL1_FS1);
-       ERROR_CHECK(result);
-
-    /* Step2. Set CNTL2 reg to DRDY active high and enabled
-       (Write CNTL2:DREN=1) */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 AMI306_REG_CNTL2,
-                                 AMI306_BIT_CNTL2_DREN |
-                                 AMI306_BIT_CNTL2_DRP);
-       ERROR_CHECK(result);
-
-    /* Step3. Set CNTL4 reg to for measurement speed (Write CNTL4, 0xA07E) */
-       result =
-           MLSLSerialWrite(mlsl_handle, pdata->address, DIM(regs), regs);
-       ERROR_CHECK(result);
-
-    /* Step4. skipped */
-
-    /* Step5. Set CNTL3 reg to forced measurement period
-       (Write CNTL3:FORCE=1) */
-       result =
-               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 AMI306_REG_CNTL3, AMI306_BIT_CNTL3_F0RCE);
-
-       return result;
-}
-
-int ami306_read(void *mlsl_handle,
-               struct ext_slave_descr *slave,
-               struct ext_slave_platform_data *pdata, unsigned char *data)
-{
-       unsigned char stat;
-       int result = ML_SUCCESS;
-       int status = ML_SUCCESS;
-
-
-       /* Measurement(x,y,z) */
-       result =
-               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                     AMI306_REG_CNTL3,
-                                     AMI306_BIT_CNTL3_F0RCE);
-       ERROR_CHECK(result);
-       udelay(500);
-
-    /* Step6. Read status reg and check if data ready (DRDY) */
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, AMI306_REG_STAT1,
-                          1, &stat);
-       ERROR_CHECK(result);
-
-    /* Step6. Does DRDY output the rising edge? */
-       if (stat & 0x40) {
-               result =
-                   MLSLSerialRead(mlsl_handle, pdata->address,
-                                  AMI306_REG_DATAX, 6,
-                                  (unsigned char *) data);
-               ERROR_CHECK(result);
-               status = ML_SUCCESS;
-       } else if (stat & 0x20)
-               status = ML_ERROR_COMPASS_DATA_OVERFLOW;
-
-       return status;
-}
-
-struct ext_slave_descr ami306_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ ami306_suspend,
-       /*.resume           = */ ami306_resume,
-       /*.read             = */ ami306_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "ami306",
-       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-       /*.id               = */ COMPASS_ID_AMI306,
-       /*.reg              = */ 0x10,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
-       /*.range            = */ {5461, 3333}
-       /* For AMI305,the range field needs to be modified to {9830.4f}*/
-};
-
-struct ext_slave_descr *ami306_get_slave_descr(void)
-{
-       return &ami306_descr;
-}
-EXPORT_SYMBOL(ami306_get_slave_descr);
-
-/**
- *  @}
- */
diff --git a/drivers/misc/mpu3050/compass/ami30x.c b/drivers/misc/mpu3050/compass/ami30x.c
deleted file mode 100755 (executable)
index 5e4a33e..0000000
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   COMPASSDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *     @file   ami30x.c
- *     @brief  Magnetometer setup and handling methods for Aichi AMI304/AMI305
- *             compass.
-*/
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-compass"
-
-#define AMI30X_REG_DATAX (0x10)
-#define AMI30X_REG_STAT1 (0x18)
-#define AMI30X_REG_CNTL1 (0x1B)
-#define AMI30X_REG_CNTL2 (0x1C)
-#define AMI30X_REG_CNTL3 (0x1D)
-
-#define AMI30X_BIT_CNTL1_PC1  (0x80)
-#define AMI30X_BIT_CNTL1_ODR1 (0x10)
-#define AMI30X_BIT_CNTL1_FS1  (0x02)
-
-#define AMI30X_BIT_CNTL2_IEN  (0x10)
-#define AMI30X_BIT_CNTL2_DREN (0x08)
-#define AMI30X_BIT_CNTL2_DRP  (0x04)
-#define AMI30X_BIT_CNTL3_F0RCE (0x40)
-
-int ami30x_suspend(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       int result;
-       unsigned char reg;
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, AMI30X_REG_CNTL1,
-                          1, &reg);
-       ERROR_CHECK(result);
-
-       reg &= ~(AMI30X_BIT_CNTL1_PC1|AMI30X_BIT_CNTL1_FS1);
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 AMI30X_REG_CNTL1, reg);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-int ami30x_resume(void *mlsl_handle,
-                 struct ext_slave_descr *slave,
-                 struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       /* Set CNTL1 reg to power model active */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 AMI30X_REG_CNTL1,
-                                 AMI30X_BIT_CNTL1_PC1|AMI30X_BIT_CNTL1_FS1);
-       ERROR_CHECK(result);
-       /* Set CNTL2 reg to DRDY active high and enabled */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 AMI30X_REG_CNTL2,
-                                 AMI30X_BIT_CNTL2_DREN |
-                                 AMI30X_BIT_CNTL2_DRP);
-       ERROR_CHECK(result);
-       /* Set CNTL3 reg to forced measurement period */
-       result =
-               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 AMI30X_REG_CNTL3, AMI30X_BIT_CNTL3_F0RCE);
-
-       return result;
-}
-
-int ami30x_read(void *mlsl_handle,
-               struct ext_slave_descr *slave,
-               struct ext_slave_platform_data *pdata, unsigned char *data)
-{
-       unsigned char stat;
-       int result = ML_SUCCESS;
-
-       /* Read status reg and check if data ready (DRDY) */
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, AMI30X_REG_STAT1,
-                          1, &stat);
-       ERROR_CHECK(result);
-
-       if (stat & 0x40) {
-               result =
-                   MLSLSerialRead(mlsl_handle, pdata->address,
-                                  AMI30X_REG_DATAX, 6,
-                                  (unsigned char *) data);
-               ERROR_CHECK(result);
-               /* start another measurement */
-               result =
-                       MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                             AMI30X_REG_CNTL3,
-                                             AMI30X_BIT_CNTL3_F0RCE);
-               ERROR_CHECK(result);
-
-               return ML_SUCCESS;
-       }
-
-       return ML_ERROR_COMPASS_DATA_NOT_READY;
-}
-
-struct ext_slave_descr ami30x_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ ami30x_suspend,
-       /*.resume           = */ ami30x_resume,
-       /*.read             = */ ami30x_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "ami30x",
-       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-       /*.id               = */ COMPASS_ID_AMI30X,
-       /*.reg              = */ 0x06,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
-       /*.range            = */ {5461, 3333}
-       /* For AMI305,the range field needs to be modified to {9830.4f}*/
-};
-
-struct ext_slave_descr *ami30x_get_slave_descr(void)
-{
-       return &ami30x_descr;
-}
-EXPORT_SYMBOL(ami30x_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/compass/hmc5883.c b/drivers/misc/mpu3050/compass/hmc5883.c
deleted file mode 100755 (executable)
index 02afd58..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @brief      Provides the interface to setup and handle a compass
- *              connected to the primary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   hmc5883.c
- *      @brief  Magnetometer setup and handling methods for honeywell hmc5883
- *              compass.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-compass"
-
-/*-----HONEYWELL HMC5883 Registers ------*/
-enum HMC_REG {
-       HMC_REG_CONF_A = 0x0,
-       HMC_REG_CONF_B = 0x1,
-       HMC_REG_MODE = 0x2,
-       HMC_REG_X_M = 0x3,
-       HMC_REG_X_L = 0x4,
-       HMC_REG_Z_M = 0x5,
-       HMC_REG_Z_L = 0x6,
-       HMC_REG_Y_M = 0x7,
-       HMC_REG_Y_L = 0x8,
-       HMC_REG_STATUS = 0x9,
-       HMC_REG_ID_A = 0xA,
-       HMC_REG_ID_B = 0xB,
-       HMC_REG_ID_C = 0xC
-};
-
-enum HMC_CONF_A {
-       HMC_CONF_A_DRATE_MASK = 0x1C,
-       HMC_CONF_A_DRATE_0_75 = 0x00,
-       HMC_CONF_A_DRATE_1_5 = 0x04,
-       HMC_CONF_A_DRATE_3 = 0x08,
-       HMC_CONF_A_DRATE_7_5 = 0x0C,
-       HMC_CONF_A_DRATE_15 = 0x10,
-       HMC_CONF_A_DRATE_30 = 0x14,
-       HMC_CONF_A_DRATE_75 = 0x18,
-       HMC_CONF_A_MEAS_MASK = 0x3,
-       HMC_CONF_A_MEAS_NORM = 0x0,
-       HMC_CONF_A_MEAS_POS = 0x1,
-       HMC_CONF_A_MEAS_NEG = 0x2
-};
-
-enum HMC_CONF_B{
-       HMC_CONF_B_GAIN_MASK = 0xE0,
-       HMC_CONF_B_GAIN_0_9 = 0x00,
-       HMC_CONF_B_GAIN_1_2 = 0x20,
-       HMC_CONF_B_GAIN_1_9 = 0x40,
-       HMC_CONF_B_GAIN_2_5 = 0x60,
-       HMC_CONF_B_GAIN_4_0 = 0x80,
-       HMC_CONF_B_GAIN_4_6 = 0xA0,
-       HMC_CONF_B_GAIN_5_5 = 0xC0,
-       HMC_CONF_B_GAIN_7_9 = 0xE0
-};
-
-enum HMC_MODE {
-       HMC_MODE_MASK = 0x3,
-       HMC_MODE_CONT = 0x0,
-       HMC_MODE_SINGLE = 0x1,
-       HMC_MODE_IDLE = 0x2,
-       HMC_MODE_SLEEP = 0x3
-};
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-int hmc5883_suspend(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 HMC_REG_MODE, HMC_MODE_SLEEP);
-       ERROR_CHECK(result);
-       MLOSSleep(3);
-
-       return result;
-}
-
-int hmc5883_resume(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       /* Use single measurement mode. Start at sleep state. */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 HMC_REG_MODE, HMC_MODE_SLEEP);
-       ERROR_CHECK(result);
-       /* Config normal measurement */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 HMC_REG_CONF_A, 0);
-       ERROR_CHECK(result);
-       /* Adjust gain to 307 LSB/Gauss */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 HMC_REG_CONF_B, HMC_CONF_B_GAIN_5_5);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-int hmc5883_read(void *mlsl_handle,
-                struct ext_slave_descr *slave,
-                struct ext_slave_platform_data *pdata,
-                unsigned char *data)
-{
-       unsigned char stat;
-       tMLError result = ML_SUCCESS;
-       unsigned char tmp;
-       short axisFixed;
-
-       /* Read status reg. to check if data is ready */
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, HMC_REG_STATUS, 1,
-                          &stat);
-       ERROR_CHECK(result);
-       if (stat & 0x01) {
-               result =
-                   MLSLSerialRead(mlsl_handle, pdata->address,
-                                  HMC_REG_X_M, 6, (unsigned char *) data);
-               ERROR_CHECK(result);
-
-               /* switch YZ axis to proper position */
-               tmp = data[2];
-               data[2] = data[4];
-               data[4] = tmp;
-               tmp = data[3];
-               data[3] = data[5];
-               data[5] = tmp;
-
-               /*drop data if overflows */
-               if ((data[0] == 0xf0) || (data[2] == 0xf0)
-                   || (data[4] == 0xf0)) {
-                       /* trigger next measurement read */
-                       result =
-                           MLSLSerialWriteSingle(mlsl_handle,
-                                                       pdata->address,
-                                                       HMC_REG_MODE,
-                                                       HMC_MODE_SINGLE);
-                       ERROR_CHECK(result);
-                       return ML_ERROR_COMPASS_DATA_OVERFLOW;
-               }
-               /* convert to fixed point and apply sensitivity correction for
-                  Z-axis */
-               axisFixed =
-                   (short) ((unsigned short) data[5] +
-                            (unsigned short) data[4] * 256);
-               /* scale up by 1.125 (36/32) */
-               axisFixed = (short) (axisFixed * 36);
-               data[4] = axisFixed >> 8;
-               data[5] = axisFixed & 0xFF;
-
-               axisFixed =
-                   (short) ((unsigned short) data[3] +
-                            (unsigned short) data[2] * 256);
-               axisFixed = (short) (axisFixed * 32);
-               data[2] = axisFixed >> 8;
-               data[3] = axisFixed & 0xFF;
-
-               axisFixed =
-                   (short) ((unsigned short) data[1] +
-                            (unsigned short) data[0] * 256);
-               axisFixed = (short) (axisFixed * 32);
-               data[0] = axisFixed >> 8;
-               data[1] = axisFixed & 0xFF;
-
-               /* trigger next measurement read */
-               result =
-                   MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                         HMC_REG_MODE, HMC_MODE_SINGLE);
-               ERROR_CHECK(result);
-
-               return ML_SUCCESS;
-       } else {
-               /* trigger next measurement read */
-               result =
-                   MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                         HMC_REG_MODE, HMC_MODE_SINGLE);
-               ERROR_CHECK(result);
-
-               return ML_ERROR_COMPASS_DATA_NOT_READY;
-       }
-}
-
-struct ext_slave_descr hmc5883_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ hmc5883_suspend,
-       /*.resume           = */ hmc5883_resume,
-       /*.read             = */ hmc5883_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "hmc5883",
-       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-       /*.id               = */ COMPASS_ID_HMC5883,
-       /*.reg              = */ 0x06,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
-       /*.range            = */ {10673, 6156},
-};
-
-struct ext_slave_descr *hmc5883_get_slave_descr(void)
-{
-       return &hmc5883_descr;
-}
-EXPORT_SYMBOL(hmc5883_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/compass/hscdtd002b.c b/drivers/misc/mpu3050/compass/hscdtd002b.c
deleted file mode 100755 (executable)
index bf26cae..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @brief      Provides the interface to setup and handle a compass
- *              connected to the primary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   hscdtd002b.c
- *      @brief  Magnetometer setup and handling methods for Alps hscdtd002b
- *              compass.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-compass"
-
-/*----- ALPS HSCDTD002B Registers ------*/
-#define COMPASS_HSCDTD002B_STAT          (0x18)
-#define COMPASS_HSCDTD002B_CTRL1         (0x1B)
-#define COMPASS_HSCDTD002B_CTRL2         (0x1C)
-#define COMPASS_HSCDTD002B_CTRL3         (0x1D)
-#define COMPASS_HSCDTD002B_DATAX         (0x10)
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Compass Initialization Functions
-*****************************************/
-
-int hscdtd002b_suspend(void *mlsl_handle,
-                      struct ext_slave_descr *slave,
-                      struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       /* Power mode: stand-by */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD002B_CTRL1, 0x00);
-       ERROR_CHECK(result);
-       MLOSSleep(1);           /* turn-off time */
-
-       return result;
-}
-
-int hscdtd002b_resume(void *mlsl_handle,
-                     struct ext_slave_descr *slave,
-                     struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       /* Soft reset */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD002B_CTRL3, 0x80);
-       ERROR_CHECK(result);
-       /* Force state; Power mode: active */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD002B_CTRL1, 0x82);
-       ERROR_CHECK(result);
-       /* Data ready enable */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD002B_CTRL2, 0x08);
-       ERROR_CHECK(result);
-       MLOSSleep(1);           /* turn-on time */
-
-       return result;
-}
-
-int hscdtd002b_read(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata,
-                   unsigned char *data)
-{
-       unsigned char stat;
-       tMLError result = ML_SUCCESS;
-       int status = ML_SUCCESS;
-
-       /* Read status reg. to check if data is ready */
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address,
-                          COMPASS_HSCDTD002B_STAT, 1, &stat);
-       ERROR_CHECK(result);
-       if (stat & 0x40) {
-               result =
-                   MLSLSerialRead(mlsl_handle, pdata->address,
-                                  COMPASS_HSCDTD002B_DATAX, 6,
-                                  (unsigned char *) data);
-               ERROR_CHECK(result);
-               status = ML_SUCCESS;
-       } else if (stat & 0x20) {
-               status = ML_ERROR_COMPASS_DATA_OVERFLOW;
-       } else {
-               status = ML_ERROR_COMPASS_DATA_NOT_READY;
-       }
-       /* trigger next measurement read */
-       result =
-               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                         COMPASS_HSCDTD002B_CTRL3, 0x40);
-       ERROR_CHECK(result);
-
-       return status;
-}
-
-struct ext_slave_descr hscdtd002b_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ hscdtd002b_suspend,
-       /*.resume           = */ hscdtd002b_resume,
-       /*.read             = */ hscdtd002b_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "hscdtd002b",
-       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-       /*.id               = */ COMPASS_ID_HSCDTD002B,
-       /*.reg              = */ 0x10,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
-       /*.range            = */ {9830, 4000},
-};
-
-struct ext_slave_descr *hscdtd002b_get_slave_descr(void)
-{
-       return &hscdtd002b_descr;
-}
-EXPORT_SYMBOL(hscdtd002b_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/compass/hscdtd004a.c b/drivers/misc/mpu3050/compass/hscdtd004a.c
deleted file mode 100755 (executable)
index 43fc14a..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @brief      Provides the interface to setup and handle a compass
- *              connected to the primary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   hscdtd004a.c
- *      @brief  Magnetometer setup and handling methods for Alps hscdtd004a
- *              compass.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-compass"
-
-/*----- ALPS HSCDTD004A Registers ------*/
-#define COMPASS_HSCDTD004A_STAT          (0x18)
-#define COMPASS_HSCDTD004A_CTRL1         (0x1B)
-#define COMPASS_HSCDTD004A_CTRL2         (0x1C)
-#define COMPASS_HSCDTD004A_CTRL3         (0x1D)
-#define COMPASS_HSCDTD004A_DATAX         (0x10)
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Compass Initialization Functions
-*****************************************/
-
-int hscdtd004a_suspend(void *mlsl_handle,
-                      struct ext_slave_descr *slave,
-                      struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       /* Power mode: stand-by */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD004A_CTRL1, 0x00);
-       ERROR_CHECK(result);
-       MLOSSleep(1);           /* turn-off time */
-
-       return result;
-}
-
-int hscdtd004a_resume(void *mlsl_handle,
-                     struct ext_slave_descr *slave,
-                     struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       /* Soft reset */
-       result =
-               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD004A_CTRL3, 0x80);
-       ERROR_CHECK(result);
-       /* Normal state; Power mode: active */
-       result =
-               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD004A_CTRL1, 0x82);
-       ERROR_CHECK(result);
-       /* Data ready enable */
-       result =
-               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD004A_CTRL2, 0x7C);
-       ERROR_CHECK(result);
-       MLOSSleep(1);           /* turn-on time */
-       return result;
-}
-
-int hscdtd004a_read(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata,
-                   unsigned char *data)
-{
-       unsigned char stat;
-       tMLError result = ML_SUCCESS;
-       int status = ML_SUCCESS;
-
-       /* Read status reg. to check if data is ready */
-       result =
-               MLSLSerialRead(mlsl_handle, pdata->address,
-                          COMPASS_HSCDTD004A_STAT, 1, &stat);
-       ERROR_CHECK(result);
-       if (stat & 0x48) {
-               result =
-                        MLSLSerialRead(mlsl_handle, pdata->address,
-                                  COMPASS_HSCDTD004A_DATAX, 6,
-                                  (unsigned char *) data);
-               ERROR_CHECK(result);
-               status = ML_SUCCESS;
-       } else if (stat & 0x68) {
-               status = ML_ERROR_COMPASS_DATA_OVERFLOW;
-       } else {
-               status = ML_ERROR_COMPASS_DATA_NOT_READY;
-       }
-       /* trigger next measurement read */
-       result =
-               MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                       COMPASS_HSCDTD004A_CTRL3, 0x40);
-       ERROR_CHECK(result);
-       return status;
-
-}
-
-struct ext_slave_descr hscdtd004a_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ hscdtd004a_suspend,
-       /*.resume           = */ hscdtd004a_resume,
-       /*.read             = */ hscdtd004a_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "hscdtd004a",
-       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-       /*.id               = */ COMPASS_ID_HSCDTD004A,
-       /*.reg              = */ 0x10,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
-       /*.range            = */ {9830, 4000},
-};
-
-struct ext_slave_descr *hscdtd004a_get_slave_descr(void)
-{
-       return &hscdtd004a_descr;
-}
-EXPORT_SYMBOL(hscdtd004a_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/compass/hscdtd00xx.c b/drivers/misc/mpu3050/compass/hscdtd00xx.c
deleted file mode 100644 (file)
index 69aa3bb..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
- $
- */
-
-/**
- *  @brief      Provides the interface to setup and handle a compass
- *              connected to the primary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   hscdtd00xx.c
- *      @brief  Magnetometer setup and handling methods for Alps hscdtd00xx
- *              compass.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-compass"
-
-/*----- ALPS HSCDTD00XX Registers ------*/
-#define COMPASS_HSCDTD00XX_STAT          (0x18)
-#define COMPASS_HSCDTD00XX_CTRL1         (0x1B)
-#define COMPASS_HSCDTD00XX_CTRL2         (0x1C)
-#define COMPASS_HSCDTD00XX_CTRL3         (0x1D)
-#define COMPASS_HSCDTD00XX_DATAX         (0x10)
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Compass Initialization Functions
-*****************************************/
-
-int hscdtd00xx_suspend(void *mlsl_handle,
-                      struct ext_slave_descr *slave,
-                      struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       /* Power mode: stand-by */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD00XX_CTRL1, 0x00);
-       ERROR_CHECK(result);
-       MLOSSleep(1);           /* turn-off time */
-
-       return result;
-}
-
-int hscdtd00xx_resume(void *mlsl_handle,
-                     struct ext_slave_descr *slave,
-                     struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       /* Soft reset */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD00XX_CTRL3, 0x80);
-       ERROR_CHECK(result);
-       /* Force state; Power mode: active */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD00XX_CTRL1, 0x82);
-       ERROR_CHECK(result);
-       /* Data ready enable */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 COMPASS_HSCDTD00XX_CTRL2, 0x08);
-       ERROR_CHECK(result);
-       MLOSSleep(1);           /* turn-on time */
-
-       return result;
-}
-
-int hscdtd00xx_read(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata,
-                   unsigned char *data)
-{
-       unsigned char stat;
-       tMLError result = ML_SUCCESS;
-
-       /* Read status reg. to check if data is ready */
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address,
-                          COMPASS_HSCDTD00XX_STAT, 1, &stat);
-       ERROR_CHECK(result);
-       if (stat & 0x40) {
-               result =
-                   MLSLSerialRead(mlsl_handle, pdata->address,
-                                  COMPASS_HSCDTD00XX_DATAX, 6,
-                                  (unsigned char *) data);
-               ERROR_CHECK(result);
-
-               /* trigger next measurement read */
-               result =
-                   MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                         COMPASS_HSCDTD00XX_CTRL3, 0x40);
-               ERROR_CHECK(result);
-
-               return ML_SUCCESS;
-       } else if (stat & 0x20) {
-               /* trigger next measurement read */
-               result =
-                   MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                         COMPASS_HSCDTD00XX_CTRL3, 0x40);
-               ERROR_CHECK(result);
-               return ML_ERROR_COMPASS_DATA_OVERFLOW;
-       } else {
-               /* trigger next measurement read */
-               result =
-                   MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                         COMPASS_HSCDTD00XX_CTRL3, 0x40);
-               ERROR_CHECK(result);
-               return ML_ERROR_COMPASS_DATA_NOT_READY;
-       }
-}
-
-struct ext_slave_descr hscdtd00xx_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ hscdtd00xx_suspend,
-       /*.resume           = */ hscdtd00xx_resume,
-       /*.read             = */ hscdtd00xx_read,
-       /*.config           = */ NULL,
-       /*.name             = */ "hscdtd00xx",
-       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-       /*.id               = */ COMPASS_ID_HSCDTD00XX,
-       /*.reg              = */ 0x10,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_LITTLE_ENDIAN,
-       /*.range            = */ {9830, 4000},
-};
-
-struct ext_slave_descr *hscdtd00xx_get_slave_descr(void)
-{
-       return &hscdtd00xx_descr;
-}
-EXPORT_SYMBOL(hscdtd00xx_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/compass/lsm303m.c b/drivers/misc/mpu3050/compass/lsm303m.c
deleted file mode 100755 (executable)
index 871d002..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @brief      Provides the interface to setup and handle a compass
- *              connected to the primary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   lsm303m.c
- *      @brief  Magnetometer setup and handling methods for ST LSM303.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-compass"
-
-/*----- ST LSM303 Registers ------*/
-enum LSM_REG {
-       LSM_REG_CONF_A = 0x0,
-       LSM_REG_CONF_B = 0x1,
-       LSM_REG_MODE = 0x2,
-       LSM_REG_X_M = 0x3,
-       LSM_REG_X_L = 0x4,
-       LSM_REG_Z_M = 0x5,
-       LSM_REG_Z_L = 0x6,
-       LSM_REG_Y_M = 0x7,
-       LSM_REG_Y_L = 0x8,
-       LSM_REG_STATUS = 0x9,
-       LSM_REG_ID_A = 0xA,
-       LSM_REG_ID_B = 0xB,
-       LSM_REG_ID_C = 0xC
-};
-
-enum LSM_CONF_A {
-       LSM_CONF_A_DRATE_MASK = 0x1C,
-       LSM_CONF_A_DRATE_0_75 = 0x00,
-       LSM_CONF_A_DRATE_1_5 = 0x04,
-       LSM_CONF_A_DRATE_3 = 0x08,
-       LSM_CONF_A_DRATE_7_5 = 0x0C,
-       LSM_CONF_A_DRATE_15 = 0x10,
-       LSM_CONF_A_DRATE_30 = 0x14,
-       LSM_CONF_A_DRATE_75 = 0x18,
-       LSM_CONF_A_MEAS_MASK = 0x3,
-       LSM_CONF_A_MEAS_NORM = 0x0,
-       LSM_CONF_A_MEAS_POS = 0x1,
-       LSM_CONF_A_MEAS_NEG = 0x2
-};
-
-enum LSM_CONF_B {
-       LSM_CONF_B_GAIN_MASK = 0xE0,
-       LSM_CONF_B_GAIN_0_9 = 0x00,
-       LSM_CONF_B_GAIN_1_2 = 0x20,
-       LSM_CONF_B_GAIN_1_9 = 0x40,
-       LSM_CONF_B_GAIN_2_5 = 0x60,
-       LSM_CONF_B_GAIN_4_0 = 0x80,
-       LSM_CONF_B_GAIN_4_6 = 0xA0,
-       LSM_CONF_B_GAIN_5_5 = 0xC0,
-       LSM_CONF_B_GAIN_7_9 = 0xE0
-};
-
-enum LSM_MODE {
-       LSM_MODE_MASK = 0x3,
-       LSM_MODE_CONT = 0x0,
-       LSM_MODE_SINGLE = 0x1,
-       LSM_MODE_IDLE = 0x2,
-       LSM_MODE_SLEEP = 0x3
-};
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-int lsm303dlhm_suspend(void *mlsl_handle,
-                      struct ext_slave_descr *slave,
-                      struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 LSM_REG_MODE, LSM_MODE_SLEEP);
-       ERROR_CHECK(result);
-       MLOSSleep(3);
-
-       return result;
-}
-
-int lsm303dlhm_resume(void *mlsl_handle,
-                     struct ext_slave_descr *slave,
-                     struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       /* Use single measurement mode. Start at sleep state. */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 LSM_REG_MODE, LSM_MODE_SLEEP);
-       ERROR_CHECK(result);
-       /* Config normal measurement */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 LSM_REG_CONF_A, 0);
-       ERROR_CHECK(result);
-       /* Adjust gain to 320 LSB/Gauss */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 LSM_REG_CONF_B, LSM_CONF_B_GAIN_5_5);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-int lsm303dlhm_read(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata,
-                   unsigned char *data)
-{
-       unsigned char stat;
-       tMLError result = ML_SUCCESS;
-       short axisFixed;
-
-       /* Read status reg. to check if data is ready */
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, LSM_REG_STATUS, 1,
-                          &stat);
-       ERROR_CHECK(result);
-       if (stat & 0x01) {
-               result =
-                   MLSLSerialRead(mlsl_handle, pdata->address,
-                                  LSM_REG_X_M, 6, (unsigned char *) data);
-               ERROR_CHECK(result);
-
-               /*drop data if overflows */
-               if ((data[0] == 0xf0) || (data[2] == 0xf0)
-                   || (data[4] == 0xf0)) {
-                       /* trigger next measurement read */
-                       result =
-                               MLSLSerialWriteSingle(mlsl_handle,
-                                                       pdata->address,
-                                                       LSM_REG_MODE,
-                                                       LSM_MODE_SINGLE);
-                       ERROR_CHECK(result);
-                       return ML_ERROR_COMPASS_DATA_OVERFLOW;
-               }
-               /* convert to fixed point and apply sensitivity correction for
-                  Z-axis */
-               axisFixed =
-                   (short) ((unsigned short) data[5] +
-                            (unsigned short) data[4] * 256);
-               /* scale up by 1.125 (36/32) approximate of 1.122 (320/285) */
-               axisFixed = (short) (axisFixed * 36);
-               data[4] = axisFixed >> 8;
-               data[5] = axisFixed & 0xFF;
-
-               axisFixed =
-                   (short) ((unsigned short) data[3] +
-                            (unsigned short) data[2] * 256);
-               axisFixed = (short) (axisFixed * 32);
-               data[2] = axisFixed >> 8;
-               data[3] = axisFixed & 0xFF;
-
-               axisFixed =
-                   (short) ((unsigned short) data[1] +
-                            (unsigned short) data[0] * 256);
-               axisFixed = (short) (axisFixed * 32);
-               data[0] = axisFixed >> 8;
-               data[1] = axisFixed & 0xFF;
-
-               /* trigger next measurement read */
-               result =
-                   MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                         LSM_REG_MODE, LSM_MODE_SINGLE);
-               ERROR_CHECK(result);
-
-               return ML_SUCCESS;
-       } else {
-               /* trigger next measurement read */
-               result =
-                   MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                         LSM_REG_MODE, LSM_MODE_SINGLE);
-               ERROR_CHECK(result);
-
-               return ML_ERROR_COMPASS_DATA_NOT_READY;
-       }
-}
-
-struct ext_slave_descr lsm303dlhm_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ lsm303dlhm_suspend,
-       /*.resume           = */ lsm303dlhm_resume,
-       /*.read             = */ lsm303dlhm_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "lsm303dlhm",
-       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-       /*.id               = */ COMPASS_ID_LSM303,
-       /*.reg              = */ 0x06,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
-       /*.range            = */ {10240, 0},
-};
-
-struct ext_slave_descr *lsm303dlhm_get_slave_descr(void)
-{
-       return &lsm303dlhm_descr;
-}
-EXPORT_SYMBOL(lsm303dlhm_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/compass/mmc314x.c b/drivers/misc/mpu3050/compass/mmc314x.c
deleted file mode 100755 (executable)
index 010d7a7..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   mmc314x.c
- *      @brief  Magnetometer setup and handling methods for ???? compass.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-compass"
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-static int reset_int = 1000;
-static int read_count = 1;
-static char reset_mode; /* in Z-init section */
-
-#define MMC314X_REG_ST (0x00)
-#define MMC314X_REG_X_MSB (0x01)
-
-#define MMC314X_CNTL_MODE_WAKE_UP (0x01)
-#define MMC314X_CNTL_MODE_SET (0x02)
-#define MMC314X_CNTL_MODE_RESET (0x04)
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-int mmc314x_suspend(void *mlsl_handle,
-                   struct ext_slave_descr *slave,
-                   struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       return result;
-}
-
-int mmc314x_resume(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-
-       int result;
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 MMC314X_REG_ST, MMC314X_CNTL_MODE_RESET);
-       ERROR_CHECK(result);
-       MLOSSleep(10);
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 MMC314X_REG_ST, MMC314X_CNTL_MODE_SET);
-       ERROR_CHECK(result);
-       MLOSSleep(10);
-       read_count = 1;
-       return ML_SUCCESS;
-}
-
-int mmc314x_read(void *mlsl_handle,
-                struct ext_slave_descr *slave,
-                struct ext_slave_platform_data *pdata,
-                unsigned char *data)
-{
-       int result, ii;
-       short tmp[3];
-       unsigned char tmpdata[6];
-
-
-       if (read_count > 1000)
-               read_count = 1;
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->address, MMC314X_REG_X_MSB,
-                          6, (unsigned char *) data);
-       ERROR_CHECK(result);
-
-       for (ii = 0; ii < 6; ii++)
-               tmpdata[ii] = data[ii];
-
-       for (ii = 0; ii < 3; ii++) {
-               tmp[ii] =
-                   (short) ((tmpdata[2 * ii] << 8) + tmpdata[2 * ii + 1]);
-               tmp[ii] = tmp[ii] - 4096;
-               tmp[ii] = tmp[ii] * 16;
-       }
-
-       for (ii = 0; ii < 3; ii++) {
-               data[2 * ii] = (unsigned char) (tmp[ii] >> 8);
-               data[2 * ii + 1] = (unsigned char) (tmp[ii]);
-       }
-
-       if (read_count % reset_int == 0) {
-               if (reset_mode) {
-                       result =
-                           MLSLSerialWriteSingle(mlsl_handle,
-                                                 pdata->address,
-                                                 MMC314X_REG_ST,
-                                                 MMC314X_CNTL_MODE_RESET);
-                       ERROR_CHECK(result);
-                       reset_mode = 0;
-                       return ML_ERROR_COMPASS_DATA_NOT_READY;
-               } else {
-                       result =
-                           MLSLSerialWriteSingle(mlsl_handle,
-                                                 pdata->address,
-                                                 MMC314X_REG_ST,
-                                                 MMC314X_CNTL_MODE_SET);
-                       ERROR_CHECK(result);
-                       reset_mode = 1;
-                       read_count++;
-                       return ML_ERROR_COMPASS_DATA_NOT_READY;
-               }
-       }
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 MMC314X_REG_ST,
-                                 MMC314X_CNTL_MODE_WAKE_UP);
-       ERROR_CHECK(result);
-       read_count++;
-
-       return ML_SUCCESS;
-}
-
-struct ext_slave_descr mmc314x_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ mmc314x_suspend,
-       /*.resume           = */ mmc314x_resume,
-       /*.read             = */ mmc314x_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "mmc314x",
-       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-       /*.id               = */ COMPASS_ID_MMC314X,
-       /*.reg              = */ 0x01,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
-       /*.range            = */ {400, 0},
-};
-
-struct ext_slave_descr *mmc314x_get_slave_descr(void)
-{
-       return &mmc314x_descr;
-}
-EXPORT_SYMBOL(mmc314x_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/compass/yas529-kernel.c b/drivers/misc/mpu3050/compass/yas529-kernel.c
deleted file mode 100755 (executable)
index 239ab66..0000000
+++ /dev/null
@@ -1,477 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   yas529.c
- *      @brief  Magnetometer setup and handling methods for Yamaha yas529
- *              compass.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#include <linux/i2c.h>
-#endif
-
-#include "mpu.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-acc"
-
-/*----- YAMAHA YAS529 Registers ------*/
-enum YAS_REG {
-       YAS_REG_CMDR            = 0x00, /* 000 < 5 */
-       YAS_REG_XOFFSETR        = 0x20, /* 001 < 5 */
-       YAS_REG_Y1OFFSETR       = 0x40, /* 010 < 5 */
-       YAS_REG_Y2OFFSETR       = 0x60, /* 011 < 5 */
-       YAS_REG_ICOILR          = 0x80, /* 100 < 5 */
-       YAS_REG_CAL             = 0xA0, /* 101 < 5 */
-       YAS_REG_CONFR           = 0xC0, /* 110 < 5 */
-       YAS_REG_DOUTR           = 0xE0  /* 111 < 5 */
-};
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-static long a1;
-static long a2;
-static long a3;
-static long a4;
-static long a5;
-static long a6;
-static long a7;
-static long a8;
-static long a9;
-
-/*****************************************
-    Yamaha I2C access functions
-*****************************************/
-
-static int yas529_sensor_i2c_write(struct i2c_adapter *i2c_adap,
-                                  unsigned char address,
-                                  unsigned int len, unsigned char *data)
-{
-       struct i2c_msg msgs[1];
-       int res;
-
-       if (NULL == data || NULL == i2c_adap)
-               return -EINVAL;
-
-       msgs[0].addr = address;
-       msgs[0].flags = 0;      /* write */
-       msgs[0].buf = (unsigned char *) data;
-       msgs[0].len = len;
-
-       res = i2c_transfer(i2c_adap, msgs, 1);
-       if (res < 1)
-               return res;
-       else
-               return 0;
-}
-
-static int yas529_sensor_i2c_read(struct i2c_adapter *i2c_adap,
-                                 unsigned char address,
-                                 unsigned char reg,
-                                 unsigned int len, unsigned char *data)
-{
-       struct i2c_msg msgs[2];
-       int res;
-
-       if (NULL == data || NULL == i2c_adap)
-               return -EINVAL;
-
-       msgs[0].addr = address;
-       msgs[0].flags = I2C_M_RD;
-       msgs[0].buf = data;
-       msgs[0].len = len;
-
-       res = i2c_transfer(i2c_adap, msgs, 1);
-       if (res < 1)
-               return res;
-       else
-               return 0;
-}
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-int yas529_suspend(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       return result;
-}
-
-int yas529_resume(void *mlsl_handle,
-                 struct ext_slave_descr *slave,
-                 struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       unsigned char dummyData[1] = { 0 };
-       unsigned char dummyRegister = 0;
-       unsigned char rawData[6];
-       unsigned char calData[9];
-
-       short xoffset, y1offset, y2offset;
-       short d2, d3, d4, d5, d6, d7, d8, d9;
-
-       /* YAS529 Application Manual MS-3C - Section 4.4.5 */
-       /* =============================================== */
-       /* Step 1 - register initialization */
-       /* zero initialization coil register - "100 00 000" */
-       dummyData[0] = YAS_REG_ICOILR | 0x00;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       /* zero config register - "110 00 000" */
-       dummyData[0] = YAS_REG_CONFR | 0x00;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-
-       /* Step 2 - initialization coil operation */
-       dummyData[0] = YAS_REG_ICOILR | 0x11;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x01;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x12;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x02;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x13;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x03;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x14;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x04;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x15;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x05;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x16;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x06;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x17;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x07;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x10;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_ICOILR | 0x00;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-
-       /* Step 3 - rough offset measurement */
-       /* Config register - Measurements results - "110 00 000" */
-       dummyData[0] = YAS_REG_CONFR | 0x00;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       /* Measurements command register - Rough offset measurement -
-          "000 00001" */
-       dummyData[0] = YAS_REG_CMDR | 0x01;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       MLOSSleep(2);           /* wait at least 1.5ms */
-
-       /* Measurement data read */
-       result =
-           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
-                                  dummyRegister, 6, rawData);
-       ERROR_CHECK(result);
-       xoffset =
-           (short) ((unsigned short) rawData[5] +
-                    ((unsigned short) rawData[4] & 0x7) * 256) - 5;
-       if (xoffset < 0)
-               xoffset = 0;
-       y1offset =
-           (short) ((unsigned short) rawData[3] +
-                    ((unsigned short) rawData[2] & 0x7) * 256) - 5;
-       if (y1offset < 0)
-               y1offset = 0;
-       y2offset =
-           (short) ((unsigned short) rawData[1] +
-                    ((unsigned short) rawData[0] & 0x7) * 256) - 5;
-       if (y2offset < 0)
-               y2offset = 0;
-
-       /* Step 4 - rough offset setting */
-       /* Set rough offset register values */
-       dummyData[0] = YAS_REG_XOFFSETR | xoffset;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_Y1OFFSETR | y1offset;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       dummyData[0] = YAS_REG_Y2OFFSETR | y2offset;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-
-       /* CAL matrix read (first read is invalid) */
-       /* Config register - CAL register read - "110 01 000" */
-       dummyData[0] = YAS_REG_CONFR | 0x08;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       /* CAL data read */
-       result =
-           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
-                                  dummyRegister, 9, calData);
-       ERROR_CHECK(result);
-       /* Config register - CAL register read - "110 01 000" */
-       dummyData[0] = YAS_REG_CONFR | 0x08;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       /* CAL data read */
-       result =
-           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
-                                  dummyRegister, 9, calData);
-       ERROR_CHECK(result);
-
-       /* Calculate coefficients of the sensitivity corrcetion matrix */
-#if 1                          /* production sensor */
-       a1 = 100;
-       d2 = (calData[0] & 0xFC) >> 2;  /* [71..66] 6bit */
-       a2 = (short) (d2 - 32);
-       /* [65..62] 4bit */
-       d3 = ((calData[0] & 0x03) << 2) | ((calData[1] & 0xC0) >> 6);
-       a3 = (short) (d3 - 8);
-       d4 = (calData[1] & 0x3F);       /* [61..56] 6bit */
-       a4 = (short) (d4 - 32);
-       d5 = (calData[2] & 0xFC) >> 2;  /* [55..50] 6bit */
-       a5 = (short) (d5 - 32) + 70;
-       /* [49..44] 6bit */
-       d6 = ((calData[2] & 0x03) << 4) | ((calData[3] & 0xF0) >> 4);
-       a6 = (short) (d6 - 32);
-       /* [43..38] 6bit */
-       d7 = ((calData[3] & 0x0F) << 2) | ((calData[4] & 0xC0) >> 6);
-       a7 = (short) (d7 - 32);
-       d8 = (calData[4] & 0x3F);       /* [37..32] 6bit */
-       a8 = (short) (d8 - 32);
-       d9 = (calData[5] & 0xFE) >> 1;  /* [31..25] 7bit */
-       a9 = (short) (d9 - 64) + 130;
-#else                          /* evaluation sensor */
-       a1 = 1.0f;
-       /* [71..66] 6bit */
-       d2 = (calData[0] & 0xFC) >> 2;
-       a2 = (short) d2;
-       /* [65..60] 6bit */
-       d3 = ((calData[0] & 0x03) << 4) | ((calData[1] & 0xF0) >> 4);
-       a3 = (short) d3;
-       /* [59..54] 6bit */
-       d4 = ((calData[1] & 0x0F) << 2) | ((calData[2] & 0xC0) >> 6);
-       a4 = (short) d4;
-       /* [53..48] 6bit */
-       d5 = (calData[2] & 0x3F);
-       a5 = (short) (d5 + 70);
-       /* [47..42] 6bit */
-       d6 = ((calData[3] & 0xFC) >> 2);
-       a6 = (short) d6;
-       /* [41..36] 6bit */
-       d7 = ((calData[3] & 0x03) << 4) | ((calData[4] & 0xF0) >> 4);
-       a7 = (short) d7;
-       /* [35..30] 6bit */
-       d8 = ((calData[4] & 0x0F) << 2) | ((calData[5] & 0xC0) >> 6);
-       a8 = (short) d8;
-       /* [29..24] 6bit */
-       d9 = (calData[5] & 0x3F);
-       a9 = (short) (d9 + 150);
-#endif
-
-       return result;
-}
-
-int yas529_read(void *mlsl_handle,
-               struct ext_slave_descr *slave,
-               struct ext_slave_platform_data *pdata, unsigned char *data)
-{
-       unsigned char stat;
-       unsigned char rawData[6];
-       unsigned char dummyData[1] = { 0 };
-       unsigned char dummyRegister = 0;
-       tMLError result = ML_SUCCESS;
-       short SX, SY1, SY2, SY, SZ;
-       short row1fixed, row2fixed, row3fixed;
-
-       /* Config register - Measurements results - "110 00 000" */
-       dummyData[0] = YAS_REG_CONFR | 0x00;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       /* Measurements command register - Normal magnetic field measurement -
-          "000 00000" */
-       dummyData[0] = YAS_REG_CMDR | 0x00;
-       result =
-           yas529_sensor_i2c_write(mlsl_handle, pdata->address, 1,
-                                   dummyData);
-       ERROR_CHECK(result);
-       MLOSSleep(10);
-       /* Measurement data read */
-       result =
-           yas529_sensor_i2c_read(mlsl_handle, pdata->address,
-                                  dummyRegister, 6,
-                                  (unsigned char *) &rawData);
-       ERROR_CHECK(result);
-
-       stat = rawData[0] & 0x80;
-       if (stat == 0x00) {
-               /* Extract raw data */
-               SX = (short) ((unsigned short) rawData[5] +
-                             ((unsigned short) rawData[4] & 0x7) * 256);
-               SY1 =
-                   (short) ((unsigned short) rawData[3] +
-                            ((unsigned short) rawData[2] & 0x7) * 256);
-               SY2 =
-                   (short) ((unsigned short) rawData[1] +
-                            ((unsigned short) rawData[0] & 0x7) * 256);
-               if ((SX <= 1) || (SY1 <= 1) || (SY2 <= 1))
-                       return ML_ERROR_COMPASS_DATA_UNDERFLOW;
-               if ((SX >= 1024) || (SY1 >= 1024) || (SY2 >= 1024))
-                       return ML_ERROR_COMPASS_DATA_OVERFLOW;
-               /* Convert to XYZ axis */
-               SX = -1 * SX;
-               SY = SY2 - SY1;
-               SZ = SY1 + SY2;
-
-               /* Apply sensitivity correction matrix */
-               row1fixed =
-                   (short) ((a1 * SX + a2 * SY + a3 * SZ) >> 7) * 41;
-               row2fixed =
-                   (short) ((a4 * SX + a5 * SY + a6 * SZ) >> 7) * 41;
-               row3fixed =
-                   (short) ((a7 * SX + a8 * SY + a9 * SZ) >> 7) * 41;
-
-               data[0] = row1fixed >> 8;
-               data[1] = row1fixed & 0xFF;
-               data[2] = row2fixed >> 8;
-               data[3] = row2fixed & 0xFF;
-               data[4] = row3fixed >> 8;
-               data[5] = row3fixed & 0xFF;
-
-               return ML_SUCCESS;
-       } else {
-               return ML_ERROR_COMPASS_DATA_NOT_READY;
-       }
-}
-
-struct ext_slave_descr yas529_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ yas529_suspend,
-       /*.resume           = */ yas529_resume,
-       /*.read             = */ yas529_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "yas529",
-       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-       /*.id               = */ COMPASS_ID_YAS529,
-       /*.reg              = */ 0x06,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
-       /*.range            = */ {19660, 8000},
-};
-
-struct ext_slave_descr *yas529_get_slave_descr(void)
-{
-       return &yas529_descr;
-}
-EXPORT_SYMBOL(yas529_get_slave_descr);
-
-/**
- *  @}
- */
diff --git a/drivers/misc/mpu3050/compass/yas530-kernel.c b/drivers/misc/mpu3050/compass/yas530-kernel.c
deleted file mode 100755 (executable)
index f6dbb56..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
-  */
- /**
-  *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
-  *  @brief      Provides the interface to setup and handle an accelerometers
-  *              connected to the secondary I2C interface of the gyroscope.
-  *
-  *  @{
-  *      @file   yas530.c
-  *      @brief  Magnetometer setup and handling methods for Yamaha yas530
-  *              compass.
-  */
-
- /* ------------------ */
- /* - Include Files. - */
- /* ------------------ */
-
-#include "mpu.h"
-#include "mltypes.h"
-
-#include "mlsl.h"
-#include "mlos.h"
-
-#ifdef __KERNEL__
-#include <asm/uaccess.h>
-#include <asm/io.h>
-#include <i2c.h>
-#endif
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-yas530:"
-
-
-extern int geomagnetic_api_resume(void);
-extern int geomagnetic_api_suspend(void);
-extern int geomagnetic_api_read(int *xyz, int *raw, int *xy1y2, int *accuracy);
-
- /*****************************************
-     Compass Initialization Functions
- *****************************************/
-
-static int
-yas530_suspend
-(
-   void *mlsl_handle,
-   struct ext_slave_descr *slave,
-   struct ext_slave_platform_data *pdata
-)
-{
-  int result = ML_SUCCESS;
-
-  geomagnetic_api_suspend();
-
-  return result;
-}
-
-
-static int
-yas530_resume
-(
-   void *mlsl_handle,
-   struct ext_slave_descr *slave,
-   struct ext_slave_platform_data *pdata
-)
-{
-  geomagnetic_api_resume();
-  return ML_SUCCESS;
-}
-
-
-static int
-yas530_read
-(
-     void *mlsl_handle,
-     struct ext_slave_descr *slave,
-     struct ext_slave_platform_data *pdata,
-     unsigned char *data
-)
-{
-  int xyz[3];
-  int raw[3];
-  short rawfixed[3];
-  int xy1y2[3];
-  int accuracy;
-
-  geomagnetic_api_read(xyz, raw, xy1y2, &accuracy);
-
-  rawfixed[0] = (short) (xyz[0]/100);
-  rawfixed[1] = (short) (xyz[1]/100);
-  rawfixed[2] = (short) (xyz[2]/100);
-
-  data[0] = rawfixed[0] >> 8;
-  data[1] = rawfixed[0] & 0xFF;
-  data[2] = rawfixed[1] >> 8;
-  data[3] = rawfixed[1] & 0xFF;
-  data[4] = rawfixed[2] >> 8;
-  data[5] = rawfixed[2] & 0xFF;
-
-  return ML_SUCCESS;
-}
-
-
-
-struct ext_slave_descr yas530_descr = {
-     /*.init          = */ NULL,
-     /*.exit          = */ NULL,
-     /*.suspend          = */ yas530_suspend,
-     /*.resume           = */ yas530_resume,
-     /*.read             = */ yas530_read,
-     /*.config           = */ NULL,
-     /*.name             = */ "yas530",
-     /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-     /*.id               = */ COMPASS_ID_YAS530,
-     /*.reg              = */ 0x06,
-     /*.len              = */ 6,
-     /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
-     /*.range            = */ {3276, 8001},
-};
-
-struct ext_slave_descr *yas530_get_slave_descr(void)
-{
-     return &yas530_descr;
-}
-
-#ifdef __KERNEL__
- EXPORT_SYMBOL(yas530_get_slave_descr);
-#endif
-
- /**
-  *  @}
- **/
diff --git a/drivers/misc/mpu3050/compass/yas530.c b/drivers/misc/mpu3050/compass/yas530.c
deleted file mode 100755 (executable)
index 9fc9acb..0000000
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-/**
- *  @defgroup   ACCELDL (Motion Library - Accelerometer Driver Layer)
- *  @brief      Provides the interface to setup and handle an accelerometers
- *              connected to the secondary I2C interface of the gyroscope.
- *
- *  @{
- *      @file   yas530.c
- *      @brief  Magnetometer setup and handling methods for Yamaha yas530
- *              compass.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#ifdef __KERNEL__
-#include <linux/module.h>
-#endif
-
-#include "mpu.h"
-#include "mlsl.h"
-#include "mlos.h"
-
-#include <log.h>
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "MPL-compass"
-
-/*----- YAMAHA YAS529 Registers ------*/
-#define YAS530_REGADDR_DEVICE_ID          (0x80)
-#define YAS530_REGADDR_ACTUATE_INIT_COIL  (0x81)
-#define YAS530_REGADDR_MEASURE_COMMAND    (0x82)
-#define YAS530_REGADDR_CONFIG             (0x83)
-#define YAS530_REGADDR_MEASURE_INTERVAL   (0x84)
-#define YAS530_REGADDR_OFFSET_X           (0x85)
-#define YAS530_REGADDR_OFFSET_Y1          (0x86)
-#define YAS530_REGADDR_OFFSET_Y2          (0x87)
-#define YAS530_REGADDR_TEST1              (0x88)
-#define YAS530_REGADDR_TEST2              (0x89)
-#define YAS530_REGADDR_CAL                (0x90)
-#define YAS530_REGADDR_MEASURE_DATA       (0xb0)
-
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-static int Cx, Cy1, Cy2;
-static int /*a1, */a2, a3, a4, a5, a6, a7, a8, a9;
-static int k;
-
-static char dx, dy1, dy2;
-static char d2, d3, d4, d5, d6, d7, d8, d9, d0;
-static char dck;
-
-/*****************************************
-    Accelerometer Initialization Functions
-*****************************************/
-
-int set_hardware_offset(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata,
-                  char offset_x, char offset_y1, char offset_y2)
-{
-       char data;
-       int result = ML_SUCCESS;
-
-       data = offset_x & 0x3f;
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-               YAS530_REGADDR_OFFSET_X, data);
-       ERROR_CHECK(result);
-
-       data = offset_y1 & 0x3f;
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-               YAS530_REGADDR_OFFSET_Y1, data);
-       ERROR_CHECK(result);
-
-       data = offset_y2 & 0x3f;
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-               YAS530_REGADDR_OFFSET_Y2, data);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-int set_measure_command(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata,
-                  int ldtc, int fors, int dlymes)
-{
-       int result = ML_SUCCESS;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-               YAS530_REGADDR_MEASURE_COMMAND, 0x01);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-int measure_normal(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata,
-                  int *busy, unsigned short *t,
-                  unsigned short *x, unsigned short *y1, unsigned short *y2)
-{
-       unsigned char data[8];
-       unsigned short b, to, xo, y1o, y2o;
-       int result;
-
-       result = set_measure_command(mlsl_handle, slave, pdata, 0, 0, 0);
-       MLOSSleep(2);
-
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-               YAS530_REGADDR_MEASURE_DATA, 8, data);
-       ERROR_CHECK(result);
-       MLOSSleep(2);
-
-       b = (data[0]>>7) & 0x01;
-       to = ((data[0]<<2) & 0x1fc) | ((data[1]>>6) & 0x03);
-       xo = ((data[2]<<5) & 0xfe0) | ((data[3]>>3) & 0x1f);
-       y1o = ((data[4]<<5) & 0xfe0) | ((data[5]>>3) & 0x1f);
-       y2o = ((data[6]<<5) & 0xfe0) | ((data[7]>>3) & 0x1f);
-
-       *busy = b;
-       *t = to;
-       *x = xo;
-       *y1 = y1o;
-       *y2 = y2o;
-
-       return result;
-}
-
-int check_offset(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata,
-                  char offset_x, char offset_y1, char offset_y2,
-                  int *flag_x, int *flag_y1, int *flag_y2)
-{
-       int result;
-       int busy;
-       short t, x, y1, y2;
-
-       result = set_hardware_offset(mlsl_handle, slave, pdata,
-               offset_x, offset_y1, offset_y2);
-       ERROR_CHECK(result);
-
-       result = measure_normal(mlsl_handle, slave, pdata,
-               &busy, &t, &x, &y1, &y2);
-       ERROR_CHECK(result);
-
-       *flag_x = 0;
-       *flag_y1 = 0;
-       *flag_y2 = 0;
-
-       if (x > 2048)
-               *flag_x = 1;
-       if (y1 > 2048)
-               *flag_y1 = 1;
-       if (y2 > 2048)
-               *flag_y2 = 1;
-       if (x < 2048)
-               *flag_x = -1;
-       if (y1 < 2048)
-               *flag_y1 = -1;
-       if (y2 < 2048)
-               *flag_y2 = -1;
-
-       return result;
-}
-
-int measure_and_set_offset(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata,
-                  char *offset)
-{
-       int i;
-       int result = ML_SUCCESS;
-       char offset_x = 0, offset_y1 = 0, offset_y2 = 0;
-       int flag_x = 0, flag_y1 = 0, flag_y2 = 0;
-       static const int correct[5] = {16, 8, 4, 2, 1};
-
-       for (i = 0; i < 5; i++) {
-               result = check_offset(mlsl_handle, slave, pdata,
-                       offset_x, offset_y1, offset_y2,
-                       &flag_x, &flag_y1, &flag_y2);
-               ERROR_CHECK(result);
-
-               if (flag_x)
-                       offset_x += flag_x * correct[i];
-               if (flag_y1)
-                       offset_y1 += flag_y1 * correct[i];
-               if (flag_y2)
-                       offset_y2 += flag_y2 * correct[i];
-       }
-
-       result = set_hardware_offset(mlsl_handle, slave, pdata,
-               offset_x, offset_y1, offset_y2);
-       ERROR_CHECK(result);
-
-       offset[0] = offset_x;
-       offset[1] = offset_y1;
-       offset[2] = offset_y2;
-
-       return result;
-}
-
-void coordinate_conversion(short x, short y1, short y2, short t,
-                                                 int *xo, int *yo, int *zo)
-{
-       int sx, sy1, sy2, sy, sz;
-       int hx, hy, hz;
-
-       sx  = x - (Cx  * t) / 100;
-       sy1 = y1 - (Cy1 * t) / 100;
-       sy2 = y2 - (Cy2 * t) / 100;
-
-       sy = sy1 - sy2;
-       sz = -sy1 - sy2;
-
-       hx = k * ((100 * sx + a2 * sy + a3 * sz) / 10);
-       hy = k * ((a4 * sx + a5 * sy + a6 * sz) / 10);
-       hz = k * ((a7 * sx + a8 * sy + a9 * sz) / 10);
-
-       *xo = hx;
-       *yo = hy;
-       *zo = hz;
-}
-
-int yas530_suspend(void *mlsl_handle,
-                  struct ext_slave_descr *slave,
-                  struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       return result;
-}
-
-int yas530_resume(void *mlsl_handle,
-                 struct ext_slave_descr *slave,
-                 struct ext_slave_platform_data *pdata)
-{
-       int result = ML_SUCCESS;
-
-       unsigned char dummyData = 0x00;
-       char offset[3] = {0, 0, 0};
-       unsigned char data[16];
-       unsigned char read_reg[1];
-
-       /* =============================================== */
-
-       /* Step 1 - Test register initialization */
-       dummyData = 0x00;
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-               YAS530_REGADDR_TEST1, dummyData);
-       ERROR_CHECK(result);
-
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-                                 YAS530_REGADDR_TEST2, dummyData);
-       ERROR_CHECK(result);
-
-       /* Device ID read  */
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-               YAS530_REGADDR_DEVICE_ID, 1, read_reg);
-
-       /*Step 2 Read the CAL register */
-       /* CAL data read */
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-               YAS530_REGADDR_CAL, 16, data);
-       ERROR_CHECK(result);
-       /* CAL data Second Read */
-       result = MLSLSerialRead(mlsl_handle, pdata->address,
-               YAS530_REGADDR_CAL, 16, data);
-       ERROR_CHECK(result);
-
-       /*Cal data */
-       dx = data[0];
-       dy1 = data[1];
-       dy2 = data[2];
-       d2 = (data[3]>>2) & 0x03f;
-       d3 = ((data[3]<<2) & 0x0c) | ((data[4]>>6) & 0x03);
-       d4 = data[4] & 0x3f;
-       d5 = (data[5]>>2) & 0x3f;
-       d6 = ((data[5]<<4) & 0x30) | ((data[6]>>4) & 0x0f);
-       d7 = ((data[6]<<3) & 0x78) | ((data[7]>>5) & 0x07);
-       d8 = ((data[7]<<1) & 0x3e) | ((data[8]>>7) & 0x01);
-       d9 = ((data[8]<<1) & 0xfe) | ((data[9]>>7) & 0x01);
-       d0 = (data[9]>>2) & 0x1f;
-       dck = ((data[9]<<1) & 0x06) | ((data[10]>>7) & 0x01);
-
-
-       /*Correction Data */
-       Cx = dx * 6 - 768;
-       Cy1 = dy1 * 6 - 768;
-       Cy2 = dy2 * 6 - 768;
-       a2 = d2 - 32;
-       a3 = d3 - 8;
-       a4 = d4 - 32;
-       a5 = d5 + 38;
-       a6 = d6 - 32;
-       a7 = d7 - 64;
-       a8 = d8 - 32;
-       a9 = d9;
-       k = d0 + 10;
-
-       /*Obtain the [49:47] bits */
-       dck &= 0x07;
-
-       /*Step 3 : Storing the CONFIG with the CLK value */
-       dummyData = 0x00 | (dck << 2);
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-               YAS530_REGADDR_CONFIG, dummyData);
-       ERROR_CHECK(result);
-
-       /*Step 4 : Set Acquisition Interval Register */
-       dummyData = 0x00;
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-               YAS530_REGADDR_MEASURE_INTERVAL, dummyData);
-       ERROR_CHECK(result);
-
-       /*Step 5 : Reset Coil */
-       dummyData = 0x00;
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->address,
-               YAS530_REGADDR_ACTUATE_INIT_COIL, dummyData);
-       ERROR_CHECK(result);
-
-       /* Offset Measurement and Set*/
-       result = measure_and_set_offset(mlsl_handle, slave, pdata, offset);
-       ERROR_CHECK(result);
-
-       return result;
-}
-
-int yas530_read(void *mlsl_handle,
-               struct ext_slave_descr *slave,
-               struct ext_slave_platform_data *pdata, unsigned char *data)
-{
-       int result = ML_SUCCESS;
-
-       int busy;
-       short t, x, y1, y2;
-       int xyz[3];
-       short rawfixed[3];
-
-       result = measure_normal(mlsl_handle, slave, pdata,
-                       &busy, &t, &x, &y1, &y2);
-       ERROR_CHECK(result);
-
-       coordinate_conversion(x, y1, y2, t, &xyz[0], &xyz[1], &xyz[2]);
-
-       rawfixed[0] = (short) (xyz[0]/100);
-       rawfixed[1] = (short) (xyz[1]/100);
-       rawfixed[2] = (short) (xyz[2]/100);
-
-       data[0] = rawfixed[0]>>8;
-       data[1] = rawfixed[0] & 0xFF;
-       data[2] = rawfixed[1]>>8;
-       data[3] = rawfixed[1] & 0xFF;
-       data[4] = rawfixed[2]>>8;
-       data[5] = rawfixed[2] & 0xFF;
-
-       return result;
-}
-
-struct ext_slave_descr yas530_descr = {
-       /*.init             = */ NULL,
-       /*.exit             = */ NULL,
-       /*.suspend          = */ yas530_suspend,
-       /*.resume           = */ yas530_resume,
-       /*.read             = */ yas530_read,
-       /*.config           = */ NULL,
-       /*.get_config       = */ NULL,
-       /*.name             = */ "yas530",
-       /*.type             = */ EXT_SLAVE_TYPE_COMPASS,
-       /*.id               = */ COMPASS_ID_YAS530,
-       /*.reg              = */ 0x06,
-       /*.len              = */ 6,
-       /*.endian           = */ EXT_SLAVE_BIG_ENDIAN,
-       /*.range            = */ {3276, 8001},
-};
-
-struct ext_slave_descr *yas530_get_slave_descr(void)
-{
-       return &yas530_descr;
-}
-EXPORT_SYMBOL(yas530_get_slave_descr);
-
-/**
- *  @}
-**/
diff --git a/drivers/misc/mpu3050/log.h b/drivers/misc/mpu3050/log.h
deleted file mode 100755 (executable)
index f2f9ea7..0000000
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (C) 2010 InvenSense Inc
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/*
- * C/C++ logging functions.  See the logging documentation for API details.
- *
- * We'd like these to be available from C code (in case we import some from
- * somewhere), so this has a C interface.
- *
- * The output will be correct when the log file is shared between multiple
- * threads and/or multiple processes so long as the operating system
- * supports O_APPEND.  These calls have mutex-protected data structures
- * and so are NOT reentrant.  Do not use MPL_LOG in a signal handler.
- */
-#ifndef _LIBS_CUTILS_MPL_LOG_H
-#define _LIBS_CUTILS_MPL_LOG_H
-
-#include <stdarg.h>
-
-#ifdef ANDROID
-#include <utils/Log.h>         /* For the LOG macro */
-#endif
-
-#ifdef __KERNEL__
-#include <linux/kernel.h>
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Normally we strip MPL_LOGV (VERBOSE messages) from release builds.
- * You can modify this (for example with "#define MPL_LOG_NDEBUG 0"
- * at the top of your source file) to change that behavior.
- */
-#ifndef MPL_LOG_NDEBUG
-#ifdef NDEBUG
-#define MPL_LOG_NDEBUG 1
-#else
-#define MPL_LOG_NDEBUG 0
-#endif
-#endif
-
-#ifdef __KERNEL__
-#define MPL_LOG_UNKNOWN MPL_LOG_VERBOSE
-#define MPL_LOG_DEFAULT KERN_DEFAULT
-#define MPL_LOG_VERBOSE KERN_CONT
-#define MPL_LOG_DEBUG   KERN_NOTICE
-#define MPL_LOG_INFO    KERN_INFO
-#define MPL_LOG_WARN    KERN_WARNING
-#define MPL_LOG_ERROR   KERN_ERR
-#define MPL_LOG_SILENT  MPL_LOG_VERBOSE
-
-#else
-       /* Based off the log priorities in android
-          /system/core/include/android/log.h */
-#define MPL_LOG_UNKNOWN                (0)
-#define MPL_LOG_DEFAULT                (1)
-#define MPL_LOG_VERBOSE                (2)
-#define MPL_LOG_DEBUG          (3)
-#define MPL_LOG_INFO           (4)
-#define MPL_LOG_WARN           (5)
-#define MPL_LOG_ERROR          (6)
-#define MPL_LOG_SILENT         (8)
-#endif
-
-
-/*
- * This is the local tag used for the following simplified
- * logging macros.  You can change this preprocessor definition
- * before using the other macros to change the tag.
- */
-#ifndef MPL_LOG_TAG
-#ifdef __KERNEL__
-#define MPL_LOG_TAG
-#else
-#define MPL_LOG_TAG NULL
-#endif
-#endif
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Simplified macro to send a verbose log message using the current MPL_LOG_TAG.
- */
-#ifndef MPL_LOGV
-#if MPL_LOG_NDEBUG
-#define MPL_LOGV(fmt, ...)                                             \
-       do {                                                            \
-               if (0)                                                  \
-                       MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, fmt, ##__VA_ARGS__);\
-       } while (0)
-#else
-#define MPL_LOGV(fmt, ...) MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
-#endif
-#endif
-
-#ifndef CONDITION
-#define CONDITION(cond)     ((cond) != 0)
-#endif
-
-#ifndef MPL_LOGV_IF
-#if MPL_LOG_NDEBUG
-#define MPL_LOGV_IF(cond, fmt, ...)  \
-       do { if (0) MPL_LOG(fmt, ##__VA_ARGS__); } while (0)
-#else
-#define MPL_LOGV_IF(cond, fmt, ...) \
-       ((CONDITION(cond))                                              \
-               ? MPL_LOG(LOG_VERBOSE, MPL_LOG_TAG, fmt, ##__VA_ARGS__) \
-               : (void)0)
-#endif
-#endif
-
-/*
- * Simplified macro to send a debug log message using the current MPL_LOG_TAG.
- */
-#ifndef MPL_LOGD
-#define MPL_LOGD(fmt, ...) MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
-#endif
-
-#ifndef MPL_LOGD_IF
-#define MPL_LOGD_IF(cond, fmt, ...) \
-       ((CONDITION(cond))                                             \
-               ? MPL_LOG(LOG_DEBUG, MPL_LOG_TAG, fmt, ##__VA_ARGS__)  \
-               : (void)0)
-#endif
-
-/*
- * Simplified macro to send an info log message using the current MPL_LOG_TAG.
- */
-#ifndef MPL_LOGI
-#define MPL_LOGI(fmt, ...) MPL_LOG(LOG_INFO, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
-#endif
-
-#ifndef MPL_LOGI_IF
-#define MPL_LOGI_IF(cond, fmt, ...) \
-       ((CONDITION(cond))                                              \
-               ? MPL_LOG(LOG_INFO, MPL_LOG_TAG, fmt, ##__VA_ARGS__)   \
-               : (void)0)
-#endif
-
-/*
- * Simplified macro to send a warning log message using the current MPL_LOG_TAG.
- */
-#ifndef MPL_LOGW
-#ifdef __KERNEL__
-#define MPL_LOGW(fmt, ...) printk(KERN_WARNING MPL_LOG_TAG fmt, ##__VA_ARGS__)
-#else
-#define MPL_LOGW(fmt, ...) MPL_LOG(LOG_WARN, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
-#endif
-#endif
-
-#ifndef MPL_LOGW_IF
-#define MPL_LOGW_IF(cond, fmt, ...) \
-       ((CONDITION(cond))                                             \
-               ? MPL_LOG(LOG_WARN, MPL_LOG_TAG, fmt, ##__VA_ARGS__)   \
-               : (void)0)
-#endif
-
-/*
- * Simplified macro to send an error log message using the current MPL_LOG_TAG.
- */
-#ifndef MPL_LOGE
-#ifdef __KERNEL__
-#define MPL_LOGE(fmt, ...) printk(KERN_ERR MPL_LOG_TAG fmt, ##__VA_ARGS__)
-#else
-#define MPL_LOGE(fmt, ...) MPL_LOG(LOG_ERROR, MPL_LOG_TAG, fmt, ##__VA_ARGS__)
-#endif
-#endif
-
-#ifndef MPL_LOGE_IF
-#define MPL_LOGE_IF(cond, fmt, ...) \
-       ((CONDITION(cond))                                             \
-               ? MPL_LOG(LOG_ERROR, MPL_LOG_TAG, fmt, ##__VA_ARGS__)  \
-               : (void)0)
-#endif
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Log a fatal error.  If the given condition fails, this stops program
- * execution like a normal assertion, but also generating the given message.
- * It is NOT stripped from release builds.  Note that the condition test
- * is -inverted- from the normal assert() semantics.
- */
-#define MPL_LOG_ALWAYS_FATAL_IF(cond, fmt, ...) \
-       ((CONDITION(cond))                                         \
-               ? ((void)android_printAssert(#cond, MPL_LOG_TAG,   \
-                                               fmt, ##__VA_ARGS__))    \
-               : (void)0)
-
-#define MPL_LOG_ALWAYS_FATAL(fmt, ...) \
-       (((void)android_printAssert(NULL, MPL_LOG_TAG, fmt, ##__VA_ARGS__)))
-
-/*
- * Versions of MPL_LOG_ALWAYS_FATAL_IF and MPL_LOG_ALWAYS_FATAL that
- * are stripped out of release builds.
- */
-#if MPL_LOG_NDEBUG
-#define MPL_LOG_FATAL_IF(cond, fmt, ...)                               \
-       do {                                                            \
-               if (0)                                                  \
-                       MPL_LOG_ALWAYS_FATAL_IF(cond, fmt, ##__VA_ARGS__); \
-       } while (0)
-#define MPL_LOG_FATAL(fmt, ...)                                                \
-       do {                                                            \
-               if (0)                                                  \
-                       MPL_LOG_ALWAYS_FATAL(fmt, ##__VA_ARGS__)        \
-       } while (0)
-#else
-#define MPL_LOG_FATAL_IF(cond, fmt, ...) \
-       MPL_LOG_ALWAYS_FATAL_IF(cond, fmt, ##__VA_ARGS__)
-#define MPL_LOG_FATAL(fmt, ...) \
-       MPL_LOG_ALWAYS_FATAL(fmt, ##__VA_ARGS__)
-#endif
-
-/*
- * Assertion that generates a log message when the assertion fails.
- * Stripped out of release builds.  Uses the current MPL_LOG_TAG.
- */
-#define MPL_LOG_ASSERT(cond, fmt, ...)                 \
-       MPL_LOG_FATAL_IF(!(cond), fmt, ##__VA_ARGS__)
-
-/* --------------------------------------------------------------------- */
-
-/*
- * Basic log message macro.
- *
- * Example:
- *  MPL_LOG(MPL_LOG_WARN, NULL, "Failed with error %d", errno);
- *
- * The second argument may be NULL or "" to indicate the "global" tag.
- */
-#ifndef MPL_LOG
-#define MPL_LOG(priority, tag, fmt, ...)               \
-       MPL_LOG_PRI(priority, tag, fmt, ##__VA_ARGS__)
-#endif
-
-/*
- * Log macro that allows you to specify a number for the priority.
- */
-#ifndef MPL_LOG_PRI
-#ifdef ANDROID
-#define MPL_LOG_PRI(priority, tag, fmt, ...) \
-       LOG(priority, tag, fmt, ##__VA_ARGS__)
-#elif defined __KERNEL__
-#define MPL_LOG_PRI(priority, tag, fmt, ...) \
-       pr_debug(MPL_##priority tag fmt, ##__VA_ARGS__)
-#else
-#define MPL_LOG_PRI(priority, tag, fmt, ...) \
-       _MLPrintLog(MPL_##priority, tag, fmt, ##__VA_ARGS__)
-#endif
-#endif
-
-/*
- * Log macro that allows you to pass in a varargs ("args" is a va_list).
- */
-#ifndef MPL_LOG_PRI_VA
-#ifdef ANDROID
-#define MPL_LOG_PRI_VA(priority, tag, fmt, args) \
-    android_vprintLog(priority, NULL, tag, fmt, args)
-#elif defined __KERNEL__
-/* not allowed in the Kernel because there is no dev_dbg that takes a va_list */
-#else
-#define MPL_LOG_PRI_VA(priority, tag, fmt, args) \
-    _MLPrintVaLog(priority, NULL, tag, fmt, args)
-#endif
-#endif
-
-/* --------------------------------------------------------------------- */
-
-/*
- * ===========================================================================
- *
- * The stuff in the rest of this file should not be used directly.
- */
-
-#ifndef ANDROID
-       int _MLPrintLog(int priority, const char *tag, const char *fmt,
-                       ...);
-       int _MLPrintVaLog(int priority, const char *tag, const char *fmt,
-                         va_list args);
-/* Final implementation of actual writing to a character device */
-       int _MLWriteLog(const char *buf, int buflen);
-#endif
-
-#ifdef __cplusplus
-}
-#endif
-#endif                         /* _LIBS_CUTILS_MPL_LOG_H */
diff --git a/drivers/misc/mpu3050/mldl_cfg.c b/drivers/misc/mpu3050/mldl_cfg.c
deleted file mode 100755 (executable)
index 9cc4cf6..0000000
+++ /dev/null
@@ -1,1739 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @addtogroup MLDL
- *
- *  @{
- *      @file   mldl_cfg.c
- *      @brief  The Motion Library Driver Layer.
- */
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#include <stddef.h>
-
-#include "mldl_cfg.h"
-#include "mpu.h"
-
-#include "mlsl.h"
-#include "mlos.h"
-
-#include "log.h"
-#undef MPL_LOG_TAG
-#define MPL_LOG_TAG "mldl_cfg:"
-
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-#ifdef M_HW
-#define SLEEP   0
-#define WAKE_UP 7
-#define RESET   1
-#define STANDBY 1
-#else
-/* licteral significance of all parameters used in MLDLPowerMgmtMPU */
-#define SLEEP   1
-#define WAKE_UP 0
-#define RESET   1
-#define STANDBY 1
-#endif
-
-/*---------------------*/
-/*-    Prototypes.    -*/
-/*---------------------*/
-
-/*----------------------*/
-/*-  Static Functions. -*/
-/*----------------------*/
-
-static int dmp_stop(struct mldl_cfg *mldl_cfg, void *gyro_handle)
-{
-       unsigned char userCtrlReg;
-       int result;
-
-       if (!mldl_cfg->dmp_is_running)
-               return ML_SUCCESS;
-
-       result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
-                               MPUREG_USER_CTRL, 1, &userCtrlReg);
-       ERROR_CHECK(result);
-       userCtrlReg = (userCtrlReg & (~BIT_FIFO_EN)) | BIT_FIFO_RST;
-       userCtrlReg = (userCtrlReg & (~BIT_DMP_EN)) | BIT_DMP_RST;
-
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                                      MPUREG_USER_CTRL, userCtrlReg);
-       ERROR_CHECK(result);
-       mldl_cfg->dmp_is_running = 0;
-
-       return result;
-
-}
-/**
- * @brief Starts the DMP running
- *
- * @return ML_SUCCESS or non-zero error code
- */
-static int dmp_start(struct mldl_cfg *pdata, void *mlsl_handle)
-{
-       unsigned char userCtrlReg;
-       int result;
-
-       if (pdata->dmp_is_running == pdata->dmp_enable)
-               return ML_SUCCESS;
-
-       result = MLSLSerialRead(mlsl_handle, pdata->addr,
-                               MPUREG_USER_CTRL, 1, &userCtrlReg);
-       ERROR_CHECK(result);
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                      MPUREG_USER_CTRL,
-                                      ((userCtrlReg & (~BIT_FIFO_EN))
-                                               |   BIT_FIFO_RST));
-       ERROR_CHECK(result);
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                      MPUREG_USER_CTRL, userCtrlReg);
-       ERROR_CHECK(result);
-
-       result = MLSLSerialRead(mlsl_handle, pdata->addr,
-                               MPUREG_USER_CTRL, 1, &userCtrlReg);
-       ERROR_CHECK(result);
-
-       if (pdata->dmp_enable)
-               userCtrlReg |= BIT_DMP_EN;
-       else
-               userCtrlReg &= ~BIT_DMP_EN;
-
-       if (pdata->fifo_enable)
-               userCtrlReg |= BIT_FIFO_EN;
-       else
-               userCtrlReg &= ~BIT_FIFO_EN;
-
-       userCtrlReg |= BIT_DMP_RST;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                      MPUREG_USER_CTRL, userCtrlReg);
-       ERROR_CHECK(result);
-       pdata->dmp_is_running = pdata->dmp_enable;
-
-       return result;
-}
-
-/**
- *  @brief  enables/disables the I2C bypass to an external device
- *          connected to MPU's secondary I2C bus.
- *  @param  enable
- *              Non-zero to enable pass through.
- *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
- */
-static int MLDLSetI2CBypass(struct mldl_cfg *mldl_cfg,
-                           void *mlsl_handle,
-                           unsigned char enable)
-{
-       unsigned char b;
-       int result;
-
-       if ((mldl_cfg->gyro_is_bypassed && enable) ||
-           (!mldl_cfg->gyro_is_bypassed && !enable))
-               return ML_SUCCESS;
-
-       /*---- get current 'USER_CTRL' into b ----*/
-       result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
-                               MPUREG_USER_CTRL, 1, &b);
-       ERROR_CHECK(result);
-
-       b &= ~BIT_AUX_IF_EN;
-
-       if (!enable) {
-               result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
-                                              MPUREG_USER_CTRL,
-                                              (b | BIT_AUX_IF_EN));
-               ERROR_CHECK(result);
-       } else {
-               /* Coming out of I2C is tricky due to several erratta.  Do not
-                * modify this algorithm
-                */
-               /*
-                * 1) wait for the right time and send the command to change
-                * the aux i2c slave address to an invalid address that will
-                * get nack'ed
-                *
-                * 0x00 is broadcast.  0x7F is unlikely to be used by any aux.
-                */
-               result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
-                                              MPUREG_AUX_SLV_ADDR, 0x7F);
-               ERROR_CHECK(result);
-               /*
-                * 2) wait enough time for a nack to occur, then go into
-                *    bypass mode:
-                */
-               MLOSSleep(2);
-               result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
-                                              MPUREG_USER_CTRL, (b));
-               ERROR_CHECK(result);
-               /*
-                * 3) wait for up to one MPU cycle then restore the slave
-                *    address
-                */
-               MLOSSleep(SAMPLING_PERIOD_US(mldl_cfg) / 1000);
-               result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
-                                              MPUREG_AUX_SLV_ADDR,
-                                              mldl_cfg->pdata->
-                                              accel.address);
-               ERROR_CHECK(result);
-
-               /*
-                * 4) reset the ime interface
-                */
-#ifdef M_HW
-               result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
-                                              MPUREG_USER_CTRL,
-                                              (b | BIT_I2C_MST_RST));
-
-#else
-               result = MLSLSerialWriteSingle(mlsl_handle, mldl_cfg->addr,
-                                              MPUREG_USER_CTRL,
-                                              (b | BIT_AUX_IF_RST));
-#endif
-               ERROR_CHECK(result);
-               MLOSSleep(2);
-       }
-       mldl_cfg->gyro_is_bypassed = enable;
-
-       return result;
-}
-
-struct tsProdRevMap {
-       unsigned char siliconRev;
-       unsigned short sensTrim;
-};
-
-#define NUM_OF_PROD_REVS (DIM(prodRevsMap))
-
-/* NOTE : 'npp' is a non production part */
-#ifdef M_HW
-#define OLDEST_PROD_REV_SUPPORTED 1
-static struct tsProdRevMap prodRevsMap[] = {
-       {0, 0},
-       {MPU_SILICON_REV_A1, 131},      /* 1 A1 (npp) */
-       {MPU_SILICON_REV_A1, 131},      /* 2 A1 (npp) */
-       {MPU_SILICON_REV_A1, 131},      /* 3 A1 (npp) */
-       {MPU_SILICON_REV_A1, 131},      /* 4 A1 (npp) */
-       {MPU_SILICON_REV_A1, 131},      /* 5 A1 (npp) */
-       {MPU_SILICON_REV_A1, 131},      /* 6 A1 (npp) */
-       {MPU_SILICON_REV_A1, 131},      /* 7 A1 (npp) */
-       {MPU_SILICON_REV_A1, 131},      /* 8 A1 (npp) */
-};
-
-#else                          /* !M_HW */
-#define OLDEST_PROD_REV_SUPPORTED 11
-
-static struct tsProdRevMap prodRevsMap[] = {
-       {0, 0},
-       {MPU_SILICON_REV_A4, 131},      /* 1 A? OBSOLETED */
-       {MPU_SILICON_REV_A4, 131},      /* 2 | */
-       {MPU_SILICON_REV_A4, 131},      /* 3 V */
-       {MPU_SILICON_REV_A4, 131},      /* 4 */
-       {MPU_SILICON_REV_A4, 131},      /* 5 */
-       {MPU_SILICON_REV_A4, 131},      /* 6 */
-       {MPU_SILICON_REV_A4, 131},      /* 7 */
-       {MPU_SILICON_REV_A4, 131},      /* 8 */
-       {MPU_SILICON_REV_A4, 131},      /* 9 */
-       {MPU_SILICON_REV_A4, 131},      /* 10 */
-       {MPU_SILICON_REV_B1, 131},      /* 11 B1 */
-       {MPU_SILICON_REV_B1, 131},      /* 12 | */
-       {MPU_SILICON_REV_B1, 131},      /* 13 V */
-       {MPU_SILICON_REV_B1, 131},      /* 14 B4 */
-       {MPU_SILICON_REV_B4, 131},      /* 15 | */
-       {MPU_SILICON_REV_B4, 131},      /* 16 V */
-       {MPU_SILICON_REV_B4, 131},      /* 17 */
-       {MPU_SILICON_REV_B4, 131},      /* 18 */
-       {MPU_SILICON_REV_B4, 115},      /* 19  */
-       {MPU_SILICON_REV_B4, 115},      /* 20 */
-       {MPU_SILICON_REV_B6, 131},      /* 21 B6 (B6/A9)  */
-       {MPU_SILICON_REV_B4, 115},      /* 22 B4 (B7/A10) */
-       {MPU_SILICON_REV_B6, 0},        /* 23 B6 (npp)    */
-       {MPU_SILICON_REV_B6, 0},        /* 24 |  (npp)    */
-       {MPU_SILICON_REV_B6, 0},        /* 25 V  (npp)    */
-       {MPU_SILICON_REV_B6, 131},      /* 26    (B6/A11) */
-};
-#endif                         /* !M_HW */
-
-/**
- *  @internal
- *  @brief  Get the silicon revision ID from OTP.
- *          The silicon revision number is in read from OTP bank 0,
- *          ADDR6[7:2].  The corresponding ID is retrieved by lookup
- *          in a map.
- *  @return The silicon revision ID (0 on error).
- */
-static int MLDLGetSiliconRev(struct mldl_cfg *pdata,
-                            void *mlsl_handle)
-{
-       int result;
-       unsigned char index = 0x00;
-       unsigned char bank =
-           (BIT_PRFTCH_EN | BIT_CFG_USER_BANK | MPU_MEM_OTP_BANK_0);
-       unsigned short memAddr = ((bank << 8) | 0x06);
-
-       result = MLSLSerialReadMem(mlsl_handle, pdata->addr,
-                                  memAddr, 1, &index);
-       ERROR_CHECK(result);
-       if (result)
-               return result;
-       index >>= 2;
-
-       /* clean the prefetch and cfg user bank bits */
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                 MPUREG_BANK_SEL, 0);
-       ERROR_CHECK(result);
-       if (result)
-               return result;
-
-       if (index < OLDEST_PROD_REV_SUPPORTED || NUM_OF_PROD_REVS <= index) {
-               pdata->silicon_revision = 0;
-               pdata->trim = 0;
-               MPL_LOGE("Unsupported Product Revision Detected : %d\n", index);
-               return ML_ERROR_INVALID_MODULE;
-       }
-
-       pdata->silicon_revision = prodRevsMap[index].siliconRev;
-       pdata->trim = prodRevsMap[index].sensTrim;
-
-       if (pdata->trim == 0) {
-               MPL_LOGE("sensitivity trim is 0"
-                        " - unsupported non production part.\n");
-               return ML_ERROR_INVALID_MODULE;
-       }
-
-       return result;
-}
-
-/**
- *  @brief  Enable / Disable the use MPU's secondary I2C interface level
- *          shifters.
- *          When enabled the secondary I2C interface to which the external
- *          device is connected runs at VDD voltage (main supply).
- *          When disabled the 2nd interface runs at VDDIO voltage.
- *          See the device specification for more details.
- *
- *  @note   using this API may produce unpredictable results, depending on how
- *          the MPU and slave device are setup on the target platform.
- *          Use of this API should entirely be restricted to system
- *          integrators. Once the correct value is found, there should be no
- *          need to change the level shifter at runtime.
- *
- *  @pre    Must be called after MLSerialOpen().
- *  @note   Typically called before MLDmpOpen().
- *
- *  @param[in]  enable:
- *                  0 to run at VDDIO (default),
- *                  1 to run at VDD.
- *
- *  @return ML_SUCCESS if successfull, a non-zero error code otherwise.
- */
-static int MLDLSetLevelShifterBit(struct mldl_cfg *pdata,
-                                 void *mlsl_handle,
-                                 unsigned char enable)
-{
-#ifndef M_HW
-       int result;
-       unsigned char reg;
-       unsigned char mask;
-       unsigned char regval;
-
-       if (0 == pdata->silicon_revision)
-               return ML_ERROR_INVALID_PARAMETER;
-
-       /*-- on parts before B6 the VDDIO bit is bit 7 of ACCEL_BURST_ADDR --
-       NOTE: this is incompatible with ST accelerometers where the VDDIO
-       bit MUST be set to enable ST's internal logic to autoincrement
-       the register address on burst reads --*/
-       if ((pdata->silicon_revision & 0xf) < MPU_SILICON_REV_B6) {
-               reg = MPUREG_ACCEL_BURST_ADDR;
-               mask = 0x80;
-       } else {
-               /*-- on B6 parts the VDDIO bit was moved to FIFO_EN2 =>
-                 the mask is always 0x04 --*/
-               reg = MPUREG_FIFO_EN2;
-               mask = 0x04;
-       }
-
-       result = MLSLSerialRead(mlsl_handle, pdata->addr, reg, 1, &regval);
-       if (result)
-               return result;
-
-       if (enable)
-               regval |= mask;
-       else
-               regval &= ~mask;
-
-       result =
-           MLSLSerialWriteSingle(mlsl_handle, pdata->addr, reg, regval);
-
-       return result;
-#else
-       return ML_SUCCESS;
-#endif
-}
-
-
-#ifdef M_HW
-/**
- *  @internal
- * @param reset 1 to reset hardware
- */
-static tMLError mpu60xx_pwr_mgmt(struct mldl_cfg *pdata,
-                                void *mlsl_handle,
-                                unsigned char reset,
-                                unsigned char powerselection)
-{
-       unsigned char b;
-       tMLError result;
-
-       if (powerselection < 0 || powerselection > 7)
-               return ML_ERROR_INVALID_PARAMETER;
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGMT_1, 1,
-                          &b);
-       ERROR_CHECK(result);
-
-       b &= ~(BITS_PWRSEL);
-
-       if (reset) {
-               /* Current sillicon has an errata where the reset will get
-                * nacked.  Ignore the error code for now. */
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                              MPUREG_PWR_MGM, b | BIT_H_RESET);
-#define M_HW_RESET_ERRATTA
-#ifndef M_HW_RESET_ERRATTA
-               ERROR_CHECK(result);
-#else
-               MLOSSleep(50);
-#endif
-       }
-
-       b |= (powerselection << 4);
-
-       if (b & BITS_PWRSEL)
-               pdata->gyro_is_suspended = FALSE;
-       else
-               pdata->gyro_is_suspended = TRUE;
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                      MPUREG_PWR_MGM, b);
-       ERROR_CHECK(result);
-
-       return ML_SUCCESS;
-}
-
-/**
- *  @internal
- */
-static tMLError MLDLStandByGyros(struct mldl_cfg *pdata,
-                                void *mlsl_handle,
-                                unsigned char disable_gx,
-                                unsigned char disable_gy,
-                                unsigned char disable_gz)
-{
-       unsigned char b;
-       tMLError result;
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGMT_2, 1,
-                          &b);
-       ERROR_CHECK(result);
-
-       b &= ~(BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG);
-       b |= (disable_gx << 2 | disable_gy << 1 | disable_gz);
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                      MPUREG_PWR_MGMT_2, b);
-       ERROR_CHECK(result);
-
-       return ML_SUCCESS;
-}
-
-/**
- *  @internal
- */
-static tMLError MLDLStandByAccels(struct mldl_cfg *pdata,
-                                 void *mlsl_handle,
-                                 unsigned char disable_ax,
-                                 unsigned char disable_ay,
-                                 unsigned char disable_az)
-{
-       unsigned char b;
-       tMLError result;
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGMT_2, 1,
-                          &b);
-       ERROR_CHECK(result);
-
-       b &= ~(BIT_STBY_XA | BIT_STBY_YA | BIT_STBY_ZA);
-       b |= (disable_ax << 2 | disable_ay << 1 | disable_az);
-
-       result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                      MPUREG_PWR_MGMT_2, b);
-       ERROR_CHECK(result);
-
-       return ML_SUCCESS;
-}
-
-#else                          /* ! M_HW */
-
-/**
- * @internal
- * @brief   This function controls the power management on the MPU device.
- *          The entire chip can be put to low power sleep mode, or individual
- *          gyros can be turned on/off.
- *
- *          Putting the device into sleep mode depending upon the changing needs
- *          of the associated applications is a recommended method for reducing
- *          power consuption.  It is a safe opearation in that sleep/wake up of
- *          gyros while running will not result in any interruption of data.
- *
- *          Although it is entirely allowed to put the device into full sleep
- *          while running the DMP, it is not recomended because it will disrupt
- *          the ongoing calculations carried on inside the DMP and consequently
- *          the sensor fusion algorithm. Furthermore, while in sleep mode
- *          read & write operation from the app processor on both registers and
- *          memory are disabled and can only regained by restoring the MPU in
- *          normal power mode.
- *          Disabling any of the gyro axis will reduce the associated power
- *          consuption from the PLL but will not stop the DMP from running
- *          state.
- *
- * @param   reset
- *              Non-zero to reset the device. Note that this setting
- *              is volatile and the corresponding register bit will
- *              clear itself right after being applied.
- * @param   sleep
- *              Non-zero to put device into full sleep.
- * @param   disable_gx
- *              Non-zero to disable gyro X.
- * @param   disable_gy
- *              Non-zero to disable gyro Y.
- * @param   disable_gz
- *              Non-zero to disable gyro Z.
- *
- * @return  ML_SUCCESS if successfull; a non-zero error code otherwise.
- */
-static int MLDLPowerMgmtMPU(struct mldl_cfg *pdata,
-                           void *mlsl_handle,
-                           unsigned char reset,
-                           unsigned char sleep,
-                           unsigned char disable_gx,
-                           unsigned char disable_gy,
-                           unsigned char disable_gz)
-{
-       unsigned char b;
-       int result;
-
-       result =
-           MLSLSerialRead(mlsl_handle, pdata->addr, MPUREG_PWR_MGM, 1,
-                          &b);
-       ERROR_CHECK(result);
-
-       /* If we are awake, we need to put it in bypass before resetting */
-       if ((!(b & BIT_SLEEP)) && reset)
-               result = MLDLSetI2CBypass(pdata, mlsl_handle, 1);
-
-       /* If we are awake, we need stop the dmp sleeping */
-       if ((!(b & BIT_SLEEP)) && sleep)
-               dmp_stop(pdata, mlsl_handle);
-
-       /* Reset if requested */
-       if (reset) {
-               MPL_LOGV("Reset MPU3050\n");
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                       MPUREG_PWR_MGM, b | BIT_H_RESET);
-               ERROR_CHECK(result);
-               MLOSSleep(5);
-               pdata->gyro_needs_reset = FALSE;
-               /* Some chips are awake after reset and some are asleep,
-                * check the status */
-               result = MLSLSerialRead(mlsl_handle, pdata->addr,
-                                       MPUREG_PWR_MGM, 1, &b);
-               ERROR_CHECK(result);
-       }
-
-       /* Update the suspended state just in case we return early */
-       if (b & BIT_SLEEP)
-               pdata->gyro_is_suspended = TRUE;
-       else
-               pdata->gyro_is_suspended = FALSE;
-
-       /* if power status match requested, nothing else's left to do */
-       if ((b & (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)) ==
-               (((sleep != 0) * BIT_SLEEP) |
-               ((disable_gx != 0) * BIT_STBY_XG) |
-               ((disable_gy != 0) * BIT_STBY_YG) |
-               ((disable_gz != 0) * BIT_STBY_ZG))) {
-               return ML_SUCCESS;
-       }
-
-       /*
-        * This specific transition between states needs to be reinterpreted:
-        *    (1,1,1,1) -> (0,1,1,1) has to become
-        *    (1,1,1,1) -> (1,0,0,0) -> (0,1,1,1)
-        * where
-        *    (1,1,1,1) is (sleep=1,disable_gx=1,disable_gy=1,disable_gz=1)
-        */
-       if ((b & (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)) ==
-                (BIT_SLEEP | BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG)
-               && ((!sleep) && disable_gx && disable_gy && disable_gz)) {
-               result = MLDLPowerMgmtMPU(pdata, mlsl_handle, 0, 1, 0, 0, 0);
-               if (result)
-                       return result;
-               b |= BIT_SLEEP;
-               b &= ~(BIT_STBY_XG | BIT_STBY_YG | BIT_STBY_ZG);
-       }
-
-       if ((b & BIT_SLEEP) != ((sleep != 0) * BIT_SLEEP)) {
-               if (sleep) {
-                       result = MLDLSetI2CBypass(pdata, mlsl_handle, 1);
-                       ERROR_CHECK(result);
-                       b |= BIT_SLEEP;
-                       result =
-                           MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                                 MPUREG_PWR_MGM, b);
-                       ERROR_CHECK(result);
-                       pdata->gyro_is_suspended = TRUE;
-               } else {
-                       b &= ~BIT_SLEEP;
-                       result =
-                           MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                                 MPUREG_PWR_MGM, b);
-                       ERROR_CHECK(result);
-                       pdata->gyro_is_suspended = FALSE;
-                       MLOSSleep(5);
-               }
-       }
-       /*---
-         WORKAROUND FOR PUTTING GYRO AXIS in STAND-BY MODE
-         1) put one axis at a time in stand-by
-         ---*/
-       if ((b & BIT_STBY_XG) != ((disable_gx != 0) * BIT_STBY_XG)) {
-               b ^= BIT_STBY_XG;
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                               MPUREG_PWR_MGM, b);
-               ERROR_CHECK(result);
-       }
-       if ((b & BIT_STBY_YG) != ((disable_gy != 0) * BIT_STBY_YG)) {
-               b ^= BIT_STBY_YG;
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                              MPUREG_PWR_MGM, b);
-               ERROR_CHECK(result);
-       }
-       if ((b & BIT_STBY_ZG) != ((disable_gz != 0) * BIT_STBY_ZG)) {
-               b ^= BIT_STBY_ZG;
-               result = MLSLSerialWriteSingle(mlsl_handle, pdata->addr,
-                                              MPUREG_PWR_MGM, b);
-               ERROR_CHECK(result);
-       }
-
-       return ML_SUCCESS;
-}
-#endif                         /* M_HW */
-
-
-void mpu_print_cfg(struct mldl_cfg *mldl_cfg)
-{
-       struct mpu3050_platform_data *pdata = mldl_cfg->pdata;
-       struct ext_slave_platform_data *accel = &mldl_cfg->pdata->accel;
-       struct ext_slave_platform_data *compass =
-           &mldl_cfg->pdata->compass;
-       struct ext_slave_platform_data *pressure =
-           &mldl_cfg->pdata->pressure;
-
-       MPL_LOGD("mldl_cfg.addr             = %02x\n", mldl_cfg->addr);
-       MPL_LOGD("mldl_cfg.int_config       = %02x\n",
-                mldl_cfg->int_config);
-       MPL_LOGD("mldl_cfg.ext_sync         = %02x\n", mldl_cfg->ext_sync);
-       MPL_LOGD("mldl_cfg.full_scale       = %02x\n",
-                mldl_cfg->full_scale);
-       MPL_LOGD("mldl_cfg.lpf              = %02x\n", mldl_cfg->lpf);
-       MPL_LOGD("mldl_cfg.clk_src          = %02x\n", mldl_cfg->clk_src);
-       MPL_LOGD("mldl_cfg.divider          = %02x\n", mldl_cfg->divider);
-       MPL_LOGD("mldl_cfg.dmp_enable       = %02x\n",
-                mldl_cfg->dmp_enable);
-       MPL_LOGD("mldl_cfg.fifo_enable      = %02x\n",
-                mldl_cfg->fifo_enable);
-       MPL_LOGD("mldl_cfg.dmp_cfg1         = %02x\n", mldl_cfg->dmp_cfg1);
-       MPL_LOGD("mldl_cfg.dmp_cfg2         = %02x\n", mldl_cfg->dmp_cfg2);
-       MPL_LOGD("mldl_cfg.offset_tc[0]     = %02x\n",
-                mldl_cfg->offset_tc[0]);
-       MPL_LOGD("mldl_cfg.offset_tc[1]     = %02x\n",
-                mldl_cfg->offset_tc[1]);
-       MPL_LOGD("mldl_cfg.offset_tc[2]     = %02x\n",
-                mldl_cfg->offset_tc[2]);
-       MPL_LOGD("mldl_cfg.silicon_revision = %02x\n",
-                mldl_cfg->silicon_revision);
-       MPL_LOGD("mldl_cfg.product_id       = %02x\n",
-                mldl_cfg->product_id);
-       MPL_LOGD("mldl_cfg.trim             = %02x\n", mldl_cfg->trim);
-       MPL_LOGD("mldl_cfg.requested_sensors= %04lx\n",
-                mldl_cfg->requested_sensors);
-
-       if (mldl_cfg->accel) {
-               MPL_LOGD("slave_accel->suspend      = %02x\n",
-                        (int) mldl_cfg->accel->suspend);
-               MPL_LOGD("slave_accel->resume       = %02x\n",
-                        (int) mldl_cfg->accel->resume);
-               MPL_LOGD("slave_accel->read         = %02x\n",
-                        (int) mldl_cfg->accel->read);
-               MPL_LOGD("slave_accel->type         = %02x\n",
-                        mldl_cfg->accel->type);
-               MPL_LOGD("slave_accel->reg          = %02x\n",
-                        mldl_cfg->accel->reg);
-               MPL_LOGD("slave_accel->len          = %02x\n",
-                        mldl_cfg->accel->len);
-               MPL_LOGD("slave_accel->endian       = %02x\n",
-                        mldl_cfg->accel->endian);
-               MPL_LOGD("slave_accel->range.mantissa= %02lx\n",
-                        mldl_cfg->accel->range.mantissa);
-               MPL_LOGD("slave_accel->range.fraction= %02lx\n",
-                        mldl_cfg->accel->range.fraction);
-       } else {
-               MPL_LOGD("slave_accel               = NULL\n");
-       }
-
-       if (mldl_cfg->compass) {
-               MPL_LOGD("slave_compass->suspend    = %02x\n",
-                        (int) mldl_cfg->compass->suspend);
-               MPL_LOGD("slave_compass->resume     = %02x\n",
-                        (int) mldl_cfg->compass->resume);
-               MPL_LOGD("slave_compass->read       = %02x\n",
-                        (int) mldl_cfg->compass->read);
-               MPL_LOGD("slave_compass->type       = %02x\n",
-                        mldl_cfg->compass->type);
-               MPL_LOGD("slave_compass->reg        = %02x\n",
-                        mldl_cfg->compass->reg);
-               MPL_LOGD("slave_compass->len        = %02x\n",
-                        mldl_cfg->compass->len);
-               MPL_LOGD("slave_compass->endian     = %02x\n",
-                        mldl_cfg->compass->endian);
-               MPL_LOGD("slave_compass->range.mantissa= %02lx\n",
-                        mldl_cfg->compass->range.mantissa);
-               MPL_LOGD("slave_compass->range.fraction= %02lx\n",
-                        mldl_cfg->compass->range.fraction);
-
-       } else {
-               MPL_LOGD("slave_compass             = NULL\n");
-       }
-
-       if (mldl_cfg->pressure) {
-               MPL_LOGD("slave_pressure->suspend    = %02x\n",
-                        (int) mldl_cfg->pressure->suspend);
-               MPL_LOGD("slave_pressure->resume     = %02x\n",
-                        (int) mldl_cfg->pressure->resume);
-               MPL_LOGD("slave_pressure->read       = %02x\n",
-                        (int) mldl_cfg->pressure->read);
-               MPL_LOGD("slave_pressure->type       = %02x\n",
-                        mldl_cfg->pressure->type);
-               MPL_LOGD("slave_pressure->reg        = %02x\n",
-                        mldl_cfg->pressure->reg);
-               MPL_LOGD("slave_pressure->len        = %02x\n",
-                        mldl_cfg->pressure->len);
-               MPL_LOGD("slave_pressure->endian     = %02x\n",
-                        mldl_cfg->pressure->endian);
-               MPL_LOGD("slave_pressure->range.mantissa= %02lx\n",
-                        mldl_cfg->pressure->range.mantissa);
-               MPL_LOGD("slave_pressure->range.fraction= %02lx\n",
-                        mldl_cfg->pressure->range.fraction);
-
-       } else {
-               MPL_LOGD("slave_pressure             = NULL\n");
-       }
-       MPL_LOGD("accel->get_slave_descr    = %x\n",
-                (unsigned int) accel->get_slave_descr);
-       MPL_LOGD("accel->irq                = %02x\n", accel->irq);
-       MPL_LOGD("accel->adapt_num          = %02x\n", accel->adapt_num);
-       MPL_LOGD("accel->bus                = %02x\n", accel->bus);
-       MPL_LOGD("accel->address            = %02x\n", accel->address);
-       MPL_LOGD("accel->orientation        =\n"
-                "                            %2d %2d %2d\n"
-                "                            %2d %2d %2d\n"
-                "                            %2d %2d %2d\n",
-                accel->orientation[0], accel->orientation[1],
-                accel->orientation[2], accel->orientation[3],
-                accel->orientation[4], accel->orientation[5],
-                accel->orientation[6], accel->orientation[7],
-                accel->orientation[8]);
-       MPL_LOGD("compass->get_slave_descr  = %x\n",
-                (unsigned int) compass->get_slave_descr);
-       MPL_LOGD("compass->irq              = %02x\n", compass->irq);
-       MPL_LOGD("compass->adapt_num        = %02x\n", compass->adapt_num);
-       MPL_LOGD("compass->bus              = %02x\n", compass->bus);
-       MPL_LOGD("compass->address          = %02x\n", compass->address);
-       MPL_LOGD("compass->orientation      =\n"
-                "                            %2d %2d %2d\n"
-                "                            %2d %2d %2d\n"
-                "                            %2d %2d %2d\n",
-                compass->orientation[0], compass->orientation[1],
-                compass->orientation[2], compass->orientation[3],
-                compass->orientation[4], compass->orientation[5],
-                compass->orientation[6], compass->orientation[7],
-                compass->orientation[8]);
-       MPL_LOGD("pressure->get_slave_descr  = %x\n",
-                (unsigned int) pressure->get_slave_descr);
-       MPL_LOGD("pressure->irq             = %02x\n", pressure->irq);
-       MPL_LOGD("pressure->adapt_num       = %02x\n", pressure->adapt_num);
-       MPL_LOGD("pressure->bus             = %02x\n", pressure->bus);
-       MPL_LOGD("pressure->address         = %02x\n", pressure->address);
-       MPL_LOGD("pressure->orientation     =\n"
-                "                            %2d %2d %2d\n"
-                "                            %2d %2d %2d\n"
-                "                            %2d %2d %2d\n",
-                pressure->orientation[0], pressure->orientation[1],
-                pressure->orientation[2], pressure->orientation[3],
-                pressure->orientation[4], pressure->orientation[5],
-                pressure->orientation[6], pressure->orientation[7],
-                pressure->orientation[8]);
-
-       MPL_LOGD("pdata->int_config         = %02x\n", pdata->int_config);
-       MPL_LOGD("pdata->level_shifter      = %02x\n",
-                pdata->level_shifter);
-       MPL_LOGD("pdata->orientation        =\n"
-                "                            %2d %2d %2d\n"
-                "                            %2d %2d %2d\n"
-                "                            %2d %2d %2d\n",
-                pdata->orientation[0], pdata->orientation[1],
-                pdata->orientation[2], pdata->orientation[3],
-                pdata->orientation[4], pdata->orientation[5],
-                pdata->orientation[6], pdata->orientation[7],
-                pdata->orientation[8]);
-
-       MPL_LOGD("Struct sizes: mldl_cfg: %d, "
-                "ext_slave_descr:%d, "
-                "mpu3050_platform_data:%d: RamOffset: %d\n",
-                sizeof(struct mldl_cfg), sizeof(struct ext_slave_descr),
-                sizeof(struct mpu3050_platform_data),
-                offsetof(struct mldl_cfg, ram));
-}
-
-int mpu_set_slave(struct mldl_cfg *mldl_cfg,
-               void *gyro_handle,
-               struct ext_slave_descr *slave,
-               struct ext_slave_platform_data *slave_pdata)
-{
-       int result;
-       unsigned char reg;
-       unsigned char slave_reg;
-       unsigned char slave_len;
-       unsigned char slave_endian;
-       unsigned char slave_address;
-
-       result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
-
-       if (NULL == slave || NULL == slave_pdata) {
-               slave_reg = 0;
-               slave_len = 0;
-               slave_endian = 0;
-               slave_address = 0;
-       } else {
-               slave_reg = slave->reg;
-               slave_len = slave->len;
-               slave_endian = slave->endian;
-               slave_address = slave_pdata->address;
-       }
-
-       /* Address */
-       result = MLSLSerialWriteSingle(gyro_handle,
-                               mldl_cfg->addr,
-                               MPUREG_AUX_SLV_ADDR,
-                               slave_address);
-       ERROR_CHECK(result);
-       /* Register */
-       result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
-                               MPUREG_ACCEL_BURST_ADDR, 1,
-                               &reg);
-       ERROR_CHECK(result);
-       reg = ((reg & 0x80) | slave_reg);
-       result = MLSLSerialWriteSingle(gyro_handle,
-                               mldl_cfg->addr,
-                               MPUREG_ACCEL_BURST_ADDR,
-                               reg);
-       ERROR_CHECK(result);
-
-#ifdef M_HW
-       /* Length, byte swapping, grouping & enable */
-       if (slave_len > BITS_SLV_LENG) {
-               MPL_LOGW("Limiting slave burst read length to "
-                       "the allowed maximum (15B, req. %d)\n",
-                       slave_len);
-               slave_len = BITS_SLV_LENG;
-       }
-       reg = slave_len;
-       if (slave_endian == EXT_SLAVE_LITTLE_ENDIAN)
-               reg |= BIT_SLV_BYTE_SW;
-       reg |= BIT_SLV_GRP;
-       reg |= BIT_SLV_ENABLE;
-
-       result = MLSLSerialWriteSingle(gyro_handle,
-                               mldl_cfg->addr,
-                               MPUREG_I2C_SLV0_CTRL,
-                               reg);
-#else
-       /* Length */
-       result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
-                               MPUREG_USER_CTRL, 1, &reg);
-       ERROR_CHECK(result);
-       reg = (reg & ~BIT_AUX_RD_LENG);
-       result = MLSLSerialWriteSingle(gyro_handle,
-                               mldl_cfg->addr,
-                               MPUREG_USER_CTRL, reg);
-       ERROR_CHECK(result);
-#endif
-
-       if (slave_address) {
-               result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, FALSE);
-               ERROR_CHECK(result);
-       }
-       return result;
-}
-
-/**
- * Check to see if the gyro was reset by testing a couple of registers known
- * to change on reset.
- *
- * @param mldl_cfg mldl configuration structure
- * @param gyro_handle handle used to communicate with the gyro
- *
- * @return ML_SUCCESS or non-zero error code
- */
-static int mpu_was_reset(struct mldl_cfg *mldl_cfg, void *gyro_handle)
-{
-       int result = ML_SUCCESS;
-       unsigned char reg;
-
-       result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
-                               MPUREG_DMP_CFG_2, 1, &reg);
-       ERROR_CHECK(result);
-
-       if (mldl_cfg->dmp_cfg2 != reg)
-               return TRUE;
-
-       if (0 != mldl_cfg->dmp_cfg1)
-               return FALSE;
-
-       result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
-                               MPUREG_SMPLRT_DIV, 1, &reg);
-       ERROR_CHECK(result);
-       if (reg != mldl_cfg->divider)
-               return TRUE;
-
-       if (0 != mldl_cfg->divider)
-               return FALSE;
-
-       /* Inconclusive assume it was reset */
-       return TRUE;
-}
-
-static int gyro_resume(struct mldl_cfg *mldl_cfg, void *gyro_handle)
-{
-       int result;
-       int ii;
-       int jj;
-       unsigned char reg;
-       unsigned char regs[7];
-
-       /* Wake up the part */
-#ifdef M_HW
-       result = mpu60xx_pwr_mgmt(mldl_cfg, gyro_handle, RESET,
-                               WAKE_UP);
-       ERROR_CHECK(result);
-
-       /* Configure the MPU */
-       result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, 1);
-       ERROR_CHECK(result);
-       /* setting int_config with the propert flag BIT_BYPASS_EN
-          should be done by the setup functions */
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_INT_PIN_CFG,
-                               (mldl_cfg->pdata->int_config |
-                                       BIT_BYPASS_EN));
-       ERROR_CHECK(result);
-       /* temporary: masking out higher bits to avoid switching
-          intelligence */
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_INT_ENABLE,
-                               (mldl_cfg->int_config));
-       ERROR_CHECK(result);
-#else
-       result = MLDLPowerMgmtMPU(mldl_cfg, gyro_handle, 0, 0,
-                               mldl_cfg->gyro_power & BIT_STBY_XG,
-                               mldl_cfg->gyro_power & BIT_STBY_YG,
-                               mldl_cfg->gyro_power & BIT_STBY_ZG);
-
-       if (!mldl_cfg->gyro_needs_reset &&
-           !mpu_was_reset(mldl_cfg, gyro_handle)) {
-               return ML_SUCCESS;
-       }
-
-       result = MLDLPowerMgmtMPU(mldl_cfg, gyro_handle, 1, 0,
-                               mldl_cfg->gyro_power & BIT_STBY_XG,
-                               mldl_cfg->gyro_power & BIT_STBY_YG,
-                               mldl_cfg->gyro_power & BIT_STBY_ZG);
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_INT_CFG,
-                               (mldl_cfg->int_config |
-                                       mldl_cfg->pdata->int_config));
-       ERROR_CHECK(result);
-#endif
-
-       result = MLSLSerialRead(gyro_handle, mldl_cfg->addr,
-                               MPUREG_PWR_MGM, 1, &reg);
-       ERROR_CHECK(result);
-       reg &= ~BITS_CLKSEL;
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_PWR_MGM,
-                               mldl_cfg->clk_src | reg);
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_SMPLRT_DIV,
-                               mldl_cfg->divider);
-       ERROR_CHECK(result);
-
-#ifdef M_HW
-       reg = DLPF_FS_SYNC_VALUE(0, mldl_cfg->full_scale, 0);
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_GYRO_CONFIG, reg);
-       reg = DLPF_FS_SYNC_VALUE(mldl_cfg->ext_sync, 0, mldl_cfg->lpf);
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_CONFIG, reg);
-#else
-       reg = DLPF_FS_SYNC_VALUE(mldl_cfg->ext_sync,
-                               mldl_cfg->full_scale, mldl_cfg->lpf);
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_DLPF_FS_SYNC, reg);
-#endif
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_DMP_CFG_1,
-                               mldl_cfg->dmp_cfg1);
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_DMP_CFG_2,
-                               mldl_cfg->dmp_cfg2);
-       ERROR_CHECK(result);
-
-       /* Write and verify memory */
-       for (ii = 0; ii < MPU_MEM_NUM_RAM_BANKS; ii++) {
-               unsigned char read[MPU_MEM_BANK_SIZE];
-
-               result = MLSLSerialWriteMem(gyro_handle,
-                                       mldl_cfg->addr,
-                                       ((ii << 8) | 0x00),
-                                       MPU_MEM_BANK_SIZE,
-                                       mldl_cfg->ram[ii]);
-               ERROR_CHECK(result);
-               result = MLSLSerialReadMem(gyro_handle, mldl_cfg->addr,
-                                       ((ii << 8) | 0x00),
-                                       MPU_MEM_BANK_SIZE, read);
-               ERROR_CHECK(result);
-
-#ifdef M_HW
-#define ML_SKIP_CHECK 38
-#else
-#define ML_SKIP_CHECK 20
-#endif
-               for (jj = 0; jj < MPU_MEM_BANK_SIZE; jj++) {
-                       /* skip the register memory locations */
-                       if (ii == 0 && jj < ML_SKIP_CHECK)
-                               continue;
-                       if (mldl_cfg->ram[ii][jj] != read[jj]) {
-                               result = ML_ERROR_SERIAL_WRITE;
-                               break;
-                       }
-               }
-               ERROR_CHECK(result);
-       }
-
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_XG_OFFS_TC,
-                               mldl_cfg->offset_tc[0]);
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_YG_OFFS_TC,
-                               mldl_cfg->offset_tc[1]);
-       ERROR_CHECK(result);
-       result = MLSLSerialWriteSingle(gyro_handle, mldl_cfg->addr,
-                               MPUREG_ZG_OFFS_TC,
-                               mldl_cfg->offset_tc[2]);
-       ERROR_CHECK(result);
-
-       regs[0] = MPUREG_X_OFFS_USRH;
-       for (ii = 0; ii < DIM(mldl_cfg->offset); ii++) {
-               regs[1 + ii * 2] =
-                       (unsigned char)(mldl_cfg->offset[ii] >> 8)
-                       & 0xff;
-               regs[1 + ii * 2 + 1] =
-                       (unsigned char)(mldl_cfg->offset[ii] & 0xff);
-       }
-       result = MLSLSerialWrite(gyro_handle, mldl_cfg->addr, 7, regs);
-       ERROR_CHECK(result);
-
-       /* Configure slaves */
-       result = MLDLSetLevelShifterBit(mldl_cfg, gyro_handle,
-                                       mldl_cfg->pdata->level_shifter);
-       ERROR_CHECK(result);
-       return result;
-}
-/*******************************************************************************
- *******************************************************************************
- * Exported functions
- *******************************************************************************
- ******************************************************************************/
-
-/**
- * Initializes the pdata structure to defaults.
- *
- * Opens the device to read silicon revision, product id and whoami.
- *
- * @param mldl_cfg
- *          The internal device configuration data structure.
- * @param mlsl_handle
- *          The serial communication handle.
- *
- * @return ML_SUCCESS if silicon revision, product id and woami are supported
- *         by this software.
- */
-int mpu3050_open(struct mldl_cfg *mldl_cfg,
-                void *mlsl_handle,
-                void *accel_handle,
-                void *compass_handle,
-                void *pressure_handle)
-{
-       int result;
-       /* Default is Logic HIGH, pushpull, latch disabled, anyread to clear */
-       mldl_cfg->ignore_system_suspend = FALSE;
-       mldl_cfg->int_config = BIT_INT_ANYRD_2CLEAR | BIT_DMP_INT_EN;
-       mldl_cfg->clk_src = MPU_CLK_SEL_PLLGYROZ;
-       mldl_cfg->lpf = MPU_FILTER_42HZ;
-       mldl_cfg->full_scale = MPU_FS_2000DPS;
-       mldl_cfg->divider = 4;
-       mldl_cfg->dmp_enable = 1;
-       mldl_cfg->fifo_enable = 1;
-       mldl_cfg->ext_sync = 0;
-       mldl_cfg->dmp_cfg1 = 0;
-       mldl_cfg->dmp_cfg2 = 0;
-       mldl_cfg->gyro_power = 0;
-       mldl_cfg->gyro_is_bypassed = TRUE;
-       mldl_cfg->dmp_is_running = FALSE;
-       mldl_cfg->gyro_is_suspended = TRUE;
-       mldl_cfg->accel_is_suspended = TRUE;
-       mldl_cfg->compass_is_suspended = TRUE;
-       mldl_cfg->pressure_is_suspended = TRUE;
-       mldl_cfg->gyro_needs_reset = FALSE;
-       if (mldl_cfg->addr == 0) {
-#ifdef __KERNEL__
-               return ML_ERROR_INVALID_PARAMETER;
-#else
-               mldl_cfg->addr = 0x68;
-#endif
-       }
-
-       /*
-        * Reset,
-        * Take the DMP out of sleep, and
-        * read the product_id, sillicon rev and whoami
-        */
-#ifdef M_HW
-       result = mpu60xx_pwr_mgmt(mldl_cfg, mlsl_handle,
-                                 RESET, WAKE_UP);
-#else
-       result = MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, RESET, 0, 0, 0, 0);
-#endif
-       ERROR_CHECK(result);
-
-       result = MLDLGetSiliconRev(mldl_cfg, mlsl_handle);
-       ERROR_CHECK(result);
-#ifndef M_HW
-       result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
-                               MPUREG_PRODUCT_ID, 1,
-                               &mldl_cfg->product_id);
-       ERROR_CHECK(result);
-#endif
-
-       /* Get the factory temperature compensation offsets */
-       result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
-                               MPUREG_XG_OFFS_TC, 1,
-                               &mldl_cfg->offset_tc[0]);
-       ERROR_CHECK(result);
-       result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
-                               MPUREG_YG_OFFS_TC, 1,
-                               &mldl_cfg->offset_tc[1]);
-       ERROR_CHECK(result);
-       result = MLSLSerialRead(mlsl_handle, mldl_cfg->addr,
-                               MPUREG_ZG_OFFS_TC, 1,
-                               &mldl_cfg->offset_tc[2]);
-       ERROR_CHECK(result);
-
-       /* Configure the MPU */
-#ifdef M_HW
-       result = mpu60xx_pwr_mgmt(mldl_cfg, mlsl_handle,
-                                 FALSE, SLEEP);
-#else
-       result =
-           MLDLPowerMgmtMPU(mldl_cfg, mlsl_handle, 0, SLEEP, 0, 0, 0);
-#endif
-       ERROR_CHECK(result);
-
-       if (mldl_cfg->accel && mldl_cfg->accel->init) {
-               result = mldl_cfg->accel->init(accel_handle,
-                                              mldl_cfg->accel,
-                                              &mldl_cfg->pdata->accel);
-               ERROR_CHECK(result);
-       }
-
-       if (mldl_cfg->compass && mldl_cfg->compass->init) {
-               result = mldl_cfg->compass->init(compass_handle,
-                                                mldl_cfg->compass,
-                                                &mldl_cfg->pdata->compass);
-               if (ML_SUCCESS != result) {
-                       MPL_LOGE("mldl_cfg->compass->init returned %d\n",
-                               result);
-                       goto out_accel;
-               }
-       }
-       if (mldl_cfg->pressure && mldl_cfg->pressure->init) {
-               result = mldl_cfg->pressure->init(pressure_handle,
-                                                 mldl_cfg->pressure,
-                                                 &mldl_cfg->pdata->pressure);
-               if (ML_SUCCESS != result) {
-                       MPL_LOGE("mldl_cfg->pressure->init returned %d\n",
-                               result);
-                       goto out_compass;
-               }
-       }
-
-       mldl_cfg->requested_sensors = ML_THREE_AXIS_GYRO;
-       if (mldl_cfg->accel && mldl_cfg->accel->resume)
-               mldl_cfg->requested_sensors |= ML_THREE_AXIS_ACCEL;
-
-       if (mldl_cfg->compass && mldl_cfg->compass->resume)
-               mldl_cfg->requested_sensors |= ML_THREE_AXIS_COMPASS;
-
-       if (mldl_cfg->pressure && mldl_cfg->pressure->resume)
-               mldl_cfg->requested_sensors |= ML_THREE_AXIS_PRESSURE;
-
-       return result;
-
-out_compass:
-       if (mldl_cfg->compass->init)
-               mldl_cfg->compass->exit(compass_handle,
-                               mldl_cfg->compass,
-                               &mldl_cfg->pdata->compass);
-out_accel:
-       if (mldl_cfg->accel->init)
-               mldl_cfg->accel->exit(accel_handle,
-                               mldl_cfg->accel,
-                               &mldl_cfg->pdata->accel);
-       return result;
-
-}
-
-/**
- * Close the mpu3050 interface
- *
- * @param mldl_cfg pointer to the configuration structure
- * @param mlsl_handle pointer to the serial layer handle
- *
- * @return ML_SUCCESS or non-zero error code
- */
-int mpu3050_close(struct mldl_cfg *mldl_cfg,
-                 void *mlsl_handle,
-                 void *accel_handle,
-                 void *compass_handle,
-                 void *pressure_handle)
-{
-       int result = ML_SUCCESS;
-       int ret_result = ML_SUCCESS;
-
-       if (mldl_cfg->accel && mldl_cfg->accel->exit) {
-               result = mldl_cfg->accel->exit(accel_handle,
-                                       mldl_cfg->accel,
-                                       &mldl_cfg->pdata->accel);
-               if (ML_SUCCESS != result)
-                       MPL_LOGE("Accel exit failed %d\n", result);
-               ret_result = result;
-       }
-       if (ML_SUCCESS == ret_result)
-               ret_result = result;
-
-       if (mldl_cfg->compass && mldl_cfg->compass->exit) {
-               result = mldl_cfg->compass->exit(compass_handle,
-                                               mldl_cfg->compass,
-                                               &mldl_cfg->pdata->compass);
-               if (ML_SUCCESS != result)
-                       MPL_LOGE("Compass exit failed %d\n", result);
-       }
-       if (ML_SUCCESS == ret_result)
-               ret_result = result;
-
-       if (mldl_cfg->pressure && mldl_cfg->pressure->exit) {
-               result = mldl_cfg->pressure->exit(pressure_handle,
-                                               mldl_cfg->pressure,
-                                               &mldl_cfg->pdata->pressure);
-               if (ML_SUCCESS != result)
-                       MPL_LOGE("Pressure exit failed %d\n", result);
-       }
-       if (ML_SUCCESS == ret_result)
-               ret_result = result;
-
-       return ret_result;
-}
-
-/**
- *  @brief  resume the MPU3050 device and all the other sensor
- *          devices from their low power state.
- *
- *  @param  mldl_cfg
- *              pointer to the configuration structure
- *  @param  gyro_handle
- *              the main file handle to the MPU3050 device.
- *  @param  accel_handle
- *              an handle to the accelerometer device, if sitting
- *              onto a separate bus. Can match mlsl_handle if
- *              the accelerometer device operates on the same
- *              primary bus of MPU.
- *  @param  compass_handle
- *              an handle to the compass device, if sitting
- *              onto a separate bus. Can match mlsl_handle if
- *              the compass device operates on the same
- *              primary bus of MPU.
- *  @param  pressure_handle
- *              an handle to the pressure sensor device, if sitting
- *              onto a separate bus. Can match mlsl_handle if
- *              the pressure sensor device operates on the same
- *              primary bus of MPU.
- *  @param  resume_gyro
- *              whether resuming the gyroscope device is
- *              actually needed (if the device supports low power
- *              mode of some sort).
- *  @param  resume_accel
- *              whether resuming the accelerometer device is
- *              actually needed (if the device supports low power
- *              mode of some sort).
- *  @param  resume_compass
- *              whether resuming the compass device is
- *              actually needed (if the device supports low power
- *              mode of some sort).
- *  @param  resume_pressure
- *              whether resuming the pressure sensor device is
- *              actually needed (if the device supports low power
- *              mode of some sort).
- *  @return  ML_SUCCESS or a non-zero error code.
- */
-int mpu3050_resume(struct mldl_cfg *mldl_cfg,
-                  void *gyro_handle,
-                  void *accel_handle,
-                  void *compass_handle,
-                  void *pressure_handle,
-                  bool resume_gyro,
-                  bool resume_accel,
-                  bool resume_compass,
-                  bool resume_pressure)
-{
-       int result = ML_SUCCESS;
-
-#ifdef CONFIG_MPU_SENSORS_DEBUG
-       mpu_print_cfg(mldl_cfg);
-#endif
-
-       if (resume_accel &&
-           ((!mldl_cfg->accel) || (!mldl_cfg->accel->resume)))
-               return ML_ERROR_INVALID_PARAMETER;
-       if (resume_compass &&
-           ((!mldl_cfg->compass) || (!mldl_cfg->compass->resume)))
-               return ML_ERROR_INVALID_PARAMETER;
-       if (resume_pressure &&
-           ((!mldl_cfg->pressure) || (!mldl_cfg->pressure->resume)))
-               return ML_ERROR_INVALID_PARAMETER;
-
-       if (resume_gyro && mldl_cfg->gyro_is_suspended) {
-               result = gyro_resume(mldl_cfg, gyro_handle);
-               ERROR_CHECK(result);
-       }
-
-       if (resume_accel && mldl_cfg->accel_is_suspended) {
-               if (!mldl_cfg->gyro_is_suspended &&
-                   EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
-                       result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
-                       ERROR_CHECK(result);
-               }
-               result = mldl_cfg->accel->resume(accel_handle,
-                                                mldl_cfg->accel,
-                                                &mldl_cfg->pdata->accel);
-               ERROR_CHECK(result);
-               mldl_cfg->accel_is_suspended = FALSE;
-       }
-
-       if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->accel_is_suspended &&
-               EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
-               result = mpu_set_slave(mldl_cfg,
-                               gyro_handle,
-                               mldl_cfg->accel,
-                               &mldl_cfg->pdata->accel);
-               ERROR_CHECK(result);
-       }
-
-       if (resume_compass && mldl_cfg->compass_is_suspended) {
-               if (!mldl_cfg->gyro_is_suspended &&
-                   EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus) {
-                       result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
-                       ERROR_CHECK(result);
-               }
-               result = mldl_cfg->compass->resume(compass_handle,
-                                                  mldl_cfg->compass,
-                                                  &mldl_cfg->pdata->
-                                                  compass);
-               ERROR_CHECK(result);
-               mldl_cfg->compass_is_suspended = FALSE;
-       }
-
-       if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->compass_is_suspended &&
-               EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus) {
-               result = mpu_set_slave(mldl_cfg,
-                               gyro_handle,
-                               mldl_cfg->compass,
-                               &mldl_cfg->pdata->compass);
-               ERROR_CHECK(result);
-       }
-
-       if (resume_pressure && mldl_cfg->pressure_is_suspended) {
-               if (!mldl_cfg->gyro_is_suspended &&
-                   EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus) {
-                       result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, TRUE);
-                       ERROR_CHECK(result);
-               }
-               result = mldl_cfg->pressure->resume(pressure_handle,
-                                                   mldl_cfg->pressure,
-                                                   &mldl_cfg->pdata->
-                                                   pressure);
-               ERROR_CHECK(result);
-               mldl_cfg->pressure_is_suspended = FALSE;
-       }
-
-       if (!mldl_cfg->gyro_is_suspended && !mldl_cfg->pressure_is_suspended &&
-               EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus) {
-               result = mpu_set_slave(mldl_cfg,
-                               gyro_handle,
-                               mldl_cfg->pressure,
-                               &mldl_cfg->pdata->pressure);
-               ERROR_CHECK(result);
-       }
-
-       /* Now start */
-       if (resume_gyro) {
-               result = dmp_start(mldl_cfg, gyro_handle);
-               ERROR_CHECK(result);
-       }
-
-       return result;
-}
-
-/**
- *  @brief  suspend the MPU3050 device and all the other sensor
- *          devices into their low power state.
- *  @param  gyro_handle
- *              the main file handle to the MPU3050 device.
- *  @param  accel_handle
- *              an handle to the accelerometer device, if sitting
- *              onto a separate bus. Can match gyro_handle if
- *              the accelerometer device operates on the same
- *              primary bus of MPU.
- *  @param  compass_handle
- *              an handle to the compass device, if sitting
- *              onto a separate bus. Can match gyro_handle if
- *              the compass device operates on the same
- *              primary bus of MPU.
- *  @param  pressure_handle
- *              an handle to the pressure sensor device, if sitting
- *              onto a separate bus. Can match gyro_handle if
- *              the pressure sensor device operates on the same
- *              primary bus of MPU.
- *  @param  accel
- *              whether suspending the accelerometer device is
- *              actually needed (if the device supports low power
- *              mode of some sort).
- *  @param  compass
- *              whether suspending the compass device is
- *              actually needed (if the device supports low power
- *              mode of some sort).
- *  @param  pressure
- *              whether suspending the pressure sensor device is
- *              actually needed (if the device supports low power
- *              mode of some sort).
- *  @return  ML_SUCCESS or a non-zero error code.
- */
-int mpu3050_suspend(struct mldl_cfg *mldl_cfg,
-                   void *gyro_handle,
-                   void *accel_handle,
-                   void *compass_handle,
-                   void *pressure_handle,
-                   bool suspend_gyro,
-                   bool suspend_accel,
-                   bool suspend_compass,
-                   bool suspend_pressure)
-{
-       int result = ML_SUCCESS;
-
-       if (suspend_gyro && !mldl_cfg->gyro_is_suspended) {
-#ifdef M_HW
-               return ML_SUCCESS;
-               /* This puts the bus into bypass mode */
-               result = MLDLSetI2CBypass(mldl_cfg, gyro_handle, 1);
-               ERROR_CHECK(result);
-               result = mpu60xx_pwr_mgmt(mldl_cfg, gyro_handle, 0, SLEEP);
-#else
-               result = MLDLPowerMgmtMPU(mldl_cfg, gyro_handle,
-                                       0, SLEEP, 0, 0, 0);
-#endif
-               ERROR_CHECK(result);
-       }
-
-       if (!mldl_cfg->accel_is_suspended && suspend_accel &&
-           mldl_cfg->accel && mldl_cfg->accel->suspend) {
-               if (!mldl_cfg->gyro_is_suspended &&
-                   EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus) {
-                       result = mpu_set_slave(mldl_cfg, gyro_handle,
-                                              NULL, NULL);
-                       ERROR_CHECK(result);
-               }
-               result = mldl_cfg->accel->suspend(accel_handle,
-                                                 mldl_cfg->accel,
-                                                 &mldl_cfg->pdata->accel);
-               ERROR_CHECK(result);
-               mldl_cfg->accel_is_suspended = TRUE;
-       }
-
-       if (!mldl_cfg->compass_is_suspended && suspend_compass &&
-           mldl_cfg->compass && mldl_cfg->compass->suspend) {
-               if (!mldl_cfg->gyro_is_suspended &&
-                   EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus) {
-                       result = mpu_set_slave(mldl_cfg, gyro_handle,
-                                              NULL, NULL);
-                       ERROR_CHECK(result);
-               }
-               result = mldl_cfg->compass->suspend(compass_handle,
-                                                   mldl_cfg->compass,
-                                                   &mldl_cfg->
-                                                   pdata->compass);
-               ERROR_CHECK(result);
-               mldl_cfg->compass_is_suspended = TRUE;
-       }
-
-       if (!mldl_cfg->pressure_is_suspended && suspend_pressure &&
-           mldl_cfg->pressure && mldl_cfg->pressure->suspend) {
-               if (!mldl_cfg->gyro_is_suspended &&
-                   EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus) {
-                       result = mpu_set_slave(mldl_cfg, gyro_handle,
-                                              NULL, NULL);
-                       ERROR_CHECK(result);
-               }
-               result = mldl_cfg->pressure->suspend(pressure_handle,
-                                                   mldl_cfg->pressure,
-                                                   &mldl_cfg->
-                                                   pdata->pressure);
-               ERROR_CHECK(result);
-               mldl_cfg->pressure_is_suspended = TRUE;
-       }
-       return result;
-}
-
-
-/**
- *  @brief  read raw sensor data from the accelerometer device
- *          in use.
- *  @param  mldl_cfg
- *              A pointer to the struct mldl_cfg data structure.
- *  @param  accel_handle
- *              The handle to the device the accelerometer is connected to.
- *  @param  data
- *              a buffer to store the raw sensor data.
- *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
- */
-int mpu3050_read_accel(struct mldl_cfg *mldl_cfg,
-                      void *accel_handle, unsigned char *data)
-{
-       if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->read)
-               if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->accel.bus)
-                       && (!mldl_cfg->gyro_is_bypassed))
-                       return ML_ERROR_FEATURE_NOT_ENABLED;
-               else
-                       return mldl_cfg->accel->read(accel_handle,
-                                                    mldl_cfg->accel,
-                                                    &mldl_cfg->pdata->accel,
-                                                    data);
-       else
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-}
-
-/**
- *  @brief  read raw sensor data from the compass device
- *          in use.
- *  @param  mldl_cfg
- *              A pointer to the struct mldl_cfg data structure.
- *  @param  compass_handle
- *              The handle to the device the compass is connected to.
- *  @param  data
- *              a buffer to store the raw sensor data.
- *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
- */
-int mpu3050_read_compass(struct mldl_cfg *mldl_cfg,
-                        void *compass_handle, unsigned char *data)
-{
-       if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->read)
-               if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->compass.bus)
-                       && (!mldl_cfg->gyro_is_bypassed))
-                       return ML_ERROR_FEATURE_NOT_ENABLED;
-               else
-                       return mldl_cfg->compass->read(compass_handle,
-                                               mldl_cfg->compass,
-                                               &mldl_cfg->pdata->compass,
-                                               data);
-       else
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-}
-
-/**
- *  @brief  read raw sensor data from the pressure device
- *          in use.
- *  @param  mldl_cfg
- *              A pointer to the struct mldl_cfg data structure.
- *  @param  pressure_handle
- *              The handle to the device the pressure sensor is connected to.
- *  @param  data
- *              a buffer to store the raw sensor data.
- *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
- */
-int mpu3050_read_pressure(struct mldl_cfg *mldl_cfg,
-                        void *pressure_handle, unsigned char *data)
-{
-       if (NULL != mldl_cfg->pressure && NULL != mldl_cfg->pressure->read)
-               if ((EXT_SLAVE_BUS_SECONDARY == mldl_cfg->pdata->pressure.bus)
-                       && (!mldl_cfg->gyro_is_bypassed))
-                       return ML_ERROR_FEATURE_NOT_ENABLED;
-               else
-                       return mldl_cfg->pressure->read(
-                               pressure_handle,
-                               mldl_cfg->pressure,
-                               &mldl_cfg->pdata->pressure,
-                               data);
-       else
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-}
-
-int mpu3050_config_accel(struct mldl_cfg *mldl_cfg,
-                       void *accel_handle,
-                       struct ext_slave_config *data)
-{
-       if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->config)
-               return mldl_cfg->accel->config(accel_handle,
-                                              mldl_cfg->accel,
-                                              &mldl_cfg->pdata->accel,
-                                              data);
-       else
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-
-}
-
-int mpu3050_config_compass(struct mldl_cfg *mldl_cfg,
-                       void *compass_handle,
-                       struct ext_slave_config *data)
-{
-       if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->config)
-               return mldl_cfg->compass->config(compass_handle,
-                                                mldl_cfg->compass,
-                                                &mldl_cfg->pdata->compass,
-                                                data);
-       else
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-
-}
-
-int mpu3050_config_pressure(struct mldl_cfg *mldl_cfg,
-                       void *pressure_handle,
-                       struct ext_slave_config *data)
-{
-       if (NULL != mldl_cfg->pressure && NULL != mldl_cfg->pressure->config)
-               return mldl_cfg->pressure->config(pressure_handle,
-                                                 mldl_cfg->pressure,
-                                                 &mldl_cfg->pdata->pressure,
-                                                 data);
-       else
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-}
-
-int mpu3050_get_config_accel(struct mldl_cfg *mldl_cfg,
-                       void *accel_handle,
-                       struct ext_slave_config *data)
-{
-       if (NULL != mldl_cfg->accel && NULL != mldl_cfg->accel->get_config)
-               return mldl_cfg->accel->get_config(accel_handle,
-                                               mldl_cfg->accel,
-                                               &mldl_cfg->pdata->accel,
-                                               data);
-       else
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-
-}
-
-int mpu3050_get_config_compass(struct mldl_cfg *mldl_cfg,
-                       void *compass_handle,
-                       struct ext_slave_config *data)
-{
-       if (NULL != mldl_cfg->compass && NULL != mldl_cfg->compass->get_config)
-               return mldl_cfg->compass->get_config(compass_handle,
-                                               mldl_cfg->compass,
-                                               &mldl_cfg->pdata->compass,
-                                               data);
-       else
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-
-}
-
-int mpu3050_get_config_pressure(struct mldl_cfg *mldl_cfg,
-                               void *pressure_handle,
-                               struct ext_slave_config *data)
-{
-       if (NULL != mldl_cfg->pressure &&
-           NULL != mldl_cfg->pressure->get_config)
-               return mldl_cfg->pressure->get_config(pressure_handle,
-                                               mldl_cfg->pressure,
-                                               &mldl_cfg->pdata->pressure,
-                                               data);
-       else
-               return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-}
-
-
-/**
- *@}
- */
diff --git a/drivers/misc/mpu3050/mldl_cfg.h b/drivers/misc/mpu3050/mldl_cfg.h
deleted file mode 100755 (executable)
index ad6a211..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @addtogroup MLDL
- *
- *  @{
- *      @file   mldl_cfg.h
- *      @brief  The Motion Library Driver Layer Configuration header file.
- */
-
-#ifndef __MLDL_CFG_H__
-#define __MLDL_CFG_H__
-
-/* ------------------ */
-/* - Include Files. - */
-/* ------------------ */
-
-#include "mlsl.h"
-#include "mpu.h"
-
-/* --------------------- */
-/* -    Defines.       - */
-/* --------------------- */
-
-    /*************************************************************************/
-    /*  Sensors                                                              */
-    /*************************************************************************/
-
-#define ML_X_GYRO                      (0x0001)
-#define ML_Y_GYRO                      (0x0002)
-#define ML_Z_GYRO                      (0x0004)
-#define ML_DMP_PROCESSOR               (0x0008)
-
-#define ML_X_ACCEL                     (0x0010)
-#define ML_Y_ACCEL                     (0x0020)
-#define ML_Z_ACCEL                     (0x0040)
-
-#define ML_X_COMPASS                   (0x0080)
-#define ML_Y_COMPASS                   (0x0100)
-#define ML_Z_COMPASS                   (0x0200)
-
-#define ML_X_PRESSURE                  (0x0300)
-#define ML_Y_PRESSURE                  (0x0800)
-#define ML_Z_PRESSURE                  (0x1000)
-
-#define ML_TEMPERATURE                 (0x2000)
-#define ML_TIME                                (0x4000)
-
-#define ML_THREE_AXIS_GYRO             (0x000F)
-#define ML_THREE_AXIS_ACCEL            (0x0070)
-#define ML_THREE_AXIS_COMPASS          (0x0380)
-#define ML_THREE_AXIS_PRESSURE         (0x1C00)
-
-#define ML_FIVE_AXIS                   (0x007B)
-#define ML_SIX_AXIS_GYRO_ACCEL         (0x007F)
-#define ML_SIX_AXIS_ACCEL_COMPASS      (0x03F0)
-#define ML_NINE_AXIS                   (0x03FF)
-#define ML_ALL_SENSORS                 (0x7FFF)
-
-#define SAMPLING_RATE_HZ(mldl_cfg)                                     \
-       ((((((mldl_cfg)->lpf) == 0) || (((mldl_cfg)->lpf) == 7))        \
-               ? (8000)                                                \
-               : (1000))                                               \
-               / ((mldl_cfg)->divider + 1))
-
-#define SAMPLING_PERIOD_US(mldl_cfg)                                   \
-       ((1000000L * ((mldl_cfg)->divider + 1)) /                       \
-       (((((mldl_cfg)->lpf) == 0) || (((mldl_cfg)->lpf) == 7))         \
-               ? (8000)                                                \
-               : (1000)))
-/* --------------------- */
-/* -    Variables.     - */
-/* --------------------- */
-
-/* Platform data for the MPU */
-struct mldl_cfg {
-       /* MPU related configuration */
-       unsigned long requested_sensors;
-       unsigned char ignore_system_suspend;
-       unsigned char addr;
-       unsigned char int_config;
-       unsigned char ext_sync;
-       unsigned char full_scale;
-       unsigned char lpf;
-       unsigned char clk_src;
-       unsigned char divider;
-       unsigned char dmp_enable;
-       unsigned char fifo_enable;
-       unsigned char dmp_cfg1;
-       unsigned char dmp_cfg2;
-       unsigned char gyro_power;
-       unsigned char offset_tc[MPU_NUM_AXES];
-       unsigned short offset[MPU_NUM_AXES];
-       unsigned char ram[MPU_MEM_NUM_RAM_BANKS][MPU_MEM_BANK_SIZE];
-
-       /* MPU Related stored status and info */
-       unsigned char silicon_revision;
-       unsigned char product_id;
-       unsigned short trim;
-
-       /* Driver/Kernel related state information */
-       int gyro_is_bypassed;
-       int dmp_is_running;
-       int gyro_is_suspended;
-       int accel_is_suspended;
-       int compass_is_suspended;
-       int pressure_is_suspended;
-       int gyro_needs_reset;
-
-       /* Slave related information */
-       struct ext_slave_descr *accel;
-       struct ext_slave_descr *compass;
-       struct ext_slave_descr *pressure;
-
-       /* Platform Data */
-       struct mpu3050_platform_data *pdata;
-};
-
-
-int mpu3050_open(struct mldl_cfg *mldl_cfg,
-                void *mlsl_handle,
-                void *accel_handle,
-                void *compass_handle,
-                void *pressure_handle);
-int mpu3050_close(struct mldl_cfg *mldl_cfg,
-                 void *mlsl_handle,
-                 void *accel_handle,
-                 void *compass_handle,
-                 void *pressure_handle);
-int mpu3050_resume(struct mldl_cfg *mldl_cfg,
-                  void *gyro_handle,
-                  void *accel_handle,
-                  void *compass_handle,
-                  void *pressure_handle,
-                  bool resume_gyro,
-                  bool resume_accel,
-                  bool resume_compass,
-                  bool resume_pressure);
-int mpu3050_suspend(struct mldl_cfg *mldl_cfg,
-                   void *gyro_handle,
-                   void *accel_handle,
-                   void *compass_handle,
-                   void *pressure_handle,
-                   bool suspend_gyro,
-                   bool suspend_accel,
-                   bool suspend_compass,
-                   bool suspend_pressure);
-int mpu3050_read_accel(struct mldl_cfg *mldl_cfg,
-                      void *accel_handle,
-                      unsigned char *data);
-int mpu3050_read_compass(struct mldl_cfg *mldl_cfg,
-                        void *compass_handle,
-                        unsigned char *data);
-int mpu3050_read_pressure(struct mldl_cfg *mldl_cfg, void *mlsl_handle,
-                         unsigned char *data);
-
-int mpu3050_config_accel(struct mldl_cfg *mldl_cfg,
-                        void *accel_handle,
-                        struct ext_slave_config *data);
-int mpu3050_config_compass(struct mldl_cfg *mldl_cfg,
-                          void *compass_handle,
-                          struct ext_slave_config *data);
-int mpu3050_config_pressure(struct mldl_cfg *mldl_cfg,
-                           void *pressure_handle,
-                           struct ext_slave_config *data);
-
-int mpu3050_get_config_accel(struct mldl_cfg *mldl_cfg,
-                            void *accel_handle,
-                            struct ext_slave_config *data);
-int mpu3050_get_config_compass(struct mldl_cfg *mldl_cfg,
-                              void *compass_handle,
-                              struct ext_slave_config *data);
-int mpu3050_get_config_pressure(struct mldl_cfg *mldl_cfg,
-                               void *pressure_handle,
-                               struct ext_slave_config *data);
-
-
-#endif                         /* __MLDL_CFG_H__ */
-
-/**
- *@}
- */
diff --git a/drivers/misc/mpu3050/mlos-kernel.c b/drivers/misc/mpu3050/mlos-kernel.c
deleted file mode 100755 (executable)
index ced9ba4..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-/**
- * @defgroup
- * @brief
- *
- * @{
- * @file     mlos-kernel.c
- * @brief
- *
- *
- */
-
-#include "mlos.h"
-#include <linux/delay.h>
-#include <linux/slab.h>
-
-void *MLOSMalloc(unsigned int numBytes)
-{
-       return kmalloc(numBytes, GFP_KERNEL);
-}
-
-tMLError MLOSFree(void *ptr)
-{
-       kfree(ptr);
-       return ML_SUCCESS;
-}
-
-tMLError MLOSCreateMutex(HANDLE *mutex)
-{
-       /* @todo implement if needed */
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-}
-
-tMLError MLOSLockMutex(HANDLE mutex)
-{
-       /* @todo implement if needed */
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-}
-
-tMLError MLOSUnlockMutex(HANDLE mutex)
-{
-       /* @todo implement if needed */
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-}
-
-tMLError MLOSDestroyMutex(HANDLE handle)
-{
-       /* @todo implement if needed */
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-}
-
-FILE *MLOSFOpen(char *filename)
-{
-       /* @todo implement if needed */
-       return NULL;
-}
-
-void MLOSFClose(FILE *fp)
-{
-       /* @todo implement if needed */
-}
-
-void MLOSSleep(int mSecs)
-{
-       msleep(mSecs);
-}
-
-unsigned long MLOSGetTickCount(void)
-{
-       /* @todo implement if needed */
-       return ML_ERROR_FEATURE_NOT_IMPLEMENTED;
-}
diff --git a/drivers/misc/mpu3050/mlos.h b/drivers/misc/mpu3050/mlos.h
deleted file mode 100755 (executable)
index 4ebb86c..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-#ifndef _MLOS_H
-#define _MLOS_H
-
-#ifndef __KERNEL__
-#include <stdio.h>
-#endif
-
-#include "mltypes.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-       /* ------------ */
-       /* - Defines. - */
-       /* ------------ */
-
-       /* - MLOSCreateFile defines. - */
-
-#define MLOS_GENERIC_READ         ((unsigned int)0x80000000)
-#define MLOS_GENERIC_WRITE        ((unsigned int)0x40000000)
-#define MLOS_FILE_SHARE_READ      ((unsigned int)0x00000001)
-#define MLOS_FILE_SHARE_WRITE     ((unsigned int)0x00000002)
-#define MLOS_OPEN_EXISTING        ((unsigned int)0x00000003)
-
-       /* ---------- */
-       /* - Enums. - */
-       /* ---------- */
-
-       /* --------------- */
-       /* - Structures. - */
-       /* --------------- */
-
-       /* --------------------- */
-       /* - Function p-types. - */
-       /* --------------------- */
-
-       void *MLOSMalloc(unsigned int numBytes);
-       tMLError MLOSFree(void *ptr);
-       tMLError MLOSCreateMutex(HANDLE *mutex);
-       tMLError MLOSLockMutex(HANDLE mutex);
-       tMLError MLOSUnlockMutex(HANDLE mutex);
-       FILE *MLOSFOpen(char *filename);
-       void MLOSFClose(FILE *fp);
-
-       tMLError MLOSDestroyMutex(HANDLE handle);
-
-       void MLOSSleep(int mSecs);
-       unsigned long MLOSGetTickCount(void);
-
-#ifdef __cplusplus
-}
-#endif
-#endif                         /* _MLOS_H */
diff --git a/drivers/misc/mpu3050/mlsl-kernel.c b/drivers/misc/mpu3050/mlsl-kernel.c
deleted file mode 100755 (executable)
index cb16051..0000000
+++ /dev/null
@@ -1,331 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-#include "mlsl.h"
-#include "mpu-i2c.h"
-
-/* ------------ */
-/* - Defines. - */
-/* ------------ */
-
-/* ---------------------- */
-/* - Types definitions. - */
-/* ---------------------- */
-
-/* --------------------- */
-/* - Function p-types. - */
-/* --------------------- */
-
-/**
- *  @brief  used to open the I2C or SPI serial port.
- *          This port is used to send and receive data to the MPU device.
- *  @param  portNum
- *              The COM port number associated with the device in use.
- *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
- */
-tMLError MLSLSerialOpen(char const *port, void **sl_handle)
-{
-       return ML_SUCCESS;
-}
-
-/**
- *  @brief  used to reset any buffering the driver may be doing
- *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
- */
-tMLError MLSLSerialReset(void *sl_handle)
-{
-       return ML_SUCCESS;
-}
-
-/**
- *  @brief  used to close the I2C or SPI serial port.
- *          This port is used to send and receive data to the MPU device.
- *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
- */
-tMLError MLSLSerialClose(void *sl_handle)
-{
-       return ML_SUCCESS;
-}
-
-/**
- *  @brief  used to read a single byte of data.
- *          This should be sent by I2C or SPI.
- *
- *  @param  slaveAddr       I2C slave address of device.
- *  @param  registerAddr    Register address to read.
- *  @param  data            Single byte of data to read.
- *
- *  @return ML_SUCCESS if the command is successful, an error code otherwise.
- */
-tMLError MLSLSerialWriteSingle(void *sl_handle,
-                              unsigned char slaveAddr,
-                              unsigned char registerAddr,
-                              unsigned char data)
-{
-       return sensor_i2c_write_register((struct i2c_adapter *) sl_handle,
-                                        slaveAddr, registerAddr, data);
-}
-
-
-/**
- *  @brief  used to write multiple bytes of data from registers.
- *          This should be sent by I2C.
- *
- *  @param  slaveAddr       I2C slave address of device.
- *  @param  registerAddr    Register address to write.
- *  @param  length          Length of burst of data.
- *  @param  data            Pointer to block of data.
- *
- *  @return ML_SUCCESS if successful, a non-zero error code otherwise.
- */
-tMLError MLSLSerialWrite(void *sl_handle,
-                        unsigned char slaveAddr,
-                        unsigned short length,
-                        unsigned char const *data)
-{
-       tMLError result;
-       const unsigned short dataLength = length - 1;
-       const unsigned char startRegAddr = data[0];
-       unsigned char i2cWrite[SERIAL_MAX_TRANSFER_SIZE + 1];
-       unsigned short bytesWritten = 0;
-
-       while (bytesWritten < dataLength) {
-               unsigned short thisLen = min(SERIAL_MAX_TRANSFER_SIZE,
-                                            dataLength - bytesWritten);
-               if (bytesWritten == 0) {
-                       result = sensor_i2c_write((struct i2c_adapter *)
-                                                 sl_handle, slaveAddr,
-                                                 1 + thisLen, data);
-               } else {
-                       /* manually increment register addr between chunks */
-                       i2cWrite[0] = startRegAddr + bytesWritten;
-                       memcpy(&i2cWrite[1], &data[1 + bytesWritten],
-                              thisLen);
-                       result = sensor_i2c_write((struct i2c_adapter *)
-                                                 sl_handle, slaveAddr,
-                                                 1 + thisLen, i2cWrite);
-               }
-               if (ML_SUCCESS != result)
-                       return result;
-               bytesWritten += thisLen;
-       }
-       return ML_SUCCESS;
-}
-
-
-/**
- *  @brief  used to read multiple bytes of data from registers.
- *          This should be sent by I2C.
- *
- *  @param  slaveAddr       I2C slave address of device.
- *  @param  registerAddr    Register address to read.
- *  @param  length          Length of burst of data.
- *  @param  data            Pointer to block of data.
- *
- *  @return Zero if successful; an error code otherwise
- */
-tMLError MLSLSerialRead(void *sl_handle,
-                       unsigned char slaveAddr,
-                       unsigned char registerAddr,
-                       unsigned short length, unsigned char *data)
-{
-       tMLError result;
-       unsigned short bytesRead = 0;
-
-       if (registerAddr == MPUREG_FIFO_R_W
-           || registerAddr == MPUREG_MEM_R_W) {
-               return ML_ERROR_INVALID_PARAMETER;
-       }
-       while (bytesRead < length) {
-               unsigned short thisLen =
-                   min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead);
-               result =
-                   sensor_i2c_read((struct i2c_adapter *) sl_handle,
-                                   slaveAddr, registerAddr + bytesRead,
-                                   thisLen, &data[bytesRead]);
-               if (ML_SUCCESS != result)
-                       return result;
-               bytesRead += thisLen;
-       }
-       return ML_SUCCESS;
-}
-
-
-/**
- *  @brief  used to write multiple bytes of data to the memory.
- *          This should be sent by I2C.
- *
- *  @param  slaveAddr       I2C slave address of device.
- *  @param  memAddr         The location in the memory to write to.
- *  @param  length          Length of burst data.
- *  @param  data            Pointer to block of data.
- *
- *  @return Zero if successful; an error code otherwise
- */
-tMLError MLSLSerialWriteMem(void *sl_handle,
-                           unsigned char slaveAddr,
-                           unsigned short memAddr,
-                           unsigned short length,
-                           unsigned char const *data)
-{
-       tMLError result;
-       unsigned short bytesWritten = 0;
-
-       if ((memAddr & 0xFF) + length > MPU_MEM_BANK_SIZE) {
-               pr_err("memory read length (%d B) extends beyond its"
-                       " limits (%d) if started at location %d\n", length,
-                       MPU_MEM_BANK_SIZE, memAddr & 0xFF);
-               return ML_ERROR_INVALID_PARAMETER;
-       }
-       while (bytesWritten < length) {
-               unsigned short thisLen =
-                   min(SERIAL_MAX_TRANSFER_SIZE, length - bytesWritten);
-               result =
-                   mpu_memory_write((struct i2c_adapter *) sl_handle,
-                                    slaveAddr, memAddr + bytesWritten,
-                                    thisLen, &data[bytesWritten]);
-               if (ML_SUCCESS != result)
-                       return result;
-               bytesWritten += thisLen;
-       }
-       return ML_SUCCESS;
-}
-
-
-/**
- *  @brief  used to read multiple bytes of data from the memory.
- *          This should be sent by I2C.
- *
- *  @param  slaveAddr       I2C slave address of device.
- *  @param  memAddr         The location in the memory to read from.
- *  @param  length          Length of burst data.
- *  @param  data            Pointer to block of data.
- *
- *  @return Zero if successful; an error code otherwise
- */
-tMLError MLSLSerialReadMem(void *sl_handle,
-                          unsigned char slaveAddr,
-                          unsigned short memAddr,
-                          unsigned short length, unsigned char *data)
-{
-       tMLError result;
-       unsigned short bytesRead = 0;
-
-       if ((memAddr & 0xFF) + length > MPU_MEM_BANK_SIZE) {
-               printk
-                   ("memory read length (%d B) extends beyond its limits (%d) "
-                    "if started at location %d\n", length,
-                    MPU_MEM_BANK_SIZE, memAddr & 0xFF);
-               return ML_ERROR_INVALID_PARAMETER;
-       }
-       while (bytesRead < length) {
-               unsigned short thisLen =
-                   min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead);
-               result =
-                   mpu_memory_read((struct i2c_adapter *) sl_handle,
-                                   slaveAddr, memAddr + bytesRead,
-                                   thisLen, &data[bytesRead]);
-               if (ML_SUCCESS != result)
-                       return result;
-               bytesRead += thisLen;
-       }
-       return ML_SUCCESS;
-}
-
-
-/**
- *  @brief  used to write multiple bytes of data to the fifo.
- *          This should be sent by I2C.
- *
- *  @param  slaveAddr       I2C slave address of device.
- *  @param  length          Length of burst of data.
- *  @param  data            Pointer to block of data.
- *
- *  @return Zero if successful; an error code otherwise
- */
-tMLError MLSLSerialWriteFifo(void *sl_handle,
-                            unsigned char slaveAddr,
-                            unsigned short length,
-                            unsigned char const *data)
-{
-       tMLError result;
-       unsigned char i2cWrite[SERIAL_MAX_TRANSFER_SIZE + 1];
-       unsigned short bytesWritten = 0;
-
-       if (length > FIFO_HW_SIZE) {
-               printk(KERN_ERR
-                      "maximum fifo write length is %d\n", FIFO_HW_SIZE);
-               return ML_ERROR_INVALID_PARAMETER;
-       }
-       while (bytesWritten < length) {
-               unsigned short thisLen =
-                   min(SERIAL_MAX_TRANSFER_SIZE, length - bytesWritten);
-               i2cWrite[0] = MPUREG_FIFO_R_W;
-               memcpy(&i2cWrite[1], &data[bytesWritten], thisLen);
-               result = sensor_i2c_write((struct i2c_adapter *) sl_handle,
-                                         slaveAddr, thisLen + 1,
-                                         i2cWrite);
-               if (ML_SUCCESS != result)
-                       return result;
-               bytesWritten += thisLen;
-       }
-       return ML_SUCCESS;
-}
-
-
-/**
- *  @brief  used to read multiple bytes of data from the fifo.
- *          This should be sent by I2C.
- *
- *  @param  slaveAddr       I2C slave address of device.
- *  @param  length          Length of burst of data.
- *  @param  data            Pointer to block of data.
- *
- *  @return Zero if successful; an error code otherwise
- */
-tMLError MLSLSerialReadFifo(void *sl_handle,
-                           unsigned char slaveAddr,
-                           unsigned short length, unsigned char *data)
-{
-       tMLError result;
-       unsigned short bytesRead = 0;
-
-       if (length > FIFO_HW_SIZE) {
-               printk(KERN_ERR
-                      "maximum fifo read length is %d\n", FIFO_HW_SIZE);
-               return ML_ERROR_INVALID_PARAMETER;
-       }
-       while (bytesRead < length) {
-               unsigned short thisLen =
-                   min(SERIAL_MAX_TRANSFER_SIZE, length - bytesRead);
-               result =
-                   sensor_i2c_read((struct i2c_adapter *) sl_handle,
-                                   slaveAddr, MPUREG_FIFO_R_W, thisLen,
-                                   &data[bytesRead]);
-               if (ML_SUCCESS != result)
-                       return result;
-               bytesRead += thisLen;
-       }
-
-       return ML_SUCCESS;
-}
-
-/**
- *  @}
- */
diff --git a/drivers/misc/mpu3050/mlsl.h b/drivers/misc/mpu3050/mlsl.h
deleted file mode 100755 (executable)
index 76f69c7..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-#ifndef __MSSL_H__
-#define __MSSL_H__
-
-#include "mltypes.h"
-#include "mpu.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* ------------ */
-/* - Defines. - */
-/* ------------ */
-
-/*
- * NOTE : to properly support Yamaha compass reads,
- * the max transfer size should be at least 9 B.
- * Length in bytes, typically a power of 2 >= 2
- */
-#define SERIAL_MAX_TRANSFER_SIZE 128
-
-/* ---------------------- */
-/* - Types definitions. - */
-/* ---------------------- */
-
-/* --------------------- */
-/* - Function p-types. - */
-/* --------------------- */
-
-       tMLError MLSLSerialOpen(char const *port,
-                               void **sl_handle);
-       tMLError MLSLSerialReset(void *sl_handle);
-       tMLError MLSLSerialClose(void *sl_handle);
-
-       tMLError MLSLSerialWriteSingle(void *sl_handle,
-                                      unsigned char slaveAddr,
-                                      unsigned char registerAddr,
-                                      unsigned char data);
-
-       tMLError MLSLSerialRead(void *sl_handle,
-                               unsigned char slaveAddr,
-                               unsigned char registerAddr,
-                               unsigned short length,
-                               unsigned char *data);
-
-       tMLError MLSLSerialWrite(void *sl_handle,
-                                unsigned char slaveAddr,
-                                unsigned short length,
-                                unsigned char const *data);
-
-       tMLError MLSLSerialReadMem(void *sl_handle,
-                                  unsigned char slaveAddr,
-                                  unsigned short memAddr,
-                                  unsigned short length,
-                                  unsigned char *data);
-
-       tMLError MLSLSerialWriteMem(void *sl_handle,
-                                   unsigned char slaveAddr,
-                                   unsigned short memAddr,
-                                   unsigned short length,
-                                   unsigned char const *data);
-
-       tMLError MLSLSerialReadFifo(void *sl_handle,
-                                   unsigned char slaveAddr,
-                                   unsigned short length,
-                                   unsigned char *data);
-
-       tMLError MLSLSerialWriteFifo(void *sl_handle,
-                                    unsigned char slaveAddr,
-                                    unsigned short length,
-                                    unsigned char const *data);
-
-       tMLError MLSLWriteCal(unsigned char *cal, unsigned int len);
-       tMLError MLSLReadCal(unsigned char *cal, unsigned int len);
-       tMLError MLSLGetCalLength(unsigned int *len);
-
-#ifdef __cplusplus
-}
-#endif
-
-/**
- * @}
- */
-#endif                         /* MLSL_H */
diff --git a/drivers/misc/mpu3050/mltypes.h b/drivers/misc/mpu3050/mltypes.h
deleted file mode 100755 (executable)
index d0b27fa..0000000
+++ /dev/null
@@ -1,227 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup MLERROR
- *  @brief  Motion Library - Error definitions.
- *          Definition of the error codes used within the MPL and returned
- *          to the user.
- *          Every function tries to return a meaningful error code basing
- *          on the occuring error condition. The error code is numeric.
- *
- *          The available error codes and their associated values are:
- *          - (0)       ML_SUCCESS
- *          - (1)       ML_ERROR
- *          - (2)       ML_ERROR_INVALID_PARAMETER
- *          - (3)       ML_ERROR_FEATURE_NOT_ENABLED
- *          - (4)       ML_ERROR_FEATURE_NOT_IMPLEMENTED
- *          - (6)       ML_ERROR_DMP_NOT_STARTED
- *          - (7)       ML_ERROR_DMP_STARTED
- *          - (8)       ML_ERROR_NOT_OPENED
- *          - (9)       ML_ERROR_OPENED
- *          - (10)      ML_ERROR_INVALID_MODULE
- *          - (11)      ML_ERROR_MEMORY_EXAUSTED
- *          - (12)      ML_ERROR_DIVIDE_BY_ZERO
- *          - (13)      ML_ERROR_ASSERTION_FAILURE
- *          - (14)      ML_ERROR_FILE_OPEN
- *          - (15)      ML_ERROR_FILE_READ
- *          - (16)      ML_ERROR_FILE_WRITE
- *          - (20)      ML_ERROR_SERIAL_CLOSED
- *          - (21)      ML_ERROR_SERIAL_OPEN_ERROR
- *          - (22)      ML_ERROR_SERIAL_READ
- *          - (23)      ML_ERROR_SERIAL_WRITE
- *          - (24)      ML_ERROR_SERIAL_DEVICE_NOT_RECOGNIZED
- *          - (25)      ML_ERROR_SM_TRANSITION
- *          - (26)      ML_ERROR_SM_IMPROPER_STATE
- *          - (30)      ML_ERROR_FIFO_OVERFLOW
- *          - (31)      ML_ERROR_FIFO_FOOTER
- *          - (32)      ML_ERROR_FIFO_READ_COUNT
- *          - (33)      ML_ERROR_FIFO_READ_DATA
- *          - (40)      ML_ERROR_MEMORY_SET
- *          - (50)      ML_ERROR_LOG_MEMORY_ERROR
- *          - (51)      ML_ERROR_LOG_OUTPUT_ERROR
- *          - (60)      ML_ERROR_OS_BAD_PTR
- *          - (61)      ML_ERROR_OS_BAD_HANDLE
- *          - (62)      ML_ERROR_OS_CREATE_FAILED
- *          - (63)      ML_ERROR_OS_LOCK_FAILED
- *          - (70)      ML_ERROR_COMPASS_DATA_OVERFLOW
- *          - (71)      ML_ERROR_COMPASS_DATA_UNDERFLOW
- *          - (72)      ML_ERROR_COMPASS_DATA_NOT_READY
- *          - (73)      ML_ERROR_COMPASS_DATA_ERROR
- *          - (75)      ML_ERROR_CALIBRATION_LOAD
- *          - (76)      ML_ERROR_CALIBRATION_STORE
- *          - (77)      ML_ERROR_CALIBRATION_LEN
- *          - (78)      ML_ERROR_CALIBRATION_CHECKSUM
- *
- *  @{
- *      @file mltypes.h
- *  @}
- */
-
-#ifndef MLTYPES_H
-#define MLTYPES_H
-
-#ifdef __KERNEL__
-#include <linux/types.h>
-#else
-#include "stdint_invensense.h"
-#endif
-#include "log.h"
-
-/*---------------------------
-    ML Types
----------------------------*/
-
-/**
- *  @struct tMLError mltypes.h "mltypes"
- *  @brief  The MPL Error Code return type.
- *
- *  @code
- *      typedef unsigned char tMLError;
- *  @endcode
- */
-typedef unsigned char tMLError;
-
-#if defined(LINUX) || defined(__KERNEL__)
-typedef unsigned int HANDLE;
-#endif
-
-#ifdef __KERNEL__
-typedef HANDLE FILE;
-#endif
-
-#ifndef __cplusplus
-#ifndef __KERNEL__
-typedef int_fast8_t bool;
-#endif
-#endif
-
-/*---------------------------
-    ML Defines
----------------------------*/
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-/* Dimension of an array */
-#ifndef DIM
-#define DIM(array) (sizeof(array)/sizeof((array)[0]))
-#endif
-
-/* - ML Errors. - */
-#define ERROR_NAME(x)   (#x)
-#define ERROR_CHECK(x)                                                  \
-       do {                                                            \
-               if (ML_SUCCESS != x) {                                  \
-                       MPL_LOGE("%s|%s|%d returning %d\n",             \
-                               __FILE__, __func__, __LINE__, x);       \
-                       return x;                                       \
-               }                                                       \
-       } while (0)
-
-#define ERROR_CHECK_FIRST(first, x)                                     \
-       { if (ML_SUCCESS == first) first = x; }
-
-#define ML_SUCCESS                       (0)
-/* Generic Error code.  Proprietary Error Codes only */
-#define ML_ERROR                         (1)
-
-/* Compatibility and other generic error codes */
-#define ML_ERROR_INVALID_PARAMETER       (2)
-#define ML_ERROR_FEATURE_NOT_ENABLED     (3)
-#define ML_ERROR_FEATURE_NOT_IMPLEMENTED (4)
-#define ML_ERROR_DMP_NOT_STARTED         (6)
-#define ML_ERROR_DMP_STARTED             (7)
-#define ML_ERROR_NOT_OPENED              (8)
-#define ML_ERROR_OPENED                  (9)
-#define ML_ERROR_INVALID_MODULE         (10)
-#define ML_ERROR_MEMORY_EXAUSTED        (11)
-#define ML_ERROR_DIVIDE_BY_ZERO         (12)
-#define ML_ERROR_ASSERTION_FAILURE      (13)
-#define ML_ERROR_FILE_OPEN              (14)
-#define ML_ERROR_FILE_READ              (15)
-#define ML_ERROR_FILE_WRITE             (16)
-#define ML_ERROR_INVALID_CONFIGURATION  (17)
-
-/* Serial Communication */
-#define ML_ERROR_SERIAL_CLOSED          (20)
-#define ML_ERROR_SERIAL_OPEN_ERROR      (21)
-#define ML_ERROR_SERIAL_READ            (22)
-#define ML_ERROR_SERIAL_WRITE           (23)
-#define ML_ERROR_SERIAL_DEVICE_NOT_RECOGNIZED  (24)
-
-/* SM = State Machine */
-#define ML_ERROR_SM_TRANSITION          (25)
-#define ML_ERROR_SM_IMPROPER_STATE      (26)
-
-/* Fifo */
-#define ML_ERROR_FIFO_OVERFLOW          (30)
-#define ML_ERROR_FIFO_FOOTER            (31)
-#define ML_ERROR_FIFO_READ_COUNT        (32)
-#define ML_ERROR_FIFO_READ_DATA         (33)
-
-/* Memory & Registers, Set & Get */
-#define ML_ERROR_MEMORY_SET             (40)
-
-#define ML_ERROR_LOG_MEMORY_ERROR       (50)
-#define ML_ERROR_LOG_OUTPUT_ERROR       (51)
-
-/* OS interface errors */
-#define ML_ERROR_OS_BAD_PTR             (60)
-#define ML_ERROR_OS_BAD_HANDLE          (61)
-#define ML_ERROR_OS_CREATE_FAILED       (62)
-#define ML_ERROR_OS_LOCK_FAILED         (63)
-
-/* Compass errors */
-#define ML_ERROR_COMPASS_DATA_OVERFLOW  (70)
-#define ML_ERROR_COMPASS_DATA_UNDERFLOW (71)
-#define ML_ERROR_COMPASS_DATA_NOT_READY (72)
-#define ML_ERROR_COMPASS_DATA_ERROR     (73)
-
-/* Load/Store calibration */
-#define ML_ERROR_CALIBRATION_LOAD       (75)
-#define ML_ERROR_CALIBRATION_STORE      (76)
-#define ML_ERROR_CALIBRATION_LEN        (77)
-#define ML_ERROR_CALIBRATION_CHECKSUM   (78)
-
-/* Accel errors */
-#define ML_ERROR_ACCEL_DATA_OVERFLOW    (79)
-#define ML_ERROR_ACCEL_DATA_UNDERFLOW   (80)
-#define ML_ERROR_ACCEL_DATA_NOT_READY   (81)
-#define ML_ERROR_ACCEL_DATA_ERROR       (82)
-
-/* For Linux coding compliance */
-#ifndef __KERNEL__
-#define EXPORT_SYMBOL(x)
-#endif
-
-/*---------------------------
-    p-Types
----------------------------*/
-
-#endif                         /* MLTYPES_H */
diff --git a/drivers/misc/mpu3050/mpu-dev.c b/drivers/misc/mpu3050/mpu-dev.c
deleted file mode 100755 (executable)
index 34f6ba4..0000000
+++ /dev/null
@@ -1,1299 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-#include <linux/i2c.h>
-#include <linux/i2c-dev.h>
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/stat.h>
-#include <linux/irq.h>
-#include <linux/gpio.h>
-#include <linux/signal.h>
-#include <linux/miscdevice.h>
-#include <linux/slab.h>
-#include <linux/version.h>
-#include <linux/pm.h>
-#include <linux/mutex.h>
-#include <linux/suspend.h>
-#include <linux/poll.h>
-#ifdef CONFIG_HAS_EARLYSUSPEND
-#include <linux/earlysuspend.h>
-#endif
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-
-#include "mpuirq.h"
-#include "slaveirq.h"
-#include "mlsl.h"
-#include "mpu-i2c.h"
-#include "mldl_cfg.h"
-#include "mpu.h"
-
-#define MPU3050_EARLY_SUSPEND_IN_DRIVER 0
-
-/* Platform data for the MPU */
-struct mpu_private_data {
-       struct mldl_cfg mldl_cfg;
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-       struct early_suspend early_suspend;
-#endif
-       struct mutex mutex;
-       wait_queue_head_t mpu_event_wait;
-       struct completion completion;
-       struct timer_list timeout;
-       struct notifier_block nb;
-       struct mpuirq_data mpu_pm_event;
-       int response_timeout;   /* In seconds */
-       unsigned long event;
-       int pid;
-};
-
-static struct i2c_client *this_client;
-
-
-static void
-mpu_pm_timeout(u_long data)
-{
-       struct mpu_private_data *mpu = (struct mpu_private_data *) data;
-       dev_dbg(&this_client->adapter->dev, "%s\n", __func__);
-       complete(&mpu->completion);
-}
-
-static int mpu_pm_notifier_callback(struct notifier_block *nb,
-                                   unsigned long event,
-                                   void *unused)
-{
-       struct mpu_private_data *mpu =
-               container_of(nb, struct mpu_private_data, nb);
-       struct timeval event_time;
-       dev_dbg(&this_client->adapter->dev, "%s: %ld\n", __func__, event);
-
-       /* Prevent the file handle from being closed before we initialize
-          the completion event */
-       mutex_lock(&mpu->mutex);
-       if (!(mpu->pid) ||
-               (event != PM_SUSPEND_PREPARE && event != PM_POST_SUSPEND)) {
-               mutex_unlock(&mpu->mutex);
-               return NOTIFY_OK;
-       }
-
-       do_gettimeofday(&event_time);
-       mpu->mpu_pm_event.interruptcount++;
-       mpu->mpu_pm_event.irqtime =
-               (((long long) event_time.tv_sec) << 32) +
-               event_time.tv_usec;
-       mpu->mpu_pm_event.data_type = MPUIRQ_DATA_TYPE_PM_EVENT;
-       mpu->mpu_pm_event.data_size = sizeof(unsigned long);
-       mpu->mpu_pm_event.data = &mpu->event;
-
-       if (event == PM_SUSPEND_PREPARE)
-               mpu->event = MPU_PM_EVENT_SUSPEND_PREPARE;
-       if (event == PM_POST_SUSPEND)
-               mpu->event = MPU_PM_EVENT_POST_SUSPEND;
-
-       if (mpu->response_timeout > 0) {
-               mpu->timeout.expires = jiffies + mpu->response_timeout * HZ;
-               add_timer(&mpu->timeout);
-       }
-       INIT_COMPLETION(mpu->completion);
-       mutex_unlock(&mpu->mutex);
-
-       wake_up_interruptible(&mpu->mpu_event_wait);
-       wait_for_completion(&mpu->completion);
-       del_timer_sync(&mpu->timeout);
-       dev_dbg(&this_client->adapter->dev, "%s: %ld DONE\n", __func__, event);
-       return NOTIFY_OK;
-}
-
-static int mpu_open(struct inode *inode, struct file *file)
-{
-       struct mpu_private_data *mpu =
-           (struct mpu_private_data *) i2c_get_clientdata(this_client);
-       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-       int result;
-       dev_dbg(&this_client->adapter->dev, "mpu_open\n");
-       dev_dbg(&this_client->adapter->dev, "current->pid %d\n",
-               current->pid);
-       mpu->pid = current->pid;
-       file->private_data = this_client;
-       /* we could do some checking on the flags supplied by "open" */
-       /* i.e. O_NONBLOCK */
-       /* -> set some flag to disable interruptible_sleep_on in mpu_read */
-
-       /* Reset the sensors to the default */
-       result = mutex_lock_interruptible(&mpu->mutex);
-       if (result) {
-               dev_err(&this_client->adapter->dev,
-                       "%s: mutex_lock_interruptible returned %d\n",
-                       __func__, result);
-               return result;
-       }
-       mldl_cfg->requested_sensors = ML_THREE_AXIS_GYRO;
-       if (mldl_cfg->accel && mldl_cfg->accel->resume)
-               mldl_cfg->requested_sensors |= ML_THREE_AXIS_ACCEL;
-
-       if (mldl_cfg->compass && mldl_cfg->compass->resume)
-               mldl_cfg->requested_sensors |= ML_THREE_AXIS_COMPASS;
-
-       if (mldl_cfg->pressure && mldl_cfg->pressure->resume)
-               mldl_cfg->requested_sensors |= ML_THREE_AXIS_PRESSURE;
-       mutex_unlock(&mpu->mutex);
-       return 0;
-}
-
-/* close function - called when the "file" /dev/mpu is closed in userspace   */
-static int mpu_release(struct inode *inode, struct file *file)
-{
-       struct i2c_client *client =
-           (struct i2c_client *) file->private_data;
-       struct mpu_private_data *mpu =
-           (struct mpu_private_data *) i2c_get_clientdata(client);
-       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-       struct i2c_adapter *accel_adapter;
-       struct i2c_adapter *compass_adapter;
-       struct i2c_adapter *pressure_adapter;
-       int result = 0;
-
-       accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
-       compass_adapter = i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
-       pressure_adapter = i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
-
-       mutex_lock(&mpu->mutex);
-       result = mpu3050_suspend(mldl_cfg, client->adapter,
-                                accel_adapter, compass_adapter,
-                                pressure_adapter,
-                                TRUE, TRUE, TRUE, TRUE);
-       mpu->pid = 0;
-       mutex_unlock(&mpu->mutex);
-       complete(&mpu->completion);
-       dev_dbg(&this_client->adapter->dev, "mpu_release\n");
-       return result;
-}
-
-/* read function called when from /dev/mpu is read.  Read from the FIFO */
-static ssize_t mpu_read(struct file *file,
-                       char __user *buf, size_t count, loff_t *offset)
-{
-       struct mpuirq_data local_mpu_pm_event;
-       struct i2c_client *client =
-           (struct i2c_client *) file->private_data;
-       struct mpu_private_data *mpu =
-           (struct mpu_private_data *) i2c_get_clientdata(client);
-       size_t len = sizeof(mpu->mpu_pm_event) + sizeof(unsigned long);
-       int err;
-
-       if (!mpu->event && (!(file->f_flags & O_NONBLOCK)))
-               wait_event_interruptible(mpu->mpu_event_wait, mpu->event);
-
-       if (!mpu->event || NULL == buf
-               || count < sizeof(mpu->mpu_pm_event) + sizeof(unsigned long))
-               return 0;
-
-       err = copy_from_user(&local_mpu_pm_event, buf,
-                       sizeof(mpu->mpu_pm_event));
-       if (err != 0) {
-               dev_err(&this_client->adapter->dev,
-                       "Copy from user returned %d\n", err);
-               return -EFAULT;
-       }
-
-       mpu->mpu_pm_event.data = local_mpu_pm_event.data;
-       err = copy_to_user((unsigned long __user *)local_mpu_pm_event.data,
-                       &mpu->event,
-                       sizeof(mpu->event));
-       if (err != 0) {
-               dev_err(&this_client->adapter->dev,
-                       "Copy to user returned %d\n", err);
-               return -EFAULT;
-       }
-       err = copy_to_user(buf, &mpu->mpu_pm_event, sizeof(mpu->mpu_pm_event));
-       if (err != 0) {
-               dev_err(&this_client->adapter->dev,
-                       "Copy to user returned %d\n", err);
-               return -EFAULT;
-       }
-       mpu->event = 0;
-       return len;
-}
-
-static unsigned int mpu_poll(struct file *file, struct poll_table_struct *poll)
-{
-       struct i2c_client *client =
-           (struct i2c_client *) file->private_data;
-       struct mpu_private_data *mpu =
-           (struct mpu_private_data *) i2c_get_clientdata(client);
-       int mask = 0;
-
-       poll_wait(file, &mpu->mpu_event_wait, poll);
-       if (mpu->event)
-               mask |= POLLIN | POLLRDNORM;
-       return mask;
-}
-
-static int
-mpu_ioctl_set_mpu_pdata(struct i2c_client *client, unsigned long arg)
-{
-       int ii;
-       struct mpu_private_data *mpu =
-           (struct mpu_private_data *) i2c_get_clientdata(client);
-       struct mpu3050_platform_data *pdata = mpu->mldl_cfg.pdata;
-       struct mpu3050_platform_data local_pdata;
-
-       if (copy_from_user(&local_pdata, (unsigned char __user *) arg,
-                               sizeof(local_pdata)))
-               return -EFAULT;
-
-       pdata->int_config = local_pdata.int_config;
-       for (ii = 0; ii < DIM(pdata->orientation); ii++)
-               pdata->orientation[ii] = local_pdata.orientation[ii];
-       pdata->level_shifter = local_pdata.level_shifter;
-
-       pdata->accel.address = local_pdata.accel.address;
-       for (ii = 0; ii < DIM(pdata->accel.orientation); ii++)
-               pdata->accel.orientation[ii] =
-                       local_pdata.accel.orientation[ii];
-
-       pdata->compass.address = local_pdata.compass.address;
-       for (ii = 0; ii < DIM(pdata->compass.orientation); ii++)
-               pdata->compass.orientation[ii] =
-                       local_pdata.compass.orientation[ii];
-
-       pdata->pressure.address = local_pdata.pressure.address;
-       for (ii = 0; ii < DIM(pdata->pressure.orientation); ii++)
-               pdata->pressure.orientation[ii] =
-                       local_pdata.pressure.orientation[ii];
-
-       dev_dbg(&client->adapter->dev, "%s\n", __func__);
-
-       return ML_SUCCESS;
-}
-
-static int
-mpu_ioctl_set_mpu_config(struct i2c_client *client, unsigned long arg)
-{
-       int ii;
-       int result = ML_SUCCESS;
-       struct mpu_private_data *mpu =
-               (struct mpu_private_data *) i2c_get_clientdata(client);
-       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-       struct mldl_cfg *temp_mldl_cfg;
-
-       dev_dbg(&this_client->adapter->dev, "%s\n", __func__);
-
-       temp_mldl_cfg = kzalloc(sizeof(struct mldl_cfg), GFP_KERNEL);
-       if (NULL == temp_mldl_cfg)
-               return -ENOMEM;
-
-       /*
-        * User space is not allowed to modify accel compass pressure or
-        * pdata structs, as well as silicon_revision product_id or trim
-        */
-       if (copy_from_user(temp_mldl_cfg, (struct mldl_cfg __user *) arg,
-                               offsetof(struct mldl_cfg, silicon_revision))) {
-               result = -EFAULT;
-               goto out;
-       }
-
-       if (mldl_cfg->gyro_is_suspended) {
-               if (mldl_cfg->addr != temp_mldl_cfg->addr)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (mldl_cfg->int_config != temp_mldl_cfg->int_config)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (mldl_cfg->ext_sync != temp_mldl_cfg->ext_sync)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (mldl_cfg->full_scale != temp_mldl_cfg->full_scale)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (mldl_cfg->lpf != temp_mldl_cfg->lpf)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (mldl_cfg->clk_src != temp_mldl_cfg->clk_src)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (mldl_cfg->divider != temp_mldl_cfg->divider)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (mldl_cfg->dmp_enable != temp_mldl_cfg->dmp_enable)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (mldl_cfg->fifo_enable != temp_mldl_cfg->fifo_enable)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (mldl_cfg->dmp_cfg1 != temp_mldl_cfg->dmp_cfg1)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (mldl_cfg->dmp_cfg2 != temp_mldl_cfg->dmp_cfg2)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (mldl_cfg->gyro_power != temp_mldl_cfg->gyro_power)
-                       mldl_cfg->gyro_needs_reset = TRUE;
-
-               for (ii = 0; ii < MPU_NUM_AXES; ii++)
-                       if (mldl_cfg->offset_tc[ii] !=
-                           temp_mldl_cfg->offset_tc[ii])
-                               mldl_cfg->gyro_needs_reset = TRUE;
-
-               for (ii = 0; ii < MPU_NUM_AXES; ii++)
-                       if (mldl_cfg->offset[ii] != temp_mldl_cfg->offset[ii])
-                               mldl_cfg->gyro_needs_reset = TRUE;
-
-               if (memcmp(mldl_cfg->ram, temp_mldl_cfg->ram,
-                               MPU_MEM_NUM_RAM_BANKS * MPU_MEM_BANK_SIZE *
-                               sizeof(unsigned char)))
-                       mldl_cfg->gyro_needs_reset = TRUE;
-       }
-
-       memcpy(mldl_cfg, temp_mldl_cfg,
-               offsetof(struct mldl_cfg, silicon_revision));
-
-out:
-       kfree(temp_mldl_cfg);
-       return result;
-}
-
-static int
-mpu_ioctl_get_mpu_config(struct i2c_client *client, unsigned long arg)
-{
-       /* Have to be careful as there are 3 pointers in the mldl_cfg
-        * structure */
-       struct mpu_private_data *mpu =
-           (struct mpu_private_data *) i2c_get_clientdata(client);
-       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-       struct mldl_cfg *local_mldl_cfg;
-       int retval = 0;
-
-       local_mldl_cfg = kzalloc(sizeof(struct mldl_cfg), GFP_KERNEL);
-       if (NULL == local_mldl_cfg)
-               return -ENOMEM;
-
-       retval =
-           copy_from_user(local_mldl_cfg, (struct mldl_cfg __user *) arg,
-                          sizeof(struct mldl_cfg));
-       if (retval) {
-               dev_err(&this_client->adapter->dev,
-                       "%s|%s:%d: EFAULT on arg\n",
-                       __FILE__, __func__, __LINE__);
-               retval = -EFAULT;
-               goto out;
-       }
-
-       /* Fill in the accel, compass, pressure and pdata pointers */
-       if (mldl_cfg->accel) {
-               retval = copy_to_user((void __user *)local_mldl_cfg->accel,
-                                     mldl_cfg->accel,
-                                     sizeof(*mldl_cfg->accel));
-               if (retval) {
-                       dev_err(&this_client->adapter->dev,
-                               "%s|%s:%d: EFAULT on accel\n",
-                               __FILE__, __func__, __LINE__);
-                       retval = -EFAULT;
-                       goto out;
-               }
-       }
-
-       if (mldl_cfg->compass) {
-               retval = copy_to_user((void __user *)local_mldl_cfg->compass,
-                                     mldl_cfg->compass,
-                                     sizeof(*mldl_cfg->compass));
-               if (retval) {
-                       dev_err(&this_client->adapter->dev,
-                               "%s|%s:%d: EFAULT on compass\n",
-                               __FILE__, __func__, __LINE__);
-                       retval = -EFAULT;
-                       goto out;
-               }
-       }
-
-       if (mldl_cfg->pressure) {
-               retval = copy_to_user((void __user *)local_mldl_cfg->pressure,
-                                     mldl_cfg->pressure,
-                                     sizeof(*mldl_cfg->pressure));
-               if (retval) {
-                       dev_err(&this_client->adapter->dev,
-                               "%s|%s:%d: EFAULT on pressure\n",
-                               __FILE__, __func__, __LINE__);
-                       retval = -EFAULT;
-                       goto out;
-               }
-       }
-
-       if (mldl_cfg->pdata) {
-               retval = copy_to_user((void __user *)local_mldl_cfg->pdata,
-                                     mldl_cfg->pdata,
-                                     sizeof(*mldl_cfg->pdata));
-               if (retval) {
-                       dev_err(&this_client->adapter->dev,
-                               "%s|%s:%d: EFAULT on pdata\n",
-                               __FILE__, __func__, __LINE__);
-                       retval = -EFAULT;
-                       goto out;
-               }
-       }
-
-       /* Do not modify the accel, compass, pressure and pdata pointers */
-       retval = copy_to_user((struct mldl_cfg __user *) arg,
-                             mldl_cfg, offsetof(struct mldl_cfg, accel));
-
-       if (retval)
-               retval = -EFAULT;
-out:
-       kfree(local_mldl_cfg);
-       return retval;
-}
-
-/**
- * Pass a requested slave configuration to the slave sensor
- *
- * @param adapter the adaptor to use to communicate with the slave
- * @param mldl_cfg the mldl configuration structuer
- * @param slave pointer to the slave descriptor
- * @param usr_config The configuration to pass to the slave sensor
- *
- * @return 0 or non-zero error code
- */
-static int slave_config(void *adapter,
-                       struct mldl_cfg *mldl_cfg,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata,
-                       struct ext_slave_config __user *usr_config)
-{
-       int retval = ML_SUCCESS;
-       struct ext_slave_config config;
-       if ((!slave) || (!slave->config))
-               return retval;
-
-       retval = copy_from_user(&config, usr_config, sizeof(config));
-       if (retval)
-               return -EFAULT;
-
-       if (config.len && config.data) {
-               int *data;
-               data = kzalloc(config.len, GFP_KERNEL);
-               if (!data)
-                       return ML_ERROR_MEMORY_EXAUSTED;
-
-               retval = copy_from_user(data,
-                                       (void __user *)config.data,
-                                       config.len);
-               if (retval) {
-                       retval = -EFAULT;
-                       kfree(data);
-                       return retval;
-               }
-               config.data = data;
-       }
-       retval = slave->config(adapter, slave, pdata, &config);
-       kfree(config.data);
-       return retval;
-}
-
-/**
- * Get a requested slave configuration from the slave sensor
- *
- * @param adapter the adaptor to use to communicate with the slave
- * @param mldl_cfg the mldl configuration structuer
- * @param slave pointer to the slave descriptor
- * @param usr_config The configuration for the slave to fill out
- *
- * @return 0 or non-zero error code
- */
-static int slave_get_config(void *adapter,
-                       struct mldl_cfg *mldl_cfg,
-                       struct ext_slave_descr *slave,
-                       struct ext_slave_platform_data *pdata,
-                       struct ext_slave_config __user *usr_config)
-{
-       int retval = ML_SUCCESS;
-       struct ext_slave_config config;
-       void *user_data;
-       if (!(slave) || !(slave->get_config))
-               return ML_SUCCESS;
-
-       retval = copy_from_user(&config, usr_config, sizeof(config));
-       if (retval)
-               return -EFAULT;
-
-       user_data = config.data;
-       if (config.len && config.data) {
-               int *data;
-               data = kzalloc(config.len, GFP_KERNEL);
-               if (!data)
-                       return ML_ERROR_MEMORY_EXAUSTED;
-
-               retval = copy_from_user(data,
-                                       (void __user *)config.data,
-                                       config.len);
-               if (retval) {
-                       retval = -EFAULT;
-                       kfree(data);
-                       return retval;
-               }
-               config.data = data;
-       }
-       retval = slave->get_config(adapter, slave, pdata, &config);
-       if (retval) {
-               kfree(config.data);
-               return retval;
-       }
-       retval = copy_to_user((unsigned char __user *) user_data,
-                       config.data,
-                       config.len);
-       kfree(config.data);
-       return retval;
-}
-
-static int mpu_handle_mlsl(void *sl_handle,
-                       unsigned char addr,
-                       unsigned int cmd,
-                       struct mpu_read_write __user *usr_msg)
-{
-       int retval = ML_SUCCESS;
-       struct mpu_read_write msg;
-       unsigned char *user_data;
-       retval = copy_from_user(&msg, usr_msg, sizeof(msg));
-       if (retval)
-               return -EFAULT;
-
-       user_data = msg.data;
-       if (msg.length && msg.data) {
-               unsigned char *data;
-               data = kzalloc(msg.length, GFP_KERNEL);
-               if (!data)
-                       return ML_ERROR_MEMORY_EXAUSTED;
-
-               retval = copy_from_user(data,
-                                       (void __user *)msg.data,
-                                       msg.length);
-               if (retval) {
-                       retval = -EFAULT;
-                       kfree(data);
-                       return retval;
-               }
-               msg.data = data;
-       } else {
-               return ML_ERROR_INVALID_PARAMETER;
-       }
-
-       switch (cmd) {
-       case MPU_READ:
-               retval = MLSLSerialRead(sl_handle, addr,
-                                       msg.address, msg.length, msg.data);
-               break;
-       case MPU_WRITE:
-               retval = MLSLSerialWrite(sl_handle, addr,
-                                       msg.length, msg.data);
-               break;
-       case MPU_READ_MEM:
-               retval = MLSLSerialReadMem(sl_handle, addr,
-                                       msg.address, msg.length, msg.data);
-               break;
-       case MPU_WRITE_MEM:
-               retval = MLSLSerialWriteMem(sl_handle, addr,
-                                       msg.address, msg.length, msg.data);
-               break;
-       case MPU_READ_FIFO:
-               retval = MLSLSerialReadFifo(sl_handle, addr,
-                                       msg.length, msg.data);
-               break;
-       case MPU_WRITE_FIFO:
-               retval = MLSLSerialWriteFifo(sl_handle, addr,
-                                       msg.length, msg.data);
-               break;
-
-       };
-       retval = copy_to_user((unsigned char __user *) user_data,
-                       msg.data,
-                       msg.length);
-       kfree(msg.data);
-       return retval;
-}
-
-/* ioctl - I/O control */
-static long mpu_ioctl(struct file *file,
-                     unsigned int cmd, unsigned long arg)
-{
-       struct i2c_client *client =
-           (struct i2c_client *) file->private_data;
-       struct mpu_private_data *mpu =
-           (struct mpu_private_data *) i2c_get_clientdata(client);
-       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-       int retval = 0;
-       struct i2c_adapter *accel_adapter;
-       struct i2c_adapter *compass_adapter;
-       struct i2c_adapter *pressure_adapter;
-
-       accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
-       compass_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
-       pressure_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
-
-       retval = mutex_lock_interruptible(&mpu->mutex);
-       if (retval) {
-               dev_err(&this_client->adapter->dev,
-                       "%s: mutex_lock_interruptible returned %d\n",
-                       __func__, retval);
-               return retval;
-       }
-
-       switch (cmd) {
-       case MPU_SET_MPU_CONFIG:
-               retval = mpu_ioctl_set_mpu_config(client, arg);
-               break;
-       case MPU_SET_PLATFORM_DATA:
-               retval = mpu_ioctl_set_mpu_pdata(client, arg);
-               break;
-       case MPU_GET_MPU_CONFIG:
-               retval = mpu_ioctl_get_mpu_config(client, arg);
-               break;
-       case MPU_READ:
-       case MPU_WRITE:
-       case MPU_READ_MEM:
-       case MPU_WRITE_MEM:
-       case MPU_READ_FIFO:
-       case MPU_WRITE_FIFO:
-               retval = mpu_handle_mlsl(client->adapter, mldl_cfg->addr, cmd,
-                                       (struct mpu_read_write __user *) arg);
-               break;
-       case MPU_CONFIG_ACCEL:
-               retval = slave_config(accel_adapter, mldl_cfg,
-                               mldl_cfg->accel,
-                               &mldl_cfg->pdata->accel,
-                               (struct ext_slave_config __user *) arg);
-               break;
-       case MPU_CONFIG_COMPASS:
-               retval = slave_config(compass_adapter, mldl_cfg,
-                               mldl_cfg->compass,
-                               &mldl_cfg->pdata->compass,
-                               (struct ext_slave_config __user *) arg);
-               break;
-       case MPU_CONFIG_PRESSURE:
-               retval = slave_config(pressure_adapter, mldl_cfg,
-                               mldl_cfg->pressure,
-                               &mldl_cfg->pdata->pressure,
-                               (struct ext_slave_config __user *) arg);
-               break;
-       case MPU_GET_CONFIG_ACCEL:
-               retval = slave_get_config(accel_adapter, mldl_cfg,
-                                       mldl_cfg->accel,
-                                       &mldl_cfg->pdata->accel,
-                                       (struct ext_slave_config __user *) arg);
-               break;
-       case MPU_GET_CONFIG_COMPASS:
-               retval = slave_get_config(compass_adapter, mldl_cfg,
-                                       mldl_cfg->compass,
-                                       &mldl_cfg->pdata->compass,
-                                       (struct ext_slave_config __user *) arg);
-               break;
-       case MPU_GET_CONFIG_PRESSURE:
-               retval = slave_get_config(pressure_adapter, mldl_cfg,
-                                       mldl_cfg->pressure,
-                                       &mldl_cfg->pdata->pressure,
-                                       (struct ext_slave_config __user *) arg);
-               break;
-       case MPU_SUSPEND:
-       {
-               unsigned long sensors;
-               sensors = ~(mldl_cfg->requested_sensors);
-               retval = mpu3050_suspend(mldl_cfg,
-                                       client->adapter,
-                                       accel_adapter,
-                                       compass_adapter,
-                                       pressure_adapter,
-                                       ((sensors & ML_THREE_AXIS_GYRO)
-                                               == ML_THREE_AXIS_GYRO),
-                                       ((sensors & ML_THREE_AXIS_ACCEL)
-                                               == ML_THREE_AXIS_ACCEL),
-                                       ((sensors & ML_THREE_AXIS_COMPASS)
-                                               == ML_THREE_AXIS_COMPASS),
-                                       ((sensors & ML_THREE_AXIS_PRESSURE)
-                                               == ML_THREE_AXIS_PRESSURE));
-       }
-       break;
-       case MPU_RESUME:
-       {
-               unsigned long sensors;
-               sensors = mldl_cfg->requested_sensors;
-               retval = mpu3050_resume(mldl_cfg,
-                                       client->adapter,
-                                       accel_adapter,
-                                       compass_adapter,
-                                       pressure_adapter,
-                                       sensors & ML_THREE_AXIS_GYRO,
-                                       sensors & ML_THREE_AXIS_ACCEL,
-                                       sensors & ML_THREE_AXIS_COMPASS,
-                                       sensors & ML_THREE_AXIS_PRESSURE);
-       }
-       break;
-       case MPU_PM_EVENT_HANDLED:
-               dev_dbg(&this_client->adapter->dev,
-                       "%s: %d\n", __func__, cmd);
-               complete(&mpu->completion);
-               break;
-       case MPU_READ_ACCEL:
-       {
-               unsigned char data[6];
-               retval = mpu3050_read_accel(mldl_cfg, client->adapter,
-                                           data);
-               if ((ML_SUCCESS == retval) &&
-                   (copy_to_user((unsigned char __user *) arg,
-                           data, sizeof(data))))
-                       retval = -EFAULT;
-       }
-       break;
-       case MPU_READ_COMPASS:
-       {
-               unsigned char data[6];
-               struct i2c_adapter *compass_adapt =
-                       i2c_get_adapter(mldl_cfg->pdata->compass.
-                                       adapt_num);
-               retval = mpu3050_read_compass(mldl_cfg, compass_adapt,
-                                                data);
-               if ((ML_SUCCESS == retval) &&
-                       (copy_to_user((unsigned char *) arg,
-                               data, sizeof(data))))
-                       retval = -EFAULT;
-       }
-       break;
-       case MPU_READ_PRESSURE:
-       {
-               unsigned char data[3];
-               struct i2c_adapter *pressure_adapt =
-                       i2c_get_adapter(mldl_cfg->pdata->pressure.
-                                       adapt_num);
-               retval =
-                       mpu3050_read_pressure(mldl_cfg, pressure_adapt,
-                                       data);
-               if ((ML_SUCCESS == retval) &&
-                   (copy_to_user((unsigned char __user *) arg,
-                           data, sizeof(data))))
-                       retval = -EFAULT;
-       }
-       break;
-       default:
-               dev_err(&this_client->adapter->dev,
-                       "%s: Unknown cmd %x, arg %lu\n", __func__, cmd,
-                       arg);
-               retval = -EINVAL;
-       }
-
-       mutex_unlock(&mpu->mutex);
-       return retval;
-}
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-void mpu3050_early_suspend(struct early_suspend *h)
-{
-       struct mpu_private_data *mpu = container_of(h,
-                                                   struct
-                                                   mpu_private_data,
-                                                   early_suspend);
-       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-       struct i2c_adapter *accel_adapter;
-       struct i2c_adapter *compass_adapter;
-       struct i2c_adapter *pressure_adapter;
-
-       accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
-       compass_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
-       pressure_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
-
-       dev_dbg(&this_client->adapter->dev, "%s: %d, %d\n", __func__,
-               h->level, mpu->mldl_cfg.gyro_is_suspended);
-       if (MPU3050_EARLY_SUSPEND_IN_DRIVER) {
-               mutex_lock(&mpu->mutex);
-               (void) mpu3050_suspend(mldl_cfg, this_client->adapter,
-                               accel_adapter, compass_adapter,
-                               pressure_adapter, TRUE, TRUE, TRUE, TRUE);
-               mutex_unlock(&mpu->mutex);
-       }
-}
-
-void mpu3050_early_resume(struct early_suspend *h)
-{
-       struct mpu_private_data *mpu = container_of(h,
-                                                   struct
-                                                   mpu_private_data,
-                                                   early_suspend);
-       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-       struct i2c_adapter *accel_adapter;
-       struct i2c_adapter *compass_adapter;
-       struct i2c_adapter *pressure_adapter;
-
-       accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
-       compass_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
-       pressure_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
-
-       if (MPU3050_EARLY_SUSPEND_IN_DRIVER) {
-               if (mpu->pid) {
-                       unsigned long sensors = mldl_cfg->requested_sensors;
-                       mutex_lock(&mpu->mutex);
-                       (void) mpu3050_resume(mldl_cfg,
-                                       this_client->adapter,
-                                       accel_adapter,
-                                       compass_adapter,
-                                       pressure_adapter,
-                                       sensors & ML_THREE_AXIS_GYRO,
-                                       sensors & ML_THREE_AXIS_ACCEL,
-                                       sensors & ML_THREE_AXIS_COMPASS,
-                                       sensors & ML_THREE_AXIS_PRESSURE);
-                       mutex_unlock(&mpu->mutex);
-                       dev_dbg(&this_client->adapter->dev,
-                               "%s for pid %d\n", __func__, mpu->pid);
-               }
-       }
-       dev_dbg(&this_client->adapter->dev, "%s: %d\n", __func__, h->level);
-}
-#endif
-
-void mpu_shutdown(struct i2c_client *client)
-{
-       struct mpu_private_data *mpu =
-           (struct mpu_private_data *) i2c_get_clientdata(client);
-       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-       struct i2c_adapter *accel_adapter;
-       struct i2c_adapter *compass_adapter;
-       struct i2c_adapter *pressure_adapter;
-
-       accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
-       compass_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
-       pressure_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
-
-       mutex_lock(&mpu->mutex);
-       (void) mpu3050_suspend(mldl_cfg, this_client->adapter,
-                              accel_adapter, compass_adapter, pressure_adapter,
-                              TRUE, TRUE, TRUE, TRUE);
-       mutex_unlock(&mpu->mutex);
-       dev_dbg(&this_client->adapter->dev, "%s\n", __func__);
-}
-
-int mpu_suspend(struct i2c_client *client, pm_message_t mesg)
-{
-       struct mpu_private_data *mpu =
-           (struct mpu_private_data *) i2c_get_clientdata(client);
-       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-       struct i2c_adapter *accel_adapter;
-       struct i2c_adapter *compass_adapter;
-       struct i2c_adapter *pressure_adapter;
-
-       accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
-       compass_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
-       pressure_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
-
-       mutex_lock(&mpu->mutex);
-       if (!mldl_cfg->ignore_system_suspend) {
-               dev_dbg(&this_client->adapter->dev,
-                       "%s: suspending on event %d\n", __func__,
-                       mesg.event);
-               (void) mpu3050_suspend(mldl_cfg, this_client->adapter,
-                                      accel_adapter, compass_adapter,
-                                      pressure_adapter,
-                                      TRUE, TRUE, TRUE, TRUE);
-       } else {
-               dev_dbg(&this_client->adapter->dev,
-                       "%s: Already suspended %d\n", __func__,
-                       mesg.event);
-       }
-       mutex_unlock(&mpu->mutex);
-       return 0;
-}
-
-int mpu_resume(struct i2c_client *client)
-{
-       struct mpu_private_data *mpu =
-           (struct mpu_private_data *) i2c_get_clientdata(client);
-       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-       struct i2c_adapter *accel_adapter;
-       struct i2c_adapter *compass_adapter;
-       struct i2c_adapter *pressure_adapter;
-
-       accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
-       compass_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
-       pressure_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
-
-       mutex_lock(&mpu->mutex);
-       if (mpu->pid && !mldl_cfg->ignore_system_suspend) {
-               unsigned long sensors = mldl_cfg->requested_sensors;
-               (void) mpu3050_resume(mldl_cfg, this_client->adapter,
-                                     accel_adapter,
-                                     compass_adapter,
-                                     pressure_adapter,
-                                     sensors & ML_THREE_AXIS_GYRO,
-                                     sensors & ML_THREE_AXIS_ACCEL,
-                                     sensors & ML_THREE_AXIS_COMPASS,
-                                     sensors & ML_THREE_AXIS_PRESSURE);
-               dev_dbg(&this_client->adapter->dev,
-                       "%s for pid %d\n", __func__, mpu->pid);
-       }
-       mutex_unlock(&mpu->mutex);
-       return 0;
-}
-
-/* define which file operations are supported */
-static const struct file_operations mpu_fops = {
-       .owner = THIS_MODULE,
-       .read = mpu_read,
-       .poll = mpu_poll,
-
-#if HAVE_COMPAT_IOCTL
-       .compat_ioctl = mpu_ioctl,
-#endif
-#if HAVE_UNLOCKED_IOCTL
-       .unlocked_ioctl = mpu_ioctl,
-#endif
-       .open = mpu_open,
-       .release = mpu_release,
-};
-
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
-I2C_CLIENT_INSMOD;
-#endif
-
-static struct miscdevice i2c_mpu_device = {
-       .minor = MISC_DYNAMIC_MINOR,
-       .name = "mpu", /* Same for both 3050 and 6000 */
-       .fops = &mpu_fops,
-};
-
-
-int mpu3050_probe(struct i2c_client *client,
-                 const struct i2c_device_id *devid)
-{
-       struct mpu3050_platform_data *pdata;
-       struct mpu_private_data *mpu;
-       struct mldl_cfg *mldl_cfg;
-       int res = 0;
-       struct i2c_adapter *accel_adapter = NULL;
-       struct i2c_adapter *compass_adapter = NULL;
-       struct i2c_adapter *pressure_adapter = NULL;
-
-       dev_dbg(&client->adapter->dev, "%s\n", __func__);
-
-       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
-               res = -ENODEV;
-               goto out_check_functionality_failed;
-       }
-
-       mpu = kzalloc(sizeof(struct mpu_private_data), GFP_KERNEL);
-       if (!mpu) {
-               res = -ENOMEM;
-               goto out_alloc_data_failed;
-       }
-
-       i2c_set_clientdata(client, mpu);
-       this_client = client;
-       mldl_cfg = &mpu->mldl_cfg;
-
-       init_waitqueue_head(&mpu->mpu_event_wait);
-
-       mutex_init(&mpu->mutex);
-       init_completion(&mpu->completion);
-
-       mpu->response_timeout = 60; /* Seconds */
-       mpu->timeout.function = mpu_pm_timeout;
-       mpu->timeout.data = (u_long) mpu;
-       init_timer(&mpu->timeout);
-
-       mpu->nb.notifier_call = mpu_pm_notifier_callback;
-       mpu->nb.priority = 0;
-       register_pm_notifier(&mpu->nb);
-
-       pdata = (struct mpu3050_platform_data *) client->dev.platform_data;
-       if (!pdata) {
-               dev_WARN(&this_client->adapter->dev,
-                        "Missing platform data for mpu3050\n");
-       } else {
-               mldl_cfg->pdata = pdata;
-
-#if defined(CONFIG_MPU_SENSORS_MPU3050_MODULE) || \
-    defined(CONFIG_MPU_SENSORS_MPU6000_MODULE)
-               pdata->accel.get_slave_descr = get_accel_slave_descr;
-               pdata->compass.get_slave_descr = get_compass_slave_descr;
-               pdata->pressure.get_slave_descr = get_pressure_slave_descr;
-#endif
-
-               if (pdata->accel.get_slave_descr) {
-                       mldl_cfg->accel =
-                           pdata->accel.get_slave_descr();
-                       dev_info(&this_client->adapter->dev,
-                                "%s: +%s\n", MPU_NAME,
-                                mldl_cfg->accel->name);
-                       accel_adapter =
-                               i2c_get_adapter(pdata->accel.adapt_num);
-                       if (pdata->accel.irq > 0) {
-                               dev_info(&this_client->adapter->dev,
-                                       "Installing Accel irq using %d\n",
-                                       pdata->accel.irq);
-                               res = slaveirq_init(accel_adapter,
-                                               &pdata->accel,
-                                               "accelirq");
-                               if (res)
-                                       goto out_accelirq_failed;
-                       } else {
-                               dev_warn(&this_client->adapter->dev,
-                                       "WARNING: Accel irq not assigned\n");
-                       }
-               } else {
-                       dev_warn(&this_client->adapter->dev,
-                                "%s: No Accel Present\n", MPU_NAME);
-               }
-
-               if (pdata->compass.get_slave_descr) {
-                       mldl_cfg->compass =
-                           pdata->compass.get_slave_descr();
-                       dev_info(&this_client->adapter->dev,
-                                "%s: +%s\n", MPU_NAME,
-                                mldl_cfg->compass->name);
-                       compass_adapter =
-                               i2c_get_adapter(pdata->compass.adapt_num);
-                       if (pdata->compass.irq > 0) {
-                               dev_info(&this_client->adapter->dev,
-                                       "Installing Compass irq using %d\n",
-                                       pdata->compass.irq);
-                               res = slaveirq_init(compass_adapter,
-                                               &pdata->compass,
-                                               "compassirq");
-                               if (res)
-                                       goto out_compassirq_failed;
-                       } else {
-                               dev_warn(&this_client->adapter->dev,
-                                       "WARNING: Compass irq not assigned\n");
-                       }
-               } else {
-                       dev_warn(&this_client->adapter->dev,
-                                "%s: No Compass Present\n", MPU_NAME);
-               }
-
-               if (pdata->pressure.get_slave_descr) {
-                       mldl_cfg->pressure =
-                           pdata->pressure.get_slave_descr();
-                       dev_info(&this_client->adapter->dev,
-                                "%s: +%s\n", MPU_NAME,
-                                mldl_cfg->pressure->name);
-                       pressure_adapter =
-                               i2c_get_adapter(pdata->pressure.adapt_num);
-
-                       if (pdata->pressure.irq > 0) {
-                               dev_info(&this_client->adapter->dev,
-                                       "Installing Pressure irq using %d\n",
-                                       pdata->pressure.irq);
-                               res = slaveirq_init(pressure_adapter,
-                                               &pdata->pressure,
-                                               "pressureirq");
-                               if (res)
-                                       goto out_pressureirq_failed;
-                       } else {
-                               dev_warn(&this_client->adapter->dev,
-                                       "WARNING: Pressure irq not assigned\n");
-                       }
-               } else {
-                       dev_warn(&this_client->adapter->dev,
-                                "%s: No Pressure Present\n", MPU_NAME);
-               }
-       }
-
-       mldl_cfg->addr = client->addr;
-       res = mpu3050_open(&mpu->mldl_cfg, client->adapter,
-                       accel_adapter, compass_adapter, pressure_adapter);
-
-       if (res) {
-               dev_err(&this_client->adapter->dev,
-                       "Unable to open %s %d\n", MPU_NAME, res);
-               res = -ENODEV;
-               goto out_whoami_failed;
-       }
-
-       res = misc_register(&i2c_mpu_device);
-       if (res < 0) {
-               dev_err(&this_client->adapter->dev,
-                       "ERROR: misc_register returned %d\n", res);
-               goto out_misc_register_failed;
-       }
-
-       if (this_client->irq > 0) {
-               dev_info(&this_client->adapter->dev,
-                        "Installing irq using %d\n", this_client->irq);
-               res = mpuirq_init(this_client);
-               if (res)
-                       goto out_mpuirq_failed;
-       } else {
-               dev_WARN(&this_client->adapter->dev,
-                       "Missing %s IRQ\n", MPU_NAME);
-       }
-
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-       mpu->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
-       mpu->early_suspend.suspend = mpu3050_early_suspend;
-       mpu->early_suspend.resume = mpu3050_early_resume;
-       register_early_suspend(&mpu->early_suspend);
-#endif
-       return res;
-
-out_mpuirq_failed:
-       misc_deregister(&i2c_mpu_device);
-out_misc_register_failed:
-       mpu3050_close(&mpu->mldl_cfg, client->adapter,
-               accel_adapter, compass_adapter, pressure_adapter);
-out_whoami_failed:
-       if (pdata &&
-           pdata->pressure.get_slave_descr &&
-           pdata->pressure.irq)
-               slaveirq_exit(&pdata->pressure);
-out_pressureirq_failed:
-       if (pdata &&
-           pdata->compass.get_slave_descr &&
-           pdata->compass.irq)
-               slaveirq_exit(&pdata->compass);
-out_compassirq_failed:
-       if (pdata &&
-           pdata->accel.get_slave_descr &&
-           pdata->accel.irq)
-               slaveirq_exit(&pdata->accel);
-out_accelirq_failed:
-       kfree(mpu);
-out_alloc_data_failed:
-out_check_functionality_failed:
-       dev_err(&this_client->adapter->dev, "%s failed %d\n", __func__,
-               res);
-       return res;
-
-}
-
-static int mpu3050_remove(struct i2c_client *client)
-{
-       struct mpu_private_data *mpu = i2c_get_clientdata(client);
-       struct i2c_adapter *accel_adapter;
-       struct i2c_adapter *compass_adapter;
-       struct i2c_adapter *pressure_adapter;
-       struct mldl_cfg *mldl_cfg = &mpu->mldl_cfg;
-       struct mpu3050_platform_data *pdata = mldl_cfg->pdata;
-
-       accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
-       compass_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->compass.adapt_num);
-       pressure_adapter =
-           i2c_get_adapter(mldl_cfg->pdata->pressure.adapt_num);
-
-       dev_dbg(&client->adapter->dev, "%s\n", __func__);
-
-#ifdef CONFIG_HAS_EARLYSUSPEND
-       unregister_early_suspend(&mpu->early_suspend);
-#endif
-       mpu3050_close(mldl_cfg, client->adapter,
-               accel_adapter, compass_adapter, pressure_adapter);
-
-       if (client->irq)
-               mpuirq_exit();
-
-       if (pdata &&
-           pdata->pressure.get_slave_descr &&
-           pdata->pressure.irq)
-               slaveirq_exit(&pdata->pressure);
-
-       if (pdata &&
-           pdata->compass.get_slave_descr &&
-           pdata->compass.irq)
-               slaveirq_exit(&pdata->compass);
-
-       if (pdata &&
-           pdata->accel.get_slave_descr &&
-           pdata->accel.irq)
-               slaveirq_exit(&pdata->accel);
-
-       misc_deregister(&i2c_mpu_device);
-       kfree(mpu);
-
-       return 0;
-}
-
-static const struct i2c_device_id mpu3050_id[] = {
-       {MPU_NAME, 0},
-       {}
-};
-
-MODULE_DEVICE_TABLE(i2c, mpu3050_id);
-
-static struct i2c_driver mpu3050_driver = {
-       .class = I2C_CLASS_HWMON,
-       .probe = mpu3050_probe,
-       .remove = mpu3050_remove,
-       .id_table = mpu3050_id,
-       .driver = {
-                  .owner = THIS_MODULE,
-                  .name = MPU_NAME,
-                  },
-#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 32)
-       .address_data = &addr_data,
-#else
-       .address_list = normal_i2c,
-#endif
-
-       .shutdown = mpu_shutdown,       /* optional */
-       .suspend = mpu_suspend, /* optional */
-       .resume = mpu_resume,   /* optional */
-
-};
-
-static int __init mpu_init(void)
-{
-       int res = i2c_add_driver(&mpu3050_driver);
-       pr_debug("%s\n", __func__);
-       if (res)
-               pr_err("%s failed\n",
-                       __func__);
-       return res;
-}
-
-static void __exit mpu_exit(void)
-{
-       pr_debug("%s\n", __func__);
-       i2c_del_driver(&mpu3050_driver);
-}
-
-module_init(mpu_init);
-module_exit(mpu_exit);
-
-MODULE_AUTHOR("Invensense Corporation");
-MODULE_DESCRIPTION("User space character device interface for MPU3050");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS(MPU_NAME);
diff --git a/drivers/misc/mpu3050/mpu-i2c.c b/drivers/misc/mpu3050/mpu-i2c.c
deleted file mode 100755 (executable)
index f3d8188..0000000
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-/**
- *  @defgroup
- *  @brief
- *
- *  @{
- *      @file   mpu-i2c.c
- *      @brief
- *
- */
-
-#include <linux/i2c.h>
-#include "mpu.h"
-
-#define MPU_I2C_RATE 100*1000
-
-int sensor_i2c_write(struct i2c_adapter *i2c_adap,
-                    unsigned char address,
-                    unsigned int len, unsigned char const *data)
-{
-       struct i2c_msg msgs[1];
-       int res;
-
-       if (NULL == data || NULL == i2c_adap)
-               return -EINVAL;
-
-       msgs[0].addr = address;
-       msgs[0].flags = 0;      /* write */
-       msgs[0].buf = (unsigned char *) data;
-       msgs[0].len = len;
-       msgs[0].scl_rate = MPU_I2C_RATE;
-
-       res = i2c_transfer(i2c_adap, msgs, 1);
-       if (res == 1)
-               return 0;
-       else if(res == 0)
-               return -EBUSY;
-       else
-               return res;
-}
-
-int sensor_i2c_write_register(struct i2c_adapter *i2c_adap,
-                             unsigned char address,
-                             unsigned char reg, unsigned char value)
-{
-       unsigned char data[2];
-
-       data[0] = reg;
-       data[1] = value;
-       return sensor_i2c_write(i2c_adap, address, 2, data);
-}
-
-int sensor_i2c_read(struct i2c_adapter *i2c_adap,
-                   unsigned char address,
-                   unsigned char reg,
-                   unsigned int len, unsigned char *data)
-{
-       struct i2c_msg msgs[2];
-       int res;
-
-       if (NULL == data || NULL == i2c_adap)
-               return -EINVAL;
-
-       msgs[0].addr = address;
-       msgs[0].flags = 0;      /* write */
-       msgs[0].buf = &reg;
-       msgs[0].len = 1;
-       msgs[0].scl_rate = MPU_I2C_RATE;
-
-       msgs[1].addr = address;
-       msgs[1].flags = I2C_M_RD;
-       msgs[1].buf = data;
-       msgs[1].len = len;
-       msgs[1].scl_rate = MPU_I2C_RATE;
-
-       res = i2c_transfer(i2c_adap, msgs, 2);
-       if (res == 2)
-               return 0;
-       else if(res == 0)
-               return -EBUSY;
-       else
-               return res;
-}
-
-int mpu_memory_read(struct i2c_adapter *i2c_adap,
-                   unsigned char mpu_addr,
-                   unsigned short mem_addr,
-                   unsigned int len, unsigned char *data)
-{
-       unsigned char bank[2];
-       unsigned char addr[2];
-       unsigned char buf;
-
-       struct i2c_msg msgs[4];
-       int ret;
-
-       if (NULL == data || NULL == i2c_adap)
-               return -EINVAL;
-
-       bank[0] = MPUREG_BANK_SEL;
-       bank[1] = mem_addr >> 8;
-
-       addr[0] = MPUREG_MEM_START_ADDR;
-       addr[1] = mem_addr & 0xFF;
-
-       buf = MPUREG_MEM_R_W;
-
-       /* Write Message */
-       msgs[0].addr = mpu_addr;
-       msgs[0].flags = 0;
-       msgs[0].buf = bank;
-       msgs[0].len = sizeof(bank);
-       msgs[0].scl_rate = MPU_I2C_RATE;
-
-       msgs[1].addr = mpu_addr;
-       msgs[1].flags = 0;
-       msgs[1].buf = addr;
-       msgs[1].len = sizeof(addr);
-       msgs[1].scl_rate = MPU_I2C_RATE;
-
-       msgs[2].addr = mpu_addr;
-       msgs[2].flags = 0;
-       msgs[2].buf = &buf;
-       msgs[2].len = 1;
-       msgs[2].scl_rate = MPU_I2C_RATE;
-
-       msgs[3].addr = mpu_addr;
-       msgs[3].flags = I2C_M_RD;
-       msgs[3].buf = data;
-       msgs[3].len = len;
-       msgs[3].scl_rate = MPU_I2C_RATE;
-
-       ret = i2c_transfer(i2c_adap, msgs, 4);
-       if (ret == 4)
-               return 0;
-       else if(ret == 0)
-               return -EBUSY;
-       else
-               return ret;
-}
-
-int mpu_memory_write(struct i2c_adapter *i2c_adap,
-                    unsigned char mpu_addr,
-                    unsigned short mem_addr,
-                    unsigned int len, unsigned char const *data)
-{
-       unsigned char bank[2];
-       unsigned char addr[2];
-       unsigned char buf[513];
-
-       struct i2c_msg msgs[3];
-       int ret;
-
-       if (NULL == data || NULL == i2c_adap)
-               return -EINVAL;
-       if (len >= (sizeof(buf) - 1))
-               return -ENOMEM;
-
-       bank[0] = MPUREG_BANK_SEL;
-       bank[1] = mem_addr >> 8;
-
-       addr[0] = MPUREG_MEM_START_ADDR;
-       addr[1] = mem_addr & 0xFF;
-
-       buf[0] = MPUREG_MEM_R_W;
-       memcpy(buf + 1, data, len);
-
-       /* Write Message */
-       msgs[0].addr = mpu_addr;
-       msgs[0].flags = 0;
-       msgs[0].buf = bank;
-       msgs[0].len = sizeof(bank);
-       msgs[0].scl_rate = MPU_I2C_RATE;
-
-       msgs[1].addr = mpu_addr;
-       msgs[1].flags = 0;
-       msgs[1].buf = addr;
-       msgs[1].len = sizeof(addr);
-       msgs[1].scl_rate = MPU_I2C_RATE;
-
-       msgs[2].addr = mpu_addr;
-       msgs[2].flags = 0;
-       msgs[2].buf = (unsigned char *) buf;
-       msgs[2].len = len + 1;
-       msgs[2].scl_rate = MPU_I2C_RATE;
-
-       ret = i2c_transfer(i2c_adap, msgs, 3);
-       if (ret == 3)
-               return 0;
-       else if(ret == 0)
-               return -EBUSY;
-       else
-               return ret;
-}
-
-/**
- *  @}
- */
diff --git a/drivers/misc/mpu3050/mpu-i2c.h b/drivers/misc/mpu3050/mpu-i2c.h
deleted file mode 100755 (executable)
index 0bbc8c6..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-/**
- * @defgroup
- * @brief
- *
- * @{
- * @file     mpu-i2c.c
- * @brief
- *
- *
- */
-
-#ifndef __MPU_I2C_H__
-#define __MPU_I2C_H__
-
-#include <linux/i2c.h>
-
-int sensor_i2c_write(struct i2c_adapter *i2c_adap,
-                    unsigned char address,
-                    unsigned int len, unsigned char const *data);
-
-int sensor_i2c_write_register(struct i2c_adapter *i2c_adap,
-                             unsigned char address,
-                             unsigned char reg, unsigned char value);
-
-int sensor_i2c_read(struct i2c_adapter *i2c_adap,
-                   unsigned char address,
-                   unsigned char reg,
-                   unsigned int len, unsigned char *data);
-
-int mpu_memory_read(struct i2c_adapter *i2c_adap,
-                   unsigned char mpu_addr,
-                   unsigned short mem_addr,
-                   unsigned int len, unsigned char *data);
-
-int mpu_memory_write(struct i2c_adapter *i2c_adap,
-                    unsigned char mpu_addr,
-                    unsigned short mem_addr,
-                    unsigned int len, unsigned char const *data);
-
-#endif /* __MPU_I2C_H__ */
diff --git a/drivers/misc/mpu3050/mpuirq.c b/drivers/misc/mpu3050/mpuirq.c
deleted file mode 100755 (executable)
index 1aaaa68..0000000
+++ /dev/null
@@ -1,338 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/stat.h>
-#include <linux/irq.h>
-#include <linux/signal.h>
-#include <linux/miscdevice.h>
-#include <linux/i2c.h>
-#include <linux/i2c-dev.h>
-#include <linux/workqueue.h>
-#include <linux/poll.h>
-#include <linux/gpio.h>
-#include <mach/gpio.h>
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-
-#include "mpu.h"
-#include "mpuirq.h"
-#include "mldl_cfg.h"
-#include "mpu-i2c.h"
-
-#define MPUIRQ_NAME "mpuirq"
-
-/* function which gets accel data and sends it to MPU */
-
-DECLARE_WAIT_QUEUE_HEAD(mpuirq_wait);
-
-struct mpuirq_dev_data {
-       struct work_struct work;
-       struct i2c_client *mpu_client;
-       struct miscdevice *dev;
-       int irq;
-       int pid;
-       int accel_divider;
-       int data_ready;
-       int timeout;
-};
-
-static struct mpuirq_dev_data mpuirq_dev_data;
-static struct mpuirq_data mpuirq_data;
-static char *interface = MPUIRQ_NAME;
-
-static void mpu_accel_data_work_fcn(struct work_struct *work);
-
-static int mpuirq_open(struct inode *inode, struct file *file)
-{
-       dev_dbg(mpuirq_dev_data.dev->this_device,
-               "%s current->pid %d\n", __func__, current->pid);
-       mpuirq_dev_data.pid = current->pid;
-       file->private_data = &mpuirq_dev_data;
-       /* we could do some checking on the flags supplied by "open" */
-       /* i.e. O_NONBLOCK */
-       /* -> set some flag to disable interruptible_sleep_on in mpuirq_read */
-       return 0;
-}
-
-/* close function - called when the "file" /dev/mpuirq is closed in userspace */
-static int mpuirq_release(struct inode *inode, struct file *file)
-{
-       dev_dbg(mpuirq_dev_data.dev->this_device, "mpuirq_release\n");
-       return 0;
-}
-
-/* read function called when from /dev/mpuirq is read */
-static ssize_t mpuirq_read(struct file *file,
-                          char *buf, size_t count, loff_t *ppos)
-{
-       int len, err;
-       struct mpuirq_dev_data *p_mpuirq_dev_data = file->private_data;
-
-       if (!mpuirq_dev_data.data_ready &&
-               mpuirq_dev_data.timeout &&
-               (!(file->f_flags & O_NONBLOCK))) {
-               wait_event_interruptible_timeout(mpuirq_wait,
-                                                mpuirq_dev_data.
-                                                data_ready,
-                                                mpuirq_dev_data.timeout);
-       }
-
-       if (mpuirq_dev_data.data_ready && NULL != buf
-           && count >= sizeof(mpuirq_data)) {
-               err = copy_to_user(buf, &mpuirq_data, sizeof(mpuirq_data));
-               mpuirq_data.data_type = 0;
-       } else {
-               return 0;
-       }
-       if (err != 0) {
-               dev_err(p_mpuirq_dev_data->dev->this_device,
-                       "Copy to user returned %d\n", err);
-               return -EFAULT;
-       }
-       mpuirq_dev_data.data_ready = 0;
-       len = sizeof(mpuirq_data);
-       return len;
-}
-
-unsigned int mpuirq_poll(struct file *file, struct poll_table_struct *poll)
-{
-       int mask = 0;
-
-       poll_wait(file, &mpuirq_wait, poll);
-       if (mpuirq_dev_data.data_ready)
-               mask |= POLLIN | POLLRDNORM;
-       return mask;
-}
-
-/* ioctl - I/O control */
-static long mpuirq_ioctl(struct file *file,
-                        unsigned int cmd, unsigned long arg)
-{
-       int retval = 0;
-       int data;
-
-       switch (cmd) {
-       case MPUIRQ_SET_TIMEOUT:
-               mpuirq_dev_data.timeout = arg;
-               break;
-
-       case MPUIRQ_GET_INTERRUPT_CNT:
-               data = mpuirq_data.interruptcount - 1;
-               if (mpuirq_data.interruptcount > 1)
-                       mpuirq_data.interruptcount = 1;
-
-               if (copy_to_user((int *) arg, &data, sizeof(int)))
-                       return -EFAULT;
-               break;
-       case MPUIRQ_GET_IRQ_TIME:
-               if (copy_to_user((int *) arg, &mpuirq_data.irqtime,
-                                sizeof(mpuirq_data.irqtime)))
-                       return -EFAULT;
-               mpuirq_data.irqtime = 0;
-               break;
-       case MPUIRQ_SET_FREQUENCY_DIVIDER:
-               mpuirq_dev_data.accel_divider = arg;
-               break;
-       default:
-               retval = -EINVAL;
-       }
-       return retval;
-}
-
-static void mpu_accel_data_work_fcn(struct work_struct *work)
-{
-       struct mpuirq_dev_data *mpuirq_dev_data =
-           (struct mpuirq_dev_data *) work;
-       struct mldl_cfg *mldl_cfg =
-           (struct mldl_cfg *)
-           i2c_get_clientdata(mpuirq_dev_data->mpu_client);
-       struct i2c_adapter *accel_adapter;
-       unsigned char wbuff[16];
-       unsigned char rbuff[16];
-       int ii;
-
-       accel_adapter = i2c_get_adapter(mldl_cfg->pdata->accel.adapt_num);
-       mldl_cfg->accel->read(accel_adapter,
-                             mldl_cfg->accel,
-                             &mldl_cfg->pdata->accel, rbuff);
-
-
-       /* @todo add other data formats here as well */
-       if (EXT_SLAVE_BIG_ENDIAN == mldl_cfg->accel->endian) {
-               for (ii = 0; ii < 3; ii++) {
-                       wbuff[2 * ii + 1] = rbuff[2 * ii + 1];
-                       wbuff[2 * ii + 2] = rbuff[2 * ii + 0];
-               }
-       } else {
-               memcpy(wbuff + 1, rbuff, mldl_cfg->accel->len);
-       }
-
-       wbuff[7] = 0;
-       wbuff[8] = 1;           /*set semaphore */
-
-       mpu_memory_write(mpuirq_dev_data->mpu_client->adapter,
-                        mldl_cfg->addr, 0x0108, 8, wbuff);
-}
-
-static irqreturn_t mpuirq_handler(int irq, void *dev_id)
-{
-       static int mycount;
-       struct timeval irqtime;
-       mycount++;
-
-       mpuirq_data.interruptcount++;
-
-       /* wake up (unblock) for reading data from userspace */
-       /* and ignore first interrupt generated in module init */
-       mpuirq_dev_data.data_ready = 1;
-
-       do_gettimeofday(&irqtime);
-       mpuirq_data.irqtime = (((long long) irqtime.tv_sec) << 32);
-       mpuirq_data.irqtime += irqtime.tv_usec;
-
-       if ((mpuirq_dev_data.accel_divider >= 0) &&
-               (0 == (mycount % (mpuirq_dev_data.accel_divider + 1)))) {
-               schedule_work((struct work_struct
-                               *) (&mpuirq_dev_data));
-       }
-
-       wake_up_interruptible(&mpuirq_wait);
-
-       return IRQ_HANDLED;
-
-}
-
-/* define which file operations are supported */
-const struct file_operations mpuirq_fops = {
-       .owner = THIS_MODULE,
-       .read = mpuirq_read,
-       .poll = mpuirq_poll,
-
-#if HAVE_COMPAT_IOCTL
-       .compat_ioctl = mpuirq_ioctl,
-#endif
-#if HAVE_UNLOCKED_IOCTL
-       .unlocked_ioctl = mpuirq_ioctl,
-#endif
-       .open = mpuirq_open,
-       .release = mpuirq_release,
-};
-
-static struct miscdevice mpuirq_device = {
-       .minor = MISC_DYNAMIC_MINOR,
-       .name = MPUIRQ_NAME,
-       .fops = &mpuirq_fops,
-};
-
-int mpuirq_init(struct i2c_client *mpu_client)
-{
-
-       int res;
-       struct mldl_cfg *mldl_cfg =
-           (struct mldl_cfg *) i2c_get_clientdata(mpu_client);
-
-       /* work_struct initialization */
-       INIT_WORK((struct work_struct *) &mpuirq_dev_data,
-                 mpu_accel_data_work_fcn);
-       mpuirq_dev_data.mpu_client = mpu_client;
-
-       dev_info(&mpu_client->adapter->dev,
-                "Module Param interface = %s\n", interface);
-
-       mpuirq_dev_data.irq = mpu_client->irq;
-       mpuirq_dev_data.pid = 0;
-       mpuirq_dev_data.accel_divider = -1;
-       mpuirq_dev_data.data_ready = 0;
-       mpuirq_dev_data.timeout = 0;
-       mpuirq_dev_data.dev = &mpuirq_device;
-
-       if (mpuirq_dev_data.irq) {
-               unsigned long flags;
-               if (BIT_ACTL_LOW ==
-                   ((mldl_cfg->pdata->int_config) & BIT_ACTL))
-                       flags = IRQF_TRIGGER_FALLING;
-               else
-                       flags = IRQF_TRIGGER_RISING;
-               /* mpu irq register xxm*/
-               res = gpio_request(mpuirq_dev_data.irq, "mpu3050_int");
-               if(res)
-               {
-                       printk("failed to request mpu3050_int GPIO %d\n",                       
-                                               gpio_to_irq(mpuirq_dev_data.irq));
-                       return res;
-               }
-               res = gpio_direction_input(mpuirq_dev_data.irq);
-               if(res)
-               {
-                       printk("failed to set mpu3050_int GPIO input\n");
-                       return res;
-               }
-               printk("gpio_to_irq(mpuirq_dev_data.irq) == %d \r\n",   
-                               gpio_to_irq(mpuirq_dev_data.irq));
-               res =request_irq(gpio_to_irq(mpuirq_dev_data.irq), mpuirq_handler, flags,
-                                                       interface,&mpuirq_dev_data.irq);
-               if (res) {
-                       dev_err(&mpu_client->adapter->dev,
-                               "myirqtest: cannot register IRQ %d\n",
-                               mpuirq_dev_data.irq);
-               } else {
-                       res = misc_register(&mpuirq_device);
-                       if (res < 0) {
-                               dev_err(&mpu_client->adapter->dev,
-                                       "misc_register returned %d\n",
-                                       res);
-                               free_irq(mpuirq_dev_data.irq,
-                                        &mpuirq_dev_data.irq);
-                       }
-               }
-
-       } else {
-               res = 0;
-       }
-
-       return res;
-}
-
-void mpuirq_exit(void)
-{
-       /* Free the IRQ first before flushing the work */
-       if (mpuirq_dev_data.irq > 0)
-               free_irq(mpuirq_dev_data.irq, &mpuirq_dev_data.irq);
-
-       flush_scheduled_work();
-
-       dev_info(mpuirq_device.this_device, "Unregistering %s\n",
-                MPUIRQ_NAME);
-       misc_deregister(&mpuirq_device);
-
-       return;
-}
-
-module_param(interface, charp, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(interface, "The Interface name");
diff --git a/drivers/misc/mpu3050/mpuirq.h b/drivers/misc/mpu3050/mpuirq.h
deleted file mode 100755 (executable)
index a71c79c..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-#ifndef __MPUIRQ__
-#define __MPUIRQ__
-
-#ifdef __KERNEL__
-#include <linux/i2c-dev.h>
-#include <linux/time.h>
-#else
-#include <sys/time.h>
-#endif
-
-#define MPUIRQ_SET_TIMEOUT           _IOW(MPU_IOCTL, 0x40, unsigned long)
-#define MPUIRQ_GET_INTERRUPT_CNT     _IOR(MPU_IOCTL, 0x41, unsigned long)
-#define MPUIRQ_GET_IRQ_TIME          _IOR(MPU_IOCTL, 0x42, struct timeval)
-#define MPUIRQ_SET_FREQUENCY_DIVIDER _IOW(MPU_IOCTL, 0x43, unsigned long)
-
-#ifdef __KERNEL__
-
-void mpuirq_exit(void);
-int mpuirq_init(struct i2c_client *mpu_client);
-
-#endif
-
-#endif
diff --git a/drivers/misc/mpu3050/slaveirq.c b/drivers/misc/mpu3050/slaveirq.c
deleted file mode 100755 (executable)
index 0276ddb..0000000
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/stat.h>
-#include <linux/irq.h>
-#include <linux/signal.h>
-#include <linux/miscdevice.h>
-#include <linux/i2c.h>
-#include <linux/i2c-dev.h>
-#include <linux/poll.h>
-#include <linux/gpio.h>
-#include <mach/gpio.h>
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-
-#include "mpu.h"
-#include "slaveirq.h"
-#include "mldl_cfg.h"
-#include "mpu-i2c.h"
-
-/* function which gets slave data and sends it to SLAVE */
-
-struct slaveirq_dev_data {
-       struct miscdevice dev;
-       struct i2c_client *slave_client;
-       struct mpuirq_data data;
-       wait_queue_head_t slaveirq_wait;
-       int irq;
-       int pid;
-       int data_ready;
-       int timeout;
-};
-
-/* The following depends on patch fa1f68db6ca7ebb6fc4487ac215bffba06c01c28
- * drivers: misc: pass miscdevice pointer via file private data
- */
-static int slaveirq_open(struct inode *inode, struct file *file)
-{
-       /* Device node is availabe in the file->private_data, this is
-        * exactly what we want so we leave it there */
-       struct slaveirq_dev_data *data =
-               container_of(file->private_data, struct slaveirq_dev_data, dev);
-
-       dev_dbg(data->dev.this_device,
-               "%s current->pid %d\n", __func__, current->pid);
-       data->pid = current->pid;
-       return 0;
-}
-
-static int slaveirq_release(struct inode *inode, struct file *file)
-{
-       struct slaveirq_dev_data *data =
-               container_of(file->private_data, struct slaveirq_dev_data, dev);
-       dev_dbg(data->dev.this_device, "slaveirq_release\n");
-       return 0;
-}
-
-/* read function called when from /dev/slaveirq is read */
-static ssize_t slaveirq_read(struct file *file,
-                          char *buf, size_t count, loff_t *ppos)
-{
-       int len, err;
-       struct slaveirq_dev_data *data =
-               container_of(file->private_data, struct slaveirq_dev_data, dev);
-
-       if (!data->data_ready &&
-               data->timeout &&
-               !(file->f_flags & O_NONBLOCK)) {
-               wait_event_interruptible_timeout(data->slaveirq_wait,
-                                                data->data_ready,
-                                                data->timeout);
-       }
-
-       if (data->data_ready && NULL != buf
-           && count >= sizeof(data->data)) {
-               err = copy_to_user(buf, &data->data, sizeof(data->data));
-               data->data.data_type = 0;
-       } else {
-               return 0;
-       }
-       if (err != 0) {
-               dev_err(data->dev.this_device,
-                       "Copy to user returned %d\n", err);
-               return -EFAULT;
-       }
-       data->data_ready = 0;
-       len = sizeof(data->data);
-       return len;
-}
-
-static unsigned int slaveirq_poll(struct file *file,
-                               struct poll_table_struct *poll)
-{
-       int mask = 0;
-       struct slaveirq_dev_data *data =
-               container_of(file->private_data, struct slaveirq_dev_data, dev);
-
-       poll_wait(file, &data->slaveirq_wait, poll);
-       if (data->data_ready)
-               mask |= POLLIN | POLLRDNORM;
-       return mask;
-}
-
-/* ioctl - I/O control */
-static long slaveirq_ioctl(struct file *file,
-                          unsigned int cmd, unsigned long arg)
-{
-       int retval = 0;
-       int tmp;
-       struct slaveirq_dev_data *data =
-               container_of(file->private_data, struct slaveirq_dev_data, dev);
-
-       switch (cmd) {
-       case SLAVEIRQ_SET_TIMEOUT:
-               data->timeout = arg;
-               break;
-
-       case SLAVEIRQ_GET_INTERRUPT_CNT:
-               tmp = data->data.interruptcount - 1;
-               if (data->data.interruptcount > 1)
-                       data->data.interruptcount = 1;
-
-               if (copy_to_user((int *) arg, &tmp, sizeof(int)))
-                       return -EFAULT;
-               break;
-       case SLAVEIRQ_GET_IRQ_TIME:
-               if (copy_to_user((int *) arg, &data->data.irqtime,
-                                sizeof(data->data.irqtime)))
-                       return -EFAULT;
-               data->data.irqtime = 0;
-               break;
-       default:
-               retval = -EINVAL;
-       }
-       return retval;
-}
-
-static irqreturn_t slaveirq_handler(int irq, void *dev_id)
-{
-       struct slaveirq_dev_data *data = (struct slaveirq_dev_data *)dev_id;
-       static int mycount;
-       struct timeval irqtime;
-       mycount++;
-
-       data->data.interruptcount++;
-
-       /* wake up (unblock) for reading data from userspace */
-       data->data_ready = 1;
-
-       do_gettimeofday(&irqtime);
-       data->data.irqtime = (((long long) irqtime.tv_sec) << 32);
-       data->data.irqtime += irqtime.tv_usec;
-       data->data.data_type |= 1;
-
-       wake_up_interruptible(&data->slaveirq_wait);
-
-       return IRQ_HANDLED;
-
-}
-
-/* define which file operations are supported */
-static const struct file_operations slaveirq_fops = {
-       .owner = THIS_MODULE,
-       .read = slaveirq_read,
-       .poll = slaveirq_poll,
-
-#if HAVE_COMPAT_IOCTL
-       .compat_ioctl = slaveirq_ioctl,
-#endif
-#if HAVE_UNLOCKED_IOCTL
-       .unlocked_ioctl = slaveirq_ioctl,
-#endif
-       .open = slaveirq_open,
-       .release = slaveirq_release,
-};
-
-int slaveirq_init(struct i2c_adapter *slave_adapter,
-                 struct ext_slave_platform_data *pdata,
-                 char *name)
-{
-
-       int res;
-       struct slaveirq_dev_data *data;
-
-       if (!pdata->irq)
-               return -EINVAL;
-
-       pdata->irq_data = kzalloc(sizeof(*data),
-                               GFP_KERNEL);
-       data = (struct slaveirq_dev_data *) pdata->irq_data;
-       if (!data)
-               return -ENOMEM;
-
-       data->dev.minor = MISC_DYNAMIC_MINOR;
-       data->dev.name = name;
-       data->dev.fops = &slaveirq_fops;
-       data->irq = pdata->irq;
-       data->pid = 0;
-       data->data_ready = 0;
-       data->timeout = 0;
-
-       /* mpu irq register xxm*/
-       res = gpio_request(data->irq, name);
-       if(res)
-       {
-               printk("failed to request %s GPIO %d\n",                        
-                                       name,data->irq);
-               return res;
-       }
-       res = gpio_direction_input(data->irq);
-       if(res)
-       {
-               printk("failed to set %s GPIO input\n",name);
-               return res;
-       }
-       printk("%s registing irq  == %d \r\n",name,gpio_to_irq(data->irq));
-       //gpio_pull_updown(data->irq, GPIOPullUp);
-       //gpio_set_value(data->irq,GPIO_HIGH);
-       init_waitqueue_head(&data->slaveirq_wait);
-       res = request_irq(gpio_to_irq(data->irq), slaveirq_handler, IRQF_TRIGGER_FALLING,data->dev.name, data);
-
-       if (res) {
-               dev_err(&slave_adapter->dev,
-                       "myirqtest: cannot register IRQ %d\n",
-                       data->irq);
-               goto out_request_irq;
-       }
-
-       res = misc_register(&data->dev);
-       if (res < 0) {
-               dev_err(&slave_adapter->dev,
-                       "misc_register returned %d\n",
-                       res);
-               goto out_misc_register;
-       }
-
-       return res;
-
-out_misc_register:
-       free_irq(data->irq, data);
-out_request_irq:
-       kfree(pdata->irq_data);
-       pdata->irq_data = NULL;
-
-       return res;
-}
-
-void slaveirq_exit(struct ext_slave_platform_data *pdata)
-{
-       struct slaveirq_dev_data *data = pdata->irq_data;
-
-       if (!pdata->irq_data || data->irq <= 0)
-               return;
-
-       dev_info(data->dev.this_device, "Unregistering %s\n",
-                data->dev.name);
-
-       free_irq(data->irq, data);
-       misc_deregister(&data->dev);
-       kfree(pdata->irq_data);
-       pdata->irq_data = NULL;
-}
diff --git a/drivers/misc/mpu3050/slaveirq.h b/drivers/misc/mpu3050/slaveirq.h
deleted file mode 100755 (executable)
index b4e1115..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-#ifndef __SLAVEIRQ__
-#define __SLAVEIRQ__
-
-#ifdef __KERNEL__
-#include <linux/i2c-dev.h>
-#endif
-
-#include "mpu.h"
-#include "mpuirq.h"
-
-#define SLAVEIRQ_SET_TIMEOUT           _IOW(MPU_IOCTL, 0x50, unsigned long)
-#define SLAVEIRQ_GET_INTERRUPT_CNT     _IOR(MPU_IOCTL, 0x51, unsigned long)
-#define SLAVEIRQ_GET_IRQ_TIME          _IOR(MPU_IOCTL, 0x52, unsigned long)
-
-#ifdef __KERNEL__
-
-void slaveirq_exit(struct ext_slave_platform_data *pdata);
-int slaveirq_init(struct i2c_adapter *slave_adapter,
-               struct ext_slave_platform_data *pdata,
-               char *name);
-
-#endif
-
-#endif
diff --git a/drivers/misc/mpu3050/timerirq.c b/drivers/misc/mpu3050/timerirq.c
deleted file mode 100755 (executable)
index 41c3ac9..0000000
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-#include <linux/interrupt.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/stat.h>
-#include <linux/signal.h>
-#include <linux/miscdevice.h>
-#include <linux/i2c.h>
-#include <linux/i2c-dev.h>
-#include <linux/poll.h>
-
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <linux/timer.h>
-#include <linux/slab.h>
-
-#include "mpu.h"
-#include "mltypes.h"
-#include "timerirq.h"
-
-/* function which gets timer data and sends it to TIMER */
-struct timerirq_data {
-       int pid;
-       int data_ready;
-       int run;
-       int timeout;
-       unsigned long period;
-       struct mpuirq_data data;
-       struct completion timer_done;
-       wait_queue_head_t timerirq_wait;
-       struct timer_list timer;
-       struct miscdevice *dev;
-};
-
-static struct miscdevice *timerirq_dev_data;
-
-static void timerirq_handler(unsigned long arg)
-{
-       struct timerirq_data *data = (struct timerirq_data *)arg;
-       struct timeval irqtime;
-
-       data->data.interruptcount++;
-
-       data->data_ready = 1;
-
-       do_gettimeofday(&irqtime);
-       data->data.irqtime = (((long long) irqtime.tv_sec) << 32);
-       data->data.irqtime += irqtime.tv_usec;
-       data->data.data_type |= 1;
-
-       dev_dbg(data->dev->this_device,
-               "%s, %lld, %ld\n", __func__, data->data.irqtime,
-               (unsigned long)data);
-
-       wake_up_interruptible(&data->timerirq_wait);
-
-       if (data->run)
-               mod_timer(&data->timer,
-                       jiffies + msecs_to_jiffies(data->period));
-       else
-               complete(&data->timer_done);
-}
-
-static int start_timerirq(struct timerirq_data *data)
-{
-       dev_dbg(data->dev->this_device,
-               "%s current->pid %d\n", __func__, current->pid);
-
-       /* Timer already running... success */
-       if (data->run)
-               return 0;
-
-       /* Don't allow a period of 0 since this would fire constantly */
-       if (!data->period)
-               return -EINVAL;
-
-       data->run = TRUE;
-       data->data_ready = FALSE;
-
-       init_completion(&data->timer_done);
-       setup_timer(&data->timer, timerirq_handler, (unsigned long)data);
-
-       return mod_timer(&data->timer,
-                       jiffies + msecs_to_jiffies(data->period));
-}
-
-static int stop_timerirq(struct timerirq_data *data)
-{
-       dev_dbg(data->dev->this_device,
-               "%s current->pid %lx\n", __func__, (unsigned long)data);
-
-       if (data->run) {
-               data->run = FALSE;
-               mod_timer(&data->timer, jiffies + 1);
-               wait_for_completion(&data->timer_done);
-       }
-       return 0;
-}
-
-/* The following depends on patch fa1f68db6ca7ebb6fc4487ac215bffba06c01c28
- * drivers: misc: pass miscdevice pointer via file private data
- */
-static int timerirq_open(struct inode *inode, struct file *file)
-{
-       /* Device node is availabe in the file->private_data, this is
-        * exactly what we want so we leave it there */
-       struct miscdevice *dev_data = file->private_data;
-       struct timerirq_data *data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-
-       data->dev = dev_data;
-       file->private_data = data;
-       data->pid = current->pid;
-       init_waitqueue_head(&data->timerirq_wait);
-
-       dev_dbg(data->dev->this_device,
-               "%s current->pid %d\n", __func__, current->pid);
-       return 0;
-}
-
-static int timerirq_release(struct inode *inode, struct file *file)
-{
-       struct timerirq_data *data = file->private_data;
-       dev_dbg(data->dev->this_device, "timerirq_release\n");
-       if (data->run)
-               stop_timerirq(data);
-       kfree(data);
-       return 0;
-}
-
-/* read function called when from /dev/timerirq is read */
-static ssize_t timerirq_read(struct file *file,
-                          char *buf, size_t count, loff_t *ppos)
-{
-       int len, err;
-       struct timerirq_data *data = file->private_data;
-
-       if (!data->data_ready &&
-               data->timeout &&
-               !(file->f_flags & O_NONBLOCK)) {
-               wait_event_interruptible_timeout(data->timerirq_wait,
-                                                data->data_ready,
-                                                data->timeout);
-       }
-
-       if (data->data_ready && NULL != buf
-           && count >= sizeof(data->data)) {
-               err = copy_to_user(buf, &data->data, sizeof(data->data));
-               data->data.data_type = 0;
-       } else {
-               return 0;
-       }
-       if (err != 0) {
-               dev_err(data->dev->this_device,
-                       "Copy to user returned %d\n", err);
-               return -EFAULT;
-       }
-       data->data_ready = 0;
-       len = sizeof(data->data);
-       return len;
-}
-
-static unsigned int timerirq_poll(struct file *file,
-                               struct poll_table_struct *poll)
-{
-       int mask = 0;
-       struct timerirq_data *data = file->private_data;
-
-       poll_wait(file, &data->timerirq_wait, poll);
-       if (data->data_ready)
-               mask |= POLLIN | POLLRDNORM;
-       return mask;
-}
-
-/* ioctl - I/O control */
-static long timerirq_ioctl(struct file *file,
-                          unsigned int cmd, unsigned long arg)
-{
-       int retval = 0;
-       int tmp;
-       struct timerirq_data *data = file->private_data;
-
-       dev_dbg(data->dev->this_device,
-               "%s current->pid %d, %d, %ld\n",
-               __func__, current->pid, cmd, arg);
-
-       if (!data)
-               return -EFAULT;
-
-       switch (cmd) {
-       case TIMERIRQ_SET_TIMEOUT:
-               data->timeout = arg;
-               break;
-       case TIMERIRQ_GET_INTERRUPT_CNT:
-               tmp = data->data.interruptcount - 1;
-               if (data->data.interruptcount > 1)
-                       data->data.interruptcount = 1;
-
-               if (copy_to_user((int *) arg, &tmp, sizeof(int)))
-                       return -EFAULT;
-               break;
-       case TIMERIRQ_START:
-               data->period = arg;
-               retval = start_timerirq(data);
-               break;
-       case TIMERIRQ_STOP:
-               retval = stop_timerirq(data);
-               break;
-       default:
-               retval = -EINVAL;
-       }
-       return retval;
-}
-
-/* define which file operations are supported */
-static const struct file_operations timerirq_fops = {
-       .owner = THIS_MODULE,
-       .read = timerirq_read,
-       .poll = timerirq_poll,
-
-#if HAVE_COMPAT_IOCTL
-       .compat_ioctl = timerirq_ioctl,
-#endif
-#if HAVE_UNLOCKED_IOCTL
-       .unlocked_ioctl = timerirq_ioctl,
-#endif
-       .open = timerirq_open,
-       .release = timerirq_release,
-};
-
-static int __init timerirq_init(void)
-{
-
-       int res;
-       static struct miscdevice *data;
-
-       data = kzalloc(sizeof(*data), GFP_KERNEL);
-       if (!data)
-               return -ENOMEM;
-       timerirq_dev_data = data;
-       data->minor = MISC_DYNAMIC_MINOR;
-       data->name = "timerirq";
-       data->fops = &timerirq_fops;
-
-       res = misc_register(data);
-       if (res < 0) {
-               dev_err(data->this_device,
-                       "misc_register returned %d\n",
-                       res);
-               return res;
-       }
-
-       return res;
-}
-module_init(timerirq_init);
-
-static void __exit timerirq_exit(void)
-{
-       struct miscdevice *data = timerirq_dev_data;
-
-       dev_info(data->this_device, "Unregistering %s\n",
-                data->name);
-
-       misc_deregister(data);
-       kfree(data);
-
-       timerirq_dev_data = NULL;
-}
-module_exit(timerirq_exit);
-
-MODULE_AUTHOR("Invensense Corporation");
-MODULE_DESCRIPTION("Timer IRQ device driver.");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("timerirq");
diff --git a/drivers/misc/mpu3050/timerirq.h b/drivers/misc/mpu3050/timerirq.h
deleted file mode 100755 (executable)
index ec2c1e2..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
- */
-
-#ifndef __TIMERIRQ__
-#define __TIMERIRQ__
-
-#include "mpu.h"
-
-#define TIMERIRQ_SET_TIMEOUT           _IOW(MPU_IOCTL, 0x60, unsigned long)
-#define TIMERIRQ_GET_INTERRUPT_CNT     _IOW(MPU_IOCTL, 0x61, unsigned long)
-#define TIMERIRQ_START                 _IOW(MPU_IOCTL, 0x62, unsigned long)
-#define TIMERIRQ_STOP                  _IO(MPU_IOCTL, 0x63)
-
-#endif
index d66d9e76b9afdfcb50f712f9cb1fa8530f06ef8f..00d9e6c624054302f44f0fb3d37499a87a056a57 100755 (executable)
@@ -1,20 +1,7 @@
 /*
  $License:
-    Copyright (C) 2010 InvenSense Corporation, All Rights Reserved.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program.  If not, see <http://www.gnu.org/licenses/>.
-  $
+    Copyright (C) 2011 InvenSense Corporation, All Rights Reserved.
+ $
  */
 
 #ifndef __MPU_H_
 #include <linux/ioctl.h>
 #elif defined LINUX
 #include <sys/ioctl.h>
-#endif
-
-#ifdef M_HW
-#include "mpu6000.h"
+#include <linux/types.h>
 #else
-#include "mpu3050.h"
+#include "mltypes.h"
 #endif
 
 /* Number of axes on each sensor */
 #define ACCEL_NUM_AXES              (3)
 #define COMPASS_NUM_AXES            (3)
 
-#if defined __KERNEL__ || defined LINUX
-#define MPU_IOCTL (0x81) /* Magic number for MPU Iocts */
-/* IOCTL commands for /dev/mpu */
-#define MPU_SET_MPU_CONFIG     _IOW(MPU_IOCTL, 0x00, struct mldl_cfg)
-#define MPU_GET_MPU_CONFIG     _IOR(MPU_IOCTL, 0x00, struct mldl_cfg)
-
-#define MPU_SET_PLATFORM_DATA  _IOW(MPU_IOCTL, 0x01, struct mldl_cfg)
-
-#define MPU_READ               _IOR(MPU_IOCTL, 0x10, struct mpu_read_write)
-#define MPU_WRITE              _IOW(MPU_IOCTL, 0x10, struct mpu_read_write)
-#define MPU_READ_MEM           _IOR(MPU_IOCTL, 0x11, struct mpu_read_write)
-#define MPU_WRITE_MEM          _IOW(MPU_IOCTL, 0x11, struct mpu_read_write)
-#define MPU_READ_FIFO          _IOR(MPU_IOCTL, 0x12, struct mpu_read_write)
-#define MPU_WRITE_FIFO         _IOW(MPU_IOCTL, 0x12, struct mpu_read_write)
-
-#define MPU_READ_COMPASS       _IOR(MPU_IOCTL, 0x12, unsigned char)
-#define MPU_READ_ACCEL         _IOR(MPU_IOCTL, 0x13, unsigned char)
-#define MPU_READ_PRESSURE      _IOR(MPU_IOCTL, 0x14, unsigned char)
-
-#define MPU_CONFIG_ACCEL       _IOW(MPU_IOCTL, 0x20, struct ext_slave_config)
-#define MPU_CONFIG_COMPASS     _IOW(MPU_IOCTL, 0x21, struct ext_slave_config)
-#define MPU_CONFIG_PRESSURE    _IOW(MPU_IOCTL, 0x22, struct ext_slave_config)
-
-#define MPU_GET_CONFIG_ACCEL   _IOR(MPU_IOCTL, 0x20, struct ext_slave_config)
-#define MPU_GET_CONFIG_COMPASS _IOR(MPU_IOCTL, 0x21, struct ext_slave_config)
-#define MPU_GET_CONFIG_PRESSURE        _IOR(MPU_IOCTL, 0x22, struct ext_slave_config)
-
-#define MPU_SUSPEND            _IO(MPU_IOCTL, 0x30)
-#define MPU_RESUME             _IO(MPU_IOCTL, 0x31)
-/* Userspace PM Event response */
-#define MPU_PM_EVENT_HANDLED   _IO(MPU_IOCTL, 0x32)
-
-#endif
-/* Structure for the following IOCTL's:
-   MPU_READ
-   MPU_WRITE
-   MPU_READ_MEM
-   MPU_WRITE_MEM
-   MPU_READ_FIFO
-   MPU_WRITE_FIFO
-*/
 struct mpu_read_write {
        /* Memory address or register address depending on ioctl */
-       unsigned short address;
-       unsigned short length;
-       unsigned char *data;
+       __u16 address;
+       __u16 length;
+       __u8 *data;
 };
 
 enum mpuirq_data_type {
-    MPUIRQ_DATA_TYPE_MPU_IRQ,
-    MPUIRQ_DATA_TYPE_SLAVE_IRQ,
-    MPUIRQ_DATA_TYPE_PM_EVENT,
-    MPUIRQ_DATA_TYPE_NUM_TYPES,
+       MPUIRQ_DATA_TYPE_MPU_IRQ,
+       MPUIRQ_DATA_TYPE_SLAVE_IRQ,
+       MPUIRQ_DATA_TYPE_PM_EVENT,
+       MPUIRQ_DATA_TYPE_NUM_TYPES,
 };
 
 /* User space PM event notification */
 #define MPU_PM_EVENT_SUSPEND_PREPARE (3)
 #define MPU_PM_EVENT_POST_SUSPEND    (4)
 
-#define MAX_MPUIRQ_DATA_SIZE (32)
-
 struct mpuirq_data {
-       int interruptcount;
-       unsigned long long irqtime;
-       int data_type;
-       int data_size;
-       void *data;
+       __u32 interruptcount;
+       __u64 irqtime;
+       __u32 data_type;
+       __s32 data;
 };
 
 enum ext_slave_config_key {
@@ -120,7 +60,36 @@ enum ext_slave_config_key {
        MPU_SLAVE_CONFIG_IRQ_RESUME,
        MPU_SLAVE_WRITE_REGISTERS,
        MPU_SLAVE_READ_REGISTERS,
-       MPU_SLAVE_CONFIG_NUM_CONFIG_KEYS,
+       MPU_SLAVE_CONFIG_INTERNAL_REFERENCE,
+       /* AMI 306 specific config keys */
+       MPU_SLAVE_PARAM,
+       MPU_SLAVE_WINDOW,
+       MPU_SLAVE_READWINPARAMS,
+       MPU_SLAVE_SEARCHOFFSET,
+       /* AKM specific config keys */
+       MPU_SLAVE_READ_SCALE,
+       /* MPU3050 and MPU6050 Keys */
+       MPU_SLAVE_INT_CONFIG,
+       MPU_SLAVE_EXT_SYNC,
+       MPU_SLAVE_FULL_SCALE,
+       MPU_SLAVE_LPF,
+       MPU_SLAVE_CLK_SRC,
+       MPU_SLAVE_DIVIDER,
+       MPU_SLAVE_DMP_ENABLE,
+       MPU_SLAVE_FIFO_ENABLE,
+       MPU_SLAVE_DMP_CFG1,
+       MPU_SLAVE_DMP_CFG2,
+       MPU_SLAVE_TC,
+       MPU_SLAVE_GYRO,
+       MPU_SLAVE_ADDR,
+       MPU_SLAVE_PRODUCT_REVISION,
+       MPU_SLAVE_SILICON_REVISION,
+       MPU_SLAVE_PRODUCT_ID,
+       MPU_SLAVE_GYRO_SENS_TRIM,
+       MPU_SLAVE_ACCEL_SENS_TRIM,
+       MPU_SLAVE_RAM,
+       /* -------------------------- */
+       MPU_SLAVE_CONFIG_NUM_CONFIG_KEYS
 };
 
 /* For the MPU_SLAVE_CONFIG_IRQ_SUSPEND and MPU_SLAVE_CONFIG_IRQ_RESUME */
@@ -131,50 +100,66 @@ enum ext_slave_config_irq_type {
 };
 
 /* Structure for the following IOCTS's
+ * MPU_CONFIG_GYRO
  * MPU_CONFIG_ACCEL
  * MPU_CONFIG_COMPASS
  * MPU_CONFIG_PRESSURE
+ * MPU_GET_CONFIG_GYRO
  * MPU_GET_CONFIG_ACCEL
  * MPU_GET_CONFIG_COMPASS
  * MPU_GET_CONFIG_PRESSURE
+ *
+ * @key one of enum ext_slave_config_key
+ * @len length of data pointed to by data
+ * @apply zero if communication with the chip is not necessary, false otherwise
+ *        This flag can be used to select cached data or to refresh cashed data
+ *        cache data to be pushed later or push immediately.  If true and the
+ *        slave is on the secondary bus the MPU will first enger bypass mode
+ *        before calling the slaves .config or .get_config funcion
+ * @data pointer to the data to confgure or get
  */
 struct ext_slave_config {
-       int key;
-       int len;
-       int apply;
+       __u8 key;
+       __u16 len;
+       __u8 apply;
        void *data;
 };
 
 enum ext_slave_type {
        EXT_SLAVE_TYPE_GYROSCOPE,
-       EXT_SLAVE_TYPE_ACCELEROMETER,
+       EXT_SLAVE_TYPE_ACCEL,
        EXT_SLAVE_TYPE_COMPASS,
        EXT_SLAVE_TYPE_PRESSURE,
        /*EXT_SLAVE_TYPE_TEMPERATURE */
+
+       EXT_SLAVE_NUM_TYPES
 };
 
 enum ext_slave_id {
        ID_INVALID = 0,
 
        ACCEL_ID_LIS331,
-       ACCEL_ID_LSM303,
+       ACCEL_ID_LSM303DLX,
        ACCEL_ID_LIS3DH,
        ACCEL_ID_KXSD9,
        ACCEL_ID_KXTF9,
        ACCEL_ID_BMA150,
        ACCEL_ID_BMA222,
-       ACCEL_ID_ADI346,
+       ACCEL_ID_BMA250,
+       ACCEL_ID_ADXL34X,
        ACCEL_ID_MMA8450,
        ACCEL_ID_MMA845X,
-       ACCEL_ID_MPU6000,
+       ACCEL_ID_MPU6050,
 
-       COMPASS_ID_AKM,
+       COMPASS_ID_AK8975,
+       COMPASS_ID_AK8972,
        COMPASS_ID_AMI30X,
        COMPASS_ID_AMI306,
        COMPASS_ID_YAS529,
        COMPASS_ID_YAS530,
        COMPASS_ID_HMC5883,
-       COMPASS_ID_LSM303,
+       COMPASS_ID_LSM303DLH,
+       COMPASS_ID_LSM303DLM,
        COMPASS_ID_MMC314X,
        COMPASS_ID_HSCDTD002B,
        COMPASS_ID_HSCDTD004A,
@@ -197,10 +182,11 @@ enum ext_slave_bus {
 
 
 /**
- *  struct ext_slave_platform_data - Platform data for mpu3050 slave devices
+ *  struct ext_slave_platform_data - Platform data for mpu3050 and mpu6050
+ *  slave devices
  *
- *  @get_slave_descr: Function pointer to retrieve the struct ext_slave_descr
- *                    for this slave
+ *  @type: the type of slave device based on the enum ext_slave_type
+ *         definitions.
  *  @irq: the irq number attached to the slave if any.
  *  @adapt_num: the I2C adapter number.
  *  @bus: the bus the slave is attached to: enum ext_slave_bus
@@ -216,20 +202,29 @@ enum ext_slave_bus {
  * column should have exactly 1 non-zero value.
  */
 struct ext_slave_platform_data {
-       struct ext_slave_descr *(*get_slave_descr) (void);
-       int irq;
-       int adapt_num;
-       int bus;
-       unsigned char address;
-       signed char orientation[9];
+       __u8 type;
+       __u32 irq;
+       __u32 adapt_num;
+       __u32 bus;
+       __u8 address;
+       __s8 orientation[9];
        void *irq_data;
        void *private_data;
 };
 
+struct fix_pnt_range {
+       __s32 mantissa;
+       __s32 fraction;
+};
+
+static inline long range_fixedpoint_to_long_mg(struct fix_pnt_range rng)
+{
+       return (long)(rng.mantissa * 1000 + rng.fraction / 10);
+}
 
-struct tFixPntRange {
-       long mantissa;
-       long fraction;
+struct ext_slave_read_trigger {
+       __u8 reg;
+       __u8 value;
 };
 
 /**
@@ -246,13 +241,15 @@ struct tFixPntRange {
  *  @name:     text name of the device
  *  @type:     device type. enum ext_slave_type
  *  @id:       enum ext_slave_id
- *  @reg:      starting register address to retrieve data.
- *  @len:      length in bytes of the sensor data.  Should be 6.
+ *  @read_reg: starting register address to retrieve data.
+ *  @read_len: length in bytes of the sensor data.  Typically  6.
  *  @endian:   byte order of the data. enum ext_slave_endian
- *  @range:    full scale range of the slave ouput: struct tFixPntRange
+ *  @range:    full scale range of the slave ouput: struct fix_pnt_range
+ *  @trigger:  If reading data first requires writing a register this is the
+ *             data to write.
  *
- *  Defines the functions and information about the slave the mpu3050 needs to
- *  use the slave device.
+ *  Defines the functions and information about the slave the mpu3050 and
+ *  mpu6050 needs to use the slave device.
  */
 struct ext_slave_descr {
        int (*init) (void *mlsl_handle,
@@ -270,7 +267,7 @@ struct ext_slave_descr {
        int (*read) (void *mlsl_handle,
                     struct ext_slave_descr *slave,
                     struct ext_slave_platform_data *pdata,
-                    unsigned char *data);
+                    __u8 *data);
        int (*config) (void *mlsl_handle,
                       struct ext_slave_descr *slave,
                       struct ext_slave_platform_data *pdata,
@@ -281,22 +278,20 @@ struct ext_slave_descr {
                           struct ext_slave_config *config);
 
        char *name;
-       unsigned char type;
-       unsigned char id;
-       unsigned char reg;
-       unsigned int len;
-       unsigned char endian;
-       struct tFixPntRange range;
+       __u8 type;
+       __u8 id;
+       __u8 read_reg;
+       __u8 read_len;
+       __u8 endian;
+       struct fix_pnt_range range;
+       struct ext_slave_read_trigger *trigger;
 };
 
 /**
- * struct mpu3050_platform_data - Platform data for the mpu3050 driver
+ * struct mpu_platform_data - Platform data for the mpu driver
  * @int_config:                Bits [7:3] of the int config register.
- * @orientation:       Orientation matrix of the gyroscope
  * @level_shifter:     0: VLogic, 1: VDD
- * @accel:             Accel platform data
- * @compass:           Compass platform data
- * @pressure:          Pressure platform data
+ * @orientation:       Orientation matrix of the gyroscope
  *
  * Contains platform specific information on how to configure the MPU3050 to
  * work on this platform.  The orientation matricies are 3x3 rotation matricies
@@ -304,164 +299,64 @@ struct ext_slave_descr {
  * platform orientation.  The values must be one of 0, 1, or -1 and each row and
  * column should have exactly 1 non-zero value.
  */
-struct mpu3050_platform_data {
-       unsigned char int_config;
-       signed char orientation[MPU_NUM_AXES * MPU_NUM_AXES];
-       unsigned char level_shifter;
-       struct ext_slave_platform_data accel;
-       struct ext_slave_platform_data compass;
-       struct ext_slave_platform_data pressure;
+struct mpu_platform_data {
+       __u8 int_config;
+       __u8 level_shifter;
+       __s8 orientation[GYRO_NUM_AXES * GYRO_NUM_AXES];
 };
 
+#if defined __KERNEL__ || defined LINUX
+#define MPU_IOCTL (0x81) /* Magic number for MPU Iocts */
+/* IOCTL commands for /dev/mpu */
 
-/*
-    Accelerometer
-*/
-#define get_accel_slave_descr NULL
-
-#ifdef CONFIG_MPU_SENSORS_ADXL346      /* ADI accelerometer */
-struct ext_slave_descr *adxl346_get_slave_descr(void);
-#undef get_accel_slave_descr
-#define get_accel_slave_descr adxl346_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_BMA150       /* Bosch accelerometer */
-struct ext_slave_descr *bma150_get_slave_descr(void);
-#undef get_accel_slave_descr
-#define get_accel_slave_descr bma150_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_BMA222       /* Bosch 222 accelerometer */
-struct ext_slave_descr *bma222_get_slave_descr(void);
-#undef get_accel_slave_descr
-#define get_accel_slave_descr bma222_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_KXSD9        /* Kionix accelerometer */
-struct ext_slave_descr *kxsd9_get_slave_descr(void);
-#undef get_accel_slave_descr
-#define get_accel_slave_descr kxsd9_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_KXTF9        /* Kionix accelerometer */
-struct ext_slave_descr *kxtf9_get_slave_descr(void);
-#undef get_accel_slave_descr
-#define get_accel_slave_descr kxtf9_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_LIS331DLH    /* ST accelerometer */
-struct ext_slave_descr *lis331dlh_get_slave_descr(void);
-#undef get_accel_slave_descr
-#define get_accel_slave_descr lis331dlh_get_slave_descr
-#endif
-
-
-#ifdef CONFIG_MPU_SENSORS_LIS3DH       /* ST accelerometer */
-struct ext_slave_descr *lis3dh_get_slave_descr(void);
-#undef get_accel_slave_descr
-#define get_accel_slave_descr lis3dh_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_LSM303DLHA   /* ST accelerometer */
-struct ext_slave_descr *lsm303dlha_get_slave_descr(void);
-#undef get_accel_slave_descr
-#define get_accel_slave_descr lsm303dlha_get_slave_descr
-#endif
-
-/* MPU6000 Accel */
-#if defined(CONFIG_MPU_SENSORS_MPU6000) || \
-    defined(CONFIG_MPU_SENSORS_MPU6000_MODULE)
-struct ext_slave_descr *mantis_get_slave_descr(void);
-#undef get_accel_slave_descr
-#define get_accel_slave_descr mantis_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_MMA8450      /* Freescale accelerometer */
-struct ext_slave_descr *mma8450_get_slave_descr(void);
-#undef get_accel_slave_descr
-#define get_accel_slave_descr mma8450_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_MMA845X      /* Freescale accelerometer */
-struct ext_slave_descr *mma845x_get_slave_descr(void);
-#undef get_accel_slave_descr
-#define get_accel_slave_descr mma845x_get_slave_descr
-#endif
-
-
-/*
-    Compass
-*/
-#define get_compass_slave_descr NULL
-
-#ifdef CONFIG_MPU_SENSORS_AK8975       /* AKM compass */
-struct ext_slave_descr *ak8975_get_slave_descr(void);
-#undef get_compass_slave_descr
-#define get_compass_slave_descr ak8975_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_AMI30X       /* AICHI Steel  AMI304/305 compass */
-struct ext_slave_descr *ami30x_get_slave_descr(void);
-#undef get_compass_slave_descr
-#define get_compass_slave_descr ami30x_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_AMI306       /* AICHI Steel AMI306 compass */
-struct ext_slave_descr *ami306_get_slave_descr(void);
-#undef get_compass_slave_descr
-#define get_compass_slave_descr ami306_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_HMC5883      /* Honeywell compass */
-struct ext_slave_descr *hmc5883_get_slave_descr(void);
-#undef get_compass_slave_descr
-#define get_compass_slave_descr hmc5883_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_MMC314X      /* MEMSIC compass */
-struct ext_slave_descr *mmc314x_get_slave_descr(void);
-#undef get_compass_slave_descr
-#define get_compass_slave_descr mmc314x_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_LSM303DLHM   /* ST compass */
-struct ext_slave_descr *lsm303dlhm_get_slave_descr(void);
-#undef get_compass_slave_descr
-#define get_compass_slave_descr lsm303dlhm_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_YAS529       /* Yamaha compass */
-struct ext_slave_descr *yas529_get_slave_descr(void);
-#undef get_compass_slave_descr
-#define get_compass_slave_descr yas529_get_slave_descr
-#endif
-
-#ifdef CONFIG_MPU_SENSORS_YAS530       /* Yamaha compass */
-struct ext_slave_descr *yas530_get_slave_descr(void);
-#undef get_compass_slave_descr
-#define get_compass_slave_descr yas530_get_slave_descr
-#endif
+/*--------------------------------------------------------------------------
+ * Deprecated, debugging only
+ */
+#define MPU_SET_MPU_PLATFORM_DATA      \
+       _IOWR(MPU_IOCTL, 0x01, struct mpu_platform_data)
+#define MPU_SET_EXT_SLAVE_PLATFORM_DATA        \
+       _IOWR(MPU_IOCTL, 0x01, struct ext_slave_platform_data)
+/*--------------------------------------------------------------------------*/
+#define MPU_GET_EXT_SLAVE_PLATFORM_DATA        \
+       _IOWR(MPU_IOCTL, 0x02, struct ext_slave_platform_data)
+#define MPU_GET_MPU_PLATFORM_DATA      \
+       _IOWR(MPU_IOCTL, 0x02, struct mpu_platform_data)
+#define MPU_GET_EXT_SLAVE_DESCR        \
+       _IOWR(MPU_IOCTL, 0x02, struct ext_slave_descr)
+
+#define MPU_READ               _IOWR(MPU_IOCTL, 0x10, struct mpu_read_write)
+#define MPU_WRITE              _IOW(MPU_IOCTL,  0x10, struct mpu_read_write)
+#define MPU_READ_MEM           _IOWR(MPU_IOCTL, 0x11, struct mpu_read_write)
+#define MPU_WRITE_MEM          _IOW(MPU_IOCTL,  0x11, struct mpu_read_write)
+#define MPU_READ_FIFO          _IOWR(MPU_IOCTL, 0x12, struct mpu_read_write)
+#define MPU_WRITE_FIFO         _IOW(MPU_IOCTL,  0x12, struct mpu_read_write)
+
+#define MPU_READ_COMPASS       _IOR(MPU_IOCTL, 0x12, __u8)
+#define MPU_READ_ACCEL         _IOR(MPU_IOCTL, 0x13, __u8)
+#define MPU_READ_PRESSURE      _IOR(MPU_IOCTL, 0x14, __u8)
+
+#define MPU_CONFIG_GYRO                _IOW(MPU_IOCTL, 0x20, struct ext_slave_config)
+#define MPU_CONFIG_ACCEL       _IOW(MPU_IOCTL, 0x21, struct ext_slave_config)
+#define MPU_CONFIG_COMPASS     _IOW(MPU_IOCTL, 0x22, struct ext_slave_config)
+#define MPU_CONFIG_PRESSURE    _IOW(MPU_IOCTL, 0x23, struct ext_slave_config)
+
+#define MPU_GET_CONFIG_GYRO    _IOWR(MPU_IOCTL, 0x20, struct ext_slave_config)
+#define MPU_GET_CONFIG_ACCEL   _IOWR(MPU_IOCTL, 0x21, struct ext_slave_config)
+#define MPU_GET_CONFIG_COMPASS _IOWR(MPU_IOCTL, 0x22, struct ext_slave_config)
+#define MPU_GET_CONFIG_PRESSURE        _IOWR(MPU_IOCTL, 0x23, struct ext_slave_config)
+
+#define MPU_SUSPEND            _IOW(MPU_IOCTL, 0x30, __u32)
+#define MPU_RESUME             _IOW(MPU_IOCTL, 0x31, __u32)
+/* Userspace PM Event response */
+#define MPU_PM_EVENT_HANDLED   _IO(MPU_IOCTL, 0x32)
 
-#ifdef CONFIG_MPU_SENSORS_HSCDTD002B   /* Alps HSCDTD002B compass */
-struct ext_slave_descr *hscdtd002b_get_slave_descr(void);
-#undef get_compass_slave_descr
-#define get_compass_slave_descr hscdtd002b_get_slave_descr
-#endif
+#define MPU_GET_REQUESTED_SENSORS      _IOR(MPU_IOCTL, 0x40, __u8)
+#define MPU_SET_REQUESTED_SENSORS      _IOW(MPU_IOCTL, 0x40, __u8)
+#define MPU_GET_IGNORE_SYSTEM_SUSPEND  _IOR(MPU_IOCTL, 0x41, __u8)
+#define MPU_SET_IGNORE_SYSTEM_SUSPEND  _IOW(MPU_IOCTL, 0x41, __u8)
+#define MPU_GET_MLDL_STATUS            _IOR(MPU_IOCTL, 0x42, __u8)
+#define MPU_GET_I2C_SLAVES_ENABLED     _IOR(MPU_IOCTL, 0x43, __u8)
 
-#ifdef CONFIG_MPU_SENSORS_HSCDTD004A   /* Alps HSCDTD004A compass */
-struct ext_slave_descr *hscdtd004a_get_slave_descr(void);
-#undef get_compass_slave_descr
-#define get_compass_slave_descr hscdtd004a_get_slave_descr
-#endif
-/*
-    Pressure
-*/
-#define get_pressure_slave_descr NULL
-
-#ifdef CONFIG_MPU_SENSORS_BMA085       /* BMA pressure */
-struct ext_slave_descr *bma085_get_slave_descr(void);
-#undef get_pressure_slave_descr
-#define get_pressure_slave_descr bma085_get_slave_descr
 #endif
 
 #endif                         /* __MPU_H_ */