summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rw-r--r--gnu/local.mk12
-rw-r--r--gnu/packages/linux-libre-loongson2f.conf2937
-rw-r--r--gnu/packages/linux.scm26
-rw-r--r--gnu/packages/patches/linux-libre-export-loongson-chipcfg.patch28
-rw-r--r--gnu/packages/patches/linux-libre-gdium.patch2549
-rw-r--r--gnu/packages/patches/linux-libre-loongson2-cpufreq-fix.patch59
-rw-r--r--gnu/packages/patches/linux-libre-loongson2-math-emu.patch386
-rw-r--r--gnu/packages/patches/linux-libre-loongson2-max-physmem-bits.patch36
-rw-r--r--gnu/packages/patches/linux-libre-mips-ftrace-fix.patch85
-rw-r--r--gnu/packages/patches/linux-libre-mips-hugetlb-fix.patch15
-rw-r--r--gnu/packages/patches/linux-libre-mips-math-emu-fix-pt1.patch35
-rw-r--r--gnu/packages/patches/linux-libre-mips-math-emu-fix-pt2.patch66
-rw-r--r--gnu/packages/patches/linux-libre-yeeloong-rfkill-key-fix.patch48
-rw-r--r--gnu/packages/patches/linux-libre-yeeloong-silence-ec-messages.patch26
-rw-r--r--gnu/packages/patches/linux-libre-yeeloong.patch3451
16 files changed, 9761 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am
index 8bae85e144..6d483f825f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -176,7 +176,8 @@ KCONFIGS =					\
   gnu/packages/linux-libre-4.4-i686.conf	\
   gnu/packages/linux-libre-4.4-x86_64.conf	\
   gnu/packages/linux-libre-4.1-i686.conf	\
-  gnu/packages/linux-libre-4.1-x86_64.conf
+  gnu/packages/linux-libre-4.1-x86_64.conf	\
+  gnu/packages/linux-libre-loongson2f.conf
 
 # Templates, examples.
 EXAMPLES =					\
diff --git a/gnu/local.mk b/gnu/local.mk
index 53621d8b94..87a2b18d8a 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -644,6 +644,18 @@ dist_patch_DATA =						\
   %D%/packages/patches/libwmf-CVE-2015-4695.patch		\
   %D%/packages/patches/libwmf-CVE-2015-4696.patch		\
   %D%/packages/patches/libxslt-generated-ids.patch		\
+  %D%/packages/patches/linux-libre-export-loongson-chipcfg.patch \
+  %D%/packages/patches/linux-libre-gdium.patch			\
+  %D%/packages/patches/linux-libre-loongson2-cpufreq-fix.patch	\
+  %D%/packages/patches/linux-libre-loongson2-math-emu.patch	\
+  %D%/packages/patches/linux-libre-loongson2-max-physmem-bits.patch \
+  %D%/packages/patches/linux-libre-mips-ftrace-fix.patch	\
+  %D%/packages/patches/linux-libre-mips-hugetlb-fix.patch	\
+  %D%/packages/patches/linux-libre-mips-math-emu-fix-pt1.patch	\
+  %D%/packages/patches/linux-libre-mips-math-emu-fix-pt2.patch	\
+  %D%/packages/patches/linux-libre-yeeloong-rfkill-key-fix.patch \
+  %D%/packages/patches/linux-libre-yeeloong-silence-ec-messages.patch \
+  %D%/packages/patches/linux-libre-yeeloong.patch		\
   %D%/packages/patches/lirc-localstatedir.patch			\
   %D%/packages/patches/lm-sensors-hwmon-attrs.patch		\
   %D%/packages/patches/lua-CVE-2014-5461.patch                      \
diff --git a/gnu/packages/linux-libre-loongson2f.conf b/gnu/packages/linux-libre-loongson2f.conf
new file mode 100644
index 0000000000..815bb913c9
--- /dev/null
+++ b/gnu/packages/linux-libre-loongson2f.conf
@@ -0,0 +1,2937 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# Linux/mips 4.1.30-gnu Kernel Configuration
+#
+CONFIG_MIPS=y
+
+#
+# Machine selection
+#
+# CONFIG_MIPS_ALCHEMY is not set
+# CONFIG_AR7 is not set
+# CONFIG_ATH25 is not set
+# CONFIG_ATH79 is not set
+# CONFIG_BMIPS_GENERIC is not set
+# CONFIG_BCM47XX is not set
+# CONFIG_BCM63XX is not set
+# CONFIG_MIPS_COBALT is not set
+# CONFIG_MACH_DECSTATION is not set
+# CONFIG_MACH_JAZZ is not set
+# CONFIG_MACH_JZ4740 is not set
+# CONFIG_LANTIQ is not set
+# CONFIG_LASAT is not set
+CONFIG_MACH_LOONGSON=y
+# CONFIG_MACH_LOONGSON1 is not set
+# CONFIG_MACH_PISTACHIO is not set
+# CONFIG_MIPS_MALTA is not set
+# CONFIG_MIPS_SEAD3 is not set
+# CONFIG_NEC_MARKEINS is not set
+# CONFIG_MACH_VR41XX is not set
+# CONFIG_NXP_STB220 is not set
+# CONFIG_NXP_STB225 is not set
+# CONFIG_PMC_MSP is not set
+# CONFIG_RALINK is not set
+# CONFIG_SGI_IP22 is not set
+# CONFIG_SGI_IP27 is not set
+# CONFIG_SGI_IP28 is not set
+# CONFIG_SGI_IP32 is not set
+# CONFIG_SIBYTE_CRHINE is not set
+# CONFIG_SIBYTE_CARMEL is not set
+# CONFIG_SIBYTE_CRHONE is not set
+# CONFIG_SIBYTE_RHONE is not set
+# CONFIG_SIBYTE_SWARM is not set
+# CONFIG_SIBYTE_LITTLESUR is not set
+# CONFIG_SIBYTE_SENTOSA is not set
+# CONFIG_SIBYTE_BIGSUR is not set
+# CONFIG_SNI_RM is not set
+# CONFIG_MACH_TX39XX is not set
+# CONFIG_MACH_TX49XX is not set
+# CONFIG_MIKROTIK_RB532 is not set
+# CONFIG_CAVIUM_OCTEON_SOC is not set
+# CONFIG_NLM_XLR_BOARD is not set
+# CONFIG_NLM_XLP_BOARD is not set
+# CONFIG_MIPS_PARAVIRT is not set
+# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
+# CONFIG_LEMOTE_FULOONG2E is not set
+CONFIG_LEMOTE_MACH2F=y
+# CONFIG_DEXXON_GDIUM is not set
+# CONFIG_LOONGSON_MACH3X is not set
+CONFIG_CS5536=y
+CONFIG_LOONGSON_SUSPEND=y
+CONFIG_LOONGSON_UART_BASE=y
+CONFIG_LOONGSON_MC146818=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_SCHED_OMIT_FRAME_POINTER=y
+CONFIG_CEVT_R4K=y
+CONFIG_CSRC_R4K=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_I8259=y
+# CONFIG_MIPS_MACHINE is not set
+# CONFIG_NO_IOPORT_MAP is not set
+CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_ISA_DMA_SUPPORT_BROKEN=y
+CONFIG_ISA_DMA_API=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_HUGETLBFS=y
+CONFIG_MIPS_HUGE_TLB_SUPPORT=y
+CONFIG_IRQ_CPU=y
+CONFIG_BOOT_ELF32=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+
+#
+# CPU selection
+#
+CONFIG_CPU_LOONGSON2F=y
+CONFIG_CPU_NOP_WORKAROUNDS=y
+CONFIG_CPU_JUMP_WORKAROUNDS=y
+CONFIG_CPU_LOONGSON2F_WORKAROUNDS=y
+CONFIG_SYS_SUPPORTS_ZBOOT=y
+CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y
+CONFIG_CPU_LOONGSON2=y
+CONFIG_SYS_HAS_CPU_LOONGSON2F=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_64BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_CPUFREQ=y
+CONFIG_CPU_SUPPORTS_ADDRWINCFG=y
+CONFIG_CPU_SUPPORTS_HUGEPAGES=y
+CONFIG_CPU_SUPPORTS_UNCACHED_ACCELERATED=y
+
+#
+# Kernel type
+#
+# CONFIG_32BIT is not set
+CONFIG_64BIT=y
+# CONFIG_KVM_GUEST is not set
+CONFIG_PAGE_SIZE_16KB=y
+# CONFIG_PAGE_SIZE_64KB is not set
+CONFIG_FORCE_MAX_ZONEORDER=12
+CONFIG_BOARD_SCACHE=y
+CONFIG_CPU_GENERIC_DUMP_TLB=y
+CONFIG_CPU_R4K_FPU=y
+CONFIG_CPU_R4K_CACHE_TLB=y
+CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y
+CONFIG_CPU_HAS_WB=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_SPARSEMEM=y
+CONFIG_HAVE_MEMORY_PRESENT=y
+CONFIG_SPARSEMEM_STATIC=y
+CONFIG_HAVE_MEMBLOCK=y
+CONFIG_HAVE_MEMBLOCK_NODE_MAP=y
+CONFIG_ARCH_DISCARD_MEMBLOCK=y
+# CONFIG_HAVE_BOOTMEM_INFO_NODE is not set
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4
+CONFIG_MEMORY_BALLOON=y
+# CONFIG_COMPACTION is not set
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_ZONE_DMA_FLAG=0
+CONFIG_VIRT_TO_BUS=y
+# CONFIG_KSM is not set
+CONFIG_DEFAULT_MMAP_MIN_ADDR=65536
+# CONFIG_TRANSPARENT_HUGEPAGE is not set
+CONFIG_NEED_PER_CPU_KM=y
+# CONFIG_CLEANCACHE is not set
+# CONFIG_FRONTSWAP is not set
+# CONFIG_CMA is not set
+# CONFIG_ZPOOL is not set
+# CONFIG_ZBUD is not set
+# CONFIG_ZSMALLOC is not set
+# CONFIG_HZ_48 is not set
+CONFIG_HZ_100=y
+# CONFIG_HZ_128 is not set
+# CONFIG_HZ_250 is not set
+# CONFIG_HZ_256 is not set
+# CONFIG_HZ_1000 is not set
+# CONFIG_HZ_1024 is not set
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_HZ=100
+CONFIG_SCHED_HRTICK=y
+# CONFIG_PREEMPT_NONE is not set
+CONFIG_PREEMPT_VOLUNTARY=y
+# CONFIG_PREEMPT is not set
+# CONFIG_KEXEC is not set
+# CONFIG_CRASH_DUMP is not set
+# CONFIG_SECCOMP is not set
+# CONFIG_MIPS_O32_FP64_SUPPORT is not set
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_PGTABLE_LEVELS=3
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+CONFIG_IRQ_WORK=y
+CONFIG_BUILDTIME_EXTABLE_SORT=y
+
+#
+# General setup
+#
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_CROSS_COMPILE=""
+# CONFIG_COMPILE_TEST is not set
+CONFIG_LOCALVERSION=""
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_HAVE_KERNEL_GZIP=y
+CONFIG_HAVE_KERNEL_BZIP2=y
+CONFIG_HAVE_KERNEL_LZMA=y
+CONFIG_HAVE_KERNEL_XZ=y
+CONFIG_HAVE_KERNEL_LZO=y
+CONFIG_HAVE_KERNEL_LZ4=y
+# CONFIG_KERNEL_GZIP is not set
+# CONFIG_KERNEL_BZIP2 is not set
+CONFIG_KERNEL_LZMA=y
+# CONFIG_KERNEL_XZ is not set
+# CONFIG_KERNEL_LZO is not set
+# CONFIG_KERNEL_LZ4 is not set
+CONFIG_DEFAULT_HOSTNAME="(none)"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_CROSS_MEMORY_ATTACH is not set
+# CONFIG_FHANDLE is not set
+# CONFIG_USELIB is not set
+# CONFIG_AUDIT is not set
+
+#
+# IRQ subsystem
+#
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_IRQ_DOMAIN=y
+# CONFIG_IRQ_DOMAIN_DEBUG is not set
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+
+#
+# Timers subsystem
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_HZ_PERIODIC=y
+# CONFIG_NO_HZ_IDLE is not set
+# CONFIG_NO_HZ is not set
+CONFIG_HIGH_RES_TIMERS=y
+
+#
+# CPU/Task time and stats accounting
+#
+CONFIG_TICK_CPU_ACCOUNTING=y
+# CONFIG_VIRT_CPU_ACCOUNTING_GEN is not set
+# CONFIG_IRQ_TIME_ACCOUNTING is not set
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_BSD_PROCESS_ACCT_V3=y
+CONFIG_TASKSTATS=y
+CONFIG_TASK_DELAY_ACCT=y
+CONFIG_TASK_XACCT=y
+CONFIG_TASK_IO_ACCOUNTING=y
+
+#
+# RCU Subsystem
+#
+CONFIG_TINY_RCU=y
+CONFIG_SRCU=y
+# CONFIG_TASKS_RCU is not set
+# CONFIG_RCU_STALL_COMMON is not set
+# CONFIG_TREE_RCU_TRACE is not set
+CONFIG_RCU_KTHREAD_PRIO=0
+# CONFIG_RCU_EXPEDITE_BOOT is not set
+# CONFIG_BUILD_BIN2C is not set
+# CONFIG_IKCONFIG is not set
+CONFIG_LOG_BUF_SHIFT=15
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_CGROUPS=y
+# CONFIG_CGROUP_DEBUG is not set
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_DEVICE=y
+CONFIG_CPUSETS=y
+CONFIG_PROC_PID_CPUSET=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_PAGE_COUNTER=y
+CONFIG_MEMCG=y
+CONFIG_MEMCG_SWAP=y
+CONFIG_MEMCG_SWAP_ENABLED=y
+CONFIG_MEMCG_KMEM=y
+CONFIG_CGROUP_HUGETLB=y
+CONFIG_CGROUP_PERF=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+CONFIG_CFS_BANDWIDTH=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_CGROUP=y
+# CONFIG_DEBUG_BLK_CGROUP is not set
+# CONFIG_CHECKPOINT_RESTORE is not set
+CONFIG_NAMESPACES=y
+CONFIG_UTS_NS=y
+CONFIG_IPC_NS=y
+# CONFIG_USER_NS is not set
+CONFIG_PID_NS=y
+CONFIG_NET_NS=y
+CONFIG_SCHED_AUTOGROUP=y
+# CONFIG_SYSFS_DEPRECATED is not set
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+CONFIG_RD_BZIP2=y
+CONFIG_RD_LZMA=y
+CONFIG_RD_XZ=y
+CONFIG_RD_LZO=y
+CONFIG_RD_LZ4=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_BPF=y
+CONFIG_EXPERT=y
+CONFIG_MULTIUSER=y
+CONFIG_SGETMASK_SYSCALL=y
+CONFIG_SYSFS_SYSCALL=y
+# CONFIG_SYSCTL_SYSCALL is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+# CONFIG_BPF_SYSCALL is not set
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_ADVISE_SYSCALLS=y
+CONFIG_PCI_QUIRKS=y
+# CONFIG_EMBEDDED is not set
+CONFIG_HAVE_PERF_EVENTS=y
+CONFIG_PERF_USE_VMALLOC=y
+
+#
+# Kernel Performance Events And Counters
+#
+CONFIG_PERF_EVENTS=y
+# CONFIG_DEBUG_PERF_USE_VMALLOC is not set
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_SYSTEM_TRUSTED_KEYRING is not set
+# CONFIG_PROFILING is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+# CONFIG_JUMP_LABEL is not set
+# CONFIG_UPROBES is not set
+CONFIG_HAVE_64BIT_ALIGNED_ACCESS=y
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_ARCH_TRACEHOOK=y
+CONFIG_HAVE_DMA_ATTRS=y
+CONFIG_HAVE_DMA_CONTIGUOUS=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_HAVE_CLK=y
+CONFIG_HAVE_DMA_API_DEBUG=y
+CONFIG_HAVE_ARCH_JUMP_LABEL=y
+CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y
+CONFIG_ARCH_WANT_COMPAT_IPC_PARSE_VERSION=y
+CONFIG_ARCH_WANT_OLD_COMPAT_IPC=y
+CONFIG_HAVE_ARCH_SECCOMP_FILTER=y
+CONFIG_HAVE_CC_STACKPROTECTOR=y
+# CONFIG_CC_STACKPROTECTOR is not set
+CONFIG_CC_STACKPROTECTOR_NONE=y
+# CONFIG_CC_STACKPROTECTOR_REGULAR is not set
+# CONFIG_CC_STACKPROTECTOR_STRONG is not set
+CONFIG_HAVE_CONTEXT_TRACKING=y
+CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y
+CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y
+CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE=y
+CONFIG_HAVE_MOD_ARCH_SPECIFIC=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_ARCH_HAS_ELF_RANDOMIZE=y
+CONFIG_CLONE_BACKWARDS=y
+
+#
+# GCOV-based kernel profiling
+#
+# CONFIG_GCOV_KERNEL is not set
+# CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_MODULE_FORCE_UNLOAD is not set
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+# CONFIG_MODULE_SIG is not set
+# CONFIG_MODULE_COMPRESS is not set
+CONFIG_BLOCK=y
+CONFIG_BLK_DEV_BSG=y
+CONFIG_BLK_DEV_BSGLIB=y
+CONFIG_BLK_DEV_INTEGRITY=y
+# CONFIG_BLK_DEV_THROTTLING is not set
+# CONFIG_BLK_CMDLINE_PARSER is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_AIX_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+CONFIG_MAC_PARTITION=y
+CONFIG_MSDOS_PARTITION=y
+CONFIG_BSD_DISKLABEL=y
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+CONFIG_EFI_PARTITION=y
+# CONFIG_SYSV68_PARTITION is not set
+# CONFIG_CMDLINE_PARTITION is not set
+CONFIG_BLOCK_COMPAT=y
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_DEADLINE=m
+CONFIG_IOSCHED_CFQ=y
+# CONFIG_CFQ_GROUP_IOSCHED is not set
+CONFIG_DEFAULT_CFQ=y
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="cfq"
+CONFIG_INLINE_SPIN_UNLOCK_IRQ=y
+CONFIG_INLINE_READ_UNLOCK=y
+CONFIG_INLINE_READ_UNLOCK_IRQ=y
+CONFIG_INLINE_WRITE_UNLOCK=y
+CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
+CONFIG_FREEZER=y
+
+#
+# Bus options (PCI, PCMCIA, EISA, ISA, TC)
+#
+CONFIG_HW_HAS_PCI=y
+CONFIG_PCI=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_BUS_ADDR_T_64BIT=y
+# CONFIG_PCI_MSI is not set
+# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_REALLOC_ENABLE_AUTO is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
+# CONFIG_PCI_PRI is not set
+# CONFIG_PCI_PASID is not set
+
+#
+# PCI host controller drivers
+#
+# CONFIG_PCIEPORTBUS is not set
+CONFIG_MMU=y
+# CONFIG_PCCARD is not set
+# CONFIG_HOTPLUG_PCI is not set
+# CONFIG_RAPIDIO is not set
+
+#
+# Executable file formats
+#
+CONFIG_BINFMT_ELF=y
+CONFIG_ARCH_BINFMT_ELF_STATE=y
+CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=y
+CONFIG_BINFMT_SCRIPT=y
+# CONFIG_HAVE_AOUT is not set
+CONFIG_BINFMT_MISC=m
+CONFIG_COREDUMP=y
+CONFIG_MIPS32_COMPAT=y
+CONFIG_COMPAT=y
+CONFIG_SYSVIPC_COMPAT=y
+CONFIG_MIPS32_O32=y
+CONFIG_MIPS32_N32=y
+CONFIG_BINFMT_ELF32=y
+
+#
+# Power management options
+#
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_SUSPEND=y
+CONFIG_SUSPEND_FREEZER=y
+CONFIG_HIBERNATE_CALLBACKS=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION=""
+CONFIG_PM_SLEEP=y
+# CONFIG_PM_AUTOSLEEP is not set
+# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+CONFIG_PM_CLK=y
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+
+#
+# CPU Power Management
+#
+
+#
+# CPU Idle
+#
+# CONFIG_CPU_IDLE is not set
+# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
+CONFIG_NET=y
+CONFIG_COMPAT_NETLINK_MESSAGES=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_DIAG is not set
+CONFIG_UNIX=y
+# CONFIG_UNIX_DIAG is not set
+CONFIG_XFRM=y
+CONFIG_XFRM_ALGO=m
+CONFIG_XFRM_USER=m
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+CONFIG_NET_KEY=m
+# CONFIG_NET_KEY_MIGRATE is not set
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_ADVANCED_ROUTER=y
+# CONFIG_IP_FIB_TRIE_STATS is not set
+CONFIG_IP_MULTIPLE_TABLES=y
+CONFIG_IP_ROUTE_MULTIPATH=y
+CONFIG_IP_ROUTE_VERBOSE=y
+CONFIG_IP_ROUTE_CLASSID=y
+# CONFIG_IP_PNP is not set
+CONFIG_NET_IPIP=m
+# CONFIG_NET_IPGRE_DEMUX is not set
+CONFIG_NET_IP_TUNNEL=m
+CONFIG_IP_MROUTE=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PIMSM_V1=y
+CONFIG_IP_PIMSM_V2=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_NET_IPVTI is not set
+# CONFIG_NET_UDP_TUNNEL is not set
+# CONFIG_NET_FOU is not set
+# CONFIG_NET_FOU_IP_TUNNELS is not set
+# CONFIG_GENEVE is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=m
+CONFIG_INET_XFRM_MODE_TUNNEL=m
+CONFIG_INET_XFRM_MODE_BEET=m
+CONFIG_INET_LRO=y
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_INET_UDP_DIAG is not set
+CONFIG_TCP_CONG_ADVANCED=y
+CONFIG_TCP_CONG_BIC=y
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_TCP_CONG_WESTWOOD=m
+CONFIG_TCP_CONG_HTCP=m
+# CONFIG_TCP_CONG_HSTCP is not set
+# CONFIG_TCP_CONG_HYBLA is not set
+# CONFIG_TCP_CONG_VEGAS is not set
+# CONFIG_TCP_CONG_SCALABLE is not set
+# CONFIG_TCP_CONG_LP is not set
+# CONFIG_TCP_CONG_VENO is not set
+# CONFIG_TCP_CONG_YEAH is not set
+# CONFIG_TCP_CONG_ILLINOIS is not set
+# CONFIG_TCP_CONG_DCTCP is not set
+CONFIG_DEFAULT_BIC=y
+# CONFIG_DEFAULT_CUBIC is not set
+# CONFIG_DEFAULT_RENO is not set
+CONFIG_DEFAULT_TCP_CONG="bic"
+CONFIG_TCP_MD5SIG=y
+CONFIG_IPV6=m
+CONFIG_IPV6_ROUTER_PREF=y
+# CONFIG_IPV6_ROUTE_INFO is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+CONFIG_INET6_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_VTI=m
+CONFIG_IPV6_SIT=m
+# CONFIG_IPV6_SIT_6RD is not set
+CONFIG_IPV6_NDISC_NODETYPE=y
+CONFIG_IPV6_TUNNEL=m
+# CONFIG_IPV6_GRE is not set
+CONFIG_IPV6_MULTIPLE_TABLES=y
+CONFIG_IPV6_SUBTREES=y
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+# CONFIG_NET_PTP_CLASSIFY is not set
+# CONFIG_NETWORK_PHY_TIMESTAMPING is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+CONFIG_NETFILTER_NETLINK=m
+# CONFIG_NETFILTER_NETLINK_ACCT is not set
+CONFIG_NETFILTER_NETLINK_QUEUE=m
+CONFIG_NETFILTER_NETLINK_LOG=m
+CONFIG_NF_CONNTRACK=m
+CONFIG_NF_CONNTRACK_MARK=y
+# CONFIG_NF_CONNTRACK_ZONES is not set
+CONFIG_NF_CONNTRACK_PROCFS=y
+# CONFIG_NF_CONNTRACK_EVENTS is not set
+# CONFIG_NF_CONNTRACK_TIMEOUT is not set
+# CONFIG_NF_CONNTRACK_TIMESTAMP is not set
+CONFIG_NF_CT_PROTO_DCCP=m
+CONFIG_NF_CT_PROTO_SCTP=m
+CONFIG_NF_CT_PROTO_UDPLITE=m
+# CONFIG_NF_CONNTRACK_AMANDA is not set
+CONFIG_NF_CONNTRACK_FTP=m
+CONFIG_NF_CONNTRACK_H323=m
+CONFIG_NF_CONNTRACK_IRC=m
+# CONFIG_NF_CONNTRACK_NETBIOS_NS is not set
+# CONFIG_NF_CONNTRACK_SNMP is not set
+# CONFIG_NF_CONNTRACK_PPTP is not set
+# CONFIG_NF_CONNTRACK_SANE is not set
+CONFIG_NF_CONNTRACK_SIP=m
+CONFIG_NF_CONNTRACK_TFTP=m
+CONFIG_NF_CT_NETLINK=m
+# CONFIG_NF_CT_NETLINK_TIMEOUT is not set
+# CONFIG_NETFILTER_NETLINK_QUEUE_CT is not set
+# CONFIG_NF_TABLES is not set
+CONFIG_NETFILTER_XTABLES=m
+
+#
+# Xtables combined modules
+#
+CONFIG_NETFILTER_XT_MARK=m
+CONFIG_NETFILTER_XT_CONNMARK=m
+
+#
+# Xtables targets
+#
+CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m
+CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
+CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
+CONFIG_NETFILTER_XT_TARGET_CT=m
+CONFIG_NETFILTER_XT_TARGET_DSCP=m
+CONFIG_NETFILTER_XT_TARGET_HL=m
+# CONFIG_NETFILTER_XT_TARGET_HMARK is not set
+CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
+# CONFIG_NETFILTER_XT_TARGET_LED is not set
+# CONFIG_NETFILTER_XT_TARGET_LOG is not set
+CONFIG_NETFILTER_XT_TARGET_MARK=m
+CONFIG_NETFILTER_XT_TARGET_NFLOG=m
+CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
+CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
+CONFIG_NETFILTER_XT_TARGET_RATEEST=m
+CONFIG_NETFILTER_XT_TARGET_TEE=m
+CONFIG_NETFILTER_XT_TARGET_TPROXY=m
+CONFIG_NETFILTER_XT_TARGET_TRACE=m
+CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
+CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
+
+#
+# Xtables matches
+#
+# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set
+# CONFIG_NETFILTER_XT_MATCH_BPF is not set
+# CONFIG_NETFILTER_XT_MATCH_CGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set
+CONFIG_NETFILTER_XT_MATCH_COMMENT=m
+CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m
+# CONFIG_NETFILTER_XT_MATCH_CONNLABEL is not set
+CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_CONNMARK=m
+CONFIG_NETFILTER_XT_MATCH_CONNTRACK=m
+CONFIG_NETFILTER_XT_MATCH_CPU=m
+# CONFIG_NETFILTER_XT_MATCH_DCCP is not set
+# CONFIG_NETFILTER_XT_MATCH_DEVGROUP is not set
+# CONFIG_NETFILTER_XT_MATCH_DSCP is not set
+CONFIG_NETFILTER_XT_MATCH_ECN=m
+# CONFIG_NETFILTER_XT_MATCH_ESP is not set
+CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m
+CONFIG_NETFILTER_XT_MATCH_HELPER=m
+CONFIG_NETFILTER_XT_MATCH_HL=m
+# CONFIG_NETFILTER_XT_MATCH_IPCOMP is not set
+CONFIG_NETFILTER_XT_MATCH_IPRANGE=m
+# CONFIG_NETFILTER_XT_MATCH_L2TP is not set
+CONFIG_NETFILTER_XT_MATCH_LENGTH=m
+CONFIG_NETFILTER_XT_MATCH_LIMIT=m
+CONFIG_NETFILTER_XT_MATCH_MAC=m
+CONFIG_NETFILTER_XT_MATCH_MARK=m
+CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m
+# CONFIG_NETFILTER_XT_MATCH_NFACCT is not set
+# CONFIG_NETFILTER_XT_MATCH_OSF is not set
+CONFIG_NETFILTER_XT_MATCH_OWNER=m
+CONFIG_NETFILTER_XT_MATCH_POLICY=m
+CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
+CONFIG_NETFILTER_XT_MATCH_QUOTA=m
+CONFIG_NETFILTER_XT_MATCH_RATEEST=m
+CONFIG_NETFILTER_XT_MATCH_REALM=m
+CONFIG_NETFILTER_XT_MATCH_RECENT=m
+CONFIG_NETFILTER_XT_MATCH_SCTP=m
+CONFIG_NETFILTER_XT_MATCH_SOCKET=m
+CONFIG_NETFILTER_XT_MATCH_STATE=m
+CONFIG_NETFILTER_XT_MATCH_STATISTIC=m
+CONFIG_NETFILTER_XT_MATCH_STRING=m
+CONFIG_NETFILTER_XT_MATCH_TCPMSS=m
+CONFIG_NETFILTER_XT_MATCH_TIME=m
+CONFIG_NETFILTER_XT_MATCH_U32=m
+# CONFIG_IP_SET is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV4=m
+CONFIG_NF_CONNTRACK_IPV4=m
+CONFIG_NF_CONNTRACK_PROC_COMPAT=y
+# CONFIG_NF_LOG_ARP is not set
+# CONFIG_NF_LOG_IPV4 is not set
+CONFIG_NF_REJECT_IPV4=m
+# CONFIG_NF_NAT_IPV4 is not set
+CONFIG_IP_NF_IPTABLES=m
+CONFIG_IP_NF_MATCH_AH=m
+CONFIG_IP_NF_MATCH_ECN=m
+# CONFIG_IP_NF_MATCH_RPFILTER is not set
+CONFIG_IP_NF_MATCH_TTL=m
+CONFIG_IP_NF_FILTER=m
+CONFIG_IP_NF_TARGET_REJECT=m
+# CONFIG_IP_NF_TARGET_SYNPROXY is not set
+# CONFIG_IP_NF_NAT is not set
+CONFIG_IP_NF_MANGLE=m
+CONFIG_IP_NF_TARGET_CLUSTERIP=m
+CONFIG_IP_NF_TARGET_ECN=m
+CONFIG_IP_NF_TARGET_TTL=m
+CONFIG_IP_NF_RAW=m
+CONFIG_IP_NF_ARPTABLES=m
+CONFIG_IP_NF_ARPFILTER=m
+CONFIG_IP_NF_ARP_MANGLE=m
+
+#
+# IPv6: Netfilter Configuration
+#
+CONFIG_NF_DEFRAG_IPV6=m
+CONFIG_NF_CONNTRACK_IPV6=m
+CONFIG_NF_REJECT_IPV6=m
+# CONFIG_NF_LOG_IPV6 is not set
+# CONFIG_NF_NAT_IPV6 is not set
+CONFIG_IP6_NF_IPTABLES=m
+CONFIG_IP6_NF_MATCH_AH=m
+CONFIG_IP6_NF_MATCH_EUI64=m
+CONFIG_IP6_NF_MATCH_FRAG=m
+CONFIG_IP6_NF_MATCH_OPTS=m
+CONFIG_IP6_NF_MATCH_HL=m
+CONFIG_IP6_NF_MATCH_IPV6HEADER=m
+CONFIG_IP6_NF_MATCH_MH=m
+# CONFIG_IP6_NF_MATCH_RPFILTER is not set
+CONFIG_IP6_NF_MATCH_RT=m
+CONFIG_IP6_NF_TARGET_HL=m
+CONFIG_IP6_NF_FILTER=m
+CONFIG_IP6_NF_TARGET_REJECT=m
+# CONFIG_IP6_NF_TARGET_SYNPROXY is not set
+CONFIG_IP6_NF_MANGLE=m
+CONFIG_IP6_NF_RAW=m
+# CONFIG_IP6_NF_NAT is not set
+# CONFIG_IP_DCCP is not set
+CONFIG_IP_SCTP=m
+# CONFIG_SCTP_DBG_OBJCNT is not set
+CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5=y
+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1 is not set
+# CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE is not set
+CONFIG_SCTP_COOKIE_HMAC_MD5=y
+# CONFIG_SCTP_COOKIE_HMAC_SHA1 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_HAVE_NET_DSA=y
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_PHONET is not set
+# CONFIG_6LOWPAN is not set
+# CONFIG_IEEE802154 is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+CONFIG_DNS_RESOLVER=m
+# CONFIG_BATMAN_ADV is not set
+# CONFIG_OPENVSWITCH is not set
+# CONFIG_VSOCKETS is not set
+# CONFIG_NETLINK_MMAP is not set
+# CONFIG_NETLINK_DIAG is not set
+# CONFIG_MPLS is not set
+# CONFIG_HSR is not set
+# CONFIG_NET_SWITCHDEV is not set
+# CONFIG_CGROUP_NET_PRIO is not set
+# CONFIG_CGROUP_NET_CLASSID is not set
+CONFIG_NET_RX_BUSY_POLL=y
+CONFIG_BQL=y
+# CONFIG_BPF_JIT is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+CONFIG_FIB_RULES=y
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_WEXT_CORE=y
+CONFIG_WEXT_PROC=y
+CONFIG_WEXT_PRIV=y
+CONFIG_CFG80211=y
+# CONFIG_NL80211_TESTMODE is not set
+# CONFIG_CFG80211_DEVELOPER_WARNINGS is not set
+# CONFIG_CFG80211_REG_DEBUG is not set
+# CONFIG_CFG80211_CERTIFICATION_ONUS is not set
+CONFIG_CFG80211_DEFAULT_PS=y
+# CONFIG_CFG80211_DEBUGFS is not set
+# CONFIG_CFG80211_INTERNAL_REGDB is not set
+CONFIG_CFG80211_WEXT=y
+# CONFIG_LIB80211 is not set
+CONFIG_MAC80211=y
+CONFIG_MAC80211_HAS_RC=y
+CONFIG_MAC80211_RC_MINSTREL=y
+CONFIG_MAC80211_RC_MINSTREL_HT=y
+# CONFIG_MAC80211_RC_MINSTREL_VHT is not set
+CONFIG_MAC80211_RC_DEFAULT_MINSTREL=y
+CONFIG_MAC80211_RC_DEFAULT="minstrel_ht"
+# CONFIG_MAC80211_MESH is not set
+CONFIG_MAC80211_LEDS=y
+# CONFIG_MAC80211_DEBUGFS is not set
+# CONFIG_MAC80211_MESSAGE_TRACING is not set
+# CONFIG_MAC80211_DEBUG_MENU is not set
+# CONFIG_WIMAX is not set
+CONFIG_RFKILL=y
+CONFIG_RFKILL_LEDS=y
+CONFIG_RFKILL_INPUT=y
+# CONFIG_RFKILL_GPIO is not set
+CONFIG_NET_9P=m
+CONFIG_NET_9P_VIRTIO=m
+# CONFIG_NET_9P_DEBUG is not set
+# CONFIG_CAIF is not set
+# CONFIG_CEPH_LIB is not set
+# CONFIG_NFC is not set
+CONFIG_HAVE_BPF_JIT=y
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+CONFIG_FW_LOADER=y
+CONFIG_FIRMWARE_IN_KERNEL=y
+CONFIG_EXTRA_FIRMWARE=""
+# CONFIG_FW_LOADER_USER_HELPER_FALLBACK is not set
+CONFIG_ALLOW_DEV_COREDUMP=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_GENERIC_CPU_DEVICES is not set
+# CONFIG_DMA_SHARED_BUFFER is not set
+
+#
+# Bus devices
+#
+# CONFIG_BRCMSTB_GISB_ARB is not set
+CONFIG_CONNECTOR=m
+# CONFIG_MTD is not set
+CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_NULL_BLK is not set
+# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set
+# CONFIG_BLK_CPQ_CISS_DA is not set
+# CONFIG_BLK_DEV_DAC960 is not set
+# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_LOOP_MIN_COUNT=8
+CONFIG_BLK_DEV_CRYPTOLOOP=m
+# CONFIG_BLK_DEV_DRBD is not set
+# CONFIG_BLK_DEV_NBD is not set
+CONFIG_BLK_DEV_NVME=m
+# CONFIG_BLK_DEV_SKD is not set
+# CONFIG_BLK_DEV_SX8 is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=16
+CONFIG_BLK_DEV_RAM_SIZE=8192
+# CONFIG_BLK_DEV_PMEM is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_VIRTIO_BLK=m
+# CONFIG_BLK_DEV_HD is not set
+# CONFIG_BLK_DEV_RBD is not set
+# CONFIG_BLK_DEV_RSXX is not set
+
+#
+# Misc devices
+#
+# CONFIG_SENSORS_LIS3LV02D is not set
+# CONFIG_DUMMY_IRQ is not set
+# CONFIG_PHANTOM is not set
+# CONFIG_SGI_IOC4 is not set
+# CONFIG_TIFM_CORE is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_SRAM is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_93CX6=y
+# CONFIG_CB710_CORE is not set
+
+#
+# Texas Instruments shared transport line discipline
+#
+# CONFIG_TI_ST is not set
+
+#
+# Altera FPGA firmware download module
+#
+
+#
+# Intel MIC Bus Driver
+#
+
+#
+# Intel MIC Host Driver
+#
+
+#
+# Intel MIC Card Driver
+#
+# CONFIG_GENWQE is not set
+# CONFIG_ECHO is not set
+# CONFIG_CXL_BASE is not set
+CONFIG_HAVE_IDE=y
+# CONFIG_IDE is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI_MOD=y
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=y
+CONFIG_SCSI_DMA=y
+CONFIG_SCSI_NETLINK=y
+# CONFIG_SCSI_MQ_DEFAULT is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=y
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+# CONFIG_SCSI_SCAN_ASYNC is not set
+
+#
+# SCSI Transports
+#
+CONFIG_SCSI_SPI_ATTRS=m
+CONFIG_SCSI_FC_ATTRS=m
+CONFIG_SCSI_ISCSI_ATTRS=m
+CONFIG_SCSI_SAS_ATTRS=m
+CONFIG_SCSI_SAS_LIBSAS=m
+CONFIG_SCSI_SAS_ATA=y
+CONFIG_SCSI_SAS_HOST_SMP=y
+CONFIG_SCSI_SRP_ATTRS=m
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_ISCSI_BOOT_SYSFS is not set
+# CONFIG_SCSI_CXGB3_ISCSI is not set
+# CONFIG_SCSI_CXGB4_ISCSI is not set
+# CONFIG_SCSI_BNX2_ISCSI is not set
+# CONFIG_BE2ISCSI is not set
+# CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+# CONFIG_SCSI_HPSA is not set
+# CONFIG_SCSI_3W_9XXX is not set
+# CONFIG_SCSI_3W_SAS is not set
+# CONFIG_SCSI_ACARD is not set
+# CONFIG_SCSI_AACRAID is not set
+# CONFIG_SCSI_AIC7XXX is not set
+# CONFIG_SCSI_AIC79XX is not set
+# CONFIG_SCSI_AIC94XX is not set
+# CONFIG_SCSI_MVSAS is not set
+# CONFIG_SCSI_MVUMI is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_SCSI_ADVANSYS is not set
+# CONFIG_SCSI_ARCMSR is not set
+# CONFIG_SCSI_ESAS2R is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
+# CONFIG_SCSI_MPT3SAS is not set
+# CONFIG_SCSI_UFSHCD is not set
+# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_SCSI_BUSLOGIC is not set
+# CONFIG_LIBFC is not set
+# CONFIG_SCSI_DMX3191D is not set
+# CONFIG_SCSI_EATA is not set
+# CONFIG_SCSI_FUTURE_DOMAIN is not set
+# CONFIG_SCSI_GDTH is not set
+# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
+# CONFIG_SCSI_INIA100 is not set
+# CONFIG_SCSI_STEX is not set
+# CONFIG_SCSI_SYM53C8XX_2 is not set
+# CONFIG_SCSI_IPR is not set
+# CONFIG_SCSI_QLOGIC_1280 is not set
+# CONFIG_SCSI_QLA_FC is not set
+# CONFIG_SCSI_QLA_ISCSI is not set
+# CONFIG_SCSI_LPFC is not set
+# CONFIG_SCSI_DC395x is not set
+# CONFIG_SCSI_AM53C974 is not set
+# CONFIG_SCSI_WD719X is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_PMCRAID is not set
+# CONFIG_SCSI_PM8001 is not set
+# CONFIG_SCSI_BFA_FC is not set
+CONFIG_SCSI_VIRTIO=m
+# CONFIG_SCSI_CHELSIO_FCOE is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+CONFIG_ATA=y
+# CONFIG_ATA_NONSTANDARD is not set
+CONFIG_ATA_VERBOSE_ERROR=y
+# CONFIG_SATA_PMP is not set
+
+#
+# Controllers with non-SFF native interface
+#
+CONFIG_SATA_AHCI=m
+CONFIG_SATA_AHCI_PLATFORM=m
+# CONFIG_SATA_INIC162X is not set
+CONFIG_SATA_ACARD_AHCI=m
+CONFIG_SATA_SIL24=m
+CONFIG_ATA_SFF=y
+
+#
+# SFF controllers with custom DMA interface
+#
+# CONFIG_PDC_ADMA is not set
+# CONFIG_SATA_QSTOR is not set
+# CONFIG_SATA_SX4 is not set
+CONFIG_ATA_BMDMA=y
+
+#
+# SATA SFF controllers with BMDMA
+#
+# CONFIG_ATA_PIIX is not set
+# CONFIG_SATA_MV is not set
+# CONFIG_SATA_NV is not set
+# CONFIG_SATA_PROMISE is not set
+# CONFIG_SATA_SIL is not set
+# CONFIG_SATA_SIS is not set
+# CONFIG_SATA_SVW is not set
+# CONFIG_SATA_ULI is not set
+# CONFIG_SATA_VIA is not set
+# CONFIG_SATA_VITESSE is not set
+
+#
+# PATA SFF controllers with BMDMA
+#
+# CONFIG_PATA_ALI is not set
+# CONFIG_PATA_AMD is not set
+# CONFIG_PATA_ARTOP is not set
+# CONFIG_PATA_ATIIXP is not set
+# CONFIG_PATA_ATP867X is not set
+# CONFIG_PATA_CMD64X is not set
+CONFIG_PATA_CS5536=y
+# CONFIG_PATA_CYPRESS is not set
+# CONFIG_PATA_EFAR is not set
+# CONFIG_PATA_HPT366 is not set
+# CONFIG_PATA_HPT37X is not set
+# CONFIG_PATA_HPT3X2N is not set
+# CONFIG_PATA_HPT3X3 is not set
+# CONFIG_PATA_IT8213 is not set
+# CONFIG_PATA_IT821X is not set
+# CONFIG_PATA_JMICRON is not set
+# CONFIG_PATA_MARVELL is not set
+# CONFIG_PATA_NETCELL is not set
+# CONFIG_PATA_NINJA32 is not set
+# CONFIG_PATA_NS87415 is not set
+# CONFIG_PATA_OLDPIIX is not set
+# CONFIG_PATA_OPTIDMA is not set
+# CONFIG_PATA_PDC2027X is not set
+# CONFIG_PATA_PDC_OLD is not set
+# CONFIG_PATA_RADISYS is not set
+# CONFIG_PATA_RDC is not set
+# CONFIG_PATA_SCH is not set
+# CONFIG_PATA_SERVERWORKS is not set
+# CONFIG_PATA_SIL680 is not set
+# CONFIG_PATA_SIS is not set
+# CONFIG_PATA_TOSHIBA is not set
+# CONFIG_PATA_TRIFLEX is not set
+# CONFIG_PATA_VIA is not set
+# CONFIG_PATA_WINBOND is not set
+
+#
+# PIO-only SFF controllers
+#
+# CONFIG_PATA_CMD640_PCI is not set
+# CONFIG_PATA_MPIIX is not set
+# CONFIG_PATA_NS87410 is not set
+# CONFIG_PATA_OPTI is not set
+# CONFIG_PATA_PLATFORM is not set
+# CONFIG_PATA_RZ1000 is not set
+
+#
+# Generic fallback / legacy drivers
+#
+# CONFIG_ATA_GENERIC is not set
+# CONFIG_PATA_LEGACY is not set
+CONFIG_MD=y
+CONFIG_BLK_DEV_MD=m
+CONFIG_MD_LINEAR=m
+CONFIG_MD_RAID0=m
+CONFIG_MD_RAID1=m
+CONFIG_MD_RAID10=m
+CONFIG_MD_RAID456=m
+# CONFIG_MD_MULTIPATH is not set
+# CONFIG_MD_FAULTY is not set
+CONFIG_BCACHE=m
+# CONFIG_BCACHE_DEBUG is not set
+# CONFIG_BCACHE_CLOSURES_DEBUG is not set
+CONFIG_BLK_DEV_DM_BUILTIN=y
+CONFIG_BLK_DEV_DM=m
+# CONFIG_DM_MQ_DEFAULT is not set
+# CONFIG_DM_DEBUG is not set
+CONFIG_DM_BUFIO=m
+CONFIG_DM_CRYPT=m
+CONFIG_DM_SNAPSHOT=m
+# CONFIG_DM_THIN_PROVISIONING is not set
+# CONFIG_DM_CACHE is not set
+# CONFIG_DM_ERA is not set
+CONFIG_DM_MIRROR=m
+# CONFIG_DM_LOG_USERSPACE is not set
+CONFIG_DM_RAID=m
+# CONFIG_DM_ZERO is not set
+# CONFIG_DM_MULTIPATH is not set
+# CONFIG_DM_DELAY is not set
+# CONFIG_DM_UEVENT is not set
+# CONFIG_DM_FLAKEY is not set
+# CONFIG_DM_VERITY is not set
+# CONFIG_DM_SWITCH is not set
+# CONFIG_DM_LOG_WRITES is not set
+# CONFIG_TARGET_CORE is not set
+# CONFIG_FUSION is not set
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_FIREWIRE is not set
+# CONFIG_FIREWIRE_NOSY is not set
+CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_NET_CORE=y
+# CONFIG_BONDING is not set
+CONFIG_DUMMY=m
+# CONFIG_EQUALIZER is not set
+# CONFIG_NET_FC is not set
+# CONFIG_NET_TEAM is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_IPVLAN is not set
+# CONFIG_VXLAN is not set
+CONFIG_NETCONSOLE=m
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+CONFIG_NET_POLL_CONTROLLER=y
+CONFIG_TUN=m
+CONFIG_VETH=m
+CONFIG_VIRTIO_NET=m
+# CONFIG_NLMON is not set
+# CONFIG_ARCNET is not set
+
+#
+# CAIF transport drivers
+#
+CONFIG_VHOST_NET=m
+CONFIG_VHOST_RING=m
+CONFIG_VHOST=m
+
+#
+# Distributed Switch Architecture drivers
+#
+# CONFIG_NET_DSA_MV88E6XXX is not set
+# CONFIG_NET_DSA_MV88E6XXX_NEED_PPU is not set
+CONFIG_ETHERNET=y
+# CONFIG_NET_VENDOR_3COM is not set
+# CONFIG_NET_VENDOR_ADAPTEC is not set
+# CONFIG_NET_VENDOR_AGERE is not set
+# CONFIG_NET_VENDOR_ALTEON is not set
+# CONFIG_ALTERA_TSE is not set
+# CONFIG_NET_VENDOR_AMD is not set
+# CONFIG_NET_VENDOR_ARC is not set
+# CONFIG_NET_VENDOR_ATHEROS is not set
+# CONFIG_NET_CADENCE is not set
+# CONFIG_NET_VENDOR_BROADCOM is not set
+# CONFIG_NET_VENDOR_BROCADE is not set
+# CONFIG_NET_VENDOR_CHELSIO is not set
+# CONFIG_NET_VENDOR_CISCO is not set
+# CONFIG_DM9000 is not set
+# CONFIG_DNET is not set
+# CONFIG_NET_VENDOR_DEC is not set
+# CONFIG_NET_VENDOR_DLINK is not set
+# CONFIG_NET_VENDOR_EMULEX is not set
+# CONFIG_NET_VENDOR_EXAR is not set
+# CONFIG_NET_VENDOR_HP is not set
+# CONFIG_NET_VENDOR_INTEL is not set
+# CONFIG_IP1000 is not set
+# CONFIG_JME is not set
+# CONFIG_NET_VENDOR_MARVELL is not set
+# CONFIG_NET_VENDOR_MELLANOX is not set
+# CONFIG_NET_VENDOR_MICREL is not set
+# CONFIG_NET_VENDOR_MYRI is not set
+# CONFIG_FEALNX is not set
+# CONFIG_NET_VENDOR_NATSEMI is not set
+# CONFIG_NET_VENDOR_NVIDIA is not set
+# CONFIG_NET_VENDOR_OKI is not set
+# CONFIG_ETHOC is not set
+# CONFIG_NET_PACKET_ENGINE is not set
+# CONFIG_NET_VENDOR_QLOGIC is not set
+# CONFIG_NET_VENDOR_QUALCOMM is not set
+CONFIG_NET_VENDOR_REALTEK=y
+# CONFIG_8139CP is not set
+CONFIG_8139TOO=y
+CONFIG_8139TOO_PIO=y
+# CONFIG_8139TOO_TUNE_TWISTER is not set
+# CONFIG_8139TOO_8129 is not set
+# CONFIG_8139_OLD_RX_RESET is not set
+# CONFIG_R8169 is not set
+# CONFIG_NET_VENDOR_RDC is not set
+# CONFIG_NET_VENDOR_ROCKER is not set
+# CONFIG_NET_VENDOR_SAMSUNG is not set
+# CONFIG_NET_VENDOR_SEEQ is not set
+# CONFIG_NET_VENDOR_SILAN is not set
+# CONFIG_NET_VENDOR_SIS is not set
+# CONFIG_SFC is not set
+# CONFIG_NET_VENDOR_SMSC is not set
+# CONFIG_NET_VENDOR_STMICRO is not set
+# CONFIG_NET_VENDOR_SUN is not set
+# CONFIG_NET_VENDOR_TEHUTI is not set
+# CONFIG_NET_VENDOR_TI is not set
+# CONFIG_NET_VENDOR_TOSHIBA is not set
+# CONFIG_NET_VENDOR_VIA is not set
+# CONFIG_NET_VENDOR_WIZNET is not set
+# CONFIG_FDDI is not set
+# CONFIG_HIPPI is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_AT803X_PHY is not set
+# CONFIG_AMD_PHY is not set
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_BCM7XXX_PHY is not set
+# CONFIG_BCM87XX_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+CONFIG_REALTEK_PHY=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_MDIO_BCM_UNIMAC is not set
+CONFIG_PPP=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_MPPE=m
+# CONFIG_PPP_MULTILINK is not set
+CONFIG_PPPOE=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_SLIP=m
+CONFIG_SLHC=m
+# CONFIG_SLIP_COMPRESSED is not set
+CONFIG_SLIP_SMART=y
+CONFIG_SLIP_MODE_SLIP6=y
+CONFIG_USB_NET_DRIVERS=m
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_RTL8152 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_USB_HSO is not set
+# CONFIG_USB_IPHETH is not set
+CONFIG_WLAN=y
+# CONFIG_LIBERTAS_THINFIRM is not set
+# CONFIG_AIRO is not set
+# CONFIG_ATMEL is not set
+# CONFIG_AT76C50X_USB is not set
+# CONFIG_PRISM54 is not set
+# CONFIG_USB_ZD1201 is not set
+# CONFIG_USB_NET_RNDIS_WLAN is not set
+# CONFIG_RTL8180 is not set
+CONFIG_RTL8187=m
+CONFIG_RTL8187_LEDS=y
+# CONFIG_ADM8211 is not set
+# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_MWL8K is not set
+CONFIG_ATH_COMMON=m
+CONFIG_ATH_CARDS=m
+# CONFIG_ATH_DEBUG is not set
+# CONFIG_ATH5K is not set
+# CONFIG_ATH5K_PCI is not set
+CONFIG_ATH9K_HW=m
+CONFIG_ATH9K_COMMON=m
+CONFIG_ATH9K_BTCOEX_SUPPORT=y
+# CONFIG_ATH9K is not set
+CONFIG_ATH9K_HTC=m
+# CONFIG_ATH9K_HTC_DEBUGFS is not set
+# CONFIG_CARL9170 is not set
+# CONFIG_ATH6KL is not set
+# CONFIG_AR5523 is not set
+# CONFIG_WIL6210 is not set
+# CONFIG_ATH10K is not set
+# CONFIG_WCN36XX is not set
+# CONFIG_B43 is not set
+# CONFIG_B43LEGACY is not set
+# CONFIG_BRCMSMAC is not set
+# CONFIG_BRCMFMAC is not set
+# CONFIG_HOSTAP is not set
+# CONFIG_IPW2100 is not set
+# CONFIG_IPW2200 is not set
+# CONFIG_IWLWIFI is not set
+# CONFIG_IWL4965 is not set
+# CONFIG_IWL3945 is not set
+# CONFIG_LIBERTAS is not set
+# CONFIG_HERMES is not set
+# CONFIG_P54_COMMON is not set
+# CONFIG_RT2X00 is not set
+# CONFIG_RTL_CARDS is not set
+# CONFIG_WL_TI is not set
+# CONFIG_ZD1211RW is not set
+# CONFIG_MWIFIEX is not set
+# CONFIG_CW1200 is not set
+# CONFIG_RSI_91X is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+# CONFIG_WAN is not set
+# CONFIG_VMXNET3 is not set
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+CONFIG_INPUT_FF_MEMLESS=y
+# CONFIG_INPUT_POLLDEV is not set
+CONFIG_INPUT_SPARSEKMAP=y
+# CONFIG_INPUT_MATRIXKMAP is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_GPIO is not set
+# CONFIG_KEYBOARD_GPIO_POLLED is not set
+# CONFIG_KEYBOARD_MATRIX is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_OPENCORES is not set
+# CONFIG_KEYBOARD_SAMSUNG is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=m
+CONFIG_MOUSE_PS2_ALPS=y
+CONFIG_MOUSE_PS2_LOGIPS2PP=y
+CONFIG_MOUSE_PS2_SYNAPTICS=y
+CONFIG_MOUSE_PS2_CYPRESS=y
+CONFIG_MOUSE_PS2_TRACKPOINT=y
+# CONFIG_MOUSE_PS2_ELANTECH is not set
+CONFIG_MOUSE_PS2_SENTELIC=y
+# CONFIG_MOUSE_PS2_TOUCHKIT is not set
+CONFIG_MOUSE_PS2_FOCALTECH=y
+# CONFIG_MOUSE_SERIAL is not set
+# CONFIG_MOUSE_APPLETOUCH is not set
+# CONFIG_MOUSE_BCM5974 is not set
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_MOUSE_GPIO is not set
+CONFIG_MOUSE_SYNAPTICS_USB=m
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+# CONFIG_INPUT_TOUCHSCREEN is not set
+CONFIG_INPUT_MISC=y
+# CONFIG_INPUT_AD714X is not set
+# CONFIG_INPUT_E3X0_BUTTON is not set
+# CONFIG_INPUT_GPIO_BEEPER is not set
+# CONFIG_INPUT_GPIO_TILT_POLLED is not set
+# CONFIG_INPUT_ATI_REMOTE2 is not set
+# CONFIG_INPUT_KEYSPAN_REMOTE is not set
+# CONFIG_INPUT_POWERMATE is not set
+# CONFIG_INPUT_YEALINK is not set
+# CONFIG_INPUT_CM109 is not set
+# CONFIG_INPUT_UINPUT is not set
+# CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set
+# CONFIG_INPUT_ADXL34X is not set
+# CONFIG_INPUT_IMS_PCU is not set
+# CONFIG_INPUT_CMA3000 is not set
+# CONFIG_INPUT_IDEAPAD_SLIDEBAR is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
+CONFIG_SERIO_I8042=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_SERIO_ALTERA_PS2 is not set
+# CONFIG_SERIO_PS2MULT is not set
+# CONFIG_SERIO_ARC_PS2 is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_TTY=y
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+CONFIG_VT_CONSOLE=y
+CONFIG_VT_CONSOLE_SLEEP=y
+CONFIG_HW_CONSOLE=y
+CONFIG_VT_HW_CONSOLE_BINDING=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_DEVPTS_MULTIPLE_INSTANCES=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_SERIAL_NONSTANDARD is not set
+# CONFIG_NOZOMI is not set
+# CONFIG_N_GSM is not set
+# CONFIG_TRACE_SINK is not set
+CONFIG_DEVMEM=y
+# CONFIG_DEVKMEM is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=m
+CONFIG_SERIAL_8250_DEPRECATED_OPTIONS=y
+CONFIG_SERIAL_8250_PCI=m
+CONFIG_SERIAL_8250_NR_UARTS=16
+CONFIG_SERIAL_8250_RUNTIME_UARTS=4
+# CONFIG_SERIAL_8250_EXTENDED is not set
+# CONFIG_SERIAL_8250_DW is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=m
+# CONFIG_SERIAL_JSM is not set
+# CONFIG_SERIAL_SCCNXP is not set
+# CONFIG_SERIAL_BCM63XX is not set
+# CONFIG_SERIAL_ALTERA_JTAGUART is not set
+# CONFIG_SERIAL_ALTERA_UART is not set
+# CONFIG_SERIAL_ARC is not set
+# CONFIG_SERIAL_RP2 is not set
+# CONFIG_SERIAL_FSL_LPUART is not set
+# CONFIG_TTY_PRINTK is not set
+CONFIG_HVC_DRIVER=y
+CONFIG_VIRTIO_CONSOLE=m
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_TIMERIOMEM=m
+CONFIG_HW_RANDOM_VIRTIO=m
+# CONFIG_R3964 is not set
+# CONFIG_APPLICOM is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_DEVPORT=y
+# CONFIG_XILLYBUS is not set
+
+#
+# I2C support
+#
+# CONFIG_I2C is not set
+# CONFIG_SPI is not set
+# CONFIG_SPMI is not set
+# CONFIG_HSI is not set
+
+#
+# PPS support
+#
+# CONFIG_PPS is not set
+
+#
+# PPS generators support
+#
+
+#
+# PTP clock support
+#
+# CONFIG_PTP_1588_CLOCK is not set
+
+#
+# Enable PHYLIB and NETWORK_PHY_TIMESTAMPING to see the additional clocks.
+#
+CONFIG_ARCH_HAVE_CUSTOM_GPIO_H=y
+CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_DEVRES=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO drivers
+#
+# CONFIG_GPIO_DWAPB is not set
+# CONFIG_GPIO_GENERIC_PLATFORM is not set
+CONFIG_GPIO_LOONGSON=y
+# CONFIG_GPIO_SCH311X is not set
+# CONFIG_GPIO_VX855 is not set
+
+#
+# MFD GPIO expanders
+#
+
+#
+# PCI GPIO expanders
+#
+# CONFIG_GPIO_AMD8111 is not set
+# CONFIG_GPIO_BT8XX is not set
+# CONFIG_GPIO_ML_IOH is not set
+# CONFIG_GPIO_RDC321X is not set
+
+#
+# USB GPIO expanders
+#
+# CONFIG_W1 is not set
+CONFIG_POWER_SUPPLY=y
+# CONFIG_POWER_SUPPLY_DEBUG is not set
+# CONFIG_PDA_POWER is not set
+# CONFIG_TEST_POWER is not set
+# CONFIG_BATTERY_DS2780 is not set
+# CONFIG_BATTERY_DS2781 is not set
+# CONFIG_BATTERY_BQ27x00 is not set
+# CONFIG_CHARGER_MAX8903 is not set
+# CONFIG_CHARGER_GPIO is not set
+# CONFIG_POWER_RESET is not set
+# CONFIG_POWER_AVS is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+
+#
+# Native drivers
+#
+# CONFIG_SENSORS_I5K_AMB is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_GPIO_FAN is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_MAX197 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_NTC_THERMISTOR is not set
+# CONFIG_SENSORS_NCT6683 is not set
+# CONFIG_SENSORS_NCT6775 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_SIS5595 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_SCH56XX_COMMON is not set
+# CONFIG_SENSORS_VIA686A is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_VT8231 is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_HWMON=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+# CONFIG_THERMAL_DEFAULT_GOV_FAIR_SHARE is not set
+# CONFIG_THERMAL_DEFAULT_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_GOV_FAIR_SHARE is not set
+CONFIG_THERMAL_GOV_STEP_WISE=y
+# CONFIG_THERMAL_GOV_BANG_BANG is not set
+# CONFIG_THERMAL_GOV_USER_SPACE is not set
+# CONFIG_THERMAL_EMULATION is not set
+
+#
+# Texas Instruments thermal drivers
+#
+# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+CONFIG_BCMA_POSSIBLE=y
+
+#
+# Broadcom specific AMBA
+#
+# CONFIG_BCMA is not set
+
+#
+# Multifunction device drivers
+#
+CONFIG_MFD_CORE=m
+# CONFIG_MFD_CROS_EC is not set
+# CONFIG_MFD_DLN2 is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_LPC_ICH is not set
+# CONFIG_LPC_SCH is not set
+# CONFIG_MFD_JANZ_CMODIO is not set
+# CONFIG_MFD_KEMPLD is not set
+# CONFIG_MFD_MT6397 is not set
+# CONFIG_MFD_VIPERBOARD is not set
+# CONFIG_UCB1400_CORE is not set
+# CONFIG_MFD_RDC321X is not set
+# CONFIG_MFD_RTSX_PCI is not set
+CONFIG_MFD_RTSX_USB=m
+# CONFIG_MFD_SM501 is not set
+# CONFIG_ABX500_CORE is not set
+# CONFIG_MFD_SYSCON is not set
+# CONFIG_MFD_TI_AM335X_TSCADC is not set
+# CONFIG_MFD_TPS65912 is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_VX855 is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_MEDIA_SUPPORT is not set
+
+#
+# Graphics support
+#
+CONFIG_VGA_ARB=y
+CONFIG_VGA_ARB_MAX_GPUS=16
+
+#
+# Direct Rendering Manager
+#
+# CONFIG_DRM is not set
+
+#
+# Frame buffer Devices
+#
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+CONFIG_FB_CMDLINE=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+CONFIG_FB_CFB_FILLRECT=y
+CONFIG_FB_CFB_COPYAREA=y
+CONFIG_FB_CFB_IMAGEBLIT=y
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+CONFIG_FB_MODE_HELPERS=y
+CONFIG_FB_TILEBLITTING=y
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_CIRRUS is not set
+# CONFIG_FB_PM2 is not set
+# CONFIG_FB_CYBER2000 is not set
+# CONFIG_FB_ASILIANT is not set
+# CONFIG_FB_IMSTT is not set
+# CONFIG_FB_UVESA is not set
+# CONFIG_FB_OPENCORES is not set
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_NVIDIA is not set
+# CONFIG_FB_RIVA is not set
+# CONFIG_FB_I740 is not set
+# CONFIG_FB_MATROX is not set
+# CONFIG_FB_RADEON is not set
+# CONFIG_FB_ATY128 is not set
+# CONFIG_FB_ATY is not set
+# CONFIG_FB_S3 is not set
+# CONFIG_FB_SAVAGE is not set
+# CONFIG_FB_SIS is not set
+# CONFIG_FB_NEOMAGIC is not set
+# CONFIG_FB_KYRO is not set
+# CONFIG_FB_3DFX is not set
+# CONFIG_FB_VOODOO1 is not set
+# CONFIG_FB_VT8623 is not set
+# CONFIG_FB_TRIDENT is not set
+# CONFIG_FB_ARK is not set
+# CONFIG_FB_PM3 is not set
+# CONFIG_FB_CARMINE is not set
+# CONFIG_FB_SMSCUFX 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_FB_AUO_K190X is not set
+# CONFIG_FB_SIMPLE is not set
+CONFIG_BACKLIGHT_LCD_SUPPORT=y
+CONFIG_LCD_CLASS_DEVICE=y
+CONFIG_LCD_PLATFORM=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
+# CONFIG_BACKLIGHT_GENERIC is not set
+# CONFIG_BACKLIGHT_GPIO is not set
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=y
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_DUMMY_CONSOLE_COLUMNS=80
+CONFIG_DUMMY_CONSOLE_ROWS=25
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+# CONFIG_LOGO_LINUX_CLUT224 is not set
+CONFIG_LOGO_LIBRE_CLUT224=y
+CONFIG_SOUND=y
+CONFIG_SOUND_OSS_CORE=y
+CONFIG_SOUND_OSS_CORE_PRECLAIM=y
+CONFIG_SND=y
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_HWDEP=m
+CONFIG_SND_RAWMIDI=m
+CONFIG_SND_SEQUENCER=m
+CONFIG_SND_SEQ_DUMMY=m
+CONFIG_SND_OSSEMUL=y
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+CONFIG_SND_PCM_OSS_PLUGINS=y
+CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_HRTIMER=m
+CONFIG_SND_SEQ_HRTIMER_DEFAULT=y
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_VMASTER=y
+CONFIG_SND_RAWMIDI_SEQ=m
+# CONFIG_SND_OPL3_LIB_SEQ is not set
+# CONFIG_SND_OPL4_LIB_SEQ is not set
+# CONFIG_SND_SBAWE_SEQ is not set
+# CONFIG_SND_EMU10K1_SEQ is not set
+CONFIG_SND_MPU401_UART=m
+CONFIG_SND_AC97_CODEC=m
+CONFIG_SND_DRIVERS=y
+CONFIG_SND_DUMMY=m
+# CONFIG_SND_ALOOP is not set
+CONFIG_SND_VIRMIDI=m
+# CONFIG_SND_MTPAV is not set
+CONFIG_SND_SERIAL_U16550=m
+CONFIG_SND_MPU401=m
+CONFIG_SND_AC97_POWER_SAVE=y
+CONFIG_SND_AC97_POWER_SAVE_DEFAULT=10
+CONFIG_SND_PCI=y
+# CONFIG_SND_AD1889 is not set
+# CONFIG_SND_ALS300 is not set
+# CONFIG_SND_ALS4000 is not set
+# CONFIG_SND_ALI5451 is not set
+# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
+# CONFIG_SND_AU8810 is not set
+# CONFIG_SND_AU8820 is not set
+# CONFIG_SND_AU8830 is not set
+# CONFIG_SND_AW2 is not set
+# CONFIG_SND_AZT3328 is not set
+# CONFIG_SND_BT87X is not set
+# CONFIG_SND_CA0106 is not set
+# CONFIG_SND_CMIPCI is not set
+# CONFIG_SND_OXYGEN is not set
+# CONFIG_SND_CS4281 is not set
+# CONFIG_SND_CS46XX is not set
+CONFIG_SND_CS5535AUDIO=m
+# CONFIG_SND_CTXFI is not set
+# CONFIG_SND_DARLA20 is not set
+# CONFIG_SND_GINA20 is not set
+# CONFIG_SND_LAYLA20 is not set
+# CONFIG_SND_DARLA24 is not set
+# CONFIG_SND_GINA24 is not set
+# CONFIG_SND_LAYLA24 is not set
+# CONFIG_SND_MONA is not set
+# CONFIG_SND_MIA is not set
+# CONFIG_SND_ECHO3G is not set
+# CONFIG_SND_INDIGO is not set
+# CONFIG_SND_INDIGOIO is not set
+# CONFIG_SND_INDIGODJ is not set
+# CONFIG_SND_INDIGOIOX is not set
+# CONFIG_SND_INDIGODJX is not set
+# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_ENS1370 is not set
+# CONFIG_SND_ENS1371 is not set
+# CONFIG_SND_ES1938 is not set
+# CONFIG_SND_ES1968 is not set
+# CONFIG_SND_FM801 is not set
+# CONFIG_SND_HDSP is not set
+# CONFIG_SND_HDSPM is not set
+# CONFIG_SND_ICE1712 is not set
+# CONFIG_SND_ICE1724 is not set
+# CONFIG_SND_INTEL8X0 is not set
+# CONFIG_SND_INTEL8X0M is not set
+# CONFIG_SND_KORG1212 is not set
+# CONFIG_SND_LOLA is not set
+# CONFIG_SND_LX6464ES is not set
+# CONFIG_SND_MAESTRO3 is not set
+# CONFIG_SND_MIXART is not set
+# CONFIG_SND_NM256 is not set
+# CONFIG_SND_PCXHR is not set
+# CONFIG_SND_RIPTIDE is not set
+# CONFIG_SND_RME32 is not set
+# CONFIG_SND_RME96 is not set
+# CONFIG_SND_RME9652 is not set
+# CONFIG_SND_SE6X is not set
+# CONFIG_SND_SONICVIBES is not set
+# CONFIG_SND_TRIDENT is not set
+# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
+# CONFIG_SND_VIRTUOSO is not set
+# CONFIG_SND_VX222 is not set
+# CONFIG_SND_YMFPCI is not set
+
+#
+# HD-Audio
+#
+# CONFIG_SND_HDA_INTEL is not set
+# CONFIG_SND_MIPS is not set
+CONFIG_SND_USB=y
+CONFIG_SND_USB_AUDIO=m
+CONFIG_SND_USB_UA101=m
+CONFIG_SND_USB_CAIAQ=m
+CONFIG_SND_USB_CAIAQ_INPUT=y
+CONFIG_SND_USB_6FIRE=m
+CONFIG_SND_USB_HIFACE=m
+CONFIG_SND_BCD2000=m
+CONFIG_SND_USB_LINE6=m
+CONFIG_SND_USB_POD=m
+CONFIG_SND_USB_PODHD=m
+CONFIG_SND_USB_TONEPORT=m
+CONFIG_SND_USB_VARIAX=m
+# CONFIG_SND_SOC is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_AC97_BUS=m
+
+#
+# HID support
+#
+CONFIG_HID=y
+CONFIG_HID_BATTERY_STRENGTH=y
+CONFIG_HIDRAW=y
+# CONFIG_UHID is not set
+CONFIG_HID_GENERIC=m
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=m
+# CONFIG_HID_ACRUX is not set
+CONFIG_HID_APPLE=m
+# CONFIG_HID_APPLEIR is not set
+# CONFIG_HID_AUREAL is not set
+CONFIG_HID_BELKIN=m
+# CONFIG_HID_BETOP_FF is not set
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+# CONFIG_HID_PRODIKEYS is not set
+CONFIG_HID_CYPRESS=m
+# CONFIG_HID_DRAGONRISE is not set
+# CONFIG_HID_EMS_FF is not set
+# CONFIG_HID_ELECOM is not set
+# CONFIG_HID_ELO is not set
+CONFIG_HID_EZKEY=m
+# CONFIG_HID_HOLTEK is not set
+# CONFIG_HID_GT683R 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_ICADE is not set
+# CONFIG_HID_TWINHAN is not set
+CONFIG_HID_KENSINGTON=m
+# CONFIG_HID_LCPOWER is not set
+# CONFIG_HID_LENOVO is not set
+CONFIG_HID_LOGITECH=m
+# CONFIG_HID_LOGITECH_DJ is not set
+# CONFIG_HID_LOGITECH_HIDPP is not set
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+# CONFIG_LOGIG940_FF is not set
+# CONFIG_LOGIWHEELS_FF is not set
+CONFIG_HID_MAGICMOUSE=m
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+# 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_PENMOUNT is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_PICOLCD is not set
+CONFIG_HID_PLANTRONICS=m
+# CONFIG_HID_PRIMAX is not set
+# CONFIG_HID_ROCCAT is not set
+# CONFIG_HID_SAITEK is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SPEEDLINK is not set
+# CONFIG_HID_STEELSERIES is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_HID_RMI is not set
+# CONFIG_HID_GREENASIA is not set
+# CONFIG_HID_SMARTJOYPLUS is not set
+# CONFIG_HID_TIVO is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_HID_THINGM is not set
+# CONFIG_HID_THRUSTMASTER is not set
+# CONFIG_HID_WACOM is not set
+# CONFIG_HID_WIIMOTE is not set
+# CONFIG_HID_XINMO is not set
+# CONFIG_HID_ZEROPLUS is not set
+# CONFIG_HID_ZYDACRON is not set
+# CONFIG_HID_SENSOR_HUB is not set
+
+#
+# USB HID support
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+CONFIG_USB_HIDDEV=y
+
+#
+# USB HID Boot Protocol drivers
+#
+CONFIG_USB_KBD=m
+# CONFIG_USB_MOUSE is not set
+CONFIG_USB_OHCI_LITTLE_ENDIAN=y
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_COMMON=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEFAULT_PERSIST=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_OTG_FSM is not set
+CONFIG_USB_MON=m
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_XHCI_HCD is not set
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_TT_NEWSCHED=y
+CONFIG_USB_EHCI_PCI=y
+# CONFIG_USB_EHCI_HCD_PLATFORM is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1362_HCD is not set
+# CONFIG_USB_FUSBH200_HCD is not set
+# CONFIG_USB_FOTG210_HCD is not set
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PCI=y
+# CONFIG_USB_OHCI_HCD_PLATFORM is not set
+# CONFIG_USB_UHCI_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HCD_TEST_MODE is not set
+
+#
+# USB Device Class drivers
+#
+CONFIG_USB_ACM=m
+CONFIG_USB_PRINTER=m
+CONFIG_USB_WDM=m
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+CONFIG_USB_STORAGE_REALTEK=m
+CONFIG_REALTEK_AUTOPM=y
+CONFIG_USB_STORAGE_DATAFAB=m
+CONFIG_USB_STORAGE_FREECOM=m
+CONFIG_USB_STORAGE_ISD200=m
+CONFIG_USB_STORAGE_USBAT=m
+CONFIG_USB_STORAGE_SDDR09=m
+CONFIG_USB_STORAGE_SDDR55=m
+CONFIG_USB_STORAGE_JUMPSHOT=m
+CONFIG_USB_STORAGE_ALAUDA=m
+CONFIG_USB_STORAGE_ONETOUCH=m
+CONFIG_USB_STORAGE_KARMA=m
+CONFIG_USB_STORAGE_CYPRESS_ATACB=m
+CONFIG_USB_STORAGE_ENE_UB6250=m
+CONFIG_USB_UAS=m
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+# CONFIG_USBIP_CORE is not set
+# CONFIG_USB_MUSB_HDRC is not set
+# CONFIG_USB_DWC3 is not set
+# CONFIG_USB_DWC2 is not set
+# CONFIG_USB_CHIPIDEA is not set
+# CONFIG_USB_ISP1760 is not set
+
+#
+# USB port drivers
+#
+CONFIG_USB_SERIAL=m
+CONFIG_USB_SERIAL_GENERIC=y
+CONFIG_USB_SERIAL_SIMPLE=m
+CONFIG_USB_SERIAL_AIRCABLE=m
+CONFIG_USB_SERIAL_ARK3116=m
+CONFIG_USB_SERIAL_BELKIN=m
+CONFIG_USB_SERIAL_CH341=m
+CONFIG_USB_SERIAL_WHITEHEAT=m
+CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m
+CONFIG_USB_SERIAL_CP210X=m
+CONFIG_USB_SERIAL_CYPRESS_M8=m
+CONFIG_USB_SERIAL_EMPEG=m
+CONFIG_USB_SERIAL_FTDI_SIO=m
+CONFIG_USB_SERIAL_VISOR=m
+CONFIG_USB_SERIAL_IPAQ=m
+CONFIG_USB_SERIAL_IR=m
+CONFIG_USB_SERIAL_EDGEPORT=m
+CONFIG_USB_SERIAL_EDGEPORT_TI=m
+CONFIG_USB_SERIAL_F81232=m
+CONFIG_USB_SERIAL_GARMIN=m
+CONFIG_USB_SERIAL_IPW=m
+CONFIG_USB_SERIAL_IUU=m
+CONFIG_USB_SERIAL_KEYSPAN_PDA=m
+CONFIG_USB_SERIAL_KEYSPAN=m
+CONFIG_USB_SERIAL_KEYSPAN_MPR=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y
+CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19=y
+CONFIG_USB_SERIAL_KEYSPAN_USA18X=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y
+CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49W=y
+CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y
+CONFIG_USB_SERIAL_KLSI=m
+CONFIG_USB_SERIAL_KOBIL_SCT=m
+CONFIG_USB_SERIAL_MCT_U232=m
+# CONFIG_USB_SERIAL_METRO is not set
+CONFIG_USB_SERIAL_MOS7720=m
+CONFIG_USB_SERIAL_MOS7840=m
+# CONFIG_USB_SERIAL_MXUPORT is not set
+CONFIG_USB_SERIAL_NAVMAN=m
+CONFIG_USB_SERIAL_PL2303=m
+CONFIG_USB_SERIAL_OTI6858=m
+CONFIG_USB_SERIAL_QCAUX=m
+CONFIG_USB_SERIAL_QUALCOMM=m
+CONFIG_USB_SERIAL_SPCP8X5=m
+CONFIG_USB_SERIAL_SAFE=m
+CONFIG_USB_SERIAL_SAFE_PADDED=y
+CONFIG_USB_SERIAL_SIERRAWIRELESS=m
+CONFIG_USB_SERIAL_SYMBOL=m
+CONFIG_USB_SERIAL_TI=m
+CONFIG_USB_SERIAL_CYBERJACK=m
+CONFIG_USB_SERIAL_XIRCOM=m
+CONFIG_USB_SERIAL_WWAN=m
+CONFIG_USB_SERIAL_OPTION=m
+CONFIG_USB_SERIAL_OMNINET=m
+CONFIG_USB_SERIAL_OPTICON=m
+# CONFIG_USB_SERIAL_XSENS_MT is not set
+# CONFIG_USB_SERIAL_WISHBONE is not set
+CONFIG_USB_SERIAL_SSU100=m
+# CONFIG_USB_SERIAL_QT2 is not set
+# CONFIG_USB_SERIAL_DEBUG is not set
+
+#
+# USB Miscellaneous drivers
+#
+CONFIG_USB_EMI62=m
+CONFIG_USB_EMI26=m
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_SISUSBVGA is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+# CONFIG_USB_TEST is not set
+# CONFIG_USB_EHSET_TEST_FIXTURE is not set
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_YUREX is not set
+CONFIG_USB_EZUSB_FX2=m
+# CONFIG_USB_LINK_LAYER_TEST is not set
+# CONFIG_USB_CHAOSKEY is not set
+
+#
+# USB Physical Layer drivers
+#
+# CONFIG_USB_PHY is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_USB_GADGET is not set
+# CONFIG_USB_LED_TRIG is not set
+# CONFIG_UWB is not set
+# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+# CONFIG_LEDS_CLASS_FLASH is not set
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_GPIO is not set
+# CONFIG_LEDS_LT3593 is not set
+
+#
+# LED driver for blink(1) USB RGB LED is under Special HID drivers (HID_THINGM)
+#
+# CONFIG_LEDS_PM8941_WLED is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+# CONFIG_LEDS_TRIGGER_TIMER is not set
+# CONFIG_LEDS_TRIGGER_ONESHOT is not set
+# CONFIG_LEDS_TRIGGER_HEARTBEAT is not set
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_CPU is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+# CONFIG_LEDS_TRIGGER_TRANSIENT is not set
+# CONFIG_LEDS_TRIGGER_CAMERA is not set
+# CONFIG_ACCESSIBILITY is not set
+# CONFIG_INFINIBAND is not set
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_HCTOSYS=y
+CONFIG_RTC_SYSTOHC=y
+CONFIG_RTC_HCTOSYS_DEVICE="rtc0"
+# CONFIG_RTC_DEBUG is not set
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+CONFIG_RTC_DRV_CMOS=y
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1685_FAMILY is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_DS2404 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_MSM6242 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_RP5C01 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_RTC_DRV_XGENE is not set
+
+#
+# HID Sensor RTC drivers
+#
+# CONFIG_RTC_DRV_HID_SENSOR_TIME is not set
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_UIO is not set
+# CONFIG_VIRT_DRIVERS is not set
+CONFIG_VIRTIO=m
+
+#
+# Virtio drivers
+#
+CONFIG_VIRTIO_PCI=m
+CONFIG_VIRTIO_PCI_LEGACY=y
+CONFIG_VIRTIO_BALLOON=m
+CONFIG_VIRTIO_INPUT=m
+CONFIG_VIRTIO_MMIO=m
+# CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES is not set
+
+#
+# Microsoft Hyper-V guest support
+#
+CONFIG_STAGING=y
+CONFIG_PRISM2_USB=m
+# CONFIG_COMEDI is not set
+# CONFIG_RTL8192U is not set
+# CONFIG_RTLLIB is not set
+# CONFIG_R8712U is not set
+# CONFIG_R8188EU is not set
+# CONFIG_R8723AU is not set
+# CONFIG_RTS5208 is not set
+# CONFIG_VT6655 is not set
+# CONFIG_VT6656 is not set
+CONFIG_FB_SM7XX=y
+# CONFIG_FB_SM750 is not set
+# CONFIG_FB_XGI is not set
+# CONFIG_FT1000 is not set
+
+#
+# Speakup console speech
+#
+# CONFIG_SPEAKUP is not set
+# CONFIG_STAGING_MEDIA is not set
+
+#
+# Android
+#
+# CONFIG_USB_WPAN_HCD is not set
+# CONFIG_WIMAX_GDM72XX is not set
+# CONFIG_LTE_GDM724X is not set
+# CONFIG_DGNC is not set
+# CONFIG_DGAP is not set
+# CONFIG_GS_FPGABOOT is not set
+# CONFIG_I2O is not set
+CONFIG_MIPS_PLATFORM_DEVICES=y
+CONFIG_LEMOTE_YEELOONG2F=y
+# CONFIG_LEMOTE_LYNLOONG2F is not set
+
+#
+# Hardware Spinlock drivers
+#
+
+#
+# Clock Source drivers
+#
+# CONFIG_ATMEL_PIT is not set
+# CONFIG_SH_TIMER_CMT is not set
+# CONFIG_SH_TIMER_MTU2 is not set
+# CONFIG_SH_TIMER_TMU is not set
+# CONFIG_EM_TIMER_STI is not set
+# CONFIG_MAILBOX is not set
+CONFIG_IOMMU_SUPPORT=y
+
+#
+# Generic IOMMU Pagetable Support
+#
+
+#
+# Remoteproc drivers
+#
+# CONFIG_STE_MODEM_RPROC is not set
+
+#
+# Rpmsg drivers
+#
+
+#
+# SOC (System On Chip) specific Drivers
+#
+# CONFIG_SOC_TI is not set
+# CONFIG_PM_DEVFREQ is not set
+# CONFIG_EXTCON is not set
+# CONFIG_MEMORY is not set
+# CONFIG_IIO is not set
+# CONFIG_VME_BUS is not set
+# CONFIG_PWM is not set
+# CONFIG_IPACK_BUS is not set
+# CONFIG_RESET_CONTROLLER is not set
+# CONFIG_FMC is not set
+
+#
+# PHY Subsystem
+#
+CONFIG_GENERIC_PHY=y
+# CONFIG_BCM_KONA_USB2_PHY is not set
+CONFIG_POWERCAP=y
+# CONFIG_MCB is not set
+# CONFIG_THUNDERBOLT is not set
+
+#
+# Android
+#
+# CONFIG_ANDROID is not set
+
+#
+# Firmware Drivers
+#
+# CONFIG_FIRMWARE_MEMMAP is not set
+
+#
+# File systems
+#
+# CONFIG_EXT2_FS is not set
+# CONFIG_EXT3_FS is not set
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_USE_FOR_EXT23=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+# CONFIG_EXT4_FS_SECURITY is not set
+CONFIG_EXT4_ENCRYPTION=m
+CONFIG_EXT4_FS_ENCRYPTION=y
+# CONFIG_EXT4_DEBUG is not set
+CONFIG_JBD2=y
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_GFS2_FS is not set
+# CONFIG_OCFS2_FS is not set
+CONFIG_BTRFS_FS=m
+CONFIG_BTRFS_FS_POSIX_ACL=y
+# CONFIG_BTRFS_FS_CHECK_INTEGRITY is not set
+# CONFIG_BTRFS_FS_RUN_SANITY_TESTS is not set
+# CONFIG_BTRFS_DEBUG is not set
+# CONFIG_BTRFS_ASSERT is not set
+# CONFIG_NILFS2_FS is not set
+# CONFIG_F2FS_FS is not set
+CONFIG_FS_POSIX_ACL=y
+CONFIG_FILE_LOCKING=y
+CONFIG_FSNOTIFY=y
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY_USER=y
+CONFIG_FANOTIFY=y
+# CONFIG_QUOTA is not set
+# CONFIG_QUOTACTL is not set
+CONFIG_AUTOFS4_FS=m
+CONFIG_FUSE_FS=m
+# CONFIG_CUSE is not set
+CONFIG_OVERLAY_FS=m
+
+#
+# Caches
+#
+CONFIG_FSCACHE=m
+# CONFIG_FSCACHE_STATS is not set
+# CONFIG_FSCACHE_HISTOGRAM is not set
+# CONFIG_FSCACHE_DEBUG is not set
+# CONFIG_FSCACHE_OBJECT_LIST is not set
+CONFIG_CACHEFILES=m
+# CONFIG_CACHEFILES_DEBUG is not set
+# CONFIG_CACHEFILES_HISTOGRAM is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_UDF_FS=m
+CONFIG_UDF_NLS=y
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=m
+CONFIG_MSDOS_FS=m
+CONFIG_VFAT_FS=m
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_KCORE=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_KERNFS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_TMPFS_XATTR=y
+CONFIG_HUGETLBFS=y
+CONFIG_HUGETLB_PAGE=y
+CONFIG_CONFIGFS_FS=m
+# CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=m
+CONFIG_NFS_V2=m
+CONFIG_NFS_V3=m
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=m
+CONFIG_NFS_SWAP=y
+CONFIG_NFS_V4_1=y
+CONFIG_NFS_V4_2=y
+CONFIG_PNFS_FILE_LAYOUT=m
+CONFIG_PNFS_BLOCK=m
+CONFIG_PNFS_FLEXFILE_LAYOUT=m
+CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN="kernel.org"
+CONFIG_NFS_V4_1_MIGRATION=y
+CONFIG_NFS_FSCACHE=y
+# CONFIG_NFS_USE_LEGACY_DNS is not set
+CONFIG_NFS_USE_KERNEL_DNS=y
+# CONFIG_NFSD is not set
+CONFIG_GRACE_PERIOD=m
+CONFIG_LOCKD=m
+CONFIG_LOCKD_V4=y
+CONFIG_NFS_ACL_SUPPORT=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=m
+CONFIG_SUNRPC_GSS=m
+CONFIG_SUNRPC_BACKCHANNEL=y
+CONFIG_SUNRPC_SWAP=y
+CONFIG_RPCSEC_GSS_KRB5=m
+# CONFIG_SUNRPC_DEBUG is not set
+# CONFIG_CEPH_FS is not set
+CONFIG_CIFS=m
+# CONFIG_CIFS_STATS is not set
+# CONFIG_CIFS_WEAK_PW_HASH is not set
+# CONFIG_CIFS_UPCALL is not set
+CONFIG_CIFS_XATTR=y
+CONFIG_CIFS_POSIX=y
+CONFIG_CIFS_ACL=y
+CONFIG_CIFS_DEBUG=y
+# CONFIG_CIFS_DEBUG2 is not set
+# CONFIG_CIFS_DFS_UPCALL is not set
+# CONFIG_CIFS_SMB2 is not set
+# CONFIG_CIFS_FSCACHE is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+CONFIG_9P_FS=m
+CONFIG_9P_FSCACHE=y
+CONFIG_9P_FS_POSIX_ACL=y
+CONFIG_9P_FS_SECURITY=y
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="utf8"
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_737=m
+CONFIG_NLS_CODEPAGE_775=m
+CONFIG_NLS_CODEPAGE_850=m
+CONFIG_NLS_CODEPAGE_852=m
+CONFIG_NLS_CODEPAGE_855=m
+CONFIG_NLS_CODEPAGE_857=m
+CONFIG_NLS_CODEPAGE_860=m
+CONFIG_NLS_CODEPAGE_861=m
+CONFIG_NLS_CODEPAGE_862=m
+CONFIG_NLS_CODEPAGE_863=m
+CONFIG_NLS_CODEPAGE_864=m
+CONFIG_NLS_CODEPAGE_865=m
+CONFIG_NLS_CODEPAGE_866=m
+CONFIG_NLS_CODEPAGE_869=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_CODEPAGE_950=m
+CONFIG_NLS_CODEPAGE_932=m
+CONFIG_NLS_CODEPAGE_949=m
+CONFIG_NLS_CODEPAGE_874=m
+CONFIG_NLS_ISO8859_8=m
+CONFIG_NLS_CODEPAGE_1250=m
+CONFIG_NLS_CODEPAGE_1251=m
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_ISO8859_2=m
+CONFIG_NLS_ISO8859_3=m
+CONFIG_NLS_ISO8859_4=m
+CONFIG_NLS_ISO8859_5=m
+CONFIG_NLS_ISO8859_6=m
+CONFIG_NLS_ISO8859_7=m
+CONFIG_NLS_ISO8859_9=m
+CONFIG_NLS_ISO8859_13=m
+CONFIG_NLS_ISO8859_14=m
+CONFIG_NLS_ISO8859_15=m
+CONFIG_NLS_KOI8_R=m
+CONFIG_NLS_KOI8_U=m
+CONFIG_NLS_MAC_ROMAN=m
+CONFIG_NLS_MAC_CELTIC=m
+CONFIG_NLS_MAC_CENTEURO=m
+CONFIG_NLS_MAC_CROATIAN=m
+CONFIG_NLS_MAC_CYRILLIC=m
+CONFIG_NLS_MAC_GAELIC=m
+CONFIG_NLS_MAC_GREEK=m
+CONFIG_NLS_MAC_ICELAND=m
+CONFIG_NLS_MAC_INUIT=m
+CONFIG_NLS_MAC_ROMANIAN=m
+CONFIG_NLS_MAC_TURKISH=m
+CONFIG_NLS_UTF8=y
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+
+#
+# printk and dmesg options
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_MESSAGE_LOGLEVEL_DEFAULT=4
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+
+#
+# Compile-time checks and compiler options
+#
+# CONFIG_DEBUG_INFO is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+CONFIG_STRIP_ASM_SYMS=y
+# CONFIG_READABLE_ASM is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+# CONFIG_PAGE_OWNER is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+# CONFIG_DEBUG_SECTION_MISMATCH is not set
+# CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
+CONFIG_DEBUG_KERNEL=y
+
+#
+# Memory Debugging
+#
+# CONFIG_PAGE_EXTENSION is not set
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_HAVE_DEBUG_KMEMLEAK=y
+# CONFIG_DEBUG_KMEMLEAK is not set
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+CONFIG_HAVE_DEBUG_STACKOVERFLOW=y
+# CONFIG_DEBUG_STACKOVERFLOW is not set
+# CONFIG_DEBUG_SHIRQ is not set
+
+#
+# Debug Lockups and Hangs
+#
+CONFIG_LOCKUP_DETECTOR=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+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_PANIC_ON_OOPS is not set
+CONFIG_PANIC_ON_OOPS_VALUE=0
+CONFIG_PANIC_TIMEOUT=0
+# CONFIG_SCHED_DEBUG is not set
+# CONFIG_SCHEDSTATS is not set
+# CONFIG_SCHED_STACK_END_CHECK is not set
+# CONFIG_DEBUG_TIMEKEEPING is not set
+CONFIG_TIMER_STATS=y
+
+#
+# Lock Debugging (spinlocks, mutexes, etc...)
+#
+# CONFIG_DEBUG_RT_MUTEXES is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+# CONFIG_DEBUG_MUTEXES is not set
+# CONFIG_DEBUG_WW_MUTEX_SLOWPATH is not set
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_ATOMIC_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_LOCK_TORTURE_TEST is not set
+# CONFIG_STACKTRACE is not set
+# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_PI_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_DEBUG_CREDENTIALS is not set
+
+#
+# RCU Debugging
+#
+# CONFIG_PROVE_RCU is not set
+# CONFIG_SPARSE_RCU_POINTER is not set
+# CONFIG_TORTURE_TEST is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_TRACE is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_NOTIFIER_ERROR_INJECTION is not set
+# CONFIG_FAULT_INJECTION 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_SYSCALL_TRACEPOINTS=y
+CONFIG_HAVE_C_RECORDMCOUNT=y
+CONFIG_TRACING_SUPPORT=y
+# CONFIG_FTRACE is not set
+
+#
+# Runtime Testing
+#
+# CONFIG_LKDTM is not set
+# CONFIG_TEST_LIST_SORT is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_RBTREE_TEST is not set
+# CONFIG_INTERVAL_TREE_TEST is not set
+# CONFIG_PERCPU_TEST is not set
+# CONFIG_ATOMIC64_SELFTEST is not set
+# CONFIG_ASYNC_RAID6_TEST is not set
+# CONFIG_TEST_HEXDUMP is not set
+# CONFIG_TEST_STRING_HELPERS is not set
+# CONFIG_TEST_KSTRTOX is not set
+# CONFIG_TEST_RHASHTABLE is not set
+# CONFIG_DMA_API_DEBUG is not set
+# CONFIG_TEST_LKM is not set
+# CONFIG_TEST_USER_COPY is not set
+# CONFIG_TEST_BPF is not set
+# CONFIG_TEST_FIRMWARE is not set
+# CONFIG_TEST_UDELAY is not set
+# CONFIG_MEMTEST is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_EARLY_PRINTK=y
+# CONFIG_CMDLINE_BOOL is not set
+# CONFIG_RUNTIME_DEBUG is not set
+# CONFIG_DEBUG_ZBOOT is not set
+# CONFIG_SPINLOCK_TEST is not set
+
+#
+# Security options
+#
+CONFIG_KEYS=y
+# CONFIG_PERSISTENT_KEYRINGS is not set
+# CONFIG_BIG_KEYS is not set
+CONFIG_ENCRYPTED_KEYS=m
+# CONFIG_SECURITY_DMESG_RESTRICT is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+CONFIG_DEFAULT_SECURITY_DAC=y
+CONFIG_DEFAULT_SECURITY=""
+CONFIG_XOR_BLOCKS=m
+CONFIG_ASYNC_CORE=m
+CONFIG_ASYNC_MEMCPY=m
+CONFIG_ASYNC_XOR=m
+CONFIG_ASYNC_PQ=m
+CONFIG_ASYNC_RAID6_RECOV=m
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+CONFIG_CRYPTO_ALGAPI=y
+CONFIG_CRYPTO_ALGAPI2=y
+CONFIG_CRYPTO_AEAD=y
+CONFIG_CRYPTO_AEAD2=y
+CONFIG_CRYPTO_BLKCIPHER=y
+CONFIG_CRYPTO_BLKCIPHER2=y
+CONFIG_CRYPTO_HASH=y
+CONFIG_CRYPTO_HASH2=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=m
+CONFIG_CRYPTO_PCOMP2=y
+CONFIG_CRYPTO_MANAGER=y
+CONFIG_CRYPTO_MANAGER2=y
+# CONFIG_CRYPTO_USER is not set
+CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
+CONFIG_CRYPTO_GF128MUL=y
+CONFIG_CRYPTO_NULL=y
+CONFIG_CRYPTO_WORKQUEUE=y
+CONFIG_CRYPTO_CRYPTD=m
+# CONFIG_CRYPTO_MCRYPTD is not set
+CONFIG_CRYPTO_AUTHENC=m
+CONFIG_CRYPTO_TEST=m
+
+#
+# Authenticated Encryption with Associated Data
+#
+CONFIG_CRYPTO_CCM=y
+CONFIG_CRYPTO_GCM=y
+CONFIG_CRYPTO_SEQIV=y
+
+#
+# Block modes
+#
+CONFIG_CRYPTO_CBC=m
+CONFIG_CRYPTO_CTR=y
+CONFIG_CRYPTO_CTS=m
+CONFIG_CRYPTO_ECB=m
+CONFIG_CRYPTO_LRW=m
+CONFIG_CRYPTO_PCBC=m
+CONFIG_CRYPTO_XTS=m
+
+#
+# Hash modes
+#
+CONFIG_CRYPTO_CMAC=m
+CONFIG_CRYPTO_HMAC=m
+CONFIG_CRYPTO_XCBC=m
+# CONFIG_CRYPTO_VMAC is not set
+
+#
+# Digest
+#
+CONFIG_CRYPTO_CRC32C=y
+# CONFIG_CRYPTO_CRC32 is not set
+CONFIG_CRYPTO_CRCT10DIF=y
+CONFIG_CRYPTO_GHASH=y
+CONFIG_CRYPTO_MD4=m
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_MICHAEL_MIC=m
+CONFIG_CRYPTO_RMD128=m
+CONFIG_CRYPTO_RMD160=m
+CONFIG_CRYPTO_RMD256=m
+CONFIG_CRYPTO_RMD320=m
+CONFIG_CRYPTO_SHA1=m
+CONFIG_CRYPTO_SHA256=m
+CONFIG_CRYPTO_SHA512=m
+CONFIG_CRYPTO_TGR192=m
+CONFIG_CRYPTO_WP512=m
+
+#
+# Ciphers
+#
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_BLOWFISH=m
+CONFIG_CRYPTO_BLOWFISH_COMMON=m
+CONFIG_CRYPTO_CAMELLIA=m
+CONFIG_CRYPTO_CAST_COMMON=m
+CONFIG_CRYPTO_CAST5=m
+CONFIG_CRYPTO_CAST6=m
+CONFIG_CRYPTO_DES=m
+CONFIG_CRYPTO_FCRYPT=m
+CONFIG_CRYPTO_KHAZAD=m
+CONFIG_CRYPTO_SALSA20=m
+CONFIG_CRYPTO_SEED=m
+CONFIG_CRYPTO_SERPENT=m
+CONFIG_CRYPTO_TEA=m
+CONFIG_CRYPTO_TWOFISH=m
+CONFIG_CRYPTO_TWOFISH_COMMON=m
+
+#
+# Compression
+#
+CONFIG_CRYPTO_DEFLATE=m
+CONFIG_CRYPTO_ZLIB=m
+CONFIG_CRYPTO_LZO=m
+CONFIG_CRYPTO_LZ4=m
+CONFIG_CRYPTO_LZ4HC=m
+
+#
+# Random Number Generation
+#
+CONFIG_CRYPTO_ANSI_CPRNG=m
+# CONFIG_CRYPTO_DRBG_MENU is not set
+# CONFIG_CRYPTO_USER_API_HASH is not set
+# CONFIG_CRYPTO_USER_API_SKCIPHER is not set
+# CONFIG_CRYPTO_USER_API_RNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_ASYMMETRIC_KEY_TYPE is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_RAID6_PQ=m
+CONFIG_BITREVERSE=y
+# CONFIG_HAVE_ARCH_BITREVERSE is not set
+CONFIG_RATIONAL=y
+CONFIG_GENERIC_NET_UTILS=y
+CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_IO=y
+CONFIG_CRC_CCITT=m
+CONFIG_CRC16=y
+CONFIG_CRC_T10DIF=y
+CONFIG_CRC_ITU_T=m
+CONFIG_CRC32=y
+# CONFIG_CRC32_SELFTEST is not set
+CONFIG_CRC32_SLICEBY8=y
+# CONFIG_CRC32_SLICEBY4 is not set
+# CONFIG_CRC32_SARWATE is not set
+# CONFIG_CRC32_BIT is not set
+# CONFIG_CRC7 is not set
+CONFIG_LIBCRC32C=y
+# CONFIG_CRC8 is not set
+# CONFIG_AUDIT_ARCH_COMPAT_GENERIC is not set
+# CONFIG_RANDOM32_SELFTEST is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_LZ4_COMPRESS=m
+CONFIG_LZ4HC_COMPRESS=m
+CONFIG_LZ4_DECOMPRESS=y
+CONFIG_XZ_DEC=y
+CONFIG_XZ_DEC_X86=y
+CONFIG_XZ_DEC_POWERPC=y
+CONFIG_XZ_DEC_IA64=y
+CONFIG_XZ_DEC_ARM=y
+CONFIG_XZ_DEC_ARMTHUMB=y
+CONFIG_XZ_DEC_SPARC=y
+CONFIG_XZ_DEC_BCJ=y
+# CONFIG_XZ_DEC_TEST is not set
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_DECOMPRESS_BZIP2=y
+CONFIG_DECOMPRESS_LZMA=y
+CONFIG_DECOMPRESS_XZ=y
+CONFIG_DECOMPRESS_LZO=y
+CONFIG_DECOMPRESS_LZ4=y
+CONFIG_TEXTSEARCH=y
+CONFIG_TEXTSEARCH_KMP=m
+CONFIG_TEXTSEARCH_BM=m
+CONFIG_TEXTSEARCH_FSM=m
+CONFIG_ASSOCIATIVE_ARRAY=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HAS_DMA=y
+CONFIG_DQL=y
+CONFIG_GLOB=y
+# CONFIG_GLOB_SELFTEST is not set
+CONFIG_NLATTR=y
+CONFIG_ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE=y
+CONFIG_AVERAGE=y
+# CONFIG_CORDIC is not set
+# CONFIG_DDR is not set
+CONFIG_OID_REGISTRY=m
+CONFIG_FONT_SUPPORT=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+# CONFIG_FONT_8x16 is not set
+CONFIG_FONT_6x11=y
+CONFIG_FONT_7x14=y
+CONFIG_FONT_PEARL_8x8=y
+CONFIG_FONT_ACORN_8x8=y
+CONFIG_FONT_MINI_4x6=y
+# CONFIG_FONT_6x10 is not set
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+CONFIG_FONT_10x18=y
+# CONFIG_ARCH_HAS_SG_CHAIN is not set
+CONFIG_KVM_COMPAT=y
+CONFIG_VIRTUALIZATION=y
diff --git a/gnu/packages/linux.scm b/gnu/packages/linux.scm
index 698fa3a36c..a8b770b273 100644
--- a/gnu/packages/linux.scm
+++ b/gnu/packages/linux.scm
@@ -372,6 +372,32 @@ It has been modified to remove all non-free binary blobs.")
        `(,@(alist-delete "kconfig" (package-native-inputs linux-libre))
          ("kconfig" ,conf))))))
 
+(define-public linux-libre-loongson2f
+  (package (inherit linux-libre-4.1)
+    (name "linux-libre-loongson2f")
+    (source (origin
+              (inherit (package-source linux-libre-4.1))
+              (patches
+               (map search-patch
+                    '("linux-libre-mips-hugetlb-fix.patch"
+                      "linux-libre-mips-ftrace-fix.patch"
+                      "linux-libre-mips-math-emu-fix-pt1.patch"
+                      "linux-libre-mips-math-emu-fix-pt2.patch"
+                      "linux-libre-loongson2-math-emu.patch"
+                      "linux-libre-loongson2-cpufreq-fix.patch"
+                      "linux-libre-loongson2-max-physmem-bits.patch"
+                      "linux-libre-export-loongson-chipcfg.patch"
+                      "linux-libre-yeeloong.patch"
+                      "linux-libre-yeeloong-rfkill-key-fix.patch"
+                      "linux-libre-yeeloong-silence-ec-messages.patch"
+                      "linux-libre-gdium.patch")))))
+    (supported-systems '("mips64el-linux"))
+    (native-inputs
+     (let ((conf (search-path %load-path
+                              "gnu/packages/linux-libre-loongson2f.conf")))
+       `(,@(alist-delete "kconfig" (package-native-inputs linux-libre-4.1))
+         ("kconfig" ,conf))))))
+
 
 ;;;
 ;;; Pluggable authentication modules (PAM).
diff --git a/gnu/packages/patches/linux-libre-export-loongson-chipcfg.patch b/gnu/packages/patches/linux-libre-export-loongson-chipcfg.patch
new file mode 100644
index 0000000000..353211b8c9
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-export-loongson-chipcfg.patch
@@ -0,0 +1,28 @@
+From: Alexandre Oliva <lxoliva@fsfla.org>
+Date: Thu, 6 Aug 2015 01:54:21 -0400
+Subject: [PATCH 6/9] Loongson: export loongson_chipcfg
+
+Building drivers/cpufreq/loongson_cpufreq as a module would fail
+because loongson_chipcfg wasn't exported in
+arch/mips/loongson/common/env.c.  Fixed.
+
+Signed-off-by: Alexandre Oliva <lxoliva@fsfla.org>
+---
+ arch/mips/loongson64/common/env.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
+index 22f04ca..fc454f2 100644
+--- a/arch/mips/loongson/common/env.c
++++ b/arch/mips/loongson/common/env.c
+@@ -29,6 +29,7 @@ struct efi_memory_map_loongson *loongson_memmap;
+ struct loongson_system_configuration loongson_sysconf;
+ 
+ u64 loongson_chipcfg[MAX_PACKAGES] = {0xffffffffbfc00180};
++EXPORT_SYMBOL_GPL(loongson_chipcfg);
+ u64 loongson_chiptemp[MAX_PACKAGES];
+ u64 loongson_freqctrl[MAX_PACKAGES];
+ 
+-- 
+2.4.3
+
diff --git a/gnu/packages/patches/linux-libre-gdium.patch b/gnu/packages/patches/linux-libre-gdium.patch
new file mode 100644
index 0000000000..6f71d65215
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-gdium.patch
@@ -0,0 +1,2549 @@
+Add support for the gdium laptop.  This selection of patches was derived from
+looking at the differences between the linux-stable and loongson-community git
+repositories.
+
+diff --git a/arch/mips/include/asm/mach-loongson/machine.h b/arch/mips/include/asm/mach-loongson/machine.h
+index cb2b602..78fcd38 100644
+--- a/arch/mips/include/asm/mach-loongson/machine.h
++++ b/arch/mips/include/asm/mach-loongson/machine.h
+@@ -24,6 +24,12 @@
+ 
+ #endif
+ 
++#ifdef CONFIG_DEXXON_GDIUM
++
++#define LOONGSON_MACHTYPE MACH_DEXXON_GDIUM2F10
++
++#endif
++
+ #ifdef CONFIG_LOONGSON_MACH3X
+ 
+ #define LOONGSON_MACHTYPE MACH_LOONGSON_GENERIC
+diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
+index 659ca91..e6a9ac3 100644
+--- a/arch/mips/loongson/Kconfig
++++ b/arch/mips/loongson/Kconfig
+@@ -59,6 +59,31 @@ config LEMOTE_MACH2F
+ 	  These family machines include fuloong2f mini PC, yeeloong2f notebook,
+ 	  LingLoong allinone PC and so forth.
+ 
++config DEXXON_GDIUM
++	bool "Dexxon Gdium Netbook"
++	select ARCH_SPARSEMEM_ENABLE
++	select BOARD_SCACHE
++	select BOOT_ELF32
++	select CEVT_R4K if ! MIPS_EXTERNAL_TIMER
++	select CPU_HAS_WB
++	select CSRC_R4K if ! MIPS_EXTERNAL_TIMER
++	select DMA_NONCOHERENT
++	select GENERIC_ISA_DMA_SUPPORT_BROKEN
++	select HW_HAS_PCI
++	select I8259
++	select IRQ_CPU
++	select ISA
++	select SYS_HAS_CPU_LOONGSON2F
++	select SYS_HAS_EARLY_PRINTK
++	select SYS_SUPPORTS_32BIT_KERNEL
++	select SYS_SUPPORTS_64BIT_KERNEL
++	select SYS_SUPPORTS_HIGHMEM
++	select SYS_SUPPORTS_LITTLE_ENDIAN
++	select ARCH_REQUIRE_GPIOLIB
++	select HAVE_PWM if MFD_SM501
++	help
++	  Dexxon gdium netbook based on Loongson 2F and SM502.
++
+ config LOONGSON_MACH3X
+ 	bool "Generic Loongson 3 family machines"
+ 	select ARCH_SPARSEMEM_ENABLE
+@@ -151,6 +176,24 @@ config LOONGSON_MC146818
+ 	bool
+ 	default n
+ 
++config GDIUM_PWM_CLOCK
++	tristate "Gdium PWM Timer"
++	default n
++	depends on HAVE_PWM && EXPERIMENTAL && BROKEN
++	select MIPS_EXTERNAL_TIMER
++	help
++	  This options enables the experimental sm501-pwm based clock. With it,
++	  you may be possible to use the loongson2f cpufreq driver.
++
++config GDIUM_VERSION
++	int "Configure Gdium Version"
++	depends on DEXXON_GDIUM
++	default "3"
++	help
++	  I have no information about how to determine which version your board
++	  is, If the default config doesn't work for it, please change it to
++	  smaller ones.
++
+ config LEFI_FIRMWARE_INTERFACE
+ 	bool
+ 
+diff --git a/arch/mips/loongson/Makefile b/arch/mips/loongson/Makefile
+index 7429994..63214c8 100644
+--- a/arch/mips/loongson/Makefile
++++ b/arch/mips/loongson/Makefile
+@@ -17,6 +17,12 @@ obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fuloong-2e/
+ obj-$(CONFIG_LEMOTE_MACH2F)  += lemote-2f/
+ 
+ #
++# Dexxon gdium netbook, based on loongson 2F and SM502
++#
++
++obj-$(CONFIG_DEXXON_GDIUM)  += gdium/
++
++#
+ # All Loongson-3 family machines
+ #
+ 
+diff --git a/arch/mips/loongson/Platform b/arch/mips/loongson/Platform
+index 0ac20eb..cd957dd 100644
+--- a/arch/mips/loongson/Platform
++++ b/arch/mips/loongson/Platform
+@@ -30,4 +30,5 @@ platform-$(CONFIG_MACH_LOONGSON) += loongson/
+ cflags-$(CONFIG_MACH_LOONGSON) += -I$(srctree)/arch/mips/include/asm/mach-loongson -mno-branch-likely
+ load-$(CONFIG_LEMOTE_FULOONG2E) += 0xffffffff80100000
+ load-$(CONFIG_LEMOTE_MACH2F) += 0xffffffff80200000
++load-$(CONFIG_DEXXON_GDIUM) += 0xffffffff80200000
+ load-$(CONFIG_LOONGSON_MACH3X) += 0xffffffff80200000
+diff --git a/arch/mips/loongson/common/cmdline.c b/arch/mips/loongson/common/cmdline.c
+index 679a18a..96d5919 100644
+--- a/arch/mips/loongson/common/cmdline.c
++++ b/arch/mips/loongson/common/cmdline.c
+@@ -66,6 +66,11 @@ void __init prom_init_cmdline(void)
+ 		if ((strstr(arcs_cmdline, "vga=")) == NULL)
+ 			strcat(arcs_cmdline, " vga=0x313");
+ 		break;
++	case MACH_DEXXON_GDIUM2F10:
++		/* gdium has a 1024x600 screen */
++		if ((strstr(arcs_cmdline, "video=")) == NULL)
++			strcat(arcs_cmdline, " video=sm501fb:1024x600@60");
++		break;
+ 	default:
+ 		break;
+ 	}
+diff --git a/arch/mips/loongson/gdium/Makefile b/arch/mips/loongson/gdium/Makefile
+new file mode 100644
+index 0000000..f3f4f51
+--- /dev/null
++++ b/arch/mips/loongson/gdium/Makefile
+@@ -0,0 +1,6 @@
++# Makefile for gdium
++
++obj-y += irq.o reset.o platform.o
++
++obj-$(CONFIG_MFD_SM501) += sm501-pwm.o
++obj-$(CONFIG_GDIUM_PWM_CLOCK) += gdium-clock.o
+diff --git a/arch/mips/loongson/gdium/gdium-clock.c b/arch/mips/loongson/gdium/gdium-clock.c
+new file mode 100644
+index 0000000..fdbf42a
+--- /dev/null
++++ b/arch/mips/loongson/gdium/gdium-clock.c
+@@ -0,0 +1,234 @@
++/*
++ * Doesn't work really well. When used, the clocksource is producing
++ * bad timings and the clockevent can't be used (don't have one shot feature
++ * thus can't switch on the fly and the pwm is initialised too late to be able
++ * to use it at boot time).
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/pwm.h>
++#include <linux/clocksource.h>
++#include <linux/debugfs.h>
++#include <asm/irq_cpu.h>
++#include <asm/mipsregs.h>
++#include <asm/mips-boards/bonito64.h>
++#include <asm/time.h>
++
++#include <loongson.h>
++
++#define CLOCK_PWM		1
++#define CLOCK_PWM_FREQ		1500000				/* Freq in Hz */
++#define CLOCK_LATCH		((CLOCK_PWM_FREQ + HZ/2) / HZ)
++#define CLOCK_PWM_PERIOD	(1000000000/CLOCK_PWM_FREQ)	/* period ns  */
++#define CLOCK_PWM_DUTY		50
++#define CLOCK_PWM_IRQ		(MIPS_CPU_IRQ_BASE + 4)
++
++static const char drv_name[] = "gdium-clock";
++
++static struct pwm_device *clock_pwm;
++
++static DEFINE_SPINLOCK(clock_pwm_lock);
++static uint64_t clock_tick;
++
++static irqreturn_t gdium_pwm_clock_interrupt(int irq, void *dev_id)
++{
++	struct clock_event_device *cd = dev_id;
++	unsigned long flag;
++
++	spin_lock_irqsave(&clock_pwm_lock, flag);
++	clock_tick++;
++	/* wait intn2 to finish */
++	do {
++		LOONGSON_INTENCLR = (1 << 13);
++	} while (LOONGSON_INTISR & (1 << 13));
++	spin_unlock_irqrestore(&clock_pwm_lock, flag);
++
++	if (cd && cd->event_handler)
++		cd->event_handler(cd);
++
++	return IRQ_HANDLED;
++}
++
++static cycle_t gdium_pwm_clock_read(struct clocksource *cs)
++{
++	unsigned long flag;
++	uint32_t jifs;
++	uint64_t ticks;
++
++	spin_lock_irqsave(&clock_pwm_lock, flag);
++	jifs = jiffies;
++	ticks = clock_tick;
++	spin_unlock_irqrestore(&clock_pwm_lock, flag);
++	/* return (cycle_t)ticks; */
++	return (cycle_t)(CLOCK_LATCH * jifs);
++}
++
++static struct clocksource gdium_pwm_clock_clocksource = {
++	.name   = "gdium_csrc",
++	.read   = gdium_pwm_clock_read,
++	.mask   = CLOCKSOURCE_MASK(64),
++	.flags	= CLOCK_SOURCE_IS_CONTINUOUS | CLOCK_SOURCE_MUST_VERIFY,
++	.shift	= 20,
++};
++
++/* Debug fs */
++static int gdium_pwm_clock_show(struct seq_file *s, void *p)
++{
++	unsigned long flag;
++	uint64_t ticks;
++
++	spin_lock_irqsave(&clock_pwm_lock, flag);
++	ticks = clock_tick;
++	spin_unlock_irqrestore(&clock_pwm_lock, flag);
++	seq_printf(s, "%lld\n", ticks);
++	return 0;
++}
++
++static int gdium_pwm_clock_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, gdium_pwm_clock_show, inode->i_private);
++}
++
++static const struct file_operations gdium_pwm_clock_fops = {
++	.open		= gdium_pwm_clock_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++	.owner		= THIS_MODULE,
++};
++static struct dentry   *debugfs_file;
++
++static void gdium_pwm_clock_set_mode(enum clock_event_mode mode,
++		struct clock_event_device *evt)
++{
++	/* Nothing to do ...  */
++}
++
++static struct clock_event_device gdium_pwm_clock_cevt = {
++	.name           = "gdium_cevt",
++	.features       = CLOCK_EVT_FEAT_PERIODIC,
++	/* .mult, .shift, .max_delta_ns and .min_delta_ns left uninitialized */
++	.rating         = 299,
++	.irq            = CLOCK_PWM_IRQ,
++	.set_mode       = gdium_pwm_clock_set_mode,
++};
++
++static struct platform_device_id platform_device_ids[] = {
++	{
++		.name = "gdium-pwmclk",
++	},
++	{}
++};
++MODULE_DEVICE_TABLE(platform, platform_device_ids);
++
++static struct platform_driver gdium_pwm_clock_driver = {
++	.driver		= {
++		.name   = drv_name,
++		.owner  = THIS_MODULE,
++	},
++	.id_table = platform_device_ids,
++};
++
++static int gdium_pwm_clock_drvinit(void)
++{
++	int ret;
++	struct clocksource *cs = &gdium_pwm_clock_clocksource;
++	struct clock_event_device *cd = &gdium_pwm_clock_cevt;
++	unsigned int cpu = smp_processor_id();
++
++	clock_tick = 0;
++
++	clock_pwm = pwm_request(CLOCK_PWM, drv_name);
++	if (clock_pwm == NULL) {
++		pr_err("unable to request PWM for Gdium clock\n");
++		return -EBUSY;
++	}
++	ret = pwm_config(clock_pwm, CLOCK_PWM_DUTY, CLOCK_PWM_PERIOD);
++	if (ret) {
++		pr_err("unable to configure PWM for Gdium clock\n");
++		goto err_pwm_request;
++	}
++	ret = pwm_enable(clock_pwm);
++	if (ret) {
++		pr_err("unable to enable PWM for Gdium clock\n");
++		goto err_pwm_request;
++	}
++
++	cd->cpumask = cpumask_of(cpu);
++
++	cd->shift = 22;
++	cd->mult  = div_sc(CLOCK_PWM_FREQ, NSEC_PER_SEC, cd->shift);
++	cd->max_delta_ns = clockevent_delta2ns(0x7FFF, cd);
++	cd->min_delta_ns = clockevent_delta2ns(0xF, cd);
++	clockevents_register_device(&gdium_pwm_clock_cevt);
++
++	/* SM501 PWM1 connected to intn2 <->ip4 */
++	LOONGSON_INTPOL = (1 << 13);
++	LOONGSON_INTEDGE &= ~(1 << 13);
++	ret = request_irq(CLOCK_PWM_IRQ, gdium_pwm_clock_interrupt, IRQF_DISABLED, drv_name, &gdium_pwm_clock_cevt);
++	if (ret) {
++		pr_err("Can't claim irq\n");
++		goto err_pwm_disable;
++	}
++
++	cs->rating = 200;
++	cs->mult = clocksource_hz2mult(CLOCK_PWM_FREQ, cs->shift);
++	ret = clocksource_register(&gdium_pwm_clock_clocksource);
++	if (ret) {
++		pr_err("Can't register clocksource\n");
++		goto err_irq;
++	}
++	pr_info("Clocksource registered with shift %d and mult %d\n",
++			cs->shift, cs->mult);
++
++	debugfs_file = debugfs_create_file(drv_name, S_IFREG | S_IRUGO,
++			NULL, NULL, &gdium_pwm_clock_fops);
++
++	return 0;
++
++err_irq:
++	free_irq(CLOCK_PWM_IRQ, &gdium_pwm_clock_cevt);
++err_pwm_disable:
++	pwm_disable(clock_pwm);
++err_pwm_request:
++	pwm_free(clock_pwm);
++	return ret;
++}
++
++static void gdium_pwm_clock_drvexit(void)
++{
++	free_irq(CLOCK_PWM_IRQ, &gdium_pwm_clock_cevt);
++	pwm_disable(clock_pwm);
++	pwm_free(clock_pwm);
++}
++
++
++static int __devinit gdium_pwm_clock_init(void)
++{
++	int ret = gdium_pwm_clock_drvinit();
++
++	if (ret) {
++		pr_err("Fail to register gdium clock driver\n");
++		return ret;
++	}
++
++	return platform_driver_register(&gdium_pwm_clock_driver);
++}
++
++static void __exit gdium_pwm_clock_cleanup(void)
++{
++	gdium_pwm_clock_drvexit();
++	platform_driver_unregister(&gdium_pwm_clock_driver);
++}
++
++module_init(gdium_pwm_clock_init);
++module_exit(gdium_pwm_clock_cleanup);
++
++MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
++MODULE_DESCRIPTION("Gdium PWM clock driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:gdium-pwmclk");
+diff --git a/arch/mips/loongson/gdium/irq.c b/arch/mips/loongson/gdium/irq.c
+new file mode 100644
+index 0000000..2415d20
+--- /dev/null
++++ b/arch/mips/loongson/gdium/irq.c
+@@ -0,0 +1,55 @@
++/*
++ * Copyright (C) 2007 Lemote Inc.
++ * Author: Fuxin Zhang, zhangfx@lemote.com
++ *
++ * Copyright (c) 2010 yajin <yajin@vm-kernel.org>
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ */
++
++#include <linux/interrupt.h>
++#include <linux/module.h>
++
++#include <loongson.h>
++#include <machine.h>
++
++#define LOONGSON_TIMER_IRQ      (MIPS_CPU_IRQ_BASE + 7) /* cpu timer */
++#define LOONGSON_NORTH_BRIDGE_IRQ       (MIPS_CPU_IRQ_BASE + 6) /* bonito */
++#define LOONGSON_UART_IRQ       (MIPS_CPU_IRQ_BASE + 3) /* cpu serial port */
++
++void mach_irq_dispatch(unsigned int pending)
++{
++	if (pending & CAUSEF_IP7)
++		do_IRQ(LOONGSON_TIMER_IRQ);
++	else if (pending & CAUSEF_IP6) {        /* North Bridge, Perf counter */
++		do_perfcnt_IRQ();
++		bonito_irqdispatch();
++	} else if (pending & CAUSEF_IP3)        /* CPU UART */
++		do_IRQ(LOONGSON_UART_IRQ);
++#if defined(CONFIG_GDIUM_PWM_CLOCK) || defined(CONFIG_GDIUM_PWM_CLOCK_MODULE)
++	else if (pending & CAUSEF_IP4)		/* SM501 PWM clock */
++		do_IRQ(MIPS_CPU_IRQ_BASE + 4);
++#endif
++	else
++		spurious_interrupt();
++}
++
++static irqreturn_t ip6_action(int cpl, void *dev_id)
++{
++	return IRQ_HANDLED;
++}
++
++struct irqaction ip6_irqaction = {
++	.handler = ip6_action,
++	.name = "cascade",
++	.flags = IRQF_SHARED,
++};
++
++void __init mach_init_irq(void)
++{
++	/* setup north bridge irq (bonito) */
++	setup_irq(LOONGSON_NORTH_BRIDGE_IRQ, &ip6_irqaction);
++}
+diff --git a/arch/mips/loongson/gdium/platform.c b/arch/mips/loongson/gdium/platform.c
+new file mode 100644
+index 0000000..ffafba4
+--- /dev/null
++++ b/arch/mips/loongson/gdium/platform.c
+@@ -0,0 +1,135 @@
++/*
++ * Copyright (c) 2009 Philippe Vachon <philippe@cowpig.ca>
++ *
++ * This program is free software; you can redistribute  it and/or modify it
++ * under  the terms of  the GNU General  Public License as published by the
++ * Free Software Foundation;  either version 2 of the  License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/platform_device.h>
++#include <linux/pwm_backlight.h>
++#include <linux/i2c.h>
++#include <linux/i2c-gpio.h>
++
++#define GDIUM_GPIO_BASE 224
++
++static struct i2c_board_info __initdata sm502dev_i2c_devices[] = {
++	{
++		I2C_BOARD_INFO("lm75", 0x48),
++	},
++	{
++		I2C_BOARD_INFO("m41t83", 0x68),
++	},
++	{
++		I2C_BOARD_INFO("gdium-laptop", 0x40),
++	},
++};
++
++static int sm502dev_backlight_init(struct device *dev)
++{
++	/* Add gpio request stuff here */
++	return 0;
++}
++
++static void sm502dev_backlight_exit(struct device *dev)
++{
++	/* Add gpio free stuff here */
++}
++
++static struct platform_pwm_backlight_data backlight_data = {
++	.pwm_id		= 0,
++	.max_brightness	= 15,
++	.dft_brightness	= 8,
++	.pwm_period_ns	= 50000, /* 20 kHz */
++	.init		= sm502dev_backlight_init,
++	.exit		= sm502dev_backlight_exit,
++};
++
++static struct platform_device backlight = {
++	.name = "pwm-backlight",
++	.dev  = {
++		.platform_data = &backlight_data,
++	},
++	.id   = -1,
++};
++
++/*
++ * Warning this stunt is very dangerous
++ * as the sm501 gpio have dynamic numbers...
++ */
++/* bus 0 is the one for the ST7, DS75 etc... */
++static struct i2c_gpio_platform_data i2c_gpio0_data = {
++#if CONFIG_GDIUM_VERSION > 2
++	.sda_pin	= GDIUM_GPIO_BASE + 13,
++	.scl_pin	= GDIUM_GPIO_BASE + 6,
++#else
++	.sda_pin        = 192+15,
++	.scl_pin        = 192+14,
++#endif
++	.udelay		= 5,
++	.timeout	= HZ / 10,
++	.sda_is_open_drain = 0,
++	.scl_is_open_drain = 0,
++};
++
++static struct platform_device i2c_gpio0_device = {
++	.name	= "i2c-gpio",
++	.id	= 0,
++	.dev	= { .platform_data  = &i2c_gpio0_data, },
++};
++
++/* bus 1 is for the CRT/VGA external screen */
++static struct i2c_gpio_platform_data i2c_gpio1_data = {
++	.sda_pin	= GDIUM_GPIO_BASE + 10,
++	.scl_pin	= GDIUM_GPIO_BASE + 9,
++	.udelay		= 5,
++	.timeout	= HZ / 10,
++	.sda_is_open_drain = 0,
++	.scl_is_open_drain = 0,
++};
++
++static struct platform_device i2c_gpio1_device = {
++	.name	= "i2c-gpio",
++	.id	= 1,
++	.dev	= { .platform_data  = &i2c_gpio1_data, },
++};
++
++static struct platform_device gdium_clock = {
++	.name		= "gdium-pwmclk",
++	.id		= -1,
++};
++
++static struct platform_device *devices[] __initdata = {
++	&i2c_gpio0_device,
++	&i2c_gpio1_device,
++	&backlight,
++	&gdium_clock,
++};
++
++static int __init gdium_platform_devices_setup(void)
++{
++	int ret;
++
++	pr_info("Registering gdium platform devices\n");
++
++	ret = i2c_register_board_info(0, sm502dev_i2c_devices,
++		ARRAY_SIZE(sm502dev_i2c_devices));
++
++	if (ret != 0) {
++		pr_info("Error while registering platform devices: %d\n", ret);
++		return ret;
++	}
++
++	platform_add_devices(devices, ARRAY_SIZE(devices));
++
++	return 0;
++}
++
++/*
++ * some devices are on the pwm stuff which is behind the mfd which is
++ * behind the pci bus so arch_initcall can't work because too early
++ */
++late_initcall(gdium_platform_devices_setup);
+diff --git a/arch/mips/loongson/gdium/reset.c b/arch/mips/loongson/gdium/reset.c
+new file mode 100644
+index 0000000..8289f95
+--- /dev/null
++++ b/arch/mips/loongson/gdium/reset.c
+@@ -0,0 +1,22 @@
++/* Board-specific reboot/shutdown routines
++ *
++ * Copyright (C) 2010 yajin <yajin@vm-kernel.org>
++ *
++ * This program is free software; you can redistribute  it and/or modify it
++ * under  the terms of  the GNU General  Public License as published by the
++ * Free Software Foundation;  either version 2 of the  License, or (at your
++ * option) any later version.
++ */
++#include <loongson.h>
++
++void mach_prepare_shutdown(void)
++{
++	LOONGSON_GPIOIE &= ~(1<<1);
++	LOONGSON_GPIODATA |= (1<<1);
++}
++
++void mach_prepare_reboot(void)
++{
++	LOONGSON_GPIOIE &= ~(1<<2);
++	LOONGSON_GPIODATA &= ~(1<<2);
++}
+diff --git a/arch/mips/loongson/gdium/sm501-pwm.c b/arch/mips/loongson/gdium/sm501-pwm.c
+new file mode 100644
+index 0000000..5af3b23
+--- /dev/null
++++ b/arch/mips/loongson/gdium/sm501-pwm.c
+@@ -0,0 +1,465 @@
++/*
++ * SM501 PWM clock
++ * Copyright (C) 2009-2010 Arnaud Patard <apatard@mandriva.com>
++ *
++ * This program is free software; you can redistribute  it and/or modify it
++ * under  the terms of  the GNU General  Public License as published by the
++ * Free Software Foundation;  either version 2 of the  License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/slab.h>
++#include <linux/pwm.h>
++#include <linux/sm501.h>
++#include <linux/sm501-regs.h>
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
++
++static const char drv_name[] = "sm501-pwm";
++
++#define INPUT_CLOCK		96 /* MHz */
++#define PWM_COUNT		3
++
++#define SM501PWM_HIGH_COUNTER	(1<<20)
++#define SM501PWM_LOW_COUNTER	(1<<8)
++#define SM501PWM_CLOCK_DIVIDE	(1>>4)
++#define SM501PWM_IP		(1<<3)
++#define SM501PWM_I		(1<<2)
++#define SM501PWM_E		(1<<0)
++
++struct pwm_device {
++	struct list_head	node;
++	struct device		*dev;
++	void __iomem		*regs;
++	int			duty_ns;
++	int			period_ns;
++	char			enabled;
++	void			(*handler)(struct pwm_device *pwm);
++
++	const char		*label;
++	unsigned int		use_count;
++	unsigned int		pwm_id;
++};
++
++struct sm501pwm_info {
++	void __iomem	*regs;
++	int		irq;
++	struct resource *res;
++	struct device	*dev;
++	struct dentry	*debugfs;
++
++	struct pwm_device pwm[3];
++};
++
++int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
++{
++	unsigned int high, low, divider;
++	int divider1, divider2;
++	unsigned long long delay;
++
++	if (!pwm || !pwm->regs || period_ns == 0 || duty_ns > period_ns)
++		return -EINVAL;
++
++	/* Get delay
++	 * We're loosing some precision but multiplying then dividing
++	 * will overflow
++	 */
++	if (period_ns > 1000) {
++		delay = period_ns / 1000;
++		delay *= INPUT_CLOCK;
++	} else {
++		delay = period_ns * 96;
++		delay /= 1000;
++	}
++
++	/* Get the number of clock low and high */
++	high  = delay * duty_ns / period_ns;
++	low = delay - high;
++
++	/* Get divider to make 'low' and 'high' fit into 12 bits */
++	/* No need to say that the divider must be >= 0 */
++	divider1 = fls(low)-12;
++	divider2 = fls(high)-12;
++
++	if (divider1 < 0)
++		divider1 = 0;
++	if (divider2 < 0)
++		divider2 = 0;
++
++	divider = max(divider1, divider2);
++
++	low >>= divider;
++	high >>= divider;
++
++	pwm->duty_ns = duty_ns;
++	pwm->period_ns = period_ns;
++
++	writel((high<<20)|(low<<8)|(divider<<4), pwm->regs);
++	return 0;
++}
++EXPORT_SYMBOL(pwm_config);
++
++int pwm_enable(struct pwm_device *pwm)
++{
++	u32 reg;
++
++	if (!pwm)
++		return -EINVAL;
++
++	switch (pwm->pwm_id) {
++	case 0:
++		sm501_configure_gpio(pwm->dev->parent, 29, 1);
++		break;
++	case 1:
++		sm501_configure_gpio(pwm->dev->parent, 30, 1);
++		break;
++	case 2:
++		sm501_configure_gpio(pwm->dev->parent, 31, 1);
++		break;
++	default:
++		return -EINVAL;
++	}
++
++	reg = readl(pwm->regs);
++	reg |= (SM501PWM_IP | SM501PWM_E);
++	writel(reg, pwm->regs);
++	pwm->enabled = 1;
++
++	return 0;
++}
++EXPORT_SYMBOL(pwm_enable);
++
++void pwm_disable(struct pwm_device *pwm)
++{
++	u32 reg;
++
++	if (!pwm)
++		return;
++
++	reg = readl(pwm->regs);
++	reg &= ~(SM501PWM_IP | SM501PWM_E);
++	writel(reg, pwm->regs);
++
++	switch (pwm->pwm_id) {
++	case 0:
++		sm501_configure_gpio(pwm->dev->parent, 29, 0);
++		break;
++	case 1:
++		sm501_configure_gpio(pwm->dev->parent, 30, 0);
++		break;
++	case 2:
++		sm501_configure_gpio(pwm->dev->parent, 31, 0);
++		break;
++	default:
++		break;
++	}
++	pwm->enabled = 0;
++}
++EXPORT_SYMBOL(pwm_disable);
++
++static DEFINE_MUTEX(pwm_lock);
++static LIST_HEAD(pwm_list);
++
++struct pwm_device *pwm_request(int pwm_id, const char *label)
++{
++	struct pwm_device *pwm;
++	int found = 0;
++
++	mutex_lock(&pwm_lock);
++
++	list_for_each_entry(pwm, &pwm_list, node) {
++		if (pwm->pwm_id == pwm_id && pwm->use_count == 0) {
++			pwm->use_count++;
++			pwm->label = label;
++			found = 1;
++			break;
++		}
++	}
++
++	mutex_unlock(&pwm_lock);
++
++	return (found) ? pwm : NULL;
++}
++EXPORT_SYMBOL(pwm_request);
++
++void pwm_free(struct pwm_device *pwm)
++{
++	mutex_lock(&pwm_lock);
++
++	if (pwm->use_count) {
++		pwm->use_count--;
++		pwm->label = NULL;
++	} else
++		dev_warn(pwm->dev, "PWM device already freed\n");
++
++	mutex_unlock(&pwm_lock);
++}
++EXPORT_SYMBOL(pwm_free);
++
++int pwm_int_enable(struct pwm_device *pwm)
++{
++	unsigned long conf;
++
++	if (!pwm || !pwm->regs || !pwm->handler)
++		return -EINVAL;
++
++	conf = readl(pwm->regs);
++	conf |= SM501PWM_I;
++	writel(conf, pwm->regs);
++	return 0;
++}
++EXPORT_SYMBOL(pwm_int_enable);
++
++int pwm_int_disable(struct pwm_device *pwm)
++{
++	unsigned long conf;
++
++	if (!pwm || !pwm->regs || !pwm->handler)
++		return -EINVAL;
++
++	conf = readl(pwm->regs);
++	conf &= ~SM501PWM_I;
++	writel(conf, pwm->regs);
++	return 0;
++}
++EXPORT_SYMBOL(pwm_int_disable);
++
++int pwm_set_handler(struct pwm_device *pwm,
++		    void (*handler)(struct pwm_device *pwm))
++{
++	if (!pwm || !handler)
++		return -EINVAL;
++	pwm->handler = handler;
++	return 0;
++}
++EXPORT_SYMBOL(pwm_set_handler);
++
++static irqreturn_t sm501pwm_irq(int irq, void *dev_id)
++{
++	unsigned long value;
++	struct sm501pwm_info *info = (struct sm501pwm_info *)dev_id;
++	struct pwm_device *pwm;
++	int i;
++
++	value = sm501_modify_reg(info->dev->parent, SM501_IRQ_STATUS, 0, 0);
++
++	/* Check is the interrupt is for us */
++	if (value & (1<<22)) {
++		for (i = 0 ; i < PWM_COUNT ; i++) {
++			/*
++			 * Find which pwm triggered the interrupt
++			 * and ack
++			 */
++			value = readl(info->regs + i*4);
++			if (value & SM501PWM_IP)
++				writel(value | SM501PWM_IP, info->regs + i*4);
++
++			pwm = &info->pwm[i];
++			if (pwm->handler)
++				pwm->handler(pwm);
++		}
++		return IRQ_HANDLED;
++	}
++
++	return IRQ_NONE;
++}
++
++static void add_pwm(int id, struct sm501pwm_info *info)
++{
++	struct pwm_device *pwm = &info->pwm[id];
++
++	pwm->use_count	= 0;
++	pwm->pwm_id	= id;
++	pwm->dev	= info->dev;
++	pwm->regs	= info->regs + id * 4;
++
++	mutex_lock(&pwm_lock);
++	list_add_tail(&pwm->node, &pwm_list);
++	mutex_unlock(&pwm_lock);
++}
++
++static void del_pwm(int id, struct sm501pwm_info *info)
++{
++	struct pwm_device *pwm = &info->pwm[id];
++
++	pwm->use_count  = 0;
++	pwm->pwm_id     = -1;
++	mutex_lock(&pwm_lock);
++	list_del(&pwm->node);
++	mutex_unlock(&pwm_lock);
++}
++
++/* Debug fs */
++static int sm501pwm_show(struct seq_file *s, void *p)
++{
++	struct pwm_device *pwm;
++
++	mutex_lock(&pwm_lock);
++	list_for_each_entry(pwm, &pwm_list, node) {
++		if (pwm->use_count) {
++			seq_printf(s, "pwm-%d (%12s) %d %d %s\n",
++					pwm->pwm_id, pwm->label,
++					pwm->duty_ns, pwm->period_ns,
++					pwm->enabled ? "on" : "off");
++			seq_printf(s, "       %08x\n", readl(pwm->regs));
++		}
++	}
++	mutex_unlock(&pwm_lock);
++
++	return 0;
++}
++
++static int sm501pwm_open(struct inode *inode, struct file *file)
++{
++	return single_open(file, sm501pwm_show, inode->i_private);
++}
++
++static const struct file_operations sm501pwm_fops = {
++	.open		= sm501pwm_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++	.owner		= THIS_MODULE,
++};
++
++static int __init sm501pwm_probe(struct platform_device *pdev)
++{
++	struct sm501pwm_info *info;
++	struct device   *dev = &pdev->dev;
++	struct resource *res;
++	int ret = 0;
++	int res_len;
++	int i;
++
++	info = kzalloc(sizeof(struct sm501pwm_info), GFP_KERNEL);
++	if (!info) {
++		dev_err(dev, "Allocation failure\n");
++		ret = -ENOMEM;
++		goto err;
++	}
++	info->dev = dev;
++	platform_set_drvdata(pdev, info);
++
++	/* Get irq number */
++	info->irq = platform_get_irq(pdev, 0);
++	if (!info->irq) {
++		dev_err(dev, "no irq found\n");
++		ret = -ENODEV;
++		goto err_alloc;
++	}
++
++	/* Get regs address */
++	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++	if (res == NULL) {
++		dev_err(dev, "No memory resource found\n");
++		ret = -ENODEV;
++		goto err_alloc;
++	}
++	info->res = res;
++	res_len = (res->end - res->start)+1;
++
++	if (!request_mem_region(res->start, res_len, drv_name)) {
++		dev_err(dev, "Can't request iomem resource\n");
++		ret = -EBUSY;
++		goto err_alloc;
++	}
++
++	info->regs = ioremap(res->start, res_len);
++	if (!info->regs) {
++		dev_err(dev, "ioremap failed\n");
++		ret = -ENOMEM;
++		goto err_mem;
++	}
++
++	ret = request_irq(info->irq, sm501pwm_irq, IRQF_SHARED, drv_name, info);
++	if (ret != 0) {
++		dev_err(dev, "can't get irq\n");
++		goto err_map;
++	}
++
++
++	sm501_unit_power(info->dev->parent, SM501_GATE_GPIO, 1);
++
++	for (i = 0; i < 3; i++)
++		add_pwm(i, info);
++
++	dev_info(dev, "SM501 PWM Found at %lx irq %d\n",
++		 (unsigned long)info->res->start, info->irq);
++
++	info->debugfs = debugfs_create_file("pwm", S_IFREG | S_IRUGO,
++				NULL, info, &sm501pwm_fops);
++
++
++	return 0;
++
++err_map:
++	iounmap(info->regs);
++
++err_mem:
++	release_mem_region(res->start, res_len);
++
++err_alloc:
++	kfree(info);
++	platform_set_drvdata(pdev, NULL);
++err:
++	return ret;
++}
++
++static int sm501pwm_remove(struct platform_device *pdev)
++{
++	struct sm501pwm_info *info = platform_get_drvdata(pdev);
++	int i;
++
++	if (info->debugfs)
++		debugfs_remove(info->debugfs);
++
++	for (i = 0; i < 3; i++) {
++		pwm_disable(&info->pwm[i]);
++		del_pwm(i, info);
++	}
++
++	sm501_unit_power(info->dev->parent, SM501_GATE_GPIO, 0);
++	sm501_modify_reg(info->dev->parent, SM501_IRQ_STATUS, 0, 1<<22);
++
++	free_irq(info->irq, info);
++	iounmap(info->regs);
++	release_mem_region(info->res->start,
++			   (info->res->end - info->res->start)+1);
++	kfree(info);
++	platform_set_drvdata(pdev, NULL);
++
++	return 0;
++}
++
++static struct platform_driver sm501pwm_driver = {
++	.probe		= sm501pwm_probe,
++	.remove		= sm501pwm_remove,
++	.driver		= {
++		.name	= drv_name,
++		.owner	= THIS_MODULE,
++	},
++};
++
++static int __devinit sm501pwm_init(void)
++{
++	return platform_driver_register(&sm501pwm_driver);
++}
++
++static void __exit sm501pwm_cleanup(void)
++{
++	platform_driver_unregister(&sm501pwm_driver);
++}
++
++module_init(sm501pwm_init);
++module_exit(sm501pwm_cleanup);
++
++MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
++MODULE_DESCRIPTION("SM501 PWM driver");
++MODULE_LICENSE("GPL");
++MODULE_ALIAS("platform:sm501-pwm");
+diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
+index 2eda01e..8adaa3d 100644
+--- a/arch/mips/pci/Makefile
++++ b/arch/mips/pci/Makefile
+@@ -30,6 +30,7 @@ obj-$(CONFIG_LASAT)		+= pci-lasat.o
+ obj-$(CONFIG_MIPS_COBALT)	+= fixup-cobalt.o
+ obj-$(CONFIG_LEMOTE_FULOONG2E)	+= fixup-fuloong2e.o ops-loongson2.o
+ obj-$(CONFIG_LEMOTE_MACH2F)	+= fixup-lemote2f.o ops-loongson2.o
++obj-$(CONFIG_DEXXON_GDIUM)      += fixup-gdium.o ops-loongson2.o
+ obj-$(CONFIG_LOONGSON_MACH3X)	+= fixup-loongson3.o ops-loongson3.o
+ obj-$(CONFIG_MIPS_MALTA)	+= fixup-malta.o pci-malta.o
+ obj-$(CONFIG_PMC_MSP7120_GW)	+= fixup-pmcmsp.o ops-pmcmsp.o
+diff --git a/arch/mips/pci/fixup-gdium.c b/arch/mips/pci/fixup-gdium.c
+new file mode 100644
+index 0000000..b296220
+--- /dev/null
++++ b/arch/mips/pci/fixup-gdium.c
+@@ -0,0 +1,90 @@
++/*
++ * Copyright (C) 2010 yajin <yajin@vm-kernel.org>
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ */
++
++#include <linux/init.h>
++#include <linux/pci.h>
++
++#include <loongson.h>
++/*
++ * http://www.pcidatabase.com
++ * GDIUM has different PCI mapping
++ *  slot 13 (0x1814/0x0301) -> RaLink rt2561 Wireless-G PCI
++ *  slog 14 (0x126f/0x0501) -> sm501
++ *  slot 15 (0x1033/0x0035) -> NEC Dual OHCI controllers
++ *                             plus Single EHCI controller
++ *  slot 16 (0x10ec/0x8139) -> Realtek 8139c
++ *  slot 17 (0x1033/0x00e0) -> NEC USB 2.0 Host Controller
++ */
++
++#undef INT_IRQA
++#undef INT_IRQB
++#undef INT_IRQC
++#undef INT_IRQD
++#define INT_IRQA 36
++#define INT_IRQB 37
++#define INT_IRQC 38
++#define INT_IRQD 39
++
++int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
++{
++	int irq = 0;
++
++	switch (slot) {
++	case 13:
++		irq = INT_IRQC + ((pin - 1) & 3);
++		break;
++	case 14:
++		irq = INT_IRQA;
++		break;
++	case 15:
++#if CONFIG_GDIUM_VERSION > 2
++		irq = INT_IRQB;
++#else
++		irq = INT_IRQA + ((pin - 1) & 3);
++#endif
++		break;
++	case 16:
++		irq = INT_IRQD;
++		break;
++#if CONFIG_GDIUM_VERSION > 2
++	case 17:
++		irq = INT_IRQC;
++		break;
++#endif
++	default:
++		pr_info(" strange pci slot number %d on gdium.\n", slot);
++		break;
++	}
++	return irq;
++}
++
++/* Do platform specific device initialization at pci_enable_device() time */
++int pcibios_plat_dev_init(struct pci_dev *dev)
++{
++	return 0;
++}
++
++/* Fixups for the USB host controllers */
++static void __init gdium_usb_host_fixup(struct pci_dev *dev)
++{
++	unsigned int val;
++	pci_read_config_dword(dev, 0xe0, &val);
++#if CONFIG_GDIUM_VERSION > 2
++	pci_write_config_dword(dev, 0xe0, (val & ~3) | 0x3);
++#else
++	pci_write_config_dword(dev, 0xe0, (val & ~7) | 0x5);
++	pci_write_config_dword(dev, 0xe4, 1<<5);
++#endif
++}
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_NEC_USB,
++				gdium_usb_host_fixup);
++#if CONFIG_GDIUM_VERSION > 2
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NEC, PCI_DEVICE_ID_CT_65550,
++				gdium_usb_host_fixup);
++#endif
+diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig
+index 15338af..e839ebf 100644
+--- a/drivers/hid/Kconfig
++++ b/drivers/hid/Kconfig
+@@ -864,6 +864,13 @@ config HID_ZYDACRON
+ 	---help---
+ 	Support for Zydacron remote control.
+ 
++config HID_GDIUM
++	bool "Gdium Fn keys support" if EMBEDDED
++	depends on USB_HID && DEXXON_GDIUM
++	default !EMBEDDED
++	---help---
++	Support for Functions keys available on Gdiums.
++
+ config HID_SENSOR_HUB
+ 	tristate "HID Sensors framework support"
+ 	depends on HID && HAS_IOMEM
+diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile
+index e4a21df..51fc941 100644
+--- a/drivers/hid/Makefile
++++ b/drivers/hid/Makefile
+@@ -98,6 +98,7 @@ obj-$(CONFIG_HID_ZYDACRON)	+= hid-zydacron.o
+ wacom-objs			:= wacom_wac.o wacom_sys.o
+ obj-$(CONFIG_HID_WACOM)		+= wacom.o
+ obj-$(CONFIG_HID_WALTOP)	+= hid-waltop.o
++obj-$(CONFIG_HID_GDIUM)		+= hid-gdium.o
+ obj-$(CONFIG_HID_WIIMOTE)	+= hid-wiimote.o
+ obj-$(CONFIG_HID_SENSOR_HUB)	+= hid-sensor-hub.o
+ obj-$(CONFIG_HID_SENSOR_CUSTOM_SENSOR)	+= hid-sensor-custom.o
+diff --git a/drivers/hid/hid-gdium.c b/drivers/hid/hid-gdium.c
+new file mode 100644
+index 0000000..67cc095
+--- /dev/null
++++ b/drivers/hid/hid-gdium.c
+@@ -0,0 +1,210 @@
++/*
++ * hid-gdium  --  Gdium laptop function keys
++ *
++ * Arnaud Patard <apatard@mandriva.com>
++ *
++ * Based on hid-apple.c
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ */
++
++
++#include <linux/device.h>
++#include <linux/hid.h>
++#include <linux/module.h>
++#include <linux/usb.h>
++
++#include "hid-ids.h"
++
++#define GDIUM_FN_ON	1
++
++static int fnmode = GDIUM_FN_ON;
++module_param(fnmode, int, 0644);
++MODULE_PARM_DESC(fnmode, "Mode of fn key on Gdium (0 = disabled, 1 = Enabled)");
++
++struct gdium_data {
++	unsigned int fn_on;
++};
++
++
++struct gdium_key_translation {
++	u16 from;
++	u16 to;
++};
++
++static struct gdium_key_translation gdium_fn_keys[] = {
++	{ KEY_F1,	KEY_CAMERA },
++	{ KEY_F2,	KEY_CONNECT },
++	{ KEY_F3,	KEY_MUTE },
++	{ KEY_F4,	KEY_VOLUMEUP},
++	{ KEY_F5,	KEY_VOLUMEDOWN },
++	{ KEY_F6,	KEY_SWITCHVIDEOMODE },
++	{ KEY_F7,	KEY_F19 }, /* F7+12. Have to use existant keycodes */
++	{ KEY_F8,	KEY_BRIGHTNESSUP },
++	{ KEY_F9,	KEY_BRIGHTNESSDOWN },
++	{ KEY_F10,	KEY_SLEEP },
++	{ KEY_F11,	KEY_PROG1 },
++	{ KEY_F12,	KEY_PROG2 },
++	{ KEY_UP,	KEY_PAGEUP },
++	{ KEY_DOWN,	KEY_PAGEDOWN },
++	{ KEY_INSERT,	KEY_NUMLOCK },
++	{ KEY_DELETE,	KEY_SCROLLLOCK },
++	{ KEY_T,	KEY_STOPCD },
++	{ KEY_F,	KEY_PREVIOUSSONG },
++	{ KEY_H,	KEY_NEXTSONG },
++	{ KEY_G,        KEY_PLAYPAUSE },
++	{ }
++};
++
++static struct gdium_key_translation *gdium_find_translation(
++		struct gdium_key_translation *table, u16 from)
++{
++	struct gdium_key_translation *trans;
++
++	/* Look for the translation */
++	for (trans = table; trans->from; trans++)
++		if (trans->from == from)
++			return trans;
++	return NULL;
++}
++
++static int hidinput_gdium_event(struct hid_device *hid, struct input_dev *input,
++		struct hid_usage *usage, __s32 value)
++{
++	struct gdium_data *data = hid_get_drvdata(hid);
++	struct gdium_key_translation *trans;
++	int do_translate;
++
++	if (usage->type != EV_KEY)
++		return 0;
++
++	if ((usage->code == KEY_FN)) {
++		data->fn_on = !!value;
++		input_event(input, usage->type, usage->code, value);
++		return 1;
++	}
++
++	if (fnmode) {
++		trans = gdium_find_translation(gdium_fn_keys, usage->code);
++		if (trans) {
++			do_translate = data->fn_on;
++			if (do_translate) {
++				input_event(input, usage->type, trans->to, value);
++				return 1;
++			}
++		}
++	}
++
++	return 0;
++}
++
++static int gdium_input_event(struct hid_device *hdev, struct hid_field *field,
++			struct hid_usage *usage, __s32 value)
++{
++	if (!(hdev->claimed & HID_CLAIMED_INPUT) || !field->hidinput || !usage->type)
++		return 0;
++
++	if (hidinput_gdium_event(hdev, field->hidinput->input, usage, value))
++		return 1;
++
++	return 0;
++}
++
++
++static void gdium_input_setup(struct input_dev *input)
++{
++	struct gdium_key_translation *trans;
++
++	set_bit(KEY_NUMLOCK, input->keybit);
++
++	/* Enable all needed keys */
++	for (trans = gdium_fn_keys; trans->from; trans++)
++		set_bit(trans->to, input->keybit);
++}
++
++static int gdium_input_mapping(struct hid_device *hdev, struct hid_input *hi,
++		struct hid_field *field, struct hid_usage *usage,
++		unsigned long **bit, int *max)
++{
++	if (((usage->hid & HID_USAGE_PAGE) == HID_UP_KEYBOARD)
++			&& ((usage->hid & HID_USAGE) == 0x82)) {
++		hid_map_usage_clear(hi, usage, bit, max, EV_KEY, KEY_FN);
++		gdium_input_setup(hi->input);
++		return 1;
++	}
++	return 0;
++}
++
++static int gdium_input_probe(struct hid_device *hdev, const struct hid_device_id *id)
++{
++	struct gdium_data *data;
++	int ret;
++
++	data = kzalloc(sizeof(*data), GFP_KERNEL);
++	if (!data) {
++		dev_err(&hdev->dev, "can't alloc gdium keyboard data\n");
++		return -ENOMEM;
++	}
++
++	hid_set_drvdata(hdev, data);
++
++	ret = hid_parse(hdev);
++	if (ret) {
++		dev_err(&hdev->dev, "parse failed\n");
++		goto err_free;
++	}
++
++	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
++	if (ret) {
++		dev_err(&hdev->dev, "hw start failed\n");
++		goto err_free;
++	}
++
++	return 0;
++err_free:
++	kfree(data);
++	return ret;
++}
++static void gdium_input_remove(struct hid_device *hdev)
++{
++	hid_hw_stop(hdev);
++	kfree(hid_get_drvdata(hdev));
++}
++
++static const struct hid_device_id gdium_input_devices[] = {
++	{ HID_USB_DEVICE(USB_VENDOR_ID_GDIUM, USB_DEVICE_ID_GDIUM) },
++	{}
++};
++MODULE_DEVICE_TABLE(hid, gdium_input_devices);
++
++static struct hid_driver gdium_input_driver = {
++	.name = "gdium-fnkeys",
++	.id_table = gdium_input_devices,
++	.probe = gdium_input_probe,
++	.remove = gdium_input_remove,
++	.event = gdium_input_event,
++	.input_mapping = gdium_input_mapping,
++};
++
++static int gdium_input_init(void)
++{
++	int ret;
++
++	ret = hid_register_driver(&gdium_input_driver);
++	if (ret)
++		 pr_err("can't register gdium keyboard driver\n");
++
++	return ret;
++}
++static void gdium_input_exit(void)
++{
++	hid_unregister_driver(&gdium_input_driver);
++}
++
++module_init(gdium_input_init);
++module_exit(gdium_input_exit);
++MODULE_LICENSE("GPL");
++
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index 7ce93d9..da52392 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -1031,6 +1031,9 @@
+ #define USB_VENDOR_ID_ZYTRONIC		0x14c8
+ #define USB_DEVICE_ID_ZYTRONIC_ZXY100	0x0005
+ 
++#define USB_VENDOR_ID_GDIUM		0x04B4
++#define USB_DEVICE_ID_GDIUM		0xe001
++
+ #define USB_VENDOR_ID_PRIMAX	0x0461
+ #define USB_DEVICE_ID_PRIMAX_MOUSE_4D22	0x4d22
+ #define USB_DEVICE_ID_PRIMAX_KEYBOARD	0x4e05
+diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
+index 91077ef..2cfd9ff 100644
+--- a/drivers/mfd/sm501.c
++++ b/drivers/mfd/sm501.c
+@@ -58,7 +58,7 @@ struct sm501_gpio {
+ struct sm501_gpio {
+ 	/* no gpio support, empty definition for sm501_devdata. */
+ };
+-#endif
++#endif	/* CONFIG_MFD_SM501_GPIO */
+ 
+ struct sm501_devdata {
+ 	spinlock_t			 reg_lock;
+@@ -1124,6 +1124,22 @@ static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
+ {
+ 	return sm->gpio.registered;
+ }
++
++void sm501_configure_gpio(struct device *dev, unsigned int gpio, unsigned
++		char mode)
++{
++	unsigned long set, reg, offset = gpio;
++
++	if (offset >= 32) {
++		reg = SM501_GPIO63_32_CONTROL;
++		offset = gpio - 32;
++	} else
++		reg = SM501_GPIO31_0_CONTROL;
++
++	set = mode ? 1 << offset : 0;
++
++	sm501_modify_reg(dev, reg, set, 0);
++}
+ #else
+ static inline int sm501_register_gpio(struct sm501_devdata *sm)
+ {
+@@ -1143,7 +1159,13 @@ static inline int sm501_gpio_isregistered(struct sm501_devdata *sm)
+ {
+ 	return 0;
+ }
+-#endif
++
++void sm501_configure_gpio(struct device *dev, unsigned int gpio,
++			 unsigned char mode)
++{
++}
++#endif	/* CONFIG_MFD_SM501_GPIO */
++EXPORT_SYMBOL_GPL(sm501_configure_gpio);
+ 
+ static int sm501_register_gpio_i2c_instance(struct sm501_devdata *sm,
+ 					    struct sm501_platdata_gpio_i2c *iic)
+@@ -1198,6 +1220,20 @@ static int sm501_register_gpio_i2c(struct sm501_devdata *sm,
+ 	return 0;
+ }
+ 
++/* register sm501 PWM device */
++static int sm501_register_pwm(struct sm501_devdata *sm)
++{
++	struct platform_device *pdev;
++
++	pdev = sm501_create_subdev(sm, "sm501-pwm", 2, 0);
++	if (!pdev)
++		return -ENOMEM;
++	sm501_create_subio(sm, &pdev->resource[0], 0x10020, 0xC);
++	sm501_create_irq(sm, &pdev->resource[1]);
++
++	return sm501_register_device(sm, pdev);
++}
++
+ /* sm501_dbg_regs
+  *
+  * Debug attribute to attach to parent device to show core registers
+@@ -1356,6 +1392,8 @@ static int sm501_init_dev(struct sm501_devdata *sm)
+ 			sm501_register_uart(sm, idata->devices);
+ 		if (idata->devices & SM501_USE_GPIO)
+ 			sm501_register_gpio(sm);
++		if (idata->devices & SM501_USE_PWM)
++			sm501_register_pwm(sm);
+ 	}
+ 
+ 	if (pdata && pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+@@ -1542,10 +1580,15 @@ static struct sm501_initdata sm501_pci_initdata = {
+ 	.devices	= SM501_USE_ALL,
+ 
+ 	/* Errata AB-3 says that 72MHz is the fastest available
+-	 * for 33MHZ PCI with proper bus-mastering operation */
+-
++	 * for 33MHZ PCI with proper bus-mastering operation
++	 * For gdium, it works under 84&112M clock freq.*/
++#ifdef CONFIG_DEXXON_GDIUM
++	.mclk		= 84 * MHZ,
++	.m1xclk		= 112 * MHZ,
++#else
+ 	.mclk		= 72 * MHZ,
+ 	.m1xclk		= 144 * MHZ,
++#endif
+ };
+ 
+ static struct sm501_platdata_fbsub sm501_pdata_fbsub = {
+diff --git a/drivers/platform/mips/Kconfig b/drivers/platform/mips/Kconfig
+index c80714b..70a607d 100644
+--- a/drivers/platform/mips/Kconfig
++++ b/drivers/platform/mips/Kconfig
+@@ -47,6 +47,17 @@ config LEMOTE_LYNLOONG2F
+ 	  size-fixed screen: 1360x768 with sisfb video driver. and also, it has
+ 	  its own specific suspend support.
+ 
++config GDIUM_LAPTOP
++	tristate "GDIUM laptop extras"
++	depends on DEXXON_GDIUM
++	select POWER_SUPPLY
++	select I2C
++	select INPUT_POLLDEV
++	default m
++	help
++	  This mini-driver drives the ST7 chipset present in the Gdium laptops.
++	  This gives battery support, wlan rfkill.
++
+ config MIPS_ACPI
+ 	bool
+ 	default y if LOONGSON_MACH3X
+diff --git a/drivers/platform/mips/Makefile b/drivers/platform/mips/Makefile
+index 0e21bfb..0bc93de 100644
+--- a/drivers/platform/mips/Makefile
++++ b/drivers/platform/mips/Makefile
+@@ -7,5 +7,7 @@ CFLAGS_yeeloong_laptop.o = -I$(srctree)/arch/mips/loongson/lemote-2f
+ 
+ obj-$(CONFIG_LEMOTE_LYNLOONG2F)	+= lynloong_pc.o
+ 
++obj-$(CONFIG_GDIUM_LAPTOP)	+= gdium_laptop.o
++
+ obj-$(CONFIG_MIPS_ACPI) += acpi_init.o
+ obj-$(CONFIG_CPU_HWMON) += cpu_hwmon.o
+diff --git a/drivers/platform/mips/gdium_laptop.c b/drivers/platform/mips/gdium_laptop.c
+new file mode 100644
+index 0000000..41a65ad
+--- /dev/null
++++ b/drivers/platform/mips/gdium_laptop.c
+@@ -0,0 +1,927 @@
++/*
++ * gdium_laptop  --  Gdium laptop extras
++ *
++ * Arnaud Patard <apatard@mandriva.com>
++ *
++ *  This program is free software; you can redistribute  it and/or modify it
++ *  under  the terms of  the GNU General  Public License as published by the
++ *  Free Software Foundation;  either version 2 of the  License, or (at your
++ *  option) any later version.
++ *
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/input-polldev.h>
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
++#include <linux/i2c.h>
++#include <linux/mutex.h>
++#include <linux/power_supply.h>
++#include <linux/workqueue.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <asm/gpio.h>
++
++/* For input device */
++#define SCAN_INTERVAL		150
++
++/* For battery status */
++#define BAT_SCAN_INTERVAL	500
++
++#define EC_FIRM_VERSION		0
++
++#if CONFIG_GDIUM_VERSION > 2
++#define EC_REG_BASE		1
++#else
++#define EC_REG_BASE		0
++#endif
++
++#define EC_STATUS		(EC_REG_BASE+0)
++#define EC_STATUS_LID		(1<<0)
++#define EC_STATUS_PWRBUT	(1<<1)
++#define EC_STATUS_BATID		(1<<2)		/* this bit has no real meaning on v2.         */
++						/* Same as EC_STATUS_ADAPT                     */
++						/* but on v3 it's BATID which mean bat present */
++#define EC_STATUS_SYS_POWER	(1<<3)
++#define EC_STATUS_WLAN		(1<<4)
++#define EC_STATUS_ADAPT		(1<<5)
++
++#define EC_CTRL			(EC_REG_BASE+1)
++#define EC_CTRL_DDR_CLK		(1<<0)
++#define EC_CTRL_CHARGE_LED	(1<<1)
++#define EC_CTRL_BEEP		(1<<2)
++#define EC_CTRL_SUSB		(1<<3)	/* memory power */
++#define EC_CTRL_TRICKLE		(1<<4)
++#define EC_CTRL_WLAN_EN		(1<<5)
++#define EC_CTRL_SUSC		(1<<6) /* main power */
++#define EC_CTRL_CHARGE_EN	(1<<7)
++
++#define EC_BAT_LOW		(EC_REG_BASE+2)
++#define EC_BAT_HIGH		(EC_REG_BASE+3)
++
++#define EC_SIGN			(EC_REG_BASE+4)
++#define EC_SIGN_OS		0xAE /* write 0xae to control pm stuff */
++#define EC_SIGN_EC		0x00 /* write 0x00 to let the st7 manage pm stuff */
++
++#if 0
++#define EC_TEST			(EC_REG_BASE+5) /* Depending on firmware version this register */
++						/* may be the programmation register so don't play */
++						/* with it */
++#endif
++
++#define BAT_VOLT_PRESENT	500000	/* Min voltage to consider battery present uV */
++#define BAT_MIN			7000000	/* Min battery voltage in uV */
++#define BAT_MIN_MV		7000	/* Min battery voltage in mV */
++#define BAT_TRICKLE_EN		8000000	/* Charging at 1.4A before  8.0V and then charging at 0.25A */
++#define BAT_MAX			7950000	/* Max battery voltage ~8V in V */
++#define BAT_MAX_MV		7950	/* Max battery voltage ~8V in V */
++#define BAT_READ_ERROR		300000	/* battery read error of 0.3V */
++#define BAT_READ_ERROR_MV	300	/* battery read error of 0.3V */
++
++#define SM502_WLAN_ON		(224+16)/* SM502 GPIO16 may be used on gdium v2 (v3?) as wlan_on */
++					/* when R422 is connected */
++
++static unsigned char verbose;
++static unsigned char gpio16;
++static unsigned char ec;
++module_param(verbose, byte, S_IRUGO | S_IWUSR);
++MODULE_PARM_DESC(verbose, "Add some debugging messages");
++module_param(gpio16, byte, S_IRUGO);
++MODULE_PARM_DESC(gpio16, "Enable wlan_on signal on SM502");
++module_param(ec, byte, S_IRUGO);
++MODULE_PARM_DESC(ec, "Let the ST7 handle the battery (default OS)");
++
++struct gdium_laptop_data {
++	struct i2c_client		*client;
++	struct input_polled_dev		*input_polldev;
++	struct dentry			*debugfs;
++	struct mutex			mutex;
++	struct platform_device		*bat_pdev;
++	struct power_supply		gdium_ac;
++	struct power_supply		gdium_battery;
++	struct workqueue_struct		*workqueue;
++	struct delayed_work		work;
++	char				charge_cmd;
++	/* important registers value */
++	char				status;
++	char				ctrl;
++	/* mV */
++	int				battery_level;
++	char				version;
++};
++
++/**********************************************************************/
++/* Low level I2C functions                                            */
++/* All are supposed to be called with mutex held                      */
++/**********************************************************************/
++/*
++ * Return battery voltage in mV
++ * >= 0 battery voltage
++ * < 0 error
++ */
++static s32 ec_read_battery(struct i2c_client *client)
++{
++	unsigned char bat_low, bat_high;
++	s32 data;
++	unsigned int ret;
++
++	/*
++	 * a = battery high
++	 * b = battery low
++	 * bat = a << 2 | b & 0x03;
++	 * battery voltage = (bat / 1024) * 5 * 2
++	 */
++	data = i2c_smbus_read_byte_data(client, EC_BAT_LOW);
++	if (data < 0) {
++		dev_err(&client->dev, "ec_read_bat: read bat_low failed\n");
++		return data;
++	}
++	bat_low = data & 0xff;
++	if (verbose)
++		dev_info(&client->dev, "bat_low %x\n", bat_low);
++
++	data = i2c_smbus_read_byte_data(client, EC_BAT_HIGH);
++	if (data < 0) {
++		dev_err(&client->dev, "ec_read_bat: read bat_high failed\n");
++		return data;
++	}
++	bat_high = data & 0xff;
++	if (verbose)
++		dev_info(&client->dev, "bat_high %x\n", bat_high);
++
++	ret = (bat_high << 2) | (bat_low & 3);
++	/*
++	 * mV
++	 */
++	ret = (ret * 5 * 2) * 1000 / 1024;
++
++	return ret;
++}
++
++static s32 ec_read_version(struct i2c_client *client)
++{
++#if CONFIG_GDIUM_VERSION > 2
++	return i2c_smbus_read_byte_data(client, EC_FIRM_VERSION);
++#else
++	return 0;
++#endif
++}
++
++static s32 ec_read_status(struct i2c_client *client)
++{
++	return i2c_smbus_read_byte_data(client, EC_STATUS);
++}
++
++static s32 ec_read_ctrl(struct i2c_client *client)
++{
++	return i2c_smbus_read_byte_data(client, EC_CTRL);
++}
++
++static s32 ec_write_ctrl(struct i2c_client *client, unsigned char newvalue)
++{
++	return i2c_smbus_write_byte_data(client, EC_CTRL, newvalue);
++}
++
++static s32 ec_read_sign(struct i2c_client *client)
++{
++	return i2c_smbus_read_byte_data(client, EC_SIGN);
++}
++
++static s32 ec_write_sign(struct i2c_client *client, unsigned char sign)
++{
++	unsigned char value;
++	s32 ret;
++
++	ret = i2c_smbus_write_byte_data(client, EC_SIGN, sign);
++	if (ret < 0) {
++		dev_err(&client->dev, "ec_set_control: write failed\n");
++		return ret;
++	}
++
++	value = ec_read_sign(client);
++	if (value != sign) {
++		dev_err(&client->dev, "Failed to set control to %s\n",
++				sign == EC_SIGN_OS ? "OS" : "EC");
++		return -EIO;
++	}
++
++	return 0;
++}
++
++#if 0
++static int ec_power_off(struct i2c_client *client)
++{
++	char value;
++	int ret;
++
++	value = ec_read_ctrl(client);
++	if (value < 0) {
++		dev_err(&client->dev, "ec_power_off: read failed\n");
++		return value;
++	}
++	value &= ~(EC_CTRL_SUSB | EC_CTRL_SUSC);
++	ret = ec_write_ctrl(client, value);
++	if (ret < 0) {
++		dev_err(&client->dev, "ec_power_off: write failed\n");
++		return ret;
++	}
++
++	return 0;
++}
++#endif
++
++static s32 ec_wlan_status(struct i2c_client *client)
++{
++	s32 value;
++
++	value = ec_read_ctrl(client);
++	if (value < 0)
++		return value;
++
++	return (value & EC_CTRL_WLAN_EN) ? 1 : 0;
++}
++
++static s32 ec_wlan_en(struct i2c_client *client, int on)
++{
++	s32 value;
++
++	value = ec_read_ctrl(client);
++	if (value < 0)
++		return value;
++
++	value &= ~EC_CTRL_WLAN_EN;
++	if (on)
++		value |= EC_CTRL_WLAN_EN;
++
++	return ec_write_ctrl(client, value&0xff);
++}
++
++#if 0
++static s32 ec_led_status(struct i2c_client *client)
++{
++	s32 value;
++
++	value = ec_read_ctrl(client);
++	if (value < 0)
++		return value;
++
++	return (value & EC_CTRL_CHARGE_LED) ? 1 : 0;
++}
++#endif
++
++/* Changing the charging led status has never worked */
++static s32 ec_led_en(struct i2c_client *client, int on)
++{
++#if 0
++	s32 value;
++
++	value = ec_read_ctrl(client);
++	if (value < 0)
++		return value;
++
++	value &= ~EC_CTRL_CHARGE_LED;
++	if (on)
++		value |= EC_CTRL_CHARGE_LED;
++	return ec_write_ctrl(client, value&0xff);
++#else
++	return 0;
++#endif
++}
++
++static s32 ec_charge_en(struct i2c_client *client, int on, int trickle)
++{
++	s32 value;
++	s32 set = 0;
++
++	value = ec_read_ctrl(client);
++	if (value < 0)
++		return value;
++
++	if (on)
++		set |= EC_CTRL_CHARGE_EN;
++	if (trickle)
++		set |= EC_CTRL_TRICKLE;
++
++	/* Be clever : don't change values if you don't need to */
++	if ((value & (EC_CTRL_CHARGE_EN | EC_CTRL_TRICKLE)) == set)
++		return 0;
++
++	value &= ~(EC_CTRL_CHARGE_EN | EC_CTRL_TRICKLE);
++	value |= set;
++	ec_led_en(client, on);
++	return ec_write_ctrl(client, (unsigned char)(value&0xff));
++
++}
++
++/**********************************************************************/
++/* Input functions                                                    */
++/**********************************************************************/
++struct gdium_keys {
++	int last_state;
++	int key_code;
++	int mask;
++	int type;
++};
++
++static struct gdium_keys gkeys[] = {
++	{
++		.key_code	= KEY_WLAN,
++		.mask		= EC_STATUS_WLAN,
++		.type		= EV_KEY,
++	},
++	{
++		.key_code	= KEY_POWER,
++		.mask		= EC_STATUS_PWRBUT,
++		.type		= EV_KEY, /*EV_PWR,*/
++	},
++	{
++		.key_code	= SW_LID,
++		.mask		= EC_STATUS_LID,
++		.type		= EV_SW,
++	},
++};
++
++static void gdium_laptop_keys_poll(struct input_polled_dev *dev)
++{
++	int state, i;
++	struct gdium_laptop_data *data = dev->private;
++	struct i2c_client *client = data->client;
++	struct input_dev *input = dev->input;
++	s32 status;
++
++	mutex_lock(&data->mutex);
++	status = ec_read_status(client);
++	mutex_unlock(&data->mutex);
++
++	if (status < 0) {
++		/*
++		 * Don't know exactly  which version of the firmware
++		 * has this bug but when the power button is pressed
++		 * there are i2c read errors :(
++		 */
++		if ((data->version >= 0x13) && !gkeys[1].last_state) {
++			input_event(input, EV_KEY, KEY_POWER, 1);
++			input_sync(input);
++			gkeys[1].last_state = 1;
++		}
++		return;
++	}
++
++	for (i = 0; i < ARRAY_SIZE(gkeys); i++) {
++		state = status & gkeys[i].mask;
++		if (state != gkeys[i].last_state) {
++			gkeys[i].last_state = state;
++			/* for power key, we want power & key press/release event */
++			if (gkeys[i].type == EV_PWR) {
++				input_event(input, EV_KEY, gkeys[i].key_code, !!state);
++				input_sync(input);
++			}
++			/* Disable wifi on key press but not key release */
++			/*
++			 * On firmware >= 0x13 the EC_STATUS_WLAN has it's
++			 * original meaning of Wifi status and no more the
++			 * wifi button status so we have to ignore the event
++			 * on theses versions
++			 */
++			if (state && (gkeys[i].key_code == KEY_WLAN) && (data->version < 0x13)) {
++				mutex_lock(&data->mutex);
++				ec_wlan_en(client, !ec_wlan_status(client));
++				if (gpio16)
++					gpio_set_value(SM502_WLAN_ON, !ec_wlan_status(client));
++				mutex_unlock(&data->mutex);
++			}
++
++			input_event(input, gkeys[i].type, gkeys[i].key_code, !!state);
++			input_sync(input);
++		}
++	}
++}
++
++static int gdium_laptop_input_init(struct gdium_laptop_data *data)
++{
++	struct i2c_client *client = data->client;
++	struct input_dev *input;
++	int ret, i;
++
++	data->input_polldev = input_allocate_polled_device();
++	if (!data->input_polldev) {
++		ret = -ENOMEM;
++		goto err;
++	}
++
++	input = data->input_polldev->input;
++	input->evbit[0] = BIT(EV_KEY) | BIT_MASK(EV_PWR) | BIT_MASK(EV_SW);
++	data->input_polldev->poll = gdium_laptop_keys_poll;
++	data->input_polldev->poll_interval = SCAN_INTERVAL;
++	data->input_polldev->private = data;
++	input->name = "gdium-keys";
++	input->dev.parent = &client->dev;
++
++	input->id.bustype = BUS_HOST;
++	input->id.vendor = 0x0001;
++	input->id.product = 0x0001;
++	input->id.version = 0x0100;
++
++	for (i = 0; i < ARRAY_SIZE(gkeys); i++)
++		input_set_capability(input, gkeys[i].type, gkeys[i].key_code);
++
++	ret = input_register_polled_device(data->input_polldev);
++	if (ret) {
++		dev_err(&client->dev, "Unable to register button device\n");
++		goto err_poll_dev;
++	}
++
++	return 0;
++
++err_poll_dev:
++	input_free_polled_device(data->input_polldev);
++err:
++	return ret;
++}
++
++static void gdium_laptop_input_exit(struct gdium_laptop_data *data)
++{
++	input_unregister_polled_device(data->input_polldev);
++	input_free_polled_device(data->input_polldev);
++}
++
++/**********************************************************************/
++/* Battery management                                                 */
++/**********************************************************************/
++static int gdium_ac_get_props(struct power_supply *psy,
++		enum power_supply_property psp,
++		union power_supply_propval *val)
++{
++	char status;
++	struct gdium_laptop_data *data = container_of(psy, struct gdium_laptop_data, gdium_ac);
++	int ret = 0;
++
++	if (!data) {
++		pr_err("gdium-ac: gdium_laptop_data not found\n");
++		return -EINVAL;
++	}
++
++	status = data->status;
++	switch (psp) {
++	case POWER_SUPPLY_PROP_ONLINE:
++		val->intval = !!(status & EC_STATUS_ADAPT);
++		break;
++	default:
++		ret = -EINVAL;
++		break;
++	}
++
++	return ret;
++}
++
++#undef RET
++#define RET (val->intval)
++
++static int gdium_battery_get_props(struct power_supply *psy,
++		enum power_supply_property psp,
++		union power_supply_propval *val)
++{
++	char status, ctrl;
++	struct gdium_laptop_data *data = container_of(psy, struct gdium_laptop_data, gdium_battery);
++	int percentage_capacity = 0, charge_now = 0, time_to_empty = 0;
++	int ret = 0, tmp;
++
++	if (!data) {
++		pr_err("gdium-battery: gdium_laptop_data not found\n");
++		return -EINVAL;
++	}
++
++	status = data->status;
++	ctrl   = data->ctrl;
++	switch (psp) {
++	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
++		/* uAh */
++		RET = 5000000;
++		break;
++	case POWER_SUPPLY_PROP_CURRENT_NOW:
++	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
++		/* This formula is gotten by gnuplot with the statistic data */
++		time_to_empty = (data->battery_level - BAT_MIN_MV + BAT_READ_ERROR_MV) * 113 - 29870;
++		if (psp == POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW) {
++			/* seconds */
++			RET = time_to_empty / 10;
++			break;
++		}
++		/* fall through */
++	case POWER_SUPPLY_PROP_CHARGE_NOW:
++	case POWER_SUPPLY_PROP_CAPACITY: {
++		tmp = data->battery_level * 1000;
++		/* > BAT_MIN to avoid negative values */
++		percentage_capacity = 0;
++		if ((status & EC_STATUS_BATID) && (tmp > BAT_MIN))
++			percentage_capacity = (tmp-BAT_MIN)*100/(BAT_MAX-BAT_MIN);
++
++		if (percentage_capacity > 100)
++			percentage_capacity = 100;
++
++		if (psp == POWER_SUPPLY_PROP_CAPACITY) {
++			RET = percentage_capacity;
++			break;
++		}
++		charge_now = 50000 * percentage_capacity;
++		if (psp == POWER_SUPPLY_PROP_CHARGE_NOW) {
++			/* uAh */
++			RET = charge_now;
++			break;
++		}
++	}	/* fall through */
++	case POWER_SUPPLY_PROP_STATUS: {
++		if (status & EC_STATUS_ADAPT)
++			if (ctrl & EC_CTRL_CHARGE_EN)
++				RET = POWER_SUPPLY_STATUS_CHARGING;
++			else
++				RET = POWER_SUPPLY_STATUS_NOT_CHARGING;
++		else
++			RET = POWER_SUPPLY_STATUS_DISCHARGING;
++
++		if (psp == POWER_SUPPLY_PROP_STATUS)
++			break;
++		/* mAh -> µA */
++		switch (RET) {
++		case POWER_SUPPLY_STATUS_CHARGING:
++			RET = -(data->charge_cmd == 2) ? 1400000 : 250000;
++			break;
++		case POWER_SUPPLY_STATUS_DISCHARGING:
++			RET = charge_now / time_to_empty * 36000;
++			break;
++		case POWER_SUPPLY_STATUS_NOT_CHARGING:
++		default:
++			RET = 0;
++			break;
++		}
++	} break;
++	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
++		RET = BAT_MAX+BAT_READ_ERROR;
++		break;
++	case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
++		RET = BAT_MIN-BAT_READ_ERROR;
++		break;
++	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
++		/* mV -> uV */
++		RET = data->battery_level * 1000;
++		break;
++	case POWER_SUPPLY_PROP_PRESENT:
++#if CONFIG_GDIUM_VERSION > 2
++		RET = !!(status & EC_STATUS_BATID);
++#else
++		RET = !!(data->battery_level > BAT_VOLT_PRESENT);
++#endif
++		break;
++	case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
++		tmp = data->battery_level * 1000;
++		RET = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
++		if (status & EC_STATUS_BATID) {
++			if (tmp >= BAT_MAX) {
++				RET = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
++				if (tmp >= BAT_MAX+BAT_READ_ERROR)
++					RET = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
++			} else if (tmp <= BAT_MIN+BAT_READ_ERROR) {
++				RET = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
++				if (tmp <= BAT_MIN)
++					RET = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
++			} else
++				RET = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
++		}
++		break;
++	case POWER_SUPPLY_PROP_CHARGE_TYPE:
++		if (ctrl & EC_CTRL_TRICKLE)
++			RET = POWER_SUPPLY_CHARGE_TYPE_TRICKLE;
++		else if (ctrl & EC_CTRL_CHARGE_EN)
++			RET = POWER_SUPPLY_CHARGE_TYPE_FAST;
++		else
++			RET = POWER_SUPPLY_CHARGE_TYPE_NONE;
++		break;
++	case POWER_SUPPLY_PROP_CURRENT_MAX:
++		/* 1.4A ? */
++		RET = 1400000;
++		break;
++	default:
++		break;
++	}
++
++	return ret;
++}
++#undef RET
++
++static enum power_supply_property gdium_ac_props[] = {
++	POWER_SUPPLY_PROP_ONLINE,
++};
++
++static enum power_supply_property gdium_battery_props[] = {
++	POWER_SUPPLY_PROP_STATUS,
++	POWER_SUPPLY_PROP_PRESENT,
++	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
++	POWER_SUPPLY_PROP_CHARGE_NOW,
++	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
++	POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
++	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
++	POWER_SUPPLY_PROP_VOLTAGE_NOW,
++	POWER_SUPPLY_PROP_CURRENT_MAX,
++	POWER_SUPPLY_PROP_CURRENT_NOW,
++	POWER_SUPPLY_PROP_CAPACITY,
++	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
++	POWER_SUPPLY_PROP_CHARGE_TYPE,
++};
++
++static void gdium_laptop_battery_work(struct work_struct *work)
++{
++	struct gdium_laptop_data *data = container_of(work, struct gdium_laptop_data, work.work);
++	struct i2c_client *client;
++	int ret;
++	char old_status, old_charge_cmd;
++	char present;
++	s32 status;
++
++	mutex_lock(&data->mutex);
++	client	= data->client;
++	status	= ec_read_status(client);
++	ret	= ec_read_battery(client);
++
++	if ((status < 0) || (ret < 0))
++		goto i2c_read_error;
++
++	old_status = data->status;
++	old_charge_cmd = data->charge_cmd;
++	data->status = status;
++
++	/*
++	 * Charge only if :
++	 * - battery present
++	 * - ac adapter plugged in
++	 * - battery not fully charged
++	 */
++#if CONFIG_GDIUM_VERSION > 2
++	present = !!(data->status & EC_STATUS_BATID);
++#else
++	present = !!(ret > BAT_VOLT_PRESENT);
++#endif
++	data->battery_level = 0;
++	if (present) {
++		data->battery_level = (unsigned int)ret;
++		if (data->status & EC_STATUS_ADAPT)
++			data->battery_level -= BAT_READ_ERROR_MV;
++	}
++
++	data->charge_cmd = 0;
++	if ((data->status & EC_STATUS_ADAPT) && present && (data->battery_level <= BAT_MAX_MV))
++		data->charge_cmd = (ret < BAT_TRICKLE_EN) ? 2 : 3;
++
++	ec_charge_en(client, (data->charge_cmd >> 1) & 1, data->charge_cmd & 1);
++
++	/*
++	 * data->ctrl must be set _after_ calling ec_charge_en as this will change the
++	 * control register content
++	 */
++	data->ctrl = ec_read_ctrl(client);
++
++	if ((data->status & EC_STATUS_ADAPT) != (old_status & EC_STATUS_ADAPT)) {
++		power_supply_changed(&data->gdium_ac);
++		/* Send charging/discharging state change */
++		power_supply_changed(&data->gdium_battery);
++	} else if ((data->status & EC_STATUS_ADAPT) &&
++			((old_charge_cmd&2) != (data->charge_cmd&2)))
++		power_supply_changed(&data->gdium_battery);
++
++i2c_read_error:
++	mutex_unlock(&data->mutex);
++	queue_delayed_work(data->workqueue, &data->work, msecs_to_jiffies(BAT_SCAN_INTERVAL));
++}
++
++static int gdium_laptop_battery_init(struct gdium_laptop_data *data)
++{
++	int ret;
++
++	data->bat_pdev = platform_device_register_simple("gdium-battery", 0, NULL, 0);
++	if (IS_ERR(data->bat_pdev))
++		return PTR_ERR(data->bat_pdev);
++
++	data->gdium_battery.name		= data->bat_pdev->name;
++	data->gdium_battery.properties		= gdium_battery_props;
++	data->gdium_battery.num_properties	= ARRAY_SIZE(gdium_battery_props);
++	data->gdium_battery.get_property	= gdium_battery_get_props;
++	data->gdium_battery.use_for_apm		= 1;
++
++	ret = power_supply_register(&data->bat_pdev->dev, &data->gdium_battery);
++	if (ret)
++		goto err_platform;
++
++	data->gdium_ac.name			= "gdium-ac";
++	data->gdium_ac.type			= POWER_SUPPLY_TYPE_MAINS;
++	data->gdium_ac.properties		= gdium_ac_props;
++	data->gdium_ac.num_properties		= ARRAY_SIZE(gdium_ac_props);
++	data->gdium_ac.get_property		= gdium_ac_get_props;
++/*	data->gdium_ac.use_for_apm_ac		= 1,	*/
++
++	ret = power_supply_register(&data->bat_pdev->dev, &data->gdium_ac);
++	if (ret)
++		goto err_battery;
++
++	if (!ec) {
++		INIT_DELAYED_WORK(&data->work, gdium_laptop_battery_work);
++		data->workqueue = create_singlethread_workqueue("gdium-battery-work");
++		if (!data->workqueue) {
++			ret = -ESRCH;
++			goto err_work;
++		}
++		queue_delayed_work(data->workqueue, &data->work, msecs_to_jiffies(BAT_SCAN_INTERVAL));
++	}
++
++	return 0;
++
++err_work:
++err_battery:
++	power_supply_unregister(&data->gdium_battery);
++err_platform:
++	platform_device_unregister(data->bat_pdev);
++
++	return ret;
++}
++static void gdium_laptop_battery_exit(struct gdium_laptop_data *data)
++{
++	if (!ec) {
++		cancel_rearming_delayed_workqueue(data->workqueue, &data->work);
++		destroy_workqueue(data->workqueue);
++	}
++	power_supply_unregister(&data->gdium_battery);
++	power_supply_unregister(&data->gdium_ac);
++	platform_device_unregister(data->bat_pdev);
++}
++
++/* Debug fs */
++static int gdium_laptop_regs_show(struct seq_file *s, void *p)
++{
++	struct gdium_laptop_data *data = s->private;
++	struct i2c_client *client = data->client;
++
++	mutex_lock(&data->mutex);
++	seq_printf(s, "Version    : 0x%02x\n", (unsigned char)ec_read_version(client));
++	seq_printf(s, "Status     : 0x%02x\n", (unsigned char)ec_read_status(client));
++	seq_printf(s, "Ctrl       : 0x%02x\n", (unsigned char)ec_read_ctrl(client));
++	seq_printf(s, "Sign       : 0x%02x\n", (unsigned char)ec_read_sign(client));
++	seq_printf(s, "Bat Lo     : 0x%02x\n", (unsigned char)i2c_smbus_read_byte_data(client, EC_BAT_LOW));
++	seq_printf(s, "Bat Hi     : 0x%02x\n", (unsigned char)i2c_smbus_read_byte_data(client, EC_BAT_HIGH));
++	seq_printf(s, "Battery    : %d uV\n",  (unsigned int)ec_read_battery(client) * 1000);
++	seq_printf(s, "Charge cmd : %s %s\n", data->charge_cmd & 2 ? "C" : " ", data->charge_cmd & 1 ? "T" : " ");
++
++	mutex_unlock(&data->mutex);
++	return 0;
++}
++
++static int gdium_laptop_regs_open(struct inode *inode,
++					 struct file *file)
++{
++	return single_open(file, gdium_laptop_regs_show, inode->i_private);
++}
++
++static const struct file_operations gdium_laptop_regs_fops = {
++	.open		= gdium_laptop_regs_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= single_release,
++	.owner		= THIS_MODULE,
++};
++
++
++static int gdium_laptop_probe(struct i2c_client *client, const struct i2c_device_id *id)
++{
++	struct gdium_laptop_data *data;
++	int ret;
++
++	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
++		dev_err(&client->dev,
++				"%s: no smbus_byte support !\n", __func__);
++		return -ENODEV;
++	}
++
++	data = kzalloc(sizeof(struct gdium_laptop_data), GFP_KERNEL);
++	if (!data)
++		return -ENOMEM;
++
++	i2c_set_clientdata(client, data);
++	data->client = client;
++	mutex_init(&data->mutex);
++
++	ret = ec_read_version(client);
++	if (ret < 0)
++		goto err_alloc;
++
++	data->version = (unsigned char)ret;
++
++	ret = gdium_laptop_input_init(data);
++	if (ret)
++		goto err_alloc;
++
++	ret = gdium_laptop_battery_init(data);
++	if (ret)
++		goto err_input;
++
++
++	if (!ec) {
++		ret = ec_write_sign(client, EC_SIGN_OS);
++		if (ret)
++			goto err_sign;
++	}
++
++	if (gpio16) {
++		ret = gpio_request(SM502_WLAN_ON, "wlan-on");
++		if (ret < 0)
++			goto err_sign;
++		gpio_set_value(SM502_WLAN_ON, ec_wlan_status(client));
++		gpio_direction_output(SM502_WLAN_ON, 1);
++	}
++
++	dev_info(&client->dev, "Found firmware 0x%02x\n", data->version);
++	data->debugfs = debugfs_create_file("gdium_laptop", S_IFREG | S_IRUGO,
++				NULL, data, &gdium_laptop_regs_fops);
++
++	return 0;
++
++err_sign:
++	gdium_laptop_battery_exit(data);
++err_input:
++	gdium_laptop_input_exit(data);
++err_alloc:
++	kfree(data);
++	return ret;
++}
++
++static int gdium_laptop_remove(struct i2c_client *client)
++{
++	struct gdium_laptop_data *data = i2c_get_clientdata(client);
++
++	if (gpio16)
++		gpio_free(SM502_WLAN_ON);
++	ec_write_sign(client, EC_SIGN_EC);
++	if (data->debugfs)
++		debugfs_remove(data->debugfs);
++
++	gdium_laptop_battery_exit(data);
++	gdium_laptop_input_exit(data);
++
++	kfree(data);
++	return 0;
++}
++
++#ifdef CONFIG_PM
++static int gdium_laptop_suspend(struct i2c_client *client, pm_message_t msg)
++{
++	struct gdium_laptop_data *data = i2c_get_clientdata(client);
++
++	if (!ec)
++		cancel_rearming_delayed_workqueue(data->workqueue, &data->work);
++	return 0;
++}
++
++static int gdium_laptop_resume(struct i2c_client *client)
++{
++	struct gdium_laptop_data *data = i2c_get_clientdata(client);
++
++	if (!ec)
++		queue_delayed_work(data->workqueue, &data->work, msecs_to_jiffies(BAT_SCAN_INTERVAL));
++	return 0;
++}
++#else
++#define gdium_laptop_suspend NULL
++#define gdium_laptop_resume NULL
++#endif
++static const struct i2c_device_id gdium_id[] = {
++	{ "gdium-laptop" },
++	{},
++};
++MODULE_DEVICE_TABLE(i2c, gdium_id);
++
++static struct i2c_driver gdium_laptop_driver = {
++	.driver = {
++		.name = "gdium-laptop",
++		.owner = THIS_MODULE,
++	},
++	.probe = gdium_laptop_probe,
++	.remove = gdium_laptop_remove,
++	.shutdown = gdium_laptop_remove,
++	.suspend = gdium_laptop_suspend,
++	.resume = gdium_laptop_resume,
++	.id_table = gdium_id,
++};
++
++static int __init gdium_laptop_init(void)
++{
++	return i2c_add_driver(&gdium_laptop_driver);
++}
++
++static void __exit gdium_laptop_exit(void)
++{
++	i2c_del_driver(&gdium_laptop_driver);
++}
++
++module_init(gdium_laptop_init);
++module_exit(gdium_laptop_exit);
++
++MODULE_AUTHOR("Arnaud Patard <apatard@mandriva.com>");
++MODULE_DESCRIPTION("Gdium laptop extras");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
+index 0fe4ad8..45e46d4 100644
+--- a/drivers/rtc/Kconfig
++++ b/drivers/rtc/Kconfig
+@@ -737,6 +737,7 @@ comment "Platform RTC drivers"
+ config RTC_DRV_CMOS
+ 	tristate "PC-style 'CMOS'"
+ 	depends on X86 || ARM || M32R || PPC || MIPS || SPARC64
++	depends on !DEXXON_GDIUM
+ 	default y if X86
+ 	help
+ 	  Say "yes" here to get direct support for the real time clock
+diff --git a/include/linux/sm501.h b/include/linux/sm501.h
+index 02fde50..a8677f0 100644
+--- a/include/linux/sm501.h
++++ b/include/linux/sm501.h
+@@ -27,6 +27,9 @@ extern unsigned long sm501_set_clock(struct device *dev,
+ extern unsigned long sm501_find_clock(struct device *dev,
+ 				      int clksrc, unsigned long req_freq);
+ 
++extern void sm501_configure_gpio(struct device *dev,
++				unsigned int gpio, unsigned char mode);
++
+ /* sm501_misc_control
+  *
+  * Modify the SM501's MISC_CONTROL register
+@@ -122,6 +125,7 @@ struct sm501_reg_init {
+ #define SM501_USE_AC97		(1<<7)
+ #define SM501_USE_I2S		(1<<8)
+ #define SM501_USE_GPIO		(1<<9)
++#define SM501_USE_PWM		(1<<10)
+ 
+ #define SM501_USE_ALL		(0xffffffff)
+ 
+-- 
+2.4.3
+
diff --git a/gnu/packages/patches/linux-libre-loongson2-cpufreq-fix.patch b/gnu/packages/patches/linux-libre-loongson2-cpufreq-fix.patch
new file mode 100644
index 0000000000..e94b31dde8
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-loongson2-cpufreq-fix.patch
@@ -0,0 +1,59 @@
+From acda4b2b30a1dbb61e5600bc787a98b705564d7a Mon Sep 17 00:00:00 2001
+From: Alexandre Oliva <lxoliva@fsfla.org>
+Date: Fri, 22 Aug 2014 19:11:21 -0300
+Subject: [PATCH 4/9] loongson2 cpufreq: unregister on init failure
+
+If the loongson2_cpufreq module fails to init, e.g. because
+any of the cpufreq_register functions fail, it must unregister
+so that the module is unloaded successfully and no misinitialized
+device remains in the udev device list.  Fixed.
+
+Signed-off-by: Alexandre Oliva <lxoliva@fsfla.org>
+---
+ drivers/cpufreq/loongson2_cpufreq.c | 20 ++++++++++++++++----
+ 1 file changed, 16 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c
+index fc897ba..ac60f6b 100644
+--- a/drivers/cpufreq/loongson2_cpufreq.c
++++ b/drivers/cpufreq/loongson2_cpufreq.c
+@@ -161,20 +161,32 @@ static int __init cpufreq_init(void)
+ 	/* Register platform stuff */
+ 	ret = platform_driver_register(&platform_driver);
+ 	if (ret)
+-		return ret;
++		goto err_return;
+ 
+ 	pr_info("cpufreq: Loongson-2F CPU frequency driver.\n");
+ 
+-	cpufreq_register_notifier(&loongson2_cpufreq_notifier_block,
+-				  CPUFREQ_TRANSITION_NOTIFIER);
++	ret = cpufreq_register_notifier(&loongson2_cpufreq_notifier_block,
++					CPUFREQ_TRANSITION_NOTIFIER);
++	if (ret)
++		goto err_platform_driver_unregister;
+ 
+ 	ret = cpufreq_register_driver(&loongson2_cpufreq_driver);
++	if (ret)
++		goto err_cpufreq_unregister_notifier;
+ 
+-	if (!ret && !nowait) {
++	if (!nowait) {
+ 		saved_cpu_wait = cpu_wait;
+ 		cpu_wait = loongson2_cpu_wait;
+ 	}
+ 
++	return 0;
++
++ err_cpufreq_unregister_notifier:
++	cpufreq_unregister_notifier(&loongson2_cpufreq_notifier_block,
++				    CPUFREQ_TRANSITION_NOTIFIER);
++ err_platform_driver_unregister:
++	platform_driver_unregister(&platform_driver);
++ err_return:
+ 	return ret;
+ }
+ 
+-- 
+2.4.3
+
diff --git a/gnu/packages/patches/linux-libre-loongson2-math-emu.patch b/gnu/packages/patches/linux-libre-loongson2-math-emu.patch
new file mode 100644
index 0000000000..7685d08760
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-loongson2-math-emu.patch
@@ -0,0 +1,386 @@
+From fd6faa493baa986e43d011f7bc84c3fe3b811b2b Mon Sep 17 00:00:00 2001
+From: Mark H Weaver <mhw@netris.org>
+Date: Thu, 6 Aug 2015 01:28:10 -0400
+Subject: [PATCH 3/9] Support Loongson2f floating-point instructions in
+ mips/math-emu.
+
+* (arch/mips/include/asm/inst.h): Add Loongson2f function field values
+  for madd/msub/nmadd/nmsub that use the spec2 opcode, and the
+  Loongson2f/MIPS-5 format field value for paired-single
+  floating-point operations.
+
+* (arch/mips/math-emu/cp1emu.c): Add support for the Loongson2f
+  instructions for madd/msub/nmadd/nmsub, which use the spec2 opcode.
+  Also add support for the Loongson2f instructions that use the
+  paired-single floating-point format.
+---
+ arch/mips/include/uapi/asm/inst.h |   4 +-
+ arch/mips/math-emu/cp1emu.c       | 281 +++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 283 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
+index 9b6ccbd..99e6430 100644
+--- a/arch/mips/include/uapi/asm/inst.h
++++ b/arch/mips/include/uapi/asm/inst.h
+@@ -65,6 +65,8 @@ enum spec_op {
+ enum spec2_op {
+ 	madd_op, maddu_op, mul_op, spec2_3_unused_op,
+ 	msub_op, msubu_op, /* more unused ops */
++	loongson_madd_op = 0x18, loongson_msub_op,
++	loongson_nmadd_op, loongson_nmsub_op,
+ 	clz_op = 0x20, clo_op,
+ 	dclz_op = 0x24, dclo_op,
+ 	sdbpp_op = 0x3f
+@@ -151,7 +153,7 @@ enum cop0_com_func {
+  */
+ enum cop1_fmt {
+ 	s_fmt, d_fmt, e_fmt, q_fmt,
+-	w_fmt, l_fmt
++	w_fmt, l_fmt, ps_fmt
+ };
+ 
+ /*
+diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
+index ed82f0e..86ec4f2 100644
+--- a/arch/mips/math-emu/cp1emu.c
++++ b/arch/mips/math-emu/cp1emu.c
+@@ -7,6 +7,9 @@
+  * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
+  * Copyright (C) 2000  MIPS Technologies, Inc.
+  *
++ * Loongson instruction support
++ * Copyright (C) 2011  Mark H Weaver <mhw@netris.org>
++ *
+  *  This program is free software; you can distribute it and/or modify it
+  *  under the terms of the GNU General Public License (Version 2) as
+  *  published by the Free Software Foundation.
+@@ -61,6 +64,11 @@ static int fpu_emu(struct pt_regs *, struct mips_fpu_struct *,
+ static int fpux_emu(struct pt_regs *,
+ 	struct mips_fpu_struct *, mips_instruction, void *__user *);
+ 
++#ifdef CONFIG_MACH_LOONGSON
++static int loongson_spec2_emu(struct pt_regs *,
++	struct mips_fpu_struct *, mips_instruction, void *__user *);
++#endif
++
+ /* Control registers */
+ 
+ #define FPCREG_RID	0	/* $0  = revision id */
+@@ -843,6 +851,14 @@ do {									\
+ #define DPFROMREG(dp, x)	DIFROMREG((dp).bits, x)
+ #define DPTOREG(dp, x)	DITOREG((dp).bits, x)
+ 
++/* Support for Loongson paired single floating-point format */
++#define PSIFROMREG(si1, si2, x) ({ u64 di; DIFROMREG(di, x);		\
++			(si1) = (u32)di; (si2) = (u32)(di >> 32); })
++#define PSITOREG(si1, si2, x) DITOREG((si1) | ((u64)(si2) << 32), x)
++
++#define PSPFROMREG(sp1, sp2, x) PSIFROMREG((sp1).bits, (sp2).bits, x)
++#define PSPTOREG(sp1, sp2, x)	PSITOREG((sp1).bits, (sp2).bits, x)
++
+ /*
+  * Emulate a CFC1 instruction.
+  */
+@@ -1367,6 +1383,16 @@ emul:
+ 			xcp->regs[MIPSInst_RD(ir)] =
+ 				xcp->regs[MIPSInst_RS(ir)];
+ 		break;
++
++#ifdef CONFIG_MACH_LOONGSON
++	case spec2_op:{
++		int sig = loongson_spec2_emu(xcp, ctx, ir, fault_addr);
++		if (sig)
++			return sig;
++		break;
++	}
++#endif
++
+ 	default:
+ sigill:
+ 		return SIGILL;
+@@ -1444,6 +1470,172 @@ DEF3OP(msub, dp, ieee754dp_mul, ieee754dp_sub, );
+ DEF3OP(nmadd, dp, ieee754dp_mul, ieee754dp_add, ieee754dp_neg);
+ DEF3OP(nmsub, dp, ieee754dp_mul, ieee754dp_sub, ieee754dp_neg);
+ 
++#ifdef CONFIG_MACH_LOONGSON
++static int loongson_spec2_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
++	mips_instruction ir, void *__user *fault_addr)
++{
++	int rfmt;		/* resulting format */
++	unsigned rcsr = 0;	/* resulting csr */
++	union {
++		union ieee754dp d;
++		struct {
++			union ieee754sp s;
++			union ieee754sp s2;
++		};
++	} rv;			/* resulting value */
++
++	/* XXX maybe add a counter for loongson spec2 fp instructions? */
++	/* MIPS_FPU_EMU_INC_STATS(cp1xops); */
++
++	switch (rfmt = (MIPSInst_FFMT(ir) & 0xf)) {
++	case s_fmt:{
++		union ieee754sp(*handler) (union ieee754sp, union ieee754sp, union ieee754sp);
++		union ieee754sp fd, fs, ft;
++
++		switch (MIPSInst_FUNC(ir)) {
++		case loongson_madd_op:
++			handler = fpemu_sp_madd;
++			goto scoptop;
++		case loongson_msub_op:
++			handler = fpemu_sp_msub;
++			goto scoptop;
++		case loongson_nmadd_op:
++			handler = fpemu_sp_nmadd;
++			goto scoptop;
++		case loongson_nmsub_op:
++			handler = fpemu_sp_nmsub;
++			goto scoptop;
++
++		      scoptop:
++			SPFROMREG(fd, MIPSInst_FD(ir));
++			SPFROMREG(fs, MIPSInst_FS(ir));
++			SPFROMREG(ft, MIPSInst_FT(ir));
++			rv.s = (*handler) (fd, fs, ft);
++
++		      copcsr:
++			if (ieee754_cxtest(IEEE754_INEXACT))
++				rcsr |= FPU_CSR_INE_X | FPU_CSR_INE_S;
++			if (ieee754_cxtest(IEEE754_UNDERFLOW))
++				rcsr |= FPU_CSR_UDF_X | FPU_CSR_UDF_S;
++			if (ieee754_cxtest(IEEE754_OVERFLOW))
++				rcsr |= FPU_CSR_OVF_X | FPU_CSR_OVF_S;
++			if (ieee754_cxtest(IEEE754_INVALID_OPERATION))
++				rcsr |= FPU_CSR_INV_X | FPU_CSR_INV_S;
++
++			break;
++
++		default:
++			return SIGILL;
++		}
++		break;
++	}
++
++	case d_fmt:{
++		union ieee754dp(*handler) (union ieee754dp, union ieee754dp, union ieee754dp);
++		union ieee754dp fd, fs, ft;
++
++		switch (MIPSInst_FUNC(ir)) {
++		case loongson_madd_op:
++			handler = fpemu_dp_madd;
++			goto dcoptop;
++		case loongson_msub_op:
++			handler = fpemu_dp_msub;
++			goto dcoptop;
++		case loongson_nmadd_op:
++			handler = fpemu_dp_nmadd;
++			goto dcoptop;
++		case loongson_nmsub_op:
++			handler = fpemu_dp_nmsub;
++			goto dcoptop;
++
++		      dcoptop:
++			DPFROMREG(fd, MIPSInst_FD(ir));
++			DPFROMREG(fs, MIPSInst_FS(ir));
++			DPFROMREG(ft, MIPSInst_FT(ir));
++			rv.d = (*handler) (fd, fs, ft);
++			goto copcsr;
++
++		default:
++			return SIGILL;
++		}
++		break;
++	}
++
++	case ps_fmt:{
++		union ieee754sp(*handler) (union ieee754sp, union ieee754sp, union ieee754sp);
++		struct _ieee754_csr ieee754_csr_save;
++		union ieee754sp fd1, fs1, ft1;
++		union ieee754sp fd2, fs2, ft2;
++
++		switch (MIPSInst_FUNC(ir)) {
++		case loongson_madd_op:
++			handler = fpemu_sp_madd;
++			goto pscoptop;
++		case loongson_msub_op:
++			handler = fpemu_sp_msub;
++			goto pscoptop;
++		case loongson_nmadd_op:
++			handler = fpemu_sp_nmadd;
++			goto pscoptop;
++		case loongson_nmsub_op:
++			handler = fpemu_sp_nmsub;
++			goto pscoptop;
++
++		      pscoptop:
++			PSPFROMREG(fd1, fd2, MIPSInst_FD(ir));
++			PSPFROMREG(fs1, fs2, MIPSInst_FS(ir));
++			PSPFROMREG(ft1, ft2, MIPSInst_FT(ir));
++			rv.s = (*handler) (fd1, fs1, ft1);
++			ieee754_csr_save = ieee754_csr;
++			rv.s2 = (*handler) (fd2, fs2, ft2);
++			ieee754_csr.cx |= ieee754_csr_save.cx;
++			ieee754_csr.sx |= ieee754_csr_save.sx;
++			goto copcsr;
++
++		default:
++			return SIGILL;
++		}
++		break;
++	}
++
++	default:
++		return SIGILL;
++	}
++
++	/*
++	 * Update the fpu CSR register for this operation.
++	 * If an exception is required, generate a tidy SIGFPE exception,
++	 * without updating the result register.
++	 * Note: cause exception bits do not accumulate, they are rewritten
++	 * for each op; only the flag/sticky bits accumulate.
++	 */
++	ctx->fcr31 = (ctx->fcr31 & ~FPU_CSR_ALL_X) | rcsr;
++	if ((ctx->fcr31 >> 5) & ctx->fcr31 & FPU_CSR_ALL_E) {
++		/*printk ("SIGFPE: fpu csr = %08x\n",ctx->fcr31); */
++		return SIGFPE;
++	}
++
++	/*
++	 * Now we can safely write the result back to the register file.
++	 */
++	switch (rfmt) {
++	case d_fmt:
++		DPTOREG(rv.d, MIPSInst_FD(ir));
++		break;
++	case s_fmt:
++		SPTOREG(rv.s, MIPSInst_FD(ir));
++		break;
++	case ps_fmt:
++		PSPTOREG(rv.s, rv.s2, MIPSInst_FD(ir));
++		break;
++	default:
++		return SIGILL;
++	}
++
++	return 0;
++}
++#endif
++
+ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ 	mips_instruction ir, void *__user *fault_addr)
+ {
+@@ -1654,7 +1846,12 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ 	unsigned cond;
+ 	union {
+ 		union ieee754dp d;
+-		union ieee754sp s;
++		struct {
++			union ieee754sp s;
++#ifdef CONFIG_MACH_LOONGSON
++			union ieee754sp s2; /* for Loongson paired singles */
++#endif
++		};
+ 		int w;
+ 		s64 l;
+ 	} rv;			/* resulting value */
+@@ -2065,6 +2262,83 @@ dcopuop:
+ 		break;
+ 	}
+ 
++#ifdef CONFIG_MACH_LOONGSON
++	case ps_fmt:{		/* 6 */
++		/* Support for Loongson paired single fp instructions */
++		union {
++			union ieee754sp(*b) (union ieee754sp, union ieee754sp);
++			union ieee754sp(*u) (union ieee754sp);
++		} handler;
++
++		switch (MIPSInst_FUNC(ir)) {
++			/* binary ops */
++		case fadd_op:
++			handler.b = ieee754sp_add;
++			goto pscopbop;
++		case fsub_op:
++			handler.b = ieee754sp_sub;
++			goto pscopbop;
++		case fmul_op:
++			handler.b = ieee754sp_mul;
++			goto pscopbop;
++
++			/* unary  ops */
++		case fabs_op:
++			handler.u = ieee754sp_abs;
++			goto pscopuop;
++		case fneg_op:
++			handler.u = ieee754sp_neg;
++			goto pscopuop;
++		case fmov_op:
++			/* an easy one */
++			PSPFROMREG(rv.s, rv.s2, MIPSInst_FS(ir));
++			break;
++
++		      pscopbop: /* paired binary op handler */
++			{
++				struct _ieee754_csr ieee754_csr_save;
++				union ieee754sp fs1, ft1;
++				union ieee754sp fs2, ft2;
++
++				PSPFROMREG(fs1, fs2, MIPSInst_FS(ir));
++				PSPFROMREG(ft1, ft2, MIPSInst_FT(ir));
++				rv.s  = (*handler.b) (fs1, ft1);
++				ieee754_csr_save = ieee754_csr;
++				rv.s2 = (*handler.b) (fs2, ft2);
++				ieee754_csr.cx |= ieee754_csr_save.cx;
++				ieee754_csr.sx |= ieee754_csr_save.sx;
++				goto copcsr;
++			}
++		      pscopuop: /* paired unary op handler */
++			{
++				struct _ieee754_csr ieee754_csr_save;
++				union ieee754sp fs1;
++				union ieee754sp fs2;
++
++				PSPFROMREG(fs1, fs2, MIPSInst_FS(ir));
++				rv.s  = (*handler.u) (fs1);
++				ieee754_csr_save = ieee754_csr;
++				rv.s2 = (*handler.u) (fs2);
++				ieee754_csr.cx |= ieee754_csr_save.cx;
++				ieee754_csr.sx |= ieee754_csr_save.sx;
++				goto copcsr;
++			}
++			break;
++
++		default:
++			if (MIPSInst_FUNC(ir) >= fcmp_op) {
++				/* Loongson fp hardware handles all
++				   cases of fp compare insns, so we
++				   shouldn't have to */
++				printk ("Loongson paired-single fp compare"
++					" unimplemented in cp1emu.c\n");
++			}
++			return SIGILL;
++		}
++		break;
++	}
++#endif
++
+ 	case l_fmt:
+ 
+ 		if (!cpu_has_mips_3_4_5_64_r2_r6)
+@@ -2136,6 +2410,11 @@ dcopuop:
+ 
+ 		DITOREG(rv.l, MIPSInst_FD(ir));
+ 		break;
++#ifdef CONFIG_MACH_LOONGSON
++	case ps_fmt:
++		PSPTOREG(rv.s, rv.s2, MIPSInst_FD(ir));
++		break;
++#endif
+ 	default:
+ 		return SIGILL;
+ 	}
+-- 
+2.4.3
+
diff --git a/gnu/packages/patches/linux-libre-loongson2-max-physmem-bits.patch b/gnu/packages/patches/linux-libre-loongson2-max-physmem-bits.patch
new file mode 100644
index 0000000000..7559cf79ba
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-loongson2-max-physmem-bits.patch
@@ -0,0 +1,36 @@
+From 8d7280c9ee3d7de6f129b9c3112faffb20841154 Mon Sep 17 00:00:00 2001
+From: Alexandre Oliva <lxoliva@fsfla.org>
+Date: Wed, 15 Oct 2014 02:00:28 -0300
+Subject: [PATCH 5/9] Loongson2: restore working MAX_PHYSMEM_BITS definition
+
+Commit c461731836 bumped MAX_PHYSMEM_BITS up unconditionally, but
+this causes Loongson2 machines to freeze very early on boot.
+
+To restore Loongson2 to a functional state, I have restored the
+original definition, for Loongson2 only.
+
+Signed-off-by: Alexandre Oliva <oliva@gnu.org>
+---
+ arch/mips/include/asm/sparsemem.h | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/arch/mips/include/asm/sparsemem.h b/arch/mips/include/asm/sparsemem.h
+index b1071c1..8b8e551 100644
+--- a/arch/mips/include/asm/sparsemem.h
++++ b/arch/mips/include/asm/sparsemem.h
+@@ -11,7 +11,11 @@
+ #else
+ # define SECTION_SIZE_BITS	28
+ #endif
+-#define MAX_PHYSMEM_BITS	48
++#if !defined(CONFIG_MACH_LOONGSON) || !defined(CONFIG_CPU_LOONGSON2)	/* Commit c461731836 broke Loongson2.  */
++# define MAX_PHYSMEM_BITS	48
++#else
++# define MAX_PHYSMEM_BITS	35
++#endif
+ 
+ #endif /* CONFIG_SPARSEMEM */
+ #endif /* _MIPS_SPARSEMEM_H */
+-- 
+2.4.3
+
diff --git a/gnu/packages/patches/linux-libre-mips-ftrace-fix.patch b/gnu/packages/patches/linux-libre-mips-ftrace-fix.patch
new file mode 100644
index 0000000000..55f136f74c
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-mips-ftrace-fix.patch
@@ -0,0 +1,85 @@
+From a5b566da301f670302930a0af4a8102a29d27f7f Mon Sep 17 00:00:00 2001
+From: Wu Zhangjin <wuzhangjin@gmail.com>
+Date: Wed, 20 Oct 2010 02:27:26 +0800
+Subject: [PATCH 7/9] MIPS: tracing/ftrace: Fixes mcount_regex for modules
+
+In some situations, the modules may have the same address space as the
+core kernel space, then, it should also match the regular R_MIPS_26
+string.
+
+Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
+---
+ scripts/recordmcount.pl | 46 +++++++++++++++++++++++++++++-----------------
+ 1 file changed, 29 insertions(+), 17 deletions(-)
+
+diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl
+index 826470d..9e6dc30 100755
+--- a/scripts/recordmcount.pl
++++ b/scripts/recordmcount.pl
+@@ -310,14 +310,33 @@ if ($arch eq "x86_64") {
+     $cc .= " -m64";
+     $objcopy .= " -O elf64-sparc";
+ } elsif ($arch eq "mips") {
+-    # To enable module support, we need to enable the -mlong-calls option
+-    # of gcc for module, after using this option, we can not get the real
+-    # offset of the calling to _mcount, but the offset of the lui
+-    # instruction or the addiu one. herein, we record the address of the
+-    # first one, and then we can replace this instruction by a branch
+-    # instruction to jump over the profiling function to filter the
+-    # indicated functions, or swith back to the lui instruction to trace
+-    # them, which means dynamic tracing.
++    # <For kernel>
++    # To disable tracing, just replace "jal _mcount" with nop;
++    # to enable tracing, replace back. so, the offset 14 is
++    # needed to be recorded.
++    #
++    #     10:   03e0082d        move    at,ra
++    #	  14:   0c000000        jal     0
++    #                    14: R_MIPS_26   _mcount
++    #                    14: R_MIPS_NONE *ABS*
++    #                    14: R_MIPS_NONE *ABS*
++    #	 18:   00020021        nop
++    #
++    # <For module>
++    #
++    # If no long call(-mlong-calls), the same to kernel.
++    #
++    # If the module space differs from the kernel space, long
++    # call is needed, as a result, the address of _mcount is
++    # needed to be recorded in a register and then jump from
++    # module space to kernel space via "jalr <register>". To
++    # disable tracing, "jalr <register>" can be replaced by
++    # nop; to enable tracing, replace it back. Since the
++    # offset of "jalr <register>" is not easy to be matched,
++    # the offset of the 1st _mcount below is recorded and to
++    # disable tracing, "lui v1, 0x0" is substituted with "b
++    # label", which jumps over "jalr <register>"; to enable
++    # tracing, replace it back.
+     #
+     #       c:	3c030000 	lui	v1,0x0
+     #			c: R_MIPS_HI16	_mcount
+@@ -329,19 +348,12 @@ if ($arch eq "x86_64") {
+     #			10: R_MIPS_NONE	*ABS*
+     #      14:	03e0082d 	move	at,ra
+     #      18:	0060f809 	jalr	v1
++    #                     label:
+     #
+-    # for the kernel:
+-    #
+-    #     10:   03e0082d        move    at,ra
+-    #	  14:   0c000000        jal     0 <loongson_halt>
+-    #                    14: R_MIPS_26   _mcount
+-    #                    14: R_MIPS_NONE *ABS*
+-    #                    14: R_MIPS_NONE *ABS*
+-    #	 18:   00020021        nop
+     if ($is_module eq "0") {
+ 	    $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_26\\s+_mcount\$";
+     } else {
+-	    $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_HI16\\s+_mcount\$";
++	    $mcount_regex = "^\\s*([0-9a-fA-F]+): R_MIPS_(HI16|26)\\s+_mcount\$";
+     }
+     $objdump .= " -Melf-trad".$endian."mips ";
+ 
+-- 
+2.4.3
+
diff --git a/gnu/packages/patches/linux-libre-mips-hugetlb-fix.patch b/gnu/packages/patches/linux-libre-mips-hugetlb-fix.patch
new file mode 100644
index 0000000000..dcc7495322
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-mips-hugetlb-fix.patch
@@ -0,0 +1,15 @@
+Fix Huge TLB support on some MIPS machines including Loongson 2F.
+
+Patch by Mark H Weaver <mhw@netris.org>
+
+--- linux-4.1.6/arch/mips/include/asm/pgtable-bits.h	2015-08-16 23:52:51.000000000 -0400
++++ linux-4.1.6/arch/mips/include/asm/pgtable-bits.h	2015-08-22 16:42:06.589995600 -0400
+@@ -160,7 +160,7 @@
+ #define _PAGE_GLOBAL_SHIFT	(_PAGE_NO_READ_SHIFT + 1)
+ #define _PAGE_GLOBAL		(1 << _PAGE_GLOBAL_SHIFT)
+ 
+-#else	/* !CONFIG_CPU_MIPSR2 && !CONFIG_CPU_MIPSR6 */
++#elif !defined(CONFIG_64BIT) || !defined(CONFIG_MIPS_HUGE_TLB_SUPPORT)
+ #define _PAGE_GLOBAL_SHIFT	(_PAGE_MODIFIED_SHIFT + 1)
+ #define _PAGE_GLOBAL		(1 << _PAGE_GLOBAL_SHIFT)
+ #endif	/* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
diff --git a/gnu/packages/patches/linux-libre-mips-math-emu-fix-pt1.patch b/gnu/packages/patches/linux-libre-mips-math-emu-fix-pt1.patch
new file mode 100644
index 0000000000..bd7cb7281e
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-mips-math-emu-fix-pt1.patch
@@ -0,0 +1,35 @@
+From 58f2873fbfd3b6734e4affedfcba569e3369f646 Mon Sep 17 00:00:00 2001
+From: Mark H Weaver <mhw@netris.org>
+Date: Thu, 6 Aug 2015 01:22:42 -0400
+Subject: [PATCH 1/9] Don't process empty cause flags after simple fp move on
+ MIPS.
+
+---
+ arch/mips/math-emu/cp1emu.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
+index 22b9b2c..139af11 100644
+--- a/arch/mips/math-emu/cp1emu.c
++++ b/arch/mips/math-emu/cp1emu.c
+@@ -1746,7 +1746,7 @@ static int fpu_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ 		case fmov_op:
+ 			/* an easy one */
+ 			SPFROMREG(rv.s, MIPSInst_FS(ir));
+-			goto copcsr;
++			break;
+ 
+ 			/* binary op on handler */
+ scopbop:
+@@ -1943,7 +1943,7 @@ copcsr:
+ 		case fmov_op:
+ 			/* an easy one */
+ 			DPFROMREG(rv.d, MIPSInst_FS(ir));
+-			goto copcsr;
++			break;
+ 
+ 			/* binary op on handler */
+ dcopbop:
+-- 
+2.4.3
+
diff --git a/gnu/packages/patches/linux-libre-mips-math-emu-fix-pt2.patch b/gnu/packages/patches/linux-libre-mips-math-emu-fix-pt2.patch
new file mode 100644
index 0000000000..408602af0d
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-mips-math-emu-fix-pt2.patch
@@ -0,0 +1,66 @@
+From 5e207ff6fc01f129a3e0ef6c33b141e4315ac633 Mon Sep 17 00:00:00 2001
+From: Mark H Weaver <mhw@netris.org>
+Date: Thu, 6 Aug 2015 01:25:50 -0400
+Subject: [PATCH 2/9] Fix handling of prefx instruction in mips/math-emu
+
+* Add prefx opcode.
+
+* Recognize the prefx instruction regardless of what bits happen to be
+  in bits 21-25, which is the format field of the floating-point ops,
+  but holds the base register of the prefx instruction.
+---
+ arch/mips/include/uapi/asm/inst.h | 3 ++-
+ arch/mips/math-emu/cp1emu.c       | 9 +++++++--
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/arch/mips/include/uapi/asm/inst.h b/arch/mips/include/uapi/asm/inst.h
+index fc0cf5a..9b6ccbd 100644
+--- a/arch/mips/include/uapi/asm/inst.h
++++ b/arch/mips/include/uapi/asm/inst.h
+@@ -180,7 +180,8 @@ enum cop1_sdw_func {
+ enum cop1x_func {
+ 	lwxc1_op     =	0x00, ldxc1_op	   =  0x01,
+ 	swxc1_op     =  0x08, sdxc1_op	   =  0x09,
+-	pfetch_op    =	0x0f, madd_s_op	   =  0x20,
++	pfetch_op    =	0x0f,
++	prefx_op     =  0x17, madd_s_op    =  0x20,
+ 	madd_d_op    =	0x21, madd_e_op	   =  0x22,
+ 	msub_s_op    =	0x28, msub_d_op	   =  0x29,
+ 	msub_e_op    =	0x2a, nmadd_s_op   =  0x30,
+diff --git a/arch/mips/math-emu/cp1emu.c b/arch/mips/math-emu/cp1emu.c
+index 139af11..ed82f0e 100644
+--- a/arch/mips/math-emu/cp1emu.c
++++ b/arch/mips/math-emu/cp1emu.c
+@@ -1545,7 +1545,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ 			break;
+ 
+ 		default:
+-			return SIGILL;
++			goto SIGILL_unless_prefx_op;
+ 		}
+ 		break;
+ 	}
+@@ -1615,7 +1615,7 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ 			goto copcsr;
+ 
+ 		default:
+-			return SIGILL;
++			goto SIGILL_unless_prefx_op;
+ 		}
+ 		break;
+ 	}
+@@ -1628,6 +1628,11 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
+ 		break;
+ 
+ 	default:
++	      SIGILL_unless_prefx_op:
++		if (MIPSInst_FUNC(ir) == prefx_op) {
++			/* ignore prefx operation */
++			break;
++		}
+ 		return SIGILL;
+ 	}
+ 
+-- 
+2.4.3
+
diff --git a/gnu/packages/patches/linux-libre-yeeloong-rfkill-key-fix.patch b/gnu/packages/patches/linux-libre-yeeloong-rfkill-key-fix.patch
new file mode 100644
index 0000000000..44f3d72e25
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-yeeloong-rfkill-key-fix.patch
@@ -0,0 +1,48 @@
+From c49e2c1b1dbe95821f8134a48ca747e5161e75a6 Mon Sep 17 00:00:00 2001
+From: Mark H Weaver <mhw@netris.org>
+Date: Sun, 23 Aug 2015 17:06:18 -0400
+Subject: [PATCH] Yeeloong: Ignore the Fn + F5 (rfkill toggle) key combination.
+
+* drivers/platform/mips/yeeloong_laptop.c (yeeloong_keymap): Do not
+  generate a user-visible key press from the Fn + F5 key combination.
+---
+ drivers/platform/mips/yeeloong_laptop.c | 23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/platform/mips/yeeloong_laptop.c b/drivers/platform/mips/yeeloong_laptop.c
+index 9f2d81b..6d7cde6 100644
+--- a/drivers/platform/mips/yeeloong_laptop.c
++++ b/drivers/platform/mips/yeeloong_laptop.c
+@@ -803,7 +803,28 @@ static const struct key_entry yeeloong_keymap[] = {
+ 	{KE_KEY, EVENT_BLACK_SCREEN, { KEY_DISPLAYTOGGLE } }, /* Fn + F2 */
+ 	{KE_KEY, EVENT_DISPLAY_TOGGLE, { KEY_SWITCHVIDEOMODE } }, /* Fn + F3 */
+ 	{KE_KEY, EVENT_AUDIO_MUTE, { KEY_MUTE } }, /* Fn + F4 */
+-	{KE_KEY, EVENT_WLAN, { KEY_WLAN } }, /* Fn + F5 */
++
++	/* XXX Fn + F5 is handled at a lower level (presumably by the
++	   embedded controller) to toggle the state of the hardware
++	   rfkill switch of the internal RTL8187B wireless adapter.
++
++	   If we also map it to KEY_WLAN, as is done by the
++	   loongson-community kernel as of August 2015, that causes
++	   the generic rfkill input subsystem to toggle the state of
++	   the software rfkill switch for all wireless devices.
++
++	   At boot time, these two switch states start out
++	   out-of-sync, so rfkill is always blocked by one or the
++	   other: pressing Fn + F5 merely toggles whether it is the
++	   software or hardware rfkill switch that's causing the
++	   block.  Even if we arranged to start with these two switch
++	   states in sync, they might possibly get out of sync at some
++	   point.  It seems fragile.
++
++	   So, instead, we simply avoid the dual meaning of this key,
++	   by ignoring the key from software. */
++	{KE_IGNORE, EVENT_WLAN, { KEY_WLAN } }, /* Fn + F5 */
++
+ 	{KE_KEY, EVENT_DISPLAY_BRIGHTNESS, { KEY_BRIGHTNESSUP } }, /* Fn + up */
+ 	{KE_KEY, EVENT_DISPLAY_BRIGHTNESS, { KEY_BRIGHTNESSDOWN } }, /* Fn + down */
+ 	{KE_KEY, EVENT_AUDIO_VOLUME, { KEY_VOLUMEUP } }, /* Fn + right */
+-- 
+2.5.0
+
diff --git a/gnu/packages/patches/linux-libre-yeeloong-silence-ec-messages.patch b/gnu/packages/patches/linux-libre-yeeloong-silence-ec-messages.patch
new file mode 100644
index 0000000000..2607ba2646
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-yeeloong-silence-ec-messages.patch
@@ -0,0 +1,26 @@
+From 2db1cedcf67ef5e1703069bbbdbac8483cd002e1 Mon Sep 17 00:00:00 2001
+From: Mark H Weaver <mhw@netris.org>
+Date: Sat, 5 Sep 2015 23:44:59 -0400
+Subject: [PATCH] yeeloong: Change "ec issued command" from KERN_INFO to
+ KERN_DEBUG.
+
+---
+ arch/mips/loongson64/lemote-2f/ec_kb3310b.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/mips/loongson/lemote-2f/ec_kb3310b.c b/arch/mips/loongson/lemote-2f/ec_kb3310b.c
+index 2b666d3..c5f4b82 100644
+--- a/arch/mips/loongson/lemote-2f/ec_kb3310b.c
++++ b/arch/mips/loongson/lemote-2f/ec_kb3310b.c
+@@ -79,7 +79,7 @@ int ec_query_seq(unsigned char cmd)
+ 		printk(KERN_ERR "%s: deadable error : timeout...\n", __func__);
+ 		ret = -EINVAL;
+ 	} else
+-		printk(KERN_INFO
++		printk(KERN_DEBUG
+ 			   "(%x/%d)ec issued command %d status : 0x%x\n",
+ 			   timeout, EC_CMD_TIMEOUT - timeout, cmd, status);
+ 
+-- 
+2.5.0
+
diff --git a/gnu/packages/patches/linux-libre-yeeloong.patch b/gnu/packages/patches/linux-libre-yeeloong.patch
new file mode 100644
index 0000000000..3b8503eb57
--- /dev/null
+++ b/gnu/packages/patches/linux-libre-yeeloong.patch
@@ -0,0 +1,3451 @@
+Add support for Lemote machines based on the Loongson 2F.  This selection of
+patches was derived from looking at the differences between the linux-stable
+and loongson-community git repositories.
+
+diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
+index f501665..a672872 100644
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -344,7 +344,7 @@ config LASAT
+ 
+ config MACH_LOONGSON
+ 	bool "Loongson family of machines"
+-	select SYS_SUPPORTS_ZBOOT
++	select SYS_SUPPORTS_ZBOOT_UART16550
+ 	help
+ 	  This enables the support of Loongson family of machines.
+ 
+@@ -1715,6 +1715,7 @@ config CPU_LOONGSON2
+ 	select CPU_SUPPORTS_64BIT_KERNEL
+ 	select CPU_SUPPORTS_HIGHMEM
+ 	select CPU_SUPPORTS_HUGEPAGES
++	select ARCH_WANT_OPTIONAL_GPIOLIB
+ 
+ config CPU_LOONGSON1
+ 	bool
+@@ -2392,7 +2393,7 @@ config CPU_SUPPORTS_MSA
+ 
+ config ARCH_FLATMEM_ENABLE
+ 	def_bool y
+-	depends on !NUMA && !CPU_LOONGSON2
++	depends on !NUMA && !(CPU_LOONGSON2 && HIBERNATION)
+ 
+ config ARCH_DISCONTIGMEM_ENABLE
+ 	bool
+diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
+index a0ee0cb..4e18add 100644
+--- a/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
++++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
+@@ -301,5 +301,40 @@ extern void _wrmsr(u32 msr, u32 hi, u32 lo);
+ /* GPIO : I/O SPACE; REG : 32BITS */
+ #define GPIOL_OUT_VAL		0x00
+ #define GPIOL_OUT_EN		0x04
++#define GPIOL_OUT_AUX1_SEL	0x10
++/* SMB : I/O SPACE, REG : 8BITS WIDTH */
++#define	SMB_SDA			0x00
++#define	SMB_STS			0x01
++#define	SMB_STS_SLVSTP		(1 << 7)
++#define	SMB_STS_SDAST		(1 << 6)
++#define	SMB_STS_BER		(1 << 5)
++#define	SMB_STS_NEGACK		(1 << 4)
++#define	SMB_STS_STASTR		(1 << 3)
++#define	SMB_STS_NMATCH		(1 << 2)
++#define	SMB_STS_MASTER		(1 << 1)
++#define	SMB_STS_XMIT		(1 << 0)
++#define	SMB_CTRL_STS		0x02
++#define	SMB_CSTS_TGSTL		(1 << 5)
++#define	SMB_CSTS_TSDA		(1 << 4)
++#define	SMB_CSTS_GCMTCH		(1 << 3)
++#define	SMB_CSTS_MATCH		(1 << 2)
++#define	SMB_CSTS_BB		(1 << 1)
++#define	SMB_CSTS_BUSY		(1 << 0)
++#define	SMB_CTRL1		0x03
++#define	SMB_CTRL1_STASTRE	(1 << 7)
++#define	SMB_CTRL1_NMINTE	(1 << 6)
++#define	SMB_CTRL1_GCMEN		(1 << 5)
++#define	SMB_CTRL1_ACK		(1 << 4)
++#define	SMB_CTRL1_RSVD		(1 << 3)
++#define	SMB_CTRL1_INTEN		(1 << 2)
++#define	SMB_CTRL1_STOP		(1 << 1)
++#define	SMB_CTRL1_START		(1 << 0)
++#define	SMB_ADDR		0x04
++#define	SMB_ADDR_SAEN		(1 << 7)
++#define	SMB_CONTROLLER_ADDR	(0xef << 0)
++#define	SMB_CTRL2		0x05
++#define	SMB_FREQ		(0x20 << 1)
++#define	SMB_ENABLE		(0x01 << 0)
++#define	SMB_CTRL3		0x06
+ 
+ #endif				/* _CS5536_H */
+diff --git a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h
+index 021d017..50aafca 100644
+--- a/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h
++++ b/arch/mips/include/asm/mach-loongson/cs5536/cs5536_mfgpt.h
+@@ -28,8 +28,19 @@ static inline void __maybe_unused enable_mfgpt0_counter(void)
+ #define COMPARE	 ((MFGPT_TICK_RATE + HZ/2) / HZ)
+ 
+ #define MFGPT_BASE	mfgpt_base
++#define MFGPT0_CMP1	(MFGPT_BASE + 0)
+ #define MFGPT0_CMP2	(MFGPT_BASE + 2)
+ #define MFGPT0_CNT	(MFGPT_BASE + 4)
+ #define MFGPT0_SETUP	(MFGPT_BASE + 6)
+ 
++#define MFGPT1_CMP1	(MFGPT_BASE + 0x08)
++#define MFGPT1_CMP2	(MFGPT_BASE + 0x0A)
++#define MFGPT1_CNT	(MFGPT_BASE + 0x0C)
++#define MFGPT1_SETUP	(MFGPT_BASE + 0x0E)
++
++#define MFGPT2_CMP1	(MFGPT_BASE + 0x10)
++#define MFGPT2_CMP2	(MFGPT_BASE + 0x12)
++#define MFGPT2_CNT	(MFGPT_BASE + 0x14)
++#define MFGPT2_SETUP	(MFGPT_BASE + 0x16)
++
+ #endif /*!_CS5536_MFGPT_H */
+diff --git a/arch/mips/include/asm/mach-loongson/loongson.h b/arch/mips/include/asm/mach-loongson/loongson.h
+index 9783103..e6febaf 100644
+--- a/arch/mips/include/asm/mach-loongson/loongson.h
++++ b/arch/mips/include/asm/mach-loongson/loongson.h
+@@ -46,6 +46,12 @@ static inline void prom_init_uart_base(void)
+ #endif
+ }
+ 
++/*
++ * Copy kernel command line from arcs_cmdline
++ */
++#include <asm/setup.h>
++extern char loongson_cmdline[COMMAND_LINE_SIZE];
++
+ /* irq operation functions */
+ extern void bonito_irqdispatch(void);
+ extern void __init bonito_irq_init(void);
+diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
+index 8d01709..9cd25da 100644
+--- a/arch/mips/kernel/time.c
++++ b/arch/mips/kernel/time.c
+@@ -119,6 +119,11 @@ static __init int cpu_has_mfc0_count_bug(void)
+ 
+ void __init time_init(void)
+ {
++#ifdef CONFIG_HR_SCHED_CLOCK
++	if (!mips_clockevent_init() || !cpu_has_mfc0_count_bug())
++		write_c0_count(0);
++#endif
++
+ 	plat_time_init();
+ 
+ 	/*
+diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
+index 156de85..659ca91 100644
+--- a/arch/mips/loongson/Kconfig
++++ b/arch/mips/loongson/Kconfig
+@@ -32,12 +32,12 @@ config LEMOTE_FULOONG2E
+ 
+ config LEMOTE_MACH2F
+ 	bool "Lemote Loongson 2F family machines"
+-	select ARCH_SPARSEMEM_ENABLE
++	select ARCH_SPARSEMEM_ENABLE if HIBERNATION
+ 	select BOARD_SCACHE
+ 	select BOOT_ELF32
+ 	select CEVT_R4K if ! MIPS_EXTERNAL_TIMER
+ 	select CPU_HAS_WB
+-	select CS5536
++	select CS5536 if PCI
+ 	select CSRC_R4K if ! MIPS_EXTERNAL_TIMER
+ 	select DMA_NONCOHERENT
+ 	select GENERIC_ISA_DMA_SUPPORT_BROKEN
+@@ -45,14 +45,13 @@ config LEMOTE_MACH2F
+ 	select HW_HAS_PCI
+ 	select I8259
+ 	select IRQ_CPU
+-	select ISA
+ 	select SYS_HAS_CPU_LOONGSON2F
+ 	select SYS_HAS_EARLY_PRINTK
+ 	select SYS_SUPPORTS_32BIT_KERNEL
+ 	select SYS_SUPPORTS_64BIT_KERNEL
+ 	select SYS_SUPPORTS_HIGHMEM
+ 	select SYS_SUPPORTS_LITTLE_ENDIAN
+-	select LOONGSON_MC146818
++	select LOONGSON_MC146818 if RTC_DRV_CMOS
+ 	help
+ 	  Lemote Loongson 2F family machines utilize the 2F revision of
+ 	  Loongson processor and the AMD CS5536 south bridge.
+diff --git a/arch/mips/loongson/common/cmdline.c b/arch/mips/loongson/common/cmdline.c
+index 72fed00..679a18a 100644
+--- a/arch/mips/loongson/common/cmdline.c
++++ b/arch/mips/loongson/common/cmdline.c
+@@ -17,10 +17,15 @@
+  * Free Software Foundation;  either version 2 of the  License, or (at your
+  * option) any later version.
+  */
++#include <linux/module.h>
+ #include <asm/bootinfo.h>
+ 
+ #include <loongson.h>
+ 
++/* the kernel command line copied from arcs_cmdline */
++char loongson_cmdline[COMMAND_LINE_SIZE];
++EXPORT_SYMBOL(loongson_cmdline);
++
+ void __init prom_init_cmdline(void)
+ {
+ 	int prom_argc;
+@@ -45,4 +50,26 @@ void __init prom_init_cmdline(void)
+ 	}
+ 
+ 	prom_init_machtype();
++
++	/* append machine specific command line */
++	switch (mips_machtype) {
++	case MACH_LEMOTE_LL2F:
++		if ((strstr(arcs_cmdline, "video=")) == NULL)
++			strcat(arcs_cmdline, " video=sisfb:1360x768-16@60");
++		break;
++	case MACH_LEMOTE_FL2F:
++		if ((strstr(arcs_cmdline, "ide_core.ignore_cable=")) == NULL)
++			strcat(arcs_cmdline, " ide_core.ignore_cable=0");
++		break;
++	case MACH_LEMOTE_ML2F7:
++		/* Mengloong-2F has a 800x480 screen */
++		if ((strstr(arcs_cmdline, "vga=")) == NULL)
++			strcat(arcs_cmdline, " vga=0x313");
++		break;
++	default:
++		break;
++	}
++
++	/* copy arcs_cmdline into loongson_cmdline */
++	strncpy(loongson_cmdline, arcs_cmdline, COMMAND_LINE_SIZE);
+ }
+diff --git a/arch/mips/loongson/lemote-2f/Makefile b/arch/mips/loongson/lemote-2f/Makefile
+index 4f9eaa3..f945bd7 100644
+--- a/arch/mips/loongson/lemote-2f/Makefile
++++ b/arch/mips/loongson/lemote-2f/Makefile
+@@ -2,7 +2,7 @@
+ # Makefile for lemote loongson2f family machines
+ #
+ 
+-obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o
++obj-y += clock.o machtype.o irq.o reset.o ec_kb3310b.o platform.o
+ 
+ #
+ # Suspend Support
+diff --git a/arch/mips/loongson/lemote-2f/platform.c b/arch/mips/loongson/lemote-2f/platform.c
+new file mode 100644
+index 0000000..5316360
+--- /dev/null
++++ b/arch/mips/loongson/lemote-2f/platform.c
+@@ -0,0 +1,48 @@
++/*
++ * Copyright (C) 2009 Lemote Inc.
++ * Author: Wu Zhangjin, wuzhangjin@gmail.com
++ *
++ * This program is free software; you can redistribute  it and/or modify it
++ * under  the terms of  the GNU General  Public License as published by the
++ * Free Software Foundation;  either version 2 of the  License, or (at your
++ * option) any later version.
++ */
++
++#include <linux/err.h>
++#include <linux/platform_device.h>
++
++#include <asm/bootinfo.h>
++
++static struct platform_device yeeloong_pdev = {
++	.name = "yeeloong_laptop",
++	.id = -1,
++};
++
++static struct platform_device lynloong_pdev = {
++	.name = "lynloong_pc",
++	.id = -1,
++};
++
++static int __init lemote2f_platform_init(void)
++{
++	struct platform_device *pdev = NULL;
++
++	switch (mips_machtype) {
++	case MACH_LEMOTE_YL2F89:
++		pdev = &yeeloong_pdev;
++		break;
++	case MACH_LEMOTE_LL2F:
++		pdev = &lynloong_pdev;
++		break;
++	default:
++		break;
++
++	}
++
++	if (pdev != NULL)
++		return platform_device_register(pdev);
++
++	return -ENODEV;
++}
++
++arch_initcall(lemote2f_platform_init);
+diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c
+index 376f2dc..b576801 100644
+--- a/drivers/ide/ide-iops.c
++++ b/drivers/ide/ide-iops.c
+@@ -27,6 +27,10 @@
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ 
++#ifdef CONFIG_LEMOTE_MACH2F
++#include <asm/bootinfo.h>
++#endif
++
+ void SELECT_MASK(ide_drive_t *drive, int mask)
+ {
+ 	const struct ide_port_ops *port_ops = drive->hwif->port_ops;
+@@ -300,6 +304,11 @@ void ide_check_nien_quirk_list(ide_drive_t *drive)
+ {
+ 	const char **list, *m = (char *)&drive->id[ATA_ID_PROD];
+ 
++#ifdef CONFIG_LEMOTE_MACH2F
++	if (mips_machtype != MACH_LEMOTE_YL2F89)
++		return;
++#endif
++
+ 	for (list = nien_quirk_list; *list != NULL; list++)
+ 		if (strstr(m, *list) != NULL) {
+ 			drive->dev_flags |= IDE_DFLAG_NIEN_QUIRK;
+diff --git a/drivers/platform/mips/Kconfig b/drivers/platform/mips/Kconfig
+index 125e569..c80714b 100644
+--- a/drivers/platform/mips/Kconfig
++++ b/drivers/platform/mips/Kconfig
+@@ -15,6 +15,38 @@ menuconfig MIPS_PLATFORM_DEVICES
+ 
+ if MIPS_PLATFORM_DEVICES
+ 
++config LEMOTE_YEELOONG2F
++	tristate "Lemote YeeLoong Laptop"
++	depends on LEMOTE_MACH2F
++	select BACKLIGHT_LCD_SUPPORT
++	select LCD_CLASS_DEVICE
++	select BACKLIGHT_CLASS_DEVICE
++	select POWER_SUPPLY
++	select HWMON
++	select VIDEO_OUTPUT_CONTROL
++	select INPUT_SPARSEKMAP
++	select INPUT_EVDEV
++	depends on INPUT
++	default m
++	help
++	  YeeLoong netbook is a mini laptop made by Lemote, which is basically
++	  compatible to FuLoong2F mini PC, but it has an extra Embedded
++	  Controller(kb3310b) for battery, hotkey, backlight, temperature and
++	  fan management.
++
++config LEMOTE_LYNLOONG2F
++	tristate "Lemote LynLoong PC"
++	depends on LEMOTE_MACH2F
++	select BACKLIGHT_LCD_SUPPORT
++	select BACKLIGHT_CLASS_DEVICE
++	select VIDEO_OUTPUT_CONTROL
++	default m
++	help
++	  LynLoong PC is an AllINONE machine made by Lemote, which is basically
++	  compatible to FuLoong2F Mini PC, the only difference is that it has a
++	  size-fixed screen: 1360x768 with sisfb video driver. and also, it has
++	  its own specific suspend support.
++
+ config MIPS_ACPI
+ 	bool
+ 	default y if LOONGSON_MACH3X
+diff --git a/drivers/platform/mips/Makefile b/drivers/platform/mips/Makefile
+index 4341284..0e21bfb 100644
+--- a/drivers/platform/mips/Makefile
++++ b/drivers/platform/mips/Makefile
+@@ -1,2 +1,11 @@
++#
++# Makefile for MIPS Platform-Specific Drivers
++#
++
++obj-$(CONFIG_LEMOTE_YEELOONG2F)	+= yeeloong_laptop.o # yeeloong_ecrom.o
++CFLAGS_yeeloong_laptop.o = -I$(srctree)/arch/mips/loongson/lemote-2f
++
++obj-$(CONFIG_LEMOTE_LYNLOONG2F)	+= lynloong_pc.o
++
+ obj-$(CONFIG_MIPS_ACPI) += acpi_init.o
+ obj-$(CONFIG_CPU_HWMON) += cpu_hwmon.o
+diff --git a/drivers/platform/mips/lynloong_pc.c b/drivers/platform/mips/lynloong_pc.c
+new file mode 100644
+index 0000000..68f29e4
+--- /dev/null
++++ b/drivers/platform/mips/lynloong_pc.c
+@@ -0,0 +1,515 @@
++/*
++ * Driver for LynLoong PC extras
++ *
++ *  Copyright (C) 2009 Lemote Inc.
++ *  Author: Wu Zhangjin <wuzhangjin@gmail.com>, Xiang Yu <xiangy@lemote.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++ */
++
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/backlight.h>	/* for backlight subdriver */
++#include <linux/fb.h>
++#include <linux/video_output.h>	/* for video output subdriver */
++#include <linux/delay.h>	/* for suspend support */
++
++#include <cs5536/cs5536.h>
++#include <cs5536/cs5536_mfgpt.h>
++
++#include <loongson.h>
++
++static u32 gpio_base, mfgpt_base;
++
++static void set_gpio_reg_high(int gpio, int reg)
++{
++	u32 val;
++
++	val = inl(gpio_base + reg);
++	val |= (1 << gpio);
++	val &= ~(1 << (16 + gpio));
++	outl(val, gpio_base + reg);
++	mmiowb();
++}
++
++static void set_gpio_reg_low(int gpio, int reg)
++{
++	u32 val;
++
++	val = inl(gpio_base + reg);
++	val |= (1 << (16 + gpio));
++	val &= ~(1 << gpio);
++	outl(val, gpio_base + reg);
++	mmiowb();
++}
++
++static void set_gpio_output_low(int gpio)
++{
++	set_gpio_reg_high(gpio, GPIOL_OUT_EN);
++	set_gpio_reg_low(gpio, GPIOL_OUT_VAL);
++}
++
++static void set_gpio_output_high(int gpio)
++{
++	set_gpio_reg_high(gpio, GPIOL_OUT_EN);
++	set_gpio_reg_high(gpio, GPIOL_OUT_VAL);
++}
++
++/* backlight subdriver */
++
++#define MAX_BRIGHTNESS 100
++#define DEFAULT_BRIGHTNESS 50
++#define MIN_BRIGHTNESS 0
++static unsigned int level;
++
++DEFINE_SPINLOCK(backlight_lock);
++/* Tune the brightness */
++static void setup_mfgpt2(void)
++{
++	unsigned long flags;
++
++	spin_lock_irqsave(&backlight_lock, flags);
++
++	/* Set MFGPT2 comparator 1,2 */
++	outw(MAX_BRIGHTNESS-level, MFGPT2_CMP1);
++	outw(MAX_BRIGHTNESS, MFGPT2_CMP2);
++	/* Clear MFGPT2 UP COUNTER */
++	outw(0, MFGPT2_CNT);
++	/* Enable counter, compare mode, 32k */
++	outw(0x8280, MFGPT2_SETUP);
++
++	spin_unlock_irqrestore(&backlight_lock, flags);
++}
++
++static int lynloong_set_brightness(struct backlight_device *bd)
++{
++	level = (bd->props.fb_blank == FB_BLANK_UNBLANK &&
++		 bd->props.power == FB_BLANK_UNBLANK) ?
++	    bd->props.brightness : 0;
++
++	if (level > MAX_BRIGHTNESS)
++		level = MAX_BRIGHTNESS;
++	else if (level < MIN_BRIGHTNESS)
++		level = MIN_BRIGHTNESS;
++
++	setup_mfgpt2();
++
++	return 0;
++}
++
++static int lynloong_get_brightness(struct backlight_device *bd)
++{
++	return level;
++}
++
++static struct backlight_ops backlight_ops = {
++	.get_brightness = lynloong_get_brightness,
++	.update_status = lynloong_set_brightness,
++};
++
++static struct backlight_device *lynloong_backlight_dev;
++
++static int lynloong_backlight_init(void)
++{
++	int ret;
++	u32 hi;
++	struct backlight_properties props;
++
++	/* Get gpio_base */
++	_rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &gpio_base);
++	/* Get mfgpt_base */
++	_rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_MFGPT), &hi, &mfgpt_base);
++	/* Get gpio_base */
++	_rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &gpio_base);
++
++	/* Select for mfgpt */
++	set_gpio_reg_high(7, GPIOL_OUT_AUX1_SEL);
++	/* Enable brightness controlling */
++	set_gpio_output_high(7);
++
++	memset(&props, 0, sizeof(struct backlight_properties));
++	props.max_brightness = MAX_BRIGHTNESS;
++	props.type = BACKLIGHT_PLATFORM;
++	lynloong_backlight_dev = backlight_device_register("backlight0", NULL,
++			NULL, &backlight_ops, &props);
++
++	if (IS_ERR(lynloong_backlight_dev)) {
++		ret = PTR_ERR(lynloong_backlight_dev);
++		return ret;
++	}
++
++	lynloong_backlight_dev->props.brightness = DEFAULT_BRIGHTNESS;
++	backlight_update_status(lynloong_backlight_dev);
++
++	return 0;
++}
++
++static void lynloong_backlight_exit(void)
++{
++	if (lynloong_backlight_dev) {
++		backlight_device_unregister(lynloong_backlight_dev);
++		lynloong_backlight_dev = NULL;
++	}
++	/* Disable brightness controlling */
++	set_gpio_output_low(7);
++}
++
++/* video output driver */
++static int vo_status = 1;
++
++static int lcd_video_output_get(struct output_device *od)
++{
++	return vo_status;
++}
++
++static int lcd_video_output_set(struct output_device *od)
++{
++	int i;
++	unsigned long status;
++
++	status = !!od->request_state;
++
++	if (status == 0) {
++		/* Set the current status as off */
++		vo_status = 0;
++		/* Turn off the backlight */
++		set_gpio_output_low(11);
++		for (i = 0; i < 0x500; i++)
++			delay();
++		/* Turn off the LCD */
++		set_gpio_output_high(8);
++	} else {
++		/* Turn on the LCD */
++		set_gpio_output_low(8);
++		for (i = 0; i < 0x500; i++)
++			delay();
++		/* Turn on the backlight */
++		set_gpio_output_high(11);
++		/* Set the current status as on */
++		vo_status = 1;
++	}
++
++	return 0;
++}
++
++static struct output_properties lcd_output_properties = {
++	.set_state = lcd_video_output_set,
++	.get_status = lcd_video_output_get,
++};
++
++static struct output_device *lcd_output_dev;
++
++static void lynloong_lcd_vo_set(int status)
++{
++	lcd_output_dev->request_state = status;
++	lcd_video_output_set(lcd_output_dev);
++}
++
++static int lynloong_vo_init(void)
++{
++	int ret;
++
++	/* Register video output device: lcd */
++	lcd_output_dev = video_output_register("LCD", NULL, NULL,
++			&lcd_output_properties);
++
++	if (IS_ERR(lcd_output_dev)) {
++		ret = PTR_ERR(lcd_output_dev);
++		lcd_output_dev = NULL;
++		return ret;
++	}
++	/* Ensure LCD is on by default */
++	lynloong_lcd_vo_set(1);
++
++	return 0;
++}
++
++static void lynloong_vo_exit(void)
++{
++	if (lcd_output_dev) {
++		video_output_unregister(lcd_output_dev);
++		lcd_output_dev = NULL;
++	}
++}
++
++/* suspend support */
++
++#ifdef CONFIG_PM
++
++static u32 smb_base;
++
++/* I2C operations */
++
++static int i2c_wait(void)
++{
++	char c;
++	int i;
++
++	udelay(1000);
++	for (i = 0; i < 20; i++) {
++		c = inb(smb_base | SMB_STS);
++		if (c & (SMB_STS_BER | SMB_STS_NEGACK))
++			return -1;
++		if (c & SMB_STS_SDAST)
++			return 0;
++		udelay(100);
++	}
++	return -2;
++}
++
++static void i2c_read_single(int addr, int regNo, char *value)
++{
++	unsigned char c;
++
++	/* Start condition */
++	c = inb(smb_base | SMB_CTRL1);
++	outb(c | SMB_CTRL1_START, smb_base | SMB_CTRL1);
++	i2c_wait();
++
++	/* Send slave address */
++	outb(addr & 0xfe, smb_base | SMB_SDA);
++	i2c_wait();
++
++	/* Acknowledge smbus */
++	c = inb(smb_base | SMB_CTRL1);
++	outb(c | SMB_CTRL1_ACK, smb_base | SMB_CTRL1);
++
++	/* Send register index */
++	outb(regNo, smb_base | SMB_SDA);
++	i2c_wait();
++
++	/* Acknowledge smbus */
++	c = inb(smb_base | SMB_CTRL1);
++	outb(c | SMB_CTRL1_ACK, smb_base | SMB_CTRL1);
++
++	/* Start condition again */
++	c = inb(smb_base | SMB_CTRL1);
++	outb(c | SMB_CTRL1_START, smb_base | SMB_CTRL1);
++	i2c_wait();
++
++	/* Send salve address again */
++	outb(1 | addr, smb_base | SMB_SDA);
++	i2c_wait();
++
++	/* Acknowledge smbus */
++	c = inb(smb_base | SMB_CTRL1);
++	outb(c | SMB_CTRL1_ACK, smb_base | SMB_CTRL1);
++
++	/* Read data */
++	*value = inb(smb_base | SMB_SDA);
++
++	/* Stop condition */
++	outb(SMB_CTRL1_STOP, smb_base | SMB_CTRL1);
++	i2c_wait();
++}
++
++static void i2c_write_single(int addr, int regNo, char value)
++{
++	unsigned char c;
++
++	/* Start condition */
++	c = inb(smb_base | SMB_CTRL1);
++	outb(c | SMB_CTRL1_START, smb_base | SMB_CTRL1);
++	i2c_wait();
++	/* Send slave address */
++	outb(addr & 0xfe, smb_base | SMB_SDA);
++	i2c_wait();;
++
++	/* Send register index */
++	outb(regNo, smb_base | SMB_SDA);
++	i2c_wait();
++
++	/* Write data */
++	outb(value, smb_base | SMB_SDA);
++	i2c_wait();
++	/* Stop condition */
++	outb(SMB_CTRL1_STOP, smb_base | SMB_CTRL1);
++	i2c_wait();
++}
++
++static void stop_clock(int clk_reg, int clk_sel)
++{
++	u8 value;
++
++	i2c_read_single(0xd3, clk_reg, &value);
++	value &= ~(1 << clk_sel);
++	i2c_write_single(0xd2, clk_reg, value);
++}
++
++static void enable_clock(int clk_reg, int clk_sel)
++{
++	u8 value;
++
++	i2c_read_single(0xd3, clk_reg, &value);
++	value |= (1 << clk_sel);
++	i2c_write_single(0xd2, clk_reg, value);
++}
++
++static char cached_clk_freq;
++static char cached_pci_fixed_freq;
++
++static void decrease_clk_freq(void)
++{
++	char value;
++
++	i2c_read_single(0xd3, 1, &value);
++	cached_clk_freq = value;
++
++	/* Select frequency by software */
++	value |= (1 << 1);
++	/* CPU, 3V66, PCI : 100, 66, 33(1) */
++	value |= (1 << 2);
++	i2c_write_single(0xd2, 1, value);
++
++	/* Cache the pci frequency */
++	i2c_read_single(0xd3, 14, &value);
++	cached_pci_fixed_freq = value;
++
++	/* Enable PCI fix mode */
++	value |= (1 << 5);
++	/* 3V66, PCI : 64MHz, 32MHz */
++	value |= (1 << 3);
++	i2c_write_single(0xd2, 14, value);
++
++}
++
++static void resume_clk_freq(void)
++{
++	i2c_write_single(0xd2, 1, cached_clk_freq);
++	i2c_write_single(0xd2, 14, cached_pci_fixed_freq);
++}
++
++static void stop_clocks(void)
++{
++	/* CPU Clock Register */
++	stop_clock(2, 5);	/* not used */
++	stop_clock(2, 6);	/* not used */
++	stop_clock(2, 7);	/* not used */
++
++	/* PCI Clock Register */
++	stop_clock(3, 1);	/* 8100 */
++	stop_clock(3, 5);	/* SIS */
++	stop_clock(3, 0);	/* not used */
++	stop_clock(3, 6);	/* not used */
++
++	/* PCI 48M Clock Register */
++	stop_clock(4, 6);	/* USB grounding */
++	stop_clock(4, 5);	/* REF(5536_14M) */
++
++	/* 3V66 Control Register */
++	stop_clock(5, 0);	/* VCH_CLK..., grounding */
++}
++
++static void enable_clocks(void)
++{
++	enable_clock(3, 1);	/* 8100 */
++	enable_clock(3, 5);	/* SIS */
++
++	enable_clock(4, 6);
++	enable_clock(4, 5);	/* REF(5536_14M) */
++
++	enable_clock(5, 0);	/* VCH_CLOCK, grounding */
++}
++
++static int lynloong_suspend(struct device *dev)
++{
++	/* Disable AMP */
++	set_gpio_output_high(6);
++	/* Turn off LCD */
++	lynloong_lcd_vo_set(0);
++
++	/* Stop the clocks of some devices */
++	stop_clocks();
++
++	/* Decrease the external clock frequency */
++	decrease_clk_freq();
++
++	return 0;
++}
++
++static int lynloong_resume(struct device *dev)
++{
++	/* Turn on the LCD */
++	lynloong_lcd_vo_set(1);
++
++	/* Resume clock frequency, enable the relative clocks */
++	resume_clk_freq();
++	enable_clocks();
++
++	/* Enable AMP */
++	set_gpio_output_low(6);
++
++	return 0;
++}
++
++static const SIMPLE_DEV_PM_OPS(lynloong_pm_ops, lynloong_suspend,
++	lynloong_resume);
++#endif	/* !CONFIG_PM */
++
++static struct platform_device_id platform_device_ids[] = {
++	{
++		.name = "lynloong_pc",
++	},
++	{}
++};
++
++MODULE_DEVICE_TABLE(platform, platform_device_ids);
++
++static struct platform_driver platform_driver = {
++	.driver = {
++		.name = "lynloong_pc",
++		.owner = THIS_MODULE,
++#ifdef CONFIG_PM
++		.pm = &lynloong_pm_ops,
++#endif
++	},
++	.id_table = platform_device_ids,
++};
++
++static int __init lynloong_init(void)
++{
++	int ret;
++
++	pr_info("LynLoong platform specific driver loaded.\n");
++
++	/* Register platform stuff */
++	ret = platform_driver_register(&platform_driver);
++	if (ret) {
++		pr_err("Failed to register LynLoong platform driver.\n");
++		return ret;
++	}
++
++	ret = lynloong_backlight_init();
++	if (ret) {
++		pr_err("Failed to register LynLoong backlight driver.\n");
++		return ret;
++	}
++
++	ret = lynloong_vo_init();
++	if (ret) {
++		pr_err("Failed to register LynLoong backlight driver.\n");
++		lynloong_vo_exit();
++		return ret;
++	}
++
++	return 0;
++}
++
++static void __exit lynloong_exit(void)
++{
++	lynloong_vo_exit();
++	lynloong_backlight_exit();
++	platform_driver_unregister(&platform_driver);
++
++	pr_info("LynLoong platform specific driver unloaded.\n");
++}
++
++module_init(lynloong_init);
++module_exit(lynloong_exit);
++
++MODULE_AUTHOR("Wu Zhangjin <wuzhangjin@gmail.com>; Xiang Yu <xiangy@lemote.com>");
++MODULE_DESCRIPTION("LynLoong PC driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/platform/mips/yeeloong_ecrom.c b/drivers/platform/mips/yeeloong_ecrom.c
+new file mode 100644
+index 0000000..1bfe4cf
+--- /dev/null
++++ b/drivers/platform/mips/yeeloong_ecrom.c
+@@ -0,0 +1,944 @@
++/*
++ * Driver for flushing/dumping ROM of EC on YeeLoong laptop
++ *
++ * Copyright (C) 2009 Lemote Inc.
++ * Author: liujl <liujl@lemote.com>
++ *
++ * NOTE :
++ * 	The EC resources accessing and programming are supported.
++ */
++
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++#include <linux/miscdevice.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++
++#include <ec_kb3310b.h>
++
++#define	EC_MISC_DEV		"ec_misc"
++#define EC_IOC_MAGIC		'E'
++
++/* ec registers range */
++#define	EC_MAX_REGADDR	0xFFFF
++#define	EC_MIN_REGADDR	0xF000
++#define	EC_RAM_ADDR	0xF800
++
++/* version burned address */
++#define	VER_ADDR	0xf7a1
++#define	VER_MAX_SIZE	7
++#define	EC_ROM_MAX_SIZE	0x10000
++
++/* ec internal register */
++#define	REG_POWER_MODE		0xF710
++#define	FLAG_NORMAL_MODE	0x00
++#define	FLAG_IDLE_MODE		0x01
++#define	FLAG_RESET_MODE		0x02
++
++/* ec update program flag */
++#define	PROGRAM_FLAG_NONE	0x00
++#define	PROGRAM_FLAG_IE		0x01
++#define	PROGRAM_FLAG_ROM	0x02
++
++/* XBI relative registers */
++#define REG_XBISEG0     0xFEA0
++#define REG_XBISEG1     0xFEA1
++#define REG_XBIRSV2     0xFEA2
++#define REG_XBIRSV3     0xFEA3
++#define REG_XBIRSV4     0xFEA4
++#define REG_XBICFG      0xFEA5
++#define REG_XBICS       0xFEA6
++#define REG_XBIWE       0xFEA7
++#define REG_XBISPIA0    0xFEA8
++#define REG_XBISPIA1    0xFEA9
++#define REG_XBISPIA2    0xFEAA
++#define REG_XBISPIDAT   0xFEAB
++#define REG_XBISPICMD   0xFEAC
++#define REG_XBISPICFG   0xFEAD
++#define REG_XBISPIDATR  0xFEAE
++#define REG_XBISPICFG2  0xFEAF
++
++/* commands definition for REG_XBISPICMD */
++#define	SPICMD_WRITE_STATUS		0x01
++#define	SPICMD_BYTE_PROGRAM		0x02
++#define	SPICMD_READ_BYTE		0x03
++#define	SPICMD_WRITE_DISABLE	0x04
++#define	SPICMD_READ_STATUS		0x05
++#define	SPICMD_WRITE_ENABLE		0x06
++#define	SPICMD_HIGH_SPEED_READ	0x0B
++#define	SPICMD_POWER_DOWN		0xB9
++#define	SPICMD_SST_EWSR			0x50
++#define	SPICMD_SST_SEC_ERASE	0x20
++#define	SPICMD_SST_BLK_ERASE	0x52
++#define	SPICMD_SST_CHIP_ERASE	0x60
++#define	SPICMD_FRDO				0x3B
++#define	SPICMD_SEC_ERASE		0xD7
++#define	SPICMD_BLK_ERASE		0xD8
++#define SPICMD_CHIP_ERASE		0xC7
++
++/* bits definition for REG_XBISPICFG */
++#define	SPICFG_AUTO_CHECK		0x01
++#define	SPICFG_SPI_BUSY			0x02
++#define	SPICFG_DUMMY_READ		0x04
++#define	SPICFG_EN_SPICMD		0x08
++#define	SPICFG_LOW_SPICS		0x10
++#define	SPICFG_EN_SHORT_READ	0x20
++#define	SPICFG_EN_OFFSET_READ	0x40
++#define	SPICFG_EN_FAST_READ		0x80
++
++/* watchdog timer registers */
++#define	REG_WDTCFG				0xfe80
++#define	REG_WDTPF				0xfe81
++#define REG_WDT					0xfe82
++
++/* lpc configure register */
++#define	REG_LPCCFG				0xfe95
++
++/* 8051 reg */
++#define	REG_PXCFG				0xff14
++
++/* Fan register in KB3310 */
++#define	REG_ECFAN_SPEED_LEVEL	0xf4e4
++#define	REG_ECFAN_SWITCH		0xf4d2
++
++/* the ec flash rom id number */
++#define	EC_ROM_PRODUCT_ID_SPANSION	0x01
++#define	EC_ROM_PRODUCT_ID_MXIC		0xC2
++#define	EC_ROM_PRODUCT_ID_AMIC		0x37
++#define	EC_ROM_PRODUCT_ID_EONIC		0x1C
++
++/* misc ioctl operations */
++#define	IOCTL_RDREG		_IOR(EC_IOC_MAGIC, 1, int)
++#define	IOCTL_WRREG		_IOW(EC_IOC_MAGIC, 2, int)
++#define	IOCTL_READ_EC		_IOR(EC_IOC_MAGIC, 3, int)
++#define	IOCTL_PROGRAM_IE	_IOW(EC_IOC_MAGIC, 4, int)
++#define	IOCTL_PROGRAM_EC	_IOW(EC_IOC_MAGIC, 5, int)
++
++/* start address for programming of EC content or IE */
++/*  ec running code start address */
++#define	EC_START_ADDR	0x00000000
++/*  ec information element storing address */
++#define	IE_START_ADDR	0x00020000
++
++/* EC state */
++#define	EC_STATE_IDLE	0x00	/*  ec in idle state */
++#define	EC_STATE_BUSY	0x01	/*  ec in busy state */
++
++/* timeout value for programming */
++#define	EC_FLASH_TIMEOUT	0x1000	/*  ec program timeout */
++/* command checkout timeout including cmd to port or state flag check */
++#define	EC_CMD_TIMEOUT		0x1000
++#define	EC_SPICMD_STANDARD_TIMEOUT	(4 * 1000)	/*  unit : us */
++#define	EC_MAX_DELAY_UNIT	(10)	/*  every time for polling */
++#define	SPI_FINISH_WAIT_TIME	10
++/* EC content max size */
++#define	EC_CONTENT_MAX_SIZE	(64 * 1024)
++#define	IE_CONTENT_MAX_SIZE	(0x100000 - IE_START_ADDR)
++
++/* the register operation access struct */
++struct ec_reg {
++	u32 addr;		/* the address of kb3310 registers */
++	u8 val;			/* the register value */
++};
++
++struct ec_info {
++	u32 start_addr;
++	u32 size;
++	u8 *buf;
++};
++
++/* open for using rom protection action */
++#define	EC_ROM_PROTECTION
++
++/* enable the chip reset mode */
++static int ec_init_reset_mode(void)
++{
++	int timeout;
++	unsigned char status = 0;
++	int ret = 0;
++
++	/* make chip goto reset mode */
++	ret = ec_query_seq(CMD_INIT_RESET_MODE);
++	if (ret < 0) {
++		printk(KERN_ERR "ec init reset mode failed.\n");
++		goto out;
++	}
++
++	/* make the action take active */
++	timeout = EC_CMD_TIMEOUT;
++	status = ec_read(REG_POWER_MODE) & FLAG_RESET_MODE;
++	while (timeout--) {
++		if (status) {
++			udelay(EC_REG_DELAY);
++			break;
++		}
++		status = ec_read(REG_POWER_MODE) & FLAG_RESET_MODE;
++		udelay(EC_REG_DELAY);
++	}
++	if (timeout <= 0) {
++		printk(KERN_ERR "ec rom fixup : can't check reset status.\n");
++		ret = -EINVAL;
++	} else
++		printk(KERN_INFO "(%d/%d)reset 0xf710 :  0x%x\n", timeout,
++			   EC_CMD_TIMEOUT - timeout, status);
++
++	/* set MCU to reset mode */
++	udelay(EC_REG_DELAY);
++	status = ec_read(REG_PXCFG);
++	status |= (1 << 0);
++	ec_write(REG_PXCFG, status);
++	udelay(EC_REG_DELAY);
++
++	/* disable FWH/LPC */
++	udelay(EC_REG_DELAY);
++	status = ec_read(REG_LPCCFG);
++	status &= ~(1 << 7);
++	ec_write(REG_LPCCFG, status);
++	udelay(EC_REG_DELAY);
++
++	printk(KERN_INFO "entering reset mode ok..............\n");
++
++ out:
++	return ret;
++}
++
++/* make ec exit from reset mode */
++static void ec_exit_reset_mode(void)
++{
++	unsigned char regval;
++
++	udelay(EC_REG_DELAY);
++	regval = ec_read(REG_LPCCFG);
++	regval |= (1 << 7);
++	ec_write(REG_LPCCFG, regval);
++	regval = ec_read(REG_PXCFG);
++	regval &= ~(1 << 0);
++	ec_write(REG_PXCFG, regval);
++	printk(KERN_INFO "exit reset mode ok..................\n");
++
++	return;
++}
++
++/* make ec disable WDD */
++static void ec_disable_WDD(void)
++{
++	unsigned char status;
++
++	udelay(EC_REG_DELAY);
++	status = ec_read(REG_WDTCFG);
++	ec_write(REG_WDTPF, 0x03);
++	ec_write(REG_WDTCFG, (status & 0x80) | 0x48);
++	printk(KERN_INFO "Disable WDD ok..................\n");
++
++	return;
++}
++
++/* make ec enable WDD */
++static void ec_enable_WDD(void)
++{
++	unsigned char status;
++
++	udelay(EC_REG_DELAY);
++	status = ec_read(REG_WDTCFG);
++	ec_write(REG_WDT, 0x28);	/* set WDT 5sec(0x28) */
++	ec_write(REG_WDTCFG, (status & 0x80) | 0x03);
++	printk(KERN_INFO "Enable WDD ok..................\n");
++
++	return;
++}
++
++/* make ec goto idle mode */
++static int ec_init_idle_mode(void)
++{
++	int timeout;
++	unsigned char status = 0;
++	int ret = 0;
++
++	ec_query_seq(CMD_INIT_IDLE_MODE);
++
++	/* make the action take active */
++	timeout = EC_CMD_TIMEOUT;
++	status = ec_read(REG_POWER_MODE) & FLAG_IDLE_MODE;
++	while (timeout--) {
++		if (status) {
++			udelay(EC_REG_DELAY);
++			break;
++		}
++		status = ec_read(REG_POWER_MODE) & FLAG_IDLE_MODE;
++		udelay(EC_REG_DELAY);
++	}
++	if (timeout <= 0) {
++		printk(KERN_ERR "ec rom fixup : can't check out the status.\n");
++		ret = -EINVAL;
++	} else
++		printk(KERN_INFO "(%d/%d)0xf710 :  0x%x\n", timeout,
++			   EC_CMD_TIMEOUT - timeout, ec_read(REG_POWER_MODE));
++
++	printk(KERN_INFO "entering idle mode ok...................\n");
++
++	return ret;
++}
++
++/* make ec exit from idle mode */
++static int ec_exit_idle_mode(void)
++{
++
++	ec_query_seq(CMD_EXIT_IDLE_MODE);
++
++	printk(KERN_INFO "exit idle mode ok...................\n");
++
++	return 0;
++}
++
++static int ec_instruction_cycle(void)
++{
++	unsigned long timeout;
++	int ret = 0;
++
++	timeout = EC_FLASH_TIMEOUT;
++	while (timeout-- >= 0) {
++		if (!(ec_read(REG_XBISPICFG) & SPICFG_SPI_BUSY))
++			break;
++	}
++	if (timeout <= 0) {
++		printk(KERN_ERR
++		       "EC_INSTRUCTION_CYCLE : timeout for check flag.\n");
++		ret = -EINVAL;
++		goto out;
++	}
++
++ out:
++	return ret;
++}
++
++/* To see if the ec is in busy state or not. */
++static inline int ec_flash_busy(unsigned long timeout)
++{
++	/* assurance the first command be going to rom */
++	if (ec_instruction_cycle() < 0)
++		return EC_STATE_BUSY;
++#if 1
++	timeout = timeout / EC_MAX_DELAY_UNIT;
++	while (timeout-- > 0) {
++		/* check the rom's status of busy flag */
++		ec_write(REG_XBISPICMD, SPICMD_READ_STATUS);
++		if (ec_instruction_cycle() < 0)
++			return EC_STATE_BUSY;
++		if ((ec_read(REG_XBISPIDAT) & 0x01) == 0x00)
++			return EC_STATE_IDLE;
++		udelay(EC_MAX_DELAY_UNIT);
++	}
++	if (timeout <= 0) {
++		printk(KERN_ERR
++		       "EC_FLASH_BUSY : timeout for check rom flag.\n");
++		return EC_STATE_BUSY;
++	}
++#else
++	/* check the rom's status of busy flag */
++	ec_write(REG_XBISPICMD, SPICMD_READ_STATUS);
++	if (ec_instruction_cycle() < 0)
++		return EC_STATE_BUSY;
++
++	timeout = timeout / EC_MAX_DELAY_UNIT;
++	while (timeout-- > 0) {
++		if ((ec_read(REG_XBISPIDAT) & 0x01) == 0x00)
++			return EC_STATE_IDLE;
++		udelay(EC_MAX_DELAY_UNIT);
++	}
++	if (timeout <= 0) {
++		printk(KERN_ERR
++		       "EC_FLASH_BUSY : timeout for check rom flag.\n");
++		return EC_STATE_BUSY;
++	}
++#endif
++
++	return EC_STATE_IDLE;
++}
++
++static int rom_instruction_cycle(unsigned char cmd)
++{
++	unsigned long timeout = 0;
++
++	switch (cmd) {
++	case SPICMD_READ_STATUS:
++	case SPICMD_WRITE_ENABLE:
++	case SPICMD_WRITE_DISABLE:
++	case SPICMD_READ_BYTE:
++	case SPICMD_HIGH_SPEED_READ:
++		timeout = 0;
++		break;
++	case SPICMD_WRITE_STATUS:
++		timeout = 300 * 1000;
++		break;
++	case SPICMD_BYTE_PROGRAM:
++		timeout = 5 * 1000;
++		break;
++	case SPICMD_SST_SEC_ERASE:
++	case SPICMD_SEC_ERASE:
++		timeout = 1000 * 1000;
++		break;
++	case SPICMD_SST_BLK_ERASE:
++	case SPICMD_BLK_ERASE:
++		timeout = 3 * 1000 * 1000;
++		break;
++	case SPICMD_SST_CHIP_ERASE:
++	case SPICMD_CHIP_ERASE:
++		timeout = 20 * 1000 * 1000;
++		break;
++	default:
++		timeout = EC_SPICMD_STANDARD_TIMEOUT;
++	}
++	if (timeout == 0)
++		return ec_instruction_cycle();
++	if (timeout < EC_SPICMD_STANDARD_TIMEOUT)
++		timeout = EC_SPICMD_STANDARD_TIMEOUT;
++
++	return ec_flash_busy(timeout);
++}
++
++/* delay for start/stop action */
++static void delay_spi(int n)
++{
++	while (n--)
++		inb(EC_IO_PORT_HIGH);
++}
++
++/* start the action to spi rom function */
++static void ec_start_spi(void)
++{
++	unsigned char val;
++
++	delay_spi(SPI_FINISH_WAIT_TIME);
++	val = ec_read(REG_XBISPICFG) | SPICFG_EN_SPICMD | SPICFG_AUTO_CHECK;
++	ec_write(REG_XBISPICFG, val);
++	delay_spi(SPI_FINISH_WAIT_TIME);
++}
++
++/* stop the action to spi rom function */
++static void ec_stop_spi(void)
++{
++	unsigned char val;
++
++	delay_spi(SPI_FINISH_WAIT_TIME);
++	val =
++	    ec_read(REG_XBISPICFG) & (~(SPICFG_EN_SPICMD | SPICFG_AUTO_CHECK));
++	ec_write(REG_XBISPICFG, val);
++	delay_spi(SPI_FINISH_WAIT_TIME);
++}
++
++/* read one byte from xbi interface */
++static int ec_read_byte(unsigned int addr, unsigned char *byte)
++{
++	int ret = 0;
++
++	/* enable spicmd writing. */
++	ec_start_spi();
++
++	/* enable write spi flash */
++	ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE);
++	if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) {
++		printk(KERN_ERR "EC_READ_BYTE : SPICMD_WRITE_ENABLE failed.\n");
++		ret = -EINVAL;
++		goto out;
++	}
++
++	/* write the address */
++	ec_write(REG_XBISPIA2, (addr & 0xff0000) >> 16);
++	ec_write(REG_XBISPIA1, (addr & 0x00ff00) >> 8);
++	ec_write(REG_XBISPIA0, (addr & 0x0000ff) >> 0);
++	/* start action */
++	ec_write(REG_XBISPICMD, SPICMD_HIGH_SPEED_READ);
++	if (rom_instruction_cycle(SPICMD_HIGH_SPEED_READ) == EC_STATE_BUSY) {
++		printk(KERN_ERR
++		       "EC_READ_BYTE : SPICMD_HIGH_SPEED_READ failed.\n");
++		ret = -EINVAL;
++		goto out;
++	}
++
++	*byte = ec_read(REG_XBISPIDAT);
++
++ out:
++	/* disable spicmd writing. */
++	ec_stop_spi();
++
++	return ret;
++}
++
++/* write one byte to ec rom */
++static int ec_write_byte(unsigned int addr, unsigned char byte)
++{
++	int ret = 0;
++
++	/* enable spicmd writing. */
++	ec_start_spi();
++
++	/* enable write spi flash */
++	ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE);
++	if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) {
++		printk(KERN_ERR
++		       "EC_WRITE_BYTE : SPICMD_WRITE_ENABLE failed.\n");
++		ret = -EINVAL;
++		goto out;
++	}
++
++	/* write the address */
++	ec_write(REG_XBISPIA2, (addr & 0xff0000) >> 16);
++	ec_write(REG_XBISPIA1, (addr & 0x00ff00) >> 8);
++	ec_write(REG_XBISPIA0, (addr & 0x0000ff) >> 0);
++	ec_write(REG_XBISPIDAT, byte);
++	/* start action */
++	ec_write(REG_XBISPICMD, SPICMD_BYTE_PROGRAM);
++	if (rom_instruction_cycle(SPICMD_BYTE_PROGRAM) == EC_STATE_BUSY) {
++		printk(KERN_ERR
++		       "EC_WRITE_BYTE : SPICMD_BYTE_PROGRAM failed.\n");
++		ret = -EINVAL;
++		goto out;
++	}
++
++ out:
++	/* disable spicmd writing. */
++	ec_stop_spi();
++
++	return ret;
++}
++
++/* unprotect SPI ROM */
++/* EC_ROM_unprotect function code */
++static int EC_ROM_unprotect(void)
++{
++	unsigned char status;
++
++	/* enable write spi flash */
++	ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE);
++	if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) {
++		printk(KERN_ERR
++		       "EC_UNIT_ERASE : SPICMD_WRITE_ENABLE failed.\n");
++		return 1;
++	}
++
++	/* unprotect the status register of rom */
++	ec_write(REG_XBISPICMD, SPICMD_READ_STATUS);
++	if (rom_instruction_cycle(SPICMD_READ_STATUS) == EC_STATE_BUSY) {
++		printk(KERN_ERR "EC_UNIT_ERASE : SPICMD_READ_STATUS failed.\n");
++		return 1;
++	}
++	status = ec_read(REG_XBISPIDAT);
++	ec_write(REG_XBISPIDAT, status & 0x02);
++	if (ec_instruction_cycle() < 0) {
++		printk(KERN_ERR "EC_UNIT_ERASE : write status value failed.\n");
++		return 1;
++	}
++
++	ec_write(REG_XBISPICMD, SPICMD_WRITE_STATUS);
++	if (rom_instruction_cycle(SPICMD_WRITE_STATUS) == EC_STATE_BUSY) {
++		printk(KERN_ERR
++		       "EC_UNIT_ERASE : SPICMD_WRITE_STATUS failed.\n");
++		return 1;
++	}
++
++	/* enable write spi flash */
++	ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE);
++	if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) {
++		printk(KERN_ERR
++		       "EC_UNIT_ERASE : SPICMD_WRITE_ENABLE failed.\n");
++		return 1;
++	}
++
++	return 0;
++}
++
++/* erase one block or chip or sector as needed */
++static int ec_unit_erase(unsigned char erase_cmd, unsigned int addr)
++{
++	unsigned char status;
++	int ret = 0, i = 0;
++	int unprotect_count = 3;
++	int check_flag = 0;
++
++	/* enable spicmd writing. */
++	ec_start_spi();
++
++#ifdef EC_ROM_PROTECTION
++	/* added for re-check SPICMD_READ_STATUS */
++	while (unprotect_count-- > 0) {
++		if (EC_ROM_unprotect()) {
++			ret = -EINVAL;
++			goto out;
++		}
++
++		/* first time:500ms --> 5.5sec -->10.5sec */
++		for (i = 0; i < ((2 - unprotect_count) * 100 + 10); i++)
++			udelay(50000);
++		ec_write(REG_XBISPICMD, SPICMD_READ_STATUS);
++		if (rom_instruction_cycle(SPICMD_READ_STATUS)
++				== EC_STATE_BUSY) {
++			printk(KERN_ERR
++			       "EC_PROGRAM_ROM : SPICMD_READ_STATUS failed.\n");
++		} else {
++			status = ec_read(REG_XBISPIDAT);
++			printk(KERN_INFO "Read unprotect status : 0x%x\n",
++				   status);
++			if ((status & 0x1C) == 0x00) {
++				printk(KERN_INFO
++					   "Read unprotect status OK1 : 0x%x\n",
++					   status & 0x1C);
++				check_flag = 1;
++				break;
++			}
++		}
++	}
++
++	if (!check_flag) {
++		printk(KERN_INFO "SPI ROM unprotect fail.\n");
++		return 1;
++	}
++#endif
++
++	/* block address fill */
++	if (erase_cmd == SPICMD_BLK_ERASE) {
++		ec_write(REG_XBISPIA2, (addr & 0x00ff0000) >> 16);
++		ec_write(REG_XBISPIA1, (addr & 0x0000ff00) >> 8);
++		ec_write(REG_XBISPIA0, (addr & 0x000000ff) >> 0);
++	}
++
++	/* erase the whole chip first */
++	ec_write(REG_XBISPICMD, erase_cmd);
++	if (rom_instruction_cycle(erase_cmd) == EC_STATE_BUSY) {
++		printk(KERN_ERR "EC_UNIT_ERASE : erase failed.\n");
++		ret = -EINVAL;
++		goto out;
++	}
++
++ out:
++	/* disable spicmd writing. */
++	ec_stop_spi();
++
++	return ret;
++}
++
++/* update the whole rom content with H/W mode
++ * PLEASE USING ec_unit_erase() FIRSTLY
++ */
++static int ec_program_rom(struct ec_info *info, int flag)
++{
++	unsigned int addr = 0;
++	unsigned long size = 0;
++	unsigned char *ptr = NULL;
++	unsigned char data;
++	unsigned char val = 0;
++	int ret = 0;
++	int i, j;
++	unsigned char status;
++
++	/* modify for program serial No.
++	 * set IE_START_ADDR & use idle mode,
++	 * disable WDD
++	 */
++	if (flag == PROGRAM_FLAG_ROM) {
++		ret = ec_init_reset_mode();
++		addr = info->start_addr + EC_START_ADDR;
++		printk(KERN_INFO "PROGRAM_FLAG_ROM..............\n");
++	} else if (flag == PROGRAM_FLAG_IE) {
++		ret = ec_init_idle_mode();
++		ec_disable_WDD();
++		addr = info->start_addr + IE_START_ADDR;
++		printk(KERN_INFO "PROGRAM_FLAG_IE..............\n");
++	} else {
++		return 0;
++	}
++
++	if (ret < 0) {
++		if (flag == PROGRAM_FLAG_IE)
++			ec_enable_WDD();
++		return ret;
++	}
++
++	size = info->size;
++	ptr = info->buf;
++	printk(KERN_INFO "starting update ec ROM..............\n");
++
++	ret = ec_unit_erase(SPICMD_BLK_ERASE, addr);
++	if (ret) {
++		printk(KERN_ERR "program ec : erase block failed.\n");
++		goto out;
++	}
++	printk(KERN_ERR "program ec : erase block OK.\n");
++
++	i = 0;
++	while (i < size) {
++		data = *(ptr + i);
++		ec_write_byte(addr, data);
++		ec_read_byte(addr, &val);
++		if (val != data) {
++			ec_write_byte(addr, data);
++			ec_read_byte(addr, &val);
++			if (val != data) {
++				printk(KERN_INFO
++				"EC : Second flash program failed at:\t");
++				printk(KERN_INFO
++				"addr : 0x%x, source : 0x%x, dest: 0x%x\n",
++				     addr, data, val);
++				printk(KERN_INFO "This should not happen... STOP\n");
++				break;
++			}
++		}
++		i++;
++		addr++;
++	}
++
++#ifdef	EC_ROM_PROTECTION
++	/* we should start spi access firstly */
++	ec_start_spi();
++
++	/* enable write spi flash */
++	ec_write(REG_XBISPICMD, SPICMD_WRITE_ENABLE);
++	if (rom_instruction_cycle(SPICMD_WRITE_ENABLE) == EC_STATE_BUSY) {
++		printk(KERN_ERR
++		       "EC_PROGRAM_ROM : SPICMD_WRITE_ENABLE failed.\n");
++		goto out1;
++	}
++
++	/* protect the status register of rom */
++	ec_write(REG_XBISPICMD, SPICMD_READ_STATUS);
++	if (rom_instruction_cycle(SPICMD_READ_STATUS) == EC_STATE_BUSY) {
++		printk(KERN_ERR
++		       "EC_PROGRAM_ROM : SPICMD_READ_STATUS failed.\n");
++		goto out1;
++	}
++	status = ec_read(REG_XBISPIDAT);
++
++	ec_write(REG_XBISPIDAT, status | 0x1C);
++	if (ec_instruction_cycle() < 0) {
++		printk(KERN_ERR
++		       "EC_PROGRAM_ROM : write status value failed.\n");
++		goto out1;
++	}
++
++	ec_write(REG_XBISPICMD, SPICMD_WRITE_STATUS);
++	if (rom_instruction_cycle(SPICMD_WRITE_STATUS) == EC_STATE_BUSY) {
++		printk(KERN_ERR
++		       "EC_PROGRAM_ROM : SPICMD_WRITE_STATUS failed.\n");
++		goto out1;
++	}
++#endif
++
++	/* disable the write action to spi rom */
++	ec_write(REG_XBISPICMD, SPICMD_WRITE_DISABLE);
++	if (rom_instruction_cycle(SPICMD_WRITE_DISABLE) == EC_STATE_BUSY) {
++		printk(KERN_ERR
++		       "EC_PROGRAM_ROM : SPICMD_WRITE_DISABLE failed.\n");
++		goto out1;
++	}
++
++ out1:
++	/* we should stop spi access firstly */
++	ec_stop_spi();
++ out:
++	/* for security */
++	for (j = 0; j < 2000; j++)
++		udelay(1000);
++
++	/* modify for program serial No.
++	 * after program No exit idle mode
++	 * and enable WDD
++	 */
++	if (flag == PROGRAM_FLAG_ROM) {
++		/* exit from the reset mode */
++		ec_exit_reset_mode();
++	} else {
++		/* ec exit from idle mode */
++		ret = ec_exit_idle_mode();
++		ec_enable_WDD();
++		if (ret < 0)
++			return ret;
++	}
++
++	return 0;
++}
++
++/* ioctl  */
++static int misc_ioctl(struct inode *inode, struct file *filp, u_int cmd,
++		      u_long arg)
++{
++	struct ec_info ecinfo;
++	void __user *ptr = (void __user *)arg;
++	struct ec_reg *ecreg = (struct ec_reg *)(filp->private_data);
++	int ret = 0;
++
++	switch (cmd) {
++	case IOCTL_RDREG:
++		ret = copy_from_user(ecreg, ptr, sizeof(struct ec_reg));
++		if (ret) {
++			printk(KERN_ERR "reg read : copy from user error.\n");
++			return -EFAULT;
++		}
++		if ((ecreg->addr > EC_MAX_REGADDR)
++		    || (ecreg->addr < EC_MIN_REGADDR)) {
++			printk(KERN_ERR
++			       "reg read : out of register address range.\n");
++			return -EINVAL;
++		}
++		ecreg->val = ec_read(ecreg->addr);
++		ret = copy_to_user(ptr, ecreg, sizeof(struct ec_reg));
++		if (ret) {
++			printk(KERN_ERR "reg read : copy to user error.\n");
++			return -EFAULT;
++		}
++		break;
++	case IOCTL_WRREG:
++		ret = copy_from_user(ecreg, ptr, sizeof(struct ec_reg));
++		if (ret) {
++			printk(KERN_ERR "reg write : copy from user error.\n");
++			return -EFAULT;
++		}
++		if ((ecreg->addr > EC_MAX_REGADDR)
++		    || (ecreg->addr < EC_MIN_REGADDR)) {
++			printk(KERN_ERR
++			       "reg write : out of register address range.\n");
++			return -EINVAL;
++		}
++		ec_write(ecreg->addr, ecreg->val);
++		break;
++	case IOCTL_READ_EC:
++		ret = copy_from_user(ecreg, ptr, sizeof(struct ec_reg));
++		if (ret) {
++			printk(KERN_ERR "spi read : copy from user error.\n");
++			return -EFAULT;
++		}
++		if ((ecreg->addr > EC_RAM_ADDR)
++		    && (ecreg->addr < EC_MAX_REGADDR)) {
++			printk(KERN_ERR
++			       "spi read : out of register address range.\n");
++			return -EINVAL;
++		}
++		ec_read_byte(ecreg->addr, &(ecreg->val));
++		ret = copy_to_user(ptr, ecreg, sizeof(struct ec_reg));
++		if (ret) {
++			printk(KERN_ERR "spi read : copy to user error.\n");
++			return -EFAULT;
++		}
++		break;
++	case IOCTL_PROGRAM_IE:
++		ecinfo.start_addr = EC_START_ADDR;
++		ecinfo.size = EC_CONTENT_MAX_SIZE;
++		ecinfo.buf = (u8 *) kmalloc(ecinfo.size, GFP_KERNEL);
++		if (ecinfo.buf == NULL) {
++			printk(KERN_ERR "program ie : kmalloc failed.\n");
++			return -ENOMEM;
++		}
++		ret = copy_from_user(ecinfo.buf, (u8 *) ptr, ecinfo.size);
++		if (ret) {
++			printk(KERN_ERR "program ie : copy from user error.\n");
++			kfree(ecinfo.buf);
++			ecinfo.buf = NULL;
++			return -EFAULT;
++		}
++
++		/* use ec_program_rom to write serial No */
++		ec_program_rom(&ecinfo, PROGRAM_FLAG_IE);
++
++		kfree(ecinfo.buf);
++		ecinfo.buf = NULL;
++		break;
++	case IOCTL_PROGRAM_EC:
++		ecinfo.start_addr = EC_START_ADDR;
++		if (get_user((ecinfo.size), (u32 *) ptr)) {
++			printk(KERN_ERR "program ec : get user error.\n");
++			return -EFAULT;
++		}
++		if ((ecinfo.size) > EC_CONTENT_MAX_SIZE) {
++			printk(KERN_ERR "program ec : size out of limited.\n");
++			return -EINVAL;
++		}
++		ecinfo.buf = (u8 *) kmalloc(ecinfo.size, GFP_KERNEL);
++		if (ecinfo.buf == NULL) {
++			printk(KERN_ERR "program ec : kmalloc failed.\n");
++			return -ENOMEM;
++		}
++		ret = copy_from_user(ecinfo.buf, ((u8 *) ptr + 4), ecinfo.size);
++		if (ret) {
++			printk(KERN_ERR "program ec : copy from user error.\n");
++			kfree(ecinfo.buf);
++			ecinfo.buf = NULL;
++			return -EFAULT;
++		}
++
++		ec_program_rom(&ecinfo, PROGRAM_FLAG_ROM);
++
++		kfree(ecinfo.buf);
++		ecinfo.buf = NULL;
++		break;
++
++	default:
++		break;
++	}
++
++	return 0;
++}
++
++static long misc_compat_ioctl(struct file *file, unsigned int cmd,
++			      unsigned long arg)
++{
++	return misc_ioctl(file->f_dentry->d_inode, file, cmd, arg);
++}
++
++static int misc_open(struct inode *inode, struct file *filp)
++{
++	struct ec_reg *ecreg = NULL;
++	ecreg = kmalloc(sizeof(struct ec_reg), GFP_KERNEL);
++	if (ecreg)
++		filp->private_data = ecreg;
++
++	return ecreg ? 0 : -ENOMEM;
++}
++
++static int misc_release(struct inode *inode, struct file *filp)
++{
++	struct ec_reg *ecreg = (struct ec_reg *)(filp->private_data);
++
++	filp->private_data = NULL;
++	kfree(ecreg);
++
++	return 0;
++}
++
++static const struct file_operations ecmisc_fops = {
++	.open = misc_open,
++	.release = misc_release,
++	.read = NULL,
++	.write = NULL,
++#ifdef	CONFIG_64BIT
++	.compat_ioctl = misc_compat_ioctl,
++#else
++	.ioctl = misc_ioctl,
++#endif
++};
++
++static struct miscdevice ecmisc_device = {
++	.minor = MISC_DYNAMIC_MINOR,
++	.name = EC_MISC_DEV,
++	.fops = &ecmisc_fops
++};
++
++static int __init ecmisc_init(void)
++{
++	int ret;
++
++	printk(KERN_INFO "EC misc device init.\n");
++	ret = misc_register(&ecmisc_device);
++
++	return ret;
++}
++
++static void __exit ecmisc_exit(void)
++{
++	printk(KERN_INFO "EC misc device exit.\n");
++	misc_deregister(&ecmisc_device);
++}
++
++module_init(ecmisc_init);
++module_exit(ecmisc_exit);
++
++MODULE_AUTHOR("liujl <liujl@lemote.com>");
++MODULE_DESCRIPTION("Driver for flushing/dumping ROM of EC on YeeLoong laptop");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/platform/mips/yeeloong_laptop.c b/drivers/platform/mips/yeeloong_laptop.c
+new file mode 100644
+index 0000000..9f2d81b
+--- /dev/null
++++ b/drivers/platform/mips/yeeloong_laptop.c
+@@ -0,0 +1,1368 @@
++/*
++ * Driver for YeeLoong laptop extras
++ *
++ *  Copyright (C) 2009 Lemote Inc.
++ *  Author: Wu Zhangjin <wuzhangjin@gmail.com>, Liu Junliang <liujl@lemote.com>
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License version 2 as
++ *  published by the Free Software Foundation.
++ */
++
++#include <linux/err.h>
++#include <linux/module.h>
++#include <linux/platform_device.h>
++#include <linux/backlight.h>	/* for backlight subdriver */
++#include <linux/fb.h>
++#include <linux/hwmon.h>	/* for hwmon subdriver */
++#include <linux/hwmon-sysfs.h>
++#include <linux/video_output.h>	/* for video output subdriver */
++#include <linux/lcd.h>		/* for lcd output subdriver */
++#include <linux/input.h>	/* for hotkey subdriver */
++#include <linux/input/sparse-keymap.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/power_supply.h>	/* for AC & Battery subdriver */
++#include <linux/reboot.h>	/* for register_reboot_notifier */
++#include <linux/suspend.h>	/* for register_pm_notifier */
++
++#include <cs5536/cs5536.h>
++
++#include <loongson.h>		/* for loongson_cmdline */
++#include <ec_kb3310b.h>
++
++#define ON	1
++#define OFF	0
++#define EVENT_START EVENT_LID
++
++/* common function */
++#define EC_VER_LEN 64
++
++static int ec_version_before(char *version)
++{
++	char *p, ec_ver[EC_VER_LEN];
++
++	p = strstr(loongson_cmdline, "EC_VER=");
++	if (!p)
++		memset(ec_ver, 0, EC_VER_LEN);
++	else {
++		strncpy(ec_ver, p, EC_VER_LEN);
++		p = strstr(ec_ver, " ");
++		if (p)
++			*p = '\0';
++	}
++
++	return (strncasecmp(ec_ver, version, 64) < 0);
++}
++
++/* backlight subdriver */
++#define MIN_BRIGHTNESS	1
++#define MAX_BRIGHTNESS	8
++
++static int yeeloong_set_brightness(struct backlight_device *bd)
++{
++	unsigned char level;
++	static unsigned char old_level;
++
++	level = (bd->props.fb_blank == FB_BLANK_UNBLANK &&
++		 bd->props.power == FB_BLANK_UNBLANK) ?
++	    bd->props.brightness : 0;
++
++	level = clamp_val(level, MIN_BRIGHTNESS, MAX_BRIGHTNESS);
++
++	/* Avoid to modify the brightness when EC is tuning it */
++	if (old_level != level) {
++		if (ec_read(REG_DISPLAY_BRIGHTNESS) == old_level)
++			ec_write(REG_DISPLAY_BRIGHTNESS, level);
++		old_level = level;
++	}
++
++	return 0;
++}
++
++static int yeeloong_get_brightness(struct backlight_device *bd)
++{
++	return ec_read(REG_DISPLAY_BRIGHTNESS);
++}
++
++static struct backlight_ops backlight_ops = {
++	.get_brightness = yeeloong_get_brightness,
++	.update_status = yeeloong_set_brightness,
++};
++
++static struct backlight_device *yeeloong_backlight_dev;
++
++static int yeeloong_backlight_init(void)
++{
++	int ret;
++	struct backlight_properties props;
++
++	memset(&props, 0, sizeof(struct backlight_properties));
++	props.max_brightness = MAX_BRIGHTNESS;
++	props.type = BACKLIGHT_PLATFORM;
++	yeeloong_backlight_dev = backlight_device_register("backlight0", NULL,
++			NULL, &backlight_ops, &props);
++
++	if (IS_ERR(yeeloong_backlight_dev)) {
++		ret = PTR_ERR(yeeloong_backlight_dev);
++		yeeloong_backlight_dev = NULL;
++		return ret;
++	}
++
++	yeeloong_backlight_dev->props.brightness =
++		yeeloong_get_brightness(yeeloong_backlight_dev);
++	backlight_update_status(yeeloong_backlight_dev);
++
++	return 0;
++}
++
++static void yeeloong_backlight_exit(void)
++{
++	if (yeeloong_backlight_dev) {
++		backlight_device_unregister(yeeloong_backlight_dev);
++		yeeloong_backlight_dev = NULL;
++	}
++}
++
++/* AC & Battery subdriver */
++
++static struct power_supply_desc yeeloong_ac_desc, yeeloong_bat_desc;
++
++#define RET (val->intval)
++
++#define BAT_CAP_CRITICAL 5
++#define BAT_CAP_HIGH     95
++
++#define get_bat(type) \
++	ec_read(REG_BAT_##type)
++
++#define get_bat_l(type) \
++	((get_bat(type##_HIGH) << 8) | get_bat(type##_LOW))
++
++static int yeeloong_get_ac_props(struct power_supply *psy,
++				enum power_supply_property psp,
++				union power_supply_propval *val)
++{
++	if (psp == POWER_SUPPLY_PROP_ONLINE)
++		RET = !!(get_bat(POWER) & BIT_BAT_POWER_ACIN);
++
++	return 0;
++}
++
++static enum power_supply_property yeeloong_ac_props[] = {
++	POWER_SUPPLY_PROP_ONLINE,
++};
++
++static struct power_supply_desc yeeloong_ac_desc = {
++	.name = "yeeloong-ac",
++	.type = POWER_SUPPLY_TYPE_MAINS,
++	.properties = yeeloong_ac_props,
++	.num_properties = ARRAY_SIZE(yeeloong_ac_props),
++	.get_property = yeeloong_get_ac_props,
++};
++
++static inline bool is_bat_in(void)
++{
++	return !!(get_bat(STATUS) & BIT_BAT_STATUS_IN);
++}
++
++static int get_bat_temp(void)
++{
++	return get_bat_l(TEMPERATURE) * 10;
++}
++
++static int get_bat_current(void)
++{
++	return -(s16)get_bat_l(CURRENT);
++}
++
++static int get_bat_voltage(void)
++{
++	return get_bat_l(VOLTAGE);
++}
++
++static char *get_manufacturer(void)
++{
++	return (get_bat(VENDOR) == FLAG_BAT_VENDOR_SANYO) ? "SANYO" : "SIMPLO";
++}
++
++static int get_relative_cap(void)
++{
++	/*
++	 * When the relative capacity becomes 2, the hardware is observed to
++	 * have been turned off forcely. so, we must tune it be suitable to
++	 * make the software do related actions.
++	 */
++	int tmp = get_bat_l(RELATIVE_CAP);
++
++	if (tmp <= (BAT_CAP_CRITICAL * 2))
++		tmp -= 3;
++
++	return tmp;
++}
++
++static int yeeloong_get_bat_props(struct power_supply *psy,
++				     enum power_supply_property psp,
++				     union power_supply_propval *val)
++{
++	switch (psp) {
++	/* Fixed information */
++	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
++		/* mV -> µV */
++		RET = get_bat_l(DESIGN_VOL) * 1000;
++		break;
++	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
++		/* mAh->µAh */
++		RET = get_bat_l(DESIGN_CAP) * 1000;
++		break;
++	case POWER_SUPPLY_PROP_CHARGE_FULL:
++		/* µAh */
++		RET = get_bat_l(FULLCHG_CAP) * 1000;
++		break;
++	case POWER_SUPPLY_PROP_MANUFACTURER:
++		val->strval = get_manufacturer();
++		break;
++	/* Dynamic information */
++	case POWER_SUPPLY_PROP_PRESENT:
++		RET = is_bat_in();
++		break;
++	case POWER_SUPPLY_PROP_CURRENT_NOW:
++		/* mA -> µA */
++		RET = is_bat_in() ? get_bat_current() * 1000 : 0;
++		break;
++	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
++		/* mV -> µV */
++		RET = is_bat_in() ? get_bat_voltage() * 1000 : 0;
++		break;
++	case POWER_SUPPLY_PROP_TEMP:
++		/* Celcius */
++		RET = is_bat_in() ? get_bat_temp() : 0;
++		break;
++	case POWER_SUPPLY_PROP_CAPACITY:
++		RET = is_bat_in() ? get_relative_cap() : 0;
++		break;
++	case POWER_SUPPLY_PROP_CAPACITY_LEVEL: {
++		int status;
++
++		if (!is_bat_in()) {
++			RET = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
++			break;
++		}
++
++		status = get_bat(STATUS);
++		RET = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
++
++		if (unlikely(status & BIT_BAT_STATUS_DESTROY)) {
++			RET = POWER_SUPPLY_CAPACITY_LEVEL_UNKNOWN;
++			break;
++		}
++
++		if (status & BIT_BAT_STATUS_FULL)
++			RET = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
++		else {
++			int curr_cap = get_relative_cap();
++
++			if (status & BIT_BAT_STATUS_LOW) {
++				RET = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
++				if (curr_cap <= BAT_CAP_CRITICAL)
++					RET = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
++			} else if (curr_cap >= BAT_CAP_HIGH)
++				RET = POWER_SUPPLY_CAPACITY_LEVEL_HIGH;
++		}
++	} break;
++	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
++		/* seconds */
++		RET = is_bat_in() ? (get_relative_cap() - 3) * 54 + 142 : 0;
++		break;
++	case POWER_SUPPLY_PROP_STATUS: {
++			int charge = get_bat(CHARGE);
++
++			RET = POWER_SUPPLY_STATUS_UNKNOWN;
++			if (charge & FLAG_BAT_CHARGE_DISCHARGE)
++				RET = POWER_SUPPLY_STATUS_DISCHARGING;
++			else if (charge & FLAG_BAT_CHARGE_CHARGE)
++				RET = POWER_SUPPLY_STATUS_CHARGING;
++	} break;
++	case POWER_SUPPLY_PROP_HEALTH: {
++			int status;
++
++			if (!is_bat_in()) {
++				RET = POWER_SUPPLY_HEALTH_UNKNOWN;
++				break;
++			}
++
++			status = get_bat(STATUS);
++			RET = POWER_SUPPLY_HEALTH_GOOD;
++
++			if (status & (BIT_BAT_STATUS_DESTROY |
++						BIT_BAT_STATUS_LOW))
++				RET = POWER_SUPPLY_HEALTH_DEAD;
++			if (get_bat(CHARGE_STATUS) &
++					BIT_BAT_CHARGE_STATUS_OVERTEMP)
++				RET = POWER_SUPPLY_HEALTH_OVERHEAT;
++	} break;
++	case POWER_SUPPLY_PROP_CHARGE_NOW:	/* 1/100(%)*1000 µAh */
++		RET = get_relative_cap() * get_bat_l(FULLCHG_CAP) * 10;
++		break;
++	default:
++		return -EINVAL;
++	}
++	return 0;
++}
++#undef RET
++
++static enum power_supply_property yeeloong_bat_props[] = {
++	POWER_SUPPLY_PROP_STATUS,
++	POWER_SUPPLY_PROP_PRESENT,
++	POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
++	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
++	POWER_SUPPLY_PROP_CHARGE_FULL,
++	POWER_SUPPLY_PROP_CHARGE_NOW,
++	POWER_SUPPLY_PROP_CURRENT_NOW,
++	POWER_SUPPLY_PROP_VOLTAGE_NOW,
++	POWER_SUPPLY_PROP_HEALTH,
++	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
++	POWER_SUPPLY_PROP_CAPACITY,
++	POWER_SUPPLY_PROP_CAPACITY_LEVEL,
++	POWER_SUPPLY_PROP_TEMP,
++	POWER_SUPPLY_PROP_MANUFACTURER,
++};
++
++static struct power_supply_desc yeeloong_bat_desc = {
++	.name = "yeeloong-bat",
++	.type = POWER_SUPPLY_TYPE_BATTERY,
++	.properties = yeeloong_bat_props,
++	.num_properties = ARRAY_SIZE(yeeloong_bat_props),
++	.get_property = yeeloong_get_bat_props,
++};
++
++static struct power_supply *yeeloong_ac, *yeeloong_bat;
++
++static int yeeloong_bat_init(void)
++{
++	struct power_supply *ac, *bat;
++
++	ac = power_supply_register(NULL, &yeeloong_ac_desc, NULL);
++	if (IS_ERR(ac))
++		return PTR_ERR(ac);
++	
++	bat = power_supply_register(NULL, &yeeloong_bat_desc, NULL);
++	if (IS_ERR(bat)) {
++		power_supply_unregister(ac);
++		return PTR_ERR(bat);
++	}
++
++	yeeloong_ac = ac;
++	yeeloong_bat = bat;
++
++	return 0;
++}
++
++static void yeeloong_bat_exit(void)
++{
++	struct power_supply *temp;
++
++	temp = yeeloong_ac;
++	yeeloong_ac = NULL;
++	power_supply_unregister(temp);
++
++	temp = yeeloong_bat;
++	yeeloong_bat = NULL;
++	power_supply_unregister(temp);
++}
++/* hwmon subdriver */
++
++#define MIN_FAN_SPEED 0
++#define MAX_FAN_SPEED 3
++
++#define get_fan(type) \
++	ec_read(REG_FAN_##type)
++
++#define set_fan(type, val) \
++	ec_write(REG_FAN_##type, val)
++
++static inline int get_fan_speed_level(void)
++{
++	return get_fan(SPEED_LEVEL);
++}
++static inline void set_fan_speed_level(int speed)
++{
++	set_fan(SPEED_LEVEL, speed);
++}
++
++static inline int get_fan_mode(void)
++{
++	return get_fan(AUTO_MAN_SWITCH);
++}
++static inline void set_fan_mode(int mode)
++{
++	set_fan(AUTO_MAN_SWITCH, mode);
++}
++
++/*
++ * 3 different modes: Full speed(0); manual mode(1); auto mode(2)
++ */
++static int get_fan_pwm_enable(void)
++{
++	return (get_fan_mode() == BIT_FAN_AUTO) ? 2 :
++		(get_fan_speed_level() == MAX_FAN_SPEED) ? 0 : 1;
++}
++
++static void set_fan_pwm_enable(int mode)
++{
++	set_fan_mode((mode == 2) ? BIT_FAN_AUTO : BIT_FAN_MANUAL);
++	if (mode == 0)
++		set_fan_speed_level(MAX_FAN_SPEED);
++}
++
++static int get_fan_pwm(void)
++{
++	return get_fan_speed_level();
++}
++
++static void set_fan_pwm(int value)
++{
++	if (get_fan_mode() != BIT_FAN_MANUAL)
++		return;
++
++	value = clamp_val(value, MIN_FAN_SPEED, MAX_FAN_SPEED);
++
++	/* We must ensure the fan is on */
++	if (value > 0)
++		set_fan(CONTROL, ON);
++
++	set_fan_speed_level(value);
++}
++
++static inline int get_fan_speed(void)
++{
++	return ((get_fan(SPEED_HIGH) & 0x0f) << 8) | get_fan(SPEED_LOW);
++}
++
++static int get_fan_rpm(void)
++{
++	return FAN_SPEED_DIVIDER / get_fan_speed();
++}
++
++static int get_cpu_temp(void)
++{
++	return (s8)ec_read(REG_TEMPERATURE_VALUE) * 1000;
++}
++
++static int get_cpu_temp_max(void)
++{
++	return 60 * 1000;
++}
++
++static int get_bat_temp_alarm(void)
++{
++	return !!(get_bat(CHARGE_STATUS) & BIT_BAT_CHARGE_STATUS_OVERTEMP);
++}
++
++static ssize_t store_sys_hwmon(void (*set) (int), const char *buf, size_t count)
++{
++	int ret;
++	unsigned long value;
++
++	if (!count)
++		return 0;
++
++	ret = kstrtoul(buf, 10, &value);
++	if (ret)
++		return ret;
++
++	set(value);
++
++	return count;
++}
++
++static ssize_t show_sys_hwmon(int (*get) (void), char *buf)
++{
++	return sprintf(buf, "%d\n", get());
++}
++
++#define CREATE_SENSOR_ATTR(_name, _mode, _set, _get)		\
++	static ssize_t show_##_name(struct device *dev,			\
++				    struct device_attribute *attr,	\
++				    char *buf)				\
++	{								\
++		return show_sys_hwmon(_set, buf);			\
++	}								\
++	static ssize_t store_##_name(struct device *dev,		\
++				     struct device_attribute *attr,	\
++				     const char *buf, size_t count)	\
++	{								\
++		return store_sys_hwmon(_get, buf, count);		\
++	}								\
++	static SENSOR_DEVICE_ATTR(_name, _mode, show_##_name, store_##_name, 0);
++
++CREATE_SENSOR_ATTR(fan1_input, S_IRUGO, get_fan_rpm, NULL);
++CREATE_SENSOR_ATTR(pwm1, S_IRUGO | S_IWUSR, get_fan_pwm, set_fan_pwm);
++CREATE_SENSOR_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, get_fan_pwm_enable,
++		set_fan_pwm_enable);
++CREATE_SENSOR_ATTR(temp1_input, S_IRUGO, get_cpu_temp, NULL);
++CREATE_SENSOR_ATTR(temp1_max, S_IRUGO, get_cpu_temp_max, NULL);
++CREATE_SENSOR_ATTR(temp2_input, S_IRUGO, get_bat_temp, NULL);
++CREATE_SENSOR_ATTR(temp2_max_alarm, S_IRUGO, get_bat_temp_alarm, NULL);
++CREATE_SENSOR_ATTR(curr1_input, S_IRUGO, get_bat_current, NULL);
++CREATE_SENSOR_ATTR(in1_input, S_IRUGO, get_bat_voltage, NULL);
++
++static ssize_t
++show_name(struct device *dev, struct device_attribute *attr, char *buf)
++{
++	return sprintf(buf, "yeeloong\n");
++}
++
++static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
++
++static struct attribute *hwmon_attributes[] = {
++	&sensor_dev_attr_pwm1.dev_attr.attr,
++	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
++	&sensor_dev_attr_fan1_input.dev_attr.attr,
++	&sensor_dev_attr_temp1_input.dev_attr.attr,
++	&sensor_dev_attr_temp1_max.dev_attr.attr,
++	&sensor_dev_attr_temp2_input.dev_attr.attr,
++	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
++	&sensor_dev_attr_curr1_input.dev_attr.attr,
++	&sensor_dev_attr_in1_input.dev_attr.attr,
++	&sensor_dev_attr_name.dev_attr.attr,
++	NULL
++};
++
++static struct attribute_group hwmon_attribute_group = {
++	.attrs = hwmon_attributes
++};
++
++static struct device *yeeloong_hwmon_dev;
++
++static int yeeloong_hwmon_init(void)
++{
++	int ret;
++
++	yeeloong_hwmon_dev = hwmon_device_register(NULL);
++	if (IS_ERR(yeeloong_hwmon_dev)) {
++		yeeloong_hwmon_dev = NULL;
++		return PTR_ERR(yeeloong_hwmon_dev);
++	}
++	ret = sysfs_create_group(&yeeloong_hwmon_dev->kobj,
++				 &hwmon_attribute_group);
++	if (ret) {
++		hwmon_device_unregister(yeeloong_hwmon_dev);
++		yeeloong_hwmon_dev = NULL;
++		return ret;
++	}
++	/* ensure fan is set to auto mode */
++	set_fan_pwm_enable(2);
++
++	return 0;
++}
++
++static void yeeloong_hwmon_exit(void)
++{
++	if (yeeloong_hwmon_dev) {
++		sysfs_remove_group(&yeeloong_hwmon_dev->kobj,
++				   &hwmon_attribute_group);
++		hwmon_device_unregister(yeeloong_hwmon_dev);
++		yeeloong_hwmon_dev = NULL;
++	}
++}
++
++/* video output subdriver */
++
++#define LCD	0
++#define CRT	1
++#define VOD_NUM	2	/* The total number of video output device*/
++
++static struct output_device *vod[VOD_NUM];
++
++static int vor[] = {REG_DISPLAY_LCD, REG_CRT_DETECT};
++
++static int get_vo_dev(struct output_device *od)
++{
++	int i, dev;
++
++	dev = -1;
++	for (i = 0; i < VOD_NUM; i++)
++		if (od == vod[i])
++			dev = i;
++
++	return dev;
++}
++
++static int vo_get_status(int dev)
++{
++	return ec_read(vor[dev]);
++}
++
++static int yeeloong_vo_get_status(struct output_device *od)
++{
++	int vd;
++
++	vd = get_vo_dev(od);
++	if (vd != -1)
++		return vo_get_status(vd);
++
++	return -ENODEV;
++}
++
++static void vo_set_state(int dev, int state)
++{
++	int addr;
++	unsigned long value;
++
++	switch (dev) {
++	case LCD:
++		addr = 0x31;
++		break;
++	case CRT:
++		addr = 0x21;
++		break;
++	default:
++		/* return directly if the wrong video output device */
++		return;
++	}
++
++	outb(addr, 0x3c4);
++	value = inb(0x3c5);
++
++	switch (dev) {
++	case LCD:
++		value |= (state ? 0x03 : 0x02);
++		break;
++	case CRT:
++		if (state)
++			clear_bit(7, &value);
++		else
++			set_bit(7, &value);
++		break;
++	default:
++		break;
++	}
++
++	outb(addr, 0x3c4);
++	outb(value, 0x3c5);
++
++	if (dev == LCD)
++		ec_write(REG_BACKLIGHT_CTRL, state);
++}
++
++static int yeeloong_vo_set_state(struct output_device *od)
++{
++	int vd;
++
++	vd = get_vo_dev(od);
++	if (vd == -1)
++		return -ENODEV;
++
++	if (vd == CRT && !vo_get_status(vd))
++		return 0;
++
++	vo_set_state(vd, !!od->request_state);
++
++	return 0;
++}
++
++static struct output_properties vop = {
++	.set_state = yeeloong_vo_set_state,
++	.get_status = yeeloong_vo_get_status,
++};
++
++static int yeeloong_vo_init(void)
++{
++	int ret, i;
++	char dev_name[VOD_NUM][4] = {"LCD", "CRT"};
++
++	/* Register video output device: lcd, crt */
++	for (i = 0; i < VOD_NUM; i++) {
++		vod[i] = video_output_register(dev_name[i], NULL, NULL, &vop);
++		if (IS_ERR(vod[i])) {
++			if (i != 0)
++				video_output_unregister(vod[i-1]);
++			ret = PTR_ERR(vod[i]);
++			vod[i] = NULL;
++			return ret;
++		}
++	}
++	/* Ensure LCD is on by default */
++	vo_set_state(LCD, ON);
++
++	/*
++	 * Turn off CRT by default, and will be enabled when the CRT
++	 * connectting event reported by SCI
++	 */
++	vo_set_state(CRT, OFF);
++
++	return 0;
++}
++
++static void yeeloong_vo_exit(void)
++{
++	int i;
++
++	for (i = 0; i < VOD_NUM; i++) {
++		if (vod[i]) {
++			video_output_unregister(vod[i]);
++			vod[i] = NULL;
++		}
++	}
++}
++
++/* lcd subdriver */
++
++struct lcd_device *lcd[VOD_NUM];
++
++static int get_lcd_dev(struct lcd_device *ld)
++{
++	int i, dev;
++
++	dev = -1;
++	for (i = 0; i < VOD_NUM; i++)
++		if (ld == lcd[i])
++			dev = i;
++
++	return dev;
++}
++
++static int yeeloong_lcd_set_power(struct lcd_device *ld, int power)
++{
++	int dev = get_lcd_dev(ld);
++
++	if (power == FB_BLANK_UNBLANK)
++		vo_set_state(dev, ON);
++	if (power == FB_BLANK_POWERDOWN)
++		vo_set_state(dev, OFF);
++
++	return 0;
++}
++
++static int yeeloong_lcd_get_power(struct lcd_device *ld)
++{
++	return vo_get_status(get_lcd_dev(ld));
++}
++
++static struct lcd_ops lcd_ops = {
++	.set_power = yeeloong_lcd_set_power,
++	.get_power = yeeloong_lcd_get_power,
++};
++
++static int yeeloong_lcd_init(void)
++{
++	int ret, i;
++	char dev_name[VOD_NUM][4] = {"LCD", "CRT"};
++
++	/* Register video output device: lcd, crt */
++	for (i = 0; i < VOD_NUM; i++) {
++		lcd[i] = lcd_device_register(dev_name[i], NULL, NULL, &lcd_ops);
++		if (IS_ERR(lcd[i])) {
++			if (i != 0)
++				lcd_device_unregister(lcd[i-1]);
++			ret = PTR_ERR(lcd[i]);
++			lcd[i] = NULL;
++			return ret;
++		}
++	}
++#if 0
++	/* This has been done by the vide output driver */
++
++	/* Ensure LCD is on by default */
++	vo_set_state(LCD, ON);
++
++	/*
++	 * Turn off CRT by default, and will be enabled when the CRT
++	 * connectting event reported by SCI
++	 */
++	vo_set_state(CRT, OFF);
++#endif
++	return 0;
++}
++
++static void yeeloong_lcd_exit(void)
++{
++	int i;
++
++	for (i = 0; i < VOD_NUM; i++) {
++		if (lcd[i]) {
++			lcd_device_unregister(lcd[i]);
++			lcd[i] = NULL;
++		}
++	}
++}
++
++/* hotkey subdriver */
++
++static struct input_dev *yeeloong_hotkey_dev;
++
++static atomic_t reboot_flag, sleep_flag;
++#define in_sleep() (&sleep_flag)
++#define in_reboot() (&reboot_flag)
++
++static const struct key_entry yeeloong_keymap[] = {
++	{KE_SW, EVENT_LID, { SW_LID } },
++	{KE_KEY, EVENT_CAMERA, { KEY_CAMERA } }, /* Fn + ESC */
++	{KE_KEY, EVENT_SLEEP, { KEY_SLEEP } }, /* Fn + F1 */
++	{KE_KEY, EVENT_BLACK_SCREEN, { KEY_DISPLAYTOGGLE } }, /* Fn + F2 */
++	{KE_KEY, EVENT_DISPLAY_TOGGLE, { KEY_SWITCHVIDEOMODE } }, /* Fn + F3 */
++	{KE_KEY, EVENT_AUDIO_MUTE, { KEY_MUTE } }, /* Fn + F4 */
++	{KE_KEY, EVENT_WLAN, { KEY_WLAN } }, /* Fn + F5 */
++	{KE_KEY, EVENT_DISPLAY_BRIGHTNESS, { KEY_BRIGHTNESSUP } }, /* Fn + up */
++	{KE_KEY, EVENT_DISPLAY_BRIGHTNESS, { KEY_BRIGHTNESSDOWN } }, /* Fn + down */
++	{KE_KEY, EVENT_AUDIO_VOLUME, { KEY_VOLUMEUP } }, /* Fn + right */
++	{KE_KEY, EVENT_AUDIO_VOLUME, { KEY_VOLUMEDOWN } }, /* Fn + left */
++	{KE_END, 0}
++};
++
++static int is_fake_event(u16 keycode)
++{
++	switch (keycode) {
++	case KEY_SLEEP:
++	case SW_LID:
++		return atomic_read(in_sleep()) | atomic_read(in_reboot());
++		break;
++	default:
++		break;
++	}
++	return 0;
++}
++
++static struct key_entry *get_event_key_entry(int event, int status)
++{
++	struct key_entry *ke;
++	static int old_brightness_status = -1;
++	static int old_volume_status = -1;
++
++	ke = sparse_keymap_entry_from_scancode(yeeloong_hotkey_dev, event);
++	if (!ke)
++		return NULL;
++
++	switch (event) {
++	case EVENT_DISPLAY_BRIGHTNESS:
++		/* current status > old one, means up */
++		if ((status < old_brightness_status) || (0 == status))
++			ke++;
++		old_brightness_status = status;
++		break;
++	case EVENT_AUDIO_VOLUME:
++		if ((status < old_volume_status) || (0 == status))
++			ke++;
++		old_volume_status = status;
++		break;
++	default:
++		break;
++	}
++
++	return ke;
++}
++
++static int report_lid_switch(int status)
++{
++	static int old_status;
++
++	/*
++	 * LID is a switch button, so, two continuous same status should be
++	 * ignored
++	 */
++	if (old_status != status) {
++		input_report_switch(yeeloong_hotkey_dev, SW_LID, !status);
++		input_sync(yeeloong_hotkey_dev);
++	}
++	old_status = status;
++
++	return status;
++}
++
++static int crt_detect_handler(int status)
++{
++	/*
++	 * When CRT is inserted, enable its output and disable the LCD output,
++	 * otherwise, do reversely.
++	 */
++	vo_set_state(CRT, status);
++	vo_set_state(LCD, !status);
++
++	return status;
++}
++
++static int displaytoggle_handler(int status)
++{
++	/* EC(>=PQ1D26) does this job for us, we can not do it again,
++	 * otherwise, the brightness will not resume to the normal level! */
++	if (ec_version_before("EC_VER=PQ1D26"))
++		vo_set_state(LCD, status);
++
++	return status;
++}
++
++static int mypow(int x, int y)
++{
++	int i, j = x;
++
++	for (i = 1; i < y; i++)
++		j *= j;
++
++	return j;
++}
++
++static int switchvideomode_handler(int status)
++{
++	/* Default status: CRT|LCD = 0|1 = 1 */
++	static int bin_state = 1;
++	int i;
++
++	/*
++	 * Only enable switch video output button
++	 * when CRT is connected
++	 */
++	if (!vo_get_status(CRT))
++		return 0;
++	/*
++	 * 2. no CRT connected: LCD on, CRT off
++	 * 3. BOTH on
++	 * 0. BOTH off
++	 * 1. LCD off, CRT on
++	 */
++
++	bin_state++;
++	if (bin_state > mypow(2, VOD_NUM) - 1)
++		bin_state = 0;
++	
++	for (i = 0; i < VOD_NUM; i++)
++		vo_set_state(i, bin_state & (1 << i));
++
++	return bin_state;
++}
++
++static int camera_handler(int status)
++{
++	int value;
++
++	value = ec_read(REG_CAMERA_CONTROL);
++	ec_write(REG_CAMERA_CONTROL, value | (1 << 1));
++
++	return status;
++}
++
++static int usb2_handler(int status)
++{
++	pr_emerg("USB2 Over Current occurred\n");
++
++	return status;
++}
++
++static int usb0_handler(int status)
++{
++	pr_emerg("USB0 Over Current occurred\n");
++
++	return status;
++}
++
++static int ac_bat_handler(int status)
++{
++	if (yeeloong_ac)
++		power_supply_changed(yeeloong_ac);
++	if (yeeloong_bat)
++		power_supply_changed(yeeloong_bat);
++
++	return status;
++}
++
++struct sci_event {
++	int reg;
++	sci_handler handler;
++};
++
++static const struct sci_event se[] = {
++	[EVENT_AC_BAT] = {0, ac_bat_handler},
++	[EVENT_AUDIO_MUTE] = {REG_AUDIO_MUTE, NULL},
++	[EVENT_AUDIO_VOLUME] = {REG_AUDIO_VOLUME, NULL},
++	[EVENT_CRT_DETECT] = {REG_CRT_DETECT, crt_detect_handler},
++	[EVENT_CAMERA] = {REG_CAMERA_STATUS, camera_handler},
++	[EVENT_BLACK_SCREEN] = {REG_DISPLAY_LCD, displaytoggle_handler},
++	[EVENT_DISPLAY_BRIGHTNESS] = {REG_DISPLAY_BRIGHTNESS, NULL},
++	[EVENT_LID] = {REG_LID_DETECT, NULL},
++	[EVENT_DISPLAY_TOGGLE] = {0, switchvideomode_handler},
++	[EVENT_USB_OC0] = {REG_USB2_FLAG, usb0_handler},
++	[EVENT_USB_OC2] = {REG_USB2_FLAG, usb2_handler},
++	[EVENT_WLAN] = {REG_WLAN, NULL},
++};
++
++static void do_event_action(int event)
++{
++	int status = -1;
++	struct key_entry *ke;
++	struct sci_event *sep;
++
++	sep = (struct sci_event *)&se[event];
++
++	if (sep->reg != 0)
++		status = ec_read(sep->reg);
++
++	if (status == -1) {
++		/* ec_read hasn't been called, status is invalid */
++		return;
++	}
++
++	if (sep->handler != NULL)
++		status = sep->handler(status);
++
++	pr_debug("%s: event: %d status: %d\n", __func__, event, status);
++
++	/* Report current key to user-space */
++	ke = get_event_key_entry(event, status);
++
++	/*
++	 * Ignore the LID and SLEEP event when we are already in sleep or
++	 * reboot state, this will avoid the recursive pm operations. but note:
++	 * the report_lid_switch() called in arch/mips/loongson/lemote-2f/pm.c
++	 * is necessary, because it is used to wake the system from sleep
++	 * state. In the future, perhaps SW_LID should works like SLEEP, no
++	 * need to function as a SWITCH, just report the state when the LID is
++	 * closed is enough, this event can tell the software to "SLEEP", no
++	 * need to tell the softwares when we are resuming from "SLEEP".
++	 */
++	if (ke && !is_fake_event(ke->keycode)) {
++		if (ke->keycode == SW_LID)
++			report_lid_switch(status);
++		else
++			sparse_keymap_report_entry(yeeloong_hotkey_dev, ke, 1,
++					true);
++	}
++}
++
++/*
++ * SCI(system control interrupt) main interrupt routine
++ *
++ * We will do the query and get event number together so the interrupt routine
++ * should be longer than 120us now at least 3ms elpase for it.
++ */
++static irqreturn_t sci_irq_handler(int irq, void *dev_id)
++{
++	int ret, event;
++
++	if (SCI_IRQ_NUM != irq)
++		return IRQ_NONE;
++
++	/* Query the event number */
++	ret = ec_query_event_num();
++	if (ret < 0)
++		return IRQ_NONE;
++
++	event = ec_get_event_num();
++	if (event < EVENT_START || event > EVENT_END)
++		return IRQ_NONE;
++
++	/* Execute corresponding actions */
++	do_event_action(event);
++
++	return IRQ_HANDLED;
++}
++
++/*
++ * Config and init some msr and gpio register properly.
++ */
++static int sci_irq_init(void)
++{
++	u32 hi, lo;
++	u32 gpio_base;
++	unsigned long flags;
++	int ret;
++
++	/* Get gpio base */
++	_rdmsr(DIVIL_MSR_REG(DIVIL_LBAR_GPIO), &hi, &lo);
++	gpio_base = lo & 0xff00;
++
++	/* Filter the former kb3310 interrupt for security */
++	ret = ec_query_event_num();
++	if (ret)
++		return ret;
++
++	/* For filtering next number interrupt */
++	udelay(10000);
++
++	/* Set gpio native registers and msrs for GPIO27 SCI EVENT PIN
++	 * gpio :
++	 *      input, pull-up, no-invert, event-count and value 0,
++	 *      no-filter, no edge mode
++	 *      gpio27 map to Virtual gpio0
++	 * msr :
++	 *      no primary and lpc
++	 *      Unrestricted Z input to IG10 from Virtual gpio 0.
++	 */
++	local_irq_save(flags);
++	_rdmsr(0x80000024, &hi, &lo);
++	lo &= ~(1 << 10);
++	_wrmsr(0x80000024, hi, lo);
++	_rdmsr(0x80000025, &hi, &lo);
++	lo &= ~(1 << 10);
++	_wrmsr(0x80000025, hi, lo);
++	_rdmsr(0x80000023, &hi, &lo);
++	lo |= (0x0a << 0);
++	_wrmsr(0x80000023, hi, lo);
++	local_irq_restore(flags);
++
++	/* Set gpio27 as sci interrupt
++	 *
++	 * input, pull-up, no-fliter, no-negedge, invert
++	 * the sci event is just about 120us
++	 */
++	asm(".set noreorder\n");
++	/*  input enable */
++	outl(0x00000800, (gpio_base | 0xA0));
++	/*  revert the input */
++	outl(0x00000800, (gpio_base | 0xA4));
++	/*  event-int enable */
++	outl(0x00000800, (gpio_base | 0xB8));
++	asm(".set reorder\n");
++
++	return 0;
++}
++
++static int notify_reboot(struct notifier_block *nb, unsigned long event, void *buf)
++{
++	switch (event) {
++	case SYS_RESTART:
++	case SYS_HALT:
++	case SYS_POWER_OFF:
++		atomic_set(in_reboot(), 1);
++		break;
++	default:
++		return NOTIFY_DONE;
++	}
++
++	return NOTIFY_OK;
++}
++
++static int notify_pm(struct notifier_block *nb, unsigned long event, void *buf)
++{
++	switch (event) {
++	case PM_HIBERNATION_PREPARE:
++	case PM_SUSPEND_PREPARE:
++		atomic_inc(in_sleep());
++		break;
++	case PM_POST_HIBERNATION:
++	case PM_POST_SUSPEND:
++	case PM_RESTORE_PREPARE:	/* do we need this ?? */
++		atomic_dec(in_sleep());
++		break;
++	default:
++		return NOTIFY_DONE;
++	}
++
++	pr_debug("%s: event = %lu, in_sleep() = %d\n", __func__, event,
++			atomic_read(in_sleep()));
++
++	return NOTIFY_OK;
++}
++
++static struct notifier_block reboot_notifier = {
++	.notifier_call = notify_reboot,
++};
++
++static struct notifier_block pm_notifier = {
++	.notifier_call = notify_pm,
++};
++
++static int yeeloong_hotkey_init(void)
++{
++	int ret = 0;
++
++	ret = register_reboot_notifier(&reboot_notifier);
++	if (ret) {
++		pr_err("Can't register reboot notifier\n");
++		goto end;
++	}
++
++	ret = register_pm_notifier(&pm_notifier);
++	if (ret) {
++		pr_err("Can't register pm notifier\n");
++		goto free_reboot_notifier;
++	}
++
++	ret = sci_irq_init();
++	if (ret) {
++		pr_err("Can't init SCI interrupt\n");
++		goto free_pm_notifier;
++	}
++
++	ret = request_threaded_irq(SCI_IRQ_NUM, NULL, &sci_irq_handler,
++			IRQF_ONESHOT, "sci", NULL);
++	if (ret) {
++		pr_err("Can't thread SCI interrupt handler\n");
++		goto free_pm_notifier;
++	}
++
++	yeeloong_hotkey_dev = input_allocate_device();
++
++	if (!yeeloong_hotkey_dev) {
++		ret = -ENOMEM;
++		goto free_irq;
++	}
++
++	yeeloong_hotkey_dev->name = "HotKeys";
++	yeeloong_hotkey_dev->phys = "button/input0";
++	yeeloong_hotkey_dev->id.bustype = BUS_HOST;
++	yeeloong_hotkey_dev->dev.parent = NULL;
++
++	ret = sparse_keymap_setup(yeeloong_hotkey_dev, yeeloong_keymap, NULL);
++	if (ret) {
++		pr_err("Failed to setup input device keymap\n");
++		goto free_dev;
++	}
++
++	ret = input_register_device(yeeloong_hotkey_dev);
++	if (ret)
++		goto free_keymap;
++
++	/* Update the current status of LID */
++	report_lid_switch(ON);
++
++#ifdef CONFIG_LOONGSON_SUSPEND
++	/* Install the real yeeloong_report_lid_status for pm.c */
++	yeeloong_report_lid_status = report_lid_switch;
++#endif
++	return 0;
++
++free_keymap:
++	sparse_keymap_free(yeeloong_hotkey_dev);
++free_dev:
++	input_free_device(yeeloong_hotkey_dev);
++free_irq:
++	free_irq(SCI_IRQ_NUM, NULL);
++free_pm_notifier:
++	unregister_pm_notifier(&pm_notifier);
++free_reboot_notifier:
++	unregister_reboot_notifier(&reboot_notifier);
++end:
++	return ret;
++}
++
++static void yeeloong_hotkey_exit(void)
++{
++	/* Free irq */
++	free_irq(SCI_IRQ_NUM, NULL);
++
++#ifdef CONFIG_LOONGSON_SUSPEND
++	/* Uninstall yeeloong_report_lid_status for pm.c */
++	if (yeeloong_report_lid_status == report_lid_switch)
++		yeeloong_report_lid_status = NULL;
++#endif
++
++	if (yeeloong_hotkey_dev) {
++		sparse_keymap_free(yeeloong_hotkey_dev);
++		input_unregister_device(yeeloong_hotkey_dev);
++		yeeloong_hotkey_dev = NULL;
++	}
++}
++
++#ifdef CONFIG_PM
++static void usb_ports_set(int status)
++{
++	status = !!status;
++
++	ec_write(REG_USB0_FLAG, status);
++	ec_write(REG_USB1_FLAG, status);
++	ec_write(REG_USB2_FLAG, status);
++}
++
++static int yeeloong_suspend(struct device *dev)
++
++{
++	if (ec_version_before("EC_VER=PQ1D27"))
++		vo_set_state(LCD, OFF);
++	vo_set_state(CRT, OFF);
++	usb_ports_set(OFF);
++
++	return 0;
++}
++
++static int yeeloong_resume(struct device *dev)
++{
++	int ret;
++
++	if (ec_version_before("EC_VER=PQ1D27"))
++		vo_set_state(LCD, ON);
++	vo_set_state(CRT, ON);
++	usb_ports_set(ON);
++
++	ret = sci_irq_init();
++	if (ret)
++		return -EFAULT;
++
++	return 0;
++}
++
++static const SIMPLE_DEV_PM_OPS(yeeloong_pm_ops, yeeloong_suspend,
++	yeeloong_resume);
++#endif
++
++static struct platform_device_id platform_device_ids[] = {
++	{
++		.name = "yeeloong_laptop",
++	},
++	{}
++};
++
++MODULE_DEVICE_TABLE(platform, platform_device_ids);
++
++static struct platform_driver platform_driver = {
++	.driver = {
++		.name = "yeeloong_laptop",
++		.owner = THIS_MODULE,
++#ifdef CONFIG_PM
++		.pm = &yeeloong_pm_ops,
++#endif
++	},
++	.id_table = platform_device_ids,
++};
++
++static int __init yeeloong_init(void)
++{
++	int ret;
++
++	pr_info("YeeLoong Laptop platform specific driver loaded.\n");
++
++	/* Register platform stuff */
++	ret = platform_driver_register(&platform_driver);
++	if (ret) {
++		pr_err("Failed to register YeeLoong platform driver.\n");
++		return ret;
++	}
++
++#define yeeloong_init_drv(drv, alias) do {			\
++	pr_info("Registered YeeLoong " alias " driver.\n");	\
++	ret = yeeloong_ ## drv ## _init();			\
++	if (ret) {						\
++		pr_err("Failed to register YeeLoong " alias " driver.\n");	\
++		yeeloong_ ## drv ## _exit();			\
++		return ret;					\
++	}							\
++} while (0)
++
++	yeeloong_init_drv(backlight, "backlight");
++	yeeloong_init_drv(bat, "battery and AC");
++	yeeloong_init_drv(hwmon, "hardware monitor");
++	yeeloong_init_drv(vo, "video output");
++	yeeloong_init_drv(lcd, "lcd output");
++	yeeloong_init_drv(hotkey, "hotkey input");
++
++	return 0;
++}
++
++static void __exit yeeloong_exit(void)
++{
++	yeeloong_hotkey_exit();
++	yeeloong_lcd_exit();
++	yeeloong_vo_exit();
++	yeeloong_hwmon_exit();
++	yeeloong_bat_exit();
++	yeeloong_backlight_exit();
++	platform_driver_unregister(&platform_driver);
++
++	pr_info("YeeLoong platform specific driver unloaded.\n");
++}
++
++module_init(yeeloong_init);
++module_exit(yeeloong_exit);
++
++MODULE_AUTHOR("Wu Zhangjin <wuzhangjin@gmail.com>; Liu Junliang <liujl@lemote.com>");
++MODULE_DESCRIPTION("YeeLoong laptop driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index 8bf495f..f6a15b6 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -36,6 +36,12 @@ config VGASTATE
+        tristate
+        default n
+ 
++config VIDEO_OUTPUT_CONTROL
++	tristate "Lowlevel video output switch controls"
++	help
++	  This framework adds support for low-level control of the video 
++	  output switch.
++
+ config VIDEOMODE_HELPERS
+ 	bool
+ 
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index 9ad3c17..3d869d9 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -7,6 +7,8 @@ obj-y				  += backlight/
+ 
+ obj-y				  += fbdev/
+ 
++#video output switch sysfs driver
++obj-$(CONFIG_VIDEO_OUTPUT_CONTROL) += output.o
+ obj-$(CONFIG_VIDEOMODE_HELPERS) += display_timing.o videomode.o
+ ifeq ($(CONFIG_OF),y)
+ obj-$(CONFIG_VIDEOMODE_HELPERS) += of_display_timing.o of_videomode.o
+diff --git a/drivers/video/output.c b/drivers/video/output.c
+new file mode 100644
+index 0000000..1446c49
+--- /dev/null
++++ b/drivers/video/output.c
+@@ -0,0 +1,133 @@
++/*
++ *  output.c - Display Output Switch driver
++ *
++ *  Copyright (C) 2006 Luming Yu <luming.yu@intel.com>
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or (at
++ *  your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful, but
++ *  WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ *  General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License along
++ *  with this program; if not, write to the Free Software Foundation, Inc.,
++ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ */
++#include <linux/module.h>
++#include <linux/video_output.h>
++#include <linux/slab.h>
++#include <linux/err.h>
++#include <linux/ctype.h>
++
++
++MODULE_DESCRIPTION("Display Output Switcher Lowlevel Control Abstraction");
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Luming Yu <luming.yu@intel.com>");
++
++static ssize_t state_show(struct device *dev, struct device_attribute *attr,
++			  char *buf)
++{
++	ssize_t ret_size = 0;
++	struct output_device *od = to_output_device(dev);
++	if (od->props)
++		ret_size = sprintf(buf,"%.8x\n",od->props->get_status(od));
++	return ret_size;
++}
++
++static ssize_t state_store(struct device *dev, struct device_attribute *attr,
++			   const char *buf,size_t count)
++{
++	char *endp;
++	struct output_device *od = to_output_device(dev);
++	int request_state = simple_strtoul(buf,&endp,0);
++	size_t size = endp - buf;
++
++	if (isspace(*endp))
++		size++;
++	if (size != count)
++		return -EINVAL;
++
++	if (od->props) {
++		od->request_state = request_state;
++		od->props->set_state(od);
++	}
++	return count;
++}
++static DEVICE_ATTR_RW(state);
++
++static void video_output_release(struct device *dev)
++{
++	struct output_device *od = to_output_device(dev);
++	kfree(od);
++}
++
++static struct attribute *video_output_attrs[] = {
++	&dev_attr_state.attr,
++	NULL,
++};
++ATTRIBUTE_GROUPS(video_output);
++
++static struct class video_output_class = {
++	.name = "video_output",
++	.dev_release = video_output_release,
++	.dev_groups = video_output_groups,
++};
++
++struct output_device *video_output_register(const char *name,
++	struct device *dev,
++	void *devdata,
++	struct output_properties *op)
++{
++	struct output_device *new_dev;
++	int ret_code = 0;
++
++	new_dev = kzalloc(sizeof(struct output_device),GFP_KERNEL);
++	if (!new_dev) {
++		ret_code = -ENOMEM;
++		goto error_return;
++	}
++	new_dev->props = op;
++	new_dev->dev.class = &video_output_class;
++	new_dev->dev.parent = dev;
++	dev_set_name(&new_dev->dev, "%s", name);
++	dev_set_drvdata(&new_dev->dev, devdata);
++	ret_code = device_register(&new_dev->dev);
++	if (ret_code) {
++		kfree(new_dev);
++		goto error_return;
++	}
++	return new_dev;
++
++error_return:
++	return ERR_PTR(ret_code);
++}
++EXPORT_SYMBOL(video_output_register);
++
++void video_output_unregister(struct output_device *dev)
++{
++	if (!dev)
++		return;
++	device_unregister(&dev->dev);
++}
++EXPORT_SYMBOL(video_output_unregister);
++
++static void __exit video_output_class_exit(void)
++{
++	class_unregister(&video_output_class);
++}
++
++static int __init video_output_class_init(void)
++{
++	return class_register(&video_output_class);
++}
++
++postcore_initcall(video_output_class_init);
++module_exit(video_output_class_exit);
+diff --git a/include/linux/video_output.h b/include/linux/video_output.h
+new file mode 100644
+index 0000000..ed5cdeb
+--- /dev/null
++++ b/include/linux/video_output.h
+@@ -0,0 +1,57 @@
++/*
++ *
++ *  Copyright (C) 2006 Luming Yu <luming.yu@intel.com>
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ *
++ *  This program is free software; you can redistribute it and/or modify
++ *  it under the terms of the GNU General Public License as published by
++ *  the Free Software Foundation; either version 2 of the License, or (at
++ *  your option) any later version.
++ *
++ *  This program is distributed in the hope that it will be useful, but
++ *  WITHOUT ANY WARRANTY; without even the implied warranty of
++ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ *  General Public License for more details.
++ *
++ *  You should have received a copy of the GNU General Public License along
++ *  with this program; if not, write to the Free Software Foundation, Inc.,
++ *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
++ *
++ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
++ */
++#ifndef _LINUX_VIDEO_OUTPUT_H
++#define _LINUX_VIDEO_OUTPUT_H
++#include <linux/device.h>
++#include <linux/err.h>
++struct output_device;
++struct output_properties {
++	int (*set_state)(struct output_device *);
++	int (*get_status)(struct output_device *);
++};
++struct output_device {
++	int request_state;
++	struct output_properties *props;
++	struct device dev;
++};
++#define to_output_device(obj) container_of(obj, struct output_device, dev)
++#if	defined(CONFIG_VIDEO_OUTPUT_CONTROL) || defined(CONFIG_VIDEO_OUTPUT_CONTROL_MODULE)
++struct output_device *video_output_register(const char *name,
++	struct device *dev,
++	void *devdata,
++	struct output_properties *op);
++void video_output_unregister(struct output_device *dev);
++#else
++static struct output_device *video_output_register(const char *name,
++        struct device *dev,
++        void *devdata,
++        struct output_properties *op)
++{
++	return ERR_PTR(-ENODEV);
++}
++static void video_output_unregister(struct output_device *dev)
++{
++	return;
++}
++#endif
++#endif
+-- 
+2.4.3
+