summaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
Diffstat (limited to 'target')
-rw-r--r--target/config/Config.in.binutils3
-rw-r--r--target/config/Config.in.compiler3
-rw-r--r--target/config/Config.in.cpu4
-rw-r--r--target/config/Config.in.gdb5
-rw-r--r--target/config/Config.in.kernelcfg1
-rw-r--r--target/config/Config.in.kernelversion11
-rw-r--r--target/config/Config.in.runtime1
-rw-r--r--target/config/Config.in.target1
-rw-r--r--target/linux/config/Config.in.ethernet10
-rw-r--r--target/linux/config/Config.in.kernel4
-rw-r--r--target/linux/config/Config.in.serial6
-rw-r--r--target/linux/patches/3.4.112/nds32.patch72132
-rw-r--r--target/nds32/Makefile3
-rw-r--r--target/nds32/kernel/andes-ag101p5
-rw-r--r--target/nds32/kernel/generic-nds322
-rw-r--r--target/nds32/systems/andes-ag101p9
-rw-r--r--target/nds32/uclibc-ng.config248
17 files changed, 72446 insertions, 2 deletions
diff --git a/target/config/Config.in.binutils b/target/config/Config.in.binutils
index 3d31a774b..494aa4469 100644
--- a/target/config/Config.in.binutils
+++ b/target/config/Config.in.binutils
@@ -17,11 +17,13 @@ config ADK_TOOLCHAIN_BINUTILS_GIT
depends on !ADK_TARGET_ARCH_ARC
depends on !ADK_TARGET_ARCH_AVR32
depends on !ADK_TARGET_ARCH_CRIS
+ depends on !ADK_TARGET_ARCH_NDS32
config ADK_TOOLCHAIN_BINUTILS_2_26_1
bool "2.26.1"
depends on !ADK_TARGET_ARCH_ARC
depends on !ADK_TARGET_ARCH_AVR32
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_CPU_CRIS_CRISV10
config ADK_TOOLCHAIN_BINUTILS_2_25_1
@@ -31,6 +33,7 @@ config ADK_TOOLCHAIN_BINUTILS_2_25_1
depends on !ADK_TARGET_ARCH_AVR32
depends on !ADK_TARGET_ARCH_H8300
depends on !ADK_TARGET_ARCH_MOXIE
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_CPU_CRIS_CRISV10
config ADK_TOOLCHAIN_BINUTILS_2_24
diff --git a/target/config/Config.in.compiler b/target/config/Config.in.compiler
index ba41d89fb..c9d950c1d 100644
--- a/target/config/Config.in.compiler
+++ b/target/config/Config.in.compiler
@@ -33,6 +33,7 @@ config ADK_TOOLCHAIN_GCC_GIT
depends on !ADK_TARGET_ARCH_ARC
depends on !ADK_TARGET_ARCH_AVR32
depends on !ADK_TARGET_ARCH_METAG
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_OR1K
select ADK_DISABLE_HONOUR_CFLAGS
@@ -41,6 +42,7 @@ config ADK_TOOLCHAIN_GCC_6_1_0
depends on !ADK_TARGET_ARCH_ARC
depends on !ADK_TARGET_ARCH_AVR32
depends on !ADK_TARGET_ARCH_METAG
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_OR1K
select ADK_DISABLE_HONOUR_CFLAGS
@@ -54,6 +56,7 @@ config ADK_TOOLCHAIN_GCC_5_4_0
depends on !ADK_TARGET_ARCH_H8300
depends on !ADK_TARGET_ARCH_M32R
depends on !ADK_TARGET_ARCH_METAG
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_OR1K
depends on !ADK_TARGET_SYSTEM_KINETIS_K70
depends on !(ADK_TARGET_LIB_GLIBC && ADK_TARGET_ARCH_SH)
diff --git a/target/config/Config.in.cpu b/target/config/Config.in.cpu
index 2b463ed33..d318a6440 100644
--- a/target/config/Config.in.cpu
+++ b/target/config/Config.in.cpu
@@ -720,7 +720,7 @@ config ADK_TARGET_CPU_MSP430
# nds32
config ADK_TARGET_CPU_NDS32
bool "nds32"
- select ADK_TARGET_WITH_NPTL
+ select ADK_TARGET_WITH_LT
select ADK_TARGET_WITH_MMU
depends on ADK_TARGET_ARCH_NDS32
@@ -1437,6 +1437,7 @@ config ADK_TARGET_GCC_CPU
default "cortex-m4" if ADK_TARGET_CPU_ARM_CORTEX_M4
default "leon" if ADK_TARGET_CPU_SPARC_LEON
default "mpcore" if ADK_TARGET_CPU_ARM_ARM11MPCORE
+ default "n13" if ADK_TARGET_CPU_NDS32
default "powerpc" if ADK_TARGET_CPU_PPC
default "powerpc64" if ADK_TARGET_CPU_PPC64_POWERPC64
default "power6" if ADK_TARGET_CPU_PPC64_POWER6
@@ -1623,6 +1624,7 @@ config ADK_TARGET_CPU_TYPE
default "mips64r6" if ADK_TARGET_CPU_MIPS64_MIPS64R6
default "mips64" if ADK_TARGET_CPU_MIPS64_LOONGSON2F
default "ppc64" if ADK_TARGET_ARCH_PPC64
+ default "nds32" if ADK_TARGET_CPU_NDS32
default "v8" if ADK_TARGET_CPU_SPARC_V8
default "v9" if ADK_TARGET_CPU_SPARC64_V9
default "leon" if ADK_TARGET_CPU_SPARC_LEON
diff --git a/target/config/Config.in.gdb b/target/config/Config.in.gdb
index a9d279044..bbde9df6c 100644
--- a/target/config/Config.in.gdb
+++ b/target/config/Config.in.gdb
@@ -4,12 +4,14 @@
choice
prompt "GNU debugger version"
default ADK_TOOLCHAIN_GDB_H8300_GIT if ADK_TARGET_ARCH_H8300
+default ADK_TOOLCHAIN_GDB_NDS32 if ADK_TARGET_ARCH_NDS32
default ADK_TOOLCHAIN_GDB_7_11_1
config ADK_TOOLCHAIN_GDB_GIT
bool "git"
depends on !ADK_TARGET_ARCH_AVR32
depends on !ADK_TARGET_ARCH_H8300
+ depends on !ADK_TARGET_ARCH_NDS32
config ADK_TOOLCHAIN_GDB_H8300_GIT
bool "h8300-git"
@@ -19,16 +21,19 @@ config ADK_TOOLCHAIN_GDB_7_11_1
bool "7.11.1"
depends on !ADK_TARGET_ARCH_AVR32
depends on !ADK_TARGET_ARCH_H8300
+ depends on !ADK_TARGET_ARCH_NDS32
config ADK_TOOLCHAIN_GDB_7_10_1
bool "7.10.1"
depends on !ADK_TARGET_ARCH_AVR32
depends on !ADK_TARGET_ARCH_H8300
+ depends on !ADK_TARGET_ARCH_NDS32
config ADK_TOOLCHAIN_GDB_7_9_1
bool "7.9.1"
depends on !ADK_TARGET_ARCH_AVR32
depends on !ADK_TARGET_ARCH_H8300
+ depends on !ADK_TARGET_ARCH_NDS32
config ADK_TOOLCHAIN_GDB_7_8_2
bool "7.8.2"
diff --git a/target/config/Config.in.kernelcfg b/target/config/Config.in.kernelcfg
index c1e562f7b..27a6bbf1e 100644
--- a/target/config/Config.in.kernelcfg
+++ b/target/config/Config.in.kernelcfg
@@ -23,4 +23,5 @@ config ADK_TARGET_KERNEL_DEFCONFIG
default "nsim_700_defconfig" if ADK_TARGET_SYSTEM_NSIM_ARCV1
default "nsim_hs_defconfig" if ADK_TARGET_SYSTEM_NSIM_ARCV2
default "10m50_defconfig" if ADK_TARGET_SYSTEM_QEMU_NIOS2
+ default "orca_defconfig" if ADK_TARGET_SYSTEM_ANDES_AG101P
diff --git a/target/config/Config.in.kernelversion b/target/config/Config.in.kernelversion
index 4411d78aa..b6b35d52f 100644
--- a/target/config/Config.in.kernelversion
+++ b/target/config/Config.in.kernelversion
@@ -11,15 +11,18 @@ default ADK_TARGET_KERNEL_VERSION_4_4_14
config ADK_TARGET_KERNEL_VERSION_GIT
bool "linux-git"
+ depends on !ADK_TARGET_ARCH_NDS32
config ADK_TARGET_KERNEL_VERSION_4_6_3
bool "4.6.3"
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_BOARD_BCM28XX
depends on !ADK_TARGET_SYSTEM_SOLIDRUN_IMX6
select ADK_TARGET_KERNEL_VERSION_4_6
config ADK_TARGET_KERNEL_VERSION_4_5_7
bool "4.5.7"
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_NIOS2
depends on !ADK_TARGET_BOARD_BCM28XX
depends on !ADK_TARGET_SYSTEM_SOLIDRUN_IMX6
@@ -27,6 +30,7 @@ config ADK_TARGET_KERNEL_VERSION_4_5_7
config ADK_TARGET_KERNEL_VERSION_4_4_14
bool "4.4.14"
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_NIOS2
depends on !ADK_TARGET_SYSTEM_SOLIDRUN_IMX6
select ADK_TARGET_KERNEL_VERSION_4_4
@@ -37,6 +41,7 @@ config ADK_TARGET_KERNEL_VERSION_4_1_26
depends on !ADK_TARGET_ARCH_BFIN
depends on !ADK_TARGET_ARCH_H8300
depends on !ADK_TARGET_ARCH_NIOS2
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_SPARC
depends on !ADK_TARGET_SYSTEM_KINETIS_K70
select ADK_TARGET_KERNEL_VERSION_4_1
@@ -46,6 +51,7 @@ config ADK_TARGET_KERNEL_VERSION_3_18_33
depends on !ADK_TARGET_ARCH_ARC
depends on !ADK_TARGET_ARCH_BFIN
depends on !ADK_TARGET_ARCH_H8300
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_NIOS2
depends on !ADK_TARGET_ARCH_SPARC
depends on !ADK_TARGET_BOARD_ATH79
@@ -60,6 +66,7 @@ config ADK_TARGET_KERNEL_VERSION_3_14_72
depends on !ADK_TARGET_ARCH_ARC
depends on !ADK_TARGET_ARCH_BFIN
depends on !ADK_TARGET_ARCH_H8300
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_NIOS2
depends on !ADK_TARGET_ARCH_SPARC
depends on !ADK_TARGET_BOARD_ATH79
@@ -72,6 +79,7 @@ config ADK_TARGET_KERNEL_VERSION_3_12_59
depends on !ADK_TARGET_ARCH_ARC
depends on !ADK_TARGET_ARCH_BFIN
depends on !ADK_TARGET_ARCH_H8300
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_NIOS2
depends on !ADK_TARGET_ARCH_SPARC
depends on !ADK_TARGET_BOARD_ATH79
@@ -86,6 +94,7 @@ config ADK_TARGET_KERNEL_VERSION_3_10_101
depends on !ADK_TARGET_ARCH_ARC
depends on !ADK_TARGET_ARCH_BFIN
depends on !ADK_TARGET_ARCH_H8300
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_NIOS2
depends on !ADK_TARGET_ARCH_SPARC
depends on !ADK_TARGET_BOARD_ATH79
@@ -115,6 +124,7 @@ config ADK_TARGET_KERNEL_VERSION_3_2_80
depends on !ADK_TARGET_ARCH_ARC
depends on !ADK_TARGET_ARCH_BFIN
depends on !ADK_TARGET_ARCH_H8300
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_NIOS2
depends on !ADK_TARGET_ARCH_SPARC
depends on !ADK_TARGET_BOARD_ATH79
@@ -129,6 +139,7 @@ config ADK_TARGET_KERNEL_VERSION_2_6_32_70
depends on !ADK_TARGET_ARCH_ARC
depends on !ADK_TARGET_ARCH_BFIN
depends on !ADK_TARGET_ARCH_H8300
+ depends on !ADK_TARGET_ARCH_NDS32
depends on !ADK_TARGET_ARCH_NIOS2
depends on !ADK_TARGET_ARCH_SPARC
depends on !ADK_TARGET_BOARD_ATH79
diff --git a/target/config/Config.in.runtime b/target/config/Config.in.runtime
index 6ed3bc5b7..6657e044c 100644
--- a/target/config/Config.in.runtime
+++ b/target/config/Config.in.runtime
@@ -285,6 +285,7 @@ config ADK_RUNTIME_CONSOLE_SERIAL_SPEED
default "9600" if ADK_TARGET_SYSTEM_FON_FON2100
default "9600" if ADK_TARGET_SYSTEM_NUMATO_MIMASV2
default "38400" if ADK_TARGET_SYSTEM_PCENGINES_WRAP
+ default "38400" if ADK_TARGET_SYSTEM_ANDES_AG101P
default "115200"
config ADK_RUNTIME_KBD_LAYOUT
diff --git a/target/config/Config.in.target b/target/config/Config.in.target
index ec72d1b44..5fef2270e 100644
--- a/target/config/Config.in.target
+++ b/target/config/Config.in.target
@@ -8,5 +8,6 @@ config ADK_TARGET_CMDLINE
default "kinetis_platform=k70-som" if ADK_TARGET_SYSTEM_KINETIS_K70
default "metag_da.console_poll=1" if ADK_TARGET_SYSTEM_QEMU_METAG
default "earlycon=uart8250,mmio32,0x9d050020,115200n8 console=ttyS0,115200n8" if ADK_TARGET_CPU_XTENSA_DE212
+ default "earlyprintk=uart8250-32bit,0x99600000" if ADK_TARGET_SYSTEM_ANDES_AG101P
default ""
diff --git a/target/linux/config/Config.in.ethernet b/target/linux/config/Config.in.ethernet
index 6ef03ee4b..cfb12e1db 100644
--- a/target/linux/config/Config.in.ethernet
+++ b/target/linux/config/Config.in.ethernet
@@ -23,6 +23,9 @@ config ADK_KERNEL_NET_VENDOR_IBM
config ADK_KERNEL_NET_VENDOR_INTEL
bool
+config ADK_KERNEL_NET_VENDOR_FARADAY
+ bool
+
config ADK_KERNEL_NET_VENDOR_FREESCALE
bool
@@ -400,6 +403,13 @@ config ADK_KERNEL_ETHOC
default y if ADK_TARGET_SYSTEM_QEMU_OR1K
default n
+config ADK_KERNEL_FTMAC100
+ bool "Andes ethernet driver"
+ select ADK_KERNEL_NET_VENDOR_FARADAY
+ depends on ADK_TARGET_SYSTEM_ANDES_AG101P
+ default y if ADK_TARGET_SYSTEM_ANDES_AG101P
+ default n
+
config ADK_KERNEL_ATL1
tristate "Atheros/Attansic L1 Gigabit Ethernet support"
select ADK_KERNEL_NET_VENDOR_ATHEROS
diff --git a/target/linux/config/Config.in.kernel b/target/linux/config/Config.in.kernel
index b52c621d1..924d0e6e6 100644
--- a/target/linux/config/Config.in.kernel
+++ b/target/linux/config/Config.in.kernel
@@ -58,11 +58,15 @@ config ADK_KERNEL_CPU_LITTLE_ENDIAN
menu "Kernel options"
+config ADK_KERNEL_HOTPLUG
+ bool
+
config ADK_KERNEL_DEVTMPFS
bool
config ADK_KERNEL_DEVTMPFS_MOUNT
bool
+ select ADK_KERNEL_HOTPLUG
config ADK_KERNEL_UEVENT_HELPER
bool
diff --git a/target/linux/config/Config.in.serial b/target/linux/config/Config.in.serial
index 113599149..82d745271 100644
--- a/target/linux/config/Config.in.serial
+++ b/target/linux/config/Config.in.serial
@@ -2,7 +2,7 @@
# material, please see the LICENCE file in the top-level directory.
menu "Serial devices support"
-depends on ADK_TARGET_WITH_SERIAL || ADK_TARGET_QEMU || ADK_TARGET_VBOX || ADK_TARGET_SIM
+depends on ADK_TARGET_WITH_SERIAL || ADK_TARGET_QEMU || ADK_TARGET_VBOX || ADK_TARGET_SIM || ADK_TARGET_GENERIC
config ADK_KERNEL_SERIAL_8250_CONSOLE
bool
@@ -90,6 +90,7 @@ config ADK_KERNEL_SERIAL_8250
depends on ADK_TARGET_SYSTEM_XILINX_KINTEX7 \
|| ADK_TARGET_SYSTEM_IMGTEC_CI20 \
|| ADK_TARGET_SYSTEM_LINKSYS_NSLU2 \
+ || ADK_TARGET_SYSTEM_ANDES_AG101P \
|| ADK_TARGET_SYSTEM_PCENGINES_APU \
|| ADK_TARGET_SYSTEM_PCENGINES_ALIX \
|| ADK_TARGET_SYSTEM_QEMU_MICROBLAZE_ML605 \
@@ -102,6 +103,7 @@ config ADK_KERNEL_SERIAL_8250
|| ADK_TARGET_SYSTEM_QEMU_XTENSA \
|| ADK_TARGET_SYSTEM_OR1K_SIM \
|| ADK_TARGET_SYSTEM_IBM_X40 \
+ || ADK_TARGET_SYSTEM_GENERIC_NDS32 \
|| ADK_TARGET_SYSTEM_GENERIC_X86 \
|| ADK_TARGET_SYSTEM_GENERIC_X86_64 \
|| ADK_TARGET_SYSTEM_MIKROTIK_RB532 \
@@ -109,6 +111,7 @@ config ADK_KERNEL_SERIAL_8250
default y if ADK_TARGET_SYSTEM_XILINX_KINTEX7
default y if ADK_TARGET_SYSTEM_IMGTEC_CI20
default y if ADK_TARGET_SYSTEM_LINKSYS_NSLU2
+ default y if ADK_TARGET_SYSTEM_ANDES_AG101P
default y if ADK_TARGET_SYSTEM_PCENGINES_APU
default y if ADK_TARGET_SYSTEM_PCENGINES_ALIX
default y if ADK_TARGET_SYSTEM_QEMU_MICROBLAZE_ML605
@@ -121,6 +124,7 @@ config ADK_KERNEL_SERIAL_8250
default y if ADK_TARGET_SYSTEM_QEMU_XTENSA
default y if ADK_TARGET_SYSTEM_OR1K_SIM
default y if ADK_TARGET_SYSTEM_IBM_X40
+ default y if ADK_TARGET_SYSTEM_GENERIC_NDS32
default y if ADK_TARGET_SYSTEM_GENERIC_X86
default y if ADK_TARGET_SYSTEM_GENERIC_X86_64
default y if ADK_TARGET_SYSTEM_MIKROTIK_RB532
diff --git a/target/linux/patches/3.4.112/nds32.patch b/target/linux/patches/3.4.112/nds32.patch
new file mode 100644
index 000000000..d0da6f7b3
--- /dev/null
+++ b/target/linux/patches/3.4.112/nds32.patch
@@ -0,0 +1,72132 @@
+diff -Nur linux-3.4.110.orig/arch/nds32/boot/install.sh linux-3.4.110/arch/nds32/boot/install.sh
+--- linux-3.4.110.orig/arch/nds32/boot/install.sh 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/boot/install.sh 2016-04-07 10:20:50.862077930 +0200
+@@ -0,0 +1,47 @@
++#!/bin/sh
++#
++# arch/nds32/boot/install.sh
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License. See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++# Copyright (C) 1995 by Linus Torvalds
++# Copyright (C) 2009 Andes Technology Corporation
++#
++# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin
++# Adapted from code in arch/i386/boot/install.sh by Russell King
++#
++# "make install" script for arm architecture
++#
++# Arguments:
++# $1 - kernel version
++# $2 - kernel image file
++# $3 - kernel map file
++# $4 - default install path (blank if root directory)
++#
++
++# User may have a custom install script
++if [ -x ~/bin/installkernel ]; then exec ~/bin/installkernel "$@"; fi
++if [ -x /sbin/installkernel ]; then exec /sbin/installkernel "$@"; fi
++
++# Normal install
++echo "Installing normal kernel"
++base=vmlinux
++
++if [ -f $4/$base-$1 ]; then
++ mv $4/$base-$1 $4/$base-$1.old
++fi
++cat $2 > $4/$base-$1
++
++# Install system map file
++if [ -f $4/System.map-$1 ]; then
++ mv $4/System.map-$1 $4/System.map-$1.old
++fi
++cp $3 $4/System.map-$1
++
++if [ -x /sbin/loadmap ]; then
++ /sbin/loadmap
++else
++ echo "You have to install it yourself"
++fi
+diff -Nur linux-3.4.110.orig/arch/nds32/boot/Makefile linux-3.4.110/arch/nds32/boot/Makefile
+--- linux-3.4.110.orig/arch/nds32/boot/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/boot/Makefile 2016-04-07 10:20:50.862077930 +0200
+@@ -0,0 +1,22 @@
++#
++# arch/nds32/boot/Makefile
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License. See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++# Copyright (C) 1995-2002 Russell King
++# Copyright (C) 2009 Andes Technology Corporation
++#
++
++targets := Image
++
++$(obj)/Image: vmlinux FORCE
++ $(call if_changed,objcopy)
++ @echo ' Kernel: $@ is ready'
++
++.PHONY: FORCE
++install: $(obj)/Image
++ $(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
++ $(obj)/Image System.map "$(INSTALL_PATH)"
++
+diff -Nur linux-3.4.110.orig/arch/nds32/common/dmabounce.c linux-3.4.110/arch/nds32/common/dmabounce.c
+--- linux-3.4.110.orig/arch/nds32/common/dmabounce.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/common/dmabounce.c 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,672 @@
++/*
++ * arch/nds32/common/dmabounce.c
++ *
++ * Special dma_{map/unmap/dma_sync}_* routines for systems that have
++ * limited DMA windows. These functions utilize bounce buffers to
++ * copy data to/from buffers located outside the DMA region. This
++ * only works for systems in which DMA memory is at the bottom of
++ * RAM and the remainder of memory is at the top an the DMA memory
++ * can be marked as ZONE_DMA. Anything beyond that such as discontigous
++ * DMA windows will require custom implementations that reserve memory
++ * areas at early bootup.
++ *
++ * Original version by Brad Parker (brad@heeltoe.com)
++ * Re-written by Christopher Hoover <ch@murgatroid.com>
++ * Made generic by Deepak Saxena <dsaxena@plexity.net>
++ *
++ * Copyright (C) 2002 Hewlett Packard Company.
++ * Copyright (C) 2004 MontaVista Software, Inc.
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * version 2 as published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/dmapool.h>
++#include <linux/list.h>
++
++#undef DEBUG
++
++#undef STATS
++#ifdef STATS
++#define DO_STATS(X) do { X ; } while (0)
++#else
++#define DO_STATS(X) do { } while (0)
++#endif
++
++/* ************************************************** */
++
++struct safe_buffer {
++ struct list_head node;
++
++ /* original request */
++ void *ptr;
++ size_t size;
++ int direction;
++
++ /* safe buffer info */
++ struct dma_pool *pool;
++ void *safe;
++ dma_addr_t safe_dma_addr;
++};
++
++struct dmabounce_device_info {
++ struct list_head node;
++
++ struct device *dev;
++ struct dma_pool *small_buffer_pool;
++ struct dma_pool *large_buffer_pool;
++ struct list_head safe_buffers;
++ unsigned long small_buffer_size, large_buffer_size;
++#ifdef STATS
++ unsigned long sbp_allocs;
++ unsigned long lbp_allocs;
++ unsigned long total_allocs;
++ unsigned long map_op_count;
++ unsigned long bounce_count;
++#endif
++};
++
++static LIST_HEAD(dmabounce_devs);
++
++#ifdef STATS
++static void print_alloc_stats(struct dmabounce_device_info *device_info)
++{
++ printk(KERN_INFO
++ "%s: dmabounce: sbp: %lu, lbp: %lu, other: %lu, total: %lu\n",
++ device_info->dev->bus_id,
++ device_info->sbp_allocs, device_info->lbp_allocs,
++ device_info->total_allocs - device_info->sbp_allocs -
++ device_info->lbp_allocs, device_info->total_allocs);
++}
++#endif
++
++/* find the given device in the dmabounce device list */
++static inline struct dmabounce_device_info *find_dmabounce_dev(struct device
++ *dev)
++{
++ struct list_head *entry;
++
++ list_for_each(entry, &dmabounce_devs) {
++ struct dmabounce_device_info *d =
++ list_entry(entry, struct dmabounce_device_info, node);
++
++ if (d->dev == dev)
++ return d;
++ }
++ return NULL;
++}
++
++/* allocate a 'safe' buffer and keep track of it */
++static inline struct safe_buffer *alloc_safe_buffer(struct dmabounce_device_info
++ *device_info, void *ptr,
++ size_t size,
++ enum dma_data_direction dir)
++{
++ struct safe_buffer *buf;
++ struct dma_pool *pool;
++ struct device *dev = device_info->dev;
++ void *safe;
++ dma_addr_t safe_dma_addr;
++
++ dev_dbg(dev, "%s(ptr=%p, size=%d, dir=%d)\n", __func__, ptr, size, dir);
++
++ DO_STATS(device_info->total_allocs++);
++
++ buf = kmalloc(sizeof(struct safe_buffer), GFP_ATOMIC);
++ if (buf == NULL) {
++ dev_warn(dev, "%s: kmalloc failed\n", __func__);
++ return NULL;
++ }
++
++ if (size <= device_info->small_buffer_size) {
++ pool = device_info->small_buffer_pool;
++ safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr);
++
++ DO_STATS(device_info->sbp_allocs++);
++ } else if (size <= device_info->large_buffer_size) {
++ pool = device_info->large_buffer_pool;
++ safe = dma_pool_alloc(pool, GFP_ATOMIC, &safe_dma_addr);
++
++ DO_STATS(device_info->lbp_allocs++);
++ } else {
++ pool = NULL;
++ safe =
++ dma_alloc_coherent(dev, size, &safe_dma_addr, GFP_ATOMIC);
++ }
++
++ if (safe == NULL) {
++ dev_warn(device_info->dev,
++ "%s: could not alloc dma memory (size=%d)\n",
++ __func__, size);
++ kfree(buf);
++ return NULL;
++ }
++#ifdef STATS
++ if (device_info->total_allocs % 1000 == 0)
++ print_alloc_stats(device_info);
++#endif
++
++ buf->ptr = ptr;
++ buf->size = size;
++ buf->direction = dir;
++ buf->pool = pool;
++ buf->safe = safe;
++ buf->safe_dma_addr = safe_dma_addr;
++
++ list_add(&buf->node, &device_info->safe_buffers);
++
++ return buf;
++}
++
++/* determine if a buffer is from our "safe" pool */
++static inline struct safe_buffer *find_safe_buffer(struct dmabounce_device_info
++ *device_info,
++ dma_addr_t safe_dma_addr)
++{
++ struct list_head *entry;
++
++ list_for_each(entry, &device_info->safe_buffers) {
++ struct safe_buffer *b =
++ list_entry(entry, struct safe_buffer, node);
++
++ if (b->safe_dma_addr == safe_dma_addr)
++ return b;
++ }
++
++ return NULL;
++}
++
++static inline void
++free_safe_buffer(struct dmabounce_device_info *device_info,
++ struct safe_buffer *buf)
++{
++ dev_dbg(device_info->dev, "%s(buf=%p)\n", __func__, buf);
++
++ list_del(&buf->node);
++
++ if (buf->pool)
++ dma_pool_free(buf->pool, buf->safe, buf->safe_dma_addr);
++ else
++ dma_free_coherent(device_info->dev, buf->size, buf->safe,
++ buf->safe_dma_addr);
++
++ kfree(buf);
++}
++
++/* ************************************************** */
++
++#ifdef STATS
++
++static void print_map_stats(struct dmabounce_device_info *device_info)
++{
++ printk(KERN_INFO
++ "%s: dmabounce: map_op_count=%lu, bounce_count=%lu\n",
++ device_info->dev->bus_id,
++ device_info->map_op_count, device_info->bounce_count);
++}
++#endif
++
++static inline dma_addr_t
++map_single(struct device *dev, void *ptr, size_t size,
++ enum dma_data_direction dir)
++{
++ struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
++ dma_addr_t dma_addr;
++ int needs_bounce = 0;
++
++ if (device_info)
++ DO_STATS(device_info->map_op_count++);
++
++ dma_addr = virt_to_dma(dev, ptr);
++
++ if (dev->dma_mask) {
++ unsigned long mask = *dev->dma_mask;
++ unsigned long limit;
++
++ limit = (mask + 1) & ~mask;
++ if (limit && size > limit) {
++ dev_err(dev, "DMA mapping too big (requested %#x "
++ "mask %#Lx)\n", size, *dev->dma_mask);
++ return ~0;
++ }
++
++ /*
++ * Figure out if we need to bounce from the DMA mask.
++ */
++ needs_bounce = (dma_addr | (dma_addr + size - 1)) & ~mask;
++ }
++
++ if (device_info
++ && (needs_bounce || dma_needs_bounce(dev, dma_addr, size))) {
++ struct safe_buffer *buf;
++
++ buf = alloc_safe_buffer(device_info, ptr, size, dir);
++ if (buf == 0) {
++ dev_err(dev, "%s: unable to map unsafe buffer %p!\n",
++ __func__, ptr);
++ return 0;
++ }
++
++ dev_dbg(dev,
++ "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
++ __func__, buf->ptr, (void *)virt_to_dma(dev, buf->ptr),
++ buf->safe, (void *)buf->safe_dma_addr);
++
++ if ((dir == DMA_TO_DEVICE) || (dir == DMA_BIDIRECTIONAL)) {
++ dev_dbg(dev, "%s: copy unsafe %p to safe %p, size %d\n",
++ __func__, ptr, buf->safe, size);
++ memcpy(buf->safe, ptr, size);
++ }
++ consistent_sync(buf->safe, size, dir);
++
++ dma_addr = buf->safe_dma_addr;
++ } else {
++ consistent_sync(ptr, size, dir);
++ }
++
++ return dma_addr;
++}
++
++static inline void
++unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction dir)
++{
++ struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
++ struct safe_buffer *buf = NULL;
++
++ /*
++ * Trying to unmap an invalid mapping
++ */
++ if (dma_addr == ~0) {
++ dev_err(dev, "Trying to unmap invalid mapping\n");
++ return;
++ }
++
++ if (device_info)
++ buf = find_safe_buffer(device_info, dma_addr);
++
++ if (buf) {
++ BUG_ON(buf->size != size);
++
++ dev_dbg(dev,
++ "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
++ __func__, buf->ptr, (void *)virt_to_dma(dev, buf->ptr),
++ buf->safe, (void *)buf->safe_dma_addr);
++
++ DO_STATS(device_info->bounce_count++);
++
++ if ((dir == DMA_FROM_DEVICE) || (dir == DMA_BIDIRECTIONAL)) {
++ dev_dbg(dev,
++ "%s: copy back safe %p to unsafe %p size %d\n",
++ __func__, buf->safe, buf->ptr, size);
++ memcpy(buf->ptr, buf->safe, size);
++ }
++ free_safe_buffer(device_info, buf);
++ }
++}
++
++static inline void
++sync_single(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction dir)
++{
++ struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
++ struct safe_buffer *buf = NULL;
++
++ if (device_info)
++ buf = find_safe_buffer(device_info, dma_addr);
++
++ if (buf) {
++ /*
++ * Both of these checks from original code need to be
++ * commented out b/c some drivers rely on the following:
++ *
++ * 1) Drivers may map a large chunk of memory into DMA space
++ * but only sync a small portion of it. Good example is
++ * allocating a large buffer, mapping it, and then
++ * breaking it up into small descriptors. No point
++ * in syncing the whole buffer if you only have to
++ * touch one descriptor.
++ *
++ * 2) Buffers that are mapped as DMA_BIDIRECTIONAL are
++ * usually only synced in one dir at a time.
++ *
++ * See drivers/net/eepro100.c for examples of both cases.
++ *
++ * -ds
++ *
++ * BUG_ON(buf->size != size);
++ * BUG_ON(buf->direction != dir);
++ */
++
++ dev_dbg(dev,
++ "%s: unsafe buffer %p (phy=%p) mapped to %p (phy=%p)\n",
++ __func__, buf->ptr, (void *)virt_to_dma(dev, buf->ptr),
++ buf->safe, (void *)buf->safe_dma_addr);
++
++ DO_STATS(device_info->bounce_count++);
++
++ switch (dir) {
++ case DMA_FROM_DEVICE:
++ dev_dbg(dev,
++ "%s: copy back safe %p to unsafe %p size %d\n",
++ __func__, buf->safe, buf->ptr, size);
++ memcpy(buf->ptr, buf->safe, size);
++ break;
++ case DMA_TO_DEVICE:
++ dev_dbg(dev,
++ "%s: copy out unsafe %p to safe %p, size %d\n",
++ __func__, buf->ptr, buf->safe, size);
++ memcpy(buf->safe, buf->ptr, size);
++ break;
++ case DMA_BIDIRECTIONAL:
++ BUG(); /* is this allowed? what does it mean? */
++ default:
++ BUG();
++ }
++ consistent_sync(buf->safe, size, dir);
++ } else {
++ consistent_sync(dma_to_virt(dev, dma_addr), size, dir);
++ }
++}
++
++/* ************************************************** */
++
++/*
++ * see if a buffer address is in an 'unsafe' range. if it is
++ * allocate a 'safe' buffer and copy the unsafe buffer into it.
++ * substitute the safe buffer for the unsafe one.
++ * (basically move the buffer from an unsafe area to a safe one)
++ */
++dma_addr_t
++dma_map_single(struct device *dev, void *ptr, size_t size,
++ enum dma_data_direction dir)
++{
++ unsigned long flags;
++ dma_addr_t dma_addr;
++
++ dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n", __func__, ptr, size, dir);
++
++ BUG_ON(dir == DMA_NONE);
++
++ local_irq_save(flags);
++
++ dma_addr = map_single(dev, ptr, size, dir);
++
++ local_irq_restore(flags);
++
++ return dma_addr;
++}
++
++/*
++ * see if a mapped address was really a "safe" buffer and if so, copy
++ * the data from the safe buffer back to the unsafe buffer and free up
++ * the safe buffer. (basically return things back to the way they
++ * should be)
++ */
++
++void
++dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction dir)
++{
++ unsigned long flags;
++
++ dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
++ __func__, (void *)dma_addr, size, dir);
++
++ BUG_ON(dir == DMA_NONE);
++
++ local_irq_save(flags);
++
++ unmap_single(dev, dma_addr, size, dir);
++
++ local_irq_restore(flags);
++}
++
++int
++dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++ unsigned long flags;
++ int i;
++
++ dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", __func__, sg, nents, dir);
++
++ BUG_ON(dir == DMA_NONE);
++
++ local_irq_save(flags);
++
++ for (i = 0; i < nents; i++, sg++) {
++ struct page *page = sg->page;
++ unsigned int offset = sg->offset;
++ unsigned int length = sg->length;
++ void *ptr = page_address(page) + offset;
++
++ sg->dma_address = map_single(dev, ptr, length, dir);
++ }
++
++ local_irq_restore(flags);
++
++ return nents;
++}
++
++void
++dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++ unsigned long flags;
++ int i;
++
++ dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", __func__, sg, nents, dir);
++
++ BUG_ON(dir == DMA_NONE);
++
++ local_irq_save(flags);
++
++ for (i = 0; i < nents; i++, sg++) {
++ dma_addr_t dma_addr = sg->dma_address;
++ unsigned int length = sg->length;
++
++ unmap_single(dev, dma_addr, length, dir);
++ }
++
++ local_irq_restore(flags);
++}
++
++void
++dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction dir)
++{
++ unsigned long flags;
++
++ dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
++ __func__, (void *)dma_addr, size, dir);
++
++ local_irq_save(flags);
++
++ sync_single(dev, dma_addr, size, dir);
++
++ local_irq_restore(flags);
++}
++
++void
++dma_sync_single_for_device(struct device *dev, dma_addr_t dma_addr, size_t size,
++ enum dma_data_direction dir)
++{
++ unsigned long flags;
++
++ dev_dbg(dev, "%s(ptr=%p,size=%d,dir=%x)\n",
++ __func__, (void *)dma_addr, size, dir);
++
++ local_irq_save(flags);
++
++ sync_single(dev, dma_addr, size, dir);
++
++ local_irq_restore(flags);
++}
++
++void
++dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++ unsigned long flags;
++ int i;
++
++ dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", __func__, sg, nents, dir);
++
++ BUG_ON(dir == DMA_NONE);
++
++ local_irq_save(flags);
++
++ for (i = 0; i < nents; i++, sg++) {
++ dma_addr_t dma_addr = sg->dma_address;
++ unsigned int length = sg->length;
++
++ sync_single(dev, dma_addr, length, dir);
++ }
++
++ local_irq_restore(flags);
++}
++
++void
++dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++ unsigned long flags;
++ int i;
++
++ dev_dbg(dev, "%s(sg=%p,nents=%d,dir=%x)\n", __func__, sg, nents, dir);
++
++ BUG_ON(dir == DMA_NONE);
++
++ local_irq_save(flags);
++
++ for (i = 0; i < nents; i++, sg++) {
++ dma_addr_t dma_addr = sg->dma_address;
++ unsigned int length = sg->length;
++
++ sync_single(dev, dma_addr, length, dir);
++ }
++
++ local_irq_restore(flags);
++}
++
++int
++dmabounce_register_dev(struct device *dev, unsigned long small_buffer_size,
++ unsigned long large_buffer_size)
++{
++ struct dmabounce_device_info *device_info;
++
++ device_info = kmalloc(sizeof(struct dmabounce_device_info), GFP_ATOMIC);
++ if (!device_info) {
++ printk(KERN_ERR
++ "Could not allocated dmabounce_device_info for %s",
++ dev->bus_id);
++ return -ENOMEM;
++ }
++
++ device_info->small_buffer_pool =
++ dma_pool_create("small_dmabounce_pool",
++ dev, small_buffer_size, 0 /* byte alignment */ ,
++ 0 /* no page-crossing issues */ );
++ if (!device_info->small_buffer_pool) {
++ printk(KERN_ERR
++ "dmabounce: could not allocate small DMA pool for %s\n",
++ dev->bus_id);
++ kfree(device_info);
++ return -ENOMEM;
++ }
++
++ if (large_buffer_size) {
++ device_info->large_buffer_pool =
++ dma_pool_create("large_dmabounce_pool",
++ dev,
++ large_buffer_size, 0 /* byte alignment */ ,
++ 0 /* no page-crossing issues */ );
++ if (!device_info->large_buffer_pool) {
++ printk(KERN_ERR
++ "dmabounce: could not allocate large DMA pool for %s\n",
++ dev->bus_id);
++ dma_pool_destroy(device_info->small_buffer_pool);
++
++ return -ENOMEM;
++ }
++ }
++
++ device_info->dev = dev;
++ device_info->small_buffer_size = small_buffer_size;
++ device_info->large_buffer_size = large_buffer_size;
++ INIT_LIST_HEAD(&device_info->safe_buffers);
++
++#ifdef STATS
++ device_info->sbp_allocs = 0;
++ device_info->lbp_allocs = 0;
++ device_info->total_allocs = 0;
++ device_info->map_op_count = 0;
++ device_info->bounce_count = 0;
++#endif
++
++ list_add(&device_info->node, &dmabounce_devs);
++
++ printk(KERN_INFO "dmabounce: registered device %s on %s bus\n",
++ dev->bus_id, dev->bus->name);
++
++ return 0;
++}
++
++void dmabounce_unregister_dev(struct device *dev)
++{
++ struct dmabounce_device_info *device_info = find_dmabounce_dev(dev);
++
++ if (!device_info) {
++ printk(KERN_WARNING
++ "%s: Never registered with dmabounce but attempting"
++ "to unregister!\n", dev->bus_id);
++ return;
++ }
++
++ if (!list_empty(&device_info->safe_buffers)) {
++ printk(KERN_ERR
++ "%s: Removing from dmabounce with pending buffers!\n",
++ dev->bus_id);
++ BUG();
++ }
++
++ if (device_info->small_buffer_pool)
++ dma_pool_destroy(device_info->small_buffer_pool);
++ if (device_info->large_buffer_pool)
++ dma_pool_destroy(device_info->large_buffer_pool);
++
++#ifdef STATS
++ print_alloc_stats(device_info);
++ print_map_stats(device_info);
++#endif
++
++ list_del(&device_info->node);
++
++ kfree(device_info);
++
++ printk(KERN_INFO "dmabounce: device %s on %s bus unregistered\n",
++ dev->bus_id, dev->bus->name);
++}
++
++EXPORT_SYMBOL(dma_map_single);
++EXPORT_SYMBOL(dma_unmap_single);
++EXPORT_SYMBOL(dma_map_sg);
++EXPORT_SYMBOL(dma_unmap_sg);
++EXPORT_SYMBOL(dma_sync_single);
++EXPORT_SYMBOL(dma_sync_sg);
++EXPORT_SYMBOL(dmabounce_register_dev);
++EXPORT_SYMBOL(dmabounce_unregister_dev);
++
++MODULE_AUTHOR
++ ("Christopher Hoover <ch@hpl.hp.com>, Deepak Saxena <dsaxena@plexity.net>");
++MODULE_DESCRIPTION
++ ("Special dma_{map/unmap/dma_sync}_* routines for systems with limited DMA windows");
++MODULE_LICENSE("GPL");
+diff -Nur linux-3.4.110.orig/arch/nds32/common/Makefile linux-3.4.110/arch/nds32/common/Makefile
+--- linux-3.4.110.orig/arch/nds32/common/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/common/Makefile 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,6 @@
++#
++# Makefile for the linux kernel.
++#
++
++obj-y += rtctime.o
++obj-$(CONFIG_DMABOUNCE) += dmabounce.o
+diff -Nur linux-3.4.110.orig/arch/nds32/common/rtctime.c linux-3.4.110/arch/nds32/common/rtctime.c
+--- linux-3.4.110.orig/arch/nds32/common/rtctime.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/common/rtctime.c 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,441 @@
++/*
++ * linux/arch/nds32/common/rtctime.c
++ *
++ * Copyright (C) 2003 Deep Blue Solutions Ltd.
++ * Based on sa1100-rtc.c, Nils Faerber, CIH, Nicolas Pitre.
++ * Based on rtc.c by Paul Gortmaker
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/time.h>
++#include <linux/rtc.h>
++#include <linux/poll.h>
++#include <linux/proc_fs.h>
++#include <linux/miscdevice.h>
++#include <linux/spinlock.h>
++#include <linux/capability.h>
++#include <linux/device.h>
++#include <linux/mutex.h>
++#include <linux/rtc.h>
++
++#include <asm/rtc.h>
++#include <asm/semaphore.h>
++
++static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
++static struct fasync_struct *rtc_async_queue;
++
++/*
++ * rtc_lock protects rtc_irq_data
++ */
++static DEFINE_SPINLOCK(rtc_lock);
++static unsigned long rtc_irq_data;
++
++/*
++ * rtc_sem protects rtc_inuse and rtc_ops
++ */
++static DEFINE_MUTEX(rtc_mutex);
++static unsigned long rtc_inuse;
++static struct rtc_ops *rtc_ops;
++
++#define rtc_epoch 1900UL
++
++/*
++ * Calculate the next alarm time given the requested alarm time mask
++ * and the current time.
++ */
++void rtc_next_alarm_time(struct rtc_time *next, struct rtc_time *now,
++ struct rtc_time *alrm)
++{
++ unsigned long next_time;
++ unsigned long now_time;
++
++ next->tm_year = now->tm_year;
++ next->tm_mon = now->tm_mon;
++ next->tm_mday = now->tm_mday;
++ next->tm_hour = alrm->tm_hour;
++ next->tm_min = alrm->tm_min;
++ next->tm_sec = alrm->tm_sec;
++
++ rtc_tm_to_time(now, &now_time);
++ rtc_tm_to_time(next, &next_time);
++
++ if (next_time < now_time) {
++ /* Advance one day */
++ next_time += 60 * 60 * 24;
++ rtc_time_to_tm(next_time, next);
++ }
++}
++
++static inline int rtc_arm_read_time(struct rtc_ops *ops, struct rtc_time *tm)
++{
++ memset(tm, 0, sizeof(struct rtc_time));
++ return ops->read_time(tm);
++}
++
++static inline int rtc_arm_set_time(struct rtc_ops *ops, struct rtc_time *tm)
++{
++ int ret;
++
++ ret = rtc_valid_tm(tm);
++ if (ret == 0)
++ ret = ops->set_time(tm);
++
++ return ret;
++}
++
++static inline int rtc_arm_read_alarm(struct rtc_ops *ops,
++ struct rtc_wkalrm *alrm)
++{
++ int ret = -EINVAL;
++ if (ops->read_alarm) {
++ memset(alrm, 0, sizeof(struct rtc_wkalrm));
++ ret = ops->read_alarm(alrm);
++ }
++ return ret;
++}
++
++static inline int rtc_arm_set_alarm(struct rtc_ops *ops,
++ struct rtc_wkalrm *alrm)
++{
++ int ret = -EINVAL;
++ if (ops->set_alarm)
++ ret = ops->set_alarm(alrm);
++ return ret;
++}
++
++void rtc_update(unsigned long num, unsigned long events)
++{
++ spin_lock(&rtc_lock);
++ rtc_irq_data = (rtc_irq_data + (num << 8)) | events;
++ spin_unlock(&rtc_lock);
++
++ wake_up_interruptible(&rtc_wait);
++ kill_fasync(&rtc_async_queue, SIGIO, POLL_IN);
++}
++
++EXPORT_SYMBOL(rtc_update);
++
++static ssize_t
++rtc_read(struct file *file, char __user * buf, size_t count, loff_t * ppos)
++{
++ DECLARE_WAITQUEUE(wait, current);
++ unsigned long data;
++ ssize_t ret;
++
++ if (count < sizeof(unsigned long))
++ return -EINVAL;
++
++ add_wait_queue(&rtc_wait, &wait);
++ do {
++ __set_current_state(TASK_INTERRUPTIBLE);
++
++ spin_lock_irq(&rtc_lock);
++ data = rtc_irq_data;
++ rtc_irq_data = 0;
++ spin_unlock_irq(&rtc_lock);
++
++ if (data != 0) {
++ ret = 0;
++ break;
++ }
++ if (file->f_flags & O_NONBLOCK) {
++ ret = -EAGAIN;
++ break;
++ }
++ if (signal_pending(current)) {
++ ret = -ERESTARTSYS;
++ break;
++ }
++ schedule();
++ } while (1);
++ set_current_state(TASK_RUNNING);
++ remove_wait_queue(&rtc_wait, &wait);
++
++ if (ret == 0) {
++ ret = put_user(data, (unsigned long __user *)buf);
++ if (ret == 0)
++ ret = sizeof(unsigned long);
++ }
++ return ret;
++}
++
++static unsigned int rtc_poll(struct file *file, poll_table * wait)
++{
++ unsigned long data;
++
++ poll_wait(file, &rtc_wait, wait);
++
++ spin_lock_irq(&rtc_lock);
++ data = rtc_irq_data;
++ spin_unlock_irq(&rtc_lock);
++
++ return data != 0 ? POLLIN | POLLRDNORM : 0;
++}
++
++static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ struct rtc_ops *ops = file->private_data;
++ struct rtc_time tm;
++ struct rtc_wkalrm alrm;
++ void __user *uarg = (void __user *)arg;
++ int ret = -EINVAL;
++
++ switch (cmd) {
++ case RTC_ALM_READ:
++ ret = rtc_arm_read_alarm(ops, &alrm);
++ if (ret)
++ break;
++ ret = copy_to_user(uarg, &alrm.time, sizeof(tm));
++ if (ret)
++ ret = -EFAULT;
++ break;
++
++ case RTC_ALM_SET:
++ ret = copy_from_user(&alrm.time, uarg, sizeof(tm));
++ if (ret) {
++ ret = -EFAULT;
++ break;
++ }
++ alrm.enabled = 0;
++ alrm.pending = 0;
++ alrm.time.tm_mday = -1;
++ alrm.time.tm_mon = -1;
++ alrm.time.tm_year = -1;
++ alrm.time.tm_wday = -1;
++ alrm.time.tm_yday = -1;
++ alrm.time.tm_isdst = -1;
++ ret = rtc_arm_set_alarm(ops, &alrm);
++ break;
++
++ case RTC_RD_TIME:
++ ret = rtc_arm_read_time(ops, &tm);
++ if (ret)
++ break;
++ ret = copy_to_user(uarg, &tm, sizeof(tm));
++ if (ret)
++ ret = -EFAULT;
++ break;
++
++ case RTC_SET_TIME:
++ if (!capable(CAP_SYS_TIME)) {
++ ret = -EACCES;
++ break;
++ }
++ ret = copy_from_user(&tm, uarg, sizeof(tm));
++ if (ret) {
++ ret = -EFAULT;
++ break;
++ }
++ ret = rtc_arm_set_time(ops, &tm);
++ break;
++
++ case RTC_EPOCH_SET:
++#ifndef rtc_epoch
++ /*
++ * There were no RTC clocks before 1900.
++ */
++ if (arg < 1900) {
++ ret = -EINVAL;
++ break;
++ }
++ if (!capable(CAP_SYS_TIME)) {
++ ret = -EACCES;
++ break;
++ }
++ rtc_epoch = arg;
++ ret = 0;
++#endif
++ break;
++
++ case RTC_EPOCH_READ:
++ ret = put_user(rtc_epoch, (unsigned long __user *)uarg);
++ break;
++
++ case RTC_WKALM_SET:
++ ret = copy_from_user(&alrm, uarg, sizeof(alrm));
++ if (ret) {
++ ret = -EFAULT;
++ break;
++ }
++ ret = rtc_arm_set_alarm(ops, &alrm);
++ break;
++
++ case RTC_WKALM_RD:
++ ret = rtc_arm_read_alarm(ops, &alrm);
++ if (ret)
++ break;
++ ret = copy_to_user(uarg, &alrm, sizeof(alrm));
++ if (ret)
++ ret = -EFAULT;
++ break;
++
++ default:
++ if (ops->ioctl)
++ ret = ops->ioctl(cmd, arg);
++ break;
++ }
++ return ret;
++}
++
++static int rtc_open(struct inode *inode, struct file *file)
++{
++ int ret;
++
++ mutex_lock(&rtc_mutex);
++
++ if (rtc_inuse) {
++ ret = -EBUSY;
++ } else if (!rtc_ops || !try_module_get(rtc_ops->owner)) {
++ ret = -ENODEV;
++ } else {
++ file->private_data = rtc_ops;
++
++ ret = rtc_ops->open ? rtc_ops->open() : 0;
++ if (ret == 0) {
++ spin_lock_irq(&rtc_lock);
++ rtc_irq_data = 0;
++ spin_unlock_irq(&rtc_lock);
++
++ rtc_inuse = 1;
++ }
++ }
++ mutex_unlock(&rtc_mutex);
++
++ return ret;
++}
++
++static int rtc_release(struct inode *inode, struct file *file)
++{
++ struct rtc_ops *ops = file->private_data;
++
++ if (ops->release)
++ ops->release();
++
++ spin_lock_irq(&rtc_lock);
++ rtc_irq_data = 0;
++ spin_unlock_irq(&rtc_lock);
++
++ module_put(rtc_ops->owner);
++ rtc_inuse = 0;
++
++ return 0;
++}
++
++static int rtc_fasync(int fd, struct file *file, int on)
++{
++ return fasync_helper(fd, file, on, &rtc_async_queue);
++}
++
++static struct file_operations rtc_fops = {
++ .owner = THIS_MODULE,
++ .llseek = no_llseek,
++ .read = rtc_read,
++ .poll = rtc_poll,
++ .ioctl = rtc_ioctl,
++ .open = rtc_open,
++ .release = rtc_release,
++ .fasync = rtc_fasync,
++};
++
++static struct miscdevice rtc_miscdev = {
++ .minor = RTC_MINOR,
++ .name = "rtc",
++ .fops = &rtc_fops,
++};
++
++static int rtc_read_proc(char *page, char **start, off_t off, int count,
++ int *eof, void *data)
++{
++ struct rtc_ops *ops = data;
++ struct rtc_wkalrm alrm;
++ struct rtc_time tm;
++ char *p = page;
++
++ if (rtc_arm_read_time(ops, &tm) == 0) {
++ p += sprintf(p,
++ "rtc_time\t: %02d:%02d:%02d\n"
++ "rtc_date\t: %04d-%02d-%02d\n"
++ "rtc_epoch\t: %04lu\n",
++ tm.tm_hour, tm.tm_min, tm.tm_sec,
++ tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
++ rtc_epoch);
++ }
++
++ if (rtc_arm_read_alarm(ops, &alrm) == 0) {
++ p += sprintf(p, "alrm_time\t: ");
++ if ((unsigned int)alrm.time.tm_hour <= 24)
++ p += sprintf(p, "%02d:", alrm.time.tm_hour);
++ else
++ p += sprintf(p, "**:");
++ if ((unsigned int)alrm.time.tm_min <= 59)
++ p += sprintf(p, "%02d:", alrm.time.tm_min);
++ else
++ p += sprintf(p, "**:");
++ if ((unsigned int)alrm.time.tm_sec <= 59)
++ p += sprintf(p, "%02d\n", alrm.time.tm_sec);
++ else
++ p += sprintf(p, "**\n");
++
++ p += sprintf(p, "alrm_date\t: ");
++ if ((unsigned int)alrm.time.tm_year <= 200)
++ p += sprintf(p, "%04d-", alrm.time.tm_year + 1900);
++ else
++ p += sprintf(p, "****-");
++ if ((unsigned int)alrm.time.tm_mon <= 11)
++ p += sprintf(p, "%02d-", alrm.time.tm_mon + 1);
++ else
++ p += sprintf(p, "**-");
++ if ((unsigned int)alrm.time.tm_mday <= 31)
++ p += sprintf(p, "%02d\n", alrm.time.tm_mday);
++ else
++ p += sprintf(p, "**\n");
++ p += sprintf(p, "alrm_wakeup\t: %s\n",
++ alrm.enabled ? "yes" : "no");
++ p += sprintf(p, "alrm_pending\t: %s\n",
++ alrm.pending ? "yes" : "no");
++ }
++
++ if (ops->proc)
++ p += ops->proc(p);
++
++ return p - page;
++}
++
++int register_rtc(struct rtc_ops *ops)
++{
++ int ret = -EBUSY;
++
++ mutex_lock(&rtc_mutex);
++ if (rtc_ops == NULL) {
++ rtc_ops = ops;
++
++ ret = misc_register(&rtc_miscdev);
++ if (ret == 0)
++ create_proc_read_entry("driver/rtc", 0, NULL,
++ rtc_read_proc, ops);
++ }
++ mutex_unlock(&rtc_mutex);
++
++ return ret;
++}
++
++EXPORT_SYMBOL(register_rtc);
++
++void unregister_rtc(struct rtc_ops *rtc)
++{
++ mutex_lock(&rtc_mutex);
++ if (rtc == rtc_ops) {
++ remove_proc_entry("driver/rtc", NULL);
++ misc_deregister(&rtc_miscdev);
++ rtc_ops = NULL;
++ }
++ mutex_unlock(&rtc_mutex);
++}
++
++EXPORT_SYMBOL(unregister_rtc);
+diff -Nur linux-3.4.110.orig/arch/nds32/configs/orca_8k_defconfig linux-3.4.110/arch/nds32/configs/orca_8k_defconfig
+--- linux-3.4.110.orig/arch/nds32/configs/orca_8k_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/configs/orca_8k_defconfig 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,132 @@
++CONFIG_EXPERIMENTAL=y
++CONFIG_CROSS_COMPILE="nds32le-linux-"
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SYSVIPC=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_HOTPLUG is not set
++# CONFIG_SIGNALFD is not set
++CONFIG_EMBEDDED=y
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_PROFILING=y
++CONFIG_OPROFILE=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_BLK_DEV_BSG is not set
++CONFIG_PLATFORM_AHBDMA=y
++CONFIG_PLATFORM_APBDMA=y
++CONFIG_SYS_CLK=30000000
++CONFIG_UART_CLK=14745600
++CONFIG_SDRAM_SIZE=0x40000000
++CONFIG_CPU_CACHE_NONALIASING=y
++CONFIG_ANDES_PAGE_SIZE_8KB=y
++CONFIG_HIGHMEM=y
++CONFIG_HZ_100=y
++CONFIG_CMDLINE="root=/dev/ram0 rw mem=1024M@0x0 initrd=0x1000000,8M earlyprintk=uart8250-32bit,0x99600000 console=ttyS0,38400n8 loglevel=7 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_IPV6 is not set
++CONFIG_BRIDGE=y
++CONFIG_MTD=y
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++CONFIG_MTD_CFI=y
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_COMPAT=y
++CONFIG_MTD_PHYSMAP_START=0x80400000
++CONFIG_MTD_PHYSMAP_LEN=0x2000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_SIZE=8192
++CONFIG_NETDEVICES=y
++CONFIG_TUN=y
++CONFIG_FTMAC100=y
++# CONFIG_INPUT_MOUSEDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_CPE_TS=y
++# CONFIG_SERIO is not set
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++# CONFIG_HW_RANDOM is not set
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++CONFIG_GPIO_FTGPIO010=y
++# CONFIG_HWMON is not set
++CONFIG_WATCHDOG=y
++CONFIG_FTWDT010_WATCHDOG=y
++CONFIG_FB=y
++CONFIG_FB_FTLCDC100=y
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_LOGO=y
++CONFIG_SOUND=y
++CONFIG_SND=y
++CONFIG_SND_PCM_OSS=y
++# CONFIG_SND_SUPPORT_OLD_API is not set
++# CONFIG_SND_VERBOSE_PROCFS is not set
++CONFIG_SND_FTSSP010=y
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++CONFIG_MMC=y
++CONFIG_MMC_FTSDC010=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++CONFIG_RTC_DRV_FTRTC010=y
++CONFIG_EXT2_FS=y
++CONFIG_FUSE_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++# CONFIG_PROC_PAGE_MONITOR is not set
++CONFIG_TMPFS=y
++CONFIG_JFFS2_FS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++CONFIG_NFS_V4_1=y
++CONFIG_NFS_USE_LEGACY_DNS=y
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_ISO8859_1=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_DEBUG_FS=y
++CONFIG_DEBUG_SHIRQ=y
++CONFIG_SCHEDSTATS=y
++CONFIG_TIMER_STATS=y
++CONFIG_SLUB_DEBUG_ON=y
++CONFIG_DEBUG_RT_MUTEXES=y
++CONFIG_DEBUG_SPINLOCK=y
++CONFIG_DEBUG_MUTEXES=y
++CONFIG_DEBUG_INFO=y
++CONFIG_DEBUG_MEMORY_INIT=y
++CONFIG_DEBUG_LIST=y
++CONFIG_DEBUG_SG=y
++# CONFIG_FTRACE is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
+diff -Nur linux-3.4.110.orig/arch/nds32/configs/orca_defconfig linux-3.4.110/arch/nds32/configs/orca_defconfig
+--- linux-3.4.110.orig/arch/nds32/configs/orca_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/configs/orca_defconfig 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,125 @@
++CONFIG_EXPERIMENTAL=y
++CONFIG_CROSS_COMPILE="nds32le-linux-"
++CONFIG_SYSVIPC=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_NAMESPACES=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS_ALL=y
++# CONFIG_HOTPLUG is not set
++CONFIG_EMBEDDED=y
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_PROFILING=y
++CONFIG_OPROFILE=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_BLK_DEV_BSG is not set
++CONFIG_MEASURE_INTERRUPT_LATENCY=y
++CONFIG_PLATFORM_AHBDMA=y
++CONFIG_PLATFORM_APBDMA=y
++CONFIG_SYS_CLK=30000000
++CONFIG_UART_CLK=14745600
++CONFIG_SDRAM_SIZE=0x40000000
++CONFIG_MEMORY_START=0x0
++# CONFIG_HWZOL is not set
++CONFIG_IVIC=y
++CONFIG_HIGH_RES_TIMERS=y
++CONFIG_PREEMPT=y
++CONFIG_HZ_100=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_IPV6 is not set
++CONFIG_BRIDGE=y
++CONFIG_MTD=y
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++CONFIG_MTD_CFI=y
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_COMPAT=y
++CONFIG_MTD_PHYSMAP_START=0x80400000
++CONFIG_MTD_PHYSMAP_LEN=0x2000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_SIZE=8192
++CONFIG_NETDEVICES=y
++CONFIG_TUN=y
++CONFIG_FTMAC100=y
++# CONFIG_INPUT_MOUSEDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_CPE_TS=m
++# CONFIG_SERIO is not set
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++# CONFIG_HW_RANDOM is not set
++CONFIG_GPIOLIB=y
++CONFIG_GPIO_SYSFS=y
++CONFIG_GPIO_FTGPIO010=m
++# CONFIG_HWMON is not set
++CONFIG_WATCHDOG=y
++CONFIG_FTWDT010_WATCHDOG=m
++CONFIG_FB=y
++CONFIG_FB_FTLCDC100=y
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_LOGO=y
++CONFIG_SOUND=y
++CONFIG_SND=y
++CONFIG_SND_PCM_OSS=y
++# CONFIG_SND_SUPPORT_OLD_API is not set
++# CONFIG_SND_VERBOSE_PROCFS is not set
++CONFIG_SND_FTSSP010=m
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++CONFIG_MMC=y
++CONFIG_MMC_FTSDC010=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++CONFIG_RTC_DRV_FTRTC010=y
++CONFIG_EXT2_FS=y
++CONFIG_FUSE_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_TMPFS=y
++CONFIG_TMPFS_POSIX_ACL=y
++CONFIG_CONFIGFS_FS=y
++CONFIG_JFFS2_FS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++CONFIG_NFS_V3_ACL=y
++CONFIG_NFS_V4=y
++CONFIG_NFS_V4_1=y
++CONFIG_NFS_USE_LEGACY_DNS=y
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_ISO8859_1=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_HEADERS_CHECK=y
++CONFIG_DEBUG_SECTION_MISMATCH=y
++# CONFIG_SCHED_DEBUG is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_FTRACE is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
+diff -Nur linux-3.4.110.orig/arch/nds32/configs/qemu_defconfig linux-3.4.110/arch/nds32/configs/qemu_defconfig
+--- linux-3.4.110.orig/arch/nds32/configs/qemu_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/configs/qemu_defconfig 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,98 @@
++CONFIG_EXPERIMENTAL=y
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SYSVIPC=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_HOTPLUG is not set
++# CONFIG_SIGNALFD is not set
++CONFIG_EMBEDDED=y
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_PROFILING=y
++CONFIG_OPROFILE=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_BLK_DEV_BSG is not set
++CONFIG_PLAT_QEMU=y
++CONFIG_SYS_CLK=40000000
++CONFIG_UART_CLK=14745600
++CONFIG_SDRAM_SIZE=0x10000000
++CONFIG_HZ_100=y
++CONFIG_CMDLINE="root=/dev/ram0 rw mem=1024M@0x0 initrd=0x1000000,8M earlyprintk=uart8250-32bit,0x99600000 console=ttyS0,38400n8 loglevel=7 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_IPV6 is not set
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_SIZE=8192
++CONFIG_FTSDC010=y
++CONFIG_NETDEVICES=y
++CONFIG_FTMAC100=y
++# CONFIG_INPUT_MOUSEDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_SERIO is not set
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++# CONFIG_HW_RANDOM is not set
++# CONFIG_HWMON is not set
++CONFIG_FB=y
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_LOGO=y
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++CONFIG_EXT2_FS_XIP=y
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_POSIX_ACL=y
++CONFIG_EXT3_FS_SECURITY=y
++CONFIG_EXT4_FS=y
++CONFIG_EXT4_FS_POSIX_ACL=y
++CONFIG_EXT4_FS_SECURITY=y
++CONFIG_EXT4_DEBUG=y
++CONFIG_FUSE_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++# CONFIG_PROC_PAGE_MONITOR is not set
++CONFIG_TMPFS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_ISO8859_1=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_DEBUG_FS=y
++CONFIG_DEBUG_SHIRQ=y
++CONFIG_DETECT_HUNG_TASK=y
++CONFIG_SCHEDSTATS=y
++CONFIG_TIMER_STATS=y
++CONFIG_SLUB_DEBUG_ON=y
++CONFIG_DEBUG_RT_MUTEXES=y
++CONFIG_DEBUG_MUTEXES=y
++CONFIG_DEBUG_INFO=y
++CONFIG_DEBUG_LIST=y
++CONFIG_DEBUG_SG=y
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
+diff -Nur linux-3.4.110.orig/arch/nds32/configs/vep-be_defconfig linux-3.4.110/arch/nds32/configs/vep-be_defconfig
+--- linux-3.4.110.orig/arch/nds32/configs/vep-be_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/configs/vep-be_defconfig 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,777 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.29
++# Mon Jul 13 11:42:57 2009
++#
++CONFIG_NDS32=y
++CONFIG_NO_IOPORT=y
++CONFIG_GENERIC_IOMAP=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++
++#
++# RCU Subsystem
++#
++CONFIG_CLASSIC_RCU=y
++# CONFIG_TREE_RCU is not set
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_TREE_RCU_TRACE is not set
++# CONFIG_PREEMPT_RCU_TRACE is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_GROUP_SCHED is not set
++# CONFIG_CGROUPS is not set
++# CONFIG_SYSFS_DEPRECATED_V2 is not set
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++# CONFIG_ELF_CORE is not set
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++# CONFIG_SIGNALFD is not set
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_PROFILING=y
++CONFIG_TRACEPOINTS=y
++# CONFIG_MARKERS is not set
++CONFIG_OPROFILE=y
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
++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 is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++# CONFIG_FREEZER is not set
++
++#
++# System Type
++#
++# CONFIG_PLAT_FARADAY is not set
++CONFIG_PLAT_VEP=y
++# CONFIG_PLAT_AG101 is not set
++# CONFIG_PLAT_AG102 is not set
++# CONFIG_PLAT_AG101P is not set
++# CONFIG_PLAT_QEMU is not set
++CONFIG_PLATFORM_INTC=y
++
++#
++# VEP Platform Options
++#
++# CONFIG_CACHE_L2 is not set
++
++#
++# Common Platform Options
++#
++# CONFIG_PLATFORM_AHBDMA is not set
++# CONFIG_PLATFORM_APBDMA is not set
++CONFIG_SYS_CLK=67737600
++CONFIG_UART_CLK=36864000
++CONFIG_SDRAM_SIZE=0x10000000
++
++#
++# Processor Features
++#
++CONFIG_CPU_CUSTOM=y
++# CONFIG_FPU is not set
++# CONFIG_AUDIO is not set
++# CONFIG_EVIC is not set
++CONFIG_CPU_CONTEXT_ID=y
++CONFIG_ANDES_PAGE_SIZE_4KB=y
++# CONFIG_ANDES_PAGE_SIZE_8KB is not set
++# CONFIG_KERNEL_SPACE_LARGE_PAGE is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_ALIGNMENT_TRAP is not set
++CONFIG_MMU=y
++
++#
++# Kernel Features
++#
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_HZ_100=y
++# CONFIG_HZ_250 is not set
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=100
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_CMDLINE="root=/dev/ram0 rw mem=64M@0x0 initrd=0x1000000,8M console=ttyS0,38400n8 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
++
++#
++# Power management options
++#
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++# CONFIG_PM is not set
++
++#
++# Bus options
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_HAVE_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_COMPAT_NET_DEV_OPS=y
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=y
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_DCB is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++CONFIG_WIRELESS=y
++# CONFIG_CFG80211 is not set
++CONFIG_WIRELESS_OLD_REGULATORY=y
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_LIB80211 is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_WIMAX is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=8192
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_FTSDC010 is not set
++# CONFIG_FTCFC010 is not set
++# CONFIG_BLK_DEV_HD is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DNET is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
++# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
++# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
++# CONFIG_B44 is not set
++CONFIG_FTMAC100=y
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++
++#
++# Enable WiMAX (Networking options) to see the WiMAX drivers
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_R3964 is not set
++# CONFIG_GPIO_FTGPIO010 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++# CONFIG_SPI is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++# CONFIG_WATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_REGULATOR is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_ACCESSIBILITY is not set
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++# CONFIG_UIO is not set
++# CONFIG_STAGING is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_BTRFS_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++CONFIG_FUSE_FS=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++# CONFIG_PROC_KCORE is not set
++CONFIG_PROC_SYSCTL=y
++# CONFIG_PROC_PAGE_MONITOR is not set
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++CONFIG_MISC_FILESYSTEMS=y
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_SQUASHFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_STACKTRACE=y
++# CONFIG_DEBUG_MEMORY_INIT is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_LATENCYTOP is not set
++CONFIG_SYSCTL_SYSCALL_CHECK=y
++CONFIG_NOP_TRACER=y
++CONFIG_RING_BUFFER=y
++CONFIG_TRACING=y
++
++#
++# Tracers
++#
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++CONFIG_DEBUG_USER=y
++# CONFIG_CCTL is not set
++CONFIG_ELFCHK_DEFAULT_ENABLE=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_MANAGER2 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_GENERIC_FIND_LAST_BIT=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++# CONFIG_CRC_ITU_T is not set
++# CONFIG_CRC32 is not set
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_DMA=y
+diff -Nur linux-3.4.110.orig/arch/nds32/configs/vep-le_defconfig linux-3.4.110/arch/nds32/configs/vep-le_defconfig
+--- linux-3.4.110.orig/arch/nds32/configs/vep-le_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/configs/vep-le_defconfig 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,777 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.29
++# Mon Jul 13 11:41:30 2009
++#
++CONFIG_NDS32=y
++CONFIG_NO_IOPORT=y
++CONFIG_GENERIC_IOMAP=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++
++#
++# RCU Subsystem
++#
++CONFIG_CLASSIC_RCU=y
++# CONFIG_TREE_RCU is not set
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_TREE_RCU_TRACE is not set
++# CONFIG_PREEMPT_RCU_TRACE is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_GROUP_SCHED is not set
++# CONFIG_CGROUPS is not set
++# CONFIG_SYSFS_DEPRECATED_V2 is not set
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_KALLSYMS is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++# CONFIG_ELF_CORE is not set
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++# CONFIG_SIGNALFD is not set
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_PROFILING=y
++CONFIG_TRACEPOINTS=y
++# CONFIG_MARKERS is not set
++CONFIG_OPROFILE=y
++CONFIG_HAVE_OPROFILE=y
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
++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 is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++# CONFIG_IOSCHED_DEADLINE is not set
++# CONFIG_IOSCHED_CFQ is not set
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++CONFIG_DEFAULT_NOOP=y
++CONFIG_DEFAULT_IOSCHED="noop"
++# CONFIG_FREEZER is not set
++
++#
++# System Type
++#
++# CONFIG_PLAT_FARADAY is not set
++CONFIG_PLAT_VEP=y
++# CONFIG_PLAT_AG101 is not set
++# CONFIG_PLAT_AG102 is not set
++# CONFIG_PLAT_AG101P is not set
++# CONFIG_PLAT_QEMU is not set
++CONFIG_PLATFORM_INTC=y
++
++#
++# VEP Platform Options
++#
++# CONFIG_CACHE_L2 is not set
++
++#
++# Common Platform Options
++#
++# CONFIG_PLATFORM_AHBDMA is not set
++# CONFIG_PLATFORM_APBDMA is not set
++CONFIG_SYS_CLK=67737600
++CONFIG_UART_CLK=36864000
++CONFIG_SDRAM_SIZE=0x10000000
++
++#
++# Processor Features
++#
++CONFIG_CPU_CUSTOM=y
++# CONFIG_FPU is not set
++# CONFIG_AUDIO is not set
++# CONFIG_EVIC is not set
++CONFIG_CPU_CONTEXT_ID=y
++CONFIG_ANDES_PAGE_SIZE_4KB=y
++# CONFIG_ANDES_PAGE_SIZE_8KB is not set
++# CONFIG_KERNEL_SPACE_LARGE_PAGE is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_ALIGNMENT_TRAP is not set
++CONFIG_MMU=y
++
++#
++# Kernel Features
++#
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_HZ_100=y
++# CONFIG_HZ_250 is not set
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=100
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_CMDLINE="root=/dev/ram0 rw mem=64M@0x0 initrd=0x1000000,8M console=ttyS0,38400n8 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
++
++#
++# Power management options
++#
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++# CONFIG_PM is not set
++
++#
++# Bus options
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_HAVE_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_COMPAT_NET_DEV_OPS=y
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=y
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_DCB is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++CONFIG_WIRELESS=y
++# CONFIG_CFG80211 is not set
++CONFIG_WIRELESS_OLD_REGULATORY=y
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_LIB80211 is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_WIMAX is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++# CONFIG_MTD is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=8192
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++# CONFIG_FTSDC010 is not set
++# CONFIG_FTCFC010 is not set
++# CONFIG_BLK_DEV_HD is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DNET is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
++# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
++# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
++# CONFIG_B44 is not set
++CONFIG_FTMAC100=y
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++
++#
++# Enable WiMAX (Networking options) to see the WiMAX drivers
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_R3964 is not set
++# CONFIG_GPIO_FTGPIO010 is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++# CONFIG_SPI is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++# CONFIG_WATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_REGULATOR is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++# CONFIG_FB is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++# CONFIG_SOUND is not set
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_ACCESSIBILITY is not set
++CONFIG_RTC_LIB=y
++# CONFIG_RTC_CLASS is not set
++# CONFIG_DMADEVICES is not set
++# CONFIG_UIO is not set
++# CONFIG_STAGING is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_BTRFS_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++CONFIG_FUSE_FS=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++# CONFIG_MSDOS_FS is not set
++# CONFIG_VFAT_FS is not set
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++# CONFIG_PROC_KCORE is not set
++CONFIG_PROC_SYSCTL=y
++# CONFIG_PROC_PAGE_MONITOR is not set
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++CONFIG_MISC_FILESYSTEMS=y
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_SQUASHFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++# CONFIG_DEBUG_KERNEL is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_STACKTRACE=y
++# CONFIG_DEBUG_MEMORY_INIT is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_LATENCYTOP is not set
++CONFIG_SYSCTL_SYSCALL_CHECK=y
++CONFIG_NOP_TRACER=y
++CONFIG_RING_BUFFER=y
++CONFIG_TRACING=y
++
++#
++# Tracers
++#
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++CONFIG_DEBUG_USER=y
++# CONFIG_CCTL is not set
++CONFIG_ELFCHK_DEFAULT_ENABLE=y
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_MANAGER2 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_GENERIC_FIND_LAST_BIT=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++# CONFIG_CRC_ITU_T is not set
++# CONFIG_CRC32 is not set
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_DMA=y
+diff -Nur linux-3.4.110.orig/arch/nds32/configs/xc5_8k_defconfig linux-3.4.110/arch/nds32/configs/xc5_8k_defconfig
+--- linux-3.4.110.orig/arch/nds32/configs/xc5_8k_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/configs/xc5_8k_defconfig 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,1051 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.29
++# Fri Oct 2 14:21:05 2009
++#
++CONFIG_NDS32=y
++# CONFIG_GENERIC_GPIO is not set
++CONFIG_NO_IOPORT=y
++CONFIG_GENERIC_IOMAP=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_HWEIGHT=y
++CONFIG_GENERIC_FIND_NEXT_BIT=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_HARDIRQS=y
++CONFIG_LOCKDEP_SUPPORT=y
++CONFIG_STACKTRACE_SUPPORT=y
++CONFIG_HAVE_LATENCYTOP_SUPPORT=y
++CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
++
++#
++# General setup
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++CONFIG_LOCALVERSION=""
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_SYSVIPC_SYSCTL=y
++# CONFIG_POSIX_MQUEUE is not set
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++# CONFIG_TASKSTATS is not set
++# CONFIG_AUDIT is not set
++
++#
++# RCU Subsystem
++#
++CONFIG_CLASSIC_RCU=y
++# CONFIG_TREE_RCU is not set
++# CONFIG_PREEMPT_RCU is not set
++# CONFIG_TREE_RCU_TRACE is not set
++# CONFIG_PREEMPT_RCU_TRACE is not set
++# CONFIG_IKCONFIG is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_GROUP_SCHED is not set
++# CONFIG_CGROUPS is not set
++# CONFIG_SYSFS_DEPRECATED_V2 is not set
++# CONFIG_RELAY is not set
++# CONFIG_NAMESPACES is not set
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL=y
++CONFIG_ANON_INODES=y
++CONFIG_EMBEDDED=y
++CONFIG_UID16=y
++CONFIG_SYSCTL_SYSCALL=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++CONFIG_KALLSYMS_EXTRA_PASS=y
++# CONFIG_HOTPLUG 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 is not set
++CONFIG_TIMERFD=y
++CONFIG_EVENTFD=y
++CONFIG_SHMEM=y
++CONFIG_AIO=y
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_SLUB_DEBUG=y
++CONFIG_COMPAT_BRK=y
++# CONFIG_SLAB is not set
++CONFIG_SLUB=y
++# CONFIG_SLOB is not set
++CONFIG_PROFILING=y
++CONFIG_TRACEPOINTS=y
++# CONFIG_MARKERS is not set
++CONFIG_OPROFILE=y
++CONFIG_HAVE_OPROFILE=y
++# CONFIG_KPROBES is not set
++CONFIG_HAVE_KPROBES=y
++CONFIG_HAVE_KRETPROBES=y
++# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set
++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 is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_BLOCK=y
++# CONFIG_LBD is not set
++# CONFIG_BLK_DEV_IO_TRACE is not set
++# CONFIG_BLK_DEV_BSG is not set
++# CONFIG_BLK_DEV_INTEGRITY is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_DEFAULT_AS is not set
++# CONFIG_DEFAULT_DEADLINE is not set
++CONFIG_DEFAULT_CFQ=y
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="cfq"
++# CONFIG_FREEZER is not set
++
++#
++# System Type
++#
++# CONFIG_PLAT_VEP is not set
++# CONFIG_PLAT_AG101 is not set
++# CONFIG_PLAT_AG102 is not set
++CONFIG_PLAT_AG101P=y
++# CONFIG_PLAT_QEMU is not set
++CONFIG_PLATFORM_INTC=y
++CONFIG_ARCH_WANT_OPTIONAL_GPIOLIB=y
++
++#
++# AG101P Platform Options
++#
++
++#
++# Common Platform Options
++#
++CONFIG_PLATFORM_AHBDMA=y
++CONFIG_PLATFORM_APBDMA=y
++CONFIG_SYS_CLK=40000000
++CONFIG_UART_CLK=14745600
++CONFIG_SDRAM_SIZE=0x10000000
++
++#
++# Processor Features
++#
++CONFIG_CPU_CUSTOM=y
++# CONFIG_FPU is not set
++# CONFIG_AUDIO is not set
++# CONFIG_EVIC is not set
++CONFIG_CPU_CONTEXT_ID=y
++# CONFIG_CPU_CACHE_NONALIASING is not set
++# CONFIG_ANDES_PAGE_SIZE_4KB is not set
++CONFIG_ANDES_PAGE_SIZE_8KB=y
++CONFIG_KERNEL_SPACE_LARGE_PAGE=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++# CONFIG_ABI1 is not set
++CONFIG_ALIGNMENT_TRAP=y
++CONFIG_GENERIC_TIME=y
++CONFIG_GENERIC_CLOCKEVENTS=y
++CONFIG_MMU=y
++
++#
++# Kernel Features
++#
++# CONFIG_NO_HZ is not set
++# CONFIG_HIGH_RES_TIMERS is not set
++CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
++CONFIG_PREEMPT_NONE=y
++# CONFIG_PREEMPT_VOLUNTARY is not set
++# CONFIG_PREEMPT is not set
++CONFIG_SELECT_MEMORY_MODEL=y
++CONFIG_FLATMEM_MANUAL=y
++# CONFIG_DISCONTIGMEM_MANUAL is not set
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_FLATMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_PAGEFLAGS_EXTENDED=y
++CONFIG_SPLIT_PTLOCK_CPUS=4
++# CONFIG_PHYS_ADDR_T_64BIT is not set
++CONFIG_ZONE_DMA_FLAG=0
++CONFIG_VIRT_TO_BUS=y
++CONFIG_UNEVICTABLE_LRU=y
++CONFIG_FORCE_MAX_ZONEORDER=11
++CONFIG_HZ_100=y
++# CONFIG_HZ_250 is not set
++# CONFIG_HZ_300 is not set
++# CONFIG_HZ_1000 is not set
++CONFIG_HZ=100
++# CONFIG_SCHED_HRTICK is not set
++CONFIG_CMDLINE="root=/dev/ram0 rw mem=128M@0x0 initrd=0x1000000,8M console=ttyS0,38400n8 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
++
++#
++# Power management options
++#
++CONFIG_SYS_SUPPORTS_APM_EMULATION=y
++CONFIG_ARCH_SUSPEND_POSSIBLE=y
++# CONFIG_PM is not set
++
++#
++# Bus options
++#
++# CONFIG_PCI is not set
++# CONFIG_ARCH_SUPPORTS_MSI is not set
++
++#
++# Executable file formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++# CONFIG_HAVE_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_COMPAT_NET_DEV_OPS=y
++CONFIG_PACKET=y
++# CONFIG_PACKET_MMAP is not set
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++# CONFIG_XFRM_SUB_POLICY is not set
++# CONFIG_XFRM_MIGRATE is not set
++# CONFIG_XFRM_STATISTICS is not set
++CONFIG_NET_KEY=y
++# CONFIG_NET_KEY_MIGRATE is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++# CONFIG_IP_PNP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_IP_MROUTE is not set
++# CONFIG_ARPD is not set
++# CONFIG_SYN_COOKIES is not set
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_XFRM_TUNNEL is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_CUBIC=y
++CONFIG_DEFAULT_TCP_CONG="cubic"
++# CONFIG_TCP_MD5SIG is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETWORK_SECMARK is not set
++# CONFIG_NETFILTER is not set
++# CONFIG_IP_DCCP is not set
++# CONFIG_IP_SCTP is not set
++# CONFIG_TIPC is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_NET_DSA is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_DCB is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_CAN is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_AF_RXRPC is not set
++# CONFIG_PHONET is not set
++CONFIG_WIRELESS=y
++# CONFIG_CFG80211 is not set
++CONFIG_WIRELESS_OLD_REGULATORY=y
++# CONFIG_WIRELESS_EXT is not set
++# CONFIG_LIB80211 is not set
++# CONFIG_MAC80211 is not set
++# CONFIG_WIMAX is not set
++# CONFIG_RFKILL is not set
++# CONFIG_NET_9P is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_DEBUG_DEVRES is not set
++# CONFIG_SYS_HYPERVISOR is not set
++# CONFIG_CONNECTOR is not set
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_TESTS is not set
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AR7_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLKDEVS=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++# CONFIG_SSFDC is not set
++# CONFIG_MTD_OOPS is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++# CONFIG_MTD_JEDECPROBE is not set
++CONFIG_MTD_GEN_PROBE=y
++# CONFIG_MTD_CFI_ADV_OPTIONS is not set
++CONFIG_MTD_MAP_BANK_WIDTH_1=y
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++CONFIG_MTD_MAP_BANK_WIDTH_4=y
++# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
++CONFIG_MTD_CFI_I1=y
++CONFIG_MTD_CFI_I2=y
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++CONFIG_MTD_CFI_INTELEXT=y
++# CONFIG_MTD_CFI_AMDSTD is not set
++# CONFIG_MTD_CFI_STAA is not set
++CONFIG_MTD_CFI_UTIL=y
++# CONFIG_MTD_RAM is not set
++# CONFIG_MTD_ROM is not set
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_COMPAT=y
++CONFIG_MTD_PHYSMAP_START=0x80400000
++CONFIG_MTD_PHYSMAP_LEN=0x2000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLOCK2MTD is not set
++
++#
++# Disk-On-Chip Device Drivers
++#
++# CONFIG_MTD_DOC2000 is not set
++# CONFIG_MTD_DOC2001 is not set
++# CONFIG_MTD_DOC2001PLUS is not set
++# CONFIG_MTD_NAND is not set
++# CONFIG_MTD_ONENAND is not set
++
++#
++# LPDDR flash memory drivers
++#
++# CONFIG_MTD_LPDDR is not set
++
++#
++# UBI - Unsorted block images
++#
++# CONFIG_MTD_UBI is not set
++# CONFIG_PARPORT is not set
++CONFIG_BLK_DEV=y
++# CONFIG_BLK_DEV_COW_COMMON is not set
++CONFIG_BLK_DEV_LOOP=y
++# CONFIG_BLK_DEV_CRYPTOLOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=8192
++# CONFIG_BLK_DEV_XIP is not set
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++CONFIG_FTSDC010=y
++# CONFIG_FTCFC010 is not set
++# CONFIG_BLK_DEV_HD is not set
++# CONFIG_MISC_DEVICES is not set
++CONFIG_HAVE_IDE=y
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++# CONFIG_SCSI is not set
++# CONFIG_SCSI_DMA is not set
++# CONFIG_SCSI_NETLINK is not set
++# CONFIG_ATA is not set
++# CONFIG_MD is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_MACVLAN is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++# CONFIG_VETH is not set
++# CONFIG_PHYLIB is not set
++CONFIG_NET_ETHERNET=y
++# CONFIG_MII is not set
++# CONFIG_SMC91X is not set
++# CONFIG_DNET is not set
++# CONFIG_IBM_NEW_EMAC_ZMII is not set
++# CONFIG_IBM_NEW_EMAC_RGMII is not set
++# CONFIG_IBM_NEW_EMAC_TAH is not set
++# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
++# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
++# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
++# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
++# CONFIG_B44 is not set
++CONFIG_FTMAC100=y
++# CONFIG_NETDEV_1000 is not set
++# CONFIG_NETDEV_10000 is not set
++
++#
++# Wireless LAN
++#
++# CONFIG_WLAN_PRE80211 is not set
++# CONFIG_WLAN_80211 is not set
++# CONFIG_IWLWIFI_LEDS is not set
++
++#
++# Enable WiMAX (Networking options) to see the WiMAX drivers
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_ISDN is not set
++# CONFIG_PHONE is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++# CONFIG_INPUT_FF_MEMLESS is not set
++# CONFIG_INPUT_POLLDEV is not set
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TABLET is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++CONFIG_TOUCHSCREEN_CPE_TS=y
++CONFIG_TOUCHSCREEN_CPE_TS_DEJITTER=y
++# CONFIG_TOUCHSCREEN_FUJITSU is not set
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_INEXIO is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++# CONFIG_TOUCHSCREEN_PENMOUNT is not set
++# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
++# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
++# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_CONSOLE_TRANSLATIONS=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_VT_HW_CONSOLE_BINDING is not set
++CONFIG_DEVKMEM=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++# CONFIG_IPMI_HANDLER is not set
++# CONFIG_HW_RANDOM is not set
++# CONFIG_R3964 is not set
++# CONFIG_GPIO_FTGPIO010_OLD is not set
++# CONFIG_RAW_DRIVER is not set
++# CONFIG_TCG_TPM is not set
++# CONFIG_I2C is not set
++# CONFIG_SPI is not set
++# CONFIG_GPIOLIB is not set
++# CONFIG_W1 is not set
++# CONFIG_POWER_SUPPLY is not set
++# CONFIG_HWMON is not set
++# CONFIG_THERMAL is not set
++# CONFIG_THERMAL_HWMON is not set
++# CONFIG_WATCHDOG is not set
++CONFIG_SSB_POSSIBLE=y
++
++#
++# Sonics Silicon Backplane
++#
++# CONFIG_SSB is not set
++
++#
++# Multifunction device drivers
++#
++# CONFIG_MFD_CORE is not set
++# CONFIG_MFD_SM501 is not set
++# CONFIG_HTC_PASIC3 is not set
++# CONFIG_MFD_TMIO is not set
++# CONFIG_REGULATOR is not set
++
++#
++# Multimedia devices
++#
++
++#
++# Multimedia core support
++#
++# CONFIG_VIDEO_DEV is not set
++# CONFIG_DVB_CORE is not set
++# CONFIG_VIDEO_MEDIA is not set
++
++#
++# Multimedia drivers
++#
++# CONFIG_DAB is not set
++
++#
++# Graphics support
++#
++# CONFIG_VGASTATE is not set
++# CONFIG_VIDEO_OUTPUT_CONTROL is not set
++CONFIG_FB=y
++# CONFIG_FIRMWARE_EDID is not set
++# CONFIG_FB_DDC is not set
++# CONFIG_FB_BOOT_VESA_SUPPORT is not set
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
++# CONFIG_FB_SYS_FILLRECT is not set
++# CONFIG_FB_SYS_COPYAREA is not set
++# CONFIG_FB_SYS_IMAGEBLIT is not set
++# CONFIG_FB_FOREIGN_ENDIAN is not set
++# CONFIG_FB_SYS_FOPS is not set
++# CONFIG_FB_SVGALIB is not set
++# CONFIG_FB_MACMODES is not set
++# CONFIG_FB_BACKLIGHT is not set
++# CONFIG_FB_MODE_HELPERS is not set
++# CONFIG_FB_TILEBLITTING is not set
++
++#
++# Frame buffer hardware drivers
++#
++# CONFIG_FB_S1D13XXX is not set
++CONFIG_FB_FTLCDC100=y
++CONFIG_PANEL_AUA036QN01=y
++# CONFIG_PANEL_CH7013A is not set
++# CONFIG_PANEL_AUA070VW04 is not set
++# CONFIG_PANEL_LW500AC9601 is not set
++CONFIG_FFB_MODE_RGB=y
++# CONFIG_FFB_MODE_YUV422 is not set
++# CONFIG_FFB_MODE_YUV420 is not set
++# CONFIG_FFB_MODE_8BPP is not set
++CONFIG_FFB_MODE_16BPP=y
++# CONFIG_FFB_MODE_24BPP is not set
++# CONFIG_FB_VIRTUAL is not set
++# CONFIG_FB_METRONOME is not set
++# CONFIG_FB_MB862XX is not set
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Display device support
++#
++# CONFIG_DISPLAY_SUPPORT is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
++# CONFIG_FONTS is not set
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++CONFIG_LOGO=y
++CONFIG_LOGO_LINUX_MONO=y
++CONFIG_LOGO_LINUX_VGA16=y
++CONFIG_LOGO_LINUX_CLUT224=y
++CONFIG_SOUND=y
++CONFIG_SOUND_OSS_CORE=y
++CONFIG_SND=y
++CONFIG_SND_TIMER=y
++CONFIG_SND_PCM=y
++# CONFIG_SND_SEQUENCER is not set
++CONFIG_SND_OSSEMUL=y
++# CONFIG_SND_MIXER_OSS is not set
++CONFIG_SND_PCM_OSS=y
++CONFIG_SND_PCM_OSS_PLUGINS=y
++# CONFIG_SND_DYNAMIC_MINORS is not set
++# CONFIG_SND_SUPPORT_OLD_API is not set
++# CONFIG_SND_VERBOSE_PROCFS is not set
++# CONFIG_SND_VERBOSE_PRINTK is not set
++# CONFIG_SND_DEBUG is not set
++CONFIG_SND_DRIVERS=y
++# CONFIG_SND_DUMMY is not set
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA NDS32 devices
++#
++CONFIG_SND_FTSSP010=y
++CONFIG_SND_FTSSP010_AC97=y
++# CONFIG_SND_FTSSP010_I2S is not set
++# CONFIG_SND_SOC is not set
++# CONFIG_SOUND_PRIME is not set
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++# CONFIG_MMC is not set
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_ACCESSIBILITY is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++# 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_DS1286 is not set
++# CONFIG_RTC_DRV_DS1511 is not set
++# CONFIG_RTC_DRV_DS1553 is not set
++# CONFIG_RTC_DRV_DS1742 is not set
++# CONFIG_RTC_DRV_STK17TA8 is not set
++# CONFIG_RTC_DRV_M48T86 is not set
++# CONFIG_RTC_DRV_M48T35 is not set
++# CONFIG_RTC_DRV_M48T59 is not set
++# CONFIG_RTC_DRV_BQ4802 is not set
++# CONFIG_RTC_DRV_V3020 is not set
++
++#
++# on-CPU RTC drivers
++#
++CONFIG_RTC_DRV_FTRTC010=y
++# CONFIG_DMADEVICES is not set
++# CONFIG_UIO is not set
++# CONFIG_STAGING is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_EXT4_FS is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++CONFIG_FILE_LOCKING=y
++# CONFIG_XFS_FS is not set
++# CONFIG_OCFS2_FS is not set
++# CONFIG_BTRFS_FS is not set
++CONFIG_DNOTIFY=y
++CONFIG_INOTIFY=y
++CONFIG_INOTIFY_USER=y
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++CONFIG_FUSE_FS=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++# CONFIG_PROC_KCORE is not set
++CONFIG_PROC_SYSCTL=y
++# CONFIG_PROC_PAGE_MONITOR is not set
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_POSIX_ACL is not set
++# CONFIG_HUGETLB_PAGE is not set
++# CONFIG_CONFIGFS_FS is not set
++CONFIG_MISC_FILESYSTEMS=y
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
++# CONFIG_JFFS2_SUMMARY is not set
++# CONFIG_JFFS2_FS_XATTR is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++# CONFIG_JFFS2_LZO is not set
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_SQUASHFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_OMFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++CONFIG_NETWORK_FILESYSTEMS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFSD is not set
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_SUNRPC_REGISTER_V4 is not set
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++# CONFIG_PARTITION_ADVANCED is not set
++CONFIG_MSDOS_PARTITION=y
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII is not set
++CONFIG_NLS_ISO8859_1=y
++# CONFIG_NLS_ISO8859_2 is not set
++# CONFIG_NLS_ISO8859_3 is not set
++# CONFIG_NLS_ISO8859_4 is not set
++# CONFIG_NLS_ISO8859_5 is not set
++# CONFIG_NLS_ISO8859_6 is not set
++# CONFIG_NLS_ISO8859_7 is not set
++# CONFIG_NLS_ISO8859_9 is not set
++# CONFIG_NLS_ISO8859_13 is not set
++# CONFIG_NLS_ISO8859_14 is not set
++# CONFIG_NLS_ISO8859_15 is not set
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++# CONFIG_NLS_UTF8 is not set
++# CONFIG_DLM is not set
++
++#
++# Kernel hacking
++#
++CONFIG_TRACE_IRQFLAGS_SUPPORT=y
++# CONFIG_PRINTK_TIME is not set
++CONFIG_ENABLE_WARN_DEPRECATED=y
++CONFIG_ENABLE_MUST_CHECK=y
++CONFIG_FRAME_WARN=1024
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_UNUSED_SYMBOLS is not set
++CONFIG_DEBUG_FS=y
++# CONFIG_HEADERS_CHECK is not set
++CONFIG_DEBUG_KERNEL=y
++CONFIG_DEBUG_SHIRQ=y
++CONFIG_DETECT_SOFTLOCKUP=y
++# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
++CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
++CONFIG_SCHED_DEBUG=y
++CONFIG_SCHEDSTATS=y
++CONFIG_TIMER_STATS=y
++# CONFIG_DEBUG_OBJECTS is not set
++# CONFIG_SLUB_DEBUG_ON is not set
++# CONFIG_SLUB_STATS is not set
++CONFIG_DEBUG_RT_MUTEXES=y
++CONFIG_DEBUG_PI_LIST=y
++# CONFIG_RT_MUTEX_TESTER is not set
++CONFIG_DEBUG_SPINLOCK=y
++CONFIG_DEBUG_MUTEXES=y
++# CONFIG_DEBUG_LOCK_ALLOC is not set
++# CONFIG_PROVE_LOCKING is not set
++# CONFIG_LOCK_STAT is not set
++CONFIG_DEBUG_SPINLOCK_SLEEP=y
++# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
++CONFIG_STACKTRACE=y
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_VM is not set
++# CONFIG_DEBUG_WRITECOUNT is not set
++# CONFIG_DEBUG_MEMORY_INIT is not set
++CONFIG_DEBUG_LIST=y
++CONFIG_DEBUG_SG=y
++# CONFIG_DEBUG_NOTIFIERS is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_BOOT_PRINTK_DELAY is not set
++# CONFIG_RCU_TORTURE_TEST is not set
++# CONFIG_RCU_CPU_STALL_DETECTOR is not set
++# CONFIG_BACKTRACE_SELF_TEST is not set
++# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
++# CONFIG_FAULT_INJECTION is not set
++# CONFIG_LATENCYTOP is not set
++CONFIG_SYSCTL_SYSCALL_CHECK=y
++CONFIG_NOP_TRACER=y
++CONFIG_RING_BUFFER=y
++CONFIG_TRACING=y
++
++#
++# Tracers
++#
++# CONFIG_IRQSOFF_TRACER is not set
++# CONFIG_SCHED_TRACER is not set
++# CONFIG_CONTEXT_SWITCH_TRACER is not set
++# CONFIG_BOOT_TRACER is not set
++# CONFIG_TRACE_BRANCH_PROFILING is not set
++# CONFIG_FTRACE_STARTUP_TEST is not set
++# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
++# CONFIG_SAMPLES is not set
++CONFIG_HAVE_ARCH_KGDB=y
++# CONFIG_KGDB is not set
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_LL is not set
++# CONFIG_CCTL is not set
++# CONFIG_ELFCHK_DEFAULT_ENABLE is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++# CONFIG_SECURITYFS is not set
++# CONFIG_SECURITY_FILE_CAPABILITIES is not set
++CONFIG_CRYPTO=y
++
++#
++# Crypto core or helper
++#
++# CONFIG_CRYPTO_FIPS is not set
++# CONFIG_CRYPTO_MANAGER is not set
++# CONFIG_CRYPTO_MANAGER2 is not set
++# CONFIG_CRYPTO_GF128MUL is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_CRYPTD is not set
++# CONFIG_CRYPTO_AUTHENC is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Authenticated Encryption with Associated Data
++#
++# CONFIG_CRYPTO_CCM is not set
++# CONFIG_CRYPTO_GCM is not set
++# CONFIG_CRYPTO_SEQIV is not set
++
++#
++# Block modes
++#
++# CONFIG_CRYPTO_CBC is not set
++# CONFIG_CRYPTO_CTR is not set
++# CONFIG_CRYPTO_CTS is not set
++# CONFIG_CRYPTO_ECB is not set
++# CONFIG_CRYPTO_LRW is not set
++# CONFIG_CRYPTO_PCBC is not set
++# CONFIG_CRYPTO_XTS is not set
++
++#
++# Hash modes
++#
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_XCBC is not set
++
++#
++# Digest
++#
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_MD4 is not set
++# CONFIG_CRYPTO_MD5 is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_RMD128 is not set
++# CONFIG_CRYPTO_RMD160 is not set
++# CONFIG_CRYPTO_RMD256 is not set
++# CONFIG_CRYPTO_RMD320 is not set
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++# CONFIG_CRYPTO_WP512 is not set
++
++#
++# Ciphers
++#
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_CAMELLIA is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_DES is not set
++# CONFIG_CRYPTO_FCRYPT is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_SALSA20 is not set
++# CONFIG_CRYPTO_SEED is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++
++#
++# Compression
++#
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_LZO is not set
++
++#
++# Random Number Generation
++#
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
++
++#
++# Library routines
++#
++CONFIG_BITREVERSE=y
++CONFIG_GENERIC_FIND_LAST_BIT=y
++# CONFIG_CRC_CCITT is not set
++# CONFIG_CRC16 is not set
++# CONFIG_CRC_T10DIF is not set
++# CONFIG_CRC_ITU_T is not set
++CONFIG_CRC32=y
++# CONFIG_CRC7 is not set
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
++CONFIG_PLIST=y
++CONFIG_HAS_IOMEM=y
++CONFIG_HAS_DMA=y
+diff -Nur linux-3.4.110.orig/arch/nds32/configs/xc5_defconfig linux-3.4.110/arch/nds32/configs/xc5_defconfig
+--- linux-3.4.110.orig/arch/nds32/configs/xc5_defconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/configs/xc5_defconfig 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,117 @@
++CONFIG_EXPERIMENTAL=y
++CONFIG_CROSS_COMPILE="nds32le-linux-"
++# CONFIG_LOCALVERSION_AUTO is not set
++CONFIG_SYSVIPC=y
++CONFIG_BSD_PROCESS_ACCT=y
++CONFIG_BSD_PROCESS_ACCT_V3=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE="/home/users/greentime/os/ramdisk/disk-nds32le-linux-glibc-v3 /home/users/greentime/os/ramdisk/disk-nds32le-linux-glibc-v3/dev/initramfs.devnodes"
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SYSCTL_SYSCALL=y
++# CONFIG_HOTPLUG is not set
++# CONFIG_SIGNALFD is not set
++CONFIG_EMBEDDED=y
++# CONFIG_VM_EVENT_COUNTERS is not set
++CONFIG_PROFILING=y
++CONFIG_OPROFILE=y
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_BLK_DEV_BSG is not set
++CONFIG_PLATFORM_AHBDMA=y
++CONFIG_PLATFORM_APBDMA=y
++CONFIG_SYS_CLK=30000000
++CONFIG_UART_CLK=14745600
++CONFIG_SDRAM_SIZE=0x8000000
++CONFIG_HZ_100=y
++CONFIG_CMDLINE="root=/dev/ram0 rw mem=128M@0x0 initrd=0x1000000,8M console=ttyS0,38400n8 earlyprintk=uart8250-32bit,0x99600000 rootfstype=ext2 init=/bin/busybox init -s user_debug=-1"
++# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
++CONFIG_NET=y
++CONFIG_PACKET=y
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
++# CONFIG_INET_XFRM_MODE_TUNNEL is not set
++# CONFIG_INET_XFRM_MODE_BEET is not set
++# CONFIG_INET_LRO is not set
++# CONFIG_INET_DIAG is not set
++# CONFIG_IPV6 is not set
++CONFIG_BRIDGE=y
++CONFIG_MTD=y
++CONFIG_MTD_CMDLINE_PARTS=y
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++CONFIG_MTD_CFI=y
++CONFIG_MTD_CFI_INTELEXT=y
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_COMPAT=y
++CONFIG_MTD_PHYSMAP_START=0x80400000
++CONFIG_MTD_PHYSMAP_LEN=0x2000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++CONFIG_BLK_DEV_LOOP=y
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_SIZE=8192
++CONFIG_NETDEVICES=y
++CONFIG_TUN=y
++CONFIG_FTMAC100=y
++# CONFIG_INPUT_MOUSEDEV is not set
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_SERIO is not set
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=3
++CONFIG_SERIAL_8250_RUNTIME_UARTS=3
++# CONFIG_HW_RANDOM is not set
++# CONFIG_HWMON is not set
++CONFIG_FB=y
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_LOGO=y
++CONFIG_SOUND=y
++CONFIG_SND=y
++CONFIG_SND_PCM_OSS=y
++# CONFIG_SND_SUPPORT_OLD_API is not set
++# CONFIG_SND_VERBOSE_PROCFS is not set
++# CONFIG_HID_SUPPORT is not set
++# CONFIG_USB_SUPPORT is not set
++CONFIG_MMC=y
++CONFIG_MMC_FTSDC010=y
++# CONFIG_MEMSTICK is not set
++# CONFIG_NEW_LEDS is not set
++# CONFIG_ACCESSIBILITY is not set
++CONFIG_RTC_LIB=y
++CONFIG_RTC_CLASS=y
++# CONFIG_RTC_HCTOSYS is not set
++CONFIG_EXT2_FS=y
++CONFIG_FUSE_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++# CONFIG_PROC_PAGE_MONITOR is not set
++CONFIG_TMPFS=y
++CONFIG_JFFS2_FS=y
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++CONFIG_NLS_CODEPAGE_437=y
++CONFIG_NLS_ISO8859_1=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_DEBUG_FS=y
++CONFIG_DEBUG_SHIRQ=y
++CONFIG_SCHEDSTATS=y
++CONFIG_TIMER_STATS=y
++CONFIG_DEBUG_RT_MUTEXES=y
++CONFIG_DEBUG_SPINLOCK=y
++CONFIG_DEBUG_MUTEXES=y
++CONFIG_DEBUG_INFO=y
++CONFIG_DEBUG_LIST=y
++CONFIG_DEBUG_SG=y
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_CRYPTO_ANSI_CPRNG is not set
++# CONFIG_CRYPTO_HW is not set
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/amic.h linux-3.4.110/arch/nds32/include/asm/amic.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/amic.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/amic.h 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,60 @@
++/*
++ * linux/arch/nds32/include/asm/amic.h
++ *
++ * Andes Multi-core Interrupt Controller Device Driver Interface
++ *
++ * Copyright (C) 2010 Andes Technology Corporation
++ *
++ * 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
++ *
++ * ChangeLog
++ *
++ * Shawn Lin 09/02/2010 Created for Andes AG102 platform code.
++ */
++
++#ifndef __NDS32_AMIC_HEADER__
++#define __NDS32_AMIC_HEADER__
++
++#define IRQ_BASE 0x0
++#define IRQ_TOTAL 0x20
++#define DEFAULT_MODE 0x000ecc00
++#define DEFAULT_LEVEL 0xffffffff
++#define AMIC_BASE AMIC_VA_BASE
++#define CONFIG 0x00
++#define CPUDC 0x04
++#define CPUID0 0x08
++#define CPUID1 0x0c
++#define INTTRG 0x20
++#define INTLVL 0x24
++#define INTSRC 0x28
++#define IPITRG 0x40
++#define IPISTA 0x44
++#define IPIPTR 0x48
++#define IPIGST 0x4c
++#define IPIGPT 0x50
++#define INTEN 0x80
++#define INTSTA 0x84
++#define HW0STA 0x88
++#define HW1STA 0x8c
++#define HW2STA 0x90
++#define HW3STA 0x94
++#define HW4STA 0x98
++#define HW5STA 0x9c
++#define PRITY0 0xa0
++#define PRITY1 0xa4
++#define PRITY2 0xa8
++#define PRITY3 0xac
++
++#endif /* __NDS32_AMIC_HEADER__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/asm-offsets.h linux-3.4.110/arch/nds32/include/asm/asm-offsets.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/asm-offsets.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/asm-offsets.h 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1 @@
++#include <generated/asm-offsets.h>
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/assembler.h linux-3.4.110/arch/nds32/include/asm/assembler.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/assembler.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/assembler.h 2016-04-07 10:20:50.882078703 +0200
+@@ -0,0 +1,141 @@
++/*
++ * linux/arch/nds32/include/asm/assembler.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_ASSEMBLER_H__
++#define __NDS32_ASSEMBLER_H__
++
++/*
++ * Stack format
++ */
++
++#define S_PAD 0xac /* Padding for stack pointer 8-byte alignment. */
++#define S_FUCOP_CTL 0xa8
++#define S_LP 0xa4
++#define S_GP 0xa0
++#define S_FP 0x9c
++#define S_R25 0x98
++#define S_R24 0x94
++#define S_R23 0x90
++#define S_R22 0x8c
++#define S_R21 0x88
++#define S_R20 0x84
++#define S_R19 0x80
++#define S_R18 0x7c
++#define S_R17 0x78
++#define S_R16 0x74
++#define S_R15 0x70
++#define S_R14 0x6c
++#define S_R13 0x68
++#define S_R12 0x64
++#define S_R11 0x60
++#define S_R10 0x5c
++#define S_R9 0x58
++#define S_R8 0x54
++#define S_R7 0x50
++#define S_R6 0x4c
++#define S_R5 0x48
++#define S_R4 0x44
++#define S_R3 0x40
++#define S_R2 0x3c
++#define S_R1 0x38
++#define S_R0 0x34
++#define S_D1LO 0x30
++#define S_D1HI 0x2c
++#define S_D0LO 0x28
++#define S_D0HI 0x24
++#define S_PP1 0x20
++#define S_PP0 0x1c
++#define S_PIPC 0x18
++#define S_PIPSW 0x14
++#define S_ORIG_R0 0x10
++#define S_SP 0xc
++#define S_IPC 0x8
++#define S_IPSW 0x4
++#define S_IR0 0x0
++
++#if !defined(CONFIG_ABI1)
++#define S_OFF 0
++#else
++#define S_OFF 24
++#endif
++
++#ifdef __ASSEMBLY__
++.macro get_thread_info, rd
++ srli \rd, $sp, #13
++ slli \rd, \rd, #13
++.endm
++
++.macro gie_disable
++ setgie.d
++#ifdef CONFIG_CPU_N1213_43U1HA0
++ isb
++#else
++ dsb
++#endif
++.endm
++
++.macro gie_enable
++ setgie.e
++#ifdef CONFIG_CPU_N1213_43U1HA0
++ isb
++#else
++ dsb
++#endif
++.endm
++
++.macro gie_save oldpsw
++ mfsr \oldpsw, $ir0
++ setgie.d
++#ifdef CONFIG_CPU_N1213_43U1HA0
++ isb
++#else
++ dsb
++#endif
++.endm
++
++.macro gie_restore oldpsw
++ andi \oldpsw, \oldpsw, #0x1
++ beqz \oldpsw, 7001f
++ setgie.e
++#ifdef CONFIG_CPU_N1213_43U1HA0
++ isb
++#else
++ dsb
++#endif
++7001:
++.endm
++
++
++#define USER(insn, reg, addr, opr) \
++9999: insn reg, addr, opr; \
++ .section __ex_table,"a"; \
++ .align 3; \
++ .long 9999b, 9001f; \
++ .previous
++
++#else /* __ASSEMBLY__ */
++
++__asm__ (".macro gie_disable\n\t"
++ "setgie.d\n\t"
++#ifdef CONFIG_CPU_N1213_43U1HA0
++ "isb\n\t"
++#else
++ "dsb\n\t"
++#endif
++ ".endm\n\t"
++ );
++
++__asm__ (".macro gie_enable\n\t"
++ "setgie.e\n\t"
++#ifdef CONFIG_CPU_N1213_43U1HA0
++ "isb\n\t"
++#else
++ "dsb\n\t"
++#endif
++ ".endm\n\t"
++ );
++
++#endif /* !__ASSEMBLY__ */
++#endif /* __NDS32_ASSEMBLER_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/atomic.h linux-3.4.110/arch/nds32/include/asm/atomic.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/atomic.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/atomic.h 2016-04-07 10:20:50.890079013 +0200
+@@ -0,0 +1,267 @@
++/*
++ * linux/arch/nds32/include/asm/atomic.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_ATOMIC_H__
++#define __NDS32_ATOMIC_H__
++
++#include <linux/types.h>
++#include <asm/barrier.h>
++#include <asm/cmpxchg.h>
++
++#if defined(CONFIG_SMP) || !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
++
++#define ATOMIC_INIT(i) { (i) }
++#define atomic_set(v,i) (((v)->counter) = (i))
++#define atomic_read(v) (*(volatile int *)&(v)->counter)
++
++static inline void atomic_add(int i, atomic_t *v)
++{
++ int temp;
++ __asm__ __volatile__(
++ "movi\t$r15, #0\n"
++ "1:\n"
++ "\tllw\t%0, [%1+$r15]\n"
++ "\tadd\t%0, %0, %2\n"
++ "\tscw\t%0, [%1+$r15]\n"
++ "\tbeqz\t%0, 1b\n"
++ : "=&r" (temp) : "r" (&v->counter), "r" (i));
++}
++
++static inline void atomic_sub(int i, atomic_t *v)
++{
++ int temp;
++ __asm__ __volatile__(
++ "movi\t$r15, #0\n"
++ "1:\n"
++ "\tllw\t%0, [%1+$r15]\n"
++ "\tsub\t%0, %0, %2\n"
++ "\tscw\t%0, [%1+$r15]\n"
++ "\tbeqz\t%0, 1b\n"
++ : "=&r" (temp) : "r" (&v->counter), "r" (i));
++}
++
++#define atomic_inc(v) atomic_add(1, v)
++#define atomic_dec(v) atomic_sub(1, v)
++
++static inline int atomic_inc_return(atomic_t *v)
++{
++ int temp1, temp2;
++ __asm__ __volatile__(
++ "movi\t$r15, #0\n"
++ "1:\n"
++ "\tllw\t%1, [%2+$r15]\n"
++ "\taddi\t%1, %1, #1\n"
++ "\tori\t%0, %1, #0\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (temp2), "=&r" (temp1)
++ : "r" (&v->counter));
++ return temp2;
++}
++
++static inline int atomic_dec_return(atomic_t *v)
++{
++ int temp1, temp2;
++ __asm__ __volatile__(
++ "movi\t$r15, #0\n"
++ "1:\n"
++ "\tllw\t%1, [%2+$r15]\n"
++ "\taddi\t%1, %1, #-1\n"
++ "\tori\t%0, %1, #0\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (temp2), "=&r" (temp1)
++ : "r" (&v->counter));
++ return temp2;
++}
++
++static inline int atomic_add_return(int i, atomic_t *v)
++{
++ int temp1, temp2;
++
++ smp_mb();
++
++ __asm__ __volatile__(
++ "movi\t$r15, #0\n"
++ "1:\n"
++ "\tllw\t%1, [%2+$r15]\n"
++ "\tadd\t%1, %1, %3\n"
++ "\tori\t%0, %1, #0\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (temp2), "=&r" (temp1)
++ : "r" (&v->counter), "r" (i));
++
++ smp_mb();
++
++ return temp2;
++}
++
++static inline int atomic_sub_return(int i, atomic_t *v)
++{
++ int temp1, temp2;
++
++ smp_mb();
++
++ __asm__ __volatile__(
++ "movi\t$r15, #0\n"
++ "1:\n"
++ "\tllw\t%1, [%2+$r15]\n"
++ "\tsub\t%1, %1, %3\n"
++ "\tori\t%0, %1, #0\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (temp2), "=&r" (temp1)
++ : "r" (&v->counter), "r" (i));
++
++ smp_mb();
++
++ return temp2;
++}
++
++/*
++ * atomic_dec_if_positive - conditionally subtract one from atomic variable
++ * @v: pointer of type atomic_t
++ *
++ * Atomically test @v and subtract one if @v is greater or equal than one.
++ * The function returns the old value of @v minus one.
++ */
++static inline int atomic_dec_if_positive(atomic_t * v)
++{
++ int temp1, temp2, temp3;
++ __asm__ __volatile__(
++ "movi\t$r15, #0\n"
++ "1:\n"
++ "\tllw\t%2, [%3+$r15]\n"
++ "\taddi\t%0, %2, #-1\n"
++ "\tslts\t%1, $r15, %2\n"
++ "\tsub\t%2, %2, %1\n"
++ "\tscw\t%2, [%3+$r15]\n"
++ "\tbeqz\t%2, 1b\n"
++ : "=&r" (temp3), "=&r" (temp2), "=&r" (temp1)
++ : "r" (&v->counter));
++ return temp3;
++}
++
++
++#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0)
++#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0)
++#define atomic_sub_and_test(i,v) (atomic_sub_return((i),(v)) == 0)
++#define atomic_add_negative(i,v) (atomic_add_return((i),(v)) < 0)
++
++
++static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
++{
++ int temp1, temp2, temp3;
++
++ smp_mb();
++
++ __asm__ __volatile__(
++ "movi\t$r15, #0\n"
++ "1:\n"
++ "\tllw\t%0, [%3+$r15]\n"
++ "\tsub\t%2, %0, %5\n"
++ "\tcmovz\t%1, %4, %2\n"
++ "\tcmovn\t%1, %0, %2\n"
++ "\tscw\t%1, [%3+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (temp3), "=&r" (temp2), "=&r" (temp1)
++ : "r" (&v->counter), "r" (new), "r" (old));
++
++ smp_mb();
++
++ return temp3;
++}
++
++static inline int atomic_xchg(atomic_t *v, int new)
++{
++ int temp1, temp2;
++ __asm__ __volatile__(
++ "movi\t$r15, #0\n"
++ "1:\n"
++ "\tllw\t%0, [%2+$r15]\n"
++ "\tori\t%1, %3, #0\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (temp2), "=&r" (temp1)
++ : "r" (&v->counter), "r" (new));
++ return temp2;
++}
++
++static inline int __atomic_add_unless(atomic_t *v, int a, int u)
++{
++ int c, old;
++
++ c = atomic_read(v);
++ while (c != u && (old = atomic_cmpxchg((v), c, c + a)) != c)
++ c = old;
++ return c;
++}
++
++static inline int atomic_inc_not_zero(atomic_t *v)
++{
++ int temp1, temp2;
++ __asm__ __volatile__(
++ "movi\t$r15, #0\n"
++ "1:\n"
++ "\tllw\t%1, [%2+$r15]\n"
++ "\tslt\t%0, $r15, %1\n"
++ "\tadd\t%1, %1, %0\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (temp2), "=&r" (temp1)
++ : "r" (&v->counter));
++ return temp2;
++}
++
++#define smp_mb__before_atomic_dec() barrier()
++#define smp_mb__after_atomic_dec() barrier()
++#define smp_mb__before_atomic_inc() barrier()
++#define smp_mb__after_atomic_inc() barrier()
++
++//#include <asm-generic/atomic-long.h>
++#else /* CONFIG_SMP*/
++
++
++
++#define ATOMIC_INIT(i) { (i) }
++
++#ifdef __KERNEL__
++
++#include <asm-generic/atomic.h>
++
++static inline int atomic_dec_if_positive(atomic_t * v)
++{
++ unsigned long flags;
++ int result;
++
++ local_irq_save(flags);
++ result = v->counter;
++ result -= 1;
++ if (result >= 0)
++ v->counter = result;
++ local_irq_restore(flags);
++ return result;
++}
++
++/* Atomic operations are already serializing on ARM */
++#define smp_mb__before_atomic_dec() barrier()
++#define smp_mb__after_atomic_dec() barrier()
++#define smp_mb__before_atomic_inc() barrier()
++#define smp_mb__after_atomic_inc() barrier()
++
++#endif
++
++#endif /* CONFIG_SMP */
++
++#ifndef CONFIG_GENERIC_ATOMIC64
++typedef struct {
++ u64 __aligned(8) counter;
++} atomic64_t;
++#define ATOMIC64_INIT(i) { (i) }
++static inline u64 atomic64_add_return(u64 i, atomic64_t *v){ return 0; }
++#endif /* CONFIG_GENERIC_ATOMIC64 */
++
++#endif /* __NDS32_ATOMIC_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/audio.h linux-3.4.110/arch/nds32/include/asm/audio.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/audio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/audio.h 2016-04-07 10:20:50.890079013 +0200
+@@ -0,0 +1,65 @@
++/*
++ * linux/arch/nds32/include/asm/audio.h
++ * Copyright (C) 2009 Andes Technology Corporation
++ */
++
++#ifndef __ASM_NDS32_AUDIO_H
++#define __ASM_NDS32_AUDIO_H
++
++#ifndef __ASSEMBLY__
++#include <linux/preempt.h>
++#include <asm/ptrace.h>
++
++extern void save_audio(struct task_struct *tsk);
++extern void audioload(struct audio_struct *audioregs);
++extern void save_audio(struct task_struct *__tsk);
++extern void do_audio_context_switch(unsigned long error_code, struct pt_regs *regs);
++
++#ifdef CONFIG_AUDIO
++
++#define test_tsk_audio(regs) (regs->NDS32_FUCOP_CTL & FUCOP_CTL_mskAUEN)
++
++struct task_struct;
++
++static inline void enable_audio(void)
++{
++ SET_FUCOP_CTL(GET_FUCOP_CTL() | FUCOP_CTL_mskAUEN);
++}
++
++static inline void disable_audio(void)
++{
++ SET_FUCOP_CTL(GET_FUCOP_CTL() & ~FUCOP_CTL_mskAUEN);
++}
++
++static inline void release_audio(struct pt_regs *regs)
++{
++ regs->NDS32_FUCOP_CTL &= ~FUCOP_CTL_mskAUEN;
++ regs->NDS32_ipsw &= ~PSW_mskAEN;
++}
++
++static inline void grab_audio(struct pt_regs *regs)
++{
++ regs->NDS32_FUCOP_CTL |= FUCOP_CTL_mskAUEN;
++ regs->NDS32_ipsw |= PSW_mskAEN;
++}
++#ifdef CONFIG_UNLAZY_AUDIO
++static inline void unlazy_audio(struct task_struct *tsk)
++{
++ preempt_disable();
++ if (test_tsk_audio(task_pt_regs(tsk)))
++ save_audio(tsk);
++ preempt_enable();
++}
++#endif
++static inline void clear_audio(struct pt_regs *regs)
++{
++ preempt_disable();
++ if (test_tsk_audio(regs)) {
++ release_audio(regs);
++ }
++ preempt_enable();
++}
++#endif /* CONFIG_AUDIO */
++#endif /* __ASSEMBLY__ */
++
++#endif /* __ASM_NDS32_AUDIO_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/auxvec.h linux-3.4.110/arch/nds32/include/asm/auxvec.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/auxvec.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/auxvec.h 2016-04-07 10:20:50.890079013 +0200
+@@ -0,0 +1,9 @@
++/*
++ * linux/arch/nds32/include/asm/auxvec.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_AUXVEC_H__
++#define __NDS32_AUXVEC_H__
++
++#endif /*__NDS32_AUXVEC_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/barrier.h linux-3.4.110/arch/nds32/include/asm/barrier.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/barrier.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/barrier.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,85 @@
++/* ============================================================================
++ *
++ * linux/arch/nds32/include/asm/system.h
++ *
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is for NDS32 architecture.
++ *
++ * Revision History:
++ *
++ * Nov.26.2007 Initial ported by Tom, Shawn, and Steven,
++ * patched for KGDB and refined code by Harry.
++ *
++ * Note:
++ *
++ * ============================================================================
++ */
++#ifndef __ASM_NDS32_BARRIER_H
++#define __ASM_NDS32_BARRIER_H
++
++#ifdef __KERNEL__
++
++/*
++ * This is used to ensure the compiler did actually allocate the register we
++ * asked it for some inline assembly sequences. Apparently we can't trust
++ * the compiler from one version to another so a bit of paranoia won't hurt.
++ * This string is meant to be concatenated with the inline asm string and
++ * will cause compilation to stop on mismatch.
++ * (for details, see gcc PR 15089)
++ */
++#define __asmeq(x, y) ".ifnc " x "," y " ; .err ; .endif\n\t"
++
++#ifndef __ASSEMBLY__
++
++#include <linux/linkage.h>
++#include <linux/irqflags.h>
++
++struct thread_info;
++struct task_struct;
++
++struct pt_regs;
++
++void die(const char *msg, struct pt_regs *regs, int err)
++ __attribute__((noreturn));
++
++void die_if_kernel(const char *str, struct pt_regs *regs, int err);
++
++#include <asm/proc-fns.h>
++
++#define UDBG_UNDEFINED (1 << 0)
++#define UDBG_SYSCALL (1 << 1)
++#define UDBG_BADABORT (1 << 2)
++#define UDBG_SEGV (1 << 3)
++#define UDBG_BUS (1 << 4)
++
++extern unsigned int user_debug;
++
++#define mb() __asm__ __volatile__ ("" : : : "memory")
++#define rmb() mb()
++#define wmb() mb()
++#define read_barrier_depends() do { } while(0)
++#define set_mb(var, value) do { var = value; mb(); } while (0)
++#define set_wmb(var, value) do { var = value; wmb(); } while (0)
++
++#ifdef CONFIG_SMP
++#define smp_mb() mb()
++#define smp_rmb() rmb()
++#define smp_wmb() wmb()
++#define smp_read_barrier_depends() read_barrier_depends()
++#else
++#define smp_mb() barrier()
++#define smp_rmb() barrier()
++#define smp_wmb() barrier()
++#define smp_read_barrier_depends() do { } while(0)
++#endif
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* __KERNEL__ */
++
++#endif //__ASM_NDS32_SYSTEM_H
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/bitfield.h linux-3.4.110/arch/nds32/include/asm/bitfield.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/bitfield.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/bitfield.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,895 @@
++/*
++ * linux/arch/nds32/include/asm/bitfield.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_BITFIELD_H__
++#define __NDS32_BITFIELD_H__
++/******************************************************************************
++ * cr0: CPU_VER (CPU Version Register)
++ *****************************************************************************/
++#define CPU_VER_offCFGID 0 /* Minor configuration */
++#define CPU_VER_offREV 16 /* Revision of the CPU version */
++#define CPU_VER_offCPUID 24 /* Major CPU versions */
++
++#define CPU_VER_mskCFGID ( 0xFFFF << CPU_VER_offCFGID )
++#define CPU_VER_mskREV ( 0xFF << CPU_VER_offREV )
++#define CPU_VER_mskCPUID ( 0xFF << CPU_VER_offCPUID )
++
++/******************************************************************************
++ * cr1: ICM_CFG (Instruction Cache/Memory Configuration Register)
++ *****************************************************************************/
++#define ICM_CFG_offISET 0 /* I-cache sets (# of cache lines) per way */
++#define ICM_CFG_offIWAY 3 /* I-cache ways */
++#define ICM_CFG_offISZ 6 /* I-cache line size */
++#define ICM_CFG_offILCK 9 /* I-cache locking support */
++#define ICM_CFG_offILMB 10 /* On-chip ILM banks */
++#define ICM_CFG_offBSAV 13 /* ILM base register alignment version */
++/* bit 15:31 reserved */
++
++#define ICM_CFG_mskISET ( 0x7 << ICM_CFG_offISET )
++#define ICM_CFG_mskIWAY ( 0x7 << ICM_CFG_offIWAY )
++#define ICM_CFG_mskISZ ( 0x7 << ICM_CFG_offISZ )
++#define ICM_CFG_mskILCK ( 0x1 << ICM_CFG_offILCK )
++#define ICM_CFG_mskILMB ( 0x7 << ICM_CFG_offILMB )
++#define ICM_CFG_mskBSAV ( 0x3 << ICM_CFG_offBSAV )
++
++/******************************************************************************
++ * cr2: DCM_CFG (Data Cache/Memory Configuration Register)
++ *****************************************************************************/
++#define DCM_CFG_offDSET 0 /* D-cache sets (# of cache lines) per way */
++#define DCM_CFG_offDWAY 3 /* D-cache ways */
++#define DCM_CFG_offDSZ 6 /* D-cache line size */
++#define DCM_CFG_offDLCK 9 /* D-cache locking support */
++#define DCM_CFG_offDLMB 10 /* On-chip DLM banks */
++#define DCM_CFG_offBSAV 13 /* DLM base register alignment version */
++/* bit 15:31 reserved */
++
++#define DCM_CFG_mskDSET ( 0x7 << DCM_CFG_offDSET )
++#define DCM_CFG_mskDWAY ( 0x7 << DCM_CFG_offDWAY )
++#define DCM_CFG_mskDSZ ( 0x7 << DCM_CFG_offDSZ )
++#define DCM_CFG_mskDLCK ( 0x1 << DCM_CFG_offDLCK )
++#define DCM_CFG_mskDLMB ( 0x7 << DCM_CFG_offDLMB )
++#define DCM_CFG_mskBSAV ( 0x3 << DCM_CFG_offBSAV )
++
++/******************************************************************************
++ * cr3: MMU_CFG (MMU Configuration Register)
++ *****************************************************************************/
++#define MMU_CFG_offMMPS 0 /* Memory management protection scheme */
++#define MMU_CFG_offMMPV 2 /* Memory management protection version number */
++#define MMU_CFG_offFATB 7 /* Fully-associative or non-fully-associative TLB */
++
++#ifdef CONFIG_FULL_ASSOC
++#define MMU_CFG_offFATBSZ 8 /* TLB entries while using full-associative TLB */
++#else
++#define MMU_CFG_offTBW 8 /* TLB ways(non-associative) TBS */
++#define MMU_CFG_offTBS 11 /* TLB sets per way(non-associative) TBS */
++/* bit 14:14 reserved */
++#endif
++
++#define MMU_CFG_offEP8MIN4 15 /* 8KB page supported while minimum page is 4KB */
++#define MMU_CFG_offfEPSZ 16 /* Extra page size supported */
++#define MMU_CFG_offTLBLCK 24 /* TLB locking support */
++#define MMU_CFG_offHPTWK 25 /* Hardware Page Table Walker implemented */
++#define MMU_CFG_offDE 26 /* Default endian */
++#define MMU_CFG_offNTPT 27 /* Partitions for non-translated attributes */
++#define MMU_CFG_offIVTB 28 /* Invisible TLB */
++#define MMU_CFG_offVLPT 29 /* VLPT for fast TLB fill handling implemented */
++#define MMU_CFG_offNTME 30 /* Non-translated VA to PA mapping */
++/* bit 31 reserved */
++
++#define MMU_CFG_mskMMPS ( 0x3 << MMU_CFG_offMMPS )
++#define MMU_CFG_mskMMPV ( 0x1F << MMU_CFG_offMMPV )
++#define MMU_CFG_mskFATB ( 0x1 << MMU_CFG_offFATB )
++#ifdef CONFIG_FULL_ASSOC
++#define MMU_CFG_mskFATBSZ ( 0x7f << MMU_CFG_offFATBSZ )
++#else
++#define MMU_CFG_mskTBW ( 0x7 << MMU_CFG_offTBW )
++#define MMU_CFG_mskTBS ( 0x7 << MMU_CFG_offTBS )
++#endif
++#define MMU_CFG_mskEP8MIN4 ( 0x1 << MMU_CFG_offEP8MIN4 )
++#define MMU_CFG_mskfEPSZ ( 0xFF << MMU_CFG_offfEPSZ )
++#define MMU_CFG_mskTLBLCK ( 0x1 << MMU_CFG_offTLBLCK )
++#define MMU_CFG_mskHPTWK ( 0x1 << MMU_CFG_offHPTWK )
++#define MMU_CFG_mskDE ( 0x1 << MMU_CFG_offDE )
++#define MMU_CFG_mskNTPT ( 0x1 << MMU_CFG_offNTPT )
++#define MMU_CFG_mskIVTB ( 0x1 << MMU_CFG_offIVTB )
++#define MMU_CFG_mskVLPT ( 0x1 << MMU_CFG_offVLPT )
++#define MMU_CFG_mskNTME ( 0x1 << MMU_CFG_offNTME )
++
++/******************************************************************************
++ * cr4: MSC_CFG (Misc Configuration Register)
++ *****************************************************************************/
++#define MSC_CFG_offEDM 0
++#define MSC_CFG_offLMDMA 1
++#define MSC_CFG_offPFM 2
++#define MSC_CFG_offHSMP 3
++#define MSC_CFG_offTRACE 4
++#define MSC_CFG_offDIV 5
++#define MSC_CFG_offMAC 6
++#define MSC_CFG_offAUDIO 7
++#define MSC_CFG_offL2C 9
++#define MSC_CFG_offRDREG 10
++#define MSC_CFG_offADR24 11
++#define MSC_CFG_offINTLC 12
++#define MSC_CFG_offBASEV 13
++#define MSC_CFG_offNOD 16
++/* bit 13:31 reserved */
++
++#define MSC_CFG_mskEDM ( 0x1 << MSC_CFG_offEDM )
++#define MSC_CFG_mskLMDMA ( 0x1 << MSC_CFG_offLMDMA )
++#define MSC_CFG_mskPFM ( 0x1 << MSC_CFG_offPFM )
++#define MSC_CFG_mskHSMP ( 0x1 << MSC_CFG_offHSMP )
++#define MSC_CFG_mskTRACE ( 0x1 << MSC_CFG_offTRACE )
++#define MSC_CFG_mskDIV ( 0x1 << MSC_CFG_offDIV )
++#define MSC_CFG_mskMAC ( 0x1 << MSC_CFG_offMAC )
++#define MSC_CFG_mskAUDIO ( 0x3 << MSC_CFG_offAUDIO )
++#define MSC_CFG_mskL2C ( 0x1 << MSC_CFG_offL2C )
++#define MSC_CFG_mskRDREG ( 0x1 << MSC_CFG_offRDREG )
++#define MSC_CFG_mskADR24 ( 0x1 << MSC_CFG_offADR24 )
++#define MSC_CFG_mskINTLC ( 0x1 << MSC_CFG_offINTLC )
++#define MSC_CFG_mskBASEV ( 0x7 << MSC_CFG_offBASEV )
++#define MSC_CFG_mskNOD ( 0x1 << MSC_CFG_offNOD )
++
++/******************************************************************************
++ * cr5: CORE_CFG (Core Identification Register)
++ *****************************************************************************/
++#define CORE_ID_offCOREID 0
++/* bit 4:31 reserved */
++
++#define CORE_ID_mskCOREID ( 0xF << CORE_ID_offCOREID )
++
++/******************************************************************************
++ * cr6: FUCOP_EXIST (FPU and Coprocessor Existence Configuration Register)
++ *****************************************************************************/
++#define FUCOP_EXIST_offCP0EX 0
++#define FUCOP_EXIST_offCP1EX 1
++#define FUCOP_EXIST_offCP2EX 2
++#define FUCOP_EXIST_offCP3EX 3
++#define FUCOP_EXIST_offCP0ISFPU 31
++
++#define FUCOP_EXIST_mskCP0EX ( 0x1 << FUCOP_EXIST_offCP0EX )
++#define FUCOP_EXIST_mskCP1EX ( 0x1 << FUCOP_EXIST_offCP1EX )
++#define FUCOP_EXIST_mskCP2EX ( 0x1 << FUCOP_EXIST_offCP2EX )
++#define FUCOP_EXIST_mskCP3EX ( 0x1 << FUCOP_EXIST_offCP3EX )
++#define FUCOP_EXIST_mskCP0ISFPU ( 0x1 << FUCOP_EXIST_offCP0ISFPU )
++
++/******************************************************************************
++ * ir0: PSW (Processor Status Word Register)
++ * ir1: IPSW (Interruption PSW Register)
++ * ir2: P_IPSW (Previous IPSW Register)
++ *****************************************************************************/
++#define PSW_offGIE 0 /* Global Interrupt Enable */
++#define PSW_offINTL 1 /* Interruption Stack Level */
++#define PSW_offPOM 3 /* Processor Operation Mode, User/Superuser */
++#define PSW_offBE 5 /* Endianness for data memory access, 1:MSB, 0:LSB */
++#define PSW_offIT 6 /* Enable instruction address translation */
++#define PSW_offDT 7 /* Enable data address translation */
++#define PSW_offIME 8 /* Instruction Machine Error flag */
++#define PSW_offDME 9 /* Data Machine Error flag */
++#define PSW_offDEX 10 /* Debug Exception */
++#define PSW_offHSS 11 /* Hardware Single Stepping */
++#define PSW_offDRBE 12 /* Device Register Endian Mode */
++#define PSW_offAEN 13 /* Audio ISA special feature */
++#define PSW_offWBNA 14 /* Write Back Non-Allocate */
++#define PSW_offIFCON 15 /* IFC On */
++#define PSW_offCPL 16 /* Current Priority Level */
++/* bit 19:31 reserved */
++
++#define PSW_mskGIE ( 0x1 << PSW_offGIE )
++#define PSW_mskINTL ( 0x3 << PSW_offINTL )
++#define PSW_mskPOM ( 0x3 << PSW_offPOM )
++#define PSW_mskBE ( 0x1 << PSW_offBE )
++#define PSW_mskIT ( 0x1 << PSW_offIT )
++#define PSW_mskDT ( 0x1 << PSW_offDT )
++#define PSW_mskIME ( 0x1 << PSW_offIME )
++#define PSW_mskDME ( 0x1 << PSW_offDME )
++#define PSW_mskDEX ( 0x1 << PSW_offDEX )
++#define PSW_mskHSS ( 0x1 << PSW_offHSS )
++#define PSW_mskDRBE ( 0x1 << PSW_offDRBE )
++#define PSW_mskAEN ( 0x1 << PSW_offAEN )
++#define PSW_mskWBNA ( 0x1 << PSW_offWBNA )
++#define PSW_mskIFCON ( 0x1 << PSW_offIFCON )
++#define PSW_mskCPL ( 0x7 << PSW_offCPL )
++
++#define PSW_SYSTEM ( 1 << PSW_offPOM )
++#define PSW_INTL_1 ( 1 << PSW_offINTL )
++#define PSW_CPL_NO ( 0 << PSW_offCPL )
++#define PSW_CPL_ANY ( 7 << PSW_offCPL )
++/******************************************************************************
++ * ir3: IVB (Interruption Vector Base Register)
++ *****************************************************************************/
++/* bit 0:12 reserved */
++#define IVB_offNIVIC 1 /* Number of input for IVIC Controller */
++#define IVB_offIVIC_VER 11 /* IVIC Version */
++#define IVB_offEVIC 13 /* External Vector Interrupt Controller mode */
++#define IVB_offESZ 14 /* Size of each vector entry */
++#define IVB_offIVBASE 16 /* BasePA of interrupt vector table */
++
++#define IVB_mskNIVIC ( 0x7 << IVB_offNIVIC )
++#define IVB_mskIVIC_VER ( 0x3 << IVB_offIVIC_VER )
++#define IVB_mskEVIC ( 0x1 << IVB_offEVIC )
++#define IVB_mskESZ ( 0x3 << IVB_offESZ )
++#define IVB_mskIVBASE ( 0xFFFF << IVB_offIVBASE )
++
++/******************************************************************************
++ * ir4: EVA (Exception Virtual Address Register)
++ * ir5: P_EVA (Previous EVA Register)
++ *****************************************************************************/
++
++ /* This register contains the VA that causes the exception */
++
++/******************************************************************************
++ * ir6: ITYPE (Interruption Type Register)
++ * ir7: P_ITYPE (Previous ITYPE Register)
++ *****************************************************************************/
++#define ITYPE_offETYPE 0 /* Exception Type */
++#define ITYPE_offINST 4 /* Exception caused by insn fetch or data access */
++/* bit 5:15 reserved */
++#define ITYPE_offSWID 16 /* SWID of debugging exception */
++/* bit 31:31 reserved */
++
++#define ITYPE_mskETYPE ( 0xF << ITYPE_offETYPE )
++#define ITYPE_mskINST ( 0x1 << ITYPE_offINST )
++#define ITYPE_mskSWID ( 0x7FFF << ITYPE_offSWID )
++
++/* Additional definitions for ITYPE register */
++#define ITYPE_offSTYPE 16 /* Arithmetic Sub Type */
++#define ITYPE_offCPID 20 /* Co-Processor ID which generate the exception */
++
++#define ITYPE_mskSTYPE ( 0xF << ITYPE_offSTYPE )
++#define ITYPE_mskCPID ( 0x3 << ITYPE_offCPID )
++
++/******************************************************************************
++ * ir8: MERR (Machine Error Log Register)
++ *****************************************************************************/
++/* bit 0:30 reserved */
++#define MERR_offBUSERR 31 /* Bus error caused by a load insn */
++
++#define MERR_mskBUSERR ( 0x1 << MERR_offBUSERR )
++
++/******************************************************************************
++ * ir9: IPC (Interruption Program Counter Register)
++ * ir10: P_IPC (Previous IPC Register)
++ * ir11: OIPC (Overflow Interruption Program Counter Register)
++ *****************************************************************************/
++
++ /* This is the shadow stack register of the Program Counter */
++
++/******************************************************************************
++ * ir12: P_P0 (Previous P0 Register)
++ * ir13: P_P1 (Previous P1 Register)
++ *****************************************************************************/
++
++ /* These are shadow registers of $p0 and $p1 */
++
++/******************************************************************************
++ * ir14: INT_MASK (Interruption Masking Register)
++ *****************************************************************************/
++#define INT_MASK_offH0IM 0 /* Hardware Interrupt 0 Mask bit */
++#define INT_MASK_offH1IM 1 /* Hardware Interrupt 1 Mask bit */
++#define INT_MASK_offH2IM 2 /* Hardware Interrupt 2 Mask bit */
++#define INT_MASK_offH3IM 3 /* Hardware Interrupt 3 Mask bit */
++#define INT_MASK_offH4IM 4 /* Hardware Interrupt 4 Mask bit */
++#define INT_MASK_offH5IM 5 /* Hardware Interrupt 5 Mask bit */
++/* bit 6:15 reserved */
++#define INT_MASK_offSIM 16 /* Software Interrupt Mask bit */
++/* bit 17:29 reserved */
++#define INT_MASK_offIDIVZE 30 /* Enable detection for Divide-By-Zero */
++#define INT_MASK_offDSSIM 31 /* Default Single Stepping Interruption Mask */
++
++#define INT_MASK_mskH0IM ( 0x1 << INT_MASK_offH0IM )
++#define INT_MASK_mskH1IM ( 0x1 << INT_MASK_offH1IM )
++#define INT_MASK_mskH2IM ( 0x1 << INT_MASK_offH2IM )
++#define INT_MASK_mskH3IM ( 0x1 << INT_MASK_offH3IM )
++#define INT_MASK_mskH4IM ( 0x1 << INT_MASK_offH4IM )
++#define INT_MASK_mskH5IM ( 0x1 << INT_MASK_offH5IM )
++#define INT_MASK_mskSIM ( 0x1 << INT_MASK_offSIM )
++#define INT_MASK_mskIDIVZE ( 0x1 << INT_MASK_offIDIVZE )
++#define INT_MASK_mskDSSIM ( 0x1 << INT_MASK_offDSSIM )
++
++/******************************************************************************
++ * ir15: INT_PEND (Interrupt Pending Register)
++ *****************************************************************************/
++#define INT_PEND_offH0I 0 /* Hardware Interrupt 0 pending bit */
++#define INT_PEND_offH1I 1 /* Hardware Interrupt 1 pending bit */
++#define INT_PEND_offH2I 2 /* Hardware Interrupt 2 pending bit */
++#define INT_PEND_offH3I 3 /* Hardware Interrupt 3 pending bit */
++#define INT_PEND_offH4I 4 /* Hardware Interrupt 4 pending bit */
++#define INT_PEND_offH5I 5 /* Hardware Interrupt 5 pending bit */
++
++#define INT_PEND_offCIPL 0 /* Current Interrupt Priority Level */
++
++/* bit 6:15 reserved */
++#define INT_PEND_offSWI 16 /* Software Interrupt pending bit */
++/* bit 17:31 reserved */
++
++#define INT_PEND_mskH0I ( 0x1 << INT_PEND_offH0I )
++#define INT_PEND_mskH1I ( 0x1 << INT_PEND_offH1I )
++#define INT_PEND_mskH2I ( 0x1 << INT_PEND_offH2I )
++#define INT_PEND_mskH3I ( 0x1 << INT_PEND_offH3I )
++#define INT_PEND_mskH4I ( 0x1 << INT_PEND_offH4I )
++#define INT_PEND_mskH5I ( 0x1 << INT_PEND_offH5I )
++#define INT_PEND_mskCIPL ( 0x1 << INT_PEND_offCIPL )
++#define INT_PEND_mskSWI ( 0x1 << INT_PEND_offSWI )
++
++/******************************************************************************
++ * mr0: MMU_CTL (MMU Control Register)
++ *****************************************************************************/
++#define MMU_CTL_offD 0 /* Default minimum page size */
++#define MMU_CTL_offNTC0 1 /* Non-Translated Cachebility of partition 0 */
++#define MMU_CTL_offNTC1 3 /* Non-Translated Cachebility of partition 1 */
++#define MMU_CTL_offNTC2 5 /* Non-Translated Cachebility of partition 2 */
++#define MMU_CTL_offNTC3 7 /* Non-Translated Cachebility of partition 3 */
++#define MMU_CTL_offTBALCK 9 /* TLB all-lock resolution scheme */
++#define MMU_CTL_offMPZIU 10 /* Multiple Page Size In Use bit */
++#define MMU_CTL_offNTM0 11 /* Non-Translated VA to PA of partition 0 */
++#define MMU_CTL_offNTM1 13 /* Non-Translated VA to PA of partition 1 */
++#define MMU_CTL_offNTM2 15 /* Non-Translated VA to PA of partition 2 */
++#define MMU_CTL_offNTM3 17 /* Non-Translated VA to PA of partition 3 */
++/* bit 19:31 reserved */
++
++#define MMU_CTL_mskD ( 0x1 << MMU_CTL_offD )
++#define MMU_CTL_mskNTC0 ( 0x3 << MMU_CTL_offNTC0 )
++#define MMU_CTL_mskNTC1 ( 0x3 << MMU_CTL_offNTC1 )
++#define MMU_CTL_mskNTC2 ( 0x3 << MMU_CTL_offNTC2 )
++#define MMU_CTL_mskNTC3 ( 0x3 << MMU_CTL_offNTC3 )
++#define MMU_CTL_mskTBALCK ( 0x1 << MMU_CTL_offTBALCK )
++#define MMU_CTL_mskMPZIU ( 0x1 << MMU_CTL_offMPZIU )
++#define MMU_CTL_mskNTM0 ( 0x3 << MMU_CTL_offNTM0 )
++#define MMU_CTL_mskNTM1 ( 0x3 << MMU_CTL_offNTM1 )
++#define MMU_CTL_mskNTM2 ( 0x3 << MMU_CTL_offNTM2 )
++#define MMU_CTL_mskNTM3 ( 0x3 << MMU_CTL_offNTM3 )
++
++/******************************************************************************
++ * mr1: L1_PPTB (L1 Physical Page Table Base Register)
++ *****************************************************************************/
++#define L1_PPTB_offNV 0 /* Enable Hardware Page Table Walker (HPTWK) */
++/* bit 1:11 reserved */
++#define L1_PPTB_offBASE 12 /* First level physical page table base address */
++
++#define L1_PPTB_mskNV ( 0x1 << L1_PPTB_offNV )
++#define L1_PPTB_mskBASE ( 0xFFFFF << L1_PPTB_offBASE )
++
++/******************************************************************************
++ * mr2: TLB_VPN (TLB Access VPN Register)
++ *****************************************************************************/
++/* bit 0:11 reserved */
++#define TLB_VPN_offVPN 12 /* Virtual Page Number */
++
++#define TLB_VPN_mskVPN ( 0xFFFFF << TLB_VPN_offVPN )
++
++/******************************************************************************
++ * mr3: TLB_DATA (TLB Access Data Register)
++ *****************************************************************************/
++#define TLB_DATA_offV 0 /* PTE is valid and present */
++#define TLB_DATA_offM 1 /* Page read/write access privilege */
++#define TLB_DATA_offD 4 /* Dirty bit */
++#define TLB_DATA_offX 5 /* Executable bit */
++#define TLB_DATA_offA 6 /* Access bit */
++#define TLB_DATA_offG 7 /* Global page (shared across contexts) */
++#define TLB_DATA_offC 8 /* Cacheability atribute */
++/* bit 11:11 reserved */
++#define TLB_DATA_offPPN 12 /* Phisical Page Number */
++
++#define TLB_DATA_mskV ( 0x1 << TLB_DATA_offV )
++#define TLB_DATA_mskM ( 0x7 << TLB_DATA_offM )
++#define TLB_DATA_mskD ( 0x1 << TLB_DATA_offD )
++#define TLB_DATA_mskX ( 0x1 << TLB_DATA_offX )
++#define TLB_DATA_mskA ( 0x1 << TLB_DATA_offA )
++#define TLB_DATA_mskG ( 0x1 << TLB_DATA_offG )
++#define TLB_DATA_mskC ( 0x7 << TLB_DATA_offC )
++#define TLB_DATA_mskPPN ( 0xFFFFF << TLB_DATA_offPPN )
++
++/******************************************************************************
++ * mr4: TLB_MISC (TLB Access Misc Register)
++ *****************************************************************************/
++#define TLB_MISC_offACC_PSZ 0 /* Page size of a PTE entry */
++#define TLB_MISC_offCID 4 /* Context id */
++/* bit 13:31 reserved */
++
++#define TLB_MISC_mskACC_PSZ ( 0xF << TLB_MISC_offACC_PSZ )
++#define TLB_MISC_mskCID ( 0x1FF << TLB_MISC_offCID )
++
++/******************************************************************************
++ * mr5: VLPT_IDX (Virtual Linear Page Table Index Register)
++ *****************************************************************************/
++#define VLPT_IDX_offZERO 0 /* Always 0 */
++#define VLPT_IDX_offEVPN 2 /* Exception Virtual Page Number */
++#define VLPT_IDX_offVLPTB 22 /* Base VA of VLPT */
++
++#define VLPT_IDX_mskZERO ( 0x3 << VLPT_IDX_offZERO )
++#define VLPT_IDX_mskEVPN ( 0xFFFFF << VLPT_IDX_offEVPN )
++#define VLPT_IDX_mskVLPTB ( 0x3FF << VLPT_IDX_offVLPTB )
++
++/******************************************************************************
++ * mr6: ILMB (Instruction Local Memory Base Register)
++ *****************************************************************************/
++#define ILMB_offIEN 0 /* Enable ILM */
++#define ILMB_offILMSZ 1 /* Size of ILM */
++/* bit 5:19 reserved */
++#define ILMB_offIBPA 20 /* Base PA of ILM */
++
++#define ILMB_mskIEN ( 0x1 << ILMB_offIEN )
++#define ILMB_mskILMSZ ( 0xF << ILMB_offILMSZ )
++#define ILMB_mskIBPA ( 0xFFF << ILMB_offIBPA )
++
++/******************************************************************************
++ * mr7: DLMB (Data Local Memory Base Register)
++ *****************************************************************************/
++#define DLMB_offDEN 0 /* Enable DLM */
++#define DLMB_offDLMSZ 1 /* Size of DLM */
++#define DLMB_offDBM 5 /* Enable Double-Buffer Mode for DLM */
++#define DLMB_offDBB 6 /* Double-buffer bank which can be accessed by the processor */
++/* bit 7:19 reserved */
++#define DLMB_offDBPA 20 /* Base PA of DLM */
++
++#define DLMB_mskDEN ( 0x1 << DLMB_offDEN )
++#define DLMB_mskDLMSZ ( 0xF << DLMB_offDLMSZ )
++#define DLMB_mskDBM ( 0x1 << DLMB_offDBM )
++#define DLMB_mskDBB ( 0x1 << DLMB_offDBB )
++#define DLMB_mskDBPA ( 0xFFF << DLMB_offDBPA )
++
++/******************************************************************************
++ * mr8: CACHE_CTL (Cache Control Register)
++ *****************************************************************************/
++#define CACHE_CTL_offIC_EN 0 /* Enable I-cache */
++#define CACHE_CTL_offDC_EN 1 /* Enable D-cache */
++#define CACHE_CTL_offICALCK 2 /* I-cache all-lock resolution scheme */
++#define CACHE_CTL_offDCALCK 3 /* D-cache all-lock resolution scheme */
++#define CACHE_CTL_offDCCWF 4 /* Enable D-cache Critical Word Forwarding */
++#define CACHE_CTL_offDCPMW 5 /* Enable D-cache concurrent miss and write-back processing */
++/* bit 6:31 reserved */
++
++#define CACHE_CTL_mskIC_EN ( 0x1 << CACHE_CTL_offIC_EN )
++#define CACHE_CTL_mskDC_EN ( 0x1 << CACHE_CTL_offDC_EN )
++#define CACHE_CTL_mskICALCK ( 0x1 << CACHE_CTL_offICALCK )
++#define CACHE_CTL_mskDCALCK ( 0x1 << CACHE_CTL_offDCALCK )
++#define CACHE_CTL_mskDCCWF ( 0x1 << CACHE_CTL_offDCCWF )
++#define CACHE_CTL_mskDCPMW ( 0x1 << CACHE_CTL_offDCPMW )
++
++/******************************************************************************
++ * mr9: HSMP_SADDR (High Speed Memory Port Starting Address)
++ *****************************************************************************/
++#define HSMP_SADDR_offEN 0 /* Enable control bit for the High Speed Memory port */
++/* bit 1:19 reserved */
++
++#define HSMP_SADDR_offRANGE 1 /* Denote the address range (only defined in HSMP v2 ) */
++#define HSMP_SADDR_offSADDR 20 /* Starting base PA of the High Speed Memory Port region */
++
++#define HSMP_SADDR_mskEN ( 0x1 << HSMP_SADDR_offEN )
++#define HSMP_SADDR_mskRANGE ( 0xFFF << HSMP_SADDR_offRANGE )
++#define HSMP_SADDR_mskSADDR ( 0xFFF << HSMP_SADDR_offSADDR )
++
++/******************************************************************************
++ * mr10: HSMP_EADDR (High Speed Memory Port Ending Address)
++ *****************************************************************************/
++/* bit 0:19 reserved */
++#define HSMP_EADDR_offEADDR 20
++
++#define HSMP_EADDR_mskEADDR ( 0xFFF << HSMP_EADDR_offEADDR )
++
++/******************************************************************************
++ * dr0+(n*5): BPCn (n=0-7) (Breakpoint Control Register)
++ *****************************************************************************/
++#define BPC_offWP 0 /* Configuration of BPAn */
++#define BPC_offEL 1 /* Enable BPAn */
++#define BPC_offS 2 /* Data address comparison for a store instruction */
++#define BPC_offP 3 /* Compared data address is PA */
++#define BPC_offC 4 /* CID value is compared with the BPCIDn register */
++#define BPC_offBE0 5 /* Enable byte mask for the comparison with register */
++#define BPC_offBE1 6 /* Enable byte mask for the comparison with register */
++#define BPC_offBE2 7 /* Enable byte mask for the comparison with register */
++#define BPC_offBE3 8 /* Enable byte mask for the comparison with register */
++#define BPC_offT 9 /* Enable breakpoint Embedded Tracer triggering operation */
++
++#define BPC_mskWP ( 0x1 << BPC_offWP )
++#define BPC_mskEL ( 0x1 << BPC_offEL )
++#define BPC_mskS ( 0x1 << BPC_offS )
++#define BPC_mskP ( 0x1 << BPC_offP )
++#define BPC_mskC ( 0x1 << BPC_offC )
++#define BPC_mskBE0 ( 0x1 << BPC_offBE0 )
++#define BPC_mskBE1 ( 0x1 << BPC_offBE1 )
++#define BPC_mskBE2 ( 0x1 << BPC_offBE2 )
++#define BPC_mskBE3 ( 0x1 << BPC_offBE3 )
++#define BPC_mskT ( 0x1 << BPC_offT )
++
++/******************************************************************************
++ * dr1+(n*5): BPAn (n=0-7) (Breakpoint Address Register)
++ *****************************************************************************/
++
++ /* These registers contain break point address */
++
++/******************************************************************************
++ * dr2+(n*5): BPAMn (n=0-7) (Breakpoint Address Mask Register)
++ *****************************************************************************/
++
++ /* These registerd contain the address comparison mask for the BPAn register */
++
++/******************************************************************************
++ * dr3+(n*5): BPVn (n=0-7) Breakpoint Data Value Register
++ *****************************************************************************/
++
++ /* The BPVn register contains the data value that will be compared with the
++ * incoming load/store data value */
++
++/******************************************************************************
++ * dr4+(n*5): BPCIDn (n=0-7) (Breakpoint Context ID Register)
++ *****************************************************************************/
++#define BPCID_offCID 0 /* CID that will be compared with a process's CID */
++/* bit 9:31 reserved */
++
++#define BPCID_mskCID ( 0x1FF << BPCID_offCID )
++
++/******************************************************************************
++ * dr40: EDM_CFG (EDM Configuration Register)
++ *****************************************************************************/
++#define EDM_CFG_offBC 0 /* Number of hardware breakpoint sets implemented */
++#define EDM_CFG_offDIMU 3 /* Debug Instruction Memory Unit exists */
++/* bit 4:15 reserved */
++#define EDM_CFG_offVER 16 /* EDM version */
++
++#define EDM_CFG_mskBC ( 0x7 << EDM_CFG_offBC )
++#define EDM_CFG_mskDIMU ( 0x1 << EDM_CFG_offDIMU )
++#define EDM_CFG_mskVER ( 0xFFFF << EDM_CFG_offVER )
++
++/******************************************************************************
++ * dr41: EDMSW (EDM Status Word)
++ *****************************************************************************/
++#define EDMSW_offWV 0 /* Write Valid */
++#define EDMSW_offRV 1 /* Read Valid */
++#define EDMSW_offDE 2 /* Debug exception has occurred for this core */
++/* bit 3:31 reserved */
++
++#define EDMSW_mskWV ( 0x1 << EDMSW_offWV )
++#define EDMSW_mskRV ( 0x1 << EDMSW_offRV )
++#define EDMSW_mskDE ( 0x1 << EDMSW_offDE )
++
++/******************************************************************************
++ * dr42: EDM_CTL (EDM Control Register)
++ *****************************************************************************/
++/* bit 0:30 reserved */
++#define EDM_CTL_offV3_EDM_MODE 6 /* EDM compatibility control bit */
++#define EDM_CTL_offDEH_SEL 31 /* Controls where debug exception is directed to */
++
++#define EDM_CTL_mskV3_EDM_MODE ( 0x1 << EDM_CTL_offV3_EDM_MODE )
++#define EDM_CTL_mskDEH_SEL ( 0x1 << EDM_CTL_offDEH_SEL )
++
++/******************************************************************************
++ * dr43: EDM_DTR (EDM Data Transfer Register)
++ *****************************************************************************/
++
++ /* This is used to exchange data between the embedded EDM logic
++ * and the processor core */
++
++/******************************************************************************
++ * dr44: BPMTC (Breakpoint Match Trigger Counter Register)
++ *****************************************************************************/
++#define BPMTC_offBPMTC 0 /* Breakpoint match trigger counter value */
++/* bit 16:31 reserved */
++
++#define BPMTC_mskBPMTC ( 0xFFFF << BPMTC_offBPMTC )
++
++/******************************************************************************
++ * dr45: DIMBR (Debug Instruction Memory Base Register)
++ *****************************************************************************/
++/* bit 0:11 reserved */
++#define DIMBR_offDIMB 12 /* Base address of the Debug Instruction Memory (DIM) */
++#define DIMBR_mskDIMB ( 0xFFFFF << DIMBR_offDIMB )
++
++/******************************************************************************
++ * dr46: TECR0(Trigger Event Control register 0)
++ * dr47: TECR1 (Trigger Event Control register 1)
++ *****************************************************************************/
++#define TECR_offBP 0 /* Controld which BP is used as a trigger source */
++#define TECR_offNMI 8 /* Use NMI as a trigger source */
++#define TECR_offHWINT 9 /* Corresponding interrupt is used as a trigger source */
++#define TECR_offEVIC 15 /* Enable HWINT as a trigger source in EVIC mode */
++#define TECR_offSYS 16 /* Enable SYSCALL instruction as a trigger source */
++#define TECR_offDBG 17 /* Enable debug exception as a trigger source */
++#define TECR_offMRE 18 /* Enable MMU related exception as a trigger source */
++#define TECR_offE 19 /* An exception is used as a trigger source */
++/* bit 20:30 reserved */
++#define TECR_offL 31 /* Link/Cascade TECR0 trigger event to TECR1 trigger event */
++
++#define TECR_mskBP ( 0xFF << TECR_offBP )
++#define TECR_mskNMI ( 0x1 << TECR_offBNMI )
++#define TECR_mskHWINT ( 0x3F << TECR_offBHWINT )
++#define TECR_mskEVIC ( 0x1 << TECR_offBEVIC )
++#define TECR_mskSYS ( 0x1 << TECR_offBSYS )
++#define TECR_mskDBG ( 0x1 << TECR_offBDBG )
++#define TECR_mskMRE ( 0x1 << TECR_offBMRE )
++#define TECR_mskE ( 0x1 << TECR_offE )
++#define TECR_mskL ( 0x1 << TECR_offL )
++
++/******************************************************************************
++ * pfr0-2: PFMC0-2 (Performance Counter Register 0-2)
++ *****************************************************************************/
++
++ /* These registers contains performance event count */
++
++/******************************************************************************
++ * pfr3: PFM_CTL (Performance Counter Control Register)
++ *****************************************************************************/
++#define PFM_CTL_offEN0 0 /* Enable PFMC0 */
++#define PFM_CTL_offEN1 1 /* Enable PFMC1 */
++#define PFM_CTL_offEN2 2 /* Enable PFMC2 */
++#define PFM_CTL_offIE0 3 /* Enable interrupt for PFMC0 */
++#define PFM_CTL_offIE1 4 /* Enable interrupt for PFMC1 */
++#define PFM_CTL_offIE2 5 /* Enable interrupt for PFMC2 */
++#define PFM_CTL_offOVF0 6 /* Overflow bit of PFMC0 */
++#define PFM_CTL_offOVF1 7 /* Overflow bit of PFMC1 */
++#define PFM_CTL_offOVF2 8 /* Overflow bit of PFMC2 */
++#define PFM_CTL_offKS0 9 /* Enable superuser mode event counting for PFMC0 */
++#define PFM_CTL_offKS1 10 /* Enable superuser mode event counting for PFMC1 */
++#define PFM_CTL_offKS2 11 /* Enable superuser mode event counting for PFMC2 */
++#define PFM_CTL_offKU0 12 /* Enable user mode event counting for PFMC0 */
++#define PFM_CTL_offKU1 13 /* Enable user mode event counting for PFMC1 */
++#define PFM_CTL_offKU2 14 /* Enable user mode event counting for PFMC2 */
++#define PFM_CTL_offSEL0 15 /* The event selection for PFMC0 */
++#define PFM_CTL_offSEL1 21 /* The event selection for PFMC1 */
++#define PFM_CTL_offSEL2 27 /* The event selection for PFMC2 */
++/* bit 28:31 reserved */
++
++#define PFM_CTL_mskEN0 ( 0x01 << PFM_CTL_offEN0 )
++#define PFM_CTL_mskEN1 ( 0x01 << PFM_CTL_offEN1 )
++#define PFM_CTL_mskEN2 ( 0x01 << PFM_CTL_offEN2 )
++#define PFM_CTL_mskIE0 ( 0x01 << PFM_CTL_offIE0 )
++#define PFM_CTL_mskIE1 ( 0x01 << PFM_CTL_offIE1 )
++#define PFM_CTL_mskIE2 ( 0x01 << PFM_CTL_offIE2 )
++#define PFM_CTL_mskOVF0 ( 0x01 << PFM_CTL_offOVF0 )
++#define PFM_CTL_mskOVF1 ( 0x01 << PFM_CTL_offOVF1 )
++#define PFM_CTL_mskOVF2 ( 0x01 << PFM_CTL_offOVF2 )
++#define PFM_CTL_mskKS0 ( 0x01 << PFM_CTL_offKS0 )
++#define PFM_CTL_mskKS1 ( 0x01 << PFM_CTL_offKS1 )
++#define PFM_CTL_mskKS2 ( 0x01 << PFM_CTL_offKS2 )
++#define PFM_CTL_mskKU0 ( 0x01 << PFM_CTL_offKU0 )
++#define PFM_CTL_mskKU1 ( 0x01 << PFM_CTL_offKU1 )
++#define PFM_CTL_mskKU2 ( 0x01 << PFM_CTL_offKU2 )
++#define PFM_CTL_mskSEL0 ( 0x01 << PFM_CTL_offSEL0 )
++#define PFM_CTL_mskSEL1 ( 0x3F << PFM_CTL_offSEL1 )
++#define PFM_CTL_mskSEL2 ( 0x3F << PFM_CTL_offSEL2 )
++
++/******************************************************************************
++ * SDZ_CTL (Structure Downsizing Control Register)
++ *****************************************************************************/
++#define SDZ_CTL_offICDZ 0 /* I-cache downsizing control */
++#define SDZ_CTL_offDCDZ 3 /* D-cache downsizing control */
++#define SDZ_CTL_offMTBDZ 6 /* MTLB downsizing control */
++#define SDZ_CTL_offBTBDZ 9 /* Branch Target Table downsizing control */
++/* bit 12:31 reserved */
++#define SDZ_CTL_mskICDZ ( 0x07 << SDZ_CTL_offICDZ )
++#define SDZ_CTL_mskDCDZ ( 0x07 << SDZ_CTL_offDCDZ )
++#define SDZ_CTL_mskMTBDZ ( 0x07 << SDZ_CTL_offMTBDZ )
++#define SDZ_CTL_mskBTBDZ ( 0x07 << SDZ_CTL_offBTBDZ )
++
++/******************************************************************************
++ * N12MISC_CTL (N12 Miscellaneous Control Register)
++ *****************************************************************************/
++#define N12MISC_CTL_offBTB 0 /* Disable Branch Target Buffer */
++#define N12MISC_CTL_offRTP 1 /* Disable Return Target Predictor */
++#define N12MISC_CTL_offPTEPF 2 /* Disable HPTWK L2 PTE pefetch */
++/* bit 3:31 reserved */
++
++#define N12MISC_CTL_makBTB ( 0x1 << N12MISC_CTL_offBTB )
++#define N12MISC_CTL_makRTP ( 0x1 << N12MISC_CTL_offRTP )
++#define N12MISC_CTL_makPTEPF ( 0x1 << N12MISC_CTL_offPTEPF )
++
++/******************************************************************************
++ * PRUSR_ACC_CTL (Privileged Resource User Access Control Registers)
++ *****************************************************************************/
++#define PRUSR_ACC_CTL_offDMA_EN 0 /* Allow user mode access of DMA registers */
++#define PRUSR_ACC_CTL_offPFM_EN 1 /* Allow user mode access of PFM registers */
++
++#define PRUSR_ACC_CTL_mskDMA_EN ( 0x1 << PRUSR_ACC_CTL_offDMA_EN )
++#define PRUSR_ACC_CTL_mskPFM_EN ( 0x1 << PRUSR_ACC_CTL_offPFM_EN )
++
++/******************************************************************************
++ * dmar0: DMA_CFG (DMA Configuration Register)
++ *****************************************************************************/
++#define DMA_CFG_offNCHN 0 /* The number of DMA channels implemented */
++#define DMA_CFG_offUNEA 2 /* Un-aligned External Address transfer feature */
++#define DMA_CFG_off2DET 3 /* 2-D Element Transfer feature */
++/* bit 4:15 reserved */
++#define DMA_CFG_offVER 16 /* DMA architecture and implementation version */
++
++#define DMA_CFG_mskNCHN ( 0x3 << DMA_CFG_offNCHN )
++#define DMA_CFG_mskUNEA ( 0x1 << DMA_CFG_offUNEA )
++#define DMA_CFG_msk2DET ( 0x1 << DMA_CFG_off2DET )
++#define DMA_CFG_mskVER ( 0xFFFF << DMA_CFG_offVER )
++
++/******************************************************************************
++ * dmar1: DMA_GCSW (DMA Global Control and Status Word Register)
++ *****************************************************************************/
++#define DMA_GCSW_offC0STAT 0 /* DMA channel 0 state */
++#define DMA_GCSW_offC1STAT 3 /* DMA channel 1 state */
++/* bit 6:11 reserved */
++#define DMA_GCSW_offC0INT 12 /* DMA channel 0 generate interrupt */
++#define DMA_GCSW_offC1INT 13 /* DMA channel 1 generate interrupt */
++/* bit 14:30 reserved */
++#define DMA_GCSW_offEN 31 /* Enable DMA engine */
++
++#define DMA_GCSW_mskC0STAT ( 0x7 << DMA_GCSW_offC0STAT )
++#define DMA_GCSW_mskC1STAT ( 0x7 << DMA_GCSW_offC1STAT )
++#define DMA_GCSW_mskC0INT ( 0x1 << DMA_GCSW_offC0INT )
++#define DMA_GCSW_mskC1INT ( 0x1 << DMA_GCSW_offC1INT )
++#define DMA_GCSW_mskEN ( 0x1 << DMA_GCSW_offEN )
++
++/******************************************************************************
++ * dmar2: DMA_CHNSEL (DMA Channel Selection Register)
++ *****************************************************************************/
++#define DMA_CHNSEL_offCHAN 0 /* Selected channel number */
++/* bit 2:31 reserved */
++
++#define DMA_CHNSEL_mskCHAN ( 0x3 << DMA_CHNSEL_offCHAN )
++
++/******************************************************************************
++ * dmar3: DMA_ACT (DMA Action Register)
++ *****************************************************************************/
++#define DMA_ACT_offACMD 0 /* DMA Action Command */
++/* bit 2:31 reserved */
++#define DMA_ACT_mskACMD ( 0x3 << DMA_ACT_offACMD )
++
++/******************************************************************************
++ * dmar4: DMA_SETUP (DMA Setup Register)
++ *****************************************************************************/
++#define DMA_SETUP_offLM 0 /* Local Memory Selection */
++#define DMA_SETUP_offTDIR 1 /* Transfer Direction */
++#define DMA_SETUP_offTES 2 /* Transfer Element Size */
++#define DMA_SETUP_offESTR 4 /* External memory transfer Stride */
++#define DMA_SETUP_offCIE 16 /* Interrupt Enable on Completion */
++#define DMA_SETUP_offSIE 17 /* Interrupt Enable on explicit Stop */
++#define DMA_SETUP_offEIE 18 /* Interrupt Enable on Error */
++#define DMA_SETUP_offUE 19 /* Enable the Un-aligned External Address */
++#define DMA_SETUP_off2DE 20 /* Enable the 2-D External Transfer */
++#define DMA_SETUP_offCOA 21 /* Transfer Coalescable */
++/* bit 22:31 reserved */
++
++#define DMA_SETUP_mskLM ( 0x1 << DMA_SETUP_offLM )
++#define DMA_SETUP_mskTDIR ( 0x1 << DMA_SETUP_offTDIR )
++#define DMA_SETUP_mskTES ( 0x3 << DMA_SETUP_offTES )
++#define DMA_SETUP_mskESTR ( 0xFFF << DMA_SETUP_offESTR )
++#define DMA_SETUP_mskCIE ( 0x1 << DMA_SETUP_offCIE )
++#define DMA_SETUP_mskSIE ( 0x1 << DMA_SETUP_offSIE )
++#define DMA_SETUP_mskEIE ( 0x1 << DMA_SETUP_offEIE )
++#define DMA_SETUP_mskUE ( 0x1 << DMA_SETUP_offUE )
++#define DMA_SETUP_msk2DE ( 0x1 << DMA_SETUP_off2DE )
++#define DMA_SETUP_mskCOA ( 0x1 << DMA_SETUP_offCOA )
++
++/******************************************************************************
++ * dmar5: DMA_ISADDR (DMA Internal Start Address Register)
++ *****************************************************************************/
++#define DMA_ISADDR_offISADDR 0 /* Internal Start Address */
++/* bit 20:31 reserved */
++#define DMA_ISADDR_mskISADDR ( 0xFFFFF << DMA_ISADDR_offISADDR )
++
++/******************************************************************************
++ * dmar6: DMA_ESADDR (DMA External Start Address Register)
++ *****************************************************************************/
++/* This register holds External Start Address */
++
++/******************************************************************************
++ * dmar7: DMA_TCNT (DMA Transfer Element Count Register)
++ *****************************************************************************/
++#define DMA_TCNT_offTCNT 0 /* DMA transfer element count */
++/* bit 18:31 reserved */
++#define DMA_TCNT_mskTCNT ( 0x3FFFF << DMA_TCNT_offTCNT )
++
++/******************************************************************************
++ * dmar8: DMA_STATUS (DMA Status Register)
++ *****************************************************************************/
++#define DMA_STATUS_offSTAT 0 /* DMA channel state */
++#define DMA_STATUS_offSTUNA 3 /* Un-aligned error on External Stride value */
++#define DMA_STATUS_offDERR 4 /* DMA Transfer Disruption Error */
++#define DMA_STATUS_offEUNA 5 /* Un-aligned error on the External address */
++#define DMA_STATUS_offIUNA 6 /* Un-aligned error on the Internal address */
++#define DMA_STATUS_offIOOR 7 /* Out-Of-Range error on the Internal address */
++#define DMA_STATUS_offEBUS 8 /* Bus Error on an External DMA transfer */
++#define DMA_STATUS_offESUP 9 /* DMA setup error */
++/* bit 10:31 reserved */
++
++#define DMA_STATUS_mskSTAT ( 0x7 << DMA_STATUS_offSTAT )
++#define DMA_STATUS_mskSTUNA ( 0x1 << DMDMA_STATUS_offSTUNA )
++#define DMA_STATUS_mskDERR ( 0x1 << DMDMA_STATUS_offDERR )
++#define DMA_STATUS_mskEUNA ( 0x1 << DMDMA_STATUS_offEUNA )
++#define DMA_STATUS_mskIUNA ( 0x1 << DMDMA_STATUS_offIUNA )
++#define DMA_STATUS_mskIOOR ( 0x1 << DMDMA_STATUS_offIOOR )
++#define DMA_STATUS_mskEBUS ( 0x1 << DMDMA_STATUS_offEBUS )
++#define DMA_STATUS_mskESUP ( 0x1 << DMDMA_STATUS_offESUP )
++
++/******************************************************************************
++ * dmar9: DMA_2DSET (DMA 2D Setup Register)
++ *****************************************************************************/
++#define DMA_2DSET_offWECNT 0 /* The Width Element Count for a 2-D region */
++#define DMA_2DSET_offHTSTR 16 /* The Height Stride for a 2-D region */
++
++#define DMA_2DSET_mskHTSTR ( 0xFFFF << DMA_2DSET_offHTSTR )
++#define DMA_2DSET_mskWECNT ( 0xFFFF << DMA_2DSET_offWECNT )
++
++/******************************************************************************
++ * dmar10: DMA_2DSCTL (DMA 2D Startup Control Register)
++ *****************************************************************************/
++#define DMA_2DSCTL_offSTWECNT 0 /* Startup Width Element Count for a 2-D region */
++/* bit 16:31 reserved */
++
++#define DMA_2DSCTL_mskSTWECNT ( 0xFFFF << DMA_2DSCTL_offSTWECNT )
++
++/******************************************************************************
++ * fpcsr: FPCSR (Floating-Point Control Status Register)
++ *****************************************************************************/
++#define FPCSR_offRM 0
++#define FPCSR_offIVO 2
++#define FPCSR_offDBZ 3
++#define FPCSR_offOVF 4
++#define FPCSR_offUDF 5
++#define FPCSR_offIEX 6
++#define FPCSR_offIVOE 7
++#define FPCSR_offDBZE 8
++#define FPCSR_offOVFE 9
++#define FPCSR_offUDFE 10
++#define FPCSR_offIEXE 11
++#define FPCSR_offDNZ 12
++#define FPCSR_offIVOT 13
++#define FPCSR_offDBZT 14
++#define FPCSR_offOVFT 15
++#define FPCSR_offUDFT 16
++#define FPCSR_offIEXT 17
++#define FPCSR_offDNIT 18
++#define FPCSR_offRIT 19
++
++#define FPCSR_mskRM ( 0x3 << FPCSR_offRM )
++#define FPCSR_mskIVO ( 0x1 << FPCSR_offIVO )
++#define FPCSR_mskDBZ ( 0x1 << FPCSR_offDBZ )
++#define FPCSR_mskOVF ( 0x1 << FPCSR_offOVF )
++#define FPCSR_mskUDF ( 0x1 << FPCSR_offUDF )
++#define FPCSR_mskIEX ( 0x1 << FPCSR_offIEX )
++#define FPCSR_mskIVOE ( 0x1 << FPCSR_offIVOE )
++#define FPCSR_mskDBZE ( 0x1 << FPCSR_offDBZE )
++#define FPCSR_mskOVFE ( 0x1 << FPCSR_offOVFE )
++#define FPCSR_mskUDFE ( 0x1 << FPCSR_offUDFE )
++#define FPCSR_mskIEXE ( 0x1 << FPCSR_offIEXE )
++#define FPCSR_mskDNZ ( 0x1 << FPCSR_offDNZ )
++#define FPCSR_mskIVOT ( 0x1 << FPCSR_offIVOT )
++#define FPCSR_mskDBZT ( 0x1 << FPCSR_offDBZT )
++#define FPCSR_mskOVFT ( 0x1 << FPCSR_offOVFT )
++#define FPCSR_mskUDFT ( 0x1 << FPCSR_offUDFT )
++#define FPCSR_mskIEXT ( 0x1 << FPCSR_offIEXT )
++#define FPCSR_mskDNIT ( 0x1 << FPCSR_offDNIT )
++#define FPCSR_mskRIT ( 0x1 << FPCSR_offRIT )
++#define FPCSR_mskALL (FPCSR_mskIVO | FPCSR_mskDBZ | FPCSR_mskOVF | FPCSR_mskUDF | FPCSR_mskIEX)
++#define FPCSR_mskALLE (FPCSR_mskIVOE | FPCSR_mskDBZE | FPCSR_mskOVFE | FPCSR_mskUDFE | FPCSR_mskIEXE)
++#define FPCSR_mskALLT (FPCSR_mskIVOT | FPCSR_mskDBZT | FPCSR_mskOVFT | FPCSR_mskUDFT | FPCSR_mskIEXT |FPCSR_mskDNIT | FPCSR_mskRIT)
++
++/******************************************************************************
++ * fpcfg: FPCFG (Floating-Point Configuration Register)
++ *****************************************************************************/
++#define FPCFG_offSP 0
++#define FPCFG_offDP 1
++#define FPCFG_offFREG 2
++#define FPCFG_offFMA 4
++#define FPCFG_offIMVER 22
++#define FPCFG_offAVER 27
++
++#define FPCFG_mskSP ( 0x1 << FPCFG_offSP )
++#define FPCFG_mskDP ( 0x1 << FPCFG_offDP )
++#define FPCFG_mskFREG ( 0x3 << FPCFG_offFREG )
++#define FPCFG_mskFMA ( 0x1 << FPCFG_offFMA )
++#define FPCFG_mskIMVER ( 0x1F << FPCFG_offIMVER )
++#define FPCFG_mskAVER ( 0x1F << FPCFG_offAVER )
++
++/******************************************************************************
++ * fucpr: FUCOP_CTL (FPU and Coprocessor Enable Control Register)
++ *****************************************************************************/
++#define FUCOP_CTL_offCP0EN 0
++#define FUCOP_CTL_offCP1EN 1
++#define FUCOP_CTL_offCP2EN 2
++#define FUCOP_CTL_offCP3EN 3
++#define FUCOP_CTL_offAUEN 31
++
++#define FUCOP_CTL_mskCP0EN ( 0x1 << FUCOP_CTL_offCP0EN )
++#define FUCOP_CTL_mskCP1EN ( 0x1 << FUCOP_CTL_offCP1EN )
++#define FUCOP_CTL_mskCP2EN ( 0x1 << FUCOP_CTL_offCP2EN )
++#define FUCOP_CTL_mskCP3EN ( 0x1 << FUCOP_CTL_offCP3EN )
++#define FUCOP_CTL_mskAUEN ( 0x1 << FUCOP_CTL_offAUEN )
++
++#endif /* __NDS32_BITFIELD_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/bitops.h linux-3.4.110/arch/nds32/include/asm/bitops.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/bitops.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/bitops.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,256 @@
++/*
++ * linux/arch/nds32/include/asm/bitops.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_BITOPS_H__
++#define __NDS32_BITOPS_H__
++
++#if defined(CONFIG_SMP) || !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
++
++/*
++#include <linux/irqflags.h>
++
++static inline void ____atomic_set_bit(unsigned int bit, volatile unsigned long *p)
++{
++ unsigned long flags;
++ unsigned long mask = 1UL << (bit & 31);
++
++ p += bit >> 5;
++
++ raw_local_irq_save(flags);
++ *p |= mask;
++ raw_local_irq_restore(flags);
++}
++
++static inline void ____atomic_clear_bit(unsigned int bit, volatile unsigned long *p)
++{
++ unsigned long flags;
++ unsigned long mask = 1UL << (bit & 31);
++
++ p += bit >> 5;
++
++ raw_local_irq_save(flags);
++ *p &= ~mask;
++ raw_local_irq_restore(flags);
++}
++
++static inline void ____atomic_change_bit(unsigned int bit, volatile unsigned long *p)
++{
++ unsigned long flags;
++ unsigned long mask = 1UL << (bit & 31);
++
++ p += bit >> 5;
++
++ raw_local_irq_save(flags);
++ *p ^= mask;
++ raw_local_irq_restore(flags);
++}
++
++static inline int
++____atomic_test_and_set_bit(unsigned int bit, volatile unsigned long *p)
++{
++ unsigned long flags;
++ unsigned int res;
++ unsigned long mask = 1UL << (bit & 31);
++
++ p += bit >> 5;
++
++ raw_local_irq_save(flags);
++ res = *p;
++ *p = res | mask;
++ raw_local_irq_restore(flags);
++
++ return (res & mask) != 0;
++}
++static inline int
++____atomic_test_and_clear_bit(unsigned int bit, volatile unsigned long *p)
++{
++ unsigned long flags;
++ unsigned int res;
++ unsigned long mask = 1UL << (bit & 31);
++
++ p += bit >> 5;
++
++ raw_local_irq_save(flags);
++ res = *p;
++ *p = res & ~mask;
++ raw_local_irq_restore(flags);
++
++ return (res & mask) != 0;
++}
++
++static inline int
++____atomic_test_and_change_bit(unsigned int bit, volatile unsigned long *p)
++{
++ unsigned long flags;
++ unsigned int res;
++ unsigned long mask = 1UL << (bit & 31);
++
++ p += bit >> 5;
++
++ raw_local_irq_save(flags);
++ res = *p;
++ *p = res ^ mask;
++ raw_local_irq_restore(flags);
++
++ return (res & mask) != 0;
++}
++
++#include <asm-generic/bitops/non-atomic.h>
++#ifndef CONFIG_SMP
++#define ATOMIC_BITOP(name,nr,p) \
++ (__builtin_constant_p(nr) ? ____atomic_##name(nr, p) : _##name(nr,p))
++#else
++#define ATOMIC_BITOP(name,nr,p) _##name(nr,p)
++#endif
++
++#define set_bit(nr,p) ATOMIC_BITOP(set_bit,nr,p)
++*/
++
++static inline void set_bit(int nr,volatile unsigned long *addr)
++{
++ unsigned long mask = BIT_MASK(nr);
++ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
++ unsigned long tmp;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%1+$r15]\n"
++ "\tor\t%0, %0, %2\n"
++ "\tscw\t%0, [%1+$r15]\n"
++ "\tbeqz\t%0, 1b\n"
++ : "=&r" (tmp)
++ : "r" (p), "r" (mask)
++ : "memory");
++}
++
++static inline void clear_bit(int nr, volatile unsigned long *addr)
++{
++ unsigned long mask = BIT_MASK(nr);
++ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
++ unsigned long tmp;
++
++ mask = ~mask;
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%1+$r15]\n"
++ "\tand\t%0, %0, %2\n"
++ "\tscw\t%0, [%1+$r15]\n"
++ "\tbeqz\t%0, 1b\n"
++ : "=&r" (tmp)
++ : "r" (p), "r" (mask)
++ : "memory");
++}
++
++static inline void change_bit(int nr, volatile unsigned long *addr)
++{
++ unsigned long mask = BIT_MASK(nr);
++ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
++ unsigned long tmp;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%1+$r15]\n"
++ "\txor\t%0, %0, %2\n"
++ "\tscw\t%0, [%1+$r15]\n"
++ "\tbeqz\t%0, 1b\n"
++ : "=&r" (tmp)
++ : "r" (p), "r" (mask)
++ : "memory");
++}
++
++static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
++{
++ unsigned long mask = BIT_MASK(nr);
++ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
++ unsigned long tmp ,ret;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%2+$r15]\n"
++ "\tor\t%1, %0, %3\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (ret), "=&r" (tmp)
++ : "r" (p), "r" (mask)
++ : "memory");
++ return (ret & mask) != 0;
++}
++
++static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
++{
++ unsigned long mask = BIT_MASK(nr);
++ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
++ unsigned long tmp, ret;
++ unsigned long mask2 = ~mask;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%2+$r15]\n"
++ "\tand\t%1, %0, %3\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (ret), "=&r" (tmp)
++ : "r" (p), "r" (mask2)
++ : "memory");
++ return (ret & mask) != 0;
++}
++
++static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
++{
++ unsigned long mask = BIT_MASK(nr);
++ unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
++ unsigned long tmp, ret;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%2+$r15]\n"
++ "\txor\t%1, %0, %3\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (ret), "=&r" (tmp)
++ : "r" (p), "r" (mask)
++ : "memory");
++ return (ret & mask) != 0;
++}
++#else
++#include <linux/irqflags.h>
++#include <asm-generic/bitops/atomic.h>
++#endif
++
++#include <linux/compiler.h>
++#include <asm-generic/bitops/non-atomic.h>
++#include <asm-generic/bitops/__ffs.h>
++#include <asm-generic/bitops/ffz.h>
++#include <asm-generic/bitops/fls.h>
++#include <asm-generic/bitops/__fls.h>
++#include <asm-generic/bitops/fls64.h>
++#include <asm-generic/bitops/find.h>
++
++#ifdef __KERNEL__
++
++#include <asm-generic/bitops/sched.h>
++#include <asm-generic/bitops/ffs.h>
++#include <asm-generic/bitops/hweight.h>
++#include <asm-generic/bitops/lock.h>
++
++#include <asm-generic/bitops/le.h>
++
++/*
++ * Ext2 is defined to use little-endian byte ordering.
++ */
++#include <asm-generic/bitops/ext2-atomic-setbit.h>
++
++#endif /* __KERNEL__ */
++
++#define smp_mb__before_clear_bit() barrier()
++#define smp_mb__after_clear_bit() barrier()
++
++#endif /* __NDS32_BITOPS_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/bitsperlong.h linux-3.4.110/arch/nds32/include/asm/bitsperlong.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/bitsperlong.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/bitsperlong.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1 @@
++#include <asm-generic/bitsperlong.h>
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/bug.h linux-3.4.110/arch/nds32/include/asm/bug.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/bug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/bug.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,18 @@
++/*
++ * linux/arch/nds32/include/asm/bug.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_BUG_H__
++#define __NDS32_BUG_H__
++
++#define HAVE_ARCH_BUG
++#include <asm-generic/bug.h>
++
++#define BUG() do { \
++ dump_stack(); \
++ printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __FUNCTION__); \
++ panic("BUG!"); \
++} while (0)
++
++#endif /* __NDS32_BUG_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/bugs.h linux-3.4.110/arch/nds32/include/asm/bugs.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/bugs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/bugs.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/bugs.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_BUGS_H__
++#define __NDS32_BUGS_H__
++
++static inline void check_bugs(void) {}
++
++#endif /* __NDS32_BUGS_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/byteorder.h linux-3.4.110/arch/nds32/include/asm/byteorder.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/byteorder.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/byteorder.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,15 @@
++/*
++ * linux/arch/nds32/include/asm/byteorder.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_BYTEORDER_H__
++#define __NDS32_BYTEORDER_H__
++
++#ifdef __NDS32_EB__
++#include <linux/byteorder/big_endian.h>
++#else
++#include <linux/byteorder/little_endian.h>
++#endif
++
++#endif /* __NDS32_BYTEORDER_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cacheflush.h linux-3.4.110/arch/nds32/include/asm/cacheflush.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/cacheflush.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/cacheflush.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,55 @@
++/*
++ * linux/arch/nds32/include/asm/cacheflush.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_CACHEFLUSH_H__
++#define __NDS32_CACHEFLUSH_H__
++
++#include <linux/mm.h>
++
++#define PG_dcache_dirty PG_arch_1
++
++void flush_cache_mm(struct mm_struct *mm);
++
++void flush_cache_dup_mm(struct mm_struct *mm);
++
++void flush_cache_range(struct vm_area_struct *vma,
++ unsigned long start, unsigned long end);
++
++void flush_cache_page(struct vm_area_struct *vma,
++ unsigned long addr, unsigned long pfn);
++
++void flush_cache_kmaps(void);
++
++void flush_cache_vmap(unsigned long start, unsigned long end);
++
++void flush_cache_vunmap(unsigned long start, unsigned long end);
++
++
++void flush_dcache_page(struct page *page);
++
++void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
++ unsigned long vaddr, void *dst, void *src, int len);
++
++void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
++ unsigned long vaddr, void *dst, void *src, int len);
++
++#ifndef CONFIG_CPU_CACHE_NONALIASING
++#define ARCH_HAS_FLUSH_ANON_PAGE
++void flush_anon_page(struct vm_area_struct *vma,
++ struct page *page, unsigned long vaddr);
++
++#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
++void flush_kernel_dcache_page(struct page *page);
++#endif
++
++void flush_icache_range(unsigned long start, unsigned long end);
++
++void flush_icache_page(struct vm_area_struct *vma, struct page *page);
++
++#define flush_dcache_mmap_lock(mapping) spin_lock_irq(&(mapping)->tree_lock)
++#define flush_dcache_mmap_unlock(mapping) spin_unlock_irq(&(mapping)->tree_lock)
++
++#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
++#endif /* __NDS32_CACHEFLUSH_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cache.h linux-3.4.110/arch/nds32/include/asm/cache.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/cache.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/cache.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,22 @@
++/*
++ * linux/arch/nds32/include/asm/cache.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_CACHE_H__
++#define __NDS32_CACHE_H__
++
++#define L1_CACHE_BYTES 32
++#define L1_CACHE_SHIFT 5
++
++/*
++ * * Memory returned by kmalloc() may be used for DMA, so we must make
++ * * sure that all such allocations are cache aligned. Otherwise,
++ * * unrelated code may cause parts of the buffer to be read into the
++ * * cache before the transfer is done, causing old data to be seen by
++ * * the CPU.
++ * */
++#define ARCH_DMA_MINALIGN L1_CACHE_BYTES
++
++
++#endif /* __NDS32_CACHE_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cache_info.h linux-3.4.110/arch/nds32/include/asm/cache_info.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/cache_info.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/cache_info.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,17 @@
++/*
++ * linux/arch/nds32/include/asm/cache.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++struct cache_info {
++ unsigned char cache_type;
++ unsigned char ways;
++ unsigned char way_bits;
++ unsigned char line_bits;
++ unsigned char line_size;
++ unsigned char set_bits;
++ unsigned short sets;
++ unsigned short size;
++ unsigned short aliasing_num;
++ unsigned int aliasing_mask;
++ unsigned int not_aliasing_mask;
++};
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/checksum.h linux-3.4.110/arch/nds32/include/asm/checksum.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/checksum.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/checksum.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,173 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1995, 96, 97, 98, 99, 2001 by Ralf Baechle
++ * Copyright (C) 1999 Silicon Graphics, Inc.
++ * Copyright (C) 2001 Thiemo Seufer.
++ * Copyright (C) 2002 Maciej W. Rozycki
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++#ifndef _ASM_CHECKSUM_H
++#define _ASM_CHECKSUM_H
++
++#include <linux/in6.h>
++
++#include <asm/uaccess.h>
++
++/*
++ * computes the checksum of a memory block at buff, length len,
++ * and adds in "sum" (32-bit)
++ *
++ * returns a 32-bit number suitable for feeding into itself
++ * or csum_tcpudp_magic
++ *
++ * this function must be called with even lengths, except
++ * for the last fragment, which may be odd
++ *
++ * it's best to have buff aligned on a 32-bit boundary
++ */
++unsigned int csum_partial(const void *buff, int len, unsigned int sum);
++
++/*
++ * this is a new version of the above that records errors it finds in *errp,
++ * but continues and zeros the rest of the buffer.
++ */
++unsigned int csum_partial_copy_from_user(const unsigned char *src, unsigned char *dst, int len,
++ unsigned int sum, int *errp);
++
++/*
++ * Copy and checksum to user
++ */
++#define HAVE_CSUM_COPY_USER
++static inline unsigned int csum_and_copy_to_user (const unsigned char *src,
++ unsigned char __user *dst,
++ int len, int sum,
++ int *err_ptr)
++{
++ sum = csum_partial(src, len, sum);
++
++ if (copy_to_user(dst, src, len)) {
++ *err_ptr = -EFAULT;
++ return -1;
++ }
++
++ return sum;
++}
++
++/*
++ * the same as csum_partial, but copies from user space (but on MIPS
++ * we have just one address space, so this is identical to the above)
++ */
++unsigned int csum_partial_copy_nocheck(const unsigned char *src, unsigned char *dst,
++ int len, unsigned int sum);
++
++/*
++ * Fold a partial checksum without adding pseudo headers
++ */
++static inline unsigned short int csum_fold(unsigned int sum)
++{
++ __asm__(
++ "slli\t$p1,%0,16\n\t"
++ "add\t%0,%0,$p1\n\t"
++ "slt\t$p1,%0,$p1\n\t"
++ "srli\t%0,%0,16\n\t"
++ "add\t%0,%0,$p1\n\t"
++ "movi\t$p1,0xffff\n\t"
++ "xor\t%0,%0,$p1"
++ : "=r" (sum)
++ : "0" (sum));
++
++ return sum;
++}
++
++/*
++ * This is a version of ip_compute_csum() optimized for IP headers,
++ * which always checksum on 4 octet boundaries.
++ *
++ * By Jorge Cwik <jorge@laser.satlink.net>, adapted for linux by
++ * Arnt Gulbrandsen.
++ */
++static inline unsigned short ip_fast_csum(unsigned char *iph, unsigned int ihl)
++{
++ unsigned int *word = (unsigned int *) iph;
++ unsigned int *stop = word + ihl;
++ unsigned int csum;
++ int carry;
++
++ csum = word[0];
++ csum += word[1];
++ carry = (csum < word[1]);
++ csum += carry;
++
++ csum += word[2];
++ carry = (csum < word[2]);
++ csum += carry;
++
++ csum += word[3];
++ carry = (csum < word[3]);
++ csum += carry;
++
++ word += 4;
++ do {
++ csum += *word;
++ carry = (csum < *word);
++ csum += carry;
++ word++;
++ } while (word != stop);
++
++ return csum_fold(csum);
++}
++
++static inline unsigned int csum_tcpudp_nofold(unsigned long saddr,
++ unsigned long daddr, unsigned short len, unsigned short proto,
++ unsigned int sum)
++{
++ __asm__(
++ "add\t%0, %0, %2\n\t"
++ "slt\t$p1, %0, %2\n\t"
++ "add\t%0, %0, $p1\n\t"
++
++ "add\t%0, %0, %3\n\t"
++ "slt\t$p1, %0, %3\n\t"
++ "add\t%0, %0, $p1\n\t"
++
++ "add\t%0, %0, %4\n\t"
++ "slt\t$p1, %0, %4\n\t"
++ "add\t%0, %0, $p1"
++ : "=r" (sum)
++ : "0" (daddr), "r"(saddr),
++#ifdef __NDS32_EL__
++ "r" (((unsigned long)htons(len)<<16) + proto*256),
++#else
++ "r" (((unsigned long)(proto)<<16) + len),
++#endif
++ "r" ((__force unsigned long)sum));
++
++ return sum;
++}
++
++/*
++ * computes the checksum of the TCP/UDP pseudo-header
++ * returns a 16-bit checksum, already complemented
++ */
++static inline unsigned short int csum_tcpudp_magic(unsigned long saddr,
++ unsigned long daddr,
++ unsigned short len,
++ unsigned short proto,
++ unsigned int sum)
++{
++ return csum_fold(csum_tcpudp_nofold(saddr, daddr, len, proto, sum));
++}
++
++/*
++ * this routine is used for miscellaneous IP-like checksums, mainly
++ * in icmp.c
++ */
++static inline unsigned short ip_compute_csum(const void * buff, int len)
++{
++ return csum_fold(csum_partial(buff, len, 0));
++}
++
++#endif /* _ASM_CHECKSUM_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cmpxchg.h linux-3.4.110/arch/nds32/include/asm/cmpxchg.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/cmpxchg.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/cmpxchg.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,88 @@
++#ifndef __ASM_NDS32_CMPXCHG_H
++#define __ASM_NDS32_CMPXCHG_H
++
++#include <asm/barrier.h>
++
++#define xchg(ptr,x) \
++ ((__typeof__(*(ptr)))__xchg((unsigned long)(x),(ptr),sizeof(*(ptr))))
++
++static inline unsigned long __xchg(unsigned long x, volatile void *ptr, int size)
++{
++ extern void __bad_xchg(volatile void *, int);
++ unsigned long ret;
++ unsigned long flags;
++
++ switch (size) {
++ case 4:
++#if defined(CONFIG_SMP) || !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%2+$r15]\n"
++ "\tori\t%1, %3, #0x0\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (ret), "=&r" (flags)
++ : "r" (ptr), "r" (x)
++ : "memory");
++#else
++ raw_local_irq_save(flags);
++ ret = *(volatile unsigned long *)ptr;
++ *(volatile unsigned long *)ptr = x;
++ raw_local_irq_restore(flags);
++#endif
++ break;
++ default:
++ __bad_xchg(ptr, size);
++ ret = 0;
++ }
++ return ret;
++}
++
++
++#define __HAVE_ARCH_CMPXCHG 1
++
++static inline unsigned long __cmpxchg(volatile void * ptr, unsigned long old,
++ unsigned long new, int size)
++{
++ extern void __cmpxchg_called_with_bad_pointer(void); /*nonexistence */
++ unsigned long retval, tmp;
++ unsigned long flags;
++ switch (size) {
++ case 4:
++#if defined(CONFIG_SMP) || !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%3+$r15]\n"
++ "\tsub\t%2, %0, %5\n"
++ "\tcmovz\t%1, %4, %2\n"
++ "\tcmovn\t%1, %0, %2\n"
++ "\tscw\t%1, [%3+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (retval), "=&r" (flags), "=&r" (tmp)
++ : "r" (ptr), "r" (new), "r" (old));
++#else
++ raw_local_irq_save(flags);
++ retval = *(volatile unsigned long *)ptr;
++ if (retval == old)
++ *(volatile unsigned long *)ptr = new;
++ raw_local_irq_restore(flags);
++#endif
++ break;
++ default:
++ __cmpxchg_called_with_bad_pointer();
++ tmp = 0;
++ }
++ return retval;
++}
++
++#define cmpxchg(ptr,o,n) \
++ ({ \
++ __typeof__(*(ptr)) _o_ = (o); \
++ __typeof__(*(ptr)) _n_ = (n); \
++ (__typeof__(*(ptr))) __cmpxchg((ptr), (unsigned long)_o_, \
++ (unsigned long)_n_, sizeof(*(ptr))); \
++ })
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cpu.h linux-3.4.110/arch/nds32/include/asm/cpu.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/cpu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/cpu.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,25 @@
++/*
++ * linux/arch/nds32/include/asm/cpu.h
++ *
++ * Copyright (C) 2004-2005 ARM Ltd.
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_NDS32_CPU_H
++#define __ASM_NDS32_CPU_H
++
++#include <linux/percpu.h>
++
++struct cpuinfo_nds32 {
++ struct cpu cpu;
++#ifdef CONFIG_SMP
++ unsigned int loops_per_jiffy;
++#endif
++};
++
++DECLARE_PER_CPU(struct cpuinfo_nds32, cpu_data);
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cputime.h linux-3.4.110/arch/nds32/include/asm/cputime.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/cputime.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/cputime.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/cputime.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_CPUTIME_H__
++#define __NDS32_CPUTIME_H__
++
++#include <asm-generic/cputime.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/cpuver.h linux-3.4.110/arch/nds32/include/asm/cpuver.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/cpuver.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/cpuver.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,34 @@
++/*
++ * linux/arch/nds32/include/asm/cpuver.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_CPUVER_H__
++#define __NDS32_CPUVER_H__
++
++#include <asm/bitfield.h>
++#include <asm/reg_access.h>
++
++#define GET_CPU_ID()\
++ (( GET_CPU_VER() & CPU_VER_mskCPUID) >> CPU_VER_offCPUID)
++
++#define GET_CPU_REV()\
++ (( GET_CPU_VER() & CPU_VER_mskREV) >> CPU_VER_offREV)
++
++#define GET_CPU_CFGID()\
++ (( GET_CPU_VER() & CPU_VER_mskCFGID) >> CPU_VER_offCFGID)
++
++#define CPU_IS_N1213_43U1HA0()\
++ (((GET_CPU_VER() & CPU_VER_mskCPUID) == 0x0c000000) &&\
++ ((GET_CPU_VER() & CPU_VER_mskREV) == 0x00010000))
++
++#define CPU_IS_N1213_43U1HB0()\
++ (((GET_CPU_VER() & CPU_VER_mskCPUID) == 0x0c000000) &&\
++ ((GET_CPU_VER() & CPU_VER_mskREV) == 0x00020000))
++
++#define CPU_IS_N1033_S()\
++ (((GET_CPU_VER() & CPU_VER_mskCPUID) == 0x0a000000) &&\
++ ((GET_CPU_VER() & CPU_VER_mskREV) == 0x000c0000))
++
++#endif
++
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/current.h linux-3.4.110/arch/nds32/include/asm/current.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/current.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/current.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,18 @@
++/*
++ * linux/arch/nds32/include/asm/current.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_CURRENT_H__
++#define __NDS32_CURRENT_H__
++
++#include <linux/thread_info.h>
++
++static inline struct task_struct *get_current(void)
++{
++ return current_thread_info()->task;
++}
++
++#define current get_current()
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/delay.h linux-3.4.110/arch/nds32/include/asm/delay.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/delay.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/delay.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,39 @@
++/*
++ * linux/arch/nds32/include/asm/delay.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_DELAY_H__
++#define __NDS32_DELAY_H__
++
++#include <asm/param.h>
++
++static inline void __delay(unsigned long loops)
++{
++ __asm__ __volatile__ (
++ "1:\n"
++ "\taddi\t%0, %0, -1\n"
++ "\tbgtz\t%0, 1b\n"
++ : "=r" (loops) : "0" (loops));
++}
++
++static inline void __udelay(unsigned long usecs, unsigned long lpj)
++{
++ usecs *= (unsigned long) (((0x8000000000000000ULL / (500000 / HZ)) +
++ 0x80000000ULL) >> 32);
++ usecs=(unsigned long)(((unsigned long long)usecs*lpj)>>32);
++ __delay(usecs);
++}
++
++#define udelay(usecs) __udelay((usecs), loops_per_jiffy)
++
++/* make sure "usecs *= ..." in udelay do not overflow. */
++#if HZ >= 1000
++#define MAX_UDELAY_MS 1
++#elif HZ <= 200
++#define MAX_UDELAY_MS 5
++#else
++#define MAX_UDELAY_MS (1000 / HZ)
++#endif
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/device.h linux-3.4.110/arch/nds32/include/asm/device.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/device.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/device.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/device.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_DEVICE_H__
++#define __NDS32_DEVICE_H__
++
++#include <asm-generic/device.h>
++
++#endif /* __NDS32_DEVICE_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/div64.h linux-3.4.110/arch/nds32/include/asm/div64.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/div64.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/div64.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/div64.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_DIV64_H__
++#define __NDS32_DIV64_H__
++
++#include <asm-generic/div64.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/dmad.h linux-3.4.110/arch/nds32/include/asm/dmad.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/dmad.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/dmad.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,1071 @@
++/*
++ * Copyright Andes Technology Corporation 2007-2008
++ * All Rights Reserved.
++ *
++ * Revision History:
++ *
++ * Aug.21.2007 Created.
++ *
++ * DESCRIPTION
++ *
++ * DMA controller driver internal supplement library.
++ *
++ */
++
++#ifndef __NDS_DMAD_INC__
++#define __NDS_DMAD_INC__
++
++#include <asm/spec.h>
++
++/*****************************************************************************
++ * Configuration section
++*****************************************************************************/
++
++/* Debug trace enable switch */
++#define DMAD_ERROR_TRACE 1 /* message for fatal errors */
++//MOD by river 2010.10.19
++#define DMAD_DEBUG_TRACE 0 /* message for debug trace */
++//End MOD by river 2010.10.19
++
++//#ifndef addr_t
++typedef u32 addr_t;
++//#endif
++/* for amerald */
++#define AMERALD_PRODUCT_ID 0x41471000
++#define AMERALD_MASK 0xFFFFF000
++
++/*****************************************************************************
++ * DMAC - AG101 AHB
++*****************************************************************************/
++/* Device base address */
++#define DMAC_BASE DMAC_FTDMAC020_0_VA_BASE
++
++/* DMA controller registers (8-bit width) */
++#define DMAC_INT (DMAC_BASE + 0x00)
++#define DMAC_INT_TC (DMAC_BASE + 0x04)
++#define DMAC_INT_TC_CLR (DMAC_BASE + 0x08)
++#define DMAC_INT_ERRABT (DMAC_BASE + 0x0c)
++#define DMAC_INT_ERRABT_CLR (DMAC_BASE + 0x10)
++#define DMAC_TC (DMAC_BASE + 0x14)
++#define DMAC_ERRABT (DMAC_BASE + 0x18)
++#define DMAC_CH_EN (DMAC_BASE + 0x1c)
++#define DMAC_CH_BUSY (DMAC_BASE + 0x20)
++#define DMAC_CSR (DMAC_BASE + 0x24)
++#define DMAC_SYNC (DMAC_BASE + 0x28)
++
++/* DMA channel registers base address */
++#define DMAC_C0_OFFSET 0x100
++#define DMAC_C1_OFFSET 0x120
++#define DMAC_C2_OFFSET 0x140
++#define DMAC_C3_OFFSET 0x160
++#define DMAC_C4_OFFSET 0x180
++#define DMAC_C5_OFFSET 0x1a0
++#define DMAC_C6_OFFSET 0x1c0
++#define DMAC_C7_OFFSET 0x1e0
++
++#define DMAC_C0_BASE (DMAC_BASE + DMAC_C0_OFFSET)
++#define DMAC_C1_BASE (DMAC_BASE + DMAC_C1_OFFSET)
++#define DMAC_C2_BASE (DMAC_BASE + DMAC_C2_OFFSET)
++#define DMAC_C3_BASE (DMAC_BASE + DMAC_C3_OFFSET)
++#define DMAC_C4_BASE (DMAC_BASE + DMAC_C4_OFFSET)
++#define DMAC_C5_BASE (DMAC_BASE + DMAC_C5_OFFSET)
++#define DMAC_C6_BASE (DMAC_BASE + DMAC_C6_OFFSET)
++#define DMAC_C7_BASE (DMAC_BASE + DMAC_C7_OFFSET)
++
++#define DMAC_MAX_CHANNELS 8
++#define DMAC_BASE_CH(n) (DMAC_C0_BASE + \
++ (DMAC_C1_OFFSET - DMAC_C0_OFFSET) * \
++ (addr_t)(n)) /* n = 0 ~ 3 */
++
++#define DMAC_CSR_OFFSET 0x00
++#define DMAC_CFG_OFFSET 0x04
++#define DMAC_SRC_ADDR_OFFSET 0x08
++#define DMAC_DST_ADDR_OFFSET 0x0c
++#define DMAC_LLP_OFFSET 0x10
++#define DMAC_SIZE_OFFSET 0x14
++
++/* DMA channel 0 registers (32-bit width) */
++#define DMAC_C0_CSR (DMAC_C0_BASE + DMAC_CSR_OFFSET)
++#define DMAC_C0_CFG (DMAC_C0_BASE + DMAC_CFG_OFFSET)
++#define DMAC_C0_SRC_ADDR (DMAC_C0_BASE + DMAC_SRC_ADDR_OFFSET)
++#define DMAC_C0_DST_ADDR (DMAC_C0_BASE + DMAC_DST_ADDR_OFFSET)
++#define DMAC_C0_LLP (DMAC_C0_BASE + DMAC_LLP_OFFSET)
++#define DMAC_C0_SIZE (DMAC_C0_BASE + DMAC_SIZE_OFFSET)
++
++/* DMA channel 1 registers (32-bit width) */
++#define DMAC_C1_CSR (DMAC_C1_BASE + DMAC_CSR_OFFSET)
++#define DMAC_C1_CFG (DMAC_C1_BASE + DMAC_CFG_OFFSET)
++#define DMAC_C1_SRC_ADDR (DMAC_C1_BASE + DMAC_SRC_ADDR_OFFSET)
++#define DMAC_C1_DST_ADDR (DMAC_C1_BASE + DMAC_DST_ADDR_OFFSET)
++#define DMAC_C1_LLP (DMAC_C1_BASE + DMAC_LLP_OFFSET)
++#define DMAC_C1_SIZE (DMAC_C1_BASE + DMAC_SIZE_OFFSET)
++
++/* DMA channel 2 registers (32-bit width) */
++#define DMAC_C2_CSR (DMAC_C2_BASE + DMAC_CSR_OFFSET)
++#define DMAC_C2_CFG (DMAC_C2_BASE + DMAC_CFG_OFFSET)
++#define DMAC_C2_SRC_ADDR (DMAC_C2_BASE + DMAC_SRC_ADDR_OFFSET)
++#define DMAC_C2_DST_ADDR (DMAC_C2_BASE + DMAC_DST_ADDR_OFFSET)
++#define DMAC_C2_LLP (DMAC_C2_BASE + DMAC_LLP_OFFSET)
++#define DMAC_C2_SIZE (DMAC_C2_BASE + DMAC_SIZE_OFFSET)
++
++/* DMA channel 3 registers (32-bit width) */
++#define DMAC_C3_CSR (DMAC_C3_BASE + DMAC_CSR_OFFSET)
++#define DMAC_C3_CFG (DMAC_C3_BASE + DMAC_CFG_OFFSET)
++#define DMAC_C3_SRC_ADDR (DMAC_C3_BASE + DMAC_SRC_ADDR_OFFSET)
++#define DMAC_C3_DST_ADDR (DMAC_C3_BASE + DMAC_DST_ADDR_OFFSET)
++#define DMAC_C3_LLP (DMAC_C3_BASE + DMAC_LLP_OFFSET)
++#define DMAC_C3_SIZE (DMAC_C3_BASE + DMAC_SIZE_OFFSET)
++
++/* DMA channel 4 registers (32-bit width) */
++#define DMAC_C4_CSR (DMAC_C4_BASE + DMAC_CSR_OFFSET)
++#define DMAC_C4_CFG (DMAC_C4_BASE + DMAC_CFG_OFFSET)
++#define DMAC_C4_SRC_ADDR (DMAC_C4_BASE + DMAC_SRC_ADDR_OFFSET)
++#define DMAC_C4_DST_ADDR (DMAC_C4_BASE + DMAC_DST_ADDR_OFFSET)
++#define DMAC_C4_LLP (DMAC_C4_BASE + DMAC_LLP_OFFSET)
++#define DMAC_C4_SIZE (DMAC_C4_BASE + DMAC_SIZE_OFFSET)
++
++/* DMA channel 5 registers (32-bit width) */
++#define DMAC_C5_CSR (DMAC_C5_BASE + DMAC_CSR_OFFSET)
++#define DMAC_C5_CFG (DMAC_C5_BASE + DMAC_CFG_OFFSET)
++#define DMAC_C5_SRC_ADDR (DMAC_C5_BASE + DMAC_SRC_ADDR_OFFSET)
++#define DMAC_C5_DST_ADDR (DMAC_C5_BASE + DMAC_DST_ADDR_OFFSET)
++#define DMAC_C5_LLP (DMAC_C5_BASE + DMAC_LLP_OFFSET)
++#define DMAC_C5_SIZE (DMAC_C5_BASE + DMAC_SIZE_OFFSET)
++
++/* DMA channel 6 registers (32-bit width) */
++#define DMAC_C6_CSR (DMAC_C6_BASE + DMAC_CSR_OFFSET)
++#define DMAC_C6_CFG (DMAC_C6_BASE + DMAC_CFG_OFFSET)
++#define DMAC_C6_SRC_ADDR (DMAC_C6_BASE + DMAC_SRC_ADDR_OFFSET)
++#define DMAC_C6_DST_ADDR (DMAC_C6_BASE + DMAC_DST_ADDR_OFFSET)
++#define DMAC_C6_LLP (DMAC_C6_BASE + DMAC_LLP_OFFSET)
++#define DMAC_C6_SIZE (DMAC_C6_BASE + DMAC_SIZE_OFFSET)
++
++/* DMA channel 7 registers (32-bit width) */
++#define DMAC_C7_CSR (DMAC_C7_BASE + DMAC_CSR_OFFSET)
++#define DMAC_C7_CFG (DMAC_C7_BASE + DMAC_CFG_OFFSET)
++#define DMAC_C7_SRC_ADDR (DMAC_C7_BASE + DMAC_SRC_ADDR_OFFSET)
++#define DMAC_C7_DST_ADDR (DMAC_C7_BASE + DMAC_DST_ADDR_OFFSET)
++#define DMAC_C7_LLP (DMAC_C7_BASE + DMAC_LLP_OFFSET)
++#define DMAC_C7_SIZE (DMAC_C7_BASE + DMAC_SIZE_OFFSET)
++
++/*****************************************************************************
++ * DMAC defs - AG101 AHB
++*****************************************************************************/
++
++/* Interrupt status register (+00) */
++#define DMAC_INT0_MASK 0x01
++#define DMAC_INT0_BIT 0
++#define DMAC_INT1_MASK 0x02
++#define DMAC_INT1_BIT 1
++#define DMAC_INT2_MASK 0x04
++#define DMAC_INT2_BIT 2
++#define DMAC_INT3_MASK 0x08
++#define DMAC_INT3_BIT 3
++
++/* Interrupt for terminal count status register (+0x04) */
++#define DMAC_INT_TC0_MASK 0x01
++#define DMAC_INT_TC0_BIT 0
++#define DMAC_INT_TC1_MASK 0x02
++#define DMAC_INT_TC1_BIT 1
++#define DMAC_INT_TC2_MASK 0x04
++#define DMAC_INT_TC2_BIT 2
++#define DMAC_INT_TC3_MASK 0x08
++#define DMAC_INT_TC3_BIT 3
++#define DMAC_INT_TC4_MASK 0x01
++#define DMAC_INT_TC4_BIT 0
++#define DMAC_INT_TC5_MASK 0x02
++#define DMAC_INT_TC5_BIT 1
++#define DMAC_INT_TC6_MASK 0x04
++#define DMAC_INT_TC6_BIT 2
++#define DMAC_INT_TC7_MASK 0x08
++#define DMAC_INT_TC7_BIT 3
++
++#define DMAC_INT_TC_MASK 0xff
++#define DMAC_INT_TC_SHIFT 0
++
++/* Interrupt for terminal count clear register (+0x08) */
++#define DMAC_INT_TC0_CLR_MASK 0x01
++#define DMAC_INT_TC0_CLR_BIT 0
++#define DMAC_INT_TC1_CLR_MASK 0x02
++#define DMAC_INT_TC1_CLR_BIT 1
++#define DMAC_INT_TC2_CLR_MASK 0x04
++#define DMAC_INT_TC2_CLR_BIT 2
++#define DMAC_INT_TC3_CLR_MASK 0x08
++#define DMAC_INT_TC3_CLR_BIT 3
++
++#define DMAC_INT_TC_CLR_MASK 0x0f
++#define DMAC_INT_TC_CLR_SHIFT 0
++
++/* Interrupt for error/abort status register (+0x0c, 32-bits width) */
++#define DMAC_INT_ERR0_MASK 0x00000001
++#define DMAC_INT_ERR0_BIT 0
++#define DMAC_INT_ERR1_MASK 0x00000002
++#define DMAC_INT_ERR1_BIT 1
++#define DMAC_INT_ERR2_MASK 0x00000004
++#define DMAC_INT_ERR2_BIT 2
++#define DMAC_INT_ERR3_MASK 0x00000008
++#define DMAC_INT_ERR3_BIT 3
++
++#define DMAC_INT_ERR_MASK 0x0000000f
++#define DMAC_INT_ERR_SHIFT 0
++
++#define DMAC_INT_ABT0_MASK 0x00010000
++#define DMAC_INT_ABT0_BIT 16
++#define DMAC_INT_ABT1_MASK 0x00020000
++#define DMAC_INT_ABT1_BIT 17
++#define DMAC_INT_ABT2_MASK 0x00040000
++#define DMAC_INT_ABT2_BIT 18
++#define DMAC_INT_ABT3_MASK 0x00080000
++#define DMAC_INT_ABT3_BIT 19
++
++#define DMAC_INT_ABT_MASK 0x000f0000
++#define DMAC_INT_ABT_SHIFT 16
++
++/* Interrupt for error/abort status clear register (+0x10, 32-bits width) */
++#define DMAC_INT_ERR0_CLR_MASK 0x00000001
++#define DMAC_INT_ERR0_CLR_BIT 0
++#define DMAC_INT_ERR1_CLR_MASK 0x00000002
++#define DMAC_INT_ERR1_CLR_BIT 1
++#define DMAC_INT_ERR2_CLR_MASK 0x00000004
++#define DMAC_INT_ERR2_CLR_BIT 2
++#define DMAC_INT_ERR3_CLR_MASK 0x00000008
++#define DMAC_INT_ERR3_CLR_BIT 3
++
++#define DMAC_INT_ERR_CLR_MASK 0x0000000f
++#define DMAC_INT_ERR_CLR_SHIFT 0
++
++#define DMAC_INT_ABT0_CLR_MASK 0x00010000
++#define DMAC_INT_ABT0_CLR_BIT 16
++#define DMAC_INT_ABT1_CLR_MASK 0x00020000
++#define DMAC_INT_ABT1_CLR_BIT 17
++#define DMAC_INT_ABT2_CLR_MASK 0x00040000
++#define DMAC_INT_ABT2_CLR_BIT 18
++#define DMAC_INT_ABT3_CLR_MASK 0x00080000
++#define DMAC_INT_ABT3_CLR_BIT 19
++
++#define DMAC_INT_ABT_CLR_MASK 0x000f0000
++#define DMAC_INT_ABT_CLR_SHIFT 16
++
++/* Terminal count status register (+0x14) */
++#define DMAC_TC0_MASK 0x01
++#define DMAC_TC0_BIT 0
++#define DMAC_TC1_MASK 0x02
++#define DMAC_TC1_BIT 1
++#define DMAC_TC2_MASK 0x04
++#define DMAC_TC2_BIT 2
++#define DMAC_TC3_MASK 0x08
++#define DMAC_TC3_BIT 3
++
++/* Error/abort status register (+0x18, 32-bits width) */
++#define DMAC_ERR0_MASK 0x00000001
++#define DMAC_ERR0_BIT 0
++#define DMAC_ERR1_MASK 0x00000002
++#define DMAC_ERR1_BIT 1
++#define DMAC_ERR2_MASK 0x00000004
++#define DMAC_ERR2_BIT 2
++#define DMAC_ERR3_MASK 0x00000008
++#define DMAC_ERR3_BIT 3
++
++#define DMAC_ABT0_MASK 0x00010000
++#define DMAC_ABT0_BIT 16
++#define DMAC_ABT1_MASK 0x00020000
++#define DMAC_ABT1_BIT 17
++#define DMAC_ABT2_MASK 0x00040000
++#define DMAC_ABT2_BIT 18
++#define DMAC_ABT3_MASK 0x00080000
++#define DMAC_ABT3_BIT 19
++
++/* Channel enable status register (+0x1c) */
++#define DMAC_CH0_EN_MASK 0x01
++#define DMAC_CH0_EN_BIT 0
++#define DMAC_CH1_EN_MASK 0x02
++#define DMAC_CH1_EN_BIT 1
++#define DMAC_CH2_EN_MASK 0x04
++#define DMAC_CH2_EN_BIT 2
++#define DMAC_CH3_EN_MASK 0x08
++#define DMAC_CH3_EN_BIT 3
++
++/* Channel busy status register (+0x20) */
++#define DMAC_CH0_BUSY_MASK 0x01
++#define DMAC_CH0_BUSY_BIT 0
++#define DMAC_CH1_BUSY_MASK 0x02
++#define DMAC_CH1_BUSY_BIT 1
++#define DMAC_CH2_BUSY_MASK 0x04
++#define DMAC_CH2_BUSY_BIT 2
++#define DMAC_CH3_BUSY_MASK 0x08
++#define DMAC_CH3_BUSY_BIT 3
++
++/* Main configuration status register (+0x24) */
++#define DMAC_DMACEN_MASK 0x01
++#define DMAC_DMACEN_BIT 0
++#define DMAC_M0ENDIAN_MASK 0x02
++#define DMAC_M0ENDIAN_BIT 1
++#define DMAC_M1ENDIAN_MASK 0x04
++#define DMAC_M1ENDIAN_BIT 2
++
++ #define DMAC_ENDIAN_LITTLE 0
++ #define DMAC_ENDIAN_BIG 1
++
++/* Sync register (+0x28) */
++#define DMAC_SYNC0_MASK 0x01
++#define DMAC_SYNC0_BIT 0
++#define DMAC_SYNC1_MASK 0x02
++#define DMAC_SYNC1_BIT 1
++#define DMAC_SYNC2_MASK 0x04
++#define DMAC_SYNC2_BIT 2
++#define DMAC_SYNC3_MASK 0x08
++#define DMAC_SYNC3_BIT 3
++
++/* DMA channel 0~n Control Registers (CH[n]_BASE + 0x00) */
++#define DMAC_CSR_CH_EN_MASK 0x00000001
++#define DMAC_CSR_CH_EN_BIT 0
++
++#define DMAC_CSR_DST_SEL_MASK 0x00000002
++#define DMAC_CSR_DST_SEL_BIT 1
++#define DMAC_CSR_SRC_SEL_MASK 0x00000004
++#define DMAC_CSR_SRC_SEL_BIT 2
++ #define DMAC_CSR_SEL_MASTER0 0x00
++ #define DMAC_CSR_SEL_MASTER1 0x01
++
++#define DMAC_CSR_DSTAD_CTL_MASK 0x00000018
++#define DMAC_CSR_DSTAD_CTL_SHIFT 3
++#define DMAC_CSR_SRCAD_CTL_MASK 0x00000060
++#define DMAC_CSR_SRCAD_CTL_SHIFT 5
++ #define DMAC_CSR_AD_INC 0x00
++ #define DMAC_CSR_AD_DEC 0x01
++ #define DMAC_CSR_AD_FIX 0x02
++
++#define DMAC_CSR_MODE_MASK 0x00000080
++#define DMAC_CSR_MODE_BIT 7
++ #define DMAC_CSR_MODE_NORMAL 0x00
++ #define DMAC_CSR_MODE_HSHK 0x01
++
++#define DMAC_CSR_DST_WIDTH_MASK 0x00000700
++#define DMAC_CSR_DST_WIDTH_SHIFT 8
++#define DMAC_CSR_SRC_WIDTH_MASK 0x00003800
++#define DMAC_CSR_SRC_WIDTH_SHIFT 11
++ #define DMAC_CSR_WIDTH_8 0x00
++ #define DMAC_CSR_WIDTH_16 0x01
++ #define DMAC_CSR_WIDTH_32 0x02
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++#define DMAC_CYCLE_TO_BYTES(cycle, width) ((cycle) << (width))
++#define DMAC_BYTES_TO_CYCLE(bytes, width) ((bytes) >> (width))
++#else
++#define DMAC_CYCLE_TO_BYTES(cycle, width) 0
++#define DMAC_BYTES_TO_CYCLE(bytes, width) 0
++#endif /* CONFIG_PLATFORM_AHBDMA */
++
++#define DMAC_CSR_ABT 0x00008000
++#define DMAC_CSR_ABT_BIT 15
++
++#define DMAC_CSR_SRC_SIZE_MASK 0x00070000
++#define DMAC_CSR_SRC_SIZE_SHIFT 16
++ #define DMAC_CSR_SIZE_1 0x00
++ #define DMAC_CSR_SIZE_4 0x01
++ #define DMAC_CSR_SIZE_8 0x02
++ #define DMAC_CSR_SIZE_16 0x03
++ #define DMAC_CSR_SIZE_32 0x04
++ #define DMAC_CSR_SIZE_64 0x05
++ #define DMAC_CSR_SIZE_128 0x06
++ #define DMAC_CSR_SIZE_256 0x07
++
++#define DMAC_CSR_PROT1 0x00080000
++#define DMAC_CSR_PROT1_BIT 19
++#define DMAC_CSR_PROT2 0x00100000
++#define DMAC_CSR_PROT2_BIT 20
++#define DMAC_CSR_PROT3 0x00200000
++#define DMAC_CSR_PROT3_BIT 21
++
++#define DMAC_CSR_CHPRI_MASK 0x00c00000
++#define DMAC_CSR_CHPRI_SHIFT 22
++ #define DMAC_CSR_CHPRI_0 0x00
++ #define DMAC_CSR_CHPRI_1 0x01
++ #define DMAC_CSR_CHPRI_2 0x02
++ #define DMAC_CSR_CHPRI_3 0x03
++
++#define DMAC_CSR_FF_TH_MASK 0x07000000
++#define DMAC_CSR_FF_TH_SHIFT 24
++ #define DMAC_CSR_FF_TH_1 0x00
++ #define DMAC_CSR_FF_TH_2 0x01
++ #define DMAC_CSR_FF_TH_4 0x02
++ #define DMAC_CSR_FF_TH_8 0x03
++ #define DMAC_CSR_FF_TH_16 0x04
++
++#define DMAC_CSR_TC_MSK_MSK 0x80000000
++#define DMAC_CSR_TC_MSK_BIT 31
++
++/* DMA channel 0~n Configuration Registers (CH[n]_BASE + 0x04) */
++#define DMAC_CFG_INT_TC_MSK 0x00000001
++#define DMAC_CFG_INT_TC_MSK_BIT 0
++#define DMAC_CFG_INT_ERR_MSK 0x00000002
++#define DMAC_CFG_INT_ERR_MSK_BIT 1
++#define DMAC_CFG_INT_ABT_MSK 0x00000004
++#define DMAC_CFG_INT_ABT_MSK_BIT 2
++
++#define DMAC_CFG_INT_SRC_RS_MASK 0x00000078
++#define DMAC_CFG_INT_SRC_RS_SHIFT 3
++#define DMAC_CFG_INT_SRC_HE_MASK 0x00000080
++#define DMAC_CFG_INT_SRC_HE_BIT 7
++
++#define DMAC_CFG_BUSY_MASK 0x00000100
++#define DMAC_CFG_BUSY_BIT 8
++
++#define DMAC_CFG_INT_DST_RS_MASK 0x00001e00
++#define DMAC_CFG_INT_DST_RS_SHIFT 9
++#define DMAC_CFG_INT_DST_HE_MASK 0x00002000
++#define DMAC_CFG_INT_DST_HE_BIT 13
++
++#ifdef CONFIG_PLAT_AG102
++ #define DMAC_REQN_IDERX 0
++ #define DMAC_REQN_IDETX 1
++ #define DMAC_REQN_I2SAC97RX 2
++ #define DMAC_REQN_I2SAC97TX 3
++ #define DMAC_REQN_UART2RX 4
++ #define DMAC_REQN_UART2TX 5
++ #define DMAC_REQN_UART1RX 6
++ #define DMAC_REQN_UART1TX 7
++ #define DMAC_REQN_SDC 8
++ #define DMAC_REQN_CFC 9
++ #define DMAC_REQN_LPCREQ0 10
++ #define DMAC_REQN_LPCREQ1 11
++ #define DMAC_REQN_LPCREQ2 12
++ #define DMAC_REQN_LPCREQ3 13
++ #define DMAC_REQN_NONE 14
++ #define DMAC_REQN_LPCREQ5 15
++ #define DMAC_REQN_MAX 15
++#else
++ #define DMAC_REQN_NONE PMU_REQN_NONE
++ #define DMAC_REQN_CFC PMU_REQN_CFC
++ #define DMAC_REQN_SSP PMU_REQN_SSP
++ #define DMAC_REQN_UART1TX PMU_REQN_UART1TX
++ #define DMAC_REQN_UART1RX PMU_REQN_UART1RX
++ #define DMAC_REQN_UART2TX PMU_REQN_UART2TX
++ #define DMAC_REQN_UART2RX PMU_REQN_UART2RX
++ #define DMAC_REQN_SDC PMU_REQN_SDC
++ #define DMAC_REQN_I2SAC97TX PMU_REQN_I2SAC97TX
++ #define DMAC_REQN_I2SAC97RX PMU_REQN_I2SAC97RX
++/* for amerald ac97 ssp2 */
++ #define DMAC_REQN_I2SAC97TX_AMERALD PMU_REQN_I2SAC97TX_AMERALD
++ #define DMAC_REQN_I2SAC97RX_AMERALD PMU_REQN_I2SAC97RX_AMERALD
++ #define DMAC_REQN_USB PMU_REQN_USB
++ #define DMAC_REQN_EXT0 PMU_REQN_EXT0
++ #define DMAC_REQN_EXT1 PMU_REQN_EXT1
++ #define DMAC_REQN_MAX PMU_REQN_MAX
++#endif
++#define DMAC_CFG_INT_LLPCNT_MASK 0x000f0000
++#define DMAC_CFG_INT_LLPCNT_SHIFT 16
++
++/* DMA channel 0~n Linked List Descriptor Registers (CH[n]_BASE + 0x10) */
++#define DMAC_LLP_ADDR_MASK 0xfffffffc
++#define DMAC_LLP_ADDR_SHIFT 2
++#define DMAC_LLP_MASTER_MASK 0x00000001
++#define DMAC_LLP_MASTER_BIT 0
++ #define DMAC_LLP_MASTER_0 0
++ #define DMAC_LLP_MASTER_1 1
++
++/* DMA channel 0~3 Transfer Size Registers (CH[n]_BASE + 0x14) */
++#define DMAC_TOT_SIZE_MASK 0x003fffff
++#define DMAC_TOT_SIZE_SHIFT 0
++
++
++/*****************************************************************************
++ * APBBR - AG101 AHB to APB Bridge
++*****************************************************************************/
++/* Device base address */
++#ifdef CONFIG_PLAT_AG102
++#define APBBR_BASE APBBR_VA_BASE
++#else
++#define APBBR_BASE APBBRG_FTAPBBRG020S_0_VA_BASE
++#endif
++
++/* DMA channel A registers (32-bit width) */
++#define APBBR_DMAA_BASE (APBBR_BASE + 0x80)
++#define APBBR_DMAB_BASE (APBBR_BASE + 0x90)
++#define APBBR_DMAC_BASE (APBBR_BASE + 0xa0)
++#define APBBR_DMAD_BASE (APBBR_BASE + 0xb0)
++
++#define APBBR_DMA_MAX_CHANNELS APBBRG_FTAPBBRG020S_IRQ_COUNT
++/* n = 0 ~ APBBRG_FTAPBBRG020S_IRQ_COUNT */
++#define APBBR_DMA_BASE_CH(n) (APBBR_DMAA_BASE + \
++ (APBBR_DMAB_BASE - APBBR_DMAA_BASE) * \
++ (addr_t)(n))
++
++#define APBBR_DMA_SAD_OFFSET 0x00
++#define APBBR_DMA_DAD_OFFSET 0x04
++#define APBBR_DMA_CYC_OFFSET 0x08
++#define APBBR_DMA_CMD_OFFSET 0x0c
++
++
++/*****************************************************************************
++ * APBBR defs - AG101 AHB to APB Bridge
++*****************************************************************************/
++
++/* APBBR slave#n (n = 1~6, 8, 11, 16~23) base/size register */
++#define APBBR_SLAVE_SIZE_MASK 0x000f0000 /* Size of address space */
++#define APBBR_SLAVE_SIZE_SHIFT 16
++ #define APBBR_SIZE_1M 0
++ #define APBBR_SIZE_2M 1
++ #define APBBR_SIZE_4M 2
++ #define APBBR_SIZE_8M 3
++ #define APBBR_SIZE_16M 4
++ #define APBBR_SIZE_32M 5
++ #define APBBR_SIZE_64M 6
++ #define APBBR_SIZE_128M 7
++ #define APBBR_SIZE_256M 8
++
++#define APBBR_SLAVE_BASE_MASK 0x3ff00000
++#define APBBR_SLAVE_BASE_SHIFT 20
++
++/* APBBR DMA channel transfer cycles register
++ * DMA cycles (data size), 1 or 4 bus data transfer cycles per DMA cycle
++ * => transfer size = cycles * data_width * burst(1 or 4)
++ * so, max = 16M*4*4 = 256M
++ */
++#define APBBR_DMA_CYC_MASK 0x00ffffff
++#define APBBR_DMA_CYC_SHIFT 0
++
++/* APBBR DMA channel command register */
++#define APBBR_DMA_CHEN_MASK 0x00000001
++#define APBBR_DMA_CHEN_BIT 0
++
++#define APBBR_DMA_FINTST_MASK 0x00000002
++#define APBBR_DMA_FINTST_BIT 1
++#define APBBR_DMA_FINTEN_MASK 0x00000004
++#define APBBR_DMA_FINTEN_BIT 2
++
++#define APBBR_DMA_BURST_MASK 0x00000008
++#define APBBR_DMA_BURST_BIT 3
++
++#define APBBR_DMA_ERRINTST_MASK 0x00000010
++#define APBBR_DMA_ERRINTST_BIT 4
++#define APBBR_DMA_ERRINTEN_MASK 0x00000020
++#define APBBR_DMA_ERRINTEN_BIT 5
++
++#define APBBR_DMA_SRCADDRSEL_MASK 0x00000040
++#define APBBR_DMA_SRCADDRSEL_BIT 6
++#define APBBR_DMA_DSTADDRSEL_MASK 0x00000080
++#define APBBR_DMA_DSTADDRSEL_BIT 7
++ #define APBBR_ADDRSEL_APB 0
++ #define APBBR_ADDRSEL_AHB 1
++
++#define APBBR_DMA_SRCADDRINC_MASK 0x00000700
++#define APBBR_DMA_SRCADDRINC_SHIFT 8
++#define APBBR_DMA_DSTADDRINC_MASK 0x00007000
++#define APBBR_DMA_DSTADDRINC_SHIFT 12
++ #define APBBR_ADDRINC_FIXED 0 /* no increment */
++ #define APBBR_ADDRINC_I1X 1 /* +1, +4 (burst) */
++ #define APBBR_ADDRINC_I2X 2 /* +2, +8 (burst) */
++ #define APBBR_ADDRINC_I4X 3 /* +4, +16 (burst) */
++ #define APBBR_ADDRINC_D1 5 /* -1 */
++ #define APBBR_ADDRINC_D2 6 /* -2 */
++ #define APBBR_ADDRINC_D4 7 /* -4 */
++
++#define APBBR_DMA_DREQSEL_MASK 0x000f0000
++#define APBBR_DMA_DREQSEL_SHIFT 16
++#define APBBR_DMA_SREQSEL_MASK 0x0f000000
++#define APBBR_DMA_SREQSEL_SHIFT 24
++
++#ifdef CONFIG_PLAT_AG102
++ #define APBBR_REQN_NONE 0
++ #define APBBR_REQN_CFC 1
++ #define APBBR_REQN_SSP 2
++ #define APBBR_REQN_SDC 8
++ #define APBBR_REQN_I2SAC97TX 6
++ #define APBBR_REQN_SSP2 8
++ #define APBBR_REQN_STUART 9
++ #define APBBR_REQN_BTUART 10
++ #define APBBR_REQN_IRDA 11
++ #define APBBR_REQN_SMMC 12
++// #define APBBR_REQN_USB 0
++ #define APBBR_REQN_I2SAC97RX 13
++ #define APBBR_REQN_FUSB220 14
++ #define APBBR_REQN_MMSC 15
++ #define APBBR_REQN_MAX 15
++#else
++ #define APBBR_REQN_NONE 0
++ #define APBBR_REQN_CFC 1
++ #define APBBR_REQN_SSP 2
++ #define APBBR_REQN_SDC 5
++/* for amerald sd */
++ #define APBBR_REQN_SDC_AMERALD 7
++/* for amerald ac97 ssp2 */
++ #define APBBR_REQN_I2SAC97TX_AMERALD 8
++ #define APBBR_REQN_I2SAC97RX_AMERALD 9
++
++ #define APBBR_REQN_I2SAC97TX 6
++ #define APBBR_REQN_SSP2 8
++ #define APBBR_REQN_STUART 9 /* UART1 ? */
++ #define APBBR_REQN_BTUART 10 /* UART2 ? */
++ #define APBBR_REQN_IRDA 11
++ #define APBBR_REQN_SMMC 12
++ //#define APBBR_REQN_USB 13
++ #define APBBR_REQN_I2SAC97RX 13
++ #define APBBR_REQN_FUSB220 14
++ #define APBBR_REQN_MMSC 15
++ #define APBBR_REQN_MAX 15
++#endif
++
++#define APBBR_DMA_DATAWIDTH_MASK 0x00300000 /* Data width of transfer */
++#define APBBR_DMA_DATAWIDTH_SHIFT 20
++ #define APBBR_DATAWIDTH_4 0 /* word */
++ #define APBBR_DATAWIDTH_2 1 /* half-word */
++ #define APBBR_DATAWIDTH_1 2 /* byte */
++
++#ifdef CONFIG_PLATFORM_APBDMA
++#define APBBR_DMA_CYCLE_TO_BYTES(cycle, width) ((cycle) << (2-(width)))
++#define APBBR_DMA_BYTES_TO_CYCLE(bytes, width) ((bytes) >> (2-(width)))
++#else
++#define APBBR_DMA_CYCLE_TO_BYTES(cycle, width) 0
++#define APBBR_DMA_BYTES_TO_CYCLE(bytes, width) 0
++#endif /* CONFIG_PLATFORM_APBDMA */
++
++
++#ifdef CONFIG_PLAT_AG102
++
++/*****************************************************************************
++ * PCU - AG102 Core APB
++*****************************************************************************/
++/* Device base address */
++#define PCU_BASE PCU_VA_BASE
++/* PMU registers (32-bit width) */
++/* Add by Dennis on 2011.03.09 */
++#define PCU_DMA_SEL (PCU_BASE+ 0x38)
++
++#else /* CONFIG_PLAT_AG102 */
++
++/*****************************************************************************
++ * PMU - AG101 Core APB
++*****************************************************************************/
++/* Device base address */
++#define PMU_BASE PMU_FTPMU010_0_VA_BASE
++
++/* PMU registers (32-bit width) */
++#define PMU_AHBDMA_REQACK (PMU_BASE + 0x90)
++
++#define PMU_CFC_REQACK_CFG (PMU_BASE + 0xa0)
++#define PMU_SSP1_REQACK_CFG (PMU_BASE + 0xa4)
++#define PMU_UART1TX_REQACK_CFG (PMU_BASE + 0xa8)
++#define PMU_UART1RX_REQACK_CFG (PMU_BASE + 0xac)
++#define PMU_UART2TX_REQACK_CFG (PMU_BASE + 0xb0)
++#define PMU_UART2RX_REQACK_CFG (PMU_BASE + 0xb4)
++#define PMU_SDC_REQACK_CFG (PMU_BASE + 0xb8)
++#define PMU_I2SAC97TX_REQACK_CFG (PMU_BASE + 0xbc)
++#define PMU_I2SAC97RX_REQACK_CFG (PMU_BASE + 0xc4)
++#define PMU_UART3TX_REQACK_CFG (PMU_BASE + 0xc0)
++#define PMU_UART3RX_REQACK_CFG (PMU_BASE + 0xcc)
++#define PMU_USB_REQACK_CFG (PMU_BASE + 0xc8)
++#define PMU_IRDA_REQACK_CFG (PMU_BASE + 0xd0)
++#define PMU_EXT0_REQACK_CFG (PMU_BASE + 0xd4)
++#define PMU_EXT1_REQACK_CFG (PMU_BASE + 0xd8)
++
++
++/*****************************************************************************
++ * PMU - AG101 Core APB
++*****************************************************************************/
++
++/* Driving capability and slew rate control register 2 (+0x48) */
++#define PMU_STUART_DCSR_MASK 0x0000000f
++#define PMU_STUART_DCSR_SHIFT 0
++#define PMU_BTUART_DCSR_MASK 0x00000f00
++#define PMU_BTUART_DCSR_SHIFT 8
++/*#define PMU_FFUART_DCSR_MASK 0x0000f000*/
++/*#define PMU_FFUART_DCSR_SHIFT 12 */
++#define PMU_PMU_DCSR_MASK 0x000f0000
++#define PMU_PMU_DCSR_SHIFT 16
++#define PMU_I2SAC97_DCSR_MASK 0x00f00000
++#define PMU_I2SAC97_DCSR_SHIFT 20
++#define PMU_SSP_DCSR_MASK 0x0f000000
++#define PMU_SSP_DCSR_SHIFT 24
++#define PMU_SD_DCSR_MASK 0xf0000000
++#define PMU_SD_DCSR_SHIFT 28
++
++/* AHB DMA REQ/ACK connection configuration status register (+0x90) */
++#define PMU_CH0_REQACK_MASK 0x0000000f
++#define PMU_CH0_REQACK_SHIFT 0
++#define PMU_CH1_REQACK_MASK 0x000000f0
++#define PMU_CH1_REQACK_SHIFT 4
++#define PMU_CH2_REQACK_MASK 0x00000f00
++#define PMU_CH2_REQACK_SHIFT 8
++#define PMU_CH3_REQACK_MASK 0x0000f000
++#define PMU_CH3_REQACK_SHIFT 12
++#define PMU_CH4_REQACK_MASK 0x000f0000
++#define PMU_CH4_REQACK_SHIFT 16
++#define PMU_CH5_REQACK_MASK 0x00f00000
++#define PMU_CH5_REQACK_SHIFT 20
++#define PMU_CH6_REQACK_MASK 0x0f000000
++#define PMU_CH6_REQACK_SHIFT 24
++#define PMU_CH7_REQACK_MASK 0xf0000000
++#define PMU_CH7_REQACK_SHIFT 28
++
++ #define PMU_REQN_NONE 0
++ #define PMU_REQN_CFC 1
++ #define PMU_REQN_SSP 2
++ #define PMU_REQN_UART1TX 3
++ #define PMU_REQN_UART1RX 4
++ #define PMU_REQN_UART2TX 5
++ #define PMU_REQN_UART2RX 6
++ #define PMU_REQN_SDC 7
++ #define PMU_REQN_I2SAC97TX 8
++ #define PMU_REQN_I2SAC97RX 10
++/* for amerald ac97 ssp2 */
++ #define PMU_REQN_I2SAC97TX_AMERALD 8
++ #define PMU_REQN_I2SAC97RX_AMERALD 9
++ #define PMU_REQN_USB 11
++ #define PMU_REQN_EXT0 14
++ #define PMU_REQN_EXT1 15
++ #define PMU_REQN_MAX 15
++
++/* CFC ..., etc, REQ/ACK connection configuration registers (0xa0 ~ 0xd8) */
++#define PMU_CHANNEL_MASK 0x00000007
++#define PMU_CHANNEL_SHIFT 0
++#define PMU_DMACUSED_MASK 0x00000008
++#define PMU_DMACUSED_BIT 3
++
++#endif /* CONFIG_PLAT_AG102 */
++
++
++/*****************************************************************************
++ * DMAD globals section
++ */
++
++enum DMAD_DMAC_CORE {
++ DMAD_DMAC_AHB_CORE,
++ DMAD_DMAC_APB_CORE
++};
++
++enum DMAD_CHREG_FLAGS {
++ DMAD_FLAGS_NON_BLOCK = 0x00000000,
++ DMAD_FLAGS_SLEEP_BLOCK = 0x00000001,
++ DMAD_FLAGS_SPIN_BLOCK = 0x00000002,
++ DMAD_FLAGS_RING_MODE = 0x00000008, /* ring submission mode */
++ DMAD_FLAGS_BIDIRECTION = 0x00000010, /* indicates both tx and rx */
++};
++
++enum DMAD_CHDIR
++{
++ DMAD_DIR_A0_TO_A1 = 0,
++ DMAD_DIR_A1_TO_A0 = 1,
++};
++
++/* AHB Channel Request
++ *
++ * Notes for developers:
++ * These should be channel-only properties. Controller-specific properties
++ * should be separated as other driver structure or driver buildin-hardcode.
++ * If controller properties are embeded in this union, request for a channel
++ * may unexpectedly override the controller setting of the request of other
++ * channels.
++ */
++typedef struct dmad_ahb_chreq
++{
++ /* channel property */
++ u32 sync; /* (in) different clock domain */
++ u32 priority; /* (in) DMAC_CSR_CHPRI_xxx */
++ u32 hw_handshake; /* (in) hardware handshaking on/off */
++ u32 burst_size; /* (in) DMAC_CSR_SIZE_xxx */
++
++ /* source property */
++ union {
++ u32 src_width; /* (in) DMAC_CSR_WIDTH_xxx */
++ u32 addr0_width; /* (in) bi-direction mode alias */
++ u32 ring_width; /* (in) ring-mode alias */
++ };
++ union {
++ u32 src_ctrl; /* (in) DMAC_CSR_AD_xxx */
++ u32 addr0_ctrl; /* (in) bi-direction mode alias */
++ u32 ring_ctrl; /* (in) ring-mode alias */
++ };
++ union {
++ u32 src_reqn; /* (in) DMAC_REQN_xxx */
++ u32 addr0_reqn; /* (in) bi-direction mode alias */
++ u32 ring_reqn; /* (in) ring-mode alias */
++ };
++
++ /* destination property */
++ union {
++ u32 dst_width; /* (in) DMAC_CSR_WIDTH_xxx */
++ u32 addr1_width; /* (in) bi-direction mode alias */
++ u32 dev_width; /* (in) ring-mode alias */
++ };
++ union {
++ u32 dst_ctrl; /* (in) DMAC_CSR_AD_xxx */
++ u32 addr1_ctrl; /* (in) bi-direction mode alias */
++ u32 dev_ctrl; /* (in) ring-mode alias */
++ };
++ union {
++ u32 dst_reqn; /* (in) DMAC_REQN_xxx */
++ u32 addr1_reqn; /* (in) bi-direction mode alias */
++ u32 dev_reqn; /* (in) ring-mode alias */
++ };
++
++ /* (in) transfer direction, valid only if following flags were set ...
++ * DMAD_FLAGS_BIDIRECTION or
++ * DMAD_FLAGS_RING_MODE
++ * value:
++ * 0 (addr0 -> addr1, or ring-buff to device)
++ * 1 (addr0 <- addr1, or device to ring-buff)
++ */
++ u32 tx_dir;
++
++} dmad_ahb_chreq;
++
++/* APB Channel Request
++ *
++ * Notes for developers:
++ * These should be channel-only properties. Controller-specific properties
++ * should be separated as other driver structure or driver buildin-hardcode.
++ * If controller properties are embeded in this union, request for a channel
++ * may unexpectedly override the controller setting of the request of other
++ * channels.
++ */
++typedef struct dmad_apb_chreq
++{
++ /* controller property (removed! should not exist in this struct) */
++
++ /* channel property */
++ u32 burst_mode; /* (in) Burst mode (0/1) */
++ u32 data_width; /* (in) APBBR_DATAWIDTH_xxx */
++
++ /* source property */
++ union {
++ u32 src_ctrl; /* (in) APBBR_ADDRINC_xxx */
++ u32 addr0_ctrl; /* (in) bi-direction mode alias */
++ u32 ring_ctrl; /* (in) ring-mode alias */
++ };
++ union {
++ u32 src_reqn; /* (in) APBBR_REQN_xxx */
++ u32 addr0_reqn; /* (in) bi-direction mode alias */
++ u32 ring_reqn; /* (in) ring-mode alias */
++ };
++
++ /* destination property */
++ union {
++ u32 dst_ctrl; /* (in) APBBR_ADDRINC_xxx */
++ u32 addr1_ctrl; /* (in) bi-direction mode alias */
++ u32 dev_ctrl; /* (in) ring-mode alias */
++ };
++ union {
++ u32 dst_reqn; /* (in) APBBR_REQN_xxx */
++ u32 addr1_reqn; /* (in) bi-direction mode alias */
++ u32 dev_reqn; /* (in) ring-mode alias */
++ };
++
++ /* (in) transfer direction, valid only if following flags were set ...
++ * DMAD_FLAGS_BIDIRECTION or
++ * DMAD_FLAGS_RING_MODE
++ * value:
++ * 0 (addr0 -> addr1, or ring-buff to device)
++ * 1 (addr0 <- addr1, or device to ring-buff)
++ */
++ u32 tx_dir;
++
++} dmad_apb_chreq;
++
++/* Channel Request Descriptor */
++typedef struct dmad_chreq
++{
++ /* common fields */
++ u32 controller; /* (in) enum DMAD_DMAC_CORE */
++ u32 flags; /* (in) enum DMAD_CHREQ_FLAGS */
++
++ /**********************************************************************
++ * ring mode specific fields (valid only for DMAD_FLAGS_RING_MODE)
++ * note:
++ * - size fields are in unit of data width
++ * * for AHB, ring size is limited to 4K * data_width of data if
++ * hw-LLP is not used
++ * * for AHB, ring size is limited to 4K * data_width * LLP-count
++ * hw-if LLP is used
++ * * for APB, ring size is limited to 16M * data_width of data
++ * - currently sw ring mode dma supports only fixed or incremental
++ * src/dst addressing
++ * - ring_size shoule >= periods * period_size
++ */
++ dma_addr_t ring_base; /* (in) ring buffer base (pa) */
++ dma_addr_t ring_size; /* (in) unit of data width */
++ addr_t dev_addr; /* (in) device data port address */
++ dma_addr_t periods; /* (in) number of ints per ring */
++ dma_addr_t period_size; /* (in) size per int, data-width */
++
++
++ /* channel-wise completion callback - called when hw-ptr catches sw-ptr
++ * (i.e., channel stops)
++ *
++ * completion_cb: (in) client supplied callback function, executed in
++ * interrupt context.
++ * completion_data: (in) client private data to be passed to data
++ * argument of completion_cb().
++ */
++ void (*completion_cb)(int channel, u16 status, void *data);
++ void *completion_data;
++ /*********************************************************************/
++
++ /* channel allocation output */
++ u32 channel; /* (out) allocated channel */
++ void *drq; /* (out) internal use (DMAD_DRQ *)*/
++
++ /* channel-alloc parameters (channel-wise properties) */
++ union {
++#ifdef CONFIG_PLATFORM_AHBDMA
++ dmad_ahb_chreq ahb_req; /* (in) for AHB DMA parameters */
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ dmad_apb_chreq apb_req; /* (in) APB Bridge DMA params */
++#endif
++ };
++
++} dmad_chreq;
++
++/* drb states are mutual exclusive */
++enum DMAD_DRB_STATE
++{
++ DMAD_DRB_STATE_FREE = 0,
++ DMAD_DRB_STATE_READY = 0x00000001,
++ DMAD_DRB_STATE_SUBMITTED = 0x00000002,
++ DMAD_DRB_STATE_EXECUTED = 0x00000004,
++ DMAD_DRB_STATE_COMPLETED = 0x00000008,
++ //DMAD_DRB_STATE_ERROR = 0x00000010,
++ DMAD_DRB_STATE_ABORT = 0x00000020,
++};
++
++/* DMA request block
++ * todo: replaced link with kernel struct list_head ??
++ */
++typedef struct dmad_drb
++{
++ u32 prev; /* (internal) previous node */
++ u32 next; /* (internal) next node */
++ u32 node; /* (internal) this node */
++
++ u32 state; /* (out) DRB's current state */
++
++ union {
++ dma_addr_t src_addr; /* (in) source pa */
++ dma_addr_t addr0; /* (in) bi-direction mode alias */
++ };
++
++ union {
++ dma_addr_t dst_addr; /* (in) destination pa */
++ dma_addr_t addr1; /* (in) bi-direction mode alias */
++ };
++
++ /* (in) AHB DMA (22 bits): 0 ~ 4M-1, unit is "data width"
++ * APB DMA (24 bits): 0 ~ 16M-1, unit is "data width * burst size"
++ * => for safe without mistakes, use dmad_make_req_cycles() to
++ * compose this value if the addressing mode is incremental
++ * mode (not working yet for decremental mode).
++ */
++ dma_addr_t req_cycle;
++
++ /* (in) if non-null, this sync object will be signaled upon dma
++ * completion (for blocked-waiting dma completion)
++ */
++ struct completion *sync;
++
++} dmad_drb;
++
++
++/******************************************************************************
++ * Debug Trace Mechanism
++ */
++#if (DMAD_ERROR_TRACE)
++#define dmad_err(format, arg...) printk(KERN_ERR format , ## arg)
++#else
++#define dmad_err(format, arg...) (void)(0)
++#endif
++
++#if (DMAD_DEBUG_TRACE)
++#define dmad_dbg(format, arg...) printk(KERN_INFO format , ## arg)
++#else
++#define dmad_dbg(format, arg...) (void)(0)
++#endif
++
++#if (defined(CONFIG_PLATFORM_AHBDMA) || defined(CONFIG_PLATFORM_APBDMA))
++
++/******************************************************************************
++ * DMAD Driver Interface
++******************************************************************************/
++
++extern int dmad_channel_alloc(dmad_chreq *ch_req);
++extern int dmad_channel_free(dmad_chreq *ch_req);
++extern int dmad_channel_enable(const dmad_chreq *ch_req, u8 enable);
++extern u32 dmad_max_size_per_drb(dmad_chreq *ch_req);
++extern u32 dmad_bytes_to_cycles(dmad_chreq *ch_req, u32 byte_size);
++
++extern int dmad_kickoff_requests(dmad_chreq *ch_req);
++extern int dmad_drain_requests(dmad_chreq *ch_req, u8 shutdown);
++
++/* for performance reason, these two functions are platform-specific */
++#ifdef CONFIG_PLATFORM_AHBDMA
++extern int dmad_probe_irq_source_ahb(void);
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++extern int dmad_probe_irq_source_apb(void);
++#endif
++
++/* note: hw_ptr here is phyical address of dma source or destination */
++extern dma_addr_t dmad_probe_hw_ptr_src(dmad_chreq *ch_req);
++extern dma_addr_t dmad_probe_hw_ptr_dst(dmad_chreq *ch_req);
++
++/*****************************************************************************
++ * routines only valid in discrete (non-ring) mode
++ */
++extern int dmad_config_channel_dir(dmad_chreq *ch_req, u8 dir);
++extern int dmad_alloc_drb(dmad_chreq *ch_req, dmad_drb **drb);
++extern int dmad_free_drb(dmad_chreq *ch_req, dmad_drb *drb);
++extern int dmad_submit_request(dmad_chreq *ch_req,
++ dmad_drb *drb, u8 keep_fired);
++extern int dmad_withdraw_request(dmad_chreq *ch_req, dmad_drb *drb);
++/****************************************************************************/
++
++/*****************************************************************************
++ * routines only valid in ring mode
++ * note: sw_ptr and hw_ptr are values offset from the ring buffer base
++ * unit of sw_ptr is data-width
++ * unit of hw_ptr returned is byte
++ */
++extern int dmad_update_ring(dmad_chreq *ch_req);
++extern int dmad_update_ring_sw_ptr(dmad_chreq *ch_req,
++ dma_addr_t sw_ptr, u8 keep_fired);
++extern dma_addr_t dmad_probe_ring_hw_ptr(dmad_chreq *ch_req);
++/****************************************************************************/
++
++#else /* CONFIG_PLATFORM_AHBDMA || CONFIG_PLATFORM_APBDMA */
++
++static inline int dmad_channel_alloc(dmad_chreq *ch_req) { return -EFAULT; }
++static inline int dmad_channel_free(dmad_chreq *ch_req) { return -EFAULT; }
++static inline int dmad_channel_enable(const dmad_chreq *ch_req, u8 enable)
++ { return -EFAULT; }
++static inline u32 dmad_max_size_per_drb(dmad_chreq *ch_req) { return 0; }
++static inline u32 dmad_bytes_to_cycles(dmad_chreq *ch_req, u32 byte_size)
++ { return 0; }
++static inline int dmad_kickoff_requests(dmad_chreq *ch_req) { return -EFAULT; }
++static inline int dmad_drain_requests(dmad_chreq *ch_req, u8 shutdown)
++ { return -EFAULT; }
++static inline int dmad_probe_irq_source_ahb(void) { return -EFAULT; }
++static inline int dmad_probe_irq_source_apb(void) { return -EFAULT; }
++static inline dma_addr_t dmad_probe_hw_ptr_src(dmad_chreq *ch_req)
++ { return (dma_addr_t)NULL; }
++static inline dma_addr_t dmad_probe_hw_ptr_dst(dmad_chreq *ch_req)
++ { return (dma_addr_t)NULL; }
++static inline int dmad_config_channel_dir(dmad_chreq *ch_req, u8 dir)
++ { return -EFAULT; }
++static inline int dmad_alloc_drb(dmad_chreq *ch_req, dmad_drb **drb)
++ { return -EFAULT; }
++static inline int dmad_free_drb(dmad_chreq *ch_req, dmad_drb *drb)
++ { return -EFAULT; }
++static inline int dmad_submit_request(dmad_chreq *ch_req,
++ dmad_drb *drb, u8 keep_fired) { return -EFAULT; }
++static inline int dmad_withdraw_request(dmad_chreq *ch_req, dmad_drb *drb)
++ { return -EFAULT; }
++static inline int dmad_update_ring(dmad_chreq *ch_req)
++ { return -EFAULT; }
++static inline int dmad_update_ring_sw_ptr(dmad_chreq *ch_req,
++ dma_addr_t sw_ptr, u8 keep_fired) { return -EFAULT; }
++static inline dma_addr_t dmad_probe_ring_hw_ptr(dmad_chreq *ch_req)
++ { return (dma_addr_t)NULL; }
++
++#endif /* CONFIG_PLATFORM_AHBDMA || CONFIG_PLATFORM_APBDMA */
++
++#endif /* __NDS_DMAD_INC__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/dma.h linux-3.4.110/arch/nds32/include/asm/dma.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/dma.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,17 @@
++/*
++ * linux/arch/nds32/include/asm/dma.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_DMA_H__
++#define __NDS32_DMA_H__
++
++#define MAX_DMA_ADDRESS 0xffffffff
++
++#ifdef CONFIG_PCI
++extern int isa_dma_bridge_buggy;
++#else
++#define isa_dma_bridge_buggy (0)
++#endif
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/dma-mapping.h linux-3.4.110/arch/nds32/include/asm/dma-mapping.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/dma-mapping.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/dma-mapping.h 2016-04-07 10:20:50.894079168 +0200
+@@ -0,0 +1,453 @@
++/*
++ * linux/arch/nds32/include/asm/dma-mapping.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef ASMNDS32_DMA_MAPPING_H
++#define ASMNDS32_DMA_MAPPING_H
++
++#ifdef __KERNEL__
++
++#include <linux/mm.h> /* need struct page */
++#include <linux/highmem.h>
++
++#include <asm/scatterlist.h>
++
++/*
++ * DMA-consistent mapping functions. These allocate/free a region of
++ * uncached, unwrite-buffered mapped memory space for use with DMA
++ * devices. This is the "generic" version. The PCI specific version
++ * is in pci.h
++ */
++extern void consistent_sync(void *kaddr, size_t size, int rw);
++
++/*
++ * Return whether the given device DMA address mask can be supported
++ * properly. For example, if your device can only drive the low 24-bits
++ * during bus mastering, then you would pass 0x00ffffff as the mask
++ * to this function.
++ */
++static inline int dma_supported(struct device *dev, u64 mask)
++{
++ return dev->dma_mask && *dev->dma_mask != 0;
++}
++
++static inline int dma_set_mask(struct device *dev, u64 dma_mask)
++{
++ if (!dev->dma_mask || !dma_supported(dev, dma_mask))
++ return -EIO;
++
++ *dev->dma_mask = dma_mask;
++
++ return 0;
++}
++
++static inline int dma_is_consistent(dma_addr_t handle)
++{
++ return 0;
++}
++
++/*
++ * DMA errors are defined by all-bits-set in the DMA address.
++ */
++static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
++{
++ return dma_addr == ~0;
++}
++
++/*
++ * Dummy noncoherent implementation. We don't provide a dma_cache_sync
++ * function so drivers using this API are highlighted with build warnings.
++ */
++static inline void *
++dma_alloc_noncoherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp)
++{
++ return NULL;
++}
++
++static inline void
++dma_free_noncoherent(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t handle)
++{
++}
++
++/**
++ * dma_alloc_coherent - allocate consistent memory for DMA
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @size: required memory size
++ * @handle: bus-specific DMA address
++ *
++ * Allocate some uncached, unbuffered memory for a device for
++ * performing DMA. This function allocates pages, and will
++ * return the CPU-viewed address, and sets @handle to be the
++ * device-viewed address.
++ */
++extern void *
++dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);
++
++/**
++ * dma_free_coherent - free memory allocated by dma_alloc_coherent
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @size: size of memory originally requested in dma_alloc_coherent
++ * @cpu_addr: CPU-view address returned from dma_alloc_coherent
++ * @handle: device-view address returned from dma_alloc_coherent
++ *
++ * Free (and unmap) a DMA buffer previously allocated by
++ * dma_alloc_coherent().
++ *
++ * References to memory and mappings associated with cpu_addr/handle
++ * during and after this call executing are illegal.
++ */
++extern void
++dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t handle);
++
++/**
++ * dma_mmap_coherent - map a coherent DMA allocation into user space
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @vma: vm_area_struct describing requested user mapping
++ * @cpu_addr: kernel CPU-view address returned from dma_alloc_coherent
++ * @handle: device-view address returned from dma_alloc_coherent
++ * @size: size of memory originally requested in dma_alloc_coherent
++ *
++ * Map a coherent DMA buffer previously allocated by dma_alloc_coherent
++ * into user space. The coherent DMA buffer must not be freed by the
++ * driver until the user space mapping has been released.
++ */
++int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
++ void *cpu_addr, dma_addr_t handle, size_t size);
++
++
++/**
++ * dma_alloc_writecombine - allocate writecombining memory for DMA
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @size: required memory size
++ * @handle: bus-specific DMA address
++ *
++ * Allocate some uncached, buffered memory for a device for
++ * performing DMA. This function allocates pages, and will
++ * return the CPU-viewed address, and sets @handle to be the
++ * device-viewed address.
++ */
++extern void *
++dma_alloc_writecombine(struct device *dev, size_t size, dma_addr_t *handle, gfp_t gfp);
++
++#define dma_free_writecombine(dev,size,cpu_addr,handle) \
++ dma_free_coherent(dev,size,cpu_addr,handle)
++
++int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
++ void *cpu_addr, dma_addr_t handle, size_t size);
++
++
++/**
++ * dma_map_single - map a single buffer for streaming DMA
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @cpu_addr: CPU direct mapped address of buffer
++ * @size: size of buffer to map
++ * @dir: DMA transfer direction
++ *
++ * Ensure that any data held in the cache is appropriately discarded
++ * or written back.
++ *
++ * The device owns this memory once this call has completed. The CPU
++ * can regain ownership by calling dma_unmap_single() or
++ * dma_sync_single_for_cpu().
++ */
++#ifndef CONFIG_DMABOUNCE
++static inline dma_addr_t
++dma_map_single(struct device *dev, void *cpu_addr, size_t size,
++ enum dma_data_direction dir)
++{
++ consistent_sync(cpu_addr, size, dir);
++ return virt_to_dma(dev, (unsigned long)cpu_addr);
++}
++#else
++extern dma_addr_t dma_map_single(struct device *,void *, size_t, enum dma_data_direction);
++#endif
++
++/**
++ * dma_map_page - map a portion of a page for streaming DMA
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @page: page that buffer resides in
++ * @offset: offset into page for start of buffer
++ * @size: size of buffer to map
++ * @dir: DMA transfer direction
++ *
++ * Ensure that any data held in the cache is appropriately discarded
++ * or written back.
++ *
++ * The device owns this memory once this call has completed. The CPU
++ * can regain ownership by calling dma_unmap_page() or
++ * dma_sync_single_for_cpu().
++ */
++static inline dma_addr_t
++dma_map_page(struct device *dev, struct page *page,
++ unsigned long offset, size_t size,
++ enum dma_data_direction dir)
++{
++ return dma_map_single(dev, page_address(page) + offset, size, (int)dir);
++}
++
++/**
++ * dma_unmap_single - unmap a single buffer previously mapped
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @handle: DMA address of buffer
++ * @size: size of buffer to map
++ * @dir: DMA transfer direction
++ *
++ * Unmap a single streaming mode DMA translation. The handle and size
++ * must match what was provided in the previous dma_map_single() call.
++ * All other usages are undefined.
++ *
++ * After this call, reads by the CPU to the buffer are guaranteed to see
++ * whatever the device wrote there.
++ */
++#ifndef CONFIG_DMABOUNCE
++static inline void
++dma_unmap_single(struct device *dev, dma_addr_t handle, size_t size,
++ enum dma_data_direction dir)
++{
++ /* nothing to do */
++}
++#else
++extern void dma_unmap_single(struct device *, dma_addr_t, size_t, enum dma_data_direction);
++#endif
++
++/**
++ * dma_unmap_page - unmap a buffer previously mapped through dma_map_page()
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @handle: DMA address of buffer
++ * @size: size of buffer to map
++ * @dir: DMA transfer direction
++ *
++ * Unmap a single streaming mode DMA translation. The handle and size
++ * must match what was provided in the previous dma_map_single() call.
++ * All other usages are undefined.
++ *
++ * After this call, reads by the CPU to the buffer are guaranteed to see
++ * whatever the device wrote there.
++ */
++static inline void
++dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
++ enum dma_data_direction dir)
++{
++ dma_unmap_single(dev, handle, size, (int)dir);
++}
++
++/**
++ * dma_map_sg - map a set of SG buffers for streaming mode DMA
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @sg: list of buffers
++ * @nents: number of buffers to map
++ * @dir: DMA transfer direction
++ *
++ * Map a set of buffers described by scatterlist in streaming
++ * mode for DMA. This is the scatter-gather version of the
++ * above dma_map_single interface. Here the scatter gather list
++ * elements are each tagged with the appropriate dma address
++ * and length. They are obtained via sg_dma_{address,length}(SG).
++ *
++ * NOTE: An implementation may be able to use a smaller number of
++ * DMA address/length pairs than there are SG table elements.
++ * (for example via virtual mapping capabilities)
++ * The routine returns the number of addr/length pairs actually
++ * used, at most nents.
++ *
++ * Device ownership issues as mentioned above for dma_map_single are
++ * the same here.
++ */
++#ifndef CONFIG_DMABOUNCE
++static inline int
++dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++ int i;
++
++ for (i = 0; i < nents; i++, sg++) {
++ void *virt;
++ unsigned long pfn;
++ struct page *page = sg_page(sg);
++
++ sg->dma_address = page_to_dma(dev, page) + sg->offset;
++ pfn = page_to_pfn(page) + sg->offset / PAGE_SIZE;
++ page = pfn_to_page(pfn);
++ if (PageHighMem(page)) {
++ virt = kmap_atomic(page);
++ consistent_sync(virt, sg->length, dir);
++ kunmap_atomic(virt);
++ } else {
++ if (sg->offset > PAGE_SIZE)
++ panic("sg->offset:%08x > PAGE_SIZE\n", sg->offset);
++ virt = page_address(page) + sg->offset;
++ consistent_sync(virt, sg->length, dir);
++ }
++ }
++ return nents;
++}
++#else
++extern int dma_map_sg(struct device *, struct scatterlist *, int, enum dma_data_direction);
++#endif
++
++/**
++ * dma_unmap_sg - unmap a set of SG buffers mapped by dma_map_sg
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @sg: list of buffers
++ * @nents: number of buffers to map
++ * @dir: DMA transfer direction
++ *
++ * Unmap a set of streaming mode DMA translations.
++ * Again, CPU read rules concerning calls here are the same as for
++ * dma_unmap_single() above.
++ */
++#ifndef CONFIG_DMABOUNCE
++static inline void
++dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++
++ /* nothing to do */
++}
++#else
++extern void dma_unmap_sg(struct device *, struct scatterlist *, int, enum dma_data_direction);
++#endif
++
++
++/**
++ * dma_sync_single_for_cpu
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @handle: DMA address of buffer
++ * @size: size of buffer to map
++ * @dir: DMA transfer direction
++ *
++ * Make physical memory consistent for a single streaming mode DMA
++ * translation after a transfer.
++ *
++ * If you perform a dma_map_single() but wish to interrogate the
++ * buffer using the cpu, yet do not wish to teardown the PCI dma
++ * mapping, you must call this function before doing so. At the
++ * next point you give the PCI dma address back to the card, you
++ * must first the perform a dma_sync_for_device, and then the
++ * device again owns the buffer.
++ */
++#ifndef CONFIG_DMABOUNCE
++static inline void
++dma_sync_single_for_cpu(struct device *dev, dma_addr_t handle, size_t size,
++ enum dma_data_direction dir)
++{
++ consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
++}
++
++static inline void
++dma_sync_single_for_device(struct device *dev, dma_addr_t handle, size_t size,
++ enum dma_data_direction dir)
++{
++ consistent_sync((void *)dma_to_virt(dev, handle), size, dir);
++}
++#else
++extern void dma_sync_single_for_cpu(struct device*, dma_addr_t, size_t, enum dma_data_direction);
++extern void dma_sync_single_for_device(struct device*, dma_addr_t, size_t, enum dma_data_direction);
++#endif
++
++
++/**
++ * dma_sync_sg_for_cpu
++ * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
++ * @sg: list of buffers
++ * @nents: number of buffers to map
++ * @dir: DMA transfer direction
++ *
++ * Make physical memory consistent for a set of streaming
++ * mode DMA translations after a transfer.
++ *
++ * The same as dma_sync_single_for_* but for a scatter-gather list,
++ * same rules and usage.
++ */
++#ifndef CONFIG_DMABOUNCE
++static inline void
++dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++ int i;
++
++ for (i = 0; i < nents; i++, sg++) {
++ char *virt = page_address( (struct page *)sg->page_link) + sg->offset;
++ consistent_sync(virt, sg->length, dir);
++ }
++}
++
++static inline void
++dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
++ enum dma_data_direction dir)
++{
++ int i;
++
++ for (i = 0; i < nents; i++, sg++) {
++ char *virt = page_address( (struct page *)sg->page_link) + sg->offset;
++ consistent_sync(virt, sg->length, dir);
++ }
++}
++#else
++extern void dma_sync_sg_for_cpu(struct device*, struct scatterlist*, int, enum dma_data_direction);
++extern void dma_sync_sg_for_device(struct device*, struct scatterlist*, int, enum dma_data_direction);
++#endif
++
++#ifdef CONFIG_DMABOUNCE
++/*
++ * For SA-1111, IXP425, and ADI systems the dma-mapping functions are "magic"
++ * and utilize bounce buffers as needed to work around limited DMA windows.
++ *
++ * On the SA-1111, a bug limits DMA to only certain regions of RAM.
++ * On the IXP425, the PCI inbound window is 64MB (256MB total RAM)
++ * On some ADI engineering systems, PCI inbound window is 32MB (12MB total RAM)
++ *
++ * The following are helper functions used by the dmabounce subystem
++ *
++ */
++
++/**
++ * dmabounce_register_dev
++ *
++ * @dev: valid struct device pointer
++ * @small_buf_size: size of buffers to use with small buffer pool
++ * @large_buf_size: size of buffers to use with large buffer pool (can be 0)
++ *
++ * This function should be called by low-level platform code to register
++ * a device as requireing DMA buffer bouncing. The function will allocate
++ * appropriate DMA pools for the device.
++ *
++ */
++extern int dmabounce_register_dev(struct device *, unsigned long, unsigned long);
++
++/**
++ * dmabounce_unregister_dev
++ *
++ * @dev: valid struct device pointer
++ *
++ * This function should be called by low-level platform code when device
++ * that was previously registered with dmabounce_register_dev is removed
++ * from the system.
++ *
++ */
++extern void dmabounce_unregister_dev(struct device *);
++
++/**
++ * dma_needs_bounce
++ *
++ * @dev: valid struct device pointer
++ * @dma_handle: dma_handle of unbounced buffer
++ * @size: size of region being mapped
++ *
++ * Platforms that utilize the dmabounce mechanism must implement
++ * this function.
++ *
++ * The dmabounce routines call this function whenever a dma-mapping
++ * is requested to determine whether a given buffer needs to be bounced
++ * or not. The function must return 0 if the buffer is OK for
++ * DMA access and 1 if the buffer needs to be bounced.
++ *
++ */
++extern int dma_needs_bounce(struct device*, dma_addr_t, size_t);
++#endif /* CONFIG_DMABOUNCE */
++
++#endif /* __KERNEL__ */
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/elf.h linux-3.4.110/arch/nds32/include/asm/elf.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/elf.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/elf.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,145 @@
++/*
++ * linux/arch/nds32/include/asm/elf.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASMNDS32_ELF_H
++#define __ASMNDS32_ELF_H
++
++/*
++ * ELF register definitions..
++ */
++
++#include <asm/ptrace.h>
++#include <asm/user.h>
++
++typedef unsigned long elf_greg_t;
++typedef unsigned long elf_freg_t[3];
++
++extern unsigned int elf_hwcap;
++
++#define EM_NDS32 167
++
++
++#define R_NDS32_NONE 0
++#define R_NDS32_16_RELA 19
++#define R_NDS32_32_RELA 20
++#define R_NDS32_9_PCREL_RELA 22
++#define R_NDS32_15_PCREL_RELA 23
++#define R_NDS32_17_PCREL_RELA 24
++#define R_NDS32_25_PCREL_RELA 25
++#define R_NDS32_HI20_RELA 26
++#define R_NDS32_LO12S3_RELA 27
++#define R_NDS32_LO12S2_RELA 28
++#define R_NDS32_LO12S1_RELA 29
++#define R_NDS32_LO12S0_RELA 30
++#define R_NDS32_SDA15S3_RELA 31
++#define R_NDS32_SDA15S2_RELA 32
++#define R_NDS32_SDA15S1_RELA 33
++#define R_NDS32_SDA15S0_RELA 34
++#define R_NDS32_GOT20 37
++#define R_NDS32_25_PLTREL 38
++#define R_NDS32_COPY 39
++#define R_NDS32_GLOB_DAT 40
++#define R_NDS32_JMP_SLOT 41
++#define R_NDS32_RELATIVE 42
++#define R_NDS32_GOTOFF 43
++#define R_NDS32_GOTPC20 44
++#define R_NDS32_GOT_HI20 45
++#define R_NDS32_GOT_LO12 46
++#define R_NDS32_GOTPC_HI20 47
++#define R_NDS32_GOTPC_LO12 48
++#define R_NDS32_GOTOFF_HI20 49
++#define R_NDS32_GOTOFF_LO12 50
++#define R_NDS32_INSN16 51
++#define R_NDS32_LABEL 52
++#define R_NDS32_LONGCALL1 53
++#define R_NDS32_LONGCALL2 54
++#define R_NDS32_LONGCALL3 55
++#define R_NDS32_LONGJUMP1 56
++#define R_NDS32_LONGJUMP2 57
++#define R_NDS32_LONGJUMP3 58
++#define R_NDS32_LOADSTORE 59
++#define R_NDS32_9_FIXED_RELA 60
++#define R_NDS32_15_FIXED_RELA 61
++#define R_NDS32_17_FIXED_RELA 62
++#define R_NDS32_25_FIXED_RELA 63
++#define R_NDS32_PLTREL_HI20 64
++#define R_NDS32_PLTREL_LO12 65
++#define R_NDS32_PLT_GOTREL_HI20 66
++#define R_NDS32_PLT_GOTREL_LO12 67
++#define R_NDS32_LO12S0_ORI_RELA 72
++#define R_NDS32_DWARF2_OP1_RELA 77
++#define R_NDS32_DWARF2_OP2_RELA 78
++#define R_NDS32_DWARF2_LEB_RELA 79
++#define R_NDS32_WORD_9_PCREL_RELA 94
++#define R_NDS32_LONGCALL4 107
++#define R_NDS32_RELA_NOP_MIX 192
++#define R_NDS32_RELA_NOP_MAX 255
++
++#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
++typedef elf_greg_t elf_gregset_t[ELF_NGREG];
++
++typedef struct user_fp elf_fpregset_t;
++
++struct elf32_hdr;
++extern int elf_check_arch(const struct elf32_hdr *hdr);
++
++/*
++ * These are used to set parameters in the core dumps.
++ */
++#define ELF_CLASS ELFCLASS32
++#ifdef __NDS32_EB__
++#define ELF_DATA ELFDATA2MSB;
++#else
++#define ELF_DATA ELFDATA2LSB;
++#endif
++#define ELF_ARCH EM_NDS32
++#define USE_ELF_CORE_DUMP
++#define ELF_EXEC_PAGESIZE PAGE_SIZE
++
++/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
++ use of this is to invoke "./ld.so someprog" to test out a new version of
++ the loader. We need to make sure that it is out of the way of the program
++ that it will "exec", and that there is sufficient room for the brk. */
++
++#define ELF_ET_DYN_BASE (2 * TASK_SIZE / 3)
++
++/* When the program starts, a1 contains a pointer to a function to be
++ registered with atexit, as per the SVR4 ABI. A value of 0 means we
++ have no such handler. */
++#define ELF_PLAT_INIT(_r, load_addr) (_r)->NDS32_r0 = 0
++
++/* This yields a mask that user programs can use to figure out what
++ instruction set this cpu supports. */
++
++#define ELF_HWCAP (elf_hwcap)
++
++/* This yields a string that ld.so will use to load implementation
++ specific libraries for optimization. This is more specific in
++ intent than poking at uname or /proc/cpuinfo. */
++
++/* For now we just provide a fairly general string that describes the
++ processor family. This could be made more specific later if someone
++ implemented optimisations that require it. 26-bit CPUs give you
++ "v1l" for ARM2 (no SWP) and "v2l" for anything else (ARM1 isn't
++ supported). 32-bit CPUs give you "v3[lb]" for anything based on an
++ ARM6 or ARM7 core and "armv4[lb]" for anything based on a StrongARM-1
++ core. */
++
++#define ELF_PLATFORM_SIZE 16
++extern char elf_platform[];
++#define ELF_PLATFORM (elf_platform)
++
++#ifdef __KERNEL__
++
++/* Old NetWinder binaries were compiled in such a way that the iBCS
++ heuristic always trips on them. Until these binaries become uncommon
++ enough not to care, don't trust the `ibcs' flag here. In any case
++ there is no other ELF system currently supported by iBCS.
++ @@ Could print a warning message to encourage users to upgrade. */
++#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
++
++#endif
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/emergency-restart.h linux-3.4.110/arch/nds32/include/asm/emergency-restart.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/emergency-restart.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/emergency-restart.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/emergency-restart.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_EMERGENCY_RESTART_H__
++#define __NDS32_EMERGENCY_RESTART_H__
++
++#include <asm-generic/emergency-restart.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/errno.h linux-3.4.110/arch/nds32/include/asm/errno.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/errno.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/errno.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/errno.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_ERRNO_H__
++#define __NDS32_ERRNO_H__
++
++#include <asm-generic/errno.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/exec.h linux-3.4.110/arch/nds32/include/asm/exec.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/exec.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/exec.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,6 @@
++#ifndef __ASM_NDS32_EXEC_H
++#define __ASM_NDS32_EXEC_H
++
++#define arch_align_stack(x) (x)
++
++#endif /* __ASM_ARM_EXEC_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/fb.h linux-3.4.110/arch/nds32/include/asm/fb.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/fb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/fb.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,25 @@
++/*
++ * linux/arch/nds32/include/asm/fb.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_FB_H__
++#define __NDS32_FB_H__
++
++
++#include <linux/fb.h>
++#include <linux/fs.h>
++#include <asm/page.h>
++
++static inline void fb_pgprotect(struct file *file, struct vm_area_struct *vma,
++ unsigned long off)
++{
++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
++}
++
++static inline int fb_is_primary_device(struct fb_info *info)
++{
++ return 0;
++}
++
++#endif /* __NDS32_FB_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/fcntl.h linux-3.4.110/arch/nds32/include/asm/fcntl.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/fcntl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/fcntl.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,37 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1995, 96, 97, 98, 99, 2003, 05 Ralf Baechle
++ */
++#ifndef _ASM_FCNTL_H
++#define _ASM_FCNTL_H
++
++/*
++ * The flavours of struct flock. "struct flock" is the ABI compliant
++ * variant. Finally struct flock64 is the LFS variant of struct flock. As
++ * a historic accident and inconsistence with the ABI definition it doesn't
++ * contain all the same fields as struct flock.
++ */
++
++#ifdef CONFIG_32BIT
++#include <linux/types.h>
++
++struct flock {
++ short l_type;
++ short l_whence;
++ off_t l_start;
++ off_t l_len;
++ long l_sysid;
++ __kernel_pid_t l_pid;
++ long pad[4];
++};
++
++#define HAVE_ARCH_STRUCT_FLOCK
++
++#endif /* CONFIG_32BIT */
++
++#include <asm-generic/fcntl.h>
++
++#endif /* _ASM_FCNTL_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/fixmap.h linux-3.4.110/arch/nds32/include/asm/fixmap.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/fixmap.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/fixmap.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,88 @@
++/*
++ * fixmap.h: compile-time virtual memory allocation
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 1998 Ingo Molnar
++ *
++ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
++ */
++
++#ifndef __ASM_NDS32_FIXMAP_H
++#define __ASM_NDS32_FIXMAP_H
++
++#ifdef CONFIG_HIGHMEM
++#include <linux/threads.h>
++#include <asm/kmap_types.h>
++#endif
++
++/*
++ * Here we define all the compile-time 'special' virtual
++ * addresses. The point is to have a constant address at
++ * compile time, but to set the physical address only
++ * in the boot process. We allocate these special addresses
++ * from the end of the consistent memory region backwards.
++ * Also this lets us do fail-safe vmalloc(), we
++ * can guarantee that these special addresses and
++ * vmalloc()-ed addresses never overlap.
++ *
++ * these 'compile-time allocated' memory buffers are
++ * fixed-size 4k pages. (or larger if used with an increment
++ * higher than 1) use fixmap_set(idx,phys) to associate
++ * physical memory with fixmap indices.
++ *
++ * TLB entries of such buffers will not be flushed across
++ * task switches.
++ */
++enum fixed_addresses {
++ FIX_KMAP_RESERVED,
++ FIX_KMAP_BEGIN,
++#ifdef CONFIG_HIGHMEM
++ FIX_KMAP_END = FIX_KMAP_BEGIN + (KM_TYPE_NR * NR_CPUS),
++#endif
++#ifdef CONFIG_EARLY_PRINTK
++ FIX_EARLY_DEBUG,
++#endif
++ FIX_RETURN_SYSCALL,
++ __end_of_fixed_addresses
++};
++#define FIXADDR_TOP ((unsigned long) (-(16 * PAGE_SIZE)))
++#define FIXADDR_SIZE ((__end_of_fixed_addresses) << PAGE_SHIFT)
++#define FIXADDR_START (FIXADDR_TOP - FIXADDR_SIZE)
++
++#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
++#define __virt_to_fix(x) ((FIXADDR_TOP - ((x)&PAGE_MASK)) >> PAGE_SHIFT)
++
++#define __this_fixmap_does_not_exist() WARN_ON(1)
++/*
++ * 'index to address' translation. If anyone tries to use the idx
++ * directly without tranlation, we catch the bug with a NULL-deference
++ * kernel oops. Illegal ranges of incoming indices are caught too.
++ */
++
++static inline unsigned long fix_to_virt(const unsigned int idx)
++{
++ /*
++ * this branch gets completely eliminated after inlining,
++ * except when someone tries to use fixaddr indices in an
++ * illegal way. (such as mixing up address types or using
++ * out-of-range indices).
++ *
++ * If it doesn't get removed, the linker will complain
++ * loudly with a reasonably clear error message..
++ */
++ if (idx >= __end_of_fixed_addresses)
++ __this_fixmap_does_not_exist();
++
++ return __fix_to_virt(idx);
++}
++
++static inline unsigned long virt_to_fix(const unsigned long vaddr)
++{
++ BUG_ON(vaddr >= FIXADDR_TOP || vaddr < FIXADDR_START);
++ return __virt_to_fix(vaddr);
++}
++
++#endif /* __ASM_NDS32_FIXMAP_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/fpu.h linux-3.4.110/arch/nds32/include/asm/fpu.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/fpu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/fpu.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,100 @@
++/*
++ * linux/arch/nds32/include/asm/fpu.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASM_NDS32_FPU_H
++#define __ASM_NDS32_FPU_H
++
++#ifndef __ASSEMBLY__
++#include <linux/preempt.h>
++#include <asm/ptrace.h>
++
++extern void save_fpu(struct task_struct *__tsk);
++extern void fpload(struct fpu_struct *fpregs);
++extern void do_fpu_exception(unsigned long error_code, struct pt_regs *regs);
++extern int do_fpu_inst(unsigned short, struct pt_regs *);
++
++#ifdef CONFIG_FPU
++
++#define test_tsk_fpu(regs) (regs->NDS32_FUCOP_CTL & FUCOP_CTL_mskCP0EN)
++
++struct task_struct;
++
++static inline void release_fpu(struct pt_regs *regs)
++{
++ regs->NDS32_FUCOP_CTL &= ~FUCOP_CTL_mskCP0EN;
++}
++
++static inline void grab_fpu(struct pt_regs *regs)
++{
++ regs->NDS32_FUCOP_CTL |= FUCOP_CTL_mskCP0EN;
++}
++
++static inline void enable_fpu(void)
++{
++ SET_FUCOP_CTL(GET_FUCOP_CTL() | FUCOP_CTL_mskCP0EN);
++}
++
++static inline void disable_fpu(void)
++{
++ SET_FUCOP_CTL(GET_FUCOP_CTL() & ~FUCOP_CTL_mskCP0EN);
++}
++
++static inline void lose_fpu(int save)
++{
++ preempt_disable();
++ if (test_tsk_fpu(task_pt_regs(current))) {
++ if (save)
++ {
++ save_fpu(current);
++# ifndef CONFIG_UNLAZY_FPU
++ last_task_used_math=NULL;
++# endif
++ }
++ release_fpu(task_pt_regs(current));
++ }
++ preempt_enable();
++}
++
++static inline void own_fpu(int restore)
++{
++ preempt_disable();
++ if (!test_tsk_fpu(task_pt_regs(current))) {
++ if (restore)
++ {
++# ifdef CONFIG_UNLAZY_FPU
++ fpload(&current->thread.fpu);
++# else
++ if((last_task_used_math!=NULL)
++ &&(last_task_used_math!=current))
++ save_fpu(last_task_used_math);
++ fpload(&current->thread.fpu);
++ last_task_used_math=current;
++#endif
++ }
++ grab_fpu(task_pt_regs(current));
++ }
++ preempt_enable();
++}
++# ifdef CONFIG_UNLAZY_FPU
++static inline void unlazy_fpu(struct task_struct *tsk)
++{
++ preempt_disable();
++ if (test_tsk_fpu(task_pt_regs(tsk)))
++ save_fpu(tsk);
++ preempt_enable();
++}
++# endif /* CONFIG_UNLAZY_FPU */
++static inline void clear_fpu(struct pt_regs *regs)
++{
++ preempt_disable();
++ if (test_tsk_fpu(regs)) {
++ release_fpu(regs);
++ }
++ preempt_enable();
++}
++#endif /* CONFIG_FPU */
++#endif /* __ASSEMBLY__ */
++
++#endif /* __ASM_NDS32_FPU_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ftpci.h linux-3.4.110/arch/nds32/include/asm/ftpci.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/ftpci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/ftpci.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,30 @@
++/*
++ * linux/arch/nds32/include/asm/ftpci.h
++ *
++ * Faraday FTPCI010 PCI Bridge Device Driver Interface
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * ChangeLog
++ *
++ * Peter Liao 09/26/2005 Created, heavily modified from Faraday A320 platform code.
++ */
++
++#ifndef __FARADAY_PLATFORM_PCI_HEADER__
++#define __FARADAY_PLATFORM_PCI_HEADER__
++
++
++#define PCI_BRIDGE_DEVID 0x4321
++#define PCI_BRIDGE_VENID 0x159b
++
++extern int ftpci_probed;
++extern void ftpci_clear_irq(unsigned int irq);
++extern void ftpci_mask_irq(unsigned int irq);
++extern void ftpci_unmask_irq(unsigned int irq);
++extern int ftpci_get_irq(void);
++#endif /* __FARADAY_PLATFORM_PCI_HEADER__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ftrace.h linux-3.4.110/arch/nds32/include/asm/ftrace.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/ftrace.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/ftrace.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,17 @@
++#ifndef _ASM_POWERPC_FTRACE
++#define _ASM_POWERPC_FTRACE
++
++#ifdef CONFIG_FUNCTION_TRACER
++#define MCOUNT_ADDR ((long)(_mcount))
++#define MCOUNT_INSN_SIZE 4 /* sizeof mcount call */
++
++#ifdef __ASSEMBLY__
++
++#else /* !__ASSEMBLY__ */
++extern void _mcount(void);
++
++#endif /* __ASSEMBLY__ */
++
++#endif
++
++#endif /* _ASM_POWERPC_FTRACE */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/futex.h linux-3.4.110/arch/nds32/include/asm/futex.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/futex.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/futex.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/futex.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_FUTEX_H__
++#define __NDS32_FUTEX_H__
++
++#include <asm-generic/futex.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/glue.h linux-3.4.110/arch/nds32/include/asm/glue.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/glue.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/glue.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,26 @@
++/*
++ * linux/arch/nds32/include/asm/glue.h
++ *
++ * Copyright (C) 1997-1999 Russell King
++ * Copyright (C) 2000-2002 Deep Blue Solutions Ltd.
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This file provides the glue to stick the processor-specific bits
++ * into the kernel in an efficient manner. The idea is to use branches
++ * when we're only targetting one class of TLB, or indirect calls
++ * when we're targetting multiple classes of TLBs.
++ */
++#ifdef __KERNEL__
++
++#ifdef __STDC__
++#define ____glue(name,fn) name##fn
++#else
++#define ____glue(name,fn) name/**/fn
++#endif
++#define __glue(name,fn) ____glue(name,fn)
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/gpio.h linux-3.4.110/arch/nds32/include/asm/gpio.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/gpio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/gpio.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,10 @@
++#ifndef _ARCH_NDS32_GPIO_H
++#define _ARCH_NDS32_GPIO_H
++
++#include <asm-generic/gpio.h>
++#define gpio_get_value __gpio_get_value
++#define gpio_set_value __gpio_set_value
++#define gpio_cansleep __gpio_cansleep
++#define gpio_to_irq __gpio_to_irq
++
++#endif /* _ARCH_NDS32_GPIO_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/hardirq.h linux-3.4.110/arch/nds32/include/asm/hardirq.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/hardirq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/hardirq.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,36 @@
++/*
++ * linux/arch/nds32/include/asm/hardirq.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++#ifndef __ASM_HARDIRQ_H
++#define __ASM_HARDIRQ_H
++
++#include <linux/cache.h>
++#include <linux/threads.h>
++#include <asm/irq.h>
++
++typedef struct {
++ unsigned int __softirq_pending;
++} ____cacheline_aligned irq_cpustat_t;
++
++#include <linux/irq_cpustat.h> /* Standard mappings for irq_cpustat_t above */
++
++#if NR_IRQS > 256
++#define HARDIRQ_BITS 9
++#else
++#define HARDIRQ_BITS 8
++#endif
++
++/*
++ * The hardirq mask has to be large enough to have space
++ * for potentially all IRQ sources in the system nesting
++ * on a single CPU:
++ */
++#if (1 << HARDIRQ_BITS) < NR_IRQS
++# error HARDIRQ_BITS is too low!
++#endif
++
++#define __ARCH_IRQ_EXIT_IRQS_DISABLED 1
++
++extern void ack_bad_irq(unsigned int irq);
++#endif /* __ASM_HARDIRQ_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/hardware.h linux-3.4.110/arch/nds32/include/asm/hardware.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/hardware.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/hardware.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,61 @@
++/*
++ * linux/arch/nds32/include/asm/hardware.h
++ *
++ * Faraday Platform Independent Hardware Configuration
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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
++ *
++ * ChangeLog
++ *
++ * Luke Lee 09/16/2005 Created.
++ * Peter Liao 10/04/2005 Modified for uClinux
++ * Harry Pan 11/02/2007 Added REGxx macros.
++ */
++
++#ifndef __FARADAY_PLATFORM_HARDWARE_HEADER__
++#define __FARADAY_PLATFORM_HARDWARE_HEADER__
++
++#include <asm/spec.h>
++
++#ifndef PCIBIOS_MIN_IO
++/* the mini io address is 0x6000,that is IO will allocate from 0-0x6000 offset*/
++#define PCIBIOS_MIN_IO 0x0
++#endif
++
++#ifndef PCIBIOS_MIN_MEM
++/* the mini MEM address is 0x100000,that is MEM will allocate from 0-0x100000 offset*/
++#define PCIBIOS_MIN_MEM 0x0
++#endif
++
++#define pcibios_assign_all_busses() 1
++
++/* Pliauo add 5 to resolve __alloc_bootmem_core return NULL pointer in bootmem.c */
++#if defined(CPU_MEM_PA_BASE) && defined(CPU_MEM_PA_SIZE)
++ #define PA_SDRAM_BASE (CPU_MEM_PA_BASE)
++#else
++ #define PA_SDRAM_BASE (0x00000000)
++#endif
++
++/*
++ * Define a simple register accessing method by Harry@Nov.02.2007
++ */
++#define REG32(a) (*(volatile unsigned int *)(a))
++#define REG16(a) (*(volatile unsigned short *)(a))
++#define REG8(a) (*(volatile unsigned char *)(a))
++
++#endif /* __FARADAY_PLATFORM_HARDWARE_HEADER__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/highmem.h linux-3.4.110/arch/nds32/include/asm/highmem.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/highmem.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/highmem.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,61 @@
++#ifndef _ASM_HIGHMEM_H
++#define _ASM_HIGHMEM_H
++
++#include <asm/kmap_types.h>
++#include <asm/fixmap.h>
++#include <asm/pgtable.h>
++
++/*
++ * Right now we initialize only a single pte table. It can be extended
++ * easily, subsequent pte tables have to be allocated in one physical
++ * chunk of RAM.
++ */
++/*
++ * Ordering is (from lower to higher memory addresses):
++ *
++ * high_memory
++ * Persistent kmap area
++ * PKMAP_BASE
++ * fixed_addresses
++ * FIXADDR_START
++ * FIXADDR_TOP
++ * Vmalloc area
++ * VMALLOC_START
++ * VMALLOC_END
++ */
++#define PKMAP_BASE ((FIXADDR_START - PGDIR_SIZE) & (PGDIR_MASK))
++#define LAST_PKMAP PTRS_PER_PTE
++#define LAST_PKMAP_MASK (LAST_PKMAP - 1)
++#define PKMAP_NR(virt) (((virt) - (PKMAP_BASE)) >> PAGE_SHIFT)
++#define PKMAP_ADDR(nr) (PKMAP_BASE + ((nr) << PAGE_SHIFT))
++#define kmap_prot PAGE_KERNEL
++
++static inline void flush_cache_kmaps(void)
++{
++ cpu_dcache_wbinval_all();
++}
++
++/* declarations for highmem.c */
++extern unsigned long highstart_pfn, highend_pfn;
++
++extern pte_t *pkmap_page_table;
++
++extern void *kmap_high(struct page *page);
++extern void kunmap_high(struct page *page);
++
++extern void kmap_init(void);
++
++/*
++ * The following functions are already defined by <linux/highmem.h>
++ * when CONFIG_HIGHMEM is not set.
++ */
++#ifdef CONFIG_HIGHMEM
++extern void *kmap(struct page *page);
++extern void kunmap(struct page *page);
++extern void *kmap_atomic(struct page *page);
++extern void __kunmap_atomic(void *kvaddr);
++extern void *kmap_atomic_pfn(unsigned long pfn);
++extern struct page *kmap_atomic_to_page(void *ptr);
++#endif
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/hw_irq.h linux-3.4.110/arch/nds32/include/asm/hw_irq.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/hw_irq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/hw_irq.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/hw_irq.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_HW_IRQ_H__
++#define __NDS32_HW_IRQ_H__
++
++
++#endif /* __NDS32_HW_IRQ_H__ */
++
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/intc.h linux-3.4.110/arch/nds32/include/asm/intc.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/intc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/intc.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,45 @@
++/*
++ * linux/arch/nds32/include/asm/intc.h
++ *
++ * Faraday FTINTC010 Interrupt Controller Device Driver Interface
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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
++ *
++ * ChangeLog
++ *
++ * Luke Lee 09/14/2005 Created, heavily modified from Faraday CPE platform code.
++ */
++
++#ifndef __FARADAY_INTC_FTINTC010_HEADER__
++#define __FARADAY_INTC_FTINTC010_HEADER__
++
++#define IRQ_SOURCE_REG 0
++#define IRQ_MASK_REG 0x04
++#define IRQ_CLEAR_REG 0x08
++#define IRQ_MODE_REG 0x0c
++#define IRQ_LEVEL_REG 0x10
++#define IRQ_STATUS_REG 0x14
++
++#define FIQ_SOURCE_REG 0x20
++#define FIQ_MASK_REG 0x24
++#define FIQ_CLEAR_REG 0x28
++#define FIQ_MODE_REG 0x2c
++#define FIQ_LEVEL_REG 0x30
++#define FIQ_STATUS_REG 0x34
++
++#endif /* __FARADAY_INTC_FTINTC010_HEADER__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ioctl.h linux-3.4.110/arch/nds32/include/asm/ioctl.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/ioctl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/ioctl.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/ioctl.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_IOCTL_H__
++#define __NDS32_IOCTL_H__
++
++#include <asm-generic/ioctl.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ioctls.h linux-3.4.110/arch/nds32/include/asm/ioctls.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/ioctls.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/ioctls.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,13 @@
++/*
++ * linux/arch/nds32/include/asm/ioctls.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASM_NDS32_IOCTLS_H
++#define __ASM_NDS32_IOCTLS_H
++
++#define FIOQSIZE 0x545E
++
++#include <asm-generic/ioctls.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/io.h linux-3.4.110/arch/nds32/include/asm/io.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/io.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/io.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,343 @@
++/*
++ * linux/arch/nds32/include/asm/io.h
++ *
++ * Copyright (C) 1996-2000 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Modifications:
++ * 16-Sep-1996 RMK Inlined the inx/outx functions & optimised for both
++ * constant addresses and variable addresses.
++ * 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture
++ * specific IO header files.
++ * 27-Mar-1999 PJB Second parameter of memcpy_toio is const..
++ * 04-Apr-1999 PJB Added check_signature.
++ * 12-Dec-1999 RMK More cleanups
++ * 18-Jun-2000 RMK Removed virt_to_* and friends definitions
++ * 05-Oct-2004 BJD Moved memory string functions to use void __iomem
++ */
++#ifndef __ASM_NDS32_IO_H
++#define __ASM_NDS32_IO_H
++
++#ifdef __KERNEL__
++
++#include <linux/types.h>
++#include <asm/byteorder.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm-generic/iomap.h>
++
++
++/*
++ * ISA I/O bus memory addresses are 1:1 with the physical address.
++ */
++#define isa_virt_to_bus virt_to_phys
++#define isa_page_to_bus page_to_phys
++#define isa_bus_to_virt phys_to_virt
++
++/*
++ * Generic IO read/write. These perform native-endian accesses. Note
++ * that some architectures will want to re-define __raw_{read,write}w.
++ */
++
++#define __raw_writeb(v,a) (*(volatile unsigned char __force *)(a) = (v))
++#define __raw_writew(v,a) (*(volatile unsigned short __force *)(a) = (v))
++#define __raw_writel(v,a) (*(volatile unsigned int __force *)(a) = (v))
++
++#define __raw_readb(a) (*(volatile unsigned char __force *)(a))
++#define __raw_readw(a) (*(volatile unsigned short __force *)(a))
++#define __raw_readl(a) (*(volatile unsigned int __force *)(a))
++
++/*
++ * Bad read/write accesses...
++ */
++extern void __readwrite_bug(const char *fn);
++
++/*
++ * Now, pick up the machine-defined IO definitions
++ */
++#ifndef __FARADAY_PLATFORM_IO_HEADER__
++#define __FARADAY_PLATFORM_IO_HEADER__
++
++#include <linux/compiler.h>
++#include <asm/spec.h>
++
++#ifndef IO_SPACE_LIMIT
++#define IO_SPACE_LIMIT 0xffffffff
++#endif
++
++#ifndef __io
++#define __io(a) ((void __iomem *)(a))
++#endif
++#define IO_ADDRESS(a) __io(a)
++#ifndef __mem_pci
++#define __mem_pci(a) (a)
++#endif
++
++#endif
++
++#ifdef __io_pci
++#warning machine class uses buggy __io_pci
++#endif
++#if defined(__arch_putb) || defined(__arch_putw) || defined(__arch_putl) || \
++ defined(__arch_getb) || defined(__arch_getw) || defined(__arch_getl)
++//-Tom for debug
++//#warning machine class uses old __arch_putw or __arch_getw
++#endif
++
++/*
++ * IO port access primitives
++ * -------------------------
++ *
++ * The ARM doesn't have special IO access instructions; all IO is memory
++ * mapped. Note that these are defined to perform little endian accesses
++ * only. Their primary purpose is to access PCI and ISA peripherals.
++ *
++ * Note that for a big endian machine, this implies that the following
++ * big endian mode connectivity is in place, as described by numerious
++ * ARM documents:
++ *
++ * PCI: D0-D7 D8-D15 D16-D23 D24-D31
++ * ARM: D24-D31 D16-D23 D8-D15 D0-D7
++ *
++ * The machine specific io.h include defines __io to translate an "IO"
++ * address to a memory address.
++ *
++ * Note that we prevent GCC re-ordering or caching values in expressions
++ * by introducing sequence points into the in*() definitions. Note that
++ * __raw_* do not guarantee this behaviour.
++ *
++ * The {in,out}[bwl] macros are for emulating x86-style PCI/ISA IO space.
++ */
++#ifdef __io
++#ifdef __NDS32_EB__
++#define inw(p) ({ unsigned int __v = be16_to_cpu(__raw_readw(__io(p))); __v; })
++#define inl(p) ({ unsigned int __v = be32_to_cpu(__raw_readl(__io(p))); __v; })
++#define outw(v,p) __raw_writew(cpu_to_be16(v),__io(p))
++#define outl(v,p) __raw_writel(cpu_to_be32(v),__io(p))
++#else
++#define inw(p) ({ unsigned int __v = le16_to_cpu(__raw_readw(__io(p))); __v; })
++#define inl(p) ({ unsigned int __v = le32_to_cpu(__raw_readl(__io(p))); __v; })
++#define outw(v,p) __raw_writew(cpu_to_le16(v),__io(p))
++#define outl(v,p) __raw_writel(cpu_to_le32(v),__io(p))
++#endif
++
++#define inb(p) ({ unsigned int __v = __raw_readb(__io(p)); __v; })
++#define outb(v,p) __raw_writeb(v,__io(p))
++
++#endif
++
++#define outb_p(val,port) outb((val),(port))
++#define outw_p(val,port) outw((val),(port))
++#define outl_p(val,port) outl((val),(port))
++#define inb_p(port) inb((port))
++#define inw_p(port) inw((port))
++#define inl_p(port) inl((port))
++
++/*
++ * String version of IO memory access ops:
++ */
++extern void _memcpy_fromio(void *, const volatile void __iomem *, size_t);
++extern void _memcpy_toio(volatile void __iomem *, const void *, size_t);
++extern void _memset_io(volatile void __iomem *, int, size_t);
++
++#define mmiowb()
++
++/*
++ * Memory access primitives
++ * ------------------------
++ *
++ * These perform PCI memory accesses via an ioremap region. They don't
++ * take an address as such, but a cookie.
++ *
++ * Again, this are defined to perform little endian accesses. See the
++ * IO port primitives for more information.
++ */
++#ifdef __mem_pci
++#ifdef __NDS32_EB__
++#define readw(c) ({ unsigned int __v = be16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
++#define readl(c) ({ unsigned int __v = be32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
++#define writew(v,c) __raw_writew(cpu_to_be16(v),__mem_pci(c))
++#define writel(v,c) __raw_writel(cpu_to_be32(v),__mem_pci(c))
++#else
++#define readw(c) ({ unsigned int __v = le16_to_cpu(__raw_readw(__mem_pci(c))); __v; })
++#define readl(c) ({ unsigned int __v = le32_to_cpu(__raw_readl(__mem_pci(c))); __v; })
++#define writew(v,c) __raw_writew(cpu_to_le16(v),__mem_pci(c))
++#define writel(v,c) __raw_writel(cpu_to_le32(v),__mem_pci(c))
++#endif
++
++#define readb(c) ({ unsigned int __v = __raw_readb(__mem_pci(c)); __v; })
++#define writeb(v,c) __raw_writeb(v,__mem_pci(c))
++
++#define readb_relaxed(addr) readb(addr)
++#define readw_relaxed(addr) readw(addr)
++#define readl_relaxed(addr) readl(addr)
++
++#define memset_io(c,v,l) _memset_io(__mem_pci(c),(v),(l))
++#define memcpy_fromio(a,c,l) _memcpy_fromio((a),__mem_pci(c),(l))
++#define memcpy_toio(c,a,l) _memcpy_toio(__mem_pci(c),(a),(l))
++
++#define eth_io_copy_and_sum(s,c,l,b) \
++ eth_copy_and_sum((s),__mem_pci(c),(l),(b))
++
++#elif !defined(readb)
++
++#define readb(c) (__readwrite_bug("readb"),0)
++#define readw(c) (__readwrite_bug("readw"),0)
++#define readl(c) (__readwrite_bug("readl"),0)
++#define writeb(v,c) __readwrite_bug("writeb")
++#define writew(v,c) __readwrite_bug("writew")
++#define writel(v,c) __readwrite_bug("writel")
++
++#define eth_io_copy_and_sum(s,c,l,b) __readwrite_bug("eth_io_copy_and_sum")
++
++#endif /* __mem_pci */
++
++/*
++ * If this architecture has ISA IO, then define the isa_read/isa_write
++ * macros.
++ */
++#ifdef __mem_isa
++
++#define isa_readb(addr) __raw_readb(__mem_isa(addr))
++#define isa_readw(addr) __raw_readw(__mem_isa(addr))
++#define isa_readl(addr) __raw_readl(__mem_isa(addr))
++#define isa_writeb(val,addr) __raw_writeb(val,__mem_isa(addr))
++#define isa_writew(val,addr) __raw_writew(val,__mem_isa(addr))
++#define isa_writel(val,addr) __raw_writel(val,__mem_isa(addr))
++#define isa_memset_io(a,b,c) _memset_io(__mem_isa(a),(b),(c))
++#define isa_memcpy_fromio(a,b,c) _memcpy_fromio((a),__mem_isa(b),(c))
++#define isa_memcpy_toio(a,b,c) _memcpy_toio(__mem_isa((a)),(b),(c))
++
++#define isa_eth_io_copy_and_sum(a,b,c,d) \
++ eth_copy_and_sum((a),__mem_isa(b),(c),(d))
++
++#else /* __mem_isa */
++
++#define isa_readb(addr) (__readwrite_bug("isa_readb"),0)
++#define isa_readw(addr) (__readwrite_bug("isa_readw"),0)
++#define isa_readl(addr) (__readwrite_bug("isa_readl"),0)
++#define isa_writeb(val,addr) __readwrite_bug("isa_writeb")
++#define isa_writew(val,addr) __readwrite_bug("isa_writew")
++#define isa_writel(val,addr) __readwrite_bug("isa_writel")
++#define isa_memset_io(a,b,c) __readwrite_bug("isa_memset_io")
++#define isa_memcpy_fromio(a,b,c) __readwrite_bug("isa_memcpy_fromio")
++#define isa_memcpy_toio(a,b,c) __readwrite_bug("isa_memcpy_toio")
++
++#define isa_eth_io_copy_and_sum(a,b,c,d) \
++ __readwrite_bug("isa_eth_io_copy_and_sum")
++
++#endif /* __mem_isa */
++
++/*
++ * ioremap and friends.
++ *
++ * ioremap takes a PCI memory address, as specified in
++ * Documentation/IO-mapping.txt.
++ */
++extern void __iomem * __ioremap(unsigned long, size_t, unsigned long, unsigned long);
++extern void __iounmap(void __iomem *addr);
++
++#ifndef __arch_ioremap
++#define ioremap(cookie,size) __ioremap(cookie,size,0,1)
++#define ioremap_nocache(cookie,size) __ioremap(cookie,size,0,1)
++#define iounmap(cookie) __iounmap(cookie)
++#else
++#define ioremap(cookie,size) __arch_ioremap((cookie),(size),0,1)
++#define ioremap_nocache(cookie,size) __arch_ioremap((cookie),(size),0,1)
++#define iounmap(cookie) __arch_iounmap(cookie)
++#endif
++
++/*
++ * can the hardware map this into one segment or not, given no other
++ * constraints.
++ */
++#define BIOVEC_MERGEABLE(vec1, vec2) \
++ ((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2)))
++
++/*
++ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
++ * access
++ */
++#define xlate_dev_mem_ptr(p) __va(p)
++
++/*
++ * Convert a virtual cached pointer to an uncached pointer
++ */
++#define xlate_dev_kmem_ptr(p) p
++static inline void readsb(const void __iomem *addr, void * data, int bytelen)
++{
++ unsigned char *ptr = (unsigned char *)addr;
++ unsigned char *ptr2 = (unsigned char *)data;
++ while(bytelen) {
++ *ptr2 = *ptr;
++ ptr2++;
++ bytelen--;
++ }
++}
++
++static inline void readsw(const void __iomem *addr, void * data, int wordlen)
++{
++ unsigned short *ptr = (unsigned short *)addr;
++ unsigned short *ptr2 = (unsigned short *)data;
++ while(wordlen) {
++ *ptr2 = *ptr;
++ ptr2++;
++ wordlen--;
++ }
++}
++
++static inline void readsl(const void __iomem *addr, void * data, int longlen)
++{
++ unsigned int *ptr = (unsigned int *)addr;
++ unsigned int *ptr2 = (unsigned int *)data;
++ while(longlen) {
++ *ptr2 = *ptr;
++ ptr2++;
++ longlen--;
++ }
++}
++static inline void writesb(void __iomem *addr, const void * data, int bytelen)
++{
++ unsigned char *ptr = (unsigned char *)addr;
++ unsigned char *ptr2 = (unsigned char *)data;
++ while(bytelen) {
++ *ptr = *ptr2;
++ ptr2++;
++ bytelen--;
++ }
++}
++static inline void writesw(void __iomem *addr, const void * data, int wordlen)
++{
++ unsigned short *ptr = (unsigned short *)addr;
++ unsigned short *ptr2 = (unsigned short *)data;
++ while(wordlen) {
++ *ptr = *ptr2;
++ ptr2++;
++ wordlen--;
++ }
++}
++static inline void writesl(void __iomem *addr, const void * data, int longlen)
++{
++ unsigned int *ptr = (unsigned int *)addr;
++ unsigned int *ptr2 = (unsigned int *)data;
++ while(longlen) {
++ *ptr = *ptr2;
++ ptr2++;
++ longlen--;
++ }
++}
++
++
++#define insb(p,d,l) BUG()
++#define insw(p,d,l) BUG()
++#define insl(p,d,l) BUG()
++#define outsb(p,d,l) BUG()
++#define outsw(p,d,l) BUG()
++#define outsl(p,d,l) BUG()
++
++#endif /* __KERNEL__ */
++#endif /* __ASM_NDS32_IO_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ipcbuf.h linux-3.4.110/arch/nds32/include/asm/ipcbuf.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/ipcbuf.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/ipcbuf.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,34 @@
++/*
++ * linux/arch/nds32/include/asm/ipcbuf.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASMNDS32_IPCBUF_H
++#define __ASMNDS32_IPCBUF_H
++
++/*
++ * The ipc64_perm structure for arm architecture.
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 32-bit mode_t and seq
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct ipc64_perm
++{
++ __kernel_key_t key;
++ __kernel_uid32_t uid;
++ __kernel_gid32_t gid;
++ __kernel_uid32_t cuid;
++ __kernel_gid32_t cgid;
++ __kernel_mode_t mode;
++ unsigned short __pad1;
++ unsigned short seq;
++ unsigned short __pad2;
++ unsigned long __unused1;
++ unsigned long __unused2;
++};
++
++#endif /* __ASMNDS32_IPCBUF_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/irqflags.h linux-3.4.110/arch/nds32/include/asm/irqflags.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/irqflags.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/irqflags.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,65 @@
++/*
++ * linux/arch/nds32/include/asm/irqflags.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#include <asm/nds32.h>
++#include <asm/assembler.h>
++
++#define arch_local_irq_disable() \
++ GIE_DISABLE();
++
++#define arch_local_irq_enable() \
++ GIE_ENABLE();
++static inline unsigned long arch_local_irq_save(void)
++{
++ unsigned long flags;
++ __asm__ __volatile__(
++ "mfsr %0, $PSW\n"
++ "andi %0, %0, #0x1\n"
++ "gie_disable\n"
++ : "=r" (flags) );
++ return flags;
++}
++static inline unsigned long arch_local_save_flags(void)
++{
++ unsigned long flags;
++ __asm__ __volatile__(
++ "mfsr %0, $PSW\n"
++ "andi %0, %0, #0x1"
++ : "=r" (flags) );
++ return flags;
++}
++static inline void arch_local_irq_restore(unsigned long flags)
++{
++ __asm__ __volatile__(
++ "beqz %0, 1f\n"
++ "gie_enable\n"
++ "1:"
++ :: "r" (flags) );
++}
++static inline int arch_irqs_disabled_flags(unsigned long flags)
++{
++ return !flags;
++}
++#if 0
++#define raw_local_irq_save(x) \
++ __asm__ __volatile__( \
++ "mfsr %0, $PSW\n" \
++ "andi %0, %0, #0x1\n" \
++ "gie_disable\n" \
++ : "=r" (x) )
++#define raw_local_save_flags(x) \
++ __asm__ __volatile__( \
++ "mfsr %0, $PSW\n" \
++ "andi %0, %0, #0x1" \
++ : "=r" (x) )
++#define raw_local_irq_restore(x) \
++ __asm__ __volatile__( \
++ "beqz %0, 1f\n" \
++ "gie_enable\n" \
++ "1:" \
++ :: "r" (x) )
++
++#define raw_irqs_disabled_flags(x) !(x)
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/irq.h linux-3.4.110/arch/nds32/include/asm/irq.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/irq.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/irq.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,50 @@
++/*
++ * linux/arch/nds32/include/asm/irq.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASM_NDS32_IRQ_H
++#define __ASM_NDS32_IRQ_H
++
++#include <asm/spec.h>
++
++#ifndef irq_canonicalize
++#define irq_canonicalize(i) (i)
++#endif
++
++#ifndef NR_IRQS
++#define NR_IRQS 128
++#endif
++
++/*
++ * Use this value to indicate lack of interrupt
++ * capability
++ */
++#ifndef NO_IRQ
++#define NO_IRQ ((unsigned int)(-1))
++#endif
++
++struct irqaction;
++
++extern void disable_irq_nosync(unsigned int);
++extern void disable_irq(unsigned int);
++extern void enable_irq(unsigned int);
++
++#define __IRQT_FALEDGE IRQ_TYPE_EDGE_FALLING
++#define __IRQT_RISEDGE IRQ_TYPE_EDGE_RISING
++#define __IRQT_LOWLVL IRQ_TYPE_LEVEL_LOW
++#define __IRQT_HIGHLVL IRQ_TYPE_LEVEL_HIGH
++
++#define IRQT_NOEDGE (0)
++#define IRQT_RISING (__IRQT_RISEDGE)
++#define IRQT_FALLING (__IRQT_FALEDGE)
++#define IRQT_BOTHEDGE (__IRQT_RISEDGE|__IRQT_FALEDGE)
++#define IRQT_LOW (__IRQT_LOWLVL)
++#define IRQT_HIGH (__IRQT_HIGHLVL)
++#define IRQT_PROBE IRQ_TYPE_PROBE
++
++struct irqaction;
++struct pt_regs;
++
++#endif
++
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/irq_regs.h linux-3.4.110/arch/nds32/include/asm/irq_regs.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/irq_regs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/irq_regs.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,9 @@
++/*
++ * linux/arch/nds32/include/asm/irq_regs.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_IRQ_REGS_H__
++#define __NDS32_IRQ_REGS_H__
++#include <asm-generic/irq_regs.h>
++#endif /* __NDS32_IRQ_REGS_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/Kbuild linux-3.4.110/arch/nds32/include/asm/Kbuild
+--- linux-3.4.110.orig/arch/nds32/include/asm/Kbuild 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/Kbuild 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,3 @@
++include include/asm-generic/Kbuild.asm
++
++header-y += pfm.h
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kdebug.h linux-3.4.110/arch/nds32/include/asm/kdebug.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/kdebug.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/kdebug.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,14 @@
++/*
++ * linux/arch/nds32/include/asm/kdebug.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_KDEBUG_H__
++#define __NDS32_KDEBUG_H__
++
++enum die_val {
++ DIE_OOPS = 1,
++ DIE_DEBUG,
++};
++
++#endif /* __NDS32_KDEBUG_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kexec.h linux-3.4.110/arch/nds32/include/asm/kexec.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/kexec.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/kexec.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,31 @@
++#ifndef _NDS32_KEXEC_H
++#define _NDS32_KEXEC_H
++
++#ifdef CONFIG_KEXEC
++
++/* Maximum physical address we can use pages from */
++#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
++/* Maximum address we can reach in physical address mode */
++#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL)
++/* Maximum address we can use for the control code buffer */
++#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL)
++
++#define KEXEC_CONTROL_PAGE_SIZE 4096
++
++#define KEXEC_ARCH KEXEC_ARCH_NDS32
++
++#define KEXEC_NDS32_ATAGS_OFFSET 0x1000
++#define KEXEC_NDS32_ZIMAGE_OFFSET 0x500000
++
++#ifndef __ASSEMBLY__
++
++struct kimage;
++/* Provide a dummy definition to avoid build failures. */
++static inline void crash_setup_regs(struct pt_regs *newregs,
++ struct pt_regs *oldregs) { }
++
++#endif /* __ASSEMBLY__ */
++
++#endif /* CONFIG_KEXEC */
++
++#endif /* _NDS32_KEXEC_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kgdb.h linux-3.4.110/arch/nds32/include/asm/kgdb.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/kgdb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/kgdb.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,90 @@
++/* ============================================================================
++ *
++ * linux/arch/nds32/include/asm/kgdb.h
++ *
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is for NDS32 KGDB support.
++ *
++ * Author: Harry Pan
++ *
++ * Revision History:
++ *
++ * Jul.14.2007 Initial ported by Harry.
++ *
++ * Note:
++ *
++ * ============================================================================
++ */
++#ifndef __ASM_NDS32_KGDB_H__
++#define __ASM_NDS32_KGDB_H__
++
++#include <asm/ptrace.h>
++
++#define BREAK_INSTR_SIZE 2
++#define CACHE_FLUSH_IS_SAFE 1
++
++#ifndef __ASSEMBLY__
++
++/*
++ * Define numbers of registers we have in NDS32 arch
++ */
++#define NDS32_NUM_GR 32 // general registers.
++#define NDS32_NUM_SPR 5 // special registers. (PC, D0, D1)
++#define NDS32_NUM_CR 6 // ctrl registers.
++#define NDS32_NUM_IR 16 // interruption registers.
++#define NDS32_NUM_MR 11 // MMU registers.
++#define NDS32_NUM_DR 48 // debug registers.
++#define NDS32_NUM_PFR 4 // performance monitoring registers.
++#define NDS32_NUM_DMAR 11 // local memory DMA registers
++#define NDS32_NUM_RACR 1 // resource access control registers.
++#define NDS32_NUM_IDR 2 // implementation dependent registers.
++#define NDS32_NUM_SR (NDS32_NUM_CR + NDS32_NUM_IR + NDS32_NUM_MR + \
++ NDS32_NUM_DR + NDS32_NUM_PFR + NDS32_NUM_DMAR + \
++ NDS32_NUM_RACR + NDS32_NUM_IDR)
++#define NDS32_NUM_REGS (NDS32_NUM_GR + NDS32_NUM_SPR + NDS32_NUM_SR)
++
++#define KGDB_MAX_NO_CPUS 1
++#define BUFMAX 2048
++#define NUMREGBYTES (NDS32_NUM_REGS << 2)
++
++/*
++ * NDS32 virtual registers layout for GDB.
++ */
++enum nds32_regnum
++{
++ NDS32_R0_REGNUM = 0, // first integer-like argument.
++ NDS32_R5_REGNUM = 5, // last integer-like argument.
++ NDS32_FP_REGNUM = 28, // frame register
++ NDS32_LP_REGNUM = 30, // link pointer
++ NDS32_SP_REGNUM = 31, // address of stack top.
++ NDS32_PC_REGNUM = 32,
++ NDS32_D0LO_REGNUM = 33,
++ NDS32_D0HI_REGNUM = 34,
++ NDS32_D1LO_REGNUM = 35,
++ NDS32_D1HI_REGNUM = 36,
++ NDS32_CR0_REGNUM = 37,
++ NDS32_IR0_REGNUM = (NDS32_CR0_REGNUM + NDS32_NUM_CR),
++ NDS32_MR0_REGNUM = (NDS32_IR0_REGNUM + NDS32_NUM_IR),
++ NDS32_DR0_REGNUM = (NDS32_MR0_REGNUM + NDS32_NUM_MR),
++ NDS32_PFR0_REGNUM = (NDS32_DR0_REGNUM + NDS32_NUM_DR),
++ NDS32_DMAR0_REGNUM = (NDS32_PFR0_REGNUM + NDS32_NUM_PFR),
++ NDS32_RACR0_REGNUM = (NDS32_DMAR0_REGNUM + NDS32_NUM_DMAR),
++ NDS32_IDR0_REGNUM = (NDS32_RACR0_REGNUM + NDS32_NUM_RACR),
++ /* nds32 calling convention. */
++ NDS32_ARG0_REGNUM = NDS32_R0_REGNUM,
++ NDS32_ARGN_REGNUM = NDS32_R5_REGNUM,
++ NDS32_RET_REGNUM = NDS32_R0_REGNUM,
++};
++
++static inline void arch_kgdb_breakpoint(void)
++{
++ asm __volatile__ ( "break 0x1ff\n" );
++}
++
++#endif /* !__ASSEMBLY__ */
++#endif /* __ASM_NDS32_KGDB_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kmap_types.h linux-3.4.110/arch/nds32/include/asm/kmap_types.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/kmap_types.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/kmap_types.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,29 @@
++/*
++ * linux/arch/nds32/include/asm/kmap-types.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_KMAP_TYPES_H
++#define __NDS32_KMAP_TYPES_H
++
++/*
++ * This is the "bare minimum". AIO seems to require this.
++ */
++enum km_type {
++ KM_BOUNCE_READ,
++ KM_SKB_SUNRPC_DATA,
++ KM_SKB_DATA_SOFTIRQ,
++ KM_USER0,
++ KM_USER1,
++ KM_BIO_SRC_IRQ,
++ KM_BIO_DST_IRQ,
++ KM_PTE0,
++ KM_PTE1,
++ KM_IRQ0,
++ KM_IRQ1,
++ KM_SOFTIRQ0,
++ KM_SOFTIRQ1,
++ KM_TYPE_NR
++};
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kprobes.h linux-3.4.110/arch/nds32/include/asm/kprobes.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/kprobes.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/kprobes.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,86 @@
++#ifndef _ASM_ANDES_KPROBES_H
++#define _ASM_ANDES_KPROBES_H
++/*
++ * Kernel Probes (KProbes)
++ *
++ * 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.
++ *
++ * Copyright (C) IBM Corporation, 2002, 2004
++ *
++ * See arch/x86/kernel/kprobes.c for x86 kprobes history.
++ */
++#include <linux/types.h>
++#include <linux/ptrace.h>
++#include <linux/percpu.h>
++
++#define __ARCH_WANT_KPROBES_INSN_SLOT
++
++struct pt_regs;
++struct kprobe;
++
++typedef unsigned short kprobe_opcode_t;
++
++#define MAX_INSN_SIZE 2
++#define MAX_STACK_SIZE 64
++#define MIN_STACK_SIZE(ADDR) \
++ (((MAX_STACK_SIZE) < (((unsigned long)current_thread_info()) + \
++ THREAD_SIZE - (unsigned long)(ADDR))) \
++ ? (MAX_STACK_SIZE) \
++ : (((unsigned long)current_thread_info()) + \
++ THREAD_SIZE - (unsigned long)(ADDR)))
++#define regs_return_value(regs) ((regs)->NDS32_r0)
++#define flush_insn_slot(p) do { } while (0)
++#define kretprobe_blacklist_size 0
++
++void arch_remove_kprobe(struct kprobe *p);
++void kretprobe_trampoline(void);
++
++/* Architecture specific copy of original instruction*/
++struct arch_specific_insn {
++ /* copy of the original instruction */
++ kprobe_opcode_t *insn;
++ /*
++ * boostable = -1: This instruction type is not boostable.
++ * boostable = 0: This instruction type is boostable.
++ * boostable = 1: This instruction has been boosted: we have
++ * added a relative jump after the instruction copy in insn,
++ * so no single-step and fixup are needed (unless there's
++ * a post_handler or break_handler).
++ */
++ int boostable;
++};
++
++struct prev_kprobe {
++ struct kprobe *kp;
++ unsigned long status;
++ unsigned long old_flags;
++ unsigned long saved_flags;
++};
++
++/* per-cpu kprobe control block */
++struct kprobe_ctlblk {
++ unsigned long kprobe_status;
++ unsigned long kprobe_old_flags;
++ unsigned long kprobe_saved_flags;
++ unsigned long *jprobe_saved_sp;
++ struct pt_regs jprobe_saved_regs;
++ kprobe_opcode_t jprobes_stack[MAX_STACK_SIZE];
++ struct prev_kprobe prev_kprobe;
++};
++
++extern int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
++extern int kprobe_exceptions_notify(struct notifier_block *self,
++ unsigned long val, void *data);
++#endif /* _ASM_ANDES_KPROBES_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/kvm.h linux-3.4.110/arch/nds32/include/asm/kvm.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/kvm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/kvm.h 2016-04-07 10:20:50.898079322 +0200
+@@ -0,0 +1,9 @@
++/*
++ * linux/arch/nds32/include/asm/kvm.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_KVM_H__
++#define __NDS32_KVM_H__
++
++#endif /* __NDS32_KVM_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/l2_cache.h linux-3.4.110/arch/nds32/include/asm/l2_cache.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/l2_cache.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/l2_cache.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,134 @@
++/*
++ * linux/arch/nds32/include/asm/l2_cache.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef L2_CACHE_H
++#define L2_CACHE_H
++
++// CCTL_CMD_OP
++#define L2_CA_CONF_OFF 0x0
++#define L2_IF_CONF_OFF 0x4
++#define L2CC_SETUP_OFF 0x8
++#define L2CC_PROT_OFF 0xC
++#define L2CC_CTRL_OFF 0x10
++#define L2_INT_EN_OFF 0x20
++#define L2_STA_OFF 0x24
++#define RDERR_ADDR_OFF 0x28
++#define WRERR_ADDR_OFF 0x2c
++#define EVDPTERR_ADDR_OFF 0x30
++#define IMPL3ERR_ADDR_OFF 0x34
++#define L2_CNT0_CTRL_OFF 0x40
++#define L2_EVNT_CNT0_OFF 0x44
++#define L2_CNT1_CTRL_OFF 0x48
++#define L2_EVNT_CNT1_OFF 0x4c
++#define L2_CCTL_CMD_OFF 0x60
++#define L2_CCTL_STATUS_OFF 0x64
++#define L2_LINE_TAG_OFF 0x68
++#define L2_LINE_DPT_OFF 0x70
++
++#define CCTL_CMD_L2_IX_INVAL 0x0
++#define CCTL_CMD_L2_PA_INVAL 0x1
++#define CCTL_CMD_L2_IX_WB 0x2
++#define CCTL_CMD_L2_PA_WB 0x3
++#define CCTL_CMD_L2_PA_WBINVAL 0x5
++#define CCTL_CMD_L2_SYNC 0xa
++// CCTL_CMD_TYPE
++#define CCTL_SINGLE_CMD 0
++#define CCTL_BLOCK_CMD 0x10
++#define CCTL_ALL_CMD 0x10
++
++/******************************************************************************
++ * L2_CA_CONF (Cache architecture configuration)
++ *****************************************************************************/
++#define L2_CA_CONF_offL2SET 0
++#define L2_CA_CONF_offL2WAY 4
++#define L2_CA_CONF_offL2CLSZ 8
++#define L2_CA_CONF_offL2DW 11
++#define L2_CA_CONF_offL2PT 14
++#define L2_CA_CONF_offL2VER 16
++
++#define L2_CA_CONF_mskL2SET (0xFUL << L2_CA_CONF_offL2SET)
++#define L2_CA_CONF_mskL2WAY (0xFUL << L2_CA_CONF_offL2WAY)
++#define L2_CA_CONF_mskL2CLSZ (0x7UL << L2_CA_CONF_offL2CLSZ)
++#define L2_CA_CONF_mskL2DW (0x7UL << L2_CA_CONF_offL2DW)
++#define L2_CA_CONF_mskL2PT (0x3UL << L2_CA_CONF_offL2PT)
++#define L2_CA_CONF_mskL2VER (0xFFFFUL << L2_CA_CONF_offL2VER)
++
++/******************************************************************************
++ * L2CC_SETUP (L2CC Setup register)
++ *****************************************************************************/
++#define L2CC_SETUP_offPART 0
++#define L2CC_SETUP_mskPART (0x3UL << L2CC_SETUP_offPART)
++#define L2CC_SETUP_offDDLATC 4
++#define L2CC_SETUP_mskDDLATC (0x3UL << L2CC_SETUP_offDDLATC)
++#define L2CC_SETUP_offTDLATC 8
++#define L2CC_SETUP_mskTDLATC (0x3UL << L2CC_SETUP_offTDLATC)
++
++/******************************************************************************
++ * L2CC_PROT (L2CC Protect register)
++ *****************************************************************************/
++#define L2CC_PROT_offMRWEN 31
++#define L2CC_PROT_mskMRWEN (0x1UL << L2CC_PROT_offMRWEN)
++//TODO finish this table
++//
++/******************************************************************************
++ * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n)
++ *****************************************************************************/
++#define L2CC_CTRL_offEN 31
++#define L2CC_CTRL_mskEN (0x1UL << L2CC_CTRL_offEN)
++
++/******************************************************************************
++ * L2_CCTL_STATUS_Mn (The L2CCTL command working status for Master n)
++ *****************************************************************************/
++#define L2_CCTL_STATUS_offCMD_COMP 31
++#define L2_CCTL_STATUS_mskCMD_COMP (0x1 << L2_CCTL_STATUS_offCMD_COMP)
++//TODO finish this table
++
++#ifndef __ASSEMBLY__
++
++#include <linux/smp.h>
++#include <asm/io.h>
++#include <asm/bitfield.h>
++
++#define L2C_R_REG(offset) inl(L2CC_VA_BASE + offset)
++#define L2C_W_REG(offset, value) outl(value, L2CC_VA_BASE + offset)
++
++#define L2_CMD_RDY() \
++ do{;}while((L2C_R_REG(L2_CCTL_STATUS_OFF) & L2_CCTL_STATUS_mskCMD_COMP) == 0)
++
++static inline unsigned long L2_CACHE_SET(void){
++ return 64 << ( ( L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2SET) >> L2_CA_CONF_offL2SET);
++}
++
++static inline unsigned long L2_CACHE_WAY(void){
++ return 1 + ( ( L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2WAY) >> L2_CA_CONF_offL2WAY);
++}
++
++static inline unsigned long L2_CACHE_LINE_SIZE(void){
++
++ return 4 << ( ( L2C_R_REG(L2_CA_CONF_OFF) & L2_CA_CONF_mskL2CLSZ) >> L2_CA_CONF_offL2CLSZ);
++}
++
++static inline unsigned long GET_L2CC_CTRL_CPU(unsigned long cpu){
++ if(cpu == smp_processor_id())
++ return L2C_R_REG(L2CC_CTRL_OFF);
++ return L2C_R_REG(L2CC_CTRL_OFF+(cpu<<8));
++}
++
++static inline void SET_L2CC_CTRL_CPU(unsigned long cpu , unsigned long val){
++ if(cpu == smp_processor_id())
++ L2C_W_REG(L2CC_CTRL_OFF,val);
++ else
++ L2C_W_REG(L2CC_CTRL_OFF+(cpu<<8),val);
++}
++
++static inline unsigned long GET_L2CC_STATUS_CPU(unsigned long cpu){
++ if(cpu == smp_processor_id())
++ return L2C_R_REG(L2_CCTL_STATUS_OFF);
++ return L2C_R_REG(L2_CCTL_STATUS_OFF+(cpu<<8));
++}
++
++#endif
++
++#endif //L2_CACHE_H
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/leds.h linux-3.4.110/arch/nds32/include/asm/leds.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/leds.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/leds.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,51 @@
++/*
++ * linux/arch/nds32/include/asm/leds.h
++ *
++ * Copyright (C) 1998 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Event-driven interface for LEDs on machines
++ * Added led_start and led_stop- Alex Holden, 28th Dec 1998.
++ */
++#ifndef ASM_NDS32_LEDS_H
++#define ASM_NDS32_LEDS_H
++
++
++typedef enum {
++ led_idle_start,
++ led_idle_end,
++ led_timer,
++ led_start,
++ led_stop,
++ led_claim, /* override idle & timer leds */
++ led_release, /* restore idle & timer leds */
++ led_start_timer_mode,
++ led_stop_timer_mode,
++ led_green_on,
++ led_green_off,
++ led_amber_on,
++ led_amber_off,
++ led_red_on,
++ led_red_off,
++ led_blue_on,
++ led_blue_off,
++ /*
++ * I want this between led_timer and led_start, but
++ * someone has decided to export this to user space
++ */
++ led_halted
++} led_event_t;
++
++/* Use this routine to handle LEDs */
++
++#ifdef CONFIG_LEDS
++extern void (*leds_event)(led_event_t);
++#else
++#define leds_event(e)
++#endif
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/limits.h linux-3.4.110/arch/nds32/include/asm/limits.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/limits.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/limits.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,16 @@
++/*
++ * linux/arch/nds32/include/asm/limits.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASM_PIPE_H
++#define __ASM_PIPE_H
++
++#ifndef PAGE_SIZE
++#include <asm/page.h>
++#endif
++
++#define PIPE_BUF PAGE_SIZE
++
++#endif
++
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/linkage.h linux-3.4.110/arch/nds32/include/asm/linkage.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/linkage.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/linkage.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,12 @@
++/*
++ * linux/arch/nds32/include/asm/linkage.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_LINKAGE_H__
++#define __NDS32_LINKAGE_H__
++
++#define __ALIGN .align 2
++#define __ALIGN_STR ".align 2"
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/local.h linux-3.4.110/arch/nds32/include/asm/local.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/local.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/local.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/local.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_LOCAL_H__
++#define __NDS32_LOCAL_H__
++
++#include <asm-generic/local.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/arch.h linux-3.4.110/arch/nds32/include/asm/mach/arch.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mach/arch.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mach/arch.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,86 @@
++/*
++ * linux/arch/nds32/include/asm/mach/arch.h
++ *
++ * Copyright (C) 2000 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef __ASSEMBLY__
++
++struct tag;
++struct meminfo;
++struct sys_timer;
++
++struct machine_desc {
++ /*
++ * Note! The first four elements are used
++ * by assembler code in head-armv.S
++ */
++ unsigned int nr; /* architecture number */
++
++ const char *name; /* architecture name */
++ unsigned int param_offset; /* parameter page */
++
++ unsigned int video_start; /* start of video RAM */
++ unsigned int video_end; /* end of video RAM */
++
++ unsigned int reserve_lp0 :1; /* never has lp0 */
++ unsigned int reserve_lp1 :1; /* never has lp1 */
++ unsigned int reserve_lp2 :1; /* never has lp2 */
++ unsigned int soft_reboot :1; /* soft reboot */
++ void (*fixup)(struct machine_desc *,
++ struct tag *, char **,
++ struct meminfo *);
++ void (*map_io)(void);/* IO mapping function */
++ void (*init_irq)(void);
++ struct sys_timer *timer; /* system tick timer */
++ void (*init_machine)(void);
++};
++
++/*
++ * * Current machine - only accessible during boot.
++ * */
++extern struct machine_desc *machine_desc;
++
++/*
++ * Set of macros to define architecture features. This is built into
++ * a table by the linker.
++ */
++#define MACHINE_START(_type,_name) \
++const struct machine_desc __mach_desc_##_type \
++ __attribute__((__section__(".arch.info"))) = { \
++ .nr = MACH_TYPE_##_type, \
++ .name = _name,
++
++#define MAINTAINER(n)
++
++#define BOOT_PARAMS(_params) \
++ .param_offset = _params,
++
++#define VIDEO(_start,_end) \
++ .video_start = _start, \
++ .video_end = _end,
++
++#define DISABLE_PARPORT(_n) \
++ .reserve_lp##_n = 1,
++
++#define SOFT_REBOOT \
++ .soft_reboot = 1,
++
++#define MAPIO(_func) \
++ .map_io = _func,
++
++#define INITIRQ(_func) \
++ .init_irq = _func,
++
++#define INIT_MACHINE(_func) \
++ .init_machine = _func,
++
++#define MACHINE_END \
++};
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/dma.h linux-3.4.110/arch/nds32/include/asm/mach/dma.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mach/dma.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mach/dma.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,56 @@
++/*
++ * linux/arch/nds32/include/asm/mach/dma.h
++ *
++ * Copyright (C) 1998-2000 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This header file describes the interface between the generic DMA handler
++ * (dma.c) and the architecture-specific DMA backends (dma-*.c)
++ */
++
++struct dma_struct;
++typedef struct dma_struct dma_t;
++
++struct dma_ops {
++ int (*request)(dmach_t, dma_t *); /* optional */
++ void (*free)(dmach_t, dma_t *); /* optional */
++ void (*enable)(dmach_t, dma_t *); /* mandatory */
++ void (*disable)(dmach_t, dma_t *); /* mandatory */
++ int (*residue)(dmach_t, dma_t *); /* optional */
++ int (*setspeed)(dmach_t, dma_t *, int); /* optional */
++ char *type;
++};
++
++struct dma_struct {
++ struct scatterlist buf; /* single DMA */
++ int sgcount; /* number of DMA SG */
++ struct scatterlist *sg; /* DMA Scatter-Gather List */
++
++ unsigned int active:1; /* Transfer active */
++ unsigned int invalid:1; /* Address/Count changed */
++ unsigned int using_sg:1; /* using scatter list? */
++ dmamode_t dma_mode; /* DMA mode */
++ int speed; /* DMA speed */
++
++ unsigned int lock; /* Device is allocated */
++ const char *device_id; /* Device name */
++
++ unsigned int dma_base; /* Controller base address */
++ int dma_irq; /* Controller IRQ */
++ struct scatterlist cur_sg; /* Current controller buffer */
++ unsigned int state;
++
++ struct dma_ops *d_ops;
++};
++
++/* Prototype: void arch_dma_init(dma)
++ * Purpose : Initialise architecture specific DMA
++ * Params : dma - pointer to array of DMA structures
++ */
++extern void arch_dma_init(dma_t *dma);
++
++extern void isa_init_dma(dma_t *dma);
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/flash.h linux-3.4.110/arch/nds32/include/asm/mach/flash.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mach/flash.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mach/flash.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,35 @@
++/*
++ * linux/arch/nds32/include/asm/mach/flash.h
++ *
++ * Copyright (C) 2003 Russell King, All Rights Reserved.
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef ASMNDS32_MACH_FLASH_H
++#define ASMNDS32_MACH_FLASH_H
++
++struct mtd_partition;
++
++/*
++ * map_name: the map probe function name
++ * width: width of mapped device
++ * init: method called at driver/device initialisation
++ * exit: method called at driver/device removal
++ * set_vpp: method called to enable or disable VPP
++ * parts: optional array of mtd_partitions for static partitioning
++ * nr_parts: number of mtd_partitions for static partitoning
++ */
++struct flash_platform_data {
++ const char *map_name;
++ unsigned int width;
++ int (*init)(void);
++ void (*exit)(void);
++ void (*set_vpp)(int on);
++ struct mtd_partition *parts;
++ unsigned int nr_parts;
++};
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/irda.h linux-3.4.110/arch/nds32/include/asm/mach/irda.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mach/irda.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mach/irda.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,21 @@
++/*
++ * linux/arch/nds32/include/asm/mach/irda.h
++ *
++ * Copyright (C) 2004 Russell King.
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_NDS32_MACH_IRDA_H
++#define __ASM_NDS32_MACH_IRDA_H
++
++struct irda_platform_data {
++ int (*startup)(struct device *);
++ void (*shutdown)(struct device *);
++ int (*set_power)(struct device *, unsigned int state);
++ void (*set_speed)(struct device *, unsigned int speed);
++};
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/map.h linux-3.4.110/arch/nds32/include/asm/mach/map.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mach/map.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mach/map.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,37 @@
++/*
++ * linux/arch/nds32/include/asm/mach/map.h
++ *
++ * Copyright (C) 1999-2000 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Page table mapping constructs and function prototypes
++ */
++struct map_desc {
++ unsigned long virtual;
++ unsigned long physical;
++ unsigned long length;
++ unsigned int type;
++};
++
++struct meminfo;
++
++#define MT_DEVICE_NCB MT_DEVICE
++#define MT_DEVICE_NCNB MT_DEVICE
++#define MT_DEVICE 0
++#define MT_CACHECLEAN 1
++#define MT_MINICLEAN 2
++#define MT_CACHE_L1 3
++#define MT_UXKRWX_V1 4
++#define MT_UXKRWX_V2 5
++#define MT_MEMORY 6
++#define MT_ROM 7
++#define MT_ILM 8
++#define MT_DLM 9
++
++extern void create_memmap_holes(struct meminfo *);
++extern void iotable_init(struct map_desc *, int);
++extern void setup_io_desc(void);
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/mmc.h linux-3.4.110/arch/nds32/include/asm/mach/mmc.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mach/mmc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mach/mmc.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,16 @@
++/*
++ * linux/arch/nds32/include/asm/mach/mmc.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++#ifndef ASMNDS32_MACH_MMC_H
++#define ASMNDS32_MACH_MMC_H
++
++#include <linux/mmc/protocol.h>
++
++struct mmc_platform_data {
++ unsigned int ocr_mask; /* available voltages */
++ u32 (*translate_vdd)(struct device *, unsigned int);
++ unsigned int (*status)(struct device *);
++};
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/pci.h linux-3.4.110/arch/nds32/include/asm/mach/pci.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mach/pci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mach/pci.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,76 @@
++/*
++ * linux/arch/nds32/include/asm/mach/pci.h
++ *
++ * Copyright (C) 2000 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ */
++
++struct pci_sys_data;
++struct pci_bus;
++
++struct hw_pci {
++ struct list_head buses;
++ int nr_controllers;
++ int (*setup)(int nr, struct pci_sys_data *);
++ struct pci_bus *(*scan)(int nr, struct pci_sys_data *);
++ void (*preinit)(void);
++ void (*postinit)(void);
++ u8 (*swizzle)(struct pci_dev *dev, u8 *pin);
++ int (*map_irq)(struct pci_dev *dev, u8 slot, u8 pin);
++};
++
++/*
++ * Per-controller structure
++ */
++struct pci_sys_data {
++ struct list_head node;
++ int busnr; /* primary bus number */
++ unsigned long mem_offset; /* bus->cpu memory mapping offset */
++ unsigned long io_offset; /* bus->cpu IO mapping offset */
++ struct pci_bus *bus; /* PCI bus */
++ struct resource *resource[3]; /* Primary PCI bus resources */
++ /* Bridge swizzling */
++ u8 (*swizzle)(struct pci_dev *, u8 *);
++ /* IRQ mapping */
++ int (*map_irq)(struct pci_dev *, u8, u8);
++ struct hw_pci *hw;
++};
++
++/*
++ * This is the standard PCI-PCI bridge swizzling algorithm.
++ */
++u8 pci_std_swizzle(struct pci_dev *dev, u8 *pinp);
++
++/*
++ * Call this with your hw_pci struct to initialise the PCI system.
++ */
++void pci_common_init(struct hw_pci *);
++
++/*
++ * PCI controllers
++ */
++extern int iop321_setup(int nr, struct pci_sys_data *);
++extern struct pci_bus *iop321_scan_bus(int nr, struct pci_sys_data *);
++extern void iop321_init(void);
++
++extern int iop331_setup(int nr, struct pci_sys_data *);
++extern struct pci_bus *iop331_scan_bus(int nr, struct pci_sys_data *);
++extern void iop331_init(void);
++
++extern int dc21285_setup(int nr, struct pci_sys_data *);
++extern struct pci_bus *dc21285_scan_bus(int nr, struct pci_sys_data *);
++extern void dc21285_preinit(void);
++extern void dc21285_postinit(void);
++
++extern int via82c505_setup(int nr, struct pci_sys_data *);
++extern struct pci_bus *via82c505_scan_bus(int nr, struct pci_sys_data *);
++extern void via82c505_init(void *sysdata);
++
++extern int pci_v3_setup(int nr, struct pci_sys_data *);
++extern struct pci_bus *pci_v3_scan_bus(int nr, struct pci_sys_data *);
++extern void pci_v3_preinit(void);
++extern void pci_v3_postinit(void);
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/serial_sa1100.h linux-3.4.110/arch/nds32/include/asm/mach/serial_sa1100.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mach/serial_sa1100.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mach/serial_sa1100.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,31 @@
++/*
++ * linux/include/asm-arm/mach/serial_sa1100.h
++ *
++ * Author: Nicolas Pitre
++ *
++ * Moved to include/asm-arm/mach and changed lots, Russell King
++ *
++ * Low level machine dependent UART functions.
++ */
++
++struct uart_port;
++struct uart_info;
++
++/*
++ * This is a temporary structure for registering these
++ * functions; it is intended to be discarded after boot.
++ */
++struct sa1100_port_fns {
++ void (*set_mctrl)(struct uart_port *, u_int);
++ u_int (*get_mctrl)(struct uart_port *);
++ void (*pm)(struct uart_port *, u_int, u_int);
++ int (*set_wake)(struct uart_port *, u_int);
++};
++
++#ifdef CONFIG_SERIAL_SA1100
++void sa1100_register_uart_fns(struct sa1100_port_fns *fns);
++void sa1100_register_uart(int idx, int port);
++#else
++#define sa1100_register_uart_fns(fns) do { } while (0)
++#define sa1100_register_uart(idx,port) do { } while (0)
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach/time.h linux-3.4.110/arch/nds32/include/asm/mach/time.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mach/time.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mach/time.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,62 @@
++/*
++ * linux/arch/nds32/include/asm/mach/time.h
++ *
++ * Copyright (C) 2004 MontaVista Software, Inc.
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_NDS32_MACH_TIME_H
++#define __ASM_NDS32_MACH_TIME_H
++
++//#include <linux/sysdev.h>
++
++/*
++ * This is our kernel timer structure.
++ *
++ * - init
++ * Initialise the kernels jiffy timer source, claim interrupt
++ * using setup_irq. This is called early on during initialisation
++ * while interrupts are still disabled on the local CPU.
++ * - suspend
++ * Suspend the kernel jiffy timer source, if necessary. This
++ * is called with interrupts disabled, after all normal devices
++ * have been suspended. If no action is required, set this to
++ * NULL.
++ * - resume
++ * Resume the kernel jiffy timer source, if necessary. This
++ * is called with interrupts disabled before any normal devices
++ * are resumed. If no action is required, set this to NULL.
++ * - offset
++ * Return the timer offset in microseconds since the last timer
++ * interrupt. Note: this must take account of any unprocessed
++ * timer interrupt which may be pending.
++ */
++
++/* + Tom from newlib
++ * Have the 32 bit jiffies value wrap 5 minutes after boot
++ * so jiffies wrap bugs show up earlier.
++ */
++//#define INITIAL_JIFFIES ((unsigned long)(unsigned int) (-300*HZ))
++
++struct sys_timer {
++// struct sys_device dev;
++ void (*init)(void);
++ void (*suspend)(void);
++ void (*resume)(void);
++ unsigned long (*offset)(void);
++};
++
++extern struct sys_timer *system_timer;
++extern void timer_tick( void);
++
++/*
++ * Kernel time keeping support.
++ */
++extern int (*set_rtc)(void);
++extern void save_time_delta(struct timespec *delta, struct timespec *rtc);
++extern void restore_time_delta(struct timespec *delta, struct timespec *rtc);
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mach-types.h linux-3.4.110/arch/nds32/include/asm/mach-types.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mach-types.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mach-types.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,14 @@
++#ifndef __ASSEMBLY__
++/* The type of machine we're running on */
++extern unsigned int __machine_arch_type;
++#endif
++
++#define MACH_TYPE_FARADAY 758
++
++# ifdef machine_arch_type
++# undef machine_arch_type
++# define machine_arch_type __machine_arch_type
++# else
++# define machine_arch_type MACH_TYPE_FARADAY
++# endif
++# define machine_is_faraday() (machine_arch_type == MACH_TYPE_FARADAY)
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/memory.h linux-3.4.110/arch/nds32/include/asm/memory.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/memory.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/memory.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,218 @@
++/*
++ * linux/arch/nds32/include/asm/memory.h
++ *
++ * Copyright (C) 2000-2002 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Note: this file should not be included by non-asm/.h files
++ */
++#ifndef __ASM_NDS32_MEMORY_H
++#define __ASM_NDS32_MEMORY_H
++
++#include <linux/compiler.h>
++#ifndef __FARADAY_PLATFORM_INDEPENDENT_MEMORY_HEADER__
++#define __FARADAY_PLATFORM_INDEPENDENT_MEMORY_HEADER__
++
++#include <asm/spec.h>
++
++#ifndef __ASSEMBLY__
++#include <asm/page.h>
++#endif
++
++#ifndef PHYS_OFFSET
++#define PHYS_OFFSET CPU_MEM_PA_BASE
++#endif
++
++#ifndef PAGE_OFFSET
++#define PAGE_OFFSET (0xC0000000)
++#endif
++
++#ifndef END_MEM
++#define END_MEM (CPU_MEM_PA_LIMIT)
++#endif
++
++#ifndef __virt_to_bus
++#define __virt_to_bus __virt_to_phys
++#endif
++
++#ifndef __bus_to_virt
++#define __bus_to_virt __phys_to_virt
++#endif
++
++#endif /* __FARADAY_PLATFORM_INDEPENDENT_MEMORY_HEADER__ */
++
++#ifndef TASK_SIZE
++/*
++ * TASK_SIZE - the maximum size of a user space task.
++ * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
++ */
++#define TASK_SIZE (0xbf000000UL)
++#define TASK_UNMAPPED_BASE (0x40000000UL)
++#endif
++
++/*
++ * Page offset: 3GB
++ */
++#ifndef PAGE_OFFSET
++#define PAGE_OFFSET (0xc0000000)
++#endif
++
++/*
++ * Physical vs virtual RAM address space conversion. These are
++ * private definitions which should NOT be used outside memory.h
++ * files. Use virt_to_phys/phys_to_virt/__pa/__va instead.
++ */
++#ifndef __virt_to_phys
++#define __virt_to_phys(x) ((x) - PAGE_OFFSET + PHYS_OFFSET)
++#define __phys_to_virt(x) ((x) - PHYS_OFFSET + PAGE_OFFSET)
++#endif
++
++/*
++ * The module space lives between the addresses given by TASK_SIZE
++ * and PAGE_OFFSET - it must be within 32MB of the kernel text.
++ */
++#define MODULES_END (PAGE_OFFSET)
++#define MODULES_VADDR (MODULES_END - 16*1048576)
++
++#if TASK_SIZE > MODULES_VADDR
++#error Top of user space clashes with start of module space
++#endif
++
++#ifndef __ASSEMBLY__
++
++/*
++ * The DMA mask corresponding to the maximum bus address allocatable
++ * using GFP_DMA. The default here places no restriction on DMA
++ * allocations. This must be the smallest DMA mask in the system,
++ * so a successful GFP_DMA allocation will always satisfy this.
++ */
++#ifndef ISA_DMA_THRESHOLD
++#define ISA_DMA_THRESHOLD (0xffffffffULL)
++#endif
++
++#ifndef arch_adjust_zones
++#define arch_adjust_zones(node,size,holes) do { } while (0)
++#endif
++
++/*
++ * PFNs are used to describe any physical page; this means
++ * PFN 0 == physical address 0.
++ *
++ * This is the PFN of the first RAM page in the kernel
++ * direct-mapped view. We assume this is the first page
++ * of RAM in the mem_map as well.
++ */
++#define PHYS_PFN_OFFSET (PHYS_OFFSET >> PAGE_SHIFT)
++
++/*
++ * These are *only* valid on the kernel direct mapped RAM memory.
++ * Note: Drivers should NOT use these. They are the wrong
++ * translation for translating DMA addresses. Use the driver
++ * DMA support - see dma-mapping.h.
++ */
++static inline unsigned long virt_to_phys(void *x)
++{
++ return __virt_to_phys((unsigned long)(x));
++}
++
++static inline void *phys_to_virt(unsigned long x)
++{
++ return (void *)(__phys_to_virt((unsigned long)(x)));
++}
++
++/*
++ * Drivers should NOT use these either.
++ */
++#define __pa(x) __virt_to_phys((unsigned long)(x))
++#define __va(x) ((void *)__phys_to_virt((unsigned long)(x)))
++
++/*
++ * Virtual <-> DMA view memory address translations
++ * Again, these are *only* valid on the kernel direct mapped RAM
++ * memory. Use of these is *deprecated* (and that doesn't mean
++ * use the __ prefixed forms instead.) See dma-mapping.h.
++ */
++static inline __deprecated unsigned long virt_to_bus(void *x)
++{
++ return __virt_to_bus((unsigned long)x);
++}
++
++static inline __deprecated void *bus_to_virt(unsigned long x)
++{
++ return (void *)__bus_to_virt(x);
++}
++
++/*
++ * Conversion between a struct page and a physical address.
++ *
++ * Note: when converting an unknown physical address to a
++ * struct page, the resulting pointer must be validated
++ * using VALID_PAGE(). It must return an invalid struct page
++ * for any physical address not corresponding to a system
++ * RAM address.
++ *
++ * pfn_valid(pfn) indicates whether a PFN number is valid
++ *
++ * virt_to_page(k) convert a _valid_ virtual address to struct page *
++ * virt_addr_valid(k) indicates whether a virtual address is valid
++ */
++#ifndef CONFIG_DISCONTIGMEM
++
++#define ARCH_PFN_OFFSET PHYS_PFN_OFFSET
++#define pfn_valid(pfn) ((pfn) >= PHYS_PFN_OFFSET && (pfn) < (PHYS_PFN_OFFSET + max_mapnr))
++
++#define virt_to_page(kaddr) (pfn_to_page(__pa(kaddr) >> PAGE_SHIFT))
++#define virt_addr_valid(kaddr) ((unsigned long)(kaddr) >= PAGE_OFFSET && (unsigned long)(kaddr) < (unsigned long)high_memory)
++
++#define PHYS_TO_NID(addr) (0)
++
++#else /* CONFIG_DISCONTIGMEM */
++
++/*
++ * This is more complex. We have a set of mem_map arrays spread
++ * around in memory.
++ */
++#include <linux/numa.h>
++
++#define pfn_valid(pfn) (PFN_TO_NID(pfn) < MAX_NUMNODES)
++
++#define virt_to_page(kaddr) \
++ (ADDR_TO_MAPBASE(kaddr) + LOCAL_MAP_NR(kaddr))
++#define virt_addr_valid(kaddr) (KVADDR_TO_NID(kaddr) < MAX_NUMNODES)
++
++/*
++ * Common discontigmem stuff.
++ * PHYS_TO_NID is used by the NDS32 kernel/setup.c
++ */
++#define PHYS_TO_NID(addr) PFN_TO_NID((addr) >> PAGE_SHIFT)
++
++#endif /* !CONFIG_DISCONTIGMEM */
++
++/*
++ * For BIO. "will die". Kill me when bio_to_phys() and bvec_to_phys() die.
++ */
++#define page_to_phys(page) (page_to_pfn(page) << PAGE_SHIFT)
++
++/*
++ * Optional device DMA address remapping. Do _not_ use directly!
++ * We should really eliminate virt_to_bus() here - it's deprecated.
++ */
++#ifndef __arch_page_to_dma
++#define page_to_dma(dev, page) ((dma_addr_t)__virt_to_bus((unsigned long)page_address(page)))
++#define dma_to_virt(dev, addr) ((void *)__bus_to_virt(addr))
++#define virt_to_dma(dev, addr) ((dma_addr_t)__virt_to_bus((unsigned long)(addr)))
++#else
++#define page_to_dma(dev, page) (__arch_page_to_dma(dev, page))
++#define dma_to_virt(dev, addr) (__arch_dma_to_virt(dev, addr))
++#define virt_to_dma(dev, addr) (__arch_virt_to_dma(dev, addr))
++#endif
++
++#endif
++
++#include <asm-generic/memory_model.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/misc_spec.h linux-3.4.110/arch/nds32/include/asm/misc_spec.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/misc_spec.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/misc_spec.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,75 @@
++/*
++ * linux/arch/nds32/include/asm/misc_spec.h
++ *
++ * Faraday A320D platform dependent definitions
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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
++ *
++ * ChangeLog
++ *
++ * Luke Lee 09/14/2005 Created
++ * Luke Lee 10/06/2005 Modified for automatic system clock rate
++ */
++
++#ifndef __A320_PLATFORM_MANUAL_DEFINITION__
++#define __A320_PLATFORM_MANUAL_DEFINITION__
++
++#define BOOT_PARAMETER_PA_BASE (PHYS_OFFSET + 0x400)
++
++#ifdef CONFIG_AUTO_SYS_CLK
++
++#ifndef __ASSEMBLY__
++extern int ag101_get_ahb_clk(void);
++extern int ag102_get_ahb_clk(void);
++
++#if defined(CONFIG_PLAT_AG101)
++#define AHB_CLK_IN ag101_get_ahb_clk()
++#elif defined(CONFIG_PLAT_AG102)
++#define AHB_CLK_IN ag102_get_ahb_clk()
++
++#endif
++
++#endif
++#define TIMER_CLK_IN (CONFIG_SYS_CLK/2)
++
++#else
++
++/* Timer clock input is APB CLOCK */
++#define TIMER_CLK_IN (CONFIG_SYS_CLK/2)
++#define AHB_CLK_IN (CONFIG_SYS_CLK)
++
++#endif
++
++#ifndef __ASSEMBLY__
++#include <linux/init.h>
++
++#ifdef CONFIG_PLATFORM_INTC
++extern void __init intc_ftintc010_init_irq(void);
++#define platform_init_irq intc_ftintc010_init_irq
++#endif
++
++#ifdef CONFIG_PLATFORM_NOINTC
++extern void __init nointc_init_irq(void);
++#define platform_init_irq nointc_init_irq
++#endif
++
++#endif
++
++#define daughter_platform_init_irq(x) /* NOP */
++
++#endif /*__A320_PLATFORM_MANUAL_DEFINITION__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mman.h linux-3.4.110/arch/nds32/include/asm/mman.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mman.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mman.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,22 @@
++/*
++ * linux/arch/nds32/include/asm/mman.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_MMAN_H__
++#define __NDS32_MMAN_H__
++
++#include <asm-generic/mman.h>
++
++#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
++#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
++#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
++#define MAP_LOCKED 0x2000 /* pages are locked */
++#define MAP_NORESERVE 0x4000 /* don't check for reservations */
++#define MAP_POPULATE 0x8000 /* populate (prefault) page tables */
++#define MAP_NONBLOCK 0x10000 /* do not block on IO */
++
++#define MCL_CURRENT 1 /* lock all current mappings */
++#define MCL_FUTURE 2 /* lock all future mappings */
++
++#endif /* __NDS32_MMAN_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mmu_context.h linux-3.4.110/arch/nds32/include/asm/mmu_context.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mmu_context.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mmu_context.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,84 @@
++/*
++ * linux/arch/nds32/include/asm/mmu_context.h
++ *
++ * Copyright (C) 1996 Russell King.
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Changelog:
++ * 27-06-1996 RMK Created
++ */
++#ifndef __ASM_NDS32_MMU_CONTEXT_H
++#define __ASM_NDS32_MMU_CONTEXT_H
++
++#include <linux/spinlock.h>
++#include <asm/tlbflush.h>
++#include <asm-generic/mm_hooks.h>
++
++static inline int
++init_new_context(struct task_struct *tsk, struct mm_struct *mm)
++{
++ mm->context.id = 0;
++ return 0;
++}
++
++#define destroy_context(mm) do { } while(0)
++
++#ifndef CONFIG_CPU_NO_CONTEXT_ID
++#define CID_BITS 9
++extern spinlock_t cid_lock;
++extern unsigned int cpu_last_cid;
++
++static inline void
++__new_context(struct mm_struct *mm)
++{
++ unsigned int cid;
++ unsigned long flags;
++
++ spin_lock_irqsave(&cid_lock, flags);
++ cid = cpu_last_cid;
++ cpu_last_cid += 1 << TLB_MISC_offCID;
++ if (cpu_last_cid == 0)
++ cpu_last_cid = 1 << TLB_MISC_offCID << CID_BITS;
++ spin_unlock_irqrestore(&cid_lock, flags);
++
++ if ((cid & TLB_MISC_mskCID ) == 0)
++ flush_tlb_all();
++
++ mm->context.id = cid;
++}
++
++static inline void
++check_context(struct mm_struct *mm)
++{
++ if (unlikely((mm->context.id ^ cpu_last_cid) >> TLB_MISC_offCID >> CID_BITS))
++ __new_context(mm);
++}
++#else
++#define check_context(m)
++#endif
++
++static inline void
++enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
++{
++}
++
++static inline void
++switch_mm(struct mm_struct *prev, struct mm_struct *next,
++ struct task_struct *tsk)
++{
++ unsigned int cpu = smp_processor_id();
++
++ if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next) {
++ check_context(next);
++ cpu_switch_mm(next);
++ }
++}
++
++#define deactivate_mm(tsk,mm) do { } while (0)
++#define activate_mm(prev,next) switch_mm(prev, next, NULL)
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mmu.h linux-3.4.110/arch/nds32/include/asm/mmu.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mmu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mmu.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,42 @@
++/*
++ * linux/arch/nds32/include/asm/mmu.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_MMU_H
++#define __NDS32_MMU_H
++
++typedef struct {
++ unsigned int id;
++} mm_context_t;
++
++#define ASID(mm) ((mm)->context.id & (TLB_MISC_mskCID >> TLB_MISC_offCID))
++inline static unsigned long ACC_PSZ(unsigned long page_size)
++{
++ switch(page_size) {
++ case(1<<12):
++ return 0;
++ case(1<<13):
++ return 1;
++ case(1<<14):
++ return 2;
++ case(1<<16):
++ return 3;
++ case(1<<18):
++ return 4;
++ case(1<<20):
++ return 5;
++ case(1<<22):
++ return 6;
++ case(1<<24):
++ return 7;
++ case(1<<26):
++ return 8;
++ case(1<<28):
++ return 9;
++ default:
++ printk("Huge Page Size is not supported \n");
++ return 0xffffffff;
++ }
++}
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/module.h linux-3.4.110/arch/nds32/include/asm/module.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/module.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/module.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,23 @@
++/*
++ * linux/arch/nds32/include/asm/module.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASM_NDS32_MODULE_H
++#define _ASM_NDS32_MODULE_H
++
++struct mod_arch_specific
++{
++ int foo;
++};
++
++#define Elf_Shdr Elf32_Shdr
++#define Elf_Sym Elf32_Sym
++#define Elf_Ehdr Elf32_Ehdr
++
++/*
++ * Include the ARM architecture version.
++ */
++#define MODULE_ARCH_VERMAGIC "NDS32vN10" __stringify(__LINUX_NDS32_ARCH__) " "
++
++#endif /* _ASM_NDS32_MODULE_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/msgbuf.h linux-3.4.110/arch/nds32/include/asm/msgbuf.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/msgbuf.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/msgbuf.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,36 @@
++/*
++ * linux/arch/nds32/include/asm/msgbuf.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_MSGBUF_H
++#define _ASMNDS32_MSGBUF_H
++
++/*
++ * The msqid64_ds structure for arm architecture.
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct msqid64_ds {
++ struct ipc64_perm msg_perm;
++ __kernel_time_t msg_stime; /* last msgsnd time */
++ unsigned long __unused1;
++ __kernel_time_t msg_rtime; /* last msgrcv time */
++ unsigned long __unused2;
++ __kernel_time_t msg_ctime; /* last change time */
++ unsigned long __unused3;
++ unsigned long msg_cbytes; /* current number of bytes on queue */
++ unsigned long msg_qnum; /* number of messages in queue */
++ unsigned long msg_qbytes; /* max number of bytes on queue */
++ __kernel_pid_t msg_lspid; /* pid of last msgsnd */
++ __kernel_pid_t msg_lrpid; /* last receive pid */
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++#endif /* _ASMNDS32_MSGBUF_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/mutex.h linux-3.4.110/arch/nds32/include/asm/mutex.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/mutex.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/mutex.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/mutex.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_MUTEX_H__
++#define __NDS32_MUTEX_H__
++
++#include <asm-generic/mutex-dec.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/namei.h linux-3.4.110/arch/nds32/include/asm/namei.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/namei.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/namei.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/namei.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_NAMEI_H__
++#define __NDS32_NAMEI_H__
++
++#define __emul_prefix() NULL
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/nds32.h linux-3.4.110/arch/nds32/include/asm/nds32.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/nds32.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/nds32.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,90 @@
++/*
++ * linux/arch/nds32/include/asm/nds32.h -- Andes NDS32 processor register interface
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2006 Andes Technology Corporation
++ *
++ */
++#ifndef _ASM_NDS32_NDS32_H_
++#define _ASM_NDS32_NDS32_H_
++
++#include <asm/bitfield.h>
++#include <asm/reg_access.h>
++
++#define MSYNC( subtype) __asm__ ("\n\tmsync "#subtype);
++#define STANDBY( cond) __asm__ ("\n\tstandby "#cond);
++
++#ifndef __ASSEMBLY__
++
++static inline void ISB( void) { __asm__ ("\n\tisb"); }
++static inline void DSB( void) { __asm__ ("\n\tdsb"); }
++
++static inline void GIE_ENABLE( void)
++{
++ __asm__ ("gie_enable\n\t");
++}
++
++static inline void GIE_DISABLE( void)
++{
++ __asm__ ("gie_disable\n\t");
++}
++
++enum cache_t{ ICACHE, DCACHE};
++
++static inline unsigned long CACHE_SET( enum cache_t cache){
++
++ if( cache == ICACHE)
++ return 64 << ( ( GET_ICM_CFG() & ICM_CFG_mskISET) >> ICM_CFG_offISET);
++ else
++ return 64 << ( ( GET_DCM_CFG() & DCM_CFG_mskDSET) >> DCM_CFG_offDSET);
++}
++
++static inline unsigned long CACHE_WAY( enum cache_t cache){
++
++ if( cache == ICACHE)
++ return 1 + ( ( GET_ICM_CFG() & ICM_CFG_mskIWAY) >> ICM_CFG_offIWAY);
++ else
++ return 1 + ( ( GET_DCM_CFG() & DCM_CFG_mskDWAY) >> DCM_CFG_offDWAY);
++}
++
++static inline unsigned long CACHE_LINE_SIZE( enum cache_t cache){
++
++ if( cache == ICACHE)
++ return 8 << ( ( ( GET_ICM_CFG() & ICM_CFG_mskISZ) >> ICM_CFG_offISZ) - 1);
++ else
++ return 8 << ( ( ( GET_DCM_CFG() & DCM_CFG_mskDSZ) >> DCM_CFG_offDSZ) - 1);
++}
++
++static inline void GIE_SAVE( unsigned long *var){
++
++ *var = GET_PSW();
++ GIE_DISABLE();
++}
++
++static inline void GIE_RESTORE( unsigned long var){
++
++ if( var & PSW_mskGIE){
++ GIE_ENABLE();
++ }
++}
++
++#endif /* __ASSEMBLY__ */
++
++#define IVB_BASE PHYS_OFFSET /* in user space for intr/exc/trap/break table base, 64KB aligned
++ * We defined at the start of the physical memory */
++
++/* The following dispatching entry */
++#define ENTRY_TLB_MISC (IVB_BASE + nrTLB_MISC*vENTRY_SZ) /* TLB misc eh# */
++/* dispatched sub-entry exception handler numbering */
++#define RD_PROT 0 /* read protrection */
++#define WRT_PROT 1 /* write protection */
++#define NOEXEC 2 /* non executable */
++#define PAGE_MODIFY 3 /* page modified */
++#define ACC_BIT 4 /* access bit */
++#define RESVED_PTE 5 /* reserved PTE attribute */
++/* reserved 6 ~ 16 */
++
++#endif /* _ASM_NDS32_NDS32_H_ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/numnodes.h linux-3.4.110/arch/nds32/include/asm/numnodes.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/numnodes.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/numnodes.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,25 @@
++/*
++ * linux/arch/nds32/include/asm/numnodes.h
++ *
++ * Copyright (C) 2002 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++/* This declaration for the size of the NUMA (CONFIG_DISCONTIGMEM)
++ * memory node table is the default.
++ *
++ * A good place to override this value is include/asm/arch/memory.h.
++ */
++
++#ifndef __ASM_NDS32_NUMNODES_H
++#define __ASM_NDS32_NUMNODES_H
++
++#ifndef NODES_SHIFT
++# define NODES_SHIFT 2 /* Normally, Max 4 Nodes */
++#endif
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/page.h linux-3.4.110/arch/nds32/include/asm/page.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/page.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/page.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,153 @@
++/*
++ * linux/arch/nds32/include/asm/page.h
++ *
++ * Copyright (C) 1995-2003 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef _ASMNDS32_PAGE_H
++#define _ASMNDS32_PAGE_H
++
++
++#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
++#define PAGE_SHIFT 12
++#endif
++#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
++#define PAGE_SHIFT 13
++#endif
++#include <linux/const.h>
++#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT)
++#define PAGE_MASK (~(PAGE_SIZE-1))
++#define PTE_MASK PAGE_MASK
++
++/* PAGE_SHIFT determines the page size */
++#define EXEC_PAGESIZE PAGE_SIZE
++
++#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_16KB
++#define LARGE_PAGE_SHIFT 14
++#define HPAGE_SHIFT 14
++#endif
++
++#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_64KB
++#define LARGE_PAGE_SHIFT 16
++#define HPAGE_SHIFT 16
++#endif
++
++#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_256KB
++#define LARGE_PAGE_SHIFT 18
++#define HPAGE_SHIFT 18
++#endif
++#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_1MB
++#define LARGE_PAGE_SHIFT 20
++#define HPAGE_SHIFT 20
++#endif
++
++#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_4MB
++#define LARGE_PAGE_SHIFT 22
++#define HPAGE_SHIFT 22
++#endif
++
++#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_16MB
++#define LARGE_PAGE_SHIFT 24
++#define HPAGE_SHIFT 24
++#endif
++
++#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_64MB
++#define LARGE_PAGE_SHIFT 26
++#define HPAGE_SHIFT 26
++#endif
++
++#ifdef CONFIG_ANDES_HUGETLB_PAGE_SIZE_256MB
++#define LARGE_PAGE_SHIFT 28
++#define HPAGE_SHIFT 28
++#endif
++
++#ifdef CONFIG_HUGETLB_PAGE
++// taken for i386 style
++#define LARGE_PAGE_SIZE (1UL << LARGE_PAGE_SHIFT)
++#define LARGE_PAGE_MASK (~(LARGE_PAGE_SIZE-1))
++// taken for SH style
++#define HPAGE_SIZE (1UL << HPAGE_SHIFT)
++#define HPAGE_MASK (~(HPAGE_SIZE-1))
++#define HUGETLB_PAGE_ORDER (HPAGE_SHIFT-PAGE_SHIFT)
++#endif
++
++
++#ifdef __KERNEL__
++
++#ifndef __ASSEMBLY__
++
++struct page;
++struct vm_area_struct;
++#ifndef CONFIG_CPU_CACHE_NONALIASING
++extern void copy_user_highpage(struct page *to, struct page *from,
++ unsigned long vaddr, struct vm_area_struct *vma);
++extern void clear_user_highpage(struct page *page, unsigned long vaddr);
++
++#define __HAVE_ARCH_COPY_USER_HIGHPAGE
++#define clear_user_highpage clear_user_highpage
++#else
++#define clear_user_page(page, vaddr, pg) clear_page(page)
++#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
++#endif
++
++void clear_page(void *page);
++void copy_page(void *to, void *from);
++
++#undef STRICT_MM_TYPECHECKS
++
++#ifdef STRICT_MM_TYPECHECKS
++/*
++ * These are used to make use of C type-checking..
++ */
++typedef struct { unsigned long pte; } pte_t;
++typedef struct { unsigned long pmd; } pmd_t;
++typedef struct { unsigned long pgd; } pgd_t;
++typedef struct { unsigned long pgprot; } pgprot_t;
++
++#define pte_val(x) ((x).pte)
++#define pmd_val(x) ((x).pmd)
++#define pgd_val(x) ((x).pgd)
++#define pgprot_val(x) ((x).pgprot)
++
++#define __pte(x) ((pte_t) { (x) } )
++#define __pmd(x) ((pmd_t) { (x) } )
++#define __pgd(x) ((pgd_t) { (x) } )
++#define __pgprot(x) ((pgprot_t) { (x) } )
++
++#else
++/*
++ * .. while these make it easier on the compiler
++ */
++typedef unsigned long pte_t;
++typedef unsigned long pmd_t;
++typedef unsigned long pgd_t;
++typedef unsigned long pgprot_t;
++
++#define pte_val(x) (x)
++#define pmd_val(x) (x)
++#define pgd_val(x) (x)
++#define pgprot_val(x) (x)
++
++#define __pte(x) (x)
++#define __pmd(x) (x)
++#define __pgd(x) (x)
++#define __pgprot(x) (x)
++
++#endif /* STRICT_MM_TYPECHECKS */
++typedef struct page *pgtable_t;
++
++#include <asm/memory.h>
++#include <asm-generic/getorder.h>
++
++#endif /* !__ASSEMBLY__ */
++
++#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
++ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
++
++#endif /* __KERNEL__ */
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/param.h linux-3.4.110/arch/nds32/include/asm/param.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/param.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/param.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,36 @@
++/*
++ * linux/arch/nds32/include/asm/param.h
++ *
++ * Copyright (C) 1995-1999 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_PARAM_H
++#define __ASM_PARAM_H
++
++#ifdef __KERNEL__
++
++# ifndef HZ
++# define HZ CONFIG_HZ /* Internal kernel timer frequency */
++# endif
++
++# define USER_HZ HZ /* User interfaces are in "ticks" */
++# define CLOCKS_PER_SEC (USER_HZ) /* like times() */
++#else
++# define HZ 100
++#endif
++
++//#define EXEC_PAGESIZE 4096
++
++#ifndef NOGROUP
++#define NOGROUP (-1)
++#endif
++
++/* max length of hostname */
++#define MAXHOSTNAMELEN 64
++
++#endif
++
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/parport.h linux-3.4.110/arch/nds32/include/asm/parport.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/parport.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/parport.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,19 @@
++/*
++ * linux/arch/nds32/include/asm/parport.h: NDS32-specific parport initialisation
++ *
++ * Copyright (C) 1999, 2000 Tim Waugh <tim@cyberelk.demon.co.uk>
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This file should only be included by drivers/parport/parport_pc.c.
++ */
++
++#ifndef __ASMNDS32_PARPORT_H
++#define __ASMNDS32_PARPORT_H
++
++static int __devinit parport_pc_find_isa_ports (int autoirq, int autodma);
++static int __devinit parport_pc_find_nonpci_ports (int autoirq, int autodma)
++{
++ return parport_pc_find_isa_ports (autoirq, autodma);
++}
++
++#endif /* !(_ASMNDS32_PARPORT_H) */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/pci.h linux-3.4.110/arch/nds32/include/asm/pci.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/pci.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/pci.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,77 @@
++/*
++ * linux/arch/nds32/include/asm/pci.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef ASMNDS32_PCI_H
++#define ASMNDS32_PCI_H
++
++#ifdef __KERNEL__
++#include <asm-generic/pci-dma-compat.h>
++
++#include <asm/hardware.h> /* for PCIBIOS_MIN_* */
++
++#define pcibios_scan_all_fns(a, b) 0
++
++static inline void pcibios_set_master(struct pci_dev *dev)
++{
++ /* No special bus mastering setup handling */
++}
++
++static inline void pcibios_penalize_isa_irq(int irq)
++{
++ /* We don't do dynamic PCI IRQ allocation */
++}
++
++/*
++ * The PCI address space does equal the physical memory address space.
++ * The networking and block device layers use this boolean for bounce
++ * buffer decisions.
++ */
++#define PCI_DMA_BUS_IS_PHYS (0)
++
++/*
++ * Whether pci_unmap_{single,page} is a nop depends upon the
++ * configuration.
++ */
++#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) dma_addr_t ADDR_NAME;
++#define DECLARE_PCI_UNMAP_LEN(LEN_NAME) __u32 LEN_NAME;
++#define pci_unmap_addr(PTR, ADDR_NAME) ((PTR)->ADDR_NAME)
++#define pci_unmap_addr_set(PTR, ADDR_NAME, VAL) (((PTR)->ADDR_NAME) = (VAL))
++#define pci_unmap_len(PTR, LEN_NAME) ((PTR)->LEN_NAME)
++#define pci_unmap_len_set(PTR, LEN_NAME, VAL) (((PTR)->LEN_NAME) = (VAL))
++
++#define HAVE_PCI_MMAP
++extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
++ enum pci_mmap_state mmap_state, int write_combine);
++
++extern void
++pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
++ struct resource *res);
++
++extern void
++pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
++ struct pci_bus_region *region);
++
++static inline struct resource *
++pcibios_select_root(struct pci_dev *pdev, struct resource *res)
++{
++ struct resource *root = NULL;
++
++ if (res->flags & IORESOURCE_IO)
++ root = &ioport_resource;
++ if (res->flags & IORESOURCE_MEM)
++ root = &iomem_resource;
++
++ return root;
++}
++
++#endif /* __KERNEL__ */
++
++/* Chances are this interrupt is wired PC-style ... */
++static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
++{
++ return channel ? 15 : 14;
++}
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/percpu.h linux-3.4.110/arch/nds32/include/asm/percpu.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/percpu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/percpu.h 2016-04-07 10:20:50.902079477 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/percpu.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_PERCPU
++#define __NDS32_PERCPU
++
++#include <asm-generic/percpu.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/pfm.h linux-3.4.110/arch/nds32/include/asm/pfm.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/pfm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/pfm.h 2016-04-07 10:20:50.906079632 +0200
+@@ -0,0 +1,16 @@
++#ifndef __PFM_H_
++#define __PFM_H_
++
++struct pcounter {
++ unsigned long long pfm0; /* value of $PFMC0 */
++ unsigned long long pfm1; /* value of $PFMC1 */
++ unsigned long long pfm2; /* value of $PFMC2 */
++};
++
++#ifdef __KERNEL__
++void sys_pfmctl(int event0, int event1, int event2, int start);
++int sys_getpfm(struct pcounter __user *p);
++int sys_setpfm(int pfm0, int pfm1, int pfm2, struct pcounter __user *p);
++#endif
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/pgalloc.h linux-3.4.110/arch/nds32/include/asm/pgalloc.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/pgalloc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/pgalloc.h 2016-04-07 10:20:50.906079632 +0200
+@@ -0,0 +1,104 @@
++/*
++ * linux/arch/nds32/include/asm/pgalloc.h
++ *
++ * Copyright (C) 2000-2001 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef _ASMNDS32_PGALLOC_H
++#define _ASMNDS32_PGALLOC_H
++
++#include <asm/processor.h>
++#include <asm/cacheflush.h>
++#include <asm/tlbflush.h>
++
++/*
++ * Since we have only two-level page tables, these are trivial
++ */
++#define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
++#define pmd_free(mm, pmd) do { } while (0)
++#define pgd_populate(mm, pmd, pte) BUG()
++#define pmd_pgtable(pmd) pmd_page(pmd)
++
++extern pgd_t *get_pgd_slow(struct mm_struct *mm);
++extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd);
++
++#define pgd_alloc(mm) get_pgd_slow(mm)
++#define pgd_free(mm, pgd) free_pgd_slow(mm, pgd)
++
++#define check_pgt_cache() do { } while (0)
++
++static inline pte_t *
++pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
++{
++ pte_t *pte;
++
++ pte = (pte_t *)__get_free_page(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO);
++
++ return pte;
++}
++
++static inline pgtable_t
++pte_alloc_one(struct mm_struct *mm, unsigned long addr)
++{
++ pgtable_t pte;
++
++ pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
++ if (pte)
++ cpu_dcache_wb_page((unsigned long)page_address(pte));
++
++ return pte;
++}
++
++/*
++ * Free one PTE table.
++ */
++static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
++{
++ if (pte) {
++ free_page((unsigned long)pte);
++ }
++}
++
++static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
++{
++ __free_page(pte);
++}
++
++/*
++ * Populate the pmdp entry with a pointer to the pte. This pmd is part
++ * of the mm address space.
++ *
++ * Ensure that we always set both PMD entries.
++ */
++static inline void
++pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
++{
++ unsigned long pte_ptr = (unsigned long)ptep;
++ unsigned long pmdval;
++
++ BUG_ON(mm != &init_mm);
++
++ /*
++ * The pmd must be loaded with the physical
++ * address of the PTE table
++ */
++ pmdval = __pa(pte_ptr) | _PAGE_KERNEL_TABLE;
++ set_pmd(pmdp, __pmd(pmdval));
++}
++
++static inline void
++pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
++{
++ unsigned long pmdval;
++
++ BUG_ON(mm == &init_mm);
++
++ pmdval = page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE;
++ set_pmd(pmdp, __pmd(pmdval));
++}
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/pgtable.h linux-3.4.110/arch/nds32/include/asm/pgtable.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/pgtable.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/pgtable.h 2016-04-07 10:20:50.910079787 +0200
+@@ -0,0 +1,429 @@
++/*
++ * linux/arch/nds32/include/asm/pgtable.h
++ *
++ * Copyright (C) 1995-2002 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef _ASMNDS32_PGTABLE_H
++#define _ASMNDS32_PGTABLE_H
++
++#include <asm-generic/4level-fixup.h>
++#include <asm-generic/sizes.h>
++
++#include <asm/memory.h>
++#include <asm/vmalloc.h>
++#include <asm/nds32.h>
++#ifndef __ASSEMBLY__
++#include <asm/fixmap.h>
++#endif
++
++#ifdef CONFIG_CACHE_L2
++#include <asm/l2_cache.h>
++#endif
++
++#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
++#define PGDIR_SHIFT 22
++#define PTRS_PER_PGD 1024
++#define PMD_SHIFT 22
++#define PTRS_PER_PMD 1
++#define PTRS_PER_PTE 1024
++#endif
++
++#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
++#define PGDIR_SHIFT 24
++#define PTRS_PER_PGD 256
++#define PMD_SHIFT 24
++#define PTRS_PER_PMD 1
++#define PTRS_PER_PTE 2048
++#endif
++
++#ifndef __ASSEMBLY__
++extern void __pte_error(const char *file, int line, unsigned long val);
++extern void __pmd_error(const char *file, int line, unsigned long val);
++extern void __pgd_error(const char *file, int line, unsigned long val);
++
++#define pte_ERROR(pte) __pte_error(__FILE__, __LINE__, pte_val(pte))
++#define pmd_ERROR(pmd) __pmd_error(__FILE__, __LINE__, pmd_val(pmd))
++#define pgd_ERROR(pgd) __pgd_error(__FILE__, __LINE__, pgd_val(pgd))
++#endif /* !__ASSEMBLY__ */
++
++#define PMD_SIZE (1UL << PMD_SHIFT)
++#define PMD_MASK (~(PMD_SIZE-1))
++#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
++#define PGDIR_MASK (~(PGDIR_SIZE-1))
++
++/*
++ * This is the lowest virtual address we can permit any user space
++ * mapping to be mapped at. This is particularly important for
++ * non-high vector CPUs.
++ */
++#define FIRST_USER_ADDRESS 0x8000
++
++#define VMALLOC_OFFSET (8 * 1024 * 1024)
++#define VMALLOC_START (((unsigned long)high_memory + VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
++#define VMALLOC_VMADDR(x) ((unsigned long)(x))
++
++
++#ifdef CONFIG_HIGHMEM
++#define CONSISTENT_BASE ((PKMAP_BASE) - (SZ_2M))
++#define CONSISTENT_END (PKMAP_BASE)
++#else
++#define CONSISTENT_BASE (FIXADDR_START - SZ_2M)
++#define CONSISTENT_END (FIXADDR_START)
++#endif
++#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT)
++
++#ifdef CONFIG_HIGHMEM
++#ifndef __ASSEMBLY__
++#include <asm/highmem.h>
++#endif
++#endif
++
++//# define VMALLOC_END (CONSISTENT_START - PAGE_SIZE)
++# define VMALLOC_END (0xf9000000)
++
++#define VMALLOC_RESERVE (128 << 20)
++#define MAXMEM (VMALLOC_END - PAGE_OFFSET - VMALLOC_RESERVE)
++#define MAXMEM_PFN PFN_DOWN(MAXMEM)
++
++#define FIRST_USER_PGD_NR 0
++#define USER_PTRS_PER_PGD ((TASK_SIZE/PGDIR_SIZE) + FIRST_USER_PGD_NR)
++
++/* L2 PTE */
++#define _PAGE_V (1UL << 0)
++
++#define _PAGE_M_XKRW (0UL << 1)
++#define _PAGE_M_UR_KR (1UL << 1)
++#define _PAGE_M_UR_KRW (2UL << 1)
++#define _PAGE_M_URW_KRW (3UL << 1)
++#define _PAGE_M_KR (5UL << 1)
++#define _PAGE_M_KRW (7UL << 1)
++
++#define _PAGE_D (1UL << 4)
++#define _PAGE_E (1UL << 5)
++#define _PAGE_A (1UL << 6)
++#define _PAGE_G (1UL << 7)
++
++#define _PAGE_C_DEV (0UL << 8)
++#define _PAGE_C_DEV_WB (1UL << 8)
++#define _PAGE_C_MEM (2UL << 8)
++#define _PAGE_C_MEM_SHRD_WB (4UL << 8)
++#define _PAGE_C_MEM_SHRD_WT (5UL << 8)
++#define _PAGE_C_MEM_WB (6UL << 8)
++#define _PAGE_C_MEM_WT (7UL << 8)
++
++#define _PAGE_L (1UL << 11)
++
++#ifndef CONFIG_NO_KERNEL_LARGE_PAGE
++#define _HAVE_PAGE_L (_PAGE_L)
++#else
++#define _HAVE_PAGE_L 0
++#endif
++#define _PAGE_FILE (1UL << 1)
++#define _PAGE_YOUNG 0
++#define _PAGE_M_MASK _PAGE_M_KRW
++#define _PAGE_C_MASK _PAGE_C_MEM_WT
++
++#ifdef CONFIG_SMP
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++#define _PAGE_CACHE_SHRD _PAGE_C_MEM_SHRD_WT
++#else
++#define _PAGE_CACHE_SHRD _PAGE_C_MEM_SHRD_WB
++#endif
++#else
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++#define _PAGE_CACHE_SHRD _PAGE_C_MEM_WT
++#else
++#define _PAGE_CACHE_SHRD _PAGE_C_MEM_WB
++#endif
++#endif
++
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++#define _PAGE_CACHE _PAGE_C_MEM_WT
++#else
++#define _PAGE_CACHE _PAGE_C_MEM_WB
++#endif
++
++/*
++ * + Level 1 descriptor (PMD)
++ */
++#define PMD_TYPE_TABLE 0
++
++#ifndef __ASSEMBLY__
++
++#define _PAGE_USER_TABLE PMD_TYPE_TABLE
++#define _PAGE_KERNEL_TABLE PMD_TYPE_TABLE
++
++#define PAGE_EXEC __pgprot(_PAGE_V | _PAGE_M_XKRW | _PAGE_E)
++#define PAGE_NONE __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_A)
++#define PAGE_READ __pgprot(_PAGE_V | _PAGE_M_UR_KR)
++#define PAGE_RDWR __pgprot(_PAGE_V | _PAGE_M_URW_KRW | _PAGE_D)
++#define PAGE_COPY __pgprot(_PAGE_V | _PAGE_M_UR_KR)
++
++#define PAGE_UXKRWX_V1 __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
++#define PAGE_UXKRWX_V2 __pgprot(_PAGE_V | _PAGE_M_XKRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
++#define PAGE_CACHE_L1 __pgprot(_HAVE_PAGE_L | _PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE)
++#define PAGE_MEMORY __pgprot(_HAVE_PAGE_L | _PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
++#define PAGE_KERNEL __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_E | _PAGE_G | _PAGE_CACHE_SHRD)
++#define PAGE_DEVICE __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D | _PAGE_G | _PAGE_C_DEV)
++#endif /* __ASSEMBLY__ */
++
++/* xwr */
++#define __P000 (PAGE_NONE | _PAGE_CACHE_SHRD)
++#define __P001 (PAGE_READ | _PAGE_CACHE_SHRD)
++#define __P010 (PAGE_COPY | _PAGE_CACHE_SHRD)
++#define __P011 (PAGE_COPY | _PAGE_CACHE_SHRD)
++#define __P100 (PAGE_EXEC | _PAGE_CACHE_SHRD)
++#define __P101 (PAGE_READ | _PAGE_E | _PAGE_CACHE_SHRD)
++#define __P110 (PAGE_COPY | _PAGE_E | _PAGE_CACHE_SHRD)
++#define __P111 (PAGE_COPY | _PAGE_E | _PAGE_CACHE_SHRD)
++
++#define __S000 (PAGE_NONE | _PAGE_CACHE_SHRD)
++#define __S001 (PAGE_READ | _PAGE_CACHE_SHRD)
++#define __S010 (PAGE_RDWR | _PAGE_CACHE_SHRD)
++#define __S011 (PAGE_RDWR | _PAGE_CACHE_SHRD)
++#define __S100 (PAGE_EXEC | _PAGE_CACHE_SHRD)
++#define __S101 (PAGE_READ | _PAGE_E | _PAGE_CACHE_SHRD)
++#define __S110 (PAGE_RDWR | _PAGE_E | _PAGE_CACHE_SHRD)
++#define __S111 (PAGE_RDWR | _PAGE_E | _PAGE_CACHE_SHRD)
++
++#ifndef __ASSEMBLY__
++/*
++ * ZERO_PAGE is a global shared page that is always zero: used
++ * for zero-mapped memory areas etc..
++ */
++extern struct page *empty_zero_page;
++#define ZERO_PAGE(vaddr) (empty_zero_page)
++
++#define pte_pfn(pte) (pte_val(pte) >> PAGE_SHIFT)
++#define pfn_pte(pfn,prot) (__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot)))
++
++#define pte_none(pte) !(pte_val(pte))
++#define pte_clear(mm,addr,ptep) set_pte_at((mm),(addr),(ptep), __pte(0))
++#define pte_page(pte) (pfn_to_page(pte_pfn(pte)))
++
++#define pte_index(address) (((address) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
++#define pte_offset_kernel(dir, address) ((pte_t *)pmd_page_kernel(*(dir)) + pte_index(address))
++#define pte_offset_map(dir, address) ((pte_t *)page_address(pmd_page(*(dir))) + pte_index(address))
++#define pte_offset_map_nested(dir, address) pte_offset_map(dir, address)
++#define pmd_page_kernel(pmd) ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
++
++#define pte_unmap(pte) do { } while (0)
++#define pte_unmap_nested(pte) do { } while (0)
++
++#define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
++
++static inline pgd_t *get_pgd( void){
++
++ return ( pgd_t *)phys_to_virt( GET_L1_PPTB() & L1_PPTB_mskBASE);
++}
++
++static inline void set_pgd( pgd_t *pgdp, pgd_t pgd){
++
++ /* TODO */
++}
++/*
++ * Set a level 1 translation table entry, and clean it out of
++ * any caches such that the MMUs can load it correctly.
++ */
++static inline void set_pmd( pmd_t *pmdp, pmd_t pmd){
++
++ *pmdp = pmd;
++#if !defined(CONFIG_CPU_DCACHE_DISABLE) && !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
++ __asm__ volatile ( "\n\tcctl %0, L1D_VA_WB" ::"r" ( pmdp) :"memory");
++ MSYNC( all);
++ DSB();
++#endif
++}
++
++/*
++ * Set a PTE and flush it out
++ */
++static inline void set_pte( pte_t *ptep, pte_t pte){
++
++ *ptep = pte;
++#if !defined(CONFIG_CPU_DCACHE_DISABLE) && !defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
++ __asm__ volatile ( "\n\tcctl %0, L1D_VA_WB" ::"r" ( ptep) :"memory");
++ MSYNC( all);
++ DSB();
++#endif
++}
++
++
++/*
++ * The following only work if pte_present() is true.
++ * Undefined behaviour if not..
++ */
++
++/*
++ * pte_write: this page is writeable for user mode
++ * pte_read: this page is readable for user mode
++ * pte_kernel_write: this page is writeable for kernel mode
++ *
++ * We don't have pte_kernel_read because kernel always can read.
++ *
++ * */
++
++#define pte_present(pte) (pte_val(pte) & _PAGE_V)
++#define pte_write(pte) ((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_URW_KRW)
++#define pte_read(pte) (((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_UR_KR) || \
++ ((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_UR_KRW) || \
++ ((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_URW_KRW))
++#define pte_kernel_write(pte) (((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_URW_KRW) || \
++ ((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_UR_KRW) || \
++ ((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_KRW) || \
++ (((pte_val(pte) & _PAGE_M_MASK) == _PAGE_M_XKRW) && pte_exec(pte)))
++#define pte_exec(pte) (pte_val(pte) & _PAGE_E)
++#define pte_dirty(pte) (pte_val(pte) & _PAGE_D)
++#define pte_young(pte) (pte_val(pte) & _PAGE_YOUNG)
++
++/*
++ * The following only works if pte_present() is not true.
++ */
++#define pte_file(pte) (pte_val(pte) & _PAGE_FILE)
++#define pte_to_pgoff(x) (pte_val(x) >> 2)
++#define pgoff_to_pte(x) __pte(((x) << 2) | _PAGE_FILE)
++
++#define PTE_FILE_MAX_BITS 29
++
++#define PTE_BIT_FUNC(fn,op) \
++static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
++
++static inline pte_t pte_wrprotect(pte_t pte)
++{
++ pte_val(pte) = pte_val(pte) & ~_PAGE_M_MASK;
++ pte_val(pte) = pte_val(pte) | _PAGE_M_UR_KR;
++ return pte;
++}
++
++static inline pte_t pte_mkwrite(pte_t pte)
++{
++ pte_val(pte) = pte_val(pte) & ~_PAGE_M_MASK;
++ pte_val(pte) = pte_val(pte) | _PAGE_M_URW_KRW;
++ return pte;
++}
++
++PTE_BIT_FUNC(exprotect, &= ~_PAGE_E);
++PTE_BIT_FUNC(mkexec, |= _PAGE_E);
++PTE_BIT_FUNC(mkclean, &= ~_PAGE_D);
++PTE_BIT_FUNC(mkdirty, |= _PAGE_D);
++PTE_BIT_FUNC(mkold, &= ~_PAGE_YOUNG);
++PTE_BIT_FUNC(mkyoung, |= _PAGE_YOUNG);
++static inline int pte_special(pte_t pte) { return 0; }
++static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
++
++/*
++ * Mark the prot value as uncacheable and unbufferable.
++ */
++#define pgprot_noncached(prot) __pgprot((pgprot_val(prot)&~_PAGE_C_MASK) | _PAGE_C_DEV)
++#define pgprot_writecombine(prot) __pgprot((pgprot_val(prot)&~_PAGE_C_MASK) | _PAGE_C_DEV_WB)
++
++#define pmd_none(pmd) (pmd_val(pmd)&0x1)
++#define pmd_present(pmd) (!pmd_none(pmd))
++#define pmd_bad(pmd) pmd_none(pmd)
++
++#define copy_pmd(pmdpd,pmdps) set_pmd((pmdpd), *(pmdps))
++#define pmd_clear(pmdp) set_pmd((pmdp), __pmd(1))
++
++static inline pmd_t __mk_pmd(pte_t *ptep, unsigned long prot)
++{
++ unsigned long ptr = (unsigned long)ptep;
++ pmd_t pmd;
++
++ /*
++ * The pmd must be loaded with the physical
++ * address of the PTE table
++ */
++
++ pmd_val(pmd) = __virt_to_phys(ptr) | prot;
++ return pmd;
++}
++
++
++#define pmd_page(pmd) virt_to_page(__va(pmd_val(pmd)))
++
++/*
++ * Permanent address of a page. We never have highmem, so this is trivial.
++ */
++#define pages_to_mb(x) ((x) >> (20 - PAGE_SHIFT))
++
++/*
++ * Conversion functions: convert a page and protection to a page entry,
++ * and a page entry and page directory to the page they refer to.
++ */
++#define mk_pte(page,prot) pfn_pte(page_to_pfn(page),prot)
++
++/*
++ * The "pgd_xxx()" functions here are trivial for a folded two-level
++ * setup: the pgd is never bad, and a pmd always exists (as it's folded
++ * into the pgd entry)
++ */
++#define pgd_none(pgd) (0)
++#define pgd_bad(pgd) (0)
++#define pgd_present(pgd) (1)
++#define pgd_clear(pgdp) do { } while (0)
++
++#define page_pte_prot(page,prot) mk_pte(page, prot)
++#define page_pte(page) mk_pte(page, __pgprot(0))
++/* Tom:
++ * L1PTE = $mr1 + ((virt >> PMD_SHIFT) << 2);
++ * L2PTE = (((virt >> PAGE_SHIFT) & (PTRS_PER_PTE -1 )) << 2);
++ * PPN = (phys & 0xfffff000);
++ *
++*/
++
++/* to find an entry in a page-table-directory */
++#define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1))
++#define pgd_offset(mm, address) ((mm)->pgd + pgd_index(address))
++/* to find an entry in a kernel page-table-directory */
++#define pgd_offset_k(addr) pgd_offset(&init_mm, addr)
++
++/* Find an entry in the second-level page table.. */
++#define pmd_offset(dir, addr) ((pmd_t *)(dir))
++
++static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
++{
++ const unsigned long mask = 0xfff;
++ pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
++ return pte;
++}
++
++extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
++
++/* Encode and decode a swap entry.
++ *
++ * We support up to 32GB of swap on 4k machines
++ */
++#define __swp_type(x) (((x).val >> 2) & 0x7f)
++#define __swp_offset(x) ((x).val >> 9)
++#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 9) })
++#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
++#define __swp_entry_to_pte(swp) ((pte_t) { (swp).val })
++
++/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
++/* FIXME: this is not correct */
++#define kern_addr_valid(addr) (1)
++
++#include <asm-generic/pgtable.h>
++
++/*
++ * We provide our own arch_get_unmapped_area to cope with VIPT caches.
++ */
++#define HAVE_ARCH_UNMAPPED_AREA
++
++/*
++ * remap a physical address `phys' of size `size' with page protection `prot'
++ * into virtual address `from'
++ */
++#define io_remap_pfn_range(vma,from,pfn,size,prot) \
++ remap_pfn_range(vma, from, pfn, size, prot)
++
++#define pgtable_cache_init() do { } while (0)
++
++#endif /* !__ASSEMBLY__ */
++
++#endif /* _ASMNDS32_PGTABLE_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/poll.h linux-3.4.110/arch/nds32/include/asm/poll.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/poll.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/poll.h 2016-04-07 10:20:50.910079787 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/poll.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASMNDS32_POLL_H
++#define __ASMNDS32_POLL_H
++
++#include <asm-generic/poll.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/posix_types.h linux-3.4.110/arch/nds32/include/asm/posix_types.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/posix_types.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/posix_types.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,40 @@
++/*
++ * arch/arm/include/asm/posix_types.h
++ *
++ * Copyright (C) 1996-1998 Russell King.
++ *
++ * 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.
++ *
++ * Changelog:
++ * 27-06-1996 RMK Created
++ */
++#ifndef __ARCH_NDS32_POSIX_TYPES_H
++#define __ARCH_NDS32_POSIX_TYPES_H
++
++/*
++ * This file is generally used by user-level software, so you need to
++ * be a little careful about namespace pollution etc. Also, we cannot
++ * assume GCC is being used.
++ */
++
++typedef unsigned short __kernel_mode_t;
++#define __kernel_mode_t __kernel_mode_t
++
++typedef unsigned short __kernel_nlink_t;
++#define __kernel_nlink_t __kernel_nlink_t
++
++typedef unsigned short __kernel_ipc_pid_t;
++#define __kernel_ipc_pid_t __kernel_ipc_pid_t
++
++typedef unsigned short __kernel_uid_t;
++typedef unsigned short __kernel_gid_t;
++#define __kernel_uid_t __kernel_uid_t
++
++typedef unsigned short __kernel_old_dev_t;
++#define __kernel_old_dev_t __kernel_old_dev_t
++
++#include <asm-generic/posix_types.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/processor.h linux-3.4.110/arch/nds32/include/asm/processor.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/processor.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/processor.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,133 @@
++/*
++ * linux/arch/nds32/include/asm/processor.h
++ */
++/* Copyright (C) 1995-1999 Russell King
++ *
++ * 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.
++ */
++/* ============================================================================
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is ptrace relative code for Andes NDS32 architecture.
++ * Original referred from ARM, fit to NDS32.
++ *
++ * Revision History:
++ *
++ * Oct.03.2007 Original from Tom, Shawn and Steven, refined by Harry.
++ *
++ * Note:
++ *
++ * ============================================================================
++ */
++#ifndef __ASM_NDS32_PROCESSOR_H
++#define __ASM_NDS32_PROCESSOR_H
++
++/*
++ * Default implementation of macro that returns current
++ * instruction pointer ("program counter").
++ */
++#define current_text_addr() ({ __label__ _l; _l: &&_l;})
++
++#ifdef __KERNEL__
++
++#include <asm/ptrace.h>
++#include <asm/procinfo.h>
++#include <asm/types.h>
++#include <asm/cpuver.h>
++#include <asm/sigcontext.h>
++
++#define KERNEL_STACK_SIZE PAGE_SIZE
++#define STACK_TOP TASK_SIZE
++#define STACK_TOP_MAX TASK_SIZE
++
++struct debug_info {
++ u32 address;
++ u16 insn;
++ u8 valid;
++};
++
++struct thread_struct {
++ /* fault info */
++ unsigned long address;
++ unsigned long trap_no;
++ unsigned long error_code;
++
++ struct fpu_struct fpu; /* Saved fpu/fpu emulator stuff. */
++ struct audio_struct audio;
++ struct debug_info debug; /* debugging */
++};
++
++#define INIT_THREAD { }
++
++#ifdef __NDS32_EB__
++#define PSW_DE PSW_mskBE
++#else
++#define PSW_DE 0x0
++#endif
++
++#ifdef CONFIG_WBNA
++#define PSW_valWBNA PSW_mskWBNA
++#else
++#define PSW_valWBNA 0x0
++#endif
++
++#define start_thread(regs,pc,sp) \
++({ \
++ unsigned long *stack = (unsigned long *)sp; \
++ set_fs(USER_DS); \
++ memzero(regs->uregs, sizeof(regs->uregs)); \
++ regs->NDS32_ipsw = (PSW_CPL_ANY | PSW_valWBNA | PSW_mskDT | PSW_mskIT | PSW_DE | PSW_mskGIE); \
++ regs->NDS32_ir0 = (PSW_CPL_ANY | PSW_valWBNA | PSW_mskDT | PSW_mskIT | PSW_DE | PSW_SYSTEM | PSW_INTL_1); \
++ regs->NDS32_ipc = pc; /* pc */ \
++ regs->NDS32_sp = sp; /* $sp */ \
++ regs->NDS32_r2 = stack[4]; /* $r2 (envp) */ \
++ regs->NDS32_r1 = stack[1]; /* $r1 (argv) */ \
++ regs->NDS32_r0 = stack[0]; /* $r0 (argc) */ \
++})
++
++
++/* Forward declaration, a strange C thing */
++struct task_struct;
++
++/* Free all resources held by a thread. */
++extern void release_thread(struct task_struct *);
++#ifdef CONFIG_FPU
++#ifndef CONFIG_UNLAZU_FPU //lazy fpu
++extern struct task_struct *last_task_used_math;
++#endif
++#endif
++#ifdef CONFIG_AUDIO
++#ifndef CONFIG_UNLAZY_AUDIO //lazy audio
++extern struct task_struct *last_task_used_audio;
++#endif
++#endif
++
++/* Prepare to copy thread state - unlazy all lazy status */
++#define prepare_to_copy(tsk) do { } while (0)
++
++unsigned long get_wchan(struct task_struct *p);
++
++#define cpu_relax() barrier()
++
++#define task_pt_regs(task) \
++ ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE \
++ - 8) - 1)
++
++/*
++ * Create a new kernel thread
++ */
++extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
++
++#define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)task_thread_info(tsk)))[1019])
++#define KSTK_ESP(tsk) (((unsigned long *)(4096+(unsigned long)task_thread_info(tsk)))[1017])
++
++
++#endif
++
++#endif /* __ASM_NDS32_PROCESSOR_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/proc-fns.h linux-3.4.110/arch/nds32/include/asm/proc-fns.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/proc-fns.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/proc-fns.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,88 @@
++/*
++ * linux/arch/nds32/include/asm/proc-fns.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_PROCFNS_H__
++#define __NDS32_PROCFNS_H__
++
++#define CPU_NAME n12
++
++#ifdef __KERNEL__
++
++#ifdef __STDC__
++#define ____cpu_fn(name,fn) name##fn
++#else
++#define ____cpu_fn(name,fn) name/**/fn
++#endif
++#define __cpu_fn(name,fn) ____cpu_fn(name,fn)
++
++#define cpu_proc_init __cpu_fn( CPU_NAME, _proc_init)
++#define cpu_proc_fin __cpu_fn( CPU_NAME, _proc_fin)
++#define cpu_do_idle __cpu_fn( CPU_NAME, _do_idle)
++#define cpu_reset __cpu_fn( CPU_NAME, _reset)
++#define cpu_switch_mm __cpu_fn( CPU_NAME, _switch_mm)
++
++#define cpu_dcache_inval_all __cpu_fn( CPU_NAME, _dcache_inval_all)
++#define cpu_dcache_wbinval_all __cpu_fn( CPU_NAME, _dcache_wbinval_all)
++#define cpu_dcache_inval_page __cpu_fn( CPU_NAME, _dcache_inval_page)
++#define cpu_dcache_wb_page __cpu_fn( CPU_NAME, _dcache_wb_page)
++#define cpu_dcache_wbinval_page __cpu_fn( CPU_NAME, _dcache_wbinval_page)
++#define cpu_dcache_inval_range __cpu_fn( CPU_NAME, _dcache_inval_range)
++#define cpu_dcache_wb_range __cpu_fn( CPU_NAME, _dcache_wb_range)
++#define cpu_dcache_wbinval_range __cpu_fn( CPU_NAME, _dcache_wbinval_range)
++
++#define cpu_icache_inval_all __cpu_fn( CPU_NAME, _icache_inval_all)
++#define cpu_icache_inval_page __cpu_fn( CPU_NAME, _icache_inval_page)
++#define cpu_icache_inval_range __cpu_fn( CPU_NAME, _icache_inval_range)
++
++#define cpu_cache_wbinval_page __cpu_fn( CPU_NAME, _cache_wbinval_page)
++#define cpu_cache_wbinval_range __cpu_fn( CPU_NAME, _cache_wbinval_range)
++#define cpu_cache_wbinval_range_check __cpu_fn( CPU_NAME, _cache_wbinval_range_check)
++
++#define cpu_dma_wb_range __cpu_fn( CPU_NAME, _dma_wb_range)
++#define cpu_dma_inval_range __cpu_fn( CPU_NAME, _dma_inval_range)
++#define cpu_dma_wbinval_range __cpu_fn( CPU_NAME, _dma_wbinval_range)
++
++#include <asm/page.h>
++
++struct mm_struct;
++struct vm_area_struct;
++extern void cpu_proc_init(void);
++extern void cpu_proc_fin(void);
++extern void cpu_do_idle(void);
++extern void cpu_reset(unsigned long reset);
++extern void cpu_switch_mm(struct mm_struct *mm);
++
++extern void cpu_dcache_inval_all(void);
++extern void cpu_dcache_wbinval_all(void);
++extern void cpu_dcache_inval_page(unsigned long page);
++extern void cpu_dcache_wb_page(unsigned long page);
++extern void cpu_dcache_wbinval_page(unsigned long page);
++extern void cpu_dcache_inval_range(unsigned long start, unsigned long end);
++extern void cpu_dcache_wb_range(unsigned long start, unsigned long end);
++extern void cpu_dcache_wbinval_range(unsigned long start, unsigned long end);
++
++extern void cpu_icache_inval_all(void);
++extern void cpu_icache_inval_page(unsigned long page);
++extern void cpu_icache_inval_range(unsigned long start, unsigned long end);
++
++extern void cpu_cache_wbinval_page(unsigned long page, int flushi);
++extern void cpu_cache_wbinval_range(unsigned long start,
++ unsigned long end, int flushi);
++extern void cpu_cache_wbinval_range_check(struct vm_area_struct *vma,
++ unsigned long start, unsigned long end);
++
++extern void cpu_dma_wb_range(unsigned long start, unsigned long end);
++extern void cpu_dma_inval_range(unsigned long start, unsigned long end);
++extern void cpu_dma_wbinval_range(unsigned long start, unsigned long end);
++
++#ifdef CONFIG_CACHE_L2
++#define cpu_L2cache_inval __cpu_fn(CPU_NAME, _L2cache_inval)
++#define cpu_L2cache_wb __cpu_fn(CPU_NAME, _L2cache_wb)
++extern void cpu_L2cache_inval(void);
++extern void cpu_L2cache_wb(void);
++#endif
++
++#endif /* __KERNEL__ */
++#endif /* __NDS32_PROCFNS_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/procinfo.h linux-3.4.110/arch/nds32/include/asm/procinfo.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/procinfo.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/procinfo.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,71 @@
++/*
++ * linux/arch/nds32/include/asm/procinfo.h
++ *
++ * Copyright (C) 1996-1999 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_PROCINFO_H
++#define __ASM_PROCINFO_H
++
++#ifndef __ASSEMBLY__
++
++/*
++ * These structure are defined in assembly
++ * ( nds32/mm/proc-nds32.S)
++ */
++struct proc_info_item {
++
++ const char *manufacturer;
++ const char *cpu_name;
++};
++
++/*
++ * Note! struct processor is always defined if we're
++ * using MULTI_CPU, otherwise this entry is unused,
++ * but still exists.
++ *
++ * NOTE! The following structure is defined by assembly
++ * language, NOT C code. For more information, check:
++ * arch/arm/mm/proc-*.S and arch/arm/kernel/head.S
++ */
++struct proc_info_list {
++
++ unsigned int cpu_val;
++ unsigned int cpu_mask;
++ const char *arch_name;
++ const char *elf_name;
++ unsigned int elf_hwcap;
++ struct proc_info_item *info;
++};
++
++extern unsigned int elf_hwcap;
++
++#endif /* __ASSEMBLY__ */
++
++#define HWCAP_MFUSR_PC 0x000001
++#define HWCAP_EXT 0x000002
++#define HWCAP_EXT2 0x000004
++#define HWCAP_FPU 0x000008
++#define HWCAP_AUDIO 0x000010
++#define HWCAP_BASE16 0x000020
++#define HWCAP_STRING 0x000040
++#define HWCAP_REDUCED_REGS 0x000080
++#define HWCAP_VIDEO 0x000100
++#define HWCAP_ENCRYPT 0x000200
++#define HWCAP_EDM 0x000400
++#define HWCAP_LMDMA 0x000800
++#define HWCAP_PFM 0x001000
++#define HWCAP_HSMP 0x002000
++#define HWCAP_TRACE 0x004000
++#define HWCAP_DIV 0x008000
++#define HWCAP_MAC 0x010000
++#define HWCAP_L2C 0x020000
++#define HWCAP_FPU_DP 0x040000
++#define HWCAP_V2 0x080000
++#define HWCAP_DX_REGS 0x100000
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ptrace.h linux-3.4.110/arch/nds32/include/asm/ptrace.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/ptrace.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/ptrace.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,119 @@
++/*
++ * linux/arch/nds32/include/asm/ptrace.h
++ *
++ * Copyright (C) 1996-2003 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_NDS32_PTRACE_H
++#define __ASM_NDS32_PTRACE_H
++
++#define PTRACE_GETREGS 12
++#define PTRACE_SETREGS 13
++#define PTRACE_GETFPREGS 14
++#define PTRACE_SETFPREGS 15
++#define PTRACE_GETAUREGS 18
++#define PTRACE_SETAUREGS 19
++
++#define PTRACE_OLDSETOPTIONS 21
++
++#define PTRACE_GET_THREAD_AREA 22
++
++#ifndef __ASSEMBLY__
++/* this struct defines the way the registers are stored on the
++ stack during a system call. */
++
++struct pt_regs {
++#if defined(CONFIG_ABI1)
++ long dummy[6];
++#endif
++ long uregs[44];
++};
++#define NDS32_osp uregs[43]
++#define NDS32_FUCOP_CTL uregs[42]
++#define NDS32_lp uregs[41]
++#define NDS32_gp uregs[40]
++#define NDS32_fp uregs[39]
++#define NDS32_r25 uregs[38]
++#define NDS32_r24 uregs[37]
++#define NDS32_r23 uregs[36]
++#define NDS32_r22 uregs[35]
++#define NDS32_r21 uregs[34]
++#define NDS32_r20 uregs[33]
++#define NDS32_r19 uregs[32]
++#define NDS32_r18 uregs[31]
++#define NDS32_r17 uregs[30]
++#define NDS32_r16 uregs[29]
++#define NDS32_r15 uregs[28]
++#define NDS32_r14 uregs[27]
++#define NDS32_r13 uregs[26]
++#define NDS32_r12 uregs[25]
++#define NDS32_r11 uregs[24]
++#define NDS32_r10 uregs[23]
++#define NDS32_r9 uregs[22]
++#define NDS32_r8 uregs[21]
++#define NDS32_r7 uregs[20]
++#define NDS32_r6 uregs[19]
++#define NDS32_r5 uregs[18]
++#define NDS32_r4 uregs[17]
++#define NDS32_r3 uregs[16]
++#define NDS32_r2 uregs[15]
++#define NDS32_r1 uregs[14]
++#define NDS32_r0 uregs[13]
++#if defined(CONFIG_HWZOL)
++#define NDS32_lc uregs[11]
++#define NDS32_le uregs[10]
++#define NDS32_lb uregs[9]
++#endif
++#define NDS32_pp1 uregs[8]
++#define NDS32_pp0 uregs[7]
++#define NDS32_pipc uregs[6]
++#define NDS32_pipsw uregs[5]
++#define NDS32_ORIG_r0 uregs[4]
++#define NDS32_sp uregs[3]
++#define NDS32_ipc uregs[2]
++#define NDS32_ipsw uregs[1]
++#define NDS32_ir0 uregs[0]
++
++#ifdef __KERNEL__
++#include <asm/bitfield.h>
++
++#define arch_has_single_step() (1)
++struct task_struct;
++extern void user_enable_single_step(struct task_struct *);
++extern void user_disable_single_step(struct task_struct *);
++
++#define user_mode(regs) (((regs)->NDS32_ipsw & PSW_mskPOM) == 0)
++
++#define interrupts_enabled(regs) (!((regs)->NDS32_ipsw & ~PSW_mskGIE))
++
++extern void show_regs(struct pt_regs *);
++
++/* Are the current registers suitable for user mode?
++ * (used to maintain security in signal handlers)
++ */
++static inline int valid_user_regs(struct pt_regs *regs)
++{
++ return user_mode(regs) && ((regs->NDS32_ipsw & PSW_mskGIE) == 1);
++}
++
++static inline unsigned long regs_return_value(struct pt_regs *regs)
++{
++ return regs->NDS32_r0;
++}
++
++
++#define instruction_pointer(regs) ((regs)->NDS32_ipc)
++
++#ifdef CONFIG_SMP
++extern unsigned long profile_pc(struct pt_regs *regs);
++#else
++#define profile_pc(regs) instruction_pointer(regs)
++#endif
++
++#endif /* __KERNEL__ */
++#endif /* __ASSEMBLY__ */
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/reg_access.h linux-3.4.110/arch/nds32/include/asm/reg_access.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/reg_access.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/reg_access.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,153 @@
++/*
++ * linux/arch/nds32/include/asm/reg_access.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_REG_ACCESS_H__
++#define __NDS32_REG_ACCESS_H__
++
++#ifndef __ASSEMBLY__
++#define DEFINE_GET_SYS_REG( reg) \
++inline static unsigned long GET_##reg( void){ \
++ unsigned long val; \
++ __asm__ volatile ( "mfsr %0, $"#reg :"=&r" (val) ::"memory"); \
++ return val; \
++}
++
++#define DEFINE_PUT_SYS_REG( reg) \
++inline static void SET_##reg( unsigned long val){ \
++ __asm__ volatile ( "\n\tmtsr %0, $"#reg \
++ "\n\tdsb" ::"r" ( val) :"memory"); \
++}
++
++#define DEFINE_PUT_SYS_REG_i( reg) \
++inline static void SET_##reg( unsigned long val){ \
++ __asm__ volatile ( "\n\tmtsr %0, $"#reg \
++ "\n\tisb" ::"r" ( val) :"memory"); \
++}
++#define DEFINE_SYS_REG_OP( reg) \
++DEFINE_GET_SYS_REG( reg); \
++DEFINE_PUT_SYS_REG( reg);
++
++#define DEFINE_SYS_REG_OP_i( reg) \
++DEFINE_GET_SYS_REG( reg); \
++DEFINE_PUT_SYS_REG_i( reg);
++
++DEFINE_SYS_REG_OP( CPU_VER);
++DEFINE_SYS_REG_OP( ICM_CFG);
++DEFINE_SYS_REG_OP( DCM_CFG);
++DEFINE_SYS_REG_OP( MMU_CFG);
++DEFINE_SYS_REG_OP( MSC_CFG);
++DEFINE_SYS_REG_OP( CORE_ID);
++DEFINE_SYS_REG_OP( FUCOP_EXIST);
++
++DEFINE_SYS_REG_OP_i( PSW);
++DEFINE_SYS_REG_OP( IPSW);
++DEFINE_SYS_REG_OP( P_IPSW);
++DEFINE_SYS_REG_OP( IVB);
++DEFINE_SYS_REG_OP( EVA);
++DEFINE_SYS_REG_OP( P_EVA);
++DEFINE_SYS_REG_OP( ITYPE);
++DEFINE_SYS_REG_OP( P_ITYPE);
++DEFINE_SYS_REG_OP( MERR);
++DEFINE_SYS_REG_OP( IPC);
++DEFINE_SYS_REG_OP( P_IPC);
++DEFINE_SYS_REG_OP( OIPC);
++DEFINE_SYS_REG_OP( P_P0);
++DEFINE_SYS_REG_OP( P_P1);
++DEFINE_SYS_REG_OP( INT_MASK);
++DEFINE_SYS_REG_OP( INT_PEND);
++DEFINE_SYS_REG_OP( INT_MASK2);
++DEFINE_SYS_REG_OP( INT_PEND2);
++DEFINE_SYS_REG_OP( INT_TRIGGER);
++
++DEFINE_SYS_REG_OP( MMU_CTL);
++DEFINE_SYS_REG_OP( L1_PPTB);
++DEFINE_SYS_REG_OP( TLB_VPN);
++DEFINE_SYS_REG_OP( TLB_DATA);
++DEFINE_SYS_REG_OP( TLB_MISC);
++DEFINE_SYS_REG_OP( VLPT_IDX);
++DEFINE_SYS_REG_OP( ILMB);
++DEFINE_SYS_REG_OP( DLMB);
++DEFINE_SYS_REG_OP( CACHE_CTL);
++DEFINE_SYS_REG_OP( HSMP_SADDR);
++DEFINE_SYS_REG_OP( HSMP_EADDR);
++
++DEFINE_SYS_REG_OP( EDM_CFG);
++DEFINE_SYS_REG_OP( EDMSW);
++DEFINE_SYS_REG_OP( EDM_CTL);
++DEFINE_SYS_REG_OP( EDM_DTR);
++DEFINE_SYS_REG_OP( BPMTC);
++DEFINE_SYS_REG_OP( DIMBR);
++DEFINE_SYS_REG_OP( TECR0);
++DEFINE_SYS_REG_OP( TECR1);
++
++DEFINE_SYS_REG_OP( BPC0);
++DEFINE_SYS_REG_OP( BPA0);
++DEFINE_SYS_REG_OP( BPAM0);
++DEFINE_SYS_REG_OP( BPV0);
++DEFINE_SYS_REG_OP( BPCID0);
++DEFINE_SYS_REG_OP( BPC1);
++DEFINE_SYS_REG_OP( BPA1);
++DEFINE_SYS_REG_OP( BPAM1);
++DEFINE_SYS_REG_OP( BPV1);
++DEFINE_SYS_REG_OP( BPCID1);
++DEFINE_SYS_REG_OP( BPC2);
++DEFINE_SYS_REG_OP( BPA2);
++DEFINE_SYS_REG_OP( BPAM2);
++DEFINE_SYS_REG_OP( BPV2);
++DEFINE_SYS_REG_OP( BPCID2);
++DEFINE_SYS_REG_OP( BPC3);
++DEFINE_SYS_REG_OP( BPA3);
++DEFINE_SYS_REG_OP( BPAM3);
++DEFINE_SYS_REG_OP( BPV3);
++DEFINE_SYS_REG_OP( BPCID3);
++DEFINE_SYS_REG_OP( BPC4);
++DEFINE_SYS_REG_OP( BPA4);
++DEFINE_SYS_REG_OP( BPAM4);
++DEFINE_SYS_REG_OP( BPV4);
++DEFINE_SYS_REG_OP( BPCID4);
++DEFINE_SYS_REG_OP( BPC5);
++DEFINE_SYS_REG_OP( BPA5);
++DEFINE_SYS_REG_OP( BPAM5);
++DEFINE_SYS_REG_OP( BPV5);
++DEFINE_SYS_REG_OP( BPCID5);
++DEFINE_SYS_REG_OP( BPC6);
++DEFINE_SYS_REG_OP( BPA6);
++DEFINE_SYS_REG_OP( BPAM6);
++DEFINE_SYS_REG_OP( BPV6);
++DEFINE_SYS_REG_OP( BPCID6);
++DEFINE_SYS_REG_OP( BPC7);
++DEFINE_SYS_REG_OP( BPA7);
++DEFINE_SYS_REG_OP( BPAM7);
++DEFINE_SYS_REG_OP( BPV7);
++DEFINE_SYS_REG_OP( BPCID7);
++
++DEFINE_SYS_REG_OP( PFMC0);
++DEFINE_SYS_REG_OP( PFMC1);
++DEFINE_SYS_REG_OP( PFMC2);
++DEFINE_SYS_REG_OP( PFM_CTL);
++
++DEFINE_SYS_REG_OP( SDZ_CTL);
++DEFINE_SYS_REG_OP( N12MISC_CTL);
++DEFINE_SYS_REG_OP( PRUSR_ACC_CTL);
++
++DEFINE_SYS_REG_OP( DMA_CFG);
++DEFINE_SYS_REG_OP( DMA_GCSW);
++DEFINE_SYS_REG_OP( DMA_CHNSEL);
++DEFINE_SYS_REG_OP( DMA_ACT);
++DEFINE_SYS_REG_OP( DMA_SETUP);
++DEFINE_SYS_REG_OP( DMA_ISADDR);
++DEFINE_SYS_REG_OP( DMA_ESADDR);
++DEFINE_SYS_REG_OP( DMA_TCNT);
++DEFINE_SYS_REG_OP( DMA_STATUS);
++DEFINE_SYS_REG_OP( DMA_2DSET);
++DEFINE_SYS_REG_OP( DMA_2DSCTL);
++
++DEFINE_SYS_REG_OP( FPCSR);
++DEFINE_SYS_REG_OP( FPCFG);
++DEFINE_SYS_REG_OP( FUCOP_CTL);
++
++#endif /* !__ASSEMBLY__ */
++
++#endif /* __NDS32_REG_ACCESS_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/resource.h linux-3.4.110/arch/nds32/include/asm/resource.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/resource.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/resource.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/resource.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_RESOURCE_H__
++#define __NDS32_RESOURCE_H__
++
++#include <asm-generic/resource.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/rtc.h linux-3.4.110/arch/nds32/include/asm/rtc.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/rtc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/rtc.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,43 @@
++/*
++ * linux/arch/nds32/include/asm/rtc.h
++ *
++ * Copyright (C) 2003 Deep Blue Solutions Ltd.
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef ASMNDS32_RTC_H
++#define ASMNDS32_RTC_H
++
++struct module;
++
++struct rtc_ops {
++ struct module *owner;
++ int (*open)(void);
++ void (*release)(void);
++ int (*ioctl)(unsigned int, unsigned long);
++
++ int (*read_time)(struct rtc_time *);
++ int (*set_time)(struct rtc_time *);
++ int (*read_alarm)(struct rtc_wkalrm *);
++ int (*set_alarm)(struct rtc_wkalrm *);
++ int (*proc)(char *buf);
++};
++
++void rtc_update(unsigned long, unsigned long);
++int register_rtc(struct rtc_ops *);
++void unregister_rtc(struct rtc_ops *);
++
++static inline int rtc_periodic_alarm(struct rtc_time *tm)
++{
++ return (tm->tm_year == -1) ||
++ ((unsigned)tm->tm_mon >= 12) ||
++ ((unsigned)(tm->tm_mday - 1) >= 31) ||
++ ((unsigned)tm->tm_hour > 23) ||
++ ((unsigned)tm->tm_min > 59) ||
++ ((unsigned)tm->tm_sec > 59);
++}
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/scatterlist.h linux-3.4.110/arch/nds32/include/asm/scatterlist.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/scatterlist.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/scatterlist.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,35 @@
++/*
++ * linux/arch/nds32/include/asm/scatterlist.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_SCATTERLIST_H
++#define _ASMNDS32_SCATTERLIST_H
++
++#include <asm/memory.h>
++#include <asm/types.h>
++#include <asm-generic/scatterlist.h>
++
++#if 0
++struct scatterlist {
++#ifdef CONFIG_DEBUG_SG
++ unsigned long sg_magic;
++#endif
++ unsigned long page_link;
++ unsigned int offset; /* buffer offset */
++ dma_addr_t dma_address; /* dma address */
++ unsigned int length; /* length */
++};
++
++/*
++ * These macros should be used after a pci_map_sg call has been done
++ * to get bus addresses of each of the SG entries and their lengths.
++ * You should only work with the number of sg entries pci_map_sg
++ * returns, or alternatively stop on the first sg_dma_len(sg) which
++ * is 0.
++ */
++#define sg_dma_address(sg) ((sg)->dma_address)
++#define sg_dma_len(sg) ((sg)->length)
++#endif
++
++#endif /* _ASMNDS32_SCATTERLIST_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/sections.h linux-3.4.110/arch/nds32/include/asm/sections.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/sections.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/sections.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/sections.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __NDS32_SECTIONS_H__
++#define __NDS32_SECTIONS_H__
++
++#include <asm-generic/sections.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/segment.h linux-3.4.110/arch/nds32/include/asm/segment.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/segment.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/segment.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,16 @@
++/*
++ * linux/arch/nds32/include/asm/segment.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASM_NDS32_SEGMENT_H
++#define __ASM_NDS32_SEGMENT_H
++
++#define __KERNEL_CS 0x0
++#define __KERNEL_DS 0x0
++
++#define __USER_CS 0x1
++#define __USER_DS 0x1
++
++#endif /* __ASM_NDS32_SEGMENT_H */
++
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/semaphore.h linux-3.4.110/arch/nds32/include/asm/semaphore.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/semaphore.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/semaphore.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,6 @@
++/*
++ * linux/arch/nds32/include/asm/semaphore.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#include <linux/semaphore.h>
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/semaphore-helper.h linux-3.4.110/arch/nds32/include/asm/semaphore-helper.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/semaphore-helper.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/semaphore-helper.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,89 @@
++/*
++ * linux/arch/nds32/include/asm/semaphore-helper.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef ASMNDS32_SEMAPHORE_HELPER_H
++#define ASMNDS32_SEMAPHORE_HELPER_H
++
++/*
++ * These two _must_ execute atomically wrt each other.
++ */
++static inline void wake_one_more(struct semaphore * sem)
++{
++ unsigned long flags;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ if (atomic_read(&sem->count) <= 0)
++ sem->waking++;
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++}
++
++static inline int waking_non_zero(struct semaphore *sem)
++{
++ unsigned long flags;
++ int ret = 0;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ if (sem->waking > 0) {
++ sem->waking--;
++ ret = 1;
++ }
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++/*
++ * waking non zero interruptible
++ * 1 got the lock
++ * 0 go to sleep
++ * -EINTR interrupted
++ *
++ * We must undo the sem->count down_interruptible() increment while we are
++ * protected by the spinlock in order to make this atomic_inc() with the
++ * atomic_read() in wake_one_more(), otherwise we can race. -arca
++ */
++static inline int waking_non_zero_interruptible(struct semaphore *sem,
++ struct task_struct *tsk)
++{
++ unsigned long flags;
++ int ret = 0;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ if (sem->waking > 0) {
++ sem->waking--;
++ ret = 1;
++ } else if (signal_pending(tsk)) {
++ atomic_inc(&sem->count);
++ ret = -EINTR;
++ }
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++/*
++ * waking_non_zero_try_lock:
++ * 1 failed to lock
++ * 0 got the lock
++ *
++ * We must undo the sem->count down_interruptible() increment while we are
++ * protected by the spinlock in order to make this atomic_inc() with the
++ * atomic_read() in wake_one_more(), otherwise we can race. -arca
++ */
++static inline int waking_non_zero_trylock(struct semaphore *sem)
++{
++ unsigned long flags;
++ int ret = 1;
++
++ spin_lock_irqsave(&semaphore_wake_lock, flags);
++ if (sem->waking <= 0)
++ atomic_inc(&sem->count);
++ else {
++ sem->waking--;
++ ret = 0;
++ }
++ spin_unlock_irqrestore(&semaphore_wake_lock, flags);
++ return ret;
++}
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/sembuf.h linux-3.4.110/arch/nds32/include/asm/sembuf.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/sembuf.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/sembuf.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,30 @@
++/*
++ * linux/arch/nds32/include/asm/sembuf.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_SEMBUF_H
++#define _ASMNDS32_SEMBUF_H
++
++/*
++ * The semid64_ds structure for arm architecture.
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct semid64_ds {
++ struct ipc64_perm sem_perm; /* permissions .. see ipc.h */
++ __kernel_time_t sem_otime; /* last semop time */
++ unsigned long __unused1;
++ __kernel_time_t sem_ctime; /* last change time */
++ unsigned long __unused2;
++ unsigned long sem_nsems; /* no. of semaphores in array */
++ unsigned long __unused3;
++ unsigned long __unused4;
++};
++
++#endif /* _ASMNDS32_SEMBUF_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/serial.h linux-3.4.110/arch/nds32/include/asm/serial.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/serial.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/serial.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,20 @@
++/*
++ * linux/arch/nds32/include/asm/serial.h
++ *
++ * Copyright (C) 1996 Russell King.
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Changelog:
++ * 15-10-1996 RMK Created
++ */
++
++#ifndef __ASM_SERIAL_H
++#define __ASM_SERIAL_H
++
++#define BASE_BAUD (CONFIG_UART_CLK / 16)
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/setup.h linux-3.4.110/arch/nds32/include/asm/setup.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/setup.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/setup.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,232 @@
++/*
++ * linux/arch/nds32/include/asm/setup.h
++ *
++ * Copyright (C) 1997-1999 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Structure passed to kernel to tell it about the
++ * hardware it's running on. See Documentation/arm/Setup
++ * for more info.
++ */
++#ifndef __ASMNDS32_SETUP_H
++#define __ASMNDS32_SETUP_H
++
++#define COMMAND_LINE_SIZE 256
++
++/* The list ends with an ATAG_NONE node. */
++#define ATAG_NONE 0x00000000
++
++struct tag_header {
++ u32 size;
++ u32 tag;
++};
++
++/* The list must start with an ATAG_CORE node */
++#define ATAG_CORE 0x54410001
++
++struct tag_core {
++ u32 flags; /* bit 0 = read-only */
++ u32 pagesize;
++ u32 rootdev;
++};
++
++/* it is allowed to have multiple ATAG_MEM nodes */
++#define ATAG_MEM 0x54410002
++
++struct tag_mem32 {
++ u32 size;
++ u32 start; /* physical start address */
++};
++
++/* VGA text type displays */
++#define ATAG_VIDEOTEXT 0x54410003
++
++struct tag_videotext {
++ u8 x;
++ u8 y;
++ u16 video_page;
++ u8 video_mode;
++ u8 video_cols;
++ u16 video_ega_bx;
++ u8 video_lines;
++ u8 video_isvga;
++ u16 video_points;
++};
++
++/* describes how the ramdisk will be used in kernel */
++#define ATAG_RAMDISK 0x54410004
++
++struct tag_ramdisk {
++ u32 flags; /* bit 0 = load, bit 1 = prompt */
++ u32 size; /* decompressed ramdisk size in _kilo_ bytes */
++ u32 start; /* starting block of floppy-based RAM disk image */
++};
++
++/*M Tom
++ * this one accidentally used virtual addresses - as such,
++ * it's deprecated.
++ * describes where the compressed ramdisk image lives (virtual address)
++ */
++#define ATAG_INITRD 0x54410005
++
++/* describes where the compressed ramdisk image lives (physical address) */
++#define ATAG_INITRD2 0x54420005
++
++struct tag_initrd {
++ u32 start; //M Tom va of start addr /* physical start address */
++ u32 size; //M Tom unzipped size /* size of compressed ramdisk image in bytes */
++};
++
++/* board serial number. "64 bits should be enough for everybody" */
++#define ATAG_SERIAL 0x54410006
++
++struct tag_serialnr {
++ u32 low;
++ u32 high;
++};
++
++/* board revision */
++#define ATAG_REVISION 0x54410007
++
++struct tag_revision {
++ u32 rev;
++};
++
++/* initial values for vesafb-type framebuffers. see struct screen_info
++ * in include/linux/tty.h
++ */
++#define ATAG_VIDEOLFB 0x54410008
++
++struct tag_videolfb {
++ u16 lfb_width;
++ u16 lfb_height;
++ u16 lfb_depth;
++ u16 lfb_linelength;
++ u32 lfb_base;
++ u32 lfb_size;
++ u8 red_size;
++ u8 red_pos;
++ u8 green_size;
++ u8 green_pos;
++ u8 blue_size;
++ u8 blue_pos;
++ u8 rsvd_size;
++ u8 rsvd_pos;
++};
++
++/* command line: \0 terminated string */
++#define ATAG_CMDLINE 0x54410009
++
++struct tag_cmdline {
++ char cmdline[COMMAND_LINE_SIZE];//M Tom
++};
++
++/* acorn RiscPC specific information */
++/*-d Tom
++#define ATAG_ACORN 0x41000101
++
++struct tag_acorn {
++ u32 memc_control_reg;
++ u32 vram_pages;
++ u8 sounddefault;
++ u8 adfsdrives;
++};
++*/
++#define ATAG_CPE 0x41000101
++struct tag_cpe {
++ u32 memc_control_reg;
++ u32 vram_pages;
++ u8 sounddefault;
++ u8 adfsdrives;
++};
++
++
++/* footbridge memory clock, see arch/arm/mach-footbridge/arch.c */
++#define ATAG_MEMCLK 0x41000402
++
++struct tag_memclk {
++ u32 fmemclk;
++};
++
++struct tag {
++ struct tag_header hdr;
++ union {
++ struct tag_core core;
++ struct tag_mem32 mem;
++ struct tag_videotext videotext;
++ struct tag_ramdisk ramdisk;
++ struct tag_initrd initrd;
++ struct tag_serialnr serialnr;
++ struct tag_revision revision;
++ struct tag_videolfb videolfb;
++ struct tag_cmdline cmdline;
++
++ /*
++ * Andes specific
++ */
++ struct tag_cpe cpe;
++
++ /*
++ * DC21285 specific
++ */
++ struct tag_memclk memclk;
++ } u;
++};
++
++struct tagtable {
++ u32 tag;
++ int (*parse)(const struct tag *);
++};
++
++#define tag_member_present(tag,member) \
++ ((unsigned long)(&((struct tag *)0L)->member + 1) \
++ <= (tag)->hdr.size * 4)
++
++#define tag_next(t) ((struct tag *)((u32 *)(t) + (t)->hdr.size))
++#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
++
++#define for_each_tag(t,base) \
++ for (t = base; t->hdr.size; t = tag_next(t))
++
++#ifdef __KERNEL__
++
++#define __tag __used __attribute__((__section__(".taglist")))
++#define __tagtable(tag, fn) \
++static struct tagtable __tagtable_##fn __tag = { tag, fn }
++
++/*
++ * Memory map description
++ */
++#ifdef CONFIG_ARCH_LH7A40X
++# define NR_BANKS 16
++#else
++# define NR_BANKS 8
++#endif
++
++struct meminfo {
++ int nr_banks;
++ struct {
++ unsigned long start;
++ unsigned long size;
++ int node;
++ } bank[NR_BANKS];
++};
++
++/*
++ * Early command line parameters.
++ */
++struct early_params {
++ const char *arg;
++ void (*fn)(char **p);
++};
++
++#define __early_param(name,fn) \
++static struct early_params __early_##fn __used \
++__attribute__((__section__("__early_param"))) = { name, fn }
++
++#endif
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/shmbuf.h linux-3.4.110/arch/nds32/include/asm/shmbuf.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/shmbuf.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/shmbuf.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,47 @@
++/*
++ * linux/arch/nds32/include/asm/shmbuf.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_SHMBUF_H
++#define _ASMNDS32_SHMBUF_H
++
++/*
++ * The shmid64_ds structure for arm architecture.
++ * Note extra padding because this structure is passed back and forth
++ * between kernel and user space.
++ *
++ * Pad space is left for:
++ * - 64-bit time_t to solve y2038 problem
++ * - 2 miscellaneous 32-bit values
++ */
++
++struct shmid64_ds {
++ struct ipc64_perm shm_perm; /* operation perms */
++ size_t shm_segsz; /* size of segment (bytes) */
++ __kernel_time_t shm_atime; /* last attach time */
++ unsigned long __unused1;
++ __kernel_time_t shm_dtime; /* last detach time */
++ unsigned long __unused2;
++ __kernel_time_t shm_ctime; /* last change time */
++ unsigned long __unused3;
++ __kernel_pid_t shm_cpid; /* pid of creator */
++ __kernel_pid_t shm_lpid; /* pid of last operator */
++ unsigned long shm_nattch; /* no. of current attaches */
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++struct shminfo64 {
++ unsigned long shmmax;
++ unsigned long shmmin;
++ unsigned long shmmni;
++ unsigned long shmseg;
++ unsigned long shmall;
++ unsigned long __unused1;
++ unsigned long __unused2;
++ unsigned long __unused3;
++ unsigned long __unused4;
++};
++
++#endif /* _ASMNDS32_SHMBUF_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/shmparam.h linux-3.4.110/arch/nds32/include/asm/shmparam.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/shmparam.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/shmparam.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,27 @@
++/*
++ * linux/arch/nds32/include/asm/shmparam.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_SHMPARAM_H
++#define _ASMNDS32_SHMPARAM_H
++
++/*
++ * This should be the size of the virtually indexed cache/ways,
++ * whichever is greater since the cache aliases every size/ways
++ * bytes.
++ */
++/*
++ * Reference ARM architecture, retain the previous code
++ * #define SHMLBA 0x4000
++ * #define REALSHMLBA (CACHE_SET( DCACHE) * CACHE_LINE_SIZE( DCACHE))
++ */
++#define SHMLBA (4 * PAGE_SIZE) /* attach addr a multiple of this */
++#define REALSHMLBA SHMLBA
++
++/*
++ * Enforce SHMLBA in shmat
++ */
++#define __ARCH_FORCE_SHMLBA
++
++#endif /* _ASMNDS32_SHMPARAM_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/sigcontext.h linux-3.4.110/arch/nds32/include/asm/sigcontext.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/sigcontext.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/sigcontext.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,81 @@
++/*
++ * linux/arch/nds32/include/asm/sigcontext.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_SIGCONTEXT_H
++#define _ASMNDS32_SIGCONTEXT_H
++
++/*
++ * Signal context structure - contains all info to do with the state
++ * before the signal handler was invoked. Note: only add new entries
++ * to the end of the structure.
++ */
++struct fpu_struct {
++ unsigned long fs_regs[32];
++ unsigned long long fd_regs[16];
++ unsigned long fpcsr;
++};
++
++struct audio_struct {
++ unsigned long auregs[32];
++};
++
++struct zol_struct {
++ unsigned long nds32_lc; /* $LC */
++ unsigned long nds32_le; /* $LE */
++ unsigned long nds32_lb; /* $LB */
++};
++
++struct sigcontext {
++ unsigned long trap_no;
++ unsigned long error_code;
++ unsigned long oldmask;
++ unsigned long nds32_r0;
++ unsigned long nds32_r1;
++ unsigned long nds32_r2;
++ unsigned long nds32_r3;
++ unsigned long nds32_r4;
++ unsigned long nds32_r5;
++ unsigned long nds32_r6;
++ unsigned long nds32_r7;
++ unsigned long nds32_r8;
++ unsigned long nds32_r9;
++ unsigned long nds32_r10;
++ unsigned long nds32_r11;
++ unsigned long nds32_r12;
++ unsigned long nds32_r13;
++ unsigned long nds32_r14;
++ unsigned long nds32_r15;
++ unsigned long nds32_r16;
++ unsigned long nds32_r17;
++ unsigned long nds32_r18;
++ unsigned long nds32_r19;
++ unsigned long nds32_r20;
++ unsigned long nds32_r21;
++ unsigned long nds32_r22;
++ unsigned long nds32_r23;
++ unsigned long nds32_r24;
++ unsigned long nds32_r25;
++ unsigned long nds32_fp; /* $r28 */
++ unsigned long nds32_gp; /* $r29 */
++ unsigned long nds32_lr; /* $r30 */
++ unsigned long nds32_sp; /* $r31 */
++ unsigned long nds32_ipc;
++ unsigned long fault_address;
++#if defined(CONFIG_FPU)
++ unsigned long used_math_flag;
++ /* FPU Registers */
++ struct fpu_struct fpu;
++#endif
++ /* Audio Registers */
++#if defined(CONFIG_AUDIO)
++ unsigned long used_audio_flag;
++ struct audio_struct audio;
++#endif
++#if defined(CONFIG_HWZOL)
++ struct zol_struct zol;
++#endif
++};
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/siginfo.h linux-3.4.110/arch/nds32/include/asm/siginfo.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/siginfo.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/siginfo.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/siginfo.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_SIGINFO_H
++#define _ASMNDS32_SIGINFO_H
++
++#include <asm-generic/siginfo.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/signal.h linux-3.4.110/arch/nds32/include/asm/signal.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/signal.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/signal.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,173 @@
++/*
++ * linux/arch/nds32/include/asm/signal.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_SIGNAL_H
++#define _ASMNDS32_SIGNAL_H
++
++#include <linux/types.h>
++
++/* Avoid too many header ordering problems. */
++struct siginfo;
++
++#ifdef __KERNEL__
++/* Most things should be clean enough to redefine this at will, if care
++ is taken to make libc match. */
++
++#define _NSIG 64
++#define _NSIG_BPW 32
++#define _NSIG_WORDS (_NSIG / _NSIG_BPW)
++
++typedef unsigned long old_sigset_t; /* at least 32 bits */
++
++typedef struct {
++ unsigned long sig[_NSIG_WORDS];
++} sigset_t;
++
++#else
++/* Here we must cater to libcs that poke about in kernel headers. */
++
++#define NSIG 32
++typedef unsigned long sigset_t;
++
++#endif /* __KERNEL__ */
++
++#define SIGHUP 1
++#define SIGINT 2
++#define SIGQUIT 3
++#define SIGILL 4
++#define SIGTRAP 5
++#define SIGABRT 6
++#define SIGIOT 6
++#define SIGBUS 7
++#define SIGFPE 8
++#define SIGKILL 9
++#define SIGUSR1 10
++#define SIGSEGV 11
++#define SIGUSR2 12
++#define SIGPIPE 13
++#define SIGALRM 14
++#define SIGTERM 15
++#define SIGSTKFLT 16
++#define SIGCHLD 17
++#define SIGCONT 18
++#define SIGSTOP 19
++#define SIGTSTP 20
++#define SIGTTIN 21
++#define SIGTTOU 22
++#define SIGURG 23
++#define SIGXCPU 24
++#define SIGXFSZ 25
++#define SIGVTALRM 26
++#define SIGPROF 27
++#define SIGWINCH 28
++#define SIGIO 29
++#define SIGPOLL SIGIO
++/*
++#define SIGLOST 29
++*/
++#define SIGPWR 30
++#define SIGSYS 31
++#define SIGUNUSED 31
++
++/* These should not be considered constants from userland. */
++#define SIGRTMIN 32
++#define SIGRTMAX _NSIG
++
++#define SIGSWI 32
++
++/*
++ * SA_FLAGS values:
++ *
++ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
++ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
++ * SA_SIGINFO deliver the signal with SIGINFO structs
++ * SA_THIRTYTWO delivers the signal in 32-bit mode, even if the task
++ * is running in 26-bit.
++ * SA_ONSTACK allows alternate signal stacks (see sigaltstack(2)).
++ * SA_RESTART flag to get restarting signals (which were the default long ago)
++ * SA_NODEFER prevents the current signal from being masked in the handler.
++ * SA_RESETHAND clears the handler when the signal is delivered.
++ *
++ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
++ * Unix names RESETHAND and NODEFER respectively.
++ */
++#define SA_NOCLDSTOP 0x00000001
++#define SA_NOCLDWAIT 0x00000002
++#define SA_SIGINFO 0x00000004
++#define SA_THIRTYTWO 0x02000000
++#define SA_RESTORER 0x04000000
++#define SA_ONSTACK 0x08000000
++#define SA_RESTART 0x10000000
++#define SA_NODEFER 0x40000000
++#define SA_RESETHAND 0x80000000
++
++#define SA_NOMASK SA_NODEFER
++#define SA_ONESHOT SA_RESETHAND
++
++
++/*
++ * sigaltstack controls
++ */
++#define SS_ONSTACK 1
++#define SS_DISABLE 2
++
++#define MINSIGSTKSZ 2048
++#define SIGSTKSZ 8192
++
++#ifdef __KERNEL__
++#define SA_IRQNOMASK 0x08000000
++#endif
++
++#include <asm-generic/signal-defs.h>
++
++#ifdef __KERNEL__
++struct old_sigaction {
++ __sighandler_t sa_handler;
++ old_sigset_t sa_mask;
++ unsigned long sa_flags;
++ __sigrestore_t sa_restorer;
++};
++
++struct sigaction {
++ __sighandler_t sa_handler;
++ unsigned long sa_flags;
++ __sigrestore_t sa_restorer;
++ sigset_t sa_mask; /* mask last for extensibility */
++};
++
++struct k_sigaction {
++ struct sigaction sa;
++};
++
++#else
++/* Here we must cater to libcs that poke about in kernel headers. */
++
++struct sigaction {
++ union {
++ __sighandler_t _sa_handler;
++ void (*_sa_sigaction)(int, struct siginfo *, void *);
++ } _u;
++ sigset_t sa_mask;
++ unsigned long sa_flags;
++ void (*sa_restorer)(void);
++};
++
++#define sa_handler _u._sa_handler
++#define sa_sigaction _u._sa_sigaction
++
++#endif /* __KERNEL__ */
++
++typedef struct sigaltstack {
++ void __user *ss_sp;
++ int ss_flags;
++ size_t ss_size;
++} stack_t;
++
++#ifdef __KERNEL__
++#include <asm/sigcontext.h>
++#define ptrace_signal_deliver(regs, cookie) do { } while (0)
++#endif
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/sizes.h linux-3.4.110/arch/nds32/include/asm/sizes.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/sizes.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/sizes.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,53 @@
++/*
++ * 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
++ */
++/* DO NOT EDIT!! - this file automatically generated
++ * from .s file by awk -f s2h.awk
++ */
++/* Size definitions
++ * Copyright (C) ARM Limited 1998. All rights reserved.
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __sizes_h
++#define __sizes_h 1
++
++/* handy sizes */
++#define SZ_1K 0x00000400
++#define SZ_4K 0x00001000
++#define SZ_8K 0x00002000
++#define SZ_16K 0x00004000
++#define SZ_64K 0x00010000
++#define SZ_128K 0x00020000
++#define SZ_256K 0x00040000
++#define SZ_512K 0x00080000
++
++#define SZ_1M 0x00100000
++#define SZ_2M 0x00200000
++#define SZ_4M 0x00400000
++#define SZ_8M 0x00800000
++#define SZ_16M 0x01000000
++#define SZ_32M 0x02000000
++#define SZ_64M 0x04000000
++#define SZ_128M 0x08000000
++#define SZ_256M 0x10000000
++#define SZ_512M 0x20000000
++
++#define SZ_1G 0x40000000
++#define SZ_2G 0x80000000
++
++#endif
++
++/* END */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/smp.h linux-3.4.110/arch/nds32/include/asm/smp.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/smp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/smp.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,42 @@
++/*
++ * linux/arch/nds32/include/asm/smp.h
++ *
++ * Copyright (C) 2004-2005 ARM Ltd.
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_NDS32_SMP_H
++#define __ASM_NDS32_SMP_H
++
++#include <linux/threads.h>
++#include <linux/cpumask.h>
++#include <linux/thread_info.h>
++
++#ifndef CONFIG_SMP
++# error "<asm-nds32/smp.h> included in non-SMP build"
++#endif
++
++/*
++ * at the moment, there's not a big penalty for changing CPUs
++ * (the >big< penalty is running SMP in the first place)
++ */
++#define PROC_CHANGE_PENALTY 15
++
++struct seq_file;
++
++/*
++ * Move global data into per-processor storage.
++ */
++extern void smp_store_cpu_info(unsigned int cpuid);
++
++#define raw_smp_processor_id() (unsigned int)(GET_CORE_ID()&CORE_ID_mskCOREID)
++
++extern void smp_init_cpus(void);
++extern void smp_send_timer(void);
++extern void arch_send_call_function_single_ipi(int cpu);
++extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
++
++#endif /* ifndef __ASM_NDS32_SMP_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/socket.h linux-3.4.110/arch/nds32/include/asm/socket.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/socket.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/socket.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/socket.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_SOCKET_H
++#define _ASMNDS32_SOCKET_H
++
++#include <asm-generic/socket.h>
++
++#endif /* _ASMNDS32_SOCKET_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/sockios.h linux-3.4.110/arch/nds32/include/asm/sockios.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/sockios.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/sockios.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,18 @@
++/*
++ * linux/arch/nds32/include/asm/sockios.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ARCH_NDS32_SOCKIOS_H
++#define __ARCH_NDS32_SOCKIOS_H
++
++/* Socket-level I/O control calls. */
++#define FIOSETOWN 0x8901
++#define SIOCSPGRP 0x8902
++#define FIOGETOWN 0x8903
++#define SIOCGPGRP 0x8904
++#define SIOCATMARK 0x8905
++#define SIOCGSTAMP 0x8906 /* Get stamp */
++#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/spec-ag101.h linux-3.4.110/arch/nds32/include/asm/spec-ag101.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/spec-ag101.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/spec-ag101.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,237 @@
++#ifndef __NDS32_AG101_SPECIFICATION_H__
++#define __NDS32_AG101_SPECIFICATION_H__
++
++#define UART0_PA_BASE 0x99600000
++#define UART0_VA_BASE 0xF9960000
++#define UART0_IRQ 7
++#define UART1_PA_BASE 0x98300000
++#define UART1_VA_BASE 0xF9830000
++#define UART1_IRQ 11
++#define CFC_FTCFC010_0_PA_BASE 0x98D00000
++#define CFC_FTCFC010_0_VA_BASE 0xF98D0000
++#define SDC_FTSDC010_0_PA_BASE 0x98e00000
++#define SDC_FTSDC010_0_VA_BASE 0xF98e0000
++#define SDMC_FTSDMC021_PA_BASE 0x90300000
++#define SDMC_FTSDMC021_VA_BASE 0xF9030000
++#define PCIC_FTPCI100_0_PA_BASE 0x90C00000
++#define PCIC_FTPCI100_0_VA_BASE 0xF90C0000
++#define PCIC_FTPCI100_0_VA_LIMIT 0xF90CFFFF
++#define PCIIO_PA_BASE 0x90C01000
++#define PCIIO_VA_BASE 0xFE901000
++#define PCIIO_0_PA_BASE 0x90C01000
++#define PCIIO_0_VA_BASE 0xFE901000
++#define PCIIO_VA_LIMIT 0xFE9FFFFF
++#define AHB_ATFAHBC020S_0_PA_BASE 0x90100000
++#define AHB_ATFAHBC020S_0_VA_BASE 0xF9010000
++
++/* DMAC */
++#define DMAC_FTDMAC020_PA_COUNT 1
++#define DMAC_FTDMAC020_PA_BASE 0x90400000
++#define DMAC_FTDMAC020_PA_LIMIT 0x90400FFF
++#define DMAC_FTDMAC020_PA_SIZE 0x00001000
++#define DMAC_FTDMAC020_0_PA_BASE 0x90400000
++#define DMAC_FTDMAC020_0_PA_LIMIT 0x90400FFF
++#define DMAC_FTDMAC020_0_PA_SIZE 0x00001000
++#define DMAC_FTDMAC020_VA_COUNT 1
++#define DMAC_FTDMAC020_VA_BASE 0xF9040000
++#define DMAC_FTDMAC020_VA_LIMIT 0xF9040FFF
++#define DMAC_FTDMAC020_VA_SIZE 0x00001000
++#define DMAC_FTDMAC020_0_VA_BASE 0xF9040000
++#define DMAC_FTDMAC020_0_VA_LIMIT 0xF9040FFF
++#define DMAC_FTDMAC020_0_VA_SIZE 0x00001000
++
++/* TIMER */
++#define TIMER_FTTMR010_PA_COUNT 1
++#define TIMER_FTTMR010_PA_BASE 0x98400000
++#define TIMER_FTTMR010_PA_LIMIT 0x98400FFF
++#define TIMER_FTTMR010_PA_SIZE 0x00001000
++#define TIMER_FTTMR010_0_PA_BASE 0x98400000
++#define TIMER_FTTMR010_0_PA_LIMIT 0x98400FFF
++#define TIMER_FTTMR010_0_PA_SIZE 0x00001000
++#define TIMER_FTTMR010_VA_COUNT 1
++#define TIMER_FTTMR010_VA_BASE 0xF9840000
++#define TIMER_FTTMR010_VA_LIMIT 0xF9840FFF
++#define TIMER_FTTMR010_VA_SIZE 0x00001000
++#define TIMER_FTTMR010_0_VA_BASE 0xF9840000
++#define TIMER_FTTMR010_0_VA_LIMIT 0xF9840FFF
++#define TIMER_FTTMR010_0_VA_SIZE 0x00001000
++
++/* RTC */
++#define RTC_FTRTC010_PA_COUNT 1
++#define RTC_FTRTC010_PA_BASE 0x98600000
++#define RTC_FTRTC010_PA_LIMIT 0x98600FFF
++#define RTC_FTRTC010_PA_SIZE 0x00001000
++#define RTC_FTRTC010_0_PA_BASE 0x98600000
++#define RTC_FTRTC010_0_PA_LIMIT 0x98600FFF
++#define RTC_FTRTC010_0_PA_SIZE 0x00001000
++#define RTC_FTRTC010_VA_COUNT 1
++#define RTC_FTRTC010_VA_BASE 0xF9860000
++#define RTC_FTRTC010_VA_LIMIT 0xF9860FFF
++#define RTC_FTRTC010_VA_SIZE 0x00001000
++#define RTC_FTRTC010_0_VA_BASE 0xF9860000
++#define RTC_FTRTC010_0_VA_LIMIT 0xF9860FFF
++#define RTC_FTRTC010_0_VA_SIZE 0x00001000
++
++/* WDT */
++#define WDT_FTWDT010_PA_COUNT 1
++#define WDT_FTWDT010_PA_BASE 0x98500000
++#define WDT_FTWDT010_PA_LIMIT 0x98500FFF
++#define WDT_FTWDT010_PA_SIZE 0x00001000
++#define WDT_FTWDT010_0_PA_BASE 0x98500000
++#define WDT_FTWDT010_0_PA_LIMIT 0x98500FFF
++#define WDT_FTWDT010_0_PA_SIZE 0x00001000
++#define WDT_FTWDT010_VA_COUNT 1
++#define WDT_FTWDT010_VA_BASE 0xF9850000
++#define WDT_FTWDT010_VA_LIMIT 0xF9850FFF
++#define WDT_FTWDT010_VA_SIZE 0x00001000
++#define WDT_FTWDT010_0_VA_BASE 0xF9850000
++#define WDT_FTWDT010_0_VA_LIMIT 0xF9850FFF
++#define WDT_FTWDT010_0_VA_SIZE 0x00001000
++
++/* GPIO */
++#define GPIO_FTGPIO010_PA_COUNT 1
++#define GPIO_FTGPIO010_PA_BASE 0x98700000
++#define GPIO_FTGPIO010_PA_LIMIT 0x98700FFF
++#define GPIO_FTGPIO010_PA_SIZE 0x00001000
++#define GPIO_FTGPIO010_0_PA_BASE 0x98700000
++#define GPIO_FTGPIO010_0_PA_LIMIT 0x98700FFF
++#define GPIO_FTGPIO010_0_PA_SIZE 0x00001000
++#define GPIO_FTGPIO010_VA_COUNT 1
++#define GPIO_FTGPIO010_VA_BASE 0xF9870000
++#define GPIO_FTGPIO010_VA_LIMIT 0xF9870FFF
++#define GPIO_FTGPIO010_VA_SIZE 0x00001000
++#define GPIO_FTGPIO010_0_VA_BASE 0xF9870000
++#define GPIO_FTGPIO010_0_VA_LIMIT 0xF9870FFF
++#define GPIO_FTGPIO010_0_VA_SIZE 0x00001000
++
++
++/* USB OTG */
++#define USB_FOTG2XX_0_PA_COUNT 1
++#define USB_FOTG2XX_0_PA_BASE 0x90B00000
++#define USB_FOTG2XX_0_PA_LIMIT 0x90B00FFF
++#define USB_FOTG2XX_0_PA_SIZE 0x00001000
++#define USB_FOTG2XX_0_VA_BASE 0xF90B0000
++#define USB_FOTG2XX_0_VA_LIMIT 0xF90B0FFF
++#define USB_FOTG2XX_0_VA_SIZE 0x00001000
++#define USB_FOTG2XX_0_IRQ 26
++#define USB_FOTG2XX_PA_COUNT 1
++#define USB_FOTG2XX_PA_BASE 0x90B00000
++#define USB_FOTG2XX_PA_LIMIT 0x90B00FFF
++#define USB_FOTG2XX_PA_SIZE 0x00001000
++#define USB_FOTG2XX_VA_BASE 0xF90B0000
++#define USB_FOTG2XX_VA_LIMIT 0xF90B0FFF
++#define USB_FOTG2XX_VA_SIZE 0x00001000
++#define USB_FOTG2XX_IRQ 26
++#define USB_FOTG2XX_IRQ_COUNT 1
++
++/* SSP */
++#define SSP_FTSSP010_PA_COUNT 1
++#define SSP_FTSSP010_PA_BASE 0x99400000
++#define SSP_FTSSP010_PA_LIMIT 0x99400FFF
++#define SSP_FTSSP010_PA_SIZE 0x00001000
++#define SSP_FTSSP010_0_PA_BASE 0x99400000
++#define SSP_FTSSP010_0_PA_LIMIT 0x99400FFF
++#define SSP_FTSSP010_0_PA_SIZE 0x00001000
++#define SSP_FTSSP010_VA_COUNT 1
++#define SSP_FTSSP010_VA_BASE 0xF9940000
++#define SSP_FTSSP010_VA_LIMIT 0xF9940FFF
++#define SSP_FTSSP010_VA_SIZE 0x00001000
++#define SSP_FTSSP010_0_VA_BASE 0xF9940000
++#define SSP_FTSSP010_0_VA_LIMIT 0xF9940FFF
++#define SSP_FTSSP010_0_VA_SIZE 0x00001000
++
++/* APBBRG */
++#define APBBRG_FTAPBBRG020S_PA_COUNT 1
++#define APBBRG_FTAPBBRG020S_PA_BASE 0x90500000
++#define APBBRG_FTAPBBRG020S_PA_LIMIT 0x90500FFF
++#define APBBRG_FTAPBBRG020S_PA_SIZE 0x00001000
++#define APBBRG_FTAPBBRG020S_0_PA_BASE 0x90500000
++#define APBBRG_FTAPBBRG020S_0_PA_LIMIT 0x90500FFF
++#define APBBRG_FTAPBBRG020S_0_PA_SIZE 0x00001000
++#define APBBRG_FTAPBBRG020S_1_PA_BASE 0x90E00000
++#define APBBRG_FTAPBBRG020S_1_PA_LIMIT 0x90E00FFF
++#define APBBRG_FTAPBBRG020S_1_PA_SIZE 0x00001000
++#define APBBRG_FTAPBBRG020S_VA_COUNT 1
++#define APBBRG_FTAPBBRG020S_VA_BASE 0xF9050000
++#define APBBRG_FTAPBBRG020S_VA_LIMIT 0xF9050FFF
++#define APBBRG_FTAPBBRG020S_VA_SIZE 0x00001000
++#define APBBRG_FTAPBBRG020S_0_VA_BASE 0xF9050000
++#define APBBRG_FTAPBBRG020S_0_VA_LIMIT 0xF9050FFF
++#define APBBRG_FTAPBBRG020S_0_VA_SIZE 0x00001000
++#define APBBRG_FTAPBBRG020S_1_VA_BASE 0xF90E0000
++#define APBBRG_FTAPBBRG020S_1_VA_LIMIT 0xF90E0FFF
++#define APBBRG_FTAPBBRG020S_1_VA_SIZE 0x00001000
++
++/* I2C */
++#define I2C_FTI2C010_PA_COUNT 1
++#define I2C_FTI2C010_PA_BASE 0x98A00000
++#define I2C_FTI2C010_PA_LIMIT 0x98A00FFF
++#define I2C_FTI2C010_PA_SIZE 0x00001000
++#define I2C_FTI2C010_0_PA_BASE 0x98A00000
++#define I2C_FTI2C010_0_PA_LIMIT 0x98A00FFF
++#define I2C_FTI2C010_0_PA_SIZE 0x00001000
++#define I2C_FTI2C010_VA_COUNT 1
++#define I2C_FTI2C010_VA_BASE 0xF98A0000
++#define I2C_FTI2C010_VA_LIMIT 0xF98A0FFF
++#define I2C_FTI2C010_VA_SIZE 0x00001000
++#define I2C_FTI2C010_0_VA_BASE 0xF98A0000
++#define I2C_FTI2C010_0_VA_LIMIT 0xF98A0FFF
++#define I2C_FTI2C010_0_VA_SIZE 0x00001000
++
++/* L2CC */
++#define L2CC_PA_BASE 0x90F00000 /* reserved */
++#define L2CC_VA_BASE 0xF90F0000 /* FIXME */
++
++#define LED_PA_COUNT 1
++#define LED_PA_BASE 0x902FF000
++#define LED_PA_LIMIT 0x90200FFF
++#define LED_PA_SIZE 0x00001000
++#define LED_0_PA_BASE 0x90200000
++#define LED_0_PA_LIMIT 0x90200FFF
++#define LED_0_PA_SIZE 0x00001000
++#define LED_VA_COUNT 1
++#define LED_VA_BASE 0xF9020000
++#define LED_VA_LIMIT 0xF9020000
++#define LED_VA_SIZE 0x00001000
++#define LED_0_VA_BASE 0xF9020000
++#define LED_0_VA_LIMIT 0xF9020000
++#define LED_0_VA_SIZE 0x00001000
++
++/* MAC */
++#define MAC_FTMAC100_PA_COUNT 1
++#define MAC_FTMAC100_PA_BASE 0x90900000
++#define MAC_FTMAC100_PA_LIMIT 0x90900FFF
++#define MAC_FTMAC100_PA_SIZE 0x00001000
++#define MAC_FTMAC100_0_PA_BASE 0x90900000
++#define MAC_FTMAC100_0_PA_LIMIT 0x90900FFF
++#define MAC_FTMAC100_0_PA_SIZE 0x00001000
++#define MAC_FTMAC100_1_PA_BASE 0x92000000
++#define MAC_FTMAC100_1_PA_LIMIT 0x92000FFF
++#define MAC_FTMAC100_1_PA_SIZE 0x00001000
++#define MAC_FTMAC100_VA_COUNT 1
++#define MAC_FTMAC100_VA_BASE 0xF9090000
++#define MAC_FTMAC100_VA_LIMIT 0xF9090FFF
++#define MAC_FTMAC100_VA_SIZE 0x00001000
++#define MAC_FTMAC100_0_VA_BASE 0xF9090000
++#define MAC_FTMAC100_0_VA_LIMIT 0xF9090FFF
++#define MAC_FTMAC100_0_VA_SIZE 0x00001000
++#define MAC_FTMAC100_1_VA_BASE 0xF9200000
++#define MAC_FTMAC100_1_VA_LIMIT 0xF9200FFF
++#define MAC_FTMAC100_1_VA_SIZE 0x00001000
++
++/* LCD */
++#define LCD_FTLCDC100_PA_COUNT 1
++#define LCD_FTLCDC100_PA_BASE 0x90600000
++#define LCD_FTLCDC100_PA_LIMIT 0x90600FFF
++#define LCD_FTLCDC100_PA_SIZE 0x00001000
++#define LCD_FTLCDC100_0_PA_BASE 0x90600000
++#define LCD_FTLCDC100_0_PA_LIMIT 0x90600FFF
++#define LCD_FTLCDC100_0_PA_SIZE 0x00001000
++#define LCD_FTLCDC100_VA_COUNT 1
++#define LCD_FTLCDC100_VA_BASE 0xF9060000
++#define LCD_FTLCDC100_VA_LIMIT 0xF9060FFF
++#define LCD_FTLCDC100_VA_SIZE 0x00001000
++#define LCD_FTLCDC100_0_VA_BASE 0xF9060000
++#define LCD_FTLCDC100_0_VA_LIMIT 0xF9060FFF
++#define LCD_FTLCDC100_0_VA_SIZE 0x00001000
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/spec-ag102.h linux-3.4.110/arch/nds32/include/asm/spec-ag102.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/spec-ag102.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/spec-ag102.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,167 @@
++#ifndef __NDS32_AG102_SPECIFICATION_H__
++#define __NDS32_AG102_SPECIFICATION_H__
++
++#define UART0_PA_BASE 0x94200000
++#define UART0_VA_BASE 0xF9420000
++#define UART0_IRQ 10
++#define UART1_PA_BASE 0x94600000
++#define UART1_VA_BASE 0xF9460000
++#define UART1_IRQ 11
++#define AMIC_PA_BASE 0x90F00000
++#define AMIC_VA_BASE 0xF90F0000
++#define GMAC_PA_BASE 0x90B00000
++#define GMAC_VA_BASE 0xF90B0000
++#define APBBR_PA_BASE 0x90D00000
++#define APBBR_VA_BASE 0xF90D0000
++#define GMAC_IRQ 25
++#define TIMER_PA_BASE 0x94900000
++#define TIMER_VA_BASE 0xF9490000
++#define L2CC_PA_BASE 0x90900000
++#define L2CC_VA_BASE 0xF9090000
++#define CFC_FTCFC010_0_PA_BASE 0x94000000
++#define CFC_FTCFC010_0_VA_BASE 0xF9400000
++#define SDC_FTSDC010_0_PA_BASE 0x94400000
++#define SDC_FTSDC010_0_VA_BASE 0xF9440000
++#define PCU_PA_BASE 0x94800000
++#define PCU_VA_BASE 0xF9480000
++#define PCIC_FTPCI100_0_PA_BASE 0x90000000
++#define PCIC_FTPCI100_0_VA_BASE 0xF9000000
++#define PCIC_FTPCI100_0_VA_LIMIT 0xF9000FFF
++#define PCIIO_PA_BASE 0x90001000
++#define PCIIO_VA_BASE 0xF8901000
++#define PCIIO_0_PA_BASE 0x90001000
++#define PCIIO_0_VA_BASE 0xF8901000
++#define PCIIO_VA_LIMIT 0xF89FFFFF
++#define LPC_IO_PA_BASE 0x90100000
++#define LPC_IO_VA_BASE 0xF9010000
++#define LPC_REG_PA_BASE 0x90200000
++#define LPC_REG_VA_BASE 0xF9020000
++#define LPC_IRQ 29
++#define GPU_PA_BASE 0x90A00000
++#define GPU_VA_BASE 0xFEA00000
++#define IDE_FTIDE020_VA_BASE 0xF9070000
++#define IDE_FTIDE020_PA_BASE 0x90700000
++#define IDE_FTIDE020_IRQ 1
++#define USB_FOTG2XX_0_PA_BASE 0x90800000
++#define USB_FOTG2XX_0_VA_BASE 0xF9080000
++#define USB_FOTG2XX_0_IRQ 26
++#define DDR2C_PA_BASE 0x90500000
++#define DDR2C_VA_BASE 0xF9050000
++#define GPIO_VA_BASE 0xF94C0000
++#define GPIO_PA_BASE 0x94C00000
++
++#define PLATFORM_LPC_IRQ_BASE 180
++#define PLATFORM_LPC_IRQ_TOTALCOUNT 22
++
++/* DMAC */
++#define DMAC_FTDMAC020_PA_COUNT 1
++#define DMAC_FTDMAC020_PA_BASE 0x90600000
++#define DMAC_FTDMAC020_PA_LIMIT 0x90600FFF
++#define DMAC_FTDMAC020_PA_SIZE 0x00001000
++#define DMAC_FTDMAC020_0_PA_BASE 0x90600000
++#define DMAC_FTDMAC020_0_PA_LIMIT 0x90600FFF
++#define DMAC_FTDMAC020_0_PA_SIZE 0x00001000
++#define DMAC_FTDMAC020_VA_COUNT 1
++#define DMAC_FTDMAC020_VA_BASE 0xF9060000
++#define DMAC_FTDMAC020_VA_LIMIT 0xF9060FFF
++#define DMAC_FTDMAC020_VA_SIZE 0x00001000
++#define DMAC_FTDMAC020_0_VA_BASE 0xF9060000
++#define DMAC_FTDMAC020_0_VA_LIMIT 0xF9060FFF
++#define DMAC_FTDMAC020_0_VA_SIZE 0x00001000
++
++/* TIMER */
++#define TIMER_FTTMR010_PA_COUNT 1
++#define TIMER_FTTMR010_PA_BASE 0x94900000
++#define TIMER_FTTMR010_PA_LIMIT 0x94900FFF
++#define TIMER_FTTMR010_PA_SIZE 0x00001000
++#define TIMER_FTTMR010_0_PA_BASE 0x94900000
++#define TIMER_FTTMR010_0_PA_LIMIT 0x94900FFF
++#define TIMER_FTTMR010_0_PA_SIZE 0x00001000
++#define TIMER_FTTMR010_VA_COUNT 1
++#define TIMER_FTTMR010_VA_BASE 0xF9490000
++#define TIMER_FTTMR010_VA_LIMIT 0xF9490FFF
++#define TIMER_FTTMR010_VA_SIZE 0x00001000
++#define TIMER_FTTMR010_0_VA_BASE 0xF9490000
++#define TIMER_FTTMR010_0_VA_LIMIT 0xF9490FFF
++#define TIMER_FTTMR010_0_VA_SIZE 0x00001000
++
++/* WDT */
++#define WDT_FTWDT010_PA_COUNT 1
++#define WDT_FTWDT010_PA_BASE 0x94A00000
++#define WDT_FTWDT010_PA_LIMIT 0x94A00FFF
++#define WDT_FTWDT010_PA_SIZE 0x00001000
++#define WDT_FTWDT010_0_PA_BASE 0x94A00000
++#define WDT_FTWDT010_0_PA_LIMIT 0x94A00FFF
++#define WDT_FTWDT010_0_PA_SIZE 0x00001000
++#define WDT_FTWDT010_VA_COUNT 1
++#define WDT_FTWDT010_VA_BASE 0xF94A0000
++#define WDT_FTWDT010_VA_LIMIT 0xF94A0FFF
++#define WDT_FTWDT010_VA_SIZE 0x00001000
++#define WDT_FTWDT010_0_VA_BASE 0xF94A0000
++#define WDT_FTWDT010_0_VA_LIMIT 0xF94A0FFF
++#define WDT_FTWDT010_0_VA_SIZE 0x00001000
++
++/* RTC */
++#define RTC_FTRTC010_PA_COUNT 1
++#define RTC_FTRTC010_PA_BASE 0x94B00000
++#define RTC_FTRTC010_PA_LIMIT 0x94B00FFF
++#define RTC_FTRTC010_PA_SIZE 0x00001000
++#define RTC_FTRTC010_0_PA_BASE 0x94B00000
++#define RTC_FTRTC010_0_PA_LIMIT 0x94B00FFF
++#define RTC_FTRTC010_0_PA_SIZE 0x00001000
++#define RTC_FTRTC010_VA_COUNT 1
++#define RTC_FTRTC010_VA_BASE 0xF94B0000
++#define RTC_FTRTC010_VA_LIMIT 0xF94B0FFF
++#define RTC_FTRTC010_VA_SIZE 0x00001000
++#define RTC_FTRTC010_0_VA_BASE 0xF94B0000
++#define RTC_FTRTC010_0_VA_LIMIT 0xF94B0FFF
++#define RTC_FTRTC010_0_VA_SIZE 0x00001000
++
++/* GPIO */
++#define GPIO_FTGPIO010_PA_COUNT 1
++#define GPIO_FTGPIO010_PA_BASE 0x94C00000
++#define GPIO_FTGPIO010_PA_LIMIT 0x94C00FFF
++#define GPIO_FTGPIO010_PA_SIZE 0x00001000
++#define GPIO_FTGPIO010_0_PA_BASE 0x94C00000
++#define GPIO_FTGPIO010_0_PA_LIMIT 0x94C00FFF
++#define GPIO_FTGPIO010_0_PA_SIZE 0x00001000
++#define GPIO_FTGPIO010_VA_COUNT 1
++#define GPIO_FTGPIO010_VA_BASE 0xF94C0000
++#define GPIO_FTGPIO010_VA_LIMIT 0xF94C0FFF
++#define GPIO_FTGPIO010_VA_SIZE 0x00001000
++#define GPIO_FTGPIO010_0_VA_BASE 0xF94C0000
++#define GPIO_FTGPIO010_0_VA_LIMIT 0xF94C0FFF
++#define GPIO_FTGPIO010_0_VA_SIZE 0x00001000
++
++/* SSP */
++#define SSP_FTSSP010_PA_BASE 0x94500000
++#define SSP_FTSSP010_0_PA_BASE 0x94500000
++#define SSP_FTSSP010_VA_BASE 0xF9450000
++#define SSP_FTSSP010_0_VA_BASE 0xF9450000
++
++/* SPI */
++#define SPI_FTSSP010_PA_BASE 0x94100000
++#define SPI_FTSSP010_0_PA_BASE 0x94100000
++#define SPI_FTSSP010_VA_BASE 0xF9410000
++#define SPI_FTSSP010_0_VA_BASE 0xF9410000
++
++/* AHB Controller */
++#define AHB_ATFAHBC020S_0_PA_BASE 0x90C00000
++#define AHB_ATFAHBC020S_0_VA_BASE 0xF90C0000
++
++#define I2C_FTI2C010_PA_COUNT 1
++#define I2C_FTI2C010_PA_BASE 0x94E00000
++#define I2C_FTI2C010_PA_LIMIT 0x94E00FFF
++#define I2C_FTI2C010_PA_SIZE 0x00001000
++#define I2C_FTI2C010_0_PA_BASE 0x94E00000
++#define I2C_FTI2C010_0_PA_LIMIT 0x94E00FFF
++#define I2C_FTI2C010_0_PA_SIZE 0x00001000
++#define I2C_FTI2C010_VA_COUNT 1
++#define I2C_FTI2C010_VA_BASE 0xF94E0000
++#define I2C_FTI2C010_VA_LIMIT 0xF94E0FFF
++#define I2C_FTI2C010_VA_SIZE 0x00001000
++#define I2C_FTI2C010_0_VA_BASE 0xF94E0000
++#define I2C_FTI2C010_0_VA_LIMIT 0xF94E0FFF
++#define I2C_FTI2C010_0_VA_SIZE 0x00001000
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/spec.h linux-3.4.110/arch/nds32/include/asm/spec.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/spec.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/spec.h 2016-04-07 10:20:50.914079941 +0200
+@@ -0,0 +1,510 @@
++/*
++ * linux/arch/nds32/include/asm/spec.h
++ *
++ * AG101 Platform Independent Specification
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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
++ *
++ * ChangeLog
++ *
++ * Luke Lee 09/14/2005 Created.
++ * 09/15/2005 Completed.
++ */
++
++#ifndef __FARADAY_PLATFORM_INDEPENDENT_SPECIFICATION__
++#define __FARADAY_PLATFORM_INDEPENDENT_SPECIFICATION__
++
++#include <asm/glue.h>
++#ifdef CONFIG_PLAT_AG102
++#include <asm/spec-ag102.h>
++#else
++#include <asm/spec-ag101.h>
++#endif
++
++/*
++ * Platform dependent specification
++ */
++#define PLATFORM_NAME "Andes AG101"
++
++/*
++ * Component counts
++ */
++
++/* INTC */
++#define INTC_COUNT 2
++#define INTC_FTINTC010_COUNT 2
++/* TIMER */
++#define TIMER_COUNT 1
++#define TIMER_FTTMR010_COUNT 1
++/* SSP */
++#define SSP_COUNT 1
++#define SSP_FTSSP010_COUNT 1
++/* PMU */
++#define PMU_COUNT 1
++#define PMU_FTPMU010_COUNT 1
++/* MAC */
++#define MAC_COUNT 1
++#define MAC_FTMAC100_COUNT 1
++
++/* SDC */
++#define SDC_COUNT 1
++#define SDC_FTSDC010_COUNT 1
++/* AHBDMA */
++#define AHBDMA_COUNT 1
++/* APBDMA */
++#define APBDMA_COUNT 1
++/* RTC */
++#define RTC_COUNT 1
++#define RTC_FTRTC010_COUNT 1
++/* WDT */
++#define WDT_COUNT 1
++#define WDT_FTWDT010_COUNT 1
++/* GPIO */
++#define GPIO_COUNT 1
++#define GPIO_FTGPIO010_COUNT 1
++/* CFC */
++#define CFC_COUNT 1
++#define CFC_FTCFC010_COUNT 1
++/* LCD */
++#define LCD_COUNT 1
++#define LCD_FTLCDC100_COUNT 1
++/* I2C */
++#define I2C_COUNT 1
++#define I2C_FTI2C010_COUNT 1
++/* USB */
++#define USB_COUNT 3
++#define USB_FOTG2XX_COUNT 1
++#define USB_FUSBH200_COUNT 1
++#define USB_FUSB220_COUNT 1
++/* DMAC */
++#define DMAC_COUNT 1
++#define DMAC_FTDMAC020_COUNT 1
++/* KMI */
++#define KMI_COUNT 2
++#define KMI_FTKBC010_COUNT 2
++/* PCI */
++#define PCI_COUNT 1
++/* PCIMEM */
++#define PCIMEM_COUNT 1
++/* PCIIO */
++#define PCIIO_COUNT 1
++/* PCIC */
++#define PCIC_COUNT 1
++#define PCIC_FTPCI100_COUNT 1
++
++/*
++ * Hierarchial Component IDs
++ */
++
++#define PLATFORM_AHBDMA_DMAC_FTDMAC020_ID 0
++#define PLATFORM_APBDMA_APBBRG_FTAPBBRG020S_ID 0
++
++/*
++ * Number of interrupts
++ */
++
++#define PLATFORM_IRQ_TOTALCOUNT 32
++#define PLATFORM_AHBDMA_IRQ_TOTALCOUNT 8
++#define PLATFORM_APBDMA_IRQ_TOTALCOUNT 4
++
++#define PLATFORM_IRQ_BASE 0
++#define PLATFORM_AHBDMA_IRQ_BASE 64
++#define PLATFORM_APBDMA_IRQ_BASE 72
++#define PLATFORM_PCI_IRQ_BASE 176
++#define PLATFORM_INTERRUPTS 202
++
++/*
++ * IRQ trigger level and trigger mode
++ */
++
++#define PLATFORM_IRQ_TRIGGER_MODE 0x000EC880
++#define PLATFORM_IRQ_TRIGGER_LEVEL 0x10000000
++#define PLATFORM_AHBDMA_IRQ_TRIGGER_MODE 0x00000000
++#define PLATFORM_AHBDMA_IRQ_TRIGGER_LEVEL 0xFFFFFFFF
++#define PLATFORM_APBDMA_IRQ_TRIGGER_MODE 0x00000000
++#define PLATFORM_APBDMA_IRQ_TRIGGER_LEVEL 0xFFFFFFFF
++
++/*
++ * Interrupt numbers of Hierarchical Architecture
++ */
++
++/* AHBDMA */
++#define PLATFORM_AHBDMA_IRQ 21
++
++/* APBDMA */
++#define PLATFORM_APBDMA_IRQ 24
++
++/* PCI */
++#ifdef CONFIG_XC5_PCI
++#define PLATFORM_PCI_IRQ 10
++#else
++#define PLATFORM_PCI_IRQ 28
++#endif
++
++
++/*
++ * Interrrupt numbers
++ */
++
++/* TIMER */
++#define TIMER_FTTMR010_IRQ_COUNT 3
++#define TIMER_FTTMR010_IRQ0 19
++#define TIMER_FTTMR010_0_IRQ0 19
++#define TIMER_FTTMR010_IRQ1 14
++#define TIMER_FTTMR010_0_IRQ1 14
++#define TIMER_FTTMR010_IRQ2 15
++#define TIMER_FTTMR010_0_IRQ2 15
++
++/* SSP */
++#define SSP_FTSSP010_IRQ_COUNT 1
++#define SSP_FTSSP010_IRQ 6
++#define SSP_FTSSP010_0_IRQ 6
++
++/* MAC */
++#define MAC_FTMAC100_IRQ_COUNT 1
++#define MAC_FTMAC100_IRQ 25
++#define MAC_FTMAC100_0_IRQ 25
++#define MAC_FTMAC100_1_IRQ 133
++
++/* SDC */
++#define SDC_FTSDC010_IRQ_COUNT 1
++#define SDC_FTSDC010_IRQ 5
++#define SDC_FTSDC010_0_IRQ 5
++
++/* RTC */
++#define RTC_FTRTC010_IRQ_COUNT 2
++#define RTC_FTRTC010_IRQ0 17
++#define RTC_FTRTC010_0_IRQ0 17
++#define RTC_FTRTC010_IRQ1 18
++#define RTC_FTRTC010_0_IRQ1 18
++
++/* WDT */
++#define WDT_FTWDT010_IRQ_COUNT 1
++#define WDT_FTWDT010_IRQ 16
++#define WDT_FTWDT010_0_IRQ 16
++
++/* GPIO */
++#define GPIO_FTGPIO010_IRQ_COUNT 1
++#define GPIO_FTGPIO010_IRQ 13
++#define GPIO_FTGPIO010_0_IRQ 13
++
++/* CFC */
++#define CFC_FTCFC010_IRQ_COUNT 2
++#define CFC_FTCFC010_IRQ0 0
++#define CFC_FTCFC010_0_IRQ0 0
++#define CFC_FTCFC010_IRQ1 1
++#define CFC_FTCFC010_0_IRQ1 1
++
++/* LCD */
++#define LCD_FTLCDC100_IRQ_COUNT 1
++#define LCD_FTLCDC100_IRQ 20
++#define LCD_FTLCDC100_0_IRQ 20
++
++/* I2C */
++#define I2C_FTI2C010_IRQ_COUNT 1
++#define I2C_FTI2C010_IRQ 3
++#define I2C_FTI2C010_0_IRQ 3
++
++/* USB */
++#define USB_FUSBH200_IRQ_COUNT 1
++#define USB_FUSBH200_IRQ 29
++#define USB_FUSBH200_0_IRQ 29
++#define USB_FUSB220_IRQ_COUNT 1
++#define USB_FUSB220_IRQ 26
++#define USB_FUSB220_0_IRQ 26
++
++/* DMAC */
++#define DMAC_FTDMAC020_IRQ_COUNT 8
++#define DMAC_FTDMAC020_IRQ0 64
++#define DMAC_FTDMAC020_0_IRQ0 64
++#define DMAC_FTDMAC020_IRQ1 65
++#define DMAC_FTDMAC020_0_IRQ1 65
++#define DMAC_FTDMAC020_IRQ2 66
++#define DMAC_FTDMAC020_0_IRQ2 66
++#define DMAC_FTDMAC020_IRQ3 67
++#define DMAC_FTDMAC020_0_IRQ3 67
++#define DMAC_FTDMAC020_IRQ4 68
++#define DMAC_FTDMAC020_0_IRQ4 68
++#define DMAC_FTDMAC020_IRQ5 69
++#define DMAC_FTDMAC020_0_IRQ5 69
++#define DMAC_FTDMAC020_IRQ6 70
++#define DMAC_FTDMAC020_0_IRQ6 70
++#define DMAC_FTDMAC020_IRQ7 71
++#define DMAC_FTDMAC020_0_IRQ7 71
++
++/* APBBRG */
++#define APBBRG_FTAPBBRG020S_IRQ_COUNT 4
++#define APBBRG_FTAPBBRG020S_IRQ0 72
++#define APBBRG_FTAPBBRG020S_0_IRQ0 72
++#define APBBRG_FTAPBBRG020S_IRQ1 73
++#define APBBRG_FTAPBBRG020S_0_IRQ1 73
++#define APBBRG_FTAPBBRG020S_IRQ2 74
++#define APBBRG_FTAPBBRG020S_0_IRQ2 74
++#define APBBRG_FTAPBBRG020S_IRQ3 75
++#define APBBRG_FTAPBBRG020S_0_IRQ3 75
++#define APBBRG_FTAPBBRG020S_1_IRQ0 172
++#define APBBRG_FTAPBBRG020S_1_IRQ1 173
++#define APBBRG_FTAPBBRG020S_1_IRQ2 174
++#define APBBRG_FTAPBBRG020S_1_IRQ3 175
++
++/* KMI */
++#define KMI_FTKBC010_IRQ_COUNT 1
++#define KMI_FTKBC010_IRQ 30
++#define KMI_FTKBC010_0_IRQ 30
++#define KMI_FTKBC010_1_IRQ 31
++
++/* PCIC */
++#define PCIC_FTPCI100_IRQ_COUNT 4
++#define PCIC_FTPCI100_IRQ0 176
++#define PCIC_FTPCI100_0_IRQ0 176
++#define PCIC_FTPCI100_IRQ1 177
++#define PCIC_FTPCI100_0_IRQ1 177
++#define PCIC_FTPCI100_IRQ2 178
++#define PCIC_FTPCI100_0_IRQ2 178
++#define PCIC_FTPCI100_IRQ3 179
++#define PCIC_FTPCI100_0_IRQ3 179
++
++/*
++ * Base addresses
++ */
++
++/* CPU */
++#define CPU_MEM_PA_BASE CONFIG_MEMORY_START
++
++
++/* INTC */
++#define INTC_FTINTC010_PA_COUNT 1
++#define INTC_FTINTC010_PA_BASE 0x98800000
++#define INTC_FTINTC010_PA_LIMIT 0x98800FFF
++#define INTC_FTINTC010_PA_SIZE 0x00001000
++#define INTC_FTINTC010_0_PA_BASE 0x98800000
++#define INTC_FTINTC010_0_PA_LIMIT 0x98800FFF
++#define INTC_FTINTC010_0_PA_SIZE 0x00001000
++#define INTC_FTINTC010_1_PA_BASE 0xB0800000
++#define INTC_FTINTC010_1_PA_LIMIT 0xB0800FFF
++#define INTC_FTINTC010_1_PA_SIZE 0x00001000
++#define INTC_FTINTC010_VA_COUNT 1
++#define INTC_FTINTC010_VA_BASE 0xF9880000
++#define INTC_FTINTC010_VA_LIMIT 0xF9880FFF
++#define INTC_FTINTC010_VA_SIZE 0x00001000
++#define INTC_FTINTC010_0_VA_BASE 0xF9880000
++#define INTC_FTINTC010_0_VA_LIMIT 0xF9880FFF
++#define INTC_FTINTC010_0_VA_SIZE 0x00001000
++#define INTC_FTINTC010_1_VA_BASE 0xFB080000
++#define INTC_FTINTC010_1_VA_LIMIT 0xFB080FFF
++#define INTC_FTINTC010_1_VA_SIZE 0x00001000
++
++/* PMU */
++#define PMU_FTPMU010_PA_COUNT 1
++#define PMU_FTPMU010_PA_BASE 0x98100000
++#define PMU_FTPMU010_PA_LIMIT 0x98100FFF
++#define PMU_FTPMU010_PA_SIZE 0x00001000
++#define PMU_FTPMU010_0_PA_BASE 0x98100000
++#define PMU_FTPMU010_0_PA_LIMIT 0x98100FFF
++#define PMU_FTPMU010_0_PA_SIZE 0x00001000
++#define PMU_FTPMU010_VA_COUNT 1
++#define PMU_FTPMU010_VA_BASE 0xF9810000
++#define PMU_FTPMU010_VA_LIMIT 0xF9810FFF
++#define PMU_FTPMU010_VA_SIZE 0x00001000
++#define PMU_FTPMU010_0_VA_BASE 0xF9810000
++#define PMU_FTPMU010_0_VA_LIMIT 0xF9810FFF
++#define PMU_FTPMU010_0_VA_SIZE 0x00001000
++
++/* USB */
++#define USB_FUSBH200_PA_COUNT 1
++#define USB_FUSBH200_PA_BASE 0x92000000
++#define USB_FUSBH200_PA_LIMIT 0x92000FFF
++#define USB_FUSBH200_PA_SIZE 0x00001000
++#define USB_FUSBH200_0_PA_BASE 0x92000000
++#define USB_FUSBH200_0_PA_LIMIT 0x92000FFF
++#define USB_FUSBH200_0_PA_SIZE 0x00001000
++#define USB_FUSBH200_VA_COUNT 1
++#define USB_FUSBH200_VA_BASE 0xF9200000
++#define USB_FUSBH200_VA_LIMIT 0xF9200FFF
++#define USB_FUSBH200_VA_SIZE 0x00001000
++#define USB_FUSBH200_0_VA_BASE 0xF9200000
++#define USB_FUSBH200_0_VA_LIMIT 0xF9200FFF
++#define USB_FUSBH200_0_VA_SIZE 0x00001000
++#define USB_FUSB220_PA_COUNT 1
++#define USB_FUSB220_PA_BASE 0x90B00000
++#define USB_FUSB220_PA_LIMIT 0x90B00FFF
++#define USB_FUSB220_PA_SIZE 0x00001000
++#define USB_FUSB220_0_PA_BASE 0x90B00000
++#define USB_FUSB220_0_PA_LIMIT 0x90B00FFF
++#define USB_FUSB220_0_PA_SIZE 0x00001000
++#define USB_FUSB220_VA_COUNT 1
++#define USB_FUSB220_VA_BASE 0xF90B0000
++#define USB_FUSB220_VA_LIMIT 0xF90B0FFF
++#define USB_FUSB220_VA_SIZE 0x00001000
++#define USB_FUSB220_0_VA_BASE 0xF90B0000
++#define USB_FUSB220_0_VA_LIMIT 0xF90B0FFF
++#define USB_FUSB220_0_VA_SIZE 0x00001000
++
++/* KMI */
++#define KMI_FTKBC010_PA_COUNT 1
++#define KMI_FTKBC010_PA_BASE 0x97200000
++#define KMI_FTKBC010_PA_LIMIT 0x97200FFF
++#define KMI_FTKBC010_PA_SIZE 0x00001000
++#define KMI_FTKBC010_0_PA_BASE 0x97200000
++#define KMI_FTKBC010_0_PA_LIMIT 0x97200FFF
++#define KMI_FTKBC010_0_PA_SIZE 0x00001000
++#define KMI_FTKBC010_1_PA_BASE 0x97300000
++#define KMI_FTKBC010_1_PA_LIMIT 0x97300FFF
++#define KMI_FTKBC010_1_PA_SIZE 0x00001000
++#define KMI_FTKBC010_VA_COUNT 1
++#define KMI_FTKBC010_VA_BASE 0xF9720000
++#define KMI_FTKBC010_VA_LIMIT 0xF9720FFF
++#define KMI_FTKBC010_VA_SIZE 0x00001000
++#define KMI_FTKBC010_0_VA_BASE 0xF9720000
++#define KMI_FTKBC010_0_VA_LIMIT 0xF9720FFF
++#define KMI_FTKBC010_0_VA_SIZE 0x00001000
++#define KMI_FTKBC010_1_VA_BASE 0xF9730000
++#define KMI_FTKBC010_1_VA_LIMIT 0xF9730FFF
++#define KMI_FTKBC010_1_VA_SIZE 0x00001000
++
++/* PCIMEM */
++#define PCIMEM_PA_COUNT 1
++#define PCIMEM_PA_BASE 0xA0000000
++#define PCIMEM_PA_LIMIT 0xAFFFFFFF
++#define PCIMEM_PA_SIZE 0x10000000
++#define PCIMEM_0_PA_BASE 0xA0000000
++#define PCIMEM_0_PA_LIMIT 0xAFFFFFFF
++#define PCIMEM_0_PA_SIZE 0x10000000
++
++
++#ifdef CONFIG_PLATFORM_AHBDMA_MODULE
++#define CONFIG_PLATFORM_AHBDMA
++#endif
++
++#ifdef CONFIG_PLATFORM_APBDMA_MODULE
++#define CONFIG_PLATFORM_APBDMA
++#endif
++
++#include <asm/misc_spec.h> /* Manual defined spec */
++
++/*
++ * Platform independent specification
++ */
++
++#define NR_IRQS PLATFORM_INTERRUPTS
++
++#ifndef TIMER_CLK_IN
++#error Missing platform dependent symbol TIMER_CLK_IN in <asm/arch/platform/misc_spec.h> file.
++#endif
++
++/*
++ * Macros for retrieving IP related information
++ */
++#define IP_IDENTIFIER __glue(__glue(IPMODULE,_),__glue(IPNAME,_))
++
++#define IP_COUNT __glue(IP_IDENTIFIER,COUNT)
++
++#define IP_IRQ_COUNT __glue(IP_IDENTIFIER,IRQ_COUNT)
++#define IP_IRQ(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ)
++#define IP_irq __glue(IP_IDENTIFIER,irq)
++
++#define IP_PA_COUNT __glue(IP_IDENTIFIER,PA_COUNT)
++#define IP_PA_BASE(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE)
++#define IP_PA_LIMIT(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT)
++#define IP_PA_SIZE(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE)
++#define IP_pa_base __glue(IP_IDENTIFIER,pa_base)
++#define IP_pa_limit __glue(IP_IDENTIFIER,pa_limit)
++#define IP_pa_size __glue(IP_IDENTIFIER,pa_size)
++
++#define IP_VA_COUNT __glue(IP_IDENTIFIER,VA_COUNT)
++#define IP_VA_BASE(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE)
++#define IP_VA_LIMIT(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT)
++#define IP_VA_SIZE(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE)
++#define IP_va_base __glue(IP_IDENTIFIER,va_base)
++#define IP_va_limit __glue(IP_IDENTIFIER,va_limit)
++#define IP_va_size __glue(IP_IDENTIFIER,va_size)
++
++/*
++ * Facility macros
++ */
++/* IRQ0~7 */
++#define IP_IRQ0(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ0)
++#define IP_IRQ1(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ1)
++#define IP_IRQ2(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ2)
++#define IP_IRQ3(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ3)
++#define IP_IRQ4(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ4)
++#define IP_IRQ5(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ5)
++#define IP_IRQ6(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ6)
++#define IP_IRQ7(n) __glue(__glue(IP_IDENTIFIER,n),_IRQ7)
++
++/* PA_BASE0~7 */
++#define IP_PA_BASE0(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE0)
++#define IP_PA_BASE1(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE1)
++#define IP_PA_BASE2(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE2)
++#define IP_PA_BASE3(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE3)
++#define IP_PA_BASE4(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE4)
++#define IP_PA_BASE5(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE5)
++#define IP_PA_BASE6(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE6)
++#define IP_PA_BASE7(n) __glue(__glue(IP_IDENTIFIER,n),_PA_BASE7)
++
++/* PA_LIMIT0~7 */
++#define IP_PA_LIMIT0(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT0)
++#define IP_PA_LIMIT1(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT1)
++#define IP_PA_LIMIT2(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT2)
++#define IP_PA_LIMIT3(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT3)
++#define IP_PA_LIMIT4(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT4)
++#define IP_PA_LIMIT5(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT5)
++#define IP_PA_LIMIT6(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT6)
++#define IP_PA_LIMIT7(n) __glue(__glue(IP_IDENTIFIER,n),_PA_LIMIT7)
++
++/* PA_SIZE0~7 */
++#define IP_PA_SIZE0(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE0)
++#define IP_PA_SIZE1(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE1)
++#define IP_PA_SIZE2(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE2)
++#define IP_PA_SIZE3(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE3)
++#define IP_PA_SIZE4(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE4)
++#define IP_PA_SIZE5(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE5)
++#define IP_PA_SIZE6(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE6)
++#define IP_PA_SIZE7(n) __glue(__glue(IP_IDENTIFIER,n),_PA_SIZE7)
++
++/* VA_BASE0~7 */
++#define IP_VA_BASE0(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE0)
++#define IP_VA_BASE1(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE1)
++#define IP_VA_BASE2(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE2)
++#define IP_VA_BASE3(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE3)
++#define IP_VA_BASE4(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE4)
++#define IP_VA_BASE5(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE5)
++#define IP_VA_BASE6(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE6)
++#define IP_VA_BASE7(n) __glue(__glue(IP_IDENTIFIER,n),_VA_BASE7)
++
++/* VA_LIMIT0~7 */
++#define IP_VA_LIMIT0(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT0)
++#define IP_VA_LIMIT1(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT1)
++#define IP_VA_LIMIT2(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT2)
++#define IP_VA_LIMIT3(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT3)
++#define IP_VA_LIMIT4(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT4)
++#define IP_VA_LIMIT5(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT5)
++#define IP_VA_LIMIT6(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT6)
++#define IP_VA_LIMIT7(n) __glue(__glue(IP_IDENTIFIER,n),_VA_LIMIT7)
++
++/* VA_SIZE0~7 */
++#define IP_VA_SIZE0(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE0)
++#define IP_VA_SIZE1(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE1)
++#define IP_VA_SIZE2(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE2)
++#define IP_VA_SIZE3(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE3)
++#define IP_VA_SIZE4(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE4)
++#define IP_VA_SIZE5(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE5)
++#define IP_VA_SIZE6(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE6)
++#define IP_VA_SIZE7(n) __glue(__glue(IP_IDENTIFIER,n),_VA_SIZE7)
++
++#endif /* __FARADAY_PLATFORM_INDEPENDENT_SPECIFICATION__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/spinlock.h linux-3.4.110/arch/nds32/include/asm/spinlock.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/spinlock.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/spinlock.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,183 @@
++/*
++ * linux/arch/nds32/include/asm/spinlock.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASM_SPINLOCK_H
++#define __ASM_SPINLOCK_H
++
++#include <asm/processor.h>
++
++#define arch_spin_is_locked(x) ((x)->lock != 0)
++
++#define arch_spin_unlock_wait(lock) \
++ do { while (arch_spin_is_locked(lock)) cpu_relax(); } while (0)
++
++#define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock)
++
++static inline void arch_spin_lock(arch_spinlock_t *lock)
++{
++ unsigned long tmp;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%1+$r15]\n"
++ "\tbnez\t%0, 1b\n"
++ "\tmovi\t%0, #0x1\n"
++ "\tscw\t%0, [%1+$r15]\n"
++ "\tbeqz\t%0, 1b\n"
++ : "=&r" (tmp)
++ : "r" (&lock->lock)
++ : "memory");
++}
++
++static inline int arch_spin_trylock(arch_spinlock_t *lock)
++{
++ unsigned long ret, tmp;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%2+$r15]\n"
++ "\tmovi\t%1, #0x1\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ : "=&r" (ret), "=&r" (tmp)
++ : "r" (&lock->lock)
++ : "memory");
++
++ return ret == 0;
++}
++
++static inline void arch_spin_unlock(arch_spinlock_t *lock)
++{
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "\tswi\t$r15, [%0]\n"
++ :
++ : "r" (&lock->lock)
++ : "memory");
++}
++
++static inline void arch_write_lock(arch_rwlock_t *rw)
++{
++ unsigned long tmp;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%1+$r15]\n"
++ "\tbnez\t%0, 1b\n"
++ "\tsethi\t%0, 0x80000\n"
++ "\tscw\t%0, [%1+$r15]\n"
++ "\tbeqz\t%0, 1b\n"
++ : "=&r" (tmp)
++ : "r" (&rw->lock)
++ : "memory");
++}
++
++static inline void arch_write_unlock(arch_rwlock_t *rw)
++{
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "\tswi\t$r15, [%0]\n"
++ :
++ : "r" (&rw->lock)
++ : "memory");
++}
++
++#define arch_write_can_lock(x) ((x)->lock == 0)
++static inline void arch_read_lock(arch_rwlock_t *rw)
++{
++ int tmp;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%1+$r15]\n"
++ "\tbltz\t%0, 1b\n"
++ "\taddi\t%0, %0, #1\n"
++ "\tscw\t%0, [%1+$r15]\n"
++ "\tbeqz\t%0, 1b\n"
++ : "=&r" (tmp)
++ : "r" (&rw->lock)
++ : "memory");
++}
++
++static inline void arch_read_unlock(arch_rwlock_t *rw)
++{
++ unsigned long tmp;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "1:\n"
++ "\tllw\t%0, [%1+$r15]\n"
++ "\taddi\t%0, %0, #-1\n"
++ "\tscw\t%0, [%1+$r15]\n"
++ "\tbeqz\t%0, 1b\n"
++ : "=&r" (tmp)
++ : "r" (&rw->lock)
++ : "memory");
++}
++
++static inline int arch_read_trylock(arch_rwlock_t *rw)
++{
++ unsigned long ret, tmp;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "\tmovi\t%0, #0x0\n"
++ "1:\n"
++ "\tllw\t%1, [%2+$r15]\n"
++ "\tbltz\t%1, 2f\n"
++ "\taddi\t%1, %1, #1\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ "\tmovi\t%0, #0x1\n"
++ "\tj\t3f\n"
++ "2:\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "3:\n"
++ : "=&r" (ret), "=&r" (tmp)
++ : "r" (&rw->lock)
++ : "memory");
++
++ return ret;
++}
++
++static inline int arch_write_trylock(arch_rwlock_t *rw)
++{
++ unsigned long ret, tmp;
++
++ __asm__ __volatile__(
++ "xor\t$r15, $r15, $r15\n"
++ "\tmovi\t%0, #0x0\n"
++ "1:\n"
++ "\tllw\t%1, [%2+$r15]\n"
++ "\tbnez\t%1, 2f\n"
++ "\tsethi\t%1, 0x80000\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "\tbeqz\t%1, 1b\n"
++ "\tmovi\t%0, #0x1\n"
++ "\tj\t3f\n"
++ "2:\n"
++ "\tscw\t%1, [%2+$r15]\n"
++ "3:\n"
++ : "=&r" (ret), "=&r" (tmp)
++ : "r" (&rw->lock)
++ : "memory");
++
++ return ret;
++}
++
++#define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
++#define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
++
++#define arch_read_can_lock(x) ((x)->lock < 0x80000000)
++
++#define arch_spin_relax(lock) cpu_relax()
++#define arch_read_relax(lock) cpu_relax()
++#define arch_write_relax(lock) cpu_relax()
++
++#endif /* __ASM_SPINLOCK_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/spinlock_types.h linux-3.4.110/arch/nds32/include/asm/spinlock_types.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/spinlock_types.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/spinlock_types.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,25 @@
++/*
++ * linux/arch/nds32/include/asm/spinlock_types.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASM_SPINLOCK_TYPES_H
++#define _ASM_SPINLOCK_TYPES_H
++
++#ifndef __LINUX_SPINLOCK_TYPES_H
++# error "please don't include this file directly"
++#endif
++
++typedef struct {
++ volatile unsigned int lock;
++} arch_spinlock_t;
++
++#define __ARCH_SPIN_LOCK_UNLOCKED { 0 }
++
++typedef struct {
++ volatile unsigned int lock;
++} arch_rwlock_t;
++
++#define __ARCH_RW_LOCK_UNLOCKED { 0 }
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/statfs.h linux-3.4.110/arch/nds32/include/asm/statfs.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/statfs.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/statfs.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/statfs.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_STATFS_H
++#define _ASMNDS32_STATFS_H
++
++#include <asm-generic/statfs.h>
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/stat.h linux-3.4.110/arch/nds32/include/asm/stat.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/stat.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/stat.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,101 @@
++/*
++ * linux/arch/nds32/include/asm/stat.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_STAT_H
++#define _ASMNDS32_STAT_H
++
++struct __old_kernel_stat {
++ unsigned short st_dev;
++ unsigned short st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++ unsigned short st_rdev;
++ unsigned long st_size;
++ unsigned long st_atime;
++ unsigned long st_mtime;
++ unsigned long st_ctime;
++};
++
++#define STAT_HAVE_NSEC
++
++struct stat {
++#if defined(__NDS32_EB__)
++ unsigned short st_dev;
++ unsigned short __pad1;
++#else
++ unsigned long st_dev;
++#endif
++ unsigned long st_ino;
++ unsigned short st_mode;
++ unsigned short st_nlink;
++ unsigned short st_uid;
++ unsigned short st_gid;
++#if defined(__NDS32_EB__)
++ unsigned short st_rdev;
++ unsigned short __pad2;
++#else
++ unsigned long st_rdev;
++#endif
++ unsigned long st_size;
++ unsigned long st_blksize;
++ unsigned long st_blocks;
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++ unsigned long __unused4;
++ unsigned long __unused5;
++};
++
++/* This matches struct stat64 in glibc2.1, hence the absolutely
++ * insane amounts of padding around dev_t's.
++ * Note: The kernel zero's the padded region because glibc might read them
++ * in the hope that the kernel has stretched to using larger sizes.
++ */
++
++struct stat64 {
++ unsigned long long st_dev;
++ unsigned long __pad0;
++
++#define STAT64_HAS_BROKEN_ST_INO 1
++ unsigned long __st_ino;
++ unsigned int st_mode;
++ unsigned int st_nlink;
++
++ unsigned long st_uid;
++ unsigned long st_gid;
++
++ unsigned long long st_rdev;
++ unsigned int __pad3;
++
++ unsigned long long st_size;
++ unsigned long st_blksize;
++
++//#if defined(__NDS32EB__)
++// unsigned long __pad4; // Future possible st_blocks hi bits
++ unsigned long long st_blocks; // Number 512-byte blocks allocated.
++//#else // Must be little
++// unsigned long st_blocks; // Number 512-byte blocks allocated.
++// unsigned long __pad4; // Future possible st_blocks hi bits
++//#endif
++
++ unsigned long st_atime;
++ unsigned long st_atime_nsec;
++
++ unsigned long st_mtime;
++ unsigned long st_mtime_nsec;
++
++ unsigned long st_ctime;
++ unsigned long st_ctime_nsec;
++
++ unsigned long long st_ino;
++};
++
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/string.h linux-3.4.110/arch/nds32/include/asm/string.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/string.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/string.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,45 @@
++/*
++ * linux/arch/nds32/include/asm/string.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASM_NDS32_STRING_H
++#define __ASM_NDS32_STRING_H
++
++/*
++ * We don't do inline string functions, since the
++ * optimised inline asm versions are not small.
++ */
++
++#define __HAVE_ARCH_STRRCHR
++extern char * strrchr(const char * s, int c);
++
++#define __HAVE_ARCH_STRCHR
++extern char * strchr(const char * s, int c);
++
++#define __HAVE_ARCH_MEMCPY
++extern void * memcpy(void *, const void *, __kernel_size_t);
++
++#define __HAVE_ARCH_MEMMOVE
++extern void * memmove(void *, const void *, __kernel_size_t);
++
++#define __HAVE_ARCH_MEMZERO
++#define __HAVE_ARCH_MEMSET
++extern void * memset(void *, int, __kernel_size_t);
++
++extern void __memzero(void *ptr, __kernel_size_t n);
++
++#define memset(p,v,n) \
++ ({ \
++ if ((n) != 0) { \
++ if (__builtin_constant_p((v)) && (v) == 0) \
++ __memzero((p),(n)); \
++ else \
++ memset((p),(v),(n)); \
++ } \
++ (p); \
++ })
++
++#define memzero(p,n) ({ if ((n) != 0) __memzero((p),(n)); (p); })
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/suspend.h linux-3.4.110/arch/nds32/include/asm/suspend.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/suspend.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/suspend.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,9 @@
++/*
++ * linux/arch/nds32/include/asm/suspend.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_SUSPEND_H
++#define _ASMNDS32_SUSPEND_H
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/swab.h linux-3.4.110/arch/nds32/include/asm/swab.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/swab.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/swab.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,34 @@
++/*
++ * include/asm/byteorder.h
++ * Copyright (C) 2008 Andes Technology, Inc.
++ */
++
++#ifndef __NDS32_SWAB_H__
++#define __NDS32_SWAB_H__
++
++#include <linux/types.h>
++#include <linux/compiler.h>
++
++static __inline__ __attribute_const__ __u32 ___arch__swab32(__u32 x)
++{
++ __asm__("wsbh %0, %0\n\t" /* word swap byte within halfword */
++ "rotri %0, %0, #16\n"
++ : "=r" (x) : "0" (x));
++ return x;
++}
++
++static __inline__ __attribute_const__ __u16 ___arch__swab16(__u16 x)
++{
++ __asm__("wsbh %0, %0\n" /* word swap byte within halfword */
++ : "=r" (x) : "0" (x));
++ return x;
++}
++#define __arch_swab32(x) ___arch__swab32(x)
++#define __arch_swab16(x) ___arch__swab16(x)
++
++#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
++# define __BYTEORDER_HAS_U64__
++# define __SWAB_64_THRU_32__
++#endif
++
++#endif /* __NDS32_SWAB_H__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/switch_to.h linux-3.4.110/arch/nds32/include/asm/switch_to.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/switch_to.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/switch_to.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,18 @@
++#ifndef __ASM_NDS32_SWITCH_TO_H
++#define __ASM_NDS32_SWITCH_TO_H
++
++#include <linux/thread_info.h>
++
++/*
++ * switch_to(prev, next) should switch from task `prev' to `next'
++ * `prev' will never be the same as `next'. schedule() itself
++ * contains the memory barrier to tell GCC not to cache `current'.
++ */
++extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
++
++#define switch_to( prev, next, last) \
++do { \
++ last = __switch_to( prev, task_thread_info( prev), task_thread_info( next)); \
++} while (0)
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/system.h linux-3.4.110/arch/nds32/include/asm/system.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/system.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/system.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,4 @@
++/* FILE TO BE DELETED. DO NOT ADD STUFF HERE! */
++#include <asm/barrier.h>
++#include <asm/switch_to.h>
++
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/termbits.h linux-3.4.110/arch/nds32/include/asm/termbits.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/termbits.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/termbits.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,198 @@
++#ifndef __ASM_NDS32_TERMBITS_H
++#define __ASM_NDS32_TERMBITS_H
++
++typedef unsigned char cc_t;
++typedef unsigned int speed_t;
++typedef unsigned int tcflag_t;
++
++#define NCCS 19
++struct termios {
++ tcflag_t c_iflag; /* input mode flags */
++ tcflag_t c_oflag; /* output mode flags */
++ tcflag_t c_cflag; /* control mode flags */
++ tcflag_t c_lflag; /* local mode flags */
++ cc_t c_line; /* line discipline */
++ cc_t c_cc[NCCS]; /* control characters */
++};
++
++struct termios2 {
++ tcflag_t c_iflag; /* input mode flags */
++ tcflag_t c_oflag; /* output mode flags */
++ tcflag_t c_cflag; /* control mode flags */
++ tcflag_t c_lflag; /* local mode flags */
++ cc_t c_line; /* line discipline */
++ cc_t c_cc[NCCS]; /* control characters */
++ speed_t c_ispeed; /* input speed */
++ speed_t c_ospeed; /* output speed */
++};
++
++struct ktermios {
++ tcflag_t c_iflag; /* input mode flags */
++ tcflag_t c_oflag; /* output mode flags */
++ tcflag_t c_cflag; /* control mode flags */
++ tcflag_t c_lflag; /* local mode flags */
++ cc_t c_line; /* line discipline */
++ cc_t c_cc[NCCS]; /* control characters */
++ speed_t c_ispeed; /* input speed */
++ speed_t c_ospeed; /* output speed */
++};
++
++
++/* c_cc characters */
++#define VINTR 0
++#define VQUIT 1
++#define VERASE 2
++#define VKILL 3
++#define VEOF 4
++#define VTIME 5
++#define VMIN 6
++#define VSWTC 7
++#define VSTART 8
++#define VSTOP 9
++#define VSUSP 10
++#define VEOL 11
++#define VREPRINT 12
++#define VDISCARD 13
++#define VWERASE 14
++#define VLNEXT 15
++#define VEOL2 16
++
++/* c_iflag bits */
++#define IGNBRK 0000001
++#define BRKINT 0000002
++#define IGNPAR 0000004
++#define PARMRK 0000010
++#define INPCK 0000020
++#define ISTRIP 0000040
++#define INLCR 0000100
++#define IGNCR 0000200
++#define ICRNL 0000400
++#define IUCLC 0001000
++#define IXON 0002000
++#define IXANY 0004000
++#define IXOFF 0010000
++#define IMAXBEL 0020000
++#define IUTF8 0040000
++
++/* c_oflag bits */
++#define OPOST 0000001
++#define OLCUC 0000002
++#define ONLCR 0000004
++#define OCRNL 0000010
++#define ONOCR 0000020
++#define ONLRET 0000040
++#define OFILL 0000100
++#define OFDEL 0000200
++#define NLDLY 0000400
++#define NL0 0000000
++#define NL1 0000400
++#define CRDLY 0003000
++#define CR0 0000000
++#define CR1 0001000
++#define CR2 0002000
++#define CR3 0003000
++#define TABDLY 0014000
++#define TAB0 0000000
++#define TAB1 0004000
++#define TAB2 0010000
++#define TAB3 0014000
++#define XTABS 0014000
++#define BSDLY 0020000
++#define BS0 0000000
++#define BS1 0020000
++#define VTDLY 0040000
++#define VT0 0000000
++#define VT1 0040000
++#define FFDLY 0100000
++#define FF0 0000000
++#define FF1 0100000
++
++/* c_cflag bit meaning */
++#define CBAUD 0010017
++#define B0 0000000 /* hang up */
++#define B50 0000001
++#define B75 0000002
++#define B110 0000003
++#define B134 0000004
++#define B150 0000005
++#define B200 0000006
++#define B300 0000007
++#define B600 0000010
++#define B1200 0000011
++#define B1800 0000012
++#define B2400 0000013
++#define B4800 0000014
++#define B9600 0000015
++#define B19200 0000016
++#define B38400 0000017
++#define EXTA B19200
++#define EXTB B38400
++#define CSIZE 0000060
++#define CS5 0000000
++#define CS6 0000020
++#define CS7 0000040
++#define CS8 0000060
++#define CSTOPB 0000100
++#define CREAD 0000200
++#define PARENB 0000400
++#define PARODD 0001000
++#define HUPCL 0002000
++#define CLOCAL 0004000
++#define CBAUDEX 0010000
++#define BOTHER 0010000
++#define B57600 0010001
++#define B115200 0010002
++#define B230400 0010003
++#define B460800 0010004
++#define B500000 0010005
++#define B576000 0010006
++#define B921600 0010007
++#define B1000000 0010010
++#define B1152000 0010011
++#define B1500000 0010012
++#define B2000000 0010013
++#define B2500000 0010014
++#define B3000000 0010015
++#define B3500000 0010016
++#define B4000000 0010017
++#define CIBAUD 002003600000 /* input baud rate */
++#define CMSPAR 010000000000 /* mark or space (stick) parity */
++#define CRTSCTS 020000000000 /* flow control */
++
++#define IBSHIFT 16
++
++/* c_lflag bits */
++#define ISIG 0000001
++#define ICANON 0000002
++#define XCASE 0000004
++#define ECHO 0000010
++#define ECHOE 0000020
++#define ECHOK 0000040
++#define ECHONL 0000100
++#define NOFLSH 0000200
++#define TOSTOP 0000400
++#define ECHOCTL 0001000
++#define ECHOPRT 0002000
++#define ECHOKE 0004000
++#define FLUSHO 0010000
++#define PENDIN 0040000
++#define IEXTEN 0100000
++#define EXTPROC 0200000
++
++/* tcflow() and TCXONC use these */
++#define TCOOFF 0
++#define TCOON 1
++#define TCIOFF 2
++#define TCION 3
++
++/* tcflush() and TCFLSH use these */
++#define TCIFLUSH 0
++#define TCOFLUSH 1
++#define TCIOFLUSH 2
++
++/* tcsetattr uses these */
++#define TCSANOW 0
++#define TCSADRAIN 1
++#define TCSAFLUSH 2
++
++#endif /* __ASM_NDS32_TERMBITS_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/termios.h linux-3.4.110/arch/nds32/include/asm/termios.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/termios.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/termios.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,116 @@
++/*
++ * linux/arch/nds32/include/asm/termios.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASM_NDS32_TERMIOS_H
++#define __ASM_NDS32_TERMIOS_H
++
++#include <asm/termbits.h>
++#include <asm/ioctls.h>
++
++struct winsize {
++ unsigned short ws_row;
++ unsigned short ws_col;
++ unsigned short ws_xpixel;
++ unsigned short ws_ypixel;
++};
++
++#define NCC 8
++struct termio {
++ unsigned short c_iflag; /* input mode flags */
++ unsigned short c_oflag; /* output mode flags */
++ unsigned short c_cflag; /* control mode flags */
++ unsigned short c_lflag; /* local mode flags */
++ unsigned char c_line; /* line discipline */
++ unsigned char c_cc[NCC]; /* control characters */
++};
++
++#ifdef __KERNEL__
++/* intr=^C quit=^| erase=del kill=^U
++ eof=^D vtime=\0 vmin=\1 sxtc=\0
++ start=^Q stop=^S susp=^Z eol=\0
++ reprint=^R discard=^U werase=^W lnext=^V
++ eol2=\0
++*/
++#define INIT_C_CC "\003\034\177\025\004\0\1\0\021\023\032\0\022\017\027\026\0"
++#endif
++
++/* modem lines */
++#define TIOCM_LE 0x001
++#define TIOCM_DTR 0x002
++#define TIOCM_RTS 0x004
++#define TIOCM_ST 0x008
++#define TIOCM_SR 0x010
++#define TIOCM_CTS 0x020
++#define TIOCM_CAR 0x040
++#define TIOCM_RNG 0x080
++#define TIOCM_DSR 0x100
++#define TIOCM_CD TIOCM_CAR
++#define TIOCM_RI TIOCM_RNG
++#define TIOCM_OUT1 0x2000
++#define TIOCM_OUT2 0x4000
++#define TIOCM_LOOP 0x8000
++
++/* ioctl (fd, TIOCSERGETLSR, &result) where result may be as below */
++
++/* line disciplines */
++#define N_TTY 0
++#define N_SLIP 1
++#define N_MOUSE 2
++#define N_PPP 3
++#define N_STRIP 4
++#define N_AX25 5
++#define N_X25 6 /* X.25 async */
++#define N_6PACK 7
++#define N_MASC 8 /* Reserved for Mobitex module <kaz@cafe.net> */
++#define N_R3964 9 /* Reserved for Simatic R3964 module */
++#define N_PROFIBUS_FDL 10 /* Reserved for Profibus <Dave@mvhi.com> */
++#define N_IRDA 11 /* Linux IrDa - http://irda.sourceforge.net/ */
++#define N_SMSBLOCK 12 /* SMS block mode - for talking to GSM data cards about SMS messages */
++#define N_HDLC 13 /* synchronous HDLC */
++#define N_SYNC_PPP 14
++#define N_HCI 15 /* Bluetooth HCI UART */
++
++#ifdef __KERNEL__
++
++/*
++ * Translate a "termio" structure into a "termios". Ugh.
++ */
++#define SET_LOW_TERMIOS_BITS(termios, termio, x) { \
++ unsigned short __tmp; \
++ get_user(__tmp,&(termio)->x); \
++ *(unsigned short *) &(termios)->x = __tmp; \
++}
++
++#define user_termio_to_kernel_termios(termios, termio) \
++({ \
++ SET_LOW_TERMIOS_BITS(termios, termio, c_iflag); \
++ SET_LOW_TERMIOS_BITS(termios, termio, c_oflag); \
++ SET_LOW_TERMIOS_BITS(termios, termio, c_cflag); \
++ SET_LOW_TERMIOS_BITS(termios, termio, c_lflag); \
++ copy_from_user((termios)->c_cc, (termio)->c_cc, NCC); \
++})
++
++/*
++ * Translate a "termios" structure into a "termio". Ugh.
++ */
++#define kernel_termios_to_user_termio(termio, termios) \
++({ \
++ put_user((termios)->c_iflag, &(termio)->c_iflag); \
++ put_user((termios)->c_oflag, &(termio)->c_oflag); \
++ put_user((termios)->c_cflag, &(termio)->c_cflag); \
++ put_user((termios)->c_lflag, &(termio)->c_lflag); \
++ put_user((termios)->c_line, &(termio)->c_line); \
++ copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \
++})
++
++#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios))
++#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios))
++
++#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios))
++#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios))
++
++#endif /* __KERNEL__ */
++
++#endif /* __ASM_NDS32_TERMIOS_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/thread_info.h linux-3.4.110/arch/nds32/include/asm/thread_info.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/thread_info.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/thread_info.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,145 @@
++/*
++ * linux/arch/nds32/include/asm/thread_info.h
++ *
++ * Copyright (C) 2002 Russell King.
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef __ASM_NDS32_THREAD_INFO_H
++#define __ASM_NDS32_THREAD_INFO_H
++
++#ifdef __KERNEL__
++
++#define THREAD_SHIFT (13)
++#define THREAD_SIZE (1 << THREAD_SHIFT)
++
++#ifndef __ASSEMBLY__
++
++struct task_struct;
++struct exec_domain;
++
++#include <asm/ptrace.h>
++#include <asm/types.h>
++
++
++typedef struct {
++ unsigned long seg;
++} mm_segment_t;
++//typedef unsigned long mm_segment_t;
++
++struct cpu_context_save {
++ unsigned long r6;
++ unsigned long r7;
++ unsigned long r8;
++ unsigned long r9;
++ unsigned long r10;
++ unsigned long r11;
++ unsigned long r12;
++ unsigned long r13;
++ unsigned long r14;
++ unsigned long fp;
++ unsigned long pc;
++};
++
++/*
++ * low level task data that entry.S needs immediate access to.
++ * __switch_to() assumes cpu_context follows immediately after cpu_domain.
++ */
++struct thread_info {
++ unsigned long flags; /* low level flags */
++ __s32 preempt_count; /* 0 => preemptable, <0 => bug */
++ mm_segment_t addr_limit; /* address limit */
++ struct task_struct *task; /* main task structure */
++ struct exec_domain *exec_domain; /* execution domain */
++ __u32 cpu; /* cpu */
++ struct cpu_context_save* sp_save; /* cpu context */
++ struct restart_block restart_block;
++};
++
++#define INIT_THREAD_INFO(tsk) \
++{ \
++ .task = &tsk, \
++ .exec_domain = &default_exec_domain, \
++ .flags = 0, \
++ .cpu = 0, \
++ .preempt_count = 1, \
++ .addr_limit = KERNEL_DS, \
++ .restart_block = { \
++ .fn = do_no_restart_syscall, \
++ }, \
++}
++
++#define init_thread_info (init_thread_union.thread_info)
++#define init_stack (init_thread_union.stack)
++
++
++/*
++ * how to get the thread information struct from C
++ */
++static inline struct thread_info *current_thread_info(void) __attribute_const__;
++
++static inline struct thread_info *current_thread_info(void)
++{
++ register unsigned long sp asm ("$sp"); //M Tom asm -> __asm__ __volatile__
++ return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
++}
++
++#define get_thread_info(ti) get_task_struct((ti)->task)
++#define put_thread_info(ti) put_task_struct((ti)->task)
++
++#define thread_saved_pc(tsk) \
++ ((unsigned long)(task_thread_info(tsk)->sp_save->pc))
++#define thread_saved_fp(tsk) \
++ ((unsigned long)(task_thread_info(tsk)->sp_save->fp))
++#endif
++
++#define THREAD_SIZE_ORDER (1)
++/*
++ * We use bit 30 of the preempt_count to indicate that kernel
++ * preemption is occuring. See include/asm-arm/hardirq.h.
++ */
++#define PREEMPT_ACTIVE 0x40000000
++
++/*
++ * thread information flags:
++ * TIF_SYSCALL_TRACE - syscall trace active
++ * TIF_NOTIFY_RESUME - resumption notification requested
++ * TIF_SIGPENDING - signal pending
++ * TIF_NEED_RESCHED - rescheduling necessary
++ * TIF_USEDFPU - FPU was used by this task this quantum (SMP)
++ * TIF_POLLING_NRFLAG - true if poll_idle() is polling TIF_NEED_RESCHED
++ * TIF_USEDAUDIO - Audio has been used by this task and no need to init the regs
++ */
++#define TIF_SIGPENDING 1
++#define TIF_NEED_RESCHED 2
++#define TIF_SINGLESTEP 3
++#define TIF_NOTIFY_RESUME 5
++#define TIF_SYSCALL_TRACE 8
++#define TIF_RESTORE_SIGMASK 9
++#define TIF_USEDFPU 16
++#define TIF_POLLING_NRFLAG 17
++#define TIF_MEMDIE 18
++#define TIF_FREEZE 19
++#define TIF_USEDAUDIO 20
++
++#define _TIF_SIGPENDING (1 << TIF_SIGPENDING)
++#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED)
++#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP)
++#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME)
++#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE)
++#define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK)
++#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG)
++#define _TIF_FREEZE (1 << TIF_FREEZE)
++
++/*
++ * Change these and you break ASM code in entry-common.S
++ */
++#define _TIF_WORK_MASK 0x000000ff
++#define _TIF_WORK_SYSCALL_ENTRY (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP)
++#define _TIF_WORK_SYSCALL_LEAVE (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP)
++
++#endif /* __KERNEL__ */
++#endif /* __ASM_NDS32_THREAD_INFO_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/timer.h linux-3.4.110/arch/nds32/include/asm/timer.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/timer.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/timer.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,94 @@
++/*
++ * include/arch/nds32/include/asm/timer.h
++ *
++ * Faraday FTTMR010 Timer Device Driver Interface
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Note
++ *
++ * As IP_COUNT might be greater than one, timer ID is computed as follows:
++ * id=0~2 : Timer 1~3 of the first FTTMR010 IP
++ * id=3~5 : Timer 1~3 of the second FTTMR010 IP
++ * ...
++ * Therefore:
++ * (id / 3) : Compute which IP
++ * (id % 3) : Compute which timer in this IP
++ * Notice:
++ * For simplicity's sake, all code does not check for invalid timer id
++ *
++ * ChangeLog
++ *
++ * Luke Lee 09/14/2005 Created, heavily modified from Faraday CPE platform code.
++ */
++
++
++#ifndef __FARADAY_TIMER_FTTMR010_HEADER__
++#define __FARADAY_TIMER_FTTMR010_HEADER__
++
++/*
++ * Definition of register offsets
++ */
++
++#define TIMER1_COUNT 0x0
++#define TIMER1_LOAD 0x4
++#define TIMER1_MATCH1 0x8
++#define TIMER1_MATCH2 0xC
++
++#define TIMER2_COUNT 0x10
++#define TIMER2_LOAD 0x14
++#define TIMER2_MATCH1 0x18
++#define TIMER2_MATCH2 0x1C
++
++#define TIMER3_COUNT 0x20
++#define TIMER3_LOAD 0x24
++#define TIMER3_MATCH1 0x28
++#define TIMER3_MATCH2 0x2C
++
++#define TIMER_TMCR 0x30
++#define TIMER_INTRSTATE 0x34
++#define TIMER_INTRMASK 0x38
++
++/* Each timer's register address is offset by 0x10 */
++#define TIMER_OFFSET 0x10
++
++/*
++ * Definition of TMCR bits
++ */
++
++#define TM1ENABLE 1
++#define TM1CLOCK (1<<1)
++#define TM1OFENABLE (1<<2)
++
++#define TM2ENABLE (1<<3)
++#define TM2CLOCK (1<<4)
++#define TM2OFENABLE (1<<5)
++
++#define TM3ENABLE (1<<6)
++#define TM3CLOCK (1<<7)
++#define TM3OFENABLE (1<<8)
++
++#define TM1UPDOWN (1<<9)
++#define TM2UPDOWN (1<<10)
++#define TM3UPDOWN (1<<11)
++
++
++#define TM1MATCH1 (1 << 0)
++#define TM1MATCH2 (1 << 1)
++#define TM1OVERFLOW (1 << 2)
++#define TM2MATCH1 (1 << 3)
++#define TM2MATCH2 (1 << 4)
++#define TM2OVERFLOW (1 << 5)
++#define TM3MATCH1 (1 << 6)
++#define TM3MATCH2 (1 << 7)
++#define TM3OVERFLOW (1 << 8)
++
++struct sys_timer;
++extern struct sys_timer platform_timer;
++
++#endif // __FARADAY_TIMER_FTTMR010_HEADER__
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/timex.h linux-3.4.110/arch/nds32/include/asm/timex.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/timex.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/timex.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,36 @@
++/*
++ * linux/arch/nds32/include/asm/timex.h
++ *
++ * Copyright (C) 1997,1998 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Architecture Specific TIME specifications
++ */
++#ifndef _ASMNDS32_TIMEX_H
++#define _ASMNDS32_TIMEX_H
++
++#ifndef __FARADAY_PLATFORM_INDEPENDENT_TIMEX_HEADER__
++#define __FARADAY_PLATFORM_INDEPENDENT_TIMEX_HEADER__
++
++#include <asm/spec.h>
++
++#ifndef CLOCK_TICK_RATE
++#define CLOCK_TICK_RATE (TIMER_CLK_IN)
++#endif
++
++#endif /* __FARADAY_PLATFORM_INDEPENDENT_TIMEX_HEADER__ */
++
++typedef unsigned long cycles_t;
++
++extern cycles_t cacheflush_time;
++
++static inline cycles_t get_cycles (void)
++{
++ return 0;
++}
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/tlbflush.h linux-3.4.110/arch/nds32/include/asm/tlbflush.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/tlbflush.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/tlbflush.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,80 @@
++/*
++ * linux/arch/nds32/include/asm/tlbflush.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_TLBFLUSH_H
++#define _ASMNDS32_TLBFLUSH_H
++
++#include <linux/spinlock.h>
++#include <linux/mm.h>
++#include <nds32_intrinsic.h>
++
++static inline void local_flush_tlb_all(void)
++{
++ asm("tlbop FLUA\n");
++ __nds32__isb();
++}
++static inline void local_flush_tlb_mm(struct mm_struct *mm)
++{
++ asm("tlbop FLUA\n");
++ __nds32__isb();
++}
++static inline void local_flush_tlb_kernel_range(unsigned long start,
++ unsigned long end)
++{
++ while(start < end) {
++ asm("tlbop %0, INV"::"r" (start));
++ __nds32__isb();
++ start += PAGE_SIZE;
++ }
++}
++
++#ifndef CONFIG_CPU_NO_CONTEXT_ID
++void local_flush_tlb_range(struct vm_area_struct *vma,
++ unsigned long start, unsigned long end);
++void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
++#else
++static inline void local_flush_tlb_range(struct vm_area_struct *vma,
++ unsigned long start, unsigned long end)
++{
++ if ((end - start) > 0x400000) {
++ asm("tlbop FLUA");
++ __nds32__isb();
++ return ;
++ }
++ while(start < end) {
++ asm("tlbop %0, INV"::"r" (start));
++ __nds32__isb();
++ start += PAGE_SIZE;
++ }
++}
++
++static inline void local_flush_tlb_page(struct vm_area_struct *vma,
++ unsigned long addr)
++{
++ asm("tlbop %0, INV"::"r" (addr));
++ __nds32__isb();
++}
++#endif
++
++#ifndef CONFIG_SMP
++#define flush_tlb_all local_flush_tlb_all
++#define flush_tlb_mm local_flush_tlb_mm
++#define flush_tlb_range local_flush_tlb_range
++#define flush_tlb_page local_flush_tlb_page
++#define flush_tlb_kernel_range local_flush_tlb_kernel_range
++#else
++void flush_tlb_all(void);
++void flush_tlb_mm(struct mm_struct *mm);
++void flush_tlb_range(struct vm_area_struct *vma,
++ unsigned long start, unsigned long end);
++void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr);
++void flush_tlb_kernel_range(unsigned long start, unsigned long end);
++#endif
++
++void update_mmu_cache(struct vm_area_struct *vma,
++ unsigned long address, pte_t* pte);
++void tlb_migrate_finish(struct mm_struct *mm);
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/tlb.h linux-3.4.110/arch/nds32/include/asm/tlb.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/tlb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/tlb.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,30 @@
++/*
++ * linux/arch/nds32/include/asm/tlb.h
++ * Copyright (C) 2009 Andes Technology Corporation
++ */
++
++#ifndef __ASMNDS32_TLB_H
++#define __ASMNDS32_TLB_H
++
++#define tlb_start_vma(tlb,vma) \
++ do { \
++ if (!tlb->fullmm) \
++ flush_cache_range(vma, vma->vm_start, vma->vm_end); \
++ } while (0)
++
++#define tlb_end_vma(tlb,vma) \
++ do { \
++ if(!tlb->fullmm) \
++ flush_tlb_range(vma, vma->vm_start, vma->vm_end); \
++ } while (0)
++
++#define __tlb_remove_tlb_entry(tlb, pte, addr) do { } while (0)
++
++#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
++
++#include <asm-generic/tlb.h>
++
++#define __pte_free_tlb(tlb, pte, addr) pte_free((tlb)->mm, pte)
++#define __pmd_free_tlb(tlb, pmd, addr) pmd_free((tln)->mm, pmd)
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/topology.h linux-3.4.110/arch/nds32/include/asm/topology.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/topology.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/topology.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,11 @@
++/*
++ * linux/arch/nds32/include/asm/topology.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASM_NDS32_TOPOLOGY_H
++#define _ASM_NDS32_TOPOLOGY_H
++
++#include <asm-generic/topology.h>
++
++#endif /* _ASM_NDS32_TOPOLOGY_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/traps.h linux-3.4.110/arch/nds32/include/asm/traps.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/traps.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/traps.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,25 @@
++/*
++ * linux/arch/nds32/include/asm/traps.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_TRAP_H
++#define _ASMNDS32_TRAP_H
++
++#include <linux/list.h>
++
++struct undef_hook {
++ struct list_head node;
++ u32 instr_mask;
++ u32 instr_val;
++ u32 cpsr_mask;
++ u32 cpsr_val;
++ int (*fn)(struct pt_regs *regs, unsigned int instr);
++};
++
++void register_undef_hook(struct undef_hook *hook);
++void unregister_undef_hook(struct undef_hook *hook);
++
++extern void __init early_trap_init(void);
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/types.h linux-3.4.110/arch/nds32/include/asm/types.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/types.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/types.h 2016-04-07 10:20:50.918080096 +0200
+@@ -0,0 +1,16 @@
++#ifndef __ASM_NDS32_TYPES_H
++#define __ASM_NDS32_TYPES_H
++
++#include <asm-generic/int-ll64.h>
++
++/*
++ * These aren't exported outside the kernel to avoid name space clashes
++ */
++#ifdef __KERNEL__
++
++#define BITS_PER_LONG 32
++
++#endif /* __KERNEL__ */
++
++#endif
++
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/uaccess.h linux-3.4.110/arch/nds32/include/asm/uaccess.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/uaccess.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/uaccess.h 2016-04-07 10:20:50.934080715 +0200
+@@ -0,0 +1,428 @@
++/*
++ * linux/arch/nds32/include/asm/uaccess.h
++ *
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#ifndef _ASMANDES_UACCESS_H
++#define _ASMANDES_UACCESS_H
++
++/*
++ * User space memory access functions
++ */
++#include <linux/sched.h>
++#include <asm/errno.h>
++#include <asm/memory.h>
++#include <asm/system.h>
++#include <asm/types.h>
++#include <linux/mm.h>
++
++#define VERIFY_READ 0
++#define VERIFY_WRITE 1
++
++/*
++ * The exception table consists of pairs of addresses: the first is the
++ * address of an instruction that is allowed to fault, and the second is
++ * the address at which the program should continue. No registers are
++ * modified, so it is entirely up to the continuation code to figure out
++ * what to do.
++ *
++ * All the routines below use bits of fixup code that are out of line
++ * with the main instruction path. This means when everything is well,
++ * we don't even have to jump over them. Further, they do not intrude
++ * on our cache or tlb entries.
++ */
++
++struct exception_table_entry
++{
++ unsigned long insn, fixup;
++};
++
++extern int fixup_exception(struct pt_regs *regs);
++
++#define KERNEL_DS ((mm_segment_t) { ~0UL })
++#define USER_DS ((mm_segment_t) {TASK_SIZE - 1})
++
++#define get_ds() (KERNEL_DS)
++#define get_fs() (current_thread_info()->addr_limit)
++
++static inline void set_fs (mm_segment_t fs)
++{
++ current_thread_info()->addr_limit = fs;
++}
++
++#define segment_eq(a, b) ((a.seg) == (b.seg))
++
++#define __range_ok(addr, size) (size <= get_fs().seg && addr <= (get_fs().seg -size))
++
++#define access_ok(type, addr, size) \
++ __range_ok((unsigned long)addr, (unsigned long)size)
++/*
++ * Single-value transfer routines. They automatically use the right
++ * size if we just have the right pointer type. Note that the functions
++ * which read from user space (*get_*) need to take care not to leak
++ * kernel data even if the calling code is buggy and fails to check
++ * the return value. This means zeroing out the destination variable
++ * or buffer on error. Normally this is done out of line by the
++ * fixup code, but there are a few places where it intrudes on the
++ * main code path. When we only write to user space, there is no
++ * problem.
++ *
++ * The "__xxx" versions of the user access functions do not verify the
++ * address space - it must have been done previously with a separate
++ * "access_ok()" call.
++ *
++ * The "xxx_error" versions set the third argument to EFAULT if an
++ * error occurs, and leave it unchanged on success. Note that these
++ * versions are void (ie, don't return a value as such).
++ */
++
++extern int __get_user_1(void *);
++extern int __get_user_2(void *);
++extern int __get_user_4(void *);
++extern int __get_user_8(void *);
++extern int __get_user_bad(void);
++
++#define __get_user_x(__r2,__p,__e,__s,__i...) \
++ __asm__ __volatile__ ( \
++ __asmeq("%0", "$r0") __asmeq("%1", "$r2") \
++ "bal __get_user_" #__s \
++ : "=&r" (__e), "=r" (__r2) \
++ : "0" (__p) \
++ : __i, "cc")
++
++#define get_user(x,p) \
++ ({ \
++ const register typeof(*(p)) __user *__p asm("$r0") = (p);\
++ register unsigned long __r2 asm("$r2"); \
++ register int __e asm("$r0"); \
++ switch (sizeof(*(__p))) { \
++ case 1: \
++ __get_user_x(__r2, __p, __e, 1, "$lp"); \
++ break; \
++ case 2: \
++ __get_user_x(__r2, __p, __e, 2, "$r3", "$lp"); \
++ break; \
++ case 4: \
++ __get_user_x(__r2, __p, __e, 4, "$lp"); \
++ break; \
++ case 8: \
++ __get_user_x(__r2, __p, __e, 8, "$lp"); \
++ break; \
++ default: __e = __get_user_bad(); break; \
++ } \
++ x = (typeof(*(p))) __r2; \
++ __e; \
++ })
++
++#define __get_user(x,ptr) \
++({ \
++ long __gu_err = 0; \
++ __get_user_err((x),(ptr),__gu_err); \
++ __gu_err; \
++})
++
++#define __get_user_error(x,ptr,err) \
++({ \
++ __get_user_err((x),(ptr),err); \
++ (void) 0; \
++})
++
++#define __get_user_err(x,ptr,err) \
++do { \
++ unsigned long __gu_addr = (unsigned long)(ptr); \
++ unsigned long __gu_val; \
++ __chk_user_ptr(ptr); \
++ switch (sizeof(*(ptr))) { \
++ case 1: __get_user_asm_byte(__gu_val,__gu_addr,err); break; \
++ case 2: __get_user_asm_half(__gu_val,__gu_addr,err); break; \
++ case 4: __get_user_asm_word(__gu_val,__gu_addr,err); break; \
++ default: (__gu_val) = __get_user_bad(); \
++ } \
++ (x) = (__typeof__(*(ptr)))__gu_val; \
++} while (0)
++
++#define __get_user_asm_byte(x,addr,err) \
++ __asm__ __volatile__( \
++ "1: lbi %1,[%2]\n" \
++ "2:\n" \
++ " .section .fixup,\"ax\"\n" \
++ " .align 2\n" \
++ "3: move %0, %3\n" \
++ " move %1, #0\n" \
++ " b 2b\n" \
++ " .previous\n" \
++ " .section __ex_table,\"a\"\n" \
++ " .align 3\n" \
++ " .long 1b, 3b\n" \
++ " .previous" \
++ : "+r" (err), "=&r" (x) \
++ : "r" (addr), "i" (-EFAULT) \
++ : "cc")
++
++#ifndef __NDS32_EB__
++#define __get_user_asm_half(x,__gu_addr,err) \
++({ \
++ unsigned long __b1, __b2; \
++ __get_user_asm_byte(__b1, __gu_addr, err); \
++ __get_user_asm_byte(__b2, __gu_addr + 1, err); \
++ (x) = __b1 | (__b2 << 8); \
++})
++#else
++#define __get_user_asm_half(x,__gu_addr,err) \
++({ \
++ unsigned long __b1, __b2; \
++ __get_user_asm_byte(__b1, __gu_addr, err); \
++ __get_user_asm_byte(__b2, __gu_addr + 1, err); \
++ (x) = (__b1 << 8) | __b2; \
++})
++#endif
++
++#define __get_user_asm_word(x,addr,err) \
++ __asm__ __volatile__( \
++ "1: lwi %1,[%2]\n" \
++ "2:\n" \
++ " .section .fixup,\"ax\"\n" \
++ " .align 2\n" \
++ "3: move %0, %3\n" \
++ " move %1, #0\n" \
++ " b 2b\n" \
++ " .previous\n" \
++ " .section __ex_table,\"a\"\n" \
++ " .align 3\n" \
++ " .long 1b, 3b\n" \
++ " .previous" \
++ : "+r" (err), "=&r" (x) \
++ : "r" (addr), "i" (-EFAULT) \
++ : "cc")
++
++extern int __put_user_1(void *, unsigned int);
++extern int __put_user_2(void *, unsigned int);
++extern int __put_user_4(void *, unsigned int);
++extern int __put_user_8(void *, unsigned long long);
++extern int __put_user_bad(void);
++
++#ifdef _GCC444
++#define __put_user_x(__r2,__p,__e,__s) \
++ __asm__ __volatile__ ( \
++ __asmeq("%0", "$r0") __asmeq("%2", "$r2") \
++ "bal __put_user_" #__s \
++ : "=&r" (__e) \
++ : "0" (__p), "r" (__r2) \
++ : "$p0", "$lp", "cc")
++#else
++#define __put_user_x(__r2,__p,__e,__s) \
++ __asm__ __volatile__ ( \
++ __asmeq("%0", "$r0") __asmeq("%2", "$r2") \
++ "bal __put_user_" #__s \
++ : "=&r" (__e) \
++ : "0" (__p), "r" (__r2) \
++ : "$r26", "$lp", "cc")
++#endif
++
++#define put_user(x,p) \
++ ({ \
++ const register typeof(*(p)) __r2 asm("$r2") = (x); \
++ const register typeof(*(p)) __user *__p asm("$r0") = (p);\
++ register int __e asm("$r0"); \
++ switch (sizeof(*(__p))) { \
++ case 1: \
++ __put_user_x(__r2, __p, __e, 1); \
++ break; \
++ case 2: \
++ __put_user_x(__r2, __p, __e, 2); \
++ break; \
++ case 4: \
++ __put_user_x(__r2, __p, __e, 4); \
++ break; \
++ case 8: \
++ __put_user_x(__r2, __p, __e, 8); \
++ break; \
++ default: __e = __put_user_bad(); break; \
++ } \
++ __e; \
++ })
++
++#define __put_user(x,ptr) \
++({ \
++ long __pu_err = 0; \
++ __put_user_err((x),(ptr),__pu_err); \
++ __pu_err; \
++})
++
++#define __put_user_error(x,ptr,err) \
++({ \
++ __put_user_err((x),(ptr),err); \
++ (void) 0; \
++})
++
++#define __put_user_err(x,ptr,err) \
++do { \
++ unsigned long __pu_addr = (unsigned long)(ptr); \
++ __typeof__(*(ptr)) __pu_val = (x); \
++ __chk_user_ptr(ptr); \
++ switch (sizeof(*(ptr))) { \
++ case 1: __put_user_asm_byte(__pu_val,__pu_addr,err); break; \
++ case 2: __put_user_asm_half(__pu_val,__pu_addr,err); break; \
++ case 4: __put_user_asm_word(__pu_val,__pu_addr,err); break; \
++ case 8: __put_user_asm_dword(__pu_val,__pu_addr,err); break; \
++ default: __put_user_bad(); \
++ } \
++} while (0)
++
++#define __put_user_asm_byte(x,__pu_addr,err) \
++ __asm__ __volatile__( \
++ "1: sbi %1,[%2]\n" \
++ "2:\n" \
++ " .section .fixup,\"ax\"\n" \
++ " .align 2\n" \
++ "3: move %0, %3\n" \
++ " b 2b\n" \
++ " .previous\n" \
++ " .section __ex_table,\"a\"\n" \
++ " .align 3\n" \
++ " .long 1b, 3b\n" \
++ " .previous" \
++ : "+r" (err) \
++ : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
++ : "cc")
++
++#ifndef __NDS32_EB__
++#define __put_user_asm_half(x,__pu_addr,err) \
++({ \
++ unsigned long __temp = (unsigned long)(x); \
++ __put_user_asm_byte(__temp, __pu_addr, err); \
++ __put_user_asm_byte(__temp >> 8, __pu_addr + 1, err); \
++})
++#else
++#define __put_user_asm_half(x,__pu_addr,err) \
++({ \
++ unsigned long __temp = (unsigned long)(x); \
++ __put_user_asm_byte(__temp >> 8, __pu_addr, err); \
++ __put_user_asm_byte(__temp, __pu_addr + 1, err); \
++})
++#endif
++
++#define __put_user_asm_word(x,__pu_addr,err) \
++ __asm__ __volatile__( \
++ "1: swi %1,[%2]\n" \
++ "2:\n" \
++ " .section .fixup,\"ax\"\n" \
++ " .align 2\n" \
++ "3: move %0, %3\n" \
++ " b 2b\n" \
++ " .previous\n" \
++ " .section __ex_table,\"a\"\n" \
++ " .align 3\n" \
++ " .long 1b, 3b\n" \
++ " .previous" \
++ : "+r" (err) \
++ : "r" (x), "r" (__pu_addr), "i" (-EFAULT) \
++ : "cc")
++
++#ifdef __NDS32_EB__
++#define __reg_oper0 "%H2"
++#define __reg_oper1 "%L2"
++#else
++#define __reg_oper0 "%L2"
++#define __reg_oper1 "%H2"
++#endif
++
++#define __put_user_asm_dword(x, __pu_addr, __pu_err) \
++ __asm__ __volatile__ ( \
++ "\n1:\tswi " __reg_oper0 ",[%1]\n" \
++ "\n2:\tswi " __reg_oper1 ",[%1+4]\n" \
++ "3:\n" \
++ " .section .fixup,\"ax\"\n" \
++ " .align 2\n" \
++ "4: move %0, %3\n" \
++ " b 3b\n" \
++ " .previous\n" \
++ " .section __ex_table,\"a\"\n" \
++ " .align 3\n" \
++ " .long 1b, 4b\n" \
++ " .long 2b, 4b\n" \
++ " .previous" \
++ : "+r"(__pu_err) \
++ : "r"(__pu_addr), "r"(x), "i"(-EFAULT) \
++ : "cc")
++extern unsigned long __arch_copy_from_user(void *to, const void __user *from, unsigned long n);
++extern unsigned long __arch_copy_to_user(void __user *to, const void *from, unsigned long n);
++extern unsigned long __arch_clear_user(void __user *addr, unsigned long n);
++extern unsigned long __arch_strncpy_from_user(char *to, const char __user *from, unsigned long count);
++extern unsigned long __arch_strnlen_user(const char __user *s, long n);
++
++static inline unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
++{
++ if (access_ok(VERIFY_READ, from, n))
++ n = __arch_copy_from_user(to, from, n);
++ else /* security hole - plug it */
++ memzero(to, n);
++ return n;
++}
++
++static inline unsigned long __copy_from_user(void *to, const void __user *from, unsigned long n)
++{
++ return __arch_copy_from_user(to, from, n);
++}
++
++static inline unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
++{
++ if (access_ok(VERIFY_WRITE, to, n))
++ n = __arch_copy_to_user(to, from, n);
++ return n;
++}
++
++static inline unsigned long __copy_to_user(void __user *to, const void *from, unsigned long n)
++{
++ return __arch_copy_to_user(to, from, n);
++}
++
++#define __copy_to_user_inatomic __copy_to_user
++#define __copy_from_user_inatomic __copy_from_user
++
++static inline unsigned long clear_user (void __user *to, unsigned long n)
++{
++ if (access_ok(VERIFY_WRITE, to, n))
++ n = __arch_clear_user(to, n);
++ return n;
++}
++
++static inline unsigned long __clear_user (void __user *to, unsigned long n)
++{
++ return __arch_clear_user(to, n);
++}
++
++/*
++ * We check the flags of vma here before __arch_strncpy_from_user().
++ * An alternative way to do it is using lwup instruction in __arch_strncpy_from_user().
++ * TODO: Should perform performance evaluation of the two.
++ */
++static inline long strncpy_from_user (char *dst, const char __user *src, long count)
++{
++ long res = -EFAULT;
++ if (access_ok(VERIFY_READ, src, 1))
++ res = __arch_strncpy_from_user(dst, src, count);
++ return res;
++}
++
++static inline long __strncpy_from_user (char *dst, const char __user *src, long count)
++{
++ return __arch_strncpy_from_user(dst, src, count);
++}
++
++#define strlen_user(s) strnlen_user(s, ~0UL >> 1)
++
++static inline long strnlen_user(const char __user *s, long n)
++{
++ unsigned long res = 0;
++
++ if (segment_eq(get_fs(),KERNEL_DS) || ((unsigned long)s < get_fs().seg))
++ res = __arch_strnlen_user(s, n);
++
++ return res;
++}
++#endif /* _ASMNDS32_UACCESS_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/ucontext.h linux-3.4.110/arch/nds32/include/asm/ucontext.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/ucontext.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/ucontext.h 2016-04-07 10:20:50.934080715 +0200
+@@ -0,0 +1,17 @@
++/*
++ * linux/arch/nds32/include/asm/ucontext.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _ASMNDS32_UCONTEXT_H
++#define _ASMNDS32_UCONTEXT_H
++
++struct ucontext {
++ unsigned long uc_flags;
++ struct ucontext *uc_link;
++ stack_t uc_stack;
++ struct sigcontext uc_mcontext;
++ sigset_t uc_sigmask; /* mask last for extensibility */
++};
++
++#endif /* !_ASMNDS32_UCONTEXT_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/unaligned.h linux-3.4.110/arch/nds32/include/asm/unaligned.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/unaligned.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/unaligned.h 2016-04-07 10:20:50.934080715 +0200
+@@ -0,0 +1,24 @@
++/*
++ * linux/arch/nds32/include/asm/unaligned.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef __ASM_NDS32_UNALIGNED_H
++#define __ASM_NDS32_UNALIGNED_H
++
++#include <linux/unaligned/le_byteshift.h>
++#include <linux/unaligned/be_byteshift.h>
++#include <linux/unaligned/generic.h>
++
++/*
++ * Select endianness
++ */
++#if defined(__NDS32_EB__)
++#define get_unaligned __get_unaligned_be
++#define put_unaligned __put_unaligned_be
++#else
++#define get_unaligned __get_unaligned_le
++#define put_unaligned __put_unaligned_le
++#endif
++
++#endif /* __ASM_NDS32_UNALIGNED_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/uncompress.h linux-3.4.110/arch/nds32/include/asm/uncompress.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/uncompress.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/uncompress.h 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,65 @@
++/*
++ * linux/arch/nds32/include/asm/uncompress.h
++ *
++ * Faraday Linux Boot Loader UART (FTUART010) Routines
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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
++ *
++ * Note
++ *
++ * The first UART (FTUART010) in the system is used for dumping debug messages.
++ *
++ * ChangeLog
++ *
++ * Luke Lee 09/21/2005 Created. Heavily modified from Faraday CPE port.
++ */
++
++#include <asm/spec.h>
++
++#ifdef CONFIG_PLAT_AG102
++#define UART_PA_BASE 0x94200000
++#else
++#define UART_PA_BASE 0x99600000
++#endif
++
++#define arch_decomp_setup()
++#define arch_decomp_wdog()
++
++#ifndef STANDALONE_DEBUG
++#define putstr debug_puts
++#endif
++
++#define SERIAL_THR 0x00
++#define SERIAL_LSR 0x14
++#define SERIAL_LSR_THRE 0x20
++
++static inline void uncompress_puts(const char *s)
++{
++ volatile unsigned *status = (volatile unsigned *)(UART_PA_BASE+SERIAL_LSR);
++ while (*s) {
++ while ((*status & SERIAL_LSR_THRE)==0);
++
++ *(volatile unsigned*)(UART_PA_BASE+SERIAL_THR) = (unsigned)*s;
++
++ if (*s == '\n') {
++ while ((*status & SERIAL_LSR_THRE)==0);
++ *(volatile unsigned*)(UART_PA_BASE+SERIAL_THR) = '\r';
++ }
++ s++;
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/unistd.h linux-3.4.110/arch/nds32/include/asm/unistd.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/unistd.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/unistd.h 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,468 @@
++/*
++ * linux/arch/nds32/include/asm/unistd.h
++ *
++ * Copyright (C) 2001-2003 Russell King
++ *
++ * 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.
++ *
++ * Please forward _all_ changes to this file to rmk@arm.linux.org.uk,
++ * no matter what the change is. Thanks!
++ */
++/* ============================================================================
++ *
++ * linux/arch/nds32/include/asm/unistd.h
++ *
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is syscall scheme for Andes NDS32 architecture.
++ *
++ * Revision History:
++ *
++ * Jul.07.2007 Original from Shawn and Tom, refined by Harry.
++ *
++ * Note:
++ *
++ * ============================================================================
++ */
++
++#ifndef __ASM_NDS32_UNISTD_H
++#define __ASM_NDS32_UNISTD_H
++
++#define __NR_SYSCALL_BASE 0x5000
++#define __NR_NDS32_BASE 0x7000
++/*
++ * This file contains the system call numbers.
++ */
++
++#define __NR_restart_syscall (__NR_SYSCALL_BASE+ 0)
++#define __NR_exit (__NR_SYSCALL_BASE+ 1)
++#define __NR_fork (__NR_SYSCALL_BASE+ 2)
++#define __NR_read (__NR_SYSCALL_BASE+ 3)
++#define __NR_write (__NR_SYSCALL_BASE+ 4)
++#define __NR_open (__NR_SYSCALL_BASE+ 5)
++#define __NR_close (__NR_SYSCALL_BASE+ 6)
++#define __NR_waitpid (__NR_SYSCALL_BASE+ 7)
++ /* 7 was sys_waitpid */
++#define __NR_creat (__NR_SYSCALL_BASE+ 8)
++#define __NR_link (__NR_SYSCALL_BASE+ 9)
++#define __NR_unlink (__NR_SYSCALL_BASE+ 10)
++#define __NR_execve (__NR_SYSCALL_BASE+ 11)
++#define __NR_chdir (__NR_SYSCALL_BASE+ 12)
++#define __NR_time (__NR_SYSCALL_BASE+ 13)
++#define __NR_mknod (__NR_SYSCALL_BASE+ 14)
++#define __NR_chmod (__NR_SYSCALL_BASE+ 15)
++#define __NR_lchown (__NR_SYSCALL_BASE+ 16)
++ /* 17 was sys_break */
++ /* 18 was sys_oldstat */
++#define __NR_lseek (__NR_SYSCALL_BASE+ 19)
++#define __NR_getpid (__NR_SYSCALL_BASE+ 20)
++#define __NR_mount (__NR_SYSCALL_BASE+ 21)
++#define __NR_umount (__NR_SYSCALL_BASE+ 22)
++#define __NR_setuid (__NR_SYSCALL_BASE+ 23)
++#define __NR_getuid (__NR_SYSCALL_BASE+ 24)
++#define __NR_stime (__NR_SYSCALL_BASE+ 25)
++#define __NR_ptrace (__NR_SYSCALL_BASE+ 26)
++#define __NR_alarm (__NR_SYSCALL_BASE+ 27)
++ /* 28 was sys_oldfstat */
++#define __NR_pause (__NR_SYSCALL_BASE+ 29)
++#define __NR_utime (__NR_SYSCALL_BASE+ 30)
++ /* 31 was sys_stty */
++ /* 32 was sys_gtty */
++#define __NR_access (__NR_SYSCALL_BASE+ 33)
++#define __NR_nice (__NR_SYSCALL_BASE+ 34)
++ /* 35 was sys_ftime */
++#define __NR_sync (__NR_SYSCALL_BASE+ 36)
++#define __NR_kill (__NR_SYSCALL_BASE+ 37)
++#define __NR_rename (__NR_SYSCALL_BASE+ 38)
++#define __NR_mkdir (__NR_SYSCALL_BASE+ 39)
++#define __NR_rmdir (__NR_SYSCALL_BASE+ 40)
++#define __NR_dup (__NR_SYSCALL_BASE+ 41)
++#define __NR_pipe (__NR_SYSCALL_BASE+ 42)
++#define __NR_times (__NR_SYSCALL_BASE+ 43)
++ /* 44 was sys_prof */
++#define __NR_brk (__NR_SYSCALL_BASE+ 45)
++#define __NR_setgid (__NR_SYSCALL_BASE+ 46)
++#define __NR_getgid (__NR_SYSCALL_BASE+ 47)
++ /* 48 was sys_signal */
++#define __NR_geteuid (__NR_SYSCALL_BASE+ 49)
++#define __NR_getegid (__NR_SYSCALL_BASE+ 50)
++#define __NR_acct (__NR_SYSCALL_BASE+ 51)
++#define __NR_umount2 (__NR_SYSCALL_BASE+ 52)
++ /* 53 was sys_lock */
++#define __NR_ioctl (__NR_SYSCALL_BASE+ 54)
++#define __NR_fcntl (__NR_SYSCALL_BASE+ 55)
++ /* 56 was sys_mpx */
++#define __NR_setpgid (__NR_SYSCALL_BASE+ 57)
++ /* 58 was sys_ulimit */
++ /* 59 was sys_olduname */
++#define __NR_umask (__NR_SYSCALL_BASE+ 60)
++#define __NR_chroot (__NR_SYSCALL_BASE+ 61)
++#define __NR_ustat (__NR_SYSCALL_BASE+ 62)
++#define __NR_dup2 (__NR_SYSCALL_BASE+ 63)
++#define __NR_getppid (__NR_SYSCALL_BASE+ 64)
++#define __NR_getpgrp (__NR_SYSCALL_BASE+ 65)
++#define __NR_setsid (__NR_SYSCALL_BASE+ 66)
++#define __NR_sigaction (__NR_SYSCALL_BASE+ 67)
++ /* 68 was sys_sgetmask */
++ /* 69 was sys_ssetmask */
++#define __NR_setreuid (__NR_SYSCALL_BASE+ 70)
++#define __NR_setregid (__NR_SYSCALL_BASE+ 71)
++#define __NR_sigsuspend (__NR_SYSCALL_BASE+ 72)
++#define __NR_sigpending (__NR_SYSCALL_BASE+ 73)
++#define __NR_sethostname (__NR_SYSCALL_BASE+ 74)
++#define __NR_setrlimit (__NR_SYSCALL_BASE+ 75)
++#define __NR_getrlimit (__NR_SYSCALL_BASE+ 76) /* Back compat 2GB limited rlimit */
++#define __NR_getrusage (__NR_SYSCALL_BASE+ 77)
++#define __NR_gettimeofday (__NR_SYSCALL_BASE+ 78)
++#define __NR_settimeofday (__NR_SYSCALL_BASE+ 79)
++#define __NR_getgroups (__NR_SYSCALL_BASE+ 80)
++#define __NR_setgroups (__NR_SYSCALL_BASE+ 81)
++#define __NR_select (__NR_SYSCALL_BASE+ 82)
++#define __NR_symlink (__NR_SYSCALL_BASE+ 83)
++ /* 84 was sys_lstat */
++#define __NR_readlink (__NR_SYSCALL_BASE+ 85)
++#define __NR_uselib (__NR_SYSCALL_BASE+ 86)
++#define __NR_swapon (__NR_SYSCALL_BASE+ 87)
++#define __NR_reboot (__NR_SYSCALL_BASE+ 88)
++#define __NR_readdir (__NR_SYSCALL_BASE+ 89)
++#define __NR_mmap (__NR_SYSCALL_BASE+ 90)
++#define __NR_munmap (__NR_SYSCALL_BASE+ 91)
++#define __NR_truncate (__NR_SYSCALL_BASE+ 92)
++#define __NR_ftruncate (__NR_SYSCALL_BASE+ 93)
++#define __NR_fchmod (__NR_SYSCALL_BASE+ 94)
++#define __NR_fchown (__NR_SYSCALL_BASE+ 95)
++#define __NR_getpriority (__NR_SYSCALL_BASE+ 96)
++#define __NR_setpriority (__NR_SYSCALL_BASE+ 97)
++ /* 98 was sys_profil */
++#define __NR_statfs (__NR_SYSCALL_BASE+ 99)
++#define __NR_fstatfs (__NR_SYSCALL_BASE+100)
++ /* 101 was sys_ioperm */
++#define __NR_socketcall (__NR_SYSCALL_BASE+102)
++#define __NR_syslog (__NR_SYSCALL_BASE+103)
++#define __NR_setitimer (__NR_SYSCALL_BASE+104)
++#define __NR_getitimer (__NR_SYSCALL_BASE+105)
++#define __NR_stat (__NR_SYSCALL_BASE+106)
++#define __NR_lstat (__NR_SYSCALL_BASE+107)
++#define __NR_fstat (__NR_SYSCALL_BASE+108)
++ /* 109 was sys_uname */
++ /* 110 was sys_iopl */
++#define __NR_vhangup (__NR_SYSCALL_BASE+111)
++ /* 112 was sys_idle */
++#define __NR_syscall (__NR_SYSCALL_BASE+113) /* syscall to call a syscall! */
++#define __NR_wait4 (__NR_SYSCALL_BASE+114)
++#define __NR_swapoff (__NR_SYSCALL_BASE+115)
++#define __NR_sysinfo (__NR_SYSCALL_BASE+116)
++#define __NR_ipc (__NR_SYSCALL_BASE+117)
++#define __NR_fsync (__NR_SYSCALL_BASE+118)
++#define __NR_sigreturn (__NR_SYSCALL_BASE+119)
++#define __NR_clone (__NR_SYSCALL_BASE+120)
++#define __NR_setdomainname (__NR_SYSCALL_BASE+121)
++#define __NR_uname (__NR_SYSCALL_BASE+122)
++ /* 123 was sys_modify_ldt */
++#define __NR_adjtimex (__NR_SYSCALL_BASE+124)
++#define __NR_mprotect (__NR_SYSCALL_BASE+125)
++#define __NR_sigprocmask (__NR_SYSCALL_BASE+126)
++ /* 127 was sys_create_module */
++#define __NR_init_module (__NR_SYSCALL_BASE+128)
++#define __NR_delete_module (__NR_SYSCALL_BASE+129)
++ /* 130 was sys_get_kernel_syms */
++#define __NR_quotactl (__NR_SYSCALL_BASE+131)
++#define __NR_getpgid (__NR_SYSCALL_BASE+132)
++#define __NR_fchdir (__NR_SYSCALL_BASE+133)
++#define __NR_bdflush (__NR_SYSCALL_BASE+134)
++#define __NR_sysfs (__NR_SYSCALL_BASE+135)
++#define __NR_personality (__NR_SYSCALL_BASE+136)
++ /* 137 was sys_afs_syscall */
++#define __NR_setfsuid (__NR_SYSCALL_BASE+138)
++#define __NR_setfsgid (__NR_SYSCALL_BASE+139)
++#define __NR__llseek (__NR_SYSCALL_BASE+140)
++#define __NR_getdents (__NR_SYSCALL_BASE+141)
++#define __NR__newselect (__NR_SYSCALL_BASE+142)
++#define __NR_flock (__NR_SYSCALL_BASE+143)
++#define __NR_msync (__NR_SYSCALL_BASE+144)
++#define __NR_readv (__NR_SYSCALL_BASE+145)
++#define __NR_writev (__NR_SYSCALL_BASE+146)
++#define __NR_getsid (__NR_SYSCALL_BASE+147)
++#define __NR_fdatasync (__NR_SYSCALL_BASE+148)
++#define __NR__sysctl (__NR_SYSCALL_BASE+149)
++#define __NR_mlock (__NR_SYSCALL_BASE+150)
++#define __NR_munlock (__NR_SYSCALL_BASE+151)
++#define __NR_mlockall (__NR_SYSCALL_BASE+152)
++#define __NR_munlockall (__NR_SYSCALL_BASE+153)
++#define __NR_sched_setparam (__NR_SYSCALL_BASE+154)
++#define __NR_sched_getparam (__NR_SYSCALL_BASE+155)
++#define __NR_sched_setscheduler (__NR_SYSCALL_BASE+156)
++#define __NR_sched_getscheduler (__NR_SYSCALL_BASE+157)
++#define __NR_sched_yield (__NR_SYSCALL_BASE+158)
++#define __NR_sched_get_priority_max (__NR_SYSCALL_BASE+159)
++#define __NR_sched_get_priority_min (__NR_SYSCALL_BASE+160)
++#define __NR_sched_rr_get_interval (__NR_SYSCALL_BASE+161)
++#define __NR_nanosleep (__NR_SYSCALL_BASE+162)
++#define __NR_mremap (__NR_SYSCALL_BASE+163)
++#define __NR_setresuid (__NR_SYSCALL_BASE+164)
++#define __NR_getresuid (__NR_SYSCALL_BASE+165)
++#define __NR_getpagesize (__NR_SYSCALL_BASE+166)
++ /* 167 was sys_query_module */
++#define __NR_poll (__NR_SYSCALL_BASE+168)
++#define __NR_nfsservctl (__NR_SYSCALL_BASE+169)
++#define __NR_setresgid (__NR_SYSCALL_BASE+170)
++#define __NR_getresgid (__NR_SYSCALL_BASE+171)
++#define __NR_prctl (__NR_SYSCALL_BASE+172)
++#define __NR_rt_sigreturn (__NR_SYSCALL_BASE+173)
++#define __NR_rt_sigaction (__NR_SYSCALL_BASE+174)
++#define __NR_rt_sigprocmask (__NR_SYSCALL_BASE+175)
++#define __NR_rt_sigpending (__NR_SYSCALL_BASE+176)
++#define __NR_rt_sigtimedwait (__NR_SYSCALL_BASE+177)
++#define __NR_rt_sigqueueinfo (__NR_SYSCALL_BASE+178)
++#define __NR_rt_sigsuspend (__NR_SYSCALL_BASE+179)
++#define __NR_pread64 (__NR_SYSCALL_BASE+180)
++#define __NR_pwrite64 (__NR_SYSCALL_BASE+181)
++#define __NR_chown (__NR_SYSCALL_BASE+182)
++#define __NR_getcwd (__NR_SYSCALL_BASE+183)
++#define __NR_capget (__NR_SYSCALL_BASE+184)
++#define __NR_capset (__NR_SYSCALL_BASE+185)
++#define __NR_sigaltstack (__NR_SYSCALL_BASE+186)
++#define __NR_sendfile (__NR_SYSCALL_BASE+187)
++ /* 188 reserved */
++ /* 189 reserved */
++#define __NR_vfork (__NR_SYSCALL_BASE+190)
++#define __NR_ugetrlimit (__NR_SYSCALL_BASE+191) /* SuS compliant getrlimit */
++#define __NR_mmap2 (__NR_SYSCALL_BASE+192)
++#define __NR_truncate64 (__NR_SYSCALL_BASE+193)
++#define __NR_ftruncate64 (__NR_SYSCALL_BASE+194)
++#define __NR_stat64 (__NR_SYSCALL_BASE+195)
++#define __NR_lstat64 (__NR_SYSCALL_BASE+196)
++#define __NR_fstat64 (__NR_SYSCALL_BASE+197)
++#define __NR_lchown32 (__NR_SYSCALL_BASE+198)
++#define __NR_getuid32 (__NR_SYSCALL_BASE+199)
++#define __NR_getgid32 (__NR_SYSCALL_BASE+200)
++#define __NR_geteuid32 (__NR_SYSCALL_BASE+201)
++#define __NR_getegid32 (__NR_SYSCALL_BASE+202)
++#define __NR_setreuid32 (__NR_SYSCALL_BASE+203)
++#define __NR_setregid32 (__NR_SYSCALL_BASE+204)
++#define __NR_getgroups32 (__NR_SYSCALL_BASE+205)
++#define __NR_setgroups32 (__NR_SYSCALL_BASE+206)
++#define __NR_fchown32 (__NR_SYSCALL_BASE+207)
++#define __NR_setresuid32 (__NR_SYSCALL_BASE+208)
++#define __NR_getresuid32 (__NR_SYSCALL_BASE+209)
++#define __NR_setresgid32 (__NR_SYSCALL_BASE+210)
++#define __NR_getresgid32 (__NR_SYSCALL_BASE+211)
++#define __NR_chown32 (__NR_SYSCALL_BASE+212)
++#define __NR_setuid32 (__NR_SYSCALL_BASE+213)
++#define __NR_setgid32 (__NR_SYSCALL_BASE+214)
++#define __NR_setfsuid32 (__NR_SYSCALL_BASE+215)
++#define __NR_setfsgid32 (__NR_SYSCALL_BASE+216)
++#define __NR_getdents64 (__NR_SYSCALL_BASE+217)
++#define __NR_pivot_root (__NR_SYSCALL_BASE+218)
++#define __NR_mincore (__NR_SYSCALL_BASE+219)
++#define __NR_madvise (__NR_SYSCALL_BASE+220)
++#define __NR_fcntl64 (__NR_SYSCALL_BASE+221)
++ /* 222 for tux */
++ /* 223 is unused */
++#define __NR_gettid (__NR_SYSCALL_BASE+224)
++#define __NR_readahead (__NR_SYSCALL_BASE+225)
++#define __NR_setxattr (__NR_SYSCALL_BASE+226)
++#define __NR_lsetxattr (__NR_SYSCALL_BASE+227)
++#define __NR_fsetxattr (__NR_SYSCALL_BASE+228)
++#define __NR_getxattr (__NR_SYSCALL_BASE+229)
++#define __NR_lgetxattr (__NR_SYSCALL_BASE+230)
++#define __NR_fgetxattr (__NR_SYSCALL_BASE+231)
++#define __NR_listxattr (__NR_SYSCALL_BASE+232)
++#define __NR_llistxattr (__NR_SYSCALL_BASE+233)
++#define __NR_flistxattr (__NR_SYSCALL_BASE+234)
++#define __NR_removexattr (__NR_SYSCALL_BASE+235)
++#define __NR_lremovexattr (__NR_SYSCALL_BASE+236)
++#define __NR_fremovexattr (__NR_SYSCALL_BASE+237)
++#define __NR_tkill (__NR_SYSCALL_BASE+238)
++#define __NR_sendfile64 (__NR_SYSCALL_BASE+239)
++#define __NR_futex (__NR_SYSCALL_BASE+240)
++#define __NR_sched_setaffinity (__NR_SYSCALL_BASE+241)
++#define __NR_sched_getaffinity (__NR_SYSCALL_BASE+242)
++#define __NR_io_setup (__NR_SYSCALL_BASE+243)
++#define __NR_io_destroy (__NR_SYSCALL_BASE+244)
++#define __NR_io_getevents (__NR_SYSCALL_BASE+245)
++#define __NR_io_submit (__NR_SYSCALL_BASE+246)
++#define __NR_io_cancel (__NR_SYSCALL_BASE+247)
++#define __NR_exit_group (__NR_SYSCALL_BASE+248)
++#define __NR_lookup_dcookie (__NR_SYSCALL_BASE+249)
++#define __NR_epoll_create (__NR_SYSCALL_BASE+250)
++#define __NR_epoll_ctl (__NR_SYSCALL_BASE+251)
++#define __NR_epoll_wait (__NR_SYSCALL_BASE+252)
++#define __NR_remap_file_pages (__NR_SYSCALL_BASE+253)
++ /* 254 for set_thread_area */
++ /* 255 for get_thread_area */
++#define __NR_set_tid_address (__NR_SYSCALL_BASE+256)
++#define __NR_timer_create (__NR_SYSCALL_BASE+257)
++#define __NR_timer_settime (__NR_SYSCALL_BASE+258)
++#define __NR_timer_gettime (__NR_SYSCALL_BASE+259)
++#define __NR_timer_getoverrun (__NR_SYSCALL_BASE+260)
++#define __NR_timer_delete (__NR_SYSCALL_BASE+261)
++#define __NR_clock_settime (__NR_SYSCALL_BASE+262)
++#define __NR_clock_gettime (__NR_SYSCALL_BASE+263)
++#define __NR_clock_getres (__NR_SYSCALL_BASE+264)
++#define __NR_clock_nanosleep (__NR_SYSCALL_BASE+265)
++#define __NR_statfs64 (__NR_SYSCALL_BASE+266)
++#define __NR_fstatfs64 (__NR_SYSCALL_BASE+267)
++#define __NR_tgkill (__NR_SYSCALL_BASE+268)
++#define __NR_utimes (__NR_SYSCALL_BASE+269)
++#define __NR_fadvise64_64 (__NR_SYSCALL_BASE+270)
++#define __NR_pciconfig_iobase (__NR_SYSCALL_BASE+271)
++#define __NR_pciconfig_read (__NR_SYSCALL_BASE+272)
++#define __NR_pciconfig_write (__NR_SYSCALL_BASE+273)
++#define __NR_mq_open (__NR_SYSCALL_BASE+274)
++#define __NR_mq_unlink (__NR_SYSCALL_BASE+275)
++#define __NR_mq_timedsend (__NR_SYSCALL_BASE+276)
++#define __NR_mq_timedreceive (__NR_SYSCALL_BASE+277)
++#define __NR_mq_notify (__NR_SYSCALL_BASE+278)
++#define __NR_mq_getsetattr (__NR_SYSCALL_BASE+279)
++#define __NR_waitid (__NR_SYSCALL_BASE+280)
++#define __NR_add_key (__NR_SYSCALL_BASE+281)
++#define __NR_request_key (__NR_SYSCALL_BASE+282)
++#define __NR_keyctl (__NR_SYSCALL_BASE+283)
++#define __NR_ioprio_set (__NR_SYSCALL_BASE+284)
++#define __NR_ioprio_get (__NR_SYSCALL_BASE+285)
++#define __NR_inotify_init (__NR_SYSCALL_BASE+286)
++#define __NR_inotify_add_watch (__NR_SYSCALL_BASE+287)
++#define __NR_inotify_rm_watch (__NR_SYSCALL_BASE+288)
++#define __NR_migrate_pages (__NR_SYSCALL_BASE+289)
++#define __NR_openat (__NR_SYSCALL_BASE+290)
++#define __NR_mkdirat (__NR_SYSCALL_BASE+291)
++#define __NR_mknodat (__NR_SYSCALL_BASE+292)
++#define __NR_fchownat (__NR_SYSCALL_BASE+293)
++#define __NR_futimesat (__NR_SYSCALL_BASE+294)
++#define __NR_fstatat64 (__NR_SYSCALL_BASE+295)
++#define __NR_unlinkat (__NR_SYSCALL_BASE+296)
++#define __NR_renameat (__NR_SYSCALL_BASE+297)
++#define __NR_linkat (__NR_SYSCALL_BASE+298)
++#define __NR_symlinkat (__NR_SYSCALL_BASE+299)
++#define __NR_readlinkat (__NR_SYSCALL_BASE+300)
++#define __NR_fchmodat (__NR_SYSCALL_BASE+301)
++#define __NR_faccessat (__NR_SYSCALL_BASE+302)
++#define __NR_pselect6 (__NR_SYSCALL_BASE+303)
++#define __NR_ppoll (__NR_SYSCALL_BASE+304)
++#define __NR_unshare (__NR_SYSCALL_BASE+305)
++#define __NR_set_robust_list (__NR_SYSCALL_BASE+306)
++#define __NR_get_robust_list (__NR_SYSCALL_BASE+307)
++#define __NR_splice (__NR_SYSCALL_BASE+308)
++#define __NR_sync_file_range2 (__NR_SYSCALL_BASE+309)
++#define __NR_tee (__NR_SYSCALL_BASE+310)
++#define __NR_vmsplice (__NR_SYSCALL_BASE+311)
++#define __NR_move_pages (__NR_SYSCALL_BASE+312)
++#define __NR_fadvise64 (__NR_SYSCALL_BASE+313)
++#define __NR_utimensat (__NR_SYSCALL_BASE+314)
++#define __NR_signalfd (__NR_SYSCALL_BASE+315)
++#define __NR_timerfd_create (__NR_SYSCALL_BASE+316)
++#define __NR_eventfd (__NR_SYSCALL_BASE+317)
++#define __NR_fallocate (__NR_SYSCALL_BASE+318)
++#define __NR_timerfd_settime (__NR_SYSCALL_BASE+319)
++#define __NR_timerfd_gettime (__NR_SYSCALL_BASE+320)
++#define __NR_getcpu (__NR_SYSCALL_BASE+321)
++#define __NR_signalfd4 (__NR_SYSCALL_BASE+322)
++#define __NR_eventfd2 (__NR_SYSCALL_BASE+323)
++#define __NR_epoll_create1 (__NR_SYSCALL_BASE+324)
++#define __NR_dup3 (__NR_SYSCALL_BASE+325)
++#define __NR_pipe2 (__NR_SYSCALL_BASE+326)
++#define __NR_inotify_init1 (__NR_SYSCALL_BASE+327)
++#define __NR_kexec_load (__NR_SYSCALL_BASE+328)
++#define __NR_accept (__NR_SYSCALL_BASE+329)
++#define __NR_bind (__NR_SYSCALL_BASE+330)
++#define __NR_connect (__NR_SYSCALL_BASE+331)
++#define __NR_getpeername (__NR_SYSCALL_BASE+332)
++#define __NR_getsockname (__NR_SYSCALL_BASE+333)
++#define __NR_getsockopt (__NR_SYSCALL_BASE+334)
++#define __NR_listen (__NR_SYSCALL_BASE+335)
++#define __NR_recv (__NR_SYSCALL_BASE+336)
++#define __NR_recvfrom (__NR_SYSCALL_BASE+337)
++#define __NR_recvmsg (__NR_SYSCALL_BASE+338)
++#define __NR_send (__NR_SYSCALL_BASE+339)
++#define __NR_sendmsg (__NR_SYSCALL_BASE+340)
++#define __NR_sendto (__NR_SYSCALL_BASE+341)
++#define __NR_setsockopt (__NR_SYSCALL_BASE+342)
++#define __NR_shutdown (__NR_SYSCALL_BASE+343)
++#define __NR_socket (__NR_SYSCALL_BASE+344)
++#define __NR_socketpair (__NR_SYSCALL_BASE+345)
++#define __NR_prlimit64 (__NR_SYSCALL_BASE+346)
++#define __NR_accept4 (__NR_SYSCALL_BASE+347)
++#define __NR_recvmmsg (__NR_SYSCALL_BASE+348)
++#define __NR_sendmmsg (__NR_SYSCALL_BASE+349)
++#define __NR_fanotify_init (__NR_SYSCALL_BASE+350)
++#define __NR_fanotify_mark (__NR_SYSCALL_BASE+351)
++#define __NR_msgget (__NR_SYSCALL_BASE+352)
++#define __NR_msgctl (__NR_SYSCALL_BASE+353)
++#define __NR_msgrcv (__NR_SYSCALL_BASE+354)
++#define __NR_msgsnd (__NR_SYSCALL_BASE+355)
++#define __NR_semget (__NR_SYSCALL_BASE+356)
++#define __NR_semctl (__NR_SYSCALL_BASE+357)
++#define __NR_semtimedop (__NR_SYSCALL_BASE+358)
++#define __NR_semop (__NR_SYSCALL_BASE+359)
++#define __NR_shmget (__NR_SYSCALL_BASE+360)
++#define __NR_shmctl (__NR_SYSCALL_BASE+361)
++#define __NR_shmat (__NR_SYSCALL_BASE+362)
++#define __NR_shmdt (__NR_SYSCALL_BASE+363)
++#define __NR_syncfs (__NR_SYSCALL_BASE+364)
++#define __NR_setns (__NR_SYSCALL_BASE+365)
++#define __NR_name_to_handle_at (__NR_SYSCALL_BASE+366)
++#define __NR_open_by_handle_at (__NR_SYSCALL_BASE+367)
++#define __NR_process_vm_readv (__NR_SYSCALL_BASE+368)
++#define __NR_process_vm_writev (__NR_SYSCALL_BASE+369)
++#define __NR_clock_adjtime (__NR_SYSCALL_BASE+370)
++#define __NR_get_mempolicy (__NR_SYSCALL_BASE+371)
++#define __NR_mbind (__NR_SYSCALL_BASE+372)
++#define __NR_perf_event_open (__NR_SYSCALL_BASE+373)
++#define __NR_preadv (__NR_SYSCALL_BASE+374)
++#define __NR_pwritev (__NR_SYSCALL_BASE+375)
++#define __NR_rt_tgsigqueueinfo (__NR_SYSCALL_BASE+376)
++#define __NR_set_mempolicy (__NR_SYSCALL_BASE+377)
++#define __NR_epoll_pwait (__NR_SYSCALL_BASE+378)
++
++
++
++
++#define __NR_lmmap (__NR_NDS32_BASE+ 1)
++#define __NR_lmunmap (__NR_NDS32_BASE+ 2)
++#define __NR_lmdma (__NR_NDS32_BASE+ 3)
++#define __NR_pfmctl (__NR_NDS32_BASE+ 4)
++#define __NR_getpfm (__NR_NDS32_BASE+ 5)
++#define __NR_setpfm (__NR_NDS32_BASE+ 6)
++#define __NR_wbna (__NR_NDS32_BASE+ 7)
++
++
++
++#ifdef __KERNEL__
++
++#define __ARCH_WANT_IPC_PARSE_VERSION
++#define __ARCH_WANT_OLD_READDIR
++#define __ARCH_WANT_STAT64
++#define __ARCH_WANT_SYS_ALARM
++#define __ARCH_WANT_SYS_GETHOSTNAME
++#define __ARCH_WANT_SYS_PAUSE
++#define __ARCH_WANT_SYS_TIME
++#define __ARCH_WANT_SYS_UTIME
++#define __ARCH_WANT_SYS_SOCKETCALL
++#define __ARCH_WANT_SYS_FADVISE64
++#define __ARCH_WANT_SYS_GETPGRP
++#define __ARCH_WANT_SYS_LLSEEK
++#define __ARCH_WANT_SYS_NICE
++#define __ARCH_WANT_SYS_OLD_GETRLIMIT
++#define __ARCH_WANT_SYS_OLD_MMAP
++#define __ARCH_WANT_SYS_OLDUMOUNT
++#define __ARCH_WANT_SYS_SIGPENDING
++#define __ARCH_WANT_SYS_SIGPROCMASK
++#define __ARCH_WANT_SYS_RT_SIGACTION
++
++/*
++ * "Conditional" syscalls
++ *
++ * What we want is __attribute__((weak,alias("sys_ni_syscall"))),
++ * but it doesn't work on all toolchains, so we just do it by hand
++ */
++#define cond_syscall(x) asm(".weak\t" #x "\n\t.set\t" #x ",sys_ni_syscall");
++
++#endif
++#endif /* __ASM_NDS32_UNISTD_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/user.h linux-3.4.110/arch/nds32/include/asm/user.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/user.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/user.h 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,89 @@
++/*
++ * linux/arch/nds32/include/asm/user.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef _NDS32_USER_H
++#define _NDS32_USER_H
++
++#include <asm/page.h>
++#include <asm/ptrace.h>
++/* Core file format: The core file is written in such a way that gdb
++ can understand it and provide useful information to the user (under
++ linux we use the 'trad-core' bfd). There are quite a number of
++ obstacles to being able to view the contents of the floating point
++ registers, and until these are solved you will not be able to view the
++ contents of them. Actually, you can read in the core file and look at
++ the contents of the user struct to find out what the floating point
++ registers contain.
++ The actual file contents are as follows:
++ UPAGE: 1 page consisting of a user struct that tells gdb what is present
++ in the file. Directly after this is a copy of the task_struct, which
++ is currently not used by gdb, but it may come in useful at some point.
++ All of the registers are stored as part of the upage. The upage should
++ always be only one page.
++ DATA: The data area is stored. We use current->end_text to
++ current->brk to pick up all of the user variables, plus any memory
++ that may have been malloced. No attempt is made to determine if a page
++ is demand-zero or if a page is totally unused, we just cover the entire
++ range. All of the addresses are rounded in such a way that an integral
++ number of pages is written.
++ STACK: We need the stack information in order to get a meaningful
++ backtrace. We need to write the data from (esp) to
++ current->start_stack, so we round each of these off in order to be able
++ to write an integer number of pages.
++ The minimum core file size is 3 pages, or 12288 bytes.
++*/
++
++struct user_fp {
++ struct fp_reg {
++ unsigned int sign1:1;
++ unsigned int unused:15;
++ unsigned int sign2:1;
++ unsigned int exponent:14;
++ unsigned int j:1;
++ unsigned int mantissa1:31;
++ unsigned int mantissa0:32;
++ } fpregs[8];
++ unsigned int fpsr:32;
++ unsigned int fpcr:32;
++ unsigned char ftype[8];
++ unsigned int init_flag;
++};
++
++/* When the kernel dumps core, it starts by dumping the user struct -
++ this will be used by gdb to figure out where the data and stack segments
++ are within the file, and what virtual addresses to use. */
++struct user{
++/* We start with the registers, to mimic the way that "memory" is returned
++ from the ptrace(3,...) function. */
++ struct pt_regs regs; /* Where the registers are actually stored */
++/* ptrace does not yet supply these. Someday.... */
++ int u_fpvalid; /* True if math co-processor being used. */
++ /* for this mess. Not yet used. */
++/* The rest of this junk is to help gdb figure out what goes where */
++ unsigned long int u_tsize; /* Text segment size (pages). */
++ unsigned long int u_dsize; /* Data segment size (pages). */
++ unsigned long int u_ssize; /* Stack segment size (pages). */
++ unsigned long start_code; /* Starting virtual address of text. */
++ unsigned long start_stack; /* Starting virtual address of stack area.
++ This is actually the bottom of the stack,
++ the top of the stack is always found in the
++ esp register. */
++ long int signal; /* Signal that caused the core dump. */
++ int reserved; /* No longer used */
++ struct pt_regs * u_ar0; /* Used by gdb to help find the values for */
++ /* the registers. */
++ unsigned long magic; /* To uniquely identify a core file */
++ char u_comm[32]; /* User command that was responsible */
++ int u_debugreg[8];
++ struct user_fp u_fp; /* FP state */
++ struct user_fp_struct * u_fp0;/* Used by gdb to help find the values for */
++ /* the FP registers. */
++};
++#define NBPG PAGE_SIZE
++#define UPAGES 1
++#define HOST_TEXT_START_ADDR (u.start_code)
++#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG)
++
++#endif /* _NDS32_USER_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/vga.h linux-3.4.110/arch/nds32/include/asm/vga.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/vga.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/vga.h 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,17 @@
++/*
++ * linux/arch/nds32/include/asm/vga.h
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#ifndef ASMNDS32_VGA_H
++#define ASMNDS32_VGA_H
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++
++#define VGA_MAP_MEM(x) (PCIMEM_BASE + (x))
++
++#define vga_readb(x) (*((volatile unsigned char *)x))
++#define vga_writeb(x,y) (*((volatile unsigned char *)y) = (x))
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/vmalloc.h linux-3.4.110/arch/nds32/include/asm/vmalloc.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/vmalloc.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/vmalloc.h 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,31 @@
++/*
++ * linux/arch/nds32/include/asm/vmalloc.h
++ *
++ * Faraday Platform Independent Virtual Memory Configuration
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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
++ *
++ * ChangeLog
++ *
++ * Luke Lee 09/16/2005 Copy from Faraday CPE codes.
++ */
++
++#ifndef __FARADAY_PLATFORM_INDEPENDENT_VMALLOC_HEADER__
++#define __FARADAY_PLATFORM_INDEPENDENT_VMALLOC_HEADER__
++
++#endif /* __FARADAY_PLATFORM_INDEPENDENT_VMALLOC_HEADER__ */
+diff -Nur linux-3.4.110.orig/arch/nds32/include/asm/xor.h linux-3.4.110/arch/nds32/include/asm/xor.h
+--- linux-3.4.110.orig/arch/nds32/include/asm/xor.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/include/asm/xor.h 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,157 @@
++/*
++ * linux/arch/nds32/include/asm/xor.h
++ *
++ * Copyright (C) 2001 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <asm-generic/xor.h>
++
++#define __XOR(a1, a2) a1 ^= a2
++
++
++#define GET_BLOCK_2(dst) \
++ __asm__( \
++ " lmw.bim %1, [%0], %2 \n"\
++ : "=r" (dst), "=r" (a1), "=r" (a2) \
++ : "0" (dst))
++
++#define GET_BLOCK_4(dst) \
++ __asm__( \
++ " lmw.bim %1, [%0], %1 \n" \ //ldmia %0, {%1, %2, %3, %4}
++ " lmw.bim %2, [%0], %2 \n" \
++ " lmw.bim %3, [%0], %3 \n" \
++ " lmw.bim %4, [%0], %4 \n" \
++ : "=r" (dst), "=r" (a1), "=r" (a2), "=r" (a3), "=r" (a4) \
++ : "0" (dst))
++
++#define XOR_BLOCK_2(src) \
++ __asm__(\
++ " lmw.bim %1, [%0], %2 \n " \
++ " lmw.bim %2, [%0], %2 \n" \
++ : "=r" (src), "=r" (b1), "=r" (b2) \
++ : "0" (src)); \
++ __XOR(a1, b1); __XOR(a2, b2);
++
++
++#define XOR_BLOCK_4(src) \
++ __asm__(\
++ "lmw.bim %1, [%0], %1 \n " \ // ldmia %0!, {%1, %2, %3, %4}
++ "lmw.bim %2, [%0], %2 \n " \
++ "lmw.bim %3, [%0], %3 \n " \
++ "lmw.bim %4, [%0], %4 \n " \
++ : "=r" (src), "=r" (b1), "=r" (b2), "=r" (b3), "=r" (b4) \
++ : "0" (src)); \
++ __XOR(a1, b1); __XOR(a2, b2); __XOR(a3, b3); __XOR(a4, b4)
++
++#define PUT_BLOCK_2(dst) \
++ __asm__ __volatile__( \
++ " smw.bim %2, [%0], %3" \
++ : "=r" (dst) \
++ : "0" (dst), "r" (a1), "r" (a2))
++
++#define PUT_BLOCK_4(dst) \
++ __asm__ __volatile__( \
++ " smw.bim %2, [%0], %5 \n" \
++ : "=r" (dst) \
++ : "0" (dst), "r" (a1), "r" (a2), "r" (a3), "r" (a4))
++
++static void
++xor_nds32regs_2(unsigned long bytes, unsigned long *p1, unsigned long *p2)
++{
++ unsigned int lines = bytes / sizeof(unsigned long) / 4;
++ register unsigned int a1 __asm__("r4");
++ register unsigned int a2 __asm__("r5");
++ register unsigned int a3 __asm__("r6");
++ register unsigned int a4 __asm__("r7");
++ register unsigned int b1 __asm__("r8");
++ register unsigned int b2 __asm__("r9");
++ register unsigned int b3 __asm__("p0");
++ register unsigned int b4 __asm__("ra");
++
++ do {
++ GET_BLOCK_4(p1);
++ XOR_BLOCK_4(p2);
++ PUT_BLOCK_4(p1);
++ } while (--lines);
++}
++
++static void
++xor_nds32regs_3(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3)
++{
++ unsigned int lines = bytes / sizeof(unsigned long) / 4;
++ register unsigned int a1 __asm__("r4");
++ register unsigned int a2 __asm__("r5");
++ register unsigned int a3 __asm__("r6");
++ register unsigned int a4 __asm__("r7");
++ register unsigned int b1 __asm__("r8");
++ register unsigned int b2 __asm__("r9");
++ register unsigned int b3 __asm__("p0");
++ register unsigned int b4 __asm__("ra");
++
++ do {
++ GET_BLOCK_4(p1);
++ XOR_BLOCK_4(p2);
++ XOR_BLOCK_4(p3);
++ PUT_BLOCK_4(p1);
++ } while (--lines);
++}
++
++static void
++xor_nds32regs_4(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4)
++{
++ unsigned int lines = bytes / sizeof(unsigned long) / 2;
++ register unsigned int a1 __asm__("r8");
++ register unsigned int a2 __asm__("r9");
++ register unsigned int b1 __asm__("p0");
++ register unsigned int b2 __asm__("ra");
++
++ do {
++ GET_BLOCK_2(p1);
++ XOR_BLOCK_2(p2);
++ XOR_BLOCK_2(p3);
++ XOR_BLOCK_2(p4);
++ PUT_BLOCK_2(p1);
++ } while (--lines);
++}
++
++static void
++xor_nds32regs_5(unsigned long bytes, unsigned long *p1, unsigned long *p2,
++ unsigned long *p3, unsigned long *p4, unsigned long *p5)
++{
++ unsigned int lines = bytes / sizeof(unsigned long) / 2;
++ register unsigned int a1 __asm__("r8");
++ register unsigned int a2 __asm__("r9");
++ register unsigned int b1 __asm__("p0");
++ register unsigned int b2 __asm__("ra");
++
++ do {
++ GET_BLOCK_2(p1);
++ XOR_BLOCK_2(p2);
++ XOR_BLOCK_2(p3);
++ XOR_BLOCK_2(p4);
++ XOR_BLOCK_2(p5);
++ PUT_BLOCK_2(p1);
++ } while (--lines);
++}
++
++static struct xor_block_template xor_block_nds32regs = {
++ .name = "nds32regs",
++ .do_2 = xor_nds32regs_2,
++ .do_3 = xor_nds32regs_3,
++ .do_4 = xor_nds32regs_4,
++ .do_5 = xor_nds32regs_5,
++};
++
++#undef XOR_TRY_TEMPLATES
++#define XOR_TRY_TEMPLATES \
++ do { \
++ xor_speed(&xor_block_nds32regs); \
++ xor_speed(&xor_block_8regs); \
++ xor_speed(&xor_block_32regs); \
++ } while (0)
+diff -Nur linux-3.4.110.orig/arch/nds32/Kconfig linux-3.4.110/arch/nds32/Kconfig
+--- linux-3.4.110.orig/arch/nds32/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/Kconfig 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,249 @@
++#
++# For a description of the syntax of this configuration file,
++# see Documentation/kbuild/kconfig-language.txt.
++#
++
++config NDS32
++ bool
++ default y
++ select RTC_LIB
++ select HAVE_OPROFILE
++ select HAVE_ARCH_KGDB
++ select HAVE_KPROBES
++ select HAVE_KRETPROBES
++ select HAVE_FUNCTION_TRACER
++ select HAVE_FUNCTION_GRAPH_TRACER
++ select HAVE_FUNCTION_TRACE_MCOUNT_TEST
++ select SYS_SUPPORTS_APM_EMULATION
++ select HAVE_IDE
++ select HAVE_MEMBLOCK
++ select HAVE_MEMBLOCK_NODE_MAP
++
++config GENERIC_GPIO
++ bool
++ default n
++
++config GENERIC_TIME
++ bool
++ default y
++
++config GENERIC_CLOCKEVENTS
++ bool
++ default y
++
++config NO_IOPORT
++ bool
++ default y
++
++config GENERIC_IOMAP
++ def_bool y
++
++config GENERIC_LOCKBREAK
++ bool
++ default y
++ depends on SMP && PREEMPT
++
++config RWSEM_GENERIC_SPINLOCK
++ bool
++ default y
++
++config RWSEM_XCHGADD_ALGORITHM
++ bool
++
++config GENERIC_HWEIGHT
++ bool
++ default y
++
++config GENERIC_FIND_NEXT_BIT
++ bool
++ default y
++
++config GENERIC_CALIBRATE_DELAY
++ bool
++ default y
++
++config GENERIC_BUST_SPINLOCK
++ bool
++
++config GENERIC_HARDIRQS
++ bool
++ default y
++
++config GENERIC_HARDIRQS_NO__DO_IRQ
++ def_bool y
++
++config LOCKDEP_SUPPORT
++ bool
++ default y
++
++config STACKTRACE_SUPPORT
++ bool
++ default y
++
++config HAVE_LATENCYTOP_SUPPORT
++ def_bool y
++
++source "init/Kconfig"
++source "kernel/Kconfig.freezer"
++
++menu "System Type"
++source "arch/nds32/platforms/Kconfig"
++source "arch/nds32/Kconfig.cpu"
++
++config VECTORS_BASE
++ hex
++ default 0xfeff0000 if MMU || CPU_HIGH_VECTOR
++ default DRAM_BASE if REMAP_VECTORS_TO_RAM
++ default 0x00000000
++ help
++ The base address of exception vectors.
++
++config MMU
++ bool
++ default y
++
++endmenu
++
++menu "Kernel Features"
++source "kernel/time/Kconfig"
++
++config SMP
++ bool "Symmetric Multi-Processing"
++ depends on PLATFORM_AMIC
++ select USE_GENERIC_SMP_HELPERS
++ help
++ This enables support for systems with more than one CPU. If you have
++ a system with only one CPU, like most personal computers, say N. If
++ you have a system with more than one CPU, say Y.
++
++ If you say N here, the kernel will run on single and multiprocessor
++ machines, but will use only one CPU of a multiprocessor machine. If
++ you say Y here, the kernel will run on many, but not all, single
++ processor machines. On a single processor machine, the kernel will
++ run faster if you say N here.
++
++ See also the <file:Documentation/smp.tex>,
++ <file:Documentation/smp.txt>, <file:Documentation/i386/IO-APIC.txt>,
++ <file:Documentation/nmi_watchdog.txt> and the SMP-HOWTO available at
++ <http://www.linuxdoc.org/docs.html#howto>.
++
++ If you don't know what to do here, say N.
++
++config NR_CPUS
++ int "Maximum number of CPUs (2-32)"
++ depends on SMP
++ default "4"
++
++source "kernel/Kconfig.preempt"
++source "mm/Kconfig"
++
++config FORCE_MAX_ZONEORDER
++ int "MAX_ORDER for the Page Allocator"
++ default "11"
++
++source "kernel/Kconfig.hz"
++
++config CMDLINE
++ string "Default kernel command string"
++ default "mem=64M@0x0 initrd=0x800000,8M root=/dev/ram0 rw console=ttyS0,38400n8 rootfstype=ext2 init=/sbin/init -s"
++
++endmenu
++
++menu "Power management options"
++
++config SYS_SUPPORTS_APM_EMULATION
++ bool
++
++config ARCH_SUSPEND_POSSIBLE
++ def_bool y
++
++source "kernel/power/Kconfig"
++
++if PLAT_AG101 || PLAT_AG102
++source "drivers/cpufreq/Kconfig"
++
++if PLAT_AG101
++choice
++ prompt "Default CPUFreq Implementation"
++ depends on CPU_FREQ
++ default AG101_CPU_FREQ_SCALING_MODE
++ help
++ This option sets which CPUFreq governor shall be loaded at
++ startup. If in doubt, select 'performance'.
++config AG101_CPU_FREQ_SCALING_MODE
++ bool "AG101 Frequency Scaling Mode"
++ help
++ Rescale CPU frequency and Bus clock without changing PLL.
++
++config AG101_CPU_FREQ_FCS
++ bool "AG101 Frequency Change Sequence (FCS)"
++ help
++ The Frequency Change Sequence (FCS) is used to change the system
++ clock frequency. While in the FCS, the system clocks stop. This
++ mode is intended for setting a different frequency to overwrite
++ the default value at initial boot-up. This can be used as a powr-
++ saving feature that allows the AG101 to run at the minimum required
++ frequency
++endchoice
++endif
++
++if PLAT_AG102
++choice
++ prompt "Default CPUFreq Implementation"
++ depends on CPU_FREQ
++ default AG102_CPU_FREQ_SCALING_MODE
++ help
++ This option sets which CPUFreq governor shall be loaded at
++ startup. If in doubt, select 'performance'.
++config AG102_CPU_FREQ_SCALING_MODE
++ bool "AG102 Frequency Scaling Mode"
++ help
++ Rescale CPU frequency and Bus clock without changing PLL.
++
++config AG102_CPU_FREQ_FCS
++ bool "AG102 Frequency Change Sequence (FCS)"
++ help
++ The Frequency Change Sequence (FCS) is used to change the system
++ clock frequency. While in the FCS, the system clocks stop. This
++ mode is intended for setting a different frequency to overwrite
++ the default value at initial boot-up. This can be used as a powr-
++ saving feature that allows the AG101 to run at the minimum required
++ frequency
++endchoice
++endif
++
++
++endif
++
++endmenu
++
++menu "Bus options"
++
++config PCI
++ bool "PCI support"
++ help
++ Find out whether you have a PCI motherboard. PCI is the name of a
++ bus system, i.e. the way the CPU talks to the other stuff inside
++ your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
++ VESA. If you have PCI, say Y, otherwise N.
++
++ The PCI-HOWTO, available from
++ <http://www.tldp.org/docs.html#howto>, contains valuable
++ information about which PCI hardware does work under Linux and which
++ doesn't.
++
++source "drivers/pci/Kconfig"
++
++endmenu
++
++menu "Executable file formats"
++source "fs/Kconfig.binfmt"
++endmenu
++
++source "net/Kconfig"
++source "drivers/Kconfig"
++source "fs/Kconfig"
++source "arch/nds32/Kconfig.debug"
++source "security/Kconfig"
++source "crypto/Kconfig"
++source "lib/Kconfig"
+diff -Nur linux-3.4.110.orig/arch/nds32/Kconfig.cpu linux-3.4.110/arch/nds32/Kconfig.cpu
+--- linux-3.4.110.orig/arch/nds32/Kconfig.cpu 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/Kconfig.cpu 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,148 @@
++comment "Processor Features"
++config CPU_N1213
++ bool
++
++config CPU_N1213_43U1HA0
++ bool
++
++config CPU_N1233F
++ bool
++
++config CPU_CUSTOM
++ bool
++
++config FPU
++ bool "fpu support"
++
++config UNLAZY_FPU
++ bool "Unlazy FPU support"
++ depends on FPU
++ help
++ Say Y here to enable unlazy FPU and disable lazy FPU.
++
++
++config AUDIO
++ bool "audio support" if CPU_CUSTOM
++
++config HWZOL
++ bool "hardware zero overhead loop support"
++ default y
++
++config UNLAZY_AUDIO
++ bool "Unlazy audio support"
++ depends on AUDIO
++ help
++ Say Y here to enable unlazy audio and disable lazy audio.
++choice
++ prompt "Vector Interrupt Controller mode"
++ default IVIC_INTC
++config IVIC_INTC
++ bool "IVIC mode with Interrupt Controller"
++config IVIC
++ bool "IVIC mode"
++config EVIC
++ bool "EVIC mode"
++endchoice
++
++config CPU_NO_CONTEXT_ID
++ def_bool CPU_N1213_43U1HA0 || SMP
++
++config CPU_CACHE_NONALIASING
++ bool "Non-aliasing cache"
++
++choice
++ prompt "Paging -- page size "
++ default ANDES_PAGE_SIZE_4KB
++config ANDES_PAGE_SIZE_4KB
++ bool "use 4KB page size"
++config ANDES_PAGE_SIZE_8KB
++ bool "use 8KB page size"
++endchoice
++
++config NO_KERNEL_LARGE_PAGE
++ def_bool CPU_N1213_43U1HA0 || SMP
++
++config CPU_ICACHE_DISABLE
++ bool "Disable I-Cache"
++ help
++ Say Y here to disable the processor instruction cache. Unless
++ you have a reason not to or are unsure, say N.
++
++config CPU_DCACHE_DISABLE
++ bool "Disable D-Cache"
++ help
++ Say Y here to disable the processor data cache. Unless
++ you have a reason not to or are unsure, say N.
++
++config CPU_DCACHE_WRITETHROUGH
++ bool "Force write through D-cache"
++ depends on !CPU_DCACHE_DISABLE
++ help
++ Say Y here to use the data cache in writethrough mode. Unless you
++ specifically require this or are unsure, say N.
++
++config KEXEC
++ bool "Kexec system call (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ help
++ kexec is a system call that implements the ability to shutdown your
++ current kernel, and to start another kernel. It is like a reboot
++ but it is independent of the system firmware. And like a reboot
++ you can start any kernel with it, not just Linux.
++
++ It is an ongoing process to be certain the hardware in a machine
++ is properly shutdown, so do not be surprised if this code does not
++ initially work for you. It may help to enable device hotplugging
++ support.
++
++config ABI1
++ bool "Allow ABI 1 binaries to run with this kernel (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ default n
++ help
++ This option preserves the old syscall interface of ABI 1. If
++ you know you'll be using ABI 2 or 2fp then you can say N here.
++ If this option is not selected and you attempt to execute a
++ legacy ABI binary then the result will be UNPREDICTABLE
++ (in fact it can be predicted that it won't work at all). If
++ in doubt say Y.
++
++config WBNA
++ bool "WBNA"
++ default n
++ help
++ Say Y here to enable write-back memory with no-write-allocation policy.
++
++config HSS
++ bool "Using Hardware Single-Step (HSS) instead of software breakpoint"
++ default y
++
++config ALIGNMENT_TRAP
++ tristate "Kernel support unaligned access handling"
++ depends on EXPERIMENTAL
++ default y
++ help
++ Andes processors cannot fetch/store information which is not
++ naturally aligned on the bus, i.e., a 4 byte fetch must start at an
++ address divisible by 4. On 32-bit Andes processors, these non-aligned
++ fetch/store instructions will be emulated in software if you say
++ here, which has a severe performance impact. This is necessary for
++ correct operation of some network protocols. With an IP-only
++ configuration it is safe to say N, otherwise say Y.
++
++config HIGHMEM
++ bool "High Memory Support"
++ depends on MMU
++ help
++ The address space of ARM processors is only 4 Gigabytes large
++ and it has to accommodate user address space, kernel address
++ space as well as some memory mapped IO. That means that, if you
++ have a large amount of physical memory and/or IO, not all of the
++ memory can be "permanently mapped" by the kernel. The physical
++ memory that is not permanently mapped is called "high memory".
++
++ Depending on the selected kernel/user memory split, minimum
++ vmalloc space and actual amount of RAM, you may not need this
++ option which should result in a slightly faster kernel.
++
++ If unsure, say n.
+diff -Nur linux-3.4.110.orig/arch/nds32/Kconfig.debug linux-3.4.110/arch/nds32/Kconfig.debug
+--- linux-3.4.110.orig/arch/nds32/Kconfig.debug 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/Kconfig.debug 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,82 @@
++menu "Kernel hacking"
++
++config TRACE_IRQFLAGS_SUPPORT
++ bool
++ default y
++
++source "lib/Kconfig.debug"
++
++config FRAME_POINTER
++ bool
++ default y
++ help
++ If you say N here, the resulting kernel will be slightly smaller and
++ faster. However, when a problem occurs with the kernel, the
++ information that is reported is severely limited. Most people
++ should say Y here.
++
++config DEBUG_USER
++ bool "Verbose user fault messages"
++ help
++ When a user program crashes due to an exception, the kernel can
++ print a brief message explaining what the problem was. This is
++ sometimes helpful for debugging but serves no purpose on a
++ production system. Most people should say N here.
++
++ In addition, you need to pass user_debug=N on the kernel command
++ line to enable this feature. N consists of the sum of:
++
++ 1 - undefined instruction events
++ 2 - system calls
++ 4 - invalid data aborts
++ 8 - SIGSEGV faults
++ 16 - SIGBUS faults
++
++config DEBUG_ERRORS
++ bool "Verbose kernel error messages"
++ depends on DEBUG_KERNEL
++ help
++ This option controls verbose debugging information which can be
++ printed when the kernel detects an internal error. This debugging
++ information is useful to kernel hackers when tracking down problems,
++ but mostly meaningless to other people. It's safe to say Y unless
++ you are concerned with the code size or don't want to see these
++ messages.
++
++config DEBUG_LL
++ bool "Kernel low-level debugging functions"
++ depends on DEBUG_KERNEL
++ help
++ Say Y here to include definitions of printascii, printchar, printhex
++ in the kernel. This is helpful if you are debugging code that
++ executes before the console is initialized.
++
++config CCTL
++ tristate "User space cache control support (EXPERIMENTAL)"
++ depends on EXPERIMENTAL
++ help
++ export cache control to user space via /proc
++
++ If unsure, say N.
++
++config ELFCHK_DEFAULT_ENABLE
++ bool "Enable ELF-Core Checking by default"
++ default n
++ select PROC_FS
++ help
++ ELF-Core Checking is a mechanism which prevents ELF binary from
++ being loaded if it requires any feature that the underlying platform
++ doesn't support.
++
++ If you say Y here, the resulting kernel enables ELF-Core Checking
++ mechanism by default.
++config EARLY_PRINTK
++ bool "Early printk support"
++ default y
++ help
++ Say Y here if you want to have an early console using the
++ earlyprintk=<name>[,<addr>][,<options>] kernel parameter. It
++ is assumed that the early console device has been initialised
++ by the boot loader prior to starting the Linux kernel.
++
++endmenu
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/asm-offsets.c linux-3.4.110/arch/nds32/kernel/asm-offsets.c
+--- linux-3.4.110.orig/arch/nds32/kernel/asm-offsets.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/asm-offsets.c 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,72 @@
++/*
++ * Copyright (C) 1995-2003 Russell King
++ * 2001-2002 Keith Owens
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * Generate definitions needed by assembly language modules.
++ * This code generates raw asm output which is post-processed to extract
++ * and format the required data.
++ *
++ * 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/sched.h>
++#include <linux/mm.h>
++#include <asm/mach/arch.h>
++#include <asm/thread_info.h>
++#include <asm/memory.h>
++#include <asm/procinfo.h>
++
++/*
++ * Make sure that the compiler and target are compatible.
++ */
++
++#if __GNUC__ < 3 || \
++ (__GNUC__ == 3 && __GNUC_MINOR__ < 4) || \
++ (__GNUC__ == 3 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ != 0 && \
++ __GNUC_PATCHLEVEL__ < 4) || \
++ (__GNUC__ == 4 && __GNUC_MINOR__ < 2)
++#error Your compiler is too buggy; it is known to miscompile kernels.
++#error Known good compilers: 3.4.4, 4.2
++#endif
++
++/* Use marker if you need to separate the values later */
++
++#define DEFINE(sym, val) \
++ asm volatile("\n->" #sym " %0 " #val : : "i" (val))
++
++#define BLANK() asm volatile("\n->" : : )
++
++int main(void)
++{
++ DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
++ BLANK();
++ DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
++ DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
++ DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit));
++ DEFINE(TI_TASK, offsetof(struct thread_info, task));
++ DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain));
++ DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
++// DEFINE(TI_TP_VALUE, offsetof(struct thread_info, tp_value));
++ DEFINE(TI_SP_SAVE, offsetof(struct thread_info, sp_save));
++ BLANK();
++ DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
++ BLANK();
++ DEFINE(MM_CONTEXT_ID, offsetof(struct mm_struct, context.id));
++ BLANK();
++ DEFINE(VMA_VM_MM, offsetof(struct vm_area_struct, vm_mm));
++ DEFINE(VMA_VM_FLAGS, offsetof(struct vm_area_struct, vm_flags));
++ BLANK();
++ DEFINE(VM_EXEC, VM_EXEC);
++ BLANK();
++ DEFINE(VIRT_OFFSET, PAGE_OFFSET);
++ BLANK();
++ DEFINE(SIZEOF_MACHINE_DESC, sizeof(struct machine_desc));
++ DEFINE(MACHINFO_TYPE, offsetof(struct machine_desc, nr));
++ DEFINE(MACHINFO_NAME, offsetof(struct machine_desc, name));
++ BLANK();
++ DEFINE(PROC_INFO_SZ, sizeof(struct proc_info_list));
++
++ return 0;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/audio.c linux-3.4.110/arch/nds32/kernel/audio.c
+--- linux-3.4.110.orig/arch/nds32/kernel/audio.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/audio.c 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,218 @@
++/*
++ * arch/nds32/kernel/audio.c
++ *
++ * Copyright (C) 2001 Manuela Cirronis, Paolo Alberelli
++ * Copyright (C) 2002 STMicroelectronics Limited
++ * Author : Stuart Menefy
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * Started from SH4 version:
++ * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/sched.h>
++#include <linux/signal.h>
++#include <asm/processor.h>
++#include <asm/user.h>
++#include <asm/io.h>
++#include <asm/bitfield.h>
++#include <asm/audio.h>
++#include "audio.h"
++/*
++ * Initially load the audio with signalling NANS. This bit pattern
++ * has the property that no matter whether considered as single or as
++ * double precision, it still represents a signalling NAN.
++ */
++
++static struct audio_struct init_audioregs = {
++ .auregs = {[0...31] = NAN32}
++};
++
++void save_audio(struct task_struct *tsk)
++{
++ unsigned int tmp;
++ enable_audio();
++ asm volatile ("mfsr %0, $MSC_CFG\n\t"
++ "andi %0, %0, %2\n\t"
++ "srli %0, %0, %3\n\t"
++ "slti %0, %0, 2\n\t"
++ "bnez %0, 99f\n\t"
++ "amfar %0, $D0.L24\n\t"
++ "swi %0, [%1+0x0]\n\t"
++ "amfar %0, $D1.L24\n\t"
++ "swi %0, [%1+0x4]\n\t"
++ "99:\n\t"
++ "amfar %0, $I0\n\t"
++ "swi %0, [%1+0x8]\n\t"
++ "amfar %0, $I1\n\t"
++ "swi %0, [%1+0xc]\n\t"
++ "amfar %0, $I2\n\t"
++ "swi %0, [%1+0x10]\n\t"
++ "amfar %0, $I3\n\t"
++ "swi %0, [%1+0x14]\n\t"
++ "amfar %0, $I4\n\t"
++ "swi %0, [%1+0x18]\n\t"
++ "amfar %0, $I5\n\t"
++ "swi %0, [%1+0x1c]\n\t"
++ "amfar %0, $I6\n\t"
++ "swi %0, [%1+0x20]\n\t"
++ "amfar %0, $I7\n\t"
++ "swi %0, [%1+0x24]\n\t"
++ "amfar %0, $M1\n\t"
++ "swi %0, [%1+0x28]\n\t"
++ "amfar %0, $M2\n\t"
++ "swi %0, [%1+0x2c]\n\t"
++ "amfar %0, $M3\n\t"
++ "swi %0, [%1+0x30]\n\t"
++ "amfar %0, $M5\n\t"
++ "swi %0, [%1+0x34]\n\t"
++ "amfar %0, $M6\n\t"
++ "swi %0, [%1+0x38]\n\t"
++ "amfar %0, $M7\n\t"
++ "swi %0, [%1+0x3c]\n\t"
++ "amfar %0, $MOD\n\t"
++ "swi %0, [%1+0x40]\n\t"
++ "amfar %0, $LB\n\t"
++ "swi %0, [%1+0x44]\n\t"
++ "amfar %0, $LE\n\t"
++ "swi %0, [%1+0x48]\n\t"
++ "amfar %0, $LC\n\t"
++ "swi %0, [%1+0x4c]\n\t"
++ "amfar %0, $ADM_VBASE\n\t"
++ "swi %0, [%1+0x50]\n\t"
++ "amfar %0, $SHFT_CTL0\n\t"
++ "swi %0, [%1+0x54]\n\t"
++ "amfar %0, $SHFT_CTL1\n\t"
++ "swi %0, [%1+0x58]\n\t"
++ "amfar2 %0, $CB_CTL\n\t"
++ "swi %0, [%1+0x5c]\n\t"
++ "amfar2 %0, $CBB0\n\t"
++ "swi %0, [%1+0x60]\n\t"
++ "amfar2 %0, $CBB1\n\t"
++ "swi %0, [%1+0x64]\n\t"
++ "amfar2 %0, $CBB2\n\t"
++ "swi %0, [%1+0x68]\n\t"
++ "amfar2 %0, $CBB3\n\t"
++ "swi %0, [%1+0x6c]\n\t"
++ "amfar2 %0, $CBE0\n\t"
++ "swi %0, [%1+0x70]\n\t"
++ "amfar2 %0, $CBE1\n\t"
++ "swi %0, [%1+0x74]\n\t"
++ "amfar2 %0, $CBE2\n\t"
++ "swi %0, [%1+0x78]\n\t"
++ "amfar2 %0, $CBE3\n\t"
++ "swi %0, [%1+0x7c]\n\t":"=&r" (tmp)
++ :"r"(&tsk->thread.audio), "i"(MSC_CFG_mskAUDIO),
++ "i"(MSC_CFG_offAUDIO)
++ :"memory");
++ disable_audio();
++}
++
++void audioload(struct audio_struct *audioregs)
++{
++ unsigned int tmp;
++ enable_audio();
++ asm volatile ("mfsr %0, $MSC_CFG\n\t"
++ "andi %0, %0, %2\n\t"
++ "srli %0, %0, %3\n\t"
++ "slti %0, %0, 2\n\t"
++ "bnez %0, 98f\n\t"
++ "lwi %0, [%1+0x0]\n\t"
++ "amtar %0, $D0.L24\n\t"
++ "lwi %0, [%1+0x4]\n\t"
++ "amtar %0, $D1.L24\n\t"
++ "98:\n\t"
++ "lwi %0, [%1+0x8]\n\t"
++ "amtar %0, $I0\n\t"
++ "lwi %0, [%1+0xc]\n\t"
++ "amtar %0, $I1\n\t"
++ "lwi %0, [%1+0x10]\n\t"
++ "amtar %0, $I2\n\t"
++ "lwi %0, [%1+0x14]\n\t"
++ "amtar %0, $I3\n\t"
++ "lwi %0, [%1+0x18]\n\t"
++ "amtar %0, $I4\n\t"
++ "lwi %0, [%1+0x1c]\n\t"
++ "amtar %0, $I5\n\t"
++ "lwi %0, [%1+0x20]\n\t"
++ "amtar %0, $I6\n\t"
++ "lwi %0, [%1+0x24]\n\t"
++ "amtar %0, $I7\n\t"
++ "lwi %0, [%1+0x28]\n\t"
++ "amtar %0, $M1\n\t"
++ "lwi %0, [%1+0x2c]\n\t"
++ "amtar %0, $M2\n\t"
++ "lwi %0, [%1+0x30]\n\t"
++ "amtar %0, $M3\n\t"
++ "lwi %0, [%1+0x34]\n\t"
++ "amtar %0, $M5\n\t"
++ "lwi %0, [%1+0x38]\n\t"
++ "amtar %0, $M6\n\t"
++ "lwi %0, [%1+0x3c]\n\t"
++ "amtar %0, $M7\n\t"
++ "lwi %0, [%1+0x40]\n\t"
++ "amtar %0, $MOD\n\t"
++ "lwi %0, [%1+0x44]\n\t"
++ "amtar %0, $LB\n\t"
++ "lwi %0, [%1+0x48]\n\t"
++ "amtar %0, $LE\n\t"
++ "lwi %0, [%1+0x4c]\n\t"
++ "amtar %0, $LC\n\t"
++ "lwi %0, [%1+0x50]\n\t"
++ "amtar %0, $ADM_VBASE\n\t"
++ "lwi %0, [%1+0x54]\n\t"
++ "amtar %0, $SHFT_CTL0\n\t"
++ "lwi %0, [%1+0x58]\n\t"
++ "amtar %0, $SHFT_CTL1\n\t"
++ "lwi %0, [%1+0x5c]\n\t"
++ "amtar2 %0, $CB_CTL\n\t"
++ "lwi %0, [%1+0x60]\n\t"
++ "amtar2 %0, $CBB0\n\t"
++ "lwi %0, [%1+0x64]\n\t"
++ "amtar2 %0, $CBB1\n\t"
++ "lwi %0, [%1+0x68]\n\t"
++ "amtar2 %0, $CBB2\n\t"
++ "lwi %0, [%1+0x6c]\n\t"
++ "amtar2 %0, $CBB3\n\t"
++ "lwi %0, [%1+0x70]\n\t"
++ "amtar2 %0, $CBE0\n\t"
++ "lwi %0, [%1+0x74]\n\t"
++ "amtar2 %0, $CBE1\n\t"
++ "lwi %0, [%1+0x78]\n\t"
++ "amtar2 %0, $CBE2\n\t"
++ "lwi %0, [%1+0x7c]\n\t"
++ "amtar2 %0, $CBE3\n\t":"=&r" (tmp)
++ :"r"(audioregs), "i"(MSC_CFG_mskAUDIO),
++ "i"(MSC_CFG_offAUDIO));
++ disable_audio();
++}
++
++void do_audio_context_switch(unsigned long error_code, struct pt_regs *regs)
++{
++ struct task_struct *tsk = current;
++
++ if (!user_mode(regs))
++ die("Audio used in kernel", regs, error_code);
++
++ /* Enable to use audio. */
++ grab_audio(regs);
++#ifndef CONFIG_UNLAZY_AUDIO //Lazy audio is used
++ if (last_task_used_audio == current)
++ return;
++
++ if (last_task_used_audio != NULL)
++ /* Other processes audio state, save away */
++ save_audio(last_task_used_audio);
++ last_task_used_audio = current;
++#endif
++ if (test_tsk_thread_flag(tsk, TIF_USEDAUDIO)) {
++ audioload(&current->thread.audio);
++ } else {
++ /* First time audio user. */
++ audioload(&init_audioregs);
++ set_tsk_thread_flag(tsk, TIF_USEDAUDIO);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/audio.h linux-3.4.110/arch/nds32/kernel/audio.h
+--- linux-3.4.110.orig/arch/nds32/kernel/audio.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/audio.h 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,2 @@
++
++#define NAN32 0x0UL
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/bios32.c linux-3.4.110/arch/nds32/kernel/bios32.c
+--- linux-3.4.110.orig/arch/nds32/kernel/bios32.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/bios32.c 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,711 @@
++/*
++ * linux/arch/nds32/kernel/bios32.c
++ *
++ * PCI bios-type initialisation for PCI machines
++ *
++ * Bits taken from various places.
++ *
++ * Copyright (C) 2009 Andes Technology Corporation
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++
++#include <asm/io.h>
++#include <asm/mach-types.h>
++#include <asm/mach/pci.h>
++
++static int debug_pci;
++static int use_firmware;
++
++/*
++ * We can't use pci_find_device() here since we are
++ * called from interrupt context.
++ */
++static void pcibios_bus_report_status(struct pci_bus *bus, u_int status_mask,
++ int warn)
++{
++ struct pci_dev *dev;
++
++ list_for_each_entry(dev, &bus->devices, bus_list) {
++ u16 status;
++
++ /*
++ * ignore host bridge - we handle
++ * that separately
++ */
++ if (dev->bus->number == 0 && dev->devfn == 0)
++ continue;
++
++ pci_read_config_word(dev, PCI_STATUS, &status);
++ if (status == 0xffff)
++ continue;
++
++ if ((status & status_mask) == 0)
++ continue;
++
++ /* clear the status errors */
++ pci_write_config_word(dev, PCI_STATUS, status & status_mask);
++
++ if (warn)
++ printk("(%s: %04X) ", pci_name(dev), status);
++ }
++
++ list_for_each_entry(dev, &bus->devices, bus_list)
++ if (dev->subordinate)
++ pcibios_bus_report_status(dev->subordinate, status_mask, warn);
++}
++
++void pcibios_report_status(u_int status_mask, int warn)
++{
++ struct list_head *l;
++
++ list_for_each(l, &pci_root_buses) {
++ struct pci_bus *bus = pci_bus_b(l);
++
++ pcibios_bus_report_status(bus, status_mask, warn);
++ }
++}
++
++/*
++ * We don't use this to fix the device, but initialisation of it.
++ * It's not the correct use for this, but it works.
++ * Note that the arbiter/ISA bridge appears to be buggy, specifically in
++ * the following area:
++ * 1. park on CPU
++ * 2. ISA bridge ping-pong
++ * 3. ISA bridge master handling of target RETRY
++ *
++ * Bug 3 is responsible for the sound DMA grinding to a halt. We now
++ * live with bug 2.
++ */
++static void __devinit pci_fixup_83c553(struct pci_dev *dev)
++{
++ /*
++ * Set memory region to start at address 0, and enable IO
++ */
++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
++ PCI_BASE_ADDRESS_SPACE_MEMORY);
++ pci_write_config_word(dev, PCI_COMMAND, PCI_COMMAND_IO);
++
++ dev->resource[0].end -= dev->resource[0].start;
++ dev->resource[0].start = 0;
++
++ /*
++ * All memory requests from ISA to be channelled to PCI
++ */
++ pci_write_config_byte(dev, 0x48, 0xff);
++
++ /*
++ * Enable ping-pong on bus master to ISA bridge transactions.
++ * This improves the sound DMA substantially. The fixed
++ * priority arbiter also helps (see below).
++ */
++ pci_write_config_byte(dev, 0x42, 0x01);
++
++ /*
++ * Enable PCI retry
++ */
++ pci_write_config_byte(dev, 0x40, 0x22);
++
++ /*
++ * We used to set the arbiter to "park on last master" (bit
++ * 1 set), but unfortunately the CyberPro does not park the
++ * bus. We must therefore park on CPU. Unfortunately, this
++ * may trigger yet another bug in the 553.
++ */
++ pci_write_config_byte(dev, 0x83, 0x02);
++
++ /*
++ * Make the ISA DMA request lowest priority, and disable
++ * rotating priorities completely.
++ */
++ pci_write_config_byte(dev, 0x80, 0x11);
++ pci_write_config_byte(dev, 0x81, 0x00);
++
++ /*
++ * Route INTA input to IRQ 11, and set IRQ11 to be level
++ * sensitive.
++ */
++ pci_write_config_word(dev, 0x44, 0xb000);
++ outb(0x08, 0x4d1);
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_83C553,
++ pci_fixup_83c553);
++
++static void __devinit pci_fixup_unassign(struct pci_dev *dev)
++{
++ dev->resource[0].end -= dev->resource[0].start;
++ dev->resource[0].start = 0;
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_WINBOND2, PCI_DEVICE_ID_WINBOND2_89C940F,
++ pci_fixup_unassign);
++
++/*
++ * Prevent the PCI layer from seeing the resources allocated to this device
++ * if it is the host bridge by marking it as such. These resources are of
++ * no consequence to the PCI layer (they are handled elsewhere).
++ */
++static void __devinit pci_fixup_dec21285(struct pci_dev *dev)
++{
++ int i;
++
++ if (dev->devfn == 0) {
++ dev->class &= 0xff;
++ dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
++ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
++ dev->resource[i].start = 0;
++ dev->resource[i].end = 0;
++ dev->resource[i].flags = 0;
++ }
++ }
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285,
++ pci_fixup_dec21285);
++
++/*
++ * PCI IDE controllers use non-standard I/O port decoding, respect it.
++ */
++static void __devinit pci_fixup_ide_bases(struct pci_dev *dev)
++{
++ struct resource *r;
++ int i;
++
++ if ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
++ return;
++
++ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
++ r = dev->resource + i;
++ if ((r->start & ~0x80) == 0x374) {
++ r->start |= 2;
++ r->end = r->start;
++ }
++ }
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, pci_fixup_ide_bases);
++
++/*
++ * Put the DEC21142 to sleep
++ */
++static void __devinit pci_fixup_dec21142(struct pci_dev *dev)
++{
++ pci_write_config_dword(dev, 0x40, 0x80000000);
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21142,
++ pci_fixup_dec21142);
++
++/*
++ * The CY82C693 needs some rather major fixups to ensure that it does
++ * the right thing. Idea from the Alpha people, with a few additions.
++ *
++ * We ensure that the IDE base registers are set to 1f0/3f4 for the
++ * primary bus, and 170/374 for the secondary bus. Also, hide them
++ * from the PCI subsystem view as well so we won't try to perform
++ * our own auto-configuration on them.
++ *
++ * In addition, we ensure that the PCI IDE interrupts are routed to
++ * IRQ 14 and IRQ 15 respectively.
++ *
++ * The above gets us to a point where the IDE on this device is
++ * functional. However, The CY82C693U _does not work_ in bus
++ * master mode without locking the PCI bus solid.
++ */
++static void __devinit pci_fixup_cy82c693(struct pci_dev *dev)
++{
++ if ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
++ u32 base0, base1;
++
++ if (dev->class & 0x80) { /* primary */
++ base0 = 0x1f0;
++ base1 = 0x3f4;
++ } else { /* secondary */
++ base0 = 0x170;
++ base1 = 0x374;
++ }
++
++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
++ base0 | PCI_BASE_ADDRESS_SPACE_IO);
++ pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
++ base1 | PCI_BASE_ADDRESS_SPACE_IO);
++
++ dev->resource[0].start = 0;
++ dev->resource[0].end = 0;
++ dev->resource[0].flags = 0;
++
++ dev->resource[1].start = 0;
++ dev->resource[1].end = 0;
++ dev->resource[1].flags = 0;
++ } else if (PCI_FUNC(dev->devfn) == 0) {
++ /*
++ * Setup IDE IRQ routing.
++ */
++ pci_write_config_byte(dev, 0x4b, 14);
++ pci_write_config_byte(dev, 0x4c, 15);
++
++ /*
++ * Disable FREQACK handshake, enable USB.
++ */
++ pci_write_config_byte(dev, 0x4d, 0x41);
++
++ /*
++ * Enable PCI retry, and PCI post-write buffer.
++ */
++ pci_write_config_byte(dev, 0x44, 0x17);
++
++ /*
++ * Enable ISA master and DMA post write buffering.
++ */
++ pci_write_config_byte(dev, 0x45, 0x03);
++ }
++}
++
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693,
++ pci_fixup_cy82c693);
++
++void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
++{
++ if (debug_pci)
++ printk("PCI: Assigning IRQ %02d to %s\n", irq, pci_name(dev));
++ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
++}
++
++/*
++ * If the bus contains any of these devices, then we must not turn on
++ * parity checking of any kind. Currently this is CyberPro 20x0 only.
++ */
++static inline int pdev_bad_for_parity(struct pci_dev *dev)
++{
++ return (dev->vendor == PCI_VENDOR_ID_INTERG &&
++ (dev->device == PCI_DEVICE_ID_INTERG_2000 ||
++ dev->device == PCI_DEVICE_ID_INTERG_2010));
++}
++
++/*
++ * Adjust the device resources from bus-centric to Linux-centric.
++ */
++static void __devinit
++pdev_fixup_device_resources(struct pci_sys_data *root, struct pci_dev *dev)
++{
++ resource_size_t offset;
++ int i;
++
++ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
++ if (dev->resource[i].start == 0)
++ continue;
++ if (dev->resource[i].flags & IORESOURCE_MEM)
++ offset = root->mem_offset;
++ else
++ offset = root->io_offset;
++
++ dev->resource[i].start += offset;
++ dev->resource[i].end += offset;
++ }
++}
++
++static void __devinit
++pbus_assign_bus_resources(struct pci_bus *bus, struct pci_sys_data *root)
++{
++ struct pci_dev *dev = bus->self;
++ int i;
++
++ if (!dev) {
++ /*
++ * Assign root bus resources.
++ */
++ for (i = 0; i < 3; i++)
++ bus->resource[i] = root->resource[i];
++ }
++}
++
++/*
++ * pcibios_fixup_bus - Called after each bus is probed,
++ * but before its children are examined.
++ */
++void __devinit pcibios_fixup_bus(struct pci_bus *bus)
++{
++ struct pci_sys_data *root = bus->sysdata;
++ struct pci_dev *dev;
++ u16 features =
++ PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_FAST_BACK;
++
++ pbus_assign_bus_resources(bus, root);
++
++ /*
++ * Walk the devices on this bus, working out what we can
++ * and can't support.
++ */
++ list_for_each_entry(dev, &bus->devices, bus_list) {
++ u16 status;
++
++ pdev_fixup_device_resources(root, dev);
++
++ pci_read_config_word(dev, PCI_STATUS, &status);
++
++ /*
++ * If any device on this bus does not support fast back
++ * to back transfers, then the bus as a whole is not able
++ * to support them. Having fast back to back transfers
++ * on saves us one PCI cycle per transaction.
++ */
++ if (!(status & PCI_STATUS_FAST_BACK))
++ features &= ~PCI_COMMAND_FAST_BACK;
++
++ if (pdev_bad_for_parity(dev))
++ features &= ~(PCI_COMMAND_SERR | PCI_COMMAND_PARITY);
++
++ switch (dev->class >> 8) {
++#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
++ case PCI_CLASS_BRIDGE_ISA:
++ case PCI_CLASS_BRIDGE_EISA:
++ /*
++ * If this device is an ISA bridge, set isa_bridge
++ * to point at this device. We will then go looking
++ * for things like keyboard, etc.
++ */
++ isa_bridge = dev;
++ break;
++#endif
++ case PCI_CLASS_BRIDGE_PCI:
++ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
++ status |=
++ PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_MASTER_ABORT;
++ status &=
++ ~(PCI_BRIDGE_CTL_BUS_RESET |
++ PCI_BRIDGE_CTL_FAST_BACK);
++ pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
++ break;
++
++ case PCI_CLASS_BRIDGE_CARDBUS:
++ pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
++ &status);
++ status |=
++ PCI_CB_BRIDGE_CTL_PARITY |
++ PCI_CB_BRIDGE_CTL_MASTER_ABORT;
++ pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
++ status);
++ break;
++ }
++ }
++
++ /*
++ * Now walk the devices again, this time setting them up.
++ */
++ list_for_each_entry(dev, &bus->devices, bus_list) {
++ u16 cmd;
++
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ cmd |= features;
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++
++ pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
++ L1_CACHE_BYTES >> 2);
++ }
++
++ /*
++ * Propagate the flags to the PCI bridge.
++ */
++ if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
++ if (features & PCI_COMMAND_FAST_BACK)
++ bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
++ if (features & PCI_COMMAND_PARITY)
++ bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
++ }
++
++ /*
++ * Report what we did for this bus
++ */
++ printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
++ bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
++}
++
++/*
++ * Convert from Linux-centric to bus-centric addresses for bridge devices.
++ */
++void
++pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
++ struct resource *res)
++{
++ struct pci_sys_data *root = dev->sysdata;
++ unsigned long offset = 0;
++
++ if (res->flags & IORESOURCE_IO)
++ offset = root->io_offset;
++ if (res->flags & IORESOURCE_MEM)
++ offset = root->mem_offset;
++
++ region->start = res->start - offset;
++ region->end = res->end - offset;
++}
++
++void __devinit
++pcibios_bus_to_resource(struct pci_dev *dev, struct resource *res,
++ struct pci_bus_region *region)
++{
++ struct pci_sys_data *root = dev->sysdata;
++ unsigned long offset = 0;
++
++ if (res->flags & IORESOURCE_IO)
++ offset = root->io_offset;
++ if (res->flags & IORESOURCE_MEM)
++ offset = root->mem_offset;
++
++ res->start = region->start + offset;
++ res->end = region->end + offset;
++}
++
++#ifdef CONFIG_HOTPLUG
++EXPORT_SYMBOL(pcibios_fixup_bus);
++EXPORT_SYMBOL(pcibios_resource_to_bus);
++EXPORT_SYMBOL(pcibios_bus_to_resource);
++#endif
++
++/*
++ * This is the standard PCI-PCI bridge swizzling algorithm:
++ *
++ * Dev: 0 1 2 3
++ * A A B C D
++ * B B C D A
++ * C C D A B
++ * D D A B C
++ * ^^^^^^^^^^ irq pin on bridge
++ */
++u8 __devinit pci_std_swizzle(struct pci_dev *dev, u8 * pinp)
++{
++ int pin = *pinp - 1;
++
++ while (dev->bus->self) {
++ pin = (pin + PCI_SLOT(dev->devfn)) & 3;
++ /*
++ * move up the chain of bridges,
++ * swizzling as we go.
++ */
++ dev = dev->bus->self;
++ }
++ *pinp = pin + 1;
++
++ return PCI_SLOT(dev->devfn);
++}
++
++/*
++ * Swizzle the device pin each time we cross a bridge.
++ * This might update pin and returns the slot number.
++ */
++static u8 __devinit pcibios_swizzle(struct pci_dev *dev, u8 * pin)
++{
++ struct pci_sys_data *sys = dev->sysdata;
++ int slot = 0, oldpin = *pin;
++
++ if (sys->swizzle)
++ slot = sys->swizzle(dev, pin);
++
++ if (debug_pci)
++ printk("PCI: %s swizzling pin %d => pin %d slot %d\n",
++ pci_name(dev), oldpin, *pin, slot);
++
++ return slot;
++}
++
++/*
++ * Map a slot/pin to an IRQ.
++ */
++static int pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ struct pci_sys_data *sys = dev->sysdata;
++ int irq = -1;
++
++ if (sys->map_irq)
++ irq = sys->map_irq(dev, slot, pin);
++
++ if (debug_pci)
++ printk("PCI: %s mapping slot %d pin %d => irq %d\n",
++ pci_name(dev), slot, pin, irq);
++
++ return irq;
++}
++
++static void __init pcibios_init_hw(struct hw_pci *hw)
++{
++ struct pci_sys_data *sys = NULL;
++ int ret;
++ int nr, busnr;
++
++ for (nr = busnr = 0; nr < hw->nr_controllers; nr++) {
++ sys = kmalloc(sizeof(struct pci_sys_data), GFP_KERNEL);
++ if (!sys)
++ panic("PCI: unable to allocate sys data!");
++
++ memset(sys, 0, sizeof(struct pci_sys_data));
++
++ sys->hw = hw;
++ sys->busnr = busnr;
++ sys->swizzle = hw->swizzle;
++ sys->map_irq = hw->map_irq;
++ sys->resource[0] = &ioport_resource;
++ sys->resource[1] = &iomem_resource;
++
++ ret = hw->setup(nr, sys);
++
++ if (ret > 0) {
++ sys->bus = hw->scan(nr, sys);
++
++ if (!sys->bus)
++ panic("PCI: unable to scan bus!");
++
++ busnr = sys->bus->subordinate + 1;
++
++ list_add(&sys->node, &hw->buses);
++ } else {
++ kfree(sys);
++ if (ret < 0)
++ break;
++ }
++ }
++}
++
++void __init pci_common_init(struct hw_pci *hw)
++{
++ struct pci_sys_data *sys;
++
++ INIT_LIST_HEAD(&hw->buses);
++
++ if (hw->preinit)
++ hw->preinit();
++ pcibios_init_hw(hw);
++ if (hw->postinit)
++ hw->postinit();
++
++ pci_fixup_irqs(pcibios_swizzle, pcibios_map_irq);
++
++ list_for_each_entry(sys, &hw->buses, node) {
++ struct pci_bus *bus = sys->bus;
++
++ if (!use_firmware) {
++ /*
++ * Size the bridge windows.
++ */
++ pci_bus_size_bridges(bus);
++
++ /*
++ * Assign resources.
++ */
++ pci_bus_assign_resources(bus);
++ }
++
++ /*
++ * Tell drivers about devices found.
++ */
++ pci_bus_add_devices(bus);
++ }
++}
++
++char *__devinit pcibios_setup(char *str)
++{
++ if (!strcmp(str, "debug")) {
++ debug_pci = 1;
++ return NULL;
++ } else if (!strcmp(str, "firmware")) {
++ use_firmware = 1;
++ return NULL;
++ }
++ return str;
++}
++
++/*
++ * From arch/i386/kernel/pci-i386.c:
++ *
++ * We need to avoid collisions with `mirrored' VGA ports
++ * and other strange ISA hardware, so we always want the
++ * addresses to be allocated in the 0x000-0x0ff region
++ * modulo 0x400.
++ *
++ * Why? Because some silly external IO cards only decode
++ * the low 10 bits of the IO address. The 0x00-0xff region
++ * is reserved for motherboard devices that decode all 16
++ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
++ * but we want to try to avoid allocating at 0x2900-0x2bff
++ * which might be mirrored at 0x0100-0x03ff..
++ */
++void pcibios_align_resource(void *data, struct resource *res,
++ resource_size_t size, resource_size_t align)
++{
++ resource_size_t start = res->start;
++
++ if (res->flags & IORESOURCE_IO && start & 0x300)
++ start = (start + 0x3ff) & ~0x3ff;
++
++ res->start = (start + align - 1) & ~(align - 1);
++}
++
++/**
++ * pcibios_enable_device - Enable I/O and memory.
++ * @dev: PCI device to be enabled
++ */
++int pcibios_enable_device(struct pci_dev *dev, int mask)
++{
++ u16 cmd, old_cmd;
++ int idx;
++ struct resource *r;
++
++ pci_read_config_word(dev, PCI_COMMAND, &cmd);
++ old_cmd = cmd;
++ for (idx = 0; idx < 6; idx++) {
++ /* Only set up the requested stuff */
++ if (!(mask & (1 << idx)))
++ continue;
++
++ r = dev->resource + idx;
++ if (!r->start && r->end) {
++ printk(KERN_ERR "PCI: Device %s not available because"
++ " of resource collisions\n", pci_name(dev));
++ return -EINVAL;
++ }
++ if (r->flags & IORESOURCE_IO)
++ cmd |= PCI_COMMAND_IO;
++ if (r->flags & IORESOURCE_MEM)
++ cmd |= PCI_COMMAND_MEMORY;
++ }
++
++ /*
++ * Bridges (eg, cardbus bridges) need to be fully enabled
++ */
++ if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
++ cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
++
++ if (cmd != old_cmd) {
++ printk("PCI: enabling device %s (%04x -> %04x)\n",
++ pci_name(dev), old_cmd, cmd);
++ pci_write_config_word(dev, PCI_COMMAND, cmd);
++ }
++ return 0;
++}
++
++int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
++ enum pci_mmap_state mmap_state, int write_combine)
++{
++ struct pci_sys_data *root = dev->sysdata;
++ unsigned long phys;
++
++ if (mmap_state == pci_mmap_io) {
++ return -EINVAL;
++ } else {
++ phys = vma->vm_pgoff + (root->mem_offset >> PAGE_SHIFT);
++ }
++
++ /*
++ * Mark this as IO
++ */
++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++
++ if (remap_pfn_range(vma, vma->vm_start, phys,
++ vma->vm_end - vma->vm_start, vma->vm_page_prot))
++ return -EAGAIN;
++
++ return 0;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/calls.S linux-3.4.110/arch/nds32/kernel/calls.S
+--- linux-3.4.110.orig/arch/nds32/kernel/calls.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/calls.S 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,400 @@
++/*
++ * linux/arch/nds32/kernel/calls.S
++ *
++ * Copyright (C) 1995-2004 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This file is included twice in entry-common.S
++ */
++
++/* 0 */ CALL(sys_restart_syscall)
++ CALL(sys_exit)
++ CALL(sys_fork_wrapper)
++ CALL(sys_read)
++ CALL(sys_write)
++/* 5 */ CALL(sys_open)
++ CALL(sys_close)
++ CALL(sys_waitpid)
++ CALL(sys_creat)
++ CALL(sys_link)
++/* 10 */ CALL(sys_unlink)
++ CALL(sys_execve_wrapper)
++ CALL(sys_chdir)
++ CALL(sys_time) /* used by libc4 */
++ CALL(sys_mknod)
++/* 15 */ CALL(sys_chmod)
++ CALL(sys_lchown16)
++ CALL(sys_ni_syscall) /* was sys_break */
++ CALL(sys_ni_syscall) /* was sys_stat */
++ CALL(sys_lseek)
++/* 20 */ CALL(sys_getpid)
++ CALL(sys_mount)
++ CALL(sys_oldumount) /* used by libc4 */
++ CALL(sys_setuid16)
++ CALL(sys_getuid16)
++/* 25 */ CALL(sys_stime)
++ CALL(sys_ptrace)
++ CALL(sys_alarm) /* used by libc4 */
++ CALL(sys_ni_syscall) /* was sys_fstat */
++ CALL(sys_pause)
++/* 30 */ CALL(sys_utime) /* used by libc4 */
++ CALL(sys_ni_syscall) /* was sys_stty */
++ CALL(sys_ni_syscall) /* was sys_getty */
++ CALL(sys_access)
++ CALL(sys_nice)
++/* 35 */ CALL(sys_ni_syscall) /* was sys_ftime */
++ CALL(sys_sync)
++ CALL(sys_kill)
++ CALL(sys_rename)
++ CALL(sys_mkdir)
++/* 40 */ CALL(sys_rmdir)
++ CALL(sys_dup)
++ CALL(sys_pipe)
++ CALL(sys_times)
++ CALL(sys_ni_syscall) /* was sys_prof */
++/* 45 */ CALL(sys_brk)
++ CALL(sys_setgid16)
++ CALL(sys_getgid16)
++ CALL(sys_ni_syscall) /* was sys_signal */
++ CALL(sys_geteuid16)
++/* 50 */ CALL(sys_getegid16)
++ CALL(sys_acct)
++ CALL(sys_umount)
++ CALL(sys_ni_syscall) /* was sys_lock */
++ CALL(sys_ioctl)
++/* 55 */ CALL(sys_fcntl)
++ CALL(sys_ni_syscall) /* was sys_mpx */
++ CALL(sys_setpgid)
++ CALL(sys_ni_syscall) /* was sys_ulimit */
++ CALL(sys_cacheflush) /* was sys_olduname */
++/* 60 */ CALL(sys_umask)
++ CALL(sys_chroot)
++ CALL(sys_ustat)
++ CALL(sys_dup2)
++ CALL(sys_getppid)
++/* 65 */ CALL(sys_getpgrp)
++ CALL(sys_setsid)
++ CALL(sys_sigaction)
++ CALL(sys_ni_syscall) /* was sys_sgetmask */
++ CALL(sys_ni_syscall) /* was sys_ssetmask */
++/* 70 */ CALL(sys_setreuid16)
++ CALL(sys_setregid16)
++ CALL(sys_sigsuspend_wrapper)
++ CALL(sys_sigpending)
++ CALL(sys_sethostname)
++/* 75 */ CALL(sys_setrlimit)
++ CALL(sys_old_getrlimit) /* used by libc4 */
++ CALL(sys_getrusage)
++ CALL(sys_gettimeofday)
++ CALL(sys_settimeofday)
++/* 80 */ CALL(sys_getgroups16)
++ CALL(sys_setgroups16)
++ CALL(old_select) /* used by libc4 */
++ CALL(sys_symlink)
++ CALL(sys_ni_syscall) /* was sys_lstat */
++/* 85 */ CALL(sys_readlink)
++ CALL(sys_uselib)
++ CALL(sys_swapon)
++ CALL(sys_reboot)
++ CALL(sys_old_readdir) /* used by libc4 */
++/* 90 */ CALL(sys_old_mmap) /* used by libc4 */
++ CALL(sys_munmap)
++ CALL(sys_truncate)
++ CALL(sys_ftruncate)
++ CALL(sys_fchmod)
++/* 95 */ CALL(sys_fchown16)
++ CALL(sys_getpriority)
++ CALL(sys_setpriority)
++ CALL(sys_ni_syscall) /* was sys_profil */
++ CALL(sys_statfs)
++/* 100 */ CALL(sys_fstatfs)
++ CALL(sys_ni_syscall)
++ CALL(sys_socketcall)
++ CALL(sys_syslog)
++ CALL(sys_setitimer)
++/* 105 */ CALL(sys_getitimer)
++ CALL(sys_newstat)
++ CALL(sys_newlstat)
++ CALL(sys_newfstat)
++ CALL(sys_ni_syscall) /* was sys_uname */
++/* 110 */ CALL(sys_ni_syscall) /* was sys_iopl */
++ CALL(sys_vhangup)
++ CALL(sys_ni_syscall)
++ CALL(sys_syscall) /* call a syscall */
++ CALL(sys_wait4)
++/* 115 */ CALL(sys_swapoff)
++ CALL(sys_sysinfo)
++ CALL(sys_ipc)
++ CALL(sys_fsync)
++ CALL(sys_sigreturn_wrapper)
++/* 120 */ CALL(sys_clone_wrapper)
++ CALL(sys_setdomainname)
++ CALL(sys_newuname)
++ CALL(sys_ni_syscall)
++ CALL(sys_adjtimex)
++/* 125 */ CALL(sys_mprotect)
++ CALL(sys_sigprocmask)
++ CALL(sys_ni_syscall) /* was sys_create_module */
++ CALL(sys_init_module)
++ CALL(sys_delete_module)
++/* 130 */ CALL(sys_ni_syscall) /* was sys_get_kernel_syms */
++ CALL(sys_quotactl)
++ CALL(sys_getpgid)
++ CALL(sys_fchdir)
++ CALL(sys_bdflush)
++/* 135 */ CALL(sys_sysfs)
++ CALL(sys_personality)
++ CALL(sys_ni_syscall) /* was _sys_afs_syscall */
++ CALL(sys_setfsuid16)
++ CALL(sys_setfsgid16)
++/* 140 */ CALL(sys_llseek)
++ CALL(sys_getdents)
++ CALL(sys_select)
++ CALL(sys_flock)
++ CALL(sys_msync)
++/* 145 */ CALL(sys_readv)
++ CALL(sys_writev)
++ CALL(sys_getsid)
++ CALL(sys_fdatasync)
++ CALL(sys_sysctl)
++/* 150 */ CALL(sys_mlock)
++ CALL(sys_munlock)
++ CALL(sys_mlockall)
++ CALL(sys_munlockall)
++ CALL(sys_sched_setparam)
++/* 155 */ CALL(sys_sched_getparam)
++ CALL(sys_sched_setscheduler)
++ CALL(sys_sched_getscheduler)
++ CALL(sys_sched_yield)
++ CALL(sys_sched_get_priority_max)
++/* 160 */ CALL(sys_sched_get_priority_min)
++ CALL(sys_sched_rr_get_interval)
++ CALL(sys_nanosleep)
++ CALL(sys_nds32_mremap)
++ CALL(sys_setresuid16)
++/* 165 */ CALL(sys_getresuid16)
++ CALL(sys_getpagesize)
++ CALL(sys_ni_syscall) /* was sys_query_module */
++ CALL(sys_poll)
++ CALL(sys_ni_syscall) /* was nfsservctl */
++/* 170 */ CALL(sys_setresgid16)
++ CALL(sys_getresgid16)
++ CALL(sys_prctl)
++ CALL(sys_rt_sigreturn_wrapper)
++ CALL(sys_rt_sigaction)
++/* 175 */ CALL(sys_rt_sigprocmask)
++ CALL(sys_rt_sigpending)
++ CALL(sys_rt_sigtimedwait)
++ CALL(sys_rt_sigqueueinfo)
++ CALL(sys_rt_sigsuspend_wrapper)
++/* 180 */ CALL(sys_pread64)
++ CALL(sys_pwrite64)
++ CALL(sys_chown16)
++ CALL(sys_getcwd)
++ CALL(sys_capget)
++/* 185 */ CALL(sys_capset)
++ CALL(sys_sigaltstack_wrapper)
++ CALL(sys_sendfile)
++ CALL(sys_ni_syscall)
++ CALL(sys_ni_syscall)
++/* 190 */ CALL(sys_vfork_wrapper)
++ CALL(sys_getrlimit)
++ CALL(sys_mmap2)
++ CALL(sys_truncate64)
++ CALL(sys_ftruncate64)
++/* 195 */ CALL(sys_stat64)
++ CALL(sys_lstat64)
++ CALL(sys_fstat64)
++ CALL(sys_lchown)
++ CALL(sys_getuid)
++/* 200 */ CALL(sys_getgid)
++ CALL(sys_geteuid)
++ CALL(sys_getegid)
++ CALL(sys_setreuid)
++ CALL(sys_setregid)
++/* 205 */ CALL(sys_getgroups)
++ CALL(sys_setgroups)
++ CALL(sys_fchown)
++ CALL(sys_setresuid)
++ CALL(sys_getresuid)
++/* 210 */ CALL(sys_setresgid)
++ CALL(sys_getresgid)
++ CALL(sys_chown)
++ CALL(sys_setuid)
++ CALL(sys_setgid)
++/* 215 */ CALL(sys_setfsuid)
++ CALL(sys_setfsgid)
++ CALL(sys_getdents64)
++ CALL(sys_pivot_root)
++ CALL(sys_mincore)
++/* 220 */ CALL(sys_madvise)
++ CALL(sys_fcntl64)
++ CALL(sys_ni_syscall) /* TUX */
++ CALL(sys_ni_syscall)
++ CALL(sys_gettid)
++/* 225 */ CALL(sys_readahead)
++ CALL(sys_setxattr)
++ CALL(sys_lsetxattr)
++ CALL(sys_fsetxattr)
++ CALL(sys_getxattr)
++/* 230 */ CALL(sys_lgetxattr)
++ CALL(sys_fgetxattr)
++ CALL(sys_listxattr)
++ CALL(sys_llistxattr)
++ CALL(sys_flistxattr)
++/* 235 */ CALL(sys_removexattr)
++ CALL(sys_lremovexattr)
++ CALL(sys_fremovexattr)
++ CALL(sys_tkill)
++ CALL(sys_sendfile64)
++/* 240 */ CALL(sys_futex_wrapper)
++ CALL(sys_sched_setaffinity)
++ CALL(sys_sched_getaffinity)
++ CALL(sys_io_setup)
++ CALL(sys_io_destroy)
++/* 245 */ CALL(sys_io_getevents)
++ CALL(sys_io_submit)
++ CALL(sys_io_cancel)
++ CALL(sys_exit_group)
++ CALL(sys_lookup_dcookie)
++/* 250 */ CALL(sys_epoll_create)
++ CALL(sys_epoll_ctl)
++ CALL(sys_epoll_wait)
++ CALL(sys_remap_file_pages)
++ CALL(sys_ni_syscall) /* sys_set_thread_area */
++/* 255 */ CALL(sys_ni_syscall) /* sys_get_thread_area */
++ CALL(sys_set_tid_address)
++ CALL(sys_timer_create)
++ CALL(sys_timer_settime)
++ CALL(sys_timer_gettime)
++/* 260 */ CALL(sys_timer_getoverrun)
++ CALL(sys_timer_delete)
++ CALL(sys_clock_settime)
++ CALL(sys_clock_gettime)
++ CALL(sys_clock_getres)
++/* 265 */ CALL(sys_clock_nanosleep)
++ CALL(sys_statfs64)
++ CALL(sys_fstatfs64)
++ CALL(sys_tgkill)
++ CALL(sys_utimes)
++/* 270 */ CALL(sys_fadvise64_64_wrapper)
++ CALL(sys_pciconfig_iobase)
++ CALL(sys_pciconfig_read)
++ CALL(sys_pciconfig_write)
++ CALL(sys_mq_open)
++/* 275 */ CALL(sys_mq_unlink)
++ CALL(sys_mq_timedsend)
++ CALL(sys_mq_timedreceive)
++ CALL(sys_mq_notify)
++ CALL(sys_mq_getsetattr)
++/* 280 */ CALL(sys_waitid)
++ CALL(sys_add_key)
++ CALL(sys_request_key)
++ CALL(sys_keyctl)
++ CALL(sys_ioprio_set)
++/* 285 */ CALL(sys_ioprio_get)
++ CALL(sys_inotify_init)
++ CALL(sys_inotify_add_watch)
++ CALL(sys_inotify_rm_watch)
++ CALL(sys_migrate_pages)
++/* 290 */ CALL(sys_openat)
++ CALL(sys_mkdirat)
++ CALL(sys_mknodat)
++ CALL(sys_fchownat)
++ CALL(sys_futimesat)
++/* 295 */ CALL(sys_fstatat64)
++ CALL(sys_unlinkat)
++ CALL(sys_renameat)
++ CALL(sys_linkat)
++ CALL(sys_symlinkat)
++/* 300 */ CALL(sys_readlinkat)
++ CALL(sys_fchmodat)
++ CALL(sys_faccessat)
++ CALL(sys_pselect6) /* sys_pselect6 */
++ CALL(sys_ppoll) /* sys_ppoll */
++/* 305 */ CALL(sys_unshare)
++ CALL(sys_set_robust_list)
++ CALL(sys_get_robust_list)
++ CALL(sys_splice)
++ CALL(sys_sync_file_range2)
++/* 310 */ CALL(sys_tee)
++ CALL(sys_vmsplice)
++ CALL(sys_move_pages)
++ CALL(sys_fadvise64)
++ CALL(sys_utimensat)
++/* 315 */ CALL(sys_signalfd)
++ CALL(sys_timerfd_create)
++ CALL(sys_eventfd)
++ CALL(sys_fallocate)
++ CALL(sys_timerfd_settime)
++/* 320 */ CALL(sys_timerfd_gettime)
++ CALL(sys_getcpu)
++ CALL(sys_signalfd4)
++ CALL(sys_eventfd2)
++ CALL(sys_epoll_create1)
++/* 325 */ CALL(sys_dup3)
++ CALL(sys_pipe2)
++ CALL(sys_inotify_init1)
++ CALL(sys_kexec_load)
++ CALL(sys_accept)
++/* 330 */ CALL(sys_bind)
++ CALL(sys_connect)
++ CALL(sys_getpeername)
++ CALL(sys_getsockname)
++ CALL(sys_getsockopt)
++/* 335 */ CALL(sys_listen)
++ CALL(sys_recv)
++ CALL(sys_recvfrom)
++ CALL(sys_recvmsg)
++ CALL(sys_send)
++/* 340 */ CALL(sys_sendmsg)
++ CALL(sys_sendto)
++ CALL(sys_setsockopt)
++ CALL(sys_shutdown)
++ CALL(sys_socket)
++/* 345 */ CALL(sys_socketpair)
++ CALL(sys_prlimit64)
++ CALL(sys_accept4)
++ CALL(sys_recvmmsg)
++ CALL(sys_sendmmsg)
++/* 350 */ CALL(sys_fanotify_init)
++ CALL(sys_fanotify_mark)
++ CALL(sys_msgget)
++ CALL(sys_msgctl)
++ CALL(sys_msgrcv)
++/* 355 */ CALL(sys_msgsnd)
++ CALL(sys_semget)
++ CALL(sys_semctl)
++ CALL(sys_semtimedop)
++ CALL(sys_semop)
++/* 360 */ CALL(sys_shmget)
++ CALL(sys_shmctl)
++ CALL(sys_shmat)
++ CALL(sys_shmdt)
++ CALL(sys_syncfs)
++/* 365 */ CALL(sys_setns)
++ CALL(sys_name_to_handle_at)
++ CALL(sys_open_by_handle_at)
++ CALL(sys_process_vm_readv)
++ CALL(sys_process_vm_writev)
++/* 370 */ CALL(sys_clock_adjtime)
++ CALL(sys_get_mempolicy)
++ CALL(sys_mbind)
++ CALL(sys_perf_event_open)
++ CALL(sys_preadv)
++/* 375 */ CALL(sys_pwritev)
++ CALL(sys_rt_tgsigqueueinfo)
++ CALL(sys_set_mempolicy)
++ CALL(sys_epoll_pwait)
++
++#ifndef syscalls_counted
++.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
++#define syscalls_counted
++#endif
++ .rept syscalls_padding
++ CALL(sys_ni_syscall)
++ .endr
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/early_printk.c linux-3.4.110/arch/nds32/kernel/early_printk.c
+--- linux-3.4.110.orig/arch/nds32/kernel/early_printk.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/early_printk.c 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,126 @@
++/*
++ * Earlyprintk support.
++ *
++ * Copyright (C) 2012 ARM Ltd.
++ * Author: Catalin Marinas <catalin.marinas@arm.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.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program. If not, see <http://www.gnu.org/licenses/>.
++ */
++#include <linux/kernel.h>
++#include <linux/console.h>
++#include <linux/init.h>
++#include <linux/string.h>
++#include <linux/mm.h>
++#include <linux/io.h>
++
++#include <linux/serial_reg.h>
++#include <asm/setup.h>
++
++extern void __iomem *early_io_map(phys_addr_t phys);
++static void __iomem *early_base;
++static void (*printch) (char ch);
++
++/*
++ * 8250/16550 (8-bit aligned registers) single character TX.
++ */
++static void uart8250_8bit_printch(char ch)
++{
++ while (!(readb(early_base + UART_LSR) & UART_LSR_THRE)) ;
++ writeb(ch, early_base + UART_TX);
++}
++
++/*
++ * 8250/16550 (32-bit aligned registers) single character TX.
++ */
++static void uart8250_32bit_printch(char ch)
++{
++ while (!(readl(early_base + (UART_LSR << 2)) & UART_LSR_THRE)) ;
++ writel(ch, early_base + (UART_TX << 2));
++}
++
++struct earlycon_match {
++ const char *name;
++ void (*printch) (char ch);
++};
++
++static const struct earlycon_match earlycon_match[] __initconst = {
++ {.name = "uart8250-8bit",.printch = uart8250_8bit_printch,},
++ {.name = "uart8250-32bit",.printch = uart8250_32bit_printch,},
++ {}
++};
++
++static void early_write(struct console *con, const char *s, unsigned n)
++{
++ while (n-- > 0) {
++ if (*s == '\n')
++ printch('\r');
++ printch(*s);
++ s++;
++ }
++}
++
++static struct console early_console_dev = {
++ .name = "earlycon",
++ .write = early_write,
++ .flags = CON_PRINTBUFFER | CON_BOOT,
++ .index = -1,
++};
++
++/*
++ * Parse earlyprintk=... parameter in the format:
++ *
++ * <name>[,<addr>][,<options>]
++ *
++ * and register the early console. It is assumed that the UART has been
++ * initialised by the bootloader already.
++ */
++static int __init setup_early_printk(char *buf)
++{
++ const struct earlycon_match *match = earlycon_match;
++ phys_addr_t paddr = 0;
++
++ if (!buf) {
++ pr_warning("No earlyprintk arguments passed.\n");
++ return 0;
++ }
++
++ while (match->name) {
++ size_t len = strlen(match->name);
++ if (!strncmp(buf, match->name, len)) {
++ buf += len;
++ break;
++ }
++ match++;
++ }
++ if (!match->name) {
++ pr_warning("Unknown earlyprintk arguments: %s\n", buf);
++ return 0;
++ }
++
++ /* I/O address */
++ if (!strncmp(buf, ",0x", 3)) {
++ char *e;
++ paddr = simple_strtoul(buf + 1, &e, 16);
++ buf = e;
++ }
++
++ if (paddr)
++ early_base = early_io_map(paddr);
++ printch = match->printch;
++ //early_console = &early_console_dev;
++ register_console(&early_console_dev);
++
++ return 0;
++}
++
++early_param("earlyprintk", setup_early_printk);
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/elfchk.c linux-3.4.110/arch/nds32/kernel/elfchk.c
+--- linux-3.4.110.orig/arch/nds32/kernel/elfchk.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/elfchk.c 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,190 @@
++#include <linux/module.h>
++#include <linux/kallsyms.h>
++#include <asm/hardware.h>
++#include <asm/uaccess.h>
++#include <asm/elf.h>
++#include <asm/fpu.h>
++#include <asm/audio.h>
++#include <linux/elf.h>
++#include <linux/proc_fs.h>
++
++#define ELF_CHECKING_OS
++#include "nds32-elf.h"
++
++extern struct proc_dir_entry *proc_dir_cpu;
++
++#ifdef CONFIG_ELFCHK_DEFAULT_ENABLE
++static int elf_check_en = 1;
++#else
++static int elf_check_en = 0;
++#endif
++
++struct reg_struct {
++
++ const char *name;
++ int idx;
++};
++
++static struct reg_struct regs[] = {
++
++ {"cpu_ver", CPU_SR_INDEX(0, 0, 0)},
++ {"icm_cfg", CPU_SR_INDEX(0, 1, 0)},
++ {"dcm_cfg", CPU_SR_INDEX(0, 2, 0)},
++ {"mmu_cfg", CPU_SR_INDEX(0, 3, 0)},
++ {"msc_cfg", CPU_SR_INDEX(0, 4, 0)},
++#ifdef CONFIG_FPU
++ {"fucop_exist", CPU_SR_INDEX(0, 5, 0)}
++#endif
++};
++
++#ifdef CONFIG_FPU
++static unsigned int read_fpu_fpcfg(void)
++{
++ unsigned int fpcfg = 0;
++
++ enable_fpu();
++ asm volatile ("fmfcfg %0\n\t":"=&r" (fpcfg));
++ disable_fpu();
++
++ return fpcfg;
++}
++#endif
++
++static unsigned int read_cpu_sr(unsigned int idx)
++{
++ switch (idx) {
++
++ case CPU_SR_INDEX(0, 0, 0):
++ return GET_CPU_VER();
++ case CPU_SR_INDEX(0, 1, 0):
++ return GET_ICM_CFG();
++ case CPU_SR_INDEX(0, 2, 0):
++ return GET_DCM_CFG();
++ case CPU_SR_INDEX(0, 3, 0):
++ return GET_MMU_CFG();
++ case CPU_SR_INDEX(0, 4, 0):
++ return GET_MSC_CFG();
++ case CPU_SR_INDEX(0, 5, 0):
++ return GET_FUCOP_EXIST();
++
++ default:
++ printk(KERN_ERR
++ "%s: invalid system register index (%d, %d, %d)\n",
++ __func__, (idx >> 7) & 0x7, (idx >> 3) & 0xf, idx & 0x7);
++
++ return SR_NOT_EXIST;
++ }
++}
++
++static unsigned int reg_read_callback(unsigned int idx)
++{
++ if (HW_IS_CPU(idx)) {
++
++ return read_cpu_sr(SR_INDEX(idx));
++ } else if (HW_IS_FPU(idx)) {
++
++#ifdef CONFIG_FPU
++ if (SR_FPU_FPCFG == SR_INDEX(idx))
++ return read_fpu_fpcfg();
++ else
++ return SR_NOT_EXIST;
++#endif
++ } else if (HW_IS_AUDIO(idx)) {
++
++ return SR_NOT_EXIST;
++ }
++
++ return SR_NOT_EXIST;
++}
++
++#define BUFLEN 1024
++
++int do_elf_check_arch(const struct elf32_hdr *hdr)
++{
++ static char msg_buf[BUFLEN];
++ unsigned int err;
++ int buf_status = 0;
++
++ if (!elf_check_en)
++ return 1;
++
++ err =
++ elf_check((void *)hdr, reg_read_callback, msg_buf, BUFLEN,
++ &buf_status);
++
++ if (err)
++ printk(KERN_WARNING "%s", msg_buf);
++
++ return !err;
++}
++
++static int proc_elf_check_read(char *page, char **start, off_t off, int count,
++ int *eof, void *data)
++{
++ return sprintf(page, "%d\n", elf_check_en);
++}
++
++#define INPUTLEN 10
++static int proc_elf_check_write(struct file *file, const char __user * buffer,
++ unsigned long count, void *data)
++{
++ unsigned long en;
++ char inbuf[INPUTLEN];
++
++ if (count > INPUTLEN - 1)
++ count = INPUTLEN - 1;
++
++ if (copy_from_user(inbuf, buffer, count))
++ return -EFAULT;
++
++ inbuf[count] = '\0';
++
++ if (!sscanf(inbuf, "%lu", &en) || en > 3)
++ return -EFAULT;
++
++ elf_check_en = en & 0x01;
++
++ return count;
++}
++
++static int proc_elf_check_read_reg(char *page, char **start,
++ off_t off, int count, int *eof, void *data)
++{
++ unsigned long val = read_cpu_sr(*(int *)data);
++
++ return sprintf(page, "0x%08lx\n", val);
++}
++
++int __init elf_check_init(void)
++{
++ static struct proc_dir_entry *res_elf_check;
++ int i;
++
++ if (!proc_dir_cpu) {
++ if (!(proc_dir_cpu = proc_mkdir("cpu", NULL)))
++ return -ENOMEM;
++ }
++
++ res_elf_check =
++ create_proc_entry("elf_core_checking", S_IWUSR | S_IRUGO,
++ proc_dir_cpu);
++ if (!res_elf_check)
++ return -ENOMEM;
++
++ res_elf_check->read_proc = proc_elf_check_read;
++ res_elf_check->write_proc = proc_elf_check_write;
++
++ for (i = 0; i < ARRAY_SIZE(regs); i++) {
++
++ if (!create_proc_read_entry(regs[i].name, S_IWUSR | S_IRUGO,
++ proc_dir_cpu,
++ proc_elf_check_read_reg,
++ &regs[i].idx))
++
++ return -ENOMEM;
++ }
++
++ return 0;
++}
++
++module_init(elf_check_init);
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ex-entry.S linux-3.4.110/arch/nds32/kernel/ex-entry.S
+--- linux-3.4.110.orig/arch/nds32/kernel/ex-entry.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/ex-entry.S 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,294 @@
++#include <linux/linkage.h>
++#include <asm/memory.h>
++#include <asm/nds32.h>
++#include <asm/assembler.h>
++#include <asm/errno.h>
++#include <asm/asm-offsets.h>
++#include <asm/page.h>
++
++ .macro push_zol
++#ifdef CONFIG_HWZOL
++ mfusr $r10, $LB
++ mfusr $r11, $LE
++ mfusr $r12, $LC
++#endif
++ .endm
++ .macro save_user_regs
++ /* $p1 is VA of percpu data */
++ sethi $p0, hi20(PAGE_OFFSET - PHYS_OFFSET)
++ add $p1, $p1, $p0
++
++ /* change to kernel stack */
++ mfsr $p0, $IPSW
++ andi $p0, $p0, #PSW_mskPOM
++ cmovz $sp, $r25, $p0
++
++ /* 8 byte aligned */
++ movi $r25, #~7
++ and $r25, $sp, $r25
++ smw.adm $sp, [$r25], $sp, #0x1
++ move $sp, $r25
++
++#if defined(CONFIG_FPU) || defined(CONFIG_AUDIO)
++ mfsr $r25, $FUCOP_CTL
++ push $r25
++ bclr $r25, $r25, #FUCOP_CTL_offCP0EN
++ mtsr $r25, $FUCOP_CTL
++#else
++ addi $sp, $sp, -4
++#endif
++ pushm $r28, $r30
++
++ /* zero fp if user mode*/
++ movi $r25, #0x0
++ cmovz $fp, $r25, $p0
++
++ lwi $r25, [$p1+#0x0]
++ pushm $r0, $r25
++#ifdef CONFIG_HWZOL
++ push_zol
++#endif
++ mfsr $r9, $P_P1
++ mfsr $r8, $P_P0
++ mfsr $r7, $P_IPC
++ mfsr $r6, $P_IPSW
++ mfsr $r18, $IPC
++ mfsr $r17, $IPSW
++ mfsr $r16, $PSW
++ pushm $r6, $r13
++ push $r0
++ lwi $p0, [$p1+#0x8]
++ push $p0
++ pushm $r16, $r18
++
++ andi $r19, $r16, #PSW_mskINTL
++ slti $r20, $r19, #4
++ bnez $r20, 1f
++ addi $r21, $r16, #-2
++ mtsr $r21, $PSW
++ isb
++1:
++ addi $sp, $sp, -S_OFF
++ .endm
++
++ .text
++
++/*
++ * Exception Vector
++ */
++exception_handlers:
++ .long unhandled_exceptions !Reset/NMI
++ .long unhandled_exceptions !TLB fill
++ .long do_page_fault !PTE not present
++ .long do_dispatch_tlb_misc !TLB misc
++ .long unhandled_exceptions !TLB VLPT
++ .long unhandled_exceptions !Machine Error
++ .long do_debug_trap !Debug related
++ .long do_dispatch_general !General exception
++ .long eh_syscall !Syscall
++ .long asm_do_IRQ !IRQ
++
++common_exception_handler:
++ save_user_regs
++ lwi $p0, [$p1+#0x4]
++ andi $p1, $p0, #0x78
++ bnez $p1, 1f
++ sethi $lp, hi20(ret_from_exception)
++ ori $lp, $lp, lo12(ret_from_exception)
++ sethi $p1, hi20(exception_handlers)
++ ori $p1, $p1, lo12(exception_handlers)
++ lw $p1, [$p1+$p0<<2]
++ move $r0, $p0
++ mfsr $r1, $EVA
++ mfsr $r2, $ITYPE
++ move $r3, $sp
++ mfsr $r4, $OIPC
++ /* enable gie if it is enabled in IPSW. */
++ mfsr $r21, $PSW
++ andi $r17, $r17, #0x1
++ or $r21, $r21, $r17
++ mtsr $r21, $PSW
++ dsb
++ jr $p1
++
++ /* syscall */
++1:
++ addi $p1, $p0, #-8
++ bnez $p1, 2f
++ sethi $lp, hi20(ret_from_exception)
++ ori $lp, $lp, lo12(ret_from_exception)
++ sethi $p1, hi20(exception_handlers)
++ ori $p1, $p1, lo12(exception_handlers)
++ lwi $p1, [$p1+#0x8<<2]
++ jr $p1
++
++ /* interrupt */
++2:
++#ifdef CONFIG_TRACE_IRQFLAGS
++ jal arch_trace_hardirqs_off
++#endif
++#if defined(CONFIG_EVIC) || defined(CONFIG_IVIC)
++ addi $r0, $p0, #-9
++#else
++# ifdef CONFIG_IVIC_INTC
++ jal get_IntSrc
++# else
++# error "Not configure Vector Interrupt Controller mode"
++# endif
++#endif
++ move $r1, $sp
++ sethi $lp, hi20(ret_from_intr)
++ ori $lp, $lp, lo12(ret_from_intr)
++ sethi $p0, hi20(exception_handlers)
++ ori $p0, $p0, lo12(exception_handlers)
++ lwi $p0, [$p0+#0x9<<2]
++ jr $p0
++
++ .macro EXCEPTION_VECTOR, num
++ .align 6
++ .ifc \num, 6
++ mfsr $p0, $EDM_CTL
++ andi $p0, $p0, EDM_CTL_mskV3_EDM_MODE
++ tnez $p0, 0x1a
++ .endif
++ /* $p1 is PA of percpu data */
++#ifdef CONFIG_CPU_N1213_43U1HA0
++ movi $p1, #0x0
++#else
++ mfsr $p1, $CORE_ID
++#endif
++ slli $p1, $p1, #0x9
++ li $p0, #(PHYS_OFFSET+0x6000)
++ or $p1, $p1, $p0
++
++ /*
++ * 0x0 saved $r25
++ * 0x4 vector number
++ * 0x8 user stack pointer
++ * 0xc kernel stack pointer
++ */
++ swi $r25, [$p1+0x0]
++ movi $p0, \num
++ swi $p0, [$p1+#0x4]
++ swi $sp, [$p1+#0x8]
++ lwi $r25, [$p1+#0xc]
++ sethi $p0, hi20(common_exception_handler)
++ ori $p0, $p0, lo12(common_exception_handler)
++ jral.ton $p0, $p0
++ .endm
++
++ .macro IPI_VECTOR, num
++ .align 6
++#ifdef CONFIG_CPU_N1213_43U1HA0
++ movi $p1, #0x0
++#else
++ mfsr $p1, $CORE_ID
++#endif
++ slli $p1, $p1, #0x9
++ li $p0, #(PHYS_OFFSET+0x6000)
++ or $p1, $p1, $p0
++
++ /*
++ * 0x10 indicator of CPU is initialized
++ * 0x14 CPU init function
++ */
++ swi $r25, [$p1+0x0]
++ movi $p0, \num
++ swi $p0, [$p1+#0x4]
++ swi $sp, [$p1+#0x8]
++ lwi $r25, [$p1+#0xc]
++ lwi $p0, [$p1+#0x10]
++ beqz $p0, 1f
++ sethi $p0, hi20(common_exception_handler)
++ ori $p0, $p0, lo12(common_exception_handler)
++ jral.ton $p0, $p0
++1:
++ lwi $p0, [$p1+#0x14]
++ jr $p0
++
++ .endm
++
++ .section ".text.init", #alloc, #execinstr
++ .global exception_vector
++exception_vector:
++ EXCEPTION_VECTOR 0
++ EXCEPTION_VECTOR 1
++ EXCEPTION_VECTOR 2
++ EXCEPTION_VECTOR 3
++ EXCEPTION_VECTOR 4
++ EXCEPTION_VECTOR 5
++ EXCEPTION_VECTOR 6
++ EXCEPTION_VECTOR 7
++ EXCEPTION_VECTOR 8
++#ifdef CONFIG_EVIC
++ EXCEPTION_VECTOR 9
++#else
++ IPI_VECTOR 9
++#endif
++ EXCEPTION_VECTOR 10
++ EXCEPTION_VECTOR 11
++ EXCEPTION_VECTOR 12
++ EXCEPTION_VECTOR 13
++ EXCEPTION_VECTOR 14
++ EXCEPTION_VECTOR 15
++ EXCEPTION_VECTOR 16
++ EXCEPTION_VECTOR 17
++ EXCEPTION_VECTOR 18
++ EXCEPTION_VECTOR 19
++ EXCEPTION_VECTOR 20
++ EXCEPTION_VECTOR 21
++ EXCEPTION_VECTOR 22
++ EXCEPTION_VECTOR 23
++ EXCEPTION_VECTOR 24
++ EXCEPTION_VECTOR 25
++ EXCEPTION_VECTOR 26
++ EXCEPTION_VECTOR 27
++ EXCEPTION_VECTOR 28
++ EXCEPTION_VECTOR 29
++ EXCEPTION_VECTOR 30
++ EXCEPTION_VECTOR 31
++ EXCEPTION_VECTOR 32
++ EXCEPTION_VECTOR 33
++ EXCEPTION_VECTOR 34
++ EXCEPTION_VECTOR 35
++ EXCEPTION_VECTOR 36
++ EXCEPTION_VECTOR 37
++ EXCEPTION_VECTOR 38
++ EXCEPTION_VECTOR 39
++ EXCEPTION_VECTOR 40
++#ifdef CONFIG_EVIC
++ IPI_VECTOR 41
++#else
++ EXCEPTION_VECTOR 41
++#endif
++ EXCEPTION_VECTOR 42
++ EXCEPTION_VECTOR 43
++ EXCEPTION_VECTOR 44
++ EXCEPTION_VECTOR 45
++ EXCEPTION_VECTOR 46
++ EXCEPTION_VECTOR 47
++ EXCEPTION_VECTOR 48
++ EXCEPTION_VECTOR 49
++ EXCEPTION_VECTOR 50
++ EXCEPTION_VECTOR 51
++ EXCEPTION_VECTOR 52
++ EXCEPTION_VECTOR 53
++ EXCEPTION_VECTOR 54
++ EXCEPTION_VECTOR 55
++ EXCEPTION_VECTOR 56
++ EXCEPTION_VECTOR 57
++ EXCEPTION_VECTOR 58
++ EXCEPTION_VECTOR 59
++ EXCEPTION_VECTOR 60
++ EXCEPTION_VECTOR 61
++ EXCEPTION_VECTOR 62
++ EXCEPTION_VECTOR 63
++ EXCEPTION_VECTOR 64
++ EXCEPTION_VECTOR 65
++ EXCEPTION_VECTOR 66
++ EXCEPTION_VECTOR 67
++ EXCEPTION_VECTOR 68
++ EXCEPTION_VECTOR 69
++ EXCEPTION_VECTOR 70
++ EXCEPTION_VECTOR 71
++ EXCEPTION_VECTOR 72
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ex-exit.S linux-3.4.110/arch/nds32/kernel/ex-exit.S
+--- linux-3.4.110.orig/arch/nds32/kernel/ex-exit.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/ex-exit.S 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,220 @@
++#include <linux/linkage.h>
++#include <asm/unistd.h>
++#include <asm/assembler.h>
++#include <asm/nds32.h>
++#include <asm/asm-offsets.h>
++#include <asm/thread_info.h>
++
++#define why $r8 // Linux syscall (!= 0)
++#define tsk $r9 // current thread_info
++
++
++ .macro pop_zol
++#ifdef CONFIG_HWZOL
++ mtusr $r10, $LB
++ mtusr $r11, $LE
++ mtusr $r12, $LC
++#endif
++ .endm
++
++ .macro restore_user_regs_first
++ setgie.d
++ isb
++ /* $p1 is VA of percpu data */
++#ifdef CONFIG_CPU_N1213_43U1HA0
++ movi $p1, #0x0
++#else
++ mfsr $p1, $CORE_ID
++#endif
++ andi $p1, $p1, #0x3
++ slli $p1, $p1, #0x9
++ sethi $p0, #0xc0006
++ or $p1, $p1, $p0
++
++ addi $sp, $sp, S_OFF
++ popm $r16, $r18
++ mtsr $r16, $PSW
++ pop $r16
++ swi $r16, [$p1+#0x8]
++ addi $sp, $sp, #4 !pop $r0
++ popm $r6, $r13
++ mtsr $r17, $IPSW
++ mtsr $r18, $IPC
++ mtsr $r6, $P_IPSW
++ mtsr $r7, $P_IPC
++ mtsr $r8, $P_P0
++ mtsr $r9, $P_P1
++#ifdef CONFIG_HWZOL
++ pop_zol
++#endif
++ .endm
++
++ .macro restore_user_regs_last
++ popm $r28, $r30
++#if defined(CONFIG_FPU) || defined(CONFIG_AUDIO)
++ pop $p0
++ mtsr $p0, $FUCOP_CTL
++#else
++ addi $sp, $sp, 4
++#endif
++
++ pop $p0
++ cmovn $sp, $p0, $p0
++
++ mfsr $p0, $IPSW
++ andi $p0, $p0, #PSW_mskPOM
++ bnez $p0, 1f
++ swi $sp, [$p1+#0xc]
++ lwi $sp, [$p1+#0x8]
++1:
++ // This is SW workaround for Bug #6294
++ li $p0, 0xc0000000
++ cctl $p0, L1D_VA_INVAL
++ lwi $p1, [$p0]
++
++ iret
++ nop
++
++ .endm
++
++ .macro restore_user_regs
++ restore_user_regs_first
++ popm $r0, $r25
++ restore_user_regs_last
++ .endm
++
++ .macro fast_restore_user_regs
++ restore_user_regs_first
++ addi $sp, $sp, #4
++ popm $r1, $r25
++ restore_user_regs_last
++ .endm
++
++#ifdef CONFIG_PREEMPT
++ .macro preempt_stop
++ .endm
++#else
++ .macro preempt_stop
++ setgie.d
++ isb
++ .endm
++#define resume_kernel no_work_pending
++#endif
++
++ENTRY(ret_from_exception)
++ preempt_stop
++ENTRY(ret_from_intr)
++ get_thread_info tsk
++ move why, #0 ! not system call
++
++/*
++ * judge Kernel or user mode
++ *
++ */
++ lwi $p0, [$sp+(#S_IPSW+#S_OFF)]
++! mfsr $p0, $IPSW ! Check if in nested interrupt
++ andi $p0, $p0, #PSW_mskINTL
++ bnez $p0, resume_kernel ! done with iret
++ j resume_userspace
++
++
++/*
++ * This is the fast syscall return path. We do as little as
++ * possible here, and this includes saving $r0 back into the SVC
++ * stack.
++ * fixed: tsk - $r9, why - $r8, $r7 - syscall #, $r8 - syscall table pointer
++ */
++ENTRY(ret_fast_syscall)
++ gie_disable
++ lwi $r1, [tsk+#TI_FLAGS]
++ andi $p1, $r1, #_TIF_WORK_MASK
++ bnez $p1, fast_work_pending
++ fast_restore_user_regs ! iret
++
++/*
++ * Ok, we need to do extra processing,
++ * enter the slow path returning from syscall, while pending work.
++ */
++fast_work_pending:
++ swi $r0, [$sp+(#S_R0+#S_OFF)] ! what is different from ret_from_exception
++ ! addi $sp, $sp, S_OFF
++ move why, #1 ! come from a syscall
++work_pending:
++ andi $p1, $r1, #_TIF_NEED_RESCHED
++ bnez $p1, work_resched
++
++ andi $p1, $r1, #_TIF_SIGPENDING|#_TIF_NOTIFY_RESUME
++ beqz $p1, no_work_pending
++
++ move $r0, $sp ! 'regs'
++ move $r2, why
++ gie_enable
++ bal do_notify_resume
++
++ b ret_slow_syscall ! return from slow_restore_user_regs
++
++work_resched:
++ bal schedule ! path, return to user mode
++
++/*
++ * "slow" syscall return path.
++ * "why" tells us if this was a real syscall.
++ */
++ENTRY(resume_userspace)
++ENTRY(ret_slow_syscall)
++ gie_disable
++ lwi $p0, [$sp+(#S_IPSW+#S_OFF)]
++! mfsr $p0, $IPSW ! Check if in nested interrupt
++ andi $p0, $p0, #PSW_mskINTL
++ bnez $p0, no_work_pending ! done with iret
++ lwi $r1, [tsk+#TI_FLAGS]
++ andi $p1, $r1, #_TIF_WORK_MASK
++ bnez $p1, work_pending ! handle work_resched, sig_pend
++
++no_work_pending:
++#ifdef CONFIG_TRACE_IRQFLAGS
++ lwi $p0, [$sp+(#S_IPSW+#S_OFF)]
++ andi $p0, $p0, #0x1
++ la $r10, arch_trace_hardirqs_off
++ la $r9, arch_trace_hardirqs_on
++ cmovz $r9, $p0, $r10
++ jral $r9
++#endif
++ restore_user_regs ! return from iret
++
++
++/*
++ * preemptive kernel
++ */
++#ifdef CONFIG_PREEMPT
++resume_kernel:
++ gie_disable
++ lwi $t0, [tsk+#TI_PREEMPT]
++ bnez $t0, no_work_pending
++need_resched:
++ lwi $t0, [tsk+#TI_FLAGS]
++ andi $p1, $t0, #_TIF_NEED_RESCHED
++ beqz $p1, no_work_pending
++
++ lwi $t0, [$sp+(#S_IPSW+#S_OFF)] ! Interrupts off?
++ andi $t0, $t0, #1
++ beqz $t0, no_work_pending
++
++ jal preempt_schedule_irq
++ b need_resched
++#endif
++
++/*
++ * This is how we return from a fork.
++ */
++ENTRY(ret_from_fork)
++ bal schedule_tail
++ get_thread_info tsk
++ lwi $r1, [tsk+#TI_FLAGS] ! check for syscall tracing
++ move why, #1
++ andi $p1, $r1, #_TIF_WORK_SYSCALL_LEAVE ! are we tracing syscalls?
++ beqz $p1, ret_slow_syscall
++ move $r0, $sp
++ bal syscall_trace_leave
++ b ret_slow_syscall
++
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ex-scall.S linux-3.4.110/arch/nds32/kernel/ex-scall.S
+--- linux-3.4.110.orig/arch/nds32/kernel/ex-scall.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/ex-scall.S 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,288 @@
++#include <linux/linkage.h>
++#include <asm/unistd.h>
++#include <asm/assembler.h>
++#include <asm/nds32.h>
++#include <asm/asm-offsets.h>
++#include <asm/thread_info.h>
++
++/*
++ * $r0 = previous task_struct,
++ * $r1 = previous thread_info,
++ * $r2 = next thread_info
++ * previous and next are guaranteed not to be the same.
++ */
++
++ENTRY(_switch)
++ smw.adm $r6, [$sp], $r14, #0xa
++ swi $sp, [$r1+ TI_SP_SAVE] /* Save $sp to task structure */
++ lwi $sp, [$r2+ TI_SP_SAVE] /* Get $sp from task structure */
++ lmw.bim $r6, [$sp], $r14, #0xa
++ ret
++
++/*
++ * These are the registers used in the syscall handler, and allow us
++ * to have in theory up to 6 arguments to a function - $r0 to $r5.
++ * $r7 is reserved for the system call number for Andes architecture.
++ *
++ * Note that tbl == why is intentional.
++ * We must set at least "tsk" and "why" when calling ret_with_reschedule.
++ */
++#define tbl $r8 // syscall table pointer
++#define why $r8 // Linux syscall (!= 0)
++#define tsk $r9 // current thread_info
++
++/*
++ * Get the system call number. let $r7 take a system call nr.
++ *
++ * if it is called from library function, $r7 is filled by library call
++ * when user program make a system call. and swid bitfield of $ir6 will
++ * always be encoded as 0x7fff.
++ *
++ * if it is called from kernel code, $r7 will be writen as syscall nr
++ * by retrieving from $ir6 'swid' bitfiled
++ */
++ .macro get_scno
++ mfsr $r7, $ITYPE
++#ifdef CONFIG_PLAT_QEMU
++ slli $r7, $r7, #1
++ srli $r7, $r7, #ITYPE_offSWID+1
++#else
++ srli $r7, $r7, #ITYPE_offSWID
++#endif
++ .endm
++
++ .macro updateipc
++ addi $r17, $r18, #4
++ swi $r17, [$sp + S_OFF + S_IPC]
++ .endm
++
++ .equ NR_syscalls,0
++#define CALL(x) .equ NR_syscalls,NR_syscalls+1
++#include "calls.S"
++#undef CALL
++#define CALL(x) .long x
++
++ENTRY(eh_syscall)
++ updateipc
++
++ get_scno
++ gie_enable
++ get_thread_info tsk
++ lwi $p0, [tsk+#TI_FLAGS] ! check for syscall tracing
++
++ andi $p1, $p0, #_TIF_WORK_SYSCALL_ENTRY ! are we tracing syscalls?
++ bnez $p1, __sys_trace
++
++ la $lp, ret_fast_syscall ! return address
++
++ li $p0, __NR_NDS32_BASE
++ addi $p0, $p0, -1
++ slt $p0, $p0, $r7
++ beqz $p0, 1f
++ addi $r1, $SP, #0
++ move $r0, $r7
++ b nds32_syscall
++1:
++ ! check upper syscall limit,
++ andi $r7, $r7, #0xfff
++ addi $p1, $r7, #-NR_syscalls ! syscall number of syscall instruction is guarded by addembler
++ bgez $p1, _SCNO_EXCEED ! call sys_* routine
++ la tbl, sys_call_table ! load syscall table pointer
++ slli $p1, $r7, #2
++ add $p1, tbl, $p1
++ lwi $p1, [$p1]
++ jr $p1 ! no return
++
++_SCNO_EXCEED:
++ ori $r0, $r7, #0
++ ori $r1, $sp, #0
++ b bad_syscall
++
++/*
++ * This is the really slow path. We're going to be doing
++ * context switches, and waiting for our parent to respond.
++ */
++__sys_trace:
++ move $r1, $sp
++ move $r0, $r7 ! trace entry [IP = 0]
++ bal syscall_trace_enter
++ move $r7, $r0
++ la $lp, __sys_trace_return ! return address
++
++ li $p0, __NR_NDS32_BASE
++ addi $p0, $p0, -1
++ slt $p0, $p0, $r7
++ beqz $p0, 1f
++ addi $r1, $SP, #0
++ b nds32_syscall
++1:
++ andi $r7, $r7, #0xfff
++ addi $p1, $sp, #S_R0+S_OFF ! pointer to regs
++ addi $p0, $r7, -#NR_syscalls ! check upper syscall limit
++ bgez $p0, _SCNO_EXCEED
++ lmw.bi $r0, [$p1], $r5 ! have to reload $r0 - $r5
++
++ slli $p0, $r7, #2 ! call sys_* routine
++ la tbl, sys_call_table ! load syscall table pointer
++ add $p0, tbl, $p0
++ lwi $p0, [$p0]
++ jr $p0
++
++__sys_trace_return:
++ swi $r0, [$sp+(#S_R0+S_OFF)] ! T: save returned $r0
++ bal syscall_trace_leave
++ b ret_slow_syscall
++
++ .type sys_call_table, #object
++ENTRY(sys_call_table)
++#include "calls.S"
++
++/*
++ * Special system call wrappers
++ *
++ * $r0 = syscall number
++ * $r8 = syscall table
++ */
++ .type sys_syscall, #function
++sys_syscall:
++
++ li $p0, __NR_NDS32_BASE
++ addi $p0, $p0, -1
++ slt $p0, $p0, $r0
++ beqz $p0, 1f
++ addi $r1, $SP, #0
++ b nds32_syscall
++1:
++ bltz $r0, 3f ! Guard whether syscall number is between 0~0x7fff.
++ andi $r0, $r0, #0xfff
++ addi $p1, $r0, #-NR_syscalls
++ bgtz $p1, 3f
++ move $p1, $r0
++ move $r0, $r1
++ move $r1, $r2
++ move $r2, $r3
++ move $r3, $r4
++ move $r4, $r5
++! add for syscall 6 args
++ lwi $r5, [$sp + (#S_SP + #S_OFF) ]
++ lwi $r5, [$r5 + #S_OFF]
++! ~add for syscall 6 args
++
++ lw $p1, [tbl+$p1<<2]
++ jr $p1
++3: b sys_ni_syscall
++
++sys_fork_wrapper:
++ addi $r0, $sp, #0
++ b sys_fork
++
++sys_vfork_wrapper:
++ addi $r0, $sp, #0
++ b sys_vfork
++
++sys_execve_wrapper:
++ addi $r3, $sp, #0
++ b sys_execve
++
++sys_clone_wrapper:
++ addi $r5, $SP, #0
++ b sys_clone
++
++sys_sigsuspend_wrapper:
++ addi $r3, $sp, #0
++ b sys_sigsuspend
++
++sys_rt_sigsuspend_wrapper:
++ addi $r2, $sp, #0
++ b sys_rt_sigsuspend
++
++sys_sigreturn_wrapper:
++ addi $r0, $sp, #0
++ b sys_sigreturn
++
++sys_rt_sigreturn_wrapper:
++ addi $r0, $sp, #0
++ b sys_rt_sigreturn
++
++sys_sigaltstack_wrapper:
++ lwi $r2, [$sp+(#S_OFF + S_SP)]
++ b do_sigaltstack
++
++sys_futex_wrapper:
++ b sys_futex
++
++#ifdef CONFIG_FUNCTION_TRACER
++ .global _mcount
++ .global ftrace_stub
++_mcount:
++ sethi $r15, hi20(function_trace_stop)
++ lwi $r15, [$r15 + lo12(function_trace_stop)]
++ bnez $r15, _ftrace_stub
++
++ sethi $r15, hi20(ftrace_trace_function)
++ lwi $p0, [$r15 + lo12(ftrace_trace_function)]
++ sethi $r15, hi20(ftrace_stub)
++ ori $r15, $r15, lo12(ftrace_stub)
++ bne $r15, $p0, trace
++
++#ifdef CONFIG_FUNCTION_GRAPH_TRACER
++ sethi $p0, hi20(ftrace_graph_return)
++ lwi $p0, [$p0 + lo12(ftrace_graph_return)]
++ bne $r15, $p0, _ftrace_graph_caller
++
++ sethi $r15, hi20(ftrace_graph_entry)
++ lwi $r15, [$r15 + lo12(ftrace_graph_entry)]
++ sethi $p0, hi20(ftrace_graph_entry_stub)
++ ori $p0, $p0, lo12(ftrace_graph_entry_stub)
++ bne $r15, $p0, _ftrace_graph_caller
++#endif
++
++_ftrace_stub:
++ftrace_stub:
++ ret
++
++trace:
++ smw.adm $r0, [$sp], $r5, #10
++ move $r0, $lp
++ sethi $r15, hi20(get_selfpc)
++ ori $r15, $r15, lo12(get_selfpc)
++ jral $r15
++ move $r1, $r0
++ lwi $r0, [$sp+36]
++ jral $p0
++ lmw.bim $r0, [$sp], $r5, #10
++ ret
++#endif
++
++#ifdef CONFIG_FUNCTION_GRAPH_TRACER
++ .global ftrace_graph_caller
++ .global return_to_handler
++_ftrace_graph_caller:
++ftrace_graph_caller:
++ sethi $p1, hi20(function_trace_stop)
++ lwi $p1, [$p1 + lo12(function_trace_stop)]
++ bnez $p1, ftrace_stub
++
++ sethi $p1, hi20(prepare_ftrace_return)
++ ori $p1, $p1, lo12(prepare_ftrace_return)
++
++ smw.adm $r0, [$sp], $r5, #10
++ move $r0, $lp
++ sethi $p0, hi20(get_selfpc)
++ ori $p0, $p0, lo12(get_selfpc)
++ jral $p0
++ move $r1, $r0
++ addi $r0, $sp, #36
++ jral $p1
++ lmw.bim $r0, [$sp], $r5, #10
++ ret
++
++return_to_handler:
++ smw.adm $r0, [$sp], $r5, #10
++ sethi $r15, hi20(ftrace_return_to_handler)
++ ori $r15, $r15, lo12(ftrace_return_to_handler)
++ jral $r15
++ move $r15, $r0
++ lmw.bim $r0, [$sp], $r5, #10
++ jr $r15
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/fpu.c linux-3.4.110/arch/nds32/kernel/fpu.c
+--- linux-3.4.110.orig/arch/nds32/kernel/fpu.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/fpu.c 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,306 @@
++/*
++ * arch/nds32/kernel/fpu.c
++ *
++ * Copyright (C) 2001 Manuela Cirronis, Paolo Alberelli
++ * Copyright (C) 2002 STMicroelectronics Limited
++ * Author : Stuart Menefy
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * Started from SH4 version:
++ * Copyright (C) 1999, 2000 Kaz Kojima & Niibe Yutaka
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/sched.h>
++#include <linux/signal.h>
++#include <asm/processor.h>
++#include <asm/user.h>
++#include <asm/io.h>
++#include <asm/bitfield.h>
++#include <asm/fpu.h>
++#include "fpu.h"
++
++extern void do_revinsn(struct pt_regs *regs);
++extern int do_fpu_denorm(struct pt_regs *regs, struct fpu_struct *fpu);
++
++static struct fpu_struct init_fpuregs = {
++ .fs_regs = {[0 ... 31] = sNAN32},
++ .fd_regs = {[0 ... 15] = sNAN64},
++ .fpcsr = FPCSR_INIT
++};
++
++void save_fpu(struct task_struct *tsk)
++{
++ unsigned int fpcfg, fpcsr;
++ enable_fpu();
++ asm volatile ("fmfcfg %0\n\t":"=&r" (fpcfg));
++ fpcfg = ((fpcfg & FPCFG_mskFREG) >> FPCFG_offFREG);
++
++ switch (fpcfg) {
++ case 3:
++ asm volatile ("fsdi $fd31, [%0+0xf8]\n\t"
++ "fsdi $fd30, [%0+0xf0]\n\t"
++ "fsdi $fd29, [%0+0xe8]\n\t"
++ "fsdi $fd28, [%0+0xe0]\n\t"
++ "fsdi $fd27, [%0+0xd8]\n\t"
++ "fsdi $fd26, [%0+0xd0]\n\t"
++ "fsdi $fd25, [%0+0xc8]\n\t"
++ "fsdi $fd24, [%0+0xc0]\n\t"
++ "fsdi $fd23, [%0+0xb8]\n\t"
++ "fsdi $fd22, [%0+0xb0]\n\t"
++ "fsdi $fd21, [%0+0xa8]\n\t"
++ "fsdi $fd20, [%0+0xa0]\n\t"
++ "fsdi $fd19, [%0+0x98]\n\t"
++ "fsdi $fd18, [%0+0x90]\n\t"
++ "fsdi $fd17, [%0+0x88]\n\t"
++ "fsdi $fd16, [%0+0x80]\n\t"
++ : /* no output */
++ :"r" (&tsk->thread.fpu)
++ :"memory");
++ /* fall through */
++ case 2:
++ asm volatile ("fssi $fs31, [%0+0x7c]\n\t"
++ "fssi $fs30, [%0+0x78]\n\t"
++ "fssi $fs29, [%0+0x74]\n\t"
++ "fssi $fs28, [%0+0x70]\n\t"
++ "fssi $fs27, [%0+0x6c]\n\t"
++ "fssi $fs26, [%0+0x68]\n\t"
++ "fssi $fs25, [%0+0x64]\n\t"
++ "fssi $fs24, [%0+0x60]\n\t"
++ "fssi $fs23, [%0+0x5c]\n\t"
++ "fssi $fs22, [%0+0x58]\n\t"
++ "fssi $fs21, [%0+0x54]\n\t"
++ "fssi $fs20, [%0+0x50]\n\t"
++ "fssi $fs19, [%0+0x4c]\n\t"
++ "fssi $fs18, [%0+0x48]\n\t"
++ "fssi $fs17, [%0+0x44]\n\t"
++ "fssi $fs16, [%0+0x40]\n\t"
++ : /* no output */
++ :"r" (&tsk->thread.fpu)
++ :"memory");
++ /* fall through */
++ case 1:
++ asm volatile ("fssi $fs15, [%0+0x3c]\n\t"
++ "fssi $fs14, [%0+0x38]\n\t"
++ "fssi $fs13, [%0+0x34]\n\t"
++ "fssi $fs12, [%0+0x30]\n\t"
++ "fssi $fs11, [%0+0x2c]\n\t"
++ "fssi $fs10, [%0+0x28]\n\t"
++ "fssi $fs9, [%0+0x24]\n\t"
++ "fssi $fs8, [%0+0x20]\n\t"
++ : /* no output */
++ :"r" (&tsk->thread.fpu)
++ :"memory");
++ /* fall through */
++ case 0:
++ asm volatile ("fssi $fs7, [%1+0x1c]\n\t"
++ "fssi $fs6, [%1+0x18]\n\t"
++ "fssi $fs5, [%1+0x14]\n\t"
++ "fssi $fs4, [%1+0x10]\n\t"
++ "fssi $fs3, [%1+0xc]\n\t"
++ "fssi $fs2, [%1+0x8]\n\t"
++ "fssi $fs1, [%1+0x4]\n\t"
++ "fssi $fs0, [%1+0x0]\n\t"
++ "fmfcsr %0\n\t"
++ "swi %0, [%1+0x100]\n\t"
++ :"=&r" (fpcsr)
++ :"r"(&tsk->thread.fpu)
++ :"memory");
++ }
++ disable_fpu();
++}
++
++void fpload(struct fpu_struct *fpregs)
++{
++ unsigned int fpcfg, fpcsr;
++ enable_fpu();
++
++ asm volatile ("fmfcfg %0\n\t":"=&r" (fpcfg));
++ fpcfg = ((fpcfg & FPCFG_mskFREG) >> FPCFG_offFREG);
++
++ switch (fpcfg) {
++ case 3:
++ asm volatile ("fldi $fd31, [%0+0xf8]\n\t"
++ "fldi $fd30, [%0+0xf0]\n\t"
++ "fldi $fd29, [%0+0xe8]\n\t"
++ "fldi $fd28, [%0+0xe0]\n\t"
++ "fldi $fd27, [%0+0xd8]\n\t"
++ "fldi $fd26, [%0+0xd0]\n\t"
++ "fldi $fd25, [%0+0xc8]\n\t"
++ "fldi $fd24, [%0+0xc0]\n\t"
++ "fldi $fd23, [%0+0xb8]\n\t"
++ "fldi $fd22, [%0+0xb0]\n\t"
++ "fldi $fd21, [%0+0xa8]\n\t"
++ "fldi $fd20, [%0+0xa0]\n\t"
++ "fldi $fd19, [%0+0x98]\n\t"
++ "fldi $fd18, [%0+0x90]\n\t"
++ "fldi $fd17, [%0+0x88]\n\t"
++ "fldi $fd16, [%0+0x80]\n\t"
++ : /* no output */
++ :"r" (fpregs));
++ /* fall through */
++ case 2:
++ asm volatile ("flsi $fs31, [%0+0x7c]\n\t"
++ "flsi $fs30, [%0+0x78]\n\t"
++ "flsi $fs29, [%0+0x74]\n\t"
++ "flsi $fs28, [%0+0x70]\n\t"
++ "flsi $fs27, [%0+0x6c]\n\t"
++ "flsi $fs26, [%0+0x68]\n\t"
++ "flsi $fs25, [%0+0x64]\n\t"
++ "flsi $fs24, [%0+0x60]\n\t"
++ "flsi $fs23, [%0+0x5c]\n\t"
++ "flsi $fs22, [%0+0x58]\n\t"
++ "flsi $fs21, [%0+0x54]\n\t"
++ "flsi $fs20, [%0+0x50]\n\t"
++ "flsi $fs19, [%0+0x4c]\n\t"
++ "flsi $fs18, [%0+0x48]\n\t"
++ "flsi $fs17, [%0+0x44]\n\t"
++ "flsi $fs16, [%0+0x40]\n\t"
++ : /* no output */
++ :"r" (fpregs));
++ /* fall through */
++ case 1:
++ asm volatile ("flsi $fs15, [%0+0x3c]\n\t"
++ "flsi $fs14, [%0+0x38]\n\t"
++ "flsi $fs13, [%0+0x34]\n\t"
++ "flsi $fs12, [%0+0x30]\n\t"
++ "flsi $fs11, [%0+0x2c]\n\t"
++ "flsi $fs10, [%0+0x28]\n\t"
++ "flsi $fs9, [%0+0x24]\n\t"
++ "flsi $fs8, [%0+0x20]\n\t"
++ : /* no output */
++ :"r" (fpregs));
++ /* fall through */
++ case 0:
++ asm volatile ("flsi $fs7, [%1+0x1c]\n\t"
++ "flsi $fs6, [%1+0x18]\n\t"
++ "flsi $fs5, [%1+0x14]\n\t"
++ "flsi $fs4, [%1+0x10]\n\t"
++ "flsi $fs3, [%1+0xc]\n\t"
++ "flsi $fs2, [%1+0x8]\n\t"
++ "flsi $fs1, [%1+0x4]\n\t"
++ "flsi $fs0, [%1+0x0]\n\t"
++ "lwi %0, [%1+0x100]\n\t"
++ "fmtcsr %0\n\t":"=&r" (fpcsr)
++ :"r"(fpregs));
++ }
++ disable_fpu();
++}
++
++void do_fpu_context_switch(unsigned long error_code, struct pt_regs *regs)
++{
++ /* Enable to use FPU. */
++
++ if (!user_mode(regs)) {
++ printk(KERN_ERR "BUG: FPU is used in kernel mode.\n");
++ BUG();
++ return;
++ }
++
++ grab_fpu(regs);
++#ifndef CONFIG_UNLAZY_FPU //Lazy FPU is used
++ if (last_task_used_math == current)
++ return;
++ if (last_task_used_math != NULL)
++ /* Other processes fpu state, save away */
++ save_fpu(last_task_used_math);
++ last_task_used_math = current;
++#endif
++ if (used_math()) {
++ fpload(&current->thread.fpu);
++ } else {
++ /* First time FPU user. */
++ fpload(&init_fpuregs);
++ set_used_math();
++ }
++
++}
++
++void do_fpu_exception(unsigned long error_code, struct pt_regs *regs)
++{
++ unsigned int subtype =
++ ((GET_ITYPE() & ITYPE_mskSTYPE) >> ITYPE_offSTYPE);
++ unsigned int cpid = ((GET_ITYPE() & ITYPE_mskCPID) >> ITYPE_offCPID);
++
++ /* FPU */
++ if ((cpid == 0) && (GET_FUCOP_EXIST() & FUCOP_EXIST_mskCP0ISFPU)) {
++ /* Coprocessor disabled exception */
++ if (subtype == 1) {
++ preempt_disable();
++ do_fpu_context_switch(error_code, regs);
++ preempt_enable();
++ }
++ /* Coprocessor exception */
++ else if (subtype == 2) {
++ siginfo_t si = { 0 };
++ unsigned int fpcsr;
++ enable_fpu();
++ asm volatile ("fmfcsr %0\n\t":"=&r" (fpcsr));
++ disable_fpu();
++
++ if (fpcsr & FPCSR_mskALLT) {
++ si.si_signo = SIGFPE;
++ /* Exception handling, denorm input, UDF and OVF */
++ if (fpcsr & FPCSR_mskDNIT) {
++ unsigned int rfpcsr;
++ lose_fpu(1);
++ si.si_signo =
++ do_fpu_denorm(regs,
++ &current->thread.fpu);
++ own_fpu(1);
++
++ if (si.si_signo == SIGFPE) {
++ rfpcsr =
++ current->thread.fpu.fpcsr;
++
++ if (rfpcsr & FPCSR_mskIVO)
++ si.si_code = FPE_FLTINV;
++ if (rfpcsr & FPCSR_mskDBZ)
++ si.si_code = FPE_FLTDIV;
++ if (rfpcsr & FPCSR_mskOVF)
++ si.si_code = FPE_FLTOVF;
++ if (rfpcsr & FPCSR_mskUDF)
++ si.si_code = FPE_FLTUND;
++ if (rfpcsr & FPCSR_mskIEX)
++ si.si_code = FPE_FLTRES;
++ } else if (si.si_code == SIGILL)
++ show_regs(regs);
++ else if (si.si_code == SIGBUS)
++ si.si_code = BUS_ADRERR;
++ } else if (fpcsr & FPCSR_mskRIT) {
++ printk("Reserved Instruction\n");
++ show_regs(regs);
++ if (!user_mode(regs))
++ do_exit(SIGILL);
++ si.si_signo = SIGILL;
++ } else if (fpcsr & FPCSR_mskUDFT)
++ si.si_code = FPE_FLTUND;
++ else if (fpcsr & FPCSR_mskOVFT)
++ si.si_code = FPE_FLTOVF;
++ else if (fpcsr & FPCSR_mskIVOT)
++ si.si_code = FPE_FLTINV;
++ else if (fpcsr & FPCSR_mskDBZT)
++ si.si_code = FPE_FLTDIV;
++ else if (fpcsr & FPCSR_mskIEXT)
++ si.si_code = FPE_FLTRES;
++ /* If something went wrong, signal */
++ if (si.si_signo) {
++ if (si.si_code == SIGILL) {
++ force_sig(si.si_signo, current);
++ } else {
++ si.si_addr =
++ (void __user *)
++ instruction_pointer(regs);
++ force_sig_info(si.si_signo, &si,
++ current);
++ }
++ }
++ } else {
++ printk("Bad FPU exception\n");
++ BUG();
++ }
++ }
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/fpu.h linux-3.4.110/arch/nds32/kernel/fpu.h
+--- linux-3.4.110.orig/arch/nds32/kernel/fpu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/fpu.h 2016-04-07 10:20:50.938080870 +0200
+@@ -0,0 +1,13 @@
++
++
++/*
++ * Initially load the FPU with signalling NANS. This bit pattern
++ * has the property that no matter whether considered as single or as
++ * double precision, it still represents a signalling NAN.
++ */
++
++ #define sNAN64 0xFFFFFFFFFFFFFFFFULL
++ #define sNAN32 0xFFFFFFFFUL
++
++ #define FPCSR_INIT 0x0 /* Hardware reset value */
++
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ftrace.c linux-3.4.110/arch/nds32/kernel/ftrace.c
+--- linux-3.4.110.orig/arch/nds32/kernel/ftrace.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/ftrace.c 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,219 @@
++/*
++ * Code for replacing ftrace calls with jumps.
++ *
++ * Copyright (C) 2007-2008 Steven Rostedt <srostedt@redhat.com>
++ *
++ * Thanks goes out to P.A. Semi, Inc for supplying me with a PPC64 box.
++ *
++ * Added function graph tracer code, taken from x86 that was written
++ * by Frederic Weisbecker, and ported to PPC by Steven Rostedt.
++ *
++ */
++
++#include <linux/spinlock.h>
++#include <linux/hardirq.h>
++#include <linux/uaccess.h>
++#include <linux/module.h>
++#include <linux/ftrace.h>
++#include <linux/percpu.h>
++#include <linux/init.h>
++#include <linux/list.h>
++
++#include <asm/cacheflush.h>
++#include <asm/ftrace.h>
++
++# define GET_ADDR(addr) (*(unsigned long *)addr)
++
++#ifdef CONFIG_DYNAMIC_FTRACE
++static unsigned int ftrace_nop_replace(void)
++{
++// return PPC_INST_NOP;
++ return 0;
++}
++
++static unsigned int
++ftrace_call_replace(unsigned long ip, unsigned long addr, int link)
++{
++ unsigned int op;
++
++ addr = GET_ADDR(addr);
++
++ /* if (link) set op to 'bl' else 'b' */
++// op = create_branch((unsigned int *)ip, addr, link ? 1 : 0);
++
++ return op;
++}
++
++static int
++ftrace_modify_code(unsigned long ip, unsigned int old, unsigned int new)
++{
++ unsigned int replaced;
++
++ /*
++ * Note: Due to modules and __init, code can
++ * disappear and change, we need to protect against faulting
++ * as well as code changing. We do this by using the
++ * probe_kernel_* functions.
++ *
++ * No real locking needed, this code is run through
++ * kstop_machine, or before SMP starts.
++ */
++
++ /* read the text we want to modify */
++ if (probe_kernel_read(&replaced, (void *)ip, MCOUNT_INSN_SIZE))
++ return -EFAULT;
++
++ /* Make sure it is what we expect it to be */
++ if (replaced != old)
++ return -EINVAL;
++
++ /* replace the text with the new text */
++ if (probe_kernel_write((void *)ip, &new, MCOUNT_INSN_SIZE))
++ return -EPERM;
++
++ flush_icache_range(ip, ip + 8);
++
++ return 0;
++}
++
++int ftrace_make_nop(struct module *mod,
++ struct dyn_ftrace *rec, unsigned long addr)
++{
++ unsigned long ip = rec->ip;
++ unsigned int old, new;
++
++ old = ftrace_call_replace(ip, addr, 1);
++ new = ftrace_nop_replace();
++ return ftrace_modify_code(ip, old, new);
++}
++
++int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
++{
++ unsigned long ip = rec->ip;
++ unsigned int old, new;
++
++ old = ftrace_nop_replace();
++ new = ftrace_call_replace(ip, addr, 1);
++ return ftrace_modify_code(ip, old, new);
++}
++
++int ftrace_update_ftrace_func(ftrace_func_t func)
++{
++ unsigned long ip = (unsigned long)(&ftrace_call);
++ unsigned int old, new;
++ int ret;
++
++ old = *(unsigned int *)&ftrace_call;
++ new = ftrace_call_replace(ip, (unsigned long)func, 1);
++ ret = ftrace_modify_code(ip, old, new);
++
++ return ret;
++}
++
++int __init ftrace_dyn_arch_init(void *data)
++{
++ /* caller expects data to be zero */
++ unsigned long *p = data;
++
++ *p = 0;
++
++ return 0;
++}
++#endif /* CONFIG_DYNAMIC_FTRACE */
++
++#ifdef CONFIG_FUNCTION_GRAPH_TRACER
++
++#ifdef CONFIG_DYNAMIC_FTRACE
++extern void ftrace_graph_call(void);
++extern void ftrace_graph_stub(void);
++
++int ftrace_enable_ftrace_graph_caller(void)
++{
++ unsigned long ip = (unsigned long)(&ftrace_graph_call);
++ unsigned long addr = (unsigned long)(&ftrace_graph_caller);
++ unsigned long stub = (unsigned long)(&ftrace_graph_stub);
++ unsigned int old, new;
++
++ old = ftrace_call_replace(ip, stub, 0);
++ new = ftrace_call_replace(ip, addr, 0);
++
++ return ftrace_modify_code(ip, old, new);
++}
++
++int ftrace_disable_ftrace_graph_caller(void)
++{
++ unsigned long ip = (unsigned long)(&ftrace_graph_call);
++ unsigned long addr = (unsigned long)(&ftrace_graph_caller);
++ unsigned long stub = (unsigned long)(&ftrace_graph_stub);
++ unsigned int old, new;
++
++ old = ftrace_call_replace(ip, addr, 0);
++ new = ftrace_call_replace(ip, stub, 0);
++
++ return ftrace_modify_code(ip, old, new);
++}
++#endif /* CONFIG_DYNAMIC_FTRACE */
++int get_selfpc(unsigned long mcount_lp)
++{
++ unsigned long symbol_size, offset;
++ kallsyms_lookup_size_offset(mcount_lp, &symbol_size, &offset);
++ return mcount_lp - offset;
++}
++
++/*
++ * Hook the return address and push it in the stack of return addrs
++ * in current thread info.
++ */
++void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
++{
++ unsigned long old;
++ int faulted;
++ struct ftrace_graph_ent trace;
++ unsigned long return_hooker = (unsigned long)&return_to_handler;
++
++ if (unlikely(atomic_read(&current->tracing_graph_pause)))
++ return;
++
++ /*
++ * Protect against fault, even if it shouldn't
++ * happen. This tool is too much intrusive to
++ * ignore such a protection.
++ */
++ asm volatile ("1: lwi %[old], [%[parent]]\n"
++ "2: swi %[return_hooker], [%[parent]]\n"
++ " movi %[faulted], 0\n"
++ "3:\n"
++ ".section .fixup, \"ax\"\n"
++ ".align 2 \n"
++ "4: movi %[faulted], 1\n"
++ " b 3b\n"
++ ".previous\n"
++ ".section __ex_table,\"a\"\n"
++ ".align 3 \n"
++ ".long 1b,4b\n"
++ ".long 2b,4b\n"
++ ".previous":[old] "=&r"(old),[faulted] "=r"(faulted)
++ :[parent] "r"(parent),[return_hooker] "r"(return_hooker)
++ :"memory");
++
++ if (unlikely(faulted)) {
++ ftrace_graph_stop();
++ WARN_ON(1);
++ return;
++ }
++
++ trace.func = self_addr;
++ trace.depth = current->curr_ret_stack + 1;
++
++ /* Only trace if the calling function expects to */
++ if (!ftrace_graph_entry(&trace)) {
++ *parent = old;
++ return;
++ }
++
++ if (ftrace_push_return_trace(old, self_addr, &trace.depth, 0) == -EBUSY) {
++ *parent = old;
++ return;
++ }
++}
++#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/head.S linux-3.4.110/arch/nds32/kernel/head.S
+--- linux-3.4.110.orig/arch/nds32/kernel/head.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/head.S 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,350 @@
++/*
++ * arch/nds32/kernel/head.S
++ *
++ * NDS32 Kernel startup code
++ *
++ * Copyright (C) 2007 Andes Technology Corporation
++ *
++ * 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/linkage.h>
++#include <linux/init.h>
++#include <asm/assembler.h>
++#include <asm/mach-types.h>
++#include <asm/procinfo.h>
++#include <asm/ptrace.h>
++#include <asm/asm-offsets.h>
++//#include <asm/system.h>
++#include <asm/page.h>
++#include <asm/pgtable.h>
++#include <asm/l2_cache.h>
++#include <asm/sizes.h>
++
++/*
++ * We place the page tables 16K below TEXTADDR. Therefore, we must make sure
++ * that TEXTADDR is correctly set. Currently, we expect the least significant
++ * 16 bits to be 0x8000, but we could probably relax this restriction to
++ * TEXTADDR >= PAGE_OFFSET + 0x4000
++ *
++ * Note that swapper_pg_dir is the virtual address of the page tables, and
++ * pgtbl gives us a position-independent reference to these tables. We can
++ * do this because _stext == TEXTADDR
++ */
++
++ .globl swapper_pg_dir
++ .equ swapper_pg_dir, TEXTADDR - 0x4000
++
++/*
++ * Kernel startup entry point.
++ * ---------------------------
++ *
++ * This is normally called from the decompressor code. The requirements
++ * are: MMU = off, D-cache = off, I-cache = dont care, $r0 = 0,
++ * $r1 = machine nr.
++ *
++ * This code is mostly position independent, so if you link the kernel at
++ * 0xc0008000, you call this at __pa(0xc0008000).
++ *
++ * See linux/arch/nds32/tools/mach-types for the complete list of machine
++ * numbers for $r1.
++ *
++ * We're trying to keep crap to a minimum; DO NOT add any machine specific
++ * crap here - that's what the boot loader (or in extreme, well justified
++ * circumstances, zImage) is for.
++ */
++ .section ".head.text", "ax"
++ .type _stext, %function
++ENTRY(_stext)
++ setgie.d ! Disable interrupt
++ isb
++ move $r1, #MACH_TYPE_FARADAY ! Note: as far, we are in the Superuser mode
++ jal __lookup_processor_type ! get processor id, $r5=procinfo, $r9=cpuid, invalid processor $r5=0
++ li $r2, 'p'
++ beqz $r5, __error ! yes, error 'p'
++ jal __lookup_machine_type ! $r5=machinfo
++ li $r2, 'a'
++ beqz $r5, __error
++
++/*
++ * Create a temporary mapping area for booting, before start_kernel
++ */
++ sethi $r4, hi20(swapper_pg_dir)
++ li $p0, (PAGE_OFFSET - PHYS_OFFSET)
++ sub $r4, $r4, $p0
++ tlbop FlushAll ! invalidate TLB\n"
++ isb
++ mtsr $r4, $L1_PPTB ! load page table pointer\n"
++
++/* set NTC0 cacheable/writeback, mutliple page size in use */
++ mfsr $r3, $MMU_CTL
++ li $r0, ~0x6
++ and $r3, $r3, $r0
++ ori $r3, $r3, 0x404
++ mtsr $r3, $MMU_CTL
++ isb
++
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++ li $r2, #(PHYS_OFFSET + 0x7bf)
++#else
++ li $r2, #(PHYS_OFFSET + 0x6bf) ! to remember here
++#endif
++ movi $r3, #0x5
++ mtsr $r3, $TLB_MISC
++
++ sethi $r3, hi20(PAGE_OFFSET)
++ li $r0, #PHYS_OFFSET
++ sethi $r5, hi20(SZ_1M) ! Use 1MB pages
++ sethi $r6, hi20(PHYS_OFFSET+SZ_32M) ! Create 32MB first, leave the rest in paging_init()
++_tlb:
++ mtsr $r3, $TLB_VPN
++ dsb
++ tlbop $r2, RWR
++ isb
++ add $r0, $r0, $r5
++ add $r3, $r3, $r5
++ add $r2, $r2, $r5
++ bne $r0, $r6, _tlb
++
++ mtsr $r3, $TLB_MISC ! setup access page size
++ li $r2, #~0xf
++ and $r3, $r3, $r2
++#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
++ ori $r3, $r3, #0x1
++#endif
++ mtsr $r3, $TLB_MISC
++
++ mfsr $r0, $MISC_CTL ! Enable BTB and RTP
++ li $r1, #~0x3
++ and $r0, $r0, $r1
++ mtsr $r0, $MISC_CTL
++
++/*
++ * Disable L2CC and wait until L2CC registers are mapped into memory to use L2$.
++ */
++#ifdef CONFIG_CACHE_L2
++ li $p0, L2CC_PA_BASE
++ li $p1, 0
++ swi $p1, [$p0 + L2CC_CTRL_OFF]
++#endif
++
++#ifdef CONFIG_PLAT_AG102
++/*
++ * Set GPUBA to 0x0c000006. GPUB 0x1c000000, FB size 64MB.
++ */
++ li $p0, DDR2C_PA_BASE + 0x02a4
++ li $p1, 0x0c000006
++ swi $p1, [$p0]
++#endif
++
++ mfsr $p1, $PSW
++ li $r15, #~0x43df ! clear WBNA|DME|IME|DT|IT|POM|INTL|GIE
++ and $p1, $p1, $r15
++#ifdef __NDS32_EB__
++ #ifdef CONFIG_WBNA
++ ori $p1, $p1, #0x40ea ! set WBNA|DT|IT|BE|POM:super|INTL:1
++ #else
++ ori $p1, $p1, #0xea ! set ----|DT|IT|BE|POM:super|INTL:1
++ #endif
++#else
++ #ifdef CONFIG_WBNA
++ ori $p1, $p1, #0x40ca ! set WBNA|DT|IT|--|POM:super|INTL:1
++ #else
++ ori $p1, $p1, #0xca ! set ----|DT|IT|--|POM:super|INTL:1
++ #endif
++#endif
++
++ mtsr $p1, $IPSW ! when iret, it will automatically enable MMU
++ la $lp, __mmap_switched
++ mtsr $lp, $IPC
++ iret
++ nop
++
++ .type __switch_data, %object
++__switch_data:
++ .long __mmap_switched
++ .long _sdata ! $r5
++ .long __bss_start ! $r6
++ .long _end ! $r7
++ .long __machine_arch_type ! $r5
++ .long init_thread_union + 8192 ! $sp
++
++
++/*
++ * The following fragment of code is executed with the MMU on in MMU mode,
++ * and uses absolute addresses; this is not position independent.
++ *
++ * $r0
++ * $r10 = points to proc info
++ * $r8 = points to machine info,
++ * $r1 = machine ID, 0x2c8 for Andes AG101 board
++ * $r9 = processor ID of value in version register
++ */
++ .align
++ .type __mmap_switched, %function
++__mmap_switched:
++ la $r3, __switch_data + 4
++ lmw.bim $r5, [$r3], $r7
++
++ move $fp, #0 ! Clear BSS (and zero $fp)
++ beq $r7, $r6, _RRT
++1: swi.bi $fp, [$r6], #4
++ bne $r7, $r6, 1b
++
++_RRT:
++ lmw.bim $r4, [$r3], $r4, #0b0001
++ sw $r1, [$r4] ! Save machine type to memory
++ b start_kernel
++
++
++/*
++ * Read processor ID register (CP#15, $CR0), and look up in the linker-built
++ * supported processor list. Note that we can't use the absolute addresses
++ * for the __proc_info lists since we aren't running with the MMU on
++ * (and therefore, we are not in the correct address space). We have to
++ * calculate the offset.
++ *
++ * $r9 = cpuid, get from $CPU_VER
++ * Returns:
++ * $r3, $r4, $r6 corrupted
++ * $r5 = proc_info pointer in physical address space
++ * $r9 = cpuid
++ */
++
++ .type __lookup_processor_type, %function
++__lookup_processor_type:
++ la $r5, __proc_info_begin
++ la $r6, __proc_info_end
++ mfsr $r9, $CPU_VER ! get cpu version
++ li $p0, (PAGE_OFFSET - PHYS_OFFSET)
++1:
++ sub $p1, $r5, $p0
++ lmw.bi $r3, [$p1], $r4 ! value, mask
++ and $r4, $r4, $r9 ! mask wanted bits
++ xor $p1, $r3, $r4
++ beqz $p1, 2f
++ addi $r5, $r5, #PROC_INFO_SZ ! sizeof(proc_info_list)
++ bne $r5, $r6, 1b
++
++ move $r5, #0 ! unknown processor -> exit
++2: ret
++
++
++
++/*
++ * Lookup machine architecture in the linker-build list of architectures.
++ * Note that we can't use the absolute addresses for the __arch_info
++ * lists since we aren't running with the MMU on (and therefore, we are
++ * not in the correct address space). We have to calculate the offset.
++ *
++ * $r1 = machine architecture number
++ * Returns:
++ * $r3, $r4, $r6 corrupted
++ * $r5 = mach_info pointer in physical address space
++ */
++ .type __lookup_machine_type, %function
++__lookup_machine_type:
++ la $r5, __arch_info_begin
++ la $r6, __arch_info_end
++1:
++ li $p0, (PAGE_OFFSET - PHYS_OFFSET)
++ sub $p1, $r5, $p0
++ lwi $r3, [$p1] ! use PA to get machine type
++ xor $p1, $r3, $r1 ! matches loader number?
++ beqz $p1, 2f ! found
++ addi $r5, $r5, #SIZEOF_MACHINE_DESC ! next machine_desc
++ bne $r5, $r6, 1b
++ move $r5, #0 ! unknown machine
++2: ret
++
++
++/*
++ * Exception handling. Something went wrong and we can't proceed. We
++ * ought to tell the user, but since we don't have any guarantee that
++ * we're even running on the right architecture, we do virtually nothing.
++ *
++ * a = invalid architecture
++ * p = invalid processor
++ *
++ * Generally, only serious errors cause this.
++ */
++__error:
++ li $r1, UART0_PA_BASE
++ sw $r2, [$r1]
++die: b die
++
++
++
++#ifdef CONFIG_SMP
++
++ .type secondary_startup, %function
++ENTRY(secondary_startup)
++ /*
++ * Common entry point for secondary CPUs.
++ *
++ * Lookup the processor type - there is no need to check the
++ * machine type as it has already been validated by the
++ * primary processor.
++ */
++ mfsr $r0, $MMU_CTL
++ ori $r0, $r0, #4
++#ifndef CONFIG_NO_KERNEL_LARGE_PAGE
++ ori $r0, $r0, #0x400
++#endif
++ mtsr $r0, $MMU_CTL
++
++ movi $r15, #0x01
++ swi $r15, [$p1+#0x10]
++ lwi $sp, [$p1+#0x18]
++
++ /*
++ * Set stack, L1_PPTB, and enable mmu
++ */
++ sethi $r4, hi20(swapper_pg_dir)
++ li $p0, (PAGE_OFFSET - PHYS_OFFSET)
++ sub $r4, $r4, $p0
++
++ tlbop FlushAll
++ isb
++ mtsr $r4, $L1_PPTB
++
++#ifdef CONFIG_CACHE_L2
++ li $r0, #0x1801
++ mtsr $r0, $HSMP_SADDR
++ isb
++ li $r0, #(L2CC_PA_BASE+0x10) ! L2CC Control
++ lwi $r1, [$r0]
++ li $r2, #~(0xf << 28)
++ and $r1, $r1, $r2
++ bset $r1, $r1, #29
++ bset $r1, $r1, #31
++ swi $r1, [$r0]
++#endif
++
++ move $fp, #0
++
++ mfsr $p1, $PSW
++ li $r15, #~0x43df ! clear WBNA|DME|IME|DT|IT|POM|INTL|GIE
++ and $p1, $p1, $r15
++#ifdef __NDS32_EB__
++ #ifdef CONFIG_WBNA
++ ori $p1, $p1, #0x40ea ! set WBNA|DT|IT|BE|POM:super|INTL:1
++ #else
++ ori $p1, $p1, #0xea ! set ----|DT|IT|BE|POM:super|INTL:1
++ #endif
++#else
++ #ifdef CONFIG_WBNA
++ ori $p1, $p1, #0x40ca ! set WBNA|DT|IT|--|POM:super|INTL:1
++ #else
++ ori $p1, $p1, #0xca ! set ----|DT|IT|--|POM:super|INTL:1
++ #endif
++#endif
++
++ mtsr $p1, $IPSW ! when iret, it will automatically enable MMU
++ la $lp, secondary_start_kernel
++ mtsr $lp, $IPC
++ iret
++ nop
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/init_task.c linux-3.4.110/arch/nds32/kernel/init_task.c
+--- linux-3.4.110.orig/arch/nds32/kernel/init_task.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/init_task.c 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,25 @@
++/*
++ * linux/arch/nds32/kernel/init_task.c
++ *
++ * Copyright (C) 2009 Andes Technology Corporation
++ */
++#include <linux/module.h>
++#include <linux/init_task.h>
++#include <linux/mqueue.h>
++#include <linux/fs.h>
++
++#include <asm/uaccess.h>
++
++static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
++static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
++
++/* Initial task structure */
++struct task_struct init_task = INIT_TASK(init_task);
++EXPORT_SYMBOL(init_task);
++
++/*
++ * Initial thread structure. Alignment of this is handled by a special
++ * linker map entry.
++ */
++union thread_union init_thread_union __init_task_data =
++ { INIT_THREAD_INFO(init_task) };
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/io.c linux-3.4.110/arch/nds32/kernel/io.c
+--- linux-3.4.110.orig/arch/nds32/kernel/io.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/io.c 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,51 @@
++#include <linux/module.h>
++#include <linux/types.h>
++
++#include <asm/io.h>
++
++/*
++ * Copy data from IO memory space to "real" memory space.
++ * This needs to be optimized.
++ */
++void _memcpy_fromio(void *to, const volatile void __iomem * from, size_t count)
++{
++ unsigned char *t = to;
++ while (count) {
++ count--;
++ *t = readb(from);
++ t++;
++ from++;
++ }
++}
++
++/*
++ * Copy data from "real" memory space to IO memory space.
++ * This needs to be optimized.
++ */
++void _memcpy_toio(volatile void __iomem * to, const void *from, size_t count)
++{
++ const unsigned char *f = from;
++ while (count) {
++ count--;
++ writeb(*f, to);
++ f++;
++ to++;
++ }
++}
++
++/*
++ * "memset" on IO memory space.
++ * This needs to be optimized.
++ */
++void _memset_io(volatile void __iomem * dst, int c, size_t count)
++{
++ while (count) {
++ count--;
++ writeb(c, dst);
++ dst++;
++ }
++}
++
++EXPORT_SYMBOL(_memcpy_fromio);
++EXPORT_SYMBOL(_memcpy_toio);
++EXPORT_SYMBOL(_memset_io);
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/irq.c linux-3.4.110/arch/nds32/kernel/irq.c
+--- linux-3.4.110.orig/arch/nds32/kernel/irq.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/irq.c 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,122 @@
++/*
++ * linux/arch/nds32/kernel/irq.c
++ *
++ * Copyright (C) 1992 Linus Torvalds
++ * Modifications for ARM processor Copyright (C) 1995-2000 Russell King.
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This file contains the code used by various IRQ handling routines:
++ * asking for different IRQ's should be done through these routines
++ * instead of just grabbing them. Thus setups with different IRQ numbers
++ * shouldn't result in any weird surprises, and installing new handlers
++ * should be easier.
++ *
++ * IRQ's are in fact implemented a bit like signal handlers for the kernel.
++ * Naturally it's not a 1:1 relation, but there are similarities.
++ */
++#include <linux/kernel_stat.h>
++#include <linux/module.h>
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++#include <linux/slab.h>
++#include <linux/random.h>
++#include <linux/seq_file.h>
++#include <linux/kallsyms.h>
++
++void (*init_arch_irq) (void)__initdata = NULL;
++unsigned long irq_err_count;
++
++void ack_bad_irq(unsigned int irq)
++{
++ printk("bad IRQ %d\n", irq);
++}
++
++int show_interrupts(struct seq_file *p, void *v)
++{
++ int i = *(loff_t *) v, cpu;
++ struct irqaction *action;
++ unsigned long flags;
++
++ if (i == 0) {
++ char cpuname[12];
++
++ seq_printf(p, " ");
++ for_each_present_cpu(cpu) {
++ sprintf(cpuname, "CPU%d", cpu);
++ seq_printf(p, " %10s", cpuname);
++ }
++ seq_putc(p, '\n');
++ }
++
++ if (i < NR_IRQS) {
++ raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
++ action = irq_desc[i].action;
++ if (!action)
++ goto unlock;
++
++ seq_printf(p, "%3d: ", i);
++ for_each_present_cpu(cpu)
++ seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
++ seq_printf(p, " %s", action->name);
++ for (action = action->next; action; action = action->next)
++ seq_printf(p, ", %s", action->name);
++
++ seq_putc(p, '\n');
++unlock:
++ raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
++ } else if (i == NR_IRQS) {
++ seq_printf(p, "Err: %10lu\n", irq_err_count);
++ }
++ return 0;
++}
++
++/*
++ * do_IRQ handles all hardware IRQ's. Decoded IRQs should not
++ * come via this function. Instead, they should provide their
++ * own 'handler'
++ */
++asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
++{
++ struct pt_regs *old_regs = set_irq_regs(regs);
++
++ /*
++ * Some hardware gives randomly wrong interrupts. Rather
++ * than crashing, do something sensible.
++ */
++ if (unlikely(irq >= NR_IRQS)) {
++ printk(KERN_EMERG "IRQ exceeds NR_IRQS\n");
++ BUG();
++ }
++
++ irq_enter();
++ generic_handle_irq(irq);
++ irq_exit();
++ set_irq_regs(old_regs);
++
++}
++
++void __init init_IRQ(void)
++{
++ int irq;
++
++ for (irq = 0; irq < NR_IRQS; irq++)
++ irq_set_noprobe(irq);
++
++ init_arch_irq();
++}
++
++#ifdef CONFIG_TRACE_IRQFLAGS
++void notrace arch_trace_hardirqs_on(void)
++{
++ trace_hardirqs_on();
++}
++
++void notrace arch_trace_hardirqs_off(void)
++{
++ trace_hardirqs_off();
++}
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/kgdb.c linux-3.4.110/arch/nds32/kernel/kgdb.c
+--- linux-3.4.110.orig/arch/nds32/kernel/kgdb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/kgdb.c 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,291 @@
++/* ============================================================================
++ *
++ * arch/nds32/kernel/kgdb.c
++ *
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is for NDS32 KGDB support.
++ *
++ * Author: Harry Pan
++ *
++ * Revision History:
++ *
++ * Nov.23.2007 Initial ported by Harry,
++ * inherited from the KGDB in 2.6.11 and 2.4.35.
++ *
++ * Note:
++ *
++ * ============================================================================
++ */
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/signal.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/spinlock.h>
++#include <linux/personality.h>
++#include <linux/ptrace.h>
++#include <linux/elf.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/kgdb.h>
++#include <linux/kdebug.h>
++
++#include <asm/atomic.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/system.h>
++#include <asm/uaccess.h>
++#include <asm/unistd.h>
++#include <asm/ptrace.h>
++#include <asm/traps.h>
++
++// ============================================================================
++// regs_to_gdb_regs()
++//
++// Make a local copy of the registers passed into the handler (bletch).
++// ============================================================================
++void pt_regs_to_gdb_regs(unsigned long *gregs, struct pt_regs *kregs)
++{
++ int regno;
++
++ /* Initialize all to zero (??) */
++ for (regno = 0; regno < NDS32_NUM_REGS; regno++)
++ gregs[regno] = 0;
++
++ gregs[0] = kregs->NDS32_r0;
++ gregs[1] = kregs->NDS32_r1;
++ gregs[2] = kregs->NDS32_r2;
++ gregs[3] = kregs->NDS32_r3;
++ gregs[4] = kregs->NDS32_r4;
++ gregs[5] = kregs->NDS32_r5;
++ gregs[6] = kregs->NDS32_r6;
++ gregs[7] = kregs->NDS32_r7;
++ gregs[8] = kregs->NDS32_r8;
++ gregs[9] = kregs->NDS32_r9;
++ gregs[10] = kregs->NDS32_r10;
++ gregs[11] = kregs->NDS32_r11;
++ gregs[12] = kregs->NDS32_r12;
++ gregs[13] = kregs->NDS32_r13;
++ gregs[14] = kregs->NDS32_r14;
++ gregs[15] = kregs->NDS32_r15;
++ gregs[16] = kregs->NDS32_r16;
++ gregs[17] = kregs->NDS32_r17;
++ gregs[18] = kregs->NDS32_r18;
++ gregs[19] = kregs->NDS32_r19;
++ gregs[20] = kregs->NDS32_r20;
++ gregs[21] = kregs->NDS32_r21;
++ gregs[22] = kregs->NDS32_r22;
++ gregs[23] = kregs->NDS32_r23;
++ gregs[24] = kregs->NDS32_r24;
++ gregs[25] = kregs->NDS32_r25;
++ gregs[26] = kregs->NDS32_pp0;
++ gregs[27] = kregs->NDS32_pp1;
++ gregs[28] = kregs->NDS32_fp;
++ gregs[29] = kregs->NDS32_gp;
++ gregs[30] = kregs->NDS32_lp;
++ gregs[31] = kregs->NDS32_sp;
++ gregs[32] = kregs->NDS32_ipc;
++ gregs[33] = kregs->NDS32_d0lo;
++ gregs[34] = kregs->NDS32_d0hi;
++ gregs[35] = kregs->NDS32_d1lo;
++ gregs[36] = kregs->NDS32_d1hi;
++ gregs[NDS32_IR0_REGNUM] = kregs->NDS32_ipsw;
++}
++
++// ============================================================================
++// gdb_regs_to_regs()
++//
++// Copy local gdb registers back to kgdb regs, for later copy to kernel.
++// ============================================================================
++void gdb_regs_to_pt_regs(unsigned long *gregs, struct pt_regs *kregs)
++{
++ kregs->NDS32_r0 = gregs[0];
++ kregs->NDS32_r1 = gregs[1];
++ kregs->NDS32_r2 = gregs[2];
++ kregs->NDS32_r3 = gregs[3];
++ kregs->NDS32_r4 = gregs[4];
++ kregs->NDS32_r5 = gregs[5];
++ kregs->NDS32_r6 = gregs[6];
++ kregs->NDS32_r7 = gregs[7];
++ kregs->NDS32_r8 = gregs[8];
++ kregs->NDS32_r9 = gregs[9];
++ kregs->NDS32_r10 = gregs[10];
++ kregs->NDS32_r11 = gregs[11];
++ kregs->NDS32_r12 = gregs[12];
++ kregs->NDS32_r13 = gregs[13];
++ kregs->NDS32_r14 = gregs[14];
++ kregs->NDS32_r15 = gregs[15];
++ kregs->NDS32_r16 = gregs[16];
++ kregs->NDS32_r17 = gregs[17];
++ kregs->NDS32_r18 = gregs[18];
++ kregs->NDS32_r19 = gregs[19];
++ kregs->NDS32_r20 = gregs[20];
++ kregs->NDS32_r21 = gregs[21];
++ kregs->NDS32_r22 = gregs[22];
++ kregs->NDS32_r23 = gregs[23];
++ kregs->NDS32_r24 = gregs[24];
++ kregs->NDS32_r25 = gregs[25];
++ kregs->NDS32_pp0 = gregs[26];
++ kregs->NDS32_pp1 = gregs[27];
++ kregs->NDS32_fp = gregs[28];
++ kregs->NDS32_gp = gregs[29];
++ kregs->NDS32_lp = gregs[30];
++ kregs->NDS32_sp = gregs[31];
++ kregs->NDS32_ipc = gregs[32];
++ kregs->NDS32_d0lo = gregs[33];
++ kregs->NDS32_d0hi = gregs[34];
++ kregs->NDS32_d1lo = gregs[35];
++ kregs->NDS32_d1hi = gregs[36];
++ kregs->NDS32_ipsw = gregs[NDS32_IR0_REGNUM];
++}
++
++// ----------------------------------------------------------------------------
++// kgdb_get_user_regs()
++//
++// Get user process registers.
++// ----------------------------------------------------------------------------
++static inline struct pt_regs *kgdb_get_user_regs(struct task_struct *task)
++{
++ return (struct pt_regs *)
++ ((unsigned long)task_thread_info(task) + THREAD_SIZE -
++ 8 - sizeof(struct pt_regs));
++}
++
++// ============================================================================
++// sleeping_thread_to_gdb_regs()
++//
++// ============================================================================
++void sleeping_thread_to_gdb_regs(unsigned long *gregs, struct task_struct *task)
++{
++ int regno;
++ struct pt_regs *tregs;
++
++ /* Just making sure... */
++ if (task == NULL)
++ return;
++
++ /* Initialize to zero */
++ for (regno = 0; regno < NDS32_NUM_REGS; regno++)
++ gregs[regno] = 0;
++
++ /* Otherwise, we have only some registers from switch_to() */
++ tregs = kgdb_get_user_regs(task);
++
++ gregs[0] = tregs->NDS32_r0;
++ gregs[1] = tregs->NDS32_r1;
++ gregs[2] = tregs->NDS32_r2;
++ gregs[3] = tregs->NDS32_r3;
++ gregs[4] = tregs->NDS32_r4;
++ gregs[5] = tregs->NDS32_r5;
++ gregs[6] = tregs->NDS32_r6;
++ gregs[7] = tregs->NDS32_r7;
++ gregs[8] = tregs->NDS32_r8;
++ gregs[9] = tregs->NDS32_r9;
++ gregs[10] = tregs->NDS32_r10;
++ gregs[11] = tregs->NDS32_r11;
++ gregs[12] = tregs->NDS32_r12;
++ gregs[13] = tregs->NDS32_r13;
++ gregs[14] = tregs->NDS32_r14;
++ gregs[15] = tregs->NDS32_r15;
++ gregs[16] = tregs->NDS32_r16;
++ gregs[17] = tregs->NDS32_r17;
++ gregs[18] = tregs->NDS32_r18;
++ gregs[19] = tregs->NDS32_r19;
++ gregs[20] = tregs->NDS32_r20;
++ gregs[21] = tregs->NDS32_r21;
++ gregs[22] = tregs->NDS32_r22;
++ gregs[23] = tregs->NDS32_r23;
++ gregs[24] = tregs->NDS32_r24;
++ gregs[25] = tregs->NDS32_r25;
++ gregs[26] = tregs->NDS32_pp0;
++ gregs[27] = tregs->NDS32_pp1;
++ gregs[28] = tregs->NDS32_fp;
++ gregs[29] = tregs->NDS32_gp;
++ gregs[30] = tregs->NDS32_lp;
++ gregs[31] = tregs->NDS32_sp;
++ gregs[32] = tregs->NDS32_ipc;
++ gregs[33] = tregs->NDS32_d0lo;
++ gregs[34] = tregs->NDS32_d0hi;
++ gregs[35] = tregs->NDS32_d1lo;
++ gregs[36] = tregs->NDS32_d1hi;
++ gregs[NDS32_IR0_REGNUM] = tregs->NDS32_ipsw;
++}
++
++int kgdb_arch_handle_exception(int exception_vector, int signo,
++ int err_code, char *remcom_in_buffer,
++ char *remcom_out_buffer,
++ struct pt_regs *linux_regs)
++{
++ long addr;
++ char *ptr;
++
++ if (0 == atomic_dec_if_positive(&kgdb_setting_breakpoint))
++ linux_regs->NDS32_ipc += 2;
++
++ switch (remcom_in_buffer[0]) {
++ case 'k':
++ case 'D':
++ case 'c':
++ case 's':
++ kgdb_contthread = NULL;
++
++ /*
++ * Try to read optional parameter, pc unchanged if no parm.
++ * If this was a compiled breakpoint, we need to move
++ * to the next instruction or we will just breakpoint
++ * over and over again.
++ */
++ ptr = &remcom_in_buffer[1];
++ if (kgdb_hex2long(&ptr, &addr)) {
++ linux_regs->NDS32_ipc = addr;
++ }
++ linux_regs->NDS32_ipsw &= ~0x800;
++ if (remcom_in_buffer[0] == 's') {
++ linux_regs->NDS32_ipsw |= 0x800;
++ }
++
++ return 0;
++ }
++
++ return -1;
++}
++
++static int kgdb_notify(struct notifier_block *self,
++ unsigned long cmd, void *ptr)
++{
++ struct die_args *args = ptr;
++ unsigned long addr = args->err;
++ if (addr > TASK_SIZE) {
++ kgdb_handle_exception(args->trapnr, args->signr,
++ args->err, args->regs);
++ return NOTIFY_STOP;
++ }
++ return NOTIFY_DONE;
++}
++
++static struct notifier_block kgdb_notifier = {
++ .notifier_call = kgdb_notify,
++};
++
++int kgdb_arch_init(void)
++{
++ register_die_notifier(&kgdb_notifier);
++}
++
++void kgdb_arch_exit(void)
++{
++ unregister_die_notifier(&kgdb_notifier);
++}
++
++struct kgdb_arch arch_kgdb_ops = {
++#ifdef __NDS32_EL__
++ .gdb_bpt_instr = {0xeb, 0xff}
++#else
++ .gdb_bpt_instr = {0xff, 0xeb}
++#endif
++};
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/kprobes.c linux-3.4.110/arch/nds32/kernel/kprobes.c
+--- linux-3.4.110.orig/arch/nds32/kernel/kprobes.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/kprobes.c 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,869 @@
++/*
++ * Kernel Probes (KProbes)
++ *
++ * 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.
++ *
++ * Copyright (C) IBM Corporation, 2002, 2004
++ *
++ * 2002-Oct Created by Vamsi Krishna S <vamsi_krishna@in.ibm.com> Kernel
++ * Probes initial implementation ( includes contributions from
++ * Rusty Russell).
++ * 2004-July Suparna Bhattacharya <suparna@in.ibm.com> added jumper probes
++ * interface to access function arguments.
++ * 2004-Oct Jim Keniston <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
++ * <prasanna@in.ibm.com> adapted for x86_64 from i386.
++ * 2005-Mar Roland McGrath <roland@redhat.com>
++ * Fixed to handle %rip-relative addressing mode correctly.
++ * 2005-May Hien Nguyen <hien@us.ibm.com>, Jim Keniston
++ * <jkenisto@us.ibm.com> and Prasanna S Panchamukhi
++ * <prasanna@in.ibm.com> added function-return probes.
++ * 2005-May Rusty Lynch <rusty.lynch@intel.com>
++ * Added function return probes functionality
++ * 2006-Feb Masami Hiramatsu <hiramatu@sdl.hitachi.co.jp> added
++ * kprobe-booster and kretprobe-booster for i386.
++ * 2007-Dec Masami Hiramatsu <mhiramat@redhat.com> added kprobe-booster
++ * and kretprobe-booster for x86-64
++ * 2007-Dec Masami Hiramatsu <mhiramat@redhat.com>, Arjan van de Ven
++ * <arjan@infradead.org> and Jim Keniston <jkenisto@us.ibm.com>
++ * unified x86 kprobes code.
++ */
++
++#include <linux/kprobes.h>
++#include <linux/ptrace.h>
++#include <linux/string.h>
++#include <linux/slab.h>
++#include <linux/hardirq.h>
++#include <linux/preempt.h>
++#include <linux/module.h>
++#include <linux/kdebug.h>
++
++#include <asm/cacheflush.h>
++#include <asm/uaccess.h>
++
++#ifdef __NDS32_EL__
++#define SZINSN(insn) (((insn & 0x00000080) == 0) ? 4 : 2)
++#define BREAK16_1FE 0xFEEB
++#else
++#define SZINSN(insn) (((insn & 0x80000000) == 0) ? 4 : 2)
++#define BREAK16_1FE 0xEBFE
++#endif
++
++void jprobe_return_point(void);
++
++DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
++DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
++
++#if 0
++/* Insert a jump instruction at address 'from', which jumps to address 'to'.*/
++static void __kprobes set_jmp_op(void *from, void *to)
++{
++ struct __arch_jmp_op {
++ char op;
++ s32 raddr;
++ } __attribute__ ((packed)) * jop;
++ jop = (struct __arch_jmp_op *)from;
++ jop->raddr = (s32) ((long)(to) - ((long)(from) + 5));
++ jop->op = RELATIVEJUMP_INSTRUCTION;
++}
++
++/*
++ * Check for the REX prefix which can only exist on X86_64
++ * X86_32 always returns 0
++ */
++static int __kprobes is_REX_prefix(kprobe_opcode_t * insn)
++{
++#ifdef CONFIG_X86_64
++ if ((*insn & 0xf0) == 0x40)
++ return 1;
++#endif
++ return 0;
++}
++
++/*
++ * Returns non-zero if opcode is boostable.
++ * RIP relative instructions are adjusted at copying time in 64 bits mode
++ */
++static int __kprobes can_boost(kprobe_opcode_t * opcodes)
++{
++ kprobe_opcode_t opcode;
++ kprobe_opcode_t *orig_opcodes = opcodes;
++
++ if (search_exception_tables(opcodes))
++ return 0; /* Page fault may occur on this address. */
++
++retry:
++ if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
++ return 0;
++ opcode = *(opcodes++);
++
++ /* 2nd-byte opcode */
++ if (opcode == 0x0f) {
++ if (opcodes - orig_opcodes > MAX_INSN_SIZE - 1)
++ return 0;
++ return test_bit(*opcodes,
++ (unsigned long *)twobyte_is_boostable);
++ }
++
++ switch (opcode & 0xf0) {
++#ifdef CONFIG_X86_64
++ case 0x40:
++ goto retry; /* REX prefix is boostable */
++#endif
++ case 0x60:
++ if (0x63 < opcode && opcode < 0x67)
++ goto retry; /* prefixes */
++ /* can't boost Address-size override and bound */
++ return (opcode != 0x62 && opcode != 0x67);
++ case 0x70:
++ return 0; /* can't boost conditional jump */
++ case 0xc0:
++ /* can't boost software-interruptions */
++ return (0xc1 < opcode && opcode < 0xcc) || opcode == 0xcf;
++ case 0xd0:
++ /* can boost AA* and XLAT */
++ return (opcode == 0xd4 || opcode == 0xd5 || opcode == 0xd7);
++ case 0xe0:
++ /* can boost in/out and absolute jmps */
++ return ((opcode & 0x04) || opcode == 0xea);
++ case 0xf0:
++ if ((opcode & 0x0c) == 0 && opcode != 0xf1)
++ goto retry; /* lock/rep(ne) prefix */
++ /* clear and set flags are boostable */
++ return (opcode == 0xf5 || (0xf7 < opcode && opcode < 0xfe));
++ default:
++ /* segment override prefixes are boostable */
++ if (opcode == 0x26 || opcode == 0x36 || opcode == 0x3e)
++ goto retry; /* prefixes */
++ /* CS override prefix and call are not boostable */
++ return (opcode != 0x2e && opcode != 0x9a);
++ }
++}
++
++/*
++ * Returns non-zero if opcode modifies the interrupt flag.
++ */
++static int __kprobes is_IF_modifier(kprobe_opcode_t * insn)
++{
++ switch (*insn) {
++ case 0xfa: /* cli */
++ case 0xfb: /* sti */
++ case 0xcf: /* iret/iretd */
++ case 0x9d: /* popf/popfd */
++ return 1;
++ }
++
++ /*
++ * on X86_64, 0x40-0x4f are REX prefixes so we need to look
++ * at the next byte instead.. but of course not recurse infinitely
++ */
++ if (is_REX_prefix(insn))
++ return is_IF_modifier(++insn);
++
++ return 0;
++}
++
++/*
++ * Adjust the displacement if the instruction uses the %rip-relative
++ * addressing mode.
++ * If it does, Return the address of the 32-bit displacement word.
++ * If not, return null.
++ * Only applicable to 64-bit x86.
++ */
++static void __kprobes fix_riprel(struct kprobe *p)
++{
++#ifdef CONFIG_X86_64
++ u8 *insn = p->ainsn.insn;
++ s64 disp;
++ int need_modrm;
++
++ /* Skip legacy instruction prefixes. */
++ while (1) {
++ switch (*insn) {
++ case 0x66:
++ case 0x67:
++ case 0x2e:
++ case 0x3e:
++ case 0x26:
++ case 0x64:
++ case 0x65:
++ case 0x36:
++ case 0xf0:
++ case 0xf3:
++ case 0xf2:
++ ++insn;
++ continue;
++ }
++ break;
++ }
++
++ /* Skip REX instruction prefix. */
++ if (is_REX_prefix(insn))
++ ++insn;
++
++ if (*insn == 0x0f) {
++ /* Two-byte opcode. */
++ ++insn;
++ need_modrm = test_bit(*insn,
++ (unsigned long *)twobyte_has_modrm);
++ } else
++ /* One-byte opcode. */
++ need_modrm = test_bit(*insn,
++ (unsigned long *)onebyte_has_modrm);
++
++ if (need_modrm) {
++ u8 modrm = *++insn;
++ if ((modrm & 0xc7) == 0x05) {
++ /* %rip+disp32 addressing mode */
++ /* Displacement follows ModRM byte. */
++ ++insn;
++ /*
++ * The copied instruction uses the %rip-relative
++ * addressing mode. Adjust the displacement for the
++ * difference between the original location of this
++ * instruction and the location of the copy that will
++ * actually be run. The tricky bit here is making sure
++ * that the sign extension happens correctly in this
++ * calculation, since we need a signed 32-bit result to
++ * be sign-extended to 64 bits when it's added to the
++ * %rip value and yield the same 64-bit result that the
++ * sign-extension of the original signed 32-bit
++ * displacement would have given.
++ */
++ disp = (u8 *) p->addr + *((s32 *) insn) -
++ (u8 *) p->ainsn.insn;
++ BUG_ON((s64) (s32) disp != disp); /* Sanity check. */
++ *(s32 *) insn = (s32) disp;
++ }
++ }
++#endif
++}
++#endif
++
++static void __kprobes arch_copy_kprobe(struct kprobe *p)
++{
++ memcpy(p->ainsn.insn, p->addr, MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
++ flush_icache_range((unsigned long)p->ainsn.insn,
++ (unsigned long)p->ainsn.insn +
++ MAX_INSN_SIZE * sizeof(kprobe_opcode_t));
++
++// fix_riprel(p);
++
++// if (can_boost(p->addr))
++// p->ainsn.boostable = 0;
++// else
++ p->ainsn.boostable = -1;
++
++ p->opcode = *p->addr;
++}
++
++int __kprobes arch_prepare_kprobe(struct kprobe *p)
++{
++ /* insn: must be on special executable page on x86. */
++ p->ainsn.insn = get_insn_slot();
++ if (!p->ainsn.insn)
++ return -ENOMEM;
++ arch_copy_kprobe(p);
++ return 0;
++}
++
++void __kprobes arch_arm_kprobe(struct kprobe *p)
++{
++ *p->addr = BREAK16_1FE;
++ flush_icache_range((unsigned long)p->addr,
++ (unsigned long)p->addr + sizeof(kprobe_opcode_t));
++}
++
++void __kprobes arch_disarm_kprobe(struct kprobe *p)
++{
++ *p->addr = p->opcode;
++ flush_icache_range((unsigned long)p->addr,
++ (unsigned long)p->addr + sizeof(kprobe_opcode_t));
++}
++
++void __kprobes arch_remove_kprobe(struct kprobe *p)
++{
++ if (p->ainsn.insn) {
++ free_insn_slot(p->ainsn.insn, (p->ainsn.boostable == 1));
++ p->ainsn.insn = NULL;
++ }
++}
++
++static void __kprobes save_previous_kprobe(struct kprobe_ctlblk *kcb)
++{
++ kcb->prev_kprobe.kp = kprobe_running();
++ kcb->prev_kprobe.status = kcb->kprobe_status;
++ kcb->prev_kprobe.old_flags = kcb->kprobe_old_flags;
++ kcb->prev_kprobe.saved_flags = kcb->kprobe_saved_flags;
++}
++
++static void __kprobes restore_previous_kprobe(struct kprobe_ctlblk *kcb)
++{
++ __get_cpu_var(current_kprobe) = kcb->prev_kprobe.kp;
++ kcb->kprobe_status = kcb->prev_kprobe.status;
++ kcb->kprobe_old_flags = kcb->prev_kprobe.old_flags;
++ kcb->kprobe_saved_flags = kcb->prev_kprobe.saved_flags;
++}
++
++static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
++ struct kprobe_ctlblk *kcb)
++{
++ __get_cpu_var(current_kprobe) = p;
++// kcb->kprobe_saved_flags = kcb->kprobe_old_flags
++// = regs->NDS32_ipsw & PSW_mskHSS;
++}
++
++static void __kprobes prepare_singlestep(struct kprobe *p, struct pt_regs *regs)
++{
++ regs->NDS32_ipsw |= PSW_mskHSS;
++ /* single step inline if the instruction is an int3 */
++// if (p->opcode == BREAK16_1FE)
++// regs->NDS32_ipc = (unsigned long)p->addr;
++// else
++ regs->NDS32_ipc = (unsigned long)p->ainsn.insn;
++}
++
++void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
++ struct pt_regs *regs)
++{
++ ri->ret_addr = (kprobe_opcode_t *) regs->NDS32_lp;
++ regs->NDS32_lp = (unsigned long)&kretprobe_trampoline;
++}
++
++static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs,
++ struct kprobe_ctlblk *kcb)
++{
++#if !defined(CONFIG_PREEMPT) || defined(CONFIG_FREEZER)
++ if (p->ainsn.boostable == 1 && !p->post_handler) {
++ /* Boost up -- we can execute copied instructions directly */
++ reset_current_kprobe();
++ regs->NDS32_ipc = (unsigned long)p->ainsn.insn;
++ preempt_enable_no_resched();
++ return;
++ }
++#endif
++ prepare_singlestep(p, regs);
++ kcb->kprobe_status = KPROBE_HIT_SS;
++}
++
++/*
++ * We have reentered the kprobe_handler(), since another probe was hit while
++ * within the handler. We save the original kprobes variables and just single
++ * step on the instruction of the new probe without calling any user handlers.
++ */
++static int __kprobes reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
++ struct kprobe_ctlblk *kcb)
++{
++ switch (kcb->kprobe_status) {
++#if 0
++ case KPROBE_HIT_SSDONE:
++#ifdef CONFIG_X86_64
++ /* TODO: Provide re-entrancy from post_kprobes_handler() and
++ * avoid exception stack corruption while single-stepping on
++ * the instruction of the new probe.
++ */
++ arch_disarm_kprobe(p);
++ regs->ip = (unsigned long)p->addr;
++ reset_current_kprobe();
++ preempt_enable_no_resched();
++ break;
++#endif
++#endif
++ case KPROBE_HIT_ACTIVE:
++ save_previous_kprobe(kcb);
++ set_current_kprobe(p, regs, kcb);
++ kprobes_inc_nmissed_count(p);
++ prepare_singlestep(p, regs);
++ kcb->kprobe_status = KPROBE_REENTER;
++ break;
++ case KPROBE_HIT_SS:
++ if (p == kprobe_running()) {
++ regs->NDS32_ipc &= ~PSW_mskHSS;
++// regs->NDS32_ipc |= kcb->kprobe_saved_flags;
++ return 0;
++ } else {
++ /* A probe has been hit in the codepath leading up
++ * to, or just after, single-stepping of a probed
++ * instruction. This entire codepath should strictly
++ * reside in .kprobes.text section. Raise a warning
++ * to highlight this peculiar case.
++ */
++ }
++ default:
++ /* impossible cases */
++ WARN_ON(1);
++ return 0;
++ }
++
++ return 1;
++}
++
++/*
++ * Interrupts are disabled on entry as trap3 is an interrupt gate and they
++ * remain disabled thorough out this function.
++ */
++static int __kprobes kprobe_handler(struct pt_regs *regs)
++{
++ kprobe_opcode_t *addr;
++ struct kprobe *p;
++ struct kprobe_ctlblk *kcb;
++
++ addr = (kprobe_opcode_t *) regs->NDS32_ipc;
++ if (*addr != BREAK16_1FE) {
++ /*
++ * The breakpoint instruction was removed right
++ * after we hit it. Another cpu has removed
++ * either a probepoint or a debugger breakpoint
++ * at this address. In either case, no further
++ * handling of this interrupt is appropriate.
++ * Back up over the (now missing) int3 and run
++ * the original instruction.
++ */
++ return 1;
++ }
++
++ /*
++ * We don't want to be preempted for the entire
++ * duration of kprobe processing. We conditionally
++ * re-enable preemption at the end of this function,
++ * and also in reenter_kprobe() and setup_singlestep().
++ */
++ preempt_disable();
++
++ kcb = get_kprobe_ctlblk();
++ p = get_kprobe(addr);
++
++ if (p) {
++ if (kprobe_running()) {
++ if (reenter_kprobe(p, regs, kcb))
++ return 1;
++ } else {
++ set_current_kprobe(p, regs, kcb);
++ kcb->kprobe_status = KPROBE_HIT_ACTIVE;
++
++ /*
++ * If we have no pre-handler or it returned 0, we
++ * continue with normal processing. If we have a
++ * pre-handler and it returned non-zero, it prepped
++ * for calling the break_handler below on re-entry
++ * for jprobe processing, so get out doing nothing
++ * more here.
++ */
++ if (!p->pre_handler || !p->pre_handler(p, regs))
++ setup_singlestep(p, regs, kcb);
++ return 1;
++ }
++ } else if (kprobe_running()) {
++ p = __get_cpu_var(current_kprobe);
++ if (p->break_handler && p->break_handler(p, regs)) {
++ setup_singlestep(p, regs, kcb);
++ return 1;
++ }
++ }
++ /* else: not a kprobe fault; let the kernel handle it */
++ preempt_enable_no_resched();
++ return 0;
++}
++
++/*
++ * When a retprobed function returns, this code saves registers and
++ * calls trampoline_handler() runs, which calls the kretprobe's handler.
++ */
++static void __used __kprobes kretprobe_trampoline_holder(void)
++{
++ asm volatile (".global kretprobe_trampoline \n"
++ "kretprobe_trampoline: \n"
++ "smw.adm $r15, [$sp], $r15, #0x0\n"
++ "smw.adm $r0, [$sp], $r5, #0x1 \n"
++ "addi $r0, $sp, #-76 \n"
++ "bal trampoline_handler \n"
++ "move $lp, $r0 \n"
++ "lmw.bim $r0, [$sp], $r5, #0x1 \n"
++ "lmw.bim $r15, [$sp], $r15, #0x0\n"
++ "ret \n");
++}
++
++/*
++ * Called from kretprobe_trampoline
++ */
++static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
++{
++ struct kretprobe_instance *ri = NULL;
++ struct hlist_head *head, empty_rp;
++ struct hlist_node *node, *tmp;
++ unsigned long flags, orig_ret_address = 0;
++ unsigned long trampoline_address = (unsigned long)&kretprobe_trampoline;
++
++ INIT_HLIST_HEAD(&empty_rp);
++ kretprobe_hash_lock(current, &head, &flags);
++
++ /*
++ * It is possible to have multiple instances associated with a given
++ * task either because multiple functions in the call path have
++ * return probes installed on them, and/or more than one
++ * return probe was registered for a target function.
++ *
++ * We can handle this because:
++ * - instances are always pushed into the head of the list
++ * - when multiple return probes are registered for the same
++ * function, the (chronologically) first instance's ret_addr
++ * will be the real return address, and all the rest will
++ * point to kretprobe_trampoline.
++ */
++ hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
++ if (ri->task != current)
++ /* another task is sharing our hash bucket */
++ continue;
++
++ if (ri->rp && ri->rp->handler) {
++ __get_cpu_var(current_kprobe) = &ri->rp->kp;
++ get_kprobe_ctlblk()->kprobe_status = KPROBE_HIT_ACTIVE;
++ ri->rp->handler(ri, regs);
++ __get_cpu_var(current_kprobe) = NULL;
++ }
++
++ orig_ret_address = (unsigned long)ri->ret_addr;
++ recycle_rp_inst(ri, &empty_rp);
++
++ if (orig_ret_address != trampoline_address)
++ /*
++ * This is the real return address. Any other
++ * instances associated with this task are for
++ * other calls deeper on the call stack
++ */
++ break;
++ }
++
++ kretprobe_assert(ri, orig_ret_address, trampoline_address);
++
++ kretprobe_hash_unlock(current, &flags);
++
++ hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
++ hlist_del(&ri->hlist);
++ kfree(ri);
++ }
++ return (void *)orig_ret_address;
++}
++
++/*
++ * Called after single-stepping. p->addr is the address of the
++ * instruction whose first byte has been replaced by the "int 3"
++ * instruction. To avoid the SMP problems that can occur when we
++ * temporarily put back the original opcode to single-step, we
++ * single-stepped a copy of the instruction. The address of this
++ * copy is p->ainsn.insn.
++ *
++ * This function prepares to return from the post-single-step
++ * interrupt. We have to fix up the stack as follows:
++ *
++ * 0) Except in the case of absolute or indirect jump or call instructions,
++ * the new ip is relative to the copied instruction. We need to make
++ * it relative to the original instruction.
++ *
++ * 1) If the single-stepped instruction was pushfl, then the TF and IF
++ * flags are set in the just-pushed flags, and may need to be cleared.
++ *
++ * 2) If the single-stepped instruction was a call, the return address
++ * that is atop the stack is the address following the copied instruction.
++ * We need to make it the address following the original instruction.
++ *
++ * If this is the first time we've single-stepped the instruction at
++ * this probepoint, and the instruction is boostable, boost it: add a
++ * jump instruction after the copied instruction, that jumps to the next
++ * instruction after the probepoint.
++ */
++static void __kprobes resume_execution(struct kprobe *p,
++ struct pt_regs *regs,
++ struct kprobe_ctlblk *kcb)
++{
++// unsigned long *tos = stack_addr(regs);
++// unsigned long copy_ip = (unsigned long)p->ainsn.insn;
++// unsigned long orig_ip = (unsigned long)p->addr;
++ kprobe_opcode_t *insn = p->ainsn.insn;
++ unsigned long rawinsn = *(unsigned long *)insn;
++ int size = SZINSN(rawinsn);
++ regs->NDS32_ipc = (unsigned long)p->addr + size;
++ regs->NDS32_ipsw &= ~PSW_mskHSS;
++#if 0
++
++ /*skip the REX prefix */
++ if (is_REX_prefix(insn))
++ insn++;
++
++ regs->flags &= ~X86_EFLAGS_TF;
++ switch (*insn) {
++ case 0x9c: /* pushfl */
++ *tos &= ~(X86_EFLAGS_TF | X86_EFLAGS_IF);
++ *tos |= kcb->kprobe_old_flags;
++ break;
++ case 0xc2: /* iret/ret/lret */
++ case 0xc3:
++ case 0xca:
++ case 0xcb:
++ case 0xcf:
++ case 0xea: /* jmp absolute -- ip is correct */
++ /* ip is already adjusted, no more changes required */
++ p->ainsn.boostable = 1;
++ goto no_change;
++ case 0xe8: /* call relative - Fix return addr */
++ *tos = orig_ip + (*tos - copy_ip);
++ break;
++#ifdef CONFIG_X86_32
++ case 0x9a: /* call absolute -- same as call absolute, indirect */
++ *tos = orig_ip + (*tos - copy_ip);
++ goto no_change;
++#endif
++ case 0xff:
++ if ((insn[1] & 0x30) == 0x10) {
++ /*
++ * call absolute, indirect
++ * Fix return addr; ip is correct.
++ * But this is not boostable
++ */
++ *tos = orig_ip + (*tos - copy_ip);
++ goto no_change;
++ } else if (((insn[1] & 0x31) == 0x20) ||
++ ((insn[1] & 0x31) == 0x21)) {
++ /*
++ * jmp near and far, absolute indirect
++ * ip is correct. And this is boostable
++ */
++ p->ainsn.boostable = 1;
++ goto no_change;
++ }
++ default:
++ break;
++ }
++
++ if (p->ainsn.boostable == 0) {
++ if ((regs->ip > copy_ip) &&
++ (regs->ip - copy_ip) + 5 < MAX_INSN_SIZE) {
++ /*
++ * These instructions can be executed directly if it
++ * jumps back to correct address.
++ */
++ set_jmp_op((void *)regs->ip,
++ (void *)orig_ip + (regs->ip - copy_ip));
++ p->ainsn.boostable = 1;
++ } else {
++ p->ainsn.boostable = -1;
++ }
++ }
++
++ regs->ip += orig_ip - copy_ip;
++
++no_change:
++ restore_btf();
++#endif
++}
++
++/*
++ * Interrupts are disabled on entry as trap1 is an interrupt gate and they
++ * remain disabled thoroughout this function.
++ */
++static int __kprobes post_kprobe_handler(struct pt_regs *regs)
++{
++ struct kprobe *cur = kprobe_running();
++ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
++
++ if (!cur)
++ return 0;
++
++ resume_execution(cur, regs, kcb);
++ regs->NDS32_ipsw |= kcb->kprobe_saved_flags;
++
++ if ((kcb->kprobe_status != KPROBE_REENTER) && cur->post_handler) {
++ kcb->kprobe_status = KPROBE_HIT_SSDONE;
++ cur->post_handler(cur, regs, 0);
++ }
++
++ /* Restore back the original saved kprobes variables and continue. */
++ if (kcb->kprobe_status == KPROBE_REENTER) {
++ restore_previous_kprobe(kcb);
++ goto out;
++ }
++ reset_current_kprobe();
++out:
++ preempt_enable_no_resched();
++
++ /*
++ * if somebody else is singlestepping across a probe point, flags
++ * will have TF set, in which case, continue the remaining processing
++ * of do_debug, as if this is not a probe hit.
++ */
++ if (regs->NDS32_ipsw & PSW_mskHSS)
++ return 0;
++
++ return 1;
++}
++
++int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
++{
++ struct kprobe *cur = kprobe_running();
++ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
++
++ switch (kcb->kprobe_status) {
++ case KPROBE_HIT_SS:
++ case KPROBE_REENTER:
++ /*
++ * We are here because the instruction being single
++ * stepped caused a page fault. We reset the current
++ * kprobe and the ip points back to the probe address
++ * and allow the page fault handler to continue as a
++ * normal page fault.
++ */
++ regs->NDS32_ipc = (unsigned long)cur->addr;
++ regs->NDS32_ipsw |= kcb->kprobe_old_flags;
++ if (kcb->kprobe_status == KPROBE_REENTER)
++ restore_previous_kprobe(kcb);
++ else
++ reset_current_kprobe();
++ preempt_enable_no_resched();
++ break;
++ case KPROBE_HIT_ACTIVE:
++ case KPROBE_HIT_SSDONE:
++ /*
++ * We increment the nmissed count for accounting,
++ * we can also use npre/npostfault count for accounting
++ * these specific fault cases.
++ */
++ kprobes_inc_nmissed_count(cur);
++
++ /*
++ * We come here because instructions in the pre/post
++ * handler caused the page_fault, this could happen
++ * if handler tries to access user space by
++ * copy_from_user(), get_user() etc. Let the
++ * user-specified handler try to fix it first.
++ */
++ if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
++ return 1;
++
++ /*
++ * In case the user-specified fault handler returned
++ * zero, try to fix up.
++ */
++ if (fixup_exception(regs))
++ return 1;
++
++ /*
++ * fixup routine could not handle it,
++ * Let do_page_fault() fix it.
++ */
++ break;
++ default:
++ break;
++ }
++ return 0;
++}
++
++/*
++ * Wrapper routine for handling exceptions.
++ */
++int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
++ unsigned long val, void *data)
++{
++ struct die_args *args = data;
++ int ret = NOTIFY_DONE;
++ int why = args->trapnr & 0xf;
++
++ if (args->regs && user_mode(args->regs))
++ return ret;
++
++ switch (why) {
++ case 1:
++ if (kprobe_handler(args->regs))
++ ret = NOTIFY_STOP;
++ break;
++ case 7:
++ if (post_kprobe_handler(args->regs))
++ ret = NOTIFY_STOP;
++ break;
++ default:
++ break;
++ }
++ return ret;
++}
++
++int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
++{
++ struct jprobe *jp = container_of(p, struct jprobe, kp);
++ unsigned long addr;
++ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
++
++ kcb->jprobe_saved_regs = *regs;
++ kcb->jprobe_saved_sp = regs->NDS32_sp;
++ addr = (unsigned long)(kcb->jprobe_saved_sp);
++
++ /*
++ * As Linus pointed out, gcc assumes that the callee
++ * owns the argument space and could overwrite it, e.g.
++ * tailcall optimization. So, to be absolutely safe
++ * we also save and restore enough stack bytes to cover
++ * the argument area.
++ */
++ memcpy(kcb->jprobes_stack, (kprobe_opcode_t *) addr,
++ MIN_STACK_SIZE(addr));
++ regs->NDS32_ipsw &= ~PSW_mskGIE;
++ trace_hardirqs_off();
++ regs->NDS32_ipc = (unsigned long)(jp->entry);
++ return 1;
++}
++
++void __kprobes jprobe_return(void)
++{
++ struct kprobe_ctlblk *kcd = get_kprobe_ctlblk();
++ asm volatile (" move $sp, %0\n"
++ " .globl jprobe_return_point\n"
++ " jprobe_return_point: \n"
++ " break #0x1fe \n"::"r" (kcd->
++ jprobe_saved_sp));
++}
++
++int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
++{
++ struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
++ struct jprobe *jp = container_of(p, struct jprobe, kp);
++
++ if (regs->NDS32_ipc == jprobe_return_point) {
++ if (regs->NDS32_sp != kcb->jprobe_saved_sp) {
++ struct pt_regs *saved_regs = &kcb->jprobe_saved_regs;
++ printk(KERN_ERR
++ "current sp %p does not match saved sp %p\n",
++ regs->NDS32_sp, kcb->jprobe_saved_sp);
++ printk(KERN_ERR "Saved registers for jprobe %p\n", jp);
++ show_regs(saved_regs);
++ printk(KERN_ERR "Current registers\n");
++ show_regs(regs);
++ BUG();
++ }
++ *regs = kcb->jprobe_saved_regs;
++ memcpy((kprobe_opcode_t *) (kcb->jprobe_saved_sp),
++ kcb->jprobes_stack,
++ MIN_STACK_SIZE(kcb->jprobe_saved_sp));
++ preempt_enable_no_resched();
++ return 1;
++ }
++ return 0;
++}
++
++int __init arch_init_kprobes(void)
++{
++ return 0;
++}
++
++int __kprobes arch_trampoline_kprobe(struct kprobe *p)
++{
++ return 0;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/machine_kexec.c linux-3.4.110/arch/nds32/kernel/machine_kexec.c
+--- linux-3.4.110.orig/arch/nds32/kernel/machine_kexec.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/machine_kexec.c 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,80 @@
++/*
++ * machine_kexec.c - handle transition of Linux booting another kernel
++ */
++
++#include <linux/mm.h>
++#include <linux/kexec.h>
++#include <linux/delay.h>
++#include <linux/reboot.h>
++#include <linux/io.h>
++#include <asm/pgtable.h>
++#include <asm/pgalloc.h>
++#include <asm/mmu_context.h>
++#include <asm/cacheflush.h>
++#include <asm/mach-types.h>
++
++extern const unsigned char relocate_new_kernel[];
++extern const unsigned int relocate_new_kernel_size;
++
++extern void setup_mm_for_reboot(char mode);
++
++extern unsigned long kexec_start_address;
++extern unsigned long kexec_indirection_page;
++extern unsigned long kexec_mach_type;
++extern unsigned long kexec_boot_atags;
++
++/*
++ * Provide a dummy crash_notes definition while crash dump arrives to nds32.
++ * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
++ */
++
++int machine_kexec_prepare(struct kimage *image)
++{
++ return 0;
++}
++
++void machine_kexec_cleanup(struct kimage *image)
++{
++}
++
++void machine_shutdown(void)
++{
++}
++
++void machine_crash_shutdown(struct pt_regs *regs)
++{
++}
++
++void machine_kexec(struct kimage *image)
++{
++ unsigned long page_list;
++ unsigned long reboot_code_buffer_phys;
++ void *reboot_code_buffer;
++
++ page_list = image->head & PAGE_MASK;
++
++ /* we need both effective and real address here */
++ reboot_code_buffer_phys =
++ page_to_pfn(image->control_code_page) << PAGE_SHIFT;
++ reboot_code_buffer = page_address(image->control_code_page);
++
++ /* Prepare parameters for reboot_code_buffer */
++ kexec_start_address = image->start;
++ kexec_indirection_page = page_list;
++ kexec_mach_type = machine_arch_type;
++ kexec_boot_atags =
++ image->start - KEXEC_NDS32_ZIMAGE_OFFSET + KEXEC_NDS32_ATAGS_OFFSET;
++
++ /* copy our kernel relocation code to the control code page */
++ memcpy(reboot_code_buffer,
++ relocate_new_kernel, relocate_new_kernel_size);
++
++ flush_icache_range((unsigned long)reboot_code_buffer,
++ (unsigned long)reboot_code_buffer +
++ KEXEC_CONTROL_PAGE_SIZE);
++ printk(KERN_INFO "Bye!\n");
++
++ cpu_proc_fin();
++ setup_mm_for_reboot(0); /* mode is not used, so just pass 0 */
++ cpu_reset(reboot_code_buffer_phys);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/Makefile linux-3.4.110/arch/nds32/kernel/Makefile
+--- linux-3.4.110.orig/arch/nds32/kernel/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/Makefile 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,45 @@
++#
++# Makefile for the linux kernel.
++#
++
++CPPFLAGS_vmlinux.lds +=-DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
++AFLAGS_head.o := -DTEXTADDR=$(TEXTADDR) -DDATAADDR=$(DATAADDR)
++
++# Object file lists.
++
++obj-y := ex-entry.o ex-exit.o ex-scall.o irq.o \
++ process.o ptrace.o setup.o signal.o \
++ sys_nds32.o time.o traps.o io.o proc.o \
++ elfchk.o
++ifdef CONFIG_FUNCTION_TRACER
++CFLAGS_REMOVE_ftrace.o = -pg
++CFLAGS_REMOVE_ex-entry.o = -pg
++CFLAGS_REMOVE_ex-exit.o = -pg
++CFLAGS_REMOVE_ex-scall.o = -pg
++CFLAGS_REMOVE_stacktrace.o = -pg
++CFLAGS_REMOVE_traps.o = -pg
++endif
++
++obj-$(CONFIG_MODULES) += nds32_ksyms.o module.o
++obj-$(CONFIG_ISA_DMA) += dma-isa.o
++obj-$(CONFIG_PCI) += bios32.o
++obj-$(CONFIG_SMP) += smp.o
++obj-$(CONFIG_KGDB) += kgdb.o
++obj-$(CONFIG_STACKTRACE) += stacktrace.o
++obj-$(CONFIG_KPROBES) += kprobes.o
++obj-$(CONFIG_FPU) += fpu.o
++obj-$(CONFIG_AUDIO) += audio.o
++obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
++obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
++obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
++
++extra-y := head.o init_task.o vmlinux.lds
++
++CFLAGS_fpu.o += \
++ $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_SP | sed -e 's/NDS32_EXT_FPU_SP/-mext-fpu-sp/') \
++ $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_DP | sed -e 's/NDS32_EXT_FPU_DP/-mext-fpu-dp/')
++ifdef CONFIG_FPU
++CFLAGS_elfchk.o += \
++ $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_SP | sed -e 's/NDS32_EXT_FPU_SP/-mext-fpu-sp/') \
++ $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_DP | sed -e 's/NDS32_EXT_FPU_DP/-mext-fpu-dp/')
++endif
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/module.c linux-3.4.110/arch/nds32/kernel/module.c
+--- linux-3.4.110.orig/arch/nds32/kernel/module.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/module.c 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,314 @@
++/*
++ * linux/arch/nds32/kernel/module.c
++ *
++ * Copyright (C) 2002 Russell King.
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Module allocation method suggested by Andi Kleen.
++ */
++#include <linux/module.h>
++#include <linux/elf.h>
++#include <linux/vmalloc.h>
++#include <linux/slab.h>
++#include <linux/mm.h>
++
++#include <asm/pgtable.h>
++
++#define DEBUG 0
++#if DEBUG
++#define PRINTK printk
++#else
++#define PRINTK(x...)
++#endif
++
++void *module_alloc(unsigned long size)
++{
++#ifdef CONFIG_KPROBES
++ if (size == 0)
++ return NULL;
++ return vmalloc_exec(size);
++#else
++ return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
++ GFP_KERNEL, PAGE_KERNEL, -1,
++ __builtin_return_address(0));
++#endif
++}
++
++void module_free(struct module *module, void *region)
++{
++ vfree(region);
++}
++
++int module_frob_arch_sections(Elf_Ehdr * hdr,
++ Elf_Shdr * sechdrs,
++ char *secstrings, struct module *mod)
++{
++ return 0;
++}
++
++void do_reloc16(unsigned int val, unsigned int *loc, unsigned int val_mask,
++ unsigned int val_shift, unsigned int loc_mask,
++ unsigned int partial_in_place, unsigned int swap)
++{
++ unsigned int tmp = 0, tmp2 = 0;
++
++ __asm__ __volatile__("\tlhi.bi\t%0, [%2], 0\n"
++ "\tbeqz\t%3, 1f\n"
++ "\twsbh\t%0, %1\n"
++ "1:\n":"=r"(tmp):"0"(tmp), "r"(loc), "r"(swap)
++ );
++
++ tmp2 = tmp & loc_mask;
++ if (partial_in_place) {
++ tmp &= (!loc_mask);
++ tmp =
++ tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
++ } else {
++ tmp = tmp2 | ((val & val_mask) >> val_shift);
++ }
++
++ __asm__ __volatile__("\tbeqz\t%3, 2f\n"
++ "\twsbh\t%0, %1\n"
++ "2:\n"
++ "\tshi.bi\t%0, [%2], 0\n":"=r"(tmp):"0"(tmp),
++ "r"(loc), "r"(swap)
++ );
++}
++
++void do_reloc32(unsigned int val, unsigned int *loc, unsigned int val_mask,
++ unsigned int val_shift, unsigned int loc_mask,
++ unsigned int partial_in_place, unsigned int swap)
++{
++ unsigned int tmp = 0, tmp2 = 0;
++
++ __asm__ __volatile__("\tlmw.bi\t%0, [%2], %0, 0\n"
++ "\tbeqz\t%3, 1f\n"
++ "\twsbh\t%0, %1\n"
++ "\trotri\t%0, %1, 16\n"
++ "1:\n":"=r"(tmp):"0"(tmp), "r"(loc), "r"(swap)
++ );
++
++ tmp2 = tmp & loc_mask;
++ if (partial_in_place) {
++ tmp &= (!loc_mask);
++ tmp =
++ tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
++ } else {
++ tmp = tmp2 | ((val & val_mask) >> val_shift);
++ }
++
++ __asm__ __volatile__("\tbeqz\t%3, 2f\n"
++ "\twsbh\t%0, %1\n"
++ "\trotri\t%0, %1, 16\n"
++ "2:\n"
++ "\tsmw.bi\t%0, [%2], %0, 0\n":"=r"(tmp):"0"(tmp),
++ "r"(loc), "r"(swap)
++ );
++}
++
++static inline int exceed_limit(int offset, unsigned int val_mask,
++ struct module *module, Elf32_Rela * rel,
++ unsigned int relindex, unsigned int reloc_order)
++{
++ int abs_off = offset < 0 ? ~offset : offset;
++
++ if (abs_off & (~val_mask)) {
++ printk(KERN_ERR "\n%s: relocation type %d out of range.\n"
++ "please rebuild the kernel module with gcc option \"-Wa,-mno-small-text\".\n",
++ module->name, ELF32_R_TYPE(rel->r_info));
++ PRINTK("section %d reloc %d offset 0x%x relative 0x%x.\n"
++ relindex, reloc_order, rel->r_offset, offset);
++ return true;
++ }
++ return false;
++}
++
++#ifdef __NDS32_EL__
++#define NEED_SWAP 1
++#else
++#define NEED_SWAP 0
++#endif
++
++int
++apply_relocate_add(Elf32_Shdr * sechdrs, const char *strtab,
++ unsigned int symindex, unsigned int relindex,
++ struct module *module)
++{
++ Elf32_Shdr *symsec = sechdrs + symindex;
++ Elf32_Shdr *relsec = sechdrs + relindex;
++ Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
++ Elf32_Rela *rel = (void *)relsec->sh_addr;
++ unsigned int i;
++
++ for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rela); i++, rel++) {
++ Elf32_Addr *loc;
++ Elf32_Sym *sym;
++ Elf32_Addr v;
++ s32 offset;
++
++ offset = ELF32_R_SYM(rel->r_info);
++ if (offset < 0
++ || offset > (symsec->sh_size / sizeof(Elf32_Sym))) {
++ printk(KERN_ERR "%s: bad relocation\n", module->name);
++ PRINTK("section %d reloc %d\n", module->name, relindex,
++ i);
++ return -ENOEXEC;
++ }
++
++ sym = ((Elf32_Sym *) symsec->sh_addr) + offset;
++
++ if (rel->r_offset < 0
++ || rel->r_offset > dstsec->sh_size - sizeof(u16)) {
++ printk(KERN_ERR "%s: out of bounds relocation\n",
++ module->name);
++ PRINTK("section %d reloc %d offset 0x%0x size %d\n",
++ relindex, i, rel->r_offset, dstsec->sh_size);
++ return -ENOEXEC;
++ }
++
++ loc = (Elf32_Addr *) (dstsec->sh_addr + rel->r_offset);
++ v = sym->st_value + rel->r_addend;
++
++ switch (ELF32_R_TYPE(rel->r_info)) {
++ case R_NDS32_NONE:
++ case R_NDS32_INSN16:
++ case R_NDS32_LABEL:
++ case R_NDS32_LONGCALL1:
++ case R_NDS32_LONGCALL2:
++ case R_NDS32_LONGCALL3:
++ case R_NDS32_LONGCALL4:
++ case R_NDS32_LONGJUMP1:
++ case R_NDS32_LONGJUMP2:
++ case R_NDS32_LONGJUMP3:
++ case R_NDS32_9_FIXED_RELA:
++ case R_NDS32_15_FIXED_RELA:
++ case R_NDS32_17_FIXED_RELA:
++ case R_NDS32_25_FIXED_RELA:
++ case R_NDS32_LOADSTORE:
++ case R_NDS32_DWARF2_OP1_RELA:
++ case R_NDS32_DWARF2_OP2_RELA:
++ case R_NDS32_DWARF2_LEB_RELA:
++ case R_NDS32_RELA_NOP_MIX...R_NDS32_RELA_NOP_MAX:
++ break;
++
++ case R_NDS32_32_RELA:
++ do_reloc32(v, loc, 0xffffffff, 0, 0, 0, 0);
++ break;
++
++ case R_NDS32_HI20_RELA:
++ do_reloc32(v, loc, 0xfffff000, 12, 0xfff00000, 0,
++ NEED_SWAP);
++ break;
++
++ case R_NDS32_LO12S3_RELA:
++ do_reloc32(v, loc, 0x00000fff, 3, 0xfffff000, 0,
++ NEED_SWAP);
++ break;
++
++ case R_NDS32_LO12S2_RELA:
++ do_reloc32(v, loc, 0x00000fff, 2, 0xfffff000, 0,
++ NEED_SWAP);
++ break;
++
++ case R_NDS32_LO12S1_RELA:
++ do_reloc32(v, loc, 0x00000fff, 1, 0xfffff000, 0,
++ NEED_SWAP);
++ break;
++
++ case R_NDS32_LO12S0_RELA:
++ case R_NDS32_LO12S0_ORI_RELA:
++ do_reloc32(v, loc, 0x00000fff, 0, 0xfffff000, 0,
++ NEED_SWAP);
++ break;
++
++ case R_NDS32_9_PCREL_RELA:
++ if (exceed_limit
++ ((v - (Elf32_Addr) loc), 0x000000ff, module, rel,
++ relindex, i))
++ return -ENOEXEC;
++ do_reloc16(v - (Elf32_Addr) loc, loc, 0x000001ff, 1,
++ 0xffffff00, 0, NEED_SWAP);
++ break;
++
++ case R_NDS32_15_PCREL_RELA:
++ if (exceed_limit
++ ((v - (Elf32_Addr) loc), 0x00003fff, module, rel,
++ relindex, i))
++ return -ENOEXEC;
++ do_reloc32(v - (Elf32_Addr) loc, loc, 0x00007fff, 1,
++ 0xffffc000, 0, NEED_SWAP);
++ break;
++
++ case R_NDS32_17_PCREL_RELA:
++ if (exceed_limit
++ ((v - (Elf32_Addr) loc), 0x0000ffff, module, rel,
++ relindex, i))
++ return -ENOEXEC;
++ do_reloc32(v - (Elf32_Addr) loc, loc, 0x0001ffff, 1,
++ 0xffff0000, 0, NEED_SWAP);
++ break;
++
++ case R_NDS32_25_PCREL_RELA:
++ if (exceed_limit
++ ((v - (Elf32_Addr) loc), 0x00ffffff, module, rel,
++ relindex, i))
++ return -ENOEXEC;
++ do_reloc32(v - (Elf32_Addr) loc, loc, 0x01ffffff, 1,
++ 0xff000000, 0, NEED_SWAP);
++ break;
++ case R_NDS32_WORD_9_PCREL_RELA:
++ if (exceed_limit
++ ((v - (Elf32_Addr) loc), 0x000000ff, module, rel,
++ relindex, i))
++ return -ENOEXEC;
++ do_reloc32(v - (Elf32_Addr) loc, loc, 0x000001ff, 1,
++ 0xffffff00, 0, NEED_SWAP);
++ break;
++
++ case R_NDS32_SDA15S3_RELA:
++ case R_NDS32_SDA15S2_RELA:
++ case R_NDS32_SDA15S1_RELA:
++ case R_NDS32_SDA15S0_RELA:
++ printk(KERN_ERR "%s: unsupported relocation type %d.\n",
++ module->name, ELF32_R_TYPE(rel->r_info));
++ printk(KERN_ERR
++ "Small data section access doesn't work in the kernel space; "
++ "please rebuild the kernel module with gcc option -G0.\n");
++ PRINTK("section %d reloc %d offset 0x%x size %d\n",
++ relindex, i, rel->r_offset, dstsec->sh_size);
++ break;
++
++ default:
++ printk(KERN_ERR "%s: unsupported relocation type %d.\n",
++ module->name, ELF32_R_TYPE(rel->r_info));
++ PRINTK("section %d reloc %d offset 0x%x size %d\n",
++ relindex, i, rel->r_offset, dstsec->sh_size);
++ }
++ }
++ return 0;
++}
++
++int
++apply_relocate(Elf32_Shdr * sechdrs, const char *strtab,
++ unsigned int symindex, unsigned int relsec,
++ struct module *module)
++{
++// printk(KERN_ERR "module %s: non-ADD RELOCATION unsupported\n", module->name);
++// return -ENOEXEC;
++ return 0;
++}
++
++int
++module_finalize(const Elf32_Ehdr * hdr, const Elf_Shdr * sechdrs,
++ struct module *module)
++{
++ return 0;
++}
++
++void module_arch_cleanup(struct module *mod)
++{
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/nds32-elf.h linux-3.4.110/arch/nds32/kernel/nds32-elf.h
+--- linux-3.4.110.orig/arch/nds32/kernel/nds32-elf.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/nds32-elf.h 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,855 @@
++#ifndef _NDS32_ELF_CHECK
++#define _NDS32_ELF_CHECK
++
++//#define TEST_ELF_CHECK_FUNC
++#ifdef TEST_ELF_CHECK_FUNC
++#include <stdio.h>
++#include <stdlib.h>
++#endif
++
++//#include <stdio.h>
++//#include <stdarg.h>
++
++#ifdef __cplusplus
++extern "C"
++{
++#else
++#include <stdbool.h>
++#endif //#ifdef __cplusplus
++
++
++ enum ELF_HEADER_FLAG_FIELD
++ {
++ EHFF_ARCH_VER = 0xF0000000, EHFF_ARCH_VER_SHIFT = 28,
++ //EHFF_RESERVED = 0x08000000,
++ EHFF_HAS_ZOL = 0x04000000,
++ EHFF_ISA_DSP = 0x02000000,
++ EHFF_ISA_FPU_MAC = 0x01000000,
++ EHFF_FPU_REG = 0x00C00000, EHFF_FPU_REG_SHIFT = 22,
++ EHFF_ISA_L2C = 0x00200000,
++ EHFF_ISA_NO_MAC = 0x00100000,
++ EHFF_ISA_MAC_DX = 0x00100000,
++ EHFF_ISA_FPU_DP = 0x00080000,
++ //EHFF_RESERVED = 0x00040000,
++ EHFF_ISA_SATURATION = 0x00020000,
++ EHFF_REDUCED_REGS = 0x00010000,
++ EHFF_ISA_STRING = 0x00008000,
++ EHFF_ISA_16BIT = 0x00004000,
++ EHFF_ISA_IFC = 0x00004000,
++ EHFF_ISA_DIV = 0x00002000,
++ EHFF_ISA_DIV_DX = 0x00002000,
++ EHFF_ISA_AUDIO = 0x00001000,
++ EHFF_ISA_FPU_SP = 0x00000800,
++ EHFF_ISA_EXT2 = 0x00000400,
++ EHFF_ISA_EXT = 0x00000200,
++ EHFF_ISA_EIT = 0x00000100,
++ EHFF_ISA_MFUSR_PC = 0x00000100,
++ EHFF_ABI_VER = 0x000000F0,
++ EHFF_ELF_VER = 0x0000000F, EHFF_ELF_VER_SHIFT = 0,
++ };
++
++
++ enum ELF_HEADER_FLAG_FIELD_ARCH_VER
++ {
++ EHFF_ARCH_VER_RESERVED = 0x0,
++ EHFF_ARCH_VER_V1 = 0x1,
++ EHFF_ARCH_VER_V2 = 0x2,
++ EHFF_ARCH_VER_V3 = 0x3,
++ EHFF_ARCH_VER_V3M = 0x4,
++ };
++
++ static const char *EHFF_ARCH_VER_MSG[] =
++ {
++ "RESERVED",
++ "BASE V1",
++ "BASE V2",
++ "BASE V3",
++ "BASE V3M",
++ };
++
++
++
++
++ /* ----------------------------------------------------------- */
++ /* 4-bit for ABI signature, allow up to 16 ABIs */
++ /* 0 : for OLD ABI V0, phase out
++ * 1 : for V1 , starting with V0 toolchain
++ * 2 : for V2
++ * 3 : for V2FP (fs0, fs1 as function parameter)
++ * 4 : for AABI */
++ /* only old N1213HC use V0 */
++ /* New ABI is used due to return register is changed to r0 from r5 */
++ /* ----------------------------------------------------------- */
++#define E_NDS_ABI_V0 0x00000000
++#define E_NDS_ABI_V1 0x00000010
++#define E_NDS_ABI_V2 0x00000020
++#define E_NDS_ABI_V2FP 0x00000030
++#define E_NDS_ABI_AABI 0x00000040
++#define E_NDS_ABI_V2FP_PLUS 0x00000050
++
++ /* ---------------------------------------------------------------------------- */
++ /* This flag signifies the version of Andes ELF */
++ /* note : */
++ /* 1. v1.3.1 and beyond is accompanying with Baseline ISA 1.0b/2.0/... in ELF. */
++ /* 2. v1.3.1 is accompanying with Baseline ISA 1.0b in ELF. */
++ /* ... | MAC | ... | DIV | ... */
++ /* 3. v1.3.1 is accompanying with Baseline ISA 2.0 and beyond in ELF. */
++ /* ... | MAC_DX | ... | DIV_DX | ... */
++ /* ---------------------------------------------------------------------------- */
++
++ enum ELF_HEADER_FLAG_FIELD_ELF_VER
++ {
++ EHFF_ELF_VER_1_3_0 = 0x0,
++ EHFF_ELF_VER_1_3_1 = 0x1,
++ EHFF_ELF_VER_1_4_0 = 0x2,
++ };
++
++ static const char *EHFF_ELF_VER_MSG[] =
++ {
++ "1.3.0",
++ "1.3.1",
++ "1.4.0",
++ };
++ /* */
++ /* sr layout : */
++ /* sr[14..10] : hardware components */
++ /* cpu / fpu / audio / ... */
++ /* sr[9..0] : sr index number dedicated for sr[14..10] */
++ /* */
++
++ //
++ // sr[14..10] definition:
++ // 0 : cpu
++ // 1 : fpu
++ // 2 : audio
++#define INDEX_HW_MASK 0x00007c00
++#define INDEX_HW_CPU 0x00000000
++#define INDEX_HW_FPU 0x00000400
++#define INDEX_HW_AUDIO 0x00000800
++#define HW_IS_CPU(sr) ((sr & INDEX_HW_MASK) == INDEX_HW_CPU)
++#define HW_IS_FPU(sr) ((sr & INDEX_HW_MASK) == INDEX_HW_FPU)
++#define HW_IS_AUDIO(sr) ((sr & INDEX_HW_MASK) == INDEX_HW_AUDIO)
++
++ //
++ // sr[9..0] definition:
++ // if (HW_IS_CPU(sr)) // cpu score
++ // sr[9..0] defined in chap 9 of Andes-Privilege-Architecture spec.
++ // else if (HW_IS_FPU(sr)) // fpu score
++ // sr[9..0] == SR_FPU_FPCFG, FPCFG defined in FPU_ISA_EXT spec.
++ // else if (HW_IS_AUDIO(sr)) // audio score
++ // //none register is used in loader checking mechanism
++ //
++#define SR_INDEX_MASK 0x000003ff
++#define SR_INDEX(sr) (sr & SR_INDEX_MASK)
++#define CPU_SR_INDEX(x,y,z) ((x << 7) + (y << 3) + z)
++#define FPU_SR_FPCFG() (INDEX_HW_FPU)
++
++ //FPU-belonged system registers
++#define SR_FPU_FPCFG 0x00
++
++#define SR_NOT_EXIST 0xffffffff
++
++ typedef unsigned int (* CALLBACK_FUNC) (unsigned int index);
++
++
++ static const char *NEC_MSG_FPU_reg[5] =
++ {
++ "N/A",
++ " 8SP/ 4DP",
++ "16SP/ 8DP",
++ "32SP/16DP",
++ "32SP/32DP"
++ };
++ static const char *NEC_MSG_endian[2] =
++ {
++ "little",
++ "big"
++ };
++
++#define EM_NDS32 167
++#if defined elf_check_swap_2 || defined elf_check_swap_4
++#error "ERROR : elf_check_swap_2 and elf_check_swap_4 are multiple defined"
++#endif
++#define elf_check_swap_2(data) (((data&0x0000ff00)>>8) | ((data&0x000000ff)<<8))
++#define elf_check_swap_4(data) (((data&0xff000000)>>24) | \
++ ((data&0x00ff0000)>>8) | \
++ ((data&0x0000ff00)<<8) | \
++ ((data&0x000000ff)<<24))
++
++#define MSC_CFG_BASEV 0x0000e000
++
++#define CPU_VER_EXT 0x00000001
++#define CPU_VER_A16 0x00000002
++#define CPU_VER_EXT2 0x00000004
++#define CPU_VER_FPU 0x00000008
++#define CPU_VER_STRING 0x00000010
++#define CPU_VER_SATURATION 0x00000020
++
++#define MSC_CFG_DIV 0x00000020
++#define MSC_CFG_MAC 0x00000040
++#define MSC_CFG_L2C 0x00000200
++#define MSC_CFG_REDUCED_REG 0x00000400
++#define MSC_CFG_NOD 0x00010000
++#define MSC_CFG_AUDIO 0x00000180
++#define MSC_CFG_AUDIO_NONE 0x00000000
++#define MSC_CFG_IFC 0x00080000
++#define MSC_CFG_MCU 0x00100000
++#define MSC_CFG_EX9IT 0x01000000
++#define MSC_CFG_MSC_EXT 0xc0000000
++
++#define MSC_CFG2_DSPPF 0x00000018
++#define MSC_CFG2_ZOL 0x00000020
++
++#define MMU_CFG_DE 0x04000000
++
++ typedef struct nds32_elfinfo_s
++ {
++ unsigned int endian; // 1.local-used constant definition
++ // 0 : little , 1 : big
++ // 2.system-used constant definition
++ // little / big depends on system definition
++ unsigned int machine; //magic number (167 for nds32 machine)
++ unsigned int mfusr_pc; //reclaim in baseline v2
++ unsigned int abi; // abi version
++ unsigned int base16; // 0 : not support , 1 : support
++ unsigned int pex1;
++ unsigned int div; //reclaim in baseline v2
++ unsigned int pex2;
++ unsigned int fpu; //fpu single precision
++ unsigned int audio;
++ unsigned int string;
++ unsigned int reduced_regs;
++ unsigned int saturation;
++ unsigned int ifc;
++ unsigned int elf_ver; //elf version number, 0 for v1.3.0, 1 for v1.3.1
++ unsigned int l2c;
++ unsigned int mac; //reclaim in baseline v2
++ //unsigned int isa_ver;//0x0, baseline = baseline V1 - 16 bit ISA
++ //0x1, baseline = baseline V1
++ //0x2, baseline = baseline V1 + V2 extension ISA
++ //unsigned int fpu_sp; //fpu double precision
++ //unsigned int fpu_reg; //fpu registers capacity
++ } nds32_elfinfo_t;
++
++ typedef enum nds32_elfchk_e
++ {
++ endian_chk = 0,
++ machine_chk,
++ isa_chk,
++ abi_chk
++ } nds32_elfchk_t;
++
++ typedef enum ELF_Fail_Type
++ {
++ EFT_NONE,
++ EFT_WARNING,
++ EFT_ERROR
++ }ELF_Fail_Type;
++
++ static inline void NEC_itoa(unsigned int value, char *buf, const unsigned int base)
++ {
++ char temp[10] = "\0", ch;
++ int len = 1, index;
++
++ while(value > 0)
++ {
++ ch = value%base;
++ value = value/base;
++ if(ch >= 10)
++ ch = ch+'a'-10;
++ else
++ ch = ch+'0';
++ temp[len++] = ch;
++ }
++ len--;
++
++ index = len;
++ while(index >= 0)
++ {
++ buf[index] = temp[len-index];
++ index--;
++ }
++ }
++
++ static inline void NEC_format(char *buf, unsigned int width)
++ {
++ unsigned int len = strlen(buf);
++ memmove(buf+(width-len), buf, len+1);
++ memset(buf, ' ', (width-len));
++ }
++
++ static void NEC_sprintf(char *buf, const char *str, ...)
++ {
++ int width, len = 0;
++ va_list ap;
++ char token, temp[100];
++ buf[0] = '\0';
++
++
++ va_start(ap, str);
++ while(*str != '\0')
++ {
++ if(*str != '%')
++ buf[len++] = *str;
++ else //*str == '%'
++ {
++ token = *(++str);
++
++ width = 0;
++ while(token >= '0' && token <= '9')
++ {
++ width *= 10;
++ width += token-'0';
++ token = *(++str);
++ }
++
++ switch(token)
++ {
++ case 'd':
++ NEC_itoa(va_arg(ap, unsigned int), temp, 10);
++ break;
++ case 'x':
++ NEC_itoa(va_arg(ap, unsigned int), temp, 16);
++ break;
++ case 's':
++ strcpy(temp, va_arg(ap, char *));
++ break;
++ }
++
++ if(width != 0)
++ NEC_format(temp, width);
++
++ buf[len++] = '\0';
++ strcat(buf, temp);
++ len = strlen(buf);
++ }
++
++ str++;
++ }
++ buf[len] = '\0';
++ }
++
++ //NDS32 strcat for avoiding buf overflow
++ static inline void NEC_strcat_safety(char *destination, unsigned int destination_size, char *source)
++ {
++ strncat(destination, source, destination_size - strlen(destination) - 1);
++ }
++
++ //NDS32 Elf Check print
++ static inline void NEC_print(char *buf, unsigned int len, ELF_Fail_Type type, const char *name, const char *cpu, const char *elf, const char *error_message)
++ {
++ char temp[100];
++ switch(type)
++ {
++ case EFT_NONE:
++ NEC_sprintf(temp, "\t | %9s | %9s | %14s\n", cpu, elf, name);
++ break;
++ case EFT_WARNING:
++ NEC_sprintf(temp, "\t?| %9s | %9s | %14s Warning: %s\n", cpu, elf, name, error_message);
++ break;
++ case EFT_ERROR:
++ NEC_sprintf(temp, "\t!| %9s | %9s | %14s Error: %s\n", cpu, elf, name, error_message);
++ break;
++ }
++ NEC_strcat_safety(buf, len, temp);
++ }
++
++ static inline bool NEC_check_bool(char *buf, unsigned int len, ELF_Fail_Type type, const char *isa, bool cpu, bool elf)
++ {
++ bool code;
++ const char *NEC_MSG_ISA[2] = { "OFF", "ON" };
++ if(!cpu && elf)
++ code = 1;
++ else
++ {
++ code = 0;
++ type = EFT_NONE;
++ }
++ NEC_print(buf, len, type, isa, NEC_MSG_ISA[cpu], NEC_MSG_ISA[elf], "Not supported by CPU");
++ return code;
++ }
++
++ static inline ELF_Fail_Type elf_ver_and_arch_ver_compatibility_check(unsigned int elf_ver, unsigned int arch_ver)
++ {
++ switch(elf_ver)
++ {
++ case EHFF_ELF_VER_1_3_0:
++ switch(arch_ver)
++ {
++ case EHFF_ARCH_VER_V1:
++ return EFT_NONE;
++ default:
++ return EFT_ERROR;
++ }
++ case EHFF_ELF_VER_1_3_1:
++ switch(arch_ver)
++ {
++ case EHFF_ARCH_VER_V1:
++ case EHFF_ARCH_VER_V2:
++ case EHFF_ARCH_VER_V3M:
++ return EFT_NONE;
++ default:
++ return EFT_ERROR;
++ }
++ case EHFF_ELF_VER_1_4_0:
++ switch(arch_ver)
++ {
++ case EHFF_ARCH_VER_V1:
++ case EHFF_ARCH_VER_V2:
++ case EHFF_ARCH_VER_V3:
++ case EHFF_ARCH_VER_V3M:
++ return EFT_NONE;
++ default:
++ return EFT_ERROR;
++ }
++ }
++ return EFT_ERROR;
++ }
++
++
++ static inline ELF_Fail_Type arch_ver_check(unsigned int CPU, unsigned int ELF)
++ {
++ switch(CPU)
++ {
++ case EHFF_ARCH_VER_V1:
++ switch(ELF)
++ {
++ case EHFF_ARCH_VER_V1:
++ return EFT_NONE;
++ default:
++ return EFT_ERROR;
++ }
++ case EHFF_ARCH_VER_V2:
++ switch(ELF)
++ {
++ case EHFF_ARCH_VER_V1:
++ case EHFF_ARCH_VER_V2:
++ return EFT_NONE;
++ default:
++ return EFT_ERROR;
++ }
++ case EHFF_ARCH_VER_V3:
++ switch(ELF)
++ {
++ case EHFF_ARCH_VER_V1:
++ case EHFF_ARCH_VER_V2:
++ case EHFF_ARCH_VER_V3:
++ case EHFF_ARCH_VER_V3M:
++ return EFT_NONE;
++ default:
++ return EFT_ERROR;
++ }
++ case EHFF_ARCH_VER_V3M:
++ switch(ELF)
++ {
++ case EHFF_ARCH_VER_V3M:
++ return EFT_NONE;
++ default:
++ return EFT_ERROR;
++ }
++ }
++ return EFT_ERROR;
++ }
++
++ // buf : buffer of char*, put Target Isa Info into *buf
++ // len : length of buffer (at least 300 chars in length)
++ // buf_status : status of buffer
++ // 0 : ok
++ // 1 : overflow
++#define TARGET_ISA_INFO_LEN 2000
++ static inline unsigned int elf_check (unsigned char *ehdr, CALLBACK_FUNC reg_read_callback, char *buf, unsigned int len, unsigned int *buf_status)
++ {
++ unsigned int SR_msc_cfg, SR_msc_cfg2 = 0, SR_cpu_ver, SR_mmu_cfg, fpcfg, fucop_exist, fpu_mount;
++ unsigned int CPU_DIV_DX_ISA, CPU_MAC_DX_ISA;
++ unsigned int eflag, ELF_arch_ver, ELF_elf_ver, CPU_arch_ver;
++ unsigned short machine;
++ unsigned char big_endian_elf = 0, big_endian_cpu;
++
++ char temp[100];
++ char temp_cpu[10];
++ char temp_elf[10];
++ int n_error, n_warning;
++ int CPU_support;
++ unsigned char FPU_reg_elf, FPU_reg_cpu;
++ ELF_Fail_Type error_type;
++
++
++
++ n_error = 0;
++ n_warning = 0;
++
++ buf[0] = '\0';
++ *buf_status = 0;
++
++ SR_cpu_ver = reg_read_callback(CPU_SR_INDEX(0,0,0));
++ SR_msc_cfg = reg_read_callback(CPU_SR_INDEX(0,4,0));
++ SR_mmu_cfg = reg_read_callback(CPU_SR_INDEX(0,3,0));
++
++ if (SR_msc_cfg & MSC_CFG_MSC_EXT)
++ SR_msc_cfg2 = reg_read_callback(CPU_SR_INDEX(0,4,1));
++
++ switch(*((char*)(ehdr+5)))
++ {
++ case 1:
++ big_endian_elf = 0;
++ break;
++ case 2:
++ big_endian_elf = 1;
++ break;
++ }
++
++ if(SR_mmu_cfg & MMU_CFG_DE)
++ big_endian_cpu = 1;
++ else
++ big_endian_cpu = 0;
++
++
++ /* 20091106 note :
++ * 1. In term of OS, elf_check() would be used in OS kernel and ld.so
++ * 2. Since OS is running on SID, eflag/machine did not need endian conversion for big endian format.
++ * 3. Later, elf_check interface is going to cover "OS" case by adding a new parameter.
++ *
++ */
++#ifdef ELF_CHECKING_OS
++ eflag = *((unsigned int *)(ehdr+36));
++ machine = *((unsigned short*)(ehdr+18));
++#else // GDB loader / SID loader
++ eflag = (big_endian_elf == 0)? *((unsigned int *)(ehdr+36)) : elf_check_swap_4(*((unsigned int *)(ehdr+36)));
++ machine = (big_endian_elf == 0)? *((unsigned short*)(ehdr+18)) : elf_check_swap_2(*((unsigned short*)(ehdr+18)));
++#endif
++
++ ELF_arch_ver = (eflag & EHFF_ARCH_VER) >> EHFF_ARCH_VER_SHIFT;
++ ELF_elf_ver = (eflag & EHFF_ELF_VER) >> EHFF_ELF_VER_SHIFT;
++
++ CPU_arch_ver = ((SR_msc_cfg & MSC_CFG_BASEV) >> 13) + 1;
++ if(CPU_arch_ver == 3)
++ if(SR_msc_cfg & MSC_CFG_MCU)
++ CPU_arch_ver = 4;
++
++ /*Basic version check
++
++ 1.ELF version check
++ 2.Architecture version check
++ 3.Machine check
++ */
++ if(ELF_elf_ver > EHFF_ELF_VER_1_4_0)
++ {
++ NEC_sprintf(temp, "Error: unsupport ELF version: 0x%x\n", ELF_elf_ver);
++ NEC_strcat_safety(buf, len, temp);
++ return 1;
++ }
++ NEC_sprintf(temp, "ELF version: %s\n", EHFF_ELF_VER_MSG[ELF_elf_ver]);
++ NEC_strcat_safety(buf, len, temp);
++
++
++ if(elf_ver_and_arch_ver_compatibility_check(ELF_elf_ver, ELF_arch_ver) == EFT_ERROR)
++ {
++ NEC_sprintf(temp, "Error: architecture version is not supported in this ELF version: %s\n", EHFF_ARCH_VER_MSG[ELF_arch_ver]);
++ NEC_strcat_safety(buf, len, temp);
++ return 1;
++ }
++
++ NEC_sprintf(temp, "\t %9s %9s \n", "CPU", "ELF");
++ NEC_strcat_safety(buf, len, temp);
++ if(big_endian_cpu != big_endian_elf)
++ {
++ error_type = EFT_ERROR;
++ n_error++;
++ }
++ else
++ error_type = EFT_NONE;
++ NEC_print(buf, len, error_type, "endianess", NEC_MSG_endian[big_endian_cpu], NEC_MSG_endian[big_endian_elf], "endianess mismatch");
++
++
++
++
++ if (EM_NDS32 != machine)
++ {
++ error_type = EFT_ERROR;
++ n_error++;
++ }
++ else
++ error_type = EFT_NONE;
++ NEC_sprintf(temp_cpu, "%d", EM_NDS32);
++ NEC_sprintf(temp_elf, "%d", machine);
++ NEC_print(buf, len, error_type, "machine", temp_cpu, temp_elf, "wrong machine");
++
++
++ error_type = arch_ver_check(CPU_arch_ver, ELF_arch_ver);
++ if(error_type == EFT_ERROR)
++ n_error++;
++ NEC_print(buf, len, error_type, "BASELINE ISA", EHFF_ARCH_VER_MSG[CPU_arch_ver], EHFF_ARCH_VER_MSG[ELF_arch_ver], "BASELINE ISA mismatch");
++
++ /*Prepare reference variables
++
++ 1.DIV, MAC, DX
++ 2.FPU
++ */
++
++ CPU_MAC_DX_ISA = 0;
++ CPU_DIV_DX_ISA = 0;
++ switch(CPU_arch_ver)
++ {
++ case EHFF_ARCH_VER_V1:
++ if (SR_msc_cfg & MSC_CFG_MAC)
++ CPU_MAC_DX_ISA = 1;
++ if (SR_msc_cfg & MSC_CFG_DIV)
++ CPU_DIV_DX_ISA = 1;
++ break;
++ case EHFF_ARCH_VER_V2:
++ case EHFF_ARCH_VER_V3:
++ case EHFF_ARCH_VER_V3M:
++ if (!(SR_msc_cfg & MSC_CFG_NOD))
++ {
++ CPU_MAC_DX_ISA = 1;
++ CPU_DIV_DX_ISA = 1;
++ }
++ break;
++ }
++ fpu_mount = 0;
++ if (SR_cpu_ver & CPU_VER_FPU)
++ {
++ fucop_exist = reg_read_callback(CPU_SR_INDEX(0,5,0));
++ if (fucop_exist & 0x80000000)
++ {
++ fpu_mount = 1;
++ fpcfg = reg_read_callback(FPU_SR_FPCFG());
++ }
++ else
++ fpu_mount = 0;
++ }
++
++ //Parse Configuration field (bit 27~8)
++
++ //bit 27 Reserved
++ //bit 26 ZOL
++ CPU_support = 0;
++ if ((SR_msc_cfg & MSC_CFG_MSC_EXT) && (SR_msc_cfg2 & MSC_CFG2_ZOL))
++ CPU_support = 1;
++ if (ELF_elf_ver == EHFF_ELF_VER_1_4_0)
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "ZOL", CPU_support, eflag & EHFF_HAS_ZOL);
++
++ //bit 25 DSP
++ CPU_support = 0;
++ if ((SR_msc_cfg & MSC_CFG_MSC_EXT) && (SR_msc_cfg2 & MSC_CFG2_DSPPF))
++ CPU_support = 1;
++ if (ELF_elf_ver == EHFF_ELF_VER_1_4_0)
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "DSP ISA", CPU_support, eflag & EHFF_ISA_DSP);
++
++ //bit 24
++ CPU_support = 0;
++ if(fpu_mount)
++ if(fpcfg & 0x00000010)
++ CPU_support = 1;
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "FPU MAC ISA", CPU_support, eflag & EHFF_ISA_FPU_MAC);
++
++ //bit 23~22
++ if(fpu_mount)
++ FPU_reg_cpu = ((fpcfg >> 2) & 0x3) + 1;
++ else
++ FPU_reg_cpu = 0;
++
++ if(eflag & (EHFF_ISA_FPU_SP | EHFF_ISA_FPU_DP | EHFF_ISA_FPU_MAC))
++ FPU_reg_elf = ((eflag & EHFF_FPU_REG) >> EHFF_FPU_REG_SHIFT) + 1;
++ else
++ FPU_reg_elf = 0;
++ if(FPU_reg_elf > FPU_reg_cpu)
++ {
++ error_type = EFT_ERROR;
++ n_error++;
++ }
++ else
++ error_type = EFT_NONE;
++ NEC_print(buf, len, error_type, "FPU REGISTER", NEC_MSG_FPU_reg[FPU_reg_cpu], NEC_MSG_FPU_reg[FPU_reg_elf],
++ "FPU REGISTERS not supported by CPU");
++ //bit 21
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "L2C ISA", SR_msc_cfg & MSC_CFG_L2C, eflag & EHFF_ISA_L2C);
++
++ //bit 20
++ //MAC_DX check
++ // Target Machine certainly has MAC_DX under the following conditions:
++ // 1. Baseline V1 ISA && MSC_CFG.MAC (softcore version)
++ // 2. Baseline V2 ISA && D0/D1 support
++ // 3. Baseline V3 ISA && D0/D1 support
++
++ switch(ELF_arch_ver)
++ {
++ case EHFF_ARCH_VER_V1:
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "MAC/MAC DX ISA", CPU_MAC_DX_ISA, !(eflag & EHFF_ISA_NO_MAC));
++ break;
++ case EHFF_ARCH_VER_V2:
++ case EHFF_ARCH_VER_V3:
++ case EHFF_ARCH_VER_V3M:
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "MAC DX ISA", CPU_MAC_DX_ISA, eflag & EHFF_ISA_MAC_DX);
++ break;
++ }
++ //bit 19
++ CPU_support = 0;
++ if(fpu_mount)
++ if(fpcfg & 0x00000002)
++ CPU_support = 1;
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "FPU DP ISA", CPU_support, eflag & EHFF_ISA_FPU_DP);
++
++
++ //bit 18 Reserved
++ //bit 17
++ switch(ELF_elf_ver)
++ {
++ case EHFF_ELF_VER_1_3_0:
++ case EHFF_ELF_VER_1_3_1:
++ break;
++ case EHFF_ELF_VER_1_4_0:
++ switch(ELF_arch_ver)
++ {
++ case EHFF_ARCH_VER_V3:
++ case EHFF_ARCH_VER_V3M:
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "SATURATION ISA", SR_cpu_ver & CPU_VER_SATURATION, eflag & EHFF_ISA_SATURATION);
++ break;
++ }
++ break;
++ }
++ //bit 16
++ if(SR_msc_cfg & MSC_CFG_REDUCED_REG)
++ CPU_support = 0;
++ else
++ CPU_support = 1;
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "32 GPR", CPU_support, (eflag & EHFF_REDUCED_REGS) == 0);
++
++ //bit 15
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "STRING ISA", SR_cpu_ver & CPU_VER_STRING, eflag & EHFF_ISA_STRING);
++
++ //bit 14
++ switch(ELF_elf_ver)
++ {
++ case EHFF_ELF_VER_1_3_0:
++ case EHFF_ELF_VER_1_3_1:
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "16-BIT ISA", SR_cpu_ver & CPU_VER_A16, eflag & EHFF_ISA_16BIT);
++ break;
++ case EHFF_ELF_VER_1_4_0:
++ switch(ELF_arch_ver)
++ {
++ case EHFF_ARCH_VER_V1:
++ case EHFF_ARCH_VER_V2:
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "16-BIT ISA", SR_cpu_ver & CPU_VER_A16, eflag & EHFF_ISA_16BIT);
++ break;
++ case EHFF_ARCH_VER_V3:
++ case EHFF_ARCH_VER_V3M:
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "IFC ISA", SR_msc_cfg & MSC_CFG_IFC, eflag & EHFF_ISA_IFC);
++ break;
++ }
++ break;
++ }
++
++ //bit 13
++ switch(ELF_arch_ver)
++ {
++ case EHFF_ARCH_VER_V1:
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "DIV DX ISA", CPU_DIV_DX_ISA, eflag & EHFF_ISA_DIV);
++ break;
++ case EHFF_ARCH_VER_V2:
++ case EHFF_ARCH_VER_V3:
++ case EHFF_ARCH_VER_V3M:
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "DIV DX ISA", CPU_DIV_DX_ISA, eflag & EHFF_ISA_DIV_DX);
++ break;
++ }
++ //bit 12
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "AUDIO/DSP ISA", SR_msc_cfg & MSC_CFG_AUDIO, eflag & EHFF_ISA_AUDIO);
++ //bit 11
++ CPU_support = 0;
++ if(fpu_mount)
++ if(fpcfg & 0x00000001)
++ CPU_support = 1;
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "FPU SP ISA", CPU_support, eflag & EHFF_ISA_FPU_SP);
++
++ //bit 10
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "PEX2 ISA", SR_cpu_ver & CPU_VER_EXT2, eflag & EHFF_ISA_EXT2);
++
++ //bit 9
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "PEX1 ISA", SR_cpu_ver & CPU_VER_EXT, eflag & EHFF_ISA_EXT);
++
++ //bit 8
++ CPU_support = 0;
++ if(CPU_arch_ver == EHFF_ARCH_VER_V3M)
++ CPU_support = 1;
++ switch(ELF_elf_ver)
++ {
++ case EHFF_ELF_VER_1_3_0:
++ case EHFF_ELF_VER_1_3_1:
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "MFUSR_PC ISA", CPU_support, eflag & EHFF_ISA_MFUSR_PC);
++ break;
++ case EHFF_ELF_VER_1_4_0:
++ switch(ELF_arch_ver)
++ {
++ case EHFF_ARCH_VER_V1:
++ case EHFF_ARCH_VER_V2:
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "MFUSR_PC ISA", CPU_support, eflag & EHFF_ISA_MFUSR_PC);
++ break;
++ case EHFF_ARCH_VER_V3:
++ case EHFF_ARCH_VER_V3M:
++ n_error += NEC_check_bool(buf, len, EFT_ERROR, "EIT ISA", SR_msc_cfg & MSC_CFG_EX9IT, eflag & EHFF_ISA_EIT);
++ break;
++ }
++ break;
++ }
++
++ if(n_error)
++ {
++ NEC_strcat_safety(buf, len, (char*)"Error: ELF and CPU mismatch\n");
++ NEC_sprintf(temp, "Total Error: %d\n", n_error);
++ NEC_strcat_safety(buf, len, temp);
++
++ NEC_strcat_safety(buf, len, (char*)"Usage error, Consult Andes Toolchains and their compatible Andes cores for the Toolchain-CPU compatibility.\n");
++ NEC_strcat_safety(buf, len, (char*)"The Loader Checking can be disabled under Debug Configuration.\n");
++ }
++ else
++ NEC_strcat_safety(buf, len, (char*)"NDS32 ELF checking pass\n");
++
++ if(n_warning)
++ {
++ NEC_sprintf(temp, "Total Warning: %d\n", n_warning);
++ NEC_strcat_safety(buf, len, temp);
++ }
++
++
++ // checking buf overflow
++ if(strlen(buf) >= len)
++ *buf_status = 1;
++
++ return n_error;
++ } //end of elf_check
++
++#undef elf_check_swap_2
++#undef elf_check_swap_4
++
++#undef MSC_CFG_BASEV
++
++#undef CPU_VER_STRING
++#undef CPU_VER_EXT
++#undef CPU_VER_A16
++#undef CPU_VER_EXT2
++#undef CPU_VER_FPU
++#undef CPU_VER_SATURATION
++
++#undef MSC_CFG_DIV
++#undef MSC_CFG_MAC
++#undef MSC_CFG_L2C
++#undef MSC_CFG_REDUCED_REG
++#undef MSC_CFG_NOD
++#undef MSC_CFG_AUDIO
++#undef MSC_CFG_AUDIO_NONE
++#undef MSC_CFG_IFC
++#undef MSC_CFG_MCU
++#undef MSC_CFG_EX9IT
++#undef MSC_CFG_MSC_EXT
++
++#undef MSC_CFG2_DSPPF
++#undef MSC_CFG2_ZOL
++
++#undef MMU_CFG_DE
++
++#ifdef __cplusplus
++}
++#endif //#ifdef __cplusplus
++
++#endif //end of _NDS32_ELF_CHECK
++
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/nds32_ksyms.c linux-3.4.110/arch/nds32/kernel/nds32_ksyms.c
+--- linux-3.4.110.orig/arch/nds32/kernel/nds32_ksyms.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/nds32_ksyms.c 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,103 @@
++/*
++ * arch/nds32/kernel/nds32_ksyms.c
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++
++#include <linux/module.h>
++#include <linux/string.h>
++#include <linux/delay.h>
++#include <linux/in6.h>
++#include <linux/syscalls.h>
++
++#include <asm/checksum.h>
++#include <asm/io.h>
++#include <asm/system.h>
++#include <asm/uaccess.h>
++
++/*
++ * libgcc functions - functions that are used internally by the
++ * compiler... (prototypes are not correct though, but that
++ * doesn't really matter since they're not versioned).
++ */
++extern void __ashldi3(void);
++extern void __ashrdi3(void);
++extern void __divsi3(void);
++extern void __lshrdi3(void);
++extern void __modsi3(void);
++extern void __muldi3(void);
++extern void __ucmpdi2(void);
++extern void __udivdi3(void);
++extern void __umoddi3(void);
++extern void __udivmoddi4(void);
++extern void __udivsi3(void);
++extern void __umodsi3(void);
++
++/*
++ * This has a special calling convention; it doesn't
++ * modify any of the usual registers, except for LR.
++ */
++#define EXPORT_SYMBOL_ALIAS(sym,orig) \
++ const struct kernel_symbol __ksymtab_##sym \
++ __attribute__((section("__ksymtab"))) = \
++ { (unsigned long)&orig, #sym };
++
++/*
++ * floating point math emulator support.
++ * These symbols will never change their calling convention...
++ */
++
++/* networking */
++EXPORT_SYMBOL(csum_partial);
++EXPORT_SYMBOL(csum_partial_copy_nocheck);
++
++/* string / mem functions */
++EXPORT_SYMBOL(strchr);
++EXPORT_SYMBOL(strrchr);
++EXPORT_SYMBOL(memset);
++EXPORT_SYMBOL(memcpy);
++EXPORT_SYMBOL(memmove);
++EXPORT_SYMBOL(__memzero);
++
++/* user mem (segment) */
++EXPORT_SYMBOL(__arch_copy_from_user);
++EXPORT_SYMBOL(__arch_copy_to_user);
++EXPORT_SYMBOL(__arch_clear_user);
++EXPORT_SYMBOL(__arch_strnlen_user);
++EXPORT_SYMBOL(__arch_strncpy_from_user);
++
++EXPORT_SYMBOL(__get_user_1);
++EXPORT_SYMBOL(__get_user_2);
++EXPORT_SYMBOL(__get_user_4);
++EXPORT_SYMBOL(__get_user_8);
++
++EXPORT_SYMBOL(__put_user_1);
++EXPORT_SYMBOL(__put_user_2);
++EXPORT_SYMBOL(__put_user_4);
++EXPORT_SYMBOL(__put_user_8);
++
++/* gcc lib functions */
++EXPORT_SYMBOL(__ashldi3);
++EXPORT_SYMBOL(__ashrdi3);
++EXPORT_SYMBOL(__divsi3);
++EXPORT_SYMBOL(__lshrdi3);
++EXPORT_SYMBOL(__modsi3);
++EXPORT_SYMBOL(__muldi3);
++EXPORT_SYMBOL(__ucmpdi2);
++EXPORT_SYMBOL(__udivdi3);
++EXPORT_SYMBOL(__umoddi3);
++EXPORT_SYMBOL(__udivmoddi4);
++EXPORT_SYMBOL(__udivsi3);
++EXPORT_SYMBOL(__umodsi3);
++
++/* syscalls */
++EXPORT_SYMBOL(sys_write);
++EXPORT_SYMBOL(sys_lseek);
++EXPORT_SYMBOL(sys_exit);
++EXPORT_SYMBOL(sys_wait4);
++
++/* cache handling */
++
++EXPORT_SYMBOL(cpu_icache_inval_all);
++EXPORT_SYMBOL(cpu_dcache_wbinval_all);
++EXPORT_SYMBOL(cpu_dma_inval_range);
++EXPORT_SYMBOL(cpu_dma_wb_range);
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/proc.c linux-3.4.110/arch/nds32/kernel/proc.c
+--- linux-3.4.110.orig/arch/nds32/kernel/proc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/proc.c 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,81 @@
++/*
++ * linux/arch/nds32/kernel/setup.c
++ *
++ * Copyright (C) 1995-2001 Russell King
++ *
++ * 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.
++ */
++/* ============================================================================
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is for Andes NDS32 architecture.
++ *
++ * Revision History:
++ *
++ * Jul.05.2007 Initial ported by Tom, revised and patched for KGDB
++ * by Harry.
++ *
++ * Note:
++ *
++ * ============================================================================
++ */
++
++#include <asm/procinfo.h>
++
++struct proc_info_item info_item = {
++ "AndesCore",
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++ "I"
++#endif
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++ "D"
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++ "(wt)"
++#else
++ "(wb)"
++#endif
++#endif
++};
++
++struct proc_info_list n10_proc_info
++ __attribute__ ((section(".proc.info.init"))) = {
++.cpu_val = 0x0a000000,.cpu_mask = 0xff000000,.arch_name =
++ "NDS32 N10",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
++ &info_item,};
++
++struct proc_info_list n12_proc_info
++ __attribute__ ((section(".proc.info.init"))) = {
++.cpu_val = 0x0c000000,.cpu_mask = 0xff000000,.arch_name =
++ "NDS32 N12",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
++ &info_item,};
++
++struct proc_info_list n13_proc_info
++ __attribute__ ((section(".proc.info.init"))) = {
++.cpu_val = 0x0d000000,.cpu_mask = 0xff000000,.arch_name =
++ "NDS32 N13",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
++ &info_item,};
++
++struct proc_info_list n968_proc_info
++ __attribute__ ((section(".proc.info.init"))) = {
++.cpu_val = 0x19000000,.cpu_mask = 0xff000000,.arch_name =
++ "NDS32 N968",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
++ &info_item,};
++
++struct proc_info_list n1068_proc_info
++ __attribute__ ((section(".proc.info.init"))) = {
++.cpu_val = 0x1a000000,.cpu_mask = 0xff000000,.arch_name =
++ "NDS32 N1068",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
++ &info_item,};
++
++// the last one (a roust way to do so)
++struct proc_info_list nXX_proc_info
++ __attribute__ ((section(".proc.info.init"))) = {
++.cpu_val = 0x00000000,.cpu_mask = 0x00000000,.arch_name =
++ "NDS32 N??",.elf_name = "NDS32 ELF",.elf_hwcap = 0,.info =
++ &info_item,};
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/process.c linux-3.4.110/arch/nds32/kernel/process.c
+--- linux-3.4.110.orig/arch/nds32/kernel/process.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/process.c 2016-04-07 10:20:50.942081024 +0200
+@@ -0,0 +1,630 @@
++/*
++ * linux/arch/nds32/kernel/process.c
++ */
++/* Copyright (C) 1996-2000 Russell King - Converted to ARM.
++ * Original Copyright (C) 1995 Linus Torvalds
++ *
++ * 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.
++ */
++/* ============================================================================
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is process implementation for NDS32 architecture, and it
++ * is original referred from ARM.
++ *
++ * Revision History:
++ *
++ * Oct.02.2007 Initial ported by Tom, Shawn, Steven, and Harry.
++ * Oct.03.2007 Updated get_wchan() for info under /proc.
++ *
++ * Note:
++ *
++ * ============================================================================
++ */
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/delay.h>
++#include <linux/kallsyms.h>
++#include <asm/hardware.h>
++#include <asm/leds.h>
++#include <asm/uaccess.h>
++#include <asm/elf.h>
++#include <asm/fpu.h>
++#include <asm/audio.h>
++#include <linux/elf.h>
++#include <linux/tick.h>
++#include <linux/proc_fs.h>
++
++extern const char *processor_modes[];
++extern void setup_mm_for_reboot(char mode);
++extern struct task_struct *_switch(struct task_struct *last,
++ struct thread_info *prev,
++ struct thread_info *next);
++
++#ifndef CONFIG_UNLAZY_FPU
++struct task_struct *last_task_used_math = NULL;
++#endif
++#ifndef CONFIG_UNLAZY_AUDIO
++struct task_struct *last_task_used_audio = NULL;
++#endif
++static volatile int hlt_counter;
++
++#ifdef CONFIG_PROC_FS
++struct proc_dir_entry *proc_dir_cpu;
++EXPORT_SYMBOL(proc_dir_cpu);
++#endif
++
++extern inline void arch_reset(char mode)
++{
++ if (mode == 's') {
++ /* Use cpu handler, jump to 0 */
++ cpu_reset(0);
++ } else {
++ /*
++ * Suppose there should be HW function.
++ * Here we used one tick watchdog as a trick.
++ * It is not very good idea in the view of SoC
++ * design, but smart in firmware functionality.
++ * Harry@Jan,08.2008
++ */
++ REG32(WDT_FTWDT010_0_VA_BASE + 0x0C) = 0; // WdCR
++ REG32(WDT_FTWDT010_0_VA_BASE + 0x04) = 1; // WdLoad
++ REG32(WDT_FTWDT010_0_VA_BASE + 0x08) = 0x5AB9; // WdRestart
++ REG32(WDT_FTWDT010_0_VA_BASE + 0x0C) = 0x13; // Go...
++ }
++}
++
++#ifndef arch_idle
++static inline void arch_idle(void)
++{
++ cpu_do_idle();
++}
++#endif
++
++void disable_hlt(void)
++{
++ hlt_counter++;
++}
++
++EXPORT_SYMBOL(disable_hlt);
++
++void enable_hlt(void)
++{
++ hlt_counter--;
++}
++
++EXPORT_SYMBOL(enable_hlt);
++
++static int __init nohlt_setup(char *__unused)
++{
++ hlt_counter = 1;
++ return 1;
++}
++
++static int __init hlt_setup(char *__unused)
++{
++ hlt_counter = 0;
++ return 1;
++}
++
++__setup("nohlt", nohlt_setup);
++__setup("hlt", hlt_setup);
++
++/*
++ * The following aren't currently used.
++ */
++
++void (*pm_idle) (void) = NULL;
++EXPORT_SYMBOL(pm_idle);
++
++void (*pm_power_off) (void);
++EXPORT_SYMBOL(pm_power_off);
++
++/*
++ * This is our default idle handler. We need to disable
++ * interrupts here to ensure we don't miss a wakeup call.
++ */
++void default_idle(void)
++{
++ local_irq_disable();
++ if (!need_resched() && !hlt_counter)
++ arch_idle();
++ local_irq_enable();
++}
++
++/*
++ * The idle thread. We try to conserve power, while trying to keep
++ * overall latency low. The architecture specific idle is passed
++ * a value to indicate the level of "idleness" of the system.
++ */
++void cpu_idle(void)
++{
++
++ /* endless idle loop with no priority at all */
++ while (1) {
++ void (*idle) (void) = pm_idle;
++
++ if (!idle)
++ idle = default_idle;
++ tick_nohz_idle_enter();
++ leds_event(led_idle_start);
++ while (!need_resched())
++ idle();
++ leds_event(led_idle_end);
++ tick_nohz_idle_exit();
++ preempt_enable_no_resched();
++ schedule();
++ preempt_disable();
++ }
++}
++
++static char reboot_mode = 'h';
++
++int __init reboot_setup(char *str)
++{
++ reboot_mode = str[0];
++ return 1;
++}
++
++#ifdef CONFIG_PLAT_AG102
++static int cpub_pwroff(void)
++{
++ //PCU_SET_REG(PCS9_PARA,
++ // PCU_PREPARE(PCS9_PARA, IE, 0x0) |
++ // PCU_PREPARE(PCS9_PARA, CMD, PCS_CMD_SCALING) |
++ // PCU_PREPARE(PCS9_PARA, SYNC, PCS_SYNC_SRC) |
++ // PCU_PREPARE(PCS9_PARA, NXTPAR, 0x1b) // turn off cpub power
++ //);
++ //printk("cpub Power off: ok!!!OKOKOK\n");
++ //REG32(PCU_VA_BASE + 0x1A4) = (0x0000001B & 0x00FFFFFF)| ((0x2 << 24) & 0x0F000000) | ((0x1 << 28) & 0x70000000) | 0x00000000;
++ //__asm__ volatile ("standby wait_done\n");
++ //PCU_SET_REG(PCS9_ST1, 0x0); // clear status
++ //REG32(PCU_VA_BASE + 0x1A8) = 0x0;
++
++ //par = PCS_POWER_CPUB;
++ //PCU_SET_REG(PCS9_PARA,
++ //PCU_PREPARE(PCS9_PARA, IE, 0x1) |
++ //PCU_PREPARE(PCS9_PARA, CMD, PCS_CMD_PW_DOWN) |
++ //PCU_PREPARE(PCS9_PARA, SYNC, PCS_SYNC_SRC) |
++ //PCU_PREPARE(PCS9_PARA, NXTPAR, 0x6) // turn off all power
++
++ //printk("cpua Power off: ok!!!YAYAYA\n");
++ //printk("The value = 0x%08x\n", (0x00000006 & 0x00FFFFFF)| ((0x1 << 24) & 0x0F000000) | ((0x2 << 28) & 0x70000000) | 0x80000000);
++ REG32(PCU_VA_BASE + 0x1A4) =
++ (0x00000006 & 0x00FFFFFF) | ((0x1 << 24) & 0x0F000000) |
++ ((0x2 << 28) & 0x70000000) | 0x80000000;
++ __asm__ volatile ("standby wake_grant\n");
++ return (0);
++}
++#else
++static int cpub_pwroff(void)
++{
++ return 0;
++}
++
++#endif
++
++__setup("reboot=", reboot_setup);
++
++void machine_halt(void)
++{
++ //ADD by river 2011.04.14
++ cpub_pwroff();
++}
++
++EXPORT_SYMBOL(machine_halt);
++
++void machine_power_off(void)
++{
++ if (pm_power_off)
++ pm_power_off();
++}
++
++EXPORT_SYMBOL(machine_power_off);
++
++void machine_restart(char *__unused)
++{
++ /*
++ * Clean and disable cache, and turn off interrupts
++ */
++ cpu_proc_fin();
++
++ /*
++ * Tell the mm system that we are going to reboot -
++ * we may need it to insert some 1:1 mappings so that
++ * soft boot works.
++ */
++ setup_mm_for_reboot(reboot_mode);
++
++ /*
++ * Now call the architecture specific reboot code.
++ */
++ arch_reset(reboot_mode);
++
++ /*
++ * Whoops - the architecture was unable to reboot.
++ * Tell the user!
++ */
++ mdelay(1000);
++ printk("Reboot failed -- System halted\n");
++ while (1) ;
++}
++
++EXPORT_SYMBOL(machine_restart);
++
++void show_regs(struct pt_regs *regs)
++{
++ print_symbol("PC is at %s\n", instruction_pointer(regs));
++ print_symbol("LR is at %s\n", regs->NDS32_lp);
++ printk("pc : [<%08lx>] lp : [<%08lx>] %s\n"
++ "sp : %08lx fp : %08lx gp : %08lx\n",
++ instruction_pointer(regs),
++ regs->NDS32_lp, print_tainted(), regs->NDS32_sp,
++ regs->NDS32_fp, regs->NDS32_gp);
++ printk("r25: %08lx r24 : %08lx\n", regs->NDS32_r25, regs->NDS32_r24);
++
++ printk("r23: %08lx r22: %08lx r21: %08lx r20: %08lx\n",
++ regs->NDS32_r23, regs->NDS32_r22,
++ regs->NDS32_r21, regs->NDS32_r20);
++ printk("r19: %08lx r18: %08lx r17: %08lx r16: %08lx\n",
++ regs->NDS32_r19, regs->NDS32_r18,
++ regs->NDS32_r17, regs->NDS32_r16);
++ printk("r15: %08lx r14: %08lx r13: %08lx r12: %08lx\n",
++ regs->NDS32_r15, regs->NDS32_r14,
++ regs->NDS32_r13, regs->NDS32_r12);
++ printk("r11: %08lx r10: %08lx r9 : %08lx r8 : %08lx\n",
++ regs->NDS32_r11, regs->NDS32_r10,
++ regs->NDS32_r9, regs->NDS32_r8);
++ printk("r7 : %08lx r6 : %08lx r5 : %08lx r4 : %08lx\n",
++ regs->NDS32_r7, regs->NDS32_r6, regs->NDS32_r5, regs->NDS32_r4);
++ printk("r3 : %08lx r2 : %08lx r1 : %08lx r0 : %08lx\n",
++ regs->NDS32_r3, regs->NDS32_r2, regs->NDS32_r1, regs->NDS32_r0);
++ printk(" IRQs o%s Segment %s\n",
++ interrupts_enabled(regs) ? "n" : "ff",
++ segment_eq(get_fs(), get_ds())? "kernel" : "user");
++}
++
++void show_fpregs(struct user_fp *regs)
++{
++ int i;
++
++ for (i = 0; i < 8; i++) {
++ unsigned long *p;
++ char type;
++
++ p = (unsigned long *)(regs->fpregs + i);
++
++ switch (regs->ftype[i]) {
++ case 1:
++ type = 'f';
++ break;
++ case 2:
++ type = 'd';
++ break;
++ case 3:
++ type = 'e';
++ break;
++ default:
++ type = '?';
++ break;
++ }
++ if (regs->init_flag)
++ type = '?';
++
++ printk(" f%d(%c): %08lx %08lx %08lx%c",
++ i, type, p[0], p[1], p[2], i & 1 ? '\n' : ' ');
++ }
++
++ printk("FPSR: %08lx FPCR: %08lx\n",
++ (unsigned long)regs->fpsr, (unsigned long)regs->fpcr);
++}
++
++/*
++ * Task structure and kernel stack allocation.
++ */
++static unsigned long *thread_info_head;
++static unsigned int nr_thread_info;
++
++#define EXTRA_TASK_STRUCT 4
++#define ll_alloc_task_struct() ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
++#define ll_free_task_struct(p) free_pages((unsigned long)(p),1)
++
++struct thread_info *alloc_thread_info(struct task_struct *task)
++{
++ struct thread_info *thread = NULL;
++
++ if (EXTRA_TASK_STRUCT) {
++ unsigned long *p = thread_info_head;
++
++ if (p) {
++ thread_info_head = (unsigned long *)p[0];
++ nr_thread_info -= 1;
++ }
++ thread = (struct thread_info *)p;
++ }
++
++ if (!thread)
++ thread = ll_alloc_task_struct();
++
++#ifdef CONFIG_MAGIC_SYSRQ
++ /*
++ * The stack must be cleared if you want SYSRQ-T to
++ * give sensible stack usage information
++ */
++ if (thread) {
++ char *p = (char *)thread;
++ memzero(p + KERNEL_STACK_SIZE, KERNEL_STACK_SIZE);
++ }
++#endif
++ return thread;
++}
++
++void free_thread_info(struct thread_info *thread)
++{
++ if (EXTRA_TASK_STRUCT && nr_thread_info < EXTRA_TASK_STRUCT) {
++ unsigned long *p = (unsigned long *)thread;
++ p[0] = (unsigned long)thread_info_head;
++ thread_info_head = p;
++ nr_thread_info += 1;
++ } else
++ ll_free_task_struct(thread);
++}
++
++/*
++ * Free current thread data structures etc..
++ */
++void exit_thread(void)
++{
++#if defined(CONFIG_FPU)
++# ifndef CONFIG_UNLAZY_FPU
++ if (last_task_used_math == current) {
++ last_task_used_math = NULL;
++ }
++# endif
++#endif
++#if defined(CONFIG_AUDIO)
++# ifndef CONFIG_UNLAZY_AUDIO
++ if (last_task_used_audio == current) {
++ last_task_used_audio = NULL;
++ }
++# endif
++#endif
++}
++
++void flush_thread(void)
++{
++ struct task_struct *tsk = current;
++
++ memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
++#if defined(CONFIG_FPU)
++ clear_fpu(task_pt_regs(tsk));
++ clear_used_math();
++# ifndef CONFIG_UNLAZY_FPU
++ if (last_task_used_math == current) {
++ last_task_used_math = NULL;
++ }
++# endif
++#endif
++
++#if defined(CONFIG_AUDIO)
++ clear_audio(task_pt_regs(tsk));
++ clear_tsk_thread_flag(tsk, TIF_USEDAUDIO);
++# ifndef CONFIG_UNLAZY_AUDIO
++ if (last_task_used_audio == current) {
++ last_task_used_audio = NULL;
++ }
++# endif
++#endif
++
++}
++
++void release_thread(struct task_struct *dead_task)
++{
++}
++
++asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
++
++/*
++ * Shuffle the argument into the correct register before calling the
++ * thread function. $r1 is the thread argument, $r2 is the pointer to
++ * the thread function, and $r3 points to the exit function.
++ */
++extern void kernel_thread_helper(void);
++asm(".section .text\n"
++ " .align\n"
++ " .type kernel_thread_helper, #function\n"
++ "kernel_thread_helper:\n"
++ " move $r2, $lp\n"
++ " move $r0, $r1\n"
++ " move $lp, $r3\n"
++ " jr $r2 \n"
++ " .size kernel_thread_helper, . - kernel_thread_helper\n"
++ " .previous");
++
++pid_t kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)
++{
++ struct pt_regs regs;
++
++ memset(&regs, 0, sizeof(regs));
++
++ regs.NDS32_r1 = (unsigned long)arg;
++ regs.NDS32_r2 = (unsigned long)fn;
++ /* to apply right path */
++ regs.NDS32_lp = regs.NDS32_r2;
++ regs.NDS32_r3 = (unsigned long)do_exit;
++ regs.NDS32_ipc = (unsigned long)kernel_thread_helper;
++
++#ifdef __NDS32_EB__
++#define PSW_DE PSW_mskBE
++#else
++#define PSW_DE 0x0
++#endif
++
++#ifdef CONFIG_WBNA
++#define PSW_valWBNA PSW_mskWBNA
++#else
++#define PSW_valWBNA 0x0
++#endif
++
++ regs.NDS32_ipsw =
++ (PSW_CPL_ANY | PSW_valWBNA | PSW_mskDT | PSW_mskIT | PSW_DE |
++ PSW_SYSTEM | PSW_INTL_1 | PSW_mskGIE);
++ regs.NDS32_ir0 =
++ (PSW_CPL_ANY | PSW_valWBNA | PSW_mskDT | PSW_mskIT | PSW_DE |
++ PSW_SYSTEM | PSW_INTL_1);
++
++ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL,
++ NULL);
++}
++
++EXPORT_SYMBOL(kernel_thread);
++
++int
++copy_thread(unsigned long clone_flags, unsigned long stack_start,
++ unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs)
++{
++ struct thread_info *thread = task_thread_info(p);
++ struct pt_regs *childregs;
++
++ childregs =
++ ((struct pt_regs *)((unsigned long)thread + THREAD_SIZE - 8)) - 1;
++
++ *childregs = *regs;
++ childregs->NDS32_r0 = 0; /* child get zero as ret. */
++ childregs->NDS32_sp = stack_start;
++ childregs->NDS32_osp = 0;
++
++ thread->sp_save = ((struct cpu_context_save *)(childregs)) - 1;
++ /* cpu context switching */
++ thread->sp_save->pc = (unsigned long)ret_from_fork;
++ if (clone_flags & CLONE_SETTLS)
++ childregs->NDS32_r25 = regs->NDS32_r3;
++
++#ifdef CONFIG_FPU
++ if (used_math()) {
++# ifdef CONFIG_UNLAZY_FPU
++ unlazy_fpu(current);
++# else
++ preempt_disable();
++ if (last_task_used_math == current)
++ save_fpu(current);
++ preempt_enable();
++# endif
++ p->thread.fpu = current->thread.fpu;
++ clear_fpu(task_pt_regs(p));
++ set_stopped_child_used_math(p);
++ }
++#endif
++
++#ifdef CONFIG_AUDIO
++ if (test_tsk_thread_flag(current, TIF_USEDAUDIO)) {
++# ifdef CONFIG_UNLAZY_AUDIO
++ unlazy_audio(current);
++# else
++ preempt_disable();
++ if (last_task_used_audio == current)
++ save_audio(current);
++ preempt_enable();
++# endif
++ p->thread.audio = current->thread.audio;
++ clear_audio(childregs);
++ set_tsk_thread_flag(p, TIF_USEDAUDIO);
++ }
++#endif
++
++#ifdef CONFIG_HWZOL
++ childregs->NDS32_lb = 0;
++ childregs->NDS32_le = 0;
++ childregs->NDS32_lc = 0;
++#endif
++
++ return 0;
++}
++
++struct task_struct *__switch_to(struct task_struct *last,
++ struct thread_info *prev,
++ struct thread_info *next)
++{
++#if defined(CONFIG_FPU) || defined(CONFIG_AUDIO)
++# ifdef CONFIG_UNLAZY_FPU
++ unlazy_fpu(prev->task);
++# endif
++# ifdef CONFIG_UNLAZY_AUDIO
++ unlazy_audio(prev->task);
++# endif
++ if (!(next->task->flags & PF_KTHREAD)) {
++#ifdef CONFIG_FPU
++ clear_fpu(task_pt_regs(next->task));
++#endif
++#ifdef CONFIG_AUDIO
++ clear_audio(task_pt_regs(next->task));
++#endif
++ }
++#endif
++ return _switch(last, prev, next);
++}
++
++/*
++ * fill in the fpe structure for a core dump...
++ */
++int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpu)
++{
++ int fpvalid = 0;
++
++#if 0 // XXX defined(CONFIG_FPU)
++ struct task_struct *tsk = current;
++
++ fpvalid = !!tsk_used_math(tsk);
++ if (fpvalid) {
++ unlazy_fpu(tsk, regs);
++ memcpy(fpu, &tsk->thread.fpu, sizeof(*fpu));
++ }
++#endif
++
++ return fpvalid;
++}
++
++EXPORT_SYMBOL(dump_fpu);
++
++unsigned long get_wchan(struct task_struct *p)
++{
++ unsigned long fp, lr;
++ unsigned long stack_start, stack_end;
++ int count = 0;
++
++ if (!p || p == current || p->state == TASK_RUNNING)
++ return 0;
++
++#ifdef CONFIG_FRAME_POINTER
++ stack_start = (unsigned long)end_of_stack(p);
++ stack_end = (unsigned long)task_stack_page(p) + THREAD_SIZE;
++
++ fp = thread_saved_fp(p);
++ do {
++ if (fp < stack_start || fp > stack_end)
++ return 0;
++ lr = ((unsigned long *)fp)[0];
++ if (!in_sched_functions(lr))
++ return lr;
++ fp = *(unsigned long *)(fp + 4);
++ } while (count++ < 16);
++ return 0;
++#else
++ return 0;
++#endif
++}
++
++EXPORT_SYMBOL(get_wchan);
++
++extern int do_elf_check_arch(const struct elf32_hdr *hdr);
++
++int elf_check_arch(const struct elf32_hdr *hdr)
++{
++ return do_elf_check_arch(hdr);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ptrace.c linux-3.4.110/arch/nds32/kernel/ptrace.c
+--- linux-3.4.110.orig/arch/nds32/kernel/ptrace.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/ptrace.c 2016-04-07 10:22:02.056831821 +0200
+@@ -0,0 +1,919 @@
++/*
++ * linux/arch/nds32/kernel/ptrace.c
++ */
++/* By Ross Biro 1/23/92
++ * edited by Linus Torvalds
++ * ARM modifications Copyright (C) 2000 Russell King
++ * NDS32 modifications Copyright (C) 2007 Harry Pan
++ *
++ * 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.
++ */
++/* ============================================================================
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is for Andes NDS32 architecture.
++ *
++ * Revision History:
++ *
++ * Jul.31.2007 Initial ported by Tom, Shawn, and Steven,
++ * revised by Harry.
++ * Current implmentation is based on Andes Instruction
++ * Set Architecture Specification (AS-0001-0001)
++ * version:3.7 date:7-20-2007.
++ * It is original taken from ARM, then fit to NDS32.
++ * Aug.15.2007 Mainly updated breakpoint handling base on NDS32 ISA.
++ * I also did code revise.
++ * Nov.14.2007 Fixed up ptrace_set_bpt() while handling 16-bit insn.
++ * Nov.27.2007 Added checking duplicate breakpoints in
++ * add_breakpoint(), based on Shawn's idea.
++ * Dec.06.2007 Added get_user_gpr().
++ * Apr.17.2009 Added support for FPU and Audio regs.
++ * Added support for PTRACE_GETFPREGS, PTRACE_SETFPREGS,
++ * PTRACE_GETAUREGS, PTRACE_SETAUREGS
++ *
++ * Note:
++ *
++ * Current layout: 0-31 GR, 32-34 SPR, 35-... SR, index start from zero.
++ *
++ * +----------+-----+--------------+---+--------+
++ * | GR | SPR | SR |...| Audio |
++ * +----------+-----+--------------+---+--------+
++ * 0 32 35 ...500 531
++ *
++ * ============================================================================
++ */
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <linux/smp.h>
++#include <linux/ptrace.h>
++#include <linux/user.h>
++#include <linux/security.h>
++#include <linux/init.h>
++
++#include <asm/uaccess.h>
++#include <asm/pgtable.h>
++#include <asm/system.h>
++#include <asm/traps.h>
++#include <asm/fpu.h>
++#include <asm/audio.h>
++
++#include "ptrace.h"
++
++#ifdef __NDS32_EL__
++#define BREAKINST 0x01EA
++#else
++#define BREAKINST 0xEA01
++#endif
++
++/* get_user_reg()
++ *
++ * This routine will get a word off of the processes privileged stack.
++ * the offset is how far from the base addr as stored in the THREAD.
++ * this routine assumes that all the privileged stacks are in our
++ * data space.
++ */
++static inline unsigned int get_user_reg(struct task_struct *task, int offset)
++{
++ return task_pt_regs(task)->uregs[offset];
++}
++
++#if !defined(CONFIG_HSS)
++/* get_user_gpr()
++ *
++ */
++static unsigned int get_user_gpr(struct task_struct *task, int idx)
++{
++ unsigned int ret;
++
++ if (idx < 26) // r0 to r25
++ ret = get_user_reg(task, idx + 13);
++ else if (idx == 26 || idx == 27) // p0, p1
++ ret = get_user_reg(task, idx - 26 + 7);
++ else if (idx > 27 && idx < 31) // fp, gp, lp
++ ret = get_user_reg(task, idx + 11);
++ else if (idx == 31) // sp
++ ret = get_user_reg(task, 3);
++ else
++ ret = 0;
++
++ return ret;
++}
++#endif
++
++/* put_user_reg()
++ *
++ * this routine will put a word on the processes privileged stack.
++ * the offset is how far from the base addr as stored in the THREAD.
++ * this routine assumes that all the privileged stacks are in our
++ * data space.
++ */
++static inline int put_user_reg(struct task_struct *task, int offset, long data)
++{
++ struct pt_regs newregs, *regs = task_pt_regs(task);
++ int ret = -EINVAL;
++
++ newregs = *regs;
++ newregs.uregs[offset] = data;
++
++ if (valid_user_regs(&newregs)) {
++ regs->uregs[offset] = data;
++ ret = 0;
++ }
++
++ return ret;
++}
++
++#if !defined(CONFIG_HSS)
++/*
++ * Read instruction.
++ */
++static inline int
++read_insn(struct task_struct *task, unsigned long addr, u32 * res)
++{
++ int ret;
++ *res = 0;
++ ret = access_process_vm(task, addr, res, 2, 0);
++ if (ret != 2)
++ return 0;
++#ifdef __NDS32_EL__
++ *res = swab16(*res);
++#endif
++ if ((*res) & 0x8000)
++ return 2;
++
++ ret = access_process_vm(task, addr, res, 4, 0);
++ if (ret != 4)
++ return 0;
++#ifdef __NDS32_EL__
++ *res = swab32(*res);
++#endif
++ return 4;
++}
++
++/* get_branch_address()
++ *
++ * Decode branch instructions and destination.
++ */
++static unsigned long
++get_branch_address(struct task_struct *child,
++ unsigned long pc, unsigned long insn, unsigned int size)
++{
++ unsigned int tpc = 0;
++
++ /*
++ * TODO: COLE
++ * would it be simpler if we use two BREAKs,
++ * one for take, one for not
++ */
++
++ if (size == 4) {
++ /* 32-bit instruction */
++ if ((insn & 0x7e000000) == 0x4c000000) // BR1
++ {
++ int cond, imm14s;
++ unsigned int rt, ra;
++
++ rt = (insn >> 20) & 0x1f;
++ ra = (insn >> 15) & 0x1f;
++ cond = (insn >> 14) & 0x01;
++ imm14s = insn & 0x00003fff;
++
++ if (imm14s & 0x00002000) // sign extend
++ imm14s -= (0x00002000 << 1);
++
++ rt = get_user_gpr(child, rt);
++ ra = get_user_gpr(child, ra);
++
++ if (((cond == 1) && (rt != ra)) || // bne
++ ((cond == 0) && (rt == ra))) // beq
++ tpc = pc + (imm14s << 1);
++ } else if ((insn & 0x7e000000) == 0x4e000000) // BR2
++ {
++ int cond, imm16s, taken = 0;
++ int rt;
++
++ rt = (insn >> 20) & 0x1f;
++ cond = (insn >> 16) & 0x0f;
++ imm16s = insn & 0x0000ffff;
++
++ if (imm16s & 0x00008000) // sign extend
++ imm16s -= (0x00008000 << 1);
++
++ rt = get_user_gpr(child, rt);
++
++ switch (cond) {
++ case 0x02: // beqz
++ if (rt == 0)
++ taken = 1;
++ break;
++ case 0x03: // bnez
++ if (rt != 0)
++ taken = 1;
++ break;
++ case 0x06: // bgtz
++ if (rt > 0)
++ taken = 1;
++ break;
++ case 0x07: // blez
++ if (rt <= 0)
++ taken = 1;
++ break;
++ case 0x04: // bgez
++ case 0x0c: // bgezal
++ if (rt >= 0)
++ taken = 1;
++ break;
++ case 0x05: // bltz
++ case 0x0d: // bltzal
++ if (rt < 0)
++ taken = 1;
++ break;
++ default:
++ printk(KERN_WARNING
++ "ptrace: unknown conditional branch.\n");
++ break;
++ }
++
++ if (taken)
++ tpc = pc + (imm16s << 1);
++ } else if ((insn & 0x7e000000) == 0x48000000) // JI
++ {
++ int imm24s;
++
++ imm24s = insn & 0x00ffffff;
++
++ if (imm24s & 0x00800000) // sign extend
++ imm24s -= (0x00800000 << 1);
++
++ tpc = pc + (imm24s << 1);
++ } else if ((insn & 0x7e000000) == 0x4a000000) // JREG
++ {
++ unsigned int rb = (insn >> 10) & 0x1f;
++
++ tpc = get_user_gpr(child, rb);
++ }
++
++ } else {
++ /* 16-bit instruction */
++
++ if ((insn & 0xf800) == 0xc000) // beqz38
++ {
++ unsigned int rt3;
++
++ rt3 = (insn >> 8) & 0x07;
++
++ rt3 = get_user_gpr(child, rt3);
++
++ if (rt3 == 0) {
++ int imm8s;
++
++ imm8s = insn & 0x00ff;
++
++ if (imm8s & 0x0080) // sign extend
++ imm8s -= (0x0080 << 1);
++
++ tpc = pc + (imm8s << 1);
++ }
++ }
++
++ if ((insn & 0xf800) == 0xc800) // bnez38
++ {
++ unsigned int rt3;
++
++ rt3 = (insn >> 8) & 0x07;
++
++ rt3 = get_user_gpr(child, rt3);
++
++ if (rt3 != 0) {
++ int imm8s;
++
++ imm8s = insn & 0x00ff;
++
++ if (imm8s & 0x0080) // sign extend
++ imm8s -= (0x0080 << 1);
++
++ tpc = pc + (imm8s << 1);
++ }
++ }
++
++ if ((insn & 0xf800) == 0xd000) // beqs38, j8
++ {
++ unsigned int rt3, r5;
++
++ rt3 = (insn >> 8) & 0x07;
++
++ rt3 = get_user_gpr(child, rt3);
++ r5 = get_user_gpr(child, 5);
++
++ if (r5 == rt3) {
++ int imm8s;
++ imm8s = insn & 0x00ff;
++
++ if (imm8s & 0x0080) // sign extend
++ imm8s -= (0x0080 << 1);
++
++ tpc = pc + (imm8s << 1);
++ }
++ }
++
++ if ((insn & 0xf800) == 0xd800) // bnes38
++ {
++ unsigned int rt3, r5;
++
++ rt3 = (insn >> 8) & 0x07;
++
++ r5 = get_user_gpr(child, 5);
++ rt3 = get_user_gpr(child, rt3);
++
++ if (r5 != rt3) {
++ int imm8s;
++
++ imm8s = insn & 0x00ff;
++
++ if (imm8s & 0x0080) // sign extend
++ imm8s -= (0x0080 << 1);
++
++ tpc = pc + (imm8s << 1);
++ }
++ }
++
++ if ((insn & 0xffe0) == 0xdd00 || // jr5
++ (insn & 0xffe0) == 0xdd80 || // ret5
++ (insn & 0xffe0) == 0xdd20) // jral5
++ {
++ unsigned int rb5;
++
++ rb5 = insn & 0x1f;
++
++ tpc = get_user_gpr(child, rb5);
++ }
++
++ if ((insn & 0xfe00) == 0xe800) {
++ int taken = 0;
++ unsigned int r15;
++
++ r15 = get_user_gpr(child, 15);
++
++ if (insn & 0x0100) // bnezs8
++ {
++ if (r15 != 0)
++ taken = 1;
++ } else // beqzs8
++ {
++ if (r15 == 0)
++ taken = 1;
++ }
++
++ if (taken) {
++ int imm8s;
++
++ imm8s = insn & 0x00ff;
++
++ if (imm8s & 0x0080) // sign extend
++ imm8s -= (0x0080 << 1);
++
++ tpc = pc + (imm8s << 1);
++ }
++ }
++ }
++
++ return tpc;
++}
++
++/*
++ * Swap instructions in the user program.
++ * swap in new_insn. save orignal value in old_insn
++ * assume new_insn is 2-bytes long
++ */
++static int
++swap_insn(struct task_struct *task, unsigned long addr,
++ u16 * old_insn, u16 * new_insn)
++{
++ int ret;
++
++ ret = access_process_vm(task, addr, old_insn, 2, 0);
++ if (ret == 2)
++ ret = access_process_vm(task, addr, new_insn, 2, 1);
++
++ return ret;
++}
++
++/*
++ * Add one breakpoint in the user program.
++ */
++static void
++add_breakpoint(struct task_struct *task, struct debug_info *dbg,
++ unsigned long addr)
++{
++ u16 new_insn = BREAKINST;
++ int res;
++
++ if (dbg->valid) {
++ printk(KERN_ERR "ptrace: too many breakpoints\n");
++ return;
++ }
++
++ dbg->address = addr;
++ res = swap_insn(task, addr, &dbg->insn, &new_insn);
++ if (res == 2)
++ dbg->valid = 1;
++ if (!dbg->valid)
++ printk(KERN_ERR "ptrace: fail to add breakpoint\n");
++}
++
++/*
++ * Clear one software breakpoint in the user program.
++ */
++static void clear_breakpoint(struct task_struct *task, struct debug_info *dbg)
++{
++ int ret;
++ unsigned int addr = dbg->address;
++ u16 old_insn;
++
++ if (!dbg->valid) {
++ return;
++ }
++ dbg->valid = 0;
++
++ ret = swap_insn(task, addr, &old_insn, &dbg->insn);
++
++ if (ret != 2 || old_insn != BREAKINST) {
++ printk(KERN_ERR "ptrace: %s:%d: corrupted NDS16 breakpoint at "
++ "0x%08x (0x%04x)\n", task->comm, task->pid,
++ addr, old_insn);
++ }
++}
++
++/*
++ * ptrace_set_swbk
++ * Set breakpoint in user program.
++ */
++void ptrace_set_swbk(struct task_struct *child)
++{
++ struct pt_regs *regs;
++ unsigned long pc;
++ unsigned int size;
++ u32 insn;
++
++ /*
++ * always clear before set,
++ * since in some sepcial case, it may fail to hit
++ */
++ ptrace_cancel_swbk(child);
++ regs = task_pt_regs(child);
++ pc = instruction_pointer(regs);
++ size = read_insn(child, pc, &insn);
++
++ printk(KERN_DEBUG " STEP.size=%d\n", size);
++
++ if (size > 0) {
++ struct debug_info *dbg = &child->thread.debug;
++ unsigned int tpc;
++
++ /* Predict next PC. */
++ tpc = get_branch_address(child, pc, insn, size);
++
++ if (tpc) {
++ printk(KERN_DEBUG " STEP.addr=0x%x\n", tpc);
++ add_breakpoint(child, dbg, tpc);
++ } else {
++ if (size == 4) {
++ printk(KERN_DEBUG " STEP.addr=0x%x\n",
++ (unsigned int)(pc + 4));
++ add_breakpoint(child, dbg, pc + 4);
++ } else if (size == 2) {
++ printk(KERN_DEBUG " STEP.addr=0x%x\n",
++ (unsigned int)(pc + 2));
++ add_breakpoint(child, dbg, pc + 2);
++ } else {
++ printk(KERN_ERR
++ "ptrace: bad step address, pc + %d\n",
++ size);
++ }
++ }
++ }
++}
++
++/*
++ * Ensure no single-step breakpoint is pending. Returns non-zero
++ * value if child was being single-stepped.
++ */
++void ptrace_cancel_swbk(struct task_struct *child)
++{
++ if (!child->thread.debug.valid) {
++ return;
++ }
++
++ clear_breakpoint(child, &child->thread.debug);
++}
++#endif /* end of !defined (CONFIG_HSS) */
++
++/*
++ * Called by kernel/ptrace.c when detaching..
++ *
++ * Make sure the single step bit is not set.
++ */
++void ptrace_disable(struct task_struct *child)
++{
++ user_disable_single_step(child);
++}
++
++/*
++ * Handle hitting a breakpoint.
++ */
++void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
++ int error_code, int si_code)
++{
++ struct siginfo info;
++
++#if !defined (CONFIG_HSS)
++ /* clear the swbk; otherwise the user will see it */
++ ptrace_cancel_swbk(tsk);
++#endif
++
++ tsk->thread.trap_no = 1;
++ tsk->thread.error_code = error_code;
++
++ memset(&info, 0, sizeof(info));
++ info.si_signo = SIGTRAP;
++ info.si_code = si_code;
++
++ info.si_addr = (void __user *)instruction_pointer(regs);
++
++ /* Send us the fake SIGTRAP */
++ force_sig_info(SIGTRAP, &info, tsk);
++}
++
++/* ptrace_read_user()
++ *
++ * Read the word at offset "off" into the "struct user". We
++ * actually access the pt_regs stored on the kernel stack.
++ */
++static int
++ptrace_read_user(struct task_struct *tsk, unsigned long off,
++ unsigned long __user * ret)
++{
++ unsigned long tmp = 0;
++
++ if (off < 500) {
++ if (off & 3 || off >= sizeof(struct user))
++ return -EIO;
++
++ if (off < sizeof(struct pt_regs))
++ tmp = get_user_reg(tsk, off >> 2);
++
++ return put_user(tmp, ret);
++ } else if (off < 532) {
++#ifdef CONFIG_AUDIO
++ off -= 500;
++ if (test_tsk_thread_flag(tsk, TIF_USEDAUDIO)) {
++#ifdef CONFIG_UNLAZY_AUDIO
++ unlazy_audio(tsk);
++#else
++ preempt_disable();
++ if (last_task_used_audio == tsk)
++ save_audio(tsk);
++ preempt_enable();
++#endif
++ tmp = tsk->thread.audio.auregs[off];
++ }
++#endif
++ return put_user(tmp, ret);
++ } else
++ return -EIO;
++}
++
++/* ptrace_write_user()
++ *
++ * Write the word at offset "off" into "struct user". We
++ * actually access the pt_regs stored on the kernel stack.
++ */
++static int
++ptrace_write_user(struct task_struct *tsk, unsigned long off, unsigned long val)
++{
++ if (off < 500) {
++ if (off & 3 || off >= sizeof(struct user))
++ return -EIO;
++
++ if (off >= sizeof(struct pt_regs))
++ return 0;
++
++ return put_user_reg(tsk, off >> 2, val);
++ } else if (off < 532) {
++#ifdef CONFIG_AUDIO
++ off -= 500;
++ if (!test_tsk_thread_flag(tsk, TIF_USEDAUDIO)) {
++ /* First time Audio user. */
++ memset(&tsk->thread.audio, 0,
++ sizeof(struct audio_struct));
++ set_tsk_thread_flag(tsk, TIF_USEDAUDIO);
++ } else {
++#ifdef CONFIG_UNLAZY_AUDIO
++ unlazy_audio(tsk);
++#else
++ if (last_task_used_audio == tsk) {
++ preempt_disable();
++ save_audio(tsk);
++ preempt_enable();
++ }
++#endif
++ /* Let the lazy mechanism do the restore. */
++ clear_audio(task_pt_regs(tsk));
++ }
++ tsk->thread.audio.auregs[off] = val;
++#endif
++ return 0;
++ } else
++ return -EIO;
++}
++
++/* ptrace_getregs()
++ *
++ * Get all user integer registers.
++ */
++static int ptrace_getregs(struct task_struct *tsk, void __user * uregs)
++{
++ struct pt_regs *regs = task_pt_regs(tsk);
++
++ return copy_to_user(uregs, regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
++}
++
++/* ptrace_setregs()
++ *
++ * Set all user integer registers.
++ */
++static int ptrace_setregs(struct task_struct *tsk, void __user * uregs)
++{
++ struct pt_regs newregs;
++ int ret;
++
++ ret = -EFAULT;
++ if (copy_from_user(&newregs, uregs, sizeof(struct pt_regs)) == 0) {
++ struct pt_regs *regs = task_pt_regs(tsk);
++
++ ret = -EINVAL;
++ if (valid_user_regs(&newregs)) {
++ *regs = newregs;
++ ret = 0;
++ }
++ }
++
++ return ret;
++}
++
++/* ptrace_getfpregs()
++ *
++ * Get the child FPU state.
++ */
++static int ptrace_getfpregs(struct task_struct *tsk, void __user * ufpregs)
++{
++#ifdef CONFIG_FPU
++ if (used_math()) {
++# ifdef CONFIG_UNLAZY_FPU
++ unlazy_fpu(tsk);
++# else
++ preempt_disable();
++ if (last_task_used_math == tsk)
++ save_fpu(tsk);
++ preempt_enable();
++# endif
++ return copy_to_user(ufpregs, &tsk->thread.fpu,
++ sizeof(struct fpu_struct)) ? -EFAULT : 0;
++ } else {
++ /* First time FPU user. */
++ memset(ufpregs, -1, sizeof(struct fpu_struct));
++ return 0;
++ }
++
++#else
++ return -EFAULT;
++#endif
++}
++
++/*
++ * Set the child FPU state.
++ */
++static int ptrace_setfpregs(struct task_struct *tsk, void __user * ufpregs)
++{
++#ifdef CONFIG_FPU
++ int ret;
++
++# ifndef CONFIG_UNLAZY_FPU
++ if (last_task_used_math == tsk)
++# endif
++ clear_fpu(task_pt_regs(tsk));
++
++ ret =
++ copy_from_user(&tsk->thread.fpu, ufpregs,
++ sizeof(struct fpu_struct)) ? -EFAULT : 0;
++
++ if (!ret && !used_math()) {
++ /* First time Audio user. */
++ set_used_math();
++ }
++
++ return ret;
++#else
++ return -EFAULT;
++#endif
++}
++
++/* ptrace_getauregs()
++ *
++ * Get the child Audio state.
++ */
++static int ptrace_getauregs(struct task_struct *tsk, void __user * uauregs)
++{
++#ifdef CONFIG_AUDIO
++ if (test_tsk_thread_flag(tsk, TIF_USEDAUDIO)) {
++#ifdef CONFIG_UNLAZY_AUDIO
++ unlazy_audio(tsk);
++#else
++ preempt_disable();
++ if (last_task_used_audio == tsk)
++ save_audio(tsk);
++ preempt_enable();
++#endif
++ return copy_to_user(uauregs, &tsk->thread.audio,
++ sizeof(struct audio_struct)) ? -EFAULT : 0;
++ } else {
++ /* First time Audio user. */
++ memset(uauregs, 0, sizeof(struct audio_struct));
++ return 0;
++ }
++
++#else
++ return -EFAULT;
++#endif
++}
++
++/*
++ * Set the child Audio state.
++ */
++static int ptrace_setauregs(struct task_struct *tsk, void __user * uauregs)
++{
++#ifdef CONFIG_AUDIO
++ int ret;
++
++#ifdef CONFIG_UNLAZY_AUDIO
++ clear_audio(task_pt_regs(tsk));
++#else
++ if (last_task_used_audio == tsk)
++ clear_audio(task_pt_regs(tsk));
++#endif
++ ret =
++ copy_from_user(&tsk->thread.audio, uauregs,
++ sizeof(struct audio_struct)) ? -EFAULT : 0;
++
++ if (!ret && !test_tsk_thread_flag(tsk, TIF_USEDAUDIO)) {
++ /* First time Audio user. */
++ set_tsk_thread_flag(tsk, TIF_USEDAUDIO);
++ }
++
++ return ret;
++#else
++ return -EFAULT;
++#endif
++}
++
++/* do_ptrace()
++ *
++ * Provide ptrace defined service.
++ */
++long arch_ptrace(struct task_struct *child, long request, unsigned long addr,
++ unsigned long data)
++{
++ int ret;
++
++ switch (request) {
++ case PTRACE_PEEKUSR:
++ ret =
++ ptrace_read_user(child, addr, (unsigned long __user *)data);
++ break;
++
++ case PTRACE_POKEUSR:
++ ret = ptrace_write_user(child, addr, data);
++ break;
++
++ case PTRACE_GETREGS:
++ ret = ptrace_getregs(child, (void __user *)data);
++ break;
++
++ case PTRACE_SETREGS:
++ ret = ptrace_setregs(child, (void __user *)data);
++ break;
++
++ case PTRACE_GETFPREGS:
++ ret = ptrace_getfpregs(child, (void __user *)data);
++ break;
++
++ case PTRACE_SETAUREGS:
++ ret = ptrace_setauregs(child, (void __user *)data);
++ break;
++
++ case PTRACE_GETAUREGS:
++ ret = ptrace_getauregs(child, (void __user *)data);
++ break;
++
++ case PTRACE_SETFPREGS:
++ ret = ptrace_setfpregs(child, (void __user *)data);
++ break;
++/*
++ case PTRACE_GET_THREAD_AREA:
++ ret = put_user(task_thread_info(child)->tp_value,
++ (unsigned long __user *) data);
++ break;
++*/
++
++ default:
++ ret = ptrace_request(child, request, addr, data);
++ break;
++ }
++
++ return ret;
++}
++
++void user_enable_single_step(struct task_struct *child)
++{
++ struct pt_regs *regs;
++ regs = task_pt_regs(child);
++#ifdef CONFIG_HSS
++ regs->NDS32_ipsw |= PSW_mskHSS;
++#else
++ ptrace_set_swbk(child);
++#endif
++ set_tsk_thread_flag(child, TIF_SINGLESTEP);
++}
++
++void user_disable_single_step(struct task_struct *child)
++{
++ struct pt_regs *regs;
++ regs = task_pt_regs(child);
++#ifdef CONFIG_HSS
++ regs->NDS32_ipsw &= ~PSW_mskHSS;
++#else
++ ptrace_cancel_swbk(child);
++#endif
++ clear_tsk_thread_flag(child, TIF_SINGLESTEP);
++}
++
++/* sys_trace()
++ *
++ * syscall trace handler.
++ */
++static inline void do_syscall_trace(void)
++{
++ if (!test_thread_flag(TIF_SYSCALL_TRACE))
++ return;
++ if (!(current->ptrace & PT_PTRACED))
++ return;
++
++ /* the 0x80 provides a way for the tracing parent to distinguish
++ between a syscall stop and SIGTRAP delivery */
++ ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
++ ? 0x80 : 0));
++ /*
++ * this isn't the same as continuing with a signal, but it will do
++ * for normal use. strace only continues with a signal if the
++ * stopping signal is not SIGTRAP. -brl
++ */
++ if (current->exit_code) {
++ send_sig(current->exit_code, current, 1);
++ current->exit_code = 0;
++ }
++}
++
++asmlinkage int syscall_trace_enter(int syscall, struct pt_regs *regs)
++{
++ int orig_r0;
++
++ orig_r0 = regs->NDS32_ORIG_r0;
++ regs->NDS32_ORIG_r0 = syscall;
++ do_syscall_trace();
++ syscall = regs->NDS32_ORIG_r0;
++ regs->NDS32_ORIG_r0 = orig_r0;
++ return syscall & 0xfff;
++}
++
++asmlinkage void syscall_trace_leave(struct pt_regs *regs)
++{
++ do_syscall_trace();
++
++ /* synthsize a single-step */
++#if !defined(CONFIG_HSS)
++ /* for SWBK, break should be remove */
++ ptrace_cancel_swbk(current);
++#endif
++ if (test_thread_flag(TIF_SINGLESTEP)) {
++ printk(KERN_INFO "synthsize trap (tf=0x%0x\n",
++ (unsigned int)current_thread_info()->flags);
++ send_sigtrap(current, regs, 0, TRAP_BRKPT);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/ptrace.h linux-3.4.110/arch/nds32/kernel/ptrace.h
+--- linux-3.4.110.orig/arch/nds32/kernel/ptrace.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/ptrace.h 2016-04-07 10:20:50.946081179 +0200
+@@ -0,0 +1,48 @@
++/*
++ * linux/arch/nds32/kernel/ptrace.h
++ */
++/* Copyright (C) 2000-2003 Russell King
++ *
++ * 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.
++ */
++/* ============================================================================
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is for Andes NDS32 architecture.
++ *
++ * Revision History:
++ *
++ * Jul.31.2007 Initial ported by Tom, Shawn, and Steven,
++ * revised by Harry.
++ * Current implmentation is based on Andes Instruction
++ * Set Architecture Specification (AS-0001-0001)
++ * version:3.7 date:7-20-2007.
++ * It is original taken from ARM, then fit to NDS32.
++ *
++ * Note:
++ *
++ * Current layout: 0-31 GR, 32-34 SPR, 35-... SR, index start from zero.
++ *
++ * +----------+-----+--------------+
++ * | GR | SPR | SR |
++ * +-------------------------------+
++ * 0 32 35 ...
++ *
++ * ============================================================================
++ */
++#ifndef __KERNEL_PTRACE_H__
++#define __KERNEL_PTRACE_H__
++
++extern void ptrace_cancel_swbk(struct task_struct *);
++extern void ptrace_set_swbk(struct task_struct *);
++extern void ptrace_break(struct task_struct *, struct pt_regs *);
++extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
++ int error_code, int si_code);
++
++#endif // __KERNEL_PTRACE_H__
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/relocate_kernel.S linux-3.4.110/arch/nds32/kernel/relocate_kernel.S
+--- linux-3.4.110.orig/arch/nds32/kernel/relocate_kernel.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/relocate_kernel.S 2016-04-07 10:20:50.946081179 +0200
+@@ -0,0 +1,89 @@
++/*
++ * relocate_kernel.S - put the kernel image in place to boot
++ */
++
++#include <asm/kexec.h>
++
++ .globl relocate_new_kernel
++relocate_new_kernel:
++ la $r0, kexec_indirection_page
++ slli $r0, $r0, 2
++ srli $r0, $r0, 2
++ lwi $r0, [$r0]
++ la $r1, kexec_start_address
++ slli $r1, $r1, 2
++ srli $r1, $r1, 2
++ lwi $r1, [$r1]
++
++0: /* top, read another word for the indirection page */
++ lwi.bi $r3, [$r0], #4
++
++ /* Is it a destination page. Put destination address to r4 */
++ andi $p0, $r3, #1
++ beqz $p0, 1f
++ li $p0, ~#1
++ and $r4, $r3, $p0
++ b 0b
++1:
++ /* Is it an indirection page */
++ andi $p0, $r3, #2
++ beqz $p0, 1f
++ li $p0, ~#2
++ and $r0, $r3, $p0
++ b 0b
++1:
++ /* are we done ? */
++ andi $p0, $r3, #4
++ beqz $p0, 1f
++ b 2f
++1:
++ /* is it source ? */
++ andi $p0, $r3, #8
++ beqz $p0, 0b
++ li $p0, ~#8
++ and $r3, $r3, $p0
++ li $r6, #(1024/16) /* 16 words per loop */
++9:
++ lmw.bim $r7, [$r3], $r22
++ smw.bim $r7, [$r4], $r22
++ addi $r6, $r6, -1
++ bnez $r6, 9b
++ b 0b
++2:
++ /* Jump to relocated kernel */
++ move $lp, $r1
++ li $r0, 0
++ la $r1, kexec_mach_type
++ slli $r1, $r1, 2
++ srli $r1, $r1, 2
++ lwi $r1, [$r1]
++ la $r2, kexec_boot_atags
++ slli $r2, $r2, 2
++ srli $r2, $r2, 2
++ lwi $r2, [$r2]
++ ret
++
++ .globl kexec_start_address
++kexec_start_address:
++ .long 0x0
++
++ .globl kexec_indirection_page
++kexec_indirection_page:
++ .long 0x0
++
++ .globl kexec_mach_type
++kexec_mach_type:
++ .long 0x0
++
++ /* phy addr of the atags for the new kernel */
++ .globl kexec_boot_atags
++kexec_boot_atags:
++ .long 0x0
++
++relocate_new_kernel_end:
++
++ .globl relocate_new_kernel_size
++relocate_new_kernel_size:
++ .long relocate_new_kernel_end - relocate_new_kernel
++
++
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/setup.c linux-3.4.110/arch/nds32/kernel/setup.c
+--- linux-3.4.110.orig/arch/nds32/kernel/setup.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/setup.c 2016-04-07 10:20:50.946081179 +0200
+@@ -0,0 +1,1049 @@
++/*
++ * linux/arch/nds32/kernel/setup.c
++ *
++ * Copyright (C) 1995-2001 Russell King
++ *
++ * 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.
++ */
++/* ============================================================================
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is for Andes NDS32 architecture.
++ *
++ * Revision History:
++ *
++ * Jul.05.2007 Initial ported by Tom, revised and patched for KGDB
++ * by Harry.
++ * Aug.26.2008 Some reworks on CPU info output for SMP.
++ *
++ * Note:
++ *
++ * ============================================================================
++ */
++#include <linux/module.h>
++#include <linux/ioport.h>
++#include <linux/delay.h>
++#include <linux/utsname.h>
++#include <linux/initrd.h>
++#include <linux/console.h>
++#include <linux/bootmem.h>
++#include <linux/seq_file.h>
++#include <linux/screen_info.h>
++#include <linux/root_dev.h>
++#include <linux/cpu.h>
++#include <linux/fs.h>
++#include <linux/memblock.h>
++#include <asm/cpu.h>
++#include <asm/setup.h>
++#include <asm/mach-types.h>
++#include <asm/cacheflush.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/time.h>
++#include <asm/cpuver.h>
++#include <asm/procinfo.h>
++#include <asm/traps.h>
++#include <asm/fpu.h>
++#include <asm/cache_info.h>
++#include <nds32_intrinsic.h>
++
++#ifndef MEM_SIZE
++#define MEM_SIZE CONFIG_SDRAM_SIZE
++#endif
++
++#ifndef RAMDISK_SIZE
++#define RAMDISK_SIZE CONFIG_BLK_DEV_RAM_SIZE
++#endif
++
++extern void (*init_arch_irq) (void);
++
++extern void paging_init(struct machine_desc *desc);
++extern void reboot_setup(char *str);
++extern int root_mountflags;
++extern unsigned long _stext, _text, _etext, _sdata, _edata, _end;
++extern unsigned int ag101_cpufreq_get(unsigned int dummy);
++
++unsigned long cpu_id, cpu_rev, cpu_cfgid;
++char *endianness = NULL;
++
++unsigned int __machine_arch_type;
++EXPORT_SYMBOL(__machine_arch_type);
++
++unsigned int elf_hwcap;
++EXPORT_SYMBOL(elf_hwcap);
++
++unsigned char aux_device_present;
++
++char elf_platform[ELF_PLATFORM_SIZE];
++EXPORT_SYMBOL(elf_platform);
++
++unsigned long phys_initrd_start __initdata = 0;
++unsigned long phys_initrd_size __initdata = 0;
++
++static struct meminfo meminfo __initdata = { 0, };
++
++static const char *machine_name;
++static struct proc_info_item proc_info;
++static char command_line[COMMAND_LINE_SIZE];
++
++struct machine_desc *machine_desc __initdata;
++
++static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
++
++DEFINE_PER_CPU(struct cpuinfo_nds32, cpu_data);
++
++/*
++ * Standard memory resources
++ */
++static struct resource mem_res[] = {
++ {
++ .name = "Video RAM",
++ .start = 0,
++ .end = 0,
++ .flags = IORESOURCE_MEM},
++ {
++ .name = "Kernel text",
++ .start = 0,
++ .end = 0,
++ .flags = IORESOURCE_MEM},
++ {
++ .name = "Kernel data",
++ .start = 0,
++ .end = 0,
++ .flags = IORESOURCE_MEM}
++};
++
++#define video_ram mem_res[0]
++#define kernel_code mem_res[1]
++#define kernel_data mem_res[2]
++
++static struct resource io_res[] = {
++ {
++ .name = "reserved",
++ .start = 0x3bc,
++ .end = 0x3be,
++ .flags = IORESOURCE_IO | IORESOURCE_BUSY},
++ {
++ .name = "reserved",
++ .start = 0x378,
++ .end = 0x37f,
++ .flags = IORESOURCE_IO | IORESOURCE_BUSY},
++ {
++ .name = "reserved",
++ .start = 0x278,
++ .end = 0x27f,
++ .flags = IORESOURCE_IO | IORESOURCE_BUSY}
++};
++
++#define lp0 io_res[0]
++#define lp1 io_res[1]
++#define lp2 io_res[2]
++
++/*
++ * The following string table, must sync with HWCAP_xx bitmask,
++ * which is defined in <asm/procinfo.h>
++ */
++static const char *hwcap_str[] = {
++ "mfusr_pc",
++ "perf1",
++ "perf2",
++ "fpu",
++ "audio",
++ "16b",
++ "string",
++ "reduced_regs",
++ "video",
++ "encrypt",
++ "edm",
++ "lmdma",
++ "pfm",
++ "hsmp",
++ "trace",
++ "div",
++ "mac",
++ "l2c",
++ "dx_regs",
++ "v2",
++ NULL,
++};
++
++static void __init squash_mem_tags(struct tag *tag)
++{
++ for (; tag->hdr.size; tag = tag_next(tag))
++ if (tag->hdr.tag == ATAG_MEM)
++ tag->hdr.tag = ATAG_NONE;
++}
++
++struct cache_info L1_cache_info[2];
++
++static void __init dump_cpu_info(int cpu)
++{
++ int i = 0, aliasing_num;
++#ifdef CONFIG_CACHE_L2
++ unsigned long l2set, l2way, l2clsz;
++#endif
++ printk("CPU%d Features: ", cpu);
++
++ for (i = 0; hwcap_str[i]; i++) {
++ if (elf_hwcap & (1 << i))
++ printk("%s ", hwcap_str[i]);
++ }
++
++ printk("\n");
++
++ L1_cache_info[ICACHE].cache_type = ICACHE;
++ L1_cache_info[ICACHE].ways = CACHE_WAY(ICACHE);
++ L1_cache_info[ICACHE].way_bits = ilog2(CACHE_WAY(ICACHE));
++ L1_cache_info[ICACHE].line_size = CACHE_LINE_SIZE(ICACHE);
++ L1_cache_info[ICACHE].line_bits = ilog2(CACHE_LINE_SIZE(ICACHE));
++ L1_cache_info[ICACHE].sets = CACHE_SET(ICACHE);
++ L1_cache_info[ICACHE].set_bits = ilog2(CACHE_SET(ICACHE));
++ L1_cache_info[ICACHE].size =
++ CACHE_SET(ICACHE) * CACHE_WAY(ICACHE) * CACHE_LINE_SIZE(ICACHE) /
++ 1024;
++ printk("L1I:%dKB/%dS/%dW/%dB\n", L1_cache_info[ICACHE].size,
++ L1_cache_info[ICACHE].sets, L1_cache_info[ICACHE].ways,
++ L1_cache_info[ICACHE].line_size);
++ aliasing_num =
++ L1_cache_info[ICACHE].size * 1024 / PAGE_SIZE /
++ L1_cache_info[ICACHE].ways;
++ if (aliasing_num & 1 && aliasing_num != 1)
++ printk
++ ("%s: not alising:%d, it should be multiple of 2 if it ia aliasing cache.\n",
++ __func__, aliasing_num);
++ L1_cache_info[ICACHE].aliasing_num = aliasing_num;
++ L1_cache_info[ICACHE].aliasing_mask = (aliasing_num - 1) << PAGE_SHIFT;
++ L1_cache_info[ICACHE].not_aliasing_mask =
++ ~L1_cache_info[ICACHE].aliasing_mask;
++ L1_cache_info[DCACHE].cache_type = DCACHE;
++ L1_cache_info[DCACHE].ways = CACHE_WAY(DCACHE);
++ L1_cache_info[DCACHE].way_bits = ilog2(CACHE_WAY(DCACHE));
++ L1_cache_info[DCACHE].line_size = CACHE_LINE_SIZE(DCACHE);
++ L1_cache_info[DCACHE].line_bits = ilog2(CACHE_LINE_SIZE(DCACHE));
++ L1_cache_info[DCACHE].sets = CACHE_SET(DCACHE);
++ L1_cache_info[DCACHE].set_bits = ilog2(CACHE_SET(DCACHE));
++ L1_cache_info[DCACHE].size =
++ CACHE_SET(DCACHE) * CACHE_WAY(DCACHE) * CACHE_LINE_SIZE(DCACHE) /
++ 1024;
++ printk("L1D:%dKB/%dS/%dW/%dB\n", L1_cache_info[DCACHE].size,
++ L1_cache_info[DCACHE].sets, L1_cache_info[DCACHE].ways,
++ L1_cache_info[DCACHE].line_size);
++ aliasing_num =
++ L1_cache_info[DCACHE].size * 1024 / PAGE_SIZE /
++ L1_cache_info[DCACHE].ways;
++#ifdef CONFIG_HIGHMEM
++ if (aliasing_num > 1 && CONFIG_HIGHMEM)
++ WARN(1,
++ "%s: HIGHMEM is not supported for alising VIPT cache. aliasing_num:%d\n",
++ __func__, aliasing_num);
++#else
++ if (aliasing_num & 1 && aliasing_num != 1)
++ printk
++ ("%s: not alising:%d, it should be multiple of 2 if it ia aliasing cache.\n",
++ __func__, aliasing_num);
++#endif
++ L1_cache_info[DCACHE].aliasing_num = aliasing_num;
++ L1_cache_info[DCACHE].aliasing_mask = (aliasing_num - 1) << PAGE_SHIFT;
++ L1_cache_info[DCACHE].not_aliasing_mask =
++ ~L1_cache_info[DCACHE].aliasing_mask;
++#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
++ printk("L1 D-Cache is WRITE-THROUGH\n");
++#else
++ printk("L1 D-Cache is WRITE-BACK\n");
++#endif
++
++
++#ifdef CONFIG_CACHE_L2
++ /* Here translation is on but I/O address is not mapped yet. */
++ SET_PSW(GET_PSW() & ~PSW_mskDT);
++ DSB();
++ l2set =
++ 64 << ((inl(L2CC_PA_BASE + L2_CA_CONF_OFF) & L2_CA_CONF_mskL2SET) >>
++ L2_CA_CONF_offL2SET);
++ l2way =
++ 1 +
++ ((inl(L2CC_PA_BASE + L2_CA_CONF_OFF) & L2_CA_CONF_mskL2WAY) >>
++ L2_CA_CONF_offL2WAY);
++ l2clsz =
++ 4 << ((inl(L2CC_PA_BASE + L2_CA_CONF_OFF) & L2_CA_CONF_mskL2CLSZ) >>
++ L2_CA_CONF_offL2CLSZ);
++ SET_PSW(GET_PSW() | PSW_mskDT);
++ DSB();
++
++ printk("L2:%luKB/%luS/%luW/%luB\n",
++ l2set * l2way * l2clsz / 1024, l2set, l2way, l2clsz);
++#endif
++#ifdef CONFIG_FPU
++ /* Disable fpu and enable when it is used. */
++ disable_fpu();
++ printk("FPU is able to use.\n");
++#endif
++}
++
++static void __init setup_processor(void)
++{
++ unsigned long tmp = 0;
++ struct proc_info_list *list;
++ extern struct proc_info_list __proc_info_begin, __proc_info_end;
++
++ register unsigned coreid = GET_CPU_VER();
++ for (list = &__proc_info_begin; list < &__proc_info_end; list++)
++// if (list->cpu_val == (GET_CPU_VER() & CPU_VER_mskCPUID))
++ if (list->cpu_val == (coreid & list->cpu_mask))
++ break;
++ /*
++ * If the architecture type is not recognised, then we
++ * can co nothing...
++ */
++ if (list >= &__proc_info_end) {
++ printk
++ ("Processor configuration botched (CPU_VER 0x%lx), unable to continue.\n",
++ GET_CPU_VER());
++ while (1) ;
++ }
++
++ proc_info = *list->info;
++
++ cpu_dcache_inval_all(); // XXX head.S turn $$ on, need change.
++ cpu_icache_inval_all();
++ DSB();
++ ISB();
++
++ cpu_id = GET_CPU_ID();
++ cpu_rev = GET_CPU_REV();
++ cpu_cfgid = GET_CPU_CFGID();
++
++ printk("CPU: %s, %s %s, CPU_VER 0x%08lx(id %lu, rev %lu, cfg %lu)\n",
++ list->arch_name,
++ proc_info.manufacturer, proc_info.cpu_name,
++ GET_CPU_VER(), cpu_id, cpu_rev, cpu_cfgid);
++
++ elf_hwcap |= HWCAP_MFUSR_PC;
++
++ if (((GET_MSC_CFG() & MSC_CFG_mskBASEV) >> MSC_CFG_offBASEV) == 0) {
++ if (CPU_IS_N1213_43U1HA0() || CPU_IS_N1213_43U1HB0())
++ elf_hwcap &= ~HWCAP_MFUSR_PC;
++
++ if (GET_MSC_CFG() & MSC_CFG_mskDIV)
++ elf_hwcap |= HWCAP_DIV;
++
++ if ((GET_MSC_CFG() & MSC_CFG_mskMAC)
++ || (cpu_id == 12 && cpu_rev < 4))
++ elf_hwcap |= HWCAP_MAC;
++ } else {
++ elf_hwcap |= HWCAP_V2;
++ elf_hwcap |= HWCAP_DIV;
++ elf_hwcap |= HWCAP_MAC;
++ }
++
++ if (cpu_cfgid & 0x0001)
++ elf_hwcap |= HWCAP_EXT;
++
++ if (cpu_cfgid & 0x0002)
++ elf_hwcap |= HWCAP_BASE16;
++
++ if (cpu_cfgid & 0x0004)
++ elf_hwcap |= HWCAP_EXT2;
++
++ if (cpu_cfgid & 0x0008)
++ elf_hwcap |= HWCAP_FPU;
++
++ if (cpu_cfgid & 0x0010)
++ elf_hwcap |= HWCAP_STRING;
++
++ if (GET_MMU_CFG() & MMU_CFG_mskDE)
++ endianness = "MSB";
++ else
++ endianness = "LSB";
++
++ if (GET_MSC_CFG() & MSC_CFG_mskEDM)
++ elf_hwcap |= HWCAP_EDM;
++
++ if (GET_MSC_CFG() & MSC_CFG_mskLMDMA)
++ elf_hwcap |= HWCAP_LMDMA;
++
++ if (GET_MSC_CFG() & MSC_CFG_mskPFM)
++ elf_hwcap |= HWCAP_PFM;
++
++ if (GET_MSC_CFG() & MSC_CFG_mskHSMP)
++ elf_hwcap |= HWCAP_HSMP;
++
++ if (GET_MSC_CFG() & MSC_CFG_mskTRACE)
++ elf_hwcap |= HWCAP_TRACE;
++
++ if (GET_MSC_CFG() & MSC_CFG_mskAUDIO)
++ elf_hwcap |= HWCAP_AUDIO;
++
++ if (GET_MSC_CFG() & MSC_CFG_mskL2C)
++ elf_hwcap |= HWCAP_L2C;
++
++#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
++ if (CPU_IS_N1213_43U1HA0()) {
++ /*
++ * Downsize dcache to bypass N1213-43u1h inconsistent
++ * use of PA and VA in fill-buffer logic issue.
++ */
++
++ if ((CACHE_SET(DCACHE) * CACHE_LINE_SIZE(DCACHE)) > 4096)
++ tmp |= 0x02 << SDZ_CTL_offDCDZ;
++
++ if ((CACHE_SET(ICACHE) * CACHE_LINE_SIZE(ICACHE)) > 4096)
++ tmp |= 0x02 << SDZ_CTL_offICDZ;
++
++ SET_SDZ_CTL(tmp);
++ ISB();
++ printk("CPU%i enabled dcache downsizing to half set/4-way.\n",
++ smp_processor_id());
++ }
++#endif /* CONFIG_ANDES_PAGE_SIZE_4KB */
++
++#ifdef CONFIG_CACHE_L2
++#ifdef CONFIG_PLAT_AG102
++ SET_HSMP_SADDR((CPU_MEM_PA_BASE & HSMP_SADDR_mskSADDR) |
++ (0xC00 << HSMP_SADDR_offRANGE) | HSMP_SADDR_mskEN);
++#endif
++
++ /* Here translation is on but I/O address is not mapped yet. */
++ SET_PSW(GET_PSW() & ~PSW_mskDT);
++ DSB();
++
++ /* This is the time when we enable L2$. */
++ /* All masters can't write another master register */
++ tmp = inl(L2CC_PA_BASE + L2CC_PROT_OFF);
++ tmp &= ~L2CC_PROT_mskMRWEN;
++ outl(tmp, L2CC_PA_BASE + L2CC_PROT_OFF);
++
++ /* All masters share the whole cache memory space */
++ tmp = inl(L2CC_PA_BASE + L2CC_SETUP_OFF);
++ tmp &= ~L2CC_SETUP_mskPART;
++ outl(tmp, L2CC_PA_BASE + L2CC_SETUP_OFF);
++
++ /* each master access self master, does not add master base */
++ tmp = inl(L2CC_PA_BASE + L2CC_CTRL_OFF);
++ tmp |= L2CC_CTRL_mskEN;
++ outl(tmp, L2CC_PA_BASE + L2CC_CTRL_OFF);
++
++ SET_PSW(GET_PSW() | PSW_mskDT);
++ ISB();
++#endif
++ tmp = GET_CACHE_CTL();
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++ tmp |= CACHE_CTL_mskDC_EN;
++#endif
++
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++ tmp |= CACHE_CTL_mskIC_EN;
++#endif
++ SET_CACHE_CTL(tmp);
++ DSB();
++ ISB();
++
++ sprintf(elf_platform, "%s %s", list->elf_name, endianness);
++
++ dump_cpu_info(smp_processor_id());
++}
++
++static struct machine_desc *__init setup_machine(unsigned int nr)
++{
++ struct machine_desc *list;
++
++ extern struct machine_desc __arch_info_begin, __arch_info_end;
++ /*
++ * locate machine in the list of supported machines.
++ */
++ for (list = &__arch_info_begin; list < &__arch_info_end; list++)
++ if (list->nr == nr)
++ break;
++ /*
++ * If the architecture type is not recognised, then we
++ * can co nothing...
++ */
++ if (list >= &__arch_info_end) {
++ printk("Architecture configuration botched (nr 0x%x), unable "
++ "to continue.\n", nr);
++ while (1) ;
++ }
++
++ printk(KERN_INFO "Machine: %s\n", list->name);
++
++ return list;
++}
++
++static void __init early_initrd(char **p)
++{
++ unsigned long start, size;
++
++ start = memparse(*p, p);
++ if (**p == ',') {
++ size = memparse((*p) + 1, p);
++
++ phys_initrd_start = start; //pa
++ phys_initrd_size = size;
++ }
++ printk(KERN_INFO
++ "phys_initrd_start at 0x%08lx, phys_initrd_size:0x%08lx\n",
++ phys_initrd_start, phys_initrd_size);
++ //memblock_reserve(phys_initrd_start, phys_initrd_size);
++}
++
++__early_param("initrd=", early_initrd);
++
++/*
++ * Pick out the memory size. We look for mem=size@start,
++ * where start and size are "size[KkMm]"
++ */
++static void __init early_mem(char **p)
++{
++ static int usermem __initdata = 0;
++ unsigned long size, start;
++
++ /*
++ * If the user specifies memory size, we
++ * blow away any automatically generated
++ * size.
++ */
++ if (usermem == 0) {
++ usermem = 1;
++ meminfo.nr_banks = 0;
++ }
++
++ start = PHYS_OFFSET; //Tom 0x0
++ size = memparse(*p, p);
++ if (**p == '@')
++ start = memparse(*p + 1, p);
++
++ meminfo.bank[meminfo.nr_banks].start = start;
++ meminfo.bank[meminfo.nr_banks].size = size;
++ meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(start);
++ memblock_add_node(meminfo.bank[meminfo.nr_banks].start,
++ meminfo.bank[meminfo.nr_banks].size, 0);
++ meminfo.nr_banks += 1;
++
++}
++
++__early_param("mem=", early_mem);
++
++/*
++ * Initial parsing of the command line.
++ */
++void __init parse_cmdline(char **cmdline_p, char *from)
++{
++ char c = ' ', *to = command_line;
++ int len = 0;
++
++ for (;;) {
++ if (c == ' ') {
++ extern struct early_params __early_begin, __early_end;
++ struct early_params *p;
++
++ for (p = &__early_begin; p < &__early_end; p++) {
++ int len = strlen(p->arg);
++
++ if (memcmp(from, p->arg, len) == 0) {
++ if (to != command_line)
++ to -= 1;
++ from += len;
++ p->fn(&from);
++
++ while (*from != ' ' && *from != '\0')
++ from++;
++ break;
++ }
++ }
++ }
++ c = *from++;
++ if (!c)
++ break;
++ if (COMMAND_LINE_SIZE <= ++len)
++ break;
++ *to++ = c;
++ }
++ *to = '\0';
++ *cmdline_p = command_line;
++}
++
++static void __init
++setup_ramdisk(int doload, int prompt, int image_start, unsigned int rd_sz)
++{
++#ifdef CONFIG_BLK_DEV_RAM
++ extern int rd_size, rd_image_start, rd_prompt, rd_doload;
++
++ rd_image_start = image_start;
++ rd_prompt = prompt;
++ rd_doload = doload;
++
++ if (rd_sz)
++ rd_size = rd_sz;
++#endif
++}
++
++static void __init
++request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
++{
++ struct resource *res;
++ int i;
++
++ kernel_code.start = virt_to_phys(&_text);
++ kernel_code.end = virt_to_phys(&_etext - 1);
++ kernel_data.start = virt_to_phys(&_sdata);
++ kernel_data.end = virt_to_phys(&_end - 1);
++
++ for (i = 0; i < mi->nr_banks; i++) {
++ unsigned long virt_start, virt_end;
++
++ if (mi->bank[i].size == 0)
++ continue;
++
++ virt_start = __phys_to_virt(mi->bank[i].start);
++ virt_end = virt_start + mi->bank[i].size - 1;
++
++ res = alloc_bootmem_low(sizeof(*res));
++ res->name = "System RAM";
++ res->start = __virt_to_phys(virt_start);
++ res->end = __virt_to_phys(virt_end);
++ res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
++
++ request_resource(&iomem_resource, res);
++
++ if (kernel_code.start >= res->start &&
++ kernel_code.end <= res->end)
++ request_resource(res, &kernel_code);
++ if (kernel_data.start >= res->start &&
++ kernel_data.end <= res->end)
++ request_resource(res, &kernel_data);
++ }
++
++ if (mdesc->video_start) {
++ video_ram.start = mdesc->video_start;
++ video_ram.end = mdesc->video_end;
++ request_resource(&iomem_resource, &video_ram);
++ }
++
++ /*
++ * Some machines don't have the possibility of ever
++ * possessing lp0, lp1 or lp2
++ */
++ if (mdesc->reserve_lp0)
++ request_resource(&ioport_resource, &lp0);
++ if (mdesc->reserve_lp1)
++ request_resource(&ioport_resource, &lp1);
++ if (mdesc->reserve_lp2)
++ request_resource(&ioport_resource, &lp2);
++}
++
++/*
++ * Tag parsing.
++ *
++ * This is the new way of passing data to the kernel at boot time. Rather
++ * than passing a fixed inflexible structure to the kernel, we pass a list
++ * of variable-sized tags to the kernel. The first tag must be a ATAG_CORE
++ * tag for the list to be recognised (to distinguish the tagged list from
++ * a param_struct). The list is terminated with a zero-length tag (this tag
++ * is not parsed in any way).
++ */
++//flag bit 0 = read-only
++static int __init parse_tag_core(const struct tag *tag)
++{
++ if (tag->hdr.size > 2) {
++ if ((tag->u.core.flags & 1) == 0)
++ root_mountflags &= ~MS_RDONLY;
++ ROOT_DEV = old_decode_dev(tag->u.core.rootdev);
++ }
++ return 0;
++}
++
++__tagtable(ATAG_CORE, parse_tag_core);
++
++static int __init parse_tag_mem32(const struct tag *tag)
++{
++ if (meminfo.nr_banks >= NR_BANKS) {
++ printk(KERN_WARNING
++ "Ignoring memory bank 0x%08x size %dKB\n",
++ tag->u.mem.start, tag->u.mem.size / 1024);
++ return -EINVAL;
++ }
++ meminfo.bank[meminfo.nr_banks].start = tag->u.mem.start;
++ meminfo.bank[meminfo.nr_banks].size = tag->u.mem.size;
++ memblock_add_node(meminfo.bank[meminfo.nr_banks].start,
++ meminfo.bank[meminfo.nr_banks].size, 0);
++ meminfo.bank[meminfo.nr_banks].node = PHYS_TO_NID(tag->u.mem.start);
++ meminfo.nr_banks += 1;
++
++ return 0;
++}
++
++__tagtable(ATAG_MEM, parse_tag_mem32);
++
++#if defined(CONFIG_VGA_CONSOLE) || defined(CONFIG_DUMMY_CONSOLE)
++struct screen_info screen_info = {
++ .orig_video_lines = 30,
++ .orig_video_cols = 80,
++ .orig_video_mode = 0,
++ .orig_video_ega_bx = 0,
++ .orig_video_isVGA = 1,
++ .orig_video_points = 8
++};
++
++static int __init parse_tag_videotext(const struct tag *tag)
++{
++ screen_info.orig_x = tag->u.videotext.x;
++ screen_info.orig_y = tag->u.videotext.y;
++ screen_info.orig_video_page = tag->u.videotext.video_page;
++ screen_info.orig_video_mode = tag->u.videotext.video_mode;
++ screen_info.orig_video_cols = tag->u.videotext.video_cols;
++ screen_info.orig_video_ega_bx = tag->u.videotext.video_ega_bx;
++ screen_info.orig_video_lines = tag->u.videotext.video_lines;
++ screen_info.orig_video_isVGA = tag->u.videotext.video_isvga;
++ screen_info.orig_video_points = tag->u.videotext.video_points;
++ return 0;
++}
++
++__tagtable(ATAG_VIDEOTEXT, parse_tag_videotext);
++#endif
++
++static int __init parse_tag_ramdisk(const struct tag *tag)
++{
++ setup_ramdisk((tag->u.ramdisk.flags & 1) == 0,
++ (tag->u.ramdisk.flags & 2) == 0,
++ tag->u.ramdisk.start, tag->u.ramdisk.size);
++ return 0;
++}
++
++__tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
++
++static int __init parse_tag_initrd(const struct tag *tag)
++{
++ printk(KERN_WARNING "ATAG_INITRD is deprecated; "
++ "please update your bootloader.\n");
++ phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
++ phys_initrd_size = tag->u.initrd.size;
++ return 0;
++}
++
++__tagtable(ATAG_INITRD, parse_tag_initrd);
++
++static int __init parse_tag_initrd2(const struct tag *tag)
++{
++ phys_initrd_start = tag->u.initrd.start;
++ phys_initrd_size = tag->u.initrd.size;
++ return 0;
++}
++
++__tagtable(ATAG_INITRD2, parse_tag_initrd2);
++
++static int __init parse_tag_revision(const struct tag *tag)
++{
++ return 0;
++}
++
++__tagtable(ATAG_REVISION, parse_tag_revision);
++
++static int __init parse_tag_cmdline(const struct tag *tag)
++{
++ strlcpy(default_command_line, tag->u.cmdline.cmdline,
++ COMMAND_LINE_SIZE);
++ return 0;
++}
++
++__tagtable(ATAG_CMDLINE, parse_tag_cmdline);
++
++/*
++ * Scan the tag table for this tag, and call its parse function.
++ * The tag table is built by the linker from all the __tagtable
++ * declarations.
++ */
++static int __init parse_tag(const struct tag *tag)
++{
++ extern struct tagtable __tagtable_begin, __tagtable_end;
++ struct tagtable *t;
++
++ for (t = &__tagtable_begin; t < &__tagtable_end; t++)
++ if (tag->hdr.tag == t->tag) {
++ t->parse(tag);
++ break;
++ }
++
++ return t < &__tagtable_end;
++}
++
++/*
++ * Parse all tags in the list, checking both the global and architecture
++ * specific tag tables.
++ */
++static void __init parse_tags(const struct tag *t)
++{
++ for (; t->hdr.size; t = tag_next(t))
++ if (!parse_tag(t))
++ printk(KERN_WARNING
++ "Ignoring unrecognised tag 0x%08x\n",
++ t->hdr.tag);
++}
++
++/*
++ * This holds our defaults.
++ */
++static struct init_tags {
++ struct tag_header hdr1;
++ struct tag_core core;
++ struct tag_header hdr2;
++ struct tag_mem32 mem;
++ struct tag_header hdr3;
++} init_tags __initdata = {
++ {tag_size(tag_core), ATAG_CORE}, //hdr1
++ {0, PAGE_SIZE, 0xff},
++ {tag_size(tag_mem32), ATAG_MEM}, //hdr2
++ {MEM_SIZE, PHYS_OFFSET},
++ {0, ATAG_NONE}
++};
++
++static unsigned long __init setup_memory(void)
++{
++ unsigned long bootmap_size;
++ unsigned long ram_start_pfn;
++ unsigned long free_ram_start_pfn;
++ phys_addr_t memory_start, memory_end;
++ struct memblock_region *region;
++
++ memory_end = memory_start = 0;
++
++ /* Find main memory where is the kernel */
++ for_each_memblock(memory, region) {
++ memory_start = region->base;
++ memory_end = region->base + region->size;
++ printk(KERN_INFO "%s: Memory: 0x%x-0x%x\n", __func__,
++ memory_start, memory_end);
++ }
++
++ if (!memory_end) {
++ panic("No memory!");
++ }
++
++ ram_start_pfn = PFN_UP(memblock_start_of_DRAM());
++ /* free_ram_start_pfn is first page after kernel */
++ free_ram_start_pfn = PFN_UP(__pa(&_end));
++ max_pfn = PFN_DOWN(memblock_end_of_DRAM());
++
++ /* it could update max_pfn */
++ if (max_pfn - ram_start_pfn <= MAXMEM_PFN)
++ max_low_pfn = max_pfn;
++ else {
++ max_low_pfn = MAXMEM_PFN + ram_start_pfn;
++#ifndef CONFIG_HIGHMEM
++ max_pfn = MAXMEM_PFN + ram_start_pfn;
++#endif
++ }
++ /* high_memory is related with VMALLOC */
++ high_memory = (void *)__va(max_low_pfn * PAGE_SIZE);
++ min_low_pfn = free_ram_start_pfn;
++
++ /*
++ * initialize the boot-time allocator (with low memory only).
++ *
++ * This makes the memory from the end of the kernel to the end of
++ * RAM usable.
++ * init_bootmem sets the global values min_low_pfn, max_low_pfn.
++ */
++ bootmap_size = init_bootmem_node(NODE_DATA(0), free_ram_start_pfn,
++ ram_start_pfn, max_low_pfn);
++ free_bootmem(PFN_PHYS(free_ram_start_pfn),
++ (max_low_pfn - free_ram_start_pfn) << PAGE_SHIFT);
++ reserve_bootmem(PFN_PHYS(free_ram_start_pfn), bootmap_size,
++ BOOTMEM_DEFAULT);
++
++ for_each_memblock(reserved, region) {
++ if (region->size != 0) {
++ printk(KERN_INFO "Reserved - 0x%08x-0x%08x\n",
++ (u32) region->base, (u32) region->size);
++ reserve_bootmem(region->base, region->size,
++ BOOTMEM_DEFAULT);
++ }
++ }
++ return max_low_pfn;
++}
++
++void __init setup_arch(char **cmdline_p)
++{
++ struct tag *tags = (struct tag *)&init_tags;
++ struct machine_desc *mdesc;
++ char *from = default_command_line;
++
++ setup_processor();
++ mdesc = setup_machine(machine_arch_type);
++ machine_desc = mdesc;
++ machine_name = mdesc->name;
++
++ if (mdesc->soft_reboot)
++ reboot_setup("s");
++
++ if (mdesc->param_offset)
++ tags = phys_to_virt(mdesc->param_offset);
++
++ if (tags->hdr.tag != ATAG_CORE)
++ tags = (struct tag *)&init_tags;
++
++ if (tags->hdr.tag == ATAG_CORE) {
++ if (meminfo.nr_banks != 0)
++ squash_mem_tags(tags);
++ parse_tags(tags);
++ }
++
++ init_mm.start_code = (unsigned long)&_text;
++ init_mm.end_code = (unsigned long)&_etext;
++ init_mm.end_data = (unsigned long)&_edata;
++ init_mm.brk = (unsigned long)&_end;
++
++ memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
++ boot_command_line[COMMAND_LINE_SIZE - 1] = '\0';
++ parse_cmdline(cmdline_p, from);
++
++ /* use generic way to parse */
++ parse_early_param();
++
++ /* setup bootmem allocator */
++ setup_memory();
++
++ strlcpy(command_line, from, COMMAND_LINE_SIZE);
++ *cmdline_p = command_line;
++
++ paging_init(mdesc);
++ request_standard_resources(&meminfo, mdesc); //- for test only
++
++#ifdef CONFIG_SMP
++ smp_init_cpus();
++#endif
++
++ /*
++ * Set up various architecture-specific pointers
++ */
++ init_arch_irq = mdesc->init_irq;
++ system_timer = mdesc->timer;
++ if (mdesc->init_machine)
++ mdesc->init_machine();
++
++#if defined(CONFIG_VT)
++#if defined(CONFIG_VGA_CONSOLE)
++ conswitchp = &vga_con;
++#elif defined(CONFIG_DUMMY_CONSOLE)
++ conswitchp = &dummy_con; //+ Tom: we will reach here
++#endif
++#endif
++
++ early_trap_init();
++}
++
++/*
++ * cpu_init - initialise one CPU.
++ *
++ * cpu_init dumps the cache information, initialises SMP specific
++ * information.
++ */
++
++void __init cpu_init(void)
++{
++ unsigned int cpu = smp_processor_id(), tmp = 0;
++
++ if (cpu >= NR_CPUS) {
++ printk(KERN_CRIT "CPU%u: bad primary CPU number\n", cpu);
++ BUG();
++ }
++
++ if (system_state == SYSTEM_BOOTING)
++ dump_cpu_info(cpu);
++
++ tmp = 1 << IVB_offESZ;
++#ifdef CONFIG_EVIC
++ tmp |= 1 << IVB_offEVIC;
++#endif
++ SET_IVB(tmp | IVB_BASE);
++ tmp = 0x10003;
++ SET_INT_MASK(tmp);
++ ISB();
++}
++
++static int __init topology_init(void)
++{
++ int cpu;
++
++ for_each_possible_cpu(cpu)
++ register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu);
++
++ return 0;
++}
++
++subsys_initcall(topology_init);
++
++static int c_show(struct seq_file *m, void *v)
++{
++ int i;
++
++ seq_printf(m, "Processor\t: %s %s (id %lu, rev %lu, cfg %lu)\n",
++ proc_info.manufacturer, proc_info.cpu_name,
++ cpu_id, cpu_rev, cpu_cfgid);
++#if defined(CONFIG_AG101_CPU_FREQ_SCALING_MODE) || defined(CONFIG_AG101_CPU_FREQ_FCS)
++ seq_printf(m, "MHz\t\t: %u\n", ag101_cpufreq_get(1) / 1000);
++#endif
++
++ seq_printf(m, "L1I\t\t: %luKB/%luS/%luW/%luB\n",
++ CACHE_SET(ICACHE) * CACHE_WAY(ICACHE) *
++ CACHE_LINE_SIZE(ICACHE) / 1024, CACHE_SET(ICACHE),
++ CACHE_WAY(ICACHE), CACHE_LINE_SIZE(ICACHE));
++
++ seq_printf(m, "L1D\t\t: %luKB/%luS/%luW/%luB\n",
++ CACHE_SET(DCACHE) * CACHE_WAY(DCACHE) *
++ CACHE_LINE_SIZE(DCACHE) / 1024, CACHE_SET(DCACHE),
++ CACHE_WAY(DCACHE), CACHE_LINE_SIZE(DCACHE));
++
++#if defined(CONFIG_SMP)
++ for_each_online_cpu(i) {
++ seq_printf(m, "Processor\t: %d\n", i);
++ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
++ per_cpu(cpu_data,
++ i).loops_per_jiffy / (500000UL / HZ),
++ (per_cpu(cpu_data, i).loops_per_jiffy /
++ (5000UL / HZ)) % 100);
++ }
++#else /* CONFIG_SMP */
++ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
++ loops_per_jiffy / (500000 / HZ),
++ (loops_per_jiffy / (5000 / HZ)) % 100);
++#endif
++
++ /* dump out the processor features */
++ seq_puts(m, "Features\t: ");
++
++ for (i = 0; hwcap_str[i]; i++)
++ if (elf_hwcap & (1 << i))
++ seq_printf(m, "%s ", hwcap_str[i]);
++
++ seq_puts(m, "\n\n");
++ seq_printf(m, "Hardware\t: %s\n", elf_platform);
++
++ return 0;
++}
++
++static void *c_start(struct seq_file *m, loff_t * pos)
++{
++ return *pos < 1 ? (void *)1 : NULL;
++}
++
++static void *c_next(struct seq_file *m, void *v, loff_t * pos)
++{
++ ++*pos;
++ return NULL;
++}
++
++static void c_stop(struct seq_file *m, void *v)
++{
++}
++
++struct seq_operations cpuinfo_op = {
++ .start = c_start,
++ .next = c_next,
++ .stop = c_stop,
++ .show = c_show
++};
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/signal.c linux-3.4.110/arch/nds32/kernel/signal.c
+--- linux-3.4.110.orig/arch/nds32/kernel/signal.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/signal.c 2016-04-07 10:20:50.946081179 +0200
+@@ -0,0 +1,850 @@
++/*
++ * linux/arch/nds32/kernel/signal.c
++ *
++ * Copyright (C) 1995-2002 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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/errno.h>
++#include <linux/signal.h>
++#include <linux/ptrace.h>
++#include <linux/personality.h>
++#include <linux/freezer.h>
++#include <linux/tracehook.h>
++
++#include <asm/cacheflush.h>
++#include <asm/ucontext.h>
++#include <asm/uaccess.h>
++#include <asm/unistd.h>
++#include <asm/fpu.h>
++#include <asm/audio.h>
++
++#include "ptrace.h"
++#include "signal.h"
++#include "fpu.h"
++#include "audio.h"
++
++#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
++
++/*
++ * For NDS32 syscalls, we encode the syscall number into the instruction.
++ */
++#if defined( __NDS32_EL__)
++#define SWI_SYS_SIGRETURN (0xeb0e0a64)
++#define SWI_SYS_RT_SIGRETURN (0xab150a64)
++#define SWI_SYS_RESTART (0x0b000a64) /* syscall __NR_restart_syscall */
++#define SWI_SYS_RESTART_LWIBI (0x0180af0d) /* lwi.bi $p0, [$sp], 4 */
++#define SWI_SYS_RESTART_JRP0 (0x0068004a) /* jr $p0 */
++#elif defined(__NDS32_EB__)
++#define SWI_SYS_SIGRETURN (0x6400000b|(__NR_sigreturn<<5))
++#define SWI_SYS_RT_SIGRETURN (0x6400000b|(__NR_rt_sigreturn<<5))
++#define SWI_SYS_RESTART (0x640a000b) /* syscall __NR_restart_syscall */
++#define SWI_SYS_RESTART_LWIBI (0x0daf8001) /* lwi.bi $p0, [$sp], 4 */
++#define SWI_SYS_RESTART_JRP0 (0x4a006800) /* jr $p0 */
++#else
++#error "NDS32, but neither __NDS32_EB__, nor __NDS32_EL__???"
++#endif
++
++#ifdef CONFIG_FPU
++static struct fpu_struct init_fpuregs = {
++ .fs_regs = {[0 ... 31] = sNAN32},
++ .fd_regs = {[0 ... 15] = sNAN64},
++ .fpcsr = FPCSR_INIT
++};
++#endif
++#ifdef CONFIG_AUDIO
++static struct audio_struct init_audioregs = {
++ .auregs = {[0...31] = NAN32}
++};
++#endif
++const unsigned long retcodes[2] = {
++ SWI_SYS_SIGRETURN,
++ SWI_SYS_RT_SIGRETURN
++};
++
++const unsigned long syscall_restart_code[3] = {
++ SWI_SYS_RESTART, /* syscall __NR_restart_syscall */
++ SWI_SYS_RESTART_LWIBI, /* lwi.bi $p0, [$sp], 4 */
++ SWI_SYS_RESTART_JRP0 /* jr $p0 */
++};
++
++static int do_signal(sigset_t * oldset, struct pt_regs *regs, int syscall);
++
++/*
++ * atomically swap in the new signal mask, and wait for a signal.
++ */
++asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask,
++ old_sigset_t mask, struct pt_regs *regs)
++{
++ sigset_t blocked;
++
++ mask &= _BLOCKABLE;
++ current->saved_sigmask = current->blocked;
++ siginitset(&blocked, mask);
++ set_current_blocked(&blocked);
++
++ current->state = TASK_INTERRUPTIBLE;
++ schedule();
++ set_thread_flag(TIF_RESTORE_SIGMASK);
++ return -ERESTARTNOHAND;
++}
++
++asmlinkage int sys_rt_sigsuspend(sigset_t __user * unewset, size_t sigsetsize,
++ struct pt_regs *regs)
++{
++ sigset_t newset;
++
++ /* XXX: Don't preclude handling different sized sigset_t's. */
++ if (sigsetsize != sizeof(sigset_t))
++ return -EINVAL;
++
++ if (copy_from_user(&newset, unewset, sizeof(newset)))
++ return -EFAULT;
++ sigdelsetmask(&newset, ~_BLOCKABLE);
++ current->saved_sigmask = current->blocked;
++ set_current_blocked(&newset);
++ current->state = TASK_INTERRUPTIBLE;
++ schedule();
++ set_thread_flag(TIF_RESTORE_SIGMASK);
++ return -ERESTARTNOHAND;
++}
++
++asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user * act,
++ struct old_sigaction __user * oact)
++{
++ struct k_sigaction new_ka, old_ka;
++ int ret;
++
++ if (act) {
++ old_sigset_t mask;
++ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
++ __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
++ __get_user(new_ka.sa.sa_restorer, &act->sa_restorer)) {
++
++ return -EFAULT;
++ }
++ __get_user(new_ka.sa.sa_flags, &act->sa_flags);
++ __get_user(mask, &act->sa_mask);
++
++ siginitset(&new_ka.sa.sa_mask, mask);
++ }
++
++ ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
++
++ if (!ret && oact) {
++
++ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
++ __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
++ __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer)) {
++
++ return -EFAULT;
++ }
++ __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
++ __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
++ }
++
++ return ret;
++}
++
++/*
++ * Auxiliary signal frame. This saves stuff like FP state.
++ * The layout of this structure is not part of the user ABI.
++ */
++struct aux_sigframe {
++};
++
++/*
++ * Do a signal return; undo the signal stack. These are aligned to 64-bit.
++ */
++struct sigframe {
++ struct sigcontext sc;
++ unsigned long extramask[_NSIG_WORDS - 1];
++ unsigned long retcode;
++ struct aux_sigframe aux __attribute__ ((aligned(8)));
++};
++
++struct rt_sigframe {
++ struct siginfo __user *pinfo;
++ void __user *puc;
++ struct siginfo info;
++ struct ucontext uc;
++ unsigned long retcode;
++ struct aux_sigframe aux __attribute__ ((aligned(8)));
++};
++
++#ifdef CONFIG_FPU
++static inline int restore_sigcontext_fpu(struct pt_regs *regs,
++ struct sigcontext __user * sc)
++{
++ struct task_struct *tsk = current;
++ unsigned long used_math_flag;
++ int ret = 0;
++
++ if (!(GET_FUCOP_EXIST() & FUCOP_EXIST_mskCP0ISFPU))
++ return 0;
++
++ __get_user_error(used_math_flag, &sc->used_math_flag, ret);
++
++ if (!used_math_flag)
++ return 0;
++
++ set_used_math();
++
++#ifdef CONFIG_UNLAZY_FPU
++ clear_fpu(regs);
++#else
++ preempt_disable();
++ if (current == last_task_used_math) {
++ last_task_used_math = NULL;
++ release_fpu(regs);
++ }
++ preempt_enable();
++#endif
++
++ return __copy_from_user(&tsk->thread.fpu, &sc->fpu,
++ sizeof(struct fpu_struct));
++}
++
++static inline int setup_sigcontext_fpu(struct pt_regs *regs,
++ struct sigcontext __user * sc)
++{
++ struct task_struct *tsk = current;
++ int ret = 0;
++
++ if (!(GET_FUCOP_EXIST() & FUCOP_EXIST_mskCP0ISFPU))
++ return 0;
++
++ __put_user_error(used_math(), &sc->used_math_flag, ret);
++
++ if (!used_math())
++ return ret;
++
++ preempt_disable();
++#ifdef CONFIG_UNLAZY_FPU
++ unlazy_fpu(tsk);
++#else
++ if (last_task_used_math != NULL)
++ save_fpu(last_task_used_math);
++#endif
++ ret = __copy_to_user(&sc->fpu, &tsk->thread.fpu,
++ sizeof(struct fpu_struct));
++
++ grab_fpu(task_pt_regs(tsk));
++ fpload(&init_fpuregs);
++#ifndef CONFIG_UNLAZY_FPU //Lazy FPU
++ last_task_used_math = current;
++#endif
++ preempt_enable();
++ return ret;
++}
++#else
++static inline int
++restore_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user * sc)
++{
++ return 0;
++}
++
++static inline int
++setup_sigcontext_fpu(struct pt_regs *regs, struct sigcontext __user * sc)
++{
++ return 0;
++}
++#endif /* CONFIG_FPU */
++
++#ifdef CONFIG_AUDIO
++static inline int restore_sigcontext_audio(struct pt_regs *regs,
++ struct sigcontext __user * sc)
++{
++ struct task_struct *tsk = current;
++ unsigned long used_audio_flag;
++ int ret = 0;
++
++ if (!(GET_MSC_CFG() & MSC_CFG_mskAUDIO))
++ return 0;
++
++ __get_user_error(used_audio_flag, &sc->used_audio_flag, ret);
++
++ if (!used_audio_flag)
++ return 0;
++
++ set_tsk_thread_flag(tsk, TIF_USEDAUDIO);
++#ifdef CONFIG_UNLAZY_AUDIO
++ clear_audio(regs);
++#else
++ preempt_disable();
++ if (current == last_task_used_audio) {
++ last_task_used_audio = NULL;
++ clear_audio(regs);
++ }
++ preempt_enable();
++#endif
++
++ return __copy_from_user(&tsk->thread.audio, &sc->audio,
++ sizeof(struct audio_struct));
++}
++
++static inline int setup_sigcontext_audio(struct pt_regs *regs,
++ struct sigcontext __user * sc)
++{
++ struct task_struct *tsk = current;
++ int ret = 0;
++
++ if (!(GET_MSC_CFG() & MSC_CFG_mskAUDIO))
++ return 0;
++
++ __put_user_error(test_tsk_thread_flag(tsk, TIF_USEDAUDIO),
++ &sc->used_audio_flag, ret);
++
++ if (!test_tsk_thread_flag(tsk, TIF_USEDAUDIO))
++ return ret;
++
++ preempt_disable();
++#ifdef CONFIG_UNLAZY_AUDIO
++ unlazy_audio(tsk);
++#else
++ if (NULL != last_task_used_audio) {
++ save_audio(tsk);
++ }
++#endif
++ ret = __copy_to_user(&sc->audio, &tsk->thread.audio,
++ sizeof(struct audio_struct));
++
++ grab_audio(task_pt_regs(tsk));
++ audioload(&init_audioregs);
++#ifndef CONFIG_UNLAZY_AUDIO //Lazy audio
++ last_task_used_audio = current;
++#endif
++ preempt_enable();
++ return ret;
++}
++#else /*CONFIG_AUDIO */
++static inline int
++restore_sigcontext_audio(struct pt_regs *regs, struct sigcontext __user * sc)
++{
++ return 0;
++}
++
++static inline int
++setup_sigcontext_audio(struct pt_regs *regs, struct sigcontext __user * sc)
++{
++ return 0;
++}
++#endif
++
++static int restore_sigcontext(struct pt_regs *regs,
++ struct sigcontext __user * sc,
++ struct aux_sigframe __user * aux)
++{
++ int err = 0;
++
++ __get_user_error(regs->NDS32_r0, &sc->nds32_r0, err);
++ __get_user_error(regs->NDS32_r1, &sc->nds32_r1, err);
++ __get_user_error(regs->NDS32_r2, &sc->nds32_r2, err);
++ __get_user_error(regs->NDS32_r3, &sc->nds32_r3, err);
++ __get_user_error(regs->NDS32_r4, &sc->nds32_r4, err);
++ __get_user_error(regs->NDS32_r5, &sc->nds32_r5, err);
++ __get_user_error(regs->NDS32_r6, &sc->nds32_r6, err);
++ __get_user_error(regs->NDS32_r7, &sc->nds32_r7, err);
++ __get_user_error(regs->NDS32_r8, &sc->nds32_r8, err);
++ __get_user_error(regs->NDS32_r9, &sc->nds32_r9, err);
++ __get_user_error(regs->NDS32_r10, &sc->nds32_r10, err);
++ __get_user_error(regs->NDS32_r11, &sc->nds32_r11, err);
++ __get_user_error(regs->NDS32_r12, &sc->nds32_r12, err);
++ __get_user_error(regs->NDS32_r13, &sc->nds32_r13, err);
++ __get_user_error(regs->NDS32_r14, &sc->nds32_r14, err);
++ __get_user_error(regs->NDS32_r15, &sc->nds32_r15, err);
++ __get_user_error(regs->NDS32_r16, &sc->nds32_r16, err);
++ __get_user_error(regs->NDS32_r17, &sc->nds32_r17, err);
++ __get_user_error(regs->NDS32_r18, &sc->nds32_r18, err);
++ __get_user_error(regs->NDS32_r19, &sc->nds32_r19, err);
++ __get_user_error(regs->NDS32_r20, &sc->nds32_r20, err);
++
++ __get_user_error(regs->NDS32_r21, &sc->nds32_r21, err);
++ __get_user_error(regs->NDS32_r22, &sc->nds32_r22, err);
++ __get_user_error(regs->NDS32_r23, &sc->nds32_r23, err);
++ __get_user_error(regs->NDS32_r24, &sc->nds32_r24, err);
++ __get_user_error(regs->NDS32_r25, &sc->nds32_r25, err);
++ __get_user_error(regs->NDS32_fp, &sc->nds32_fp, err);
++ __get_user_error(regs->NDS32_gp, &sc->nds32_gp, err);
++ __get_user_error(regs->NDS32_lp, &sc->nds32_lr, err);
++ __get_user_error(regs->NDS32_sp, &sc->nds32_sp, err);
++
++ __get_user_error(regs->NDS32_ipc, &sc->nds32_ipc, err);
++#if defined(CONFIG_HWZOL)
++ __get_user_error(regs->NDS32_lc, &sc->zol.nds32_lc, err);
++ __get_user_error(regs->NDS32_le, &sc->zol.nds32_le, err);
++ __get_user_error(regs->NDS32_lb, &sc->zol.nds32_lb, err);
++#endif
++
++ err |= !valid_user_regs(regs);
++ err |= restore_sigcontext_audio(regs, sc);
++ err |= restore_sigcontext_fpu(regs, sc);
++
++ return err;
++}
++
++asmlinkage int sys_sigreturn(struct pt_regs *regs)
++{
++ struct sigframe __user *frame;
++ sigset_t set;
++
++ /* Always make any pending restarted system calls return -EINTR */
++ current_thread_info()->restart_block.fn = do_no_restart_syscall;
++
++ /*
++ * Since we stacked the signal on a 64-bit boundary,
++ * then 'sp' should be word aligned here. If it's
++ * not, then the user is trying to mess with us.
++ */
++ if (regs->NDS32_sp & 7)
++ goto badframe;
++
++ frame = (struct sigframe __user *)regs->NDS32_sp;
++
++ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
++ goto badframe;
++
++ if (__get_user(set.sig[0], &frame->sc.oldmask)
++ || (_NSIG_WORDS > 1
++ && __copy_from_user(&set.sig[1], &frame->extramask,
++ sizeof(frame->extramask))))
++ goto badframe;
++
++ sigdelsetmask(&set, ~_BLOCKABLE);
++ spin_lock_irq(&current->sighand->siglock);
++ current->blocked = set;
++ recalc_sigpending();
++ spin_unlock_irq(&current->sighand->siglock);
++
++ if (restore_sigcontext(regs, &frame->sc, &frame->aux))
++ goto badframe;
++
++ return regs->NDS32_r0;
++
++badframe:
++ force_sig(SIGSEGV, current);
++ return 0;
++}
++
++asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
++{
++ struct rt_sigframe __user *frame;
++ sigset_t set;
++
++ /* Always make any pending restarted system calls return -EINTR */
++ current_thread_info()->restart_block.fn = do_no_restart_syscall;
++
++ /*
++ * Since we stacked the signal on a 64-bit boundary,
++ * then 'sp' should be word aligned here. If it's
++ * not, then the user is trying to mess with us.
++ */
++ if (regs->NDS32_sp & 7)
++ goto badframe;
++
++ frame = (struct rt_sigframe __user *)regs->NDS32_sp;
++
++ if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
++ goto badframe;
++
++ if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
++ goto badframe;
++
++ sigdelsetmask(&set, ~_BLOCKABLE);
++ spin_lock_irq(&current->sighand->siglock);
++ current->blocked = set;
++ recalc_sigpending();
++ spin_unlock_irq(&current->sighand->siglock);
++
++ if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &frame->aux))
++ goto badframe;
++
++ if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->NDS32_sp) ==
++ -EFAULT)
++ goto badframe;
++
++ return regs->NDS32_r0;
++
++badframe:
++ force_sig(SIGSEGV, current);
++ return 0;
++}
++
++static int setup_sigcontext(struct sigcontext __user * sc,
++ struct aux_sigframe __user * aux,
++ struct pt_regs *regs, unsigned long mask)
++{
++ int err = 0;
++
++ err |= setup_sigcontext_fpu(regs, sc);
++ err |= setup_sigcontext_audio(regs, sc);
++
++ __put_user_error(regs->NDS32_r0, &sc->nds32_r0, err);
++ __put_user_error(regs->NDS32_r1, &sc->nds32_r1, err);
++ __put_user_error(regs->NDS32_r2, &sc->nds32_r2, err);
++ __put_user_error(regs->NDS32_r3, &sc->nds32_r3, err);
++ __put_user_error(regs->NDS32_r4, &sc->nds32_r4, err);
++ __put_user_error(regs->NDS32_r5, &sc->nds32_r5, err);
++ __put_user_error(regs->NDS32_r6, &sc->nds32_r6, err);
++ __put_user_error(regs->NDS32_r7, &sc->nds32_r7, err);
++ __put_user_error(regs->NDS32_r8, &sc->nds32_r8, err);
++ __put_user_error(regs->NDS32_r9, &sc->nds32_r9, err);
++ __put_user_error(regs->NDS32_r10, &sc->nds32_r10, err);
++ __put_user_error(regs->NDS32_r11, &sc->nds32_r11, err);
++ __put_user_error(regs->NDS32_r12, &sc->nds32_r12, err);
++ __put_user_error(regs->NDS32_r13, &sc->nds32_r13, err);
++ __put_user_error(regs->NDS32_r14, &sc->nds32_r14, err);
++ __put_user_error(regs->NDS32_r15, &sc->nds32_r15, err);
++ __put_user_error(regs->NDS32_r16, &sc->nds32_r16, err);
++ __put_user_error(regs->NDS32_r17, &sc->nds32_r17, err);
++ __put_user_error(regs->NDS32_r18, &sc->nds32_r18, err);
++ __put_user_error(regs->NDS32_r19, &sc->nds32_r19, err);
++ __put_user_error(regs->NDS32_r20, &sc->nds32_r20, err);
++
++ __put_user_error(regs->NDS32_r21, &sc->nds32_r21, err);
++ __put_user_error(regs->NDS32_r22, &sc->nds32_r22, err);
++ __put_user_error(regs->NDS32_r23, &sc->nds32_r23, err);
++ __put_user_error(regs->NDS32_r24, &sc->nds32_r24, err);
++ __put_user_error(regs->NDS32_r25, &sc->nds32_r25, err);
++ __put_user_error(regs->NDS32_fp, &sc->nds32_fp, err);
++ __put_user_error(regs->NDS32_gp, &sc->nds32_gp, err);
++ __put_user_error(regs->NDS32_lp, &sc->nds32_lr, err);
++ __put_user_error(regs->NDS32_sp, &sc->nds32_sp, err);
++ __put_user_error(regs->NDS32_ipc, &sc->nds32_ipc, err);
++#if defined(CONFIG_HWZOL)
++ __get_user_error(regs->NDS32_lc, &sc->zol.nds32_lc, err);
++ __get_user_error(regs->NDS32_le, &sc->zol.nds32_le, err);
++ __get_user_error(regs->NDS32_lb, &sc->zol.nds32_lb, err);
++#endif
++
++ __put_user_error(current->thread.trap_no, &sc->trap_no, err);
++ __put_user_error(current->thread.error_code, &sc->error_code, err);
++ __put_user_error(current->thread.address, &sc->fault_address, err);
++ __put_user_error(mask, &sc->oldmask, err);
++
++ return err;
++}
++
++static inline void __user *get_sigframe(struct k_sigaction *ka,
++ struct pt_regs *regs, int framesize)
++{
++ unsigned long sp = regs->NDS32_sp;
++ void __user *frame;
++
++ /*
++ * This is the X/Open sanctioned signal stack switching.
++ */
++ if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
++ sp = current->sas_ss_sp + current->sas_ss_size;
++
++ /*
++ * ATPCS B01 mandates 8-byte alignment
++ */
++ frame = (void __user *)((sp - framesize) & ~7);
++
++ /*
++ * Check that we can actually write to the signal frame.
++ */
++ if (!access_ok(VERIFY_WRITE, frame, framesize))
++ frame = NULL;
++
++ return frame;
++}
++
++static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
++ unsigned long __user * rc, void __user * frame,
++ int usig)
++{
++ unsigned long handler = (unsigned long)ka->sa.sa_handler;
++ unsigned long retcode;
++ struct sigframe *sf = (struct sigframe *)frame;
++
++ /*
++ * Maybe we need to deliver a 32-bit signal to a 26-bit task.
++ */
++ if (ka->sa.sa_flags & SA_RESTORER) {
++ retcode = (unsigned long)ka->sa.sa_restorer;
++ } else {
++
++ unsigned int idx = 0; //thumb;
++ unsigned long line_size = CACHE_LINE_SIZE(ICACHE);
++ unsigned long start, end;
++
++ if (ka->sa.sa_flags & SA_SIGINFO)
++ idx++;
++
++ if (__put_user(retcodes[idx], rc))
++ return 1;
++
++ /*
++ * Ensure that the instruction cache sees
++ * the return code written onto the stack.
++ */
++ start = (unsigned long)rc & ~(line_size - 1);
++ end = start + line_size;
++ flush_icache_range(start, end);
++
++ retcode = KERN_SIGRETURN_CODE + (idx << 2);
++ }
++
++ regs->NDS32_r0 = usig;
++ regs->NDS32_r1 = 0;
++ regs->NDS32_r2 = (unsigned long)&sf->sc;
++ regs->NDS32_sp = (unsigned long)frame;
++ regs->NDS32_lp = retcode;
++ regs->NDS32_ipc = handler;
++ /* Also store handler address in r15 for updating GP in the handler. */
++ regs->NDS32_r15 = handler;
++
++ return 0;
++}
++
++static int setup_frame(int usig, struct k_sigaction *ka, sigset_t * set,
++ struct pt_regs *regs)
++{
++ struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
++ int err = 0;
++
++ if (!frame)
++ return 1;
++
++ err |= setup_sigcontext(&frame->sc, &frame->aux, regs, set->sig[0]);
++
++ if (_NSIG_WORDS > 1) {
++ err |= __copy_to_user(frame->extramask, &set->sig[1],
++ sizeof(frame->extramask));
++ }
++
++ if (err == 0)
++ err = setup_return(regs, ka, &frame->retcode, frame, usig);
++
++ return err;
++}
++
++static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t * info,
++ sigset_t * set, struct pt_regs *regs)
++{
++ struct rt_sigframe __user *frame =
++ get_sigframe(ka, regs, sizeof(*frame));
++ stack_t stack;
++ int err = 0;
++
++ if (!frame)
++ return 1;
++
++ __put_user_error(&frame->info, &frame->pinfo, err);
++ __put_user_error(&frame->uc, &frame->puc, err);
++ err |= copy_siginfo_to_user(&frame->info, info);
++
++ __put_user_error(0, &frame->uc.uc_flags, err);
++ __put_user_error(NULL, &frame->uc.uc_link, err);
++
++ memset(&stack, 0, sizeof(stack));
++ stack.ss_sp = (void __user *)current->sas_ss_sp;
++ stack.ss_flags = sas_ss_flags(regs->NDS32_sp); //NDS32_sp
++ stack.ss_size = current->sas_ss_size;
++ err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack));
++
++ err |= setup_sigcontext(&frame->uc.uc_mcontext, &frame->aux,
++ regs, set->sig[0]);
++ err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
++
++ if (err == 0)
++ err = setup_return(regs, ka, &frame->retcode, frame, usig);
++
++ if (err == 0) {
++ /*
++ * For realtime signals we must also set the second and third
++ * arguments for the signal handler.
++ * -- Peter Maydell <pmaydell@chiark.greenend.org.uk> 2000-12-06
++ */
++ regs->NDS32_r1 = (unsigned long)&frame->info;
++ regs->NDS32_r2 = (unsigned long)&frame->uc;
++ }
++
++ return err;
++}
++
++static inline void setup_restart_syscall(struct pt_regs *regs)
++{
++ regs->NDS32_r0 = regs->NDS32_ORIG_r0;
++ regs->NDS32_ipc -= 4;
++}
++
++/*
++ * OK, we're invoking a handler
++ */
++static void handle_signal(unsigned long sig, struct k_sigaction *ka,
++ siginfo_t * info, sigset_t * oldset,
++ struct pt_regs *regs, int syscall)
++{
++ struct thread_info *thread = current_thread_info();
++ struct task_struct *tsk = current;
++ int usig = sig;
++ int ret;
++
++ /*
++ * If we were from a system call, check for system call restarting...
++ */
++ if (syscall) {
++ switch (regs->NDS32_r0) {
++ case -ERESTART_RESTARTBLOCK:
++ case -ERESTARTNOHAND:
++ regs->NDS32_r0 = -EINTR;
++ break;
++ case -ERESTARTSYS:
++ if (!(ka->sa.sa_flags & SA_RESTART)) {
++ regs->NDS32_r0 = -EINTR;
++ break;
++ }
++ /* fallthrough */
++ case -ERESTARTNOINTR:
++ setup_restart_syscall(regs);
++ }
++ }
++
++ /*
++ * translate the signal
++ */
++ if (usig < 32 && thread->exec_domain
++ && thread->exec_domain->signal_invmap)
++ usig = thread->exec_domain->signal_invmap[usig];
++
++ /*
++ * Set up the stack frame
++ */
++ if (ka->sa.sa_flags & SA_SIGINFO)
++ ret = setup_rt_frame(usig, ka, info, oldset, regs);
++ else
++ ret = setup_frame(usig, ka, oldset, regs);
++
++ /*
++ * Check that the resulting registers are actually sane.
++ */
++ ret |= !valid_user_regs(regs);
++
++ /*
++ * Block the signal if we were unsuccessful.
++ */
++ if (ret == 0) {
++ spin_lock_irq(&tsk->sighand->siglock);
++ sigorsets(&tsk->blocked, &tsk->blocked, &ka->sa.sa_mask);
++ if (!(ka->sa.sa_flags & SA_NODEFER))
++ sigaddset(&tsk->blocked, sig);
++ recalc_sigpending();
++ spin_unlock_irq(&tsk->sighand->siglock);
++#if 0 & defined(CONFIG_HSS)
++ /* COLE: i marked this tempory.
++ It doesn't behave the same as x86 */
++ /* Clear HSS when entering the signal handler,
++ User should be step into signal handler */
++ if (regs->NDS32_ipsw & PSW_mskHSS) {
++ regs->NDS32_ipsw &= ~PSW_mskHSS;
++ printk(KERN_INFO "clear for sig %d. pc=0x%08x\n", sig,
++ regs->NDS32_ipc);
++ }
++#endif
++ return;
++ }
++
++ force_sigsegv(sig, tsk);
++}
++
++/*
++ * Note that 'init' is a special process: it doesn't get signals it doesn't
++ * want to handle. Thus you cannot kill init even with a SIGKILL even by
++ * mistake.
++ *
++ * Note that we go through the signals twice: once to check the signals that
++ * the kernel can handle, and then we build all the user-level signal handling
++ * stack-frames in one go after that.
++ */
++asmlinkage int do_signal(sigset_t * oldset, struct pt_regs *regs, int syscall)
++{
++ struct k_sigaction ka;
++ siginfo_t info;
++ int signr;
++
++ /*
++ * We want the common case to go fast, which
++ * is why we may in certain cases get here from
++ * kernel mode. Just return without doing anything
++ * if so.
++ */
++
++ if (!user_mode(regs))
++ return 0;
++
++ if (try_to_freeze())
++ goto no_signal;
++
++ if (test_thread_flag(TIF_RESTORE_SIGMASK))
++ oldset = &current->saved_sigmask;
++
++ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
++
++ if (signr > 0) {
++ handle_signal(signr, &ka, &info, oldset, regs, syscall);
++ /*
++ * A signal was successfully delivered; the saved
++ * sigmask will have been stored in the signal frame,
++ * and will be restored by sigreturn, so we can simply
++ * clear the TIF_RESTORE_SIGMASK flag.
++ */
++ if (test_thread_flag(TIF_RESTORE_SIGMASK))
++ clear_thread_flag(TIF_RESTORE_SIGMASK);
++ return 1;
++ }
++
++no_signal:
++ /*
++ * No signal to deliver to the process - restart the syscall.
++ */
++ if (syscall) {
++ switch (regs->NDS32_r0) {
++ u32 __user *usp;
++
++ case -ERESTART_RESTARTBLOCK:
++ regs->NDS32_sp -= 4;
++ usp = (u32 __user *) regs->NDS32_sp;
++
++ if (put_user(regs->NDS32_ipc, usp) == 0)
++ regs->NDS32_ipc = KERN_RESTART_CODE;
++ else {
++ regs->NDS32_sp += 4;
++ force_sigsegv(0, current);
++ }
++ regs->NDS32_r0 = regs->NDS32_ORIG_r0;
++ break;
++
++ case -ERESTARTNOHAND:
++ case -ERESTARTSYS:
++ case -ERESTARTNOINTR:
++
++ setup_restart_syscall(regs);
++ break;
++ }
++ if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
++ clear_thread_flag(TIF_RESTORE_SIGMASK);
++ sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
++ }
++ }
++
++ return 0;
++}
++
++asmlinkage void do_notify_resume(struct pt_regs *regs,
++ unsigned int thread_flags, int syscall)
++{
++ if (thread_flags & _TIF_SIGPENDING)
++ do_signal(&current->blocked, regs, syscall);
++ if (thread_flags & _TIF_NOTIFY_RESUME) {
++ clear_thread_flag(TIF_NOTIFY_RESUME);
++ tracehook_notify_resume(regs);
++ if (current->replacement_session_keyring)
++ key_replace_session_keyring();
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/signal.h linux-3.4.110/arch/nds32/kernel/signal.h
+--- linux-3.4.110.orig/arch/nds32/kernel/signal.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/signal.h 2016-04-07 10:20:50.946081179 +0200
+@@ -0,0 +1,20 @@
++/*
++ * linux/arch/arm/kernel/signal.h
++ *
++ * Copyright (C) 2005-2009 Russell King.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <asm/fixmap.h>
++
++#define RETURN_SYSCALL_BASE (0x2000)
++#define RETURN_SYSCALL_PA_BASE (PHYS_OFFSET | RETURN_SYSCALL_BASE)
++
++#define KERN_SIGRETURN_CODE (fix_to_virt(FIX_RETURN_SYSCALL))
++#define KERN_RESTART_CODE (KERN_SIGRETURN_CODE + sizeof(retcodes))
++
++extern const unsigned long retcodes[2];
++extern const unsigned long syscall_restart_code[3];
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/smp.c linux-3.4.110/arch/nds32/kernel/smp.c
+--- linux-3.4.110.orig/arch/nds32/kernel/smp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/smp.c 2016-04-07 10:20:50.946081179 +0200
+@@ -0,0 +1,335 @@
++/*
++ * linux/arch/nds32/kernel/smp.c
++ *
++ * Copyright (C) 2002 ARM Limited, All Rights Reserved.
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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/delay.h>
++#include <linux/init.h>
++#include <linux/spinlock.h>
++#include <linux/sched.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/cache.h>
++#include <linux/profile.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/cpu.h>
++#include <linux/smp.h>
++#include <linux/seq_file.h>
++#include <asm/atomic.h>
++#include <asm/cacheflush.h>
++#include <asm/cpu.h>
++#include <asm/processor.h>
++#include <asm/tlbflush.h>
++#include <asm/ptrace.h>
++#include <linux/err.h>
++#include <asm/irq_regs.h>
++#include <asm/mmu_context.h>
++#include <asm/mmu.h>
++
++void smp_init_cpus(void)
++{
++ int i;
++ for (i = 0; i < NR_CPUS; i++)
++ cpu_set(i, cpu_possible_map);
++}
++
++int setup_profiling_timer(unsigned int multiplier)
++{
++ return 0;
++}
++
++struct tlb_data {
++ struct vm_area_struct *vma;
++ unsigned long start;
++ unsigned long end;
++};
++
++static void ipi_flush_tlb_all(void *data)
++{
++ local_flush_tlb_all();
++}
++
++void flush_tlb_all(void)
++{
++ on_each_cpu(ipi_flush_tlb_all, NULL, 1);
++}
++
++static void ipi_flush_tlb_mm(void *data)
++{
++ struct mm_struct *mm = (struct mm_struct *)data;
++ local_flush_tlb_mm(mm);
++}
++
++void flush_tlb_mm(struct mm_struct *mm)
++{
++ on_each_cpu(ipi_flush_tlb_mm, mm, 1);
++}
++
++static void ipi_flush_tlb_page(void *data)
++{
++ struct tlb_data *t = (struct tlb_data *)data;
++ local_flush_tlb_page(t->vma, t->start);
++}
++
++void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
++{
++ struct tlb_data data;
++
++ data.vma = vma;
++ data.start = addr;
++ on_each_cpu(ipi_flush_tlb_page, &data, 1);
++}
++
++static void ipi_flush_tlb_range(void *data)
++{
++ struct tlb_data *t = (struct tlb_data *)data;
++ local_flush_tlb_range(t->vma, t->start, t->end);
++}
++
++void flush_tlb_range(struct vm_area_struct *vma,
++ unsigned long start, unsigned long end)
++{
++ struct tlb_data data;
++
++ data.vma = vma;
++ data.start = start;
++ data.end = end;
++ on_each_cpu(ipi_flush_tlb_range, &data, 1);
++}
++
++static void ipi_flush_tlb_kernel_range(void *data)
++{
++ struct tlb_data *t = (struct tlb_data *)data;
++ local_flush_tlb_kernel_range(t->start, t->end);
++}
++
++void flush_tlb_kernel_range(unsigned long start, unsigned long end)
++{
++ struct tlb_data data;
++
++ data.start = start;
++ data.end = end;
++ on_each_cpu(ipi_flush_tlb_kernel_range, &data, 1);
++}
++
++/* IPI implementation */
++static inline unsigned long read_ipi_trigger(void)
++{
++ /* AMIC IPI trigger register */
++ return *(volatile unsigned long *)(AMIC_VA_BASE + 0x40);
++}
++
++static inline void write_ipi_trigger(const struct cpumask *mask)
++{
++ unsigned long data = *cpus_addr(*mask);
++ *(volatile unsigned long *)(AMIC_VA_BASE + 0x40) = data;
++}
++
++static inline void clear_ipi_status(void)
++{
++ *(volatile unsigned long *)(AMIC_VA_BASE + 0x44) = 0xf;
++ asm("msync store\nisb");
++}
++
++static void __init send_IPI_boot(int cpu, struct task_struct *tsk)
++{
++ extern void secondary_startup(void);
++ unsigned long *ptr = (unsigned long *)(0xc0006000 + (cpu << 9));
++ ptr[5] = virt_to_phys(secondary_startup);
++ ptr[6] = (unsigned long)task_stack_page(tsk) + THREAD_SIZE - 8;
++ asm("cctl %0, L1D_VA_WB, alevel\n"::"r"(ptr));
++ asm("cctl %0, L1D_VA_INVAL, alevel\nmsync\ndsb\n"::"r"(ptr));
++ write_ipi_trigger(get_cpu_mask(cpu));
++}
++
++static int __init wait_cpu_boot_done(int cpu)
++{
++ int i, state;
++ for (i = 0; i < 10000; i++) {
++ state = read_ipi_trigger();
++ if ((state & (1 << cpu)) == 0)
++ break;
++ udelay(100);
++ }
++ return (i == 10000) ? -1 : 0;
++}
++
++void __init secondary_start_kernel(void)
++{
++ unsigned long tmp;
++ unsigned int cpu = smp_processor_id();
++
++ atomic_inc(&init_mm.mm_count);
++ current->active_mm = &init_mm;
++
++ /*
++ * enable cache.
++ */
++
++#ifdef CONFIG_ANDES_PAGE_SIZE_4KB
++ if (CPU_IS_N1213_43U1HA0()) {
++ /* Downsize cache to bypass cache aliasing issue */
++
++ if ((CACHE_SET(ICACHE) * CACHE_LINE_SIZE(ICACHE)) > 4096)
++ tmp = 0x02 << SDZ_CTL_offICDZ;
++
++ if ((CACHE_SET(DCACHE) * CACHE_LINE_SIZE(DCACHE)) > 4096)
++ tmp |= 0x02 << SDZ_CTL_offDCDZ;
++
++ SET_SDZ_CTL(tmp);
++ ISB();
++// printk("CPU%d enabled cache downsizing.\n", cpu);
++ }
++#endif /* CONFIG_ANDES_PAGE_SIZE_4KB */
++
++ tmp = GET_CACHE_CTL();
++#ifndef CONFIG_CPU_DCACHE_DISABLE
++ tmp |= CACHE_CTL_mskDC_EN;
++#endif
++
++#ifndef CONFIG_CPU_ICACHE_DISABLE
++ tmp |= CACHE_CTL_mskIC_EN;
++#endif
++ SET_CACHE_CTL(tmp);
++ DSB();
++ ISB();
++
++ preempt_disable();
++ local_irq_enable();
++
++ //assume all of cores runs the same speed
++ //calibrate_delay();
++ /* store cpu info ot the second cpu */
++ smp_store_cpu_info(cpu);
++
++ clear_ipi_status();
++ cpu_idle();
++}
++
++/*
++ * Called by both boot and secondaries to move global data into
++ * per-processor storage.
++ */
++void __init smp_store_cpu_info(unsigned int cpuid)
++{
++ struct cpuinfo_nds32 *cpu_info = &per_cpu(cpu_data, cpuid);
++
++ cpu_info->loops_per_jiffy = loops_per_jiffy;
++}
++
++/* functions be used by generic layer */
++void arch_send_call_function_single_ipi(int cpu)
++{
++ write_ipi_trigger(get_cpu_mask(cpu));
++}
++
++void arch_send_call_function_ipi_mask(const struct cpumask *mask)
++{
++ write_ipi_trigger(mask);
++}
++
++static void __init smp_boot_one_cpu(int cpu)
++{
++ struct task_struct *idle;
++ int ret;
++
++ idle = fork_idle(cpu);
++ if (IS_ERR(idle))
++ panic(KERN_ERR "Fork failed for CPU %d", cpu);
++
++ send_IPI_boot(cpu, idle);
++ ret = wait_cpu_boot_done(cpu);
++ if (ret == 0)
++ cpu_set(cpu, cpu_online_map);
++ else
++ put_task_struct(idle);
++}
++
++static void ipi_timer(void *data)
++{
++ profile_tick(CPU_PROFILING);
++ update_process_times(user_mode(get_irq_regs()));
++}
++
++void smp_send_timer(void)
++{
++ smp_call_function(ipi_timer, NULL, 0);
++}
++
++static void ipi_stop(void *data)
++{
++ cpu_clear(smp_processor_id(), cpu_online_map);
++ local_irq_enable();
++ for (;;) ;
++}
++
++void smp_send_stop(void)
++{
++ smp_call_function(ipi_stop, NULL, 0);
++}
++
++void smp_send_reschedule(int cpu)
++{
++ write_ipi_trigger(get_cpu_mask(cpu));
++}
++
++static void ipi_handler(unsigned int irq, struct irq_desc *desc)
++{
++ clear_ipi_status();
++ generic_smp_call_function_single_interrupt();
++ generic_smp_call_function_interrupt();
++}
++
++void __init smp_prepare_cpus(unsigned int max_cpus)
++{
++ /*
++ * XXX detect how many cores exist
++ */
++ int i;
++ unsigned int cpu = smp_processor_id();
++
++ /* store master core cpu info */
++ smp_store_cpu_info(cpu);
++ for (i = 0; i < max_cpus; i++)
++ cpu_set(i, cpu_present_map);
++
++ /* setup IPI handler */
++ set_irq_chip(32, &dummy_irq_chip);
++ set_irq_chained_handler(32, ipi_handler);
++}
++
++int __cpuinit __cpu_up(unsigned int cpu)
++{
++ smp_boot_one_cpu(cpu);
++ return cpu_online(cpu) ? 0 : -ENOSYS;
++}
++
++void __init smp_cpus_done(unsigned int max_cpus)
++{
++ int cpu;
++ unsigned long bogosum = 0;
++
++ for_each_online_cpu(cpu)
++ bogosum += per_cpu(cpu_data, cpu).loops_per_jiffy;
++
++ printk(KERN_INFO "SMP: Total of %d processors activated "
++ "(%lu.%02lu BogoMIPS).\n",
++ num_online_cpus(),
++ bogosum / (500000 / HZ), (bogosum / (5000 / HZ)) % 100);
++
++ /* now we can set all interruption don't cared */
++ *(volatile unsigned long *)(AMIC_VA_BASE + 0x4) = 0xffffffff;
++}
++
++void __init smp_prepare_boot_cpu(void)
++{
++ unsigned int cpu = smp_processor_id();
++ unsigned long *ptr = (unsigned long *)(0xc0006000 + (cpu << 9));
++ ptr[4] = 1;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/stacktrace.c linux-3.4.110/arch/nds32/kernel/stacktrace.c
+--- linux-3.4.110.orig/arch/nds32/kernel/stacktrace.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/stacktrace.c 2016-04-07 10:20:50.946081179 +0200
+@@ -0,0 +1,41 @@
++#include <linux/sched.h>
++#include <linux/stacktrace.h>
++void save_stack_trace(struct stack_trace *trace)
++{
++ save_stack_trace_tsk(current, trace);
++}
++
++void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
++{
++ unsigned long *fpn;
++ int skip = trace->skip;
++ int savesched;
++
++ if (tsk == current) {
++ __asm__ __volatile__("\tori\t%0, $fp, #0\n":"=r"(fpn));
++ savesched = 1;
++ } else {
++ fpn = (unsigned long *)thread_saved_fp(tsk);
++ savesched = 0;
++ }
++
++ while (!kstack_end(fpn) && !((unsigned long)fpn & 0x3)
++ && (fpn >= (unsigned long *)TASK_SIZE)) {
++ unsigned long lpp, fpp;
++ lpp = fpn[0];
++ fpp = fpn[-1];
++ if (!__kernel_text_address(lpp))
++ break;
++
++ if (savesched || !in_sched_functions(lpp)) {
++ if (skip) {
++ skip--;
++ } else {
++ trace->entries[trace->nr_entries++] = lpp;
++ if (trace->nr_entries >= trace->max_entries)
++ break;
++ }
++ }
++ fpn = (unsigned long *)fpp;
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/sys_nds32.c linux-3.4.110/arch/nds32/kernel/sys_nds32.c
+--- linux-3.4.110.orig/arch/nds32/kernel/sys_nds32.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/sys_nds32.c 2016-04-07 10:20:50.946081179 +0200
+@@ -0,0 +1,331 @@
++/*
++ * linux/arch/nds32/kernel/sys_nds32.c
++ *
++ * Copyright (C) People who wrote linux/arch/i386/kernel/sys_i386.c
++ * Copyright (C) 2007 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This file contains various random system calls that
++ * have a non-standard calling sequence on the Linux/nds32
++ * platform.
++ */
++#include <linux/module.h>
++#include <linux/errno.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <linux/mm.h>
++#include <linux/sem.h>
++#include <linux/msg.h>
++#include <linux/shm.h>
++#include <linux/stat.h>
++#include <linux/syscalls.h>
++#include <linux/mman.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/utsname.h>
++#include <linux/ipc.h>
++
++#include <asm/uaccess.h>
++#include <asm/unistd.h>
++#include <asm/pfm.h>
++
++extern unsigned long do_mremap(unsigned long addr, unsigned long old_len,
++ unsigned long new_len, unsigned long flags,
++ unsigned long new_addr);
++
++struct mmap_arg_struct {
++ unsigned long addr;
++ unsigned long len;
++ unsigned long prot;
++ unsigned long flags;
++ unsigned long fd;
++ unsigned long offset;
++};
++
++asmlinkage unsigned long sys_mmap2(unsigned long addr, unsigned long len,
++ unsigned long prot, unsigned long flags,
++ unsigned long fd, unsigned long pgoff)
++{
++ if (pgoff & (~PAGE_MASK >> 12))
++ return -EINVAL;
++
++ return sys_mmap_pgoff(addr, len, prot, flags, fd,
++ pgoff >> (PAGE_SHIFT - 12));
++}
++
++asmlinkage unsigned long
++sys_nds32_mremap(unsigned long addr, unsigned long old_len,
++ unsigned long new_len, unsigned long flags,
++ unsigned long new_addr)
++{
++ unsigned long ret = -EINVAL;
++
++ if (flags & MREMAP_FIXED && new_addr < FIRST_USER_ADDRESS)
++ goto out;
++
++ down_write(&current->mm->mmap_sem);
++ ret = do_mremap(addr, old_len, new_len, flags, new_addr);
++ up_write(&current->mm->mmap_sem);
++
++out:
++ return ret;
++}
++
++/*
++ * Perform the select(nd, in, out, ex, tv) and mmap() system
++ * calls.
++ */
++
++struct sel_arg_struct {
++ unsigned long n;
++ fd_set __user *inp, *outp, *exp;
++ struct timeval __user *tvp;
++};
++
++asmlinkage int old_select(struct sel_arg_struct __user * arg)
++{
++ struct sel_arg_struct a;
++
++ if (copy_from_user(&a, arg, sizeof(a)))
++ return -EFAULT;
++ /* sys_select() does the appropriate kernel locking */
++ return sys_select(a.n, a.inp, a.outp, a.exp, a.tvp);
++}
++
++/*
++ * sys_ipc() is the de-multiplexer for the SysV IPC calls..
++ *
++ * This is really horribly ugly.
++ */
++asmlinkage long sys_ipc(unsigned int call, int first, unsigned long second,
++ unsigned long third, void __user * ptr, long fifth)
++{
++ int version, ret;
++
++ version = call >> 16; /* hack for backward compatibility */
++ call &= 0xffff;
++
++ switch (call) {
++ case SEMOP:
++ return sys_semtimedop(first, (struct sembuf __user *)ptr,
++ second, NULL);
++ case SEMTIMEDOP:
++ return sys_semtimedop(first, (struct sembuf __user *)ptr,
++ second,
++ (const struct timespec __user *)fifth);
++
++ case SEMGET:
++ return sys_semget(first, second, third);
++ case SEMCTL:{
++ union semun fourth;
++ if (!ptr)
++ return -EINVAL;
++ if (get_user(fourth.__pad, (void __user * __user *)ptr))
++ return -EFAULT;
++ return sys_semctl(first, second, third, fourth);
++ }
++
++ case MSGSND:
++ return sys_msgsnd(first, (struct msgbuf __user *)ptr,
++ second, third);
++ case MSGRCV:
++ switch (version) {
++ case 0:{
++ struct ipc_kludge tmp;
++ if (!ptr)
++ return -EINVAL;
++ if (copy_from_user
++ (&tmp, (struct ipc_kludge __user *)ptr,
++ sizeof(tmp)))
++ return -EFAULT;
++ return sys_msgrcv(first, tmp.msgp, second,
++ tmp.msgtyp, third);
++ }
++ default:
++ return sys_msgrcv(first,
++ (struct msgbuf __user *)ptr,
++ second, fifth, third);
++ }
++ case MSGGET:
++ return sys_msgget((key_t) first, second);
++ case MSGCTL:
++ return sys_msgctl(first, second, (struct msqid_ds __user *)ptr);
++
++ case SHMAT:
++ switch (version) {
++ default:{
++ ulong raddr;
++ ret =
++ do_shmat(first, (char __user *)ptr, second,
++ &raddr);
++ if (ret)
++ return ret;
++ return put_user(raddr, (ulong __user *) third);
++ }
++ case 1: /* Of course, we don't support iBCS2! */
++ return -EINVAL;
++ }
++ case SHMDT:
++ return sys_shmdt((char __user *)ptr);
++ case SHMGET:
++ return sys_shmget(first, second, third);
++ case SHMCTL:
++ return sys_shmctl(first, second, (struct shmid_ds __user *)ptr);
++ default:
++ return -ENOSYS;
++ }
++}
++
++/* Fork a new task - this creates a new program thread.
++ * This is called indirectly via a small wrapper
++ */
++asmlinkage int sys_fork(struct pt_regs *regs)
++{
++ return do_fork(SIGCHLD, regs->NDS32_sp, regs, 0, NULL, NULL);
++}
++
++/* Clone a task - this clones the calling program thread.
++ * This is called indirectly via a small wrapper
++ */
++asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp,
++ int __user * parent_tidptr, int tls_val,
++ int __user * child_tidptr, struct pt_regs *regs)
++{
++ if (!newsp)
++ newsp = regs->NDS32_sp;
++
++ return do_fork(clone_flags, newsp, regs, 0, parent_tidptr,
++ child_tidptr);
++}
++
++asmlinkage int sys_vfork(struct pt_regs *regs)
++{
++ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->NDS32_sp, regs,
++ 0, NULL, NULL);
++}
++
++/* sys_execve() executes a new program.
++ * This is called indirectly via a small wrapper
++ */
++asmlinkage int sys_execve(const char __user * filenamei,
++ const char __user * const __user * argv,
++ const char __user * const __user * envp,
++ struct pt_regs *regs)
++{
++ int error;
++ char *filename;
++
++ filename = getname(filenamei);
++ error = PTR_ERR(filename);
++ if (IS_ERR(filename))
++ goto out;
++
++ error = do_execve(filename, argv, envp, regs);
++ putname(filename);
++
++out:
++ return error;
++}
++
++asmlinkage unsigned long sys_getpagesize(void)
++{
++ return PAGE_SIZE; /* Possibly older binaries want 8192 on sun4's? */
++}
++
++int kernel_execve(const char *filename, const char *const argv[],
++ const char *const envp[])
++{
++ struct pt_regs regs;
++ int ret;
++
++ memset(&regs, 0, sizeof(struct pt_regs));
++ ret = do_execve(filename, argv, envp, &regs);
++
++ if (ret < 0) {
++ goto out;
++ }
++ /*
++ * Save argc to the register structure for userspace.
++ */
++ regs.NDS32_r0 = ret;
++
++ /*
++ * We were successful. We won't be returning to our caller, but
++ * instead to user space by manipulating the kernel stack.
++ */
++ asm("addi $r0, %0, %1\n\t"
++ "move $r1, %2\n\t"
++ "move $r2, %3\n\t"
++ "bal memmove\n\t" /* copy regs to top of stack */
++ "move $r8, #0\n\t" /* not a syscall */
++ "move $r9, %0\n\t" /* thread structure */
++ "move $sp, $r0\n\t" /* reposition stack pointer */
++"b resume_userspace":
++: "r"(current_thread_info()),
++ "ir"(THREAD_SIZE - 8 - sizeof(regs)),
++ "r"(&regs), "ir"(sizeof(regs))
++#ifdef _GCC444
++: "$r0", "$r1", "$r2", "$r4", "$r5", "$r8", "$r9", "$p0", "$p1",
++ "memory");
++#else
++: "$r0", "$r1", "$r2", "$r4", "$r5", "$r8", "$r9", "$r26", "$r27",
++ "memory");
++#endif
++out:
++ return ret;
++}
++
++EXPORT_SYMBOL(kernel_execve);
++
++int sys_cacheflush(unsigned int start, unsigned int end)
++{
++ struct vm_area_struct *vma;
++
++ vma = find_vma(current->mm, start);
++ if (!vma)
++ return 0;
++ cpu_cache_wbinval_range_check(vma, start, end);
++ return 0;
++}
++
++asmlinkage long sys_fadvise64_64_wrapper(int fd, int advice, loff_t offset,
++ loff_t len)
++{
++ return sys_fadvise64_64(fd, offset, len, advice);
++}
++
++asmlinkage int nds32_syscall(int number, struct pt_regs *regs)
++{
++ switch (number) {
++ case 0x7000: /* cacheflush */
++ return sys_cacheflush(regs->NDS32_r1, regs->NDS32_r2);
++
++#ifdef CONFIG_OPROFILE
++ case __NR_pfmctl:
++ sys_pfmctl(regs->NDS32_r1, regs->NDS32_r2, regs->NDS32_r3,
++ regs->NDS32_r4);
++ return 0;
++
++ case __NR_getpfm:
++ return sys_getpfm((struct pcounter __user *)regs->NDS32_r1);
++
++ case __NR_setpfm:
++ return sys_setpfm(regs->NDS32_r1, regs->NDS32_r2,
++ regs->NDS32_r3,
++ (struct pcounter __user *)regs->NDS32_r4);
++#endif
++ case __NR_wbna:
++ if (regs->NDS32_r1)
++ regs->NDS32_ipsw |= PSW_mskWBNA;
++ else
++ regs->NDS32_ipsw &= ~PSW_mskWBNA;
++ return 0;
++
++ default:
++ return -ENOSYS;
++ }
++ return -ENOSYS;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/time.c linux-3.4.110/arch/nds32/kernel/time.c
+--- linux-3.4.110.orig/arch/nds32/kernel/time.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/time.c 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,94 @@
++/*
++ * linux/arch/nds32/kernel/time.c
++ *
++ * Copyright (C) 1991, 1992, 1995 Linus Torvalds
++ * Modifications for ARM (C) 1994-2001 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This file contains the ARM-specific time handling details:
++ * reading the RTC at bootup, etc...
++ *
++ * 1994-07-02 Alan Modra
++ * fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime
++ * 1998-12-20 Updated NTP code according to technical memorandum Jan '96
++ * "A Kernel Model for Precision Timekeeping" by Dave Mills
++ */
++#include <linux/sched.h>
++#include <linux/profile.h>
++#include <linux/timer.h>
++#include <asm/irq_regs.h>
++#include <linux/syscore_ops.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/time.h>
++
++/*
++ * Our system timer.
++ */
++struct sys_timer *system_timer;
++
++#ifdef CONFIG_SMP
++unsigned long profile_pc(struct pt_regs *regs)
++{
++ unsigned long fp, pc = instruction_pointer(regs);
++
++ if (in_lock_functions(pc)) {
++ fp = regs->NDS32_fp;
++ pc = ((unsigned long *)fp)[-1];
++ }
++
++ return pc;
++}
++
++EXPORT_SYMBOL(profile_pc);
++#endif
++#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
++static int timer_suspend(void)
++{
++ if (system_timer->suspend)
++ system_timer->suspend();
++
++ return 0;
++}
++
++static void timer_resume(void)
++{
++ if (system_timer->resume)
++ system_timer->resume();
++}
++#else
++#define timer_suspend NULL
++#define timer_resume NULL
++#endif
++#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
++u32 arch_gettimeoffset(void)
++{
++ if (system_timer->offset != NULL)
++ return system_timer->offset() * 1000;
++
++ return 0;
++}
++#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */
++static struct syscore_ops timer_syscore_ops = {
++ .suspend = timer_suspend,
++ .resume = timer_resume,
++};
++
++static int __init timer_init_syscore_ops(void)
++{
++ register_syscore_ops(&timer_syscore_ops);
++
++ return 0;
++}
++
++device_initcall(timer_init_syscore_ops);
++
++void __init time_init(void)
++{
++ system_timer = machine_desc->timer;
++ system_timer->init(); // link to cpe_timer_init
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/traps.c linux-3.4.110/arch/nds32/kernel/traps.c
+--- linux-3.4.110.orig/arch/nds32/kernel/traps.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/traps.c 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,733 @@
++/*
++ * linux/arch/nds32/kernel/traps.c
++ *
++ * Copyright (C) 1995-2002 Russell King
++ * Fragments that appear the same as linux/arch/i386/kernel/traps.c (C) Linus Torvalds
++ *
++ * 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.
++ *
++ * 'traps.c' handles hardware exceptions after we have saved some state in
++ * 'linux/arch/nds32/lib/traps.S'. Mostly a debugging aid, but will probably
++ * kill the offending process.
++ */
++/* ============================================================================
++ *
++ * linux/arch/nds32/kernel/traps.c
++ *
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is trap handling for NDS32 core, initial refer from ARM.
++ *
++ * Revision History:
++ *
++ * Jul.16.2007 Initial ported by Tom, revised for KGDB by Harry.
++ *
++ * Note:
++ *
++ * ============================================================================
++ */
++#include <linux/module.h>
++#include <linux/personality.h>
++#include <linux/kallsyms.h>
++#include <linux/hardirq.h>
++#include <linux/kdebug.h>
++
++#include <asm/cacheflush.h>
++#include <asm/uaccess.h>
++#include <asm/unistd.h>
++#include <asm/traps.h>
++#include <asm/fpu.h>
++#include <asm/audio.h>
++
++#include <linux/ptrace.h>
++#include <nds32_intrinsic.h>
++#include "ptrace.h"
++#include "signal.h"
++
++extern void show_pte(struct mm_struct *mm, unsigned long addr);
++
++#ifdef CONFIG_DEBUG_USER
++unsigned int user_debug;
++
++static int __init user_debug_setup(char *str)
++{
++ get_option(&str, &user_debug);
++ return 1;
++}
++
++__setup("user_debug=", user_debug_setup);
++#endif
++
++/*
++ * Dump out the contents of some memory nicely...
++ */
++void dump_mem(const char *str, unsigned long bottom, unsigned long top)
++{
++ unsigned long p = bottom & ~31;
++ mm_segment_t fs;
++ int i;
++
++ /*
++ * We need to switch to kernel mode so that we can use __get_user
++ * to safely read from kernel space. Note that we now dump the
++ * code first, just in case the backtrace kills us.
++ */
++ fs = get_fs();
++ set_fs(KERNEL_DS);
++
++ printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
++
++ for (p = bottom & ~31; p < top;) {
++ printk("%04lx: ", p & 0xffff);
++
++ for (i = 0; i < 8; i++, p += 4) {
++ unsigned int val;
++
++ if (p < bottom || p >= top)
++ printk(" ");
++ else {
++ __get_user(val, (unsigned long *)p);
++ printk("%08x ", val);
++ }
++ }
++ printk("\n");
++ }
++
++ set_fs(fs);
++}
++
++EXPORT_SYMBOL(dump_mem);
++
++/* These intrinsic functions are not supported in V2 toolchains of BSP321. */
++#ifndef __NDS32_BASELINE_V2__
++#define DEBUG_TLB_CACHE
++#endif
++#ifdef DEBUG_TLB_CACHE
++/* This is the number of TLB entries. User should change it if necessary. */
++#define TLB_NUM 128
++unsigned int tlb_misc_new[TLB_NUM], tlb_vpn_new[TLB_NUM], tlb_data_new[TLB_NUM];
++/* To get the whole TLB contents once it uses va=0x0 */
++void dump_tlb(unsigned long va)
++{
++ unsigned int rd_num, tlb_vpn, tlb_misc, tlb_data, mmu_cfg, tlb_num;
++
++ /* save tlb system registers */
++ tlb_vpn = __nds32__mfsr(NDS32_SR_TLB_VPN);
++ tlb_misc = __nds32__mfsr(NDS32_SR_TLB_MISC);
++ tlb_data = __nds32__mfsr(NDS32_SR_TLB_DATA);
++ mmu_cfg = __nds32__mfsr(NDS32_SR_MMU_CFG);
++ tlb_num =
++ (((mmu_cfg & MMU_CFG_mskTBW) >> MMU_CFG_offTBW) +
++ 1) * (1 << (((mmu_cfg & MMU_CFG_mskTBS) >> MMU_CFG_offTBS) + 2));
++
++ for (rd_num = 0; rd_num < tlb_num; rd_num++) {
++ /* read tlb entry with index */
++ __nds32__tlbop_trd(rd_num);
++ __nds32__dsb();
++ tlb_vpn_new[rd_num] = __nds32__mfsr(NDS32_SR_TLB_VPN);
++ tlb_misc_new[rd_num] = __nds32__mfsr(NDS32_SR_TLB_MISC);
++ tlb_data_new[rd_num] = __nds32__mfsr(NDS32_SR_TLB_DATA);
++ }
++
++ /* restore tlb system registers */
++ __nds32__mtsr(tlb_vpn, NDS32_SR_TLB_VPN);
++ __nds32__mtsr(tlb_misc, NDS32_SR_TLB_MISC);
++ __nds32__dsb();
++
++ printk("cur VPN:%08x, MISC:%08x, DATA:%08x\n", tlb_vpn, tlb_misc,
++ tlb_data);
++ /* to read out all the data */
++ for (rd_num = 0; rd_num < tlb_num; rd_num++) {
++ /*unsigned int vpn = tlb_vpn_new[rd_num] & PAGE_MASK; */
++ if (tlb_data_new[rd_num] & 0x1)
++ if (va == 0x0
++ || (va != 0x0
++ && (tlb_vpn_new[rd_num] == (va & PAGE_MASK))))
++ printk
++ ("idx:0x%08x, VPN:%08x, MISC:%08x, DATA:%08x\n",
++ rd_num, tlb_vpn_new[rd_num],
++ tlb_misc_new[rd_num],
++ tlb_data_new[rd_num]);
++ }
++}
++
++EXPORT_SYMBOL(dump_tlb);
++
++struct cache_element {
++ unsigned int pa;
++ unsigned int wd;
++ unsigned int cacheline[8];
++ unsigned char dirty;
++ unsigned char valid;
++ unsigned char lock;
++};
++
++/* This is the number of cache entries. User should change it if necessary. */
++#define CACHE_SET_NUM 0x100
++#define CACHE_WAY_NUM 0x4
++volatile struct cache_element ce[CACHE_SET_NUM][CACHE_WAY_NUM];
++#define CCTL_mskDIRTY 0x400000
++#define CCTL_offDIRTY 22
++#define CCTL_mskVALID 0x2
++#define CCTL_offVALID 1
++#define CCTL_mskLOCK 0x1
++#define CCTL_offLOCK 0
++#define CCTL_mskTAG 0x3ffffc
++#define CCTL_offTAG 0x2
++extern unsigned long va2idx(unsigned long va, unsigned int cache_type,
++ unsigned long *way_offset);
++#include <asm/cache_info.h>
++extern struct cache_info L1_cache_info[2];
++void dump_cache(unsigned int cache_type)
++{
++ volatile unsigned long idx, way, ra, tag, i;
++ unsigned long sets, ways, line_size, set_bits, way_bits, line_bits,
++ way_offset;
++
++ ways = L1_cache_info[DCACHE].ways;
++ sets = L1_cache_info[DCACHE].sets;
++ set_bits = L1_cache_info[cache_type].set_bits;
++ way_bits = L1_cache_info[cache_type].way_bits;
++ line_bits = L1_cache_info[cache_type].line_bits;
++ line_size = L1_cache_info[cache_type].line_size;
++ way_offset = set_bits + line_bits;
++
++ if (cache_type != ICACHE && cache_type != DCACHE) {
++ printk("%s not supported cache_type:%x\n", __func__,
++ cache_type);
++ return;
++ }
++
++ /* NDS32_CCTL_L1I_IX_RTAG Read tag L1I cache */
++ /* NDS32_CCTL_L1I_IX_RWD Read word data L1I cache */
++
++ for (idx = 0; idx < sets; idx++) {
++ for (way = 0; way < ways; way++) {
++ ra = (way << way_offset) | (idx << line_bits);
++ if (cache_type == ICACHE)
++ tag =
++ __nds32__cctlidx_read
++ (NDS32_CCTL_L1I_IX_RTAG, ra);
++ else
++ tag =
++ __nds32__cctlidx_read
++ (NDS32_CCTL_L1D_IX_RTAG, ra);
++ ce[idx][way].dirty =
++ (unsigned char)(tag & CCTL_mskDIRTY) >>
++ CCTL_offDIRTY;
++ ce[idx][way].valid =
++ (unsigned char)(tag & CCTL_mskVALID) >>
++ CCTL_offVALID;
++ ce[idx][way].lock =
++ (unsigned char)(tag & CCTL_mskLOCK) >> CCTL_offLOCK;
++ ce[idx][way].pa =
++ (tag & CCTL_mskTAG) >> CCTL_offTAG << PAGE_SHIFT;
++ for (i = 0; i < line_size / 4; i++) {
++ if (cache_type == ICACHE)
++ ce[idx][way].cacheline[i] =
++ __nds32__cctlidx_read
++ (NDS32_CCTL_L1I_IX_RWD,
++ (ra | i << 2));
++ else
++ ce[idx][way].cacheline[i] =
++ __nds32__cctlidx_read
++ (NDS32_CCTL_L1D_IX_RWD,
++ (ra | i << 2));
++ }
++ }
++ }
++ printk("dump %s\n", cache_type ? "DCACHE" : "ICACHE");
++ printk("%8s %4s %4s %1s %1s %1s %8s %8s %8s %8s %8s %8s %8s %8s\n",
++ "ADDRESS", "SET", "WAY", "V", "D", "L", "00", "04", "08", "0C",
++ "10", "14", "18", "1C");
++ for (idx = 0; idx < sets; idx++) {
++ for (way = 0; way < ways; way++) {
++ printk("%08lx %04lx %04lx %1u %1u %1u ",
++ ce[idx][way].pa +
++ ((idx * line_size) % PAGE_SIZE), idx, way,
++ ce[idx][way].valid, ce[idx][way].dirty,
++ ce[idx][way].lock);
++ for (i = 0; i < line_size / 4; i++) {
++ printk("%08x ", ce[idx][way].cacheline[i]);
++ }
++ printk("\n");
++ }
++ }
++}
++
++EXPORT_SYMBOL(dump_cache);
++
++void dump_cache_va(unsigned int cache_type, unsigned int va)
++{
++ volatile struct cache_element cache_entry[4];
++ volatile unsigned long idx, way, tag, ra, i;
++ unsigned long ways, line_size, set_bits, line_bits, way_offset;
++
++ ways = L1_cache_info[cache_type].ways;
++ line_size = CACHE_LINE_SIZE(cache_type);
++ set_bits = L1_cache_info[cache_type].set_bits;
++ line_bits = L1_cache_info[cache_type].line_bits;
++
++ if (cache_type != ICACHE && cache_type != DCACHE) {
++ printk("%s not supported cache_type:%x\n", __func__,
++ cache_type);
++ return;
++ }
++ idx = va2idx(va, cache_type, &way_offset);
++ //idx = (va & (((1 << set_bits) - 1) << line_bits)) >> line_bits;
++ for (way = 0; way < ways; way++) {
++ ra = (way << way_offset) | idx;
++ if (cache_type == ICACHE)
++ tag = __nds32__cctlidx_read(NDS32_CCTL_L1I_IX_RTAG, ra);
++ else
++ tag = __nds32__cctlidx_read(NDS32_CCTL_L1D_IX_RTAG, ra);
++ cache_entry[way].dirty =
++ (unsigned char)(tag & CCTL_mskDIRTY) >> CCTL_offDIRTY;
++ cache_entry[way].valid =
++ (unsigned char)(tag & CCTL_mskVALID) >> CCTL_offVALID;
++ cache_entry[way].lock =
++ (unsigned char)(tag & CCTL_mskLOCK) >> CCTL_offLOCK;
++ cache_entry[way].pa =
++ (tag & CCTL_mskTAG) >> CCTL_offTAG << PAGE_SHIFT;
++ for (i = 0; i < line_size / 4; i++) {
++ if (cache_type == ICACHE)
++ cache_entry[way].cacheline[i] =
++ __nds32__cctlidx_read(NDS32_CCTL_L1I_IX_RWD,
++ (ra | i << 2));
++ else
++ cache_entry[way].cacheline[i] =
++ __nds32__cctlidx_read(NDS32_CCTL_L1D_IX_RWD,
++ (ra | i << 2));
++ }
++ }
++ printk("dump %s va:%x\n", cache_type ? "DCACHE" : "ICACHE", va);
++
++ printk("%8s %4s %4s %1s %1s %1s %8s %8s %8s %8s %8s %8s %8s %8s\n",
++ "ADDRESS", "SET", "WAY", "V", "D", "L", "00", "04", "08", "0C",
++ "10", "14", "18", "1C");
++ for (way = 0; way < ways; way++) {
++ printk("%08lx %04lx %04lx %1u %1u %1u ",
++ cache_entry[way].pa +
++ (((idx >> line_bits) * line_size) % PAGE_SIZE),
++ (idx >> line_bits), way, cache_entry[way].valid,
++ cache_entry[way].dirty, cache_entry[way].lock);
++ for (i = 0; i < 8; i++) {
++ printk("%08x ", cache_entry[way].cacheline[i]);
++ }
++ printk("\n");
++ }
++}
++
++EXPORT_SYMBOL(dump_cache_va);
++#endif
++
++static void dump_instr(struct pt_regs *regs)
++{
++ unsigned long addr = instruction_pointer(regs);
++ const int width = 8;
++ mm_segment_t fs;
++ int i;
++
++ return;
++ /*
++ * We need to switch to kernel mode so that we can use __get_user
++ * to safely read from kernel space. Note that we now dump the
++ * code first, just in case the backtrace kills us.
++ */
++ fs = get_fs();
++ set_fs(KERNEL_DS);
++
++ printk("Code: ");
++ for (i = -4; i < 1; i++) {
++ unsigned int val, bad;
++
++ bad = __get_user(val, &((u32 *) addr)[i]);
++
++ if (!bad)
++ printk(i == 0 ? "(%0*x) " : "%0*x ", width, val);
++ else {
++ printk("bad PC value.");
++ break;
++ }
++ }
++ printk("\n");
++
++ set_fs(fs);
++}
++
++#define LOOP_TIMES (100)
++void dump_stack(void)
++{
++ int cnt = LOOP_TIMES;
++#ifndef CONFIG_FRAME_POINTER
++ unsigned long *stack;
++ unsigned long addr;
++
++ __asm__ __volatile__("\tori\t%0, $sp, #0\n":"=r"(stack));
++ printk("Call Trace:\n");
++ while (!kstack_end(stack)) {
++ addr = *stack++;
++ if (__kernel_text_address(addr)) {
++ printk("[<%08lx>] ", addr);
++ print_symbol("%s\n", addr);
++ }
++ cnt--;
++ if (cnt < 0)
++ break;
++ }
++ printk("\n");
++#else
++ unsigned long *fpn;
++ __asm__ __volatile__("\tori\t%0, $fp, #0\n":"=r"(fpn));
++ printk("Call Trace:\n");
++ while (!kstack_end((void *)fpn) && !((unsigned long)fpn & 0x3)
++ && ((unsigned long)fpn >= TASK_SIZE)) {
++ unsigned long lpp, fpp;
++#if !defined(NDS32_ABI_2)
++ lpp = fpn[0];
++ fpp = fpn[1];
++#else
++ lpp = fpn[0];
++ fpp = fpn[-1];
++#endif
++ if (__kernel_text_address(lpp)) {
++ printk("[<%08lx>] ", lpp);
++ print_symbol("%s\n", lpp);
++ fpn = (unsigned long *)fpp;
++ }
++ cnt--;
++ if (cnt < 0)
++ break;
++ }
++ printk("\n");
++#endif
++}
++
++EXPORT_SYMBOL(dump_stack);
++
++void show_stack(struct task_struct *tsk, unsigned long *sp)
++{
++ unsigned long fp;
++
++ if (!tsk)
++ tsk = current;
++
++ if (tsk != current)
++ fp = thread_saved_fp(tsk);
++ else
++ asm("move %0, $fp":"=r"(fp));
++
++ dump_stack();
++ barrier();
++}
++
++DEFINE_SPINLOCK(die_lock);
++
++/*
++ * This function is protected against re-entrancy.
++ */
++void die(const char *str, struct pt_regs *regs, int err)
++{
++ struct task_struct *tsk = current;
++ static int die_counter;
++
++ console_verbose();
++ spin_lock_irq(&die_lock);
++ bust_spinlocks(1);
++
++ printk("Internal error: %s: %x [#%d]\n", str, err, ++die_counter);
++ print_modules();
++ printk("CPU: %i\n", smp_processor_id());
++ show_regs(regs);
++ printk("Process %s (pid: %d, stack limit = 0x%p)\n",
++ tsk->comm, tsk->pid, task_thread_info(tsk) + 1);
++
++ if (!user_mode(regs) || in_interrupt()) {
++ dump_mem("Stack: ", regs->NDS32_sp,
++ 8192 + (unsigned long)task_thread_info(tsk));
++ dump_instr(regs);
++ dump_stack();
++ }
++
++ bust_spinlocks(0);
++ spin_unlock_irq(&die_lock);
++ do_exit(SIGSEGV);
++}
++
++void die_if_kernel(const char *str, struct pt_regs *regs, int err)
++{
++ if (user_mode(regs))
++ return;
++
++ die(str, regs, err);
++}
++
++int bad_syscall(int n, struct pt_regs *regs)
++{
++ struct thread_info *thread = current_thread_info();
++ siginfo_t info;
++
++ if (current->personality != PER_LINUX && thread->exec_domain->handler) {
++ thread->exec_domain->handler(n, regs);
++ return regs->NDS32_r0;
++ }
++#ifdef CONFIG_DEBUG_USER
++ if (user_debug & UDBG_SYSCALL) {
++ printk(KERN_ERR "[%d] %s: obsolete system call %08x.\n",
++ current->pid, current->comm, n);
++ dump_instr(regs);
++ }
++#endif
++
++ info.si_signo = SIGILL;
++ info.si_errno = 0;
++ info.si_code = ILL_ILLTRP;
++ info.si_addr = (void __user *)instruction_pointer(regs) - 4;
++
++ force_sig_info(SIGILL, &info, current);
++ die_if_kernel("Oops - bad syscall", regs, n);
++ return regs->NDS32_r0;
++}
++
++void __pte_error(const char *file, int line, unsigned long val)
++{
++ printk("%s:%d: bad pte %08lx.\n", file, line, val);
++}
++
++void __pmd_error(const char *file, int line, unsigned long val)
++{
++ printk("%s:%d: bad pmd %08lx.\n", file, line, val);
++}
++
++void __pgd_error(const char *file, int line, unsigned long val)
++{
++ printk("%s:%d: bad pgd %08lx.\n", file, line, val);
++}
++
++extern char exception_vector[73][64];
++void __init trap_init(void)
++{
++ return;
++}
++
++void __init early_trap_init(void)
++{
++ unsigned long ivb = 0;
++ unsigned long base = 0xc0000000;
++
++ memcpy((unsigned long *)base, (unsigned long *)exception_vector,
++ sizeof(exception_vector));
++ ivb = __nds32__mfsr(NDS32_SR_IVB);
++#ifdef CONFIG_EVIC
++ __nds32__mtsr((ivb & ~IVB_mskESZ) | (2 << IVB_offESZ) |
++ (1 << IVB_offEVIC) | IVB_BASE, NDS32_SR_IVB);
++#else
++ /* Check platform support. */
++# if defined (CONFIG_IVIC_INTC)
++ if (((ivb & IVB_mskNIVIC) >> IVB_offNIVIC) >= 2)
++ panic
++ ("IVIC mode is not allowed on the platform with interrupt controller\n");
++# elif defined(CONFIG_IVIC)
++ if (((ivb & IVB_mskNIVIC) >> IVB_offNIVIC) < 2)
++ panic
++ ("IVIC mode is not allowed on the platform without interrupt controller\n");
++# endif
++ __nds32__mtsr((ivb & ~IVB_mskESZ) | (2 << IVB_offESZ) | IVB_BASE,
++ NDS32_SR_IVB);
++#endif
++ __nds32__mtsr(0x10003, NDS32_SR_INT_MASK);
++ /*
++ * Copy signal return handlers into the vector page, and
++ * set sigreturn to be a pointer to these.
++ */
++ memcpy((void *)KERN_SIGRETURN_CODE, retcodes, sizeof(retcodes));
++ memcpy((void *)KERN_RESTART_CODE, syscall_restart_code,
++ sizeof(syscall_restart_code));
++
++ /*
++ * 0x2000 is 8K-aligned of 0x1240 = 73 vectors * 64byte
++ * 0x1000 is page saving sigreturn & restart code
++ */
++ flush_icache_range(base, base + 0x3000);
++}
++
++#if 0
++COLE:use send_sigtrap instread
++ static __inline__ void do_trap(int trapnr, int signr, const char *str,
++ struct pt_regs *regs,
++ unsigned long error_code, siginfo_t * info)
++{
++ if (user_mode(regs)) {
++ /* trap_signal */
++ struct task_struct *tsk = current;
++ tsk->thread.error_code = error_code;
++ tsk->thread.trap_no = trapnr;
++ if (info)
++ force_sig_info(signr, info, tsk);
++ else
++ force_sig(signr, tsk);
++ return;
++ } else {
++ /* kernel_trap */
++ if (!fixup_exception(regs))
++ die(str, regs, error_code);
++ return;
++ }
++}
++#endif
++
++/*
++ * I modified original debug_trap to apply KGDB stuff,
++ * Harry@Jul.18.2007
++ */
++void do_debug_trap(unsigned long entry, unsigned long addr,
++ unsigned long type, struct pt_regs *regs)
++{
++ if (notify_die(DIE_DEBUG, "debug", regs, addr, type, SIGTRAP)
++ == NOTIFY_STOP)
++ return;
++
++#if !defined(CONFIG_HSS)
++ /* clear the swbk; otherwise the user will see it */
++ if (test_tsk_thread_flag(current, TIF_SINGLESTEP))
++ ptrace_cancel_swbk(current);
++#endif
++
++ /* do_trap(1, SIGTRAP, 0, regs, 0, NULL); */
++ if (user_mode(regs)) {
++ /* trap_signal */
++ send_sigtrap(current, regs, 0, TRAP_BRKPT);
++ } else {
++ /* kernel_trap */
++ if (!fixup_exception(regs))
++ die("unexpected kernel_trap", regs, 0);
++ }
++}
++
++void unhandled_interruption(struct pt_regs *regs)
++{
++ siginfo_t si;
++ printk("unhandled_interruption\n");
++ show_regs(regs);
++ if (!user_mode(regs))
++ do_exit(SIGKILL);
++ si.si_signo = SIGKILL;
++ si.si_errno = 0;
++ force_sig_info(SIGKILL, &si, current);
++}
++
++void unhandled_exceptions(unsigned long entry, unsigned long addr,
++ unsigned long type, struct pt_regs *regs)
++{
++ siginfo_t si;
++ printk("Unhandled Exception: entry: %lx addr:%lx itype:%lx\n", entry,
++ addr, type);
++ show_regs(regs);
++ if (!user_mode(regs))
++ do_exit(SIGKILL);
++ si.si_signo = SIGKILL;
++ si.si_errno = 0;
++ si.si_addr = (void *)addr;
++ force_sig_info(SIGKILL, &si, current);
++}
++
++extern int do_page_fault(unsigned long entry, unsigned long addr,
++ unsigned int error_code, struct pt_regs *regs);
++
++/*
++ * 2:DEF dispatch for TLB MISC exception handler
++*/
++
++void do_dispatch_tlb_misc(unsigned long entry, unsigned long addr,
++ unsigned long type, struct pt_regs *regs)
++{
++ type = type & (ITYPE_mskINST | ITYPE_mskETYPE);
++ if ((type & 0xf) < 5)
++ do_page_fault(entry, addr, type, regs);
++ else
++ unhandled_exceptions(entry, addr, type, regs);
++}
++
++int (*do_unaligned_access) (unsigned long entry, unsigned long addr,
++ unsigned long type, struct pt_regs * regs) = NULL;
++
++EXPORT_SYMBOL(do_unaligned_access);
++
++void do_revinsn(struct pt_regs *regs)
++{
++ siginfo_t si;
++ printk("Reserved Instruction\n");
++ show_regs(regs);
++ if (!user_mode(regs))
++ do_exit(SIGILL);
++ si.si_signo = SIGILL;
++ si.si_errno = 0;
++ force_sig_info(SIGILL, &si, current);
++}
++
++/*
++ * 7:DEF dispatch for General exception handler
++ */
++void do_dispatch_general(unsigned long entry, unsigned long addr,
++ unsigned long itype, struct pt_regs *regs,
++ unsigned long oipc)
++{
++ unsigned int swid = itype >> ITYPE_offSWID;
++ unsigned long type = itype & (ITYPE_mskINST | ITYPE_mskETYPE);
++ if (type == 0) { /* Alignment check */
++
++ if (do_unaligned_access) {
++
++ int ret = do_unaligned_access(entry, addr, type, regs);
++
++ if (ret == 0)
++ return;
++
++ if (ret == -EFAULT)
++ printk
++ ("Unhandled unaligned access exception\n");
++ }
++ do_page_fault(entry, addr, type, regs);
++ } else if (type == 1) /* Reserved instruction */
++ do_revinsn(regs);
++ else if (type == 6) { /* Coprocessor */
++ if (((GET_ITYPE() & ITYPE_mskSTYPE) >> ITYPE_offSTYPE) == 3) {
++#ifdef CONFIG_AUDIO
++ preempt_disable();
++ do_audio_context_switch(type, regs);
++ preempt_enable();
++#else
++ unhandled_exceptions(entry, addr, type, regs);
++#endif
++ } else {
++#ifdef CONFIG_FPU
++ do_fpu_exception(type, regs);
++#else
++ unhandled_exceptions(entry, addr, type, regs);
++#endif
++ }
++ } else if (type == 2 && swid == 0x1a) {
++ /* trap, used on v3 EDM target debugging workaround */
++ /*
++ * DIPC(OIPC) is passed as parameter before
++ * interrupt is enabled, so the DIPC will not be corrupted
++ * even though interrupts are coming in
++ */
++ /*
++ * 1. update ipc
++ * 2. update pt_regs ipc with oipc
++ * 3. update pt_regs ipsw (clear DEX)
++ */
++ __asm__ volatile ("mtsr %0, $IPC\n\t"::"r" (oipc));
++ regs->NDS32_ipc = oipc;
++ regs->NDS32_ipsw &= ~0x400;
++ do_debug_trap(entry, addr, itype, regs);
++ } else
++ unhandled_exceptions(entry, addr, type, regs);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/kernel/vmlinux.lds.S linux-3.4.110/arch/nds32/kernel/vmlinux.lds.S
+--- linux-3.4.110.orig/arch/nds32/kernel/vmlinux.lds.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/kernel/vmlinux.lds.S 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,74 @@
++#include <asm/page.h>
++#include <asm/thread_info.h>
++#include <asm/cache.h>
++#include <asm/memory.h>
++
++#define LOAD_OFFSET (PAGE_OFFSET - PHYS_OFFSET)
++#include <asm-generic/vmlinux.lds.h>
++
++OUTPUT_ARCH(nds32)
++ENTRY(_stext_lma)
++jiffies = jiffies_64;
++
++SECTIONS
++{
++ _stext_lma = TEXTADDR - LOAD_OFFSET;
++ . = TEXTADDR;
++ __init_begin = .;
++ HEAD_TEXT_SECTION
++ INIT_TEXT_SECTION(PAGE_SIZE)
++ /* These sections are arch specific. */
++ .arch_info : AT(ADDR(.arch_info) - LOAD_OFFSET) {
++ . = ALIGN(4);
++ VMLINUX_SYMBOL(__proc_info_begin) = .;
++ *(.proc.info.init)
++ VMLINUX_SYMBOL(__proc_info_end) = .;
++ __arch_info_begin = .;
++ *(.arch.info)
++ __arch_info_end = .;
++ __tagtable_begin = .;
++ *(.taglist)
++ __tagtable_end = .;
++ . = ALIGN(16);
++ __pv_table_begin = .;
++ *(.pv_table)
++ __pv_table_end = .;
++ __early_begin = .;
++ *(__early_param)
++ __early_end = .;
++ }
++
++ INIT_DATA_SECTION(16)
++ PERCPU_SECTION(L1_CACHE_BYTES)
++ __init_end = .;
++
++ . = ALIGN(PAGE_SIZE);
++ _stext = .;
++ /* Real text segment */
++ .text : AT(ADDR(.text) - LOAD_OFFSET) {
++ _text = .; /* Text and read-only data */
++ TEXT_TEXT
++ SCHED_TEXT
++ LOCK_TEXT
++ KPROBES_TEXT
++ IRQENTRY_TEXT
++ *(.fixup)
++ }
++
++ _etext = .; /* End of text and rodata section */
++
++ _sdata = .;
++ RO_DATA_SECTION(PAGE_SIZE)
++ RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
++ _edata = .;
++
++ EXCEPTION_TABLE(16)
++ NOTES
++ BSS_SECTION(4, 4, 4)
++ _end = .;
++
++ STABS_DEBUG
++ DWARF_DEBUG
++
++ DISCARDS
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/copy_page.S linux-3.4.110/arch/nds32/lib/copy_page.S
+--- linux-3.4.110.orig/arch/nds32/lib/copy_page.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/copy_page.S 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,36 @@
++/*
++ * linux/arch/nds32/lib/copypage.S
++ * Copyright (C) 2009 Andes Technology Corporation
++ */
++#include <linux/linkage.h>
++#include <asm/page.h>
++
++ .text
++ENTRY(copy_page)
++ pushm $r2, $r10
++ movi $r2, PAGE_SIZE >> 5
++.Lcopy_loop:
++ lmw.bim $r3, [$r1], $r10
++ smw.bim $r3, [$r0], $r10
++ subi45 $r2, #1
++ bnez38 $r2, .Lcopy_loop
++ popm $r2, $r10
++ ret
++
++ENTRY(clear_page)
++ pushm $r1, $r9
++ movi $r1, PAGE_SIZE >> 5
++ movi55 $r2, #0
++ movi55 $r3, #0
++ movi55 $r4, #0
++ movi55 $r5, #0
++ movi55 $r6, #0
++ movi55 $r7, #0
++ movi55 $r8, #0
++ movi55 $r9, #0
++.Lclear_loop:
++ smw.bim $r2, [$r0], $r9
++ subi45 $r1, #1
++ bnez38 $r1, .Lclear_loop
++ popm $r1, $r9
++ ret
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/csum_partial.c linux-3.4.110/arch/nds32/lib/csum_partial.c
+--- linux-3.4.110.orig/arch/nds32/lib/csum_partial.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/csum_partial.c 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,135 @@
++/*
++ * INET An implementation of the TCP/IP protocol suite for the LINUX
++ * operating system. INET is implemented using the BSD Socket
++ * interface as the means of communication with the user level.
++ *
++ * MIPS specific IP/TCP/UDP checksumming routines
++ *
++ * Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
++ * Lots of code moved from tcp.c and ip.c; see those files
++ * for more names.
++ *
++ * 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/types.h>
++
++#include <net/checksum.h>
++#include <asm/byteorder.h>
++#include <asm/string.h>
++#include <asm/uaccess.h>
++
++#define addc(_t,_r) \
++ __asm__ __volatile__ ( \
++ "add\t%0, %0, %1\n\t" \
++ "slt\t$p1, %0, %1\n\t" \
++ "add\r%0, %0, $p1\n\t" \
++ : "=r"(_t) \
++ : "r"(_r), "0"(_t));
++
++static inline unsigned short from32to16(unsigned int x)
++{
++ /* 32 bits --> 16 bits + carry */
++ x = (x & 0xffff) + (x >> 16);
++ /* 16 bits + carry --> 16 bits including carry */
++ x = (x & 0xffff) + (x >> 16);
++ return (unsigned short)x;
++}
++
++static inline unsigned int do_csum(const unsigned char *buff, int len)
++{
++ int odd;
++ register unsigned int result = 0;
++ register unsigned int count;
++ if (len <= 0)
++ goto out;
++ odd = 1 & (unsigned long)buff;
++ if (odd) {
++ result = be16_to_cpu(*buff);
++ len--;
++ buff++;
++ }
++ count = len >> 1; /* nr of 16-bit words.. */
++ if (count) {
++ if (2 & (unsigned long)buff) {
++ result += *(unsigned short *)buff;
++ count--;
++ len -= 2;
++ buff += 2;
++ }
++ count >>= 1; /* nr of 32-bit words.. */
++ if (count) {
++ while (count >= 8) {
++ __asm__
++ __volatile__("lmw.bi $r17, [%1], $r24\n\t"
++ "add\t%0, %0, $r17\n\t"
++ "slt\t$p1, %0, $r17\n\t"
++ "add\r%0, %0, $p1\n\t"
++ "add\t%0, %0, $r18\n\t"
++ "slt\t$p1, %0, $r18\n\t"
++ "add\r%0, %0, $p1\n\t"
++ "add\t%0, %0, $r19\n\t"
++ "slt\t$p1, %0, $r19\n\t"
++ "add\r%0, %0, $p1\n\t"
++ "add\t%0, %0, $r20\n\t"
++ "slt\t$p1, %0, $r20\n\t"
++ "add\r%0, %0, $p1\n\t"
++ "add\t%0, %0, $r21\n\t"
++ "slt\t$p1, %0, $r21\n\t"
++ "add\r%0, %0, $p1\n\t"
++ "add\t%0, %0, $r22\n\t"
++ "slt\t$p1, %0, $r22\n\t"
++ "add\r%0, %0, $p1\n\t"
++ "add\t%0, %0, $r23\n\t"
++ "slt\t$p1, %0, $r23\n\t"
++ "add\r%0, %0, $p1\n\t"
++ "add\t%0, %0, $r24\n\t"
++ "slt\t$p1, %0, $r24\n\t"
++ "add\r%0, %0, $p1\n\t":"=r"
++ (result)
++ :"r"(buff), "0"(result)
++ :"$r17", "$r18", "$r19",
++ "$r20", "$r21", "$r22", "$r23",
++ "$r24");
++ count -= 8;
++ buff += 32;
++ }
++ while (count) {
++ unsigned int w = *(unsigned int *)buff;
++ count--;
++ buff += 4;
++ addc(result, w);
++ }
++ result = (result & 0xffff) + (result >> 16);
++ }
++ if (len & 2) {
++ result += *(unsigned short *)buff;
++ buff += 2;
++ }
++ }
++ if (len & 1)
++ result += le16_to_cpu(*buff);
++ result = from32to16(result);
++ if (odd)
++ result = swab16(result);
++out:
++ return result;
++}
++
++/*
++ * computes a partial checksum, e.g. for TCP/UDP fragments
++ */
++/*
++ * why bother folding?
++ */
++unsigned int csum_partial(const void *buff, int len, unsigned int sum)
++{
++ unsigned int result = 0;
++// printk("csum_partial %x %x %x\n", buff, len, sum);
++ result = do_csum(buff, len);
++ addc(result, sum);
++ return (unsigned short)from32to16(result);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/csum_partial_copy.c linux-3.4.110/arch/nds32/lib/csum_partial_copy.c
+--- linux-3.4.110.orig/arch/nds32/lib/csum_partial_copy.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/csum_partial_copy.c 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,58 @@
++/*
++ * INET An implementation of the TCP/IP protocol suite for the LINUX
++ * operating system. INET is implemented using the BSD Socket
++ * interface as the means of communication with the user level.
++ *
++ * MIPS specific IP/TCP/UDP checksumming routines
++ *
++ * Authors: Ralf Baechle, <ralf@waldorf-gmbh.de>
++ * Lots of code moved from tcp.c and ip.c; see those files
++ * for more names.
++ *
++ * 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/kernel.h>
++#include <net/checksum.h>
++#include <linux/types.h>
++#include <asm/byteorder.h>
++#include <asm/string.h>
++#include <asm/uaccess.h>
++
++/*
++ * copy while checksumming, otherwise like csum_partial
++ */
++unsigned int csum_partial_copy_nocheck(const unsigned char *src,
++ unsigned char *dst, int len,
++ unsigned int sum)
++{
++ /*
++ * It's 2:30 am and I don't feel like doing it real ...
++ * This is lots slower than the real thing (tm)
++ */
++ sum = csum_partial(src, len, sum);
++ memcpy(dst, src, len);
++
++ return sum;
++}
++
++/*
++ * Copy from userspace and compute checksum. If we catch an exception
++ * then zero the rest of the buffer.
++ */
++unsigned int csum_partial_copy_from_user(const unsigned char *src,
++ unsigned char *dst, int len,
++ unsigned int sum, int *err_ptr)
++{
++ int missing;
++
++ missing = copy_from_user(dst, src, len);
++ if (missing) {
++ memset(dst + len - missing, 0, missing);
++ *err_ptr = -EFAULT;
++ }
++
++ return csum_partial(dst, len, sum);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/divmod.c linux-3.4.110/arch/nds32/lib/divmod.c
+--- linux-3.4.110.orig/arch/nds32/lib/divmod.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/divmod.c 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,46 @@
++extern unsigned long udivmodsi4(unsigned long num, unsigned long den,
++ int modwanted);
++
++long __divsi3(long a, long b)
++{
++ int neg = 0;
++ long res;
++
++ if (a < 0) {
++ a = -a;
++ neg = !neg;
++ }
++
++ if (b < 0) {
++ b = -b;
++ neg = !neg;
++ }
++
++ res = udivmodsi4(a, b, 0);
++
++ if (neg)
++ res = -res;
++
++ return res;
++}
++
++long __modsi3(long a, long b)
++{
++ int neg = 0;
++ long res;
++
++ if (a < 0) {
++ a = -a;
++ neg = 1;
++ }
++
++ if (b < 0)
++ b = -b;
++
++ res = udivmodsi4(a, b, 1);
++
++ if (neg)
++ res = -res;
++
++ return res;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/findbit.S linux-3.4.110/arch/nds32/lib/findbit.S
+--- linux-3.4.110.orig/arch/nds32/lib/findbit.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/findbit.S 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,108 @@
++/*
++ * linux/arch/nds32/lib/findbit.S
++ *
++ * Copyright (C) 1995-2000 Russell King
++ * Copyright (C) 2006 Andes Technology Corporation
++ *
++ * 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/linkage.h>
++
++ .text
++
++/*
++ * Purpose : Find a 'zero' bit
++ * Prototype: int find_first_zero_bit(void *addr, int maxbit);
++ */
++ENTRY(_find_first_zero_bit)
++ move $r2, #0
++ move $p0, #0 ! Reset bit count
++next_word:
++ move $r4, #4
++ lmw.bim $p1, [$r0], $p1
++ li $r3, #0xffffffff ! Inversion mask
++ xor $p1, $p1, $r3 ! Inverted the word
++ addi $p0, $p0, #32
++ beqz $p1, next_word
++ addi $p0, $p0, #-32
++next_byte:
++ beqz $r4, next_word
++ andi $r3, $p1, #0xff ! Get the next byte
++ bnez $r3, found ! Found zero bit in this byte
++ addi $p0, $p0, #8 ! Update bit count
++ addi $r4, $r4, #-1
++ srli $p1, $p1, #8
++ bgt $r1, $p0, next_byte
++ addi $r0, $r1, #1 ! Return not found
++ ret
++
++/*
++ * Purpose : Find next 'zero' bit
++ * Prototype: int find_next_zero_bit(void *addr, int maxbit, int offset)
++ */
++ENTRY(_find_next_zero_bit)
++ beqz $r2, _find_first_zero_bit ! If offset=0, goto find_first_zero_bit
++ srli $p0, $r2, #5 ! Get offset byte count
++ slli $p0, $p0, #2
++ add $r0, $r0, $p0 ! $r0 is the first word to load
++ lmw.bim $p1, [$r0], $p1
++ li $p0, #0xffffffff ! Inversion mask
++ xor $p1, $p1, $p0 ! Inverted the word
++ andi $r4, $r2, #31 ! Left bits in offset
++ srl $p1, $p1, $r4 ! Shift out the left bits
++ xor $p0, $p0, $p0
++ subri $r4, $r4, #31
++loop:
++ andi $r3, $p1, #0xff ! The first byte to check
++ bnez $r3, found ! Found zero bit in this byte
++ addi $p0, $p0, #8
++ addi $r4, $r4, #-8
++ srli $p1, $p1, #8 ! Move on to the next byte
++ bgtz $r4, loop
++ b next_word
++
++/*
++ * One or more bits in the LSB of $p1 are assumed to be set.
++ */
++
++found:
++ move $p1, $r3
++ xor $r4, $r4, $r4
++ andi $r5, $p1, #0x0f ! Get bits 0-3
++ move $r3, #4 ! For 0 case (no set bit found)
++ cmovn $r3, $r4, $r5 ! Not 0 case (There's set bit in these 4 bits)
++ add $p0, $p0, $r3 ! Update bit count
++ slli $r3, $p1, #4 ! Not 0 case (Find set bit in these 4 bits)
++ cmovn $p1, $r3, $r5 ! For 0 case (Find set bit in the rest 4 bits)
++ andi $r5, $p1, #0x30 ! Get 4-5
++ move $r3, #2 ! For 0 case (no set bit found)
++ cmovn $r3, $r4, $r5 ! Not 0 case (There's set bit in these 2 bits)
++ add $p0, $p0, $r3 ! Update bit count
++ slli $r3, $p1, #2 ! Not 0 case (Find set bit in these 2 bits)
++ cmovn $p1, $r3, $r5 ! For 0 case (Find set bit in the rest 2 bits)
++ andi $r5, $p1, #0x40 ! Get bit 6
++ move $r3, #1 ! For 0 case (bit 6 is not set)
++ cmovn $r3, $r4, $r5 ! Not 0 case (bit 6 is set bit)
++ add $r5, $p0, $r3
++ add $r0, $r5, $r2
++ ret
++
++ENTRY(_ext2_find_first_zero_bit)
++ pushm $r2, $r4
++ move $r2, #0
++ move $p0, #0 ! Reset bit count
++1:
++ lbi.bi $r3, [$r0], #1
++ xori $r3, $r3, #0xff
++ addi $p0, $p0, #8
++ beqz $r3, 1b
++ addi $p0, $p0, #-8
++
++2:
++ b found ! No return
++ popm $r2, $r4
++ ret
++
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/getuser.S linux-3.4.110/arch/nds32/lib/getuser.S
+--- linux-3.4.110.orig/arch/nds32/lib/getuser.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/getuser.S 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,79 @@
++/*
++ * linux/arch/nds32/lib/getuser.S
++ *
++ * Copyright (C) 2001 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Idea from x86 version, (C) Copyright 1998 Linus Torvalds
++ *
++ * These functions have a non-standard call interface to make them more
++ * efficient, especially as they return an error value in addition to
++ * the "real" return value.
++ *
++ * __get_user_X
++ *
++ * Inputs: $r0 contains the address
++ * Outputs: $r0 is the error code
++ * $r2, $r3 contains the zero-extended value
++ * lr corrupted
++ *
++ * No other registers must be altered. (see include/asm-nds32/uaccess.h
++ * for specific ASM register usage).
++ *
++ * Note that ADDR_LIMIT is either 0 or 0xc0000000.
++ * Note also that it is intended that __get_user_bad is not global.
++ */
++#include <asm/asm-offsets.h>
++#include <asm/thread_info.h>
++#include <asm/errno.h>
++#include <linux/linkage.h>
++
++
++ENTRY(__get_user_1)
++1: lbi $r2, [$r0]
++ move $r0, #0
++ ret
++
++ENTRY(__get_user_2)
++2: lbi.bi $r2, [$r0], #1
++3: lbi $r3, [$r0]
++#ifndef __NDS32_EB__
++ slli $p1, $r3, #8
++ or $r2, $r2, $p1
++#else
++ slli $p1, $r2, #8
++ or $r2, $r3, $p1
++#endif
++ move $r0, #0
++ ret
++
++ENTRY(__get_user_4)
++4: lwi $r2, [$r0]
++ move $r0, #0
++ ret
++
++ENTRY(__get_user_8)
++5: lwi.bi $r2, [$r0], #4
++6: lwi $r3, [$r0]
++ move $r0, #0
++ ret
++
++__get_user_bad_8:
++ move $r3, #0
++__get_user_bad:
++ move $r2, #0
++ move $r0, #-EFAULT
++ ret
++
++.section __ex_table, "a"
++ .long 1b, __get_user_bad
++ .long 2b, __get_user_bad
++ .long 3b, __get_user_bad
++ .long 4b, __get_user_bad
++ .long 5b, __get_user_bad_8
++ .long 6b, __get_user_bad_8
++.previous
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/libgcc2.c linux-3.4.110/arch/nds32/lib/libgcc2.c
+--- linux-3.4.110.orig/arch/nds32/lib/libgcc2.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/libgcc2.c 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,351 @@
++#define BITS_PER_UNIT 8
++#include "longlong.h"
++typedef unsigned int UQItype __attribute__ ((mode(QI)));
++typedef int SItype __attribute__ ((mode(SI)));
++typedef unsigned int USItype __attribute__ ((mode(SI)));
++typedef int DItype __attribute__ ((mode(DI)));
++typedef unsigned int UDItype __attribute__ ((mode(DI)));
++
++typedef int word_type __attribute__ ((mode(__word__)));
++
++#define Wtype SItype
++#define UWtype USItype
++#define DWtype DItype
++#define UDWtype UDItype
++
++#ifdef __NDS32_EB__
++struct DWstruct {
++ Wtype high, low;
++};
++#else
++struct DWstruct {
++ Wtype low, high;
++};
++#endif
++
++typedef union {
++ struct DWstruct s;
++ DWtype ll;
++} DWunion;
++DWtype __negdi2(DWtype u)
++{
++ const DWunion uu = {.ll = u };
++ const DWunion w = { {.low = -uu.s.low,
++ .high = -uu.s.high - ((UWtype) - uu.s.low > 0)}
++ };
++
++ return w.ll;
++}
++
++DWtype __lshrdi3(DWtype u, word_type b)
++{
++ const DWunion uu = {.ll = u };
++ const word_type bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
++ DWunion w;
++
++ if (b == 0)
++ return u;
++
++ if (bm <= 0) {
++ w.s.high = 0;
++ w.s.low = (UWtype) uu.s.high >> -bm;
++ } else {
++ const UWtype carries = (UWtype) uu.s.high << bm;
++
++ w.s.high = (UWtype) uu.s.high >> b;
++ w.s.low = ((UWtype) uu.s.low >> b) | carries;
++ }
++
++ return w.ll;
++}
++
++DWtype __ashldi3(DWtype u, word_type b)
++{
++ const DWunion uu = {.ll = u };
++ const word_type bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
++ DWunion w;
++
++ if (b == 0)
++ return u;
++
++ if (bm <= 0) {
++ w.s.low = 0;
++ w.s.high = (UWtype) uu.s.low << -bm;
++ } else {
++ const UWtype carries = (UWtype) uu.s.low >> bm;
++
++ w.s.low = (UWtype) uu.s.low << b;
++ w.s.high = ((UWtype) uu.s.high << b) | carries;
++ }
++
++ return w.ll;
++}
++
++DWtype __ashrdi3(DWtype u, word_type b)
++{
++ const DWunion uu = {.ll = u };
++ const word_type bm = (sizeof(Wtype) * BITS_PER_UNIT) - b;
++ DWunion w;
++
++ if (b == 0)
++ return u;
++
++ if (bm <= 0) {
++ /* w.s.high = 1..1 or 0..0 */
++ w.s.high = uu.s.high >> (sizeof(Wtype) * BITS_PER_UNIT - 1);
++ w.s.low = uu.s.high >> -bm;
++ } else {
++ const UWtype carries = (UWtype) uu.s.high << bm;
++
++ w.s.high = uu.s.high >> b;
++ w.s.low = ((UWtype) uu.s.low >> b) | carries;
++ }
++
++ return w.ll;
++}
++
++DWtype __muldi3(DWtype u, DWtype v)
++{
++ const DWunion uu = {.ll = u };
++ const DWunion vv = {.ll = v };
++ DWunion w = {.ll = __umulsidi3(uu.s.low, vv.s.low) };
++
++ w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high
++ + (UWtype) uu.s.high * (UWtype) vv.s.low);
++
++ return w.ll;
++}
++
++const UQItype __clz_tab[] = {
++ 0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
++ 5, 5, 5, 5, 5, 5, 5, 5,
++ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
++ 6, 6, 6, 6, 6, 6, 6, 6,
++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
++ 7, 7, 7, 7, 7, 7, 7, 7,
++ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
++ 7, 7, 7, 7, 7, 7, 7, 7,
++ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
++ 8, 8, 8, 8, 8, 8, 8, 8,
++ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
++ 8, 8, 8, 8, 8, 8, 8, 8,
++ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
++ 8, 8, 8, 8, 8, 8, 8, 8,
++ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
++ 8, 8, 8, 8, 8, 8, 8, 8,
++};
++
++UDWtype __udivmoddi4(UDWtype n, UDWtype d, UDWtype * rp)
++{
++ const DWunion nn = {.ll = n };
++ const DWunion dd = {.ll = d };
++ DWunion rr;
++ UWtype d0, d1, n0, n1, n2;
++ UWtype q0, q1;
++ UWtype b, bm;
++ DWunion ww;
++
++ d0 = dd.s.low;
++ d1 = dd.s.high;
++ n0 = nn.s.low;
++ n1 = nn.s.high;
++
++#if !UDIV_NEEDS_NORMALIZATION
++ if (d1 == 0) {
++ if (d0 > n1) {
++ /* 0q = nn / 0D */
++
++ udiv_qrnnd(q0, n0, n1, n0, d0);
++ q1 = 0;
++
++ /* Remainder in n0. */
++ } else {
++ /* qq = NN / 0d */
++
++ if (d0 == 0)
++ d0 = 1 / d0; /* Divide intentionally by zero. */
++
++ udiv_qrnnd(q1, n1, 0, n1, d0);
++ udiv_qrnnd(q0, n0, n1, n0, d0);
++
++ /* Remainder in n0. */
++ }
++
++ if (rp != 0) {
++ rr.s.low = n0;
++ rr.s.high = 0;
++ *rp = rr.ll;
++ }
++ }
++#else /* UDIV_NEEDS_NORMALIZATION */
++
++ if (d1 == 0) {
++ if (d0 > n1) {
++ /* 0q = nn / 0D */
++
++ count_leading_zeros(bm, d0);
++
++ if (bm != 0) {
++ /* Normalize, i.e. make the most significant bit of the
++ denominator set. */
++
++ d0 = d0 << bm;
++ n1 = (n1 << bm) | (n0 >> (W_TYPE_SIZE - bm));
++ n0 = n0 << bm;
++ }
++
++ udiv_qrnnd(q0, n0, n1, n0, d0);
++ q1 = 0;
++
++ /* Remainder in n0 >> bm. */
++ } else {
++ /* qq = NN / 0d */
++
++ if (d0 == 0)
++ d0 = 1 / d0; /* Divide intentionally by zero. */
++
++ count_leading_zeros(bm, d0);
++
++ if (bm == 0) {
++ /* From (n1 >= d0) /\ (the most significant bit of d0 is set),
++ conclude (the most significant bit of n1 is set) /\ (the
++ leading quotient digit q1 = 1).
++
++ This special case is necessary, not an optimization.
++ (Shifts counts of W_TYPE_SIZE are undefined.) */
++
++ n1 -= d0;
++ q1 = 1;
++ } else {
++ /* Normalize. */
++
++ b = W_TYPE_SIZE - bm;
++
++ d0 = d0 << bm;
++ n2 = n1 >> b;
++ n1 = (n1 << bm) | (n0 >> b);
++ n0 = n0 << bm;
++
++ udiv_qrnnd(q1, n1, n2, n1, d0);
++ }
++
++ /* n1 != d0... */
++
++ udiv_qrnnd(q0, n0, n1, n0, d0);
++
++ /* Remainder in n0 >> bm. */
++ }
++
++ if (rp != 0) {
++ rr.s.low = n0 >> bm;
++ rr.s.high = 0;
++ *rp = rr.ll;
++ }
++ }
++#endif /* UDIV_NEEDS_NORMALIZATION */
++
++ else {
++ if (d1 > n1) {
++ /* 00 = nn / DD */
++
++ q0 = 0;
++ q1 = 0;
++
++ /* Remainder in n1n0. */
++ if (rp != 0) {
++ rr.s.low = n0;
++ rr.s.high = n1;
++ *rp = rr.ll;
++ }
++ } else {
++ /* 0q = NN / dd */
++
++ count_leading_zeros(bm, d1);
++ if (bm == 0) {
++ /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
++ conclude (the most significant bit of n1 is set) /\ (the
++ quotient digit q0 = 0 or 1).
++
++ This special case is necessary, not an optimization. */
++
++ /* The condition on the next line takes advantage of that
++ n1 >= d1 (true due to program flow). */
++ if (n1 > d1 || n0 >= d0) {
++ q0 = 1;
++ sub_ddmmss(n1, n0, n1, n0, d1, d0);
++ } else
++ q0 = 0;
++
++ q1 = 0;
++
++ if (rp != 0) {
++ rr.s.low = n0;
++ rr.s.high = n1;
++ *rp = rr.ll;
++ }
++ } else {
++ UWtype m1, m0;
++ /* Normalize. */
++
++ b = W_TYPE_SIZE - bm;
++
++ d1 = (d1 << bm) | (d0 >> b);
++ d0 = d0 << bm;
++ n2 = n1 >> b;
++ n1 = (n1 << bm) | (n0 >> b);
++ n0 = n0 << bm;
++
++ udiv_qrnnd(q0, n1, n2, n1, d1);
++ umul_ppmm(m1, m0, q0, d0);
++
++ if (m1 > n1 || (m1 == n1 && m0 > n0)) {
++ q0--;
++ sub_ddmmss(m1, m0, m1, m0, d1, d0);
++ }
++
++ q1 = 0;
++
++ /* Remainder in (n1n0 - m1m0) >> bm. */
++ if (rp != 0) {
++ sub_ddmmss(n1, n0, n1, n0, m1, m0);
++ rr.s.low = (n1 << b) | (n0 >> bm);
++ rr.s.high = n1 >> bm;
++ *rp = rr.ll;
++ }
++ }
++ }
++ }
++
++ ww.s.low = q0, ww.s.high = q1;
++ return ww.ll;
++}
++
++UDWtype __umoddi3(UDWtype u, UDWtype v)
++{
++ UDWtype w;
++
++ (void)__udivmoddi4(u, v, &w);
++
++ return w;
++}
++
++UDWtype __udivdi3(UDWtype n, UDWtype d)
++{
++ return __udivmoddi4(n, d, (UDWtype *) 0);
++}
++
++word_type __ucmpdi2(DWtype a, DWtype b)
++{
++ const DWunion au = {.ll = a };
++ const DWunion bu = {.ll = b };
++
++ if ((UWtype) au.s.high < (UWtype) bu.s.high)
++ return 0;
++ else if ((UWtype) au.s.high > (UWtype) bu.s.high)
++ return 2;
++ if ((UWtype) au.s.low < (UWtype) bu.s.low)
++ return 0;
++ else if ((UWtype) au.s.low > (UWtype) bu.s.low)
++ return 2;
++ return 1;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/longlong.h linux-3.4.110/arch/nds32/lib/longlong.h
+--- linux-3.4.110.orig/arch/nds32/lib/longlong.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/longlong.h 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,105 @@
++#define __BITS4 (W_TYPE_SIZE / 4)
++#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2))
++#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1))
++#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2))
++
++#define W_TYPE_SIZE (4 * 8)
++#define UHWtype USItype
++
++#define sub_ddmmss(sh, sl, ah, al, bh, bl) \
++ do { \
++ UWtype __x; \
++ __x = (al) - (bl); \
++ (sh) = (ah) - (bh) - (__x > (al)); \
++ (sl) = __x; \
++ } while (0)
++
++#define umul_ppmm(w1, w0, u, v) \
++ do { \
++ UWtype __x0, __x1, __x2, __x3; \
++ UHWtype __ul, __vl, __uh, __vh; \
++ \
++ __ul = __ll_lowpart (u); \
++ __uh = __ll_highpart (u); \
++ __vl = __ll_lowpart (v); \
++ __vh = __ll_highpart (v); \
++ \
++ __x0 = (UWtype) __ul * __vl; \
++ __x1 = (UWtype) __ul * __vh; \
++ __x2 = (UWtype) __uh * __vl; \
++ __x3 = (UWtype) __uh * __vh; \
++ \
++ __x1 += __ll_highpart (__x0);/* this can't give carry */ \
++ __x1 += __x2; /* but this indeed can */ \
++ if (__x1 < __x2) /* did we get it? */ \
++ __x3 += __ll_B; /* yes, add it in the proper pos. */ \
++ \
++ (w1) = __x3 + __ll_highpart (__x1); \
++ (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0); \
++ } while (0)
++
++#define __umulsidi3(u, v) \
++ ({DWunion __w; \
++ umul_ppmm (__w.s.high, __w.s.low, u, v); \
++ __w.ll; })
++
++#define __udiv_qrnnd_c(q, r, n1, n0, d) \
++ do { \
++ UWtype __d1, __d0, __q1, __q0; \
++ UWtype __r1, __r0, __m; \
++ __d1 = __ll_highpart (d); \
++ __d0 = __ll_lowpart (d); \
++ \
++ __r1 = (n1) % __d1; \
++ __q1 = (n1) / __d1; \
++ __m = (UWtype) __q1 * __d0; \
++ __r1 = __r1 * __ll_B | __ll_highpart (n0); \
++ if (__r1 < __m) \
++ { \
++ __q1--, __r1 += (d); \
++ if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\
++ if (__r1 < __m) \
++ __q1--, __r1 += (d); \
++ } \
++ __r1 -= __m; \
++ \
++ __r0 = __r1 % __d1; \
++ __q0 = __r1 / __d1; \
++ __m = (UWtype) __q0 * __d0; \
++ __r0 = __r0 * __ll_B | __ll_lowpart (n0); \
++ if (__r0 < __m) \
++ { \
++ __q0--, __r0 += (d); \
++ if (__r0 >= (d)) \
++ if (__r0 < __m) \
++ __q0--, __r0 += (d); \
++ } \
++ __r0 -= __m; \
++ \
++ (q) = (UWtype) __q1 * __ll_B | __q0; \
++ (r) = __r0; \
++ } while (0)
++
++#define UDIV_NEEDS_NORMALIZATION 1
++#define udiv_qrnnd __udiv_qrnnd_c
++
++#define count_leading_zeros(count, x) \
++ do { \
++ UWtype __xr = (x); \
++ UWtype __a; \
++ \
++ if (W_TYPE_SIZE <= 32) \
++ { \
++ __a = __xr < ((UWtype)1<<2*__BITS4) \
++ ? (__xr < ((UWtype)1<<__BITS4) ? 0 : __BITS4) \
++ : (__xr < ((UWtype)1<<3*__BITS4) ? 2*__BITS4 : 3*__BITS4); \
++ } \
++ else \
++ { \
++ for (__a = W_TYPE_SIZE - 8; __a > 0; __a -= 8) \
++ if (((__xr >> __a) & 0xff) != 0) \
++ break; \
++ } \
++ \
++ (count) = W_TYPE_SIZE - (__clz_tab[__xr >> __a] + __a); \
++ } while (0)
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/Makefile linux-3.4.110/arch/nds32/lib/Makefile
+--- linux-3.4.110.orig/arch/nds32/lib/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/Makefile 2016-04-07 10:20:50.950081334 +0200
+@@ -0,0 +1,19 @@
++#
++# linux/arch/nds32/lib/Makefile
++#
++# Copyright (C) 2006 Andes Technology Corporation
++#
++
++lib-y := csum_partial_copy.o csum_partial.o \
++ copy_page.o memcpy.o memmove.o \
++ memset.o memzero.o strncpy_from_user.o \
++ strnlen_user.o strchr.o strrchr.o \
++ uaccess.o getuser.o \
++ putuser.o libgcc2.o divmod.o udivmod.o udivmodsi4.o
++
++ifdef CONFIG_FUNCTION_TRACER
++CFLAGS_REMOVE_libgcc2.o = -pg
++CFLAGS_REMOVE_divmod.o = -pg
++CFLAGS_REMOVE_udivmod.o = -pg
++CFLAGS_REMOVE_udivmodsi4.o = -pg
++endif
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/memcpy.S linux-3.4.110/arch/nds32/lib/memcpy.S
+--- linux-3.4.110.orig/arch/nds32/lib/memcpy.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/memcpy.S 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,101 @@
++/*
++ * linux/arch/nds32/lib/memcpy.S -- Memory copy function.
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2001 Hiroyuki Kondo, and Hirokazu Takata
++ * Copyright (C) 2004 Hirokazu Takata
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ */
++
++#include <linux/linkage.h>
++
++/*
++ void *memcpy(void *dst, const void *src, int n);
++
++ dst: $r0
++ src: $r1
++ n : $r2
++ ret: $r0 - pointer to the memory area dst.
++*/
++
++#include <linux/linkage.h>
++
++ .text
++
++ENTRY(memcpy)
++ move $r5, $r0
++ beq $r0, $r1, quit_memcpy
++ beqz $r2, quit_memcpy
++ srli $r3, $r2, #5 ! check if len < cache-line size 32
++ beqz $r3, word_copy_entry
++ andi $r4, $r0, #0x3 ! check byte-align
++ beqz $r4, unalign_word_copy_entry
++
++ addi $r4, $r4,#-4
++ abs $r4, $r4 ! check how many un-align byte to copy
++ sub $r2, $r2, $r4 ! update $R2
++
++unalign_byte_copy:
++ lbi.bi $r3, [$r1], #1
++ addi $r4, $r4, #-1
++ sbi.bi $r3, [$r0], #1
++ bnez $r4, unalign_byte_copy
++ beqz $r2, quit_memcpy
++
++unalign_word_copy_entry:
++ andi $r3, $r0, 0x1f ! check cache-line unaligncount
++ beqz $r3, cache_copy
++
++ addi $r3, $r3, #-32
++ abs $r3, $r3
++ sub $r2, $r2, $r3 ! update $R2
++
++unalign_word_copy:
++ lmw.bim $r4, [$r1], $r4
++ addi $r3, $r3, #-4
++ smw.bim $r4, [$r0], $r4
++ bnez $r3, unalign_word_copy
++ beqz $r2, quit_memcpy
++
++ addi $r3, $r2, #-32 ! to check $r2< cache_line , than go to word_copy
++ bltz $r3, word_copy_entry
++cache_copy:
++ srli $r3, $r2, #5
++ beqz $r3, word_copy_entry
++ pushm $r6, $r13
++3:
++ lmw.bim $r6, [$r1], $r13
++ addi $r3, $r3, #-1
++ smw.bim $r6, [$r0], $r13
++ bnez $r3, 3b
++ popm $r6, $r13
++
++word_copy_entry:
++ andi $r2, $r2, #31
++
++ beqz $r2, quit_memcpy
++5:
++ srli $r3, $r2, #2
++ beqz $r3, byte_copy
++word_copy:
++ lmw.bim $r4, [$r1], $r4
++ addi $r3, $r3, #-1
++ smw.bim $r4, [$r0], $r4
++ bnez $r3, word_copy
++ andi $r2, $r2, #3
++ beqz $r2, quit_memcpy
++byte_copy:
++ lbi.bi $r3, [$r1], #1
++ addi $r2, $r2, #-1
++
++ sbi.bi $r3, [$r0], #1
++ bnez $r2, byte_copy
++quit_memcpy:
++ move $r0, $r5
++ ret
++
++ .end
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/memmove.S linux-3.4.110/arch/nds32/lib/memmove.S
+--- linux-3.4.110.orig/arch/nds32/lib/memmove.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/memmove.S 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,80 @@
++/*
++ * linux/arch/nds32/lib/memmove.S -- Memory move function.
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2001 Hiroyuki Kondo, and Hirokazu Takata
++ * Copyright (C) 2004 Hirokazu Takata
++ * Copyright (C) 2006 Andes Technology Corporation
++ *
++ */
++
++#include <linux/linkage.h>
++
++/*
++ void *memmove(void *dst, const void *src, int n);
++
++ dst: $r0
++ src: $r1
++ n : $r2
++ ret: $r0 - pointer to the memory area dst.
++*/
++ .text
++
++ENTRY(memmove)
++ move $r5, $r0 ! Set return value = det
++ beq $r0, $r1, exit_memcpy ! Exit when det = src
++ beqz $r2, exit_memcpy ! Exit when n = 0
++ pushm $t0, $t1 ! Save reg
++ srli $p1, $r2, #2 ! $p1 is how many words to copy
++
++ ! Avoid data lost when memory overlap
++ ! Copy data reversely when src < dst
++ slt $p0, $r0, $r1 ! check if $r0 < $r1
++ beqz $p0, do_reverse ! branch if dst > src
++
++ ! No reverse, dst < src
++ andi $r2, $r2, #3 ! How many bytes are less than a word
++ li $t0, #1 ! Determining copy direction in byte_cpy
++ beqz $p1, byte_cpy ! When n is less than a word
++
++word_cpy:
++ lmw.bim $p0, [$r1], $p0 ! Read a word from src
++ addi $p1, $p1, #-1 ! How many words left to copy
++ smw.bim $p0, [$r0], $p0 ! Copy the word to det
++ bnez $p1, word_cpy ! If remained words > 0
++ beqz $r2, end_memcpy ! No left bytes to copy
++ b byte_cpy
++
++do_reverse:
++ add $r0, $r0, $r2 ! Start with the end of $r0
++ add $r1, $r1, $r2 ! Start with the end of $r1
++ andi $r2, $r2, #3 ! How many bytes are less than a word
++ li $t0, #-1 ! Determining copy direction in byte_cpy
++ beqz $p1, reverse_byte_cpy ! When n is less than a word
++
++reverse_word_cpy:
++ lmw.adm $p0, [$r1], $p0 ! Read a word from src
++ addi $p1, $p1, #-1 ! How many words left to copy
++ smw.adm $p0, [$r0], $p0 ! Copy the word to det
++ bnez $p1, reverse_word_cpy ! If remained words > 0
++ beqz $r2, end_memcpy ! No left bytes to copy
++
++reverse_byte_cpy:
++ addi $r0, $r0, #-1
++ addi $r1, $r1, #-1
++byte_cpy: ! Less than 4 bytes to copy now
++ lb.bi $p0, [$r1], $t0 ! Read a byte from src
++ addi $r2, $r2, #-1 ! How many bytes left to copy
++ sb.bi $p0, [$r0], $t0 ! copy the byte to det
++ bnez $r2, byte_cpy ! If remained bytes > 0
++
++end_memcpy:
++ popm $t0, $t1
++exit_memcpy:
++ move $r0, $r5
++ ret
++
++ .end
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/memset.S linux-3.4.110/arch/nds32/lib/memset.S
+--- linux-3.4.110.orig/arch/nds32/lib/memset.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/memset.S 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,51 @@
++
++/*
++ * linux/arch/nds32/lib/memset.S -- memset function.
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2001,2002 Hiroyuki Kondo, and Hirokazu Takata
++ * Copyright (C) 2004 Hirokazu Takata
++ * Copyright (C) 2006 Andes Technology Corporation
++ *
++ */
++#include <linux/linkage.h>
++#include <asm/assembler.h>
++
++/*
++ void *memset(void *dst, int val, int len);
++
++ dst: $r0
++ val: $r1
++ len: $r2
++ ret: $r0 - pointer to the memory area dst.
++*/
++ .text
++ENTRY(memset)
++ move $r5, $r0 ! Return value
++ beqz $r2, end_memset ! Exit when len = 0
++ srli $p1, $r2, 2 ! $p1 is how many words to copy
++ andi $r2, $r2, 3 ! How many bytes are less than a word
++ beqz $p1, byte_set ! When n is less than a word
++
++ ! set $r1 from ??????ab to abababab
++ andi $r1, $r1, #0x00ff ! $r1 = 000000ab
++ slli $p0, $r1, #8 ! $p0 = 0000ab00
++ or $r1, $r1, $p0 ! $r1 = 0000abab
++ slli $p0, $r1, #16 ! $p0 = abab0000
++ or $r1, $r1, $p0 ! $r1 = abababab
++word_set:
++ addi $p1, $p1, #-1 ! How many words left to copy
++ smw.bim $r1, [$r0], $r1 ! Copy the word to det
++ bnez $p1, word_set ! Still words to set, continue looping
++ beqz $r2, end_memset ! No left byte to set
++byte_set: ! Less than 4 bytes left to set
++ addi $r2, $r2, #-1 ! Decrease len by 1
++ sbi.bi $r1, [$r0], #1 ! Set data of the next byte to $r1
++ bnez $r2, byte_set ! Still bytes left to set
++end_memset:
++ move $r0, $r5
++ ret
++
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/memzero.S linux-3.4.110/arch/nds32/lib/memzero.S
+--- linux-3.4.110.orig/arch/nds32/lib/memzero.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/memzero.S 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,36 @@
++/*
++ * linux/arch/nds32/lib/memzero.S
++ *
++ * Copyright (C) 1995-2000 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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/linkage.h>
++#include <asm/assembler.h>
++
++ .text
++/*
++ * void *__memzero(void *dst, int len);
++ *
++ * dst: $r0
++ * len: $r1
++ * ret: $r0 - pointer to the memory area dst.
++ *
++ * Call memset(dst, 0, len) to perform memzero.
++ * Currently no optimization because only being referenced in 31 files
++ * (For comparison, memset being referenced in 2527 files)
++ */
++ENTRY(__memzero)
++ beqz $r1, 1f
++ push $lp
++ move $r2, $r1
++ move $r1, #0
++ push $r0
++ bal memset
++ pop $r0
++ pop $lp
++1:
++ ret
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/putuser.S linux-3.4.110/arch/nds32/lib/putuser.S
+--- linux-3.4.110.orig/arch/nds32/lib/putuser.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/putuser.S 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,68 @@
++/*
++ * linux/arch/nds32/lib/putuser.S
++ *
++ * Copyright (C) 2001 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Idea from x86 version, (C) Copyright 1998 Linus Torvalds
++ *
++ * These functions have a non-standard call interface to make
++ * them more efficient, especially as they return an error
++ * value in addition to the "real" return value.
++ *
++ * __put_user_X
++ *
++ * Inputs: $r0 contains the address
++ * $r2, $r3 contains the value
++ * Outputs: $r0 is the error code
++ * lr corrupted
++ *
++ * No other registers must be altered. (see include/asm-arm/uaccess.h
++ * for specific ASM register usage).
++ *
++ * Note that ADDR_LIMIT is either 0 or 0xc0000000
++ * Note also that it is intended that __put_user_bad is not global.
++ */
++#include <asm/asm-offsets.h>
++#include <asm/thread_info.h>
++#include <asm/errno.h>
++#include <linux/linkage.h>
++
++ .text
++
++ENTRY(__put_user_1)
++1: sb $r2, [$r0]
++ move $r0, #0
++ ret
++
++ENTRY(__put_user_2)
++2: shi $r2, [$r0] ! Store input halfword
++ move $r0, #0
++ ret
++
++ENTRY(__put_user_4)
++3: sw $r2, [$r0]
++ move $r0, #0
++ ret
++
++ENTRY(__put_user_8)
++5: swi.bi $r2, [$r0], #4
++6: sw $r3, [$r0]
++ move $r0, #0
++ ret
++
++__put_user_bad:
++ move $r0, #-EFAULT
++ ret
++
++.section __ex_table, "a"
++ .long 1b, __put_user_bad
++ .long 2b, __put_user_bad
++ .long 3b, __put_user_bad
++ .long 5b, __put_user_bad
++ .long 6b, __put_user_bad
++.previous
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/strchr.S linux-3.4.110/arch/nds32/lib/strchr.S
+--- linux-3.4.110.orig/arch/nds32/lib/strchr.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/strchr.S 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,37 @@
++/*
++ * linux/arch/nds32/lib/strchr.S
++ *
++ * Copyright (C) 1995-2000 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * ASM optimised string functions
++ */
++#include <linux/linkage.h>
++#include <asm/assembler.h>
++
++/*
++ * Prototype: char *strrchr(const char *s, int c);
++ * Purpose : Returns a pointer to the first occurrence of the character c
++ * in the string s. Here "character" means "byte" - these functions
++ * do not work with wide or multi-byte characters.
++ */
++
++ .text
++
++ENTRY(strchr)
++ move $r5, $r0 ! Setup return value
++ andi $r1, $r1, #0xff ! Wipe out useless bits
++loop:
++ lbi.bi $p0, [$r5], #1 ! Load the next byte
++ beqz $p0, exit ! Reach EOS (NULL), return NULL
++ bne $p0, $r1, loop ! Continue if != c
++ addi $r5, $r5, #-1 ! Found
++exit:
++ cmovz $r5, $p0, $p0 ! Return NULL if EOS (NULL)
++ move $r0, $r5
++ ret
++
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/strncpy_from_user.S linux-3.4.110/arch/nds32/lib/strncpy_from_user.S
+--- linux-3.4.110.orig/arch/nds32/lib/strncpy_from_user.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/strncpy_from_user.S 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,45 @@
++/*
++ * linux/arch/nds32/lib/strncpy_from_user.S
++ *
++ * Copyright (C) 1995-2000 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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/linkage.h>
++#include <asm/assembler.h>
++#include <asm/errno.h>
++
++
++/*
++ * Copy a string from user space to kernel space.
++ * $r0 = dst, $r1 = src, $r2 = n (byte length)
++ * returns the number of characters copied (strlen of copied string),
++ * -EFAULT on exception, or "len" if we fill the whole buffer
++ */
++
++ .text
++ .align 4
++ENTRY(__arch_strncpy_from_user)
++ move $p1, $r1 ! Record the start src addr
++loop:
++ addi $r2, $r2, #-1 ! Decrease n by 1
++ bltz $r2, exit ! Exit if n < 0
++USER( lbi.bi, $p0, [$r1], #1) ! Load the byte from src
++ sbi.bi $p0, [$r0], #1 ! Store the byte to dst
++ bnez $p0, loop ! Continue looping if terminator is not reached
++ addi $r1, $r1, #-1 ! Don't count the terminator
++exit:
++ sub $r0, $r1, $p1 ! Get copied count
++ ret
++
++ .section .fixup,"ax"
++ .align 0
++9001: xor $p0, $p0, $p0
++ sb $p0, [$r0] ! Zero the buffer
++ move $r0, -EFAULT ! Return -EFAULT
++ ret
++ .previous
++
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/strnlen_user.S linux-3.4.110/arch/nds32/lib/strnlen_user.S
+--- linux-3.4.110.orig/arch/nds32/lib/strnlen_user.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/strnlen_user.S 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,43 @@
++/*
++ * linux/arch/nds32/lib/strnlen_user.S
++ *
++ * Copyright (C) 1995-2000 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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/linkage.h>
++#include <asm/assembler.h>
++#include <asm/errno.h>
++
++ .text
++
++/* Prototype: unsigned long ___arch_strnlen_user(const char *str, long n)
++ * Purpose : get length of a string in user memory
++ * Params : str - address of string in user memory
++ * Returns : length of string *including terminator*
++ * or zero on exception, or n + 1 if too long
++ */
++ .align 4
++ENTRY(__arch_strnlen_user)
++ move $p0, $r0 ! Record the start addr
++ ! beqz $r0, exit ! Exit when Null address
++ beqz $r1, exit ! Exit when n = 0
++loop:
++USER( lbi.bi, $p1, [$r0], #1) ! Load the next byte
++ beqz $p1, exit ! Exit when terminator is reached
++ addi $r1, $r1, #-1 ! Decrease n by 1
++ bnez $r1, loop ! Continue looping if n != 0
++ addi $r0, $r0, #1 ! Return n+1 if too long
++exit:
++ sub $r0, $r0, $p0 ! Get the counted length
++ ret
++
++ .section .fixup,"ax"
++ .align 0
++9001: move $r0, #0 ! Return 0 on exception
++ ret
++ .previous
++
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/strrchr.S linux-3.4.110/arch/nds32/lib/strrchr.S
+--- linux-3.4.110.orig/arch/nds32/lib/strrchr.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/strrchr.S 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,37 @@
++/*
++ * linux/arch/nds32/lib/strrchr.S
++ *
++ * Copyright (C) 1995-2000 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * ASM optimised string functions
++ */
++#include <linux/linkage.h>
++#include <asm/assembler.h>
++
++ .text
++/*
++ * Prototype: char *strrchr(const char *s, int c);
++ * Purpose : Returns a pointer to the last occurrence of the character c
++ * in the string s. Here "character" means "byte" - these functions
++ * do not work with wide or multi-byte characters.
++ */
++ .align 4
++ENTRY(strrchr)
++ move $r5, #0
++ beqz $r0, exit
++ andi $r1, $r1, #0xff ! Wipe out useless bits
++loop:
++ lbi $p0, [$r0] ! Load the next byte
++ xor $p1, $p0, $r1 ! Test if the byte == c
++ cmovz $r5, $r0, $p1 ! Save the current position
++ addi $r0, $r0, #1 ! Move on to the next byte
++ bnez $p0, loop ! Continue if not NULL (EOS)
++exit:
++ move $r0, $r5
++ ret
++
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/uaccess.S linux-3.4.110/arch/nds32/lib/uaccess.S
+--- linux-3.4.110.orig/arch/nds32/lib/uaccess.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/uaccess.S 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,159 @@
++/*
++ * linux/arch/nds32/lib/uaccess.S
++ *
++ * Copyright (C) 1995, 1996,1997,1998 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Routines to block copy data to/from user memory
++ * These are highly optimised both for the 4k page size
++ * and for various alignments.
++ */
++#include <linux/linkage.h>
++#include <asm/assembler.h>
++#include <asm/errno.h>
++
++ .text
++
++//#define PAGE_SHIFT 12
++
++/* Prototype: int __arch_copy_to_user(void *to, const char *from, size_t n)
++ * Purpose : copy a block to user memory from kernel memory
++ * Params : to - user memory
++ * : from - kernel memory
++ * : n - number of bytes to copy
++ * Returns : Number of bytes NOT copied.
++ */
++
++ENTRY(__arch_copy_to_user)
++ push $r0
++ push $r2
++ beqz $r2, ctu_exit
++ srli $p0, $r2, #2 ! $p0 = number of word to clear
++ andi $r2, $r2, #3 ! Bytes less than a word to copy
++ beqz $p0, byte_ctu ! Only less than a word to copy
++word_ctu:
++ lmw.bim $p1, [$r1], $p1 ! Load the next word
++USER( smw.bim,$p1, [$r0], $p1) ! Store the next word
++ addi $p0, $p0, #-1 ! Decrease word count
++ bnez $p0, word_ctu ! Continue looping to copy all words
++ beqz $r2, ctu_exit ! No left bytes to copy
++byte_ctu:
++ lbi.bi $p1, [$r1], #1 ! Load the next byte
++USER( sbi.bi, $p1, [$r0], #1) ! Store the next byte
++ addi $r2, $r2, #-1 ! Decrease byte count
++ bnez $r2, byte_ctu ! Continue looping to clear all left bytes
++ctu_exit:
++ move $r0, $r2 ! Set return value
++ pop $r2
++ pop $r2 ! Pop saved $r0 to $r2 to not corrupt return value
++ ret
++
++ .section .fixup,"ax"
++ .align 0
++9001:
++ pop $p1 ! Original $r2, n
++ pop $p0 ! Original $r0, void *to
++ sub $r1, $r0, $p0 ! Bytes copied
++ sub $r2, $p1, $r1 ! Bytes left to copy
++ push $lp
++ move $r0, $p0
++ bal __memzero ! Clean up the memory
++ pop $lp
++ move $r0, $r2
++ ret
++
++ .previous
++
++/* Prototype: unsigned long __arch_copy_from_user(void *to,const void *from,unsigned long n);
++ * Purpose : copy a block from user memory to kernel memory
++ * Params : to - kernel memory
++ * : from - user memory
++ * : n - number of bytes to copy
++ * Returns : Number of bytes NOT copied.
++ */
++
++
++ENTRY(__arch_copy_from_user)
++ push $r1
++ push $r2
++ beqz $r2, cfu_exit
++ srli $p0, $r2, #2 ! $p0 = number of word to clear
++ andi $r2, $r2, #3 ! Bytes less than a word to copy
++ beqz $p0, byte_cfu ! Only less than a word to copy
++word_cfu:
++USER( lmw.bim,$p1, [$r1], $p1) ! Load the next word
++ smw.bim $p1, [$r0], $p1 ! Store the next word
++ addi $p0, $p0, #-1 ! Decrease word count
++ bnez $p0, word_cfu ! Continue looping to copy all words
++ beqz $r2, cfu_exit ! No left bytes to copy
++byte_cfu:
++USER( lbi.bi, $p1, [$r1], #1) ! Load the next byte
++ sbi.bi $p1, [$r0], #1 ! Store the next byte
++ addi $r2, $r2, #-1 ! Decrease byte count
++ bnez $r2, byte_cfu ! Continue looping to clear all left bytes
++cfu_exit:
++ move $r0, $r2 ! Set return value
++ pop $r2
++ pop $r1
++ ret
++
++ .section .fixup,"ax"
++ .align 0
++ /*
++ * We took an exception. $r0 contains a pointer to
++ * the byte not copied.
++ */
++9001:
++ pop $p1 ! Original $r2, n
++ pop $p0 ! Original $r0, void *to
++ sub $r1, $r1, $p0 ! Bytes copied
++ sub $r2, $p1, $r1 ! Bytes left to copy
++ push $lp
++ bal __memzero ! Clean up the memory
++ pop $lp
++ move $r0, $r2
++ ret
++ .previous
++
++/* Prototype: int __arch_clear_user(void *addr, size_t sz)
++ * Purpose : clear some user memory
++ * Params : addr - user memory address to clear
++ * : sz - number of bytes to clear
++ * Returns : number of bytes NOT cleared
++ */
++ .align 5
++ENTRY(__arch_clear_user)
++ pushm $r0, $r1
++ beqz $r1, clear_exit
++ xor $p1, $p1, $p1 ! Use $p1=0 to clear mem
++ srli $p0, $r1, #2 ! $p0 = number of word to clear
++ andi $r1, $r1, #3 ! Bytes less than a word to copy
++ beqz $p0, byte_clear ! Only less than a word to clear
++word_clear:
++USER( smw.bim,$p1, [$r0], $p1) ! Clear the word
++ addi $p0, $p0, #-1 ! Decrease word count
++ bnez $p0, word_clear ! Continue looping to clear all words
++ beqz $r1, clear_exit ! No left bytes to copy
++byte_clear:
++USER( sbi.bi, $p1, [$r0], #1) ! Clear the byte
++ addi $r1, $r1, #-1 ! Decrease byte count
++ bnez $r1, byte_clear ! Continue looping to clear all left bytes
++clear_exit:
++ move $r0, $r1 ! Set return value
++ pop $r1
++ pop $r1 ! Pop saved $r0 to $r1 to not corrupt return value
++ ret
++
++ .section .fixup,"ax"
++ .align 0
++9001:
++ popm $p0, $p1 ! $p0 = original $r0, *addr, $p1 = original $r1, n
++ sub $p0, $r0, $p0 ! Bytes copied
++ sub $r0, $p1, $p0 ! Bytes left to copy
++ ret
++ .previous
++
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/udivmod.c linux-3.4.110/arch/nds32/lib/udivmod.c
+--- linux-3.4.110.orig/arch/nds32/lib/udivmod.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/udivmod.c 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,12 @@
++extern unsigned long udivmodsi4(unsigned long num, unsigned long den,
++ int modwanted);
++
++long __udivsi3(long a, long b)
++{
++ return udivmodsi4(a, b, 0);
++}
++
++long __umodsi3(long a, long b)
++{
++ return udivmodsi4(a, b, 1);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/lib/udivmodsi4.c linux-3.4.110/arch/nds32/lib/udivmodsi4.c
+--- linux-3.4.110.orig/arch/nds32/lib/udivmodsi4.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/lib/udivmodsi4.c 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,21 @@
++unsigned long udivmodsi4(unsigned long num, unsigned long den, int modwanted)
++{
++ unsigned long bit = 1;
++ unsigned long res = 0;
++
++ while (den < num && bit && !(den & (1L << 31))) {
++ den <<= 1;
++ bit <<= 1;
++ }
++ while (bit) {
++ if (num >= den) {
++ num -= den;
++ res |= bit;
++ }
++ bit >>= 1;
++ den >>= 1;
++ }
++ if (modwanted)
++ return num;
++ return res;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/Makefile linux-3.4.110/arch/nds32/Makefile
+--- linux-3.4.110.orig/arch/nds32/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/Makefile 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,100 @@
++#
++# arch/nds32/Makefile
++#
++# This file is subject to the terms and conditions of the GNU General Public
++# License. See the file "COPYING" in the main directory of this archive
++# for more details.
++#
++# Copyright (C) 1995-2001 by Russell King
++
++LDFLAGS_vmlinux :=-nostdlib --no-undefined -X
++OBJCOPYFLAGS :=-O binary -R .note -R .note.gnu.build-id -R .comment -S
++GZFLAGS :=-9
++KBUILD_CFLAGS +=-pipe -mno-sched-prolog-epilog
++
++# Do not use arch/nds32/defconfig - it's always outdated.
++# Select a platform tht is kept up-to-date
++KBUILD_DEFCONFIG := orca_defconfig
++
++ifeq ($(CONFIG_FRAME_POINTER),y)
++KBUILD_CFLAGS +=-fno-omit-frame-pointer
++endif
++
++comma = ,
++
++# This selects which instruction set is used.
++# Note that GCC does not numerically define an architecture version
++# macro, but instead defines a whole series of macros which makes
++# testing for a specific architecture or later rather impossible.
++arch-y +=-D__nds32__
++gcc_ver :=$(shell $(CC) -E -dM -xc /dev/null | grep __VERSION__ | sed 's/\#define __VERSION__ //')
++ifeq ($(shell expr `echo $(gcc_ver)` \>= 4.9.2 ), 1)
++arch-y += \
++ $(shell $(CC) -E -dM -xc /dev/null | \
++ grep -o -m1 NDS32_EXT_FPU_SP | \
++ sed -e 's/NDS32_EXT_FPU_SP/-mno-ext-fpu-sp -mfloat-abi=soft/') \
++ $(shell $(CC) -E -dM -xc /dev/null | \
++ grep -o -m1 NDS32_EXT_FPU_DP | \
++ sed -e 's/NDS32_EXT_FPU_DP/-mno-ext-fpu-dp -mfloat-abi=soft/')
++tune-y =-D__OPTIMIZE__ -mcmodel=large -D__ARCH_WANT_SYS_WAITPID
++else
++$(shell echo $(__VERSION__))
++arch-y += $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_SP | \
++ sed -e 's/NDS32_EXT_FPU_SP/-mno-ext-fpu-sp/') \
++ $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_EXT_FPU_DP | \
++ sed -e 's/NDS32_EXT_FPU_DP/-mno-ext-fpu-dp/') \
++ $(shell $(CC) -E -dM -xc /dev/null | grep -o -m1 NDS32_ABI | \
++ sed -e 's/NDS32_ABI/-mabi=2/')
++tune-y =-D__OPTIMIZE__ -G0 -D__ARCH_WANT_SYS_WAITPID -D_GCC444
++endif
++
++# This is a workaround for FUNCTION_TRACER because v3push will push $fp, $gp and $lp.
++ifdef CONFIG_FUNCTION_TRACER
++arch-y += -mno-v3push
++endif
++# This selects how we optimise for the processor.
++# Need -Unds32 for gcc < 3.x
++CHECKFLAGS += -D__nds32__
++
++KBUILD_CFLAGS +=$(CFLAGS_ABI) $(arch-y) $(tune-y) -Unds32 -DSTRICT_MM_TYPECHECKS # for c-style checking for page.h
++KBUILD_AFLAGS +=$(AFLAGS_ABI) $(arch-y) $(tune-y)
++
++#Default value
++head-y := arch/nds32/kernel/head.o arch/nds32/kernel/init_task.o
++textaddr-y := 0xC000C000
++
++TEXTADDR := $(textaddr-y)
++
++export TEXTADDR DATAADDR GZFLAGS
++
++
++# If we have a machine-specific directory, then include it in the build.
++core-y += arch/nds32/kernel/ arch/nds32/mm/
++core-y += arch/nds32/platforms/
++core-$(CONFIG_FPU) += arch/nds32/math-emu/
++
++drivers-$(CONFIG_OPROFILE) += arch/nds32/oprofile/
++
++libs-y += arch/nds32/lib/
++
++boot := arch/nds32/boot
++
++.PHONY: FORCE
++
++Image: vmlinux
++ $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
++
++CLEAN_FILES += include/asm-nds32/constants.h*
++
++# We use MRPROPER_FILES and CLEAN_FILES now
++archclean:
++ $(Q)$(MAKE) $(clean)=$(boot)
++
++.PHONY: arch/nds32/kernel/asm-offsets.s
++arch/nds32/kernel/asm-offsets.s: arch/nds32/kernel/asm-offsets.c
++ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
++
++
++define archhelp
++ echo ' Image - kernel image (arch/$(ARCH)/boot/Image)'
++endef
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_add.c linux-3.4.110/arch/nds32/math-emu/dp_add.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_add.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_add.c 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,179 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y)
++{
++ COMPXDP;
++ COMPYDP;
++
++ EXPLODEXDP;
++ EXPLODEYDP;
++
++ CLEARCX;
++
++ FLUSHXDP;
++ FLUSHYDP;
++
++ switch (CLPAIR(xc, yc)) {
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_nanxcpt(ieee754dp_indef(), "add", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
++ return x;
++
++ /* Infinity handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
++ if (xs == ys)
++ return x;
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_xcpt(ieee754dp_indef(), "add", x, y);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
++ return x;
++
++ /* Zero handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
++ if (xs == ys)
++ return x;
++ else
++ return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
++ return x;
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
++ DPDNORMX;
++
++ /* FALL THROUGH */
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
++ DPDNORMY;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
++ DPDNORMX;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
++ break;
++ }
++ assert(xm & DP_HIDDEN_BIT);
++ assert(ym & DP_HIDDEN_BIT);
++
++ /* provide guard,round and stick bit space */
++ xm <<= 3;
++ ym <<= 3;
++
++ if (xe > ye) {
++ /* have to shift y fraction right to align
++ */
++ int s = xe - ye;
++ ym = XDPSRS(ym, s);
++ ye += s;
++ } else if (ye > xe) {
++ /* have to shift x fraction right to align
++ */
++ int s = ye - xe;
++ xm = XDPSRS(xm, s);
++ xe += s;
++ }
++ assert(xe == ye);
++ assert(xe <= DP_EMAX);
++
++ if (xs == ys) {
++ /* generate 28 bit result of adding two 27 bit numbers
++ * leaving result in xm,xs,xe
++ */
++ xm = xm + ym;
++ xe = xe;
++ xs = xs;
++
++ if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
++ xm = XDPSRS1(xm);
++ xe++;
++ }
++ } else {
++ if (xm >= ym) {
++ xm = xm - ym;
++ xe = xe;
++ xs = xs;
++ } else {
++ xm = ym - xm;
++ xe = xe;
++ xs = ys;
++ }
++ if (xm == 0)
++ return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD);
++
++ /* normalize to rounding precision */
++ while ((xm >> (DP_MBITS + 3)) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++
++ }
++ DPNORMRET2(xs, xe, xm, "add", x, y);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_cmp.c linux-3.4.110/arch/nds32/math-emu/dp_cmp.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_cmp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_cmp.c 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,66 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cmp, int sig)
++{
++ COMPXDP;
++ COMPYDP;
++
++ EXPLODEXDP;
++ EXPLODEYDP;
++ FLUSHXDP;
++ FLUSHYDP;
++ CLEARCX; /* Even clear inexact flag here */
++
++ if (ieee754dp_isnan(x) || ieee754dp_isnan(y)) {
++ if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
++ SETCX(IEEE754_INVALID_OPERATION);
++ if (cmp & IEEE754_CUN)
++ return 1;
++ if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
++ if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION))
++ return ieee754si_xcpt(0, "fcmpf", x);
++ }
++ return 0;
++ } else {
++ s64 vx = x.bits;
++ s64 vy = y.bits;
++
++ if (vx < 0)
++ vx = -vx ^ DP_SIGN_BIT;
++ if (vy < 0)
++ vy = -vy ^ DP_SIGN_BIT;
++
++ if (vx < vy)
++ return (cmp & IEEE754_CLT) != 0;
++ else if (vx == vy)
++ return (cmp & IEEE754_CEQ) != 0;
++ else
++ return (cmp & IEEE754_CGT) != 0;
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_div.c linux-3.4.110/arch/nds32/math-emu/dp_div.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_div.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_div.c 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,155 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y)
++{
++ COMPXDP;
++ COMPYDP;
++
++ EXPLODEXDP;
++ EXPLODEYDP;
++
++ CLEARCX;
++
++ FLUSHXDP;
++ FLUSHYDP;
++
++ switch (CLPAIR(xc, yc)) {
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_nanxcpt(ieee754dp_indef(), "div", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
++ return x;
++
++ /* Infinity handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
++ return ieee754dp_zero(xs ^ ys);
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
++ return ieee754dp_inf(xs ^ ys);
++
++ /* Zero handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_xcpt(ieee754dp_indef(), "div", x, y);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
++ SETCX(IEEE754_ZERO_DIVIDE);
++ return ieee754dp_xcpt(ieee754dp_inf(xs ^ ys), "div", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
++ return ieee754dp_zero(xs == ys ? 0 : 1);
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
++ DPDNORMX;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
++ DPDNORMY;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
++ DPDNORMX;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
++ break;
++ }
++ assert(xm & DP_HIDDEN_BIT);
++ assert(ym & DP_HIDDEN_BIT);
++
++ /* provide rounding space */
++ xm <<= 3;
++ ym <<= 3;
++
++ {
++ /* now the dirty work */
++
++ u64 rm = 0;
++ int re = xe - ye;
++ u64 bm;
++
++ for (bm = DP_MBIT(DP_MBITS + 2); bm; bm >>= 1) {
++ if (xm >= ym) {
++ xm -= ym;
++ rm |= bm;
++ if (xm == 0)
++ break;
++ }
++ xm <<= 1;
++ }
++ rm <<= 1;
++ if (xm)
++ rm |= 1; /* have remainder, set sticky */
++
++ assert(rm);
++
++ /* normalise rm to rounding precision ?
++ */
++ while ((rm >> (DP_MBITS + 3)) == 0) {
++ rm <<= 1;
++ re--;
++ }
++
++ DPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_fint.c linux-3.4.110/arch/nds32/math-emu/dp_fint.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_fint.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_fint.c 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,79 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++ieee754dp ieee754dp_fint(int x)
++{
++ u64 xm;
++ int xe;
++ int xs;
++
++ CLEARCX;
++
++ if (x == 0)
++ return ieee754dp_zero(0);
++ if (x == 1 || x == -1)
++ return ieee754dp_one(x < 0);
++ if (x == 10 || x == -10)
++ return ieee754dp_ten(x < 0);
++
++ xs = (x < 0);
++ if (xs) {
++ if (x == (1 << 31))
++ xm = ((unsigned)1 << 31); /* max neg can't be safely negated */
++ else
++ xm = -x;
++ } else {
++ xm = x;
++ }
++
++#if 1
++ /* normalize - result can never be inexact or overflow */
++ xe = DP_MBITS;
++ while ((xm >> DP_MBITS) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++ return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
++#else
++ /* normalize */
++ xe = DP_MBITS + 3;
++ while ((xm >> (DP_MBITS + 3)) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++ DPNORMRET1(xs, xe, xm, "fint", x);
++#endif
++}
++
++ieee754dp ieee754dp_funs(unsigned int u)
++{
++ if ((int)u < 0)
++ return ieee754dp_add(ieee754dp_1e31(),
++ ieee754dp_fint(u & ~(1 << 31)));
++ return ieee754dp_fint(u);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_flong.c linux-3.4.110/arch/nds32/math-emu/dp_flong.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_flong.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_flong.c 2016-04-07 10:20:50.958081643 +0200
+@@ -0,0 +1,77 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++ieee754dp ieee754dp_flong(s64 x)
++{
++ u64 xm;
++ int xe;
++ int xs;
++
++ CLEARCX;
++
++ if (x == 0)
++ return ieee754dp_zero(0);
++ if (x == 1 || x == -1)
++ return ieee754dp_one(x < 0);
++ if (x == 10 || x == -10)
++ return ieee754dp_ten(x < 0);
++
++ xs = (x < 0);
++ if (xs) {
++ if (x == (1ULL << 63))
++ xm = (1ULL << 63); /* max neg can't be safely negated */
++ else
++ xm = -x;
++ } else {
++ xm = x;
++ }
++
++ /* normalize */
++ xe = DP_MBITS + 3;
++ if (xm >> (DP_MBITS + 1 + 3)) {
++ /* shunt out overflow bits */
++ while (xm >> (DP_MBITS + 1 + 3)) {
++ XDPSRSX1();
++ }
++ } else {
++ /* normalize in grs extended double precision */
++ while ((xm >> (DP_MBITS + 3)) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++ }
++ DPNORMRET1(xs, xe, xm, "dp_flong", x);
++}
++
++ieee754dp ieee754dp_fulong(u64 u)
++{
++ if ((s64) u < 0)
++ return ieee754dp_add(ieee754dp_1e63(),
++ ieee754dp_flong(u & ~(1ULL << 63)));
++ return ieee754dp_flong(u);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_frexp.c linux-3.4.110/arch/nds32/math-emu/dp_frexp.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_frexp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_frexp.c 2016-04-07 10:20:50.974082262 +0200
+@@ -0,0 +1,52 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++/* close to ieeep754dp_logb
++*/
++ieee754dp ieee754dp_frexp(ieee754dp x, int *eptr)
++{
++ COMPXDP;
++ CLEARCX;
++ EXPLODEXDP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_INF:
++ case IEEE754_CLASS_ZERO:
++ *eptr = 0;
++ return x;
++ case IEEE754_CLASS_DNORM:
++ DPDNORMX;
++ break;
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ *eptr = xe + 1;
++ return builddp(xs, -1 + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_fsp.c linux-3.4.110/arch/nds32/math-emu/dp_fsp.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_fsp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_fsp.c 2016-04-07 10:20:50.974082262 +0200
+@@ -0,0 +1,71 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++ieee754dp ieee754dp_fsp(ieee754sp x)
++{
++ COMPXSP;
++
++ EXPLODEXSP;
++
++ CLEARCX;
++
++ FLUSHXSP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_nanxcpt(ieee754dp_indef(), "fsp");
++ case IEEE754_CLASS_QNAN:
++ return ieee754dp_nanxcpt(builddp(xs,
++ DP_EMAX + 1 + DP_EBIAS,
++ ((u64) xm
++ << (DP_MBITS -
++ SP_MBITS))), "fsp", x);
++ case IEEE754_CLASS_INF:
++ return ieee754dp_inf(xs);
++ case IEEE754_CLASS_ZERO:
++ return ieee754dp_zero(xs);
++ case IEEE754_CLASS_DNORM:
++ /* normalize */
++ while ((xm >> SP_MBITS) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++ break;
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++
++ /* CANT possibly overflow,underflow, or need rounding
++ */
++
++ /* drop the hidden bit */
++ xm &= ~SP_HIDDEN_BIT;
++
++ return builddp(xs, xe + DP_EBIAS, (u64) xm << (DP_MBITS - SP_MBITS));
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_logb.c linux-3.4.110/arch/nds32/math-emu/dp_logb.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_logb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_logb.c 2016-04-07 10:20:50.974082262 +0200
+@@ -0,0 +1,53 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++ieee754dp ieee754dp_logb(ieee754dp x)
++{
++ COMPXDP;
++
++ CLEARCX;
++
++ EXPLODEXDP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ return ieee754dp_nanxcpt(x, "logb", x);
++ case IEEE754_CLASS_QNAN:
++ return x;
++ case IEEE754_CLASS_INF:
++ return ieee754dp_inf(0);
++ case IEEE754_CLASS_ZERO:
++ return ieee754dp_inf(1);
++ case IEEE754_CLASS_DNORM:
++ DPDNORMX;
++ break;
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ return ieee754dp_fint(xe);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_modf.c linux-3.4.110/arch/nds32/math-emu/dp_modf.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_modf.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_modf.c 2016-04-07 10:20:50.974082262 +0200
+@@ -0,0 +1,79 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++/* modf function is always exact for a finite number
++*/
++ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip)
++{
++ COMPXDP;
++
++ CLEARCX;
++
++ EXPLODEXDP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_INF:
++ case IEEE754_CLASS_ZERO:
++ *ip = x;
++ return x;
++ case IEEE754_CLASS_DNORM:
++ /* far to small */
++ *ip = ieee754dp_zero(xs);
++ return x;
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ if (xe < 0) {
++ *ip = ieee754dp_zero(xs);
++ return x;
++ }
++ if (xe >= DP_MBITS) {
++ *ip = x;
++ return ieee754dp_zero(xs);
++ }
++ /* generate ipart mantissa by clearing bottom bits
++ */
++ *ip = builddp(xs, xe + DP_EBIAS,
++ ((xm >> (DP_MBITS - xe)) << (DP_MBITS - xe)) &
++ ~DP_HIDDEN_BIT);
++
++ /* generate fpart mantissa by clearing top bits
++ * and normalizing (must be able to normalize)
++ */
++ xm = (xm << (64 - (DP_MBITS - xe))) >> (64 - (DP_MBITS - xe));
++ if (xm == 0)
++ return ieee754dp_zero(xs);
++
++ while ((xm >> DP_MBITS) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++ return builddp(xs, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_mul.c linux-3.4.110/arch/nds32/math-emu/dp_mul.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_mul.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_mul.c 2016-04-07 10:20:50.974082262 +0200
+@@ -0,0 +1,170 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y)
++{
++ COMPXDP;
++ COMPYDP;
++
++ EXPLODEXDP;
++ EXPLODEYDP;
++
++ CLEARCX;
++
++ FLUSHXDP;
++ FLUSHYDP;
++
++ switch (CLPAIR(xc, yc)) {
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_nanxcpt(ieee754dp_indef(), "mul", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
++ return x;
++
++ /* Infinity handling */
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_xcpt(ieee754dp_indef(), "mul", x, y);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
++ return ieee754dp_inf(xs ^ ys);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
++ return ieee754dp_zero(xs ^ ys);
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
++ DPDNORMX;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
++ DPDNORMY;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
++ DPDNORMX;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
++ break;
++ }
++ /* rm = xm * ym, re = xe+ye basicly */
++ assert(xm & DP_HIDDEN_BIT);
++ assert(ym & DP_HIDDEN_BIT);
++ {
++ int re = xe + ye;
++ int rs = xs ^ ys;
++ u64 rm;
++
++ /* shunt to top of word */
++ xm <<= 64 - (DP_MBITS + 1);
++ ym <<= 64 - (DP_MBITS + 1);
++
++ /* multiply 32bits xm,ym to give high 32bits rm with stickness
++ */
++
++ /* 32 * 32 => 64 */
++#define DPXMULT(x, y) ((u64)(x) * (u64)y)
++
++ {
++ unsigned lxm = xm;
++ unsigned hxm = xm >> 32;
++ unsigned lym = ym;
++ unsigned hym = ym >> 32;
++ u64 lrm;
++ u64 hrm;
++
++ lrm = DPXMULT(lxm, lym);
++ hrm = DPXMULT(hxm, hym);
++
++ {
++ u64 t = DPXMULT(lxm, hym);
++ {
++ u64 at = lrm + (t << 32);
++ hrm += at < lrm;
++ lrm = at;
++ }
++ hrm = hrm + (t >> 32);
++ }
++
++ {
++ u64 t = DPXMULT(hxm, lym);
++ {
++ u64 at = lrm + (t << 32);
++ hrm += at < lrm;
++ lrm = at;
++ }
++ hrm = hrm + (t >> 32);
++ }
++ rm = hrm | (lrm != 0);
++ }
++
++ /*
++ * sticky shift down to normal rounding precision
++ */
++ if ((s64) rm < 0) {
++ rm = (rm >> (64 - (DP_MBITS + 1 + 3))) |
++ ((rm << (DP_MBITS + 1 + 3)) != 0);
++ re++;
++ } else {
++ rm = (rm >> (64 - (DP_MBITS + 1 + 3 + 1))) |
++ ((rm << (DP_MBITS + 1 + 3 + 1)) != 0);
++ }
++ assert(rm & (DP_HIDDEN_BIT << 3));
++ DPNORMRET2(rs, re, rm, "mul", x, y);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_scalb.c linux-3.4.110/arch/nds32/math-emu/dp_scalb.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_scalb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_scalb.c 2016-04-07 10:20:50.974082262 +0200
+@@ -0,0 +1,56 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++ieee754dp ieee754dp_scalb(ieee754dp x, int n)
++{
++ COMPXDP;
++
++ CLEARCX;
++
++ EXPLODEXDP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ return ieee754dp_nanxcpt(x, "scalb", x, n);
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_INF:
++ case IEEE754_CLASS_ZERO:
++ return x;
++ case IEEE754_CLASS_DNORM:
++ DPDNORMX;
++ break;
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ DPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
++}
++
++ieee754dp ieee754dp_ldexp(ieee754dp x, int n)
++{
++ return ieee754dp_scalb(x, n);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_simple.c linux-3.4.110/arch/nds32/math-emu/dp_simple.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_simple.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_simple.c 2016-04-07 10:20:50.974082262 +0200
+@@ -0,0 +1,87 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++int ieee754dp_finite(ieee754dp x)
++{
++ return DPBEXP(x) != DP_EMAX + 1 + DP_EBIAS;
++}
++
++ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y)
++{
++ CLEARCX;
++ DPSIGN(x) = DPSIGN(y);
++ return x;
++}
++
++ieee754dp ieee754dp_neg(ieee754dp x)
++{
++ COMPXDP;
++
++ EXPLODEXDP;
++ CLEARCX;
++ FLUSHXDP;
++
++ /*
++ * Invert the sign ALWAYS to prevent an endless recursion on
++ * pow() in libc.
++ */
++ /* quick fix up */
++ DPSIGN(x) ^= 1;
++
++ if (xc == IEEE754_CLASS_SNAN) {
++ ieee754dp y = ieee754dp_indef();
++ SETCX(IEEE754_INVALID_OPERATION);
++ DPSIGN(y) = DPSIGN(x);
++ return ieee754dp_nanxcpt(y, "neg");
++ }
++
++ if (ieee754dp_isnan(x)) /* but not infinity */
++ return ieee754dp_nanxcpt(x, "neg", x);
++ return x;
++}
++
++ieee754dp ieee754dp_abs(ieee754dp x)
++{
++ COMPXDP;
++
++ EXPLODEXDP;
++ CLEARCX;
++ FLUSHXDP;
++
++ if (xc == IEEE754_CLASS_SNAN) {
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_nanxcpt(ieee754dp_indef(), "neg");
++ }
++
++ if (ieee754dp_isnan(x)) /* but not infinity */
++ return ieee754dp_nanxcpt(x, "abs", x);
++
++ /* quick fix up */
++ DPSIGN(x) = 0;
++ return x;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_sqrt.c linux-3.4.110/arch/nds32/math-emu/dp_sqrt.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_sqrt.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_sqrt.c 2016-04-07 10:20:50.974082262 +0200
+@@ -0,0 +1,164 @@
++/* IEEE754 floating point arithmetic
++ * double precision square root
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++static const unsigned table[] = {
++ 0, 1204, 3062, 5746, 9193, 13348, 18162, 23592,
++ 29598, 36145, 43202, 50740, 58733, 67158, 75992,
++ 85215, 83599, 71378, 60428, 50647, 41945, 34246,
++ 27478, 21581, 16499, 12183, 8588, 5674, 3403,
++ 1742, 661, 130
++};
++
++ieee754dp ieee754dp_sqrt(ieee754dp x)
++{
++ struct _ieee754_csr oldcsr;
++ ieee754dp y, z, t;
++ unsigned scalx, yh;
++ COMPXDP;
++
++ EXPLODEXDP;
++ CLEARCX;
++ FLUSHXDP;
++
++ /* x == INF or NAN? */
++ switch (xc) {
++ case IEEE754_CLASS_QNAN:
++ /* sqrt(Nan) = Nan */
++ return ieee754dp_nanxcpt(x, "sqrt");
++ case IEEE754_CLASS_SNAN:
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
++ case IEEE754_CLASS_ZERO:
++ /* sqrt(0) = 0 */
++ return x;
++ case IEEE754_CLASS_INF:
++ if (xs) {
++ /* sqrt(-Inf) = Nan */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
++ }
++ /* sqrt(+Inf) = Inf */
++ return x;
++ case IEEE754_CLASS_DNORM:
++ DPDNORMX;
++ /* fall through */
++ case IEEE754_CLASS_NORM:
++ if (xs) {
++ /* sqrt(-x) = Nan */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_nanxcpt(ieee754dp_indef(), "sqrt");
++ }
++ break;
++ }
++
++ /* save old csr; switch off INX enable & flag; set RN rounding */
++ oldcsr = ieee754_csr;
++ ieee754_csr.mx &= ~IEEE754_INEXACT;
++ ieee754_csr.sx &= ~IEEE754_INEXACT;
++ ieee754_csr.rm = IEEE754_RN;
++
++ /* adjust exponent to prevent overflow */
++ scalx = 0;
++ if (xe > 512) { /* x > 2**-512? */
++ xe -= 512; /* x = x / 2**512 */
++ scalx += 256;
++ } else if (xe < -512) { /* x < 2**-512? */
++ xe += 512; /* x = x * 2**512 */
++ scalx -= 256;
++ }
++
++ y = x = builddp(0, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
++
++ /* magic initial approximation to almost 8 sig. bits */
++ yh = y.bits >> 32;
++ yh = (yh >> 1) + 0x1ff80000;
++ yh = yh - table[(yh >> 15) & 31];
++ y.bits = ((u64) yh << 32) | (y.bits & 0xffffffff);
++
++ /* Heron's rule once with correction to improve to ~18 sig. bits */
++ /* t=x/y; y=y+t; py[n0]=py[n0]-0x00100006; py[n1]=0; */
++ t = ieee754dp_div(x, y);
++ y = ieee754dp_add(y, t);
++ y.bits -= 0x0010000600000000LL;
++ y.bits &= 0xffffffff00000000LL;
++
++ /* triple to almost 56 sig. bits: y ~= sqrt(x) to within 1 ulp */
++ /* t=y*y; z=t; pt[n0]+=0x00100000; t+=z; z=(x-z)*y; */
++ z = t = ieee754dp_mul(y, y);
++ t.parts.bexp += 0x001;
++ t = ieee754dp_add(t, z);
++ z = ieee754dp_mul(ieee754dp_sub(x, z), y);
++
++ /* t=z/(t+x) ; pt[n0]+=0x00100000; y+=t; */
++ t = ieee754dp_div(z, ieee754dp_add(t, x));
++ t.parts.bexp += 0x001;
++ y = ieee754dp_add(y, t);
++
++ /* twiddle last bit to force y correctly rounded */
++
++ /* set RZ, clear INEX flag */
++ ieee754_csr.rm = IEEE754_RZ;
++ ieee754_csr.sx &= ~IEEE754_INEXACT;
++
++ /* t=x/y; ...chopped quotient, possibly inexact */
++ t = ieee754dp_div(x, y);
++
++ if (ieee754_csr.sx & IEEE754_INEXACT || t.bits != y.bits) {
++
++ if (!(ieee754_csr.sx & IEEE754_INEXACT))
++ /* t = t-ulp */
++ t.bits -= 1;
++
++ /* add inexact to result status */
++ oldcsr.cx |= IEEE754_INEXACT;
++ oldcsr.sx |= IEEE754_INEXACT;
++
++ switch (oldcsr.rm) {
++ case IEEE754_RP:
++ y.bits += 1;
++ /* drop through */
++ case IEEE754_RN:
++ t.bits += 1;
++ break;
++ }
++
++ /* y=y+t; ...chopped sum */
++ y = ieee754dp_add(y, t);
++
++ /* adjust scalx for correctly rounded sqrt(x) */
++ scalx -= 1;
++ }
++
++ /* py[n0]=py[n0]+scalx; ...scale back y */
++ y.parts.bexp += scalx;
++
++ /* restore rounding mode, possibly set inexact */
++ ieee754_csr = oldcsr;
++
++ return y;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_sub.c linux-3.4.110/arch/nds32/math-emu/dp_sub.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_sub.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_sub.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,187 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y)
++{
++ COMPXDP;
++ COMPYDP;
++
++ EXPLODEXDP;
++ EXPLODEYDP;
++
++ CLEARCX;
++
++ FLUSHXDP;
++ FLUSHYDP;
++
++ switch (CLPAIR(xc, yc)) {
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_nanxcpt(ieee754dp_indef(), "sub", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
++ return x;
++
++ /* Infinity handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
++ if (xs != ys)
++ return x;
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754dp_xcpt(ieee754dp_indef(), "sub", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
++ return ieee754dp_inf(ys ^ 1);
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
++ return x;
++
++ /* Zero handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
++ if (xs != ys)
++ return x;
++ else
++ return ieee754dp_zero(ieee754_csr.rm == IEEE754_RD);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
++ return x;
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
++ /* quick fix up */
++ DPSIGN(y) ^= 1;
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
++ DPDNORMX;
++ /* FAAL THOROUGH */
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
++ /* normalize ym,ye */
++ DPDNORMY;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
++ /* normalize xm,xe */
++ DPDNORMX;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
++ break;
++ }
++ /* flip sign of y and handle as add */
++ ys ^= 1;
++
++ assert(xm & DP_HIDDEN_BIT);
++ assert(ym & DP_HIDDEN_BIT);
++
++ /* provide guard,round and stick bit dpace */
++ xm <<= 3;
++ ym <<= 3;
++
++ if (xe > ye) {
++ /* have to shift y fraction right to align
++ */
++ int s = xe - ye;
++ ym = XDPSRS(ym, s);
++ ye += s;
++ } else if (ye > xe) {
++ /* have to shift x fraction right to align
++ */
++ int s = ye - xe;
++ xm = XDPSRS(xm, s);
++ xe += s;
++ }
++ assert(xe == ye);
++ assert(xe <= DP_EMAX);
++
++ if (xs == ys) {
++ /* generate 28 bit result of adding two 27 bit numbers
++ */
++ xm = xm + ym;
++ xe = xe;
++ xs = xs;
++
++ if (xm >> (DP_MBITS + 1 + 3)) { /* carry out */
++ xm = XDPSRS1(xm); /* shift preserving sticky */
++ xe++;
++ }
++ } else {
++ if (xm >= ym) {
++ xm = xm - ym;
++ xe = xe;
++ xs = xs;
++ } else {
++ xm = ym - xm;
++ xe = xe;
++ xs = ys;
++ }
++ if (xm == 0) {
++ if (ieee754_csr.rm == IEEE754_RD)
++ return ieee754dp_zero(1); /* round negative inf. => sign = -1 */
++ else
++ return ieee754dp_zero(0); /* other round modes => sign = 1 */
++ }
++
++ /* normalize to rounding precision
++ */
++ while ((xm >> (DP_MBITS + 3)) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++ }
++ DPNORMRET2(xs, xe, xm, "sub", x, y);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_tint.c linux-3.4.110/arch/nds32/math-emu/dp_tint.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_tint.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_tint.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,121 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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/kernel.h>
++#include "ieee754dp.h"
++
++int ieee754dp_tint(ieee754dp x)
++{
++ COMPXDP;
++
++ CLEARCX;
++
++ EXPLODEXDP;
++ FLUSHXDP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_INF:
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
++ case IEEE754_CLASS_ZERO:
++ return 0;
++ case IEEE754_CLASS_DNORM:
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ if (xe > 31) {
++ /* Set invalid. We will only use overflow for floating
++ point overflow */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
++ }
++ /* oh gawd */
++ if (xe > DP_MBITS) {
++ xm <<= xe - DP_MBITS;
++ } else if (xe < DP_MBITS) {
++ u64 residue;
++ int round;
++ int sticky;
++ int odd;
++
++ if (xe < -1) {
++ residue = xm;
++ round = 0;
++ sticky = residue != 0;
++ xm = 0;
++ } else {
++ residue = xm << (64 - DP_MBITS + xe);
++ round = (residue >> 63) != 0;
++ sticky = (residue << 1) != 0;
++ xm >>= DP_MBITS - xe;
++ }
++ /* Note: At this point upper 32 bits of xm are guaranteed
++ to be zero */
++ odd = (xm & 0x1) != 0x0;
++ switch (ieee754_csr.rm) {
++ case IEEE754_RN:
++ if (round && (sticky || odd))
++ xm++;
++ break;
++ case IEEE754_RZ:
++ break;
++ case IEEE754_RU: /* toward +Infinity */
++ if ((round || sticky) && !xs)
++ xm++;
++ break;
++ case IEEE754_RD: /* toward -Infinity */
++ if ((round || sticky) && xs)
++ xm++;
++ break;
++ }
++ /* look for valid corner case 0x80000000 */
++ if ((xm >> 31) != 0 && (xs == 0 || xm != 0x80000000)) {
++ /* This can happen after rounding */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754si_xcpt(ieee754si_indef(), "dp_tint", x);
++ }
++ if (round || sticky)
++ SETCX(IEEE754_INEXACT);
++ }
++ if (xs)
++ return -xm;
++ else
++ return xm;
++}
++
++unsigned int ieee754dp_tuns(ieee754dp x)
++{
++ ieee754dp hb = ieee754dp_1e31();
++
++ /* what if x < 0 ?? */
++ if (ieee754dp_lt(x, hb))
++ return (unsigned)ieee754dp_tint(x);
++
++ return (unsigned)ieee754dp_tint(ieee754dp_sub(x, hb)) |
++ ((unsigned)1 << 31);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/dp_tlong.c linux-3.4.110/arch/nds32/math-emu/dp_tlong.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/dp_tlong.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/dp_tlong.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,123 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++s64 ieee754dp_tlong(ieee754dp x)
++{
++ COMPXDP;
++
++ CLEARCX;
++
++ EXPLODEXDP;
++ FLUSHXDP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_INF:
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
++ case IEEE754_CLASS_ZERO:
++ return 0;
++ case IEEE754_CLASS_DNORM:
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ if (xe >= 63) {
++ /* look for valid corner case */
++ if (xe == 63 && xs && xm == DP_HIDDEN_BIT)
++ return -0x8000000000000000LL;
++ /* Set invalid. We will only use overflow for floating
++ point overflow */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
++ }
++ /* oh gawd */
++ if (xe > DP_MBITS) {
++ xm <<= xe - DP_MBITS;
++ } else if (xe < DP_MBITS) {
++ u64 residue;
++ int round;
++ int sticky;
++ int odd;
++
++ if (xe < -1) {
++ residue = xm;
++ round = 0;
++ sticky = residue != 0;
++ xm = 0;
++ } else {
++ /* Shifting a u64 64 times does not work,
++ * so we do it in two steps. Be aware that xe
++ * may be -1 */
++ residue = xm << (xe + 1);
++ residue <<= 63 - DP_MBITS;
++ round = (residue >> 63) != 0;
++ sticky = (residue << 1) != 0;
++ xm >>= DP_MBITS - xe;
++ }
++ odd = (xm & 0x1) != 0x0;
++ switch (ieee754_csr.rm) {
++ case IEEE754_RN:
++ if (round && (sticky || odd))
++ xm++;
++ break;
++ case IEEE754_RZ:
++ break;
++ case IEEE754_RU: /* toward +Infinity */
++ if ((round || sticky) && !xs)
++ xm++;
++ break;
++ case IEEE754_RD: /* toward -Infinity */
++ if ((round || sticky) && xs)
++ xm++;
++ break;
++ }
++ if ((xm >> 63) != 0) {
++ /* This can happen after rounding */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754di_xcpt(ieee754di_indef(), "dp_tlong", x);
++ }
++ if (round || sticky)
++ SETCX(IEEE754_INEXACT);
++ }
++ if (xs)
++ return -xm;
++ else
++ return xm;
++}
++
++u64 ieee754dp_tulong(ieee754dp x)
++{
++ ieee754dp hb = ieee754dp_1e63();
++
++ /* what if x < 0 ?? */
++ if (ieee754dp_lt(x, hb))
++ return (u64) ieee754dp_tlong(x);
++
++ return (u64) ieee754dp_tlong(ieee754dp_sub(x, hb)) | (1ULL << 63);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/fpuemu.c linux-3.4.110/arch/nds32/math-emu/fpuemu.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/fpuemu.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/fpuemu.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,565 @@
++/*
++ * linux/arch/nds32/math-emu/fpuemu.c: a nds32 coprocessor (fpu) instruction emulator
++ *
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc.
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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.
++ *
++ * A complete emulator for MIPS coprocessor 1 instructions. This is
++ * required for #float(switch) or #float(trap), where it catches all
++ * COP1 instructions via the "CoProcessor Unusable" exception.
++ *
++ * More surprisingly it is also required for #float(ieee), to help out
++ * the hardware fpu at the boundaries of the IEEE-754 representation
++ * (denormalised values, infinities, underflow, etc). It is made
++ * quite nasty because emulation of some non-COP1 instructions is
++ * required, e.g. in branch delay slots.
++ *
++ * Note if you know that you won't have an fpu, then you'll get much
++ * better performance by compiling with -msoft-float!
++ */
++#include <linux/sched.h>
++#include <linux/debugfs.h>
++
++#include <asm/processor.h>
++#include <asm/ptrace.h>
++#include <asm/bitfield.h>
++#include <asm/uaccess.h>
++
++#include "ieee754.h"
++#include "insn.h"
++#include "fpu_emulator.h"
++
++/* Function which emulates a floating point instruction. */
++
++static int fpu_emu(struct pt_regs *, struct fpu_struct *, unsigned long);
++
++/* Further private data for which no space exists in fpu_struct */
++
++struct fpu_emulator_stats fpuemustats;
++
++/* rounding mode */
++#define FPU_FPCSR_RN 0x0 /* nearest */
++#define FPU_FPCSR_RU 0x1 /* towards +Infinity */
++#define FPU_FPCSR_RD 0x2 /* towards -Infinity */
++#define FPU_FPCSR_RZ 0x3 /* towards zero */
++
++/* Convert Mips rounding mode (0..3) to IEEE library modes. */
++static const unsigned char ieee_rm[4] = {
++ [FPU_FPCSR_RN] = IEEE754_RN,
++ [FPU_FPCSR_RU] = IEEE754_RU,
++ [FPU_FPCSR_RD] = IEEE754_RD,
++ [FPU_FPCSR_RZ] = IEEE754_RZ,
++};
++
++/* Convert IEEE library modes to NDS32 rounding mode (0..3). */
++static const unsigned char nds32_rm[4] = {
++ [IEEE754_RN] = FPU_FPCSR_RN,
++ [IEEE754_RZ] = FPU_FPCSR_RZ,
++ [IEEE754_RD] = FPU_FPCSR_RD,
++ [IEEE754_RU] = FPU_FPCSR_RU,
++};
++
++/*
++ * In the Linux kernel, we support selection of FPR format on the
++ * basis of the Status.FR bit. This does imply that, if a full 32
++ * FPRs are desired, there needs to be a flip-flop that can be written
++ * to one at that bit position. In any case, O32 MIPS ABI uses
++ * only the even FPRs (Status.FR = 0).
++ */
++
++#define CP0_STATUS_FR_SUPPORT
++
++#ifdef CP0_STATUS_FR_SUPPORT
++#define FR_BIT ST0_FR
++#else
++#define FR_BIT 0
++#endif
++
++#define SIFROMREG(si, x) ((si) = *((unsigned long *)ctx + x))
++#define SITOREG(si, x) (*((unsigned long *)ctx + x)= (si))
++
++#ifdef __NDS32_EL__
++#define DIFROMREG(di, x) ((di) = (unsigned long long)ptr[2*x] << 32 | (unsigned long long)ptr[2*x+1])
++#define DITOREG(di, x) ptr[2*x] = (di) >> 32; ptr[2*x+1] = (unsigned long)(di)
++#else
++#define DIFROMREG(di, x) ((di) = (unsigned long long)ptr[2*x+1] << 32 | (unsigned long long)ptr[2*x])
++#define DITOREG(di, x) ptr[2*x+1] = (di) >> 32; ptr[2*x] = (unsigned long)(di)
++#endif
++
++#define SPFROMREG(sp, x) SIFROMREG((sp).bits, x)
++#define SPTOREG(sp, x) SITOREG((sp).bits, x)
++#define DPFROMREG(dp, x) DIFROMREG((dp).bits, x)
++#define DPTOREG(dp, x) DITOREG((dp).bits, x)
++
++#define DEF3OP(name, p, f1, f2, f3) \
++static ieee754##p fpemu_##p##_##name(ieee754##p r, ieee754##p s, \
++ ieee754##p t) \
++{ \
++ struct _ieee754_csr ieee754_csr_save; \
++ s = f1(s, t); \
++ ieee754_csr_save = ieee754_csr; \
++ s = f2(s, r); \
++ ieee754_csr_save.cx |= ieee754_csr.cx; \
++ ieee754_csr_save.sx |= ieee754_csr.sx; \
++ s = f3(s); \
++ ieee754_csr.cx |= ieee754_csr_save.cx; \
++ ieee754_csr.sx |= ieee754_csr_save.sx; \
++ return s; \
++}
++
++DEF3OP(madd, sp, ieee754sp_mul, ieee754sp_add,);
++DEF3OP(msub, sp, ieee754sp_mul, ieee754sp_sub,);
++DEF3OP(nmadd, sp, ieee754sp_mul, ieee754sp_add, ieee754sp_neg);
++DEF3OP(nmsub, sp, ieee754sp_mul, ieee754sp_sub, ieee754sp_neg);
++DEF3OP(madd, dp, ieee754dp_mul, ieee754dp_add,);
++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);
++
++/*
++ * Emulate the floating point instruction w/ denorm input pointed at by IPC.
++ * According to spec, only FPU arithmetic, data format conversion, and compare instructions.
++ */
++
++static int fpuEmulate(struct pt_regs *regs, struct fpu_struct *fpu)
++{
++ unsigned long insn = 0, addr = regs->NDS32_ipc;
++ unsigned long emulpc, contpc;
++ unsigned char *pc = (void *)&insn;
++ char c;
++ int i = 0;
++
++ for (i = 0; i < 4; i++) {
++ if (__get_user(c, (unsigned char *)addr++))
++ return SIGBUS;
++ *pc++ = c;
++ }
++
++ insn = be32_to_cpu(insn);
++
++ emulpc = regs->NDS32_ipc;
++ contpc = regs->NDS32_ipc + 4;
++
++ fpuemustats.emulated++;
++ switch (NDS32Insn_OPCODE(insn)) {
++ case cop0_op:
++ switch (NDS32Insn_OPCODE_COP0(insn)) {
++
++ case fs1_op:
++ case fs2_op:
++ case fd1_op:
++ case fd2_op:
++ {
++ int sig;
++
++ /* a real fpu computation instruction */
++ if ((sig = fpu_emu(regs, fpu, insn)))
++ return sig;
++ }
++ break;
++
++ default:
++ return SIGILL;
++ }
++ break;
++ default:
++ return SIGILL;
++ }
++
++ /* we did it !! */
++ regs->NDS32_ipc = contpc;
++
++ return 0;
++}
++
++/*
++ * Conversion table from NDS32 fcmp TYP
++ * cond = ieee754dp_cmp(x,y,IEEE754_UN,sig);
++ */
++static const unsigned char cmptab[8] = {
++ IEEE754_CEQ,
++ IEEE754_CLT,
++ IEEE754_CLT | IEEE754_CEQ,
++ IEEE754_CUN,
++ 0,
++ 0,
++ 0,
++ 0,
++};
++
++/*
++ * Emulate a single FPU arithmetic instruction.
++ */
++static int fpu_emu(struct pt_regs *xcp, struct fpu_struct *ctx,
++ unsigned long insn)
++{
++ int rfmt; /* resulting format */
++ unsigned rfpcsr = 0; /* resulting csr */
++ unsigned long *ptr = (unsigned long *)ctx;
++ union {
++ ieee754dp d;
++ ieee754sp s;
++ int w;
++ } rv; /* resulting value */
++
++ fpuemustats.fpuops++;
++ switch (rfmt = NDS32Insn_OPCODE_COP0(insn)) {
++ case fs1_op:{
++ union {
++ ieee754sp(*t) (ieee754sp, ieee754sp, ieee754sp);
++ ieee754sp(*b) (ieee754sp, ieee754sp);
++ ieee754sp(*u) (ieee754sp);
++ } handler;
++
++ switch (NDS32Insn_OPCODE_BIT69(insn)) {
++ case fadds_op:
++ handler.b = ieee754sp_add;
++ goto scopbop;
++ case fsubs_op:
++ handler.b = ieee754sp_sub;
++ goto scopbop;
++ case fmadds_op:
++ handler.t = fpemu_sp_madd;
++ goto scoptop;
++ case fmsubs_op:
++ handler.t = fpemu_sp_msub;
++ goto scoptop;
++ case fnmadds_op:
++ handler.t = fpemu_sp_nmadd;
++ goto scoptop;
++ case fnmsubs_op:
++ handler.t = fpemu_sp_nmsub;
++ goto scoptop;
++ case fmuls_op:
++ handler.b = ieee754sp_mul;
++ goto scopbop;
++ case fdivs_op:
++ handler.b = ieee754sp_div;
++ goto scopbop;
++
++ /* binary op on handler */
++scoptop:
++ {
++ ieee754sp fd, fr, fs, ft;
++
++ SPFROMREG(fr,
++ NDS32Insn_OPCODE_Rt(insn));
++ SPFROMREG(fs,
++ NDS32Insn_OPCODE_Ra(insn));
++ SPFROMREG(ft,
++ NDS32Insn_OPCODE_Rb(insn));
++ fd = (*handler.t) (fr, fs, ft);
++ SPTOREG(fd, NDS32Insn_OPCODE_Rt(insn));
++ }
++scopbop:
++ {
++ ieee754sp fs, ft;
++
++ SPFROMREG(fs,
++ NDS32Insn_OPCODE_Ra(insn));
++ SPFROMREG(ft,
++ NDS32Insn_OPCODE_Rb(insn));
++
++ rv.s = (*handler.b) (fs, ft);
++ goto copcsr;
++ }
++scopuop:
++ {
++ ieee754sp fs;
++
++ SPFROMREG(fs,
++ NDS32Insn_OPCODE_Ra(insn));
++ rv.s = (*handler.u) (fs);
++ goto copcsr;
++ }
++copcsr:
++ if (ieee754_cxtest(IEEE754_INEXACT))
++ rfpcsr |= FPCSR_mskIEX;
++ if (ieee754_cxtest(IEEE754_UNDERFLOW))
++ rfpcsr |= FPCSR_mskUDF;
++ if (ieee754_cxtest(IEEE754_OVERFLOW))
++ rfpcsr |= FPCSR_mskOVF;
++ if (ieee754_cxtest(IEEE754_ZERO_DIVIDE))
++ rfpcsr |= FPCSR_mskDBZ;
++ if (ieee754_cxtest(IEEE754_INVALID_OPERATION))
++ rfpcsr |= FPCSR_mskIVO;
++ break;
++
++ case fs1_f2op_op:
++ switch (NDS32Insn_OPCODE_BIT1014(insn)) {
++ case fs2d_op:{
++ ieee754sp fs;
++ SPFROMREG(fs,
++ NDS32Insn_OPCODE_Ra
++ (insn));
++ rv.d = ieee754dp_fsp(fs);
++ rfmt = fd1_op;
++ goto copcsr;
++ }
++ case fsqrts_op:
++ handler.u = ieee754sp_sqrt;
++ goto scopuop;
++ case fabss_op:
++ handler.u = ieee754sp_abs;
++ goto scopuop;
++ default:
++ return SIGILL;
++ }
++ default:
++ return SIGILL;
++ }
++ break;
++ }
++
++ case fs2_op:
++ switch (NDS32Insn_OPCODE_BIT69(insn)) {
++ case fcmpeqs_op:
++ case fcmpeqs_e_op:
++ case fcmplts_op:
++ case fcmplts_e_op:
++ case fcmples_op:
++ case fcmples_e_op:
++ case fcmpuns_op:
++ case fcmpuns_e_op:
++ {
++ unsigned int cmpop =
++ NDS32Insn_OPCODE_BIT69(insn);
++ if (cmpop < 0x8) {
++ ieee754sp fs, ft;
++
++ SPFROMREG(fs,
++ NDS32Insn_OPCODE_Ra(insn));
++ SPFROMREG(ft,
++ NDS32Insn_OPCODE_Rb(insn));
++ rv.w =
++ ieee754sp_cmp(fs, ft,
++ cmptab[(cmpop >> 1) &
++ 0x7],
++ cmpop & 0x1);
++ if ((cmpop & 0x1)
++ &&
++ ieee754_cxtest
++ (IEEE754_INVALID_OPERATION))
++ rfpcsr = FPCSR_mskIVO;
++ else
++ goto copcsr;
++ } else
++ return SIGILL;
++ }
++ break;
++
++ default:
++ return SIGILL;
++ }
++ break;
++
++ case fd1_op:
++ {
++ union {
++ ieee754dp(*t) (ieee754dp, ieee754dp, ieee754dp);
++ ieee754dp(*b) (ieee754dp, ieee754dp);
++ ieee754dp(*u) (ieee754dp);
++ } handler;
++
++ switch (NDS32Insn_OPCODE_BIT69(insn)) {
++ case faddd_op:
++ handler.b = ieee754dp_add;
++ goto dcopbop;
++ case fsubd_op:
++ handler.b = ieee754dp_sub;
++ goto dcopbop;
++ case fmaddd_op:
++ handler.t = fpemu_dp_madd;
++ goto tdcoptop;
++ case fmsubd_op:
++ handler.t = fpemu_dp_msub;
++ goto tdcoptop;
++ case fnmaddd_op:
++ handler.t = fpemu_dp_nmadd;
++ goto tdcoptop;
++ case fnmsubd_op:
++ handler.t = fpemu_dp_nmsub;
++ goto tdcoptop;
++
++tdcoptop:
++ {
++ ieee754dp fd, fr, fs, ft;
++
++ DPFROMREG(fr,
++ NDS32Insn_OPCODE_Rt(insn));
++ DPFROMREG(fs,
++ NDS32Insn_OPCODE_Ra(insn));
++ DPFROMREG(ft,
++ NDS32Insn_OPCODE_Rb(insn));
++ fd = (*handler.t) (fr, fs, ft);
++ DPTOREG(fd, NDS32Insn_OPCODE_Rt(insn));
++ goto copcsr;
++ }
++
++ case fmuld_op:
++ handler.b = ieee754dp_mul;
++ goto dcopbop;
++ case fdivd_op:
++ handler.b = ieee754dp_div;
++ goto dcopbop;
++
++ /* binary op on handler */
++dcopbop: {
++ ieee754dp fs, ft;
++
++ DPFROMREG(fs,
++ NDS32Insn_OPCODE_Ra(insn));
++ DPFROMREG(ft,
++ NDS32Insn_OPCODE_Rb(insn));
++
++ rv.d = (*handler.b) (fs, ft);
++ goto copcsr;
++ }
++dcopuop: {
++ ieee754dp fs;
++
++ DPFROMREG(fs,
++ NDS32Insn_OPCODE_Ra(insn));
++ rv.d = (*handler.u) (fs);
++ goto copcsr;
++ }
++
++ case fd1_f2op_op:
++ switch (NDS32Insn_OPCODE_BIT1014(insn)) {
++ case fd2s_op:{
++ ieee754dp fs;
++
++ DPFROMREG(fs,
++ NDS32Insn_OPCODE_Ra
++ (insn));
++ rv.s = ieee754sp_fdp(fs);
++ rfmt = fd1_op;
++ goto copcsr;
++ }
++ case fsqrtd_op:
++ handler.u = ieee754dp_sqrt;
++ goto dcopuop;
++ case fabsd_op:
++ handler.u = ieee754dp_abs;
++ goto dcopuop;
++ default:
++ return SIGILL;
++ }
++ default:
++ return SIGILL;
++ }
++ break;
++ }
++
++ case fd2_op:
++ switch (NDS32Insn_OPCODE_BIT69(insn)) {
++ case fcmpeqd_op:
++ case fcmpeqd_e_op:
++ case fcmpltd_op:
++ case fcmpltd_e_op:
++ case fcmpled_op:
++ case fcmpled_e_op:
++ case fcmpund_op:
++ case fcmpund_e_op:
++ {
++ unsigned cmpop = NDS32Insn_OPCODE_BIT69(insn);
++ if (cmpop < 0x8) {
++ ieee754dp fs, ft;
++
++ DPFROMREG(fs,
++ NDS32Insn_OPCODE_Ra(insn));
++ DPFROMREG(ft,
++ NDS32Insn_OPCODE_Rb(insn));
++ rv.w =
++ ieee754dp_cmp(fs, ft,
++ cmptab[(cmpop >> 1) &
++ 0x7],
++ cmpop & 0x1);
++ rfmt = fs2_op;
++ if ((cmpop & 0x1)
++ &&
++ ieee754_cxtest
++ (IEEE754_INVALID_OPERATION))
++ rfpcsr = FPCSR_mskIVO;
++ else
++ goto copcsr;
++ } else
++ return SIGILL;
++ }
++ break;
++ default:
++ return SIGILL;
++ }
++ break;
++
++ default:
++ return SIGILL;
++ }
++
++ /*
++ * Now we can safely write the result back to the register file.
++ */
++ switch (rfmt) {
++ case fd1_op:
++ case fd2_op:
++ DPTOREG(rv.d, NDS32Insn_OPCODE_Rt(insn));
++ break;
++ case fs1_op:
++ case fs2_op:
++ SPTOREG(rv.s, NDS32Insn_OPCODE_Rt(insn));
++ 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->fpcsr = (ctx->fpcsr & ~FPCSR_mskALL) | rfpcsr;
++ if ((ctx->fpcsr << 5) & ctx->fpcsr & FPCSR_mskALLE) {
++ return SIGFPE;
++ }
++
++ return 0;
++}
++
++int do_fpu_denorm(struct pt_regs *regs, struct fpu_struct *fpu)
++{
++ int sig = 0;
++
++ /*
++ * The 'ieee754_csr' is an alias of
++ * fpcsr->RM. No need to copy fpcsr->RM to
++ * ieee754_csr. But ieee754_csr.rm is ieee
++ * library modes. (not NDS32 rounding mode)
++ */
++ /* convert to ieee library modes */
++ ieee754_csr.rm = ieee_rm[ieee754_csr.rm];
++ sig = fpuEmulate(regs, fpu);
++ /* revert to NDS32 rounding mode */
++ ieee754_csr.rm = nds32_rm[ieee754_csr.rm];
++
++ return sig;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/fpu_emulator.h linux-3.4.110/arch/nds32/math-emu/fpu_emulator.h
+--- linux-3.4.110.orig/arch/nds32/math-emu/fpu_emulator.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/fpu_emulator.h 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,36 @@
++/*
++ * 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.
++ *
++ * This program is distributed in the hope 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.
++ *
++ * Further private data for which no space exists in mips_fpu_struct.
++ * This should be subsumed into the mips_fpu_struct structure as
++ * defined in processor.h as soon as the absurd wired absolute assembler
++ * offsets become dynamic at compile time.
++ *
++ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
++ */
++#ifndef _ASM_FPU_EMULATOR_H
++#define _ASM_FPU_EMULATOR_H
++
++struct fpu_emulator_stats {
++ unsigned int emulated;
++ unsigned int loads;
++ unsigned int stores;
++ unsigned int fpuops;
++ unsigned int errors;
++};
++
++extern struct fpu_emulator_stats fpuemustats;
++
++#endif /* _ASM_FPU_EMULATOR_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754.c linux-3.4.110/arch/nds32/math-emu/ieee754.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/ieee754.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/ieee754.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,125 @@
++/* ieee754 floating point arithmetic
++ * single and double precision
++ *
++ * BUGS
++ * not much dp done
++ * doesn't generate IEEE754_INEXACT
++ *
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754int.h"
++#include "ieee754sp.h"
++#include "ieee754dp.h"
++
++#define DP_EBIAS 1023
++#define DP_EMIN (-1022)
++#define DP_EMAX 1023
++
++#define SP_EBIAS 127
++#define SP_EMIN (-126)
++#define SP_EMAX 127
++
++/* special constants
++*/
++
++#if (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN) || defined(__NDS32_EL__)
++#define SPSTR(s, b, m) {m, b, s}
++#define DPSTR(s, b, mh, ml) {ml, mh, b, s}
++#endif
++
++#ifdef __NDS32_EB__
++#define SPSTR(s, b, m) {s, b, m}
++#define DPSTR(s, b, mh, ml) {s, b, mh, ml}
++#endif
++
++const struct ieee754dp_konst __ieee754dp_spcvals[] = {
++ DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* + zero */
++ DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 0), /* - zero */
++ DPSTR(0, DP_EBIAS, 0, 0), /* + 1.0 */
++ DPSTR(1, DP_EBIAS, 0, 0), /* - 1.0 */
++ DPSTR(0, 3 + DP_EBIAS, 0x40000, 0), /* + 10.0 */
++ DPSTR(1, 3 + DP_EBIAS, 0x40000, 0), /* - 10.0 */
++ DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* + infinity */
++ DPSTR(1, DP_EMAX + 1 + DP_EBIAS, 0, 0), /* - infinity */
++ DPSTR(0, DP_EMAX + 1 + DP_EBIAS, 0x7FFFF, 0xFFFFFFFF), /* + indef quiet Nan */
++ DPSTR(0, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* + max */
++ DPSTR(1, DP_EMAX + DP_EBIAS, 0xFFFFF, 0xFFFFFFFF), /* - max */
++ DPSTR(0, DP_EMIN + DP_EBIAS, 0, 0), /* + min normal */
++ DPSTR(1, DP_EMIN + DP_EBIAS, 0, 0), /* - min normal */
++ DPSTR(0, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* + min denormal */
++ DPSTR(1, DP_EMIN - 1 + DP_EBIAS, 0, 1), /* - min denormal */
++ DPSTR(0, 31 + DP_EBIAS, 0, 0), /* + 1.0e31 */
++ DPSTR(0, 63 + DP_EBIAS, 0, 0), /* + 1.0e63 */
++};
++
++const struct ieee754sp_konst __ieee754sp_spcvals[] = {
++ SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 0), /* + zero */
++ SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 0), /* - zero */
++ SPSTR(0, SP_EBIAS, 0), /* + 1.0 */
++ SPSTR(1, SP_EBIAS, 0), /* - 1.0 */
++ SPSTR(0, 3 + SP_EBIAS, 0x200000), /* + 10.0 */
++ SPSTR(1, 3 + SP_EBIAS, 0x200000), /* - 10.0 */
++ SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0), /* + infinity */
++ SPSTR(1, SP_EMAX + 1 + SP_EBIAS, 0), /* - infinity */
++ SPSTR(0, SP_EMAX + 1 + SP_EBIAS, 0x3FFFFF), /* + indef quiet Nan */
++ SPSTR(0, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* + max normal */
++ SPSTR(1, SP_EMAX + SP_EBIAS, 0x7FFFFF), /* - max normal */
++ SPSTR(0, SP_EMIN + SP_EBIAS, 0), /* + min normal */
++ SPSTR(1, SP_EMIN + SP_EBIAS, 0), /* - min normal */
++ SPSTR(0, SP_EMIN - 1 + SP_EBIAS, 1), /* + min denormal */
++ SPSTR(1, SP_EMIN - 1 + SP_EBIAS, 1), /* - min denormal */
++ SPSTR(0, 31 + SP_EBIAS, 0), /* + 1.0e31 */
++ SPSTR(0, 63 + SP_EBIAS, 0), /* + 1.0e63 */
++};
++
++int ieee754si_xcpt(int r, const char *op, ...)
++{
++ struct ieee754xctx ax;
++
++ if (!TSTX())
++ return r;
++ ax.op = op;
++ ax.rt = IEEE754_RT_SI;
++ ax.rv.si = r;
++ va_start(ax.ap, op);
++ ieee754_xcpt(&ax);
++ va_end(ax.ap);
++ return ax.rv.si;
++}
++
++s64 ieee754di_xcpt(s64 r, const char *op, ...)
++{
++ struct ieee754xctx ax;
++
++ if (!TSTX())
++ return r;
++ ax.op = op;
++ ax.rt = IEEE754_RT_DI;
++ ax.rv.di = r;
++ va_start(ax.ap, op);
++ ieee754_xcpt(&ax);
++ va_end(ax.ap);
++ return ax.rv.di;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754d.c linux-3.4.110/arch/nds32/math-emu/ieee754d.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/ieee754d.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/ieee754d.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,134 @@
++/*
++ * Some debug functions
++ *
++ * MIPS floating point support
++ *
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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.
++ *
++ * Nov 7, 2000
++ * Modified to build and operate in Linux kernel environment.
++ *
++ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
++ */
++
++#include <linux/kernel.h>
++#include "ieee754.h"
++
++#define DP_EBIAS 1023
++#define DP_EMIN (-1022)
++#define DP_EMAX 1023
++#define DP_FBITS 52
++
++#define SP_EBIAS 127
++#define SP_EMIN (-126)
++#define SP_EMAX 127
++#define SP_FBITS 23
++
++#define DP_MBIT(x) ((u64)1 << (x))
++#define DP_HIDDEN_BIT DP_MBIT(DP_FBITS)
++#define DP_SIGN_BIT DP_MBIT(63)
++
++#define SP_MBIT(x) ((u32)1 << (x))
++#define SP_HIDDEN_BIT SP_MBIT(SP_FBITS)
++#define SP_SIGN_BIT SP_MBIT(31)
++
++#define SPSIGN(sp) (sp.parts.sign)
++#define SPBEXP(sp) (sp.parts.bexp)
++#define SPMANT(sp) (sp.parts.mant)
++
++#define DPSIGN(dp) (dp.parts.sign)
++#define DPBEXP(dp) (dp.parts.bexp)
++#define DPMANT(dp) (dp.parts.mant)
++
++ieee754dp ieee754dp_dump(char *m, ieee754dp x)
++{
++ int i;
++
++ printk("%s", m);
++ printk("<%08x,%08x>\n", (unsigned)(x.bits >> 32), (unsigned)x.bits);
++ printk("\t=");
++ switch (ieee754dp_class(x)) {
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_SNAN:
++ printk("Nan %c", DPSIGN(x) ? '-' : '+');
++ for (i = DP_FBITS - 1; i >= 0; i--)
++ printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
++ break;
++ case IEEE754_CLASS_INF:
++ printk("%cInfinity", DPSIGN(x) ? '-' : '+');
++ break;
++ case IEEE754_CLASS_ZERO:
++ printk("%cZero", DPSIGN(x) ? '-' : '+');
++ break;
++ case IEEE754_CLASS_DNORM:
++ printk("%c0.", DPSIGN(x) ? '-' : '+');
++ for (i = DP_FBITS - 1; i >= 0; i--)
++ printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
++ printk("e%d", DPBEXP(x) - DP_EBIAS);
++ break;
++ case IEEE754_CLASS_NORM:
++ printk("%c1.", DPSIGN(x) ? '-' : '+');
++ for (i = DP_FBITS - 1; i >= 0; i--)
++ printk("%c", DPMANT(x) & DP_MBIT(i) ? '1' : '0');
++ printk("e%d", DPBEXP(x) - DP_EBIAS);
++ break;
++ default:
++ printk("Illegal/Unknown IEEE754 value class");
++ }
++ printk("\n");
++ return x;
++}
++
++ieee754sp ieee754sp_dump(char *m, ieee754sp x)
++{
++ int i;
++
++ printk("%s=", m);
++ printk("<%08x>\n", (unsigned)x.bits);
++ printk("\t=");
++ switch (ieee754sp_class(x)) {
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_SNAN:
++ printk("Nan %c", SPSIGN(x) ? '-' : '+');
++ for (i = SP_FBITS - 1; i >= 0; i--)
++ printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
++ break;
++ case IEEE754_CLASS_INF:
++ printk("%cInfinity", SPSIGN(x) ? '-' : '+');
++ break;
++ case IEEE754_CLASS_ZERO:
++ printk("%cZero", SPSIGN(x) ? '-' : '+');
++ break;
++ case IEEE754_CLASS_DNORM:
++ printk("%c0.", SPSIGN(x) ? '-' : '+');
++ for (i = SP_FBITS - 1; i >= 0; i--)
++ printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
++ printk("e%d", SPBEXP(x) - SP_EBIAS);
++ break;
++ case IEEE754_CLASS_NORM:
++ printk("%c1.", SPSIGN(x) ? '-' : '+');
++ for (i = SP_FBITS - 1; i >= 0; i--)
++ printk("%c", SPMANT(x) & SP_MBIT(i) ? '1' : '0');
++ printk("e%d", SPBEXP(x) - SP_EBIAS);
++ break;
++ default:
++ printk("Illegal/Unknown IEEE754 value class");
++ }
++ printk("\n");
++ return x;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754dp.c linux-3.4.110/arch/nds32/math-emu/ieee754dp.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/ieee754dp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/ieee754dp.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,239 @@
++/* IEEE754 floating point arithmetic
++ * double precision: common utilities
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754dp.h"
++
++int ieee754dp_class(ieee754dp x)
++{
++ COMPXDP;
++ EXPLODEXDP;
++ return xc;
++}
++
++int ieee754dp_isnan(ieee754dp x)
++{
++ return ieee754dp_class(x) >= IEEE754_CLASS_SNAN;
++}
++
++int ieee754dp_issnan(ieee754dp x)
++{
++ assert(ieee754dp_isnan(x));
++ return ((DPMANT(x) & DP_MBIT(DP_MBITS - 1)) == DP_MBIT(DP_MBITS - 1));
++}
++
++ieee754dp ieee754dp_xcpt(ieee754dp r, const char *op, ...)
++{
++ struct ieee754xctx ax;
++ if (!TSTX())
++ return r;
++
++ ax.op = op;
++ ax.rt = IEEE754_RT_DP;
++ ax.rv.dp = r;
++ va_start(ax.ap, op);
++ ieee754_xcpt(&ax);
++ va_end(ax.ap);
++ return ax.rv.dp;
++}
++
++ieee754dp ieee754dp_nanxcpt(ieee754dp r, const char *op, ...)
++{
++ struct ieee754xctx ax;
++
++ assert(ieee754dp_isnan(r));
++
++ if (!ieee754dp_issnan(r)) /* QNAN does not cause invalid op !! */
++ return r;
++
++ if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) {
++ /* not enabled convert to a quiet NaN */
++ DPMANT(r) &= (~DP_MBIT(DP_MBITS - 1));
++ if (ieee754dp_isnan(r))
++ return r;
++ else
++ return ieee754dp_indef();
++ }
++
++ ax.op = op;
++ ax.rt = 0;
++ ax.rv.dp = r;
++ va_start(ax.ap, op);
++ ieee754_xcpt(&ax);
++ va_end(ax.ap);
++ return ax.rv.dp;
++}
++
++ieee754dp ieee754dp_bestnan(ieee754dp x, ieee754dp y)
++{
++ assert(ieee754dp_isnan(x));
++ assert(ieee754dp_isnan(y));
++
++ if (DPMANT(x) > DPMANT(y))
++ return x;
++ else
++ return y;
++}
++
++static u64 get_rounding(int sn, u64 xm)
++{
++ /* inexact must round of 3 bits
++ */
++ if (xm & (DP_MBIT(3) - 1)) {
++ switch (ieee754_csr.rm) {
++ case IEEE754_RZ:
++ break;
++ case IEEE754_RN:
++ xm += 0x3 + ((xm >> 3) & 1);
++ /* xm += (xm&0x8)?0x4:0x3 */
++ break;
++ case IEEE754_RU: /* toward +Infinity */
++ if (!sn) /* ?? */
++ xm += 0x8;
++ break;
++ case IEEE754_RD: /* toward -Infinity */
++ if (sn) /* ?? */
++ xm += 0x8;
++ break;
++ }
++ }
++ return xm;
++}
++
++/* generate a normal/denormal number with over,under handling
++ * sn is sign
++ * xe is an unbiased exponent
++ * xm is 3bit extended precision value.
++ */
++ieee754dp ieee754dp_format(int sn, int xe, u64 xm)
++{
++ assert(xm); /* we don't gen exact zeros (probably should) */
++
++ assert((xm >> (DP_MBITS + 1 + 3)) == 0); /* no execess */
++ assert(xm & (DP_HIDDEN_BIT << 3));
++
++ if (xe < DP_EMIN) {
++ /* strip lower bits */
++ int es = DP_EMIN - xe;
++
++ if (ieee754_csr.nod) {
++ SETCX(IEEE754_UNDERFLOW);
++ SETCX(IEEE754_INEXACT);
++
++ switch (ieee754_csr.rm) {
++ case IEEE754_RN:
++ return ieee754dp_zero(sn);
++ case IEEE754_RZ:
++ return ieee754dp_zero(sn);
++ case IEEE754_RU: /* toward +Infinity */
++ if (sn == 0)
++ return ieee754dp_min(0);
++ else
++ return ieee754dp_zero(1);
++ case IEEE754_RD: /* toward -Infinity */
++ if (sn == 0)
++ return ieee754dp_zero(0);
++ else
++ return ieee754dp_min(1);
++ }
++ }
++
++ if (xe == DP_EMIN - 1
++ && get_rounding(sn, xm) >> (DP_MBITS + 1 + 3)) {
++ /* Not tiny after rounding */
++ SETCX(IEEE754_INEXACT);
++ xm = get_rounding(sn, xm);
++ xm >>= 1;
++ /* Clear grs bits */
++ xm &= ~(DP_MBIT(3) - 1);
++ xe++;
++ } else {
++ /* sticky right shift es bits
++ */
++ xm = XDPSRS(xm, es);
++ xe += es;
++ assert((xm & (DP_HIDDEN_BIT << 3)) == 0);
++ assert(xe == DP_EMIN);
++ }
++ }
++ if (xm & (DP_MBIT(3) - 1)) {
++ SETCX(IEEE754_INEXACT);
++ if ((xm & (DP_HIDDEN_BIT << 3)) == 0) {
++ SETCX(IEEE754_UNDERFLOW);
++ }
++
++ /* inexact must round of 3 bits
++ */
++ xm = get_rounding(sn, xm);
++ /* adjust exponent for rounding add overflowing
++ */
++ if (xm >> (DP_MBITS + 3 + 1)) {
++ /* add causes mantissa overflow */
++ xm >>= 1;
++ xe++;
++ }
++ }
++ /* strip grs bits */
++ xm >>= 3;
++
++ assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */
++ assert(xe >= DP_EMIN);
++
++ if (xe > DP_EMAX) {
++ SETCX(IEEE754_OVERFLOW);
++ SETCX(IEEE754_INEXACT);
++ /* -O can be table indexed by (rm,sn) */
++ switch (ieee754_csr.rm) {
++ case IEEE754_RN:
++ return ieee754dp_inf(sn);
++ case IEEE754_RZ:
++ return ieee754dp_max(sn);
++ case IEEE754_RU: /* toward +Infinity */
++ if (sn == 0)
++ return ieee754dp_inf(0);
++ else
++ return ieee754dp_max(1);
++ case IEEE754_RD: /* toward -Infinity */
++ if (sn == 0)
++ return ieee754dp_max(0);
++ else
++ return ieee754dp_inf(1);
++ }
++ }
++ /* gen norm/denorm/zero */
++
++ if ((xm & DP_HIDDEN_BIT) == 0) {
++ /* we underflow (tiny/zero) */
++ assert(xe == DP_EMIN);
++ if (ieee754_csr.mx & IEEE754_UNDERFLOW)
++ SETCX(IEEE754_UNDERFLOW);
++ return builddp(sn, DP_EMIN - 1 + DP_EBIAS, xm);
++ } else {
++ assert((xm >> (DP_MBITS + 1)) == 0); /* no execess */
++ assert(xm & DP_HIDDEN_BIT);
++
++ return builddp(sn, xe + DP_EBIAS, xm & ~DP_HIDDEN_BIT);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754dp.h linux-3.4.110/arch/nds32/math-emu/ieee754dp.h
+--- linux-3.4.110.orig/arch/nds32/math-emu/ieee754dp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/ieee754dp.h 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,83 @@
++/*
++ * IEEE754 floating point
++ * double precision internal header file
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754int.h"
++
++#define assert(expr) ((void)0)
++
++/* 3bit extended double precision sticky right shift */
++#define XDPSRS(v,rs) \
++ ((rs > (DP_MBITS+3))?1:((v) >> (rs)) | ((v) << (64-(rs)) != 0))
++
++#define XDPSRSX1() \
++ (xe++, (xm = (xm >> 1) | (xm & 1)))
++
++#define XDPSRS1(v) \
++ (((v) >> 1) | ((v) & 1))
++
++/* convert denormal to normalized with extended exponent */
++#define DPDNORMx(m,e) \
++ while( (m >> DP_MBITS) == 0) { m <<= 1; e--; }
++#define DPDNORMX DPDNORMx(xm, xe)
++#define DPDNORMY DPDNORMx(ym, ye)
++
++static inline ieee754dp builddp(int s, int bx, u64 m)
++{
++ ieee754dp r;
++
++ assert((s) == 0 || (s) == 1);
++ assert((bx) >= DP_EMIN - 1 + DP_EBIAS
++ && (bx) <= DP_EMAX + 1 + DP_EBIAS);
++ assert(((m) >> DP_MBITS) == 0);
++
++ r.parts.sign = s;
++ r.parts.bexp = bx;
++ r.parts.mant = m;
++ return r;
++}
++
++extern int ieee754dp_isnan(ieee754dp);
++extern int ieee754dp_issnan(ieee754dp);
++extern int ieee754si_xcpt(int, const char *, ...);
++extern s64 ieee754di_xcpt(s64, const char *, ...);
++extern ieee754dp ieee754dp_xcpt(ieee754dp, const char *, ...);
++extern ieee754dp ieee754dp_nanxcpt(ieee754dp, const char *, ...);
++extern ieee754dp ieee754dp_bestnan(ieee754dp, ieee754dp);
++extern ieee754dp ieee754dp_format(int, int, u64);
++
++
++#define DPNORMRET2(s, e, m, name, a0, a1) \
++{ \
++ ieee754dp V = ieee754dp_format(s, e, m); \
++ if(TSTX()) \
++ return ieee754dp_xcpt(V, name, a0, a1); \
++ else \
++ return V; \
++}
++
++#define DPNORMRET1(s, e, m, name, a0) DPNORMRET2(s, e, m, name, a0, a0)
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754.h linux-3.4.110/arch/nds32/math-emu/ieee754.h
+--- linux-3.4.110.orig/arch/nds32/math-emu/ieee754.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/ieee754.h 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,467 @@
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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.
++ *
++ * Nov 7, 2000
++ * Modification to allow integration with Linux kernel
++ *
++ * Kevin D. Kissell, kevink@mips.com and Carsten Langgard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
++ */
++#ifndef __ARCH_MIPS_MATH_EMU_IEEE754_H
++#define __ARCH_MIPS_MATH_EMU_IEEE754_H
++
++#include <asm/byteorder.h>
++#include <linux/types.h>
++#include <linux/sched.h>
++
++/*
++ * Not very pretty, but the Linux kernel's normal va_list definition
++ * does not allow it to be used as a structure element, as it is here.
++ */
++#ifndef _STDARG_H
++#include <stdarg.h>
++#endif
++
++#ifdef __LITTLE_ENDIAN
++struct ieee754dp_konst {
++ unsigned mantlo:32;
++ unsigned manthi:20;
++ unsigned bexp:11;
++ unsigned sign:1;
++};
++struct ieee754sp_konst {
++ unsigned mant:23;
++ unsigned bexp:8;
++ unsigned sign:1;
++};
++
++typedef union _ieee754dp {
++ struct ieee754dp_konst oparts;
++ struct {
++ u64 mant:52;
++ unsigned int bexp:11;
++ unsigned int sign:1;
++ } parts;
++ u64 bits;
++ double d;
++} ieee754dp;
++
++typedef union _ieee754sp {
++ struct ieee754sp_konst parts;
++ float f;
++ u32 bits;
++} ieee754sp;
++#endif
++
++#ifdef __BIG_ENDIAN
++struct ieee754dp_konst {
++ unsigned sign:1;
++ unsigned bexp:11;
++ unsigned manthi:20;
++ unsigned mantlo:32;
++};
++
++typedef union _ieee754dp {
++ struct ieee754dp_konst oparts;
++ struct {
++ unsigned int sign:1;
++ unsigned int bexp:11;
++ u64 mant:52;
++ } parts;
++ double d;
++ u64 bits;
++} ieee754dp;
++
++struct ieee754sp_konst {
++ unsigned sign:1;
++ unsigned bexp:8;
++ unsigned mant:23;
++};
++
++typedef union _ieee754sp {
++ struct ieee754sp_konst parts;
++ float f;
++ u32 bits;
++} ieee754sp;
++#endif
++
++/*
++ * single precision (often aka float)
++*/
++int ieee754sp_finite(ieee754sp x);
++int ieee754sp_class(ieee754sp x);
++
++ieee754sp ieee754sp_abs(ieee754sp x);
++ieee754sp ieee754sp_neg(ieee754sp x);
++ieee754sp ieee754sp_scalb(ieee754sp x, int);
++ieee754sp ieee754sp_logb(ieee754sp x);
++
++/* x with sign of y */
++ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y);
++
++ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y);
++ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y);
++ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y);
++ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y);
++
++ieee754sp ieee754sp_fint(int x);
++ieee754sp ieee754sp_funs(unsigned x);
++ieee754sp ieee754sp_flong(s64 x);
++ieee754sp ieee754sp_fulong(u64 x);
++ieee754sp ieee754sp_fdp(ieee754dp x);
++
++int ieee754sp_tint(ieee754sp x);
++unsigned int ieee754sp_tuns(ieee754sp x);
++s64 ieee754sp_tlong(ieee754sp x);
++u64 ieee754sp_tulong(ieee754sp x);
++
++int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cop, int sig);
++/*
++ * basic sp math
++ */
++ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip);
++ieee754sp ieee754sp_frexp(ieee754sp x, int *exp);
++ieee754sp ieee754sp_ldexp(ieee754sp x, int exp);
++
++ieee754sp ieee754sp_ceil(ieee754sp x);
++ieee754sp ieee754sp_floor(ieee754sp x);
++ieee754sp ieee754sp_trunc(ieee754sp x);
++
++ieee754sp ieee754sp_sqrt(ieee754sp x);
++
++/*
++ * double precision (often aka double)
++*/
++int ieee754dp_finite(ieee754dp x);
++int ieee754dp_class(ieee754dp x);
++
++/* x with sign of y */
++ieee754dp ieee754dp_copysign(ieee754dp x, ieee754dp y);
++
++ieee754dp ieee754dp_add(ieee754dp x, ieee754dp y);
++ieee754dp ieee754dp_sub(ieee754dp x, ieee754dp y);
++ieee754dp ieee754dp_mul(ieee754dp x, ieee754dp y);
++ieee754dp ieee754dp_div(ieee754dp x, ieee754dp y);
++
++ieee754dp ieee754dp_abs(ieee754dp x);
++ieee754dp ieee754dp_neg(ieee754dp x);
++ieee754dp ieee754dp_scalb(ieee754dp x, int);
++
++/* return exponent as integer in floating point format
++ */
++ieee754dp ieee754dp_logb(ieee754dp x);
++
++ieee754dp ieee754dp_fint(int x);
++ieee754dp ieee754dp_funs(unsigned x);
++ieee754dp ieee754dp_flong(s64 x);
++ieee754dp ieee754dp_fulong(u64 x);
++ieee754dp ieee754dp_fsp(ieee754sp x);
++
++ieee754dp ieee754dp_ceil(ieee754dp x);
++ieee754dp ieee754dp_floor(ieee754dp x);
++ieee754dp ieee754dp_trunc(ieee754dp x);
++
++int ieee754dp_tint(ieee754dp x);
++unsigned int ieee754dp_tuns(ieee754dp x);
++s64 ieee754dp_tlong(ieee754dp x);
++u64 ieee754dp_tulong(ieee754dp x);
++
++int ieee754dp_cmp(ieee754dp x, ieee754dp y, int cop, int sig);
++/*
++ * basic sp math
++ */
++ieee754dp ieee754dp_modf(ieee754dp x, ieee754dp * ip);
++ieee754dp ieee754dp_frexp(ieee754dp x, int *exp);
++ieee754dp ieee754dp_ldexp(ieee754dp x, int exp);
++
++ieee754dp ieee754dp_ceil(ieee754dp x);
++ieee754dp ieee754dp_floor(ieee754dp x);
++ieee754dp ieee754dp_trunc(ieee754dp x);
++
++ieee754dp ieee754dp_sqrt(ieee754dp x);
++
++
++
++/* 5 types of floating point number
++*/
++#define IEEE754_CLASS_NORM 0x00
++#define IEEE754_CLASS_ZERO 0x01
++#define IEEE754_CLASS_DNORM 0x02
++#define IEEE754_CLASS_INF 0x03
++#define IEEE754_CLASS_SNAN 0x04
++#define IEEE754_CLASS_QNAN 0x05
++
++/* exception numbers */
++#define IEEE754_INVALID_OPERATION 0x01
++#define IEEE754_ZERO_DIVIDE 0x02
++#define IEEE754_OVERFLOW 0x04
++#define IEEE754_UNDERFLOW 0x08
++#define IEEE754_INEXACT 0x10
++
++/* cmp operators
++*/
++#define IEEE754_CLT 0x01
++#define IEEE754_CEQ 0x02
++#define IEEE754_CGT 0x04
++#define IEEE754_CUN 0x08
++
++/* rounding mode
++*/
++#define IEEE754_RN 0 /* round to nearest */
++#define IEEE754_RZ 1 /* round toward zero */
++#define IEEE754_RD 2 /* round toward -Infinity */
++#define IEEE754_RU 3 /* round toward +Infinity */
++
++/* other naming */
++#define IEEE754_RM IEEE754_RD
++#define IEEE754_RP IEEE754_RU
++
++/* "normal" comparisons
++*/
++static inline int ieee754sp_eq(ieee754sp x, ieee754sp y)
++{
++ return ieee754sp_cmp(x, y, IEEE754_CEQ, 0);
++}
++
++static inline int ieee754sp_ne(ieee754sp x, ieee754sp y)
++{
++ return ieee754sp_cmp(x, y,
++ IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
++}
++
++static inline int ieee754sp_lt(ieee754sp x, ieee754sp y)
++{
++ return ieee754sp_cmp(x, y, IEEE754_CLT, 0);
++}
++
++static inline int ieee754sp_le(ieee754sp x, ieee754sp y)
++{
++ return ieee754sp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
++}
++
++static inline int ieee754sp_gt(ieee754sp x, ieee754sp y)
++{
++ return ieee754sp_cmp(x, y, IEEE754_CGT, 0);
++}
++
++
++static inline int ieee754sp_ge(ieee754sp x, ieee754sp y)
++{
++ return ieee754sp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
++}
++
++static inline int ieee754dp_eq(ieee754dp x, ieee754dp y)
++{
++ return ieee754dp_cmp(x, y, IEEE754_CEQ, 0);
++}
++
++static inline int ieee754dp_ne(ieee754dp x, ieee754dp y)
++{
++ return ieee754dp_cmp(x, y,
++ IEEE754_CLT | IEEE754_CGT | IEEE754_CUN, 0);
++}
++
++static inline int ieee754dp_lt(ieee754dp x, ieee754dp y)
++{
++ return ieee754dp_cmp(x, y, IEEE754_CLT, 0);
++}
++
++static inline int ieee754dp_le(ieee754dp x, ieee754dp y)
++{
++ return ieee754dp_cmp(x, y, IEEE754_CLT | IEEE754_CEQ, 0);
++}
++
++static inline int ieee754dp_gt(ieee754dp x, ieee754dp y)
++{
++ return ieee754dp_cmp(x, y, IEEE754_CGT, 0);
++}
++
++static inline int ieee754dp_ge(ieee754dp x, ieee754dp y)
++{
++ return ieee754dp_cmp(x, y, IEEE754_CGT | IEEE754_CEQ, 0);
++}
++
++
++/*
++ * Like strtod
++ */
++ieee754dp ieee754dp_fstr(const char *s, char **endp);
++char *ieee754dp_tstr(ieee754dp x, int prec, int fmt, int af);
++
++
++/*
++ * The control status register
++ */
++struct _ieee754_csr {
++#ifdef __BIG_ENDIAN
++ unsigned pad0:12;
++ unsigned cx:7; /* exceptions this operation */
++ unsigned nod:1; /* set 1 for no denormalised numbers */
++ unsigned mx:5; /* exception enable mask */
++ unsigned sx:5; /* exceptions total */
++ unsigned rm:2; /* current rounding mode */
++#endif
++#ifdef __LITTLE_ENDIAN
++ unsigned rm:2; /* current rounding mode */
++ unsigned sx:5; /* exceptions total */
++ unsigned mx:5; /* exception enable mask */
++ unsigned nod:1; /* set 1 for no denormalised numbers */
++ unsigned cx:7; /* exceptions this operation */
++ unsigned pad0:12;
++#endif
++};
++#define ieee754_csr (*(struct _ieee754_csr *)(&current->thread.fpu.fpcsr))
++
++static inline unsigned ieee754_getrm(void)
++{
++ return (ieee754_csr.rm);
++}
++static inline unsigned ieee754_setrm(unsigned rm)
++{
++ return (ieee754_csr.rm = rm);
++}
++
++/*
++ * get current exceptions
++ */
++static inline unsigned ieee754_getcx(void)
++{
++ return (ieee754_csr.cx);
++}
++
++/* test for current exception condition
++ */
++static inline int ieee754_cxtest(unsigned n)
++{
++ return (ieee754_csr.cx & n);
++}
++
++/*
++ * get sticky exceptions
++ */
++static inline unsigned ieee754_getsx(void)
++{
++ return (ieee754_csr.sx);
++}
++
++/* clear sticky conditions
++*/
++static inline unsigned ieee754_clrsx(void)
++{
++ return (ieee754_csr.sx = 0);
++}
++
++/* test for sticky exception condition
++ */
++static inline int ieee754_sxtest(unsigned n)
++{
++ return (ieee754_csr.sx & n);
++}
++
++/* debugging */
++ieee754sp ieee754sp_dump(char *s, ieee754sp x);
++ieee754dp ieee754dp_dump(char *s, ieee754dp x);
++
++#define IEEE754_SPCVAL_PZERO 0
++#define IEEE754_SPCVAL_NZERO 1
++#define IEEE754_SPCVAL_PONE 2
++#define IEEE754_SPCVAL_NONE 3
++#define IEEE754_SPCVAL_PTEN 4
++#define IEEE754_SPCVAL_NTEN 5
++#define IEEE754_SPCVAL_PINFINITY 6
++#define IEEE754_SPCVAL_NINFINITY 7
++#define IEEE754_SPCVAL_INDEF 8
++#define IEEE754_SPCVAL_PMAX 9 /* +max norm */
++#define IEEE754_SPCVAL_NMAX 10 /* -max norm */
++#define IEEE754_SPCVAL_PMIN 11 /* +min norm */
++#define IEEE754_SPCVAL_NMIN 12 /* +min norm */
++#define IEEE754_SPCVAL_PMIND 13 /* +min denorm */
++#define IEEE754_SPCVAL_NMIND 14 /* +min denorm */
++#define IEEE754_SPCVAL_P1E31 15 /* + 1.0e31 */
++#define IEEE754_SPCVAL_P1E63 16 /* + 1.0e63 */
++
++extern const struct ieee754dp_konst __ieee754dp_spcvals[];
++extern const struct ieee754sp_konst __ieee754sp_spcvals[];
++#define ieee754dp_spcvals ((const ieee754dp *)__ieee754dp_spcvals)
++#define ieee754sp_spcvals ((const ieee754sp *)__ieee754sp_spcvals)
++
++/*
++ * Return infinity with given sign
++ */
++#define ieee754dp_inf(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
++#define ieee754dp_zero(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
++#define ieee754dp_one(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
++#define ieee754dp_ten(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
++#define ieee754dp_indef() (ieee754dp_spcvals[IEEE754_SPCVAL_INDEF])
++#define ieee754dp_max(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
++#define ieee754dp_min(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
++#define ieee754dp_mind(sn) (ieee754dp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
++#define ieee754dp_1e31() (ieee754dp_spcvals[IEEE754_SPCVAL_P1E31])
++#define ieee754dp_1e63() (ieee754dp_spcvals[IEEE754_SPCVAL_P1E63])
++
++#define ieee754sp_inf(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PINFINITY+(sn)])
++#define ieee754sp_zero(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PZERO+(sn)])
++#define ieee754sp_one(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PONE+(sn)])
++#define ieee754sp_ten(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PTEN+(sn)])
++#define ieee754sp_indef() (ieee754sp_spcvals[IEEE754_SPCVAL_INDEF])
++#define ieee754sp_max(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMAX+(sn)])
++#define ieee754sp_min(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIN+(sn)])
++#define ieee754sp_mind(sn) (ieee754sp_spcvals[IEEE754_SPCVAL_PMIND+(sn)])
++#define ieee754sp_1e31() (ieee754sp_spcvals[IEEE754_SPCVAL_P1E31])
++#define ieee754sp_1e63() (ieee754sp_spcvals[IEEE754_SPCVAL_P1E63])
++
++/*
++ * Indefinite integer value
++ */
++#define ieee754si_indef() INT_MAX
++#ifdef LONG_LONG_MAX
++#define ieee754di_indef() LONG_LONG_MAX
++#else
++#define ieee754di_indef() ((s64)(~0ULL>>1))
++#endif
++
++/* IEEE exception context, passed to handler */
++struct ieee754xctx {
++ const char *op; /* operation name */
++ int rt; /* result type */
++ union {
++ ieee754sp sp; /* single precision */
++ ieee754dp dp; /* double precision */
++#ifdef IEEE854_XP
++ ieee754xp xp; /* extended precision */
++#endif
++ int si; /* standard signed integer (32bits) */
++ s64 di; /* extended signed integer (64bits) */
++ } rv; /* default result format implied by op */
++ va_list ap;
++};
++
++/* result types for xctx.rt */
++#define IEEE754_RT_SP 0
++#define IEEE754_RT_DP 1
++#define IEEE754_RT_XP 2
++#define IEEE754_RT_SI 3
++#define IEEE754_RT_DI 4
++
++extern void ieee754_xcpt(struct ieee754xctx *xcp);
++
++/* compat */
++#define ieee754dp_fix(x) ieee754dp_tint(x)
++#define ieee754sp_fix(x) ieee754sp_tint(x)
++
++#endif /* __ARCH_MIPS_MATH_EMU_IEEE754_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754int.h linux-3.4.110/arch/nds32/math-emu/ieee754int.h
+--- linux-3.4.110.orig/arch/nds32/math-emu/ieee754int.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/ieee754int.h 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,165 @@
++/*
++ * IEEE754 floating point
++ * common internal header file
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754.h"
++
++#define DP_EBIAS 1023
++#define DP_EMIN (-1022)
++#define DP_EMAX 1023
++#define DP_MBITS 52
++
++#define SP_EBIAS 127
++#define SP_EMIN (-126)
++#define SP_EMAX 127
++#define SP_MBITS 23
++
++#define DP_MBIT(x) ((u64)1 << (x))
++#define DP_HIDDEN_BIT DP_MBIT(DP_MBITS)
++#define DP_SIGN_BIT DP_MBIT(63)
++
++#define SP_MBIT(x) ((u32)1 << (x))
++#define SP_HIDDEN_BIT SP_MBIT(SP_MBITS)
++#define SP_SIGN_BIT SP_MBIT(31)
++
++
++#define SPSIGN(sp) (sp.parts.sign)
++#define SPBEXP(sp) (sp.parts.bexp)
++#define SPMANT(sp) (sp.parts.mant)
++
++#define DPSIGN(dp) (dp.parts.sign)
++#define DPBEXP(dp) (dp.parts.bexp)
++#define DPMANT(dp) (dp.parts.mant)
++
++#define CLPAIR(x, y) ((x)*6+(y))
++
++#define CLEARCX \
++ (ieee754_csr.cx = 0)
++
++#define SETCX(x) \
++ (ieee754_csr.cx |= (x), ieee754_csr.sx |= (x))
++
++#define SETANDTESTCX(x) \
++ (SETCX(x), ieee754_csr.mx & (x))
++
++#define TSTX() \
++ (ieee754_csr.cx & ieee754_csr.mx)
++
++
++#define COMPXSP \
++ unsigned xm; int xe; int xs; int xc
++
++#define COMPYSP \
++ unsigned ym; int ye; int ys; int yc
++
++#define EXPLODESP(v, vc, vs, ve, vm) \
++{\
++ vs = SPSIGN(v);\
++ ve = SPBEXP(v);\
++ vm = SPMANT(v);\
++ if(ve == SP_EMAX+1+SP_EBIAS){\
++ if(vm == 0)\
++ vc = IEEE754_CLASS_INF;\
++ else if(vm & SP_MBIT(SP_MBITS-1)) \
++ vc = IEEE754_CLASS_SNAN;\
++ else \
++ vc = IEEE754_CLASS_QNAN;\
++ } else if(ve == SP_EMIN-1+SP_EBIAS) {\
++ if(vm) {\
++ ve = SP_EMIN;\
++ vc = IEEE754_CLASS_DNORM;\
++ } else\
++ vc = IEEE754_CLASS_ZERO;\
++ } else {\
++ ve -= SP_EBIAS;\
++ vm |= SP_HIDDEN_BIT;\
++ vc = IEEE754_CLASS_NORM;\
++ }\
++}
++#define EXPLODEXSP EXPLODESP(x, xc, xs, xe, xm)
++#define EXPLODEYSP EXPLODESP(y, yc, ys, ye, ym)
++
++
++#define COMPXDP \
++u64 xm; int xe; int xs; int xc
++
++#define COMPYDP \
++u64 ym; int ye; int ys; int yc
++
++#define EXPLODEDP(v, vc, vs, ve, vm) \
++{\
++ vm = DPMANT(v);\
++ vs = DPSIGN(v);\
++ ve = DPBEXP(v);\
++ if(ve == DP_EMAX+1+DP_EBIAS){\
++ if(vm == 0)\
++ vc = IEEE754_CLASS_INF;\
++ else if(vm & DP_MBIT(DP_MBITS-1)) \
++ vc = IEEE754_CLASS_SNAN;\
++ else \
++ vc = IEEE754_CLASS_QNAN;\
++ } else if(ve == DP_EMIN-1+DP_EBIAS) {\
++ if(vm) {\
++ ve = DP_EMIN;\
++ vc = IEEE754_CLASS_DNORM;\
++ } else\
++ vc = IEEE754_CLASS_ZERO;\
++ } else {\
++ ve -= DP_EBIAS;\
++ vm |= DP_HIDDEN_BIT;\
++ vc = IEEE754_CLASS_NORM;\
++ }\
++}
++#define EXPLODEXDP EXPLODEDP(x, xc, xs, xe, xm)
++#define EXPLODEYDP EXPLODEDP(y, yc, ys, ye, ym)
++
++#define FLUSHDP(v, vc, vs, ve, vm) \
++ if(vc==IEEE754_CLASS_DNORM) {\
++ if(ieee754_csr.nod) {\
++ SETCX(IEEE754_INEXACT);\
++ vc = IEEE754_CLASS_ZERO;\
++ ve = DP_EMIN-1+DP_EBIAS;\
++ vm = 0;\
++ v = ieee754dp_zero(vs);\
++ }\
++ }
++
++#define FLUSHSP(v, vc, vs, ve, vm) \
++ if(vc==IEEE754_CLASS_DNORM) {\
++ if(ieee754_csr.nod) {\
++ SETCX(IEEE754_INEXACT);\
++ vc = IEEE754_CLASS_ZERO;\
++ ve = SP_EMIN-1+SP_EBIAS;\
++ vm = 0;\
++ v = ieee754sp_zero(vs);\
++ }\
++ }
++
++#define FLUSHXDP FLUSHDP(x, xc, xs, xe, xm)
++#define FLUSHYDP FLUSHDP(y, yc, ys, ye, ym)
++#define FLUSHXSP FLUSHSP(x, xc, xs, xe, xm)
++#define FLUSHYSP FLUSHSP(y, yc, ys, ye, ym)
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754m.c linux-3.4.110/arch/nds32/math-emu/ieee754m.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/ieee754m.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/ieee754m.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,55 @@
++/*
++ * floor, trunc, ceil
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754.h"
++
++ieee754dp ieee754dp_floor(ieee754dp x)
++{
++ ieee754dp i;
++
++ if (ieee754dp_lt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
++ return ieee754dp_sub(i, ieee754dp_one(0));
++ else
++ return i;
++}
++
++ieee754dp ieee754dp_ceil(ieee754dp x)
++{
++ ieee754dp i;
++
++ if (ieee754dp_gt(ieee754dp_modf(x, &i), ieee754dp_zero(0)))
++ return ieee754dp_add(i, ieee754dp_one(0));
++ else
++ return i;
++}
++
++ieee754dp ieee754dp_trunc(ieee754dp x)
++{
++ ieee754dp i;
++
++ (void)ieee754dp_modf(x, &i);
++ return i;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754sp.c linux-3.4.110/arch/nds32/math-emu/ieee754sp.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/ieee754sp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/ieee754sp.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,239 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++int ieee754sp_class(ieee754sp x)
++{
++ COMPXSP;
++ EXPLODEXSP;
++ return xc;
++}
++
++int ieee754sp_isnan(ieee754sp x)
++{
++ return ieee754sp_class(x) >= IEEE754_CLASS_SNAN;
++}
++
++int ieee754sp_issnan(ieee754sp x)
++{
++ assert(ieee754sp_isnan(x));
++ return (SPMANT(x) & SP_MBIT(SP_MBITS - 1));
++}
++
++ieee754sp ieee754sp_xcpt(ieee754sp r, const char *op, ...)
++{
++ struct ieee754xctx ax;
++
++ if (!TSTX())
++ return r;
++
++ ax.op = op;
++ ax.rt = IEEE754_RT_SP;
++ ax.rv.sp = r;
++ va_start(ax.ap, op);
++ ieee754_xcpt(&ax);
++ va_end(ax.ap);
++ return ax.rv.sp;
++}
++
++ieee754sp ieee754sp_nanxcpt(ieee754sp r, const char *op, ...)
++{
++ struct ieee754xctx ax;
++
++ assert(ieee754sp_isnan(r));
++
++ if (!ieee754sp_issnan(r)) /* QNAN does not cause invalid op !! */
++ return r;
++
++ if (!SETANDTESTCX(IEEE754_INVALID_OPERATION)) {
++ /* not enabled convert to a quiet NaN */
++ SPMANT(r) &= (~SP_MBIT(SP_MBITS - 1));
++ if (ieee754sp_isnan(r))
++ return r;
++ else
++ return ieee754sp_indef();
++ }
++
++ ax.op = op;
++ ax.rt = 0;
++ ax.rv.sp = r;
++ va_start(ax.ap, op);
++ ieee754_xcpt(&ax);
++ va_end(ax.ap);
++ return ax.rv.sp;
++}
++
++ieee754sp ieee754sp_bestnan(ieee754sp x, ieee754sp y)
++{
++ assert(ieee754sp_isnan(x));
++ assert(ieee754sp_isnan(y));
++
++ if (SPMANT(x) > SPMANT(y))
++ return x;
++ else
++ return y;
++}
++
++static unsigned get_rounding(int sn, unsigned xm)
++{
++ /* inexact must round of 3 bits
++ */
++ if (xm & (SP_MBIT(3) - 1)) {
++ switch (ieee754_csr.rm) {
++ case IEEE754_RZ:
++ break;
++ case IEEE754_RN:
++ xm += 0x3 + ((xm >> 3) & 1);
++ /* xm += (xm&0x8)?0x4:0x3 */
++ break;
++ case IEEE754_RU: /* toward +Infinity */
++ if (!sn) /* ?? */
++ xm += 0x8;
++ break;
++ case IEEE754_RD: /* toward -Infinity */
++ if (sn) /* ?? */
++ xm += 0x8;
++ break;
++ }
++ }
++ return xm;
++}
++
++/* generate a normal/denormal number with over,under handling
++ * sn is sign
++ * xe is an unbiased exponent
++ * xm is 3bit extended precision value.
++ */
++ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
++{
++ assert(xm); /* we don't gen exact zeros (probably should) */
++
++ assert((xm >> (SP_MBITS + 1 + 3)) == 0); /* no execess */
++ assert(xm & (SP_HIDDEN_BIT << 3));
++
++ if (xe < SP_EMIN) {
++ /* strip lower bits */
++ int es = SP_EMIN - xe;
++
++ if (ieee754_csr.nod) {
++ SETCX(IEEE754_UNDERFLOW);
++ SETCX(IEEE754_INEXACT);
++
++ switch (ieee754_csr.rm) {
++ case IEEE754_RN:
++ return ieee754sp_zero(sn);
++ case IEEE754_RZ:
++ return ieee754sp_zero(sn);
++ case IEEE754_RU: /* toward +Infinity */
++ if (sn == 0)
++ return ieee754sp_min(0);
++ else
++ return ieee754sp_zero(1);
++ case IEEE754_RD: /* toward -Infinity */
++ if (sn == 0)
++ return ieee754sp_zero(0);
++ else
++ return ieee754sp_min(1);
++ }
++ }
++
++ if (xe == SP_EMIN - 1
++ && get_rounding(sn, xm) >> (SP_MBITS + 1 + 3)) {
++ /* Not tiny after rounding */
++ SETCX(IEEE754_INEXACT);
++ xm = get_rounding(sn, xm);
++ xm >>= 1;
++ /* Clear grs bits */
++ xm &= ~(SP_MBIT(3) - 1);
++ xe++;
++ } else {
++ /* sticky right shift es bits
++ */
++ SPXSRSXn(es);
++ assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
++ assert(xe == SP_EMIN);
++ }
++ }
++ if (xm & (SP_MBIT(3) - 1)) {
++ SETCX(IEEE754_INEXACT);
++ if ((xm & (SP_HIDDEN_BIT << 3)) == 0) {
++ SETCX(IEEE754_UNDERFLOW);
++ }
++
++ /* inexact must round of 3 bits
++ */
++ xm = get_rounding(sn, xm);
++ /* adjust exponent for rounding add overflowing
++ */
++ if (xm >> (SP_MBITS + 1 + 3)) {
++ /* add causes mantissa overflow */
++ xm >>= 1;
++ xe++;
++ }
++ }
++ /* strip grs bits */
++ xm >>= 3;
++
++ assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */
++ assert(xe >= SP_EMIN);
++
++ if (xe > SP_EMAX) {
++ SETCX(IEEE754_OVERFLOW);
++ SETCX(IEEE754_INEXACT);
++ /* -O can be table indexed by (rm,sn) */
++ switch (ieee754_csr.rm) {
++ case IEEE754_RN:
++ return ieee754sp_inf(sn);
++ case IEEE754_RZ:
++ return ieee754sp_max(sn);
++ case IEEE754_RU: /* toward +Infinity */
++ if (sn == 0)
++ return ieee754sp_inf(0);
++ else
++ return ieee754sp_max(1);
++ case IEEE754_RD: /* toward -Infinity */
++ if (sn == 0)
++ return ieee754sp_max(0);
++ else
++ return ieee754sp_inf(1);
++ }
++ }
++ /* gen norm/denorm/zero */
++
++ if ((xm & SP_HIDDEN_BIT) == 0) {
++ /* we underflow (tiny/zero) */
++ assert(xe == SP_EMIN);
++ if (ieee754_csr.mx & IEEE754_UNDERFLOW)
++ SETCX(IEEE754_UNDERFLOW);
++ return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
++ } else {
++ assert((xm >> (SP_MBITS + 1)) == 0); /* no execess */
++ assert(xm & SP_HIDDEN_BIT);
++
++ return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754sp.h linux-3.4.110/arch/nds32/math-emu/ieee754sp.h
+--- linux-3.4.110.orig/arch/nds32/math-emu/ieee754sp.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/ieee754sp.h 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,89 @@
++/*
++ * IEEE754 floating point
++ * double precision internal header file
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754int.h"
++
++#define assert(expr) ((void)0)
++
++/* 3bit extended single precision sticky right shift */
++#define SPXSRSXn(rs) \
++ (xe += rs, \
++ xm = (rs > (SP_MBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
++
++#define SPXSRSX1() \
++ (xe++, (xm = (xm >> 1) | (xm & 1)))
++
++#define SPXSRSYn(rs) \
++ (ye+=rs, \
++ ym = (rs > (SP_MBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
++
++#define SPXSRSY1() \
++ (ye++, (ym = (ym >> 1) | (ym & 1)))
++
++/* convert denormal to normalized with extended exponent */
++#define SPDNORMx(m,e) \
++ while( (m >> SP_MBITS) == 0) { m <<= 1; e--; }
++#define SPDNORMX SPDNORMx(xm, xe)
++#define SPDNORMY SPDNORMx(ym, ye)
++
++static inline ieee754sp buildsp(int s, int bx, unsigned m)
++{
++ ieee754sp r;
++
++ assert((s) == 0 || (s) == 1);
++ assert((bx) >= SP_EMIN - 1 + SP_EBIAS
++ && (bx) <= SP_EMAX + 1 + SP_EBIAS);
++ assert(((m) >> SP_MBITS) == 0);
++
++ r.parts.sign = s;
++ r.parts.bexp = bx;
++ r.parts.mant = m;
++
++ return r;
++}
++
++extern int ieee754sp_isnan(ieee754sp);
++extern int ieee754sp_issnan(ieee754sp);
++extern int ieee754si_xcpt(int, const char *, ...);
++extern s64 ieee754di_xcpt(s64, const char *, ...);
++extern ieee754sp ieee754sp_xcpt(ieee754sp, const char *, ...);
++extern ieee754sp ieee754sp_nanxcpt(ieee754sp, const char *, ...);
++extern ieee754sp ieee754sp_bestnan(ieee754sp, ieee754sp);
++extern ieee754sp ieee754sp_format(int, int, unsigned);
++
++
++#define SPNORMRET2(s, e, m, name, a0, a1) \
++{ \
++ ieee754sp V = ieee754sp_format(s, e, m); \
++ if(TSTX()) \
++ return ieee754sp_xcpt(V, name, a0, a1); \
++ else \
++ return V; \
++}
++
++#define SPNORMRET1(s, e, m, name, a0) SPNORMRET2(s, e, m, name, a0, a0)
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/ieee754xcpt.c linux-3.4.110/arch/nds32/math-emu/ieee754xcpt.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/ieee754xcpt.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/ieee754xcpt.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,48 @@
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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.
++ *
++ * ########################################################################
++ */
++
++/**************************************************************************
++ * Nov 7, 2000
++ * Added preprocessor hacks to map to Linux kernel diagnostics.
++ *
++ * Kevin D. Kissell, kevink@mips.com and Carsten Langgaard, carstenl@mips.com
++ * Copyright (C) 2000 MIPS Technologies, Inc. All rights reserved.
++ *************************************************************************/
++
++#include <linux/kernel.h>
++#include "ieee754.h"
++
++/*
++ * Very naff exception handler (you can plug in your own and
++ * override this).
++ */
++
++static const char *const rtnames[] = {
++ "sp", "dp", "xp", "si", "di"
++};
++
++void ieee754_xcpt(struct ieee754xctx *xcp)
++{
++ printk(KERN_DEBUG "floating point exception in \"%s\", type=%s\n",
++ xcp->op, rtnames[xcp->rt]);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/insn.h linux-3.4.110/arch/nds32/math-emu/insn.h
+--- linux-3.4.110.orig/arch/nds32/math-emu/insn.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/insn.h 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,101 @@
++#ifndef _ASM_INST_H
++#define _ASM_INST_H
++
++#define cop0_op 0x35
++
++/*
++ * COP0 field of opcodes.
++ */
++#define fs1_op 0x0
++#define fs2_op 0x4
++#define fd1_op 0x8
++#define fd2_op 0xc
++
++/*
++ * FS1 opcode.
++ */
++enum fs1 {
++ fadds_op, fsubs_op, fcpynss_op, fcpyss_op,
++ fmadds_op, fmsubs_op, fcmovns_op, fcmovzs_op,
++ fnmadds_op, fnmsubs_op,
++ fmuls_op = 0xc, fdivs_op,
++ fs1_f2op_op = 0xf
++};
++
++/*
++ * FS1/F2OP opcode.
++ */
++enum fs1_f2 {
++ fs2d_op, fsqrts_op, fabss_op = 0x5,
++ fui2s_op = 0x8, fsi2s_op = 0xc,
++ fs2ui_op = 0x10, fs2ui_z_op = 0x14,
++ fs2si_op = 0x18, fs2si_z_op = 0x1c
++};
++
++/*
++ * FS2 opcode.
++ */
++enum fs2 {
++ fcmpeqs_op, fcmpeqs_e_op, fcmplts_op, fcmplts_e_op,
++ fcmples_op, fcmples_e_op, fcmpuns_op, fcmpuns_e_op
++};
++
++/*
++ * FD1 opcode.
++ */
++enum fd1 {
++ faddd_op, fsubd_op, fcpynsd_op, fcpysd_op,
++ fmaddd_op, fmsubd_op, fcmovnd_op, fcmovzd_op,
++ fnmaddd_op, fnmsubd_op,
++ fmuld_op = 0xc, fdivd_op, fd1_f2op_op = 0xf
++};
++
++/*
++ * FD1/F2OP opcode.
++ */
++enum fd1_f2 {
++ fd2s_op, fsqrtd_op, fabsd_op = 0x5,
++ fui2d_op = 0x8, fsi2d_op = 0xc,
++ fd2ui_op = 0x10, fd2ui_z_op = 0x14,
++ fd2si_op = 0x18, fd2si_z_op = 0x1c
++};
++
++/*
++ * FD2 opcode.
++ */
++enum fd2 {
++ fcmpeqd_op, fcmpeqd_e_op, fcmpltd_op, fcmpltd_e_op,
++ fcmpled_op, fcmpled_e_op, fcmpund_op, fcmpund_e_op
++};
++
++
++#define NDS32Insn(x) x
++
++#define I_OPCODE_off 25
++#define NDS32Insn_OPCODE(x) (NDS32Insn(x) >> I_OPCODE_off)
++
++#define I_OPCODE_offRt 20
++#define I_OPCODE_mskRt (0x1fUL << I_OPCODE_offRt)
++#define NDS32Insn_OPCODE_Rt(x) ((NDS32Insn(x) & I_OPCODE_mskRt) >> I_OPCODE_offRt)
++
++#define I_OPCODE_offRa 15
++#define I_OPCODE_mskRa (0x1fUL << I_OPCODE_offRa)
++#define NDS32Insn_OPCODE_Ra(x) ((NDS32Insn(x) & I_OPCODE_mskRa) >> I_OPCODE_offRa)
++
++#define I_OPCODE_offRb 10
++#define I_OPCODE_mskRb (0x1fUL << I_OPCODE_offRb)
++#define NDS32Insn_OPCODE_Rb(x) ((NDS32Insn(x) & I_OPCODE_mskRb) >> I_OPCODE_offRb)
++
++#define I_OPCODE_offbit1014 10
++#define I_OPCODE_mskbit1014 (0x1fUL << I_OPCODE_offbit1014)
++#define NDS32Insn_OPCODE_BIT1014(x) ((NDS32Insn(x) & I_OPCODE_mskbit1014) >> I_OPCODE_offbit1014)
++
++#define I_OPCODE_offbit69 6
++#define I_OPCODE_mskbit69 (0xfUL << I_OPCODE_offbit69)
++#define NDS32Insn_OPCODE_BIT69(x) ((NDS32Insn(x) & I_OPCODE_mskbit69) >> I_OPCODE_offbit69)
++
++#define I_OPCODE_offCOP0 0
++#define I_OPCODE_mskCOP0 (0x3fUL << I_OPCODE_offCOP0)
++#define NDS32Insn_OPCODE_COP0(x) ((NDS32Insn(x) & I_OPCODE_mskCOP0) >> I_OPCODE_offCOP0)
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/Makefile linux-3.4.110/arch/nds32/math-emu/Makefile
+--- linux-3.4.110.orig/arch/nds32/math-emu/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/Makefile 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,13 @@
++#
++# Makefile for the Linux/nds32 kernel FPU emulation.
++#
++
++obj-y := fpuemu.o ieee754m.o ieee754d.o ieee754dp.o ieee754sp.o ieee754.o \
++ ieee754xcpt.o dp_frexp.o dp_modf.o dp_div.o dp_mul.o dp_sub.o \
++ dp_add.o dp_fsp.o dp_cmp.o dp_logb.o dp_scalb.o dp_simple.o \
++ dp_tint.o dp_fint.o dp_tlong.o dp_flong.o sp_frexp.o sp_modf.o \
++ sp_div.o sp_mul.o sp_sub.o sp_add.o sp_fdp.o sp_cmp.o sp_logb.o \
++ sp_scalb.o sp_simple.o sp_tint.o sp_fint.o sp_tlong.o sp_flong.o \
++ dp_sqrt.o sp_sqrt.o
++
++EXTRA_CFLAGS += -Werror
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_add.c linux-3.4.110/arch/nds32/math-emu/sp_add.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_add.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_add.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,173 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++ieee754sp ieee754sp_add(ieee754sp x, ieee754sp y)
++{
++ COMPXSP;
++ COMPYSP;
++
++ EXPLODEXSP;
++ EXPLODEYSP;
++
++ CLEARCX;
++
++ FLUSHXSP;
++ FLUSHYSP;
++
++ switch (CLPAIR(xc, yc)) {
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_nanxcpt(ieee754sp_indef(), "add", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
++ return x;
++
++ /* Infinity handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
++ if (xs == ys)
++ return x;
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_xcpt(ieee754sp_indef(), "add", x, y);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
++ return x;
++
++ /* Zero handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
++ if (xs == ys)
++ return x;
++ else
++ return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
++ return x;
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
++ SPDNORMX;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
++ SPDNORMY;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
++ SPDNORMX;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
++ break;
++ }
++ assert(xm & SP_HIDDEN_BIT);
++ assert(ym & SP_HIDDEN_BIT);
++
++ /* provide guard,round and stick bit space */
++ xm <<= 3;
++ ym <<= 3;
++
++ if (xe > ye) {
++ /* have to shift y fraction right to align
++ */
++ int s = xe - ye;
++ SPXSRSYn(s);
++ } else if (ye > xe) {
++ /* have to shift x fraction right to align
++ */
++ int s = ye - xe;
++ SPXSRSXn(s);
++ }
++ assert(xe == ye);
++ assert(xe <= SP_EMAX);
++
++ if (xs == ys) {
++ /* generate 28 bit result of adding two 27 bit numbers
++ * leaving result in xm,xs,xe
++ */
++ xm = xm + ym;
++ xe = xe;
++ xs = xs;
++
++ if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
++ SPXSRSX1();
++ }
++ } else {
++ if (xm >= ym) {
++ xm = xm - ym;
++ xe = xe;
++ xs = xs;
++ } else {
++ xm = ym - xm;
++ xe = xe;
++ xs = ys;
++ }
++ if (xm == 0)
++ return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD);
++
++ /* normalize in extended single precision */
++ while ((xm >> (SP_MBITS + 3)) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++
++ }
++ SPNORMRET2(xs, xe, xm, "add", x, y);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_cmp.c linux-3.4.110/arch/nds32/math-emu/sp_cmp.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_cmp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_cmp.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,66 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++int ieee754sp_cmp(ieee754sp x, ieee754sp y, int cmp, int sig)
++{
++ COMPXSP;
++ COMPYSP;
++
++ EXPLODEXSP;
++ EXPLODEYSP;
++ FLUSHXSP;
++ FLUSHYSP;
++ CLEARCX; /* Even clear inexact flag here */
++
++ if (ieee754sp_isnan(x) || ieee754sp_isnan(y)) {
++ if (sig || xc == IEEE754_CLASS_SNAN || yc == IEEE754_CLASS_SNAN)
++ SETCX(IEEE754_INVALID_OPERATION);
++ if (cmp & IEEE754_CUN)
++ return 1;
++ if (cmp & (IEEE754_CLT | IEEE754_CGT)) {
++ if (sig && SETANDTESTCX(IEEE754_INVALID_OPERATION))
++ return ieee754si_xcpt(0, "fcmpf", x);
++ }
++ return 0;
++ } else {
++ int vx = x.bits;
++ int vy = y.bits;
++
++ if (vx < 0)
++ vx = -vx ^ SP_SIGN_BIT;
++ if (vy < 0)
++ vy = -vy ^ SP_SIGN_BIT;
++
++ if (vx < vy)
++ return (cmp & IEEE754_CLT) != 0;
++ else if (vx == vy)
++ return (cmp & IEEE754_CEQ) != 0;
++ else
++ return (cmp & IEEE754_CGT) != 0;
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_div.c linux-3.4.110/arch/nds32/math-emu/sp_div.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_div.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_div.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,155 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++ieee754sp ieee754sp_div(ieee754sp x, ieee754sp y)
++{
++ COMPXSP;
++ COMPYSP;
++
++ EXPLODEXSP;
++ EXPLODEYSP;
++
++ CLEARCX;
++
++ FLUSHXSP;
++ FLUSHYSP;
++
++ switch (CLPAIR(xc, yc)) {
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_nanxcpt(ieee754sp_indef(), "div", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
++ return x;
++
++ /* Infinity handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
++ return ieee754sp_zero(xs ^ ys);
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
++ return ieee754sp_inf(xs ^ ys);
++
++ /* Zero handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_xcpt(ieee754sp_indef(), "div", x, y);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
++ SETCX(IEEE754_ZERO_DIVIDE);
++ return ieee754sp_xcpt(ieee754sp_inf(xs ^ ys), "div", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
++ return ieee754sp_zero(xs == ys ? 0 : 1);
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
++ SPDNORMX;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
++ SPDNORMY;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
++ SPDNORMX;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
++ break;
++ }
++ assert(xm & SP_HIDDEN_BIT);
++ assert(ym & SP_HIDDEN_BIT);
++
++ /* provide rounding space */
++ xm <<= 3;
++ ym <<= 3;
++
++ {
++ /* now the dirty work */
++
++ unsigned rm = 0;
++ int re = xe - ye;
++ unsigned bm;
++
++ for (bm = SP_MBIT(SP_MBITS + 2); bm; bm >>= 1) {
++ if (xm >= ym) {
++ xm -= ym;
++ rm |= bm;
++ if (xm == 0)
++ break;
++ }
++ xm <<= 1;
++ }
++ rm <<= 1;
++ if (xm)
++ rm |= 1; /* have remainder, set sticky */
++
++ assert(rm);
++
++ /* normalise rm to rounding precision ?
++ */
++ while ((rm >> (SP_MBITS + 3)) == 0) {
++ rm <<= 1;
++ re--;
++ }
++
++ SPNORMRET2(xs == ys ? 0 : 1, re, rm, "div", x, y);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_fdp.c linux-3.4.110/arch/nds32/math-emu/sp_fdp.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_fdp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_fdp.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,76 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++ieee754sp ieee754sp_fdp(ieee754dp x)
++{
++ COMPXDP;
++ ieee754sp nan;
++
++ EXPLODEXDP;
++
++ CLEARCX;
++
++ FLUSHXDP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_nanxcpt(ieee754sp_indef(), "fdp");
++ case IEEE754_CLASS_QNAN:
++ nan = buildsp(xs, SP_EMAX + 1 + SP_EBIAS, (u32)
++ (xm >> (DP_MBITS - SP_MBITS)));
++ if (!ieee754sp_isnan(nan))
++ nan = ieee754sp_indef();
++ return ieee754sp_nanxcpt(nan, "fdp", x);
++ case IEEE754_CLASS_INF:
++ return ieee754sp_inf(xs);
++ case IEEE754_CLASS_ZERO:
++ return ieee754sp_zero(xs);
++ case IEEE754_CLASS_DNORM:
++ /* can't possibly be sp representable */
++ SETCX(IEEE754_UNDERFLOW);
++ SETCX(IEEE754_INEXACT);
++ if ((ieee754_csr.rm == IEEE754_RU && !xs) ||
++ (ieee754_csr.rm == IEEE754_RD && xs))
++ return ieee754sp_xcpt(ieee754sp_mind(xs), "fdp", x);
++ return ieee754sp_xcpt(ieee754sp_zero(xs), "fdp", x);
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++
++ {
++ u32 rm;
++
++ /* convert from DP_MBITS to SP_MBITS+3 with sticky right shift
++ */
++ rm = (xm >> (DP_MBITS - (SP_MBITS + 3))) |
++ ((xm << (64 - (DP_MBITS - (SP_MBITS + 3)))) != 0);
++
++ SPNORMRET1(xs, xe, rm, "fdp", x);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_fint.c linux-3.4.110/arch/nds32/math-emu/sp_fint.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_fint.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_fint.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,78 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++ieee754sp ieee754sp_fint(int x)
++{
++ unsigned xm;
++ int xe;
++ int xs;
++
++ CLEARCX;
++
++ if (x == 0)
++ return ieee754sp_zero(0);
++ if (x == 1 || x == -1)
++ return ieee754sp_one(x < 0);
++ if (x == 10 || x == -10)
++ return ieee754sp_ten(x < 0);
++
++ xs = (x < 0);
++ if (xs) {
++ if (x == (1 << 31))
++ xm = ((unsigned)1 << 31); /* max neg can't be safely negated */
++ else
++ xm = -x;
++ } else {
++ xm = x;
++ }
++ xe = SP_MBITS + 3;
++
++ if (xm >> (SP_MBITS + 1 + 3)) {
++ /* shunt out overflow bits
++ */
++ while (xm >> (SP_MBITS + 1 + 3)) {
++ SPXSRSX1();
++ }
++ } else {
++ /* normalize in grs extended single precision
++ */
++ while ((xm >> (SP_MBITS + 3)) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++ }
++ SPNORMRET1(xs, xe, xm, "fint", x);
++}
++
++ieee754sp ieee754sp_funs(unsigned int u)
++{
++ if ((int)u < 0)
++ return ieee754sp_add(ieee754sp_1e31(),
++ ieee754sp_fint(u & ~(1 << 31)));
++ return ieee754sp_fint(u);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_flong.c linux-3.4.110/arch/nds32/math-emu/sp_flong.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_flong.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_flong.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,77 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++ieee754sp ieee754sp_flong(s64 x)
++{
++ u64 xm; /* <--- need 64-bit mantissa temp */
++ int xe;
++ int xs;
++
++ CLEARCX;
++
++ if (x == 0)
++ return ieee754sp_zero(0);
++ if (x == 1 || x == -1)
++ return ieee754sp_one(x < 0);
++ if (x == 10 || x == -10)
++ return ieee754sp_ten(x < 0);
++
++ xs = (x < 0);
++ if (xs) {
++ if (x == (1ULL << 63))
++ xm = (1ULL << 63); /* max neg can't be safely negated */
++ else
++ xm = -x;
++ } else {
++ xm = x;
++ }
++ xe = SP_MBITS + 3;
++
++ if (xm >> (SP_MBITS + 1 + 3)) {
++ /* shunt out overflow bits
++ */
++ while (xm >> (SP_MBITS + 1 + 3)) {
++ SPXSRSX1();
++ }
++ } else {
++ /* normalize in grs extended single precision */
++ while ((xm >> (SP_MBITS + 3)) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++ }
++ SPNORMRET1(xs, xe, xm, "sp_flong", x);
++}
++
++ieee754sp ieee754sp_fulong(u64 u)
++{
++ if ((s64) u < 0)
++ return ieee754sp_add(ieee754sp_1e63(),
++ ieee754sp_flong(u & ~(1ULL << 63)));
++ return ieee754sp_flong(u);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_frexp.c linux-3.4.110/arch/nds32/math-emu/sp_frexp.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_frexp.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_frexp.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,52 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++/* close to ieeep754sp_logb
++*/
++ieee754sp ieee754sp_frexp(ieee754sp x, int *eptr)
++{
++ COMPXSP;
++ CLEARCX;
++ EXPLODEXSP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_INF:
++ case IEEE754_CLASS_ZERO:
++ *eptr = 0;
++ return x;
++ case IEEE754_CLASS_DNORM:
++ SPDNORMX;
++ break;
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ *eptr = xe + 1;
++ return buildsp(xs, -1 + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_logb.c linux-3.4.110/arch/nds32/math-emu/sp_logb.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_logb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_logb.c 2016-04-07 10:20:50.978082417 +0200
+@@ -0,0 +1,53 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++ieee754sp ieee754sp_logb(ieee754sp x)
++{
++ COMPXSP;
++
++ CLEARCX;
++
++ EXPLODEXSP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ return ieee754sp_nanxcpt(x, "logb", x);
++ case IEEE754_CLASS_QNAN:
++ return x;
++ case IEEE754_CLASS_INF:
++ return ieee754sp_inf(0);
++ case IEEE754_CLASS_ZERO:
++ return ieee754sp_inf(1);
++ case IEEE754_CLASS_DNORM:
++ SPDNORMX;
++ break;
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ return ieee754sp_fint(xe);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_modf.c linux-3.4.110/arch/nds32/math-emu/sp_modf.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_modf.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_modf.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,79 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++/* modf function is always exact for a finite number
++*/
++ieee754sp ieee754sp_modf(ieee754sp x, ieee754sp * ip)
++{
++ COMPXSP;
++
++ CLEARCX;
++
++ EXPLODEXSP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_INF:
++ case IEEE754_CLASS_ZERO:
++ *ip = x;
++ return x;
++ case IEEE754_CLASS_DNORM:
++ /* far to small */
++ *ip = ieee754sp_zero(xs);
++ return x;
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ if (xe < 0) {
++ *ip = ieee754sp_zero(xs);
++ return x;
++ }
++ if (xe >= SP_MBITS) {
++ *ip = x;
++ return ieee754sp_zero(xs);
++ }
++ /* generate ipart mantissa by clearing bottom bits
++ */
++ *ip = buildsp(xs, xe + SP_EBIAS,
++ ((xm >> (SP_MBITS - xe)) << (SP_MBITS - xe)) &
++ ~SP_HIDDEN_BIT);
++
++ /* generate fpart mantissa by clearing top bits
++ * and normalizing (must be able to normalize)
++ */
++ xm = (xm << (32 - (SP_MBITS - xe))) >> (32 - (SP_MBITS - xe));
++ if (xm == 0)
++ return ieee754sp_zero(xs);
++
++ while ((xm >> SP_MBITS) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++ return buildsp(xs, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_mul.c linux-3.4.110/arch/nds32/math-emu/sp_mul.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_mul.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_mul.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,168 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++ieee754sp ieee754sp_mul(ieee754sp x, ieee754sp y)
++{
++ COMPXSP;
++ COMPYSP;
++
++ EXPLODEXSP;
++ EXPLODEYSP;
++
++ CLEARCX;
++
++ FLUSHXSP;
++ FLUSHYSP;
++
++ switch (CLPAIR(xc, yc)) {
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_nanxcpt(ieee754sp_indef(), "mul", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
++ return x;
++
++ /* Infinity handling */
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_xcpt(ieee754sp_indef(), "mul", x, y);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
++ return ieee754sp_inf(xs ^ ys);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
++ return ieee754sp_zero(xs ^ ys);
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
++ SPDNORMX;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
++ SPDNORMY;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
++ SPDNORMX;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
++ break;
++ }
++ /* rm = xm * ym, re = xe+ye basicly */
++ assert(xm & SP_HIDDEN_BIT);
++ assert(ym & SP_HIDDEN_BIT);
++
++ {
++ int re = xe + ye;
++ int rs = xs ^ ys;
++ unsigned rm;
++
++ /* shunt to top of word */
++ xm <<= 32 - (SP_MBITS + 1);
++ ym <<= 32 - (SP_MBITS + 1);
++
++ /* multiply 32bits xm,ym to give high 32bits rm with stickness
++ */
++ {
++ unsigned short lxm = xm & 0xffff;
++ unsigned short hxm = xm >> 16;
++ unsigned short lym = ym & 0xffff;
++ unsigned short hym = ym >> 16;
++ unsigned lrm;
++ unsigned hrm;
++
++ lrm = lxm * lym; /* 16 * 16 => 32 */
++ hrm = hxm * hym; /* 16 * 16 => 32 */
++
++ {
++ unsigned t = lxm * hym; /* 16 * 16 => 32 */
++ {
++ unsigned at = lrm + (t << 16);
++ hrm += at < lrm;
++ lrm = at;
++ }
++ hrm = hrm + (t >> 16);
++ }
++
++ {
++ unsigned t = hxm * lym; /* 16 * 16 => 32 */
++ {
++ unsigned at = lrm + (t << 16);
++ hrm += at < lrm;
++ lrm = at;
++ }
++ hrm = hrm + (t >> 16);
++ }
++ rm = hrm | (lrm != 0);
++ }
++
++ /*
++ * sticky shift down to normal rounding precision
++ */
++ if ((int)rm < 0) {
++ rm = (rm >> (32 - (SP_MBITS + 1 + 3))) |
++ ((rm << (SP_MBITS + 1 + 3)) != 0);
++ re++;
++ } else {
++ rm = (rm >> (32 - (SP_MBITS + 1 + 3 + 1))) |
++ ((rm << (SP_MBITS + 1 + 3 + 1)) != 0);
++ }
++ assert(rm & (SP_HIDDEN_BIT << 3));
++
++ SPNORMRET2(rs, re, rm, "mul", x, y);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_scalb.c linux-3.4.110/arch/nds32/math-emu/sp_scalb.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_scalb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_scalb.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,56 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++ieee754sp ieee754sp_scalb(ieee754sp x, int n)
++{
++ COMPXSP;
++
++ CLEARCX;
++
++ EXPLODEXSP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ return ieee754sp_nanxcpt(x, "scalb", x, n);
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_INF:
++ case IEEE754_CLASS_ZERO:
++ return x;
++ case IEEE754_CLASS_DNORM:
++ SPDNORMX;
++ break;
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ SPNORMRET2(xs, xe + n, xm << 3, "scalb", x, n);
++}
++
++ieee754sp ieee754sp_ldexp(ieee754sp x, int n)
++{
++ return ieee754sp_scalb(x, n);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_simple.c linux-3.4.110/arch/nds32/math-emu/sp_simple.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_simple.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_simple.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,87 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++int ieee754sp_finite(ieee754sp x)
++{
++ return SPBEXP(x) != SP_EMAX + 1 + SP_EBIAS;
++}
++
++ieee754sp ieee754sp_copysign(ieee754sp x, ieee754sp y)
++{
++ CLEARCX;
++ SPSIGN(x) = SPSIGN(y);
++ return x;
++}
++
++ieee754sp ieee754sp_neg(ieee754sp x)
++{
++ COMPXSP;
++
++ EXPLODEXSP;
++ CLEARCX;
++ FLUSHXSP;
++
++ /*
++ * Invert the sign ALWAYS to prevent an endless recursion on
++ * pow() in libc.
++ */
++ /* quick fix up */
++ SPSIGN(x) ^= 1;
++
++ if (xc == IEEE754_CLASS_SNAN) {
++ ieee754sp y = ieee754sp_indef();
++ SETCX(IEEE754_INVALID_OPERATION);
++ SPSIGN(y) = SPSIGN(x);
++ return ieee754sp_nanxcpt(y, "neg");
++ }
++
++ if (ieee754sp_isnan(x)) /* but not infinity */
++ return ieee754sp_nanxcpt(x, "neg", x);
++ return x;
++}
++
++ieee754sp ieee754sp_abs(ieee754sp x)
++{
++ COMPXSP;
++
++ EXPLODEXSP;
++ CLEARCX;
++ FLUSHXSP;
++
++ if (xc == IEEE754_CLASS_SNAN) {
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_nanxcpt(ieee754sp_indef(), "abs");
++ }
++
++ if (ieee754sp_isnan(x)) /* but not infinity */
++ return ieee754sp_nanxcpt(x, "abs", x);
++
++ /* quick fix up */
++ SPSIGN(x) = 0;
++ return x;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_sqrt.c linux-3.4.110/arch/nds32/math-emu/sp_sqrt.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_sqrt.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_sqrt.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,116 @@
++/* IEEE754 floating point arithmetic
++ * single precision square root
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++ieee754sp ieee754sp_sqrt(ieee754sp x)
++{
++ int ix, s, q, m, t, i;
++ unsigned int r;
++ COMPXSP;
++
++ /* take care of Inf and NaN */
++
++ EXPLODEXSP;
++ CLEARCX;
++ FLUSHXSP;
++
++ /* x == INF or NAN? */
++ switch (xc) {
++ case IEEE754_CLASS_QNAN:
++ /* sqrt(Nan) = Nan */
++ return ieee754sp_nanxcpt(x, "sqrt");
++ case IEEE754_CLASS_SNAN:
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
++ case IEEE754_CLASS_ZERO:
++ /* sqrt(0) = 0 */
++ return x;
++ case IEEE754_CLASS_INF:
++ if (xs) {
++ /* sqrt(-Inf) = Nan */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
++ }
++ /* sqrt(+Inf) = Inf */
++ return x;
++ case IEEE754_CLASS_DNORM:
++ case IEEE754_CLASS_NORM:
++ if (xs) {
++ /* sqrt(-x) = Nan */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_nanxcpt(ieee754sp_indef(), "sqrt");
++ }
++ break;
++ }
++
++ ix = x.bits;
++
++ /* normalize x */
++ m = (ix >> 23);
++ if (m == 0) { /* subnormal x */
++ for (i = 0; (ix & 0x00800000) == 0; i++)
++ ix <<= 1;
++ m -= i - 1;
++ }
++ m -= 127; /* unbias exponent */
++ ix = (ix & 0x007fffff) | 0x00800000;
++ if (m & 1) /* odd m, double x to make it even */
++ ix += ix;
++ m >>= 1; /* m = [m/2] */
++
++ /* generate sqrt(x) bit by bit */
++ ix += ix;
++ q = s = 0; /* q = sqrt(x) */
++ r = 0x01000000; /* r = moving bit from right to left */
++
++ while (r != 0) {
++ t = s + r;
++ if (t <= ix) {
++ s = t + r;
++ ix -= t;
++ q += r;
++ }
++ ix += ix;
++ r >>= 1;
++ }
++
++ if (ix != 0) {
++ SETCX(IEEE754_INEXACT);
++ switch (ieee754_csr.rm) {
++ case IEEE754_RP:
++ q += 2;
++ break;
++ case IEEE754_RN:
++ q += (q & 1);
++ break;
++ }
++ }
++ ix = (q >> 1) + 0x3f000000;
++ ix += (m << 23);
++ x.bits = ix;
++ return x;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_sub.c linux-3.4.110/arch/nds32/math-emu/sp_sub.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_sub.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_sub.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,180 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++ieee754sp ieee754sp_sub(ieee754sp x, ieee754sp y)
++{
++ COMPXSP;
++ COMPYSP;
++
++ EXPLODEXSP;
++ EXPLODEYSP;
++
++ CLEARCX;
++
++ FLUSHXSP;
++ FLUSHYSP;
++
++ switch (CLPAIR(xc, yc)) {
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF):
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_nanxcpt(ieee754sp_indef(), "sub", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN):
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM):
++ case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF):
++ return x;
++
++ /* Infinity handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
++ if (xs != ys)
++ return x;
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754sp_xcpt(ieee754sp_indef(), "sub", x, y);
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF):
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF):
++ return ieee754sp_inf(ys ^ 1);
++
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
++ return x;
++
++ /* Zero handling
++ */
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
++ if (xs != ys)
++ return x;
++ else
++ return ieee754sp_zero(ieee754_csr.rm == IEEE754_RD);
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO):
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO):
++ return x;
++
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
++ case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM):
++ /* quick fix up */
++ DPSIGN(y) ^= 1;
++ return y;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM):
++ SPDNORMX;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM):
++ SPDNORMY;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM):
++ SPDNORMX;
++ break;
++
++ case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
++ break;
++ }
++ /* flip sign of y and handle as add */
++ ys ^= 1;
++
++ assert(xm & SP_HIDDEN_BIT);
++ assert(ym & SP_HIDDEN_BIT);
++
++ /* provide guard,round and stick bit space */
++ xm <<= 3;
++ ym <<= 3;
++
++ if (xe > ye) {
++ /* have to shift y fraction right to align
++ */
++ int s = xe - ye;
++ SPXSRSYn(s);
++ } else if (ye > xe) {
++ /* have to shift x fraction right to align
++ */
++ int s = ye - xe;
++ SPXSRSXn(s);
++ }
++ assert(xe == ye);
++ assert(xe <= SP_EMAX);
++
++ if (xs == ys) {
++ /* generate 28 bit result of adding two 27 bit numbers
++ */
++ xm = xm + ym;
++ xe = xe;
++ xs = xs;
++
++ if (xm >> (SP_MBITS + 1 + 3)) { /* carry out */
++ SPXSRSX1(); /* shift preserving sticky */
++ }
++ } else {
++ if (xm >= ym) {
++ xm = xm - ym;
++ xe = xe;
++ xs = xs;
++ } else {
++ xm = ym - xm;
++ xe = xe;
++ xs = ys;
++ }
++ if (xm == 0) {
++ if (ieee754_csr.rm == IEEE754_RD)
++ return ieee754sp_zero(1); /* round negative inf. => sign = -1 */
++ else
++ return ieee754sp_zero(0); /* other round modes => sign = 1 */
++ }
++ /* normalize to rounding precision
++ */
++ while ((xm >> (SP_MBITS + 3)) == 0) {
++ xm <<= 1;
++ xe--;
++ }
++ }
++ SPNORMRET2(xs, xe, xm, "sub", x, y);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_tint.c linux-3.4.110/arch/nds32/math-emu/sp_tint.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_tint.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_tint.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,125 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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/kernel.h>
++#include "ieee754sp.h"
++
++int ieee754sp_tint(ieee754sp x)
++{
++ COMPXSP;
++
++ CLEARCX;
++
++ EXPLODEXSP;
++ FLUSHXSP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_INF:
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
++ case IEEE754_CLASS_ZERO:
++ return 0;
++ case IEEE754_CLASS_DNORM:
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ if (xe >= 31) {
++ /* look for valid corner case */
++ if (xe == 31 && xs && xm == SP_HIDDEN_BIT)
++ return -0x80000000;
++ /* Set invalid. We will only use overflow for floating
++ point overflow */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
++ }
++ /* oh gawd */
++ if (xe > SP_MBITS) {
++ xm <<= xe - SP_MBITS;
++ } else {
++ u32 residue;
++ int round;
++ int sticky;
++ int odd;
++
++ if (xe < -1) {
++ residue = xm;
++ round = 0;
++ sticky = residue != 0;
++ xm = 0;
++ } else {
++ /* Shifting a u32 32 times does not work,
++ * so we do it in two steps. Be aware that xe
++ * may be -1 */
++ residue = xm << (xe + 1);
++ residue <<= 31 - SP_MBITS;
++ round = (residue >> 31) != 0;
++ sticky = (residue << 1) != 0;
++ xm >>= SP_MBITS - xe;
++ }
++ odd = (xm & 0x1) != 0x0;
++ switch (ieee754_csr.rm) {
++ case IEEE754_RN:
++ if (round && (sticky || odd))
++ xm++;
++ break;
++ case IEEE754_RZ:
++ break;
++ case IEEE754_RU: /* toward +Infinity */
++ if ((round || sticky) && !xs)
++ xm++;
++ break;
++ case IEEE754_RD: /* toward -Infinity */
++ if ((round || sticky) && xs)
++ xm++;
++ break;
++ }
++ if ((xm >> 31) != 0) {
++ /* This can happen after rounding */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754si_xcpt(ieee754si_indef(), "sp_tint", x);
++ }
++ if (round || sticky)
++ SETCX(IEEE754_INEXACT);
++ }
++ if (xs)
++ return -xm;
++ else
++ return xm;
++}
++
++unsigned int ieee754sp_tuns(ieee754sp x)
++{
++ ieee754sp hb = ieee754sp_1e31();
++
++ /* what if x < 0 ?? */
++ if (ieee754sp_lt(x, hb))
++ return (unsigned)ieee754sp_tint(x);
++
++ return (unsigned)ieee754sp_tint(ieee754sp_sub(x, hb)) |
++ ((unsigned)1 << 31);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/math-emu/sp_tlong.c linux-3.4.110/arch/nds32/math-emu/sp_tlong.c
+--- linux-3.4.110.orig/arch/nds32/math-emu/sp_tlong.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/math-emu/sp_tlong.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,119 @@
++/* IEEE754 floating point arithmetic
++ * single precision
++ */
++/*
++ * MIPS floating point support
++ * Copyright (C) 1994-2000 Algorithmics Ltd.
++ * http://www.algor.co.uk
++ *
++ * ########################################################################
++ *
++ * 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.
++ *
++ * This program is distributed in the hope 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 "ieee754sp.h"
++
++s64 ieee754sp_tlong(ieee754sp x)
++{
++ COMPXDP; /* <-- need 64-bit mantissa tmp */
++
++ CLEARCX;
++
++ EXPLODEXSP;
++ FLUSHXSP;
++
++ switch (xc) {
++ case IEEE754_CLASS_SNAN:
++ case IEEE754_CLASS_QNAN:
++ case IEEE754_CLASS_INF:
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
++ case IEEE754_CLASS_ZERO:
++ return 0;
++ case IEEE754_CLASS_DNORM:
++ case IEEE754_CLASS_NORM:
++ break;
++ }
++ if (xe >= 63) {
++ /* look for valid corner case */
++ if (xe == 63 && xs && xm == SP_HIDDEN_BIT)
++ return -0x8000000000000000LL;
++ /* Set invalid. We will only use overflow for floating
++ point overflow */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
++ }
++ /* oh gawd */
++ if (xe > SP_MBITS) {
++ xm <<= xe - SP_MBITS;
++ } else if (xe < SP_MBITS) {
++ u32 residue;
++ int round;
++ int sticky;
++ int odd;
++
++ if (xe < -1) {
++ residue = xm;
++ round = 0;
++ sticky = residue != 0;
++ xm = 0;
++ } else {
++ residue = xm << (32 - SP_MBITS + xe);
++ round = (residue >> 31) != 0;
++ sticky = (residue << 1) != 0;
++ xm >>= SP_MBITS - xe;
++ }
++ odd = (xm & 0x1) != 0x0;
++ switch (ieee754_csr.rm) {
++ case IEEE754_RN:
++ if (round && (sticky || odd))
++ xm++;
++ break;
++ case IEEE754_RZ:
++ break;
++ case IEEE754_RU: /* toward +Infinity */
++ if ((round || sticky) && !xs)
++ xm++;
++ break;
++ case IEEE754_RD: /* toward -Infinity */
++ if ((round || sticky) && xs)
++ xm++;
++ break;
++ }
++ if ((xm >> 63) != 0) {
++ /* This can happen after rounding */
++ SETCX(IEEE754_INVALID_OPERATION);
++ return ieee754di_xcpt(ieee754di_indef(), "sp_tlong", x);
++ }
++ if (round || sticky)
++ SETCX(IEEE754_INEXACT);
++ }
++ if (xs)
++ return -xm;
++ else
++ return xm;
++}
++
++u64 ieee754sp_tulong(ieee754sp x)
++{
++ ieee754sp hb = ieee754sp_1e63();
++
++ /* what if x < 0 ?? */
++ if (ieee754sp_lt(x, hb))
++ return (u64) ieee754sp_tlong(x);
++
++ return (u64) ieee754sp_tlong(ieee754sp_sub(x, hb)) | (1ULL << 63);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/alignment.c linux-3.4.110/arch/nds32/mm/alignment.c
+--- linux-3.4.110.orig/arch/nds32/mm/alignment.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/alignment.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,560 @@
++/*
++ * linux/arch/nds32/mm/alignment.c
++ *
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/proc_fs.h>
++#include <linux/uaccess.h>
++
++#include <asm/unaligned.h>
++
++#ifdef CONFIG_PROC_FS
++extern struct proc_dir_entry *proc_dir_cpu;
++#endif
++
++#define DEBUG(enable, tagged, ...) \
++ do{ \
++ if (enable) { \
++ if (tagged) \
++ printk(KERN_WARNING "[ %30s() ] ", __func__); \
++ printk(KERN_WARNING __VA_ARGS__); \
++ } \
++ } while (0)
++
++#define RT(inst) (((inst) >> 20) & 0x1FUL)
++#define RA(inst) (((inst) >> 15) & 0x1FUL)
++#define RB(inst) (((inst) >> 10) & 0x1FUL)
++#define SV(inst) (((inst) >> 8) & 0x3UL)
++#define IMM(inst) (((inst) >> 0) & 0x3FFFUL)
++
++#define RA3(inst) (((inst) >> 3) & 0x7UL)
++#define RT3(inst) (((inst) >> 6) & 0x7UL)
++#define IMM3U(inst) (((inst) >> 0) & 0x7UL)
++
++#define RA5(inst) (((inst) >> 0) & 0x1FUL)
++#define RT4(inst) (((inst) >> 5) & 0xFUL)
++
++extern int (*do_unaligned_access)
++ (unsigned long entry, unsigned long addr,
++ unsigned long type, struct pt_regs * regs);
++extern int va_present(struct mm_struct *mm, unsigned long addr);
++extern int va_kernel_present(unsigned long addr);
++extern int va_readable(struct pt_regs *regs, unsigned long addr);
++extern int va_writable(struct pt_regs *regs, unsigned long addr);
++
++static int mode = 0x3;
++module_param(mode, int, 1);
++
++static inline unsigned long *idx_to_addr(struct pt_regs *regs, int idx)
++{
++ /* this should be consistent with ptrace.h */
++ if (idx >= 0 && idx <= 25) /* R0-R25 */
++ return &regs->NDS32_r0 + idx;
++ else if (idx >= 28 && idx <= 30) /* FP, GP, LP */
++ return &regs->NDS32_fp + (idx - 28);
++ else if (idx == 31) /* SP */
++ return &regs->NDS32_sp;
++ else
++ return NULL; /* cause a segfault */
++}
++
++static inline unsigned long get_inst(unsigned long addr)
++{
++ /* FIXME: consider 16-bit inst. */
++ return be32_to_cpu(get_unaligned((u32 *) addr));
++}
++
++static inline unsigned long get_data(unsigned long addr, int len)
++{
++ if (len == 4)
++ return get_unaligned((u32 *) addr);
++ else
++ return get_unaligned((u16 *) addr);
++}
++
++static inline void set_data(unsigned long addr, unsigned long val, int len)
++{
++ if (len == 4)
++ put_unaligned(val, (u32 *) addr);
++ else
++ put_unaligned(val, (u16 *) addr);
++}
++
++static inline unsigned long sign_extend(unsigned long val, int len)
++{
++ unsigned long ret = 0;
++ unsigned char *s, *t;
++ int i = 0;
++
++ val = cpu_to_le32(val);
++
++ s = (void *)&val;
++ t = (void *)&ret;
++
++ while (i++ < len)
++ *t++ = *s++;
++
++ if (((*(t - 1)) & 0x80) && (i < 4)) {
++
++ while (i++ <= 4)
++ *t++ = 0xff;
++ }
++
++ return le32_to_cpu(ret);
++}
++
++static inline int do_16(unsigned long inst, struct pt_regs *regs)
++{
++ int imm, regular, load, len, addr_mode, idx_mode;
++ unsigned long unaligned_addr, target_val, source_idx, target_idx,
++ shift = 0;
++ switch ((inst >> 9) & 0x3F) {
++
++ case 0x12: /* LHI333 */
++ imm = 1;
++ regular = 1;
++ load = 1;
++ len = 2;
++ addr_mode = 3;
++ idx_mode = 3;
++ break;
++ case 0x10: /* LWI333 */
++ imm = 1;
++ regular = 1;
++ load = 1;
++ len = 4;
++ addr_mode = 3;
++ idx_mode = 3;
++ break;
++ case 0x11: /* LWI333.bi */
++ imm = 1;
++ regular = 0;
++ load = 1;
++ len = 4;
++ addr_mode = 3;
++ idx_mode = 3;
++ break;
++ case 0x1A: /* LWI450 */
++ imm = 0;
++ regular = 1;
++ load = 1;
++ len = 4;
++ addr_mode = 5;
++ idx_mode = 4;
++ break;
++ case 0x16: /* SHI333 */
++ imm = 1;
++ regular = 1;
++ load = 0;
++ len = 2;
++ addr_mode = 3;
++ idx_mode = 3;
++ break;
++ case 0x14: /* SWI333 */
++ imm = 1;
++ regular = 1;
++ load = 0;
++ len = 4;
++ addr_mode = 3;
++ idx_mode = 3;
++ break;
++ case 0x15: /* SWI333.bi */
++ imm = 1;
++ regular = 0;
++ load = 0;
++ len = 4;
++ addr_mode = 3;
++ idx_mode = 3;
++ break;
++ case 0x1B: /* SWI450 */
++ imm = 0;
++ regular = 1;
++ load = 0;
++ len = 4;
++ addr_mode = 5;
++ idx_mode = 4;
++ break;
++
++ default:
++ return -EFAULT;
++ }
++
++ if (addr_mode == 3) {
++ unaligned_addr = *idx_to_addr(regs, RA3(inst));
++ source_idx = RA3(inst);
++ } else {
++ unaligned_addr = *idx_to_addr(regs, RA5(inst));
++ source_idx = RA5(inst);
++ }
++
++ if (idx_mode == 3)
++ target_idx = RT3(inst);
++ else
++ target_idx = RT4(inst);
++
++ if (imm)
++ shift = IMM3U(inst) * len;
++
++ if (regular)
++ unaligned_addr += shift;
++ else
++ *idx_to_addr(regs, source_idx) = unaligned_addr + shift;
++
++ if (load) {
++
++ if (!va_readable(regs, unaligned_addr))
++ return -EACCES;
++
++ if (!access_ok(VERIFY_READ, (void *)unaligned_addr, len))
++ return -EACCES;
++
++ *idx_to_addr(regs, target_idx) = get_data(unaligned_addr, len);
++ } else {
++
++ if (!va_writable(regs, unaligned_addr))
++ return -EACCES;
++
++ if (!access_ok(VERIFY_WRITE, (void *)unaligned_addr, len))
++ return -EACCES;
++
++ target_val = *idx_to_addr(regs, target_idx);
++ set_data(unaligned_addr, target_val, len);
++ }
++
++ regs->NDS32_ipc += 2;
++
++ return 0;
++}
++
++static inline int do_32(unsigned long inst, struct pt_regs *regs)
++{
++ int imm, regular, load, len, sign_ext;
++ unsigned long unsligned_addr, target_val, shift;
++
++ unsligned_addr = *idx_to_addr(regs, RA(inst));
++
++ switch ((inst >> 25) << 1) {
++
++ case 0x02: /* LHI */
++ imm = 1;
++ regular = 1;
++ load = 1;
++ len = 2;
++ sign_ext = 0;
++ break;
++ case 0x0A: /* LHI.bi */
++ imm = 1;
++ regular = 0;
++ load = 1;
++ len = 2;
++ sign_ext = 0;
++ break;
++ case 0x22: /* LHSI */
++ imm = 1;
++ regular = 1;
++ load = 1;
++ len = 2;
++ sign_ext = 1;
++ break;
++ case 0x2A: /* LHSI.bi */
++ imm = 1;
++ regular = 0;
++ load = 1;
++ len = 2;
++ sign_ext = 1;
++ break;
++ case 0x04: /* LWI */
++ imm = 1;
++ regular = 1;
++ load = 1;
++ len = 4;
++ sign_ext = 0;
++ break;
++ case 0x0C: /* LWI.bi */
++ imm = 1;
++ regular = 0;
++ load = 1;
++ len = 4;
++ sign_ext = 0;
++ break;
++ case 0x12: /* SHI */
++ imm = 1;
++ regular = 1;
++ load = 0;
++ len = 2;
++ sign_ext = 0;
++ break;
++ case 0x1A: /* SHI.bi */
++ imm = 1;
++ regular = 0;
++ load = 0;
++ len = 2;
++ sign_ext = 0;
++ break;
++ case 0x14: /* SWI */
++ imm = 1;
++ regular = 1;
++ load = 0;
++ len = 4;
++ sign_ext = 0;
++ break;
++ case 0x1C: /* SWI.bi */
++ imm = 1;
++ regular = 0;
++ load = 0;
++ len = 4;
++ sign_ext = 0;
++ break;
++
++ default:
++ switch (inst & 0xff) {
++
++ case 0x01: /* LH */
++ imm = 0;
++ regular = 1;
++ load = 1;
++ len = 2;
++ sign_ext = 0;
++ break;
++ case 0x05: /* LH.bi */
++ imm = 0;
++ regular = 0;
++ load = 1;
++ len = 2;
++ sign_ext = 0;
++ break;
++ case 0x11: /* LHS */
++ imm = 0;
++ regular = 1;
++ load = 1;
++ len = 2;
++ sign_ext = 1;
++ break;
++ case 0x15: /* LHS.bi */
++ imm = 0;
++ regular = 0;
++ load = 1;
++ len = 2;
++ sign_ext = 1;
++ break;
++ case 0x02: /* LW */
++ imm = 0;
++ regular = 1;
++ load = 1;
++ len = 4;
++ sign_ext = 0;
++ break;
++ case 0x06: /* LW.bi */
++ imm = 0;
++ regular = 0;
++ load = 1;
++ len = 4;
++ sign_ext = 0;
++ break;
++ case 0x09: /* SH */
++ imm = 0;
++ regular = 1;
++ load = 0;
++ len = 2;
++ sign_ext = 0;
++ break;
++ case 0x0D: /* SH.bi */
++ imm = 0;
++ regular = 0;
++ load = 0;
++ len = 2;
++ sign_ext = 0;
++ break;
++ case 0x0A: /* SW */
++ imm = 0;
++ regular = 1;
++ load = 0;
++ len = 4;
++ sign_ext = 0;
++ break;
++ case 0x0E: /* SW.bi */
++ imm = 0;
++ regular = 0;
++ load = 0;
++ len = 4;
++ sign_ext = 0;
++ break;
++
++ default:
++ return -EFAULT;
++ }
++ }
++
++ if (imm)
++ shift = IMM(inst) * len;
++ else
++ shift = *idx_to_addr(regs, RB(inst)) << SV(inst);
++
++ if (regular)
++ unsligned_addr += shift;
++ else
++ *idx_to_addr(regs, RA(inst)) = unsligned_addr + shift;
++
++ if (load) {
++
++ if (!va_readable(regs, unsligned_addr))
++ return -EACCES;
++
++ if (!access_ok(VERIFY_READ, (void *)unsligned_addr, len))
++ return -EACCES;
++
++ if (sign_ext)
++ *idx_to_addr(regs, RT(inst)) =
++ sign_extend(get_data(unsligned_addr, len), len);
++ else
++ *idx_to_addr(regs, RT(inst)) =
++ get_data(unsligned_addr, len);
++ } else {
++
++ if (!va_writable(regs, unsligned_addr))
++ return -EACCES;
++
++ if (!access_ok(VERIFY_WRITE, (void *)unsligned_addr, len))
++ return -EACCES;
++
++ target_val = *idx_to_addr(regs, RT(inst));
++ set_data(unsligned_addr, target_val, len);
++ }
++
++ regs->NDS32_ipc += 4;
++
++ return 0;
++}
++
++static int _do_unaligned_access(unsigned long entry, unsigned long addr,
++ unsigned long type, struct pt_regs *regs)
++{
++ unsigned long inst;
++ int ret = -EFAULT;
++
++ if (user_mode(regs)) {
++ /* user mode */
++ if (!va_present(current->mm, addr))
++ return ret;
++ } else {
++ /* kernel mode */
++ if (!va_kernel_present(addr))
++ return ret;
++ }
++
++ inst = get_inst(regs->NDS32_ipc);
++
++ DEBUG(mode & 0x04, 1,
++ "Faulting Addr: 0x%08lx, PC: 0x%08lx [ 0x%08lx ]\n", addr,
++ regs->NDS32_ipc, inst);
++
++ if ((user_mode(regs) && (mode & 0x01))
++ || (!user_mode(regs) && (mode & 0x02))) {
++
++ mm_segment_t seg = get_fs();
++
++ set_fs(KERNEL_DS);
++
++ if (inst & 0x80000000)
++ ret = do_16((inst >> 16) & 0xffff, regs);
++ else
++ ret = do_32(inst, regs);
++
++ set_fs(seg);
++ }
++
++ return ret;
++}
++
++#ifdef CONFIG_PROC_FS
++
++static int proc_alignment_read(char *page, char **start, off_t off, int count,
++ int *eof, void *data)
++{
++ char *p = page;
++ int len;
++
++ p += sprintf(p, "(0x01) User Mode: %s\n", mode & 0x01 ? "on" : "off");
++ p += sprintf(p, "(0x02) Kernel Mode: %s\n", mode & 0x02 ? "on" : "off");
++ p += sprintf(p, "(0x04) Warning: %s\n", mode & 0x04 ? "on" : "off");
++
++ len = (p - page) - off;
++ if (len < 0)
++ len = 0;
++
++ *eof = (len <= count) ? 1 : 0;
++ *start = page + off;
++
++ return len;
++}
++
++#define INPUTLEN 12 /* '0' + 'x' + 8digit + '\n' + '\0' */
++
++static int proc_alignment_write(struct file *file, const char __user * buffer,
++ unsigned long count, void *data)
++{
++ unsigned long en;
++ char *endp;
++ char inbuf[INPUTLEN];
++
++ if (count > INPUTLEN - 1)
++ return -EFAULT;
++
++ if (copy_from_user(inbuf, buffer, count))
++ return -EFAULT;
++
++ inbuf[count - 1] = '\0';
++
++ en = simple_strtoul(inbuf, &endp, 0);
++ if (en > 0x07)
++ return -EFAULT;
++
++ mode = en & 0x7;
++
++ return count;
++}
++
++#endif /* CONFIG_PROC_FS */
++
++static int __init unaligned_access_init(void)
++{
++#ifdef CONFIG_PROC_FS
++ static struct proc_dir_entry *res_alignment;
++
++ if (!proc_dir_cpu)
++ if (!(proc_dir_cpu = proc_mkdir("cpu", NULL)))
++ return -ENOMEM;
++
++ if (!
++ (res_alignment =
++ create_proc_entry("alignment", S_IWUSR | S_IRUGO, proc_dir_cpu)))
++ return -ENOMEM;
++
++ res_alignment->read_proc = proc_alignment_read;
++ res_alignment->write_proc = proc_alignment_write;
++#endif
++ do_unaligned_access = _do_unaligned_access;
++
++ return 0;
++}
++
++static void __exit unaligned_access_exit(void)
++{
++#ifdef CONFIG_PROC_FS
++ remove_proc_entry("alignment", proc_dir_cpu);
++#endif
++ do_unaligned_access = NULL;
++}
++
++MODULE_AUTHOR("Roy Lee");
++MODULE_DESCRIPTION("Unaligned Access Handler");
++MODULE_LICENSE("GPL");
++
++module_init(unaligned_access_init);
++module_exit(unaligned_access_exit);
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/cacheflush.c linux-3.4.110/arch/nds32/mm/cacheflush.c
+--- linux-3.4.110.orig/arch/nds32/mm/cacheflush.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/cacheflush.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,355 @@
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/pagemap.h>
++#include <linux/module.h>
++#include <asm/cacheflush.h>
++#include <asm/proc-fns.h>
++#include <asm/shmparam.h>
++#include <asm/cache_info.h>
++
++extern struct cache_info L1_cache_info[2];
++
++#ifdef CONFIG_CPU_CACHE_NONALIASING
++void flush_cache_mm(struct mm_struct *mm)
++{
++}
++
++void flush_cache_dup_mm(struct mm_struct *mm)
++{
++}
++
++void flush_cache_range(struct vm_area_struct *vma,
++ unsigned long start, unsigned long end)
++{
++}
++
++void flush_cache_page(struct vm_area_struct *vma,
++ unsigned long addr, unsigned long pfn)
++{
++}
++
++void flush_cache_vmap(unsigned long start, unsigned long end)
++{
++}
++
++void flush_cache_vunmap(unsigned long start, unsigned long end)
++{
++}
++
++void flush_dcache_page(struct page *page)
++{
++ struct address_space *mapping;
++
++ if (!PageHighMem(page)) {
++ mapping = page_mapping(page);
++ if (mapping && !mapping_mapped(mapping))
++ set_bit(PG_dcache_dirty, &page->flags);
++ else
++ cpu_dcache_wbinval_page((unsigned long)
++ page_address(page));
++ } else {
++ unsigned long kaddr = (unsigned long)kmap_atomic(page);
++ cpu_dcache_wbinval_page(kaddr);
++ kunmap_atomic((void *)kaddr);
++ }
++}
++
++void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
++ unsigned long vaddr, void *dst, void *src, int len)
++{
++ unsigned long line_size, start, end;
++
++ memcpy(dst, src, len);
++ if (vma->vm_flags & VM_EXEC) {
++ line_size = L1_cache_info[DCACHE].line_size;
++ start = (unsigned long)dst & ~(line_size - 1);
++ end =
++ ((unsigned long)dst + len + line_size - 1) & ~(line_size -
++ 1);
++ cpu_cache_wbinval_range(start, end, 1);
++ }
++}
++
++void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
++ unsigned long vaddr, void *dst, void *src, int len)
++{
++ memcpy(dst, src, len);
++}
++
++void flush_icache_range(unsigned long start, unsigned long end)
++{
++ cpu_cache_wbinval_range(start, end, 1);
++}
++
++void flush_icache_page(struct vm_area_struct *vma, struct page *page)
++{
++}
++
++void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
++ pte_t * pte)
++{
++ struct page *page;
++ unsigned long pfn = pte_pfn(*pte);
++
++ if (!pfn_valid(pfn))
++ return;
++
++ if (vma->vm_mm == current->active_mm)
++ asm("mtsr %1, $mr2\ndsb\n"
++ "tlbop %0, RWR\nisb\n"
++ ::"r"(*pte), "r"(addr));
++
++ page = pfn_to_page(pfn);
++
++ if ((test_and_clear_bit(PG_dcache_dirty, &page->flags)) ||
++ (vma->vm_flags & VM_EXEC)) {
++
++ if (!PageHighMem(page)) {
++ cpu_cache_wbinval_page((unsigned long)
++ page_address(page),
++ vma->vm_flags & VM_EXEC);
++ } else {
++ unsigned long kaddr = (unsigned long)kmap_atomic(page);
++ cpu_cache_wbinval_page(kaddr, vma->vm_flags & VM_EXEC);
++ kunmap_atomic((void *)kaddr);
++ }
++ }
++}
++#else
++int va_present(struct mm_struct *mm, unsigned long addr);
++
++static inline unsigned long aliasing(unsigned long addr, unsigned long page)
++{
++ return ((addr & PAGE_MASK) ^ page) & (REALSHMLBA - 1);
++}
++
++static inline unsigned long kremap0(unsigned long uaddr, unsigned long pa)
++{
++ unsigned long kaddr, pte;
++
++#define BASE_ADDR0 0xffffc000
++ kaddr = BASE_ADDR0 | (uaddr & L1_cache_info[DCACHE].aliasing_mask);
++ pte = (pa | PAGE_KERNEL);
++ asm("mtsr %1, $mr2\ndsb\n"
++ "tlbop %0, RWLK\nisb\n"
++ ::"r"(pte), "r"(kaddr));
++ return kaddr;
++}
++
++static inline void kunmap01(unsigned long kaddr)
++{
++ asm volatile ("tlbop %0, UNLK\n\t"
++ "tlbop %0, INV\n\t"
++ ::"r" (kaddr));
++}
++
++static inline unsigned long kremap1(unsigned long uaddr, unsigned long pa)
++{
++ unsigned long kaddr, pte;
++
++#define BASE_ADDR1 0xffff8000
++ kaddr = BASE_ADDR1 | (uaddr & L1_cache_info[DCACHE].aliasing_mask);
++ pte = (pa | PAGE_KERNEL);
++ asm("mtsr %1, $mr2\ndsb\n"
++ "tlbop %0, RWLK\nisb\n"
++ ::"r"(pte), "r"(kaddr));
++ return kaddr;
++}
++
++void flush_cache_mm(struct mm_struct *mm)
++{
++ cpu_dcache_wbinval_all();
++ cpu_icache_inval_all();
++}
++
++void flush_cache_dup_mm(struct mm_struct *mm)
++{
++}
++
++void flush_cache_range(struct vm_area_struct *vma,
++ unsigned long start, unsigned long end)
++{
++ if ((end - start) > 8 * PAGE_SIZE) {
++ cpu_dcache_wbinval_all();
++ if (vma->vm_flags & VM_EXEC)
++ cpu_icache_inval_all();
++ return;
++ }
++
++ while (start < end) {
++ if (va_present(vma->vm_mm, start))
++ cpu_cache_wbinval_page(start, vma->vm_flags & VM_EXEC);
++ start += PAGE_SIZE;
++ }
++}
++
++void flush_cache_page(struct vm_area_struct *vma,
++ unsigned long addr, unsigned long pfn)
++{
++ unsigned long vto, flags;
++
++ local_irq_save(flags);
++ vto = kremap0(addr, pfn << PAGE_SHIFT);
++ cpu_cache_wbinval_page(vto, vma->vm_flags & VM_EXEC);
++ kunmap01(vto);
++ local_irq_restore(flags);
++}
++
++void flush_cache_vmap(unsigned long start, unsigned long end)
++{
++ cpu_dcache_wbinval_all();
++}
++
++void flush_cache_vunmap(unsigned long start, unsigned long end)
++{
++ cpu_dcache_wbinval_all();
++}
++
++void copy_user_highpage(struct page *to, struct page *from,
++ unsigned long vaddr, struct vm_area_struct *vma)
++{
++ unsigned long vto, vfrom, flags, kto, kfrom, pfrom, pto;
++ kto = ((unsigned long)page_address(to) & PAGE_MASK);
++ kfrom = ((unsigned long)page_address(from) & PAGE_MASK);
++ pto = page_to_phys(to);
++ pfrom = page_to_phys(from);
++
++ if (aliasing(vaddr, (unsigned long)kfrom))
++ cpu_dcache_wb_page((unsigned long)kfrom);
++ if (aliasing(vaddr, (unsigned long)kto))
++ cpu_dcache_inval_page((unsigned long)kto);
++ local_irq_save(flags);
++ vto = kremap0(vaddr, pto);
++ vfrom = kremap1(vaddr, pfrom);
++ copy_page((void *)vto, (void *)vfrom);
++ kunmap01(vfrom);
++ kunmap01(vto);
++ local_irq_restore(flags);
++}
++
++EXPORT_SYMBOL(copy_user_highpage);
++
++void clear_user_highpage(struct page *page, unsigned long vaddr)
++{
++ unsigned long vto, flags, kto;
++
++ kto = ((unsigned long)page_address(page) & PAGE_MASK);
++
++ local_irq_save(flags);
++ if (aliasing(kto, vaddr) && kto != 0) {
++ cpu_dcache_inval_page(kto);
++ cpu_icache_inval_page(kto);
++ }
++ vto = kremap0(vaddr, page_to_phys(page));
++ clear_page((void *)vto);
++ kunmap01(vto);
++ local_irq_restore(flags);
++}
++
++EXPORT_SYMBOL(clear_user_highpage);
++
++void flush_dcache_page(struct page *page)
++{
++ struct address_space *mapping;
++
++ mapping = page_mapping(page);
++ if (mapping && !mapping_mapped(mapping))
++ set_bit(PG_dcache_dirty, &page->flags);
++ else {
++ int i, pc;
++ unsigned long vto, kaddr, flags;
++ cpu_dcache_wbinval_page((unsigned long)page_address(page));
++ kaddr = (unsigned long)page_address(page);
++ pc = CACHE_SET(DCACHE) * CACHE_LINE_SIZE(DCACHE) / PAGE_SIZE;
++ for (i = 0; i < pc; i++) {
++ local_irq_save(flags);
++ vto = kremap0(kaddr + i * PAGE_SIZE, __pa(kaddr));
++ cpu_dcache_wbinval_page(vto);
++ kunmap01(vto);
++ local_irq_restore(flags);
++ }
++ }
++}
++
++void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
++ unsigned long vaddr, void *dst, void *src, int len)
++{
++ unsigned long line_size, start, end, vto, flags;
++
++ local_irq_save(flags);
++ vto = kremap0(vaddr, page_to_phys(page));
++ dst = (void *)(vto | (vaddr & (PAGE_SIZE - 1)));
++ memcpy(dst, src, len);
++ if (vma->vm_flags & VM_EXEC) {
++ line_size = L1_cache_info[DCACHE].line_size;
++ start = (unsigned long)dst & ~(line_size - 1);
++ end =
++ ((unsigned long)dst + len + line_size - 1) & ~(line_size -
++ 1);
++ cpu_cache_wbinval_range(start, end, 1);
++ }
++ kunmap01(vto);
++ local_irq_restore(flags);
++}
++
++void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
++ unsigned long vaddr, void *dst, void *src, int len)
++{
++ unsigned long vto, flags;
++
++ local_irq_save(flags);
++ vto = kremap0(vaddr, page_to_phys(page));
++ src = (void *)(vto | (vaddr & (PAGE_SIZE - 1)));
++ memcpy(dst, src, len);
++ kunmap01(vto);
++ local_irq_restore(flags);
++}
++
++void flush_anon_page(struct vm_area_struct *vma,
++ struct page *page, unsigned long vaddr)
++{
++ if (!PageAnon(page))
++ return;
++
++ if (vma->vm_mm != current->active_mm)
++ return;
++
++ cpu_cache_wbinval_page(vaddr & PAGE_MASK, vma->vm_flags & VM_EXEC);
++}
++
++void flush_kernel_dcache_page(struct page *page)
++{
++ cpu_dcache_wbinval_page((unsigned long)page_address(page));
++}
++
++void flush_icache_range(unsigned long start, unsigned long end)
++{
++ cpu_cache_wbinval_range(start, end, 1);
++}
++
++void flush_icache_page(struct vm_area_struct *vma, struct page *page)
++{
++}
++
++void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
++ pte_t * pte)
++{
++ struct page *page;
++ unsigned long pfn = pte_pfn(*pte);
++
++ if (!pfn_valid(pfn))
++ return;
++
++ if (vma->vm_mm == current->active_mm) {
++ asm("mtsr %1, $mr2\ndsb\n"
++ "tlbop %0, RWR\nisb\n"
++ ::"r"(*pte), "r"(addr));
++ }
++
++ page = pfn_to_page(pfn);
++ if (test_and_clear_bit(PG_dcache_dirty, &page->flags) ||
++ (vma->vm_flags & VM_EXEC))
++ cpu_dcache_wbinval_page((unsigned long)page_address(page));
++}
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/cctl.c linux-3.4.110/arch/nds32/mm/cctl.c
+--- linux-3.4.110.orig/arch/nds32/mm/cctl.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/cctl.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,284 @@
++/*
++ * linux/arch/nds32/mm/cctl.c
++ *
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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 "cctl.h"
++
++#define DEBUG( enable, tagged, ...) \
++ do{ \
++ if( enable){ \
++ if( tagged) \
++ printk( "[ %30s() ] ", __func__); \
++ printk( __VA_ARGS__); \
++ } \
++ } while( 0)
++
++static int debug = 1;
++module_param(debug, int, 0);
++
++static int proc_read_cache_en(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++
++ if (!strncmp(data, "ic_en", 7))
++ return sprintf(page, "I-cache: %s\n",
++ (GET_CACHE_CTL() & CACHE_CTL_mskIC_EN) ?
++ "Enabled" : "Disabled");
++ else
++ return sprintf(page, "D-cache: %s\n",
++ (GET_CACHE_CTL() & CACHE_CTL_mskDC_EN) ?
++ "Enabled" : "Disabled");
++}
++
++static int proc_write_cache_en(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++
++ unsigned long en, saved_gie;
++ char inbuf[INPUTLEN];
++
++ if (count > INPUTLEN - 1)
++ count = INPUTLEN - 1;
++
++ if (copy_from_user(inbuf, buffer, count))
++ return -EFAULT;
++
++ inbuf[count] = '\0';
++
++ if (!sscanf(inbuf, "%lu", &en) || en > 1)
++ return -EFAULT;
++
++ GIE_SAVE(&saved_gie);
++
++ if (!strncmp(data, "ic_en", 7)) {
++
++ if (en && !(GET_CACHE_CTL() & CACHE_CTL_mskIC_EN)) {
++
++ SET_CACHE_CTL(GET_CACHE_CTL() | CACHE_CTL_mskIC_EN);
++ DEBUG(debug, 1, "I-cache: Enabled\n");
++ } else if (!en && (GET_CACHE_CTL() & CACHE_CTL_mskIC_EN)) {
++
++ SET_CACHE_CTL(GET_CACHE_CTL() & ~CACHE_CTL_mskIC_EN);
++ cpu_icache_inval_all();
++ DEBUG(debug, 1, "I-cache: Disabled\n");
++ }
++ } else {
++ if (en && !(GET_CACHE_CTL() & CACHE_CTL_mskDC_EN)) {
++
++ SET_CACHE_CTL(GET_CACHE_CTL() | CACHE_CTL_mskDC_EN);
++ DEBUG(debug, 1, "D-cache: Enabled\n");
++ } else if (!en && (GET_CACHE_CTL() & CACHE_CTL_mskDC_EN)) {
++
++ SET_CACHE_CTL(GET_CACHE_CTL() & ~CACHE_CTL_mskDC_EN);
++ cpu_dcache_wbinval_all();
++ DEBUG(debug, 1, "D-cache: Disabled\n");
++ }
++ }
++
++ GIE_RESTORE(saved_gie);
++
++ return count;
++}
++
++struct entry_struct proc_table_cache_en[] = {
++
++ {"ic_en", 0644, proc_read_cache_en, proc_write_cache_en},
++ {"dc_en", 0644, proc_read_cache_en, proc_write_cache_en},
++ {NULL, 0, NULL, NULL}
++};
++
++static int sprint_cache_sdz(char *buf, unsigned long size, unsigned long way,
++ unsigned sdz)
++{
++
++ return sprintf(buf, "[%c] %luK x %lu\n[%c] %luK x %lu\n"
++ "[%c] %luK x %lu\n[%c] %luK x %lu\n",
++ (sdz == 0) ? '*' : ' ', (size / 1024), way,
++ (sdz == 1) ? '*' : ' ', (size / 1024), way / 2,
++ (sdz == 2) ? '*' : ' ', (size / 1024) / 2, way,
++ (sdz == 3) ? '*' : ' ', (size / 1024) / 2, way / 2);
++}
++
++static int proc_read_cache_sdz(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++
++ if (!strncmp(data, "ic_sdz", 7)) {
++
++ return sprint_cache_sdz(page,
++ CACHE_LINE_SIZE(ICACHE) *
++ CACHE_SET(ICACHE), CACHE_WAY(ICACHE),
++ (GET_SDZ_CTL() & SDZ_CTL_mskICDZ) >>
++ SDZ_CTL_offICDZ);
++ } else {
++ return sprint_cache_sdz(page,
++ CACHE_LINE_SIZE(DCACHE) *
++ CACHE_SET(DCACHE), CACHE_WAY(DCACHE),
++ (GET_SDZ_CTL() & SDZ_CTL_mskDCDZ) >>
++ SDZ_CTL_offDCDZ);
++ }
++}
++
++static int proc_write_cache_sdz(struct file *file, const char *buffer,
++ unsigned long count, void *data)
++{
++
++ unsigned long mode, saved_gie, saved_cctl;
++ char inbuf[INPUTLEN];
++
++ if (count > INPUTLEN - 1)
++ count = INPUTLEN - 1;
++
++ if (copy_from_user(inbuf, buffer, count))
++ return -EFAULT;
++
++ inbuf[count] = '\0';
++
++ if (!sscanf(inbuf, "%lu", &mode) || mode > 3)
++ return -EFAULT;
++
++ GIE_SAVE(&saved_gie);
++
++ saved_cctl = GET_CACHE_CTL();
++ DEBUG(debug, 1, "saved_gie: %ld, saved_cctl: 0x%08lx\n", saved_gie,
++ saved_cctl);
++
++ if (!strncmp(data, "ic_sdz", 7)) {
++
++ DEBUG(debug, 1, "IC_SDZ: mode %ld\n", mode);
++
++ if (mode == 2 || mode == 3) {
++
++ if (CACHE_LINE_SIZE(ICACHE) * CACHE_SET(ICACHE) / 2 <
++ 4096) {
++
++ GIE_RESTORE(saved_gie);
++ DEBUG(debug, 1, "Error: way size < 4096\n");
++ return -1;
++ }
++ }
++
++ /* turn off and flush cache */
++ DEBUG(debug, 1, "turning off cache\n");
++ SET_CACHE_CTL(saved_cctl & ~CACHE_CTL_mskIC_EN);
++ DEBUG(debug, 1, "flushing cache\n");
++ cpu_icache_inval_all();
++
++ /* perform down size operation */
++ DEBUG(debug, 1, "downsizing cache\n");
++ SET_SDZ_CTL((GET_SDZ_CTL() & ~SDZ_CTL_mskICDZ) |
++ (mode << SDZ_CTL_offICDZ));
++ } else {
++
++ DEBUG(debug, 1, "DC_SDZ: mode %ld\n", mode);
++
++ if (mode == 2 || mode == 3) {
++
++ if (CACHE_LINE_SIZE(DCACHE) * CACHE_SET(DCACHE) / 2 <
++ 4096) {
++
++ GIE_RESTORE(saved_gie);
++ DEBUG(debug, 1, "Error: way size < 4096\n");
++ return -1;
++ }
++ }
++
++ /* turn off and flush cache */
++ DEBUG(debug, 1, "turning off cache\n");
++ SET_CACHE_CTL(saved_cctl & ~CACHE_CTL_mskDC_EN);
++ DEBUG(debug, 1, "flushing cache\n");
++ cpu_dcache_wbinval_all();
++
++ /* perform down size operation */
++ DEBUG(debug, 1, "downsizing cache\n");
++ SET_SDZ_CTL((GET_SDZ_CTL() & ~SDZ_CTL_mskDCDZ) |
++ (mode << SDZ_CTL_offDCDZ));
++ }
++
++ /* turn on cache ( if it was enabled) */
++ DEBUG(debug, 1, "restoring saved_cctl : 0x%08lx\n", saved_cctl);
++ SET_CACHE_CTL(saved_cctl);
++
++ DEBUG(debug, 1, "restoring saved_git: %ld\n", saved_gie);
++ GIE_RESTORE(saved_gie);
++
++ return count;
++}
++
++struct entry_struct proc_table_cache_sdz[] = {
++
++ {"ic_sdz", 0644, proc_read_cache_sdz, proc_write_cache_sdz},
++ {"dc_sdz", 0644, proc_read_cache_sdz, proc_write_cache_sdz},
++ {NULL, 0, NULL, NULL}
++};
++
++static struct proc_dir_entry *proc_cctl;
++
++static void create_seq_entry(struct entry_struct *e, mode_t mode,
++ struct proc_dir_entry *parent)
++{
++
++ struct proc_dir_entry *entry = create_proc_entry(e->name, mode, parent);
++
++ if (entry) {
++
++ entry->read_proc = e->readop;
++ entry->write_proc = e->writeop;
++ entry->data = e->name;
++ }
++}
++
++static void install_proc_table(struct entry_struct *table)
++{
++
++ while (table->name) {
++
++ create_seq_entry(table, table->perm, proc_cctl);
++ table++;
++ }
++}
++
++static void remove_proc_table(struct entry_struct *table)
++{
++
++ while (table->name) {
++
++ remove_proc_entry(table->name, proc_cctl);
++ table++;
++ }
++}
++
++static int __init init_cctl(void)
++{
++
++ DEBUG(debug, 1, "CCTL module registered\n");
++
++ proc_cctl = proc_mkdir("cctl", NULL);
++
++ install_proc_table(proc_table_cache_en);
++ install_proc_table(proc_table_cache_sdz);
++
++ return 0;
++}
++
++static void __exit cleanup_cctl(void)
++{
++
++ remove_proc_table(proc_table_cache_sdz);
++ remove_proc_table(proc_table_cache_en);
++ remove_proc_entry("cctl", NULL);
++
++ DEBUG(debug, 1, "CCTL module unregistered\n");
++}
++
++module_init(init_cctl);
++module_exit(cleanup_cctl);
++
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("Userspace Cache Control Module");
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/cctl.h linux-3.4.110/arch/nds32/mm/cctl.h
+--- linux-3.4.110.orig/arch/nds32/mm/cctl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/cctl.h 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,22 @@
++#ifndef CCTL_H
++#define CCTL_H
++
++#include <linux/module.h>
++#include <linux/blkdev.h>
++#include <linux/proc_fs.h>
++#include <asm/nds32.h>
++
++#define INPUTLEN 32
++
++extern void cpu_icache_flush(void);
++extern void cpu_dcache_flush(void);
++
++struct entry_struct{
++
++ char *name;
++ int perm;
++ read_proc_t *readop;
++ write_proc_t *writeop;
++};
++
++#endif /* CCTL_H */
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/consistent.c linux-3.4.110/arch/nds32/mm/consistent.c
+--- linux-3.4.110.orig/arch/nds32/mm/consistent.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/consistent.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,448 @@
++/*
++ * linux/arch/nds32/mm/consistent.c
++ *
++ * Copyright (C) 2000-2004 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * DMA uncached mapping support.
++ */
++#include <linux/dma-mapping.h>
++#include <linux/sched.h>
++#include <linux/slab.h>
++#include <asm/cacheflush.h>
++#include <asm/tlbflush.h>
++#include <asm/pgtable.h>
++#include <linux/module.h>
++
++/*
++ * This is the page table (2MB) covering uncached, DMA consistent allocations
++ */
++static pte_t *consistent_pte;
++static DEFINE_RAW_SPINLOCK(consistent_lock);
++
++/*
++ * VM region handling support.
++ *
++ * This should become something generic, handling VM region allocations for
++ * vmalloc and similar (ioremap, module space, etc).
++ *
++ * I envisage vmalloc()'s supporting vm_struct becoming:
++ *
++ * struct vm_struct {
++ * struct vm_region region;
++ * unsigned long flags;
++ * struct page **pages;
++ * unsigned int nr_pages;
++ * unsigned long phys_addr;
++ * };
++ *
++ * get_vm_area() would then call vm_region_alloc with an appropriate
++ * struct vm_region head (eg):
++ *
++ * struct vm_region vmalloc_head = {
++ * .vm_list = LIST_HEAD_INIT(vmalloc_head.vm_list),
++ * .vm_start = VMALLOC_START,
++ * .vm_end = VMALLOC_END,
++ * };
++ *
++ * However, vmalloc_head.vm_start is variable (typically, it is dependent on
++ * the amount of RAM found at boot time.) I would imagine that get_vm_area()
++ * would have to initialise this each time prior to calling vm_region_alloc().
++ */
++struct arch_vm_region {
++ struct list_head vm_list;
++ unsigned long vm_start;
++ unsigned long vm_end;
++ struct page *vm_pages;
++};
++
++static struct arch_vm_region consistent_head = {
++ .vm_list = LIST_HEAD_INIT(consistent_head.vm_list),
++ .vm_start = CONSISTENT_BASE,
++ .vm_end = CONSISTENT_END,
++};
++
++static struct arch_vm_region *vm_region_alloc(struct arch_vm_region *head,
++ size_t size, int gfp)
++{
++ unsigned long addr = head->vm_start, end = head->vm_end - size;
++ unsigned long flags;
++ struct arch_vm_region *c, *new;
++
++ new = kmalloc(sizeof(struct arch_vm_region), gfp);
++ if (!new)
++ goto out;
++
++ raw_spin_lock_irqsave(&consistent_lock, flags);
++
++ list_for_each_entry(c, &head->vm_list, vm_list) {
++ if ((addr + size) < addr)
++ goto nospc;
++ if ((addr + size) <= c->vm_start)
++ goto found;
++ addr = c->vm_end;
++ if (addr > end)
++ goto nospc;
++ }
++
++found:
++ /*
++ * Insert this entry _before_ the one we found.
++ */
++ list_add_tail(&new->vm_list, &c->vm_list);
++ new->vm_start = addr;
++ new->vm_end = addr + size;
++
++ raw_spin_unlock_irqrestore(&consistent_lock, flags);
++ return new;
++
++nospc:
++ raw_spin_unlock_irqrestore(&consistent_lock, flags);
++ kfree(new);
++out:
++ return NULL;
++}
++
++static struct arch_vm_region *vm_region_find(struct arch_vm_region *head,
++ unsigned long addr)
++{
++ struct arch_vm_region *c;
++
++ list_for_each_entry(c, &head->vm_list, vm_list) {
++ if (c->vm_start == addr)
++ goto out;
++ }
++ c = NULL;
++out:
++ return c;
++}
++
++#ifdef CONFIG_HUGETLB_PAGE
++#error ARM Coherent DMA allocator does not (yet) support huge TLB
++#endif
++
++static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t * handle,
++ int gfp, pgprot_t prot)
++{
++ struct page *page;
++ struct arch_vm_region *c;
++ unsigned long order;
++ unsigned int i;
++ u64 mask = ISA_DMA_THRESHOLD, limit;
++
++ if (!consistent_pte) {
++ printk(KERN_ERR "%s: not initialised\n", __func__);
++ dump_stack();
++ return NULL;
++ }
++
++ if (dev) {
++ mask = dev->coherent_dma_mask;
++
++ /*
++ * Sanity check the DMA mask - it must be non-zero, and
++ * must be able to be satisfied by a DMA allocation.
++ */
++ if (mask == 0) {
++ dev_warn(dev, "coherent DMA mask is unset\n");
++ goto no_page;
++ }
++
++ if ((~mask) & ISA_DMA_THRESHOLD) {
++ dev_warn(dev, "coherent DMA mask %#llx is smaller "
++ "than system GFP_DMA mask %#llx\n",
++ mask, (unsigned long long)ISA_DMA_THRESHOLD);
++ goto no_page;
++ }
++ }
++
++ /*
++ * Sanity check the allocation size.
++ */
++ size = PAGE_ALIGN(size);
++ limit = (mask + 1) & ~mask;
++ if ((limit && size >= limit) ||
++ size >= (CONSISTENT_END - CONSISTENT_BASE)) {
++ printk(KERN_WARNING "coherent allocation too big "
++ "(requested %#x mask %#llx)\n", size, mask);
++ goto no_page;
++ }
++
++ order = get_order(size);
++
++ if (mask != 0xffffffff)
++ gfp |= GFP_DMA;
++
++ page = alloc_pages(gfp, order);
++ if (!page)
++ goto no_page;
++
++ for (i = 1; i < (1 << order); i++)
++ atomic_set(&(page + i)->_count, 1);
++
++ /*
++ * Invalidate any data that might be lurking in the
++ * kernel direct-mapped region for device DMA.
++ */
++ {
++ unsigned long kaddr = (unsigned long)page_address(page);
++ memset(page_address(page), 0, size);
++ cpu_dma_wbinval_range(kaddr, kaddr + size);
++ }
++
++ /*
++ * Allocate a virtual address in the consistent mapping region.
++ */
++ c = vm_region_alloc(&consistent_head, size,
++ gfp & ~(__GFP_DMA | __GFP_HIGHMEM));
++ if (c) {
++ pte_t *pte = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
++ struct page *end = page + (1 << order);
++
++ c->vm_pages = page;
++
++ /*
++ * Set the "dma handle"
++ */
++ *handle = page_to_dma(dev, page);
++
++ do {
++ BUG_ON(!pte_none(*pte));
++
++ /*
++ * x86 does not mark the pages reserved...
++ */
++ SetPageReserved(page);
++ set_pte(pte, mk_pte(page, prot));
++ page++;
++ pte++;
++ } while (size -= PAGE_SIZE);
++
++ /*
++ * Free the otherwise unused pages.
++ */
++ while (page < end) {
++ __free_page(page);
++ page++;
++ }
++
++ return (void *)c->vm_start;
++ }
++
++ if (page)
++ __free_pages(page, order);
++no_page:
++ *handle = ~0;
++ return NULL;
++}
++
++/*
++ * Allocate DMA-coherent memory space and return both the kernel remapped
++ * virtual and bus address for that space.
++ */
++void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t * handle,
++ gfp_t gfp)
++{
++ return __dma_alloc(dev, size, handle, gfp,
++ pgprot_noncached(PAGE_KERNEL));
++}
++
++EXPORT_SYMBOL(dma_alloc_coherent);
++
++/*
++ * Allocate a writecombining region, in much the same way as
++ * dma_alloc_coherent above.
++ */
++void *dma_alloc_writecombine(struct device *dev, size_t size,
++ dma_addr_t * handle, gfp_t gfp)
++{
++ return __dma_alloc(dev, size, handle, gfp,
++ pgprot_writecombine(PAGE_KERNEL));
++}
++
++EXPORT_SYMBOL(dma_alloc_writecombine);
++
++static int dma_mmap(struct device *dev, struct vm_area_struct *vma,
++ void *cpu_addr, dma_addr_t dma_addr, size_t size)
++{
++ unsigned long flags, user_size, kern_size;
++ struct arch_vm_region *c;
++ int ret = -ENXIO;
++
++ user_size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
++
++ raw_spin_lock_irqsave(&consistent_lock, flags);
++ c = vm_region_find(&consistent_head, (unsigned long)cpu_addr);
++ raw_spin_unlock_irqrestore(&consistent_lock, flags);
++
++ if (c) {
++ unsigned long off = vma->vm_pgoff;
++
++ kern_size = (c->vm_end - c->vm_start) >> PAGE_SHIFT;
++
++ if (off < kern_size && user_size <= (kern_size - off)) {
++ vma->vm_flags |= VM_RESERVED;
++ ret = remap_pfn_range(vma, vma->vm_start,
++ page_to_pfn(c->vm_pages) + off,
++ user_size << PAGE_SHIFT,
++ vma->vm_page_prot);
++ }
++ }
++
++ return ret;
++}
++
++int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
++ void *cpu_addr, dma_addr_t dma_addr, size_t size)
++{
++ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
++ return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
++}
++
++EXPORT_SYMBOL(dma_mmap_coherent);
++
++int dma_mmap_writecombine(struct device *dev, struct vm_area_struct *vma,
++ void *cpu_addr, dma_addr_t dma_addr, size_t size)
++{
++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
++ return dma_mmap(dev, vma, cpu_addr, dma_addr, size);
++}
++
++EXPORT_SYMBOL(dma_mmap_writecombine);
++
++/*
++ * free a page as defined by the above mapping.
++ */
++void dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
++ dma_addr_t handle)
++{
++ struct arch_vm_region *c;
++ unsigned long flags, addr;
++ pte_t *ptep;
++
++ size = PAGE_ALIGN(size);
++
++ raw_spin_lock_irqsave(&consistent_lock, flags);
++
++ c = vm_region_find(&consistent_head, (unsigned long)cpu_addr);
++ if (!c)
++ goto no_area;
++
++ if ((c->vm_end - c->vm_start) != size) {
++ printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n",
++ __func__, c->vm_end - c->vm_start, size);
++ dump_stack();
++ size = c->vm_end - c->vm_start;
++ }
++
++ ptep = consistent_pte + CONSISTENT_OFFSET(c->vm_start);
++ addr = c->vm_start;
++ do {
++ pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep);
++ unsigned long pfn;
++
++ ptep++;
++ addr += PAGE_SIZE;
++
++ if (!pte_none(pte) && pte_present(pte)) {
++ pfn = pte_pfn(pte);
++
++ if (pfn_valid(pfn)) {
++ struct page *page = pfn_to_page(pfn);
++
++ /*
++ * x86 does not mark the pages reserved...
++ */
++ ClearPageReserved(page);
++
++ __free_page(page);
++ continue;
++ }
++ }
++
++ printk(KERN_CRIT "%s: bad page in kernel page table\n",
++ __func__);
++ } while (size -= PAGE_SIZE);
++
++ flush_tlb_kernel_range(c->vm_start, c->vm_end);
++
++ list_del(&c->vm_list);
++
++ raw_spin_unlock_irqrestore(&consistent_lock, flags);
++
++ kfree(c);
++ return;
++
++no_area:
++ raw_spin_unlock_irqrestore(&consistent_lock, flags);
++ printk(KERN_ERR "%s: trying to free invalid coherent area: %p\n",
++ __func__, cpu_addr);
++ dump_stack();
++}
++
++EXPORT_SYMBOL(dma_free_coherent);
++
++/*
++ * Initialise the consistent memory allocation.
++ */
++static int __init consistent_init(void)
++{
++ pgd_t *pgd;
++ pmd_t *pmd;
++ pte_t *pte;
++ int ret = 0;
++
++ do {
++ pgd = pgd_offset(&init_mm, CONSISTENT_BASE);
++ pmd = pmd_alloc(&init_mm, pgd, CONSISTENT_BASE);
++ if (!pmd) {
++ printk(KERN_ERR "%s: no pmd tables\n", __func__);
++ ret = -ENOMEM;
++ break;
++ }
++ /* The first level mapping may be created in somewhere.
++ * It's not necessary to warn here. */
++ /* WARN_ON(!pmd_none(*pmd)); */
++
++ pte = pte_alloc_kernel(pmd, CONSISTENT_BASE);
++ if (!pte) {
++ ret = -ENOMEM;
++ break;
++ }
++
++ consistent_pte = pte;
++ } while (0);
++
++ return ret;
++}
++
++core_initcall(consistent_init);
++
++/*
++ * Make an area consistent for devices.
++ */
++void consistent_sync(void *vaddr, size_t size, int direction)
++{
++ unsigned long start = (unsigned long)vaddr;
++ unsigned long end = start + size;
++
++ switch (direction) {
++ case DMA_FROM_DEVICE: /* invalidate only */
++ cpu_dma_inval_range(start, end);
++ break;
++ case DMA_TO_DEVICE: /* writeback only */
++ cpu_dma_wb_range(start, end);
++ break;
++ case DMA_BIDIRECTIONAL: /* writeback and invalidate */
++ cpu_dma_wbinval_range(start, end);
++ break;
++ default:
++ BUG();
++ }
++}
++
++EXPORT_SYMBOL(consistent_sync);
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/extable.c linux-3.4.110/arch/nds32/mm/extable.c
+--- linux-3.4.110.orig/arch/nds32/mm/extable.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/extable.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,18 @@
++/*
++ * linux/arch/nds32/mm/extable.c
++ *
++ * Copyright (C) 2009 Andes Technology Corporation
++ */
++#include <linux/module.h>
++#include <asm/uaccess.h>
++
++int fixup_exception(struct pt_regs *regs)
++{
++ const struct exception_table_entry *fixup;
++
++ fixup = search_exception_tables(instruction_pointer(regs));
++ if (fixup)
++ regs->NDS32_ipc = fixup->fixup;
++
++ return fixup != NULL;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/fault.c linux-3.4.110/arch/nds32/mm/fault.c
+--- linux-3.4.110.orig/arch/nds32/mm/fault.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/fault.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,507 @@
++/*
++ * linux/arch/arm/mm/fault.c
++ *
++ * Copyright (C) 1995 Linus Torvalds
++ * Modifications for ARM processor (c) 1995-2004 Russell King
++ *
++ * 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.
++ */
++/* ============================================================================
++ *
++ * linux/arch/nds32/mm/fault.c
++ *
++ * Copyright (C) 2007 Andes Technology Corporation
++ * This file is part of Linux and should be licensed under the GPL.
++ * See the file COPYING for conditions for redistribution.
++ *
++ * Abstract:
++ *
++ * This program is for NDS32 architecture, referred from ARM's
++ * implementation.
++ *
++ * Revision History:
++ *
++ * Nov.26.2007 Initial ported by Tom, Shawn, and Steven,
++ * patched for KGDB and refined code by Harry.
++ *
++ * Note:
++ *
++ * ============================================================================
++ */
++#include <linux/module.h>
++#include <linux/signal.h>
++#include <linux/ptrace.h>
++#include <linux/mm.h>
++#include <linux/init.h>
++#include <linux/hardirq.h>
++
++#include <asm/system.h>
++#include <asm/pgtable.h>
++#include <asm/tlbflush.h>
++#include <asm/uaccess.h>
++
++#include "fault.h"
++
++/*
++ * This is useful to dump out the page tables associated with
++ * 'addr' in mm 'mm'.
++ */
++void show_pte(struct mm_struct *mm, unsigned long addr)
++{
++ pgd_t *pgd;
++ if (!mm)
++ mm = &init_mm;
++
++ printk(KERN_ALERT "pgd = %p\n", mm->pgd);
++ pgd = pgd_offset(mm, addr);
++ printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
++
++ do {
++ pmd_t *pmd;
++
++ if (pgd_none(*pgd))
++ break;
++
++ if (pgd_bad(*pgd)) {
++ printk("(bad)");
++ break;
++ }
++
++ pmd = pmd_offset(pgd, addr);
++#if PTRS_PER_PMD != 1
++ printk(", *pmd=%08lx", pmd_val(*pmd));
++#endif
++
++ if (pmd_none(*pmd))
++ break;
++
++ if (pmd_bad(*pmd)) {
++ printk("(bad)");
++ break;
++ }
++#ifndef CONFIG_HIGHMEM
++ {
++ pte_t *pte;
++ /* We must not map this if we have highmem enabled */
++ pte = pte_offset_map(pmd, addr);
++ printk(", *pte=%08lx", pte_val(*pte));
++ pte_unmap(pte);
++ }
++#endif
++ } while (0);
++
++ printk("\n");
++}
++
++/*
++ * Oops. The kernel tried to access some page that wasn't present.
++ */
++static void
++__do_kernel_fault(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
++ struct pt_regs *regs)
++{
++ /*
++ * Are we prepared to handle this kernel fault?
++ */
++ if (fixup_exception(regs))
++ return;
++
++ /*
++ * No handler, we'll have to terminate things with extreme prejudice.
++ */
++ bust_spinlocks(1);
++ printk(KERN_ALERT
++ "__do_kernel_fault: Unable to handle kernel %s at virtual address %08lx\n",
++ (addr < PAGE_SIZE) ? "NULL pointer dereference" :
++ "paging request", addr);
++
++ show_pte(mm, addr);
++ die("Oops", regs, fsr);
++ bust_spinlocks(0);
++ do_exit(SIGKILL);
++}
++
++/*
++ * Something tried to access memory that isn't in our memory map..
++ * User mode accesses just cause a SIGSEGV
++ */
++static void
++__do_user_fault(struct task_struct *tsk, unsigned long addr,
++ unsigned int fsr, int code, struct pt_regs *regs)
++{
++ struct siginfo si;
++
++#ifdef CONFIG_DEBUG_USER
++ if (user_debug & UDBG_SEGV) {
++ printk(KERN_DEBUG
++ "%s: unhandled page fault at 0x%08lx, code 0x%03x\n",
++ tsk->comm, addr, fsr);
++ show_pte(tsk->mm, addr);
++ show_regs(regs);
++ }
++#endif
++
++ tsk->thread.address = addr;
++ tsk->thread.error_code = fsr;
++ tsk->thread.trap_no = 14;
++ si.si_signo = SIGSEGV;
++ si.si_errno = 0;
++ si.si_code = code;
++ si.si_addr = (void __user *)addr;
++ force_sig_info(SIGSEGV, &si, tsk);
++}
++
++void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
++{
++ struct task_struct *tsk = current;
++ struct mm_struct *mm = tsk->active_mm;
++
++ /*
++ * If we are in kernel mode at this point, we
++ * have no context to handle this fault with.
++ */
++ if (user_mode(regs)) {
++ __do_user_fault(tsk, addr, fsr, SEGV_MAPERR, regs);
++ } else {
++ __do_kernel_fault(mm, addr, fsr, regs);
++ }
++}
++
++#define VM_FAULT_BADMAP 0x010000
++#define VM_FAULT_BADACCESS 0x020000
++
++void do_page_fault(unsigned long entry, unsigned long addr,
++ unsigned int error_code, struct pt_regs *regs)
++{
++ struct task_struct *tsk;
++ struct mm_struct *mm;
++ struct vm_area_struct *vma;
++ siginfo_t info;
++ int fault;
++ unsigned int mask = VM_READ | VM_WRITE | VM_EXEC;
++ unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
++
++ error_code = error_code & (ITYPE_mskINST | ITYPE_mskETYPE);
++ tsk = current;
++ mm = tsk->mm;
++ info.si_code = SEGV_MAPERR;
++ /*
++ * We fault-in kernel-space virtual memory on-demand. The
++ * 'reference' page table is init_mm.pgd.
++ *
++ * NOTE! We MUST NOT take any locks for this case. We may
++ * be in an interrupt or a critical region, and should
++ * only copy the information from the master page table,
++ * nothing more.
++ */
++ if (addr >= TASK_SIZE) {
++ if (user_mode(regs))
++ goto bad_area_nosemaphore;
++
++ if (addr >= TASK_SIZE && addr < VMALLOC_END && (entry == 2))
++ goto vmalloc_fault;
++ else
++ goto no_context;
++ }
++
++ /*
++ * If we're in an interrupt or have no user
++ * context, we must not take the fault..
++ */
++ if (unlikely(in_atomic() || !mm))
++ goto no_context;
++
++ /*
++ * As per x86, we may deadlock here. However, since the kernel only
++ * validly references user space from well defined areas of the code,
++ * we can bug out early if this is from code which shouldn't.
++ */
++ if (unlikely(!down_read_trylock(&mm->mmap_sem))) {
++ if (!user_mode(regs) &&
++ !search_exception_tables(instruction_pointer(regs)))
++ goto no_context;
++retry:
++ down_read(&mm->mmap_sem);
++ } else {
++ /*
++ * The above down_read_trylock() might have succeeded in which
++ * case, we'll have missed the might_sleep() from down_read().
++ */
++ might_sleep();
++#ifdef CONFIG_DEBUG_VM
++ if (!user_mode(regs) &&
++ !search_exception_tables(instruction_pointer(regs)))
++ goto no_context;
++#endif
++ }
++
++ vma = find_vma(mm, addr);
++
++ if (unlikely(!vma))
++ goto bad_area;
++
++ if (vma->vm_start <= addr)
++ goto good_area;
++
++ if (unlikely(!(vma->vm_flags & VM_GROWSDOWN)))
++ goto bad_area;
++
++ if (unlikely(expand_stack(vma, addr)))
++ goto bad_area;
++
++ /*
++ * Ok, we have a good vm_area for this memory access, so
++ * we can handle it..
++ */
++
++good_area:
++ info.si_code = SEGV_ACCERR;
++
++ /* first do some preliminary protection checks */
++ if (entry == 2) {
++ if (error_code & ITYPE_mskINST)
++ mask = VM_EXEC;
++ else {
++ mask = VM_READ | VM_WRITE;
++ if (vma->vm_flags & VM_WRITE)
++ flags |= FAULT_FLAG_WRITE;
++ }
++ } else if (entry == 3) {
++ switch (error_code & ITYPE_mskETYPE) {
++ case RD_PROT:
++ mask = VM_READ;
++ break;
++ case WRT_PROT:
++ mask = VM_WRITE;
++ flags |= FAULT_FLAG_WRITE;
++ break;
++ case NOEXEC:
++ mask = VM_EXEC;
++ break;
++ case PAGE_MODIFY:
++ mask = VM_WRITE;
++ flags |= FAULT_FLAG_WRITE;
++ break;
++ case ACC_BIT:
++ BUG();
++ default:
++ break;
++ }
++
++ }
++ if (!(vma->vm_flags & mask))
++ goto bad_area;
++
++ /*
++ * If for any reason at all we couldn't handle the fault,
++ * make sure we exit gracefully rather than endlessly redo
++ * the fault.
++ */
++
++ fault = handle_mm_fault(mm, vma, addr, flags);
++
++ /*
++ * If we need to retry but a fatal signal is pending, handle the
++ * signal first. We do not need to release the mmap_sem because it
++ * would already be released in __lock_page_or_retry in mm/filemap.c.
++ */
++ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current))
++ return;
++
++ if (unlikely(fault & VM_FAULT_ERROR)) {
++ if (fault & VM_FAULT_OOM)
++ goto out_of_memory;
++ else if (fault & VM_FAULT_SIGBUS)
++ goto do_sigbus;
++ BUG();
++ }
++
++ /*
++ * Major/minor page fault accounting is only done on the initial
++ * attempt. If we go through a retry, it is extremely likely that the
++ * page will be found in page cache at that point.
++ */
++ if (flags & FAULT_FLAG_ALLOW_RETRY) {
++ if (fault & VM_FAULT_MAJOR)
++ tsk->maj_flt++;
++ else
++ tsk->min_flt++;
++ if (fault & VM_FAULT_RETRY) {
++ flags &= ~FAULT_FLAG_ALLOW_RETRY;
++ flags |= FAULT_FLAG_TRIED;
++
++ /* No need to up_read(&mm->mmap_sem) as we would
++ * have already released it in __lock_page_or_retry
++ * in mm/filemap.c.
++ */
++ goto retry;
++ }
++ }
++
++ up_read(&mm->mmap_sem);
++ return;
++
++ /*
++ * Something tried to access memory that isn't in our memory map..
++ * Fix it, but check if it's kernel or user first..
++ */
++bad_area:
++ up_read(&mm->mmap_sem);
++
++bad_area_nosemaphore:
++
++ /* User mode accesses just cause a SIGSEGV */
++
++ if (user_mode(regs)) {
++ tsk->thread.address = addr;
++ tsk->thread.error_code = error_code;
++ tsk->thread.trap_no = 14;
++ info.si_signo = SIGSEGV;
++ info.si_errno = 0;
++ /* info.si_code has been set above */
++ info.si_addr = (void *)addr;
++ force_sig_info(SIGSEGV, &info, tsk);
++ return;
++ }
++
++no_context:
++
++ /* Are we prepared to handle this kernel fault?
++ *
++ * (The kernel has valid exception-points in the source
++ * when it acesses user-memory. When it fails in one
++ * of those points, we find it in a table and do a jump
++ * to some fixup code that loads an appropriate error
++ * code)
++ */
++
++ {
++ const struct exception_table_entry *entry;
++
++ if ((entry =
++ search_exception_tables(instruction_pointer(regs))) !=
++ NULL) {
++ /* Adjust the instruction pointer in the stackframe */
++ instruction_pointer(regs) = entry->fixup;
++ return;
++ }
++ }
++
++ /*
++ * Oops. The kernel tried to access some bad page. We'll have to
++ * terminate things with extreme prejudice.
++ */
++
++ bust_spinlocks(1);
++ printk(KERN_ALERT
++ "Unable to handle kernel %s at virtual address %08lx\n",
++ (addr < PAGE_SIZE) ? "NULL pointer dereference" :
++ "paging request", addr);
++
++ show_pte(mm, addr);
++ die("Oops", regs, error_code);
++ bust_spinlocks(0);
++ do_exit(SIGKILL);
++
++ /* TODO: verify this necessity */
++ return;
++
++ /*
++ * We ran out of memory, or some other thing happened to us that made
++ * us unable to handle the page fault gracefully.
++ */
++
++out_of_memory:
++ up_read(&mm->mmap_sem);
++ if (!user_mode(regs))
++ goto no_context;
++ pagefault_out_of_memory();
++ return;
++
++do_sigbus:
++ up_read(&mm->mmap_sem);
++
++ /* Kernel mode? Handle exceptions or die */
++ if (!user_mode(regs))
++ goto no_context;
++
++ /*
++ * Send a sigbus
++ */
++ tsk->thread.address = addr;
++ tsk->thread.error_code = error_code;
++ tsk->thread.trap_no = 14;
++ info.si_signo = SIGBUS;
++ info.si_errno = 0;
++ info.si_code = BUS_ADRERR;
++ info.si_addr = (void *)addr;
++ force_sig_info(SIGBUS, &info, tsk);
++
++ return;
++
++vmalloc_fault:
++ {
++ /*
++ * Synchronize this task's top level page-table
++ * with the 'reference' page table.
++ *
++ * Use current_pgd instead of tsk->active_mm->pgd
++ * since the latter might be unavailable if this
++ * code is executed in a misfortunately run irq
++ * (like inside schedule() between switch_mm and
++ * switch_to...).
++ */
++
++ unsigned int index = pgd_index(addr);
++ pgd_t *pgd, *pgd_k;
++ pud_t *pud, *pud_k;
++ pmd_t *pmd, *pmd_k;
++ pte_t *pte_k;
++
++ pgd = (pgd_t *) __va(GET_L1_PPTB()) + index;
++ pgd_k = init_mm.pgd + index;
++
++ if (!pgd_present(*pgd_k))
++ goto no_context;
++
++ pud = pud_offset(pgd, addr);
++ pud_k = pud_offset(pgd_k, addr);
++ if (!pud_present(*pud_k))
++ goto no_context;
++
++ pmd = pmd_offset(pud, addr);
++ pmd_k = pmd_offset(pud_k, addr);
++ if (!pmd_present(*pmd_k))
++ goto no_context;
++
++ if (!pmd_present(*pmd)) {
++ set_pmd(pmd, *pmd_k);
++ /* TODO: need to do a cache flush like arm,
++ * maybe add at header file */
++ } else
++
++ BUG_ON(pmd_page(*pmd) != pmd_page(*pmd_k));
++
++ /*
++ * Since the vmalloc area is global, we don't
++ * need to copy individual PTE's, it is enough to
++ * copy the pgd pointer into the pte page of the
++ * root task. If that is there, we'll find our pte if
++ * it exists.
++ */
++
++ /* Make sure the actual PTE exists as well to
++ * catch kernel vmalloc-area accesses to non-mapped
++ * addres. If we don't do this, this will just
++ * silently loop forever.
++ */
++
++ pte_k = pte_offset_kernel(pmd_k, addr);
++ if (!pte_present(*pte_k))
++ goto no_context;
++
++ return;
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/fault.h linux-3.4.110/arch/nds32/mm/fault.h
+--- linux-3.4.110.orig/arch/nds32/mm/fault.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/fault.h 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,5 @@
++void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs);
++
++void show_pte(struct mm_struct *mm, unsigned long addr);
++
++unsigned long search_exception_table(unsigned long addr);
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/highmem.c linux-3.4.110/arch/nds32/mm/highmem.c
+--- linux-3.4.110.orig/arch/nds32/mm/highmem.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/highmem.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,76 @@
++#include <linux/export.h>
++#include <linux/highmem.h>
++#include <linux/sched.h>
++#include <linux/smp.h>
++#include <linux/interrupt.h>
++#include <linux/bootmem.h>
++#include <asm/fixmap.h>
++#include <asm/tlbflush.h>
++
++void *kmap(struct page *page)
++{
++ unsigned long vaddr;
++ might_sleep();
++ if (!PageHighMem(page))
++ return page_address(page);
++ vaddr = (unsigned long)kmap_high(page);
++ return (void *)vaddr;
++}
++
++EXPORT_SYMBOL(kmap);
++
++void kunmap(struct page *page)
++{
++ BUG_ON(in_interrupt());
++ if (!PageHighMem(page))
++ return;
++ kunmap_high(page);
++}
++
++EXPORT_SYMBOL(kunmap);
++
++/*
++ * kmap_atomic/kunmap_atomic is significantly faster than kmap/kunmap because
++ * no global lock is needed and because the kmap code must perform a global TLB
++ * invalidation when the kmap pool wraps.
++ *
++ * However when holding an atomic kmap is is not legal to sleep, so atomic
++ * kmaps are appropriate for short, tight code paths only.
++ */
++void *kmap_atomic(struct page *page)
++{
++ unsigned int idx;
++ unsigned long vaddr, pte;
++ int type;
++
++ pagefault_disable();
++ if (!PageHighMem(page))
++ return page_address(page);
++
++ type = kmap_atomic_idx_push();
++
++ idx = type + KM_TYPE_NR * smp_processor_id();
++ vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
++ pte = (page_to_pfn(page) << PAGE_SHIFT) | (PAGE_KERNEL);
++ asm volatile ("mtsr %0, $TLB_VPN\n\t"
++ "dsb\n\t"
++ "tlbop %1, RWLK\n\t"
++ "isb\n\t"
++ ::"r" (vaddr), "r"(pte));
++ return (void *)vaddr;
++}
++
++EXPORT_SYMBOL(kmap_atomic);
++
++void __kunmap_atomic(void *kvaddr)
++{
++ if (kvaddr >= (void *)FIXADDR_START) {
++ kmap_atomic_idx_pop();
++ asm volatile ("tlbop %0, UNLK\n\t"
++ "tlbop %0, INV\n\t"
++ ::"r" (kvaddr));
++ }
++ pagefault_enable();
++}
++
++EXPORT_SYMBOL(__kunmap_atomic);
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/init.c linux-3.4.110/arch/nds32/mm/init.c
+--- linux-3.4.110.orig/arch/nds32/mm/init.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/init.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,438 @@
++/*
++ * linux/arch/nds32/mm/init.c
++ *
++ * Copyright (C) 1995-2002 Russell King
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++#include <linux/kernel.h>
++#include <linux/errno.h>
++#include <linux/swap.h>
++#include <linux/init.h>
++#include <linux/bootmem.h>
++#include <linux/mman.h>
++#include <linux/nodemask.h>
++#include <linux/initrd.h>
++#include <linux/highmem.h>
++#include <linux/memblock.h>
++
++#include <asm/sections.h>
++#include <asm/mach-types.h>
++#include <asm/hardware.h>
++#include <asm/setup.h>
++#include <asm/tlb.h>
++#include <asm/page.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++
++#include "mm.h"
++#include "../../kernel/signal.h"
++
++#define TABLE_SIZE (PTRS_PER_PTE * sizeof(pte_t))
++
++DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
++DEFINE_SPINLOCK(anon_alias_lock);
++extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
++extern unsigned long phys_initrd_start;
++extern unsigned long phys_initrd_size;
++
++/*
++ * empty_zero_page is a special page that is used for
++ * zero-initialized data and COW.
++ */
++struct page *empty_zero_page;
++
++void show_mem(unsigned int flags)
++{
++ int free = 0, total = 0, reserved = 0;
++ int shared = 0, cached = 0, slab = 0, node;
++
++ printk("Mem-info:\n");
++ show_free_areas(flags);
++ printk("Free swap: %6ldkB\n", nr_swap_pages << (PAGE_SHIFT - 10));
++
++ for_each_online_node(node) {
++ struct page *page, *end;
++
++ page = NODE_MEM_MAP(node);
++ end = page + NODE_DATA(node)->node_spanned_pages;
++
++ do {
++ total++;
++ if (PageReserved(page))
++ reserved++;
++ else if (PageSwapCache(page))
++ cached++;
++ else if (PageSlab(page))
++ slab++;
++ else if (!page_count(page))
++ free++;
++ else
++ shared += page_count(page) - 1;
++ page++;
++ } while (page < end);
++ }
++
++ printk("%d pages of RAM\n", total);
++ printk("%d free pages\n", free);
++ printk("%d reserved pages\n", reserved);
++ printk("%d slab pages\n", slab);
++ printk("%d pages shared\n", shared);
++ printk("%d pages swap cached\n", cached);
++}
++
++struct node_info {
++ unsigned int start;
++ unsigned int end;
++ int bootmap_pages;
++};
++
++#define O_PFN_DOWN(x) ((x) >> PAGE_SHIFT)
++#define V_PFN_DOWN(x) O_PFN_DOWN(__pa(x))
++
++#define O_PFN_UP(x) (PAGE_ALIGN(x) >> PAGE_SHIFT)
++#define V_PFN_UP(x) O_PFN_UP(__pa(x))
++
++#define PFN_SIZE(x) ((x) >> PAGE_SHIFT)
++#define PFN_RANGE(s,e) PFN_SIZE(PAGE_ALIGN((unsigned long)(e)) - \
++ (((unsigned long)(s)) & PAGE_MASK))
++#ifdef CONFIG_EARLY_PRINTK
++#include <asm/fixmap.h>
++
++/*
++ * Using tlbop to create an early I/O mapping
++ */
++void __iomem *__init early_io_map(phys_addr_t pa)
++{
++ unsigned long va;
++ pa &= PAGE_MASK;
++ pa += pgprot_val(PAGE_DEVICE);
++ va = fix_to_virt(FIX_EARLY_DEBUG);
++ /* insert and lock this page to tlb entry directly */
++ asm volatile ("mtsr %0, $TLB_VPN\n\t"
++ "dsb\n\t"
++ "tlbop %1, RWLK\n\t" "isb\n\t"::"r" (va), "r"(pa));
++ return (void __iomem *)va;
++}
++
++int __init early_io_unmap(void)
++{
++ unsigned long va;
++ va = fix_to_virt(FIX_EARLY_DEBUG);
++ asm volatile ("tlbop %0, UNLK\n\t"
++ "tlbop %0, INV\n\t" "isb\n\t"::"r" (va));
++ return 0;
++}
++
++late_initcall(early_io_unmap);
++#endif
++
++static void __init zone_sizes_init(void)
++{
++ unsigned long zones_size[MAX_NR_ZONES];
++
++ /* Clear the zone sizes */
++ memset(zones_size, 0, sizeof(zones_size));
++
++ zones_size[ZONE_NORMAL] = max_low_pfn;
++#ifdef CONFIG_HIGHMEM
++ zones_size[ZONE_HIGHMEM] = max_pfn;
++#endif
++ free_area_init_nodes(zones_size);
++
++}
++
++/*
++ * Map all physical memory under high_memory into kernel's address space.
++ *
++ * This is explicitly coded for two-level page tables, so if you need
++ * something else then this needs to change.
++ */
++static void __init map_ram(void)
++{
++ unsigned long v, p, e;
++ pgd_t *pge;
++ pud_t *pue;
++ pmd_t *pme;
++ pte_t *pte;
++ /* These mark extents of read-only kernel pages...
++ * ...from vmlinux.lds.S
++ */
++
++ p = (u32) memblock_start_of_DRAM() & PAGE_MASK;
++ e = min((u32) memblock_end_of_DRAM(), (u32) __pa(high_memory));
++
++ v = (u32) __va(p);
++ pge = pgd_offset_k(v);
++
++ while (p < e) {
++ int j;
++ pue = pud_offset(pge, v);
++ pme = pmd_offset(pue, v);
++
++ if ((u32) pue != (u32) pge || (u32) pme != (u32) pge) {
++ panic("%s: Kernel hardcoded for "
++ "two-level page tables", __func__);
++ }
++
++ /* Alloc one page for holding PTE's... */
++ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++ set_pmd(pme, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
++
++ /* Fill the newly allocated page with PTE'S */
++ for (j = 0; p < e && j < PTRS_PER_PTE;
++ v += PAGE_SIZE, p += PAGE_SIZE, j++, pte++) {
++ /* Create mapping between p and v. */
++ /* TODO: more fine grant for page access permission */
++ set_pte(pte, __pte(p + pgprot_val(PAGE_KERNEL)));
++ }
++
++ pge++;
++ }
++}
++
++static void __init fixedrange_init(void)
++{
++ unsigned long vaddr, phys, prot;
++ pgd_t *pgd;
++ pud_t *pud;
++ pmd_t *pmd;
++ pte_t *pte;
++
++ /*
++ * Fixed mappings:
++ */
++ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1);
++ pgd = swapper_pg_dir + pgd_index(vaddr);
++ pud = pud_offset(pgd, vaddr);
++ pmd = pmd_offset(pud, vaddr);
++ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++ set_pmd(pmd, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
++
++ /* create return_syscall mapping. */
++ vaddr = __fix_to_virt(FIX_RETURN_SYSCALL);
++ phys = RETURN_SYSCALL_PA_BASE;
++ prot = PAGE_UXKRWX_V2;
++ pte = pte_offset_kernel(pmd, vaddr);
++ set_pte(pte, pfn_pte(phys >> PAGE_SHIFT, prot));
++
++#ifdef CONFIG_HIGHMEM
++ /*
++ * Permanent kmaps:
++ */
++ vaddr = PKMAP_BASE;
++
++ pgd = swapper_pg_dir + pgd_index(vaddr);
++ pud = pud_offset(pgd, vaddr);
++ pmd = pmd_offset(pud, vaddr);
++ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
++ set_pmd(pmd, __pmd(__pa(pte) + _PAGE_KERNEL_TABLE));
++ pkmap_page_table = pte;
++#endif /* CONFIG_HIGHMEM */
++}
++
++/*
++ * paging_init() sets up the page tables, initialises the zone memory
++ * maps, and sets up the zero page, bad page and bad page tables.
++ */
++void __init paging_init(struct machine_desc *mdesc)
++{
++ void *zero_page;
++ int i;
++
++ printk(KERN_INFO "Setting up paging and PTEs.\n");
++
++#ifdef CONFIG_BLK_DEV_INITRD
++ if (phys_initrd_size) {
++ /* assume initrd is put on node 0 */
++ reserve_bootmem_node(NODE_DATA(0), phys_initrd_start,
++ phys_initrd_size, BOOTMEM_DEFAULT);
++ initrd_start = __phys_to_virt(phys_initrd_start);
++ initrd_end = initrd_start + phys_initrd_size;
++ printk(KERN_INFO
++ "initrd_start at 0x%08lx, initrd_end at 0x%08lx\n",
++ initrd_start, initrd_end);
++ }
++#endif
++
++ /* clear out the init_mm.pgd that will contain the kernel's mappings */
++ for (i = 0; i < PTRS_PER_PGD; i++)
++ swapper_pg_dir[i] = __pgd(1);
++
++ map_ram();
++
++ if (mdesc->map_io)
++ mdesc->map_io();
++
++ fixedrange_init();
++
++ /* allocate space for empty_zero_page */
++ zero_page = alloc_bootmem_low_pages(PAGE_SIZE);
++ memset(zero_page, 0, PAGE_SIZE);
++
++ zone_sizes_init();
++
++ empty_zero_page = virt_to_page(zero_page);
++#ifdef CONFIG_NO_KERNEL_LARGE_PAGE
++ SET_MMU_CTL(GET_MMU_CTL() & ~0x400);
++#endif
++#ifdef CONFIG_SMP
++ cpu_dcache_wbinval_all();
++#endif
++ flush_dcache_page(empty_zero_page);
++}
++
++static inline int free_area(unsigned long addr, unsigned long end, char *s)
++{
++ unsigned int size = (end - addr) >> 10;
++ int pages = 0;
++
++ for (; addr < end; addr += PAGE_SIZE) {
++ struct page *page = virt_to_page(addr);
++ ClearPageReserved(page);
++ init_page_count(page);
++ free_page(addr);
++ totalram_pages++;
++ pages++;
++ }
++
++ if (size && s)
++ printk(KERN_INFO "free_area: Freeing %s memory: %dK\n", s,
++ size);
++
++ return pages;
++}
++
++/* Free the reserved page into the buddy system, so it gets managed. */
++static inline void __free_reserved_page(struct page *page)
++{
++ ClearPageReserved(page);
++ init_page_count(page);
++ __free_page(page);
++}
++
++#ifdef CONFIG_HIGHMEM
++void free_highmem_page(struct page *page)
++{
++ __free_reserved_page(page);
++ totalram_pages++;
++ totalhigh_pages++;
++}
++#endif
++
++static inline void __init free_highmem(void)
++{
++#ifdef CONFIG_HIGHMEM
++ unsigned long pfn;
++ for (pfn = PFN_UP(__pa(high_memory)); pfn < max_pfn; pfn++) {
++ phys_addr_t paddr = (phys_addr_t) pfn << PAGE_SHIFT;
++ if (!memblock_is_reserved(paddr))
++ free_highmem_page(pfn_to_page(pfn));
++ }
++#endif
++}
++
++static void __init set_max_mapnr_init(void)
++{
++ max_mapnr = max_pfn;
++}
++
++/*
++ * mem_init() marks the free areas in the mem_map and tells us how much
++ * memory is free. This is done after various parts of the system have
++ * claimed their memory after the kernel image.
++ */
++void __init mem_init(void)
++{
++ phys_addr_t memory_start = memblock_start_of_DRAM();
++ BUG_ON(!mem_map);
++ set_max_mapnr_init();
++
++ free_highmem();
++
++ /* this will put all low memory onto the freelists */
++ totalram_pages += free_all_bootmem();
++
++ printk(KERN_INFO "virtual kernel memory layout:\n"
++ " fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
++#ifdef CONFIG_HIGHMEM
++ " pkmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
++#endif
++ " consist : 0x%08lx - 0x%08lx (%4ld MB)\n"
++ " vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n"
++ " lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n"
++ " .init : 0x%08lx - 0x%08lx (%4ld kB)\n"
++ " .data : 0x%08lx - 0x%08lx (%4ld kB)\n"
++ " .text : 0x%08lx - 0x%08lx (%4ld kB)\n",
++ FIXADDR_START, FIXADDR_TOP, (FIXADDR_TOP - FIXADDR_START) >> 10,
++#ifdef CONFIG_HIGHMEM
++ PKMAP_BASE, PKMAP_BASE + LAST_PKMAP * PAGE_SIZE,
++ (LAST_PKMAP * PAGE_SIZE) >> 10,
++#endif
++ CONSISTENT_BASE, CONSISTENT_END,
++ ((CONSISTENT_END) - (CONSISTENT_BASE)) >> 20, VMALLOC_START,
++ (unsigned long)VMALLOC_END, (VMALLOC_END - VMALLOC_START) >> 20,
++ (unsigned long)__va(memory_start), (unsigned long)high_memory,
++ ((unsigned long)high_memory -
++ (unsigned long)__va(memory_start)) >> 20,
++ (unsigned long)&__init_begin, (unsigned long)&__init_end,
++ ((unsigned long)&__init_end -
++ (unsigned long)&__init_begin) >> 10, (unsigned long)&_etext,
++ (unsigned long)&_edata,
++ ((unsigned long)&_edata - (unsigned long)&_etext) >> 10,
++ (unsigned long)&_text, (unsigned long)&_etext,
++ ((unsigned long)&_etext - (unsigned long)&_text) >> 10);
++
++ /*
++ * Check boundaries twice: Some fundamental inconsistencies can
++ * be detected at build time already.
++ */
++#define __FIXADDR_TOP (-PAGE_SIZE)
++#ifdef CONFIG_HIGHMEM
++ BUILD_BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE > FIXADDR_START);
++ BUILD_BUG_ON((CONSISTENT_END) > PKMAP_BASE);
++#endif
++ BUILD_BUG_ON(VMALLOC_END > CONSISTENT_BASE);
++#define high_memory (-128UL << 20)
++ BUILD_BUG_ON(VMALLOC_START >= VMALLOC_END);
++#undef high_memory
++#undef __FIXADDR_TOP
++
++#ifdef CONFIG_HIGHMEM
++ BUG_ON(PKMAP_BASE + LAST_PKMAP * PAGE_SIZE > FIXADDR_START);
++ BUG_ON(CONSISTENT_END > PKMAP_BASE);
++#endif
++ BUG_ON(VMALLOC_END > CONSISTENT_BASE);
++ BUG_ON(VMALLOC_START >= VMALLOC_END);
++ BUG_ON((unsigned long)high_memory > VMALLOC_START);
++
++ return;
++}
++
++void free_initmem(void)
++{
++ free_area((unsigned long)(&__init_begin),
++ (unsigned long)(&__init_end), "init");
++}
++
++#ifdef CONFIG_BLK_DEV_INITRD
++static int keep_initrd;
++
++void free_initrd_mem(unsigned long start, unsigned long end)
++{
++ if (!keep_initrd)
++ free_area(start, end, "initrd");
++}
++
++static int __init keepinitrd_setup(char *__unused)
++{
++ keep_initrd = 1;
++ return 1;
++}
++
++__setup("keepinitrd", keepinitrd_setup);
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/ioremap.c linux-3.4.110/arch/nds32/mm/ioremap.c
+--- linux-3.4.110.orig/arch/nds32/mm/ioremap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/ioremap.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,89 @@
++/*
++ * linux/arch/nds32/mm/ioremap.c
++ *
++ * Re-map IO memory to kernel address space so that we can access it.
++ *
++ * (C) Copyright 1995 1996 Linus Torvalds
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * Hacked for ARM by Phil Blundell <philb@gnu.org>
++ * Hacked to allow all architectures to build, and various cleanups
++ * by Russell King
++ *
++ * This allows a driver to remap an arbitrary region of bus memory into
++ * virtual space. One should *only* use readl, writel, memcpy_toio and
++ * so on with such remapped areas.
++ *
++ * Because the ARM only has a 32-bit address space we can't address the
++ * whole of the (physical) PCI space at once. PCI huge-mode addressing
++ * allows us to circumvent this restriction by splitting PCI space into
++ * two 2GB chunks and mapping only one at a time into processor memory.
++ * We use MMU protection domains to trap any attempt to access the bank
++ * that is not currently mapped. (This isn't fully implemented yet.)
++ */
++#include <linux/module.h>
++#include <linux/vmalloc.h>
++#include <linux/io.h>
++#include <asm/cacheflush.h>
++
++/*
++ * Remap an arbitrary physical address space into the kernel virtual
++ * address space. Needed when the kernel wants to access high addresses
++ * directly.
++ *
++ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
++ * have to convert them into an offset in a page-aligned mapping, but the
++ * caller shouldn't need to know that small detail.
++ *
++ * 'flags' are the extra L_PTE_ flags that you want to specify for this
++ * mapping. See include/asm-arm/proc-armv/pgtable.h for more information.
++ */
++void __iomem *__ioremap(unsigned long phys_addr, size_t size,
++ unsigned long flags, unsigned long align)
++{
++ struct vm_struct *area;
++ unsigned long addr, offset, last_addr;
++ pgprot_t prot;
++
++ /* Don't allow wraparound or zero size */
++ last_addr = phys_addr + size - 1;
++ if (!size || last_addr < phys_addr)
++ return NULL;
++
++ /*
++ * Mappings have to be page-aligned
++ */
++ offset = phys_addr & ~PAGE_MASK;
++ phys_addr &= PAGE_MASK;
++ size = PAGE_ALIGN(last_addr + 1) - phys_addr;
++
++ /*
++ * Ok, go for it..
++ */
++ area = get_vm_area(size, VM_IOREMAP);
++ if (!area)
++ return NULL;
++
++ area->phys_addr = phys_addr;
++ addr = (unsigned long)area->addr;
++ /* TODO: verify this value for ioremap */
++ prot = __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D |
++ _PAGE_G | _PAGE_C_DEV | flags);
++ /* TODO: verify this use generic ioremap_page_range instead of
++ * self's remap_area_pages */
++ if (ioremap_page_range(addr, addr + size, phys_addr, prot)) {
++ vunmap((void *)addr);
++ return NULL;
++ }
++ return (__force void __iomem *)(offset + (char *)addr);
++
++}
++
++EXPORT_SYMBOL(__ioremap);
++
++void __iounmap(void __iomem * addr)
++{
++ vunmap((void *)(PAGE_MASK & (unsigned long)addr));
++}
++
++EXPORT_SYMBOL(__iounmap);
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/Makefile linux-3.4.110/arch/nds32/mm/Makefile
+--- linux-3.4.110.orig/arch/nds32/mm/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/Makefile 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,24 @@
++#
++# Makefile for the linux arm-specific parts of the memory manager.
++#
++
++obj-y := consistent.o extable.o \
++ fault.o init.o ioremap.o mmap.o \
++ mm-nds32.o cacheflush.o
++
++obj-y += proc-n12.o
++obj-$(CONFIG_CCTL) += cctl.o
++obj-$(CONFIG_ALIGNMENT_TRAP) += alignment.o
++ifneq ($(CONFIG_CPU_NO_CONTEXT_ID), y)
++obj-y += tlb.o
++endif
++gcc_ver :=$(shell $(CC) -E -dM -xc /dev/null | grep __VERSION__ | sed 's/\#define __VERSION__ //')
++ifeq ($(shell expr `echo $(gcc_ver)` \>= 4.9.2 ), 1)
++CFLAGS_proc-n12.o += -fomit-frame-pointer
++else
++CFLAGS_proc-n12.o += -fomit-frame-pointer -mno-16bit
++endif
++obj-$(CONFIG_HIGHMEM) += highmem.o
++ifdef CONFIG_FUNCTION_TRACER
++CFLAGS_REMOVE_proc-n12.o = -pg
++endif
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/mmap.c linux-3.4.110/arch/nds32/mm/mmap.c
+--- linux-3.4.110.orig/arch/nds32/mm/mmap.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/mmap.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,101 @@
++/*
++ * linux/arch/nds32/mm/mmap.c
++ *
++ * Copyright (C) 2009 Andes Technology Corporation
++ */
++#include <linux/sched.h>
++#include <linux/mman.h>
++#include <linux/shm.h>
++
++#define COLOUR_ALIGN(addr,pgoff) \
++ ((((addr)+REALSHMLBA-1)&~(REALSHMLBA-1)) + \
++ (((pgoff)<<PAGE_SHIFT) & (REALSHMLBA-1)))
++
++/*
++ * We need to ensure that shared mappings are correctly aligned to
++ * avoid aliasing issues with VIPT caches. We need to ensure that
++ * a specific page of an object is always mapped at a multiple of
++ * SHMLBA bytes.
++ *
++ * We unconditionally provide this function for all cases, however
++ * in the VIVT case, we optimise out the alignment rules.
++ */
++unsigned long
++arch_get_unmapped_area(struct file *filp, unsigned long addr,
++ unsigned long len, unsigned long pgoff,
++ unsigned long flags)
++{
++ struct mm_struct *mm = current->mm;
++ struct vm_area_struct *vma;
++ unsigned long start_addr;
++ int do_align = 0;
++#ifdef CONFIG_CPU_CACHE_NONALIASING
++ int aliasing = 0;
++#else
++ int aliasing = 1;
++#endif
++
++ /*
++ * We only need to do colour alignment if either the I or D
++ * caches alias.
++ */
++ if (aliasing)
++ do_align = filp || (flags & MAP_SHARED);
++
++ /*
++ * We should enforce the MAP_FIXED case. However, currently
++ * the generic kernel code doesn't allow us to handle this.
++ */
++ if (flags & MAP_FIXED) {
++ if (aliasing && flags & MAP_SHARED && addr & (REALSHMLBA - 1))
++ return -EINVAL;
++ return addr;
++ }
++
++ if (len > TASK_SIZE)
++ return -ENOMEM;
++
++ if (addr) {
++ if (do_align)
++ addr = COLOUR_ALIGN(addr, pgoff);
++ else
++ addr = PAGE_ALIGN(addr);
++
++ vma = find_vma(mm, addr);
++ if (TASK_SIZE - len >= addr &&
++ (!vma || addr + len <= vma->vm_start))
++ return addr;
++ }
++ start_addr = addr = mm->free_area_cache;
++
++full_search:
++ if (do_align)
++ addr = COLOUR_ALIGN(addr, pgoff);
++ else
++ addr = PAGE_ALIGN(addr);
++
++ for (vma = find_vma(mm, addr);; vma = vma->vm_next) {
++ /* At this point: (!vma || addr < vma->vm_end). */
++ if (TASK_SIZE - len < addr) {
++ /*
++ * Start a new search - just in case we missed
++ * some holes.
++ */
++ if (start_addr != TASK_UNMAPPED_BASE) {
++ start_addr = addr = TASK_UNMAPPED_BASE;
++ goto full_search;
++ }
++ return -ENOMEM;
++ }
++ if (!vma || addr + len <= vma->vm_start) {
++ /*
++ * Remember the place where we stopped the search:
++ */
++ mm->free_area_cache = addr + len;
++ return addr;
++ }
++ addr = vma->vm_end;
++ if (do_align)
++ addr = COLOUR_ALIGN(addr, pgoff);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/mm.h linux-3.4.110/arch/nds32/mm/mm.h
+--- linux-3.4.110.orig/arch/nds32/mm/mm.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/mm.h 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,19 @@
++/* the upper-most page table pointer */
++
++#ifdef CONFIG_MMU
++
++extern pmd_t *top_pmd;
++
++#define TOP_PTE(x) pte_offset_kernel(top_pmd, x)
++
++static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
++{
++ return pmd_offset(pgd, virt);
++}
++
++static inline pmd_t *pmd_off_k(unsigned long virt)
++{
++ return pmd_off(pgd_offset_k(virt), virt);
++}
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/mm-nds32.c linux-3.4.110/arch/nds32/mm/mm-nds32.c
+--- linux-3.4.110.orig/arch/nds32/mm/mm-nds32.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/mm-nds32.c 2016-04-07 10:20:50.982082572 +0200
+@@ -0,0 +1,267 @@
++/*
++ * linux/arch/nds32/mm/mm-nds32.c
++ *
++ * Copyright (C) 1998-2002 Russell King
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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.
++ *
++ * Page table sludge for Andes N10/N12 processor architectures.
++ */
++#include <linux/module.h>
++#include <linux/mm.h>
++#include <linux/bootmem.h>
++#include <linux/init_task.h>
++
++#include <asm/pgalloc.h>
++#include <asm/pgtable.h>
++#include <asm/setup.h>
++#include <asm/fixmap.h>
++
++#include <asm/mach/map.h>
++#include "./../kernel/signal.h"
++
++extern void _text, _stext, _etext;
++extern void *high_memory;
++
++#define FIRST_KERNEL_PGD_NR (USER_PTRS_PER_PGD)
++
++/*
++ * need to get a 4k page for level 1
++ */
++
++pgd_t *get_pgd_slow(struct mm_struct *mm)
++{
++ pgd_t *new_pgd, *init_pgd;
++ int i;
++
++ new_pgd = (pgd_t *) __get_free_pages(GFP_KERNEL, 0); //M order 0: one page
++ if (!new_pgd)
++ return NULL;
++ for (i = 0; i < PTRS_PER_PGD; i++) {
++ (*new_pgd) = 1;
++ new_pgd++;
++ }
++ new_pgd -= PTRS_PER_PGD;
++
++ init_pgd = pgd_offset_k(0);
++
++ memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
++ (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
++
++ cpu_dcache_wb_range((unsigned long)new_pgd,
++ (unsigned long)new_pgd +
++ PTRS_PER_PGD * sizeof(pgd_t));
++ inc_zone_page_state(virt_to_page((unsigned long *)new_pgd),
++ NR_PAGETABLE);
++
++ return new_pgd;
++}
++
++void free_pgd_slow(struct mm_struct *mm, pgd_t * pgd)
++{
++ pmd_t *pmd;
++ struct page *pte;
++
++ if (!pgd)
++ return;
++
++ pmd = (pmd_t *) pgd;
++ if (pmd_none(*pmd))
++ goto free;
++ if (pmd_bad(*pmd)) {
++ pmd_ERROR(*pmd);
++ pmd_clear(pmd);
++ goto free;
++ }
++
++ pte = pmd_page(*pmd);
++ pmd_clear(pmd);
++ dec_zone_page_state(virt_to_page((unsigned long *)pgd), NR_PAGETABLE);
++ pte_free(mm, pte);
++ pmd_free(mm, pmd);
++free:
++ free_pages((unsigned long)pgd, 0);
++}
++
++/*
++ * Add a PAGE mapping between VIRT and PHYS in domain
++ * DOMAIN with protection PROT. Note that due to the
++ * way we map the PTEs, we must allocate two PTE_SIZE'd
++ * blocks - one for the Linux pte table, and one for
++ * the hardware pte table.
++ */
++static inline void
++alloc_init_page(unsigned long virt, unsigned long phys, unsigned int prot_l1,
++ pgprot_t prot)
++{
++ pmd_t *pmdp;
++ pte_t *ptep;
++
++ pmdp = pmd_offset(pgd_offset_k(virt), virt); //L1PTE
++ if (pmd_none(*pmdp)) { //must not or 0xc0000000
++ ptep = alloc_bootmem_low_pages(PTRS_PER_PTE * sizeof(pte_t));
++ set_pmd(pmdp, __mk_pmd(ptep, 0));
++ }
++ ptep = pte_offset_kernel(pmdp, virt); //L2PTE
++ set_pte(ptep, pfn_pte(phys >> PAGE_SHIFT, prot));
++}
++
++/*
++ * Clear any PGD mapping. On a two-level page table system,
++ * the clearance is done by the middle-level functions (pmd)
++ * rather than the top-level (pgd) functions.
++ */
++static inline void clear_mapping(unsigned long virt)
++{
++ pmd_clear(pmd_offset(pgd_offset_k(virt), virt));
++}
++
++struct mem_types {
++ unsigned int prot_pte;
++ unsigned int prot_l1;
++};
++
++static struct mem_types mem_types[] __initdata = {
++ [MT_DEVICE] = {
++ .prot_pte = 0x9f, //_KERNPG_TABLE,
++ .prot_l1 = PMD_TYPE_TABLE,
++ },
++ [MT_CACHECLEAN] = {
++ .prot_l1 = PMD_TYPE_TABLE,
++ .prot_pte = 0x0, //_KERNPG_TABLE,
++ },
++ [MT_MINICLEAN] = {
++ .prot_l1 = PMD_TYPE_TABLE,
++ .prot_pte = 0x0, // _KERNPG_TABLE,
++ },
++ [MT_CACHE_L1] = {
++ .prot_pte = PAGE_CACHE_L1,
++ .prot_l1 = PMD_TYPE_TABLE,
++ },
++ [MT_UXKRWX_V1] = {
++ .prot_pte = PAGE_UXKRWX_V1,
++ .prot_l1 = PMD_TYPE_TABLE,
++ },
++ [MT_UXKRWX_V2] = {
++ .prot_pte = PAGE_UXKRWX_V2,
++ .prot_l1 = PMD_TYPE_TABLE,
++ },
++ [MT_MEMORY] = {
++ .prot_pte = PAGE_MEMORY,
++ .prot_l1 = PMD_TYPE_TABLE,
++ },
++ [MT_ROM] = {
++ .prot_l1 = PMD_TYPE_TABLE,
++ .prot_pte = 0x2bb, // _KERNPG_TABLE,
++ },
++ [MT_ILM] = {
++ .prot_l1 = PMD_TYPE_TABLE,
++ .prot_pte = 0x2b7, // _KERNPG_TABLE,
++ },
++ [MT_DLM] = {
++ .prot_l1 = PMD_TYPE_TABLE,
++ .prot_pte = 0x297, // _KERNPG_TABLE,
++ }
++};
++
++/*
++ * Create the page directory entries and any necessary
++ * page tables for the mapping specified by `md'. We
++ * are able to cope here with varying sizes and address
++ * offsets, and we take full advantage of sections.
++ */
++static void __init create_mapping(struct map_desc *md)
++{
++ unsigned long virt, length;
++ int prot_l1;
++ pgprot_t prot_pte;
++ long off;
++
++ printk("virt:0x%08lx,phys:%08lx,size:%08lx,pte:%08x\n",
++ md->virtual, md->physical, md->length,
++ __pgprot(mem_types[md->type].prot_pte));
++
++ if (md->virtual < TASK_SIZE) {
++ printk(KERN_WARNING "BUG: not creating mapping area for "
++ "0x%08lx at 0x%08lx in user region, next frame\n",
++ md->physical, md->virtual);
++ panic("In :%s, line:%d", __func__, __LINE__);
++ return;
++ }
++
++ if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
++ md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
++ printk(KERN_WARNING "BUG: mapping area for 0x%08lx at 0x%08lx "
++ "overlaps vmalloc space, next frame\n",
++ md->physical, md->virtual);
++ panic("In :%s, line:%d", __func__, __LINE__);
++ }
++
++ prot_pte = __pgprot(mem_types[md->type].prot_pte);
++ prot_l1 = mem_types[md->type].prot_l1;
++ virt = md->virtual;
++ off = md->physical - virt;
++
++ length = md->length;
++ if (mem_types[md->type].prot_l1 == 1 &&
++ (virt & 0xfffff || (virt + off) & 0xfffff
++ || (virt + length) & 0xfffff)) {
++ printk(KERN_WARNING
++ "BUG: map area for 0x%08lx at 0x%08lx can not "
++ "be mapped using pages, ignoring. next frame\n",
++ md->physical, md->virtual);
++ panic("In :%s, line:%d", __func__, __LINE__);
++ return;
++ }
++
++ while (length >= PAGE_SIZE) {
++#ifdef CONFIG_SMP
++ if (((virt >= (unsigned long)&_text)
++ && (virt < (unsigned long)&_etext))
++ || ((virt >= 0xc0000000) && (virt < 0xc0008000)))
++ prot_pte = __pgprot(mem_types[MT_CACHE_L1].prot_pte);
++#endif
++ alloc_init_page(virt, virt + off, prot_l1, prot_pte);
++ virt += PAGE_SIZE;
++ length -= PAGE_SIZE;
++ }
++}
++
++/*
++ * In order to soft-boot, we need to insert a 1:1 mapping in place of
++ * the user-mode pages. This will then ensure that we have predictable
++ * results when turning the mmu off
++ */
++void setup_mm_for_reboot(char mode)
++{
++ unsigned long pmdval;
++ pgd_t *pgd;
++ pmd_t *pmd;
++ int i;
++
++ if (current->mm && current->mm->pgd)
++ pgd = current->mm->pgd;
++ else
++ pgd = init_mm.pgd;
++
++ for (i = 0; i < USER_PTRS_PER_PGD; i++) {
++ pmdval = (i << PGDIR_SHIFT);
++ pmd = pmd_offset(pgd + i, i << PGDIR_SHIFT);
++ set_pmd(pmd, __pmd(pmdval));
++ }
++}
++
++/*
++ * Create the architecture specific mappings
++ */
++void __init iotable_init(struct map_desc *io_desc, int nr)
++{
++ int i;
++
++ for (i = 0; i < nr; i++) {
++ create_mapping(io_desc + i);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/proc-n12.c linux-3.4.110/arch/nds32/mm/proc-n12.c
+--- linux-3.4.110.orig/arch/nds32/mm/proc-n12.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/proc-n12.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,845 @@
++/*
++ * linux/arch/nds32/mm/proc-nds32.c
++ *
++ * Copyright (C) 2006 Andes Technology Corporation
++ *
++ * 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
++ *
++ *
++ * These are the low level assembler for performing cache and TLB
++ * functions on the nds32.
++ *
++ */
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/mm.h>
++#include <asm/nds32.h>
++#include <asm/pgtable.h>
++#include <asm/tlbflush.h>
++#include <asm/cacheflush.h>
++#ifdef CONFIG_CACHE_L2
++#include <asm/l2_cache.h>
++#endif
++#include <nds32_intrinsic.h>
++
++#include <asm/cache_info.h>
++extern struct cache_info L1_cache_info[2];
++
++#ifdef CONFIG_CACHE_L2
++void n12_L2cache_inval(void)
++{
++ unsigned long cmd = CCTL_CMD_L2_IX_INVAL | CCTL_ALL_CMD;
++
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, CCTL_CMD_L2_SYNC);
++ L2_CMD_RDY();
++}
++
++void n12_L2cache_wb(void)
++{
++ unsigned long cmd = CCTL_CMD_L2_IX_WB | CCTL_ALL_CMD;
++
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, CCTL_CMD_L2_SYNC);
++ L2_CMD_RDY();
++}
++#endif
++
++int va_kernel_present(unsigned long addr)
++{
++ pmd_t *pmd;
++ pte_t *ptep, pte;
++ int ret = 0;
++
++ pmd = pmd_offset(pgd_offset_k(addr), addr);
++ if (!pmd_none(*pmd)) {
++ ptep = pte_offset_map(pmd, addr);
++ pte = *ptep;
++ if (pte_present(pte))
++ ret = 1;
++ }
++ return ret;
++}
++
++int va_present(struct mm_struct *mm, unsigned long addr)
++{
++ pgd_t *pgd;
++ pud_t *pud;
++ pmd_t *pmd;
++ pte_t *ptep, pte;
++ int ret = 0;
++
++ pgd = pgd_offset(mm, addr);
++ if (!pgd_none(*pgd)) {
++ pud = pud_offset(pgd, addr);
++ if (!pud_none(*pud)) {
++ pmd = pmd_offset(pud, addr);
++ if (!pmd_none(*pmd)) {
++ ptep = pte_offset_map(pmd, addr);
++ pte = *ptep;
++ if (pte_present(pte))
++ ret = 1;
++ }
++ }
++ }
++ return ret;
++
++}
++
++int va_readable(struct pt_regs *regs, unsigned long addr)
++{
++ struct mm_struct *mm = current->mm;
++ pgd_t *pgd;
++ pud_t *pud;
++ pmd_t *pmd;
++ pte_t *ptep, pte;
++ int ret = 0;
++
++ if (user_mode(regs)) {
++ /* user mode */
++ pgd = pgd_offset(mm, addr);
++ if (!pgd_none(*pgd)) {
++ pud = pud_offset(pgd, addr);
++ if (!pud_none(*pud)) {
++ pmd = pmd_offset(pud, addr);
++ if (!pmd_none(*pmd)) {
++ ptep = pte_offset_map(pmd, addr);
++ pte = *ptep;
++ if (pte_present(pte) && pte_read(pte))
++ ret = 1;
++ }
++ }
++ }
++ } else {
++ /* superuser mode is always readable, so we can only
++ * check it is present or not*/
++ pmd = pmd_offset(pgd_offset_k(addr), addr);
++ if (!pmd_none(*pmd)) {
++ ptep = pte_offset_map(pmd, addr);
++ pte = *ptep;
++ if (pte_present(pte))
++ ret = 1;
++ }
++ }
++ return ret;
++}
++
++int va_writable(struct pt_regs *regs, unsigned long addr)
++{
++ struct mm_struct *mm = current->mm;
++ pgd_t *pgd;
++ pud_t *pud;
++ pmd_t *pmd;
++ pte_t *ptep, pte;
++ int ret = 0;
++
++ if (user_mode(regs)) {
++ /* user mode */
++ pgd = pgd_offset(mm, addr);
++ if (!pgd_none(*pgd)) {
++ pud = pud_offset(pgd, addr);
++ if (!pud_none(*pud)) {
++ pmd = pmd_offset(pud, addr);
++ if (!pmd_none(*pmd)) {
++ ptep = pte_offset_map(pmd, addr);
++ pte = *ptep;
++ if (pte_present(pte) && pte_write(pte))
++ ret = 1;
++ }
++ }
++ }
++ } else {
++ /* superuser mode */
++ pmd = pmd_offset(pgd_offset_k(addr), addr);
++ if (!pmd_none(*pmd)) {
++ ptep = pte_offset_map(pmd, addr);
++ pte = *ptep;
++ if (pte_present(pte) && pte_kernel_write(pte))
++ ret = 1;
++ }
++ }
++ return ret;
++}
++
++#if 0
++static inline void flush_fill_buffer(void)
++{
++ unsigned long kaddr, pte, flags;
++
++ local_irq_save(flags);
++#define BASE_ADDR2 0xffff4000
++ kaddr = BASE_ADDR2;
++ pte = (0x6000 | _PAGE_V | _PAGE_M_KRW | _PAGE_G | _PAGE_C_DEV);
++ asm("tlbop %0, INV\nisb\n"::"r"(kaddr));
++ asm("mtsr %1, $mr2\ndsb\n"
++ "tlbop %0, RWR\nisb\n"::"r"(pte), "r"(kaddr));
++asm("lmw.bi $r0, [%0], $r1\n"::"r"(kaddr):"$r0", "$r1");
++ local_irq_restore(flags);
++}
++#else
++static inline void flush_fill_buffer(void)
++{
++}
++#endif
++
++/*
++ * All
++ */
++void n12_icache_inval_all(void)
++{
++ unsigned long end, line_size;
++
++ line_size = L1_cache_info[ICACHE].line_size;
++ end =
++ line_size * L1_cache_info[ICACHE].ways * L1_cache_info[ICACHE].sets;
++
++ do {
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1I_IX_INVAL"::"r" (end));
++ } while (end > 0);
++}
++
++void n12_dcache_inval_all(void)
++{
++#ifdef CONFIG_PLAT_AG102
++ __asm__ volatile ("\n\tcctl L1D_INVALALL");
++#else
++ unsigned long end, line_size;
++
++ line_size = L1_cache_info[DCACHE].line_size;
++ end =
++ line_size * L1_cache_info[DCACHE].ways * L1_cache_info[DCACHE].sets;
++
++ do {
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
++ } while (end > 0);
++#endif
++}
++
++void n12_dcache_wb_all(void)
++{
++#ifdef __NDS32_BASELINE_V3
++#ifdef CONFIG_CACHE_L2
++ __nds32__cctl_l1d_wball_alvl();
++#else
++ __nds32__cctl_l1d_wball_one_lvl();
++#endif
++#else
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ unsigned long end, line_size;
++
++ line_size = L1_cache_info[DCACHE].line_size;
++ end =
++ line_size * L1_cache_info[DCACHE].ways * L1_cache_info[DCACHE].sets;
++
++ do {
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
++ } while (end > 0);
++#endif
++#endif
++}
++
++void n12_dcache_wbinval_all(void)
++{
++ unsigned long end, line_size;
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ unsigned long saved_gie;
++#endif
++
++ line_size = L1_cache_info[DCACHE].line_size;
++ end =
++ line_size * L1_cache_info[DCACHE].ways * L1_cache_info[DCACHE].sets;
++
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ GIE_SAVE(&saved_gie);
++#endif
++#ifdef __NDS32_BASELINE_V3
++#ifdef CONFIG_CACHE_L2
++ __nds32__cctl_l1d_wball_alvl();
++#else
++ __nds32__cctl_l1d_wball_one_lvl();
++#endif
++ __nds32__cctl_l1d_invalall();
++#else
++ do {
++ end -= line_size;
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
++#endif
++#ifndef CONFIG_PLAT_AG102
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
++#endif
++ end -= line_size;
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
++#endif
++#ifndef CONFIG_PLAT_AG102
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
++#endif
++ end -= line_size;
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
++#endif
++#ifndef CONFIG_PLAT_AG102
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
++#endif
++ end -= line_size;
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_WB"::"r" (end));
++#endif
++#ifndef CONFIG_PLAT_AG102
++ __asm__ volatile ("\n\tcctl %0, L1D_IX_INVAL"::"r" (end));
++#endif
++ } while (end > 0);
++#ifdef CONFIG_PLAT_AG102
++ __asm__ volatile ("\n\tcctl L1D_INVALALL");
++#endif
++#endif
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ GIE_RESTORE(saved_gie);
++#endif
++}
++
++/*
++ * Page
++ */
++void n12_icache_inval_page(unsigned long start)
++{
++ unsigned long line_size, end;
++
++ line_size = L1_cache_info[ICACHE].line_size;
++ end = start + PAGE_SIZE;
++
++ do {
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (end));
++ } while (end != start);
++}
++
++void n12_dcache_inval_page(unsigned long start)
++{
++ unsigned long line_size, end;
++
++ line_size = L1_cache_info[DCACHE].line_size;
++ end = start + PAGE_SIZE;
++
++ flush_fill_buffer();
++ do {
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
++ } while (end != start);
++}
++
++void n12_dcache_wb_page(unsigned long start)
++{
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ unsigned long line_size, end;
++
++ line_size = L1_cache_info[DCACHE].line_size;
++ end = start + PAGE_SIZE;
++
++ flush_fill_buffer();
++ do {
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
++ end -= line_size;
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
++ } while (end != start);
++#endif
++}
++
++void n12_dcache_wbinval_page(unsigned long start)
++{
++ unsigned long line_size, end;
++
++ line_size = L1_cache_info[DCACHE].line_size;
++ end = start + PAGE_SIZE;
++
++ flush_fill_buffer();
++ do {
++ end -= line_size;
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
++#endif
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
++ end -= line_size;
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
++#endif
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
++ end -= line_size;
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
++#endif
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
++ end -= line_size;
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (end));
++#endif
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (end));
++ } while (end != start);
++}
++
++void n12_cache_wbinval_page(unsigned long page, int flushi)
++{
++ n12_dcache_wbinval_page(page);
++ if (flushi)
++ n12_icache_inval_page(page);
++}
++
++/* These functions are used to invalidate cache by idx instead of
++ * virtual address. User can use virtual address to do this purpose.
++ * It supports 4way and 32KB cache size with 32bytes cacheline size. */
++#include <nds32_intrinsic.h>
++//#define WB_WITH_IDX
++inline unsigned long va2idx(unsigned long va, unsigned int cache_type,
++ unsigned long *way_offset)
++{
++ unsigned char set_bits, way_bits, line_bits;
++ unsigned int idx;
++ set_bits = L1_cache_info[cache_type].set_bits;
++ way_bits = L1_cache_info[cache_type].way_bits;
++ line_bits = L1_cache_info[cache_type].line_bits;
++ *way_offset = set_bits + line_bits;
++
++ idx = (va & (((1 << set_bits) - 1) << line_bits));
++ return idx;
++}
++
++static inline void n12_dcache_inval_idx(unsigned long p)
++{
++ unsigned long idx, i, way_offset;
++ unsigned char ways;
++ ways = L1_cache_info[DCACHE].ways;
++
++ /* Unroll loop. Not support 2 ways invalidate. */
++ if (ways == 2)
++ panic("This way size is not supported. ways:%u, %s\n", ways,
++ __func__);
++ idx = va2idx(p, DCACHE, &way_offset);
++ for (i = 0; i < ways / 4; i++) {
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
++ (idx | i << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
++ (idx | (i + 1) << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
++ (idx | (i + 2) << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
++ (idx | (i + 3) << way_offset));
++ }
++}
++
++static inline void n12_dcache_wb_idx(unsigned long p)
++{
++ unsigned long idx, i, way_offset;
++ unsigned char ways;
++ ways = L1_cache_info[DCACHE].ways;
++
++ /* Unroll the loop. Not support 2 ways invalidate. */
++ if (ways == 2)
++ panic("This way size is not supported. ways:%d, %s\n", ways,
++ __func__);
++ idx = va2idx(p, DCACHE, &way_offset);
++ for (i = 0; i < ways / 4; i++) {
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
++ (idx | i << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
++ (idx | i << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
++ (idx | (i + 1) << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
++ (idx | (i + 1) << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
++ (idx | (i + 2) << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
++ (idx | (i + 2) << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
++ (idx | (i + 3) << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_INVAL,
++ (idx | (i + 3) << way_offset));
++ }
++}
++
++static inline void n12_dcache_wbinval_idx(unsigned long p)
++{
++ unsigned long idx, i, way_offset;
++ unsigned char ways;
++ ways = L1_cache_info[DCACHE].ways;
++
++ /* Unroll the loop. Not support 2 ways invalidate. */
++ if (ways == 2)
++ panic("This way size is not supported. ways:%d, %s\n", ways,
++ __func__);
++ idx = va2idx(p, DCACHE, &way_offset);
++ for (i = 0; i < ways / 4; i++) {
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
++ (idx | i << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
++ (idx | (i + 1) << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
++ (idx | (i + 2) << way_offset));
++ __nds32__cctlidx_wbinval(NDS32_CCTL_L1D_IX_WB,
++ (idx | (i + 3) << way_offset));
++ }
++}
++
++/*
++ * Range
++ */
++void n12_icache_inval_range(unsigned long start, unsigned long end)
++{
++ unsigned long line_size;
++
++ line_size = L1_cache_info[ICACHE].line_size;
++
++ while (end > start) {
++ __asm__ volatile ("\n\tcctl %0, L1I_VA_INVAL"::"r" (start));
++ start += line_size;
++ }
++}
++
++void n12_dcache_inval_range(unsigned long start, unsigned long end)
++{
++ unsigned long line_size;
++
++ line_size = L1_cache_info[DCACHE].line_size;
++
++ flush_fill_buffer();
++ while (end > start) {
++#ifdef WB_WITH_IDX
++ n12_dcache_inval_idx(start);
++#else
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (start));
++#endif
++ start += line_size;
++ }
++}
++
++void n12_dcache_wb_range(unsigned long start, unsigned long end)
++{
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++ unsigned long line_size;
++
++ line_size = L1_cache_info[DCACHE].line_size;
++
++ flush_fill_buffer();
++ while (end > start) {
++#ifdef WB_WITH_IDX
++ n12_dcache_wb_idx(start);
++#else
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (start));
++#endif
++ start += line_size;
++ }
++#endif
++}
++
++void n12_dcache_wbinval_range(unsigned long start, unsigned long end)
++{
++ unsigned long line_size;
++
++ line_size = L1_cache_info[DCACHE].line_size;
++
++ flush_fill_buffer();
++ while (end > start) {
++#ifndef CONFIG_CPU_DCACHE_WRITETHROUGH
++#ifdef WB_WITH_IDX
++ n12_dcache_wbinval_idx(start);
++#else
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_WB"::"r" (start));
++#endif
++#endif
++ __asm__ volatile ("\n\tcctl %0, L1D_VA_INVAL"::"r" (start));
++ start += line_size;
++ }
++}
++
++void n12_cache_wbinval_range(unsigned long start, unsigned long end, int flushi)
++{
++ n12_dcache_wbinval_range(start, end);
++ if (flushi)
++ n12_icache_inval_range(start, end);
++}
++
++void n12_cache_wbinval_range_check(struct vm_area_struct *vma,
++ unsigned long start, unsigned long end)
++{
++ unsigned long line_size, t_start, t_end;
++ int flushi;
++
++ flushi = vma->vm_flags & VM_EXEC;
++ line_size = L1_cache_info[DCACHE].line_size;
++ start = start & ~(line_size - 1);
++ end = (end + line_size - 1) & ~(line_size - 1);
++
++ if ((end - start) > (8 * PAGE_SIZE)) {
++ n12_dcache_wbinval_all();
++ if (flushi)
++ n12_icache_inval_all();
++ return;
++ }
++
++ t_start = (start + PAGE_SIZE) & PAGE_MASK;
++ t_end = ((end - 1) & PAGE_MASK);
++
++ if ((start & PAGE_MASK) == t_end) {
++ if (va_present(vma->vm_mm, start))
++ n12_cache_wbinval_range(start, end, flushi);
++ return;
++ }
++
++ if (va_present(vma->vm_mm, start))
++ n12_cache_wbinval_range(start, t_start, flushi);
++
++ if (va_present(vma->vm_mm, end - 1))
++ n12_cache_wbinval_range(t_end, end, flushi);
++
++ while (t_start < t_end) {
++ if (va_present(vma->vm_mm, t_start))
++ n12_cache_wbinval_page(t_start, flushi);
++ t_start += PAGE_SIZE;
++ }
++}
++
++/*
++ * DMA
++ */
++void n12_dma_wb_range(unsigned long start, unsigned long end)
++{
++ unsigned long line_size;
++ line_size = L1_cache_info[DCACHE].line_size;
++ start = start & (~(line_size - 1));
++ end = (end + line_size - 1) & (~(line_size - 1));
++ if (unlikely(start == end))
++ return;
++
++ n12_dcache_wb_range(start, end);
++
++#ifdef CONFIG_CACHE_L2
++ {
++ unsigned long p_start = __pa(start);
++ unsigned long p_end = __pa(end);
++ unsigned long cmd;
++ //TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE
++ line_size = L2_CACHE_LINE_SIZE();
++ cmd =
++ (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_WB |
++ CCTL_SINGLE_CMD;
++ do {
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
++ cmd += line_size;
++ p_start += line_size;
++ } while (p_end > p_start);
++ cmd = CCTL_CMD_L2_SYNC;
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
++ L2_CMD_RDY();
++
++ }
++#endif
++}
++
++#ifdef CONFIG_CACHE_L2
++void n12_l2dcache_wbinval_range(unsigned long start, unsigned long end)
++{
++ unsigned long p_start;
++ unsigned long p_end;
++ unsigned long cmd;
++ unsigned long line_size;
++
++ p_start = __pa(start);
++ p_end = __pa(end);
++ //TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE
++ line_size = L2_CACHE_LINE_SIZE();
++ cmd =
++ (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_WBINVAL |
++ CCTL_SINGLE_CMD;
++ do {
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
++ cmd += line_size;
++ p_start += line_size;
++ } while (p_end > p_start);
++ cmd = CCTL_CMD_L2_SYNC;
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
++ L2_CMD_RDY();
++
++}
++#endif
++
++void n12_dma_inval_range(unsigned long start, unsigned long end)
++{
++ unsigned long line_size;
++ unsigned long old_start = start;
++ unsigned long old_end = end;
++ line_size = L1_cache_info[DCACHE].line_size;
++ start = start & (~(line_size - 1));
++ end = (end + line_size - 1) & (~(line_size - 1));
++ if (unlikely(start == end))
++ return;
++ if (start != old_start) {
++ n12_dcache_wbinval_range(start, start + line_size);
++#ifdef CONFIG_CACHE_L2
++ n12_l2dcache_wbinval_range(start, start + line_size);
++#endif
++ }
++ if (end != old_end) {
++ n12_dcache_wbinval_range(end - line_size, end);
++#ifdef CONFIG_CACHE_L2
++ n12_l2dcache_wbinval_range(end - line_size, end);
++#endif
++ }
++ n12_dcache_inval_range(start, end);
++#ifdef CONFIG_CACHE_L2
++ unsigned long p_start = __pa(start);
++ unsigned long p_end = __pa(end);
++ unsigned long cmd;
++ //TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE
++ line_size = L2_CACHE_LINE_SIZE();
++ cmd =
++ (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_INVAL |
++ CCTL_SINGLE_CMD;
++ do {
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
++ cmd += line_size;
++ p_start += line_size;
++ } while (p_end > p_start);
++ cmd = CCTL_CMD_L2_SYNC;
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
++ L2_CMD_RDY();
++#endif
++
++}
++
++void n12_dma_wbinval_range(unsigned long start, unsigned long end)
++{
++ unsigned long line_size;
++ line_size = L1_cache_info[DCACHE].line_size;
++ start = start & (~(line_size - 1));
++ end = (end + line_size - 1) & (~(line_size - 1));
++ if (unlikely(start == end))
++ return;
++
++ n12_dcache_wbinval_range(start, end);
++#ifdef CONFIG_CACHE_L2
++ {
++ unsigned long p_start = __pa(start);
++ unsigned long p_end = __pa(end);
++ unsigned long cmd;
++ //TODO Can Use PAGE Mode to optimize if range large than PAGE_SIZE
++ line_size = L2_CACHE_LINE_SIZE();
++ cmd =
++ (p_start & ~(line_size - 1)) | CCTL_CMD_L2_PA_WBINVAL |
++ CCTL_SINGLE_CMD;
++ do {
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
++ cmd += line_size;
++ p_start += line_size;
++ } while (p_end > p_start);
++ cmd = CCTL_CMD_L2_SYNC;
++ L2_CMD_RDY();
++ L2C_W_REG(L2_CCTL_CMD_OFF, cmd);
++ L2_CMD_RDY();
++
++ }
++#endif
++}
++
++void n12_proc_init(void)
++{
++}
++
++void n12_proc_fin(void)
++{
++}
++
++void n12_do_idle(void)
++{
++ STANDBY(no_wake_grant);
++}
++
++void n12_reset(unsigned long reset)
++{
++ GIE_DISABLE();
++ SET_CACHE_CTL(GET_CACHE_CTL() &
++ ~(CACHE_CTL_mskIC_EN | CACHE_CTL_mskDC_EN));
++ n12_dcache_wbinval_all();
++ n12_icache_inval_all();
++
++ __asm__ __volatile__("jr.toff %0\n\t"::"r"(reset));
++}
++
++void n12_switch_mm(struct mm_struct *mm)
++{
++ unsigned long cid;
++#ifndef CONFIG_CPU_NO_CONTEXT_ID
++ cid = GET_TLB_MISC();
++ cid = (cid & ~TLB_MISC_mskCID) | mm->context.id;
++ SET_TLB_MISC(cid);
++#endif
++ SET_L1_PPTB(__pa(mm->pgd));
++ //workaround N10 single-entry cache flush issue
++ //the following line can be removed once the issue is fixed.
++ __asm__ __volatile__("tlbop %0, INV"::"r"(cid));
++ __nds32__isb();
++#ifdef CONFIG_CPU_NO_CONTEXT_ID
++ local_flush_tlb_mm(mm);
++#endif
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/mm/tlb.c linux-3.4.110/arch/nds32/mm/tlb.c
+--- linux-3.4.110.orig/arch/nds32/mm/tlb.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/mm/tlb.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,47 @@
++#include <linux/spinlock_types.h>
++#include <linux/mm.h>
++#include <linux/sched.h>
++#include <asm/nds32.h>
++#include <nds32_intrinsic.h>
++
++unsigned int cpu_last_cid = { TLB_MISC_mskCID + (2 << TLB_MISC_offCID) };
++
++DEFINE_SPINLOCK(cid_lock);
++
++void local_flush_tlb_range(struct vm_area_struct *vma,
++ unsigned long start, unsigned long end)
++{
++ unsigned long flags, ocid, ncid;
++
++ if ((end - start) > 0x400000) {
++ asm("tlbop FLUA");
++ __nds32__isb();
++ return;
++ }
++
++ spin_lock_irqsave(&cid_lock, flags);
++ ocid = GET_TLB_MISC();
++ ncid = (ocid & ~TLB_MISC_mskCID) | vma->vm_mm->context.id;
++ SET_TLB_MISC(ncid);
++ while (start < end) {
++ asm("tlbop %0, INV"::"r"(start));
++ __nds32__isb();
++ start += PAGE_SIZE;
++ }
++ SET_TLB_MISC(ocid);
++ spin_unlock_irqrestore(&cid_lock, flags);
++}
++
++void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
++{
++ unsigned long flags, ocid, ncid;
++
++ spin_lock_irqsave(&cid_lock, flags);
++ ocid = GET_TLB_MISC();
++ ncid = (ocid & ~TLB_MISC_mskCID) | vma->vm_mm->context.id;
++ SET_TLB_MISC(ncid);
++ asm("tlbop %0, INV"::"r"(addr));
++ __nds32__isb();
++ SET_TLB_MISC(ocid);
++ spin_unlock_irqrestore(&cid_lock, flags);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/oprofile/common.c linux-3.4.110/arch/nds32/oprofile/common.c
+--- linux-3.4.110.orig/arch/nds32/oprofile/common.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/oprofile/common.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,104 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2004, 2005 Ralf Baechle
++ * Copyright (C) 2005 MIPS Technologies, Inc.
++ * Copyright (C) 2008 Andes Technology Corporation
++ */
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/oprofile.h>
++#include <linux/smp.h>
++
++#include "op_impl.h"
++
++extern struct op_nds32_model op_model_nds32_ops __attribute__ ((weak));
++
++static struct op_nds32_model *model;
++
++static struct op_counter_config ctr[20];
++
++static int op_nds32_setup(void)
++{
++ /* Pre-compute the values to stuff in the hardware registers. */
++ model->reg_setup(ctr);
++
++ /* Configure the registers on all cpus. */
++ on_each_cpu(model->cpu_setup, NULL, 1);
++
++ return 0;
++}
++
++static int op_nds32_create_files(struct super_block *sb, struct dentry *root)
++{
++ int i;
++
++ for (i = 0; i < model->num_counters; ++i) {
++ struct dentry *dir;
++ char buf[4];
++
++ snprintf(buf, sizeof buf, "%d", i);
++ dir = oprofilefs_mkdir(sb, root, buf);
++
++ oprofilefs_create_ulong(sb, dir, "enabled", &ctr[i].enabled);
++ oprofilefs_create_ulong(sb, dir, "event", &ctr[i].event);
++ oprofilefs_create_ulong(sb, dir, "count", &ctr[i].count);
++ oprofilefs_create_ulong(sb, dir, "kernel", &ctr[i].kernel);
++ oprofilefs_create_ulong(sb, dir, "user", &ctr[i].user);
++ oprofilefs_create_ulong(sb, dir, "exl", &ctr[i].exl);
++ /* Dummy. */
++ oprofilefs_create_ulong(sb, dir, "unit_mask",
++ &ctr[i].unit_mask);
++ }
++
++ return 0;
++}
++
++static int op_nds32_start(void)
++{
++ on_each_cpu(model->cpu_start, NULL, 1);
++
++ return 0;
++}
++
++static void op_nds32_stop(void)
++{
++ /* Disable performance monitoring for all counters. */
++ on_each_cpu(model->cpu_stop, NULL, 1);
++}
++
++int __init oprofile_arch_init(struct oprofile_operations *ops)
++{
++ struct op_nds32_model *lmodel = NULL;
++ int res;
++
++ lmodel = &op_model_nds32_ops;
++
++ if (!lmodel)
++ return -ENODEV;
++
++ res = lmodel->init();
++ if (res)
++ return res;
++
++ model = lmodel;
++
++ ops->create_files = op_nds32_create_files;
++ ops->setup = op_nds32_setup;
++ ops->start = op_nds32_start;
++ ops->stop = op_nds32_stop;
++ ops->cpu_type = lmodel->cpu_type;
++
++ printk(KERN_INFO "oprofile: using %s performance monitoring.\n",
++ lmodel->cpu_type);
++
++ return 0;
++}
++
++void oprofile_arch_exit(void)
++{
++ if (model)
++ model->exit();
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/oprofile/Makefile linux-3.4.110/arch/nds32/oprofile/Makefile
+--- linux-3.4.110.orig/arch/nds32/oprofile/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/oprofile/Makefile 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,11 @@
++EXTRA_CFLAGS :=
++
++obj-$(CONFIG_OPROFILE) += oprofile.o
++
++DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
++ oprof.o cpu_buffer.o buffer_sync.o \
++ event_buffer.o oprofile_files.o \
++ oprofilefs.o oprofile_stats.o \
++ timer_int.o )
++
++oprofile-y := $(DRIVER_OBJS) common.o op_model_nds32.o
+diff -Nur linux-3.4.110.orig/arch/nds32/oprofile/op_impl.h linux-3.4.110/arch/nds32/oprofile/op_impl.h
+--- linux-3.4.110.orig/arch/nds32/oprofile/op_impl.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/oprofile/op_impl.h 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,42 @@
++/**
++ * @file arch/alpha/oprofile/op_impl.h
++ *
++ * @remark Copyright 2002 OProfile authors
++ * @remark Read the file COPYING
++ *
++ * @author Richard Henderson <rth@twiddle.net>
++ */
++
++#ifndef OP_IMPL_H
++#define OP_IMPL_H 1
++
++struct pt_regs;
++
++extern int null_perf_irq(struct pt_regs *regs);
++extern int (*perf_irq)(struct pt_regs *regs);
++
++/* Per-counter configuration as set via oprofilefs. */
++struct op_counter_config {
++ unsigned long enabled;
++ unsigned long event;
++ unsigned long count;
++ /* Dummies because I am too lazy to hack the userspace tools. */
++ unsigned long kernel;
++ unsigned long user;
++ unsigned long exl;
++ unsigned long unit_mask;
++};
++
++/* Per-architecture configury and hooks. */
++struct op_nds32_model {
++ void (*reg_setup) (struct op_counter_config *);
++ void (*cpu_setup) (void * dummy);
++ int (*init)(void);
++ void (*exit)(void);
++ void (*cpu_start)(void *args);
++ void (*cpu_stop)(void *args);
++ char *cpu_type;
++ unsigned char num_counters;
++};
++
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/oprofile/op_model_nds32.c linux-3.4.110/arch/nds32/oprofile/op_model_nds32.c
+--- linux-3.4.110.orig/arch/nds32/oprofile/op_model_nds32.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/oprofile/op_model_nds32.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,400 @@
++/*
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ *
++ * Copyright (C) 2004, 2005 by Ralf Baechle
++ * Copyright (C) 2005 by MIPS Technologies, Inc.
++ * Copyright (C) 2007 Andes Technology Corporation
++ */
++#include <linux/oprofile.h>
++#include <linux/interrupt.h>
++#include <linux/smp.h>
++#include <asm/irq_regs.h>
++#include <asm/nds32.h>
++#include <asm/uaccess.h>
++#include <asm/pfm.h>
++
++#include "op_impl.h"
++
++#ifdef CONFIG_PLAT_AG102
++#include <asm/amic.h>
++#define NDS32_PERFCNTR_IRQA 23
++#define NDS32_PERFCNTR_IRQB 22
++#else
++#define NDS32_PERFCNTR_IRQA 10
++#endif
++#define NDS32_PERFCTL_EN(num) (1 << num)
++#define NDS32_PERFCTL_INTEN (1UL << 3)
++#define NDS32_PERFCTL_OVERFLOW (1UL << 6)
++#define NDS32_PERFCTL_NOKERNEL (1UL << 9)
++#define NDS32_PERFCTL_NOUSER (1UL << 12)
++#define NDS32_PERFCTL_EVENT_0(event) (event << 15)
++#define NDS32_PERFCTL_EVENT_1(event) (event << 16)
++#define NDS32_PERFCTL_EVENT_2(event) (event << 22)
++
++static unsigned long long ov0, ov1, ov2;
++static int syscall = 0;
++
++struct pmu_counter {
++ volatile unsigned long ovf;
++ unsigned long reset_counter;
++};
++
++enum { PFMC0, PFMC1, PFMC2, MAX_COUNTERS };
++
++static struct pmu_counter results[MAX_COUNTERS];
++
++static inline unsigned int read_perfcntr(int counter)
++{
++ switch (counter) {
++ case PFMC0:
++ return GET_PFMC0();
++ break;
++ case PFMC1:
++ return GET_PFMC1();
++ break;
++ case PFMC2:
++ return GET_PFMC2();
++ break;
++ default:
++ printk(KERN_ERR
++ "Oprofile read_perfcntr: CPU has no %d performance counters\n",
++ counter);
++ }
++
++ return 0;
++}
++
++static inline unsigned int read_perfctrl(void)
++{
++ return GET_PFM_CTL();
++}
++
++static inline void write_perfcntr(int counter, unsigned int value)
++{
++ switch (counter) {
++ case PFMC0:
++ SET_PFMC0(value);
++ break;
++ case PFMC1:
++ SET_PFMC1(value);
++ break;
++ case PFMC2:
++ SET_PFMC2(value);
++ break;
++ default:
++ printk(KERN_ERR
++ "Oprofile write_perfcntr: CPU has no %d performance counters\n",
++ counter);
++ }
++}
++
++static inline void write_perfctrl(unsigned int value)
++{
++ SET_PFM_CTL(value);
++}
++
++struct op_nds32_model op_model_nds32_ops;
++
++static struct nds32_register_config {
++ unsigned int control[3];
++ unsigned int counter[3];
++} reg;
++
++/* Compute all of the registers in preparation for enabling profiling. */
++
++static void nds32_reg_setup(struct op_counter_config *ctr)
++{
++ unsigned int counters = op_model_nds32_ops.num_counters;
++ int i;
++
++ /* Compute the performance counter control word. */
++ /* For now count kernel and user mode */
++ for (i = 0; i < counters; i++) {
++ reg.control[i] = 0;
++ reg.counter[i] = 0;
++
++ if (!ctr[i].enabled)
++ continue;
++
++ switch (i) {
++ case 0:
++ reg.control[i] = NDS32_PERFCTL_EVENT_0(ctr[i].event) |
++ (NDS32_PERFCTL_INTEN << i);
++ break;
++ case 1:
++ reg.control[i] = NDS32_PERFCTL_EVENT_1(ctr[i].event) |
++ (NDS32_PERFCTL_INTEN << i);
++ break;
++ case 2:
++ reg.control[i] = NDS32_PERFCTL_EVENT_2(ctr[i].event) |
++ (NDS32_PERFCTL_INTEN << i);
++ break;
++ default:
++ printk(KERN_ERR
++ "Oprofile nds32_reg_setup: CPU has no %d performance counters\n",
++ i);
++ }
++ if (!(ctr[i].kernel))
++ reg.control[i] |= (NDS32_PERFCTL_NOKERNEL << i);
++ if (!(ctr[i].user))
++ reg.control[i] |= (NDS32_PERFCTL_NOUSER << i);
++ reg.counter[i] = -ctr[i].count;
++ }
++}
++
++/* Program all of the registers in preparation for enabling profiling. */
++
++static void nds32_cpu_setup(void *args)
++{
++ unsigned int counters = op_model_nds32_ops.num_counters;
++
++ switch (counters) {
++ case 3:
++ write_perfcntr(2, reg.counter[2]);
++ case 2:
++ write_perfcntr(1, reg.counter[1]);
++ case 1:
++ write_perfcntr(0, reg.counter[0]);
++ }
++ write_perfctrl(0);
++}
++
++/* Start all counters on current CPU */
++static void nds32_cpu_start(void *args)
++{
++ unsigned int counters = op_model_nds32_ops.num_counters;
++ unsigned int value = 0;
++
++ switch (counters) {
++ case 3:
++ if (reg.control[2])
++ value |= (NDS32_PERFCTL_EN(2) | reg.control[2]);
++ case 2:
++ if (reg.control[1])
++ value |= (NDS32_PERFCTL_EN(1) | reg.control[1]);
++ case 1:
++ if (reg.control[0])
++ value |= (NDS32_PERFCTL_EN(0) | reg.control[0]);
++ }
++ write_perfctrl(value);
++}
++
++/* Stop all counters on current CPU */
++static void nds32_cpu_stop(void *args)
++{
++ write_perfctrl(0);
++}
++
++static irqreturn_t nds32_perfcount_handler(int irq, void *dev_id)
++{
++ unsigned int control, i;
++
++ control = read_perfctrl();
++ write_perfctrl(0);
++
++ if (syscall) {
++ if (control & PFM_CTL_mskOVF0)
++ ov0++;
++ if (control & PFM_CTL_mskOVF1)
++ ov1++;
++ if (control & PFM_CTL_mskOVF2)
++ ov2++;
++ } else {
++ for (i = 0; i < MAX_COUNTERS; i++) {
++ if ((control & (NDS32_PERFCTL_INTEN << i))
++ && (control & (NDS32_PERFCTL_OVERFLOW << i))) {
++ oprofile_add_sample(get_irq_regs(), i);
++ write_perfcntr(i, reg.counter[i]);
++ break;
++ }
++ }
++ }
++ write_perfctrl(control);
++
++ return IRQ_HANDLED;
++}
++
++static inline int n_counters(void)
++{
++ return 3;
++}
++
++static inline void reset_counters(int counters)
++{
++ switch (counters) {
++ case 3:
++ write_perfcntr(2, 0);
++ case 2:
++ write_perfcntr(1, 0);
++ case 1:
++ write_perfcntr(0, 0);
++ }
++ write_perfctrl(0);
++}
++
++static int __init nds32_init(void)
++{
++ int counters, ret;
++
++ counters = n_counters();
++ if (counters == 0) {
++ printk(KERN_ERR "Oprofile: CPU has no performance counters\n");
++ return -ENODEV;
++ }
++
++ reset_counters(counters);
++
++ op_model_nds32_ops.num_counters = counters;
++ op_model_nds32_ops.cpu_type = "nds32";
++
++ ret =
++ request_irq(NDS32_PERFCNTR_IRQA, nds32_perfcount_handler,
++ IRQF_SHARED, "NDS32 PERFCNTR", (void *)results);
++ if (ret < 0) {
++ printk(KERN_ERR "oprofile: unable to request IRQ%d\n",
++ NDS32_PERFCNTR_IRQA);
++ return ret;
++ }
++#ifdef CONFIG_PLAT_AG102
++ unsigned int tmp;
++ /* Set NDS32_PERFCNTR_IRQA to bind on core A */
++ tmp =
++ *(volatile unsigned long *)(AMIC_VA_BASE + CPUID0 +
++ ((NDS32_PERFCNTR_IRQA >> 4) << 2));
++ tmp &= ~(0x11 << ((NDS32_PERFCNTR_IRQA & ~0x10) * 2));
++ *(volatile unsigned long *)(AMIC_VA_BASE + CPUID0 +
++ ((NDS32_PERFCNTR_IRQA >> 4) << 2)) = tmp;
++ tmp =
++ (*(volatile unsigned long *)(AMIC_VA_BASE + CPUDC)) & ~(1 <<
++ NDS32_PERFCNTR_IRQA);
++ *(volatile unsigned long *)(AMIC_VA_BASE + CPUDC) = tmp;
++
++ ret =
++ request_irq(NDS32_PERFCNTR_IRQB, nds32_perfcount_handler,
++ IRQF_SHARED, "NDS32 PERFCNTR", (void *)results);
++ if (ret < 0) {
++ printk(KERN_ERR "oprofile: unable to request IRQ%d\n",
++ NDS32_PERFCNTR_IRQB);
++ return ret;
++ }
++ /* Set NDS32_PERFCNTR_IRQB to bind on core B */
++ tmp =
++ *(volatile unsigned long *)(AMIC_VA_BASE + CPUID0 +
++ ((NDS32_PERFCNTR_IRQB >> 4) << 2));
++ tmp &= ~(0x11 << ((NDS32_PERFCNTR_IRQB & ~0x10) * 2));
++ tmp |= 1 << ((NDS32_PERFCNTR_IRQB & ~0x10) * 2);
++ *(volatile unsigned long *)(AMIC_VA_BASE + CPUID0 +
++ ((NDS32_PERFCNTR_IRQB >> 4) << 2)) = tmp;
++ tmp =
++ (*(volatile unsigned long *)(AMIC_VA_BASE + CPUDC)) & ~(1 <<
++ NDS32_PERFCNTR_IRQB);
++ *(volatile unsigned long *)(AMIC_VA_BASE + CPUDC) = tmp;
++#endif
++
++ return 0;
++}
++
++static void nds32_exit(void)
++{
++ reset_counters(op_model_nds32_ops.num_counters);
++
++ free_irq(NDS32_PERFCNTR_IRQA, results);
++#ifdef CONFIG_PLAT_AG102
++ free_irq(NDS32_PERFCNTR_IRQB, results);
++#endif
++}
++
++void sys_pfmctl(int event0, int event1, int event2, int start)
++{
++ unsigned int ctl = 0;
++
++ if (start) {
++ syscall = 1;
++ if (event0 >= 0)
++ ctl |=
++ (NDS32_PERFCTL_EVENT_0(event0) |
++ (NDS32_PERFCTL_INTEN << 0) | NDS32_PERFCTL_EN(0));
++ if (event1 >= 0)
++ ctl |=
++ (NDS32_PERFCTL_EVENT_1(event1) |
++ (NDS32_PERFCTL_INTEN << 1) | NDS32_PERFCTL_EN(1));
++ if (event2 >= 0)
++ ctl |=
++ (NDS32_PERFCTL_EVENT_2(event2) |
++ (NDS32_PERFCTL_INTEN << 2) | NDS32_PERFCTL_EN(2));
++ } else {
++ syscall = 0;
++ if (event0 >= 0)
++ ctl &=
++ ~((NDS32_PERFCTL_INTEN << 0) | NDS32_PERFCTL_EN(0));
++ if (event1 >= 0)
++ ctl &=
++ ~((NDS32_PERFCTL_INTEN << 1) | NDS32_PERFCTL_EN(1));
++ if (event2 >= 0)
++ ctl &=
++ ~((NDS32_PERFCTL_INTEN << 2) | NDS32_PERFCTL_EN(2));
++ }
++
++ write_perfctrl(ctl);
++
++}
++
++int sys_getpfm(struct pcounter __user * p)
++{
++ struct pcounter pfm;
++ unsigned int control;
++
++ control = read_perfctrl();
++ write_perfctrl(0);
++
++ pfm.pfm0 = ov0 << 32 | GET_PFMC0();
++ pfm.pfm1 = ov1 << 32 | GET_PFMC1();
++ pfm.pfm2 = ov2 << 32 | GET_PFMC2();
++
++ if (copy_to_user(p, &pfm, sizeof(pfm)))
++ return -EFAULT;
++
++ write_perfctrl(control);
++
++ return 0;
++}
++
++int sys_setpfm(int pfm0, int pfm1, int pfm2, struct pcounter __user * p)
++{
++ struct pcounter pfm;
++ unsigned int control;
++
++ control = read_perfctrl();
++ write_perfctrl(0);
++
++ if (copy_from_user(&pfm, p, sizeof(pfm)))
++ return -EFAULT;
++
++ if (pfm0) {
++ SET_PFMC0((unsigned int)(pfm.pfm0 & 0xffffffff));
++ ov0 = pfm.pfm0 >> 32;
++ }
++ if (pfm1) {
++ SET_PFMC1((unsigned int)(pfm.pfm1 & 0xffffffff));
++ ov1 = pfm.pfm1 >> 32;
++ }
++ if (pfm2) {
++ SET_PFMC2((unsigned int)(pfm.pfm2 & 0xffffffff));
++ ov2 = pfm.pfm2 >> 32;
++ }
++
++ write_perfctrl(control);
++
++ return 0;
++}
++
++struct op_nds32_model op_model_nds32_ops = {
++ .reg_setup = nds32_reg_setup,
++ .cpu_setup = nds32_cpu_setup,
++ .init = nds32_init,
++ .exit = nds32_exit,
++ .cpu_start = nds32_cpu_start,
++ .cpu_stop = nds32_cpu_stop,
++};
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/cpu-fcs.c linux-3.4.110/arch/nds32/platforms/ag101/cpu-fcs.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101/cpu-fcs.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101/cpu-fcs.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,401 @@
++/*
++ * linux/arch/nds32/platforms/ag101/cpu-fcs.c
++ *
++ * Copyright (C) 2002,2003 Intrinsyc Software
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * History:
++ * 31-Jul-2002 : Initial version [FB]
++ * 29-Jan-2003 : added PXA255 support [FB]
++ * 20-Apr-2003 : ported to v2.5 (Dustin McIntire, Sensoria Corp.)
++ * 18-Jun-2008 : ported to NDS32 architecture ( Roy Lee, Andestech Corp.)
++ *
++ * Note:
++ * This driver may change the memory bus clock rate, but will not do any
++ * platform specific access timing changes... for example if you have flash
++ * memory connected to CS0, you will need to register a platform specific
++ * notifier which will adjust the memory access strobes to maintain a
++ * minimum strobe width.
++ *
++ */
++#include <linux/module.h>
++#include <linux/cpufreq.h>
++#include <linux/interrupt.h>
++
++#include <asm/hardware.h>
++#include <asm/localmem.h>
++#include <asm/system.h>
++#include <asm/nds32.h>
++#include <asm/irq_regs.h>
++
++#define NDS32_FCS_IRQ 8
++#define AG101_MIN_FREQ 100000
++#define AG101_MAX_FREQ 400000
++#define OSC_KHZ 10000 /* 10 MHz AG101 */
++
++#define USE_CACHE 0
++struct ag101_freq_struct {
++
++ unsigned int khz; /* cpu_clk in khz */
++ unsigned int pll; /* pll mul */
++ unsigned int div; /* ahb div */
++ unsigned int frange; /* pll1 freq range */
++};
++
++struct ag101_freq_struct ag101_run_freqs[] = {
++
++ /* khz , pll, div, frange pll/cpu/ahb/apb */
++ {100000, 10, 2, 0}, /* 400/400/050/025 */
++ {200000, 20, 4, 1}, /* 400/400/050/025 */
++ {300000, 30, 6, 2}, /* 400/400/050/025 */
++ {400000, 40, 8, 2}, /* 400/400/050/025 */
++ {500000, 50, 10, 3}, /* 500/500/050/025 */
++ {0,}
++};
++
++#define NUM_RUN_FREQS ARRAY_SIZE( ag101_run_freqs)
++static struct cpufreq_frequency_table ag101_run_freq_table[NUM_RUN_FREQS + 1];
++
++/* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */
++static struct ag101_freq_struct ag101_turbo_freqs[] = {
++
++ /* khz , pll, div, frange pll/cpu/ahb/apb */
++ {100000, 10, 2, 0}, /* 400/400/050/025 */
++ {200000, 20, 4, 1}, /* 400/400/050/025 */
++ {300000, 30, 6, 2}, /* 400/400/050/025 */
++ {400000, 40, 8, 2}, /* 400/400/050/025 */
++ {500000, 50, 10, 3}, /* 500/500/050/025 */
++ {0,}
++};
++
++#define NUM_TURBO_FREQS ARRAY_SIZE( ag101_turbo_freqs)
++static struct cpufreq_frequency_table ag101_turbo_freq_table[NUM_TURBO_FREQS +
++ 1];
++
++/* Generic helper function get CPU clocks in kHz */
++unsigned int ag101_cpufreq_get(unsigned int dummy)
++{
++
++ unsigned int mul = (REG32(PMU_FTPMU010_VA_BASE + 0x30) >> 3UL) & 0x01ff; /* pll1 mul */
++ return OSC_KHZ * mul;
++}
++
++/* find a valid frequency point */
++static int ag101_verify_policy(struct cpufreq_policy *policy)
++{
++
++ struct cpufreq_frequency_table *ag101_freqs_table;
++
++ if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
++
++ ag101_freqs_table = ag101_run_freq_table;
++ } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) {
++
++ ag101_freqs_table = ag101_turbo_freq_table;
++ } else {
++ printk
++ ("CPU PXA: Unknown policy found. Using CPUFREQ_POLICY_PERFORMANCE\n");
++ ag101_freqs_table = ag101_run_freq_table;
++ }
++
++ printk("Verified CPU policy: %dKhz min to %dKhz max\n", policy->min,
++ policy->max);
++
++ return cpufreq_frequency_table_verify(policy, ag101_freqs_table);
++}
++
++static int cal_edivahbclk(int div)
++{
++
++ switch (div) {
++
++ case 1:
++ case 2:
++ case 3:
++ case 4:
++ case 5:
++ case 6:
++ return --div;
++ case 8:
++ return 8;
++ case 10:
++ return 9;
++ case 12:
++ return 10;
++ case 14:
++ return 11;
++ case 15:
++ return 12;
++ case 18:
++ return 13;
++ case 20:
++ return 14;
++ default:
++ printk("Error: No such CPU/AHB frequency ratio %d", div);
++ }
++
++ return 9;
++}
++
++void start_fcs(unsigned int pll, unsigned int frange, unsigned int div)
++{
++
++ /* PDLLCR0 */
++ REG32(PMU_FTPMU010_VA_BASE + 0x30) &= ~0x00003ff8; /* clear PLL1NS and PLL1FRANG fields */
++ REG32(PMU_FTPMU010_VA_BASE + 0x30) |= (pll << 3); /* set PLL1NS */
++ REG32(PMU_FTPMU010_VA_BASE + 0x30) |= (frange << 12); /* set PLL1FRANG */
++
++ /* PMODE */
++ REG32(PMU_FTPMU010_VA_BASE + 0x0c) &= ~0x000000ff; /* clear EDIVAHBCLK field */
++ REG32(PMU_FTPMU010_VA_BASE + 0x0c) |= (div << 4); /* set EDIVAHBCLK [7:4] */
++ REG32(PMU_FTPMU010_VA_BASE + 0x0c) |= (1UL << 2); /* [2]: FCS */
++
++ __asm__ __volatile__("msync all");
++ __asm__ __volatile__("isb");
++ __asm__ __volatile__("standby wake_grant");
++ REG32(PMU_FTPMU010_VA_BASE + 0x30) |= (1UL << 16); /* PDLLCR0 bit[16]==1:disable dll */
++}
++
++void end_fcs(void)
++{
++
++ /* Leave this function as a place marker. */
++}
++
++static int nds32_fcs_handler(int irq, void *dev_id)
++{
++
++ REG32(PMU_FTPMU010_VA_BASE + 0x20) = (1UL << 17); /* Clear IntFCS PMSR[17] */
++ REG32(PMU_FTPMU010_VA_BASE + 0x0c) &= ~(1UL << 2); /* Power Mode Register */
++
++ return 1;
++}
++
++static int ag101_speedstep(int idx)
++{
++
++ unsigned int pll, frange, div;
++ unsigned long flags = 0;
++ int irq, saved_irq_mask;
++ void (*do_fcs) (unsigned int pll, unsigned int frange,
++ unsigned int div);
++
++#if USE_CACHE
++
++ int i;
++ int line_size = CACHE_LINE_SIZE(ICACHE);
++ unsigned long start = ((unsigned long)start_fcs) & ~(line_size - 1);
++ unsigned long end =
++ (((unsigned long)end_fcs) + line_size) & ~(line_size - 1);
++
++ printk("&start_fcs(): 0x%08lx, aligned to: 0x%08lx\n",
++ (unsigned long)start_fcs, start);
++ printk("&end_fcs(): 0x%08lx, aligned to: 0x%08lx\n",
++ (unsigned long)end_fcs, end);
++
++ for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
++ __asm__ volatile ("\n\tcctl %0, L1I_VA_FILLCK"::
++ "r" (i):"memory");
++
++ do_fcs = start_fcs;
++#else
++ unsigned long buf, aligned_buf, len = PAGE_SIZE;
++
++ buf = (unsigned long)kmalloc(0x100000 + 1000, GFP_KERNEL);
++ if (!buf)
++ printk("Error: kmalloc( base) failed\n");
++
++ aligned_buf = (buf + 0x100000 - 1) & 0xFFF00000;
++
++ if (sys_lmmap(LM_ILM, aligned_buf, aligned_buf + 0x1000, 0, NULL)) {
++ printk("Error: lmmap failed, can't scale frequency.\n");
++#ifdef CONFIG_CPU_FREQ_DEBUG
++ WARN_ON(1);
++#endif
++ return 0;
++ }
++
++ if (((GET_ILMB() & ILMB_mskILMSZ) >> ILMB_offILMSZ) == 9)
++ len = 0x400;
++ else if (((GET_ILMB() & ILMB_mskILMSZ) >> ILMB_offILMSZ) == 10)
++ len = 0x800;
++ memcpy((unsigned char *)aligned_buf, (unsigned char *)start_fcs, len);
++
++ do_fcs = (void *)aligned_buf;
++#endif
++ pll = ag101_run_freqs[idx].pll;
++ div = cal_edivahbclk(ag101_run_freqs[idx].div);
++ frange = ag101_run_freqs[idx].frange;
++
++ irq =
++ request_irq(NDS32_FCS_IRQ, nds32_fcs_handler,
++ IRQF_DISABLED | IRQF_TRIGGER_FALLING,
++ "NDS32 Frequency Change Sequence",
++ (void *)ag101_run_freqs);
++ if (irq < 0)
++ printk(KERN_ERR "Error: unable to request FCS IRQ%d\n",
++ NDS32_FCS_IRQ);
++
++ local_irq_save(flags);
++
++ saved_irq_mask = REG32(INTC_FTINTC010_VA_BASE + 0x04);
++ REG32(INTC_FTINTC010_VA_BASE + 0x04) = (1UL << NDS32_FCS_IRQ);
++
++ do_fcs(pll, frange, div);
++
++ REG32(INTC_FTINTC010_VA_BASE + 0x04) = saved_irq_mask;
++
++ local_irq_restore(flags);
++ free_irq(NDS32_FCS_IRQ, ag101_run_freqs);
++
++#if USE_CACHE
++ for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
++ __asm__ volatile ("\n\tcctl %0, L1I_VA_ULCK"::"r" (i):"memory");
++#else
++ if (sys_lmunmap(aligned_buf, 0))
++ printk("Error: lmunmap failed\n");
++
++ kfree((void *)buf);
++#endif
++ return 1;
++}
++
++static int ag101_set_target(struct cpufreq_policy *policy,
++ unsigned int target_freq, unsigned int relation)
++{
++
++ unsigned int idx;
++ struct cpufreq_frequency_table *ag101_freqs_table;
++ struct ag101_freq_struct *ag101_freq_settings;
++ struct cpufreq_freqs freqs;
++
++ /* Get the current policy */
++ if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
++
++ ag101_freq_settings = ag101_run_freqs;
++ ag101_freqs_table = ag101_run_freq_table;
++ } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) {
++
++ ag101_freq_settings = ag101_turbo_freqs;
++ ag101_freqs_table = ag101_turbo_freq_table;
++ } else {
++ printk
++ ("Unknown FCS policy found. Using CPUFREQ_POLICY_PERFORMANCE\n");
++ ag101_freq_settings = ag101_run_freqs;
++ ag101_freqs_table = ag101_run_freq_table;
++ }
++
++ /* Lookup the next frequency */
++ if (cpufreq_frequency_table_target
++ (policy, ag101_freqs_table, target_freq, relation, &idx))
++ return -EINVAL;
++
++ freqs.old = policy->cur;
++ freqs.new = ag101_freq_settings[idx].khz;
++ freqs.cpu = policy->cpu;
++
++ /*
++ * Tell everyone what we're about to do...
++ * you should add a notify client with any platform specific
++ * Vcc changing capability
++ */
++ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
++
++ if (freqs.new != freqs.old) {
++ if (!ag101_speedstep(idx))
++ return -ENODEV;
++ }
++
++ /*
++ * Tell everyone what we've just done...
++ * you should add a notify client with any platform specific
++ * SDRAM refresh timer adjustments
++ */
++ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
++
++ return 0;
++}
++
++static int ag101_cpufreq_init(struct cpufreq_policy *policy)
++{
++
++ int i;
++ /* set default policy and cpuinfo */
++ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
++ policy->policy = CPUFREQ_POLICY_PERFORMANCE;
++ policy->cpuinfo.max_freq = AG101_MAX_FREQ;
++ policy->cpuinfo.min_freq = AG101_MIN_FREQ;
++ policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
++ policy->cur = ag101_cpufreq_get(0); /* current freq */
++ policy->min = policy->max = policy->cur;
++
++ /* Generate the run cpufreq_frequency_table struct */
++ for (i = 0; i < NUM_RUN_FREQS; i++) {
++
++ ag101_run_freq_table[i].frequency = ag101_run_freqs[i].khz;
++ ag101_run_freq_table[i].index = i;
++ }
++
++ ag101_run_freq_table[i].frequency = CPUFREQ_TABLE_END;
++
++ /* Generate the turbo cpufreq_frequency_table struct */
++ for (i = 0; i < NUM_TURBO_FREQS; i++) {
++
++ ag101_turbo_freq_table[i].frequency = ag101_turbo_freqs[i].khz;
++ ag101_turbo_freq_table[i].index = i;
++ }
++
++ ag101_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END;
++
++ printk("CPU frequency change support initialized\n");
++
++ return 0;
++}
++
++static struct cpufreq_driver ag101_cpufreq_driver = {
++
++ .verify = ag101_verify_policy,
++ .target = ag101_set_target,
++ .init = ag101_cpufreq_init,
++ .get = ag101_cpufreq_get,
++ .name = "AG101",
++};
++
++static int __init ag101_cpu_init(void)
++{
++
++ if (CPU_IS_N1213_43U1HA0() || CPU_IS_N1213_43U1HB0()) {
++
++ /* Clear IntFS, IntFCS and irq8 */
++ REG32(PMU_FTPMU010_VA_BASE + 0x20) = (1UL << 16);
++ return cpufreq_register_driver(&ag101_cpufreq_driver);
++ } else
++ return -ENODEV;
++}
++
++static void __exit ag101_cpu_exit(void)
++{
++
++ if (CPU_IS_N1213_43U1HA0() || CPU_IS_N1213_43U1HB0())
++ cpufreq_unregister_driver(&ag101_cpufreq_driver);
++}
++
++MODULE_AUTHOR("Andes Technology Corporation");
++MODULE_DESCRIPTION("CPU frequency changing driver for the AG101 architecture");
++MODULE_LICENSE("GPL");
++module_init(ag101_cpu_init);
++module_exit(ag101_cpu_exit);
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/devices.c linux-3.4.110/arch/nds32/platforms/ag101/devices.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101/devices.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101/devices.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,94 @@
++#include <linux/serial_8250.h>
++#include <asm/mach-types.h>
++#include <asm/sizes.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/spec.h>
++#include <asm/intc.h>
++#include <asm/timer.h>
++
++const struct map_desc platform_io_desc[] __initdata = {
++ {UART0_VA_BASE, UART0_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {UART1_VA_BASE, UART1_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {INTC_FTINTC010_0_VA_BASE, INTC_FTINTC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {TIMER_FTTMR010_0_VA_BASE, TIMER_FTTMR010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {SSP_FTSSP010_0_VA_BASE, SSP_FTSSP010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {PMU_FTPMU010_0_VA_BASE, PMU_FTPMU010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {MAC_FTMAC100_0_VA_BASE, MAC_FTMAC100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {SDC_FTSDC010_0_VA_BASE, SDC_FTSDC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {RTC_FTRTC010_0_VA_BASE, RTC_FTRTC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {WDT_FTWDT010_0_VA_BASE, WDT_FTWDT010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {GPIO_FTGPIO010_0_VA_BASE, GPIO_FTGPIO010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {CFC_FTCFC010_0_VA_BASE, CFC_FTCFC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {LCD_FTLCDC100_0_VA_BASE, LCD_FTLCDC100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {I2C_FTI2C010_0_VA_BASE, I2C_FTI2C010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {DMAC_FTDMAC020_0_VA_BASE, DMAC_FTDMAC020_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {APBBRG_FTAPBBRG020S_0_VA_BASE, APBBRG_FTAPBBRG020S_0_PA_BASE,
++ PAGE_SIZE, MT_DEVICE_NCB},
++ {KMI_FTKBC010_0_VA_BASE, KMI_FTKBC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCNB},
++ {KMI_FTKBC010_1_VA_BASE, KMI_FTKBC010_1_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCNB},
++ {USB_FUSB220_0_VA_BASE, USB_FUSB220_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCNB},
++ {PCIIO_0_VA_BASE, PCIIO_0_PA_BASE, 0x000FF000, MT_DEVICE_NCB},
++ {PCIC_FTPCI100_0_VA_BASE, PCIC_FTPCI100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {LED_VA_BASE, LED_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {SDMC_FTSDMC021_VA_BASE, SDMC_FTSDMC021_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {L2CC_VA_BASE, L2CC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB}
++};
++
++static void __init platform_map_io(void)
++{
++ iotable_init((struct map_desc *)platform_io_desc,
++ ARRAY_SIZE(platform_io_desc));
++}
++
++static struct uart_port uart0 = {
++ .membase = (void __iomem *)UART0_VA_BASE,
++ .irq = UART0_IRQ,
++ .uartclk = CONFIG_UART_CLK,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .line = 0,
++ .mapbase = UART0_PA_BASE,
++};
++
++static struct uart_port uart1 = {
++ .membase = (void __iomem *)UART1_VA_BASE,
++ .irq = UART1_IRQ,
++ .uartclk = CONFIG_UART_CLK,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .line = 1,
++ .mapbase = UART1_PA_BASE,
++};
++
++void ag101_calc_ahb_clk(void);
++static void __init soc_init(void)
++{
++ ag101_calc_ahb_clk();
++ early_serial_setup(&uart0);
++ early_serial_setup(&uart1);
++}
++
++MACHINE_START(FARADAY, PLATFORM_NAME)
++ .param_offset = BOOT_PARAMETER_PA_BASE,.map_io = platform_map_io,.init_irq = platform_init_irq,.timer = &platform_timer, /* defined in timer.c */
++ .init_machine = soc_init, MACHINE_END
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/fia320.c linux-3.4.110/arch/nds32/platforms/ag101/fia320.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101/fia320.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101/fia320.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,103 @@
++/*
++ * linux/arch/nds32/platforms/ag101/fia320.c
++ *
++ * Faraday A320D Platform Dependent Functions
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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
++ *
++ * ChangeLog
++ *
++ * Luke Lee 09/26/2005 Created
++ * Peter Liao 09/29/2005 Port dynamically getting AHB clock
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/pm.h>
++#include <linux/sched.h>
++#include <linux/irq.h>
++
++#include <asm/hardware.h>
++#include <asm/spec.h>
++
++#ifdef CONFIG_AUTO_SYS_CLK
++#include <nds32_intrinsic.h>
++#define AG101B0 (0x0c020003)
++
++/*
++ * Table for ahb divisor, PMODE[07:04]
++ */
++static const int ahb_div[16] = {
++ 1, 2, 3, 4, 5, 6, 3, 5,
++ 8, 10, 12, 14, 15, 18, 20, -1
++};
++
++/* ag101_get_ahb_clk()
++ *
++ * return AHB clock in Hz.
++ */
++static int ahbclk;
++void ag101_calc_ahb_clk(void)
++{
++ /*
++ * FIXME: We should not put AG101 term in here, Harry@Oct.23.2007
++ */
++ const unsigned int osc = 10; // OSC in MHz
++ unsigned int mul, div, cpu, pll;
++ unsigned int ahb = 0; // ahb clk in Hz
++ unsigned int cpu_ver;
++
++ mul = (REG32(PMU_FTPMU010_0_VA_BASE + 0x30) >> 3) & 0x01ff; // pll1 mul
++ div = (REG32(PMU_FTPMU010_0_VA_BASE + 0x4) >> 8) & 0x000f; // pll1 div
++ ahb = (REG32(PMU_FTPMU010_0_VA_BASE + 0x4) >> 4) & 0x000f; // ahb div
++ div += 1;
++
++ pll = (osc * mul / div); // depend on OSC.
++
++ //AG101B0 PLL divider fix
++ cpu_ver = __nds32__mfsr(NDS32_SR_CPU_VER);
++ if (AG101B0 == cpu_ver)
++ pll >>= 1;
++
++ if (-1 != ahb_div[ahb]) {
++ if ((ahb == 6) || (ahb == 7)) // special cases for 3:2 & 5:2
++ cpu = pll >> 1; // divide by 2
++ else
++ cpu = pll;
++
++ ahb = pll / ahb_div[ahb]; // become ahb clk in MHz.
++
++ printk("AG101 auto-detected AHB clock: CPU/AHB=%uMHz/%uMHz\n",
++ cpu, ahb);
++ ahb *= 1000000; // become ahb clk in Hz.
++ ahbclk = (int)ahb;
++ } else {
++ printk("Unknown AHB divisor:0x%x\n", ahb);
++ ahbclk = 0;
++ }
++
++ ahbclk = (int)ahb;
++}
++
++int ag101_get_ahb_clk(void)
++{
++ return ahbclk;
++}
++
++EXPORT_SYMBOL(ag101_get_ahb_clk);
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/freq-scaling.c linux-3.4.110/arch/nds32/platforms/ag101/freq-scaling.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101/freq-scaling.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101/freq-scaling.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,367 @@
++/*
++ * linux/arch/nds32/platforms/ag101/cpu-fcs.c
++ *
++ * Copyright (C) 2002,2003 Intrinsyc Software
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * History:
++ * 31-Jul-2002 : Initial version [FB]
++ * 29-Jan-2003 : added PXA255 support [FB]
++ * 20-Apr-2003 : ported to v2.5 (Dustin McIntire, Sensoria Corp.)
++ * 18-Jun-2008 : ported to NDS32 architecture ( Roy Lee, Andestech Corp.)
++ *
++ * Note:
++ * This driver may change the memory bus clock rate, but will not do any
++ * platform specific access timing changes... for example if you have flash
++ * memory connected to CS0, you will need to register a platform specific
++ * notifier which will adjust the memory access strobes to maintain a
++ * minimum strobe width.
++ *
++ */
++#include <linux/module.h>
++#include <linux/cpufreq.h>
++#include <linux/interrupt.h>
++
++#include <asm/hardware.h>
++#include <asm/localmem.h>
++#include <asm/system.h>
++#include <asm/nds32.h>
++#include <asm/irq_regs.h>
++
++#define NDS32_FCS_IRQ 8
++#define AG101_MIN_FREQ 70000
++#define AG101_MAX_FREQ 420000
++#define OSC_KHZ 10000 /* 10 MHz AG101 */
++
++#define USE_CACHE 0
++struct ag101_freq_struct {
++
++ unsigned int khz; /* cpu_clk in khz */
++ unsigned int sf; /* scaling factor */
++ unsigned int cr; /* clock ratio */
++};
++
++struct ag101_freq_struct ag101_run_freqs[] = {
++
++ /* khz , sf, cr pll/cpu/ahb/apb */
++ {AG101_MAX_FREQ / 6, 6, 1}, /* 420/070/070/035 */
++ {AG101_MAX_FREQ / 1, 1, 6}, /* 420/420/070/035 */
++ {0}
++};
++
++#define NUM_RUN_FREQS ARRAY_SIZE( ag101_run_freqs)
++static struct cpufreq_frequency_table ag101_run_freq_table[NUM_RUN_FREQS + 1];
++
++/* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */
++static struct ag101_freq_struct ag101_turbo_freqs[] = {
++
++ /* khz , sf, cr pll/cpu/ahb/apb */
++ {AG101_MAX_FREQ / 6, 6, 1}, /* 420/070/070/035 */
++ {AG101_MAX_FREQ / 1, 1, 6}, /* 420/420/070/035 */
++ {0}
++};
++
++#define NUM_TURBO_FREQS ARRAY_SIZE( ag101_turbo_freqs)
++static struct cpufreq_frequency_table ag101_turbo_freq_table[NUM_TURBO_FREQS +
++ 1];
++
++/* Generic helper function get CPU clocks in kHz */
++unsigned int ag101_cpufreq_get(unsigned int dummy)
++{
++
++ unsigned int pll = (REG32(PMU_FTPMU010_VA_BASE + 0x30) >> 3UL) & 0x01ff; /* pll */
++ unsigned int sf = (REG32(PMU_FTPMU010_VA_BASE + 0x0c) >> 8UL) & 0x0f; /* scaling factor */
++
++ return OSC_KHZ * pll / (sf + 1);
++}
++
++/* find a valid frequency point */
++static int ag101_verify_policy(struct cpufreq_policy *policy)
++{
++
++ struct cpufreq_frequency_table *ag101_freqs_table;
++
++ if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
++
++ ag101_freqs_table = ag101_run_freq_table;
++ } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) {
++
++ ag101_freqs_table = ag101_turbo_freq_table;
++ } else {
++ printk
++ ("CPU PXA: Unknown policy found. Using CPUFREQ_POLICY_PERFORMANCE\n");
++ ag101_freqs_table = ag101_run_freq_table;
++ }
++
++ printk("Verified CPU policy: %dKhz min to %dKhz max\n", policy->min,
++ policy->max);
++
++ return cpufreq_frequency_table_verify(policy, ag101_freqs_table);
++}
++
++void start_fcs(unsigned int sf, unsigned cr)
++{
++
++ /* set EFSF in PMODE [11:8] */
++ REG32(PMU_FTPMU010_VA_BASE + 0x0c) &= ~(0xfUL << 8);
++ REG32(PMU_FTPMU010_VA_BASE + 0x0c) |= (sf << 8);
++
++ /* set EDIVAHBCLK [7:4] */
++ REG32(PMU_FTPMU010_VA_BASE + 0x0c) &= ~(0xffUL << 0);
++ REG32(PMU_FTPMU010_VA_BASE + 0x0c) |= (cr << 4);
++
++ /* PMR[1]: scaling mode */
++ REG32(PMU_FTPMU010_VA_BASE + 0x0c) |= (1UL << 1);
++
++ __asm__ __volatile__("msync all");
++ __asm__ __volatile__("isb");
++ __asm__ __volatile__("standby wake_grant");
++ // REG32( PMU_FTPMU010_VA_BASE + 0x30) |= ( 1UL << 16); /* PDLLCR0 bit[16]==1:disable dll */
++ REG32(PMU_FTPMU010_VA_BASE + 0x0c) &= ~(1UL << 1); /* Power Mode Register */
++}
++
++void end_fcs(void)
++{
++
++ /* Leave this function as a place marker. */
++}
++
++static int cal_edivahbclk(int div)
++{
++
++ switch (div) {
++
++ case 1:
++ case 2:
++ case 3:
++ case 4:
++ case 5:
++ case 6:
++ return --div;
++ case 8:
++ return 8;
++ case 10:
++ return 9;
++ case 12:
++ return 10;
++ case 14:
++ return 11;
++ case 15:
++ return 12;
++ case 18:
++ return 13;
++ case 20:
++ return 14;
++ default:
++ printk("Error: No such CPU/AHB frequency ratio %d", div);
++ }
++
++ return 9;
++}
++
++static int ag101_speedstep(int idx)
++{
++
++ unsigned int sf, cr;
++ unsigned long flags = 0;
++ void (*do_fcs) (unsigned int efsf, unsigned int edivhbaclk);
++
++#if USE_CACHE
++
++ int i;
++ int line_size = CACHE_LINE_SIZE(ICACHE);
++ unsigned long start = ((unsigned long)start_fcs) & ~(line_size - 1);
++ unsigned long end =
++ (((unsigned long)end_fcs) + line_size) & ~(line_size - 1);
++
++ printk("&start_fcs(): 0x%08lx, aligned to: 0x%08lx\n",
++ (unsigned long)start_fcs, start);
++ printk("&end_fcs(): 0x%08lx, aligned to: 0x%08lx\n",
++ (unsigned long)end_fcs, end);
++
++ for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
++ __asm__ volatile ("\n\tcctl %0, L1I_VA_FILLCK"::
++ "r" (i):"memory");
++
++ do_fcs = start_fcs;
++#else
++ unsigned long buf, aligned_buf, len = PAGE_SIZE;
++
++ buf = (unsigned long)kmalloc(0x100000 + 1000, GFP_KERNEL);
++ if (!buf)
++ printk("Error: kmalloc( base) failed\n");
++
++ aligned_buf = (buf + 0x100000 - 1) & 0xFFF00000;
++
++ if (sys_lmmap(LM_ILM, aligned_buf, aligned_buf + 0x1000, 0, NULL)) {
++ printk("Error: lmmap failed, can't scale frequency.\n");
++#ifdef CONFIG_CPU_FREQ_DEBUG
++ WARN_ON(1);
++#endif
++ return 0;
++ }
++
++ if (((GET_ILMB() & ILMB_mskILMSZ) >> ILMB_offILMSZ) == 9)
++ len = 0x400;
++ else if (((GET_ILMB() & ILMB_mskILMSZ) >> ILMB_offILMSZ) == 10)
++ len = 0x800;
++ memcpy((unsigned char *)aligned_buf, (unsigned char *)start_fcs, len);
++
++ do_fcs = (void *)aligned_buf;
++#endif
++ sf = ag101_run_freqs[idx].sf - 1;
++ cr = cal_edivahbclk(ag101_run_freqs[idx].cr);
++
++ local_irq_save(flags);
++ do_fcs(sf, cr);
++ local_irq_restore(flags);
++
++#if USE_CACHE
++ for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
++ __asm__ volatile ("\n\tcctl %0, L1I_VA_ULCK"::"r" (i):"memory");
++#else
++ if (sys_lmunmap(aligned_buf, 0))
++ printk("Error: lmunmap failed\n");
++
++ kfree((void *)buf);
++#endif
++ return 1;
++}
++
++static int ag101_set_target(struct cpufreq_policy *policy,
++ unsigned int target_freq, unsigned int relation)
++{
++
++ unsigned int idx;
++ struct cpufreq_frequency_table *ag101_freqs_table;
++ struct ag101_freq_struct *ag101_freq_settings;
++ struct cpufreq_freqs freqs;
++
++ /* Get the current policy */
++ if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) {
++
++ ag101_freq_settings = ag101_run_freqs;
++ ag101_freqs_table = ag101_run_freq_table;
++ } else if (policy->policy == CPUFREQ_POLICY_POWERSAVE) {
++
++ ag101_freq_settings = ag101_turbo_freqs;
++ ag101_freqs_table = ag101_turbo_freq_table;
++ } else {
++ printk
++ ("Unknown FCS policy found. Using CPUFREQ_POLICY_PERFORMANCE\n");
++ ag101_freq_settings = ag101_run_freqs;
++ ag101_freqs_table = ag101_run_freq_table;
++ }
++
++ /* Lookup the next frequency */
++ if (cpufreq_frequency_table_target
++ (policy, ag101_freqs_table, target_freq, relation, &idx))
++ return -EINVAL;
++
++ freqs.old = policy->cur;
++ freqs.new = ag101_freq_settings[idx].khz;
++ freqs.cpu = policy->cpu;
++
++ /*
++ * Tell everyone what we're about to do...
++ * you should add a notify client with any platform specific
++ * Vcc changing capability
++ */
++ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
++
++ if (freqs.new != freqs.old) {
++
++ if (!ag101_speedstep(idx))
++ return -ENODEV;
++ }
++
++ /*
++ * Tell everyone what we've just done...
++ * you should add a notify client with any platform specific
++ * SDRAM refresh timer adjustments
++ */
++ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
++
++ return 0;
++}
++
++static int ag101_cpufreq_init(struct cpufreq_policy *policy)
++{
++
++ int i;
++ /* set default policy and cpuinfo */
++ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
++ policy->policy = CPUFREQ_POLICY_PERFORMANCE;
++ policy->cpuinfo.max_freq = AG101_MAX_FREQ;
++ policy->cpuinfo.min_freq = AG101_MIN_FREQ;
++ policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
++ policy->cur = ag101_cpufreq_get(0); /* current freq */
++ policy->min = policy->max = policy->cur;
++
++ /* Generate the run cpufreq_frequency_table struct */
++ for (i = 0; i < NUM_RUN_FREQS; i++) {
++
++ ag101_run_freq_table[i].frequency = ag101_run_freqs[i].khz;
++ ag101_run_freq_table[i].index = i;
++ }
++
++ ag101_run_freq_table[i].frequency = CPUFREQ_TABLE_END;
++
++ /* Generate the turbo cpufreq_frequency_table struct */
++ for (i = 0; i < NUM_TURBO_FREQS; i++) {
++
++ ag101_turbo_freq_table[i].frequency = ag101_turbo_freqs[i].khz;
++ ag101_turbo_freq_table[i].index = i;
++ }
++
++ ag101_turbo_freq_table[i].frequency = CPUFREQ_TABLE_END;
++
++ printk("CPU frequency change support initialized\n");
++
++ return 0;
++}
++
++static struct cpufreq_driver ag101_cpufreq_driver = {
++
++ .verify = ag101_verify_policy,
++ .target = ag101_set_target,
++ .init = ag101_cpufreq_init,
++ .get = ag101_cpufreq_get,
++ .name = "AG101",
++};
++
++static int __init ag101_cpu_init(void)
++{
++
++ if (CPU_IS_N1213_43U1HA0() || CPU_IS_N1213_43U1HB0())
++ return cpufreq_register_driver(&ag101_cpufreq_driver);
++ else
++ return -ENODEV;
++}
++
++static void __exit ag101_cpu_exit(void)
++{
++
++ if (CPU_IS_N1213_43U1HA0() || CPU_IS_N1213_43U1HB0())
++ cpufreq_unregister_driver(&ag101_cpufreq_driver);
++}
++
++MODULE_AUTHOR("Andes Technology Corporation");
++MODULE_DESCRIPTION("CPU frequency changing driver for the AG101 architecture");
++MODULE_LICENSE("GPL");
++module_init(ag101_cpu_init);
++module_exit(ag101_cpu_exit);
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/Kconfig linux-3.4.110/arch/nds32/platforms/ag101/Kconfig
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101/Kconfig 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,9 @@
++menu "AG101 Platform Options"
++
++config AUTO_SYS_CLK
++ bool "Automatic AHB Clock Detection"
++ default y
++ help
++ Automatic detection of AHB clock
++
++endmenu
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/Makefile linux-3.4.110/arch/nds32/platforms/ag101/Makefile
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101/Makefile 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,5 @@
++obj-y = devices.o
++obj-$(CONFIG_AUTO_SYS_CLK) += fia320.o
++obj-$(CONFIG_PM) += pm.o sleep.o
++obj-$(CONFIG_AG101_CPU_FREQ_FCS) += cpu-fcs.o
++obj-$(CONFIG_AG101_CPU_FREQ_SCALING_MODE) += freq-scaling.o
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/pm.c linux-3.4.110/arch/nds32/platforms/ag101/pm.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101/pm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101/pm.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,190 @@
++/*
++ * AG101 Power Management Routines
++ *
++ * Copyright (c) 2007 Harry Pan <harry@andestech.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License.
++ *
++ * Abstract:
++ *
++ * This program is for AG101 power management routines.
++ * It is initail referred from 2.6.11 SA1100 PM driver.
++ *
++ * Revision History:
++ *
++ * Jul.13.2007 Initial code by Harry.
++ */
++#include <linux/init.h>
++#include <linux/suspend.h>
++#include <linux/errno.h>
++#include <linux/time.h>
++#include <linux/delay.h>
++
++#include <asm/hardware.h>
++#include <asm/memory.h>
++#include <asm/system.h>
++#include <asm/mach/time.h>
++#include <asm/cacheflush.h>
++
++extern void ag101_cpu_sleep(void);
++extern void ag101_cpu_resume(void);
++extern void ag101_cpu_resume2(void);
++
++#include <asm/timer.h>
++/*
++ * AG101 PMU sleep mode handler.
++ */
++void ag101_pmu_sleep(void)
++{
++ int i;
++ static int irq_saves[3];
++
++ irq_saves[0] = REG32(INTC_FTINTC010_VA_BASE + 0x4);
++ irq_saves[1] = REG32(INTC_FTINTC010_VA_BASE + 0xc);
++ irq_saves[2] = REG32(INTC_FTINTC010_VA_BASE + 0x10);
++
++ /* save SDRAM settings */
++ for (i = 0; i < 0x30; i += 4)
++ REG32(PMU_FTPMU010_VA_BASE + 0x50 + i) = REG32(SDMC_FTSDMC021_VA_BASE + i); //SDRAMC
++
++ /* set resume return address */
++ REG32(PMU_FTPMU010_VA_BASE + 0x88) =
++ virt_to_phys(ag101_cpu_resume) | 0x10000000;
++ REG32(PMU_FTPMU010_VA_BASE + 0x8c) = (u32) ag101_cpu_resume2;
++ REG32(PMU_FTPMU010_VA_BASE + 0x80) = GET_L1_PPTB();
++
++ /* setup wakeup sources */
++ REG32(PMU_FTPMU010_VA_BASE + 0x14) |= -1;
++ REG32(PMU_FTPMU010_VA_BASE + 0x10) |= 0x1fff;
++
++ cpu_dcache_wbinval_all();
++ cpu_icache_inval_all();
++ SET_CACHE_CTL(GET_CACHE_CTL() & ~CACHE_CTL_mskDC_EN);
++ ag101_cpu_sleep();
++
++#ifndef CONFIG_ANDES_PAGE_SIZE_8KB
++
++ if (CPU_IS_N1213_43U1HA0()) {
++ int tmp = 0;
++ /* Downsize cache to bypass cache aliasing issue */
++
++ if ((CACHE_SET(ICACHE) * CACHE_LINE_SIZE(ICACHE)) > 4096)
++ tmp = 0x02 << SDZ_CTL_offICDZ;
++
++ if ((CACHE_SET(DCACHE) * CACHE_LINE_SIZE(DCACHE)) > 4096)
++ tmp |= 0x02 << SDZ_CTL_offDCDZ;
++
++ SET_SDZ_CTL(tmp);
++ ISB();
++ }
++#endif
++
++ SET_CACHE_CTL(GET_CACHE_CTL() | CACHE_CTL_mskDC_EN);
++ REG32(INTC_FTINTC010_VA_BASE + 0x4) = irq_saves[0];
++ REG32(INTC_FTINTC010_VA_BASE + 0xc) = irq_saves[1];
++ REG32(INTC_FTINTC010_VA_BASE + 0x10) = irq_saves[2];
++}
++
++static int ag101_pm_valid(suspend_state_t state)
++{
++ switch (state) {
++ case PM_SUSPEND_ON:
++ case PM_SUSPEND_STANDBY:
++ case PM_SUSPEND_MEM:
++ return 1;
++
++ default:
++ return 0;
++ }
++}
++
++static int ag101_pm_begin(suspend_state_t state)
++{
++ /* TBD if we need it */
++ return 0;
++}
++
++static unsigned long irq_save;
++static inline void setup_wakeup_event(void)
++{
++ REG32(GPIO_FTGPIO010_VA_BASE + 0x20) = 1;
++ irq_save = REG32(INTC_FTINTC010_VA_BASE + 0x4);
++ REG32(INTC_FTINTC010_VA_BASE + 0x4) &= ~(1 << 19);
++ REG32(INTC_FTINTC010_VA_BASE + 0x4) |= 1 << 13;
++}
++
++static inline void remove_wakeup_event(void)
++{
++ REG32(GPIO_FTGPIO010_VA_BASE + 0x30) = 1;
++ REG32(GPIO_FTGPIO010_VA_BASE + 0x20) = 0;
++ REG32(INTC_FTINTC010_VA_BASE + 0x4) = irq_save;
++}
++
++static inline void cpu_standby(void)
++{
++ asm __volatile__("standby no_wake_grant");
++}
++
++static int ag101_pm_enter(suspend_state_t state)
++{
++ switch (state) {
++ case PM_SUSPEND_STANDBY:
++ setup_wakeup_event();
++ cpu_standby();
++ remove_wakeup_event();
++ return 0;
++ case PM_SUSPEND_MEM:
++ ag101_pmu_sleep();
++ return 0;
++ default:
++ return -EINVAL;
++ }
++}
++
++/*
++ * Called after processes are frozen, but before we shutdown devices.
++ */
++static int ag101_pm_prepare(void)
++{
++ /* TBD if we need it */
++ return 0;
++}
++
++/*
++ * Called after devices are wakeuped, but before processes are thawed.
++ */
++static void ag101_pm_finish(void)
++{
++ /* TBD if we need it */
++}
++
++static void ag101_pm_end(void)
++{
++ /* TBD if we need it */
++}
++
++/*
++ * Set to PM_DISK_FIRMWARE so we can quickly veto suspend-to-disk.
++ */
++static struct platform_suspend_ops ag101_pm_ops = {
++ .valid = ag101_pm_valid,
++ .begin = ag101_pm_begin,
++ .prepare = ag101_pm_prepare,
++ .enter = ag101_pm_enter,
++ .finish = ag101_pm_finish,
++ .end = ag101_pm_end,
++};
++
++static int __init ag101_pm_init(void)
++{
++ printk("PM driver init\n");
++ suspend_set_ops(&ag101_pm_ops);
++ REG32(GPIO_FTGPIO010_VA_BASE + 0x30) = 1;
++ REG32(INTC_FTINTC010_VA_BASE + 0x0c) &= ~(1 << 13);
++ REG32(INTC_FTINTC010_VA_BASE + 0x10) &= ~(1 << 13);
++
++ return 0;
++}
++
++late_initcall(ag101_pm_init);
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101/sleep.S linux-3.4.110/arch/nds32/platforms/ag101/sleep.S
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101/sleep.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101/sleep.S 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,118 @@
++/*
++ * AG101 Assembler Sleep/WakeUp Management Routines
++ *
++ * Copyright (c) 2007 Harry Pan <harry@andestech.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License.
++ *
++ * Abstract:
++ *
++ * This program is for AG101 suspend/wakeup.
++ *
++ * Revision History:
++ *
++ * Jul.13.2007 Initial code by Harry.
++ */
++#include <linux/linkage.h>
++#include <asm/assembler.h>
++#include <asm/hardware.h>
++#include <asm/spec.h>
++
++ .text
++
++/* ag101_cpu_suspend()
++ *
++ * Causes AG101 to enter sleep state
++ */
++
++ENTRY(ag101_cpu_sleep)
++ pushm $r0, $r30
++ mfusr $r0, $d0.lo ! $d0 lo byte
++ mfusr $r1, $d0.hi ! $d0 hi byte
++ mfusr $r2, $d1.lo ! $d1 lo byte
++ mfusr $r3, $d1.hi ! $d1 hi byte
++ mfsr $r4, $mr0
++ mfsr $r5, $mr1
++ mfsr $r6, $mr4
++ mfsr $r7, $mr6
++ mfsr $r8, $mr7
++ mfsr $r9, $mr8
++ mfsr $r10, $ir0
++ mfsr $r11, $ir1
++ mfsr $r12, $ir2
++ mfsr $r13, $ir3
++ mfsr $r14, $ir9
++ mfsr $r15, $ir10
++ mfsr $r16, $ir12
++ mfsr $r17, $ir13
++ mfsr $r18, $ir14
++ mfsr $r19, $ir15
++ pushm $r0, $r19
++
++ sethi $r0, hi20(PMU_FTPMU010_0_VA_BASE + 0x84)
++ ori $r2, $r0, lo12(PMU_FTPMU010_0_VA_BASE + 0x84)
++ swi $r31, [$r2]
++
++ lwi $r2, [$r0+#0x0c] ! sleep mode
++ ori $r2, $r2, #1
++ swi $r2, [$r0+#0x0c] ! sleep mode
++ standby wake_grant
++1:
++ b 1b ! loop waiting for sleep
++
++/* ag101_cpu_resume()
++ *
++ * Entry point from boot code back to kernel.
++ *
++ */
++
++ENTRY(ag101_cpu_resume)
++ mfsr $r2, $mr0
++ ori $r2, $r2, #0x6
++#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
++ ori $r2, $r2, #0x1
++#endif
++ mtsr $r2, $mr0
++
++ sethi $r2, hi20(PMU_FTPMU010_0_PA_BASE + 0x80)
++ ori $r2, $r2, lo12(PMU_FTPMU010_0_PA_BASE + 0x80)
++ lwi $r3, [$r2]
++ lwi $r4, [$r2 + 0xc]
++ mtsr $r3, $mr1
++
++ mfsr $r0, $mr8
++ ori $r0, $r0, #0x1
++ mtsr $r0, $mr8
++
++ sethi $r2, hi20(AHB_ATFAHBC020S_0_PA_BASE + 0x88)
++ ori $r2, $r2, lo12(AHB_ATFAHBC020S_0_PA_BASE + 0x88)
++ movi $r3, #0x1
++ swi $r3, [$r2]
++
++ jral.ton $r4, $r4
++
++ENTRY(ag101_cpu_resume2)
++ popm $r0, $r19
++ mtusr $r0, $d0.lo ! $d0 lo byte
++ mtusr $r1, $d0.hi ! $d0 hi byte
++ mtusr $r2, $d1.lo ! $d1 lo byte
++ mtusr $r3, $d1.hi ! $d1 hi byte
++ mtsr $r4, $mr0
++ mtsr $r5, $mr1
++ mtsr $r6, $mr4
++ mtsr $r7, $mr6
++ mtsr $r8, $mr7
++ mtsr $r9, $mr8
++ mtsr $r10, $ir0
++ mtsr $r11, $ir1
++ mtsr $r12, $ir2
++ mtsr $r13, $ir3
++ mtsr $r14, $ir9
++ mtsr $r15, $ir10
++ mtsr $r16, $ir12
++ mtsr $r17, $ir13
++ mtsr $r18, $ir14
++ mtsr $r19, $ir15
++ popm $r0, $r30
++ ret
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101p/devices.c linux-3.4.110/arch/nds32/platforms/ag101p/devices.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101p/devices.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101p/devices.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,104 @@
++#include <linux/serial_8250.h>
++#include <asm/mach-types.h>
++#include <asm/sizes.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/spec.h>
++#include <asm/timer.h>
++
++const struct map_desc platform_io_desc[] __initdata = {
++ {UART0_VA_BASE, UART0_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {UART1_VA_BASE, UART1_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {INTC_FTINTC010_0_VA_BASE, INTC_FTINTC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {TIMER_FTTMR010_0_VA_BASE, TIMER_FTTMR010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {SSP_FTSSP010_0_VA_BASE, SSP_FTSSP010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {PMU_FTPMU010_0_VA_BASE, PMU_FTPMU010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {MAC_FTMAC100_0_VA_BASE, MAC_FTMAC100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {SDC_FTSDC010_0_VA_BASE, SDC_FTSDC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {RTC_FTRTC010_0_VA_BASE, RTC_FTRTC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {WDT_FTWDT010_0_VA_BASE, WDT_FTWDT010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {GPIO_FTGPIO010_0_VA_BASE, GPIO_FTGPIO010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {CFC_FTCFC010_0_VA_BASE, CFC_FTCFC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {LCD_FTLCDC100_0_VA_BASE, LCD_FTLCDC100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {I2C_FTI2C010_0_VA_BASE, I2C_FTI2C010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {DMAC_FTDMAC020_0_VA_BASE, DMAC_FTDMAC020_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {APBBRG_FTAPBBRG020S_0_VA_BASE, APBBRG_FTAPBBRG020S_0_PA_BASE,
++ PAGE_SIZE, MT_DEVICE_NCB},
++ {USB_FOTG2XX_0_VA_BASE, USB_FOTG2XX_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {PCIIO_0_VA_BASE, PCIIO_0_PA_BASE, (0x000FF000 & PAGE_MASK),
++ MT_DEVICE_NCB},
++ {PCIC_FTPCI100_0_VA_BASE, PCIC_FTPCI100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {AHB_ATFAHBC020S_0_VA_BASE, AHB_ATFAHBC020S_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {LED_VA_BASE, LED_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {SDMC_FTSDMC021_VA_BASE, SDMC_FTSDMC021_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {L2CC_VA_BASE, L2CC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB}
++};
++
++static void __init platform_map_io(void)
++{
++ iotable_init((struct map_desc *)platform_io_desc,
++ ARRAY_SIZE(platform_io_desc));
++}
++
++static struct uart_port uart0 = {
++ .membase = (void __iomem *)UART0_VA_BASE,
++ .irq = UART0_IRQ,
++ .uartclk = CONFIG_UART_CLK,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .line = 0,
++ .mapbase = UART0_PA_BASE,
++};
++
++static struct uart_port uart1 = {
++ .membase = (void __iomem *)UART1_VA_BASE,
++ .irq = UART1_IRQ,
++ .uartclk = CONFIG_UART_CLK,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .line = 1,
++ .mapbase = UART1_PA_BASE,
++};
++
++static void __init soc_init(void)
++{
++ early_serial_setup(&uart0);
++ early_serial_setup(&uart1);
++}
++
++MACHINE_START(FARADAY, PLATFORM_NAME)
++ .param_offset = BOOT_PARAMETER_PA_BASE,
++ .map_io = platform_map_io,
++ .init_irq = platform_init_irq,
++ .timer = &platform_timer, /* defined in timer.c */
++ .init_machine = soc_init,
++MACHINE_END static struct platform_device usb_dev_otg_host = {
++ .name = "fotg-ehci",
++};
++
++static int __init fotg_init(void)
++{
++ platform_device_register(&usb_dev_otg_host);
++ return 0;
++}
++
++device_initcall(fotg_init);
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101p/interrupt-latency.c linux-3.4.110/arch/nds32/platforms/ag101p/interrupt-latency.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101p/interrupt-latency.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101p/interrupt-latency.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,197 @@
++/*
++ * interrupt_latency v1.0 11/25/01
++ * www.embeddedlinuxinterfacing.com
++ *
++ * The original location of this code is
++ * http://www.embeddedlinuxinterfacing.com/chapters/11/
++ *
++ * Copyright (C) 2001 by Craig Hollabaugh
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU Library 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
++ * Library General Public License for more details.
++ *
++ * You should have received a copy of the GNU Library 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
++ */
++
++/*
++ * interrupt_latency.c is based on procfs_example.c by Erik Mouw.
++ * For more information, please see, The Linux Kernel Procfs Guide, Erik Mouw
++ * http://kernelnewbies.org/documents/kdoc/procfs-guide/lkprocfsguide.html
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/proc_fs.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <nds32_intrinsic.h>
++
++#define ILT_MODULE_VERSION "1.0"
++#define MODULE_NAME "interrupt_latency"
++
++#define USE_PFM
++static int interruptcount = 0;
++#ifdef USE_PFM
++static unsigned int start_cycle = 0, finish_cycle = 0;
++static unsigned int start_inst = 0, finish_inst = 0;
++static unsigned int start_int = 0, finish_int = 0;
++#else
++static struct timeval tv1, tv2; /* do_gettimeofday fills these */
++#endif
++
++#define INTERRUPT 9
++
++static struct proc_dir_entry *interrupt_latency_file;
++
++/*
++ * function interrupt_interrupt_latency
++ * This function is the interrupt handler for interrupt 7. It sets the tv2
++ * structure using do_gettimeofday. It then deasserts D7.
++ */
++static irqreturn_t interrupt_interrupt_latency(int irq, void *dev_id)
++{
++ unsigned int ir15, pfm_ctl;
++#ifdef USE_PFM
++ /* disable counter */
++ pfm_ctl = 0x4410000; //cycles, instructions and icache misses
++ //pfm_ctl = 0x4c0000; //instructions and interrupts
++ //pfm_ctl = 0x4510000; //icache accesses and misses
++ __nds32__mtsr(pfm_ctl, NDS32_SR_PFM_CTL); //instructions and interrupts
++ finish_cycle = __nds32__mfsr(NDS32_SR_PFMC0);
++ finish_inst = __nds32__mfsr(NDS32_SR_PFMC2);
++ finish_int = __nds32__mfsr(NDS32_SR_PFMC1);
++#else
++ do_gettimeofday(&tv2);
++#endif
++ /* deassert the interrupt signal */
++ ir15 = __nds32__mfsr(NDS32_SR_INT_PEND);
++ __nds32__mtsr((~0x10000) & ir15, NDS32_SR_INT_PEND);
++ __nds32__dsb();
++
++ interruptcount++;
++ return IRQ_HANDLED;
++}
++
++/*
++ * function proc_read_interrupt_latency
++ * The kernel executes this function when a read operation occurs on
++ * /proc/interrupt_latency. This function sets the tv1 structure. It asserts
++ * D7 which should immediately cause interrupt 7 to occur. The handler
++ * records tv2 and deasserts D7. This function returns the time differential
++ * between tv2 and tv1.
++ */
++static int proc_read_interrupt_latency(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len;
++ unsigned int ir15, pfm_ctl;
++#ifdef USE_PFM
++ //pfm_ctl = 0x4c0007;
++ //pfm_ctl = 0x4510007;
++ pfm_ctl = 0x4410007;
++ start_cycle = __nds32__mfsr(NDS32_SR_PFMC0);
++ start_inst = __nds32__mfsr(NDS32_SR_PFMC2);
++ start_int = __nds32__mfsr(NDS32_SR_PFMC1);
++ __nds32__mtsr(pfm_ctl, NDS32_SR_PFM_CTL);
++#else
++ do_gettimeofday(&tv1);
++#endif
++ /* assert the interrupt signal */
++ ir15 = __nds32__mfsr(NDS32_SR_INT_PEND);
++ __nds32__mtsr(0x10000 | ir15, NDS32_SR_INT_PEND);
++ __nds32__dsb();
++
++#ifdef USE_PFM
++ len =
++ sprintf(page,
++ "Cnt0 %11u Start %11u Finish %11u Cycles %11u\n"
++ "Cnt2 %11u Start %11u Finish %11u icache miss %11u\n"
++ "Cnt1 %11u Start %11u Finish %11u Instructions %11u\n"
++ "Count %11i\n", ((pfm_ctl & 0x8000) >> 15), start_cycle,
++ finish_cycle, (finish_cycle - start_cycle),
++ ((pfm_ctl & 0xfc00000) >> 22), start_inst, finish_inst,
++ (finish_inst - start_inst), ((pfm_ctl & 0x3f0000) >> 16),
++ start_int, finish_int, (finish_int - start_int),
++ interruptcount);
++#else
++ len = sprintf(page, "Start %9i.%06i\nFinish %9i.%06i\nLatency %17i\n\
++Count %19i\n", (int)tv1.tv_sec, (int)tv1.tv_usec, (int)tv2.tv_sec, (int)tv2.tv_usec, (int)(tv2.tv_usec - tv1.tv_usec), interruptcount);
++#endif
++ *eof = 1;
++ return len;
++}
++
++/*
++ * function init_interrupt_latency
++ * This function creates the /proc directory entry interrupt_latency. It
++ * also configures the parallel port then requests interrupt 7 from Linux.
++ */
++static int __init init_interrupt_latency(void)
++{
++ int rv = 0;
++ unsigned int ir14;
++
++ interrupt_latency_file =
++ create_proc_entry("interrupt_latency", 0444, NULL);
++ if (interrupt_latency_file == NULL) {
++ return -ENOMEM;
++ }
++
++ interrupt_latency_file->data = NULL;
++ interrupt_latency_file->read_proc = &proc_read_interrupt_latency;
++ interrupt_latency_file->write_proc = NULL;
++
++ /* request interrupt from linux */
++ rv = request_irq(INTERRUPT, interrupt_interrupt_latency, IRQF_DISABLED,
++ "interrupt_latency", (void *)NULL);
++ if (rv) {
++ printk("Can't get interrupt %d\n", INTERRUPT);
++ goto no_interrupt_latency;
++ }
++
++ /* unmask SWI */
++ ir14 = __nds32__mfsr(NDS32_SR_INT_MASK);
++ __nds32__mtsr((0x10000 | ir14), NDS32_SR_INT_MASK);
++ __nds32__dsb();
++
++ /* everything initialized */
++ printk(KERN_INFO "%s %s initialized\n", MODULE_NAME,
++ ILT_MODULE_VERSION);
++ return 0;
++
++ /* remove the proc entry on error */
++no_interrupt_latency:
++ remove_proc_entry("interrupt_latency", NULL);
++ return 0;
++}
++
++/*
++ * function cleanup_interrupt_latency
++ * This function frees interrupt then removes the /proc directory entry
++ * interrupt_latency.
++ */
++static void __exit cleanup_interrupt_latency(void)
++{
++ /* free the interrupt */
++ free_irq(INTERRUPT, (void *)NULL);
++
++ remove_proc_entry("interrupt_latency", NULL);
++
++ printk(KERN_INFO "%s %s removed\n", MODULE_NAME, ILT_MODULE_VERSION);
++}
++
++module_init(init_interrupt_latency);
++module_exit(cleanup_interrupt_latency);
++
++MODULE_DESCRIPTION("interrupt_latency proc module");
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101p/Kconfig linux-3.4.110/arch/nds32/platforms/ag101p/Kconfig
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101p/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101p/Kconfig 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,11 @@
++menu "AG101P Platform Options"
++config CACHE_L2
++bool "Support L2 cache"
++ default n
++
++config MEASURE_INTERRUPT_LATENCY
++ bool "Measure interrupt latency"
++ default n
++ help
++ Enable measuring interrupt latency with software interrupt
++endmenu
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag101p/Makefile linux-3.4.110/arch/nds32/platforms/ag101p/Makefile
+--- linux-3.4.110.orig/arch/nds32/platforms/ag101p/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag101p/Makefile 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,2 @@
++obj-y = devices.o
++obj-$(CONFIG_MEASURE_INTERRUPT_LATENCY) += interrupt-latency.o
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/ahbclkcal.c linux-3.4.110/arch/nds32/platforms/ag102/ahbclkcal.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag102/ahbclkcal.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag102/ahbclkcal.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,216 @@
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/pm.h>
++#include <linux/sched.h>
++#include <linux/irq.h>
++
++#include <asm/hardware.h>
++#include <asm/spec.h>
++#ifdef CONFIG_AUTO_SYS_CLK
++
++#define OSCH3_CLK 33000000
++#define OSCH_CLK 25000000
++#define MHZ 1000000
++/*
++ * Table for ahb divisor, PMODE[07:04]
++ */
++static const int ahb_div[16] = {
++ 1, 2, 3, 4, 5, 6, 3, 5,
++ 8, 10, 12, 14, 15, 18, 20, -1
++};
++
++/* ag102_get_ahb_clk()
++ *
++ * return AHB clock in Hz.
++ */
++static int ahbclk;
++void ag102_calc_ahb_clk(void)
++{
++ unsigned int pcs1_param;
++ unsigned int pcs4_param;
++ unsigned int pcs5_param;
++ unsigned int main_PLL_div;
++ unsigned int main_PLL_out;
++ unsigned int ratio;
++ unsigned int main_PLL_N;
++ unsigned int main_PLL_M = 1;
++ unsigned int F_core0;
++ unsigned int F_core1;
++ unsigned int F_l2cc;
++ unsigned int F_ddr2;
++ unsigned int F_ahb;
++ unsigned int F_apb;
++ unsigned int F_pci;
++
++ pcs1_param = REG32(PCU_VA_BASE + 0xa4); //pcs1 parameter register, for core/ahb/apb clk ratio setting
++ main_PLL_div = (pcs1_param >> 4) & 0x3;
++ ratio = pcs1_param & 0xf;
++
++ pcs4_param = REG32(PCU_VA_BASE + 0x104); //pcs4 parameter register, for main PLL setting
++ main_PLL_N = pcs4_param & 0xff;
++ main_PLL_out = (OSCH3_CLK * main_PLL_N / main_PLL_M) >> main_PLL_div;
++
++ pcs5_param = REG32(PCU_VA_BASE + 0x124); //pcs5 parameter register, for PCI PLL/DLL setting
++
++ switch (ratio) {
++ case 0:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0;
++ F_l2cc = F_core0 >> 1;
++ F_ddr2 = F_core0 >> 1;
++ F_ahb = F_core0 >> 2;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 1:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0;
++ F_l2cc = F_core0 >> 1;
++ F_ddr2 = F_core0 >> 1;
++ F_ahb = F_core0 >> 3;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 2:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0 >> 1;
++ F_l2cc = F_core0 >> 1;
++ F_ddr2 = F_core0 >> 1;
++ F_ahb = F_core0 >> 2;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 3:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0 >> 1;
++ F_l2cc = F_core0 >> 1;
++ F_ddr2 = F_core0 >> 1;
++ F_ahb = F_core0 >> 3;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 4:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0 >> 2;
++ F_l2cc = F_core0 >> 2;
++ F_ddr2 = F_core0 >> 1;
++ F_ahb = F_core0 >> 2;
++ F_apb = F_ahb >> 1;
++ break;
++ case 5:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0 >> 2;
++ F_l2cc = F_core0 >> 2;
++ F_ddr2 = F_core0 >> 1;
++ F_ahb = F_core0 >> 3;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 6:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0;
++ F_l2cc = F_core0;
++ F_ddr2 = F_core0 >> 1;
++ F_ahb = F_core0 >> 2;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 7:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0;
++ F_l2cc = F_core0;
++ F_ddr2 = F_core0 >> 1;
++ F_ahb = F_core0 >> 3;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 8:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0;
++ F_l2cc = F_core0 >> 1;
++ F_ddr2 = OSCH_CLK * 24 / 2;
++ F_ahb = F_core0 >> 2;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 9:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0;
++ F_l2cc = F_core0 >> 1;
++ F_ddr2 = OSCH_CLK * 24 / 2;
++ F_ahb = F_core0 >> 3;
++ F_apb = F_ahb >> 1;
++ break;
++ case 10:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0 >> 1;
++ F_l2cc = F_core0 >> 1;
++ F_ddr2 = OSCH_CLK * 24 / 2;
++ F_ahb = F_core0 >> 2;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 11:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0 >> 1;
++ F_l2cc = F_core0 >> 1;
++ F_ddr2 = OSCH_CLK * 24 / 2;
++ F_ahb = F_core0 >> 3;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 12:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0 >> 2;
++ F_l2cc = F_core0 >> 2;
++ F_ddr2 = OSCH_CLK * 24 / 2;
++ F_ahb = F_core0 >> 2;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 13:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0 >> 2;
++ F_l2cc = F_core0 >> 2;
++ F_ddr2 = OSCH_CLK * 24 / 2;
++ F_ahb = F_core0 >> 3;
++ F_apb = F_ahb >> 1;
++ break;
++
++ case 14:
++ F_core0 = main_PLL_out;
++ F_core1 = F_core0;
++ F_l2cc = F_core0;
++ F_ddr2 = F_core0;
++ F_ahb = F_core0;
++ F_apb = F_ahb;
++ break;
++ default: // 15
++ F_core0 = OSCH3_CLK;
++ F_core1 = F_core0;
++ F_l2cc = F_core0;
++ F_ddr2 = F_core0;
++ F_ahb = F_core0;
++ F_apb = F_ahb;
++ break;
++ }
++
++ F_pci = OSCH_CLK * 24 / 9;
++ if ((pcs5_param & 0x800) == 0)
++ F_pci = F_pci >> 1;
++
++ ahbclk = (int)F_ahb;
++}
++
++int ag102_get_ahb_clk(void)
++{
++ //return ahbclk+MHZ;
++ return ahbclk;
++}
++
++EXPORT_SYMBOL(ag102_get_ahb_clk);
++#else
++void ag102_calc_ahb_clk(void)
++{
++}
++#endif
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/devices.c linux-3.4.110/arch/nds32/platforms/ag102/devices.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag102/devices.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag102/devices.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,181 @@
++#include <linux/serial_8250.h>
++#include <asm/mach-types.h>
++#include <asm/sizes.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/timer.h>
++#include <linux/platform_device.h>
++#include <linux/usb/g_hid.h>
++
++extern void amic_init(void);
++
++const struct map_desc platform_io_desc[] __initdata = {
++ {UART0_VA_BASE, UART0_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {UART1_VA_BASE, UART1_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {AMIC_VA_BASE, AMIC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {GMAC_VA_BASE, GMAC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {APBBR_VA_BASE, APBBR_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {TIMER_VA_BASE, TIMER_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {L2CC_VA_BASE, L2CC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {PCIIO_0_VA_BASE, PCIIO_0_PA_BASE, 0x0000F000, MT_DEVICE_NCB},
++ {PCIC_FTPCI100_0_VA_BASE, PCIC_FTPCI100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {SDC_FTSDC010_0_VA_BASE, SDC_FTSDC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {RTC_FTRTC010_0_VA_BASE, RTC_FTRTC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {WDT_FTWDT010_0_VA_BASE, WDT_FTWDT010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {I2C_FTI2C010_0_VA_BASE, I2C_FTI2C010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {GPIO_FTGPIO010_0_VA_BASE, GPIO_FTGPIO010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {PCU_VA_BASE, PCU_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {LPC_IO_VA_BASE, LPC_IO_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {LPC_REG_VA_BASE, LPC_REG_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {DMAC_FTDMAC020_0_VA_BASE, DMAC_FTDMAC020_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {GPU_VA_BASE, GPU_PA_BASE, SZ_64K, MT_DEVICE_NCB},
++ {IDE_FTIDE020_VA_BASE, IDE_FTIDE020_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {USB_FOTG2XX_0_VA_BASE, USB_FOTG2XX_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {CFC_FTCFC010_0_VA_BASE, CFC_FTCFC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {SSP_FTSSP010_0_VA_BASE, SSP_FTSSP010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {SPI_FTSSP010_0_VA_BASE, SPI_FTSSP010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {DDR2C_VA_BASE, DDR2C_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {AHB_ATFAHBC020S_0_VA_BASE, AHB_ATFAHBC020S_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB}
++ //{ GPIO_VA_BASE, GPIO_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB }
++};
++
++/* hid descriptor for a keyboard */
++static struct hidg_func_descriptor my_hid_data = {
++ .subclass = 0, /* No subclass */
++ .protocol = 1, /* Keyboard */
++ .report_length = 8,
++ .report_desc_length = 63,
++ .report_desc = {
++ 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
++ 0x09, 0x06, /* USAGE (Keyboard) */
++ 0xa1, 0x01, /* COLLECTION (Application) */
++ 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
++ 0x19, 0xe0, /* USAGE_MINIMUM (Keyboard LeftControl) */
++ 0x29, 0xe7, /* USAGE_MAXIMUM (Keyboard Right GUI) */
++ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
++ 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */
++ 0x75, 0x01, /* REPORT_SIZE (1) */
++ 0x95, 0x08, /* REPORT_COUNT (8) */
++ 0x81, 0x02, /* INPUT (Data,Var,Abs) */
++ 0x95, 0x01, /* REPORT_COUNT (1) */
++ 0x75, 0x08, /* REPORT_SIZE (8) */
++ 0x81, 0x03, /* INPUT (Cnst,Var,Abs) */
++ 0x95, 0x05, /* REPORT_COUNT (5) */
++ 0x75, 0x01, /* REPORT_SIZE (1) */
++ 0x05, 0x08, /* USAGE_PAGE (LEDs) */
++ 0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */
++ 0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
++ 0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
++ 0x95, 0x01, /* REPORT_COUNT (1) */
++ 0x75, 0x03, /* REPORT_SIZE (3) */
++ 0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */
++ 0x95, 0x06, /* REPORT_COUNT (6) */
++ 0x75, 0x08, /* REPORT_SIZE (8) */
++ 0x15, 0x00, /* LOGICAL_MINIMUM (0) */
++ 0x25, 0x65, /* LOGICAL_MAXIMUM (101) */
++ 0x05, 0x07, /* USAGE_PAGE (Keyboard) */
++ 0x19, 0x00, /* USAGE_MINIMUM (Reserved) */
++ 0x29, 0x65, /* USAGE_MAXIMUM (Keyboard Application) */
++ 0x81, 0x00, /* INPUT (Data,Ary,Abs) */
++ 0xc0 /* END_COLLECTION */
++ }
++};
++
++static struct platform_device my_hid = {
++ .name = "hidg",
++ .id = 0,
++ .num_resources = 0,
++ .resource = 0,
++ .dev.platform_data = &my_hid_data,
++};
++
++static void __init platform_map_io(void)
++{
++ iotable_init((struct map_desc *)platform_io_desc,
++ ARRAY_SIZE(platform_io_desc));
++}
++
++static struct resource ftgmac100_resources[] = {
++ [0] = {
++ .start = GMAC_PA_BASE,
++ .end = GMAC_PA_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = GMAC_IRQ,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device ftgmac100_device = {
++ .name = "ftgmac100",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(ftgmac100_resources),
++ .resource = ftgmac100_resources,
++};
++
++static int __init devices_init(void)
++{
++ platform_device_register(&ftgmac100_device);
++ platform_device_register(&my_hid);
++ return 0;
++}
++
++arch_initcall(devices_init);
++
++static struct uart_port uart0 = {
++ .membase = (void __iomem *)UART0_VA_BASE,
++ .irq = UART0_IRQ,
++ .uartclk = CONFIG_UART_CLK,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .line = 0,
++ .mapbase = UART0_PA_BASE,
++};
++
++static struct uart_port uart1 = {
++ .membase = (void __iomem *)UART1_VA_BASE,
++ .irq = UART1_IRQ,
++ .uartclk = CONFIG_UART_CLK,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .line = 1,
++ .mapbase = UART1_PA_BASE,
++};
++
++void ag102_calc_ahb_clk(void);
++static void __init soc_init(void)
++{
++ ag102_calc_ahb_clk();
++ early_serial_setup(&uart0);
++ early_serial_setup(&uart1);
++}
++
++MACHINE_START(FARADAY, PLATFORM_NAME)
++ .param_offset = BOOT_PARAMETER_PA_BASE,.map_io = platform_map_io,.init_irq = amic_init,.timer = &platform_timer, /* defined in timer.c */
++.init_machine = soc_init,
++ MACHINE_END static struct platform_device usb_dev_otg_host = {
++ .name = "fotg-ehci",
++};
++
++static int __init fotg_init(void)
++{
++ platform_device_register(&usb_dev_otg_host);
++ return 0;
++}
++
++device_initcall(fotg_init);
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/freq-scaling.c linux-3.4.110/arch/nds32/platforms/ag102/freq-scaling.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag102/freq-scaling.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag102/freq-scaling.c 2016-04-07 10:20:50.986082726 +0200
+@@ -0,0 +1,512 @@
++/*
++ * linux/arch/nds32/platforms/ag102/cpu-fcs.c
++ *
++ * Copyright (C) 2002,2003 Intrinsyc Software
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * History:
++ * 31-Jul-2002 : Initial version [FB]
++ * 29-Jan-2003 : added PXA255 support [FB]
++ * 20-Apr-2003 : ported to v2.5 (Dustin McIntire, Sensoria Corp.)
++ * 18-Jun-2008 : ported to NDS32 architecture ( Roy Lee, Andestech Corp.)
++ * 13-Oct-2010 : ported to NDS32 AG102 architecture(Gavin Guo, Andestech Corp.)
++ *
++ * Note:
++ * This driver may change the memory bus clock rate, but will not do any
++ * platform specific access timing changes... for example if you have flash
++ * memory connected to CS0, you will need to register a platform specific
++ * notifier which will adjust the memory access strobes to maintain a
++ * minimum strobe width.
++ *
++ */
++#include <linux/module.h>
++#include <linux/cpufreq.h>
++#include <linux/interrupt.h>
++
++#include <linux/delay.h>
++#include <asm/hardware.h>
++#include <asm/localmem.h>
++#include <asm/system.h>
++#include <asm/nds32.h>
++#include <asm/irq_regs.h>
++#include "pcu.h"
++
++void __ddr_fsc_lock_start();
++void __ddr_fsc_lock_end();
++#define AG102_MIN_FREQ 200000000
++#define AG102_MAX_FREQ 1000000000
++#define OSCH3_CLK 33000000 /* 33MHz AG102 */
++
++struct ag102_freq_struct {
++ unsigned int khz; /* cpu_clk in khz */
++ unsigned int sf; /* scaling factor */
++ unsigned int cr; /* clock ratio */
++};
++
++struct ag102_freq_struct ag102_run_freqs[] = {
++ /* khz sf, cr */
++ {OSCH3_CLK * 7, 7, 0}, /* CPUA 231MHz */
++ {OSCH3_CLK * 8, 8, 0}, /* CPUA 264MHz */
++ {OSCH3_CLK * 9, 9, 0},
++ {OSCH3_CLK * 10, 10, 0},
++ {OSCH3_CLK * 11, 11, 0},
++ {OSCH3_CLK * 12, 12, 0},
++ {OSCH3_CLK * 13, 13, 0},
++ {OSCH3_CLK * 14, 14, 0},
++ {OSCH3_CLK * 15, 15, 0},
++ {OSCH3_CLK * 16, 16, 0},
++ /*
++ * {OSCH3_CLK * 17, 17, 0},
++ * {OSCH3_CLK * 18, 18, 0},
++ * {OSCH3_CLK * 19, 19, 0},
++ * {OSCH3_CLK * 20, 20, 0},
++ * {OSCH3_CLK * 21, 21, 0},
++ * {OSCH3_CLK * 22, 22, 0},
++ * {OSCH3_CLK * 23, 23, 0},
++ * {OSCH3_CLK * 24, 24, 0},
++ * {OSCH3_CLK * 25, 25, 0},
++ * {OSCH3_CLK * 26, 26, 0},
++ * {OSCH3_CLK * 27, 27, 0},
++ * {OSCH3_CLK * 28, 28, 0},
++ * {OSCH3_CLK * 29, 29, 0},
++ * {OSCH3_CLK * 30, 30, 0},
++ */
++ {0} /* The last 30 is CPUA 1000MHz */
++};
++
++#define NUM_RUN_FREQS ARRAY_SIZE(ag102_run_freqs)
++static struct cpufreq_frequency_table ag102_run_freq_table[NUM_RUN_FREQS + 1];
++
++/* Generic helper function get CPU clocks in kHz */
++unsigned int ag102_cpufreq_get(unsigned int dummy)
++{
++ unsigned int main_PLL_M = 1;
++ unsigned int main_PLL_out;
++ unsigned int main_PLL_div;
++ unsigned int ratio;
++ unsigned int main_PLL_N;
++ unsigned int pcs1_param;
++ unsigned int pcs4_param;
++
++ pcs1_param = PCU_GET_REG(PCS1_ST2);
++ main_PLL_div = PCU_EXTRACT(PCS1_ST2, DIV, pcs1_param);
++ ratio = PCU_EXTRACT(PCS1_ST2, RATIO, pcs1_param);
++
++ pcs4_param = PCU_GET_REG(PCS4_ST2);
++ main_PLL_N = PCU_EXTRACT(PCS4_ST2, N_FACTOR, pcs4_param);
++ main_PLL_out = (OSCH3_CLK * main_PLL_N / main_PLL_M) >> main_PLL_div;
++
++ printk("CPU frequency is %d\n", main_PLL_out);
++ return main_PLL_out;
++}
++
++/* find a valid frequency point */
++static int ag102_verify_policy(struct cpufreq_policy *policy)
++{
++ printk("Verified CPU policy: %dKhz min to %dKhz max\n", policy->min,
++ policy->max);
++ return cpufreq_frequency_table_verify(policy, ag102_run_freq_table);
++}
++
++void wakeup_and_ddr_train(void)
++{
++ unsigned int csr_reg;
++ unsigned long ddr2_va_base = DDR2C_VA_BASE;
++ /* issue standby */
++ /*standby(PCU_STBY_WAIT_DONE); */
++ __asm__ __volatile__("__fcs_stby:");
++ __asm__ __volatile__("standby wait_done");
++ /* Fill the inline assembly codes into Cache to avoid SDRAM access before the data training is done */
++ __asm__ __volatile__("__ddr_fsc_lock_start:\n"
++ "li $p0, %0 \n"
++ "lwi $p1, [$p0 + 0x1f0] \n"
++ "ori $p1, $p1, 0x100 \n"
++ "swi $p1, [$p0 + 0x1f0] ! DLL Reset \n"
++ "msync \n"
++ "isb \n"
++ "1: \n"
++ "lwi $p1, [$p0 + 0x1f0] \n"
++ "andi $p1, $p1, 0x100 \n"
++ "bnez $p1, 1b ! Wait until DLL reset is done\n"
++ "__trigger_dt:\n"
++ "li $p0, %1 \n"
++ "lwi $p1, [$p0] \n"
++ "li $p0, 0x40000000 \n"
++ "or $p1, $p1, $p0 \n"
++ "li $p0, %2 \n"
++ "swi $p1, [$p0] ! Trigger data training\n"
++ "msync \n"
++ "isb \n"
++ "li $p0, %3 \n"
++ "__wait_init_0:\n"
++ "lwi $p1, [$p0 + 0xc] \n"
++ "srli $p1, $p1, 23 \n"
++ "andi $p1, $p1, 0x1 \n"
++ "bnez $p1, __wait_init_0 ! Wait until init bit in CSR == 0\n"
++ "lwi $p1, [$p0 + 0xc] \n"
++ "srli $p1, $p1, 20 \n"
++ "andi $p1, $p1, 0x1 \n"
++ "beqz $p1, __dt_pass ! Monitor data training result\n"
++ "li $p0, 0xff942000 \n"
++ "li $p1, 0x45 \n"
++ "swi $p1, [$p0] ! put 'E' to UART\n"
++ "li $p1, 0x52 \n"
++ "swi $p1, [$p0] ! put 'R' to UART\n"
++ "li $p1, 0x52 \n"
++ "swi $p1, [$p0] ! put 'R' to UART\n"
++ "li $p1, 0x4f \n"
++ "swi $p1, [$p0] ! put 'O' to UART\n"
++ "li $p1, 0x52 \n"
++ "swi $p1, [$p0] ! put 'R' to UART\n"
++ "li $p1, 0xd \n"
++ "swi $p1, [$p0] ! put '\\r' to UART\n"
++ "li $p1, 0xa \n"
++ "swi $p1, [$p0] ! put '\\n' to UART\n"
++ "j __ddr_fsc_lock_end \n"
++ "__dt_pass:\n"
++ "li $p0, 0xff942000 \n"
++ "li $p1, 0x50 \n"
++ "swi $p1, [$p0] ! put 'P' to UART\n"
++ "li $p1, 'A \n"
++ "swi $p1, [$p0] ! put 'A' to UART\n"
++ "li $p1, 0x53 \n"
++ "swi $p1, [$p0] ! put 'S' to UART\n"
++ "li $p1, 0x53 \n"
++ "swi $p1, [$p0] ! put 'S' to UART\n"
++ "li $p1, '\\r \n"
++ "swi $p1, [$p0] ! put '\\r' to UART\n"
++ "li $p1, '\\n \n"
++ "swi $p1, [$p0] ! put '\\n' to UART\n"
++ "__ddr_fsc_lock_end: \n"::
++ "r"
++ (ddr2_va_base),
++ "r"
++ (ddr2_va_base),
++ "r"(ddr2_va_base), "r"(ddr2_va_base));
++
++ csr_reg = GET_REG(DDR2C_VA_BASE + 0xc);
++ if (csr_reg & 0x100000) {
++ printk("\n###### Data training error ######\nCSR = 0x%x\n\n",
++ csr_reg);
++ }
++}
++
++void check_status()
++{
++ unsigned int reg_value_tmp;
++
++ /*
++ * CPU will continue if it is waked up
++ * => check status
++ */
++ reg_value_tmp = PCU_GET_REG(BSM_STATUS);
++ if (PCU_EXTRACT(BSM_STATUS, STS, reg_value_tmp) != PCS_BSM_DONE) {
++ printk("ERROR: BSM status is not expected:0x%x\n",
++ reg_value_tmp);
++ }
++ PCU_SET_REG(BSM_STATUS, 0x0); // write to clear the status
++
++ /*
++ * Maybe we will need the following code in the future
++ * if (pcs1_used) {
++ * reg_value_tmp = PCU_GET_REG(PCS1_ST1);
++ * if (PCU_EXTRACT(PCS1_ST1, STS, reg_value_tmp) != PCS_STS_DONE) {
++ * printk("ERROR: PCS1 status is not expected:0x%x\n", reg_value_tmp);
++ * printk("DEBUG: PCS1 status 2 is 0x%x\n", PCU_GET_REG(PCS1_ST2));
++ * }
++ * PCU_SET_REG(PCS1_ST1, 0x0); // write to clear the status
++ * pcs1_used = 0;
++ * }
++ */
++
++ /* if (pcs4_used) { */
++ reg_value_tmp = PCU_GET_REG(PCS4_ST1);
++ if (PCU_EXTRACT(PCS4_ST1, STS, reg_value_tmp) != PCS_STS_DONE) {
++ printk("ERROR: PCS4 status is not expected:0x%x\n",
++ reg_value_tmp);
++ printk("DEBUG: PCS4 status 2 is 0x%x\n", PCU_GET_REG(PCS4_ST2));
++ }
++ PCU_SET_REG(PCS4_ST1, 0x0); /* write to clear the status */
++ /* pcs4_used = 0; */
++ /* } */
++
++}
++
++void start_fcs(unsigned int pll_n_factor, unsigned org_div_param)
++{
++ unsigned int pll_range;
++ unsigned int pcs4_prmtr;
++
++ /*
++ * We must keep the frequency between 266~533.
++ * because this is the frequency having been tested.
++ */
++ if (org_div_param == 0) {
++ if ((pll_n_factor < 7) || (pll_n_factor > 16)) { /* 266~533 */
++ printk("\npll_n_factor:%d, org_div_param:%d\n",
++ pll_n_factor, org_div_param);
++ printk
++ ("The input is not accepted! Please input the other value\n");
++ return;
++ }
++ } else { /* div = 1(the divsior is 2), (pll_n_factor*33MHz/2) */
++ if (pll_n_factor < 16) { /* (533/2~1000/2) */
++ printk("\npll_n_factor:%d, org_div_param:%d\n",
++ pll_n_factor, org_div_param);
++ printk
++ ("The input is not accepted! Please input the other value\n");
++ return;
++ }
++
++ }
++ /* Setup the pll_range, pcu need to know the frequency which we setup */
++ if (org_div_param == 0) {
++ if (pll_n_factor <= 15) {
++ pll_range = 2;
++ } else
++ pll_range = 3;
++ } else if (org_div_param == 1) {
++ if (pll_n_factor >= 16 && pll_n_factor <= 30) {
++ pll_range = 2;
++ } else
++ pll_range = 3;
++ }
++
++ printk("\npll_n_factor:%d, org_div_param:%d, pll_range:%d\n",
++ pll_n_factor, org_div_param, pll_range);
++ /* PCS4 */
++ PCU_SET_REG(PCS4_CFG, 0); /* stop */
++ pcs4_prmtr = PCU_PREPARE(PCS4_PARA, IE, 1) | PCU_PREPARE(PCS4_PARA, CMD, PCS_CMD_NOP) | PCU_PREPARE(PCS4_PARA, SYNC, 1) | PCU_PREPARE(PCS4_PARA, PWDN, 0) | PCU_PREPARE(PCS4_PARA, RANGE, pll_range) | /* PLL range */
++ pll_n_factor; /* PLL N factor */
++ PCU_SET_REG(PCS4_PARA, pcs4_prmtr);
++
++ /* BSM */
++ PCU_SET_REG(BSM_CTRL, PCU_PREPARE(BSM_CTRL, IE, 1) | PCU_PREPARE(BSM_CTRL, CMD, PCS_CMD_SCALING | PCS_CMD_DRAM_SF) | PCU_PREPARE(BSM_CTRL, SYNC, 1) | PCU_PREPARE(BSM_CTRL, LINK0, 4) | /* scaling link start */
++ PCU_PREPARE(BSM_CTRL, LINK1, 0x0)); /* wakeup link start */
++ wakeup_and_ddr_train();
++ check_status();
++}
++
++void end_fcs(void)
++{
++ /* Leave this function as a place marker. */
++}
++
++#define LPS_PREC 8
++void calibration()
++{
++ unsigned long ticks, loopbit, lpj;
++ int lps_precision = LPS_PREC;
++
++ lpj = (1 << 12);
++
++ printk(KERN_INFO "Calibrating delay loop... ");
++ while ((lpj <<= 1) != 0) {
++ /* wait for "start of" clock tick */
++ ticks = jiffies;
++ while (ticks == jiffies)
++ /* nothing */ ;
++ /* Go .. */
++ ticks = jiffies;
++ __delay(lpj);
++ ticks = jiffies - ticks;
++ if (ticks)
++ break;
++ }
++
++ /*
++ * Do a binary approximation to get lpj set to
++ * equal one clock (up to lps_precision bits)
++ */
++ lpj >>= 1;
++ loopbit = lpj;
++ while (lps_precision-- && (loopbit >>= 1)) {
++ lpj |= loopbit;
++ ticks = jiffies;
++ while (ticks == jiffies)
++ /* nothing */ ;
++ ticks = jiffies;
++ __delay(lpj);
++ if (jiffies != ticks) /* longer than 1 tick */
++ lpj &= ~loopbit;
++ }
++
++ printk(KERN_CONT "%lu.%02lu BogoMIPS modified(lpj=%lu)\n",
++ lpj / (500000 / HZ), (lpj / (5000 / HZ)) % 100, lpj);
++}
++
++static int ag102_speedstep(int idx)
++{
++ unsigned int j;
++ char ch = 'a';
++ unsigned int sf, cr;
++ unsigned long flags = 0;
++ unsigned long org_div_param;
++ void (*do_fcs) (unsigned int efsf, unsigned int edivhbaclk);
++ int i;
++ int line_size = CACHE_LINE_SIZE(ICACHE);
++ unsigned long start =
++ ((unsigned long)__ddr_fsc_lock_start) & ~(line_size - 1);
++ unsigned long end =
++ (((unsigned long)__ddr_fsc_lock_end) + line_size) & ~(line_size -
++ 1);
++
++ printk("&__ddr_fsc_lock_start(): 0x%08lx, aligned to: 0x%08lx\n",
++ (unsigned long)__ddr_fsc_lock_start, start);
++ printk("&__ddr_fsc_lock_end(): 0x%08lx, aligned to: 0x%08lx\n",
++ (unsigned long)__ddr_fsc_lock_end, end);
++
++ for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
++ __asm__ volatile ("\n\tcctl %0, L1I_VA_FILLCK"::
++ "r" (i):"memory");
++
++ do_fcs = start_fcs;
++ org_div_param = (PCU_GET_REG(PCS1_ST2) >> 4) & 0x3;
++ sf = ag102_run_freqs[idx].sf;
++ if (org_div_param == 1)
++ sf *= 2;
++#if 0
++ calibration();
++ printk("pcu read value,before frequency scaling:");
++ ag102_cpufreq_get(0);
++#endif
++ local_irq_save(flags);
++ do_fcs(sf, org_div_param);
++ local_irq_restore(flags);
++#if 0
++ printk("\npcu read value,after frequency scaling:");
++ ag102_cpufreq_get(0);
++#endif
++
++ for (i = start; i <= end; i += CACHE_LINE_SIZE(ICACHE))
++ __asm__ volatile ("\n\tcctl %0, L1I_VA_ULCK"::"r" (i):"memory");
++
++ return 1;
++}
++
++static int ag102_set_target(struct cpufreq_policy *policy,
++ unsigned int target_freq, unsigned int relation)
++{
++ unsigned int idx, i, j;
++ char ch = 'a';
++ struct cpufreq_frequency_table *ag102_freqs_table;
++ struct ag102_freq_struct *ag102_freq_settings;
++ struct cpufreq_freqs freqs;
++
++ ag102_freq_settings = ag102_run_freqs;
++ ag102_freqs_table = ag102_run_freq_table;
++
++ if (target_freq > AG102_MAX_FREQ || target_freq < AG102_MIN_FREQ) {
++ printk
++ ("\nThe frequency you input is illegal!!Please enter the frequency between %d ~ %d\n",
++ AG102_MIN_FREQ, AG102_MAX_FREQ);
++ return -EINVAL;
++ }
++
++ /* Lookup the next frequency */
++ if (cpufreq_frequency_table_target
++ (policy, ag102_freqs_table, target_freq, relation, &idx))
++ return -EINVAL;
++
++ freqs.old = policy->cur;
++ freqs.new = ag102_freq_settings[idx].khz;
++ freqs.cpu = policy->cpu;
++
++ /*
++ * Tell everyone what we're about to do...
++ * you should add a notify client with any platform specific
++ * Vcc changing capability
++ */
++ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
++
++ if (freqs.new != freqs.old) {
++
++ if (!ag102_speedstep(idx))
++ return -ENODEV;
++ }
++
++ /*
++ * Tell everyone what we've just done...
++ * you should add a notify client with any platform specific
++ * SDRAM refresh timer adjustments
++ */
++ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
++#if 0
++ printk("After CPUFREQ_POSTCHANGE, scaling:\n");
++ calibration();
++ printk("Speed test...");
++ for (i = 0; i < 26; i++) {
++ for (j = 0; j < 500000000; j++) ;
++ printk("%c", ch);
++ ch += 1;
++ }
++ printk("\n");
++#endif
++ return 0;
++}
++
++static int ag102_cpufreq_init(struct cpufreq_policy *policy)
++{
++ int i;
++ /* set default policy and cpuinfo */
++ policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
++ policy->policy = CPUFREQ_POLICY_PERFORMANCE;
++ policy->cpuinfo.max_freq = AG102_MAX_FREQ;
++ policy->cpuinfo.min_freq = AG102_MIN_FREQ;
++ policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */
++ policy->cur = ag102_cpufreq_get(0); /* current freq */
++ policy->min = AG102_MIN_FREQ;
++ policy->max = AG102_MAX_FREQ;
++
++ /* Generate the run cpufreq_frequency_table struct */
++ for (i = 0; i < NUM_RUN_FREQS; i++) {
++
++ ag102_run_freq_table[i].frequency = ag102_run_freqs[i].khz;
++ ag102_run_freq_table[i].index = i;
++ }
++
++ ag102_run_freq_table[i].frequency = CPUFREQ_TABLE_END;
++
++ printk("CPU frequency change support initialized\n");
++
++ return 0;
++}
++
++static struct cpufreq_driver ag102_cpufreq_driver = {
++
++ .verify = ag102_verify_policy,
++ .target = ag102_set_target,
++ .init = ag102_cpufreq_init,
++ .get = ag102_cpufreq_get,
++ .name = "AG102",
++};
++
++static int __init ag102_cpu_init(void)
++{
++ return cpufreq_register_driver(&ag102_cpufreq_driver);
++}
++
++static void __exit ag102_cpu_exit(void)
++{
++ cpufreq_unregister_driver(&ag102_cpufreq_driver);
++}
++
++MODULE_AUTHOR("Andes Technology Corporation");
++MODULE_DESCRIPTION("CPU frequency changing driver for the AG102 architecture");
++MODULE_LICENSE("GPL");
++module_init(ag102_cpu_init);
++module_exit(ag102_cpu_exit);
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/gmac.h linux-3.4.110/arch/nds32/platforms/ag102/gmac.h
+--- linux-3.4.110.orig/arch/nds32/platforms/ag102/gmac.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag102/gmac.h 2016-04-07 10:20:51.002083345 +0200
+@@ -0,0 +1,354 @@
++#ifdef CONFIG_PLAT_AG102
++#include <asm/spec-ag102.h>
++#else
++#include <asm/spec-ag101.h>
++#endif
++
++#ifndef __GMAC_H
++#define __GMAC_H
++
++// ======================================================
++// GMAC register definition
++// ======================================================
++// GMAC register
++//
++//#define CPE_GMAC_BASE 0xFF90B000 //VA Base
++#define CPE_DDR2_MEM_BASE 0x00000000
++
++#define BIT_MASK(bit_h, bit_l) ((((UINT32)0x1<<(1+bit_h-bit_l))-(UINT32)0x1)<<bit_l)
++
++#define GMAC_REG_ISR (GMAC_VA_BASE+0x0) // interrupt sataus register
++#define GMAC_REG_IME (GMAC_VA_BASE+0x4) // interrupt enable register
++#define GMAC_REG_MAC_MADR (GMAC_VA_BASE+0x8) // mac most signification address
++#define GMAC_REG_MAC_LADR (GMAC_VA_BASE+0xc) // mac least signification address
++#define GMAC_REG_NPTXPD (GMAC_VA_BASE+0x18) // normal priority poll demand
++#define GMAC_REG_RXPD (GMAC_VA_BASE+0x1c) // receive poll demand
++#define GMAC_REG_HPTXPD (GMAC_VA_BASE+0x28) // high priority poll demand
++#define GMAC_REG_NPTXR_BADR (GMAC_VA_BASE+0x20) // normal proprity tx ring base
++#define GMAC_REG_RXR_BADR (GMAC_VA_BASE+0x24) // rx ring base
++#define GMAC_REG_HPTXR_BADR (GMAC_VA_BASE+0x28) // high priority tx ring base
++#define GMAC_REG_DBLAC (GMAC_VA_BASE+0x38) // DMA burst lenght and arbitration control
++#define GMAC_REG_DMAFIFOS (GMAC_VA_BASE+0x3c) // DMA FIFO status
++#define GMAC_REG_REVR (GMAC_VA_BASE+0x40) // revision
++#define GMAC_REG_FEAR (GMAC_VA_BASE+0x44) // feature register
++#define GMAC_REG_TPAFCR (GMAC_VA_BASE+0x48) // Tramsmit Prority Arbitration and FIFO control
++#define GMAC_REG_MACCR (GMAC_VA_BASE+0x50) // mac control register
++#define GMAC_REG_MACSR (GMAC_VA_BASE+0x54) // mac status register
++#define GMAC_REG_PHYCR (GMAC_VA_BASE+0x60) // phy control register
++#define GMAC_REG_PHYDATA (GMAC_VA_BASE+0x64) // phy data register
++#define GMAC_REG_WOLCR (GMAC_VA_BASE+0x70) // wake-on-lan control register
++#define GMAC_REG_WOLSR (GMAC_VA_BASE+0x74) // wake-on-lan status register
++#define GMAC_REG_WFCRC (GMAC_VA_BASE+0x78) // wake-up frame CRC register
++#define GMAC_REG_WFBM1 (GMAC_VA_BASE+0x80) // wake-up frame byte mask 1st
++#define GMAC_REG_WFBM2 (GMAC_VA_BASE+0x84) // wake-up frame byte mask 2nd
++#define GMAC_REG_WFBM3 (GMAC_VA_BASE+0x88) // wake-up frame byte mask 3rd
++#define GMAC_REG_WFBM4 (GMAC_VA_BASE+0x8c) // wake-up frame byte mask 4th
++#define GMAC_REG_RXR_PTR (GMAC_VA_BASE+0x98) //
++#define GMAC_REG_TPKT_CNT (GMAC_VA_BASE+0xa0) // tx packet count
++#define GMAC_REG_TMCOL_SCOL (GMAC_VA_BASE+0xa4) // tx mcol and scol count
++#define GMAC_REG_TECOL_FAIL (GMAC_VA_BASE+0xa8) // tx ecol and fail count
++#define GMAC_REG_TLCOL_URUN (GMAC_VA_BASE+0xac) // tx lcol and urun count
++#define GMAC_REG_RPKT_CNT (GMAC_VA_BASE+0xb0) // rx packet count
++#define GMAC_REG_BROPKT_CNT (GMAC_VA_BASE+0xb4) // broad cast packet count
++#define GMAC_REG_MULPKT_CNT (GMAC_VA_BASE+0xb8) // multicast packet count
++#define GMAC_REG_RPF_AEP (GMAC_VA_BASE+0xbc) //
++#define GMAC_REG_RUNT_CNT (GMAC_VA_BASE+0xc0) // rx runt packet
++#define GMAC_REG_CRCER_FLT (GMAC_VA_BASE+0xc4) // crc error and FLT
++#define GMAC_REG_RCOL_LOST (GMAC_VA_BASE+0xc8) // rx lost and collision count
++
++// interrupt enable
++#define GMAC_IME_PHY_STS_CHG_MASK (BIT_MASK(9, 9)) //
++#define GMAC_IME_PHY_STS_CHG_OFFSET (9)
++#define GMAC_IME_AHB_ERR_MASK (BIT_MASK(8, 8)) //
++#define GMAC_IME_AHB_ERR_OFFSET (8)
++#define GMAC_IME_TPKT_LOST_MASK (BIT_MASK(7, 7)) //
++#define GMAC_IME_TPKT_LOST_OFFSET (7)
++#define GMAC_IME_TXBUF_UNAVA_MASK (BIT_MASK(6, 6)) //
++#define GMAC_IME_TXBUF_UNAVA_OFFSET (6)
++#define GMAC_IME_TPKT2F_MASK (BIT_MASK(5, 5)) //
++#define GMAC_IME_TPKT2F_OFFSET (5)
++#define GMAC_IME_TPKT2B_MASK (BIT_MASK(4, 4)) //
++#define GMAC_IME_TPKT2B_OFFSET (4)
++#define GMAC_IME_RPKT_LOST_MASK (BIT_MASK(3, 3)) //
++#define GMAC_IME_RPKT_LOST_OFFSET (3)
++#define GMAC_IME_RXBUF_UNAVA_MASK (BIT_MASK(2, 2)) //
++#define GMAC_IME_RXBUF_UNAVA_OFFSET (2)
++#define GMAC_IME_RPKT2F_MASK (BIT_MASK(1, 1)) //
++#define GMAC_IME_RPKT2F_OFFSET (1)
++#define GMAC_IME_RPKT2B_MASK (BIT_MASK(0, 0)) //
++#define GMAC_IME_RPKT2B_OFFSET (0)
++
++
++// interrupt status
++#define GMAC_ISR_PHY_STS_CHG_MASK (BIT_MASK(9, 9)) //
++#define GMAC_ISR_PHY_STS_CHG_OFFSET (9)
++#define GMAC_ISR_AHB_ERR_MASK (BIT_MASK(8, 8)) //
++#define GMAC_ISR_AHB_ERR_OFFSET (8)
++#define GMAC_ISR_TPKT_LOST_MASK (BIT_MASK(7, 7)) //
++#define GMAC_ISR_TPKT_LOST_OFFSET (7)
++#define GMAC_ISR_TXBUF_UNAVA_MASK (BIT_MASK(6, 6)) //
++#define GMAC_ISR_TXBUF_UNAVA_OFFSET (6)
++#define GMAC_ISR_TPKT2F_MASK (BIT_MASK(5, 5)) //
++#define GMAC_ISR_TPKT2F_OFFSET (5)
++#define GMAC_ISR_TPKT2B_MASK (BIT_MASK(4, 4)) //
++#define GMAC_ISR_TPKT2B_OFFSET (4)
++#define GMAC_ISR_RPKT_LOST_MASK (BIT_MASK(3, 3)) //
++#define GMAC_ISR_RPKT_LOST_OFFSET (3)
++#define GMAC_ISR_RXBUF_UNAVA_MASK (BIT_MASK(2, 2)) //
++#define GMAC_ISR_RXBUF_UNAVA_OFFSET (2)
++#define GMAC_ISR_RPKT2F_MASK (BIT_MASK(1, 1)) //
++#define GMAC_ISR_RPKT2F_OFFSET (1)
++#define GMAC_ISR_RPKT2B_MASK (BIT_MASK(0, 0)) //
++#define GMAC_ISR_RPKT2B_OFFSET (0)
++
++//bit field for TPAFCR control
++#define GMAC_TPAFCR_TFIFO_SIZE_MASK (BIT_MASK(29, 27)) //
++#define GMAC_TPAFCR_TFIFO_SIZE_OFFSET (27)
++#define GMAC_TPAFCR_RFIFO_SIZE_MASK (BIT_MASK(26, 24)) //
++#define GMAC_TPAFCR_RFIFO_SIZE_OFFSET (24)
++#define GMAC_TPAFCR_EARLY_TXTHR_MASK (BIT_MASK(23, 16)) //
++#define GMAC_TPAFCR_EARLY_TXTHR_OFFSET (16)
++#define GMAC_TPAFCR_EARLY_RXTHR_MASK (BIT_MASK(15, 8)) //
++#define GMAC_TPAFCR_EARLY_RXTHR_OFFSET (8)
++#define GMAC_TPAFCR_HPKT_THR_MASK (BIT_MASK(7, 4)) //
++#define GMAC_TPAFCR_HPKT_THR_OFFSET (4)
++#define GMAC_TPAFCR_NPKT_THR_MASK (BIT_MASK(3, 0)) //
++#define GMAC_TPAFCR_NPKT_THR_OFFSET (0)
++
++//bit field for MAC control
++#define GMAC_MACCR_SW_RST_MASK (BIT_MASK(31, 31)) //
++#define GMAC_MACCR_SW_RST_OFFSET (31)
++#define GMAC_MACCR_DIRECT_PATH_MASK (BIT_MASK(21, 21)) //
++#define GMAC_MACCR_DIRECT_PATH_OFFSET (21)
++#define GMAC_MACCR_SPEED_MASK (BIT_MASK(19, 19)) //
++#define GMAC_MACCR_SPEED_OFFSET (19)
++#define GMAC_MACCR_DISCARD_CRCERR_MASK (BIT_MASK(18, 18)) //
++#define GMAC_MACCR_DISCARD_CRCERR_OFFSET (18)
++#define GMAC_MACCR_BROADPKT_EN_MASK (BIT_MASK(17, 17)) //
++#define GMAC_MACCR_BROADPKT_EN_OFFSET (17)
++#define GMAC_MACCR_RX_MULTIPKT_EN_MASK (BIT_MASK(16, 16)) //
++#define GMAC_MACCR_RX_MULTIPKT_EN_OFFSET (16)
++#define GMAC_MACCR_RX_HT_EN_MASK (BIT_MASK(15, 15)) //
++#define GMAC_MACCR_RX_HT_EN_OFFSET (15)
++#define GMAC_MACCR_RX_ALLADR_MASK (BIT_MASK(14, 14)) //
++#define GMAC_MACCR_RX_ALLADR_OFFSET (14)
++#define GMAC_MACCR_JUMBO_LF_MASK (BIT_MASK(13, 13)) //
++#define GMAC_MACCR_JUMBO_LF_OFFSET (13)
++#define GMAC_MACCR_RX_RUNT_MASK (BIT_MASK(12, 12)) //
++#define GMAC_MACCR_RX_RUNT_OFFSET (12)
++#define GMAC_MACCR_CRC_APD_MASK (BIT_MASK(10, 10)) //
++#define GMAC_MACCR_CRC_APD_OFFSET (10)
++#define GMAC_MACCR_GMAC_MODE_MASK (BIT_MASK(9, 9)) //
++#define GMAC_MACCR_GMAC_MODE_OFFSET (9)
++#define GMAC_MACCR_FULLDUP_MASK (BIT_MASK(8, 8)) //
++#define GMAC_MACCR_FULLDUP_OFFSET (8)
++#define GMAC_MACCR_ENRX_IN_HALFTX_MASK (BIT_MASK(7, 7)) //
++#define GMAC_MACCR_ENRX_IN_HALFTX_OFFSET (7)
++#define GMAC_MACCR_LOOP_EN_MASK (BIT_MASK(6, 6)) //
++#define GMAC_MACCR_LOOP_EN_OFFSET (6)
++#define GMAC_MACCR_HPTXR_EN_MASK (BIT_MASK(5, 5)) //
++#define GMAC_MACCR_HPTXR_EN_OFFSET (5)
++#define GMAC_MACCR_REMOVE_VLAN_MASK (BIT_MASK(4, 4)) //
++#define GMAC_MACCR_REMOVE_VLAN_OFFSET (4)
++#define GMAC_MACCR_RXMAC_EN_MASK (BIT_MASK(3, 3)) //
++#define GMAC_MACCR_RXMAC_EN_OFFSET (3)
++#define GMAC_MACCR_TXMAC_EN_MASK (BIT_MASK(2, 2)) //
++#define GMAC_MACCR_TXMAC_EN_OFFSET (2)
++#define GMAC_MACCR_RXDMA_EN_MASK (BIT_MASK(1, 1)) //
++#define GMAC_MACCR_RXDMA_EN_OFFSET (1)
++#define GMAC_MACCR_TXDMA_EN_MASK (BIT_MASK(0, 0)) //
++#define GMAC_MACCR_TXDMA_EN_OFFSET (0)
++
++//bit field for PHY control
++#define GMAC_PHYCR_MIIWR_MASK (BIT_MASK(27, 27)) //
++#define GMAC_PHYCR_MIIWR_OFFSET (27)
++#define GMAC_PHYCR_MIIRD_MASK (BIT_MASK(26, 26)) //
++#define GMAC_PHYCR_MIIRD_OFFSET (26)
++#define GMAC_PHYCR_REGAD_MASK (BIT_MASK(25, 21)) // register address
++#define GMAC_PHYCR_REGAD_OFFSET (21)
++#define GMAC_PHYCR_PHYAD_MASK (BIT_MASK(20, 16)) // phy address
++#define GMAC_PHYCR_PHYAD_OFFSET (16)
++#define GMAC_PHYCR_MDC_CYCTHR_MASK (BIT_MASK(5, 0)) // cycle threshold
++#define GMAC_PHYCR_MDC_CYCTHR_OFFSET (0)
++
++//bit field for PHY data
++#define GMAC_PHYDATA_MIIRDATA_MASK (BIT_MASK(31, 16)) // read data
++#define GMAC_PHYDATA_MIIRDATA_OFFSET (16)
++#define GMAC_PHYDATA_MIIWDATA_MASK (BIT_MASK(15, 0)) // write data
++#define GMAC_PHYDATA_MIIWDATA_OFFSET (0)
++
++//bit field for WOLCR
++#define GMAC_WOLCR_WOL_TYPE_MASK (BIT_MASK(258, 24)) //
++#define GMAC_WOLCR_WOL_TYPE_OFFSET (24)
++#define GMAC_WOLCR_SW_PDNPHY_MASK (BIT_MASK(18, 18)) //
++#define GMAC_WOLCR_SW_PDNPHY_OFFSET (18)
++#define GMAC_WOLCR_WAKEUP_SEL_MASK (BIT_MASK(17, 16)) //
++#define GMAC_WOLCR_WAKEUP_SEL_OFFSET (16)
++#define GMAC_WOLCR_PWRSAV_MASK (BIT_MASK(15, 15)) //
++#define GMAC_WOLCR_PWRSAV_OFFSET (15)
++#define GMAC_WOLCR_WAKEUP4_EN_MASK (BIT_MASK(6, 6)) //
++#define GMAC_WOLCR_WAKEUP4_EN_OFFSET (6)
++#define GMAC_WOLCR_WAKEUP3_EN_MASK (BIT_MASK(5, 5)) //
++#define GMAC_WOLCR_WAKEUP3_EN_OFFSET (5)
++#define GMAC_WOLCR_WAKEUP2_EN_MASK (BIT_MASK(4, 4)) //
++#define GMAC_WOLCR_WAKEUP2_EN_OFFSET (4)
++#define GMAC_WOLCR_WAKEUP1_EN_MASK (BIT_MASK(3, 3)) //
++#define GMAC_WOLCR_WAKEUP1_EN_OFFSET (3)
++#define GMAC_WOLCR_MAGICPKT_EN_MASK (BIT_MASK(2, 2)) //
++#define GMAC_WOLCR_MAGICPKT_EN_OFFSET (2)
++#define GMAC_WOLCR_LINKCHG1_EN_MASK (BIT_MASK(1, 1)) // read data
++#define GMAC_WOLCR_LINKCHG1_EN_OFFSET (1)
++#define GMAC_WOLCR_LINKCHG0_EN_MASK (BIT_MASK(0, 0)) // write data
++#define GMAC_WOLCR_LINKCHG0_EN_OFFSET (0)
++
++//bit field for WOLSR
++#define GMAC_WOLSR_WAKEUP4_STS_MASK (BIT_MASK(6, 6)) //
++#define GMAC_WOLSR_WAKEUP4_STS_OFFSET (6)
++#define GMAC_WOLSR_WAKEUP3_STS_MASK (BIT_MASK(5, 5)) //
++#define GMAC_WOLSR_WAKEUP3_STS_OFFSET (5)
++#define GMAC_WOLSR_WAKEUP2_STS_MASK (BIT_MASK(4, 4)) //
++#define GMAC_WOLSR_WAKEUP2_STS_OFFSET (4)
++#define GMAC_WOLSR_WAKEUP1_STS_MASK (BIT_MASK(3, 3)) //
++#define GMAC_WOLSR_WAKEUP1_STS_OFFSET (3)
++#define GMAC_WOLSR_MAGICPKT_STS_MASK (BIT_MASK(2, 2)) //
++#define GMAC_WOLSR_MAGICPKT_STS_OFFSET (2)
++#define GMAC_WOLSR_LINKCHG1_STS_MASK (BIT_MASK(1, 1)) // read data
++#define GMAC_WOLSR_LINKCHG1_STS_OFFSET (1)
++#define GMAC_WOLSR_LINKCHG0_STS_MASK (BIT_MASK(0, 0)) // write data
++#define GMAC_WOLSR_LINKCHG0_STS_OFFSET (0)
++
++// feature
++#define GMAC_FEAR_TFIFO_RSIZE_MASK (BIT_MASK(5, 3)) // tx fifo size
++#define GMAC_FEAR_TFIFO_RSIZE_OFFSET (3)
++#define GMAC_FEAR_RFIFO_RSIZE_MASK (BIT_MASK(2, 0)) // rx fufo size
++#define GMAC_FEAR_RFIFO_RSIZE_OFFSET (0)
++
++// ======================================================
++// GMAC access macro
++// ======================================================
++#define GMAC_SET_FIELD(reg, field, value) SET_FIELD(GMAC_REG_##reg, GMAC_##reg##_##field##_##MASK, GMAC_##reg##_##field##_##OFFSET, value)
++#define GMAC_GET_FIELD(reg, field) GET_FIELD(GMAC_REG_##reg, GMAC_##reg##_##field##_##MASK, GMAC_##reg##_##field##_##OFFSET)
++#define GMAC_TEST_FIELD(reg, field) TEST_FIELD(GMAC_REG_##reg, GMAC_##reg##_##field##_##MASK)
++
++#define GMAC_SET_REG(reg, value) SET_REG(GMAC_REG_##reg, value)
++#define GMAC_GET_REG(reg) GET_REG(GMAC_REG_##reg)
++#define GMAC_TEST_BIT(reg, field, value) VAR_TEST_BIT(value, GMAC_##reg##_##field##_##MASK)
++
++#define GMAC_EXTRACT(reg, field, value) EXTRACT_FIELD(value, GMAC_##reg##_##field##_##MASK, GMAC_##reg##_##field##_##OFFSET )
++#define GMAC_PREPARE(reg, field, value) PREPARE_FIELD(value, GMAC_##reg##_##field##_##MASK, GMAC_##reg##_##field##_##OFFSET )
++
++#define GMAC_DEFAULT(reg, field) PREPARE_FIELD(GMAC_##reg##_##field##_##DEFAULT, GMAC_##reg##_##field##_##MASK, GMAC_##reg##_##field##_##OFFSET )
++
++#define GMAC_TEST_SIG(var, sig) VAR_TEST_BIT(var, GMAC_ISR_SIG_##sig)
++#define GMAC_SET_SIG(var, sig) VAR_SET_BIT(var, GMAC_ISR_SIG_##sig)
++#define GMAC_CLR_SIG(var, sig) VAR_CLR_BIT(var, GMAC_ISR_SIG_##sig)
++
++#define FTGMAC100_MEM_BASE (CPE_DDR2_MEM_BASE + 0x00700000) //new: higher space of RAM
++#define FTGMAC100_TXR_BASE (FTGMAC100_MEM_BASE) // 2048 des., 4 byte, 4 DWs
++#define FTGMAC100_RXR_BASE (FTGMAC100_MEM_BASE+ 4096*4*4*2) // offset 2 BASE ADDRESS
++#define FTGMAC100_TXBUF_BASE (FTGMAC100_MEM_BASE+ 0x100000) // offset 2 SIZE ADDRESS
++#define FTGMAC100_RXBUF_BASE (FTGMAC100_MEM_BASE+ 0x400000) // offset 3 SIZE ADDRESS
++
++#define FTGMAC100_DESCRIPTOR_BYTE 16
++#define FTGMAC100_RXBUF_SIZE 1024
++
++//#define GMAC_DAH (0xef12)
++//#define GMAC_DAL (0x3456789a)
++#define GMAC_DAH (0x5555)
++#define GMAC_DAL (0x55555555)
++
++// ======================================================
++// DAVICOM DM9161A PHY register definition
++// ======================================================
++#define DVC_PHY_ID (0x0181b8a0)
++#define DVC_PHY_ADDR (0x0)
++#define DVC_PHY_REG_CTL (0)
++#define DVC_PHY_REG_STS (1)
++#define DVC_PHY_REG_CFG (17)
++#define DVC_PHY_REG_CTL_SW_RST (0x1<<15)
++#define DVC_PHY_REG_CTL_AN_EN (0x1<<12)
++#define DVC_PHY_REG_CTL_AN_RST (0x1<<9)
++#define DVC_PHY_REG_CTL_LOOPBACK (0x1<<14)
++
++// ======================================================
++// Marvell 88E1119R GPHY register definition
++// ======================================================
++#define MAR_GPHY_ID (0x01410e80)
++#define MAR_GPHY_ADDR (0x1f)
++#define MAR_GPHY_REG_CTL (0)
++#define MAR_GPHY_REG_STS (1)
++#define MAR_GPHY_REG_ID0 (2)
++#define MAR_GPHY_REG_ID1 (3)
++#define MAR_GPHY_REG_LPA (5)
++#define MAR_GPHY_REG_COP_CTL (16) // page 0
++#define MAR_GPHY_REG_MAC1 (16) // page 2
++#define MAR_GPHY_REG_LED_CTL (16) // page 3
++#define MAR_GPHY_REG_PKT_GEN (16) // page 6
++#define MAR_GPHY_REG_COP_STS1 (17) // page 0
++#define MAR_GPHY_REG_LED_POLAR (17) // page 3
++#define MAR_GPHY_REG_COP_STS2 (19) // page 0
++#define MAR_GPHY_REG_MAC2 (21) // page 2
++#define MAR_GPHY_REG_MAC_INT_EN (18) // page 0
++#define MAR_GPHY_REG_MAC_STS (19) // page 2
++#define MAR_GPHY_REG_PAGE (22)
++
++#define MAR_GPHY_REG_CTL_SW_RST (0x1<<15)
++#define MAR_GPHY_REG_CTL_AN_EN (0x1<<12)
++#define MAR_GPHY_REG_CTL_START_AN (0x1<<9)
++#define MAR_GPHY_REG_CTL_FULL_DUP (0x1<<8)
++#define MAR_GPHY_REG_CTL_LOOPBACK (0x1<<14)
++#define MAR_GPHY_REG_CTL_SPEED ((0x1<<13)|(0x1<<6))
++#define MAR_GPHY_REG_CTL_SPEED_1000M (0x1<<6)
++#define MAR_GPHY_REG_CTL_SPEED_100M (0x1<<13)
++#define MAR_GPHY_REG_CTL_SPEED_10M (0x0)
++#define MAR_GPHY_REG_STS_AN_COMPLETE (0x1<<5)
++#define MAR_GPHY_REG_MAC1_CLK125_DIS (0x1<<2)
++#define MAR_GPHY_REG_MAC2_SPEED (0x7)
++#define MAR_GPHY_REG_MAC2_SPEED_1000M (0x6)
++#define MAR_GPHY_REG_MAC2_SPEED_100M (0x1) //(0x5)
++#define MAR_GPHY_REG_MAC2_SPEED_10M (0x4)
++#define MAR_GPHY_REG_MAC2_LINE_LOOPBACK (0x1<<14)
++#define MAR_GPHY_REG_EN_STUB (0x1<<5)
++
++typedef struct {
++ UINT8 speed; // 0=10Mbps, 1=100Mbps, 2=1000Mbps
++ UINT8 duplex; // 0=half, 1=full
++} ETH_PHY_STAT;
++
++
++INT32 gmac_test_main();
++INT32 gmac_stress_main(UINT32 test_item, UINT32 test_cnt);
++INT32 gmac_phy_check();
++INT32 gmac_phy_pwr_ctl(UINT32 pwr);
++
++void eth_mac_init(ETH_PHY_STAT *phy_stat);
++void eth_mac_config(UINT32 type);
++void eth_mac_register_dump();
++INT32 eth_mac_interrupt_setup();
++
++INT32 eth_phy_detect(UINT32* phy_addr, UINT32* phy_id);
++INT32 eth_phy_hook_driver (UINT32 phy_id);
++
++void eth_phy_init_mar(UINT32 phy_addr);
++void eth_phy_init_dvc(UINT32 phy_addr);
++//typedef void (*FP_ETH_PHY_INIT)(UINT32 phy_addr);
++
++void eth_phy_config_dvc(UINT32 type, UINT32 phy_addr);
++void eth_phy_config_mar(UINT32 type, UINT32 phy_addr);
++//typedef void (*FP_ETH_PHY_CONFIG)(UINT32 type, UINT32 phy_addr);
++
++UINT32 eth_phy_stat_dvc(UINT32 phy_addr, ETH_PHY_STAT *phy_stat);
++UINT32 eth_phy_stat_mar(UINT32 phy_addr, ETH_PHY_STAT *phy_stat);
++//typedef UINT32 (*FP_ETH_PHY_STAT)(UINT32 phy_addr, ETH_PHY_STAT *phy_stat);
++
++//typedef UINT32 (*FP_ETH_PHY_REG_READ)(UINT32 phy_addr, UINT32 phy_page, UINT32 phy_reg, UINT32 *phy_data);
++//typedef UINT32 (*FP_ETH_PHY_REG_WRITE)(UINT32 phy_addr, UINT32 phy_page, UINT32 phy_reg, UINT32 phy_data);
++
++//extern FP_ETH_PHY_CONFIG eth_phy_config;
++//extern FP_ETH_PHY_INIT eth_phy_init;
++//extern FP_ETH_PHY_STAT eth_phy_stat;
++//extern FP_ETH_PHY_REG_WRITE eth_phy_reg_write;
++//extern FP_ETH_PHY_REG_READ eth_phy_reg_read;
++
++
++#endif // __GMAC_H
+\ No newline at end of file
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/Kconfig linux-3.4.110/arch/nds32/platforms/ag102/Kconfig
+--- linux-3.4.110.orig/arch/nds32/platforms/ag102/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag102/Kconfig 2016-04-07 10:20:51.002083345 +0200
+@@ -0,0 +1,16 @@
++menu "AG102 Platform Options"
++
++config CACHE_L2
++ bool "Support L2 cache"
++ default y
++
++config LPC
++ bool "LPC support"
++
++config AUTO_SYS_CLK
++ bool "Automatic AHB Clock Detection"
++ default y
++ help
++ Automatic detection of AHB clock
++
++endmenu
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/lpc.c linux-3.4.110/arch/nds32/platforms/ag102/lpc.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag102/lpc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag102/lpc.c 2016-04-07 10:20:51.002083345 +0200
+@@ -0,0 +1,230 @@
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++
++#include <asm/spec.h>
++
++#define LPC_REG_SCR 0x10
++#define LPC_REG_SIR 0x14
++#define LPC_REG_SIMR 0x18
++
++/*
++ * Level trigger IRQ chip methods
++ */
++
++static void lpc_level_unmask_irq(unsigned int irq)
++{
++ unsigned int val;
++// *(volatile unsigned int *) (LPC_REG_BASE + LPC_REG_SIR) =
++// 1 << (irq - PLATFORM_LPC_IRQ_BASE);
++ val = *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR);
++ val &= ~(1 << (irq - PLATFORM_LPC_IRQ_BASE));
++ *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR) = val;
++}
++
++static void lpc_level_mask_irq(unsigned int irq)
++{
++ unsigned int val;
++ val = *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR);
++ val |= 1 << (irq - PLATFORM_LPC_IRQ_BASE);
++ *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR) = val;
++}
++
++static void lpc_level_ack_irq(unsigned int irq)
++{
++ *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIR) =
++ 1 << (irq - PLATFORM_LPC_IRQ_BASE);
++}
++
++static struct irq_chip lpc_simple_chip = {
++ .ack = lpc_level_ack_irq,
++ .mask = lpc_level_mask_irq,
++ .unmask = lpc_level_unmask_irq,
++};
++
++void lpc_irq_rounter(unsigned int irq, struct irq_desc *desc)
++{
++ unsigned int lpc_status;
++ unsigned int lpc_mask;
++ unsigned int lpc_irq;
++ int i;
++ struct irq_desc *lpc_desc;
++
++ desc->chip->mask(irq);
++ desc->chip->ack(irq);
++
++ lpc_status = *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIR);
++ lpc_mask = *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR);
++ *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR) = 0xffffffff;
++ for (i = 0; i < PLATFORM_LPC_IRQ_TOTALCOUNT; i++) {
++ if (!(~lpc_mask & (1 << i) & lpc_status))
++ continue;
++ lpc_irq = PLATFORM_LPC_IRQ_BASE + i;
++ lpc_desc = irq_desc + lpc_irq;
++ lpc_desc->handle_irq(lpc_irq, lpc_desc);
++ *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIR) =
++ 1 << i;
++ }
++ *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SIMR) = lpc_mask;
++
++ desc->chip->unmask(irq);
++}
++
++int __init lpc_init_irq(void)
++{
++ int i;
++
++ *(volatile unsigned int *)(LPC_REG_VA_BASE + LPC_REG_SCR) = 0x1f3;
++ /* Register all IRQ */
++ for (i = PLATFORM_LPC_IRQ_BASE;
++ i < PLATFORM_LPC_IRQ_BASE + PLATFORM_LPC_IRQ_TOTALCOUNT; i++) {
++ // level trigger
++ set_irq_chip(i, &lpc_simple_chip);
++ set_irq_handler(i, handle_simple_irq);
++
++ }
++ set_irq_chained_handler(LPC_IRQ, lpc_irq_rounter);
++
++ return 0;
++}
++
++device_initcall(lpc_init_irq);
++
++#define ITE_ADDR 0x2e
++#define ITE_DATA 0x2f
++void outlpc(unsigned int addr, unsigned int data)
++{
++ *(volatile unsigned int *)(LPC_IO_VA_BASE + 4 * addr) = data;
++}
++
++unsigned int inlpc(unsigned int addr)
++{
++ return *(volatile unsigned int *)(LPC_IO_VA_BASE + 4 * addr);
++}
++
++int __init ite8717_init(void)
++{
++ unsigned char data1, data2;
++ unsigned int count;
++ /* enter configure mode */
++ outlpc(ITE_ADDR, 0x87);
++ outlpc(ITE_ADDR, 0x01);
++ outlpc(ITE_ADDR, 0x55);
++ outlpc(ITE_ADDR, 0x55);
++ /* check chip */
++ outlpc(ITE_ADDR, 0x20);
++ data1 = inlpc(ITE_DATA);
++ outlpc(ITE_ADDR, 0x21);
++ data2 = inlpc(ITE_DATA);
++ if ((data1 != 0x87) && (data2 != 0x17))
++ goto not_found;
++ /* earlyio program */
++ outlpc(ITE_ADDR, 0x07); // LDN=0 -> FDC
++ outlpc(ITE_DATA, 0x00);
++ outlpc(ITE_ADDR, 0x30); // Enable FDC
++ outlpc(ITE_DATA, 0x01);
++ outlpc(ITE_ADDR, 0xf1); // Set (Index 0F1h) = 90h
++ outlpc(ITE_DATA, 0x80);
++
++ outlpc(0x64, 0xaa); // Send KBC self-test command
++ count = 0;
++ do {
++ if (count++ > 0x10000)
++ break;
++ data1 = ~inlpc(0x64);
++ } while (data1 & 0x01);
++ data2 = inlpc(0x60);
++ outlpc(0x64, 0xcb); // Set PS2 mode
++ count = 0;
++ do {
++ if (count++ > 0x10000)
++ break;
++ data1 = inlpc(0x64);
++ } while (data1 & 0x02);
++ outlpc(0x60, 0x01);
++ count = 0;
++ do {
++ if (count++ > 0x10000)
++ break;
++ data1 = inlpc(0x64);
++ } while (data1 & 0x02);
++ outlpc(0x64, 0x60); // 60h = write 8042 command byte
++ count = 0;
++ do {
++ if (count++ > 0x10000)
++ break;
++ data1 = inlpc(0x64);
++ } while (data1 & 0x02);
++ outlpc(0x60, 0x45); // AT interface, keyboard enabled, system flag
++ count = 0;
++ do {
++ if (count++ > 0x10000)
++ break;
++ data1 = inlpc(0x64);
++ } while (data1 & 0x02);
++ outlpc(0x64, 0xae);
++ count = 0;
++ do {
++ if (count++ > 0x10000)
++ break;
++ data1 = ~inlpc(0x64);
++ } while (data1 & 0x01);
++ outlpc(ITE_ADDR, 0x23);
++ outlpc(ITE_DATA, 0x00);
++
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x04);
++ outlpc(ITE_ADDR, 0xf0);
++ data1 = inlpc(ITE_DATA);
++ data1 &= 0x18;
++ data1 |= 0x0;
++ outlpc(ITE_DATA, data1);
++ outlpc(ITE_ADDR, 0xf2);
++ data1 = inlpc(ITE_DATA);
++ data1 &= 0x2e;
++ data1 |= 0xa;
++ outlpc(ITE_DATA, data1);
++ outlpc(ITE_ADDR, 0xf4);
++ data1 = inlpc(ITE_DATA);
++ data1 &= 0xaf;
++ data1 |= 0x80;
++ outlpc(ITE_DATA, data1);
++ outlpc(ITE_ADDR, 0xf5);
++ data1 = inlpc(ITE_DATA);
++ data1 &= 0x3f;
++ data1 |= 0x0;
++ outlpc(ITE_DATA, data1);
++ /* initialize all device */
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x04);
++ outlpc(ITE_ADDR, 0x30);
++ outlpc(ITE_DATA, 0x01);
++#if 1
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x05);
++ outlpc(ITE_ADDR, 0xf0);
++ outlpc(ITE_DATA, 0x4e);
++ outlpc(ITE_ADDR, 0x71);
++ outlpc(ITE_DATA, 0x01);
++#endif
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x06);
++ outlpc(ITE_ADDR, 0x30);
++ outlpc(ITE_DATA, 0x01);
++#if 1
++ outlpc(ITE_ADDR, 0xf0);
++ outlpc(ITE_DATA, 0x01);
++ outlpc(ITE_ADDR, 0x71);
++ outlpc(ITE_DATA, 0x01);
++#endif
++
++ /* exit configure mode */
++ outlpc(ITE_ADDR, 0x02);
++ outlpc(ITE_DATA, 0x02);
++ return 0;
++not_found:
++ printk("ITE8717 not found\n");
++ return -1;
++}
++
++subsys_initcall(ite8717_init);
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/Makefile linux-3.4.110/arch/nds32/platforms/ag102/Makefile
+--- linux-3.4.110.orig/arch/nds32/platforms/ag102/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag102/Makefile 2016-04-07 10:20:51.002083345 +0200
+@@ -0,0 +1,5 @@
++obj-y += devices.o ahbclkcal.o
++obj-$(CONFIG_LPC) += lpc.o
++obj-$(CONFIG_PM) += pm.o sleep.o
++obj-$(CONFIG_AG102_CPU_FREQ_FCS) += cpu-fcs.o
++obj-$(CONFIG_AG102_CPU_FREQ_SCALING_MODE) += freq-scaling.o
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/pcu.h linux-3.4.110/arch/nds32/platforms/ag102/pcu.h
+--- linux-3.4.110.orig/arch/nds32/platforms/ag102/pcu.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag102/pcu.h 2016-04-07 10:20:51.002083345 +0200
+@@ -0,0 +1,1887 @@
++#ifndef __PCU_H
++#define __PCU_H
++#include <asm/spec.h>
++#define CPE_PCU_BASE PCU_VA_BASE
++//Data type
++typedef enum Bool {
++ FALSE,
++ TRUE
++} BOOL;
++
++typedef enum {
++ SUCCESS=0,
++ FAIL
++} STATUS;
++
++typedef unsigned char UINT8;
++typedef char INT8;
++typedef unsigned short UINT16;
++typedef short INT16;
++typedef unsigned int UINT32;
++typedef int INT32;
++typedef unsigned long long UINT64;
++typedef long long INT64;
++
++//Registion IO operation macro
++#define REG32(a) (*(volatile UINT32 *)(a))
++#define REG16(a) (*(volatile UINT16 *)(a))
++#define REG8(a) (*(volatile UINT8 *)(a))
++
++#define inb(a) REG8(a)
++#define inhw(a) REG16(a)
++#define inw(a) REG32(a)
++
++#define outb(a, v) (REG8(a) = (UINT8)(v))
++#define outhw(a, v) (REG16(a) = (UINT16)(v))
++#define outw(a, v) (REG32(a) = (UINT32)(v))
++
++
++// Register bit operation macro
++#define ANDES_BIT_MASK(bit_h, bit_l) ((((UINT32)0x1<<(1+bit_h-bit_l))-(UINT32)0x1)<<bit_l)
++
++
++#define SET_BIT(addr, bit) do { outw(addr, (inw(addr) | (0x1<<(bit)))); } while(0)
++#define CLR_BIT(addr, bit) do { outw(addr, (inw(addr) & (~(0x1<<(bit))))); } while(0)
++
++#define SET_FIELD(addr, mask, offset, value) do {\
++ outw(addr, ((inw(addr) & (~mask)) | (((value) << (offset)) &(mask)))); \
++ } while (0)
++#define GET_FIELD(addr, mask, offset) ((inw(addr)&(mask))>> (offset))
++
++#define TEST_FIELD(addr, mask) (inw(addr)&(mask))
++
++#define SET_REG(addr, value) do { outw(addr, value); } while (0)
++#define GET_REG(addr) (inw(addr))
++
++#define CHECK_FIELD(value, mask) ( (value)&(mask) )
++#define EXTRACT_FIELD(value, mask, offset) ( ((value)&(mask))>>(offset) )
++#define PREPARE_FIELD(value, mask, offset) ( ((value)<<(offset))&(mask) )
++
++
++// Variable bit operation macro
++#define VAR_TEST_BIT(var, sig) ((var)&(sig))
++#define VAR_SET_BIT(var, sig) ((var) = (var)|(sig))
++#define VAR_CLR_BIT(var, sig) ((var) = (var)&(~(sig)))
++// ============================
++// PCU register definition
++// ============================
++#define PCU_REG_VER (CPE_PCU_BASE+0x000) //version
++#define PCU_REG_SPINFO (CPE_PCU_BASE+0x004) //scartch pad information
++#define PCU_REG_SOCID (CPE_PCU_BASE+0x010) //SoC ID
++#define PCU_REG_AHB_CFG (CPE_PCU_BASE+0x014) //AHB device configuration
++#define PCU_REG_APB_CFG (CPE_PCU_BASE+0x018) //APB device configuration
++#define PCU_REG_DCSR0 (CPE_PCU_BASE+0x020) //driving capability and slew rate control 0
++#define PCU_REG_DCSR1 (CPE_PCU_BASE+0x024) //driving capability and slew rate control 1
++#define PCU_REG_DCSR2 (CPE_PCU_BASE+0x028) //driving capability and slew rate control 2
++#define PCU_REG_MFPS0 (CPE_PCU_BASE+0x030) //multi-function port setting 0
++#define PCU_REG_MFPS1 (CPE_PCU_BASE+0x034) //multi-function port setting 1
++#define PCU_REG_DMA_SEL (CPE_PCU_BASE+0x038) //dma engin selection
++#define PCU_REG_OSC_CTRL (CPE_PCU_BASE+0x040) //OSC control register
++#define PCU_REG_PWM_DIV (CPE_PCU_BASE+0x044) //PWM clock divider value
++#define PCU_REG_MISC (CPE_PCU_BASE+0x048) //misc register
++#define PCU_REG_BSM_CTRL (CPE_PCU_BASE+0x080) //BSM control register
++#define PCU_REG_BSM_STATUS (CPE_PCU_BASE+0x084) //BSM status
++#define PCU_REG_WAKEUP_SEN (CPE_PCU_BASE+0x088) //wakeup event signal sensitivity
++#define PCU_REG_WAKEUP_STATUS (CPE_PCU_BASE+0x08c) //wakeup event status
++#define PCU_REG_RESET_TIMER (CPE_PCU_BASE+0x090) //reset timer register
++#define PCU_REG_INTR (CPE_PCU_BASE+0x094) //interrup register
++#define PCU_REG_PCS1_CFG (CPE_PCU_BASE+0x0a0)
++#define PCU_REG_PCS1_PARA (CPE_PCU_BASE+0x0a4)
++#define PCU_REG_PCS1_ST1 (CPE_PCU_BASE+0x0a8)
++#define PCU_REG_PCS1_ST2 (CPE_PCU_BASE+0x0ac)
++#define PCU_REG_PCS1_PDD (CPE_PCU_BASE+0x0b0)
++#define PCU_REG_PCS2_CFG (CPE_PCU_BASE+0x0c0)
++#define PCU_REG_PCS2_PARA (CPE_PCU_BASE+0x0c4)
++#define PCU_REG_PCS2_ST1 (CPE_PCU_BASE+0x0c8)
++#define PCU_REG_PCS2_ST2 (CPE_PCU_BASE+0x0cc)
++#define PCU_REG_PCS2_PDD (CPE_PCU_BASE+0x0d0)
++#define PCU_REG_PCS3_CFG (CPE_PCU_BASE+0x0e0)
++#define PCU_REG_PCS3_PARA (CPE_PCU_BASE+0x0e4)
++#define PCU_REG_PCS3_ST1 (CPE_PCU_BASE+0x0e8)
++#define PCU_REG_PCS3_ST2 (CPE_PCU_BASE+0x0ec)
++#define PCU_REG_PCS3_PDD (CPE_PCU_BASE+0x0f0)
++#define PCU_REG_PCS4_CFG (CPE_PCU_BASE+0x100)
++#define PCU_REG_PCS4_PARA (CPE_PCU_BASE+0x104)
++#define PCU_REG_PCS4_ST1 (CPE_PCU_BASE+0x108)
++#define PCU_REG_PCS4_ST2 (CPE_PCU_BASE+0x10c)
++#define PCU_REG_PCS4_PDD (CPE_PCU_BASE+0x110)
++#define PCU_REG_PCS5_CFG (CPE_PCU_BASE+0x120)
++#define PCU_REG_PCS5_PARA (CPE_PCU_BASE+0x124)
++#define PCU_REG_PCS5_ST1 (CPE_PCU_BASE+0x128)
++#define PCU_REG_PCS5_ST2 (CPE_PCU_BASE+0x12c)
++#define PCU_REG_PCS5_PDD (CPE_PCU_BASE+0x130)
++#define PCU_REG_PCS6_CFG (CPE_PCU_BASE+0x140)
++#define PCU_REG_PCS6_PARA (CPE_PCU_BASE+0x144)
++#define PCU_REG_PCS6_ST1 (CPE_PCU_BASE+0x148)
++#define PCU_REG_PCS6_ST2 (CPE_PCU_BASE+0x14c)
++#define PCU_REG_PCS6_PDD (CPE_PCU_BASE+0x150)
++#define PCU_REG_PCS7_CFG (CPE_PCU_BASE+0x160)
++#define PCU_REG_PCS7_PARA (CPE_PCU_BASE+0x164)
++#define PCU_REG_PCS7_ST1 (CPE_PCU_BASE+0x168)
++#define PCU_REG_PCS7_ST2 (CPE_PCU_BASE+0x16c)
++#define PCU_REG_PCS7_PDD (CPE_PCU_BASE+0x170)
++#define PCU_REG_PCS8_CFG (CPE_PCU_BASE+0x180)
++#define PCU_REG_PCS8_PARA (CPE_PCU_BASE+0x184)
++#define PCU_REG_PCS8_ST1 (CPE_PCU_BASE+0x188)
++#define PCU_REG_PCS8_ST2 (CPE_PCU_BASE+0x18c)
++#define PCU_REG_PCS8_PDD (CPE_PCU_BASE+0x190)
++#define PCU_REG_PCS9_CFG (CPE_PCU_BASE+0x1a0)
++#define PCU_REG_PCS9_PARA (CPE_PCU_BASE+0x1a4)
++#define PCU_REG_PCS9_ST1 (CPE_PCU_BASE+0x1a8)
++#define PCU_REG_PCS9_ST2 (CPE_PCU_BASE+0x1ac)
++#define PCU_REG_PCS9_PDD (CPE_PCU_BASE+0x1b0)
++
++#define PCU_SCRATCH_OFFSET_SHIFT (8)
++#define PCU_SCRATCH_SIZE_SHIFT (2) // in byte, 2 means (1<<2) = 4 bytes
++#define PCU_REG_SCRATCH_MEM (CPE_PCU_BASE+ (PCU_SPINFO_OFFSET_DEFAULT<<PCU_SCRATCH_OFFSET_SHIFT) )
++
++// revision register
++#define PCU_VER_VER_MASK (ANDES_BIT_MASK(31, 16))
++#define PCU_VER_VER_OFFSET (16)
++#define PCU_VER_VER_DEFAULT (0x1)
++#define PCU_VER_PCSNO_MASK (ANDES_BIT_MASK(7, 0))
++#define PCU_VER_PCSNO_OFFSET (0)
++#define PCU_VER_PCSNO_DEFAULT (0x9)
++#define PCU_VER_DEFAULT ((PCU_VER_VER_DEFAULT << PCU_VER_VER_OFFSET ) |\
++ (PCU_VER_PCSNO_DEFAULT << PCU_VER_PCSNO_OFFSET))
++
++//scratch pad info
++#define PCU_SPINFO_OFFSET_MASK (ANDES_BIT_MASK(11, 8))
++#define PCU_SPINFO_OFFSET_OFFSET (8)
++#define PCU_SPINFO_OFFSET_DEFAULT (0x4)
++#define PCU_SPINFO_SIZE_MASK (ANDES_BIT_MASK(7, 0))
++#define PCU_SPINFO_SIZE_OFFSET (0)
++#define PCU_SPINFO_SIZE_DEFAULT (0x40)
++#define PCU_SPINFO_DEFAULT ((PCU_SPINFO_OFFSET_DEFAULT << PCU_SPINFO_OFFSET_OFFSET) |\
++ (PCU_SPINFO_SIZE_DEFAULT << PCU_SPINFO_SIZE_OFFSET ))
++
++// revision register
++#define PCU_SOCID_DEV_MASK (ANDES_BIT_MASK(31, 16))
++#define PCU_SOCID_DEV_OFFSET (16)
++#define PCU_SOCID_DEV_DEFAULT (0x102)
++#define PCU_SOCID_MAJ_MASK (ANDES_BIT_MASK(15, 4))
++#define PCU_SOCID_MAJ_OFFSET (4)
++#define PCU_SOCID_MAJ_DEFAULT (0x1)
++#define PCU_SOCID_MIN_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_SOCID_MIN_OFFSET (0)
++#define PCU_SOCID_MIN_DEFAULT (0x0)
++#define PCU_SOCID_DEFAULT ((PCU_SOCID_DEV_DEFAULT << PCU_SOCID_DEV_OFFSET) |\
++ (PCU_SOCID_MAJ_DEFAULT << PCU_SOCID_MAJ_OFFSET) |\
++ (PCU_SOCID_MIN_DEFAULT << PCU_SOCID_MIN_OFFSET))
++
++// AHB configuration
++#define PCU_AHB_CFG_AHB2AHB_MEM3_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_AHB_CFG_AHB2AHB_MEM3_OFFSET (31)
++#define PCU_AHB_CFG_AHB2AHB_MEM3_DEFAULT (0x1)
++#define PCU_AHB_CFG_AHB2AHB_MEM2_MASK (ANDES_BIT_MASK(30, 30))
++#define PCU_AHB_CFG_AHB2AHB_MEM2_OFFSET (30)
++#define PCU_AHB_CFG_AHB2AHB_MEM2_DEFAULT (0x1)
++#define PCU_AHB_CFG_AHB2AHB_MEM1_MASK (ANDES_BIT_MASK(29, 29))
++#define PCU_AHB_CFG_AHB2AHB_MEM1_OFFSET (29)
++#define PCU_AHB_CFG_AHB2AHB_MEM1_DEFAULT (0x1)
++#define PCU_AHB_CFG_AHB2AHB_MEM0_MASK (ANDES_BIT_MASK(28, 28))
++#define PCU_AHB_CFG_AHB2AHB_MEM0_OFFSET (28)
++#define PCU_AHB_CFG_AHB2AHB_MEM0_DEFAULT (0x1)
++#define PCU_AHB_CFG_AHB2AHB_REG_MASK (ANDES_BIT_MASK(27, 27))
++#define PCU_AHB_CFG_AHB2AHB_REG_OFFSET (27)
++#define PCU_AHB_CFG_AHB2AHB_REG_DEFAULT (0x1)
++#define PCU_AHB_CFG_L2CC_MASK (ANDES_BIT_MASK(20, 20))
++#define PCU_AHB_CFG_L2CC_OFFSET (20)
++#define PCU_AHB_CFG_L2CC_DEFAULT (0x1)
++#define PCU_AHB_CFG_PCI_MEM_MASK (ANDES_BIT_MASK(19, 19))
++#define PCU_AHB_CFG_PCI_MEM_OFFSET (19)
++#define PCU_AHB_CFG_PCI_MEM_DEFAULT (0x1)
++#define PCU_AHB_CFG_PCI_IO_MASK (ANDES_BIT_MASK(18, 18))
++#define PCU_AHB_CFG_PCI_IO_OFFSET (18)
++#define PCU_AHB_CFG_PCI_IO_DEFAULT (0x1)
++#define PCU_AHB_CFG_LPC_REG_MASK (ANDES_BIT_MASK(17, 17))
++#define PCU_AHB_CFG_LPC_REG_OFFSET (17)
++#define PCU_AHB_CFG_LPC_REG_DEFAULT (0x1)
++#define PCU_AHB_CFG_LPC_IO_MASK (ANDES_BIT_MASK(16, 16))
++#define PCU_AHB_CFG_LPC_IO_OFFSET (16)
++#define PCU_AHB_CFG_LPC_IO_DEFAULT (0x1)
++#define PCU_AHB_CFG_INTC_MASK (ANDES_BIT_MASK(15, 15))
++#define PCU_AHB_CFG_INTC_OFFSET (15)
++#define PCU_AHB_CFG_INTC_DEFAULT (0x1)
++#define PCU_AHB_CFG_USB_MASK (ANDES_BIT_MASK(14, 14))
++#define PCU_AHB_CFG_USB_OFFSET (14)
++#define PCU_AHB_CFG_USB_DEFAULT (0x1)
++#define PCU_AHB_CFG_IDE_MASK (ANDES_BIT_MASK(13, 13))
++#define PCU_AHB_CFG_IDE_OFFSET (13)
++#define PCU_AHB_CFG_IDE_DEFAULT (0x1)
++#define PCU_AHB_CFG_GMAC_MASK (ANDES_BIT_MASK(12, 12))
++#define PCU_AHB_CFG_GMAC_OFFSET (12)
++#define PCU_AHB_CFG_GMAC_DEFAULT (0x1)
++#define PCU_AHB_CFG_GPU_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_AHB_CFG_GPU_OFFSET (9)
++#define PCU_AHB_CFG_GPU_DEFAULT (0x1)
++#define PCU_AHB_CFG_DLM2_MASK (ANDES_BIT_MASK(8, 8))
++#define PCU_AHB_CFG_DLM2_OFFSET (8)
++#define PCU_AHB_CFG_DLM2_DEFAULT (0x1)
++#define PCU_AHB_CFG_DMAC_MASK (ANDES_BIT_MASK(7, 7))
++#define PCU_AHB_CFG_DMAC_OFFSET (7)
++#define PCU_AHB_CFG_DMAC_DEFAULT (0x1)
++#define PCU_AHB_CFG_DDR2_MEM_MASK (ANDES_BIT_MASK(6, 6))
++#define PCU_AHB_CFG_DDR2_MEM_OFFSET (6)
++#define PCU_AHB_CFG_DDR2_MEM_DEFAULT (0x1)
++#define PCU_AHB_CFG_DDR2C_MASK (ANDES_BIT_MASK(5, 5))
++#define PCU_AHB_CFG_DDR2C_OFFSET (5)
++#define PCU_AHB_CFG_DDR2C_DEFAULT (0x1)
++#define PCU_AHB_CFG_SPI_MASK (ANDES_BIT_MASK(4, 4))
++#define PCU_AHB_CFG_SPI_OFFSET (4)
++#define PCU_AHB_CFG_SPI_DEFAULT (0x1)
++#define PCU_AHB_CFG_DLM1_MASK (ANDES_BIT_MASK(3, 3))
++#define PCU_AHB_CFG_DLM1_OFFSET (3)
++#define PCU_AHB_CFG_DLM1_DEFAULT (0x1)
++#define PCU_AHB_CFG_APB_MASK (ANDES_BIT_MASK(2, 2))
++#define PCU_AHB_CFG_APB_OFFSET (2)
++#define PCU_AHB_CFG_APB_DEFAULT (0x1)
++#define PCU_AHB_CFG_APBREG_MASK (ANDES_BIT_MASK(1, 1))
++#define PCU_AHB_CFG_APBREG_OFFSET (1)
++#define PCU_AHB_CFG_APBREG_DEFAULT (0x1)
++#define PCU_AHB_CFG_AHBC_MASK (ANDES_BIT_MASK(0, 0))
++#define PCU_AHB_CFG_AHBC_OFFSET (0)
++#define PCU_AHB_CFG_AHBC_DEFAULT (0x1)
++#define PCU_AHB_CFG_DEFAULT ((PCU_AHB_CFG_AHB2AHB_MEM3_DEFAULT << PCU_AHB_CFG_AHB2AHB_MEM3_OFFSET) |\
++ (PCU_AHB_CFG_AHB2AHB_MEM2_DEFAULT << PCU_AHB_CFG_AHB2AHB_MEM2_OFFSET) |\
++ (PCU_AHB_CFG_AHB2AHB_MEM1_DEFAULT << PCU_AHB_CFG_AHB2AHB_MEM1_OFFSET) |\
++ (PCU_AHB_CFG_AHB2AHB_MEM0_DEFAULT << PCU_AHB_CFG_AHB2AHB_MEM0_OFFSET) |\
++ (PCU_AHB_CFG_AHB2AHB_REG_DEFAULT << PCU_AHB_CFG_AHB2AHB_REG_OFFSET ) |\
++ (PCU_AHB_CFG_L2CC_DEFAULT << PCU_AHB_CFG_L2CC_OFFSET ) |\
++ (PCU_AHB_CFG_PCI_MEM_DEFAULT << PCU_AHB_CFG_PCI_MEM_OFFSET ) |\
++ (PCU_AHB_CFG_PCI_IO_DEFAULT << PCU_AHB_CFG_PCI_IO_OFFSET ) |\
++ (PCU_AHB_CFG_LPC_REG_DEFAULT << PCU_AHB_CFG_LPC_REG_OFFSET ) |\
++ (PCU_AHB_CFG_LPC_IO_DEFAULT << PCU_AHB_CFG_LPC_IO_OFFSET ) |\
++ (PCU_AHB_CFG_INTC_DEFAULT << PCU_AHB_CFG_INTC_OFFSET ) |\
++ (PCU_AHB_CFG_USB_DEFAULT << PCU_AHB_CFG_USB_OFFSET ) |\
++ (PCU_AHB_CFG_IDE_DEFAULT << PCU_AHB_CFG_IDE_OFFSET ) |\
++ (PCU_AHB_CFG_GMAC_DEFAULT << PCU_AHB_CFG_GMAC_OFFSET ) |\
++ (PCU_AHB_CFG_GPU_DEFAULT << PCU_AHB_CFG_GPU_OFFSET ) |\
++ (PCU_AHB_CFG_DLM2_DEFAULT << PCU_AHB_CFG_DLM2_OFFSET ) |\
++ (PCU_AHB_CFG_DMAC_DEFAULT << PCU_AHB_CFG_DMAC_OFFSET ) |\
++ (PCU_AHB_CFG_DDR2_MEM_DEFAULT << PCU_AHB_CFG_DDR2_MEM_OFFSET ) |\
++ (PCU_AHB_CFG_DDR2C_DEFAULT << PCU_AHB_CFG_DDR2C_OFFSET ) |\
++ (PCU_AHB_CFG_SPI_DEFAULT << PCU_AHB_CFG_SPI_OFFSET ) |\
++ (PCU_AHB_CFG_DLM1_DEFAULT << PCU_AHB_CFG_DLM1_OFFSET ) |\
++ (PCU_AHB_CFG_APB_DEFAULT << PCU_AHB_CFG_APB_OFFSET ) |\
++ (PCU_AHB_CFG_APBREG_DEFAULT << PCU_AHB_CFG_APBREG_OFFSET ) |\
++ (PCU_AHB_CFG_AHBC_DEFAULT << PCU_AHB_CFG_AHBC_OFFSET ))
++
++// APB configuration
++#define PCU_APB_CFG_PWM_MASK (ANDES_BIT_MASK(23, 23))
++#define PCU_APB_CFG_PWM_OFFSET (23)
++#define PCU_APB_CFG_PWM_DEFAULT (0x1)
++#define PCU_APB_CFG_I2C_MASK (ANDES_BIT_MASK(22, 22))
++#define PCU_APB_CFG_I2C_OFFSET (22)
++#define PCU_APB_CFG_I2C_DEFAULT (0x1)
++#define PCU_APB_CFG_GPIO_MASK (ANDES_BIT_MASK(20, 20))
++#define PCU_APB_CFG_GPIO_OFFSET (20)
++#define PCU_APB_CFG_GPIO_DEFAULT (0x1)
++#define PCU_APB_CFG_RTC_MASK (ANDES_BIT_MASK(19, 19))
++#define PCU_APB_CFG_RTC_OFFSET (19)
++#define PCU_APB_CFG_RTC_DEFAULT (0x1)
++#define PCU_APB_CFG_WDT_MASK (ANDES_BIT_MASK(18, 18))
++#define PCU_APB_CFG_WDT_OFFSET (18)
++#define PCU_APB_CFG_WDT_DEFAULT (0x1)
++#define PCU_APB_CFG_TMR_MASK (ANDES_BIT_MASK(17, 17))
++#define PCU_APB_CFG_TMR_OFFSET (17)
++#define PCU_APB_CFG_TMR_DEFAULT (0x1)
++#define PCU_APB_CFG_PCU_MASK (ANDES_BIT_MASK(16, 16))
++#define PCU_APB_CFG_PCU_OFFSET (16)
++#define PCU_APB_CFG_PCU_DEFAULT (0x1)
++#define PCU_APB_CFG_UART2_MASK (ANDES_BIT_MASK(8, 8))
++#define PCU_APB_CFG_UART2_OFFSET (8)
++#define PCU_APB_CFG_UART2_DEFAULT (0x1)
++#define PCU_APB_CFG_AC97I2C_MASK (ANDES_BIT_MASK(6, 6))
++#define PCU_APB_CFG_AC97I2C_OFFSET (6)
++#define PCU_APB_CFG_AC97I2C_DEFAULT (0x1)
++#define PCU_APB_CFG_SDC_MASK (ANDES_BIT_MASK(5, 5))
++#define PCU_APB_CFG_SDC_OFFSET (5)
++#define PCU_APB_CFG_SDC_DEFAULT (0x1)
++#define PCU_APB_CFG_UART1_MASK (ANDES_BIT_MASK(3, 3))
++#define PCU_APB_CFG_UART1_OFFSET (3)
++#define PCU_APB_CFG_UART1_DEFAULT (0x1)
++#define PCU_APB_CFG_SSP_MASK (ANDES_BIT_MASK(2, 2))
++#define PCU_APB_CFG_SSP_OFFSET (2)
++#define PCU_APB_CFG_SSP_DEFAULT (0x1)
++#define PCU_APB_CFG_CFC_MASK (ANDES_BIT_MASK(1, 1))
++#define PCU_APB_CFG_CFC_OFFSET (1)
++#define PCU_APB_CFG_CFC_DEFAULT (0x1)
++#define PCU_APB_CFG_DEFAULT ((PCU_APB_CFG_PWM_DEFAULT << PCU_APB_CFG_PWM_OFFSET ) |\
++ (PCU_APB_CFG_I2C_DEFAULT << PCU_APB_CFG_I2C_OFFSET ) |\
++ (PCU_APB_CFG_GPIO_DEFAULT << PCU_APB_CFG_GPIO_OFFSET ) |\
++ (PCU_APB_CFG_RTC_DEFAULT << PCU_APB_CFG_RTC_OFFSET ) |\
++ (PCU_APB_CFG_WDT_DEFAULT << PCU_APB_CFG_WDT_OFFSET ) |\
++ (PCU_APB_CFG_TMR_DEFAULT << PCU_APB_CFG_TMR_OFFSET ) |\
++ (PCU_APB_CFG_PCU_DEFAULT << PCU_APB_CFG_PCU_OFFSET ) |\
++ (PCU_APB_CFG_UART2_DEFAULT << PCU_APB_CFG_UART2_OFFSET ) |\
++ (PCU_APB_CFG_AC97I2C_DEFAULT << PCU_APB_CFG_AC97I2C_OFFSET) |\
++ (PCU_APB_CFG_SDC_DEFAULT << PCU_APB_CFG_SDC_OFFSET ) |\
++ (PCU_APB_CFG_UART1_DEFAULT << PCU_APB_CFG_UART1_OFFSET ) |\
++ (PCU_APB_CFG_SSP_DEFAULT << PCU_APB_CFG_SSP_OFFSET ) |\
++ (PCU_APB_CFG_CFC_DEFAULT << PCU_APB_CFG_CFC_OFFSET ))
++
++// Driving Capability and Slew Rate
++#define PCU_DCSR0_GPU_MASK (ANDES_BIT_MASK(22, 20))
++#define PCU_DCSR0_GPU_OFFSET (20)
++#define PCU_DCSR0_GPU_DEFAULT (0xb)
++#define PCU_DCSR0_GMAC_MASK (ANDES_BIT_MASK(19, 16))
++#define PCU_DCSR0_GMAC_OFFSET (16)
++#define PCU_DCSR0_GMAC_DEFAULT (0x3)
++#define PCU_DCSR0_ULPI_MASK (ANDES_BIT_MASK(15, 12))
++#define PCU_DCSR0_ULPI_OFFSET (12)
++#define PCU_DCSR0_ULPI_DEFAULT (0xb)
++#define PCU_DCSR0_LPC_MASK (ANDES_BIT_MASK(11, 8))
++#define PCU_DCSR0_LPC_OFFSET (8)
++#define PCU_DCSR0_LPC_DEFAULT (0xb)
++#define PCU_DCSR0_PCIAHB_MASK (ANDES_BIT_MASK(4, 0))
++#define PCU_DCSR0_PCIAHB_OFFSET (0)
++#define PCU_DCSR0_PCIAHB_DEFAULT (0xb)
++#define PCU_DCSR1_I2C_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_DCSR1_I2C_OFFSET (0)
++#define PCU_DCSR1_I2C_DEFAULT (0x9)
++#define PCU_DCSR2_PCU_MASK (ANDES_BIT_MASK(31, 28))
++#define PCU_DCSR2_PCU_OFFSET (28)
++#define PCU_DCSR2_PCU_DEFAULT (0x3)
++#define PCU_DCSR2_GPIO_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_DCSR2_GPIO_OFFSET (24)
++#define PCU_DCSR2_GPIO_DEFAULT (0x9)
++#define PCU_DCSR2_CFC_MASK (ANDES_BIT_MASK(23, 20))
++#define PCU_DCSR2_CFC_OFFSET (20)
++#define PCU_DCSR2_CFC_DEFAULT (0xb)
++#define PCU_DCSR2_SD_MASK (ANDES_BIT_MASK(19, 16))
++#define PCU_DCSR2_SD_OFFSET (16)
++#define PCU_DCSR2_SD_DEFAULT (0xb)
++#define PCU_DCSR2_SPI_MASK (ANDES_BIT_MASK(15, 12))
++#define PCU_DCSR2_SPI_OFFSET (12)
++#define PCU_DCSR2_SPI_DEFAULT (0x9)
++#define PCU_DCSR2_AC97_MASK (ANDES_BIT_MASK(11, 8))
++#define PCU_DCSR2_AC97_OFFSET (8)
++#define PCU_DCSR2_AC97_DEFAULT (0xb)
++#define PCU_DCSR2_UART2_MASK (ANDES_BIT_MASK(7, 4))
++#define PCU_DCSR2_UART2_OFFSET (4)
++#define PCU_DCSR2_UART2_DEFAULT (0x9)
++#define PCU_DCSR2_UART1_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_DCSR2_UART1_OFFSET (0)
++#define PCU_DCSR2_UART1_DEFAULT (0x9)
++#define PCU_DCSR0_DEFAULT ((PCU_DCSR0_GPU_DEFAULT << PCU_DCSR0_GPU_OFFSET ) |\
++ (PCU_DCSR0_GMAC_DEFAULT << PCU_DCSR0_GMAC_OFFSET ) |\
++ (PCU_DCSR0_ULPI_DEFAULT << PCU_DCSR0_ULPI_OFFSET ) |\
++ (PCU_DCSR0_LPC_DEFAULT << PCU_DCSR0_LPC_OFFSET ) |\
++ (PCU_DCSR0_PCIAHB_DEFAULT << PCU_DCSR0_PCIAHB_OFFSET))
++#define PCU_DCSR0_DFT_MASK ((PCU_DCSR0_GPU_MASK ) |\
++ (PCU_DCSR0_GMAC_MASK ) |\
++ (PCU_DCSR0_ULPI_MASK ) |\
++ (PCU_DCSR0_LPC_MASK ) |\
++ (PCU_DCSR0_PCIAHB_MASK))
++
++#define PCU_DCSR1_DEFAULT (PCU_DCSR1_I2C_DEFAULT << PCU_DCSR1_I2C_OFFSET )
++#define PCU_DCSR1_DFT_MASK (PCU_DCSR1_I2C_MASK)
++
++#define PCU_DCSR2_DEFAULT ((PCU_DCSR2_PCU_DEFAULT << PCU_DCSR2_PCU_OFFSET ) |\
++ (PCU_DCSR2_GPIO_DEFAULT << PCU_DCSR2_GPIO_OFFSET ) |\
++ (PCU_DCSR2_CFC_DEFAULT << PCU_DCSR2_CFC_OFFSET ) |\
++ (PCU_DCSR2_SD_DEFAULT << PCU_DCSR2_SD_OFFSET ) |\
++ (PCU_DCSR2_SPI_DEFAULT << PCU_DCSR2_SPI_OFFSET ) |\
++ (PCU_DCSR2_AC97_DEFAULT << PCU_DCSR2_AC97_OFFSET ) |\
++ (PCU_DCSR2_UART2_DEFAULT << PCU_DCSR2_UART2_OFFSET ) |\
++ (PCU_DCSR2_UART1_DEFAULT << PCU_DCSR2_UART1_OFFSET ))
++#define PCU_DCSR2_DFT_MASK ((PCU_DCSR2_PCU_MASK ) |\
++ (PCU_DCSR2_GPIO_MASK ) |\
++ (PCU_DCSR2_CFC_MASK ) |\
++ (PCU_DCSR2_SD_MASK ) |\
++ (PCU_DCSR2_SPI_MASK ) |\
++ (PCU_DCSR2_AC97_MASK ) |\
++ (PCU_DCSR2_UART2_MASK) |\
++ (PCU_DCSR2_UART1_MASK))
++
++//multi function port setting
++#define PCU_MFPS0_ENDIAN_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_MFPS0_ENDIAN_OFFSET (31)
++//#define PCU_MFPS0_ENDIAN_DEFAULT (0x)
++#define PCU_MFPS0_IVB_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_MFPS0_IVB_OFFSET (28)
++//#define PCU_MFPS0_IVB_DEFAULT (0x)
++#define PCU_MFPS0_AHBTARGET_MASK (ANDES_BIT_MASK(4, 4))
++#define PCU_MFPS0_AHBTARGET_OFFSET (4)
++//#define PCU_MFPS0_AHBTARGET_DEFAULT (0x)
++#define PCU_MFPS0_AHBDBG_MASK (ANDES_BIT_MASK(3, 3))
++#define PCU_MFPS0_AHBDBG_OFFSET (3)
++//#define PCU_MFPS0_AHBDBG_DEFAULT (0x)
++#define PCU_MFPS0_MINI_MASK (ANDES_BIT_MASK(2, 2))
++#define PCU_MFPS0_MINI_OFFSET (2)
++//#define PCU_MFPS0_MINI_DEFAULT (0x)
++#define PCU_MFPS0_IDE_MASK (ANDES_BIT_MASK(1, 1))
++#define PCU_MFPS0_IDE_OFFSET (1)
++//#define PCU_MFPS0_IDE_DEFAULT (0x)
++#define PCU_MFPS0_PCI_MASK (ANDES_BIT_MASK(0, 0))
++#define PCU_MFPS0_PCI_OFFSET (0)
++//#define PCU_MFPS0_PCI_DEFAULT (0x)
++
++#define PCU_MFPS1_EXT_INT_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_MFPS1_EXT_INT_OFFSET (31)
++#define PCU_MFPS1_EXT_INT_DEFAULT (0x0)
++#define PCU_MFPS1_AHB_FAST_REQ_MASK (ANDES_BIT_MASK(30, 30))
++#define PCU_MFPS1_AHB_FAST_REQ_OFFSET (30)
++#define PCU_MFPS1_AHB_FAST_REQ_DEFAULT (0x1)
++#define PCU_MFPS1_HSMP_FAST_REQ_MASK (ANDES_BIT_MASK(29, 29))
++#define PCU_MFPS1_HSMP_FAST_REQ_OFFSET (29)
++#define PCU_MFPS1_HSMP_FAST_REQ_DEFAULT (0x1)
++#define PCU_MFPS1_DVO_MASK (ANDES_BIT_MASK(28, 28))
++#define PCU_MFPS1_DVO_OFFSET (28)
++#define PCU_MFPS1_DVO_DEFAULT (0x0)
++#define PCU_MFPS1_SD_GPIO_MASK (ANDES_BIT_MASK(10, 10))
++#define PCU_MFPS1_SD_GPIO_OFFSET (10)
++#define PCU_MFPS1_SD_GPIO_DEFAULT (0x1)
++#define PCU_MFPS1_SPI_GPIO_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_MFPS1_SPI_GPIO_OFFSET (9)
++#define PCU_MFPS1_SPI_GPIO_DEFAULT (0x1)
++#define PCU_MFPS1_UART2_GPIO_MASK (ANDES_BIT_MASK(8, 8))
++#define PCU_MFPS1_UART2_GPIO_OFFSET (8)
++#define PCU_MFPS1_UART2_GPIO_DEFAULT (0x1)
++#define PCU_MFPS1_UART1_GPIO_MASK (ANDES_BIT_MASK(7, 7))
++#define PCU_MFPS1_UART1_GPIO_OFFSET (7)
++#define PCU_MFPS1_UART1_GPIO_DEFAULT (0x1)
++#define PCU_MFPS1_I2C_GPIO_MASK (ANDES_BIT_MASK(6, 6))
++#define PCU_MFPS1_I2C_GPIO_OFFSET (6)
++#define PCU_MFPS1_I2C_GPIO_DEFAULT (0x1)
++#define PCU_MFPS1_PME_GPIO_MASK (ANDES_BIT_MASK(5, 5))
++#define PCU_MFPS1_PME_GPIO_OFFSET (5)
++#define PCU_MFPS1_PME_GPIO_DEFAULT (0x1)
++#define PCU_MFPS1_PWEN_GPIO_MASK (ANDES_BIT_MASK(4, 4))
++#define PCU_MFPS1_PWEN_GPIO_OFFSET (4)
++#define PCU_MFPS1_PWEN_GPIO_DEFAULT (0x1)
++#define PCU_MFPS1_AC97_GPIO_MASK (ANDES_BIT_MASK(3, 3))
++#define PCU_MFPS1_AC97_GPIO_OFFSET (3)
++#define PCU_MFPS1_AC97_GPIO_DEFAULT (0x0)
++#define PCU_MFPS1_PWM1_GPIO_MASK (ANDES_BIT_MASK(2, 2))
++#define PCU_MFPS1_PWM1_GPIO_OFFSET (2)
++#define PCU_MFPS1_PWM1_GPIO_DEFAULT (0x0)
++#define PCU_MFPS1_PWM0_GPIO_MASK (ANDES_BIT_MASK(1, 1))
++#define PCU_MFPS1_PWM0_GPIO_OFFSET (1)
++#define PCU_MFPS1_PWM0_GPIO_DEFAULT (0x0)
++#define PCU_MFPS1_SUSPEND_GPIO_MASK (ANDES_BIT_MASK(0, 0))
++#define PCU_MFPS1_SUSPEND_GPIO_OFFSET (0)
++#define PCU_MFPS1_SUSPEND_GPIO_DEFAULT (0x0)
++#define PCU_MFPS1_DEFAULT ((PCU_MFPS1_EXT_INT_DEFAULT << PCU_MFPS1_EXT_INT_OFFSET )|\
++ (PCU_MFPS1_AHB_FAST_REQ_DEFAULT << PCU_MFPS1_AHB_FAST_REQ_OFFSET )|\
++ (PCU_MFPS1_HSMP_FAST_REQ_DEFAULT << PCU_MFPS1_HSMP_FAST_REQ_OFFSET)|\
++ (PCU_MFPS1_DVO_DEFAULT << PCU_MFPS1_DVO_OFFSET )|\
++ (PCU_MFPS1_SD_GPIO_DEFAULT << PCU_MFPS1_SD_GPIO_OFFSET )|\
++ (PCU_MFPS1_SPI_GPIO_DEFAULT << PCU_MFPS1_SPI_GPIO_OFFSET )|\
++ (PCU_MFPS1_UART2_GPIO_DEFAULT << PCU_MFPS1_UART2_GPIO_OFFSET )|\
++ (PCU_MFPS1_UART1_GPIO_DEFAULT << PCU_MFPS1_UART1_GPIO_OFFSET )|\
++ (PCU_MFPS1_I2C_GPIO_DEFAULT << PCU_MFPS1_I2C_GPIO_OFFSET )|\
++ (PCU_MFPS1_PME_GPIO_DEFAULT << PCU_MFPS1_PME_GPIO_OFFSET )|\
++ (PCU_MFPS1_PWEN_GPIO_DEFAULT << PCU_MFPS1_PWEN_GPIO_OFFSET )|\
++ (PCU_MFPS1_AC97_GPIO_DEFAULT << PCU_MFPS1_AC97_GPIO_OFFSET )|\
++ (PCU_MFPS1_PWM1_GPIO_DEFAULT << PCU_MFPS1_PWM1_GPIO_OFFSET )|\
++ (PCU_MFPS1_PWM0_GPIO_DEFAULT << PCU_MFPS1_PWM0_GPIO_OFFSET )|\
++ (PCU_MFPS1_SUSPEND_GPIO_DEFAULT << PCU_MFPS1_SUSPEND_GPIO_OFFSET ))
++#define PCU_MFPS1_DFT_MASK ((PCU_MFPS1_EXT_INT_MASK )|\
++ (PCU_MFPS1_AHB_FAST_REQ_MASK )|\
++ (PCU_MFPS1_HSMP_FAST_REQ_MASK)|\
++ (PCU_MFPS1_DVO_MASK )|\
++ (PCU_MFPS1_SD_GPIO_MASK )|\
++ (PCU_MFPS1_SPI_GPIO_MASK )|\
++ (PCU_MFPS1_UART2_GPIO_MASK )|\
++ (PCU_MFPS1_UART1_GPIO_MASK )|\
++ (PCU_MFPS1_I2C_GPIO_MASK )|\
++ (PCU_MFPS1_PME_GPIO_MASK )|\
++ (PCU_MFPS1_PWEN_GPIO_MASK )|\
++ (PCU_MFPS1_AC97_GPIO_MASK )|\
++ (PCU_MFPS1_PWM1_GPIO_MASK )|\
++ (PCU_MFPS1_PWM0_GPIO_MASK )|\
++ (PCU_MFPS1_SUSPEND_GPIO_MASK ))
++
++//DMA engine selection
++#define PCU_DMA_SEL_CFC_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_DMA_SEL_CFC_OFFSET (9)
++#define PCU_DMA_SEL_CFC_DEFAULT (0x0)
++#define PCU_DMA_SEL_SD_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_DMA_SEL_SD_OFFSET (9)
++#define PCU_DMA_SEL_SD_DEFAULT (0x0)
++#define PCU_DMA_SEL_UART2_TX_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_DMA_SEL_UART2_TX_OFFSET (9)
++#define PCU_DMA_SEL_UART2_TX_DEFAULT (0x0)
++#define PCU_DMA_SEL_UART2_RX_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_DMA_SEL_UART2_RX_OFFSET (9)
++#define PCU_DMA_SEL_UART2_RX_DEFAULT (0x0)
++#define PCU_DMA_SEL_UART1_TX_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_DMA_SEL_UART1_TX_OFFSET (9)
++#define PCU_DMA_SEL_UART1_TX_DEFAULT (0x0)
++#define PCU_DMA_SEL_UART1_RX_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_DMA_SEL_UART1_RX_OFFSET (9)
++#define PCU_DMA_SEL_UART1_RX_DEFAULT (0x0)
++#define PCU_DMA_SEL_AC97_TX_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_DMA_SEL_AC97_TX_OFFSET (9)
++#define PCU_DMA_SEL_AC97_TX_DEFAULT (0x0)
++#define PCU_DMA_SEL_AC97_RX_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_DMA_SEL_AC97_RX_OFFSET (9)
++#define PCU_DMA_SEL_AC97_RX_DEFAULT (0x0)
++#define PCU_DMA_SEL_DEFAULT ((PCU_DMA_SEL_CFC_DEFAULT << PCU_DMA_SEL_CFC_OFFSET ) |\
++ (PCU_DMA_SEL_SD_DEFAULT << PCU_DMA_SEL_SD_OFFSET ) |\
++ (PCU_DMA_SEL_UART2_TX_DEFAULT << PCU_DMA_SEL_UART2_TX_OFFSET) |\
++ (PCU_DMA_SEL_UART2_RX_DEFAULT << PCU_DMA_SEL_UART2_RX_OFFSET) |\
++ (PCU_DMA_SEL_UART1_TX_DEFAULT << PCU_DMA_SEL_UART1_TX_OFFSET) |\
++ (PCU_DMA_SEL_UART1_RX_DEFAULT << PCU_DMA_SEL_UART1_RX_OFFSET) |\
++ (PCU_DMA_SEL_AC97_TX_DEFAULT << PCU_DMA_SEL_AC97_TX_OFFSET ) |\
++ (PCU_DMA_SEL_AC97_RX_DEFAULT << PCU_DMA_SEL_AC97_RX_OFFSET ) )
++#define PCU_DMA_SEL_DFT_MASK ((PCU_DMA_SEL_CFC_MASK ) |\
++ (PCU_DMA_SEL_SD_MASK ) |\
++ (PCU_DMA_SEL_UART2_TX_MASK) |\
++ (PCU_DMA_SEL_UART2_RX_MASK) |\
++ (PCU_DMA_SEL_UART1_TX_MASK) |\
++ (PCU_DMA_SEL_UART1_RX_MASK) |\
++ (PCU_DMA_SEL_AC97_TX_MASK ) |\
++ (PCU_DMA_SEL_AC97_RX_MASK ) )
++
++// OSC control
++#define PCU_OSC_CTRL_OSCH3RAN_MASK (ANDES_BIT_MASK(9, 8))
++#define PCU_OSC_CTRL_OSCH3RAN_OFFSET (8)
++//#define PCU_OSC_CTRL_OSCH3RAN_DEFAULT (0x0)
++#define PCU_OSC_CTRL_OSCH2RAN_MASK (ANDES_BIT_MASK(7, 6))
++#define PCU_OSC_CTRL_OSCH2RAN_OFFSET (6)
++#define PCU_OSC_CTRL_OSCH2RAN_DEFAULT (0x2)
++#define PCU_OSC_CTRL_OSCH1RAN_MASK (ANDES_BIT_MASK(5, 4))
++#define PCU_OSC_CTRL_OSCH1RAN_OFFSET (4)
++//#define PCU_OSC_CTRL_OSCH1RAN_DEFAULT (0x0)
++#define PCU_OSC_CTRL_OSCHTRI_MASK (ANDES_BIT_MASK(2, 2))
++#define PCU_OSC_CTRL_OSCHTRI_OFFSET (2)
++#define PCU_OSC_CTRL_OSCHTRI_DEFAULT (0x0)
++#define PCU_OSC_CTRL_OSCHSTABLE_MASK (ANDES_BIT_MASK(1, 1))
++#define PCU_OSC_CTRL_OSCHSTABLE_OFFSET (1)
++//#define PCU_OSC_CTRL_OSCHSTABLE_DEFAULT (0x0)
++#define PCU_OSC_CTRL_OSCHOFF_MASK (ANDES_BIT_MASK(0, 0))
++#define PCU_OSC_CTRL_OSCHOFF_OFFSET (0)
++//#define PCU_OSC_CTRL_OSCHOFF_DEFAULT (0x0)
++#define PCU_OSC_CTRL_DEFAULT (PCU_OSC_CTRL_OSCH2RAN_DEFAULT << PCU_OSC_CTRL_OSCH2RAN_OFFSET )
++#define PCU_OSC_CTRL_DFT_MASK (PCU_OSC_CTRL_OSCH2RAN_MASK )
++
++// PWM divider
++#define PCU_PWM_DIV_DIV_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PWM_DIV_DIV_OFFSET (0)
++#define PCU_PWM_DIV_DIV_DEFAULT (0x0)
++#define PCU_PWM_DIV_DEFAULT (PCU_PWM_DIV_DIV_DEFAULT<<PCU_PWM_DIV_DIV_OFFSET)
++#define PCU_PWM_DIV_DFT_MASK (PCU_PWM_DIV_DIV_MASK)
++
++// MISC
++#define PCU_MISC_HW_RST_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_MISC_HW_RST_OFFSET (31)
++#define PCU_MISC_HW_RST_DEFAULT (0x0)
++#define PCU_MISC_WD_RST_MASK (ANDES_BIT_MASK(30, 30))
++#define PCU_MISC_WD_RST_OFFSET (30)
++#define PCU_MISC_WD_RST_DEFAULT (0x0)
++#define PCU_MISC_CPUB_SRST_MASK (ANDES_BIT_MASK(29, 29))
++#define PCU_MISC_CPUB_SRST_OFFSET (29)
++#define PCU_MISC_CPUB_SRST_DEFAULT (0x0)
++#define PCU_MISC_CPUA_SRST_MASK (ANDES_BIT_MASK(28, 28))
++#define PCU_MISC_CPUA_SRST_OFFSET (28)
++#define PCU_MISC_CPUA_SRST_DEFAULT (0x0)
++#define PCU_MISC_PW_FAIL_MASK (ANDES_BIT_MASK(27, 27))
++#define PCU_MISC_PW_FAIL_OFFSET (27)
++#define PCU_MISC_PW_FAIL_DEFAULT (0x0)
++#define PCU_MISC_PW_DAILY_MASK (ANDES_BIT_MASK(26, 26))
++#define PCU_MISC_PW_DAILY_OFFSET (26)
++#define PCU_MISC_PW_DAILY_DEFAULT (0x0)
++#define PCU_MISC_PW_LPC_MASK (ANDES_BIT_MASK(25, 25))
++#define PCU_MISC_PW_LPC_OFFSET (25)
++#define PCU_MISC_PW_LPC_DEFAULT (0x0)
++#define PCU_MISC_PW_PCI_MASK (ANDES_BIT_MASK(24, 24))
++#define PCU_MISC_PW_PCI_OFFSET (24)
++#define PCU_MISC_PW_PCI_DEFAULT (0x0)
++#define PCU_MISC_PW_RTC_MASK (ANDES_BIT_MASK(23, 23))
++#define PCU_MISC_PW_RTC_OFFSET (23)
++#define PCU_MISC_PW_RTC_DEFAULT (0x0)
++#define PCU_MISC_PW_WOL_MASK (ANDES_BIT_MASK(22, 22))
++#define PCU_MISC_PW_WOL_OFFSET (2)
++#define PCU_MISC_PW_WOL_DEFAULT (0x0)
++#define PCU_MISC_PW_GPIO5_MASK (ANDES_BIT_MASK(21, 21))
++#define PCU_MISC_PW_GPIO5_OFFSET (21)
++#define PCU_MISC_PW_GPIO5_DEFAULT (0x0)
++#define PCU_MISC_PW_GPIO4_MASK (ANDES_BIT_MASK(20, 20))
++#define PCU_MISC_PW_GPIO4_OFFSET (20)
++#define PCU_MISC_PW_GPIO4_DEFAULT (0x0)
++#define PCU_MISC_PW_GPIO3_MASK (ANDES_BIT_MASK(19, 19))
++#define PCU_MISC_PW_GPIO3_OFFSET (19)
++#define PCU_MISC_PW_GPIO3_DEFAULT (0x0)
++#define PCU_MISC_PW_GPIO2_MASK (ANDES_BIT_MASK(18, 18))
++#define PCU_MISC_PW_GPIO2_OFFSET (18)
++#define PCU_MISC_PW_GPIO2_DEFAULT (0x0)
++#define PCU_MISC_PW_GPIO1_MASK (ANDES_BIT_MASK(17, 17))
++#define PCU_MISC_PW_GPIO1_OFFSET (17)
++#define PCU_MISC_PW_GPIO1_DEFAULT (0x0)
++#define PCU_MISC_PW_GPIO0_MASK (ANDES_BIT_MASK(16, 16))
++#define PCU_MISC_PW_GPIO0_OFFSET (16)
++#define PCU_MISC_PW_GPIO0_DEFAULT (0x0)
++#define PCU_MISC_EN_CPUB_MASK (ANDES_BIT_MASK(15, 15))
++#define PCU_MISC_EN_CPUB_OFFSET (15)
++#define PCU_MISC_EN_CPUB_DEFAULT (0x0)
++#define PCU_MISC_EN_CPUA_MASK (ANDES_BIT_MASK(14, 14))
++#define PCU_MISC_EN_CPUA_OFFSET (14)
++#define PCU_MISC_EN_CPUA_DEFAULT (0x1)
++#define PCU_MISC_DDR_DLL_TEST_MASK (ANDES_BIT_MASK(12, 12))
++#define PCU_MISC_DDR_DLL_TEST_OFFSET (12)
++#define PCU_MISC_DDR_DLL_TEST_DEFAULT (0x0)
++#define PCU_MISC_DDR_DDQ_TEST_MASK (ANDES_BIT_MASK(11, 11))
++#define PCU_MISC_DDR_DDQ_TEST_OFFSET (11)
++#define PCU_MISC_DDR_DDQ_TEST_DEFAULT (0x0)
++#define PCU_MISC_DDR_DLL_SRST_MASK (ANDES_BIT_MASK(10, 10))
++#define PCU_MISC_DDR_DLL_SRST_OFFSET (10)
++#define PCU_MISC_DDR_DLL_SRST_DEFAULT (0x0)
++#define PCU_MISC_DDR_PLL_BYPASS_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_MISC_DDR_PLL_BYPASS_OFFSET (9)
++#define PCU_MISC_DDR_PLL_BYPASS_DEFAULT (0x0)
++#define PCU_MISC_400MHZ_SEL_MASK (ANDES_BIT_MASK(8, 8))
++#define PCU_MISC_400MHZ_SEL_OFFSET (8)
++#define PCU_MISC_400MHZ_SEL_DEFAULT (0x0)
++#define PCU_MISC_EXLM_WAIT_B_MASK (ANDES_BIT_MASK(7, 6))
++#define PCU_MISC_EXLM_WAIT_B_OFFSET (6)
++#define PCU_MISC_EXLM_WAIT_B_DEFAULT (0x0)
++#define PCU_MISC_EXLM_WAIT_A_MASK (ANDES_BIT_MASK(5, 4))
++#define PCU_MISC_EXLM_WAIT_A_OFFSET (4)
++#define PCU_MISC_EXLM_WAIT_A_DEFAULT (0x0)
++#define PCU_MISC_USB_WAKE_MASK (ANDES_BIT_MASK(3, 3))
++#define PCU_MISC_USB_WAKE_OFFSET (3)
++#define PCU_MISC_USB_WAKE_DEFAULT (0x0)
++#define PCU_MISC_RST_PCI_MASK (ANDES_BIT_MASK(2, 2))
++#define PCU_MISC_RST_PCI_OFFSET (2)
++#define PCU_MISC_RST_PCI_DEFAULT (0x0)
++#define PCU_MISC_RST_CPUB_MASK (ANDES_BIT_MASK(1, 1))
++#define PCU_MISC_RST_CPUB_OFFSET (1)
++#define PCU_MISC_RST_CPUB_DEFAULT (0x0)
++#define PCU_MISC_RST_CPUA_MASK (ANDES_BIT_MASK(0, 0))
++#define PCU_MISC_RST_CPUA_OFFSET (0)
++#define PCU_MISC_RST_CPUA_DEFAULT (0x0)
++#define PCU_MISC_DEFAULT (/*(PCU_MISC_EN_CPUB_DEFAULT << PCU_MISC_EN_CPUB_OFFSET )|*/\
++ (PCU_MISC_EN_CPUA_DEFAULT << PCU_MISC_EN_CPUA_OFFSET )|\
++ (PCU_MISC_DDR_DLL_TEST_DEFAULT << PCU_MISC_DDR_DLL_TEST_OFFSET )|\
++ (PCU_MISC_DDR_DDQ_TEST_DEFAULT << PCU_MISC_DDR_DDQ_TEST_OFFSET )|\
++ (PCU_MISC_DDR_DLL_SRST_DEFAULT << PCU_MISC_DDR_DLL_SRST_OFFSET )|\
++ (PCU_MISC_DDR_PLL_BYPASS_DEFAULT << PCU_MISC_DDR_PLL_BYPASS_OFFSET )|\
++ (PCU_MISC_400MHZ_SEL_DEFAULT << PCU_MISC_400MHZ_SEL_OFFSET )|\
++ (PCU_MISC_EXLM_WAIT_B_DEFAULT << PCU_MISC_EXLM_WAIT_B_OFFSET )|\
++ (PCU_MISC_EXLM_WAIT_A_DEFAULT << PCU_MISC_EXLM_WAIT_A_OFFSET )|\
++ (PCU_MISC_USB_WAKE_DEFAULT << PCU_MISC_USB_WAKE_OFFSET )|\
++ (PCU_MISC_RST_PCI_DEFAULT << PCU_MISC_RST_PCI_OFFSET )|\
++ (PCU_MISC_RST_CPUB_DEFAULT << PCU_MISC_RST_CPUB_OFFSET )|\
++ (PCU_MISC_RST_CPUA_DEFAULT << PCU_MISC_RST_CPUA_OFFSET ))
++#define PCU_MISC_DFT_MASK (/*(PCU_MISC_EN_CPUB_MASK )|*/\
++ (PCU_MISC_EN_CPUA_MASK )|\
++ (PCU_MISC_DDR_DLL_TEST_MASK )|\
++ (PCU_MISC_DDR_DDQ_TEST_MASK )|\
++ (PCU_MISC_DDR_DLL_SRST_MASK )|\
++ (PCU_MISC_DDR_PLL_BYPASS_MASK)|\
++ (PCU_MISC_400MHZ_SEL_MASK )|\
++ (PCU_MISC_EXLM_WAIT_B_MASK )|\
++ (PCU_MISC_EXLM_WAIT_A_MASK )|\
++ (PCU_MISC_USB_WAKE_MASK )|\
++ (PCU_MISC_RST_PCI_MASK )|\
++ (PCU_MISC_RST_CPUB_MASK )|\
++ (PCU_MISC_RST_CPUA_MASK ))
++#define PCU_MISC_W1C_MASK ((PCU_MISC_HW_RST_MASK )|\
++ (PCU_MISC_WD_RST_MASK )|\
++ (PCU_MISC_CPUB_SRST_MASK)|\
++ (PCU_MISC_CPUA_SRST_MASK))
++
++// BSM control and status
++#define PCU_BSM_CTRL_IE_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_BSM_CTRL_IE_OFFSET (31)
++#define PCU_BSM_CTRL_IE_DEFAULT (0x0)
++#define PCU_BSM_CTRL_CMD_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_BSM_CTRL_CMD_OFFSET (28)
++#define PCU_BSM_CTRL_CMD_DEFAULT (0x0)
++#define PCU_BSM_CTRL_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_BSM_CTRL_SYNC_OFFSET (24)
++#define PCU_BSM_CTRL_SYNC_DEFAULT (0x3)
++#define PCU_BSM_CTRL_LINK1_MASK (ANDES_BIT_MASK(7, 4))
++#define PCU_BSM_CTRL_LINK1_OFFSET (4)
++#define PCU_BSM_CTRL_LINK1_DEFAULT (0x0)
++#define PCU_BSM_CTRL_LINK0_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_BSM_CTRL_LINK0_OFFSET (0)
++#define PCU_BSM_CTRL_LINK0_DEFAULT (0x0)
++#define PCU_BSM_CTRL_DEFAULT ((PCU_BSM_CTRL_IE_DEFAULT << PCU_BSM_CTRL_IE_OFFSET ) |\
++ (PCU_BSM_CTRL_CMD_DEFAULT << PCU_BSM_CTRL_CMD_OFFSET ) |\
++ (PCU_BSM_CTRL_SYNC_DEFAULT << PCU_BSM_CTRL_SYNC_OFFSET ) |\
++ (PCU_BSM_CTRL_LINK1_DEFAULT << PCU_BSM_CTRL_LINK1_OFFSET) |\
++ (PCU_BSM_CTRL_LINK0_DEFAULT << PCU_BSM_CTRL_LINK0_OFFSET))
++
++#define PCU_BSM_STATUS_STS_MASK (ANDES_BIT_MASK(31, 28))
++#define PCU_BSM_STATUS_STS_OFFSET (28)
++#define PCU_BSM_STATUS_STS_DEFAULT (0x0)
++#define PCU_BSM_STATUS_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_BSM_STATUS_SYNC_OFFSET (24)
++#define PCU_BSM_STATUS_SYNC_DEFAULT (0x0)
++#define PCU_BSM_STATUS_CI1_MASK (ANDES_BIT_MASK(7, 4))
++#define PCU_BSM_STATUS_CI1_OFFSET (4)
++#define PCU_BSM_STATUS_CI1_DEFAULT (0x0)
++#define PCU_BSM_STATUS_CI0_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_BSM_STATUS_CI0_OFFSET (0)
++#define PCU_BSM_STATUS_CI0_DEFAULT (0x0)
++#define PCU_BSM_STATUS_DEFAULT ((PCU_BSM_STATUS_STS_DEFAULT << PCU_BSM_STATUS_STS_OFFSET) |\
++ (PCU_BSM_STATUS_CI1_DEFAULT << PCU_BSM_STATUS_CI1_OFFSET) |\
++ (PCU_BSM_STATUS_CI0_DEFAULT << PCU_BSM_STATUS_CI0_OFFSET))
++
++//wakeup event sensitivity
++#define PCU_WAKEUP_SEN_POL15_MASK (ANDES_BIT_MASK(15, 15))
++#define PCU_WAKEUP_SEN_POL15_OFFSET (15)
++#define PCU_WAKEUP_SEN_POL15_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL14_MASK (ANDES_BIT_MASK(14, 14))
++#define PCU_WAKEUP_SEN_POL14_OFFSET (14)
++#define PCU_WAKEUP_SEN_POL14_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL13_MASK (ANDES_BIT_MASK(13, 13))
++#define PCU_WAKEUP_SEN_POL13_OFFSET (13)
++#define PCU_WAKEUP_SEN_POL13_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL12_MASK (ANDES_BIT_MASK(12, 12))
++#define PCU_WAKEUP_SEN_POL12_OFFSET (12)
++#define PCU_WAKEUP_SEN_POL12_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL11_MASK (ANDES_BIT_MASK(11, 11))
++#define PCU_WAKEUP_SEN_POL11_OFFSET (11)
++#define PCU_WAKEUP_SEN_POL11_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL10_MASK (ANDES_BIT_MASK(10, 10))
++#define PCU_WAKEUP_SEN_POL10_OFFSET (10)
++#define PCU_WAKEUP_SEN_POL10_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL9_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_WAKEUP_SEN_POL9_OFFSET (9)
++#define PCU_WAKEUP_SEN_POL9_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL8_MASK (ANDES_BIT_MASK(8, 8))
++#define PCU_WAKEUP_SEN_POL8_OFFSET (8)
++#define PCU_WAKEUP_SEN_POL8_DEFAULT (0x1)
++#define PCU_WAKEUP_SEN_POL7_MASK (ANDES_BIT_MASK(7, 7))
++#define PCU_WAKEUP_SEN_POL7_OFFSET (7)
++#define PCU_WAKEUP_SEN_POL7_DEFAULT (0x1)
++#define PCU_WAKEUP_SEN_POL6_MASK (ANDES_BIT_MASK(6, 6))
++#define PCU_WAKEUP_SEN_POL6_OFFSET (6)
++#define PCU_WAKEUP_SEN_POL6_DEFAULT (0x1)
++#define PCU_WAKEUP_SEN_POL5_MASK (ANDES_BIT_MASK(5, 5))
++#define PCU_WAKEUP_SEN_POL5_OFFSET (5)
++#define PCU_WAKEUP_SEN_POL5_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL4_MASK (ANDES_BIT_MASK(4, 4))
++#define PCU_WAKEUP_SEN_POL4_OFFSET (4)
++#define PCU_WAKEUP_SEN_POL4_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL3_MASK (ANDES_BIT_MASK(3, 3))
++#define PCU_WAKEUP_SEN_POL3_OFFSET (3)
++#define PCU_WAKEUP_SEN_POL3_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL2_MASK (ANDES_BIT_MASK(2, 2))
++#define PCU_WAKEUP_SEN_POL2_OFFSET (2)
++#define PCU_WAKEUP_SEN_POL2_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL1_MASK (ANDES_BIT_MASK(1, 1))
++#define PCU_WAKEUP_SEN_POL1_OFFSET (1)
++#define PCU_WAKEUP_SEN_POL1_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL0_MASK (ANDES_BIT_MASK(0, 0))
++#define PCU_WAKEUP_SEN_POL0_OFFSET (0)
++#define PCU_WAKEUP_SEN_POL0_DEFAULT (0x0)
++#define PCU_WAKEUP_SEN_POL_MASK (ANDES_BIT_MASK(15, 0))
++#define PCU_WAKEUP_SEN_POL_OFFSET (0)
++#define PCU_WAKEUP_SEN_POL_DEFAULT ((PCU_WAKEUP_SEN_POL15_DEFAULT << PCU_WAKEUP_SEN_POL15_OFFSET) |\
++ (PCU_WAKEUP_SEN_POL14_DEFAULT << PCU_WAKEUP_SEN_POL14_OFFSET) |\
++ (PCU_WAKEUP_SEN_POL13_DEFAULT << PCU_WAKEUP_SEN_POL13_OFFSET) |\
++ (PCU_WAKEUP_SEN_POL12_DEFAULT << PCU_WAKEUP_SEN_POL12_OFFSET) |\
++ (PCU_WAKEUP_SEN_POL11_DEFAULT << PCU_WAKEUP_SEN_POL11_OFFSET) |\
++ (PCU_WAKEUP_SEN_POL10_DEFAULT << PCU_WAKEUP_SEN_POL10_OFFSET) |\
++ (PCU_WAKEUP_SEN_POL9_DEFAULT << PCU_WAKEUP_SEN_POL9_OFFSET ) |\
++ (PCU_WAKEUP_SEN_POL8_DEFAULT << PCU_WAKEUP_SEN_POL8_OFFSET ) |\
++ (PCU_WAKEUP_SEN_POL7_DEFAULT << PCU_WAKEUP_SEN_POL7_OFFSET ) |\
++ (PCU_WAKEUP_SEN_POL6_DEFAULT << PCU_WAKEUP_SEN_POL6_OFFSET ) |\
++ (PCU_WAKEUP_SEN_POL5_DEFAULT << PCU_WAKEUP_SEN_POL5_OFFSET ) |\
++ (PCU_WAKEUP_SEN_POL4_DEFAULT << PCU_WAKEUP_SEN_POL4_OFFSET ) |\
++ (PCU_WAKEUP_SEN_POL3_DEFAULT << PCU_WAKEUP_SEN_POL3_OFFSET ) |\
++ (PCU_WAKEUP_SEN_POL2_DEFAULT << PCU_WAKEUP_SEN_POL3_OFFSET ) |\
++ (PCU_WAKEUP_SEN_POL1_DEFAULT << PCU_WAKEUP_SEN_POL2_OFFSET ) |\
++ (PCU_WAKEUP_SEN_POL0_DEFAULT << PCU_WAKEUP_SEN_POL0_OFFSET ) )
++#define PCU_WAKEUP_SEN_DEFAULT (PCU_WAKEUP_SEN_POL_DEFAULT)
++#define PCU_WAKEUP_SEN_DFT_MASK (PCU_WAKEUP_SEN_POL_MASK)
++
++#define PCU_WAKEUP_SEN_GPIO0_POL_MASK PCU_WAKEUP_SEN_POL0_MASK
++#define PCU_WAKEUP_SEN_GPIO0_POL_OFFSET PCU_WAKEUP_SEN_POL0_OFFSET
++#define PCU_WAKEUP_SEN_GPIO0_POL_DEFAULT PCU_WAKEUP_SEN_POL0_DEFAULT
++#define PCU_WAKEUP_SEN_GPIO1_POL_MASK PCU_WAKEUP_SEN_POL1_MASK
++#define PCU_WAKEUP_SEN_GPIO1_POL_OFFSET PCU_WAKEUP_SEN_POL1_OFFSET
++#define PCU_WAKEUP_SEN_GPIO1_POL_DEFAULT PCU_WAKEUP_SEN_POL1_DEFAULT
++#define PCU_WAKEUP_SEN_GPIO2_POL_MASK PCU_WAKEUP_SEN_POL2_MASK
++#define PCU_WAKEUP_SEN_GPIO2_POL_OFFSET PCU_WAKEUP_SEN_POL2_OFFSET
++#define PCU_WAKEUP_SEN_GPIO2_POL_DEFAULT PCU_WAKEUP_SEN_POL2_DEFAULT
++#define PCU_WAKEUP_SEN_GPIO3_POL_MASK PCU_WAKEUP_SEN_POL3_MASK
++#define PCU_WAKEUP_SEN_GPIO3_POL_OFFSET PCU_WAKEUP_SEN_POL3_OFFSET
++#define PCU_WAKEUP_SEN_GPIO3_POL_DEFAULT PCU_WAKEUP_SEN_POL3_DEFAULT
++#define PCU_WAKEUP_SEN_GPIO4_POL_MASK PCU_WAKEUP_SEN_POL4_MASK
++#define PCU_WAKEUP_SEN_GPIO4_POL_OFFSET PCU_WAKEUP_SEN_POL4_OFFSET
++#define PCU_WAKEUP_SEN_GPIO4_POL_DEFAULT PCU_WAKEUP_SEN_POL4_DEFAULT
++#define PCU_WAKEUP_SEN_GPIO5_POL_MASK PCU_WAKEUP_SEN_POL5_MASK
++#define PCU_WAKEUP_SEN_GPIO5_POL_OFFSET PCU_WAKEUP_SEN_POL5_OFFSET
++#define PCU_WAKEUP_SEN_GPIO5_POL_DEFAULT PCU_WAKEUP_SEN_POL5_DEFAULT
++#define PCU_WAKEUP_SEN_WOL_POL_MASK PCU_WAKEUP_SEN_POL6_MASK
++#define PCU_WAKEUP_SEN_WOL_POL_OFFSET PCU_WAKEUP_SEN_POL6_OFFSET
++#define PCU_WAKEUP_SEN_WOL_POL_DEFAULT PCU_WAKEUP_SEN_POL6_DEFAULT
++#define PCU_WAKEUP_SEN_RTC_POL_MASK PCU_WAKEUP_SEN_POL7_MASK
++#define PCU_WAKEUP_SEN_RTC_POL_OFFSET PCU_WAKEUP_SEN_POL7_OFFSET
++#define PCU_WAKEUP_SEN_RTC_POL_DEFAULT PCU_WAKEUP_SEN_POL7_DEFAULT
++#define PCU_WAKEUP_SEN_DAY_POL_OFFSET PCU_WAKEUP_SEN_POL8_OFFSET
++#define PCU_WAKEUP_SEN_DAY_POL_DEFAULT PCU_WAKEUP_SEN_POL8_DEFAULT
++#define PCU_WAKEUP_SEN_DBG_POL_MASK PCU_WAKEUP_SEN_POL9_MASK
++#define PCU_WAKEUP_SEN_DBG_POL_OFFSET PCU_WAKEUP_SEN_POL9_OFFSET
++#define PCU_WAKEUP_SEN_DBG_POL_DEFAULT PCU_WAKEUP_SEN_POL9_DEFAULT
++#define PCU_WAKEUP_SEN_PCI_POL_MASK PCU_WAKEUP_SEN_POL10_MASK
++#define PCU_WAKEUP_SEN_PCI_POL_OFFSET PCU_WAKEUP_SEN_POL10_OFFSET
++#define PCU_WAKEUP_SEN_PCI_POL_DEFAULT PCU_WAKEUP_SEN_POL10_DEFAULT
++#define PCU_WAKEUP_SEN_LPC_POL_MASK PCU_WAKEUP_SEN_POL11_MASK
++#define PCU_WAKEUP_SEN_LPC_POL_OFFSET PCU_WAKEUP_SEN_POL11_OFFSET
++#define PCU_WAKEUP_SEN_LPC_POL_DEFAULT PCU_WAKEUP_SEN_POL11_DEFAULT
++
++// wakeup event status register
++#define PCU_WAKEUP_STATUS_SIG_MASK (ANDES_BIT_MASK(15, 0))
++#define PCU_WAKEUP_STATUS_SIG_OFFSET (0)
++#define PCU_WAKEUP_STATUS_SIG_DEFAULT (0x0)
++#define PCU_WAKEUP_STATUS_DEFAULT (PCU_WAKEUP_STATUS_SIG_DEFAULT << PCU_WAKEUP_STATUS_SIG_OFFSET)
++#define PCU_WAKEUP_STATUS_DFT_MASK (PCU_WAKEUP_STATUS_SIG_MASK)
++
++//reset timing
++#define PCU_RESET_TIMER_RG3_MASK (ANDES_BIT_MASK(31, 24))
++#define PCU_RESET_TIMER_RG3_OFFSET (24)
++#define PCU_RESET_TIMER_RG3_DEFAULT PCU_RESET_TIMER_RG3_CNT_DEFAULT // in rtl fast reset, this will be 0x2
++#define PCU_RESET_TIMER_RG3_SRC_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_RESET_TIMER_RG3_SRC_OFFSET (31)
++#define PCU_RESET_TIMER_RG3_SRC_DEFAULT (0x0)
++#define PCU_RESET_TIMER_RG3_CNT_MASK (ANDES_BIT_MASK(30, 24))
++#define PCU_RESET_TIMER_RG3_CNT_OFFSET (24)
++#define PCU_RESET_TIMER_RG3_CNT_DEFAULT (0x4)
++#define PCU_RESET_TIMER_RG2_MASK (ANDES_BIT_MASK(23, 16))
++#define PCU_RESET_TIMER_RG2_OFFSET (16)
++#define PCU_RESET_TIMER_RG2_DEFAULT PCU_RESET_TIMER_RG2_CNT_DEFAULT // in rtl fast reset, this will be 0x2
++#define PCU_RESET_TIMER_RG2_SRC_MASK (ANDES_BIT_MASK(23, 23))
++#define PCU_RESET_TIMER_RG2_SRC_OFFSET (23)
++#define PCU_RESET_TIMER_RG2_SRC_DEFAULT (0x0)
++#define PCU_RESET_TIMER_RG2_CNT_MASK (ANDES_BIT_MASK(22, 16))
++#define PCU_RESET_TIMER_RG2_CNT_OFFSET (16)
++#define PCU_RESET_TIMER_RG2_CNT_DEFAULT (0x4)
++#define PCU_RESET_TIMER_RG1_MASK (ANDES_BIT_MASK(15, 8))
++#define PCU_RESET_TIMER_RG1_OFFSET (8)
++#define PCU_RESET_TIMER_RG1_DEFAULT PCU_RESET_TIMER_RG1_CNT_DEFAULT // in rtl fast reset, this will be 0x2
++#define PCU_RESET_TIMER_RG1_SRC_MASK (ANDES_BIT_MASK(15, 15))
++#define PCU_RESET_TIMER_RG1_SRC_OFFSET (15)
++#define PCU_RESET_TIMER_RG1_SRC_DEFAULT (0x0)
++#define PCU_RESET_TIMER_RG1_CNT_MASK (ANDES_BIT_MASK(14, 8))
++#define PCU_RESET_TIMER_RG1_CNT_OFFSET (8)
++#define PCU_RESET_TIMER_RG1_CNT_DEFAULT (0x4)
++#define PCU_RESET_TIMER_RG0_MASK (ANDES_BIT_MASK(7, 0))
++#define PCU_RESET_TIMER_RG0_OFFSET (0)
++#define PCU_RESET_TIMER_RG0_DEFAULT PCU_RESET_TIMER_RG0_CNT_DEFAULT // in rtl fast reset, this will be 0x2
++#define PCU_RESET_TIMER_RG0_SRC_MASK (ANDES_BIT_MASK(7, 7))
++#define PCU_RESET_TIMER_RG0_SRC_OFFSET (7)
++#define PCU_RESET_TIMER_RG0_SRC_DEFAULT (0x0)
++#define PCU_RESET_TIMER_RG0_CNT_MASK (ANDES_BIT_MASK(6, 0))
++#define PCU_RESET_TIMER_RG0_CNT_OFFSET (0)
++#define PCU_RESET_TIMER_RG0_CNT_DEFAULT (0x4)
++
++#define PCU_RESET_TIMER_DEFAULT 0x0 /*((PCU_RESET_TIMER_RG3_DEFAULT << PCU_RESET_TIMER_RG3_OFFSET)|\
++ (PCU_RESET_TIMER_RG2_DEFAULT << PCU_RESET_TIMER_RG2_OFFSET)|\
++ (PCU_RESET_TIMER_RG1_DEFAULT << PCU_RESET_TIMER_RG1_OFFSET)|\
++ (PCU_RESET_TIMER_RG0_DEFAULT << PCU_RESET_TIMER_RG0_OFFSET))*/
++#define PCU_RESET_TIMER_DFT_MASK 0x0 /*((PCU_RESET_TIMER_RG3_MASK)|\
++ (PCU_RESET_TIMER_RG2_MASK)|\
++ (PCU_RESET_TIMER_RG1_MASK)|\
++ (PCU_RESET_TIMER_RG0_MASK))*/
++#define PCU_RST_TIMER_SRC_500US (0x1)
++#define PCU_RST_TIMER_SRC_30US (0x0)
++
++// interrupt
++#define PCU_INTR_GPIOSEC_MASK (ANDES_BIT_MASK(11, 11))
++#define PCU_INTR_PWRLOW_MASK (ANDES_BIT_MASK(10, 10))
++#define PCU_INTR_PCS9_MASK (ANDES_BIT_MASK(9, 9))
++#define PCU_INTR_PCS9_OFFSET (9)
++#define PCU_INTR_PCS9_DEFAULT (0x0)
++#define PCU_INTR_PCS8_MASK (ANDES_BIT_MASK(8, 8))
++#define PCU_INTR_PCS8_OFFSET (8)
++#define PCU_INTR_PCS8_DEFAULT (0x0)
++#define PCU_INTR_PCS7_MASK (ANDES_BIT_MASK(7, 7))
++#define PCU_INTR_PCS7_OFFSET (7)
++#define PCU_INTR_PCS7_DEFAULT (0x0)
++#define PCU_INTR_PCS6_MASK (ANDES_BIT_MASK(6, 6))
++#define PCU_INTR_PCS6_OFFSET (6)
++#define PCU_INTR_PCS6_DEFAULT (0x0)
++#define PCU_INTR_PCS5_MASK (ANDES_BIT_MASK(5, 5))
++#define PCU_INTR_PCS5_OFFSET (5)
++#define PCU_INTR_PCS5_DEFAULT (0x0)
++#define PCU_INTR_PCS4_MASK (ANDES_BIT_MASK(4, 4))
++#define PCU_INTR_PCS4_OFFSET (4)
++#define PCU_INTR_PCS4_DEFAULT (0x0)
++#define PCU_INTR_PCS3_MASK (ANDES_BIT_MASK(3, 3))
++#define PCU_INTR_PCS3_OFFSET (3)
++#define PCU_INTR_PCS3_DEFAULT (0x0)
++#define PCU_INTR_PCS2_MASK (ANDES_BIT_MASK(2, 2))
++#define PCU_INTR_PCS2_OFFSET (2)
++#define PCU_INTR_PCS2_DEFAULT (0x0)
++#define PCU_INTR_PCS1_MASK (ANDES_BIT_MASK(1, 1))
++#define PCU_INTR_PCS1_OFFSET (1)
++#define PCU_INTR_PCS1_DEFAULT (0x0)
++#define PCU_INTR_BSM_MASK (ANDES_BIT_MASK(0, 0))
++#define PCU_INTR_BSM_OFFSET (0)
++#define PCU_INTR_BSM_DEFAULT (0x0)
++#define PCU_INTR_DEFAULT (0x0)
++
++// bits field for PCS1 registers
++#define PCU_PCS1_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS1_CFG_TYPE_OFFSET (28)
++#define PCU_PCS1_CFG_TYPE_DEFAULT (0x1)
++#define PCU_PCS1_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
++#define PCU_PCS1_CFG_WR_OFFSET (27)
++#define PCU_PCS1_CFG_WR_DEFAULT (0x0)
++#define PCU_PCS1_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
++#define PCU_PCS1_CFG_SR_OFFSET (0)
++#define PCU_PCS1_CFG_SR_DEFAULT (0x0)
++#define PCU_PCS1_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
++#define PCU_PCS1_CFG_LS_OFFSET (20)
++#define PCU_PCS1_CFG_LS_DEFAULT (0x0)
++#define PCU_PCS1_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
++#define PCU_PCS1_CFG_LW_OFFSET (16)
++#define PCU_PCS1_CFG_LW_DEFAULT (0x0)
++#define PCU_PCS1_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
++#define PCU_PCS1_CFG_WKEN_OFFSET (0)
++#define PCU_PCS1_CFG_WKEN_DEFAULT (0x0)
++#define PCU_PCS1_CFG_DEFAULT ((PCU_PCS1_CFG_TYPE_DEFAULT << PCU_PCS1_CFG_TYPE_OFFSET)|\
++ (PCU_PCS1_CFG_WR_DEFAULT << PCU_PCS1_CFG_WR_OFFSET )|\
++ (PCU_PCS1_CFG_SR_DEFAULT << PCU_PCS1_CFG_SR_OFFSET )|\
++ (PCU_PCS1_CFG_LS_DEFAULT << PCU_PCS1_CFG_LS_OFFSET )|\
++ (PCU_PCS1_CFG_LW_DEFAULT << PCU_PCS1_CFG_LW_OFFSET )|\
++ (PCU_PCS1_CFG_WKEN_DEFAULT << PCU_PCS1_CFG_WKEN_OFFSET))
++
++#define PCU_PCS1_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_PCS1_PARA_IE_OFFSET (31)
++#define PCU_PCS1_PARA_IE_DEFAULT (0x0)
++#define PCU_PCS1_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS1_PARA_CMD_OFFSET (28)
++#define PCU_PCS1_PARA_CMD_DEFAULT (0x0)
++#define PCU_PCS1_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS1_PARA_SYNC_OFFSET (24)
++#define PCU_PCS1_PARA_SYNC_DEFAULT (0x3)
++#define PCU_PCS1_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS1_PARA_NXTPAR_OFFSET (0)
++#define PCU_PCS1_PARA_NXTPAR_DEFAULT (0x1)
++#define PCU_PCS1_PARA_DIV_MASK (ANDES_BIT_MASK(5, 4))
++#define PCU_PCS1_PARA_DIV_OFFSET (4)
++//#define PCU_PCS1_PARA_DIV_DEFAULT (0x0) //jumper setting
++#define PCU_PCS1_PARA_RATIO_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PCS1_PARA_RATIO_OFFSET (0)
++//#define PCU_PCS1_PARA_RATIO_DEFAULT (0x0) //jumper setting
++#define PCU_PCS1_PARA_DEFAULT ((PCU_PCS1_PARA_IE_DEFAULT << PCU_PCS1_PARA_IE_OFFSET )|\
++ (PCU_PCS1_PARA_CMD_DEFAULT << PCU_PCS1_PARA_CMD_OFFSET )|\
++ (PCU_PCS1_PARA_SYNC_DEFAULT << PCU_PCS1_PARA_SYNC_OFFSET))
++#define PCU_PCS1_PARA_DFT_MASK ((PCU_PCS1_PARA_IE_MASK )|\
++ (PCU_PCS1_PARA_CMD_MASK )|\
++ (PCU_PCS1_PARA_SYNC_MASK))
++
++#define PCU_PCS1_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS1_ST1_STS_OFFSET (28)
++#define PCU_PCS1_ST1_STS_DEFAULT (0x0)
++#define PCU_PCS1_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PCS1_ST1_ERR_OFFSET (0)
++#define PCU_PCS1_ST1_ERR_DEFAULT (0x0)
++#define PCU_PCS1_ST1_DEFAULT ((PCU_PCS1_ST1_STS_DEFAULT << PCU_PCS1_ST1_STS_OFFSET )|\
++ (PCU_PCS1_ST1_ERR_DEFAULT << PCU_PCS1_ST1_ERR_OFFSET ))
++
++#define PCU_PCS1_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS1_ST2_SYNC_OFFSET (24)
++#define PCU_PCS1_ST2_SYNC_DEFAULT (0x0)
++#define PCU_PCS1_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS1_ST2_CURPAR_OFFSET (0)
++//#define PCU_PCS1_ST2_CURPAR_DEFAULT (0x0)
++#define PCU_PCS1_ST2_DIV_MASK (ANDES_BIT_MASK(5, 4))
++#define PCU_PCS1_ST2_DIV_OFFSET (4)
++//#define PCU_PCS1_ST2_DIV_DEFAULT (0x0) //jumper setting
++#define PCU_PCS1_ST2_RATIO_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PCS1_ST2_RATIO_OFFSET (0)
++//#define PCU_PCS1_ST2_RATIO_DEFAULT (0x0) //jumper setting
++#define PCU_PCS1_ST2_DEFAULT (PCU_PCS1_ST2_SYNC_DEFAULT << PCU_PCS1_ST2_SYNC_OFFSET)
++#define PCU_PCS1_ST2_DFT_MASK (PCU_PCS1_ST2_SYNC_MASK)
++
++
++// bits field for PCS2 registers
++#define PCU_PCS2_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS2_CFG_TYPE_OFFSET (28)
++#define PCU_PCS2_CFG_TYPE_DEFAULT (0x2)
++#define PCU_PCS2_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
++#define PCU_PCS2_CFG_WR_OFFSET (27)
++#define PCU_PCS2_CFG_WR_DEFAULT (0x0)
++#define PCU_PCS2_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
++#define PCU_PCS2_CFG_SR_OFFSET (0)
++#define PCU_PCS2_CFG_SR_DEFAULT (0x0)
++#define PCU_PCS2_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
++#define PCU_PCS2_CFG_LS_OFFSET (20)
++#define PCU_PCS2_CFG_LS_DEFAULT (0x0)
++#define PCU_PCS2_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
++#define PCU_PCS2_CFG_LW_OFFSET (16)
++#define PCU_PCS2_CFG_LW_DEFAULT (0x0)
++#define PCU_PCS2_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
++#define PCU_PCS2_CFG_WKEN_OFFSET (0)
++#define PCU_PCS2_CFG_WKEN_DEFAULT (0x0)
++#define PCU_PCS2_CFG_DEFAULT ((PCU_PCS2_CFG_TYPE_DEFAULT << PCU_PCS2_CFG_TYPE_OFFSET)|\
++ (PCU_PCS2_CFG_WR_DEFAULT << PCU_PCS2_CFG_WR_OFFSET )|\
++ (PCU_PCS2_CFG_SR_DEFAULT << PCU_PCS2_CFG_SR_OFFSET )|\
++ (PCU_PCS2_CFG_LS_DEFAULT << PCU_PCS2_CFG_LS_OFFSET )|\
++ (PCU_PCS2_CFG_LW_DEFAULT << PCU_PCS2_CFG_LW_OFFSET )|\
++ (PCU_PCS2_CFG_WKEN_DEFAULT << PCU_PCS2_CFG_WKEN_OFFSET))
++
++#define PCU_PCS2_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_PCS2_PARA_IE_OFFSET (31)
++#define PCU_PCS2_PARA_IE_DEFAULT (0x0)
++#define PCU_PCS2_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS2_PARA_CMD_OFFSET (28)
++#define PCU_PCS2_PARA_CMD_DEFAULT (0x0)
++#define PCU_PCS2_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS2_PARA_SYNC_OFFSET (24)
++#define PCU_PCS2_PARA_SYNC_DEFAULT (0x3)
++#define PCU_PCS2_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS2_PARA_NXTPAR_OFFSET (0)
++#define PCU_PCS2_PARA_NXTPAR_DEFAULT (0x0)
++#define PCU_PCS2_PARA_DEFAULT ((PCU_PCS2_PARA_IE_DEFAULT << PCU_PCS2_PARA_IE_OFFSET )|\
++ (PCU_PCS2_PARA_CMD_DEFAULT << PCU_PCS2_PARA_CMD_OFFSET )|\
++ (PCU_PCS2_PARA_SYNC_DEFAULT << PCU_PCS2_PARA_SYNC_OFFSET )|\
++ (PCU_PCS2_PARA_NXTPAR_DEFAULT << PCU_PCS2_PARA_NXTPAR_OFFSET))
++#define PCU_PCS2_PARA_DFT_MASK ((PCU_PCS2_PARA_IE_MASK )|\
++ (PCU_PCS2_PARA_CMD_MASK )|\
++ (PCU_PCS2_PARA_SYNC_MASK )|\
++ (PCU_PCS2_PARA_NXTPAR_MASK))
++
++#define PCU_PCS2_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS2_ST1_STS_OFFSET (28)
++#define PCU_PCS2_ST1_STS_DEFAULT (0x0)
++#define PCU_PCS2_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PCS2_ST1_ERR_OFFSET (0)
++#define PCU_PCS2_ST1_ERR_DEFAULT (0x0)
++#define PCU_PCS2_ST1_DEFAULT ((PCU_PCS2_ST1_STS_DEFAULT << PCU_PCS2_ST1_STS_OFFSET )|\
++ (PCU_PCS2_ST1_ERR_DEFAULT << PCU_PCS2_ST1_ERR_OFFSET ))
++
++#define PCU_PCS2_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS2_ST2_SYNC_OFFSET (24)
++#define PCU_PCS2_ST2_SYNC_DEFAULT (0x0)
++#define PCU_PCS2_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS2_ST2_CURPAR_OFFSET (0)
++#define PCU_PCS2_ST2_CURPAR_DEFAULT (0x0)
++#define PCU_PCS2_ST2_DEFAULT ((PCU_PCS2_ST2_SYNC_DEFAULT << PCU_PCS2_ST2_SYNC_OFFSET )|\
++ (PCU_PCS2_ST2_CURPAR_DEFAULT << PCU_PCS2_ST2_CURPAR_OFFSET))
++#define PCU_PCS2_ST2_DFT_MASK ((PCU_PCS2_ST2_SYNC_MASK )|\
++ (PCU_PCS2_ST2_CURPAR_MASK))
++
++// bits field for PCS3 registers
++#define PCU_PCS3_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS3_CFG_TYPE_OFFSET (28)
++#define PCU_PCS3_CFG_TYPE_DEFAULT (0x2)
++#define PCU_PCS3_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
++#define PCU_PCS3_CFG_WR_OFFSET (27)
++#define PCU_PCS3_CFG_WR_DEFAULT (0x0)
++#define PCU_PCS3_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
++#define PCU_PCS3_CFG_SR_OFFSET (0)
++#define PCU_PCS3_CFG_SR_DEFAULT (0x0)
++#define PCU_PCS3_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
++#define PCU_PCS3_CFG_LS_OFFSET (20)
++#define PCU_PCS3_CFG_LS_DEFAULT (0x0)
++#define PCU_PCS3_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
++#define PCU_PCS3_CFG_LW_OFFSET (16)
++#define PCU_PCS3_CFG_LW_DEFAULT (0x0)
++#define PCU_PCS3_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
++#define PCU_PCS3_CFG_WKEN_OFFSET (0)
++#define PCU_PCS3_CFG_WKEN_DEFAULT (0x0)
++#define PCU_PCS3_CFG_DEFAULT ((PCU_PCS3_CFG_TYPE_DEFAULT << PCU_PCS3_CFG_TYPE_OFFSET)|\
++ (PCU_PCS3_CFG_WR_DEFAULT << PCU_PCS3_CFG_WR_OFFSET )|\
++ (PCU_PCS3_CFG_SR_DEFAULT << PCU_PCS3_CFG_SR_OFFSET )|\
++ (PCU_PCS3_CFG_LS_DEFAULT << PCU_PCS3_CFG_LS_OFFSET )|\
++ (PCU_PCS3_CFG_LW_DEFAULT << PCU_PCS3_CFG_LW_OFFSET )|\
++ (PCU_PCS3_CFG_WKEN_DEFAULT << PCU_PCS3_CFG_WKEN_OFFSET))
++
++#define PCU_PCS3_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_PCS3_PARA_IE_OFFSET (31)
++#define PCU_PCS3_PARA_IE_DEFAULT (0x0)
++#define PCU_PCS3_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS3_PARA_CMD_OFFSET (28)
++#define PCU_PCS3_PARA_CMD_DEFAULT (0x0)
++#define PCU_PCS3_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS3_PARA_SYNC_OFFSET (24)
++#define PCU_PCS3_PARA_SYNC_DEFAULT (0x3)
++#define PCU_PCS3_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS3_PARA_NXTPAR_OFFSET (0)
++#define PCU_PCS3_PARA_NXTPAR_DEFAULT (0x0)
++#define PCU_PCS3_PARA_DEFAULT ((PCU_PCS3_PARA_IE_DEFAULT << PCU_PCS3_PARA_IE_OFFSET )|\
++ (PCU_PCS3_PARA_CMD_DEFAULT << PCU_PCS3_PARA_CMD_OFFSET )|\
++ (PCU_PCS3_PARA_SYNC_DEFAULT << PCU_PCS3_PARA_SYNC_OFFSET )|\
++ (PCU_PCS3_PARA_NXTPAR_DEFAULT << PCU_PCS3_PARA_NXTPAR_OFFSET))
++#define PCU_PCS3_PARA_DFT_MASK ((PCU_PCS3_PARA_IE_MASK )|\
++ (PCU_PCS3_PARA_CMD_MASK )|\
++ (PCU_PCS3_PARA_SYNC_MASK )|\
++ (PCU_PCS3_PARA_NXTPAR_MASK))
++
++#define PCU_PCS3_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS3_ST1_STS_OFFSET (28)
++#define PCU_PCS3_ST1_STS_DEFAULT (0x0)
++#define PCU_PCS3_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PCS3_ST1_ERR_OFFSET (0)
++#define PCU_PCS3_ST1_ERR_DEFAULT (0x0)
++#define PCU_PCS3_ST1_DEFAULT ((PCU_PCS3_ST1_STS_DEFAULT << PCU_PCS3_ST1_STS_OFFSET )|\
++ (PCU_PCS3_ST1_ERR_DEFAULT << PCU_PCS3_ST1_ERR_OFFSET ))
++
++#define PCU_PCS3_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS3_ST2_SYNC_OFFSET (24)
++#define PCU_PCS3_ST2_SYNC_DEFAULT (0x0)
++#define PCU_PCS3_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS3_ST2_CURPAR_OFFSET (0)
++#define PCU_PCS3_ST2_CURPAR_DEFAULT (0x0)
++#define PCU_PCS3_ST2_DEFAULT ((PCU_PCS3_ST2_SYNC_DEFAULT << PCU_PCS3_ST2_SYNC_OFFSET )|\
++ (PCU_PCS3_ST2_CURPAR_DEFAULT << PCU_PCS3_ST2_CURPAR_OFFSET))
++#define PCU_PCS3_ST2_DFT_MASK ((PCU_PCS3_ST2_SYNC_MASK )|\
++ (PCU_PCS3_ST2_CURPAR_MASK))
++
++// bits field for PCS4 registers
++#define PCU_PCS4_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS4_CFG_TYPE_OFFSET (28)
++#define PCU_PCS4_CFG_TYPE_DEFAULT (0x0)
++#define PCU_PCS4_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
++#define PCU_PCS4_CFG_WR_OFFSET (27)
++#define PCU_PCS4_CFG_WR_DEFAULT (0x0)
++#define PCU_PCS4_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
++#define PCU_PCS4_CFG_SR_OFFSET (0)
++#define PCU_PCS4_CFG_SR_DEFAULT (0x0)
++#define PCU_PCS4_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
++#define PCU_PCS4_CFG_LS_OFFSET (20)
++#define PCU_PCS4_CFG_LS_DEFAULT (0x0)
++#define PCU_PCS4_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
++#define PCU_PCS4_CFG_LW_OFFSET (16)
++#define PCU_PCS4_CFG_LW_DEFAULT (0x0)
++#define PCU_PCS4_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
++#define PCU_PCS4_CFG_WKEN_OFFSET (0)
++#define PCU_PCS4_CFG_WKEN_DEFAULT (0x0)
++#define PCU_PCS4_CFG_DEFAULT ((PCU_PCS4_CFG_TYPE_DEFAULT << PCU_PCS4_CFG_TYPE_OFFSET)|\
++ (PCU_PCS4_CFG_WR_DEFAULT << PCU_PCS4_CFG_WR_OFFSET )|\
++ (PCU_PCS4_CFG_SR_DEFAULT << PCU_PCS4_CFG_SR_OFFSET )|\
++ (PCU_PCS4_CFG_LS_DEFAULT << PCU_PCS4_CFG_LS_OFFSET )|\
++ (PCU_PCS4_CFG_LW_DEFAULT << PCU_PCS4_CFG_LW_OFFSET )|\
++ (PCU_PCS4_CFG_WKEN_DEFAULT << PCU_PCS4_CFG_WKEN_OFFSET))
++
++#define PCU_PCS4_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_PCS4_PARA_IE_OFFSET (31)
++#define PCU_PCS4_PARA_IE_DEFAULT (0x0)
++#define PCU_PCS4_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS4_PARA_CMD_OFFSET (28)
++#define PCU_PCS4_PARA_CMD_DEFAULT (0x0)
++#define PCU_PCS4_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS4_PARA_SYNC_OFFSET (24)
++#define PCU_PCS4_PARA_SYNC_DEFAULT (0x3)
++#define PCU_PCS4_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS4_PARA_NXTPAR_OFFSET (0)
++#define PCU_PCS4_PARA_NXTPAR_DEFAULT (0x4)
++#define PCU_PCS4_PARA_PWDN_MASK (ANDES_BIT_MASK(23, 23))
++#define PCU_PCS4_PARA_PWDN_OFFSET (23)
++#define PCU_PCS4_PARA_PWDN_DEFAULT (0x0)
++#define PCU_PCS4_PARA_RANGE_MASK (ANDES_BIT_MASK(17, 16))
++#define PCU_PCS4_PARA_RANGE_OFFSET (16)
++#define PCU_PCS4_PARA_RANGE_DEFAULT (0x0)
++#define PCU_PCS4_PARA_N_FACTOR_MASK (ANDES_BIT_MASK(7, 0))
++#define PCU_PCS4_PARA_N_FACTOR_OFFSET (0)
++#define PCU_PCS4_PARA_N_FACTOR_DEFAULT (0x4)
++#define PCU_PCS4_PARA_DEFAULT ((PCU_PCS4_PARA_IE_DEFAULT << PCU_PCS4_PARA_IE_OFFSET )|\
++ (PCU_PCS4_PARA_CMD_DEFAULT << PCU_PCS4_PARA_CMD_OFFSET )|\
++ (PCU_PCS4_PARA_SYNC_DEFAULT << PCU_PCS4_PARA_SYNC_OFFSET)|\
++ (PCU_PCS4_PARA_PWDN_DEFAULT << PCU_PCS4_PARA_PWDN_OFFSET))
++#define PCU_PCS4_PARA_DFT_MASK ((PCU_PCS4_PARA_IE_MASK )|\
++ (PCU_PCS4_PARA_CMD_MASK )|\
++ (PCU_PCS4_PARA_SYNC_MASK)|\
++ (PCU_PCS4_PARA_PWDN_MASK))
++
++#define PCU_PCS4_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS4_ST1_STS_OFFSET (28)
++#define PCU_PCS4_ST1_STS_DEFAULT (0x0)
++#define PCU_PCS4_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PCS4_ST1_ERR_OFFSET (0)
++#define PCU_PCS4_ST1_ERR_DEFAULT (0x0)
++#define PCU_PCS4_ST1_DEFAULT ((PCU_PCS4_ST1_STS_DEFAULT << PCU_PCS4_ST1_STS_OFFSET )|\
++ (PCU_PCS4_ST1_ERR_DEFAULT << PCU_PCS4_ST1_ERR_OFFSET ))
++
++#define PCU_PCS4_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS4_ST2_SYNC_OFFSET (24)
++#define PCU_PCS4_ST2_SYNC_DEFAULT (0x0)
++#define PCU_PCS4_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS4_ST2_CURPAR_OFFSET (0)
++//#define PCU_PCS4_ST2_CURPAR_DEFAULT (0x0)
++#define PCU_PCS4_ST2_PWDN_MASK PCU_PCS4_PARA_PWDN_MASK
++#define PCU_PCS4_ST2_PWDN_OFFSET PCU_PCS4_PARA_PWDN_OFFSET
++#define PCU_PCS4_ST2_PWDN_DEFAULT PCU_PCS4_PARA_PWDN_DEFAULT
++#define PCU_PCS4_ST2_RANGE_MASK PCU_PCS4_PARA_RANGE_MASK
++#define PCU_PCS4_ST2_RANGE_OFFSET PCU_PCS4_PARA_RANGE_OFFSET
++//#define PCU_PCS4_ST2_RANGE_DEFAULT PCU_PCS4_PARA_RANGE_DEFAULT
++#define PCU_PCS4_ST2_N_FACTOR_MASK PCU_PCS4_PARA_N_FACTOR_MASK
++#define PCU_PCS4_ST2_N_FACTOR_OFFSET PCU_PCS4_PARA_N_FACTOR_OFFSET
++//#define PCU_PCS4_ST2_N_FACTOR_DEFAULT PCU_PCS4_PARA_N_FACTOR_DEFAULT
++#define PCU_PCS4_ST2_DEFAULT ((PCU_PCS4_ST2_SYNC_DEFAULT << PCU_PCS4_ST2_SYNC_OFFSET)|\
++ (PCU_PCS4_ST2_PWDN_DEFAULT << PCU_PCS4_ST2_PWDN_OFFSET))
++#define PCU_PCS4_ST2_DFT_MASK ((PCU_PCS4_ST2_SYNC_MASK)|\
++ (PCU_PCS4_ST2_PWDN_MASK))
++
++// bits field for PCS5 registers
++#define PCU_PCS5_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS5_CFG_TYPE_OFFSET (28)
++#define PCU_PCS5_CFG_TYPE_DEFAULT (0x0)
++#define PCU_PCS5_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
++#define PCU_PCS5_CFG_WR_OFFSET (27)
++#define PCU_PCS5_CFG_WR_DEFAULT (0x0)
++#define PCU_PCS5_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
++#define PCU_PCS5_CFG_SR_OFFSET (0)
++#define PCU_PCS5_CFG_SR_DEFAULT (0x0)
++#define PCU_PCS5_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
++#define PCU_PCS5_CFG_LS_OFFSET (20)
++#define PCU_PCS5_CFG_LS_DEFAULT (0x0)
++#define PCU_PCS5_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
++#define PCU_PCS5_CFG_LW_OFFSET (16)
++#define PCU_PCS5_CFG_LW_DEFAULT (0x0)
++#define PCU_PCS5_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
++#define PCU_PCS5_CFG_WKEN_OFFSET (0)
++#define PCU_PCS5_CFG_WKEN_DEFAULT (0x0)
++#define PCU_PCS5_CFG_DEFAULT ((PCU_PCS5_CFG_TYPE_DEFAULT << PCU_PCS5_CFG_TYPE_OFFSET)|\
++ (PCU_PCS5_CFG_WR_DEFAULT << PCU_PCS5_CFG_WR_OFFSET )|\
++ (PCU_PCS5_CFG_SR_DEFAULT << PCU_PCS5_CFG_SR_OFFSET )|\
++ (PCU_PCS5_CFG_LS_DEFAULT << PCU_PCS5_CFG_LS_OFFSET )|\
++ (PCU_PCS5_CFG_LW_DEFAULT << PCU_PCS5_CFG_LW_OFFSET )|\
++ (PCU_PCS5_CFG_WKEN_DEFAULT << PCU_PCS5_CFG_WKEN_OFFSET))
++
++#define PCU_PCS5_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_PCS5_PARA_IE_OFFSET (31)
++#define PCU_PCS5_PARA_IE_DEFAULT (0x0)
++#define PCU_PCS5_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS5_PARA_CMD_OFFSET (28)
++#define PCU_PCS5_PARA_CMD_DEFAULT (0x0)
++#define PCU_PCS5_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS5_PARA_SYNC_OFFSET (24)
++#define PCU_PCS5_PARA_SYNC_DEFAULT (0x3)
++#define PCU_PCS5_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS5_PARA_NXTPAR_OFFSET (0)
++#define PCU_PCS5_PARA_NXTPAR_DEFAULT (0x0)
++#define PCU_PCS5_PARA_DLL_PWDN_MASK (ANDES_BIT_MASK(23, 23))
++#define PCU_PCS5_PARA_DLL_PWDN_OFFSET (23)
++#define PCU_PCS5_PARA_DLL_PWDN_DEFAULT (0x0)
++#define PCU_PCS5_PARA_PLL_PWDN_MASK (ANDES_BIT_MASK(22, 22))
++#define PCU_PCS5_PARA_PLL_PWDN_OFFSET (22)
++#define PCU_PCS5_PARA_PLL_PWDN_DEFAULT (0x0)
++#define PCU_PCS5_PARA_DLL_BYPASS_MASK (ANDES_BIT_MASK(16, 16))
++#define PCU_PCS5_PARA_DLL_BYPASS_OFFSET (16)
++#define PCU_PCS5_PARA_DLL_BYPASS_DEFAULT (0x0)
++#define PCU_PCS5_PARA_DLL_DELAY_MASK (ANDES_BIT_MASK(15, 12))
++#define PCU_PCS5_PARA_DLL_DELAY_OFFSET (12)
++#define PCU_PCS5_PARA_DLL_DELAY_DEFAULT (0x0)
++#define PCU_PCS5_PARA_66MHZ_MASK (ANDES_BIT_MASK(11, 11))
++#define PCU_PCS5_PARA_66MHZ_OFFSET (11)
++//#define PCU_PCS5_PARA_66MHZ_DEFAULT (0x0) /dumper setting
++#define PCU_PCS5_PARA_DEFAULT ((PCU_PCS5_PARA_IE_DEFAULT << PCU_PCS5_PARA_IE_OFFSET )|\
++ (PCU_PCS5_PARA_CMD_DEFAULT << PCU_PCS5_PARA_CMD_OFFSET )|\
++ (PCU_PCS5_PARA_SYNC_DEFAULT << PCU_PCS5_PARA_SYNC_OFFSET )|\
++ (PCU_PCS5_PARA_PLL_PWDN_DEFAULT << PCU_PCS5_PARA_PLL_PWDN_OFFSET )|\
++ (PCU_PCS5_PARA_DLL_DELAY_DEFAULT << PCU_PCS5_PARA_DLL_DELAY_OFFSET ))
++#define PCU_PCS5_PARA_DFT_MASK ((PCU_PCS5_PARA_IE_MASK )|\
++ (PCU_PCS5_PARA_CMD_MASK )|\
++ (PCU_PCS5_PARA_SYNC_MASK )|\
++ (PCU_PCS5_PARA_PLL_PWDN_MASK )|\
++ (PCU_PCS5_PARA_DLL_DELAY_MASK ))
++
++#define PCU_PCS5_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS5_ST1_STS_OFFSET (28)
++#define PCU_PCS5_ST1_STS_DEFAULT (0x0)
++#define PCU_PCS5_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PCS5_ST1_ERR_OFFSET (0)
++#define PCU_PCS5_ST1_ERR_DEFAULT (0x0)
++#define PCU_PCS5_ST1_DEFAULT ((PCU_PCS5_ST1_STS_DEFAULT << PCU_PCS5_ST1_STS_OFFSET )|\
++ (PCU_PCS5_ST1_ERR_DEFAULT << PCU_PCS5_ST1_ERR_OFFSET ))
++
++#define PCU_PCS5_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS5_ST2_SYNC_OFFSET (24)
++#define PCU_PCS5_ST2_SYNC_DEFAULT (0x0)
++#define PCU_PCS5_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS5_ST2_CURPAR_OFFSET (0)
++//#define PCU_PCS5_ST2_CURPAR_DEFAULT (0x0) //no default
++#define PCU_PCS5_ST2_DLL_PWDN_MASK PCU_PCS5_PARA_DLL_PWDN_MASK
++#define PCU_PCS5_ST2_DLL_PWDN_OFFSET PCU_PCS5_PARA_DLL_PWDN_OFFSET
++#define PCU_PCS5_ST2_DLL_PWDN_DEFAULT PCU_PCS5_PARA_DLL_PWDN_DEFAULT
++#define PCU_PCS5_ST2_PLL_PWDN_MASK PCU_PCS5_PARA_PLL_PWDN_MASK
++#define PCU_PCS5_ST2_PLL_PWDN_OFFSET PCU_PCS5_PARA_PLL_PWDN_OFFSET
++#define PCU_PCS5_ST2_PLL_PWDN_DEFAULT PCU_PCS5_PARA_PLL_PWDN_DEFAULT
++#define PCU_PCS5_ST2_DLL_BYPASS_MASK PCU_PCS5_PARA_DLL_BYPASS_MASK
++#define PCU_PCS5_ST2_DLL_BYPASS_OFFSET PCU_PCS5_PARA_DLL_BYPASS_OFFSET
++#define PCU_PCS5_ST2_DLL_BYPASS_DEFAULT PCU_PCS5_PARA_DLL_BYPASS_DEFAULT
++#define PCU_PCS5_ST2_DLL_DELAY_MASK PCU_PCS5_PARA_DLL_DELAY_MASK
++#define PCU_PCS5_ST2_DLL_DELAY_OFFSET PCU_PCS5_PARA_DLL_DELAY_OFFSET
++#define PCU_PCS5_ST2_DLL_DELAY_DEFAULT PCU_PCS5_PARA_DLL_DELAY_DEFAULT
++#define PCU_PCS5_ST2_DEFAULT ((PCU_PCS5_ST2_SYNC_DEFAULT << PCU_PCS5_ST2_SYNC_OFFSET )|\
++ (PCU_PCS5_ST2_PLL_PWDN_DEFAULT << PCU_PCS5_ST2_PLL_PWDN_OFFSET )|\
++ (PCU_PCS5_ST2_DLL_DELAY_DEFAULT << PCU_PCS5_ST2_DLL_DELAY_OFFSET ))
++#define PCU_PCS5_ST2_DFT_MASK ((PCU_PCS5_ST2_SYNC_MASK )|\
++ (PCU_PCS5_ST2_PLL_PWDN_MASK )|\
++ (PCU_PCS5_ST2_DLL_DELAY_MASK ))
++
++// bits field for PCS6 registers
++#define PCU_PCS6_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS6_CFG_TYPE_OFFSET (28)
++#define PCU_PCS6_CFG_TYPE_DEFAULT (0x0)
++#define PCU_PCS6_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
++#define PCU_PCS6_CFG_WR_OFFSET (27)
++#define PCU_PCS6_CFG_WR_DEFAULT (0x0)
++#define PCU_PCS6_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
++#define PCU_PCS6_CFG_SR_OFFSET (0)
++#define PCU_PCS6_CFG_SR_DEFAULT (0x0)
++#define PCU_PCS6_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
++#define PCU_PCS6_CFG_LS_OFFSET (20)
++#define PCU_PCS6_CFG_LS_DEFAULT (0x0)
++#define PCU_PCS6_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
++#define PCU_PCS6_CFG_LW_OFFSET (16)
++#define PCU_PCS6_CFG_LW_DEFAULT (0x0)
++#define PCU_PCS6_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
++#define PCU_PCS6_CFG_WKEN_OFFSET (0)
++#define PCU_PCS6_CFG_WKEN_DEFAULT (0x0)
++#define PCU_PCS6_CFG_DEFAULT ((PCU_PCS6_CFG_TYPE_DEFAULT << PCU_PCS6_CFG_TYPE_OFFSET)|\
++ (PCU_PCS6_CFG_WR_DEFAULT << PCU_PCS6_CFG_WR_OFFSET )|\
++ (PCU_PCS6_CFG_SR_DEFAULT << PCU_PCS6_CFG_SR_OFFSET )|\
++ (PCU_PCS6_CFG_LS_DEFAULT << PCU_PCS6_CFG_LS_OFFSET )|\
++ (PCU_PCS6_CFG_LW_DEFAULT << PCU_PCS6_CFG_LW_OFFSET )|\
++ (PCU_PCS6_CFG_WKEN_DEFAULT << PCU_PCS6_CFG_WKEN_OFFSET))
++
++#define PCU_PCS6_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_PCS6_PARA_IE_OFFSET (31)
++#define PCU_PCS6_PARA_IE_DEFAULT (0x0)
++#define PCU_PCS6_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS6_PARA_CMD_OFFSET (28)
++#define PCU_PCS6_PARA_CMD_DEFAULT (0x0)
++#define PCU_PCS6_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS6_PARA_SYNC_OFFSET (24)
++#define PCU_PCS6_PARA_SYNC_DEFAULT (0x3)
++#define PCU_PCS6_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS6_PARA_NXTPAR_OFFSET (0)
++#define PCU_PCS6_PARA_NXTPAR_DEFAULT (0x0)
++#define PCU_PCS6_PARA_PWDN_MASK (ANDES_BIT_MASK(23, 23))
++#define PCU_PCS6_PARA_PWDN_OFFSET (23)
++#define PCU_PCS6_PARA_PWDN_DEFAULT (0x0)
++#define PCU_PCS6_PARA_DEFAULT ((PCU_PCS6_PARA_IE_DEFAULT << PCU_PCS6_PARA_IE_OFFSET )|\
++ (PCU_PCS6_PARA_CMD_DEFAULT << PCU_PCS6_PARA_CMD_OFFSET )|\
++ (PCU_PCS6_PARA_SYNC_DEFAULT << PCU_PCS6_PARA_SYNC_OFFSET)|\
++ (PCU_PCS6_PARA_PWDN_DEFAULT << PCU_PCS6_PARA_PWDN_OFFSET))
++#define PCU_PCS6_PARA_DFT_MASK ((PCU_PCS6_PARA_IE_MASK )|\
++ (PCU_PCS6_PARA_CMD_MASK )|\
++ (PCU_PCS6_PARA_SYNC_MASK)|\
++ (PCU_PCS6_PARA_PWDN_MASK))
++
++#define PCU_PCS6_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS6_ST1_STS_OFFSET (28)
++#define PCU_PCS6_ST1_STS_DEFAULT (0x0)
++#define PCU_PCS6_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PCS6_ST1_ERR_OFFSET (0)
++#define PCU_PCS6_ST1_ERR_DEFAULT (0x0)
++#define PCU_PCS6_ST1_DEFAULT ((PCU_PCS6_ST1_STS_DEFAULT << PCU_PCS6_ST1_STS_OFFSET )|\
++ (PCU_PCS6_ST1_ERR_DEFAULT << PCU_PCS6_ST1_ERR_OFFSET ))
++
++#define PCU_PCS6_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS6_ST2_SYNC_OFFSET (24)
++#define PCU_PCS6_ST2_SYNC_DEFAULT (0x0)
++#define PCU_PCS6_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS6_ST2_CURPAR_OFFSET (0)
++//#define PCU_PCS6_ST2_CURPAR_DEFAULT (0x0) //no default
++#define PCU_PCS6_ST2_PWDN_MASK PCU_PCS6_PARA_PWDN_MASK
++#define PCU_PCS6_ST2_PWDN_OFFSET PCU_PCS6_PARA_PWDN_OFFSET
++#define PCU_PCS6_ST2_PWDN_DEFAULT PCU_PCS6_PARA_PWDN_DEFAULT
++#define PCU_PCS6_ST2_DEFAULT ((PCU_PCS6_ST2_SYNC_DEFAULT << PCU_PCS6_ST2_SYNC_OFFSET)|\
++ (PCU_PCS6_ST2_PWDN_DEFAULT << PCU_PCS6_ST2_PWDN_OFFSET))
++#define PCU_PCS6_ST2_DFT_MASK ((PCU_PCS6_ST2_SYNC_MASK)|\
++ (PCU_PCS6_ST2_PWDN_MASK))
++
++// bits field for PCS7 registers
++#define PCU_PCS7_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS7_CFG_TYPE_OFFSET (28)
++#define PCU_PCS7_CFG_TYPE_DEFAULT (0x0)
++#define PCU_PCS7_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
++#define PCU_PCS7_CFG_WR_OFFSET (27)
++#define PCU_PCS7_CFG_WR_DEFAULT (0x0)
++#define PCU_PCS7_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
++#define PCU_PCS7_CFG_SR_OFFSET (0)
++#define PCU_PCS7_CFG_SR_DEFAULT (0x0)
++#define PCU_PCS7_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
++#define PCU_PCS7_CFG_LS_OFFSET (20)
++#define PCU_PCS7_CFG_LS_DEFAULT (0x0)
++#define PCU_PCS7_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
++#define PCU_PCS7_CFG_LW_OFFSET (16)
++#define PCU_PCS7_CFG_LW_DEFAULT (0x0)
++#define PCU_PCS7_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
++#define PCU_PCS7_CFG_WKEN_OFFSET (0)
++#define PCU_PCS7_CFG_WKEN_DEFAULT (0x0)
++#define PCU_PCS7_CFG_DEFAULT ((PCU_PCS7_CFG_TYPE_DEFAULT << PCU_PCS7_CFG_TYPE_OFFSET)|\
++ (PCU_PCS7_CFG_WR_DEFAULT << PCU_PCS7_CFG_WR_OFFSET )|\
++ (PCU_PCS7_CFG_SR_DEFAULT << PCU_PCS7_CFG_SR_OFFSET )|\
++ (PCU_PCS7_CFG_LS_DEFAULT << PCU_PCS7_CFG_LS_OFFSET )|\
++ (PCU_PCS7_CFG_LW_DEFAULT << PCU_PCS7_CFG_LW_OFFSET )|\
++ (PCU_PCS7_CFG_WKEN_DEFAULT << PCU_PCS7_CFG_WKEN_OFFSET))
++
++#define PCU_PCS7_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_PCS7_PARA_IE_OFFSET (31)
++#define PCU_PCS7_PARA_IE_DEFAULT (0x0)
++#define PCU_PCS7_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS7_PARA_CMD_OFFSET (28)
++#define PCU_PCS7_PARA_CMD_DEFAULT (0x0)
++#define PCU_PCS7_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS7_PARA_SYNC_OFFSET (24)
++#define PCU_PCS7_PARA_SYNC_DEFAULT (0x3)
++#define PCU_PCS7_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS7_PARA_NXTPAR_OFFSET (0)
++#define PCU_PCS7_PARA_NXTPAR_DEFAULT (0x0)
++#define PCU_PCS7_PARA_PWDN_MASK (ANDES_BIT_MASK(23, 23))
++#define PCU_PCS7_PARA_PWDN_OFFSET (23)
++#define PCU_PCS7_PARA_PWDN_DEFAULT (0x0)
++#define PCU_PCS7_PARA_DEFAULT ((PCU_PCS7_PARA_IE_DEFAULT << PCU_PCS7_PARA_IE_OFFSET )|\
++ (PCU_PCS7_PARA_CMD_DEFAULT << PCU_PCS7_PARA_CMD_OFFSET )|\
++ (PCU_PCS7_PARA_SYNC_DEFAULT << PCU_PCS7_PARA_SYNC_OFFSET)|\
++ (PCU_PCS7_PARA_PWDN_DEFAULT << PCU_PCS7_PARA_PWDN_OFFSET))
++#define PCU_PCS7_PARA_DFT_MASK ((PCU_PCS7_PARA_IE_MASK )|\
++ (PCU_PCS7_PARA_CMD_MASK )|\
++ (PCU_PCS7_PARA_SYNC_MASK)|\
++ (PCU_PCS7_PARA_PWDN_MASK))
++
++#define PCU_PCS7_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS7_ST1_STS_OFFSET (28)
++#define PCU_PCS7_ST1_STS_DEFAULT (0x0)
++#define PCU_PCS7_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PCS7_ST1_ERR_OFFSET (0)
++#define PCU_PCS7_ST1_ERR_DEFAULT (0x0)
++#define PCU_PCS7_ST1_DEFAULT ((PCU_PCS7_ST1_STS_DEFAULT << PCU_PCS7_ST1_STS_OFFSET )|\
++ (PCU_PCS7_ST1_ERR_DEFAULT << PCU_PCS7_ST1_ERR_OFFSET ))
++
++#define PCU_PCS7_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS7_ST2_SYNC_OFFSET (24)
++#define PCU_PCS7_ST2_SYNC_DEFAULT (0x0)
++#define PCU_PCS7_ST2_CURPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS7_ST2_CURPAR_OFFSET (0)
++//#define PCU_PCS7_ST2_CURPAR_DEFAULT (0x0) //no default
++#define PCU_PCS7_ST2_PWDN_MASK PCU_PCS7_PARA_PWDN_MASK
++#define PCU_PCS7_ST2_PWDN_OFFSET PCU_PCS7_PARA_PWDN_OFFSET
++#define PCU_PCS7_ST2_PWDN_DEFAULT PCU_PCS7_PARA_PWDN_DEFAULT
++#define PCU_PCS7_ST2_DEFAULT ((PCU_PCS7_ST2_SYNC_DEFAULT << PCU_PCS7_ST2_SYNC_OFFSET)|\
++ (PCU_PCS7_ST2_PWDN_DEFAULT << PCU_PCS7_ST2_PWDN_OFFSET))
++#define PCU_PCS7_ST2_DFT_MASK ((PCU_PCS7_ST2_SYNC_MASK)|\
++ (PCU_PCS7_ST2_PWDN_MASK))
++
++// bits field for PCS8 registers
++#define PCU_PCS8_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS8_CFG_TYPE_OFFSET (28)
++#define PCU_PCS8_CFG_TYPE_DEFAULT (0x4)
++#define PCU_PCS8_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
++#define PCU_PCS8_CFG_WR_OFFSET (27)
++#define PCU_PCS8_CFG_WR_DEFAULT (0x0)
++#define PCU_PCS8_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
++#define PCU_PCS8_CFG_SR_OFFSET (0)
++#define PCU_PCS8_CFG_SR_DEFAULT (0x0)
++#define PCU_PCS8_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
++#define PCU_PCS8_CFG_LS_OFFSET (20)
++#define PCU_PCS8_CFG_LS_DEFAULT (0x0)
++#define PCU_PCS8_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
++#define PCU_PCS8_CFG_LW_OFFSET (16)
++#define PCU_PCS8_CFG_LW_DEFAULT (0x0)
++#define PCU_PCS8_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
++#define PCU_PCS8_CFG_WKEN_OFFSET (0)
++#define PCU_PCS8_CFG_WKEN_DEFAULT (0x0)
++#define PCU_PCS8_CFG_DEFAULT ((PCU_PCS8_CFG_TYPE_DEFAULT << PCU_PCS8_CFG_TYPE_OFFSET)|\
++ (PCU_PCS8_CFG_WR_DEFAULT << PCU_PCS8_CFG_WR_OFFSET )|\
++ (PCU_PCS8_CFG_SR_DEFAULT << PCU_PCS8_CFG_SR_OFFSET )|\
++ (PCU_PCS8_CFG_LS_DEFAULT << PCU_PCS8_CFG_LS_OFFSET )|\
++ (PCU_PCS8_CFG_LW_DEFAULT << PCU_PCS8_CFG_LW_OFFSET )|\
++ (PCU_PCS8_CFG_WKEN_DEFAULT << PCU_PCS8_CFG_WKEN_OFFSET))
++
++#define PCU_PCS8_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_PCS8_PARA_IE_OFFSET (31)
++#define PCU_PCS8_PARA_IE_DEFAULT (0x0)
++#define PCU_PCS8_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS8_PARA_CMD_OFFSET (28)
++#define PCU_PCS8_PARA_CMD_DEFAULT (0x0)
++#define PCU_PCS8_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS8_PARA_SYNC_OFFSET (24)
++#define PCU_PCS8_PARA_SYNC_DEFAULT (0x3)
++#define PCU_PCS8_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS8_PARA_NXTPAR_OFFSET (0)
++#define PCU_PCS8_PARA_NXTPAR_DEFAULT (0x0)
++#define PCU_PCS8_PARA_STOP_MASK (ANDES_BIT_MASK(13, 13))
++#define PCU_PCS8_PARA_STOP_OFFSET (13)
++#define PCU_PCS8_PARA_STOP_DEFAULT (0x0)
++#define PCU_PCS8_PARA_START_MASK (ANDES_BIT_MASK(12, 12))
++#define PCU_PCS8_PARA_START_OFFSET (12)
++#define PCU_PCS8_PARA_START_DEFAULT (0x0)
++#define PCU_PCS8_PARA_BYTES_MASK (ANDES_BIT_MASK(10, 8))
++#define PCU_PCS8_PARA_BYTES_OFFSET (8)
++#define PCU_PCS8_PARA_BYTES_DEFAULT (0x0)
++#define PCU_PCS8_PARA_ADDR_MASK (ANDES_BIT_MASK(7, 1))
++#define PCU_PCS8_PARA_ADDR_OFFSET (1)
++#define PCU_PCS8_PARA_ADDR_DEFAULT (0x0)
++#define PCU_PCS8_PARA_READ_MASK (ANDES_BIT_MASK(0, 0))
++#define PCU_PCS8_PARA_READ_OFFSET (0)
++#define PCU_PCS8_PARA_READ_DEFAULT (0x0)
++#define PCU_PCS8_PARA_DEFAULT ((PCU_PCS8_PARA_IE_DEFAULT << PCU_PCS8_PARA_IE_OFFSET )|\
++ (PCU_PCS8_PARA_CMD_DEFAULT << PCU_PCS8_PARA_CMD_OFFSET )|\
++ (PCU_PCS8_PARA_SYNC_DEFAULT << PCU_PCS8_PARA_SYNC_OFFSET )|\
++ (PCU_PCS8_PARA_NXTPAR_DEFAULT << PCU_PCS8_PARA_NXTPAR_OFFSET))
++
++
++#define PCU_PCS8_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS8_ST1_STS_OFFSET (28)
++#define PCU_PCS8_ST1_STS_DEFAULT (0x0)
++#define PCU_PCS8_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PCS8_ST1_ERR_OFFSET (0)
++#define PCU_PCS8_ST1_ERR_DEFAULT (0x0)
++#define PCU_PCS8_ST1_DEFAULT ((PCU_PCS8_ST1_STS_DEFAULT << PCU_PCS8_ST1_STS_OFFSET )|\
++ (PCU_PCS8_ST1_ERR_DEFAULT << PCU_PCS8_ST1_ERR_OFFSET ))
++
++#define PCU_PCS8_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS8_ST2_SYNC_OFFSET (24)
++#define PCU_PCS8_ST2_SYNC_DEFAULT (0x0)
++#define PCU_PCS8_ST2_CURPAR_MASK PCU_PCS8_PARA_NXTPAR_MASK
++#define PCU_PCS8_ST2_CURPAR_OFFSET PCU_PCS8_PARA_NXTPAR_OFFSET
++#define PCU_PCS8_ST2_CURPAR_DEFAULT PCU_PCS8_PARA_NXTPAR_DEFAULT
++#define PCU_PCS8_ST2_DEFAULT ((PCU_PCS8_ST2_SYNC_DEFAULT << PCU_PCS8_ST2_SYNC_OFFSET )|\
++ (PCU_PCS8_ST2_CURPAR_DEFAULT << PCU_PCS8_ST2_CURPAR_OFFSET))
++
++
++#define PCU_PCS8_PDD_4TH_BYTE_MASK (ANDES_BIT_MASK(31, 24))
++#define PCU_PCS8_PDD_4TH_BYTE_OFFSET (24)
++#define PCU_PCS8_PDD_4TH_BYTE_DEFAULT (0x0)
++#define PCU_PCS8_PDD_3RD_BYTE_MASK (ANDES_BIT_MASK(23, 16))
++#define PCU_PCS8_PDD_3RD_BYTE_OFFSET (16)
++#define PCU_PCS8_PDD_3RD_BYTE_DEFAULT (0x0)
++#define PCU_PCS8_PDD_2ND_BYTE_MASK (ANDES_BIT_MASK(15, 8))
++#define PCU_PCS8_PDD_2ND_BYTE_OFFSET (8)
++#define PCU_PCS8_PDD_2ND_BYTE_DEFAULT (0x0)
++#define PCU_PCS8_PDD_1ST_BYTE_MASK (ANDES_BIT_MASK(7, 0))
++#define PCU_PCS8_PDD_1ST_BYTE_OFFSET (0)
++#define PCU_PCS8_PDD_1ST_BYTE_DEFAULT (0x0)
++#define PCU_PCS8_PDD_DEFAULT ((PCU_PCS8_PDD_4TH_BYTE_DEFAULT << PCU_PCS8_PDD_4TH_BYTE_OFFSET)|\
++ (PCU_PCS8_PDD_3RD_BYTE_DEFAULT << PCU_PCS8_PDD_3RD_BYTE_OFFSET)|\
++ (PCU_PCS8_PDD_2ND_BYTE_DEFAULT << PCU_PCS8_PDD_2ND_BYTE_OFFSET)|\
++ (PCU_PCS8_PDD_1ST_BYTE_DEFAULT << PCU_PCS8_PDD_1ST_BYTE_OFFSET))
++
++// bits field for PCS9 registers
++#define PCU_PCS9_CFG_TYPE_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS9_CFG_TYPE_OFFSET (28)
++#define PCU_PCS9_CFG_TYPE_DEFAULT (0x6)
++#define PCU_PCS9_CFG_WR_MASK (ANDES_BIT_MASK(27, 27))
++#define PCU_PCS9_CFG_WR_OFFSET (27)
++#define PCU_PCS9_CFG_WR_DEFAULT (0x0)
++#define PCU_PCS9_CFG_SR_MASK (ANDES_BIT_MASK(26, 26))
++#define PCU_PCS9_CFG_SR_OFFSET (0)
++#define PCU_PCS9_CFG_SR_DEFAULT (0x0)
++#define PCU_PCS9_CFG_LS_MASK (ANDES_BIT_MASK(23, 20))
++#define PCU_PCS9_CFG_LS_OFFSET (20)
++#define PCU_PCS9_CFG_LS_DEFAULT (0x0)
++#define PCU_PCS9_CFG_LW_MASK (ANDES_BIT_MASK(19, 16))
++#define PCU_PCS9_CFG_LW_OFFSET (16)
++#define PCU_PCS9_CFG_LW_DEFAULT (0x0)
++#define PCU_PCS9_CFG_WKEN_MASK (ANDES_BIT_MASK(15, 0))
++#define PCU_PCS9_CFG_WKEN_OFFSET (0)
++#define PCU_PCS9_CFG_WKEN_DEFAULT (0x0)
++#define PCU_PCS9_CFG_DEFAULT ((PCU_PCS9_CFG_TYPE_DEFAULT << PCU_PCS9_CFG_TYPE_OFFSET)|\
++ (PCU_PCS9_CFG_WR_DEFAULT << PCU_PCS9_CFG_WR_OFFSET )|\
++ (PCU_PCS9_CFG_SR_DEFAULT << PCU_PCS9_CFG_SR_OFFSET )|\
++ (PCU_PCS9_CFG_LS_DEFAULT << PCU_PCS9_CFG_LS_OFFSET )|\
++ (PCU_PCS9_CFG_LW_DEFAULT << PCU_PCS9_CFG_LW_OFFSET )|\
++ (PCU_PCS9_CFG_WKEN_DEFAULT << PCU_PCS9_CFG_WKEN_OFFSET))
++
++#define PCU_PCS9_PARA_IE_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_PCS9_PARA_IE_OFFSET (31)
++#define PCU_PCS9_PARA_IE_DEFAULT (0x0)
++#define PCU_PCS9_PARA_CMD_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS9_PARA_CMD_OFFSET (28)
++#define PCU_PCS9_PARA_CMD_DEFAULT (0x0)
++#define PCU_PCS9_PARA_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS9_PARA_SYNC_OFFSET (24)
++#define PCU_PCS9_PARA_SYNC_DEFAULT (0x3)
++#define PCU_PCS9_PARA_NXTPAR_MASK (ANDES_BIT_MASK(23, 0))
++#define PCU_PCS9_PARA_NXTPAR_OFFSET (0)
++#define PCU_PCS9_PARA_NXTPAR_DEFAULT (0x0)
++#define PCU_PCS9_PARA_TEST_MASK (PCS_POWER_GPU_AND_DAC |\
++ PCS_POWER_CPUB )
++
++#define PCU_PCS9_PARA_TEST PCU_PCS9_PARA_TEST_MASK
++
++#define PCU_PCS9_PARA_DEFAULT ((PCU_PCS9_PARA_IE_DEFAULT << PCU_PCS9_PARA_IE_OFFSET )|\
++ (PCU_PCS9_PARA_CMD_DEFAULT << PCU_PCS9_PARA_CMD_OFFSET )|\
++ (PCU_PCS9_PARA_SYNC_DEFAULT << PCU_PCS9_PARA_SYNC_OFFSET )|\
++ (PCU_PCS9_PARA_NXTPAR_DEFAULT << PCU_PCS9_PARA_NXTPAR_OFFSET))
++
++#define PCU_PCS9_ST1_STS_MASK (ANDES_BIT_MASK(30, 28))
++#define PCU_PCS9_ST1_STS_OFFSET (28)
++#define PCU_PCS9_ST1_STS_DEFAULT (0x0)
++#define PCU_PCS9_ST1_ERR_MASK (ANDES_BIT_MASK(3, 0))
++#define PCU_PCS9_ST1_ERR_OFFSET (0)
++#define PCU_PCS9_ST1_ERR_DEFAULT (0x0)
++#define PCU_PCS9_ST1_DEFAULT ((PCU_PCS9_ST1_STS_DEFAULT << PCU_PCS9_ST1_STS_OFFSET )|\
++ (PCU_PCS9_ST1_ERR_DEFAULT << PCU_PCS9_ST1_ERR_OFFSET ))
++
++#define PCU_PCS9_ST2_SYNC_MASK (ANDES_BIT_MASK(27, 24))
++#define PCU_PCS9_ST2_SYNC_OFFSET (24)
++#define PCU_PCS9_ST2_SYNC_DEFAULT (0x0)
++#define PCU_PCS9_ST2_CURPAR_MASK PCU_PCS9_PARA_NXTPAR_MASK
++#define PCU_PCS9_ST2_CURPAR_OFFSET PCU_PCS9_PARA_NXTPAR_OFFSET
++#define PCU_PCS9_ST2_CURPAR_DEFAULT (0x1f)
++#define PCU_PCS9_ST2_DEFAULT ((PCU_PCS9_ST2_SYNC_DEFAULT << PCU_PCS9_ST2_SYNC_OFFSET )|\
++ (PCU_PCS9_ST2_CURPAR_DEFAULT << PCU_PCS9_ST2_CURPAR_OFFSET))
++
++#define PCU_PCS9_PDD_CLR_PWOFF_FLAG_MASK (ANDES_BIT_MASK(31, 31))
++#define PCU_PCS9_PDD_CLR_PWOFF_FLAG_OFFSET (31)
++#define PCU_PCS9_PDD_CLR_PWOFF_FLAG_DEFAULT (0x0)
++#define PCU_PCS9_PDD_SUSP2RAM_MASK (ANDES_BIT_MASK(30, 30))
++#define PCU_PCS9_PDD_SUSP2RAM_OFFSET (30)
++#define PCU_PCS9_PDD_SUSP2RAM_DEFAULT (0x0)
++#define PCU_PCS9_PDD_PWR_OFF_TIME_MASK (ANDES_BIT_MASK(29, 28))
++#define PCU_PCS9_PDD_PWR_OFF_TIME_OFFSET (28)
++#define PCU_PCS9_PDD_PWR_OFF_TIME_DEFAULT (0x3)
++#define PCU_PCS9_PDD_TICK_MASK (ANDES_BIT_MASK(24, 24))
++#define PCU_PCS9_PDD_TICK_OFFSET (24)
++#define PCU_PCS9_PDD_TICK_DEFAULT (0x1)
++#define PCU_PCS9_PDD_TIMER4_MASK (ANDES_BIT_MASK(23, 18))
++#define PCU_PCS9_PDD_TIMER4_OFFSET (18)
++#define PCU_PCS9_PDD_TIMER4_DEFAULT (0x20)
++#define PCU_PCS9_PDD_TIMER3_MASK (ANDES_BIT_MASK(17, 12))
++#define PCU_PCS9_PDD_TIMER3_OFFSET (12)
++#define PCU_PCS9_PDD_TIMER3_DEFAULT (0x20)
++#define PCU_PCS9_PDD_TIMER2_MASK (ANDES_BIT_MASK(11, 6))
++#define PCU_PCS9_PDD_TIMER2_OFFSET (6)
++#define PCU_PCS9_PDD_TIMER2_DEFAULT (0x20)
++#define PCU_PCS9_PDD_TIMER1_MASK (ANDES_BIT_MASK(5, 0))
++#define PCU_PCS9_PDD_TIMER1_OFFSET (0)
++#define PCU_PCS9_PDD_TIMER1_DEFAULT (0x20)
++
++#define PCU_PCS9_PDD_DEFAULT ((PCU_PCS9_PDD_CLR_PWOFF_FLAG_DEFAULT << PCU_PCS9_PDD_CLR_PWOFF_FLAG_OFFSET)|\
++ (PCU_PCS9_PDD_SUSP2RAM_DEFAULT << PCU_PCS9_PDD_SUSP2RAM_OFFSET )|\
++ (PCU_PCS9_PDD_PWR_OFF_TIME_DEFAULT << PCU_PCS9_PDD_PWR_OFF_TIME_OFFSET )|\
++ (PCU_PCS9_PDD_TICK_DEFAULT << PCU_PCS9_PDD_TICK_OFFSET )|\
++ (PCU_PCS9_PDD_TIMER4_DEFAULT << PCU_PCS9_PDD_TIMER4_OFFSET )|\
++ (PCU_PCS9_PDD_TIMER3_DEFAULT << PCU_PCS9_PDD_TIMER3_OFFSET )|\
++ (PCU_PCS9_PDD_TIMER2_DEFAULT << PCU_PCS9_PDD_TIMER2_OFFSET )|\
++ (PCU_PCS9_PDD_TIMER1_DEFAULT << PCU_PCS9_PDD_TIMER1_OFFSET ))
++
++// ======================================================
++// PCU definitaion macro
++// ======================================================
++#define PCS_TYPE_PLL 0
++#define PCS_TYPE_DIVIDER 1
++#define PCS_TYPE_CLK_GATING 2
++#define PCS_TYPE_I2C 4
++#define PCS_TYPE_PMBUS 5
++
++#define PCS_WKEN0 (0x1<<0)
++#define PCS_WKEN1 (0x1<<1)
++#define PCS_WKEN2 (0x1<<2)
++#define PCS_WKEN3 (0x1<<3)
++#define PCS_WKEN4 (0x1<<4)
++#define PCS_WKEN5 (0x1<<5)
++#define PCS_WKEN6 (0x1<<6)
++#define PCS_WKEN7 (0x1<<7)
++#define PCS_WKEN8 (0x1<<8)
++#define PCS_WKEN9 (0x1<<9)
++#define PCS_WKEN10 (0x1<<10)
++#define PCS_WKEN11 (0x1<<11)
++#define PCS_WKEN12 (0x1<<12)
++#define PCS_WKEN13 (0x1<<13)
++#define PCS_WKEN14 (0x1<<14)
++#define PCS_WKEN15 (0x1<<15)
++
++#define PCS_WKEN_GPIO0 PCS_WKEN0
++#define PCS_WKEN_GPIO1 PCS_WKEN1
++#define PCS_WKEN_GPIO2 PCS_WKEN2
++#define PCS_WKEN_GPIO3 PCS_WKEN3
++#define PCS_WKEN_GPIO4 PCS_WKEN4
++#define PCS_WKEN_GPIO5 PCS_WKEN5
++#define PCS_WKEN_WOL PCS_WKEN6
++#define PCS_WKEN_RTC PCS_WKEN7
++#define PCS_WKEN_DAY PCS_WKEN8
++#define PCS_WKEN_DBG PCS_WKEN9
++#define PCS_WKEN_PCI PCS_WKEN10
++#define PCS_WKEN_LPC PCS_WKEN11
++#define PCS_WKEN_SRC_CNT 12 // wakeup source number
++#define PCS_WKEN_SRC_MASK ((1<<PCS_WKEN_SRC_CNT)-1)
++
++#define PCS_CMD_NOP 0x0
++#define PCS_CMD_SCALING 0x1
++#define PCS_CMD_PW_DOWN 0x2
++#define PCS_CMD_DRAM_SF 0x4 // DRAM self-refresh
++
++#define PCS_SYNC_CPUA_STBY 0x1
++#define PCS_SYNC_CPUB_STBY 0x2
++
++#if ((!defined(CORE0_IDLE)) && (!defined(CORE1_IDLE)))
++ #define PCS_SYNC_SRC PCS_SYNC_CPUA_STBY
++#elif (!defined(CORE0_IDLE))
++ #define PCS_SYNC_SRC PCS_SYNC_CPUA_STBY
++#else //(!defined(CORE1_IDLE))
++ #define PCS_SYNC_SRC PCS_SYNC_CPUB_STBY
++#endif
++
++#define PCS_PLL_DIVIDE1 0
++#define PCS_PLL_DIVIDE2 1
++#define PCS_PLL_DIVIDE4 2
++#define PCS_PLL_DIVIDE8 3
++
++#define PCS_RATIO_44221H 0 // h(alf): stands for 0.5,
++#define PCS_RATIO_4422HQ 1 // q(uarter) stands for 0.25,
++#define PCS_RATIO_42221H 2 // f(ixed) stands for fixed 400Mhz
++#define PCS_RATIO_4222HQ 3
++#define PCS_RATIO_41121H 4
++#define PCS_RATIO_4112HQ 5
++#define PCS_RATIO_44421H 6
++#define PCS_RATIO_4442HQ 7
++#define PCS_RATIO_442F1H 8
++#define PCS_RATIO_442FHQ 9
++#define PCS_RATIO_422F1H 10
++#define PCS_RATIO_422FHQ 11
++#define PCS_RATIO_411F1H 12
++#define PCS_RATIO_411FHQ 13
++#define PCS_RATIO_111111e 14 // enable pll
++#define PCS_RATIO_111111d 15 // disable pll
++#define PCS_RATIO_MAX PCS_RATIO_111111d
++#define PCS_RATIO_CNT (PCS_RATIO_MAX+1)
++
++#define PCS_GATING_DDR2_HCLK (0x1<<2 )
++#define PCS_GATING_AHB2AHB_HCLK (0x1<<3 )
++#define PCS_GATING_DMAC_HCLK (0x1<<4 )
++#define PCS_GATING_L2CC_HCLK (0x1<<5 )
++#define PCS_GATING_LPC_HCLK (0x1<<6 )
++#define PCS_GATING_I2C_HCLK (0x1<<7 )
++#define PCS_GATING_IDE_HCLK (0x1<<8 )
++#define PCS_GATING_GPU_HCLK (0x1<<9)
++#define PCS_GATING_GMAC_HCLK (0x1<<10)
++#define PCS_GATING_USB_HCLK (0x1<<11)
++#define PCS_GATING_PCI_HCLK (0x1<<12)
++#define PCS_GATING_HCLK_CNT (16)
++#define PCS_GATING_HCLK_VALID (PCS_GATING_DDR2_HCLK |\
++ PCS_GATING_AHB2AHB_HCLK|\
++ PCS_GATING_DMAC_HCLK |\
++ PCS_GATING_L2CC_HCLK |\
++ PCS_GATING_LPC_HCLK |\
++ PCS_GATING_I2C_HCLK |\
++ PCS_GATING_IDE_HCLK |\
++ PCS_GATING_GPU_HCLK |\
++ PCS_GATING_GMAC_HCLK |\
++ PCS_GATING_USB_HCLK |\
++ PCS_GATING_PCI_HCLK )
++
++#define PCS_GATING_NO_PCLK (0x0)
++#define PCS_GATING_SPI_PCLK (0x1<<0 )
++#define PCS_GATING_CFC_PCLK (0x1<<1 )
++#define PCS_GATING_SDC_PCLK (0x1<<2 )
++#define PCS_GATING_WDT_PCLK (0x1<<3 )
++#define PCS_GATING_TMR_PCLK (0x1<<4 )
++#define PCS_GATING_GPIO_PCLK (0x1<<5 )
++#define PCS_GATING_PWM_PCLK (0x1<<6 )
++#define PCS_GATING_I2C_PCLK (0x1<<7 )
++#define PCS_GATING_AC97I2S_PCLK (0x1<<8)
++#define PCS_GATING_UART1_PCLK (0x1<<9)
++#define PCS_GATING_UART2_PCLK (0x1<<10)
++#define PCS_GATING_PCLK_CNT (16)
++
++#define PCS_MAIN_PLL_FREF (33) // reference frequency in MHz
++#define PCS_MAIN_PLL_M_FACTOR (1) // fixed M factor of Main PLL
++#define PCS_MAIN_PLL_50MHZ_H (66)
++#define PCS_MAIN_PLL_125MHZ_L (99)
++#define PCS_MAIN_PLL_125MHZ_H (132)
++#define PCS_MAIN_PLL_250MHZ_L (231)
++#define PCS_MAIN_PLL_250MHZ_H (264)
++#define PCS_MAIN_PLL_500MHZ_L (495)
++#define PCS_MAIN_PLL_500MHZ_H (528)
++#define PCS_MAIN_PLL_830MHZ_L (825)
++//#define PCS_MAIN_PLL_800MHZ_H ()
++//#define PCS_MAIN_PLL_1000MHZ_L ()
++//#define PCS_MAIN_PLL_1000MHZ_H ()
++#define PCS_MAIN_PLL_CNT (4)
++#define PCS_PLL_50to125MHZ (0x0)
++#define PCS_PLL_125to250MHZ (0x1)
++#define PCS_PLL_250to500MHZ (0x2)
++#define PCS_PLL_500to1000MHZ (0x3)
++
++#define PCU_PLL_N_FACTOR(seed, F_ref, M_factor, F_low, F_high) \
++ (((seed)%( 1+ (F_high)*(M_factor)/(F_ref) - (F_low)*(M_factor)/(F_ref))) + ((F_low)*(M_factor)/(F_ref)))
++#define PCS_MAIN_PLL_N_FACTOR(seed, F_low, F_high) \
++ PCU_PLL_N_FACTOR(seed, PCS_MAIN_PLL_FREF, PCS_MAIN_PLL_M_FACTOR, F_low, F_high)
++#define PCS_MAIN_PLL_CLOCK(n_factor) ((n_factor/PCS_MAIN_PLL_M_FACTOR)*PCS_MAIN_PLL_FREF)
++
++#define PCS_POWER_GPU_AND_DAC (0x1<<1)
++#define PCS_POWER_CPUB (0x1<<2)
++#define PCS_POWER_CNT (5)
++
++#define PCS_TICK_OSCH 0x0
++#define PCS_TICK_OSCL 0x1
++
++//
++#define PCS_STS_NORMAL 0x0
++#define PCS_STS_READY 0x1
++#define PCS_STS_SEQUENCE 0x2
++#define PCS_STS_DONE 0x4
++#define PCS_STS_WAKEN 0x6
++
++#define PCS_ERR_NONE 0x0
++#define PCS_ERR_ILLEGAL 0x1
++#define PCS_ERR_SYNC_TIMEOUT 0x2
++#define PCS_ERR_UPDATE_TIMEOUT 0x3
++
++//
++#define PCS_BSM_IDLE 0x0
++#define PCS_BSM_SCALING 0x1
++#define PCS_BSM_DONE 0x3
++#define PCS_BSM_PWDN 0x4
++#define PCS_BSM_ERROR 0x7
++#define PCS_BSM_WAKEN 0x8
++
++#define PCS_BSM_VALID_NO_MAX 9
++
++//
++#define PCS_SCALING_WITH_WAIT_DOWN 0
++#define PCS_SCALING_WITH_WAKE_GRANT 1
++#define PCS_PW_DOWN_WITH_WAIT_DOWN 2
++#define PCS_PW_DOWN_WAKE_GRANT 3
++
++#define PCS_WAKE_WITH_SCALING_CNT (PCS_SCALING_WITH_WAKE_GRANT+1)
++#define PCS_WAKE_WITH_PWDnSCL_CNT (PCS_PW_DOWN_WAKE_GRANT+1)
++
++// standby mode define macro
++#define PCU_STBY_NO_WAKE_GRANT 0
++#define PCU_STBY_WAKE_GRANT 1
++#define PCU_STBY_WAIT_DONE 2
++
++
++// PCU interrupt service routine signal
++#define PCU_ISR_SIG_NONE 0x0
++#define PCU_ISR_SIG_BSM PCU_INTR_BSM_MASK
++#define PCU_ISR_SIG_PCS1 PCU_INTR_PCS1_MASK
++#define PCU_ISR_SIG_PCS2 PCU_INTR_PCS2_MASK
++#define PCU_ISR_SIG_PCS3 PCU_INTR_PCS3_MASK
++#define PCU_ISR_SIG_PCS4 PCU_INTR_PCS4_MASK
++#define PCU_ISR_SIG_PCS5 PCU_INTR_PCS5_MASK
++#define PCU_ISR_SIG_PCS6 PCU_INTR_PCS6_MASK
++#define PCU_ISR_SIG_PCS7 PCU_INTR_PCS7_MASK
++#define PCU_ISR_SIG_PCS8 PCU_INTR_PCS8_MASK
++#define PCU_ISR_SIG_PCS9 PCU_INTR_PCS9_MASK
++
++// ======================================================
++// PCU access macro
++// ======================================================
++#define PCU_SET_FIELD(reg, field, value) SET_FIELD(PCU_REG_##reg, PCU_##reg##_##field##_##MASK, PCU_##reg##_##field##_##OFFSET, value)
++#define PCU_GET_FIELD(reg, field) GET_FIELD(PCU_REG_##reg, PCU_##reg##_##field##_##MASK, PCU_##reg##_##field##_##OFFSET)
++#define PCU_TEST_FIELD(reg, field) TEST_FIELD(PCU_REG_##reg, PCU_##reg##_##field##_##MASK)
++
++#define PCU_SET_REG(reg, value) SET_REG(PCU_REG_##reg, value)
++#define PCU_GET_REG(reg) GET_REG(PCU_REG_##reg)
++#define PCU_TEST_BIT(reg, field, value) VAR_TEST_BIT(value, PCU_##reg##_##field##_##MASK)
++
++#define PCU_CHECK(reg, field, value) CHECK_FIELD (value, PCU_##reg##_##field##_##MASK)
++#define PCU_EXTRACT(reg, field, value) EXTRACT_FIELD(value, PCU_##reg##_##field##_##MASK, PCU_##reg##_##field##_##OFFSET )
++#define PCU_PREPARE(reg, field, value) PREPARE_FIELD(value, PCU_##reg##_##field##_##MASK, PCU_##reg##_##field##_##OFFSET )
++
++#define PCU_DEFAULT(reg, field) ( PCU_##reg##_##field##_##DEFAULT )
++
++#define PCU_TEST_SIG(var, sig) VAR_TEST_BIT(var, PCU_ISR_SIG_##sig)
++#define PCU_SET_SIG(var, sig) VAR_SET_BIT(var, PCU_ISR_SIG_##sig)
++#define PCU_CLR_SIG(var, sig) VAR_CLR_BIT(var, PCU_ISR_SIG_##sig)
++
++// ======================================================
++// PCU access function prototype
++// ======================================================
++#if __STDC__ || defined(__cplusplus)
++#define PROTO_PARAMS(s) s
++#else
++#define PROTO_PARAMS(s) ()
++#endif
++
++#endif //__PCU_H
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/pm.c linux-3.4.110/arch/nds32/platforms/ag102/pm.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ag102/pm.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag102/pm.c 2016-04-07 10:20:51.002083345 +0200
+@@ -0,0 +1,1614 @@
++/*
++ * AG101 Power Management Routines
++ *
++ * Copyright (c) 2010 Gavin Guo <gavinguo@andestech.com>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License.
++ *
++ * Abstract:
++ *
++ * This program is for AG102 power management routines.
++ *
++ * Revision History:
++ *
++ * Jul.19.2010 Initial code by Gavin.
++ */
++#include <linux/init.h>
++#include <linux/suspend.h>
++#include <linux/errno.h>
++#include <linux/time.h>
++#include <linux/delay.h>
++/*
++ * the following include file is for testing device node
++ */
++#include <linux/device.h>
++#include <linux/fs.h>
++#include <asm/uaccess.h>
++/*************************/
++#include <asm/hardware.h>
++#include <asm/memory.h>
++#include <asm/system.h>
++#include <asm/mach/time.h>
++#include <asm/cacheflush.h>
++#include <asm/timer.h>
++#include <asm/io.h>
++#include <asm/amic.h>
++
++#include "pcu.h"
++#include "gmac.h"
++
++#ifdef CONFIG_PLAT_AG102
++#include <asm/spec-ag102.h>
++#endif
++
++#define ANDES_PCU_STRING "andes_pcu"
++static int andes_pcu_major;
++static struct class *andes_pcu_class;
++extern void ag102_cpu_sleep(void);
++extern void ag102_cpu_resume(void);
++extern void ag102_cpu_resume2(void);
++extern void __SELF_REFRESH_LOCK_START();
++extern void __SELF_REFRESH_LOCK_END();
++extern void ftpci_postinit(void /**sysdata*/ );
++UINT32 mac_dah, mac_dal;
++
++// ADD by river 2010.12.07 for WOL
++
++UINT32 eth_phy_reg_read(UINT32 phy_addr, UINT32 phy_page, UINT32 phy_reg,
++ UINT32 * phy_data)
++{
++ UINT32 cycthr = GMAC_GET_FIELD(PHYCR, MDC_CYCTHR);
++ UINT32 wdata;
++ UINT32 rdata;
++ //TIMER_P timer;
++
++ printk(">>>>> GMAC : Calling eth_phy_reg_read()...\n");
++
++ wdata = GMAC_PREPARE(PHYCR, MIIRD, 0x1) |
++ GMAC_PREPARE(PHYCR, PHYAD, phy_addr) |
++ GMAC_PREPARE(PHYCR, REGAD, phy_reg) | cycthr;
++
++ printk(">>>>> GMAC : wdata = [0x%08x]\n", wdata);
++
++ GMAC_SET_REG(PHYCR, wdata);
++
++ // wait phy data read
++ //TIMER_INIT(timer, 10000); // trigger timer & wait until finish of data read
++ //while ( (!TIMER_IS_TIMEOUT(timer)) && (GMAC_GET_FIELD(PHYCR, MIIRD))) {
++ // TIMER_TICK(timer);
++ //}
++
++ while (GMAC_GET_FIELD(PHYCR, MIIRD)) {
++ mdelay(50);
++ }
++
++ if (GMAC_GET_FIELD(PHYCR, MIIRD)) {
++ printk("ERR: GPHY read reg[%x] timeout!\n", phy_reg);
++ return 1;
++ } else {
++ rdata = GMAC_GET_FIELD(PHYDATA, MIIRDATA);
++ *phy_data = rdata;
++ printk("GPHY read [%x] \n", rdata);
++ return 0;
++ }
++}
++
++UINT32 eth_phy_reg_write(UINT32 phy_addr, UINT32 phy_page, UINT32 phy_reg,
++ UINT32 phy_data)
++{
++ UINT32 wdata;
++ //TIMER_P timer;
++
++ printk(">>>>> GMAC : Calling eth_phy_reg_write()...\n");
++
++ GMAC_SET_FIELD(PHYDATA, MIIWDATA, phy_data);
++ wdata = GMAC_PREPARE(PHYCR, MIIWR, 0x1) | GMAC_PREPARE(PHYCR, PHYAD, phy_addr) | GMAC_PREPARE(PHYCR, REGAD, phy_reg) | 0x34; //cycthr;
++ GMAC_SET_REG(PHYCR, wdata);
++
++ // wait phy data write
++ //TIMER_INIT(timer, 10000); // trigger timer & wait until finish of data write
++ //while ( (!TIMER_IS_TIMEOUT(timer)) && (GMAC_GET_FIELD(PHYCR, MIIWR))) {
++ // TIMER_TICK(timer);
++ //}
++
++ while (GMAC_GET_FIELD(PHYCR, MIIWR)) {
++ mdelay(50);
++ }
++
++ if (GMAC_GET_FIELD(PHYCR, MIIWR)) {
++ printk("ERR: GPHY write reg[%x] = %x timeout!\n", phy_reg,
++ phy_data);
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
++INT32 eth_phy_detect(UINT32 * phy_addr, UINT32 * phy_id)
++{
++ UINT32 i, find, data1, data2;
++
++ printk(">>>>> GMAC : Calling eth_phy_detect()...\n");
++
++ for (i = 0, find = 0; i <= 0x1f; i++) {
++ eth_phy_reg_read(i, 0, 2, &data1);
++ if ((data1 != 0) && (data1 != 0xffff)) {
++ find = 1;
++ break;
++ }
++ }
++
++ if (find == 0) {
++ printk("Err: no valid phy found!\n");
++ *phy_id = 0;
++ return (-1);
++ }
++
++ eth_phy_reg_read(i, 0, 2, &data1);
++ eth_phy_reg_read(i, 0, 3, &data2);
++ *phy_id = (data1 << 16) | (data2 & 0xffff);
++ *phy_addr = i;
++ printk("Info: phy id = 0x%08x!\n", *phy_id);
++ return 0;
++}
++
++void eth_phy_init(UINT32 phy_addr)
++{
++ UINT32 data, i;
++ //TIMER_P timer;
++ //phy_addr = DVC_PHY_ADDR;
++
++ printk(">>>>> GMAC : Calling eth_phy_init()...\n");
++ // GPHY SW reset
++ eth_phy_reg_read(phy_addr, 0, DVC_PHY_REG_CTL, &data);
++ data |=
++ DVC_PHY_REG_CTL_SW_RST | DVC_PHY_REG_CTL_AN_EN |
++ DVC_PHY_REG_CTL_AN_RST;
++ eth_phy_reg_write(phy_addr, 0, DVC_PHY_REG_CTL, data);
++ for (i = 0; i < 10000; i++) { // must delay enough for phy to get ready
++ //eth_mdelay(2000);
++ mdelay(2);
++ eth_phy_reg_read(phy_addr, 0, DVC_PHY_REG_CTL, &data);
++ if ((data & 0x8000) == 0)
++ break;
++ }
++ if ((data & 0x8000) != 0) {
++ printk("Err: phy sw reset timeout!!!\n");
++ }
++ eth_phy_reg_read(phy_addr, 0, DVC_PHY_REG_CTL, &data);
++ printk("phy control = 0x%x\n", data);
++ eth_phy_reg_read(phy_addr, 0, DVC_PHY_REG_STS, &data);
++ printk("phy status = 0x%x\n", data);
++
++ return;
++}
++
++// initialize MAC setting
++void eth_mac_init(ETH_PHY_STAT * phy_stat)
++{
++ UINT32 i, wdata, rdata;
++ UINT32 duplex, speed, gmac;
++ //UINT32 mac_dah, mac_dal;
++ printk(">>>>> GMAC : Calling eth_mac_init()...\n");
++
++ wdata = GMAC_PREPARE(MACCR, SW_RST, 0x1);
++ GMAC_SET_REG(MACCR, wdata);
++ for (i = 0; i < 1000; i++) { // must delay enough for phy to get ready
++ //eth_mdelay(8000); // delay should be enough
++ mdelay(8);
++ rdata = GMAC_GET_REG(FEAR);
++ if ((rdata >> 31) == 0)
++ break;
++ }
++ if ((rdata >> 31) != 0) {
++ printk("Err: mac sw reset timeout!!!\n");
++ }
++ if (phy_stat->speed == 2) { //giga
++ gmac = 0x1;
++ speed = 0x1;
++ } else if (phy_stat->speed == 1) { //100 Mbps
++ gmac = 0x0;
++ speed = 0x1;
++ } else { //10 Mbps
++ gmac = 0x0;
++ speed = 0x0;
++ }
++ duplex = phy_stat->duplex;
++ GMAC_SET_REG(ISR, 0xffff); // Interrupt Status, write 1 to clear
++ GMAC_SET_REG(IME, 0xffff); // Interrupt Enable, enabling all interrupts
++ GMAC_SET_REG(MAC_MADR, mac_dah);
++ GMAC_SET_REG(MAC_LADR, mac_dal);
++ rdata = GMAC_GET_REG(FEAR);
++ GMAC_SET_FIELD(TPAFCR, TFIFO_SIZE,
++ GMAC_EXTRACT(FEAR, TFIFO_RSIZE, rdata));
++ GMAC_SET_FIELD(TPAFCR, RFIFO_SIZE,
++ GMAC_EXTRACT(FEAR, RFIFO_RSIZE, rdata));
++
++ wdata = GMAC_PREPARE(MACCR, RX_MULTIPKT_EN, 0x1) |
++ GMAC_PREPARE(MACCR, BROADPKT_EN, 0x1) |
++ GMAC_PREPARE(MACCR, RX_ALLADR, 0x1) |
++ GMAC_PREPARE(MACCR, CRC_APD, 0x1) |
++ GMAC_PREPARE(MACCR, FULLDUP, duplex) |
++ GMAC_PREPARE(MACCR, RX_RUNT, 0x1) |
++ GMAC_PREPARE(MACCR, SPEED, speed) |
++ GMAC_PREPARE(MACCR, GMAC_MODE, gmac) |
++ GMAC_PREPARE(MACCR, RXMAC_EN, 0x1) |
++ GMAC_PREPARE(MACCR, TXMAC_EN, 0x1) |
++ GMAC_PREPARE(MACCR, RXDMA_EN, 0x1) |
++ GMAC_PREPARE(MACCR, TXDMA_EN, 0x1);
++ GMAC_SET_REG(MACCR, wdata);
++
++#ifdef AHBC_NO_REMAP
++ GMAC_SET_REG(NPTXR_BADR, FTGMAC100_TXR_BASE | 0x40000000);
++ GMAC_SET_REG(RXR_BADR, FTGMAC100_RXR_BASE | 0x40000000);
++#else
++ GMAC_SET_REG(NPTXR_BADR, FTGMAC100_TXR_BASE);
++ GMAC_SET_REG(RXR_BADR, FTGMAC100_RXR_BASE);
++#endif
++ return;
++}
++
++UINT32 eth_phy_stat(UINT32 phy_addr, ETH_PHY_STAT * phy_stat)
++{
++
++ phy_stat->speed = 0x1;
++ phy_stat->duplex = 0x1;
++
++ return 0;
++}
++
++void gmac_set_wol()
++{
++ UINT32 wdata;
++
++ // Set Rx Wake-up Frame
++ // write 1 clear register before enable power saving mode
++ GMAC_SET_REG(WOLSR, 0xffffffff); // clear wol status
++
++ // set wakeup_sel and power saving mode enable
++ wdata = GMAC_PREPARE(WOLCR, MAGICPKT_EN, 0x1) |
++ GMAC_PREPARE(WOLCR, PWRSAV, 0x1);
++
++ GMAC_SET_REG(WOLCR, wdata);
++
++ return;
++}
++
++// End ADD by river 2010.12.07 for WOL
++
++//////////////////////////////// LPC wake up ///////////////////////////////////////////////////
++#define CPE_LPCIO_BASE LPC_IO_VA_BASE //VA Base
++#define CPE_LPCREG_BASE LPC_REG_VA_BASE //VA Base
++#define CPE_IC_BASE AMIC_VA_BASE
++
++#define ITE_ADDR 0x2e
++#define ITE_DATA 0x2f
++
++#define KBC_CMD 0x64
++#define KBC_STATUS KBC_CMD
++#define KBC_DATA 0x60
++
++#define BIT_OBF 0x01
++#define BIT_IBF 0x02
++
++#define LPC_REG_SCR 0x10
++#define LPC_REG_SIR 0x14
++#define LPC_REG_SIMR 0x18
++
++#define SIRQ_KB 1
++#define SIRQ_MS 12
++
++//#define outlpc(addr, data) outb(data, CPE_LPCIO_BASE + 4 * addr)
++//#define inlpc(addr) inb(CPE_LPCIO_BASE + 4 * addr)
++#define inlpc(addr) REG32(CPE_LPCIO_BASE + 4 * addr)
++
++#define IRQ_LPC 29
++#define LEVEL 0
++#define H_ACTIVE 0
++#define L_ACTIVE 1
++#define IRQ_MASK 0x80
++#define IRQ_MODE 0x20
++#define IRQ_LEVEL 0x24
++
++UINT32 IRQSources = 0; //define the current irq source for debug
++
++static inline void outlpc(unsigned long addr, unsigned long data)
++{
++ REG32(CPE_LPCIO_BASE + 4 * addr) = data;
++}
++
++static void kbc_cmd(UINT8 cmd)
++{
++ int loop_limit = 1000;
++ int i;
++ UINT8 tmpc;
++
++ // wait until the input buffer is empty
++ for (i = 0; i < loop_limit; i++) {
++ tmpc = inlpc(KBC_STATUS);
++ if ((tmpc & BIT_IBF) == 0)
++ break;
++ }
++
++ outlpc(KBC_CMD, cmd);
++}
++
++static void kbc_wdata(UINT8 wdata)
++{
++ int loop_limit = 1000;
++ int i;
++ UINT8 tmpc;
++
++ // wait until the input buffer is empty
++ for (i = 0; i < loop_limit; i++) {
++ tmpc = inlpc(KBC_STATUS);
++ if ((tmpc & BIT_IBF) == 0)
++ break;
++ }
++
++ outlpc(KBC_DATA, wdata);
++}
++
++static UINT8 kbc_rdata(void)
++{
++ int loop_limit = 1000;
++ int i;
++ UINT8 rdata;
++ UINT8 tmpc;
++
++ // wait until the output buffer is not empty
++ for (i = 0; i < loop_limit; i++) {
++ tmpc = inlpc(KBC_STATUS);
++ if (tmpc & BIT_OBF)
++ break;
++ }
++
++ rdata = inlpc(KBC_DATA);
++ return (rdata);
++}
++
++static void delay_loop(int max_no)
++{
++ int i;
++
++ for (i = 0; i < max_no; i++) ;
++}
++
++static UINT8 get_response(void)
++{
++ UINT8 tmpc;
++
++ delay_loop(200000);
++ tmpc = kbc_rdata();
++ return (tmpc);
++}
++
++int it8718f_init(void)
++{
++ static int initialized = 0;
++ UINT8 tmpc;
++ unsigned int chip_id;
++
++ if (initialized == 1)
++ return (0);
++
++ // Enter the configuration mode
++ outlpc(ITE_ADDR, 0x87);
++ outlpc(ITE_ADDR, 0x01);
++ outlpc(ITE_ADDR, 0x55);
++ outlpc(ITE_ADDR, 0x55);
++
++ // Check the chip ID
++ printk("Check IT8718F chip ID => ");
++ outlpc(ITE_ADDR, 0x20);
++ tmpc = inlpc(ITE_DATA);
++ chip_id = (tmpc & 0xff) << 8;
++ outlpc(ITE_ADDR, 0x21);
++ tmpc = inlpc(ITE_DATA);
++ chip_id |= tmpc & 0xff;
++
++ if (chip_id != 0x8718) {
++ printk("FAILED with chip ID = 0x%C%C.\n", (chip_id >> 8) & 0xff,
++ chip_id & 0xff);
++ return (1);
++ } else
++ printk("PASSED\n");
++
++ // KBC Self Test
++ printk("KBC self-test => ");
++ kbc_cmd(0xaa);
++ tmpc = kbc_rdata();
++ if (tmpc != 0x55) {
++ printk("FAILED with code = 0x%C\n", tmpc & 0xff);
++ return (2);
++ } else
++ printk("PASSED\n");
++
++ // KBC Interface Test
++ printk("KBC interface test => ");
++ kbc_cmd(0xab);
++ tmpc = kbc_rdata();
++ switch (tmpc) {
++ case 0:
++ printk("PASSED\n");
++ break;
++
++ case 1:
++ printk("FAILED as the clock is stuck low\n");
++ return (3);
++
++ case 2:
++ printk("FAILED as the clock is stuck high\n");
++ return (3);
++
++ case 3:
++ printk("FAILED as the data is stuck low\n");
++ return (3);
++
++ case 4:
++ printk("FAILED as the data is stuck high\n");
++ return (3);
++
++ default:
++ printk("FAILED with unknown error\n");
++ return (3);
++ break;
++ }
++
++ // Read the KBC mode
++ kbc_cmd(0xca);
++ tmpc = kbc_rdata();
++
++ // Set KBC to the PS/2 mode
++ tmpc |= 0x01;
++ kbc_cmd(0xcb);
++ kbc_wdata(tmpc);
++
++ // Enable keyboard
++ kbc_wdata(0xf4);
++ tmpc = get_response();
++ printk("@@@@@ : Response of enabling keyboard = 0x%x\n", tmpc & 0xff);
++
++ // Enable mouse
++ kbc_cmd(0xd4);
++ kbc_wdata(0xf4);
++ tmpc = get_response();
++ //outmsg("Response of enabling mouse = 0x%C\n", tmpc & 0xff);
++
++ // bit 6: translate
++ // bit 5: mouse enable
++ // bit 4: keyboard enable
++ // bit 3: ignore keyboard lock
++ // bit 2: system flag
++ // bit 1: mouse interrupt enable
++ // bit 0: Keyboard interrupt enable
++ kbc_cmd(0x60);
++ kbc_wdata(0x47);
++
++ // Set repeat rate and delay
++ kbc_wdata(0xf3);
++ kbc_wdata(0x00);
++ tmpc = get_response();
++
++ // Set LDN = 5 (Keyboard)
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x05);
++
++ // KBC clock = 8MHz, Key lock enabled, interrupt type can be changed
++ outlpc(ITE_ADDR, 0xf0);
++ outlpc(ITE_DATA, 0x4e);
++
++ // Low-level triggered interrupt
++ outlpc(ITE_ADDR, 0x71);
++ outlpc(ITE_DATA, 0x01);
++
++ // Set LDN = 6 (Mouse)
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x06);
++
++ // Enable mouse
++ outlpc(ITE_ADDR, 0x30);
++ outlpc(ITE_DATA, 0x01);
++
++ // Interrupt type can be changed
++ outlpc(ITE_ADDR, 0xf0);
++ outlpc(ITE_DATA, 0x01);
++
++ // Low-level triggered interrupt
++ outlpc(ITE_ADDR, 0x71);
++ outlpc(ITE_DATA, 0x01);
++
++ // Exit the configuration mode
++ outlpc(ITE_ADDR, 0x02);
++ outlpc(ITE_DATA, 0x02);
++
++ initialized = 1;
++ return (0);
++}
++
++//INT for lpc
++/* Turn the interrupt source on. */
++void UnmaskIRQ(UINT32 IRQ)
++{
++ volatile UINT32 *IRQBase;
++
++ IRQBase = (UINT32 *) CPE_IC_BASE;
++
++ IRQBase[(IRQ_MASK / sizeof(UINT32))] |= (1 << IRQ);
++}
++
++void EnableIRQ()
++{
++
++ __asm__ volatile ("setgie.d\n\t"
++ "isb\n\t"
++ "mfsr $r1, $INT_MASK\n\t"
++ "ori $r1, $r1, #0x3f\n\t"
++ "mtsr $r1, $INT_MASK\n\t"
++ "setgie.e\n\t" "isb\n\t");
++
++}
++
++void SetIRQmode(UINT32 IRQ, UINT32 edge)
++{
++ volatile UINT32 *IRQBase;
++
++ IRQBase = (UINT32 *) CPE_IC_BASE;
++
++ if (edge)
++ IRQBase[(IRQ_MODE / sizeof(UINT32))] |= (1 << IRQ);
++ else
++ IRQBase[(IRQ_MODE / sizeof(UINT32))] &= ~(1 << IRQ);
++}
++
++void SetIRQlevel(UINT32 IRQ, UINT32 low)
++{
++ volatile UINT32 *IRQBase;
++
++ IRQBase = (UINT32 *) CPE_IC_BASE;
++
++ if (low)
++ IRQBase[(IRQ_LEVEL / sizeof(UINT32))] |= (1 << IRQ);
++ else
++ IRQBase[(IRQ_LEVEL / sizeof(UINT32))] &= ~(1 << IRQ);
++}
++
++BOOL SetIntTrig(UINT32 intNum, int intMode, int intLevel)
++{
++ if (intNum >= 32) {
++ printk("ERROR: The interrupt number %d is incorrect\n", intNum);
++ return FALSE;
++ } else {
++ SetIRQmode(intNum, intMode);
++ SetIRQlevel(intNum, intLevel);
++ return TRUE;
++ }
++}
++
++BOOL EnableInt(UINT32 intNum)
++{
++
++ if (intNum >= 32) {
++ printk("ERROR: The interrupt number %d is incorrect\n", intNum);
++ return FALSE;
++ } else {
++ IRQSources |= 1 << intNum;
++ UnmaskIRQ(intNum);
++ EnableIRQ();
++ return TRUE;
++ }
++}
++
++//End INT for lpc
++
++void enable_sirq(void)
++{
++ UINT32 data;
++
++ // Unmask SERIRQs of Keyboard and Mouse
++ data = inw(CPE_LPCREG_BASE + LPC_REG_SIMR);
++ data &= ~((1 << SIRQ_KB) | (1 << SIRQ_MS));
++ outw(CPE_LPCREG_BASE + LPC_REG_SIMR, data);
++
++ // Enable SERIRQ
++ data = inw(CPE_LPCREG_BASE + LPC_REG_SCR);
++ data |= 0x1;
++ outw(CPE_LPCREG_BASE + LPC_REG_SCR, data);
++}
++
++void ite_set_pme()
++{
++
++ UINT8 tmpc;
++ unsigned int chip_id;
++ // Enter the configuration mode
++ outlpc(ITE_ADDR, 0x87);
++ outlpc(ITE_ADDR, 0x01);
++ outlpc(ITE_ADDR, 0x55);
++ outlpc(ITE_ADDR, 0x55);
++
++ // Check the chip ID
++ printk("@@@@@ : Check IT8718F chip ID in get_lpc_value => \n");
++ outlpc(ITE_ADDR, 0x20);
++ tmpc = inlpc(ITE_DATA);
++ chip_id = (tmpc & 0xff) << 8;
++ outlpc(ITE_ADDR, 0x21);
++ tmpc = inlpc(ITE_DATA);
++ chip_id |= tmpc & 0xff;
++
++ printk("@@@@@ : chip_id = 0x%08x\n", chip_id);
++ if (chip_id != 0x8718) {
++ printk("FAILED with chip ID = 0x%C%C.\n", (chip_id >> 8) & 0xff,
++ chip_id & 0xff);
++ return (1);
++ } else
++ printk("@@@@@ : PASSED\n");
++
++ // Set LDN = 5
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x05);
++
++ //Read index 30
++ outlpc(ITE_ADDR, 0x30);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x30] = 0x%x\n", tmpc);
++ //Set index 30 bit0 = 0;
++ outlpc(ITE_ADDR, 0x30);
++ outlpc(ITE_DATA, tmpc & 0xFE);
++
++ // Set LDN = 6
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x06);
++
++ //Read index 30
++ outlpc(ITE_ADDR, 0x30);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x30] = 0x%x\n", tmpc);
++ //Set index 30 bit0 = 0;
++ outlpc(ITE_ADDR, 0x30);
++ outlpc(ITE_DATA, tmpc & 0xFE);
++
++ // Set LDN = 4 for PME
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x04);
++
++ //Read index F0
++ outlpc(ITE_ADDR, 0xF0);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF0] = 0x%x\n", tmpc);
++ //Set index F0 BIT[4:3]=1;
++ outlpc(ITE_ADDR, 0xF0);
++ outlpc(ITE_DATA, tmpc | 0x18);
++
++ //PME output enable
++ //Read index F2
++ outlpc(ITE_ADDR, 0xF2);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF2] = 0x%x\n", tmpc);
++ //Set index F2 bit6=0;
++ outlpc(ITE_ADDR, 0xF2);
++ outlpc(ITE_DATA, tmpc & 0xBF);
++
++ // Exit the configuration mode
++ outlpc(ITE_ADDR, 0x02);
++ outlpc(ITE_DATA, 0x02);
++}
++
++void get_keyboard_status()
++{
++
++ printk("Getting keyboard status....\n");
++
++ UINT8 tmpc;
++ unsigned int chip_id;
++
++ // Enter the configuration mode
++ outlpc(ITE_ADDR, 0x87);
++ outlpc(ITE_ADDR, 0x01);
++ outlpc(ITE_ADDR, 0x55);
++ outlpc(ITE_ADDR, 0x55);
++
++ // Check the chip ID
++ //printk("@@@@@ : Check IT8718F chip ID in get_lpc_value => \n");
++ outlpc(ITE_ADDR, 0x20);
++ tmpc = inlpc(ITE_DATA);
++ chip_id = (tmpc & 0xff) << 8;
++ outlpc(ITE_ADDR, 0x21);
++ tmpc = inlpc(ITE_DATA);
++ chip_id |= tmpc & 0xff;
++
++ //printk("@@@@@ : chip_id = 0x%08x\n", chip_id);
++ if (chip_id != 0x8718) {
++ printk("FAILED with chip ID = 0x%C%C.\n", (chip_id >> 8) & 0xff,
++ chip_id & 0xff);
++ return (1);
++ }
++ // Set LDN = 4 for PME
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x04);
++
++ ///////// Dump configuration register
++ outlpc(ITE_ADDR, 0xf1);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xf1] = 0x%x\n", tmpc);
++
++ ///////// Dump configuration register
++ outlpc(ITE_ADDR, 0xf0);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xf0] = 0x%x\n", tmpc);
++
++}
++
++void get_lpc_value()
++{
++ UINT8 tmpc;
++ unsigned int chip_id;
++
++ // Enter the configuration mode
++ outlpc(ITE_ADDR, 0x87);
++ outlpc(ITE_ADDR, 0x01);
++ outlpc(ITE_ADDR, 0x55);
++ outlpc(ITE_ADDR, 0x55);
++
++ // Check the chip ID
++ printk("@@@@@ : Check IT8718F chip ID in get_lpc_value => \n");
++ outlpc(ITE_ADDR, 0x20);
++ tmpc = inlpc(ITE_DATA);
++ chip_id = (tmpc & 0xff) << 8;
++ outlpc(ITE_ADDR, 0x21);
++ tmpc = inlpc(ITE_DATA);
++ chip_id |= tmpc & 0xff;
++
++ printk("@@@@@ : chip_id = 0x%08x\n", chip_id);
++ if (chip_id != 0x8718) {
++ printk("FAILED with chip ID = 0x%C%C.\n", (chip_id >> 8) & 0xff,
++ chip_id & 0xff);
++ return (1);
++ } else
++ printk("@@@@@ : PASSED\n");
++
++ printk("=================== Get Values ==================\n");
++ //////////// Environment Controller configuration register
++ printk("@@@@@ : Environment Controller configuration register\n");
++ // Set LDN = 4 for PME
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x04);
++
++ printk("@@@@@ : LDN = 4\n");
++
++ ///////// Dump configuration register
++ outlpc(ITE_ADDR, 0x30);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x30] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x60);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x60] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x61);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x61] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x62);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x62] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x63);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x63] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x70);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x70] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xf0);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xf0] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xf1);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xf1] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xf2);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xf2] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xf3);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xf3] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xf4);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xf4] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xf5);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xf5] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xf6);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xf6] = 0x%x\n", tmpc);
++
++ //////////// Keyboard configuration register
++ printk("@@@@@ : Keyboard configuration register\n");
++ // Set LDN = 5
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x05);
++
++ printk("@@@@@ : LDN = 5\n");
++
++ outlpc(ITE_ADDR, 0x30);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x30] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x60);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x60] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x61);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x61] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x62);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x62] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x63);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x63] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x70);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x70] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x71);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x71] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xf0);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xf0] = 0x%x\n", tmpc);
++
++ //////////// GPIO configuration register
++ printk("@@@@@ : GPIO configuration register\n");
++ // Set LDN = 7 for GPIO
++ outlpc(ITE_ADDR, 0x07);
++ outlpc(ITE_DATA, 0x07);
++
++ printk("@@@@@ : LDN = 7\n");
++
++ outlpc(ITE_ADDR, 0x60);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x60] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x62);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x62] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x63);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x63] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x64);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x64] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x65);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x65] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x70);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x70] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x71);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x71] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x72);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x72] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x73);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x73] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0x74);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0x74] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xB0);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xB0] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xB1);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xB1] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xB2);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xB2] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xB3);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xB3] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xB4);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xB4] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xB5);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xB5] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xB8);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xB8] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xBA);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xBA] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xBB);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xBB] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xBC);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xBC] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xBD);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xBD] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xC0);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xC0] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xC1);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xC1] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xC2);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xC2] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xC3);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xC3] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xC4);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xC4] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xC5);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xC5] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xC8);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xC8] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xC9);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xC9] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xCA);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xCA] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xCB);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xCB] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xCC);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xCC] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xCD);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xCD] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xE0);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xE0] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xE1);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xE1] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xE2);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xE2] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xE3);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xE3] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xE4);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xE4] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xE5);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xE5] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xE6);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xE6] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xF0);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF0] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xF1);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF1] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xF2);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF2] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xF3);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF3] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xF4);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF4] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xF5);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF5] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xF6);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF6] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xF7);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF7] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xF8);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF8] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xF9);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xF9] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xFA);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xFA] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xFB);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xFB] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xFC);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xFC] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xFD);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xFD] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xFE);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xFE] = 0x%x\n", tmpc);
++
++ outlpc(ITE_ADDR, 0xFF);
++ tmpc = inlpc(ITE_DATA);
++ printk("[0xFF] = 0x%x\n", tmpc);
++
++ printk("=================== End Get Values ==================\n");
++
++}
++
++/////////////////////////////// End LPC wake up ///////////////////////////////////////////////
++
++/*
++ * AG102 PMU sleep mode handler.
++ */
++void andes_suspend_to_ram()
++{
++ int i, k, l, checksum, checksuma;
++ unsigned int addr, reg;
++ static int irq_saves[3];
++ unsigned int tmp;
++ pgd_t *pgdv;
++ pud_t *pudv;
++ pmd_t *pmdv;
++ pte_t *ptev;
++ unsigned int resume_addr /*, resume_temp */ ;
++ //unsigned int *resume_tempaddr;
++ __asm__ volatile ("mfsr %0, $ir14\n\t":"=&r" (tmp));
++ //printk("\nag102_cpu_resume:0x%x\n", ag102_cpu_resume);
++ //printk( KERN_WARNING "\nag102_cpu_resume2:0x%x\n", ag102_cpu_resume2);
++ pgdv =
++ (pgd_t *) __va((GET_L1_PPTB() & L1_PPTB_mskBASE)) +
++ pgd_index((unsigned int)ag102_cpu_resume);
++ pudv = pud_offset(pgdv, (unsigned int)ag102_cpu_resume);
++ pmdv = pmd_offset(pudv, (unsigned int)ag102_cpu_resume);
++ ptev = pte_offset_map(pmdv, (unsigned int)ag102_cpu_resume);
++ //printk("ag102_cpu_resume pte:0x%x\n", ptev);
++ resume_addr =
++ ((*ptev) & TLB_DATA_mskPPN) | ((unsigned int)ag102_cpu_resume &
++ 0x00000fff);
++ printk("resume_addr using Page Table :0x%08x\n", resume_addr);
++
++ //ADD by river 2010.09.23
++ printk("@@@@@ resume_addr(VA):0x%08x\n", ag102_cpu_resume);
++ printk("@@@@@ resume_addr2(VA):0x%08x\n", ag102_cpu_resume2);
++ printk("@@@@@ resume_addr(PA) using virt_to_phys :0x%08x\n",
++ virt_to_phys(ag102_cpu_resume));
++ printk("@@@@@ resume_addr2(PA):0x%08x\n",
++ virt_to_phys(ag102_cpu_resume2));
++ printk("@@@@@ AHB Controller for ROM :0x%08x\n",
++ REG32(AHB_ATFAHBC020S_0_VA_BASE + 0x10));
++ printk("@@@@@ AHB Controller for RAM :0x%08x\n",
++ REG32(AHB_ATFAHBC020S_0_VA_BASE + 0x18));
++ //End ADD by river 2010.09.23
++
++ /* trigger mode regs */
++ irq_saves[0] = REG32(AMIC_VA_BASE + 0x20);
++ /* trigger level regs */
++ irq_saves[1] = REG32(AMIC_VA_BASE + 0x24);
++ /* interrupt enable regs */
++ irq_saves[2] = REG32(AMIC_VA_BASE + 0x80);
++ /* save SDRAM settings */
++
++ /* set resume return address */
++ //REG32(PCU_VA_BASE + 0x400) = (resume_addr);
++ REG32(PCU_VA_BASE + 0x400) = (resume_addr) | 0x80000000;
++ REG32(PCU_VA_BASE + 0x404) = (u32) ag102_cpu_resume2;
++ REG32(PCU_VA_BASE + 0x410) = GET_L1_PPTB();
++ //ADD by river 2010.12.02 for reserve kernel remap
++ REG32(PCU_VA_BASE + 0x418) = REG32(AHB_ATFAHBC020S_0_VA_BASE + 0x10);
++ REG32(PCU_VA_BASE + 0x41C) = REG32(AHB_ATFAHBC020S_0_VA_BASE + 0x18);
++ //End ADD by river 2010.12.02 for reserve kernel remap
++ printk("L1_PPTB (PA) =0x%08x\n", GET_L1_PPTB());
++ printk("L1_PPTB (VA) in virtual address =0x%08x\n",
++ phys_to_virt(GET_L1_PPTB()));
++
++ //ADD by river 2010.12.07
++ UINT32 phy_id, phy_addr;
++ ETH_PHY_STAT phy_stat;
++
++ if (eth_phy_detect(&phy_addr, &phy_id) != 0) {
++ printk("ERR: fail to detect known PHY!!!\n");
++ return;
++ }
++ //TEST by river 2010.12.10
++ eth_phy_init(phy_addr);
++ eth_phy_stat(phy_addr, &phy_stat);
++ eth_mac_init(&phy_stat);
++ //End TEST by river 2010.12.10
++ gmac_set_wol();
++ //End ADD by river 2010.12.07
++
++ /////////// ADD by river 2010.12.20 for LPC wakeup /////////////////////////////
++ if (it8718f_init() != 0)
++ return;
++
++ //INTC setup
++ SetIntTrig(IRQ_LPC, LEVEL, H_ACTIVE);
++ EnableInt(IRQ_LPC); // including INT_MASK and GIE in Core
++
++ enable_sirq();
++
++ //__asm__ volatile ("1:\n\t");
++ //__asm__ volatile ("b 1b\n\t");
++
++ printk("Calling ite_set_pme() YAYAYA....\n");
++ ite_set_pme();
++
++ printk("Get Value..... YAYAYA....1\n");
++ get_lpc_value();
++
++ /////////// End ADD by river 2010.12.20 for LPC wakeup /////////////////////////////
++
++ //set GPIO[2] as suspend2dram power control pin
++ PCU_SET_FIELD(MFPS1, SUSPEND_GPIO, 0x1);
++ PCU_SET_FIELD(PCS9_PDD, SUSP2RAM, 0x1);
++ //ADD by river 2010.12.07
++ PCU_SET_REG(PCS9_CFG, PCU_PREPARE(PCS9_CFG, WKEN, PCS_WKEN_WOL | PCS_WKEN_LPC | PCS_WKEN_RTC)); // use only gpio0 and wol
++ //PCU_SET_REG(PCS9_CFG, PCU_PREPARE(PCS9_CFG, WKEN, PCS_WKEN_LPC)); // use lpc
++
++ //End ADD by river 2010.12.07
++
++ /* set pwoer status */
++ //int par = PCS_POWER_GPU_AND_DAC|PCS_POWER_CPUB;
++ int reg_tmp = PCU_PREPARE(PCS9_PARA, IE, 0x1) |
++ PCU_PREPARE(PCS9_PARA, CMD,
++ PCS_CMD_PW_DOWN /*PCS_CMD_SCALING|PCS_CMD_DRAM_SF */ ) |
++ PCU_PREPARE(PCS9_PARA, SYNC, PCS_SYNC_SRC) | PCU_PREPARE(PCS9_PARA, NXTPAR, 0 /*par */ ); // change power status
++ PCU_SET_REG(PCS9_PARA, reg_tmp);
++
++ //PCU_SET_FIELD(MFPS1, SUSPEND_GPIO, 0x1);
++ /* setup wakeup sources */
++ /*
++ k = PCU_PREPARE(WAKEUP_SEN, GPIO0_POL, 0x1) |
++ PCU_PREPARE(WAKEUP_SEN, GPIO1_POL, 0x1) |
++ PCU_PREPARE(WAKEUP_SEN, GPIO2_POL, 0x1) |
++ PCU_PREPARE(WAKEUP_SEN, GPIO3_POL, 0x1) |
++ PCU_PREPARE(WAKEUP_SEN, GPIO4_POL, 0x1) |
++ PCU_PREPARE(WAKEUP_SEN, GPIO5_POL, 0x1) |
++ PCU_PREPARE(WAKEUP_SEN, WOL_POL, 0x1) |
++ PCU_PREPARE(WAKEUP_SEN, LPC_POL, 0x1);
++ l = ~k; //set polarity
++ //l = 0x1c0;
++ PCU_SET_REG(WAKEUP_SEN, l);
++ PCU_SET_REG(PCS9_CFG, PCU_PREPARE(PCS9_CFG, WKEN, k));
++ */
++ /* Set PDD register and set suspend_to_ram */
++ //PCU_SET_FIELD(PCS9_PDD, SUSP2RAM, 0x1);
++
++ cpu_dcache_wbinval_all();
++ cpu_icache_inval_all();
++ SET_CACHE_CTL(GET_CACHE_CTL() & ~CACHE_CTL_mskDC_EN);
++
++ /* lock self-refresh code to L1 cache */
++
++ addr = (unsigned int)__SELF_REFRESH_LOCK_START;
++ reg = (((unsigned int)__SELF_REFRESH_LOCK_END - (unsigned int)__SELF_REFRESH_LOCK_START) >> 5) + 1; //
++
++ for (i = 0; i < reg; i++) {
++ __asm__ volatile ("li $p0, 0x0\n\t"
++ "add $p0, $p0, %0\n\t"
++ "cctl $p0, L1I_VA_FILLCK\n\t"
++ "isb\n\t"::"r" (addr));
++
++ addr += 32;
++ }
++
++ unsigned char *ptr;
++ //ADD by river 2010.11.19
++ printk("The resume address's content is :\n");
++ ptr = (unsigned char *)ag102_cpu_resume;
++ for (i = 0; i < 20; i++) {
++ printk("0x%02x - ", *ptr++);
++ }
++
++ printk("Get Value..... YAYAYA....2\n");
++ get_lpc_value();
++
++ //End ADD by river 2010.11.19
++ ag102_cpu_sleep();
++ printk("return success-1..........\n");
++ /* wakeup and ckeck */
++ /*
++ reg_tmp = PCU_GET_REG(PCS9_ST2);// check Status-2
++ if (PCU_EXTRACT(PCS9_ST2, CURPAR, reg_tmp) != par)
++ printk("Parameter setup is not the same!\n");
++
++ reg_tmp = PCU_GET_REG(PCS9_ST1); // check Status-1
++ if (PCU_EXTRACT(PCS9_ST1, STS, reg_tmp) != PCS_STS_DONE)
++ printk("The work is not done?!\n");
++ if (PCU_EXTRACT(PCS9_ST1, ERR, reg_tmp) != PCS_ERR_NONE)
++ printk("Some error happened!!\n");
++ PCU_SET_REG(PCS9_ST1, 0x0); //clear status
++
++ */
++ ftpci_postinit();
++ SET_CACHE_CTL(GET_CACHE_CTL() | CACHE_CTL_mskDC_EN);
++ /* trigger mode regs */
++ REG32(AMIC_VA_BASE + 0x20) = irq_saves[0];
++ /* trigger level regs */
++ REG32(AMIC_VA_BASE + 0x24) = irq_saves[1];
++ /* interrupt enable regs */
++ REG32(AMIC_VA_BASE + 0x80) = irq_saves[2];
++ __asm__ volatile ("mtsr %0, $ir14\n\t"::"r" (tmp));
++
++ printk("return success-2..........\n");
++ dump_stack();
++
++}
++
++static int ag102_pm_valid(suspend_state_t state)
++{
++ switch (state) {
++ case PM_SUSPEND_ON:
++ case PM_SUSPEND_STANDBY:
++ case PM_SUSPEND_MEM:
++ return 1;
++
++ default:
++ return 0;
++ }
++}
++
++static int ag102_pm_begin(suspend_state_t state)
++{
++ /* TBD if we need it */
++ return 0;
++}
++
++static void andes_suspend_cpu(void)
++{
++ unsigned int irq_save;
++ /* setup GPIO interrupt enable regs to enable GPIO0 */
++ REG32(GPIO_VA_BASE + 0x20) = 1;
++ /* save interrupt enable regs */
++ irq_save = REG32(AMIC_VA_BASE + 0x80);
++ /* accept all interrupts to wake up except timer interrupt */
++ REG32(AMIC_VA_BASE + 0x80) &= ~(1 << 19);
++ /* enable UART0 interrupt */
++ REG32(AMIC_VA_BASE + 0x80) |= 1 << 13;
++
++ /*
++ * for more IRQ info, please refer to
++ * arch/nds32/include/asm/spec.h&spec-ag102.h
++ */
++
++ __asm__ volatile ("standby no_wake_grant\n\t");
++ /* clear GPIO interrupt */
++ REG32(GPIO_VA_BASE + 0x30) = 1;
++ /* disable GPIO interrupt */
++ REG32(GPIO_VA_BASE + 0x20) = 0;
++ /* restore GPIO enable regs */
++ REG32(AMIC_VA_BASE + 0x80) = irq_save;
++}
++
++static int ag102_pm_enter(suspend_state_t state)
++{
++ switch (state) {
++ case PM_SUSPEND_STANDBY:
++ andes_suspend_cpu();
++ return 0;
++ case PM_SUSPEND_MEM:
++ printk("@@@@@@@@@@ : ag102_pm_enter()... from gavin.......\n");
++ andes_suspend_to_ram();
++ return 0;
++ default:
++ return -EINVAL;
++ }
++}
++
++/*
++ * Called after processes are frozen, but before we shutdown devices.
++ */
++static int ag102_pm_prepare(void)
++{
++ /* TBD if we need it */
++ return 0;
++}
++
++/*
++ * Called after devices are wakeuped, but before processes are thawed.
++ */
++static void ag102_pm_finish(void)
++{
++ /* TBD if we need it */
++}
++
++static void ag102_pm_end(void)
++{
++ /* TBD if we need it */
++#if 0
++ class_destroy(andes_pcu_class);
++ unregister_chrdev(andes_pcu_major, ANDES_PCU_STRING);
++#endif
++ printk("pm_exit\n");
++}
++
++static int andes_pcu_ioctl(struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ return 0;
++}
++
++static int andes_pcu_open(struct inode *inode, struct file *file)
++{
++ return 0;
++}
++
++static ssize_t andes_pcu_write(struct file *filp, const char *buff,
++ size_t count, loff_t * ppos)
++{
++ char data;
++ get_user(data, buff);
++ switch (data) {
++ case 's':
++ printk("Just suspend cpu\n");
++ andes_suspend_cpu();
++ break;
++ case 'm':
++ printk("Suspend to ram\n");
++ andes_suspend_to_ram();
++ break;
++ }
++ return 0;
++}
++
++static int andes_pcu_release(struct inode *inode, struct file *file)
++{
++ return 0;
++}
++
++static struct file_operations andes_pcu_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = andes_pcu_ioctl,
++ .open = andes_pcu_open,
++ .write = andes_pcu_write,
++ .release = andes_pcu_release,
++};
++
++static struct platform_suspend_ops ag102_pm_ops = {
++ .valid = ag102_pm_valid,
++ .begin = ag102_pm_begin,
++ .prepare = ag102_pm_prepare,
++ .enter = ag102_pm_enter,
++ .finish = ag102_pm_finish,
++ .end = ag102_pm_end,
++};
++
++//PCU power-off workaround {
++#undef IRQ_LEVEL
++#include <linux/interrupt.h>
++#include <linux/irq.h>
++
++//#define PM_DEBUG
++#ifdef PM_DEBUG
++#define PRINTK printk
++#else
++#define PRINTK(...)
++#endif
++
++static volatile int pcuirq = 0;
++
++static inline void poweroff_pcu(void)
++{
++ PRINTK(KERN_INFO "[kernel] poweroff_pcu()");
++ REG32(PCU_VA_BASE + 0x1a4) = (2 << 28) | (1 << 24) | (6 << 0); //power-down, sync CPUA, domain GPU+CPUB
++ __asm__ volatile ("standby wait_done\n");
++ REG32(PCU_VA_BASE + 0x1a8) = 0x0; //PCS9 status normal, no error
++}
++
++static inline void clear_pcu_status(void)
++{
++ PRINTK(KERN_INFO "[kernel] clear_pcu_status()");
++ REG32(PCU_VA_BASE + 0x1b0) |= (1 << 31); //clear poweroff flag
++ asm("msync store\nisb");
++}
++
++static irqreturn_t gpio0_isr(int irq, void *dev_id)
++{
++ PRINTK(KERN_INFO "[kernel] gpio0_isr(irq=%d)\n", irq);
++
++ // is GPIO0 IRQ
++ if (REG32(GPIO_VA_BASE + 0x28) & (1 << 0)) {
++ PRINTK(KERN_INFO "GPIO#0 ASSERT!\n");
++
++ pcuirq = 0;
++
++ //disable GPIO0 IRQ
++ REG32(GPIO_VA_BASE + 0x2c) |= (1 << 0); //GPIO0 IRQ mask, level mode AMIC.GPIO#0 also cleared
++
++// REG32(AMIC_VA_BASE + 0x84) = (1<<13); //AMIC clear GPIO interrupt
++
++ return IRQ_HANDLED;
++ }
++
++ return IRQ_NONE;
++}
++
++#define GPIO_SEC (1<<11)
++static irqreturn_t pcu_isr(int irq, void *dev_id)
++{
++ UINT32 status = REG32(PCU_VA_BASE + 0x94);
++ PRINTK(KERN_INFO "[kernel] pcu_isr(irq=%d) status=0x%08x\n", irq,
++ status);
++ if (0 == (GPIO_SEC & status))
++ return IRQ_NONE;
++
++ PRINTK(KERN_INFO "[kernel] GPIO_SEC\n");
++ clear_pcu_status(); //clear PCS9 IRQ (level mode => AMIC.PCU also cleared)
++ pcuirq++;
++ if (1 == pcuirq) {
++ //enable GPIO0 IRQ
++ REG32(GPIO_VA_BASE + 0x30) = (1 << 0); //GPIO0 IRQ cleared
++// REG32(AMIC_VA_BASE + 0x84) = (1 << 13); //AMIC clear GPIO interrupt
++// enable_irq(GPIO_FTGPIO010_IRQ);
++ REG32(AMIC_VA_BASE + 0x80) |= (1 << 13); //AMIC enable GPIO IRQ
++ REG32(GPIO_VA_BASE + 0x2c) &= ~(1 << 0); //GPIO0 IRQ unmask
++ } else if (5 == pcuirq) {
++ poweroff_pcu();
++ }
++// REG32(AMIC_VA_BASE + 0x84) = (1 << 8); //PCU IRQ clear
++
++ return IRQ_HANDLED;
++}
++
++//PCU power-off workaround }
++
++static int __init ag102_pm_init(void)
++{
++ int ret = 0;
++ struct device *temp_class;
++ printk("PM driver init\n");
++ suspend_set_ops(&ag102_pm_ops);
++
++ andes_pcu_major = register_chrdev(0, ANDES_PCU_STRING, &andes_pcu_fops);
++
++ printk("@@@@@ : andes_pcu_major = 0x%08x\n", andes_pcu_major);
++ if (andes_pcu_major < 0) {
++ printk("Unable to get a major for andes pcu driver!\n");
++ return andes_pcu_major;
++ }
++
++ andes_pcu_class = class_create(THIS_MODULE, ANDES_PCU_STRING);
++
++ if (IS_ERR(andes_pcu_class)) {
++ printk(KERN_ERR "Error creating andes pcu class.\n");
++ ret = PTR_ERR(andes_pcu_class);
++ goto err_out1;
++ }
++
++ temp_class = device_create(andes_pcu_class, NULL,
++ MKDEV(andes_pcu_major, 0),
++ NULL, ANDES_PCU_STRING);
++
++ if (IS_ERR(temp_class)) {
++ printk(KERN_ERR "Error creating andes pcu class device.\n");
++ ret = PTR_ERR(temp_class);
++ goto err_out2;
++ }
++
++ mac_dah = GMAC_GET_REG(MAC_MADR);
++ mac_dal = GMAC_GET_REG(MAC_LADR);
++
++ //poweroff workaround
++ {
++ if (request_irq
++ (PCU_IRQ, pcu_isr, IRQF_SHARED, "PCU_POWEROFF", pcu_isr)) {
++ printk("Failed to request PCU interrupt.\n");
++ }
++
++ if (request_irq
++ (GPIO_FTGPIO010_IRQ, gpio0_isr, IRQF_SHARED,
++ "GPIO0_FOR_PCU", gpio0_isr)) {
++ printk("Failed to request GPIO0 interrupt.\n");
++ }
++
++ REG32(PCU_VA_BASE + 0x1b0) |= (3 << 28); //poweroff in 5s
++
++ //AMIC setup
++ // PCU IRQ default edge trigger, rising edge
++ // GPIO_FTGPIO010_IRQ default edge trigger, rising edge
++// REG32(AMIC_VA_BASE + 0x20) &= ~(1 << 8); //PCU IRQ level trigger
++// REG32(AMIC_VA_BASE + 0x24) &= ~(1 << 8); //PCU IRQ active-high
++// REG32(AMIC_VA_BASE + 0x20) &= ~(1 << 13); //GPIO IRQ level trigger
++
++ //GPIO #0 setup
++ REG32(GPIO_VA_BASE + 0x08) &= ~(1 << 0); //GPIO0 input
++ REG32(GPIO_VA_BASE + 0x18) &= ~(1 << 0); //GPIO0 not pulled (external pull-high)
++ REG32(GPIO_VA_BASE + 0x2c) |= (1 << 0); //GPIO0 IRQ masked
++ REG32(GPIO_VA_BASE + 0x34) |= (1 << 0); //GPIO0 IRQ level trigger
++// REG32(GPIO_VA_BASE + 0x38) &= ~(1<<0); //GPIO0 IRQ single edge
++ REG32(GPIO_VA_BASE + 0x3c) &= ~(1 << 0); //GPIO0 IRQ high-active
++ REG32(GPIO_VA_BASE + 0x40) |= (1 << 0); //GPIO0 enable bounce
++ REG32(GPIO_VA_BASE + 0x40) = 0xffff; //GPIO bounce time = x/PCLK
++// REG32(GPIO_VA_BASE + 0x30) = (1<<0); //GPIO0 IRQ cleared
++ REG32(GPIO_VA_BASE + 0x20) |= (1 << 0); //GPIO0 IRQ enable
++
++// enable_irq(PCU_IRQ);
++ REG32(AMIC_VA_BASE + 0x80) |= (1 << 8); //IRQ enabled
++ }
++
++ printk("pm_init\n");
++ return 0;
++err_out2:
++ class_destroy(andes_pcu_class);
++err_out1:
++ unregister_chrdev(andes_pcu_major, ANDES_PCU_STRING);
++ return 1;
++}
++
++//static void resume_to_ccode(void)
++//{
++// printk("Resume to C code successfully....\n");
++//}
++
++late_initcall(ag102_pm_init);
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ag102/sleep.S linux-3.4.110/arch/nds32/platforms/ag102/sleep.S
+--- linux-3.4.110.orig/arch/nds32/platforms/ag102/sleep.S 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ag102/sleep.S 2016-04-07 10:20:51.002083345 +0200
+@@ -0,0 +1,465 @@
++#include <asm/spec-ag102.h>
++.text
++
++.globl ag102_cpu_sleep
++.globl ag102_cpu_resume
++.globl ag102_cpu_resume2
++.globl __SELF_REFRESH_LOCK_START
++.globl __SELF_REFRESH_LOCK_END
++
++#! 0x94200000; keep r0, r1, r2
++ .macro putch ch
++ li $r0, #0x94200000
++ move $r2, \ch
++88:
++ lwi $r1, [$r0+#0x14]
++ srli $r1, $r1, #5
++ andi $r1, $r1, #0x1
++ beqz $r1, 88b
++ swi $r2, [$r0]
++ .endm
++#! 0x94200000; keep r3, r4
++ .macro hex2asc val
++ addi \val, \val, -10
++ bltz \val, 1f
++ addi \val, \val, 0x41
++ j 2f
++1:
++ addi \val, \val, 0x3a
++2:
++ .endm
++
++ .macro print_hex mhex
++ move $r3, \mhex
++
++ srli $r4, $r3, #28
++ andi $r4, $r4, 0xf
++ hex2asc $r4
++ putch $r4
++ srli $r4, $r3, #24
++ andi $r4, $r4, 0xf
++ hex2asc $r4
++ putch $r4
++ srli $r4, $r3, #20
++ andi $r4, $r4, 0xf
++ hex2asc $r4
++ putch $r4
++ srli $r4, $r3, #16
++ andi $r4, $r4, 0xf
++ hex2asc $r4
++ putch $r4
++ srli $r4, $r3, #12
++ andi $r4, $r4, 0xf
++ hex2asc $r4
++ putch $r4
++ srli $r4, $r3, #8
++ andi $r4, $r4, 0xf
++ hex2asc $r4
++ putch $r4
++ srli $r4, $r3, #4
++ andi $r4, $r4, 0xf
++ hex2asc $r4
++ putch $r4
++ move $r4, $r3
++ andi $r4, $r4, 0xf
++ hex2asc $r4
++ putch $r4
++ .endm
++
++ag102_cpu_resume2:
++/*1:
++b 1b*/
++ //MOD by river 2010.10.13
++ popm $r0, $r19
++ mtusr $r0, $d0.lo ! $d0 lo byte
++ mtusr $r1, $d0.hi ! $d0 hi byte
++ mtusr $r2, $d1.lo ! $d1 lo byte
++ mtusr $r3, $d1.hi ! $d1 hi byte
++ mtsr $r4, $mr0
++ mtsr $r5, $mr1
++ mtsr $r6, $mr4
++ mtsr $r7, $mr6
++ mtsr $r8, $mr7
++ mtsr $r9, $mr8
++ mtsr $r10, $ir0
++ mtsr $r11, $ir1
++ mtsr $r12, $ir2
++ mtsr $r13, $ir3
++ mtsr $r14, $ir9
++ mtsr $r15, $ir10
++ mtsr $r16, $ir12
++ mtsr $r17, $ir13
++ mtsr $r18, $ir14
++ mtsr $r19, $ir15
++ //End MOD by river 2010.10.13
++ popm $r0, $r30
++ ret
++
++ag102_cpu_sleep:
++
++ pushm $r0, $r30
++ //MOD by river 2010.10.13
++ mfusr $r0, $d0.lo ! $d0 lo byte
++ mfusr $r1, $d0.hi ! $d0 hi byte
++ mfusr $r2, $d1.lo ! $d1 lo byte
++ mfusr $r3, $d1.hi ! $d1 hi byte
++ mfsr $r4, $mr0
++ mfsr $r5, $mr1
++ mfsr $r6, $mr4
++ mfsr $r7, $mr6
++ mfsr $r8, $mr7
++ mfsr $r9, $mr8
++ mfsr $r10, $ir0
++ mfsr $r11, $ir1
++ mfsr $r12, $ir2
++ mfsr $r13, $ir3
++ mfsr $r14, $ir9
++ mfsr $r15, $ir10
++ mfsr $r16, $ir12
++ mfsr $r17, $ir13
++ mfsr $r18, $ir14
++ mfsr $r19, $ir15
++ pushm $r0, $r19
++ //End MOD by river 2010.10.13
++
++ /* store $sp to 0x408 scratch pad */
++ sethi $r0, hi20(PCU_VA_BASE + 0x408)
++ ori $r2, $r0, lo12(PCU_VA_BASE + 0x408)
++ swi $r31, [$r2]
++
++ /* set signaure "SUSP" to 0x40c */
++ li $r0, (PCU_VA_BASE + 0x40c)
++ li $r1, 0x53555350 ! set signature "SUSP" to scratch pad register offset 0x40c
++ swi $r1, [$r0]
++
++ /*
++ * store 8 bytes from 16mb to pcu scratch pad resgister
++ * due to data training process will destroy it
++ */
++ li $r0, 0x10000
++ li $r2, (PCU_VA_BASE + 0x414)
++ lwi $r1, [$r0]
++ swi $r1, [$r2]
++ lwi $r1, [$r0 + 0x4]
++ swi $r1, [$r2 + 0x4]
++
++ /* ADD by river 2010.09.23 */
++ /* Save PSW in PCU_VA_BASE + 0x420 */
++ li $r0, (PCU_VA_BASE + 0x420)
++ mfsr $r1, $ir0
++ swi $r1, [$r0]
++ /* Save $mr0 in PCU_VA_BASE + 0x424 */
++ li $r0, (PCU_VA_BASE + 0x424)
++ mfsr $r1, $mr0
++ swi $r1, [$r0]
++ /* Save $mr1 in PCU_VA_BASE + 0x428 */
++ li $r0, (PCU_VA_BASE + 0x428)
++ mfsr $r1, $mr1
++ swi $r1, [$r0]
++ /* Save $mr2 in PCU_VA_BASE + 0x42c */
++ li $r0, (PCU_VA_BASE + 0x42c)
++ mfsr $r1, $mr2
++ swi $r1, [$r0]
++ /* Save $mr3 in PCU_VA_BASE + 0x430 */
++ li $r0, (PCU_VA_BASE + 0x430)
++ mfsr $r1, $mr3
++ swi $r1, [$r0]
++ /* Save $mr4 in PCU_VA_BASE + 0x434 */
++ li $r0, (PCU_VA_BASE + 0x434)
++ mfsr $r1, $mr4
++ swi $r1, [$r0]
++ /* Save $mr5 in PCU_VA_BASE + 0x438 */
++ //li $r0, (PCU_VA_BASE + 0x438)
++ //mfsr $r1, $mr5
++ //swi $r1, [$r0]
++ /* Save $mr6 in PCU_VA_BASE + 0x43c */
++ li $r0, (PCU_VA_BASE + 0x43c)
++ mfsr $r1, $mr6
++ swi $r1, [$r0]
++ /* Save $mr7 in PCU_VA_BASE + 0x440 */
++ li $r0, (PCU_VA_BASE + 0x440)
++ mfsr $r1, $mr7
++ swi $r1, [$r0]
++ /* Save $mr8 in PCU_VA_BASE + 0x444 */
++ li $r0, (PCU_VA_BASE + 0x444)
++ mfsr $r1, $mr8
++ swi $r1, [$r0]
++
++ /* Save $ir3 in PCU_VA_BASE + 0x450 */
++ li $r0, (PCU_VA_BASE + 0x450)
++ mfsr $r1, $ir3
++ swi $r1, [$r0]
++
++ /* Save $ir14 in PCU_VA_BASE + 0x454 */
++ li $r0, (PCU_VA_BASE + 0x454)
++ mfsr $r1, $ir14
++ swi $r1, [$r0]
++
++ /* Save $ir15 in PCU_VA_BASE + 0x458 */
++ li $r0, (PCU_VA_BASE + 0x458)
++ mfsr $r1, $ir15
++ swi $r1, [$r0]
++
++ tlbop FlushAll
++ isb
++ /* End ADD by river 2010.09.23 */
++
++ //Trace by river 2010.12.01
++ /*1:
++ b 1b*/
++ //End Trace by river 2010.12.01
++.p2align 5
++__SELF_REFRESH_LOCK_START:
++ /*sethi $r0, hi20(0x900005cc)
++ ori $r0, $r0, lo12(0x900005cc)
++ sethi $r1, hi20(DDR2C_VA_BASE)
++ swi $r0, [$r1+0x4]
++
++ msync
++ isb
++
++ standby wake_grant
++ .p2align 5*/
++ sethi $r0, hi20(DDR2C_VA_BASE)
++ lwi $r1, [$r0+0x4]
++ li $r2, 0x07ffefff
++ and $r1, $r2, $r1
++ li $r2, 0x90001000
++ or $r1, $r2, $r1
++ swi $r1, [$r0+0x4]
++
++ msync
++ isb
++
++ standby wake_grant
++ .p2align
++
++__SELF_REFRESH_LOCK_END:
++
++ag102_cpu_resume:
++ /* TRACE by river 2010.12.02 */
++ /*1:
++ b 1b*/
++ /* End TRACE by river 2010.12.02 */
++ mfsr $r2, $mr0
++ ori $r2, $r2, #0x6
++#ifdef CONFIG_ANDES_PAGE_SIZE_8KB
++ ori $r2, $r2, #0x1
++#endif
++ mtsr $r2, $mr0
++
++ /* ADD by river 2010.09.23 */
++ li $r3, 'C
++ putch $r3
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++ li $r3, 'P
++ putch $r3
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++ li $r3, 'U
++ putch $r3
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++ li $r3, 'R
++ putch $r3
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++ li $r3, 'E
++ putch $r3
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++ li $r3, 'S
++ putch $r3
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++ li $r3, 'U
++ putch $r3
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++ li $r3, 'M
++ putch $r3
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++ li $r3, 'E
++ putch $r3
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++ /* ADD by river 2010.09.23 */
++
++ /*tlbop FlushAll*/ ! invalidate TLB\n"
++
++ /* ADD by river 2010.09.23 */
++ /* restore PSW */
++ //sethi $r2, hi20(PCU_PA_BASE + 0x420)
++ //ori $r2, $r2, lo12(PCU_PA_BASE + 0x420)
++ //lwi $r3, [$r2]
++ //mtsr $r3, $ir0
++ //move $p1, $r3
++ /* restore $mr0 */
++ sethi $r2, hi20(PCU_PA_BASE + 0x424)
++ ori $r2, $r2, lo12(PCU_PA_BASE + 0x424)
++ lwi $r3, [$r2]
++ mtsr $r3, $mr0
++ /* restore $mr1 */
++ sethi $r2, hi20(PCU_PA_BASE + 0x428)
++ ori $r2, $r2, lo12(PCU_PA_BASE + 0x428)
++ lwi $r3, [$r2]
++ mtsr $r3, $mr1
++
++ /* restore $mr2 */
++ //sethi $r2, hi20(PCU_PA_BASE + 0x42c)
++ //ori $r2, $r2, lo12(PCU_PA_BASE + 0x42c)
++ //lwi $r3, [$r2]
++ //mtsr $r3, $mr2
++ /* restore $mr3 */
++ //sethi $r2, hi20(PCU_PA_BASE + 0x430)
++ //ori $r2, $r2, lo12(PCU_PA_BASE + 0x430)
++ //lwi $r3, [$r2]
++ //mtsr $r3, $mr3
++ /* restore $mr4 */
++ sethi $r2, hi20(PCU_PA_BASE + 0x434)
++ ori $r2, $r2, lo12(PCU_PA_BASE + 0x434)
++ lwi $r3, [$r2]
++ mtsr $r3, $mr4
++ /* restore $mr5 */
++ //sethi $r2, hi20(PCU_PA_BASE + 0x438)
++ //ori $r2, $r2, lo12(PCU_PA_BASE + 0x438)
++ //lwi $r3, [$r2]
++ //mtsr $r3, $mr5
++ /* restore $mr6 */
++ sethi $r2, hi20(PCU_PA_BASE + 0x43c)
++ ori $r2, $r2, lo12(PCU_PA_BASE + 0x43c)
++ lwi $r3, [$r2]
++ mtsr $r3, $mr6
++ /* restore $mr7 */
++ sethi $r2, hi20(PCU_PA_BASE + 0x440)
++ ori $r2, $r2, lo12(PCU_PA_BASE + 0x440)
++ lwi $r3, [$r2]
++ mtsr $r3, $mr7
++ /* restore $mr8 */
++ sethi $r2, hi20(PCU_PA_BASE + 0x444)
++ ori $r2, $r2, lo12(PCU_PA_BASE + 0x444)
++ lwi $r3, [$r2]
++ /* ADD by river 2010.12.02 for ICache Enable */
++ ori $r3, $r3, #0x1
++ /* End ADD by river 2010.12.02 for ICache Enable */
++ mtsr $r3, $mr8
++
++ /* restore $ir3 */
++ sethi $r2, hi20(PCU_PA_BASE + 0x450)
++ ori $r2, $r2, lo12(PCU_PA_BASE + 0x450)
++ lwi $r3, [$r2]
++ mtsr $r3, $ir3
++
++ move $p1, $r3
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++ print_hex $p1
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++
++
++ /* restore $ir14 */
++ sethi $r2, hi20(PCU_PA_BASE + 0x454)
++ ori $r2, $r2, lo12(PCU_PA_BASE + 0x454)
++ lwi $r3, [$r2]
++ mtsr $r3, $ir14
++
++ /* restore $ir15 */
++ sethi $r2, hi20(PCU_PA_BASE + 0x458)
++ ori $r2, $r2, lo12(PCU_PA_BASE + 0x458)
++ lwi $r3, [$r2]
++ mtsr $r3, $ir15
++
++ li $r3, '\r
++ putch $r3
++ li $r3, '\n
++ putch $r3
++ move $p1, $r3
++ print_hex $p1
++
++ /* End ADD by river 2010.09.23 */
++
++ /* in this buggy version(ram locate at 1G) TC01 we don't need to do remap.
++ * ebios set memory locate at 1G & size = 1G, for more detail info, please
++ * refer to ebios boot.S.
++ *
++ * sethi $r2, hi20(0x90c00000 + 0x88)
++ * ori $r2, $r2, lo12(0x90c00000 + 0x88)
++ * movi $r3, #0x1
++ * swi $r3, [$r2]
++ **/
++
++ /* restore 8 bytes from pcu scratch pad resgister to 16mb */
++ li $r0, 0x10000
++ li $r2, (PCU_PA_BASE + 0x414)
++ lwi $r1, [$r2]
++ swi $r1, [$r0]
++ lwi $r1, [$r2 + 0x4]
++ swi $r1, [$r0 + 0x4]
++
++ .p2align 5
++ resume_lock_start:
++ /* ADD by river 2010.12.02 for ag102_cpu_resume2 for jral.ton $r4, $r4 */
++ sethi $r2, hi20(PCU_PA_BASE + 0x404)
++ ori $r2, $r2, lo12(PCU_PA_BASE + 0x404)
++ lwi $r4, [$r2]
++ /* End ADD by river 2010.12.02 for ag102_cpu_resume2 */
++
++ /* ADD by river 2010.12.02 for restore kernel ROM map */
++ sethi $r0, hi20(0x40080000)
++ ori $r0, $r0, lo12(0x40080000)
++ sethi $r1, hi20(AHB_ATFAHBC020S_0_PA_BASE + 0x10)
++ ori $r1, $r1, lo12(AHB_ATFAHBC020S_0_PA_BASE + 0x10)
++ swi $r0, [$r1]
++
++ /* ADD by river 2010.12.02 for restore kernel RAM map */
++ sethi $r0, hi20(0x000A0000)
++ ori $r0, $r0, lo12(0x000A0000)
++ sethi $r1, hi20(AHB_ATFAHBC020S_0_PA_BASE + 0x18)
++ ori $r1, $r1, lo12(AHB_ATFAHBC020S_0_PA_BASE + 0x18)
++ swi $r0, [$r1]
++
++ /******************* Gavin version ***************************/
++ //MOD by river 2010.10.13
++ /*sethi $r2, hi20(PCU_PA_BASE + 0x404)
++ ori $r2, $r2, lo12(PCU_PA_BASE + 0x404)
++ lwi $r4, [$r2]
++ mtsr $r4, $IPC
++ li $r1, 0xcb
++ mtsr $r1, $IPSW
++ iret*/
++ //End MOD by river 2010.10.13
++ //End Gavin version////////////////////////////////////////////////////////////
++
++ /* End ADD by river 2010.09.23 */
++ //MOD by river 2010.10.13
++ //////// jral.ton version ////////////////////////////////////////////////////
++
++ jral.ton $r4, $r4
++ .p2align
++ resume_lock_end:
++ //End MOD by river 2010.10.13
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/amic.c linux-3.4.110/arch/nds32/platforms/amic.c
+--- linux-3.4.110.orig/arch/nds32/platforms/amic.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/amic.c 2016-04-07 10:20:51.002083345 +0200
+@@ -0,0 +1,203 @@
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/delay.h>
++
++#include <asm/io.h>
++#include <asm/amic.h>
++
++#define DEBUG(enabled, tagged, ...) \
++ do { \
++ if (enabled) { \
++ if (tagged) \
++ printk("[ %30s() ] ", __func__); \
++ printk(__VA_ARGS__); \
++ } \
++ } while (0)
++
++static DEFINE_SPINLOCK(amic_irq_lock);
++
++static void amic_ack_irq(unsigned int irq)
++{
++ unsigned int data;
++
++ spin_lock(&amic_irq_lock);
++ writel(1 << irq, AMIC_BASE + INTSTA);
++ data = readl(AMIC_BASE + INTSTA);
++ spin_unlock(&amic_irq_lock);
++}
++
++static void amic_mask_irq(unsigned int irq)
++{
++ unsigned int data;
++
++ spin_lock(&amic_irq_lock);
++ data = readl(AMIC_BASE + INTEN);
++ data &= ~(1 << irq);
++ writel(data, AMIC_BASE + INTEN);
++ data = readl(AMIC_BASE + INTEN);
++ spin_unlock(&amic_irq_lock);
++}
++
++static int amic_set_type(unsigned int irq, unsigned int flow_type)
++{
++ unsigned int data;
++
++ spin_lock(&amic_irq_lock);
++ if (flow_type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
++ data = readl(AMIC_BASE + INTTRG);
++ data |= 1 << irq;
++ writel(data, AMIC_BASE + INTTRG);
++ }
++
++ if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
++ data = readl(AMIC_BASE + INTTRG);
++ data &= ~(1 << irq);
++ writel(data, AMIC_BASE + INTTRG);
++ }
++
++ if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_EDGE_FALLING)) {
++ data = readl(AMIC_BASE + INTLVL);
++ data |= 1 << irq;
++ writel(data, AMIC_BASE + INTLVL);
++ }
++
++ if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING)) {
++ data = readl(AMIC_BASE + INTLVL);
++ data &= ~(1 << irq);
++ writel(data, AMIC_BASE + INTLVL);
++ }
++ spin_unlock(&amic_irq_lock);
++ return 0;
++}
++
++static void amic_unmask_irq(unsigned int irq)
++{
++ unsigned int data;
++
++ spin_lock(&amic_irq_lock);
++ data = readl(AMIC_BASE + INTEN);
++ data |= 1 << irq;
++ writel(data, AMIC_BASE + INTEN);
++ data = readl(AMIC_BASE + INTEN);
++ spin_unlock(&amic_irq_lock);
++}
++
++static int amic_set_affinity(unsigned int irq, const struct cpumask *dest)
++{
++ int cnt = 0;
++ int cpu;
++ volatile unsigned int data;
++ volatile unsigned int dc, amic_irq;
++
++ if (num_online_cpus() > 2)
++ return 0;
++
++ spin_lock(&amic_irq_lock);
++ /* remap irq number for real controller */
++ /* this may be needed in future */
++ /* amic_irq = irq_remap(irq); */
++ amic_irq = irq;
++
++ /* change owner */
++ data = readl(AMIC_BASE + CPUID0 + ((amic_irq >> 4) << 2));
++ for_each_online_cpu(cpu) {
++ if (cpumask_test_cpu(cpu, dest)) {
++ data &= ~(0x3 << ((amic_irq & ~0x10) * 2));
++ data |= cpu << ((amic_irq & ~0x10) * 2);
++ cnt++;
++ }
++ }
++ writel(data, AMIC_BASE + CPUID0 + ((amic_irq >> 4) << 2));
++
++ dc = readl(AMIC_BASE + CPUDC);
++ if (cnt == 2) /* set bit */
++ writel((dc | (1 << amic_irq)), (AMIC_BASE + CPUDC));
++ else /* clear bit */
++ writel((dc & ~(1 << amic_irq)), (AMIC_BASE + CPUDC));
++
++ spin_unlock(&amic_irq_lock);
++
++ DEBUG(0, 1, "en=%08x,status=%08x\n", readl(AMIC_BASE + INTEN),
++ readl(AMIC_BASE + INTSTA));
++
++ return 0;
++}
++
++static struct irq_chip amic_chip = {
++ .name = "AMIC",
++ .ack = amic_ack_irq,
++ .mask = amic_mask_irq,
++ .unmask = amic_unmask_irq,
++ .set_affinity = amic_set_affinity,
++ .set_type = amic_set_type,
++};
++
++void __init amic_init(void)
++{
++ int i, edge;
++ unsigned int temp = smp_processor_id();
++ temp |= temp << 2;
++ temp |= temp << 4;
++ temp |= temp << 8;
++ temp |= temp << 16;
++
++ writel(0x0, AMIC_BASE + INTEN);
++ writel(0x0, AMIC_BASE + CPUDC);
++ writel(temp, AMIC_BASE + CPUID0);
++ writel(temp, AMIC_BASE + CPUID1);
++ writel(0xffff, AMIC_BASE + IPISTA);
++ writel(0xffffffff, AMIC_BASE + INTSTA);
++ writel(0x11111111, AMIC_BASE + PRITY0);
++ writel(0x11111111, AMIC_BASE + PRITY1);
++ writel(0x11111111, AMIC_BASE + PRITY2);
++ writel(0x11111111, AMIC_BASE + PRITY3);
++ writel(DEFAULT_MODE, AMIC_BASE + INTTRG);
++ writel(~DEFAULT_LEVEL, AMIC_BASE + INTLVL);
++ printk("AMIC config %x %x\n", temp, readl(AMIC_BASE + CONFIG));
++
++ for (i = IRQ_BASE, edge = 1; i < IRQ_BASE + IRQ_TOTAL; i++, edge <<= 1) {
++ set_irq_chip(i, &amic_chip);
++ if (DEFAULT_MODE & edge)
++ set_irq_handler(i, handle_edge_irq);
++ else
++ set_irq_handler(i, handle_level_irq);
++ }
++
++}
++
++unsigned int get_IntSrc(void)
++{
++ unsigned int irqsta, irq = 31;
++
++ spin_lock(&amic_irq_lock);
++ irqsta = readl(AMIC_BASE + IPISTA);
++ if (irqsta != 0)
++ irqsta = 0;
++ else
++ irqsta = readl(AMIC_BASE + INTSTA);
++ spin_unlock(&amic_irq_lock);
++
++ if (irqsta == 0)
++ return 32;
++ if (irqsta & 0x0000ffff) {
++ irq -= 16;
++ irqsta <<= 16;
++ }
++ if (irqsta & 0x00ff0000) {
++ irq -= 8;
++ irqsta <<= 8;
++ }
++ if (irqsta & 0x0f000000) {
++ irq -= 4;
++ irqsta <<= 4;
++ }
++ if (irqsta & 0x30000000) {
++ irq -= 2;
++ irqsta <<= 2;
++ }
++ if (irqsta & 0x40000000) {
++ irq -= 1;
++ }
++ return irq;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/dmad.c linux-3.4.110/arch/nds32/platforms/dmad.c
+--- linux-3.4.110.orig/arch/nds32/platforms/dmad.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/dmad.c 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,3601 @@
++/*****************************************************************************
++ *
++ * Copyright Andes Technology Corporation 2007-2008
++ * All Rights Reserved.
++ *
++ * Revision History:
++ *
++ * Aug.21.2007 Created.
++ * Feb.23.2009 Porting to Linux 2.6.
++*****************************************************************************/
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/spinlock.h>
++#include <linux/completion.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <asm/sizes.h>
++#include <asm/types.h>
++#include <asm/io.h>
++#include <asm/dmad.h>
++#include <linux/irq.h>
++
++#if (defined(CONFIG_PLATFORM_AHBDMA) || defined(CONFIG_PLATFORM_APBDMA))
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++#define DMAD_AHB_MAX_CHANNELS DMAC_MAX_CHANNELS
++#else
++#define DMAD_AHB_MAX_CHANNELS 0
++#endif /* CONFIG_PLATFORM_AHBDMA */
++
++#ifdef CONFIG_PLATFORM_APBDMA
++#define DMAD_APB_MAX_CHANNELS APBBR_DMA_MAX_CHANNELS
++#else
++#define DMAD_APB_MAX_CHANNELS 0
++#endif /* CONFIG_PLATFORM_APBDMA */
++
++#define DMAD_DRB_POOL_SIZE 32 /* 128 */
++
++/* reg/io supplementals */
++static inline void setbl(addr_t bit, addr_t reg)
++{
++ outl(inl(reg) | (addr_t) ((addr_t) 1 << bit), reg);
++}
++
++static inline void clrbl(addr_t bit, addr_t reg)
++{
++ outl(inl(reg) & (~((addr_t) ((addr_t) 1 << bit))), reg);
++}
++
++static inline addr_t getbl(addr_t bit, addr_t reg)
++{
++ return inl(reg) & (addr_t) ((addr_t) 1 << bit);
++}
++
++/******************************************************************************/
++
++enum DMAD_DRQ_FLAGS {
++ DMAD_DRQ_STATE_READY = 0x00000001, /* channel allocation status */
++ DMAD_DRQ_STATE_ABORT = 0x00000002, /* abort drb alloc block-wait */
++ DMAD_DRQ_DIR_A1_TO_A0 = 0x00000004, /* Transfer direction */
++};
++
++#define DMAD_DRQ_DIR_MASK DMAD_DRQ_DIR_A1_TO_A0
++
++/* DMA request queue, one instance per channel */
++typedef struct dmad_drq {
++ u32 state; /* enum DMAD_DRQ_STATE */
++
++ addr_t channel_base; /* register base address */
++ addr_t enable_port; /* enable register */
++ addr_t src_port; /* source address register */
++ addr_t dst_port; /* dest address register */
++ addr_t cyc_port; /* size(cycle) register */
++
++ u32 flags; /* enum DMAD_CHREQ_FLAGS */
++
++ spinlock_t drb_pool_lock;
++ dmad_drb *drb_pool; /* drb pool */
++
++ u32 fre_head; /* free list head */
++ u32 fre_tail; /* free list tail */
++
++ u32 rdy_head; /* ready list head */
++ u32 rdy_tail; /* ready list tail */
++
++ u32 sbt_head; /* submitted list head */
++ u32 sbt_tail; /* submitted list tail */
++
++ u32 data_width; /* dma transfer data width */
++
++ struct completion drb_alloc_sync;
++
++ /* client supplied callback function, executed in interrupt context
++ * client private data to be passed to data argument of completion_cb().
++ */
++ void (*completion_cb) (int channel, u16 status, void *data);
++ void *completion_data;
++
++ /* ring-mode fields are valid for DMAD_FLAGS_RING_MODE */
++ dma_addr_t ring_base; /* ring buffer base address */
++ dma_addr_t ring_size; /* size (of data width) */
++ addr_t ring_port; /* for setup/fetch hw_ptr */
++ dmad_drb *ring_drb;
++
++ addr_t dev_addr; /* device data port */
++
++ int periods; /* interrupts periods */
++ dma_addr_t period_size; /* of dma data with */
++ dma_addr_t period_bytes; /* Period size, in bytes */
++
++ /* ring_size - period_size * periods */
++ dma_addr_t remnant_size;
++
++ dma_addr_t sw_ptr; /* sw pointer */
++ int sw_p_idx; /* current ring_ptr */
++ dma_addr_t sw_p_off; /* offset to period base */
++
++} dmad_drq;
++
++/* To shrink code size and improve performance, common channel registers
++ * are preload in drq struct at channel allocation time. One of the key
++ * dependency is the enable bit of both DMAC and APBDMA channel command
++ * registers. Please make sure hw design them at bit 0 of the command register
++ * in future evolvement.
++ */
++#if (DMAC_CSR_CH_EN_BIT != APBBR_DMA_CHEN_BIT)
++#error "DMAC_CSR_CH_EN_BIT != APBBR_DMA_CHEN_BIT"
++#endif
++
++#define DMAD_PORT_ENABLE_BIT APBBR_DMA_CHEN_BIT
++
++static inline void dmad_enable_channel(dmad_drq * drq)
++{
++ setbl(DMAD_PORT_ENABLE_BIT, drq->enable_port);
++}
++
++static inline void dmad_disable_channel(dmad_drq * drq)
++{
++ clrbl(DMAD_PORT_ENABLE_BIT, drq->enable_port);
++}
++
++static inline addr_t dmad_is_channel_enabled(dmad_drq * drq)
++{
++ return (addr_t) getbl(DMAD_PORT_ENABLE_BIT, drq->enable_port);
++}
++
++/* AHB DMAC channel re-route table structure */
++typedef struct _DMAD_AHB_CH_ROUTE {
++ u32 dev_reqn; /* device req/gnt number */
++ addr_t clear_cr; /* routing control register address */
++ addr_t route_cr; /* routing control register address */
++} DMAD_AHB_CH_ROUTE;
++
++#ifdef CONFIG_PLAT_AG102
++#if 0
++/* AHB DMAC channel re-route table. Indexed by AHB DMAC req/ack number. */
++static DMAD_AHB_CH_ROUTE ahb_ch_route_table[] __attribute__ ((__unused__)) = {
++ /* all todo ... */
++
++ {
++ 0x00, DMAC_REQN_IDERX, DMAC_REQN_IDERX}, {
++ 0x01, DMAC_REQN_IDETX, DMAC_REQN_IDETX}, {
++ 0x02, DMAC_REQN_I2SAC97RX, DMAC_REQN_I2SAC97RX}, {
++ 0x03, DMAC_REQN_I2SAC97TX, DMAC_REQN_I2SAC97TX}, {
++ 0x04, DMAC_REQN_UART2RX, DMAC_REQN_UART2RX}, {
++ 0x05, DMAC_REQN_UART2TX, DMAC_REQN_UART2TX}, {
++ 0x06, DMAC_REQN_UART1RX, DMAC_REQN_UART1RX}, {
++ 0x07, DMAC_REQN_UART1TX, DMAC_REQN_UART1TX}, {
++ 0x08, DMAC_REQN_SDC, DMAC_REQN_SDC}, {
++ 0x09, DMAC_REQN_CFC, DMAC_REQN_CFC}, {
++ 0x0a, DMAC_REQN_LPCREQ0, DMAC_REQN_LPCREQ0}, {
++ 0x0b, DMAC_REQN_LPCREQ1, DMAC_REQN_LPCREQ1}, {
++ 0x0c, DMAC_REQN_LPCREQ2, DMAC_REQN_LPCREQ2}, {
++ 0x0d, DMAC_REQN_LPCREQ3, DMAC_REQN_LPCREQ3}, {
++ 0x0e, 0, 0}, {
++0x0f, DMAC_REQN_LPCREQ5, DMAC_REQN_LPCREQ5},};
++#endif
++#else /* CONFIG_PLAT_AG102 */
++
++/* AHB DMAC channel re-route table. Indexed by AHB DMAC req/ack number. */
++static DMAD_AHB_CH_ROUTE ahb_ch_route_table[] = {
++ {0x00, 0, 0},
++ {0x01, PMU_CFC_REQACK_CFG, PMU_CFC_REQACK_CFG},
++ {0x02, PMU_SSP1_REQACK_CFG, PMU_SSP1_REQACK_CFG},
++ {0x03, PMU_UART1RX_REQACK_CFG, PMU_UART1TX_REQACK_CFG},
++ {0x04, PMU_UART1TX_REQACK_CFG, PMU_UART1RX_REQACK_CFG},
++ {0x05, PMU_UART2RX_REQACK_CFG, PMU_UART2TX_REQACK_CFG},
++ {0x06, PMU_UART2TX_REQACK_CFG, PMU_UART2RX_REQACK_CFG},
++ {0x07, PMU_SDC_REQACK_CFG, PMU_SDC_REQACK_CFG},
++ {0x08, PMU_I2SAC97RX_REQACK_CFG, PMU_I2SAC97TX_REQACK_CFG},
++ {0x09, 0, 0},
++ {0x0a, PMU_I2SAC97TX_REQACK_CFG, PMU_I2SAC97RX_REQACK_CFG},
++ {0x0b, PMU_USB_REQACK_CFG, PMU_USB_REQACK_CFG},
++ {0x0c, 0, 0},
++ {0x0d, 0, 0},
++ {0x0e, PMU_EXT0_REQACK_CFG, PMU_EXT0_REQACK_CFG},
++ {0x0f, PMU_EXT1_REQACK_CFG, PMU_EXT1_REQACK_CFG},
++};
++
++#endif /* CONFIG_PLAT_AG102 */
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++
++/* system irq number (per channel, ahb) */
++static const unsigned int ahb_irqs[DMAD_AHB_MAX_CHANNELS] = {
++ DMAC_FTDMAC020_0_IRQ0,
++ DMAC_FTDMAC020_0_IRQ1,
++ DMAC_FTDMAC020_0_IRQ2,
++ DMAC_FTDMAC020_0_IRQ3,
++ DMAC_FTDMAC020_0_IRQ4,
++ DMAC_FTDMAC020_0_IRQ5,
++ DMAC_FTDMAC020_0_IRQ6,
++ DMAC_FTDMAC020_0_IRQ7,
++};
++
++#endif /* CONFIG_PLATFORM_AHBDMA */
++
++#ifdef CONFIG_PLATFORM_APBDMA
++
++/* APB Bridge DMA request number re-route table */
++typedef struct _DMAD_APB_REQN_ROUTE {
++ u32 apb_reqn; /* APB device req/gnt number */
++ u32 ahb_reqn_tx; /* AHB DMAC req/ack number (tx) */
++ u32 ahb_reqn_rx; /* AHB DMAC req/ack number (rx) */
++ u32 bus_sel; /* APBBR_ADDRSEL_APB(0) or APBBR_ADDRSEL_AHB(1) */
++} DMAD_APB_REQN_ROUTE;
++
++#ifdef CONFIG_PLAT_AG102
++
++/* APB Bridge DMA request number re-route table. Indexed by APB DMA req/gnt
++ * number. */
++static DMAD_APB_REQN_ROUTE apb_reqn_route_table[] = {
++ {0x00, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x01, DMAC_REQN_CFC, DMAC_REQN_CFC, APBBR_ADDRSEL_APB},
++ {0x02, 0x00, 0x00, APBBR_ADDRSEL_APB},
++ {0x03, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x04, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ //MOD by river 2010.10.20
++ {0x05, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ //End MOD by river 2010.10.20
++ {0x06, DMAC_REQN_I2SAC97TX, DMAC_REQN_I2SAC97RX, APBBR_ADDRSEL_APB},
++ {0x07, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ //MOD by river 2010.10.20
++ {0x08, DMAC_REQN_SDC, DMAC_REQN_SDC, APBBR_ADDRSEL_APB},
++ //End MOD by river 2010.10.20
++ {0x09, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x0a, DMAC_REQN_UART2TX, DMAC_REQN_UART2RX, APBBR_ADDRSEL_APB},
++ {0x0b, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x0c, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x0d, DMAC_REQN_I2SAC97TX, DMAC_REQN_I2SAC97RX, APBBR_ADDRSEL_APB},
++ {0x0e, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x0f, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++};
++
++#else /* CONFIG_PLAT_AG102 */
++
++/* APB Bridge DMA request number re-route table. Indexed by APB DMA req/gnt
++ * number. */
++static DMAD_APB_REQN_ROUTE apb_reqn_route_table[] = {
++ {0x00, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x01, DMAC_REQN_CFC, DMAC_REQN_CFC, APBBR_ADDRSEL_APB},
++ {0x02, DMAC_REQN_SSP, DMAC_REQN_SSP, APBBR_ADDRSEL_APB},
++ {0x03, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x04, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x05, DMAC_REQN_SDC, DMAC_REQN_SDC, APBBR_ADDRSEL_APB},
++ {0x06, DMAC_REQN_I2SAC97TX, DMAC_REQN_I2SAC97RX, APBBR_ADDRSEL_APB},
++/* for amerald
++ { 0x07, 0x00, 0x00, APBBR_ADDRSEL_AHB },*/
++ {0x07, APBBR_REQN_SDC_AMERALD, APBBR_REQN_SDC_AMERALD,
++ APBBR_ADDRSEL_AHB},
++/* for amerald ac97
++ { 0x08, 0x00, 0x00, APBBR_ADDRSEL_AHB }, */
++ {0x08, APBBR_REQN_I2SAC97TX_AMERALD, APBBR_REQN_I2SAC97TX_AMERALD,
++ APBBR_ADDRSEL_APB},
++ {0x09, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x0a, DMAC_REQN_UART2TX, DMAC_REQN_UART2RX, APBBR_ADDRSEL_APB},
++ {0x0b, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x0c, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x0d, DMAC_REQN_I2SAC97TX, DMAC_REQN_I2SAC97RX, APBBR_ADDRSEL_APB},
++ {0x0e, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++ {0x0f, 0x00, 0x00, APBBR_ADDRSEL_AHB},
++};
++
++#endif /* CONFIG_PLAT_AG102 */
++
++/* system irq number (per channel, apb) */
++static const unsigned int apb_irqs[DMAD_APB_MAX_CHANNELS] = {
++ APBBRG_FTAPBBRG020S_0_IRQ0,
++ APBBRG_FTAPBBRG020S_0_IRQ1,
++ APBBRG_FTAPBBRG020S_0_IRQ2,
++ APBBRG_FTAPBBRG020S_0_IRQ3,
++};
++
++#endif
++
++/* Driver data structure, one instance per system */
++typedef struct DMAD_DATA_STRUCT {
++ /* Driver data initialization flag */
++
++ /* DMA queue pool access control object */
++ spinlock_t drq_pool_lock;
++
++ /* DMA queue base address, to ease alloc/free flow */
++ dmad_drq *drq_pool;
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ /* DMA queue for AHB DMA channels */
++ dmad_drq *ahb_drq_pool;
++#endif
++
++#ifdef CONFIG_PLATFORM_APBDMA
++ /* DMA queue for APB DMA channels */
++ dmad_drq *apb_drq_pool;
++#endif
++
++} DMAD_DATA;
++
++/* Driver data structure instance, one instance per system */
++static DMAD_DATA dmad __attribute__ ((aligned(4))) = {
++ .drq_pool_lock = __SPIN_LOCK_UNLOCKED(dmad.drq_pool_lock),
++// .drq_pool_lock = SPIN_LOCK_UNLOCKED,
++ .drq_pool = 0,
++#ifdef CONFIG_PLATFORM_AHBDMA
++ .ahb_drq_pool = 0,
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ .apb_drq_pool = 0,
++#endif
++};
++
++/**
++ * dmad_next_drb - static function
++ * @drb_pool : [in] The raw DRB pool of a DMA channel
++ * @node : [in] The node number to lookup its next node
++ * @drb : [out] The drb next to the "node" node number
++ *
++ * Lookup next DRB of the specified node number. "drb" is null if reaches end
++ * of the list.
++ */
++static inline void dmad_next_drb(dmad_drb * drb_pool, u32 node, dmad_drb ** drb)
++{
++ if (likely(drb_pool[node].next != 0))
++ *drb = &drb_pool[drb_pool[node].next];
++ else
++ *drb = 0;
++}
++
++/**
++ * dmad_prev_drb - static function
++ * @drb_pool : [in] The raw DRB pool of a DMA channel
++ * @node : [in] The node number to lookup its previous node
++ * @drb : [out] The drb previous to the "node" node number
++ *
++ * Lookup previous DRB of the specified node number. "drb" is null if reaches
++ * head-end of the list.
++ */
++static inline void dmad_prev_drb(dmad_drb * drb_pool, u32 node, dmad_drb ** drb)
++{
++ if (unlikely(drb_pool[node].prev != 0))
++ *drb = &drb_pool[drb_pool[node].prev];
++ else
++ *drb = 0;
++}
++
++/**
++ * dmad_detach_node - static function
++ * @drb_pool : [in] The raw DRB pool of a DMA channel
++ * @head : [in/out] Reference to the head node number
++ * @tail : [in/out] Reference to the tail node number
++ * @node : [in] The node to be dettached from the queue
++ *
++ * Detached a DRB specified by the node number from the queue. The head and
++ * tail records will be updated accordingly.
++ */
++static inline void dmad_detach_node(dmad_drb * drb_pool,
++ u32 * head, u32 * tail, u32 node)
++{
++ if (likely(drb_pool[node].prev != 0)) {
++ /* prev->next = this->next (= 0, if this is a tail) */
++ drb_pool[drb_pool[node].prev].next = drb_pool[node].next;
++ } else {
++ /* this node is head, move head to next node
++ * (= 0, if this is the only one node) */
++ *head = drb_pool[node].next;
++ }
++
++ if (unlikely(drb_pool[node].next != 0)) {
++ /* next->prev = this->prev (= 0, if this is a head) */
++ drb_pool[drb_pool[node].next].prev = drb_pool[node].prev;
++ } else {
++ /* this node is tail, move tail to previous node
++ * (= 0, if this is the only one node) */
++ *tail = drb_pool[node].prev;
++ }
++
++ drb_pool[node].prev = drb_pool[node].next = 0;
++}
++
++/**
++ * dmad_detach_head - static function
++ * @drb_pool : [in] The raw DRB pool of a DMA channel
++ * @head : [in/out] Reference to the head node number
++ * @tail : [in/out] Reference to the tail node number
++ * @drb : [out] The detached head node; null if the queue is empty
++ *
++ * Detached a DRB from the head of the queue. The head and tail records will
++ * be updated accordingly.
++ */
++static inline void dmad_detach_head(dmad_drb * drb_pool,
++ u32 * head, u32 * tail, dmad_drb ** drb)
++{
++ if (unlikely(*head == 0)) {
++ *drb = NULL;
++ return;
++ }
++
++ *drb = &drb_pool[*head];
++
++ if (likely((*drb)->next != 0)) {
++ /* next->prev = this->prev (= 0, if this is a head) */
++ drb_pool[(*drb)->next].prev = 0;
++
++ /* prev->next = this->next (do nothing, if this is a head) */
++
++ /* head = this->next */
++ *head = (*drb)->next;
++ } else {
++ /* head = tail = 0 */
++ *head = 0;
++ *tail = 0;
++ }
++
++ /* this->prev = this->next = 0 (do nothing, if save code size) */
++ (*drb)->prev = (*drb)->next = 0;
++}
++
++/**
++ * dmad_get_head - static function
++ * @drb_pool : [in] The raw DRB pool of a DMA channel
++ * @head : [in/out] Reference to the head node number
++ * @tail : [in/out] Reference to the tail node number
++ * @drb : [out] The head node; null if the queue is empty
++ *
++ * Get a DRB from the head of the queue. The head and tail records remain
++ * unchanged.
++ */
++static inline void dmad_get_head(dmad_drb * drb_pool, const u32 * head,
++ const u32 * tail, dmad_drb ** drb)
++{
++ if (unlikely(*head == 0)) {
++ *drb = NULL;
++ return;
++ }
++
++ *drb = &drb_pool[*head];
++}
++
++/**
++ * dmad_detach_tail - static function
++ * @drb_pool : [in] The raw DRB pool of a DMA channel
++ * @head : [in/out] Reference to the head node number
++ * @tail : [in/out] Reference to the tail node number
++ * @drb : [out] The tail node; null if the queue is empty
++ *
++ * Detached a DRB from the head of the queue. The head and tail records will
++ * be updated accordingly.
++ */
++static inline void dmad_detach_tail(dmad_drb * drb_pool,
++ u32 * head, u32 * tail, dmad_drb ** drb)
++{
++ if (unlikely(*tail == 0)) {
++ *drb = NULL;
++ return;
++ }
++
++ *drb = &drb_pool[*tail];
++
++ if (likely((*drb)->prev != 0)) {
++ /* prev->next = this->next (= 0, if this is a tail) */
++ drb_pool[(*drb)->prev].next = 0;
++
++ /* next->prev = this->prev (do nothing, if this is a tail) */
++
++ /* tail = this->prev */
++ *tail = (*drb)->prev;
++ } else {
++ /* head = tail = 0 */
++ *head = 0;
++ *tail = 0;
++ }
++
++ /* this->next = this->prev = 0 (do nothing, if save code size) */
++ (*drb)->prev = (*drb)->next = 0;
++}
++
++/**
++ * dmad_get_tail - static function
++ * @drb_pool : [in] The raw DRB pool of a DMA channel
++ * @head : [in/out] Reference to the head node number
++ * @tail : [in/out] Reference to the tail node number
++ * @drb : [out] The tail node; null if the queue is empty
++ *
++ * Get a DRB from the tail of the queue. The head and tail records remain
++ * unchanged.
++ */
++static inline void dmad_get_tail(dmad_drb * drb_pool,
++ u32 * head, u32 * tail, dmad_drb ** drb)
++{
++ if (unlikely(*tail == 0)) {
++ *drb = NULL;
++ return;
++ }
++
++ *drb = &drb_pool[*tail];
++}
++
++/**
++ * dmad_attach_head - static function
++ * @drb_pool : [in] The raw DRB pool of a DMA channel
++ * @head : [in/out] Reference to the head node number
++ * @tail : [in/out] Reference to the tail node number
++ * @node : [in] The node to be attached
++ *
++ * Attach a DRB node to the head of the queue. The head and tail records will
++ * be updated accordingly.
++ */
++static inline void dmad_attach_head(dmad_drb * drb_pool,
++ u32 * head, u32 * tail, u32 node)
++{
++ if (likely(*head != 0)) {
++ /* head->prev = this */
++ drb_pool[*head].prev = node;
++
++ /* this->next = head */
++ drb_pool[node].next = *head;
++ /* this->prev = 0 */
++ drb_pool[node].prev = 0;
++
++ /* head = node */
++ *head = node;
++ } else {
++ /* head = tail = node */
++ *head = *tail = node;
++ drb_pool[node].prev = drb_pool[node].next = 0;
++ }
++}
++
++/**
++ * dmad_attach_head - static function
++ * @drb_pool : [in] The raw DRB pool of a DMA channel
++ * @head : [in/out] Reference to the head node number
++ * @tail : [in/out] Reference to the tail node number
++ * @node : [in] The node to be attached
++ *
++ * Attach a DRB node to the tail of the queue. The head and tail records will
++ * be updated accordingly.
++ */
++static inline void dmad_attach_tail(dmad_drb * drb_pool,
++ u32 * head, u32 * tail, u32 node)
++{
++ if (likely(*tail != 0)) {
++ /* tail->next = this */
++ drb_pool[*tail].next = node;
++
++ /* this->prev = tail */
++ drb_pool[node].prev = *tail;
++ /* this->next = 0 */
++ drb_pool[node].next = 0;
++
++ /* tail = node */
++ *tail = node;
++ } else {
++ /* head = tail = node */
++ *head = *tail = node;
++ drb_pool[node].prev = drb_pool[node].next = 0;
++ }
++}
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++
++/**
++ * dmad_ahb_isr - AHB DMA interrupt service routine
++ *
++ * @irq : [in] The irq number
++ * @dev_id : [in] The identifier to identify the asserted channel
++ *
++ * This is the ISR that services all AHB DMA channels.
++ */
++static irqreturn_t dmad_ahb_isr(int irq, void *dev_id)
++{
++ dmad_drq *drq;
++ dmad_drb *drb, *drb_iter;
++ u32 channel = ((u32) dev_id) - 1;
++ u8 tc_int = 0;
++ u8 err_int = 0;
++ u8 abt_int = 0;
++ u8 cpl_events = 1;
++
++ dmad_dbg("%s() >> channel(%d)\n", __func__, channel);
++
++ if (channel >= DMAD_AHB_MAX_CHANNELS) {
++ dmad_err("%s() invlaid channel number: %d!\n",
++ __func__, channel);
++ return IRQ_HANDLED;
++ }
++
++ /* Fetch channel's DRQ struct (DMA Request Queue) */
++ drq = (dmad_drq *) & dmad.ahb_drq_pool[channel];
++
++ /* Check DMA status register to get channel number */
++ if (likely(getbl(channel, DMAC_INT_TC))) {
++
++ /* Mark as TC int */
++ tc_int = 1;
++
++ /* DMAC INT TC status clear */
++ setbl(channel, DMAC_INT_TC_CLR);
++
++ } else if (getbl(channel + DMAC_INT_ERR_SHIFT, DMAC_INT_ERRABT)) {
++
++ /* Mark as ERR int */
++ err_int = 1;
++
++ /* DMAC INT ERR status clear */
++ setbl(channel + DMAC_INT_ERR_CLR_SHIFT, DMAC_INT_ERRABT_CLR);
++
++ } else if (getbl(channel + DMAC_INT_ABT_SHIFT, DMAC_INT_ERRABT)) {
++
++ /* Mark as ABT int */
++ abt_int = 1;
++
++ /* DMAC INT ABT status clear */
++ setbl(channel + DMAC_INT_ABT_CLR_SHIFT, DMAC_INT_ERRABT_CLR);
++
++ } else {
++
++ dmad_err("%s() possible false-fired ahb dma int,"
++ "channel %d status-reg: tc(0x%08x) arrabt(0x%08x)\n",
++ __func__, channel,
++ inl(DMAC_INT_TC), inl(DMAC_INT_ERRABT_CLR));
++
++ /* Stop DMA channel (make sure the channel will be stopped) */
++ clrbl(DMAC_CSR_CH_EN_BIT, drq->channel_base + DMAC_CSR_OFFSET);
++
++ return IRQ_HANDLED;
++ }
++
++ /* DMAC
++ * Stop DMA channel temporarily */
++ dmad_disable_channel(drq);
++
++ spin_lock(&drq->drb_pool_lock);
++
++ /* Lookup/detach latest submitted DRB (DMA Request Block) from
++ * the DRQ (DMA Request Queue), so ISR could kick off next DRB */
++ dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb);
++ if (drb == NULL) {
++ spin_unlock(&drq->drb_pool_lock);
++ /* submitted list could be empty if client cancel all requests
++ * of the channel. */
++ return IRQ_HANDLED;
++ }
++
++ /* release blocking of drb-allocation, if any ... */
++ if (unlikely((drq->fre_head == 0) &&
++ (drq->flags & DMAD_FLAGS_SLEEP_BLOCK))) {
++ complete_all(&drq->drb_alloc_sync);
++ }
++
++ /* Process DRBs according to interrupt reason */
++ if (tc_int) {
++
++ dmad_dbg("dma finish\n");
++
++ dmad_dbg("finish drb(%d 0x%08x) addr0(0x%08x) "
++ "addr1(0x%08x) size(0x%08x)\n",
++ drb->node, (u32) drb, drb->src_addr,
++ drb->dst_addr, drb->req_cycle);
++
++ if (drb->req_cycle == 0)
++ cpl_events = 0;
++
++ // Mark DRB state as completed
++ drb->state = DMAD_DRB_STATE_COMPLETED;
++ if (cpl_events && drb->sync)
++ complete_all(drb->sync);
++
++ dmad_attach_tail(drq->drb_pool, &drq->fre_head,
++ &drq->fre_tail, drb->node);
++
++ // Check whether there are pending requests in the DRQ
++ if (drq->sbt_head != 0) {
++
++ // Lookup next DRB (DMA Request Block)
++ drb_iter = &drq->drb_pool[drq->sbt_head];
++
++ dmad_dbg("exec drb(%d 0x%08x) addr0(0x%08x) "
++ "addr1(0x%08x) size(0x%08x)\n",
++ drb_iter->node, (u32) drb_iter,
++ drb_iter->src_addr, drb_iter->dst_addr,
++ drb_iter->req_cycle);
++
++ // Kick-off DMA for next DRB
++ // - Source and destination address
++ if (drq->flags & DMAD_DRQ_DIR_A1_TO_A0) {
++ outl(drb_iter->addr1, drq->src_port);
++ outl(drb_iter->addr0, drq->dst_port);
++ } else {
++ outl(drb_iter->addr0, drq->src_port);
++ outl(drb_iter->addr1, drq->dst_port);
++ }
++
++ /* - Transfer size (in units of source width) */
++ outl(drb_iter->req_cycle, drq->cyc_port);
++
++ /* Kick off next request */
++ dmad_enable_channel(drq);
++
++ drb_iter->state = DMAD_DRB_STATE_EXECUTED;
++
++ } else {
++ /* No pending requests, keep the DMA channel stopped */
++ }
++
++ } else {
++
++ dmad_err("%s() ahb dma channel %d error!\n", __func__, channel);
++
++ /* Zero out src, dst, and size */
++ outl(0, drq->src_port);
++ outl(0, drq->dst_port);
++ outl(0, drq->cyc_port);
++
++ /* Remove all pending requests in the queue */
++ drb_iter = drb;
++ while (drb_iter) {
++
++ dmad_err("abort drb(%d 0x%08x) addr0(0x%08x) "
++ "addr1(0x%08x) size(0x%08x)\n",
++ drb_iter->node, (u32) drb_iter,
++ drb_iter->src_addr, drb_iter->dst_addr,
++ drb_iter->req_cycle);
++
++ if (drb_iter->req_cycle == 0)
++ cpl_events = 0;
++
++ /* Mark DRB state as abort */
++ drb_iter->state = DMAD_DRB_STATE_ABORT;
++
++ if (cpl_events && drb_iter->sync)
++ complete_all(drb_iter->sync);
++
++ dmad_attach_tail(drq->drb_pool, &drq->fre_head,
++ &drq->fre_tail, drb_iter->node);
++
++ /* Detach next submitted DRB (DMA Request Block)
++ * from the DRQ (DMA Request Queue) */
++ dmad_detach_head(drq->drb_pool, &drq->sbt_head,
++ &drq->sbt_tail, &drb_iter);
++ }
++ }
++
++ spin_unlock(&drq->drb_pool_lock);
++
++ /* dispatch interrupt-context level callbacks */
++ if (cpl_events && drq->completion_cb) {
++ /* signal DMA driver that new node is available */
++ drq->completion_cb(channel, tc_int, drq->completion_data);
++ }
++
++ dmad_dbg("%s() <<\n", __func__);
++
++ return IRQ_HANDLED;
++}
++
++/**
++ * dmad_ahb_config_dir - prepare command reg according to tx direction
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @channel_cmds : [out] Reference to array of command words to be prepared with
++ * @return : none
++ *
++ * Prepare command registers according to transfer direction ...
++ * channel_cmd[0] DMAC_CSR
++ * channel_cmd[1] DMAC_CFG
++ *
++ * This function only serves as local helper. No protection wrappers.
++ */
++static void dmad_ahb_config_dir(dmad_chreq * ch_req, addr_t * channel_cmds)
++{
++ dmad_drq *drq = (dmad_drq *) ch_req->drq;
++ dmad_ahb_chreq *ahb_req = (dmad_ahb_chreq *) (&ch_req->ahb_req);
++/* for amerald */
++ u32 reqn0, reqn1;
++ dmad_dbg("%s() channel_cmds(0x%08x, 0x%08x)\n",
++ __func__, channel_cmds[0], channel_cmds[1]);
++/* for amerald */
++ if ((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID) {
++ reqn0 = ahb_req->addr0_reqn;
++ reqn1 = ahb_req->addr1_reqn;
++ } else {
++ reqn0 = ch_req->channel;
++ reqn1 = ch_req->channel;
++ }
++ channel_cmds[0] &= ~(addr_t)
++ (DMAC_CSR_SRC_WIDTH_MASK | DMAC_CSR_SRCAD_CTL_MASK |
++ DMAC_CSR_DST_WIDTH_MASK | DMAC_CSR_DSTAD_CTL_MASK |
++ DMAC_CSR_MODE_MASK);
++ channel_cmds[1] &= ~(addr_t)
++ (DMAC_CFG_INT_SRC_RS_MASK | DMAC_CFG_INT_SRC_HE_MASK |
++ DMAC_CFG_INT_DST_RS_MASK | DMAC_CFG_INT_DST_HE_MASK);
++
++ /* 0 - addr0 to addr1; 1 - addr1 to addr0 */
++ if (ahb_req->tx_dir == 0) {
++
++ dmad_dbg("%s() addr0 --> addr1\n", __func__);
++
++ /* - Channel CSR
++ * DST_SEL : 0 (Master 0)
++ * SRC_SEL : 0 (Master 0)
++ * DSTAD_CTL : ahb_req->dst_ctrl
++ * SRCAD_CTL : ahb_req->src_ctrl
++ * MODE : 0 (normal)
++ * DST_WIDTH : ahb_req->dst_width
++ * SRC_WIDTH : ahb_req->src_width
++ * SRC_SIZE : 0 (burst size = 1 byte)
++ */
++ channel_cmds[0] |=
++ (((ahb_req->addr0_width << DMAC_CSR_SRC_WIDTH_SHIFT) &
++ DMAC_CSR_SRC_WIDTH_MASK) |
++ ((ahb_req->addr0_ctrl << DMAC_CSR_SRCAD_CTL_SHIFT) &
++ DMAC_CSR_SRCAD_CTL_MASK) |
++ ((ahb_req->addr1_width << DMAC_CSR_DST_WIDTH_SHIFT) &
++ DMAC_CSR_DST_WIDTH_MASK) |
++ ((ahb_req->addr1_ctrl << DMAC_CSR_DSTAD_CTL_SHIFT) &
++ DMAC_CSR_DSTAD_CTL_MASK));
++
++ /* - Channel CFG
++ * SRC_RS : channel number (not reqn)
++ * SRC_HE : 0 if memory, 1 if device
++ * DST_RS : channel number (not reqn)
++ * DST_HE : 0 if memory, 1 if device
++ */
++ if (likely(ahb_req->hw_handshake != 0)) {
++ /* Channel CSR - Enable HW-handshake mode */
++ channel_cmds[0] |= DMAC_CSR_MODE_MASK;
++
++ /* Channel CFG - Device REQN and HW-handshake mode */
++#ifdef CONFIG_PLAT_AG102
++ /* AG102 fixes this bug */
++ if (ahb_req->addr0_reqn != DMAC_REQN_NONE) {
++ channel_cmds[1] |= (DMAC_CFG_INT_SRC_HE_MASK |
++ ((ahb_req->addr0_reqn <<
++ DMAC_CFG_INT_SRC_RS_SHIFT)
++ &
++ DMAC_CFG_INT_SRC_RS_MASK));
++ }
++
++ if (ahb_req->addr1_reqn != DMAC_REQN_NONE) {
++ channel_cmds[1] |= (DMAC_CFG_INT_DST_HE_MASK |
++ ((ahb_req->addr1_reqn <<
++ DMAC_CFG_INT_DST_RS_SHIFT)
++ &
++ DMAC_CFG_INT_DST_RS_MASK));
++ }
++#else
++ /* AG101/XC5 bug */
++/* for amerald */
++ if (ahb_req->addr0_reqn != DMAC_REQN_NONE) {
++ channel_cmds[1] |= (DMAC_CFG_INT_SRC_HE_MASK |
++ ((reqn0 <<
++ DMAC_CFG_INT_SRC_RS_SHIFT)
++ &
++ DMAC_CFG_INT_SRC_RS_MASK));
++ }
++
++ if (ahb_req->addr1_reqn != DMAC_REQN_NONE) {
++ channel_cmds[1] |= (DMAC_CFG_INT_DST_HE_MASK |
++ ((reqn1 <<
++ DMAC_CFG_INT_DST_RS_SHIFT)
++ &
++ DMAC_CFG_INT_DST_RS_MASK));
++ }
++#endif
++ }
++
++ /* update source data width for faster cycle/byte size conversion */
++ drq->data_width = ahb_req->addr0_width;
++
++ /* remember channel transfer direction */
++ drq->flags &= ~(addr_t) DMAD_DRQ_DIR_A1_TO_A0;
++
++ } else {
++
++ dmad_dbg("%s() addr0 <-- addr1\n", __func__);
++
++ /* - Channel CSR
++ * DST_SEL : 0 (Master 0)
++ * SRC_SEL : 0 (Master 0)
++ * DSTAD_CTL : ahb_req->dst_ctrl
++ * SRCAD_CTL : ahb_req->src_ctrl
++ * MODE : 0 (normal)
++ * DST_WIDTH : ahb_req->dst_width
++ * SRC_WIDTH : ahb_req->src_width
++ * SRC_SIZE : 0 (burst size = 1 byte)
++ */
++ channel_cmds[0] |=
++ (((ahb_req->addr1_width << DMAC_CSR_SRC_WIDTH_SHIFT) &
++ DMAC_CSR_SRC_WIDTH_MASK) |
++ ((ahb_req->addr1_ctrl << DMAC_CSR_SRCAD_CTL_SHIFT) &
++ DMAC_CSR_SRCAD_CTL_MASK) |
++ ((ahb_req->addr0_width << DMAC_CSR_DST_WIDTH_SHIFT) &
++ DMAC_CSR_DST_WIDTH_MASK) |
++ ((ahb_req->addr0_ctrl << DMAC_CSR_DSTAD_CTL_SHIFT) &
++ DMAC_CSR_DSTAD_CTL_MASK));
++
++ /* - Channel CFG
++ * SRC_RS : channel number (not reqn)
++ * SRC_HE : 0 if memory, 1 if device
++ * DST_RS : channel number (not reqn)
++ * DST_HE : 0 if memory, 1 if device
++ */
++ if (likely(ahb_req->hw_handshake != 0)) {
++ /* Channel CSR - Enable HW-handshake mode */
++ channel_cmds[0] |= DMAC_CSR_MODE_MASK;
++
++ /* Channel CFG - Device REQN and HW-handshake mode */
++#ifdef CONFIG_PLAT_AG102
++ /* AG102 fixes this bug */
++ if (ahb_req->addr1_reqn != DMAC_REQN_NONE) {
++ channel_cmds[1] |= (DMAC_CFG_INT_SRC_HE_MASK |
++ ((ahb_req->addr1_reqn <<
++ DMAC_CFG_INT_SRC_RS_SHIFT)
++ &
++ DMAC_CFG_INT_SRC_RS_MASK));
++ }
++
++ if (ahb_req->addr0_reqn != DMAC_REQN_NONE) {
++ channel_cmds[1] |= (DMAC_CFG_INT_DST_HE_MASK |
++ ((ahb_req->addr0_reqn <<
++ DMAC_CFG_INT_DST_RS_SHIFT)
++ &
++ DMAC_CFG_INT_DST_RS_MASK));
++ }
++#else
++ /* AG101/XC5 bug */
++/* for amerald */
++ if (ahb_req->addr1_reqn != DMAC_REQN_NONE) {
++ channel_cmds[1] |= (DMAC_CFG_INT_SRC_HE_MASK |
++ ((reqn1 <<
++ DMAC_CFG_INT_SRC_RS_SHIFT)
++ &
++ DMAC_CFG_INT_SRC_RS_MASK));
++ }
++
++ if (ahb_req->addr0_reqn != DMAC_REQN_NONE) {
++ channel_cmds[1] |= (DMAC_CFG_INT_DST_HE_MASK |
++ ((reqn0 <<
++ DMAC_CFG_INT_DST_RS_SHIFT)
++ &
++ DMAC_CFG_INT_DST_RS_MASK));
++ }
++#endif
++ }
++
++ /* source data width */
++ drq->data_width = ahb_req->addr1_width;
++
++ /* remember channel transfer direction */
++ drq->flags |= (addr_t) DMAD_DRQ_DIR_A1_TO_A0;
++ }
++
++ dmad_dbg("%s() channel_cmds(0x%08x, 0x%08x)\n",
++ __func__, channel_cmds[0], channel_cmds[1]);
++}
++
++/**
++ * dmad_ahb_init - initialize a ahb dma channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @return : 0 if success, non-zero if any error
++ *
++ * Register AHB DMA ISR and performs hw initialization for the given DMA
++ * channel.
++ */
++static int dmad_ahb_init(dmad_chreq * ch_req)
++{
++ int err = 0;
++ dmad_drq *drq = (dmad_drq *) ch_req->drq;
++ dmad_ahb_chreq *ahb_req = (dmad_ahb_chreq *) (&ch_req->ahb_req);
++ u32 channel = (u32) ch_req->channel;
++ addr_t channel_base = drq->channel_base;
++ addr_t channel_cmds[2]; // [0] DMAC_CSR; [1] DMAC_CFG
++ unsigned long lock_flags;
++
++ dmad_dbg("%s()\n", __func__);
++
++ /* register interrupt handler */
++ err = request_irq(ahb_irqs[channel], dmad_ahb_isr, 0,
++ "AHB_DMA", (void *)(channel + 1));
++ if (unlikely(err != 0)) {
++ dmad_err("unable to request IRQ %d for AHB DMA "
++ "(error %d)\n", ahb_irqs[channel], err);
++ free_irq(ahb_irqs[channel], (void *)(channel + 1));
++ return err;
++ }
++
++ spin_lock_irqsave(&dmad.drq_pool_lock, lock_flags);
++
++ /**********************************************************
++ * Following code require _safe_exit return path
++ */
++
++#ifdef CONFIG_PLAT_AG102
++ /* PCU
++ *
++ * Add by Dennis 2011.03.09
++ * set 0 to dma selection register to using AHB
++ * DMA.
++ */
++ if (ahb_req->dst_reqn == ahb_req->src_reqn) {
++ dmad_err
++ ("[dmad] invalid source reqn(%d) or destination reqn(%d)\n",
++ ahb_req->src_reqn, ahb_req->dst_reqn);
++ err = -EBADR;
++ goto _safe_exit;
++ }
++ outl(0, PCU_DMA_SEL);
++#else /* CONFIG_PLAT_AG102 */
++
++ /* PMU
++ *
++ * Route APB device DMA to an AHB DMAC channel and specify the channel
++ * number. (connection status could be read back from PMU_AHBDMA_REQACK
++ * register)
++ *
++ * Note: Only one device is routed per AHB DMA channel, the other target
++ * should be either (1) the same device (same reqn), or (2) the AHB
++ * device (reqn = 0).
++ */
++
++ if (ahb_req->dst_reqn != DMAC_REQN_NONE) {
++ // DMA transfer to device
++ if ((ahb_req->dst_reqn > DMAC_REQN_MAX) ||
++ (ahb_ch_route_table[ahb_req->dst_reqn].route_cr == 0)) {
++ dmad_err("Invalid destination reqn(%d) "
++ "or route_cr(0x%08x)\n", ahb_req->dst_reqn,
++ (u32) ahb_ch_route_table[ahb_req->dst_reqn].
++ route_cr);
++ err = -EBADR;
++ goto _safe_exit;
++ }
++
++ outl(0, ahb_ch_route_table[ahb_req->dst_reqn].clear_cr);
++ outl(PMU_DMACUSED_MASK | ((channel << PMU_CHANNEL_SHIFT) &
++ PMU_CHANNEL_MASK),
++ ahb_ch_route_table[ahb_req->dst_reqn].route_cr);
++
++ } else if (ahb_req->src_reqn != DMAC_REQN_NONE) {
++
++ // DMA transfer from device
++ if ((ahb_req->src_reqn > DMAC_REQN_MAX) ||
++ (ahb_ch_route_table[ahb_req->src_reqn].route_cr == 0)) {
++ dmad_err("Invalid source reqn(%d) or "
++ "route_cr(0x%08x)\n", ahb_req->src_reqn,
++ (u32) ahb_ch_route_table[ahb_req->src_reqn].
++ route_cr);
++ err = -EBADR;
++ goto _safe_exit;
++ }
++
++ outl(0, ahb_ch_route_table[ahb_req->src_reqn].clear_cr);
++ outl(PMU_DMACUSED_MASK | ((channel << PMU_CHANNEL_SHIFT) &
++ PMU_CHANNEL_MASK),
++ ahb_ch_route_table[ahb_req->src_reqn].route_cr);
++ }
++#endif /* CONFIG_PLAT_AG102 */
++
++ /* DMAC (Controller Setting) */
++
++ /* - INT TC/ERR/ABT status clear */
++ setbl(channel, DMAC_INT_TC_CLR);
++ setbl(channel + DMAC_INT_ERR_CLR_SHIFT, DMAC_INT_ERRABT_CLR);
++ setbl(channel + DMAC_INT_ABT_CLR_SHIFT, DMAC_INT_ERRABT_CLR);
++
++ // - CSR (enable DMAC, set M0 & M1 default to little endian)
++ outl(DMAC_DMACEN_MASK |
++ ((DMAC_ENDIAN_LITTLE << DMAC_M0ENDIAN_BIT) & DMAC_M0ENDIAN_MASK) |
++ ((DMAC_ENDIAN_LITTLE << DMAC_M1ENDIAN_BIT) & DMAC_M1ENDIAN_MASK),
++ DMAC_CSR);
++
++ /* DMAC (Channel-Specific Setting) */
++ /* - SYNC */
++ if (ahb_req->sync)
++ setbl(channel, DMAC_SYNC);
++ else
++ clrbl(channel, DMAC_SYNC);
++
++ /* - Channel CSR
++ * CH_EN : 0 (disable)
++ * DST_SEL : 0 (Master 0)
++ * SRC_SEL : 0 (Master 0)
++ * DSTAD_CTL : ahb_req->dst_ctrl
++ * SRCAD_CTL : ahb_req->src_ctrl
++ * MODE : 0 (normal)
++ * DST_WIDTH : ahb_req->dst_width
++ * SRC_WIDTH : ahb_req->src_width
++ * ABT : 0 (not abort)
++ * SRC_SIZE : 0 (burst size = 1 byte)
++ * PROT1 : 0 (user mode)
++ * PROT2 : 0 (bot bufferable)
++ * PROT3 : 0 (not cacheable)
++ * CHPRI : ahb_req->priority
++ * DMA_FF_TH : 0 (FIA320 only, threshold = 1)
++ * TC_MSK : 0 (TC counter status enable)
++ */
++ channel_cmds[0] = (ahb_req->priority << DMAC_CSR_CHPRI_SHIFT) &
++ DMAC_CSR_CHPRI_MASK;
++ channel_cmds[0] |= (ahb_req->burst_size << DMAC_CSR_SRC_SIZE_SHIFT) &
++ DMAC_CSR_SRC_SIZE_MASK;
++
++ // - Channel CFG
++ // INT_TC_MSK : 0 (enable TC int)
++ // INT_ERR_MSK : 0 (enable ERR int)
++ // INT_ABT_MSK : 0 (enable ABT int)
++ // SRC_RS : 0
++ // SRC_HE : 0
++ // BUSY : r/o
++ // DST_RS : 0
++ // DST_HE : 0
++ // LLP_CNT : r/o
++ channel_cmds[1] = 0;
++
++ if (0 ==
++ (ch_req->flags & (DMAD_FLAGS_RING_MODE | DMAD_FLAGS_BIDIRECTION)))
++ ahb_req->tx_dir = 0;
++
++ dmad_ahb_config_dir(ch_req, channel_cmds);
++
++ outl(channel_cmds[0], channel_base + DMAC_CSR_OFFSET);
++ outl(channel_cmds[1], channel_base + DMAC_CFG_OFFSET);
++
++ /* SRCADR and DESADR */
++ outl(0, (addr_t) drq->src_port);
++ outl(0, (addr_t) drq->dst_port);
++
++ /* CYC (transfer size) */
++ outl(0, (addr_t) drq->cyc_port);
++
++ /* LLP */
++ outl(0, channel_base + DMAC_LLP_OFFSET);
++
++ /* TOT_SIZE - not now */
++
++_safe_exit:
++
++ spin_unlock_irqrestore(&dmad.drq_pool_lock, lock_flags);
++
++ return err;
++}
++
++#endif /* CONFIG_PLATFORM_AHBDMA */
++
++#ifdef CONFIG_PLATFORM_APBDMA
++
++/**
++ * dmad_apb_isr - APB DMA interrupt service routine
++ *
++ * @irq : [in] The irq number
++ * @dev_id : [in] The identifier to identify the asserted channel
++ *
++ * This is the ISR that services all APB DMA channels.
++ */
++static irqreturn_t dmad_apb_isr(int irq, void *dev_id)
++{
++ dmad_drq *drq;
++ dmad_drb *drb, *drb_iter;
++ u32 channel = ((u32) dev_id) - 1;
++ u32 status;
++ u8 finish_int = 0;
++ u8 err_int = 0;
++ u8 cpl_events = 1;
++
++ dmad_dbg("%s() >> channel(%d)\n", __func__, channel);
++
++ if (channel >= DMAD_APB_MAX_CHANNELS) {
++ dmad_err("%s() invlaid channel number: %d!\n",
++ __func__, channel);
++ return IRQ_HANDLED;
++ }
++
++ /* Lookup channel's DRQ (DMA Request Queue) */
++ drq = (dmad_drq *) & dmad.apb_drq_pool[channel];
++
++ /* - Check DMA status register to get channel number */
++ status = inl((addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
++
++ if (likely(status & APBBR_DMA_FINTST_MASK)) {
++
++ /*dmad_dbg("apb dma int status: finish (0x%08x)\n", status); */
++ finish_int = 1;
++
++ /* APB DMA finish int status clear */
++ clrbl(APBBR_DMA_FINTST_BIT,
++ (addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
++
++ } else if (status & APBBR_DMA_ERRINTST_MASK) {
++
++ /* Perform DMA error checking if no valid channel was found
++ * who assert the finish signal. */
++ dmad_err("apb dma int status: err (0x%08x)\n", status);
++
++ /* Mark as error int */
++ err_int = 1;
++
++ /* APB DMA error int status clear */
++ clrbl(APBBR_DMA_ERRINTST_BIT,
++ (addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
++
++ } else {
++
++ dmad_err("%s() possible false-fired apb dma int,"
++ " channel %d status-reg: 0x%08x\n",
++ __func__, channel, status);
++
++ /* Stop DMA channel (make sure the channel will be stopped) */
++ clrbl(APBBR_DMA_CHEN_BIT,
++ (addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
++
++ return IRQ_HANDLED;
++ }
++
++ /* Stop DMA channel (make sure the channel will be stopped) */
++ dmad_disable_channel(drq);
++
++ spin_lock(&drq->drb_pool_lock);
++
++ /* Lookup/detach latest submitted DRB (DMA Request Block) from */
++ /* the DRQ (DMA Request Queue), so ISR could kick off next DRB */
++ dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb);
++
++ if (unlikely(drb == NULL)) {
++ spin_unlock(&drq->drb_pool_lock);
++ return IRQ_HANDLED;
++ }
++
++ /* release blocking of drb-allocation, if any ... */
++ if (unlikely((drq->fre_head == 0) &&
++ (drq->flags & DMAD_FLAGS_SLEEP_BLOCK))) {
++ complete_all(&drq->drb_alloc_sync);
++ }
++
++ /* Process DRBs according to the cause of this interrupt */
++ if (likely(finish_int)) {
++
++ if (drb->req_cycle == 0)
++ cpl_events = 0;
++
++ /* Mark DRB state as completed */
++ drb->state = DMAD_DRB_STATE_COMPLETED;
++ if (cpl_events && drb->sync)
++ complete_all(drb->sync);
++
++ dmad_attach_tail(drq->drb_pool, &drq->fre_head,
++ &drq->fre_tail, drb->node);
++
++ /* Check whether there are pending requests in the DRQ */
++ if (drq->sbt_head != 0) {
++
++ /* Lookup next DRB (DMA Request Block) */
++ drb_iter = &drq->drb_pool[drq->sbt_head];
++
++ dmad_dbg("exec drb(%d 0x%08x) addr0(0x%08x) "
++ "addr1(0x%08x) size(0x%08x)\n",
++ drb_iter->node, (u32) drb_iter,
++ drb_iter->src_addr, drb_iter->dst_addr,
++ drb_iter->req_cycle);
++
++ /* Kick-off DMA for next DRB */
++ /* - Source and destination address */
++ if (drq->flags & DMAD_DRQ_DIR_A1_TO_A0) {
++ outl(drb_iter->addr1, drq->src_port);
++ outl(drb_iter->addr0, drq->dst_port);
++ } else {
++ outl(drb_iter->addr0, drq->src_port);
++ outl(drb_iter->addr1, drq->dst_port);
++ }
++
++ /* - Transfer size (in units of source width) */
++ outl(drb_iter->req_cycle, drq->cyc_port);
++
++ /* Kick off next request */
++ dmad_enable_channel(drq);
++
++ drb_iter->state = DMAD_DRB_STATE_EXECUTED;
++
++ } else {
++ /* No pending requests, keep the DMA channel stopped */
++ }
++
++ } else if (err_int) {
++
++ dmad_err("%s() apb dma channel %d error!\n", __func__, channel);
++
++ /* Zero out src, dst, and size */
++ outl(0, drq->src_port);
++ outl(0, drq->dst_port);
++ outl(0, drq->cyc_port);
++
++ /* Remove all pending requests in the queue */
++ drb_iter = drb;
++ while (drb_iter) {
++
++ dmad_err("abort drb(%d 0x%08x) addr0(0x%08x) "
++ "addr1(0x%08x) size(0x%08x)\n",
++ drb_iter->node, (u32) drb_iter,
++ drb_iter->src_addr, drb_iter->dst_addr,
++ drb_iter->req_cycle);
++
++ if (drb_iter->req_cycle == 0)
++ cpl_events = 0;
++
++ /* Mark DRB state as abort */
++ drb_iter->state = DMAD_DRB_STATE_ABORT;
++
++ if (cpl_events && drb_iter->sync)
++ complete_all(drb_iter->sync);
++
++ dmad_attach_tail(drq->drb_pool, &drq->fre_head,
++ &drq->fre_tail, drb_iter->node);
++
++ dmad_detach_head(drq->drb_pool, &drq->sbt_head,
++ &drq->sbt_tail, &drb_iter);
++ }
++ }
++
++ spin_unlock(&drq->drb_pool_lock);
++
++ /* dispatch interrupt-context level callbacks */
++ if (cpl_events && drq->completion_cb) {
++ /* signal DMA driver that new node is available */
++ drq->completion_cb(channel, status, drq->completion_data);
++ }
++
++ dmad_dbg("%s() <<\n", __func__);
++
++ return IRQ_HANDLED;
++}
++
++/**
++ * dmad_apb_config_dir - prepare command reg according to tx direction
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @channel_cmds : [out] Reference to array of command words to be prepared with
++ * @return : none
++ *
++ * Prepare command registers according to transfer direction ...
++ * channel_cmd[0] APBBR_DMA_CMD
++ *
++ * This function only serves as local helper. No protection wrappers.
++ */
++static void dmad_apb_config_dir(dmad_chreq * ch_req, addr_t * channel_cmds)
++{
++ dmad_drq *drq = (dmad_drq *) ch_req->drq;
++ dmad_apb_chreq *apb_req = (dmad_apb_chreq *) (&ch_req->apb_req);
++
++ dmad_dbg("%s() channel_cmd(0x%08x)\n", __func__, channel_cmds[0]);
++
++ *channel_cmds &= ~(addr_t)
++ (APBBR_DMA_SRCADDRINC_MASK | APBBR_DMA_DSTADDRINC_MASK |
++ APBBR_DMA_DSTADDRSEL_MASK | APBBR_DMA_DREQSEL_MASK |
++ APBBR_DMA_SRCADDRSEL_MASK | APBBR_DMA_SREQSEL_MASK);
++
++ /* 0 - addr0 to addr1; 1 - addr1 to addr0 */
++ if (apb_req->tx_dir == 0) {
++
++ dmad_dbg("%s() addr0 --> addr1\n", __func__);
++
++ /* APB Bridge DMA (Channel Setting)
++ * - CMD
++ * SRCADR : apb_req->src_ctrl
++ * DESADR : apb_req->dst_ctrl
++ */
++ *channel_cmds |=
++ (((apb_req->addr0_ctrl << APBBR_DMA_SRCADDRINC_SHIFT) &
++ APBBR_DMA_SRCADDRINC_MASK) |
++ ((apb_req->addr1_ctrl << APBBR_DMA_DSTADDRINC_SHIFT) &
++ APBBR_DMA_DSTADDRINC_MASK));
++
++ /* - CMD
++ * DESADRSEL : AHB/APB, driver auto-conf
++ * DREQSEL
++ */
++ *channel_cmds |=
++ ((addr_t) (APBBR_DMA_DSTADDRSEL_MASK &
++ (apb_reqn_route_table[apb_req->addr1_reqn].
++ bus_sel << APBBR_DMA_DSTADDRSEL_BIT)) |
++ (((addr_t) apb_req->
++ addr1_reqn << APBBR_DMA_DREQSEL_SHIFT) &
++ APBBR_DMA_DREQSEL_MASK));
++
++ /* - CMD
++ * SRCADRSEL : AHB/APB, driver auto-conf
++ * SREQSEL
++ */
++ *channel_cmds |=
++ ((addr_t) (APBBR_DMA_SRCADDRSEL_MASK &
++ (apb_reqn_route_table[apb_req->addr0_reqn].
++ bus_sel << APBBR_DMA_SRCADDRSEL_BIT)) |
++ (((addr_t) apb_req->
++ addr0_reqn << APBBR_DMA_SREQSEL_SHIFT) &
++ APBBR_DMA_SREQSEL_MASK));
++
++ drq->flags &= ~(addr_t) DMAD_DRQ_DIR_A1_TO_A0;
++
++ } else {
++
++ dmad_dbg("%s() addr0 <-- addr1\n", __func__);
++
++ /* APB Bridge DMA (Channel Setting)
++ * - CMD
++ * SRCADR : apb_req->src_ctrl
++ * DESADR : apb_req->dst_ctrl
++ */
++ *channel_cmds |=
++ (((apb_req->addr1_ctrl << APBBR_DMA_SRCADDRINC_SHIFT) &
++ APBBR_DMA_SRCADDRINC_MASK) |
++ ((apb_req->addr0_ctrl << APBBR_DMA_DSTADDRINC_SHIFT) &
++ APBBR_DMA_DSTADDRINC_MASK));
++
++ /* - CMD
++ * DESADRSEL : AHB/APB, driver auto-conf
++ * DREQSEL
++ */
++ *channel_cmds |= ((addr_t) (APBBR_DMA_DSTADDRSEL_MASK &
++ (apb_reqn_route_table
++ [apb_req->addr0_reqn].
++ bus_sel <<
++ APBBR_DMA_DSTADDRSEL_BIT)) |
++ (((addr_t) apb_req->
++ addr0_reqn << APBBR_DMA_DREQSEL_SHIFT) &
++ APBBR_DMA_DREQSEL_MASK));
++
++ /* - CMD
++ * SRCADRSEL : AHB/APB, driver auto-conf
++ * SREQSEL
++ */
++ *channel_cmds |= ((addr_t) (APBBR_DMA_SRCADDRSEL_MASK &
++ (apb_reqn_route_table
++ [apb_req->addr1_reqn].
++ bus_sel <<
++ APBBR_DMA_SRCADDRSEL_BIT)) |
++ (((addr_t) apb_req->
++ addr1_reqn << APBBR_DMA_SREQSEL_SHIFT) &
++ APBBR_DMA_SREQSEL_MASK));
++
++ drq->flags |= (addr_t) DMAD_DRQ_DIR_A1_TO_A0;
++ }
++
++ dmad_dbg("%s() channel_cmd(0x%08x)\n", __func__, channel_cmds[0]);
++}
++
++/**
++ * dmad_apb_init - initialize a apb dma channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @return : 0 if success, non-zero if any error
++ *
++ * Register APB DMA ISR and performs hw initialization for the given DMA
++ * channel.
++ */
++static int dmad_apb_init(dmad_chreq * ch_req)
++{
++ int err = 0;
++ dmad_drq *drq = (dmad_drq *) ch_req->drq;
++ dmad_apb_chreq *apb_req = (dmad_apb_chreq *) (&ch_req->apb_req);
++ u32 channel = (u32) ch_req->channel;
++ addr_t channel_cmd = 0;
++ unsigned long lock_flags;
++
++ dmad_dbg("%s()\n", __func__);
++
++ /* register interrupt handler */
++ err = request_irq(apb_irqs[channel], dmad_apb_isr, 0,
++ "APB_DMA", (void *)(channel + 1));
++ if (unlikely(err != 0)) {
++ dmad_err("unable to request IRQ %d for APB DMA (error %d)\n",
++ apb_irqs[channel], err);
++ free_irq(apb_irqs[channel], (void *)(channel + 1));
++ return err;
++ }
++
++ spin_lock_irqsave(&dmad.drq_pool_lock, lock_flags);
++
++ /**********************************************************
++ * Following code require _safe_exit return path
++ */
++
++#ifdef CONFIG_PLAT_AG102
++
++ /* PCU
++ *
++ */
++ //ADD by river 2010.10.20
++ if (unlikely((apb_req->src_reqn > APBBR_REQN_MAX) ||
++ (apb_req->dst_reqn > APBBR_REQN_MAX))) {
++ dmad_err("Invalid source reqn(%d) or destination reqn(%d)\n",
++ apb_req->src_reqn, apb_req->dst_reqn);
++ err = -EBADR;
++ goto _safe_exit;
++ }
++
++ if (apb_req->src_reqn != APBBR_REQN_NONE) {
++ u32 ahb_reqn;
++
++ if (apb_req->tx_dir == DMAD_DIR_A0_TO_A1)
++ ahb_reqn =
++ apb_reqn_route_table[apb_req->src_reqn].ahb_reqn_tx;
++ else
++ ahb_reqn =
++ apb_reqn_route_table[apb_req->src_reqn].ahb_reqn_rx;
++
++ }
++
++ if (apb_req->dst_reqn != APBBR_REQN_NONE) {
++ u32 ahb_reqn;
++
++ if (apb_req->tx_dir == DMAD_DIR_A0_TO_A1)
++ ahb_reqn =
++ apb_reqn_route_table[apb_req->dst_reqn].ahb_reqn_tx;
++ else
++ ahb_reqn =
++ apb_reqn_route_table[apb_req->dst_reqn].ahb_reqn_rx;
++
++ }
++ //End ADD by river 2010.10.20
++
++#else /* CONFIG_PLAT_AG102 */
++
++ /* PMU
++ * - Undo APB device DMA to AHB DMAC channel routing. (connection status
++ * is obtained from reading back the PMU_AHBDMA_REQACK register)
++ */
++ if (unlikely((apb_req->src_reqn > APBBR_REQN_MAX) ||
++ (apb_req->dst_reqn > APBBR_REQN_MAX))) {
++ dmad_err("Invalid source reqn(%d) or destination reqn(%d)\n",
++ apb_req->src_reqn, apb_req->dst_reqn);
++ err = -EBADR;
++ goto _safe_exit;
++ }
++
++ if (apb_req->src_reqn != APBBR_REQN_NONE) {
++ u32 ahb_reqn;
++
++ if (apb_req->tx_dir == DMAD_DIR_A0_TO_A1)
++ ahb_reqn =
++ apb_reqn_route_table[apb_req->src_reqn].ahb_reqn_tx;
++ else
++ ahb_reqn =
++ apb_reqn_route_table[apb_req->src_reqn].ahb_reqn_rx;
++
++ outl(0, ahb_ch_route_table[ahb_reqn].clear_cr);
++ outl(0, ahb_ch_route_table[ahb_reqn].route_cr);
++ outl(0, ahb_ch_route_table[ahb_reqn].clear_cr);
++ outl(0, ahb_ch_route_table[ahb_reqn].route_cr);
++ }
++
++ if (apb_req->dst_reqn != APBBR_REQN_NONE) {
++ u32 ahb_reqn;
++
++ if (apb_req->tx_dir == DMAD_DIR_A0_TO_A1)
++ ahb_reqn =
++ apb_reqn_route_table[apb_req->dst_reqn].ahb_reqn_tx;
++ else
++ ahb_reqn =
++ apb_reqn_route_table[apb_req->dst_reqn].ahb_reqn_rx;
++
++ outl(0, ahb_ch_route_table[ahb_reqn].clear_cr);
++ outl(0, ahb_ch_route_table[ahb_reqn].route_cr);
++ outl(0, ahb_ch_route_table[ahb_reqn].clear_cr);
++ outl(0, ahb_ch_route_table[ahb_reqn].route_cr);
++ }
++#endif /* CONFIG_PLAT_AG102 */
++
++ /* APB Bridge DMA (Channel Setting)
++ * - CMD
++ * ENBDIS : 0 (disable for now)
++ * FININTSTS : 0 (clear finishing interrupt status)
++ * FININTENB : 1 (enable finishing interrupt)
++ * BURMOD : apb_req->burst_mode
++ * ERRINTSTS : 0 (clear error interrupt status)
++ * ERRINTENB : 1 (enable error interrupt)
++ * SRCADRSEL : AHB/APB, driver auto-conf
++ * DESADRSEL : AHB/APB, driver auto-conf
++ * SRCADR : apb_req->src_ctrl
++ * DESADR : apb_req->dst_ctrl
++ * REQSEL : apb_req->src_reqn
++ * DATAWIDTH : apb_req->data_width
++ */
++
++ /* - CMD
++ * ENBDIS
++ * FININTSTS
++ * FININTENB
++ * BURMOD
++ * ERRINTSTS
++ * ERRINTENB
++ * DATAWIDTH
++ */
++ channel_cmd =
++ ((addr_t) APBBR_DMA_FINTEN_MASK | APBBR_DMA_ERRINTEN_MASK |
++ ((apb_req->
++ burst_mode << APBBR_DMA_BURST_BIT) & APBBR_DMA_BURST_MASK) |
++ ((apb_req->
++ data_width << APBBR_DMA_DATAWIDTH_SHIFT) &
++ APBBR_DMA_DATAWIDTH_MASK));
++
++ /* - CMD
++ * SRCADRSEL
++ * DESADRSEL
++ * SRCADR
++ * DESADR
++ * REQSEL
++ */
++ if (0 ==
++ (ch_req->flags & (DMAD_FLAGS_RING_MODE | DMAD_FLAGS_BIDIRECTION)))
++ apb_req->tx_dir = 0;
++ dmad_apb_config_dir(ch_req, &channel_cmd);
++
++ /* - CMD outport */
++ outl(channel_cmd, (addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
++
++ /* SRCADR and DESADR */
++ outl(0, (addr_t) drq->src_port);
++ outl(0, (addr_t) drq->dst_port);
++
++ /* CYC (transfer size) */
++ outl(0, (addr_t) drq->cyc_port);
++
++ /* keep channel data width for faster cycle/byte size conversion */
++ drq->data_width = apb_req->data_width;
++
++_safe_exit:
++
++ spin_unlock_irqrestore(&dmad.drq_pool_lock, lock_flags);
++
++ return err;
++}
++
++#endif /* CONFIG_PLATFORM_APBDMA */
++
++/**
++ * dmad_channel_init - initialize given dma channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @return : 0 if success, non-zero if any error
++ *
++ * This function serves as the abstraction layer of dmad_ahb_init()
++ * and dmad_apb_init() functions.
++ */
++static int dmad_channel_init(dmad_chreq * ch_req)
++{
++ int err = 0;
++
++ dmad_dbg("%s()\n", __func__);
++
++ if (unlikely(ch_req == NULL))
++ return -EFAULT;
++
++ if (unlikely(ch_req->drq == NULL))
++ return -EBADR;
++
++ /* Initialize DMA controller */
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE)
++ err = dmad_ahb_init(ch_req);
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE)
++ err = dmad_apb_init(ch_req);
++#endif
++
++ return err;
++}
++
++static inline void dmad_reset_channel(dmad_drq * drq)
++{
++ /* disable dma controller */
++ dmad_disable_channel(drq);
++
++ /* Source and destination address */
++ outl(0, drq->src_port);
++ outl(0, drq->dst_port);
++
++ /* Transfer size (in units of source width) */
++ outl(0, drq->cyc_port);
++}
++
++/**
++ * dmad_channel_reset - reset given dma channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @return : 0 if success, non-zero if any error
++ *
++ * This function serves as the abstraction layer of dmad_ahb_reset()
++ * and dmad_apb_reset() functions.
++ */
++static int dmad_channel_reset(dmad_chreq * ch_req)
++{
++ u32 channel = (u32) ch_req->channel;
++ unsigned long lock_flags;
++ int err = 0;
++
++ dmad_dbg("%s()\n", __func__);
++
++ if (unlikely(ch_req == NULL))
++ return -EFAULT;
++
++ if (unlikely(ch_req->drq == NULL))
++ return -EBADR;
++
++ spin_lock_irqsave(&((dmad_drq *) ch_req->drq)->drb_pool_lock,
++ lock_flags);
++
++ /* stop DMA channel */
++ dmad_reset_channel((dmad_drq *) ch_req->drq);
++
++ spin_unlock_irqrestore(&((dmad_drq *) ch_req->drq)->drb_pool_lock,
++ lock_flags);
++
++ /* unregister interrupt handler */
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE)
++ free_irq(ahb_irqs[channel], (void *)(channel + 1));
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE)
++ free_irq(apb_irqs[channel], (void *)(channel + 1));
++#endif
++
++ return err;
++}
++
++/**
++ * dmad_channel_alloc - allocates and initialize a dma channel
++ * @ch_req : [in/out] Reference to the DMA request descriptor structure
++ * @return : 0 if success, non-zero if any error
++ *
++ * This function allocates a DMA channel according to client's request
++ * parameters. ISR and HW state will also be initialized accordingly.
++ */
++int dmad_channel_alloc(dmad_chreq * ch_req)
++{
++ dmad_drq *drq_iter = NULL;
++ dmad_drb *drb_iter;
++ int err = 0;
++ u32 i = 0;
++
++ dmad_dbg("%s()\n", __func__);
++
++ if (ch_req == NULL) {
++ printk(KERN_ERR "%s() invalid argument!\n", __func__);
++ return -EFAULT;
++ }
++
++ spin_lock(&dmad.drq_pool_lock);
++
++ /* locate an available DMA channel */
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
++
++ drq_iter = dmad.ahb_drq_pool;
++
++ if ((ch_req->ahb_req.src_reqn != DMAC_REQN_NONE) ||
++ (ch_req->ahb_req.dst_reqn != DMAC_REQN_NONE)) {
++ /* [2007-12-03] It looks current board have problem to
++ * do dma traffic for APB devices on DMAC channel 0/1.
++ * Redirect all APB devices to start from channel 2.
++ */
++
++ /* [todo] include USB controller ? */
++ drq_iter = &dmad.ahb_drq_pool[2];
++ for (i = 2; i < DMAD_AHB_MAX_CHANNELS; ++i, ++drq_iter) {
++ if (!(drq_iter->state & DMAD_DRQ_STATE_READY))
++ break;
++ }
++ } else {
++ /* channel for other devices is free to allocate */
++ for (i = 0; i < DMAD_AHB_MAX_CHANNELS; ++i, ++drq_iter) {
++ if (!(drq_iter->state & DMAD_DRQ_STATE_READY))
++ break;
++ }
++ }
++
++ if (unlikely(i == DMAD_AHB_MAX_CHANNELS)) {
++ spin_unlock(&dmad.drq_pool_lock);
++ dmad_err("out of available channels (AHB DMAC)!\n");
++ return -ENOSPC;
++ }
++
++ dmad_dbg("allocated channel: %d (AHB DMAC)\n", i);
++
++ }
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE) {
++
++ drq_iter = dmad.apb_drq_pool;
++
++ for (i = 0; i < DMAD_APB_MAX_CHANNELS; ++i, ++drq_iter) {
++ if ((drq_iter->state & DMAD_DRQ_STATE_READY) == 0)
++ break;
++ }
++
++ if (unlikely(i == DMAD_APB_MAX_CHANNELS)) {
++ spin_unlock(&dmad.drq_pool_lock);
++ dmad_err("out of available channels (APB DMAC)!\n");
++ return -ENOSPC;
++ }
++
++ dmad_dbg("allocated channel: %d (APB DMAC)\n", i);
++ }
++#endif
++ if (drq_iter == NULL) {
++ spin_unlock(&dmad.drq_pool_lock);
++ printk(KERN_ERR "%s() invalid argument!\n", __func__);
++ return -EFAULT;
++ }
++
++ spin_unlock(&dmad.drq_pool_lock);
++ memset(drq_iter, 0, sizeof(dmad_drq));
++
++ /* Initialize DMA channel's DRB pool as list of free DRBs */
++ drq_iter->drb_pool =
++ kmalloc(DMAD_DRB_POOL_SIZE * sizeof(dmad_drb), GFP_ATOMIC);
++
++ if (drq_iter->drb_pool == NULL) {
++ printk(KERN_ERR "%s() failed to allocate drb pool!\n",
++ __func__);
++ return -ENOMEM;
++ }
++
++ /* Allocate the DMA channel */
++ drq_iter->state = DMAD_DRQ_STATE_READY;
++ drq_iter->flags = ch_req->flags;
++
++ /* Initialize synchronization object for DMA queue access control */
++ spin_lock_init(&drq_iter->drb_pool_lock);
++
++ /* Initialize synchronization object for free drb notification */
++ init_completion(&drq_iter->drb_alloc_sync);
++
++ /* Record the channel number in client's struct */
++ ch_req->channel = i;
++
++ /* Record the channel's queue handle in client's struct */
++ ch_req->drq = drq_iter;
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
++ drq_iter->channel_base = (addr_t) DMAC_BASE_CH(i);
++ drq_iter->enable_port =
++ (addr_t) drq_iter->channel_base + DMAC_CSR_OFFSET;
++ drq_iter->src_port =
++ (addr_t) drq_iter->channel_base + DMAC_SRC_ADDR_OFFSET;
++ drq_iter->dst_port =
++ (addr_t) drq_iter->channel_base + DMAC_DST_ADDR_OFFSET;
++ drq_iter->cyc_port =
++ (addr_t) drq_iter->channel_base + DMAC_SIZE_OFFSET;
++ }
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE) {
++ drq_iter->channel_base = (addr_t) APBBR_DMA_BASE_CH(i);
++ drq_iter->enable_port =
++ (addr_t) drq_iter->channel_base + APBBR_DMA_CMD_OFFSET;
++ drq_iter->src_port =
++ (addr_t) drq_iter->channel_base + APBBR_DMA_SAD_OFFSET;
++ drq_iter->dst_port =
++ (addr_t) drq_iter->channel_base + APBBR_DMA_DAD_OFFSET;
++ drq_iter->cyc_port =
++ (addr_t) drq_iter->channel_base + APBBR_DMA_CYC_OFFSET;
++ }
++#endif
++ /* drb-0 is an invalid node - for node validation */
++ drb_iter = &drq_iter->drb_pool[0];
++ drb_iter->prev = 0;
++ drb_iter->next = 0;
++ drb_iter->node = 0;
++ ++drb_iter;
++
++ /* init other drbs - link in order */
++ for (i = 1; i < DMAD_DRB_POOL_SIZE; ++i, ++drb_iter) {
++ drb_iter->prev = i - 1;
++ drb_iter->next = i + 1;
++ drb_iter->node = i;
++ }
++ drq_iter->drb_pool[DMAD_DRB_POOL_SIZE - 1].next = 0;
++
++ /* Initialize channel's DRB free-list, ready-list, and submitted-list */
++ drq_iter->fre_head = 1;
++ drq_iter->fre_tail = DMAD_DRB_POOL_SIZE - 1;
++ drq_iter->rdy_head = drq_iter->rdy_tail = 0;
++ drq_iter->sbt_head = drq_iter->sbt_tail = 0;
++
++ /* initialize ring buffer mode resources */
++ if (ch_req->flags & DMAD_FLAGS_RING_MODE) {
++
++ int remnant = (int)ch_req->ring_size -
++ (int)ch_req->periods * (int)ch_req->period_size;
++ if (remnant == 0) {
++ drq_iter->periods = ch_req->periods;
++ } else if (remnant > 0) {
++ drq_iter->periods = ch_req->periods; // + 1;
++ } else {
++ dmad_err("%s() Error - buffer_size < "
++ "periods * period_size!\n", __func__);
++ err = -EFAULT;
++ goto _err_exit;
++ }
++
++ drq_iter->ring_size = ch_req->ring_size;
++ drq_iter->period_size = ch_req->period_size;
++ drq_iter->remnant_size = (dma_addr_t) remnant;
++
++ drq_iter->ring_base = (dma_addr_t) ch_req->ring_base;
++ drq_iter->dev_addr = (dma_addr_t) ch_req->dev_addr;
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
++ if ((ch_req->ahb_req.ring_ctrl == DMAC_CSR_AD_DEC) ||
++ (ch_req->ahb_req.dev_ctrl == DMAC_CSR_AD_DEC)) {
++ dmad_err("%s() Error - decremental"
++ " addressing DMA is not supported in"
++ " ring mode currently!\n", __func__);
++ err = -EFAULT;
++ goto _err_exit;
++ }
++
++ if (ch_req->ahb_req.ring_ctrl == DMAC_CSR_AD_FIX) {
++ dmad_err("%s() Error - ring address control is "
++ "fixed in ring DMA mode!\n", __func__);
++ err = -EFAULT;
++ goto _err_exit;
++ }
++
++ drq_iter->period_bytes =
++ DMAC_CYCLE_TO_BYTES(ch_req->period_size,
++ ch_req->ahb_req.ring_width);
++
++ /* 0 - addr0 to addr1; 1 - addr1 to addr0 */
++ if (ch_req->ahb_req.tx_dir == 0)
++ drq_iter->ring_port =
++ (addr_t) drq_iter->src_port;
++ else
++ drq_iter->ring_port =
++ (addr_t) drq_iter->dst_port;
++
++ }
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE) {
++
++ if ((ch_req->apb_req.ring_ctrl >= APBBR_ADDRINC_D1) ||
++ (ch_req->apb_req.dev_ctrl >= APBBR_ADDRINC_D1)) {
++ dmad_err("%s() Error - decremental"
++ " addressing DMA is not supported in"
++ " ring mode currently!\n", __func__);
++ err = -EFAULT;
++ goto _err_exit;
++ }
++
++ if (ch_req->apb_req.ring_ctrl == APBBR_ADDRINC_FIXED) {
++ dmad_err("%s() Error - ring address control is "
++ "fixed in ring DMA mode!\n", __func__);
++ err = -EFAULT;
++ goto _err_exit;
++ }
++
++ drq_iter->period_bytes =
++ APBBR_DMA_CYCLE_TO_BYTES(ch_req->period_size,
++ ch_req->apb_req.
++ data_width);
++
++ /* 0 - addr0 to addr1; 1 - addr1 to addr0 */
++ if (ch_req->apb_req.tx_dir == 0)
++ drq_iter->ring_port =
++ (addr_t) drq_iter->src_port;
++ else
++ drq_iter->ring_port =
++ (addr_t) drq_iter->dst_port;
++ }
++#endif
++ dmad_dbg("%s() ring: base(0x%08x) port(0x%08x) periods(0x%08x)"
++ " period_size(0x%08x) period_bytes(0x%08x)"
++ " remnant_size(0x%08x)\n",
++ __func__, drq_iter->ring_base, drq_iter->ring_port,
++ drq_iter->periods, drq_iter->period_size,
++ drq_iter->period_bytes, drq_iter->remnant_size);
++ }
++
++ drq_iter->completion_cb = ch_req->completion_cb;
++ drq_iter->completion_data = ch_req->completion_data;
++
++ /* Initialize the channel && register isr */
++ err = dmad_channel_init(ch_req);
++
++_err_exit:
++
++ if (err != 0) {
++ spin_lock(&dmad.drq_pool_lock);
++
++ kfree(drq_iter->drb_pool);
++ memset(drq_iter, 0, sizeof(dmad_drq));
++
++ ch_req->channel = -1;
++ ch_req->drq = (void *)0;
++
++ spin_unlock(&dmad.drq_pool_lock);
++
++ dmad_err("Failed to initialize APB DMA! "
++ "Channel allocation aborted!\n");
++ }
++
++ return err;
++}
++
++EXPORT_SYMBOL_GPL(dmad_channel_alloc);
++
++/**
++ * dmad_channel_free - release a dma channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @return : 0 if success, non-zero if any error
++ *
++ * This function releases a DMA channel. The channel is available for future
++ * allocation after the invokation.
++ */
++int dmad_channel_free(dmad_chreq * ch_req)
++{
++ dmad_drq *drq;
++
++ dmad_dbg("%s()\n", __func__);
++
++ if (unlikely(ch_req == NULL)) {
++ dmad_err("null ch_req!\n");
++ return -EFAULT;
++ }
++
++ drq = (dmad_drq *) ch_req->drq;
++
++ if (unlikely(drq == NULL)) {
++ dmad_err("null ch_req->drq!\n");
++ return -EBADR;
++ }
++ if (unlikely((ch_req->channel < 0) ||
++ ((drq->state & DMAD_DRQ_STATE_READY) == 0))) {
++ dmad_err("try to free a free channel!\n");
++ return -EBADR;
++ }
++
++ /* Stop/abort channel I/O
++ * (forced to shutdown and should be protected against isr)
++ */
++ dmad_drain_requests(ch_req, 1);
++ dmad_channel_reset(ch_req);
++
++ dmad_dbg("freed channel: %d\n", ch_req->channel);
++
++ spin_lock(&dmad.drq_pool_lock);
++
++ kfree(drq->drb_pool);
++ memset(drq, 0, sizeof(dmad_drq));
++
++ ch_req->drq = 0;
++ ch_req->channel = (u32) - 1;
++
++ spin_unlock(&dmad.drq_pool_lock);
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(dmad_channel_free);
++
++/**
++ * dmad_channel_enable - enable/disable a dma channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @enable : [in] 1 to enable the channel, 0 to disable
++ * @return : 0 if success, non-zero if any error
++ *
++ * Enable or disable the given DMA channel.
++ */
++int dmad_channel_enable(const dmad_chreq * ch_req, u8 enable)
++{
++ dmad_drq *drq;
++ unsigned long lock_flags;
++
++ dmad_dbg("%s()\n", __func__);
++
++ if (unlikely(ch_req == NULL))
++ return -EFAULT;
++
++ drq = (dmad_drq *) ch_req->drq;
++
++ if (unlikely(drq == NULL))
++ return -EBADR;
++
++ spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
++
++ /* Enable/disable DMA channel */
++ if (enable)
++ dmad_enable_channel(drq);
++ else
++ dmad_disable_channel(drq);
++
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(dmad_channel_enable);
++
++/**
++ * dmad_config_channel_dir - config dma channel transfer direction
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @dir : [in] DMAD_DRQ_DIR_A0_TO_A1 or DMAD_DRQ_DIR_A1_TO_A0
++ * @return : 0 if success, non-zero if any error
++ *
++ * Reconfigure the channel transfer direction. This function works only if
++ * the channel was allocated with the DMAD_FLAGS_BIDIRECTION flags. Note
++ * that bi-direction mode and ring mode are mutual-exclusive from user's
++ * perspective.
++ */
++int dmad_config_channel_dir(dmad_chreq * ch_req, u8 dir)
++{
++ dmad_drq *drq;
++ addr_t channel_cmds[2];
++ unsigned long lock_flags;
++ u8 cur_dir;
++
++ if (unlikely(ch_req == NULL))
++ return -EFAULT;
++
++ drq = (dmad_drq *) ch_req->drq;
++
++ if (unlikely(drq == NULL))
++ return -EBADR;
++
++ if (unlikely(!(ch_req->flags & DMAD_FLAGS_BIDIRECTION))) {
++ dmad_err("%s() Channel is not configured as"
++ " bidirectional!\n", __func__);
++ return -EFAULT;
++ }
++
++ cur_dir = drq->flags & DMAD_DRQ_DIR_MASK;
++ if (dir == cur_dir) {
++ dmad_dbg("%s() cur_dir(%d) == dir(%d) skip reprogramming hw.\n",
++ __func__, cur_dir, dir);
++ return 0;
++ }
++
++ spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
++
++ if (unlikely((drq->sbt_head != 0) /*||dmad_is_channel_enabled(drq) */ )) {
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++ dmad_err("%s() Cannot change direction while the "
++ "channel has pending requests!\n", __func__);
++ return -EFAULT;
++ }
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
++
++ channel_cmds[0] =
++ inl((addr_t) drq->channel_base + DMAC_CSR_OFFSET);
++ channel_cmds[1] =
++ inl((addr_t) drq->channel_base + DMAC_CFG_OFFSET);
++
++ ch_req->ahb_req.tx_dir = dir;
++ dmad_ahb_config_dir(ch_req, channel_cmds);
++
++ outl(channel_cmds[1],
++ (addr_t) drq->channel_base + DMAC_CFG_OFFSET);
++ outl(channel_cmds[0],
++ (addr_t) drq->channel_base + DMAC_CSR_OFFSET);
++
++ }
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE) {
++
++ channel_cmds[0] =
++ inl((addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
++
++ ch_req->apb_req.tx_dir = dir;
++ dmad_apb_config_dir(ch_req, channel_cmds);
++
++ outl(channel_cmds[0],
++ (addr_t) drq->channel_base + APBBR_DMA_CMD_OFFSET);
++ }
++#endif
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(dmad_config_channel_dir);
++
++/**
++ * dmad_max_size_per_drb - return maximum transfer size per drb
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @return : The maximum transfer size per drb, in bytes.
++ *
++ * Calculate the maximum transfer size per drb according to the setting of
++ * data width during channel initialization.
++ *
++ * Return size is aligned to 4-byte boundary; this ensures the alignment
++ * requirement of dma starting address if the function was used in a loop to
++ * separate a large size dma transfer.
++ */
++u32 dmad_max_size_per_drb(dmad_chreq * ch_req)
++{
++ addr_t size = 0;
++ addr_t data_width = (addr_t) ((dmad_drq *) ch_req->drq)->data_width;
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
++ size = DMAC_CYCLE_TO_BYTES(DMAC_TOT_SIZE_MASK & ((addr_t) ~ 3),
++ data_width);
++ }
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE) {
++ size =
++ APBBR_DMA_CYCLE_TO_BYTES(APBBR_DMA_CYC_MASK &
++ ((addr_t) ~ 3), data_width);
++ }
++#endif
++ dmad_dbg("%s() - 0x%08x bytes\n", __func__, size);
++
++ return size;
++}
++
++EXPORT_SYMBOL_GPL(dmad_max_size_per_drb);
++
++/**
++ * dmad_bytes_to_cycles - calculate drb transfer size, in cycles
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @byte_size : [in] The DMA transfer size to be converted, in bytes
++ * @return : The drb transfer size, in cycles.
++ *
++ * Calculate the drb transfer cycle according to the setting of channel data
++ * width and burst setting.
++ *
++ * AHB DMA : unit is number of "data width".
++ * APB DMA : unit is number of "data width * burst size"
++ *
++ * APB Note: According to specification, decrement addressing seems to regard
++ * the burst size setting. For code efficiency,
++ * dmad_make_req_cycles() does not take care of this case and might
++ * produce wrong result.
++ */
++u32 dmad_bytes_to_cycles(dmad_chreq * ch_req, u32 byte_size)
++{
++ addr_t cycle = 0;
++ addr_t data_width = (addr_t) ((dmad_drq *) ch_req->drq)->data_width;
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
++ cycle = DMAC_BYTES_TO_CYCLE(byte_size, data_width);
++ }
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE) {
++ cycle = APBBR_DMA_BYTES_TO_CYCLE(byte_size, data_width);
++ if (ch_req->apb_req.burst_mode)
++ cycle = cycle >> 2;
++ }
++#endif
++
++ dmad_dbg("%s() - 0x%08x bytes --> 0x%08x cycles\n",
++ __func__, byte_size, cycle);
++
++ return cycle;
++}
++
++EXPORT_SYMBOL_GPL(dmad_bytes_to_cycles);
++
++/**
++ * dmad_alloc_drb_internal - allocate a dma-request-block of a dma channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @drb : [out] Reference to a drb pointer to receive the allocated drb
++ * @return : 0 if success, non-zero if any error
++ *
++ * Allocates a DRB (DMA request block) of the given DMA channel. DRB is a
++ * single dma request which will be pushed into the submission queue of the
++ * given DMA channel. This is a lightweight internal version of
++ * dmad_alloc_drb() majorly for use in ring mode. Critical access to the
++ * drb pool should be protected before entering this function.
++ */
++static inline int dmad_alloc_drb_internal(dmad_drq * drq, dmad_drb ** drb)
++{
++ /* Initialize drb ptr in case of fail allocation */
++ *drb = NULL;
++
++ if (unlikely(drq->fre_head == 0)) {
++ return -EAGAIN;
++ }
++
++ dmad_detach_head(drq->drb_pool, &drq->fre_head, &drq->fre_tail, drb);
++
++ dmad_attach_tail(drq->drb_pool,
++ &drq->rdy_head, &drq->rdy_tail, (*drb)->node);
++
++ (*drb)->state = DMAD_DRB_STATE_READY;
++ (*drb)->sync = 0;
++
++ dmad_dbg("%s() drb(%d 0x%08x)\n", __func__, (*drb)->node, (u32) (*drb));
++
++ return 0;
++}
++
++/**
++ * dmad_alloc_drb - allocate a dma-request-block of a dma channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @drb : [out] Reference to a drb pointer to receive the allocated drb
++ * @return : 0 if success, non-zero if any error
++ *
++ * Allocates a DRB (DMA request block) of the given DMA channel. DRB is a
++ * single dma request which will be pushed into the submission queue of the
++ * given DMA channel.
++ */
++int dmad_alloc_drb(dmad_chreq * ch_req, dmad_drb ** drb)
++{
++ dmad_drq *drq;
++ unsigned long lock_flags;
++
++ dmad_dbg("%s()\n", __func__);
++
++ if (unlikely(ch_req == NULL)) {
++ dmad_err("null ch_req!\n");
++ return -EFAULT;
++ }
++
++ drq = (dmad_drq *) ch_req->drq;
++
++ if (likely(drq == NULL)) {
++ dmad_err("null ch_req->drq!\n");
++ return -EBADR;
++ }
++
++ spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
++
++ /* Initialize drb ptr in case of fail allocation */
++ *drb = NULL;
++
++ if (unlikely(drq->fre_head == 0)) {
++
++ drq->state &= (u32) ~ DMAD_DRQ_STATE_ABORT;
++
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++
++_wait_for_free_drbs:
++
++ /* Wait for free urbs */
++ if (drq->flags & DMAD_FLAGS_SLEEP_BLOCK) {
++
++ int timeout =
++ wait_for_completion_interruptible_timeout(&drq->
++ drb_alloc_sync,
++ msecs_to_jiffies
++ (6000));
++
++ /* reset sync object */
++ INIT_COMPLETION(drq->drb_alloc_sync);
++
++ if (timeout < 0) {
++ dmad_err("%s() wait for"
++ " completion error! (%d)\n",
++ __func__, timeout);
++ return timeout;
++ }
++
++ } else if (drq->flags & DMAD_FLAGS_SPIN_BLOCK) {
++
++ u32 timeout = 0x00ffffff;
++
++ while ((drq->fre_head == 0) && (--timeout != 0)) {
++ }
++ if (timeout == 0) {
++ dmad_err("%s() polling wait for "
++ "completion timeout!\n", __func__);
++ return -EAGAIN;
++ }
++
++ } else {
++ return -EAGAIN;
++ }
++
++ spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
++
++ /* check whether all the requests of the channel has been
++ * abandoned or not */
++ if (unlikely(drq->state & DMAD_DRQ_STATE_ABORT)) {
++ dmad_dbg("%s() drb-allocation aborted due"
++ " to cancel-request ...\n", __func__);
++ drq->state &= (u32) ~ DMAD_DRQ_STATE_ABORT;
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++ return -ECANCELED;
++ }
++
++ /* check again to avoid non-atomic operation between above
++ * two calls */
++ if (unlikely(drq->fre_head == 0)) {
++ dmad_dbg("%s() lost free drbs ... "
++ "continue waiting ...\n", __func__);
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++ goto _wait_for_free_drbs;
++ }
++ }
++
++ dmad_detach_head(drq->drb_pool, &drq->fre_head, &drq->fre_tail, drb);
++
++ dmad_attach_tail(drq->drb_pool,
++ &drq->rdy_head, &drq->rdy_tail, (*drb)->node);
++
++ (*drb)->state = DMAD_DRB_STATE_READY;
++ (*drb)->sync = 0;
++
++ dmad_dbg("%s() drb(%d 0x%08x)\n", __func__, (*drb)->node, (u32) (*drb));
++
++ drq->state &= (u32) ~ DMAD_DRQ_STATE_ABORT;
++
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(dmad_alloc_drb);
++
++/**
++ * dmad_free_drb - free a dma-request-block of a dma channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @drb : [in] Reference to a drb to be freed
++ * @return : 0 if success, non-zero if any error
++ *
++ * Frees a DRB (DMA request block) of the given DMA channel. DRB is a
++ * single dma request which will be pushed into the submission queue of the
++ * given DMA channel.
++ */
++int dmad_free_drb(dmad_chreq * ch_req, dmad_drb * drb)
++{
++ dmad_drq *drq;
++ unsigned long lock_flags;
++
++ dmad_dbg("%s()\n", __func__);
++
++ if (unlikely(ch_req == NULL)) {
++ dmad_err("null ch_req!\n");
++ return -EFAULT;
++ }
++
++ drq = (dmad_drq *) ch_req->drq;
++
++ if (unlikely(drq == NULL)) {
++ dmad_err("null ch_req->drq!\n");
++ return -EBADR;
++ }
++
++ spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
++
++ /****************************************************
++ * Following code requires _safe_exit return path
++ */
++
++ if (unlikely((drq->rdy_head == 0) || (drb->node == 0) ||
++ (drb->state != DMAD_DRB_STATE_READY) ||
++ (drb->node >= DMAD_DRB_POOL_SIZE))) {
++ dmad_err("Ready-queue is empty or invalid node!\n");
++
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++ return -EBADR;
++ }
++
++ dmad_detach_node(drq->drb_pool,
++ &drq->rdy_head, &drq->rdy_tail, drb->node);
++ dmad_attach_tail(drq->drb_pool,
++ &drq->fre_head, &drq->fre_tail, drb->node);
++
++ drb->state = DMAD_DRB_STATE_FREE;
++ drb->sync = 0;
++
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(dmad_free_drb);
++
++/**
++ * dmad_submit_request_internal - submit a dma-request-block to the dma channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @drb : [in] Reference to a drb to be submitted
++ * @keep_fired : [in] non-zero to kickoff dma even the channel has stopped due
++ * to finishing its previous request
++ * @return : 0 if success, non-zero if any error
++ *
++ * Submit a DRB (DMA request block) of the given DMA channel to submission
++ * queue. DRB is a single dma request which will be pushed into the
++ * submission queue of the given DMA channel. This is a lightweight internal
++ * version of dmad_alloc_drb() majorly for use in ring mode. Critical access to
++ * the drb pool should be protected before entering this function.
++ */
++static inline int dmad_submit_request_internal(dmad_drq * drq, dmad_drb * drb)
++{
++ if (drb->state == DMAD_DRB_STATE_READY) {
++ /* Detach user node from ready list */
++ dmad_detach_node(drq->drb_pool,
++ &drq->rdy_head, &drq->rdy_tail, drb->node);
++
++ dmad_attach_tail(drq->drb_pool,
++ &drq->sbt_head, &drq->sbt_tail, drb->node);
++
++ drb->state = DMAD_DRB_STATE_SUBMITTED;
++
++ dmad_dbg("%s() submit drb(%d 0x%08x) addr0(0x%08x) "
++ "addr1(0x%08x) size(0x%08x) state(%d)\n", __func__,
++ drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
++ drb->req_cycle, drb->state);
++ } else {
++ dmad_dbg("%s() skip drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x)"
++ " size(0x%08x) state(%d)\n", __func__,
++ drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
++ drb->req_cycle, drb->state);
++ }
++
++ return 0;
++}
++
++/**
++ * dmad_submit_request - submit a dma-request-block to the dma channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @drb : [in] Reference to a drb to be submitted
++ * @keep_fired : [in] non-zero to kickoff dma even the channel has stopped due
++ * to finishing its previous request
++ * @return : 0 if success, non-zero if any error
++ *
++ * Submit a DRB (DMA request block) of the given DMA channel to submission
++ * queue. DRB is a single dma request which will be pushed into the
++ * submission queue of the given DMA channel.
++ */
++int dmad_submit_request(dmad_chreq * ch_req, dmad_drb * drb, u8 keep_fired)
++{
++ dmad_drq *drq;
++ unsigned long lock_flags;
++
++ dmad_dbg("%s()\n", __func__);
++
++ if (unlikely(ch_req == NULL)) {
++ dmad_err("null ch_req!\n");
++ return -EFAULT;
++ }
++
++ drq = (dmad_drq *) ch_req->drq;
++
++ if (unlikely(drq == NULL)) {
++ dmad_err("null ch_req->drq!\n");
++ return -EBADR;
++ }
++
++ spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
++
++ /******************************************************
++ * Following code require _safe_exit return path
++ */
++
++ if (unlikely((drq->rdy_head == 0) || (drb->node == 0) ||
++ (drb->node >= DMAD_DRB_POOL_SIZE))) {
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++ return -EBADR;
++ }
++
++ /* Detach user node from ready list */
++ dmad_detach_node(drq->drb_pool, &drq->rdy_head, &drq->rdy_tail,
++ drb->node);
++
++ /* Queue DRB to the end of the submitted list */
++ dmad_dbg("submit drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
++ "size(0x%08x) sync(0x%08x) fire(%d)\n",
++ drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
++ drb->req_cycle, (u32) drb->sync, keep_fired);
++
++ /* Check if submission is performed to an empty queue */
++ if (unlikely(keep_fired && (drq->sbt_head == 0))) {
++ /* DMA is not running, so kick off transmission */
++ dmad_dbg("kickoff dma engine.\n");
++
++ dmad_attach_tail(drq->drb_pool,
++ &drq->sbt_head, &drq->sbt_tail, drb->node);
++
++ /* Source and destination address */
++ if (drq->flags & DMAD_DRQ_DIR_A1_TO_A0) {
++ outl(drb->addr1, (addr_t) drq->src_port);
++ outl(drb->addr0, (addr_t) drq->dst_port);
++ } else {
++ outl(drb->addr0, (addr_t) drq->src_port);
++ outl(drb->addr1, (addr_t) drq->dst_port);
++ }
++
++ /* Transfer size (in units of source width) */
++ outl(drb->req_cycle, (addr_t) drq->cyc_port);
++
++ /* Enable DMA channel (Kick off transmission when client
++ * enable it's transfer state) */
++ dmad_enable_channel(drq);
++
++ drb->state = DMAD_DRB_STATE_EXECUTED;
++
++ } else {
++ /* DMA is already running, so only queue DRB to the end of the
++ * list */
++ dmad_attach_tail(drq->drb_pool,
++ &drq->sbt_head, &drq->sbt_tail, drb->node);
++ drb->state = DMAD_DRB_STATE_SUBMITTED;
++ }
++
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(dmad_submit_request);
++
++/**
++ * dmad_withdraw_request - cancel a submitted dma-request-block
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @drb : [in] Reference to a drb to be submitted
++ * @keep_fired : [in] non-zero to kickoff dma even the channel has stopped due
++ * to finishing its previous request
++ * @return : 0 if success, non-zero if any error
++ *
++ * Cancel a submitted DRB (DMA request block) of the given DMA channel in its
++ * submission queue. DRB is a single dma request which will be pushed into the
++ * submission queue of the given DMA channel. Cancellation fails if the DRB has
++ * already been kicked off.
++ */
++int dmad_withdraw_request(dmad_chreq * ch_req, dmad_drb * drb)
++{
++ dmad_drq *drq = 0;
++ unsigned long lock_flags;
++
++ dmad_dbg("%s()\n", __func__);
++
++ if (unlikely(ch_req == NULL)) {
++ dmad_err("null ch_req!\n");
++ return -EFAULT;
++ }
++
++ drq = (dmad_drq *) ch_req->drq;
++
++ if (unlikely(drq == NULL)) {
++ dmad_err("null ch_req->drq!\n");
++ return -EBADR;
++ }
++
++ if (unlikely(drq->sbt_head == 0))
++ return -EBADR;
++
++ if (unlikely((drb->node == 0) || (drb->node >= DMAD_DRB_POOL_SIZE)))
++ return -EBADR;
++
++ spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
++
++ if (unlikely((drq->sbt_head == 0) || (drb->node == 0) ||
++ (drb->state != DMAD_DRB_STATE_SUBMITTED) ||
++ (drb->node >= DMAD_DRB_POOL_SIZE))) {
++ dmad_err("Submitted-queue is empty or invalid node!\n");
++
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++ return -EBADR;
++ }
++
++ dmad_dbg("cancel drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
++ "size(0x%08x) state(%d)\n",
++ drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
++ drb->req_cycle, drb->state);
++
++ if (unlikely(drb->state == DMAD_DRB_STATE_EXECUTED)) {
++ dmad_dbg("Already running drb cannot be stopped currently!\n");
++
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++ return 0;/*-EBADR; */
++ }
++
++ dmad_detach_node(drq->drb_pool,
++ &drq->rdy_head, &drq->rdy_tail, drb->node);
++ dmad_attach_tail(drq->drb_pool,
++ &drq->fre_head, &drq->fre_tail, drb->node);
++
++ drb->state = DMAD_DRB_STATE_FREE;
++
++ if (drb->sync)
++ complete_all(drb->sync);
++ drb->sync = 0;
++
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(dmad_withdraw_request);
++
++/**
++ * dmad_kickoff_requests_internal - kickoff hw DMA transmission
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @return : 0 if success, non-zero if any error
++ *
++ * Kickoff hw DMA transmission of the given DMA channel. This function is
++ * valid for both ring & non-ring mode. This is a lightweight internal version
++ * of dmad_kickoff_requests() majorly for use in ring mode. Critical access to
++ * the drb pool should be protected before entering this function.
++ */
++static inline int dmad_kickoff_requests_internal(dmad_drq * drq)
++{
++ dmad_drb *drb;
++
++ dmad_get_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb);
++
++ if (!drb) {
++ dmad_err("%s() null drb!\n", __func__);
++ return -EBADR;
++ }
++
++ dmad_dbg("%s() drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
++ "size(0x%08x) state(%d)\n", __func__,
++ drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
++ drb->req_cycle, drb->state);
++
++ if (drb->state == DMAD_DRB_STATE_SUBMITTED) {
++ /* Transfer size (in units of source width) */
++ outl(drb->req_cycle, (addr_t) drq->cyc_port);
++
++ /* Source and destination address */
++ if (drq->flags & DMAD_DRQ_DIR_A1_TO_A0) {
++ outl(drb->addr1, (addr_t) drq->src_port);
++ outl(drb->addr0, (addr_t) drq->dst_port);
++ } else {
++ outl(drb->addr0, (addr_t) drq->src_port);
++ outl(drb->addr1, (addr_t) drq->dst_port);
++ }
++
++ drb->state = DMAD_DRB_STATE_EXECUTED;
++ }
++
++ /* Enable DMA channel */
++ if (!dmad_is_channel_enabled(drq)) {
++ dmad_enable_channel(drq);
++ }
++
++ return 0;
++}
++
++/**
++ * dmad_kickoff_requests - kickoff hw DMA transmission of the given DMA channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @return : 0 if success, non-zero if any error
++ *
++ * Kickoff hw DMA transmission of the given DMA channel. This function is
++ * valid for both ring & non-ring mode.
++ */
++int dmad_kickoff_requests(dmad_chreq * ch_req)
++{
++ dmad_drq *drq = 0;
++ dmad_drb *drb = 0;
++ unsigned long lock_flags;
++ dma_addr_t req_cycle;
++
++ dmad_dbg("%s()\n", __func__);
++
++ if (unlikely(ch_req == NULL)) {
++ dmad_err("null ch_req!\n");
++ return -EFAULT;
++ }
++
++ drq = (dmad_drq *) ch_req->drq;
++
++ if (unlikely(drq == NULL)) {
++ dmad_err("null ch_req->drq!\n");
++ return -EBADR;
++ }
++
++ spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
++
++ dmad_get_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb);
++
++ dmad_dbg("drq(0x%08x) channel_base(0x%08x)\n",
++ (u32) drq, drq->channel_base);
++ dmad_dbg("kick off drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
++ "size(0x%08x) state(%d) a1_to_a0(%d)\n",
++ (u32) drb->node, (u32) drb, drb->addr0, drb->addr1,
++ drb->req_cycle, drb->state,
++ drq->flags & DMAD_DRQ_DIR_A1_TO_A0);
++
++ /* do nothing if no drbs are in the submission queue */
++ if (unlikely((drb == 0) || (drb->state != DMAD_DRB_STATE_SUBMITTED))) {
++ dmad_dbg("%s() invalid drb(%d 0x%08x) or drb-state(%d)!\n",
++ __func__,
++ drb->node, (u32) drb, drb ? drb->state : 0xffffffff);
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++ return 0;
++ }
++
++ req_cycle = drb->req_cycle;
++
++ if (unlikely(req_cycle == 0)) {
++ dmad_dbg("%s() zero transfer size!\n", __func__);
++ goto _safe_exit;
++ }
++
++ /* Transfer size (in units of source width) */
++ outl(req_cycle, (addr_t) drq->cyc_port);
++
++ /* Source and destination address */
++ if (drq->flags & DMAD_DRQ_DIR_A1_TO_A0) {
++ outl(drb->addr1, (addr_t) drq->src_port);
++ outl(drb->addr0, (addr_t) drq->dst_port);
++ } else {
++ outl(drb->addr0, (addr_t) drq->src_port);
++ outl(drb->addr1, (addr_t) drq->dst_port);
++ }
++
++ drb->state = DMAD_DRB_STATE_EXECUTED;
++
++ /* Enable DMA channel */
++ dmad_enable_channel(drq);
++
++_safe_exit:
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(dmad_kickoff_requests);
++
++/**
++ * dmad_probe_hw_ptr_src - probe DMA source hw-address of the given channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @return : physical address of current HW source pointer
++ *
++ * Probe DMA source hw-address of the given channel.
++ */
++dma_addr_t dmad_probe_hw_ptr_src(dmad_chreq * ch_req)
++{
++ return (dma_addr_t) inl(((dmad_drq *) ch_req->drq)->src_port);
++}
++
++EXPORT_SYMBOL_GPL(dmad_probe_hw_ptr_src);
++
++/**
++ * dmad_probe_hw_ptr_dst - probe DMA destination hw-address of the given channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @return : physical address of current HW destination pointer
++ *
++ * Probe DMA destination hw-address of the given channel.
++ */
++dma_addr_t dmad_probe_hw_ptr_dst(dmad_chreq * ch_req)
++{
++ return (dma_addr_t) inl(((dmad_drq *) ch_req->drq)->dst_port);
++}
++
++EXPORT_SYMBOL_GPL(dmad_probe_hw_ptr_dst);
++
++/**
++ * dmad_update_ring - update DMA ring buffer base && size of the given channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @size : [in] The new ring buffer size, in unit of data width (cycles)
++ * @return : 0 if success, non-zero if any error
++ *
++ * Update DMA ring buffer size of the given channel. This function is valid
++ * only if the channel is initialized as ring buffer mode.
++ */
++int dmad_update_ring(dmad_chreq * ch_req)
++{
++ unsigned long lock_flags;
++ dmad_drq *drq = (dmad_drq *) ch_req->drq;
++ int remnant;
++
++ if (unlikely(dmad_is_channel_enabled(drq))) {
++ dmad_err("%s() Error - dma channel should be "
++ "disabled before updating ring size!\n", __func__);
++ return -EFAULT;
++ }
++
++ spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
++
++ /* todo: range checking */
++
++ remnant = (int)ch_req->ring_size -
++ (int)ch_req->periods * (int)ch_req->period_size;
++ if (remnant == 0) {
++ drq->periods = ch_req->periods;
++ } else if (remnant > 0) {
++ drq->periods = ch_req->periods; // + 1;
++ } else {
++ dmad_err("%s() Error - buffer_size < "
++ "periods * period_size!\n", __func__);
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++ return -EFAULT;
++ }
++
++ drq->ring_base = ch_req->ring_base;
++ drq->ring_size = ch_req->ring_size;
++ drq->period_size = ch_req->period_size;
++ drq->remnant_size = (dma_addr_t) remnant;
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE) {
++ drq->period_bytes =
++ DMAC_CYCLE_TO_BYTES(drq->period_size, drq->data_width);
++ }
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE) {
++ drq->period_bytes =
++ APBBR_DMA_CYCLE_TO_BYTES(drq->period_size, drq->data_width);
++ }
++#endif
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++
++ dmad_dbg("%s() ring: base(0x%08x) port(0x%08x) periods(0x%08x) "
++ "period_size(0x%08x) period_bytes(0x%08x) "
++ "remnant_size(0x%08x)\n",
++ __func__, drq->ring_base, drq->ring_port,
++ drq->periods, drq->period_size, drq->period_bytes,
++ drq->remnant_size);
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(dmad_update_ring);
++
++/**
++ * dmad_update_ring_sw_ptr - update DMA ring buffer sw-pointer
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @sw_ptr : [in] The new sw-pointer for the hw-pointer to chase of
++ * @keep_fired : [in] non-zero to kickoff dma even the channel has stopped due
++ * to finishing its previous request
++ * @return : 0 if success, non-zero if any error
++ *
++ * Update DMA ring buffer sw-pointer of the given channel on the fly. This
++ * function is valid only if the channel is initialized as ring buffer mode.
++ * Uint of sw_ptr is in number of dma data width.
++ */
++int dmad_update_ring_sw_ptr(dmad_chreq * ch_req,
++ dma_addr_t sw_ptr, u8 keep_fired)
++{
++ dmad_drq *drq;
++ unsigned long lock_flags;
++ dma_addr_t hw_off = 0, ring_ptr;
++ dma_addr_t sw_p_off, ring_p_off, period_size, period_bytes;
++ dma_addr_t remnant_size;
++ int sw_p_idx, ring_p_idx, period, periods;
++ dmad_drb *drb = NULL;
++
++ /*if (ch_req == NULL) { */
++ /* dmad_dbg("%s() null ch_req!\n", __func__); */
++ /* return -EFAULT; */
++ /*} */
++
++ drq = (dmad_drq *) ch_req->drq;
++
++ /*if (drq == NULL) { */
++ /* dmad_dbg("%s() null ch_req->drq!\n", __func__); */
++ /* return -EBADR; */
++ /*} */
++
++ if (unlikely(sw_ptr > drq->ring_size)) {
++ dmad_err("%s() Invalid ring buffer sw-pointer "
++ "range (0x%08x)! ring_size(0x%08x)\n",
++ __func__, sw_ptr, drq->ring_size);
++ return -EBADR;
++ }
++
++ spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
++
++ periods = drq->periods;
++ period_size = drq->period_size;
++ period_bytes = drq->period_bytes;
++ remnant_size = drq->remnant_size;
++
++ ring_ptr = drq->sw_ptr;
++ ring_p_idx = drq->sw_p_idx;
++ ring_p_off = drq->sw_p_off;
++
++ sw_p_idx = (int)(sw_ptr / period_size);
++ sw_p_off = sw_ptr % period_size;
++
++ if (remnant_size && (sw_p_idx == periods)) {
++ --sw_p_idx;
++ sw_p_off += period_size;
++ }
++
++ dmad_dbg("%s() ring_ptr(0x%08x) ring_p_idx(0x%08x) "
++ "ring_p_off(0x%08x)\n",
++ __func__, ring_ptr, ring_p_idx, ring_p_off);
++ dmad_dbg("%s() sw_ptr(0x%08x) sw_p_idx(0x%08x) sw_p_off(0x%08x)\n",
++ __func__, sw_ptr, sw_p_idx, sw_p_off);
++
++ if (drq->ring_drb &&
++ (drq->ring_drb->state & (DMAD_DRB_STATE_READY |
++ DMAD_DRB_STATE_SUBMITTED |
++ DMAD_DRB_STATE_EXECUTED))) {
++ drb = drq->ring_drb;
++ } else {
++ /* alloc new drb if there is none yet at ring_ptr */
++ if (0 != dmad_alloc_drb_internal(drq, &drb)) {
++ dmad_err("%s() drb allocation failed!\n", __func__);
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++ return -ENOSPC;
++ }
++ drb->addr0 = ((dma_addr_t) ring_p_idx * period_bytes) +
++ drq->ring_base;
++ drb->addr1 = drq->dev_addr;
++ drb->req_cycle = 0; // redundent, though, no harm to performance
++
++ dmad_dbg("init_drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
++ "size(0x%08x) state(%d)\n",
++ (u32) drb->node, (u32) drb, drb->src_addr,
++ drb->dst_addr, drb->req_cycle, drb->state);
++
++ drq->ring_drb = drb;
++ }
++
++ /* Following code-path has been optimized. The design flow is expanded
++ * below for reference.
++ *
++ * if (sw_ptr >= ring_ptr)
++ * if (sw_p_idx == ring_p_idx)
++ * ring_drb::req_cycle <- sw_p_off
++ * if (ring_drb::state == executed)
++ * hw_cycle <- sw_p_idx
++ * fi
++ * else
++ * ring_drb::req_cycle <- period_size
++ * if (ring_drb::state == executed)
++ * hw_cycle <- period_size
++ * fi
++ * for (i = ring_p_idx+1 ~ sw_p_idx-1)
++ * new_drb::ring_addr <- i * period_bytes + ring_base
++ * new_drb::req_cycle <- period_size
++ * rof
++ * sw_drb::ring_addr <- sw_p_idx * period_bytes + ring_base
++ * sw_drb::req_cycle <- sw_p_off
++ * else
++ * // sw_ptr < ring_ptr
++ * ring_drb::req_cycle <- period_size
++ * if (ring_drb::state == executed)
++ * hw_cycle <- period_size
++ * fi
++ * for (i = ring_p_idx+1 ~ idx_max)
++ * new_drb::ring_addr <- i * period_bytes + ring_base
++ * new_drb::req_cycle <- period_size
++ * rof
++ * for (i = 0 ~ sw_p_idx-1)
++ * new_drb::ring_addr <- i * period_bytes + ring_base
++ * new_drb::req_cycle <- period_size
++ * rof
++ * sw_drb::ring_addr <- sw_p_idx * period_bytes + ring_base
++ * sw_drb::req_cycle <- sw_p_off
++ * fi
++ */
++ if ((sw_ptr >= ring_ptr) && (sw_p_idx == ring_p_idx) && (sw_p_off != 0)) {
++
++ dmad_dbg("update ring drb\n");
++
++ /* update drb size at ring_ptr */
++ drb->req_cycle = sw_p_off;
++
++ dmad_dbg("ring_drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
++ "size(0x%08x) state(%d)\n",
++ (u32) drb->node, (u32) drb, drb->addr0, drb->addr1,
++ drb->req_cycle, drb->state);
++
++ /* update hw dma size of this drb if it has been sent to the
++ * controller */
++ if (drb->state == DMAD_DRB_STATE_EXECUTED) {
++ dmad_disable_channel(drq);
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE)
++ hw_off = DMAC_BYTES_TO_CYCLE((addr_t)
++ inl((addr_t) drq->
++ ring_port) -
++ (addr_t) drb->
++ addr0,
++ drq->data_width);
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE)
++ hw_off = APBBR_DMA_BYTES_TO_CYCLE((addr_t)
++ inl((addr_t)
++ drq->
++ ring_port)
++ -
++ (addr_t) drb->
++ addr0,
++ drq->
++ data_width);
++#endif
++ dmad_dbg("hw_off(0x%08x) sw_p_off(0x%08x)\n",
++ (u32) hw_off, (u32) sw_p_off);
++
++ if (sw_p_off < hw_off)
++ dmad_err("%s() underrun! sw_p_off(0x%08x) <"
++ " hw_off(0x%08x)\n", __func__,
++ (u32) sw_p_off, (u32) hw_off);
++ else
++ outl(sw_p_off - hw_off, drq->cyc_port);
++
++ dmad_enable_channel(drq);
++
++ } else {
++ dmad_submit_request_internal(drq, drb);
++ }
++
++ } else {
++
++ dmad_dbg("fulfill ring drb - sw_ptr(0x%08x) ring_ptr(0x%08x)\n",
++ (u32) sw_ptr, (u32) ring_ptr);
++
++ /* fulfill last drb at ring_ptr */
++ if (ring_p_idx == (periods - 1))
++ drb->req_cycle = period_size + remnant_size;
++ else
++ drb->req_cycle = period_size;
++
++ dmad_dbg("ring_drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
++ "size(0x%08x) state(%d)\n",
++ (u32) drb->node, (u32) drb, drb->addr0, drb->addr1,
++ drb->req_cycle, drb->state);
++
++ if (drb->state == DMAD_DRB_STATE_EXECUTED) {
++ dmad_disable_channel(drq);
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE)
++ hw_off = DMAC_BYTES_TO_CYCLE((addr_t)
++ inl((addr_t) drq->
++ ring_port) -
++ (addr_t) drb->
++ addr0,
++ drq->data_width);
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE)
++ hw_off = APBBR_DMA_BYTES_TO_CYCLE((addr_t)
++ inl((addr_t)
++ drq->
++ ring_port)
++ -
++ (addr_t) drb->
++ addr0,
++ drq->
++ data_width);
++#endif
++ dmad_dbg("hw_off(0x%08x) period_size(0x%08x)\n",
++ (u32) hw_off, (u32) period_size);
++
++ if (ring_p_idx == (periods - 1)) {
++ if (period_size < hw_off)
++ dmad_err("%s() illegal! "
++ "period_size(0x%08x) + "
++ "remnant_size(0x%08x) < "
++ "hw_off(0x%08x)\n", __func__,
++ (u32) period_size,
++ (u32) remnant_size,
++ (u32) hw_off);
++ else
++ outl(period_size + remnant_size -
++ hw_off, drq->cyc_port);
++ } else {
++ if (period_size < hw_off)
++ dmad_err("%s() illegal! "
++ "period_size(0x%08x) < "
++ "hw_off(0x%08x)\n", __func__,
++ (u32) period_size,
++ (u32) hw_off);
++ else
++ outl(period_size - hw_off,
++ drq->cyc_port);
++ }
++
++ dmad_enable_channel(drq);
++
++ } else {
++ dmad_submit_request_internal(drq, drb);
++ }
++
++ ++ring_p_idx;
++
++ /* adjust sw_ptr period index ahead by one ring cycle */
++ //if (sw_ptr < ring_ptr) {
++ if (sw_p_idx < ring_p_idx) {
++ sw_p_idx += periods;
++ }
++
++ /* allocate in-between (ring_ptr+1 to sw_ptr-1)
++ * full-cycle drbs */
++ for (period = ring_p_idx; period < sw_p_idx; ++period) {
++ if (0 != dmad_alloc_drb_internal(drq, &drb)) {
++ dmad_err("%s() drb allocation failed!\n",
++ __func__);
++ spin_unlock_irqrestore(&drq->drb_pool_lock,
++ lock_flags);
++ return -ENOSPC;
++ }
++
++ drb->addr0 = (dma_addr_t) (period % periods) *
++ period_bytes + drq->ring_base;
++ drb->addr1 = drq->dev_addr;
++
++ if (period == (periods - 1)) {
++ drb->req_cycle = period_size + remnant_size;
++ } else {
++ drb->req_cycle = period_size;
++ }
++
++ dmad_dbg("inbtw_drb(%d 0x%08x) addr0(0x%08x) "
++ "addr1(0x%08x) size(0x%08x) state(%d)\n",
++ (u32) drb->node, (u32) drb, drb->addr0,
++ drb->addr1, drb->req_cycle, drb->state);
++
++ dmad_submit_request_internal(drq, drb);
++ }
++
++ /* allocate drb right at sw_ptr */
++ if (0 != dmad_alloc_drb_internal(drq, &drb)) {
++ dmad_err("%s() drb allocation failed!\n", __func__);
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++ return -ENOSPC;
++ }
++ drb->addr0 = (dma_addr_t) (sw_p_idx % periods) *
++ period_bytes + drq->ring_base;
++ drb->addr1 = drq->dev_addr;
++ drb->req_cycle = sw_p_off;
++
++ dmad_dbg("swptr_drb(%d 0x%08x) addr0(0x%08x) addr1(0x%08x) "
++ "size(0x%08x) state(%d)\n",
++ (u32) drb->node, (u32) drb, drb->addr0, drb->addr1,
++ drb->req_cycle, drb->state);
++
++ drq->ring_drb = drb;
++
++ if (sw_p_off > 0)
++ dmad_submit_request_internal(drq, drb);
++ }
++
++ drq->sw_ptr = sw_ptr % drq->ring_size;
++ drq->sw_p_idx = sw_p_idx % periods;
++ drq->sw_p_off = sw_p_off;
++
++ if (likely(keep_fired)) {
++ dmad_kickoff_requests_internal(drq);
++ }
++
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++
++ return 0;
++}
++
++EXPORT_SYMBOL_GPL(dmad_update_ring_sw_ptr);
++
++/**
++ * dmad_probe_ring_hw_ptr - probe DMA ring buffer position of the given channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @return : Ring buffer position of current HW ring buffer pointer
++ *
++ * Probe DMA ring buffer position of the given channel. The position is
++ * relative to the ring buffer base. This function is valid only if the
++ * channel is initialized as ring buffer mode.
++ */
++dma_addr_t dmad_probe_ring_hw_ptr(dmad_chreq * ch_req)
++{
++ dmad_drq *drq = (dmad_drq *) ch_req->drq;
++ dma_addr_t cycles =
++ (dma_addr_t) inl(drq->ring_port) - (dma_addr_t) drq->ring_base;
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (ch_req->controller == DMAD_DMAC_AHB_CORE)
++ cycles = DMAC_BYTES_TO_CYCLE(cycles, drq->data_width);
++#endif
++#ifdef CONFIG_PLATFORM_APBDMA
++ if (ch_req->controller == DMAD_DMAC_APB_CORE)
++ cycles = APBBR_DMA_BYTES_TO_CYCLE(cycles, drq->data_width);
++#endif
++ return cycles;
++}
++
++EXPORT_SYMBOL_GPL(dmad_probe_ring_hw_ptr);
++
++/**
++ * dmad_channel_drain - cancel DMA transmission of the given DMA channel
++ * @controller : [in] One of the enum value of DMAD_DMAC_CORE
++ * @drq : [in] Reference to the DMA queue structure (dmad_drq)
++ * @shutdown : [in] Non-zero to force a immediate channel shutdown
++ * @return : 0 if success, non-zero if any error
++ *
++ * Stop the DMA transmission and cancel all submitted requests of the given
++ * DMA channel. This function drains a single channel and is the internal
++ * implementation of the interface routine dmad_drain_requests() and the
++ * module_exit function.
++ */
++static int dmad_channel_drain(u32 controller, dmad_drq * drq, u8 shutdown)
++{
++ dmad_drb *drb = 0;
++ unsigned long lock_flags;
++
++ if (unlikely(drq == NULL)) {
++ dmad_err("null ch_req->drq!\n");
++ return -EBADR;
++ }
++
++ spin_lock_irqsave(&drq->drb_pool_lock, lock_flags);
++
++ /* Stop DMA channel if forced to shutdown immediately */
++ if (shutdown) {
++ /* disable dma controller */
++ dmad_reset_channel(drq);
++
++ /* todo: more settings to stop DMA controller ?? */
++
++ /*if (drb->state == DMAD_DRB_STATE_EXECUTED) { */
++ /*} */
++ }
++
++ /* Detach DRBs in submit queue */
++ dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail, &drb);
++
++ while (drb) {
++ dmad_dbg("cancel sbt drb(%d 0x%08x) addr0(0x%08x) "
++ "addr1(0x%08x) size(0x%08x) state(%d)\n",
++ drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
++ drb->req_cycle, (u32) drb->state);
++
++ /* Mark DRB state as abort */
++ drb->state = DMAD_DRB_STATE_ABORT;
++
++ if (drb->sync)
++ complete_all(drb->sync);
++
++ dmad_attach_tail(drq->drb_pool, &drq->fre_head, &drq->fre_tail,
++ drb->node);
++
++ dmad_detach_head(drq->drb_pool, &drq->sbt_head, &drq->sbt_tail,
++ &drb);
++ }
++
++ /* Detach DRBs in ready queue */
++ dmad_detach_head(drq->drb_pool, &drq->rdy_head, &drq->rdy_tail, &drb);
++
++ while (drb) {
++ dmad_dbg("cancel rdy drb(%d 0x%08x) addr0(0x%08x) "
++ "addr1(0x%08x) size(0x%08x) state(%d)\n",
++ drb->node, (u32) drb, drb->src_addr, drb->dst_addr,
++ drb->req_cycle, (u32) drb->state);
++
++ /* Mark DRB state as abort */
++ drb->state = DMAD_DRB_STATE_ABORT;
++
++ dmad_attach_tail(drq->drb_pool, &drq->fre_head, &drq->fre_tail,
++ drb->node);
++
++ /* Detach next submitted DRB (DMA Request Block) from the
++ * DRQ (DMA Request Queue) */
++ dmad_detach_head(drq->drb_pool, &drq->rdy_head, &drq->rdy_tail,
++ &drb);
++ }
++
++ drq->state |= DMAD_DRQ_STATE_ABORT;
++
++ drq->ring_drb = NULL;
++ drq->sw_ptr = 0;
++ drq->sw_p_idx = 0;
++ drq->sw_p_off = 0;
++
++ spin_unlock_irqrestore(&drq->drb_pool_lock, lock_flags);
++
++ if ( /*(drq->fre_head == 0) && */ (drq->flags & DMAD_FLAGS_SLEEP_BLOCK)) {
++ complete_all(&drq->drb_alloc_sync);
++ }
++
++ return 0;
++}
++
++/**
++ * dmad_cancel_requests - cancel DMA transmission of the given DMA channel
++ * @ch_req : [in] Reference to the DMA request descriptor structure
++ * @shutdown : [in] Non-zero to force a immediate channel shutdown
++ * @return : 0 if success, non-zero if any error
++ *
++ * Stop the DMA transmission and cancel all submitted requests of the given
++ * DMA channel.
++ */
++int dmad_drain_requests(dmad_chreq * ch_req, u8 shutdown)
++{
++ dmad_dbg("%s()\n", __func__);
++
++ if (ch_req == NULL) {
++ dmad_err("null ch_req!\n");
++ return -EFAULT;
++ }
++
++ return dmad_channel_drain(ch_req->controller, ch_req->drq, shutdown);
++}
++
++EXPORT_SYMBOL_GPL(dmad_drain_requests);
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++
++/**
++ * dmad_probe_irq_source - probe DMA channel who asserts the shared sw-irq line
++ * @return : The channel number which asserts the shared sw-irq line
++ *
++ * Probe DMA channel who asserts the shared sw-irq line.
++ */
++int dmad_probe_irq_source_ahb(void)
++{
++ int channel; /* interrupt channel number */
++
++ /* todo: spin_lock */
++
++ /* - Check DMA status register to get channel number */
++ for (channel = 0; channel < DMAD_AHB_MAX_CHANNELS; ++channel) {
++ if (getbl(channel, DMAC_INT_TC))
++ return channel;
++ }
++
++ /* Perform DMA error checking if no valid channel was found who
++ * assert the finish signal. */
++ for (channel = 0; channel < DMAD_AHB_MAX_CHANNELS; ++channel) {
++ if (getbl(channel, DMAC_INT_ERRABT))
++ return channel;
++ if (getbl(channel << DMAC_INT_ABT_SHIFT, DMAC_INT_ERRABT))
++ return channel;
++ }
++
++ /* todo: spin_unlock */
++
++ return -EFAULT;
++}
++
++EXPORT_SYMBOL_GPL(dmad_probe_irq_source_ahb);
++
++#endif /* CONFIG_PLATFORM_AHBDMA */
++
++#ifdef CONFIG_PLATFORM_APBDMA
++
++int dmad_probe_irq_source_apb(void)
++{
++ int channel; /* interrupt channel number */
++
++ /* todo: spin_lock */
++
++ /* Check DMA status register to get channel number */
++ for (channel = 0; channel < DMAD_APB_MAX_CHANNELS; ++channel) {
++ if (getbl(APBBR_DMA_FINTST_BIT, APBBR_DMA_BASE_CH(channel) +
++ APBBR_DMA_CMD_OFFSET))
++ return channel;
++ }
++
++ /* Perform DMA error checking if no valid channel was found who
++ * assert the finish signal. */
++ for (channel = 0; channel < DMAD_APB_MAX_CHANNELS; ++channel) {
++ if (getbl(APBBR_DMA_ERRINTST_BIT, APBBR_DMA_BASE_CH(channel) +
++ APBBR_DMA_CMD_OFFSET))
++ return channel;
++ }
++
++ /* todo: spin_unlock */
++
++ return -EFAULT;
++}
++
++EXPORT_SYMBOL_GPL(dmad_probe_irq_source_apb);
++
++#endif /* CONFIG_PLATFORM_APBDMA */
++
++/**
++ * dmad_module_init - dma module-init function
++ * @return : 0 if success, non-zero if any error
++ */
++int __init dmad_module_init(void)
++{
++ int err = 0;
++ dmad_dbg("%s() >>\n", __func__);
++
++ /* clear device struct since the module may be load/unload many times */
++ memset(&dmad, 0, sizeof(dmad));
++
++ dmad.drq_pool =
++ kmalloc((DMAD_AHB_MAX_CHANNELS +
++ DMAD_APB_MAX_CHANNELS) * sizeof(dmad_drq), GFP_KERNEL);
++ if (dmad.drq_pool == NULL) {
++ dmad_err("%s() failed to allocate drb pool!\n", __func__);
++ return -ENOMEM;
++ }
++
++ memset(dmad.drq_pool, 0,
++ (DMAD_AHB_MAX_CHANNELS + DMAD_APB_MAX_CHANNELS) *
++ sizeof(dmad_drq));
++
++ spin_lock_init(&dmad.drq_pool_lock);
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ dmad.ahb_drq_pool = dmad.drq_pool;
++ if (unlikely(!request_region(DMAC_BASE, SZ_1K, "AHB DMAC"))) {
++ dmad_err("Cannot reserve AHB DMAC I/O region\n");
++ err = -EBUSY;
++ }
++#endif
++
++#ifdef CONFIG_PLATFORM_APBDMA
++ dmad.apb_drq_pool = &dmad.drq_pool[DMAD_AHB_MAX_CHANNELS];
++ if (unlikely(!request_region(APBBR_BASE, SZ_1K, "APB DMAC"))) {
++ dmad_err("Cannot reserve APB DMAC I/O region\n");
++ err = -EBUSY;
++ }
++#endif
++
++ dmad_dbg("DMA module init result: (%d)\n", err);
++ dmad_dbg(" AHB channels: %d; APB channels %d; "
++ "DRBs per channel: %d\n",
++ DMAC_MAX_CHANNELS, APBBR_DMA_MAX_CHANNELS, DMAD_DRB_POOL_SIZE);
++
++ dmad_dbg("%s() return code (%d) <<\n", __func__, err);
++ return err;
++}
++
++/**
++ * dmad_module_init - dma module clean up function
++ */
++void __exit dmad_module_exit(void)
++{
++ dmad_drq *drq;
++ u32 channel;
++
++ dmad_dbg("%s() >>\n", __func__);
++
++ spin_lock(&dmad.drq_pool_lock);
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ /* cancel existing requests and unregister interrupt handler */
++ for (channel = 0; channel < DMAD_AHB_MAX_CHANNELS; ++channel) {
++
++ /* shutdown dma requests */
++ drq = (dmad_drq *) & dmad.ahb_drq_pool[channel];
++
++ if ((drq->state & DMAD_DRQ_STATE_READY) != 0)
++ dmad_channel_drain(DMAD_DMAC_AHB_CORE, drq, 1);
++
++ /* free registered irq handlers */
++ free_irq(ahb_irqs[channel], (void *)(channel + 1));
++ }
++#endif
++
++#ifdef CONFIG_PLATFORM_APBDMA
++ /* cancel existing requests and unregister interrupt handler */
++ for (channel = 0; channel < DMAD_APB_MAX_CHANNELS; ++channel) {
++
++ /* shutdown dma requests */
++ drq = (dmad_drq *) & dmad.apb_drq_pool[channel];
++
++ if ((drq->state & DMAD_DRQ_STATE_READY) != 0)
++ dmad_channel_drain(DMAD_DMAC_APB_CORE, drq, 1);
++
++ /* free registered irq handlers */
++ free_irq(apb_irqs[channel], (void *)(channel + 1));
++ }
++#endif
++ spin_unlock(&dmad.drq_pool_lock);
++
++ if (dmad.drq_pool)
++ kfree(dmad.drq_pool);
++ memset(&dmad, 0, sizeof(dmad));
++
++ /* release I/O space */
++#ifdef CONFIG_PLATFORM_AHBDMA
++ release_region(DMAC_BASE, SZ_1K);
++#endif /*CONFIG_PLATFORM_AHBDMA */
++
++#ifdef CONFIG_PLATFORM_APBDMA
++ release_region(APBBR_BASE, SZ_1K);
++#endif /* CONFIG_PLATFORM_APBDMA */
++
++ dmad_dbg("DMA module unloaded!\n");
++}
++
++#ifndef MODULE
++arch_initcall(dmad_module_init);
++#else
++module_init(dmad_module_init);
++module_exit(dmad_module_exit);
++#endif
++
++#endif /* CONFIG_PLATFORM_AHBDMA || CONFIG_PLATFORM_APBDMA */
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/dmad_intc.c linux-3.4.110/arch/nds32/platforms/dmad_intc.c
+--- linux-3.4.110.orig/arch/nds32/platforms/dmad_intc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/dmad_intc.c 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,124 @@
++/*
++ * linux/arch/armnommu/mach-faraday/platform-a320/apb_intc.c
++ *
++ * Faraday AHB DMA Interrupt Process Driver Implementation
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.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.
++ *
++ *
++ * ChangeLog
++ *
++ * Peter Liao 09/28/2005 Created
++ */
++
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <asm/io.h>
++
++#include <asm/intc.h>
++#include <asm/spec.h>
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++extern int dmad_probe_irq_source_ahb(void);
++
++void AHBDMA_irq_rounter(unsigned int irq, struct irq_desc *desc)
++{
++ int ahb_irq;
++ struct irq_desc *ahb_desc;
++ struct irq_data data;
++ data.irq = irq;
++
++ raw_spin_lock(&desc->lock);
++ desc->irq_data.chip->irq_mask(&data);
++ desc->irq_data.chip->irq_ack(&data);
++
++ ahb_irq = dmad_probe_irq_source_ahb();
++ if (ahb_irq >= 0) {
++ ahb_irq += DMAC_FTDMAC020_IRQ0;
++ ahb_desc = irq_desc + ahb_irq;
++
++ raw_spin_unlock(&desc->lock);
++ ahb_desc->handle_irq(ahb_irq, ahb_desc);
++ raw_spin_lock(&desc->lock);
++ }
++
++ desc->irq_data.chip->irq_unmask(&data);
++ raw_spin_unlock(&desc->lock);
++}
++
++int __init intc_ftdmac020_init_irq(void)
++{
++ int i;
++
++ /* Register all IRQ */
++ for (i = DMAC_FTDMAC020_IRQ0;
++ i < DMAC_FTDMAC020_IRQ0 + DMAC_FTDMAC020_IRQ_COUNT; i++) {
++ // level trigger
++ irq_set_chip(i, &dummy_irq_chip);
++ irq_set_handler(i, handle_simple_irq);
++ }
++ irq_set_chained_handler(PLATFORM_AHBDMA_IRQ, AHBDMA_irq_rounter);
++
++ return 0;
++}
++
++arch_initcall(intc_ftdmac020_init_irq);
++#endif /* CONFIG_PLATFORM_AHBDMA */
++
++#ifdef CONFIG_PLATFORM_APBDMA
++extern int dmad_probe_irq_source_apb(void);
++
++void APBDMA_irq_rounter(unsigned int irq, struct irq_desc *desc)
++{
++ int apb_irq;
++ struct irq_desc *apb_desc;
++ struct irq_data data;
++ data.irq = irq;
++
++ raw_spin_lock(&desc->lock);
++
++ //mask_ack_irq(desc, irq);
++ desc->irq_data.chip->irq_mask(&data);
++ desc->irq_data.chip->irq_ack(&data);
++
++ apb_irq = dmad_probe_irq_source_apb();
++ //printk(KERN_INFO "irq (%d) ch(%d)\n", irq, apb_irq);
++
++ if (apb_irq >= 0) {
++ apb_irq += APBBRG_FTAPBBRG020S_0_IRQ0;
++ apb_desc = irq_desc + apb_irq;
++
++ raw_spin_unlock(&desc->lock);
++ apb_desc->handle_irq(irq, apb_desc);
++ raw_spin_lock(&desc->lock);
++ }
++
++ desc->irq_data.chip->irq_unmask(&data);
++ raw_spin_unlock(&desc->lock);
++}
++
++int __init intc_ftapbbrg020s_init_irq(void)
++{
++ int i;
++
++ /* Register all IRQ */
++ for (i = APBBRG_FTAPBBRG020S_0_IRQ0;
++ i < APBBRG_FTAPBBRG020S_0_IRQ0 + APBBRG_FTAPBBRG020S_IRQ_COUNT;
++ i++) {
++ // level trigger
++ irq_set_chip(i, &dummy_irq_chip);
++ irq_set_handler(i, handle_simple_irq);
++ }
++
++ irq_set_chained_handler(PLATFORM_APBDMA_IRQ, APBDMA_irq_rounter);
++
++ return 0;
++}
++
++arch_initcall(intc_ftapbbrg020s_init_irq);
++#endif /* CONFIG_PLATFORM_APBDMA */
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/ftpci.c linux-3.4.110/arch/nds32/platforms/ftpci.c
+--- linux-3.4.110.orig/arch/nds32/platforms/ftpci.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/ftpci.c 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,497 @@
++/*
++ * linux/arch/nds32/platforms/ftpci.c
++ *
++ * Faraday FTPCI100 PCI Bridge Controller Device Driver Implementation
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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
++ *
++ *
++ * ChangeLog
++ *
++ * Peter Liao 09/28/2005 Created.
++ */
++
++#include <linux/sched.h>
++#include <linux/kernel.h>
++#include <linux/pci.h>
++#include <linux/ptrace.h>
++#include <linux/slab.h>
++#include <linux/ioport.h>
++#include <linux/interrupt.h>
++#include <linux/spinlock.h>
++#include <linux/init.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/mach/pci.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/ftpci.h>
++#include <asm/spec.h>
++#include <asm/mach-types.h>
++
++#define IPMODULE PCIC
++#define IPNAME FTPCI100
++
++#define DEBUGFPCI
++#undef DEBUGFPCI
++
++#ifdef DEBUGFPCI
++#define DBGFPCI(x...) printk(x)
++#else
++#define DBGFPCI(x...)
++#endif
++#define FPCI_VA_BASE IP_VA_BASE(0)
++#define FTPCI_PCI_BRIDGE_VENID PCI_BRIDGE_VENID
++#define FPCI_IO_VA_BASE PCIIO_VA_BASE
++#define FPCI_IO_PA_BASE PCIIO_PA_BASE
++#define FPCI_IO_VA_END PCIIO_VA_LIMIT
++#define FPCI_MEM_VA_BASE PCIMEM_VA_BASE
++#define FPCI_MEM_PA_BASE PCIMEM_PA_BASE
++#define FPCI_MEM_VA_END PCIMEM_VA_LIMIT
++#define FPCI_MEM_PA_END (PCIMEM_PA_BASE + SZ_256M)
++
++// --------------------------------------------------------------------
++// AHB Control Register
++// --------------------------------------------------------------------
++#define FTPCI_IOSIZE_REG 0x0
++#define FTPCI_PROT_REG 0x4
++#define FTPCI_CTRL_REG 0x8
++#define FTPCI_ERREN_REG 0xc
++#define FTPCI_SOFTRST_REG 0x10
++#define FTPCI_EN64_REG 0x14
++#define FTPCI_ADDRH32_REG 0x18
++#define FTPCI_CFG_ADR_REG 0x28
++#define FTPCI_CFG_DATA_REG 0x2c
++
++// --------------------------------------------------------------------
++// FTPCI_IOSIZE_REG's constant definitions
++// --------------------------------------------------------------------
++#define FTPCI_BASE_IO_SIZE_1M 0x0
++#define FTPCI_BASE_IO_SIZE_2M 0x1
++#define FTPCI_BASE_IO_SIZE_4M 0x2
++#define FTPCI_BASE_IO_SIZE_8M 0x3
++#define FTPCI_BASE_IO_SIZE_16M 0x4
++#define FTPCI_BASE_IO_SIZE_32M 0x5
++#define FTPCI_BASE_IO_SIZE_64M 0x6
++#define FTPCI_BASE_IO_SIZE_128M 0x7
++#define FTPCI_BASE_IO_SIZE_256M 0x8
++#define FTPCI_BASE_IO_SIZE_512M 0x9
++#define FTPCI_BASE_IO_SIZE_1G 0xa
++#define FTPCI_BASE_IO_SIZE_2G 0xb
++
++// --------------------------------------------------------------------
++// PCI Configuration Register
++// --------------------------------------------------------------------
++#define PCI_INT_MASK 0x4c
++#define PCI_MEM_BASE_SIZE1 0x50
++#define PCI_MEM_BASE_SIZE2 0x54
++#define PCI_MEM_BASE_SIZE3 0x58
++
++// --------------------------------------------------------------------
++// PCI_INT_MASK's bit definitions
++// --------------------------------------------------------------------
++#define PCI_INTA_ENABLE (1U<<22)
++#define PCI_INTB_ENABLE (1U<<23)
++#define PCI_INTC_ENABLE (1U<<24)
++#define PCI_INTD_ENABLE (1U<<25)
++
++// --------------------------------------------------------------------
++// PCI_MEM_BASE_SIZE1's constant definitions
++// --------------------------------------------------------------------
++#define FTPCI_BASE_ADR_SIZE_1MB (PHYS_OFFSET | (0x0<<16))
++#define FTPCI_BASE_ADR_SIZE_2MB (PHYS_OFFSET | (0x1<<16))
++#define FTPCI_BASE_ADR_SIZE_4MB (PHYS_OFFSET | (0x2<<16))
++#define FTPCI_BASE_ADR_SIZE_8MB (PHYS_OFFSET | (0x3<<16))
++#define FTPCI_BASE_ADR_SIZE_16MB (PHYS_OFFSET | (0x4<<16))
++#define FTPCI_BASE_ADR_SIZE_32MB (PHYS_OFFSET | (0x5<<16))
++#define FTPCI_BASE_ADR_SIZE_64MB (PHYS_OFFSET | (0x6<<16))
++#define FTPCI_BASE_ADR_SIZE_128MB (PHYS_OFFSET | (0x7<<16))
++#define FTPCI_BASE_ADR_SIZE_256MB (PHYS_OFFSET | (0x8<<16))
++#define FTPCI_BASE_ADR_SIZE_512MB (PHYS_OFFSET | (0x9<<16))
++#define FTPCI_BASE_ADR_SIZE_1GB (PHYS_OFFSET | (0xa<<16))
++#define FTPCI_BASE_ADR_SIZE_2GB (PHYS_OFFSET | (0xb<<16))
++
++#define CONFIG_CMD(bus, device_fn, where) (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3) )
++
++struct pci_dev *pci_bridge = NULL;
++static unsigned int pci_config_addr;
++static unsigned int pci_config_data;
++int ftpci_probed = 0;
++
++static struct resource pcic_resource = {
++ .name = "Faradat PCIC",
++ .start = IP_VA_BASE(0),
++ .end = IP_VA_LIMIT(0),
++};
++
++// Luke Lee 03/21/2005 mod begin
++static int ftpci_read_config_byte(struct pci_bus *bus, unsigned int devfn,
++ int where, u8 * val)
++{
++ u32 v;
++ unsigned int shift;
++
++ outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = inl(pci_config_data);
++ shift = (where & 0x3) * 8;
++ *val = (v >> shift) & 0xff;
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int ftpci_read_config_word(struct pci_bus *bus, unsigned int devfn,
++ int where, u16 * val)
++{
++ u32 v;
++ unsigned int shift;
++
++ outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = inl(pci_config_data);
++ shift = (where & 0x3) * 8;
++ *val = (v >> shift) & 0xffff;
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int ftpci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
++ int where, u32 * val)
++{
++ u32 v;
++
++ outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ v = inl(pci_config_data);
++ *val = v;
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int ftpci_write_config_byte(struct pci_bus *bus, unsigned int devfn,
++ int where, u8 val)
++{
++ u32 org_val;
++ unsigned int shift;
++
++ shift = (where & 0x3) * 8;
++ outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ org_val = inl(pci_config_data);
++ org_val = (org_val & ~(0xff << shift)) | ((u32) val << shift);
++ outl(org_val, pci_config_data);
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int ftpci_write_config_word(struct pci_bus *bus, unsigned int devfn,
++ int where, u16 val)
++{
++ u32 org_val;
++ unsigned int shift;
++
++ shift = (where & 0x3) * 8;
++ outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ org_val = inl(pci_config_data);
++ org_val = (org_val & ~(0xffff << shift)) | ((u32) val << shift);
++ outl(org_val, pci_config_data);
++ return PCIBIOS_SUCCESSFUL;
++}
++
++static int ftpci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
++ int where, u32 val)
++{
++ outl(CONFIG_CMD(bus->number, devfn, where), pci_config_addr);
++ outl(val, pci_config_data);
++ return PCIBIOS_SUCCESSFUL;
++}
++
++// Luke Lee 03/21/2005 mod end
++
++// Luke Lee 03/21/2005 ins begin
++static int ftpci_read_config(struct pci_bus *bus, unsigned int devfn, int where,
++ int size, u32 * val)
++{
++ int r;
++ switch (size) {
++ case 1:
++ r = ftpci_read_config_byte(bus, devfn, where, (u8 *) val); // Luke Lee TOFIX 03/22/2005 : convert to (u8*) -- beware of endian !
++ break;
++ case 2:
++ r = ftpci_read_config_word(bus, devfn, where, (u16 *) val); // Luke Lee TOFIX 03/22/2005 : convert to (u16*) -- beware of endian !
++ break;
++
++ default:
++ r = ftpci_read_config_dword(bus, devfn, where, val);
++ break;
++ }
++
++ return r;
++}
++
++static int ftpci_write_config(struct pci_bus *bus, unsigned int devfn,
++ int where, int size, u32 val)
++{
++ int r;
++ switch (size) {
++ case 1:
++ r = ftpci_write_config_byte(bus, devfn, where, val);
++ break;
++ case 2:
++ r = ftpci_write_config_word(bus, devfn, where, val);
++ break;
++
++ case 4:
++ r = ftpci_write_config_dword(bus, devfn, where, val);
++ break;
++ default:
++ printk("Invalid size for ftpci_write()\n");
++ r = PCIBIOS_FUNC_NOT_SUPPORTED; // Luke Lee 03/23/2005 ins 1
++ }
++
++ return r;
++}
++
++// Luke Lee 03/21/2005 ins end
++
++static struct pci_ops ftpci_ops = {
++ // Luke Lee 03/21/2005 mod begin
++ .read = ftpci_read_config,
++ .write = ftpci_write_config,
++ // Luke Lee 03/21/2005 mod end
++};
++
++/* using virtual address for pci_resource_start() function*/
++static struct resource pci_io = {
++ .name = "Faraday PCI I/O Space",
++ .start = FPCI_IO_VA_BASE,
++ .end = FPCI_IO_VA_END,
++ .flags = IORESOURCE_IO,
++};
++
++/* using physical address for memory resource*/
++static struct resource pci_mem = {
++ .name = "Faraday PCI non-prefetchable Memory Space",
++ .start = FPCI_MEM_PA_BASE,
++ .end = FPCI_MEM_PA_END,
++ .flags = IORESOURCE_MEM,
++};
++
++// Luke Lee 03/23/2005 unrem 1 rem 1
++int __init ftpci_setup_resource(struct resource **resource)
++{
++ DBGFPCI("PCI I/O space from %08lX to %08lX\n", pci_io.start,
++ pci_io.end);
++ DBGFPCI("PCI Memory space from %08lX to %08lX\n", pci_mem.start,
++ pci_mem.end);
++ if (request_resource(&ioport_resource, &pci_io)) {
++ printk(KERN_ERR "PCI: unable to allocate io region\n");
++ return -EBUSY; // Luke Lee 03/23/2005 unrem 1
++ }
++ if (request_resource(&iomem_resource, &pci_mem)) {
++ printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
++ "memory region\n");
++ return -EBUSY; // Luke Lee 03/23/2005 unrem 1
++ }
++
++ /*
++ * bus->resource[0] is the IO resource for this bus
++ * bus->resource[1] is the mem resource for this bus
++ * bus->resource[2] is the prefetch mem resource for this bus
++ */
++
++ resource[0] = &pci_io;
++ resource[1] = &pci_mem;
++ resource[2] = NULL;
++
++ return 1; // Luke Lee 03/23/2005 unrem 1
++}
++
++int ftpci_get_irq(void)
++{
++ unsigned int status;
++ ftpci_read_config_dword(pci_bridge->bus, pci_bridge->devfn, 0x4c, &status); // Luke Lee 03/22/2005 mod 1
++ DBGFPCI("ftpci_get_irq,status=0x%x\n", status);
++ status = (status >> 28);
++ if (status & 0x1)
++ return 0;
++ if (status & 0x2)
++ return 1;
++ if (status & 0x4)
++ return 2;
++ if (status & 0x8)
++ return 3;
++ return -1;
++}
++
++void ftpci_clear_irq(unsigned int irq)
++{
++ //int i;
++ unsigned int status;
++ ftpci_read_config_dword(pci_bridge->bus, pci_bridge->devfn, 0x4c, &status); // Luke Lee 03/22/2005 mod 1
++ if (irq == 0)
++ status = (status & 0xfffffff) | ((0x1) << 28);
++ else if (irq == 1)
++ status = (status & 0xfffffff) | ((0x2) << 28);
++ else if (irq == 2)
++ status = (status & 0xfffffff) | ((0x4) << 28);
++ else if (irq == 3)
++ status = (status & 0xfffffff) | ((0x8) << 28);
++ ftpci_write_config_dword(pci_bridge->bus, pci_bridge->devfn, 0x4c, status); // Luke Lee 03/22/2005 mod 1
++}
++
++void ftpci_unmask_irq(unsigned int irq)
++{
++ u32 val;
++ ftpci_read_config_dword(pci_bridge->bus, pci_bridge->devfn,
++ PCI_INT_MASK, &val);
++ val |= (PCI_INTA_ENABLE << irq);
++ ftpci_write_config_dword(pci_bridge->bus, pci_bridge->devfn,
++ PCI_INT_MASK, val);
++}
++
++void ftpci_mask_irq(unsigned int irq)
++{
++ u32 val;
++ ftpci_read_config_dword(pci_bridge->bus, pci_bridge->devfn,
++ PCI_INT_MASK, &val);
++ val &= ~(PCI_INTA_ENABLE << irq);
++ ftpci_write_config_dword(pci_bridge->bus, pci_bridge->devfn,
++ PCI_INT_MASK, val);
++}
++
++static int ftpci_probe(unsigned int addr_p)
++{
++ unsigned int *addr = (unsigned int *)addr_p;
++ *(volatile unsigned int *)addr = 0x80000000;
++ if (*(volatile unsigned int *)addr == 0x80000000) {
++ DBGFPCI("Faraday FPCI bridge probed ok\n");
++ ftpci_probed = 1;
++ } else {
++ ftpci_probed = 0;
++ }
++ *(volatile unsigned int *)addr = 0x0;
++ return ftpci_probed;
++}
++
++void __init ftpci_preinit(void /**sysdata*/ ) // Luke Lee 03/22/2005 mod 1
++{
++ DBGFPCI("ftpci_preinit()\n\r");
++
++#ifdef CONFIG_PLAT_AG101
++ /* Walk around for A321 but remove after leopard pci */
++ *(volatile unsigned long *)(FPCI_VA_BASE + 0x8) = 0x10;
++#endif
++
++ pci_config_addr = FPCI_VA_BASE + FTPCI_CFG_ADR_REG;
++ pci_config_data = FPCI_VA_BASE + FTPCI_CFG_DATA_REG;
++ DBGFPCI("Config addr is %08X, data port is %08X\n",
++ (int)pci_config_addr, (int)pci_config_data);
++
++ if (!ftpci_probe(pci_config_addr))
++ return;
++}
++
++void ftpci_postinit(void /**sysdata*/ )
++{
++ u32 val;
++ DBGFPCI("ftpci_postinit()\n\r");
++ pci_bridge = pci_get_device(PCI_BRIDGE_VENID, PCI_BRIDGE_DEVID, NULL);
++ if (pci_bridge == NULL)
++ return;
++ // Enable the Interrupt Mask (INTA/INTB/INTC/INTD)
++ ftpci_read_config_dword(pci_bridge->bus, pci_bridge->devfn, PCI_INT_MASK, &val); // Luke Lee 03/22/2005 mod 1
++ val |=
++ (PCI_INTA_ENABLE | PCI_INTB_ENABLE | PCI_INTC_ENABLE |
++ PCI_INTD_ENABLE);
++ ftpci_write_config_dword(pci_bridge->bus, pci_bridge->devfn, PCI_INT_MASK, val); // Luke Lee 03/22/2005 mod 1
++
++ // Write DMA Start Address/Size Data to the Bridge configuration space
++ ftpci_write_config_dword(pci_bridge->bus, pci_bridge->devfn, PCI_MEM_BASE_SIZE1, FTPCI_BASE_ADR_SIZE_1GB); // Luke Lee 03/22/2005 mod 1
++ DBGFPCI("%s: Post init ok\n", __func__);
++}
++
++/*
++ * This routine handles multiple bridges.
++ */
++static u8 __init fpci_swizzle(struct pci_dev *dev, u8 * pinp)
++{
++ // If there are one more bridges on our platfrom, we need to implement this function.
++ DBGFPCI("a320_swizzle(%X,%X)\n\r", (unsigned)dev, (unsigned)pinp);
++ return 0;
++}
++
++static int __init fpci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
++{
++ DBGFPCI("a320_map_irq,slot=%d pin=%d\n", PCI_SLOT(dev->devfn), pin);
++ switch ((PCI_SLOT(dev->devfn) + pin - 8 - 1) % 4) {
++ case 0:
++ return IP_IRQ0(0);
++ case 1:
++ return IP_IRQ1(0);
++ case 2:
++ return IP_IRQ2(0);
++ case 3:
++ return IP_IRQ3(0);
++ default:
++ printk(KERN_ERR "Not Support Slot %d\n", slot);
++ break;
++ }
++ return -1;
++}
++
++int __init ftpci_setup(int nr, struct pci_sys_data *sys)
++{
++ int ret = 0;
++ if (nr == 0) {
++ ret = ftpci_setup_resource(sys->resource);
++// sys->mem_offset = FPCI_MEM_VA_BASE - FPCI_MEM_PA_BASE;
++ sys->mem_offset = 0;
++ sys->io_offset = FPCI_IO_VA_BASE - FPCI_IO_PA_BASE;
++ }
++ return ret;
++}
++
++static struct pci_bus *__devinit ftpci_scan_bus(int nr,
++ struct pci_sys_data *sys)
++{
++ return pci_scan_bus(sys->busnr, &ftpci_ops, sys);
++}
++
++static struct hw_pci a320_pci __initdata = {
++ .swizzle = fpci_swizzle,
++ .map_irq = fpci_map_irq,
++ .setup = ftpci_setup,
++ .nr_controllers = 1,
++ .scan = ftpci_scan_bus,
++ .preinit = ftpci_preinit, /* The first called init function */
++ .postinit = ftpci_postinit, /* It is called after hw init and scanned PCI bus */
++};
++
++static int __init fpci_init(void)
++{
++#ifdef MODULE
++ printk(KERN_INFO "Faraday PCI driver Init");
++#endif
++ printk(KERN_DEBUG "Init A321 PCI bridge controller\n");
++ /* Register I/O address range of this PCI Bridge Controller */
++ DBGFPCI("Name:%s, Base=%lX, End=%lX\n", pcic_resource.name,
++ pcic_resource.start, pcic_resource.end);
++ request_resource(&ioport_resource, &pcic_resource);
++ pci_common_init(&a320_pci);
++ return 0;
++}
++
++subsys_initcall(fpci_init);
++
++EXPORT_SYMBOL(ftpci_probed);
++EXPORT_SYMBOL(ftpci_clear_irq);
++EXPORT_SYMBOL(ftpci_get_irq);
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/intc.c linux-3.4.110/arch/nds32/platforms/intc.c
+--- linux-3.4.110.orig/arch/nds32/platforms/intc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/intc.c 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,257 @@
++/*
++ * linux/arch/nds32/platforms/intc.c
++ *
++ * Faraday FTINTC010 Master Interrupt Controller Device Driver Implementation
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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
++ *
++ * Note
++ *
++ * This program implements only the master INTC of the platform. Slave INTCs must
++ * be initialized by themselves.
++ *
++ * ChangeLog
++ *
++ * Luke Lee 09/14/2005 Created.
++ */
++
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <asm/io.h>
++
++#include <asm/intc.h>
++#include <asm/spec.h>
++#include <asm/ftpci.h>
++
++#define IPMODULE INTC
++#define IPNAME FTINTC010
++
++/*
++ * Edge trigger IRQ chip methods
++ */
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++spinlock_t irq_chip_lock;
++#endif
++
++static void intc_ftintc010_ack_irq(struct irq_data *data)
++{
++ unsigned int tmp;
++
++ // ack and disable
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++ spin_lock_irq(&irq_chip_lock);
++#endif
++ *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_CLEAR_REG) = 1 << data->irq;
++ tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_CLEAR_REG);
++ tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MODE_REG);
++
++ if (!(tmp & (1UL << data->irq))) { /* level trigger */
++
++ *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG) &=
++ ~(1 << data->irq);
++ tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG);
++ }
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++ spin_unlock_irq(&irq_chip_lock);
++#endif
++}
++
++static void intc_ftintc010_mask_irq(struct irq_data *data)
++{
++ unsigned int tmp;
++
++ // disable
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++ spin_lock_irq(&irq_chip_lock);
++#endif
++ *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG) &=
++ ~(1 << data->irq);
++ tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG);
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++ spin_unlock_irq(&irq_chip_lock);
++#endif
++}
++
++static void intc_ftintc010_mask_ack_irq(struct irq_data *data)
++{
++ unsigned int tmp;
++
++ // disable
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++ spin_lock_irq(&irq_chip_lock);
++#endif
++ *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG) &=
++ ~(1 << data->irq);
++ tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG);
++
++ *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_CLEAR_REG) = 1 << data->irq;
++ tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_CLEAR_REG);
++
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++ spin_unlock_irq(&irq_chip_lock);
++#endif
++}
++
++static void intc_ftintc010_unmask_irq(struct irq_data *data)
++{
++ unsigned int tmp;
++
++ // enable
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++ spin_lock_irq(&irq_chip_lock);
++#endif
++ *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG) |= 1 << data->irq;
++ tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MASK_REG);
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++ spin_unlock_irq(&irq_chip_lock);
++#endif
++}
++
++static int intc_ftintc010_set_type(struct irq_data *data,
++ unsigned int flow_type)
++{
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++ spin_lock_irq(&irq_chip_lock);
++#endif
++ /*
++ * IRQ Trigger Mode Register 1: edge
++ * IRQ Trigger Level Register 1: active high
++ */
++
++ int tmp;
++
++ if (flow_type & (IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW)) {
++
++ *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_LEVEL_REG) &=
++ ~(1UL << data->irq);
++ tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_LEVEL_REG);
++ }
++
++ if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_HIGH)) {
++
++ *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_LEVEL_REG) |=
++ (1UL << data->irq);
++ tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_LEVEL_REG);
++ }
++
++ if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
++
++ *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MODE_REG) |=
++ (1UL << data->irq);
++ tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MODE_REG);
++ (irq_desc + data->irq)->handle_irq = handle_edge_irq;
++ }
++
++ if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
++
++ *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MODE_REG) &=
++ ~(1UL << data->irq);
++ tmp = *(volatile unsigned *)(IP_VA_BASE(0) + IRQ_MODE_REG);
++ (irq_desc + data->irq)->handle_irq = handle_level_irq;
++ }
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++ spin_unlock_irq(&irq_chip_lock);
++#endif
++ return 0;
++}
++
++static struct irq_chip intc_ftintc010_chip = {
++
++ .irq_ack = intc_ftintc010_ack_irq,
++ .irq_mask = intc_ftintc010_mask_irq,
++ .irq_mask_ack = intc_ftintc010_mask_ack_irq,
++ .irq_unmask = intc_ftintc010_unmask_irq,
++ .irq_set_type = intc_ftintc010_set_type,
++};
++
++static struct resource intc_resource = {
++
++ .name = "Main interrupt controller",
++ .start = IP_VA_BASE(0),
++ .end = IP_VA_BASE(0) + IP_VA_SIZE(0),
++};
++
++/*
++ * Initialization of master interrupt controller, after this INTC is
++ * enabled, the rest of Linux initialization codes can then be completed.
++ * For example, timer interrupts and UART interrupts must be enabled during
++ * the boot process.
++ */
++void __init intc_ftintc010_init_irq(void)
++{
++ int i, edge;
++
++#if defined(CONFIG_SMP) && defined(CONFIG_IRQ_PER_CPU)
++ spin_lock_init(&irq_chip_lock);
++#endif
++ /* Initialize the INTC */
++ outl(0x00000000, IP_VA_BASE(0) + IRQ_MASK_REG);
++ outl(0x00000000, IP_VA_BASE(0) + FIQ_MASK_REG);
++ outl(0xffffffff, IP_VA_BASE(0) + IRQ_CLEAR_REG);
++ outl(0xffffffff, IP_VA_BASE(0) + FIQ_CLEAR_REG);
++ outl(PLATFORM_IRQ_TRIGGER_MODE, IP_VA_BASE(0) + IRQ_MODE_REG);
++ /* FTINTC010: bit 0=active high or rising edge, 1=active low or falling edge. */
++ outl(PLATFORM_IRQ_TRIGGER_LEVEL, IP_VA_BASE(0) + IRQ_LEVEL_REG);
++
++ /* Register all IRQ */
++ for (i = PLATFORM_IRQ_BASE, edge = 1;
++ i < PLATFORM_IRQ_BASE + PLATFORM_IRQ_TOTALCOUNT; i++, edge <<= 1) {
++
++ irq_set_chip(i, &intc_ftintc010_chip);
++
++ if (PLATFORM_IRQ_TRIGGER_MODE & edge) /* edge trigger */
++ irq_set_handler(i, handle_edge_irq);
++
++ else /* level trigger */
++ irq_set_handler(i, handle_level_irq);
++ }
++
++ /* Register I/O address range of this INTC */
++ request_resource(&ioport_resource, &intc_resource);
++
++}
++
++unsigned int get_IntSrc(void)
++{
++ unsigned int irq_status, irq = 31;
++
++ irq_status = inl(IP_VA_BASE(0) + IRQ_STATUS_REG);
++ if (irq_status == 0)
++ return 32;
++ if (irq_status & 0x0000ffff) {
++ irq -= 16;
++ irq_status <<= 16;
++ }
++ if (irq_status & 0x00ff0000) {
++ irq -= 8;
++ irq_status <<= 8;
++ }
++ if (irq_status & 0x0f000000) {
++ irq -= 4;
++ irq_status <<= 4;
++ }
++ if (irq_status & 0x30000000) {
++ irq -= 2;
++ irq_status <<= 2;
++ }
++ if (irq_status & 0x40000000) {
++ irq -= 1;
++ }
++ return irq;
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/Kconfig linux-3.4.110/arch/nds32/platforms/Kconfig
+--- linux-3.4.110.orig/arch/nds32/platforms/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/Kconfig 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,122 @@
++choice
++ prompt "platform type"
++ default PLAT_AG101P
++
++config PLAT_VEP
++ bool "vep platform"
++ select CPU_CUSTOM
++ select PLATFORM_INTC
++
++config PLAT_AG101
++ bool "ag101 platform"
++ select CPU_N1213
++ select CPU_N1213_43U1HA0
++ select PLATFORM_INTC
++
++config PLAT_AG102
++ bool "ag102 platform"
++ select CPU_N1233F
++ select PLATFORM_AMIC
++
++config PLAT_AG101P
++ bool "ag101p platform"
++ select CPU_CUSTOM
++ select PLATFORM_INTC if !IVIC
++ select PLATFORM_NOINTC if IVIC
++
++config PLAT_QEMU
++ bool "qemu platform"
++ select CPU_CUSTOM
++ select PLATFORM_INTC
++endchoice
++
++config PLATFORM_NOINTC
++ def_bool n
++ depends on PLAT_AG101P
++
++config PLATFORM_INTC
++ def_bool n
++ depends on !PLAT_AG102
++
++config PLATFORM_AMIC
++ def_bool n
++ depends on PLAT_AG102
++
++config ARCH_WANT_OPTIONAL_GPIOLIB
++ bool "Arch Want Optional GPIOLIB"
++ default y
++
++if PLAT_VEP
++source "arch/nds32/platforms/vep/Kconfig"
++endif
++
++if PLAT_AG101
++source "arch/nds32/platforms/ag101/Kconfig"
++endif
++
++if PLAT_AG102
++source "arch/nds32/platforms/ag102/Kconfig"
++endif
++
++if PLAT_AG101P
++source "arch/nds32/platforms/ag101p/Kconfig"
++endif
++
++if PLAT_QEMU
++source "arch/nds32/platforms/qemu/Kconfig"
++endif
++
++menu "Common Platform Options"
++
++config PLATFORM_AHBDMA
++ tristate "AHB DMA Support"
++ help
++ AHB DMA service API support for other device drivers
++
++config PLATFORM_APBDMA
++ tristate "APB DMA Support"
++ help
++ AHB DMA service API support for other device drivers
++
++config SYS_CLK
++ int "AHB System Clock"
++ default 67737600
++ help
++ Manual setting of AHB clock, must match the jumper setting on
++ the board, or the system time won't be correctly calculated.
++ Notice that even when AUTO_SYS_CLK is ON, this value is still
++ required for adjusting minor time offsets. However, the influence
++ should be within micro-second to nano-second scale.
++
++config UART_CLK
++ int "UART Clock"
++ default 18432000
++ help
++ Change the UART clock in case of non-3.6864MHz OSC is used as main
++ clock source, or an external UART clock source is fed from GPIO23.
++ To support external UART clock from GPIO23, set PMU
++ "Multi-Function Port Setting Register" bit #8 (UartClkSel) to 1.
++ This control register can be found at physical address 0x98100028
++ If this options is changed, please also append "38400" to your
++ kernel command line, e.g.:
++ console=uart,shift,2,io,0xF9820000,38400
++ Note: For A320, the default UART clock is obtained by = 5 * OSC =
++ 5 * 3.6864MHz = 18.432MHz.
++
++menu "Memory configuration"
++
++config SDRAM_SIZE
++ hex "SDRAM Size (hex)"
++ default 4000000
++ ---help---
++ RAM size
++
++config MEMORY_START
++ hex "Physical memory start address"
++ default "0x00000000"
++ ---help---
++ Physical memory start address, you may modify it if it is porting to
++ a new SoC with different start address.
++endmenu
++
++endmenu
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/Makefile linux-3.4.110/arch/nds32/platforms/Makefile
+--- linux-3.4.110.orig/arch/nds32/platforms/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/Makefile 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,25 @@
++obj-y := timer.o
++
++ifdef CONFIG_FUNCTION_TRACER
++CFLAGS_REMOVE_timer.o = -pg
++endif
++
++obj-$(CONFIG_PLATFORM_NOINTC) += nointc.o
++obj-$(CONFIG_PLATFORM_INTC) += intc.o
++obj-$(CONFIG_PLATFORM_AMIC) += amic.o
++
++ifeq ("$(CONFIG_PLATFORM_AHBDMA)", "y")
++ obj-y += dmad_intc.o dmad.o
++else
++ ifeq ("$(CONFIG_PLATFORM_APBDMA)", "y")
++ obj-y += dmad_intc.o dmad.o
++ endif
++endif
++
++obj-$(CONFIG_PCI) += ftpci.o pci_intc.o
++
++obj-$(CONFIG_PLAT_VEP) += vep/
++obj-$(CONFIG_PLAT_AG101) += ag101/
++obj-$(CONFIG_PLAT_AG102) += ag102/
++obj-$(CONFIG_PLAT_AG101P) += ag101p/
++obj-$(CONFIG_PLAT_QEMU) += qemu/
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/nointc.c linux-3.4.110/arch/nds32/platforms/nointc.c
+--- linux-3.4.110.orig/arch/nds32/platforms/nointc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/nointc.c 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,134 @@
++/*
++ * linux/arch/nds32/platforms/intc.c
++ *
++ * Faraday FTINTC010 Master Interrupt Controller Device Driver Implementation
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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/irq.h>
++
++static void nointc_ack_irq(struct irq_data *data)
++{
++ SET_INT_PEND2(1 << data->irq);
++#if 0
++ asm volatile ("mtsr %0, $INT_PEND2\n\t"
++ "dsb\n\t"::"r" (1 << data->irq));
++#endif
++#if 0
++ asm volatile ("mfsr $r6, $INT_MASK2\n\t"
++ "and $r6, $r6,%0\n\t"
++ "mtsr $r6, $INT_MASK2\n\t"
++ "dsb\n\t"::"r" (~(1 << data->irq)):"$r6");
++#endif
++}
++
++static void nointc_mask_irq(struct irq_data *data)
++{
++ unsigned long int_mask2 = GET_INT_MASK2();
++ SET_INT_MASK2(int_mask2 & (~(1 << data->irq)));
++#if 0
++ asm volatile ("mfsr $r6, $INT_MASK2\n\t"
++ "and $r6, $r6,%0\n\t"
++ "mtsr $r6, $INT_MASK2\n\t"
++ "dsb\n\t"::"r" (~(1 << data->irq)):"$r6");
++#endif
++}
++
++static void nointc_mask_ack_irq(struct irq_data *data)
++{
++ unsigned long int_mask2 = GET_INT_MASK2();
++ SET_INT_MASK2(int_mask2 & (~(1 << data->irq)));
++ SET_INT_PEND2(1 << data->irq);
++#if 0
++ asm volatile ("not $r7, %0\n\t"
++ "mfsr $r6, $INT_MASK2\n\t"
++ "and $r6, $r6, $r7\n\t"
++ "mtsr $r6, $INT_MASK2\n\t"
++ "mtsr %0, $INT_PEND2\n\t"
++ "dsb\n\t"::"r" (1 << data->irq):"$r6", "$r7");
++#endif
++
++}
++
++static void nointc_unmask_irq(struct irq_data *data)
++{
++ unsigned long int_mask2 = GET_INT_MASK2();
++ SET_INT_MASK2(int_mask2 | (1 << data->irq));
++#if 0
++ asm volatile ("mfsr $r6, $INT_MASK2\n\t"
++ "or $r6, $r6,%0\n\t"
++ "mtsr $r6, $INT_MASK2\n\t"
++ "dsb\n\t"::"r" (1 << data->irq):"$r6");
++#endif
++}
++
++static int nointc_set_type(struct irq_data *data, unsigned int flow_type)
++{
++ printk(KERN_WARNING "interrupt type is not configurable\n");
++ return 0;
++}
++
++static struct irq_chip nointc_chip = {
++
++ .irq_ack = nointc_ack_irq,
++ .irq_mask = nointc_mask_irq,
++ .irq_mask_ack = nointc_mask_ack_irq,
++ .irq_unmask = nointc_unmask_irq,
++ .irq_set_type = nointc_set_type,
++};
++
++static unsigned int __initdata nivic_map[6] = { 6, 2, 10, 16, 24, 32 };
++
++void __init nointc_init_irq(void)
++{
++ int i;
++ unsigned long int_trigger_type, int_vec_base, nivic;
++
++ int_vec_base = GET_IVB();
++
++#if 0
++ asm volatile ("mfsr %0, $IVB\n":"=r" (int_vec_base));
++#endif
++
++ if (((int_vec_base & IVB_mskIVIC_VER) >> IVB_offIVIC_VER) == 0) {
++ panic("Unable to use NOINTC option to boot on this cpu\n");
++ }
++
++ nivic = (int_vec_base & IVB_mskNIVIC) >> IVB_offNIVIC;
++ if (nivic >= (sizeof nivic_map / sizeof nivic_map[0])) {
++ panic
++ ("The number of input for IVIC Controller is not supported on this cpu\n");
++ }
++ nivic = nivic_map[nivic];
++
++ int_trigger_type = GET_INT_TRIGGER();
++#if 0
++ asm volatile ("mfsr %0, $INT_TRIGGER\n":"=r" (int_trigger_type));
++#endif
++
++ for (i = 0; i < nivic; i++) {
++ irq_set_chip(i, &nointc_chip);
++ if (int_trigger_type & (1 << i))
++ /* edge-triggered */
++ irq_set_handler(i, handle_edge_irq);
++ else
++ /* level-triggered */
++ irq_set_handler(i, handle_level_irq);
++ }
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/pci_intc.c linux-3.4.110/arch/nds32/platforms/pci_intc.c
+--- linux-3.4.110.orig/arch/nds32/platforms/pci_intc.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/pci_intc.c 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,93 @@
++/*
++ * linux/arch/nds32/platforms/pci_intc.c
++ *
++ * Faraday PCI Bridge Interrupt Process Driver Implementation
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2008 Andes Technology Corporation
++ *
++ * 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.
++ *
++ *
++ * ChangeLog
++ *
++ * Luke Lee 09/15/2005 Created.
++ * Luke Lee 09/27/2005 Fixed for parent chip registration and notification.
++ * Peter Liao 09/28/2005 Port for PCI IP
++ */
++
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <asm/io.h>
++
++#include <asm/spec.h>
++#include <asm/ftpci.h>
++
++#define IPMODULE PCIC
++#define IPNAME FPCI010
++
++/*
++ * Level trigger IRQ chip methods
++ */
++
++static void intc_ftpci100_level_ack_irq(unsigned int irq)
++{
++ ftpci_clear_irq(irq - PLATFORM_PCI_IRQ_BASE);
++}
++
++static void intc_ftpci100_level_mask_irq(unsigned int irq)
++{
++ ftpci_mask_irq(irq - PLATFORM_PCI_IRQ_BASE);
++}
++
++static void intc_ftpci100_level_unmask_irq(unsigned int irq)
++{
++ ftpci_unmask_irq(irq - PLATFORM_PCI_IRQ_BASE);
++}
++
++static struct irq_chip intc_ftpci100_level_chip = {
++ .ack = intc_ftpci100_level_ack_irq,
++ .mask = intc_ftpci100_level_mask_irq,
++ .unmask = intc_ftpci100_level_unmask_irq,
++};
++
++void pci_irq_rounter(unsigned int irq, struct irq_desc *desc)
++{
++ int pci_irq;
++ struct irq_desc *pci_desc;
++
++ desc->chip->mask(irq);
++ desc->chip->ack(irq);
++
++ pci_irq = ftpci_get_irq();
++ if (pci_irq >= 0) {
++ pci_irq += PCIC_FTPCI100_IRQ0;
++ pci_desc = irq_desc + pci_irq;
++ pci_desc->handle_irq(pci_irq, pci_desc);
++ }
++
++ desc->chip->unmask(irq);
++}
++
++int __init intc_ftpci100_init_irq(void)
++{
++ int i;
++
++ /* Register all IRQ */
++ for (i = PCIC_FTPCI100_IRQ0;
++ i < PCIC_FTPCI100_IRQ0 + PCIC_FTPCI100_IRQ_COUNT; i++) {
++ // level trigger
++ set_irq_chip(i, &intc_ftpci100_level_chip);
++ set_irq_handler(i, handle_level_irq);
++ }
++#ifndef CONFIG_PLAT_AG101
++ set_irq_chained_handler(PLATFORM_PCI_IRQ, pci_irq_rounter);
++#endif
++
++ return 0;
++}
++
++subsys_initcall(intc_ftpci100_init_irq);
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/qemu/devices.c linux-3.4.110/arch/nds32/platforms/qemu/devices.c
+--- linux-3.4.110.orig/arch/nds32/platforms/qemu/devices.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/qemu/devices.c 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,124 @@
++#include <linux/serial_8250.h>
++#include <asm/mach-types.h>
++#include <asm/sizes.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/spec.h>
++#include <asm/intc.h>
++#include <asm/timer.h>
++
++const struct map_desc platform_io_desc[] __initdata = {
++ {UART0_VA_BASE, UART0_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {UART1_VA_BASE, UART1_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {INTC_FTINTC010_0_VA_BASE, INTC_FTINTC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {TIMER_FTTMR010_0_VA_BASE, TIMER_FTTMR010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {SSP_FTSSP010_0_VA_BASE, SSP_FTSSP010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {PMU_FTPMU010_0_VA_BASE, PMU_FTPMU010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {MAC_FTMAC100_0_VA_BASE, MAC_FTMAC100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {SDC_FTSDC010_0_VA_BASE, SDC_FTSDC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {RTC_FTRTC010_0_VA_BASE, RTC_FTRTC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {WDT_FTWDT010_0_VA_BASE, WDT_FTWDT010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {GPIO_FTGPIO010_0_VA_BASE, GPIO_FTGPIO010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {CFC_FTCFC010_0_VA_BASE, CFC_FTCFC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {LCD_FTLCDC100_0_VA_BASE, LCD_FTLCDC100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {I2C_FTI2C010_0_VA_BASE, I2C_FTI2C010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {DMAC_FTDMAC020_0_VA_BASE, DMAC_FTDMAC020_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {APBBRG_FTAPBBRG020S_0_VA_BASE, APBBRG_FTAPBBRG020S_0_PA_BASE,
++ PAGE_SIZE, MT_DEVICE_NCB},
++ {PCIIO_0_VA_BASE, PCIIO_0_PA_BASE, 0x000FF000, MT_DEVICE_NCB},
++ {PCIC_FTPCI100_0_VA_BASE, PCIC_FTPCI100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {LED_VA_BASE, LED_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {SDMC_FTSDMC021_VA_BASE, SDMC_FTSDMC021_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {L2CC_VA_BASE, L2CC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB}
++};
++
++static void __init platform_map_io(void)
++{
++ iotable_init((struct map_desc *)platform_io_desc,
++ ARRAY_SIZE(platform_io_desc));
++}
++
++static struct uart_port uart0 = {
++ .membase = (void __iomem *)UART0_VA_BASE,
++ .irq = UART0_IRQ,
++ .uartclk = CONFIG_UART_CLK,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .line = 0,
++ .mapbase = UART0_PA_BASE,
++};
++
++static struct uart_port uart1 = {
++ .membase = (void __iomem *)UART1_VA_BASE,
++ .irq = UART1_IRQ,
++ .uartclk = CONFIG_UART_CLK,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .line = 1,
++ .mapbase = UART1_PA_BASE,
++};
++
++static void __init soc_init(void)
++{
++ early_serial_setup(&uart0);
++ early_serial_setup(&uart1);
++}
++
++static struct resource smc91x_resources[] = {
++ [0] = {
++ .name = "smc91x",
++ .start = 0x92100000,
++ .end = 0x92110000,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = 25,
++ .end = 25,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device smc91x_device = {
++ .name = "smc91x",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(smc91x_resources),
++ .resource = smc91x_resources,
++};
++
++static __init int smc_init(void)
++{
++ int ret;
++ ret = platform_device_register(&smc91x_device);
++ if (ret == 0)
++ printk("smc is installed now.\n");
++ else
++ printk("smc failed.\n");
++ return 0;
++}
++
++module_init(smc_init);
++
++MACHINE_START(FARADAY, PLATFORM_NAME)
++ .param_offset = BOOT_PARAMETER_PA_BASE,
++ .map_io = platform_map_io,
++ .init_irq = platform_init_irq,
++ .timer = &platform_timer, /* defined in timer.c */
++ .init_machine = soc_init,
++MACHINE_END
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/qemu/Kconfig linux-3.4.110/arch/nds32/platforms/qemu/Kconfig
+--- linux-3.4.110.orig/arch/nds32/platforms/qemu/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/qemu/Kconfig 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,3 @@
++menu "QEMU Platform Options"
++
++endmenu
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/qemu/Makefile linux-3.4.110/arch/nds32/platforms/qemu/Makefile
+--- linux-3.4.110.orig/arch/nds32/platforms/qemu/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/qemu/Makefile 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1 @@
++obj-y = devices.o
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/timer.c linux-3.4.110/arch/nds32/platforms/timer.c
+--- linux-3.4.110.orig/arch/nds32/platforms/timer.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/timer.c 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,250 @@
++/*
++ * linux/arch/nds32/platforms/timer.c
++ *
++ * Faraday FTTMR010 Timer Device Driver Implementation
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ * Copyright (C) 2009 Andes Technology Corporation
++ *
++ * 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/irq.h>
++#include <linux/clocksource.h>
++#include <linux/clockchips.h>
++
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/cpufreq.h>
++
++#include <asm/mach/time.h>
++#include <asm/timer.h>
++#include <asm/spec.h>
++
++#define REG32_TMR(x) *(volatile unsigned long *)(TIMER_FTTMR010_VA_BASE + (x))
++#define APB_CLK_IN (AHB_CLK_IN / 2)
++
++static struct resource timer_resource = {
++ .name = "Timer 1~3",
++ .start = TIMER_FTTMR010_VA_BASE,
++ .end = TIMER_FTTMR010_VA_LIMIT,
++};
++
++static inline cycle_t clocksource_read_cycles(struct clocksource *cs)
++{
++ return (cycle_t) REG32_TMR(TIMER3_COUNT);
++}
++
++static void clksrc_fttmr010_resume(struct clocksource *cs)
++{
++ REG32_TMR(TIMER_INTRMASK) |= TM3MATCH1 | TM3MATCH2 | TM3OVERFLOW;
++ REG32_TMR(TIMER_TMCR) |= TM3UPDOWN | TM3ENABLE;
++}
++
++static struct clocksource clksrc_fttmr010 = {
++ .name = "fttmr010_tm1",
++ .rating = 300,
++ .read = clocksource_read_cycles,
++ .mask = CLOCKSOURCE_MASK(32),
++ .shift = 21,
++ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
++ .resume = clksrc_fttmr010_resume,
++};
++
++static void __init fttmr010_clocksource_init(void)
++{
++ clksrc_fttmr010.mult =
++ clocksource_hz2mult(APB_CLK_IN, clksrc_fttmr010.shift);
++
++ REG32_TMR(TIMER3_LOAD) = 0;
++ REG32_TMR(TIMER_INTRMASK) |= TM3MATCH1 | TM3MATCH2 | TM3OVERFLOW;
++ REG32_TMR(TIMER_TMCR) |= TM3UPDOWN | TM3ENABLE;
++ if (clocksource_register(&clksrc_fttmr010))
++ printk(KERN_ERR "Error: failed to register %s\n",
++ clksrc_fttmr010.name);
++}
++
++static int fttmr010_set_next_event(unsigned long cycles,
++ struct clock_event_device *evt)
++{
++ REG32_TMR(TIMER1_LOAD) = cycles;
++ return 0;
++}
++
++static void fttmr010_set_mode(enum clock_event_mode mode,
++ struct clock_event_device *evt)
++{
++ switch (mode) {
++ case CLOCK_EVT_MODE_ONESHOT:
++ REG32_TMR(TIMER1_LOAD) = 0xffffffff;
++ REG32_TMR(TIMER_TMCR) |= TM1ENABLE;
++ break;
++
++ case CLOCK_EVT_MODE_PERIODIC:
++ REG32_TMR(TIMER1_COUNT) = APB_CLK_IN / HZ - 1;
++ REG32_TMR(TIMER1_LOAD) = APB_CLK_IN / HZ - 1;
++ REG32_TMR(TIMER_TMCR) |= TM1ENABLE;
++ break;
++ case CLOCK_EVT_MODE_UNUSED:
++ break;
++ case CLOCK_EVT_MODE_SHUTDOWN:
++ REG32_TMR(TIMER_TMCR) &= ~TM1ENABLE;
++ break;
++ case CLOCK_EVT_MODE_RESUME:
++ REG32_TMR(TIMER_INTRMASK) |= TM1MATCH1 | TM1MATCH2;
++ REG32_TMR(TIMER_TMCR) |= TM1ENABLE | TM1OFENABLE;
++ break;
++ }
++}
++
++static struct clock_event_device clockevent_fttmr010 = {
++ .name = "fttmr010_tm1",
++ .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
++ .shift = 32,
++ .cpumask = cpu_all_mask,
++ .set_next_event = fttmr010_set_next_event,
++ .set_mode = fttmr010_set_mode,
++};
++
++static irqreturn_t timer1_interrupt(int irq, void *dev_id)
++{
++ struct clock_event_device *evt = dev_id;
++
++ REG32_TMR(TIMER_INTRSTATE) = TM1MATCH1 | TM1MATCH2 | TM1OVERFLOW;
++
++ evt->event_handler(evt);
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction timer1_irq = {
++ .name = "Timer Tick",
++ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
++ .handler = timer1_interrupt,
++ .dev_id = &clockevent_fttmr010
++};
++
++static void __init fttmr010_clockevent_init(void)
++{
++ clockevent_fttmr010.mult =
++ div_sc(APB_CLK_IN, NSEC_PER_SEC, clockevent_fttmr010.shift);
++ clockevent_fttmr010.max_delta_ns =
++ clockevent_delta2ns(0xffffffff, &clockevent_fttmr010);
++ clockevent_fttmr010.min_delta_ns =
++ clockevent_delta2ns(3, &clockevent_fttmr010);
++
++ clockevents_register_device(&clockevent_fttmr010);
++ setup_irq(TIMER_FTTMR010_IRQ0, &timer1_irq);
++}
++
++static void fttmr010_resume(void)
++{
++}
++
++#ifdef CONFIG_CPU_FREQ
++void ag102_calc_ahb_clk(void);
++static int fttmr010_cpufreq_notifier(struct notifier_block *nb,
++ unsigned long val, void *data)
++{
++ if (val == CPUFREQ_POSTCHANGE) {
++
++ unsigned long flags;
++#ifdef CONFIG_PLAT_AG102
++ ag102_calc_ahb_clk();
++#endif
++ local_irq_save(flags);
++
++ clocksource_unregister(&clksrc_fttmr010);
++
++ clksrc_fttmr010.mult =
++ clocksource_hz2mult(APB_CLK_IN, clksrc_fttmr010.shift);
++#ifdef CONFIG_PLAT_AG101
++ clksrc_fttmr010.mult_orig =
++ clocksource_hz2mult(APB_CLK_IN, clksrc_fttmr010.shift);
++#endif
++
++ if (clocksource_register(&clksrc_fttmr010))
++ printk(KERN_ERR "Error: failed to re-register %s\n",
++ clksrc_fttmr010.name);
++ else
++ printk("Re-register clock source %s\n",
++ clksrc_fttmr010.name);
++
++ local_irq_restore(flags);
++
++ clockevent_fttmr010.mult =
++ div_sc(APB_CLK_IN, NSEC_PER_SEC, clockevent_fttmr010.shift);
++
++#ifdef CONFIG_PLAT_AG102
++ printk("Add timer clock modifier...\n");
++ fttmr010_set_mode(CLOCK_EVT_MODE_PERIODIC, 0);
++#endif
++ }
++
++ return 0;
++}
++
++static struct notifier_block fttmr010_cpufreq_notifier_block = {
++ .notifier_call = fttmr010_cpufreq_notifier
++};
++
++static int __init fttmr010_init_cpufreq(void)
++{
++ if (cpufreq_register_notifier(&fttmr010_cpufreq_notifier_block,
++ CPUFREQ_TRANSITION_NOTIFIER))
++ printk("fttmr010: Failed to setup cpufreq notifier\n");
++
++ return 0;
++}
++
++core_initcall(fttmr010_init_cpufreq);
++#endif
++
++static int clksrc_init;
++static void __init fttmr010_init(void)
++{
++ request_resource(&ioport_resource, &timer_resource);
++
++ printk
++ ("FTTMR010 timer 1 installed on IRQ %d, with clock %d at %d HZ.\r\n",
++ TIMER_FTTMR010_IRQ0, APB_CLK_IN, HZ);
++
++ REG32_TMR(TIMER_TMCR) &=
++ ~(TM1ENABLE | TM1CLOCK | TM1OFENABLE | TM1UPDOWN);
++ REG32_TMR(TIMER_INTRMASK) |= TM1MATCH1 | TM1MATCH2;
++ REG32_TMR(TIMER_TMCR) |= TM1OFENABLE;
++
++ fttmr010_clocksource_init();
++ fttmr010_clockevent_init();
++ clksrc_init = 1;
++}
++
++struct sys_timer platform_timer = {
++ .init = fttmr010_init,
++ .resume = fttmr010_resume,
++};
++
++unsigned long long sched_clock(void)
++{
++ if (clksrc_init)
++ return
++ clocksource_cyc2ns(clocksource_read_cycles
++ (&clksrc_fttmr010), clksrc_fttmr010.mult,
++ clksrc_fttmr010.shift);
++ else
++ return (unsigned long long)(jiffies - INITIAL_JIFFIES)
++ * (NSEC_PER_SEC / HZ);
++}
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/vep/devices.c linux-3.4.110/arch/nds32/platforms/vep/devices.c
+--- linux-3.4.110.orig/arch/nds32/platforms/vep/devices.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/vep/devices.c 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,83 @@
++#include <linux/serial_8250.h>
++#include <asm/mach-types.h>
++#include <asm/sizes.h>
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++#include <asm/spec.h>
++#include <asm/intc.h>
++#include <asm/timer.h>
++
++const struct map_desc platform_io_desc[] __initdata = {
++ {UART0_VA_BASE, UART0_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {UART1_VA_BASE, UART1_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {INTC_FTINTC010_0_VA_BASE, INTC_FTINTC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {TIMER_FTTMR010_0_VA_BASE, TIMER_FTTMR010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {SSP_FTSSP010_0_VA_BASE, SSP_FTSSP010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {PMU_FTPMU010_0_VA_BASE, PMU_FTPMU010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {MAC_FTMAC100_0_VA_BASE, MAC_FTMAC100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {SDC_FTSDC010_0_VA_BASE, SDC_FTSDC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {RTC_FTRTC010_0_VA_BASE, RTC_FTRTC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {WDT_FTWDT010_0_VA_BASE, WDT_FTWDT010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {GPIO_FTGPIO010_0_VA_BASE, GPIO_FTGPIO010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {CFC_FTCFC010_0_VA_BASE, CFC_FTCFC010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {LCD_FTLCDC100_0_VA_BASE, LCD_FTLCDC100_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {I2C_FTI2C010_0_VA_BASE, I2C_FTI2C010_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {DMAC_FTDMAC020_0_VA_BASE, DMAC_FTDMAC020_0_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {APBBRG_FTAPBBRG020S_0_VA_BASE, APBBRG_FTAPBBRG020S_0_PA_BASE,
++ PAGE_SIZE, MT_DEVICE_NCB},
++ {LED_VA_BASE, LED_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB},
++ {SDMC_FTSDMC021_VA_BASE, SDMC_FTSDMC021_PA_BASE, PAGE_SIZE,
++ MT_DEVICE_NCB},
++ {L2CC_VA_BASE, L2CC_PA_BASE, PAGE_SIZE, MT_DEVICE_NCB}
++};
++
++static void __init platform_map_io(void)
++{
++ iotable_init((struct map_desc *)platform_io_desc,
++ ARRAY_SIZE(platform_io_desc));
++}
++
++static struct uart_port uart0 = {
++ .membase = (void __iomem *)UART0_VA_BASE,
++ .irq = UART0_IRQ,
++ .uartclk = CONFIG_UART_CLK,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .line = 0,
++ .mapbase = UART0_PA_BASE,
++};
++
++static struct uart_port uart1 = {
++ .membase = (void __iomem *)UART1_VA_BASE,
++ .irq = UART1_IRQ,
++ .uartclk = CONFIG_UART_CLK,
++ .regshift = 2,
++ .iotype = UPIO_MEM,
++ .flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF,
++ .line = 1,
++ .mapbase = UART1_PA_BASE,
++};
++
++static void __init soc_init(void)
++{
++ early_serial_setup(&uart0);
++ early_serial_setup(&uart1);
++}
++
++MACHINE_START(FARADAY, PLATFORM_NAME)
++ .param_offset = BOOT_PARAMETER_PA_BASE,.map_io = platform_map_io,.init_irq = platform_init_irq,.timer = &platform_timer, /* defined in timer.c */
++ .init_machine = soc_init, MACHINE_END
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/vep/Kconfig linux-3.4.110/arch/nds32/platforms/vep/Kconfig
+--- linux-3.4.110.orig/arch/nds32/platforms/vep/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/vep/Kconfig 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,7 @@
++menu "VEP Platform Options"
++
++config CACHE_L2
++ bool "Support L2 cache"
++ default n
++
++endmenu
+diff -Nur linux-3.4.110.orig/arch/nds32/platforms/vep/Makefile linux-3.4.110/arch/nds32/platforms/vep/Makefile
+--- linux-3.4.110.orig/arch/nds32/platforms/vep/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/arch/nds32/platforms/vep/Makefile 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1 @@
++obj-y = devices.o
+diff -Nur linux-3.4.110.orig/build_linux.sh linux-3.4.110/build_linux.sh
+--- linux-3.4.110.orig/build_linux.sh 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/build_linux.sh 2016-04-07 10:20:51.018083964 +0200
+@@ -0,0 +1,202 @@
++#!/bin/sh
++
++export ARCH=nds32
++
++print_help()
++{
++ echo "Usage: <platform> [platform_defconfig] [--bootm] [--ramdisk=<ramdisk absolute path>]"
++ echo "Stop Building."
++ exit
++}
++
++BUILDBOOTM=0
++BUILDBOOTPIMAGE=0
++BUILDHEADERS=0
++
++case "$1" in
++ qemu)
++ TARGET=qemu_defconfig
++ IMAGE=qemu
++ export CROSS_COMPILE=nds32le-linux-
++ echo "Building $IMAGE kernel."
++ ;;
++ vep-be)
++ TARGET=vep-be_defconfig
++ IMAGE=vep-be
++ export CROSS_COMPILE=nds32be-linux-
++ echo "Building $IMAGE kernel."
++ ;;
++ vep-le)
++ TARGET=vep-le_defconfig
++ IMAGE=vep-le
++ export CROSS_COMPILE=nds32le-linux-
++ echo "Building $IMAGE kernel."
++ ;;
++ xc5)
++ TARGET=xc5_defconfig
++ IMAGE=xc5
++ export CROSS_COMPILE=nds32le-linux-
++ echo "Building $IMAGE kernel."
++ ;;
++ xc5_8k)
++ TARGET=xc5_8k_defconfig
++ IMAGE=xc5_8k
++ export CROSS_COMPILE=nds32le-linux-
++ echo "Building $IMAGE kernel."
++ ;;
++ ag101a0)
++ TARGET=ag101a0_defconfig
++ IMAGE=ag101a0
++ export CROSS_COMPILE=nds32le-linux-
++ echo "Building $IMAGE kernel."
++ ;;
++ ag101b0)
++ TARGET=ag101b0_defconfig
++ IMAGE=ag101b0
++ export CROSS_COMPILE=nds32le-linux-
++ echo "Building $IMAGE kernel."
++ ;;
++ ag102)
++ TARGET=ag102_defconfig
++ IMAGE=ag102
++ export CROSS_COMPILE=nds32le-linux-
++ echo "Building $IMAGE kernel."
++ ;;
++ u200)
++ TARGET=u200_defconfig
++ IMAGE=u200
++ export CROSS_COMPILE=nds32le-linux-
++ echo "Building $IMAGE kernel."
++ ;;
++ xc5-qa)
++ TARGET=xc5-qa_defconfig
++ IMAGE=xc5-qa
++ export CROSS_COMPILE=nds32le-linux-
++ echo "Building $IMAGE kernel."
++ ;;
++ ag101-qa)
++ TARGET=ag101-qa_defconfig
++ IMAGE=ag101-qa
++ export CROSS_COMPILE=nds32le-linux-
++ echo "Building $IMAGE kernel."
++ ;;
++ *)
++ if [ $# = 1 ]; then
++ echo "No defconfig is given."
++ print_help
++ fi
++ if [ ! -e $2 ]; then
++ echo "Given defconfig is not exist."
++ print_help
++ elif [ ! -f $2 ]; then
++ echo "Given defconfig is not a file."
++ print_help
++ elif [ ! -s $2 ]; then
++ echo "Given defconfig is size 0."
++ print_help
++ elif [ ! -r $2 ]; then
++ echo "Given defconfig has no read attribute."
++ print_help
++ fi
++ TARGET=none
++ IMAGE=$1
++ export CROSS_COMPILE=nds32le-linux-
++ echo "Building $IMAGE kernel."
++esac
++
++ZIMAGE="$IMAGE"_zImage
++VMLINUZ="$IMAGE"_vmlinuz
++VMLINUX="$IMAGE"_vmlinux
++BOOTPIMAGE="$IMAGE"_bootpImage
++BOOTP="$IMAGE"_bootp
++BOOTM="$IMAGE"_bootm
++
++for ARG in $@; do
++ if [ $ARG = $1 ]; then
++ continue
++ fi
++
++ if [ $ARG = $2 ]; then
++ if [ $TARGET = "none" ]; then
++ continue
++ fi
++ fi
++
++ case "$ARG" in
++
++ --bootm)
++ BUILDBOOTM=1
++ ;;
++
++ --ramdisk=*)
++ BUILDBOOTPIMAGE=1
++ RAMDISK=${ARG#*=}
++ if [ ! -e $RAMDISK ]; then
++ echo "Given ramdisk is not exist."
++ print_help
++ elif [ ! -f $RAMDISK ]; then
++ echo "Given ramdisk is not a file."
++ print_help
++ elif [ ! -s $RAMDISK ]; then
++ echo "Given ramdisk is size 0."
++ print_help
++ elif [ ! -r $RAMDISK ]; then
++ echo "Given ramdisk has no read attribute."
++ print_help
++ fi
++ ;;
++# --headers)
++# BUILDHEADERS=1
++# git apply ../linux-2.6-patch/headers.patch
++# echo "Exporting kernel headers."
++# ;;
++ *)
++ print_help
++ esac
++done
++
++if [ "$OSTYPE" = "cygwin" ]; then
++ HOST_LOADLIBES=-lintl\ -lcurses
++fi
++export HOST_LOADLIBES
++
++which ${CROSS_COMPILE}gcc &> /dev/null || export CROSS_COMPILE=nds32-elf-
++
++make mrproper | tee $IMAGE.log
++if [ $TARGET != "none" ]; then
++ make $TARGET| tee -a $IMAGE.log
++else
++ cp $2 .config
++fi
++
++if [ $BUILDHEADERS = 1 ]; then
++ make dep | tee -a $IMAGE.log
++ make headers_install | tee -a $IMAGE.log
++else
++ make | tee -a $IMAGE.log
++
++ cp arch/nds32/boot/zImage ./$ZIMAGE | tee -a $IMAGE.log
++ cp arch/nds32/boot/compressed/vmlinux ./$VMLINUZ | tee -a $IMAGE.log
++ cp ./vmlinux ./$VMLINUX | tee -a $IMAGE.log
++
++ if [ $BUILDBOOTPIMAGE = 1 ]; then
++ make bootpImage INITRD=$RAMDISK | tee -a $IMAGE.log
++ cp arch/nds32/boot/bootpImage ./$BOOTPIMAGE | tee -a $IMAGE.log
++ cp arch/nds32/boot/bootp/bootp ./$BOOTP | tee -a $IMAGE.log
++ fi
++
++ if [ $BUILDBOOTM = 1 ]; then
++ if [ -e "../u-boot/tools/mkimage" ]; then
++ ../u-boot/tools/mkimage \
++ -A nds32 \
++ -O linux \
++ -T kernel \
++ -C none \
++ -a 0x500000 \
++ -e 0x500040 \
++ -d ./arch/nds32/boot/zImage $BOOTM | tee -a $IMAGE.log
++ else
++ echo "Error: ../u-boot/tools/mkimage not found" | tee -a $IMAGE.log
++ fi
++ fi
++fi
+diff -Nur linux-3.4.110.orig/drivers/block/ftcfc010.c linux-3.4.110/drivers/block/ftcfc010.c
+--- linux-3.4.110.orig/drivers/block/ftcfc010.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/block/ftcfc010.c 2016-04-07 10:20:51.022084119 +0200
+@@ -0,0 +1,1299 @@
++/* drivers/block/CPESD/ftsdc010.c
++ *******************************************************************************
++ * Faraday FTSDC010 Device Driver
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ *
++ * All Rights Reserved
++ *
++ * Porting to Linux 2.6 on 20050815
++ * Author: Chris Lee, I-Jui Sung, Peter Liao (support APB DMA)
++ * Version: 0.2
++ * History:
++ * 0.1 new creation
++ * 0.2 Porting to meet the style of linux dma
++ * 0.3 modify dma usage to virtual irq of dma interrupt
++ * 0.4 (20050701) Improve r/w performance
++ * 0.5 Porting to Linux 2.6 and replace busy_loop checking with timer's timeout
++ * Todo:
++ *******************************************************************************
++ */
++
++#define DEBUG_OFF 0
++
++#define DEBUG( enable, tagged, ...) \
++do{ \
++ if( enable){ \
++ if( tagged) \
++ printk( "[ %30s() ] ", __func__); \
++ printk( __VA_ARGS__); \
++ } \
++} while( 0)
++
++#include <linux/interrupt.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/hdreg.h> /* HDIO_GETGEO */
++#include <linux/fs.h>
++#include <linux/blkdev.h>
++#include <linux/buffer_head.h> /* invalidate_bdev */
++#include <linux/bio.h>
++#include <linux/pci.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/spec.h>
++#include <asm/dmad.h>
++
++#define IPMODULE CFC
++#define IPNAME FTCFC010
++
++#include "ftcfc010.h"
++
++static int hardsect_size = 512;
++module_param( hardsect_size, int, 0);
++
++static int cf_major = 0; /* must be declared before including blk.h */
++#define DEVICE_NAME "Faraday CFC" /* name for messaging */
++
++#define FTCFC_VA_BASE IP_VA_BASE( 0)
++#define FTCFC_PA_BASE IP_PA_BASE( 0)
++#define FTCFC_IRQ CFC_FTCFC010_IRQ1
++
++#undef CF_DEBUG
++#define CF_DEBUG 0
++struct block_device_operations cf_fops;
++
++typedef struct cf_dev {
++
++ int size; /* device size in sectors */
++ int usage; /* # of users currently */
++ int media_change; /* Flag: media changed? */
++ struct gendisk *gd; /* The gendisk structure */
++ spinlock_t lock; /* For mutual exclusion */
++ struct request_queue *queue; /* The device request queue */
++ int card_state;
++ u32 lba_sec_offset;
++ dmad_chreq ch_req;
++
++} cf_dev_t;
++
++static cf_dev_t *cf_devices;
++static cf_card_t cf_card_info;
++
++static dma_addr_t dma_buf;
++struct completion cf_dma_cmpl;
++
++static uint first_run;
++static uint cf_err_code;
++
++static int g_cf_sectors;
++
++static void SetTransferSize( u32 Addr, u32 Type, u32 OP_Type, u32 Inc_Addr, u32 Transize)
++{
++ u32 ctrl_reg, buf_ctrl_reg;
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++
++ /* set read/write command */
++ while( cfc->HostStatus & BUF_ACTIVE_BIT)
++ ;
++
++ /* Set Transfer size mode to default */
++ cfc->TransSzMode2En = 0;
++
++ /* set 8/16 bits mode */
++ ctrl_reg = cfc->ControlReg;
++
++ if( Transize == SIZE_1_BYTE)
++ ctrl_reg = ( ctrl_reg & ~MODE_BIT) | BYTE_MODE;
++ else
++ ctrl_reg = ( ctrl_reg & ~MODE_BIT) | WORD_MODE;
++
++ DEBUG( CF_DEBUG, 1, "ctrl 1: 0x%08lx\n", ( unsigned long)ctrl_reg);
++ cfc->ControlReg = ctrl_reg;
++
++ /* Write command to buffer */
++ buf_ctrl_reg = cfc->BuffCtrlReg;
++ buf_ctrl_reg = ( buf_ctrl_reg & ~ADR_BIT & ~TYPE_BIT & ~RW_BIT & ~INCADR_BIT & ~TRANS_SIZE_CONTROL_BIT)
++ | Addr | Type | OP_Type | Inc_Addr | ( Transize << TRANS_SIZE_LOC);
++
++ cfc->BuffCtrlReg = buf_ctrl_reg;
++ DEBUG( CF_DEBUG, 1, "buf_ctrl 1: 0x%08lx\n", ( unsigned long)buf_ctrl_reg);
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++}
++
++static void SetTransferSizeEx( u32 Addr, u32 Type, u32 OP_Type, u32 Inc_Addr, u32 Transize)
++{
++ u32 ctrl_reg, buf_ctrl_reg;
++
++ DEBUG( CF_DEBUG, 1, "Enter, SetTransferSizeEx: %d\n", Transize);
++
++ /* set read/write command */
++ while( cfc->HostStatus & BUF_ACTIVE_BIT)
++ ;
++
++ /* Set Transfer size mode to default */
++ cfc->TransSzMode2En = 1;
++
++ /* set 8/16 bits mode */
++ ctrl_reg = cfc->ControlReg;
++
++ if( Transize == SIZE_1_BYTE)
++ ctrl_reg = ( ctrl_reg & ~MODE_BIT) | BYTE_MODE;
++ else
++ ctrl_reg = ( ctrl_reg & ~MODE_BIT) | WORD_MODE;
++
++ cfc->ControlReg = ctrl_reg;
++
++ /* Set Transfer size mode2 reg in FTCFC */
++ cfc->TransSzMode2Cnt = Transize - 1;
++
++ /* Write command to buffer */
++ buf_ctrl_reg = cfc->BuffCtrlReg;
++ buf_ctrl_reg = ( buf_ctrl_reg & ~ADR_BIT & ~TYPE_BIT & ~RW_BIT & ~INCADR_BIT & ~TRANS_SIZE_CONTROL_BIT)
++ | Addr | Type | OP_Type | Inc_Addr;
++
++ cfc->BuffCtrlReg = buf_ctrl_reg;
++
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++}
++
++static void WriteCFCardByte( u32 Addr, u8 Value, u32 Type)
++{
++ while( !( cfc->HostStatus & RDY_nIREQ_BIT))
++ ;
++
++ SetTransferSize( Addr, Type, WRITE_OP, NOINCADR, SIZE_1_BYTE);
++
++ cfc->BufferData = Value;
++
++ while( !( cfc->HostStatus & INTA_BIT))
++ ;
++
++ /* clear command complete status */
++ cfc->HostStatus = INTA_BIT;
++}
++
++static u8 ReadCFCardByte( u32 Addr, u32 Type)
++{
++ u8 ret_data;
++
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++
++ /* wait until ready */
++ while( !( cfc->HostStatus & RDY_nIREQ_BIT))
++ ;
++
++ SetTransferSize( Addr, Type, READ_OP, NOINCADR, SIZE_1_BYTE);
++
++ while( !( cfc->HostStatus & INTA_BIT))
++ ;
++
++ ret_data = cfc->BufferData & 0xff;
++ DEBUG( CF_DEBUG, 1, "data: 0x%02x\n", ret_data);
++
++ while( !( cfc->HostStatus & INTA_BIT))
++ ;
++
++ /* clear command complete status */
++ cfc->HostStatus = INTA_BIT;
++
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++ return ret_data;
++}
++
++/* set Head-cylinder-sector on CF */
++static u32 Translate_Config_HCS( u32 LBA, u32 Sec_count)
++{
++ u8 DriveHead = ( u8)( 0xE0 | ( LBA >> 24)); /* 0xE0 set in LBA mode (bit 7&5 must set to 1) */
++ u8 CylHigh = ( u8)( ( LBA >> 16) & 0xFF);
++ u8 CylLow = ( u8)( ( LBA >> 8) & 0xFF);
++ u8 SecNum = ( u8)( LBA & 0xFF);
++
++ DEBUG( CF_DEBUG, 1, "LBA:%d, %d %d %d %d, count: %d\n",
++ LBA, DriveHead, CylHigh, CylLow, SecNum, Sec_count);
++
++ /* Set CF-ATA reg for start sector */
++ WriteCFCardByte( BLKMEM_DRIVE_REG, DriveHead, COMMON_MEM);
++ WriteCFCardByte( BLKMEM_CYLINDER_HIGH_REG, CylHigh, COMMON_MEM);
++ WriteCFCardByte( BLKMEM_CYLINDER_LOW_REG, CylLow, COMMON_MEM);
++ WriteCFCardByte( BLKMEM_SECTOR_NUMBER_REG, SecNum, COMMON_MEM);
++ WriteCFCardByte( BLKMEM_SECTOR_COUNT_REG, Sec_count, COMMON_MEM);
++
++ return 1;
++}
++
++/*
++ * SetCFCardConfiguration(): ATTRIBUTE MEMORY
++ * Set CF storgae card configuration option register
++ * Conf1 Conf0 Disk Card Mode
++ * ---------------------------------------------------------------
++ * 0 0 Memory Mapped
++ * 0 1 I/O Mapped, any 16 byte system decoded
++ * 1 0 I/O Mapped, 1F0h - 1F7h / 3F6h - 3F7h
++ * 1 1 I/O Mapped, 170h - 177h / 376h - 377h
++ */
++static void SetCFCardMode( u8 Mode)
++{
++ u8 Reg;
++
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++
++ Reg = ReadCFCardByte( CONFIG_OPTION_REG, ATTRIBUTE_MEM); /* CONFIG_OPTION_REG = 0x200 */
++ Reg &= ( LEVLREQ_BIT | SRESET_BIT); /* clear bit0-5 */
++
++ WriteCFCardByte( CONFIG_OPTION_REG, Reg | Mode, ATTRIBUTE_MEM);
++
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++}
++
++/* return 0: fail, 1: success */
++static u32 CF_SendCommand( u16 Cmd)
++{
++ u16 Reg;
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++
++ do{
++ WriteCFCardByte( BLKMEM_COMMAND_REG, Cmd, COMMON_MEM);
++
++ /*
++ * Check status register of Task file register is valid for access
++ * No other bits in status register are valid when BUSY bit is
++ * set to a 1
++ */
++ while( ( ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM) & BUSY_BIT))
++ ;
++
++ Reg = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
++
++ if( Reg & ERR_BIT){
++
++ DEBUG( CF_DEBUG, 1, "Exit ( fail)\n");
++ return 0;
++ }
++
++ } while( !( Reg & RDY_BIT));
++
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++ return 1;
++}
++
++static void CardReset( void)
++{
++ u32 ctrl_reg = cfc->ControlReg;
++ u8 data;
++
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++ cfc->ControlReg = ctrl_reg | RESET_BIT | SIGNAL_ON | PWR_ON; /* set reset bit, float control, power on */
++
++ /* Software must manually clear this bit */
++ mdelay( 100);
++
++ /* clear reset bit */
++ cfc->ControlReg = ( ctrl_reg &~ RESET_BIT) | SIGNAL_ON | PWR_ON | DATA_CMP_INT_MASK | IO_INT_MASK;
++
++ do {
++ data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
++
++ } while( data & BUSY_BIT); /* please be careful that is locked here */
++
++ data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
++
++ /* Check if Drive Ready & Drive Seek Complete */
++ if( data == ( RDY_BIT | DSC_BIT))
++ DEBUG( CF_DEBUG, 1, "Reset CF OK, data: 0x%02x\n", ( unsigned char)data);
++ else
++ DEBUG( CF_DEBUG, 1, "Reset CF fail, data: 0x%02x\n", ( unsigned char)data);
++
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++}
++
++static u32 CFCardInit( void)
++{
++ u8 buff[CF_SECTOR_SIZE];
++ u32 i;
++ u32 BSA, BSM, BSIO, BSMOW, BSIORW, apb_ns;
++
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++
++ if( !( cfc->HostStatus & CARD_DETECT_BIT)){
++
++ DEBUG( CF_DEBUG, 1, "No CF Card In Socket\n");
++ return -1;
++ }
++
++ CardReset();
++
++ /* set timer */
++
++ apb_ns = 1000000000 / ( AHB_CLK_IN / 2 ); /* the time of APB clock */
++ BSA = ( 50 + ( apb_ns - ( 50 % apb_ns))) / apb_ns; /* Based on the item tc( R) of BSA */
++ BSMOW = 3;
++ BSIORW = 3;
++ BSM = ( 30 + ( apb_ns - ( 30 % apb_ns))) / apb_ns; /* Base on the item tw( WE) of BSM */
++ BSIO = ( 35 + ( apb_ns - ( 35 % apb_ns))) / apb_ns; /* Base on the item tsuA( IORD,IOWR) of BSIO */
++
++ cfc->TimeCfgReg = ( ( BSMOW & 0x03) << 12)
++ | ( ( BSIORW & 0x03) << 14)
++ | ( ( BSA & 0x0f) << 0)
++ | ( ( BSM & 0x0f) << 4)
++ | ( ( BSIO & 0x0f) << 8);
++
++ SetCFCardMode( CF_MEM_MAP_MODE); /* set memory mode read write access */
++
++ cfc->MultiSector = 0x1; /* enable multi sector read/write */
++
++ /* select drive */
++ WriteCFCardByte( BLKMEM_DRIVE_REG, 0, COMMON_MEM);
++
++ /* identify drive device */
++ if( !CF_SendCommand( ATA_IDENTIFY_DRIVE)){
++
++ DEBUG( CF_DEBUG, 1, "Send Identify Drive command fail\n");
++ return -1;
++ }
++
++ SetTransferSize( BLKMEM_DATA_REG, COMMON_MEM, READ_OP, NOINCADR, SIZE_512_BYTE);
++
++ for( i = 0; i < CF_SECTOR_SIZE / 4; i++){
++
++ while( !( cfc->HostStatus & BUF_DATA_RDY_BIT))
++ ;
++
++ *( ( u32*)&buff[ i*4]) = cfc->BufferData;
++ }
++
++ /* clear command complete status */
++ cfc->HostStatus = INTA_BIT;
++
++ g_cf_sectors = ( ( u32)buff[ 15] << 24) | ( ( u32)buff[ 14] << 16) | ( ( u32)buff[ 17] << 8) | ( ( u32)buff[ 16]);
++ DEBUG( CF_DEBUG, 1, "Card identify - capicity: %d sectors, size: %d kbytes \n", g_cf_sectors, g_cf_sectors >> 1);
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++
++ return 0;
++}
++
++static int cfc_read_block( cf_card_t *info, uint size, uint *buf)
++{
++ /*
++ * Please refer SanDisk SD Manual v1.9 Section 5.1.9.2 ( page 5-76) to set the timeout setting
++ */
++ unsigned long timeout = jiffies + CFC_TIMEOUT_BASE *( ( size + 2048 + 511) >> 9);
++ uint count;
++ u8 data;
++ dmad_chreq *ch_req = (dmad_chreq *)info->private;
++ dmad_drb *drb = 0;
++ u32 drb_size = 0;
++ dma_addr_t addr_iter;
++
++ if( info->DMAEnable){
++
++ DEBUG( CF_DEBUG, 1, "DMA Read - size: %d, buf: 0x%08lx, dma_buf: 0x%08lx\n",
++ size, ( unsigned long)buf, ( unsigned long)dma_buf);
++
++ init_completion(&cf_dma_cmpl);
++
++ if (dma_buf)
++ consistent_sync(__va(dma_buf), size, DMA_FROM_DEVICE);
++ else
++ consistent_sync(buf, size, DMA_FROM_DEVICE);
++
++ //prepare parameter for add dma entry
++ dmad_config_channel_dir(ch_req, DMAD_DIR_A0_TO_A1);
++
++ drb_size = dmad_max_size_per_drb(ch_req);
++
++ if (dma_buf)
++ addr_iter = dma_buf; // given dest phy addr
++ else
++ addr_iter = __pa(buf);
++
++ cfc->ControlReg |= ENDMA_BIT;
++
++ while (size > 0) {
++
++ if (unlikely(0 != dmad_alloc_drb(ch_req, &drb) || (drb == 0))) {
++ printk(KERN_ERR "%s() Failed to allocate dma request block!\n", __func__);
++ return FALSE;
++ }
++
++ drb->addr0 = FTCFC_PA_BASE + 0x10;
++ drb->addr1 = addr_iter;
++
++ if (size <= drb_size) {
++ drb->req_cycle = dmad_bytes_to_cycles(ch_req, size);
++ drb->sync = &cf_dma_cmpl;
++ size = 0;
++ } else {
++ drb->req_cycle = dmad_bytes_to_cycles(ch_req, drb_size);
++ drb->sync = 0;
++ size -= drb_size;
++ addr_iter += drb_size;
++ }
++ //printk(KERN_INFO "%s() size_remain 0x%08x.\n", __func__, size);
++
++ if (unlikely(0 != dmad_submit_request(ch_req, drb, 1))) {
++ printk(KERN_ERR "%s() Failed to submit dma request block!\n", __func__);
++ return FALSE;
++ }
++ }
++
++ if (wait_for_completion_timeout(&cf_dma_cmpl, timeout - jiffies) == 0)
++ printk("%s: read timeout\n", __func__);
++
++ DEBUG( CF_DEBUG, 1, "ControlReg: 0x%08x, HostStatus: 0x%08x, BufCtrl: 0x%08x\n",
++ cfc->ControlReg, cfc->HostStatus, cfc->BuffCtrlReg);
++
++ while( !( cfc->HostStatus & INTA_BIT))
++ ;
++
++ cfc->HostStatus = INTA_BIT;
++
++ /* Stop DMA */
++ cfc->ControlReg &= ~ENDMA_BIT;
++ cfc->ControlReg &= ~MODE_BIT;
++
++ do {
++ data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
++
++ } while( data & BUSY_BIT);
++ }
++ else {
++ while( size > 0){
++
++ /* read data from FIFO */
++ if( size >= ( CFC_READ_FIFO_LEN << 2))
++ count = CFC_READ_FIFO_LEN;
++ else
++ count = size >> 2;
++
++ /* read data from FIFO */
++ DEBUG( CF_DEBUG, 0, "\n");
++ size -= ( count << 2);
++ }
++ }
++
++ data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
++
++ while( 1){
++
++ if( data & ERR_BIT){
++
++ DEBUG( CF_DEBUG, 1, "ERROR: ( CFReadSector) CF Read sector error.\n");
++ return FALSE;
++ }
++ else if( data & DWF_BIT){
++
++ DEBUG( CF_DEBUG, 1, "ERROR: ( CFReadSector) CF write fault error.\n");
++ return FALSE;
++ }
++ else if( data & ( RDY_BIT | DSC_BIT)){
++
++ break;
++ }
++ data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
++ }
++
++ return TRUE;
++}
++
++static int cfc_write_block( cf_card_t *info, uint size, uint *buf)
++{
++ unsigned long timeout = jiffies + CFC_TIMEOUT_BASE * 3 *( ( size + 511) >> 9);
++ uint count;
++ u8 data;
++ dmad_chreq *ch_req = (dmad_chreq *)info->private;
++ dmad_drb *drb = 0;
++ u32 drb_size = 0;
++ dma_addr_t addr_iter;
++
++ if( info->DMAEnable){
++
++ DEBUG( CF_DEBUG, 1, "size: %d, buf: %p) - DMA Write\n", size, buf);
++
++ init_completion(&cf_dma_cmpl);
++
++ if (dma_buf)
++ consistent_sync(__va(dma_buf), size, DMA_TO_DEVICE);
++ else
++ consistent_sync(buf, size, DMA_TO_DEVICE);
++
++ //prepare parameter for add dma entry
++ dmad_config_channel_dir(ch_req, DMAD_DIR_A1_TO_A0);
++
++ drb_size = dmad_max_size_per_drb(ch_req);
++
++ if (dma_buf)
++ addr_iter = dma_buf; // given dest phy addr
++ else
++ addr_iter = __pa(buf);
++
++ cfc->ControlReg |= ENDMA_BIT;
++
++ while (size > 0) {
++
++ if (unlikely(0 != dmad_alloc_drb(ch_req, &drb) || (drb == 0))) {
++ printk(KERN_ERR "%s() Failed to allocate dma request block!\n", __func__);
++ return FALSE;
++ }
++
++ drb->addr0 = FTCFC_PA_BASE + 0x10;
++ drb->addr1 = addr_iter;
++
++ if (size <= drb_size) {
++ drb->req_cycle = dmad_bytes_to_cycles(ch_req, size);
++ drb->sync = &cf_dma_cmpl;
++ size = 0;
++ } else {
++ drb->req_cycle = dmad_bytes_to_cycles(ch_req, drb_size);
++ drb->sync = 0;
++ size -= drb_size;
++ addr_iter += drb_size;
++ }
++ //printk(KERN_INFO "%s() size_remain 0x%08x.\n", __func__, size);
++
++ if (unlikely(0 != dmad_submit_request(ch_req, drb, 1))) {
++ printk(KERN_ERR "%s() Failed to submit dma request block!\n", __func__);
++ return FALSE;
++ }
++ }
++
++ if (wait_for_completion_timeout(&cf_dma_cmpl, timeout - jiffies) == 0)
++ printk("write timeout\n");
++
++ while( !( cfc->HostStatus & INTA_BIT))
++ ;
++
++ cfc->HostStatus = INTA_BIT;
++ /* Stop DMA */
++ cfc->ControlReg &= ~ENDMA_BIT;
++ cfc->ControlReg &= ~MODE_BIT;
++
++ do{
++ data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
++
++ } while( data & BUSY_BIT);
++ }
++ else {
++ while( size > 0){
++
++ /* write data from FIFO */
++ if( size >= ( CFC_WRITE_FIFO_LEN << 2))
++ count = CFC_WRITE_FIFO_LEN;
++ else
++ count = ( size >> 2);
++
++ size -= ( count << 2);
++ }
++ }
++
++ data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
++
++ while( 1){
++
++ if( data & ERR_BIT){
++
++ DEBUG( CF_DEBUG, 1, "ERROR: ( CFReadSector) CF Read sector error.\n");
++ return FALSE;
++ }
++ else if( data & DWF_BIT){
++
++ DEBUG( CF_DEBUG, 1, "ERROR: ( CFReadSector) CF write fault error.\n");
++ return FALSE;
++ }
++ else if( data & ( RDY_BIT | DSC_BIT))
++ break;
++
++ data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
++ }
++ return TRUE;
++}
++
++static int cf_card_insert( cf_card_t *info)
++{
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++ CardReset();
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++
++ return TRUE;
++}
++
++/* Free IRQ and DMA resources */
++static void cf_free( cf_dev_t *dev)
++{
++ release_region( FTCFC_VA_BASE, 0x48); /* return ioport */
++ free_irq( FTCFC_IRQ, dev); /* return Hotswapping irq */
++
++ if (cf_card_info.DMAEnable) {
++#if (CF_DEBUG)
++ if (dev->ch_req.controller == DMAD_DMAC_APB_CORE)
++ printk("%s: free APB dma channel (%d)\n", __func__, dev->ch_req.channel);
++ else
++ printk("%s: free AHB dma channel (%d)\n", __func__, dev->ch_req.channel);
++#endif
++ dmad_channel_free(&dev->ch_req);
++ cf_card_info.DMAEnable = FALSE;
++ }
++}
++
++static int cf_card_remove( cf_card_t *info)
++{
++ cf_err_code = ERR_NO_ERROR;
++
++ info->ActiveState = FALSE;
++ info->WriteProtect = FALSE;
++ info->RCA = 0;
++
++ /* reset host interface controller */
++ cfc->ControlReg |= RESET_BIT;
++
++ mdelay( 100);
++ cfc->ControlReg &= ~RESET_BIT; /* must manually clear reset bit */
++ return TRUE;
++}
++
++irqreturn_t cf_hotswap_interrupt_handler( int irq, void *dev_id)
++{
++ cf_dev_t *dev = dev_id;
++
++ DEBUG( CF_DEBUG, 1, "irq: %d\n", irq);
++
++ /*
++ * When the card is inserted or removed, we must delay a short time to make sure
++ * the SDC_STATUS_REG_CARD_INSERT bit of status register is stable
++ */
++
++ if( cfc->HostStatus & INT_CD_BIT ){
++
++ mdelay( 100); /* wait 0.1 sec for card stable */
++
++ DEBUG( CF_DEBUG, 1, "Card %s\n", cfc->HostStatus & CARD_DETECT_BIT ? "Insert" : "Remove");
++ if( cfc->HostStatus & CARD_DETECT_BIT ){
++
++ dev->card_state = CF_CARD_INSERT;
++ cf_card_insert( &cf_card_info);
++ }
++ else {
++ dev->card_state = CF_CARD_REMOVE;
++ cf_card_remove( &cf_card_info);
++ }
++
++ cfc->HostStatus = INT_CD_BIT;
++ }
++ else{
++ DEBUG( CF_DEBUG, 1, "cfc->HostStatus & INT_CD_BIT == 0\n");
++ }
++
++ DEBUG( CF_DEBUG, 1, "Exit: card state = %d\n", dev->card_state);
++ return IRQ_HANDLED;
++}
++
++int cf_read_multiple_block( cf_card_t *info, uint addr, uint count, uint size, uint timeout, unchar *buf)
++{
++ u8 data;
++
++ DEBUG( CF_DEBUG, 1, "read block addr: 0x%x(%d) sectors: %d\n", addr, addr, count);
++
++ cf_err_code = ERR_NO_ERROR;
++ Translate_Config_HCS( addr, count);
++ CF_SendCommand( ATA_READ_SECTOR);
++
++ do{
++ data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
++
++ } while( data & BUSY_BIT);
++
++ SetTransferSizeEx( BLKMEM_DATA_REG, COMMON_MEM, READ_OP, NOINCADR, CF_SECTOR_SIZE * count);
++
++ if( first_run == 0){
++
++ udelay( 100000);
++
++ first_run = 1;
++ }
++
++ if( !cfc_read_block( info, CF_SECTOR_SIZE * count, ( uint *)buf))
++ return FALSE;
++
++ if( cf_err_code != ERR_NO_ERROR){
++
++ DEBUG( CF_DEBUG, 1, "error = 0x%x\n", cf_err_code);
++ DEBUG( CF_DEBUG, 1, "r addr %d count %d\n", addr, count);
++
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++int cf_write_multiple_block( cf_card_t *info, uint addr, uint count, uint size, uint timeout, unchar *buf)
++{
++ u8 data;
++
++ DEBUG( CF_DEBUG, 1, "write block addr: 0x%08lx, sectors: %x, sector: %x\n", ( unsigned long)addr, count, 512);
++
++ cf_err_code = ERR_NO_ERROR;
++ Translate_Config_HCS( addr, count);
++ CF_SendCommand( ATA_WRITE_SECTOR);
++ do {
++ data = ReadCFCardByte( BLKMEM_STATUS_REG, COMMON_MEM);
++ } while( data & BUSY_BIT);
++
++ SetTransferSizeEx( BLKMEM_DATA_REG, COMMON_MEM, WRITE_OP, NOINCADR, CF_SECTOR_SIZE * count);
++
++ if( !cfc_write_block( info, CF_SECTOR_SIZE*count, ( uint *) buf))
++ return FALSE;
++
++ if( cf_err_code != ERR_NO_ERROR){
++
++ DEBUG( CF_DEBUG, 1, "error: 0x%08lx\n", ( unsigned long)cf_err_code);
++ DEBUG( CF_DEBUG, 1, "w addr: %d, count: %d\n", addr, count);
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++
++/***************************************************************************
++ * SD Card Read/Write/Erase Function
++ ***************************************************************************/
++int cf_read_sector( cf_card_t *info, uint addr, uint count, unchar *buf)
++{
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++
++ if( !cf_read_multiple_block( info, addr + cf_devices->lba_sec_offset, count,
++ info->CSD.ReadBlockLength, info->ReadAccessTimoutCycle, buf)){
++
++ DEBUG( CF_DEBUG, 1, "read failed\n");
++ return FALSE;
++ }
++
++ DEBUG( CF_DEBUG, 1, "read ok\n");
++
++ if( cf_devices->lba_sec_offset == 0){
++
++ if( !cf_read_multiple_block( info, 0, 1, info->CSD.ReadBlockLength, info->ReadAccessTimoutCycle, buf))
++ return FALSE;
++
++ /* lba ( ??) sector offset */
++ cf_devices->lba_sec_offset = ( *( buf + 0x1C6))
++ | ( *( buf + 0x1C7)) << 8
++ | ( *( buf + 0x1C8)) << 16
++ | ( *( buf + 0x1C9)) << 24;
++
++ /* device total sector number */
++ g_cf_sectors = ( *( buf + 0x1CA))
++ | ( *( buf + 0x1CB)) << 8
++ | ( *( buf + 0x1CC)) << 16
++ | ( *( buf + 0x1CD)) << 24;
++
++ /* only for testing , it only to let format command ok */
++ if( ( buf[ 0x1be] != 0x0) && ( buf[ 0x1be] != 0x80)) /* partition identify */
++ cf_devices->lba_sec_offset = 0; /* sector 0 is PBR */
++ else
++ cf_devices->lba_sec_offset = ( buf[ 0x1c6])
++ | ( buf[ 0x1c7] << 8)
++ | ( buf[ 0x1c8] << 16)
++ | ( buf[ 0x1c9] << 24);
++
++ DEBUG( CF_DEBUG, 1, "lba_sec_offet is %d\n", cf_devices->lba_sec_offset);
++ DEBUG( CF_DEBUG, 1, "the device( partition) total sector number is %d\n", g_cf_sectors);
++ }
++
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++ return TRUE;
++}
++
++int cf_write_sector( cf_card_t *info, uint addr, uint count, unchar *buf)
++{
++ if( !cf_write_multiple_block( info, addr+cf_devices->lba_sec_offset, count,
++ info->CSD.ReadBlockLength, info->ReadAccessTimoutCycle, buf)){
++
++ DEBUG( CF_DEBUG, 1, "write failed\n");
++
++ return FALSE;
++ }
++
++ DEBUG( CF_DEBUG, 1, "write ok\n");
++
++ return TRUE;
++}
++
++/*
++ * Perform an actual transfer:
++ * Returns: # of sectors transferred. 0 = error
++ */
++int cf_transfer( cf_dev_t *device, const struct request *req)
++{
++ int status = 0;
++ int count = 0;
++
++ struct bio *bio = req->bio;
++ struct bio_vec *bvec;
++ struct req_iterator iter;
++
++ DEBUG( CF_DEBUG, 1, "req sector: %d, phys_seg: %d, buf: 0x%08lx\n",
++ (int)req->__sector, req->nr_phys_segments,
++ (unsigned long)bio_data(bio));
++
++ spin_unlock_irq( &device->lock);
++
++ rq_for_each_segment( bvec, req, iter){
++
++ unsigned char *buf = page_address( bvec->bv_page) + bvec->bv_offset;
++ int sectors = bio_cur_bytes( bio) >> 9;
++
++ DEBUG( CF_DEBUG, 1, "bvec[%2d]: sector: %d, count: %d, curr: %d, buf: 0x%08lx\n",
++ iter.i, ( int)bio->bi_sector, count, ( int)sectors, ( unsigned long)buf);
++
++ cf_card_info.private = (void *)&device->ch_req;
++
++ if( rq_data_dir( req) == 0) /* Read */
++ status = cf_read_sector( &cf_card_info, bio->bi_sector, sectors, buf);
++ else
++ status = cf_write_sector( &cf_card_info, bio->bi_sector, sectors, buf);
++
++ DEBUG( CF_DEBUG, 1, "status: %d\n", status);
++
++ if (status <= 0) {
++ spin_lock_irq( &device->lock);
++ return count;
++ }
++
++ count += sectors;
++ bio->bi_sector += sectors;
++ }
++
++ spin_lock_irq( &device->lock);
++
++ if( status <= 0)
++ return 0;
++ else
++ return count;
++}
++
++static int cf_card_setup(cf_dev_t *dev)
++{
++ int i;
++
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++ first_run = 0;
++ cf_err_code = ERR_NO_ERROR;
++
++ cf_card_info.ActiveState = FALSE;
++ cf_card_info.WriteProtect = FALSE;
++ cf_card_info.IOAddr = FTCFC_VA_BASE;
++ cf_card_info.DMAEnable = TRUE;
++ cf_card_info.DMAChannel = dev->ch_req.channel;
++ cf_card_info.SysFrequency = AHB_CLK_IN / 2;
++ cf_card_info.RCA = 0;
++
++ DEBUG( CF_DEBUG, 1, "DMA Enable is %d, Sys frequency = %d\n", cf_card_info.DMAEnable, cf_card_info.SysFrequency);
++
++ if( !cf_card_insert( &cf_card_info))
++ return FALSE;
++
++ /* Marketing MB is not 1048576 */
++ DEBUG( CF_DEBUG, 1, "FTCFC010: CF Card Capacity = %d KBytes\n", g_cf_sectors >> 1);
++
++ for( i = 0; i < CF_DEVS; i++)
++ cf_devices[i].size = g_cf_sectors; /* unit is block, not bytes */
++
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++
++ return TRUE;
++}
++
++int cf_ioctl( struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
++{
++ int size;
++ struct hd_geometry geo;
++ cf_dev_t *device = bdev->bd_disk->private_data;
++
++ DEBUG( CF_DEBUG, 1, "ioctl 0x%x 0x%lx\n", cmd, arg);
++
++ switch ( cmd){
++
++ case BLKGETSIZE:
++ /*
++ * Return the device size, expressed in sectors
++ * FIXME: distinguish between kernel sector size and media sector size
++ */
++ size = device->size;
++ __copy_to_user ( ( long *) arg, &size, sizeof ( long));
++ return 0;
++
++ case HDIO_GETGEO:
++ /*
++ * get geometry: we have to fake one... trim the size to a
++ * multiple of 64 ( 32k): tell we have 16 sectors, 4 heads,
++ * whatever cylinders. Tell also that data starts at sector. 4.
++ */
++ geo.cylinders = ( device->size / 4) / 8; /* ?? only for test */
++ geo.heads = 4;
++ geo.sectors = 8;
++ geo.start = 0;
++ __copy_to_user ( ( void *) arg, &geo, sizeof ( geo));
++ return 0;
++
++ default:
++ /* For ioctls we don't understand, let the block layer handle them */
++ return -ENOTTY;
++ }
++
++ return -ENOTTY; /* unknown command */
++}
++
++static void cf_request( struct request_queue *q)
++{
++ cf_dev_t *dev;
++ int ret = 0;
++ struct request *req;
++ static int act = 0;
++
++ if( act)
++ return;
++
++ act = 1;
++
++ while( ( req = blk_fetch_request( q)) != NULL){
++
++ dev = req->rq_disk->private_data;
++
++ if( !dev || dev->card_state == CF_CARD_REMOVE){
++
++ DEBUG( CF_DEBUG, 1, "CF: locating device error\n");
++ __blk_end_request_cur( req, -EIO);
++
++ act = 0;
++ return;
++ }
++
++ ret = cf_transfer( dev, req);
++ __blk_end_request( req, 0, ret << 9);
++ }
++
++ act = 0;
++}
++
++static int cf_dma_ch_alloc(cf_dev_t *dev)
++{
++ dmad_chreq *ch_req = &dev->ch_req;
++
++ memset(ch_req, 0, sizeof(dmad_chreq));
++
++#ifdef CONFIG_PLATFORM_APBDMA
++
++ ch_req->apb_req.addr0_ctrl = APBBR_ADDRINC_FIXED; /* (in) APBBR_ADDRINC_xxx */
++ ch_req->apb_req.addr0_reqn = APBBR_REQN_CFC; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
++ ch_req->apb_req.addr1_ctrl = APBBR_ADDRINC_I4X; /* (in) APBBR_ADDRINC_xxx */
++ ch_req->apb_req.addr1_reqn = APBBR_REQN_NONE; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
++ ch_req->apb_req.burst_mode = 0; /* (in) Burst mode (0: no burst 1-, 1: burst 4- data cycles per dma cycle) */
++ ch_req->apb_req.data_width = APBBR_DATAWIDTH_4; /* (in) APBBR_DATAWIDTH_4(word), APBBR_DATAWIDTH_2(half-word), APBBR_DATAWIDTH_1(byte) */
++ ch_req->apb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
++
++ ch_req->controller = DMAD_DMAC_APB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
++ ch_req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
++
++ if (dmad_channel_alloc(ch_req) != 0) {
++ memset(ch_req, 0, sizeof(dmad_chreq));
++ printk(KERN_INFO "%s: APB dma channel allocation failed\n", __func__);
++ goto _try_ahb;
++ }
++
++#if (CF_DEBUG)
++ printk("%s: APB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
++#endif
++
++ return 0;
++
++_try_ahb:
++
++#endif /* CONFIG_PLATFORM_APBDMA */
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++
++ ch_req->ahb_req.sync = 1; /* (in) non-zero if src and dst have different clock domain */
++ ch_req->ahb_req.priority = DMAC_CSR_CHPRI_1; /* (in) DMAC_CSR_CHPRI_0 (lowest) ~ DMAC_CSR_CHPRI_3 (highest) */
++ ch_req->ahb_req.hw_handshake = 1; /* (in) non-zero to enable hardware handshake mode */
++ ch_req->ahb_req.burst_size = DMAC_CSR_SIZE_4; /* (in) DMAC_CSR_SIZE_1 ~ DMAC_CSR_SIZE_256 */
++ ch_req->ahb_req.addr0_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
++ ch_req->ahb_req.addr0_ctrl = DMAC_CSR_AD_FIX; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
++ ch_req->ahb_req.addr0_reqn = DMAC_REQN_CFC; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
++ ch_req->ahb_req.addr1_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
++ ch_req->ahb_req.addr1_ctrl = DMAC_CSR_AD_INC; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
++ ch_req->ahb_req.addr1_reqn = DMAC_REQN_NONE; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
++ ch_req->ahb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
++
++ ch_req->controller = DMAD_DMAC_AHB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
++ ch_req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
++
++ if (dmad_channel_alloc(ch_req) != 0) {
++ memset(ch_req, 0, sizeof(dmad_chreq));
++ printk(KERN_INFO "%s: AHB dma channel allocation failed\n", __func__);
++ goto _err_exit;
++ }
++
++#if (CF_DEBUG)
++ printk("%s: AHB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
++#endif
++
++ return 0;
++
++_err_exit:
++
++#endif /* CONFIG_PLATFORM_AHBDMA */
++
++ return -ENODEV;
++}
++
++/*
++ * Note no locks taken out here. In a worst case scenario, we could drop
++ * a chunk of system memory. But that should never happen, since validation
++ * happens at open or mount time, when locks are held.
++ */
++static int cf_revalidate( struct gendisk *gd)
++{
++ cf_dev_t *dev = gd->private_data;
++
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++ dev->card_state = cfc->HostStatus & CARD_DETECT_BIT ? CF_CARD_INSERT : CF_CARD_REMOVE;
++
++ DEBUG( CF_DEBUG, 1, "card state: %s\n",
++ dev->card_state == CF_CARD_INSERT ? "INSERT" :
++ dev->card_state == CF_CARD_WORK ? "WORK" : "REMOVE");
++
++ if( !dev->usage){
++
++ if( cf_card_setup(dev) != TRUE){
++
++ DEBUG( CF_DEBUG, 1, "cf_card_setup failed\n");
++ dev->card_state = CF_CARD_REMOVE;
++
++ return -1;
++ }
++ else {
++ DEBUG( CF_DEBUG, 1, "CFC Driver with DMA Mode\n");
++
++ if (cf_card_info.DMAEnable) {
++ /* acquire dma channel */
++ if (cf_dma_ch_alloc(dev) != 0) {
++ cf_card_info.DMAEnable = FALSE;
++ cf_free( dev);
++ DEBUG( CF_DEBUG, 1, "Request DMA resource failed\n");
++ return -1;
++ }
++ DEBUG( CF_DEBUG, 1, "Request DMA resource success\n");
++ }
++
++ /* SDC interrupt, currently only for HotSwap */
++ DEBUG( CF_DEBUG, 1, "Request CFC IRQ: %d\n", FTCFC_IRQ);
++
++ if( request_irq( FTCFC_IRQ, cf_hotswap_interrupt_handler, IRQF_DISABLED, "CF controller", dev) != 0){
++
++ DEBUG( CF_DEBUG, 1, "Unable to allocate CFC IRQ: 0x%x\n", FTCFC_IRQ);
++ cf_free( dev);
++ return -1;
++ }
++
++ /* require io port address for sd controller */
++ if( request_region( FTCFC_VA_BASE, 0x48, "CF Controller") == NULL){
++
++ DEBUG( CF_DEBUG, 1, "request io port of sd controller fail\n");
++ cf_free( dev);
++ return -1;
++ }
++
++ dev->card_state = CF_CARD_WORK;
++ }
++ }
++
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++
++ return 0;
++}
++
++/* TODO: forbids open for write when WRITE_PROTECT = 1 */
++static int cf_open( struct block_device *bdev, fmode_t mode)
++{
++ cf_dev_t *dev= bdev->bd_disk->private_data; /* device information */
++
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++
++ if( ( cfc->HostStatus & CARD_DETECT_BIT) != CARD_DETECT_BIT){
++
++ DEBUG( CF_DEBUG, 1, "Error: ( ENOMEDIUM)\n");
++ return -ENOMEDIUM;
++ }
++
++ if( CFCardInit()){
++
++ DEBUG( CF_DEBUG, 1, "root initialize failed\n");
++ return FALSE;
++ }
++
++ if( !dev->usage){
++
++ dev->media_change = 1;
++ DEBUG( CF_DEBUG, 1, "forced check_disk_change check\n");
++ check_disk_change( bdev);
++ }
++ else{
++ dev->media_change = 0;
++ }
++
++ DEBUG( CF_DEBUG, 1, "set_capacity() to %d blocks ( %d KBytes)\n", dev->size, dev->size >> 1);
++ set_capacity( dev->gd, dev->size);
++ dev->usage++;
++ cf_devices->lba_sec_offset = 0;
++ DEBUG( CF_DEBUG, 1, "dev: 0x%08lx, cf_devices: 0x%08lx\n", ( unsigned long)dev, ( unsigned long)cf_devices);
++
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++
++ return 0; /* success */
++}
++
++static int cf_release( struct gendisk *gd, fmode_t mode)
++{
++ cf_dev_t *dev = gd->private_data;
++
++ DEBUG( CF_DEBUG, 1, "Enter\n");
++
++ dev->usage--;
++
++ if( !dev->usage)
++ cf_free( dev);
++
++ DEBUG( CF_DEBUG, 1, "Exit\n");
++
++ return 0;
++}
++
++static void setup_device( struct cf_dev *dev, int which)
++{
++ memset ( dev, 0, sizeof ( struct cf_dev));
++ dev->size = 0;
++ spin_lock_init( &dev->lock);
++
++ dev->queue = blk_init_queue( cf_request, &dev->lock);
++
++ if( !dev->queue)
++ goto out_vfree;
++
++ blk_queue_logical_block_size( dev->queue, hardsect_size);
++ dev->queue->queuedata = dev;
++
++ dev->card_state = CF_CARD_REMOVE;
++
++ /* And the gendisk structure. */
++ dev->gd = alloc_disk( CF_MINORS);
++ if( ! dev->gd){
++
++ DEBUG( CF_DEBUG, 1, "alloc_disk failure\n");
++ goto out_vfree;
++ }
++
++ dev->gd->flags = GENHD_FL_REMOVABLE | GENHD_FL_SUPPRESS_PARTITION_INFO;
++ dev->gd->major = cf_major;
++ dev->gd->first_minor = which * CF_MINORS;
++ dev->gd->minors = CF_MINORS;
++ dev->gd->fops = &cf_fops;
++ dev->gd->queue = dev->queue;
++ dev->gd->private_data = dev;
++
++ snprintf ( dev->gd->disk_name, 32, "cpecf%c", which + 'a');
++ set_capacity( dev->gd, 0);
++ add_disk( dev->gd);
++
++ return;
++
++out_vfree:
++
++ return;
++}
++
++static int cf_media_changed( struct gendisk *gd)
++{
++ struct cf_dev *dev = gd->private_data;
++
++ DEBUG( CF_DEBUG, 1, "cf_media_changed = %d\n", dev->media_change);
++
++ return dev->media_change;
++}
++
++struct block_device_operations cf_fops = {
++
++ .owner = THIS_MODULE,
++ .open = cf_open,
++ .release = cf_release,
++ .ioctl = cf_ioctl,
++ .revalidate_disk = cf_revalidate,
++ .media_changed = cf_media_changed,
++};
++
++static int __init cf_module_init( void)
++{
++ int result= -ENOMEM, i;
++
++ DEBUG( 1, 0, "Faraday CF controller Driver (DMA mode)\n");
++
++ cf_major = register_blkdev( cf_major, DEVICE_NAME);
++
++ if( cf_major <= 0){
++
++ DEBUG( CF_DEBUG, 1, ":unable to get major number\n");
++ return -EBUSY;
++ }
++
++ DEBUG( 1, 0, "CF: make node with 'mknod /dev/cpecf b %d 0'\n", cf_major);
++
++ cf_devices = kzalloc( CF_DEVS * sizeof( cf_dev_t), GFP_KERNEL);
++
++ if( !cf_devices)
++ goto fail_malloc;
++
++ for( i = 0; i < CF_DEVS; i++)
++ setup_device( cf_devices + i, i);
++
++ return 0;
++
++fail_malloc:
++
++ if( cf_devices)
++ kfree( cf_devices);
++
++ unregister_blkdev( cf_major, DEVICE_NAME);
++
++ return result;
++}
++
++static void cf_module_cleanup( void)
++{
++ int i;
++
++ if( cf_devices){
++
++ for( i = 0; i < CF_DEVS; i++){
++
++ del_gendisk( cf_devices[i].gd);
++ put_disk( cf_devices[i].gd);
++
++ if( cf_devices[i].queue)
++ blk_cleanup_queue( cf_devices[i].queue);
++ }
++
++ kfree( cf_devices);
++ }
++
++ unregister_blkdev( cf_major, DEVICE_NAME);
++}
++
++module_init( cf_module_init);
++module_exit( cf_module_cleanup);
++
++MODULE_AUTHOR( "Faraday Corp.");
++MODULE_LICENSE( "GPL");
+diff -Nur linux-3.4.110.orig/drivers/block/ftcfc010.h linux-3.4.110/drivers/block/ftcfc010.h
+--- linux-3.4.110.orig/drivers/block/ftcfc010.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/block/ftcfc010.h 2016-04-07 10:20:51.022084119 +0200
+@@ -0,0 +1,438 @@
++/* drivers/block/CPECF/ftcfc.h
++ *
++ * Faraday FTCFC010 Device Driver
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ *
++ * All Rights Reserved
++ */
++
++#ifndef _FTCFC_H_
++#define _FTCFC_H_
++
++#define CF_DEBUG 1
++
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++#define CF_DEVS 1 /* number of disks */
++#define CF_MINORS 16 /* minors per disk */
++#define CF_SECTOR_SIZE 512 /* sector size */
++
++/* SD Card State */
++#define CF_CARD_REMOVE 0
++#define CF_CARD_INSERT 1
++#define CF_CARD_WORK 2
++
++/* data window register */
++#define CFC_READ_FIFO_LEN 4
++#define CFC_WRITE_FIFO_LEN 4
++
++/* card type, sd or mmc */
++#define MEMORY_CARD_TYPE_SD 0
++#define MEMORY_CARD_TYPE_MMC 1
++
++/*****************************************************************************
++ * SYSTEM ERROR_CODE
++ ****************************************************************************/
++#define ERR_NO_ERROR 0x00000000
++
++/* command error */
++#define ERR_DATA_CRC_ERROR 0x00000100
++#define ERR_RSP_CRC_ERROR 0x00000200
++#define ERR_DATA_TIMEOUT_ERROR 0x00000400
++#define ERR_RSP_TIMEOUT_ERROR 0x00000800
++
++#define ERR_WAIT_OVERRUN_TIMEOUT 0x00001000
++#define ERR_WAIT_UNDERRUN_TIMEOUT 0x00002000
++#define ERR_WAIT_DATA_CRC_TIMEOUT 0x00004000
++#define ERR_WAIT_TRANSFER_END_TIMEOUT 0x00008000
++
++#define ERR_SEND_COMMAND_TIMEOUT 0x00010000
++
++/* using APB DMA error */
++#define ERR_APBDMA_RSP_ERROR 0x02000000
++
++/*
++ * Please refer SanDisk SD Manual v1.9 Section 5.1.9.2 (page 5-76) to set the timeout setting
++ */
++#if CF_DEBUG
++#define CFC_TIMEOUT_BASE (HZ/2) /* Unit is 500 ms */
++#else
++#define CFC_TIMEOUT_BASE (HZ/3) /* Unit is 333 ms */
++#endif
++
++typedef struct _cf_cid_t
++{
++ uint ManufacturerID;
++ uint ApplicationID;
++ unchar ProductName[7];
++ uint ProductRevisionHigh;
++ uint ProductRevisionLow;
++ uint ProductSerialNumber;
++ uint ManufactureMonth;
++ uint ManufactureYear;
++} cf_cid_t;
++
++typedef struct _cf_ccf_t
++{
++ uint CSDStructure;
++ uint MMCSpecVersion;
++ uint TAAC_u;
++ uint NSAC_u;
++ uint TransferSpeed;
++ uint CardCmdClass;
++ uint ReadBlockLength;
++ uint ReadBlockPartial;
++ uint WriteBlockMisalign;
++ uint ReadBlockMisalign;
++ uint DSRImplemant;
++ uint BlockNumber;
++ uint MemorySize;
++ uint VDDReadMin_u;
++ uint VDDReadMax_u;
++ uint VDDWriteMin_u;
++ uint VDDWriteMax_u;
++ uint EraseBlkEnable;
++ uint EraseSectorSize;
++ uint WriteProtectGroupSize;
++ uint WriteProtectGroupEnable;
++ uint WriteSpeedFactor;
++ uint WriteBlockLength;
++ unchar WriteBlockPartial;
++ unchar CopyFlag;
++ unchar PermanentWriteProtect;
++ unchar TemporaryWriteProtect;
++ unchar FileFormat;
++} cf_ccf_t;
++
++/*****************************************************************************
++ * SD SCR register
++ ****************************************************************************/
++typedef struct _cf_scr_t
++{
++ uint Reserved:16;
++ uint SD_BUS_WIDTH:4;
++ uint SD_SECURITY:3;
++ uint DATA_STAT_AFTER_ERASE:1;
++ uint SD_SPEC:4;
++ uint SCR_STRUCTURE:4;
++
++ uint ManufacturerReserved;
++} cf_scr_t;
++
++/*****************************************************************************
++ * sd card structure
++ ****************************************************************************/
++typedef struct _cf_card_t
++{
++ /* host interface configuration */
++ uint IOAddr; /* host controller register base address */
++ uint DMAEnable;
++ uint DMAChannel;
++
++ uint CardType;
++
++ uint CIDWord[4];
++ cf_cid_t CID;
++
++ uint CSDWord[4];
++ cf_ccf_t CSD;
++
++ ushort RCA;
++ cf_scr_t SCR;
++
++ /* access time out */
++ uint ReadAccessTimoutCycle;
++ uint WriteAccessTimoutCycle;
++
++ /* system configurations */
++ uint SysFrequency;
++
++ /* card status */
++ int ActiveState;
++ int WriteProtect;
++
++ void *private;
++} cf_card_t;
++
++typedef struct _CF_Dev
++{
++ u32 dev_size; /* used same as sect_num */
++ u32 sect_num; /* sector num */
++ u8 blksize_bit; /* It's not used */
++ u32 blksize; /* size of block in file system, 1024 */
++
++ u32 phy_blksize; /* Physical size of block on the CF. It's not used */
++ u32 phy_sectorsize; /* the size of erasable sector. It's not used */
++ u32 wp_grp_size; /* the size of write protected group. It's not used */
++
++ spinlock_t lock; /* synchronization */
++ struct semaphore sema; /* synchronization */
++ u32 usage;
++
++ u8 busy;
++
++ wait_queue_head_t select_wait; /* Kernel thread blocked on it. It's not used */
++ u8 cmd; /* What command being executed. */
++ u32 result; /* set by tasklet */
++ u8 *buff;
++
++ u32 lba_sec_offset;
++
++ /*APB_DMA */
++
++ u8 DMATransDir; /* 0: IDLE, 1:READ, 2:WRITE */
++} CF_Dev;
++
++#define CFC_R_IDLE 0x00
++#define CFC_R_START_TRANSFER 0x01
++#define CFC_R_SET_CFCARD_REG 0x02
++#define CFC_R_SET_CFCARD_READ_CMD 0x03
++#define CFC_R_CHK_CFCARD_READY 0x04
++#define CFC_R_SET_DMA_REG 0x05
++#define CFC_R_DMA_START 0x06
++#define CFC_R_DMA_INT 0x07
++#define CFC_R_DMA_FINISH 0x08
++#define CFC_R_PIO_START 0x09
++#define CFC_R_PIO_FINISH 0x0A
++#define CFC_R_CHECK_CFCARD_BUSY 0x0B
++#define CFC_R_CHECK_CFCARD_READY 0x0C
++
++#define CFC_W_IDLE 0x00
++#define CFC_W_START_TRANSFER 0x10
++#define CFC_W_SET_CFCARD_REG 0x20
++#define CFC_W_SET_CFCARD_READ_CMD 0x30
++#define CFC_W_CHK_CFCARD_READY 0x40
++#define CFC_W_SET_DMA_REG 0x50
++#define CFC_W_DMA_START 0x60
++#define CFC_W_DMA_INT 0x70
++#define CFC_W_DMA_FINISH 0x80
++#define CFC_W_PIO_START 0x90
++#define CFC_W_PIO_FINISH 0xA0
++#define CFC_W_CHECK_CFCARD_BUSY 0xB0
++#define CFC_W_CHECK_CFCARD_READY 0xC0
++
++#define DMA_IDLE 0x00
++#define DMA_READ 0x01
++#define DMA_WRITE 0x02
++
++typedef struct CFCTYPE
++{
++ u32 HostStatus; /* 0x00 */
++ u32 ControlReg; /* 0x04 */
++ u32 TimeCfgReg; /* 0x08 */
++ u32 BuffCtrlReg; /* 0x0C */
++ u32 BufferData; /* 0x10 */
++ u32 MultiSector; /* 0x14 */
++
++ /* Enchanced Feature */
++ u32 TransSzMode2En; /* 0x18 */
++ u32 TransSzMode2Cnt; /* 0x1C */
++ u32 Reserved[4]; /* 0x20~0x2F is reserved */
++ u32 Revision; /* 0x30 */
++ u32 Feature; /* 0x34 (define buffer size) */
++
++} CFCTYPE;
++
++#define cfc ((volatile struct CFCTYPE *) (FTCFC_VA_BASE))
++
++typedef struct _tag_CFCardInfo
++{
++ u32 SectTotal;
++ u8 ConfigOptionReg;
++ u8 ConfigAndStatusReg;
++ u8 PinReplaceReg;
++ u8 SocketCopyReg;
++
++} CF_CARD_INFO;
++
++#define CFC_C_Complete 0x00000400
++#define CFC_B_Ready 0x00000200
++#define CFC_8bit 0x00000040
++#define CFC_16bit 0x00000000
++#define CFC_Reset 0x00000020
++#define CFC_T_2048 0x000C0000
++#define CFC_T_1024 0x000B0000
++#define CFC_T_512 0x000A0000
++#define CFC_T_256 0x00090000
++#define CFC_T_128 0x00080000
++#define CFC_T_64 0x00070000
++#define CFC_T_32 0x00060000
++#define CFC_T_16 0x00050000
++#define CFC_T_8 0x00040000
++#define CFC_T_4 0x00030000
++#define CFC_T_2 0x00020000
++#define CFC_T_1 0x00010000
++#define CFC_Read 0x00000000
++#define CFC_Write 0x00008000
++#define CFC_Increment 0x00004000
++#define CFC_Attribute 0x00000000
++#define CFC_Memory 0x00002000
++#define CFC_IO 0x00003000
++
++/* CF status register bit mapping */
++#define RDY_nIREQ_BIT 0x0001
++#define CARD_DETECT_BIT 0x0002
++#define VOL33_SENSE_BIT 0x0004
++#define VOL40_SENSE_BIT 0x0008
++#define STATUS_CHANGE_BIT 0x0010
++#define SPKR_BIT 0x0020
++#define BUF_ACTIVE_BIT 0x0100
++#define BUF_DATA_RDY_BIT 0x0200
++#define INTA_BIT 0x0400
++#define BUF_SIZE_BITS 0xF000
++#define INT_CD_BIT 0x10000
++#define INT_IO_BIT 0x20000
++
++/* CF control register bit mapping */
++#define POWER_CONTROL_BIT 0x000F
++#define FLOW_CONTROL_BIT 0x0010
++#define RESET_BIT 0x0020
++#define MODE_BIT 0x0040
++#define DMA_BIT 0x0100
++
++#define PWR_ON 1
++#define PWR_OFF 0
++
++#define SIGNAL_ON 0x0010
++#define SIGNAL_OFF 0x0000
++
++#define BYTE_MODE 0x0040
++#define WORD_MODE 0x0000
++
++#define ENDMA_BIT 0x0100
++#define DISDMA_BIT 0x0000
++
++#define CARD_DETECT_INT_MASK 0x0200
++#define DATA_CMP_INT_MASK 0x0400
++#define IO_INT_MASK 0x0800
++
++/* active buffer control register bit mapping */
++#define ADR_BIT 0x007FF
++#define TYPE_BIT 0x03000
++#define INCADR_BIT 0x04000
++#define RW_BIT 0x08000
++#define TRANS_SIZE_CONTROL_BIT 0xF0000
++
++#define INCADR 0x04000
++#define NOINCADR 0x00000
++#define TRANS_SIZE_LOC 16
++
++#define SIZE_1_BYTE 0x01
++#define SIZE_2_BYTE 0x02
++#define SIZE_4_BYTE 0x03
++#define SIZE_8_BYTE 0x04
++#define SIZE_16_BYTE 0x05
++#define SIZE_32_BYTE 0x06
++#define SIZE_64_BYTE 0x07
++#define SIZE_128_BYTE 0x08
++#define SIZE_256_BYTE 0x09
++#define SIZE_512_BYTE 0x0a
++#define SIZE_1024_BYTE 0x0b
++#define SIZE_2048_BYTE 0x0c
++
++#define READ_OP 0x00000
++#define WRITE_OP 0x08000
++
++/* type description */
++#define ATTRIBUTE_MEM 0x00000
++#define COMMON_MEM 0x02000
++
++/*
++ * CF card
++ * memory map register
++ * IO block register
++ */
++#define BLKMEM_DATA_REG 0x000
++#define BLKMEM_ERROR_REG ( BLKMEM_DATA_REG + 0x01)
++#define BLKMEM_FEATURE_REG ( BLKMEM_DATA_REG + 0x01)
++#define BLKMEM_SECTOR_COUNT_REG ( BLKMEM_DATA_REG + 0x02)
++#define BLKMEM_SECTOR_NUMBER_REG ( BLKMEM_DATA_REG + 0x03)
++#define BLKMEM_CYLINDER_LOW_REG ( BLKMEM_DATA_REG + 0x04)
++#define BLKMEM_CYLINDER_HIGH_REG ( BLKMEM_DATA_REG + 0x05)
++#define BLKMEM_DRIVE_REG ( BLKMEM_DATA_REG + 0x06)
++#define BLKMEM_STATUS_REG ( BLKMEM_DATA_REG + 0x07)
++#define BLKMEM_COMMAND_REG ( BLKMEM_DATA_REG + 0x07)
++
++#define BLKMEM_EVEN_DATA_REG ( BLKMEM_DATA_REG + 0x08)
++#define BLKMEM_ODD_DATA_REG ( BLKMEM_DATA_REG + 0x09)
++#define BLKMEM_DUP_ERROR_REG ( BLKMEM_DATA_REG + 0x0d)
++#define BLKMEM_DUP_FEATURE_REG ( BLKMEM_DATA_REG + 0x0d)
++#define BLKMEM_DEV_CONTROL_REG ( BLKMEM_DATA_REG + 0x0e)
++#define BLKMEM_DRIVE_ADDR_REG ( BLKMEM_DATA_REG + 0x0f)
++#define BLKMEM_WINDOW_REG ( BLKMEM_DATA_REG + 0x400)
++#define BLKMEM_MAX_WINDOW_REG ( BLKMEM_DATA_REG + 0x7ff)
++
++/* status register */
++#define BUSY_BIT 0x80
++#define RDY_BIT 0x40
++#define DWF_BIT 0x20
++#define DSC_BIT 0x10
++#define DRQ_BIT 0x08
++#define CORR_BIT 0x04
++#define ERR_BIT 0x01
++
++/* CF ATA command */
++#define ATA_CHECK_POWER_MODE 0xe5
++#define ATA_EXECUTE_DRIVE_DIAG 0x90
++#define ATA_ERASE_SECTOR 0xc0
++#define ATA_FORMAT_TRACK 0x50
++#define ATA_IDENTIFY_DRIVE 0xec
++#define ATA_IDLE 0xe3
++#define ATA_IDLE_IMMEDIATE 0xe1
++#define ATA_INIT_DRIVE_PARA 0x91
++#define ATA_READ_BUFFER 0xe4
++#define ATA_READ_LONG_SECTOR 0x22
++#define ATA_READ_MULTIPLE 0xc4
++#define ATA_READ_SECTOR 0x21
++#define ATA_READ_VERIFY_SECTOR 0x40
++#define ATA_RECALIBRATE 0x10
++#define ATA_REQUEST_SENSE 0x03
++#define ATA_SECURITY_DISABLE_PASSWORD 0xf6
++#define ATA_SECURITY_EREASE_PREPARE 0xf3
++#define ATA_SECURITY_ERASE_UNIT 0xf4
++#define ATA_SECURITY_FREEZE_LOCK 0xf5
++#define ATA_SECURITY_SET_PASSWORD 0xf1
++#define ATA_SECURITY_UNLOCK 0xf2
++#define ATA_SEEK 0x70
++#define ATA_SET_FEATURE 0xef
++#define ATA_SET_MULTIPLE_MODE 0xc6
++#define ATA_SET_SLEEP_MODE 0xe6
++#define ATA_STANDBY 0xe2
++#define ATA_STANDBY_IMMEDIATE 0xe0
++#define ATA_TRANSFER_SECTOR 0x87
++#define ATA_WEAR_LEVEL 0xf5
++#define ATA_WRITE_BUFFER 0xe8
++#define ATA_WRITE_LONG_SECTOR 0x32
++#define ATA_WRITE_MULTIPLE 0xc5
++#define ATA_WRITE_MULTIPLE_WO_ERASE 0xcd
++#define ATA_WRITE_SECTOR 0x30
++#define ATA_WRITE_SECTOR_WO_ERASE 0x38
++#define ATA_WRITE_VERIFY 0x3c
++
++#define CF_MEM_MAP_MODE 0x0
++/* attribute memory space register description */
++#define ATTRIBUTE_MEM_BASE 0
++#define ATTRIBUTE_MEM_CONFIG_BASE 0x200
++#define CONFIG_OPTION_REG ( ATTRIBUTE_MEM_CONFIG_BASE + 0x00)
++#define CARD_CONFIG_STATUS_REG ( ATTRIBUTE_MEM_CONFIG_BASE + 0x02)
++#define PIN_REPLACE_REG ( ATTRIBUTE_MEM_CONFIG_BASE + 0x04)
++#define SOCKET_COPY_REG ( ATTRIBUTE_MEM_CONFIG_BASE + 0x06)
++
++/* configuration option register */
++#define CONF0_BIT 0x01
++#define CONF1_BIT 0x02
++#define CONF2_BIT 0x04
++#define CONF3_BIT 0x08
++#define CONF4_BIT 0x10
++#define CONF5_BIT 0x20
++#define LEVLREQ_BIT 0x40
++#define SRESET_BIT 0x80
++
++#endif
+diff -Nur linux-3.4.110.orig/drivers/block/ftsdc010.c linux-3.4.110/drivers/block/ftsdc010.c
+--- linux-3.4.110.orig/drivers/block/ftsdc010.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/block/ftsdc010.c 2016-04-07 10:20:51.022084119 +0200
+@@ -0,0 +1,2206 @@
++/* drivers/block/CPESD/ftsdc010.c
++ *******************************************************************************
++ * Faraday FTSDC010 Device Driver
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ *
++ * All Rights Reserved
++ *
++ * Porting to Linux 2.6 on 20050815
++ * Author: Chris Lee, I-Jui Sung, Peter Liao (support APB DMA)
++ * Version: 0.2
++ * History:
++ * 0.1 new creation
++ * 0.2 Porting to meet the style of linux dma
++ * 0.3 modify dma usage to virtual irq of dma interrupt
++ * 0.4 (20050701) Improve r/w performance
++ * 0.5 Porting to Linux 2.6 and replace busy_loop checking with timer's timeout
++ * Todo:
++ *******************************************************************************
++ */
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/hdreg.h> /* HDIO_GETGEO */
++#include <linux/fs.h>
++#include <linux/blkdev.h>
++#include <linux/buffer_head.h> /* invalidate_bdev */
++#include <linux/bio.h>
++#include <linux/pci.h>
++#include <linux/mutex.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/spec.h>
++#include <asm/dmad.h>
++
++#define IPMODULE SDC
++#define IPNAME FTSDC010
++
++/* Define CONFIG_FTSDC010_USE_TIMER_DELAY if you want to use software timer instead of busy loop checking */
++#define CONFIG_FTSDC010_USE_TIMER_DELAY
++#undef CONFIG_FTSDC010_USE_TIMER_DELAY
++#include "ftsdc010.h"
++#include <linux/interrupt.h>
++MODULE_AUTHOR("Faraday Corp.");
++MODULE_LICENSE("Faraday License");
++
++/* options */
++#define FORCE_PCI_CONSISTENCY 1 /* define it to 1 if met consistency problems */
++#define KERNEL_SECTOR_SIZE 512 /* Use this when we refer to kernel related sector size */
++
++static int hardsect_size = 512;
++module_param(hardsect_size, int, 0);
++/*------------------------------------------------------------------------------
++ * Predefine for block device
++ */
++#define MAJOR_NR sd_major /* force definitions on in blk.h */
++static int sd_major=0;//SD_MAJOR; /* must be declared before including blk.h */
++#define SD_SHIFT 4 /* max 16 partitions */
++#define DEVICE_NAME "Faraday SDC" /* name for messaging */
++#define DEVICE_REQUEST sd_request
++#define DEVICE_NR(device) (MINOR(device) >> SD_SHIFT)
++//#define DEVICE_INTR sd_intrptr /* pointer to the bottom half */
++#define DEVICE_NO_RANDOM /* no entropy to contribute */
++#define DEVICE_OFF(d) /* do-nothing */
++
++/*#include <linux/blk.h>
++#include <linux/blkpg.h>*/ /* blk_ioctl() */
++
++/*------------------------------------------------------------------------------
++ * Macro definition
++ */
++#define FTSDC_VA_BASE IP_VA_BASE(0)
++#define FTSDC_PA_BASE IP_PA_BASE(0)
++#define FTSDC_IRQ IP_IRQ(0)
++#define SDC_W_REG(offset, value) outl(value, IP_VA_BASE(0) + offset)
++#define SDC_R_REG(offset) inl(IP_VA_BASE(0) + offset)
++
++
++/*------------------------------------------------------------------------------
++ * Global variable
++ */
++
++/* The following items are obtained through kmalloc() in sd_module_init() */
++
++struct block_device_operations sd_fops;
++/* our device structure */
++struct sd_dev {
++ int size; /* device size in sectors */
++ int usage; /* # of users currently */
++ int media_change; /* Flag: media changed? */
++ struct gendisk *gd; /* The gendisk structure */
++ spinlock_t lock; /* For mutual exclusion */
++ struct request_queue *queue; /* The device request queue */
++ int card_state;
++ dmad_chreq ch_req;
++ bool dma_enable;
++};
++static struct sd_dev *sd_devices = NULL;
++
++static sd_card_t sd_card_info;
++static int sector_offset,Do_onetime;
++
++dma_addr_t dma_buf = 0; /* ?? non-zero for for manually debug ?? */
++struct completion sd_dma_cmpl;
++
++static int sync_mode=0;
++
++static uint first_run = 0;
++uint sd_err_code;
++
++#define FILE_FORMAT_HARD_DISK_LIKE 0
++#define FILE_FORMAT_FLOPPY_LIKE 1
++#define FILE_FORMAT_UNIVERSAL 2
++#define FILE_FORMAT_UNKNOW 3
++#define FILE_FORMAT_RESERVED 4
++
++#define K 1000
++
++uint TAAC_TimeUnitTable[] = { // unit is ns
++ 1, 10, 100, 1 * K, 10 * K, 100 * K, 1 * K * K, 10 * K * K
++};
++
++uint TRANS_SPEED_RateUintTable[] = {
++ 100 * K, 1 * K * K, 10 * K * K, 100 * K * K
++};
++
++uint TRANS_SPEED_TimeValueTable_u[] = { // unit=1/10
++ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
++};
++
++uint VDD_CURR_MIN_Table_u[] = { // unit=1/10
++ 5, 10, 50, 100, 250, 350, 600, 1000
++};
++
++uint VDD_CURR_MAX_Table_u[] = {
++ 1, 5, 10, 25, 35, 45, 80, 200
++};
++
++uint TAAC_TimeValueTable_u[] = { // unit=1/10
++ 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80
++};
++
++
++unsigned int SDC_READ_FIFO_LEN;
++unsigned int SDC_WRITE_FIFO_LEN;
++
++/*------------------------------------------------------------------------------
++ * Local declaration of function
++ */
++static int sd_revalidate(struct gendisk *gd);
++static int sd_media_changed(struct gendisk *gd);
++static int sd_card_setup(struct sd_dev *dev);
++int sd_check_err(uint status);
++int sd_get_scr(sd_card_t *info, uint *scr);
++int sd_set_transfer_state(sd_card_t *info);
++uint sd_block_size_convert(uint size);
++int sd_read_sector(sd_card_t *info, uint addr, uint count, unchar *buf);
++void sd_reset_host_controller(void);
++/*------------------------------------------------------------------------------
++ * Local function
++ */
++
++/*
++ * SD host controller operation
++ */
++int sdc_send_cmd(uint cmd, uint arg, uint *rsp)
++{
++#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
++ int count = 0;
++#else
++ unsigned long timeout = jiffies + SDC_GET_STATUS_RETRY_TIMEOUT_COUNT;
++#endif
++ int i;
++ uint status;
++ P_DEBUG("SD Cmd is %d\n",cmd);
++
++ /* clear command relative bits of status register */
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_RSP_CRC_FAIL | SDC_STATUS_REG_RSP_TIMEOUT | SDC_STATUS_REG_RSP_CRC_OK| SDC_STATUS_REG_CMD_SEND);
++ /* write argument to arugument register if necessary */
++ SDC_W_REG(SDC_ARGU_REG, arg);
++ /* send command */
++ SDC_W_REG(SDC_CMD_REG, cmd | SDC_CMD_REG_CMD_EN);
++
++ /* wait for the CMD_SEND bit of status register is set */
++#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
++ while (count++ < SDC_GET_STATUS_RETRY_COUNT) {
++#else
++ while (time_before(jiffies, timeout)) {
++#endif
++ status = SDC_R_REG(SDC_STATUS_REG);
++ if (!(cmd & SDC_CMD_REG_NEED_RSP)) {
++ /* if this command does not need response, wait command sent flag */
++ if (status & SDC_STATUS_REG_CMD_SEND) {
++ /* clear command sent bit */
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_CMD_SEND);
++ sd_err_code = ERR_NO_ERROR;
++ return TRUE;
++ }
++ } else {
++ /* if this command needs response */
++ if (status & SDC_STATUS_REG_RSP_TIMEOUT) {
++ /* clear response timeout bit */
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_RSP_TIMEOUT);
++ sd_err_code = ERR_RSP_TIMEOUT_ERROR;
++ printk("%s() ERR_RSP_TIMEOUT_ERROR\n", __func__);
++ return FALSE;
++ } else if (status & SDC_STATUS_REG_RSP_CRC_FAIL) {
++ /* clear response fail bit */
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_RSP_CRC_FAIL);
++ sd_err_code = ERR_RSP_CRC_ERROR;
++ printk("%s() ERR_RSP_CRC_ERROR\n", __func__);
++ return FALSE;
++ } else if (status & SDC_STATUS_REG_RSP_CRC_OK) {
++ /* clear response OK bit */
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_RSP_CRC_OK);
++ /* if it is long response */
++ if (cmd & SDC_CMD_REG_LONG_RSP)
++ for (i = 0; i < 4; i++, rsp++)
++ *rsp = SDC_R_REG(SDC_RESPONSE0_REG + (i * 4));
++ else
++ *rsp = SDC_R_REG(SDC_RESPONSE0_REG);
++ sd_err_code = ERR_NO_ERROR;
++ return TRUE;
++ }
++ }
++ }
++ sd_err_code = ERR_SEND_COMMAND_TIMEOUT;
++ P_DEBUG("%s() ERR_SEND_COMMAND_TIMEOUT\n", __func__);
++ return FALSE;
++}
++
++int sdc_check_tx_ready(void)
++{
++ uint status;
++#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
++ int count = 0;
++ while (count++ < SDC_GET_STATUS_RETRY_COUNT) {
++#else
++ unsigned long timeout = jiffies + SDC_GET_STATUS_RETRY_TIMEOUT_COUNT;
++ while (time_before(jiffies, timeout)) {
++#endif
++ status = SDC_R_REG(SDC_STATUS_REG);
++ if (status & SDC_STATUS_REG_FIFO_UNDERRUN) {
++ /* clear FIFO underrun bit */
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_FIFO_UNDERRUN);
++ return TRUE;
++ } else if (status & SDC_STATUS_REG_DATA_TIMEOUT) {
++ /* clear data timeout bit */
++ printk("Wait Write FIFO TimeOut\n");
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_TIMEOUT);
++ sd_err_code = ERR_DATA_TIMEOUT_ERROR;
++ return FALSE;
++ }
++ }
++ sd_err_code = ERR_WAIT_UNDERRUN_TIMEOUT;
++ P_DEBUG("%s() ERR_WAIT_UNDERRUN_TIMEOUT\n", __func__);
++ return FALSE;
++}
++
++int sdc_check_rx_ready(void)
++{
++ uint status;
++#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
++ int count = 0;
++ while (count++ < SDC_GET_STATUS_RETRY_COUNT) {
++#else
++ unsigned long timeout = jiffies + SDC_GET_STATUS_RETRY_TIMEOUT_COUNT;
++ while (time_before(jiffies, timeout)) {
++#endif
++ status = SDC_R_REG(SDC_STATUS_REG);
++ if (status & SDC_STATUS_REG_FIFO_OVERRUN) {
++ /* clear FIFO overrun bit */
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_FIFO_OVERRUN);
++ return TRUE;
++ } else if (status & SDC_STATUS_REG_DATA_TIMEOUT) {
++ /* clear data timeout bit */
++ printk("Wait Read FIFO TimeOut\n");
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_TIMEOUT);
++ sd_err_code = ERR_DATA_TIMEOUT_ERROR;
++ return FALSE;
++ }
++ }
++ sd_err_code = ERR_WAIT_OVERRUN_TIMEOUT;
++ P_DEBUG("%s() ERR_WAIT_OVERRUN_TIMEOUT\n", __func__);
++ return FALSE;
++}
++
++int sdc_check_data_crc(void)
++{
++ uint status=0;
++#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
++ int count = 0;
++ while (count++ < SDC_GET_STATUS_RETRY_COUNT) {
++#else
++ unsigned long timeout = jiffies + SDC_GET_STATUS_RETRY_TIMEOUT_COUNT;
++ while (time_before(jiffies, timeout)) {
++#endif
++ status = SDC_R_REG(SDC_STATUS_REG);
++ if (status & SDC_STATUS_REG_DATA_CRC_OK) {
++ P_DEBUGG("%s : receive data ok, status=0x%x\n", __func__, status);
++ /* clear data CRC OK bit */
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_CRC_OK);
++ return TRUE;
++ } else if (status & SDC_STATUS_REG_DATA_CRC_FAIL) {
++ /* clear data CRC fail bit */
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_CRC_FAIL);
++ sd_err_code = ERR_DATA_CRC_ERROR;
++ printk("%s() ERR_DATA_CRC_ERROR\n", __func__);
++ return FALSE;
++ } else if (status & SDC_STATUS_REG_DATA_TIMEOUT) {
++ /* clear data timeout bit */
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_TIMEOUT);
++ sd_err_code = ERR_DATA_TIMEOUT_ERROR;
++ printk("%s() ERR_DATA_TIMEOUT_ERROR\n", __func__);
++ return FALSE;
++ }
++ }
++ P_DEBUG("%s() ERR_WAIT_DATA_CRC_TIMEOUT, status=0x%x\n", __func__, status);
++ sd_err_code = ERR_WAIT_DATA_CRC_TIMEOUT;
++ return FALSE;
++}
++
++static inline int sdc_check_data_end(void)
++{
++ uint status;
++#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
++ int count = 0;
++ while (count++ < SDC_GET_STATUS_RETRY_COUNT) {
++#else
++ unsigned long timeout = jiffies + SDC_GET_STATUS_RETRY_TIMEOUT_COUNT;
++ while (time_before(jiffies, timeout)) {
++#endif
++ status = SDC_R_REG(SDC_STATUS_REG);
++ if (status & SDC_STATUS_REG_DATA_END) {
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_END);
++ return TRUE;
++ } else if (status & SDC_STATUS_REG_DATA_TIMEOUT) {
++ /* clear data timeout bit */
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_DATA_TIMEOUT);
++ sd_err_code = ERR_DATA_TIMEOUT_ERROR;
++ printk("%s() ERR_DATA_TIMEOUT_ERROR\n", __func__);
++ return FALSE;
++ }
++ }
++ sd_err_code = ERR_WAIT_TRANSFER_END_TIMEOUT;
++ P_DEBUG("%s() ERR_WAIT_TRANSFER_END_TIMEOUT\n", __func__);
++ return FALSE;
++}
++
++int sdc_set_bus_width_cmd(sd_card_t *info, uint width)
++{
++ uint status;
++
++ /* send CMD55 to indicate to the card that the next command is an application specific command */
++ if (!sdc_send_cmd(SD_APP_CMD | SDC_CMD_REG_NEED_RSP, (((uint)info->RCA) << 16), &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++ /* send ACMD6 to set bus width */
++ if (!sdc_send_cmd(SD_SET_BUS_WIDTH_CMD | SDC_CMD_REG_APP_CMD | SDC_CMD_REG_NEED_RSP, width, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++
++ return TRUE;
++}
++
++int sdc_set_bus_width(sd_card_t *info)
++{
++ uint width;
++
++ /* if it is not SD card, it does not support wide bus */
++ if (info->CardType != MEMORY_CARD_TYPE_SD)
++ return TRUE;
++ /* get SCR register */
++ if (!sd_get_scr(info, (uint *) &info->SCR))
++ return FALSE;
++ /* if host controller does not support wide bus, return */
++ if ((SDC_R_REG(SDC_BUS_WIDTH_REG) & SDC_WIDE_BUS_SUPPORT) != SDC_WIDE_BUS_SUPPORT)
++ return TRUE;
++ if (!sd_set_transfer_state(info))
++ return FALSE;
++ if (info->SCR.SD_BUS_WIDTH & SD_SCR_4_BIT_BIT)
++ width = SD_BUS_WIDTH_4_BIT;
++ else
++ width = SD_BUS_WIDTH_1_BIT;
++ if (!sdc_set_bus_width_cmd(info, width))
++ return FALSE;
++ if (width == SD_BUS_WIDTH_1_BIT)
++ SDC_W_REG(SDC_BUS_WIDTH_REG, SDC_BUS_WIDTH_REG_SINGLE_BUS);
++ else
++ SDC_W_REG(SDC_BUS_WIDTH_REG, SDC_BUS_WIDTH_REG_WIDE_BUS);
++
++ return TRUE;
++}
++
++static inline int sdc_pre_erase_cmd(uint nr_blocks)
++{
++ uint status;
++ sd_card_t *info=&sd_card_info;
++ /* send CMD55 to indicate to the card that the next command is an application specific command */
++ if (!sdc_send_cmd(SD_APP_CMD | SDC_CMD_REG_NEED_RSP, (((uint)info->RCA) << 16), &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++ /* send ACMD6 to set bus width */
++ if (!sdc_send_cmd(23 | SDC_CMD_REG_APP_CMD | SDC_CMD_REG_NEED_RSP, nr_blocks, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++
++ return TRUE;
++}
++
++
++uint sdc_set_bus_clock(sd_card_t *info, uint clock)
++{
++ uint div = 0, reg;
++
++ while (clock < (info->SysFrequency / (2 * (div + 1))))
++ div++;
++ /* write clock divided */
++ reg = SDC_R_REG(SDC_CLOCK_CTRL_REG);
++ reg &= (~SDC_CLOCK_REG_CLK_DIV | 0x80); //ijsung: preserv SD or MMC
++ reg += div & SDC_CLOCK_REG_CLK_DIV;
++ SDC_W_REG(SDC_CLOCK_CTRL_REG, reg);
++ P_DEBUG("%s: SD clock=%d, info->SysFrequency=%d, div=%d\n",__func__,clock, info->SysFrequency, div);
++ return info->SysFrequency / (2 * (div + 1));
++}
++
++static inline int sdc_set_block_size(uint size)
++{
++ uint status;
++ static uint last_size=0;
++ if (size == last_size)
++ return TRUE;
++ else
++ last_size=size;
++
++ if (!sdc_send_cmd(SD_SET_BLOCKLEN_CMD | SDC_CMD_REG_NEED_RSP, size, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++ return TRUE;
++}
++
++void sdc_set_card_type(int type)
++{
++ uint reg;
++
++ reg = SDC_R_REG(SDC_CLOCK_CTRL_REG);
++ reg &= ~SDC_CLOCK_REG_CARD_TYPE;
++
++ if (type == MEMORY_CARD_TYPE_SD) {
++ reg |= SDC_CARD_TYPE_SD;
++ }
++ else {
++ reg |= SDC_CARD_TYPE_MMC;
++ }
++
++ SDC_W_REG(SDC_CLOCK_CTRL_REG, reg);
++}
++
++int sdc_read_block(sd_card_t *info, uint size, uint *buf)
++{
++ /*
++ * Please refer SanDisk SD Manual v1.9 Section 5.1.9.2 (page 5-76) to set the timeout setting
++ */
++ unsigned long timeout = jiffies + SDC_TIMEOUT_BASE*((size+511)>>9);
++ uint count, i;
++ dmad_chreq *ch_req = (dmad_chreq *)info->private;
++ dmad_drb *drb = 0;
++ u32 drb_size = 0;
++ dma_addr_t addr_iter;
++
++ //if (info->DMAEnable) {
++ if ((info->DMAEnable) && ((size & 0xf) == 0)) {
++ P_DEBUG("%s:size=%d, buf=%p) - DMA Read\n", __func__, size,buf );
++ P_DEBUG("dma_buf = %d\n", dma_buf);
++
++ init_completion(&sd_dma_cmpl);
++
++ if (dma_buf)
++ consistent_sync(__va(dma_buf), size, DMA_FROM_DEVICE);
++ else
++ consistent_sync(buf, size, DMA_FROM_DEVICE);
++
++ //prepare parameter for add dma entry
++ dmad_config_channel_dir(ch_req, DMAD_DIR_A0_TO_A1);
++
++ drb_size = dmad_max_size_per_drb(ch_req);
++
++ if (dma_buf)
++ addr_iter = dma_buf; // given dest phy addr
++ else
++ addr_iter = __pa(buf);
++
++ while (size > 0) {
++
++ if (unlikely(0 != dmad_alloc_drb(ch_req, &drb) || (drb == 0))) {
++ printk(KERN_ERR "%s() Failed to allocate dma request block!\n", __func__);
++ return FALSE;
++ }
++
++ drb->addr0 = FTSDC_PA_BASE + SDC_DATA_WINDOW_REG;
++ drb->addr1 = addr_iter;
++
++ if (size <= drb_size) {
++ drb->req_cycle = dmad_bytes_to_cycles(ch_req, size);
++ drb->sync = &sd_dma_cmpl;
++ size = 0;
++ } else {
++ drb->req_cycle = dmad_bytes_to_cycles(ch_req, drb_size);
++ drb->sync = 0;
++ size -= drb_size;
++ addr_iter += drb_size;
++ }
++ //printk(KERN_INFO "%s() size_remain 0x%08x.\n", __func__, size);
++
++ if (unlikely(0 != dmad_submit_request(ch_req, drb, 1))) {
++ printk(KERN_ERR "%s() Failed to submit dma request block!\n", __func__);
++ return FALSE;
++ }
++ }
++
++ if (wait_for_completion_timeout(&sd_dma_cmpl, timeout - jiffies) == 0)
++ printk("%s: read timeout\n", __func__);
++ } else {
++ while (size > 0) {
++ if (!sdc_check_rx_ready()) {
++ printk("error...........\n");
++ return FALSE;
++ }
++ /* read data from FIFO */
++ if (size >= (SDC_READ_FIFO_LEN << 2))
++ count = SDC_READ_FIFO_LEN;
++ else
++ count = size >> 2;
++ /* read data from FIFO */
++ P_DEBUG("\n");
++ for (i = 1; i <= count; i++, buf++)
++ {
++ *buf = SDC_R_REG(SDC_DATA_WINDOW_REG);
++ P_DEBUG("%.8x ",*buf);
++ }
++ size -= (count << 2);
++ }
++ }
++ return sdc_check_data_crc();
++}
++
++int sdc_write_block(sd_card_t *info, uint size, uint *buf)
++{
++ unsigned long timeout = jiffies + SDC_TIMEOUT_BASE*3*((size+511)>>9);
++ uint count, i;
++ dmad_chreq *ch_req = (dmad_chreq *)info->private;
++ dmad_drb *drb = 0;
++ u32 drb_size = 0;
++ dma_addr_t addr_iter;
++
++ //if (info->DMAEnable) {
++ if ((info->DMAEnable) && ((size & 0xf) == 0)) {
++ P_DEBUG("%s:size=%d, buf=%p) - DMA Write\n", __func__, size,buf );
++
++ init_completion(&sd_dma_cmpl);
++
++ if (dma_buf)
++ consistent_sync(__va(dma_buf), size, DMA_TO_DEVICE);
++ else
++ consistent_sync(buf, size, DMA_TO_DEVICE);
++
++ //prepare parameter for add dma entry
++ dmad_config_channel_dir(ch_req, DMAD_DIR_A1_TO_A0);
++
++ drb_size = dmad_max_size_per_drb(ch_req);
++
++ if (dma_buf)
++ addr_iter = dma_buf; // given dest phy addr
++ else
++ addr_iter = __pa(buf);
++
++ while (size > 0) {
++
++ if (unlikely(0 != dmad_alloc_drb(ch_req, &drb) || (drb == 0))) {
++ printk(KERN_ERR "%s() Failed to allocate dma request block!\n", __func__);
++ return FALSE;
++ }
++
++ drb->addr0 = FTSDC_PA_BASE + SDC_DATA_WINDOW_REG;
++ drb->addr1 = addr_iter;
++
++ if (size <= drb_size) {
++ drb->req_cycle = dmad_bytes_to_cycles(ch_req, size);
++ drb->sync = &sd_dma_cmpl;
++ size = 0;
++ } else {
++ drb->req_cycle = dmad_bytes_to_cycles(ch_req, drb_size);
++ drb->sync = 0;
++ size -= drb_size;
++ addr_iter += drb_size;
++ }
++ //printk(KERN_INFO "%s() size_remain 0x%08x.\n", __func__, size);
++
++ if (unlikely(0 != dmad_submit_request(ch_req, drb, 1))) {
++ printk(KERN_ERR "%s() Failed to submit dma request block!\n", __func__);
++ return FALSE;
++ }
++ }
++
++ if (wait_for_completion_timeout(&sd_dma_cmpl, timeout - jiffies) == 0)
++ printk("write timeout\n");
++ } else {
++ while (size > 0) {
++ if (!sdc_check_tx_ready())
++ return FALSE;
++ /* write data from FIFO */
++ if (size >= (SDC_WRITE_FIFO_LEN << 2))
++ count = SDC_WRITE_FIFO_LEN;
++ else
++ count = (size >> 2) ;
++ /* write data from FIFO */
++ for (i = 0; i < count; i++, buf++)
++ SDC_W_REG(SDC_DATA_WINDOW_REG, *buf);
++ size -= (count << 2);
++ }
++ }
++ return sdc_check_data_crc();
++}
++
++void sdc_config_transfer(sd_card_t *SDCard, uint len, uint size, uint rw, uint timeout)
++{
++ u32 con;
++ /* write timeout */
++ SDC_W_REG(SDC_DATA_TIMER_REG, timeout * 2);
++ /* set data length */
++ SDC_W_REG(SDC_DATA_LEN_REG, len);
++
++ /* set data block */
++ if (SDCard->DMAEnable) {
++ con = sd_block_size_convert(size) | SDC_DATA_CTRL_REG_DMA_EN | rw | SDC_DATA_CTRL_REG_DATA_EN;
++ con |= SDC_DMA_TYPE_4;
++ P_DEBUG("%s() transfer DMA mode\n", __func__);
++ SDC_W_REG(SDC_DATA_CTRL_REG, con);
++ } else {
++ P_DEBUG("%s() transfer nonDMA mode\n", __func__);
++ SDC_W_REG(SDC_DATA_CTRL_REG, sd_block_size_convert(size) | rw | SDC_DATA_CTRL_REG_DATA_EN);
++ }
++}
++
++/* Note: This funciton may be called by interrupt handler */
++void sdc_reset(void)
++{
++ uint ret;
++ unsigned long delay = jiffies + (HZ/10)*3; //Delay 300ms
++
++ /* reset host interface */
++ SDC_W_REG(SDC_CMD_REG, SDC_CMD_REG_SDC_RST);
++
++ /* loop, until the reset bit is clear */
++ do {
++ ret = SDC_R_REG(SDC_CMD_REG);
++ } while ((ret & SDC_CMD_REG_SDC_RST) != 0);
++ #if 0
++ udelay(1000);
++ #else
++ while(time_before(jiffies, delay));
++ #endif
++}
++
++/*
++ * SD card operation
++ */
++void sd_endian_change(uint *dt, int len)
++{
++ uint ul;
++
++ for(; len > 0; len--, dt++) {
++ ul = *dt;
++ ((unchar *)dt)[0] = ((unchar *)&ul)[3];
++ ((unchar *)dt)[1] = ((unchar *)&ul)[2];
++ ((unchar *)dt)[2] = ((unchar *)&ul)[1];
++ ((unchar *)dt)[3] = ((unchar *)&ul)[0];
++ }
++}
++
++int sd_get_ocr(sd_card_t *info, uint hocr, uint *cocr)
++{
++ uint status;
++ int count = 0;
++
++ do {
++ if (info->CardType == MEMORY_CARD_TYPE_SD) {
++ /* send CMD55 to indicate to the card that the next command is an application specific command */
++ if (!sdc_send_cmd(SD_APP_CMD | SDC_CMD_REG_NEED_RSP, ((uint) info->RCA) << 16, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++ /* send ACMD41 to get OCR register */
++ if (!sdc_send_cmd(SD_APP_OP_COND | SDC_CMD_REG_APP_CMD | SDC_CMD_REG_NEED_RSP, (uint) hocr, (uint *) cocr))
++ return FALSE;
++ } else {
++ /* send CMD1 to get OCR register */
++ if (!sdc_send_cmd(SD_MMC_OP_COND | SDC_CMD_REG_NEED_RSP, (uint) hocr, (uint *) cocr))
++ return FALSE;
++ }
++ if (count++ > SD_CARD_GET_OCR_RETRY_COUNT) {
++ sd_err_code = ERR_SD_CARD_IS_BUSY;
++ printk("%s : ERR_SD_CARD_IS_BUSY\n", __func__);
++ return FALSE;
++ }
++ udelay(1000); /* According to spec, at most 1 msec or 74 clock cycles */
++ } while ((*cocr & SD_OCR_BUSY_BIT) != SD_OCR_BUSY_BIT);
++
++ return TRUE;
++}
++
++int sd_get_scr(sd_card_t *info, uint *scr)
++{
++ uint status;
++
++ if (!sd_set_transfer_state(info))
++ return FALSE;
++ if (!sdc_set_block_size(8))
++ return FALSE;
++ sdc_config_transfer(info, 8, 8, SDC_DATA_CTRL_REG_DATA_READ, 0xFFFFFFFF);
++ /* send CMD55 to indicate to the card that the next command is an application specific command */
++ if (!sdc_send_cmd(SD_APP_CMD | SDC_CMD_REG_NEED_RSP, ((uint) info->RCA) << 16, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++ /* send ACMD51 to get SCR */
++ if (!sdc_send_cmd(SD_SEND_SCR_CMD | SDC_CMD_REG_APP_CMD | SDC_CMD_REG_NEED_RSP, 0, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++ if (!sdc_read_block(info, 8, (uint *) scr))
++ return FALSE;
++ if (!sdc_check_data_end())
++ return FALSE;
++ sd_endian_change(scr, 2);
++
++ return TRUE;
++}
++
++int sd_check_err(uint status)
++{
++ if (status & SD_STATUS_ERROR_BITS) {
++ sd_err_code = ERR_SD_CARD_STATUS_ERROR;
++ printk("%s() ERR_SD_CARD_STATUS_ERROR %X\n", __func__, status);
++ return FALSE;
++ }
++ sd_err_code = ERR_NO_ERROR;
++ return TRUE;
++}
++
++int sd_get_card_state(sd_card_t *info, uint *ret)
++{
++ uint status;
++
++ /* send CMD13 to get card status */
++ if (!sdc_send_cmd(SD_SEND_STATUS_CMD | SDC_CMD_REG_NEED_RSP, ((uint) info->RCA) << 16, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++ *ret = (status & SD_STATUS_CURRENT_STATE) >> SD_STATUS_CURRENT_STATE_LOC;
++ return TRUE;
++}
++
++int sd_operation_complete(sd_card_t *info, uint finish)
++{
++ uint state;
++ int count = 0;
++ while (count++ < SD_CARD_WAIT_OPERATION_COMPLETE_RETRY_COUNT) {
++ if (!sd_get_card_state(info, &state))
++ return FALSE;
++ if (state == finish)
++ return TRUE;
++ }
++ P_DEBUG("%s() error\n", __func__);
++ return FALSE;
++}
++
++int sd_stop_transmission(void)
++{
++ uint status;
++
++ /* send CMD12 to stop transmission */
++ if (!sdc_send_cmd(SD_STOP_TRANSMISSION_CMD | SDC_CMD_REG_NEED_RSP, 0, &status))
++ return FALSE;
++
++ if (!sd_check_err(status))
++ return FALSE;
++
++ return TRUE;
++}
++
++int sd_set_card_standby(sd_card_t *info)
++{
++ uint state;
++ int count = 0;
++ while (count++ < SD_CARD_STATE_CHANGE_RETRY_COUNT) {
++ if (!sd_get_card_state(info, &state))
++ return FALSE;
++
++ switch (state) {
++ case SD_IDLE_STATE:
++ case SD_READY_STATE:
++ case SD_IDENT_STATE:
++ printk("%s() error\n", __func__);
++ return FALSE;
++ case SD_DIS_STATE:
++ return sd_operation_complete(info, SD_STBY_STATE);
++ case SD_TRAN_STATE:
++ if (!sdc_send_cmd(SD_SELECT_CARD_CMD, 0, NULL))
++ return FALSE;
++ break;
++ case SD_DATA_STATE:
++ if (sd_operation_complete(info, SD_TRAN_STATE))
++ return TRUE;
++ if (sd_err_code != ERR_NO_ERROR)
++ return FALSE;
++ if (!sd_stop_transmission())
++ return FALSE;
++ break;
++ case SD_RCV_STATE:
++ if (sd_operation_complete(info, SD_TRAN_STATE))
++ return TRUE;
++ if (sd_err_code != ERR_NO_ERROR)
++ return FALSE;
++ if (!sd_stop_transmission())
++ return FALSE;
++ break;
++ case SD_PRG_STATE:
++ if (!sd_operation_complete(info, SD_TRAN_STATE))
++ return FALSE;
++ break;
++ case SD_STBY_STATE:
++ return TRUE;
++ }
++ }
++ P_DEBUG("%s() error\n", __func__);
++ return FALSE;
++}
++
++uint two_power(uint n)
++{
++ uint pow = 1;
++
++ for (; n > 0; n--)
++ pow <<= 1;
++ return pow;
++}
++
++int sd_csd_parse(sd_csd_t *csd, uint *csd_word)
++{
++ sd_csd_bit_t *csd_bit;
++ uint mult, blocks, len;
++
++ if ((csd_word[0] & 0x00000001) != 1) {
++ sd_err_code = ERR_CSD_REGISTER_ERROR;
++ printk("%s() ERR_CSD_REGISTER_ERROR\n", __func__);
++ return FALSE;
++ }
++
++ csd_bit = (sd_csd_bit_t *) csd_word;
++ csd->CSDStructure = csd_bit->CSD_STRUCTURE;
++ csd->MMCSpecVersion = csd_bit->MMC_SPEC_VERS;
++ csd->TAAC_u = TAAC_TimeValueTable_u[csd_bit->TAAC_TimeValue] * TAAC_TimeUnitTable[csd_bit->TAAC_TimeUnit] / 10;
++ csd->NSAC_u = csd_bit->NSAC * 100;
++ csd->TransferSpeed = TRANS_SPEED_RateUintTable[csd_bit->TRAN_SPEED_RateUnit] * TRANS_SPEED_TimeValueTable_u[csd_bit->TRAN_SPEED_TimeValue] / 10;
++ csd->CardCmdClass = csd_bit->CCC;
++ csd->ReadBlockLength = two_power(csd_bit->READ_BL_LEN);
++ csd->ReadBlockPartial = csd_bit->READ_BL_PARTIAL;
++ csd->WriteBlockMisalign = csd_bit->WRITE_BLK_MISALIGN;
++ csd->ReadBlockMisalign = csd_bit->READ_BLK_MISALIGN;
++ csd->DSRImplemant = csd_bit->DSR_IMP;
++ mult = 1 << (csd_bit->C_SIZE_MULT + 2);
++ blocks = ((csd_bit->C_SIZE_1 | (csd_bit->C_SIZE_2 << 2)) + 1) * mult;
++ len = 1 << (csd_bit->READ_BL_LEN);
++ csd->BlockNumber = blocks;
++ csd->MemorySize = blocks * len;
++ csd->VDDReadMin_u = VDD_CURR_MIN_Table_u[csd_bit->VDD_R_CURR_MIN];
++ csd->VDDReadMax_u = VDD_CURR_MAX_Table_u[csd_bit->VDD_R_CURR_MAX];
++ csd->VDDWriteMin_u = VDD_CURR_MIN_Table_u[csd_bit->VDD_W_CURR_MIN];
++ csd->VDDWriteMax_u = VDD_CURR_MAX_Table_u[csd_bit->VDD_W_CURR_MAX];
++ csd->EraseBlkEnable = csd_bit->ERASE_BLK_ENABLE;
++ csd->EraseSectorSize = csd_bit->ERASE_SECTOR_SIZE + 1;
++ csd->WriteProtectGroupSize = csd_bit->WP_GRP_SIZE + 1;
++ csd->WriteProtectGroupEnable = csd_bit->WP_GRP_ENABLE;
++ csd->WriteSpeedFactor = two_power(csd_bit->R2W_FACTOR);
++ csd->WriteBlockLength = two_power(csd_bit->WRITE_BL_LEN);
++ csd->WriteBlockPartial = csd_bit->WRITE_BL_PARTIAL;
++ csd->CopyFlag = csd_bit->COPY;
++ csd->PermanentWriteProtect = csd_bit->PERM_WRITE_PROTECT;
++ csd->TemporaryWriteProtect = csd_bit->TMP_WRITE_PROTECT;
++
++ if (csd_bit->FILE_FORMAT_GRP == 0)
++ csd->FileFormat = csd_bit->FILE_FORMAT;
++ else
++ csd->FileFormat = FILE_FORMAT_RESERVED;
++
++ return TRUE;
++}
++
++int sd_cid_parse(sd_cid_t *cid, uint *cid_word)
++{
++ unchar *ptr;
++ int i;
++
++ if ((cid_word[0] & 0x00000001) != 1)
++ {
++ sd_err_code = ERR_CID_REGISTER_ERROR;
++ printk("%s() ERR_CID_REGISTER_ERROR\n", __func__);
++ return FALSE;
++ }
++
++ cid->ManufacturerID = (cid_word[3] & 0xFF000000) >> 24;
++ cid->ApplicationID = (cid_word[3] & 0x00FFFF00) >> 8;
++
++ ptr = (unchar *) cid_word;
++ ptr += 15 - 3;
++ for (i = 0; i < 6; i++, ptr--)
++ cid->ProductName[i] = *ptr;
++ cid->ProductName[6] = '\0' ;
++
++ cid->ProductRevisionLow = (cid_word[1] & 0x00F00000) >> 20;
++ cid->ProductRevisionHigh = (cid_word[1] & 0x000F0000) >> 16;
++ cid->ProductSerialNumber = ((cid_word[1] & 0x0000FFFF) << 16) + ((cid_word[0] & 0xFFFF0000) >> 16);
++ cid->ManufactureMonth = ((cid_word[0] & 0x00000F00) >> 8);
++ cid->ManufactureYear = ((cid_word[0] & 0x0000F000) >> 12) + SD_DEFAULT_YEAR_CODE;
++
++ return TRUE;
++}
++
++uint sd_read_timeout_cycle(uint clock, sd_csd_t *csd)
++{
++#if 1 //ivan for 100ms maximux from document "ProdManualIndGradeSDv1.0[1].pdf" chapter A-2
++ return clock/10; // /10;
++#else
++ uint ret, total, per;
++
++ per = 1000000000 / clock;
++ total = (csd->TAAC_u + (csd->NSAC_u * 100 * per)) * 100;
++
++ if (total > (100 * 1000 * 1000))
++ total = 100 * 1000 * 1000;
++ ret = total / per;
++
++ return ret;
++#endif
++}
++
++uint sd_block_size_convert(uint size)
++{
++ uint ret = 0;
++
++ while (size >= 2) {
++ size >>= 1;
++ ret++;
++ }
++ return ret;
++}
++
++int sd_select_card(sd_card_t *info)
++{
++ uint status;
++
++ /* send CMD7 with valid RCA to select */
++ if (!sdc_send_cmd(SD_SELECT_CARD_CMD | SDC_CMD_REG_NEED_RSP, ((uint)info->RCA) << 16, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++ return TRUE;
++}
++
++int sd_set_transfer_state(sd_card_t *info)
++{
++ uint state;
++ int count = 0;
++ while (count++ < SD_CARD_STATE_CHANGE_RETRY_COUNT) {
++ if (!sd_get_card_state(info, &state))
++ return FALSE;
++
++ switch (state) {
++ case SD_IDLE_STATE:
++ case SD_READY_STATE:
++ case SD_IDENT_STATE:
++ printk("%s() error\n", __func__);
++ return FALSE;
++ case SD_DIS_STATE:
++ if (!sd_operation_complete(info, SD_STBY_STATE))
++ return FALSE;
++ break;
++ case SD_TRAN_STATE:
++ return TRUE;
++ case SD_DATA_STATE:
++ if (sd_operation_complete(info, SD_TRAN_STATE))
++ return TRUE;
++ if (sd_err_code != ERR_NO_ERROR)
++ return FALSE;
++ if (!sd_stop_transmission())
++ return FALSE;
++ break;
++ case SD_RCV_STATE:
++ if (sd_operation_complete(info, SD_TRAN_STATE))
++ return TRUE;
++ if (sd_err_code != ERR_NO_ERROR)
++ return FALSE;
++ if (!sd_stop_transmission())
++ return FALSE;
++ break;
++ case SD_PRG_STATE:
++ if (!sd_operation_complete(info, SD_TRAN_STATE))
++ return FALSE;
++ break;
++ case SD_STBY_STATE:
++ if (!sd_select_card(info))
++ return FALSE;
++ }
++ }
++ P_DEBUG("%s() error\n", __func__);
++ return FALSE;
++}
++
++uint sd_write_timeout_cycle(uint clock, sd_csd_t *CSD)
++{
++#if 1 //ivan for 250ms maximux from document
++ return clock/4; //ijsung hack
++#else
++ uint ret, total, pre;
++
++ pre = 1000000000 / clock;
++ total = CSD->WriteSpeedFactor * 100 * (CSD->TAAC_u + (CSD->NSAC_u * 100 * pre));
++
++ if (total > (100 * 1000 * 1000))
++ total = 100 * 1000 * 1000;
++ ret = total / pre;
++
++ return ret;
++#endif
++}
++
++int sd_card_identify(sd_card_t *info)
++{
++ uint rca, status, cid[4];
++
++ /* reset all cards */
++ if (!sdc_send_cmd(SD_GO_IDLE_STATE_CMD, 0, NULL))
++ return FALSE;
++ udelay(1000);
++ /* Do operating voltage range validation */
++ /* get OCR register */
++ if (!sd_get_ocr(info, SDC_OCR, (uint *) &info->OCR))
++ return FALSE;
++ /* ckeck the operation conditions */
++ if ((info->OCR & SDC_OCR) == 0) {
++ sd_err_code = ERR_OUT_OF_VOLF_RANGE;
++ return FALSE;
++ }
++
++ /* send CMD2 to get CID register */
++ if (!sdc_send_cmd(SD_ALL_SEND_CID_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, 0, cid))
++ return FALSE;
++ if (info->CardType == MEMORY_CARD_TYPE_SD) {
++ /* send CMD3 to get RCA register */
++ if (!sdc_send_cmd(SD_SEND_RELATIVE_ADDR_CMD | SDC_CMD_REG_NEED_RSP, 0, &rca))
++ return FALSE;
++ info->RCA = (ushort) (rca >> 16);
++ } else {
++ /* so far, we only support one interface, so we can give RCA any value */
++ info->RCA = 0x1;
++ /* send CMD3 to set RCA register */
++ if (!sdc_send_cmd(SD_SEND_RELATIVE_ADDR_CMD | SDC_CMD_REG_NEED_RSP, (info->RCA << 16), &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++int sd_card_init(sd_card_t *info)
++{
++ uint clock;
++
++ P_DEBUG("--> %s\n", __func__);
++ if ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_INSERT) != SDC_CARD_INSERT)
++ return FALSE;
++ sd_err_code = ERR_NO_ERROR;
++ /* At first, set card type to SD */
++ info->CardType = MEMORY_CARD_TYPE_SD;
++ /* set memory card type */
++ sdc_set_card_type(info->CardType);
++ /* start card idenfication process */
++ if (!sd_card_identify(info)) {
++ printk("this is not SD card\n");
++ sd_err_code = ERR_NO_ERROR;
++ info->CardType = MEMORY_CARD_TYPE_MMC;
++ /* set memory card type */
++ sdc_set_card_type(info->CardType);
++ if (!sd_card_identify(info))
++ return FALSE;
++ }
++
++ /* get CSD */
++ if (!sd_set_card_standby(info))
++ return FALSE;
++ /* send CMD9 to get CSD register */
++ if (!sdc_send_cmd(SD_SEND_CSD_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, ((uint) info->RCA) << 16, info->CSDWord))
++ return FALSE;
++ sd_csd_parse(&info->CSD, info->CSDWord);
++
++ if (info->CSD.ReadBlockLength != SD_SECTOR_SIZE) {
++ printk("Sector size is mis-matched (SD CSD report=0x%X,SD_SECTOR_SIZE=0x%X)\n", info->CSD.ReadBlockLength, SD_SECTOR_SIZE);
++ info->CSD.ReadBlockLength = SD_SECTOR_SIZE;
++// return FALSE;
++ }
++
++ /* get CID */
++ /* send CMD10 to get CID register */
++ if (!sdc_send_cmd(SD_SEND_CID_CMD | SDC_CMD_REG_NEED_RSP | SDC_CMD_REG_LONG_RSP, ((uint) info->RCA) << 16, info->CIDWord))
++ return FALSE;
++ sd_cid_parse(&info->CID, info->CIDWord);
++
++ /* Set card bus clock. sdc_set_bus_clock() will give the real card bus clock has been set. */
++ clock = sdc_set_bus_clock(info, info->CSD.TransferSpeed);
++ info->ReadAccessTimoutCycle = sd_read_timeout_cycle(clock, &(info->CSD));
++ info->WriteAccessTimoutCycle = sd_write_timeout_cycle(clock, &(info->CSD));
++ /* set bus width */
++ if (!sdc_set_bus_width(info))
++ return FALSE;
++
++ /* check write protect */
++ info->WriteProtect = ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_LOCK) == SDC_STATUS_REG_CARD_LOCK) ? TRUE : FALSE;
++ if(info->WriteProtect == TRUE)
++ printk("SD/MMC Card is Write Protected\n");
++ info->ActiveState = TRUE;
++ P_DEBUG("<-- %s\n", __func__);
++
++ return TRUE;
++}
++
++int sd_card_insert(sd_card_t *info)
++{
++ P_DEBUG("--> %s\n", __func__);
++ /* reset host interface controller */
++ sdc_reset();
++ /* turn on clock using default clock*/
++ SDC_W_REG(SDC_CLOCK_CTRL_REG, SDC_R_REG(SDC_CLOCK_CTRL_REG)&0xff);
++
++ if (!sd_card_init(info)) {
++ printk("root initialize failed\n");
++ return FALSE;
++ }
++ /* set interrupt mask register */
++ SDC_W_REG(SDC_INT_MASK_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);
++ P_DEBUG("<-- %s\n", __func__);
++
++ return TRUE;
++}
++
++int sd_card_remove(sd_card_t *info)
++{
++ sd_err_code = ERR_NO_ERROR;
++
++ info->ActiveState = FALSE;
++ info->WriteProtect = FALSE;
++ info->RCA = 0;
++ /* reset host interface controller */
++ sdc_reset();
++ /* set interrupt mask register */
++ SDC_W_REG(SDC_INT_MASK_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);
++ sd_err_code = ERR_CARD_NOT_EXIST;
++ /* turn off clock */
++ SDC_W_REG(SDC_CLOCK_CTRL_REG, SDC_R_REG(SDC_CLOCK_CTRL_REG) | 0x100);
++ return TRUE;
++}
++
++irqreturn_t sd_hotswap_interrupt_handler(int irq, void *dev_id)
++{
++ uint status;
++ struct sd_dev *dev = dev_id;
++
++ P_DEBUG("--> %s, irq=%d\n", __func__, irq);
++ /* When the card is inserted or removed, we must delay a short time to make sure */
++ /* the SDC_STATUS_REG_CARD_INSERT bit of status register is stable */
++ udelay(1000);
++ status = SDC_R_REG(SDC_STATUS_REG);
++ if ((status & SDC_STATUS_REG_CARD_CHANGE) == SDC_STATUS_REG_CARD_CHANGE) {
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);
++ if ((status & SDC_STATUS_REG_CARD_INSERT) == SDC_CARD_INSERT) {
++ dev->card_state = SD_CARD_INSERT;
++ printk("Card Insert\n");
++ sd_card_insert(&sd_card_info);
++ } else {
++ dev->card_state = SD_CARD_REMOVE;
++ printk("Card Remove\n");
++ sd_card_remove(&sd_card_info);
++ /* remove all current transfers as I/O error*/
++#if 0 //ASYNC
++ spin_lock_irqsave(&io_request_lock, status);
++ INIT_REQUEST;
++ while(!QUEUE_EMPTY)
++ end_request(0);
++ bh_busy=0;
++ spin_unlock_irqrestore(&io_request_lock, status);
++#endif
++ }
++ } else if ((status & SDC_STATUS_REG_DATA_TIMEOUT) == SDC_STATUS_REG_DATA_TIMEOUT) {
++ SDC_W_REG(SDC_CLEAR_REG, SDC_STATUS_REG_CARD_CHANGE | SDC_STATUS_REG_DATA_TIMEOUT);
++
++#if 0 //ASYNC
++ printk("Data timeout. Retry.\n");
++ sd_clustered_bh(2);
++#else
++ printk("Data timeout. Retry.\n");
++#endif
++ }
++ P_DEBUGG("card state=%d\n", dev->card_state);
++ P_DEBUG("<-- %s\n", __func__);
++ return IRQ_HANDLED;
++}
++
++/*------------------------------------
++ * Block-driver specific functions
++ */
++/*
++ * Find the device for this request.
++ */
++#if 0
++static inline struct sd_dev *sd_locate_device(const struct request *req)
++{
++ int devno;
++ struct sd_dev *dev;
++
++ P_DEBUG("--> %s\n", __func__);
++#if 0
++ /* Check if the minor number is in range */
++ devno = DEVICE_NR(req->rq_dev);
++ P_DEBUGG("minor=%d\n", devno);
++ if (devno >= SD_DEVS) {
++ static int count = 0;
++
++ if (count++ < 5) /* print the message at most five times */
++ P_DEBUG("request for unknown device\n");
++ return NULL;
++ }
++#endif
++ dev = sd_devices + devno;
++ P_DEBUGG("card_state=%d\n", dev->card_state);
++ P_DEBUG("<-- %s\n", __func__);
++ return dev;
++}
++
++int sd_card_check_exist(sd_card_t *info)
++{
++ /* if card is not exist */
++ if ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_INSERT) != SDC_CARD_INSERT) {
++ sd_card_remove(info);
++ return FALSE;
++ }
++ /* if card is not active */
++ if (!info->ActiveState)
++ {
++ return sd_card_insert(info);
++ }
++ return TRUE;
++}
++#endif
++
++void sd_reset_host_controller(void)
++{
++ uint clock, mask, width;
++
++ /* read register */
++ clock = SDC_R_REG(SDC_CLOCK_CTRL_REG);
++ width = SDC_R_REG(SDC_BUS_WIDTH_REG);
++ mask = SDC_R_REG(SDC_INT_MASK_REG);
++ /* reset host interface */
++ sdc_reset();
++ /* restore register */
++ SDC_W_REG(SDC_CLOCK_CTRL_REG, clock);
++ SDC_W_REG(SDC_BUS_WIDTH_REG, width);
++ SDC_W_REG(SDC_INT_MASK_REG, mask);
++}
++
++int sd_read_single_block(sd_card_t *info, uint addr, uint size, uint timeout, unchar *buf)
++{
++ uint status;
++
++ if (!sdc_set_block_size(size))
++ return FALSE;
++
++ sdc_config_transfer(info, size, size, SDC_DATA_CTRL_REG_DATA_READ, timeout);
++
++ if (!sdc_send_cmd(SD_READ_SINGLE_BLOCK_CMD | SDC_CMD_REG_NEED_RSP, addr, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++
++#ifdef DELAY_FOR_DMA_READ
++ if (first_run==0) {
++ int i=0;
++ for(i=0;i<10;i++)
++ udelay(1000);
++ first_run=1;
++ }
++#endif
++ if (!sdc_read_block(info, size, (uint *) buf))
++ return FALSE;
++
++ if (sd_err_code != ERR_NO_ERROR) {
++ printk("%s() error=0x%X\n", __func__, sd_err_code);
++ sd_reset_host_controller();
++ return FALSE;
++ } else {
++ if (!sdc_check_data_end()) {
++ sd_stop_transmission();
++ printk("%s()2 error=0x%X\n", __func__, sd_err_code);
++ return FALSE;
++ }
++ }
++
++ return TRUE;
++}
++
++int sd_write_single_block(sd_card_t *info, uint addr, uint size, uint timeout, unchar *buf)
++{
++ uint status;
++
++ if (!sdc_set_block_size(size))
++ return FALSE;
++
++ sdc_config_transfer(info, size, size, SDC_DATA_CTRL_REG_DATA_WRITE, timeout);
++
++ if (!sdc_send_cmd(SD_WRITE_SINGLE_BLOCK_CMD | SDC_CMD_REG_NEED_RSP, addr, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++
++ if (!sdc_write_block(info, size, (uint *) buf))
++ return FALSE;
++ if (sd_err_code != ERR_NO_ERROR) {
++ printk("%s() error=0x%X\n", __func__, sd_err_code);
++ sd_reset_host_controller();
++ return FALSE;
++ } else {
++ if (!sdc_check_data_end()) {
++ sd_stop_transmission();
++ printk("%s()2 error=0x%X\n", __func__, sd_err_code);
++ return FALSE;
++ }
++ }
++
++ return TRUE;
++}
++
++int sd_read_multiple_block(sd_card_t *info, uint addr, uint count, uint size, uint timeout, unchar *buf)
++{
++ uint err, status;
++
++ if (!sdc_set_block_size(size))
++ return FALSE;
++
++ sdc_config_transfer(info, count * size, size, SDC_DATA_CTRL_REG_DATA_READ, timeout);
++
++ if (!sdc_send_cmd(SD_READ_MULTIPLE_BLOCK_CMD | SDC_CMD_REG_NEED_RSP, addr, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++
++#ifdef DELAY_FOR_DMA_READ
++ if (first_run==0) {
++ int i=0;
++ for(i=0;i<10;i++)
++ udelay(1000);
++ first_run=1;
++ }
++#endif
++#if 0 //ijsung: Sometimes this will cause IRQ lost, and is slower. Use method below
++ while (count > 0) {
++ if (!sdc_read_block(info, size, (uint *) buf))
++ return FALSE;
++ count--;
++ buf += size;
++ }
++#else //ijsung: DMA at once.
++ if (!sdc_read_block(info, size*count, (uint *) buf))
++ return FALSE;
++#endif
++ if (sd_err_code != ERR_NO_ERROR) {
++ err = sd_err_code;
++ sd_stop_transmission();
++ sd_reset_host_controller();
++ sd_err_code |= err;
++ printk("%s() error=0x%X\n", __func__, sd_err_code);
++ return FALSE;
++ } else {
++ if (!sdc_check_data_end()) {
++ err = sd_err_code;
++ sd_stop_transmission();
++ sd_err_code |= err;
++ printk("%s()2 error=0x%X\n", __func__, sd_err_code);
++ return FALSE;
++ }
++ if (!sd_stop_transmission())
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++int sd_write_multiple_block(sd_card_t *info, uint addr, uint count, uint size, uint timeout, unchar *buf)
++{
++ uint ErrorCode, status;
++
++ if(!sdc_set_block_size(size))
++ return FALSE;
++
++ sdc_config_transfer(info, count * size, size, SDC_DATA_CTRL_REG_DATA_WRITE, timeout);
++ sdc_pre_erase_cmd(count); //ijsung: pre-erase
++ if (!sdc_send_cmd(SD_WRITE_MULTIPLE_BLOCK_CMD | SDC_CMD_REG_NEED_RSP, addr, &status))
++ return FALSE;
++ if (!sd_check_err(status))
++ return FALSE;
++#if 0 //ijsung: Sometimes this will cause IRQ lost, and is slower. Use method below
++ while (count > 0) {
++ if (!sdc_write_block(info, size, (uint *) buf))
++ return FALSE;
++ count--;
++ buf += size;
++ }
++#else //ijsung: DMA at once.
++ if (!sdc_write_block(info, size*count, (uint *) buf))
++ return FALSE;
++#endif
++
++ if (sd_err_code != ERR_NO_ERROR)
++ {
++ ErrorCode = sd_err_code;
++ sd_stop_transmission();
++ sd_reset_host_controller();
++ sd_err_code |= ErrorCode;
++ printk("%s() error=0x%X\n", __func__, sd_err_code);
++ return FALSE;
++ } else {
++ if (!sdc_check_data_end()) {
++ ErrorCode = sd_err_code;
++ sd_stop_transmission();
++ sd_err_code |= ErrorCode;
++ printk("%s()2 error=0x%X\n", __func__, sd_err_code);
++ return FALSE;
++ }
++ if (!sd_stop_transmission())
++ return FALSE;
++ }
++
++ return TRUE;
++}
++
++int sd_wait_transfer_state(sd_card_t *info)
++{
++ uint state;
++ int count = 0;
++ while (count++ < SD_CARD_WAIT_TRANSFER_STATE_RETRY_COUNT) {
++ if (!sd_get_card_state(info, &state))
++ return FALSE;
++
++ switch (state) {
++ case SD_IDLE_STATE:
++ case SD_READY_STATE:
++ case SD_IDENT_STATE:
++ case SD_DIS_STATE:
++ case SD_STBY_STATE:
++ printk("%s() error\n", __func__);
++ return FALSE;
++ case SD_TRAN_STATE:
++ return TRUE;
++ case SD_DATA_STATE:
++ case SD_RCV_STATE:
++ case SD_PRG_STATE:
++ break;
++ }
++ }
++ sd_err_code = ERR_SD_CARD_IS_BUSY;
++ P_DEBUG("%s() ERR_SD_CARD_IS_BUSY\n", __func__);
++ return FALSE;
++}
++
++/***************************************************************************
++SD Card Read/Write/Erase Function
++***************************************************************************/
++int sd_read_sector(sd_card_t *info, uint addr, uint count, unchar *buf)
++{
++ int cnt;
++ uint start;
++ sync_mode=1;
++ P_DEBUG("%s : sector = %d,count = %d\n",__func__,addr,count);
++ if (count > MAX_READ_SECTOR_NR) {
++ P_DEBUG("Readable Block Number Per Commands is 0x%X\n",MAX_READ_SECTOR_NR);
++ return FALSE;
++ }
++
++ sd_err_code = ERR_NO_ERROR;
++
++ if (!info->ActiveState) {
++ P_DEBUG("%s : SD card not active!!\n", __func__);
++ return FALSE;
++ }
++
++ if (!sd_set_transfer_state(info))
++ return FALSE;
++
++ start = addr * info->CSD.ReadBlockLength;
++ cnt = (int) count;
++
++ while (cnt > 0) {
++ if (cnt > 1) {
++ if (!sd_read_multiple_block(info, start, (cnt > MAX_MULTI_BLOCK_NUM) ? MAX_MULTI_BLOCK_NUM : cnt,
++ info->CSD.ReadBlockLength, info->ReadAccessTimoutCycle, buf))
++ return FALSE;
++ } else {
++ if (!sd_read_single_block(info, start, info->CSD.ReadBlockLength, info->ReadAccessTimoutCycle, buf))
++ return FALSE;
++ return TRUE;
++ }
++
++ if (!sd_wait_transfer_state(info))
++ return FALSE;
++
++ cnt -= MAX_MULTI_BLOCK_NUM;
++ start += MAX_MULTI_BLOCK_NUM * info->CSD.ReadBlockLength;
++ buf += MAX_MULTI_BLOCK_NUM * info->CSD.ReadBlockLength;
++ }
++
++ return TRUE;
++}
++
++int sd_write_sector(sd_card_t *info, uint addr, uint count, unchar *buf)
++{
++ int cnt;
++ uint start;
++
++ if (count > MAX_WRITE_SECTOR_NR) {
++ P_DEBUG("Writable Block Number Per Commands is 0x%X\n",MAX_WRITE_SECTOR_NR);
++ return FALSE;
++ }
++
++ sd_err_code = ERR_NO_ERROR;
++
++ if (!info->ActiveState) {
++ P_DEBUG("%s : SD card not active!!\n", __func__);
++ return FALSE;
++ }
++
++ if (info->WriteProtect == TRUE) {
++ sd_err_code = ERR_SD_CARD_IS_LOCK;
++ printk("Write Protected!!\n");
++ return FALSE;
++ }
++ if (!sd_set_transfer_state(info))
++ return FALSE;
++
++ start = addr * info->CSD.ReadBlockLength;
++ cnt = (int) count;
++
++ while (cnt > 0) {
++ if (cnt > 1) {
++ if (!sd_write_multiple_block(info, start, (cnt > MAX_MULTI_BLOCK_NUM) ? MAX_MULTI_BLOCK_NUM : cnt,
++ info->CSD.ReadBlockLength, info->WriteAccessTimoutCycle, buf))
++ return FALSE;
++ } else {
++ if (!sd_write_single_block(info, start, info->CSD.ReadBlockLength, info->WriteAccessTimoutCycle, buf))
++ return FALSE;
++ return TRUE;
++ }
++
++ if (!sd_wait_transfer_state(info))
++ return FALSE;
++
++ cnt -= MAX_MULTI_BLOCK_NUM;
++ start += MAX_MULTI_BLOCK_NUM * info->CSD.ReadBlockLength;
++ buf += MAX_MULTI_BLOCK_NUM * info->CSD.ReadBlockLength;
++ }
++
++ return TRUE;
++}
++/*----------------------------------------------
++ * Perform an actual transfer:
++ * Returns: # of sectors transferred. 0 = error
++ */
++static int sd_transfer(struct sd_dev *device, const struct request *req)
++{
++ int status = 0;
++ int count = 0;
++
++ struct bio *bio = req->bio;
++ struct bio_vec *bvec;
++ struct req_iterator iter;
++
++ spin_unlock_irq( &device->lock);
++
++#if 0
++ P_DEBUG("\nreq sector: %d, nr_sectors: %d, hard_cur_sectors: %d phys_seg: %d, buf: 0x%08lx\n",
++ (int)req->sector, (int)req->nr_sectors, (int)req->hard_cur_sectors,
++ (int)req->nr_phys_segments, (ulong)bio_data( bio));
++#endif
++
++ rq_for_each_segment( bvec, req, iter) {
++
++ unsigned char *buf = page_address( bvec->bv_page) + bvec->bv_offset;
++ int sectors = bio_cur_bytes(bio) >> 9;
++
++ P_DEBUG("bvec[%2d]: sector: %d, count: %d, curr: %d, buf: 0x%08lx, ",
++ iter.i, (int)bio->bi_sector, count, (int)sectors, (unsigned long)buf);
++
++ sd_card_info.private = (void *)&device->ch_req;
++
++ if( rq_data_dir(req) == 0) /* Read */
++ status = sd_read_sector( &sd_card_info, sector_offset + bio->bi_sector, sectors, buf);
++ else
++ status = sd_write_sector( &sd_card_info, sector_offset + bio->bi_sector, sectors, buf);
++
++ P_DEBUG("status: %d\n", status);
++
++ if (status <= 0) {
++ spin_lock_irq( &device->lock);
++ return count;
++ }
++
++ count += sectors;
++ bio->bi_sector += sectors;
++ }
++
++ if( ( req->__sector == 0) && !Do_onetime){
++
++ unsigned char *buf = bio_data( bio);
++
++ if( ( buf[ 0x1be] != 0x0) && ( buf[ 0x1be] != 0x80)) /* partition identify */
++ sector_offset = 0; //sector 0 is PBR
++ else
++ sector_offset = ( buf[ 0x1c6]) | ( buf[ 0x1c7] << 8) | ( buf[ 0x1c8] <<16) |( buf[ 0x1c9] << 24);
++
++ P_DEBUG( "sector_offset = %d\n", sector_offset);
++ Do_onetime = 1;
++ }
++
++ spin_lock_irq( &device->lock);
++
++ if( status <= 0)
++ return 0;
++ else
++ return count;
++}
++
++#ifdef SD_DEBUG
++uint sd_dev_info(void)
++{
++ sd_csd_t *CSD;
++ sd_cid_t *CID;
++
++ P_DEBUG("============SDCard=====================================\n");
++#if 0
++ if (!sd_card_check_exist(&sd_card_info))
++ {
++ P_DEBUG("SD Card does not exist!!!");
++ return FALSE;
++ }
++#else
++ if (!sd_card_info.ActiveState) {
++ P_DEBUG("%s : SD card not active!!\n", __func__);
++ return FALSE;
++ }
++#endif
++
++ /* print OCR, RCA register */
++ P_DEBUG("OCR>> 0x%08X RCA>> 0x%04X\n", (uint) sd_card_info.OCR, sd_card_info.RCA);
++ /* print CID register */
++ P_DEBUG("CID>> 0x%08X 0x%08X 0x%08X 0x%08X\n", sd_card_info.CIDWord[0], sd_card_info.CIDWord[1], sd_card_info.CIDWord[2], sd_card_info.CIDWord[3]);
++ CID = &(sd_card_info.CID);
++ P_DEBUG(" MID:0x%02X OID:0x%04X PNM:%s PRV:%d.%d PSN:0x%08X\n", CID->ManufacturerID, CID->ApplicationID, CID->ProductName,
++ CID->ProductRevisionHigh, CID->ProductRevisionLow, CID->ProductSerialNumber);
++ P_DEBUG(" MDT:%d/%d\n", CID->ManufactureMonth, CID->ManufactureYear);
++ /* print CSD register */
++ P_DEBUG("CSD>> 0x%08X 0x%08X 0x%08X 0x%08X\n", sd_card_info.CSDWord[0], sd_card_info.CSDWord[1], sd_card_info.CSDWord[2], sd_card_info.CSDWord[3]);
++ CSD = &(sd_card_info.CSD);
++ P_DEBUG(" CSDStructure:%d Spec.Version:%d\n", CSD->CSDStructure, CSD->MMCSpecVersion);
++ P_DEBUG(" TAAC:%dns NSAC:%d clock cycles\n", CSD->TAAC_u, CSD->NSAC_u);
++ P_DEBUG(" TransferSpeed:%d bit/s CardCommandClass:0x%03X\n", CSD->TransferSpeed, CSD->CardCmdClass);
++ P_DEBUG(" ReadBlLen:%d ReadBlPartial:%X WriteBlkMisalign:%X ReadBlkMisalign:%X\n", CSD->ReadBlockLength, CSD->ReadBlockPartial, CSD->WriteBlockMisalign, CSD->ReadBlockMisalign);
++ P_DEBUG(" DSP:%X BlockNumber:%d MemorySize:%d \n", CSD->DSRImplemant, CSD->BlockNumber, CSD->MemorySize);
++ P_DEBUG(" VDD_R_MIN:%d/10mA VDD_R_MAX:%dmA\n", (uint) CSD->VDDReadMin_u, (uint) CSD->VDDReadMax_u);
++ P_DEBUG(" VDD_W_MIN:%d/10mA VDD_W_MAX:%dmA\n", (uint) CSD->VDDWriteMin_u, (uint) CSD->VDDWriteMax_u);
++ P_DEBUG(" EraseBlkEnable:%d EraseSectorSize:%d WpGrpSize:%d WpGrpEnable:%X\n", CSD->EraseBlkEnable, CSD->EraseSectorSize, CSD->WriteProtectGroupSize, CSD->WriteProtectGroupEnable);
++ P_DEBUG(" WriteSpeedFactor:%d WriteBlLen:%d WriteBlPartial:%X\n", CSD->WriteSpeedFactor, CSD->WriteBlockLength, CSD->WriteBlockPartial);
++ P_DEBUG(" Copy:%X PermWrProtect:%X TmpWrProtect:%X FileFormat:%X\n", CSD->CopyFlag, CSD->PermanentWriteProtect, CSD->TemporaryWriteProtect, CSD->FileFormat);
++ P_DEBUG(" ReadTimoutCycle:0x%08X WriteTimoutCycle:0x%08X\n", sd_card_info.ReadAccessTimoutCycle, sd_card_info.WriteAccessTimoutCycle);
++ /* print SCR register */
++ P_DEBUG("SCR>> 0x%08X 0x%08X \n", *(((uint *) &sd_card_info.SCR)), *(((uint *) &sd_card_info.SCR) + 1));
++ P_DEBUG(" SCR_STRUCTURE:%d, SD_SPEC:%d, Data_status_after_erase:%d\n", sd_card_info.SCR.SCR_STRUCTURE, sd_card_info.SCR.SD_SPEC, sd_card_info.SCR.DATA_STAT_AFTER_ERASE);
++ P_DEBUG(" sd_security:%d, SD_BUS_WIDTH:%X\n", sd_card_info.SCR.SD_SECURITY, sd_card_info.SCR.SD_BUS_WIDTH);
++
++ return TRUE;
++}
++#endif
++
++static int sd_card_setup(struct sd_dev *dev)
++{
++ uint sd_card_size;
++ int i;
++
++ P_DEBUG("--> %s\n", __func__);
++ first_run = 0;
++ sd_err_code = ERR_NO_ERROR;
++
++ sd_card_info.ActiveState = FALSE;
++ sd_card_info.WriteProtect = FALSE;
++ sd_card_info.IOAddr = FTSDC_VA_BASE;
++ sd_card_info.DMAEnable = FALSE;
++
++ sd_card_info.SysFrequency = AHB_CLK_IN/2;
++ P_DEBUG("DMA Enable is %d, Sys frequency = %d\n", sd_card_info.DMAEnable, sd_card_info.SysFrequency);
++ sd_card_info.RCA = 0;
++ sd_card_info.Drive = 'S';
++
++ if (!sd_card_insert(&sd_card_info))
++ return FALSE;
++#ifdef SD_DEBUG
++ if (!sd_dev_info())
++ return FALSE;
++#endif
++ sd_card_size = sd_card_info.CSD.MemorySize;
++ printk(KERN_NOTICE "FTSDC010: SD Card Capacity=%d MB\n", sd_card_size/1000000); /* Marketing MB is not 1048576 */
++
++ for (i = 0; i < SD_DEVS; i++) {
++ sd_devices[i].size = sd_card_size / SD_SECTOR_SIZE; //unit is block, not bytes
++
++#if 0
++ sd_partitions[i << SD_SHIFT].nr_sects =sd_size * (SD_BLKSIZE / SD_SECTOR_SIZE);
++ P_DEBUG ("%s() %d-th device, size=%d blks(blks=%d),nr_sects=%ld\n", __func__, i, sd_size, SD_BLKSIZE, sd_partitions[i << SD_SHIFT].nr_sects);
++#endif
++ //sd_devices[i].card_state = SD_CARD_WORK;
++ //sema_init(&(sd_devices[i].sema), 1); // add by Charles Tsai*/
++ }
++
++ sd_card_info.DMAEnable = dev->dma_enable;
++
++ P_DEBUG("<-- %s\n", __func__);
++ return TRUE;
++}
++
++/*
++ * Driver stuff
++ */
++/*------------------------------------
++ * The ioctl implementation
++ */
++int sd_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd, unsigned long arg)
++{
++ int size;
++ struct hd_geometry geo;
++ struct sd_dev *device=bdev->bd_disk->private_data;
++ P_DEBUG ("ioctl 0x%x 0x%lx\n", cmd, arg);
++ switch (cmd) {
++ case BLKGETSIZE:
++ /* Return the device size, expressed in sectors */
++ /* FIXME: distinguish between kernel sector size and media sector size */
++ size = device->size;
++ __copy_to_user ((long *) arg, &size, sizeof (long));
++ return 0;
++#if 0
++ case BLKFLSBUF: /* flush */
++ return blk_ioctl(inode->i_rdev, cmd, arg);
++ case BLKRAGET: /* return the readahead value */
++ return blk_ioctl(inode->i_rdev, cmd, arg);
++ case BLKRASET: /* set the readahead value */
++ if (!capable (CAP_SYS_RAWIO))
++ return -EACCES;
++ if (arg > 0xff)
++ return -EINVAL; /* limit it */
++ return 0;
++// case BLKRRPART: /* re-read partition table */
++// return sd_revalidate (inode->i_rdev);
++#endif
++ case HDIO_GETGEO:
++ /*
++ * get geometry: we have to fake one... trim the size to a
++ * multiple of 64 (32k): tell we have 16 sectors, 4 heads,
++ * whatever cylinders. Tell also that data starts at sector. 4.
++ */
++ geo.cylinders = (device->size/4)/8; /* ?? only for test */
++ geo.heads = 4;
++ geo.sectors = 8;
++ geo.start = 0;
++ __copy_to_user ((void *) arg, &geo, sizeof (geo));
++ return 0;
++ default:
++ /*
++ * For ioctls we don't understand, let the block layer handle them.
++ */
++ return -ENOTTY;//blk_ioctl (inode->i_rdev, cmd, arg);
++ }
++
++ return -ENOTTY; /* unknown command */
++}
++
++static void sd_request(struct request_queue *q)
++{
++ struct sd_dev *dev;
++ static int active;
++#ifndef A320_SD_USE_ASYNC_DMA
++ int ret;
++ struct request *req;
++#else
++ if(bh_busy)
++ return;
++#endif
++ if(active)
++ return;
++ active = 1;
++ P_DEBUG("--> %s\n", __func__);
++repeat:
++ /* Locate the device */
++ if((req=blk_fetch_request(q))==NULL) {
++ active = 0;
++ return;
++ }
++ dev = req->rq_disk->private_data;
++ if (!dev||dev->card_state == SD_CARD_REMOVE) {
++ if(!dev)
++ printk(KERN_NOTICE"SD: locating device error\n");
++ __blk_end_request_cur(req, -EIO);
++ goto repeat;
++ }
++#ifndef A320_SD_USE_ASYNC_DMA
++ sync_mode=1;
++ //spin_unlock_irq(&io_request_lock);
++ ret = sd_transfer(dev, req);
++ __blk_end_request(req, 0, ret << 9);
++ //spin_lock_irq(&io_request_lock);
++ goto repeat;
++
++#else
++ sync_mode=0; //Use new async DMA machanism
++ //printk("%s: set up initial DMA, from sector %d to buffer 0x%X\n", __func__, CURRENT->sector+sector_offset, CURRENT->buffer);
++ //sd_init_async_dma();
++ sd_clustered_bh(1);
++ //bh_busy=1;
++#endif
++ P_DEBUG("<-- %s\n", __func__);
++}
++
++#if 0
++/*-----------------------------------------
++ * Support for removable devices
++ */
++int sd_check_change(kdev_t i_rdev)
++{
++ int minor = DEVICE_NR(i_rdev);
++ struct sd_dev *dev = sd_devices + minor;
++
++ P_DEBUG("--> %s\n", __func__);
++ P_DEBUG("minor=%d\n", minor);
++ if (minor >= SD_DEVS) /* paranoid */
++ return 0;
++ P_DEBUG("check change for dev %d\n", minor);
++ if (dev->usage) {
++ P_DEBUG("disk not change\n");
++ P_DEBUG("<-- %s\n", __func__);
++ return 0; /* still valid */
++ }
++ P_DEBUG("disk changed\n");
++ P_DEBUG("<-- %s\n", __func__);
++ return 1; /* expired */
++}
++#endif
++
++static int sd_dma_ch_alloc(struct sd_dev *dev)
++{
++ dmad_chreq *ch_req = &dev->ch_req;
++
++ memset(ch_req, 0, sizeof(dmad_chreq));
++
++#ifdef CONFIG_PLATFORM_APBDMA
++
++ ch_req->apb_req.addr0_ctrl = APBBR_ADDRINC_FIXED; /* (in) APBBR_ADDRINC_xxx */
++/* for amerald */
++ if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID){
++ ch_req->apb_req.addr0_reqn = APBBR_REQN_SDC_AMERALD;
++ }else
++ ch_req->apb_req.addr0_reqn = APBBR_REQN_SDC; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
++ ch_req->apb_req.addr1_ctrl = APBBR_ADDRINC_I4X; /* (in) APBBR_ADDRINC_xxx */
++ ch_req->apb_req.addr1_reqn = APBBR_REQN_NONE; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
++ ch_req->apb_req.burst_mode = 1; /* (in) Burst mode (0: no burst 1-, 1: burst 4- data cycles per dma cycle) */
++ ch_req->apb_req.data_width = APBBR_DATAWIDTH_4; /* (in) APBBR_DATAWIDTH_4(word), APBBR_DATAWIDTH_2(half-word), APBBR_DATAWIDTH_1(byte) */
++ ch_req->apb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
++
++ ch_req->controller = DMAD_DMAC_APB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
++ ch_req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
++
++ if (dmad_channel_alloc(ch_req) != 0) {
++ memset(ch_req, 0, sizeof(dmad_chreq));
++ printk(KERN_INFO "%s: APB dma channel allocation failed\n", __func__);
++ goto _try_ahb;
++ }
++
++ P_DEBUG("%s: APB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
++ //printk("%s: APB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
++
++ return 0;
++
++_try_ahb:
++
++#endif /* CONFIG_PLATFORM_APBDMA */
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++
++ ch_req->ahb_req.sync = 1; /* (in) non-zero if src and dst have different clock domain */
++ ch_req->ahb_req.priority = DMAC_CSR_CHPRI_1; /* (in) DMAC_CSR_CHPRI_0 (lowest) ~ DMAC_CSR_CHPRI_3 (highest) */
++ ch_req->ahb_req.hw_handshake = 1; /* (in) non-zero to enable hardware handshake mode */
++ ch_req->ahb_req.burst_size = DMAC_CSR_SIZE_4; /* (in) DMAC_CSR_SIZE_1 ~ DMAC_CSR_SIZE_256 */
++ ch_req->ahb_req.addr0_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
++ ch_req->ahb_req.addr0_ctrl = DMAC_CSR_AD_FIX; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
++ ch_req->ahb_req.addr0_reqn = DMAC_REQN_SDC; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
++ ch_req->ahb_req.addr1_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
++ ch_req->ahb_req.addr1_ctrl = DMAC_CSR_AD_INC; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
++ ch_req->ahb_req.addr1_reqn = DMAC_REQN_NONE; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
++ ch_req->ahb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
++
++ ch_req->controller = DMAD_DMAC_AHB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
++ ch_req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
++
++ if (dmad_channel_alloc(ch_req) != 0) {
++ memset(ch_req, 0, sizeof(dmad_chreq));
++ printk(KERN_INFO "%s: AHB dma channel allocation failed\n", __func__);
++ goto _err_exit;
++ }
++
++ P_DEBUG("%s: AHB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
++ //printk("%s: AHB dma channel allocated (ch: %d)\n", __func__, ch_req->channel);
++
++ return 0;
++
++_err_exit:
++
++#endif /* CONFIG_PLATFORM_AHBDMA */
++
++ return -ENODEV;
++}
++
++/*--------------------------------
++ * Note no locks taken out here. In a worst case scenario, we could drop
++ * a chunk of system memory. But that should never happen, since validation
++ * happens at open or mount time, when locks are held.
++ */
++static int sd_revalidate(struct gendisk *gd)
++{
++ struct sd_dev *dev = gd->private_data;
++
++ P_DEBUG("--> %s\n", __func__);
++ P_DEBUG("card state=%s\n", dev->card_state == SD_CARD_INSERT ? "INSERT" : dev->card_state == SD_CARD_WORK ? "WORK" : "REMOVE");
++
++ if (dev->usage == 0) {
++ if (sd_card_setup(dev) != TRUE) {
++ dev->card_state = SD_CARD_REMOVE;
++ return -1;
++ } else {
++ enable_irq(FTSDC_IRQ);
++ dev->card_state = SD_CARD_WORK;
++ }
++ }
++ P_DEBUG("<-- %s\n", __func__);
++
++ return 0;
++}
++
++/*
++ * Device open and close
++ * TODO: forbids open for write when WRITE_PROTECT=1
++ */
++int sd_open(struct block_device *bdev, fmode_t mode)
++{
++ struct sd_dev *dev= bdev->bd_disk->private_data; /* device information */
++ P_DEBUG("--> %s\n", __func__);
++ /* Early return if there's nothing in the card slot */
++ if ((SDC_R_REG(SDC_STATUS_REG) & SDC_STATUS_REG_CARD_INSERT) != SDC_CARD_INSERT) {
++ P_DEBUG("<-- %s (ENOMEDIUM)\n", __func__);
++ return -ENOMEDIUM;
++ }
++ //spin_lock(&dev->lock);
++ if (!dev->usage) {
++ dev->media_change=1;
++ P_DEBUG("%s: forced check_disk_change check\n", __func__);
++ check_disk_change(bdev);
++ sector_offset=0;
++ Do_onetime=0;
++ } else
++ dev->media_change=0;
++
++ /* Set size HERE:
++ * must rely on sd_revalidate to set correct size
++ * (seems on check_disk_change()) */
++ P_DEBUG("%s: set_capacity() to %d blocks (%d bytes)\n",__func__, dev->size, dev->size*SD_SECTOR_SIZE);
++ set_capacity(dev->gd, dev->size);
++ dev->usage++;
++ P_DEBUG("<-- %s\n", __func__);
++
++ return 0; /* success */
++}
++
++int sd_release(struct gendisk *gd, fmode_t mode)
++{
++ struct sd_dev *dev = gd->private_data;
++
++ disable_irq(FTSDC_IRQ);
++ printk(" + sd_release : umount SD\n");
++
++ P_DEBUG("--> %s\n", __func__);
++ dev->usage--;
++ P_DEBUG("<-- %s\n", __func__);
++
++ return 0;
++}
++
++/*--------------------------------------
++ * The file operations
++ */
++struct block_device_operations sd_fops = {
++ owner: THIS_MODULE,
++ open: sd_open,
++ release: sd_release,
++ ioctl: sd_ioctl,
++ revalidate_disk: sd_revalidate,
++ media_changed: sd_media_changed,
++};
++
++void init_sd_pmu(void)
++{
++
++#ifdef CONFIG_FIE8100_PLATFORM
++ unsigned int u32temp;
++ u32temp = *(volatile unsigned int *)(A320_PMU_VA_BASE + 0x14);
++ u32temp &= ~0x3000;
++ u32temp |= 0x2000;
++ *(volatile unsigned int *)(A320_PMU_VA_BASE + 0x14)=u32temp;
++#endif
++
++#ifdef CONFIG_FIE7000_PLATFORM
++ *(volatile unsigned int *)(A320_PMU_VA_BASE + 0x114) = (*(volatile unsigned int *)(A320_PMU_VA_BASE + 0x114) & 0xFFFF0FFF) | 0x00002000;
++#endif
++}
++
++/*
++ * Set up our internal device.
++ */
++static int setup_device(struct sd_dev *dev)
++{
++ /*
++ * Get some memory.
++ */
++ memset (dev, 0, sizeof (struct sd_dev));
++ dev->size = 0;//SD_DUMMY_SIZE/SD_SECTOR_SIZE; /* We'll fill this with correct size later*/
++ spin_lock_init(&dev->lock);
++ /* Request Queue */
++ dev->queue = blk_init_queue(sd_request, &dev->lock);
++ if (dev->queue == NULL)
++ return -EFAULT;
++
++ blk_queue_logical_block_size(dev->queue, hardsect_size);
++ dev->queue->queuedata = dev;
++
++ dev->card_state = SD_CARD_REMOVE;
++
++ /*
++ * And the gendisk structure.
++ */
++ dev->gd = alloc_disk(SD_MINORS);
++ if (! dev->gd) {
++ printk (KERN_NOTICE "alloc_disk failure\n");
++ return -EFAULT;
++ }
++
++ dev->gd->flags = GENHD_FL_REMOVABLE|GENHD_FL_SUPPRESS_PARTITION_INFO;
++ dev->gd->major = sd_major;
++ dev->gd->first_minor = 0;
++ dev->gd->minors = SD_MINORS;
++ dev->gd->fops = &sd_fops;
++ dev->gd->queue = dev->queue;
++ dev->gd->private_data = dev;
++ snprintf (dev->gd->disk_name, 32, "cpesd%c", 'a');
++ set_capacity(dev->gd, 0); //SD_DUMMY_SIZE/SD_SECTOR_SIZE*(hardsect_size/KERNEL_SECTOR_SIZE));
++ add_disk(dev->gd);
++
++ /*
++ * dma alloc
++ */
++ if (sd_dma_ch_alloc(dev) == 0) {
++ printk(KERN_NOTICE "Faraday SD controller Driver (DMA mode)\n");
++ dev->dma_enable = true;
++ } else {
++ printk(KERN_NOTICE "Faraday SD controller Driver (PIO mode)\n");
++ }
++
++ return 0;
++}
++/*
++ * Look for a media change.
++ */
++static int sd_media_changed(struct gendisk *gd)
++{
++ struct sd_dev *dev = gd->private_data;
++ return dev->media_change;
++}
++
++/*
++ * module stuff
++ */
++static int __init sd_module_init(void)
++{
++ int result=-ENOMEM;
++ spinlock_t complete_lock;
++ unsigned long iflags;
++ spin_lock_init(&complete_lock);
++
++#ifdef CONFIG_PLAT_QEMU
++ SDC_READ_FIFO_LEN = SDC_WRITE_FIFO_LEN = SDC_R_REG(0x44) & 0xff;
++#else
++ if(SDC_R_REG(0xa0) == 0x00030101)
++ SDC_READ_FIFO_LEN = SDC_WRITE_FIFO_LEN = SDC_R_REG(0x9c) & 0xff;
++ else
++ SDC_READ_FIFO_LEN = SDC_WRITE_FIFO_LEN = SDC_R_REG(SDC_FEATURE_REG) & 0xff;
++#endif
++ /* Register SD driver */
++ sd_major = register_blkdev(sd_major, DEVICE_NAME);
++ if (sd_major <= 0) {
++ printk(KERN_WARNING DEVICE_NAME ":unable to get major number\n");
++ return -EBUSY;
++ }
++ init_sd_pmu(); /* Power on SDC */
++ P_DEBUG("SD Major Number = %d\n", sd_major);
++ printk(KERN_ALERT "SD: make node with 'mknod /dev/cpesd b %d 0'\n", sd_major);
++
++ sd_devices = kmalloc(sizeof(struct sd_dev), GFP_KERNEL);
++ if (!sd_devices)
++ goto fail_malloc;
++ memset(sd_devices, 0, sizeof(struct sd_dev));
++
++ if (setup_device(sd_devices))
++ goto fail_malloc;
++
++ P_DEBUG("Request SDC IRQ=%d\n", FTSDC_IRQ);
++ spin_lock_irqsave(&complete_lock, iflags);
++ if (request_irq(FTSDC_IRQ, sd_hotswap_interrupt_handler, IRQF_DISABLED, "SD controller", sd_devices) != 0) {
++ printk(KERN_ERR "Unable to allocate SDC IRQ=0x%X\n", FTSDC_IRQ);
++ goto fail_malloc;
++ }
++ disable_irq(FTSDC_IRQ);
++ spin_unlock_irqrestore(&complete_lock, iflags);
++ if (request_region(FTSDC_VA_BASE, 0x48, "SD Controller") == NULL) {
++ printk(KERN_ERR "request io port of sd controller fail\n");
++ goto fail_mem;
++ }
++
++ return 0; /* succeed */
++
++fail_mem:
++ free_irq(FTSDC_IRQ, sd_devices);
++
++fail_malloc:
++ if (sd_devices)
++ kfree(sd_devices);
++ unregister_blkdev(sd_major, DEVICE_NAME);
++ return result;
++}
++
++static void sd_module_cleanup(void)
++{
++ P_DEBUG("--> %s\n", __func__);
++
++ /* unregister the device now to avoid further operations during cleanup */
++
++ if (sd_devices) {
++ del_gendisk(sd_devices->gd);
++ put_disk(sd_devices->gd);
++ if(sd_devices->queue)
++ blk_cleanup_queue(sd_devices->queue);
++
++ if (sd_devices->dma_enable)
++ dmad_channel_free(&sd_devices->ch_req);
++
++ kfree(sd_devices);
++ }
++
++ release_region(FTSDC_VA_BASE, 0x48);
++ free_irq(FTSDC_IRQ, sd_devices);
++
++ unregister_blkdev(sd_major, DEVICE_NAME);
++ P_DEBUG("<-- %s\n", __func__);
++}
++
++module_init(sd_module_init);
++module_exit(sd_module_cleanup);
+diff -Nur linux-3.4.110.orig/drivers/block/ftsdc010.h linux-3.4.110/drivers/block/ftsdc010.h
+--- linux-3.4.110.orig/drivers/block/ftsdc010.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/block/ftsdc010.h 2016-04-07 10:20:51.022084119 +0200
+@@ -0,0 +1,477 @@
++/* drivers/block/CPESD/ftsdc010.h
++ *
++ * Faraday FTSDC010 Device Driver
++ *
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ *
++ * All Rights Reserved
++ */
++
++#ifndef _FTSDC010_H_
++#define _FTSDC010_H_
++
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++//#define SD_DEBUG
++#define DELAY_FOR_DMA_READ
++
++#ifdef SD_DEBUG
++ #define P_DEBUG(fmt, args...) printk(KERN_ALERT "SD: " fmt, ## args)
++#else
++ #define P_DEBUG(a...)
++#endif
++#define P_DEBUGG(a...)
++
++#define MAX_READ_SECTOR_NR 96 //16
++#define MAX_WRITE_SECTOR_NR MAX_READ_SECTOR_NR
++
++#define SD_MAJOR 6 /* default major number, if zero, it means dynamic allocate */
++#define SD_DEVS 1 /* number of disks */
++#define SD_MINORS 16 /* minors per disk */
++#define SD_RAHEAD 2 /* number of sectors */
++#define SD_BLKSIZE 1024 /* block size */
++#define SD_SECTOR_SIZE 512 /* sector size */
++#define SD_DUMMY_SIZE (256*1024*1024) // for sake of hotswap/hotplug
++#if 0
++typedef struct _sd_dev_t {
++ int size;
++ int usage;
++ //struct timer_list timer;
++ spinlock_t lock;
++ struct semaphore sema; // synchronization
++ int card_state;
++} sd_dev_t;
++#endif
++//---------SD Card State
++#define SD_CARD_REMOVE 0
++#define SD_CARD_INSERT 1
++#define SD_CARD_WORK 2
++
++/* so far, SD controller support 3.2-3.3 VDD */
++#define SDC_OCR 0x00FF8000
++
++/* sd controller register */
++#define SDC_CMD_REG 0x00000000
++#define SDC_ARGU_REG 0x00000004
++#define SDC_RESPONSE0_REG 0x00000008
++#define SDC_RESPONSE1_REG 0x0000000C
++#define SDC_RESPONSE2_REG 0x00000010
++#define SDC_RESPONSE3_REG 0x00000014
++#define SDC_RSP_CMD_REG 0x00000018
++#define SDC_DATA_CTRL_REG 0x0000001C
++#define SDC_DATA_TIMER_REG 0x00000020
++#define SDC_DATA_LEN_REG 0x00000024
++#define SDC_STATUS_REG 0x00000028
++#define SDC_CLEAR_REG 0x0000002C
++#define SDC_INT_MASK_REG 0x00000030
++#define SDC_POWER_CTRL_REG 0x00000034
++#define SDC_CLOCK_CTRL_REG 0x00000038
++#define SDC_BUS_WIDTH_REG 0x0000003C
++#define SDC_DATA_WINDOW_REG 0x00000040
++#ifdef A320D_BUILDIN_SDC
++#define SDC_FEATURE_REG 0x00000044
++#define SDC_REVISION_REG 0x00000048
++#else
++#define SDC_MMC_INT_RSP_REG 0x00000044
++#define SDC_GP_OUTPUT_REG 0x00000048
++#define SDC_FEATURE_REG 0x0000009C
++#define SDC_REVISION_REG 0x000000A0
++#endif
++
++/* bit mapping of command register */
++#define SDC_CMD_REG_INDEX 0x0000003F
++#define SDC_CMD_REG_NEED_RSP 0x00000040
++#define SDC_CMD_REG_LONG_RSP 0x00000080
++#define SDC_CMD_REG_APP_CMD 0x00000100
++#define SDC_CMD_REG_CMD_EN 0x00000200
++#define SDC_CMD_REG_SDC_RST 0x00000400
++
++/* bit mapping of response command register */
++#define SDC_RSP_CMD_REG_INDEX 0x0000003F
++#define SDC_RSP_CMD_REG_APP 0x00000040
++
++/* bit mapping of data control register */
++#define SDC_DATA_CTRL_REG_BLK_SIZE 0x0000000F
++#define SDC_DATA_CTRL_REG_DATA_WRITE 0x00000010
++#define SDC_DATA_CTRL_REG_DATA_READ 0x00000000
++#define SDC_DATA_CTRL_REG_DMA_EN 0x00000020
++#define SDC_DATA_CTRL_REG_DATA_EN 0x00000040
++
++#define SDC_DMA_TYPE_1 0x00000000
++#define SDC_DMA_TYPE_4 0x00000100
++#define SDC_DMA_TYPE_8 0x00000200
++
++/* bit mapping of status/clear/mask register */
++#define SDC_STATUS_REG_RSP_CRC_FAIL 0x00000001
++#define SDC_STATUS_REG_DATA_CRC_FAIL 0x00000002
++#define SDC_STATUS_REG_RSP_TIMEOUT 0x00000004
++#define SDC_STATUS_REG_DATA_TIMEOUT 0x00000008
++#define SDC_STATUS_REG_RSP_CRC_OK 0x00000010
++#define SDC_STATUS_REG_DATA_CRC_OK 0x00000020
++#define SDC_STATUS_REG_CMD_SEND 0x00000040
++#define SDC_STATUS_REG_DATA_END 0x00000080
++#define SDC_STATUS_REG_FIFO_UNDERRUN 0x00000100
++#define SDC_STATUS_REG_FIFO_OVERRUN 0x00000200
++#define SDC_STATUS_REG_CARD_CHANGE 0x00000400
++#define SDC_STATUS_REG_CARD_INSERT 0x00000800
++#define SDC_STATUS_REG_CARD_LOCK 0x00001000
++
++#define SDC_CARD_INSERT 0x0
++#define SDC_CARD_REMOVE SDC_STATUS_REG_CARD_INSERT
++
++/* bit mapping of power control register */
++#define SDC_POWER_REG_POWER_ON 0x00000010
++#define SDC_POWER_REG_POWER_BITS 0x0000000F
++
++/* bit mapping of clock control register */
++#define SDC_CLOCK_REG_CARD_TYPE 0x00000080
++#define SDC_CLOCK_REG_CLK_DIV 0x0000007F
++
++/* card type */
++#define SDC_CARD_TYPE_SD SDC_CLOCK_REG_CARD_TYPE
++#define SDC_CARD_TYPE_MMC 0x0
++
++/* bit mapping of bus width register */
++#define SDC_BUS_WIDTH_REG_SINGLE_BUS 0x00000001
++#define SDC_BUS_WIDTH_REG_WIDE_BUS 0x00000004
++#define SDC_WIDE_BUS_SUPPORT 0x00000008
++
++/* data window register */
++//#define SDC_READ_FIFO_LEN 4
++//#define SDC_WRITE_FIFO_LEN 4
++
++/* card type, sd or mmc */
++#define MEMORY_CARD_TYPE_SD 0
++#define MEMORY_CARD_TYPE_MMC 1
++
++/********************************************************************/
++/* SYSTEM ERROR_CODE */
++/********************************************************************/
++#define ERR_NO_ERROR 0x00000000
++
++/* general error */
++#define ERR_CARD_NOT_EXIST 0x00000001
++#define ERR_OUT_OF_VOLF_RANGE 0x00000002
++#define ERR_SD_PARTITIAL_READ_ERROR 0x00000004
++#define ERR_SD_PARTITIAL_WRITE_ERROR 0x00000008
++
++#define ERR_SD_CARD_IS_LOCK 0x00000010
++
++/* command error */
++#define ERR_DATA_CRC_ERROR 0x00000100
++#define ERR_RSP_CRC_ERROR 0x00000200
++#define ERR_DATA_TIMEOUT_ERROR 0x00000400
++#define ERR_RSP_TIMEOUT_ERROR 0x00000800
++
++#define ERR_WAIT_OVERRUN_TIMEOUT 0x00001000
++#define ERR_WAIT_UNDERRUN_TIMEOUT 0x00002000
++#define ERR_WAIT_DATA_CRC_TIMEOUT 0x00004000
++#define ERR_WAIT_TRANSFER_END_TIMEOUT 0x00008000
++
++#define ERR_SEND_COMMAND_TIMEOUT 0x00010000
++
++/* sd error */
++#define ERR_SD_CARD_IS_BUSY 0x00100000
++#define ERR_CID_REGISTER_ERROR 0x00200000
++#define ERR_CSD_REGISTER_ERROR 0x00400000
++
++/* sd card status error */
++#define ERR_SD_CARD_STATUS_ERROR 0x01000000
++/* SDC using APB DMA error */
++#define ERR_DMA_RSP_ERROR 0x02000000
++
++#define SD_SCR_1_BIT_BIT 0x0001
++#define SD_SCR_4_BIT_BIT 0x0004
++
++/********************************************************************/
++/* The bit mapping of SD Status register */
++/********************************************************************/
++#define SD_STATUS_OUT_OF_RANGE 0x80000000
++#define SD_STATUS_ADDRESS_ERROR 0x40000000
++#define SD_STATUS_BLOCK_LEN_ERROR 0x20000000
++#define SD_STATUS_ERASE_SEQ_ERROR 0x10000000
++#define SD_STATUS_ERASE_PARAM 0x08000000
++#define SD_STATUS_WP_VIOLATION 0x04000000
++#define SD_STATUS_CARD_IS_LOCK 0x02000000
++#define SD_STATUS_LOCK_UNLOCK_FILED 0x01000000
++#define SD_STATUS_COM_CRC_ERROR 0x00800000
++#define SD_STATUS_ILLEGAL_COMMAND 0x00400000
++#define SD_STATUS_CARD_ECC_FAILED 0x00200000
++#define SD_STATUS_CC_ERROR 0x00100000
++#define SD_STATUS_ERROR 0x00080000
++#define SD_STATUS_UNDERRUN 0x00040000
++#define SD_STATUS_OVERRUN 0x00020000
++#define SD_STATUS_CID_CSD_OVERWRITE 0x00010000
++#define SD_STATUS_WP_ERASE_SKIP 0x00008000
++#define SD_STATUS_CARD_ECC_DISABLE 0x00004000
++#define SD_STATUS_ERASE_RESET 0x00002000
++#define SD_STATUS_CURRENT_STATE 0x00001E00
++#define SD_STATUS_READY_FOR_DATA 0x00000100
++#define SD_STATUS_APP_CMD 0x00000020
++#define SD_STATUS_AKE_SEQ_ERROR 0x00000008
++#define SD_STATUS_ERROR_BITS (SD_STATUS_ADDRESS_ERROR | SD_STATUS_BLOCK_LEN_ERROR | SD_STATUS_ERASE_SEQ_ERROR | SD_STATUS_ERASE_PARAM | SD_STATUS_WP_VIOLATION | SD_STATUS_LOCK_UNLOCK_FILED | SD_STATUS_CARD_ECC_FAILED | SD_STATUS_CC_ERROR | SD_STATUS_ERROR | SD_STATUS_UNDERRUN | SD_STATUS_OVERRUN | SD_STATUS_CID_CSD_OVERWRITE | SD_STATUS_WP_ERASE_SKIP | SD_STATUS_AKE_SEQ_ERROR)
++#define SD_STATUS_CURRENT_STATE_LOC 9
++
++/********************************************************************/
++/* SD command response type */
++/********************************************************************/
++#define SD_NO_RESPONSE 0
++#define SD_RESPONSE_R1 1
++#define SD_RESPONSE_R1b 2
++#define SD_RESPONSE_R2 3
++#define SD_RESPONSE_R3 4
++#define SD_RESPONSE_R6 5
++
++/********************************************************************/
++/* SD command */
++/********************************************************************/
++#define SD_GO_IDLE_STATE_CMD 0
++#define SD_MMC_OP_COND 1
++#define SD_ALL_SEND_CID_CMD 2
++#define SD_SEND_RELATIVE_ADDR_CMD 3
++#define SD_SET_DSR_CMD 4
++#define SD_SET_BUS_WIDTH_CMD 6
++#define SD_SELECT_CARD_CMD 7
++#define SD_SEND_CSD_CMD 9
++#define SD_SEND_CID_CMD 10
++#define SD_STOP_TRANSMISSION_CMD 12
++#define SD_SEND_STATUS_CMD 13
++#define SD_GO_INACTIVE_STATE_CMD 15
++#define SD_SET_BLOCKLEN_CMD 16
++#define SD_READ_SINGLE_BLOCK_CMD 17
++#define SD_READ_MULTIPLE_BLOCK_CMD 18
++#define SD_WRITE_SINGLE_BLOCK_CMD 24
++#define SD_WRITE_MULTIPLE_BLOCK_CMD 25
++#define SD_PROGRAM_CSD_CMD 27
++#define SD_ERASE_SECTOR_START_CMD 32
++#define SD_ERASE_SECTOR_END_CMD 33
++#define SD_ERASE_CMD 38
++#define SD_APP_OP_COND 41
++#define SD_LOCK_UNLOCK_CMD 42
++#define SD_SEND_SCR_CMD 51
++#define SD_APP_CMD 55
++#define SD_GET_CMD 56
++
++/* retry count */
++#ifndef CONFIG_FTSDC010_USE_TIMER_DELAY
++#define SD_CARD_GET_OCR_RETRY_COUNT 0x1000
++#define SD_CARD_WAIT_OPERATION_COMPLETE_RETRY_COUNT 8000
++#define SD_CARD_STATE_CHANGE_RETRY_COUNT 30000
++#define SD_CARD_WAIT_TRANSFER_STATE_RETRY_COUNT 30000
++#define SDC_GET_STATUS_RETRY_COUNT 0x300000
++#else
++#define SD_CARD_GET_OCR_RETRY_COUNT 0x1000
++#define SD_CARD_WAIT_OPERATION_COMPLETE_RETRY_COUNT 8000
++#define SD_CARD_STATE_CHANGE_RETRY_COUNT 10000
++#define SD_CARD_WAIT_TRANSFER_STATE_RETRY_COUNT 10000
++#endif
++
++/*
++ * Please refer SanDisk SD Manual v1.9 Section 5.1.9.2 (page 5-76) to set the timeout setting
++ */
++#ifdef SD_DEBUG
++#define SDC_TIMEOUT_BASE (HZ/2) // Unit is 500 ms
++#else
++#define SDC_TIMEOUT_BASE (HZ/3) // Unit is 333 ms
++#endif
++#define SDC_GET_STATUS_RETRY_TIMEOUT_COUNT (HZ*4)
++
++/* sd card standby state */
++#define SD_IDLE_STATE 0
++#define SD_READY_STATE 1
++#define SD_IDENT_STATE 2
++#define SD_STBY_STATE 3
++#define SD_TRAN_STATE 4
++#define SD_DATA_STATE 5
++#define SD_RCV_STATE 6
++#define SD_PRG_STATE 7
++#define SD_DIS_STATE 8
++
++#define SD_BUS_WIDTH_1_BIT 0
++#define SD_BUS_WIDTH_4_BIT 2
++
++/********************************************************************/
++/* SD card OCR register */
++/********************************************************************/
++#define SD_OCR_BUSY_BIT 0x80000000
++
++/********************************************************************/
++/* SD CID register */
++/********************************************************************/
++#define SD_DEFAULT_MONTH_CODE 1
++#define SD_DEFAULT_YEAR_CODE 2000
++#define MAX_MULTI_BLOCK_NUM 126
++
++typedef struct _sd_cid_t
++{
++ uint ManufacturerID;
++ uint ApplicationID;
++ unchar ProductName[7];
++ uint ProductRevisionHigh;
++ uint ProductRevisionLow;
++ uint ProductSerialNumber;
++ uint ManufactureMonth;
++ uint ManufactureYear;
++} sd_cid_t;
++
++/********************************************************************/
++/* SD CSD register */
++/********************************************************************/
++#define SD_CSD_STRUCTURE_1_0 0
++#define SD_CSD_STRUCTURE_1_1 1
++
++#define SD_CSD_SPEC_VERS_1_0_1_2 0
++#define SD_CSD_SPEC_VERS_1_4 1
++#define SD_CSD_SPEC_VERS_2_1 2
++
++#define SD_TAAC_TIME_UINT_BITS 0x07
++#define SD_TAAC_TIME_VALUE_BITS 0x78
++
++typedef struct _sd_csd_t
++{
++ uint CSDStructure;
++ uint MMCSpecVersion;
++ uint TAAC_u;
++ uint NSAC_u;
++ uint TransferSpeed;
++ uint CardCmdClass;
++ uint ReadBlockLength;
++ uint ReadBlockPartial;
++ uint WriteBlockMisalign;
++ uint ReadBlockMisalign;
++ uint DSRImplemant;
++ uint BlockNumber;
++ uint MemorySize;
++ uint VDDReadMin_u;
++ uint VDDReadMax_u;
++ uint VDDWriteMin_u;
++ uint VDDWriteMax_u;
++ uint EraseBlkEnable;
++ uint EraseSectorSize;
++ uint WriteProtectGroupSize;
++ uint WriteProtectGroupEnable;
++ uint WriteSpeedFactor;
++ uint WriteBlockLength;
++ unchar WriteBlockPartial;
++ unchar CopyFlag;
++ unchar PermanentWriteProtect;
++ unchar TemporaryWriteProtect;
++ unchar FileFormat;
++} sd_csd_t;
++
++typedef struct _sd_csd_bit_t
++{
++ uint NotUsed:1;
++ uint CRC:7;
++ uint MMCardReserved1:2;
++ uint FILE_FORMAT:2;
++ uint TMP_WRITE_PROTECT:1;
++ uint PERM_WRITE_PROTECT:1;
++ uint COPY:1;
++ uint FILE_FORMAT_GRP:1;
++
++ uint Reserved2:5;
++ uint WRITE_BL_PARTIAL:1;
++ uint WRITE_BL_LEN:4;
++ uint R2W_FACTOR:3;
++ uint MMCardReserved0:2;
++ uint WP_GRP_ENABLE:1;
++
++ uint WP_GRP_SIZE:7;
++ uint ERASE_SECTOR_SIZE:7;
++ uint ERASE_BLK_ENABLE:1;
++ uint C_SIZE_MULT:3;
++ uint VDD_W_CURR_MAX:3;
++ uint VDD_W_CURR_MIN:3;
++ uint VDD_R_CURR_MAX:3;
++ uint VDD_R_CURR_MIN:3;
++
++ uint C_SIZE_1:2;
++ uint C_SIZE_2:10; // divide its into 2, 10bits
++
++ uint Reserved1:2;
++ uint DSR_IMP:1;
++ uint READ_BLK_MISALIGN:1;
++ uint WRITE_BLK_MISALIGN:1;
++ uint READ_BL_PARTIAL:1;
++
++ uint READ_BL_LEN:4;
++ uint CCC:12;
++
++ uint TRAN_SPEED_RateUnit:3;
++ uint TRAN_SPEED_TimeValue:4;
++ uint TRAN_SPEED_Reserved:1;
++
++ uint NSAC:8;
++
++ uint TAAC_TimeUnit:3;
++ uint TAAC_TimeValue:4;
++ uint TAAC_Reserved:1;
++
++ uint Reserved0:2;
++ uint MMC_SPEC_VERS:4;
++ uint CSD_STRUCTURE:2;
++} sd_csd_bit_t;
++
++/********************************************************************/
++/* SD SCR register */
++/********************************************************************/
++typedef struct _sd_scr_t
++{
++ uint Reserved:16;
++ uint SD_BUS_WIDTH:4;
++ uint SD_SECURITY:3;
++ uint DATA_STAT_AFTER_ERASE:1;
++ uint SD_SPEC:4;
++ uint SCR_STRUCTURE:4;
++
++ uint ManufacturerReserved;
++} sd_scr_t;
++
++/********************************************************************/
++/* sd card structure */
++/********************************************************************/
++typedef struct _sd_card_t
++{
++ /* host interface configuration */
++ uint IOAddr; /* host controller register base address */
++ uint DMAEnable;
++
++ uint CardType;
++
++ /* card register */
++ uint OCR;
++
++ uint CIDWord[4];
++ sd_cid_t CID;
++
++ uint CSDWord[4];
++ sd_csd_t CSD;
++
++ ushort RCA;
++ sd_scr_t SCR;
++
++ /* access time out */
++ uint ReadAccessTimoutCycle;
++ uint WriteAccessTimoutCycle;
++
++ /* Drive Name */
++ uint Drive;
++
++ /* system configurations */
++ uint SysFrequency;
++
++ /* card status */
++ int ActiveState;
++ int WriteProtect;
++
++ void *private;
++} sd_card_t;
++
++#endif
+diff -Nur linux-3.4.110.orig/drivers/block/Kconfig linux-3.4.110/drivers/block/Kconfig
+--- linux-3.4.110.orig/drivers/block/Kconfig 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/block/Kconfig 2016-04-07 10:20:51.022084119 +0200
+@@ -498,6 +498,14 @@
+ block device driver. It communicates with a back-end driver
+ in another domain which drives the actual block device.
+
++config FTSDC010
++ tristate "Faraday FTSDC010 driver"
++ depends on NDS32
++
++config FTCFC010
++ tristate "Faraday FTCFC010 driver"
++ depends on NDS32
++
+ config XEN_BLKDEV_BACKEND
+ tristate "Xen block-device backend driver"
+ depends on XEN_BACKEND
+diff -Nur linux-3.4.110.orig/drivers/block/Makefile linux-3.4.110/drivers/block/Makefile
+--- linux-3.4.110.orig/drivers/block/Makefile 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/block/Makefile 2016-04-07 10:20:51.050085202 +0200
+@@ -43,3 +43,5 @@
+ obj-$(CONFIG_BLK_DEV_PCIESSD_MTIP32XX) += mtip32xx/
+
+ swim_mod-y := swim.o swim_asm.o
++obj-$(CONFIG_FTSDC010) += ftsdc010.o
++obj-$(CONFIG_FTCFC010) += ftcfc010.o
+diff -Nur linux-3.4.110.orig/drivers/gpio/gpio-ftgpio010.c linux-3.4.110/drivers/gpio/gpio-ftgpio010.c
+--- linux-3.4.110.orig/drivers/gpio/gpio-ftgpio010.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/gpio/gpio-ftgpio010.c 2016-04-07 10:20:51.050085202 +0200
+@@ -0,0 +1,218 @@
++#include <linux/module.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++#include <linux/gpio.h>
++
++#define GPIO_DATA_OUT 0x00
++#define GPIO_DATA_IN 0x04
++#define PIN_DIR 0x08
++#define PIN_BYPASS 0x0C
++#define GPIO_DATA_SET 0x10
++#define GPIO_DATA_CLEAR 0x14
++#define PIN_PULL_ENABLE 0x18
++#define PIN_PULL_TYPE 0x1C
++#define INT_ENABLE 0x20
++#define INT_RAW_STATE 0x24
++#define INT_MASKED_STATE 0x28
++#define INT_MASK 0x2C
++#define INT_CLEAR 0x30
++#define INT_TRIGGER 0x34
++#define INT_BOTH 0x38
++#define INT_RISE_NEG 0x3C
++#define BOUNCE_ENABLE 0x40
++#define BOUNCE_PRE_SCALE 0x44
++
++#define GPIO_READL(offset) \
++ readl(GPIO_FTGPIO010_VA_BASE + (offset))
++
++#define GPIO_WRITEL(val, offset) \
++ writel((val), GPIO_FTGPIO010_VA_BASE + (offset))
++
++#define FTGPIO010_VIRTUAL_IRQ_BASE 100
++
++static int irq_to_gpio(unsigned int irq)
++{
++ return irq - FTGPIO010_VIRTUAL_IRQ_BASE;
++}
++
++static int ftgpio_to_irq(struct gpio_chip *gc, unsigned int offset)
++{
++ return FTGPIO010_VIRTUAL_IRQ_BASE + offset;
++}
++
++static int ftgpio_get(struct gpio_chip *gc, unsigned int gpio)
++{
++ return (GPIO_READL(GPIO_DATA_IN) >> gpio & 1);
++}
++
++static void ftgpio_set(struct gpio_chip *gc, unsigned int gpio, int data)
++{
++ unsigned long val;
++
++ if (data)
++ val = GPIO_READL(GPIO_DATA_OUT) | (0x1UL << gpio);
++ else
++ val = GPIO_READL(GPIO_DATA_OUT) & ~(0x1UL << gpio);
++
++ GPIO_WRITEL(val, GPIO_DATA_OUT);
++}
++
++static int ftgpio_dir_in(struct gpio_chip *gc, unsigned int gpio)
++{
++ unsigned long val;
++
++ val = GPIO_READL(PIN_DIR) & ~(0x1UL << gpio);
++ GPIO_WRITEL(val, PIN_DIR);
++
++ return 0;
++}
++
++static int ftgpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int data)
++{
++ unsigned long val;
++
++ val = GPIO_READL(PIN_DIR) | (0x1UL << gpio);
++ GPIO_WRITEL(val, PIN_DIR);
++
++ gc->set(gc, gpio, data);
++
++ return 0;
++}
++
++static struct gpio_chip ftgpio_chip = {
++
++ .label = "FTGPIO010",
++ .base = 0,
++ .ngpio = 16,
++ .direction_input = ftgpio_dir_in,
++ .direction_output = ftgpio_dir_out,
++ .get = ftgpio_get,
++ .set = ftgpio_set,
++ .to_irq = ftgpio_to_irq,
++};
++
++static void ftgpio_irq_ack(struct irq_data *data)
++{
++ GPIO_WRITEL(0x1UL << irq_to_gpio(data->irq), INT_CLEAR);
++}
++
++static void ftgpio_irq_mask(struct irq_data *data)
++{
++ unsigned long val;
++
++ val = GPIO_READL(INT_MASK) | (0x1UL << irq_to_gpio(data->irq));
++ GPIO_WRITEL(val, INT_MASK);
++}
++
++static void ftgpio_irq_unmask(struct irq_data *data)
++{
++ unsigned long val;
++ val = GPIO_READL(INT_MASK) & ~(0x1UL << irq_to_gpio(data->irq));
++ GPIO_WRITEL(val, INT_MASK);
++}
++
++static int ftgpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
++{
++ unsigned long bit = 0x1UL << irq_to_gpio(data->irq);
++ unsigned long val;
++ val = GPIO_READL(INT_BOTH);
++
++ if (flow_type & IRQF_TRIGGER_RISING && flow_type & IRQF_TRIGGER_FALLING)
++ GPIO_WRITEL(val | bit, INT_BOTH);
++ else
++ GPIO_WRITEL(val & ~bit, INT_BOTH);
++
++ val = GPIO_READL(INT_RISE_NEG);
++
++ if (flow_type & IRQF_TRIGGER_FALLING)
++ GPIO_WRITEL(val | bit, INT_RISE_NEG);
++ else if (flow_type & IRQF_TRIGGER_RISING)
++ GPIO_WRITEL(val & ~bit, INT_RISE_NEG);
++
++ return 0;
++}
++
++static struct irq_chip ftgpio_irq_chip = {
++
++ .name = "FTGPIO010_irq",
++ .irq_ack = ftgpio_irq_ack,
++ .irq_mask = ftgpio_irq_mask,
++ .irq_unmask = ftgpio_irq_unmask,
++ .irq_set_type = ftgpio_irq_set_type,
++};
++
++static void gpio_irq_router(unsigned int irq, struct irq_desc *desc)
++{
++ unsigned long status;
++ int i = 0;
++
++ status = GPIO_READL(INT_RAW_STATE);
++ status &= ~((1 << 22) | (1 << 25) | (1 << 26));
++
++ while (status) {
++
++ if (status & 0x1UL)
++ generic_handle_irq(gpio_to_irq(i));
++
++ status >>= 1;
++ i++;
++ }
++}
++
++static int gpio_init(void)
++{
++ int i;
++
++ /* disable interrupt */
++ GPIO_WRITEL(0x00000000UL, INT_ENABLE);
++
++ /* mask interrupt */
++ GPIO_WRITEL(0x0000FFFFUL, INT_MASK);
++
++ /* triggered interrupt on both edge */
++ GPIO_WRITEL(0x0000FFFFUL, INT_BOTH);
++
++ /* clear interrupt */
++ GPIO_WRITEL(0x0000FFFFUL, INT_CLEAR);
++
++ /* enable de-bouncing */
++ GPIO_WRITEL(0x0000FFFFUL, BOUNCE_ENABLE);
++
++ /* enable interrupt */
++ GPIO_WRITEL(0x0000FFFFUL, INT_ENABLE);
++
++ gpiochip_add(&ftgpio_chip);
++
++ for (i = 0; i < ftgpio_chip.ngpio; i++) {
++
++ irq_set_chip(gpio_to_irq(i), &ftgpio_irq_chip);
++ irq_set_handler(gpio_to_irq(i), handle_level_irq);
++ }
++
++ irq_set_chained_handler(GPIO_FTGPIO010_IRQ, gpio_irq_router);
++
++ pr_info("GPIO module inserted\n");
++
++ return 0;
++}
++
++static void __exit gpio_exit(void)
++{
++ int i=0;
++ /* disable interrupt */
++ GPIO_WRITEL(0x00000000UL, INT_ENABLE);
++ while(i<ftgpio_chip.ngpio)
++ gpio_free(i++);
++
++ if (gpiochip_remove(&ftgpio_chip))
++ pr_info("failed to remove gpiochip\n");
++
++ pr_info("GPIO module removed\n");
++}
++
++MODULE_DESCRIPTION("FTGPIO010");
++MODULE_LICENSE("GPL");
++
++module_init(gpio_init);
++module_exit(gpio_exit);
+diff -Nur linux-3.4.110.orig/drivers/gpio/Kconfig linux-3.4.110/drivers/gpio/Kconfig
+--- linux-3.4.110.orig/drivers/gpio/Kconfig 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/gpio/Kconfig 2016-04-07 10:20:51.050085202 +0200
+@@ -492,6 +492,10 @@
+ This enables support for the Philips UCB1400 GPIO pins.
+ The UCB1400 is an AC97 audio codec.
+
++config GPIO_FTGPIO010
++ tristate "Farady FTGPIO010 GPIO support"
++ depends on NDS32 && GENERIC_GPIO && ARCH_WANT_OPTIONAL_GPIOLIB
++
+ comment "MODULbus GPIO expanders:"
+
+ config GPIO_JANZ_TTL
+diff -Nur linux-3.4.110.orig/drivers/gpio/Makefile linux-3.4.110/drivers/gpio/Makefile
+--- linux-3.4.110.orig/drivers/gpio/Makefile 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/gpio/Makefile 2016-04-07 10:20:51.050085202 +0200
+@@ -64,3 +64,4 @@
+ obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o
+ obj-$(CONFIG_GPIO_WM8994) += gpio-wm8994.o
+ obj-$(CONFIG_GPIO_XILINX) += gpio-xilinx.o
++obj-$(CONFIG_GPIO_FTGPIO010) += gpio-ftgpio010.o
+\ No newline at end of file
+diff -Nur linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/cpe_ts.c linux-3.4.110/drivers/input/touchscreen/cpe_ts/cpe_ts.c
+--- linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/cpe_ts.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/input/touchscreen/cpe_ts/cpe_ts.c 2016-04-07 10:20:51.050085202 +0200
+@@ -0,0 +1,376 @@
++#include <linux/input.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++#include <linux/io.h>
++
++#include <asm/irq.h>
++#include "cpe_ts.h"
++
++
++#include <linux/module.h>
++
++#include <linux/irqnr.h>
++#include <linux/irq.h>
++
++#define TOUCHSCREEN_IRQ 28
++
++#define ads_dbg( enabled, tagged, ...) \
++ do{ \
++ if( enabled){ \
++ if( tagged) \
++ printk( "[ %30s() ] ", __func__); \
++ printk( __VA_ARGS__); \
++ } \
++ } while( 0)
++
++#define TS_POLL_DELAY ( 1 * 1000000) /* ns delay before the first sample */
++#define TS_POLL_PERIOD ( delay * 1000000) /* ns delay between samples */
++
++static int debug = 0;
++static int delay = 25;
++
++module_param(debug, int, 0);
++module_param(delay, int, 0);
++
++struct ads7846
++{
++ void __iomem * regs;
++ struct input_dev *input;
++ char phys[32];
++ struct hrtimer timer;
++ int irq;
++ spinlock_t lock;
++ bool disabled;
++};
++
++struct ts_event
++{
++ int x;
++ int y;
++ int z1, z2;
++ int Rt;
++};
++
++struct ads7846 touchscreen;
++
++#define ADS_START ( 0x1UL << 7)
++#define ADS_A2A1A0_d_y ( 0x1UL << 4) /* differential */
++#define ADS_A2A1A0_d_z1 ( 0x3UL << 4) /* differential */
++#define ADS_A2A1A0_d_z2 ( 0x4UL << 4) /* differential */
++#define ADS_A2A1A0_d_x ( 0x5UL << 4) /* differential */
++#define ADS_12_BIT ( 0x0UL << 3)
++#define ADS_SER ( 0x1UL << 2) /* non-differential */
++#define ADS_DFR ( 0x0UL << 2) /* differential */
++#define ADS_PD10_PDOWN ( 0x0UL << 0) /* lowpower mode + penirq */
++#define ADS_PD10_ADC_ON ( 0x1UL << 0) /* ADC on */
++#define ADS_PD10_REF_ON ( 0x2UL << 0) /* vREF on + penirq */
++#define ADS_PD10_ALL_ON ( 0x3UL << 0) /* ADC + vREF on */
++
++#define MAX_12BIT ( ( 0x1UL << 12) - 1)
++
++#define READ_X ( ADS_A2A1A0_d_x | ADS_12_BIT | ADS_DFR)
++#define READ_Y ( ADS_A2A1A0_d_y | ADS_12_BIT | ADS_DFR)
++#define READ_Z1 ( ADS_A2A1A0_d_z1 | ADS_12_BIT | ADS_DFR)
++#define READ_Z2 ( ADS_A2A1A0_d_z2 | ADS_12_BIT | ADS_DFR)
++
++static int
++read_val(struct ads7846 *ts, unsigned long cmd)
++{
++ unsigned long data = 0;
++ int repeat = 5;
++ int i;
++
++ ads_dbg(0, 1, "Queuing data: 0x%08lx\n", cmd << 16);
++
++ for (i = 0; i < repeat; i++)
++ {
++ while (!(REG32(ts->regs + SSP_REG_SR) & SSP_SR_mskTFNF));
++ REG32(ts->regs + SSP_REG_DR) = (ADS_START | cmd | ADS_PD10_ALL_ON) << 16;
++ }
++
++ for (i = 0; i < repeat; i++)
++ {
++ while (!(REG32(ts->regs + SSP_REG_SR) & SSP_SR_mskRFVE));
++ data = (REG32(ts->regs + SSP_REG_DR) >> 3) & 0xFFF;
++ }
++
++ while (!(REG32(ts->regs + SSP_REG_SR) & SSP_SR_mskTFNF));
++ REG32(ts->regs + SSP_REG_DR) = (ADS_START | cmd) << 16;
++
++ while (!(REG32(ts->regs + SSP_REG_SR) & SSP_SR_mskRFVE));
++
++ data = (REG32(ts->regs + SSP_REG_DR) >> 3) & 0xFFF;
++ ads_dbg(0, 1, "CMD <%02lx> data: 0x%08lx( %ld)\n", cmd, data, data);
++
++ return data;
++}
++
++static int pendown(struct ads7846 *ts)
++{
++ return read_val(ts, READ_Z1) > 40;
++}
++
++static void report(struct ads7846 *ts, struct ts_event *e)
++{
++ e->x = read_val(ts, READ_X);
++ e->y = read_val(ts, READ_Y);
++ e->z1 = read_val(ts, READ_Z1);
++ e->z2 = read_val(ts, READ_Z2);
++
++ ads_dbg(debug, 1, "x: %4d, y: %4d, z1: %4d, z2: %4d\n", e->x, e->y, e->z1, e->z2);
++}
++
++#define FILTER_LIMIT 35
++
++static enum hrtimer_restart ads7846_timer(struct hrtimer *handle)
++{
++ struct ads7846 *ts = container_of(handle, struct ads7846, timer);
++ struct ts_event e;
++ struct irq_desc *desc = (struct irq_desc *)irq_get_irq_data((unsigned int)ts->irq);
++ static int xp = 0, yp = 0;
++
++ if (ts->disabled)
++ return HRTIMER_NORESTART;
++
++ if (!pendown(ts))
++ {
++ ads_dbg(debug, 1, "Release\n");
++
++ input_report_key(ts->input, BTN_TOUCH, 0);
++ input_report_abs(ts->input, ABS_PRESSURE, 0);
++ input_sync(ts->input);
++
++ if(desc->irq_data.chip->irq_ack)
++ desc->irq_data.chip->irq_ack(&desc->irq_data);
++ enable_irq(ts->irq);
++ return HRTIMER_NORESTART;
++ }
++ report(ts, &e);
++
++#ifdef CONFIG_TOUCHSCREEN_CPE_TS_DEJITTER
++ if (abs(xp - e.x) > FILTER_LIMIT || abs(yp - e.y) > FILTER_LIMIT)
++ {
++#endif
++ input_report_key(ts->input, BTN_TOUCH, 1);
++ input_report_abs(ts->input, ABS_X, e.x);
++ input_report_abs(ts->input, ABS_Y, e.y);
++ input_report_abs(ts->input, ABS_PRESSURE, 50);
++ xp = e.x;
++ yp = e.y;
++#ifdef CONFIG_TOUCHSCREEN_CPE_TS_DEJITTER
++ }
++#endif
++ input_sync(ts->input);
++ hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_PERIOD), HRTIMER_MODE_REL);
++ ads_dbg(0, 1, "Leave\n");
++ return HRTIMER_NORESTART;
++}
++
++static irqreturn_t ads7846_irq(int irq, void *handle)
++{
++ struct ads7846 *ts = handle;
++
++ if (ts->disabled)
++ return IRQ_HANDLED;
++
++ disable_irq_nosync(irq);
++ hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY), HRTIMER_MODE_REL);
++
++ return IRQ_HANDLED;
++}
++
++static int xspi_init_hw(void __iomem *regs_base)
++{
++ int rev = REG32(regs_base + SSP_REG_REV);
++ int reva = REG32(regs_base + SSP_REG_REV-0x20);
++
++ if ((((rev & SSP_REV_mskMAJOR_REV) >> SSP_REV_offMAJOR_REV) != 1)&&
++ (((reva & SSP_REV_mskMAJOR_REV) >> SSP_REV_offMAJOR_REV) != 1))
++ {
++ ads_dbg(1, 0, "ADS7846 Touchscreen controller initialized failed:\n"
++ "\tcannot detect Faraday SSP Controller\n");
++ return -ENXIO;
++ }
++ REG32(regs_base + SSP_REG_CR2) |= (1UL << SSP_CR2_offSSPRST);
++
++ REG32(regs_base + SSP_REG_CR1) =
++ (0UL << SSP_CR1_offPDL) | /* Padding Data Length */
++ (23UL << SSP_CR1_offSDL) | /* Serial Data Length */
++ (5UL << SSP_CR1_offSCLKDIV); /* SCLK Divider */
++
++ REG32(regs_base + SSP_REG_CR0) =
++ (1UL << SSP_CR0_offFFMT) | /* Frame Format */
++ (3UL << SSP_CR0_offOPM) | /* Operation Mode */
++ (0UL << SSP_CR0_offSCLKPO) | /* SCLK Polarity */
++ (0UL << SSP_CR0_offSCLKPH); /* SCLK Phase */
++
++ REG32(regs_base + SSP_REG_CR2) |= (1UL << SSP_CR2_offTXFCLR) | (1UL << SSP_CR2_offRXFCLR);
++ REG32(regs_base + SSP_REG_CR2) |= (1UL << SSP_CR2_offSSPEN) | (1UL << SSP_CR2_offTXDOE);
++ return 0;
++}
++
++static int ads7846_probe(struct platform_device *pdev)
++{
++ struct ads7846 *ts = &touchscreen;
++ struct input_dev *input_dev;
++ int err = 0;
++ platform_set_drvdata(pdev, ts);
++
++ ts->regs = ioremap(0x98b00000, 44);
++ err = xspi_init_hw(ts->regs);
++ if (err)
++ goto err_unmap;
++ input_dev = input_allocate_device();
++ if (!input_dev)
++ {
++ err = -ENOMEM;
++ goto err_free_mem;
++ }
++
++ ts->input = input_dev;
++
++ hrtimer_init(&ts->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
++ ts->timer.function = ads7846_timer;
++
++ input_dev->name = "ADS7846 Touchscreen";
++ input_dev->phys = ts->phys;
++
++ input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
++ input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
++ input_set_abs_params(input_dev, ABS_X, 0, MAX_12BIT, 0, 0);
++ input_set_abs_params(input_dev, ABS_Y, 0, MAX_12BIT, 0, 0);
++ input_set_abs_params(input_dev, ABS_PRESSURE, 0, MAX_12BIT, 0, 0);
++
++ ts->irq = TOUCHSCREEN_IRQ;
++
++ if (request_irq(ts->irq, ads7846_irq, IRQF_TRIGGER_RISING, "touch screen", ts))
++ goto err_free_mem;
++
++ err = input_register_device(input_dev);
++ if (err)
++ goto err_free_irq;
++
++ spin_lock_init(&ts->lock);
++ return 0;
++err_free_irq:
++ free_irq(ts->irq, ts);
++err_free_mem:
++ input_free_device(input_dev);
++err_unmap:
++ iounmap(ts->regs);
++
++ return err;
++}
++
++static int __devexit ads7846_remove(struct platform_device *pdev)
++{
++ struct ads7846 *ts = platform_get_drvdata(pdev);
++
++ disable_irq(ts->irq);
++ free_irq(ts->irq, ts);
++ iounmap(ts->regs);
++ input_unregister_device(ts->input);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++static int ads7846_suspend( struct platform_device *pdev, pm_message_t message)
++{
++ struct ads7846 *ts = platform_get_drvdata(pdev);
++
++ spin_lock_irq(&ts->lock);
++ ts->disabled = true;
++ disable_irq(ts->irq);
++ spin_unlock_irq(&ts->lock);
++
++ return 0;
++}
++
++static int ads7846_resume( struct platform_device *pdev)
++{
++ struct ads7846 *ts = platform_get_drvdata(pdev);
++
++ spin_lock_irq(&ts->lock);
++
++ enable_irq(ts->irq);
++ ts->disabled = false;
++
++ spin_unlock_irq(&ts->lock);
++
++ return 0;
++}
++#else
++#define ads7846_suspend NULL
++#define ads7846_resume NULL
++#endif
++
++static void platform_device_release(struct device *dev){
++}
++
++static struct resource ads7846_resources[] =
++{
++ [0] = {
++ .start = SSP_FTSSP010_PA_BASE,
++ .end = SSP_FTSSP010_PA_LIMIT,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = TOUCHSCREEN_IRQ, //feed me! SSP_FTSSP010_IRQ in spec.h
++ .end = TOUCHSCREEN_IRQ,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_device ads7846_device =
++{
++ .name = "ads7846",
++ .id = -1,
++ .resource = ads7846_resources,
++ .num_resources = ARRAY_SIZE(ads7846_resources),
++ .dev = {
++ .release = platform_device_release,
++ },
++};
++
++#if 0
++static struct platform_driver ads7846_driver =
++{
++ .driver = {
++ .name = "ads7846",
++ .owner = THIS_MODULE,
++ },
++ .probe = ads7846_probe,
++ .remove = __devexit_p(ads7846_remove),
++ .suspend = ads7846_suspend,
++ .resume = ads7846_resume,
++};
++#else
++static struct platform_driver ads7846_driver =
++{
++ .driver = {
++ .name = "ads7846",
++ },
++ .probe = ads7846_probe,
++ .remove = __devexit_p(ads7846_remove),
++ .suspend = ads7846_suspend,
++ .resume = ads7846_resume,
++};
++#endif
++
++static int __init ads7846_init(void)
++{
++ platform_device_register(&ads7846_device);
++ return platform_driver_register(&ads7846_driver);
++}
++
++static void __exit ads7846_exit(void)
++{
++ platform_device_unregister(&ads7846_device);
++ platform_driver_unregister(&ads7846_driver);
++}
++
++module_init(ads7846_init);
++module_exit(ads7846_exit);
++MODULE_DESCRIPTION("ADS7846 TouchScreen Driver");
++MODULE_LICENSE("GPL");
+diff -Nur linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/cpe_ts.h linux-3.4.110/drivers/input/touchscreen/cpe_ts/cpe_ts.h
+--- linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/cpe_ts.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/input/touchscreen/cpe_ts/cpe_ts.h 2016-04-07 10:20:51.050085202 +0200
+@@ -0,0 +1,218 @@
++#ifndef SSP_FARADAY_H
++#define SSP_FARADAY_H
++
++#define XILINX_SPI_NAME "faraday-spi"
++
++/*
++ * Register definitions as per "OPB Serial Peripheral Interface ( SPI) ( v1.00e)
++ * Product Specification", DS464
++ */
++#define XSPI_CR_OFFSET 0x62 /* 16-bit Control Register */
++
++#define XSPI_CR_ENABLE 0x02
++#define XSPI_CR_MASTER_MODE 0x04
++#define XSPI_CR_CPOL 0x08
++#define XSPI_CR_CPHA 0x10
++#define XSPI_CR_MODE_MASK ( XSPI_CR_CPHA | XSPI_CR_CPOL)
++#define XSPI_CR_TXFIFO_RESET 0x20
++#define XSPI_CR_RXFIFO_RESET 0x40
++#define XSPI_CR_MANUAL_SSELECT 0x80
++#define XSPI_CR_TRANS_INHIBIT 0x100
++
++#define XSPI_SR_OFFSET 0x67 /* 8-bit Status Register */
++
++#define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */
++#define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */
++#define XSPI_SR_TX_EMPTY_MASK 0x04 /* Transmit FIFO is empty */
++#define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */
++#define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */
++
++#define XSPI_TXD_OFFSET 0x6b /* 8-bit Data Transmit Register */
++#define XSPI_RXD_OFFSET 0x6f /* 8-bit Data Receive Register */
++
++#define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */
++
++/* Register definitions as per "OPB IPIF ( v3.01c) Product Specification", DS414
++ * IPIF registers are 32 bit
++ */
++#define XIPIF_V123B_DGIER_OFFSET 0x1c /* IPIF global int enable reg */
++#define XIPIF_V123B_GINTR_ENABLE 0x80000000
++
++#define XIPIF_V123B_IISR_OFFSET 0x20 /* IPIF interrupt status reg */
++#define XIPIF_V123B_IIER_OFFSET 0x28 /* IPIF interrupt enable reg */
++
++#define XSPI_INTR_MODE_FAULT 0x01 /* Mode fault error */
++#define XSPI_INTR_SLAVE_MODE_FAULT 0x02 /* Selected as slave while disabled */
++#define XSPI_INTR_TX_EMPTY 0x04 /* TxFIFO is empty */
++#define XSPI_INTR_TX_UNDERRUN 0x08 /* TxFIFO was underrun */
++#define XSPI_INTR_RX_FULL 0x10 /* RxFIFO is full */
++#define XSPI_INTR_RX_OVERRUN 0x20 /* RxFIFO was overrun */
++
++#define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */
++#define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */
++
++/*************************************************************************/
++#if 0
++#define SSP_REG_CR0 ( SSP_FTSSP010_VA_BASE + 0x00) /* SSP Control Register 0 */
++#define SSP_REG_CR1 ( SSP_FTSSP010_VA_BASE + 0x04) /* SSP Control Register 1 */
++#define SSP_REG_CR2 ( SSP_FTSSP010_VA_BASE + 0x08) /* SSP Control Register 2 */
++#define SSP_REG_SR ( SSP_FTSSP010_VA_BASE + 0x0c) /* SSP Status Register */
++#define SSP_REG_ICR ( SSP_FTSSP010_VA_BASE + 0x10) /* SSP Interrupt Control Register */
++#define SSP_REG_ISR ( SSP_FTSSP010_VA_BASE + 0x14) /* SSP Interrupt Status Register */
++#define SSP_REG_DR ( SSP_FTSSP010_VA_BASE + 0x18) /* SSP Data Register */
++#define SSP_REG_ACL ( SSP_FTSSP010_VA_BASE + 0x20) /* AC-Link Slot Valid Register */
++#define SSP_REG_REV ( SSP_FTSSP010_VA_BASE + 0x40) /* SSP Revision Register */
++#define SSP_REG_FEA ( SSP_FTSSP010_VA_BASE + 0x44) /* SSP Feature Register */
++#endif
++#define SSP_REG_CR0 0x00 /* SSP Control Register 0 */
++#define SSP_REG_CR1 0x04 /* SSP Control Register 1 */
++#define SSP_REG_CR2 0x08 /* SSP Control Register 2 */
++#define SSP_REG_SR 0x0C /* SSP Status Register */
++#define SSP_REG_ICR 0x10 /* SSP Interrupt Control Register */
++#define SSP_REG_ISR 0x14 /* SSP Interrupt Status Register */
++#define SSP_REG_DR 0x18 /* SSP Data Register */
++#define SSP_REG_ACL 0x20 /* AC-Link Slot Valid Register */
++#define SSP_REG_REV 0x60 /* SSP Revision Register */
++#define SSP_REG_FEA 0x64 /* SSP Feature Register */
++
++#define SSP_CR0_offFFMT 12 /* Frame Format */
++#define SSP_CR0_offFSDIST 8 /* Frame/Sync and Data Distance */
++#define SSP_CR0_offLBM 7 /* Loopback Mode */
++#define SSP_CR0_offLSB 6 /* Bit Sequence Indicator */
++#define SSP_CR0_offFSPO 5 /* Frame/Sync Polarity */
++#define SSP_CR0_offFSJSFY 4 /* Data Justify */
++#define SSP_CR0_offOPM 2 /* Operation Mode */
++#define SSP_CR0_offSCLKPO 1 /* SCLK Polarity */
++#define SSP_CR0_offSCLKPH 0 /* SCLK Phase */
++
++#define SSP_CR0_mskFFMT ( 0x07UL << SSP_CR0_offFFMT)
++#define SSP_CR0_mskFSDIST ( 0x03UL << SSP_CR0_offFSDIST)
++#define SSP_CR0_mskLBM ( 0x01UL << SSP_CR0_offLBM)
++#define SSP_CR0_mskLSB ( 0x01UL << SSP_CR0_offLSB)
++#define SSP_CR0_mskFSPO ( 0x01UL << SSP_CR0_offFSPO)
++#define SSP_CR0_mskFSJSFY ( 0x01UL << SSP_CR0_offFSJSFY)
++#define SSP_CR0_mskOPM ( 0x03UL << SSP_CR0_offOPM)
++#define SSP_CR0_mskSCLKPO ( 0x01UL << SSP_CR0_offSCLKPO)
++#define SSP_CR0_mskSCLKPH ( 0x01UL << SSP_CR0_offSCLKPH)
++
++#define SSP_CR1_offPDL 24 /* Padding Data Length */
++#define SSP_CR1_offSDL 16 /* Serial Data Length */
++#define SSP_CR1_offSCLKDIV 0 /* SCLK Divider */
++
++#define SSP_CR1_mskPDL ( 0xFFUL << SSP_CR1_offPDL)
++#define SSP_CR1_mskSDL ( 0x1FUL << SSP_CR1_offSDL)
++#define SSP_CR1_mskSCLKDIV ( 0xFFUL << SSP_CR1_offSCLKDIV)
++
++#define SSP_CR2_offSSPRST 6 /* SSP Reset */
++#define SSP_CR2_offACCRST 5 /* AC-Link Cold Reset Enable */
++#define SSP_CR2_offACWRST 4 /* AC-Link Warm Reset Enable */
++#define SSP_CR2_offTXFCLR 3 /* Transmit FIFO Clear */
++#define SSP_CR2_offRXFCLR 2 /* Recieve FIFO clear */
++#define SSP_CR2_offTXDOE 1 /* Transmit Data Output Enable */
++#define SSP_CR2_offSSPEN 0 /* The SSP Enable */
++
++#define SSP_CR2_mskSSPRST ( 0x01UL << SSP_CR2_offSSPRST)
++#define SSP_CR2_mskACCRST ( 0x01UL << SSP_CR2_offACCRST)
++#define SSP_CR2_mskACWRST ( 0x01UL << SSP_CR2_offACWRST)
++#define SSP_CR2_mskTXFCLR ( 0x01UL << SSP_CR2_offTXFCLR)
++#define SSP_CR2_mskRXFCLR ( 0x01UL << SSP_CR2_offRXFCLR)
++#define SSP_CR2_mskTXDOE ( 0x01UL << SSP_CR2_offTXDOE)
++#define SSP_CR2_mskSSPEN ( 0x01UL << SSP_CR2_offSSPEN)
++
++#define SSP_SR_offTFVE 12 /* Transmit FIFO Valid Entries */
++#define SSP_SR_offRFVE 4 /* Recieve FIFO Valid Entries */
++#define SSP_SR_offBUSY 2 /* Busy Indicator */
++#define SSP_SR_offTFNF 1 /* Transmit FIFO not full */
++#define SSP_SR_offRFF 0 /* Recieve FIFO full */
++
++#define SSP_SR_mskTFVE ( 0x1FUL << SSP_SR_offTFVE)
++#define SSP_SR_mskRFVE ( 0x1FUL << SSP_SR_offRFVE)
++#define SSP_SR_mskBUSY ( 0x01UL << SSP_SR_offBUSY)
++#define SSP_SR_mskTFNF ( 0x01UL << SSP_SR_offTFNF)
++#define SSP_SR_mskRFF ( 0x01UL << SSP_SR_offRFF)
++
++#define SSP_ICR_offTFTHOD 12 /* Transmit FIFO Threshold */
++#define SSP_ICR_offRFTHOD 8 /* Recieve FIFO Threshold */
++#define SSP_ICR_offAC97FCEN 6 /* AC97 Frame Complete */
++#define SSP_ICR_offTFDMAEN 5 /* Transmit DMA Request Enable */
++#define SSP_ICR_offRFDMAEN 4 /* Recieve DMA Request Enable */
++#define SSP_ICR_offTFTHIEN 3 /* Transmit FIFO Threshold Interrupt */
++#define SSP_ICR_offRFTHIEN 2 /* Recieve FIFO Threshold Interrupt */
++#define SSP_ICR_offTFURIEN 1 /* Transmit FIFO Underrun Interrupt Enable */
++#define SSP_ICR_offRFORIEN 0 /* Recieve FIFO Overrun Interrupt Enable */
++
++#define SSP_ICR_mskTFTHOD ( 0x0FUL << SSP_ICR_offTFTHOD)
++#define SSP_ICR_mskRFTHOD ( 0x0FUL << SSP_ICR_offRFTHOD)
++#define SSP_ICR_mskAC97FCEN ( 0x01UL << SSP_ICR_offAC97FCEN)
++#define SSP_ICR_mskTFDMAEN ( 0x01UL << SSP_ICR_offTFDMAEN)
++#define SSP_ICR_mskRFDMAEN ( 0x01UL << SSP_ICR_offRFDMAEN)
++#define SSP_ICR_mskTFTHIEN ( 0x01UL << SSP_ICR_offTFTHIEN)
++#define SSP_ICR_mskRFTHIEN ( 0x01UL << SSP_ICR_offRFTHIEN)
++#define SSP_ICR_mskTFURIEN ( 0x01UL << SSP_ICR_offTFURIEN)
++#define SSP_ICR_mskRFORIEN ( 0x01UL << SSP_ICR_offRFORIEN)
++
++#define SSP_ISR_offAC97FCI 4 /* AC97 Frame Complete Interrupt */
++#define SSP_ISR_offTFTHI 3 /* Transmit FIFO Threshold Interrupt */
++#define SSP_ISR_offRFTHI 2 /* Recieve FIFO Threshold Interrupt */
++#define SSP_ISR_offTFURI 1 /* Transmit FIFO underrun Interrupt */
++#define SSP_ISR_offRFORI 0 /* Recieve FIFO Overun Interrupt */
++
++#define SSP_ISR_mskAC97FCI ( 0x01UL << SSP_ISR_offAC97FCI)
++#define SSP_ISR_mskTFTHI ( 0x01UL << SSP_ISR_offTFTHI)
++#define SSP_ISR_mskRFTHI ( 0x01UL << SSP_ISR_offRFTHI)
++#define SSP_ISR_mskTFURI ( 0x01UL << SSP_ISR_offTFURI)
++#define SSP_ISR_mskRFORI ( 0x01UL << SSP_ISR_offRFORI)
++
++#define SSP_ACL_offSLOT1V 14 /* The 1st Slot is Valid */
++#define SSP_ACL_offSLOT2V 13 /* The 2nd Slot is Valid */
++#define SSP_ACL_offSLOT3V 12 /* The 3th Slot is Valid */
++#define SSP_ACL_offSLOT4V 11 /* The 4th Slot is Valid */
++#define SSP_ACL_offSLOT5V 10 /* The 5th Slot is Valid */
++#define SSP_ACL_offSLOT6V 9 /* The 6th Slot is Valid */
++#define SSP_ACL_offSLOT7V 8 /* The 7th Slot is Valid */
++#define SSP_ACL_offSLOT8V 7 /* The 8th Slot is Valid */
++#define SSP_ACL_offSLOT9V 6 /* The 9th Slot is Valid */
++#define SSP_ACL_offSLOT10V 5 /* The 10th Slot is Valid */
++#define SSP_ACL_offSLOT11V 4 /* The 11th Slot is Valid */
++#define SSP_ACL_offSLOT12V 3 /* The 12th Slot is Valid */
++#define SSP_ACL_offCODECID 0 /* Codec ID, which will be shifted out as tag slot */
++
++#define SSP_ACL_mskSLOT1V ( 0x01UL << SSP_ACL_offSLOT1V)
++#define SSP_ACL_mskSLOT2V ( 0x01UL << SSP_ACL_offSLOT2V)
++#define SSP_ACL_mskSLOT3V ( 0x01UL << SSP_ACL_offSLOT3V)
++#define SSP_ACL_mskSLOT4V ( 0x01UL << SSP_ACL_offSLOT4V)
++#define SSP_ACL_mskSLOT5V ( 0x01UL << SSP_ACL_offSLOT5V)
++#define SSP_ACL_mskSLOT6V ( 0x01UL << SSP_ACL_offSLOT6V)
++#define SSP_ACL_mskSLOT7V ( 0x01UL << SSP_ACL_offSLOT7V)
++#define SSP_ACL_mskSLOT8V ( 0x01UL << SSP_ACL_offSLOT8V)
++#define SSP_ACL_mskSLOT9V ( 0x01UL << SSP_ACL_offSLOT9V)
++#define SSP_ACL_mskSLOT10V ( 0x01UL << SSP_ACL_offSLOT10V)
++#define SSP_ACL_mskSLOT11V ( 0x01UL << SSP_ACL_offSLOT11V)
++#define SSP_ACL_mskSLOT12V ( 0x01UL << SSP_ACL_offSLOT12V)
++#define SSP_ACL_mskCODECID ( 0x03UL << SSP_ACL_offCODECID)
++
++#define SSP_REV_offMAJOR_REV 16 /* Major Revision Number */
++#define SSP_REV_offMINOR_REV 8 /* Minor Revision Number */
++#define SSP_REV_offREL_REV 0 /* Release Number */
++
++#define SSP_REV_mskMAJOR_REV ( 0xFFUL << SSP_REV_offMAJOR_REV)
++#define SSP_REV_mskMINOR_REV ( 0xFFUL << SSP_REV_offMINOR_REV)
++#define SSP_REV_mskREL_REV ( 0xFFUL << SSP_REV_offREL_REV)
++
++#define SSP_FEA_offSSP_FCFG 27 /* The SSP Functional Configurations */
++#define SSP_FEA_offSPIMWR_FCFG 26 /* Motorola's SPI and National Semiconductor's Microwire Configurations */
++#define SSP_FEA_offI2S_FCFG 25 /* Philips's I2S Functional Configurations */
++#define SSP_FEA_offAC97_FCFG 24 /* Intel's AC-Link Functional Configurations */
++#define SSP_FEA_offTXFIFO_WIDTH 16 /* Transmit FIFO Size Configurations */
++#define SSP_FEA_offRXFIFO_WIDTH 8 /* Recieve FIFO Size Configuration */
++#define SSP_FEA_offFIFO_WIDTH 0 /* Transmit/Recieve FIFO Width */
++
++#define SSP_FEA_mskSSP_FCFG ( 0x01UL << SSP_FEA_offSSP_FCFG)
++#define SSP_FEA_mskSPIMWR_FCFG ( 0x01UL << SSP_FEA_offSPIMWR_FCFG)
++#define SSP_FEA_mskI2S_FCFG ( 0x01UL << SSP_FEA_offI2S_FCFG)
++#define SSP_FEA_mskAC97_FCFG ( 0x01UL << SSP_FEA_offAC97_FCFG)
++#define SSP_FEA_mskTXFIFO_WIDTH ( 0xFFUL << SSP_FEA_offTXFIFO_WIDTH)
++#define SSP_FEA_mskRXFIFO_WIDTH ( 0xFFUL << SSP_FEA_offRXFIFO_WIDTH)
++#define SSP_FEA_mskFIFO_WIDTH ( 0xFFUL << SSP_FEA_offFIFO_WIDTH)
++
++#endif /* SSP_FARADAY */
+diff -Nur linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/Makefile linux-3.4.110/drivers/input/touchscreen/cpe_ts/Makefile
+--- linux-3.4.110.orig/drivers/input/touchscreen/cpe_ts/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/input/touchscreen/cpe_ts/Makefile 2016-04-07 10:20:51.050085202 +0200
+@@ -0,0 +1 @@
++obj-$(CONFIG_TOUCHSCREEN_CPE_TS) += cpe_ts.o
+diff -Nur linux-3.4.110.orig/drivers/input/touchscreen/Kconfig linux-3.4.110/drivers/input/touchscreen/Kconfig
+--- linux-3.4.110.orig/drivers/input/touchscreen/Kconfig 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/input/touchscreen/Kconfig 2016-04-07 10:20:51.050085202 +0200
+@@ -86,6 +86,26 @@
+ To compile this driver as a module, choose M here: the
+ module will be called ad7879-spi.
+
++config TOUCHSCREEN_CPE_TS
++ tristate "Touchscreen Driver for AG101/XC5"
++ help
++ This driver directly accesses SPI controller to communicate with
++ the ads7846 chip.
++
++ Once we have a SPI controller driver
++ , we can adopt to the SPI
++ framework that kernel provides.
++
++config TOUCHSCREEN_CPE_TS_DEJITTER
++ bool "Dejitter Detection"
++ depends on TOUCHSCREEN_CPE_TS
++ default y
++ help
++ Say Y here to enable dejitter detection in AG101/Leopard Touchscreen Driver.
++
++ If unsure, say y.
++
++
+ config TOUCHSCREEN_ATMEL_MXT
+ tristate "Atmel mXT I2C Touchscreen"
+ depends on I2C
+diff -Nur linux-3.4.110.orig/drivers/input/touchscreen/Makefile linux-3.4.110/drivers/input/touchscreen/Makefile
+--- linux-3.4.110.orig/drivers/input/touchscreen/Makefile 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/input/touchscreen/Makefile 2016-04-07 10:20:51.050085202 +0200
+@@ -69,3 +69,4 @@
+ obj-$(CONFIG_TOUCHSCREEN_WM97XX_ZYLONITE) += zylonite-wm97xx.o
+ obj-$(CONFIG_TOUCHSCREEN_W90X900) += w90p910_ts.o
+ obj-$(CONFIG_TOUCHSCREEN_TPS6507X) += tps6507x-ts.o
++obj-$(CONFIG_TOUCHSCREEN_CPE_TS) += cpe_ts/
+diff -Nur linux-3.4.110.orig/drivers/mmc/core/bus.c linux-3.4.110/drivers/mmc/core/bus.c
+--- linux-3.4.110.orig/drivers/mmc/core/bus.c 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/mmc/core/bus.c 2016-04-07 10:20:51.050085202 +0200
+@@ -26,7 +26,9 @@
+ #include "bus.h"
+
+ #define to_mmc_driver(d) container_of(d, struct mmc_driver, drv)
+-
++#ifdef CONFIG_MMC_TEST
++static struct mmc_driver *mmc_test_drv;
++#endif
+ static ssize_t mmc_type_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+ {
+@@ -109,6 +111,11 @@
+ struct mmc_driver *drv = to_mmc_driver(dev->driver);
+ struct mmc_card *card = mmc_dev_to_card(dev);
+
++ #ifdef CONFIG_MMC_TEST
++ mmc_test_drv->probe(card);
++ printk("debug mmc_bus_probe\n");
++ #endif
++
+ return drv->probe(card);
+ }
+
+@@ -200,6 +207,11 @@
+ int mmc_register_driver(struct mmc_driver *drv)
+ {
+ drv->drv.bus = &mmc_bus_type;
++ #ifdef CONFIG_MMC_TEST
++ printk("debug defined config_mmc_test in mmc_register_driver\n");
++ if(!strcmp(drv->drv.name,"mmc_test"))
++ mmc_test_drv = drv;
++ #endif
+ return driver_register(&drv->drv);
+ }
+
+diff -Nur linux-3.4.110.orig/drivers/mmc/host/ftsdc010.c linux-3.4.110/drivers/mmc/host/ftsdc010.c
+--- linux-3.4.110.orig/drivers/mmc/host/ftsdc010.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/mmc/host/ftsdc010.c 2016-04-07 10:20:51.050085202 +0200
+@@ -0,0 +1,1586 @@
++/* drivers/mmc/host/ftsdc010.c
++ * Copyright (C) 2010 Andestech
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#include <linux/module.h>
++#include <linux/dma-mapping.h>
++#include <linux/clk.h>
++#include <linux/mmc/host.h>
++#include <linux/mmc/mmc.h>
++#include <linux/mmc/card.h>
++#include <linux/platform_device.h>
++#include <linux/debugfs.h>
++#include <linux/seq_file.h>
++#include <linux/irq.h>
++#include <linux/interrupt.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++
++#include <asm/io.h>
++#include <asm/spec.h>
++#include <asm/dmad.h>
++
++#include "ftsdc010.h"
++
++#define DRIVER_NAME "ftsdc010"
++
++#define REG_READ(addr) readl((host->base + addr))
++#define REG_WRITE(data, addr) writel((data), (host->base + addr))
++
++#define APB_CLK_IN (AHB_CLK_IN / 2)
++
++enum dbg_channels {
++ dbg_err = (1 << 0),
++ dbg_debug = (1 << 1),
++ dbg_info = (1 << 2),
++ dbg_irq = (1 << 3),
++ dbg_sg = (1 << 4),
++ dbg_dma = (1 << 5),
++ dbg_pio = (1 << 6),
++ dbg_fail = (1 << 7),
++ dbg_conf = (1 << 8),
++};
++
++static struct workqueue_struct *mywq;
++
++static const int dbgmap_err = dbg_fail;
++static const int dbgmap_info = dbg_info | dbg_conf;
++static const int dbgmap_debug = dbg_err | dbg_debug | dbg_info | dbg_conf;
++#if 1
++#define dbg(host, channels, args...) \
++ do { \
++ if (dbgmap_err & channels) \
++ dev_err(&host->pdev->dev, args); \
++ else if (dbgmap_info & channels) \
++ dev_info(&host->pdev->dev, args); \
++ else if (dbgmap_debug & channels) \
++ dev_dbg(&host->pdev->dev, args); \
++ } while (0)
++#endif
++#if 0
++#define dbg(host, channels, args...) \
++ do { \
++ printk(KERN_INFO "%s: ", "ftsdc");\
++ printk(args); \
++ } while(0)
++#endif
++
++static void finalize_request(struct ftsdc_host *host);
++static void ftsdc_send_request(struct mmc_host *mmc);
++
++#ifdef CONFIG_MMC_DEBUG
++
++static void dbg_dumpregs(struct ftsdc_host *host, char *prefix)
++{
++ u32 con, cmdarg, r0, r1, r2, r3, rcmd, dcon, dtimer,
++ dlen, sta, clr, imask, pcon, ccon, bwidth, scon1,
++ scon2, ssta, fea;
++
++ con = REG_READ(SDC_CMD_REG);
++ cmdarg = REG_READ(SDC_ARGU_REG);
++ r0 = REG_READ(SDC_RESPONSE0_REG);
++ r1 = REG_READ(SDC_RESPONSE1_REG);
++ r2 = REG_READ(SDC_RESPONSE2_REG);
++ r3 = REG_READ(SDC_RESPONSE3_REG);
++ rcmd = REG_READ(SDC_RSP_CMD_REG);
++ dcon = REG_READ(SDC_DATA_CTRL_REG);
++ dtimer = REG_READ(SDC_DATA_TIMER_REG);
++ dlen = REG_READ(SDC_DATA_LEN_REG);
++ sta = REG_READ(SDC_STATUS_REG);
++ clr = REG_READ(SDC_CLEAR_REG);
++ imask = REG_READ(SDC_INT_MASK_REG);
++ pcon = REG_READ(SDC_POWER_CTRL_REG);
++ ccon = REG_READ(SDC_CLOCK_CTRL_REG);
++ bwidth = REG_READ(SDC_BUS_WIDTH_REG);
++ scon1 = REG_READ(SDC_SDIO_CTRL1_REG);
++ scon2 = REG_READ(SDC_SDIO_CTRL2_REG);
++ ssta = REG_READ(SDC_SDIO_STATUS_REG);
++ fea = REG_READ(SDC_FEATURE_REG);
++
++ dbg(host, dbg_debug, "%s CON:[%08x] STA:[%08x] INT:[%08x], PWR:[%08x], CLK:[%08x]\n",
++ prefix, con, sta, imask, pcon, ccon);
++
++ dbg(host, dbg_debug, "%s DCON:[%08x] DTIME:[%08x]"
++ " DLEN:[%08x] DWIDTH:[%08x]\n",
++ prefix, dcon, dtimer, dlen, bwidth);
++
++ dbg(host, dbg_debug, "%s R0:[%08x] R1:[%08x]"
++ " R2:[%08x] R3:[%08x]\n",
++ prefix, r0, r1, r2, r3);
++
++ dbg(host, dbg_debug, "%s SCON1:[%08x] SCON2:[%08x]"
++ " SSTA:[%08x] FEA:[%08x]\n",
++ prefix, scon1, scon2, ssta, fea);
++}
++
++static void prepare_dbgmsg(struct ftsdc_host *host, struct mmc_command *cmd,
++ int stop)
++{
++ snprintf(host->dbgmsg_cmd, 300,
++ "#%u%s op:%i arg:0x%08x flags:0x08%x retries:%u",
++ host->ccnt, (stop ? " (STOP)" : ""),
++ cmd->opcode, cmd->arg, cmd->flags, cmd->retries);
++
++ if (cmd->data) {
++ snprintf(host->dbgmsg_dat, 300,
++ "#%u bsize:%u blocks:%u bytes:%u",
++ host->dcnt, cmd->data->blksz,
++ cmd->data->blocks,
++ cmd->data->blocks * cmd->data->blksz);
++ } else {
++ host->dbgmsg_dat[0] = '\0';
++ }
++}
++
++static void dbg_dumpcmd(struct ftsdc_host *host, struct mmc_command *cmd,
++ int fail)
++{
++ unsigned int dbglvl = fail ? dbg_fail : dbg_debug;
++
++ if (!cmd)
++ return;
++
++ if (cmd->error == 0) {
++ dbg(host, dbglvl, "CMD[OK] %s R0:0x%08x\n",
++ host->dbgmsg_cmd, cmd->resp[0]);
++ } else {
++ dbg(host, dbglvl, "CMD[ERR %i] %s Status:%s\n",
++ cmd->error, host->dbgmsg_cmd, host->status);
++ }
++
++ if (!cmd->data)
++ return;
++
++ if (cmd->data->error == 0) {
++ dbg(host, dbglvl, "DAT[OK] %s\n", host->dbgmsg_dat);
++ } else {
++ dbg(host, dbglvl, "DAT[ERR %i] %s DCNT:0x%08x\n",
++ cmd->data->error, host->dbgmsg_dat,
++ REG_READ(SDC_DATA_LEN_REG));
++ }
++}
++#else
++static void dbg_dumpcmd(struct ftsdc_host *host,
++ struct mmc_command *cmd, int fail) { }
++
++static void prepare_dbgmsg(struct ftsdc_host *host, struct mmc_command *cmd,
++ int stop) { }
++
++static void dbg_dumpregs(struct ftsdc_host *host, char *prefix) { }
++
++#endif /* CONFIG_MMC_DEBUG */
++
++static inline bool ftsdc_dmaexist(struct ftsdc_host *host)
++{
++ return (host->dma_req != NULL);
++}
++
++static inline u32 enable_imask(struct ftsdc_host *host, u32 imask)
++{
++ u32 newmask;
++
++#ifdef CONFIG_MMC_DEBUG
++ if (imask & SDC_STATUS_REG_SDIO_INTR) printk("\n*** E ***\n");
++#endif
++ newmask = REG_READ(SDC_INT_MASK_REG);
++ newmask |= imask;
++
++ REG_WRITE(newmask, SDC_INT_MASK_REG);
++
++ return newmask;
++}
++
++static inline u32 disable_imask(struct ftsdc_host *host, u32 imask)
++{
++ u32 newmask;
++
++#ifdef CONFIG_MMC_DEBUG
++ if (imask & SDC_STATUS_REG_SDIO_INTR) printk("\n*** D ***\n");
++#endif
++ newmask = REG_READ(SDC_INT_MASK_REG);
++ newmask &= ~imask;
++
++ REG_WRITE(newmask, SDC_INT_MASK_REG);
++
++ return newmask;
++}
++
++static inline void clear_imask(struct ftsdc_host *host)
++{
++ u32 mask = REG_READ(SDC_INT_MASK_REG);
++
++ /* preserve the SDIO IRQ mask state */
++ mask &= (SDC_INT_MASK_REG_SDIO_INTR | SDC_INT_MASK_REG_CARD_CHANGE);
++ REG_WRITE(mask, SDC_INT_MASK_REG);
++}
++
++//static void ftsdc_check_sdio_irq(struct ftsdc_host *host)
++//{
++// if (host->sdio_irqen) {
++// u32 con = REG_READ(SDC_STATUS_REG);
++// if (con & SDC_STATUS_REG_SDIO_INTR) {
++// printk(KERN_DEBUG "%s: signalling irq\n", __func__);
++// mmc_signal_sdio_irq(host->mmc);
++// }
++// }
++//}
++
++static inline void get_data_buffer(struct ftsdc_host *host)
++{
++ struct scatterlist *sg;
++
++ BUG_ON(host->buf_sgptr >= host->mrq->data->sg_len);
++
++ sg = &host->mrq->data->sg[host->buf_sgptr];
++
++ host->buf_bytes = sg->length;
++ host->buf_ptr = host->dodma ? (u32 *)sg->dma_address : sg_virt(sg);
++ host->buf_sgptr++;
++}
++
++static inline u32 cal_blksz(unsigned int blksz)
++{
++ u32 blksztwo = 0;
++
++ while (blksz >>= 1)
++ blksztwo++;
++
++ return blksztwo;
++}
++
++/**
++ * ftsdc_enable_irq - enable IRQ, after having disabled it.
++ * @host: The device state.
++ * @more: True if more IRQs are expected from transfer.
++ *
++ * Enable the main IRQ if needed after it has been disabled.
++ *
++ * The IRQ can be one of the following states:
++ * - enable after data read/write
++ * - disable when handle data read/write
++ */
++static void ftsdc_enable_irq(struct ftsdc_host *host, bool enable)
++{
++ unsigned long flags;
++ local_irq_save(flags);
++
++ host->irq_enabled = enable;
++
++ if (enable)
++ enable_irq(host->irq);
++ else
++ disable_irq(host->irq);
++
++ local_irq_restore(flags);
++}
++
++static void do_pio_read(struct ftsdc_host *host)
++{
++ u32 fifo;
++ u32 fifo_words;
++ u32 *ptr;
++ u32 status;
++ u32 retry = 0;
++
++
++ BUG_ON(host->buf_bytes != 0);
++
++ while (host->buf_sgptr < host->mrq->data->sg_len) {
++ get_data_buffer(host);
++
++ dbg(host, dbg_pio,
++ "pio_read(): new target: [%i]@[%p]\n",
++ host->buf_bytes, host->buf_ptr);
++
++ while (host->buf_bytes) {
++ status = REG_READ(SDC_STATUS_REG);
++
++ if (status & SDC_STATUS_REG_FIFO_OVERRUN) {
++ fifo = host->fifo_len > host->buf_bytes ?
++ host->buf_bytes : host->fifo_len;
++
++#if 1
++ dbg(host, dbg_pio,
++ "pio_read(): fifo:[%02i] buffer:[%03i] dcnt:[%08X]\n",
++ fifo, host->buf_bytes,
++ REG_READ(SDC_DATA_LEN_REG));
++#endif
++
++ host->buf_bytes -= fifo;
++ host->buf_count += fifo;
++
++ fifo_words = fifo >> 2;
++ ptr = host->buf_ptr;
++ while (fifo_words--)
++ *ptr++ = REG_READ(SDC_DATA_WINDOW_REG);
++
++ host->buf_ptr = ptr;
++ //ADD by river 2010.10.26 for adding some delays for SD card to put data into FIFO again
++ //mdelay(1);
++ udelay(800);
++ //End ADD by river 2010.10.26 for adding some delays for SD card to put data into FIFO again
++
++ /* sdio allow non-power-of-2 blksz */
++ if (fifo & 3) {
++ u32 n = fifo & 3;
++ u32 data = REG_READ(SDC_DATA_WINDOW_REG);
++ u8 *p = (u8 *)host->buf_ptr;
++
++ while (n--) {
++ *p++ = data;
++ data >>= 8;
++ }
++ }
++ } else {
++ udelay(1);
++ if (++retry >= SDC_PIO_RETRY) {
++ host->mrq->data->error = -EIO;
++ goto err;
++ }
++ }
++ }
++ }
++
++err:
++
++ host->buf_active = XFER_NONE;
++ host->complete_what = COMPLETION_FINALIZE;
++}
++
++static void do_pio_write(struct ftsdc_host *host)
++{
++ u32 fifo;
++ u32 *ptr;
++ u32 status;
++ u32 retry = 0;
++
++ BUG_ON(host->buf_bytes != 0);
++
++ while (host->buf_sgptr < host->mrq->data->sg_len) {
++ get_data_buffer(host);
++
++ dbg(host, dbg_pio,
++ "pio_write(): new source: [%i]@[%p]\n",
++ host->buf_bytes, host->buf_ptr);
++
++ while (host->buf_bytes) {
++ status = REG_READ(SDC_STATUS_REG);
++ if (status & SDC_STATUS_REG_FIFO_UNDERRUN) {
++ fifo = host->fifo_len > host->buf_bytes ?
++ host->buf_bytes : host->fifo_len;
++
++ dbg(host, dbg_pio,
++ "pio_write(): fifo:[%02i] buffer:[%03i] dcnt:[%08X]\n",
++ fifo, host->buf_bytes,
++ REG_READ(SDC_DATA_LEN_REG));
++
++ host->buf_bytes -= fifo;
++ host->buf_count += fifo;
++
++ fifo = (fifo + 3) >> 2;
++ ptr = host->buf_ptr;
++ while (fifo--) {
++ REG_WRITE(*ptr, SDC_DATA_WINDOW_REG);
++ ptr++;
++ }
++ host->buf_ptr = ptr;
++ } else {
++ udelay(1);
++ if (++retry >= SDC_PIO_RETRY) {
++ host->mrq->data->error = -EIO;
++ goto err;
++ }
++ }
++ }
++ }
++
++err:
++ host->buf_active = XFER_NONE;
++ host->complete_what = COMPLETION_FINALIZE;
++}
++
++static void do_dma_access(struct ftsdc_host *host)
++{
++ int res;
++ unsigned long timeout;
++ dmad_chreq *req = host->dma_req;
++ dmad_drb *drb = 0;
++
++ while (host->buf_sgptr < host->mrq->data->sg_len) {
++
++ INIT_COMPLETION(host->dma_complete);
++ get_data_buffer(host);
++
++ dbg(host, dbg_dma,
++ "dma_%s(): new target: [%i]@[%p]\n",
++ host->buf_active == XFER_READ ? "read" : "write",
++ host->buf_bytes, host->buf_ptr);
++
++ res = dmad_alloc_drb(req, &drb);
++ if (res != 0 || (drb == 0)) {
++ dbg(host, dbg_err, "%s() Failed to allocate dma request block!\n", __func__);
++ host->mrq->data->error = -ENODEV;
++ goto err;
++ }
++
++ drb->addr0 = SDC_FTSDC010_0_PA_BASE + SDC_DATA_WINDOW_REG;
++ drb->addr1 = (dma_addr_t)host->buf_ptr;
++ drb->req_cycle = dmad_bytes_to_cycles(req, host->buf_bytes);
++ drb->sync = &host->dma_complete;
++
++ timeout = SDC_TIMEOUT_BASE*((host->buf_bytes+511)>>9);
++
++ res = dmad_submit_request(req, drb, 1);
++ if (res != 0) {
++ dbg(host, dbg_err, "%s() Failed to submit dma request block!\n", __func__);
++ host->mrq->data->error = -ENODEV;
++ goto err;
++ }
++
++ dbg(host, dbg_err, "reach here!\n");
++ if (wait_for_completion_timeout(&host->dma_complete, timeout) == 0) {
++ dbg(host, dbg_err, "%s: read timeout\n", __func__);
++ host->mrq->data->error = -ETIMEDOUT;
++ goto err;
++ }
++ }
++
++ host->dma_finish = true;
++err:
++ host->buf_active = XFER_NONE;
++ host->complete_what = COMPLETION_FINALIZE;
++}
++
++static void ftsdc_work(struct work_struct *work)
++{
++ struct ftsdc_host *host =
++ container_of(work, struct ftsdc_host, work);
++
++ ftsdc_enable_irq(host, false);
++
++ if (host->dodma) {
++ do_dma_access(host);
++ } else {
++ if (host->buf_active == XFER_WRITE)
++ do_pio_write(host);
++
++ if (host->buf_active == XFER_READ)
++ do_pio_read(host);
++ }
++
++ tasklet_schedule(&host->pio_tasklet);
++ ftsdc_enable_irq(host, true);
++}
++
++
++static void pio_tasklet(unsigned long data)
++{
++ struct ftsdc_host *host = (struct ftsdc_host *) data;
++
++ if (host->complete_what == COMPLETION_XFER_PROGRESS) {
++ queue_work(mywq, (struct work_struct *)&host->work);
++ return;
++ }
++
++ if (host->complete_what == COMPLETION_FINALIZE) {
++ clear_imask(host);
++ if (host->buf_active != XFER_NONE) {
++ dbg(host, dbg_err, "unfinished %s "
++ "- buf_count:[%u] buf_bytes:[%u]\n",
++ (host->buf_active == XFER_READ) ? "read" : "write",
++ host->buf_count, host->buf_bytes);
++
++ if (host->mrq->data)
++ host->mrq->data->error = -EINVAL;
++ }
++
++ finalize_request(host);
++ }
++}
++
++
++static void finalize_request(struct ftsdc_host *host)
++{
++ struct mmc_request *mrq = host->mrq;
++ struct mmc_command *cmd;
++ u32 con;
++ int debug_as_failure = 0;
++
++ if (host->complete_what != COMPLETION_FINALIZE)
++ return;
++
++ if (!mrq)
++ return;
++
++ cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd;
++
++ if (cmd->data && (cmd->error == 0) &&
++ (cmd->data->error == 0)) {
++ if (host->dodma && (!host->dma_finish)) {
++ dbg(host, dbg_dma, "DMA Missing (%d)!\n",
++ host->dma_finish);
++ return;
++ }
++ host->dodma = false;
++ }
++
++ /* Read response from controller. */
++ if (cmd->flags & MMC_RSP_136) {
++ cmd->resp[3] = REG_READ(SDC_RESPONSE0_REG);
++ cmd->resp[2] = REG_READ(SDC_RESPONSE1_REG);
++ cmd->resp[1] = REG_READ(SDC_RESPONSE2_REG);
++ cmd->resp[0] = REG_READ(SDC_RESPONSE3_REG);
++ } else if (cmd->flags & MMC_RSP_PRESENT) {
++ cmd->resp[0] = REG_READ(SDC_RESPONSE0_REG);
++ }
++
++ if (cmd->error)
++ debug_as_failure = 1;
++
++ if (cmd->data && cmd->data->error)
++ debug_as_failure = 1;
++
++ dbg_dumpcmd(host, cmd, debug_as_failure);
++
++ clear_imask(host);
++ con = REG_READ(SDC_STATUS_REG);
++ con &= ~SDC_CLEAR_REG_SDIO_INTR;
++ REG_WRITE(con, SDC_CLEAR_REG);
++
++ if (cmd->data && cmd->error)
++ cmd->data->error = cmd->error;
++
++ if (cmd->data && cmd->data->stop && (!host->cmd_is_stop)) {
++ host->cmd_is_stop = 1;
++ ftsdc_send_request(host->mmc);
++ return;
++ }
++
++ /* If we have no data transfer we are finished here */
++ if (!mrq->data)
++ goto request_done;
++
++ /* Calulate the amout of bytes transfer if there was no error */
++ if (mrq->data->error == 0) {
++ mrq->data->bytes_xfered =
++ (mrq->data->blocks * mrq->data->blksz);
++ } else {
++ mrq->data->bytes_xfered = 0;
++ }
++
++request_done:
++ host->complete_what = COMPLETION_NONE;
++ host->mrq = NULL;
++
++ host->last_opcode = mrq->cmd->opcode;
++ mmc_request_done(host->mmc, mrq);
++}
++
++static void ftsdc_send_command(struct ftsdc_host *host,
++ struct mmc_command *cmd)
++{
++ u32 ccon = 0;
++ u32 newmask = 0;
++ u32 scon;
++
++ if (cmd->data) {
++ host->complete_what = COMPLETION_XFER_PROGRESS;
++ newmask |= SDC_INT_MASK_REG_RSP_TIMEOUT;
++ } else if (cmd->flags & MMC_RSP_PRESENT) {
++ host->complete_what = COMPLETION_RSPFIN;
++ newmask |= SDC_INT_MASK_REG_RSP_TIMEOUT;
++ } else {
++ host->complete_what = COMPLETION_CMDSENT;
++ newmask |= SDC_INT_MASK_REG_CMD_SEND;
++ }
++
++ ccon |= cmd->opcode & SDC_CMD_REG_INDEX;
++ ccon |= SDC_CMD_REG_CMD_EN;
++
++ if (cmd->flags & MMC_RSP_PRESENT) {
++ ccon |= SDC_CMD_REG_NEED_RSP;
++ newmask |= SDC_INT_MASK_REG_RSP_CRC_OK |
++ SDC_INT_MASK_REG_RSP_CRC_FAIL;
++ }
++
++ if (cmd->flags & MMC_RSP_136)
++ ccon |= SDC_CMD_REG_LONG_RSP;
++
++ /* applicatiion specific cmd must follow an MMC_APP_CMD. The
++ * value will be updated in finalize_request function */
++ if (host->last_opcode == MMC_APP_CMD)
++ ccon |= SDC_CMD_REG_APP_CMD;
++
++ enable_imask(host, newmask);
++ REG_WRITE(cmd->arg, SDC_ARGU_REG);
++
++ scon = REG_READ(SDC_SDIO_CTRL1_REG);
++ if (host->mmc->card != NULL && mmc_card_sdio(host->mmc->card))
++ scon |= SDC_SDIO_CTRL1_REG_SDIO_ENABLE;
++ else
++ scon &= ~SDC_SDIO_CTRL1_REG_SDIO_ENABLE;
++ REG_WRITE(scon, SDC_SDIO_CTRL1_REG);
++
++ dbg_dumpregs(host, "");
++ dbg(host, dbg_debug, "CON[%x]\n", ccon);
++
++ REG_WRITE(ccon, SDC_CMD_REG);
++}
++
++static int ftsdc_setup_data(struct ftsdc_host *host, struct mmc_data *data)
++{
++ u32 dcon, newmask = 0;
++
++ /* configure data transfer paramter */
++
++ if (!data)
++ return 0;
++ if(host->mmc->card && host->mmc->card->type==(unsigned int)MMC_TYPE_SD){
++ if (((data->blksz - 1) & data->blksz) != 0) {
++ pr_warning("%s: can't do non-power-of 2 sized block transfers (blksz %d)\n", __func__, data->blksz);
++ return -EINVAL;
++ }
++ }
++
++ if (data->blksz <= 2) {
++ /* We cannot deal with unaligned blocks with more than
++ * one block being transfered. */
++
++ if (data->blocks > 1) {
++ pr_warning("%s: can't do non-word sized block transfers (blksz %d)\n", __func__, data->blksz);
++ return -EINVAL;
++ }
++ }
++
++ /* data length */
++ dcon = data->blksz * data->blocks;
++ REG_WRITE(dcon, SDC_DATA_LEN_REG);
++
++ /* write data control */
++ dcon = 0;
++ dcon = cal_blksz(data->blksz);
++
++ /* enable UNDERFUN will trigger interrupt immediatedly
++ * So setup it when rsp is received successfully
++ */
++ if (data->flags & MMC_DATA_WRITE) {
++ dcon |= SDC_DATA_CTRL_REG_DATA_WRITE;
++ } else {
++ dcon &= ~SDC_DATA_CTRL_REG_DATA_WRITE;
++ newmask |= SDC_INT_MASK_REG_FIFO_OVERRUN;
++ }
++
++ /* always reset fifo since last transfer may fail */
++ dcon |= SDC_DATA_CTRL_REG_FIFO_RST;
++
++ /* enable data transfer which will be pended until cmd is send */
++ dcon |= SDC_DATA_CTRL_REG_DATA_EN;
++
++ if (ftsdc_dmaexist(host) &&
++ ((data->blksz * data->blocks) & 0xf) == 0) {
++ newmask &= ~SDC_INT_MASK_REG_FIFO_OVERRUN;
++ dcon |= SDC_DATA_CTRL_REG_DMA_EN;
++ dcon |= SDC_DMA_TYPE_4;
++ host->dodma = true;
++
++ }
++
++ REG_WRITE(dcon, SDC_DATA_CTRL_REG);
++
++ /* add to IMASK register */
++ newmask |= SDC_INT_MASK_REG_DATA_CRC_FAIL |
++ SDC_INT_MASK_REG_DATA_TIMEOUT;
++
++ enable_imask(host, newmask);
++
++ /* handle sdio */
++ dcon = SDC_SDIO_CTRL1_REG_READ_WAIT_ENABLE & REG_READ(SDC_SDIO_CTRL1_REG);
++ dcon |= data->blksz | data->blocks << 15;
++ if (1 < data->blocks)
++ dcon |= SDC_SDIO_CTRL1_REG_SDIO_BLK_MODE;
++ REG_WRITE(dcon, SDC_SDIO_CTRL1_REG);
++
++ return 0;
++}
++
++#define BOTH_DIR (MMC_DATA_WRITE | MMC_DATA_READ)
++
++static int ftsdc_prepare_buffer(struct ftsdc_host *host, struct mmc_data *data)
++{
++ int rw = (data->flags & MMC_DATA_WRITE) ? 1 : 0;
++
++ if ((!host->mrq) || (!host->mrq->data))
++ return -EINVAL;
++
++ BUG_ON((data->flags & BOTH_DIR) == BOTH_DIR);
++
++ host->buf_sgptr = 0;
++ host->buf_bytes = 0;
++ host->buf_count = 0;
++ host->buf_active = rw ? XFER_WRITE : XFER_READ;
++
++ if (host->dodma) {
++ u32 dma_len;
++ u32 drb_size;
++ dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
++ rw ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
++ if (dma_len == 0)
++ return -ENOMEM;
++
++
++ dmad_config_channel_dir(host->dma_req,
++ rw ? DMAD_DIR_A1_TO_A0 : DMAD_DIR_A0_TO_A1);
++
++ drb_size = dmad_max_size_per_drb(host->dma_req);
++ if (drb_size < (data->blksz & data->blocks))
++ return -ENODEV;
++
++ host->dma_finish = false;
++ }
++
++ return 0;
++}
++
++static irqreturn_t ftsdc_irq(int irq, void *dev_id)
++{
++ struct ftsdc_host *host = dev_id;
++ struct mmc_command *cmd;
++ u32 mci_status;
++ u32 mci_clear;
++ u32 mci_imsk;
++ unsigned long iflags;
++
++ mci_status = REG_READ(SDC_STATUS_REG);
++ mci_imsk = REG_READ(SDC_INT_MASK_REG);
++
++ dbg(host, dbg_debug, "irq: status:0x%08x, mask : %08x\n", mci_status, mci_imsk);
++
++ if (mci_status & SDC_STATUS_REG_SDIO_INTR) {
++ if (mci_imsk & SDC_INT_MASK_REG_SDIO_INTR) {
++ mci_clear = SDC_CLEAR_REG_SDIO_INTR;
++ REG_WRITE(mci_clear, SDC_CLEAR_REG);
++
++ mmc_signal_sdio_irq(host->mmc);
++ return IRQ_HANDLED;
++ }
++ }
++
++ spin_lock_irqsave(&host->complete_lock, iflags);
++
++ mci_status = REG_READ(SDC_STATUS_REG);
++ mci_clear = 0;
++
++ if (mci_status & SDC_STATUS_REG_CARD_CHANGE) {
++ if ((mci_status & SDC_STATUS_REG_CARD_DETECT)
++ == SDC_CARD_INSERT) {
++ host->status = "card insert";
++ mmc_detect_change(host->mmc, msecs_to_jiffies(500));
++ } else {
++ host->status = "card remove";
++ }
++
++ mci_clear |= SDC_CLEAR_REG_CARD_CHANGE;
++ dbg(host, dbg_irq, "%s\n", host->status);
++
++ if (host->complete_what != COMPLETION_NONE) {
++ host->mrq->cmd->error = -EIO;
++ goto close_transfer;
++ }
++
++ goto irq_out;
++ }
++
++ if ((host->complete_what == COMPLETION_NONE) ||
++ (host->complete_what == COMPLETION_FINALIZE)) {
++ host->status = "nothing to complete";
++ mci_clear = -1u;
++ goto irq_out;
++ }
++
++ if (!host->mrq) {
++ host->status = "no active mrq";
++ clear_imask(host);
++ goto irq_out;
++ }
++
++ cmd = host->cmd_is_stop ? host->mrq->stop : host->mrq->cmd;
++
++ if (!cmd) {
++ host->status = "no active cmd";
++ clear_imask(host);
++ goto irq_out;
++ }
++
++ if (mci_status & SDC_STATUS_REG_CMD_SEND) {
++ mci_clear |= SDC_CLEAR_REG_CMD_SEND;
++
++ if (host->complete_what == COMPLETION_CMDSENT) {
++ host->status = "ok: command sent";
++ goto close_transfer;
++ } else {
++ host->status = "error: command sent(status not match)";
++ cmd->error = -EINVAL;
++ goto fail_transfer;
++ }
++ }
++
++ /* handle error status */
++ if (mci_status & SDC_STATUS_REG_RSP_TIMEOUT) {
++ dbg(host, dbg_err, "CMDSTAT: error RSP TIMEOUT\n");
++ mci_clear |= SDC_CLEAR_REG_RSP_TIMEOUT;
++ cmd->error = -ETIMEDOUT;
++ host->status = "error: response timeout";
++ goto fail_transfer;
++ }
++
++ if (mci_status & SDC_STATUS_REG_RSP_CRC_FAIL) {
++ mci_clear |= SDC_CLEAR_REG_RSP_CRC_FAIL;
++ /* This is wierd hack */
++ if (cmd->flags & MMC_RSP_CRC) {
++ dbg(host, dbg_err, "CMDSTAT: error RSP CRC\n");
++ cmd->error = -EILSEQ;
++ host->status = "error: RSP CRC failed";
++ goto fail_transfer;
++ } else {
++ host->status = "R3 or R4 type command";
++ goto close_transfer;
++ }
++ }
++
++ if (mci_status & SDC_STATUS_REG_RSP_CRC_OK) {
++ mci_clear |= SDC_CLEAR_REG_RSP_CRC_OK;
++
++ if (host->complete_what == COMPLETION_XFER_PROGRESS) {
++ REG_WRITE(mci_clear, SDC_CLEAR_REG);
++
++ host->status = "RSP recv OK";
++ if (!cmd->data)
++ goto close_transfer;
++
++ if (host->dodma) {
++ tasklet_schedule(&host->pio_tasklet);
++ host->status = "dma access";
++ goto irq_out;
++ }
++
++ if (host->buf_active == XFER_WRITE)
++ enable_imask(host, SDC_INT_MASK_REG_FIFO_UNDERRUN);
++ } else if (host->complete_what == COMPLETION_RSPFIN) {
++ goto close_transfer;
++ }
++ }
++
++ /* handler data transfer */
++ if (mci_status & SDC_STATUS_REG_DATA_TIMEOUT) {
++ dbg(host, dbg_err, "CMDSTAT: error DATA TIMEOUT\n");
++ mci_clear |= SDC_CLEAR_REG_DATA_TIMEOUT;
++ cmd->error = -ETIMEDOUT;
++ host->status = "error: data timeout";
++ goto fail_transfer;
++ }
++
++ if (mci_status & SDC_STATUS_REG_DATA_CRC_FAIL) {
++ dbg(host, dbg_err, "CMDSTAT: error DATA CRC\n");
++ mci_clear |= SDC_CLEAR_REG_DATA_CRC_FAIL;
++ cmd->error = -EILSEQ;
++ host->status = "error: data CRC fail";
++ goto fail_transfer;
++ }
++
++ if ((mci_status & SDC_STATUS_REG_FIFO_UNDERRUN) ||
++ mci_status & SDC_STATUS_REG_FIFO_OVERRUN) {
++
++ disable_imask(host, SDC_INT_MASK_REG_FIFO_OVERRUN |
++ SDC_INT_MASK_REG_FIFO_UNDERRUN);
++
++ if (!host->dodma) {
++ if (host->buf_active == XFER_WRITE) {
++ tasklet_schedule(&host->pio_tasklet);
++ host->status = "pio tx";
++ } else if (host->buf_active == XFER_READ) {
++
++ tasklet_schedule(&host->pio_tasklet);
++ host->status = "pio rx";
++ }
++ }
++ }
++
++ goto irq_out;
++
++fail_transfer:
++ host->buf_active = XFER_NONE;
++
++close_transfer:
++ host->complete_what = COMPLETION_FINALIZE;
++
++ clear_imask(host);
++ tasklet_schedule(&host->pio_tasklet);
++
++irq_out:
++ REG_WRITE(mci_clear, SDC_CLEAR_REG);
++
++ dbg(host, dbg_debug, "irq: %s\n", host->status);
++ spin_unlock_irqrestore(&host->complete_lock, iflags);
++ return IRQ_HANDLED;
++}
++
++static void ftsdc_send_request(struct mmc_host *mmc)
++{
++ struct ftsdc_host *host = mmc_priv(mmc);
++ struct mmc_request *mrq = host->mrq;
++ struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd;
++
++ host->ccnt++;
++ prepare_dbgmsg(host, cmd, host->cmd_is_stop);
++ dbg(host, dbg_debug, "%s\n", host->dbgmsg_cmd);
++
++ if (cmd->data) {
++ int res = ftsdc_setup_data(host, cmd->data);
++
++ host->dcnt++;
++
++ if (res) {
++ dbg(host, dbg_err, "setup data error %d\n", res);
++ cmd->error = res;
++ cmd->data->error = res;
++
++ mmc_request_done(mmc, mrq);
++ return;
++ }
++
++ res = ftsdc_prepare_buffer(host, cmd->data);
++
++ if (res) {
++ dbg(host, dbg_err, "data prepare error %d\n", res);
++ cmd->error = res;
++ cmd->data->error = res;
++
++ mmc_request_done(mmc, mrq);
++ return;
++ }
++ }
++
++ /* Send command */
++ ftsdc_send_command(host, cmd);
++}
++
++static int ftsdc_get_cd(struct mmc_host *mmc)
++{
++ struct ftsdc_host *host = mmc_priv(mmc);
++
++ u32 con = REG_READ(SDC_STATUS_REG);
++ dbg(host, dbg_debug, "get_cd status:%.8x\n\n", con);
++
++ return (con & SDC_STATUS_REG_CARD_DETECT) ? 0 : 1;
++}
++
++static void ftsdc_request(struct mmc_host *mmc, struct mmc_request *mrq)
++{
++ struct ftsdc_host *host = mmc_priv(mmc);
++
++/* work_around_for_amerald(mrq);*/
++ host->status = "mmc request";
++ host->cmd_is_stop = 0;
++ host->mrq = mrq;
++ if (ftsdc_get_cd(mmc) == 0) {
++ dbg(host, dbg_err, "%s: no medium present\n", __func__);
++ host->mrq->cmd->error = -ENOMEDIUM;
++ mmc_request_done(mmc, mrq);
++ } else {
++ ftsdc_send_request(mmc);
++ }
++
++ dbg(host, dbg_debug, "send request \n");
++}
++
++static void ftsdc_set_clk(struct ftsdc_host *host, struct mmc_ios *ios)
++{
++ u32 clk_div = 0;
++ u32 con;
++
++ dbg(host, dbg_debug, "request clk : %u \n", ios->clock);
++ con = REG_READ(SDC_CLOCK_CTRL_REG);
++ if (ios->clock == 0) {
++ host->real_rate = 0;
++ con |= SDC_CLOCK_CTRL_REG_CLK_DIS;
++ } else {
++ clk_div = (APB_CLK_IN / (ios->clock << 1)) - 1;
++ host->real_rate = APB_CLK_IN / ((clk_div+1)<<1);
++ if (host->real_rate > ios->clock) {
++ ++clk_div;
++ host->real_rate = APB_CLK_IN / ((clk_div+1)<<1);
++ }
++ if (clk_div > 127)
++ dbg(host, dbg_err, "%s: no match clock rate, %u\n", __func__, ios->clock);
++
++ con = (con & ~SDC_CLOCK_CTRL_REG_CLK_DIV) | (clk_div & SDC_CLOCK_CTRL_REG_CLK_DIV);
++ con &= ~SDC_CLOCK_CTRL_REG_CLK_DIS;
++ }
++
++ REG_WRITE(con, SDC_CLOCK_CTRL_REG);
++}
++
++static void ftsdc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
++{
++ struct ftsdc_host *host = mmc_priv(mmc);
++ u32 con;
++
++ con = REG_READ(SDC_POWER_CTRL_REG);
++ switch (ios->power_mode) {
++ case MMC_POWER_ON:
++ case MMC_POWER_UP:
++ con |= SDC_POWER_CTRL_REG_POWER_ON;
++ break;
++ case MMC_POWER_OFF:
++ default:
++ con &= ~SDC_POWER_CTRL_REG_POWER_ON;
++ break;
++ }
++
++ REG_WRITE(con, SDC_POWER_CTRL_REG);
++
++ ftsdc_set_clk(host, ios);
++
++ if ((ios->power_mode == MMC_POWER_ON) ||
++ (ios->power_mode == MMC_POWER_UP)) {
++ dbg(host, dbg_debug, "running at %ukHz (requested: %ukHz).\n",
++ host->real_rate/1000, ios->clock/1000);
++ } else {
++ dbg(host, dbg_debug, "powered down.\n");
++ }
++
++ host->bus_width = ios->bus_width;
++ /* write bus configure */
++ con = REG_READ(SDC_BUS_WIDTH_REG);
++
++ con &= ~(SDC_BUS_WIDTH_REG_SINGLE_BUS |
++ SDC_BUS_WIDTH_REG_WIDE_4_BUS |
++ SDC_BUS_WIDTH_REG_WIDE_8_BUS);
++ if (host->bus_width == MMC_BUS_WIDTH_1)
++ con |= SDC_BUS_WIDTH_REG_SINGLE_BUS;
++ else if (host->bus_width == MMC_BUS_WIDTH_4)
++ con |= SDC_BUS_WIDTH_REG_WIDE_4_BUS;
++ else if (host->bus_width == MMC_BUS_WIDTH_8)
++ con |= SDC_BUS_WIDTH_REG_WIDE_8_BUS;
++ else {
++ dbg(host, dbg_err, "set_ios: can't support bus mode");
++ }
++ REG_WRITE(con, SDC_BUS_WIDTH_REG);
++
++ /*set rsp and data timeout */
++ con = -1;
++ REG_WRITE(con, SDC_DATA_TIMER_REG);
++}
++
++static int ftsdc_get_ro(struct mmc_host *mmc)
++{
++ struct ftsdc_host *host = mmc_priv(mmc);
++ u32 con = REG_READ(SDC_STATUS_REG);
++ dbg(host, dbg_debug, "get_ro status:%.8x\n", con);
++
++ return (con & SDC_STATUS_REG_CARD_LOCK) ? 1 : 0;
++}
++
++
++static void ftsdc_enable_sdio_irq(struct mmc_host *mmc, int enable)
++{
++ struct ftsdc_host *host = mmc_priv(mmc);
++ unsigned long flags;
++ u32 con;
++#ifdef CONFIG_MMC_DEBUG
++ u32 ena;
++#endif
++
++ local_irq_save(flags);
++
++ con = REG_READ(SDC_INT_MASK_REG);
++#ifdef CONFIG_MMC_DEBUG
++ ena = (con & SDC_STATUS_REG_SDIO_INTR) ? 1:0;
++ if (ena == enable)
++ printk("\n*** XXX ***\n");
++#endif
++
++ con = enable ? (con | SDC_STATUS_REG_SDIO_INTR) : (con & ~SDC_STATUS_REG_SDIO_INTR);
++ REG_WRITE(con, SDC_INT_MASK_REG);
++
++#ifdef CONFIG_MMC_DEBUG
++ //check and ensure data out to SD host controller
++ ena = (REG_READ(SDC_INT_MASK_REG) & SDC_STATUS_REG_SDIO_INTR) ? 1:0;
++ if (ena != enable) {
++ printk("\n*** YYY ***\n");
++ }
++#endif
++
++ local_irq_restore(flags);
++}
++
++static struct mmc_host_ops ftsdc_ops = {
++ .request = ftsdc_request,
++ .set_ios = ftsdc_set_ios,
++ .get_ro = ftsdc_get_ro,
++ .get_cd = ftsdc_get_cd,
++ .enable_sdio_irq = ftsdc_enable_sdio_irq,
++};
++
++#ifdef CONFIG_DEBUG_FS
++
++static int ftsdc_state_show(struct seq_file *seq, void *v)
++{
++ struct ftsdc_host *host = seq->private;
++
++ seq_printf(seq, "Register base = 0x%08x\n", (u32)host->base);
++ seq_printf(seq, "Clock rate = %u\n", host->real_rate);
++ seq_printf(seq, "host status = %s\n", host->status);
++ seq_printf(seq, "IRQ = %d\n", host->irq);
++ seq_printf(seq, "IRQ enabled = %d\n", host->irq_enabled);
++ seq_printf(seq, "complete what = %d\n", host->complete_what);
++ seq_printf(seq, "dma support = %d\n", ftsdc_dmaexist(host));
++ seq_printf(seq, "use dma = %d\n", host->dodma);
++
++ return 0;
++}
++
++static int ftsdc_state_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, ftsdc_state_show, inode->i_private);
++}
++
++static const struct file_operations ftsdc_fops_state = {
++ .owner = THIS_MODULE,
++ .open = ftsdc_state_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++#define DBG_REG(_r) { .addr = SDC_## _r ## _REG, .name = #_r }
++
++struct ftsdc_reg {
++ unsigned short addr;
++ unsigned char *name;
++} debug_regs[] = {
++ DBG_REG(CMD),
++ DBG_REG(ARGU),
++ DBG_REG(RESPONSE0),
++ DBG_REG(RESPONSE1),
++ DBG_REG(RESPONSE2),
++ DBG_REG(RESPONSE3),
++ DBG_REG(RSP_CMD),
++ DBG_REG(DATA_CTRL),
++ DBG_REG(DATA_TIMER),
++ DBG_REG(DATA_LEN),
++ DBG_REG(STATUS),
++ DBG_REG(CLEAR),
++ DBG_REG(INT_MASK),
++ DBG_REG(POWER_CTRL),
++ DBG_REG(CLOCK_CTRL),
++ DBG_REG(BUS_WIDTH),
++ DBG_REG(SDIO_CTRL1),
++ DBG_REG(SDIO_CTRL2),
++ DBG_REG(SDIO_STATUS),
++ DBG_REG(FEATURE),
++ DBG_REG(REVISION),
++ {}
++};
++
++static int ftsdc_regs_show(struct seq_file *seq, void *v)
++{
++ struct ftsdc_host *host = seq->private;
++ struct ftsdc_reg *rptr = debug_regs;
++
++ for (; rptr->name; rptr++)
++ seq_printf(seq, "SDI%s\t=0x%08x\n", rptr->name,
++ REG_READ(rptr->addr));
++
++ return 0;
++}
++
++static int ftsdc_regs_open(struct inode *inode, struct file *file)
++{
++ return single_open(file, ftsdc_regs_show, inode->i_private);
++}
++
++static const struct file_operations ftsdc_fops_regs = {
++ .owner = THIS_MODULE,
++ .open = ftsdc_regs_open,
++ .read = seq_read,
++ .llseek = seq_lseek,
++ .release = single_release,
++};
++
++static void ftsdc_debugfs_attach(struct ftsdc_host *host)
++{
++ struct device *dev = &host->pdev->dev;
++
++ host->debug_root = debugfs_create_dir(dev_name(dev), NULL);
++ if (IS_ERR(host->debug_root)) {
++ dev_err(dev, "failed to create debugfs root\n");
++ return;
++ }
++
++ host->debug_state = debugfs_create_file("state", 0444,
++ host->debug_root, host,
++ &ftsdc_fops_state);
++
++ if (IS_ERR(host->debug_state))
++ dev_err(dev, "failed to create debug state file\n");
++
++ host->debug_regs = debugfs_create_file("regs", 0444,
++ host->debug_root, host,
++ &ftsdc_fops_regs);
++
++ if (IS_ERR(host->debug_regs))
++ dev_err(dev, "failed to create debug regs file\n");
++}
++
++static void ftsdc_debugfs_remove(struct ftsdc_host *host)
++{
++ debugfs_remove(host->debug_regs);
++ debugfs_remove(host->debug_state);
++ debugfs_remove(host->debug_root);
++}
++
++#else
++static inline void ftsdc_debugfs_attach(struct ftsdc_host *host) { }
++static inline void ftsdc_debugfs_remove(struct ftsdc_host *host) { }
++
++#endif /* CONFIG_DEBUG_FS */
++
++#if (defined(CONFIG_PLATFORM_AHBDMA) || defined(CONFIG_PLATFORM_APBDMA))
++static int ftsdc_alloc_dma(struct ftsdc_host *host)
++{
++ dmad_chreq *req = host->dma_req;
++
++ req = kzalloc(sizeof(dmad_chreq), GFP_KERNEL);
++#ifdef CONFIG_PLATFORM_APBDMA
++#ifdef CONFIG_PLAT_AG102
++ //ADD by river 2010.10.20
++ outl(inl(PCU_VA_BASE + 0x38) | 0x00000300, PCU_VA_BASE + 0x38);
++ //End ADD by river 2010.10.20
++#endif
++ req->apb_req.addr0_ctrl = APBBR_ADDRINC_FIXED; /* (in) APBBR_ADDRINC_xxx */
++/* for amerald */
++ if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID){
++ req->apb_req.addr0_reqn = APBBR_REQN_SDC_AMERALD;
++ }else
++ {
++ req->apb_req.addr0_reqn = APBBR_REQN_SDC; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
++ }
++ req->apb_req.addr1_ctrl = APBBR_ADDRINC_I4X; /* (in) APBBR_ADDRINC_xxx */
++ req->apb_req.addr1_reqn = APBBR_REQN_NONE; /* (in) APBBR_REQN_xxx (also used to help determine bus selection) */
++ req->apb_req.burst_mode = 1; /* (in) Burst mode (0: no burst 1-, 1: burst 4- data cycles per dma cycle) */
++ req->apb_req.data_width = APBBR_DATAWIDTH_4; /* (in) APBBR_DATAWIDTH_4(word), APBBR_DATAWIDTH_2(half-word), APBBR_DATAWIDTH_1(byte) */
++ req->apb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
++ req->controller = DMAD_DMAC_APB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
++ req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
++
++ if (dmad_channel_alloc(req) == 0) {
++ dbg(host, dbg_debug, "%s: APB dma channel allocated (ch: %d)\n", __func__, req->channel);
++ host->dma_req = req;
++ return 0;
++ }
++
++ memset(req, 0, sizeof(dmad_chreq));
++ dbg(host, dbg_info, "%s: APB dma channel allocation failed\n", __func__);
++#endif /* CONFIG_PLATFORM_APBDMA */
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ req->ahb_req.sync = 1; /* (in) non-zero if src and dst have different clock domain */
++ req->ahb_req.priority = DMAC_CSR_CHPRI_1; /* (in) DMAC_CSR_CHPRI_0 (lowest) ~ DMAC_CSR_CHPRI_3 (highest) */
++ req->ahb_req.hw_handshake = 1; /* (in) non-zero to enable hardware handshake mode */
++ req->ahb_req.burst_size = DMAC_CSR_SIZE_4; /* (in) DMAC_CSR_SIZE_1 ~ DMAC_CSR_SIZE_256 */
++ req->ahb_req.addr0_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
++ req->ahb_req.addr0_ctrl = DMAC_CSR_AD_FIX; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
++ req->ahb_req.addr0_reqn = DMAC_REQN_SDC; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
++ req->ahb_req.addr1_width = DMAC_CSR_WIDTH_32; /* (in) DMAC_CSR_WIDTH_8, DMAC_CSR_WIDTH_16, or DMAC_CSR_WIDTH_32 */
++ req->ahb_req.addr1_ctrl = DMAC_CSR_AD_INC; /* (in) DMAC_CSR_AD_INC, DMAC_CSR_AD_DEC, or DMAC_CSR_AD_FIX */
++ req->ahb_req.addr1_reqn = DMAC_REQN_NONE; /* (in) DMAC_REQN_xxx (also used to help determine channel number) */
++ req->ahb_req.tx_dir = DMAD_DIR_A0_TO_A1; /* (in) DMAD_DIR_A0_TO_A1, DMAD_DIR_A1_TO_A0 */
++
++ req->controller = DMAD_DMAC_AHB_CORE; /* (in) DMAD_DMAC_AHB_CORE, DMAD_DMAC_APB_CORE */
++ req->flags = DMAD_FLAGS_SLEEP_BLOCK | DMAD_FLAGS_BIDIRECTION;
++
++ if (dmad_channel_alloc(req) == 0) {
++ dbg(host, dbg_debug, "%s: AHB dma channel allocated (ch: %d)\n", __func__, req->channel);
++ host->dma_req = req;
++ return 0;
++ }
++
++ dbg(host, dbg_info, "%s: AHB dma channel allocation failed\n", __func__);
++#endif
++
++ kfree(req);
++ return -ENODEV;
++
++}
++#endif
++
++static int __devinit ftsdc_probe(struct platform_device *pdev)
++{
++ struct ftsdc_host *host;
++ struct mmc_host *mmc;
++ int ret = -ENOMEM;
++ u32 con;
++
++ mmc = mmc_alloc_host(sizeof(struct ftsdc_host), &pdev->dev);
++ if (!mmc) {
++// ret = -ENOMEM;
++ goto probe_out;
++ }
++
++ host = mmc_priv(mmc);
++ host->mmc = mmc;
++ host->pdev = pdev;
++
++ mywq = create_workqueue("atcsdc_queue");
++ if (NULL == mywq)
++ goto probe_free_host;
++
++ spin_lock_init(&host->complete_lock);
++ tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
++ init_completion(&host->dma_complete);
++ INIT_WORK(&host->work, ftsdc_work);
++
++ host->complete_what = COMPLETION_NONE;
++ host->buf_active = XFER_NONE;
++
++#if (defined(CONFIG_PLATFORM_AHBDMA) || defined(CONFIG_PLATFORM_APBDMA))
++ ftsdc_alloc_dma(host);
++#endif
++
++ host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
++ if (!host->mem) {
++ dev_err(&pdev->dev,
++ "failed to get io memory region resouce.\n");
++
++ ret = -ENOENT;
++ goto probe_free_host;
++ }
++
++ host->mem = request_mem_region(host->mem->start,
++ resource_size(host->mem), pdev->name);
++
++ if (!host->mem) {
++ dev_err(&pdev->dev, "failed to request io memory region.\n");
++ ret = -ENOENT;
++ goto probe_free_wq;
++ }
++
++ host->base = (void __iomem *) SDC_FTSDC010_0_VA_BASE;
++ host->irq = SDC_FTSDC010_IRQ;
++ if (request_irq(host->irq, ftsdc_irq, IRQF_DISABLED, DRIVER_NAME, host)) {
++ dev_err(&pdev->dev, "failed to request mci interrupt.\n");
++ ret = -ENOENT;
++ goto probe_free_mem_region;
++ }
++ host->irq_enabled = true;
++
++ /* enable card change interruption */
++ con = REG_READ(SDC_INT_MASK_REG);
++ con |= SDC_INT_MASK_REG_CARD_CHANGE;
++ REG_WRITE(con, SDC_INT_MASK_REG);
++
++ con = REG_READ(SDC_BUS_WIDTH_REG);
++
++ mmc->ops = &ftsdc_ops;
++ mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
++
++ if (con & SDC_WIDE_4_BUS_SUPPORT)
++ mmc->caps |= MMC_CAP_4_BIT_DATA;
++ else if (con & SDC_WIDE_8_BUS_SUPPORT)
++ mmc->caps |= MMC_CAP_8_BIT_DATA;
++
++#ifndef A320D_BUILDIN_SDC
++ mmc->caps |= MMC_CAP_SDIO_IRQ;
++#endif
++
++ mmc->f_min = APB_CLK_IN / (2 * 128);
++ mmc->f_max = APB_CLK_IN / 2;
++
++ /* limit SDIO mode max size */
++ mmc->max_req_size = 128 * 1024 * 1024 - 1;
++ mmc->max_blk_size = 2047;
++ mmc->max_req_size = (mmc->max_req_size + 1) / (mmc->max_blk_size + 1);
++ mmc->max_seg_size = mmc->max_req_size;
++ mmc->max_blk_count = (1<<17)-1;
++
++ /* kernel default value. see Doc/block/biodocs.txt */
++ /*
++ 'struct mmc_host' has no member named 'max_phys_segs'
++ 'struct mmc_host' has no member named 'max_hw_segs'
++ */
++// mmc->max_phys_segs = 128;
++// mmc->max_hw_segs = 128;
++
++ /* set fifo lenght and default threshold half */
++ con = REG_READ(SDC_FEATURE_REG);
++ host->fifo_len = (con & SDC_FEATURE_REG_FIFO_DEPTH) * sizeof(u32);
++
++ dbg(host, dbg_debug,
++ "probe: mapped mci_base:%p irq:%u.\n",
++ host->base, host->irq);
++
++ dbg_dumpregs(host, "");
++
++ ret = mmc_add_host(mmc);
++ if (ret) {
++ dev_err(&pdev->dev, "failed to add mmc host.\n");
++ goto probe_free_irq;
++ }
++
++ ftsdc_debugfs_attach(host);
++
++ platform_set_drvdata(pdev, mmc);
++ dev_info(&pdev->dev, "%s - using %s SDIO IRQ\n", mmc_hostname(mmc),
++ mmc->caps & MMC_CAP_SDIO_IRQ ? "hw" : "sw");
++
++ return 0;
++
++ probe_free_irq:
++ free_irq(host->irq, host);
++
++ probe_free_mem_region:
++ release_mem_region(host->mem->start, resource_size(host->mem));
++
++probe_free_wq:
++ destroy_workqueue(mywq);
++
++ probe_free_host:
++ mmc_free_host(mmc);
++
++ probe_out:
++ return ret;
++}
++
++static void ftsdc_shutdown(struct platform_device *pdev)
++{
++ struct mmc_host *mmc = platform_get_drvdata(pdev);
++ struct ftsdc_host *host = mmc_priv(mmc);
++
++ flush_workqueue(mywq);
++ destroy_workqueue(mywq);
++
++ ftsdc_debugfs_remove(host);
++ mmc_remove_host(mmc);
++}
++
++static int __devexit ftsdc_remove(struct platform_device *pdev)
++{
++ struct mmc_host *mmc = platform_get_drvdata(pdev);
++ struct ftsdc_host *host = mmc_priv(mmc);
++
++ ftsdc_shutdown(pdev);
++
++ tasklet_disable(&host->pio_tasklet);
++
++ if (ftsdc_dmaexist(host))
++ kfree(host->dma_req);
++
++ free_irq(host->irq, host);
++
++ release_mem_region(host->mem->start, resource_size(host->mem));
++
++ mmc_free_host(mmc);
++ return 0;
++}
++
++
++#ifdef CONFIG_PM
++static int ftsdc_free_dma(struct ftsdc_host *host)
++{
++ dmad_channel_free(host->dma_req);
++ return 0;
++}
++
++static int ftsdc_suspend(struct platform_device *pdev, pm_message_t state)
++{
++ struct mmc_host *mmc = platform_get_drvdata(pdev);
++ struct ftsdc_host *host = mmc_priv(mmc);
++ int ret = 0;
++ if (mmc) {
++ ftsdc_free_dma(host);
++ ret = mmc_suspend_host(mmc);
++ }
++ return ret;
++
++}
++
++static int ftsdc_resume(struct platform_device *pdev)
++{
++ struct mmc_host *mmc = platform_get_drvdata(pdev);
++ int ret = 0;
++ struct ftsdc_host *host = mmc_priv(mmc);
++ if (mmc) {
++#if (defined(CONFIG_PLATFORM_AHBDMA) || defined(CONFIG_PLATFORM_APBDMA))
++ ftsdc_alloc_dma(host);
++#endif
++ ret = mmc_resume_host(mmc);
++ }
++ return ret;
++}
++
++static void platform_device_release(struct device *dev){
++}
++
++
++#else
++#define ftsdc_suspend NULL
++#define ftsdc_resume NULL
++#endif
++
++
++static struct platform_driver ftsdc_driver = {
++ .driver = {
++ .name = "ftsdc010",
++ .owner = THIS_MODULE,
++ },
++ .probe = ftsdc_probe,
++ .remove = __devexit_p(ftsdc_remove),
++ .shutdown = ftsdc_shutdown,
++ .suspend = ftsdc_suspend,
++ .resume = ftsdc_resume,
++};
++
++static struct resource sdc_resource[] = {
++ [0] = {
++ .start = SDC_FTSDC010_0_VA_BASE,
++ .end = SDC_FTSDC010_0_VA_BASE + 0x1000 - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ [1] = {
++ .start = SDC_FTSDC010_0_IRQ,
++ .flags = IORESOURCE_IRQ,
++ }
++
++};
++
++struct platform_device sdc_device = {
++ .name = "ftsdc010",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(sdc_resource),
++ .resource = sdc_resource,
++ .dev = {
++ .release = platform_device_release,
++ },
++};
++
++static int __init ftsdc_init(void)
++{
++ platform_device_register(&sdc_device);
++ return platform_driver_register(&ftsdc_driver);
++}
++
++static void __exit ftsdc_exit(void)
++{
++ platform_driver_unregister(&ftsdc_driver);
++ platform_device_unregister(&sdc_device);
++}
++module_init(ftsdc_init);
++module_exit(ftsdc_exit);
++
++MODULE_DESCRIPTION("Andestech Leopard MMC/SD Card Interface driver");
++MODULE_LICENSE("GPL v2");
+diff -Nur linux-3.4.110.orig/drivers/mmc/host/ftsdc010.h linux-3.4.110/drivers/mmc/host/ftsdc010.h
+--- linux-3.4.110.orig/drivers/mmc/host/ftsdc010.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/mmc/host/ftsdc010.h 2016-04-07 10:20:51.050085202 +0200
+@@ -0,0 +1,240 @@
++/*
++ * linux/driver/mmc/ftsdc010.h - Andestech MMC/SD driver
++ * Andestech FTSDC010 Device Driver
++ *
++ * Andestech (C) 2005 Faraday Corp. (http://www.Andestech.com)
++ *
++ * All Rights Reserved
++ */
++
++#ifndef _FTSDC010_H_
++#define _FTSDC010_H_
++
++//#define SD_DEBUG
++#define DELAY_FOR_DMA_READ
++
++#ifdef SD_DEBUG
++ #define P_DEBUG(fmt, args...) printk(KERN_ALERT "SD: " fmt, ## args)
++#else
++ #define P_DEBUG(a...)
++#endif
++#define P_DEBUGG(a...)
++
++/* used for dma timeout */
++#define SDC_TIMEOUT_BASE (HZ/2) // Unit is 500 ms
++
++/* used for pio retry times */
++#define SDC_PIO_RETRY 0x300000
++
++/* sd controller register */
++#define SDC_CMD_REG 0x00000000
++#define SDC_ARGU_REG 0x00000004
++#define SDC_RESPONSE0_REG 0x00000008
++#define SDC_RESPONSE1_REG 0x0000000C
++#define SDC_RESPONSE2_REG 0x00000010
++#define SDC_RESPONSE3_REG 0x00000014
++#define SDC_RSP_CMD_REG 0x00000018
++#define SDC_DATA_CTRL_REG 0x0000001C
++#define SDC_DATA_TIMER_REG 0x00000020
++#define SDC_DATA_LEN_REG 0x00000024
++#define SDC_STATUS_REG 0x00000028
++#define SDC_CLEAR_REG 0x0000002C
++#define SDC_INT_MASK_REG 0x00000030
++#define SDC_POWER_CTRL_REG 0x00000034
++#define SDC_CLOCK_CTRL_REG 0x00000038
++#define SDC_BUS_WIDTH_REG 0x0000003C
++#define SDC_DATA_WINDOW_REG 0x00000040
++
++#ifdef A320D_BUILDIN_SDC
++#define SDC_FEATURE_REG 0x00000044
++#define SDC_REVISION_REG 0x00000048
++#else
++#define SDC_MMC_INT_RSP_REG 0x00000044
++#define SDC_GP_OUTPUT_REG 0x00000048
++#define SDC_FEATURE_REG 0x0000009C
++#define SDC_REVISION_REG 0x000000A0
++#endif
++
++#define SDC_SDIO_CTRL1_REG 0x0000006C
++#define SDC_SDIO_CTRL2_REG 0x00000070
++#define SDC_SDIO_STATUS_REG 0x00000074
++
++/* bit mapping of command register */
++#define SDC_CMD_REG_INDEX 0x0000003F
++#define SDC_CMD_REG_NEED_RSP 0x00000040
++#define SDC_CMD_REG_LONG_RSP 0x00000080
++#define SDC_CMD_REG_APP_CMD 0x00000100
++#define SDC_CMD_REG_CMD_EN 0x00000200
++#define SDC_CMD_REG_SDC_RST 0x00000400
++#define SDC_CMD_MMC_INT_STOP 0x00000800
++
++/* bit mapping of response command register */
++#define SDC_RSP_CMD_REG_INDEX 0x0000003F
++#define SDC_RSP_CMD_REG_APP 0x00000040
++
++/* bit mapping of data control register */
++#define SDC_DATA_CTRL_REG_BLK_SIZE 0x0000000F
++#define SDC_DATA_CTRL_REG_DATA_WRITE 0x00000010
++#define SDC_DATA_CTRL_REG_DMA_EN 0x00000020
++#define SDC_DATA_CTRL_REG_DATA_EN 0x00000040
++#define SDC_DATA_CTRL_REG_FIFOTH 0x00000080
++#define SDC_DATA_CTRL_REG_DMA_TYPE 0x00000300
++#define SDC_DATA_CTRL_REG_FIFO_RST 0x00000400
++#define SDC_CPRM_DATA_CHANGE_ENDIAN_EN 0x00000800
++#define SDC_CPRM_DATA_SWAP_HL_EN 0x00001000
++
++#define SDC_DMA_TYPE_1 0x00000000
++#define SDC_DMA_TYPE_4 0x00000100
++#define SDC_DMA_TYPE_8 0x00000200
++
++/* bit mapping of status register */
++#define SDC_STATUS_REG_RSP_CRC_FAIL 0x00000001
++#define SDC_STATUS_REG_DATA_CRC_FAIL 0x00000002
++#define SDC_STATUS_REG_RSP_TIMEOUT 0x00000004
++#define SDC_STATUS_REG_DATA_TIMEOUT 0x00000008
++#define SDC_STATUS_REG_RSP_CRC_OK 0x00000010
++#define SDC_STATUS_REG_DATA_CRC_OK 0x00000020
++#define SDC_STATUS_REG_CMD_SEND 0x00000040
++#define SDC_STATUS_REG_DATA_END 0x00000080
++#define SDC_STATUS_REG_FIFO_UNDERRUN 0x00000100
++#define SDC_STATUS_REG_FIFO_OVERRUN 0x00000200
++#define SDC_STATUS_REG_CARD_CHANGE 0x00000400
++#define SDC_STATUS_REG_CARD_DETECT 0x00000800
++#define SDC_STATUS_REG_CARD_LOCK 0x00001000
++#define SDC_STATUS_REG_CP_READY 0x00002000
++#define SDC_STATUS_REG_CP_BUF_READY 0x00004000
++#define SDC_STATUS_REG_PLAIN_TEXT_READY 0x00008000
++#define SDC_STATUS_REG_SDIO_INTR 0x00010000
++
++/* bit mapping of clear register */
++#define SDC_CLEAR_REG_RSP_CRC_FAIL 0x00000001
++#define SDC_CLEAR_REG_DATA_CRC_FAIL 0x00000002
++#define SDC_CLEAR_REG_RSP_TIMEOUT 0x00000004
++#define SDC_CLEAR_REG_DATA_TIMEOUT 0x00000008
++#define SDC_CLEAR_REG_RSP_CRC_OK 0x00000010
++#define SDC_CLEAR_REG_DATA_CRC_OK 0x00000020
++#define SDC_CLEAR_REG_CMD_SEND 0x00000040
++#define SDC_CLEAR_REG_DATA_END 0x00000080
++#define SDC_CLEAR_REG_CARD_CHANGE 0x00000400
++#define SDC_CLEAR_REG_SDIO_INTR 0x00010000
++
++/* bit mapping of int_mask register */
++#define SDC_INT_MASK_REG_RSP_CRC_FAIL 0x00000001
++#define SDC_INT_MASK_REG_DATA_CRC_FAIL 0x00000002
++#define SDC_INT_MASK_REG_RSP_TIMEOUT 0x00000004
++#define SDC_INT_MASK_REG_DATA_TIMEOUT 0x00000008
++#define SDC_INT_MASK_REG_RSP_CRC_OK 0x00000010
++#define SDC_INT_MASK_REG_DATA_CRC_OK 0x00000020
++#define SDC_INT_MASK_REG_CMD_SEND 0x00000040
++#define SDC_INT_MASK_REG_DATA_END 0x00000080
++#define SDC_INT_MASK_REG_FIFO_UNDERRUN 0x00000100
++#define SDC_INT_MASK_REG_FIFO_OVERRUN 0x00000200
++#define SDC_INT_MASK_REG_CARD_CHANGE 0x00000400
++#define SDC_INT_MASK_REG_CARD_LOCK 0x00001000
++#define SDC_INT_MASK_REG_CP_READY 0x00002000
++#define SDC_INT_MASK_REG_CP_BUF_READY 0x00004000
++#define SDC_INT_MASK_REG_PLAIN_TEXT_READY 0x00008000
++#define SDC_INT_MASK_REG_SDIO_INTR 0x00010000
++
++
++#define SDC_CARD_INSERT 0x0
++#define SDC_CARD_REMOVE SDC_STATUS_REG_CARD_DETECT
++
++/* bit mapping of power control register */
++#define SDC_POWER_CTRL_REG_POWER_ON 0x00000010
++#define SDC_POWER_CTRL_REG_POWER_BITS 0x0000000F
++
++/* bit mapping of clock control register */
++#define SDC_CLOCK_CTRL_REG_CLK_DIV 0x0000007F
++#define SDC_CLOCK_CTRL_REG_CARD_TYPE 0x00000080
++#define SDC_CLOCK_CTRL_REG_CLK_DIS 0x00000100
++
++/* card type */
++#define SDC_CARD_TYPE_SD SDC_CLOCK_REG_CARD_TYPE
++#define SDC_CARD_TYPE_MMC 0x0
++
++/* bit mapping of bus width register */
++#define SDC_BUS_WIDTH_REG_SINGLE_BUS 0x00000001
++#define SDC_BUS_WIDTH_REG_WIDE_8_BUS 0x00000002
++#define SDC_BUS_WIDTH_REG_WIDE_4_BUS 0x00000004
++#define SDC_BUS_WIDTH_REG_WIDE_BUS_SUPPORT 0x00000018
++#define SDC_BUS_WIDTH_REG_CARD_DETECT 0x00000020
++
++#define SDC_WIDE_4_BUS_SUPPORT 0x00000008
++#define SDC_WIDE_8_BUS_SUPPORT 0x00000010
++
++/* bit mapping of feature register */
++#define SDC_FEATURE_REG_FIFO_DEPTH 0x000000FF
++#define SDC_FEATURE_REG_CPRM_FUNCTION 0x00000100
++
++/* bit mapping of sdio control register */
++#define SDC_SDIO_CTRL1_REG_SDIO_BLK_NO 0xFFFF8000
++#define SDC_SDIO_CTRL1_REG_SDIO_ENABLE 0x00004000
++#define SDC_SDIO_CTRL1_REG_READ_WAIT_ENABLE 0x00002000
++#define SDC_SDIO_CTRL1_REG_SDIO_BLK_MODE 0x00001000
++#define SDC_SDIO_CTRL1_REG_SDIO_BLK_SIZE 0x00000FFF
++
++/* bit mapping of sdio status register */
++#define SDC_SDIO_SDIO_STATUS_REG_FIFO_REMAIN_NO 0x00FE0000
++#define SDC_SDIO_SDIO_STATUS_REG_SDIO_BLK_CNT 0x0001FFFF
++
++enum ftsdc_waitfor {
++ COMPLETION_NONE,
++ COMPLETION_FINALIZE,
++ COMPLETION_CMDSENT,
++ COMPLETION_RSPFIN,
++ COMPLETION_XFER_PROGRESS,
++};
++
++struct ftsdc_host {
++ struct platform_device *pdev;
++ struct mmc_host *mmc;
++ struct resource *mem;
++ struct clk *clk;
++ void __iomem *base;
++ int irq;
++
++ unsigned int real_rate;
++ bool irq_enabled;
++ unsigned int fifo_len; /* bytes */
++ unsigned int last_opcode; /* keep last successful cmd to judge application specific command */
++
++ struct mmc_request *mrq;
++ int cmd_is_stop;
++
++ spinlock_t complete_lock;
++ enum ftsdc_waitfor complete_what;
++
++ struct completion dma_complete;
++ dmad_chreq *dma_req;
++ bool dodma;
++ bool dma_finish;
++
++
++ u32 buf_sgptr; /* keep next scallterlist buffer index */
++ u32 buf_bytes; /* keep current total scallterlist buffer length */
++ u32 buf_count; /* keep real data size rw from sd */
++ u32 *buf_ptr; /* keep current scallterlist buffer address */
++#define XFER_NONE 0
++#define XFER_READ 1
++#define XFER_WRITE 2
++ u32 buf_active; /* keep current transfer mode */
++
++ int bus_width;
++
++ char dbgmsg_cmd[301];
++ char dbgmsg_dat[301];
++ char *status;
++
++ unsigned int ccnt, dcnt;
++ struct tasklet_struct pio_tasklet;
++ struct work_struct work;
++
++#ifdef CONFIG_DEBUG_FS
++ struct dentry *debug_root;
++ struct dentry *debug_state;
++ struct dentry *debug_regs;
++#endif
++};
++
++#endif
+diff -Nur linux-3.4.110.orig/drivers/mmc/host/Kconfig linux-3.4.110/drivers/mmc/host/Kconfig
+--- linux-3.4.110.orig/drivers/mmc/host/Kconfig 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/mmc/host/Kconfig 2016-04-07 10:20:51.050085202 +0200
+@@ -609,3 +609,8 @@
+
+ Note: These controllers only support SDIO cards and do not
+ support MMC or SD memory cards.
++
++config MMC_FTSDC010
++ tristate "Andestech MMC/SD function support"
++ depends on NDS32 && !FTSDC010
++
+diff -Nur linux-3.4.110.orig/drivers/mmc/host/Makefile linux-3.4.110/drivers/mmc/host/Makefile
+--- linux-3.4.110.orig/drivers/mmc/host/Makefile 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/mmc/host/Makefile 2016-04-07 10:20:51.050085202 +0200
+@@ -45,6 +45,7 @@
+ obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o
+ obj-$(CONFIG_MMC_VUB300) += vub300.o
+ obj-$(CONFIG_MMC_USHC) += ushc.o
++obj-$(CONFIG_MMC_FTSDC010) += ftsdc010.o
+
+ obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-pltfm.o
+ obj-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o
+diff -Nur linux-3.4.110.orig/drivers/net/ethernet/faraday/ftmac100.c linux-3.4.110/drivers/net/ethernet/faraday/ftmac100.c
+--- linux-3.4.110.orig/drivers/net/ethernet/faraday/ftmac100.c 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/net/ethernet/faraday/ftmac100.c 2016-04-07 10:20:51.054085357 +0200
+@@ -1,1202 +1,1210 @@
+ /*
+- * Faraday FTMAC100 10/100 Ethernet
++ * drivers/net/ftmac100.c
+ *
+- * (C) Copyright 2009-2011 Faraday Technology
+- * Po-Yu Chuang <ratbert@faraday-tech.com>
++ * Faraday FTMAC100 Device Driver
+ *
+- * 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.
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ *
++ * All Rights Reserved
+ *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+-
+-#include <linux/dma-mapping.h>
+-#include <linux/etherdevice.h>
+-#include <linux/ethtool.h>
++#include <linux/module.h>
+ #include <linux/init.h>
++#include <linux/moduleparam.h>
++
++#include <linux/sched.h>
++#include <linux/kernel.h> /* printk() */
++#include <linux/slab.h> /* kmalloc() */
++#include <linux/errno.h> /* error codes */
++#include <linux/types.h> /* size_t */
+ #include <linux/interrupt.h>
+-#include <linux/io.h>
+-#include <linux/mii.h>
+-#include <linux/module.h>
+-#include <linux/netdevice.h>
++
++#include <linux/in.h>
+ #include <linux/platform_device.h>
++#include <linux/netdevice.h> /* struct device, and other headers */
++#include <linux/etherdevice.h> /* eth_type_trans */
++#include <linux/ip.h> /* struct iphdr */
++#include <linux/tcp.h> /* struct tcphdr */
++#include <linux/skbuff.h>
++
++#include <linux/in6.h>
++#include <asm/checksum.h>
++
++
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/fcntl.h>
++#include <linux/ptrace.h>
++#include <linux/ioport.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/proc_fs.h>
++#include <asm/bitops.h>
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <linux/pci.h>
++#include <linux/delay.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
+
++#include <asm/cacheflush.h> // dma_clean_range
++#include <asm/spec.h>
+ #include "ftmac100.h"
+
+-#define DRV_NAME "ftmac100"
+-#define DRV_VERSION "0.2"
+-
+-#define RX_QUEUE_ENTRIES 128 /* must be power of 2 */
+-#define TX_QUEUE_ENTRIES 16 /* must be power of 2 */
++#define IPMODULE MAC
++#define IPNAME FTMAC100
+
+-#define MAX_PKT_SIZE 1518
+-#define RX_BUF_SIZE 2044 /* must be smaller than 0x7ff */
++#define ENABLE_BOTTOM_HALF 0
++#define ZERO_COPY 1
+
+-#if MAX_PKT_SIZE > 0x7ff
+-#error invalid MAX_PKT_SIZE
+-#endif
+-
+-#if RX_BUF_SIZE > 0x7ff || RX_BUF_SIZE > PAGE_SIZE
+-#error invalid RX_BUF_SIZE
+-#endif
+-
+-/******************************************************************************
+- * private data
+- *****************************************************************************/
+-struct ftmac100_descs {
+- struct ftmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
+- struct ftmac100_txdes txdes[TX_QUEUE_ENTRIES];
+-};
+-
+-struct ftmac100 {
+- struct resource *res;
+- void __iomem *base;
+- int irq;
+-
+- struct ftmac100_descs *descs;
+- dma_addr_t descs_dma_addr;
+-
+- unsigned int rx_pointer;
+- unsigned int tx_clean_pointer;
+- unsigned int tx_pointer;
+- unsigned int tx_pending;
+-
+- spinlock_t tx_lock;
+-
+- struct net_device *netdev;
+- struct device *dev;
+- struct napi_struct napi;
++#define FTMAC100_DEBUG 0
++#define CARDNAME "FTMAC100"
+
+- struct mii_if_info mii;
+-};
+-
+-static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
+- struct ftmac100_rxdes *rxdes, gfp_t gfp);
+-
+-/******************************************************************************
+- * internal functions (hardware register access)
+- *****************************************************************************/
+-#define INT_MASK_ALL_ENABLED (FTMAC100_INT_RPKT_FINISH | \
+- FTMAC100_INT_NORXBUF | \
+- FTMAC100_INT_XPKT_OK | \
+- FTMAC100_INT_XPKT_LOST | \
+- FTMAC100_INT_RPKT_LOST | \
+- FTMAC100_INT_AHB_ERR | \
+- FTMAC100_INT_PHYSTS_CHG)
++MODULE_AUTHOR("Faraday Corp.");
++MODULE_LICENSE("GPL");
+
+-#define INT_MASK_ALL_DISABLED 0
++static const char version[] = "Faraday FTMAC100 Driver (Linux 2.6) 09/28/05 - (C) 2005 Faraday Corp.\n";
++static volatile int trans_busy = 0;
++static const char mac_string[] = "Faraday MAC";
+
+-static void ftmac100_enable_all_int(struct ftmac100 *priv)
+-{
+- iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTMAC100_OFFSET_IMR);
+-}
++#if FTMAC100_DEBUG > 2
++static void print_packet( unsigned char * buf, int length );
++#endif
+
+-static void ftmac100_disable_all_int(struct ftmac100 *priv)
+-{
+- iowrite32(INT_MASK_ALL_DISABLED, priv->base + FTMAC100_OFFSET_IMR);
+-}
++#if FTMAC100_DEBUG > 0
++#define PRINTK printk
++#else
++#define PRINTK(x...)
++#endif
+
+-static void ftmac100_set_rx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
+-{
+- iowrite32(addr, priv->base + FTMAC100_OFFSET_RXR_BADR);
++static int ftmac100_open(struct net_device *dev);
++static void ftmac100_timeout (struct net_device *dev);
++static int ftmac100_close(struct net_device *dev);
++static struct net_device_stats * ftmac100_query_statistics( struct net_device *dev);
++#ifdef HAVE_MULTICAST
++static void ftmac100_set_multicast_list(struct net_device *dev);
++#endif
++static void ftmac100_phy_configure(struct net_device* dev) {};
++static irqreturn_t ftmac100_interrupt(int irq, void * dev_id);
++static void ftmac100_rcv(void *dev);
++static int ftmac100_setup(struct net_device *dev);
++static int ftmac100_reset( struct net_device* dev );
++static void ftmac100_enable( struct net_device *dev );
++
++static void put_mac(int base, unsigned char *mac_addr)
++{
++ int val;
++
++ val = ((u32)mac_addr[0])<<8 | (u32)mac_addr[1];
++ outl(val, base);
++ val = ((((u32)mac_addr[2])<<24)&0xff000000) |
++ ((((u32)mac_addr[3])<<16)&0xff0000) |
++ ((((u32)mac_addr[4])<<8)&0xff00) |
++ ((((u32)mac_addr[5])<<0)&0xff);
++ outl(val, base+4);
++}
++
++static void get_mac(int base, unsigned char *mac_addr)
++{
++ int val;
++
++ //printk("+get_mac\n");
++
++ val = inl(base);
++ mac_addr[0] = (val>>8)&0xff;
++ mac_addr[1] = val&0xff;
++ val = inl(base+4); //john add +4
++ mac_addr[2] = (val>>24)&0xff;
++ mac_addr[3] = (val>>16)&0xff;
++ mac_addr[4] = (val>>8)&0xff;
++ mac_addr[5] = val&0xff;
++}
++
++static void auto_get_mac(int id,unsigned char *mac_addr)
++{
++ get_mac(MAC_FTMAC100_0_VA_BASE + MAC_MADR_REG, mac_addr);
++
++ if (memcmp(mac_addr, "\0\0\0\0\0\0", 6) == 0) {
++ mac_addr[0]=0;
++ mac_addr[1]=0x23;
++ mac_addr[2]=0x96;
++ mac_addr[3]=0x00;
++ mac_addr[4]=0xff;
++ mac_addr[5]=0x00;
++ }
+ }
+
+-static void ftmac100_set_tx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
++/*
++ * Print the Ethernet address
++ */
++static void ft_print_mac(unsigned char *mac_addr)
+ {
+- iowrite32(addr, priv->base + FTMAC100_OFFSET_TXR_BADR);
++ printk("ADDR: %pM\n", mac_addr);
+ }
+
+-static void ftmac100_txdma_start_polling(struct ftmac100 *priv)
+-{
+- iowrite32(1, priv->base + FTMAC100_OFFSET_TXPD);
+-}
+
+-static int ftmac100_reset(struct ftmac100 *priv)
++#ifdef HAVE_MULTICAST
++/*
++ * Finds the CRC32 of a set of bytes.
++ * Again, from Peter Cammaert's code.
++ */
++static int crc32( char * s, int length )
+ {
+- struct net_device *netdev = priv->netdev;
+- int i;
+-
+- /* NOTE: reset clears all registers */
+- iowrite32(FTMAC100_MACCR_SW_RST, priv->base + FTMAC100_OFFSET_MACCR);
+-
+- for (i = 0; i < 5; i++) {
+- unsigned int maccr;
+-
+- maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR);
+- if (!(maccr & FTMAC100_MACCR_SW_RST)) {
+- /*
+- * FTMAC100_MACCR_SW_RST cleared does not indicate
+- * that hardware reset completed (what the f*ck).
+- * We still need to wait for a while.
+- */
+- udelay(500);
+- return 0;
++ /* indices */
++ int perByte;
++ int perBit;
++ /* crc polynomial for Ethernet */
++ const unsigned long poly = 0xedb88320;
++ /* crc value - preinitialized to all 1's */
++ unsigned long crc_value = 0xffffffff;
++
++ //printk("+crc32\n");
++
++ for ( perByte = 0; perByte < length; perByte ++ ) {
++ unsigned char c;
++
++ c = *(s++);
++ for ( perBit = 0; perBit < 8; perBit++ ) {
++ crc_value = (crc_value>>1)^
++ (((crc_value^c)&0x01)?poly:0);
++ c >>= 1;
+ }
+-
+- udelay(1000);
+ }
+-
+- netdev_err(netdev, "software reset failed\n");
+- return -EIO;
+-}
+-
+-static void ftmac100_set_mac(struct ftmac100 *priv, const unsigned char *mac)
+-{
+- unsigned int maddr = mac[0] << 8 | mac[1];
+- unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
+-
+- iowrite32(maddr, priv->base + FTMAC100_OFFSET_MAC_MADR);
+- iowrite32(laddr, priv->base + FTMAC100_OFFSET_MAC_LADR);
++ return crc_value;
+ }
++#endif
+
+-#define MACCR_ENABLE_ALL (FTMAC100_MACCR_XMT_EN | \
+- FTMAC100_MACCR_RCV_EN | \
+- FTMAC100_MACCR_XDMA_EN | \
+- FTMAC100_MACCR_RDMA_EN | \
+- FTMAC100_MACCR_CRC_APD | \
+- FTMAC100_MACCR_FULLDUP | \
+- FTMAC100_MACCR_RX_RUNT | \
+- FTMAC100_MACCR_RX_BROADPKT)
+-
+-static int ftmac100_start_hw(struct ftmac100 *priv)
++static int ftmac100_reset( struct net_device* dev )
+ {
+- struct net_device *netdev = priv->netdev;
++ unsigned ioaddr = dev->base_addr;
++ int rcount;
+
+- if (ftmac100_reset(priv))
+- return -EIO;
++ PRINTK("+ftmac100_reset:I/O addr=%X\n", ioaddr);
+
+- /* setup ring buffer base registers */
+- ftmac100_set_rx_ring_base(priv,
+- priv->descs_dma_addr +
+- offsetof(struct ftmac100_descs, rxdes));
+- ftmac100_set_tx_ring_base(priv,
+- priv->descs_dma_addr +
+- offsetof(struct ftmac100_descs, txdes));
++ outl( SW_RST_bit, ioaddr + MACCR_REG );
+
+- iowrite32(FTMAC100_APTC_RXPOLL_CNT(1), priv->base + FTMAC100_OFFSET_APTC);
++ /* this should pause enough for the chip to be happy */
++ for (rcount = 0; (inl( ioaddr + MACCR_REG ) & SW_RST_bit) != 0; rcount++) {
++ //mdelay(10);
++ msleep_interruptible(10);
++ if (rcount > 5) // Retry 5 times
++ return -ENODEV;
++ }
+
+- ftmac100_set_mac(priv, netdev->dev_addr);
++ outl( 0, ioaddr + IMR_REG ); /* Disable all interrupts */
++ if (inl(ioaddr+IMR_REG)!=0)
++ return -ENODEV;
+
+- iowrite32(MACCR_ENABLE_ALL, priv->base + FTMAC100_OFFSET_MACCR);
+- return 0;
++ return 0;
+ }
+
+-static void ftmac100_stop_hw(struct ftmac100 *priv)
+-{
+- iowrite32(0, priv->base + FTMAC100_OFFSET_MACCR);
+-}
+
+-/******************************************************************************
+- * internal functions (receive descriptor)
+- *****************************************************************************/
+-static bool ftmac100_rxdes_first_segment(struct ftmac100_rxdes *rxdes)
+-{
+- return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FRS);
+-}
+-
+-static bool ftmac100_rxdes_last_segment(struct ftmac100_rxdes *rxdes)
++/*
++ . Function: ftmac100_enable
++ . Purpose: let the chip talk to the outside work
++ . Method:
++ . 1. Enable the transmitter
++ . 2. Enable the receiver
++ . 3. Enable interrupts
++*/
++static void ftmac100_enable( struct net_device *dev )
+ {
+- return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_LRS);
+-}
++ unsigned int ioaddr = dev->base_addr;
++ int i;
++ struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
++ char mac_addr[6];
+
+-static bool ftmac100_rxdes_owned_by_dma(struct ftmac100_rxdes *rxdes)
+-{
+- return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
+-}
++ //printk("+ftmac100_enable\n");
++ PRINTK("%s:ftmac100_enable ioaddr=%X\n", dev->name, ioaddr);
+
+-static void ftmac100_rxdes_set_dma_own(struct ftmac100_rxdes *rxdes)
+-{
+- /* clear status bits */
+- rxdes->rxdes0 = cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
++ for (i=0; i<RXDES_NUM; ++i) {
++ priv->rx_descs[i].RXDMA_OWN = OWNBY_FTMAC100; // owned by FTMAC100
++ }
++ priv->rx_idx = 0;
++
++ for (i=0; i<TXDES_NUM; ++i) {
++ priv->tx_descs[i].TXDMA_OWN = OWNBY_SOFTWARE; // owned by software
++ }
++ priv->tx_idx = 0;
++
++
++ /* set the MAC address */
++ put_mac(ioaddr + MAC_MADR_REG, dev->dev_addr);
++
++ //john add
++ get_mac(ioaddr + MAC_MADR_REG, mac_addr);
++ ft_print_mac(mac_addr);
++
++ outl( priv->rx_descs_dma, ioaddr + RXR_BADR_REG);
++ outl( priv->tx_descs_dma, ioaddr + TXR_BADR_REG);
++ outl( 0x00001010, ioaddr + ITC_REG); // TODO: threshold too small
++ outl( (0UL<<TXPOLL_CNT)|(0x1<<RXPOLL_CNT), ioaddr + APTC_REG); // TODO: bandwidth overhead maybe too big, polling too often ?!
++ outl( 0x1d8, ioaddr + DBLAC_REG ); //Luke Lee: 1 110 010 111 (0x397)
++
++ /* now, enable interrupts */
++ outl( PHYSTS_CHG_bit
++ | AHB_ERR_bit
++ | RPKT_LOST_bit
++ | RPKT_SAV_bit
++ | XPKT_LOST_bit
++ | XPKT_OK_bit
++ | NOTXBUF_bit
++ | XPKT_FINISH_bit
++ | NORXBUF_bit
++ | RPKT_FINISH_bit
++ , ioaddr + IMR_REG);
++
++ /// enable trans/recv,...
++ outl( priv->maccr_val, ioaddr + MACCR_REG );
++ PRINTK("%s:ftmac100_enable DONE\n", dev->name);
+ }
+
+-static bool ftmac100_rxdes_rx_error(struct ftmac100_rxdes *rxdes)
++/*
++ . Function: ftmac100_shutdown
++ . Purpose: closes down the SMC91xxx chip.
++ . Method:
++ . 1. zero the interrupt mask
++ . 2. clear the enable receive flag
++ . 3. clear the enable xmit flags
++ .
++ . TODO:
++ . (1) maybe utilize power down mode.
++ . Why not yet? Because while the chip will go into power down mode,
++ . the manual says that it will wake up in response to any I/O requests
++ . in the register space. Empirical results do not show this working.
++*/
++static void ftmac100_shutdown( unsigned int ioaddr )
+ {
+- return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ERR);
+-}
++ //printk("+ftmac100_shutdown\n");
+
+-static bool ftmac100_rxdes_crc_error(struct ftmac100_rxdes *rxdes)
+-{
+- return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_CRC_ERR);
++ outl( 0, ioaddr + IMR_REG );
++ outl( 0, ioaddr + MACCR_REG );
+ }
+
+-static bool ftmac100_rxdes_frame_too_long(struct ftmac100_rxdes *rxdes)
++/*
++ * Function: ftmac100_wait_to_send_packet( struct sk_buff * skb, struct device * )
++ * Purpose:
++ * Attempt to allocate memory for a packet, if chip-memory is not
++ * available, then tell the card to generate an interrupt when it
++ * is available*
++ *
++ * Algorithm:
++ *
++ * o if the saved_skb is not currently null, then drop this packet
++ * on the floor. This should never happen, because of TBUSY.
++ * o if the saved_skb is null, then replace it with the current packet,
++ * o See if I can sending it now.
++ * o (NO): Enable interrupts and let the interrupt handler deal with it.
++ * o (YES):Send it now.
++ */
++static int ftmac100_wait_to_send_packet( struct sk_buff * skb, struct net_device * dev )
+ {
+- return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FTL);
+-}
++ struct ftmac100_local *priv=(struct ftmac100_local *)netdev_priv(dev);
++ unsigned int ioaddr=dev->base_addr;
++ volatile TX_DESC *cur_desc;
++ int length;
++ unsigned long flags;
++
++ //printk("+ftmac100_wait_to_send_packet\n");
++
++ spin_lock_irqsave(&priv->lock, flags);
++ if (skb==NULL) {
++ printk("%s(%d): NULL skb???\n", __FILE__,__LINE__);
++ spin_unlock_irqrestore(&priv->lock, flags);
++ return 0;
++ }
++
++ cur_desc = &priv->tx_descs[priv->tx_idx];
++#if ZERO_COPY
++ /* Record buffer address to be freed later */
++ priv->tx_skbuff[priv->tx_idx] = skb;
++#endif
++
++#ifdef not_complete_yet
++ if (cur_desc->TXDMA_OWN != TX_OWNBY_SOFTWARE) /// no empty transmit descriptor
++ {
++ DO_PRINT("no empty transmit descriptor\n");
++ DO_PRINT("jiffies = %d\n", jiffies);
++ lp->stats.tx_dropped++;
++ netif_stop_queue(dev); /// waiting to do:
++ spin_unlock_irqrestore(&lp->lock, flags);
++
++ return 1;
++ }
++#endif /* end_of_not */
++
++ for (; cur_desc->TXDMA_OWN != OWNBY_SOFTWARE; ) {
++ PRINTK( KERN_WARNING "NO empty TX\n"); //printk("no empty TX descriptor:0x%x:0x%x\n",(unsigned)cur_desc,(unsigned)cur_desc[0]);
++ udelay(1);
++ }
++ length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;
++ length = min(length, TX_BUF_SIZE); // truncate jumbo packets
++
++#if FTMAC100_DEBUG > 2
++ printk("Transmitting Packet at 0x%x\n",(unsigned int)cur_desc->VIR_TXBUF_BADR);
++ print_packet( skb->data, length );
++#endif
+
+-static bool ftmac100_rxdes_runt(struct ftmac100_rxdes *rxdes)
+-{
+- return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RUNT);
+-}
++#if ZERO_COPY
++ cur_desc->VIR_TXBUF_BADR = (unsigned)skb->data;
++ cur_desc->TXBUF_BADR = virt_to_phys(skb->data);
++ cpu_dma_wb_range((unsigned)skb->data, ((unsigned)(skb->data) + length + CACHE_LINE_SIZE( DCACHE) - 1 )&(~(CACHE_LINE_SIZE( DCACHE)-1)) );
+
+-static bool ftmac100_rxdes_odd_nibble(struct ftmac100_rxdes *rxdes)
+-{
+- return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ODD_NB);
+-}
++#else
++ memcpy((char *)cur_desc->VIR_TXBUF_BADR, skb->data, length);
++#endif
+
+-static unsigned int ftmac100_rxdes_frame_length(struct ftmac100_rxdes *rxdes)
+-{
+- return le32_to_cpu(rxdes->rxdes0) & FTMAC100_RXDES0_RFL;
++ cur_desc->TXBUF_Size = length;
++ cur_desc->LTS = 1;
++ cur_desc->FTS = 1;
++
++ cur_desc->TX2FIC = 0;
++ cur_desc->TXIC = 0;
++
++ cur_desc->TXDMA_OWN = OWNBY_FTMAC100;
++
++ outl( 0xffffffff, ioaddr + TXPD_REG );
++
++ priv->tx_idx = (priv->tx_idx + 1) & (TXDES_NUM-1);
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += skb->len;
++#if !ZERO_COPY
++ dev_kfree_skb_any (skb);
++#endif
++ dev->trans_start = jiffies;
++ spin_unlock_irqrestore(&priv->lock, flags);
++ return 0;
+ }
+
+-static bool ftmac100_rxdes_multicast(struct ftmac100_rxdes *rxdes)
+-{
+- return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_MULTICAST);
+-}
++//#define dma_allocate(x,y,z,w) dma_alloc_coherent((x),(y),(dma_addr_t*)(z),(w))
++#define dma_allocate(x,y,z,w) dma_alloc_writecombine((x),(y),(dma_addr_t*)(z),(w))
+
+-static void ftmac100_rxdes_set_buffer_size(struct ftmac100_rxdes *rxdes,
+- unsigned int size)
++static int ftmac100_ringbuf_alloc(struct net_device *dev,struct ftmac100_local *priv)
+ {
+- rxdes->rxdes1 &= cpu_to_le32(FTMAC100_RXDES1_EDORR);
+- rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_RXBUF_SIZE(size));
+-}
++ int i;
+
+-static void ftmac100_rxdes_set_end_of_ring(struct ftmac100_rxdes *rxdes)
+-{
+- rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_EDORR);
+-}
++ //printk("+ftmac100_ringbuf_alloc\n");
+
+-static void ftmac100_rxdes_set_dma_addr(struct ftmac100_rxdes *rxdes,
+- dma_addr_t addr)
+-{
+- rxdes->rxdes2 = cpu_to_le32(addr);
+-}
++ priv->rx_descs = dma_allocate( NULL, sizeof(RX_DESC)*RXDES_NUM, &(priv->rx_descs_dma), GFP_KERNEL );
++ if (priv->rx_descs == NULL || (( (u32)priv->rx_descs & 0xf)!=0)) {
++ printk("Receive Ring Buffer allocation error\n");
++ return -ENOMEM;
++ }
++#if FTMAC100_DEBUG > 2
++ else
++ printk( KERN_INFO "* Allocated RX descs=%X, bus addr=%X, size=%d*%d=%d\n",
++ (unsigned)priv->rx_descs, (unsigned)priv->rx_descs_dma,
++ sizeof(RX_DESC),RXDES_NUM,sizeof(RX_DESC)*RXDES_NUM );
++#endif
++ memset((unsigned int *)priv->rx_descs, 0, sizeof(RX_DESC)*RXDES_NUM);
+
+-static dma_addr_t ftmac100_rxdes_get_dma_addr(struct ftmac100_rxdes *rxdes)
+-{
+- return le32_to_cpu(rxdes->rxdes2);
++ priv->rx_buf = dma_allocate( NULL, RX_BUF_SIZE*RXDES_NUM, &(priv->rx_buf_dma), GFP_KERNEL );
++ if (priv->rx_buf == NULL || (( (u32)priv->rx_buf & 3)!=0)) {
++ printk("Receive Ring Buffer allocation error\n");
++ return -ENOMEM;
++ }
++#if FTMAC100_DEBUG > 2
++ else
++ printk( KERN_INFO "* Allocated RX buf=%X, bus addr=%X, size=%d*%d=%d\n",
++ (unsigned)priv->rx_buf, (unsigned)priv->rx_buf_dma,
++ RX_BUF_SIZE, RXDES_NUM, RX_BUF_SIZE*RXDES_NUM );
++#endif
++
++ memset((void *)priv->rx_buf,0,sizeof(RX_BUF_SIZE)*RXDES_NUM);
++
++ for (i=0; i<RXDES_NUM; ++i) {
++ priv->rx_descs[i].RXBUF_Size = RX_BUF_SIZE;
++ priv->rx_descs[i].EDOTR = 0; // not last descriptor
++ priv->rx_descs[i].RXBUF_BADR = priv->rx_buf_dma+RX_BUF_SIZE*i;
++ priv->rx_descs[i].VIR_RXBUF_BADR=(unsigned int)priv->rx_buf+RX_BUF_SIZE*i;
++ }
++ priv->rx_descs[RXDES_NUM-1].EDOTR = 1; // is last descriptor
++
++ priv->tx_descs = dma_allocate( NULL, sizeof(TX_DESC)*TXDES_NUM, &(priv->tx_descs_dma), GFP_KERNEL );
++ if (priv->tx_descs == NULL || (( (u32)priv->tx_descs & 0xf)!=0)) {
++ printk("Transmit Ring Buffer allocation error\n");
++ return -ENOMEM;
++ }
++#if FTMAC100_DEBUG > 2
++ else
++ printk( KERN_INFO "* Allocated TX descs=%X, bus addr=%X, size=%d*%d=%d\n",
++ (unsigned)priv->tx_descs, (unsigned)priv->tx_descs_dma, sizeof(TX_DESC),TXDES_NUM,sizeof(TX_DESC)*TXDES_NUM);
++#endif
++ memset((void *)priv->tx_descs,0,sizeof(TX_DESC)*TXDES_NUM);
++
++ priv->tx_buf = dma_allocate( NULL, TX_BUF_SIZE*TXDES_NUM, &(priv->tx_buf_dma), GFP_KERNEL );
++ if (priv->tx_buf == NULL || (( (u32)priv->tx_buf & 0x3)!=0)) {
++ printk("Transmit Ring Buffer allocation error\n");
++ return -ENOMEM;
++ }
++#if FTMAC100_DEBUG > 2
++ else
++ printk( KERN_INFO "* Allocated TX buf=%X, bus addr=%X, size=%d*%d=%d\n",
++ (unsigned)priv->tx_buf, (unsigned)priv->tx_buf_dma,
++ TX_BUF_SIZE, TXDES_NUM, TX_BUF_SIZE*TXDES_NUM );
++#endif
++
++ memset((void *)priv->tx_buf,0,sizeof(TX_BUF_SIZE)*TXDES_NUM);
++
++ for (i=0; i<TXDES_NUM; ++i) {
++ priv->tx_descs[i].EDOTR = 0; // not last descriptor
++ priv->tx_descs[i].TXBUF_BADR=priv->tx_buf_dma+TX_BUF_SIZE*i;
++ priv->tx_descs[i].VIR_TXBUF_BADR=(unsigned int)priv->tx_buf+TX_BUF_SIZE*i;
++ }
++ priv->tx_descs[TXDES_NUM-1].EDOTR = 1; // is last descriptor
++ return 0;
+ }
+
+ /*
+- * rxdes3 is not used by hardware. We use it to keep track of page.
+- * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
++ * Function: ftmac100_poll( struct net_device *dev )
++ *
++ * Purpose:
++ * poll interface callback function.
+ */
+-static void ftmac100_rxdes_set_page(struct ftmac100_rxdes *rxdes, struct page *page)
++void ftmac100_poll(struct net_device *dev)
+ {
+- rxdes->rxdes3 = (unsigned int)page;
++ disable_irq(dev->irq);
++ ftmac100_interrupt(dev->irq, dev);
++ enable_irq(dev->irq);
+ }
+
+-static struct page *ftmac100_rxdes_get_page(struct ftmac100_rxdes *rxdes)
+-{
+- return (struct page *)rxdes->rxdes3;
+-}
+-
+-/******************************************************************************
+- * internal functions (receive)
+- *****************************************************************************/
+-static int ftmac100_next_rx_pointer(int pointer)
++/*
++ * Function: ftmac100_setup( struct net_device *dev )
++ *
++ * Purpose:
++ * Tests to see if the device 'dev' points to an ftmac100 chip.
++ * Returns a 0 on success
++ */
++static const struct net_device_ops ftmac100_ops = {
++ .ndo_init = ftmac100_setup,
++ .ndo_open = ftmac100_open,
++ .ndo_stop = ftmac100_close,
++ .ndo_start_xmit = ftmac100_wait_to_send_packet,
++ .ndo_get_stats = ftmac100_query_statistics,
++ .ndo_tx_timeout = ftmac100_timeout,
++#ifdef HAVE_MULTICAST
++ .ndo_set_multicast_list = ftmac100_set_multicast_list,
++#endif
++ .ndo_set_mac_address = eth_mac_addr,
++#ifdef CONFIG_NET_POLL_CONTROLLER
++ .ndo_poll_controller = ftmac100_poll,
++#endif
++};
++static int ftmac100_setup(struct net_device *dev)
+ {
+- return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
+-}
++ int retval;
++ static unsigned version_printed = 0;
++ struct ftmac100_local *priv;
++
++ if (version_printed++ == 0)
++ printk(KERN_INFO "%s", version);
++
++ /* Now, print out the card info, in a short format.. */
++ printk(KERN_INFO "%s: device at %#3x IRQ:%d NOWAIT:%d\n",dev->name,
++ (unsigned)dev->base_addr, dev->irq, dev->dma);
++
++ /* Initialize priviate data */
++ priv = (struct ftmac100_local *)netdev_priv(dev);
++ memset(priv, 0, sizeof(struct ftmac100_local));
++ spin_lock_init(&priv->lock);
++ priv->maccr_val = FULLDUP_bit
++ | CRC_APD_bit
++ | MDC_SEL_bit
++ | RCV_EN_bit
++ | XMT_EN_bit
++ | RDMA_EN_bit
++ | XDMA_EN_bit ;
++ retval = ftmac100_ringbuf_alloc(dev,priv);
++ if (retval)
++ goto err_out;
++
++ /* now, reset the chip, and put it into a known state */
++ retval = ftmac100_reset( dev );
++ if (retval) {
++ printk( "%s: unable to reset.\n", dev->name );
++ goto err_out;
++ }
++
++ /* Fill in the fields of the device structure with ethernet values. */
++ ether_setup(dev);
++
++ /* Grab the IRQ */
++ retval = request_irq(dev->irq, &ftmac100_interrupt, IRQF_DISABLED, dev->name, dev);
++ if (retval) {
++ printk("%s: unable to get IRQ %d (irqval=%d).\n", dev->name, dev->irq, retval);
++ goto err_out;
++ }
++
++#if 0
++ if ((proc_ftmac100 = create_proc_entry( "ftmac100", 0, 0 ))) {
++ proc_ftmac100->read_proc = ftmac100_read_proc;
++ proc_ftmac100->data = dev;
++ proc_ftmac100->owner = THIS_MODULE;
++ }
++#endif
+
+-static void ftmac100_rx_pointer_advance(struct ftmac100 *priv)
+-{
+- priv->rx_pointer = ftmac100_next_rx_pointer(priv->rx_pointer);
+-}
++ return 0;
+
+-static struct ftmac100_rxdes *ftmac100_current_rxdes(struct ftmac100 *priv)
+-{
+- return &priv->descs->rxdes[priv->rx_pointer];
++err_out:
++ dma_free_coherent( NULL, sizeof(RX_DESC)*RXDES_NUM, (void*)priv->rx_descs, (dma_addr_t)priv->rx_descs_dma );
++ dma_free_coherent( NULL, RX_BUF_SIZE*RXDES_NUM, (void*)priv->rx_buf, (dma_addr_t)priv->rx_buf_dma );
++ dma_free_coherent( NULL, sizeof(TX_DESC)*TXDES_NUM, (void*)priv->tx_descs, (dma_addr_t)priv->tx_descs_dma );
++ dma_free_coherent( NULL, TX_BUF_SIZE*TXDES_NUM, (void*)priv->tx_buf, (dma_addr_t)priv->tx_buf_dma );
++ priv->rx_descs = NULL; priv->rx_descs_dma = 0;
++ priv->rx_buf = NULL; priv->rx_buf_dma = 0;
++ priv->tx_descs = NULL; priv->tx_descs_dma = 0;
++ priv->tx_buf = NULL; priv->tx_buf_dma = 0;
++ return retval;
+ }
+
+-static struct ftmac100_rxdes *
+-ftmac100_rx_locate_first_segment(struct ftmac100 *priv)
+-{
+- struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
+
+- while (!ftmac100_rxdes_owned_by_dma(rxdes)) {
+- if (ftmac100_rxdes_first_segment(rxdes))
+- return rxdes;
++#if FTMAC100_DEBUG > 2
++static void print_packet( unsigned char * buf, int length )
++{
++#if FTMAC100_DEBUG > 3
++ int i;
++ int remainder;
++ int lines;
++#endif
+
+- ftmac100_rxdes_set_dma_own(rxdes);
+- ftmac100_rx_pointer_advance(priv);
+- rxdes = ftmac100_current_rxdes(priv);
+- }
++// printk("Packet of length %d \n", length );
+
+- return NULL;
++#if FTMAC100_DEBUG > 3
++ lines = length >> 4;
++ remainder = length & 15;
++
++ for ( i = 0; i < lines ; i ++ ) {
++ int cur;
++ for ( cur = 0; cur < 8; cur ++ ) {
++ unsigned char a, b;
++ a = *(buf ++ );
++ b = *(buf ++ );
++ printk("%02x%02x ", a, b );
++ }
++ printk("\n");
++ }
++ for ( i = 0; i < remainder/2 ; i++ ) {
++ unsigned char a, b;
++
++ a = *(buf ++ );
++ b = *(buf ++ );
++ printk("%02x%02x ", a, b );
++ }
++ printk("\n");
++#endif
+ }
++#endif
+
+-static bool ftmac100_rx_packet_error(struct ftmac100 *priv,
+- struct ftmac100_rxdes *rxdes)
+-{
+- struct net_device *netdev = priv->netdev;
+- bool error = false;
+-
+- if (unlikely(ftmac100_rxdes_rx_error(rxdes))) {
+- if (net_ratelimit())
+- netdev_info(netdev, "rx err\n");
+-
+- netdev->stats.rx_errors++;
+- error = true;
+- }
+-
+- if (unlikely(ftmac100_rxdes_crc_error(rxdes))) {
+- if (net_ratelimit())
+- netdev_info(netdev, "rx crc err\n");
+-
+- netdev->stats.rx_crc_errors++;
+- error = true;
+- }
+-
+- if (unlikely(ftmac100_rxdes_frame_too_long(rxdes))) {
+- if (net_ratelimit())
+- netdev_info(netdev, "rx frame too long\n");
+-
+- netdev->stats.rx_length_errors++;
+- error = true;
+- } else if (unlikely(ftmac100_rxdes_runt(rxdes))) {
+- if (net_ratelimit())
+- netdev_info(netdev, "rx runt\n");
+-
+- netdev->stats.rx_length_errors++;
+- error = true;
+- } else if (unlikely(ftmac100_rxdes_odd_nibble(rxdes))) {
+- if (net_ratelimit())
+- netdev_info(netdev, "rx odd nibble\n");
+-
+- netdev->stats.rx_length_errors++;
+- error = true;
+- }
+-
+- return error;
+-}
+
+-static void ftmac100_rx_drop_packet(struct ftmac100 *priv)
++/*
++ * Open and Initialize the board
++ *
++ * Set up everything, reset the card, etc ..
++ *
++ */
++static int ftmac100_open(struct net_device *dev)
+ {
+- struct net_device *netdev = priv->netdev;
+- struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
+- bool done = false;
+-
+- if (net_ratelimit())
+- netdev_dbg(netdev, "drop packet %p\n", rxdes);
++ int retval = 0;
++ PRINTK("+%s:ftmac100_open\n", dev->name);
+
+- do {
+- if (ftmac100_rxdes_last_segment(rxdes))
+- done = true;
++ //netif_start_queue(dev);
+
+- ftmac100_rxdes_set_dma_own(rxdes);
+- ftmac100_rx_pointer_advance(priv);
+- rxdes = ftmac100_current_rxdes(priv);
+- } while (!done && !ftmac100_rxdes_owned_by_dma(rxdes));
+-
+- netdev->stats.rx_dropped++;
++ /* reset the hardware */
++ ftmac100_reset( dev );
++ retval = ftmac100_reset( dev );
++ if (retval) {
++ printk( "%s: unable to reset.\n", dev->name );
++ retval = -ENODEV;
++ } else {
++ ftmac100_enable( dev );
++
++ /* Configure the PHY */
++ ftmac100_phy_configure(dev);
++
++ netif_start_queue(dev);
++
++ PRINTK("+%s:ftmac100_open DONE\n", dev->name);
++ }
++
++ return retval;
+ }
+
+-static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed)
+-{
+- struct net_device *netdev = priv->netdev;
+- struct ftmac100_rxdes *rxdes;
+- struct sk_buff *skb;
+- struct page *page;
+- dma_addr_t map;
+- int length;
+
+- rxdes = ftmac100_rx_locate_first_segment(priv);
+- if (!rxdes)
+- return false;
+-
+- if (unlikely(ftmac100_rx_packet_error(priv, rxdes))) {
+- ftmac100_rx_drop_packet(priv);
+- return true;
+- }
+-
+- /*
+- * It is impossible to get multi-segment packets
+- * because we always provide big enough receive buffers.
+- */
+- if (unlikely(!ftmac100_rxdes_last_segment(rxdes)))
+- BUG();
+-
+- /* start processing */
+- skb = netdev_alloc_skb_ip_align(netdev, 128);
+- if (unlikely(!skb)) {
+- if (net_ratelimit())
+- netdev_err(netdev, "rx skb alloc failed\n");
+-
+- ftmac100_rx_drop_packet(priv);
+- return true;
+- }
+-
+- if (unlikely(ftmac100_rxdes_multicast(rxdes)))
+- netdev->stats.multicast++;
+-
+- map = ftmac100_rxdes_get_dma_addr(rxdes);
+- dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+-
+- length = ftmac100_rxdes_frame_length(rxdes);
+- page = ftmac100_rxdes_get_page(rxdes);
+- skb_fill_page_desc(skb, 0, page, 0, length);
+- skb->len += length;
+- skb->data_len += length;
+-
+- /* page might be freed in __pskb_pull_tail() */
+- if (length > 64)
+- skb->truesize += PAGE_SIZE;
+- __pskb_pull_tail(skb, min(length, 64));
+-
+- ftmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
+-
+- ftmac100_rx_pointer_advance(priv);
+-
+- skb->protocol = eth_type_trans(skb, netdev);
+-
+- netdev->stats.rx_packets++;
+- netdev->stats.rx_bytes += skb->len;
++/*
++ * Called by the kernel to send a packet out into the void
++ * of the net. This routine is largely based on
++ * skeleton.c, from Becker.
++ *
++ */
++static void ftmac100_timeout (struct net_device *dev)
++{
++ /* If we get here, some higher level has decided we are broken.
++ There should really be a "kick me" function call instead. */
++ printk(KERN_WARNING "%s: transmit timed out?\n",dev->name);
+
+- /* push packet to protocol stack */
+- netif_receive_skb(skb);
++ //printk("+ftmac100_timeout\n");
+
+- (*processed)++;
+- return true;
++ ftmac100_reset( dev );
++ ftmac100_enable( dev );
++ ftmac100_phy_configure(dev);
++ netif_wake_queue(dev);
++ dev->trans_start = jiffies;
+ }
+
+-/******************************************************************************
+- * internal functions (transmit descriptor)
+- *****************************************************************************/
+-static void ftmac100_txdes_reset(struct ftmac100_txdes *txdes)
++#if ZERO_COPY
++/*
++ * Free transmitted skb buffer when it's safe.
++ */
++static void ftmac100_free_tx (struct net_device *dev, int irq)
+ {
+- /* clear all except end of ring bit */
+- txdes->txdes0 = 0;
+- txdes->txdes1 &= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
+- txdes->txdes2 = 0;
+- txdes->txdes3 = 0;
+-}
++ struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
++ //volatile TX_DESC *cur_desc;
++ int entry = priv->old_tx & (TXDES_NUM-1);
++
++ //enter spinlock
++ if (!irq)
++ spin_lock(&priv->lock);
++
++ /* Free used tx skbuffs */
++ while (entry != priv->tx_idx) {
++ struct sk_buff *skb;
++
++ skb = priv->tx_skbuff[entry];
++ if(skb) {
++ dev_kfree_skb_any (skb);
++ priv->tx_skbuff[entry] = 0;
++ }
+
+-static bool ftmac100_txdes_owned_by_dma(struct ftmac100_txdes *txdes)
+-{
+- return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
+-}
++ entry = (entry + 1) & (TXDES_NUM-1);
++ }
+
+-static void ftmac100_txdes_set_dma_own(struct ftmac100_txdes *txdes)
+-{
+- /*
+- * Make sure dma own bit will not be set before any other
+- * descriptor fields.
+- */
+- wmb();
+- txdes->txdes0 |= cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
+-}
++ if (!irq)
++ spin_unlock(&priv->lock);
++ //exit spinloc
+
+-static bool ftmac100_txdes_excessive_collision(struct ftmac100_txdes *txdes)
+-{
+- return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_EXSCOL);
++ priv->old_tx = entry;
++ netif_wake_queue (dev);
+ }
++#endif
+
+-static bool ftmac100_txdes_late_collision(struct ftmac100_txdes *txdes)
+-{
+- return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_LATECOL);
+-}
++/*
++ .
++ . This is the main routine of the driver, to handle the net_device when
++ . it needs some attention.
++ .
++ . So:
++ . first, save state of the chipset
++ . branch off into routines to handle each case, and acknowledge
++ . each to the interrupt register
++ . and finally restore state.
++ .
++ */
+
+-static void ftmac100_txdes_set_end_of_ring(struct ftmac100_txdes *txdes)
+-{
+- txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
+-}
++#if FTMAC100_DEBUG > 2
+
+-static void ftmac100_txdes_set_first_segment(struct ftmac100_txdes *txdes)
++static void dump_intc(void)
+ {
+- txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_FTS);
++ printk( " INTC[0] IRQSRC=%08X,MASK=%08X,MOD=%08X,LEV=%08X,STAT=%08X\n",
++ *((volatile unsigned*)(INTC_FTINTC010_VA_BASE+0)),
++ *((volatile unsigned*)(INTC_FTINTC010_VA_BASE+0x4)),
++ *((volatile unsigned*)(INTC_FTINTC010_VA_BASE+0xc)),
++ *((volatile unsigned*)(INTC_FTINTC010_VA_BASE+0x10)),
++ *((volatile unsigned*)(INTC_FTINTC010_VA_BASE+0x14)) );
++ printk( " INTC[1] IRQSRC=%08X,MASK=%08X,MOD=%08X,LEV=%08X,STAT=%08X\n",
++ *((volatile unsigned*)(INTC_FTINTC010_1_VA_BASE+0)),
++ *((volatile unsigned*)(INTC_FTINTC010_1_VA_BASE+0x4)),
++ *((volatile unsigned*)(INTC_FTINTC010_1_VA_BASE+0xc)),
++ *((volatile unsigned*)(INTC_FTINTC010_1_VA_BASE+0x10)),
++ *((volatile unsigned*)(INTC_FTINTC010_1_VA_BASE+0x14)) );
+ }
++#else
++#define dump_intc()
++#endif
+
+-static void ftmac100_txdes_set_last_segment(struct ftmac100_txdes *txdes)
++#if FTMAC100_DEBUG > 2
++static void show_intstatus(unsigned char status)
+ {
+- txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_LTS);
++ static int count = 0;
++ if (status & PHYSTS_CHG_bit)
++ printk( "[%d]%s ", count, "PHYSTS_CHG" );
++ if (status & AHB_ERR_bit)
++ printk( "[%d]%s ", count, "AHB_ERR" );
++ if (status & RPKT_LOST_bit)
++ printk( "[%d]%s ", count, "RPKT_LOST" );
++ if (status & RPKT_SAV_bit)
++ printk( "[%d]%s ", count, "RPKT_SAV" );
++ if (status & XPKT_LOST_bit)
++ printk( "[%d]%s ", count, "XPKT_LOST" );
++ if (status & XPKT_OK_bit)
++ printk( "[%d]%s ", count, "XPKT_OK" );
++ if (status & NOTXBUF_bit)
++ printk( "[%d]%s ", count, "NOTXBUF" );
++ if (status & XPKT_FINISH_bit)
++ printk( "[%d]%s ", count, "XPKT_FINISH" );
++ if (status & NORXBUF_bit)
++ printk( "[%d]%s ", count, "NORXBUF" );
++ if (status & RPKT_FINISH_bit)
++ printk( "[%d]%s ", count, "RPKT_FINISH" );
++ if (status & ~(PHYSTS_CHG_bit | AHB_ERR_bit | RPKT_LOST_bit | RPKT_SAV_bit
++ | XPKT_LOST_bit | XPKT_OK_bit | NOTXBUF_bit | XPKT_FINISH_bit
++ | NORXBUF_bit | RPKT_FINISH_bit))
++ printk( "[%d]%s ", count, "<Unknown>" );
++ count++;
+ }
++#else
++#define show_intstatus(x)
++#endif
++
+
+-static void ftmac100_txdes_set_txint(struct ftmac100_txdes *txdes)
++/*
++ * The interrupt handler
++ */
++static irqreturn_t ftmac100_interrupt(int irq, void * dev_id)
+ {
+- txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXIC);
+-}
++ struct net_device *dev = dev_id;
++ unsigned int ioaddr = dev->base_addr;
++ unsigned status; // interrupt status
++ unsigned char mask; // interrupt mask
++ struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
++ unsigned long flags;
++
++ spin_lock_irqsave(&priv->lock,flags); // Luke 08/18/2005 ins
++ PRINTK(KERN_INFO "+ftmac100_interrupt\n");
++ dump_intc();
++
++ if (dev == NULL||priv == NULL) {
++ printk(KERN_WARNING "%s: irq %d for unknown device.\n", "ftmac100_interrupt", irq);
++ return IRQ_HANDLED;
++ }
++
++ /* read the interrupt status register */
++ mask = inl( ioaddr + IMR_REG );
++
++ /* read the status flag, and mask it */
++ status = inl( ioaddr + ISR_REG ) & mask;
++
++ show_intstatus(status);
++
++ if ( status & RPKT_FINISH_bit )
++ ftmac100_rcv(dev);
++
++ if (status & NORXBUF_bit) {
++ //printk("<0x%x:NORXBUF>",status);
++ outl( mask & ~NORXBUF_bit, ioaddr + IMR_REG);
++ trans_busy = 1;
++
++#if ENABLE_BOTTOM_HALF
++ priv->rcv_tq.sync = 0;
++ priv->rcv_tq.routine=ftmac100_rcv;
++ priv->rcv_tq.data = dev;
++ queue_task(&priv->rcv_tq, &tq_timer);
++ //queue_task(&priv->rcv_tq, &tq_immediate);
++#else
++ ftmac100_rcv( dev );
++#endif
++ }
++
++ if (status & AHB_ERR_bit)
++ printk("<0x%x:AHB_ERR>",status);
++
++ if (status & XPKT_FINISH_bit)
++ printk( "[XPKT_FINISH]" );
++
++ /*
++ if (status & PHYSTS_CHG_bit) {
++ }
++ */
++ if (status & XPKT_OK_bit) {
++#if ZERO_COPY
++ ftmac100_free_tx(dev,1);
++#endif
++ }
++ /*
++ if (status & NOTXBUF_bit) {
++ }
++ */
++
++ if (status & RPKT_LOST_bit)
++ priv->stats.rx_errors++;
++
++ if (status & XPKT_LOST_bit) {
++#if ZERO_COPY
++ ftmac100_free_tx(dev,1);
++#endif
++ priv->stats.tx_errors++;
++ }
++
++ PRINTK(KERN_INFO "+ftmac100_interrupt DONE\n");
++ dump_intc();
++ PRINTK(KERN_INFO "\n");
++ spin_unlock_irqrestore(&priv->lock,flags); // Luke 08/18/2005 ins
+
+-static void ftmac100_txdes_set_buffer_size(struct ftmac100_txdes *txdes,
+- unsigned int len)
+-{
+- txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXBUF_SIZE(len));
++ return IRQ_HANDLED;
+ }
+
+-static void ftmac100_txdes_set_dma_addr(struct ftmac100_txdes *txdes,
+- dma_addr_t addr)
+-{
+- txdes->txdes2 = cpu_to_le32(addr);
+-}
+
+-static dma_addr_t ftmac100_txdes_get_dma_addr(struct ftmac100_txdes *txdes)
+-{
+- return le32_to_cpu(txdes->txdes2);
+-}
+
+ /*
+- * txdes3 is not used by hardware. We use it to keep track of socket buffer.
+- * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
++ . ftmac100_rcv - receive a packet from the card
++ .
++ . There is ( at least ) a packet waiting to be read from
++ . chip-memory.
++ .
++ . o Read the status
++ . o If an error, record it
++ . o otherwise, read in the packet
+ */
+-static void ftmac100_txdes_set_skb(struct ftmac100_txdes *txdes, struct sk_buff *skb)
+-{
+- txdes->txdes3 = (unsigned int)skb;
+-}
+
+-static struct sk_buff *ftmac100_txdes_get_skb(struct ftmac100_txdes *txdes)
++static void ftmac100_rcv(void *devp)
+ {
+- return (struct sk_buff *)txdes->txdes3;
++ struct net_device *dev=(struct net_device *)devp;
++ struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
++ unsigned int ioaddr=dev->base_addr;
++ int packet_length;
++ int rcv_cnt;
++ volatile RX_DESC *cur_desc;
++ int cpy_length;
++ int cur_idx;
++ int seg_length;
++ int have_package;
++ int have_frs;
++ int start_idx;
++
++ struct sk_buff * skb;
++ unsigned char * data;
++
++ PRINTK("+ ftmac100_rcv\n");
++
++ start_idx = priv->rx_idx;
++
++ for (rcv_cnt=0; rcv_cnt<8 ; ++rcv_cnt) {
++ packet_length = 0;
++ cur_idx = priv->rx_idx;
++
++ have_package = 0;
++ have_frs = 0;
++ for (; (cur_desc = &priv->rx_descs[priv->rx_idx])->RXDMA_OWN==0; ) {
++ have_package = 1;
++ priv->rx_idx = (priv->rx_idx+1) & (RXDES_NUM-1);
++ if (cur_desc->FRS) {
++ have_frs = 1;
++ if (cur_desc->RX_ERR || cur_desc->CRC_ERR || cur_desc->FTL
++ || cur_desc->RUNT || cur_desc->RX_ODD_NB) {
++ priv->stats.rx_errors++; // error frame....
++ break;
++ }
++ if (cur_desc->MULTICAST)
++ priv->stats.multicast++;
++ packet_length = cur_desc->ReceiveFrameLength; // normal frame
++ }
++ if ( cur_desc->LRS ) // packet's last frame
++ break;
++ }
++ if (have_package==0)
++ goto done;
++ if (have_frs == 0)
++ priv->stats.rx_over_errors++;
++
++ if (packet_length>0) {
++ // Allocate enough memory for entire receive frame, to be safe
++ skb = dev_alloc_skb( packet_length + 2 );
++
++ if ( skb == NULL ) {
++ printk(KERN_NOTICE "%s: Low memory, packet dropped.\n", dev->name);
++ priv->stats.rx_dropped++;
++ goto done;
++ }
++
++ skb_reserve( skb, 2 ); /* 16 bit alignment */
++ skb->dev = dev;
++
++ data = skb_put( skb, packet_length );
++ cpy_length = 0;
++ for (; cur_idx!=priv->rx_idx; cur_idx = (cur_idx+1) & (RXDES_NUM-1)) {
++ seg_length = min(packet_length - cpy_length, RX_BUF_SIZE);
++ memcpy(data+cpy_length, (char *)priv->rx_descs[cur_idx].VIR_RXBUF_BADR, seg_length);
++ cpy_length += seg_length;
++ }
++
++ skb->protocol = eth_type_trans(skb, dev);
++ netif_rx(skb);
++ dev->last_rx = jiffies;
++ priv->stats.rx_packets++;
++ priv->stats.rx_bytes += skb->len;
++ }
++ }
++
++done:
++ if (start_idx != priv->rx_idx) {
++ for (cur_idx = (start_idx+1)%RXDES_NUM; cur_idx != priv->rx_idx; cur_idx = (cur_idx+1)%RXDES_NUM) {
++ priv->rx_descs[cur_idx].RXDMA_OWN = 1;
++ }
++ priv->rx_descs[start_idx].RXDMA_OWN = 1;
++ }
++ if (trans_busy == 1) {
++ outl( priv->maccr_val, ioaddr + MACCR_REG );
++ outl( inl(ioaddr + IMR_REG) | NORXBUF_bit, ioaddr + IMR_REG);
++ }
++
++ PRINTK("+ ftmac100_rcv DONE\n");
++
++ return;
+ }
+
+-/******************************************************************************
+- * internal functions (transmit)
+- *****************************************************************************/
+-static int ftmac100_next_tx_pointer(int pointer)
++/*
++ . ftmac100_close
++ .
++ . this makes the board clean up everything that it can
++ . and not talk to the outside world. Caused by
++ . an 'ifconfig ethX down'
++ .
++ */
++static int ftmac100_close(struct net_device *dev)
+ {
+- return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
+-}
++ //printk("+ftmac100_close\n");
+
+-static void ftmac100_tx_pointer_advance(struct ftmac100 *priv)
+-{
+- priv->tx_pointer = ftmac100_next_tx_pointer(priv->tx_pointer);
++ netif_stop_queue(dev);
++
++ ftmac100_shutdown( dev->base_addr );
++#if ZERO_COPY
++ ftmac100_free_tx(dev,0);
++#endif
++ return 0;
+ }
+
+-static void ftmac100_tx_clean_pointer_advance(struct ftmac100 *priv)
++/*
++ . Get the current statistics.
++ . This may be called with the card open or closed.
++ */
++static struct net_device_stats* ftmac100_query_statistics(struct net_device *dev)
+ {
+- priv->tx_clean_pointer = ftmac100_next_tx_pointer(priv->tx_clean_pointer);
+-}
++ struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
+
+-static struct ftmac100_txdes *ftmac100_current_txdes(struct ftmac100 *priv)
+-{
+- return &priv->descs->txdes[priv->tx_pointer];
+-}
++ PRINTK("+ftmac100_query_statistics\n");
+
+-static struct ftmac100_txdes *ftmac100_current_clean_txdes(struct ftmac100 *priv)
+-{
+- return &priv->descs->txdes[priv->tx_clean_pointer];
++ return &priv->stats;
+ }
+
+-static bool ftmac100_tx_complete_packet(struct ftmac100 *priv)
+-{
+- struct net_device *netdev = priv->netdev;
+- struct ftmac100_txdes *txdes;
+- struct sk_buff *skb;
+- dma_addr_t map;
+-
+- if (priv->tx_pending == 0)
+- return false;
+
+- txdes = ftmac100_current_clean_txdes(priv);
+-
+- if (ftmac100_txdes_owned_by_dma(txdes))
+- return false;
+-
+- skb = ftmac100_txdes_get_skb(txdes);
+- map = ftmac100_txdes_get_dma_addr(txdes);
+-
+- if (unlikely(ftmac100_txdes_excessive_collision(txdes) ||
+- ftmac100_txdes_late_collision(txdes))) {
+- /*
+- * packet transmitted to ethernet lost due to late collision
+- * or excessive collision
+- */
+- netdev->stats.tx_aborted_errors++;
+- } else {
+- netdev->stats.tx_packets++;
+- netdev->stats.tx_bytes += skb->len;
+- }
++#ifdef HAVE_MULTICAST
+
+- dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+- dev_kfree_skb(skb);
+-
+- ftmac100_txdes_reset(txdes);
+-
+- ftmac100_tx_clean_pointer_advance(priv);
+-
+- spin_lock(&priv->tx_lock);
+- priv->tx_pending--;
+- spin_unlock(&priv->tx_lock);
+- netif_wake_queue(netdev);
+-
+- return true;
+-}
++/*
++ . Function: ftmac100_setmulticast( unsigned int ioaddr, int count, dev_mc_list * adds )
++ . Purpose:
++ . This sets the internal hardware table to filter out unwanted multicast
++ . packets before they take up memory.
++ */
+
+-static void ftmac100_tx_complete(struct ftmac100 *priv)
++static void ftmac100_setmulticast( unsigned int ioaddr, int count, struct dev_mc_list * addrs )
+ {
+- while (ftmac100_tx_complete_packet(priv))
+- ;
++ struct dev_mc_list * cur_addr;
++ int crc_val;
++
++ //printk("+ftmac100_setmulticast\n");
++
++ for (cur_addr = addrs ; cur_addr!=NULL ; cur_addr = cur_addr->next ) {
++ if ( !( *cur_addr->dmi_addr & 1 ) )
++ continue;
++ crc_val = crc32( cur_addr->dmi_addr, 6 );
++ crc_val = (crc_val>>26)&0x3f; // ¨ú MSB 6 bit
++ if (crc_val >= 32)
++ outl(inl(ioaddr+MAHT1_REG) | (1UL<<(crc_val-32)), ioaddr+MAHT1_REG);
++ else
++ outl(inl(ioaddr+MAHT0_REG) | (1UL<<crc_val), ioaddr+MAHT0_REG);
++ }
+ }
+
+-static int ftmac100_xmit(struct ftmac100 *priv, struct sk_buff *skb,
+- dma_addr_t map)
+-{
+- struct net_device *netdev = priv->netdev;
+- struct ftmac100_txdes *txdes;
+- unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
+-
+- txdes = ftmac100_current_txdes(priv);
+- ftmac100_tx_pointer_advance(priv);
+-
+- /* setup TX descriptor */
+- ftmac100_txdes_set_skb(txdes, skb);
+- ftmac100_txdes_set_dma_addr(txdes, map);
+-
+- ftmac100_txdes_set_first_segment(txdes);
+- ftmac100_txdes_set_last_segment(txdes);
+- ftmac100_txdes_set_txint(txdes);
+- ftmac100_txdes_set_buffer_size(txdes, len);
+
+- spin_lock(&priv->tx_lock);
+- priv->tx_pending++;
+- if (priv->tx_pending == TX_QUEUE_ENTRIES)
+- netif_stop_queue(netdev);
+-
+- /* start transmit */
+- ftmac100_txdes_set_dma_own(txdes);
+- spin_unlock(&priv->tx_lock);
++/*
++ . ftmac100_set_multicast_list
++ .
++ . This routine will, depending on the values passed to it,
++ . either make it accept multicast packets, go into
++ . promiscuous mode ( for TCPDUMP and cousins ) or accept
++ . a select set of multicast packets
++*/
++static void ftmac100_set_multicast_list(struct net_device *dev)
++{
++ unsigned int ioaddr = dev->base_addr;
++ struct ftmac100_local *priv = (struct ftmac100_local *)netdev_priv(dev);
++
++ //printk("+ftmac100_set_multicast_list\n");
++
++ if (dev->flags & IFF_PROMISC)
++ priv->maccr_val |= RCV_ALL_bit;
++ else
++ priv->maccr_val &= ~RCV_ALL_bit;
++
++ if ( !(dev->flags & IFF_ALLMULTI) )
++ priv->maccr_val |= RX_MULTIPKT_bit;
++ else
++ priv->maccr_val &= ~RX_MULTIPKT_bit;
++
++ if (dev->mc_count) {
++ priv->maccr_val |= HT_MULTI_EN_bit;
++ ftmac100_setmulticast( ioaddr, dev->mc_count, dev->mc_list );
++ }
++ else
++ priv->maccr_val &= ~HT_MULTI_EN_bit;
+
+- ftmac100_txdma_start_polling(priv);
+- return NETDEV_TX_OK;
++ outl( priv->maccr_val, ioaddr + MACCR_REG );
+ }
++#endif
+
+-/******************************************************************************
+- * internal functions (buffer)
+- *****************************************************************************/
+-static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
+- struct ftmac100_rxdes *rxdes, gfp_t gfp)
+-{
+- struct net_device *netdev = priv->netdev;
+- struct page *page;
+- dma_addr_t map;
+-
+- page = alloc_page(gfp);
+- if (!page) {
+- if (net_ratelimit())
+- netdev_err(netdev, "failed to allocate rx page\n");
+- return -ENOMEM;
+- }
+-
+- map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
+- if (unlikely(dma_mapping_error(priv->dev, map))) {
+- if (net_ratelimit())
+- netdev_err(netdev, "failed to map rx page\n");
+- __free_page(page);
+- return -ENOMEM;
+- }
+-
+- ftmac100_rxdes_set_page(rxdes, page);
+- ftmac100_rxdes_set_dma_addr(rxdes, map);
+- ftmac100_rxdes_set_buffer_size(rxdes, RX_BUF_SIZE);
+- ftmac100_rxdes_set_dma_own(rxdes);
+- return 0;
+-}
++/*
++ * Module initialization function
++ */
+
+-static void ftmac100_free_buffers(struct ftmac100 *priv)
++static int ftmac100_probe(struct platform_device *pdev)
+ {
+- int i;
++ int result,thisresult;
++ struct net_device *dev;
++ struct resource *iores;
+
+- for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+- struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+- struct page *page = ftmac100_rxdes_get_page(rxdes);
+- dma_addr_t map = ftmac100_rxdes_get_dma_addr(rxdes);
++ PRINTK("+init_module\n");
+
+- if (!page)
+- continue;
++ result = -ENODEV;
+
+- dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+- __free_page(page);
++ dev = alloc_etherdev(sizeof(struct ftmac100_local));
++ if (!dev) {
++ printk(KERN_ERR "Fail allocating ethernet device");
++ return -ENODEV;
+ }
+-
+- for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
+- struct ftmac100_txdes *txdes = &priv->descs->txdes[i];
+- struct sk_buff *skb = ftmac100_txdes_get_skb(txdes);
+- dma_addr_t map = ftmac100_txdes_get_dma_addr(txdes);
+-
+- if (!skb)
+- continue;
+-
+- dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+- dev_kfree_skb(skb);
++ iores = platform_get_resource(pdev, IORESOURCE_IO, 0);
++ /* Copy the parameters from the platform specification */
++ dev->base_addr = iores->start;
++ dev->irq = platform_get_irq(pdev, 0);
++ dev->netdev_ops = &ftmac100_ops;
++
++ //dev->dma = nowait; // Use DMA field for nowait
++ /* Setup initial mac address */
++ auto_get_mac(pdev->id,dev->dev_addr);
++
++ if ((thisresult = register_netdev(dev)) != 0) {
++ free_irq( dev->irq, dev );
++ free_netdev(dev);
++ } else {
++ platform_set_drvdata(pdev, dev);
+ }
++ if (thisresult == 0) // any of the devices initialized, run
++ result = 0;
+
+- dma_free_coherent(priv->dev, sizeof(struct ftmac100_descs),
+- priv->descs, priv->descs_dma_addr);
++ return result;
+ }
+
+-static int ftmac100_alloc_buffers(struct ftmac100 *priv)
+-{
+- int i;
+-
+- priv->descs = dma_alloc_coherent(priv->dev, sizeof(struct ftmac100_descs),
+- &priv->descs_dma_addr, GFP_KERNEL);
+- if (!priv->descs)
+- return -ENOMEM;
+-
+- memset(priv->descs, 0, sizeof(struct ftmac100_descs));
+-
+- /* initialize RX ring */
+- ftmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
+-
+- for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+- struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+-
+- if (ftmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL))
+- goto err;
+- }
+-
+- /* initialize TX ring */
+- ftmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
+- return 0;
+-
+-err:
+- ftmac100_free_buffers(priv);
+- return -ENOMEM;
+-}
+
+-/******************************************************************************
+- * struct mii_if_info functions
+- *****************************************************************************/
+-static int ftmac100_mdio_read(struct net_device *netdev, int phy_id, int reg)
++/*
++ * Cleanup when module is removed with rmmod
++ */
++
++static int ftmac100_remove(struct platform_device *pdev)
+ {
+- struct ftmac100 *priv = netdev_priv(netdev);
+- unsigned int phycr;
+- int i;
+-
+- phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
+- FTMAC100_PHYCR_REGAD(reg) |
+- FTMAC100_PHYCR_MIIRD;
+-
+- iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
+-
+- for (i = 0; i < 10; i++) {
+- phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
+-
+- if ((phycr & FTMAC100_PHYCR_MIIRD) == 0)
+- return phycr & FTMAC100_PHYCR_MIIRDATA;
+-
+- udelay(100);
+- }
+-
+- netdev_err(netdev, "mdio read timed out\n");
++ struct net_device *dev;
++ struct ftmac100_local *priv;
++ PRINTK("+cleanup_module\n");
++
++ dev = platform_get_drvdata(pdev);
++
++ priv = (struct ftmac100_local *)netdev_priv(dev);
++ if (priv->rx_descs)
++ dma_free_coherent( NULL, sizeof(RX_DESC)*RXDES_NUM, (void*)priv->rx_descs, (dma_addr_t)priv->rx_descs_dma );
++ if (priv->rx_buf)
++ dma_free_coherent( NULL, RX_BUF_SIZE*RXDES_NUM, (void*)priv->rx_buf, (dma_addr_t)priv->rx_buf_dma );
++ if (priv->tx_descs)
++ dma_free_coherent( NULL, sizeof(TX_DESC)*TXDES_NUM, (void*)priv->tx_descs, (dma_addr_t)priv->tx_descs_dma );
++ if (priv->tx_buf)
++ dma_free_coherent( NULL, TX_BUF_SIZE*TXDES_NUM, (void*)priv->tx_buf, (dma_addr_t)priv->tx_buf_dma );
++ priv->rx_descs = NULL; priv->rx_descs_dma = 0;
++ priv->rx_buf = NULL; priv->rx_buf_dma = 0;
++ priv->tx_descs = NULL; priv->tx_descs_dma = 0;
++ priv->tx_buf = NULL; priv->tx_buf_dma = 0;
++
++ /* No need to check MOD_IN_USE, as sys_delete_module() checks. */
++ unregister_netdev(dev);
++
++ free_irq(dev->irq, dev);
++ //TODO: where is the request_region ?
++ //release_region(devFMAC.base_addr, SMC_IO_EXTENT);
++ free_netdev(dev);
+ return 0;
+ }
+
+-static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg,
+- int data)
+-{
+- struct ftmac100 *priv = netdev_priv(netdev);
+- unsigned int phycr;
+- int i;
+-
+- phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
+- FTMAC100_PHYCR_REGAD(reg) |
+- FTMAC100_PHYCR_MIIWR;
+-
+- data = FTMAC100_PHYWDATA_MIIWDATA(data);
+-
+- iowrite32(data, priv->base + FTMAC100_OFFSET_PHYWDATA);
+- iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
+-
+- for (i = 0; i < 10; i++) {
+- phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
+-
+- if ((phycr & FTMAC100_PHYCR_MIIWR) == 0)
+- return;
+-
+- udelay(100);
+- }
+-
+- netdev_err(netdev, "mdio write timed out\n");
+-}
+-
+-/******************************************************************************
+- * struct ethtool_ops functions
+- *****************************************************************************/
+-static void ftmac100_get_drvinfo(struct net_device *netdev,
+- struct ethtool_drvinfo *info)
+-{
+- strcpy(info->driver, DRV_NAME);
+- strcpy(info->version, DRV_VERSION);
+- strcpy(info->bus_info, dev_name(&netdev->dev));
+-}
+-
+-static int ftmac100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+-{
+- struct ftmac100 *priv = netdev_priv(netdev);
+- return mii_ethtool_gset(&priv->mii, cmd);
+-}
+-
+-static int ftmac100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+-{
+- struct ftmac100 *priv = netdev_priv(netdev);
+- return mii_ethtool_sset(&priv->mii, cmd);
+-}
+-
+-static int ftmac100_nway_reset(struct net_device *netdev)
++static int ftmac100_suspend(struct platform_device *pdev, pm_message_t state)
+ {
+- struct ftmac100 *priv = netdev_priv(netdev);
+- return mii_nway_restart(&priv->mii);
+-}
+-
+-static u32 ftmac100_get_link(struct net_device *netdev)
+-{
+- struct ftmac100 *priv = netdev_priv(netdev);
+- return mii_link_ok(&priv->mii);
+-}
+-
+-static const struct ethtool_ops ftmac100_ethtool_ops = {
+- .set_settings = ftmac100_set_settings,
+- .get_settings = ftmac100_get_settings,
+- .get_drvinfo = ftmac100_get_drvinfo,
+- .nway_reset = ftmac100_nway_reset,
+- .get_link = ftmac100_get_link,
+-};
+-
+-/******************************************************************************
+- * interrupt handler
+- *****************************************************************************/
+-static irqreturn_t ftmac100_interrupt(int irq, void *dev_id)
+-{
+- struct net_device *netdev = dev_id;
+- struct ftmac100 *priv = netdev_priv(netdev);
+-
+- if (likely(netif_running(netdev))) {
+- /* Disable interrupts for polling */
+- ftmac100_disable_all_int(priv);
+- napi_schedule(&priv->napi);
+- }
+-
+- return IRQ_HANDLED;
+-}
+-
+-/******************************************************************************
+- * struct napi_struct functions
+- *****************************************************************************/
+-static int ftmac100_poll(struct napi_struct *napi, int budget)
+-{
+- struct ftmac100 *priv = container_of(napi, struct ftmac100, napi);
+- struct net_device *netdev = priv->netdev;
+- unsigned int status;
+- bool completed = true;
+- int rx = 0;
+-
+- status = ioread32(priv->base + FTMAC100_OFFSET_ISR);
+-
+- if (status & (FTMAC100_INT_RPKT_FINISH | FTMAC100_INT_NORXBUF)) {
+- /*
+- * FTMAC100_INT_RPKT_FINISH:
+- * RX DMA has received packets into RX buffer successfully
+- *
+- * FTMAC100_INT_NORXBUF:
+- * RX buffer unavailable
+- */
+- bool retry;
+-
+- do {
+- retry = ftmac100_rx_packet(priv, &rx);
+- } while (retry && rx < budget);
++ struct net_device *ndev = platform_get_drvdata(pdev);
+
+- if (retry && rx == budget)
+- completed = false;
+- }
+-
+- if (status & (FTMAC100_INT_XPKT_OK | FTMAC100_INT_XPKT_LOST)) {
+- /*
+- * FTMAC100_INT_XPKT_OK:
+- * packet transmitted to ethernet successfully
+- *
+- * FTMAC100_INT_XPKT_LOST:
+- * packet transmitted to ethernet lost due to late
+- * collision or excessive collision
+- */
+- ftmac100_tx_complete(priv);
+- }
+-
+- if (status & (FTMAC100_INT_NORXBUF | FTMAC100_INT_RPKT_LOST |
+- FTMAC100_INT_AHB_ERR | FTMAC100_INT_PHYSTS_CHG)) {
+- if (net_ratelimit())
+- netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status,
+- status & FTMAC100_INT_NORXBUF ? "NORXBUF " : "",
+- status & FTMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
+- status & FTMAC100_INT_AHB_ERR ? "AHB_ERR " : "",
+- status & FTMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : "");
+-
+- if (status & FTMAC100_INT_NORXBUF) {
+- /* RX buffer unavailable */
+- netdev->stats.rx_over_errors++;
+- }
+-
+- if (status & FTMAC100_INT_RPKT_LOST) {
+- /* received packet lost due to RX FIFO full */
+- netdev->stats.rx_fifo_errors++;
+- }
+-
+- if (status & FTMAC100_INT_PHYSTS_CHG) {
+- /* PHY link status change */
+- mii_check_link(&priv->mii);
++ if (ndev) {
++ if (netif_running(ndev)) {
++ netif_device_detach(ndev);
++ ftmac100_shutdown(ndev->base_addr);
+ }
+ }
+-
+- if (completed) {
+- /* stop polling */
+- napi_complete(napi);
+- ftmac100_enable_all_int(priv);
+- }
+-
+- return rx;
+-}
+-
+-/******************************************************************************
+- * struct net_device_ops functions
+- *****************************************************************************/
+-static int ftmac100_open(struct net_device *netdev)
+-{
+- struct ftmac100 *priv = netdev_priv(netdev);
+- int err;
+-
+- err = ftmac100_alloc_buffers(priv);
+- if (err) {
+- netdev_err(netdev, "failed to allocate buffers\n");
+- goto err_alloc;
+- }
+-
+- err = request_irq(priv->irq, ftmac100_interrupt, 0, netdev->name, netdev);
+- if (err) {
+- netdev_err(netdev, "failed to request irq %d\n", priv->irq);
+- goto err_irq;
+- }
+-
+- priv->rx_pointer = 0;
+- priv->tx_clean_pointer = 0;
+- priv->tx_pointer = 0;
+- priv->tx_pending = 0;
+-
+- err = ftmac100_start_hw(priv);
+- if (err)
+- goto err_hw;
+-
+- napi_enable(&priv->napi);
+- netif_start_queue(netdev);
+-
+- ftmac100_enable_all_int(priv);
+-
+- return 0;
+-
+-err_hw:
+- free_irq(priv->irq, netdev);
+-err_irq:
+- ftmac100_free_buffers(priv);
+-err_alloc:
+- return err;
+-}
+-
+-static int ftmac100_stop(struct net_device *netdev)
+-{
+- struct ftmac100 *priv = netdev_priv(netdev);
+-
+- ftmac100_disable_all_int(priv);
+- netif_stop_queue(netdev);
+- napi_disable(&priv->napi);
+- ftmac100_stop_hw(priv);
+- free_irq(priv->irq, netdev);
+- ftmac100_free_buffers(priv);
+-
+ return 0;
+ }
+
+-static int ftmac100_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
++static int ftmac100_resume(struct platform_device *pdev)
+ {
+- struct ftmac100 *priv = netdev_priv(netdev);
+- dma_addr_t map;
+-
+- if (unlikely(skb->len > MAX_PKT_SIZE)) {
+- if (net_ratelimit())
+- netdev_dbg(netdev, "tx packet too big\n");
+-
+- netdev->stats.tx_dropped++;
+- dev_kfree_skb(skb);
+- return NETDEV_TX_OK;
+- }
++ struct net_device *ndev = platform_get_drvdata(pdev);
+
+- map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
+- if (unlikely(dma_mapping_error(priv->dev, map))) {
+- /* drop packet */
+- if (net_ratelimit())
+- netdev_err(netdev, "map socket buffer failed\n");
+-
+- netdev->stats.tx_dropped++;
+- dev_kfree_skb(skb);
+- return NETDEV_TX_OK;
++ if (ndev) {
++ if (netif_running(ndev)) {
++ ftmac100_reset(ndev);
++ ftmac100_enable(ndev);
++ netif_device_attach(ndev);
++ }
+ }
+-
+- return ftmac100_xmit(priv, skb, map);
++ return 0;
+ }
+
+-/* optional */
+-static int ftmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+-{
+- struct ftmac100 *priv = netdev_priv(netdev);
+- struct mii_ioctl_data *data = if_mii(ifr);
+-
+- return generic_mii_ioctl(&priv->mii, data, cmd, NULL);
++static void platform_device_release(struct device *dev){
+ }
+
+-static const struct net_device_ops ftmac100_netdev_ops = {
+- .ndo_open = ftmac100_open,
+- .ndo_stop = ftmac100_stop,
+- .ndo_start_xmit = ftmac100_hard_start_xmit,
+- .ndo_set_mac_address = eth_mac_addr,
+- .ndo_validate_addr = eth_validate_addr,
+- .ndo_do_ioctl = ftmac100_do_ioctl,
++static struct platform_driver ftmac100_driver = {
++ .probe = ftmac100_probe,
++ .remove = ftmac100_remove,
++ .suspend = ftmac100_suspend,
++ .resume = ftmac100_resume,
++ .driver = {
++ .name = "ftmac100",
++ },
+ };
+
+-/******************************************************************************
+- * struct platform_driver functions
+- *****************************************************************************/
+-static int ftmac100_probe(struct platform_device *pdev)
+-{
+- struct resource *res;
+- int irq;
+- struct net_device *netdev;
+- struct ftmac100 *priv;
+- int err;
+-
+- if (!pdev)
+- return -ENODEV;
+-
+- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+- if (!res)
+- return -ENXIO;
+-
+- irq = platform_get_irq(pdev, 0);
+- if (irq < 0)
+- return irq;
+-
+- /* setup net_device */
+- netdev = alloc_etherdev(sizeof(*priv));
+- if (!netdev) {
+- err = -ENOMEM;
+- goto err_alloc_etherdev;
+- }
+-
+- SET_NETDEV_DEV(netdev, &pdev->dev);
+- SET_ETHTOOL_OPS(netdev, &ftmac100_ethtool_ops);
+- netdev->netdev_ops = &ftmac100_netdev_ops;
+-
+- platform_set_drvdata(pdev, netdev);
+-
+- /* setup private data */
+- priv = netdev_priv(netdev);
+- priv->netdev = netdev;
+- priv->dev = &pdev->dev;
+-
+- spin_lock_init(&priv->tx_lock);
+-
+- /* initialize NAPI */
+- netif_napi_add(netdev, &priv->napi, ftmac100_poll, 64);
+-
+- /* map io memory */
+- priv->res = request_mem_region(res->start, resource_size(res),
+- dev_name(&pdev->dev));
+- if (!priv->res) {
+- dev_err(&pdev->dev, "Could not reserve memory region\n");
+- err = -ENOMEM;
+- goto err_req_mem;
+- }
+-
+- priv->base = ioremap(res->start, resource_size(res));
+- if (!priv->base) {
+- dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
+- err = -EIO;
+- goto err_ioremap;
+- }
+-
+- priv->irq = irq;
+-
+- /* initialize struct mii_if_info */
+- priv->mii.phy_id = 0;
+- priv->mii.phy_id_mask = 0x1f;
+- priv->mii.reg_num_mask = 0x1f;
+- priv->mii.dev = netdev;
+- priv->mii.mdio_read = ftmac100_mdio_read;
+- priv->mii.mdio_write = ftmac100_mdio_write;
+-
+- /* register network device */
+- err = register_netdev(netdev);
+- if (err) {
+- dev_err(&pdev->dev, "Failed to register netdev\n");
+- goto err_register_netdev;
+- }
+-
+- netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
+-
+- if (!is_valid_ether_addr(netdev->dev_addr)) {
+- eth_hw_addr_random(netdev);
+- netdev_info(netdev, "generated random MAC address %pM\n",
+- netdev->dev_addr);
+- }
+-
+- return 0;
+-
+-err_register_netdev:
+- iounmap(priv->base);
+-err_ioremap:
+- release_resource(priv->res);
+-err_req_mem:
+- netif_napi_del(&priv->napi);
+- platform_set_drvdata(pdev, NULL);
+- free_netdev(netdev);
+-err_alloc_etherdev:
+- return err;
+-}
+-
+-static int __exit ftmac100_remove(struct platform_device *pdev)
+-{
+- struct net_device *netdev;
+- struct ftmac100 *priv;
+-
+- netdev = platform_get_drvdata(pdev);
+- priv = netdev_priv(netdev);
+-
+- unregister_netdev(netdev);
+-
+- iounmap(priv->base);
+- release_resource(priv->res);
+-
+- netif_napi_del(&priv->napi);
+- platform_set_drvdata(pdev, NULL);
+- free_netdev(netdev);
+- return 0;
+-}
++static struct resource ftmac100_resources_a320[] = {
++ [0] = {
++ .start = MAC_FTMAC100_0_VA_BASE,
++ .end = MAC_FTMAC100_0_VA_LIMIT,
++ .flags = IORESOURCE_IO,
++ },
++ [1] = {
++ .start = MAC_FTMAC100_0_IRQ,
++ .flags = IORESOURCE_IRQ,
++ },
++};
+
+-static struct platform_driver ftmac100_driver = {
+- .probe = ftmac100_probe,
+- .remove = __exit_p(ftmac100_remove),
+- .driver = {
+- .name = DRV_NAME,
+- .owner = THIS_MODULE,
++static struct platform_device ftmac100_device_a320 = {
++ .name = "ftmac100",
++ .id = 0,
++ .num_resources = ARRAY_SIZE(ftmac100_resources_a320),
++ .resource = ftmac100_resources_a320,
++ .dev = {
++ .release = platform_device_release,
+ },
+ };
+
+-/******************************************************************************
+- * initialization / finalization
+- *****************************************************************************/
++
+ static int __init ftmac100_init(void)
+ {
+- pr_info("Loading version " DRV_VERSION " ...\n");
++ platform_device_register(&ftmac100_device_a320);
+ return platform_driver_register(&ftmac100_driver);
+ }
+
+ static void __exit ftmac100_exit(void)
+ {
+ platform_driver_unregister(&ftmac100_driver);
++ platform_device_unregister(&ftmac100_device_a320);
+ }
+
+ module_init(ftmac100_init);
+ module_exit(ftmac100_exit);
+-
+-MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
+-MODULE_DESCRIPTION("FTMAC100 driver");
+-MODULE_LICENSE("GPL");
+diff -Nur linux-3.4.110.orig/drivers/net/ethernet/faraday/ftmac100.h linux-3.4.110/drivers/net/ethernet/faraday/ftmac100.h
+--- linux-3.4.110.orig/drivers/net/ethernet/faraday/ftmac100.h 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/net/ethernet/faraday/ftmac100.h 2016-04-07 10:20:51.054085357 +0200
+@@ -1,180 +1,267 @@
+ /*
+- * Faraday FTMAC100 10/100 Ethernet
++ * drivers/net/ftmac100.h
+ *
+- * (C) Copyright 2009-2011 Faraday Technology
+- * Po-Yu Chuang <ratbert@faraday-tech.com>
++ * Faraday FTMAC100 Device Driver
+ *
+- * 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.
++ * Copyright (C) 2005 Faraday Corp. (http://www.faraday-tech.com)
++ *
++ * All Rights Reserved
+ *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+- */
+-
+-#ifndef __FTMAC100_H
+-#define __FTMAC100_H
+-
+-#define FTMAC100_OFFSET_ISR 0x00
+-#define FTMAC100_OFFSET_IMR 0x04
+-#define FTMAC100_OFFSET_MAC_MADR 0x08
+-#define FTMAC100_OFFSET_MAC_LADR 0x0c
+-#define FTMAC100_OFFSET_MAHT0 0x10
+-#define FTMAC100_OFFSET_MAHT1 0x14
+-#define FTMAC100_OFFSET_TXPD 0x18
+-#define FTMAC100_OFFSET_RXPD 0x1c
+-#define FTMAC100_OFFSET_TXR_BADR 0x20
+-#define FTMAC100_OFFSET_RXR_BADR 0x24
+-#define FTMAC100_OFFSET_ITC 0x28
+-#define FTMAC100_OFFSET_APTC 0x2c
+-#define FTMAC100_OFFSET_DBLAC 0x30
+-#define FTMAC100_OFFSET_MACCR 0x88
+-#define FTMAC100_OFFSET_MACSR 0x8c
+-#define FTMAC100_OFFSET_PHYCR 0x90
+-#define FTMAC100_OFFSET_PHYWDATA 0x94
+-#define FTMAC100_OFFSET_FCR 0x98
+-#define FTMAC100_OFFSET_BPR 0x9c
+-#define FTMAC100_OFFSET_TS 0xc4
+-#define FTMAC100_OFFSET_DMAFIFOS 0xc8
+-#define FTMAC100_OFFSET_TM 0xcc
+-#define FTMAC100_OFFSET_TX_MCOL_SCOL 0xd4
+-#define FTMAC100_OFFSET_RPF_AEP 0xd8
+-#define FTMAC100_OFFSET_XM_PG 0xdc
+-#define FTMAC100_OFFSET_RUNT_TLCC 0xe0
+-#define FTMAC100_OFFSET_CRCER_FTL 0xe4
+-#define FTMAC100_OFFSET_RLC_RCC 0xe8
+-#define FTMAC100_OFFSET_BROC 0xec
+-#define FTMAC100_OFFSET_MULCA 0xf0
+-#define FTMAC100_OFFSET_RP 0xf4
+-#define FTMAC100_OFFSET_XP 0xf8
+-
+-/*
+- * Interrupt status register & interrupt mask register
+- */
+-#define FTMAC100_INT_RPKT_FINISH (1 << 0)
+-#define FTMAC100_INT_NORXBUF (1 << 1)
+-#define FTMAC100_INT_XPKT_FINISH (1 << 2)
+-#define FTMAC100_INT_NOTXBUF (1 << 3)
+-#define FTMAC100_INT_XPKT_OK (1 << 4)
+-#define FTMAC100_INT_XPKT_LOST (1 << 5)
+-#define FTMAC100_INT_RPKT_SAV (1 << 6)
+-#define FTMAC100_INT_RPKT_LOST (1 << 7)
+-#define FTMAC100_INT_AHB_ERR (1 << 8)
+-#define FTMAC100_INT_PHYSTS_CHG (1 << 9)
+-
+-/*
+- * Interrupt timer control register
+ */
+-#define FTMAC100_ITC_RXINT_CNT(x) (((x) & 0xf) << 0)
+-#define FTMAC100_ITC_RXINT_THR(x) (((x) & 0x7) << 4)
+-#define FTMAC100_ITC_RXINT_TIME_SEL (1 << 7)
+-#define FTMAC100_ITC_TXINT_CNT(x) (((x) & 0xf) << 8)
+-#define FTMAC100_ITC_TXINT_THR(x) (((x) & 0x7) << 12)
+-#define FTMAC100_ITC_TXINT_TIME_SEL (1 << 15)
+
+-/*
+- * Automatic polling timer control register
+- */
+-#define FTMAC100_APTC_RXPOLL_CNT(x) (((x) & 0xf) << 0)
+-#define FTMAC100_APTC_RXPOLL_TIME_SEL (1 << 4)
+-#define FTMAC100_APTC_TXPOLL_CNT(x) (((x) & 0xf) << 8)
+-#define FTMAC100_APTC_TXPOLL_TIME_SEL (1 << 12)
++#ifndef _FTMAC100_H_
++#define _FTMAC100_H_
+
+-/*
+- * DMA burst length and arbitration control register
+- */
+-#define FTMAC100_DBLAC_INCR4_EN (1 << 0)
+-#define FTMAC100_DBLAC_INCR8_EN (1 << 1)
+-#define FTMAC100_DBLAC_INCR16_EN (1 << 2)
+-#define FTMAC100_DBLAC_RXFIFO_LTHR(x) (((x) & 0x7) << 3)
+-#define FTMAC100_DBLAC_RXFIFO_HTHR(x) (((x) & 0x7) << 6)
+-#define FTMAC100_DBLAC_RX_THR_EN (1 << 9)
++#define ISR_REG 0x00 // interrups status register
++#define IMR_REG 0x04 // interrupt maks register
++#define MAC_MADR_REG 0x08 // MAC address (Most significant)
++#define MAC_LADR_REG 0x0c // MAC address (Least significant)
++
++#define MAHT0_REG 0x10 // Multicast Address Hash Table 0 register
++#define MAHT1_REG 0x14 // Multicast Address Hash Table 1 register
++#define TXPD_REG 0x18 // Transmit Poll Demand register
++#define RXPD_REG 0x1c // Receive Poll Demand register
++#define TXR_BADR_REG 0x20 // Transmit Ring Base Address register
++#define RXR_BADR_REG 0x24 // Receive Ring Base Address register
++#define ITC_REG 0x28 // interrupt timer control register
++#define APTC_REG 0x2c // Automatic Polling Timer control register
++#define DBLAC_REG 0x30 // DMA Burst Length and Arbitration control register
++
++
++
++#define MACCR_REG 0x88 // MAC control register
++#define MACSR_REG 0x8c // MAC status register
++#define PHYCR_REG 0x90 // PHY control register
++#define PHYWDATA_REG 0x94 // PHY Write Data register
++#define FCR_REG 0x98 // Flow Control register
++#define BPR_REG 0x9c // back pressure register
++#define WOLCR_REG 0xa0 // Wake-On-Lan control register
++#define WOLSR_REG 0xa4 // Wake-On-Lan status register
++#define WFCRC_REG 0xa8 // Wake-up Frame CRC register
++#define WFBM1_REG 0xb0 // wake-up frame byte mask 1st double word register
++#define WFBM2_REG 0xb4 // wake-up frame byte mask 2nd double word register
++#define WFBM3_REG 0xb8 // wake-up frame byte mask 3rd double word register
++#define WFBM4_REG 0xbc // wake-up frame byte mask 4th double word register
++#define TM_REG 0xcc // test mode register
++
++#define PHYSTS_CHG_bit (1UL<<9)
++#define AHB_ERR_bit (1UL<<8)
++#define RPKT_LOST_bit (1UL<<7)
++#define RPKT_SAV_bit (1UL<<6)
++#define XPKT_LOST_bit (1UL<<5)
++#define XPKT_OK_bit (1UL<<4)
++#define NOTXBUF_bit (1UL<<3)
++#define XPKT_FINISH_bit (1UL<<2)
++#define NORXBUF_bit (1UL<<1)
++#define RPKT_FINISH_bit (1UL<<0)
++
++
++#ifdef __NDS32_EB__
++typedef struct
++{
++ unsigned int Reserved2:19;
++ unsigned int TXPOLL_TIME_SEL:1;
++ unsigned int TXPOLL_CNT:4;
++ unsigned int Reserved1:3;
++ unsigned int RXPOLL_TIME_SEL:1;
++ unsigned int RXPOLL_CNT:4;
++}FTMAC100_APTCR_Status;
++#else
++typedef struct
++{
++ unsigned int RXPOLL_CNT:4;
++ unsigned int RXPOLL_TIME_SEL:1;
++ unsigned int Reserved1:3;
++ unsigned int TXPOLL_CNT:4;
++ unsigned int TXPOLL_TIME_SEL:1;
++ unsigned int Reserved2:19;
++} FTMAC100_APTCR_Status;
++#endif
++
++#define RX_BROADPKT_bit (1UL<<17) // Receiving broadcast packet
++#define RX_MULTIPKT_bit (1UL<<16) // receiving multicast packet
++#define FULLDUP_bit (1UL<<15) // full duplex
++#define CRC_APD_bit (1UL<<14) // append crc to transmit packet
++#define MDC_SEL_bit (1UL<<13) // set MDC as TX_CK/10
++#define RCV_ALL_bit (1UL<<12) // not check incoming packet's destination address
++#define RX_FTL_bit (1UL<<11) // Store incoming packet even its length is great than 1518 byte
++#define RX_RUNT_bit (1UL<<10) // Store incoming packet even its length is les than 64 byte
++#define HT_MULTI_EN_bit (1UL<<9)
++#define RCV_EN_bit (1UL<<8) // receiver enable
++#define XMT_EN_bit (1UL<<5) // transmitter enable
++#define CRC_DIS_bit (1UL<<4)
++#define LOOP_EN_bit (1UL<<3) // Internal loop-back
++#define SW_RST_bit (1UL<<2) // software reset/
++#define RDMA_EN_bit (1UL<<1) // enable DMA receiving channel
++#define XDMA_EN_bit (1UL<<0) // enable DMA transmitting channel
++
++
++// --------------------------------------------------------------------
++// Receive Ring descriptor structure
++// --------------------------------------------------------------------
++#ifdef __NDS32_EB__
++typedef struct
++{
++ // RXDES0
++ unsigned int RXDMA_OWN:1; // 1 ==> owned by FTMAC100, 0 ==> owned by software
++ unsigned int Reserved3:1;
++ unsigned int FRS:1;
++ unsigned int LRS:1;
++ unsigned int Reserved2:5;
++ unsigned int RX_ODD_NB:1;
++ unsigned int RUNT:1;
++ unsigned int FTL:1;
++ unsigned int CRC_ERR:1; //19
++ unsigned int RX_ERR:1; //18
++ unsigned int BROARDCAST:1; //17
++ unsigned int MULTICAST:1; //16
++ unsigned int Reserved1:5; //11~15
++ unsigned int ReceiveFrameLength:11;//0~10
++
++ // RXDES1
++ unsigned int EDOTR:1;
++ unsigned int Reserved:20;
++ unsigned int RXBUF_Size:11;
++
++ // RXDES2
++ unsigned int RXBUF_BADR;
++
++ unsigned int VIR_RXBUF_BADR; // not defined, §Ú­Ì®³¨Ó©ñ receive buffer ªº virtual address
++
++}RX_DESC;
++
++
++typedef struct
++{
++ // TXDES0
++ unsigned int TXDMA_OWN:1;
++ unsigned int Reserved1:29;
++ unsigned int TXPKT_EXSCOL:1;
++ unsigned int TXPKT_LATECOL:1;
++
++ // TXDES1
++ unsigned int EDOTR:1;
++ unsigned int TXIC:1;
++ unsigned int TX2FIC:1;
++ unsigned int FTS:1;
++ unsigned int LTS:1;
++ unsigned int Reserved2:16;
++ unsigned int TXBUF_Size:11;
++
++ // RXDES2
++ unsigned int TXBUF_BADR;
++ unsigned int VIR_TXBUF_BADR;
++}TX_DESC;
++#else
++typedef struct
++{
++ // RXDES0
++ unsigned int ReceiveFrameLength:11;//0~10
++ unsigned int Reserved1:5; //11~15
++ unsigned int MULTICAST:1; //16
++ unsigned int BROARDCAST:1; //17
++ unsigned int RX_ERR:1; //18
++ unsigned int CRC_ERR:1; //19
++ unsigned int FTL:1;
++ unsigned int RUNT:1;
++ unsigned int RX_ODD_NB:1;
++ unsigned int Reserved2:5;
++ unsigned int LRS:1;
++ unsigned int FRS:1;
++ unsigned int Reserved3:1;
++ unsigned int RXDMA_OWN:1; // 1 ==> owned by FTMAC100, 0 ==> owned by software
++
++ // RXDES1
++ unsigned int RXBUF_Size:11;
++ unsigned int Reserved:20;
++ unsigned int EDOTR:1;
++
++ // RXDES2
++ unsigned int RXBUF_BADR;
++
++ unsigned int VIR_RXBUF_BADR; // not defined, §Ú­Ì®³¨Ó©ñ receive buffer ªº virtual address
++
++} RX_DESC;
++
++
++typedef struct
++{
++ // TXDES0
++ unsigned int TXPKT_LATECOL:1;
++ unsigned int TXPKT_EXSCOL:1;
++ unsigned int Reserved1:29;
++ unsigned int TXDMA_OWN:1;
++
++ // TXDES1
++ unsigned int TXBUF_Size:11;
++ unsigned int Reserved2:16;
++ unsigned int LTS:1;
++ unsigned int FTS:1;
++ unsigned int TX2FIC:1;
++ unsigned int TXIC:1;
++ unsigned int EDOTR:1;
++
++ // RXDES2
++ unsigned int TXBUF_BADR;
++ unsigned int VIR_TXBUF_BADR;
++} TX_DESC;
++#endif
++
++// waiting to do:
++#define TXPOLL_CNT 8
++#define RXPOLL_CNT 0
++
++#define OWNBY_SOFTWARE 0
++#define OWNBY_FTMAC100 1
++
++// --------------------------------------------------------------------
++// driver related definition
++// --------------------------------------------------------------------
++#define RXDES_NUM 256 // must be 2's power
++#define RX_BUF_SIZE 1536
++#define TXDES_NUM 64 // must be 2's power
++#define TX_BUF_SIZE 1536 // Luke Lee : Just bigger than 1518
++
++
++struct ftmac100_local
++{
++ // these are things that the kernel wants me to keep, so users
++ // can find out semi-useless statistics of how well the card is
++ // performing
++ struct net_device_stats stats;
++
++ // Set to true during the auto-negotiation sequence
++ int autoneg_active;
++
++ // Address of our PHY port
++ unsigned int phyaddr;
++
++ // Type of PHY
++ unsigned int phytype;
++
++ // Last contents of PHY Register 18
++ unsigned int lastPhy18;
++
++ spinlock_t lock;
++
++ volatile RX_DESC *rx_descs; // receive ring base address
++ unsigned int rx_descs_dma; // receive ring physical base address
++ char *rx_buf; // receive buffer cpu address
++ int rx_buf_dma; // receive buffer physical address
++ int rx_idx; // receive descriptor
++ //struct sk_buff *rx_skbuff[RXDES_NUM];
++
++ volatile TX_DESC *tx_descs;
++ unsigned int tx_descs_dma;
++ char *tx_buf;
++ int tx_buf_dma;
++ int tx_idx;
++ int old_tx;
++ struct sk_buff *tx_skbuff[RXDES_NUM];
++
++ int maccr_val;
++};
+
+-/*
+- * MAC control register
+- */
+-#define FTMAC100_MACCR_XDMA_EN (1 << 0)
+-#define FTMAC100_MACCR_RDMA_EN (1 << 1)
+-#define FTMAC100_MACCR_SW_RST (1 << 2)
+-#define FTMAC100_MACCR_LOOP_EN (1 << 3)
+-#define FTMAC100_MACCR_CRC_DIS (1 << 4)
+-#define FTMAC100_MACCR_XMT_EN (1 << 5)
+-#define FTMAC100_MACCR_ENRX_IN_HALFTX (1 << 6)
+-#define FTMAC100_MACCR_RCV_EN (1 << 8)
+-#define FTMAC100_MACCR_HT_MULTI_EN (1 << 9)
+-#define FTMAC100_MACCR_RX_RUNT (1 << 10)
+-#define FTMAC100_MACCR_RX_FTL (1 << 11)
+-#define FTMAC100_MACCR_RCV_ALL (1 << 12)
+-#define FTMAC100_MACCR_CRC_APD (1 << 14)
+-#define FTMAC100_MACCR_FULLDUP (1 << 15)
+-#define FTMAC100_MACCR_RX_MULTIPKT (1 << 16)
+-#define FTMAC100_MACCR_RX_BROADPKT (1 << 17)
+-
+-/*
+- * PHY control register
+- */
+-#define FTMAC100_PHYCR_MIIRDATA 0xffff
+-#define FTMAC100_PHYCR_PHYAD(x) (((x) & 0x1f) << 16)
+-#define FTMAC100_PHYCR_REGAD(x) (((x) & 0x1f) << 21)
+-#define FTMAC100_PHYCR_MIIRD (1 << 26)
+-#define FTMAC100_PHYCR_MIIWR (1 << 27)
+-
+-/*
+- * PHY write data register
+- */
+-#define FTMAC100_PHYWDATA_MIIWDATA(x) ((x) & 0xffff)
+-
+-/*
+- * Transmit descriptor, aligned to 16 bytes
+- */
+-struct ftmac100_txdes {
+- unsigned int txdes0;
+- unsigned int txdes1;
+- unsigned int txdes2; /* TXBUF_BADR */
+- unsigned int txdes3; /* not used by HW */
+-} __attribute__ ((aligned(16)));
+-
+-#define FTMAC100_TXDES0_TXPKT_LATECOL (1 << 0)
+-#define FTMAC100_TXDES0_TXPKT_EXSCOL (1 << 1)
+-#define FTMAC100_TXDES0_TXDMA_OWN (1 << 31)
+-
+-#define FTMAC100_TXDES1_TXBUF_SIZE(x) ((x) & 0x7ff)
+-#define FTMAC100_TXDES1_LTS (1 << 27)
+-#define FTMAC100_TXDES1_FTS (1 << 28)
+-#define FTMAC100_TXDES1_TX2FIC (1 << 29)
+-#define FTMAC100_TXDES1_TXIC (1 << 30)
+-#define FTMAC100_TXDES1_EDOTR (1 << 31)
+-
+-/*
+- * Receive descriptor, aligned to 16 bytes
+- */
+-struct ftmac100_rxdes {
+- unsigned int rxdes0;
+- unsigned int rxdes1;
+- unsigned int rxdes2; /* RXBUF_BADR */
+- unsigned int rxdes3; /* not used by HW */
+-} __attribute__ ((aligned(16)));
+-
+-#define FTMAC100_RXDES0_RFL 0x7ff
+-#define FTMAC100_RXDES0_MULTICAST (1 << 16)
+-#define FTMAC100_RXDES0_BROADCAST (1 << 17)
+-#define FTMAC100_RXDES0_RX_ERR (1 << 18)
+-#define FTMAC100_RXDES0_CRC_ERR (1 << 19)
+-#define FTMAC100_RXDES0_FTL (1 << 20)
+-#define FTMAC100_RXDES0_RUNT (1 << 21)
+-#define FTMAC100_RXDES0_RX_ODD_NB (1 << 22)
+-#define FTMAC100_RXDES0_LRS (1 << 28)
+-#define FTMAC100_RXDES0_FRS (1 << 29)
+-#define FTMAC100_RXDES0_RXDMA_OWN (1 << 31)
++#endif
+
+-#define FTMAC100_RXDES1_RXBUF_SIZE(x) ((x) & 0x7ff)
+-#define FTMAC100_RXDES1_EDORR (1 << 31)
+
+-#endif /* __FTMAC100_H */
+diff -Nur linux-3.4.110.orig/drivers/net/ethernet/faraday/Kconfig linux-3.4.110/drivers/net/ethernet/faraday/Kconfig
+--- linux-3.4.110.orig/drivers/net/ethernet/faraday/Kconfig 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/net/ethernet/faraday/Kconfig 2016-04-07 10:20:51.054085357 +0200
+@@ -5,7 +5,7 @@
+ config NET_VENDOR_FARADAY
+ bool "Faraday devices"
+ default y
+- depends on ARM
++ depends on ARM || NDS32
+ ---help---
+ If you have a network (Ethernet) card belonging to this class, say Y
+ and read the Ethernet-HOWTO, available from
+@@ -20,7 +20,7 @@
+
+ config FTMAC100
+ tristate "Faraday FTMAC100 10/100 Ethernet support"
+- depends on ARM
++ depends on ARM || NDS32
+ select NET_CORE
+ select MII
+ ---help---
+diff -Nur linux-3.4.110.orig/drivers/pci/Makefile linux-3.4.110/drivers/pci/Makefile
+--- linux-3.4.110.orig/drivers/pci/Makefile 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/pci/Makefile 2016-04-07 10:20:51.054085357 +0200
+@@ -49,6 +49,7 @@
+ obj-$(CONFIG_MICROBLAZE) += setup-bus.o
+ obj-$(CONFIG_TILE) += setup-bus.o setup-irq.o
+ obj-$(CONFIG_SPARC_LEON) += setup-bus.o setup-irq.o
++obj-$(CONFIG_NDS32) += setup-bus.o setup-irq.o
+
+ #
+ # ACPI Related PCI FW Functions
+diff -Nur linux-3.4.110.orig/drivers/rtc/Kconfig linux-3.4.110/drivers/rtc/Kconfig
+--- linux-3.4.110.orig/drivers/rtc/Kconfig 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/rtc/Kconfig 2016-04-07 10:20:51.054085357 +0200
+@@ -779,6 +779,16 @@
+ This driver can also be built as a module. If so, the module
+ will be called rtc-ep93xx.
+
++config RTC_DRV_FTRTC010
++ tristate "Faraday Real Time Clock"
++ depends on NDS32
++ help
++ If you say Y here you will get access to the real time clock
++ built into your AG101 CPU.
++
++ To compile this driver as a module, choose M here: the
++ module will be called rtc-ftrtc010.
++
+ config RTC_DRV_SA1100
+ tristate "SA11x0/PXA2xx/PXA910"
+ depends on ARCH_SA1100 || ARCH_PXA || ARCH_MMP
+diff -Nur linux-3.4.110.orig/drivers/rtc/Makefile linux-3.4.110/drivers/rtc/Makefile
+--- linux-3.4.110.orig/drivers/rtc/Makefile 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/rtc/Makefile 2016-04-07 10:20:51.054085357 +0200
+@@ -50,6 +50,7 @@
+ obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o
+ obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o
+ obj-$(CONFIG_RTC_DRV_IMXDI) += rtc-imxdi.o
++obj-$(CONFIG_RTC_DRV_FTRTC010) += rtc-ftrtc010.o
+ obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o
+ obj-$(CONFIG_RTC_DRV_ISL12022) += rtc-isl12022.o
+ obj-$(CONFIG_RTC_DRV_JZ4740) += rtc-jz4740.o
+diff -Nur linux-3.4.110.orig/drivers/rtc/rtc-ftrtc010.c linux-3.4.110/drivers/rtc/rtc-ftrtc010.c
+--- linux-3.4.110.orig/drivers/rtc/rtc-ftrtc010.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/rtc/rtc-ftrtc010.c 2016-04-07 10:20:51.054085357 +0200
+@@ -0,0 +1,371 @@
++/*
++ * Faraday RTC Support
++ *
++ * Copyright (C) 2006, 2007, 2008 Paul Mundt
++ * Copyright (C) 2006 Jamie Lenehan
++ * Copyright (C) 2008 Angelo Castello
++ * Copyright (C) 2008 Roy Lee
++ *
++ * Based on the old arch/sh/kernel/cpu/rtc.c by:
++ *
++ * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
++ * Copyright (C) 1999 Tetsuya Okada & Niibe Yutaka
++ *
++ * This file is subject to the terms and conditions of the GNU General Public
++ * License. See the file "COPYING" in the main directory of this archive
++ * for more details.
++ */
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/rtc.h>
++#include <linux/delay.h>
++#include <linux/init.h>
++#include <linux/platform_device.h>
++#include <linux/seq_file.h>
++#include <linux/interrupt.h>
++#include <linux/io.h>
++
++#define PCLK ( AHB_CLK_IN / 2)
++
++#define DRV_NAME "faraday-rtc"
++
++#define RTC_REG( off) ( *( volatile unsigned long *)( rtc->regbase + ( off)))
++
++#define RTC_CR RTC_REG( 0x20) /* Control */
++#define RTC_CR_IE ( 0x1UL << 0)
++#define RTC_CR_IES ( 0x1UL << 1)
++#define RTC_CR_IEM ( 0x1UL << 2)
++#define RTC_CR_IEH ( 0x1UL << 3)
++#define RTC_CR_IED ( 0x1UL << 4)
++#define RTC_CR_ALRM ( 0x1UL << 5)
++#define RTC_CR_LOAD ( 0x1UL << 6)
++
++#define RTC_RR RTC_REG( 0x1C) /* RTC Record Register */
++#define RTC_DIV RTC_REG( 0x38) /* RTC Divede Register */
++#define RTC_REV RTC_REG( 0x3C) /* RTC Divede Register */
++
++#define RTC_IR RTC_REG( 0x34) /* RTC interrupt state */
++#define RTC_IR_IES ( 0x1UL << 0) /* RTC interrupt state */
++#define RTC_IR_IEM ( 0x1UL << 1) /* RTC interrupt state */
++#define RTC_IR_IEH ( 0x1UL << 2) /* RTC interrupt state */
++#define RTC_IR_IED ( 0x1UL << 3) /* RTC interrupt state */
++#define RTC_IR_ALRM ( 0x1UL << 4) /* RTC interrupt state */
++
++#define RTC_SECOND RTC_REG( 0x00) /* RTC sec */
++#define RTC_MINUTE RTC_REG( 0x04) /* RTC min */
++#define RTC_HOUR RTC_REG( 0x08) /* RTC hour */
++#define RTC_DAYS RTC_REG( 0x0C) /* RTC day */
++
++#define RTC_ALRM_SECOND RTC_REG( 0x10) /* RTC alarm sec */
++#define RTC_ALRM_MINUTE RTC_REG( 0x14) /* RTC alarm min */
++#define RTC_ALRM_HOUR RTC_REG( 0x18) /* RTC alarm hour */
++
++#define RTC_WRITE_SECOND RTC_REG( 0x24) /* RTC write port for sec */
++#define RTC_WRITE_MINUTE RTC_REG( 0x28) /* RTC write port for min */
++#define RTC_WRITE_HOUR RTC_REG( 0x2C) /* RTC write port for hour */
++#define RTC_WRITE_DAYS RTC_REG( 0x30) /* RTC write port for day */
++
++struct ft_rtc{
++
++ void __iomem *regbase;
++ struct resource *res;
++ unsigned int alarm_irq;
++ unsigned int interrupt_irq;
++ struct rtc_device *rtc_dev;
++ spinlock_t lock; /* Protects this structure */
++};
++
++struct ft_rtc rtc_platform_data;
++
++static irqreturn_t ft_rtc_interrupt( int irq, void *dev_id){
++
++ struct ft_rtc *rtc = dev_id;
++ if( RTC_IR & RTC_IR_IES){
++
++ RTC_IR &= ~RTC_IR_IES;
++ rtc_update_irq( rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
++
++ return IRQ_HANDLED;
++ }
++
++ return IRQ_NONE;
++}
++
++static irqreturn_t ft_rtc_alarm( int irq, void *dev_id){
++
++ struct ft_rtc *rtc = dev_id;
++ if( RTC_IR & RTC_IR_ALRM){
++
++ RTC_CR &= ~RTC_CR_ALRM;
++ RTC_IR &= ~RTC_IR_ALRM;
++ rtc_update_irq( rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
++
++ return IRQ_HANDLED;
++ }
++
++ return IRQ_NONE;
++}
++
++static void ft_rtc_release( struct device *dev){
++
++ struct ft_rtc *rtc = dev_get_drvdata( dev);
++
++ RTC_CR &= ~RTC_CR_IES;
++ RTC_CR &= ~RTC_CR_ALRM;
++}
++
++/* rick add */
++static int ft_alarm_irq_enable(struct device *dev, unsigned int enabled)
++{
++// printk("\n\nft_alarm_irq_enable\n\n");
++
++ struct ft_rtc *rtc = dev_get_drvdata( dev);
++ spin_lock_irq(&rtc->lock);
++ if (enabled)
++ RTC_CR |= RTC_CR_ALRM;
++ else
++ RTC_CR &= ~RTC_CR_ALRM;
++ spin_unlock_irq(&rtc->lock);
++ return 0;
++}
++
++static int ft_rtc_read_time( struct device *dev, struct rtc_time *tm){
++ struct ft_rtc *rtc = dev_get_drvdata( dev);
++ unsigned long time = RTC_DAYS * 86400 + RTC_HOUR * 3600 + RTC_MINUTE * 60 + RTC_SECOND;
++ rtc_time_to_tm( time, tm);
++ if( rtc_valid_tm( tm) < 0) {
++ dev_err( dev, "invalid date\n");
++ rtc_time_to_tm( 0, tm);
++ }
++ return 0;
++}
++
++static int ft_rtc_set_time( struct device *dev, struct rtc_time *tm){
++
++ struct ft_rtc *rtc = dev_get_drvdata( dev);
++ unsigned long time = 0;
++
++ rtc_tm_to_time( tm, &time);
++
++ RTC_WRITE_DAYS = time / 86400;
++ time %= 86400;
++
++ RTC_WRITE_HOUR = time / 3600;
++ time %= 3600;
++
++ RTC_WRITE_MINUTE = time / 60;
++ time %= 60;
++
++ RTC_WRITE_SECOND = time;
++
++ RTC_CR |= RTC_CR_LOAD;
++
++ return 0;
++}
++
++static int ft_rtc_read_alarm( struct device *dev, struct rtc_wkalrm *wkalrm){
++
++ struct ft_rtc *rtc = dev_get_drvdata( dev);
++ struct rtc_time *tm = &wkalrm->time;
++
++ tm->tm_sec = RTC_ALRM_SECOND;
++ tm->tm_min = RTC_ALRM_MINUTE;
++ tm->tm_hour = RTC_ALRM_HOUR;
++
++ wkalrm->enabled = ( RTC_CR & RTC_CR_ALRM) ? 1 : 0;
++
++ return 0;
++}
++
++static int ft_rtc_set_alarm( struct device *dev, struct rtc_wkalrm *wkalrm){
++
++ struct ft_rtc *rtc = dev_get_drvdata( dev);
++ struct rtc_time *tm = &wkalrm->time;
++ int err = rtc_valid_tm( tm);
++ if( err < 0){
++
++ dev_err( dev, "invalid alarm value\n");
++ return err;
++ }
++
++ /* disable alarm interrupt and clear the alarm flag */
++ RTC_CR &= ~RTC_CR_ALRM;
++
++ /* set alarm time */
++ RTC_ALRM_SECOND = tm->tm_sec;
++ RTC_ALRM_MINUTE = tm->tm_min;
++ RTC_ALRM_HOUR = tm->tm_hour;
++
++ if( wkalrm->enabled)
++ RTC_CR |= RTC_CR_ALRM;
++
++ return 0;
++}
++
++/*
++static int ft_rtc_irq_set_state( struct device *dev, int enabled){
++ struct ft_rtc *rtc = dev_get_drvdata( dev);
++ if( enabled)
++ RTC_CR |= RTC_CR_IES;
++ else
++ RTC_CR &= ~RTC_CR_IES;
++
++ return 0;
++}
++
++*/
++
++static struct rtc_class_ops ft_rtc_ops = {
++
++ .release = ft_rtc_release,
++ .alarm_irq_enable = ft_alarm_irq_enable,
++
++ .read_time = ft_rtc_read_time,
++ .set_time = ft_rtc_set_time,
++ .read_alarm = ft_rtc_read_alarm,
++ .set_alarm = ft_rtc_set_alarm,
++};
++
++static int __devinit ft_rtc_probe( struct platform_device *pdev){
++
++ struct ft_rtc *rtc = &rtc_platform_data;
++ int ret = -ENOENT;
++ spin_lock_init(&rtc->lock);
++
++ if( ( rtc->alarm_irq = platform_get_irq( pdev, 0)) < 0)
++ goto err_exit;
++
++ if( ( rtc->interrupt_irq = platform_get_irq( pdev, 1)) < 0)
++ goto err_exit;
++
++ if( !( rtc->res = platform_get_resource( pdev, IORESOURCE_MEM, 0)))
++ goto err_exit;
++
++ if( ( ret = request_irq( rtc->alarm_irq , ft_rtc_alarm, 0, "RTC Alarm : ftrtc010", rtc)))
++ goto err_exit;
++
++ if( ( ret = request_irq( rtc->interrupt_irq , ft_rtc_interrupt, 0, "RTC Interrupt : ftrtc010", rtc)))
++ goto err_interrupt_irq;
++
++ ret = -EBUSY;
++
++ if( !( rtc->res = request_mem_region( rtc->res->start, rtc->res->end - rtc->res->start + 1, pdev->name)))
++ goto err_request_region;
++
++ ret = -EINVAL;
++
++ if( !( rtc->regbase = ioremap_nocache( rtc->res->start, rtc->res->end - rtc->res->start + 1)))
++ goto err_ioremap1;
++
++
++ //RTC_DIV = ( 0x1UL << 31) | 2; /* AG101 */
++ RTC_CR |= RTC_CR_IE;
++ platform_set_drvdata( pdev, rtc);
++ device_init_wakeup(&pdev->dev, true);
++
++ rtc->rtc_dev = rtc_device_register( DRV_NAME, &pdev->dev, &ft_rtc_ops, THIS_MODULE);
++
++ if( IS_ERR( rtc->rtc_dev)) {
++
++ ret = PTR_ERR( rtc->rtc_dev);
++ goto err_unmap;
++ }
++
++ rtc->rtc_dev->max_user_freq = 256;
++ rtc->rtc_dev->irq_freq = 1;
++ return 0;
++
++err_unmap:
++ iounmap( rtc->regbase);
++err_ioremap1:
++ release_resource( rtc->res);
++err_request_region:
++ free_irq( rtc->interrupt_irq, rtc);
++err_interrupt_irq:
++ free_irq( rtc->alarm_irq, rtc);
++err_exit:
++ return ret;
++}
++
++static int __devexit ft_rtc_remove( struct platform_device *pdev){
++
++ struct ft_rtc *rtc = platform_get_drvdata( pdev);
++
++ rtc_device_unregister( rtc->rtc_dev);
++
++ RTC_CR &= ~RTC_CR_ALRM;
++
++ free_irq( rtc->alarm_irq, rtc);
++ free_irq( rtc->interrupt_irq, rtc);
++
++ iounmap( rtc->regbase);
++
++ platform_set_drvdata( pdev, NULL);
++
++ return 0;
++}
++
++static void platform_device_release(struct device *dev){
++}
++
++static struct resource rtc_resources[] = {
++ {
++ .start = RTC_FTRTC010_PA_BASE,
++ .end = RTC_FTRTC010_PA_LIMIT,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = RTC_FTRTC010_IRQ0,
++ .end = RTC_FTRTC010_IRQ0,
++ .flags = IORESOURCE_IRQ,
++ },
++ {
++ .start = RTC_FTRTC010_IRQ1,
++ .end = RTC_FTRTC010_IRQ1,
++ .flags = IORESOURCE_IRQ,
++ },
++};
++
++static struct platform_driver ft_rtc_platform_driver = {
++
++ .driver = {
++ .name = DRV_NAME,
++ .owner = THIS_MODULE,
++ },
++ .probe = ft_rtc_probe,
++ .remove = __devexit_p( ft_rtc_remove),
++};
++
++static struct platform_device rtc_device = {
++
++ .name = DRV_NAME,
++ .id = 0,
++ .resource = rtc_resources,
++ .num_resources = ARRAY_SIZE( rtc_resources),
++ .dev = {
++ .platform_data = &rtc_platform_data,
++ .release = platform_device_release,
++ },
++};
++
++static int __init ft_rtc_init( void){
++ platform_device_register( &rtc_device);
++ return platform_driver_register( &ft_rtc_platform_driver);
++}
++
++static void __exit ft_rtc_exit( void){
++
++ platform_driver_unregister( &ft_rtc_platform_driver);
++ platform_device_unregister( &rtc_device);
++}
++
++module_init( ft_rtc_init);
++module_exit( ft_rtc_exit);
++
++MODULE_DESCRIPTION( "SuperH on-chip RTC driver");
++MODULE_AUTHOR( "Paul Mundt <lethal@linux-sh.org>, "
++ "Jamie Lenehan <lenehan@twibble.org>, "
++ "Angelo Castello <angelo.castello@st.com>, "
++ "Roy Lee <roylee@andestech.com>");
++MODULE_LICENSE( "GPL");
++MODULE_ALIAS( "platform:" DRV_NAME);
+diff -Nur linux-3.4.110.orig/drivers/tty/serial/8250/8250.c linux-3.4.110/drivers/tty/serial/8250/8250.c
+--- linux-3.4.110.orig/drivers/tty/serial/8250/8250.c 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/tty/serial/8250/8250.c 2016-04-07 10:20:51.054085357 +0200
+@@ -570,6 +570,7 @@
+ serial_out(up, UART_ICR, value);
+ }
+
++#ifndef CONFIG_NDS32
+ static unsigned int serial_icr_read(struct uart_8250_port *up, int offset)
+ {
+ unsigned int value;
+@@ -581,6 +582,7 @@
+
+ return value;
+ }
++#endif
+
+ /*
+ * FIFO support.
+@@ -722,6 +724,7 @@
+ return count;
+ }
+
++#ifndef CONFIG_NDS32
+ /*
+ * Read UART ID using the divisor method - set DLL and DLM to zero
+ * and the revision will be in DLL and device type in DLM. We
+@@ -749,7 +752,9 @@
+
+ return id;
+ }
++#endif
+
++#ifndef CONFIG_NDS32
+ /*
+ * This is a helper routine to autodetect StarTech/Exar/Oxsemi UART's.
+ * When this function is called we know it is at least a StarTech
+@@ -842,6 +847,7 @@
+ else
+ up->port.type = PORT_16650V2;
+ }
++#endif
+
+ /*
+ * We detected a chip without a FIFO. Only two fall into
+@@ -865,6 +871,7 @@
+ up->port.type = PORT_16450;
+ }
+
++#ifndef CONFIG_NDS32
+ static int broken_efr(struct uart_8250_port *up)
+ {
+ /*
+@@ -877,6 +884,7 @@
+
+ return 0;
+ }
++#endif
+
+ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
+ {
+@@ -908,7 +916,7 @@
+
+ up->port.type = PORT_16550A;
+ up->capabilities |= UART_CAP_FIFO;
+-
++#ifndef CONFIG_NDS32
+ /*
+ * Check for presence of the EFR when DLAB is set.
+ * Only ST16C650V1 UARTs pass this test.
+@@ -937,6 +945,7 @@
+ autoconfig_has_efr(up);
+ return;
+ }
++#endif
+
+ /*
+ * Check for a National Semiconductor SuperIO chip.
+@@ -1156,10 +1165,11 @@
+ * We also initialise the EFR (if any) to zero for later. The
+ * EFR occupies the same register location as the FCR and IIR.
+ */
++#ifndef CONFIG_NDS32
+ serial_out(up, UART_LCR, UART_LCR_CONF_MODE_B);
+ serial_out(up, UART_EFR, 0);
+ serial_out(up, UART_LCR, 0);
+-
++#endif
+ serial_out(up, UART_FCR, UART_FCR_ENABLE_FIFO);
+ scratch = serial_in(up, UART_IIR) >> 6;
+
+diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/faradayfb.h linux-3.4.110/drivers/video/FTLCDC100/faradayfb.h
+--- linux-3.4.110.orig/drivers/video/FTLCDC100/faradayfb.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/video/FTLCDC100/faradayfb.h 2016-04-07 10:20:51.058085512 +0200
+@@ -0,0 +1,215 @@
++#ifndef __FARADAYFB_H
++#define __FARADAYFB_H
++
++#define FARADAYFB_MODULE_NAME "faradayfb"
++#define DEBUG(enabled, tagged, ...) \
++ do { \
++ if (enabled) { \
++ if (tagged) \
++ printk("[ %30s() ] ", __func__); \
++ printk(__VA_ARGS__); \
++ } \
++ } while (0)
++
++#if defined(CONFIG_FFB_MODE_RGB)
++# define DEFAULT_COLOR FFB_MODE_RGB
++#elif defined(CONFIG_FFB_MODE_YUV422)
++# define DEFAULT_COLOR FFB_MODE_YUV422
++#elif defined(CONFIG_FFB_MODE_YUV420)
++# define DEFAULT_COLOR FFB_MODE_YUV420
++#endif
++
++#if defined(CONFIG_FFB_MODE_8BPP)
++# define DEFAULT_BPP FFB_MODE_8BPP
++#elif defined(CONFIG_FFB_MODE_16BPP)
++# define DEFAULT_BPP FFB_MODE_16BPP
++#elif defined(CONFIG_FFB_MODE_24BPP)
++# define DEFAULT_BPP FFB_MODE_24BPP
++#endif
++
++#define FFB_DEFAULT_MODE (DEFAULT_COLOR | DEFAULT_BPP)
++
++struct lcd_param {
++
++ unsigned long value;
++ unsigned long flags;
++};
++
++inline struct lcd_param* get_lcd_time(struct lcd_param* array, unsigned long num_array, unsigned long type)
++{
++ int i;
++
++ for (i = 0; i < num_array; i++) {
++
++ struct lcd_param *r = &array[i];
++
++ if (r->flags & type & 0xff)
++ return r;
++ }
++
++ return NULL;
++}
++
++inline struct lcd_param* get_lcd_ctrl(struct lcd_param* array, unsigned long num_array, unsigned long type)
++{
++ int i;
++
++ for (i = 0; i < num_array; i++) {
++
++ struct lcd_param *r = &array[i];
++
++ if ((r->flags & type & 0xff) && (r->flags & type & 0xff00))
++ return r;
++ }
++
++ return NULL;
++}
++
++enum { RGB_8, RGB_16, RGB_24, NR_RGB};
++
++struct faradayfb_rgb {
++
++ struct fb_bitfield red;
++ struct fb_bitfield green;
++ struct fb_bitfield blue;
++ struct fb_bitfield transp;
++};
++
++/* This structure describes the machine which we are running on. */
++struct faradayfb_mach_info {
++
++ unsigned long num_time0;
++ struct lcd_param * time0;
++
++ unsigned long num_time1;
++ struct lcd_param * time1;
++
++ unsigned long num_time2;
++ struct lcd_param * time2;
++
++ unsigned long num_control;
++ struct lcd_param * control;
++
++ unsigned long pixclock;
++
++ unsigned long xres;
++ unsigned long yres;
++
++ unsigned int max_bpp;
++ unsigned int sync;
++
++ unsigned int cmap_greyscale:1,
++ cmap_inverse:1,
++ cmap_static:1,
++ unused:29;
++};
++
++struct faradayfb_info {
++
++ struct fb_info *info;
++ struct faradayfb_rgb *rgb[NR_RGB];
++
++ unsigned int xres;
++ unsigned int yres;
++ unsigned int max_bpp;
++
++ /*
++ * These are the addresses we mapped
++ * the framebuffer memory region to.
++ */
++ dma_addr_t map_dma;
++ unsigned char * map_cpu;
++ unsigned int map_size;
++
++ unsigned char * screen_cpu;
++ dma_addr_t screen_dma;
++ u32 * palette_cpu;
++ dma_addr_t palette_dma;
++ unsigned int palette_size;
++
++ unsigned int cmap_inverse:1,
++ cmap_static:1,
++ unused:30;
++
++ unsigned long time0;
++ unsigned long time1;
++ unsigned long time2;
++ unsigned long control;
++ unsigned long int_mask;
++ unsigned long io_base;
++
++ unsigned int state;
++ unsigned int task_state;
++ struct semaphore ctrlr_sem;
++ wait_queue_head_t ctrlr_wait;
++ struct work_struct task;
++
++ unsigned long smode;
++ unsigned long frame420_size;
++};
++
++/*
++ * These are the actions for set_ctrlr_state
++ */
++#define C_DISABLE 0
++#define C_ENABLE 1
++#define C_DISABLE_CLKCHANGE 2
++#define C_ENABLE_CLKCHANGE 3
++#define C_REENABLE 4
++#define C_DISABLE_PM 5
++#define C_ENABLE_PM 6
++#define C_STARTUP 7
++
++#define FARADAY_LCDTIME0_GET_HBP(x) ((((x) >> 24) & 0xFF) + 1)
++#define FARADAY_LCDTIME0_GET_HFP(x) ((((x) >> 16) & 0xFF) + 1)
++#define FARADAY_LCDTIME0_GET_HW(x) ((((x) >> 8) & 0xFF) + 1)
++#define FARADAY_LCDTIME1_GET_VBP(x) ((((x) >> 24) & 0xFF) )
++#define FARADAY_LCDTIME1_GET_VFP(x) ((((x) >> 16) & 0xFF) )
++#define FARADAY_LCDTIME1_GET_VW(x) ((((x) >> 8) & 0xFF) + 1)
++
++#define FARADAY_LCDTIME0_HBP(x) ((((x) - 1) & 0xFF) << 24)
++#define FARADAY_LCDTIME0_HFP(x) ((((x) - 1) & 0xFF) << 16)
++#define FARADAY_LCDTIME0_HW(x) ((((x) - 1) & 0xFF) << 8)
++#define FARADAY_LCDTIME0_PL(x) (((((x) >> 4) - 1) & 0x3F) << 2)
++#define FARADAY_LCDTIME1_VBP(x) ((((x) ) & 0xFF) << 24)
++#define FARADAY_LCDTIME1_VFP(x) ((((x) ) & 0xFF) << 16)
++#define FARADAY_LCDTIME1_VW(x) ((((x) - 1) & 0xFF) << 8)
++#define FARADAY_LCDTIME1_LF(x) ((((x) - 1) & 0x3FF) )
++
++#define FFB_MODE_RGB 0x00000001
++#define FFB_MODE_YUV420 0x00000002
++#define FFB_MODE_YUV422 0x00000004
++
++#define FFB_MODE_8BPP 0x00000100
++#define FFB_MODE_16BPP 0x00000200
++#define FFB_MODE_24BPP 0x00000400
++
++/* Minimum X and Y resolutions */
++#define MIN_XRES 64
++#define MIN_YRES 64
++
++typedef struct LCDTag {
++
++ u32 Timing0; /* 0x00 */
++ u32 Timing1; /* 0x04 */
++ u32 Timing2; /* 0x08 */
++ u32 Timing3; /* 0x0C */
++ u32 UPBase; /* 0x10 */
++ u32 LPBase; /* 0x14 */
++ u32 INTREnable; /* 0x18 */
++ u32 Control; /* 0x1C */
++ u32 Status; /* 0x20 */
++ u32 Interrupt; /* 0x24 */
++ u32 UPCurr; /* 0x28 */
++ u32 LPCurr; /* 0x2C */
++ u32 Reserved1[5]; /* 0x30~0x40 */
++ u32 GPIO; /* 0x44 */
++ u32 Reserved2[0x74 - 6]; /* 0x48~0x1FC */
++
++ u32 Palette[0x80]; /* 0x200~0x3FC */
++ u32 TestReg[0x100]; /* 0x400~0x7FC */
++
++} LCD_Register;
++
++#endif /* __FARADAYFB_H */
++
+diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/faradayfb-main.c linux-3.4.110/drivers/video/FTLCDC100/faradayfb-main.c
+--- linux-3.4.110.orig/drivers/video/FTLCDC100/faradayfb-main.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/video/FTLCDC100/faradayfb-main.c 2016-04-07 10:20:51.058085512 +0200
+@@ -0,0 +1,911 @@
++#include <linux/module.h>
++#include <linux/fb.h>
++#include <linux/delay.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/interrupt.h>
++#include <linux/platform_device.h>
++
++#include <asm/uaccess.h>
++#include <asm/atomic.h>
++#include <asm/mach-types.h>
++
++#include "faradayfb.h"
++#include "lcd-info.c"
++#include "pingpong-module.c"
++
++static u32 faradayfb_pseudo_palette[32];
++static inline void faradayfb_lcd_power(struct fb_info *info, int on)
++{
++ struct faradayfb_info *fbi = info->par;
++ volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
++
++ if (on)
++ fbi->control |= (1UL << 11);
++ else
++ fbi->control &= ~(1UL << 11);
++
++ plcd->Control = fbi->control;
++}
++
++static void faradayfb_setup_gpio(struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
++
++ plcd->GPIO = 0x010000;
++}
++
++static inline void faradayfb_pmu_on(void)
++{
++ REG32(PMU_FTPMU010_VA_BASE + 0x44) |= 0x00700000;
++}
++
++static inline void faradayfb_pmu_off(void)
++{
++ REG32(PMU_FTPMU010_VA_BASE + 0x44) &= ~0x00700000;
++}
++
++static void faradayfb_enable_controller(struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
++
++ plcd->Timing0 = fbi->time0;
++ plcd->Timing1 = fbi->time1;
++ plcd->Timing2 = fbi->time2;
++ plcd->Control = fbi->control & ~0x01;
++
++ plcd->UPBase = fbi->screen_dma | fbi->frame420_size;
++
++ faradayfb_pmu_on();
++ plcd->Control |= 0x01;
++
++ DEBUG(0, 1, "Time0 = 0x%08x\n", plcd->Timing0);
++ DEBUG(0, 1, "Time1 = 0x%08x\n", plcd->Timing1);
++ DEBUG(0, 1, "Time2 = 0x%08x\n", plcd->Timing2);
++ DEBUG(0, 1, "Control = 0x%08x\n", plcd->Control);
++ DEBUG(0, 1, "UPBase = 0x%08x\n", plcd->UPBase);
++}
++
++static void faradayfb_disable_controller(struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
++ DECLARE_WAITQUEUE(wait, current);
++
++ set_current_state(TASK_UNINTERRUPTIBLE);
++ add_wait_queue(&fbi->ctrlr_wait, &wait);
++
++ fbi->control &= ~0x0001;
++ plcd->Control = fbi->control;
++ faradayfb_pmu_off();
++
++ schedule_timeout(20 * HZ / 1000);
++ remove_wait_queue(&fbi->ctrlr_wait, &wait);
++}
++
++static void faradayfb_enable_int(struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
++
++ plcd->INTREnable = fbi->int_mask;
++}
++
++static void faradayfb_disable_int(struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
++
++ fbi->int_mask = plcd->INTREnable;
++ plcd->INTREnable = 0;
++ plcd->Status = 0x1e;
++}
++
++static struct faradayfb_rgb def_rgb_8 = {
++
++ .red = { .offset = 0, .length = 4 },
++ .green = { .offset = 0, .length = 4 },
++ .blue = { .offset = 0, .length = 4 },
++ .transp = { .offset = 0, .length = 0 },
++};
++
++static struct faradayfb_rgb def_rgb_16 = {
++
++ .red = { .offset = 11, .length = 5, .msb_right = 0 },
++ .green = { .offset = 5, .length = 6, .msb_right = 0 },
++ .blue = { .offset = 0, .length = 5, .msb_right = 0 },
++ .transp = { .offset = 15, .length = 0, .msb_right = 0 },
++};
++
++static struct faradayfb_rgb def_rgb_24 = {
++
++ .red = { .offset = 16, .length = 8, .msb_right = 0 },
++ .green = { .offset = 8, .length = 8, .msb_right = 0 },
++ .blue = { .offset = 0, .length = 8, .msb_right = 0 },
++ .transp = { .offset = 0, .length = 0, .msb_right = 0 },
++};
++
++static inline void faradayfb_schedule_work(struct fb_info *info, unsigned int state)
++{
++ struct faradayfb_info *fbi = info->par;
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ /*
++ * We need to handle two requests being made at the same time.
++ * There are two important cases:
++ * 1. When we are changing VT (C_REENABLE) while unblanking (C_ENABLE)
++ * We must perform the unblanking, which will do our REENABLE for us.
++ * 2. When we are blanking, but immediately unblank before we have
++ * blanked. We do the "REENABLE" thing here as well, just to be sure.
++ */
++ if (fbi->task_state == C_ENABLE && state == C_REENABLE)
++ state = (unsigned int) - 1;
++
++ if (fbi->task_state == C_DISABLE && state == C_ENABLE)
++ state = C_REENABLE;
++
++ if (state != (unsigned int) - 1) {
++
++ fbi->task_state = state;
++ schedule_work(&fbi->task);
++ }
++
++ local_irq_restore(flags);
++}
++
++static int faradayfb_setpalettereg(unsigned int regno, unsigned int red,
++ unsigned int green, unsigned int blue, unsigned int trans,
++ struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++
++ if (regno < fbi->palette_size) {
++
++ fbi->palette_cpu[regno] = ((red >> 0) & (0x1fUL << 11)) |
++ ((green >> 5) & (0x3F << 5)) |
++ ((blue >> 11) & (0x1f << 0));
++
++ return 0;
++ }
++
++ return 1;
++}
++
++static int faradayfb_setcolreg(unsigned int regno, unsigned int red, unsigned int green,
++ unsigned int blue, unsigned int trans, struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ int ret = 1;
++ /*
++ * If inverse mode was selected, invert all the colours
++ * rather than the register number. The register number
++ * is what you poke into the framebuffer to produce the
++ * colour you requested.
++ */
++ if (fbi->cmap_inverse) {
++
++ red = 0xffff - red;
++ green = 0xffff - green;
++ blue = 0xffff - blue;
++ }
++
++ /*
++ * If greyscale is true, then we convert the RGB value
++ * to greyscale no mater what visual we are using.
++ */
++ if (info->var.grayscale)
++ red = green = blue = (19595 * red + 38470 * green + 7471 * blue) >> 16;
++
++ switch(info->fix.visual) {
++
++ case FB_VISUAL_TRUECOLOR:
++ /*
++ * 12 or 16-bit True Colour. We encode the RGB value
++ * according to the RGB bitfield information.
++ */
++ if (regno < 16) {
++
++ u32 col;
++ red >>= (16 - info->var.red.length);
++ green >>= (16 - info->var.green.length);
++ blue >>= (16 - info->var.blue.length);
++ col = (red << info->var.red.offset) |
++ (green << info->var.green.offset) |
++ (blue << info->var.blue.offset) ;
++
++ switch(info->var.bits_per_pixel) {
++
++ /* is the following code correct?? */
++ case 16:
++ case 32:
++ ((u32 *)(info->pseudo_palette))[regno] = col;
++ ret=0;
++ break;
++ }
++ }
++ break;
++
++ case FB_VISUAL_STATIC_PSEUDOCOLOR:
++ case FB_VISUAL_PSEUDOCOLOR:
++ if (fbi->smode == FFB_MODE_RGB)
++ ret = faradayfb_setpalettereg(regno, red, green, blue, trans, info);
++ break;
++ }
++
++ return ret;
++}
++
++/*
++ * Round up in the following order: bits_per_pixel, xres,
++ * yres, xres_virtual, yres_virtual, xoffset, yoffset, grayscale,
++ * bitfields, horizontal timing, vertical timing.
++ */
++static int faradayfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ int rgbidx;
++
++ var->xres = min(var->xres, (unsigned int)MIN_XRES);
++ var->yres = min(var->yres, (unsigned int)MIN_YRES);
++ var->xres = max(var->xres, fbi->xres);
++ var->yres = max(var->yres, fbi->yres);
++ var->xres_virtual = max(var->xres_virtual, var->xres);
++ var->yres_virtual = max(var->yres_virtual, var->yres);
++
++ DEBUG(0, 1, "var->bits_per_pixel = %d\n", var->bits_per_pixel);
++
++ switch (var->bits_per_pixel) {
++
++ case 1: case 2: case 4: case 8:
++ rgbidx = RGB_8;
++ break;
++
++ case 16:
++ rgbidx = RGB_16;
++ break;
++
++ case 32:
++ rgbidx = RGB_24;
++ break;
++
++ default:
++ return -EINVAL;
++ }
++
++ /*
++ * Copy the RGB parameters for this display
++ * from the machine specific parameters.
++ */
++ var->red = fbi->rgb[ rgbidx]->red;
++ var->green = fbi->rgb[ rgbidx]->green;
++ var->blue = fbi->rgb[ rgbidx]->blue;
++ var->transp = fbi->rgb[ rgbidx]->transp;
++
++ DEBUG(0, 1, "RGBT length = %d:%d:%d:%d\n",
++ var->red.length, var->green.length, var->blue.length, var->transp.length);
++
++ DEBUG(0, 1, "RGBT offset = %d:%d:%d:%d\n",
++ var->red.offset, var->green.offset, var->blue.offset, var->transp.offset);
++
++ DEBUG(0, 1, "Leave\n");
++
++ return 0;
++}
++
++/*
++ * Configures LCD Controller based on entries in var parameter. Settings are
++ * only written to the controller if changes were made.
++ */
++static int faradayfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
++
++ DEBUG(0, 1, "var: xres=%d hslen=%d lm=%d rm=%d\n", var->xres, var->hsync_len, var->left_margin, var->right_margin);
++ DEBUG(0, 1, "var: yres=%d vslen=%d um=%d bm=%d\n", var->yres, var->vsync_len, var->upper_margin, var->lower_margin);
++
++ fbi->time0 = FARADAY_LCDTIME0_HFP(var->left_margin)
++ | FARADAY_LCDTIME0_HBP(var->right_margin)
++ | FARADAY_LCDTIME0_HW(var->hsync_len)
++ | FARADAY_LCDTIME0_PL(var->xres);
++
++ fbi->time1 = FARADAY_LCDTIME1_VBP(var->upper_margin)
++ | FARADAY_LCDTIME1_VFP(var->lower_margin)
++ | FARADAY_LCDTIME1_VW(var->vsync_len)
++ | FARADAY_LCDTIME1_LF(var->yres);
++
++ if ((plcd->Timing0 != fbi->time0)
++ || (plcd->Timing1 != fbi->time1)
++ || (plcd->Timing2 != fbi->time2)
++ || (plcd->Control != fbi->control)) {
++
++ faradayfb_schedule_work(info, C_REENABLE);
++ }
++
++ return 0;
++}
++
++/* Set the user defined part of the display for the specified console */
++static int faradayfb_set_par(struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ struct fb_var_screeninfo *var = &info->var;
++ unsigned long palette_mem_size;
++
++ if (var->bits_per_pixel == 16 || var->bits_per_pixel == 32)
++ info->fix.visual = FB_VISUAL_TRUECOLOR;
++ else if (!fbi->cmap_static)
++ info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
++ else {
++ /*
++ * Some people have weird ideas about wanting static
++ * pseudocolor maps. I suspect their user space
++ * applications are broken.
++ */
++ info->fix.visual = FB_VISUAL_STATIC_PSEUDOCOLOR;
++ }
++
++ info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
++
++ fbi->palette_size = var->bits_per_pixel == 8 ? 256 : 16;
++
++ palette_mem_size = fbi->palette_size * sizeof(u32);
++
++ DEBUG(0, 1, "info->fix.line_length = %d\n", info->fix.line_length);
++ DEBUG(0, 1, "palette_mem_size = 0x%08lx\n", (unsigned long) palette_mem_size);
++
++ fbi->palette_cpu = (u32 *)(fbi->map_cpu + PAGE_SIZE - palette_mem_size);
++
++ fbi->palette_dma = fbi->map_dma + PAGE_SIZE - palette_mem_size;
++
++ /* Set (any) board control register to handle new color depth */
++ faradayfb_activate_var(var, info);
++
++ DEBUG(0, 1, "Leave\n");
++
++ return 0;
++}
++
++static irqreturn_t faradayfb_handle_irq(int irq, void *dev_id)
++{
++#if 0
++ struct fb_info *info = (struct fb_info*)dev_id;
++ struct faradayfb_info *fbi = info->par;
++ volatile LCD_Register *plcd = (LCD_Register *)fbi->io_base;
++ u32 status = plcd->Interrupt;
++#endif
++ return IRQ_HANDLED;
++}
++
++/*
++ * This function must be called from task context only, since it will
++ * sleep when disabling the LCD controller, or if we get two contending
++ * processes trying to alter state.
++ */
++static void set_ctrlr_state(struct fb_info *info, unsigned int state)
++{
++ struct faradayfb_info *fbi = info->par;
++ unsigned int old_state;
++
++ down(&fbi->ctrlr_sem);
++
++ old_state = fbi->state;
++
++ /* Hack around fbcon initialisation. */
++ if (old_state == C_STARTUP && state == C_REENABLE)
++ state = C_ENABLE;
++
++ switch (state) {
++ case C_DISABLE_PM:
++ case C_DISABLE:
++
++ /* Disable controller */
++ if (old_state != C_DISABLE) {
++
++ fbi->state = state;
++ faradayfb_disable_int(info);
++ faradayfb_lcd_power(info, 0);
++ // faradayfb_disable_controller(info);
++ }
++ break;
++
++ case C_REENABLE:
++ /*
++ * Re-enable the controller only if it was already
++ * enabled. This is so we reprogram the control
++ * registers.
++ */
++ if (old_state == C_ENABLE) {
++
++ faradayfb_disable_int(info);
++ faradayfb_lcd_power(info, 0);
++ faradayfb_disable_controller(info);
++
++ faradayfb_setup_gpio(info);
++ faradayfb_lcd_power(info, 1);
++ faradayfb_enable_controller(info);
++ faradayfb_enable_int(info);
++ }
++ break;
++
++ case C_ENABLE_PM:
++ /*
++ * Re-enable the controller after PM. This is not
++ * perfect - think about the case where we were doing
++ * a clock change, and we suspended half-way through.
++ */
++ if (old_state != C_DISABLE_PM)
++ break;
++ /* fall through */
++
++ case C_ENABLE:
++ /*
++ * Power up the LCD screen, enable controller, and
++ * turn on the backlight.
++ */
++ if (old_state != C_ENABLE) {
++
++ fbi->state = C_ENABLE;
++ faradayfb_setup_gpio(info);
++ faradayfb_lcd_power(info, 1);
++ faradayfb_enable_controller(info);
++ faradayfb_enable_int(info);
++ }
++ break;
++ }
++ up(&fbi->ctrlr_sem);
++}
++
++/*
++ * Blank the display by setting all palette values to zero. Note, the
++ * 12 and 16 bpp modes don't really use the palette, so this will not
++ * blank the display in all modes.
++ */
++static int faradayfb_blank(int blank, struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ int i;
++
++ switch (blank) {
++ case FB_BLANK_POWERDOWN:
++ case FB_BLANK_VSYNC_SUSPEND:
++ case FB_BLANK_HSYNC_SUSPEND:
++ case FB_BLANK_NORMAL:
++
++ if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR ||
++ info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR) {
++
++ for (i = 0; i < fbi->palette_size; i++)
++ faradayfb_setpalettereg(i, 0, 0, 0, 0, info);
++ }
++
++ faradayfb_schedule_work(info, C_DISABLE);
++
++ break;
++
++ case FB_BLANK_UNBLANK:
++
++ if (info->fix.visual == FB_VISUAL_PSEUDOCOLOR ||
++ info->fix.visual == FB_VISUAL_STATIC_PSEUDOCOLOR)
++ fb_set_cmap(&info->cmap, info);
++
++ faradayfb_schedule_work(info, C_ENABLE);
++
++ break;
++ }
++
++ return 0;
++}
++
++/*
++ * Our LCD controller task (which is called when we blank or unblank)
++ * via keventd.
++ */
++static void faradayfb_task(struct work_struct *dummy)
++{
++ struct faradayfb_info *fbi = container_of(dummy, struct faradayfb_info, task);
++ struct fb_info *info = fbi->info;
++ unsigned int state;
++
++ state = xchg(&fbi->task_state, -1);
++ set_ctrlr_state(info, state);
++}
++
++/* Fake monspecs to fill in fbinfo structure */
++static struct fb_monspecs monspecs = {
++
++ .hfmin = 30000,
++ .hfmax = 70000,
++ .vfmin = 50,
++ .vfmax = 65,
++};
++
++static int ffb_get_mach_param(struct faradayfb_mach_info *inf, struct fb_info *info, unsigned long smode)
++{
++ struct faradayfb_info *fbi = info->par;
++ struct lcd_param *tparam;
++ unsigned long bpp_mode;
++
++ if (!(tparam = get_lcd_time(inf->time0, inf->num_time0, smode)))
++ return -1;
++
++ fbi->time0 = tparam->value;
++
++ if (!(tparam = get_lcd_time(inf->time1, inf->num_time1, smode)))
++ return -1;
++
++ fbi->time1 = tparam->value;
++
++ if (!(tparam = get_lcd_time(inf->time2, inf->num_time2, smode)))
++ return -1;
++
++ fbi->time2 = tparam->value;
++
++ switch(info->var.bits_per_pixel) {
++
++ case 1: case 2: case 4: case 8:
++ bpp_mode = FFB_MODE_8BPP;
++ break;
++
++ case 16:
++ bpp_mode = FFB_MODE_16BPP;
++ break;
++
++ case 32:
++ bpp_mode = FFB_MODE_24BPP;
++ break;
++
++ default:
++ DEBUG(1, 1, "Unsupported BPP, set default BPP to 16\n");
++ bpp_mode = FFB_MODE_16BPP;
++ break;
++ }
++
++ if (!(tparam = get_lcd_ctrl(inf->control, inf->num_control, smode | bpp_mode)))
++ return -1;
++
++ fbi->control = tparam->value;
++
++ fbi->xres = inf->xres;
++ fbi->yres = inf->yres;
++
++ return 0;
++}
++
++static int faradayfb_set_var(struct fb_info *info, struct faradayfb_mach_info *inf, unsigned long type)
++{
++ struct faradayfb_info *fbi = info->par;
++ unsigned long t_smode = 0;
++
++ if (!type)
++ t_smode = fbi->smode;
++ else
++ t_smode = type;
++
++ if (ffb_get_mach_param(inf, info, t_smode)) {
++
++ DEBUG(1, 1, "Not support mode(%lx)\n", t_smode);
++ return -1;
++ }
++
++ info->var.xres = fbi->xres;
++ info->var.xres_virtual = fbi->xres;
++ info->var.yres = fbi->yres;
++ info->var.yres_virtual = fbi->yres;
++
++ info->var.upper_margin = FARADAY_LCDTIME1_GET_VBP(fbi->time1);
++ info->var.lower_margin = FARADAY_LCDTIME1_GET_VFP(fbi->time1);
++ info->var.vsync_len = FARADAY_LCDTIME1_GET_VW(fbi->time1);
++ info->var.left_margin = FARADAY_LCDTIME0_GET_HFP(fbi->time0);
++ info->var.right_margin = FARADAY_LCDTIME0_GET_HBP(fbi->time0);
++ info->var.hsync_len = FARADAY_LCDTIME0_GET_HW(fbi->time0);
++
++ fbi->int_mask = 0;
++
++ if (t_smode & FFB_MODE_YUV420)
++ fbi->frame420_size = (((info->var.xres * info->var.yres + 0xffff) & 0xffff0000) >> 16) << 2;
++ else
++ fbi->frame420_size = 0;
++
++ return 0;
++}
++
++static struct fb_ops faradayfb_ops = {
++
++ .owner = THIS_MODULE,
++ .fb_check_var = faradayfb_check_var,
++ .fb_set_par = faradayfb_set_par,
++ .fb_setcolreg = faradayfb_setcolreg,
++ .fb_fillrect = cfb_fillrect,
++ .fb_copyarea = cfb_copyarea,
++ .fb_imageblit = cfb_imageblit,
++ .fb_blank = faradayfb_blank,
++ .fb_mmap = faradayfb_mmap,
++ .fb_ioctl = faradayfb_ioctl,
++};
++
++static struct fb_info * __init faradayfb_init_fbinfo(struct device *dev)
++{
++ struct faradayfb_mach_info *inf;
++ struct fb_info *info;
++ struct faradayfb_info *fbi;
++
++ if (!(info = framebuffer_alloc(sizeof(struct faradayfb_info), dev)))
++ return NULL;
++
++ fbi = info->par;
++ fbi->info = info;
++
++ fbi->io_base = LCD_FTLCDC100_0_VA_BASE;
++ strcpy(info->fix.id, FARADAYFB_MODULE_NAME);
++
++ info->fix.type = FB_TYPE_PACKED_PIXELS;
++ info->fix.type_aux = 0;
++ info->fix.xpanstep = 0;
++ info->fix.ypanstep = 0;
++ info->fix.ywrapstep = 0;
++ info->fix.accel = FB_ACCEL_NONE;
++
++ info->var.nonstd = 0;
++ info->var.activate = FB_ACTIVATE_NOW;
++ info->var.height = -1;
++ info->var.width = -1;
++ info->var.accel_flags = 0;
++ info->var.vmode = FB_VMODE_NONINTERLACED;
++
++ info->fbops = &faradayfb_ops;
++ info->flags = FBINFO_DEFAULT;
++ info->monspecs = monspecs;
++ info->pseudo_palette = &faradayfb_pseudo_palette;
++
++ fbi->rgb[RGB_8] = &def_rgb_8;
++ fbi->rgb[RGB_16] = &def_rgb_16;
++ fbi->rgb[RGB_24] = &def_rgb_24;
++
++ inf = (struct faradayfb_mach_info*)dev->platform_data;
++
++ /*
++ * People just don't seem to get this. We don't support
++ * anything but correct entries now, so panic if someone
++ * does something stupid.
++ */
++
++ fbi->xres = inf->xres;
++ fbi->yres = inf->yres;
++ fbi->max_bpp = 32;
++#if defined(CONFIG_FFB_MODE_8BPP)
++ info->var.bits_per_pixel = min((u32)8, inf->max_bpp);
++#elif defined(CONFIG_FFB_MODE_16BPP)
++ info->var.bits_per_pixel = min((u32)16, inf->max_bpp);
++#elif defined(CONFIG_FFB_MODE_24BPP)
++ info->var.bits_per_pixel = min((u32)32, inf->max_bpp);
++ info->var.bits_per_pixel = 32;
++#endif
++
++ info->var.pixclock = inf->pixclock;
++ info->var.sync = inf->sync;
++ info->var.grayscale = inf->cmap_greyscale;
++ fbi->cmap_inverse = inf->cmap_inverse;
++ fbi->cmap_static = inf->cmap_static;
++
++ fbi->smode = FFB_DEFAULT_MODE;
++
++ if (faradayfb_set_var(info, inf, 0))
++ goto err;
++
++ fbi->state = C_STARTUP;
++ fbi->task_state = (unsigned char) - 1;
++ info->fix.smem_len = faradayfb_cal_frame_buf_size(fbi);
++
++ init_waitqueue_head(&fbi->ctrlr_wait);
++ INIT_WORK(&fbi->task, faradayfb_task);
++ init_MUTEX(&fbi->ctrlr_sem);
++
++ return info;
++err:
++ kfree(fbi);
++ kfree(info);
++
++ return NULL;
++}
++
++static int faradayfb_probe(struct platform_device *pdev)
++{
++ struct fb_info *info;
++ struct faradayfb_info *fbi;
++ int irq;
++ int ret = 0;
++
++ ret = -ENOMEM;
++
++ if (!(info = faradayfb_init_fbinfo(&pdev->dev))) {
++
++ DEBUG(1, 1, "unable to allocate memory for device info\n");
++ goto err_exit;
++ }
++
++ fbi = info->par;
++
++ /* Initialize video memory */
++ if ((ret = faradayfb_map_video_memory(info)) < 0)
++ goto err_free_mem;
++
++ ret = -EINVAL;
++
++ if ((irq = platform_get_irq(pdev, 0)) <= 0)
++ goto err_free_map;
++
++ if (request_irq(irq, faradayfb_handle_irq, IRQF_DISABLED, "LCD", info)) {
++
++ DEBUG(1, 1, "request_irq failed: %d\n", ret);
++ goto err_free_map;
++ }
++
++ /*
++ * This makes sure that our colour bitfield
++ * descriptors are correctly initialised.
++ */
++ faradayfb_check_var(&info->var, info);
++ faradayfb_set_par(info);
++
++ dev_set_drvdata(&pdev->dev, info);
++
++// <============================================
++ if ((ret = register_framebuffer(info)) < 0) {
++
++ DEBUG(1, 1, "register_framebuffer failed\n");
++ goto err_free_irq;
++ }
++// <============================================
++
++ faradayfb_clean_screen(info);
++
++ return 0;
++
++err_free_irq:
++ dev_set_drvdata(&pdev->dev, NULL);
++ free_irq(irq, info);
++err_free_map:
++ faradayfb_unmap_video_memory(info);
++err_free_mem:
++ kfree(info->par);
++ kfree(info);
++err_exit:
++ return ret;
++}
++
++/* Called when the device is being detached from the driver */
++static int faradayfb_remove(struct platform_device *pdev)
++{
++ struct fb_info *info = platform_get_drvdata(pdev);
++ int irq;
++
++ set_ctrlr_state(info, C_DISABLE);
++
++ irq = platform_get_irq(pdev, 0);
++ free_irq(irq, info);
++
++ unregister_framebuffer(info);
++ faradayfb_unmap_video_memory(info);
++ dev_set_drvdata(&pdev->dev, NULL);
++ kfree(info->par);
++ kfree(info);
++
++ return 0;
++}
++
++#ifdef CONFIG_PM
++
++/* suspend and resume support for the lcd controller */
++static int faradayfb_suspend(struct platform_device *pdev, pm_message_t mesg)
++{
++ struct fb_info *info = platform_get_drvdata(pdev);
++
++ // if (level == SUSPEND_DISABLE || level == SUSPEND_POWER_DOWN)
++ if (mesg.event == PM_EVENT_PRETHAW || mesg.event & PM_EVENT_SLEEP)
++ set_ctrlr_state(info, C_DISABLE_PM);
++
++ return 0;
++}
++
++static int faradayfb_resume(struct platform_device *pdev)
++{
++ struct fb_info *info = platform_get_drvdata(pdev);
++
++ // need modify
++ // if (level == RESUME_ENABLE)
++ set_ctrlr_state(info, C_ENABLE_PM);
++
++ return 0;
++}
++
++#else
++#define faradayfb_suspend NULL
++#define faradayfb_resume NULL
++#endif
++
++static struct resource faradayfb_resource[] = {
++
++ {
++ .start = LCD_FTLCDC100_0_PA_BASE,
++ .end = LCD_FTLCDC100_0_PA_LIMIT,
++ .flags = IORESOURCE_MEM,
++ },
++ {
++ .start = LCD_FTLCDC100_0_IRQ,
++ .end = LCD_FTLCDC100_0_IRQ,
++ .flags = IORESOURCE_IRQ,
++ }
++};
++
++static u64 faradayfb_dmamask = ~(u32)0;
++
++static struct platform_device faradayfb_device = {
++
++ .name = "faraday-lcd",
++ .id = -1,
++ .num_resources = ARRAY_SIZE(faradayfb_resource),
++ .resource = faradayfb_resource,
++ .dev = {
++
++ .platform_data = &ffb_mach_info,
++ .dma_mask = &faradayfb_dmamask,
++ .coherent_dma_mask = 0xffffffff,
++ }
++};
++
++static struct platform_driver faradayfb_driver = {
++ .probe = faradayfb_probe,
++ .remove = faradayfb_remove,
++ .suspend = faradayfb_suspend,
++ .resume = faradayfb_resume,
++ .driver = {
++ .name = "faraday-lcd",
++ },
++};
++
++/*
++rick note faraday driver
++*/
++
++/* Register both the driver and the device */
++int __init faradayfb_init(void)
++{
++ int ret = 0;
++ /* Register the device with LDM */
++
++#if 1
++ if (platform_device_register(&faradayfb_device)) {
++
++ DEBUG(1, 1, "failed to register faradayfb device\n");
++ ret = -ENODEV;
++ goto exit;
++ }
++#endif
++ /* Register the driver with LDM */
++ if (platform_driver_register(&faradayfb_driver)) {
++
++ DEBUG(1, 1, "failed to register faradayfb driver\n");
++ platform_device_unregister(&faradayfb_device);
++ ret = -ENODEV;
++ goto exit;
++ }
++exit:
++ return ret;
++}
++
++static void __exit faradayfb_cleanup(void)
++{
++ platform_driver_unregister(&faradayfb_driver);
++ platform_device_unregister(&faradayfb_device);
++}
++
++module_init(faradayfb_init);
++module_exit(faradayfb_cleanup);
++MODULE_DESCRIPTION("Faraday LCD driver");
++MODULE_AUTHOR("Francis Huang <francish@faraday-tech.com>");
++MODULE_LICENSE("GPL");
+diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/Kconfig linux-3.4.110/drivers/video/FTLCDC100/Kconfig
+--- linux-3.4.110.orig/drivers/video/FTLCDC100/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/video/FTLCDC100/Kconfig 2016-04-07 10:20:51.058085512 +0200
+@@ -0,0 +1,74 @@
++config FB_FTLCDC100
++ tristate "Faraday FTLCDC100 driver"
++ depends on FB && NDS32
++ select FB_CFB_FILLRECT
++ select FB_CFB_COPYAREA
++ select FB_CFB_IMAGEBLIT
++
++ choice
++ prompt "Default LCD Panel"
++ depends on FB_FTLCDC100
++ default PANEL_AUA036QN01
++ help
++ This option select a default panel setting for the LCD controller
++
++ config PANEL_AUA036QN01
++ bool "AU 3.5 inch LCD Panel"
++
++ config PANEL_CH7013A
++ bool "Chrontel Digital PC to TV Encoder"
++ select I2C
++ select I2C_FARADAY
++ select CH7013A
++
++ config PANEL_AUA070VW04
++ bool "AU 7.0 inch LCD Panel"
++
++ config PANEL_LW500AC9601
++ bool "CHIMEI 5.0 inch LCD panel"
++
++ endchoice
++
++ # config FTLCD_OSD
++ # bool "Enable OSD (On Screen Display)"
++ # depends on FB_FTLCDC100
++ # default n
++ # ---help---
++ # This enables access to the OSD (On Screen Display) for Faraday
++ # FTLCDC100 LCD control. Disabling OSD will reduce the size of
++ # the kernel by approximately 6kb.
++ #
++
++ choice
++ prompt "Default Color Mode"
++ depends on FB_FTLCDC100
++ default FFB_MODE_RGB
++ help
++ This option select default color mode
++
++ config FFB_MODE_RGB
++ bool "RGB Mode"
++ config FFB_MODE_YUV422
++ bool "YUV422 Mode"
++ config FFB_MODE_YUV420
++ bool "YUV420 Mode"
++ endchoice
++
++ choice
++ prompt "Default BPP"
++ depends on FB_FTLCDC100
++ default FFB_MODE_16BPP
++ help
++ This option select default BPP (bits-per-pixel)
++
++ config FFB_MODE_8BPP
++ depends on FFB_MODE_RGB || FFB_MODE_YUV420
++ bool "8 bits-per-pixel"
++ config FFB_MODE_16BPP
++ depends on FFB_MODE_RGB || FFB_MODE_YUV422
++ bool "16 bits-per-pixel"
++ config FFB_MODE_24BPP
++ depends on FFB_MODE_RGB
++ bool "24 bits-per-pixel"
++ endchoice
++
+diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/lcd-info.c linux-3.4.110/drivers/video/FTLCDC100/lcd-info.c
+--- linux-3.4.110.orig/drivers/video/FTLCDC100/lcd-info.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/video/FTLCDC100/lcd-info.c 2016-04-07 10:20:51.058085512 +0200
+@@ -0,0 +1,264 @@
++/*
++ * HBP : Horizontal Back Porch
++ * HFP : Horizontal Front Porch
++ * HSPW: Horizontal Sync. Pulse Width
++ * PPL : Pixels-per-line = 16(PPL+1)
++ */
++#define ENC_PARAM_TIME0(HBP, HFP, HSPW, PPL) \
++ ((((HBP) - 1) << 24) | \
++ (((HFP) - 1) << 16) | \
++ (((HSPW) - 1) << 8 ) | \
++ ((((PPL) >> 4) - 1) << 2 ))
++
++/*
++ * HBP : Vertical Back Porch
++ * HFP : Vertical Front Porch
++ * HSPW: Vertical Sync. Pulse Width
++ * LPP : Lines-per-panel = LPP + 1
++ */
++#define ENC_PARAM_TIME1(VBP, VFP, VSPW, LPP) \
++ ((((VBP) ) << 24) | \
++ (((VFP) ) << 16) | \
++ (((VSPW) - 1) << 10) | \
++ (((LPP) - 1) ))
++
++/*
++ * PRA : Pixel Rate Adaptive
++ * IOE : Invert Panel Output Enable
++ * IPC : Invert Panel Clock (Test Chip Testing)
++ * IHS : Invert Horisontal Sync.
++ * IVS : Invert Versical Sync.
++ * PCD : Panel Clock Divisor
++ */
++#define ENC_PARAM_TIME2(PRA, IOE, IPC, IHS, IVS, PCD) \
++ (((PRA) << 15) | \
++ ((IOE) << 14) | \
++ ((IPC) << 13) | \
++ ((IHS) << 12) | \
++ ((IVS) << 11) | \
++ (((PCD) - 1) ))
++
++/*
++ * Enable YCbCr
++ * Enable YCbCr420
++ * FIFO threadhold
++ * Panel type, 0-6bit, 1-8bit
++ * LcdVComp, when to generate interrupt, 1: start of back_porch
++ * Power Enable
++ * Big Endian Pixel/Byte Ordering
++ * BGR
++ * TFT
++ * LCD bits per pixel
++ * Controller Enable
++ */
++
++#define ENC_PARAM_CTRL(ENYUV, ENYUV420, FIFOTH, PTYPE, VCOMP, LCD_ON, ENDIAN, BGR, TFT, BPP, LCD_EN) \
++ ((ENYUV << 18) | \
++ (ENYUV420 << 17) | \
++ (FIFOTH << 16) | \
++ (PTYPE << 15) | \
++ (VCOMP << 12) | \
++ (LCD_ON << 11) | \
++ (ENDIAN << 9) | \
++ (BGR << 8) | \
++ (TFT << 5) | \
++ (BPP << 1) | \
++ (LCD_EN))
++
++static struct lcd_param control[] = {
++
++ {
++ .value = ENC_PARAM_CTRL(0, 0, 1, 1, 0x3, 1, 0x0, 1, 1, 0x3, 1),
++ .flags = FFB_MODE_RGB | FFB_MODE_8BPP,
++ },
++ {
++ .value = ENC_PARAM_CTRL(1, 1, 1, 1, 0x3, 1, 0x0, 0, 1, 0x3, 1),
++ .flags = FFB_MODE_YUV420 | FFB_MODE_8BPP,
++ },
++ {
++ .value = ENC_PARAM_CTRL(1, 0, 1, 1, 0x3, 1, 0x0, 0, 1, 0x4, 1),
++ .flags = FFB_MODE_YUV422 | FFB_MODE_16BPP,
++ },
++ {
++ .value = ENC_PARAM_CTRL(0, 0, 1, 1, 0x3, 1, 0x0, 1, 1, 0x4, 1),
++ .flags = FFB_MODE_RGB | FFB_MODE_16BPP,
++ },
++ {
++ .value = ENC_PARAM_CTRL(0, 0, 1, 1, 0x3, 1, 0x0, 1, 1, 0x5, 1),
++ .flags = FFB_MODE_RGB | FFB_MODE_24BPP,
++ },
++};
++
++#ifdef CONFIG_PANEL_AUA036QN01
++
++static struct lcd_param time0[] = {
++
++ {
++ .value = ENC_PARAM_TIME0(7, 6, 1, 320),
++ .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
++ },
++};
++
++static struct lcd_param time1[] = {
++
++ {
++ .value = ENC_PARAM_TIME1(1, 1, 1, 240),
++ .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
++ },
++};
++
++static struct lcd_param time2[] = {
++
++ {
++ .value = ENC_PARAM_TIME2(0, 0, 1, 1, 1, 0x7),
++ .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
++ },
++};
++
++static struct faradayfb_mach_info ffb_mach_info = {
++
++ .pixclock = 171521,
++ .xres = 320,
++ .yres = 240,
++ .max_bpp = 24,
++ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .num_time0 = ARRAY_SIZE(time0),
++ .time0 = time0,
++ .num_time1 = ARRAY_SIZE(time1),
++ .time1 = time1,
++ .num_time2 = ARRAY_SIZE(time2),
++ .time2 = time2,
++ .num_control = ARRAY_SIZE(control),
++ .control = control,
++};
++#endif
++
++#ifdef CONFIG_PANEL_AUA070VW04
++static struct lcd_param time0[] = {
++
++ {
++ .value = ENC_PARAM_TIME0(88, 40, 128, 800),
++ .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
++ },
++};
++
++static struct lcd_param time1[] = {
++
++ {
++ .value = ENC_PARAM_TIME1(21, 1, 3, 480),
++ .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
++ },
++};
++
++static struct lcd_param time2[] = {
++
++ {
++ .value = ENC_PARAM_TIME2(0, 1, 1, 1, 1, 0x5),
++ .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
++ },
++};
++
++static struct faradayfb_mach_info ffb_mach_info = {
++
++ .pixclock = 171521,
++ .xres = 800,
++ .yres = 480,
++ .max_bpp = 24,
++ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .num_time0 = ARRAY_SIZE(time0),
++ .time0 = time0,
++ .num_time1 = ARRAY_SIZE(time1),
++ .time1 = time1,
++ .num_time2 = ARRAY_SIZE(time2),
++ .time2 = time2,
++ .num_control = ARRAY_SIZE(control),
++ .control = control,
++};
++
++#endif
++
++#ifdef CONFIG_PANEL_LW500AC9601
++static struct lcd_param time0[] = {
++
++ {
++ .value = ENC_PARAM_TIME0(88, 40, 128, 800),
++ .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
++ },
++};
++
++static struct lcd_param time1[] = {
++
++ {
++ .value = ENC_PARAM_TIME1(21, 1, 3, 480),
++ .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
++ },
++};
++
++static struct lcd_param time2[] = {
++
++ {
++ .value = ENC_PARAM_TIME2( 0, 0, 1, 1, 1, 0x3),
++ .flags = FFB_MODE_RGB | FFB_MODE_YUV420 | FFB_MODE_YUV422,
++ },
++};
++
++static struct faradayfb_mach_info ffb_mach_info = {
++
++ .pixclock = 171521,
++ .xres = 800,
++ .yres = 480,
++ .max_bpp = 24,
++ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .num_time0 = ARRAY_SIZE(time0),
++ .time0 = time0,
++ .num_time1 = ARRAY_SIZE(time1),
++ .time1 = time1,
++ .num_time2 = ARRAY_SIZE(time2),
++ .time2 = time2,
++ .num_control = ARRAY_SIZE(control),
++ .control = control,
++};
++#endif
++
++#ifdef CONFIG_CH7013A
++static struct lcd_param time0[] = {
++
++ {
++ .value = ENC_PARAM_TIME0(42, 10, 96, 640),
++ .flags = FFB_MODE_RGB,
++ },
++};
++
++static struct lcd_param time1[] = {
++
++ {
++ .value = ENC_PARAM_TIME1(28, 5, 2, 480),
++ .flags = FFB_MODE_RGB,
++ },
++};
++static struct lcd_param time2[] = {
++
++ {
++ .value = ENC_PARAM_TIME2(0, 1, 1, 0, 0, 0x3),
++ .flags = FFB_MODE_RGB,
++ },
++};
++
++static struct faradayfb_mach_info ffb_mach_info = {
++
++ .pixclock = 37910,
++ .xres = 640,
++ .yres = 480,
++ .max_bpp = 24,
++ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
++ .num_time0 = ARRAY_SIZE(time0),
++ .time0 = time0,
++ .num_time1 = ARRAY_SIZE(time1),
++ .time1 = time1,
++ .num_time2 = ARRAY_SIZE(time2),
++ .time2 = time2,
++ .num_control = ARRAY_SIZE(control),
++ .control = control,
++};
++
++#endif /* CONFIG_CH7013A */
+diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/Makefile linux-3.4.110/drivers/video/FTLCDC100/Makefile
+--- linux-3.4.110.orig/drivers/video/FTLCDC100/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/video/FTLCDC100/Makefile 2016-04-07 10:20:51.058085512 +0200
+@@ -0,0 +1 @@
++obj-$(CONFIG_FB_FTLCDC100) += faradayfb-main.o
+diff -Nur linux-3.4.110.orig/drivers/video/FTLCDC100/pingpong-module.c linux-3.4.110/drivers/video/FTLCDC100/pingpong-module.c
+--- linux-3.4.110.orig/drivers/video/FTLCDC100/pingpong-module.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/video/FTLCDC100/pingpong-module.c 2016-04-07 10:20:51.058085512 +0200
+@@ -0,0 +1,592 @@
++void *fmem_alloc(size_t size, dma_addr_t *dma_handle, unsigned long flags)
++{
++ struct page *page;
++ void *cpu_addr = NULL;
++
++ size = PAGE_ALIGN(size);
++
++ if (!(page = alloc_pages(GFP_DMA, get_order(size)))) {
++
++ DEBUG(1, 1, "alloc_pages fail! (requested %#x)", size);
++ goto no_page;
++ }
++
++ *dma_handle = page_to_phys(page);
++
++ if ((cpu_addr = __ioremap(*dma_handle, size, flags, 1))) {
++
++ do {
++ SetPageReserved(page);
++ page++;
++ } while (size -= PAGE_SIZE);
++ }
++ else {
++ __free_pages(page, get_order(size));
++ DEBUG(1, 1, "__ioremap fail! (phy %#x)", *dma_handle);
++ }
++no_page:
++ return cpu_addr;
++}
++
++void fmem_free(size_t size, void *cpu_addr, dma_addr_t handle)
++{
++ struct page *page = pfn_to_page(handle >> PAGE_SHIFT);
++
++ __iounmap(cpu_addr);
++ size = PAGE_ALIGN(size);
++
++ do {
++ ClearPageReserved(page);
++ __free_page(page);
++ page++;
++
++ } while (size -= PAGE_SIZE);
++}
++
++static int faradayfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
++{
++ struct faradayfb_info *fbi = info->par;
++ unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
++ int ret = -EINVAL;
++
++ DEBUG(0, 1, "Enter\n");
++
++ if (off < info->fix.smem_len) {
++
++ off += fbi->screen_dma & PAGE_MASK;
++ vma->vm_pgoff = off >> PAGE_SHIFT;
++ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
++ vma->vm_flags |= VM_RESERVED;
++ ret = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
++ vma->vm_end - vma->vm_start, vma->vm_page_prot);
++ }
++ else {
++ DEBUG(1, 1, "buffer mapping error !!\n");
++ }
++
++ DEBUG(0, 1, "Leave\n");
++
++ return ret;
++}
++
++/*
++ * Allocates the DRAM memory for the frame buffer. This buffer is
++ * remapped into a non-cached, non-buffered, memory region to
++ * allow palette and pixel writes to occur without flushing the
++ * cache. Once this area is remapped, all virtual memory
++ * access to the video memory should occur at the new region.
++ */
++static int __init faradayfb_map_video_memory(struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++
++ /*
++ * We reserve one page for the palette, plus the size
++ * of the framebuffer.
++ */
++ fbi->map_size = PAGE_ALIGN(info->fix.smem_len + PAGE_SIZE);
++
++ fbi->map_cpu = fmem_alloc(fbi->map_size, &fbi->map_dma, pgprot_writecombine(PAGE_KERNEL));
++ // fbi->map_cpu = dma_alloc_writecombine(fbi->info->dev, fbi->map_size, &fbi->map_dma, GFP_KERNEL);
++
++ if (fbi->map_cpu) {
++
++ memset(fbi->map_cpu, 0x1d, fbi->map_size);
++ info->screen_base = fbi->map_cpu + PAGE_SIZE;
++ fbi->screen_dma = fbi->map_dma + PAGE_SIZE;
++ info->fix.smem_start = fbi->screen_dma;
++ }
++
++ return fbi->map_cpu ? 0 : -ENOMEM;
++}
++
++static inline void faradayfb_clean_screen(struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ int size = info->var.xres * info->var.yres;
++
++ if (fbi->smode & FFB_MODE_YUV422) {
++
++ memset(fbi->map_cpu, 16, size * info->var.bits_per_pixel / 8);
++ }
++ else if (fbi->smode & FFB_MODE_YUV420) {
++
++ memset(fbi->map_cpu, 16, size);
++ memset(fbi->map_cpu + PAGE_SIZE + ((size + 0xffff) & 0xffff0000), 128, size / 4);
++ memset(fbi->map_cpu + PAGE_SIZE + ((size + 0xffff) & 0xffff0000) * 5 / 4, 128, size / 4);
++ }
++}
++
++static inline void faradayfb_unmap_video_memory(struct fb_info *info)
++{
++ struct faradayfb_info *fbi = info->par;
++ fmem_free(fbi->map_size, fbi->map_cpu, fbi->map_dma);
++}
++
++#define FRAME_SIZE_RGB(xres, yres, mbpp) ((xres) * (yres) * (mbpp) / 8)
++#define FRAME_SIZE_YUV422(xres, yres, mbpp) (((xres) * (yres) * (mbpp) / 8) * 2)
++#define FRAME_SIZE_YUV420(xres, yres, mbpp) (((((xres) * (yres) * (mbpp) / 8) + 0xffff) & 0xffff0000) * 3 / 2)
++
++static inline u32 faradayfb_cal_frame_buf_size(struct faradayfb_info *fbi)
++{
++ u32 size_rgb = FRAME_SIZE_RGB(fbi->xres, fbi->yres, fbi->max_bpp);
++ u32 size_yuv422 = FRAME_SIZE_YUV422(fbi->xres, fbi->yres, 8);
++ u32 size_yuv420 = FRAME_SIZE_YUV420(fbi->xres, fbi->yres, 8);
++
++ return max(size_rgb, max(size_yuv422, size_yuv420));
++}
++
++#ifdef CONFIG_FTLCD_OSD
++/************************************
++ * OSD
++ ***********************************/
++#define FOSD_SETPOS 0x46e1
++#define FOSD_SETDIM 0x46e2
++#define FOSD_SETSCAL 0x46e3
++#define FLCD_SET_TRANSPARENT 0x46e4
++#define FLCD_SET_STRING 0x46e5
++#define FOSD_ON 0x46e6
++#define FOSD_OFF 0x46e7
++#define FRREG 0x46e8
++#define FWREG 0x46e9
++
++#define dig_alpha (16 * 10) + (16 * 26) + (16 * 3)
++
++struct fosd_string {
++
++ unsigned int Str_row;
++ unsigned int display_mode;
++ unsigned int fg_color;
++ unsigned int bg_color;
++ unsigned char Str_OSD[30];
++};
++
++struct fosd_data {
++
++ unsigned int HPos;
++ unsigned int VPos;
++ unsigned int HDim;
++ unsigned int VDim;
++ unsigned int transparent_level;
++ unsigned int HScal;
++ unsigned int VScal;
++ struct fosd_string Str_Data[10];
++};
++
++unsigned int OSD_Font[] = {
++
++ /* 0 */
++ 0x00, 0x00, 0x00, 0x3e, 0x63, 0x67, 0x6f, 0x7b,
++ 0x73, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
++
++ /* 1 */
++ 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x0c, 0x0c,
++ 0x0c, 0x0c, 0x0c, 0x3f, 0x00, 0x00, 0x00, 0x00,
++
++ /* 2 */
++ 0x00, 0x00, 0x00, 0x3e, 0x63, 0x03, 0x06, 0x0c,
++ 0x18, 0x30, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00,
++
++ /* 3 */
++ 0x00, 0x00, 0x00, 0x3E, 0x63, 0x03, 0x03, 0x1e,
++ 0x03, 0x03, 0x63, 0x3E, 0x00, 0x00, 0x00, 0x00,
++
++ /* 4 */
++ 0x00, 0x00, 0x00, 0x06, 0x0e, 0x1e, 0x36, 0x66,
++ 0x7f, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00,
++
++ /* 5 */
++ 0x00, 0x00, 0x00, 0x7f, 0x60, 0x60, 0x60, 0x7e,
++ 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
++
++ /* 6 */
++ 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7e,
++ 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
++
++ /* 7 */
++ 0x00, 0x00, 0x00, 0x7f, 0x63, 0x03, 0x06, 0x0c,
++ 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00,
++
++ /* 8 */
++ 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x3e,
++ 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
++
++ /* 9 */
++ 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x3f,
++ 0x03, 0x03, 0x06, 0x3c, 0x00, 0x00, 0x00, 0x00,
++
++ /* A */
++ 0x00, 0x00, 0x00, 0x08, 0x1c, 0x36, 0x63, 0x63,
++ 0x7f, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
++
++ /* B */
++ 0x00, 0x00, 0x00, 0x7E, 0x33, 0x33, 0x33, 0x3E,
++ 0x33, 0x33, 0x33, 0x7E, 0x00, 0x00, 0x00, 0x00,
++
++ /* C */
++ 0x00, 0x00, 0x00, 0x1E, 0x33, 0x61, 0x60, 0x60,
++ 0x60, 0x61, 0x33, 0x1E, 0x00, 0x00, 0x00, 0x00,
++
++ /* D */
++ 0x00, 0x00, 0x00, 0x7c, 0x36, 0x33, 0x33, 0x33,
++ 0x33, 0x33, 0x36, 0x7C, 0x00, 0x00, 0x00, 0x00,
++
++ /* E */
++ 0x00, 0x00, 0x00, 0x7f, 0x33, 0x31, 0x34, 0x3c,
++ 0x34, 0x31, 0x33, 0x7f, 0x00, 0x00, 0x00, 0x00,
++
++ /* F */
++ 0x00, 0x00, 0x00, 0x7f, 0x33, 0x31, 0x34, 0x3c,
++ 0x34, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00,
++
++ /* G */
++ 0x00, 0x00, 0x00, 0x1E, 0x33, 0x61, 0x60, 0x60,
++ 0x6F, 0x63, 0x36, 0x7C, 0x00, 0x00, 0x00, 0x00,
++
++ /* H */
++ 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x64, 0x7f,
++ 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
++
++ /* I */
++ 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++
++ /* J */
++ 0x00, 0x00, 0x00, 0x0f, 0x06, 0x06, 0x06, 0x06,
++ 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00,
++
++ /* K */
++ 0x00, 0x00, 0x00, 0x73, 0x33, 0x36, 0x36, 0x3c,
++ 0x36, 0x36, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00,
++
++ /* L */
++ 0x00, 0x00, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30,
++ 0x30, 0x31, 0x33, 0x7f, 0x00, 0x00, 0x00, 0x00,
++
++ /* M */
++ 0x00, 0x00, 0x00, 0x63, 0x77, 0x7f, 0x6b, 0x63,
++ 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
++
++ /* N */
++ 0x00, 0x00, 0x00, 0x63, 0x73, 0x7b, 0x7f, 0x6f,
++ 0x67, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
++
++ /* O */
++ 0x00, 0x00, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x63,
++ 0x63, 0x63, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00,
++
++ /* P */
++ 0x00, 0x00, 0x00, 0x7e, 0x33, 0x33, 0x33, 0x3e,
++ 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00,
++
++ /* Q */
++ 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63,
++ 0x6b, 0x6f, 0x3e, 0x06, 0x07, 0x00, 0x00, 0x00,
++
++ /* R */
++ 0x00, 0x00, 0x00, 0x7e, 0x33, 0x33, 0x33, 0x3e,
++ 0x36, 0x33, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00,
++
++ /* S */
++ 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x30, 0x1c,
++ 0x06, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
++
++ /* T */
++ 0x00, 0x00, 0x00, 0xFF, 0x99, 0x18, 0x18, 0x18,
++ 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00,
++
++ /* U */
++ 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63,
++ 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00,
++
++ /* V */
++ 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63,
++ 0x63, 0x36, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00,
++
++ /* W */
++ 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63,
++ 0x6b, 0x7f, 0x77, 0x63, 0x00, 0x00, 0x00, 0x00,
++
++ /* X */
++ 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x36, 0x1c,
++ 0x36, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00,
++
++ /* Y */
++ 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x36, 0x1c,
++ 0x1c, 0x1c, 0x1c, 0x3e, 0x00, 0x00, 0x00, 0x00,
++
++ /* Z */
++ 0x00, 0x00, 0x00, 0x7f, 0x63, 0x46, 0x0c, 0x18,
++ 0x30, 0x61, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00,
++
++ /* space */
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++
++ /* = */
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x00,
++ 0x00, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++
++ /* , */
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++ 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00,
++};
++
++void OSD_On(struct faradayfb_info *fbi)
++{
++ REG32(fbi->io_base + 0x34) &= 0xfffffffe;
++ REG32(fbi->io_base + 0x34) |= 1;
++}
++
++void OSD_Off(struct faradayfb_info *fbi)
++{
++ REG32(fbi->io_base + 0x34) &= 0xfffffffe;
++}
++
++void OSD_Pos(struct faradayfb_info *fbi, int HPos, int VPos)
++{
++ REG32(fbi->io_base + 0x38) = (HPos << 10) | VPos;
++}
++
++void OSD_Dim(struct faradayfb_info *fbi, int HDim, int VDim)
++{
++ REG32(fbi->io_base + 0x34) &= 0x0000001f;
++ REG32(fbi->io_base + 0x34) |= ((HDim << 10) | (VDim << 5));
++}
++
++void OSD_transparent(struct faradayfb_info *fbi, int level)
++{
++ REG32(fbi->io_base + 0x40) &= 0xffffff00;
++ REG32(fbi->io_base + 0x40) |= (level << 6);
++}
++
++void OSD_fg_color(struct faradayfb_info *fbi, int pal0, int pal1, int pal2, int pal3)
++{
++ REG32(fbi->io_base + 0x3c) = (pal0) | (pal1 << 8) | (pal2 << 16) | (pal3<< 24);
++}
++
++void OSD_bg_color(struct faradayfb_info *fbi, int pal1, int pal2, int pal3)
++{
++ REG32(fbi->io_base + 0x40) &= 0x000000ff;
++ REG32(fbi->io_base + 0x40) |= (pal1 << 8) | (pal2 << 16) | (pal3 << 24);
++}
++
++void OSD_Scal(struct faradayfb_info *fbi, int HScal, int VScal)
++{
++ REG32(fbi->io_base + 0x34) &= 0xffffffe1;
++ REG32(fbi->io_base + 0x34) |= (HScal << 3) | (VScal << 1);
++}
++
++void OSD_putc(struct faradayfb_info *fbi, char c, int position, unsigned int value)
++{
++ if (c >= '0' && c <= '9')
++ REG32(fbi->io_base + 0xc000 + position * 4) = ((c -'0') << 4) | value;
++
++ else if (c>= 'A' && c <= 'Z')
++ REG32(fbi->io_base + 0xc000 + position * 4) = ((c - 'A' + 10) << 4) | value;
++
++ if (c == ' ')
++ REG32(fbi->io_base + 0xc000 + position * 4) = (('Z' - 'A' + 10 + 1) << 4) | value;
++
++ if (c == '=')
++ REG32(fbi->io_base + 0xc000 + position * 4) = (('Z' - 'A' + 10 + 2) << 4) | value;
++
++ if (c == ',')
++ REG32(fbi->io_base + 0xc000 + position * 4) = (('Z' - 'A' + 10 + 3) << 4) | value;
++}
++
++void OSD_puts(struct faradayfb_info *fbi, char *str, int position, unsigned int value)
++{
++ int i;
++
++ for (i = 0; i < strlen(str); i++)
++ OSD_putc(fbi, *(str + i), position + i, value);
++}
++
++void OSD_String(struct faradayfb_info *fbi, int row, int mode, char *str, int fg_color, int bg_color)
++{
++ int i, j, x, y;
++ unsigned int value = fg_color | bg_color;
++
++ /* 10 digit & 26 alphabet & ' ' & '=' & ',' */
++ for (i = 0; i < dig_alpha; i++) {
++
++ x = 0;
++ y = OSD_Font[i];
++
++ for (j = 0; j < 12; j ++) { /* reorder */
++ if (y & 1)
++ x |= 1;
++ y >>= 1;
++ x <<= 1;
++ }
++
++ x >>= 1;
++ REG32(fbi->io_base + 0x8000 + i * 4) = x;
++ }
++
++ OSD_puts(fbi, str, row, value);
++
++ if (mode == 2) { /* YCbCr */
++
++ OSD_fg_color(fbi, 0x57, 0x88, 0x3B, 0xFF);
++ OSD_bg_color(fbi, 0x57, 0x88, 0x3B);
++ }
++ else {
++ OSD_fg_color(fbi, 0x07, 0x38, 0xC0, 0xFF);
++ OSD_bg_color(fbi, 0x07, 0x38, 0xc0);
++ }
++}
++#endif /* CONFIG_FTLCD_OSD */
++
++struct andesIO {
++
++ unsigned long Regaddr;
++ unsigned long Regoffset;
++ unsigned long Regvalue;
++};
++
++static int faradayfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
++{
++ int ret = 0;
++#ifdef CONFIG_FTLCD_OSD
++ struct faradayfb_info *fbi = info->par;
++ int i;
++ struct fosd_data fosd;
++
++ struct andesIO IOAccess;
++ unsigned long *Regaccess;
++#endif
++
++ DEBUG(0, 1, "Enter\n");
++
++ switch (cmd) {
++#ifdef CONFIG_FTLCD_OSD
++ case FRREG:
++
++ if (copy_from_user(&IOAccess, (struct andesIO *)arg, sizeof(struct andesIO))) {
++
++ ret = -EFAULT;
++ break;
++ }
++
++ Regaccess = (unsigned long *)(((IOAccess.Regaddr >> 4) | (unsigned long)0xF0000000) + IOAccess.Regoffset);
++
++ IOAccess.Regvalue = *(Regaccess);
++
++ if (copy_to_user((struct andesIO *)arg, &IOAccess, sizeof(struct andesIO))) {
++ ret = -EFAULT;
++ break;
++ }
++
++ break;
++
++ case FWREG:
++
++ if (copy_from_user(&IOAccess, (struct andesIO *)arg, sizeof(struct andesIO))) {
++ ret = -EFAULT;
++ break;
++ }
++
++ Regaccess = (unsigned long *)(((IOAccess.Regaddr >> 4) | (unsigned long)0xF0000000) + IOAccess.Regoffset);
++ *(Regaccess) = IOAccess.Regvalue;
++
++ break;
++
++ case FOSD_ON:
++
++ DEBUG(1, 1, "FOSD_ON:\n");
++ OSD_On(fbi);
++ break;
++
++ case FOSD_OFF:
++
++ DEBUG(1, 1, "FOSD_OFF:\n");
++ OSD_Off(fbi);
++ break;
++
++ case FOSD_SETPOS:
++
++ DEBUG(1, 1, "FOSD_SETPOS:\n");
++
++ if (copy_from_user(&fosd, (unsigned int *)arg, 2 * sizeof(unsigned int))) {
++
++ ret = -EFAULT;
++ break;
++ }
++
++ OSD_Pos(fbi, fosd.HPos, fosd.VPos);
++ DEBUG(1, 1, "OSD_Pos = %d %d\n", fosd.HPos, fosd.VPos);
++ break;
++
++ case FOSD_SETDIM:
++
++ DEBUG(1, 1, "FOSD_SETDIM:\n");
++
++ if (copy_from_user(&fosd, (unsigned int *)arg, 4 * sizeof(unsigned int))) {
++
++ ret = -EFAULT;
++ break;
++ }
++
++ OSD_Dim(fbi, fosd.HDim, fosd.VDim);
++ DEBUG(1, 1, "OSD_Dim = %d %d\n", fosd.HDim, fosd.VDim);
++ break;
++
++ case FOSD_SETSCAL:
++
++ DEBUG(1, 1, "FOSD_SETSCAL:\n");
++
++ if (copy_from_user(&fosd, (unsigned int *)arg, 7 * sizeof(unsigned int))) {
++ ret = -EFAULT;
++ break;
++ }
++
++ OSD_Scal(fbi, fosd.HScal, fosd.VScal);
++ break;
++
++ case FLCD_SET_TRANSPARENT:
++
++ DEBUG(1, 1, "FLCD_SET_TRANSPARENT:\n");
++
++ if (copy_from_user(&fosd, (unsigned int *)arg, 5 * sizeof(unsigned int))) {
++
++ ret = -EFAULT;
++ break;
++ }
++
++ OSD_transparent(fbi, fosd.transparent_level);
++ DEBUG(1, 1, "OSD_transparent = %d\n", fosd.transparent_level);
++ break;
++
++ case FLCD_SET_STRING:
++
++ DEBUG(1, 1, "FLCD_SET_STRING:\n");
++
++ if (copy_from_user(&fosd, (unsigned int *)arg, sizeof(struct fosd_data))) {
++
++ ret = -EFAULT;
++ break;
++ }
++
++ for (i = 0; i < fosd.VDim; i++)
++
++ OSD_String(fbi, fosd.Str_Data[i].Str_row,
++ fosd.Str_Data[i].display_mode,
++ fosd.Str_Data[i].Str_OSD,
++ fosd.Str_Data[i].fg_color,
++ fosd.Str_Data[i].bg_color);
++ break;
++#endif /* CONFIG_FTLCD_OSD */
++
++ default:
++
++ DEBUG(1, 1, "IOCTL CMD(0x%08u) no define!\n", cmd);
++ ret = -EFAULT;
++ break;
++ }
++
++ DEBUG(0, 1, "Leave\n");
++ return ret;
++}
++
+diff -Nur linux-3.4.110.orig/drivers/video/Kconfig linux-3.4.110/drivers/video/Kconfig
+--- linux-3.4.110.orig/drivers/video/Kconfig 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/video/Kconfig 2016-04-07 10:20:51.058085512 +0200
+@@ -2166,6 +2166,8 @@
+ ---help---
+ Say Y here to enable support for PNX4008 RGB Framebuffer
+
++source "drivers/video/FTLCDC100/Kconfig"
++
+ config FB_IBM_GXT4500
+ tristate "Framebuffer support for IBM GXT4500P adaptor"
+ depends on FB && PPC
+diff -Nur linux-3.4.110.orig/drivers/video/Makefile linux-3.4.110/drivers/video/Makefile
+--- linux-3.4.110.orig/drivers/video/Makefile 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/video/Makefile 2016-04-07 10:20:51.058085512 +0200
+@@ -143,6 +143,7 @@
+ obj-$(CONFIG_FB_CARMINE) += carminefb.o
+ obj-$(CONFIG_FB_MB862XX) += mb862xx/
+ obj-$(CONFIG_FB_MSM) += msm/
++obj-$(CONFIG_FB_FTLCDC100) += FTLCDC100/
+ obj-$(CONFIG_FB_NUC900) += nuc900fb.o
+ obj-$(CONFIG_FB_JZ4740) += jz4740_fb.o
+ obj-$(CONFIG_FB_PUV3_UNIGFX) += fb-puv3.o
+diff -Nur linux-3.4.110.orig/drivers/watchdog/ftwdt010_wdt.c linux-3.4.110/drivers/watchdog/ftwdt010_wdt.c
+--- linux-3.4.110.orig/drivers/watchdog/ftwdt010_wdt.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/drivers/watchdog/ftwdt010_wdt.c 2016-04-07 10:20:51.058085512 +0200
+@@ -0,0 +1,127 @@
++/*
++ * Watchdog driver for the FTWDT010 Watch Dog Driver
++ *
++ * (c) Copyright 2004 Faraday Technology Corp. (www.faraday-tech.com)
++ * Based on sa1100_wdt.c by Oleg Drokin <green@crimea.edu>
++ * Based on SoftDog driver by Alan Cox <alan@redhat.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.
++ *
++ * 27/11/2004 Initial release
++ */
++#include <linux/module.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/watchdog.h>
++#include <linux/delay.h>
++#include <asm/uaccess.h>
++
++#define DEBUG( str, ...) \
++ do{ \
++ if( debug) \
++ printk( str, ##__VA_ARGS__); \
++ } while(0)
++
++#define wdcounter (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x00))
++#define wdload (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x04))
++#define wdrestart (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x08))
++#define wdcr (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x0C))
++#define wdstatus (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x10))
++#define wdclear (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x14))
++#define wdintrcter (*( volatile unsigned long *)( WDT_FTWDT010_VA_BASE + 0x18))
++
++#define TIMER_MARGIN 60 /* (secs) Default is 1 minute */
++#define RESTART_MAGIC 0x5AB9
++#define PCLK (AHB_CLK_IN / 2)
++
++static int debug = 0;
++static int timeout = TIMER_MARGIN; /* in seconds */
++
++module_param(debug, int, 0);
++module_param(timeout, int, 0);
++
++static int ftwdt010_dog_open(struct inode *inode, struct file *file){
++
++#if 0
++ /* Allow only one person to hold it open */
++ if( test_and_set_bit( 1, &ftwdt010_wdt_users))
++ return -EBUSY;
++
++ ftwdt010_wdt_users = 1;
++#endif
++ DEBUG("Activating WDT..\n");
++
++ wdcr = 0;
++ wdload = PCLK * timeout;
++ wdrestart = RESTART_MAGIC; /* Magic number */
++ wdcr = 0x03; /* Enable WDT */
++
++ return 0;
++}
++
++static int ftwdt010_dog_release(struct inode *inode, struct file *file){
++
++#ifndef CONFIG_WATCHDOG_NOWAYOUT
++ /*
++ * Shut off the timer.
++ * Lock it in if it's a module and we defined ...NOWAYOUT
++ */
++ wdcr = 0;
++ DEBUG( "Deactivating WDT..\n");
++#endif
++ return 0;
++}
++
++static ssize_t ftwdt010_dog_write(struct file *file, const char *data, size_t len, loff_t *ppos){
++
++ if(len){
++
++ wdrestart = RESTART_MAGIC;
++ return 1;
++ }
++
++ return 0;
++}
++
++static struct file_operations ftwdt010_dog_fops = {
++
++ .owner = THIS_MODULE,
++ .llseek = no_llseek,
++ .write = ftwdt010_dog_write,
++ .open = ftwdt010_dog_open,
++ .release = ftwdt010_dog_release,
++};
++
++static struct miscdevice ftwdt010_dog_miscdev = {
++
++ WATCHDOG_MINOR,
++ "FTWDT010 watchdog",
++ &ftwdt010_dog_fops
++};
++
++static int __init ftwdt010_dog_init( void){
++
++ int ret;
++
++ ret = misc_register(&ftwdt010_dog_miscdev);
++
++ if( ret)
++ return ret;
++
++ DEBUG("FTWDT010 watchdog timer: timer timeout %d sec\n", timeout);
++
++ return 0;
++}
++
++static void __exit ftwdt010_dog_exit( void){
++
++ misc_deregister(&ftwdt010_dog_miscdev);
++}
++
++module_init(ftwdt010_dog_init);
++module_exit(ftwdt010_dog_exit);
++MODULE_AUTHOR("Faraday Corp.");
++MODULE_LICENSE("GPL");
+diff -Nur linux-3.4.110.orig/drivers/watchdog/Kconfig linux-3.4.110/drivers/watchdog/Kconfig
+--- linux-3.4.110.orig/drivers/watchdog/Kconfig 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/watchdog/Kconfig 2016-04-07 10:20:51.058085512 +0200
+@@ -64,6 +64,12 @@
+ To compile this driver as a module, choose M here: the
+ module will be called softdog.
+
++config FTWDT010_WATCHDOG
++ tristate "FTWDT010_WATCHDOG"
++ help
++ Support for Faraday ftwdt010 watchdog. When the watchdog triigers the
++ system will be reset.
++
+ config WM831X_WATCHDOG
+ tristate "WM831x watchdog"
+ depends on MFD_WM831X
+diff -Nur linux-3.4.110.orig/drivers/watchdog/Makefile linux-3.4.110/drivers/watchdog/Makefile
+--- linux-3.4.110.orig/drivers/watchdog/Makefile 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/drivers/watchdog/Makefile 2016-04-07 10:20:51.058085512 +0200
+@@ -163,6 +163,7 @@
+ obj-$(CONFIG_XEN_WDT) += xen_wdt.o
+
+ # Architecture Independent
++obj-$(CONFIG_FTWDT010_WATCHDOG) += ftwdt010_wdt.o
+ obj-$(CONFIG_WM831X_WATCHDOG) += wm831x_wdt.o
+ obj-$(CONFIG_WM8350_WATCHDOG) += wm8350_wdt.o
+ obj-$(CONFIG_MAX63XX_WATCHDOG) += max63xx_wdt.o
+diff -Nur linux-3.4.110.orig/include/linux/mm.h linux-3.4.110/include/linux/mm.h
+--- linux-3.4.110.orig/include/linux/mm.h 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/include/linux/mm.h 2016-04-07 10:20:51.058085512 +0200
+@@ -157,6 +157,7 @@
+ #define FAULT_FLAG_ALLOW_RETRY 0x08 /* Retry fault if blocking */
+ #define FAULT_FLAG_RETRY_NOWAIT 0x10 /* Don't drop mmap_sem and wait when retrying */
+ #define FAULT_FLAG_KILLABLE 0x20 /* The fault task is in SIGKILL killable region */
++#define FAULT_FLAG_TRIED 0x40 /* second try */
+
+ /*
+ * This interface is used by x86 PAT code to identify a pfn mapping that is
+diff -Nur linux-3.4.110.orig/include/linux/semaphore.h linux-3.4.110/include/linux/semaphore.h
+--- linux-3.4.110.orig/include/linux/semaphore.h 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/include/linux/semaphore.h 2016-04-07 10:20:51.062085666 +0200
+@@ -36,6 +36,9 @@
+ lockdep_init_map(&sem->lock.dep_map, "semaphore->lock", &__key, 0);
+ }
+
++#define init_MUTEX(sem) sema_init(sem, 1)
++#define init_MUTEX_LOCKED(sem) sema_init(sem, 0)
++
+ extern void down(struct semaphore *sem);
+ extern int __must_check down_interruptible(struct semaphore *sem);
+ extern int __must_check down_killable(struct semaphore *sem);
+diff -Nur linux-3.4.110.orig/init/Kconfig linux-3.4.110/init/Kconfig
+--- linux-3.4.110.orig/init/Kconfig 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/init/Kconfig 2016-04-07 10:20:51.062085666 +0200
+@@ -966,7 +966,7 @@
+
+ config UID16
+ bool "Enable 16-bit UID system calls" if EXPERT
+- depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION)
++ depends on ARM || BLACKFIN || CRIS || FRV || H8300 || X86_32 || M68K || NDS32 || (S390 && !64BIT) || SUPERH || SPARC32 || (SPARC64 && COMPAT) || UML || (X86_64 && IA32_EMULATION)
+ default y
+ help
+ This enables the legacy 16-bit UID syscall wrappers.
+diff -Nur linux-3.4.110.orig/kernel/Makefile linux-3.4.110/kernel/Makefile
+--- linux-3.4.110.orig/kernel/Makefile 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/kernel/Makefile 2016-04-07 10:20:51.062085666 +0200
+@@ -20,6 +20,7 @@
+ CFLAGS_REMOVE_rtmutex-debug.o = -pg
+ CFLAGS_REMOVE_cgroup-debug.o = -pg
+ CFLAGS_REMOVE_irq_work.o = -pg
++CFLAGS_REMOVE_kallsyms.o = -pg
+ endif
+
+ obj-y += sched/
+diff -Nur linux-3.4.110.orig/kernel/trace/Kconfig linux-3.4.110/kernel/trace/Kconfig
+--- linux-3.4.110.orig/kernel/trace/Kconfig 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/kernel/trace/Kconfig 2016-04-07 10:20:51.062085666 +0200
+@@ -141,7 +141,7 @@
+ config FUNCTION_TRACER
+ bool "Kernel Function Tracer"
+ depends on HAVE_FUNCTION_TRACER
+- select FRAME_POINTER if !ARM_UNWIND && !PPC && !S390 && !MICROBLAZE
++ select FRAME_POINTER if !ARM_UNWIND && !PPC && !S390 && !MICROBLAZE && !NDS32
+ select KALLSYMS
+ select GENERIC_TRACER
+ select CONTEXT_SWITCH_TRACER
+diff -Nur linux-3.4.110.orig/lib/Kconfig.debug linux-3.4.110/lib/Kconfig.debug
+--- linux-3.4.110.orig/lib/Kconfig.debug 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/lib/Kconfig.debug 2016-04-07 10:20:51.062085666 +0200
+@@ -615,7 +615,7 @@
+ bool
+ depends on DEBUG_KERNEL && TRACE_IRQFLAGS_SUPPORT && STACKTRACE_SUPPORT && LOCKDEP_SUPPORT
+ select STACKTRACE
+- select FRAME_POINTER if !MIPS && !PPC && !ARM_UNWIND && !S390 && !MICROBLAZE
++ select FRAME_POINTER if !MIPS && !PPC && !ARM_UNWIND && !S390 && !MICROBLAZE && !NDS32
+ select KALLSYMS
+ select KALLSYMS_ALL
+
+@@ -1122,7 +1122,7 @@
+ depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT
+ depends on !X86_64
+ select STACKTRACE
+- select FRAME_POINTER if !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND
++ select FRAME_POINTER if !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND && !NDS32
+ help
+ Provide stacktrace filter for fault-injection capabilities
+
+@@ -1132,7 +1132,7 @@
+ depends on DEBUG_KERNEL
+ depends on STACKTRACE_SUPPORT
+ depends on PROC_FS
+- select FRAME_POINTER if !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND
++ select FRAME_POINTER if !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM_UNWIND && !NDS32
+ select KALLSYMS
+ select KALLSYMS_ALL
+ select STACKTRACE
+diff -Nur linux-3.4.110.orig/sound/Kconfig linux-3.4.110/sound/Kconfig
+--- linux-3.4.110.orig/sound/Kconfig 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/sound/Kconfig 2016-04-07 10:20:51.062085666 +0200
+@@ -93,6 +93,8 @@
+
+ source "sound/sh/Kconfig"
+
++source "sound/nds32/Kconfig"
++
+ # the following will depend on the order of config.
+ # here assuming USB is defined before ALSA
+ source "sound/usb/Kconfig"
+diff -Nur linux-3.4.110.orig/sound/Makefile linux-3.4.110/sound/Makefile
+--- linux-3.4.110.orig/sound/Makefile 2015-10-22 03:20:09.000000000 +0200
++++ linux-3.4.110/sound/Makefile 2016-04-07 10:20:51.062085666 +0200
+@@ -6,7 +6,7 @@
+ obj-$(CONFIG_SOUND_PRIME) += oss/
+ obj-$(CONFIG_DMASOUND) += oss/
+ obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ sh/ synth/ usb/ \
+- firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/
++ firewire/ sparc/ spi/ parisc/ pcmcia/ mips/ soc/ atmel/ nds32/
+ obj-$(CONFIG_SND_AOA) += aoa/
+
+ # This one must be compilable even if sound is configured out
+diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_ALSA.c linux-3.4.110/sound/nds32/FTSSP010_ALSA.c
+--- linux-3.4.110.orig/sound/nds32/FTSSP010_ALSA.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/sound/nds32/FTSSP010_ALSA.c 2016-04-07 10:20:51.062085666 +0200
+@@ -0,0 +1,2020 @@
++/* FTSSP010 - UDA1345TS module:
++ *
++ * $log$
++ *
++ * 2006/02/23: I-Jui Sung: OSS emulation half-duplex
++ * playback/capture at 48K, 44.1K, 8K
++ * with mono/stereo 16bit/8bit
++ *
++ * 2006/02/22: I-Jui Sung: OSS emulation playback at 44.1KHz
++ * 16-bit mono completed. Relying ALSA to
++ * resample
++ * 2009/02/24: dma upgrade checking list:
++ * - ac97 mode playback ................. ok
++ * - ac97 mode capture .................. ok
++ * - i2s mode playback .................. ok
++ * - i2s mode capture ................... ok
++ * - mixer support (snd_ctl_add, ...) ... todo
++ * - debug /proc entry .................. ok
++ */
++
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <asm/io.h>
++#include <linux/delay.h>
++//#include <asm/spec.h>
++#include <asm/dmad.h>
++#include <linux/dma-mapping.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/initval.h>
++#include <sound/asound.h>
++#include <linux/i2c.h>
++#include <sound/control.h>
++#include <linux/interrupt.h>
++
++#include <asm/hardware.h>
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/spec.h>
++
++#include "FTSSP010_UDA1345TS.h"
++
++//ADD by river 2011.06.02
++struct alc5630_data;
++//End ADD by river 2011.06.02
++
++void init_hw(unsigned int cardno,unsigned int ac97, struct i2c_client *client);
++
++#if (!defined(CONFIG_PLATFORM_AHBDMA) && !defined(CONFIG_PLATFORM_APBDMA))
++#warning needs ahb/apb dma to wrok
++#endif
++
++/* ---------------------------------------------------------------------------
++ * Define the debug level of FTSSP_DEBUG
++ */
++#define FTSSP_DEBUG 0
++#define FTSSP_DEBUG_VERBOSE 0
++#define FTSSP_PROC_FS 0
++
++#undef VVDBG
++#if (FTSSP_DEBUG_VERBOSE)
++#define VVDBG(vvar...) (void)0
++//#define VVDBG(vvar...) printk(KERN_INFO vvar)
++#else
++#define VVDBG(vvar...) (void)0
++#endif
++
++#undef ERR
++#define ERR(vvar...) printk(KERN_ERR vvar)
++
++#undef INFO
++#define INFO(vvar...) printk(KERN_INFO vvar)
++
++#if (FTSSP_DEBUG)
++#undef DBG
++#define DBG(vvar...) printk(KERN_INFO vvar)
++#else
++#define DBG(vvar...) (void)0
++#endif
++
++#if (FTSSP_DEBUG_VERBOSE)
++#undef VDBG
++#define VDBG(vvar...) printk(KERN_INFO vvar)
++#else
++#define VDBG(vvar...) (void)0
++#endif
++
++#ifdef CONFIG_SND_FTSSP010_I2S
++//ADD by river 2011.02.11
++static struct i2c_client *g_i2c_client;
++
++////////// ADD by river 2011.01.26
++// Each client has this additional data
++struct alc5630_data {
++ struct i2c_client *client;
++ struct delayed_work work;
++ unsigned long gpio2_value;
++ struct mutex mtx;
++};
++
++static int alc5630_i2c_attach(struct i2c_adapter *adapter);
++static int alc5630_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id);
++static int alc5630_i2c_suspend(struct i2c_client *i2c_client, pm_message_t mesg);
++static int alc5630_i2c_resume(struct i2c_client *i2c_client);
++
++static int alc5630_i2c_remove(struct i2c_client *client);
++static int ftssp_alsa_init(struct i2c_client *client);
++
++
++static int i2s_alc5630_read(unsigned int raddr, char *data, struct i2c_client *client)
++{
++ struct i2c_adapter *adap = client->adapter;
++ struct i2c_msg msg;
++ int ret, i2c_value;
++
++ //Reading ALC5630 register
++ msg.addr = raddr;
++ msg.flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
++ msg.len = 1;
++ msg.buf = (char *)data;
++
++ //ret = i2c_transfer(adap, &msg, 1);
++ #ifndef CONFIG_SND_FTSSP010_AC97
++ ret = i2c_transfer(adap, &msg, 1);
++ #endif
++
++ if (ret != 0) {
++ printk("i2c read failed\n");
++ return -1;
++ }
++ else
++ {
++ i2c_value = (data[0]&0xff) << 8 | (data[1]&0xff);
++ return i2c_value;
++ }
++
++}
++
++static void i2s_alc5630_write(unsigned int addr, unsigned int data, struct i2c_client *client)
++{
++
++ struct i2c_adapter *adap = client->adapter;
++ struct i2c_msg msg;
++ int ret, i2c_value;
++ char buf[3];
++
++ //Writing ALC5630 register
++ i2c_value = 0x0;
++ msg.addr = addr;
++ msg.flags = (client->flags & I2C_M_TEN) | ~I2C_M_RD;
++ msg.len = 1;
++
++ buf[0] = (data >> 8) & 0xff;
++ buf[1] = data & 0xff;
++ msg.buf = (char *)buf;
++
++ //ret = i2c_transfer(adap, &msg, 1);
++ #ifndef CONFIG_SND_FTSSP010_AC97
++ ret = i2c_transfer(adap, &msg, 1);
++ #endif
++
++ if (ret != 0) {
++ printk("i2c write failed\n");
++ }
++
++}
++
++static void i2s_alc5630_read_test(struct i2c_client *client)
++{
++ char data[3];
++ //printk(">>>>> : i2s_alc5630_read_test().....\n");
++ printk("Reg 0x%02x = 0x%08x\n", 0x0, i2s_alc5630_read(0x0, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x02, i2s_alc5630_read(0x02, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x04, i2s_alc5630_read(0x04, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x06, i2s_alc5630_read(0x06, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x08, i2s_alc5630_read(0x08, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x0a, i2s_alc5630_read(0x0a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x0c, i2s_alc5630_read(0x0c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x0e, i2s_alc5630_read(0x0e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x10, i2s_alc5630_read(0x10, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x12, i2s_alc5630_read(0x12, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x14, i2s_alc5630_read(0x14, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x16, i2s_alc5630_read(0x16, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x18, i2s_alc5630_read(0x18, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x1a, i2s_alc5630_read(0x1a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x1c, i2s_alc5630_read(0x1c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x1e, i2s_alc5630_read(0x1e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x20, i2s_alc5630_read(0x20, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x22, i2s_alc5630_read(0x22, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x24, i2s_alc5630_read(0x24, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x26, i2s_alc5630_read(0x26, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x28, i2s_alc5630_read(0x28, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x2a, i2s_alc5630_read(0x2a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x2c, i2s_alc5630_read(0x2c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x2e, i2s_alc5630_read(0x2e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x30, i2s_alc5630_read(0x30, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x32, i2s_alc5630_read(0x32, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x34, i2s_alc5630_read(0x34, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x36, i2s_alc5630_read(0x36, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x38, i2s_alc5630_read(0x38, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x3a, i2s_alc5630_read(0x3a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x3c, i2s_alc5630_read(0x3c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x3e, i2s_alc5630_read(0x3e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x40, i2s_alc5630_read(0x40, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x42, i2s_alc5630_read(0x42, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x44, i2s_alc5630_read(0x44, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x46, i2s_alc5630_read(0x46, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x48, i2s_alc5630_read(0x48, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x4a, i2s_alc5630_read(0x4a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x4c, i2s_alc5630_read(0x4c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x4e, i2s_alc5630_read(0x4e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x50, i2s_alc5630_read(0x50, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x52, i2s_alc5630_read(0x52, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x54, i2s_alc5630_read(0x54, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x56, i2s_alc5630_read(0x56, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x58, i2s_alc5630_read(0x58, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x5a, i2s_alc5630_read(0x5a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x5c, i2s_alc5630_read(0x5c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x5e, i2s_alc5630_read(0x5e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x60, i2s_alc5630_read(0x60, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x62, i2s_alc5630_read(0x62, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x64, i2s_alc5630_read(0x64, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x66, i2s_alc5630_read(0x66, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x68, i2s_alc5630_read(0x68, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x6a, i2s_alc5630_read(0x6a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x6c, i2s_alc5630_read(0x6c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x6e, i2s_alc5630_read(0x6e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x70, i2s_alc5630_read(0x70, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x72, i2s_alc5630_read(0x72, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x74, i2s_alc5630_read(0x74, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x76, i2s_alc5630_read(0x76, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x78, i2s_alc5630_read(0x78, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x7a, i2s_alc5630_read(0x7a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x7c, i2s_alc5630_read(0x7c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x7e, i2s_alc5630_read(0x7e, data,client));
++
++}
++
++static int alc5630_i2c_attach(struct i2c_adapter *adapter){
++
++ struct i2c_board_info info;
++ struct i2c_client *client;
++
++ int ret=0;
++
++ //i2c_dbg( 1, "alc5630_i2c_attach() is called.\n");
++ //printk(">>>>>>>>>> (2) alc5630_i2c_attach() is called.\n");
++
++ //ret = i2c_probe(adapter, &addr_data, alc5630_detect);
++ memset(&info, 0, sizeof(struct i2c_board_info));
++ strlcpy(info.type, "alc5630_codec", I2C_NAME_SIZE);
++ //info.addr = 0x3e;
++ info.addr = 0x66;
++ //info.platform_data = node;
++
++ //client = i2c_new_device(adapter, &info);
++ #ifndef CONFIG_SND_FTSSP010_AC97
++ client = i2c_new_device(adapter, &info);
++ #endif
++ if (!client) {
++ printk("$$$$$????? : i2c_new_device() failed.....\n");
++ return -ENODEV;
++ }
++ /*
++ * We know the driver is already loaded, so the device should be
++ * already bound. If not it means binding failed, and then there
++ * is no point in keeping the device instantiated.
++ */
++ if (!client->driver) {
++ //i2c_unregister_device(client);
++ #ifndef CONFIG_SND_FTSSP010_AC97
++ i2c_unregister_device(client);
++ #endif
++ return -ENODEV;
++ }
++
++ /*
++ * Let i2c-core delete that device on driver removal.
++ * This is safe because i2c-core holds the core_lock mutex for us.
++ */
++ list_add_tail(&client->detected, &client->driver->clients);
++
++ return ret;
++}
++
++static irqreturn_t gpio2_irq(int irq, void *dev_id)
++{
++
++ struct i2c_client *client = (struct i2c_client *)dev_id;
++ struct alc5630_data *alc5630 = i2c_get_clientdata(client);
++
++ unsigned long org_mask, org_dir;
++ //printk("@@@@@#####$$$$$!!!!! : gpio2_irq is detected ???....\n");
++
++ //Mask GPIO interrupt
++ //REG32(AMIC_VA_BASE + 0x80) = REG32(AMIC_VA_BASE + 0x80) & ~(1 << 13); //GPIO interrupt disable
++
++ //Dump AMIC contents and ir~
++ unsigned long ir0,ir1,ir2, ir3, ir4, ir5;
++ unsigned long ir6, ir7, ir8, ir9, ir10;
++ unsigned long ir11, ir12, ir13, ir14, ir15;
++ unsigned long gpio2_value, value;
++ char data[3];
++
++
++ //__asm__ volatile ("setgie.d\n\t");
++ //REG32(AMIC_VA_BASE + 0x80) = 0;
++
++
++ //Get original gpio direction
++ org_dir = REG32(GPIO_VA_BASE + 0x08);
++
++ //Get original gpio interrupt mask
++ org_mask = REG32(GPIO_VA_BASE + 0x2c);
++
++ //Mask all gpio interrupt
++ REG32(GPIO_VA_BASE + 0x2c) = 0x0000FFFF;
++ //Clear all gpio interrupt
++ REG32(GPIO_VA_BASE + 0x30) = 0x0000FFFF;
++
++ //Get gpio pin value
++ REG32(GPIO_VA_BASE + 0x08) = REG32(GPIO_VA_BASE + 0x08) & ~(0x1UL << 2); //Set gpio2 direction => input
++ gpio2_value = (REG32(GPIO_VA_BASE + 0x04) >> 2 & 1);
++ //printk("The gpio2 value is 0x%08x\n",gpio2_value);
++
++
++ alc5630->gpio2_value = gpio2_value;
++ schedule_delayed_work(&alc5630->work, 1);
++
++ /*if (gpio3_value==0x1) {
++ i2s_alc5630_write(0x02, 0x0000, g_i2c_client);
++ i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0040 , g_i2c_client);
++ printk("External speaker is plugged in... and Try to mute internal speaker......\n");
++ }
++ else {
++ i2s_alc5630_write(0x02, 0x5F5F, g_i2c_client);
++ i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0440 , g_i2c_client);
++ printk("External speaker is pulled ... and Try to unmute internal speaker......\n");
++ }*/
++
++
++ //Set gpio3 pin value to 0
++ //REG32(GPIO_VA_BASE + 0x08) = REG32(GPIO_VA_BASE + 0x08) | (0x1UL << 3); //Set gpio3 direction => output
++ //value = REG32(GPIO_VA_BASE + 0x00) & ~(0x1UL << 3);
++ //REG32(GPIO_VA_BASE + 0x00) = value;
++
++ //Get gpio pin value again
++ //REG32(GPIO_VA_BASE + 0x08) = REG32(GPIO_VA_BASE + 0x08) & ~(0x1UL << 3); //Set gpio3 direction => input
++ //gpio3_value = (REG32(GPIO_VA_BASE + 0x04) >> 3 & 1);
++ //printk("The gpio3 value is 0x%08x\n",gpio3_value);
++
++ //restore original gpio interrupt mask
++ REG32(GPIO_VA_BASE + 0x2c) = org_mask;
++
++ //restore original gpio direction
++ REG32(GPIO_VA_BASE + 0x08) = org_dir;
++
++ //unmask GPIO interrupt
++ //REG32(AMIC_VA_BASE + 0x80) = REG32(AMIC_VA_BASE + 0x80) | (1 << 13); //GPIO interrupt enable
++ REG32(AMIC_VA_BASE + 0x84) = REG32(AMIC_VA_BASE + 0x84) | (1 << 13); //Clear GPIO interrupt
++ REG32(GPIO_VA_BASE + 0x30) = 0x0000FFFF; //Clear all gpio interrupt
++
++ //printk("@@@@@#####$$$$$!!!!! : gpio2_irq() is exited....\n");
++
++ return IRQ_HANDLED;
++}
++
++static void iic_work(struct work_struct *work)
++{
++ char data[3];
++ struct alc5630_data *alc5630 =
++ container_of(to_delayed_work(work), struct alc5630_data, work);
++
++
++ if (alc5630->gpio2_value==0x0) {
++ //i2s_alc5630_write(0x02, 0x0000, alc5630->client);
++ i2s_alc5630_write(0x02, 0x5F5F, alc5630->client);
++ i2s_alc5630_write(0x3A, (i2s_alc5630_read(0x3A, data,alc5630->client) & 0xFBFF) | 0x0040 , alc5630->client);
++ //printk("External speaker is plugged in... and Try to mute internal speaker......\n");
++ //i2s_alc5630_read_test(alc5630->client);
++ }
++ else {
++ //i2s_alc5630_write(0x02, 0x5F5F, alc5630->client);
++ i2s_alc5630_write(0x02, 0x0000, alc5630->client);
++ i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,alc5630->client)|0x0440 , alc5630->client);
++ //printk("External speaker is pulled ... and Try to unmute internal speaker......\n");
++ //i2s_alc5630_read_test(alc5630->client);
++ }
++ //ftsdc_enable_irq(host, false);
++
++
++ //ftsdc_enable_irq(host, true);
++}
++
++static int alc5630_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
++{
++
++ struct alc5630_data *alc5630;
++ struct i2c_adapter *adap = client->adapter;
++ //unsigned char ret1, ret2;
++ struct i2c_msg msg;
++ char rbuf[3], wbuf[3];
++ int ret, i2c_rvalue, i2c_wvalue;
++ unsigned int gpio2_value;
++ char data[3];
++
++ //i2c_dbg( 1, "alc5630_i2c_probe() is called.\n");
++ //printk(">>>>>>>>>> (3) alc5630_i2c_probe() is called.\n");
++
++ alc5630 = kzalloc(sizeof(struct alc5630_data), GFP_KERNEL);
++
++ if (!alc5630)
++ return -ENOMEM;
++
++ mutex_init(&alc5630->mtx);
++ client-> flags = 0;
++ alc5630->client = client;
++ i2c_set_clientdata(client, alc5630);
++
++ //ADD by river 2011.05.18 for GPIO2 interrupt => edge trigger and rising edge
++ REG32(GPIO_VA_BASE + 0x20) = 0x00000000;
++ REG32(GPIO_VA_BASE + 0x2c) = 0x00000000;
++ REG32(GPIO_VA_BASE + 0x2c) = 0x00000000;
++ REG32(GPIO_VA_BASE + 0x30) = 0x0000FFFF;
++ REG32(GPIO_VA_BASE + 0x38) = 0x0000FFFF;
++ REG32(GPIO_VA_BASE + 0x40) = 0x0000FFFF;
++
++
++ REG32(GPIO_VA_BASE + 0x08) = REG32(GPIO_VA_BASE + 0x08) & ~(1 << 2); //GPIO2 as input
++ REG32(GPIO_VA_BASE + 0x34) = REG32(GPIO_VA_BASE + 0x34) & ~(1 << 2); //GPIO2 edge trigger
++ //REG32(GPIO_VA_BASE + 0x38) = REG32(GPIO_VA_BASE + 0x38) & ~(1 << 2); //GPIO2 single edge
++ REG32(GPIO_VA_BASE + 0x38) = REG32(GPIO_VA_BASE + 0x38) | (1 << 2); //GPIO2 both edge
++ REG32(GPIO_VA_BASE + 0x3c) = REG32(GPIO_VA_BASE + 0x3c) & ~(1 << 2); //GPIO2 rising edge
++ REG32(GPIO_VA_BASE + 0x20) = REG32(GPIO_VA_BASE + 0x20) | (1 << 2); //GPIO2 pin interrupt enable
++
++ REG32(AMIC_VA_BASE + 0x20) = REG32(AMIC_VA_BASE + 0x20) | (1 << 13); //Interrupt Trigger Mode (edge trigger)
++ REG32(AMIC_VA_BASE + 0x24) = REG32(AMIC_VA_BASE + 0x24) & ~(1 << 13); //Interrupt Trigger edge(rising edge)
++ REG32(AMIC_VA_BASE + 0x80) = REG32(AMIC_VA_BASE + 0x80) | (1 << 13); //GPIO interrupt enabled
++ //REG32(AMIC_VA_BASE + 0x80) = 0; //GPIO interrupt enabled
++
++ if (request_irq(GPIO_FTGPIO010_IRQ, gpio2_irq, IRQF_SHARED, "gpio2", client)) {
++ printk("Failed to request GPIO2 interrupt.\n");
++ goto fail;
++ }
++
++ //ADD by river 2011.07.11
++ //REG32(GPIO_VA_BASE + 0x08) = REG32(GPIO_VA_BASE + 0x08) & ~(0x1UL << 3); //Set gpio3 direction => input
++ gpio2_value = (REG32(GPIO_VA_BASE + 0x04) >> 2 & 1);
++ //printk("The gpio2 value is 0x%08x\n",gpio2_value);
++ alc5630->gpio2_value = gpio2_value;
++
++ if (gpio2_value==0x0) {
++ i2s_alc5630_write(0x02, 0x5F5F, alc5630->client);
++ i2s_alc5630_write(0x3A, (i2s_alc5630_read(0x3A, data,alc5630->client) & 0xFBFF) | 0x0040 , alc5630->client);
++ //printk("@@@@@ alc5630_i2c_probe : External speaker is plugged in... and Try to mute internal speaker......\n");
++ //i2s_alc5630_read_test(alc5630->client);
++ }
++ else {
++ i2s_alc5630_write(0x02, 0x0000, alc5630->client);
++ i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,alc5630->client)|0x0440 , alc5630->client);
++ //printk("@@@@@ alc5630_i2c_probe : External speaker is pulled ... and Try to unmute internal speaker......\n");
++ //i2s_alc5630_read_test(alc5630->client);
++ }
++
++ //End ADD by river 2011.07.11
++
++ //ADD by river 2011.06.02
++ INIT_DELAYED_WORK(&alc5630->work, iic_work);
++ //End ADD by river 2011.06.02
++ //End ADD by river 2011.05.18
++
++ ftssp_alsa_init(client);
++
++ return 0;
++ fail:
++ mutex_destroy(&alc5630->mtx);
++ kfree(alc5630);
++ return -EINVAL;
++
++}
++
++////////End ADD by river 2011.01.26
++#endif
++
++/* ---------------------------------------------------------------------------
++ * Preserved size of memory space for audio DMA ring
++ */
++#define FTSSP_HW_DMA_SIZE (512 * 1024)
++
++/* Buffer sizes reported to ALSA layer - AC97 mode */
++
++/* ring size, exported to application */
++#define AC97_HW_BUFFER_BYTES_MAX (42 * 1024)
++/* should not exceed AC97_HW_PERIOD_BYTES_MAX */
++#define AC97_HW_PERIOD_BYTES_MIN (2 * 1024)
++/* AC97_HW_PERIOD_BYTES_MAX * AC97_HW_PERIODS_MAX <= AC97_HW_BUFFER_SIZE */
++#define AC97_HW_PERIOD_BYTES_MAX (8 * 1024)
++/* 3 <= AC97_HW_PERIODS_MIN <= AC97_HW_PERIODS_MAX */
++#define AC97_HW_PERIODS_MIN 3
++/* AC97_HW_PERIOD_BYTES_MAX * AC97_HW_PERIODS_MAX <= AC97_HW_BUFFER_SIZE */
++#define AC97_HW_PERIODS_MAX 5
++
++/* Driver internal dma buffer size, x2 for S16_LE(16-bits) to AC97 (20-bits),
++ * x6 for sampling rate converion from minimum 8k to AC97 48k.
++ *
++ * Note that AC97 mode cannot do playback and recording simultaneouly. So we
++ * use up all FTSSP_HW_DMA_SIZE of memory.
++ */
++#define AC97_HW_DMA_SIZE (AC97_HW_BUFFER_BYTES_MAX * 2 * 6)
++
++/* Buffer sizes reported to ALSA layer - I2S mode */
++
++/* ring size, exported to application */
++#define I2S_HW_BUFFER_BYTES_MAX (256 * 1024)
++/* should not exceed I2S_HW_PERIOD_BYTES_MAX */
++#define I2S_HW_PERIOD_BYTES_MIN (2 * 1024)
++/* I2S_HW_PERIOD_BYTES_MAX * I2S_HW_PERIODS_MAX <= I2S_HW_BUFFER_SIZE */
++#define I2S_HW_PERIOD_BYTES_MAX (32 * 1024)
++/* 3 <= I2S_HW_PERIODS_MIN <= I2S_HW_PERIODS_MAX */
++#define I2S_HW_PERIODS_MIN 3
++/* I2S_HW_PERIOD_BYTES_MAX * I2S_HW_PERIODS_MAX <= I2S_HW_BUFFER_SIZE */
++#define I2S_HW_PERIODS_MAX 8
++
++/* Page-in size for playback and capture each. Note that I2S mode can do
++ * playback and recording simultaneouly, so this size should be less than or
++ * equal to FTSSP_HW_DMA_SIZE/2
++ */
++#define I2S_HW_DMA_SIZE (I2S_HW_BUFFER_BYTES_MAX)
++
++/* ---------------------------------------------------------------------------
++ * Audio formats
++ */
++#define AC97_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
++#define AC97_CODEC_SAMPLE_RATES (SNDRV_PCM_RATE_48000 | \
++ SNDRV_PCM_RATE_16000 | \
++ SNDRV_PCM_RATE_8000)
++#define AC97_CODEC_SAMPLE_RATE_MIN (8000)
++#define AC97_CODEC_SAMPLE_RATE_MAX (48000)
++
++#define I2S_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
++#define I2S_CODEC_SAMPLE_RATES (SNDRV_PCM_RATE_48000 | \
++ SNDRV_PCM_RATE_44100 | \
++ SNDRV_PCM_RATE_32000 | \
++ SNDRV_PCM_RATE_22050 | \
++ SNDRV_PCM_RATE_16000 | \
++ SNDRV_PCM_RATE_11025 | \
++ SNDRV_PCM_RATE_8000)
++#define I2S_CODEC_SAMPLE_RATE_MIN (8000)
++#define I2S_CODEC_SAMPLE_RATE_MAX (48000)
++
++
++/* ---------------------------------------------------------------------------
++ * Configuration
++ */
++#if (CONFIG_PROC_FS == 0)
++#undef FTSSP_PROC_FS
++#define FTSSP_PROC_FS 0
++#else
++#if (FTSSP_PROC_FS)
++#include <sound/info.h>
++#endif /* FTSSP_PROC_FS */
++#endif /* CONFIG_PROC_FS */
++
++#define FTSSP_CARD_ID "ftssp010"
++#define FTSSP_DRIVER_NAME "ftssp"
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Faraday Technology Corp.");
++MODULE_DESCRIPTION("FTSSP010 Linux 2.6 Driver");
++
++static int cardno = 0;
++//static const unsigned int SSP_FTSSP010_pa_base[SSP_FTSSP010_IRQ_COUNT] =
++// { SSP_FTSSP010_PA_BASE };
++
++/* Driver mode */
++#ifdef CONFIG_SND_FTSSP010_AC97
++static int ac97 = 1;
++#else
++static int ac97 = 0;
++#endif
++
++// ----------------------------------------------
++module_param(cardno, int, 0);
++MODULE_PARM_DESC(cardno, "FTSSP No.");
++
++module_param(ac97, int, 0);
++MODULE_PARM_DESC(ac97, "AC97 mode");
++// ----------------------------------------------
++
++/* ---------------------------------------------------------------------------
++ * Structures
++ */
++
++/* private data for card */
++typedef struct {
++ struct snd_card *card;
++ struct snd_pcm *pcm;
++ struct snd_pcm_substream *substream_tx;
++ struct snd_pcm_substream *substream_rx;
++#if (FTSSP_PROC_FS)
++ struct snd_info_entry *info_buf_max;
++ struct snd_info_entry *info_period_min;
++ struct snd_info_entry *info_period_max;
++ struct snd_info_entry *info_periods_min;
++ struct snd_info_entry *info_periods_max;
++#endif
++} ftssp_chip;
++
++/* dma request descriptors */
++dmad_chreq dma_chreq_tx = {
++ .channel = -1,
++ .drq = NULL,
++};
++
++dmad_chreq dma_chreq_rx = {
++ .channel = -1,
++ .drq = NULL,
++};
++
++/* Holds ALSA card instance pointers */
++struct snd_card *ftssp_cards[SSP_FTSSP010_COUNT];
++
++/* snd_pcm_hardware */
++static struct snd_pcm_hardware snd_ftssp_pcm_hw =
++{
++ .info = SNDRV_PCM_INFO_INTERLEAVED,
++ .formats = I2S_CODEC_FORMATS,
++ .rates = I2S_CODEC_SAMPLE_RATES,
++ .rate_min = I2S_CODEC_SAMPLE_RATE_MIN,
++ .rate_max = I2S_CODEC_SAMPLE_RATE_MAX,
++ .channels_min = 1,
++ .channels_max = 2,
++ .buffer_bytes_max = I2S_HW_BUFFER_BYTES_MAX,
++ .period_bytes_min = I2S_HW_PERIOD_BYTES_MIN,
++ .period_bytes_max = I2S_HW_PERIOD_BYTES_MAX,
++ .periods_min = I2S_HW_PERIODS_MIN,
++ .periods_max = I2S_HW_PERIODS_MAX,
++};
++
++/* private data for a substream (playback or capture) */
++/* function pointer for set up AHBDMA for this substream */
++typedef void (*start_t)(int cardno, unsigned use_dma);
++typedef void (*pmu_set_clocking_t)(unsigned int);
++typedef void (*ftssp010_config_t)(int cardno, unsigned is_stereo,
++ unsigned speed, int use8bit);
++
++typedef struct {
++ u32 busy;
++ spinlock_t dma_lock;
++ unsigned dma_area_va;
++ int dma_width;
++ unsigned int tx_period;
++ unsigned int rx_period;
++
++ start_t start;
++ pmu_set_clocking_t pmu_set_clocking;
++ ftssp010_config_t hw_config;
++} ftssp_substream;
++
++static ftssp_substream ftssp010_substreams[2] = {
++ /* Playback substream */
++ {
++ busy : 0,
++ start : ftssp010_start_tx,
++ pmu_set_clocking : pmu_set_i2s_clocking,
++ hw_config : ftssp010_config_tx,
++ },
++ /* Capture substream */
++ {
++ busy : 0,
++ start : ftssp010_start_rx,
++ pmu_set_clocking : pmu_set_i2s_clocking,
++ hw_config : ftssp010_config_rx,
++ }
++};
++
++/* (AC97 only) Convert 16 bits PCM data in user buffer to/from 20 bits PCM data
++ * (32 bits actaully in dma buffer) for AC97 codec.
++ */
++static int snd_ftssp_playback_copy(struct snd_pcm_substream *substream,
++ int channel, snd_pcm_uframes_t pos, void *usr_buf,
++ snd_pcm_uframes_t count)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *) runtime->private_data;
++
++
++ //printk("~~~~~ : snd_ftssp_playback_copy() is invoked....\n");
++ u32 *dma_va = NULL;
++ u16 *usr_va = usr_buf;
++ int copy_words;
++ int pcm_data;
++
++ dmad_chreq *dma_chreq;
++
++ /* frames_to_bytes(runtime, pos + count) * 2(bytes/per pcm) /
++ * 4(bytes per dma unit) */
++ u32 sw_ptr = (u32)frames_to_bytes(runtime, pos + count) >> 1;
++
++ switch (runtime->rate) {
++ case 8000:
++ sw_ptr *= 6;
++
++ dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
++ frames_to_bytes(runtime, pos * 6) * 2);
++
++ VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
++ __func__, (u32)pos, (u32)count, (u32)(pos + count));
++ VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
++ __func__, (u32)ftssp010_substream->dma_area_va,
++ (u32)dma_va,
++ (u32)dma_va +
++ (u32)2 * frames_to_bytes(runtime, count * 6));
++
++ if (runtime->channels == 1) {
++ while (count--) {
++ dma_va[0] = (u32)(*usr_va++) << 4;
++ dma_va[1] = dma_va[2] = dma_va[3] =
++ dma_va[4] = dma_va[5] = dma_va[0];
++ //memcpy(&dma_va[1], &dma_va[0], 5 * 4 * 1);
++ dma_va += 6;
++ }
++ } else { // assume 2 channels
++ while (count--) {
++ dma_va[0] = (u32)(*usr_va++) << 4;
++ dma_va[1] = (u32)(*usr_va++) << 4;
++ dma_va[2] = dma_va[4] = dma_va[6] =
++ dma_va[8] = dma_va[10] = dma_va[0];
++ dma_va[3] = dma_va[5] = dma_va[7] =
++ dma_va[9] = dma_va[11] = dma_va[0];
++ //memcpy(&dma_va[2], &dma_va[0], 5 * 4 * 2);
++ dma_va += 12;
++ }
++ }
++ break;
++ case 16000:
++ sw_ptr *= 3;
++
++ dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
++ frames_to_bytes(runtime, pos * 3) * 2);
++
++ VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
++ __func__, (u32)pos, (u32)count, (u32)(pos + count));
++ VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
++ __func__, (u32)ftssp010_substream->dma_area_va,
++ (u32)dma_va,
++ (u32)dma_va +
++ (u32)2 * frames_to_bytes(runtime, count * 3));
++
++ if (runtime->channels == 1) {
++ while (count--) {
++ dma_va[0] = (u32)(*usr_va++) << 4;
++ dma_va[1] = dma_va[2] = dma_va[0];
++ //memcpy(&dma_va[1], &dma_va[0], 2 * 4 * 1);
++ dma_va += 3;
++ }
++ } else { // assume 2 channels
++ while (count--) {
++ dma_va[0] = (u32)(*usr_va++) << 4;
++ dma_va[1] = (u32)(*usr_va++) << 4;
++ dma_va[2] = dma_va[4] = dma_va[0];
++ dma_va[3] = dma_va[5] = dma_va[1];
++ //memcpy(&dma_va[2], &dma_va[0], 2 * 4 * 2);
++ dma_va += 6;
++ }
++ }
++ break;
++ case 48000:
++ default:
++ dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
++ frames_to_bytes(runtime, pos) * 2);
++ copy_words = 2 * frames_to_bytes(runtime, count) / sizeof(u32);
++
++ VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
++ __func__, (u32)pos, (u32)count, (u32)(pos + count));
++ VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
++ __func__, (u32)ftssp010_substream->dma_area_va,
++ (u32)dma_va,
++ (u32)dma_va + (u32)copy_words*4);
++
++ while (copy_words--) {
++ pcm_data = (*usr_va++);
++ *dma_va++= pcm_data << 4;
++ }
++ break;
++ }
++
++ dma_chreq = &dma_chreq_tx;
++
++ if (dmad_update_ring_sw_ptr(dma_chreq, sw_ptr,
++ (runtime->status->state == SNDRV_PCM_STATE_RUNNING) ? 1:0) != 0)
++ {
++ ERR("%s: failed to update sw-pointer!\n", __func__);
++ return -ENODEV;
++ }
++
++ return 0;
++}
++
++static int snd_ftssp_capture_copy(struct snd_pcm_substream *substream,
++ int channel, snd_pcm_uframes_t pos, void *usr_buf,
++ snd_pcm_uframes_t count)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *) runtime->private_data;
++
++ //printk("~~~~~ : snd_ftssp_capture_copy() is invoked....\n");
++ //printk(">>>>>>>>>> : snd_ftssp_capture_copy() for recording....\n");
++ u32 *dma_va = NULL;
++ u16 *usr_va = usr_buf;
++
++ switch (runtime->rate) {
++ case 8000:
++ dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
++ frames_to_bytes(runtime, pos * 6) * 2);
++
++ VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
++ __func__, (u32)pos, (u32)count, (u32)(pos + count));
++ VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
++ __func__, (u32)ftssp010_substream->dma_area_va,
++ (u32)dma_va,
++ (u32)dma_va +
++ (u32)2 * frames_to_bytes(runtime, count * 6));
++
++ if (runtime->channels == 1) {
++ while (count--) {
++ *usr_va++ = (u16)(dma_va[0] >> 4);
++ dma_va += 6;
++ }
++ } else {
++ while (count--) {
++ usr_va[0] = (u16)(dma_va[0] >> 4);
++
++ /* [hw-limit] only slot-3 has valid data in
++ * recording mode -- check TAG_DATA_MONO
++ * defined in "FTSSP010_lib.c". Mask out
++ * one channel to avoid hi-freq noise.
++ */
++ usr_va[1] = usr_va[0];
++ usr_va += 2;
++ dma_va += 12;
++ }
++ }
++ break;
++ case 16000:
++ dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
++ frames_to_bytes(runtime, pos * 3) * 2);
++
++ VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
++ __func__, (u32)pos, (u32)count, (u32)(pos + count));
++ VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
++ __func__, (u32)ftssp010_substream->dma_area_va,
++ (u32)dma_va,
++ (u32)dma_va +
++ (u32)2 * frames_to_bytes(runtime, count * 3));
++
++ if (runtime->channels == 1) {
++ while (count--) {
++ *usr_va++ = (u16)(dma_va[0] >> 4);
++ dma_va += 3;
++ }
++ } else {
++ while (count--) {
++ usr_va[0] = (u16)(dma_va[0] >> 4);
++
++ /* [hw-limit] only slot-3 has valid data in
++ * recording mode -- check TAG_DATA_MONO
++ * defined in "FTSSP010_lib.c". Mask out
++ * one channel to avoid hi-freq noise.
++ */
++ usr_va[1] = usr_va[0];
++ usr_va += 2;
++ dma_va += 6;
++ }
++ }
++ break;
++ case 48000:
++ default:
++ dma_va = (unsigned *)(ftssp010_substream->dma_area_va +
++ frames_to_bytes(runtime, pos) * 2);
++
++ VVDBG("%s: pos(0x%08x) count(0x%08x) next_pos(0x%08x)\n",
++ __func__, (u32)pos, (u32)count, (u32)(pos + count));
++ VVDBG("%s: va base(0x%08x) range (0x%08x ~ 0x%08x)\n",
++ __func__, (u32)ftssp010_substream->dma_area_va,
++ (u32)dma_va,
++ (u32)dma_va +
++ (u32)2 * frames_to_bytes(runtime, count));
++
++ if (runtime->channels == 1) {
++ while (count--) {
++ *usr_va++ = (u16)(*dma_va++ >> 4);
++ }
++ } else {
++ while (count--) {
++ usr_va[0] = (u16)(dma_va[0] >> 4);
++
++ /* [hw-limit] only slot-3 has valid data in
++ * recording mode -- check TAG_DATA_MONO
++ * defined in "FTSSP010_lib.c". Mask out
++ * one channel to avoid hi-freq noise.
++ */
++ usr_va[1] = usr_va[0];
++ usr_va += 2;
++ dma_va += 2;
++ }
++ }
++ break;
++ }
++
++ return 0;
++}
++
++/**
++ * These dma callbacks are called in interrupt context.
++ * @data: pointer to the chip-wide structure.
++ * TODO: use stream-specifc data
++ */
++__attribute__((__unused__))
++static void ftssp_dma_callback_tx(int ch, u16 int_status, void *data)
++{
++ ftssp_chip *chip = (ftssp_chip *)data;
++
++ //printk("~~~~~ : ftssp_dma_callback_tx() is invoked....\n");
++ if (!ac97) {
++ /* in i2s mode, no indication to driver for user data length.
++ * For simplicity, just go ahead by one period */
++
++ struct snd_pcm_runtime *runtime = chip->substream_tx->runtime;
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *)runtime->private_data;
++ u32 sw_ptr;
++ u32 tx_period = ftssp010_substream->tx_period + 1;
++
++ if (tx_period == runtime->periods)
++ sw_ptr = runtime->buffer_size;
++ else
++ sw_ptr = tx_period * runtime->period_size;
++
++ sw_ptr = (u32)frames_to_bytes(runtime, sw_ptr) >> 1;
++
++ if (dmad_update_ring_sw_ptr(&dma_chreq_tx, (u32)sw_ptr, 0)) {
++ ERR("%s: failed to update sw-pointer!\n", __func__);
++ }
++
++ ftssp010_substream->tx_period = tx_period % runtime->periods;
++ }
++
++ snd_pcm_period_elapsed(chip->substream_tx);
++}
++
++__attribute__((__unused__))
++static void ftssp_dma_callback_rx(int ch, u16 int_status, void *data)
++{
++ ftssp_chip *chip = (ftssp_chip *)data;
++ struct snd_pcm_runtime *runtime = chip->substream_rx->runtime;
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *)runtime->private_data;
++
++ //printk("~~~~~ : ftssp_dma_callback_rx() is invoked....\n");
++ //printk(">>>>>>>>>> : ftssp_dma_callback_rx() for recording....\n");
++
++ u32 sw_ptr;
++ u32 rx_period = ftssp010_substream->rx_period + 1;
++
++ if (rx_period == runtime->periods)
++ sw_ptr = runtime->buffer_size;
++ else
++ sw_ptr = rx_period * runtime->period_size;
++
++ if (ac97) {
++ switch (runtime->rate) {
++ case 8000:
++ sw_ptr = sw_ptr * 6;
++ break;
++ case 16000:
++ sw_ptr = sw_ptr * 3;
++ break;
++ case 48000:
++ default:
++ break;
++ }
++ }
++ sw_ptr = (u32)frames_to_bytes(runtime, sw_ptr) >> 1;
++
++ if (dmad_update_ring_sw_ptr(&dma_chreq_rx, (u32)sw_ptr, 0) != 0) {
++ ERR("%s: failed to update sw-pointer!\n", __func__);
++ }
++
++ ftssp010_substream->rx_period = rx_period % runtime->periods;
++
++ snd_pcm_period_elapsed(chip->substream_rx);
++}
++
++static inline int snd_ftssp_dma_ch_alloc(struct snd_pcm_substream *substream)
++{
++ dmad_chreq *ch_req __attribute__((__unused__)) = 0;
++
++ //printk("~~~~~ WATCH : snd_ftssp_dma_ch_alloc() is invoked....\n");
++#ifdef CONFIG_PLATFORM_APBDMA
++
++ if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++ ch_req = &dma_chreq_tx;
++ ch_req->completion_cb = ftssp_dma_callback_tx;
++ ch_req->apb_req.tx_dir = DMAD_DIR_A0_TO_A1;
++ /*for amerald ac97 ssp2 */
++ if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID)
++ {
++ ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97TX_AMERALD;
++ }
++ else
++ ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97TX;
++ } else {
++ ch_req = &dma_chreq_rx;
++ ch_req->completion_cb = ftssp_dma_callback_rx;
++ ch_req->apb_req.tx_dir = DMAD_DIR_A1_TO_A0;
++ /*for amerald ac97 ssp2 */
++ if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID)
++ {
++ ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97RX_AMERALD;
++ }
++ else
++ ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97RX;
++ }
++
++ ch_req->controller = DMAD_DMAC_APB_CORE;
++ ch_req->flags = DMAD_FLAGS_RING_MODE;
++ ch_req->ring_base = 0;
++ ch_req->dev_addr = (dma_addr_t)FTSSP010_DATA_PA(cardno);
++ ch_req->periods = 0;
++ ch_req->period_size = 0;
++
++ if (ac97) {
++ ch_req->apb_req.ring_ctrl = APBBR_ADDRINC_I4X;
++ ch_req->apb_req.ring_reqn = APBBR_REQN_NONE;
++ ch_req->apb_req.dev_ctrl = APBBR_ADDRINC_FIXED;
++ ch_req->apb_req.burst_mode = 0;
++ ch_req->apb_req.data_width = APBBR_DATAWIDTH_4;
++ } else {
++ ch_req->apb_req.ring_ctrl = APBBR_ADDRINC_I2X;
++ ch_req->apb_req.ring_reqn = APBBR_REQN_NONE;
++ ch_req->apb_req.dev_ctrl = APBBR_ADDRINC_FIXED;
++ ch_req->apb_req.burst_mode = 0;
++ ch_req->apb_req.data_width = APBBR_DATAWIDTH_2;
++ }
++
++ ch_req->completion_data = (void *)snd_pcm_substream_chip(substream);
++
++ if (dmad_channel_alloc(ch_req) != 0) {
++ ERR("%s: APBDMA channel allocation failed\n",__func__);
++ goto _try_ahb;
++ }
++
++ DBG("%s: APBDMA channel allocated (ch: %d) ring_mode\n",
++ __func__, ch_req->channel);
++
++ return 0;
++
++_try_ahb:
++
++#endif /* CONFIG_PLATFORM_APBDMA */
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++ if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++ ch_req = &dma_chreq_tx;
++ ch_req->completion_cb = ftssp_dma_callback_tx;
++ ch_req->ahb_req.tx_dir = DMAD_DIR_A0_TO_A1;
++ if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID)
++ {
++ ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97TX_AMERALD;
++ }
++ else
++ ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97TX;
++ } else {
++ ch_req = &dma_chreq_rx;
++ ch_req->completion_cb = ftssp_dma_callback_rx;
++ ch_req->ahb_req.tx_dir = DMAD_DIR_A1_TO_A0;
++ if((inl(PMU_BASE) & AMERALD_MASK) == AMERALD_PRODUCT_ID)
++ {
++ ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97RX_AMERALD;
++ }
++ else
++ ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97RX;
++ }
++
++ ch_req->controller = DMAD_DMAC_AHB_CORE;
++ ch_req->flags = DMAD_FLAGS_RING_MODE;
++ ch_req->ring_base = 0;
++ ch_req->dev_addr = (dma_addr_t)FTSSP010_DATA_PA(cardno);
++ ch_req->periods = 0;
++ ch_req->period_size = 0;
++
++ ch_req->ahb_req.sync = 1;
++ ch_req->ahb_req.priority = DMAC_CSR_CHPRI_2;
++ ch_req->ahb_req.hw_handshake = 1;
++ ch_req->ahb_req.burst_size = DMAC_CSR_SIZE_1;
++
++ if (ac97) {
++ ch_req->ahb_req.ring_width = DMAC_CSR_WIDTH_32;
++ ch_req->ahb_req.ring_ctrl = DMAC_CSR_AD_INC;
++ ch_req->ahb_req.ring_reqn = DMAC_REQN_NONE;
++ ch_req->ahb_req.dev_width = DMAC_CSR_WIDTH_32;
++ ch_req->ahb_req.dev_ctrl = DMAC_CSR_AD_FIX;
++ } else {
++ ch_req->ahb_req.ring_width = DMAC_CSR_WIDTH_16;
++ ch_req->ahb_req.ring_ctrl = DMAC_CSR_AD_INC;
++ ch_req->ahb_req.ring_reqn = DMAC_REQN_NONE;
++ ch_req->ahb_req.dev_width = DMAC_CSR_WIDTH_16;
++ ch_req->ahb_req.dev_ctrl = DMAC_CSR_AD_FIX;
++ }
++
++ ch_req->completion_data = (void *)snd_pcm_substream_chip(substream);
++
++ if (dmad_channel_alloc(ch_req) != 0) {
++ ERR("%s: AHBDMA channel allocation failed\n", __func__);
++ goto _err_exit;
++ }
++
++ DBG("%s: AHBDMA channel allocated (ch: %d) ring_mode\n",
++ __func__, ch_req->channel);
++
++ return 0;
++
++_err_exit:
++
++#endif /* CONFIG_PLATFORM_AHBDMA */
++
++ return -ENODEV;
++}
++
++static inline ftssp_substream *ftssp010_substream_new(int stream_id)
++{
++ ftssp_substream *s = NULL;
++
++ //printk("~~~~~ : ftssp010_substream_new() is invoked....\n");
++
++ switch (stream_id) {
++ case SNDRV_PCM_STREAM_PLAYBACK:
++ s = &ftssp010_substreams[0];
++ break;
++ case SNDRV_PCM_STREAM_CAPTURE:
++ s = &ftssp010_substreams[1];
++ break;
++ default:
++ ERR("%s: wrong stream type (%d)\n", __func__, stream_id);
++ return NULL;
++ }
++
++ if (s->busy) {
++ ERR("%s: device busy!\n", __func__);
++ return NULL;
++ }
++ s->busy = 1;
++
++ spin_lock_init(&s->dma_lock);
++
++ return s;
++}
++
++static int snd_ftssp_pcm_open(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ int stream_id = substream->pstr->stream;
++
++ VDBG("%s, %s\n", __func__,
++ (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++ "playback" : "capture");
++
++ //printk("~~~~~ : snd_ftssp_pcm_open() is invoked....\n");
++
++ /* Both playback and capture share a hardware description */
++ runtime->hw = snd_ftssp_pcm_hw;
++
++ /* Allocate & Initialize stream-specific data */
++ runtime->private_data = ftssp010_substream_new(stream_id);
++
++ if (runtime->private_data) {
++ //printk("~~~~~ YAYAYA @@@@@ : Calling snd_ftssp_dma_ch_alloc().\n");
++ return snd_ftssp_dma_ch_alloc(substream);
++ }
++ else
++ return -EBUSY;
++}
++
++static int snd_ftssp_pcm_close(struct snd_pcm_substream *substream)
++{
++ int stream_id = substream->pstr->stream;
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *)substream->runtime->private_data;
++
++ VDBG("%s, %s\n", __func__,
++ (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++ "playback" : "capture");
++
++ //printk("~~~~~ : snd_ftssp_pcm_close() is invoked....\n");
++
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
++ dmad_channel_free(&dma_chreq_tx);
++ else
++ dmad_channel_free(&dma_chreq_rx);
++
++ ftssp010_substream->busy = 0;
++ return 0;
++}
++
++static int snd_ftssp_pcm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *hw_params)
++{
++ VDBG("%s, %s\n", __func__,
++ (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++ "playback" : "capture");
++
++ //printk("~~~~~ : snd_ftssp_pcm_hw_params() is invoked....\n");
++
++ if (ac97)
++ return snd_pcm_lib_malloc_pages(substream, AC97_HW_DMA_SIZE);
++ else
++ return snd_pcm_lib_malloc_pages(substream, I2S_HW_DMA_SIZE);
++}
++
++static int snd_ftssp_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++ VDBG("%s, %s\n", __func__,
++ (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++ "playback" : "capture");
++ //printk("~~~~~ : snd_ftssp_pcm_hw_free() is invoked....\n");
++
++ if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ dmad_drain_requests(&dma_chreq_tx, 1);
++ else
++ dmad_drain_requests(&dma_chreq_rx, 1);
++
++ return snd_pcm_lib_free_pages(substream);
++}
++
++/* Prepare FTSSP010 AHBDMA for playback & capture */
++static int snd_ftssp_pcm_prepare(struct snd_pcm_substream *substream)
++{
++ ftssp_chip *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ //printk("~~~~~ : snd_ftssp_pcm_prepare() is invoked....\n");
++ //printk("@@@@@ >>>>> : snd_ftssp_pcm_prepare() is called.\n");
++
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *)runtime->private_data;
++
++ int stream_id = substream->pstr->stream;
++ dmad_chreq *dma_chreq;
++ unsigned period_size, buffer_size;
++
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
++ dma_chreq = &dma_chreq_tx;
++ else
++ dma_chreq = &dma_chreq_rx;
++
++ period_size = frames_to_bytes(runtime, runtime->period_size);
++ buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
++
++ if (runtime->format != SNDRV_PCM_FORMAT_S16_LE)
++ return -ENODEV;
++
++ if (ac97) {
++ switch (runtime->rate) {
++ case 8000:
++ period_size *= 12;
++ buffer_size *= 12;
++ break;
++ case 16000:
++ period_size *= 6;
++ buffer_size *= 6;
++ break;
++ case 48000:
++ default:
++ period_size *= 2;
++ buffer_size *= 2;
++ break;
++ }
++
++ ftssp010_substream->dma_width = 4;
++ } else {
++ ftssp010_substream->dma_width = 2;
++ }
++
++ dmad_drain_requests(dma_chreq, 1);
++
++ dma_chreq->ring_base = (dma_addr_t)runtime->dma_addr;
++ dma_chreq->periods = (dma_addr_t)runtime->periods;
++ if (ac97) {
++ dma_chreq->period_size = (dma_addr_t)(period_size >> 2);
++ dma_chreq->ring_size = (dma_addr_t)(buffer_size >> 2);
++ } else {
++ dma_chreq->period_size = (dma_addr_t)(period_size >> 1);
++ dma_chreq->ring_size = (dma_addr_t)(buffer_size >> 1);
++ }
++ dmad_update_ring(dma_chreq);
++
++ /* Set PMU, FTSSP010, and DMA */
++ spin_lock(&ftssp010_substream->dma_lock);
++
++ /* keep DMA buffer VA for copy() callback */
++ // todo: support playback/capture simultaneously
++ ftssp010_substream->dma_area_va = (u32)runtime->dma_area;
++
++ if (ac97) {
++ ftssp010_substream->pmu_set_clocking(48000);
++ ftssp010_substream->hw_config(cardno,
++ runtime->channels > 1 ? 1 : 0, /* 1: stereo, 0: mono */
++ 48000, ftssp010_substream->dma_width);
++ } else {
++
++ ftssp010_substream->pmu_set_clocking(runtime->rate);
++ ftssp010_substream->hw_config(cardno,
++ runtime->channels > 1 ? 1 : 0, /* 1: stereo, 0: mono */
++ runtime->rate, ftssp010_substream->dma_width);
++ }
++
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
++ ftssp010_substream->tx_period = 0;
++ chip->substream_tx = substream;
++ } else {
++ ftssp010_substream->rx_period = 0;
++ chip->substream_rx = substream;
++ }
++
++ spin_unlock(&ftssp010_substream->dma_lock);
++
++ VVDBG("%s <<\n", __func__);
++
++ return 0;
++}
++
++static inline int snd_ftssp_start_play(ftssp_substream *ftssp010_substream,
++ struct snd_pcm_runtime *runtime)
++{
++ int err = 0;
++
++ //printk("~~~~~ : snd_ftssp_start_play() is invoked....\n");
++
++ if (ac97) {
++ /* in ac97 mode, user data was fed to dma buffer through
++ * driver-provided copy callback */
++ err = dmad_kickoff_requests(&dma_chreq_tx);
++ if (err != 0) {
++ ERR("%s: failed to kickoff dma!\n", __func__);
++ return err;
++ }
++ } else {
++ /* in i2s mode, no indication to driver for user data length
++ * (except start threshold). For simplicity at start, just go
++ * ahead by one cycle */
++
++ u32 sw_ptr =
++ (u32)frames_to_bytes(runtime, runtime->buffer_size) >>1;
++
++ err = dmad_update_ring_sw_ptr(&dma_chreq_tx, sw_ptr, 0);
++ if (err != 0) {
++ ERR("%s: failed to update sw-pointer!\n", __func__);
++ return err;
++ }
++
++ err = dmad_kickoff_requests(&dma_chreq_tx);
++ if (err != 0) {
++ ERR("%s: failed to kickoff dma!\n", __func__);
++ return err;
++ }
++ }
++
++ ftssp010_substream->start(cardno, 1);
++
++ //ADD by river 2011.03.08
++ //i2s_alc5630_write(0x02, 0x0000, g_i2c_client);
++ //i2s_alc5630_write(0x04, 0x0000, g_i2c_client);
++ //i2s_alc5630_write(0x0c, 0x1010, g_i2c_client);
++ //i2s_alc5630_write(0x10, 0xff03, g_i2c_client);
++ //End ADD by river 2011.03.08
++
++ return 0;
++}
++
++static inline int snd_ftssp_start_record(ftssp_substream *ftssp010_substream,
++ struct snd_pcm_runtime *runtime)
++{
++ int err = 0;
++
++ //printk("~~~~~ : snd_ftssp_start_record() is invoked....\n");
++
++ u32 sw_ptr = (u32)frames_to_bytes(runtime, runtime->buffer_size);
++
++ if (ac97) {
++ switch (runtime->rate) {
++ case 8000:
++ sw_ptr = (sw_ptr * 3);
++ break;
++ case 16000:
++ sw_ptr = (sw_ptr * 3) >> 1;
++ break;
++ case 48000:
++ default:
++ sw_ptr = sw_ptr >> 1;
++ break;
++ }
++ } else {
++
++ //printk(">>>>>>>>>> : snd_ftssp_start_record() for recording....\n");
++ sw_ptr = sw_ptr >> 1;
++ }
++
++ err = dmad_update_ring_sw_ptr(&dma_chreq_rx, sw_ptr, 0);
++ if (err != 0) {
++ ERR("%s: failed to update sw-pointer!\n", __func__);
++ return err;
++ }
++
++ err = dmad_kickoff_requests(&dma_chreq_rx);
++ if (err != 0) {
++ ERR("%s: failed to kickoff dma!\n", __func__);
++ return err;
++ }
++
++ ftssp010_substream->start(cardno, 1);
++
++ return 0;
++}
++
++/* Triggers AHBDMA for playback & capture */
++static int snd_ftssp_pcm_trigger(struct snd_pcm_substream * substream, int cmd)
++{
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *)substream->runtime->private_data;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ int err = 0;
++ int stream_id = substream->pstr->stream;
++
++ //printk("~~~~~ : snd_ftssp_pcm_trigger() is invoked....\n");
++
++ /* note local interrupts are already disabled in the midlevel code */
++ spin_lock(&ftssp010_substream->dma_lock);
++
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++
++ VDBG("%s: SNDRV_PCM_TRIGGER_START state(0x%08x)\n",
++ __func__, (u32)runtime->status->state);
++
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
++ err = snd_ftssp_start_play(ftssp010_substream, runtime);
++ } else {
++ err = snd_ftssp_start_record(ftssp010_substream,
++ runtime);
++ }
++ break;
++
++ case SNDRV_PCM_TRIGGER_STOP:
++
++ VDBG("%s: SNDRV_PCM_TRIGGER_STOP state(0x%08x)\n",
++ __func__, (u32)substream->runtime->status->state);
++
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
++ ftssp010_stop_tx(cardno);
++ dmad_drain_requests(&dma_chreq_tx, 1);
++ } else {
++ ftssp010_stop_rx(cardno);
++ dmad_drain_requests(&dma_chreq_rx, 1);
++ }
++ break;
++ default:
++ err = -EINVAL;
++ break;
++ }
++
++ spin_unlock(&ftssp010_substream->dma_lock);
++ return err;
++}
++
++// pcm middle-layer call this function within irq (snd_pcm_period_elapsed) or
++// with local irq disabled (snd_pcm_lib_write1)
++static snd_pcm_uframes_t snd_ftssp_pcm_pointer(
++ struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ u32 hw_ptr;
++ snd_pcm_uframes_t ret;
++ int stream_id = substream->pstr->stream;
++
++ //printk("~~~~~ : snd_ftssp_pcm_pointer() is invoked....\n");
++
++
++ /* Fetch DMA pointer, with spin lock */
++ //spin_lock_irqsave(&ftssp010_substream->dma_lock, flags);
++
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
++ hw_ptr = dmad_probe_ring_hw_ptr(&dma_chreq_tx);
++ } else {
++ hw_ptr = dmad_probe_ring_hw_ptr(&dma_chreq_rx);
++ }
++
++ //spin_unlock_irqrestore(&ftssp010_substream->dma_lock, flags);
++
++ if (ac97) {
++ ret = bytes_to_frames(runtime, hw_ptr << 1);
++
++ switch (runtime->rate) {
++ case 8000:
++ ret = ret / 6;
++ break;
++ case 16000:
++ ret = ret / 3;
++ break;
++ case 48000:
++ default:
++ break;
++ }
++ } else {
++ ret = bytes_to_frames(runtime, hw_ptr << 1);
++ }
++
++
++ VVDBG("%s: hw_ptr(0x%08x) ret(0x%08x)\n",
++ (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ? "p" : "c",
++ (u32)hw_ptr, (u32)ret);
++
++ /* ALSA requires return value 0 <= ret < buffer_size */
++ if (ret >= runtime->buffer_size)
++ return 0;
++ return ret;
++}
++
++/* For FTSSP010 driver, operations are shared among playback & capture */
++static struct snd_pcm_ops snd_ftssp_playback_ops = {
++ .open = snd_ftssp_pcm_open,
++ .close = snd_ftssp_pcm_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_ftssp_pcm_hw_params,
++ .hw_free = snd_ftssp_pcm_hw_free,
++ .prepare = snd_ftssp_pcm_prepare,
++ .trigger = snd_ftssp_pcm_trigger,
++ .pointer = snd_ftssp_pcm_pointer,
++ .copy = NULL,
++};
++
++static struct snd_pcm_ops snd_ftssp_capture_ops = {
++ .open = snd_ftssp_pcm_open,
++ .close = snd_ftssp_pcm_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_ftssp_pcm_hw_params,
++ .hw_free = snd_ftssp_pcm_hw_free,
++ .prepare = snd_ftssp_pcm_prepare,
++ .trigger = snd_ftssp_pcm_trigger,
++ .pointer = snd_ftssp_pcm_pointer,
++ .copy = NULL,
++};
++
++/* ALSA PCM constructor */
++static int snd_ftssp_new_pcm(ftssp_chip *chip)
++{
++ struct snd_pcm *pcm;
++ int err;
++
++ //printk("~~~~~ : snd_ftssp_new_pcm() is invoked....\n");
++
++ /* PCM device #0 with 1 playback and 1 capture */
++ if ((err = snd_pcm_new(chip->card, "ftssp_pcm", 0, 1, 1, &pcm)) < 0)
++ return err;
++
++ pcm->private_data = chip;
++ strcpy(pcm->name, "ftssp_pcm device");
++ chip->pcm = pcm;
++
++ /* set operators for playback and capture*/
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
++ &snd_ftssp_playback_ops);
++
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
++ &snd_ftssp_capture_ops);
++
++ /* Pre-allocate buffer, as suggested by ALSA driver document */
++ // todo: support playback/capture simultaneously
++ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++ NULL, FTSSP_HW_DMA_SIZE, FTSSP_HW_DMA_SIZE);
++
++ /* Force half-duplex (on A320D, or AC97 mode) */
++ if (ac97)
++ pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
++
++ return 0;
++}
++
++#if (FTSSP_PROC_FS)
++static void snd_ftssp_buf_max_read(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ snd_iprintf(buffer, "%d\n", snd_ftssp_pcm_hw.buffer_bytes_max);
++}
++
++static void snd_ftssp_buf_max_write(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ char tmp[128];
++ char *ptr_e;
++ u32 val;
++
++ if (buffer->size == 0)
++ return;
++
++ memset(tmp, 0, 128);
++ snd_info_get_str(tmp, buffer->buffer, 127);
++
++ val = simple_strtoul(tmp, &ptr_e, 10);
++ if (*ptr_e == 'k')
++ val *= 1024;
++ else if (*ptr_e == 'm')
++ val *= 1024 * 1024;
++
++ if (ac97) {
++ if (val > AC97_HW_BUFFER_BYTES_MAX)
++ val = AC97_HW_BUFFER_BYTES_MAX;
++ } else {
++ if (val > I2S_HW_BUFFER_BYTES_MAX)
++ val = I2S_HW_BUFFER_BYTES_MAX;
++ }
++
++ snd_ftssp_pcm_hw.buffer_bytes_max = (size_t)val;
++}
++
++static void snd_ftssp_period_min_read(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ snd_iprintf(buffer, "%d\n", snd_ftssp_pcm_hw.period_bytes_min);
++}
++
++static void snd_ftssp_period_min_write(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ char tmp[128];
++ char *ptr_e;
++ u32 val;
++
++ if (buffer->size == 0)
++ return;
++
++ memset(tmp, 0, 128);
++ snd_info_get_str(tmp, buffer->buffer, 127);
++
++ val = simple_strtoul(tmp, &ptr_e, 10);
++ if (*ptr_e == 'k')
++ val *= 1024;
++ else if (*ptr_e == 'm')
++ val *= 1024 * 1024;
++
++ snd_ftssp_pcm_hw.period_bytes_min = (size_t)val;
++
++ if ((val * snd_ftssp_pcm_hw.periods_max) >
++ snd_ftssp_pcm_hw.buffer_bytes_max) {
++ INFO("\nWarning: period_bytes(%d) * periods(%d) exceeds "
++ "hw_buffer_size(%d).\n",
++ snd_ftssp_pcm_hw.period_bytes_min,
++ snd_ftssp_pcm_hw.periods_max,
++ snd_ftssp_pcm_hw.buffer_bytes_max);
++ INFO(" Unexpected access violation may occur!\n");
++ }
++}
++
++static void snd_ftssp_period_max_read(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ snd_iprintf(buffer, "%d\n", snd_ftssp_pcm_hw.period_bytes_max);
++}
++
++static void snd_ftssp_period_max_write(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ char tmp[128];
++ char *ptr_e;
++ u32 val;
++
++ if (buffer->size == 0)
++ return;
++
++ memset(tmp, 0, 128);
++ snd_info_get_str(tmp, buffer->buffer, 127);
++
++ val = simple_strtoul(tmp, &ptr_e, 10);
++ if (*ptr_e == 'k')
++ val *= 1024;
++ else if (*ptr_e == 'm')
++ val *= 1024 * 1024;
++
++ snd_ftssp_pcm_hw.period_bytes_max = (size_t)val;
++
++ if ((val * snd_ftssp_pcm_hw.periods_max) >
++ snd_ftssp_pcm_hw.buffer_bytes_max) {
++ INFO("\nWarning: period_bytes(%d) * periods(%d) exceeds "
++ "hw_buffer_size(%d).\n",
++ snd_ftssp_pcm_hw.period_bytes_max,
++ snd_ftssp_pcm_hw.periods_max,
++ snd_ftssp_pcm_hw.buffer_bytes_max);
++ INFO(" Unexpected access violation may occur!\n");
++ }
++}
++
++static void snd_ftssp_periods_min_read(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ snd_iprintf(buffer, "%d\n", snd_ftssp_pcm_hw.periods_min);
++}
++
++static void snd_ftssp_periods_min_write(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ char tmp[128];
++ char *ptr_e;
++ u32 val;
++
++ if (buffer->size == 0)
++ return;
++
++ memset(tmp, 0, 128);
++ snd_info_get_str(tmp, buffer->buffer, 127);
++
++ val = simple_strtoul(tmp, &ptr_e, 10);
++ if (*ptr_e == 'k')
++ val *= 1024;
++ else if (*ptr_e == 'm')
++ val *= 1024 * 1024;
++
++ snd_ftssp_pcm_hw.periods_min = (size_t)val;
++
++ if ((val * snd_ftssp_pcm_hw.period_bytes_max) >
++ snd_ftssp_pcm_hw.buffer_bytes_max) {
++ INFO("\nWarning: period_bytes(%d) * periods(%d) exceeds "
++ "hw_buffer_size(%d).\n",
++ snd_ftssp_pcm_hw.period_bytes_max,
++ snd_ftssp_pcm_hw.periods_min,
++ snd_ftssp_pcm_hw.buffer_bytes_max);
++ INFO(" Unexpected access violation may occur!\n");
++ }
++}
++
++static void snd_ftssp_periods_max_read(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ snd_iprintf(buffer, "%d\n", snd_ftssp_pcm_hw.periods_max);
++}
++
++static void snd_ftssp_periods_max_write(struct snd_info_entry *entry,
++ struct snd_info_buffer *buffer)
++{
++ char tmp[128];
++ char *ptr_e;
++ u32 val;
++
++ if (buffer->size == 0)
++ return;
++
++ memset(tmp, 0, 128);
++ snd_info_get_str(tmp, buffer->buffer, 127);
++
++ val = simple_strtoul(tmp, &ptr_e, 10);
++ if (*ptr_e == 'k')
++ val *= 1024;
++ else if (*ptr_e == 'm')
++ val *= 1024 * 1024;
++
++ snd_ftssp_pcm_hw.periods_max = (size_t)val;
++
++ if ((val * snd_ftssp_pcm_hw.period_bytes_max) >
++ snd_ftssp_pcm_hw.buffer_bytes_max) {
++ INFO("\nWarning: period_bytes(%d) * periods(%d) exceeds "
++ "hw_buffer_size(%d).\n",
++ snd_ftssp_pcm_hw.period_bytes_max,
++ snd_ftssp_pcm_hw.periods_max,
++ snd_ftssp_pcm_hw.buffer_bytes_max);
++ INFO(" Unexpected access violation may occur!\n");
++ }
++}
++#endif //FTSSP_PROC_FS
++
++static inline void ftssp_ac97_init(void)
++{
++ //driver_name = AC97_DRIVER_NAME;
++ //codec_info = AC97_CODEC_NAME;
++
++ /* Change codec-dependent callbacks to AC97 */
++ ftssp010_substreams[0].pmu_set_clocking = pmu_set_ac97_clocking;
++ ftssp010_substreams[0].hw_config = ftssp010_config_ac97_play;
++ ftssp010_substreams[1].pmu_set_clocking = pmu_set_ac97_clocking;
++ ftssp010_substreams[1].hw_config = ftssp010_config_ac97_rec;
++
++ snd_ftssp_playback_ops.copy = snd_ftssp_playback_copy;
++ snd_ftssp_capture_ops.copy = snd_ftssp_capture_copy;
++
++ snd_ftssp_pcm_hw.rates = AC97_CODEC_SAMPLE_RATES;
++ snd_ftssp_pcm_hw.rate_min = AC97_CODEC_SAMPLE_RATE_MIN;
++ snd_ftssp_pcm_hw.rate_max = AC97_CODEC_SAMPLE_RATE_MAX;
++ snd_ftssp_pcm_hw.formats = AC97_CODEC_FORMATS;
++ snd_ftssp_pcm_hw.buffer_bytes_max = AC97_HW_BUFFER_BYTES_MAX;
++ snd_ftssp_pcm_hw.period_bytes_min = AC97_HW_PERIOD_BYTES_MIN;
++ snd_ftssp_pcm_hw.period_bytes_max = AC97_HW_PERIOD_BYTES_MAX;
++ snd_ftssp_pcm_hw.periods_min = AC97_HW_PERIODS_MIN;
++ snd_ftssp_pcm_hw.periods_max = AC97_HW_PERIODS_MAX;
++}
++
++static int ftssp_alsa_init(struct i2c_client *client)
++{
++ ftssp_chip *chip;
++ int err;
++
++ //ADD by river 2011.03.08
++ //g_i2c_client = client;
++ //End ADD by river 2011.03.08
++ //printk(">>>>>>>>> (4) ftssp_alsa_init().\n");
++ init_hw(cardno, ac97, client);
++
++ if (ac97)
++ ftssp_ac97_init();
++
++ DBG("%s: FTSSP010 #%d (Physical Addr=0x%08X), mode: %s\n",
++ __func__,
++ cardno, SSP_FTSSP010_pa_base[cardno],
++ ac97 ? "ac97" : "i2s");
++
++ err = snd_card_create(cardno, FTSSP_CARD_ID, THIS_MODULE,
++ sizeof(ftssp_chip), &ftssp_cards[cardno]);
++ if (err < 0)
++ return err;
++
++ if (ac97) {
++ sprintf(ftssp_cards[cardno]->driver, FTSSP_DRIVER_NAME);
++ sprintf(ftssp_cards[cardno]->shortname,
++ FTSSP_DRIVER_NAME "_ac97");
++ sprintf(ftssp_cards[cardno]->longname,
++ FTSSP_DRIVER_NAME "_ac97 controller");
++ } else {
++ sprintf(ftssp_cards[cardno]->driver, FTSSP_DRIVER_NAME);
++ sprintf(ftssp_cards[cardno]->shortname,
++ FTSSP_DRIVER_NAME "_i2s");
++ sprintf(ftssp_cards[cardno]->longname,
++ FTSSP_DRIVER_NAME "_i2s controller");
++ }
++
++ // PCM
++ chip = (ftssp_chip *)(ftssp_cards[cardno]->private_data);
++ chip->card = ftssp_cards[cardno];
++
++ if ((err = snd_ftssp_new_pcm(chip))) {
++ ERR("%s, Can't new PCM devices\n",__func__);
++ return -ENODEV;
++ }
++
++#if (FTSSP_PROC_FS)
++ // new a proc entries subordinate to card->proc_root for debugging
++ // /proc/card#/buf_max
++ snd_card_proc_new(chip->card, "buf_max", &chip->info_buf_max);
++ if (chip->info_buf_max) {
++ chip->info_buf_max->c.text.read = snd_ftssp_buf_max_read;
++ chip->info_buf_max->c.text.write = snd_ftssp_buf_max_write;
++ }
++ // /proc/card#/period_min
++ snd_card_proc_new(chip->card, "period_size_min",
++ &chip->info_period_min);
++ if (chip->info_period_min) {
++ chip->info_period_min->c.text.read = snd_ftssp_period_min_read;
++ chip->info_period_min->c.text.write =
++ snd_ftssp_period_min_write;
++ }
++ // /proc/card#/period_max
++ snd_card_proc_new(chip->card, "period_size_max",
++ &chip->info_period_max);
++ if (chip->info_period_max) {
++ chip->info_period_max->c.text.read = snd_ftssp_period_max_read;
++ chip->info_period_max->c.text.write =
++ snd_ftssp_period_max_write;
++ }
++ // /proc/card#/periods_min
++ snd_card_proc_new(chip->card, "periods_min", &chip->info_periods_min);
++ if (chip->info_periods_min) {
++ chip->info_periods_min->c.text.read =
++ snd_ftssp_periods_min_read;
++ chip->info_periods_min->c.text.write =
++ snd_ftssp_periods_min_write;
++ }
++ // /proc/card#/periods_max
++ snd_card_proc_new(chip->card, "periods_max", &chip->info_periods_max);
++ if (chip->info_periods_max) {
++ chip->info_periods_max->c.text.read =
++ snd_ftssp_periods_max_read;
++ chip->info_periods_max->c.text.write =
++ snd_ftssp_periods_max_write;
++ }
++#endif
++
++ // Register the card to ALSA
++ if ((err = snd_card_register(chip->card)) == 0) {
++ INFO("%s card registered!\n", FTSSP_CARD_ID);
++ }
++
++ return 0;
++}
++
++#ifdef CONFIG_SND_FTSSP010_I2S
++//ADD by river 2011.01.26
++static int alc5630_i2c_remove(struct i2c_client *client)
++{
++ struct alc5630_data *alc5630 = i2c_get_clientdata(client);
++
++ // power down codec chip
++ //tas_write_reg(tas, TAS_REG_ACR, 1, &tmp);
++
++ mutex_destroy(&alc5630->mtx);
++ kfree(alc5630);
++ return 0;
++}
++
++static const struct i2c_device_id alc5630_i2c_id[] = {
++ { "alc5630_codec", 0 },
++ { }
++};
++
++// This is the driver that will be inserted
++static struct i2c_driver alc5630_driver = {
++ .driver = {
++ .name = "alc5630_codec",
++ .owner = THIS_MODULE,
++ },
++ .attach_adapter = alc5630_i2c_attach,
++ .probe = alc5630_i2c_probe,
++ .remove = alc5630_i2c_remove,
++ .suspend = alc5630_i2c_suspend,
++ .resume = alc5630_i2c_resume,
++ .id_table = alc5630_i2c_id,
++};
++
++static int alc5630_i2c_suspend(struct i2c_client *i2c_client, pm_message_t mesg)
++{
++ //printk("@@@@@ TRACE by river 2011.05.10 : alc5630_i2c_suspend() is invoked.\n");
++
++ //i2c_del_driver(&alc5630_driver);
++ //#ifndef CONFIG_SND_FTSSP010_AC97
++ // i2c_del_driver(&alc5630_driver);
++ //#endif
++ //printk("@@@@@ TRACE by river 2011.05.10 : alc5630_i2c_suspend() -2 is invoked.\n");
++ dmad_channel_free(&dma_chreq_tx);
++ dmad_channel_free(&dma_chreq_rx);
++ //printk("@@@@@ TRACE by river 2011.05.10 : alc5630_i2c_suspend() -3 is invoked.\n");
++ //snd_card_free(ftssp_cards[cardno]);
++
++ return 0;
++
++}
++
++static int alc5630_i2c_resume(struct i2c_client *i2c_client)
++{
++
++ //printk("@@@@@ TRACE by river 2011.05.10 : alc5630_i2c_resume() is invoked.\n");
++ //#ifdef CONFIG_SND_FTSSP010_AC97
++ // ftssp_alsa_init(NULL);
++ //#else
++ // return i2c_add_driver(&alc5630_driver);
++ //#endif
++
++ return 0;
++
++}
++#endif
++
++static __init int ftssp_alsa_i2c_i2s_init(void)
++{
++
++ //printk(">>>>>>>>>> (1) ftssp_alsa_i2c_i2s_init().\n");
++ //return i2c_add_driver(&alc5630_driver);
++ #ifdef CONFIG_SND_FTSSP010_AC97
++ return ftssp_alsa_init(NULL);
++ #else
++ return i2c_add_driver(&alc5630_driver);
++ #endif
++}
++//End ADD by river 2011.01.26
++
++static __exit void ftssp_alsa_i2c_i2s_exit(void)
++{
++ DBG("%s, cleaning up\n",__func__);
++
++ //i2c_del_driver(&alc5630_driver);
++ #ifndef CONFIG_SND_FTSSP010_AC97
++ i2c_del_driver(&alc5630_driver);
++ #endif
++
++ dmad_channel_free(&dma_chreq_tx);
++ dmad_channel_free(&dma_chreq_rx);
++
++ snd_card_free(ftssp_cards[cardno]);
++}
++
++/*static __exit void ftssp_alsa_exit(void)
++{
++ DBG("%s, cleaning up\n",__func__);
++
++ dmad_channel_free(&dma_chreq_tx);
++ dmad_channel_free(&dma_chreq_rx);
++
++ snd_card_free(ftssp_cards[cardno]);
++}*/
++
++//MOD by river 2011.01.26
++//module_init(ftssp_alsa_init);
++//module_exit(ftssp_alsa_exit);
++module_init(ftssp_alsa_i2c_i2s_init);
++module_exit(ftssp_alsa_i2c_i2s_exit);
++//End MOD by river 2011.01.26
+diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_HDA.c linux-3.4.110/sound/nds32/FTSSP010_HDA.c
+--- linux-3.4.110.orig/sound/nds32/FTSSP010_HDA.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/sound/nds32/FTSSP010_HDA.c 2016-04-07 10:20:51.062085666 +0200
+@@ -0,0 +1,745 @@
++/* FTSSP010 - UDA1345TS module:
++ *
++ * $log$
++ *
++ * 2006/02/23: I-Jui Sung: OSS emulation half-duplex
++ * playback/capture at 48K, 44.1K, 8K
++ * with mono/stereo 16bit/8bit
++ *
++ * 2006/02/22: I-Jui Sung: OSS emulation playback at 44.1KHz
++ * 16-bit mono completed. Relying ALSA to
++ * resample
++ * 2009/02/24: dma upgrade checking list:
++ * - ac97 mode playback ................. ok
++ * - ac97 mode capture .................. ok
++ * - i2s mode playback .................. ok
++ * - i2s mode capture ................... ok
++ * - mixer support (snd_ctl_add, ...) ... todo
++ * - debug /proc entry .................. ok
++ */
++
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <asm/io.h>
++#include <linux/delay.h>
++#include <asm/spec.h>
++#include <asm/dmad.h>
++#include <linux/dma-mapping.h>
++#include <sound/core.h>
++#include <sound/pcm.h>
++#include <sound/initval.h>
++#include <sound/asound.h>
++#include <sound/control.h>
++#include "FTSSP010_HDA.h"
++void init_hw(unsigned int cardno);
++
++#if (!defined(CONFIG_PLATFORM_AHBDMA) && !defined(CONFIG_PLATFORM_APBDMA))
++#warning needs ahb/apb dma to wrok
++#endif
++
++/* ---------------------------------------------------------------------------
++ * Define the debug level of FTSSP_DEBUG
++ */
++#define FTSSP_DEBUG 0
++#define FTSSP_DEBUG_VERBOSE 0
++#define FTSSP_PROC_FS 1
++
++#undef VVDBG
++#if (FTSSP_DEBUG_VERBOSE)
++//#define VVDBG(vvar...) (void)0
++#define VVDBG(vvar...) printk(KERN_INFO vvar)
++#else
++#define VVDBG(vvar...) (void)0
++#endif
++
++#undef ERR
++#define ERR(vvar...) printk(KERN_ERR vvar)
++
++#undef INFO
++#define INFO(vvar...) printk(KERN_INFO vvar)
++
++#if (FTSSP_DEBUG)
++#undef DBG
++#define DBG(vvar...) printk(KERN_INFO vvar)
++#else
++#define DBG(vvar...) (void)0
++#endif
++
++#if (FTSSP_DEBUG_VERBOSE)
++#undef VDBG
++#define VDBG(vvar...) printk(KERN_INFO vvar)
++#else
++#define VDBG(vvar...) (void)0
++#endif
++
++/* ---------------------------------------------------------------------------
++ * Preserved size of memory space for audio DMA ring
++ */
++#define FTSSP_HW_DMA_SIZE (512 * 1024)
++
++
++/* HDA HW configuration*/
++/* ring size, exported to application */
++#define HDA_HW_BUFFER_BYTES_MAX (256 * 1024)
++#define HDA_HW_PERIOD_BYTES_MIN (2 * 1024)
++#define HDA_HW_PERIOD_BYTES_MAX (32 * 1024)
++#define HDA_HW_PERIODS_MIN 3
++#define HDA_HW_PERIODS_MAX 8
++
++#define HDA_HW_DMA_SIZE (HDA_HW_BUFFER_BYTES_MAX)
++
++
++/* ---------------------------------------------------------------------------
++ * Audio formats
++ */
++
++/* HDA formats */
++#define HDA_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
++#define HDA_CODEC_SAMPLE_RATES (SNDRV_PCM_RATE_192000 | \
++ SNDRV_PCM_RATE_176400| \
++ SNDRV_PCM_RATE_96000 | \
++ SNDRV_PCM_RATE_88200 | \
++ SNDRV_PCM_RATE_48000 | \
++ SNDRV_PCM_RATE_44100 | \
++ SNDRV_PCM_RATE_32000 | \
++ SNDRV_PCM_RATE_22050 | \
++ SNDRV_PCM_RATE_16000 | \
++ SNDRV_PCM_RATE_11025 | \
++ SNDRV_PCM_RATE_8000)
++#define HDA_CODEC_SAMPLE_RATE_MIN (8000)
++#define HDA_CODEC_SAMPLE_RATE_MAX (192000)
++
++/* ---------------------------------------------------------------------------
++ * Configuration
++ */
++#if (CONFIG_PROC_FS == 0)
++#undef FTSSP_PROC_FS
++#define FTSSP_PROC_FS 0
++#else
++#if (FTSSP_PROC_FS)
++#include <sound/info.h>
++#endif /* FTSSP_PROC_FS */
++#endif /* CONFIG_PROC_FS */
++
++#define FTSSP_CARD_ID "ftssp010"
++#define FTSSP_DRIVER_NAME "ftssp"
++
++MODULE_LICENSE("Faraday License");
++MODULE_AUTHOR("Faraday Technology Corp.");
++MODULE_DESCRIPTION("FTSSP010 Linux 2.6 Driver");
++
++static int cardno = 0;
++static const unsigned int SSP_FTSSP010_pa_base[SSP_FTSSP010_IRQ_COUNT] =
++ { SSP_FTSSP010_PA_BASE };
++
++/* Driver mode */
++
++// ----------------------------------------------
++module_param(cardno, int, 0);
++MODULE_PARM_DESC(cardno, "FTSSP No.");
++
++// ----------------------------------------------
++
++/* ---------------------------------------------------------------------------
++ * Structures
++ */
++
++/* private data for card */
++typedef struct {
++ struct snd_card *card;
++ struct snd_pcm *pcm;
++ struct snd_pcm_substream *substream_tx;
++ struct snd_pcm_substream *substream_rx;
++} ftssp_chip;
++
++/* dma request descriptors */
++dmad_chreq dma_chreq_tx = {
++ .channel = -1,
++ .drq = NULL,
++};
++
++dmad_chreq dma_chreq_rx = {
++ .channel = -1,
++ .drq = NULL,
++};
++
++/* Holds ALSA card instance pointers */
++struct snd_card *ftssp_cards[SSP_FTSSP010_COUNT];
++
++/* snd_pcm_hardware */
++static struct snd_pcm_hardware snd_ftssp_pcm_hw =
++{
++ .info = SNDRV_PCM_INFO_INTERLEAVED,
++ .formats = HDA_CODEC_FORMATS,
++ .rates = HDA_CODEC_SAMPLE_RATES,
++ .rate_min = HDA_CODEC_SAMPLE_RATE_MIN,
++ .rate_max = HDA_CODEC_SAMPLE_RATE_MAX,
++ .channels_min = 1,
++ .channels_max = 2,
++ .buffer_bytes_max = HDA_HW_BUFFER_BYTES_MAX,
++ .period_bytes_min = HDA_HW_PERIOD_BYTES_MIN,
++ .period_bytes_max = HDA_HW_PERIOD_BYTES_MAX,
++ .periods_min = HDA_HW_PERIODS_MIN,
++ .periods_max = HDA_HW_PERIODS_MAX,
++};
++
++/* private data for a substream (playback or capture) */
++/* function pointer for set up AHBDMA for this substream */
++typedef void (*start_t)(int cardno, unsigned use_dma);
++typedef void (*ftssp010_config_t)(int cardno, unsigned is_stereo,
++ unsigned speed, int use8bit);
++
++typedef struct {
++ u32 busy;
++ spinlock_t dma_lock;
++ unsigned dma_area_va;
++ int dma_width;
++ unsigned int tx_period;
++ unsigned int rx_period;
++
++ start_t start;
++ ftssp010_config_t hw_config;
++} ftssp_substream;
++
++static ftssp_substream ftssp010_substreams[2] = {
++ /* Playback substream */
++ {
++ busy : 0,
++ hw_config : ftssp010_config_hda_play,
++ },
++ /* Capture substream */
++ {
++ busy : 0,
++ hw_config : ftssp010_config_hda_rec,
++ }
++};
++
++
++/**
++ * These dma callbacks are called in interrupt context.
++ * @data: pointer to the chip-wide structure.
++ * TODO: use stream-specifc data
++ */
++__attribute__((__unused__))
++static void ftssp_dma_callback_tx(int ch, u16 int_status, void *data)
++{
++ ftssp_chip *chip = (ftssp_chip *)data;
++ struct snd_pcm_runtime *runtime = chip->substream_tx->runtime;
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *)runtime->private_data;
++ u32 sw_ptr;
++ u32 tx_period = ftssp010_substream->tx_period + 1;
++
++ if (tx_period == runtime->periods)
++ sw_ptr = runtime->buffer_size;
++ else
++ sw_ptr = tx_period * runtime->period_size;
++
++ sw_ptr = (u32)frames_to_bytes(runtime, sw_ptr) >> 1;
++
++ if (dmad_update_ring_sw_ptr(&dma_chreq_tx, (u32)sw_ptr, 0)) {
++ ERR("%s: failed to update sw-pointer!\n", __func__);
++ }
++
++ ftssp010_substream->tx_period = tx_period % runtime->periods;
++ snd_pcm_period_elapsed(chip->substream_tx);
++}
++
++__attribute__((__unused__))
++static void ftssp_dma_callback_rx(int ch, u16 int_status, void *data)
++{
++ ftssp_chip *chip = (ftssp_chip *)data;
++ struct snd_pcm_runtime *runtime = chip->substream_rx->runtime;
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *)runtime->private_data;
++ u32 sw_ptr;
++ u32 rx_period = ftssp010_substream->rx_period + 1;
++
++ if (rx_period == runtime->periods)
++ sw_ptr = runtime->buffer_size;
++ else
++ sw_ptr = rx_period * runtime->period_size;
++ sw_ptr = (u32)frames_to_bytes(runtime, sw_ptr) >> 1;
++
++ if (dmad_update_ring_sw_ptr(&dma_chreq_rx, (u32)sw_ptr, 0) != 0) {
++ ERR("%s: failed to update sw-pointer!\n", __func__);
++ }
++
++ ftssp010_substream->rx_period = rx_period % runtime->periods;
++
++ snd_pcm_period_elapsed(chip->substream_rx);
++}
++
++static inline int snd_ftssp_dma_ch_alloc(struct snd_pcm_substream *substream)
++{
++ dmad_chreq *ch_req __attribute__((__unused__)) = 0;
++
++#ifdef CONFIG_PLATFORM_APBDMA
++
++ if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++ ch_req = &dma_chreq_tx;
++ ch_req->completion_cb = ftssp_dma_callback_tx;
++ ch_req->apb_req.tx_dir = DMAD_DIR_A0_TO_A1;
++ ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97TX;
++ } else {
++ ch_req = &dma_chreq_rx;
++ ch_req->completion_cb = ftssp_dma_callback_rx;
++ ch_req->apb_req.tx_dir = DMAD_DIR_A1_TO_A0;
++ ch_req->apb_req.dev_reqn = APBBR_REQN_I2SAC97RX;
++ }
++
++ ch_req->controller = DMAD_DMAC_APB_CORE;
++ ch_req->flags = DMAD_FLAGS_RING_MODE;
++ ch_req->ring_base = 0;
++ ch_req->dev_addr = (dma_addr_t)FTSSP010_DATA_PA(cardno);
++ ch_req->periods = 0;
++ ch_req->period_size = 0;
++
++ ch_req->apb_req.ring_ctrl = APBBR_ADDRINC_I2X;
++ ch_req->apb_req.ring_reqn = APBBR_REQN_NONE;
++ ch_req->apb_req.dev_ctrl = APBBR_ADDRINC_FIXED;
++ ch_req->apb_req.burst_mode = 0;
++ ch_req->apb_req.data_width = APBBR_DATAWIDTH_2;
++ ch_req->completion_data = (void *)snd_pcm_substream_chip(substream);
++
++ ch_req->completion_data = (void *)snd_pcm_substream_chip(substream);
++
++ if (dmad_channel_alloc(ch_req) != 0) {
++ ERR("%s: APBDMA channel allocation failed\n",__func__);
++ goto _try_ahb;
++ }
++
++ DBG("%s: APBDMA channel allocated (ch: %d) ring_mode\n",
++ __func__, ch_req->channel);
++
++ return 0;
++
++_try_ahb:
++
++#endif /* CONFIG_PLATFORM_APBDMA */
++
++#ifdef CONFIG_PLATFORM_AHBDMA
++
++ if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) {
++ ch_req = &dma_chreq_tx;
++ ch_req->completion_cb = ftssp_dma_callback_tx;
++ ch_req->ahb_req.tx_dir = DMAD_DIR_A0_TO_A1;
++ ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97TX;
++ } else {
++ ch_req = &dma_chreq_rx;
++ ch_req->completion_cb = ftssp_dma_callback_rx;
++ ch_req->ahb_req.tx_dir = DMAD_DIR_A1_TO_A0;
++ ch_req->ahb_req.dev_reqn = DMAC_REQN_I2SAC97RX;
++ }
++
++ ch_req->controller = DMAD_DMAC_AHB_CORE;
++ ch_req->flags = DMAD_FLAGS_RING_MODE;
++ ch_req->ring_base = 0;
++ ch_req->dev_addr = (dma_addr_t)FTSSP010_DATA_PA(cardno);
++ ch_req->periods = 0;
++ ch_req->period_size = 0;
++
++ ch_req->ahb_req.sync = 1;
++ ch_req->ahb_req.priority = DMAC_CSR_CHPRI_2;
++ ch_req->ahb_req.hw_handshake = 1;
++ ch_req->ahb_req.burst_size = DMAC_CSR_SIZE_1;
++
++ ch_req->ahb_req.ring_width = DMAC_CSR_WIDTH_32;
++ ch_req->ahb_req.ring_ctrl = DMAC_CSR_AD_INC;
++ ch_req->ahb_req.ring_reqn = DMAC_REQN_NONE;
++ ch_req->ahb_req.dev_width = DMAC_CSR_WIDTH_32;
++ ch_req->ahb_req.dev_ctrl = DMAC_CSR_AD_FIX;
++
++ ch_req->completion_data = (void *)snd_pcm_substream_chip(substream);
++
++ if (dmad_channel_alloc(ch_req) != 0) {
++ ERR("%s: AHBDMA channel allocation failed\n", __func__);
++ goto _err_exit;
++ }
++
++ DBG("%s: AHBDMA channel allocated (ch: %d) ring_mode\n",
++ __func__, ch_req->channel);
++
++ return 0;
++
++_err_exit:
++
++#endif /* CONFIG_PLATFORM_AHBDMA */
++
++ return -ENODEV;
++}
++
++static inline ftssp_substream *ftssp010_substream_new(int stream_id)
++{
++ ftssp_substream *s = NULL;
++
++ switch (stream_id) {
++ case SNDRV_PCM_STREAM_PLAYBACK:
++ s = &ftssp010_substreams[0];
++ break;
++ case SNDRV_PCM_STREAM_CAPTURE:
++ s = &ftssp010_substreams[1];
++ break;
++ default:
++ ERR("%s: wrong stream type (%d)\n", __func__, stream_id);
++ return NULL;
++ }
++
++ if (s->busy) {
++ ERR("%s: device busy!\n", __func__);
++ return NULL;
++ }
++ s->busy = 1;
++
++ spin_lock_init(&s->dma_lock);
++
++ return s;
++}
++
++static int snd_ftssp_pcm_open(struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ int stream_id = substream->pstr->stream;
++
++ VDBG("%s, %s\n", __func__,
++ (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++ "playback" : "capture");
++
++ /* Both playback and capture share a hardware description */
++ runtime->hw = snd_ftssp_pcm_hw;
++
++ /* Allocate & Initialize stream-specific data */
++ runtime->private_data = ftssp010_substream_new(stream_id);
++
++ if (runtime->private_data)
++ return snd_ftssp_dma_ch_alloc(substream);
++ else
++ return -EBUSY;
++}
++
++static int snd_ftssp_pcm_close(struct snd_pcm_substream *substream)
++{
++ int stream_id = substream->pstr->stream;
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *)substream->runtime->private_data;
++
++ VDBG("%s, %s\n", __func__,
++ (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++ "playback" : "capture");
++
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
++ dmad_channel_free(&dma_chreq_tx);
++ else
++ dmad_channel_free(&dma_chreq_rx);
++
++ ftssp010_substream->busy = 0;
++ return 0;
++}
++
++static int snd_ftssp_pcm_hw_params(struct snd_pcm_substream *substream,
++ struct snd_pcm_hw_params *hw_params)
++{
++ VDBG("%s, %s\n", __func__,
++ (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++ "playback" : "capture");
++
++ return snd_pcm_lib_malloc_pages(substream, HDA_HW_DMA_SIZE);
++}
++
++static int snd_ftssp_pcm_hw_free(struct snd_pcm_substream *substream)
++{
++ VDBG("%s, %s\n", __func__,
++ (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
++ "playback" : "capture");
++
++ if (substream->pstr->stream == SNDRV_PCM_STREAM_PLAYBACK)
++ dmad_drain_requests(&dma_chreq_tx, 1);
++ else
++ dmad_drain_requests(&dma_chreq_rx, 1);
++
++ return snd_pcm_lib_free_pages(substream);
++}
++
++/* Prepare FTSSP010 AHBDMA for playback & capture */
++static int snd_ftssp_pcm_prepare(struct snd_pcm_substream *substream)
++{
++ ftssp_chip *chip = snd_pcm_substream_chip(substream);
++ struct snd_pcm_runtime *runtime = substream->runtime;
++
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *)runtime->private_data;
++
++ int stream_id = substream->pstr->stream;
++ dmad_chreq *dma_chreq;
++ unsigned period_size, buffer_size;
++ VVDBG("%s before spin_lock<<\n", __func__);
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK)
++ dma_chreq = &dma_chreq_tx;
++ else
++ dma_chreq = &dma_chreq_rx;
++
++ period_size = frames_to_bytes(runtime, runtime->period_size);
++ buffer_size = frames_to_bytes(runtime, runtime->buffer_size);
++
++ if (runtime->format != SNDRV_PCM_FORMAT_S16_LE)
++ return -ENODEV;
++
++ ftssp010_substream->dma_width = 4;
++
++ dmad_drain_requests(dma_chreq, 1);
++
++ dma_chreq->ring_base = (dma_addr_t)runtime->dma_addr;
++ dma_chreq->periods = (dma_addr_t)runtime->periods;
++ dma_chreq->period_size = (dma_addr_t)(period_size >> 1);
++ dma_chreq->ring_size = (dma_addr_t)(buffer_size >> 1);
++ dmad_update_ring(dma_chreq);
++
++ /* Set PMU, FTSSP010, and DMA */
++ spin_lock(&ftssp010_substream->dma_lock);
++
++ /* keep DMA buffer VA for copy() callback */
++ // todo: support playback/capture simultaneously
++ ftssp010_substream->dma_area_va = (u32)runtime->dma_area;
++ VVDBG("%s before hw_config<<\n", __func__);
++ ftssp010_substream->hw_config(cardno,
++ runtime->channels > 1 ? 1 : 0, /* 1: stereo, 0: mono */
++ runtime->rate, ftssp010_substream->dma_width);
++ VVDBG("%s after hw_config<<\n", __func__);
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
++ ftssp010_substream->tx_period = 0;
++ chip->substream_tx = substream;
++ } else {
++ ftssp010_substream->rx_period = 0;
++ chip->substream_rx = substream;
++ }
++
++ spin_unlock(&ftssp010_substream->dma_lock);
++ VVDBG("%s after spin_unlock <<\n", __func__);
++
++ return 0;
++}
++
++static inline int snd_ftssp_start_play(ftssp_substream *ftssp010_substream,
++ struct snd_pcm_runtime *runtime)
++{
++ int err = 0;
++ u32 sw_ptr =
++ (u32)frames_to_bytes(runtime, runtime->buffer_size) >> 1;
++
++ err = dmad_update_ring_sw_ptr(&dma_chreq_tx, sw_ptr, 0);
++ if (err != 0) {
++ ERR("%s: failed to update sw-pointer!\n", __func__);
++ return err;
++ }
++ err = dmad_kickoff_requests(&dma_chreq_tx);
++ if (err != 0) {
++ ERR("%s: failed to kickoff dma!\n", __func__);
++ return err;
++ }
++
++ return 0;
++}
++
++static inline int snd_ftssp_start_record(ftssp_substream *ftssp010_substream,
++ struct snd_pcm_runtime *runtime)
++{
++ int err = 0;
++ u32 sw_ptr = (u32)frames_to_bytes(runtime, runtime->buffer_size);
++
++ sw_ptr = sw_ptr >> 1;
++ printk(">>>>>>>>>> : snd_ftssp_start_record() for recording....\n");
++ err = dmad_update_ring_sw_ptr(&dma_chreq_rx, sw_ptr, 0);
++ if (err != 0) {
++ ERR("%s: failed to update sw-pointer!\n", __func__);
++ return err;
++ }
++
++ err = dmad_kickoff_requests(&dma_chreq_rx);
++ if (err != 0) {
++ ERR("%s: failed to kickoff dma!\n", __func__);
++ return err;
++ }
++
++
++ return 0;
++}
++
++/* Triggers AHBDMA for playback & capture */
++static int snd_ftssp_pcm_trigger(struct snd_pcm_substream * substream, int cmd)
++{
++ ftssp_substream *ftssp010_substream =
++ (ftssp_substream *)substream->runtime->private_data;
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ int err = 0;
++ int stream_id = substream->pstr->stream;
++
++ /* note local interrupts are already disabled in the midlevel code */
++ spin_lock(&ftssp010_substream->dma_lock);
++
++ switch (cmd) {
++ case SNDRV_PCM_TRIGGER_START:
++
++ VDBG("%s: SNDRV_PCM_TRIGGER_START state(0x%08x)\n",
++ __func__, (u32)runtime->status->state);
++
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
++ err = snd_ftssp_start_play(ftssp010_substream, runtime);
++ } else {
++ err = snd_ftssp_start_record(ftssp010_substream,
++ runtime);
++ }
++ break;
++
++ case SNDRV_PCM_TRIGGER_STOP:
++
++ VDBG("%s: SNDRV_PCM_TRIGGER_STOP state(0x%08x)\n",
++ __func__, (u32)substream->runtime->status->state);
++
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
++ ftssp010_stop_tx(cardno);
++ dmad_drain_requests(&dma_chreq_tx, 1);
++ } else {
++ ftssp010_stop_rx(cardno);
++ dmad_drain_requests(&dma_chreq_rx, 1);
++ }
++ break;
++ default:
++ err = -EINVAL;
++ break;
++ }
++
++ spin_unlock(&ftssp010_substream->dma_lock);
++ return err;
++}
++
++// pcm middle-layer call this function within irq (snd_pcm_period_elapsed) or
++// with local irq disabled (snd_pcm_lib_write1)
++static snd_pcm_uframes_t snd_ftssp_pcm_pointer(
++ struct snd_pcm_substream *substream)
++{
++ struct snd_pcm_runtime *runtime = substream->runtime;
++ u32 hw_ptr;
++ snd_pcm_uframes_t ret;
++ int stream_id = substream->pstr->stream;
++
++ /* Fetch DMA pointer, with spin lock */
++ //spin_lock_irqsave(&ftssp010_substream->dma_lock, flags);
++
++ if (stream_id == SNDRV_PCM_STREAM_PLAYBACK) {
++ hw_ptr = dmad_probe_ring_hw_ptr(&dma_chreq_tx);
++ } else {
++ hw_ptr = dmad_probe_ring_hw_ptr(&dma_chreq_rx);
++ }
++ ret = bytes_to_frames(runtime, hw_ptr << 1);
++ //spin_unlock_irqrestore(&ftssp010_substream->dma_lock, flags);
++ VVDBG("%s: hw_ptr(0x%08x) ret(0x%08x)\n",
++ (stream_id == SNDRV_PCM_STREAM_PLAYBACK) ? "p" : "c",
++ (u32)hw_ptr, (u32)ret);
++
++ /* ALSA requires return value 0 <= ret < buffer_size */
++ if (ret >= runtime->buffer_size)
++ return 0;
++ return ret;
++}
++
++/* For FTSSP010 driver, operations are shared among playback & capture */
++static struct snd_pcm_ops snd_ftssp_playback_ops = {
++ .open = snd_ftssp_pcm_open,
++ .close = snd_ftssp_pcm_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_ftssp_pcm_hw_params,
++ .hw_free = snd_ftssp_pcm_hw_free,
++ .prepare = snd_ftssp_pcm_prepare,
++ .trigger = snd_ftssp_pcm_trigger,
++ .pointer = snd_ftssp_pcm_pointer,
++ .copy = NULL,
++};
++
++static struct snd_pcm_ops snd_ftssp_capture_ops = {
++ .open = snd_ftssp_pcm_open,
++ .close = snd_ftssp_pcm_close,
++ .ioctl = snd_pcm_lib_ioctl,
++ .hw_params = snd_ftssp_pcm_hw_params,
++ .hw_free = snd_ftssp_pcm_hw_free,
++ .prepare = snd_ftssp_pcm_prepare,
++ .trigger = snd_ftssp_pcm_trigger,
++ .pointer = snd_ftssp_pcm_pointer,
++ .copy = NULL,
++};
++
++/* ALSA PCM constructor */
++static int snd_ftssp_new_pcm(ftssp_chip *chip)
++{
++ struct snd_pcm *pcm;
++ int err;
++
++ /* PCM device #0 with 1 playback and 1 capture */
++ if ((err = snd_pcm_new(chip->card, "ftssp_pcm", 0, 1, 1, &pcm)) < 0)
++ return err;
++
++ pcm->private_data = chip;
++ strcpy(pcm->name, "ftssp_pcm device");
++ chip->pcm = pcm;
++
++ /* set operators for playback and capture*/
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK,
++ &snd_ftssp_playback_ops);
++
++ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
++ &snd_ftssp_capture_ops);
++
++ /* Pre-allocate buffer, as suggested by ALSA driver document */
++ // todo: support playback/capture simultaneously
++ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
++ NULL, FTSSP_HW_DMA_SIZE, FTSSP_HW_DMA_SIZE);
++
++ return 0;
++}
++
++static __init int ftssp_alsa_init(void)
++{
++ ftssp_chip *chip;
++ int err;
++ init_hw(cardno);
++ INFO("After init_hw!\n");
++ err = snd_card_create(cardno, FTSSP_CARD_ID, THIS_MODULE,
++ sizeof(ftssp_chip), &ftssp_cards[cardno]);
++ INFO("After snd_card_create!\n");
++ if (err < 0)
++ return err;
++ sprintf(ftssp_cards[cardno]->driver, FTSSP_DRIVER_NAME);
++ sprintf(ftssp_cards[cardno]->shortname,
++ FTSSP_DRIVER_NAME "_HDA");
++ sprintf(ftssp_cards[cardno]->longname,
++ FTSSP_DRIVER_NAME "_HDA controller");
++ /* PCM */
++ chip = (ftssp_chip *)(ftssp_cards[cardno]->private_data);
++ chip->card = ftssp_cards[cardno];
++
++ if ((err = snd_ftssp_new_pcm(chip))) {
++ ERR("%s, Can't new PCM devices\n",__func__);
++ return -ENODEV;
++ }
++
++
++ /* Register the card to ALSA */
++ if ((err = snd_card_register(chip->card)) == 0) {
++ INFO("%s card registered!\n", FTSSP_CARD_ID);
++ }
++
++ return 0;
++}
++
++static __exit void ftssp_alsa_exit(void)
++{
++ DBG("%s, cleaning up\n",__func__);
++
++ dmad_channel_free(&dma_chreq_tx);
++ dmad_channel_free(&dma_chreq_rx);
++
++ snd_card_free(ftssp_cards[cardno]);
++}
++
++module_init(ftssp_alsa_init);
++module_exit(ftssp_alsa_exit);
+diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_HDA.h linux-3.4.110/sound/nds32/FTSSP010_HDA.h
+--- linux-3.4.110.orig/sound/nds32/FTSSP010_HDA.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/sound/nds32/FTSSP010_HDA.h 2016-04-07 10:20:51.062085666 +0200
+@@ -0,0 +1,34 @@
++/* FTSSP010 - HDA supporting library header */
++/*
++ *
++ * $log$
++ *
++ */
++#include <linux/init.h>
++#include <linux/module.h>
++#include <asm/io.h>
++#include <linux/delay.h>
++#include <asm/spec.h>
++#include <linux/dma-mapping.h>
++
++
++#define FTSSP010_DATA(x) (SSP_FTSSP010_va_base[(x)]+0x18)
++#define FTSSP010_DATA_PA(x) (SSP_FTSSP010_pa_base[(x)]+0x18)
++
++
++/* Returns FTSSP010 status */
++extern void ftssp010_set_int_control(int cardno, unsigned val);
++extern int ftssp010_get_status(int cardno);
++extern unsigned ftssp010_get_int_status(int cardno);
++/* Polls FIFO full register */
++extern int ftssp010_tx_fifo_not_full(int cardno);
++
++/* Configure FTSSP010 to a given sampling rate and channel number */
++extern void ftssp010_config_hda_play(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
++
++extern void ftssp010_config_hda_rec(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
++
++extern void ftssp010_stop_tx(int cardno);
++extern void ftssp010_stop_rx(int cardno);
++
++
+diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_HDA_lib.c linux-3.4.110/sound/nds32/FTSSP010_HDA_lib.c
+--- linux-3.4.110.orig/sound/nds32/FTSSP010_HDA_lib.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/sound/nds32/FTSSP010_HDA_lib.c 2016-04-07 10:20:51.062085666 +0200
+@@ -0,0 +1,477 @@
++/* FTSSP010 - UDA1345TS module
++ *
++ * $log$
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <asm/io.h>
++#include <linux/delay.h>
++#include <asm/spec.h>
++#include <asm/dmad.h>
++#include <linux/dma-mapping.h>
++#include "hda.h"
++
++#if 0
++MODULE_LICENSE("Faraday License");
++MODULE_AUTHOR("Faraday Technology Corp.");
++MODULE_DESCRIPTION("FTSSP010 - UDA1345TS Linux 2.6 Library");
++#endif
++#undef ERR
++#define ERR(vvar...) printk(KERN_ERR vvar)
++#define DBG(vvar...) printk(KERN_INFO vvar)
++
++#define SSP_TXFCLR 0x8
++#define SSP_RXFCLR 0x4
++#define SSP_RFIEN 0x4
++#define SSP_TFIEN 0x8
++#define SSP_SSPEN 0x1
++#define SSP_TXDOE 0x2
++#define SSP_RXDMAEN 0x10
++#define SSP_TXDMAEN 0x20
++#define SSP_RFURIEN 0x1
++#define SSP_TFURIEN 0x2
++#define HDA_STRNUM_RX 1
++#define HDA_STRNUM_TX 2
++#define HDA_CHANUM 0
++#define HDA_CRST_MASK 0x20
++/* Initialize FTSSP010 to output to UDA1345TS via I2S */
++#define FTSSP010_CONTROL0(x) (SSP_FTSSP010_va_base[(x)]+0x0)
++#define FTSSP010_CONTROL0_OPM_STEREO 0xC
++#define FTSSP010_CONTROL0_OPM_MONO 0x8
++
++#define FTSSP010_CONTROL1(x) (SSP_FTSSP010_va_base[(x)]+0x4)
++#define FTSSP010_CONTROL2(x) (SSP_FTSSP010_va_base[(x)]+0x8)
++
++#define FTSSP010_INT_CONTROL(x) (SSP_FTSSP010_va_base[(x)]+0x10)
++#define FTSSP010_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0xC)
++#define FTSSP010_INT_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0x14)
++#define FTSSP010_DATA(x) (SSP_FTSSP010_va_base[(x)]+0x18)
++#define FTSSP010_INFO(x) (SSP_FTSSP010_va_base[(x)]+0x1C)
++#define FTSSP010_AC_COMMAND(x) (SSP_FTSSP010_va_base[(x)]+0x28)
++#define FTSSP010_IRSPR(x) (SSP_FTSSP010_va_base[(x)]+0x2C)
++#define FTSSP010_ICMDST(x) (SSP_FTSSP010_va_base[(x)]+0x30)
++#define HDA_REG_OSDC(x) (SSP_FTSSP010_va_base[(x)]+0x50)
++#define HDA_REG_ISDC(x) (SSP_FTSSP010_va_base[(x)]+0x54)
++
++static const unsigned int SSP_FTSSP010_va_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_VA_BASE };
++static const unsigned int SSP_FTSSP010_pa_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_PA_BASE };
++
++void SetSSP_Enable(int cardno, int enable)
++{
++ volatile unsigned int ctrl = 0;
++
++ ctrl = inl(FTSSP010_CONTROL2(cardno));
++ if(enable)
++ ctrl |= SSP_SSPEN + SSP_TXDOE;
++ else
++ ctrl &= ~(SSP_SSPEN + SSP_TXDOE);
++
++ outl(ctrl, FTSSP010_CONTROL2(cardno));
++}
++void SetSSP_Enable_rx(int cardno, int enable)
++{
++ volatile unsigned int ctrl = 0;
++
++ ctrl = inl(FTSSP010_CONTROL2(cardno));
++ if(enable)
++ ctrl |= SSP_SSPEN ;
++ else
++ ctrl &= ~(SSP_SSPEN);
++
++ outl(ctrl, FTSSP010_CONTROL2(cardno));
++}
++
++void SetSSP_FIFO_Threshold(int cardno, unsigned int trans_len,unsigned int rec_len)
++{
++ volatile unsigned int ctrl = 0;
++ ctrl = inl(FTSSP010_INT_CONTROL(cardno));
++
++ ctrl &= ~0x0000FF00;
++ ctrl |= ((trans_len << 12) + (rec_len << 8)) & 0x0000FF00;
++
++ outl(ctrl, FTSSP010_INT_CONTROL(cardno));
++}
++void SetSSP_IntMask(int cardno,int Mask)
++{
++ volatile unsigned int ctrl = 0;
++ ctrl = inl(FTSSP010_INT_CONTROL(cardno));
++ ctrl &= ~0x3F;
++ ctrl |= Mask;
++ outw(ctrl, FTSSP010_INT_CONTROL(cardno));
++}
++void SetSSP_TXFIFO(int cardno, unsigned int threshold,unsigned int underrun)
++{
++ volatile unsigned int data = 0;
++
++ data = inl(FTSSP010_INT_CONTROL(cardno));
++
++ if (threshold)
++ data |= SSP_TFIEN;
++ else
++ data &= ~SSP_TFIEN; //Howard@2007-4-13
++
++ if (underrun)
++ data |= SSP_TFURIEN;
++ else
++ data &= ~SSP_TFURIEN; //Howard@2007-4-13
++
++ outl(data, FTSSP010_INT_CONTROL(cardno));
++}
++void SetSSP_RXFIFO(int cardno,unsigned int threshold,unsigned int underrun)
++{
++ volatile unsigned int data = 0;
++
++ data = inl(FTSSP010_INT_CONTROL(cardno));
++
++ if (threshold)
++ data |= SSP_RFIEN;
++ else
++ data &= ~SSP_RFIEN; //Howard@2007-4-13
++
++ if (underrun)
++ data |= SSP_RFURIEN;
++ else
++ data &= ~SSP_RFURIEN; //Howard@2007-4-13
++
++ outl(data, FTSSP010_INT_CONTROL(cardno));
++}
++void SetSSP_DMA(int cardno, unsigned int trans,unsigned int rec)
++{
++ volatile unsigned int data = 0;
++
++ data = inl(FTSSP010_INT_CONTROL(cardno));
++
++ if (trans)
++ data |= SSP_TXDMAEN;
++ else
++ data &= ~SSP_TXDMAEN;
++
++ if (rec)
++ data |= SSP_RXDMAEN;
++ else
++ data &= ~SSP_RXDMAEN;
++
++ outl(data, FTSSP010_INT_CONTROL(cardno));
++}
++void SSPClearTxFIFO(int cardno)
++{
++ volatile unsigned int data = 0;
++
++ data = inl(FTSSP010_CONTROL2(cardno));
++ data |= SSP_TXFCLR;
++ outl(data, FTSSP010_CONTROL2(cardno));
++}
++
++
++void SSPClearRxFIFO(int cardno)
++{
++ volatile unsigned int data = 0;
++
++ data = inl(FTSSP010_CONTROL2(cardno));
++ data |= SSP_RXFCLR;
++ outl(data, FTSSP010_CONTROL2(cardno));
++}
++
++void ftssp010_set_int_control(int cardno, unsigned val)
++{
++ outl(val, FTSSP010_INT_CONTROL(cardno));
++}
++
++unsigned ftssp010_get_int_status(int cardno)
++{
++ return (inl(FTSSP010_INT_STATUS(cardno)));
++}
++
++int ftssp010_get_status(int cardno)
++{
++ return (inl(FTSSP010_STATUS(cardno)));
++}
++
++int ftssp010_tx_fifo_not_full(int cardno)
++{
++ return (inl(FTSSP010_STATUS(cardno))&0x2)==0x2;
++}
++
++int ftssp010_tx_fifo_vaild_entries(int cardno)
++{
++ return (inl(FTSSP010_STATUS(cardno))>>12) & 0x1f;
++}
++
++/* Configure FTSSP010 to a given sampling rate and channel number
++ * for HDA mode in playback mode
++ */
++void init_hw(unsigned int cardno)
++{
++ /* Step 1: Set HDA Mode & HDA Format */
++ outl(HDA_MODE | 0x4000, FTSSP010_CONTROL0(cardno)); /* set FTSSP010 to HDA mode */
++ mdelay(50);
++ outl(HDA_CRST_CLR | (5 << HDA_RST_FCNT_OFS), FTSSP010_CONTROL2(cardno)); /* Cold Reset AC-Link */
++ mdelay(50);
++ while((inl(FTSSP010_CONTROL2(cardno)) & HDA_CRST_MASK) != HDA_CRST_CLR);
++ SetSSP_IntMask(cardno, 0);
++
++}
++void SSPClearFIFO(int cardno, unsigned int tx, unsigned int rx)
++{
++ unsigned int data;
++
++ if (tx == 1) {
++ //clear TX
++ data = inl(FTSSP010_CONTROL2(cardno));
++ //data = REG32(SSP_REG_CTRL2);
++ data |= SSP_TXFCLR;
++ outl(data, FTSSP010_CONTROL2(cardno));
++ //REG32(SSP_REG_CTRL2) = data;
++ }
++
++ if (rx == 1) {
++ //clear RX
++ data = inl(FTSSP010_CONTROL2(cardno));
++ //data = REG32(SSP_REG_CTRL2);
++ data |= SSP_RXFCLR;
++ //REG32(SSP_REG_CTRL2) = data;
++ outl(data, FTSSP010_CONTROL2(cardno));
++ }
++}
++void hda_cmd_rsp(int cardno, unsigned int node_num, unsigned int verb_num, unsigned int func_num)
++{
++ //unsigned int HDA_REG_ICMDST;
++ volatile unsigned int hda_cmd = HDA_COD_DEVADDR | (node_num << 20) | (verb_num << 8) | func_num;
++ //Wait CMD Bus Not Busy
++ while((inl(FTSSP010_ICMDST(cardno)) & HDA_ICB_MASK) != 0);
++ //Write CMD into ICW
++ outl(hda_cmd, FTSSP010_AC_COMMAND(cardno));
++ mdelay(50);
++ //Wait new resp is latched into IRR
++ while((inl(FTSSP010_ICMDST(cardno)) & HDA_IRV_MASK) == 0);
++ //Get Resp From IRR & Compare with Expected Resp
++ //clear IRV
++ outl(inl(FTSSP010_ICMDST(cardno)) | (1 << HDA_IRV_OFFSET), FTSSP010_ICMDST(cardno));
++ mdelay(50);
++}
++void hda_cmdrsp_proc(int cardno, unsigned int node_num, unsigned int issue_cmd, unsigned int expect_rsp)
++{
++ unsigned int hda_cmd = HDA_COD_DEVADDR | node_num | issue_cmd;
++ unsigned int HDA_REG_ICMDST;
++ //Wait CMD Bus Not Busy
++ while((inl(FTSSP010_ICMDST(cardno)) & HDA_ICB_MASK) != 0);
++
++ //Write CMD into ICW
++ //REG32(HDA_REG_ICMDW) = hda_cmd;
++ outl(hda_cmd, FTSSP010_AC_COMMAND(cardno));
++ mdelay(50);
++ //Wait new resp is latched into IRR
++ while((inl(FTSSP010_ICMDST(cardno)) & HDA_IRV_MASK) == 0);
++ //Get Resp From IRR & Compare with Expected Resp
++ if (inl(FTSSP010_IRSPR(cardno)) != expect_rsp) {
++ ERR("%s: unexpected rsp!",__func__);
++ }
++ else {
++ //clear IRV
++ outl(inl(FTSSP010_ICMDST(cardno)) | (1 << HDA_IRV_OFFSET), FTSSP010_ICMDST(cardno));
++ }
++}
++unsigned int hda_covfmt_setup(unsigned int type, unsigned int base, unsigned int mult, unsigned int div, unsigned int bits, unsigned int chnum)
++{
++ unsigned int hda_fmt = type << HDA_FMT_TYPE_OFS |
++ base << HDA_FMT_BASE_OFS |
++ mult << HDA_FMT_MULT_OFS |
++ div << HDA_FMT_DIV_OFS |
++ bits << HDA_FMT_BITS_OFS |
++ chnum << HDA_FMT_CHNUM_OFS;
++ return hda_fmt;
++}
++unsigned int hda_covstr_setup(unsigned int stream, unsigned int channel)
++{
++ unsigned int hda_str = stream << HDA_STR_STR_OFS |
++ channel << HDA_STR_CHA_OFS ;
++ return hda_str;
++}
++unsigned int hda_converter_setup(int cardno, unsigned int mode, unsigned int type, unsigned int base, unsigned mult, unsigned int div, unsigned int bits, unsigned int chnum, unsigned int stream, unsigned int channel)
++{
++ unsigned int hda_fmt = 0;
++ unsigned int hda_str = 0;
++ unsigned int exp_rsp = 0;
++ unsigned int node_num = 0;
++
++ if (mode == HDA_OUT_STR) {
++ node_num = HDA_OUTCOV_NODE;
++ }
++ else {
++ node_num = HDA_INCOV_NODE;
++ }
++ //a: Set Converter Format to Converter
++ hda_fmt = hda_covfmt_setup(type, base, mult, div, bits, chnum);
++ exp_rsp = HDA_RESP_ZERO_VAL;
++ hda_cmdrsp_proc(cardno, node_num, (HDA_CMD_SETCVTFMT | hda_fmt), exp_rsp);
++ //b: Get Converter Format from Converter
++ exp_rsp = hda_fmt;
++ hda_cmdrsp_proc(cardno, node_num, HDA_CMD_GETCVTFMT, exp_rsp);
++ //c: Set Converter Stream to Converter
++ hda_str = hda_covstr_setup(stream, channel);
++ exp_rsp = HDA_RESP_ZERO_VAL;
++ hda_cmdrsp_proc(cardno, node_num, (HDA_CMD_SETCVTSTR | hda_str), exp_rsp);
++ //d: Get Converter Stream from Converter
++ exp_rsp = hda_str;
++ hda_cmdrsp_proc(cardno, node_num, HDA_CMD_GETCVTSTR, exp_rsp);
++
++ return hda_fmt;
++}
++void hda_iosdc_setup(int cardno, unsigned int io_sel, unsigned int ctrl, unsigned int stream_num, unsigned int hda_fmt)
++{
++ unsigned int hda_reg_base = (io_sel == 1)? HDA_REG_OSDC(cardno) : HDA_REG_ISDC(cardno);
++ if (ctrl == 1) {//run
++ outl((stream_num << HDA_SDC_STNUM_OFFSET) | hda_fmt, hda_reg_base);
++ outl((inl(hda_reg_base) | (1 << HDA_SDC_SRUN_OFFSET)),hda_reg_base);
++ }
++
++}
++static void _ftssp010_config_hda(int cardno, unsigned is_stereo, unsigned speed, int is_rec)
++{
++ unsigned int hda_fmt = 0;
++ unsigned int div = 0,mult = 0, base = 0;
++ switch (speed) {
++ case 44100:
++ base = 1;
++ div = 0;
++ break;
++ case 48000:
++ div = 0;
++ break;
++ case 96000:
++ mult = 1;
++ break;
++ case 192000:
++ mult = 3;
++ break;
++ }
++
++ if (is_rec) { /* Recording */
++ /* ------------------------------------------------ */
++ /* Codec initialization */
++ /* ------------------------------------------------ */
++ /* Step 3: Codec Evaluation */
++ /* root_node -> node 1(Audio Func Group) */
++ /* -> node 2(Output Converter) */
++ /* -> node 3(Input Converter) */
++ /* ------------------------------------------------ */
++ //input
++ hda_cmd_rsp(cardno, 0x1a, 0x707, 0x20); //pin complex => input enable, port-c LINE1
++ hda_cmd_rsp(cardno, 0x08, 0x3f0, 0x3f);//pin amp => max LINE ADC amplifier gain
++ hda_cmd_rsp(cardno, 0x1a, 0x3f0, 0x00);//pin complex => no mute
++ hda_cmd_rsp(cardno, 0x23, 0x3f2, 0x3f);//pin complex => no mute
++ /* ------------------------------ */
++ /* Step 4: Output Converter Setup */
++ /* ------------------------------ */
++ /* Set Converter Format & Stream to Node 2(Output Converter) */
++ /* type = PCM, base = 48K, mult = xN, div = /M, bits = 8~32bits/sample, chnum = 1 */
++ /* stream = 1, lowest channel = 0 */
++
++ hda_fmt = hda_converter_setup(cardno, HDA_IN_STR, //MODE
++ 0, base, mult, div, 1, 1, //FORMAT
++ HDA_STRNUM_RX, HDA_CHANUM); //STREAM
++ /* ---------------------------- */
++ /* Step 5: Enable Output Stream */
++ /* ---------------------------- */
++ hda_iosdc_setup(cardno, HDA_IN_STR, HDA_STR_RUN, HDA_STRNUM_RX, hda_fmt);
++ SetSSP_Enable_rx(cardno, 1);
++ SetSSP_RXFIFO(cardno, 0, 0);
++ SetSSP_TXFIFO(cardno, 0, 0);
++ SetSSP_FIFO_Threshold(cardno,12,12);
++ SetSSP_DMA(cardno, 0, 1);
++
++ SSPClearTxFIFO(cardno);
++ SSPClearRxFIFO(cardno);
++
++ //SetSSP_Enable_rx(cardno, 0);
++
++ } else { /* Playback */
++ /* ------------------------------------------------ */
++ /* Codec initialization */
++ /* ------------------------------------------------ */
++ /* Step 3: Codec Evaluation */
++ /* root_node -> node 1(Audio Func Group) */
++ /* -> node 2(Output Converter) */
++ /* -> node 3(Input Converter) */
++ /* ------------------------------------------------ */
++ //DBG("%s before_cmd_rsp<<",__func__);
++ hda_cmd_rsp(cardno, 0x14, 0x707, 0x40);//pin complex => output
++ //DBG("%s after hda_cmd_rsp<<pin complex => output>>",__func__);
++ hda_cmd_rsp(cardno, 0x0c, 0x3f0, 0x3f);//pin amp => 0x3f
++ hda_cmd_rsp(cardno, 0x14, 0x3f0, 0x00);//pin complex => no mute
++ //DBG("%s after hda_cmd_rsp",__func__);
++ //msleep_interruptible(10);
++ /* ------------------------------ */
++ /* Step 4: Output Converter Setup */
++ /* ------------------------------ */
++ /* Set Converter Format & Stream to Node 2(Output Converter) */
++ /* type = PCM, base = 48K, mult = xN, div = /M, bits = 8~32bits/sample, chnum = 1 */
++ /* stream = 1, lowest channel = 0 */
++ hda_fmt = hda_converter_setup(cardno, HDA_OUT_STR, //MODE
++ 0, base, mult, div, 1, 1, //FORMAT
++ HDA_STRNUM_TX, HDA_CHANUM); //STREAM
++ //DBG("%s after hda_converter_setup",__func__);
++ /* ---------------------------- */
++ /* Step 5: Enable Output Stream */
++ /* ---------------------------- */
++ hda_iosdc_setup(cardno, HDA_OUT_STR, HDA_STR_RUN, HDA_STRNUM_TX, hda_fmt);
++ SetSSP_Enable(cardno, 1);
++ SetSSP_RXFIFO(cardno, 0, 0);
++ SetSSP_TXFIFO(cardno, 0, 0);
++ //outl(0xC, FTSSP010_CONTROL2(cardno)); /* Disable FTSSP010, clear RX/TX Fifo. */
++ SetSSP_FIFO_Threshold(cardno,12,12);
++ SetSSP_DMA(cardno,1,0);
++
++ SSPClearTxFIFO(cardno);
++ SSPClearRxFIFO(cardno);
++ }
++
++ while(inl(FTSSP010_INT_STATUS(cardno))&0x3);
++}
++/* for HDA */
++void ftssp010_config_hda_play(int cardno, unsigned is_stereo, unsigned speed, int use8bit)
++{
++ _ftssp010_config_hda(cardno, is_stereo, speed, 0);
++}
++
++void ftssp010_config_hda_rec(int cardno, unsigned is_stereo, unsigned speed, int use8bit)
++{
++ _ftssp010_config_hda(cardno, is_stereo, speed, 1);
++}
++
++
++
++void ftssp010_stop_tx(int cardno)
++{
++ unsigned int hda_reg_base = HDA_REG_OSDC(cardno);
++ SetSSP_Enable(cardno,0);
++ SetSSP_DMA(cardno,0,0);
++
++ /* turn off output node */
++ hda_cmd_rsp(cardno,0x14, 0x707, 0); //pin complex => input enable, port-c LINE1
++ hda_cmd_rsp(cardno,0x0c, 0x3f0, 0x80); //pin amp => max LINE ADC amplifier gain
++ hda_cmd_rsp(cardno,0x14, 0x3f0, 0x80); //pin complex => no mute
++
++ outl(0, hda_reg_base);
++ SSPClearFIFO(cardno, 1, 0);
++ //outl(inl(FTSSP010_INT_CONTROL(cardno)) & (~0x22), FTSSP010_INT_CONTROL(cardno));
++}
++
++void ftssp010_stop_rx(int cardno)
++{
++ unsigned int hda_reg_base = HDA_REG_ISDC(cardno);
++ SetSSP_Enable_rx(cardno, 0);
++ SetSSP_DMA(cardno, 0, 0);
++
++ /* turn off output node */
++ hda_cmd_rsp(cardno,0x1a, 0x707, 0); //pin complex => input enable, port-c LINE1
++ hda_cmd_rsp(cardno,0x08, 0x3f0, 0x80);//pin amp => LINE ADC amplifier gain
++ hda_cmd_rsp(cardno,0x1a, 0x3f0, 0x80);//pin complex => mute
++ hda_cmd_rsp(cardno,0x23, 0x3f2, 0x80);//pin complex => no mute
++
++ outl(0, hda_reg_base);
++ SSPClearFIFO(cardno, 0, 1);
++ //outl(inl(FTSSP010_INT_CONTROL(cardno)) & (~0x11), FTSSP010_INT_CONTROL(cardno));
++}
++
+diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_lib.c linux-3.4.110/sound/nds32/FTSSP010_lib.c
+--- linux-3.4.110.orig/sound/nds32/FTSSP010_lib.c 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/sound/nds32/FTSSP010_lib.c 2016-04-07 10:20:51.062085666 +0200
+@@ -0,0 +1,795 @@
++/* FTSSP010 - UDA1345TS module
++ *
++ * $log$
++ */
++
++#include <linux/init.h>
++#include <linux/module.h>
++#include <asm/io.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <asm/spec.h>
++#include <asm/dmad.h>
++#include <linux/dma-mapping.h>
++#include "FTSSP010_UDA1345TS.h"
++
++#if 0
++MODULE_LICENSE("Faraday License");
++MODULE_AUTHOR("Faraday Technology Corp.");
++MODULE_DESCRIPTION("FTSSP010 - UDA1345TS Linux 2.6 Library");
++#endif
++
++#define PMU_PDLLCR1 (PMU_FTPMU010_VA_BASE+0x34)
++#define PMU_MFPSR (PMU_FTPMU010_VA_BASE+0x28)
++#define PMU_I2SAC97_REQACKCFG (PMU_FTPMU010_VA_BASE+0xbc)
++#define PMU_C4 (PMU_FTPMU010_VA_BASE+0xc4)
++
++#define SSPCLK_TO_SCLKDIV(sspclk_div2,bps) ((sspclk_div2)/(bps)-1)
++
++// Each client has this additional data
++struct alc5630_data {
++ struct i2c_client *client;
++ struct delayed_work work;
++ unsigned long gpio2_value;
++ struct mutex mtx;
++};
++
++//ADD by river 2011.01.26
++static int i2s_alc5630_read(unsigned int raddr, char *data, struct i2c_client *client)
++{
++#ifndef CONFIG_SND_FTSSP010_AC97
++ struct i2c_adapter *adap = client->adapter;
++ int ret;
++#endif
++ struct i2c_msg msg;
++ int i2c_value;
++
++ //Reading ALC5630 register
++ msg.addr = raddr;
++ msg.flags = (client->flags & I2C_M_TEN) | I2C_M_RD;
++ msg.len = 1;
++ msg.buf = (char *)data;
++
++ //ret = i2c_transfer(adap, &msg, 1);
++#ifndef CONFIG_SND_FTSSP010_AC97
++ ret = i2c_transfer(adap, &msg, 1);
++ if (ret != 0) {
++ printk("i2c read failed\n");
++ return -1;
++ }
++ else
++#endif
++ {
++ i2c_value = (data[0]&0xff) << 8 | (data[1]&0xff);
++ return i2c_value;
++ }
++}
++
++static void i2s_alc5630_write(unsigned int raddr, unsigned int data, struct i2c_client *client)
++{
++#ifndef CONFIG_SND_FTSSP010_AC97
++ struct i2c_adapter *adap = client->adapter;
++ int ret;
++#endif
++ struct i2c_msg msg;
++ char buf[3];
++
++ //Writing ALC5630 register
++ msg.addr = raddr;
++ msg.flags = (client->flags & I2C_M_TEN) | ~I2C_M_RD;
++ msg.len = 1;
++
++ buf[0] = (data >> 8) & 0xff;
++ buf[1] = data & 0xff;
++ msg.buf = (char *)buf;
++
++ //ret = i2c_transfer(adap, &msg, 1);
++#ifndef CONFIG_SND_FTSSP010_AC97
++ ret = i2c_transfer(adap, &msg, 1);
++ if (ret != 0)
++ {
++ printk("i2c write failed\n");
++ }
++#endif
++}
++
++/*
++static void i2s_alc5630_master_stereo_mode(struct i2c_client *client)
++{
++ //printk(">>>>>>>>> (7) i2s_alc5630_master_stereo_mode() is called.\n");
++ i2s_alc5630_write(0x02, 0x5f5f, client);
++ mdelay(50);
++ i2s_alc5630_write(0x04, 0x5f5f, client);
++ mdelay(50);
++ i2s_alc5630_write(0x26, 0x000f, client);
++ mdelay(50);
++ i2s_alc5630_write(0x34, 0x0000, client); // codec master mode
++ //i2s_alc5630_write(0x34, 0x8000, client); // codec slave mode
++ mdelay(50);
++ i2s_alc5630_write(0x3a, 0x0801, client);
++ mdelay(50);
++ i2s_alc5630_write(0x3c, 0xffff, client);
++ mdelay(50);
++ i2s_alc5630_write(0x3e, 0xffff, client);
++ mdelay(50);
++ i2s_alc5630_write(0x60, 0x3075, client); // codec master mode. divider.
++ mdelay(50);
++ i2s_alc5630_write(0x62, 0x1010, client); // codec master mode. divider.
++
++}
++*/
++
++/*
++static void i2s_alc5630_read_test(struct i2c_client *client)
++{
++ char data[3];
++ printk(">>>>> : i2s_alc5630_read_test().....\n");
++ printk("Reg 0x%02x = 0x%08x\n", 0x0, i2s_alc5630_read(0x0, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x02, i2s_alc5630_read(0x02, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x04, i2s_alc5630_read(0x04, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x06, i2s_alc5630_read(0x06, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x08, i2s_alc5630_read(0x08, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x0a, i2s_alc5630_read(0x0a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x0c, i2s_alc5630_read(0x0c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x0e, i2s_alc5630_read(0x0e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x10, i2s_alc5630_read(0x10, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x12, i2s_alc5630_read(0x12, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x14, i2s_alc5630_read(0x14, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x16, i2s_alc5630_read(0x16, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x18, i2s_alc5630_read(0x18, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x1a, i2s_alc5630_read(0x1a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x1c, i2s_alc5630_read(0x1c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x1e, i2s_alc5630_read(0x1e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x20, i2s_alc5630_read(0x20, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x22, i2s_alc5630_read(0x22, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x24, i2s_alc5630_read(0x24, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x26, i2s_alc5630_read(0x26, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x28, i2s_alc5630_read(0x28, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x2a, i2s_alc5630_read(0x2a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x2c, i2s_alc5630_read(0x2c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x2e, i2s_alc5630_read(0x2e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x30, i2s_alc5630_read(0x30, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x32, i2s_alc5630_read(0x32, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x34, i2s_alc5630_read(0x34, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x36, i2s_alc5630_read(0x36, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x38, i2s_alc5630_read(0x38, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x3a, i2s_alc5630_read(0x3a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x3c, i2s_alc5630_read(0x3c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x3e, i2s_alc5630_read(0x3e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x40, i2s_alc5630_read(0x40, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x42, i2s_alc5630_read(0x42, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x44, i2s_alc5630_read(0x44, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x46, i2s_alc5630_read(0x46, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x48, i2s_alc5630_read(0x48, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x4a, i2s_alc5630_read(0x4a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x4c, i2s_alc5630_read(0x4c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x4e, i2s_alc5630_read(0x4e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x50, i2s_alc5630_read(0x50, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x52, i2s_alc5630_read(0x52, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x54, i2s_alc5630_read(0x54, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x56, i2s_alc5630_read(0x56, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x58, i2s_alc5630_read(0x58, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x5a, i2s_alc5630_read(0x5a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x5c, i2s_alc5630_read(0x5c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x5e, i2s_alc5630_read(0x5e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x60, i2s_alc5630_read(0x60, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x62, i2s_alc5630_read(0x62, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x64, i2s_alc5630_read(0x64, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x66, i2s_alc5630_read(0x66, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x68, i2s_alc5630_read(0x68, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x6a, i2s_alc5630_read(0x6a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x6c, i2s_alc5630_read(0x6c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x6e, i2s_alc5630_read(0x6e, data,client));
++
++ printk("Reg 0x%02x = 0x%08x\n", 0x70, i2s_alc5630_read(0x70, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x72, i2s_alc5630_read(0x72, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x74, i2s_alc5630_read(0x74, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x76, i2s_alc5630_read(0x76, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x78, i2s_alc5630_read(0x78, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x7a, i2s_alc5630_read(0x7a, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x7c, i2s_alc5630_read(0x7c, data,client));
++ printk("Reg 0x%02x = 0x%08x\n", 0x7e, i2s_alc5630_read(0x7e, data,client));
++
++}
++*/
++
++static void i2s_al5630_slave_stereo_mode(struct i2c_client *client)
++{
++
++
++ i2s_alc5630_write(0x34, 0x8000, client); // codec slave mode
++ i2s_alc5630_write(0x0c, 0x1010, client);
++ i2s_alc5630_write(0x10, 0xee03, client);
++ i2s_alc5630_write(0x1c, 0x0748, client);
++ //i2s_alc5630_write(0x02, 0x8080, client);
++ //i2s_alc5630_write(0x04, 0x8888, client);
++ i2s_alc5630_write(0x62, 0x0000, client);
++
++}
++
++//End ADD by river 2011.01.26
++
++
++/* Drive PMU to generate I2S main clocking signal. Also configures PMU to set correct DMA REQ/ACK pair */
++void pmu_set_i2s_clocking(unsigned int speed)
++{
++ unsigned int pmu_pdllcr1; /* PLL/DLL Control Register 1 */
++ /* Configure PMU to generate I2S main clock */
++ #ifdef CONFIG_PLAT_AG101
++ pmu_pdllcr1 = inl(PMU_PDLLCR1)&0xfff0ffff; /* Bit 19-16 are relevent */
++ #endif
++
++ switch (speed) {
++ case 8000:
++ pmu_pdllcr1 |= 0x00000000; /* 2.048MHz x2 */
++ break;
++ case 11025:
++ pmu_pdllcr1 |= 0x00010000; /* 2.8224MHz x2 */
++ break;
++ case 16000:
++ pmu_pdllcr1 |= 0x00020000; /* 4.096MHz x2 */
++ break;
++ case 22050:
++ pmu_pdllcr1 |= 0x00030000; /* 5.6448MHz x2 */
++ break;
++ case 32000:
++ pmu_pdllcr1 |= 0x00040000; /* 8.192MHz x2 */
++ break;
++ case 44100:
++ pmu_pdllcr1 |= 0x00050000; /* 11.2896Mhz x2 */
++ break;
++ case 48000:
++ pmu_pdllcr1 |= 0x00060000; /* 12.2880MHz x2 */
++ break;
++ default:
++ printk("%s: Unknown i2s speed %d\n",__func__,speed);
++ };
++
++ #ifdef CONFIG_PLAT_AG101
++ outl(pmu_pdllcr1, PMU_PDLLCR1);
++ /* Configure PMU to select I2S output (instead of AC97) */
++ outl(inl(PMU_MFPSR)&(~(1<<3)), PMU_MFPSR); /* clear bit 3 of MFPSR*/
++ #endif
++}
++
++/* Drive PMU to generate AC97 main clocking signal. Also configures PMU to set correct DMA REQ/ACK pair */
++void pmu_set_ac97_clocking(unsigned int speed)
++{
++ /* Configure PMU to select AC97 output (instead of I2S) */
++ /* Set GPIO[26] to AC97 clock, use 49.152MHz main clock (AC97 CLK1) */
++ //outl(inl(PMU_MFPSR)|((1<<13)|(1<<3)), PMU_MFPSR); /* Set bit 13 & 3 of MFPSR*/
++ #ifndef CONFIG_PLAT_AG102
++ outl(inl(PMU_MFPSR)|((1<<13)|(1<<3)), PMU_MFPSR); /* Set bit 13 & 3 of MFPSR*/
++ #endif
++}
++
++/* Programs PMU to set I2S/AC97 DMA Channel, ch=0-7 */
++void pmu_set_i2s_dma_channel(unsigned ch)
++{
++ #ifdef CONFIG_PLAT_AG101
++ ch&=0x7;
++ //outl((inl(PMU_I2SAC97_REQACKCFG)&(~0x7))|ch, PMU_I2SAC97_REQACKCFG);
++ outl(0xa, PMU_I2SAC97_REQACKCFG);
++ outl(0xb, PMU_C4);
++ #endif
++}
++
++/* Initialize FTSSP010 to output to UDA1345TS via I2S */
++#define FTSSP010_CONTROL0(x) (SSP_FTSSP010_va_base[(x)]+0x0)
++#define FTSSP010_CONTROL0_OPM_STEREO 0xC
++#define FTSSP010_CONTROL0_OPM_MONO 0x8
++
++#define FTSSP010_CONTROL1(x) (SSP_FTSSP010_va_base[(x)]+0x4)
++#define FTSSP010_CONTROL2(x) (SSP_FTSSP010_va_base[(x)]+0x8)
++
++#define FTSSP010_INT_CONTROL(x) (SSP_FTSSP010_va_base[(x)]+0x10)
++#define FTSSP010_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0xC)
++#define FTSSP010_INT_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0x14)
++#define FTSSP010_DATA(x) (SSP_FTSSP010_va_base[(x)]+0x18)
++#define FTSSP010_INFO(x) (SSP_FTSSP010_va_base[(x)]+0x1C)
++
++//static const unsigned int SSP_FTSSP010_va_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_VA_BASE };
++//static const unsigned int SSP_FTSSP010_pa_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_PA_BASE };
++
++//ADD by river 2011.02.11
++static struct i2c_client *g_i2c_client;
++
++
++#define FTSSP010_ACLINK_SLOT_VALID(x) (SSP_FTSSP010_va_base[(x)]+0x20)
++
++void ftssp010_set_int_control(int cardno, unsigned val)
++{
++ outl(val, FTSSP010_INT_CONTROL(cardno));
++}
++
++unsigned ftssp010_get_int_status(int cardno)
++{
++ return (inl(FTSSP010_INT_STATUS(cardno)));
++}
++
++int ftssp010_get_status(int cardno)
++{
++ return (inl(FTSSP010_STATUS(cardno)));
++}
++
++int ftssp010_tx_fifo_not_full(int cardno)
++{
++ return (inl(FTSSP010_STATUS(cardno))&0x2)==0x2;
++}
++
++int ftssp010_tx_fifo_vaild_entries(int cardno)
++{
++ return (inl(FTSSP010_STATUS(cardno))>>12) & 0x1f;
++}
++
++#include "FTSSP010_W83972D.h"
++
++// AC97 codec tags
++#define TAG_COMMAND 0xe000
++#define TAG_DATA 0x9800 /* Slot 3/4 */
++#define TAG_DATA_MONO 0x9000 /* Slot 3 */
++//#define TAG_DATA_LINE_IN 0x9000 /* Slot 3 */
++
++void ftssp010_ac97_write_codec_start(unsigned int cardno)
++{
++ outl(0x0, FTSSP010_INT_CONTROL(cardno));/*Disable interrupts & DMA req */
++ outl(0xC, FTSSP010_CONTROL2(cardno)); /* Disable FTSSP010, clear RX/TX Fifo. */
++ outl(TAG_COMMAND, FTSSP010_ACLINK_SLOT_VALID(cardno));
++}
++
++void ftssp010_ac97_write_codec(unsigned int cardno,unsigned int reg,unsigned int data)
++{
++ outl(reg << 12, FTSSP010_DATA(cardno));
++ mdelay(50);
++ outl(data << 4, FTSSP010_DATA(cardno));
++ mdelay(50);
++}
++
++void ftssp010_ac97_write_codec_commit(unsigned int cardno)
++{
++ while((inl(FTSSP010_CONTROL2(cardno))&0x1)==0) {
++ outl(0x3 , FTSSP010_CONTROL2(cardno)); /* SSPEN + TXDOE */
++ }
++ while(ftssp010_tx_fifo_vaild_entries(cardno))
++ ;
++ /* Wait for frame completion */
++ while((inl(FTSSP010_INT_STATUS(cardno))&0x10)==0)
++ ;
++ outl(0x0, FTSSP010_CONTROL2(cardno));
++}
++
++/* Configure FTSSP010 to a given sampling rate and channel number
++ * for AC97 mode in playback mode
++ */
++void init_hw(unsigned int cardno,unsigned int ac97, struct i2c_client *client)
++{
++
++ //printk(">>>>>>>>>> (5) init_hw() is called.\n");
++ g_i2c_client = client;
++
++ if(ac97)
++ {
++ //pmu_set_ac97_clocking(48000);
++ #ifndef CONFIG_PLAT_AG102
++ pmu_set_ac97_clocking(48000);
++ #endif
++ outl(0x400c, FTSSP010_CONTROL0(cardno)); /* set FTSSP010 to AC97 mode */
++ mdelay(50);
++ outl(0xc400, FTSSP010_INT_CONTROL(cardno));
++ mdelay(50);
++ outl(0x20, FTSSP010_CONTROL2(cardno)); /* Cold Reset AC-Link */
++ mdelay(50);
++ while(inl(FTSSP010_CONTROL2(cardno)))
++ mdelay(50);
++ outl(0x40, FTSSP010_CONTROL2(cardno)); /* Reset AC-Link */
++ mdelay(1500);
++ }
++ else
++ {
++
++ //printk(">>>>>>>>> (6) I2S mode selected....YAYAYA......\n");
++ #ifdef CONFIG_PLAT_AG101
++ outl(inl(PMU_MFPSR)&(~(1<<3)), PMU_MFPSR); /* clear bit 3 of MFPSR*/
++ outl(0xa, PMU_I2SAC97_REQACKCFG);
++ outl(0xb, PMU_C4);
++ #endif
++
++ //MOD by river 2011.01.26
++ //i2s_alc5630_master_stereo_mode(client);
++ i2s_al5630_slave_stereo_mode(client);
++ //ssp_slave_stereo_mode();
++ //End MOD by river 2011.01.26
++ outl(0x311c, FTSSP010_CONTROL0(cardno)); /* I2S Master */
++ outl(0, FTSSP010_CONTROL1(cardno)); /* I2S Master */
++ outl(0xc400, FTSSP010_INT_CONTROL(cardno)); /* I2S Master */
++ outl(0x40, FTSSP010_CONTROL2(cardno)); /* Reset AC-Link */
++
++ //i2s_alc5630_read_test(client);
++ }
++}
++static void _ftssp010_config_ac97(int cardno, unsigned is_stereo, unsigned speed, int is_rec)
++{
++ /* Codec initialization */
++ ftssp010_ac97_write_codec_start(cardno);
++ ftssp010_ac97_write_codec(cardno, W83972D_RESET, 0);
++ ftssp010_ac97_write_codec_commit(cardno);
++
++ msleep_interruptible(10);
++ ftssp010_ac97_write_codec_start(cardno);
++
++ if (is_rec) { /* Recording */
++ /* Mute output */
++ //ftssp010_ac97_write_codec(cardno, W83972D_STEREO_OUTPUT_CONTROL, 0x8000);
++ /* Mute PCM */
++ //ftssp010_ac97_write_codec(cardno, W83972D_PCM_OUTPUT_CONTROL, 0x8000);
++
++ /* Register 0x10, Line-In/Mic Gain */
++ ftssp010_ac97_write_codec(cardno, W83972D_LINE_IN_VOLUME, 0x808);
++ //ftssp010_ac97_write_codec(cardno, W83972D_AUX_INPUT_CONTROL, 0x808);
++ ftssp010_ac97_write_codec(cardno, W83972D_MIC_VOLUME, 0x8);
++ /* FIXME: REC from line-in only */
++
++ /* Register 0x1A, Record Select=StereoMix */
++ ftssp010_ac97_write_codec(cardno, W83972D_RECORD_SELECT, 0x505 /*404*/);
++ /* Register 0x1C, Record Gain=0db */
++ ftssp010_ac97_write_codec(cardno, W83972D_RECORD_GAIN, 0x808);
++ ftssp010_ac97_write_codec(cardno, W83972D_RECORD_GAIN_MIC, 0x8);
++ } else { /* Playback */
++ /* Register 0x10, Mute Line-In/Mic Gain */
++ ftssp010_ac97_write_codec(cardno, W83972D_LINE_IN_VOLUME, 0x8000);
++ ftssp010_ac97_write_codec(cardno, W83972D_MIC_VOLUME, 0x8000);
++
++ /* Register 0x1A, Mute Record Gains */
++ ftssp010_ac97_write_codec(cardno, W83972D_RECORD_GAIN, 0x8000);
++ ftssp010_ac97_write_codec(cardno, W83972D_RECORD_GAIN_MIC, 0x8000);
++
++ /* Output */
++ ftssp010_ac97_write_codec(cardno, W83972D_STEREO_OUTPUT_CONTROL, 0);
++ ftssp010_ac97_write_codec(cardno, W83972D_PCM_OUTPUT_CONTROL, 0x808);
++ }
++
++#if 0
++ ftssp010_ac97_write_codec(cardno, W83972D_EXT_AUDIO_CONTROL, 0x1);
++ ftssp010_ac97_write_codec(cardno, W83972D_DAC_SAMPLE_RATE_CONTROL, speed);
++#endif
++
++ ftssp010_ac97_write_codec_commit(cardno);
++ msleep_interruptible(10);
++
++ /* Start data transfer */
++// if(is_rec) {
++// outl(TAG_DATA_LINE_IN, FTSSP010_ACLINK_SLOT_VALID(cardno));
++// } else {
++ if(is_stereo)
++ outl(TAG_DATA, FTSSP010_ACLINK_SLOT_VALID(cardno));
++ else
++ outl(TAG_DATA_MONO, FTSSP010_ACLINK_SLOT_VALID(cardno));
++// }
++ while(inl(FTSSP010_INT_STATUS(cardno))&0x3);
++// msleep_interruptible(10);
++}
++
++void ftssp010_config_ac97_play(int cardno, unsigned is_stereo, unsigned speed, int use8bit)
++{
++ _ftssp010_config_ac97(cardno, is_stereo, speed, 0);
++}
++
++void ftssp010_config_ac97_rec(int cardno, unsigned is_stereo, unsigned speed, int use8bit)
++{
++ _ftssp010_config_ac97(cardno, is_stereo, speed, 1);
++}
++/*
++ * Configure FTSSP010 to a given sampling rate and channel number
++ * for I2S mode
++ */
++void ftssp010_config(int cardno, unsigned is_stereo, unsigned speed, int width, int is_rec)
++{
++ int use8bit = (width == 1 ? 1 : 0);
++ unsigned opm, bps = 2 * (use8bit ? 8 : 16); /* bits per 1 second audio data. */
++ unsigned fpclkdiv = 0;
++
++ //ADD by river 2011.06.02
++ struct alc5630_data *alc5630;
++ char data[3];
++ opm = is_stereo ? FTSSP010_CONTROL0_OPM_STEREO : FTSSP010_CONTROL0_OPM_MONO;
++ //MOD by river 2011.01.27
++ outl(0x3100 | opm, FTSSP010_CONTROL0(cardno)); /* I2S Master */
++ //End MOD by river 2011.01.27
++
++#if 0
++ printk("%s: use %dHz %d-bit %s \n",__func__,
++ speed,
++ use8bit?8:16,
++ is_stereo?"stereo":"mono"
++ );
++#endif
++
++ /* configures CONTROL1 to use suitable clock divider.
++ the I2S clock is generated from PMU. */
++ bps *= speed;
++ switch(speed) {
++ case 8000: /* SCLK : 256KHZ */
++ i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client); //?
++ i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
++ i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
++ //i2s_alc5630_write(0x44, 0x6a0, g_i2c_client); //?
++ //i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
++ //i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
++ fpclkdiv = 0xBB;
++
++ //fpclkdiv=SSPCLK_TO_SCLKDIV(2048000, bps);
++ break;
++ case 11025: /* SCLK : 352.8KHZ */
++ i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client); //?
++ i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
++ i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
++ fpclkdiv = 0x88;
++ //fpclkdiv=SSPCLK_TO_SCLKDIV(2822400, bps);
++ break;
++ case 16000: /* SCLK : 512KHZ */
++ i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client); //?
++ i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
++ i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
++ fpclkdiv = 0x5f;
++ //fpclkdiv=SSPCLK_TO_SCLKDIV(4096000, bps);
++ break;
++ case 22050: /* SCLK : 705.6KHZ */
++ i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
++ i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
++ i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
++ fpclkdiv = 0x45;
++ //fpclkdiv=SSPCLK_TO_SCLKDIV(5644800, bps);
++ break;
++ case 24000: /* SCLK : 768KHZ */
++ i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
++ i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
++ i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
++ fpclkdiv = 0x3e;
++ //fpclkdiv=SSPCLK_TO_SCLKDIV(5644800, bps);
++ break;
++ case 32000: /* SCLK : 1024KHZ */
++ i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
++ i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
++ i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
++ //fpclkdiv = 0x2e;
++ fpclkdiv = 0x2f;
++ //fpclkdiv=SSPCLK_TO_SCLKDIV(8192000, bps);
++ break;
++ case 44100: /* SCLK : 1.4112 MHZ */ /* 96 MHZ */
++ i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
++ i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
++ i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
++ fpclkdiv = 0x22;
++ //fpclkdiv=SSPCLK_TO_SCLKDIV(11289600, bps);
++ break;
++ case 48000: /* SCLK : 1.536 MHZ */
++ i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
++ i2s_alc5630_write(0x60, 0x3174, g_i2c_client);
++ i2s_alc5630_write(0x62, 0x1010, g_i2c_client);
++ fpclkdiv = 0x1f;
++ //fpclkdiv=SSPCLK_TO_SCLKDIV(12288000, bps);
++
++ break;
++ default:
++ printk("%s: unsupported speed %d\n", __func__,speed);
++ return;
++ };
++
++
++ if(!use8bit) {
++ outl(0xf0000|fpclkdiv, FTSSP010_CONTROL1(cardno)); /* 16bits */
++ //outl(0xf0000|0x10, FTSSP010_CONTROL1(cardno)); /* 16bits */
++ //outl(0xf0000|0x22, FTSSP010_CONTROL1(cardno)); /* 16bits */
++ } else {
++ outl(0x70000|fpclkdiv, FTSSP010_CONTROL1(cardno)); /* 8bits */
++ }
++
++ //printk("#####$$$$$ : bps = %d\n", bps);
++ //printk("#####$$$$$ : speed = %d\n", speed);
++ //printk("#####$$$$$ : fpclkdiv = 0x%08x\n", fpclkdiv);
++ //printk("#####$$$$$ : FTSSP010_CONTROL1(cardno) = 0x%08x\n", inl(FTSSP010_CONTROL1(cardno)));
++
++ if(is_rec)
++ outl(inl(FTSSP010_INT_CONTROL(cardno))&(~0x0f15), FTSSP010_INT_CONTROL(cardno)); /* Disable all interrupts */
++ else
++ outl(inl(FTSSP010_INT_CONTROL(cardno))&(~0xf02a) , FTSSP010_INT_CONTROL(cardno)); /* Disable all interrupts */
++
++ outl(0xc, FTSSP010_CONTROL2(cardno)); /* clear FIFOs */
++
++ //ADD by river 2011.06.02
++ alc5630 = i2c_get_clientdata(g_i2c_client);
++ //End
++
++ if(is_rec) {
++ printk("ftssp010_config() for I2S mode in record.\n");
++ //ADD by river 2011.03.21
++ //TEST by river 2011.03.22 for recording => workable
++ //i2s_alc5630_write(0x0e, 0x8888, g_i2c_client);
++ i2s_alc5630_write(0x0e, 0x0808, g_i2c_client);
++ i2s_alc5630_write(0x10, 0xee03, g_i2c_client);
++ i2s_alc5630_write(0x22, 0x0500, g_i2c_client);
++ i2s_alc5630_write(0x1c, 0x0748, g_i2c_client);
++ i2s_alc5630_write(0x14, 0x1f1f, g_i2c_client);
++ i2s_alc5630_write(0x12, 0xdfdf, g_i2c_client);
++
++ i2s_alc5630_write(0x26, 0x000f, g_i2c_client);
++ i2s_alc5630_write(0x3a, 0xffff, g_i2c_client);
++ i2s_alc5630_write(0x3c, 0xffff, g_i2c_client);
++ //i2s_alc5630_write(0x3e, 0xffff, g_i2c_client);
++ i2s_alc5630_write(0x3e, 0x80cf, g_i2c_client);
++
++ i2s_alc5630_write(0x44, 0x3ea0, g_i2c_client);
++ i2s_alc5630_write(0x42, 0x2000, g_i2c_client);
++ i2s_alc5630_write(0x40, 0x8c0a, g_i2c_client);
++
++ //i2s_alc5630_write(0x02, 0x0000, g_i2c_client);
++ i2s_alc5630_write(0x02, 0x8080, g_i2c_client);
++ i2s_alc5630_write(0x04, 0x0000, g_i2c_client);
++ //End TEST by river 2011.03.22
++
++ //printk("ftssp010_config() for I2S mode (Recording) ===> Dump register.\n");
++ //i2s_alc5630_read_test(g_i2c_client);
++
++ }
++ else {
++ //printk("ftssp010_config() for I2S mode in playback.\n");
++ //ADD by river 2011.03.24 for record and playback case
++ i2s_alc5630_write(0x0e, 0x0808, g_i2c_client);
++ i2s_alc5630_write(0x12, 0xcbcb, g_i2c_client);
++ i2s_alc5630_write(0x14, 0x7f7f, g_i2c_client);
++ i2s_alc5630_write(0x22, 0x0000, g_i2c_client);
++ i2s_alc5630_write(0x3e, 0x8000, g_i2c_client);
++ i2s_alc5630_write(0x40, 0x0c0a, g_i2c_client);
++ i2s_alc5630_write(0x42, 0x0000, g_i2c_client);
++ //End ADD by river 2011.03.24 for record and playback case
++
++ //TEST by river 2011.03.23
++ i2s_alc5630_write(0x26, 0x0000, g_i2c_client);
++ i2s_alc5630_write(0x3c, 0x2000, g_i2c_client);
++ i2s_alc5630_write(0x3a, 0x0002, g_i2c_client);
++ i2s_alc5630_write(0x3c, 0xa330, g_i2c_client);
++ i2s_alc5630_write(0x3a, 0xc843, g_i2c_client);
++ //End TEST by river 2011.03.23
++
++ //ADD by river 2011.03.23 for HP Out De-pop
++ i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0002 , g_i2c_client);
++ i2s_alc5630_write(0x04, i2s_alc5630_read(0x04, data,g_i2c_client)|0x8080 , g_i2c_client);
++ i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0040 , g_i2c_client);
++ i2s_alc5630_write(0x3c, i2s_alc5630_read(0x3C, data,g_i2c_client)|0x2000 , g_i2c_client);
++ i2s_alc5630_write(0x3E, i2s_alc5630_read(0x3E, data,g_i2c_client)|0xfC00 , g_i2c_client);
++ i2s_alc5630_write(0x5E, i2s_alc5630_read(0x5E, data,g_i2c_client)|0x0100 , g_i2c_client);
++ mdelay(500);
++ i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0200 , g_i2c_client);
++ i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0100 , g_i2c_client);
++ i2s_alc5630_write(0x5E, i2s_alc5630_read(0x5E, data,g_i2c_client)& 0xfeff ,g_i2c_client);
++ //End ADD by river 2011.03.23 for HP Out De-pop
++
++
++ //TEST by river 2011.03.22
++ i2s_alc5630_write(0x1c, 0x0748, g_i2c_client);
++ //End TEST by river 2011.03.22
++
++
++ //TEST by river 2011.03.16
++ //i2s_alc5630_write(0x02, 0x8080, g_i2c_client);
++ i2s_alc5630_write(0x26, 0x000f, g_i2c_client);
++ //End TEST by river 2011.03.16
++
++ //ADD by river 2011.03.23
++ if (alc5630->gpio2_value==0x0)
++ i2s_alc5630_write(0x3A, (i2s_alc5630_read(0x3A, data,g_i2c_client) & 0xFBFF)|0x0040 , g_i2c_client);
++ else
++ i2s_alc5630_write(0x3A, i2s_alc5630_read(0x3A, data,g_i2c_client)|0x0440 , g_i2c_client);
++
++
++ i2s_alc5630_write(0x5E, i2s_alc5630_read(0x5E, data,g_i2c_client)|0x0020 , g_i2c_client);
++ i2s_alc5630_write(0x5E, i2s_alc5630_read(0x5E, data,g_i2c_client)|0x00c0 , g_i2c_client);
++ i2s_alc5630_write(0x04, i2s_alc5630_read(0x04, data,g_i2c_client)& 0x7f7f , g_i2c_client);
++ mdelay(30);
++
++ if (alc5630->gpio2_value==0x0) {
++ //printk(">>>>>>>>>>>> Turn off internal speaker.....\n");
++ i2s_alc5630_write(0x02, 0x5F5F, g_i2c_client);
++ //i2s_alc5630_write(0x02, 0x0000, g_i2c_client);
++ }
++ else {
++ //printk(">>>>>>>>>>>> Turn on internal speaker.....\n");
++ i2s_alc5630_write(0x02, 0x0000, g_i2c_client);
++ //i2s_alc5630_write(0x02, 0x5F5F, g_i2c_client);
++ }
++ //End ADD by river 2011.03.23
++
++
++ //printk("ftssp010_config() for I2S mode (Playback) ===> Dump register.\n");
++ //i2s_alc5630_read_test(g_i2c_client);
++ }
++
++#if 0
++ /* Stuff TX fifo */
++ while(ftssp010_tx_fifo_not_full(cardno)) {
++ outl(0x0, FTSSP010_DATA(cardno));
++ }
++#endif
++}
++
++void ftssp010_config_tx(int cardno, unsigned is_stereo, unsigned speed, int width)
++{
++ return ftssp010_config(cardno, is_stereo, speed, width, 0);
++}
++
++void ftssp010_config_rx(int cardno, unsigned is_stereo, unsigned speed, int width)
++{
++ return ftssp010_config(cardno, is_stereo, speed, width, 1);
++}
++
++/* Configures FTSSP010 to start TX. If use_dma being nonzero,
++ * FTSSP010 will use hardware handshake for DMA */
++void ftssp010_start_tx(int cardno, unsigned use_dma)
++{
++ unsigned bogus=0x800*3;
++ if(use_dma) {
++ /* Enable H/W DMA Request and set TX DMA threshold to 12*/
++// outl(0xC022, FTSSP010_INT_CONTROL(cardno));
++ outl(inl(FTSSP010_INT_CONTROL(cardno)) | 0xc422, FTSSP010_INT_CONTROL(cardno));
++#if 0
++ printk("%s: enable DMA request\n", __func__);
++#endif
++ }
++// outl(0x3, FTSSP010_CONTROL2(cardno));
++ outl(inl(FTSSP010_CONTROL2(cardno)) | 0x3, FTSSP010_CONTROL2(cardno));
++// printk("%s\n",__func__);
++// printk("int_control 0x%x\n",inl(FTSSP010_INT_CONTROL(cardno)));
++// printk("control2 0x%x\n",inl(FTSSP010_CONTROL2(cardno)));
++ if(!use_dma) {
++ while(bogus>0) {
++ while(!ftssp010_tx_fifo_not_full(cardno))
++ udelay(50);
++ outl(0, FTSSP010_DATA(cardno));
++ bogus--;
++ }
++ }
++}
++
++/* Configures FTSSP010 to start RX. If use_dma being nonzero,
++ * FTSSP010 will use hardware handshake for DMA */
++void ftssp010_start_rx(int cardno, unsigned use_dma)
++{
++ if(use_dma) {
++ /* Enable H/W DMA Request and set RX DMA threshold to 2*/
++// outl(0x0111, FTSSP010_INT_CONTROL(cardno));
++ outl(inl(FTSSP010_INT_CONTROL(cardno)) | 0xc411, FTSSP010_INT_CONTROL(cardno));
++#if 0
++ printk("%s: enable DMA request\n", __func__);
++#endif
++ }
++// outl(0x3, FTSSP010_CONTROL2(cardno));
++ outl(inl(FTSSP010_CONTROL2(cardno)) | 0x3, FTSSP010_CONTROL2(cardno));
++// printk("%s\n",__func__);
++// printk("int_control 0x%x\n",inl(FTSSP010_INT_CONTROL(cardno)));
++// printk("control2 0x%x\n",inl(FTSSP010_CONTROL2(cardno)));
++}
++
++void ftssp010_stop_tx(int cardno)
++{
++// outl(0, FTSSP010_CONTROL2(cardno));
++ outl(inl(FTSSP010_INT_CONTROL(cardno)) & (~0x22), FTSSP010_INT_CONTROL(cardno));
++// printk("%s\n",__func__);
++// printk("int_control 0x%x\n",inl(FTSSP010_INT_CONTROL(cardno)));
++// printk("control2 0x%x\n",inl(FTSSP010_CONTROL2(cardno)));
++}
++
++void ftssp010_stop_rx(int cardno)
++{
++ //outl(0, FTSSP010_CONTROL2(cardno));
++ outl(inl(FTSSP010_INT_CONTROL(cardno)) & (~0x11), FTSSP010_INT_CONTROL(cardno));
++ //printk("%s\n",__func__);
++ //printk("int_control 0x%x\n",inl(FTSSP010_INT_CONTROL(cardno)));
++ //printk("control2 0x%x\n",inl(FTSSP010_CONTROL2(cardno)));
++}
++
+diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_UDA1345TS.h linux-3.4.110/sound/nds32/FTSSP010_UDA1345TS.h
+--- linux-3.4.110.orig/sound/nds32/FTSSP010_UDA1345TS.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/sound/nds32/FTSSP010_UDA1345TS.h 2016-04-07 10:20:51.066085821 +0200
+@@ -0,0 +1,81 @@
++/* FTSSP010 - UDA1345TS supporting library header */
++/*
++ *
++ * $log$
++ *
++ */
++#include <linux/init.h>
++#include <linux/module.h>
++#include <asm/io.h>
++#include <linux/delay.h>
++#include <asm/spec.h>
++#include <linux/dma-mapping.h>
++
++/* Programming sequence:
++ * Suppose your playback format is 44.1KHz, 16 bit stereo
++ * PIO mode:
++ * pmu_set_i2s_clocking(44100);
++ * ftssp010_config(1, 44100, 0);
++ * ftssp010_start_tx(0);
++ * while(ftssp010_tx_fifo_not_full()) {
++ * Poke_your_PCM_data_to_FTSSP_data_port
++ *
++ * DMA mode:
++ * pmu_set_i2s_clocking(44100);
++ * ftssp010_config(1, 44100);
++ * <setup DMA controller, acquire DMA channel>
++ * pmu_set_i2s_dma_channel(ch);
++ * ftssp010_start_tx(1);
++ * <wait DMA to complete..>
++ * ftssp010_stop_tx();
++ */
++#define FTSSP010_DATA(x) (SSP_FTSSP010_va_base[(x)]+0x18)
++#define FTSSP010_DATA_PA(x) (SSP_FTSSP010_pa_base[(x)]+0x18)
++
++/* Initialize FTSSP010 to output to UDA1345TS via I2S */
++#define FTSSP010_CONTROL0(x) (SSP_FTSSP010_va_base[(x)]+0x0)
++#define FTSSP010_CONTROL0_OPM_STEREO 0xC
++#define FTSSP010_CONTROL0_OPM_MONO 0x8
++
++#define FTSSP010_CONTROL1(x) (SSP_FTSSP010_va_base[(x)]+0x4)
++#define FTSSP010_CONTROL2(x) (SSP_FTSSP010_va_base[(x)]+0x8)
++
++#define FTSSP010_INT_CONTROL(x) (SSP_FTSSP010_va_base[(x)]+0x10)
++#define FTSSP010_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0xC)
++#define FTSSP010_INT_STATUS(x) (SSP_FTSSP010_va_base[(x)]+0x14)
++#define FTSSP010_DATA(x) (SSP_FTSSP010_va_base[(x)]+0x18)
++#define FTSSP010_INFO(x) (SSP_FTSSP010_va_base[(x)]+0x1C)
++
++static const unsigned int SSP_FTSSP010_va_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_VA_BASE };
++static const unsigned int SSP_FTSSP010_pa_base[SSP_FTSSP010_IRQ_COUNT] = { SSP_FTSSP010_PA_BASE };
++
++/* Drive PMU to generate I2S main clocking signal. Also configures PMU to set correct DMA REQ/ACK pair */
++extern void pmu_set_i2s_clocking(unsigned int speed);
++/* Programs PMU to set I2S/AC97 DMA Channel, ch=0-7 */
++extern void pmu_set_i2s_dma_channel(unsigned ch);
++
++/* Drive PMU to generate AC97 main clocking signal. Also configures PMU to set correct DMA REQ/ACK pair */
++extern void pmu_set_ac97_clocking(unsigned int speed);
++
++/* Returns FTSSP010 status */
++extern void ftssp010_set_int_control(int cardno, unsigned val);
++extern int ftssp010_get_status(int cardno);
++extern unsigned ftssp010_get_int_status(int cardno);
++/* Polls FIFO full register */
++extern int ftssp010_tx_fifo_not_full(int cardno);
++/* Configure FTSSP010 to a given sampling rate and channel number */
++extern void ftssp010_config_tx(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
++extern void ftssp010_config_rx(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
++
++/* Configure FTSSP010 to a given sampling rate and channel number */
++extern void ftssp010_config_ac97_play(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
++
++extern void ftssp010_config_ac97_rec(int cardno, unsigned is_stereo, unsigned speed, int use8bit);
++
++/* Initialize FTSSP010 to output to UDA1345TS via I2S */
++extern void ftssp010_start_tx(int cardno, unsigned use_dma);
++extern void ftssp010_start_rx(int cardno, unsigned use_dma);
++extern void ftssp010_stop_tx(int cardno);
++extern void ftssp010_stop_rx(int cardno);
++
++
+diff -Nur linux-3.4.110.orig/sound/nds32/FTSSP010_W83972D.h linux-3.4.110/sound/nds32/FTSSP010_W83972D.h
+--- linux-3.4.110.orig/sound/nds32/FTSSP010_W83972D.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/sound/nds32/FTSSP010_W83972D.h 2016-04-07 10:20:51.066085821 +0200
+@@ -0,0 +1,17 @@
++/* AC97 Codec related */
++
++
++/* Register Index for Winbond W83972D AC97 Codec */
++#define W83972D_RESET 0x0
++#define W83972D_STEREO_OUTPUT_CONTROL 0x2
++#define W83972D_MIC_VOLUME 0xE
++#define W83972D_LINE_IN_VOLUME 0x10
++#define W83972D_AUX_INPUT_CONTROL 0x16
++#define W83972D_PCM_OUTPUT_CONTROL 0x18
++#define W83972D_RECORD_SELECT 0x1A
++#define W83972D_RECORD_GAIN 0x1C
++#define W83972D_RECORD_GAIN_MIC 0x1E
++#define W83972D_EXT_AUDIO_CONTROL 0x2A
++#define W83972D_DAC_SAMPLE_RATE_CONTROL 0x2C
++#define W83972D_VER1 0x7C
++#define W83972D_VER2 0x7E
+diff -Nur linux-3.4.110.orig/sound/nds32/hda.h linux-3.4.110/sound/nds32/hda.h
+--- linux-3.4.110.orig/sound/nds32/hda.h 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/sound/nds32/hda.h 2016-04-07 10:20:51.066085821 +0200
+@@ -0,0 +1,106 @@
++// HDA Mode definition
++ #define HDA_MODE 0x80000000
++
++ // HDA CTRL definition
++ #define HDA_CRST_SET 0x00
++ #define HDA_CRST_CLR 0x20
++ #define HDA_CRST_MASK 0x20
++ #define HDA_RST_FCNT_OFS 8
++
++ // HDA LNKST definition
++ #define HDA_COD_ALIVE 0x20000000
++
++ // HDA INTC definition
++ #define HDA_INTC_USOLEN 0x40000
++ #define HDA_INTC_SDIWEN 0x20000
++ #define HDA_INTC_CRINTE 0x10000
++
++ // HDA INTST definition
++ #define HDA_INTST_USOLEN 0x80
++ #define HDA_INTST_SDIWEN 0x40
++ #define HDA_INTST_CRINTE 0x20
++
++ // HDA ICMDST mask & offset
++ #define HDA_IRRADD_MASK 0xf0
++ #define HDA_IRRUNSOL_MASK 0x08
++ #define HDA_IRV_MASK 0x02
++ #define HDA_ICB_MASK 0x01
++ #define HDA_IRRADD_OFFSET 4
++ #define HDA_IRRUNSOL_OFFSET 3
++ #define HDA_IRV_OFFSET 1
++ #define HDA_ICB_OFFSET 0
++ //HDA OSDC/ISDC bit offset
++ #define HDA_SDC_STNUM_OFFSET 28
++ #define HDA_SDC_SRUN_OFFSET 15
++ #define HDA_SDC_BASE_OFFSET 14
++ #define HDA_SDC_MULT_OFFSET 11
++ #define HDA_SDC_DIV_OFFSET 8
++ #define HDA_SDC_BITS_OFFSET 4
++ #define HDA_SDC_CHAN_OFFSET 0
++
++ // HDA Codec CMD
++ #define HDA_COD_DEVADDR 0x00000000
++ #define HDA_ROOT_NODE 0x00000000
++ #define HDA_AUDIO_NODE 0x00100000
++ #define HDA_OUTCOV_NODE 0x00200000
++ //#define HDA_INCOV_NODE 0x0FF00000
++ #define HDA_INCOV_NODE 0x00800000 //kane, for real CODEC node mapping
++ #define HDA_CMD_FGRST 0x0007FF00
++ #define HDA_CMD_GETVID 0x000F0000
++ #define HDA_CMD_SUBNCNT 0x000F0004
++ #define HDA_CMD_FGTYPE 0x000F0005
++ #define HDA_CMD_AUDIOWCAP 0x000F0009
++ #define HDA_CMD_SETCVTSTR 0x00070600
++ #define HDA_CMD_GETCVTSTR 0x000F0600
++ #define HDA_CMD_SETCVTFMT 0x00020000
++ #define HDA_CMD_GETCVTFMT 0x000A0000
++ #define HDA_CMD_SETPROCST 0x00070300
++ #define HDA_CMD_TRIGUNSOL 0x00070400
++ //HDA Codec Resp
++ #define HDA_RESP_ZERO_VAL 0x00000000
++ #define HDA_RESP_EXP_VID 0x10ec0888
++ #define HDA_RSP_NODNUM_MSK 0xff0000
++ #define HDA_RSP_NODCNT_MSK 0x0000ff
++ #define HDA_RSP_NODNUM_OFS 16
++ #define HDA_RSP_NODCNT_OFS 0
++ #define HDA_RSP_FGNTYPE_MSK 0xff
++ #define HDA_RSP_FGNUSCAP_MSK 0x100
++ #define HDA_RSP_FGNTYPE_OFS 0
++ #define HDA_RSP_FGNUSCAP_OFS 8
++ #define HDA_RSP_AWCTYPE_MSK 0xf00000
++ #define HDA_RSP_AWCUSCAP_MSK 0x000080
++ #define HDA_RSP_AWCSTE_MSK 0x000001
++ #define HDA_RSP_AWCTYPE_OFS 20
++ #define HDA_RSP_AWCUSCAP_OFS 7
++ #define HDA_RSP_AWCSTE_OFS 0
++ #define HDA_RSP_CVTCHA_MSK 0x00
++ #define HDA_RSP_CVTSTR_MSK 0xf0
++ #define HDA_RSP_FMTTYPE_MSK 0x8000
++ #define HDA_RSP_FMTBASE_MSK 0x4000
++ #define HDA_RSP_FMTMULT_MSK 0x3800
++ #define HDA_RSP_FMTDIV_MSK 0x0700
++ #define HDA_RSP_FMTBITS_MSK 0x0070
++ #define HDA_RSP_FMTCHNUM_MSK 0x000f
++ //HDA Func Group definition
++ #define HDA_FG_AUDIO 0x1
++ // HDA Audio Widiget definition
++ #define HDA_AWC_INPUT 0x1
++ #define HDA_AWC_OUTPUT 0x0
++ #define HDA_AWC_MONO 0x0
++ #define HDA_AWC_STEREO 0x1
++ // HDA Converter Format definition
++ #define HDA_FMT_TYPE_OFS 15
++ #define HDA_FMT_BASE_OFS 14
++ #define HDA_FMT_MULT_OFS 11
++ #define HDA_FMT_DIV_OFS 8
++ #define HDA_FMT_BITS_OFS 4
++ #define HDA_FMT_CHNUM_OFS 0
++ // HDA Coverter Stream definition
++ #define HDA_STR_STR_OFS 4
++ #define HDA_STR_CHA_OFS 0
++ // HDA IOSDC definition
++ #define HDA_IN_STR 0
++ #define HDA_OUT_STR 1
++ #define HDA_STR_STOP 0
++ #define HDA_STR_RUN 1
++
+diff -Nur linux-3.4.110.orig/sound/nds32/Kconfig linux-3.4.110/sound/nds32/Kconfig
+--- linux-3.4.110.orig/sound/nds32/Kconfig 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/sound/nds32/Kconfig 2016-04-07 10:20:51.066085821 +0200
+@@ -0,0 +1,22 @@
++menu "ALSA NDS32 devices"
++ depends on SND!=n && NDS32
++
++config SND_FTSSP010
++ tristate "Faraday FTSSP010 audio Driver"
++ depends on SND && NDS32
++ select SND_PCM
++# select SND_AC97_CODEC
++
++choice
++ prompt "AC97/I2S/HDA selection"
++ depends on SND_FTSSP010
++ default SND_FTSSP010_AC97
++config SND_FTSSP010_AC97
++ bool "AC97"
++config SND_FTSSP010_I2S
++ bool "I2S"
++config SND_FTSSP010_HDA
++ bool "HDA"
++endchoice
++endmenu
++
+diff -Nur linux-3.4.110.orig/sound/nds32/Makefile linux-3.4.110/sound/nds32/Makefile
+--- linux-3.4.110.orig/sound/nds32/Makefile 1970-01-01 01:00:00.000000000 +0100
++++ linux-3.4.110/sound/nds32/Makefile 2016-04-07 10:20:51.066085821 +0200
+@@ -0,0 +1,10 @@
++ifeq ($(CONFIG_SND_FTSSP010_AC97),y)
++snd-ftssp010-objs := FTSSP010_ALSA.o FTSSP010_lib.o
++endif
++ifeq ($(CONFIG_SND_FTSSP010_I2S),y)
++snd-ftssp010-objs := FTSSP010_ALSA.o FTSSP010_lib.o
++endif
++ifeq ($(CONFIG_SND_FTSSP010_HDA),y)
++snd-ftssp010-objs := FTSSP010_HDA.o FTSSP010_HDA_lib.o
++endif
++obj-$(CONFIG_SND_FTSSP010) += snd-ftssp010.o
diff --git a/target/nds32/Makefile b/target/nds32/Makefile
index 3d8f8d42b..146491b3b 100644
--- a/target/nds32/Makefile
+++ b/target/nds32/Makefile
@@ -6,6 +6,9 @@ include $(ADK_TOPDIR)/mk/kernel-build.mk
include $(ADK_TOPDIR)/mk/image.mk
KERNEL:=$(LINUX_DIR)/$(ADK_TARGET_KERNEL)
+ifeq ($(ADK_TARGET_KERNEL_IMAGE),y)
+KERNEL:=$(LINUX_DIR)/arch/nds32/boot/Image
+endif
# target helper text
ifeq ($(ADK_TARGET_FS),archive)
diff --git a/target/nds32/kernel/andes-ag101p b/target/nds32/kernel/andes-ag101p
new file mode 100644
index 000000000..2f9a5e3c8
--- /dev/null
+++ b/target/nds32/kernel/andes-ag101p
@@ -0,0 +1,5 @@
+CONFIG_NDS32=y
+CONFIG_PLATFORM_AHBDMA=y
+CONFIG_PLATFORM_APBDMA=y
+CONFIG_UART_CLK=14745600
+CONFIG_DEBUG_USER=y
diff --git a/target/nds32/kernel/generic-nds32 b/target/nds32/kernel/generic-nds32
new file mode 100644
index 000000000..3d59624f7
--- /dev/null
+++ b/target/nds32/kernel/generic-nds32
@@ -0,0 +1,2 @@
+CONFIG_NDS32=y
+CONFIG_EARLY_PRINTK=y
diff --git a/target/nds32/systems/andes-ag101p b/target/nds32/systems/andes-ag101p
new file mode 100644
index 000000000..31d35a479
--- /dev/null
+++ b/target/nds32/systems/andes-ag101p
@@ -0,0 +1,9 @@
+config ADK_TARGET_SYSTEM_ANDES_AG101P
+ bool "Andes Technology AG101P"
+ depends on ADK_TARGET_LITTLE_ENDIAN
+ select ADK_TARGET_WITH_SERIAL
+ select ADK_TARGET_WITH_NET
+ select ADK_TARGET_WITH_NETDEVICE
+ select ADK_TARGET_KERNEL_IMAGE
+ help
+ Andes Technology AG101P (ADP-XC7KFF676)
diff --git a/target/nds32/uclibc-ng.config b/target/nds32/uclibc-ng.config
new file mode 100644
index 000000000..91d933139
--- /dev/null
+++ b/target/nds32/uclibc-ng.config
@@ -0,0 +1,248 @@
+#
+# Automatically generated file; DO NOT EDIT.
+# uClibc-ng 1.0.14 C Library Configuration
+#
+# TARGET_alpha is not set
+# TARGET_arc is not set
+# TARGET_arm is not set
+# TARGET_avr32 is not set
+# TARGET_bfin is not set
+# TARGET_c6x is not set
+# TARGET_cris is not set
+# TARGET_frv is not set
+# TARGET_h8300 is not set
+# TARGET_hppa is not set
+# TARGET_i386 is not set
+# TARGET_ia64 is not set
+# TARGET_lm32 is not set
+# TARGET_m68k is not set
+# TARGET_metag is not set
+# TARGET_microblaze is not set
+# TARGET_mips is not set
+TARGET_nds32=y
+# TARGET_nios2 is not set
+# TARGET_or1k is not set
+# TARGET_powerpc is not set
+# TARGET_sh is not set
+# TARGET_sparc is not set
+# TARGET_x86_64 is not set
+# TARGET_xtensa is not set
+
+#
+# Target Architecture Features and Options
+#
+TARGET_ARCH="nds32"
+FORCE_OPTIONS_FOR_ARCH=y
+CONFIG_NDS32_PAGE_SIZE_4K=y
+# CONFIG_NDS32_PAGE_SIZE_8K is not set
+TARGET_SUBARCH=""
+
+#
+# Using ELF file format
+#
+ARCH_HAS_DEPRECATED_SYSCALLS=y
+ARCH_ANY_ENDIAN=y
+ARCH_LITTLE_ENDIAN=y
+# ARCH_WANTS_BIG_ENDIAN is not set
+ARCH_WANTS_LITTLE_ENDIAN=y
+ARCH_HAS_MMU=y
+ARCH_USE_MMU=y
+UCLIBC_HAS_FLOATS=y
+UCLIBC_HAS_FPU=y
+DO_C99_MATH=y
+# DO_XSI_MATH is not set
+# UCLIBC_HAS_FENV is not set
+KERNEL_HEADERS=""
+HAVE_DOT_CONFIG=y
+
+#
+# General Library Settings
+#
+DOPIC=y
+HAVE_SHARED=y
+# FORCE_SHAREABLE_TEXT_SEGMENTS is not set
+LDSO_LDD_SUPPORT=y
+LDSO_CACHE_SUPPORT=y
+# LDSO_PRELOAD_ENV_SUPPORT is not set
+# LDSO_PRELOAD_FILE_SUPPORT is not set
+LDSO_BASE_FILENAME="ld.so"
+# LDSO_STANDALONE_SUPPORT is not set
+# LDSO_PRELINK_SUPPORT is not set
+# UCLIBC_STATIC_LDCONFIG is not set
+LDSO_RUNPATH=y
+LDSO_RUNPATH_OF_EXECUTABLE=y
+LDSO_SAFE_RUNPATH=y
+LDSO_SEARCH_INTERP_PATH=y
+LDSO_LD_LIBRARY_PATH=y
+LDSO_NO_CLEANUP=y
+UCLIBC_CTOR_DTOR=y
+# LDSO_GNU_HASH_SUPPORT is not set
+# HAS_NO_THREADS is not set
+UCLIBC_HAS_LINUXTHREADS=y
+UCLIBC_HAS_THREADS=y
+PTHREADS_DEBUG_SUPPORT=y
+UCLIBC_HAS_SYSLOG=y
+UCLIBC_HAS_LFS=y
+MALLOC=y
+# MALLOC_SIMPLE is not set
+# MALLOC_STANDARD is not set
+MALLOC_GLIBC_COMPAT=y
+# UCLIBC_HAS_OBSTACK is not set
+UCLIBC_DYNAMIC_ATEXIT=y
+COMPAT_ATEXIT=y
+UCLIBC_HAS_UTMPX=y
+UCLIBC_HAS_UTMP=y
+UCLIBC_SUSV2_LEGACY=y
+UCLIBC_SUSV3_LEGACY=y
+# UCLIBC_SUSV3_LEGACY_MACROS is not set
+UCLIBC_SUSV4_LEGACY=y
+# UCLIBC_STRICT_HEADERS is not set
+# UCLIBC_HAS_STUBS is not set
+UCLIBC_HAS_SHADOW=y
+UCLIBC_HAS_PROGRAM_INVOCATION_NAME=y
+UCLIBC_HAS___PROGNAME=y
+UCLIBC_HAS_PTY=y
+ASSUME_DEVPTS=y
+UNIX98PTY_ONLY=y
+UCLIBC_HAS_GETPT=y
+UCLIBC_HAS_LIBUTIL=y
+UCLIBC_HAS_TM_EXTENSIONS=y
+UCLIBC_HAS_TZ_CACHING=y
+UCLIBC_HAS_TZ_FILE=y
+UCLIBC_HAS_TZ_FILE_READ_MANY=y
+UCLIBC_TZ_FILE_PATH="/etc/TZ"
+UCLIBC_FALLBACK_TO_ETC_LOCALTIME=y
+
+#
+# Advanced Library Settings
+#
+UCLIBC_PWD_BUFFER_SIZE=256
+UCLIBC_GRP_BUFFER_SIZE=256
+
+#
+# Support various families of functions
+#
+UCLIBC_LINUX_MODULE_26=y
+# UCLIBC_LINUX_MODULE_24 is not set
+UCLIBC_LINUX_SPECIFIC=y
+UCLIBC_HAS_GNU_ERROR=y
+UCLIBC_BSD_SPECIFIC=y
+UCLIBC_HAS_BSD_ERR=y
+UCLIBC_HAS_OBSOLETE_BSD_SIGNAL=y
+# UCLIBC_HAS_OBSOLETE_SYSV_SIGNAL is not set
+# UCLIBC_NTP_LEGACY is not set
+UCLIBC_SV4_DEPRECATED=y
+UCLIBC_HAS_REALTIME=y
+UCLIBC_HAS_ADVANCED_REALTIME=y
+UCLIBC_HAS_EPOLL=y
+UCLIBC_HAS_XATTR=y
+# UCLIBC_HAS_PROFILING is not set
+UCLIBC_HAS_CRYPT_IMPL=y
+UCLIBC_HAS_SHA256_CRYPT_IMPL=y
+# UCLIBC_HAS_SHA512_CRYPT_IMPL is not set
+UCLIBC_HAS_CRYPT=y
+UCLIBC_HAS_NETWORK_SUPPORT=y
+UCLIBC_HAS_SOCKET=y
+UCLIBC_HAS_IPV4=y
+UCLIBC_HAS_IPV6=y
+# UCLIBC_HAS_RPC is not set
+UCLIBC_USE_NETLINK=y
+UCLIBC_SUPPORT_AI_ADDRCONFIG=y
+UCLIBC_HAS_BSD_RES_CLOSE=y
+UCLIBC_HAS_COMPAT_RES_STATE=y
+# UCLIBC_HAS_EXTRA_COMPAT_RES_STATE is not set
+UCLIBC_HAS_RESOLVER_SUPPORT=y
+UCLIBC_HAS_LIBRESOLV_STUB=y
+UCLIBC_HAS_LIBNSL_STUB=y
+
+#
+# String and Stdio Support
+#
+UCLIBC_HAS_STRING_GENERIC_OPT=y
+UCLIBC_HAS_STRING_ARCH_OPT=y
+UCLIBC_HAS_CTYPE_TABLES=y
+UCLIBC_HAS_CTYPE_SIGNED=y
+# UCLIBC_HAS_CTYPE_UNSAFE is not set
+UCLIBC_HAS_CTYPE_CHECKED=y
+# UCLIBC_HAS_CTYPE_ENFORCED is not set
+UCLIBC_HAS_WCHAR=y
+# UCLIBC_HAS_LOCALE is not set
+UCLIBC_HAS_HEXADECIMAL_FLOATS=y
+UCLIBC_HAS_GLIBC_CUSTOM_PRINTF=y
+UCLIBC_PRINTF_SCANF_POSITIONAL_ARGS=9
+# UCLIBC_HAS_STDIO_BUFSIZ_256 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_512 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_1024 is not set
+# UCLIBC_HAS_STDIO_BUFSIZ_2048 is not set
+UCLIBC_HAS_STDIO_BUFSIZ_4096=y
+# UCLIBC_HAS_STDIO_BUFSIZ_8192 is not set
+UCLIBC_HAS_STDIO_BUILTIN_BUFFER_NONE=y
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_4 is not set
+# UCLIBC_HAS_STDIO_BUILTIN_BUFFER_8 is not set
+# UCLIBC_HAS_STDIO_SHUTDOWN_ON_ABORT is not set
+UCLIBC_HAS_STDIO_GETC_MACRO=y
+UCLIBC_HAS_STDIO_PUTC_MACRO=y
+UCLIBC_HAS_STDIO_AUTO_RW_TRANSITION=y
+# UCLIBC_HAS_FOPEN_LARGEFILE_MODE is not set
+UCLIBC_HAS_FOPEN_EXCLUSIVE_MODE=y
+# UCLIBC_HAS_FOPEN_CLOSEEXEC_MODE is not set
+UCLIBC_HAS_GLIBC_CUSTOM_STREAMS=y
+UCLIBC_HAS_PRINTF_M_SPEC=y
+UCLIBC_HAS_ERRNO_MESSAGES=y
+# UCLIBC_HAS_SYS_ERRLIST is not set
+UCLIBC_HAS_SIGNUM_MESSAGES=y
+# UCLIBC_HAS_SYS_SIGLIST is not set
+UCLIBC_HAS_GNU_GETOPT=y
+UCLIBC_HAS_GETOPT_LONG=y
+UCLIBC_HAS_GNU_GETSUBOPT=y
+UCLIBC_HAS_ARGP=y
+
+#
+# Big and Tall
+#
+UCLIBC_HAS_REGEX=y
+# UCLIBC_HAS_REGEX_OLD is not set
+UCLIBC_HAS_FNMATCH=y
+# UCLIBC_HAS_FNMATCH_OLD is not set
+UCLIBC_HAS_WORDEXP=y
+UCLIBC_HAS_NFTW=y
+UCLIBC_HAS_FTW=y
+UCLIBC_HAS_FTS=y
+UCLIBC_HAS_GLOB=y
+UCLIBC_HAS_GNU_GLOB=y
+
+#
+# Library Installation Options
+#
+RUNTIME_PREFIX="/"
+DEVEL_PREFIX="/usr/"
+MULTILIB_DIR="lib"
+HARDWIRED_ABSPATH=y
+
+#
+# Security options
+#
+# UCLIBC_BUILD_PIE is not set
+UCLIBC_HAS_ARC4RANDOM=y
+# ARC4RANDOM_USES_NODEV is not set
+# UCLIBC_HAS_SSP is not set
+UCLIBC_BUILD_RELRO=y
+UCLIBC_BUILD_NOW=y
+UCLIBC_BUILD_NOEXECSTACK=y
+
+#
+# Development/debugging options
+#
+CROSS_COMPILER_PREFIX=""
+UCLIBC_EXTRA_CFLAGS=""
+# DODEBUG is not set
+# DODEBUG_PT is not set
+# DOSTRIP is not set
+# DOASSERTS is not set
+# SUPPORT_LD_DEBUG is not set
+# SUPPORT_LD_DEBUG_EARLY is not set
+# UCLIBC_MALLOC_DEBUGGING is not set
+# UCLIBC_HAS_BACKTRACE is not set
+WARNINGS="-Wall"
+# EXTRA_WARNINGS is not set
+# DOMULTI is not set