summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--classes/nylon-image.bbclass16
-rw-r--r--conf/distro/debianslug.conf14
-rw-r--r--conf/distro/nylon.conf17
-rw-r--r--conf/distro/openslug.conf14
-rw-r--r--conf/distro/preferred-gpe-versions-2.7.inc6
-rw-r--r--conf/distro/slugos-bag.conf4
-rw-r--r--conf/distro/slugos-bau.conf4
-rw-r--r--conf/distro/slugos-btu.conf4
-rw-r--r--conf/distro/slugos-lag.conf15
-rw-r--r--conf/distro/slugos-lau.conf6
-rw-r--r--conf/distro/slugos-ltu.conf14
-rw-r--r--conf/distro/slugos-packages.conf6
-rw-r--r--conf/distro/slugos.conf12
-rw-r--r--conf/distro/ucslugc.conf4
-rw-r--r--conf/machine/ep93xx.conf18
-rw-r--r--conf/machine/include/ixp4xx.conf2
-rw-r--r--packages/chillispot/chillispot_0.98.bb1
-rw-r--r--packages/chillispot/chillispot_1.0RC3.bb1
-rw-r--r--packages/cups/cups_1.1.23.bb34
-rw-r--r--packages/e17/e-wm_0.16.999.023.bb12
-rw-r--r--packages/gcc/gcc3-build.inc5
-rw-r--r--packages/glibc/glibc_2.2.5.bb2
-rw-r--r--packages/gnome/gnome-cups-manager_0.31.bb14
-rw-r--r--packages/gnome/libgnomecups_0.2.2.bb12
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth-0.36.3/segfault.patch30
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth-0.37/change-sdp-to-bluetooth.patch12
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth-0.37/dbus-service-name.patch47
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth-0.37/hciattach-path.patch11
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth-0.37/icon-resize.patch43
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth_0.36.3.bb15
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth_0.37.bb17
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth_0.38.bb13
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth_0.43.bb15
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth_0.44.bb15
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth_0.51.bb18
-rw-r--r--packages/gpe-bluetooth/gpe-bluetooth_0.52.bb14
-rw-r--r--packages/gpe-calendar/gpe-calendar-0.61/remove-render.patch10
-rw-r--r--packages/gpe-calendar/gpe-calendar_0.56.bb9
-rw-r--r--packages/gpe-calendar/gpe-calendar_0.58.bb10
-rw-r--r--packages/gpe-calendar/gpe-calendar_0.59.bb10
-rw-r--r--packages/gpe-calendar/gpe-calendar_0.61.bb11
-rw-r--r--packages/gpe-calendar/gpe-calendar_0.63.bb10
-rw-r--r--packages/gpe-calendar/gpe-calendar_0.64.bb10
-rw-r--r--packages/gpe-calendar/gpe-calendar_0.65.bb11
-rw-r--r--packages/gpe-calendar/gpe-calendar_0.70.bb15
-rw-r--r--packages/initscripts/initscripts-1.0/slugos/checkroot.sh2
-rw-r--r--packages/initscripts/initscripts-slugos_1.0.bb2
-rw-r--r--packages/libao/libao-plugin-alsa_0.8.6.bb30
-rw-r--r--packages/libeventdb/libeventdb_0.15.bb24
-rw-r--r--packages/libeventdb/libeventdb_0.19.bb19
-rw-r--r--packages/libgpewidget/files/.mtn2git_empty (renamed from packages/gpe-bluetooth/gpe-bluetooth-0.36.3/.mtn2git_empty)0
-rw-r--r--packages/libgpewidget/files/pkgconfig.patch11
-rw-r--r--packages/libgpewidget/libgpewidget-0.100/fixdoc.patch10
-rw-r--r--packages/libgpewidget/libgpewidget-0.99/doc.patch15
-rw-r--r--packages/libgpewidget/libgpewidget_0.100.bb21
-rw-r--r--packages/libgpewidget/libgpewidget_0.109.bb30
-rw-r--r--packages/libgpewidget/libgpewidget_0.95.bb25
-rw-r--r--packages/libgpewidget/libgpewidget_0.96.bb25
-rw-r--r--packages/libgpewidget/libgpewidget_0.97.bb25
-rw-r--r--packages/libgpewidget/libgpewidget_0.99.bb20
-rw-r--r--packages/libsexy/libsexy_0.1.6.bb17
-rw-r--r--packages/linux/ep93xx-kernel/.mtn2git_empty (renamed from packages/gpe-bluetooth/gpe-bluetooth-0.37/.mtn2git_empty)0
-rw-r--r--packages/linux/ep93xx-kernel/defconfig920
-rw-r--r--packages/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff43746
-rw-r--r--packages/linux/ep93xx-kernel_2.6.15.bb19
-rw-r--r--packages/linux/linux-mtx-1-2.4.27/23-mtx-1_watchdog_autotrigger.patch98
-rw-r--r--packages/linux/linux-mtx-1-2.4.27/24-mtx-1_sysbtn.patch257
-rw-r--r--packages/linux/linux-mtx-1-2.4.27/25-mtx-sio2.diff12
-rw-r--r--packages/linux/linux-mtx-1-2.4.27/26-usbd-amd-pb1x00-kit-23may2003-update.diff130
-rw-r--r--packages/linux/linux-mtx-1-2.4.27/27-usbd-amd-pb1x00-kit-23may2003-usbd.diff15816
-rw-r--r--packages/linux/linux-mtx-1-2.4.27/29-au1000-pci-config-clear-errors.diff15
-rw-r--r--packages/linux/linux-mtx-1-2.4.27/defconfig-mtx-194
-rw-r--r--packages/linux/linux-mtx-1_2.4.24.bb2
-rw-r--r--packages/linux/linux-mtx-1_2.4.27.bb19
-rwxr-xr-xpackages/lirc/files/lircexec.init4
-rw-r--r--packages/lirc/lirc-modules_0.8.0.bb2
-rw-r--r--packages/lirc/lirc_0.8.0.bb5
-rw-r--r--packages/matchbox-panel/matchbox-panel-0.9.2/system-monitor-crash-fix.patch72
-rw-r--r--packages/matchbox-panel/matchbox-panel_0.9.2.bb2
-rw-r--r--packages/meta/nylon-image-base.bb5
-rw-r--r--packages/meta/nylon-image-standard.bb7
-rw-r--r--packages/meta/slugos-image.bb6
-rw-r--r--packages/meta/slugos-packages.bb3
-rw-r--r--packages/mozilla/firefox-1.0.7/.mtn2git_empty (renamed from packages/gpe-calendar/gpe-calendar-0.61/.mtn2git_empty)0
-rw-r--r--packages/mozilla/firefox-1.0.7/firefox-cc-fix.patch21
-rw-r--r--packages/mozilla/firefox-1.0.7/jsautocfg.h52
-rw-r--r--packages/mozilla/firefox-1.0.7/mozconfig53
-rw-r--r--packages/musicpd/mpd/mpd.init32
-rw-r--r--packages/nylon/nylon-scripts_cvs.bb1
-rw-r--r--packages/nylon/nylon-statistics.bb1
-rw-r--r--packages/nylon/simple-firewall.bb17
-rw-r--r--packages/radlib/.mtn2git_empty (renamed from packages/libgpewidget/libgpewidget-0.100/.mtn2git_empty)0
-rw-r--r--packages/radlib/radlib-common.inc58
-rw-r--r--packages/radlib/radlib-mysql.inc6
-rw-r--r--packages/radlib/radlib-mysql_2.6.2.bb3
-rw-r--r--packages/radlib/radlib.inc1
-rw-r--r--packages/radlib/radlib_2.6.2.bb3
-rw-r--r--packages/slugos-init/files/boot/disk2
-rw-r--r--packages/slugos-init/slugos-init_0.10.bb2
-rw-r--r--packages/usbutils/usbutils_0.70.bb3
-rw-r--r--packages/vpnc/files/default.conf19
-rw-r--r--packages/vpnc/files/vpnc-script.patch30
-rw-r--r--packages/vpnc/vpnc_0.3.3.bb24
-rw-r--r--packages/wview/.mtn2git_empty (renamed from packages/libgpewidget/libgpewidget-0.99/.mtn2git_empty)0
-rw-r--r--packages/wview/wview-common.inc39
-rw-r--r--packages/wview/wview-mysql.inc7
-rw-r--r--packages/wview/wview-sim-mysql_3.1.3.bb3
-rw-r--r--packages/wview/wview-sim_3.1.3.bb4
-rw-r--r--packages/wview/wview-vpro-mysql_3.1.3.bb3
-rw-r--r--packages/wview/wview-vpro_3.1.3.bb4
-rw-r--r--packages/wview/wview-wxt510-mysql_3.1.3.bb3
-rw-r--r--packages/wview/wview-wxt510_3.1.3.bb4
-rw-r--r--packages/wview/wview.inc2
113 files changed, 61913 insertions, 577 deletions
diff --git a/classes/nylon-image.bbclass b/classes/nylon-image.bbclass
new file mode 100644
index 0000000000..8517c033e9
--- /dev/null
+++ b/classes/nylon-image.bbclass
@@ -0,0 +1,16 @@
+# we dont need the kernel in the image
+ROOTFS_POSTPROCESS_COMMAND = "rm -f ${IMAGE_ROOTFS}/tmp/zImage*"
+
+# create a tar.gz (.imgz) file containing the filesystem and the kernel
+nylon_create_imgz() {
+ rm -rf ${DEPLOY_DIR_IMAGE}/tmp
+ rm -f ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.imgz
+ install -d ${DEPLOY_DIR_IMAGE}/tmp
+
+ cp ${DEPLOY_DIR_IMAGE}/${KERNEL_IMAGE_NAME}.flash.bin ${DEPLOY_DIR_IMAGE}/tmp/zImage.flash
+ cp ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.rootfs.${type} ${DEPLOY_DIR_IMAGE}/tmp/rootfs.${type}
+ ( cd ${DEPLOY_DIR_IMAGE}/tmp; tar cvzf ${DEPLOY_DIR_IMAGE}/${IMAGE_NAME}.imgz * )
+ rm -r ${DEPLOY_DIR_IMAGE}/tmp
+}
+
+IMAGE_POSTPROCESS_COMMAND += "nylon_create_imgz;"
diff --git a/conf/distro/debianslug.conf b/conf/distro/debianslug.conf
index 16c54c77da..c5c9f6868c 100644
--- a/conf/distro/debianslug.conf
+++ b/conf/distro/debianslug.conf
@@ -6,8 +6,8 @@
# STANDARD DebianSlug DEFINITIONS
#----------------------------------------------------------------------------------
DISTRO_NAME = "DebianSlug"
-DISTRO_VERSION = "3.2-beta"
-DISTRO_FEED = "unstable"
+# DISTRO_VERSION = "${SLUGOS_VERSION}${DISTRO_REVISION}-${DISTRO_TYPE}"
+# DISTRO_FEED = "unstable"
DISTRO_TYPE = "beta"
SLUGOS_IMAGENAME = "debianslug"
SLUGOS_IMAGESEX = "little-endian"
@@ -21,16 +21,6 @@ SLUGOS_FLASH_IMAGE = "yes"
DEBIANSLUG_EXTRA_BBFILES ?= ""
#----------------------------------------------------------------------------------
-# FEEDS
-# The following lines define where on the internet DebianSlug looks for packages
-# when downloading new packages or updating existing packages. Additional feeds
-# (such as a local feed) can be defined in local.conf
-#----------------------------------------------------------------------------------
-# Add to the user's feeds from local.conf (there may be none)
-FEED_URIS_append += "cross##http://ipkg.nslu2-linux.org/feeds/slugos-lag/cross/${DISTRO_FEED}"
-FEED_URIS_append += "native##http://ipkg.nslu2-linux.org/feeds/slugos-lag/native/${DISTRO_FEED}"
-
-#----------------------------------------------------------------------------------
# FIRMWARE CONFIGURATION
#----------------------------------------------------------------------------------
# EXTRA PACKAGES
diff --git a/conf/distro/nylon.conf b/conf/distro/nylon.conf
index c7fcb83610..a1d81e336f 100644
--- a/conf/distro/nylon.conf
+++ b/conf/distro/nylon.conf
@@ -11,7 +11,7 @@
#
# Bruno Randolf <bruno.randolf@4g-systems.biz>
-INHERIT += "package_ipk debian"
+INHERIT += "package_ipk debian nylon-mirrors"
INHERIT += "linux_modules"
PREFERRED_PROVIDERS += " virtual/${TARGET_PREFIX}gcc-initial:gcc-cross-initial"
@@ -37,11 +37,18 @@ PREFERRED_VERSION_usbutils = "0.11"
# usually overrrided from local.conf
NYLON_RELEASE = "unstable"
-# use meshcub.org mirrors
+# use meshcub.org mirrors for CVS sources
CVS_TARBALL_STASH = "http://meshcube.org/nylon/${NYLON_RELEASE}/sources/"
-INHERIT += "nylon-mirrors"
-export FEED_URIS="nylon##http://meshcube.org/nylon/${NYLON_RELEASE}/feed"
+export FEED_URIS = " \
+ nylon##http://meshcube.org/nylon/${NYLON_RELEASE}/feed \
+ nylon-bin##http://meshcube.org/nylon/${NYLON_RELEASE}/binary-feed"
+# image names
+DISTRO_VERSION = "${NYLON_VERSION}"
+BUILDNAME := "${NYLON_VERSION}"
+KERNEL_VERSION = "2.4.27"
+#this does not work: ${@base_read_file('${STAGING_DIR}/${HOST_SYS}/kernel/kernel-abiversion')}
IMAGE_NAME = "${IMAGE_BASENAME}-${MACHINE}_${BUILDNAME}"
-KERNEL_IMAGE_NAME = "kernel-${KV}-${MACHINE}_${BUILDNAME}"
+KERNEL_IMAGE_NAME = "kernel-${KERNEL_VERSION}-${MACHINE}_${BUILDNAME}"
+
diff --git a/conf/distro/openslug.conf b/conf/distro/openslug.conf
index 8c1a16c77f..304cd6dcfa 100644
--- a/conf/distro/openslug.conf
+++ b/conf/distro/openslug.conf
@@ -6,8 +6,8 @@
# STANDARD OpenSlug DEFINITIONS
#----------------------------------------------------------------------------------
DISTRO_NAME = "OpenSlug"
-DISTRO_VERSION = "3.2-beta"
-DISTRO_FEED = "unstable"
+# DISTRO_VERSION = "${SLUGOS_VERSION}${DISTRO_REVISION}-${DISTRO_TYPE}"
+# DISTRO_FEED = "unstable"
DISTRO_TYPE = "beta"
SLUGOS_IMAGENAME = "openslug"
SLUGOS_IMAGESEX = "big-endian"
@@ -21,16 +21,6 @@ SLUGOS_FLASH_IMAGE = "yes"
OPENSLUG_EXTRA_BBFILES ?= ""
#----------------------------------------------------------------------------------
-# FEEDS
-# The following lines define where on the internet OpenSlug looks for packages
-# when downloading new packages or updating existing packages. Additional feeds
-# (such as a local feed) can be defined in local.conf
-#----------------------------------------------------------------------------------
-# Add to the user's feeds from local.conf (there may be none)
-FEED_URIS_append += "cross##http://ipkg.nslu2-linux.org/feeds/slugos-bag/cross/${DISTRO_FEED}"
-FEED_URIS_append += "native##http://ipkg.nslu2-linux.org/feeds/slugos-bag/native/${DISTRO_FEED}"
-
-#----------------------------------------------------------------------------------
# FIRMWARE CONFIGURATION
#----------------------------------------------------------------------------------
# EXTRA PACKAGES
diff --git a/conf/distro/preferred-gpe-versions-2.7.inc b/conf/distro/preferred-gpe-versions-2.7.inc
index dd175d32d4..ea0ab62610 100644
--- a/conf/distro/preferred-gpe-versions-2.7.inc
+++ b/conf/distro/preferred-gpe-versions-2.7.inc
@@ -23,7 +23,7 @@ PREFERRED_VERSION_glib-2.0 ?= "2.6.4"
PREFERRED_VERSION_gtk+ ?= "2.6.10"
PREFERRED_VERSION_pango ?= "1.8.1"
PREFERRED_VERSION_librsvg ?= "2.6.5"
-PREFERRED_VERSION_libgpewidget ?= "0.106"
+PREFERRED_VERSION_libgpewidget ?= "0.109"
PREFERRED_VERSION_libgpepimc ?= "0.5"
PREFERRED_VERSION_libgpevtype ?= "0.14"
PREFERRED_VERSION_libschedule ?= "0.15"
@@ -46,14 +46,14 @@ PREFERRED_VERSION_gpe-login ?= "0.83"
PREFERRED_VERSION_gpe-session-scripts ?= "0.66"
PREFERRED_VERSION_gpe-soundserver ?= "0.4-1"
PREFERRED_VERSION_gpe-todo ?= "0.55"
-PREFERRED_VERSION_gpe-calendar ?= "0.69"
+PREFERRED_VERSION_gpe-calendar ?= "0.70"
PREFERRED_VERSION_gpe-sketchbook ?= "0.2.9"
PREFERRED_VERSION_gpe-contacts ?= "0.43"
PREFERRED_VERSION_gpe-today ?= "0.10"
PREFERRED_VERSION_matchbox-panel-manager ?= "0.1"
PREFERRED_VERSION_dbus ?= "0.23.4"
PREFERRED_VERSION_gpe-beam ?= "0.2.8"
-PREFERRED_VERSION_gpe-bluetooth ?= "0.49"
+PREFERRED_VERSION_gpe-bluetooth ?= "0.51"
PREFERRED_VERSION_gpe-su ?= "0.19"
PREFERRED_VERSION_gpe-conf ?= "0.1.29"
PREFERRED_VERSION_gpe-clock ?= "0.23"
diff --git a/conf/distro/slugos-bag.conf b/conf/distro/slugos-bag.conf
index 3710243dab..037ca09644 100644
--- a/conf/distro/slugos-bag.conf
+++ b/conf/distro/slugos-bag.conf
@@ -6,8 +6,8 @@
# This slugos variant corresponds to OpenSlug
DISTRO_NAME ?= "slugos-bag"
-DISTRO_VERSION ?= "3.2-beta"
-DISTRO_FEED ?= "unstable"
+# DISTRO_VERSION = "${SLUGOS_VERSION}${DISTRO_REVISION}-${DISTRO_TYPE}"
+# DISTRO_FEED ?= "unstable"
DISTRO_TYPE ?= "beta"
ARCH_BYTE_SEX = "be"
diff --git a/conf/distro/slugos-bau.conf b/conf/distro/slugos-bau.conf
index 9a025d1bbd..5f4cb26ba8 100644
--- a/conf/distro/slugos-bau.conf
+++ b/conf/distro/slugos-bau.conf
@@ -7,8 +7,8 @@
# This slugos variant is not supported - there are no nslu2-linux.org
# regular builds and there is no feed.
DISTRO_NAME ?= "slugos-bau"
-DISTRO_VERSION ?= "3.2-beta"
-DISTRO_FEED ?= "unstable"
+# DISTRO_VERSION = "${SLUGOS_VERSION}${DISTRO_REVISION}-${DISTRO_TYPE}"
+# DISTRO_FEED ?= "unstable"
DISTRO_TYPE ?= "alpha"
ARCH_BYTE_SEX = "be"
diff --git a/conf/distro/slugos-btu.conf b/conf/distro/slugos-btu.conf
index 33f5d0a952..fc584d75d9 100644
--- a/conf/distro/slugos-btu.conf
+++ b/conf/distro/slugos-btu.conf
@@ -6,8 +6,8 @@
# This slugos variant corresponds to UcSlugC
DISTRO_NAME ?= "slugos-btu"
-DISTRO_VERSION ?= "3.2-beta"
-DISTRO_FEED ?= "unstable"
+# DISTRO_VERSION = "${SLUGOS_VERSION}${DISTRO_REVISION}-${DISTRO_TYPE}"
+# DISTRO_FEED ?= "unstable"
DISTRO_TYPE ?= "beta"
ARCH_BYTE_SEX = "be"
diff --git a/conf/distro/slugos-lag.conf b/conf/distro/slugos-lag.conf
index ddfeba3c59..f8a0631ef8 100644
--- a/conf/distro/slugos-lag.conf
+++ b/conf/distro/slugos-lag.conf
@@ -2,16 +2,21 @@
#@NAME: SLUGOS-LAG
#@DESCRIPTION: Linux Distribution for the NSLU2
-# This slugos variant is not supported - there are no nslu2-linux.org
-# regular builds and there is no feed.
+# See slugos.conf for an explanation of this file.
+
+# This slugos variant corresponds to DebianSlug
DISTRO_NAME ?= "slugos-lag"
-DISTRO_VERSION ?= "3.2-beta"
-DISTRO_FEED ?= "unstable"
-DISTRO_TYPE ?= "alpha"
+# DISTRO_VERSION = "${SLUGOS_VERSION}${DISTRO_REVISION}-${DISTRO_TYPE}"
+# DISTRO_FEED ?= "unstable"
+DISTRO_TYPE ?= "beta"
ARCH_BYTE_SEX = "le"
ARM_INSTRUCTION_SET = "arm"
TARGET_OS = "linux"
SLUGOS_IMAGESEX ?= "big-endian"
+FEED_URIS_append += "cross##http://ipkg.nslu2-linux.org/feeds/slugos-lag/cross/${DISTRO_FEED}"
+FEED_URIS_append += "native##http://ipkg.nslu2-linux.org/feeds/slugos-lag/native/${DISTRO_FEED}"
+
+
include conf/distro/slugos.conf
diff --git a/conf/distro/slugos-lau.conf b/conf/distro/slugos-lau.conf
index 6dc2c1f77b..6bf60df15f 100644
--- a/conf/distro/slugos-lau.conf
+++ b/conf/distro/slugos-lau.conf
@@ -5,8 +5,8 @@
# This slugos variant is not supported - there are no nslu2-linux.org
# regular builds and there is no feed.
DISTRO_NAME ?= "slugos-lau"
-DISTRO_VERSION ?= "3.2-beta"
-DISTRO_FEED ?= "unstable"
+# DISTRO_VERSION = "${SLUGOS_VERSION}${DISTRO_REVISION}-${DISTRO_TYPE}"
+# DISTRO_FEED ?= "unstable"
DISTRO_TYPE ?= "alpha"
ARCH_BYTE_SEX = "le"
@@ -14,4 +14,6 @@ ARM_INSTRUCTION_SET = "arm"
TARGET_OS = "linux-uclibc"
SLUGOS_IMAGESEX ?= "big-endian"
+# no feeds
+
include conf/distro/slugos.conf
diff --git a/conf/distro/slugos-ltu.conf b/conf/distro/slugos-ltu.conf
index 9e02bd1bb9..dbf444748c 100644
--- a/conf/distro/slugos-ltu.conf
+++ b/conf/distro/slugos-ltu.conf
@@ -2,16 +2,20 @@
#@NAME: SLUGOS-LTU
#@DESCRIPTION: Linux Distribution for the NSLU2
-# This slugos variant is not supported - there are no nslu2-linux.org
-# regular builds and there is no feed.
+# See slugos.conf for an explanation of this file.
+
DISTRO_NAME ?= "slugos-ltu"
-DISTRO_VERSION ?= "3.2-beta"
-DISTRO_FEED ?= "unstable"
-DISTRO_TYPE ?= "alpha"
+# DISTRO_VERSION = "${SLUGOS_VERSION}${DISTRO_REVISION}-${DISTRO_TYPE}"
+# DISTRO_FEED ?= "unstable"
+DISTRO_TYPE ?= "beta"
ARCH_BYTE_SEX = "le"
ARM_INSTRUCTION_SET = "thumb"
TARGET_OS = "linux-uclibc"
SLUGOS_IMAGESEX ?= "big-endian"
+FEED_URIS_append += "cross##http://ipkg.nslu2-linux.org/feeds/slugos-ltu/cross/${DISTRO_FEED}"
+FEED_URIS_append += "native##http://ipkg.nslu2-linux.org/feeds/slugos-ltu/native/${DISTRO_FEED}"
+
+
include conf/distro/slugos.conf
diff --git a/conf/distro/slugos-packages.conf b/conf/distro/slugos-packages.conf
index dc1c711a57..28b85cd57e 100644
--- a/conf/distro/slugos-packages.conf
+++ b/conf/distro/slugos-packages.conf
@@ -27,6 +27,7 @@ ${PKGDIR}/packages/cpio/*.bb \
${PKGDIR}/packages/cron/*.bb \
${PKGDIR}/packages/ctorrent/*.bb \
${PKGDIR}/packages/ctrlproxy/*.bb \
+${PKGDIR}/packages/curl/*.bb \
${PKGDIR}/packages/cvs/*.bb \
${PKGDIR}/packages/cyrus-imapd/*.bb \
${PKGDIR}/packages/cyrus-sasl/*.bb \
@@ -90,6 +91,8 @@ ${PKGDIR}/packages/libaal/*.bb \
${PKGDIR}/packages/libao/*.bb \
${PKGDIR}/packages/libdvb/*.bb \
${PKGDIR}/packages/libexif/*.bb \
+${PKGDIR}/packages/libgcrypt/*.bb \
+${PKGDIR}/packages/libgpg-error/*.bb \
${PKGDIR}/packages/libgphoto2/*.bb \
${PKGDIR}/packages/libgsm/*.bb \
${PKGDIR}/packages/libiconv/*.bb \
@@ -180,6 +183,7 @@ ${PKGDIR}/packages/pwc/*.bb \
${PKGDIR}/packages/python/*.bb \
${PKGDIR}/packages/qc-usb/*.bb \
${PKGDIR}/packages/quilt/*.bb \
+${PKGDIR}/packages/radlib/*.bb \
${PKGDIR}/packages/readline/*.bb \
${PKGDIR}/packages/reiser4progs/*.bb \
${PKGDIR}/packages/reiserfsprogs/*.bb \
@@ -216,11 +220,13 @@ ${PKGDIR}/packages/usbutils/*.bb \
${PKGDIR}/packages/util-linux/*.bb \
${PKGDIR}/packages/vim/*.bb \
${PKGDIR}/packages/vlan/*.bb \
+${PKGDIR}/packages/vpnc/*.bb \
${PKGDIR}/packages/vsftpd/*.bb \
${PKGDIR}/packages/wakelan/*.bb \
${PKGDIR}/packages/wget/*.bb \
${PKGDIR}/packages/wireless-tools/*.bb \
${PKGDIR}/packages/wpa-supplicant/*.bb \
+${PKGDIR}/packages/wview/*.bb \
${PKGDIR}/packages/x11/*.bb \
${PKGDIR}/packages/xau/*.bb \
${PKGDIR}/packages/xdmcp/*.bb \
diff --git a/conf/distro/slugos.conf b/conf/distro/slugos.conf
index 16a5999738..3b094d769d 100644
--- a/conf/distro/slugos.conf
+++ b/conf/distro/slugos.conf
@@ -33,10 +33,16 @@
# The following must be set in the top level distro file:
#
#DISTRO_NAME
-#DISTRO_VERSION
-#DISTRO_FEED
#DISTRO_TYPE
+# The following may be overridden to make sub-versions
+SLUGOS_VERSION = "3.6"
+DISTRO_REVISION ?= ""
+DISTRO_VERSION ?= "${SLUGOS_VERSION}${DISTRO_REVISION}-${DISTRO_TYPE}"
+# For release (only):
+# DISTRO_FEED ?= "${SLUGOS_VERSION}-${DISTRO_TYPE}"
+DISTRO_FEED ?= "unstable"
+
# The following must also be set, they define the basic format of the build
#
#ARCH_BYTE_SEX "be" or "le"
@@ -50,8 +56,6 @@ USE_NLS ?= "no"
# To make errors easier to identify:
DISTRO_NAME ?= "INVALID-${ARCH_BYTE_SEX}-${ARM_INSTRUCTION_SET}-${TARGET_OS}"
-DISTRO_VERSION ?= "INVALID"
-DISTRO_FEED ?= "INVALID"
DISTRO_TYPE ?= "INVALID"
# The following must not be changed.
diff --git a/conf/distro/ucslugc.conf b/conf/distro/ucslugc.conf
index 45daeb6632..24ef6e6c33 100644
--- a/conf/distro/ucslugc.conf
+++ b/conf/distro/ucslugc.conf
@@ -4,8 +4,8 @@
# This is SLUGOS-BTU with a different name...
DISTRO_NAME = "UcSlugC"
-DISTRO_VERSION = "3.2-beta"
-DISTRO_FEED = "unstable"
+# DISTRO_VERSION = "${SLUGOS_VERSION}${DISTRO_REVISION}-${DISTRO_TYPE}"
+# DISTRO_FEED = "unstable"
DISTRO_TYPE = "beta"
SLUGOS_IMAGENAME = "ucslugc"
SLUGOS_IMAGESEX = "big-endian"
diff --git a/conf/machine/ep93xx.conf b/conf/machine/ep93xx.conf
new file mode 100644
index 0000000000..7eed2b3748
--- /dev/null
+++ b/conf/machine/ep93xx.conf
@@ -0,0 +1,18 @@
+#@TYPE: Machine
+#@Name: Cirrus Logic EP-93xx Development Platform
+#@DESCRIPTION: Machine configuration for Cirrus Logic EP-93xx Development Platform
+
+TARGET_ARCH = "arm"
+
+IPKG_ARCHS = "all arm armv5te ${MACHINE}"
+
+PREFERRED_PROVIDER_virtual/kernel = "${MACHINE}-kernel"
+
+
+# used by sysvinit_2
+SERIAL_CONSOLE = "115200 ttyS0"
+
+# used by some images
+ROOT_FLASH_SIZE = "8"
+
+
diff --git a/conf/machine/include/ixp4xx.conf b/conf/machine/include/ixp4xx.conf
index 7239d59076..639bf4a74e 100644
--- a/conf/machine/include/ixp4xx.conf
+++ b/conf/machine/include/ixp4xx.conf
@@ -161,7 +161,7 @@ SRCDATE_irssi ?= "20050930"
CVS_TARBALL_STASH = "http://sources.nslu2-linux.org/sources/"
INHERIT += "nslu2-mirrors"
-PREFERRED_VERSION_ipkg ?= "0.99.155"
+PREFERRED_VERSION_ipkg ?= "0.99.154"
PREFERRED_VERSION_ipkg-native ?= "0.99.154"
#-------------------------------------------------------------------------------
diff --git a/packages/chillispot/chillispot_0.98.bb b/packages/chillispot/chillispot_0.98.bb
index f3ebc90ee5..662d7eab9c 100644
--- a/packages/chillispot/chillispot_0.98.bb
+++ b/packages/chillispot/chillispot_0.98.bb
@@ -5,6 +5,7 @@ LICENSE = "GPL"
PR = "r1"
SRC_URI = "http://www.chillispot.org/download/chillispot-${PV}.tar.gz \
+ file://no-ansi.patch;patch=1 \
file://init"
RRECOMMENDS = "kernel-module-tun"
diff --git a/packages/chillispot/chillispot_1.0RC3.bb b/packages/chillispot/chillispot_1.0RC3.bb
index 3e52abd914..1012f4acbc 100644
--- a/packages/chillispot/chillispot_1.0RC3.bb
+++ b/packages/chillispot/chillispot_1.0RC3.bb
@@ -3,6 +3,7 @@ HOMEPAGE = "http://www.chillispot.org/"
MAINTAINER = "Bruno Randolf <bruno.randolf@4g-systems.biz>"
LICENSE = "GPL"
SRC_URI = "http://www.chillispot.org/download/chillispot-${PV}.tar.gz \
+ file://no-ansi.patch;patch=1 \
file://init"
RDEPENDS = "kernel-module-tun"
diff --git a/packages/cups/cups_1.1.23.bb b/packages/cups/cups_1.1.23.bb
new file mode 100644
index 0000000000..9094bb9dff
--- /dev/null
+++ b/packages/cups/cups_1.1.23.bb
@@ -0,0 +1,34 @@
+DEPENDS = "openssl jpeg libpng zlib"
+DESCRIPTION = "An Internet printing system for Unix."
+SECTION = "console/utils"
+LICENSE = "GPL LGPL"
+
+SRC_URI = "ftp://ftp.easysw.com/pub/cups/${PV}/cups-${PV}-source.tar.bz2"
+
+inherit autotools binconfig
+
+LDFLAGS += " -L${STAGING_LIBDIR} "
+
+do_compile () {
+ #Eeeks! Hack alert!
+ grep CUPS config.h.in~ | grep define >> config.h
+ sed -i s:STRIP:NOSTRIP: Makedefs
+ sed -i s:serial:: backend/Makefile
+
+ oe_runmake "SSLLIBS=-lssl -lcrypto -L${STAGING_LIBDIR}" \
+ "LIBPNG=-lpng -lm -L${STAGING_LIBDIR}" \
+ "LIBJPEG=-ljpeg -L${STAGING_LIBDIR}" \
+ "LIBZ=-lz -L${STAGING_LIBDIR}" \
+ "-I."
+}
+
+do_install () {
+ oe_runmake "DSTROOT=${D}" install
+}
+
+do_stage () {
+ install -d ${STAGING_INCDIR}/cups
+ install ${S}/cups/*.h ${STAGING_INCDIR}/cups/
+ oe_libinstall -C cups -so libcups ${STAGING_LIBDIR}
+}
+
diff --git a/packages/e17/e-wm_0.16.999.023.bb b/packages/e17/e-wm_0.16.999.023.bb
index ef0162a174..8bca19b616 100644
--- a/packages/e17/e-wm_0.16.999.023.bb
+++ b/packages/e17/e-wm_0.16.999.023.bb
@@ -8,8 +8,8 @@ PR = "r3"
SRC_URI = "http://enlightenment.freedesktop.org/files/enlightenment-${PV}.tar.gz \
file://fix-configure.patch;patch=1 \
file://remove-large-fonts.patch;patch=1 \
- file://Xsession.d/98enlightenment \
- cvs://anonymous@thinktux.net/root;module=e17/apps/e/data/themes;date=20050926"
+ file://Xsession.d/98enlightenment"
+# cvs://anonymous@thinktux.net/root;module=e17/apps/e/data/themes;date=20050926"
# file://disable-splash.patch;patch=1 \
# http://cvs.sourceforge.net/viewcvs.py/*checkout*/enlightenment/e17/apps/e/data/themes/default_entry.edc?rev=1.1 \
# http://cvs.sourceforge.net/viewcvs.py/*checkout*/enlightenment/e17/apps/e/data/themes/images/focus.png?rev=1.1 \
@@ -36,10 +36,10 @@ FILES_${PN} = "${bindir}/* ${libdir}/* ${datadir} ${sysconfdir}"
do_compile_prepend() {
find ${S} -name Makefile | xargs sed -i 's:/usr/include:${STAGING_INCDIR}:'
find ${S} -name Makefile | xargs sed -i 's:/usr/X11R6/include:${STAGING_INCDIR}:'
- mv "${WORKDIR}/themes/default_entry.edc" "${S}/data/themes/"
- mv "${WORKDIR}/themes/images/focus.png" "${S}/data/themes/images/"
- mv "${WORKDIR}/themes/images/entry.png" "${S}/data/themes/images/"
- mv "${WORKDIR}/themes/images/entry_focus.png" "${S}/data/themes/images/"
+# mv "${WORKDIR}/themes/default_entry.edc" "${S}/data/themes/"
+# mv "${WORKDIR}/themes/images/focus.png" "${S}/data/themes/images/"
+# mv "${WORKDIR}/themes/images/entry.png" "${S}/data/themes/images/"
+# mv "${WORKDIR}/themes/images/entry_focus.png" "${S}/data/themes/images/"
}
do_install_append() {
diff --git a/packages/gcc/gcc3-build.inc b/packages/gcc/gcc3-build.inc
index a09c6cf1f5..b7523c42f2 100644
--- a/packages/gcc/gcc3-build.inc
+++ b/packages/gcc/gcc3-build.inc
@@ -47,7 +47,10 @@ CPPFLAGS = ""
# Used by configure to define additional values for FLAGS_FOR_TARGET -
# passed to all the compilers.
ARCH_FLAGS_FOR_TARGET = ""
-ARCH_FLAGS_FOR_TARGET_nslu2 = "${TARGET_CC_ARCH}"
+#NOTE: not tested on other platforms, the following is probably correct
+# everywhere!
+ARCH_FLAGS_FOR_TARGET_slugos = "${TARGET_CC_ARCH}"
+ARCH_FLAGS_FOR_TARGET_unslung = "${TARGET_CC_ARCH}"
EXTRA_OEMAKE += "ARCH_FLAGS_FOR_TARGET='${ARCH_FLAGS_FOR_TARGET}'"
def get_gcc_fpu_setting(bb, d):
diff --git a/packages/glibc/glibc_2.2.5.bb b/packages/glibc/glibc_2.2.5.bb
index f214dd5fdc..22210c1335 100644
--- a/packages/glibc/glibc_2.2.5.bb
+++ b/packages/glibc/glibc_2.2.5.bb
@@ -249,7 +249,7 @@ include glibc-package.bbclass
# Unslung distribution specific packages follow ...
PACKAGES_unslung = "libc6-unslung"
-PACKAGE_ARCH_nslu2 = "nslu2"
+PACKAGE_ARCH_unslung = "nslu2"
MAINTAINER_libc6-unslung = "NSLU2 Linux <www.nslu2-linux.org>"
RDEPENDS_libc6-unslung = "nslu2-linksys-libs"
RPROVIDES_libc6-unslung = "libc6"
diff --git a/packages/gnome/gnome-cups-manager_0.31.bb b/packages/gnome/gnome-cups-manager_0.31.bb
new file mode 100644
index 0000000000..2023cdac5d
--- /dev/null
+++ b/packages/gnome/gnome-cups-manager_0.31.bb
@@ -0,0 +1,14 @@
+DESCRIPTION="Gnome Cups Manager"
+LICENSE="GPLv2"
+PR="r0"
+
+DEPENDS="glib-2.0 gtk+ pango libgnomecups"
+
+inherit gnome pkgconfig
+
+SRC_URI = "http://ftp.gnome.org/pub/gnome/sources/gnome-cups-manager/0.31/gnome-cups-manager-0.31.tar.bz2"
+
+do_stage() {
+autotools_stage_all
+}
+
diff --git a/packages/gnome/libgnomecups_0.2.2.bb b/packages/gnome/libgnomecups_0.2.2.bb
new file mode 100644
index 0000000000..4fcefb6454
--- /dev/null
+++ b/packages/gnome/libgnomecups_0.2.2.bb
@@ -0,0 +1,12 @@
+DESCRIPTION="Gnome Cups Manager"
+LICENSE="GPLv2"
+PR="r0"
+
+DEPENDS="glib-2.0 gtk+ pango cups"
+
+inherit gnome pkgconfig
+
+do_stage() {
+autotools_stage_all
+}
+
diff --git a/packages/gpe-bluetooth/gpe-bluetooth-0.36.3/segfault.patch b/packages/gpe-bluetooth/gpe-bluetooth-0.36.3/segfault.patch
deleted file mode 100644
index d18cb38aac..0000000000
--- a/packages/gpe-bluetooth/gpe-bluetooth-0.36.3/segfault.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-Index: main.c
-===================================================================
-RCS file: /cvs/gpe/base/gpe-bluetooth/main.c,v
-retrieving revision 1.51
-retrieving revision 1.52
-diff -u -r1.51 -r1.52
---- main.c 7 Mar 2004 17:41:27 -0000 1.51
-+++ main.c 7 Sep 2004 00:01:17 -0000 1.52
-@@ -508,7 +508,7 @@
- {
- GtkWidget *window;
- GdkBitmap *bitmap;
-- GtkWidget *menu_remove, *menu_file;
-+ GtkWidget *menu_remove;
- GtkTooltips *tooltips;
- int dd;
-
-@@ -560,12 +560,10 @@
-
- gtk_widget_show (menu_devices);
- gtk_widget_show (menu_remove);
-- gtk_widget_show (menu_file);
-
- gtk_menu_append (GTK_MENU (menu), menu_radio_on);
- gtk_menu_append (GTK_MENU (menu), menu_radio_off);
- gtk_menu_append (GTK_MENU (menu), menu_devices);
-- gtk_menu_append (GTK_MENU (menu), menu_file);
- gtk_menu_append (GTK_MENU (menu), menu_remove);
-
- if (gpe_load_icons (my_icons) == FALSE)
diff --git a/packages/gpe-bluetooth/gpe-bluetooth-0.37/change-sdp-to-bluetooth.patch b/packages/gpe-bluetooth/gpe-bluetooth-0.37/change-sdp-to-bluetooth.patch
deleted file mode 100644
index 009b9a576f..0000000000
--- a/packages/gpe-bluetooth/gpe-bluetooth-0.37/change-sdp-to-bluetooth.patch
+++ /dev/null
@@ -1,12 +0,0 @@
-diff -urNd ../gpe-bluetooth-0.37-r0/gpe-bluetooth-0.37/Makefile gpe-bluetooth-0.37/Makefile
---- ../gpe-bluetooth-0.37-r0/gpe-bluetooth-0.37/Makefile 2004-09-07 01:01:06.000000000 +0100
-+++ gpe-bluetooth-0.37/Makefile 2004-10-18 11:55:53.000000000 +0100
-@@ -20,7 +20,7 @@
- PACKAGE_CFLAGS += $(STANDARD_CFLAGS) $(GPECFLAGS) `pkg-config --cflags dbus-glib-1` `pkg-config --cflags libglade-2.0` `pkg-config --cflags mimedir-1.0` `$(LIBGPEVTYPE_PC_EXTRA) pkg-config --cflags $(LIBGPEVTYPE_PC)`
- PACKAGE_CPPFLAGS += $(STANDARD_CPPFLAGS) -DDBUS_API_SUBJECT_TO_CHANGE -DGPE_BLUETOOTH
- PACKAGE_CPPFLAGS += -DPACKAGE=\"$(PACKAGE)\" -DPREFIX=\"$(PREFIX)\" -DPACKAGE_LOCALE_DIR=\"$(PREFIX)/share/locale\"
--PACKAGE_LDFLAGS += $(GPELIBS) -lbluetooth -lsdp `pkg-config --libs gthread-2.0` `pkg-config --libs dbus-glib-1` `pkg-config --libs libglade-2.0` -lopenobex `pkg-config --libs mimedir-1.0` `$(LIBGPEVTYPE_PC_EXTRA) pkg-config --libs $(LIBGPEVTYPE_PC)` -lsqlite
-+PACKAGE_LDFLAGS += $(GPELIBS) -lbluetooth -lbluetooth `pkg-config --libs gthread-2.0` `pkg-config --libs dbus-glib-1` `pkg-config --libs libglade-2.0` -lopenobex `pkg-config --libs mimedir-1.0` `$(LIBGPEVTYPE_PC_EXTRA) pkg-config --libs $(LIBGPEVTYPE_PC)` -lsqlite
-
- ifeq ($(CVSBUILD),yes)
- BUILD = ../build
diff --git a/packages/gpe-bluetooth/gpe-bluetooth-0.37/dbus-service-name.patch b/packages/gpe-bluetooth/gpe-bluetooth-0.37/dbus-service-name.patch
deleted file mode 100644
index b7dc93b4e8..0000000000
--- a/packages/gpe-bluetooth/gpe-bluetooth-0.37/dbus-service-name.patch
+++ /dev/null
@@ -1,47 +0,0 @@
-Index: dbus.c
-===================================================================
-RCS file: /cvs/gpe/base/gpe-bluetooth/dbus.c,v
-retrieving revision 1.7
-diff -u -r1.7 dbus.c
---- gpe-bluetooth/dbus.c 7 Sep 2004 00:01:27 -0000 1.7
-+++ gpe-bluetooth/dbus.c 9 Jan 2005 13:56:46 -0000
-@@ -1,5 +1,5 @@
- /*
-- * Copyright (C) 2002, 2003, 2004 Philip Blundell <philb@gnu.org>
-+ * Copyright (C) 2002, 2003, 2004, 2005 Philip Blundell <philb@gnu.org>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
-@@ -27,9 +27,11 @@
-
- #define _(x) gettext(x)
-
--#define SERVICE_NAME "org.handhelds.gpe.bluez"
--#define PIN_INTERFACE_NAME SERVICE_NAME ".PinAgent"
--#define OBEX_INTERFACE_NAME SERVICE_NAME ".OBEX"
-+#define PIN_SERVICE_NAME "org.bluez.PinAgent"
-+#define PIN_INTERFACE_NAME PIN_SERVICE_NAME
-+
-+#define OBEX_SERVICE_NAME "org.handhelds.gpe.bluez"
-+#define OBEX_INTERFACE_NAME OBEX_SERVICE_NAME ".OBEX"
-
- extern DBusHandlerResult bluez_pin_handle_dbus_request (DBusConnection *connection, DBusMessage *message);
- extern DBusHandlerResult obex_client_handle_dbus_request (DBusConnection *connection, DBusMessage *message);
-@@ -96,7 +98,7 @@
-
- dbus_connection_register_object_path (connection, object_path1, &dbus_pin_vtable, NULL);
-
-- dbus_bus_acquire_service (connection, SERVICE_NAME, 0, &error);
-+ dbus_bus_acquire_service (connection, PIN_SERVICE_NAME, 0, &error);
- if (dbus_error_is_set (&error))
- {
- gpe_error_box_fmt (_("Failed to acquire service: %s"), error.message);
-@@ -118,7 +120,7 @@
-
- dbus_connection_register_object_path (connection, object_path2, &dbus_obex_vtable, NULL);
-
-- dbus_bus_acquire_service (connection, SERVICE_NAME, 0, &error);
-+ dbus_bus_acquire_service (connection, OBEX_SERVICE_NAME, 0, &error);
- if (dbus_error_is_set (&error))
- {
- gpe_error_box_fmt (_("Failed to acquire service: %s"), error.message);
diff --git a/packages/gpe-bluetooth/gpe-bluetooth-0.37/hciattach-path.patch b/packages/gpe-bluetooth/gpe-bluetooth-0.37/hciattach-path.patch
deleted file mode 100644
index 4b122668a6..0000000000
--- a/packages/gpe-bluetooth/gpe-bluetooth-0.37/hciattach-path.patch
+++ /dev/null
@@ -1,11 +0,0 @@
---- gpe-bluetooth-0.37/hciattach.sh.old 2004-11-23 14:11:16.000000000 +0000
-+++ gpe-bluetooth-0.37/hciattach.sh 2004-11-23 14:11:23.000000000 +0000
-@@ -3,7 +3,7 @@
- if [ -f /etc/sysconfig/bluetooth ]; then
- . /etc/sysconfig/bluetooth
-
-- exec hciattach -n $BLUETOOTH_PORT $BLUETOOTH_PROTOCOL $BLUETOOTH_SPEED
-+ exec /sbin/hciattach -n $BLUETOOTH_PORT $BLUETOOTH_PROTOCOL $BLUETOOTH_SPEED
- else
- echo "Bluetooth not configured"
- exit 1
diff --git a/packages/gpe-bluetooth/gpe-bluetooth-0.37/icon-resize.patch b/packages/gpe-bluetooth/gpe-bluetooth-0.37/icon-resize.patch
deleted file mode 100644
index 2580d9c3c8..0000000000
--- a/packages/gpe-bluetooth/gpe-bluetooth-0.37/icon-resize.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-diff -u -r1.52 main.c
---- gpe-bluetooth/main.c 7 Sep 2004 00:01:17 -0000 1.52
-+++ gpe-bluetooth/main.c 19 Oct 2004 08:16:27 -0000
-@@ -503,6 +503,22 @@
- g_timeout_add (time, (GSourceFunc) cancel_dock_message, (gpointer)id);
- }
-
-+gboolean
-+configure_event (GtkWidget *window, GdkEventConfigure *event, GdkBitmap *bitmap)
-+{
-+ GdkPixbuf *buf;
-+ int xoff, yoff;
-+
-+ buf = gpe_find_icon ("bt-off");
-+
-+ xoff = (event->width - gdk_pixbuf_get_width (buf)) / 2;
-+ yoff = (event->height - gdk_pixbuf_get_height (buf)) / 2;
-+
-+ gtk_widget_shape_combine_mask (window, bitmap, xoff, yoff);
-+
-+ return FALSE;
-+}
-+
- int
- main (int argc, char *argv[])
- {
-@@ -572,14 +588,14 @@
- icon = gtk_image_new_from_pixbuf (gpe_find_icon (radio_is_on ? "bt-on" : "bt-off"));
- gtk_widget_show (icon);
- gdk_pixbuf_render_pixmap_and_mask (gpe_find_icon ("bt-off"), NULL, &bitmap, 255);
-- gtk_widget_shape_combine_mask (window, bitmap, 2, 0);
-- gdk_bitmap_unref (bitmap);
-+ gtk_widget_shape_combine_mask (window, bitmap, 0, 0);
-
- gpe_set_window_icon (window, "bt-on");
-
- tooltips = gtk_tooltips_new ();
- gtk_tooltips_set_tip (GTK_TOOLTIPS (tooltips), window, _("This is the Bluetooth control.\nTap here to turn the radio on and off, or to see a list of Bluetooth devices."), NULL);
-
-+ g_signal_connect (G_OBJECT (window), "configure-event", G_CALLBACK (configure_event), bitmap);
- g_signal_connect (G_OBJECT (window), "button-press-event", G_CALLBACK (clicked), NULL);
- gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK);
-
diff --git a/packages/gpe-bluetooth/gpe-bluetooth_0.36.3.bb b/packages/gpe-bluetooth/gpe-bluetooth_0.36.3.bb
deleted file mode 100644
index 763f9a739f..0000000000
--- a/packages/gpe-bluetooth/gpe-bluetooth_0.36.3.bb
+++ /dev/null
@@ -1,15 +0,0 @@
-LICENSE = "GPL"
-inherit gpe
-
-DESCRIPTION = "GPE bluetooth support"
-DEPENDS = "gtk+ libdisplaymigration libgpewidget openobex libgpevtype bluez-libs sqlite dbus libglade blueprobe"
-RDEPENDS = "bluez-utils blueprobe"
-MAINTAINER = "Phil Blundell <pb@handhelds.org>"
-SECTION = "gpe"
-PRIORITY = "optional"
-PR = "r3"
-
-SRC_URI += "file://segfault.patch;patch=1;pnum=0"
-
-FILES_${PN} += '${datadir}/bluez-pin'
-
diff --git a/packages/gpe-bluetooth/gpe-bluetooth_0.37.bb b/packages/gpe-bluetooth/gpe-bluetooth_0.37.bb
deleted file mode 100644
index 5c7581e224..0000000000
--- a/packages/gpe-bluetooth/gpe-bluetooth_0.37.bb
+++ /dev/null
@@ -1,17 +0,0 @@
-LICENSE = "GPL"
-inherit gpe
-
-DESCRIPTION = "GPE bluetooth support"
-DEPENDS = "gtk+ libdisplaymigration libgpewidget openobex libgpevtype bluez-libs sqlite dbus libglade blueprobe bluez-utils-dbus"
-RDEPENDS = "bluez-utils-dbus blueprobe"
-MAINTAINER = "Phil Blundell <pb@handhelds.org>"
-SECTION = "gpe"
-PRIORITY = "optional"
-PR = "r7"
-
-FILES_${PN} += '${datadir}/bluez-pin'
-
-SRC_URI += "file://change-sdp-to-bluetooth.patch;patch=1 \
- file://icon-resize.patch;patch=1 \
- file://hciattach-path.patch;patch=1 \
- file://dbus-service-name.patch;patch=1"
diff --git a/packages/gpe-bluetooth/gpe-bluetooth_0.38.bb b/packages/gpe-bluetooth/gpe-bluetooth_0.38.bb
deleted file mode 100644
index 80076dab01..0000000000
--- a/packages/gpe-bluetooth/gpe-bluetooth_0.38.bb
+++ /dev/null
@@ -1,13 +0,0 @@
-LICENSE = "GPL"
-inherit gpe
-
-DESCRIPTION = "GPE bluetooth support"
-DEPENDS = "gtk+ libdisplaymigration libgpewidget openobex libgpevtype bluez-libs sqlite dbus libglade blueprobe bluez-utils-dbus"
-RDEPENDS = "bluez-utils-dbus blueprobe"
-MAINTAINER = "Phil Blundell <pb@handhelds.org>"
-SECTION = "gpe"
-PRIORITY = "optional"
-PR = "r0"
-
-FILES_${PN} += '${datadir}/bluez-pin'
-
diff --git a/packages/gpe-bluetooth/gpe-bluetooth_0.43.bb b/packages/gpe-bluetooth/gpe-bluetooth_0.43.bb
deleted file mode 100644
index 6a4e6dc907..0000000000
--- a/packages/gpe-bluetooth/gpe-bluetooth_0.43.bb
+++ /dev/null
@@ -1,15 +0,0 @@
-LICENSE = "GPL"
-inherit gpe autotools
-
-DESCRIPTION = "GPE bluetooth support"
-DEPENDS = "gtk+ libdisplaymigration libgpewidget openobex libgpevtype bluez-libs sqlite dbus libglade blueprobe bluez-utils-dbus"
-RDEPENDS = "bluez-utils-dbus blueprobe"
-MAINTAINER = "Phil Blundell <pb@handhelds.org>"
-SECTION = "gpe"
-PRIORITY = "optional"
-PR = "r0"
-
-SRC_URI = "${GPE_MIRROR}/${PN}-${PV}.tar.bz2"
-
-FILES_${PN} += '${datadir}/bluez-pin'
-
diff --git a/packages/gpe-bluetooth/gpe-bluetooth_0.44.bb b/packages/gpe-bluetooth/gpe-bluetooth_0.44.bb
deleted file mode 100644
index 6a4e6dc907..0000000000
--- a/packages/gpe-bluetooth/gpe-bluetooth_0.44.bb
+++ /dev/null
@@ -1,15 +0,0 @@
-LICENSE = "GPL"
-inherit gpe autotools
-
-DESCRIPTION = "GPE bluetooth support"
-DEPENDS = "gtk+ libdisplaymigration libgpewidget openobex libgpevtype bluez-libs sqlite dbus libglade blueprobe bluez-utils-dbus"
-RDEPENDS = "bluez-utils-dbus blueprobe"
-MAINTAINER = "Phil Blundell <pb@handhelds.org>"
-SECTION = "gpe"
-PRIORITY = "optional"
-PR = "r0"
-
-SRC_URI = "${GPE_MIRROR}/${PN}-${PV}.tar.bz2"
-
-FILES_${PN} += '${datadir}/bluez-pin'
-
diff --git a/packages/gpe-bluetooth/gpe-bluetooth_0.51.bb b/packages/gpe-bluetooth/gpe-bluetooth_0.51.bb
new file mode 100644
index 0000000000..1089c08413
--- /dev/null
+++ b/packages/gpe-bluetooth/gpe-bluetooth_0.51.bb
@@ -0,0 +1,18 @@
+LICENSE = "GPL"
+DESCRIPTION = "GPE bluetooth support user interface tool."
+SECTION = "gpe"
+PRIORITY = "optional"
+MAINTAINER = "Florian Boor <florian.boor@kernelconcepts.de>"
+PR = "r1"
+
+DEPENDS = "gtk+ libcontactsdb libdisplaymigration libgpewidget openobex libgpevtype bluez-libs sqlite dbus libglade blueprobe bluez-utils-dbus"
+RDEPENDS = "bluez-utils-dbus blueprobe"
+
+GPE_TARBALL_SUFFIX= "bz2"
+inherit gpe autotools
+
+FILES_${PN} += '${datadir}/bluez-pin'
+
+do_configure () {
+ autotools_do_configure
+} \ No newline at end of file
diff --git a/packages/gpe-bluetooth/gpe-bluetooth_0.52.bb b/packages/gpe-bluetooth/gpe-bluetooth_0.52.bb
new file mode 100644
index 0000000000..ce28d0b347
--- /dev/null
+++ b/packages/gpe-bluetooth/gpe-bluetooth_0.52.bb
@@ -0,0 +1,14 @@
+LICENSE = "GPL"
+DESCRIPTION = "GPE bluetooth support user interface tool."
+SECTION = "gpe"
+PRIORITY = "optional"
+MAINTAINER = "Florian Boor <florian.boor@kernelconcepts.de>"
+PR = "r0"
+
+DEPENDS = "gtk+ libcontactsdb libdisplaymigration libgpewidget openobex libgpevtype bluez-libs sqlite dbus libglade blueprobe bluez-utils-dbus"
+RDEPENDS = "bluez-utils-dbus blueprobe"
+
+GPE_TARBALL_SUFFIX= "bz2"
+inherit gpe autotools
+
+FILES_${PN} += '${datadir}/bluez-pin'
diff --git a/packages/gpe-calendar/gpe-calendar-0.61/remove-render.patch b/packages/gpe-calendar/gpe-calendar-0.61/remove-render.patch
deleted file mode 100644
index 70353e8186..0000000000
--- a/packages/gpe-calendar/gpe-calendar-0.61/remove-render.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- ../gpe-calendar-0.61-r0/gpe-calendar-0.61/main.c 2005-01-09 13:59:38.000000000 +0100
-+++ gpe-calendar-0.61/main.c 2005-04-20 21:26:48.686200320 +0200
-@@ -22,7 +22,6 @@
-
- #include <gpe/init.h>
- #include <gpe/pixmaps.h>
--#include <gpe/render.h>
- #include <gpe/errorbox.h>
-
- #include <gpe/event-db.h>
diff --git a/packages/gpe-calendar/gpe-calendar_0.56.bb b/packages/gpe-calendar/gpe-calendar_0.56.bb
deleted file mode 100644
index 9e2f03c31d..0000000000
--- a/packages/gpe-calendar/gpe-calendar_0.56.bb
+++ /dev/null
@@ -1,9 +0,0 @@
-LICENSE = "GPL"
-inherit gpe
-
-DEPENDS = "libeventdb libschedule libxsettings libxsettings-client libgpepimc libdisplaymigration libgpevtype"
-SECTION = "gpe"
-RDEPENDS = "gpe-icons"
-DESCRIPTION = "GPE calendar"
-
-SRC_URI = "${GPE_MIRROR}/${PN}-${PV}.tar.gz"
diff --git a/packages/gpe-calendar/gpe-calendar_0.58.bb b/packages/gpe-calendar/gpe-calendar_0.58.bb
deleted file mode 100644
index ff7fc617fc..0000000000
--- a/packages/gpe-calendar/gpe-calendar_0.58.bb
+++ /dev/null
@@ -1,10 +0,0 @@
-LICENSE = "GPL"
-PR = "r0"
-
-inherit gpe
-
-DEPENDS = "libeventdb libschedule libxsettings libxsettings-client libgpepimc libdisplaymigration libgpevtype"
-SECTION = "gpe"
-RDEPENDS = "gpe-icons"
-DESCRIPTION = "GPE calendar"
-
diff --git a/packages/gpe-calendar/gpe-calendar_0.59.bb b/packages/gpe-calendar/gpe-calendar_0.59.bb
deleted file mode 100644
index ff7fc617fc..0000000000
--- a/packages/gpe-calendar/gpe-calendar_0.59.bb
+++ /dev/null
@@ -1,10 +0,0 @@
-LICENSE = "GPL"
-PR = "r0"
-
-inherit gpe
-
-DEPENDS = "libeventdb libschedule libxsettings libxsettings-client libgpepimc libdisplaymigration libgpevtype"
-SECTION = "gpe"
-RDEPENDS = "gpe-icons"
-DESCRIPTION = "GPE calendar"
-
diff --git a/packages/gpe-calendar/gpe-calendar_0.61.bb b/packages/gpe-calendar/gpe-calendar_0.61.bb
deleted file mode 100644
index eb387e5d87..0000000000
--- a/packages/gpe-calendar/gpe-calendar_0.61.bb
+++ /dev/null
@@ -1,11 +0,0 @@
-LICENSE = "GPL"
-PR = "r1"
-
-inherit gpe
-
-DEPENDS = "libeventdb libschedule libxsettings libxsettings-client libgpepimc libdisplaymigration libgpevtype"
-SECTION = "gpe"
-RDEPENDS = "gpe-icons"
-DESCRIPTION = "GPE calendar"
-
-SRC_URI += "file://remove-render.patch;patch=1"
diff --git a/packages/gpe-calendar/gpe-calendar_0.63.bb b/packages/gpe-calendar/gpe-calendar_0.63.bb
deleted file mode 100644
index 2a2530808b..0000000000
--- a/packages/gpe-calendar/gpe-calendar_0.63.bb
+++ /dev/null
@@ -1,10 +0,0 @@
-LICENSE = "GPL"
-PR = "r1"
-
-inherit autotools gpe
-
-DEPENDS = "libeventdb libschedule libxsettings libxsettings-client libgpepimc libdisplaymigration libgpevtype"
-SECTION = "gpe"
-RDEPENDS = "gpe-icons"
-DESCRIPTION = "GPE calendar"
-
diff --git a/packages/gpe-calendar/gpe-calendar_0.64.bb b/packages/gpe-calendar/gpe-calendar_0.64.bb
deleted file mode 100644
index 2a2530808b..0000000000
--- a/packages/gpe-calendar/gpe-calendar_0.64.bb
+++ /dev/null
@@ -1,10 +0,0 @@
-LICENSE = "GPL"
-PR = "r1"
-
-inherit autotools gpe
-
-DEPENDS = "libeventdb libschedule libxsettings libxsettings-client libgpepimc libdisplaymigration libgpevtype"
-SECTION = "gpe"
-RDEPENDS = "gpe-icons"
-DESCRIPTION = "GPE calendar"
-
diff --git a/packages/gpe-calendar/gpe-calendar_0.65.bb b/packages/gpe-calendar/gpe-calendar_0.65.bb
deleted file mode 100644
index da50299bcd..0000000000
--- a/packages/gpe-calendar/gpe-calendar_0.65.bb
+++ /dev/null
@@ -1,11 +0,0 @@
-LICENSE = "GPL"
-PR = "r0"
-GPE_TARBALL_SUFFIX = "bz2"
-
-inherit autotools gpe
-
-DEPENDS = "libeventdb libschedule libxsettings libxsettings-client libgpepimc libdisplaymigration libgpevtype"
-SECTION = "gpe"
-RDEPENDS = "gpe-icons"
-DESCRIPTION = "GPE calendar"
-
diff --git a/packages/gpe-calendar/gpe-calendar_0.70.bb b/packages/gpe-calendar/gpe-calendar_0.70.bb
new file mode 100644
index 0000000000..eeab0a366c
--- /dev/null
+++ b/packages/gpe-calendar/gpe-calendar_0.70.bb
@@ -0,0 +1,15 @@
+LICENSE = "GPL"
+PR = "r0"
+GPE_TARBALL_SUFFIX = "bz2"
+MAINTAINER = "Florian Boor <florian.boor@kernelconcepts.de>"
+
+inherit autotools gpe
+
+DEPENDS = "dbus libeventdb libschedule libxsettings-client libgpepimc libgpevtype"
+SECTION = "gpe"
+RDEPENDS = "gpe-icons"
+DESCRIPTION = "GPE calendar is the calendar application of the GPE PIM suite."
+
+do_configure () {
+ autotools_do_configure
+} \ No newline at end of file
diff --git a/packages/initscripts/initscripts-1.0/slugos/checkroot.sh b/packages/initscripts/initscripts-1.0/slugos/checkroot.sh
index c70855ee43..3943f13427 100644
--- a/packages/initscripts/initscripts-1.0/slugos/checkroot.sh
+++ b/packages/initscripts/initscripts-1.0/slugos/checkroot.sh
@@ -130,7 +130,7 @@ else
echo "CONTROL-D will exit from this shell and REBOOT the system."
echo
leds system panic
- beep -r 5
+ leds beep -r 5
# Start a single user shell on the console
if single_user_ok
then
diff --git a/packages/initscripts/initscripts-slugos_1.0.bb b/packages/initscripts/initscripts-slugos_1.0.bb
index df89fd161b..7a4f79c20b 100644
--- a/packages/initscripts/initscripts-slugos_1.0.bb
+++ b/packages/initscripts/initscripts-slugos_1.0.bb
@@ -11,7 +11,7 @@ RCONFLICTS = "initscripts"
# All other standard definitions inherited from initscripts
# Except the PR which is hacked here. The format used is
# a suffix
-PR := "${PR}.8"
+PR := "${PR}.9"
FILESPATH = "${@base_set_filespath([ '${FILE_DIRNAME}/${P}', '${FILE_DIRNAME}/initscripts-${PV}', '${FILE_DIRNAME}/files', '${FILE_DIRNAME}' ], d)}"
diff --git a/packages/libao/libao-plugin-alsa_0.8.6.bb b/packages/libao/libao-plugin-alsa_0.8.6.bb
new file mode 100644
index 0000000000..30cde27074
--- /dev/null
+++ b/packages/libao/libao-plugin-alsa_0.8.6.bb
@@ -0,0 +1,30 @@
+LICENSE = "GPL"
+DESCRIPTION = "A cross platform audio library. This is the ALSA plugin."
+HOMEPAGE = "http://www.xiph.org/ao/"
+SECTION = "libs"
+PRIORITY = "optional"
+MAINTAINER = "Matthias Goebl <matthias.goebl@goebl.net>"
+DEPENDS = "alsa-lib libao"
+RDEPENDS = "libao2 (>=${PV})"
+PROVIDES = "libao-alsa"
+PACKAGES = "libao-alsa libao-alsa-dev"
+PR = "r2"
+
+SRC_URI = "http://downloads.xiph.org/releases/ao/libao-${PV}.tar.gz"
+S = "${WORKDIR}/libao-${PV}"
+
+inherit autotools pkgconfig
+
+EXTRA_OECONF = "--disable-esd --disable-esdtest \
+ --disable-oss \
+ --enable-alsa09 --enable-alsa09-mmap \
+ --disable-arts --disable-nas"
+
+do_stage() {
+ install -d ${STAGING_LIBDIR}/ao
+ install -d ${STAGING_LIBDIR}/ao/plugins-2
+ oe_libinstall -so -C src/plugins/alsa09/.libs libalsa09 ${STAGING_LIBDIR}/ao/plugins-2
+}
+
+FILES_libao-alsa = "${libdir}/ao/plugins-2/libalsa*.so"
+FILES_libao-alsa-dev = "${libdir}/ao/plugins-2/libalsa*.la"
diff --git a/packages/libeventdb/libeventdb_0.15.bb b/packages/libeventdb/libeventdb_0.15.bb
deleted file mode 100644
index 9d3dcbe622..0000000000
--- a/packages/libeventdb/libeventdb_0.15.bb
+++ /dev/null
@@ -1,24 +0,0 @@
-LICENSE = "LGPL"
-DESCRIPTION = "Database access library for GPE calendar"
-SECTION = "gpe/libs"
-PRIORITY = "optional"
-MAINTAINER = "Philip Blundell <pb@handhelds.org>"
-DEPENDS = "libgpewidget libgpepimc sqlite"
-
-inherit pkgconfig gpe
-
-headers = "event-db.h"
-
-do_stage () {
- oe_libinstall -so libeventdb ${STAGING_LIBDIR}
-
- mkdir -p ${STAGING_INCDIR}/gpe
- for h in ${headers}; do
- install -m 0644 ${S}/gpe/$h ${STAGING_INCDIR}/gpe/$h
- done
-}
-
-do_install () {
- gpe_do_install
- oe_runmake PREFIX=${prefix} DESTDIR=${D} install-devel
-}
diff --git a/packages/libeventdb/libeventdb_0.19.bb b/packages/libeventdb/libeventdb_0.19.bb
new file mode 100644
index 0000000000..c423fb4d5b
--- /dev/null
+++ b/packages/libeventdb/libeventdb_0.19.bb
@@ -0,0 +1,19 @@
+LICENSE = "LGPL"
+DESCRIPTION = "Database access library for GPE calendar"
+SECTION = "gpe/libs"
+PRIORITY = "optional"
+DEPENDS = "libgpewidget libgpepimc sqlite"
+MAINTAINER = "Florian Boor <florian.boor@kernelconcepts.de>"
+
+GPE_TARBALL_SUFFIX = "bz2"
+
+inherit pkgconfig gpe autotools
+
+
+do_stage () {
+ autotools_stage_all
+}
+
+do_configure () {
+ autotools_do_configure
+} \ No newline at end of file
diff --git a/packages/gpe-bluetooth/gpe-bluetooth-0.36.3/.mtn2git_empty b/packages/libgpewidget/files/.mtn2git_empty
index e69de29bb2..e69de29bb2 100644
--- a/packages/gpe-bluetooth/gpe-bluetooth-0.36.3/.mtn2git_empty
+++ b/packages/libgpewidget/files/.mtn2git_empty
diff --git a/packages/libgpewidget/files/pkgconfig.patch b/packages/libgpewidget/files/pkgconfig.patch
new file mode 100644
index 0000000000..317e01a9b4
--- /dev/null
+++ b/packages/libgpewidget/files/pkgconfig.patch
@@ -0,0 +1,11 @@
+--- configure.ac.orig 2006-02-04 17:37:55.000000000 +0100
++++ configure.ac 2006-02-06 00:56:28.000000000 +0100
+@@ -36,7 +36,7 @@
+ ENABLE_CAIRO=$enableval
+ ],
+ [
+- PKG_CHECK_EXISTS(cairo, [ENABLE_CAIRO=yes], [ENABLE_CAIRO=no])
++ PKG_CHECK_MODULES(cairo, [ENABLE_CAIRO=yes], [ENABLE_CAIRO=no])
+ ])
+
+ ENABLE_HILDON=false
diff --git a/packages/libgpewidget/libgpewidget-0.100/fixdoc.patch b/packages/libgpewidget/libgpewidget-0.100/fixdoc.patch
deleted file mode 100644
index c5c83af303..0000000000
--- a/packages/libgpewidget/libgpewidget-0.100/fixdoc.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- /tmp/libgpewidget-0.100/doc/gtk-doc.make 2005-04-21 23:56:55.000000000 +0200
-+++ libgpewidget-0.100/doc/gtk-doc.make 2005-04-22 12:36:23.628751472 +0200
-@@ -27,7 +27,6 @@
- $(DOC_MAIN_SGML_FILE) \
- $(DOC_MODULE)-sections.txt \
- $(DOC_MODULE)-overrides.txt
--# $(DOC_MODULE).types \
-
- DOC_STAMPS=scan-build.stamp tmpl-build.stamp sgml-build.stamp html-build.stamp \
- $(srcdir)/tmpl.stamp $(srcdir)/sgml.stamp $(srcdir)/html.stamp
diff --git a/packages/libgpewidget/libgpewidget-0.99/doc.patch b/packages/libgpewidget/libgpewidget-0.99/doc.patch
deleted file mode 100644
index 06b61049e3..0000000000
--- a/packages/libgpewidget/libgpewidget-0.99/doc.patch
+++ /dev/null
@@ -1,15 +0,0 @@
---- libgpewidget-0.99/doc/Makefile.am.orig 2005-04-19 13:32:58.335718432 +0100
-+++ libgpewidget-0.99/doc/Makefile.am 2005-04-19 13:33:06.755438440 +0100
-@@ -26,12 +26,6 @@
- gtkdoc-mkdb --module=$(DOC_MODULE) $(MKDB_OPTIONS) --source-dir=../gpe --source-dir=.. --main-sgml-file=$(DOC_MAIN_SGML_FILE)
- gtkdoc-mkhtml $(DOC_MODULE) $(DOC_MAIN_SGML_FILE)
-
--else
--all: doc
--doc:
-- @echo "Use \"configure --enable-gtk-doc\" to enable documentation"
-- @exit 1
--
- endif
-
- clean-local:
diff --git a/packages/libgpewidget/libgpewidget_0.100.bb b/packages/libgpewidget/libgpewidget_0.100.bb
deleted file mode 100644
index 977577c469..0000000000
--- a/packages/libgpewidget/libgpewidget_0.100.bb
+++ /dev/null
@@ -1,21 +0,0 @@
-LICENSE = "LGPL"
-PR = "r2"
-DESCRIPTION = "libgpewidget contains a collection of widgets and other common code shared by many GPE applications."
-SECTION = "gpe/libs"
-PRIORITY = "optional"
-MAINTAINER = "Philip Blundell <pb@handhelds.org>"
-DEPENDS="gtk+ libxrender gtk-doc intltool-native"
-#DEPENDS = "gtk+ cairo libxrender gtk-doc intltool-native"
-
-SRC_URI = "${GPE_MIRROR}/${PN}-${PV}.tar.bz2 \
- file://fixdoc.patch;patch=1"
-
-inherit pkgconfig autotools
-
-#EXTRA_OECONF = "--enable-cairo"
-
-do_stage () {
- oe_libinstall -C .libs -so libgpewidget ${STAGING_LIBDIR}
- autotools_stage_includes
-}
-
diff --git a/packages/libgpewidget/libgpewidget_0.109.bb b/packages/libgpewidget/libgpewidget_0.109.bb
new file mode 100644
index 0000000000..0b3f2e1b06
--- /dev/null
+++ b/packages/libgpewidget/libgpewidget_0.109.bb
@@ -0,0 +1,30 @@
+LICENSE = "LGPL"
+DESCRIPTION = "libgpewidget contains a collection of widgets and other common code shared by many GPE applications."
+SECTION = "gpe/libs"
+PRIORITY = "optional"
+DEPENDS = "gtk+ cairo libxrender gtk-doc intltool-native"
+MAINTAINER = "Florian Boor <florian.boor@kernelconcepts.de>"
+PR = "r1"
+
+PACKAGES =+ "libgpewidget-bin"
+
+PARALLEL_MAKE = ""
+
+SRC_URI = "${GPE_MIRROR}/${PN}-${PV}.tar.bz2 \
+ file://pkgconfig.patch;patch=1;pnum=0"
+
+inherit pkgconfig autotools
+
+FILES_libgpewidget-bin = "${bindir}"
+
+EXTRA_OECONF = "--enable-cairo"
+
+LDFLAGS += " -L${STAGING_LIBDIR}"
+
+do_stage () {
+ autotools_stage_all
+}
+
+do_configure () {
+ autotools_do_configure
+} \ No newline at end of file
diff --git a/packages/libgpewidget/libgpewidget_0.95.bb b/packages/libgpewidget/libgpewidget_0.95.bb
deleted file mode 100644
index 0951beed01..0000000000
--- a/packages/libgpewidget/libgpewidget_0.95.bb
+++ /dev/null
@@ -1,25 +0,0 @@
-LICENSE = "LGPL"
-PR = "r1"
-DESCRIPTION = "libgpewidget contains a collection of widgets and other common code shared by many GPE applications."
-SECTION = "gpe/libs"
-PRIORITY = "optional"
-MAINTAINER = "Philip Blundell <pb@handhelds.org>"
-DEPENDS = "gtk+ cairo libxrender"
-
-inherit pkgconfig gpe
-
-headers = "infoprint.h init.h render.h errorbox.h smallbox.h pixmaps.h gpetimesel.h gtkdatecombo.h dirbrowser.h stylus.h picturebutton.h popup_menu.h spacing.h translabel.h question.h windows.h gpe-iconlist.h gtksimplemenu.h gpewindowlist.h tray.h popup.h gpeiconlistview.h gpehelp.h gpeiconlistitem.h gpeclockface.h"
-
-do_stage () {
- oe_libinstall -so libgpewidget ${STAGING_LIBDIR}
-
- mkdir -p ${STAGING_INCDIR}/gpe
- for h in ${headers}; do
- install -m 0644 ${S}/gpe/$h ${STAGING_INCDIR}/gpe/$h
- done
-}
-
-do_install_append () {
- oe_runmake PREFIX='${prefix}' DESTDIR='${D}' install-devel
-}
-
diff --git a/packages/libgpewidget/libgpewidget_0.96.bb b/packages/libgpewidget/libgpewidget_0.96.bb
deleted file mode 100644
index 0951beed01..0000000000
--- a/packages/libgpewidget/libgpewidget_0.96.bb
+++ /dev/null
@@ -1,25 +0,0 @@
-LICENSE = "LGPL"
-PR = "r1"
-DESCRIPTION = "libgpewidget contains a collection of widgets and other common code shared by many GPE applications."
-SECTION = "gpe/libs"
-PRIORITY = "optional"
-MAINTAINER = "Philip Blundell <pb@handhelds.org>"
-DEPENDS = "gtk+ cairo libxrender"
-
-inherit pkgconfig gpe
-
-headers = "infoprint.h init.h render.h errorbox.h smallbox.h pixmaps.h gpetimesel.h gtkdatecombo.h dirbrowser.h stylus.h picturebutton.h popup_menu.h spacing.h translabel.h question.h windows.h gpe-iconlist.h gtksimplemenu.h gpewindowlist.h tray.h popup.h gpeiconlistview.h gpehelp.h gpeiconlistitem.h gpeclockface.h"
-
-do_stage () {
- oe_libinstall -so libgpewidget ${STAGING_LIBDIR}
-
- mkdir -p ${STAGING_INCDIR}/gpe
- for h in ${headers}; do
- install -m 0644 ${S}/gpe/$h ${STAGING_INCDIR}/gpe/$h
- done
-}
-
-do_install_append () {
- oe_runmake PREFIX='${prefix}' DESTDIR='${D}' install-devel
-}
-
diff --git a/packages/libgpewidget/libgpewidget_0.97.bb b/packages/libgpewidget/libgpewidget_0.97.bb
deleted file mode 100644
index 0951beed01..0000000000
--- a/packages/libgpewidget/libgpewidget_0.97.bb
+++ /dev/null
@@ -1,25 +0,0 @@
-LICENSE = "LGPL"
-PR = "r1"
-DESCRIPTION = "libgpewidget contains a collection of widgets and other common code shared by many GPE applications."
-SECTION = "gpe/libs"
-PRIORITY = "optional"
-MAINTAINER = "Philip Blundell <pb@handhelds.org>"
-DEPENDS = "gtk+ cairo libxrender"
-
-inherit pkgconfig gpe
-
-headers = "infoprint.h init.h render.h errorbox.h smallbox.h pixmaps.h gpetimesel.h gtkdatecombo.h dirbrowser.h stylus.h picturebutton.h popup_menu.h spacing.h translabel.h question.h windows.h gpe-iconlist.h gtksimplemenu.h gpewindowlist.h tray.h popup.h gpeiconlistview.h gpehelp.h gpeiconlistitem.h gpeclockface.h"
-
-do_stage () {
- oe_libinstall -so libgpewidget ${STAGING_LIBDIR}
-
- mkdir -p ${STAGING_INCDIR}/gpe
- for h in ${headers}; do
- install -m 0644 ${S}/gpe/$h ${STAGING_INCDIR}/gpe/$h
- done
-}
-
-do_install_append () {
- oe_runmake PREFIX='${prefix}' DESTDIR='${D}' install-devel
-}
-
diff --git a/packages/libgpewidget/libgpewidget_0.99.bb b/packages/libgpewidget/libgpewidget_0.99.bb
deleted file mode 100644
index c932e67d76..0000000000
--- a/packages/libgpewidget/libgpewidget_0.99.bb
+++ /dev/null
@@ -1,20 +0,0 @@
-LICENSE = "LGPL"
-PR = "r0"
-DESCRIPTION = "libgpewidget contains a collection of widgets and other common code shared by many GPE applications."
-SECTION = "gpe/libs"
-PRIORITY = "optional"
-MAINTAINER = "Philip Blundell <pb@handhelds.org>"
-DEPENDS = "gtk+ cairo libxrender gtk-doc intltool-native"
-
-SRC_URI = "${GPE_MIRROR}/${PN}-${PV}.tar.bz2 \
- file://doc.patch;patch=1"
-
-inherit pkgconfig autotools
-
-EXTRA_OECONF = "--enable-cairo"
-
-do_stage () {
- oe_libinstall -C .libs -so libgpewidget ${STAGING_LIBDIR}
- autotools_stage_includes
-}
-
diff --git a/packages/libsexy/libsexy_0.1.6.bb b/packages/libsexy/libsexy_0.1.6.bb
new file mode 100644
index 0000000000..5ac5d296fb
--- /dev/null
+++ b/packages/libsexy/libsexy_0.1.6.bb
@@ -0,0 +1,17 @@
+DESCRIPTION = "Libsexy is a collection of GTK+ widgets that extend the functionality of such standard widgets as GtkEntry and GtkLabel"
+HOMEPAGE = "http://wiki.chipx86.com/wiki/Libsexy"
+AUTHOR = "Christian Hammond <chipx86@chipx86.com>"
+MAINTAINER = "Koen Kooi <koen@handhelds.org>""
+PR = "r0"
+
+DEPENDS = "gtk+ enchant libxml2"
+
+SRC_URI = "http://osiris.chipx86.com/projects/libsexy/releases/${P}.tar.gz"
+
+inherit autotools pkgconfig
+
+do_stage() {
+autotools_stage_all
+}
+
+
diff --git a/packages/gpe-bluetooth/gpe-bluetooth-0.37/.mtn2git_empty b/packages/linux/ep93xx-kernel/.mtn2git_empty
index e69de29bb2..e69de29bb2 100644
--- a/packages/gpe-bluetooth/gpe-bluetooth-0.37/.mtn2git_empty
+++ b/packages/linux/ep93xx-kernel/.mtn2git_empty
diff --git a/packages/linux/ep93xx-kernel/defconfig b/packages/linux/ep93xx-kernel/defconfig
new file mode 100644
index 0000000000..1a0aa51aea
--- /dev/null
+++ b/packages/linux/ep93xx-kernel/defconfig
@@ -0,0 +1,920 @@
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.9-rc2-ep93xx
+# Mon Nov 8 16:40:30 2004
+#
+CONFIG_ARM=y
+CONFIG_MMU=y
+CONFIG_UID16=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+CONFIG_GENERIC_IOMAP=y
+
+#
+# Code maturity level options
+#
+CONFIG_EXPERIMENTAL=y
+# CONFIG_CLEAN_COMPILE is not set
+CONFIG_BROKEN=y
+CONFIG_BROKEN_ON_SMP=y
+
+#
+# General setup
+#
+CONFIG_LOCALVERSION=""
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+# CONFIG_POSIX_MQUEUE is not set
+# CONFIG_BSD_PROCESS_ACCT is not set
+CONFIG_SYSCTL=y
+# CONFIG_AUDIT is not set
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_HOTPLUG is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+# CONFIG_EMBEDDED is not set
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+CONFIG_IOSCHED_DEADLINE=y
+CONFIG_IOSCHED_CFQ=y
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SHMEM=y
+# CONFIG_TINY_SHMEM is not set
+
+#
+# Loadable module support
+#
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_OBSOLETE_MODPARM=y
+# CONFIG_MODVERSIONS is not set
+CONFIG_KMOD=y
+
+#
+# System Type
+#
+# CONFIG_ARCH_CLPS7500 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_CO285 is not set
+# CONFIG_ARCH_EBSA110 is not set
+CONFIG_ARCH_EP93XX=y
+# CONFIG_ARCH_CAMELOT is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_IOP3XX is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_VERSATILE_PB is not set
+# CONFIG_ARCH_IMX is not set
+
+#
+# EP93xx
+#
+# CONFIG_ARCH_EP9301 is not set
+# CONFIG_ARCH_EP9302 is not set
+CONFIG_ARCH_EP9312=y
+# CONFIG_ARCH_EP9315 is not set
+CONFIG_MACH_EDB9312=y
+# CONFIG_MACH_ACC is not set
+CONFIG_EP93XX_DMA=y
+CONFIG_ARCH_EP93XX_IDE=y
+CONFIG_EP93XX_SSP=y
+CONFIG_EP93XX_SSP_CIRRUS=y
+# CONFIG_EP93XX_SSP_LINUX is not set
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM920T=y
+CONFIG_CPU_32v4=y
+CONFIG_CPU_ABRT_EV4T=y
+CONFIG_CPU_CACHE_V4WT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+
+#
+# Processor Features
+#
+# CONFIG_ARM_THUMB is not set
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+
+#
+# General setup
+#
+CONFIG_DISCONTIGMEM=y
+CONFIG_ARM_AMBA=y
+# CONFIG_ZBOOT_ROM is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+
+#
+# At least one math emulation must be selected
+#
+CONFIG_FPE_NWFPE=y
+# CONFIG_FPE_NWFPE_XP is not set
+# CONFIG_FPE_FASTFPE is not set
+CONFIG_BINFMT_ELF=y
+CONFIG_BINFMT_AOUT=y
+CONFIG_BINFMT_MISC=y
+
+#
+# Generic Driver Options
+#
+# CONFIG_STANDALONE is not set
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_PM is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_ARTHUR is not set
+CONFIG_CMDLINE="root=/dev/hda1"
+CONFIG_LEDS=y
+CONFIG_LEDS_TIMER=y
+CONFIG_LEDS_CPU=y
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Parallel port support
+#
+# CONFIG_PARPORT is not set
+
+#
+# Memory Technology Devices (MTD)
+#
+CONFIG_MTD=y
+# CONFIG_MTD_DEBUG is not set
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_REDBOOT_PARTS=y
+CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
+# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
+CONFIG_MTD_CMDLINE_PARTS=y
+# CONFIG_MTD_AFS_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_FTL=y
+CONFIG_NFTL=y
+CONFIG_NFTL_RW=y
+CONFIG_INFTL=y
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=y
+CONFIG_MTD_JEDECPROBE=y
+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=y
+CONFIG_MTD_CFI_AMDSTD_RETRY=0
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_CFI_UTIL=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+CONFIG_MTD_ABSENT=y
+# CONFIG_MTD_OBSOLETE_CHIPS is not set
+
+#
+# Mapping drivers for chip access
+#
+CONFIG_MTD_COMPLEX_MAPPINGS=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_START=0x60000000
+CONFIG_MTD_PHYSMAP_LEN=0x02000000
+CONFIG_MTD_PHYSMAP_BANKWIDTH=4
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_EDB7312 is not set
+# CONFIG_MTD_IMPA7 is not set
+
+#
+# Self-contained MTD device drivers
+#
+CONFIG_MTD_SLRAM=y
+CONFIG_MTD_PHRAM=y
+CONFIG_MTD_MTDRAM=y
+CONFIG_MTDRAM_TOTAL_SIZE=512
+CONFIG_MTDRAM_ERASE_SIZE=1
+CONFIG_MTDRAM_ABS_POS=0x20000000
+# CONFIG_MTD_BLKMTD 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
+
+#
+# NAND Flash Device Drivers
+#
+CONFIG_MTD_NAND=y
+CONFIG_MTD_NAND_VERIFY_WRITE=y
+CONFIG_MTD_NAND_IDS=y
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+
+#
+# Plug and Play support
+#
+
+#
+# Block devices
+#
+# CONFIG_BLK_DEV_FD 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_SIZE=12288
+CONFIG_BLK_DEV_INITRD=y
+
+#
+# Multi-device support (RAID and LVM)
+#
+# CONFIG_MD is not set
+
+#
+# Networking support
+#
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+CONFIG_PACKET_MMAP=y
+# CONFIG_NETLINK_DEV is not set
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_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_TUNNEL is not set
+# CONFIG_IPV6 is not set
+# CONFIG_NETFILTER is not set
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+
+#
+# SCTP Configuration (EXPERIMENTAL)
+#
+# CONFIG_IP_SCTP is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_NET_DIVERT is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_NET_HW_FLOWCONTROL is not set
+
+#
+# QoS and/or fair queueing
+#
+# CONFIG_NET_SCHED is not set
+# CONFIG_NET_CLS_ROUTE is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+CONFIG_NETPOLL=y
+# CONFIG_NETPOLL_RX is not set
+# CONFIG_NETPOLL_TRAP is not set
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_HAMRADIO is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+CONFIG_NETDEVICES=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_EQUALIZER is not set
+# CONFIG_TUN is not set
+
+#
+# Ethernet (10 or 100Mbit)
+#
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_EP93XX_ETHERNET=y
+# CONFIG_SMC91X is not set
+
+#
+# Ethernet (1000 Mbit)
+#
+
+#
+# Ethernet (10000 Mbit)
+#
+
+#
+# Token Ring devices
+#
+
+#
+# Wireless LAN (non-hamradio)
+#
+# CONFIG_NET_RADIO is not set
+
+#
+# Wan interfaces
+#
+# CONFIG_WAN is not set
+# CONFIG_PPP is not set
+# CONFIG_SLIP is not set
+# CONFIG_SHAPER is not set
+CONFIG_NETCONSOLE=y
+
+#
+# ATA/ATAPI/MFM/RLL support
+#
+CONFIG_IDE=y
+CONFIG_BLK_DEV_IDE=y
+
+#
+# Please see Documentation/ide.txt for help/info on IDE drives
+#
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_BLK_DEV_IDEDISK=y
+CONFIG_IDEDISK_MULTI_MODE=y
+CONFIG_BLK_DEV_IDECD=y
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_BLK_DEV_IDEFLOPPY is not set
+# CONFIG_BLK_DEV_IDESCSI is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+# CONFIG_IDE_TASKFILE_IO is not set
+
+#
+# IDE chipset support/bugfixes
+#
+CONFIG_IDE_GENERIC=y
+CONFIG_BLK_DEV_EP93XX=y
+# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
+CONFIG_IDE_ARM=y
+# CONFIG_BLK_DEV_IDEDMA is not set
+# CONFIG_IDEDMA_AUTO is not set
+# CONFIG_BLK_DEV_HD is not set
+
+#
+# SCSI device support
+#
+CONFIG_SCSI=y
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+# CONFIG_BLK_DEV_SD is not set
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+
+#
+# SCSI Transport Attributes
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+
+#
+# SCSI low-level drivers
+#
+# CONFIG_SCSI_SATA is not set
+# CONFIG_SCSI_DEBUG is not set
+
+#
+# Fusion MPT device support
+#
+
+#
+# IEEE 1394 (FireWire) support
+#
+# CONFIG_IEEE1394 is not set
+
+#
+# I2O device support
+#
+
+#
+# ISDN subsystem
+#
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=y
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
+# CONFIG_INPUT_JOYDEV is not set
+# CONFIG_INPUT_TSDEV is not set
+# CONFIG_INPUT_EVDEV is not set
+# CONFIG_INPUT_EVBUG is not set
+
+#
+# Input I/O drivers
+#
+# CONFIG_GAMEPORT is not set
+CONFIG_SOUND_GAMEPORT=y
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+# CONFIG_SERIO_CT82C710 is not set
+# CONFIG_SERIO_AMBAKMI is not set
+# CONFIG_SERIO_RAW is not set
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=y
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+# CONFIG_KEYBOARD_XTKBD is not set
+# CONFIG_KEYBOARD_NEWTON is not set
+CONFIG_KEYBOARD_EP93XX=y
+CONFIG_KEYBOARD_EP93XX_SPI=y
+CONFIG_KEYBOARD_EP93XX_8X8=y
+CONFIG_INPUT_MOUSE=y
+CONFIG_MOUSE_PS2=y
+CONFIG_MOUSE_SERIAL=y
+# CONFIG_MOUSE_VSXXXAA is not set
+# CONFIG_INPUT_JOYSTICK is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+CONFIG_TOUCHSCREEN_EP93XX=y
+# CONFIG_INPUT_MISC is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_VT_CONSOLE=y
+CONFIG_HW_CONSOLE=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+# CONFIG_SERIAL_8250 is not set
+
+#
+# Non-8250 serial port support
+#
+# CONFIG_SERIAL_AMBA_PL010 is not set
+# CONFIG_SERIAL_AMBA_PL011 is not set
+CONFIG_SERIAL_EP93XX=y
+CONFIG_SERIAL_EP93XX_CONSOLE=y
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+
+#
+# IPMI
+#
+# CONFIG_IPMI_HANDLER is not set
+
+#
+# Watchdog Cards
+#
+# CONFIG_WATCHDOG is not set
+# CONFIG_NVRAM is not set
+# CONFIG_RTC is not set
+# CONFIG_EP93XX_RTC is not set
+# CONFIG_DTLK is not set
+# CONFIG_R3964 is not set
+
+#
+# Ftape, the floppy tape device driver
+#
+# CONFIG_DRM is not set
+# CONFIG_RAW_DRIVER is not set
+
+#
+# I2C support
+#
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+
+#
+# I2C Algorithms
+#
+CONFIG_I2C_ALGOBIT=y
+# CONFIG_I2C_ALGOPCF is not set
+# CONFIG_I2C_ALGOPCA is not set
+
+#
+# I2C Hardware Bus support
+#
+# CONFIG_I2C_AMD756 is not set
+# CONFIG_I2C_AMD8111 is not set
+CONFIG_I2C_EP93XX=y
+# CONFIG_I2C_ISA is not set
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_SCx200_ACB is not set
+# CONFIG_I2C_PCA_ISA is not set
+
+#
+# Hardware Sensors Chip support
+#
+CONFIG_I2C_SENSOR=y
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ASB100 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_FSCHER is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83627HF is not set
+
+#
+# Other I2C Chip support
+#
+CONFIG_SENSORS_DS1337=y
+CONFIG_SENSORS_EEPROM=y
+# CONFIG_SENSORS_PCF8574 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_RTC8564 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+
+#
+# Multimedia devices
+#
+# CONFIG_VIDEO_DEV is not set
+
+#
+# Digital Video Broadcasting Devices
+#
+# CONFIG_DVB is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+CONFIG_EXT3_FS=y
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+CONFIG_REISERFS_FS=y
+# CONFIG_REISERFS_CHECK is not set
+# CONFIG_REISERFS_PROC_INFO is not set
+# CONFIG_REISERFS_FS_XATTR is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_XFS_FS is not set
+# CONFIG_MINIX_FS is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_QUOTA is not set
+CONFIG_AUTOFS_FS=y
+# CONFIG_AUTOFS4_FS is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+CONFIG_ISO9660_FS=y
+CONFIG_JOLIET=y
+CONFIG_ZISOFS=y
+CONFIG_ZISOFS_FS=y
+CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
+
+#
+# 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_SYSFS=y
+# CONFIG_DEVFS_FS is not set
+# CONFIG_DEVFS_MOUNT is not set
+# CONFIG_DEVFS_DEBUG is not set
+# CONFIG_DEVPTS_FS_XATTR is not set
+CONFIG_TMPFS=y
+# CONFIG_HUGETLBFS is not set
+# CONFIG_HUGETLB_PAGE is not set
+CONFIG_RAMFS=y
+
+#
+# Miscellaneous filesystems
+#
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+# CONFIG_JFFS_FS is not set
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_FS_DEBUG=0
+# CONFIG_JFFS2_FS_NAND is not set
+CONFIG_JFFS2_COMPRESSION_OPTIONS=y
+CONFIG_JFFS2_ZLIB=y
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+# CONFIG_JFFS2_CMODE_NONE is not set
+CONFIG_JFFS2_CMODE_PRIORITY=y
+# CONFIG_JFFS2_CMODE_SIZE is not set
+# CONFIG_CRAMFS is not set
+# CONFIG_VXFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+
+#
+# Network File Systems
+#
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V4 is not set
+# CONFIG_NFS_DIRECTIO is not set
+# CONFIG_NFSD is not set
+CONFIG_ROOT_NFS=y
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+# CONFIG_EXPORTFS is not set
+CONFIG_SUNRPC=y
+# 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=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+
+#
+# Native Language Support
+#
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=y
+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=y
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=y
+
+#
+# Profiling support
+#
+# CONFIG_PROFILING is not set
+
+#
+# Graphics support
+#
+CONFIG_FB=y
+CONFIG_FB_MODE_HELPERS=y
+# CONFIG_FB_ARMCLCD is not set
+# CONFIG_FB_CX25871_I2C is not set
+CONFIG_FB_EP93XX=y
+# CONFIG_FB_CRT_EP93XX is not set
+CONFIG_FB_LCD_EP93XX=y
+# CONFIG_FB_LCD_EP93XX_SHARP is not set
+# CONFIG_FB_CX25871 is not set
+# CONFIG_FB_EP93XX_8BPP is not set
+# CONFIG_FB_EP93XX_16BPP_565 is not set
+# CONFIG_FB_EP93XX_24BPP is not set
+CONFIG_FB_EP93XX_32BPP=y
+# CONFIG_FB_VIRTUAL is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_FONT_6x11=y
+CONFIG_FONT_PEARL_8x8=y
+CONFIG_FONT_ACORN_8x8=y
+# CONFIG_FONT_MINI_4x6 is not set
+CONFIG_FONT_SUN8x16=y
+CONFIG_FONT_SUN12x22=y
+
+#
+# Logo configuration
+#
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+
+#
+# Sound
+#
+CONFIG_SOUND=y
+
+#
+# Advanced Linux Sound Architecture
+#
+# CONFIG_SND is not set
+
+#
+# Open Sound System
+#
+CONFIG_SOUND_PRIME=y
+# CONFIG_SOUND_BT878 is not set
+# CONFIG_SOUND_FUSION is not set
+# CONFIG_SOUND_CS4281 is not set
+# CONFIG_SOUND_SONICVIBES is not set
+# CONFIG_SOUND_TRIDENT is not set
+# CONFIG_SOUND_MSNDCLAS is not set
+# CONFIG_SOUND_MSNDPIN is not set
+# CONFIG_SOUND_OSS is not set
+# CONFIG_SOUND_TVMIXER is not set
+# CONFIG_SOUND_AD1980 is not set
+
+#
+# Misc devices
+#
+
+#
+# USB support
+#
+# CONFIG_USB is not set
+
+#
+# USB Gadget Support
+#
+# CONFIG_USB_GADGET is not set
+
+#
+# MMC/SD Card support
+#
+# CONFIG_MMC is not set
+
+#
+# Kernel hacking
+#
+CONFIG_DEBUG_KERNEL=y
+CONFIG_MAGIC_SYSRQ=y
+# CONFIG_DEBUG_SLAB is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_DEBUG_INFO=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_USER=y
+# CONFIG_DEBUG_WAITQ is not set
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_LL_PRINTK_HACK=y
+# CONFIG_DEBUG_ICEDCC is not set
+
+#
+# Security options
+#
+# CONFIG_SECURITY is not set
+
+#
+# Cryptographic options
+#
+# CONFIG_CRYPTO is not set
+
+#
+# Library routines
+#
+CONFIG_CRC_CCITT=y
+CONFIG_CRC32=y
+CONFIG_LIBCRC32C=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=y
diff --git a/packages/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff b/packages/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff
new file mode 100644
index 0000000000..3dc6b004b8
--- /dev/null
+++ b/packages/linux/ep93xx-kernel/linux-2.6.15-ep93xx-gao19.diff
@@ -0,0 +1,43746 @@
+diff --git a/Documentation/arm/ep93xx/config.txt b/Documentation/arm/ep93xx/config.txt
+new file mode 100644
+index 0000000..9d13a15
+--- /dev/null
++++ b/Documentation/arm/ep93xx/config.txt
+@@ -0,0 +1,207 @@
++-------------------------------------------------------------------------
++config.txt
++
++Information on configuration options in the Linux kernel for the Cirrus
++EP93xx.
++
++Note to developers: Let's stick to the essentials on "how to turn things
++on in the Linux build." This information is presented from the standpoint
++of someone doing a build, looking at a make menuconfig screen. If what you
++are describing doesn't fit here, it should get its own document to go into
++the level of detail you feel is most practicle.
++-------------------------------------------------------------------------
++
++All options configured as built-in drivers, not loadable modules.
++So on options that are selected by < >, select <*>, not <M>. To
++do this either hit 'y' or hit the space bar twice.
++
++
++----------------
++Audio
++----------------
++Needed by:
++Needs: DMA Support, dev fs.
++
++Ac97 and I2S audio are currently mutually exclusive.
++
++To enable Ac97 Audio:
++ Go into "Sound --->"
++ Enable "Sound Support"
++ Enable "OSS sound modules"
++ Select "Ac97" for "Cirrus EP93xx Sound Support"
++
++To enable I2S Audio:
++ Go into "Sound --->"
++ Enable "Sound Support"
++ Enable "OSS sound modules"
++ Select "I2S" for "Cirrus EP93xx Sound Support"
++ If you have an EDB9312 board, select "CS4228A" for "Cirrus I2S Codec Support"
++ If you have an EDB9301 board, select "CS4271" for "Cirrus I2S Codec Support"
++
++
++----------------
++Dev Fs
++----------------
++ DEVFS support is no longer available.
++ Please consider using udev or create device nodes manually instead.
++ You might also need to adapt your startup scripts and userspace
++ apps.
++
++----------------
++DMA
++----------------
++Needed by: Audio, IDE/DMA
++Needs:
++
++To enable DMA:
++ Go into "System Type --->"
++ Go into "EP93XX Options --->"
++ Enable "EP93XX Internal DMA Support"
++
++
++----------------
++IDE
++----------------
++Needed by:
++Needs:
++ To Turn on IDE support for the platform, you need to enable
++General IDE support first - CONFIG_BLK_DEV_IDE, CONFIG_BLK_DEV_IDEDISK,
++CONFIG_BLK_DEV_IDECD.
++
++ If multiword DMA and ultra DMA support is needed, general DMA support for
++the platform must be enabled first. See DMA section of this document for
++options to enable DMA for the platform.
++
++ If CDROM support is enabled, ISO9660 file system support should be enabled.
++If a DVD support is needed, UDF file system support should be enabled.
++
++To enable CONFIG_BLK_DEV_IDE:
++ Go into "ATA /ATAPI/MFM/RLL support --->"
++ Enable "ATA/ATAPI/MFM/RLL support"
++ Go into "IDE, ATA, and ATAPI Block devices --->"
++ Enable "Enhanced IDE/MFM/RLL disk/cdrom/tape/floppy support"
++
++To enable CONFIG_BLK_DEV_IDEDISK:
++ Go into "ATA /ATAPI/MFM/RLL support --->"
++ Go into "IDE, ATA, and ATAPI Block devices --->"
++ Enable "Include IDE/ATA-2 DISK support"
++
++To enable CONFIG_BLK_DEV_IDECD:
++ Go into "ATA /ATAPI/MFM/RLL support --->"
++ Go into "IDE, ATA, and ATAPI Block devices --->"
++ Enable "Include IDE/ATAPI CDROM support"
++
++To enable EP93XX IDE (PIO mode only):
++ Go into "ATA /ATAPI/MFM/RLL support --->"
++ Go into "IDE, ATA, and ATAPI Block devices --->"
++ Enable "EP93XX IDE Support"
++
++To enable EP93XX IDE DMA (mdma and udma modes):
++ Go into "ATA /ATAPI/MFM/RLL support --->"
++ Go into "IDE, ATA, and ATAPI Block devices --->"
++ Enable "EP93XX IDE DMA support"
++
++To enabled ISO 9660 file system support:
++ Go into "File systems --->"
++ Enable "ISo 9660 CDROM file system support"
++ Enable "Microsoft Joliet CDROM extensions"
++
++To enable UDF file system support:
++ Go into "File systems --->"
++ Enable "UDF file system support (read only)"
++
++See also /Documentation/arm/ep93xx/ide-hard-drive-support.txt for information
++on configuring the hard drive.
++
++----------------
++IrDA
++----------------
++Described in /Documentation/arm/ep93xx/irda.txt
++
++
++----------------
++NFS
++----------------
++Described in /Documentation/arm/ep93xx/nfs.txt
++
++
++----------------
++Serial Terminal
++----------------
++To enable serial terminal:
++ Go into "Character devices --->"
++ Turn off "Support for console on virtual terminal"
++ Turn off "Virtual terminal"
++ Go into "Serial drivers --->"
++ Turn on "Cirrus EP93xx ARM AMBA serial port support"
++ Turn on "Support for console on EP93xx serial port"
++
++Serial terminal is the bottom jack of J7.
++Format is 57600,8N1, flow control: "none".
++
++
++----------------
++Touchscreen
++----------------
++To enable touchscreen driver:
++ Go into "Character devices --->"
++ Go into "Mice --->"
++ Enable "Mouse Support (not serial and bus mice)"
++ Disable "PS/2 Mouse (aka "auxiliary device") support
++ Enable "EP93xx touch screen support"
++
++
++----------------
++USB
++----------------
++The order of all of the following statements is critical as some options enable
++other options.
++
++To enable basic USB support(required for all devices listed below):
++ Go into "USB support --->"
++ Enable "Support for USB"
++ Enable "Preliminary USB device filesystem" (optional)
++ Enable "EP93XX OHCI-compatible host interface support"
++
++To enable support for USB mouse:
++ Go into "Input core support --->"
++ Enable "Input core support"
++ Enable "Mouse support"
++
++ Go back to the top level of menuconfig
++
++ Go into "USB support --->"
++ Enable "USB Human Interface Device (full HID) support"
++ Enable "HID input layer support"
++
++To enable support for USB Keyboard:
++ Go into "Input core support --->"
++ Enable "Input core support"
++ Enable "Keyboard support"
++
++ Go back to the top level of menuconfig
++
++ Go into "USB support --->"
++ Enable "USB Human Interface Device (full HID) support"
++ Enable "HID input layer support"
++
++ Go back to the top level of menuconfig
++ Go into "Character devices --->"
++ Set EP93xx Keyboard Support to "USB"
++
++To enable USB Mass Storage support:
++ Go into "SCSI Support --->"
++ Enable "SCSI Support"
++ Enable "SCSI disk support"
++
++ Go back to the top level of menuconfig
++
++ Go into "USB support --->"
++ Enable "USB Mass Storage support"
++
++ Go back to the top level of menuconfig
++
++(optional - Do this if you want to mount a USB flash drive)
++ Go into "File systems --->"
++ Enable "DOS FAT fs support"
++ Enable "VFAT (Windows-95) fs support"
+diff --git a/Documentation/arm/ep93xx/dma.txt b/Documentation/arm/ep93xx/dma.txt
+new file mode 100644
+index 0000000..e7fc1bb
+--- /dev/null
++++ b/Documentation/arm/ep93xx/dma.txt
+@@ -0,0 +1,300 @@
++Support Functions for the Cirrus Logic ep93xx Internal DMA controller.
++==============================================================================
++
++State diagram
++
++States:
++Uninitialized (!pause & !xfer_enable)
++Stopped (pause & !xfer_enable)
++Transferring (!pause & xfer_enable)
++Stopped by starvation (pause & xfer_enable)
++
++ _______________
++ request ----------> | | <------- free -----------
++ | Uninitialized | /\
++ |_______________| ||
++ ||
++ || ||
++ init || ------------------------------>||
++ || /\ ||
++ \/ || ||
++ _________ ||
++ ||<-- start && new_buffers <= 1 -- | | <----- flush <--------- ||
++ || | Stopped | /\ ||
++ || ---------> pause------> |_________| -------------------->|| ||
++ || /\ ||
++ || || || ||
++ || || || start && new_buffers > 1 ||
++ || || || ||
++ || || \/ ||
++ || || ______________ ||
++ || || | | ------------------------->||
++ || ||<---------------- | Transferring | ------------------->|| ||
++ || || |______________| || ||
++ || || || ||
++ || || || || ||
++ || || || new_buffers = 0 || ||
++ || || /\ || || ||
++ || || || \/ || ||
++ || || new_buffers > 1 || || ||
++ || || || || ||
++ || || _______________________ || ||
++ || ||<-------------- | | || ||
++ \/ | Stopped by starvation | ------------>|| ||
++ ---------------------------> |_______________________| || ||
++ || ||
++ || /\ || ||
++ || || || ||
++ || ||<-------- flush <--------------- ||
++ || ||
++ ------------------------------------------->||
++
++
++------------------------------------------------------------------------------
++EP93XX DMA API Functions
++------------------------------------------------------------------------------
++
++ int ep93xx_dma_request(int * handle, const char * device_id,
++ ep93xx_dma_dev_t device)
++
++This function will allocate a DMA channel for a particular hardware
++peripheral. Before initiating a transfer on the allocated channel, the
++channel has to be setup, and buffers have to be added to the channel.
++
++Parameters:
++ int * handle A pointer which is filled in with a unique
++ integer value, or handle. The handle is used
++ to verify the validity of each call to
++ access the dma channel.
++
++ const char * device_id string which is the name of the device
++ attached to the dma channel.
++
++ ep93xx_dma_dev_t device hardware port to attach to the dma channel
++
++------------------------------------------------------------------------------
++
++ int ep93xx_dma_free(int handle)
++
++This function disables and powers down the dma channel, and releases it
++for future requests. Buffers queued up for the specified channel are
++released without transferring.
++
++Parameters:
++ int handle A unique integer value, assigned
++ during open, used to verify the validity of
++ this call to access a DMA channel.
++
++------------------------------------------------------------------------------
++
++ int ep93xx_dma_add_buffer(int handle, unsigned int source,
++ unsigned int dest, unsigned int size
++ unsigned int last, unsigned int buf_id)
++
++This function adds a buffer entry to the DMA buffer queue. If the channel is
++in the active transfer state, the buffer is immediately transferred,
++otherwise the buffer is not transferred until a start or resume
++command is issued. A -1 is returned if an error occurs, otherwise
++a 0 is returned.
++
++Parameter:
++ int handle A unique integer value, assigned
++ during open, used to verify the validity of
++ this call to access a dma channel.
++
++ unsigned int source physical address for the start of this
++ buffer.
++
++ unsigned int source physical address destination of the data.
++
++ unsigned int size buffer size in bytes
++
++ unsigned int last 1 if this is the last buffer in the transfer.
++ If 1, disable the NFBint so we aren't
++ interrupted for another buffer
++ when we know there won't be another.
++
++ unsigned int buf_id Unique value used to identify this buffer.
++
++------------------------------------------------------------------------------
++
++ int ep93xx_dma_remove_buffer(int handle, unsigned int * address,
++ unsigned int * size)
++
++This function removes a buffer entry from the DMA buffer queue. If a buffer
++was removed successfully, a 0 is returned, otherwise -1 is returned.
++
++Parameter:
++ int handle A unique integer value, assigned
++ during open, used to verify the validity of
++ this call to access a dma channel.
++
++ unsigned int * buf_id Pointer to an integer which is filled in
++ with the buffer id..
++
++------------------------------------------------------------------------------
++
++ int ep93xx_dma_queue_full(int handle)
++
++This function queries to determine if the buffer queue for the specified
++channel is full. A return value of 1 indicates the queue is not full, and a
++0 indicates the queue is full.
++
++Parameters:
++ int handle A unique integer value, assigned
++ during open, used to verify the validity of
++ this call to access a dma channel.
++
++------------------------------------------------------------------------------
++
++ int ep93xx_dma_get_position(int handle, unsigned int * buf_id,
++ unsigned int * total)
++
++This function fills in the buffer ID of the current buffer and fills in the
++total bytes transferred on the channel. If no buffer is active on the channel,
++buf_id is filled in with a -1, otherwise it is the active buffer.
++
++Parameter:
++ int handle A unique integer value, assigned
++ during open, used to verify the validity of
++ this call to access a dma channel.
++
++ unsigned int * buf_id pointer to an integer which is filled in with
++ buffer ID of the buffer currently
++ transferring.
++
++ unsigned int * total pointer to an integer which is filled in
++ with the total bytes transferred on the channel.
++
++------------------------------------------------------------------------------
++
++ int ep93xx_dma_config(int handle, unsigned int flags_m2m,
++ unsigned int flags_m2p, dma_callback callback,
++ unsigned int user_data)
++
++This function configures the DMA channel registers and installs a dma
++callback function into the DMA instance. The DMA callback function is
++defined by the driver which is using this DMA channel. It is called in
++response to DMA interrupts, at the end of the DMA channel's interrupt
++handler. A -1 is returned if an error occurs, otherwise a 0 is returned.
++
++Parameter:
++ int handle A unique integer value, assigned
++ during open, used to verify the validity of
++ this call to access a dma channel.
++
++ unsigned int flags_m2m Flags used for M2M channel configuration.
++
++ unsigned int flags_m2p Flags used for M2P/P2M channel
++ configuration.
++
++ dma_callback callback Pointer to the callback function which will
++ be called at the end of the dma interrupt
++ service routine.
++
++ unsigned int user_data Data defined by the driver installing the
++ callback function. This piece of data will
++ be returned to the driver when the callback
++ function is called.
++
++Callback function prototype:
++
++ void (* dma_callback)(ep93xx_dma_int_t interrupt,
++ ep93xx_dma_dev_t device, unsigned int user_data)
++
++ Parameters:
++ ep93xx_dma_int_t interrupt
++ used by the DMA driver to inform the DMA callback
++ function of the type of DMA interrupt that happened.
++
++ ep93xx_dma_dev_t device
++ hardware port attached to the dma channel.
++
++ unsigned int user_data
++ is a value defined and passed in by the driver which
++ registered the callback function.
++
++------------------------------------------------------------------------------
++
++ int ep93xx_dma_start(int handle, unsigned int channels,
++ unsigned int * handles
++
++This function enables the DMA channel, and initiates the transfer. If the
++peripheral interface calls for it, multiple DMA channels can be started
++with one call to this IOCTL. A -1 is returned if an error occurs,
++otherwise a 0 is returned.
++
++Parameter:
++ int handle A unique integer value, assigned
++ during open, used to verify the validity of
++ this call to access a dma channel. For a start
++ multiple, this handle can be the handle
++ for any of the channels to be started.
++
++ unsigned int channels Number of channels to start for this transfer.
++ Specifically this applies to an audio interface
++ where you can have up to 3 dma channels
++ servicing a 6 audio channel output, in which case
++ you need to initiate transfers on all 3 dma
++ channels as closely together as possible. For
++ the case of only one channel to be started, this
++ field should be a 1.
++
++ unsigned int * handles Pointer to an array of handles, one for
++ each channel which is to be started. If only one
++ channel is to be started, this field should be
++ NULL.
++
++------------------------------------------------------------------------------
++
++ int ep93xx_dma_pause(int handle, unsigned int channels,
++ unsigned int * handles)
++
++This function disables the DMA channel, pausing the transfer. The
++position within the currently transferring buffer is saved, and restored upon
++restarting the transfer on this channel. If the peripheral interface calls
++for it, multiple DMA channels can be paused with one call to this IOCTL.
++A -1 is returned if an error occurs, otherwise a 0 is returned.
++
++Parameter:
++ int handle A unique integer value, assigned
++ during open, used to verify the validity of
++ this call to access a dma channel.
++
++ unsigned int channels Number of channels to pause for this
++ transfer. Specifically this applies to
++ an audio interface where you can have
++ up to 3 dma channels servicing a 6
++ audio channel output, in which case you
++ need to pause transfers on all 3 dma
++ channels as closely together as possible.
++
++ unsigned int * handles Pointer to an array of handles, one for
++ each channel which is to be paused.
++
++NOTE: There is another way to pause the DMA channel - starve it.
++When the dma channel reaches the point where there are no buffers in
++the queue, but the interface has not been paused, then the dma instance
++will indicate that the channel is in the transfer state, but the
++channel itself is disabled until a new buffer is added to the queue
++If the channel is stopped via this method, a resume command is not
++required to restart a transfer. A transfer is started immediately
++after two new buffers are added to the queue. The reason for two is
++so that both channel buffer descriptors can be programmed with valid
++buffers
++
++------------------------------------------------------------------------------
++
++ int ep93xx_dma_flush(int handle)
++
++This function completely flushes all queued buffers and any on going
++DMA transfers on a given channel. If the dma channel is in the
++active transfer state, once two buffers are added to the queue, the
++channel will begin transferring data right away. If in the stop
++state, a start command must be issued before any new buffers are
++processed. A -1 is returned if an error occurs, otherwise a 0 is returned.
++
++Parameters:
++ int handle A unique integer value, assigned
++ during open, used to verify the validity of
++ this call to access a dma channel.
+diff --git a/Documentation/arm/ep93xx/status.txt b/Documentation/arm/ep93xx/status.txt
+new file mode 100644
+index 0000000..082c2dd
+--- /dev/null
++++ b/Documentation/arm/ep93xx/status.txt
+@@ -0,0 +1,288 @@
++#
++# EP93xx driver support status
++#
++
++======================================================================
++(I) Introduction
++======================================================================
++
++The EP93xx are embedded System On Chip (SOC) processors produced
++by Cirrus (www.cirrus.com). They provided support based on 2.4.21-rmk1
++kernels, and they said that there might be 2.6.x support some day.
++Meanwhile they've released a 2.6.8.1 based kernel called "ursus".
++
++Currently we still have got a communication problem with cirrus,
++for some reason it seems to be impossible to directly talk to their
++developers. Hope this will change some day, but we really cannot afford
++to just sit down and wait.
++
++The purpose of this file is to document success and todo's.
++
++ - Section II describes hardware support, organized according to the
++ EP9315 datasheet. Other device datasheets are ordered similarly,
++ though section numbers may vary.
++
++ - Section III contains other miscellaneous information.
++
++The latest version of this document may be found at:
++
++ linux/Documentation/arm/ep93xx/status.txt
++
++projects homepage can be found at:
++
++ http://members.inode.at/m.burian/ep93xx/index.html
++
++
++======================================================================
++(II) Hardware Support
++======================================================================
++
++These section numbers mirror the EP9315 datasheet.
++
++1. Introduction
++---------------
++N/A
++
++2. ARM920T Core and Advanced High-Speed Bus (AHB)
++-------------------------------------------------
++We have standard Linux 2.6 support for ARM920T Core. Thumb support
++is pretty shaky, as most people do not seem to use Thumb in the
++kernel. Address translation uses 16K small pages exclusively (FIXME:
++is this true?)
++
++3. MaverickCrunch Coprocessor
++-----------------------------
++People have started with forward porting. Note that there's more
++to it than just kernel support. You also need to have a toolchain
++supporting it. We're in need of a comprehensive HOWTO that explains kernel,
++toolchain and userspace aspects to a point where average developers can use it
++
++
++4. Boot ROM
++-----------
++Well, not really kernel related, most people start with redboot. Make
++sure to use a version that passes the correct machine type. Some
++people also started porting blob / uboot.
++
++If any support is added for this device, it will likely be a simple
++char device that allows you to read the contents of the boot rom
++for interests sake.
++
++5. System Controller
++--------------------
++System Controllers registers are set by startup code and by individual
++drivers as needed, we try to keep the processor dependent stuff to
++a minimum.
++
++Ray really wants to overhaul the system configuration stuff and move
++towards something like the SA1100 people are doing. It should make
++things a lot cleaner for drivers that share physical pins, or for
++multifunctional blocks that require several drivers (eg: UART2 with
++IrDA support)
++
++There is currently no dynamic clock control support. We'll probably
++want to tie into the CPUfreq code at some point.
++
++There is no support for querying the system boot configuration or
++last reset source.
++
++There is no power management support. Individual drivers may power
++up silicon blocks as required. Some research is needed to map the
++EP93xx power states onto the ACPI or PCI states that everyone seems
++to use.
++
++There is no support for the TICK and WATCHDOGEXPIRED interrupts
++generated by this block.
++
++There is no support for the AHB bus arbiter priority settings.
++
++6. Vectored Interrupt Controller
++--------------------------------
++Since we can boot this can't be done dead wrong. Standard level-triggered
++interrupt support is present.
++
++No FIQ interrupts are supported.
++
++Support for demultiplexing GPIO IRQs is available.
++
++
++7. Raster Engine With Analog/LCD Integrated Timing and Interface
++----------------------------------------------------------------
++
++Michael has rewritten large parts of the framebuffer driver based on
++skeleton.c. You need to adapt this in case you can't live with
++the standard display(s) that are included. Framebuffer is fixed
++size, you can change some settings at compile time, though.
++TODO: clean ups, different resolutions, etc
++
++
++8. Graphics Accelerator
++-----------------------
++not available yet, will be done after the framebuffer code has been
++cleaned up.
++
++
++9. 1/10/100 Mbps Ethernet LAN Controller
++----------------------------------------
++Supported. Driver has been reviewed and cleaned up.
++Uses generic mii routines now. It might be possible
++to use DMA - but in that case we'd need to find a
++workaround to get around the fact that it can only
++transfer 32bit aligned data, while we'd need to transfer
++data that's only 16 bit aligned.
++
++NICE-TO-HAVE: Could be ported to use NAPI.
++
++10. DMA Controller
++------------------
++There is some code and documentation ported forward from the Cirrus
++2.4 port.
++
++11. Universal Serial Bus Host Controller
++----------------------------------------
++Ray has written some glue code to plug the OHCI host controller into
++the Linux 2.6 USB stack. This has been tested on an EDB9301 board with
++a single port populated. A serial dongle worked fine, and several
++different flash keys seem to work okay with the USB mass storage
++driver using SCSI disk emulation. This hasn't really been stress tested
++yet, but initial results look very encouraging.
++
++12. Static Memory Controller
++----------------------------
++Not sure how much kernel support is required here. Flash and memory
++timing needs to be setup by the bootloader, so there's not much
++that needs to be done here.
++
++No support for PCMCIA at this time.
++
++13. SDRAM, SyncROM, and SyncFLASH Controller
++--------------------------------------------
++Again, this is probably the bootloaders problem.
++
++There is an errata about system instability when suspending with
++an SDRAM bus speed over 50 MHz. May need to tweak this if we start
++doing power management modes.
++
++14. UART1 With HDLC and Modem Control Signals
++---------------------------------------------
++We've got a driver to use this one as UART. No DMA support. FIFO support
++works. No HDLC support. Needs some syscon support to cleanly handle
++HDLC and some modem signals.
++
++15. UART2
++---------
++We've got a driver to use this one as UART. No DMA support. FIFO support
++works. No IrDA SIR support. Needs some syscon support to cleanly handle
++IrDA SIR.
++
++16. UART3 With HDLC Encoder
++---------------------------
++We've got a driver to use this one as UART. No DMA support. FIFO support
++works. No HDLC or RS-485 support. Needs some syscon support to cleanly
++handle HDLC and RS-485.
++
++17. IRDA
++--------
++There is some code and documentation ported forward from the Cirrus
++2.4 port. No idea how well this works, if at all.
++
++18. TIMERS
++----------
++Timer1 is used at 508 kHz with a reload value of 5080 to provide a 100 Hz
++tick signal to drive the kernel.
++
++Timer 2 and 3 are not currently used, nor is the debug timer 4.
++
++
++19. WATCHDOG Timer
++------------------
++Ray has some initial experimental code written (not pushed) to drive this.
++The onboard watchdog seems to have a 250 ms (!) timeout, while most PC
++dogs seem to have timeouts on the order of one minute or more. The standard
++approach of having a user level process open the watchdog device and
++kick it every so often seems like a bad idea here... a momentary system
++load spike could easily delay the monitor from being scheduled, and the
++system would reboot.
++
++Test out a watchdog monitor running at a high scheduling priority, or else
++design a kernel watchdog that kicks the dog every timer tick and exports
++a more reasonable timeout value to userspace.
++
++20. Real Time Clock With Software Trim
++--------------------------------------
++We did not bother to write a driver yet, it would require a design
++that ensures CPU is always powered on, and always have at least
++a 32kHz clock running. Most people prefer to use and external RTC.
++We've got support for the DS1337 RTC that seems to be popular on
++ep93xx based boards.
++
++21. I2S Controller
++------------------
++No support yet. Klaus is working on it.
++
++22. AC97 Controller
++-------------------
++Supported but could need some testing.
++
++23. Synchronous Serial Port
++---------------------------
++Two driver are available, a forward port from the cirrus driver and
++another driver from Ray.
++
++24. Pulse Width Modulator
++-------------------------
++No support yet.
++
++25. Analog Touch Screen Interface
++---------------------------------
++People already played with this, AFAIK one would need a silicon
++revision > D1 (November 2004) for this to work properly.
++
++26. Keypad Interface
++--------------------
++We've got a driver for the 8x8 keypad. Chances are that you might
++want to create a custom keymap. There's also support for mobile
++phone like input (key 1 becomes -> A -> B -> C) if pressed repeatedly
++within half a second.
++
++27. IDE interface
++-----------------
++We've got IDE working in polling only, no DMA support so far.
++It needs to be cleaned up, too.
++
++28. GPIO
++--------
++Standard LED support for red and green leds is present.
++
++Michael has written an I2C bus driver using the new Linux device driver model.
++It supports an external DS1337 RTC device on the EECLK/EEDAT pins.
++
++Need some syscon support to cleanly handle the multi-function GPIO pins.
++
++Demultiplexing of GPIO interrupts is possible now.
++
++29. Security
++------------
++No information available on this, so support is unlikely in the near future.
++
++30. Glossary
++------------
++N/A
++
++
++======================================================================
++(III) Stuff not found in the datasheet
++======================================================================
++
++1. printascii hack has been removed from our tree.
++
++2. I2C driver
++We've got a bit banging I2C driver
++
++3. External RTC (DS1337)
++Setting and getting the time works
++TODO: advanced features, such as alarm, timer for /dev/rtc
++
++4. Controller Area Network (CAN)
++We have got a character device based driver for the OKI ML9620 CAN Controller.
++
+diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
+index 4b15f5f..f23341e 100644
+--- a/arch/arm/Kconfig
++++ b/arch/arm/Kconfig
+@@ -103,6 +103,17 @@ config ARCH_EBSA110
+ Ethernet interface, two PCMCIA sockets, two serial ports and a
+ parallel port.
+
++config ARCH_EP93XX
++ bool "EP93xx"
++ select ARM_AMBA
++ help
++ Say Y here to enable support for the Cirrus EP93xx CPU family
++ and choose your specific CPU below.
++
++ See the Cirrus web page for details.
++
++ <http://www.cirrus.com/>
++
+ config ARCH_CAMELOT
+ bool "Epxa10db"
+ help
+@@ -219,6 +230,8 @@ endchoice
+
+ source "arch/arm/mach-clps711x/Kconfig"
+
++source "arch/arm/mach-ep93xx/Kconfig"
++
+ source "arch/arm/mach-epxa10db/Kconfig"
+
+ source "arch/arm/mach-footbridge/Kconfig"
+@@ -403,7 +416,7 @@ config NO_IDLE_HZ
+
+ config ARCH_DISCONTIGMEM_ENABLE
+ bool
+- default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM)
++ default (ARCH_LH7A40X && !LH7A40X_CONTIGMEM) || ARCH_EP93XX
+ help
+ Say Y to support efficient handling of discontiguous physical memory,
+ for architectures which are either NUMA (Non-Uniform Memory Access)
+@@ -415,7 +428,7 @@ source "mm/Kconfig"
+ config LEDS
+ bool "Timer and CPU usage LEDs"
+ depends on ARCH_CDB89712 || ARCH_CO285 || ARCH_EBSA110 || \
+- ARCH_EBSA285 || ARCH_IMX || ARCH_INTEGRATOR || \
++ ARCH_EBSA285 || ARCH_EP93XX || ARCH_IMX || ARCH_INTEGRATOR || \
+ ARCH_LUBBOCK || MACH_MAINSTONE || ARCH_NETWINDER || \
+ ARCH_OMAP || ARCH_P720T || ARCH_PXA_IDP || \
+ ARCH_SA1100 || ARCH_SHARK || ARCH_VERSATILE
+@@ -432,7 +445,7 @@ config LEDS
+
+ config LEDS_TIMER
+ bool "Timer LED" if (!ARCH_CDB89712 && !ARCH_OMAP) || \
+- MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
++ MACH_OMAP_H2 || MACH_OMAP_PERSEUS2
+ depends on LEDS
+ default y if ARCH_EBSA110
+ help
+@@ -702,9 +715,10 @@ source "drivers/block/Kconfig"
+
+ source "drivers/acorn/block/Kconfig"
+
+-if PCMCIA || ARCH_CLPS7500 || ARCH_IOP3XX || ARCH_IXP4XX \
+- || ARCH_L7200 || ARCH_LH7A40X || ARCH_PXA || ARCH_RPC \
+- || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK || FOOTBRIDGE
++if PCMCIA || ARCH_CLPS7500 || ARCH_EP9312 || ARCH_EP9315 \
++ || ARCH_IOP3XX || ARCH_IXP4XX || ARCH_L7200 || ARCH_LH7A40X \
++ || ARCH_PXA || ARCH_RPC || ARCH_S3C2410 || ARCH_SA1100 || ARCH_SHARK \
++ || FOOTBRIDGE
+ source "drivers/ide/Kconfig"
+ endif
+
+diff --git a/arch/arm/Makefile b/arch/arm/Makefile
+index 81bd219..924d31f 100644
+--- a/arch/arm/Makefile
++++ b/arch/arm/Makefile
+@@ -92,6 +92,7 @@ textaddr-$(CONFIG_ARCH_FORTUNET) := 0x
+ machine-$(CONFIG_ARCH_IOP3XX) := iop3xx
+ machine-$(CONFIG_ARCH_IXP4XX) := ixp4xx
+ machine-$(CONFIG_ARCH_IXP2000) := ixp2000
++ machine-$(CONFIG_ARCH_EP93XX) := ep93xx
+ machine-$(CONFIG_ARCH_OMAP1) := omap1
+ machine-$(CONFIG_ARCH_OMAP2) := omap2
+ incdir-$(CONFIG_ARCH_OMAP) := omap
+diff --git a/arch/arm/configs/adssphere_defconfig b/arch/arm/configs/adssphere_defconfig
+new file mode 100644
+index 0000000..195d80e
+--- /dev/null
++++ b/arch/arm/configs/adssphere_defconfig
+@@ -0,0 +1,1240 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.12.2
++# Wed Jul 6 13:49:08 2005
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++CONFIG_GENERIC_IOMAP=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_CLEAN_COMPILE=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_SYSCTL=y
++# CONFIG_AUDIT is not set
++CONFIG_HOTPLUG=y
++CONFIG_KOBJECT_UEVENT=y
++# CONFIG_IKCONFIG is not set
++# CONFIG_EMBEDDED is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++CONFIG_CC_ALIGN_FUNCTIONS=0
++CONFIG_CC_ALIGN_LABELS=0
++CONFIG_CC_ALIGN_LOOPS=0
++CONFIG_CC_ALIGN_JUMPS=0
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++# CONFIG_MODULE_FORCE_UNLOAD is not set
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++# CONFIG_KMOD is not set
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_H720X is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++CONFIG_ARCH_EP9315=y
++# CONFIG_MACH_EDB9315 is not set
++CONFIG_MACH_ADSSPHERE=y
++# CONFIG_MACH_ZEFEERDZQ is not set
++CONFIG_EP93XX_DMA=y
++# CONFIG_ARCH_EP93XX_IDE is not set
++# CONFIG_EP93XX_SSP is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_THUMB is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++CONFIG_ISA_DMA_API=y
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++CONFIG_PCCARD=y
++# CONFIG_PCMCIA_DEBUG is not set
++CONFIG_PCMCIA=y
++
++#
++# PC-card bridges
++#
++# CONFIG_TCIC is not set
++CONFIG_PCMCIA_EP93XX=y
++
++#
++# Kernel Features
++#
++# CONFIG_SMP is not set
++# CONFIG_PREEMPT is not set
++CONFIG_DISCONTIGMEM=y
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++# CONFIG_LEDS_CPU is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="console=ttyAM0,38400 rw root=/dev/ram initrd=0x00600000,5m ramdisk_size=12288 rootfstype=ext2 mtdparts=flash:256k(boot),256k(bootvars),1536k(zImage),5m(ramdisk.gz),-(flashfs1) SERIALGETTY=ttyAM0 SERIALBAUD=38400"
++# CONFIG_XIP_KERNEL is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++CONFIG_FW_LOADER=y
++# CONFIG_DEBUG_DRIVER is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL 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=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++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
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++CONFIG_MTD_ADSFLASH=y
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 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_BLKMTD 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
++
++#
++# NAND Flash Device Drivers
++#
++# CONFIG_MTD_NAND is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# 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_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=4096
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CDROM_PKTCDVD is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# ATA/ATAPI/MFM/RLL support
++#
++CONFIG_IDE=y
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++CONFIG_BLK_DEV_IDECS=y
++# CONFIG_BLK_DEV_IDECD is not set
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++CONFIG_BLK_DEV_EP93XX=y
++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
++CONFIG_IDE_ARM=y
++# CONFIG_BLK_DEV_IDEDMA is not set
++# CONFIG_IDEDMA_AUTO is not set
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI=y
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# PCMCIA SCSI adapter support
++#
++# CONFIG_PCMCIA_AHA152X is not set
++# CONFIG_PCMCIA_FDOMAIN is not set
++# CONFIG_PCMCIA_NINJA_SCSI is not set
++# CONFIG_PCMCIA_QLOGIC is not set
++# CONFIG_PCMCIA_SYM53C500 is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Fusion MPT device support
++#
++
++#
++# IEEE 1394 (FireWire) support
++#
++
++#
++# I2O device support
++#
++
++#
++# Networking support
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++# CONFIG_NET_KEY is not set
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++CONFIG_IP_MROUTE=y
++# CONFIG_IP_PIMSM_V1 is not set
++# CONFIG_IP_PIMSM_V2 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_TUNNEL is not set
++CONFIG_IP_TCPDIAG=y
++# CONFIG_IP_TCPDIAG_IPV6 is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++CONFIG_BT=y
++CONFIG_BT_L2CAP=y
++# CONFIG_BT_SCO is not set
++# CONFIG_BT_RFCOMM is not set
++CONFIG_BT_BNEP=y
++# CONFIG_BT_BNEP_MC_FILTER is not set
++# CONFIG_BT_BNEP_PROTO_FILTER is not set
++# CONFIG_BT_HIDP is not set
++
++#
++# Bluetooth device drivers
++#
++CONFIG_BT_HCIUSB=y
++# CONFIG_BT_HCIUSB_SCO is not set
++# CONFIG_BT_HCIUART is not set
++# CONFIG_BT_HCIBCM203X is not set
++# CONFIG_BT_HCIBPA10X is not set
++# CONFIG_BT_HCIBFUSB is not set
++# CONFIG_BT_HCIDTL1 is not set
++# CONFIG_BT_HCIBT3C is not set
++# CONFIG_BT_HCIBLUECARD is not set
++# CONFIG_BT_HCIBTUART is not set
++# CONFIG_BT_HCIVHCI is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++CONFIG_NET_RADIO=y
++
++#
++# Obsolete Wireless cards support (pre-802.11)
++#
++# CONFIG_STRIP is not set
++# CONFIG_PCMCIA_WAVELAN is not set
++# CONFIG_PCMCIA_NETWAVE is not set
++
++#
++# Wireless 802.11 Frequency Hopping cards support
++#
++# CONFIG_PCMCIA_RAYCS is not set
++
++#
++# Wireless 802.11b ISA/PCI cards support
++#
++CONFIG_HERMES=y
++CONFIG_ATMEL=y
++
++#
++# Wireless 802.11b Pcmcia/Cardbus cards support
++#
++CONFIG_PCMCIA_HERMES=y
++CONFIG_AIRO_CS=y
++CONFIG_PCMCIA_ATMEL=y
++CONFIG_PCMCIA_WL3501=y
++CONFIG_NET_WIRELESS=y
++
++#
++# PCMCIA network device support
++#
++CONFIG_NET_PCMCIA=y
++# CONFIG_PCMCIA_3C589 is not set
++# CONFIG_PCMCIA_3C574 is not set
++# CONFIG_PCMCIA_FMVJ18X is not set
++CONFIG_PCMCIA_PCNET=y
++# CONFIG_PCMCIA_NMCLAN is not set
++# CONFIG_PCMCIA_SMC91C92 is not set
++# CONFIG_PCMCIA_XIRC2PS is not set
++# CONFIG_PCMCIA_AXNET is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# CONFIG_INPUT_JOYDEV is not set
++CONFIG_INPUT_TSDEV=y
++CONFIG_INPUT_TSDEV_SCREEN_X=640
++CONFIG_INPUT_TSDEV_SCREEN_Y=480
++CONFIG_INPUT_EVDEV=y
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++# CONFIG_KEYBOARD_EP93XX is not set
++CONFIG_INPUT_MOUSE=y
++# CONFIG_MOUSE_PS2 is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++CONFIG_TOUCHSCREEN_EP93XX=y
++# 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_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++
++#
++# Watchdog Cards
++#
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_EP93XX_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++# CONFIG_EP93XX_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_DRM is not set
++
++#
++# PCMCIA character devices
++#
++# CONFIG_SYNCLINK_CS is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Hardware Sensors Chip support
++#
++CONFIG_I2C_SENSOR=y
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++
++#
++# Other I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++CONFIG_SENSORS_DS1307=y
++CONFIG_SENSORS_EEPROM=y
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# Misc devices
++#
++
++#
++# Multimedia devices
++#
++CONFIG_VIDEO_DEV=y
++
++#
++# Video For Linux
++#
++
++#
++# Video Adapters
++#
++# CONFIG_VIDEO_CPIA is not set
++# CONFIG_VIDEO_SAA5246A is not set
++# CONFIG_VIDEO_SAA5249 is not set
++# CONFIG_TUNER_3036 is not set
++# CONFIG_VIDEO_OVCAMCHIP is not set
++
++#
++# Radio Adapters
++#
++# CONFIG_RADIO_MAESTRO is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# Graphics support
++#
++CONFIG_FB=y
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++CONFIG_FB_SOFT_CURSOR=y
++# CONFIG_FB_MACMODES is not set
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_TILEBLITTING is not set
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_CX25871_I2C is not set
++CONFIG_FB_EP93XX=y
++# CONFIG_FB_CRT_EP93XX is not set
++# CONFIG_FB_LCD_EP93XX is not set
++# CONFIG_FB_LCD_EP93XX_SHARP is not set
++CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343=y
++# CONFIG_FB_CX25871 is not set
++# CONFIG_FB_EP93XX_8BPP is not set
++CONFIG_FB_EP93XX_16BPP_565=y
++# CONFIG_FB_EP93XX_24BPP is not set
++# CONFIG_FB_EP93XX_32BPP is not set
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++# CONFIG_FONT_MINI_4x6 is not set
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++
++#
++# Logo configuration
++#
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_LOGO_LINUX_CLUT224=y
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++# CONFIG_SND is not set
++
++#
++# Open Sound System
++#
++CONFIG_SOUND_PRIME=y
++# CONFIG_SOUND_BT878 is not set
++# CONFIG_SOUND_FUSION is not set
++# CONFIG_SOUND_CS4281 is not set
++# CONFIG_SOUND_SONICVIBES is not set
++# CONFIG_SOUND_TRIDENT is not set
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++CONFIG_SOUND_OSS=y
++# CONFIG_SOUND_TRACEINIT is not set
++# CONFIG_SOUND_DMAP is not set
++# CONFIG_SOUND_AD1816 is not set
++# CONFIG_SOUND_SGALAXY is not set
++# CONFIG_SOUND_ADLIB is not set
++# CONFIG_SOUND_ACI_MIXER is not set
++# CONFIG_SOUND_CS4232 is not set
++# CONFIG_SOUND_SSCAPE is not set
++# CONFIG_SOUND_GUS is not set
++# CONFIG_SOUND_VMIDI is not set
++# CONFIG_SOUND_TRIX is not set
++# CONFIG_SOUND_MSS is not set
++# CONFIG_SOUND_MPU401 is not set
++# CONFIG_SOUND_NM256 is not set
++# CONFIG_SOUND_MAD16 is not set
++# CONFIG_SOUND_PAS is not set
++# CONFIG_SOUND_PSS is not set
++# CONFIG_SOUND_SB is not set
++# CONFIG_SOUND_AWE32_SYNTH is not set
++# CONFIG_SOUND_WAVEFRONT is not set
++# CONFIG_SOUND_MAUI is not set
++# CONFIG_SOUND_YM3812 is not set
++# CONFIG_SOUND_OPL3SA1 is not set
++# CONFIG_SOUND_OPL3SA2 is not set
++# CONFIG_SOUND_UART6850 is not set
++# CONFIG_SOUND_AEDSP16 is not set
++CONFIG_SOUND_EP93XX_AC97=y
++# CONFIG_SOUND_TVMIXER is not set
++# CONFIG_SOUND_AD1980 is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++# CONFIG_USB_ARCH_HAS_OHCI is not set
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++# CONFIG_USB_BANDWIDTH is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_SL811_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_AUDIO is not set
++
++#
++# USB Bluetooth TTY can only be used with disabled Bluetooth subsystem
++#
++# CONFIG_USB_MIDI is not set
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++CONFIG_USB_HIDINPUT=y
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB Multimedia devices
++#
++# CONFIG_USB_DABUSB is not set
++# CONFIG_USB_VICAM is not set
++# CONFIG_USB_DSBR is not set
++# CONFIG_USB_IBMCAM is not set
++# CONFIG_USB_KONICAWC is not set
++CONFIG_USB_OV511=y
++# CONFIG_USB_SE401 is not set
++# CONFIG_USB_SN9C102 is not set
++# CONFIG_USB_STV680 is not set
++# CONFIG_USB_PWC is not set
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++CONFIG_USB_PEGASUS=y
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_USB_ZD1201 is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGETKIT is not set
++# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_IDMOUSE is not set
++
++#
++# USB ATM/DSL drivers
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++
++#
++# XFS support
++#
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++# CONFIG_MSDOS_FS is not set
++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_SYSFS=y
++# CONFIG_DEVFS_FS is not set
++CONFIG_DEVPTS_FS_XATTR=y
++# CONFIG_DEVPTS_FS_SECURITY is not set
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_XATTR is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++# CONFIG_JFFS2_FS_NAND is not set
++# CONFIG_JFFS2_FS_NOR_ECC is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++CONFIG_CRAMFS=y
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_SUNRPC=y
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++CONFIG_NLS_CODEPAGE_850=y
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 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=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_FS is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_LL is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Hardware crypto devices
++#
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++# CONFIG_LIBCRC32C is not set
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/dma03_defconfig b/arch/arm/configs/dma03_defconfig
+new file mode 100644
+index 0000000..59b677c
+--- /dev/null
++++ b/arch/arm/configs/dma03_defconfig
+@@ -0,0 +1,1281 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.15-rc4
++# Fri Dec 9 21:21:27 2005
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++# CONFIG_CLEAN_COMPILE is not set
++CONFIG_BROKEN=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_LOCALVERSION_AUTO=y
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_SYSCTL=y
++# CONFIG_AUDIT is not set
++CONFIG_HOTPLUG=y
++CONFIG_KOBJECT_UEVENT=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_EMBEDDED is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++CONFIG_CC_ALIGN_FUNCTIONS=0
++CONFIG_CC_ALIGN_LABELS=0
++CONFIG_CC_ALIGN_LOOPS=0
++CONFIG_CC_ALIGN_JUMPS=0
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# Block layer
++#
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_DEFAULT_AS=y
++# CONFIG_DEFAULT_DEADLINE is not set
++# CONFIG_DEFAULT_CFQ is not set
++# CONFIG_DEFAULT_NOOP is not set
++CONFIG_DEFAULT_IOSCHED="anticipatory"
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_REALVIEW is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_AAEC2000 is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++CONFIG_ARCH_EP9315=y
++# CONFIG_MACH_EDB9315 is not set
++# CONFIG_MACH_ADSSPHERE is not set
++# CONFIG_MACH_ZEFEERDZQ is not set
++CONFIG_MACH_DMA03=y
++CONFIG_ARCH_EP93XX_GPIO_IRQ=y
++CONFIG_EP93XX_DMA=y
++CONFIG_EP93XX_SSP=y
++CONFIG_EP93XX_SSP_CIRRUS=y
++# CONFIG_EP93XX_SSP_LINUX is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_THUMB is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++CONFIG_ISA_DMA_API=y
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_PREEMPT is not set
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
++CONFIG_SELECT_MEMORY_MODEL=y
++# CONFIG_FLATMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM_MANUAL=y
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_NEED_MULTIPLE_NODES=y
++# CONFIG_SPARSEMEM_STATIC is not set
++CONFIG_SPLIT_PTLOCK_CPUS=4096
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="root=/dev/hda1 slram=sram,0x20000000,0x2010000 parport=0xD0000020,74 lp=parport0"
++# CONFIG_XIP_KERNEL is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_AOUT=y
++CONFIG_BINFMT_MISC=y
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_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_TUNNEL is not set
++CONFIG_INET_DIAG=y
++CONFIG_INET_TCP_DIAG=y
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_BIC=y
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++
++#
++# DCCP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_DCCP is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++# CONFIG_IEEE80211 is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++# CONFIG_STANDALONE is not set
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++
++#
++# Connector - unified userspace <-> kernelspace linker
++#
++# CONFIG_CONNECTOR is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_PARTITIONS=y
++CONFIG_MTD_REDBOOT_PARTS=y
++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
++CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL is not set
++# CONFIG_RFD_FTL is not set
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++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=y
++CONFIG_MTD_CFI_AMDSTD_RETRY=0
++CONFIG_MTD_CFI_STAA=y
++CONFIG_MTD_CFI_UTIL=y
++CONFIG_MTD_RAM=y
++CONFIG_MTD_ROM=y
++CONFIG_MTD_ABSENT=y
++# CONFIG_MTD_OBSOLETE_CHIPS is not set
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x60000000
++CONFIG_MTD_PHYSMAP_LEN=0x02000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_IMPA7 is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_SLRAM=y
++CONFIG_MTD_PHRAM=y
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLKMTD 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
++
++#
++# NAND Flash Device Drivers
++#
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++
++#
++# OneNAND Flash Device Drivers
++#
++# CONFIG_MTD_ONENAND is not set
++
++#
++# Parallel port support
++#
++CONFIG_PARPORT=y
++CONFIG_PARPORT_PC=y
++# CONFIG_PARPORT_PC_FIFO is not set
++# CONFIG_PARPORT_PC_SUPERIO is not set
++# CONFIG_PARPORT_ARC is not set
++# CONFIG_PARPORT_GSC is not set
++CONFIG_PARPORT_1284=y
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_PARIDE is not set
++# 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_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=12288
++CONFIG_BLK_DEV_INITRD=y
++# CONFIG_CDROM_PKTCDVD is not set
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# ATA/ATAPI/MFM/RLL support
++#
++CONFIG_IDE=y
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++CONFIG_IDEDISK_MULTI_MODE=y
++CONFIG_BLK_DEV_IDECD=y
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++CONFIG_BLK_DEV_EP93XX=y
++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
++CONFIG_IDE_ARM=y
++# CONFIG_BLK_DEV_IDEDMA is not set
++# CONFIG_IDEDMA_AUTO is not set
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++# CONFIG_RAID_ATTRS is not set
++CONFIG_SCSI=y
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++# CONFIG_SCSI_SAS_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_ISCSI_TCP is not set
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_PPA is not set
++# CONFIG_SCSI_IMM is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Fusion MPT device support
++#
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# PHY device support
++#
++# CONFIG_PHYLIB is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++# CONFIG_NET_POCKET is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PLIP is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++CONFIG_NETCONSOLE=y
++CONFIG_NETPOLL=y
++# CONFIG_NETPOLL_RX is not set
++# CONFIG_NETPOLL_TRAP is not set
++CONFIG_NET_POLL_CONTROLLER=y
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++CONFIG_KEYBOARD_EP93XX=y
++CONFIG_KEYBOARD_EP93XX_SPI=y
++CONFIG_KEYBOARD_EP93XX_8X8=y
++CONFIG_KEYBOARD_EP93XX_8X8_CYCLING=y
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++# CONFIG_TOUCHSCREEN_ELO is not set
++# CONFIG_TOUCHSCREEN_MTOUCH is not set
++# CONFIG_TOUCHSCREEN_MK712 is not set
++CONFIG_TOUCHSCREEN_EP93XX=y
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_PARKBD is not set
++# CONFIG_SERIO_AMBAKMI is not set
++CONFIG_SERIO_LIBPS2=y
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++CONFIG_SERIAL_8250=y
++CONFIG_SERIAL_8250_CONSOLE=y
++CONFIG_SERIAL_8250_NR_UARTS=4
++# CONFIG_SERIAL_8250_EXTENDED is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++CONFIG_PRINTER=m
++# CONFIG_LP_CONSOLE is not set
++CONFIG_PPDEV=m
++# CONFIG_TIPAR is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++
++#
++# Watchdog Cards
++#
++# CONFIG_WATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++# CONFIG_EP93XX_RTC is not set
++CONFIG_DS1337_RTC=y
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++
++#
++# CAN bus devices
++#
++CONFIG_CAN_BUS=y
++CONFIG_OKI_CAN_ML9620=y
++# CONFIG_OKI_CAN_ML9620_MICRO9 is not set
++CONFIG_OKI_CAN_ML9620_GASSNER=y
++CONFIG_OKI_CAN_ML9620_2DEV=y
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++# CONFIG_TCG_TPM is not set
++# CONFIG_TELCLOCK is not set
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_PARPORT is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++CONFIG_SENSORS_DS1337=y
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_SENSORS_DS1307 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_RTC_X1205_I2C is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# Hardware Monitoring support
++#
++CONFIG_HWMON=y
++# CONFIG_HWMON_VID is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83792D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Misc devices
++#
++
++#
++# Multimedia Capabilities Port drivers
++#
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# Graphics support
++#
++CONFIG_FB=y
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++# CONFIG_FB_MACMODES is not set
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_TILEBLITTING is not set
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_CX25871_I2C is not set
++CONFIG_FB_EP93XX=y
++# CONFIG_FB_CRT_EP93XX is not set
++# CONFIG_FB_LCD_EP93XX is not set
++CONFIG_FB_LCD_EP93XX_SHARP=y
++# CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343 is not set
++# CONFIG_FB_CX25871 is not set
++# CONFIG_FB_LCD_TX09D50VM1CCA is not set
++# CONFIG_FB_EP93XX_8BPP is not set
++# CONFIG_FB_EP93XX_16BPP_565 is not set
++# CONFIG_FB_EP93XX_24BPP is not set
++CONFIG_FB_EP93XX_32BPP=y
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++CONFIG_FONT_6x11=y
++CONFIG_FONT_7x14=y
++CONFIG_FONT_PEARL_8x8=y
++CONFIG_FONT_ACORN_8x8=y
++CONFIG_FONT_MINI_4x6=y
++CONFIG_FONT_SUN8x16=y
++CONFIG_FONT_SUN12x22=y
++CONFIG_FONT_10x18=y
++
++#
++# Logo configuration
++#
++# CONFIG_LOGO is not set
++CONFIG_BACKLIGHT_LCD_SUPPORT=y
++CONFIG_BACKLIGHT_CLASS_DEVICE=y
++CONFIG_BACKLIGHT_DEVICE=y
++CONFIG_LCD_CLASS_DEVICE=y
++CONFIG_LCD_DEVICE=y
++
++#
++# Sound
++#
++CONFIG_SOUND=m
++
++#
++# Advanced Linux Sound Architecture
++#
++# CONFIG_SND is not set
++
++#
++# Open Sound System
++#
++CONFIG_SOUND_PRIME=m
++# CONFIG_OBSOLETE_OSS_DRIVER is not set
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++CONFIG_SOUND_OSS=m
++# CONFIG_SOUND_TRACEINIT is not set
++# CONFIG_SOUND_DMAP is not set
++# CONFIG_SOUND_AD1816 is not set
++# CONFIG_SOUND_ADLIB is not set
++# CONFIG_SOUND_ACI_MIXER is not set
++# CONFIG_SOUND_VMIDI is not set
++# CONFIG_SOUND_TRIX is not set
++# CONFIG_SOUND_MSS is not set
++# CONFIG_SOUND_MPU401 is not set
++# CONFIG_SOUND_PAS is not set
++# CONFIG_SOUND_PSS is not set
++# CONFIG_SOUND_SB is not set
++# CONFIG_SOUND_OPL3SA2 is not set
++# CONFIG_SOUND_UART6850 is not set
++# CONFIG_SOUND_AEDSP16 is not set
++CONFIG_SOUND_EP93XX_AC97=m
++CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297=y
++# CONFIG_SOUND_EP93XX_AUDIO_PIO is not set
++# CONFIG_SOUND_TVMIXER is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_BANDWIDTH is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set
++# CONFIG_USB_ACM is not set
++CONFIG_USB_PRINTER=y
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
++#
++
++#
++# may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++CONFIG_USB_STORAGE_DATAFAB=y
++CONFIG_USB_STORAGE_FREECOM=y
++CONFIG_USB_STORAGE_ISD200=y
++CONFIG_USB_STORAGE_DPCM=y
++CONFIG_USB_STORAGE_USBAT=y
++CONFIG_USB_STORAGE_SDDR09=y
++CONFIG_USB_STORAGE_SDDR55=y
++CONFIG_USB_STORAGE_JUMPSHOT=y
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++CONFIG_USB_HIDINPUT=y
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_ACECAD is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_ITMTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_YEALINK is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++# CONFIG_USB_KEYSPAN_REMOTE is not set
++# CONFIG_USB_APPLETOUCH is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB Multimedia devices
++#
++# CONFIG_USB_DABUSB is not set
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++# CONFIG_USB_USS720 is not set
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGETKIT is not set
++# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++CONFIG_REISERFS_FS=y
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_REISERFS_FS_XATTR is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++CONFIG_ROMFS_FS=y
++CONFIG_INOTIFY=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++CONFIG_AUTOFS_FS=y
++# CONFIG_AUTOFS4_FS is not set
++CONFIG_FUSE_FS=y
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_ZISOFS_FS=y
++CONFIG_UDF_FS=y
++CONFIG_UDF_NLS=y
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=850
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++CONFIG_NTFS_FS=y
++# CONFIG_NTFS_DEBUG is not set
++# CONFIG_NTFS_RW is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++CONFIG_TMPFS=y
++# CONFIG_HUGETLBFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++CONFIG_RELAYFS_FS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_SUMMARY is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++CONFIG_9P_FS=y
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++CONFIG_NLS_CODEPAGE_850=y
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++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=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_LOG_BUF_SHIFT=17
++# CONFIG_DETECT_SOFTLOCKUP is not set
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_FS is not set
++# CONFIG_DEBUG_VM is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_RCU_TORTURE_TEST is not set
++CONFIG_DEBUG_USER=y
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++CONFIG_CRYPTO=y
++CONFIG_CRYPTO_HMAC=y
++CONFIG_CRYPTO_NULL=y
++CONFIG_CRYPTO_MD4=y
++CONFIG_CRYPTO_MD5=y
++CONFIG_CRYPTO_SHA1=y
++CONFIG_CRYPTO_SHA256=y
++CONFIG_CRYPTO_SHA512=y
++CONFIG_CRYPTO_WP512=y
++CONFIG_CRYPTO_TGR192=y
++CONFIG_CRYPTO_DES=y
++CONFIG_CRYPTO_BLOWFISH=y
++CONFIG_CRYPTO_TWOFISH=y
++CONFIG_CRYPTO_SERPENT=y
++CONFIG_CRYPTO_AES=y
++CONFIG_CRYPTO_CAST5=y
++CONFIG_CRYPTO_CAST6=y
++CONFIG_CRYPTO_TEA=y
++CONFIG_CRYPTO_ARC4=y
++CONFIG_CRYPTO_KHAZAD=y
++CONFIG_CRYPTO_ANUBIS=y
++CONFIG_CRYPTO_DEFLATE=y
++CONFIG_CRYPTO_MICHAEL_MIC=y
++CONFIG_CRYPTO_CRC32C=y
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Hardware crypto devices
++#
++
++#
++# Library routines
++#
++CONFIG_CRC_CCITT=y
++CONFIG_CRC16=y
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/edb9301_defconfig b/arch/arm/configs/edb9301_defconfig
+new file mode 100644
+index 0000000..e105976
+--- /dev/null
++++ b/arch/arm/configs/edb9301_defconfig
+@@ -0,0 +1,965 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.9-rc2-ep93xx
++# Mon Nov 8 16:32:53 2004
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_IOMAP=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_CLEAN_COMPILE=y
++CONFIG_BROKEN_ON_SMP=y
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_SYSCTL=y
++# CONFIG_AUDIT is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_HOTPLUG=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_EMBEDDED=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++CONFIG_IOSCHED_DEADLINE=y
++# CONFIG_IOSCHED_CFQ is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++# CONFIG_TINY_SHMEM is not set
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE_PB is not set
++# CONFIG_ARCH_IMX is not set
++
++#
++# EP93xx
++#
++CONFIG_ARCH_EP9301=y
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++# CONFIG_ARCH_EP9315 is not set
++CONFIG_MACH_EDB9301=y
++# CONFIG_MACH_TTML is not set
++CONFIG_EP93XX_DMA=y
++CONFIG_EP93XX_SSP=y
++CONFIG_EP93XX_SSP_CIRRUS=y
++# CONFIG_EP93XX_SSP_LINUX is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# General setup
++#
++CONFIG_DISCONTIGMEM=y
++CONFIG_ARM_AMBA=y
++# CONFIG_ZBOOT_ROM is not set
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++
++#
++# PCMCIA/CardBus support
++#
++# CONFIG_PCMCIA is not set
++
++#
++# At least one math emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_PM is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_ARTHUR is not set
++CONFIG_CMDLINE="root=/dev/nfs ip=dhcp"
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_REDBOOT_PARTS=y
++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL 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=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
++# 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 is not set
++# 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=y
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x60000000
++CONFIG_MTD_PHYSMAP_LEN=0x01000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 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_BLKMTD 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
++
++#
++# NAND Flash Device Drivers
++#
++# CONFIG_MTD_NAND is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Networking support
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++# CONFIG_NETLINK_DEV is not set
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI=y
++# CONFIG_SCSI_PROC_FS is not set
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Fusion MPT device support
++#
++
++#
++# IEEE 1394 (FireWire) support
++#
++
++#
++# I2O device support
++#
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++CONFIG_INPUT_EVDEV=y
++CONFIG_INPUT_EVBUG=y
++
++#
++# Input I/O drivers
++#
++# CONFIG_GAMEPORT is not set
++CONFIG_SOUND_GAMEPORT=y
++# CONFIG_SERIO 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_TOUCHSCREEN is not set
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_UINPUT=y
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++
++#
++# Watchdog Cards
++#
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_EP93XX_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++CONFIG_EP93XX_RTC=y
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_DRM is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++# CONFIG_I2C_EP93XX is not set
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_SCx200_ACB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Hardware Sensors Chip support
++#
++# CONFIG_I2C_SENSOR is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++
++#
++# Other I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++CONFIG_I2C_DEBUG_CORE=y
++CONFIG_I2C_DEBUG_ALGO=y
++CONFIG_I2C_DEBUG_BUS=y
++CONFIG_I2C_DEBUG_CHIP=y
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_JBD is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++# CONFIG_MSDOS_FS is not set
++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_SYSFS=y
++# CONFIG_DEVFS_FS is not set
++CONFIG_DEVPTS_FS_XATTR=y
++CONFIG_DEVPTS_FS_SECURITY=y
++CONFIG_TMPFS=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++# CONFIG_JFFS2_FS_NAND is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++# CONFIG_EXPORTFS is not set
++CONFIG_SUNRPC=y
++# 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=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII 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
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Graphics support
++#
++# CONFIG_FB is not set
++# CONFIG_FB_CX25871_I2C is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++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=y
++CONFIG_SND_PCM_OSS=y
++CONFIG_SND_VERBOSE_PRINTK=y
++CONFIG_SND_DEBUG=y
++CONFIG_SND_DEBUG_MEMORY=y
++CONFIG_SND_DEBUG_DETECT=y
++
++#
++# Generic devices
++#
++CONFIG_SND_DUMMY=y
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA ARM devices
++#
++
++#
++# ALSA USB devices
++#
++# CONFIG_SND_USB_AUDIO is not set
++# CONFIG_SND_USB_USX2Y is not set
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++
++#
++# Misc devices
++#
++
++#
++# USB support
++#
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_BANDWIDTH is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_EHCI_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811HS is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_AUDIO is not set
++# CONFIG_USB_BLUETOOTH_TTY is not set
++# CONFIG_USB_MIDI is not set
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++CONFIG_USB_STORAGE_RW_DETECT=y
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_HP8200e is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# USB Human Interface Devices (HID)
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_HPUSBSCSI is not set
++
++#
++# USB Multimedia devices
++#
++# CONFIG_USB_DABUSB is not set
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network adaptors
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++CONFIG_USB_SERIAL=y
++# CONFIG_USB_SERIAL_CONSOLE is not set
++# CONFIG_USB_SERIAL_GENERIC is not set
++# CONFIG_USB_SERIAL_BELKIN is not set
++# CONFIG_USB_SERIAL_WHITEHEAT is not set
++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
++# CONFIG_USB_SERIAL_EMPEG is not set
++# CONFIG_USB_SERIAL_FTDI_SIO is not set
++# CONFIG_USB_SERIAL_VISOR is not set
++# CONFIG_USB_SERIAL_IPAQ is not set
++# CONFIG_USB_SERIAL_IR is not set
++# CONFIG_USB_SERIAL_EDGEPORT is not set
++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
++# CONFIG_USB_SERIAL_KEYSPAN is not set
++# CONFIG_USB_SERIAL_KLSI is not set
++# CONFIG_USB_SERIAL_KOBIL_SCT is not set
++# CONFIG_USB_SERIAL_MCT_U232 is not set
++CONFIG_USB_SERIAL_PL2303=y
++# CONFIG_USB_SERIAL_SAFE is not set
++# CONFIG_USB_SERIAL_CYBERJACK is not set
++# CONFIG_USB_SERIAL_XIRCOM is not set
++# CONFIG_USB_SERIAL_OMNINET is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_TIGL is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# Kernel hacking
++#
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_DEBUG_SLAB=y
++CONFIG_DEBUG_SPINLOCK=y
++CONFIG_DEBUG_BUGVERBOSE=y
++# CONFIG_DEBUG_INFO is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_WAITQ=y
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_LL_PRINTK_HACK is not set
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/edb9312_defconfig b/arch/arm/configs/edb9312_defconfig
+new file mode 100644
+index 0000000..1a0aa51
+--- /dev/null
++++ b/arch/arm/configs/edb9312_defconfig
+@@ -0,0 +1,920 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.9-rc2-ep93xx
++# Mon Nov 8 16:40:30 2004
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_IOMAP=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++# CONFIG_CLEAN_COMPILE is not set
++CONFIG_BROKEN=y
++CONFIG_BROKEN_ON_SMP=y
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_SYSCTL=y
++# CONFIG_AUDIT is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_HOTPLUG is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++# CONFIG_EMBEDDED is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++# CONFIG_TINY_SHMEM is not set
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE_PB is not set
++# CONFIG_ARCH_IMX is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++# CONFIG_ARCH_EP9302 is not set
++CONFIG_ARCH_EP9312=y
++# CONFIG_ARCH_EP9315 is not set
++CONFIG_MACH_EDB9312=y
++# CONFIG_MACH_ACC is not set
++CONFIG_EP93XX_DMA=y
++CONFIG_ARCH_EP93XX_IDE=y
++CONFIG_EP93XX_SSP=y
++CONFIG_EP93XX_SSP_CIRRUS=y
++# CONFIG_EP93XX_SSP_LINUX is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_THUMB is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# General setup
++#
++CONFIG_DISCONTIGMEM=y
++CONFIG_ARM_AMBA=y
++# CONFIG_ZBOOT_ROM is not set
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++
++#
++# At least one math emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_AOUT=y
++CONFIG_BINFMT_MISC=y
++
++#
++# Generic Driver Options
++#
++# CONFIG_STANDALONE is not set
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_PM is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_ARTHUR is not set
++CONFIG_CMDLINE="root=/dev/hda1"
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_PARTITIONS=y
++CONFIG_MTD_CONCAT=y
++CONFIG_MTD_REDBOOT_PARTS=y
++CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
++CONFIG_MTD_CMDLINE_PARTS=y
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++CONFIG_FTL=y
++CONFIG_NFTL=y
++CONFIG_NFTL_RW=y
++CONFIG_INFTL=y
++
++#
++# RAM/ROM/Flash chip drivers
++#
++CONFIG_MTD_CFI=y
++CONFIG_MTD_JEDECPROBE=y
++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=y
++CONFIG_MTD_CFI_AMDSTD_RETRY=0
++CONFIG_MTD_CFI_STAA=y
++CONFIG_MTD_CFI_UTIL=y
++CONFIG_MTD_RAM=y
++CONFIG_MTD_ROM=y
++CONFIG_MTD_ABSENT=y
++# CONFIG_MTD_OBSOLETE_CHIPS is not set
++
++#
++# Mapping drivers for chip access
++#
++CONFIG_MTD_COMPLEX_MAPPINGS=y
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x60000000
++CONFIG_MTD_PHYSMAP_LEN=0x02000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++# CONFIG_MTD_IMPA7 is not set
++
++#
++# Self-contained MTD device drivers
++#
++CONFIG_MTD_SLRAM=y
++CONFIG_MTD_PHRAM=y
++CONFIG_MTD_MTDRAM=y
++CONFIG_MTDRAM_TOTAL_SIZE=512
++CONFIG_MTDRAM_ERASE_SIZE=1
++CONFIG_MTDRAM_ABS_POS=0x20000000
++# CONFIG_MTD_BLKMTD 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
++
++#
++# NAND Flash Device Drivers
++#
++CONFIG_MTD_NAND=y
++CONFIG_MTD_NAND_VERIFY_WRITE=y
++CONFIG_MTD_NAND_IDS=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD 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_SIZE=12288
++CONFIG_BLK_DEV_INITRD=y
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Networking support
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++# CONFIG_NETLINK_DEV is not set
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_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_TUNNEL is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++CONFIG_NETPOLL=y
++# CONFIG_NETPOLL_RX is not set
++# CONFIG_NETPOLL_TRAP is not set
++CONFIG_NET_POLL_CONTROLLER=y
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++CONFIG_NETCONSOLE=y
++
++#
++# ATA/ATAPI/MFM/RLL support
++#
++CONFIG_IDE=y
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++CONFIG_IDEDISK_MULTI_MODE=y
++CONFIG_BLK_DEV_IDECD=y
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++# CONFIG_IDE_TASKFILE_IO is not set
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++CONFIG_BLK_DEV_EP93XX=y
++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
++CONFIG_IDE_ARM=y
++# CONFIG_BLK_DEV_IDEDMA is not set
++# CONFIG_IDEDMA_AUTO is not set
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI=y
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++# CONFIG_BLK_DEV_SD is not set
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Fusion MPT device support
++#
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input I/O drivers
++#
++# CONFIG_GAMEPORT is not set
++CONFIG_SOUND_GAMEPORT=y
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_CT82C710 is not set
++# CONFIG_SERIO_AMBAKMI is not set
++# CONFIG_SERIO_RAW is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++CONFIG_KEYBOARD_EP93XX=y
++CONFIG_KEYBOARD_EP93XX_SPI=y
++CONFIG_KEYBOARD_EP93XX_8X8=y
++CONFIG_INPUT_MOUSE=y
++CONFIG_MOUSE_PS2=y
++CONFIG_MOUSE_SERIAL=y
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++CONFIG_TOUCHSCREEN_EP93XX=y
++# CONFIG_INPUT_MISC is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++
++#
++# Watchdog Cards
++#
++# CONFIG_WATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++# CONFIG_EP93XX_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_DRM is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_SCx200_ACB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Hardware Sensors Chip support
++#
++CONFIG_I2C_SENSOR=y
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++
++#
++# Other I2C Chip support
++#
++CONFIG_SENSORS_DS1337=y
++CONFIG_SENSORS_EEPROM=y
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++CONFIG_REISERFS_FS=y
++# CONFIG_REISERFS_CHECK is not set
++# CONFIG_REISERFS_PROC_INFO is not set
++# CONFIG_REISERFS_FS_XATTR is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++CONFIG_ROMFS_FS=y
++# CONFIG_QUOTA is not set
++CONFIG_AUTOFS_FS=y
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_ZISOFS_FS=y
++CONFIG_UDF_FS=y
++CONFIG_UDF_NLS=y
++
++#
++# 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_SYSFS=y
++# CONFIG_DEVFS_FS is not set
++# CONFIG_DEVFS_MOUNT is not set
++# CONFIG_DEVFS_DEBUG is not set
++# CONFIG_DEVPTS_FS_XATTR is not set
++CONFIG_TMPFS=y
++# CONFIG_HUGETLBFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++# CONFIG_JFFS2_FS_NAND is not set
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++# CONFIG_EXPORTFS is not set
++CONFIG_SUNRPC=y
++# 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=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++CONFIG_NLS_ASCII=y
++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=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Graphics support
++#
++CONFIG_FB=y
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_CX25871_I2C is not set
++CONFIG_FB_EP93XX=y
++# CONFIG_FB_CRT_EP93XX is not set
++CONFIG_FB_LCD_EP93XX=y
++# CONFIG_FB_LCD_EP93XX_SHARP is not set
++# CONFIG_FB_CX25871 is not set
++# CONFIG_FB_EP93XX_8BPP is not set
++# CONFIG_FB_EP93XX_16BPP_565 is not set
++# CONFIG_FB_EP93XX_24BPP is not set
++CONFIG_FB_EP93XX_32BPP=y
++# CONFIG_FB_VIRTUAL is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++CONFIG_FONT_6x11=y
++CONFIG_FONT_PEARL_8x8=y
++CONFIG_FONT_ACORN_8x8=y
++# CONFIG_FONT_MINI_4x6 is not set
++CONFIG_FONT_SUN8x16=y
++CONFIG_FONT_SUN12x22=y
++
++#
++# Logo configuration
++#
++CONFIG_LOGO=y
++CONFIG_LOGO_LINUX_MONO=y
++CONFIG_LOGO_LINUX_VGA16=y
++CONFIG_LOGO_LINUX_CLUT224=y
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++# CONFIG_SND is not set
++
++#
++# Open Sound System
++#
++CONFIG_SOUND_PRIME=y
++# CONFIG_SOUND_BT878 is not set
++# CONFIG_SOUND_FUSION is not set
++# CONFIG_SOUND_CS4281 is not set
++# CONFIG_SOUND_SONICVIBES is not set
++# CONFIG_SOUND_TRIDENT is not set
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++# CONFIG_SOUND_OSS is not set
++# CONFIG_SOUND_TVMIXER is not set
++# CONFIG_SOUND_AD1980 is not set
++
++#
++# Misc devices
++#
++
++#
++# USB support
++#
++# CONFIG_USB is not set
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# Kernel hacking
++#
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++CONFIG_DEBUG_LL_PRINTK_HACK=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++CONFIG_CRC_CCITT=y
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/edb9315_defconfig b/arch/arm/configs/edb9315_defconfig
+new file mode 100644
+index 0000000..3e6033b
+--- /dev/null
++++ b/arch/arm/configs/edb9315_defconfig
+@@ -0,0 +1,954 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.9-rc2-ep93xx
++# Mon Nov 8 17:01:50 2004
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_IOMAP=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++# CONFIG_CLEAN_COMPILE is not set
++CONFIG_BROKEN=y
++CONFIG_BROKEN_ON_SMP=y
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++CONFIG_POSIX_MQUEUE=y
++CONFIG_BSD_PROCESS_ACCT=y
++# CONFIG_BSD_PROCESS_ACCT_V3 is not set
++CONFIG_SYSCTL=y
++# CONFIG_AUDIT is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_HOTPLUG is not set
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_EMBEDDED=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++# CONFIG_TINY_SHMEM is not set
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE_PB is not set
++# CONFIG_ARCH_IMX is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++CONFIG_ARCH_EP9315=y
++CONFIG_MACH_EDB9315=y
++CONFIG_EP93XX_DMA=y
++# CONFIG_ARCH_EP93XX_IDE is not set
++CONFIG_EP93XX_SSP=y
++CONFIG_EP93XX_SSP_CIRRUS=y
++# CONFIG_EP93XX_SSP_LINUX is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# General setup
++#
++CONFIG_DISCONTIGMEM=y
++CONFIG_ARM_AMBA=y
++# CONFIG_ZBOOT_ROM is not set
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++
++#
++# At least one math emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_PM is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_ARTHUR is not set
++CONFIG_CMDLINE="console=ttyCL0 map=mtd6,0x30000000,+0x200000 root=/dev/nfs nfsroot=192.168.1.224:/nfsarm_grma video=ep93xxfb ip=192.168.1.220:192.168.1.224:192.168.1.2:255.255.255.0::eth0:"
++CONFIG_LEDS=y
++CONFIG_LEDS_TIMER=y
++CONFIG_LEDS_CPU=y
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++CONFIG_MTD_DEBUG=y
++CONFIG_MTD_DEBUG_VERBOSE=3
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_REDBOOT_PARTS=y
++CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED=y
++CONFIG_MTD_REDBOOT_PARTS_READONLY=y
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL 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=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
++# CONFIG_MTD_MAP_BANK_WIDTH_2 is not set
++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 is not set
++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=y
++CONFIG_MTD_ROM=y
++# CONFIG_MTD_ABSENT is not set
++# CONFIG_MTD_OBSOLETE_CHIPS is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x60000000
++CONFIG_MTD_PHYSMAP_LEN=0x2000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=4
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++CONFIG_MTD_MTDRAM=y
++CONFIG_MTDRAM_TOTAL_SIZE=512
++CONFIG_MTDRAM_ERASE_SIZE=128
++CONFIG_MTDRAM_ABS_POS=0x20000000
++# CONFIG_MTD_BLKMTD 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
++
++#
++# NAND Flash Device Drivers
++#
++# CONFIG_MTD_NAND is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD 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_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Networking support
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++# CONFIG_NETLINK_DEV is not set
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_PNP=y
++# CONFIG_IP_PNP_DHCP is not set
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_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_TUNNEL is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++
++#
++# ATA/ATAPI/MFM/RLL support
++#
++# CONFIG_IDE is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI=y
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Fusion MPT device support
++#
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++# CONFIG_INPUT_EVDEV is not set
++# CONFIG_INPUT_EVBUG is not set
++
++#
++# Input I/O drivers
++#
++# CONFIG_GAMEPORT is not set
++CONFIG_SOUND_GAMEPORT=y
++CONFIG_SERIO=y
++# CONFIG_SERIO_SERPORT is not set
++# CONFIG_SERIO_CT82C710 is not set
++# CONFIG_SERIO_AMBAKMI is not set
++# CONFIG_SERIO_RAW is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++CONFIG_KEYBOARD_EP93XX=y
++# CONFIG_KEYBOARD_EP93XX_SPI is not set
++# CONFIG_KEYBOARD_EP93XX_8X8 is not set
++CONFIG_INPUT_MOUSE=y
++# CONFIG_MOUSE_PS2 is not set
++# CONFIG_MOUSE_SERIAL is not set
++# CONFIG_MOUSE_VSXXXAA is not set
++# CONFIG_INPUT_JOYSTICK is not set
++CONFIG_INPUT_TOUCHSCREEN=y
++# CONFIG_TOUCHSCREEN_GUNZE is not set
++CONFIG_TOUCHSCREEN_EP93XX=y
++# CONFIG_INPUT_MISC is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++
++#
++# Watchdog Cards
++#
++# CONFIG_WATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++# CONFIG_EP93XX_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_DRM is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_SCx200_ACB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Hardware Sensors Chip support
++#
++# CONFIG_I2C_SENSOR is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++
++#
++# Other I2C Chip support
++#
++CONFIG_SENSORS_DS1337=y
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++CONFIG_I2C_DEBUG_CORE=y
++CONFIG_I2C_DEBUG_ALGO=y
++CONFIG_I2C_DEBUG_BUS=y
++CONFIG_I2C_DEBUG_CHIP=y
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_JBD is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_QUOTA is not set
++CONFIG_AUTOFS_FS=y
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++CONFIG_MSDOS_FS=y
++CONFIG_VFAT_FS=y
++CONFIG_FAT_DEFAULT_CODEPAGE=437
++CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
++# CONFIG_NTFS_FS is not set
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++# CONFIG_DEVFS_FS is not set
++CONFIG_DEVPTS_FS_XATTR=y
++# CONFIG_DEVPTS_FS_SECURITY is not set
++CONFIG_TMPFS=y
++# CONFIG_HUGETLBFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=2
++# CONFIG_JFFS2_FS_NAND is not set
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++# CONFIG_EXPORTFS is not set
++CONFIG_SUNRPC=y
++# 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=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++CONFIG_LDM_PARTITION=y
++# CONFIG_LDM_DEBUG is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++CONFIG_NLS_CODEPAGE_850=y
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 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=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Graphics support
++#
++CONFIG_FB=y
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_CX25871_I2C is not set
++CONFIG_FB_EP93XX=y
++# CONFIG_FB_CRT_EP93XX is not set
++CONFIG_FB_LCD_EP93XX=y
++# CONFIG_FB_LCD_EP93XX_SHARP is not set
++# CONFIG_FB_CX25871 is not set
++# CONFIG_FB_EP93XX_8BPP is not set
++CONFIG_FB_EP93XX_16BPP_565=y
++# CONFIG_FB_EP93XX_24BPP is not set
++# CONFIG_FB_EP93XX_32BPP is not set
++# CONFIG_FB_VIRTUAL is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FONTS=y
++CONFIG_FONT_8x8=y
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++# CONFIG_FONT_MINI_4x6 is not set
++# CONFIG_FONT_SUN8x16 is not set
++# CONFIG_FONT_SUN12x22 is not set
++
++#
++# Logo configuration
++#
++CONFIG_LOGO=y
++# CONFIG_LOGO_LINUX_MONO is not set
++# CONFIG_LOGO_LINUX_VGA16 is not set
++CONFIG_LOGO_LINUX_CLUT224=y
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# Misc devices
++#
++
++#
++# USB support
++#
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++# CONFIG_USB_DEVICEFS is not set
++# CONFIG_USB_BANDWIDTH is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_EHCI_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811HS is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_BLUETOOTH_TTY is not set
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_RW_DETECT is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_HP8200e is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# USB Human Interface Devices (HID)
++#
++CONFIG_USB_HID=y
++CONFIG_USB_HIDINPUT=y
++# CONFIG_HID_FF is not set
++CONFIG_USB_HIDDEV=y
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_HPUSBSCSI is not set
++
++#
++# USB Multimedia devices
++#
++# CONFIG_USB_DABUSB is not set
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network adaptors
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_TIGL is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGETSERVO is not set
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# Kernel hacking
++#
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_MAGIC_SYSRQ is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_LL_PRINTK_HACK is not set
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/ttml_defconfig b/arch/arm/configs/ttml_defconfig
+new file mode 100644
+index 0000000..e0b96ae
+--- /dev/null
++++ b/arch/arm/configs/ttml_defconfig
+@@ -0,0 +1,1052 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.13
++# Thu Sep 8 16:54:14 2005
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_CLEAN_COMPILE=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_SYSCTL=y
++# CONFIG_AUDIT is not set
++CONFIG_HOTPLUG=y
++CONFIG_KOBJECT_UEVENT=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_EMBEDDED=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++CONFIG_CC_ALIGN_FUNCTIONS=0
++CONFIG_CC_ALIGN_LABELS=0
++CONFIG_CC_ALIGN_LOOPS=0
++CONFIG_CC_ALIGN_JUMPS=0
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++# CONFIG_MODULE_UNLOAD is not set
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_AAEC2000 is not set
++
++#
++# EP93xx
++#
++CONFIG_ARCH_EP9301=y
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++# CONFIG_ARCH_EP9315 is not set
++# CONFIG_MACH_EDB9301 is not set
++CONFIG_MACH_TTML=y
++# CONFIG_ARCH_EP93XX_GPIO_IRQ is not set
++CONFIG_EP93XX_DMA=y
++CONFIG_EP93XX_SSP=y
++# CONFIG_EP93XX_SSP_CIRRUS is not set
++CONFIG_EP93XX_SSP_LINUX=y
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++CONFIG_ISA_DMA_API=y
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_PREEMPT is not set
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
++CONFIG_SELECT_MEMORY_MODEL=y
++# CONFIG_FLATMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM_MANUAL=y
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_NEED_MULTIPLE_NODES=y
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="ip=off root=1f02 rootfstype=jffs2"
++# CONFIG_XIP_KERNEL is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++CONFIG_IP_TCPDIAG=y
++# CONFIG_IP_TCPDIAG_IPV6 is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_BIC=y
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++CONFIG_MTD_REDBOOT_PARTS=y
++CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL 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=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
++# 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 is not set
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_OTP 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=y
++# CONFIG_MTD_ABSENT is not set
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++CONFIG_MTD_PHYSMAP=y
++CONFIG_MTD_PHYSMAP_START=0x60000000
++CONFIG_MTD_PHYSMAP_LEN=0x01000000
++CONFIG_MTD_PHYSMAP_BANKWIDTH=2
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++# CONFIG_MTD_PLATRAM is not set
++
++#
++# Self-contained MTD device drivers
++#
++# CONFIG_MTD_SLRAM is not set
++# CONFIG_MTD_PHRAM is not set
++# CONFIG_MTD_MTDRAM is not set
++# CONFIG_MTD_BLKMTD 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
++
++#
++# NAND Flash Device Drivers
++#
++# CONFIG_MTD_NAND is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_COW_COMMON is not set
++# CONFIG_BLK_DEV_LOOP is not set
++# CONFIG_BLK_DEV_NBD is not set
++# CONFIG_BLK_DEV_UB is not set
++# CONFIG_BLK_DEV_RAM is not set
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CDROM_PKTCDVD 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_ATA_OVER_ETH is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI=y
++# CONFIG_SCSI_PROC_FS is not set
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Fusion MPT device support
++#
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++
++#
++# I2O device support
++#
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++CONFIG_INPUT_EVDEV=y
++CONFIG_INPUT_EVBUG=y
++
++#
++# Input Device Drivers
++#
++# CONFIG_INPUT_KEYBOARD is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_UINPUT=y
++
++#
++# Hardware I/O ports
++#
++# CONFIG_SERIO is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_TTML_DEVICES=y
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++
++#
++# Watchdog Cards
++#
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_EP93XX_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++CONFIG_EP93XX_RTC=y
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++
++#
++# CAN bus devices
++#
++# CONFIG_CAN_BUS is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_EP93XX is not set
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_PCA_ISA is not set
++# CONFIG_I2C_SENSOR is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_SENSORS_DS1307 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++CONFIG_I2C_DEBUG_CORE=y
++CONFIG_I2C_DEBUG_ALGO=y
++CONFIG_I2C_DEBUG_BUS=y
++CONFIG_I2C_DEBUG_CHIP=y
++
++#
++# Hardware Monitoring support
++#
++CONFIG_HWMON=y
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Misc devices
++#
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# Graphics support
++#
++# CONFIG_FB is not set
++# CONFIG_FB_CX25871_I2C is not set
++
++#
++# Sound
++#
++# CONFIG_SOUND is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_BANDWIDTH is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_BLUETOOTH_TTY is not set
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# USB Input Devices
++#
++# CONFIG_USB_HID is not set
++
++#
++# USB HID Boot Protocol drivers
++#
++# CONFIG_USB_KBD is not set
++# CONFIG_USB_MOUSE is not set
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_ACECAD is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_ITMTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++# CONFIG_USB_KEYSPAN_REMOTE is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB Multimedia devices
++#
++# CONFIG_USB_DABUSB is not set
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++CONFIG_USB_SERIAL=y
++# CONFIG_USB_SERIAL_CONSOLE is not set
++# CONFIG_USB_SERIAL_GENERIC is not set
++# CONFIG_USB_SERIAL_AIRPRIME is not set
++# CONFIG_USB_SERIAL_BELKIN is not set
++# CONFIG_USB_SERIAL_WHITEHEAT is not set
++# CONFIG_USB_SERIAL_DIGI_ACCELEPORT is not set
++# CONFIG_USB_SERIAL_CP2101 is not set
++# CONFIG_USB_SERIAL_CYPRESS_M8 is not set
++# CONFIG_USB_SERIAL_EMPEG is not set
++# CONFIG_USB_SERIAL_FTDI_SIO is not set
++# CONFIG_USB_SERIAL_VISOR is not set
++# CONFIG_USB_SERIAL_IPAQ is not set
++# CONFIG_USB_SERIAL_IR is not set
++# CONFIG_USB_SERIAL_EDGEPORT is not set
++# CONFIG_USB_SERIAL_EDGEPORT_TI is not set
++# CONFIG_USB_SERIAL_GARMIN is not set
++# CONFIG_USB_SERIAL_IPW is not set
++# CONFIG_USB_SERIAL_KEYSPAN_PDA is not set
++# CONFIG_USB_SERIAL_KEYSPAN is not set
++# CONFIG_USB_SERIAL_KLSI is not set
++# CONFIG_USB_SERIAL_KOBIL_SCT is not set
++# CONFIG_USB_SERIAL_MCT_U232 is not set
++CONFIG_USB_SERIAL_PL2303=y
++# CONFIG_USB_SERIAL_HP4X is not set
++# CONFIG_USB_SERIAL_SAFE is not set
++# CONFIG_USB_SERIAL_TI is not set
++# CONFIG_USB_SERIAL_CYBERJACK is not set
++# CONFIG_USB_SERIAL_XIRCOM is not set
++# CONFIG_USB_SERIAL_OMNINET is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGETKIT is not set
++# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# File systems
++#
++# CONFIG_EXT2_FS is not set
++# CONFIG_EXT3_FS is not set
++# CONFIG_JBD is not set
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++
++#
++# XFS support
++#
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++CONFIG_INOTIFY=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++# CONFIG_MSDOS_FS is not set
++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_SYSFS=y
++CONFIG_DEVPTS_FS_XATTR=y
++CONFIG_DEVPTS_FS_SECURITY=y
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_XATTR is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++# CONFIG_RPCSEC_GSS_KRB5 is not set
++# CONFIG_RPCSEC_GSS_SPKM3 is not set
++# CONFIG_SMB_FS is not set
++# CONFIG_CIFS is not set
++# CONFIG_NCP_FS is not set
++# CONFIG_CODA_FS is not set
++# CONFIG_AFS_FS is not set
++
++#
++# Partition Types
++#
++CONFIG_PARTITION_ADVANCED=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII 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
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_KOBJECT is not set
++# CONFIG_DEBUG_BUGVERBOSE is not set
++# CONFIG_DEBUG_INFO is not set
++# CONFIG_DEBUG_FS is not set
++CONFIG_FRAME_POINTER=y
++# CONFIG_DEBUG_USER is not set
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Hardware crypto devices
++#
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/zefeerdzb_defconfig b/arch/arm/configs/zefeerdzb_defconfig
+new file mode 100644
+index 0000000..39aefdd
+--- /dev/null
++++ b/arch/arm/configs/zefeerdzb_defconfig
+@@ -0,0 +1,961 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.9-rc2-ep93xx
++# Fri Jan 7 11:19:19 2005
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_IOMAP=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++CONFIG_CLEAN_COMPILE=y
++CONFIG_BROKEN_ON_SMP=y
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++# CONFIG_SWAP is not set
++CONFIG_SYSVIPC=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_SYSCTL=y
++# CONFIG_AUDIT is not set
++CONFIG_LOG_BUF_SHIFT=14
++CONFIG_HOTPLUG=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++CONFIG_EMBEDDED=y
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_IOSCHED_NOOP=y
++# CONFIG_IOSCHED_AS is not set
++CONFIG_IOSCHED_DEADLINE=y
++# CONFIG_IOSCHED_CFQ is not set
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++# CONFIG_TINY_SHMEM is not set
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE_PB is not set
++# CONFIG_ARCH_IMX is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++CONFIG_ARCH_EP9302=y
++# CONFIG_ARCH_EP9312 is not set
++# CONFIG_ARCH_EP9315 is not set
++# CONFIG_MACH_EDB9302 is not set
++CONFIG_MACH_ZEFEERDZB=y
++CONFIG_ARCH_EP93XX_GPIO_IRQ=y
++CONFIG_EP93XX_DMA=y
++# CONFIG_EP93XX_SSP is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++CONFIG_ARM_THUMB=y
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# General setup
++#
++CONFIG_DISCONTIGMEM=y
++CONFIG_ARM_AMBA=y
++# CONFIG_ZBOOT_ROM is not set
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++
++#
++# PCMCIA/CardBus support
++#
++# CONFIG_PCMCIA is not set
++
++#
++# At least one math emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++CONFIG_FPE_NWFPE_XP=y
++# CONFIG_FPE_FASTFPE is not set
++CONFIG_BINFMT_ELF=y
++# CONFIG_BINFMT_AOUT is not set
++# CONFIG_BINFMT_MISC is not set
++
++#
++# Generic Driver Options
++#
++CONFIG_STANDALONE=y
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++# CONFIG_PM is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_ARTHUR is not set
++CONFIG_CMDLINE="root=/dev/nfs ip=dhcp"
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_REDBOOT_PARTS=y
++# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
++# CONFIG_MTD_REDBOOT_PARTS_READONLY is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL 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=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
++# 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 is not set
++# 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=y
++# CONFIG_MTD_ABSENT is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++CONFIG_MTD_ZEFEERDZB=y
++
++#
++# 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_BLKMTD 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
++
++#
++# NAND Flash Device Drivers
++#
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++CONFIG_MTD_NAND_IDS=y
++CONFIG_MTD_NAND_ZEFEEREVB=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# CONFIG_BLK_DEV_FD 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_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_SIZE=6144
++CONFIG_BLK_DEV_INITRD=y
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Networking support
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++# CONFIG_NETLINK_DEV is not set
++CONFIG_UNIX=y
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++# CONFIG_IP_MULTICAST is not set
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++CONFIG_IP_PNP_BOOTP=y
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_ARPD is not set
++CONFIG_SYN_COOKIES=y
++# CONFIG_INET_AH is not set
++# CONFIG_INET_ESP is not set
++# CONFIG_INET_IPCOMP is not set
++# CONFIG_INET_TUNNEL is not set
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_HW_FLOWCONTROL is not set
++
++#
++# QoS and/or fair queueing
++#
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_NETPOLL is not set
++# CONFIG_NET_POLL_CONTROLLER is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++# CONFIG_NET_RADIO is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++# CONFIG_NETCONSOLE is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI=y
++# CONFIG_SCSI_PROC_FS is not set
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++# CONFIG_CHR_DEV_SG is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Fusion MPT device support
++#
++
++#
++# IEEE 1394 (FireWire) support
++#
++
++#
++# I2O device support
++#
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++
++#
++# Userland interfaces
++#
++# CONFIG_INPUT_MOUSEDEV is not set
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++CONFIG_INPUT_EVDEV=y
++CONFIG_INPUT_EVBUG=y
++
++#
++# Input I/O drivers
++#
++# CONFIG_GAMEPORT is not set
++CONFIG_SOUND_GAMEPORT=y
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_CT82C710 is not set
++# CONFIG_SERIO_AMBAKMI is not set
++# CONFIG_SERIO_RAW is not set
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++CONFIG_KEYBOARD_ATKBD=y
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++CONFIG_KEYBOARD_EP93XX=y
++# CONFIG_KEYBOARD_EP93XX_SPI is not set
++# CONFIG_KEYBOARD_EP93XX_8X8 is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++CONFIG_INPUT_MISC=y
++CONFIG_INPUT_UINPUT=y
++
++#
++# Character devices
++#
++# CONFIG_VT is not set
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++# CONFIG_LEGACY_PTYS is not set
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++
++#
++# Watchdog Cards
++#
++CONFIG_WATCHDOG=y
++# CONFIG_WATCHDOG_NOWAYOUT is not set
++
++#
++# Watchdog Device Drivers
++#
++# CONFIG_SOFT_WATCHDOG is not set
++CONFIG_EP93XX_WATCHDOG=y
++
++#
++# USB-based Watchdog Cards
++#
++# CONFIG_USBPCWATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++CONFIG_EP93XX_RTC=y
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++# CONFIG_DRM is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++# CONFIG_I2C_AMD756 is not set
++# CONFIG_I2C_AMD8111 is not set
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_SCx200_ACB is not set
++# CONFIG_I2C_PCA_ISA is not set
++
++#
++# Hardware Sensors Chip support
++#
++# CONFIG_I2C_SENSOR is not set
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++
++#
++# Other I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++# CONFIG_SENSORS_M41T00 is not set
++CONFIG_I2C_DEBUG_CORE=y
++CONFIG_I2C_DEBUG_ALGO=y
++CONFIG_I2C_DEBUG_BUS=y
++CONFIG_I2C_DEBUG_CHIP=y
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++CONFIG_EXT2_FS_XATTR=y
++CONFIG_EXT2_FS_POSIX_ACL=y
++CONFIG_EXT2_FS_SECURITY=y
++# CONFIG_EXT3_FS is not set
++# CONFIG_JBD is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++CONFIG_FS_POSIX_ACL=y
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++# CONFIG_ROMFS_FS is not set
++# CONFIG_QUOTA is not set
++# CONFIG_AUTOFS_FS is not set
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++# CONFIG_ISO9660_FS is not set
++# CONFIG_UDF_FS is not set
++
++#
++# DOS/FAT/NT Filesystems
++#
++CONFIG_FAT_FS=y
++# CONFIG_MSDOS_FS is not set
++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_SYSFS=y
++# CONFIG_DEVFS_FS is not set
++CONFIG_DEVPTS_FS_XATTR=y
++CONFIG_DEVPTS_FS_SECURITY=y
++CONFIG_TMPFS=y
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_NAND=y
++CONFIG_JFFS2_COMPRESSION_OPTIONS=y
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_JFFS2_CMODE_NONE is not set
++CONFIG_JFFS2_CMODE_PRIORITY=y
++# CONFIG_JFFS2_CMODE_SIZE is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V4 is not set
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++# CONFIG_EXPORTFS is not set
++CONFIG_SUNRPC=y
++# 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=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII 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
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Graphics support
++#
++# CONFIG_FB is not set
++# CONFIG_FB_CX25871_I2C is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++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=y
++CONFIG_SND_PCM_OSS=y
++CONFIG_SND_VERBOSE_PRINTK=y
++CONFIG_SND_DEBUG=y
++CONFIG_SND_DEBUG_MEMORY=y
++CONFIG_SND_DEBUG_DETECT=y
++
++#
++# Generic devices
++#
++CONFIG_SND_DUMMY=y
++# CONFIG_SND_MTPAV is not set
++# CONFIG_SND_SERIAL_U16550 is not set
++# CONFIG_SND_MPU401 is not set
++
++#
++# ALSA ARM devices
++#
++
++#
++# ALSA USB devices
++#
++# CONFIG_SND_USB_AUDIO is not set
++# CONFIG_SND_USB_USX2Y is not set
++
++#
++# Open Sound System
++#
++# CONFIG_SOUND_PRIME is not set
++
++#
++# Misc devices
++#
++
++#
++# USB support
++#
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_BANDWIDTH is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_EHCI_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_UHCI_HCD is not set
++# CONFIG_USB_SL811HS is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_AUDIO is not set
++# CONFIG_USB_BLUETOOTH_TTY is not set
++# CONFIG_USB_MIDI is not set
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++CONFIG_USB_STORAGE_RW_DETECT=y
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_HP8200e is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# USB Human Interface Devices (HID)
++#
++CONFIG_USB_HID=y
++CONFIG_USB_HIDINPUT=y
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++# CONFIG_USB_HPUSBSCSI is not set
++
++#
++# USB Multimedia devices
++#
++# CONFIG_USB_DABUSB is not set
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network adaptors
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_TIGL is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# Kernel hacking
++#
++CONFIG_DEBUG_KERNEL=y
++CONFIG_MAGIC_SYSRQ=y
++CONFIG_DEBUG_SLAB=y
++CONFIG_DEBUG_SPINLOCK=y
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++CONFIG_DEBUG_WAITQ=y
++CONFIG_DEBUG_ERRORS=y
++# CONFIG_DEBUG_DONT_REORDER_CODE is not set
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_LL_PRINTK_HACK is not set
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++# CONFIG_CRYPTO is not set
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/configs/zefeerdzq_defconfig b/arch/arm/configs/zefeerdzq_defconfig
+new file mode 100644
+index 0000000..8314eee
+--- /dev/null
++++ b/arch/arm/configs/zefeerdzq_defconfig
+@@ -0,0 +1,1174 @@
++#
++# Automatically generated make config: don't edit
++# Linux kernel version: 2.6.13
++# Tue Oct 4 10:04:06 2005
++#
++CONFIG_ARM=y
++CONFIG_MMU=y
++CONFIG_UID16=y
++CONFIG_RWSEM_GENERIC_SPINLOCK=y
++CONFIG_GENERIC_CALIBRATE_DELAY=y
++
++#
++# Code maturity level options
++#
++CONFIG_EXPERIMENTAL=y
++# CONFIG_CLEAN_COMPILE is not set
++CONFIG_BROKEN=y
++CONFIG_BROKEN_ON_SMP=y
++CONFIG_INIT_ENV_ARG_LIMIT=32
++
++#
++# General setup
++#
++CONFIG_LOCALVERSION=""
++CONFIG_SWAP=y
++CONFIG_SYSVIPC=y
++# CONFIG_POSIX_MQUEUE is not set
++# CONFIG_BSD_PROCESS_ACCT is not set
++CONFIG_SYSCTL=y
++# CONFIG_AUDIT is not set
++# CONFIG_HOTPLUG is not set
++CONFIG_KOBJECT_UEVENT=y
++CONFIG_IKCONFIG=y
++CONFIG_IKCONFIG_PROC=y
++# CONFIG_EMBEDDED is not set
++CONFIG_KALLSYMS=y
++# CONFIG_KALLSYMS_ALL is not set
++# CONFIG_KALLSYMS_EXTRA_PASS is not set
++CONFIG_PRINTK=y
++CONFIG_BUG=y
++CONFIG_BASE_FULL=y
++CONFIG_FUTEX=y
++CONFIG_EPOLL=y
++CONFIG_CC_OPTIMIZE_FOR_SIZE=y
++CONFIG_SHMEM=y
++CONFIG_CC_ALIGN_FUNCTIONS=0
++CONFIG_CC_ALIGN_LABELS=0
++CONFIG_CC_ALIGN_LOOPS=0
++CONFIG_CC_ALIGN_JUMPS=0
++# CONFIG_TINY_SHMEM is not set
++CONFIG_BASE_SMALL=0
++
++#
++# Loadable module support
++#
++CONFIG_MODULES=y
++CONFIG_MODULE_UNLOAD=y
++CONFIG_MODULE_FORCE_UNLOAD=y
++CONFIG_OBSOLETE_MODPARM=y
++# CONFIG_MODVERSIONS is not set
++# CONFIG_MODULE_SRCVERSION_ALL is not set
++CONFIG_KMOD=y
++
++#
++# System Type
++#
++# CONFIG_ARCH_CLPS7500 is not set
++# CONFIG_ARCH_CLPS711X is not set
++# CONFIG_ARCH_CO285 is not set
++# CONFIG_ARCH_EBSA110 is not set
++CONFIG_ARCH_EP93XX=y
++# CONFIG_ARCH_CAMELOT is not set
++# CONFIG_ARCH_FOOTBRIDGE is not set
++# CONFIG_ARCH_INTEGRATOR is not set
++# CONFIG_ARCH_IOP3XX is not set
++# CONFIG_ARCH_IXP4XX is not set
++# CONFIG_ARCH_IXP2000 is not set
++# CONFIG_ARCH_L7200 is not set
++# CONFIG_ARCH_PXA is not set
++# CONFIG_ARCH_RPC is not set
++# CONFIG_ARCH_SA1100 is not set
++# CONFIG_ARCH_S3C2410 is not set
++# CONFIG_ARCH_SHARK is not set
++# CONFIG_ARCH_LH7A40X is not set
++# CONFIG_ARCH_OMAP is not set
++# CONFIG_ARCH_VERSATILE is not set
++# CONFIG_ARCH_IMX is not set
++# CONFIG_ARCH_H720X is not set
++# CONFIG_ARCH_AAEC2000 is not set
++
++#
++# EP93xx
++#
++# CONFIG_ARCH_EP9301 is not set
++# CONFIG_ARCH_EP9302 is not set
++# CONFIG_ARCH_EP9312 is not set
++CONFIG_ARCH_EP9315=y
++# CONFIG_MACH_EDB9315 is not set
++# CONFIG_MACH_ADSSPHERE is not set
++CONFIG_MACH_ZEFEERDZQ=y
++# CONFIG_MACH_DMA03 is not set
++# CONFIG_ARCH_EP93XX_GPIO_IRQ is not set
++CONFIG_EP93XX_DMA=y
++# CONFIG_ARCH_EP93XX_IDE is not set
++# CONFIG_EP93XX_SSP is not set
++
++#
++# Processor Type
++#
++CONFIG_CPU_32=y
++CONFIG_CPU_ARM920T=y
++CONFIG_CPU_32v4=y
++CONFIG_CPU_ABRT_EV4T=y
++CONFIG_CPU_CACHE_V4WT=y
++CONFIG_CPU_CACHE_VIVT=y
++CONFIG_CPU_COPY_V4WB=y
++CONFIG_CPU_TLB_V4WBI=y
++
++#
++# Processor Features
++#
++# CONFIG_ARM_THUMB is not set
++# CONFIG_CPU_ICACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_DISABLE is not set
++# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
++
++#
++# Bus support
++#
++CONFIG_ARM_AMBA=y
++CONFIG_ISA_DMA_API=y
++
++#
++# PCCARD (PCMCIA/CardBus) support
++#
++# CONFIG_PCCARD is not set
++
++#
++# Kernel Features
++#
++# CONFIG_SMP is not set
++# CONFIG_PREEMPT is not set
++# CONFIG_NO_IDLE_HZ is not set
++CONFIG_ARCH_DISCONTIGMEM_ENABLE=y
++CONFIG_SELECT_MEMORY_MODEL=y
++# CONFIG_FLATMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM_MANUAL=y
++# CONFIG_SPARSEMEM_MANUAL is not set
++CONFIG_DISCONTIGMEM=y
++CONFIG_FLAT_NODE_MEM_MAP=y
++CONFIG_NEED_MULTIPLE_NODES=y
++# CONFIG_LEDS is not set
++CONFIG_ALIGNMENT_TRAP=y
++
++#
++# Boot options
++#
++CONFIG_ZBOOT_ROM_TEXT=0x0
++CONFIG_ZBOOT_ROM_BSS=0x0
++CONFIG_CMDLINE="root=/dev/ram"
++# CONFIG_XIP_KERNEL is not set
++
++#
++# Floating point emulation
++#
++
++#
++# At least one emulation must be selected
++#
++CONFIG_FPE_NWFPE=y
++# CONFIG_FPE_NWFPE_XP is not set
++# CONFIG_FPE_FASTFPE is not set
++
++#
++# Userspace binary formats
++#
++CONFIG_BINFMT_ELF=y
++CONFIG_BINFMT_AOUT=y
++CONFIG_BINFMT_MISC=y
++# CONFIG_ARTHUR is not set
++
++#
++# Power management options
++#
++# CONFIG_PM is not set
++
++#
++# Networking
++#
++CONFIG_NET=y
++
++#
++# Networking options
++#
++CONFIG_PACKET=y
++CONFIG_PACKET_MMAP=y
++CONFIG_UNIX=y
++CONFIG_XFRM=y
++# CONFIG_XFRM_USER is not set
++CONFIG_NET_KEY=y
++CONFIG_INET=y
++CONFIG_IP_MULTICAST=y
++# CONFIG_IP_ADVANCED_ROUTER is not set
++CONFIG_IP_FIB_HASH=y
++CONFIG_IP_PNP=y
++CONFIG_IP_PNP_DHCP=y
++# CONFIG_IP_PNP_BOOTP is not set
++# CONFIG_IP_PNP_RARP is not set
++# CONFIG_NET_IPIP is not set
++# CONFIG_NET_IPGRE is not set
++# CONFIG_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_TUNNEL is not set
++CONFIG_IP_TCPDIAG=y
++# CONFIG_IP_TCPDIAG_IPV6 is not set
++# CONFIG_TCP_CONG_ADVANCED is not set
++CONFIG_TCP_CONG_BIC=y
++# CONFIG_IPV6 is not set
++# CONFIG_NETFILTER is not set
++
++#
++# SCTP Configuration (EXPERIMENTAL)
++#
++# CONFIG_IP_SCTP is not set
++# CONFIG_ATM is not set
++# CONFIG_BRIDGE is not set
++# CONFIG_VLAN_8021Q is not set
++# CONFIG_DECNET is not set
++# CONFIG_LLC2 is not set
++# CONFIG_IPX is not set
++# CONFIG_ATALK is not set
++# CONFIG_X25 is not set
++# CONFIG_LAPB is not set
++# CONFIG_NET_DIVERT is not set
++# CONFIG_ECONET is not set
++# CONFIG_WAN_ROUTER is not set
++# CONFIG_NET_SCHED is not set
++# CONFIG_NET_CLS_ROUTE is not set
++
++#
++# Network testing
++#
++# CONFIG_NET_PKTGEN is not set
++# CONFIG_HAMRADIO is not set
++# CONFIG_IRDA is not set
++# CONFIG_BT is not set
++
++#
++# Device Drivers
++#
++
++#
++# Generic Driver Options
++#
++# CONFIG_STANDALONE is not set
++CONFIG_PREVENT_FIRMWARE_BUILD=y
++# CONFIG_FW_LOADER is not set
++# CONFIG_DEBUG_DRIVER is not set
++
++#
++# Memory Technology Devices (MTD)
++#
++CONFIG_MTD=y
++# CONFIG_MTD_DEBUG is not set
++# CONFIG_MTD_CONCAT is not set
++CONFIG_MTD_PARTITIONS=y
++# CONFIG_MTD_REDBOOT_PARTS is not set
++# CONFIG_MTD_CMDLINE_PARTS is not set
++# CONFIG_MTD_AFS_PARTS is not set
++
++#
++# User Modules And Translation Layers
++#
++CONFIG_MTD_CHAR=y
++CONFIG_MTD_BLOCK=y
++# CONFIG_FTL is not set
++# CONFIG_NFTL is not set
++# CONFIG_INFTL 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=y
++CONFIG_MTD_CFI_NOSWAP=y
++# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
++# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
++CONFIG_MTD_CFI_GEOMETRY=y
++# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
++CONFIG_MTD_MAP_BANK_WIDTH_2=y
++# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
++# 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 is not set
++# CONFIG_MTD_CFI_I4 is not set
++# CONFIG_MTD_CFI_I8 is not set
++# CONFIG_MTD_OTP 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
++# CONFIG_MTD_OBSOLETE_CHIPS is not set
++# CONFIG_MTD_XIP is not set
++
++#
++# Mapping drivers for chip access
++#
++# CONFIG_MTD_COMPLEX_MAPPINGS is not set
++# CONFIG_MTD_PHYSMAP is not set
++# CONFIG_MTD_ARM_INTEGRATOR is not set
++# CONFIG_MTD_EDB7312 is not set
++# CONFIG_MTD_PLATRAM is not set
++CONFIG_MTD_ZEFEERDZQ=y
++
++#
++# 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_BLKMTD 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
++
++#
++# NAND Flash Device Drivers
++#
++CONFIG_MTD_NAND=y
++# CONFIG_MTD_NAND_VERIFY_WRITE is not set
++CONFIG_MTD_NAND_IDS=y
++CONFIG_MTD_NAND_ZEFEEREVB=y
++# CONFIG_MTD_NAND_DISKONCHIP is not set
++# CONFIG_MTD_NAND_NANDSIM is not set
++
++#
++# Parallel port support
++#
++# CONFIG_PARPORT is not set
++
++#
++# Plug and Play support
++#
++
++#
++# Block devices
++#
++# 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_UB is not set
++CONFIG_BLK_DEV_RAM=y
++CONFIG_BLK_DEV_RAM_COUNT=16
++CONFIG_BLK_DEV_RAM_SIZE=12288
++CONFIG_BLK_DEV_INITRD=y
++CONFIG_INITRAMFS_SOURCE=""
++# CONFIG_CDROM_PKTCDVD is not set
++
++#
++# IO Schedulers
++#
++CONFIG_IOSCHED_NOOP=y
++CONFIG_IOSCHED_AS=y
++CONFIG_IOSCHED_DEADLINE=y
++CONFIG_IOSCHED_CFQ=y
++# CONFIG_ATA_OVER_ETH is not set
++
++#
++# ATA/ATAPI/MFM/RLL support
++#
++CONFIG_IDE=y
++CONFIG_BLK_DEV_IDE=y
++
++#
++# Please see Documentation/ide.txt for help/info on IDE drives
++#
++# CONFIG_BLK_DEV_IDE_SATA is not set
++CONFIG_BLK_DEV_IDEDISK=y
++# CONFIG_IDEDISK_MULTI_MODE is not set
++CONFIG_BLK_DEV_IDECD=y
++# CONFIG_BLK_DEV_IDETAPE is not set
++# CONFIG_BLK_DEV_IDEFLOPPY is not set
++# CONFIG_BLK_DEV_IDESCSI is not set
++# CONFIG_IDE_TASK_IOCTL is not set
++
++#
++# IDE chipset support/bugfixes
++#
++CONFIG_IDE_GENERIC=y
++CONFIG_BLK_DEV_EP93XX=y
++# CONFIG_BLK_DEV_IDEDMA_EP93XX is not set
++CONFIG_IDE_ARM=y
++# CONFIG_BLK_DEV_IDEDMA is not set
++# CONFIG_IDEDMA_AUTO is not set
++# CONFIG_BLK_DEV_HD is not set
++
++#
++# SCSI device support
++#
++CONFIG_SCSI=y
++CONFIG_SCSI_PROC_FS=y
++
++#
++# SCSI support type (disk, tape, CD-ROM)
++#
++CONFIG_BLK_DEV_SD=y
++# CONFIG_CHR_DEV_ST is not set
++# CONFIG_CHR_DEV_OSST is not set
++# CONFIG_BLK_DEV_SR is not set
++CONFIG_CHR_DEV_SG=y
++# CONFIG_CHR_DEV_SCH is not set
++
++#
++# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
++#
++# CONFIG_SCSI_MULTI_LUN is not set
++# CONFIG_SCSI_CONSTANTS is not set
++# CONFIG_SCSI_LOGGING is not set
++
++#
++# SCSI Transport Attributes
++#
++# CONFIG_SCSI_SPI_ATTRS is not set
++# CONFIG_SCSI_FC_ATTRS is not set
++# CONFIG_SCSI_ISCSI_ATTRS is not set
++
++#
++# SCSI low-level drivers
++#
++# CONFIG_SCSI_SATA is not set
++# CONFIG_SCSI_DEBUG is not set
++
++#
++# Multi-device support (RAID and LVM)
++#
++# CONFIG_MD is not set
++
++#
++# Fusion MPT device support
++#
++# CONFIG_FUSION is not set
++
++#
++# IEEE 1394 (FireWire) support
++#
++# CONFIG_IEEE1394 is not set
++
++#
++# I2O device support
++#
++
++#
++# Network device support
++#
++CONFIG_NETDEVICES=y
++# CONFIG_DUMMY is not set
++# CONFIG_BONDING is not set
++# CONFIG_EQUALIZER is not set
++# CONFIG_TUN is not set
++
++#
++# Ethernet (10 or 100Mbit)
++#
++CONFIG_NET_ETHERNET=y
++CONFIG_MII=y
++CONFIG_EP93XX_ETHERNET=y
++# CONFIG_SMC91X is not set
++# CONFIG_DM9000 is not set
++
++#
++# Ethernet (1000 Mbit)
++#
++
++#
++# Ethernet (10000 Mbit)
++#
++
++#
++# Token Ring devices
++#
++
++#
++# Wireless LAN (non-hamradio)
++#
++CONFIG_NET_RADIO=y
++
++#
++# Obsolete Wireless cards support (pre-802.11)
++#
++# CONFIG_STRIP is not set
++# CONFIG_ATMEL is not set
++
++#
++# Wan interfaces
++#
++# CONFIG_WAN is not set
++# CONFIG_PPP is not set
++# CONFIG_SLIP is not set
++# CONFIG_SHAPER is not set
++CONFIG_NETCONSOLE=y
++CONFIG_NETPOLL=y
++# CONFIG_NETPOLL_RX is not set
++# CONFIG_NETPOLL_TRAP is not set
++CONFIG_NET_POLL_CONTROLLER=y
++
++#
++# ISDN subsystem
++#
++# CONFIG_ISDN is not set
++
++#
++# Input device support
++#
++CONFIG_INPUT=y
++
++#
++# Userland interfaces
++#
++CONFIG_INPUT_MOUSEDEV=y
++CONFIG_INPUT_MOUSEDEV_PSAUX=y
++CONFIG_INPUT_MOUSEDEV_SCREEN_X=640
++CONFIG_INPUT_MOUSEDEV_SCREEN_Y=480
++# CONFIG_INPUT_JOYDEV is not set
++# CONFIG_INPUT_TSDEV is not set
++CONFIG_INPUT_EVDEV=y
++CONFIG_INPUT_EVBUG=y
++
++#
++# Input Device Drivers
++#
++CONFIG_INPUT_KEYBOARD=y
++# CONFIG_KEYBOARD_ATKBD is not set
++# CONFIG_KEYBOARD_SUNKBD is not set
++# CONFIG_KEYBOARD_LKKBD is not set
++# CONFIG_KEYBOARD_XTKBD is not set
++# CONFIG_KEYBOARD_NEWTON is not set
++CONFIG_KEYBOARD_EP93XX=y
++# CONFIG_KEYBOARD_EP93XX_SPI is not set
++# CONFIG_KEYBOARD_EP93XX_8X8 is not set
++# CONFIG_INPUT_MOUSE is not set
++# CONFIG_INPUT_JOYSTICK is not set
++# CONFIG_INPUT_TOUCHSCREEN is not set
++# CONFIG_INPUT_MISC is not set
++
++#
++# Hardware I/O ports
++#
++CONFIG_SERIO=y
++CONFIG_SERIO_SERPORT=y
++# CONFIG_SERIO_AMBAKMI is not set
++# CONFIG_SERIO_RAW is not set
++# CONFIG_GAMEPORT is not set
++
++#
++# Character devices
++#
++CONFIG_VT=y
++CONFIG_VT_CONSOLE=y
++CONFIG_HW_CONSOLE=y
++# CONFIG_SERIAL_NONSTANDARD is not set
++
++#
++# Serial drivers
++#
++# CONFIG_SERIAL_8250 is not set
++
++#
++# Non-8250 serial port support
++#
++# CONFIG_SERIAL_AMBA_PL010 is not set
++# CONFIG_SERIAL_AMBA_PL011 is not set
++CONFIG_SERIAL_EP93XX=y
++CONFIG_SERIAL_EP93XX_CONSOLE=y
++CONFIG_SERIAL_CORE=y
++CONFIG_SERIAL_CORE_CONSOLE=y
++CONFIG_UNIX98_PTYS=y
++CONFIG_LEGACY_PTYS=y
++CONFIG_LEGACY_PTY_COUNT=256
++
++#
++# IPMI
++#
++# CONFIG_IPMI_HANDLER is not set
++
++#
++# Watchdog Cards
++#
++# CONFIG_WATCHDOG is not set
++# CONFIG_NVRAM is not set
++# CONFIG_RTC is not set
++# CONFIG_EP93XX_RTC is not set
++# CONFIG_DS1337_RTC is not set
++# CONFIG_DTLK is not set
++# CONFIG_R3964 is not set
++
++#
++# Ftape, the floppy tape device driver
++#
++
++#
++# CAN bus devices
++#
++# CONFIG_CAN_BUS is not set
++# CONFIG_RAW_DRIVER is not set
++
++#
++# TPM devices
++#
++
++#
++# I2C support
++#
++CONFIG_I2C=y
++CONFIG_I2C_CHARDEV=y
++
++#
++# I2C Algorithms
++#
++CONFIG_I2C_ALGOBIT=y
++# CONFIG_I2C_ALGOPCF is not set
++# CONFIG_I2C_ALGOPCA is not set
++
++#
++# I2C Hardware Bus support
++#
++CONFIG_I2C_EP93XX=y
++# CONFIG_I2C_ISA is not set
++# CONFIG_I2C_PARPORT_LIGHT is not set
++# CONFIG_I2C_STUB is not set
++# CONFIG_I2C_PCA_ISA is not set
++# CONFIG_I2C_SENSOR is not set
++
++#
++# Miscellaneous I2C Chip support
++#
++# CONFIG_SENSORS_DS1337 is not set
++# CONFIG_SENSORS_DS1374 is not set
++# CONFIG_SENSORS_DS1307 is not set
++# CONFIG_SENSORS_EEPROM is not set
++# CONFIG_SENSORS_PCF8574 is not set
++# CONFIG_SENSORS_PCA9539 is not set
++# CONFIG_SENSORS_PCF8591 is not set
++# CONFIG_SENSORS_RTC8564 is not set
++# CONFIG_SENSORS_MAX6875 is not set
++# CONFIG_I2C_DEBUG_CORE is not set
++# CONFIG_I2C_DEBUG_ALGO is not set
++# CONFIG_I2C_DEBUG_BUS is not set
++# CONFIG_I2C_DEBUG_CHIP is not set
++
++#
++# Hardware Monitoring support
++#
++CONFIG_HWMON=y
++# CONFIG_SENSORS_ADM1021 is not set
++# CONFIG_SENSORS_ADM1025 is not set
++# CONFIG_SENSORS_ADM1026 is not set
++# CONFIG_SENSORS_ADM1031 is not set
++# CONFIG_SENSORS_ADM9240 is not set
++# CONFIG_SENSORS_ASB100 is not set
++# CONFIG_SENSORS_ATXP1 is not set
++# CONFIG_SENSORS_DS1621 is not set
++# CONFIG_SENSORS_FSCHER is not set
++# CONFIG_SENSORS_FSCPOS is not set
++# CONFIG_SENSORS_GL518SM is not set
++# CONFIG_SENSORS_GL520SM is not set
++# CONFIG_SENSORS_IT87 is not set
++# CONFIG_SENSORS_LM63 is not set
++# CONFIG_SENSORS_LM75 is not set
++# CONFIG_SENSORS_LM77 is not set
++# CONFIG_SENSORS_LM78 is not set
++# CONFIG_SENSORS_LM80 is not set
++# CONFIG_SENSORS_LM83 is not set
++# CONFIG_SENSORS_LM85 is not set
++# CONFIG_SENSORS_LM87 is not set
++# CONFIG_SENSORS_LM90 is not set
++# CONFIG_SENSORS_LM92 is not set
++# CONFIG_SENSORS_MAX1619 is not set
++# CONFIG_SENSORS_PC87360 is not set
++# CONFIG_SENSORS_SMSC47M1 is not set
++# CONFIG_SENSORS_SMSC47B397 is not set
++# CONFIG_SENSORS_W83781D is not set
++# CONFIG_SENSORS_W83L785TS is not set
++# CONFIG_SENSORS_W83627HF is not set
++# CONFIG_SENSORS_W83627EHF is not set
++# CONFIG_HWMON_DEBUG_CHIP is not set
++
++#
++# Misc devices
++#
++
++#
++# Multimedia devices
++#
++# CONFIG_VIDEO_DEV is not set
++
++#
++# Digital Video Broadcasting Devices
++#
++# CONFIG_DVB is not set
++
++#
++# Graphics support
++#
++CONFIG_FB=y
++CONFIG_FB_CFB_FILLRECT=y
++CONFIG_FB_CFB_COPYAREA=y
++CONFIG_FB_CFB_IMAGEBLIT=y
++CONFIG_FB_SOFT_CURSOR=y
++# CONFIG_FB_MACMODES is not set
++CONFIG_FB_MODE_HELPERS=y
++# CONFIG_FB_TILEBLITTING is not set
++# CONFIG_FB_ARMCLCD is not set
++# CONFIG_FB_CX25871_I2C is not set
++CONFIG_FB_EP93XX=y
++# CONFIG_FB_CRT_EP93XX is not set
++# CONFIG_FB_LCD_EP93XX is not set
++# CONFIG_FB_LCD_EP93XX_SHARP is not set
++# CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343 is not set
++# CONFIG_FB_CX25871 is not set
++CONFIG_FB_LCD_TX09D50VM1CCA=y
++# CONFIG_FB_EP93XX_8BPP is not set
++# CONFIG_FB_EP93XX_16BPP_565 is not set
++CONFIG_FB_EP93XX_24BPP=y
++# CONFIG_FB_EP93XX_32BPP is not set
++# CONFIG_FB_S1D13XXX is not set
++# CONFIG_FB_VIRTUAL is not set
++
++#
++# Console display driver support
++#
++# CONFIG_VGA_CONSOLE is not set
++CONFIG_DUMMY_CONSOLE=y
++CONFIG_FRAMEBUFFER_CONSOLE=y
++CONFIG_FONTS=y
++# CONFIG_FONT_8x8 is not set
++CONFIG_FONT_8x16=y
++# CONFIG_FONT_6x11 is not set
++# CONFIG_FONT_7x14 is not set
++# CONFIG_FONT_PEARL_8x8 is not set
++# CONFIG_FONT_ACORN_8x8 is not set
++# CONFIG_FONT_MINI_4x6 is not set
++CONFIG_FONT_SUN8x16=y
++# CONFIG_FONT_SUN12x22 is not set
++# CONFIG_FONT_10x18 is not set
++
++#
++# Logo configuration
++#
++CONFIG_LOGO=y
++CONFIG_LOGO_LINUX_MONO=y
++CONFIG_LOGO_LINUX_VGA16=y
++CONFIG_LOGO_LINUX_CLUT224=y
++# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
++
++#
++# Sound
++#
++CONFIG_SOUND=y
++
++#
++# Advanced Linux Sound Architecture
++#
++# CONFIG_SND is not set
++
++#
++# Open Sound System
++#
++CONFIG_SOUND_PRIME=y
++# CONFIG_SOUND_MSNDCLAS is not set
++# CONFIG_SOUND_MSNDPIN is not set
++# CONFIG_SOUND_OSS is not set
++# CONFIG_SOUND_TVMIXER is not set
++# CONFIG_SOUND_AD1980 is not set
++
++#
++# USB support
++#
++CONFIG_USB_ARCH_HAS_HCD=y
++CONFIG_USB_ARCH_HAS_OHCI=y
++CONFIG_USB=y
++# CONFIG_USB_DEBUG is not set
++
++#
++# Miscellaneous USB options
++#
++CONFIG_USB_DEVICEFS=y
++# CONFIG_USB_BANDWIDTH is not set
++# CONFIG_USB_DYNAMIC_MINORS is not set
++# CONFIG_USB_OTG is not set
++
++#
++# USB Host Controller Drivers
++#
++# CONFIG_USB_ISP116X_HCD is not set
++CONFIG_USB_OHCI_HCD=y
++# CONFIG_USB_OHCI_BIG_ENDIAN is not set
++CONFIG_USB_OHCI_LITTLE_ENDIAN=y
++# CONFIG_USB_SL811_HCD is not set
++
++#
++# USB Device Class drivers
++#
++# CONFIG_USB_AUDIO is not set
++# CONFIG_USB_BLUETOOTH_TTY is not set
++# CONFIG_USB_MIDI is not set
++# CONFIG_USB_ACM is not set
++# CONFIG_USB_PRINTER is not set
++
++#
++# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' may also be needed; see USB_STORAGE Help for more information
++#
++CONFIG_USB_STORAGE=y
++# CONFIG_USB_STORAGE_DEBUG is not set
++# CONFIG_USB_STORAGE_DATAFAB is not set
++# CONFIG_USB_STORAGE_FREECOM is not set
++# CONFIG_USB_STORAGE_ISD200 is not set
++# CONFIG_USB_STORAGE_DPCM is not set
++# CONFIG_USB_STORAGE_USBAT is not set
++# CONFIG_USB_STORAGE_SDDR09 is not set
++# CONFIG_USB_STORAGE_SDDR55 is not set
++# CONFIG_USB_STORAGE_JUMPSHOT is not set
++
++#
++# USB Input Devices
++#
++CONFIG_USB_HID=y
++CONFIG_USB_HIDINPUT=y
++# CONFIG_HID_FF is not set
++# CONFIG_USB_HIDDEV is not set
++# CONFIG_USB_AIPTEK is not set
++# CONFIG_USB_WACOM is not set
++# CONFIG_USB_ACECAD is not set
++# CONFIG_USB_KBTAB is not set
++# CONFIG_USB_POWERMATE is not set
++# CONFIG_USB_MTOUCH is not set
++# CONFIG_USB_ITMTOUCH is not set
++# CONFIG_USB_EGALAX is not set
++# CONFIG_USB_XPAD is not set
++# CONFIG_USB_ATI_REMOTE is not set
++# CONFIG_USB_KEYSPAN_REMOTE is not set
++
++#
++# USB Imaging devices
++#
++# CONFIG_USB_MDC800 is not set
++# CONFIG_USB_MICROTEK is not set
++
++#
++# USB Multimedia devices
++#
++# CONFIG_USB_DABUSB is not set
++
++#
++# Video4Linux support is needed for USB Multimedia device support
++#
++
++#
++# USB Network Adapters
++#
++# CONFIG_USB_CATC is not set
++# CONFIG_USB_KAWETH is not set
++# CONFIG_USB_PEGASUS is not set
++# CONFIG_USB_RTL8150 is not set
++# CONFIG_USB_USBNET is not set
++# CONFIG_USB_ZD1201 is not set
++CONFIG_USB_MON=y
++
++#
++# USB port drivers
++#
++
++#
++# USB Serial Converter support
++#
++# CONFIG_USB_SERIAL is not set
++
++#
++# USB Miscellaneous drivers
++#
++# CONFIG_USB_EMI62 is not set
++# CONFIG_USB_EMI26 is not set
++# CONFIG_USB_AUERSWALD is not set
++# CONFIG_USB_RIO500 is not set
++# CONFIG_USB_LEGOTOWER is not set
++# CONFIG_USB_LCD is not set
++# CONFIG_USB_LED is not set
++# CONFIG_USB_CYTHERM is not set
++# CONFIG_USB_PHIDGETKIT is not set
++# CONFIG_USB_PHIDGETSERVO is not set
++# CONFIG_USB_IDMOUSE is not set
++# CONFIG_USB_LD is not set
++# CONFIG_USB_TEST is not set
++
++#
++# USB DSL modem support
++#
++
++#
++# USB Gadget Support
++#
++# CONFIG_USB_GADGET is not set
++
++#
++# MMC/SD Card support
++#
++# CONFIG_MMC is not set
++
++#
++# File systems
++#
++CONFIG_EXT2_FS=y
++# CONFIG_EXT2_FS_XATTR is not set
++# CONFIG_EXT2_FS_XIP is not set
++CONFIG_EXT3_FS=y
++CONFIG_EXT3_FS_XATTR=y
++# CONFIG_EXT3_FS_POSIX_ACL is not set
++# CONFIG_EXT3_FS_SECURITY is not set
++CONFIG_JBD=y
++# CONFIG_JBD_DEBUG is not set
++CONFIG_FS_MBCACHE=y
++# CONFIG_REISERFS_FS is not set
++# CONFIG_JFS_FS is not set
++# CONFIG_FS_POSIX_ACL is not set
++
++#
++# XFS support
++#
++# CONFIG_XFS_FS is not set
++# CONFIG_MINIX_FS is not set
++CONFIG_ROMFS_FS=y
++CONFIG_INOTIFY=y
++# CONFIG_QUOTA is not set
++CONFIG_DNOTIFY=y
++CONFIG_AUTOFS_FS=y
++# CONFIG_AUTOFS4_FS is not set
++
++#
++# CD-ROM/DVD Filesystems
++#
++CONFIG_ISO9660_FS=y
++CONFIG_JOLIET=y
++CONFIG_ZISOFS=y
++CONFIG_ZISOFS_FS=y
++CONFIG_UDF_FS=y
++CONFIG_UDF_NLS=y
++
++#
++# 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=y
++# CONFIG_NTFS_DEBUG is not set
++CONFIG_NTFS_RW=y
++
++#
++# Pseudo filesystems
++#
++CONFIG_PROC_FS=y
++CONFIG_SYSFS=y
++# CONFIG_DEVPTS_FS_XATTR is not set
++CONFIG_TMPFS=y
++# CONFIG_TMPFS_XATTR is not set
++# CONFIG_HUGETLBFS is not set
++# CONFIG_HUGETLB_PAGE is not set
++CONFIG_RAMFS=y
++
++#
++# Miscellaneous filesystems
++#
++# CONFIG_ADFS_FS is not set
++# CONFIG_AFFS_FS is not set
++# CONFIG_HFS_FS is not set
++# CONFIG_HFSPLUS_FS is not set
++# CONFIG_BEFS_FS is not set
++# CONFIG_BFS_FS is not set
++# CONFIG_EFS_FS is not set
++# CONFIG_JFFS_FS is not set
++CONFIG_JFFS2_FS=y
++CONFIG_JFFS2_FS_DEBUG=0
++CONFIG_JFFS2_FS_WRITEBUFFER=y
++# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
++CONFIG_JFFS2_ZLIB=y
++CONFIG_JFFS2_RTIME=y
++# CONFIG_JFFS2_RUBIN is not set
++# CONFIG_CRAMFS is not set
++# CONFIG_VXFS_FS is not set
++# CONFIG_HPFS_FS is not set
++# CONFIG_QNX4FS_FS is not set
++# CONFIG_SYSV_FS is not set
++# CONFIG_UFS_FS is not set
++
++#
++# Network File Systems
++#
++CONFIG_NFS_FS=y
++CONFIG_NFS_V3=y
++# CONFIG_NFS_V3_ACL is not set
++CONFIG_NFS_V4=y
++# CONFIG_NFS_DIRECTIO is not set
++# CONFIG_NFSD is not set
++CONFIG_ROOT_NFS=y
++CONFIG_LOCKD=y
++CONFIG_LOCKD_V4=y
++CONFIG_NFS_COMMON=y
++CONFIG_SUNRPC=y
++CONFIG_SUNRPC_GSS=y
++CONFIG_RPCSEC_GSS_KRB5=y
++# 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=y
++# CONFIG_ACORN_PARTITION is not set
++# CONFIG_OSF_PARTITION is not set
++# CONFIG_AMIGA_PARTITION is not set
++# CONFIG_ATARI_PARTITION is not set
++# CONFIG_MAC_PARTITION is not set
++CONFIG_MSDOS_PARTITION=y
++# CONFIG_BSD_DISKLABEL is not set
++# CONFIG_MINIX_SUBPARTITION is not set
++# CONFIG_SOLARIS_X86_PARTITION is not set
++# CONFIG_UNIXWARE_DISKLABEL is not set
++# CONFIG_LDM_PARTITION is not set
++# CONFIG_SGI_PARTITION is not set
++# CONFIG_ULTRIX_PARTITION is not set
++# CONFIG_SUN_PARTITION is not set
++# CONFIG_EFI_PARTITION is not set
++
++#
++# Native Language Support
++#
++CONFIG_NLS=y
++CONFIG_NLS_DEFAULT="iso8859-1"
++CONFIG_NLS_CODEPAGE_437=y
++# CONFIG_NLS_CODEPAGE_737 is not set
++# CONFIG_NLS_CODEPAGE_775 is not set
++# CONFIG_NLS_CODEPAGE_850 is not set
++# CONFIG_NLS_CODEPAGE_852 is not set
++# CONFIG_NLS_CODEPAGE_855 is not set
++# CONFIG_NLS_CODEPAGE_857 is not set
++# CONFIG_NLS_CODEPAGE_860 is not set
++# CONFIG_NLS_CODEPAGE_861 is not set
++# CONFIG_NLS_CODEPAGE_862 is not set
++# CONFIG_NLS_CODEPAGE_863 is not set
++# CONFIG_NLS_CODEPAGE_864 is not set
++# CONFIG_NLS_CODEPAGE_865 is not set
++# CONFIG_NLS_CODEPAGE_866 is not set
++# CONFIG_NLS_CODEPAGE_869 is not set
++# CONFIG_NLS_CODEPAGE_936 is not set
++# CONFIG_NLS_CODEPAGE_950 is not set
++# CONFIG_NLS_CODEPAGE_932 is not set
++# CONFIG_NLS_CODEPAGE_949 is not set
++# CONFIG_NLS_CODEPAGE_874 is not set
++# CONFIG_NLS_ISO8859_8 is not set
++# CONFIG_NLS_CODEPAGE_1250 is not set
++# CONFIG_NLS_CODEPAGE_1251 is not set
++# CONFIG_NLS_ASCII 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=y
++# CONFIG_NLS_KOI8_R is not set
++# CONFIG_NLS_KOI8_U is not set
++CONFIG_NLS_UTF8=y
++
++#
++# Profiling support
++#
++# CONFIG_PROFILING is not set
++
++#
++# Kernel hacking
++#
++# CONFIG_PRINTK_TIME is not set
++CONFIG_DEBUG_KERNEL=y
++# CONFIG_MAGIC_SYSRQ is not set
++CONFIG_LOG_BUF_SHIFT=14
++# CONFIG_SCHEDSTATS is not set
++# CONFIG_DEBUG_SLAB is not set
++# CONFIG_DEBUG_SPINLOCK is not set
++# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
++# CONFIG_DEBUG_KOBJECT is not set
++CONFIG_DEBUG_BUGVERBOSE=y
++CONFIG_DEBUG_INFO=y
++# CONFIG_DEBUG_FS is not set
++CONFIG_FRAME_POINTER=y
++CONFIG_DEBUG_USER=y
++# CONFIG_DEBUG_WAITQ is not set
++CONFIG_DEBUG_ERRORS=y
++CONFIG_DEBUG_DONT_REORDER_CODE=y
++CONFIG_DEBUG_LL=y
++# CONFIG_DEBUG_ICEDCC is not set
++
++#
++# Security options
++#
++# CONFIG_KEYS is not set
++# CONFIG_SECURITY is not set
++
++#
++# Cryptographic options
++#
++CONFIG_CRYPTO=y
++# CONFIG_CRYPTO_HMAC is not set
++# CONFIG_CRYPTO_NULL is not set
++# CONFIG_CRYPTO_MD4 is not set
++CONFIG_CRYPTO_MD5=y
++# CONFIG_CRYPTO_SHA1 is not set
++# CONFIG_CRYPTO_SHA256 is not set
++# CONFIG_CRYPTO_SHA512 is not set
++# CONFIG_CRYPTO_WP512 is not set
++# CONFIG_CRYPTO_TGR192 is not set
++CONFIG_CRYPTO_DES=y
++# CONFIG_CRYPTO_BLOWFISH is not set
++# CONFIG_CRYPTO_TWOFISH is not set
++# CONFIG_CRYPTO_SERPENT is not set
++# CONFIG_CRYPTO_AES is not set
++# CONFIG_CRYPTO_CAST5 is not set
++# CONFIG_CRYPTO_CAST6 is not set
++# CONFIG_CRYPTO_TEA is not set
++# CONFIG_CRYPTO_ARC4 is not set
++# CONFIG_CRYPTO_KHAZAD is not set
++# CONFIG_CRYPTO_ANUBIS is not set
++# CONFIG_CRYPTO_DEFLATE is not set
++# CONFIG_CRYPTO_MICHAEL_MIC is not set
++# CONFIG_CRYPTO_CRC32C is not set
++# CONFIG_CRYPTO_TEST is not set
++
++#
++# Hardware crypto devices
++#
++
++#
++# Library routines
++#
++# CONFIG_CRC_CCITT is not set
++CONFIG_CRC32=y
++CONFIG_LIBCRC32C=y
++CONFIG_ZLIB_INFLATE=y
++CONFIG_ZLIB_DEFLATE=y
+diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig
+new file mode 100644
+index 0000000..2b5c2d6
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/Kconfig
+@@ -0,0 +1,193 @@
++
++menu "EP93xx"
++ depends on ARCH_EP93XX
++
++choice
++ prompt "EP93xx CPU Type"
++ default EP9312
++ help
++ There are several types of EP93xx CPUs available.
++ Choosing the right one here enables you to select
++ model specific drivers later.
++
++config ARCH_EP9301
++ bool "EP9301"
++ help
++ Say Y here if you have intend to run this kernel on a EP9301 CPU.
++
++config ARCH_EP9302
++ bool "EP9302"
++ help
++ Say Y here if you have intend to run this kernel on a EP9302 CPU.
++
++config ARCH_EP9312
++ bool "EP9312"
++ help
++ Say Y here if you intend to run this kernel on a EP9312 CPU.
++
++
++config ARCH_EP9315
++ bool "EP9315"
++ help
++ Say Y here if you intend to run this kernel on a EP9315 CPU.
++endchoice
++
++choice
++ prompt "EP9301 Boards"
++ depends on ARCH_EP9301
++ default EDB9301
++ help
++ There are several EP9301-based boards available.
++ Choosing the right one here enables various board-
++ specific options.
++
++config MACH_EDB9301
++ bool "Cirrus Logic EDB9301"
++ select MTD
++ select MTD_PHYSMAP
++ help
++ Say Y here if you intend to run this kernel on an EDB9301.
++
++config MACH_TTML
++ bool "TTML TripDawg"
++ help
++ Say Y here if you intend to run this kernel on an TTML TripDawg.
++
++endchoice
++
++choice
++ prompt "EP9302 Boards"
++ depends on ARCH_EP9302
++ default EDB9302
++ help
++ There are several EP9302-based boards available.
++ Choosing the right one here enables various board-
++ specific options.
++
++config MACH_EDB9302
++ bool "Cirrus Logic EDB9302"
++ select MTD
++ select MTD_PHYSMAP
++ help
++ Say Y here if you intend to run this kernel on an EDB9302.
++
++config MACH_ZEFEERDZB
++ bool "Dave Zefeer DZB on ZefeerEVB-L"
++ select MTD
++ help
++ Say Y here if you intend to run this kernel on an Zefeer DZB.
++ pluggend onto ZefeerEVB-L board.
++
++config MACH_ZEFEER_EVBL_107
++ bool " Dave ZefeerEVB-L - version 1.0.7 (PCB CS044404)"
++ depends on MACH_ZEFEERDZB
++ default n
++ help
++ Say Y here if you intend to run this kernel on an ZefeerEVB-L
++ version 1.0.7.
++
++endchoice
++
++choice
++ prompt "EP9312 Boards"
++ depends on ARCH_EP9312
++ default EDB9312
++ help
++ There are several EP9312-based boards available.
++ Choosing the right one here enables various board-
++ specific options.
++
++config MACH_EDB9312
++ bool "Cirrus Logic EDB9312"
++ select MTD
++ select MTD_PHYSMAP
++ help
++ Say Y here if you intend to run this kernel on an EDB9312.
++
++
++config MACH_ACC
++ bool "HiFish ACC"
++ help
++ Say Y here if you are using the HiFish Audio Control Center"
++
++endchoice
++
++choice
++ prompt "EP9315 Boards"
++ depends on ARCH_EP9315
++ default EDB9315
++ help
++ There are several EP9315-based boards available.
++ Choosing the right one here enables various board-
++ specific options.
++
++config MACH_EDB9315
++ bool "Cirrus Logic EDB9315"
++ select MTD
++ select MTD_PHYSMAP
++ help
++ Say Y here if you intend to run this kernel on an EDB9315.
++
++config MACH_ADSSPHERE
++ bool "Applied Data Systems Sphere"
++ select MTD
++ help
++ Say Y here if you intend to run this kernel on an ADSSPHERE.
++
++config MACH_ZEFEERDZQ
++ bool "Dave Zefeer DZQ on ZefeerEVB (L or H)"
++ select MTD
++ help
++ Say Y here if you intend to run this kernel on an Zefeer DZQ.
++ Both evaluation board are supported (ZefeerEVB-L/ZefeerEVB-H).
++
++config MACH_DMA03
++ bool "Gassner DMA03"
++ select MTD
++ select MTD_PHYSMAP
++ help
++ Say Y here if you intend to run this kernel on an DMA03.
++
++endchoice
++
++config ARCH_EP93XX_GPIO_IRQ
++ bool " EP93xx GPIO IRQ demux"
++ depends on ARCH_EP93XX
++ help
++ Say Y here if you want to expand the IRQ number to GPIO IRQ.
++
++config EP93XX_DMA
++ bool " EP93xx Internal DMA Support"
++ default y
++ help
++ Say Y here if you want to enable DMA Support for EP93XX family
++ CPUs.
++
++config EP93XX_SSP
++ bool "SSP support"
++ help
++ If you require SSP support, there are two SSP drivers
++ available to choose from.
++
++choice
++ prompt "SSP driver"
++ depends on EP93XX_SSP
++ default EP93XX_SSP_LINUX
++
++config EP93XX_SSP_CIRRUS
++ tristate "Cirrus Logic SSP driver"
++ depends on EP93XX_SSP
++ help
++ Say Y here for the Cirrus-supplied SSP driver. It is
++ quite specific to the EDB93xx evaluation boards.
++
++config EP93XX_SSP_LINUX
++ tristate "Linux SSP driver"
++ depends on EP93XX_SSP
++ help
++ Say Y here for an SSP driver which is heavily based on the
++ SA-1100 and PXA2xx SSP drivers.
++
++endchoice
++
++endmenu
+diff --git a/arch/arm/mach-ep93xx/Makefile b/arch/arm/mach-ep93xx/Makefile
+new file mode 100644
+index 0000000..19c56b3
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/Makefile
+@@ -0,0 +1,17 @@
++obj-y += ep93xx.o irq.o time.o
++
++obj-$(CONFIG_MACH_ACC) += mach-acc.o
++obj-$(CONFIG_MACH_EDB9301) += mach-edb9301.o
++obj-$(CONFIG_MACH_EDB9302) += mach-edb9302.o
++obj-$(CONFIG_MACH_EDB9312) += mach-edb9312.o
++obj-$(CONFIG_MACH_EDB9315) += mach-edb9315.o
++obj-$(CONFIG_MACH_ADSSPHERE) += mach-adssphere.o
++obj-$(CONFIG_MACH_TTML) += mach-ttml.o
++obj-$(CONFIG_MACH_ZEFEERDZB) += mach-zefeerdzb.o
++obj-$(CONFIG_MACH_ZEFEERDZQ) += mach-zefeerdzq.o
++obj-$(CONFIG_MACH_DMA03) += mach-dma03.o
++
++obj-$(CONFIG_EP93XX_DMA) += dma_ep93xx.o
++
++obj-$(CONFIG_EP93XX_SSP_LINUX) += ssp.o ssp2.o
++obj-$(CONFIG_EP93XX_SSP_CIRRUS) += ssp-cirrus.o
+diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot
+new file mode 100644
+index 0000000..c87653e
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/Makefile.boot
+@@ -0,0 +1,6 @@
++ zreladdr-y := 0x00008000
++params_phys-y := 0x00000100
++ zreladdr-$(CONFIG_MACH_ZEFEERDZB) := 0xD0008000
++params_phys-$(CONFIG_MACH_ZEFEERDZB) := 0xD0000100
++ zreladdr-$(CONFIG_MACH_ZEFEERDZQ) := 0xD0008000
++params_phys-$(CONFIG_MACH_ZEFEERDZQ) := 0xD0000100
+diff --git a/arch/arm/mach-ep93xx/dma_ep93xx.c b/arch/arm/mach-ep93xx/dma_ep93xx.c
+new file mode 100644
+index 0000000..817de48
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/dma_ep93xx.c
+@@ -0,0 +1,3346 @@
++/******************************************************************************
++ * arch/arm/mach-ep9312/dma_ep93xx.c
++ *
++ * Support functions for the ep93xx internal DMA channels.
++ * (see also Documentation/arm/ep93xx/dma.txt)
++ *
++ * Copyright (C) 2003 Cirrus Logic
++ *
++ * A large portion of this file is based on the dma api implemented by
++ * Nicolas Pitre, dma-sa1100.c, copyrighted 2000.
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ ****************************************************************************/
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/sched.h>
++#include <linux/spinlock.h>
++#include <linux/slab.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++
++#include <asm/system.h>
++#include <asm/irq.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++#include <asm/mach/dma.h>
++#include "dma_ep93xx.h"
++
++/*****************************************************************************
++ *
++ * Debugging macros
++ *
++ ****************************************************************************/
++#undef DEBUG
++/*#define DEBUG 1 */
++#ifdef DEBUG
++#define DPRINTK( x... ) printk( ##x )
++#else
++#define DPRINTK( x... )
++#endif
++
++/*****************************************************************************
++ *
++ * static global variables
++ *
++ ****************************************************************************/
++ep93xx_dma_t dma_chan[MAX_EP93XX_DMA_CHANNELS];
++
++/*
++ * Maximum physical DMA buffer size
++ */
++#define MAX_DMA_SIZE 0xffff
++#define MAX_DMA_ORDER 12
++
++/*
++ * lock used to protect the list of dma channels while searching for a free
++ * channel during dma_request.
++ */
++static spinlock_t dma_list_lock = SPIN_LOCK_UNLOCKED;
++
++/*****************************************************************************
++ *
++ * Internal DMA processing functions.
++ *
++ ****************************************************************************/
++/*****************************************************************************
++ *
++ * get_dma_channel_from_handle()
++ *
++ * If Handle is valid, returns the DMA channel # (0 to 9 for channels 1-10)
++ * If Handle is not valid, returns -1.
++ *
++ ****************************************************************************/
++static int dma_get_channel_from_handle(int handle)
++{
++ int channel;
++
++ /*
++ * Get the DMA channel # from the handle.
++ */
++ channel = ((int)handle & DMA_HANDLE_SPECIFIER_MASK) >> 28;
++
++ /*
++ * See if this is a valid handle.
++ */
++ if (dma_chan[channel].last_valid_handle != (int)handle) {
++ DPRINTK("DMA ERROR - invalid handle 0x%x \n", handle);
++ /*
++ * Fail, invalid handle
++ */
++ return (-1);
++ }
++
++ /*
++ * See if this instance is still open
++ */
++ if (!dma_chan[channel].ref_count) {
++ /*
++ * Fail, instance closed
++ */
++ return (-1);
++ }
++
++ return (channel);
++}
++
++/*****************************************************************************
++ *
++ * dma_m2m_irq_handler
++ *
++ * TODO: need to add support for M2M interrupt handling!!!
++ *
++ ****************************************************************************/
++static irqreturn_t
++dma_m2m_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++{
++ ep93xx_dma_t *dma = (ep93xx_dma_t *) dev_id;
++ unsigned int M2M_reg_base = dma->reg_base;
++ ep93xx_dma_dev_t dma_int = UNDEF_INT;
++ unsigned int read_back, loop, uiCONTROL, uiINTERRUPT;
++
++ loop = readl(M2M_reg_base + M2M_OFFSET_INTERRUPT);
++
++ /*
++ * Determine what kind of dma interrupt this is.
++ */
++ if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) &
++ INTERRUPT_M2M_STALLINT)
++ dma_int = STALL;
++ else if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) &
++ INTERRUPT_M2M_NFBINT)
++ dma_int = NFB;
++ else if (readl(M2M_reg_base + M2M_OFFSET_INTERRUPT) &
++ INTERRUPT_M2M_DONEINT)
++ dma_int = DONE;
++
++ DPRINTK("IRQ: b=%#x st=%#x\n", (int)dma->current_buffer->source,
++ dma_int);
++
++ /*
++ * Stall Interrupt: The Channel is stalled, meaning nothing is
++ * programmed to transfer right now. So, we're back to the
++ * beginnning. If there's a buffer to transfer, program it into
++ * max and base 0 registers.
++ */
++ if (dma_int == STALL) {
++ DPRINTK("1 ");
++
++ if (dma->total_buffers) {
++
++ if (readl(M2M_reg_base + M2M_OFFSET_BCR0) !=
++ 0) {
++ writel(0x0, M2M_reg_base + M2M_OFFSET_INTERRUPT);
++ return IRQ_HANDLED;
++
++ }
++
++ /*
++ * The current_buffer has already been tranfered, so add the
++ * byte count to the total_bytes field.
++ */
++ dma->total_bytes = dma->total_bytes +
++ dma->buffer_queue[dma->current_buffer].size;
++
++ /*
++ * Mark the current_buffer as used.
++ */
++ dma->buffer_queue[dma->current_buffer].used = TRUE;
++
++ /*
++ * Increment the used buffer counter
++ */
++ dma->used_buffers++;
++
++ DPRINTK("#%d", dma->current_buffer);
++
++ /*
++ * Increment the current_buffer
++ */
++ dma->current_buffer = (dma->current_buffer + 1) %
++ MAX_EP93XX_DMA_BUFFERS;
++
++ /*
++ * check if there's a new buffer to transfer.
++ */
++ if (dma->new_buffers && dma->xfer_enable) {
++ /*
++ * We have a new buffer to transfer so program in the buffer
++ * values. Since a STALL interrupt was triggered, we
++ * program the buffer descriptor 0
++ *
++ * Set the SAR_BASE/DAR_BASE/BCR registers with values from the
++ * next buffer in the queue.
++ */
++ writel(dma->buffer_queue[dma->current_buffer].
++ source,
++ M2M_reg_base + M2M_OFFSET_SAR_BASE0);
++ writel(dma->buffer_queue[dma->current_buffer].
++ dest,
++ M2M_reg_base + M2M_OFFSET_DAR_BASE0);
++ writel(dma->buffer_queue[dma->current_buffer].
++ size,
++ M2M_reg_base + M2M_OFFSET_BCR0);
++
++ /*
++ * Decrement the new buffer counter
++ */
++ dma->new_buffers--;
++
++ /*
++ * If there's a second new buffer, we program the second
++ * buffer descriptor.
++ */
++#if 0
++ if (dma->new_buffers) {
++ DPRINTK("A ");
++
++ /*
++ * Set the SAR_BASE/DAR_BASE/BCR registers with values from the
++ * next buffer in the queue.
++ */
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ source,
++ M2M_reg_base + M2M_OFFSET_SAR_BASE1);
++
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ dest,
++ M2M_reg_base + M2M_OFFSET_DAR_BASE0);
++
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ size,
++ M2M_reg_base + M2M_OFFSET_BCR0);
++
++ /*
++ * Decrement the new buffer counter
++ */
++ dma->new_buffers--;
++
++ /*
++ * Enable the NFB Interrupt.
++ */
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL |= CONTROL_M2M_NFBINTEN;
++ writel(uiCONTROL,
++ M2M_reg_base + M2M_OFFSET_CONTROL);
++ }
++#endif
++ }
++ /*
++ * Read my lips. No new buffers.
++ */
++ else {
++ DPRINTK("2 \n");
++ /*
++ * There's a chance we setup both buffer descriptors, but
++ * didn't service the NFB quickly enough, causing the channel
++ * to transfer both buffers, then enter the stall state.
++ * So, we need to be able to process the second buffer.
++ */
++ if ((dma->used_buffers + dma->new_buffers) <
++ dma->total_buffers) {
++ DPRINTK("3 ");
++
++ /*
++ * The current_buffer has already been tranfered, so add the
++ * byte count to the total_bytes field.
++ */
++ dma->total_bytes = dma->total_bytes +
++ dma->buffer_queue[dma->
++ current_buffer].
++ size;
++
++ /*
++ * Mark the current_buffer as used.
++ */
++ dma->buffer_queue[dma->current_buffer].
++ used = TRUE;
++
++ /*
++ * Increment the used buffer counter
++ */
++ dma->used_buffers++;
++
++ DPRINTK("#%d", dma->current_buffer);
++
++ /*
++ * Increment the current buffer pointer.
++ */
++ dma->current_buffer =
++ (dma->current_buffer +
++ 1) % MAX_EP93XX_DMA_BUFFERS;
++
++ }
++
++ /*
++ * No new buffers to transfer, so disable the channel.
++ */
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2M_ENABLE;
++ writel(uiCONTROL,
++ M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * Indicate that this channel is in the pause by starvation
++ * state by setting the pause bit to true.
++ */
++ dma->pause = TRUE;
++
++ DPRINTK("End of stall handling. \n");
++ DPRINTK("STATUS - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_STATUS));
++ DPRINTK("CONTROL - 0x%x \n",
++ readl(M2M_reg_base + M2M_CONTROL.Value));
++ DPRINTK("REMAIN - 0x%x \n",
++ readl(M2M_reg_base + M2M_REMAIN.Value));
++ DPRINTK("PPALLOC - 0x%x \n",
++ readl(M2M_reg_base + M2M_PPALLOC.Value));
++ DPRINTK("BASE0 - 0x%x \n",
++ readl(M2M_reg_base + M2M_BASE0.Value));
++ DPRINTK("MAXCNT0 - 0x%x \n",
++ readl(M2M_reg_base + M2M_MAXCNT0.Value));
++ DPRINTK("CURRENT0 - 0x%x \n",
++ readl(M2M_reg_base + M2M_CURRENT0.Value));
++ DPRINTK("BASE1 - 0x%x \n",
++ readl(M2M_reg_base + M2M_BASE1.Value));
++ DPRINTK("MAXCNT1 - 0x%x \n",
++ readl(M2M_reg_base + M2M_MAXCNT1.Value));
++ DPRINTK("CURRENT1 - 0x%x \n",
++ readl(M2M_reg_base + M2M_CURRENT1.Value));
++
++ DPRINTK
++ ("Buffer buf_id source size last used \n");
++ for (loop = 0; loop < 32; loop++) {
++ DPRINTK
++ ("%d 0x%x 0x%x 0x%x %d %d \n",
++ loop,
++ dma->buffer_queue[loop].buf_id,
++ dma->buffer_queue[loop].source,
++ dma->buffer_queue[loop].size,
++ dma->buffer_queue[loop].last,
++ dma->buffer_queue[loop].used);
++ }
++ DPRINTK("Pause - %d \n", dma->pause);
++ DPRINTK("xfer_enable - %d \n",
++ dma->xfer_enable);
++ DPRINTK("total bytes - 0x%x \n",
++ dma->total_bytes);
++ DPRINTK("total buffer - %d \n",
++ dma->total_buffers);
++ DPRINTK("new buffers - %d \n",
++ dma->new_buffers);
++ DPRINTK("current buffer - %d \n",
++ dma->current_buffer);
++ DPRINTK("last buffer - %d \n",
++ dma->last_buffer);
++ DPRINTK("used buffers - %d \n",
++ dma->used_buffers);
++ DPRINTK("callback addr - 0x%x \n",
++ dma->callback);
++ }
++ }
++ /*
++ * Total number of buffers in the queue is 0.
++ */
++ else {
++ /*
++ * No buffers to transfer, or old buffers to mark as used,
++ * so Disable the channel
++ */
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2M_ENABLE;
++ writel(uiCONTROL,
++ M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * Must read the control register back after a write.
++ */
++ read_back =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * Indicate that this channel is in the pause by
++ * starvation state by setting the pause bit to true.
++ */
++ dma->pause = TRUE;
++ }
++ }
++ /*
++ * Next Frame Buffer Interrupt. If there's a new buffer program it
++ * Check if this is the last buffer in the transfer,
++ * and if it is, disable the NFB int to prevent being
++ * interrupted for another buffer when we know there won't be
++ * another.
++ */
++ if (dma_int == NFB) {
++ DPRINTK("5 ");
++
++ if (dma->total_buffers) {
++ DPRINTK("6 ");
++ /*
++ * The iCurrentBuffer has already been transfered. so add the
++ * byte count from the current buffer to the total byte count.
++ */
++ dma->total_bytes = dma->total_bytes +
++ dma->buffer_queue[dma->current_buffer].size;
++
++ /*
++ * Mark the Current Buffer as used.
++ */
++ dma->buffer_queue[dma->current_buffer].used = TRUE;
++
++ /*
++ * Increment the used buffer counter
++ */
++ dma->used_buffers++;
++
++ DPRINTK("#%d", dma->current_buffer);
++
++ if ((dma->buffer_queue[(dma->current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].last)
++ || (dma->new_buffers == 0)
++ || (dma->xfer_enable == FALSE)) {
++ DPRINTK("7 ");
++
++ /*
++ * This is the last Buffer in this transaction, so disable
++ * the NFB interrupt. We shouldn't get an NFB int when the
++ * FSM moves to the ON state where it would typically get the
++ * NFB int indicating a new buffer can be programmed.
++ * Instead, once in the ON state, the DMA will just proceed
++ * to complet the transfer of the current buffer, move the
++ * FSB directly to the STALL state where a STALL interrupt
++ * will be generated.
++ */
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2M_NFBINTEN;
++ writel(uiCONTROL,
++ M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * The current buffer has been transferred, so increment
++ * the current buffer counter to reflect this.
++ */
++ dma->current_buffer =
++ (dma->current_buffer +
++ 1) % MAX_EP93XX_DMA_BUFFERS;
++
++ DPRINTK("End of NFB handling. \n");
++ DPRINTK("STATUS - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_STATUS));
++ DPRINTK("CONTROL - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL));
++ DPRINTK("REMAIN - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_REMAIN));
++ DPRINTK("PPALLOC - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_PPALLOC));
++ DPRINTK("BASE0 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_BASE0));
++ DPRINTK("MAXCNT0 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_MAXCNT0));
++ DPRINTK("CURRENT0 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_CURRENT0));
++ DPRINTK("BASE1 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_BASE1));
++ DPRINTK("MAXCNT1 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_MAXCNT1));
++ DPRINTK("CURRENT1 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_CURRENT1));
++
++ DPRINTK
++ ("Buffer buf_id source size last used \n");
++ for (loop = 0; loop < 32; loop++) {
++ DPRINTK
++ ("%d 0x%x 0x%x 0x%x %d %d \n",
++ loop,
++ dma->buffer_queue[loop].buf_id,
++ dma->buffer_queue[loop].source,
++ dma->buffer_queue[loop].size,
++ dma->buffer_queue[loop].last,
++ dma->buffer_queue[loop].used);
++ }
++ DPRINTK
++ ("pause 0x%x 0x%x 0x%x %d %d \n",
++ dma->pause_buf.buf_id,
++ dma->pause_buf.source, dma->pause_buf.size,
++ dma->pause_buf.last, dma->pause_buf.used);
++
++ DPRINTK("Pause - %d \n", dma->pause);
++ DPRINTK("xfer_enable - %d \n",
++ dma->xfer_enable);
++ DPRINTK("total bytes - 0x%x \n",
++ dma->total_bytes);
++ DPRINTK("total buffer - %d \n",
++ dma->total_buffers);
++ DPRINTK("new buffers - %d \n",
++ dma->new_buffers);
++ DPRINTK("current buffer - %d \n",
++ dma->current_buffer);
++ DPRINTK("last buffer - %d \n",
++ dma->last_buffer);
++ DPRINTK("used buffers - %d \n",
++ dma->used_buffers);
++ DPRINTK("callback addr - 0x%x \n",
++ dma->callback);
++
++ } else if (dma->new_buffers) {
++ DPRINTK("8 ");
++ /*
++ * we have a new buffer, so increment the current buffer to
++ * point to the next buffer, which is already programmed into
++ * the DMA. Next time around, it'll be pointing to the
++ * current buffer.
++ */
++ dma->current_buffer =
++ (dma->current_buffer +
++ 1) % MAX_EP93XX_DMA_BUFFERS;
++
++ /*
++ * we know we have a new buffer to program as the next
++ * buffer, so check which set of SAR_BASE/DAR_BASE/BCR registers
++ * to program.
++ */
++ if (readl(M2M_reg_base + M2M_OFFSET_STATUS) & STATUS_M2M_NB) {
++ /*
++ * Set the SAR_BASE1/DAR_BASE1/BCR1 registers with values from the
++ * next buffer in the queue.
++ */
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ source,
++ M2M_reg_base + M2M_OFFSET_SAR_BASE1);
++
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ dest,
++ M2M_reg_base + M2M_OFFSET_DAR_BASE1);
++
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ size,
++ M2M_reg_base + M2M_OFFSET_BCR1);
++ } else {
++ /*
++ * Set the SAR_BASE0/DAR_BASE0/BCR0 registers with values from the
++ * next buffer in the queue.
++ */
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ source,
++ M2M_reg_base + M2M_OFFSET_SAR_BASE0);
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ dest,
++ M2M_reg_base + M2M_OFFSET_DAR_BASE0);
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ size,
++ M2M_reg_base + M2M_OFFSET_BCR0);
++ }
++
++ /*
++ * Decrement the new buffers counter
++ */
++ dma->new_buffers--;
++ }
++ }
++ /*
++ * Total number of buffers is 0 - really we should never get here,
++ * but just in case.
++ */
++ else {
++ DPRINTK("9 \n");
++
++ /*
++ * No new buffers to transfer, so Disable the channel
++ */
++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2M_ENABLE;
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * Indicate that the channel is paused by starvation.
++ */
++ dma->pause = 1;
++ }
++ }
++
++ /*
++ * Done interrupt generated, indicating that the transfer is complete.
++ */
++ if (dma_int == DONE) {
++#if 0
++ /* The current_buffer has already been tranfered, so add the
++ * byte count to the total_bytes field.
++ */
++ dma->total_bytes = dma->total_bytes +
++ dma->buffer_queue[dma->current_buffer].size;
++
++ /*
++ * Mark the current_buffer as used.
++ */
++ dma->buffer_queue[dma->current_buffer].used = TRUE;
++
++ /*
++ * Increment the used buffer counter
++ */
++ dma->used_buffers++;
++
++ /*
++ * Increment the current_buffer
++ */
++ dma->current_buffer = (dma->current_buffer + 1) %
++ MAX_EP93XX_DMA_BUFFERS;
++#endif
++ /*
++ * Clear the interrupt.
++ */
++ uiINTERRUPT =
++ readl(M2M_reg_base + M2M_OFFSET_INTERRUPT);
++ uiINTERRUPT &= ~INTERRUPT_M2M_DONEINT;
++ writel(uiINTERRUPT,
++ M2M_reg_base + M2M_OFFSET_INTERRUPT);
++
++ DPRINTK("STATUS - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_STATUS));
++ DPRINTK("CONTROL - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL));
++ DPRINTK("SAR_BASE0 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_SAR_BASE0));
++ DPRINTK("DAR_BASE0 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_DAR_BASE0));
++ DPRINTK("SAR_CURRENT0 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_SAR_CURRENT0));
++ DPRINTK("DAR_CURRENT0 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_DAR_CURRENT0));
++ DPRINTK("BCR0 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_BCR0));
++ DPRINTK("SAR_BASE1 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_SAR_BASE1));
++ DPRINTK("DAR_BASE1 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_DAR_BASE1));
++ DPRINTK("BCR1 - 0x%x \n",
++ readl(M2M_reg_base + M2M_OFFSET_BCR1));
++
++ /*
++ * Disable the channel.
++ */
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2M_ENABLE;
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * Indicate that we're in the stopped mode.
++ */
++ dma->pause = 1;
++ dma->xfer_enable = 0;
++ }
++
++ /*
++ * Make sure the interrupt was valid, and if it was, then check
++ * if a callback function was installed for this DMA channel. If a
++ * callback was installed call it.
++ */
++ if ((dma_int != UNDEF_INT) && dma->callback) {
++ dma->callback(dma_int, dma->device, dma->user_data);
++ }
++ return IRQ_HANDLED;
++}
++
++/*****************************************************************************
++ *
++ * dma_m2p_irq_handler
++ *
++ *
++ *
++ ****************************************************************************/
++static irqreturn_t
++dma_m2p_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++{
++ ep93xx_dma_t *dma = (ep93xx_dma_t *) dev_id;
++ unsigned int M2P_reg_base = dma->reg_base;
++ unsigned int read_back;
++ ep93xx_dma_dev_t dma_int = UNDEF_INT;
++ unsigned int loop, uiCONTROL, uiINTERRUPT;
++
++ /*
++ * Determine what kind of dma interrupt this is.
++ */
++ if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) &
++ INTERRUPT_M2P_STALLINT)
++ dma_int = STALL;
++ else if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) &
++ INTERRUPT_M2P_NFBINT)
++ dma_int = NFB;
++ else if (readl(M2P_reg_base + M2P_OFFSET_INTERRUPT) &
++ INTERRUPT_M2P_CHERRORINT)
++ dma_int = CHERROR;
++
++ /*
++ * Stall Interrupt: The Channel is stalled, meaning nothing is
++ * programmed to transfer right now. So, we're back to the
++ * beginnning. If there's a buffer to transfer, program it into
++ * max and base 0 registers.
++ */
++ if (dma_int == STALL) {
++ DPRINTK("1 ");
++
++ if (dma->total_buffers) {
++ /*
++ * The current_buffer has already been tranfered, so add the
++ * byte count to the total_bytes field.
++ */
++ dma->total_bytes = dma->total_bytes +
++ dma->buffer_queue[dma->current_buffer].size;
++
++ /*
++ * Mark the current_buffer as used.
++ */
++ dma->buffer_queue[dma->current_buffer].used = TRUE;
++
++ /*
++ * Increment the used buffer counter
++ */
++ dma->used_buffers++;
++
++ DPRINTK("#%d", dma->current_buffer);
++
++ /*
++ * Increment the current_buffer
++ */
++ dma->current_buffer = (dma->current_buffer + 1) %
++ MAX_EP93XX_DMA_BUFFERS;
++
++ /*
++ * check if there's a new buffer to transfer.
++ */
++ if (dma->new_buffers && dma->xfer_enable) {
++ /*
++ * We have a new buffer to transfer so program in the buffer
++ * values. Since a STALL interrupt was triggered, we
++ * program the base0 and maxcnt0
++ *
++ * Set the MAXCNT0 register with the buffer size
++ */
++ writel(dma->buffer_queue[dma->current_buffer].size,
++ M2P_reg_base + M2P_OFFSET_MAXCNT0);
++
++ /*
++ * Set the BASE0 register with the buffer base address
++ */
++ writel(dma->buffer_queue[dma->current_buffer].source,
++ M2P_reg_base + M2P_OFFSET_BASE0);
++
++ /*
++ * Decrement the new buffer counter
++ */
++ dma->new_buffers--;
++
++ if (dma->new_buffers) {
++ DPRINTK("A ");
++ /*
++ * Set the MAXCNT1 register with the buffer size
++ */
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ size,
++ M2P_reg_base + M2P_OFFSET_MAXCNT1);
++
++ /*
++ * Set the BASE1 register with the buffer base address
++ */
++ writel(dma->
++ buffer_queue[dma->
++ current_buffer +
++ 1 %
++ MAX_EP93XX_DMA_BUFFERS].
++ source,
++ M2P_reg_base + M2P_OFFSET_BASE1);
++
++ /*
++ * Decrement the new buffer counter
++ */
++ dma->new_buffers--;
++
++ /*
++ * Enable the NFB Interrupt.
++ */
++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++ uiCONTROL |= CONTROL_M2P_NFBINTEN;
++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++ }
++ }
++ /*
++ * No new buffers.
++ */
++ else {
++ DPRINTK("2 \n");
++ /*
++ * There's a chance we setup both buffer descriptors, but
++ * didn't service the NFB quickly enough, causing the channel
++ * to transfer both buffers, then enter the stall state.
++ * So, we need to be able to process the second buffer.
++ */
++ if ((dma->used_buffers + dma->new_buffers) <
++ dma->total_buffers) {
++ DPRINTK("3 ");
++
++ /*
++ * The current_buffer has already been tranfered, so add the
++ * byte count to the total_bytes field.
++ */
++ dma->total_bytes = dma->total_bytes +
++ dma->buffer_queue[dma->
++ current_buffer].
++ size;
++
++ /*
++ * Mark the current_buffer as used.
++ */
++ dma->buffer_queue[dma->current_buffer].
++ used = TRUE;
++
++ /*
++ * Increment the used buffer counter
++ */
++ dma->used_buffers++;
++
++ DPRINTK("#%d", dma->current_buffer);
++
++ /*
++ * Increment the current buffer pointer.
++ */
++ dma->current_buffer =
++ (dma->current_buffer +
++ 1) % MAX_EP93XX_DMA_BUFFERS;
++
++ }
++
++ /*
++ * No new buffers to transfer, so disable the channel.
++ */
++ /* go dma_regs->CONTROL.Field.ENABLE = 0; */
++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2P_ENABLE;
++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++ /*
++ * Indicate that this channel is in the pause by starvation
++ * state by setting the pause bit to true.
++ */
++ dma->pause = TRUE;
++
++ DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS));
++ DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL));
++ DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN));
++ DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC));
++ DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0));
++ DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0));
++ DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0));
++ DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1));
++ DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1));
++ DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
++
++ DPRINTK
++ ("Buffer buf_id source size last used \n");
++ for (loop = 0; loop < 32; loop++) {
++ DPRINTK
++ ("%d 0x%x 0x%x 0x%x %d %d \n",
++ loop,
++ dma->buffer_queue[loop].buf_id,
++ dma->buffer_queue[loop].source,
++ dma->buffer_queue[loop].size,
++ dma->buffer_queue[loop].last,
++ dma->buffer_queue[loop].used);
++ }
++ DPRINTK
++ ("pause 0x%x 0x%x 0x%x %d %d \n",
++ dma->pause_buf.buf_id,
++ dma->pause_buf.source, dma->pause_buf.size,
++ dma->pause_buf.last, dma->pause_buf.used);
++
++ DPRINTK("Pause - %d \n", dma->pause);
++ DPRINTK("xfer_enable - %d \n",
++ dma->xfer_enable);
++ DPRINTK("total bytes - 0x%x \n",
++ dma->total_bytes);
++ DPRINTK("total buffer - %d \n",
++ dma->total_buffers);
++ DPRINTK("new buffers - %d \n",
++ dma->new_buffers);
++ DPRINTK("current buffer - %d \n",
++ dma->current_buffer);
++ DPRINTK("last buffer - %d \n",
++ dma->last_buffer);
++ DPRINTK("used buffers - %d \n",
++ dma->used_buffers);
++ DPRINTK("callback addr - 0x%x \n",
++ dma->callback);
++ }
++ }
++ /*
++ * Total number of buffers in the queue is 0.
++ */
++ else {
++ /*
++ * No buffers to transfer, or old buffers to mark as used,
++ * so Disable the channel
++ */
++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2P_ENABLE;
++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++ /*
++ * Must read the control register back after a write.
++ */
++ read_back = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++
++ /*
++ * Indicate that this channel is in the pause by
++ * starvation state by setting the pause bit to true.
++ */
++ dma->pause = TRUE;
++ }
++ }
++ /*
++ * Next Frame Buffer Interrupt. If there's a new buffer program it
++ * Check if this is the last buffer in the transfer,
++ * and if it is, disable the NFB int to prevent being
++ * interrupted for another buffer when we know there won't be
++ * another.
++ */
++ if (dma_int == NFB) {
++ DPRINTK("5 ");
++
++ if (dma->total_buffers) {
++ DPRINTK("6 ");
++ /*
++ * The iCurrentBuffer has already been transfered. so add the
++ * byte count from the current buffer to the total byte count.
++ */
++ dma->total_bytes = dma->total_bytes +
++ dma->buffer_queue[dma->current_buffer].size;
++
++ /*
++ * Mark the Current Buffer as used.
++ */
++ dma->buffer_queue[dma->current_buffer].used = TRUE;
++
++ /*
++ * Increment the used buffer counter
++ */
++ dma->used_buffers++;
++
++ DPRINTK("#%d", dma->current_buffer);
++
++ if ((dma->buffer_queue[(dma->current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].last)
++ || (dma->new_buffers == 0)
++ || (dma->xfer_enable == FALSE)) {
++ DPRINTK("7 ");
++
++ /*
++ * This is the last Buffer in this transaction, so disable
++ * the NFB interrupt. We shouldn't get an NFB int when the
++ * FSM moves to the ON state where it would typically get the
++ * NFB int indicating a new buffer can be programmed.
++ * Instead, once in the ON state, the DMA will just proceed
++ * to complet the transfer of the current buffer, move the
++ * FSB directly to the STALL state where a STALL interrupt
++ * will be generated.
++ */
++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2P_NFBINTEN;
++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++ /*
++ * The current buffer has been transferred, so increment
++ * the current buffer counter to reflect this.
++ */
++ dma->current_buffer =
++ (dma->current_buffer +
++ 1) % MAX_EP93XX_DMA_BUFFERS;
++
++ DPRINTK("End of NFB handling. \n");
++ DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS));
++ DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL));
++ DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN));
++ DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC));
++ DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0));
++ DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0));
++ DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0));
++ DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1));
++ DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1));
++ DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
++
++ DPRINTK
++ ("Buffer buf_id source size last used \n");
++ for (loop = 0; loop < 32; loop++) {
++ DPRINTK
++ ("%d 0x%x 0x%x 0x%x %d %d \n",
++ loop,
++ dma->buffer_queue[loop].buf_id,
++ dma->buffer_queue[loop].source,
++ dma->buffer_queue[loop].size,
++ dma->buffer_queue[loop].last,
++ dma->buffer_queue[loop].used);
++ }
++ DPRINTK
++ ("pause 0x%x 0x%x 0x%x %d %d \n",
++ dma->pause_buf.buf_id,
++ dma->pause_buf.source, dma->pause_buf.size,
++ dma->pause_buf.last, dma->pause_buf.used);
++
++ DPRINTK("Pause - %d \n", dma->pause);
++ DPRINTK("xfer_enable - %d \n",
++ dma->xfer_enable);
++ DPRINTK("total bytes - 0x%x \n",
++ dma->total_bytes);
++ DPRINTK("total buffer - %d \n",
++ dma->total_buffers);
++ DPRINTK("new buffers - %d \n",
++ dma->new_buffers);
++ DPRINTK("current buffer - %d \n",
++ dma->current_buffer);
++ DPRINTK("last buffer - %d \n",
++ dma->last_buffer);
++ DPRINTK("used buffers - %d \n",
++ dma->used_buffers);
++ DPRINTK("callback addr - 0x%x \n",
++ dma->callback);
++
++ } else if (dma->new_buffers) {
++ DPRINTK("8 ");
++ /*
++ * we have a new buffer, so increment the current buffer to
++ * point to the next buffer, which is already programmed into
++ * the DMA. Next time around, it'll be pointing to the
++ * current buffer.
++ */
++ dma->current_buffer =
++ (dma->current_buffer +
++ 1) % MAX_EP93XX_DMA_BUFFERS;
++
++ /*
++ * we know we have a new buffer to program as the next
++ * buffer, so check which set of MAXCNT and BASE registers
++ * to program.
++ */
++ if (readl(M2P_reg_base + M2P_OFFSET_STATUS) &
++ STATUS_M2P_NEXTBUFFER) {
++ /*
++ * Set the MAXCNT1 register with the buffer size
++ */
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ size,
++ M2P_reg_base + M2P_OFFSET_MAXCNT1);
++
++ /*
++ * Set the BASE1 register with the buffer base address
++ */
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ source,
++ M2P_reg_base + M2P_OFFSET_BASE1);
++ } else {
++ /*
++ * Set the MAXCNT0 register with the buffer size
++ */
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ size,
++ M2P_reg_base + M2P_OFFSET_MAXCNT0);
++
++ /*
++ * Set the BASE0 register with the buffer base address
++ */
++ writel(dma->
++ buffer_queue[(dma->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].
++ source,
++ M2P_reg_base + M2P_OFFSET_BASE0);
++ }
++
++ /*
++ * Decrement the new buffers counter
++ */
++ dma->new_buffers--;
++ }
++ }
++ /*
++ * Total number of buffers is 0 - really we should never get here,
++ * but just in case.
++ */
++ else {
++ DPRINTK("9 \n");
++
++ /*
++ * No new buffers to transfer, so Disable the channel
++ */
++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2P_ENABLE;
++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++ }
++ }
++ /*
++ * Channel Error Interrupt, or perhipheral interrupt, specific to the
++ * memory to/from peripheral channels.
++ */
++ if (dma_int == CHERROR) {
++ /*
++ * just clear the interrupt, it's really up to the peripheral
++ * driver to determine if any further action is necessary.
++ */
++ uiINTERRUPT =
++ readl(M2P_reg_base + M2P_OFFSET_INTERRUPT);
++ uiINTERRUPT &= ~INTERRUPT_M2P_CHERRORINT;
++ writel(uiINTERRUPT, M2P_reg_base + M2P_OFFSET_INTERRUPT);
++ }
++
++ /*
++ * Make sure the interrupt was valid, and if it was, then check
++ * if a callback function was installed for this DMA channel. If a
++ * callback was installed call it.
++ */
++ if ((dma_int != UNDEF_INT) && dma->callback) {
++ dma->callback(dma_int, dma->device, dma->user_data);
++ }
++ return IRQ_HANDLED;
++}
++
++/*****************************************************************************
++ *
++ * ep9312_dma_open_m2p(int device)
++ *
++ * Description: This function will attempt to open a M2P/P2M DMA channel.
++ * If the open is successful, the channel number is returned,
++ * otherwise a negative number is returned.
++ *
++ * Parameters:
++ * device: device for which the dma channel is requested.
++ *
++ ****************************************************************************/
++static int dma_open_m2p(int device)
++{
++ int channel = -1;
++ unsigned int loop;
++ unsigned int M2P_reg_base;
++ unsigned int uiPWRCNT;
++
++ DPRINTK("DMA Open M2P with hw dev %d\n", device);
++
++ /*
++ * Lock the dma channel list.
++ */
++ spin_lock(&dma_list_lock);
++ DPRINTK("1\n");
++ /*
++ * Verify that the device requesting DMA isn't already using a DMA channel
++ */
++ if (device >= 10) {
++ loop = 1; /* Rx transfer requested */
++ } else {
++ loop = 0; /* Tx transfer requested */
++ }
++
++ for (; loop < 10; loop = loop + 2) {
++ /*
++ * Before checking for a matching device, check that the
++ * channel is in use, otherwise the device field is
++ * invalid.
++ */
++ if (dma_chan[loop].ref_count) {
++ if (device == dma_chan[loop].device) {
++ DPRINTK("DMA Open M2P - Error\n");
++ /*
++ * Fail.
++ */
++ return (-1);
++ }
++ }
++ }
++
++ /*
++ * Get a DMA channel instance for the given hardware device.
++ * If this is a TX look for even numbered channels, else look for
++ * odd numbered channels
++ */
++ if (device >= 10) {
++ loop = 1; /* Rx transfer requested */
++ } else {
++ loop = 0; /* Tx transfer requested */
++ }
++
++ for (; loop < 10; loop = loop + 2) {
++ if (!dma_chan[loop].ref_count) {
++ /*
++ * Capture the channel and increment the reference count.
++ */
++ channel = loop;
++ dma_chan[channel].ref_count++;
++ break;
++ }
++ }
++
++ /*
++ * Unlock the dma channel list.
++ */
++ spin_unlock(&dma_list_lock);
++
++ /*
++ * See if we got a valid channel.
++ */
++ if (channel < 0) {
++ /*
++ * Fail.
++ */
++ return (-1);
++ }
++
++ /*
++ * Point regs to the correct dma channel register base.
++ */
++ M2P_reg_base = dma_chan[channel].reg_base;
++
++ /*
++ * Turn on the clock for the specified DMA channel
++ * TODO: need to use the correct register name for the
++ * power control register.
++ */
++ uiPWRCNT = readl(SYSCON_PWRCNT);
++ switch (channel) {
++ case 0:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH0;
++ break;
++ }
++
++ case 1:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH1;
++ break;
++ }
++
++ case 2:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH2;
++ break;
++ }
++
++ case 3:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH3;
++ break;
++ }
++
++ case 4:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH4;
++ break;
++ }
++
++ case 5:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH5;
++ break;
++ }
++
++ case 6:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH6;
++ break;
++ }
++
++ case 7:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH7;
++ break;
++ }
++ case 8:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH8;
++ break;
++ }
++ case 9:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2PCH9;
++ break;
++ }
++
++ default:
++ {
++ return (-1);
++ }
++ }
++ writel(uiPWRCNT, SYSCON_PWRCNT);
++
++ /*
++ * Clear out the control register before any further setup.
++ */
++ writel(0, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++ /*
++ * Setup the peripheral port value in the DMA channel registers.
++ */
++ if (device < 10) {
++ writel((unsigned int)device,
++ M2P_reg_base + M2P_OFFSET_PPALLOC);
++ } else {
++ writel((unsigned int)(device - 10),
++ M2P_reg_base + M2P_OFFSET_PPALLOC);
++ }
++
++ /*
++ * Let's hold on to the value of the Hw device for comparison later.
++ */
++ dma_chan[channel].device = device;
++
++ /*
++ * Success.
++ */
++ return (channel);
++}
++
++/*****************************************************************************
++ *
++ * dma_open_m2m(int device)
++ *
++ * Description: This function will attempt to open a M2M DMA channel.
++ * If the open is successful, the channel number is returned,
++ * otherwise a negative number is returned.
++ *
++ * Parameters:
++ * device: device for which the dma channel is requested.
++ *
++ ****************************************************************************/
++static int dma_open_m2m(int device)
++{
++ int channel = -1;
++ unsigned int loop;
++ unsigned int M2M_reg_base;
++ unsigned int uiPWRCNT, uiCONTROL;
++
++ DPRINTK("DMA Open M2M with hw dev %d\n", device);
++
++ /*
++ * Lock the dma channel list.
++ */
++ spin_lock(&dma_list_lock);
++ DPRINTK("1\n");
++
++ /*
++ * Check if this device is already allocated a channel.
++ * TODO: can one M2M device be allocated multiple channels?
++ */
++ for (loop = DMA_MEMORY; loop < UNDEF; loop++) {
++ /*
++ * Before checking for a matching device, check that the
++ * channel is in use, otherwise the device field is
++ * invalid.
++ */
++ if (dma_chan[loop].ref_count) {
++ if (device == dma_chan[loop].device) {
++ DPRINTK
++ ("Error - dma_open_m2m - already allocated channel\n");
++
++ /*
++ * Unlock the dma channel list.
++ */
++ spin_unlock(&dma_list_lock);
++
++ /*
++ * Fail.
++ */
++ return (-1);
++ }
++ }
++ }
++
++ /*
++ * Get a DMA channel instance for the given hardware device.
++ */
++ for (loop = 10; loop < 12; loop++) {
++ if (!dma_chan[loop].ref_count) {
++ /*
++ * Capture the channel and increment the reference count.
++ */
++ channel = loop;
++ dma_chan[channel].ref_count++;
++ break;
++ }
++ }
++
++ /*
++ * Unlock the dma channel list.
++ */
++ spin_unlock(&dma_list_lock);
++
++ /*
++ * See if we got a valid channel.
++ */
++ if (channel < 0) {
++ /*
++ * Fail.
++ */
++ return (-1);
++ }
++
++ /*
++ * Point regs to the correct dma channel register base.
++ */
++ M2M_reg_base = dma_chan[channel].reg_base;
++
++ /*
++ * Turn on the clock for the specified DMA channel
++ * TODO: need to use the correct register name for the
++ * power control register.
++ */
++ uiPWRCNT = readl(SYSCON_PWRCNT);
++ switch (channel) {
++ case 10:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH0;
++ break;
++ }
++
++ case 11:
++ {
++ uiPWRCNT |= SYSCON_PWRCNT_DMA_M2MCH1;
++ break;
++ }
++
++ default:
++ {
++ return (-1);
++ }
++ }
++ writel(uiPWRCNT, SYSCON_PWRCNT);
++
++ DPRINTK("DMA Open - power control: 0x%x \n",
++ readl(SYSCON_PWRCNT));
++
++ /*
++ * Clear out the control register before any further setup.
++ */
++ writel(0, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * Setup the transfer mode and the request source selection within
++ * the DMA M2M channel registers.
++ */
++ switch (device) {
++ case DMA_MEMORY:
++ {
++ /*
++ * Clear TM field, set RSS field to 0
++ */
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &=
++ ~(CONTROL_M2M_TM_MASK | CONTROL_M2M_RSS_MASK);
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ break;
++ }
++
++ case DMA_IDE:
++ {
++ /*
++ * Set RSS field to 3, Set NO_HDSK, Set PW field to 1
++ */
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &=
++ ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_PW_MASK);
++ uiCONTROL |=
++ (3 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK |
++ (2 << CONTROL_M2M_PW_SHIFT);
++
++ uiCONTROL &= ~(CONTROL_M2M_ETDP_MASK);
++ uiCONTROL &= ~(CONTROL_M2M_DACKP);
++ uiCONTROL &= ~(CONTROL_M2M_DREQP_MASK);
++
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ break;
++ }
++
++ case DMARx_SSP:
++ {
++ /*
++ * Set RSS field to 1, Set NO_HDSK, Set TM field to 2
++ */
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &=
++ ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
++ uiCONTROL |=
++ (1 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK |
++ (2 << CONTROL_M2M_TM_SHIFT);
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ break;
++ }
++
++ case DMATx_SSP:
++ {
++ /*
++ * Set RSS field to 2, Set NO_HDSK, Set TM field to 1
++ */
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &=
++ ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
++ uiCONTROL |=
++ (2 << CONTROL_M2M_RSS_SHIFT) | CONTROL_M2M_NO_HDSK |
++ (1 << CONTROL_M2M_TM_SHIFT);
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ break;
++ }
++
++ case DMATx_EXT_DREQ:
++ {
++ /*
++ * Set TM field to 2, set RSS field to 0
++ */
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &=
++ ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
++ uiCONTROL |= 1 << CONTROL_M2M_TM_SHIFT;
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ break;
++ }
++
++ case DMARx_EXT_DREQ:
++ {
++
++ /*
++ * Set TM field to 2, set RSS field to 0
++ */
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &=
++ ~(CONTROL_M2M_RSS_MASK | CONTROL_M2M_TM_MASK);
++ uiCONTROL |= 2 << CONTROL_M2M_TM_SHIFT;
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ break;
++ }
++
++ default:
++ {
++ return -1;
++ }
++ }
++
++ /*
++ * Let's hold on to the value of the Hw device for comparison later.
++ */
++ dma_chan[channel].device = device;
++
++ /*
++ * Success.
++ */
++ return (channel);
++}
++
++/*****************************************************************************
++ *
++ * int dma_config_m2m(ep93xx_dma_t * dma, unsigned int flags_m2m,
++ * dma_callback callback, unsigned int user_data)
++ *
++ * Description: Configure the DMA channel and install a callback function.
++ * This function will have to be called for every transfer
++ *
++ * dma: Pointer to the dma instance data for the M2M channel to
++ * configure.
++ * flags_m2m Flags used to configure an M2M dma channel and determine
++ * if a callback function and user_data information are included
++ * in this call.
++ * callback function pointer which is called near the end of the
++ * dma channel's irq handler.
++ * user_data defined by the calling driver.
++ *
++ ****************************************************************************/
++static int
++dma_config_m2m(ep93xx_dma_t * dma, unsigned int flags_m2m,
++ dma_callback callback, unsigned int user_data)
++{
++ unsigned long flags;
++ unsigned int M2M_reg_base, uiCONTROL;
++
++ /*
++ * Make sure the channel is disabled before configuring the channel.
++ *
++ * TODO: Is this correct?? Making a big change here...
++ */
++ /* if(!dma->pause || (!dma->pause && dma->xfer_enable)) */
++ if (dma->xfer_enable) {
++ /*
++ * DMA channel is not paused, so we can't configure it.
++ */
++ DPRINTK("DMA channel not paused, so can't configure! \n");
++ return (-1);
++ }
++
++ /*
++ * Mask interrupts.
++ */
++ local_irq_save(flags);
++
++ /*
++ * Setup a pointer into the dma channel's register set.
++ */
++ M2M_reg_base = dma->reg_base;
++
++ /*
++ * By default we enable the stall interrupt.
++ */
++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL |= CONTROL_M2M_STALLINTEN;
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * By default we enable the done interrupt.
++ */
++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2M_DONEINTEN;
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * Set up the transfer control fields based on values passed in
++ * the flags_m2m field.
++ */
++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ if (flags_m2m & DESTINATION_HOLD) {
++ uiCONTROL |= CONTROL_M2M_DAH;
++ } else {
++ uiCONTROL &= ~CONTROL_M2M_DAH;
++ }
++
++ if (flags_m2m & SOURCE_HOLD) {
++ uiCONTROL |= CONTROL_M2M_SAH;
++ } else {
++ uiCONTROL &= ~CONTROL_M2M_SAH;
++ }
++
++ uiCONTROL &= ~CONTROL_M2M_TM_MASK;
++ uiCONTROL |=
++ (((flags_m2m & TRANSFER_MODE_MASK) >> TRANSFER_MODE_SHIFT) <<
++ CONTROL_M2M_TM_SHIFT) & CONTROL_M2M_TM_MASK;
++
++ uiCONTROL &= ~CONTROL_M2M_PWSC_MASK;
++ uiCONTROL |= (((flags_m2m & WAIT_STATES_MASK) >> WAIT_STATES_SHIFT) <<
++ CONTROL_M2M_PWSC_SHIFT) & CONTROL_M2M_PWSC_MASK;
++
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * Save the callback function in the dma instance for this channel.
++ */
++ dma->callback = callback;
++
++ /*
++ * Save the user data in the the dma instance for this channel.
++ */
++ dma->user_data = user_data;
++
++ /*
++ * Put the dma instance into the pause state by setting the
++ * pause bit to true.
++ */
++ dma->pause = TRUE;
++
++ local_irq_restore(flags);
++
++ /*
++ * Success.
++ */
++ return (0);
++}
++
++/*****************************************************************************
++ *
++ * int dma_start(int handle, unsigned int channels, unsigned int * handles)
++ *
++ * Description: Initiate a transfer on up to 3 channels.
++ *
++ * handle: handle for the channel to initiate transfer on.
++ * channels: number of channels to initiate transfers on.
++ * handles: pointer to an array of handles, one for each channel which
++ * is to be started.
++ *
++ ****************************************************************************/
++static int dma_start_m2m(int channel, ep93xx_dma_t * dma)
++{
++ unsigned long flags;
++ unsigned int M2M_reg_base = dma->reg_base;
++ unsigned int uiCONTROL;
++
++ /*
++ * Mask interrupts while we get this started.
++ */
++ local_irq_save(flags);
++
++ /*
++ * Make sure the channel has at least one buffer in the queue.
++ */
++ if (dma->new_buffers < 1) {
++ /*
++ * Unmask irqs
++ */
++ local_irq_restore(flags);
++
++ DPRINTK("DMA Start: Channel starved.\n");
++
++ /*
++ * This channel does not have enough buffers queued up,
++ * so enter the pause by starvation state.
++ */
++ dma->xfer_enable = TRUE;
++ dma->pause = TRUE;
++
++ /*
++ * Success.
++ */
++ return (0);
++ }
++
++ /*
++ * Clear any pending interrupts.
++ */
++ writel(0x0, M2M_reg_base + M2M_OFFSET_INTERRUPT);
++
++ /*
++ * Set up one or both buffer descriptors with values from the next one or
++ * two buffers in the queue. By default enable the next frame buffer
++ * interrupt on the channel.
++ */
++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2M_NFBINTEN;
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * enable the stall interrupt.
++ */
++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL |= CONTROL_M2M_STALLINTEN;
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * Update the dma channel instance transfer state.
++ */
++ dma->xfer_enable = TRUE;
++ dma->pause = FALSE;
++
++ /*
++ * Decrement the new buffers counter.
++ */
++ dma->new_buffers--;
++
++ /*
++ * Program up the first buffer descriptor with a source and destination
++ * and a byte count.
++ */
++ writel(dma->buffer_queue[dma->current_buffer].source,
++ M2M_reg_base + M2M_OFFSET_SAR_BASE0);
++
++ writel(dma->buffer_queue[dma->current_buffer].dest,
++ M2M_reg_base + M2M_OFFSET_DAR_BASE0);
++
++ writel(dma->buffer_queue[dma->current_buffer].size,
++ M2M_reg_base + M2M_OFFSET_BCR0);
++
++ /*
++ * Now we enable the channel. This initiates the transfer.
++ */
++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL |= CONTROL_M2M_ENABLE;
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++
++ /*
++ * Before restoring irqs set up the second buffer descriptor
++ * with a second buffer if we have a second buffer.
++ */
++ /* if(dma->new_buffers)
++ {
++ outl( dma->buffer_queue[(dma->current_buffer + 1) %
++ MAX_EP93XX_DMA_BUFFERS].source,
++ M2M_reg_base+M2M_OFFSET_SAR_BASE1 );
++
++ outl( dma->buffer_queue[(dma->current_buffer + 1) %
++ MAX_EP93XX_DMA_BUFFERS].dest,
++ M2M_reg_base+M2M_OFFSET_DAR_BASE1 );
++
++ outl( dma->buffer_queue[(dma->current_buffer + 1) %
++ MAX_EP93XX_DMA_BUFFERS].size,
++ M2M_reg_base+M2M_OFFSET_BCR1 );
++ } */
++
++ /*
++ * If this is a memory to memory transfer, we need to s/w trigger the
++ * transfer by setting the start bit within the control register.
++ */
++ if (dma->device == DMA_MEMORY) {
++ uiCONTROL =
++ readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL |= CONTROL_M2M_START;
++ writel(uiCONTROL,
++ M2M_reg_base + M2M_OFFSET_CONTROL);
++ }
++
++ DPRINTK("DMA - It's been started!!");
++ DPRINTK("STATUS - 0x%x \n", readl(M2M_reg_base + M2M_OFFSET_STATUS));
++ DPRINTK("CONTROL - 0x%x \n", readl(M2M_reg_base + M2M_CONTROL.Value));
++ DPRINTK("REMAIN - 0x%x \n", readl(M2M_reg_base + M2M_REMAIN.Value));
++ DPRINTK("PPALLOC - 0x%x \n", readl(M2M_reg_base + M2M_PPALLOC.Value));
++ DPRINTK("BASE0 - 0x%x \n", readl(M2M_reg_base + M2M_BASE0.Value));
++ DPRINTK("MAXCNT0 - 0x%x \n", readl(M2M_reg_base + M2M_MAXCNT0.Value));
++ DPRINTK("CURRENT0 - 0x%x \n", readl(M2M_reg_base + M2M_CURRENT0.Value));
++ DPRINTK("BASE1 - 0x%x \n", readl(M2M_reg_base + M2M_BASE1.Value));
++ DPRINTK("MAXCNT1 - 0x%x \n", readl(M2M_reg_base + M2M_MAXCNT1.Value));
++ DPRINTK("CURRENT1 - 0x%x \n", readl(M2M_reg_base + M2M_CURRENT1.Value));
++
++ DPRINTK("Pause - %d \n", dma_pointers[0]->pause);
++ DPRINTK("xfer_enable - %d \n", dma_pointers[0]->xfer_enable);
++ DPRINTK("total bytes - 0x%x \n", dma_pointers[0]->total_bytes);
++ DPRINTK("total buffer - %d \n", dma_pointers[0]->total_buffers);
++ DPRINTK("new buffers - %d \n", dma_pointers[0]->new_buffers);
++ DPRINTK("current buffer - %d \n", dma_pointers[0]->current_buffer);
++ DPRINTK("last buffer - %d \n", dma_pointers[0]->last_buffer);
++ DPRINTK("used buffers - %d \n", dma_pointers[0]->used_buffers);
++
++ /*
++ * Unmask irqs
++ */
++ local_irq_restore(flags);
++
++ /*
++ * Success.
++ */
++ return (0);
++}
++
++/*****************************************************************************
++ *
++ * DMA interface functions
++ *
++ ****************************************************************************/
++
++/*****************************************************************************
++ *
++ * int dma_init(int handle, unsigned int flags_m2p, unsigned int flags_m2m,
++ * dma_callback callback, unsigned int user_data)
++ *
++ * Description: Configure the DMA channel and install a callback function.
++ *
++ * handle: Handle unique the each instance of the dma interface, used
++ * to verify this call.
++ * flags_m2p Flags used to configure an M2P/P2M dma channel and determine
++ * if a callback function and user_data information are included
++ * in this call. This field should be NULL if handle represents
++ * an M2M channel.
++ * flags_m2m Flags used to configure an M2M dma channel and determine
++ * if a callback function and user_data information are included
++ * in this call. This field should be NULL if handle represents
++ * an M2P/P2M channel.
++ * callback function pointer which is called near the end of the
++ * dma channel's irq handler.
++ * user_data defined by the calling driver.
++ *
++ ****************************************************************************/
++int
++ep93xx_dma_config(int handle, unsigned int flags_m2p, unsigned int flags_m2m,
++ dma_callback callback, unsigned int user_data)
++{
++ int channel;
++ ep93xx_dma_t *dma;
++ unsigned long flags;
++ unsigned int M2P_reg_base, uiCONTROL;
++
++ /*
++ * Get the DMA hw channel # from the handle.
++ */
++ channel = dma_get_channel_from_handle(handle);
++
++ /*
++ * See if this is a valid handle.
++ */
++ if (channel < 0) {
++ printk(KERN_ERR "DMA Config: Invalid dma handle.\n");
++
++ /*
++ * Fail.
++ */
++ return (-EINVAL);
++ }
++
++ DPRINTK("DMA Config \n");
++
++ dma = &dma_chan[channel];
++
++ local_irq_save(flags);
++
++ /*
++ * Check if the channel is currently transferring.
++ */
++ if (dma->xfer_enable) {
++ local_irq_restore(flags);
++
++ /*
++ * Already transferring, invalid command.
++ */
++ return (-EINVAL);
++ }
++
++ /*
++ * Check if this is an m2m function.
++ */
++ if (channel >= 10) {
++ local_irq_restore(flags);
++
++ /*
++ * Call another function to handle m2m config.
++ */
++ return (dma_config_m2m(dma, flags_m2m, callback, user_data));
++ }
++
++ /*
++ * Setup a pointer into the dma channel's register set.
++ */
++ M2P_reg_base = dma->reg_base;
++
++ /*
++ * By default we enable the stall interrupt.
++ */
++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++ uiCONTROL |= CONTROL_M2P_STALLINTEN;
++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++ /*
++ * Configure the channel for an error from the peripheral.
++ */
++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++ if (flags_m2p && CHANNEL_ERROR_INT_ENABLE)
++ uiCONTROL |= CONTROL_M2P_CHERRORINTEN;
++ else
++ uiCONTROL &= ~CONTROL_M2P_CHERRORINTEN;
++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++ if (flags_m2p && EP93XX_DMA_ABORT)
++ uiCONTROL |= CONTROL_M2P_ABRT;
++ else
++ uiCONTROL &= ~CONTROL_M2P_ABRT;
++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++ if (flags_m2p && IGNORE_CHANNEL_ERROR)
++ uiCONTROL |= CONTROL_M2P_ICE;
++ else
++ uiCONTROL &= ~CONTROL_M2P_ICE;
++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++
++ /*
++ * Save the callback function in the dma instance for this channel.
++ */
++ dma->callback = callback;
++
++ /*
++ * Save the user data in the the dma instance for this channel.
++ */
++ dma->user_data = user_data;
++
++ /*
++ * Put the dma instance into the pause state by setting the
++ * pause bit to true.
++ */
++ dma->pause = TRUE;
++
++ local_irq_restore(flags);
++
++ /*
++ * Success.
++ */
++ return (0);
++}
++
++/*****************************************************************************
++ *
++ * int dma_start(int handle, unsigned int channels, unsigned int * handles)
++ *
++ * Description: Initiate a transfer on up to 3 channels.
++ *
++ * handle: handle for the channel to initiate transfer on.
++ * channels: number of channels to initiate transfers on.
++ * handles: pointer to an array of handles, one for each channel which
++ * is to be started.
++ *
++ ****************************************************************************/
++int ep93xx_dma_start(int handle, unsigned int channels, unsigned int *handles)
++{
++ ep93xx_dma_t *dma_pointers[3];
++ unsigned int M2P_reg_bases[3];
++ unsigned int loop, uiCONTROL;
++ unsigned long flags;
++ int channel;
++
++ /*
++ * Get the DMA hw channel # from the handle.
++ */
++ channel = dma_get_channel_from_handle(handle);
++
++ /*
++ * See if this is a valid handle.
++ */
++ if (channel < 0) {
++ printk(KERN_ERR "DMA Start: Invalid dma handle.\n");
++
++ /*
++ * Fail.
++ */
++ return (-EINVAL);
++ }
++
++ if (channels < 1) {
++ printk(KERN_ERR "DMA Start: Invalid parameter.\n");
++
++ return (-EINVAL);
++ }
++
++ DPRINTK("DMA Start \n");
++
++ /*
++ * Mask off registers.
++ */
++ local_irq_save(flags);
++
++ /*
++ * Check if this is a start multiple.
++ */
++ if (channels > 1) {
++ DPRINTK
++ ("DMA ERROR: Start, multiple start not supported yet \n");
++ return (-1);
++ }
++ /*
++ * Only one channel
++ */
++ else {
++ /*
++ * Check if this channel is already transferring.
++ */
++ if (dma_chan[channel].xfer_enable && !dma_chan[channel].pause) {
++ printk(KERN_ERR
++ "DMA Start: Invalid command for channel %d.\n",
++ channel);
++ DPRINTK("DMA Start: Invalid command for channel %d.\n",
++ channel);
++
++ /*
++ * Unmask irqs
++ */
++ local_irq_restore(flags);
++
++ /*
++ * This channel is already transferring, so return an error.
++ */
++ return (-EINVAL);
++ }
++
++ /*
++ * If this is an M2M channel, call a different function.
++ */
++ if (channel >= 10) {
++ /*
++ * Unmask irqs
++ */
++ local_irq_restore(flags);
++
++ /*
++ * Call the m2m start function. Only start one channel.
++ */
++ return (dma_start_m2m(channel, &dma_chan[channel]));
++ }
++
++ /*
++ * Make sure the channel has at least one buffer in the queue.
++ */
++ if (dma_chan[channel].new_buffers < 1) {
++ DPRINTK("DMA Start: Channel starved.\n");
++
++ /*
++ * This channel does not have enough buffers queued up,
++ * so enter the pause by starvation state.
++ */
++ dma_chan[channel].xfer_enable = TRUE;
++ dma_chan[channel].pause = TRUE;
++
++ /*
++ * Unmask irqs
++ */
++ local_irq_restore(flags);
++
++ /*
++ * Success.
++ */
++ return (0);
++ }
++
++ /*
++ * Set up a dma instance pointer for this dma channel.
++ */
++ dma_pointers[0] = &dma_chan[channel];
++
++ /*
++ * Set up a pointer to the register set for this channel.
++ */
++ M2P_reg_bases[0] = dma_pointers[0]->reg_base;
++ }
++
++ /*
++ * Setup both MAXCNT registers with values from the next two buffers
++ * in the queue, and enable the next frame buffer interrupt on the channel.
++ */
++ for (loop = 0; loop < channels; loop++) {
++ /*
++ * By default we enable the next frame buffer interrupt.
++ */
++ uiCONTROL = readl(M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
++ uiCONTROL |= CONTROL_M2P_NFBINTEN;
++ writel(uiCONTROL, M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
++
++ /*
++ * Check if we need to restore a paused transfer.
++ */
++ if (dma_pointers[loop]->pause_buf.buf_id != -1) {
++ writel(dma_pointers[loop]->pause_buf.size,
++ M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT0);
++ } else {
++ writel(dma_pointers[loop]->
++ buffer_queue[dma_pointers[loop]->current_buffer].
++ size,
++ M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT0);
++ }
++ }
++
++ for (loop = 0; loop < channels; loop++) {
++ /*
++ * Enable the specified dma channels.
++ */
++ uiCONTROL =
++ readl(M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
++ uiCONTROL |= CONTROL_M2P_ENABLE;
++ writel(uiCONTROL,
++ M2P_reg_bases[loop] + M2P_OFFSET_CONTROL);
++
++ /*
++ * Update the dma channel instance transfer state.
++ */
++ dma_pointers[loop]->xfer_enable = TRUE;
++ dma_pointers[loop]->pause = FALSE;
++
++ if (dma_pointers[loop]->pause_buf.buf_id == -1) {
++ dma_pointers[loop]->new_buffers--;
++ }
++ }
++
++ /*
++ * Program up the BASE0 registers for all specified channels, this
++ * will initiate transfers on all specified channels.
++ */
++ for (loop = 0; loop < channels; loop++) {
++ /*
++ * Check if we need to restore a paused transfer.
++ */
++ if (dma_pointers[loop]->pause_buf.buf_id != -1) {
++ writel(dma_pointers[loop]->pause_buf.source,
++ M2P_reg_bases[loop] + M2P_OFFSET_BASE0);
++
++ /*
++ * Set the pause buffer to NULL
++ */
++ dma_pointers[loop]->pause_buf.buf_id = -1;
++ dma_pointers[loop]->pause_buf.size = 0;
++ } else {
++ writel(dma_pointers[loop]->
++ buffer_queue[dma_pointers[loop]->current_buffer].
++ source,
++ M2P_reg_bases[loop] + M2P_OFFSET_BASE0);
++ }
++ }
++
++ /*
++ * Before restoring irqs setup the second MAXCNT/BASE
++ * register with a second buffer.
++ */
++ for (loop = 0; loop < channels; loop++) {
++ if (dma_pointers[loop]->new_buffers) {
++ writel(dma_pointers[loop]->
++ buffer_queue[(dma_pointers[loop]->
++ current_buffer +
++ 1) % MAX_EP93XX_DMA_BUFFERS].size,
++ M2P_reg_bases[loop] + M2P_OFFSET_MAXCNT1);
++ writel(dma_pointers[loop]->
++ buffer_queue[(dma_pointers[loop]->
++ current_buffer +
++ 1) %
++ MAX_EP93XX_DMA_BUFFERS].source,
++ M2P_reg_bases[loop] + M2P_OFFSET_BASE1);
++ }
++ }
++
++/*
++ DPRINTK("DMA - It's been started!!");
++ DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_STATUS)));
++ DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_CONTROL)));
++ DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_REMAIN)));
++ DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_PPALLOC)));
++ DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_BASE0)));
++ DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_MAXCNT0)));
++ DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_CURRENT0)));
++ DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_BASE1)));
++ DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_MAXCNT1)));
++ DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base+M2P_OFFSET_CURRENT1)));
++
++ DPRINTK("Pause - %d \n", dma_pointers[0]->pause);
++ DPRINTK("xfer_enable - %d \n", dma_pointers[0]->xfer_enable);
++ DPRINTK("total bytes - 0x%x \n", dma_pointers[0]->total_bytes);
++ DPRINTK("total buffer - %d \n", dma_pointers[0]->total_buffers);
++ DPRINTK("new buffers - %d \n", dma_pointers[0]->new_buffers);
++ DPRINTK("current buffer - %d \n", dma_pointers[0]->current_buffer);
++ DPRINTK("last buffer - %d \n", dma_pointers[0]->last_buffer);
++ DPRINTK("used buffers - %d \n", dma_pointers[0]->used_buffers);
++*/
++ /*
++ * Unmask irqs
++ */
++ local_irq_restore(flags);
++
++ /*
++ * Success.
++ */
++ return (0);
++}
++
++/*****************************************************************************
++ *
++ * int ep93xx_dma_add_buffer(int handle, unsigned int * address,
++ * unsigned int size, unsigned int last)
++ *
++ * Description: Add a buffer entry to the DMA buffer queue.
++ *
++ * handle: handle for the channel to add this buffer to.
++ * address: Pointer to an integer which is the start address of the
++ * buffer which is to be added to the queue.
++ * size: size of the buffer in bytes.
++ * last: 1 if this is the last buffer in this stream, 0 otherwise.
++ *
++ ****************************************************************************/
++int
++ep93xx_dma_add_buffer(int handle, unsigned int source, unsigned int dest,
++ unsigned int size, unsigned int last, unsigned int buf_id)
++{
++ unsigned long flags;
++ ep93xx_dma_t *dma;
++ int channel;
++
++ /*
++ * Get the DMA hw channel # from the handle.
++ */
++ channel = dma_get_channel_from_handle(handle);
++
++ /*
++ * See if this is a valid handle.
++ */
++ if (channel < 0) {
++ printk(KERN_ERR "DMA Add Buffer: Invalid dma handle.\n");
++
++ /*
++ * Fail.
++ */
++ return (-EINVAL);
++ }
++
++ /*
++ * Get a pointer to the dma instance.
++ */
++ dma = &dma_chan[channel];
++
++ /*
++ * Mask interrupts and hold on to the original state.
++ */
++ local_irq_save(flags);
++
++ /*
++ * If the buffer queue is full, last_buffer is the same as current_buffer and
++ * we're not tranfering, or last_buffer is pointing to a used buffer, then exit.
++ * TODO: do I need to do any more checks?
++ */
++ if (dma->total_buffers >= MAX_EP93XX_DMA_BUFFERS) {
++ /*
++ * Restore the state of the irqs
++ */
++ local_irq_restore(flags);
++
++ /*
++ * Fail.
++ */
++ return (-1);
++ }
++
++ /*
++ * Add this buffer to the queue
++ */
++ dma->buffer_queue[dma->last_buffer].source = source;
++ dma->buffer_queue[dma->last_buffer].dest = dest;
++ dma->buffer_queue[dma->last_buffer].size = size;
++ dma->buffer_queue[dma->last_buffer].last = last;
++ dma->buffer_queue[dma->last_buffer].buf_id = buf_id;
++
++ /*
++ * Reset the used field of the buffer structure.
++ */
++ dma->buffer_queue[dma->last_buffer].used = FALSE;
++
++ /*
++ * Increment the End Item Pointer.
++ */
++ dma->last_buffer = (dma->last_buffer + 1) % MAX_EP93XX_DMA_BUFFERS;
++
++ /*
++ * Increment the new buffers counter and the total buffers counter
++ */
++ dma->new_buffers++;
++ dma->total_buffers++;
++
++ /*
++ * restore the interrupt state.
++ */
++ local_irq_restore(flags);
++
++ /*
++ * Check if the channel was starved into a stopped state.
++ */
++ if (dma->pause && dma->xfer_enable) {
++ if (dma->new_buffers >= 1) {
++ DPRINTK
++ ("DMA - calling start from add after starve. \n");
++
++ /*
++ * The channel was starved into a stopped state, and we've got
++ * 2 new buffers, so start tranferring again.
++ */
++ ep93xx_dma_start(handle, 1, NULL);
++ }
++ }
++
++ /*
++ * Success.
++ */
++ return (0);
++}
++
++/*****************************************************************************
++ *
++ * int ep93xx_dma_remove_buffer(int handle, unsigned int * address,
++ * unsigned int * size)
++ *
++ * Description: Remove a buffer entry from the DMA buffer queue. If
++ * buffer was removed successfully, return 0, otherwise
++ * return -1.
++ *
++ * handle: handle for the channel to remove a buffer from.
++ * address: Pointer to an integer which is filled in with the start
++ * address of the removed buffer.
++ * size: Pointer to an integer which is filled in with the size in
++ * bytes of the removed buffer.
++ *
++ ****************************************************************************/
++int ep93xx_dma_remove_buffer(int handle, unsigned int *buf_id)
++{
++ unsigned int test;
++ unsigned int loop;
++ int return_val = -1;
++ unsigned long flags;
++ ep93xx_dma_t *dma;
++ int channel;
++
++ /*
++ * Get the DMA hw channel # from the handle.
++ */
++ channel = dma_get_channel_from_handle(handle);
++
++ /*
++ * See if this is a valid handle.
++ */
++ if (channel < 0) {
++ printk(KERN_ERR "DMA Remove Buffer: Invalid dma handle.\n");
++
++ /*
++ * Fail.
++ */
++ return (-EINVAL);
++ }
++
++ dma = &dma_chan[channel];
++
++ /*
++ * Mask interrupts and hold on to the original state.
++ */
++ local_irq_save(flags);
++
++ /*
++ * Make sure there are used buffers to be returned.
++ */
++ if (dma->used_buffers) {
++ test = dma->last_buffer;
++
++ for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) {
++ if (dma->buffer_queue[test].used
++ && (dma->buffer_queue[test].buf_id != -1)) {
++ /*DPRINTK("buffer %d used \n", test); */
++
++ /*
++ * This is a used buffer, fill in the buf_id pointer
++ * with the buf_id for this buffer.
++ */
++ *buf_id = dma->buffer_queue[test].buf_id;
++
++ /*
++ * Reset this buffer structure
++ */
++ dma->buffer_queue[test].buf_id = -1;
++
++ /*
++ * Decrement the used buffer counter, and the total buffer counter.
++ */
++ dma->used_buffers--;
++ dma->total_buffers--;
++
++ /*
++ * Successful removal of a buffer, so set the return
++ * value to 0, then exit this loop.
++ */
++ return_val = 0;
++ break;
++ }
++
++ /*
++ * This buffer isn't used, let's see if the next one is.
++ */
++ test = (test + 1) % MAX_EP93XX_DMA_BUFFERS;
++ }
++ }
++
++ /*
++ * Restore interrupts.
++ */
++ local_irq_restore(flags);
++
++ /*
++ * Success.
++ */
++ return (return_val);
++}
++
++/*****************************************************************************
++ *
++ * int ep93xx_dma_pause(int handle, unsigned int channels,
++ * unsigned int * handles)
++ *
++ * Description: Disable any ongoing transfer for the given channel, retaining
++ * the state of the current buffer transaction so that upon
++ * resume, the dma will continue where it left off.
++ *
++ * handle: Handle for the channel to be paused. If this is a pause for
++ * for multiple channels, handle is a valid handle for one of
++ * the channels to be paused.
++ * channels: number of channel to pause transfers on.
++ * handles: Pointer to an array of handles, one for each channel which
++ * to be paused. If this pause is intended only for one
++ * channel, this field should be set to NULL.
++ *
++ ****************************************************************************/
++int ep93xx_dma_pause(int handle, unsigned int channels, unsigned int *handles)
++{
++ unsigned long flags;
++ ep93xx_dma_t *dma;
++ int channel;
++ unsigned int M2M_reg_base, M2P_reg_base;
++
++ DPRINTK("ep93xx_dma_pause \n");
++
++ /*
++ * Mask interrupts and hold on to the original state.
++ */
++ local_irq_save(flags);
++
++ /*
++ * Get the DMA hw channel # from the handle.
++ */
++ channel = dma_get_channel_from_handle(handle);
++
++ /*
++ * See if this is a valid handle.
++ */
++ if (channel < 0) {
++ /*
++ * restore interrupts.
++ */
++ local_irq_restore(flags);
++
++ printk(KERN_ERR "DMA Pause: Invalid dma handle.\n");
++
++ /*
++ * Fail.
++ */
++ return (-EINVAL);
++ }
++
++ DPRINTK("DMA %d: pause \n", channel);
++
++ /*
++ * Set up a pointer to the dma instance data.
++ */
++ dma = &dma_chan[channel];
++
++ /*
++ * Set a pointer to the dma channel registers.
++ */
++ if (channel < 10) {
++ M2P_reg_base = dma->reg_base;
++ } else {
++ M2M_reg_base = dma->reg_base;
++ }
++
++ /*
++ * Check if we're already paused.
++ */
++ if (dma->pause) {
++ /*
++ * We're paused, but are we stopped?
++ */
++ if (dma->xfer_enable) {
++ /*
++ * Put the channel in the stopped state.
++ */
++ dma->xfer_enable = FALSE;
++ }
++
++ DPRINTK("DMA Pause - already paused.");
++ } else {
++ /*
++ * Put the channel into the stopped state.
++ */
++ dma->xfer_enable = FALSE;
++ dma->pause = TRUE;
++ }
++
++ /*
++ * restore interrupts.
++ */
++ local_irq_restore(flags);
++
++ /*
++ * Already paused, so exit.
++ */
++ return (0);
++}
++
++/*****************************************************************************
++ *
++ * void ep93xx_dma_flush(int handle)
++ *
++ * Description: Flushes all queued buffers and transfers in progress
++ * for the given channel. Return the buffer entries
++ * to the calling function.
++ *
++ * handle: handle for the channel for which the flush is intended.
++ *
++ ****************************************************************************/
++int ep93xx_dma_flush(int handle)
++{
++ unsigned int loop;
++ unsigned long flags;
++ ep93xx_dma_t *dma;
++ int channel;
++ unsigned int M2P_reg_base;
++
++ /*
++ * Get the DMA hw channel # from the handle.
++ */
++ channel = dma_get_channel_from_handle(handle);
++
++ /*
++ * See if this is a valid handle.
++ */
++ if (channel < 0) {
++ printk(KERN_ERR "DMA Flush: Invalid dma handle.\n");
++
++ /*
++ * Fail.
++ */
++ return (-EINVAL);
++ }
++
++ DPRINTK("DMA %d: flush \n", channel);
++
++ /*
++ * Set up a pointer to the dma instance data for this channel
++ */
++ dma = &dma_chan[channel];
++
++ /*
++ * Mask interrupts and hold on to the original state.
++ */
++ local_irq_save(flags);
++
++ for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) {
++ dma->buffer_queue[loop].buf_id = -1;
++ }
++
++ /*
++ * Set the Current and Last item to zero.
++ */
++ dma->current_buffer = 0;
++ dma->last_buffer = 0;
++
++ /*
++ * Reset the Buffer counters
++ */
++ dma->used_buffers = 0;
++ dma->new_buffers = 0;
++ dma->total_buffers = 0;
++
++ /*
++ * reset the Total bytes counter.
++ */
++ dma->total_bytes = 0;
++
++ M2P_reg_base = dma_chan[channel].reg_base;
++
++ /*
++ * restore interrupts.
++ */
++ local_irq_restore(flags);
++
++ /*
++ * Success.
++ */
++ return (0);
++}
++
++/*****************************************************************************
++ *
++ * int ep93xx_dma_queue_full(int handle)
++ *
++ * Description: Query to determine if the DMA queue of buffers for
++ * a given channel is full.
++ * 0 = queue is full
++ * 1 = queue is not full
++ *
++ * handle: handle for the channel to query.
++ *
++ ****************************************************************************/
++int ep93xx_dma_queue_full(int handle)
++{
++ int list_full = 0;
++ unsigned long flags;
++ int channel;
++
++ /*
++ * Get the DMA hw channel # from the handle.
++ */
++ channel = dma_get_channel_from_handle(handle);
++
++ /*
++ * See if this is a valid handle.
++ */
++ if (channel < 0) {
++ printk(KERN_ERR "DMA Queue Full: Invalid dma handle.\n");
++
++ /*
++ * Fail.
++ */
++ return (-EINVAL);
++ }
++
++ DPRINTK("DMA %d: queue full \n", channel);
++
++ /*
++ * Mask interrupts and hold on to the original state.
++ */
++ local_irq_save(flags);
++
++ /*
++ * If the last item is equal to the used item then
++ * the queue is full.
++ */
++ if (dma_chan[channel].total_buffers < MAX_EP93XX_DMA_BUFFERS) {
++ list_full = FALSE;
++ } else {
++ list_full = TRUE;
++ }
++
++ /*
++ * restore interrupts.
++ */
++ local_irq_restore(flags);
++
++ return (list_full);
++}
++
++
++/*****************************************************************************
++ *
++ * int ep93xx_dma_get_position()
++ *
++ * Description: Takes two integer pointers and fills them with the start
++ * and current address of the buffer currently transferring
++ * on the specified DMA channel.
++ *
++ * handle handle for the channel to query.
++ * *buf_id buffer id for the current buffer transferring on the
++ * dma channel.
++ * *total total bytes transferred on the channel. Only counts
++ * whole buffers transferred.
++ * *current_frac number of bytes transferred so far in the current buffer.
++ ****************************************************************************/
++int
++ep93xx_dma_get_position(int handle, unsigned int * buf_id,
++ unsigned int * total, unsigned int * current_frac )
++{
++ int channel;
++ ep93xx_dma_t * dma;
++ unsigned int buf_id1, total1, current_frac1, buf_id2, total2;
++ unsigned int Status, NextBuffer, StateIsBufNext, M2P_reg_base=0;
++ unsigned int pause1, pause2;
++
++ /*
++ * Get the DMA hw channel # from the handle. See if this is a
++ * valid handle.
++ */
++ channel = dma_get_channel_from_handle(handle);
++ if (channel < 0) {
++ printk(KERN_ERR "DMA Get Position: Invalid dma handle.\n");
++ return(-EINVAL);
++ }
++
++ dma = &dma_chan[channel];
++
++ /*
++ * If DMA moves to a new buffer in the middle of us grabbing the
++ * buffer info, then do it over again.
++ */
++ do{
++ buf_id1 = dma->buffer_queue[dma->current_buffer].buf_id;
++ total1 = dma->total_bytes;
++ pause1 = dma->pause;
++
++ if (channel < 10) {
++ /* M2P */
++ M2P_reg_base = dma->reg_base;
++
++ Status = inl(M2P_reg_base+M2P_OFFSET_STATUS);
++
++ NextBuffer = ((Status & STATUS_M2P_NEXTBUFFER) != 0);
++
++ StateIsBufNext = ((Status & STATUS_M2P_CURRENT_MASK) ==
++ STATUS_M2P_DMA_BUF_NEXT);
++
++ if( NextBuffer ^ StateIsBufNext )
++ current_frac1 = inl(M2P_reg_base+M2P_OFFSET_CURRENT1) -
++ inl(M2P_reg_base+M2P_OFFSET_BASE1);
++ else
++ current_frac1 = inl(M2P_reg_base+M2P_OFFSET_CURRENT0) -
++ inl(M2P_reg_base+M2P_OFFSET_BASE0);
++
++ } else {
++ /* M2M - TODO implement this for M2M */
++ current_frac1 = 0;
++ }
++
++ buf_id2 = dma->buffer_queue[dma->current_buffer].buf_id;
++ total2 = dma->total_bytes;
++ pause2 = dma->pause;
++
++ } while ( (buf_id1 != buf_id2) || (total1 != total2) || (pause1 != pause2) );
++
++ if (pause1)
++ current_frac1 = 0;
++
++ if (buf_id)
++ *buf_id = buf_id1;
++
++ if (total)
++ *total = total1;
++
++ if (current_frac)
++ *current_frac = current_frac1;
++
++ /*
++ * Success.
++ */
++ return(0);
++}
++
++/* changed for AC97 port from Virgo 1-4-3 */
++#if 0
++/*****************************************************************************
++ *
++ * int ep93xx_dma_get_position(int handle, unsigned int * buf_id,
++ unsigned int * total)
++ *
++ * Description: Takes two integer pointers and fills them with the start
++ * and current address of the buffer currently transferring
++ * on the specified DMA channel.
++ *
++ * handle: handle for the channel to query.
++ * buf_id: pointer which is filled in with the buffer id for the
++ * current buffer transferring on the dma channel.
++ * buffer being transferred.
++ * total : pointer which is filled in with the total bytes
++ * transferred on the channel.
++ ****************************************************************************/
++int
++ep93xx_dma_get_position(int handle, unsigned int *buf_id, unsigned int *total)
++{
++ int channel;
++ ep93xx_dma_t *dma;
++
++ /*
++ * Get the DMA hw channel # from the handle.
++ */
++ channel = dma_get_channel_from_handle(handle);
++
++ /*
++ * See if this is a valid handle.
++ */
++ if (channel < 0) {
++ printk(KERN_ERR "DMA Get Position: Invalid dma handle.\n");
++
++ /*
++ * Fail.
++ */
++ return (-EINVAL);
++ }
++
++ dma = &dma_chan[channel];
++
++ /*
++ * TODO: should irqs be disabled here?
++ */
++
++ *buf_id = dma->buffer_queue[dma->current_buffer].buf_id;
++
++ *total = dma->total_bytes;
++
++ DPRINTK("DMA buf_id %d, total %d\n", *buf_id, *total);
++
++ /*
++ * Success.
++ */
++ return (0);
++}
++#endif
++
++
++
++/*****************************************************************************
++ *
++ * int ep93xx_dma_get_total(int handle)
++ *
++ * Description: Returns the total number of bytes transferred on the
++ * specified channel since the channel was requested.
++ *
++ * handle: handle for the channel to query.
++ *
++ ****************************************************************************/
++int ep93xx_dma_get_total(int handle)
++{
++ int channel;
++
++ /*
++ * Get the DMA hw channel # from the handle.
++ */
++ channel = dma_get_channel_from_handle(handle);
++
++ /*
++ * See if this is a valid handle.
++ */
++ if (channel < 0) {
++ printk(KERN_ERR "DMA Get Total: Invalid dma handle.\n");
++
++ /*
++ * Fail.
++ */
++ return (-EINVAL);
++ }
++
++ DPRINTK("DMA %d: total: %d \n", channel, dma_chan[channel].total_bytes);
++
++ /*
++ * Return the total number of bytes transferred on this channel since
++ * it was requested.
++ */
++ return (dma_chan[channel].total_bytes);
++}
++
++/*****************************************************************************
++ * ep93xx_dma_request
++ *
++ * Description: This function will allocate a DMA channel for a particular
++ * hardware peripheral. Before initiating a transfer on the allocated
++ * channel, the channel must be set up and buffers have to queued up.
++ *
++ * handle: pointer to an integer which is filled in with a unique
++ * handle for this instance of the dma interface.
++ * device_id string with the device name, primarily used by /proc.
++ * device hardware device ID for which the requested dma channel will
++ * transfer data.
++ *
++ ****************************************************************************/
++int
++ep93xx_dma_request(int *handle, const char *device_id, ep93xx_dma_dev_t device)
++{
++ ep93xx_dma_t *dma = NULL;
++ int channel;
++ unsigned int error = 0;
++ unsigned int loop;
++ unsigned int M2P_reg_base;
++
++ /*
++ * Check if the device requesting a DMA channel is a valid device.
++ */
++ if ((device >= UNDEF) || (device < 0)) {
++ /*
++ * Invalid device, so return an error.
++ */
++ return (-ENODEV);
++ }
++
++ /*
++ * We've got a valid hardware device requesting a DMA channel.
++ * Now check if the device should open an M2P or M2M channel
++ */
++ if (device < 20) {
++ channel = dma_open_m2p(device);
++ } else {
++ channel = dma_open_m2m(device);
++ }
++
++ /*
++ * Check if we successfully opened a DMA channel
++ */
++ if (channel < 0) {
++ printk(KERN_ERR
++ "%s: Could not open dma channel for this device.\n",
++ device_id);
++
++ /*
++ * Fail.
++ */
++ return (-EBUSY);
++ }
++
++ dma = &dma_chan[channel];
++
++ /*
++ * Request the appropriate IRQ for the specified channel
++ */
++ if (channel < 10) {
++ error = request_irq(dma->irq, dma_m2p_irq_handler, SA_INTERRUPT,
++ device_id, (void *)dma);
++ } else {
++ error =
++ request_irq(dma->irq, &dma_m2m_irq_handler, SA_INTERRUPT,
++ device_id, (void *)dma);
++ }
++
++ /*
++ * Check for any errors during the irq request
++ */
++ if (error) {
++ printk(KERN_ERR
++ "%s: unable to request IRQ %d for DMA channel\n",
++ device_id, dma->irq);
++ /*
++ * Fail.
++ */
++ return (error);
++ }
++
++ /*
++ * Generate a valid handle and exit.
++ *
++ * Increment the last valid handle.
++ * Check for wraparound (unlikely, but we like to be complete).
++ */
++ dma->last_valid_handle++;
++
++ if ((dma->last_valid_handle & DMA_HANDLE_SPECIFIER_MASK) !=
++ (channel << 28)) {
++ /*
++ * If we wrapped around start over.
++ */
++ dma->last_valid_handle = (channel << 28) + 1;
++ }
++
++ /*
++ * Fill in the handle pointer with a valid handle for
++ * this dma channel instance.
++ */
++ *handle = dma->last_valid_handle;
++
++ DPRINTK("Handle for channel %d: 0x%x\n", channel, *handle);
++
++ /*
++ * Save the device ID and device name.
++ */
++ dma->device = device;
++ dma->device_id = device_id;
++
++ /*
++ * Init all fields within the dma instance.
++ */
++ for (loop = 0; loop < MAX_EP93XX_DMA_BUFFERS; loop++) {
++ dma->buffer_queue[loop].buf_id = -1;
++ }
++
++ /*
++ * Initialize all buffer queue variables.
++ */
++ dma->current_buffer = 0;
++ dma->last_buffer = 0;
++
++ dma->new_buffers = 0;
++ dma->used_buffers = 0;
++ dma->total_buffers = 0;
++
++ /*
++ * Initialize the total bytes variable
++ */
++ dma->total_bytes = 0;
++
++ /*
++ * Initialize the transfer and pause state variables to 0.
++ */
++ dma->xfer_enable = 0;
++
++ dma->pause = 0;
++
++ /*
++ * Initialize the pause buffer structure.
++ */
++ dma->pause_buf.buf_id = -1;
++
++ /*
++ * Initialize the callback function and user data fields.
++ */
++ dma->callback = NULL;
++
++ /*
++ * User data used as a parameter for the Callback function. The user
++ * sets up the data and sends it with the callback function.
++ */
++ dma->user_data = 0;
++
++ M2P_reg_base = dma_chan[channel].reg_base;
++
++ /*
++ * Debugging message.
++ */
++ DPRINTK("Successfully requested dma channel %d\n", channel);
++ DPRINTK("STATUS - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_STATUS));
++ DPRINTK("CONTROL - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CONTROL));
++ DPRINTK("REMAIN - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_REMAIN));
++ DPRINTK("PPALLOC - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_PPALLOC));
++ DPRINTK("BASE0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE0));
++ DPRINTK("MAXCNT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT0));
++ DPRINTK("CURRENT0 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT0));
++ DPRINTK("BASE1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_BASE1));
++ DPRINTK("MAXCNT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_MAXCNT1));
++ DPRINTK("CURRENT1 - 0x%x \n", readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
++
++ DPRINTK("Buffer source size last used \n");
++ for (loop = 0; loop < 5; loop++) {
++ DPRINTK("%d 0x%x 0x%x %d %d \n",
++ loop, dma->buffer_queue[loop].source,
++ dma->buffer_queue[loop].size,
++ dma->buffer_queue[loop].last,
++ dma->buffer_queue[loop].used);
++ }
++ DPRINTK("pause 0x%x 0x%x %d %d \n",
++ dma->pause_buf.source, dma->pause_buf.size,
++ dma->pause_buf.last, dma->pause_buf.used);
++
++ DPRINTK("Pause - %d \n", dma->pause);
++ DPRINTK("xfer_enable - %d \n", dma->xfer_enable);
++ DPRINTK("total bytes - 0x%x \n", dma->total_bytes);
++ DPRINTK("total buffer - %d \n", dma->total_buffers);
++ DPRINTK("new buffers - %d \n", dma->new_buffers);
++ DPRINTK("current buffer - %d \n", dma->current_buffer);
++ DPRINTK("last buffer - %d \n", dma->last_buffer);
++ DPRINTK("used buffers - %d \n", dma->used_buffers);
++
++ DPRINTK("CURRENT1 - 0x%x \n",
++ readl(M2P_reg_base + M2P_OFFSET_CURRENT1));
++ DPRINTK("VIC0IRQSTATUS - 0x%x, VIC0INTENABLE - 0x%x \n",
++ *(unsigned int *)(VIC0IRQSTATUS),
++ *(unsigned int *)(VIC0INTENABLE));
++
++ /*
++ * Success.
++ */
++ return (0);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_dma_free
++ *
++ * Description: This function will free the dma channel for future requests.
++ *
++ * handle: handle for the channel to be freed.
++ *
++ ****************************************************************************/
++int ep93xx_dma_free(int handle)
++{
++ ep93xx_dma_t *dma;
++ unsigned int M2M_reg_base, M2P_reg_base, uiCONTROL;
++ int channel;
++
++ /*
++ * Get the DMA hw channel # from the handle.
++ */
++ channel = dma_get_channel_from_handle(handle);
++
++ /*
++ * See if this is a valid handle.
++ */
++ if (channel < 0) {
++ printk(KERN_ERR "DMA Free: Invalid dma handle.\n");
++
++ /*
++ * Fail.
++ */
++ return (-EINVAL);
++ }
++
++ /*
++ * Get a pointer to the dma instance.
++ */
++ dma = &dma_chan[channel];
++
++ /*
++ * Disable the dma channel
++ */
++ if (channel < 10) {
++ /*
++ * M2P channel
++ */
++ M2P_reg_base = dma->reg_base;
++
++ uiCONTROL = readl(M2P_reg_base + M2P_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2P_ENABLE;
++ writel(uiCONTROL, M2P_reg_base + M2P_OFFSET_CONTROL);
++ } else {
++ /*
++ * M2M channel
++ */
++ M2M_reg_base = dma->reg_base;
++
++ uiCONTROL = readl(M2M_reg_base + M2M_OFFSET_CONTROL);
++ uiCONTROL &= ~CONTROL_M2M_ENABLE;
++ writel(uiCONTROL, M2M_reg_base + M2M_OFFSET_CONTROL);
++ }
++
++ /*
++ * Free the interrupt servicing this dma channel
++ */
++ free_irq(dma->irq, (void *)dma);
++
++ /*
++ * Decrement the reference count for this instance of the dma interface
++ */
++ dma->ref_count--;
++
++ /*
++ * Set the transfer and pause state variables to 0
++ * (unititialized state).
++ */
++ dma->xfer_enable = 0;
++ dma->pause = 0;
++
++ /*
++ * Debugging message.
++ */
++ DPRINTK("Successfully freed dma channel %d\n", channel);
++
++ /*
++ * Success.
++ */
++ return (0);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_dma_init(void)
++ *
++ * Description: This function is called during system initialization to
++ * setup the interrupt number and register set base address for each DMA
++ * channel.
++ *
++ ****************************************************************************/
++static int __init ep93xx_dma_init(void)
++{
++ int channel;
++
++ /*
++ * Init some values in each dma instance.
++ */
++ for (channel = 0; channel < MAX_EP93XX_DMA_CHANNELS; channel++) {
++ /*
++ * IRQ for the specified dma channel.
++ */
++ dma_chan[channel].irq = IRQ_DMAM2P0 + channel;
++
++ /*
++ * Initial value of the dma channel handle.
++ */
++ dma_chan[channel].last_valid_handle = channel << 28;
++
++ /*
++ * Give the instance a pointer to the dma channel register
++ * base.
++ */
++ if (channel < 10) {
++ dma_chan[channel].reg_base = DMAM2PChannelBase[channel];
++ } else {
++ dma_chan[channel].reg_base =
++ DMAM2MChannelBase[channel - 10];
++ }
++
++ /*
++ * Initialize the reference count for this channel.
++ */
++ dma_chan[channel].ref_count = 0;
++ }
++
++ DPRINTK("DMA Interface intitialization complete\n");
++
++ /*
++ * Success
++ */
++ return 0;
++}
++
++__initcall(ep93xx_dma_init);
++
++EXPORT_SYMBOL(ep93xx_dma_add_buffer);
++EXPORT_SYMBOL(ep93xx_dma_config);
++EXPORT_SYMBOL(ep93xx_dma_flush);
++EXPORT_SYMBOL(ep93xx_dma_free);
++EXPORT_SYMBOL(ep93xx_dma_get_position);
++EXPORT_SYMBOL(ep93xx_dma_get_total);
++EXPORT_SYMBOL(ep93xx_dma_init);
++EXPORT_SYMBOL(ep93xx_dma_pause);
++EXPORT_SYMBOL(ep93xx_dma_queue_full);
++EXPORT_SYMBOL(ep93xx_dma_remove_buffer);
++EXPORT_SYMBOL(ep93xx_dma_request);
++EXPORT_SYMBOL(ep93xx_dma_start);
++
+diff --git a/arch/arm/mach-ep93xx/dma_ep93xx.h b/arch/arm/mach-ep93xx/dma_ep93xx.h
+new file mode 100644
+index 0000000..3ec0b0d
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/dma_ep93xx.h
+@@ -0,0 +1,194 @@
++/*****************************************************************************
++ *
++ * arch/arm/mach-ep93xx/dma_ep93xx.h
++ *
++ * DESCRIPTION: 93XX DMA controller API private defintions.
++ *
++ * Copyright Cirrus Logic Corporation, 2003. All rights reserved
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ ****************************************************************************/
++#ifndef _EP93XX_DMA_H_
++#define _EP93XX_DMA_H_
++
++#define MAX_EP93XX_DMA_BUFFERS 32
++
++#ifndef TRUE
++#define TRUE 1
++#endif
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++#ifndef NULL
++#define NULL 0
++#endif
++
++/*****************************************************************************
++ *
++ * DMA buffer structure type.
++ *
++ ****************************************************************************/
++typedef struct ep93xx_dma_buffer_s {
++ unsigned int source; /* buffer physical source address. */
++ unsigned int dest; /* buffer physical destination address, */
++ /* only used with the 2 M2M channels. */
++ unsigned int size; /* buffer size in bytes */
++ unsigned int last; /* 1 if this is the last buffer */
++ /* in this transaction. If 1, */
++ /* disable the NFBint so we aren't */
++ /* interrupted for another buffer */
++ /* when we know there won't be another. */
++ unsigned int used; /* This field is set to 1 by the DMA */
++ /* interface after the buffer is transferred */
++ int buf_id; /* unique identifyer specified by the */
++ /* the driver which requested the dma */
++} ep93xx_dma_buffer_t;
++
++typedef ep93xx_dma_buffer_t *ep93xx_dma_buffer_p;
++
++/*****************************************************************************
++ *
++ * Instance definition for the DMA interface.
++ *
++ ****************************************************************************/
++typedef struct ep7312_dma_s {
++ /*
++ * This 1 when the instance is in use, and 0 when it's not.
++ */
++ unsigned int ref_count;
++
++ /*
++ * This is the last valid handle for this instance. When giving out a
++ * new handle this will be incremented and given out.
++ */
++ int last_valid_handle;
++
++ /*
++ * device specifies one of the 20 DMA hardware ports this
++ * DMA channel will service.
++ */
++ ep93xx_dma_dev_t device;
++
++ /*
++ * DMABufferQueue is the queue of buffer structure pointers which the
++ * dma channel will use to setup transfers.
++ */
++ ep93xx_dma_buffer_t buffer_queue[MAX_EP93XX_DMA_BUFFERS];
++
++ /*
++ * currnt_buffer : This is the buffer currently being transfered on
++ * this channel.
++ * last_buffer : This is the last buffer for this transfer.
++ * Note: current_buffer + 1 is already programmed into the dma
++ * channel as the next buffer to transfer. Don't write
++ * over either entry.
++ */
++ int current_buffer;
++ int last_buffer;
++
++ /*
++ * The following 3 fields are buffer counters.
++ *
++ * iNewBuffers: Buffers in the queue which have not been transfered.
++ * iUsedBuffers: Buffers in the queue which have have been tranferred,
++ * and are waiting to be returned.
++ * iTotalBuffers: Total number of buffers in the queue.
++ */
++ int new_buffers;
++ int used_buffers;
++ int total_buffers;
++
++ /*
++ * uiTotalBytes has the total bytes transfered on the channel since the
++ * last flush. This value does not include the bytes tranfered in the
++ * current buffer. A byte count is only added after a complete buffer
++ * is tranfered.
++ */
++ unsigned int total_bytes;
++
++ /*
++ * Interrupt number for this channel
++ */
++ unsigned int irq;
++
++ /*
++ * Indicates whether or not the channel is currently enabled to transfer
++ * data.
++ */
++ unsigned int xfer_enable;
++
++ /*
++ * pause indicates if the dma channel was paused by calling the pause
++ * ioctl.
++ */
++ unsigned int pause;
++
++ /*
++ * buffer structure used during a pause to capture the current
++ * address and remaining bytes for the buffer actively being transferred
++ * on the channel. This buffer will be used to reprogram the dma
++ * channel upon a resume.
++ */
++ ep93xx_dma_buffer_t pause_buf;
++
++ /*
++ * DMACallback is a function pointer which the calling application can
++ * use install a function to. this fuction can be used to notify the
++ * calling application of an interrupt.
++ */
++ dma_callback callback;
++
++ /*
++ * User data used as a parameter for the Callback function. The user
++ * sets up the data and sends it with the callback function.
++ */
++ unsigned int user_data;
++
++ /*
++ * A string representation of the device attached to the channel.
++ */
++ const char *device_id;
++
++ /*
++ * The register base address for this dma channel.
++ */
++ unsigned int reg_base;
++
++} ep93xx_dma_t;
++
++/*****************************************************************************
++ *
++ * DMA macros
++ *
++ ****************************************************************************/
++#define DMA_HANDLE_SPECIFIER_MASK 0xF0000000
++#define DMA_CH0_HANDLE_SPECIFIER 0x00000000
++#define DMA_CH1_HANDLE_SPECIFIER 0x10000000
++#define DMA_CH2_HANDLE_SPECIFIER 0x20000000
++#define DMA_CH3_HANDLE_SPECIFIER 0x30000000
++#define DMA_CH4_HANDLE_SPECIFIER 0x40000000
++#define DMA_CH5_HANDLE_SPECIFIER 0x50000000
++#define DMA_CH6_HANDLE_SPECIFIER 0x60000000
++#define DMA_CH7_HANDLE_SPECIFIER 0x70000000
++#define DMA_CH8_HANDLE_SPECIFIER 0x80000000
++#define DMA_CH9_HANDLE_SPECIFIER 0x90000000
++#define DMA_CH10_HANDLE_SPECIFIER 0xA0000000
++#define DMA_CH11_HANDLE_SPECIFIER 0xB0000000
++
++#endif
++
+diff --git a/arch/arm/mach-ep93xx/ep93xx.c b/arch/arm/mach-ep93xx/ep93xx.c
+new file mode 100644
+index 0000000..a565f14
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/ep93xx.c
+@@ -0,0 +1,571 @@
++/*
++ * linux/arch/arm/mach-ep93xx/ep93xx.c
++ *
++ * Copyright (C) 2000-2003 Deep Blue Solutions Ltd
++ * Copyright (C) 2004 Ray Lehtiniemi
++ * Copyright (C) 2005 Michael Burian
++ *
++ * 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/device.h>
++#include <linux/interrupt.h>
++
++#include <asm/irq.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/hardware/amba.h>
++#include <asm/mach/time.h>
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++static __init void check_model(void)
++{
++ unsigned long x;
++ char *model;
++ char *rev;
++
++ printk(KERN_INFO "CPU model: ");
++
++ x = readl(USRFLG);
++ switch (x) {
++ case 0:
++ model = "15";
++ break;
++ case 2:
++ model = "12";
++ break;
++ case 4:
++ model = "01";
++ break;
++ default:
++ printk("(unknown model %ld) ", x);
++ model = "xx";
++ break;
++ }
++
++ x = readl(SYSCON_SYSCFG) >> 28;
++ switch (x) {
++ case 0:
++ rev = "A";
++ break;
++ case 1:
++ rev = "B";
++ break;
++ case 2:
++ rev = "C";
++ break;
++ case 3:
++ rev = "D0";
++ break;
++ case 4:
++ rev = "D1";
++ break;
++ case 5:
++ rev = "E";
++ break;
++ default:
++ printk("(unknown revision %ld) ", x);
++ rev = "unknown";
++ break;
++ }
++
++ printk("Cirrus Logic EP93%s, silicon rev %s\n", model, rev);
++}
++
++static struct amba_device dma_device = {
++ .dev = {
++ .bus_id = "0x80000000:dma",
++ },
++ .res = {
++ .start = DMA_BASE,
++ .end = DMA_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80000000,
++};
++
++static struct amba_device mac_device = {
++ .dev = {
++ .bus_id = "0x80010000:mac",
++ },
++ .res = {
++ .start = MAC_BASE,
++ .end = MAC_BASE + SZ_64K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80010000,
++};
++
++static struct amba_device usb_device = {
++ .dev = {
++ .bus_id = "0x80020000:usb",
++ .coherent_dma_mask = 0xffffffff,
++ },
++ .res = {
++ .start = USB_BASE,
++ .end = USB_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {IRQ_USH, NO_IRQ},
++ .periphid = 0x80020000,
++};
++
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++static struct amba_device raster_device = {
++ .dev = {
++ .bus_id = "0x80030000:raster",
++ },
++ .res = {
++ .start = RASTER_BASE,
++ .end = RASTER_BASE + SZ_8K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80030000,
++};
++#endif
++
++static struct amba_device sdram_device = {
++ .dev = {
++ .bus_id = "0x80060000:sdram",
++ },
++ .res = {
++ .start = SDRAM_BASE,
++ .end = SDRAM_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80060000,
++};
++
++static struct amba_device smc_device = {
++ .dev = {
++ .bus_id = "0x80080000:smc",
++ },
++ .res = {
++ .start = SMC_BASE,
++ .end = SMC_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80080000,
++};
++
++static struct amba_device boot_device = {
++ .dev = {
++ .bus_id = "0x80090000:boot",
++ },
++ .res = {
++ .start = BOOT_BASE,
++ .end = BOOT_BASE + SZ_16K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80090000,
++};
++
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++static struct amba_device ide_device = {
++ .dev = {
++ .bus_id = "0x800a0000:ide",
++ },
++ .res = {
++ .start = IDE_BASE,
++ .end = IDE_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x800a0000,
++};
++#endif
++
++static struct amba_device vic1_device = {
++ .dev = {
++ .bus_id = "0x800b0000:vic1",
++ },
++ .res = {
++ .start = VIC0_BASE,
++ .end = VIC0_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x800b0000,
++};
++
++static struct amba_device vic2_device = {
++ .dev = {
++ .bus_id = "0x800c0000:vic2",
++ },
++ .res = {
++ .start = VIC1_BASE,
++ .end = VIC1_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x800c0000,
++};
++
++static struct amba_device timer_device = {
++ .dev = {
++ .bus_id = "0x80810000:timer",
++ },
++ .res = {
++ .start = TIMERS_BASE,
++ .end = TIMERS_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80810000,
++};
++
++static struct amba_device i2s_device = {
++ .dev = {
++ .bus_id = "0x80820000:i2s",
++ },
++ .res = {
++ .start = I2S_BASE,
++ .end = I2S_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80820000,
++};
++
++static struct amba_device security_device = {
++ .dev = {
++ .bus_id = "0x80830000:security",
++ },
++ .res = {
++ .start = SECURITY_BASE,
++ .end = SECURITY_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80830000,
++};
++
++static struct amba_device gpio_device = {
++ .dev = {
++ .bus_id = "0x80840000:gpio",
++ },
++ .res = {
++ .start = GPIO_BASE,
++ .end = GPIO_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80840000,
++};
++
++static struct amba_device ac97_device = {
++ .dev = {
++ .bus_id = "0x80880000:ac97",
++ },
++ .res = {
++ .start = AC97_BASE,
++ .end = AC97_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80880000,
++};
++
++static struct amba_device ssp_device = {
++ .dev = {
++ .bus_id = "0x808a0000:ssp",
++ },
++ .res = {
++ .start = SSP_BASE,
++ .end = SSP_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x808a0000,
++};
++
++static struct amba_device irda_device = {
++ .dev = {
++ .bus_id = "0x808b0000:irda",
++ },
++ .res = {
++ .start = IRDA_BASE,
++ .end = IRDA_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x808b0000,
++};
++
++static struct amba_device uart1_device = {
++ .dev = {
++ .bus_id = "0x808c0000:uart1",
++ },
++ .res = {
++ .start = UART1_BASE,
++ .end = UART1_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {IRQ_UART1, NO_IRQ},
++ .periphid = 0x808c0000,
++};
++
++static struct amba_device uart2_device = {
++ .dev = {
++ .bus_id = "0x808d0000:uart2",
++ },
++ .res = {
++ .start = UART2_BASE,
++ .end = UART2_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {IRQ_UART2, NO_IRQ},
++ .periphid = 0x808d0000,
++};
++
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++static struct amba_device uart3_device = {
++ .dev = {
++ .bus_id = "0x808e0000:uart3",
++ },
++ .res = {
++ .start = UART3_BASE,
++ .end = UART3_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {IRQ_UART3, NO_IRQ},
++ .periphid = 0x808e0000,
++};
++
++static struct amba_device key_device = {
++ .dev = {
++ .bus_id = "0x808f0000:key",
++ },
++ .res = {
++ .start = KEY_BASE,
++ .end = KEY_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x808f0000,
++};
++
++static struct amba_device touch_device = {
++ .dev = {
++ .bus_id = "0x80900000:touch",
++ },
++ .res = {
++ .start = TOUCH_BASE,
++ .end = TOUCH_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80900000,
++};
++
++static struct amba_device pwm_device = {
++ .dev = {
++ .bus_id = "0x80910000:pwm",
++ },
++ .res = {
++ .start = PWM_BASE,
++ .end = PWM_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80910000,
++};
++#endif
++
++static struct amba_device rtc_device = {
++ .dev = {
++ .bus_id = "0x80920000:rtc",
++ },
++ .res = {
++ .start = RTC_BASE,
++ .end = RTC_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {IRQ_RTC, NO_IRQ},
++ .periphid = 0x80920000,
++};
++
++static struct amba_device syscon_device = {
++ .dev = {
++ .bus_id = "0x80930000:syscon",
++ },
++ .res = {
++ .start = SYSCON_BASE,
++ .end = SYSCON_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80930000,
++};
++
++static struct amba_device watchdog_device = {
++ .dev = {
++ .bus_id = "0x80940000:watchdog",
++ },
++ .res = {
++ .start = WATCHDOG_BASE,
++ .end = WATCHDOG_BASE + SZ_4K - 1,
++ .flags = IORESOURCE_MEM,
++ },
++ .irq = {NO_IRQ, NO_IRQ},
++ .periphid = 0x80940000,
++};
++
++static struct amba_device *amba_devs[] __initdata = {
++ /* AHB devices */
++ &dma_device,
++ &mac_device,
++ &usb_device,
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++ &raster_device,
++#endif
++ &sdram_device,
++ &smc_device,
++ &boot_device,
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++ &ide_device,
++#endif
++ &vic1_device,
++ &vic2_device,
++
++ /* APB devices */
++ &timer_device,
++ &i2s_device,
++ &security_device,
++ &gpio_device,
++ &ac97_device,
++ &ssp_device,
++ &irda_device,
++ &uart1_device,
++ &uart2_device,
++#if defined(CONFIG_ARCH_EP9312) || defined (CONFIG_ARCH_EP9315)
++ &uart3_device,
++ &key_device,
++ &touch_device,
++ &pwm_device,
++#endif
++ &rtc_device,
++ &syscon_device,
++ &watchdog_device,
++};
++
++static int __init ep93xx_init(void)
++{
++ int i;
++
++ check_model();
++
++ for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
++ struct amba_device *d = amba_devs[i];
++ amba_device_register(d, &iomem_resource);
++ }
++
++ return 0;
++}
++
++arch_initcall(ep93xx_init);
++
++#define TIMER_INTERVAL (508 * mSEC_10 / 1000)
++#define TICKS2USECS(x) ((x) * 1000 / 508)
++
++static unsigned long timer_reload;
++
++/*
++ * Returns number of ms since last clock interrupt. Note that interrupts
++ * will have been disabled by do_gettimeoffset()
++ */
++static unsigned long ep93xx_gettimeoffset(void)
++{
++ unsigned long ticks1, ticks2, status;
++
++ /*
++ * Get the current number of ticks. Note that there is a race
++ * condition between us reading the timer and checking for
++ * an interrupt. We get around this by ensuring that the
++ * counter has not reloaded between our two reads.
++ */
++ ticks2 = readl(TIMER1VALUE) & 0xffff;
++ do {
++ ticks1 = ticks2;
++ status = readl(VIC0RAWINTR);
++ ticks2 = readl(TIMER1VALUE) & 0xffff;
++ } while (ticks2 > ticks1);
++
++ /*
++ * Number of ticks since last interrupt.
++ */
++ ticks1 = timer_reload - ticks2;
++
++ /*
++ * Interrupt pending? If so, we've reloaded once already.
++ */
++ if (status & (1 << IRQ_TIMER1))
++ ticks1 += timer_reload;
++
++ return TICKS2USECS(ticks1);
++}
++
++/*
++ * IRQ handler for the timer
++ */
++static irqreturn_t
++ep93xx_timer_interrupt(int irq, void *dev_id, struct pt_regs *regs)
++{
++ /* ...clear the interrupt */
++ writel(1, TIMER1CLEAR);
++
++ timer_tick(regs);
++
++ return IRQ_HANDLED;
++}
++
++static struct irqaction ep93xx_timer_irq = {
++ .name = "timer",
++ .flags = SA_INTERRUPT,
++ .handler = ep93xx_timer_interrupt
++};
++
++/*
++ * Set up timer interrupt
++ */
++static void __init __ep93xx_init_timer(unsigned long reload, unsigned int ctrl)
++{
++ unsigned int timer_ctrl = 0x80 | 0x40 | 0x08; /* periodic at 508 kHz */
++
++ timer_reload = reload;
++ timer_ctrl |= ctrl;
++
++ /*
++ * Initialise to a known state (all timers off)
++ */
++
++ writel(0, TIMER1CONTROL);
++ writel(0, TIMER2CONTROL);
++ writel(0, TIMER3CONTROL);
++
++ writel(timer_reload, TIMER1LOAD);
++ writel(timer_reload, TIMER1VALUE);
++ writel(timer_ctrl, TIMER1CONTROL);
++
++ setup_irq(IRQ_TIMER1, &ep93xx_timer_irq);
++}
++
++static void __init ep93xx_init_timer(void)
++{
++ /* 10 ms interval on a 508 kHz clock */
++ __ep93xx_init_timer(5080, 0);
++}
++
++struct sys_timer ep93xx_timer = {
++ .init = ep93xx_init_timer,
++ .offset = ep93xx_gettimeoffset,
++};
+diff --git a/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h b/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h
+new file mode 100644
+index 0000000..d396e96
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h
+@@ -0,0 +1,41 @@
++/*
++ * linux/arch/arm/mach-ep93xx/ep93xx_gpio_irq.h
++ *
++ * Copyright (C) 2004 Contec Steuerungstechnik & Automation GmbH
++ * Manfred Gruber <manfred.gruber@contec.at>
++ *
++ * 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
++ */
++
++/*
++ * configuration struct for GPIO IRQs
++ *
++ * enable = 1 --> this EGIO is a irq
++ * enable = 0 --> this EGIO is a GPIO
++ * flags can be IRQT_RISING
++ * IRQT_FALLING
++ * IRQT_LOW
++ * IRQT_HIGH
++ * IRQT_PROBE
++ *
++ * On IRQT_PROBE nothing is done in setup irq code
++ */
++
++struct ep93xx_egpio_irq
++{
++ unsigned int enable;
++ unsigned int flags;
++};
++
+diff --git a/arch/arm/mach-ep93xx/irq.c b/arch/arm/mach-ep93xx/irq.c
+new file mode 100644
+index 0000000..578c783
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/irq.c
+@@ -0,0 +1,601 @@
++/*
++ * linux/arch/arm/mach-ep93xx/irq.c
++ *
++ * Copyright (C) 1999 ARM Limited
++ *
++ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA. All rights reserved.
++ *
++ * Copyright (C) 2002-2003 Cirrus Logic, Inc.
++ *
++ * Demux IRQ 59 by
++ * Copyright (C) 2004 Contec Steuerungstechnik & Automation GmbH
++ * Manfred Gruber <manfred.gruber@contec.at>
++ *
++ * 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
++ *
++ *
++ * Modified by Stefano Lena <stefano.lena@dave-tech.it>, DAVE s.r.l.
++ * for Cirrus Logic EP93xx series
++ *
++ *
++ */
++
++#include <linux/kernel.h>
++#include <linux/timer.h>
++#include <linux/init.h>
++
++#include <asm/irq.h>
++
++#include <asm/arch/irqs.h>
++
++#include <asm/mach/irq.h>
++#include <asm/io.h>
++#include <asm/arch/hardware.h>
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++#include <asm/arch/regmap.h>
++#include <linux/errno.h>
++#include "ep93xx_gpio_irq.h"
++extern struct ep93xx_egpio_irq egpio_irqs[];
++
++/* GPIO Port A/B debug messages */
++/* #define DEBUG_GPIO */
++#ifdef DEBUG_GPIO
++#define IRQDBG(args...) printk(args)
++#else
++#define IRQDBG(args...) do {} while(0)
++#endif
++#endif
++/********************************************************************
++ * Interrupt functions are defined as machine specific here.
++ *
++ * Note:
++ * 1. Only normal interrupts are defined here.
++ * FIQs are a separate class of interrupts and would
++ * be slowed down if handled like normal interrupts.
++ *
++ * 2. TBD Invalid interrupt numbers are not checked.
++ * Some interrupt inputs are tied to GND, which means
++ * they will immediately activate when unmasked.
++ * Which may be useful for some devices.
++ *
++ * 3. TBD Edge triggered interrupts are not specially
++ * handled. The architecture should provide a way to
++ * set up the edge trigger features and then a way to
++ * control the acknowledge to the interrupt.
++ *
++ ************************************************************************/
++
++ /********************************************************************
++ * demux interrupt handler for GPIO Port A and B on ep93xx
++ *
++ * Note:
++ That IRQs from 64 to 79 defined as GPIO_IRQ0 - GPIO_IRQ15
++ * GPIO IRQs on port F are as the are defined as IRQ_GPIOX
++ * which are NOT handled in demux interrupt handler !!!!!
++ *
++ * Default in mach-xy file a struct ep93xx_egpio_irq
++ * can be set up, there you can configure which gpio
++ * of Port A/B should be used as interrupt on startup.
++ * Setting up this IRQs in your driver direct not on startup
++ * you have to do a set_irq_type(GPIO_IRQX, flags) before
++ * calling request irq. Possible Flags are:
++ * IRQT_RISING, IRQT_FALLING, IRQT_LOW, IRQT_HIGH, IRQT_PROBE, IRQ_DB, IRQ_NOTDB
++ * On IRQT_PROBE nothing is done.
++ ************************************************************************/
++
++ /********************************************************************
++ * TODO:
++ *
++ * Configure ack, mask, unsmask to use the right
++ * Port F GPIO registers.
++ *
++************************************************************************/
++
++static void ep93xx_vic1_mask(unsigned int irq)
++{
++ writel((1 << irq), VIC0INTENCLEAR);
++}
++
++static void ep93xx_vic1_unmask(unsigned int irq)
++{
++ writel((1 << irq), VIC0INTENABLE);
++}
++
++static struct irqchip vic1_chip = {
++ .ack = ep93xx_vic1_mask,
++ .mask = ep93xx_vic1_mask,
++ .unmask = ep93xx_vic1_unmask,
++};
++
++static void ep93xx_vic2_mask(unsigned int irq)
++{
++ writel((1 << (irq - 32)), VIC1INTENCLEAR);
++}
++
++static void ep93xx_vic2_unmask(unsigned int irq)
++{
++ writel((1 << (irq - 32)), VIC1INTENABLE);
++}
++
++static struct irqchip vic2_chip = {
++ .ack = ep93xx_vic2_mask,
++ .mask = ep93xx_vic2_mask,
++ .unmask = ep93xx_vic2_unmask,
++};
++
++static void ep93xx_rtc_ack(unsigned int irq)
++{
++}
++
++static struct irqchip rtc_chip = {
++ .ack = ep93xx_rtc_ack,
++ .mask = ep93xx_vic2_mask,
++ .unmask = ep93xx_vic2_unmask,
++};
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++/*
++ * ack EGPIO irq's
++ * Ack only for edge triggered int's valid
++ */
++static void inline ep93xx_ack_gpio_irq(u32 irq)
++{
++ u32 irq_status;
++ u32 bit = IRQ_TO_BIT(irq);
++
++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++ /* Port A */
++ if(bit & 0xFF) {
++ irq_status = readl(GPIO_INTSTATUSA);
++ if(irq_status & bit)
++ writel(bit, GPIO_AEOI);
++ }
++
++ /* Port B */
++ if(bit & 0xFF00) {
++ irq_status = readl(GPIO_INTSTATUSB);
++ if(irq_status & (bit >> 8))
++ writel((bit >> 8), GPIO_BEOI);
++
++ }
++}
++
++/*
++ * unmask EGPIO irq's (enable)
++ */
++static void inline ep93xx_unmask_gpio_irq(u32 irq)
++{
++ u32 irq_status;
++ u32 bit = IRQ_TO_BIT(irq);
++
++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++ /* Port A */
++ if(bit & 0xFF) {
++ irq_status = readl(GPIO_AINTEN);
++ irq_status |= bit;
++ writel(irq_status, GPIO_AINTEN);
++ }
++
++ /* Port B */
++ if(bit & 0xFF00) {
++ irq_status = readl(GPIO_BINTEN);
++ irq_status |= (bit >> 8);
++ writel(irq_status, GPIO_BINTEN);
++ }
++}
++
++/*
++ * Enable debounce on EGPIO IRQ
++ */
++
++static void ep93xx_debounce_enable(u32 irq)
++{
++ u32 db_status;
++ u32 bit = IRQ_TO_BIT(irq);
++
++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++ /* Port A */
++ if (bit & 0xFF) {
++ db_status = readl(GPIO_ADB);
++ db_status |= bit ;
++ writel(db_status, GPIO_ADB);
++ }
++
++ /* Port B */
++ if (bit & 0xFF00 ) {
++ db_status = readl(GPIO_BDB);
++ db_status |= (bit >> 8) ;
++ writel(db_status, GPIO_BDB);
++ }
++
++}
++
++/*
++ * Disable debounce on EGPIO IRQ
++ */
++static void ep93xx_debounce_disable(u32 irq)
++{
++ u32 db_status;
++ u32 bit = IRQ_TO_BIT(irq);
++
++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++ /* Port A */
++ if (bit & 0xFF) {
++ db_status = readl(GPIO_ADB);
++ db_status &= ~bit ;
++ writel(db_status, GPIO_ADB);
++ }
++
++ /* Port B */
++ if (bit & 0xFF00 ) {
++ db_status = readl(GPIO_BDB);
++ db_status &= ~(bit >> 8) ;
++ writel(db_status, GPIO_BDB);
++ }
++
++}
++
++/*
++ * mask EGPIO irq's (disable)
++ */
++static void inline ep93xx_mask_gpio_irq(u32 irq)
++{
++ u32 irq_status;
++ u32 bit = IRQ_TO_BIT(irq);
++
++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++ /* Port A */
++ if(bit & 0xFF) {
++ irq_status = readl(GPIO_AINTEN);
++ irq_status &= ~bit;
++ writel(irq_status, GPIO_AINTEN);
++ }
++
++ /* Port B */
++ if(bit & 0xFF00) {
++ irq_status = readl(GPIO_BINTEN);
++ irq_status &= ~(bit >> 8);
++ writel(irq_status, GPIO_BINTEN);
++ }
++}
++
++
++
++/*
++ * make a EGPIO to a irq input
++ */
++static int ep93xx_make_egio_to_irq(u32 bit,u32 irq)
++{
++ u32 irq_value;
++ int ret;
++
++ IRQDBG("%s irq: %d bit 0x%x\n",__FUNCTION__, irq, bit);
++
++ if(bit & 0xFF) {
++ /* Set direction to input for EGPIOA */
++ irq_value = readl(GPIO_PADDR);
++ irq_value &= ~bit;
++ if((ret = writel(irq_value, GPIO_PADDR)) != irq_value) {
++ printk("%s irq: %d cannot set direction register(GPIO_PADDR) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
++ return -EFAULT;
++ }
++ }
++ /* Port B */
++ if(bit & 0xFF00) {
++ /* Set direction to input for EGPIOB */
++ irq_value = readl(GPIO_PBDDR);
++ irq_value &= ~(bit >> 8);
++ if((ret = writel(irq_value, GPIO_PBDDR)) != irq_value) {
++ printk("%s irq: %d cannot set direction register(GPIO_PBDDR) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
++ return -EFAULT;
++ }
++ }
++
++ return 0;
++}
++
++/*
++ * make a EGPIO edge/level sensitive
++ */
++static int ep93xx_make_egio_sensitive(u32 bit, unsigned int flags,u32 irq)
++{
++ u32 irq_value;
++ int ret;
++
++ /* PORT A */
++ if(bit & 0xFF) {
++ /* Enable edge/level sensitive IRQ on EGPIO PORT A */
++ irq_value = readl(GPIO_AINTTYPE1);
++ if(flags && 1)
++ irq_value |= bit;
++ else
++ irq_value &= ~bit;
++ if((ret = writel(irq_value, GPIO_AINTTYPE1)) != irq_value) {
++ printk("%s irq: %d cannot set IRQ parameter(GPIO_AINTYPE1) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
++ return -EFAULT;
++ }
++ }
++
++ /* Port B */
++ if(bit & 0xFF00) {
++ /* Enable edge/level sensitive IRQ on EGPIO PORT B */
++ irq_value = readl(GPIO_BINTTYPE1);
++ if(flags && 1)
++ irq_value |= (bit >> 8);
++ else
++ irq_value &= ~(bit >> 8);
++ if((ret = writel(irq_value, GPIO_BINTTYPE1)) != irq_value) {
++ /* printk("%s irq: %d cannot set IRQ parameter(GPIO_BINTYPE1) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret); */
++ return -EFAULT;
++ }
++ }
++
++ return 0;
++}
++
++/*
++ * make a EGPIO high/low sensitive
++ */
++static int ep93xx_make_egio_high_low_sensitive(u32 bit, unsigned int flags,u32 irq)
++{
++ u32 irq_value;
++ int ret;
++
++ /* PORT A */
++ if(bit & 0xFF) {
++ /* Enable high/low sensitive IRQ on EGPIO PORT A */
++ irq_value = readl(GPIO_AINTTYPE2);
++ if(flags && 1)
++ irq_value |= bit;
++ else
++ irq_value &= ~bit;
++ if((ret = writel(irq_value, GPIO_AINTTYPE2)) != irq_value) {
++ printk("%s irq: %d cannot set IRQ parameter(GPIO_AINTTYPE2) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
++ return -EFAULT;
++ }
++ }
++
++ /* Port B */
++ if(bit & 0xFF00) {
++ /* Enable high/low sensitive IRQ on EGPIO PORT B */
++ irq_value = readl(GPIO_BINTTYPE2);
++ if(flags && 1)
++ irq_value |= (bit >> 8);
++ else
++ irq_value &= ~(bit >> 8);
++ if((ret = writel(irq_value, GPIO_BINTTYPE2)) != irq_value)
++ {
++ printk("%s irq: %d cannot set IRQ parameter(GPIO_BINTYPE2) value 0x%x written 0x%x\n",__FUNCTION__,irq,irq_value,ret);
++ return -EFAULT;
++ }
++ }
++
++ return 0;
++}
++
++
++
++
++/*
++ * type of GPIO irq's
++ */
++static int ep93xx_gpio_demux_handler_type(unsigned int irq, unsigned int flags)
++{
++ u32 bit = IRQ_TO_BIT(irq);
++ unsigned int debounce = 0;
++
++ IRQDBG("%s irq: %d\n",__FUNCTION__,irq);
++
++ /*if (flags == IRQT_PROBE)
++ return 0;*/
++
++ if ((flags & __IRQT_RISEDGE) | (flags & __IRQT_FALEDGE) | (flags & __IRQT_LOWLVL) | (flags & __IRQT_HIGHLVL) | (flags & IRQT_DB) | (flags & IRQT_NOTDB)) {
++ if(0 != ep93xx_make_egio_to_irq(bit,irq)) {
++ printk("%s irq: %d cannot set direction register GPIO_PXDDR\n",__FUNCTION__,irq);
++ return -EINVAL;
++ } else {
++ if ((flags & IRQT_DB) | (flags & IRQT_NOTDB)) { /* To use switch structure extract debounce
++ flags from flags variable */
++ debounce = (flags & IRQT_DB) | (flags & IRQT_NOTDB);
++ flags &= ~debounce;
++ }
++ if((flags & __IRQT_RISEDGE) | (flags & __IRQT_FALEDGE)) {
++ /* Configure for edge IRQ */
++ if(0 == ep93xx_make_egio_sensitive(bit, 1,irq)) {
++ switch(flags) {
++ case __IRQT_RISEDGE:
++ if(0 != ep93xx_make_egio_high_low_sensitive(bit, 1,irq)) {
++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
++ return -EINVAL;
++ }
++ break;
++ case __IRQT_FALEDGE:
++ if(0 != ep93xx_make_egio_high_low_sensitive(bit, 0,irq)) {
++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
++ return -EINVAL;
++ }
++ break;
++ }
++
++ /* Now we set IRQ handler for edge */
++ /* set_irq_handler(irq, do_edge_IRQ); */
++ } else {
++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE1\n",__FUNCTION__,irq);
++ return -EINVAL;
++ }
++
++ } else {
++ if((flags & __IRQT_LOWLVL) | (flags & __IRQT_HIGHLVL)) {
++ /* Configure for level IRQ */
++ if(0 == ep93xx_make_egio_sensitive(bit, 0,irq)) {
++ switch(flags)
++ {
++ case __IRQT_HIGHLVL:
++ if(0 != ep93xx_make_egio_high_low_sensitive(bit, 1,irq))
++ {
++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
++ return -EINVAL;
++ }
++ break;
++ case __IRQT_LOWLVL:
++ if(0 != ep93xx_make_egio_high_low_sensitive(bit, 0,irq))
++ {
++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE2\n",__FUNCTION__,irq);
++ return -EINVAL;
++ }
++ break;
++ }
++
++ /* Now we set IRQ handler level sensitive */
++ /* set_irq_handler(irq, do_level_IRQ); */
++ } else {
++ printk("%s irq: %d cannot set sensitive register GPIO_XINTYPE1\n",__FUNCTION__,irq);
++ return -EINVAL;
++ }
++
++ }
++ }
++ }
++ /* For debounce flags handling */
++ if ((debounce & IRQT_DB) | (debounce & IRQT_NOTDB)) {
++ switch(debounce)
++ {
++ case IRQT_DB:
++ ep93xx_debounce_enable(irq);
++ break;
++ case IRQT_NOTDB:
++ ep93xx_debounce_disable(irq);
++ break;
++ }
++ }
++ } else {
++ printk("ep93xx_type_gpio_irq: IRQ:%d no flags defined\n",irq);
++ return -EINVAL;
++ }
++return 0;
++}
++
++/*
++ * GPIO call handler
++ */
++static void ep93xx_gpio_handler(unsigned int mask, unsigned int irq, struct irqdesc *desc, struct pt_regs *regs)
++{
++ IRQDBG("%s irq: %d\n",__FUNCTION__,irq);
++
++ desc = irq_desc + irq;
++
++ while (mask) {
++ if (mask & 1) {
++ IRQDBG("handling irq %d\n", irq);
++ desc->handle(irq, desc, regs);
++ }
++ irq++;
++ desc++;
++ mask >>= 1;
++ }
++
++}
++
++/*
++ * GPIO dmux handler
++ */
++static void ep93xx_gpio_demux_handler(unsigned int irq_gpio, struct irqdesc *desc, struct pt_regs *regs)
++{
++ unsigned int mask;
++ unsigned int irq = IRQ_CHAINED_GPIO(0);
++
++ /*
++ * Mask the parent IRQ.
++ */
++ ep93xx_vic2_mask(irq_gpio);
++
++ mask = readl(GPIO_INTSTATUSA) | (readl(GPIO_INTSTATUSB) << 8);
++
++ irq = IRQ_CHAINED_GPIO(0);
++ IRQDBG("%s mask: 0x%x irq: %d\n",__FUNCTION__,mask,irq);
++ ep93xx_gpio_handler(mask, irq, desc, regs);
++
++ /*
++ * Unmask the parent IRQ
++ */
++ ep93xx_vic2_unmask(irq_gpio);
++}
++
++
++static struct irqchip ep93xx_gpio_irq = {
++ .ack = ep93xx_ack_gpio_irq,
++ .mask = ep93xx_mask_gpio_irq,
++ .unmask = ep93xx_unmask_gpio_irq,
++ .set_type = ep93xx_gpio_demux_handler_type,
++};
++
++#endif
++
++
++void __init ep93xx_init_irq(void)
++{
++ unsigned int i;
++
++ /* Interrupt bits 0 and 1 are unused */
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++ for (i = 2; i < NR_GLBL_IRQS; i++) {
++#else
++ for (i = 2; i < NR_IRQS; i++) {
++#endif
++ if(i < 32){
++ /* Interrupts below 32 belong to VIC1 */
++ set_irq_handler(i, do_level_IRQ);
++ set_irq_chip(i, &vic1_chip);
++ set_irq_flags(i, IRQF_VALID);
++
++ } else {
++ if (i == IRQ_1HZ) {
++ /* 1 Hz int is edge trigered, and not ackable */
++ set_irq_handler(i, do_edge_IRQ);
++ set_irq_chip(i, &rtc_chip);
++ set_irq_flags(i, IRQF_VALID | IRQF_NOAUTOEN);
++ } else {
++ /* Interrupt 32 and above belong to VIC2 */
++ set_irq_handler(i, do_level_IRQ);
++ set_irq_chip(i, &vic2_chip);
++ set_irq_flags(i, IRQF_VALID);
++ }
++ }
++ }
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++ for (i = IRQ_CHAINED_GPIO(0) ; i <= IRQ_CHAINED_GPIO(15); i++) {
++
++ IRQDBG("%s irq: %d init \n",__FUNCTION__, i);
++
++ /* GPIO Interrupt is demux to 16 IRQs */
++ set_irq_chip(i, &ep93xx_gpio_irq);
++ set_irq_flags(i, IRQF_VALID);
++
++ if(egpio_irqs[i - NR_GLBL_IRQS].enable == 1) {
++ set_irq_handler(i, do_level_IRQ);
++ set_irq_type(i, egpio_irqs[i - NR_GLBL_IRQS].flags);
++ } else {
++ set_irq_handler(i, do_edge_IRQ);
++ }
++ }
++ set_irq_chained_handler(IRQ_GPIO, ep93xx_gpio_demux_handler);
++#endif
++}
+diff --git a/arch/arm/mach-ep93xx/mach-acc.c b/arch/arm/mach-ep93xx/mach-acc.c
+new file mode 100644
+index 0000000..aa002ac
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-acc.c
+@@ -0,0 +1,67 @@
++/*
++ * linux/arch/arm/mach-ep93xx/acc.c
++ *
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ * Copyright (C) 2004 Ray Lehtiniemi
++ * Copyright (C) 2004 Klaus Fetscher
++ *
++ * 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/kernel.h>
++#include <linux/init.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++
++#include <asm/arch/platform.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++ the associated device drivers */
++
++static struct map_desc acc_io_desc[] __initdata = {
++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE },
++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE },
++};
++
++static void __init acc_map_io(void)
++{
++ iotable_init(acc_io_desc, ARRAY_SIZE(acc_io_desc));
++}
++
++static void __init acc_init(void)
++{
++}
++
++MACHINE_START(ACC, "acc")
++ /* Maintainer HiFish */
++ .phys_ram = SDRAM_START,
++ .phys_io = 0x80000000,
++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
++ .boot_params = (SDRAM_START + 0x00000100),
++
++ .map_io = acc_map_io,
++ .init_irq = ep93xx_init_irq,
++ .init_machine = acc_init,
++ .timer = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-adssphere.c b/arch/arm/mach-ep93xx/mach-adssphere.c
+new file mode 100644
+index 0000000..2cbf5ca
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-adssphere.c
+@@ -0,0 +1,281 @@
++/*
++ * linux/arch/arm/mach-ep93xx/adssphere.c
++ *
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ * Copyright (C) 2004 Ray Lehtiniemi
++ * Copyright (C) 2005 Robert Whaley, ADS
++ *
++ * 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/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/platform_device.h>
++#include <linux/fb.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/arch/adssphere.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++ the associated device drivers */
++
++static struct map_desc adssphere_io_desc[] __initdata =
++{
++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE },
++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE },
++ { ADSSPHERE_BASE_VIRT, ADSSPHERE_BASE_PHYS, SZ_1M, MT_DEVICE },
++};
++
++static void __init adssphere_map_io(void)
++{
++ iotable_init(adssphere_io_desc, ARRAY_SIZE(adssphere_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++ return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++ .map_name = "cfi_probe",
++ .width = 4,
++ .init = flash_init,
++ .exit = flash_exit,
++ .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++ .start = 0x60000000,
++ .end = 0x60000000 + SZ_32M - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++ .name = "flash",
++ .id = 0,
++ .dev = {
++ .platform_data = &flash_data,
++ },
++ .num_resources = 1,
++ .resource = &cfi_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED 1
++#define LED_STATE_CLAIMED 2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_GREEN 1
++#define LED_MASK (LED_GREEN)
++
++void adssphere_leds_event(led_event_t evt)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ switch (evt) {
++ case led_start:
++ led_state = LED_STATE_ENABLED;
++ hw_led_state = LED_GREEN;
++ break;
++
++ case led_stop:
++ led_state &= ~LED_STATE_ENABLED;
++ hw_led_state = 0;
++ break;
++
++ case led_claim:
++ led_state |= LED_STATE_CLAIMED;
++ hw_led_state = LED_GREEN;
++ break;
++
++ case led_release:
++ led_state &= ~LED_STATE_CLAIMED;
++ hw_led_state = 0;
++ break;
++
++ case led_timer:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state ^= LED_GREEN;
++ break;
++
++ case led_idle_start:
++ break;
++
++ case led_idle_end:
++ break;
++
++ case led_halted:
++ break;
++
++ case led_green_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_GREEN;
++ break;
++
++ case led_green_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_GREEN;
++ break;
++
++ case led_amber_on:
++ break;
++
++ case led_amber_off:
++ break;
++
++ case led_red_on:
++ break;
++
++ case led_red_off:
++ break;
++
++ default:
++ break;
++ }
++
++ writel(0x03, GPIO_PEDDR);
++
++ if (led_state & LED_STATE_ENABLED)
++ writel(hw_led_state, GPIO_PEDR);
++ local_irq_restore(flags);
++}
++
++#endif
++
++#ifdef CONFIG_SOUND_EP93XX_AC97
++void adssphere_audio_power(int on)
++{
++ unsigned int tmp;
++
++ tmp = readb(ADSSPHERE_CR1);
++ if (on) {
++ tmp |= ADSSPHERE_CR1_AMP_ON;
++ tmp &= ~ADSSPHERE_CR1_CDC_ON;
++ } else {
++ tmp &= ~ADSSPHERE_CR1_AMP_ON;
++ tmp |= ADSSPHERE_CR1_CDC_ON;
++ }
++ writeb(tmp, ADSSPHERE_CR1);
++}
++
++#endif
++
++#ifdef CONFIG_FB_EP93XX
++void adssphere_blank(int blank_mode)
++{
++ unsigned int tmp;
++
++ switch (blank_mode) {
++ case FB_BLANK_UNBLANK:
++ case FB_BLANK_NORMAL:
++ /* turn on backlight via enable and pwm */
++ /* enable fb signals */
++ tmp = readl(ADSSPHERE_CR1);
++ tmp &= ~ADSSPHERE_CR1_PNL_ON;
++ tmp |= ADSSPHERE_CR1_PNL_EN | ADSSPHERE_CR1_BL_ON;
++ writel(tmp, ADSSPHERE_CR1);
++
++ writel(100, PWM0_TC);
++ writel(99, PWM0_DC);
++ writel(1, PWM0_EN);
++
++ break;
++
++
++ case FB_BLANK_VSYNC_SUSPEND:
++ case FB_BLANK_HSYNC_SUSPEND:
++ case FB_BLANK_POWERDOWN:
++
++ /* disable fb signals */
++ /* turn off backlight via enable and pwm */
++ tmp = readl(ADSSPHERE_CR1);
++ tmp |= ADSSPHERE_CR1_PNL_ON;
++ tmp &= ~(ADSSPHERE_CR1_PNL_EN | ADSSPHERE_CR1_BL_ON);
++ writel(tmp, ADSSPHERE_CR1);
++
++ writel(0, PWM0_EN);
++
++ break;
++ }
++}
++#endif
++
++static void __init adssphere_init (void)
++{
++#if 0
++ printk("physmap_configure\n");
++ physmap_configure(0x60000000, 0x02000000, 4, NULL);
++#endif
++ printk("platform_device_register\n");
++ platform_device_register(&cfi_flash_device);
++#ifdef CONFIG_LEDS
++ leds_event = adssphere_leds_event;
++#endif
++ leds_event(led_start);
++#ifdef CONFIG_SOUND_EP93XX_AC97
++ adssphere_audio_power(1);
++#endif
++}
++
++MACHINE_START(ADSSPHERE, "adssphere")
++ /* Maintainer: Applied Data Systems */
++ .phys_ram = SDRAM_START,
++ .phys_io = 0x80000000,
++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
++ .boot_params = (SDRAM_START + 0x00000100),
++
++ .map_io = adssphere_map_io,
++ .init_irq = ep93xx_init_irq,
++ .init_machine = adssphere_init,
++ .timer = &ep93xx_timer,
++MACHINE_END
++
+diff --git a/arch/arm/mach-ep93xx/mach-dma03.c b/arch/arm/mach-ep93xx/mach-dma03.c
+new file mode 100644
+index 0000000..2223f80
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-dma03.c
+@@ -0,0 +1,343 @@
++/*
++ * linux/arch/arm/mach-ep93xx/mach-dma03.c
++ * Copyright (C) 2005 Michael Burian
++ *
++ * based on arch/arm/mach-ep93xx/mach-edb9315.c
++ *
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ * Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#ifdef CONFIG_SERIAL_8250
++#include <linux/serial_8250.h>
++#endif
++
++#ifdef CONFIG_PARPORT_PC
++#include <linux/parport.h>
++#endif
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++#ifdef CONFIG_SERIAL_8250
++#include <asm/serial.h>
++#endif
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++#include "ep93xx_gpio_irq.h"
++#endif
++
++
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++ the associated device drivers */
++
++static struct map_desc dma03_io_desc[] __initdata = {
++ {EP93XX_AHB_BASE, __phys_to_pfn(io_v2p(EP93XX_AHB_BASE)), SZ_1M, MT_DEVICE},
++ {EP93XX_APB_BASE, __phys_to_pfn(io_v2p(EP93XX_APB_BASE)), SZ_8M, MT_DEVICE},
++#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_PARPORT_PC)
++ { 0xD0000000, __phys_to_pfn(0x70000000), SZ_4K, MT_DEVICE }, /* 2x UARTS, LPT; 16C552 */
++#endif
++};
++
++static void __init dma03_map_io(void)
++{
++ iotable_init(dma03_io_desc, ARRAY_SIZE(dma03_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++ return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++ .map_name = "cfi_probe",
++ .width = 4,
++ .init = flash_init,
++ .exit = flash_exit,
++ .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++ .start = 0x60000000,
++ .end = 0x60000000 + SZ_32M - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++ .name = "flash",
++ .dev = {
++ .platform_data = &flash_data,
++ },
++ .num_resources = 1,
++ .resource = &cfi_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED 1
++#define LED_STATE_CLAIMED 2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED 2
++#define LED_GREEN 1
++#define LED_MASK (LED_GREEN | LED_RED)
++
++void dma03_leds_event(led_event_t evt)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ switch (evt) {
++ case led_start:
++ led_state = LED_STATE_ENABLED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_stop:
++ led_state &= ~LED_STATE_ENABLED;
++ hw_led_state = 0;
++ break;
++
++ case led_claim:
++ led_state |= LED_STATE_CLAIMED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_release:
++ led_state &= ~LED_STATE_CLAIMED;
++ hw_led_state = 0;
++ break;
++
++ case led_timer:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state ^= LED_GREEN;
++ break;
++
++ case led_idle_start:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state &= ~LED_RED;
++ break;
++
++ case led_idle_end:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_halted:
++ break;
++
++ case led_green_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_GREEN;
++ break;
++
++ case led_green_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_GREEN;
++ break;
++
++ case led_amber_on:
++ break;
++
++ case led_amber_off:
++ break;
++
++ case led_red_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_red_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_RED;
++ break;
++
++ default:
++ break;
++ }
++
++ writel(0x03, GPIO_PEDDR);
++
++ if (led_state & LED_STATE_ENABLED)
++ writel(hw_led_state, GPIO_PEDR);
++
++ local_irq_restore(flags);
++}
++
++#endif
++
++
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++/* GPIO irq description
++ * IRQs are set up in arch/arm/mach-ep93xx/irq.c
++ * flags can be IRQT_RISING
++ * IRQT_FALLING
++ * IRQT_LOW
++ * IRQT_HIGH
++ * IRQT_PROBE
++ *
++ * On IRQT_PROBE nothing is done in setup irq code
++ */
++
++/* For IRQ Demux */
++
++#define DISABLED 0
++#define ENABLED 1
++struct ep93xx_egpio_irq egpio_irqs[] __initdata =
++{
++ /* EGPIO IRQ 0 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 1 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 2 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 3 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 4 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 5 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 6 */
++ { ENABLED, IRQT_HIGH }, /* OKI ML9620 CAN controller can0 */
++ /* EGPIO IRQ 7 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 8 */
++ { ENABLED, IRQT_HIGH }, /* 16C552 serial UART 1 */
++ /* EGPIO IRQ 9 */
++ { ENABLED, IRQT_HIGH }, /* 16C552 serial UART 2 */
++ /* EGPIO IRQ 10 */
++ { ENABLED, IRQT_RISING }, /* 16C552 parallel port 1 */
++ /* EGPIO IRQ 11 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 12 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 13 */
++ { ENABLED, IRQT_HIGH }, /* OKI ML9620 CAN controller can1 */
++ /* EGPIO IRQ 14 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 15 */
++ { DISABLED, IRQT_PROBE },
++};
++#endif
++
++#ifdef CONFIG_SERIAL_8250
++static struct plat_serial8250_port serial_platform_data[] = {
++ {
++ .mapbase = 0x70000008,
++ .irq = GPIO_IRQ8,
++ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SHARE_IRQ,
++ .iotype = UPIO_MEM,
++ .regshift = 0,
++ .uartclk = BASE_BAUD*16,
++ } , {
++ .mapbase = 0x70000010,
++ .irq = GPIO_IRQ9,
++ .flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP | UPF_SHARE_IRQ,
++ .iotype = UPIO_MEM,
++ .regshift = 0,
++ .uartclk = BASE_BAUD*16,
++ }, { },
++};
++
++static struct platform_device serial_device = {
++ .name = "serial8250",
++ .id = PLAT8250_DEV_PLATFORM,
++ .dev = {
++ .platform_data = serial_platform_data,
++ },
++};
++#endif
++
++static struct platform_device *devices[] __initdata = {
++ &cfi_flash_device,
++#ifdef CONFIG_SERIAL_8250
++ &serial_device,
++#endif
++};
++
++static void __init dma03_init(void)
++{
++ struct parport *port;
++ physmap_configure(0x60000000, 0x02000000, 4, NULL);
++ platform_add_devices(devices, ARRAY_SIZE(devices));
++
++#ifdef CONFIG_PARPORT_PC
++ port = parport_pc_probe_port(0xD0000020, 0, GPIO_IRQ10, 0, NULL);
++// How to register that beast without crashing?
++// if(port)
++// port = parport_register_port(0xD0000020, GPIO_IRQ10, 0, NULL); // note that passing NULL as fops arg is a bad idea(tm)
++// if(port)
++// parport_announce_port(port);
++#endif
++
++#ifdef CONFIG_LEDS
++ leds_event = dma03_leds_event;
++#endif
++ leds_event(led_start);
++}
++
++MACHINE_START(DMA03, "dma03")
++ /* Maintainer: Michael Burian */
++ .phys_ram = SDRAM_START,
++ .phys_io = 0x80000000,
++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
++ .boot_params = (SDRAM_START + 0x00000100),
++
++ .map_io = dma03_map_io,
++ .init_irq = ep93xx_init_irq,
++ .init_machine = dma03_init,
++ .timer = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-edb9301.c b/arch/arm/mach-ep93xx/mach-edb9301.c
+new file mode 100644
+index 0000000..68004e2
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-edb9301.c
+@@ -0,0 +1,219 @@
++/*
++ * linux/arch/arm/mach-ep93xx/edb9301.c
++ *
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ * Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++ the associated device drivers */
++
++static struct map_desc edb9301_io_desc[] __initdata = {
++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE },
++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE },
++};
++
++static void __init edb9301_map_io(void)
++{
++ iotable_init(edb9301_io_desc, ARRAY_SIZE(edb9301_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++ return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++ .map_name = "cfi_probe",
++ .width = 2,
++ .init = flash_init,
++ .exit = flash_exit,
++ .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++ .start = 0x60000000,
++ .end = 0x60000000 + SZ_16M - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++ .name = "flash",
++ .dev = {
++ .platform_data = &flash_data,
++ },
++ .num_resources = 1,
++ .resource = &cfi_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED 1
++#define LED_STATE_CLAIMED 2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED 2
++#define LED_GREEN 1
++#define LED_MASK (LED_GREEN | LED_RED)
++
++void edb9301_leds_event(led_event_t evt)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ switch (evt) {
++ case led_start:
++ led_state = LED_STATE_ENABLED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_stop:
++ led_state &= ~LED_STATE_ENABLED;
++ hw_led_state = 0;
++ break;
++
++ case led_claim:
++ led_state |= LED_STATE_CLAIMED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_release:
++ led_state &= ~LED_STATE_CLAIMED;
++ hw_led_state = 0;
++ break;
++
++ case led_timer:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state ^= LED_GREEN;
++ break;
++
++ case led_idle_start:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state &= ~LED_RED;
++ break;
++
++ case led_idle_end:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_halted:
++ break;
++
++ case led_green_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_GREEN;
++ break;
++
++ case led_green_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_GREEN;
++ break;
++
++ case led_amber_on:
++ break;
++
++ case led_amber_off:
++ break;
++
++ case led_red_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_red_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_RED;
++ break;
++
++ default:
++ break;
++ }
++
++ writel(0x03, GPIO_PEDDR);
++
++ if (led_state & LED_STATE_ENABLED)
++ writel(hw_led_state, GPIO_PEDR);
++
++ local_irq_restore(flags);
++}
++
++#endif
++
++static void __init edb9301_init(void)
++{
++ physmap_configure(0x60000000, 0x01000000, 2, NULL);
++ platform_device_register(&cfi_flash_device);
++#ifdef CONFIG_LEDS
++ leds_event = edb9301_leds_event;
++#endif
++ leds_event(led_start);
++}
++
++MACHINE_START(EDB9301, "edb9301")
++ /* Maintainer: Michael Burian */
++ .phys_ram = SDRAM_START,
++ .phys_io = 0x80000000,
++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
++ .boot_params = (SDRAM_START + 0x00000100),
++
++ .map_io = edb9301_map_io,
++ .init_irq = ep93xx_init_irq,
++ .init_machine = edb9301_init,
++ .timer = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-edb9302.c b/arch/arm/mach-ep93xx/mach-edb9302.c
+new file mode 100644
+index 0000000..ac74a1e
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-edb9302.c
+@@ -0,0 +1,362 @@
++/*
++ * linux/arch/arm/mach-ep93xx/edb9302.c
++ *
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ * Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++#include <asm/arch/mach-edb9302.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++ the associated device drivers */
++
++static struct map_desc edb9302_io_desc[] __initdata = {
++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE },
++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE },
++};
++
++static void __init edb9302_map_io(void)
++{
++ iotable_init(edb9302_io_desc, ARRAY_SIZE(edb9302_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++ return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++ .map_name = "cfi_probe",
++ .width = 2,
++ .init = flash_init,
++ .exit = flash_exit,
++ .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++ .start = 0x60000000,
++ .end = 0x60000000 + SZ_16M - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++ .name = "flash",
++ .dev = {
++ .platform_data = &flash_data,
++ },
++ .num_resources = 1,
++ .resource = &cfi_flash_resource,
++};
++
++/* SSP hackery */
++
++static void ssp_cs_flash(struct ssp_slave *s, int enable)
++{
++ unsigned long x = readl(GPIO_PADR);
++ if (enable)
++ x &= ~0x80;
++ else
++ x |= 0x80;
++ writel(x, GPIO_PADR);
++}
++
++struct ep93xx_ssp_slave ep93xx_ssp_flash = {
++ {
++ LIST_HEAD_INIT(ep93xx_ssp_flash.slave.list),
++ NULL,
++ 0,
++ 0,
++ 8,
++ 1,
++ ssp_cs_flash},
++ ((0 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_MOTOROLA << SSPCR0_FRF_SHIFT) |
++ SSPCR0_SPO | SSPCR0_SPH | (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)),
++ (SSPC1_SSE | SSPC1_RORIE),
++ 2
++};
++
++EXPORT_SYMBOL(ep93xx_ssp_flash);
++
++static void ssp_cs_codec(struct ssp_slave *s, int enable)
++{
++ unsigned long x = readl(GPIO_PADR);
++ if (enable)
++ x &= ~0x40;
++ else
++ x |= 0x40;
++ writel(x, GPIO_PADR);
++}
++
++struct ep93xx_ssp_slave ep93xx_ssp_codec = {
++ {
++ LIST_HEAD_INIT(ep93xx_ssp_codec.slave.list),
++ NULL,
++ 0,
++ 0,
++ 8,
++ 1,
++ ssp_cs_codec},
++ ((31 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_TI << SSPCR0_FRF_SHIFT) |
++ (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)),
++ (SSPC1_SSE | SSPC1_RORIE),
++ 48
++};
++
++EXPORT_SYMBOL(ep93xx_ssp_codec);
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED 1
++#define LED_STATE_CLAIMED 2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED 2
++#define LED_GREEN 1
++#define LED_MASK (LED_GREEN | LED_RED)
++
++void edb9302_leds_event(led_event_t evt)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ switch (evt) {
++ case led_start:
++ led_state = LED_STATE_ENABLED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_stop:
++ led_state &= ~LED_STATE_ENABLED;
++ hw_led_state = 0;
++ break;
++
++ case led_claim:
++ led_state |= LED_STATE_CLAIMED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_release:
++ led_state &= ~LED_STATE_CLAIMED;
++ hw_led_state = 0;
++ break;
++
++ case led_timer:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state ^= LED_GREEN;
++ break;
++
++ case led_idle_start:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state &= ~LED_RED;
++ break;
++
++ case led_idle_end:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_halted:
++ break;
++
++ case led_green_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_GREEN;
++ break;
++
++ case led_green_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_GREEN;
++ break;
++
++ case led_amber_on:
++ break;
++
++ case led_amber_off:
++ break;
++
++ case led_red_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_red_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_RED;
++ break;
++
++ default:
++ break;
++ }
++
++ writel(0x03, GPIO_PEDDR);
++
++ if (led_state & LED_STATE_ENABLED)
++ writel(hw_led_state, GPIO_PEDR);
++
++ local_irq_restore(flags);
++}
++
++#endif
++
++static void __init edb9302_init_gpio(void)
++{
++ /* port A */
++ /* EGPIO0-7 */
++ writel(0xc2, GPIO_PADDR);
++ writel(0xc0, GPIO_PADR);
++
++ /* port B */
++ /* EGPIO8-15 */
++ writel(0x00, GPIO_PBDDR);
++ writel(0x00, GPIO_PBDR);
++
++ /* port C */
++ /* GPIO0 */
++ writel(0x00, GPIO_PCDDR);
++ writel(0x00, GPIO_PCDR);
++
++ /* port E */
++ /* RDLED, GRLED */
++ writel(0x03, GPIO_PEDDR);
++ writel(0x03, GPIO_PEDR);
++
++ /* port F */
++ /* GPIO5, GPIO6, GPIO7 */
++ writel(0x00, GPIO_PFDDR);
++ writel(0x00, GPIO_PFDR);
++
++ /* port G */
++ /* EECLK, EEDAT */
++ writel(0x00, GPIO_PGDDR);
++ writel(0x00, GPIO_PGDR);
++
++ /* port H */
++ /* GPIO1, GPIO2, GPIO3, GPIO4 */
++ writel(0x00, GPIO_PHDDR);
++ writel(0x00, GPIO_PHDR);
++}
++
++/* looks like this might be more generic than just edb9302... */
++int ssp_do_asymmetric(struct ep93xx_ssp_slave *ss, void *tx, int tlen, void *rx,
++ int rlen)
++{
++ struct ssp_slave *s = (struct ssp_slave *)ss;
++ int err;
++
++ if ((err = ssp_start(s)) < 0)
++ goto out1;
++
++ ssp_select(s);
++
++ if ((err = ssp_post(s, tlen, tx, NULL)) < 0)
++ goto out2;
++
++ ssp_wait(s);
++
++ if ((err = ssp_post(s, rlen, NULL, rx)) < 0)
++ goto out2;
++
++ ssp_wait(s);
++
++ out2:
++ ssp_deselect(s);
++ ssp_finish(s);
++ out1:
++ return err;
++}
++
++/* start poking at the Atmel AT25F1024 flash chip */
++void poke_flash(void)
++{
++ unsigned char rdsr[1] = { 0x05 };
++ unsigned char rdid[1] = { 0x15 };
++ unsigned char rsp[10];
++
++ ssp_do_asymmetric(&ep93xx_ssp_flash, rdsr, 1, rsp, 1);
++ printk(KERN_WARNING "RDSR returns %02x\n", rsp[0]);
++
++ ssp_do_asymmetric(&ep93xx_ssp_flash, rdid, 1, rsp, 2);
++ printk(KERN_WARNING "RDID returns %02x:%02x\n", rsp[0], rsp[1]);
++}
++
++static void __init edb9302_init(void)
++{
++ physmap_configure(0x60000000, 0x01000000, 2, NULL);
++ platform_device_register(&cfi_flash_device);
++ edb9302_init_gpio();
++#ifdef CONFIG_LEDS
++ leds_event = edb9302_leds_event;
++#endif
++ leds_event(led_start);
++ if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_flash.slave) < 0)
++ printk(KERN_ERR "EDB9302: unable to add flash slave\n");
++ if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_codec.slave) < 0)
++ printk(KERN_ERR "EDB9302: unable to add codec slave\n");
++}
++
++MACHINE_START(EDB9302, "edb9302")
++ /* Maintainer: Michael Burian */
++ .phys_ram = SDRAM_START,
++ .phys_io = 0x80000000,
++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
++ .boot_params = (SDRAM_START + 0x00000100),
++
++ .map_io = edb9302_map_io,
++ .init_irq = ep93xx_init_irq,
++ .init_machine = edb9302_init,
++ .timer = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-edb9312.c b/arch/arm/mach-ep93xx/mach-edb9312.c
+new file mode 100644
+index 0000000..e67b673
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-edb9312.c
+@@ -0,0 +1,219 @@
++/*
++ * linux/arch/arm/mach-ep93xx/edb9312.c
++ *
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ * Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++ the associated device drivers */
++
++static struct map_desc edb9312_io_desc[] __initdata = {
++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE },
++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE },
++};
++
++static void __init edb9312_map_io(void)
++{
++ iotable_init(edb9312_io_desc, ARRAY_SIZE(edb9312_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++ return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++ .map_name = "cfi_probe",
++ .width = 4,
++ .init = flash_init,
++ .exit = flash_exit,
++ .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++ .start = 0x60000000,
++ .end = 0x60000000 + SZ_32M - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++ .name = "flash",
++ .dev = {
++ .platform_data = &flash_data,
++ },
++ .num_resources = 1,
++ .resource = &cfi_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED 1
++#define LED_STATE_CLAIMED 2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED 2
++#define LED_GREEN 1
++#define LED_MASK (LED_GREEN | LED_RED)
++
++void edb9312_leds_event(led_event_t evt)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ switch (evt) {
++ case led_start:
++ led_state = LED_STATE_ENABLED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_stop:
++ led_state &= ~LED_STATE_ENABLED;
++ hw_led_state = 0;
++ break;
++
++ case led_claim:
++ led_state |= LED_STATE_CLAIMED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_release:
++ led_state &= ~LED_STATE_CLAIMED;
++ hw_led_state = 0;
++ break;
++
++ case led_timer:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state ^= LED_GREEN;
++ break;
++
++ case led_idle_start:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state &= ~LED_RED;
++ break;
++
++ case led_idle_end:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_halted:
++ break;
++
++ case led_green_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_GREEN;
++ break;
++
++ case led_green_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_GREEN;
++ break;
++
++ case led_amber_on:
++ break;
++
++ case led_amber_off:
++ break;
++
++ case led_red_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_red_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_RED;
++ break;
++
++ default:
++ break;
++ }
++
++ writel(0x03, GPIO_PEDDR);
++
++ if (led_state & LED_STATE_ENABLED)
++ writel(hw_led_state, GPIO_PEDR);
++
++ local_irq_restore(flags);
++}
++
++#endif
++
++static void __init edb9312_init(void)
++{
++ physmap_configure(0x60000000, 0x02000000, 4, NULL);
++ platform_device_register(&cfi_flash_device);
++#ifdef CONFIG_LEDS
++ leds_event = edb9312_leds_event;
++#endif
++ leds_event(led_start);
++}
++
++MACHINE_START(EDB9312, "edb9312")
++ /* Maintainer: Michael Burian */
++ .phys_ram = SDRAM_START,
++ .phys_io = 0x80000000,
++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
++ .boot_params = (SDRAM_START + 0x00000100),
++
++ .map_io = edb9312_map_io,
++ .init_irq = ep93xx_init_irq,
++ .init_machine = edb9312_init,
++ .timer = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-edb9315.c b/arch/arm/mach-ep93xx/mach-edb9315.c
+new file mode 100644
+index 0000000..14c680a
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-edb9315.c
+@@ -0,0 +1,219 @@
++/*
++ * linux/arch/arm/mach-ep93xx/edb9315.c
++ *
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ * (c) Copyright 2002-2003 Cirrus Logic, Inc., Austin, Tx
++ * Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++ the associated device drivers */
++
++static struct map_desc edb9315_io_desc[] __initdata = {
++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE },
++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE },
++};
++
++static void __init edb9315_map_io(void)
++{
++ iotable_init(edb9315_io_desc, ARRAY_SIZE(edb9315_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++ return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++ .map_name = "cfi_probe",
++ .width = 4,
++ .init = flash_init,
++ .exit = flash_exit,
++ .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++ .start = 0x60000000,
++ .end = 0x60000000 + SZ_32M - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++ .name = "flash",
++ .dev = {
++ .platform_data = &flash_data,
++ },
++ .num_resources = 1,
++ .resource = &cfi_flash_resource,
++};
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED 1
++#define LED_STATE_CLAIMED 2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED 2
++#define LED_GREEN 1
++#define LED_MASK (LED_GREEN | LED_RED)
++
++void edb9315_leds_event(led_event_t evt)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ switch (evt) {
++ case led_start:
++ led_state = LED_STATE_ENABLED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_stop:
++ led_state &= ~LED_STATE_ENABLED;
++ hw_led_state = 0;
++ break;
++
++ case led_claim:
++ led_state |= LED_STATE_CLAIMED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_release:
++ led_state &= ~LED_STATE_CLAIMED;
++ hw_led_state = 0;
++ break;
++
++ case led_timer:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state ^= LED_GREEN;
++ break;
++
++ case led_idle_start:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state &= ~LED_RED;
++ break;
++
++ case led_idle_end:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_halted:
++ break;
++
++ case led_green_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_GREEN;
++ break;
++
++ case led_green_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_GREEN;
++ break;
++
++ case led_amber_on:
++ break;
++
++ case led_amber_off:
++ break;
++
++ case led_red_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_red_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_RED;
++ break;
++
++ default:
++ break;
++ }
++
++ writel(0x03, GPIO_PEDDR);
++
++ if (led_state & LED_STATE_ENABLED)
++ writel(hw_led_state, GPIO_PEDR);
++
++ local_irq_restore(flags);
++}
++
++#endif
++
++static void __init edb9315_init(void)
++{
++ physmap_configure(0x60000000, 0x02000000, 4, NULL);
++ platform_device_register(&cfi_flash_device);
++#ifdef CONFIG_LEDS
++ leds_event = edb9315_leds_event;
++#endif
++ leds_event(led_start);
++}
++
++MACHINE_START(EDB9315, "edb9315")
++ /* Maintainer: Michael Burian */
++ .phys_ram = SDRAM_START,
++ .phys_io = 0x80000000,
++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
++ .boot_params = (SDRAM_START + 0x00000100),
++
++ .map_io = edb9315_map_io,
++ .init_irq = ep93xx_init_irq,
++ .init_machine = edb9315_init,
++ .timer = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-ttml.c b/arch/arm/mach-ep93xx/mach-ttml.c
+new file mode 100644
+index 0000000..872dd01
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-ttml.c
+@@ -0,0 +1,369 @@
++/*
++ * linux/arch/arm/mach-ep93xx/mach-ttml.c
++ *
++ * Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++#include <asm/arch/mach-ttml.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++ the associated device drivers */
++
++static struct map_desc ttml_io_desc[] __initdata = {
++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE },
++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE },
++};
++
++static void __init ttml_map_io(void)
++{
++ iotable_init(ttml_io_desc, ARRAY_SIZE(ttml_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++static int flash_init(void)
++{
++ return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++ .map_name = "cfi_probe",
++ .width = 2,
++ .init = flash_init,
++ .exit = flash_exit,
++ .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++ .start = 0x60000000,
++ .end = 0x60000000 + SZ_16M - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++ .name = "flash",
++ .dev = {
++ .platform_data = &flash_data,
++ },
++ .num_resources = 1,
++ .resource = &cfi_flash_resource,
++};
++
++/* SSP hackery */
++
++static void ssp_cs_timicro(struct ssp_slave *s, int enable)
++{
++ unsigned long x = readl(GPIO_PBDR);
++ if (enable)
++ x &= ~0x10;
++ else
++ x |= 0x10;
++ writel(x, GPIO_PBDR);
++}
++
++struct ep93xx_ssp_slave ep93xx_ssp_micro = {
++ {
++ LIST_HEAD_INIT(ep93xx_ssp_micro.slave.list),
++ NULL,
++ 0,
++ 0,
++ 8,
++ 1,
++ ssp_cs_timicro},
++ ((31 << SSPCR0_SCR_SHIFT) | (SSPCR0_FRF_TI << SSPCR0_FRF_SHIFT) |
++ (SSPCR0_DSS_8BIT << SSPCR0_DSS_SHIFT)),
++ (SSPC1_SSE | SSPC1_RORIE),
++ 48
++};
++
++EXPORT_SYMBOL(ep93xx_ssp_micro);
++
++static void ssp_cs_expansion(struct ssp_slave *s, int enable)
++{
++ unsigned long x = readl(GPIO_PBDR);
++ if (enable)
++ x &= ~0x20;
++ else
++ x |= 0x20;
++ writel(x, GPIO_PBDR);
++}
++
++struct ep93xx_ssp_slave ep93xx_ssp_expansion = {
++ {
++ LIST_HEAD_INIT(ep93xx_ssp_expansion.slave.list),
++ NULL,
++ 0,
++ 0,
++ 8,
++ 1,
++ ssp_cs_expansion},
++ 0,
++ 0,
++ 0
++};
++
++EXPORT_SYMBOL(ep93xx_ssp_expansion);
++
++/**
++ * ssp_do_ttml - perform a single SSP transaction to the TTML micro
++ * @s: the slave
++ * @len: the number of words to transfer
++ * @tx: a buffer of @len words to clock out to slave
++ * @rx: a buffer of @len words to clock in from slave
++ *
++ * Use the SSP transaction interface to drive the TTML micro. The
++ * first byte back from the micro is the length of the reply, excluding
++ * the len and the csum bytes. @rlen and @rx had better be bigger
++ * than any reply the micro might generate.
++ */
++int ssp_do_ttml(struct ep93xx_ssp_slave *ss, void *tx, int tlen, void *rx,
++ int rlen)
++{
++ struct ssp_slave *s = (struct ssp_slave *)ss;
++ int len;
++ int err;
++
++ if ((err = ssp_start(s)) < 0)
++ goto out1;
++
++ ssp_select(s);
++
++ if ((err = ssp_post(s, tlen, tx, NULL)) < 0)
++ goto out2;
++
++ ssp_wait(s);
++
++ if ((err = ssp_post(s, 1, NULL, rx)) < 0)
++ goto out2;
++
++ ssp_wait(s);
++
++ {
++ char *b = rx;
++ len = ((b[0] >> 4) & 0x07) + 2;
++ }
++
++ if (len > rlen) {
++ printk(KERN_WARNING "SSP: rx buffer truncated\n");
++ len = rlen;
++ }
++
++ if ((err = ssp_post(s, len - 1, NULL, rx + 1)) < 0)
++ goto out2;
++
++ err = ssp_wait(s);
++
++ out2:
++ ssp_deselect(s);
++ out1:
++ ssp_finish(s);
++ return err;
++}
++
++EXPORT_SYMBOL(ssp_do_ttml);
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED 1
++#define LED_STATE_CLAIMED 2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED 2
++#define LED_GREEN 1
++#define LED_MASK (LED_GREEN | LED_RED)
++
++void ttml_leds_event(led_event_t evt)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ switch (evt) {
++ case led_start:
++ led_state = LED_STATE_ENABLED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_stop:
++ led_state &= ~LED_STATE_ENABLED;
++ hw_led_state = 0;
++ break;
++
++ case led_claim:
++ led_state |= LED_STATE_CLAIMED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_release:
++ led_state &= ~LED_STATE_CLAIMED;
++ hw_led_state = 0;
++ break;
++
++ case led_timer:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state ^= LED_GREEN;
++ break;
++
++ case led_idle_start:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state &= ~LED_RED;
++ break;
++
++ case led_idle_end:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_halted:
++ break;
++
++ case led_green_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_GREEN;
++ break;
++
++ case led_green_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_GREEN;
++ break;
++
++ case led_amber_on:
++ break;
++
++ case led_amber_off:
++ break;
++
++ case led_red_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_red_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_RED;
++ break;
++
++ default:
++ break;
++ }
++
++ writel(0x03, GPIO_PEDDR);
++
++ if (led_state & LED_STATE_ENABLED)
++ writel(hw_led_state, GPIO_PEDR);
++
++ local_irq_restore(flags);
++}
++
++#endif
++
++static void __init ttml_init_gpio(void)
++{
++ /* port A */
++ writel(0x00, GPIO_PADDR);
++
++ /* port B */
++ writel(0xf1, GPIO_PBDDR);
++ writel(0xf1, GPIO_PBDR);
++
++ /* port C */
++ writel(0x01, GPIO_PCDDR);
++ writel(0x01, GPIO_PCDR);
++
++ /* port E */
++ writel(0x03, GPIO_PEDDR);
++ writel(0x03, GPIO_PEDR);
++
++ /* port F */
++ writel(0x00, GPIO_PFDDR);
++ writel(0x00, GPIO_PFDR);
++
++ /* port G */
++ writel(0x00, GPIO_PGDDR);
++ writel(0x00, GPIO_PGDR);
++
++ /* port H */
++ writel(0x04, GPIO_PHDDR);
++ writel(0x00, GPIO_PHDR);
++}
++
++static void __init ttml_init(void)
++{
++ physmap_configure(0x60000000, 0x01000000, 2, NULL);
++ platform_device_register(&cfi_flash_device);
++ ttml_init_gpio();
++#ifdef CONFIG_LEDS
++ leds_event = ttml_leds_event;
++#endif
++ leds_event(led_start);
++
++ if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_micro.slave) < 0)
++ printk(KERN_ERR "EP93XX: unable to add micro slave\n");
++
++ if (ssp_add_slave(&ep93xx_ssp_master, &ep93xx_ssp_expansion.slave) < 0)
++ printk(KERN_ERR "EP93XX: unable to add expansion slave\n");
++
++}
++
++MACHINE_START(EDB9301, "ttml")
++ /* Maintainer: Michael Burian */
++ .phys_ram = SDRAM_START,
++ .phys_io = 0x80000000,
++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
++ .boot_params = (SDRAM_START + 0x00000100),
++
++ .map_io = ttml_map_io,
++ .init_irq = ep93xx_init_irq,
++ .init_machine = ttml_init,
++ .timer = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-zefeerdzb.c b/arch/arm/mach-ep93xx/mach-zefeerdzb.c
+new file mode 100644
+index 0000000..c224ca1
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-zefeerdzb.c
+@@ -0,0 +1,237 @@
++/*
++ * linux/arch/arm/mach-ep93xx/zefeerdzb.c
++ *
++ * Copyright (C) 2004, 2005 DAVE Srl <www.dave-tech.it>
++ *
++ * 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/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++ the associated device drivers */
++
++static struct map_desc zefeerdzb_io_desc[] __initdata = {
++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE },
++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE },
++};
++
++static void __init zefeerdzb_map_io(void)
++{
++ iotable_init(zefeerdzb_io_desc, ARRAY_SIZE(zefeerdzb_io_desc));
++}
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED 1
++#define LED_STATE_CLAIMED 2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED 2
++#define LED_GREEN 1
++#define LED_MASK (LED_GREEN | LED_RED)
++
++void zefeerdzb_leds_event(led_event_t evt)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ switch (evt) {
++ case led_start:
++ led_state = LED_STATE_ENABLED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_stop:
++ led_state &= ~LED_STATE_ENABLED;
++ hw_led_state = 0;
++ break;
++
++ case led_claim:
++ led_state |= LED_STATE_CLAIMED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_release:
++ led_state &= ~LED_STATE_CLAIMED;
++ hw_led_state = 0;
++ break;
++
++ case led_timer:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state ^= LED_GREEN;
++ break;
++
++ case led_idle_start:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state &= ~LED_RED;
++ break;
++
++ case led_idle_end:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_halted:
++ break;
++
++ case led_green_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_GREEN;
++ break;
++
++ case led_green_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_GREEN;
++ break;
++
++ case led_amber_on:
++ break;
++
++ case led_amber_off:
++ break;
++
++ case led_red_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_red_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_RED;
++ break;
++
++ default:
++ break;
++ }
++
++ writel(0x03, GPIO_PEDDR);
++
++ if (led_state & LED_STATE_ENABLED)
++ writel(hw_led_state, GPIO_PEDR);
++
++ local_irq_restore(flags);
++}
++
++#endif
++
++static void __init zefeerdzb_init(void)
++{
++ /*
++ physmap_configure(0x60000000, 0x01000000, 2, NULL);
++ platform_device_register(&cfi_flash_device);
++ */
++
++#ifdef CONFIG_LEDS
++ leds_event = zefeerdzb_leds_event;
++#endif
++ leds_event(led_start);
++}
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++#include "ep93xx_gpio_irq.h"
++#endif
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++/* GPIO irq description
++ * IRQs are set up in arch/arm/mach-ep93xx/irq.c
++ * flags can be IRQT_RISING
++ * IRQT_FALLING
++ * IRQT_LOW
++ * IRQT_HIGH
++ * IRQT_PROBE
++ *
++ * On IRQT_PROBE nothing is done in setup irq code
++ */
++
++/* For IRQ Demux */
++
++#define DISABLED 0
++#define ENABLED 1
++struct ep93xx_egpio_irq egpio_irqs[] __initdata =
++{
++ /* EGPIO IRQ 0 */
++ { DISABLED , IRQT_PROBE },
++ /* EGPIO IRQ 1 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 2 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 3 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 4 */
++ { ENABLED, IRQT_LOW }, /* CAN 0 GPIO IRQ */
++ /* EGPIO IRQ 5 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 6 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 7 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 8 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 9 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 10 */
++ { ENABLED, IRQT_LOW }, /* CAN 1 GPIO IRQ */
++ /* EGPIO IRQ 11 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 12 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 13 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 14 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 15 */
++ { DISABLED, IRQT_PROBE },
++};
++#endif
++
++MACHINE_START(ZEFEERDZB, "Zefeer DZB")
++ /* Maintainer: DAVE Srl <www.dave-tech.it> */
++ .phys_ram = SDRAM_START,
++ .phys_io = 0x80000000,
++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
++ .boot_params = (SDRAM_START + 0x00000100),
++
++ .map_io = zefeerdzb_map_io,
++ .init_irq = ep93xx_init_irq,
++ .init_machine = zefeerdzb_init,
++ .timer = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/mach-zefeerdzq.c b/arch/arm/mach-ep93xx/mach-zefeerdzq.c
+new file mode 100644
+index 0000000..4cae7a7
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/mach-zefeerdzq.c
+@@ -0,0 +1,279 @@
++/*
++ * linux/arch/arm/mach-ep93xx/zefeerdzq.c
++ *
++ * Copyright (C) 2004, 2005 DAVE Srl <www.dave-tech.it>
++ *
++ * 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/config.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/device.h>
++#include <linux/mtd/physmap.h>
++#include <linux/platform_device.h>
++
++#include <asm/mach-types.h>
++#include <asm/memory.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/sizes.h>
++#include <asm/leds.h>
++#include <asm/system.h>
++
++#include <asm/arch/platform.h>
++#include <asm/arch/regmap.h>
++
++#include <asm/mach/arch.h>
++#include <asm/mach/flash.h>
++#include <asm/mach/map.h>
++
++extern void ep93xx_init_irq(void);
++
++/* break this up into individual register blocks and map them in
++ the associated device drivers */
++
++static struct map_desc zefeerdzq_io_desc[] __initdata = {
++ { EP93XX_AHB_BASE, io_v2p(EP93XX_AHB_BASE), SZ_1M, MT_DEVICE },
++ { EP93XX_APB_BASE, io_v2p(EP93XX_APB_BASE), SZ_8M, MT_DEVICE },
++};
++
++static void __init zefeerdzq_map_io(void)
++{
++ iotable_init(zefeerdzq_io_desc, ARRAY_SIZE(zefeerdzq_io_desc));
++}
++
++/*
++ * Flash handling.
++ */
++
++/*
++static int flash_init(void)
++{
++ return 0;
++}
++
++static void flash_exit(void)
++{
++}
++
++static void flash_set_vpp(int on)
++{
++}
++
++static struct flash_platform_data flash_data = {
++ .map_name = "cfi_probe",
++ .width = 4,
++ .init = flash_init,
++ .exit = flash_exit,
++ .set_vpp = flash_set_vpp,
++};
++
++static struct resource cfi_flash_resource = {
++ .start = 0x60000000,
++ .end = 0x60000000 + SZ_32M - 1,
++ .flags = IORESOURCE_MEM,
++};
++
++static struct platform_device cfi_flash_device = {
++ .name = "ZefeerDZQ Boot Flash",
++ .dev = {
++ .platform_data = &flash_data,
++ },
++ .num_resources = 1,
++ .resource = &cfi_flash_resource,
++};
++*/
++
++#ifdef CONFIG_LEDS
++
++#define LED_STATE_ENABLED 1
++#define LED_STATE_CLAIMED 2
++
++static unsigned int led_state;
++static unsigned int hw_led_state;
++
++#define LED_RED 2
++#define LED_GREEN 1
++#define LED_MASK (LED_GREEN | LED_RED)
++
++void zefeerdzq_leds_event(led_event_t evt)
++{
++ unsigned long flags;
++
++ local_irq_save(flags);
++
++ switch (evt) {
++ case led_start:
++ led_state = LED_STATE_ENABLED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_stop:
++ led_state &= ~LED_STATE_ENABLED;
++ hw_led_state = 0;
++ break;
++
++ case led_claim:
++ led_state |= LED_STATE_CLAIMED;
++ hw_led_state = LED_RED | LED_GREEN;
++ break;
++
++ case led_release:
++ led_state &= ~LED_STATE_CLAIMED;
++ hw_led_state = 0;
++ break;
++
++ case led_timer:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state ^= LED_GREEN;
++ break;
++
++ case led_idle_start:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state &= ~LED_RED;
++ break;
++
++ case led_idle_end:
++ if (!(led_state & LED_STATE_CLAIMED))
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_halted:
++ break;
++
++ case led_green_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_GREEN;
++ break;
++
++ case led_green_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_GREEN;
++ break;
++
++ case led_amber_on:
++ break;
++
++ case led_amber_off:
++ break;
++
++ case led_red_on:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state |= LED_RED;
++ break;
++
++ case led_red_off:
++ if (led_state & LED_STATE_CLAIMED)
++ hw_led_state &= ~LED_RED;
++ break;
++
++ default:
++ break;
++ }
++
++ writel(0x03, GPIO_PEDDR);
++
++ if (led_state & LED_STATE_ENABLED)
++ writel(hw_led_state, GPIO_PEDR);
++
++ local_irq_restore(flags);
++}
++
++#endif
++
++static void __init zefeerdzq_init(void)
++{
++ /*
++ physmap_configure(0x60000000, 0x01000000, 2, NULL);
++ platform_device_register(&cfi_flash_device);
++ */
++
++#ifdef CONFIG_LEDS
++ leds_event = zefeerdzq_leds_event;
++#endif
++ leds_event(led_start);
++}
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++#include "ep93xx_gpio_irq.h"
++#endif
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++/* GPIO irq description
++ * IRQs are set up in arch/arm/mach-ep93xx/irq.c
++ * flags can be IRQT_RISING
++ * IRQT_FALLING
++ * IRQT_LOW
++ * IRQT_HIGH
++ * IRQT_PROBE
++ *
++ * On IRQT_PROBE nothing is done in setup irq code
++ */
++
++/* For IRQ Demux */
++
++#define DISABLED 0
++#define ENABLED 1
++struct ep93xx_egpio_irq egpio_irqs[] __initdata =
++{
++ /* EGPIO IRQ 0 */
++ { DISABLED , IRQT_PROBE },
++ /* EGPIO IRQ 1 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 2 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 3 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 4 */
++ { ENABLED, IRQT_LOW }, /* CAN 0 GPIO IRQ */
++ /* EGPIO IRQ 5 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 6 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 7 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 8 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 9 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 10 */
++ { ENABLED, IRQT_LOW }, /* CAN 1 GPIO IRQ */
++ /* EGPIO IRQ 11 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 12 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 13 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 14 */
++ { DISABLED, IRQT_PROBE },
++ /* EGPIO IRQ 15 */
++ { DISABLED, IRQT_PROBE },
++};
++#endif
++
++MACHINE_START(ZEFEERDZQ, "Zefeer DZQ")
++ /* Maintainer: DAVE Srl <www.dave-tech.it> */
++ .phys_ram = SDRAM_START,
++ .phys_io = 0x80000000,
++ .io_pg_offst = ((0xe0000000) >> 18) & 0xfffc,
++ .boot_params = (SDRAM_START + 0x00000100),
++
++ .map_io = zefeerdzq_map_io,
++ .init_irq = ep93xx_init_irq,
++ .init_machine = zefeerdzq_init,
++ .timer = &ep93xx_timer,
++MACHINE_END
+diff --git a/arch/arm/mach-ep93xx/ssp-cirrus.c b/arch/arm/mach-ep93xx/ssp-cirrus.c
+new file mode 100644
+index 0000000..853c6c4
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/ssp-cirrus.c
+@@ -0,0 +1,646 @@
++/*
++ * FILE: ssp.c
++ *
++ * DESCRIPTION: SSP Interface Driver Module implementation
++ *
++ * Copyright Cirrus Logic Corporation, 2001-2003. All rights reserved
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++/*
++ * This driver provides a way to read and write devices on the SSP
++ * interface.
++ *
++ * For Tx devices, EGPIO7 is used as an address pin:
++ * I2S Codec CS4228 = EGPIO7 == 1
++ * Serial Flash AT25F1024 = EGPIO7 == 0
++ */
++#include <linux/delay.h>
++#include <linux/interrupt.h>
++
++#include <asm/irq.h>
++#include <asm/semaphore.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/ssp-cirrus.h>
++
++#undef DEBUG
++/* #define DEBUG 1 */
++#ifdef DEBUG
++#define DPRINTK( x... ) printk( ##x )
++#else
++#define DPRINTK( x... )
++#endif
++
++#define EP93XX_KEY_TIMER_PERIOD_MSEC 20
++
++static int SSP_Open(enum SSPDeviceType Device, SSPDataCallback Callback);
++static int SSP_Close(int Handle);
++static int SSP_Read(int Handle, unsigned int Addr, unsigned int *pValue);
++static int SSP_Write(int Handle, unsigned int Addr, unsigned int Value);
++static int CheckHandle(int Handle);
++
++static void SetSSPtoPS2(void);
++static void SetSSPtoI2S(void);
++static int ReadIntoBuffer(void);
++
++static int SSP_Write_I2SCodec(int Handle, unsigned int RegAddr,
++ unsigned int RegValue);
++
++/*
++ * Key buffer...
++ */
++#define KEYBUF_SIZE 256
++static unsigned int uiKeyBuffer[KEYBUF_SIZE];
++
++static spinlock_t ssp_spinlock = SPIN_LOCK_UNLOCKED;
++
++enum SSPmodes {
++ SSP_MODE_UNKNOWN = 0,
++ SSP_MODE_PS2,
++ SSP_MODE_I2S,
++ SSP_MODE_FLASH,
++};
++
++static struct timer_list g_KbdTimer;
++static enum SSPmodes gSSPmode = SSP_MODE_UNKNOWN;
++static SSPDataCallback gKeyCallback = NULL;
++static int gHookedInterrupt = 0;
++
++/*
++ * Keep the last valid handle for SSP for kbd, i2s, and flash
++ */
++static int iLastValidHandle = -1;
++static int KeyboardHandle = 0;
++static int I2SHandle = 0;
++static int FlashHandle = 0;
++
++#define SSP_DEVICE_MASK 0xf0000000
++#define SSP_DEVICE_SHIFT 28
++
++SSP_DRIVER_API SSPinstance = {
++ SSP_Open,
++ SSP_Read,
++ SSP_Write,
++ SSP_Close,
++};
++
++/*
++ * The only instance of this driver.
++ */
++SSP_DRIVER_API *SSPDriver = &SSPinstance;
++
++/**
++ * SSPIrqHandler - get all of the keys out of the SPI FIFO.
++ */
++irqreturn_t SSPIrqHandler(int irq, void *dev_id, struct pt_regs *regs)
++{
++ /*
++ * Get key codes from SSP and send them to the keyboard callback.
++ */
++ ReadIntoBuffer();
++
++ /*
++ * Clear the interrupt.
++ */
++ writel(0, SSPIIR);
++ return IRQ_HANDLED;
++}
++
++/**
++ * TimerRoutine
++ *
++ * This function is called periodically to make sure that no keys are stuck in
++ * the SPI FIFO. This is necessary because the SPI only interrupts on half
++ * full FIFO which can leave up to one keyboard event in the FIFO until another
++ * key is pressed.
++ */
++static void TimerRoutine(unsigned long Data)
++{
++ int keycount;
++
++ /*
++ * Get key codes from SSP and send them to the keyboard callback.
++ */
++ keycount = ReadIntoBuffer();
++
++ /*
++ * If no keys were received, call the Data callback anyway so it can
++ * check for stuck keys.
++ */
++ if ((keycount == 0) && gKeyCallback)
++ gKeyCallback(-1);
++
++ /*
++ * Reschedule our timer in another 20 mSec.
++ */
++ g_KbdTimer.expires =
++ jiffies + MSECS_TO_JIFFIES(EP93XX_KEY_TIMER_PERIOD_MSEC);
++ add_timer(&g_KbdTimer);
++}
++
++/**
++ * HookInterrupt
++ *
++ * Requests SSP interrupt, sets up interrupt handler, sets up keyboard polling
++ * timer.
++ */
++static int HookInterrupt(void)
++{
++ if (gHookedInterrupt) {
++ printk(KERN_ERR "SSP driver interrupt already hooked\n");
++ return -1;
++ }
++
++ if (request_irq
++ (IRQ_SSPRX, SSPIrqHandler, SA_INTERRUPT, "ep93xxsspd", NULL)) {
++ printk(KERN_ERR "SSP driver failed to get IRQ handler\n");
++ return -1;
++ }
++
++ gHookedInterrupt = 1;
++
++ /*
++ * Initialize the timer that we will use to poll the SPI.
++ */
++ init_timer(&g_KbdTimer);
++ g_KbdTimer.function = TimerRoutine;
++ g_KbdTimer.data = 1;
++ g_KbdTimer.expires =
++ jiffies + MSECS_TO_JIFFIES(EP93XX_KEY_TIMER_PERIOD_MSEC);
++
++ add_timer(&g_KbdTimer);
++
++ return 0;
++}
++
++static int SSP_Open(enum SSPDeviceType Device, SSPDataCallback Callback)
++{
++ int Handle;
++
++ /*
++ * Generate a handle and pass it back.
++ *
++ * Increment the last valid handle.
++ * Check for wraparound (unlikely, but we like to be complete).
++ */
++ iLastValidHandle++;
++
++ /*
++ * If we wrapped around start over. Unlikely.
++ */
++ if ((iLastValidHandle & ~SSP_DEVICE_MASK) == 0)
++ iLastValidHandle = 1;
++
++ Handle = iLastValidHandle | (Device << SSP_DEVICE_SHIFT);
++
++ switch (Device) {
++ case PS2_KEYBOARD:
++ {
++ DPRINTK("SSP_Open - PS2_KEYBOARD\n");
++ if (KeyboardHandle)
++ return -1;
++
++ DPRINTK("Handle:%08x Callback:%08x -- Success\n",
++ Handle, (unsigned int)Callback);
++
++ KeyboardHandle = Handle;
++ /* Hook the interrupt if we have not yet. */
++ HookInterrupt();
++ SetSSPtoPS2();
++ gKeyCallback = Callback;
++
++ break;
++ }
++ case I2S_CODEC:
++ {
++ DPRINTK("SSP_Open - I2S_CODEC\n");
++ if (I2SHandle)
++ return -1;
++
++ DPRINTK("Handle:%08x Callback:%08x -- Success\n",
++ Handle, (unsigned int)Callback);
++
++ I2SHandle = Handle;
++ break;
++ }
++ case SERIAL_FLASH:
++ {
++ DPRINTK("SSP_Open - SERIAL_FLASH\n");
++ if (FlashHandle)
++ return -1;
++
++ DPRINTK("Handle:%08x Callback:%08x -- Success\n",
++ Handle, (unsigned int)Callback);
++
++ FlashHandle = Handle;
++ break;
++ }
++ default:
++ {
++ return -1;
++ }
++ }
++
++ return Handle;
++}
++
++/**
++ * SSP_Close
++ *
++ * Release that Handle!
++ */
++static int SSP_Close(int Handle)
++{
++ /*
++ * Find out which device this API was called for.
++ */
++ switch (CheckHandle(Handle)) {
++ case PS2_KEYBOARD:
++ {
++ DPRINTK("SSP_Open - PS2_KEYBOARD\n");
++ del_timer(&g_KbdTimer);
++ free_irq(IRQ_SSPRX, NULL);
++ gKeyCallback = NULL;
++ KeyboardHandle = 0;
++ gHookedInterrupt = 0;
++ break;
++ }
++ case I2S_CODEC:
++ {
++ DPRINTK("SSP_Open - I2S_CODEC\n");
++ I2SHandle = 0;
++ break;
++ }
++ case SERIAL_FLASH:
++ {
++ DPRINTK("SSP_Open - SERIAL_FLASH\n");
++ FlashHandle = 0;
++ break;
++ }
++ default:
++ {
++ return -1;
++ }
++ }
++ return 0;
++}
++
++static int SSP_Read(int Handle, unsigned int Addr, unsigned int *pValue)
++{
++ DPRINTK("SSP_Read\n");
++ return 0;
++}
++
++static int SSP_Write(int Handle, unsigned int Addr, unsigned int Value)
++{
++ int iRet = 0;
++ /* DPRINTK("SSP_Write - Handle:0x%08x Addr:0x%08x Value:0x%08x\n",
++ Handle, Addr, Value ); */
++
++ /*
++ * Find out which device this API was called for.
++ */
++ switch (CheckHandle(Handle)) {
++ case PS2_KEYBOARD:
++ {
++ break;
++ }
++ case I2S_CODEC:
++ {
++ iRet = SSP_Write_I2SCodec(Handle, Addr, Value);
++ break;
++ }
++ case SERIAL_FLASH:
++ {
++ break;
++ }
++ default:
++ {
++ return -1;
++ }
++ }
++
++ return iRet;
++}
++
++static void SetSSPtoPS2(void)
++{
++ unsigned int uiRegTemp;
++
++ if (gSSPmode == SSP_MODE_PS2)
++ return;
++
++ /*
++ * Disable the SSP, disable interrupts
++ */
++ writel(0, SSPCR1);
++
++ /*
++ * It takes almost a millisecond for a key to come in so
++ * make sure we have completed all transactions.
++ */
++ mdelay(1);
++
++ /*
++ * Set EGPIO7 to disable EEPROM device on EDB9312.
++ */
++ uiRegTemp = readl(GPIO_PADDR);
++ writel(uiRegTemp | 0x80, GPIO_PADDR);
++
++ uiRegTemp = readl(GPIO_PADR);
++ writel(uiRegTemp | 0x80, GPIO_PADR);
++
++ /*
++ * Still haven't enabled the keyboard. So anything in
++ * the rx fifo is garbage. Time to take out the trash.
++ */
++ while (readl(SSPSR) & SSPSR_RNE) {
++ uiRegTemp = readl(SSPDR);
++ }
++
++ /*
++ * SPICR0_SPO - SCLKOUT Polarity
++ * SPICR0_SPH - SCLKOUT Phase
++ * Motorola format, 11 bit, one start, 8 data, one bit for
++ * parity, one stop bit.
++ */
++ writel((SSPCR0_FRF_MOTOROLA | SSPCR0_SPH | SSPCR0_SPO |
++ SSPCR0_DSS_11BIT), SSPCR0);
++ /*
++ * Configure the device as a slave, Clear FIFO overrun interrupts,
++ * enable interrupts and reset the device.
++ */
++ writel((SSPC1_MS | SSPC1_RIE | SSPC1_SOD), SSPCR1);
++ writel(0, SSPIIR);
++ writel((SSPC1_MS | SSPC1_RIE | SSPC1_SOD | SSPC1_SSE),
++ SSPCR1);
++
++ /*
++ * Configure EGPIO pins 12 and 14 as outputs because they are used
++ * as buffer enables for the SPI interface to the ps2 keyboard.
++ * Clear EGPIO pins 12 and 14, this will enable the SPI keyboard.
++ */
++ uiRegTemp = readl(GPIO_PBDDR);
++ writel(uiRegTemp | 0x50, GPIO_PBDDR);
++
++ uiRegTemp = readl(GPIO_PBDR);
++ writel(uiRegTemp & ~0x50, GPIO_PBDR);
++
++ gSSPmode = SSP_MODE_PS2;
++}
++
++static void SetSSPtoI2S(void)
++{
++ unsigned int uiRegTemp;
++
++ if (gSSPmode == SSP_MODE_I2S)
++ return;
++
++ /*
++ * Disable recieve interrupts.
++ */
++ writel((SSPC1_MS | SSPC1_SSE), SSPCR1);
++
++ /*
++ * Set GPIO pins 12 and 14, this will bring the clock line low
++ * which signals to the keyboard to buffer keystrokes.
++ * Note that EGPIO 14 is the clock line and EGPIO 12 is data line.
++ */
++ uiRegTemp = readl(GPIO_PBDR);
++ writel(0x50 | uiRegTemp, GPIO_PBDR);
++
++ /*
++ * It takes almost a millisecond for an partial keystrokes to come in.
++ * Delay to make sure we have completed all transactions.
++ */
++ mdelay(1);
++
++ /*
++ * Anything we just recieved is garbage. Time to take out the trash.
++ */
++ while (readl(SSPSR) & SSPSR_RNE) {
++ uiRegTemp = readl(SSPDR);
++ }
++
++ /*
++ * Disable the SSP and disable interrupts
++ */
++ writel(0, SSPCR1);
++
++ /*
++ * Clock will be 14.7 MHz divided by 4.
++ */
++ writel(2, SSPCPSR);
++
++ /*
++ * Configure EGPIO7 as an output and set it. This selects
++ * I2S codec as the device on the SSP output instead of
++ * the serial flash.
++ */
++ uiRegTemp = readl(GPIO_PADDR);
++ writel(uiRegTemp | 0x80, GPIO_PADDR);
++
++ uiRegTemp = readl(GPIO_PADR);
++ writel(uiRegTemp | 0x80, GPIO_PADR);
++
++ /*
++ * Motorola format, 8 bit.
++ */
++ writel((SSPCR0_SPO | SSPCR0_SPH | SSPCR0_FRF_MOTOROLA |
++ SSPCR0_DSS_8BIT), SSPCR0);
++
++ /*
++ * Configure the device as master, reenable the device.
++ */
++ writel(SSPC1_SSE, SSPCR1);
++
++ gSSPmode = SSP_MODE_I2S;
++
++ udelay(10);
++}
++
++/**
++ * CheckHandle
++ *
++ * If Handle is valid, returns 0. Otherwise it returns -1.
++ */
++static int CheckHandle(int Handle)
++{
++ int iRet;
++
++ if ((Handle != KeyboardHandle) &&
++ (Handle != I2SHandle) && (Handle != FlashHandle)) {
++ DPRINTK("OOPS! Invalid SSP Handle!\n");
++ return -1;
++ }
++
++ /*
++ * Get the SSP driver instance number from the handle.
++ */
++ iRet = (((int)Handle & SSP_DEVICE_MASK) >> SSP_DEVICE_SHIFT);
++
++#if 0
++ switch (iRet) {
++ case PS2_KEYBOARD:
++ DPRINTK("CheckHandle - valid - Keyboard\n");
++ break;
++
++ case I2S_CODEC:
++ DPRINTK("CheckHandle - valid - I2S\n");
++ break;
++
++ case SERIAL_FLASH:
++ DPRINTK("CheckHandle - valid - Keyboard\n");
++ break;
++ }
++#endif
++
++ return iRet;
++}
++
++/**
++ * ReadIntoBuffer
++ *
++ * Drains the SSP rx fifo into a buffer here. If we overflow this buffer
++ * then something's wrong.
++ */
++static int ReadIntoBuffer(void)
++{
++ unsigned int count, index, saved_count, uiRegTemp;
++
++ count = 0;
++ index = 0;
++
++ if (gSSPmode != SSP_MODE_PS2)
++ return 0;
++
++ /*
++ * This spinlock will prevent I2S from grabbing the SSP to do a
++ * write while we are using the SSP for PS2.
++ *
++ * There is a slight chance that we are in the beginning phase
++ * of doing an I2S write but the mode flag hadn't yet switched
++ * to I2S. If that happens we will end up waiting on I2S to
++ * finish a write. Not great.
++ */
++ spin_lock(&ssp_spinlock);
++
++ while (readl(SSPSR) & SSPSR_RNE) {
++ /*
++ * Read in the value from the SPI controller into
++ * the partial key buffer.
++ */
++ uiKeyBuffer[count] = readl(SSPDR);
++ if (((uiKeyBuffer[count] & 0x3fc) != 0x3e0) &&
++ ((uiKeyBuffer[count] & 0x3fc) != 0x3c0)) {
++ /*
++ * Set GPIO pins 12 and 14, this will bring the clock line low
++ * which signals to the keyboard to buffer keystrokes.
++ * Note that EGPIO 14 is the clock line and EGPIO 12 is data line.
++ */
++ uiRegTemp = readl(GPIO_PBDR);
++ writel(0x50 | uiRegTemp, GPIO_PBDR);
++
++ writel(0, SSPCR1);
++ writel((SSPC1_MS | SSPC1_RIE | SSPC1_SSE),
++ SSPCR1);
++
++ /*
++ * Clear EGPIO pins 12 and 14, this will enable the SPI keyboard.
++ */
++ uiRegTemp = readl(GPIO_PBDR);
++ writel(uiRegTemp & ~0x50, GPIO_PBDR);
++
++ count++;
++ break;
++ }
++ count++;
++ }
++
++ saved_count = count;
++ index = 0;
++ while (count) {
++ /*
++ * No callback, dump data.
++ */
++ if (gKeyCallback)
++ gKeyCallback(uiKeyBuffer[index++]);
++
++ count--;
++ }
++
++ spin_unlock(&ssp_spinlock);
++
++ return saved_count;
++}
++
++/**
++ * SSP_Write_I2SCodec
++ *
++ */
++static int SSP_Write_I2SCodec
++ (int Handle, unsigned int RegAddr, unsigned int RegValue) {
++ enum SSPmodes saved_mode;
++
++ DPRINTK("SSP_Write_I2SCodec\n");
++
++ spin_lock(&ssp_spinlock);
++
++ /*
++ * Save the SSP mode. Switch to I2S mode if we're not
++ * already in I2S mode.
++ */
++ saved_mode = gSSPmode;
++ SetSSPtoI2S();
++
++ /*
++ * Let TX fifo clear out. Poll the Transmit Fifo Empty bit.
++ */
++ while (!(readl(SSPSR) & SSPSR_TFE)) ;
++
++ /*
++ * Write the data out to the tx fifo.
++ */
++ writel(0x20, SSPDR); /* chip address for CS4228 */
++ writel((RegAddr & 0xff), SSPDR);
++ writel((RegValue & 0xff), SSPDR);
++
++ /*
++ * Let TX fifo clear out. Poll the Transmit Fifo Empty bit.
++ */
++ while (!(readl(SSPSR) & SSPSR_TFE)) ;
++
++ /*
++ * Delay to let stuff make it out of the SR before doing
++ * anthing else to the SSP. It takes 6.8 uSec to do a
++ * I2S codec register write.
++ */
++ udelay(10);
++
++ /*
++ * If we were in PS2 mode, switch back to PS2 mode.
++ * If we weren't in PS2 mode, that means we didn't compile in
++ * the PS2 keyboard support, so no need to switch to PS2 mode.
++ */
++ if (saved_mode == SSP_MODE_PS2)
++ SetSSPtoPS2();
++
++ spin_unlock(&ssp_spinlock);
++
++ return 0;
++}
+diff --git a/arch/arm/mach-ep93xx/ssp.c b/arch/arm/mach-ep93xx/ssp.c
+new file mode 100644
+index 0000000..4e1b973
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/ssp.c
+@@ -0,0 +1,246 @@
++/*
++ * linux/arch/arm/mach-ep93xx/ssp.c
++ *
++ * Generic SSP driver. This provides shared access to the SSP
++ * interface operating in master mode.
++ *
++ * Copyright (C) 2004 Ray Lehtiniemi.
++ * Copyright (C) 2004 Siconix, Inc.
++ *
++ * 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/sched.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++
++#include <asm/arch/ssp.h>
++
++/* ================================================================
++ Front End Interface
++ ================================================================ */
++
++/***
++ * ssp_add_slave - register an ssp_slave with an ssp_master
++ * @m: the master
++ * @s: the slave
++ *
++ * Grabs the frontend lock and adds slave to list.
++ */
++int ssp_add_slave(struct ssp_master *m, struct ssp_slave *s)
++{
++ if (s->master != NULL)
++ return -EBUSY;
++ down(&m->sem);
++ list_add(&s->list, &m->slave);
++ s->master = m;
++ up(&m->sem);
++ return 0;
++}
++
++EXPORT_SYMBOL(ssp_add_slave);
++
++/***
++ * ssp_remove_slave - de-register an ssp_slave from its master
++ * @m: the master
++ * @s: the slave
++ *
++ * Grabs the frontend lock and removes slave from list.
++ */
++void ssp_remove_slave(struct ssp_master *m, struct ssp_slave *s)
++{
++ if (s->master != m)
++ return;
++ down(&m->sem);
++ list_del(&s->list);
++ s->master = NULL;
++ up(&m->sem);
++}
++
++EXPORT_SYMBOL(ssp_remove_slave);
++
++/***
++ * ssp_do - perform a single SSP transaction on the slave
++ * @s: the slave
++ * @len: the number of words to transfer
++ * @tx: a buffer of @len words to clock out to slave
++ * @rx: a buffer of @len words to clock in from slave
++ *
++ * Grabs the frontend lock, configures the ssp master as required
++ * by the slave, asserts the slave devices chip select line, and
++ * schedules the backend to perform the transfer.
++ *
++ * Once the backend signals completion, the chip select is negated
++ * and the frontend lock is released.
++ *
++ * The backend will transfer @len * @s->nbytes from @tx and
++ * into @rx. Make sure your buffers are big enough! If @tx
++ * or @rx are null, then null data will be clocked in and/or out.
++ */
++int ssp_do(struct ssp_slave *s, int len, void *tx, void *rx)
++{
++ int err;
++
++ if ((err = ssp_start(s)) < 0)
++ goto out1;
++
++ ssp_select(s);
++
++ if ((err = ssp_post(s, len, tx, rx)) < 0)
++ goto out2;
++
++ err = ssp_wait(s);
++
++ out2:
++ ssp_deselect(s);
++ ssp_finish(s);
++ out1:
++ return err;
++}
++
++EXPORT_SYMBOL(ssp_do);
++
++/* ================================================================
++ Transaction Interface
++ ================================================================ */
++
++static int __ssp_txn_start(struct ssp_slave *s);
++
++/***
++ * ssp_start - Grab and configure the SSP bus (blocking)
++ * @s: the slave
++ *
++ * This call will grab and initialize the SSP bus, blocking
++ * until the bus is ready.
++ */
++int ssp_start(struct ssp_slave *s)
++{
++ down(&s->master->sem);
++ return __ssp_txn_start(s);
++}
++
++EXPORT_SYMBOL(ssp_start);
++
++/***
++ * ssp_trystart - Grab and configure the SSP bus (non-blocking)
++ * @s: the slave
++ *
++ * This call will grab and initialize the SSP bus, returning
++ * with an error if the bus is not free.
++ */
++int ssp_trystart(struct ssp_slave *s)
++{
++ if (!down_trylock(&s->master->sem))
++ return -EBUSY;
++ return __ssp_txn_start(s);
++}
++
++EXPORT_SYMBOL(ssp_trystart);
++
++static int __ssp_txn_start(struct ssp_slave *s)
++{
++ return s->master->ops->configure(s);
++}
++
++/***
++ * ssp_select - assert the slave CS line
++ * @s: the slave
++ *
++ * assert the device-specific CS line
++ */
++void ssp_select(struct ssp_slave *s)
++{
++ s->chip_select(s, 1);
++}
++
++EXPORT_SYMBOL(ssp_select);
++
++/***
++ * ssp_post - start the backend for the slave's master
++ * @s: the slave
++ *
++ * Start the backend data transfer for this master.
++ */
++int ssp_post(struct ssp_slave *s, int len, void *tx, void *rx)
++{
++ struct ssp_transfer *t;
++
++ t = &s->master->transfer;
++
++ t->size = s->nbytes;
++ t->len = len;
++ t->rlen = len;
++ t->tx = tx;
++ t->rx = rx;
++ t->c = &s->master->completion;
++ init_completion(t->c);
++
++ return s->master->ops->enable(t);
++}
++
++EXPORT_SYMBOL(ssp_post);
++
++/***
++ * ssp_wait - block until the SP transfer is complete
++ * @s: the slave
++ *
++ * block until the SP transfer is complete.
++ */
++int ssp_wait(struct ssp_slave *s)
++{
++ wait_for_completion(&s->master->completion);
++ return s->master->ops->disable();
++}
++
++EXPORT_SYMBOL(ssp_wait);
++
++/***
++ * ssp_deselect - assert the slave CS line
++ * @s: the slave
++ *
++ * negate the device-specific CS line
++ */
++void ssp_deselect(struct ssp_slave *s)
++{
++ s->chip_select(s, 0);
++}
++
++EXPORT_SYMBOL(ssp_deselect);
++
++/***
++ * ssp_finish - release the ssp bus
++ * @s: the slave
++ *
++ * Releases the frontend lock.
++ */
++void ssp_finish(struct ssp_slave *s)
++{
++ up(&s->master->sem);
++}
++
++EXPORT_SYMBOL(ssp_finish);
++
++/* ================================================================
++ Module Stuff
++ ================================================================ */
++
++int __init ssp_init(void)
++{
++ printk(KERN_INFO "Generic SSP Support version 0.1\n");
++ return 0;
++}
++
++void __exit ssp_exit(void)
++{
++}
++
++module_init(ssp_init);
++module_exit(ssp_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi");
++MODULE_DESCRIPTION("Generic SSP driver");
++MODULE_LICENSE("GPL");
+diff --git a/arch/arm/mach-ep93xx/ssp2.c b/arch/arm/mach-ep93xx/ssp2.c
+new file mode 100644
+index 0000000..6a4ff10
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/ssp2.c
+@@ -0,0 +1,354 @@
++/*
++ * linux/arch/arm/mach-ep93xx/ssp.c
++ *
++ * EP93xx SSP driver. This provides shared access to the SSP
++ * interface operating in master mode.
++ *
++ * Copyright (C) 2004 Ray Lehtiniemi.
++ * Copyright (C) 2004 Siconix, Inc.
++ *
++ * 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/errno.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/spinlock.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/hardware.h>
++
++#include <asm/arch/ssp.h>
++#include <asm/arch/ssp2.h>
++
++/* print out all chars tx, rx, and dropped */
++#define _(x...) /* printk(KERN_WARNING x); printk("\n") */
++
++/* the current transfer */
++static struct ssp_transfer *transfer;
++
++/* stupid SSP gives rx int only when rx fifo > half full :-P */
++static void do_rx_poll(void *x);
++static DECLARE_WORK(work, do_rx_poll, NULL);
++
++/* also implement a timeout in the worker, to prevent hard lockups
++ if something goes south... */
++static int timeout;
++
++/* serialize the rx irq and the work poller routines */
++static spinlock_t spinlock = SPIN_LOCK_UNLOCKED;
++
++/* ----------------- Hardware Control --------------------- */
++
++/* send a word */
++static __inline__ void x_ssp_send(__u16 dat)
++{
++ writel(dat, SSPDR);
++ _("\ttx %08x", dat);
++}
++
++/* send a word to clock the recv */
++static __inline__ void x_ssp_clock(void)
++{
++ writel(0, SSPDR);
++ _("\tt- --------");
++}
++
++/* recv a word */
++static __inline__ __u16 x_ssp_recv(void)
++{
++ unsigned long dat = readl(SSPDR);
++ _("\trx %08lx", dat);
++ return dat & 0xffff;
++}
++
++/* discard a word */
++static __inline__ void x_ssp_discard(void)
++{
++#if 1
++ unsigned long dat = readl(SSPDR);
++ _("\tr- %08lx (discard)", dat);
++#else
++ (void)readl(SSPDR);
++ _("\tr- --------");
++#endif
++}
++
++/* are there chars in the rx fifo? */
++static __inline__ int x_ssp_available(void)
++{
++ return (readl(SSPSR) & SSPSR_RNE) ? 1 : 0;
++}
++
++/* is there room in the tx fifo? */
++static __inline__ int x_ssp_has_room(void)
++{
++ return (readl(SSPSR) & SSPSR_TNF) ? 1 : 0;
++}
++
++/* is the transmitter busy? */
++static __inline__ int x_ssp_busy(void)
++{
++ return (readl(SSPSR) & SSPSR_BSY) ? 1 : 0;
++}
++
++/* flush the RX and TX fifos */
++static void x_ssp_flush(void)
++{
++ do {
++ while (x_ssp_available())
++ x_ssp_discard();
++ } while (x_ssp_busy());
++
++ /* just in case there is a race... in any event, this should be harmless */
++ x_ssp_discard();
++}
++
++/* set up all regs as required by the slave */
++static void x_ssp_configure(struct ep93xx_ssp_slave *s)
++{
++ writel(s->cr1, SSPCR1);
++ writel(s->cr0, SSPCR0);
++ writel(s->cpsr, SSPCPSR);
++ writel(s->cr1 & ~SSPC1_SSE, SSPCR1);
++ writel(s->cr1, SSPCR1);
++}
++
++/* enable chip select and all ints */
++static __inline__ void x_ssp_enable(void)
++{
++ unsigned long x = readl(SSPCR1);
++ writel(x | SSPC1_TIE | SSPC1_RIE | SSPC1_RORIE, SSPCR1);
++}
++
++/* disable chip select and all ints */
++static __inline__ void x_ssp_disable(void)
++{
++ unsigned long x = readl(SSPCR1);
++ writel(x & ~(SSPC1_TIE | SSPC1_RIE | SSPC1_RORIE), SSPCR1);
++}
++
++/* disable tx int */
++static __inline__ void x_ssp_stop_tx(void)
++{
++ unsigned long x = readl(SSPCR1);
++ writel(x & ~SSPC1_TIE, SSPCR1);
++}
++
++/* ---------------------- Master Methods ------------------------- */
++
++static int ep93xx_ssp_configure(struct ssp_slave *ss)
++{
++ struct ep93xx_ssp_slave *s = (struct ep93xx_ssp_slave *)ss;
++ _("SSP transfer");
++ x_ssp_configure(s);
++ return 0;
++}
++
++static int ep93xx_ssp_enable(struct ssp_transfer *t)
++{
++ _("{");
++ transfer = t;
++ timeout = 0;
++ schedule_delayed_work(&work, 1);
++ x_ssp_enable();
++ return 0;
++}
++
++static int ep93xx_ssp_disable(void)
++{
++ x_ssp_disable();
++ cancel_delayed_work(&work);
++ transfer = NULL;
++ _("}");
++ return 0;
++}
++
++static struct ssp_master_ops my_ops = {
++ .configure = ep93xx_ssp_configure,
++ .enable = ep93xx_ssp_enable,
++ .disable = ep93xx_ssp_disable,
++};
++
++/* ----------------- Registration Stuff FIXME ------------- */
++
++#include <linux/completion.h>
++#include <asm/types.h>
++#include <asm/semaphore.h>
++
++struct ssp_master ep93xx_ssp_master = {
++ __MUTEX_INITIALIZER(ep93xx_ssp_master.sem),
++ COMPLETION_INITIALIZER(ep93xx_ssp_master.completion),
++ LIST_HEAD_INIT(ep93xx_ssp_master.slave),
++ {
++ 0,
++ 0,
++ 0,
++ NULL,
++ NULL,
++ NULL},
++ &my_ops
++};
++
++EXPORT_SYMBOL(ep93xx_ssp_master);
++
++/* -------------------- Bottom Half ----------------------- */
++
++static void do_tx(void)
++{
++ if (transfer == NULL) {
++ printk(KERN_WARNING "Null tx transfer...\n");
++ return;
++ }
++
++ while (transfer->len != 0) {
++
++ if (!x_ssp_has_room())
++ return;
++
++ if (transfer->tx == NULL) {
++ x_ssp_clock();
++
++ } else if (transfer->size == 1) {
++ __u8 *t = transfer->tx;
++ x_ssp_send(*t);
++ transfer->tx += 1;
++
++ } else if (transfer->size == 2) {
++ __u16 *t = transfer->tx;
++ x_ssp_send(*t);
++ transfer->tx += 2;
++
++ } else if (transfer->size == 4) {
++ __u32 *t = transfer->tx;
++ x_ssp_send(*t);
++ transfer->tx += 4;
++ }
++
++ transfer->len--;
++ }
++
++ x_ssp_stop_tx();
++}
++
++static void __do_rx(void)
++{
++ if (transfer == NULL) {
++ printk(KERN_WARNING "Null rx transfer...\n");
++ return;
++ }
++
++ while (transfer->rlen != 0) {
++
++ if (!x_ssp_available())
++ return;
++
++ if (transfer->rx == NULL) {
++ x_ssp_discard();
++
++ } else if (transfer->size == 1) {
++ __u8 *t = transfer->rx;
++ *t = x_ssp_recv();
++ transfer->rx += 1;
++
++ } else if (transfer->size == 2) {
++ __u16 *t = transfer->rx;
++ *t = x_ssp_recv();
++ transfer->rx += 2;
++
++ } else if (transfer->size == 4) {
++ __u32 *t = transfer->rx;
++ *t = x_ssp_recv();
++ transfer->rx += 4;
++ }
++
++ transfer->rlen--;
++ timeout = 0;
++ }
++
++ complete(transfer->c);
++}
++
++static void do_rx(void)
++{
++ unsigned long flags;
++ spin_lock_irqsave(&spinlock, flags);
++ __do_rx();
++ spin_unlock_irqrestore(&spinlock, flags);
++}
++
++static void do_rx_poll(void *x)
++{
++ unsigned long flags;
++ spin_lock_irqsave(&spinlock, flags);
++ __do_rx();
++ timeout++;
++ if (timeout == 100) {
++ x_ssp_disable();
++ complete(transfer->c);
++ } else {
++ schedule_delayed_work(&work, 1);
++ }
++ spin_unlock_irqrestore(&spinlock, flags);
++}
++
++static irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++{
++ unsigned int status = readl(SSPIIR);
++
++ if (transfer == NULL) {
++ printk(KERN_WARNING "SSP: no active transfer\n");
++ x_ssp_flush();
++ x_ssp_disable();
++ }
++
++ if (status & SSPIIR_RORIS)
++ printk(KERN_WARNING "SSP: receiver overrun\n");
++
++ if (status & SSPIIR_TIS)
++ do_tx();
++
++ if (status & SSPIIR_RIS)
++ do_rx();
++
++ writel(0, SSPICR);
++
++ return status ? IRQ_HANDLED : IRQ_NONE;
++}
++
++/* -------------------- Module Stuff ---------------------- */
++
++int __init ep93xx_ssp_init(void)
++{
++ int i;
++
++ if (readl(SYSCON_DEVCFG) & SYSCON_DEVCFG_I2SonSSP)
++ return -ENODEV;
++
++ i = request_irq(IRQ_SSP, irq_handler, 0, "SSP", NULL);
++
++ if (i)
++ printk(KERN_ERR
++ "EP93XX: unable to grab SSP interrupt, error %d\n", i);
++
++ printk(KERN_INFO "EP93xx SSP driver version 0.1\n");
++ return 0;
++}
++
++void __exit ep93xx_ssp_exit(void)
++{
++ free_irq(IRQ_SSP, NULL);
++}
++
++module_init(ep93xx_ssp_init);
++module_exit(ep93xx_ssp_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi");
++MODULE_DESCRIPTION("EP93xx SSP driver");
++MODULE_LICENSE("GPL");
+diff --git a/arch/arm/mach-ep93xx/time.c b/arch/arm/mach-ep93xx/time.c
+new file mode 100644
+index 0000000..459a179
+--- /dev/null
++++ b/arch/arm/mach-ep93xx/time.c
+@@ -0,0 +1,40 @@
++/*
++ * linux/arch/arm/mach-ep93xx/time.c
++ *
++ * Copyright (C) 2000-2001 Deep Blue Solutions
++ *
++ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA. All rights reserved.
++ * Copyright (C) 2002-2003 Cirrus Logic, Inc.
++ *
++ * 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/sched.h>
++#include <linux/init.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++
++extern int (*set_rtc) (void);
++
++static int ep93xx_set_rtc(void)
++{
++ writel(xtime.tv_sec, RTCLR);
++ return 1;
++}
++
++static int ep93xx_rtc_init(void)
++{
++ writel(0, RTCCR);
++ writel(0, RTCEOI);
++
++ writel(xtime.tv_sec, RTCDR);
++
++ set_rtc = ep93xx_set_rtc;
++
++ return 0;
++}
++
++__initcall(ep93xx_rtc_init);
+diff --git a/arch/arm/mm/Kconfig b/arch/arm/mm/Kconfig
+index e84fdde..85c90bf 100644
+--- a/arch/arm/mm/Kconfig
++++ b/arch/arm/mm/Kconfig
+@@ -62,8 +62,8 @@ config CPU_ARM720T
+ # ARM920T
+ config CPU_ARM920T
+ bool "Support ARM920T processor" if !ARCH_S3C2410
+- depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000
+- default y if ARCH_S3C2410
++ depends on ARCH_INTEGRATOR || ARCH_S3C2410 || ARCH_IMX || ARCH_AAEC2000 || ARCH_EP93XX
++ default y if ARCH_S3C2410 || ARCH_EP93XX
+ select CPU_32v4
+ select CPU_ABRT_EV4T
+ select CPU_CACHE_V4WT
+diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
+index 8b276ee..cc8aedb 100644
+--- a/arch/arm/mm/init.c
++++ b/arch/arm/mm/init.c
+@@ -212,6 +212,10 @@ static __init void reserve_node_zero(pg_
+ if (machine_is_integrator() || machine_is_cintegrator())
+ res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
+
++ /* TBD vector table and initial stack below pg_dir */
++ if (machine_is_edb9301() || machine_is_edb9312() || machine_is_edb9315() || machine_is_acc())
++ res_size = __pa(swapper_pg_dir) - PHYS_OFFSET;
++
+ /*
+ * These should likewise go elsewhere. They pre-reserve the
+ * screen memory region at the start of main system memory.
+diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
+index 84e68cd..c4a267b 100644
+--- a/drivers/char/Kconfig
++++ b/drivers/char/Kconfig
+@@ -4,6 +4,16 @@
+
+ menu "Character devices"
+
++config TTML_DEVICES
++ tristate "TTML TripDawg system devices"
++ depends on MACH_TTML
++ default m
++ ---help---
++ If you say y or m here, you will get several character devices
++ which allow you to use the LEDs, buzzer, speedometer, and so
++ on. These devices are mapped into the 10,{240-254} range, which
++ is reserved for local devices.
++
+ config VT
+ bool "Virtual terminal" if EMBEDDED
+ select INPUT
+@@ -762,6 +772,26 @@ config EFI_RTC
+ bool "EFI Real Time Clock Services"
+ depends on IA64
+
++config EP93XX_RTC
++ bool "Cirrus EP93xx Real Time Clock support"
++ depends on ARCH_EP93XX
++ help
++ Provides EFI and legacy RTC support on the Cirrus EP93xx family of
++ devices via the /dev/rtc character node (10/135).
++
++config DS1337_RTC
++ tristate "Dallas Semiconductor DS1337 Real Time Clock /dev/rtc interface"
++ depends on I2C && EXPERIMENTAL && !EP93XX_RTC
++ select SENSORS_DS1337
++ help
++ Say Y here you have got a DS1337 real time clock on your I2C bus.
++ This here is just an interface to access it via the /dev/rtc
++ character node (10/135). All the hard work will be done
++ in the I2C driver (drivers/i2c/chips/ds1337.c).
++
++ This driver can also be built as a module. If so, the module
++ will be called ds1337glue.
++
+ config DS1302
+ tristate "DS1302 RTC support"
+ depends on M32R && (PLAT_M32700UT || PLAT_OPSPUT)
+@@ -893,6 +923,8 @@ source "drivers/char/drm/Kconfig"
+
+ source "drivers/char/pcmcia/Kconfig"
+
++source "drivers/char/can/Kconfig"
++
+ config MWAVE
+ tristate "ACP Modem (Mwave) support"
+ depends on X86
+diff --git a/drivers/char/Makefile b/drivers/char/Makefile
+index 4aeae68..579570d 100644
+--- a/drivers/char/Makefile
++++ b/drivers/char/Makefile
+@@ -9,6 +9,7 @@ FONTMAPFILE = cp437.uni
+
+ obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o
+
++obj-$(CONFIG_TTML_DEVICES) += ttml.o
+ obj-$(CONFIG_LEGACY_PTYS) += pty.o
+ obj-$(CONFIG_UNIX98_PTYS) += pty.o
+ obj-y += misc.o
+@@ -65,6 +66,8 @@ obj-$(CONFIG_SGI_IP27_RTC) += ip27-rtc.o
+ obj-$(CONFIG_DS1302) += ds1302.o
+ obj-$(CONFIG_S3C2410_RTC) += s3c2410-rtc.o
+ obj-$(CONFIG_RTC_VR41XX) += vr41xx_rtc.o
++obj-$(CONFIG_EP93XX_RTC) += ep93xx-rtc.o
++obj-$(CONFIG_DS1337_RTC) += ds1337glue.o
+ ifeq ($(CONFIG_GENERIC_NVRAM),y)
+ obj-$(CONFIG_NVRAM) += generic_nvram.o
+ else
+@@ -119,3 +122,6 @@ $(obj)/defkeymap.c $(obj)/qtronixmap.c:
+ rm $@.tmp
+
+ endif
++
++obj-$(CONFIG_CAN_BUS) += can/
++
+diff --git a/drivers/char/can/Kconfig b/drivers/char/can/Kconfig
+new file mode 100644
+index 0000000..9834c66
+--- /dev/null
++++ b/drivers/char/can/Kconfig
+@@ -0,0 +1,46 @@
++#
++# CAN bus character devices configuration
++#
++
++menu "CAN bus devices"
++
++config CAN_BUS
++ bool "CAN bus character devices"
++ help
++ If you say y here, you will get support for CAN bus
++ character device drivers.
++
++config OKI_CAN_ML9620
++ tristate "OKI ML9620 CAN BUS"
++ depends on CAN_BUS
++ help
++ If you say y or m here, you will get support for OKI ML9620
++ character device based CAN driver for one CAN bus.
++
++choice
++ prompt "OKI ML9620 configuration"
++ depends on OKI_CAN_ML9620
++ help
++ Specific configuration for OKI ML9620 configuration.
++
++config OKI_CAN_ML9620_MICRO9
++ bool "OKI ML9620 Contec Hypercontrol Micro9 configuration"
++ depends on OKI_CAN_ML9620
++ help
++ Select this if you have Contec Hypercontrol Micro9 board.
++
++config OKI_CAN_ML9620_GASSNER
++ bool "OKI ML9620 Gassner configuration"
++ help
++ Select this if you want to have Gassner specific changes.
++
++endchoice
++
++config OKI_CAN_ML9620_2DEV
++ bool "OKI ML9620 CAN BUS 2nd DEVICE"
++ depends on OKI_CAN_ML9620
++ help
++ If you say y here, you will get support for a second
++ OKI ML9620 CAN bus.
++
++endmenu
+diff --git a/drivers/char/can/Makefile b/drivers/char/can/Makefile
+new file mode 100644
+index 0000000..f9bcf2a
+--- /dev/null
++++ b/drivers/char/can/Makefile
+@@ -0,0 +1,4 @@
++#
++# Makefile for CAN BUS character devices
++#
++obj-$(CONFIG_OKI_CAN_ML9620) += oki_ml9620.o
+diff --git a/drivers/char/can/oki_ml9620.c b/drivers/char/can/oki_ml9620.c
+new file mode 100644
+index 0000000..d60cca4
+--- /dev/null
++++ b/drivers/char/can/oki_ml9620.c
+@@ -0,0 +1,1006 @@
++/*
++ * drivers/char/can/oki_ml9620_core.c
++ *
++ * OKI ML9620 CAN Controler driver
++ *
++ * Author: Manfred Gruber <manfred.gruber@contec.at>
++ *
++ * Copyright 2004 (c) Manfred Gruber
++ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H
++ * Kufstein/Austria www.contec.at
++ *
++ * This driver was written for Contec Hypercontrol Micro9 Board:
++ * 1. CAN Controller is on Hypercontrol Micro9 CPU board
++ * 2. CAN Controller is on Hypercontrol Micro9 Eval board
++ *
++ * Contec uses this driver on their Hypercontrol Micro9 boards based on
++ * Cirrus Logic EP93XX, we have changed Adr-/Databus timing to use OKI ML9620.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ *
++ */
++
++/*Versions:
++ - 0.01 Inital version Only worked CAN1
++ - 0.02 CAN1/CAN2 worked, EVAL-board and CPU-BOARD Micro9
++ - 0.03 changes from Michael Burian to correct:
++ errors, functions, adr/databus-problems - thanks a lot Michael
++ changed to correct name oki_ml9620_X and put in drivers/char/can/
++ deleted some wrong statements
++ - 0.04 Michael Burian: read/write expect/return count in bytes now, cleanups
++ - 0.05 Michael Burian: use mux'd IRQs for both devices now
++ - 0.06 Michael Burian: only queue messages when /dev/can[01] is open
++ - 0.07 Michael Burian: implement non-blocking read
++ - 0.08 Michael Burian: replace completion with waitq, implement poll support
++*/
++
++/*Todo:
++ - Baudrate over /proc configure
++ - remove potential infinite loop in write / make write return immediately
++ (no longer wait for hardware, do this in background)
++ - implement fsync to allow waiting till hardware has written, if desired
++ - implement poll for write
++ - implement buffered write
++ - use kfifo for buffering read
++ - use kfifo for buffering write
++ - look for a more elegant solution for
++*/
++
++/* Enable for debugging */
++/*#define OKI_DEBUG */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/signal.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/major.h>
++#include <linux/config.h>
++#include <linux/moduleparam.h>
++#include <linux/types.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/stddef.h> /* offsetof(), etc. */
++#include <linux/completion.h>
++#include <linux/poll.h>
++#include <linux/can/oki_ml9620_ctrl.h>
++#include <asm/segment.h>
++#include <asm/hardware.h>
++#include <asm/bitops.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/arch/regmap.h>
++#include "oki_ml9620.h"
++
++/* fops */
++static int oki_read(struct file *file, char *buf, size_t count,loff_t *ppos);
++static int oki_write(struct file *file, const char *buf, size_t count,loff_t *ppos);
++static int oki_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
++static int oki_open(struct inode *inode, struct file *file);
++static int oki_release(struct inode *inode, struct file *file);
++static unsigned int oki_poll(struct file *file, poll_table *wait);
++
++/* IRQ */
++static irqreturn_t oki_irqhandler(int irq, void *dev_id, struct pt_regs *regs);
++
++/* CAN */
++static void hw_init(struct can_device *c);
++static int set_baudrate(struct can_device *c, int baud);
++static int check_status(struct can_device *c);
++static int activate(struct can_device *c, unsigned char new_status);
++static void store_data_in_buffer(struct can_device *c, struct can_msg *data);
++
++void store_data_in_buffer(struct can_device *c, struct can_msg *data)
++{
++ /* No need to fill up the queue when nobody cares. */
++ if (atomic_read(&c->can_opened))
++ return;
++
++ DBG_OKI(KERN_INFO, "DATA Stored: ID 0x%x dlc 0x%x rtr 0x%x ext 0x%x DATA: 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",data->id,data->dlc,data->rtr,data->ext,data->data[0],data->data[1],data->data[2],data->data[3],data->data[4],data->data[5],data->data[6],data->data[7]);
++
++ if (memcpy(&c->tail->msg, data, sizeof(struct can_msg)) != NULL) {
++ c->tail->next = kmalloc(sizeof(struct recbuf), GFP_KERNEL);
++ if (c->tail->next != NULL) {
++ c->tail->next->prev = c->tail;
++ c->tail = c->tail->next;
++ /* up sema to allow read */
++ wake_up_interruptible(&c->rx_waitq);
++ return;
++ }
++ }
++}
++
++int set_baudrate(struct can_device *c, int baud)
++{
++ unsigned long v = (unsigned long)c->virt_addr_can;
++ int index = 0;
++
++ /* unlock hardware */
++ c->reg.cancont = readb(v + CANCONT);
++ c->reg.cancont |= CONT_FLAG_INIT;
++ writeb(c->reg.cancont, v + CANCONT);
++
++ c->reg.cancont = readb(v + CANCONT);
++ c->reg.cancont |= CONT_FLAG_CCE;
++ writeb(c->reg.cancont, v + CANCONT);
++
++ DBG_OUT(KERN_DEBUG, ": /dev/can%d set_baudrate %dkb\n", c->minor, baud);
++
++ /* Lookuptable baudrate => Timing array index */
++ switch (baud){
++ case 10: index = 0; break;
++ case 20: index = 1; break;
++ case 50: index = 2; break;
++ case 100: index = 3; break;
++ case 125: index = 4; break;
++ case 250: index = 5; break;
++ case 500: index = 6; break;
++ case 800: index = 7; break;
++ case 1000: index = 8; break;
++ default: index = 4; break;
++ }
++
++ /* set baudrate */
++ c->reg.canbitt[0] = bd_tbl[index].btiming0;
++ c->reg.canbitt[1] = bd_tbl[index].btiming1;
++ c->reg.canbpre = bd_tbl[index].bpre;
++ writeb(c->reg.canbitt[0], v + CANBITT0);
++ writeb(c->reg.canbitt[1], v + CANBITT1);
++ writeb(c->reg.canbpre, v + CANBPRE);
++
++ /* lock hardware */
++ c->reg.cancont = readb(v + CANCONT);
++ c->reg.cancont &= ~CONT_FLAG_CCE;
++ writeb(c->reg.cancont, v + CANCONT);
++
++ c->reg.cancont = readb(v + CANCONT);
++ c->reg.cancont &= ~CONT_FLAG_INIT;
++ writeb(c->reg.cancont, v + CANCONT);
++
++ return baud;
++}
++
++void hw_init(struct can_device *c)
++{
++ unsigned char i;
++ unsigned long v = (unsigned long)c->virt_addr_can;
++
++ spin_lock_init(&c->can_lock);
++
++ c->reg.cancont |= CONT_FLAG_INIT;
++ writeb(c->reg.cancont, v + CANCONT);
++
++ /* All Messages disabled with MsgVal = 0 */
++ c->reg.if1id[3] = 0x00;
++ writeb(c->reg.if1id[3], v + IF1ID3);
++
++ /* set, so that ID Register will get transfered */
++ c->reg.if1cmask = 0x38;
++ writeb(c->reg.if1cmask, v + IF1CMASK);
++
++ for (i = 1; i < (NUM_MSG + 1); i++) {
++ while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
++ c->reg.if1creq = i;
++ writeb(c->reg.if1creq, v + IF1CREQ);
++ }
++
++ for (i = CAN_STD_RX_BUFFER_START; i < (CAN_STD_RX_BUFFER_END + 1); i++) {
++ c->reg.if1id[3] = 0x80;
++ writeb(c->reg.if1id[3], v + IF1ID3);
++
++ c->reg.if1id[2] = 0x00;
++ writeb(c->reg.if1id[2], v + IF1ID2);
++
++ /*c->reg.if1mask[3] = 0x00; */
++ c->reg.if1mask[3] = 0x20;
++ writeb(c->reg.if1mask[3], v + IF1MASK3);
++
++ c->reg.if1mask[2] = 0x00;
++ writeb(c->reg.if1mask[2], v + IF1MASK2);
++
++ /* Transfer Controll u. ID bits */
++ c->reg.if1cmask = 0xF8;
++ writeb(c->reg.if1cmask, v + IF1CMASK);
++
++ if (i == CAN_STD_RX_BUFFER_END) {
++ c->reg.if1mcont[0] = 0x80; /* FIFO END */
++ writeb(c->reg.if1mcont[0], v + IF1MCONT0);
++ } else {
++ c->reg.if1mcont[0] = 0x00;
++ writeb(c->reg.if1mcont[0], v + IF1MCONT0);
++ }
++
++ c->reg.if1mcont[1] = 0x14; /* this MsgObj trig. Int on Rx */
++ writeb(c->reg.if1mcont[1], v + IF1MCONT1);
++
++ c->reg.if1creq = i;
++ writeb(c->reg.if1creq, v + IF1CREQ);
++
++ while ((c->reg.if1busy = readb(v + IF1BUSY) & 0x80)) ;
++ }
++
++ /* Extended Frames */
++ c->reg.if1id[3] = 0xC0;
++ writeb(c->reg.if1id[3], v + IF1ID3);
++
++ c->reg.if1id[2] = 0x00;
++ writeb(c->reg.if1id[2], v + IF1ID2);
++
++ c->reg.if1id[1] = 0x00;
++ writeb(c->reg.if1id[1], v + IF1ID1);
++
++ c->reg.if1id[0] = 0x00;
++ writeb(c->reg.if1id[0], v + IF1ID0);
++
++ c->reg.if1mask[3] = 0x00;
++ writeb(c->reg.if1mask[3], v + IF1MASK3);
++
++ c->reg.if1mask[2] = 0x00;
++ writeb(c->reg.if1mask[2], v + IF1MASK2);
++
++ c->reg.if1mask[1] = 0x00;
++ writeb(c->reg.if1mask[1], v + IF1MASK1);
++
++ c->reg.if1mask[0] = 0x00;
++ writeb(c->reg.if1mask[0], v + IF1MASK0);
++
++ /* Transfer Control and ID bits */
++ c->reg.if1cmask = 0xF8;
++ writeb(c->reg.if1cmask, v + IF1CMASK);
++
++ c->reg.if1mcont[0] = 0x80; /* EOB = 1 */
++ writeb(c->reg.if1mcont[0], v + IF1MCONT0);
++
++ c->reg.if1mcont[1] = 0x14; /* this MsgObj trig. Int on Rx */
++ writeb(c->reg.if1mcont[1], v + IF1MCONT1);
++
++ c->reg.if1creq = CAN_EXT_RX_BUFFER;
++ writeb(c->reg.if1creq, v + IF1CREQ);
++
++ /* Wait till everything has been written */
++ while ((c->reg.if1busy = readb(v + IF1BUSY) & 0x80)) ;
++
++ c->reg.cancont = readl(v + CANCONT);
++ c->reg.cancont |= CONT_FLAG_IE + CONT_FLAG_SIE + CONT_FLAG_EIE;
++ writeb(c->reg.cancont, v + CANCONT);
++
++ /*End Init */
++ c->reg.cancont = readb(v + CANCONT);
++ c->reg.cancont &= ~CONT_FLAG_INIT;
++ writeb(c->reg.cancont, v + CANCONT);
++
++ /* store baudrate default 125 kBit/sec */
++ c->baudrate = (unsigned short)set_baudrate(c, 125);
++
++ /* reset overrun counter */
++ c->overrun = 0;
++}
++
++static irqreturn_t oki_irqhandler(int irq, void *dev_id, struct pt_regs *regs)
++{
++ unsigned short int_type = 0;
++ unsigned short i;
++ unsigned char stat_reg, k;
++ struct can_msg msg;
++ struct can_device *c = dev_id;
++ unsigned long v = (unsigned long)c->virt_addr_can;
++ int minor = c->minor;
++ unsigned long flags;
++ int irq_count = 0;
++
++ spin_lock_irqsave(&c->can_lock, flags);
++
++ /*
++ * read can interrupt register1,
++ * we only want to detect if it is a status interrupt!
++ */
++ int_type += (readb(v + CANINT1) << 8);
++
++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ 0x%x occured, virt addr:0x%08x\n",minor,int_type,v);
++
++ /* STATUS IRQ */
++ if (int_type & 0x8000) {
++ c->reg.canstat = stat_reg = readb(v + CANSTAT);
++ c->reg.canstat = 0x00;
++ writeb(c->reg.canstat, v + CANSTAT);
++
++ DBG_OKI(KERN_ERR, "/dev/can%d IRQ is STATUS IRQ BSTAT is 0x%x\n",minor,stat_reg);
++
++ /*if ((stat_reg & 0xE0) == 0xE0) */
++ /* changed back to get bus off state */
++ if ((stat_reg & 0x80) == 0x80) {
++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is BUS OFF\n",minor);
++ /* set "Bus off" flag */
++ c->status |= CAN_STS_BUS_OFF;
++ /* clear flag */
++ c->status &= ~CAN_STS_TXOK;
++
++ c->last_error_code = 10;
++ } else {
++ /* clear "Bus off" flag */
++ c->status &= ~CAN_STS_BUS_OFF;
++ }
++
++ if ((stat_reg & 0x60) == 0x60) {
++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS CAN_STS_WARNING %x \n",minor,(stat_reg & 0x7));
++ c->last_error_code = (stat_reg & 0x7);
++ /* set WARNING flag */
++ c->status |= CAN_STS_WARNING;
++ } else {
++ /* clear WARNING flag */
++ c->status &= ~CAN_STS_WARNING;
++ }
++
++ /* TXOK */
++ if ((stat_reg & 0x08) == 0x08) {
++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS TXOK\n",minor);
++
++ /* clear error */
++ c->last_error_code_write = 0;
++ /* clear error --> no error */
++ c->last_error_code = 0;
++ /* clear error var for debug */
++ c->last_error_code_debug = 0;
++ }
++
++ /* ROK */
++ if ((stat_reg & 0x10) == 0x10) {
++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS IRQ RXOK\n",minor);
++
++ /* clear error --> no error */
++ c->last_error_code = 0;
++ /* clear error var for debug */
++ c->last_error_code_debug = 0;
++ }
++
++ if((c->last_error_code >= 1 && c->last_error_code <= 7) || c->last_error_code == 10){
++ if(c->last_error_code < 10 && ((stat_reg & 0x80) == 0x80) && (c->last_error_code != c->last_error_code_debug)){
++ c->last_error_code_debug = 10;
++ DBG_OUT(KERN_ERR, ": /dev/can%d Error BUS OFF, do ioctl STATUS\n",minor);
++
++ }
++
++ if (c->last_error_code != c->last_error_code_debug) {
++ c->last_error_code_debug = c->last_error_code;
++ DBG_OUT(KERN_ERR, ": /dev/can%d %s\n",minor,err[c->last_error_code]);
++ }
++
++ if (c->last_error_code > 0) {
++ /* switch off controller, warning state is higher than 1 */
++ /* so CAN message has a form error or was not */
++ /* acknwledged by other devices or we are in bus off state */
++ activate(c, CAN_STS_CNTRL_OFF);
++ }
++ goto out;
++ }
++
++ DBG_OKI(KERN_ERR, ": /dev/can%d IRQ is STATUS IRQ END \n",minor);
++ }
++
++ /* read next IRQ */
++ /* only read can interrupt register0, we don't want detect a status interrupt here! */
++ int_type = readb(v + CANINT0);
++
++ while (int_type && (irq_count++ < OKI_CAN_MAX_IRQS)) {
++ switch (int_type) {
++ case CAN_TX_BUFFER:
++ case CAN_RTX_BUFFER:
++
++ DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_TX_BUFFER/CAN_RTX_BUFFER IRQ 0x%x\n",minor,int_type);
++ while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
++
++ /* Clear Int Pnd */
++ c->reg.if1cmask = 0x08;
++ writeb(c->reg.if1cmask, v + IF1CMASK);
++
++ c->reg.if1creq = (unsigned char)int_type;
++ writeb(c->reg.if1creq, v + IF1CREQ);
++
++ CAN_DEBUG(IF1CMASK,"CAN_TX_BUFFER/CAN_RTX_BUFFER IF1CMASK");
++ CAN_DEBUG(IF1CREQ,"CAN_TX_BUFFER/CAN_RTX_BUFFER IF1CREQ");
++
++ /* Wait till everything has been written */
++ while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
++ c->status |= CAN_STS_TXOK;
++ c->tx_in_progress = 0;
++ DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_TX_BUFFER/CAN_RTX_BUFFER IRQ 0x%x END\n",minor,int_type);
++ break;
++ case CAN_STD_RX_BUFFER_START:
++ case 2:
++ case 3:
++ case 4:
++ case 5:
++ case 6:
++ case 7:
++ case 8:
++ case 9:
++ case 10:
++ case 11:
++ case CAN_STD_RX_BUFFER_END:
++ DBG_OKI(KERN_ERR, "/dev/can%d IRQ is CAN_STD_RX_BUFFER_START/CAN_STD_RX_BUFFER_END IRQ 0x%x\n",minor,int_type);
++ do {
++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
++ /* Get all unsigned chars */
++ c->reg.if2cmask = 0x3F;
++ writeb(c->reg.if2cmask, v + IF2CMASK);
++ c->reg.if2creq = (unsigned char)int_type;
++ writeb(c->reg.if2creq, v + IF2CREQ);
++
++ /* Wait till everything has been written */
++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
++ /* is NewData set? */
++ if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x80) {
++ /* Extended Frame? */
++ if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x40)
++ msg.ext = 1;
++ else
++ msg.ext = 0;
++
++ msg.dlc = ((c->reg.if2mcont[0] = readb(v + IF2MCONT0)) & 0x0F);
++ msg.id = (((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x1F) << 6);
++ msg.id += ((c->reg.if2id[2] = readb(v + IF2ID2)) >> 2);
++
++ k = (unsigned char)((msg.dlc <= 8) ? (msg.dlc) : 8);
++ for (i = 0; i < k; i++)
++ msg.data[i] = c->reg.if2data[i] = readb(v + IF2DATA0 +i);
++
++ /* Is MsgLost set? */
++ if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x40)
++ c->status |= CAN_STS_OVERRUN;
++ else
++ c->status &= ~CAN_STS_OVERRUN;
++ /* is DIR set? */
++ if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x20)
++ msg.rtr = 1;
++ else
++ msg.rtr = 0;
++ /* clear MsgLst */
++ c->reg.if2mcont[1] &= 0xBF;
++ writeb(c->reg.if2mcont[1], v + IF2MCONT1);
++ c->reg.if2cmask = 0x10;
++ writeb(c->reg.if2cmask, v + IF2CMASK);
++ c->reg.if2creq = (unsigned char)int_type;
++ writeb(c->reg.if2creq, v + IF2CREQ);
++
++ /* Wait till everything has been written */
++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
++
++ /* Store Data */
++ store_data_in_buffer(c,&msg);
++ } else {
++ /* exit while loop */
++ break;
++ }
++ int_type++;
++ }
++ while (int_type <= CAN_STD_RX_BUFFER_END);
++ DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_STD_RX_BUFFER_START/CAN_STD_RX_BUFFER_END IRQ 0x%x\n",minor,int_type);
++ break;
++ /* Extended Frames */
++ case CAN_EXT_RX_BUFFER:
++ DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_EXT_RX_BUFFER IRQ 0x%x\n",minor,int_type);
++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
++ /* Get all unsigned chars */
++ c->reg.if2cmask = 0x3F;
++ writeb(c->reg.if2cmask, v + IF2CMASK);
++ c->reg.if2creq = (unsigned char)int_type;
++ writeb(c->reg.if2creq, v + IF2CREQ);
++ /* Wait till everything has been written */
++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80) ;
++ /* is NewData set? */
++ if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x80) {
++ /* Extended Frame? */
++ if ((c->reg.if2id[3] = readb(v + IF2ID3)) & 0x40)
++ msg.ext = 1;
++ else
++ msg.ext = 0;
++
++ msg.dlc = ((c->reg.if2mcont[0] = readb(v + IF2MCONT0)) & 0x0F);
++ msg.id = c->reg.if2id[0] = readb(v + IF2ID0);
++ msg.id += ((c->reg.if2id[1] = readb(v + IF2ID1)) << 8);
++ msg.id += ((c->reg.if2id[2] = readb(v + IF2ID2)) << 16);
++ msg.id += (((c->reg.if2id[3] = readb(v + IF2ID2)) & 0x1F) << 24);
++
++ k = (unsigned char)((msg.dlc <= 8) ? (msg.dlc) : 8);
++ for (i = 0; i < k; i++)
++ msg.data[i] = c->reg.if2data[i] = readb(v + IF2DATA0 + i);
++ /* Is MsgLost set? */
++ if ((c->reg.if2mcont[1] = readb(v + IF2MCONT1)) & 0x40)
++ c->status |= CAN_STS_OVERRUN;
++ else
++ c->status &= ~CAN_STS_OVERRUN;
++
++ /* clear MsgLst */
++ c->reg.if2mcont[1] &= 0xBF;
++ writeb(c->reg.if2mcont[1], v + IF2MCONT1);
++ c->reg.if2cmask = 0x10;
++ writeb(c->reg.if2cmask, v + IF2CMASK);
++ c->reg.if2creq = (unsigned char)int_type;
++ writeb(c->reg.if2creq, v + IF2CREQ);
++
++ /* Wait till everything has been written */
++ while ((c->reg.if2busy = readb(v + IF2BUSY)) & 0x80);
++ /* Store Data */
++ store_data_in_buffer(c, &msg);
++ }
++ DBG_OKI(KERN_ERR, " /dev/can%d IRQ is CAN_EXT_RX_BUFFER IRQ 0x%x\n",minor,int_type);
++ break;
++ default:
++ DBG_OKI(KERN_ERR, " /dev/can%d IRQ is default 0x%x\n",minor,int_type);
++ goto out;
++ break;
++ }
++ /* read next IRQ */
++ /* only read can interrupt register0, we don't want detect a status interrupt here! */
++ int_type = readb(v + CANINT0);
++ } /* while */
++out:
++ spin_unlock_irqrestore(&c->can_lock, flags);
++ return IRQ_HANDLED;
++}
++
++static struct file_operations oki_fops = {
++ .owner = THIS_MODULE,
++ .read = oki_read,
++ .write = oki_write,
++ .ioctl = oki_ioctl,
++ .open = oki_open,
++ .release = oki_release,
++ .poll = oki_poll,
++};
++
++int oki_read(struct file *file, char *buf, size_t count, loff_t * ppos)
++{
++ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
++ struct can_device *c = info_can[minor];
++ int ret = 0;
++ int i, tmp;
++
++ if (count < sizeof(struct can_msg))
++ return -EINVAL;
++
++ if ((c->head == c->tail) && (file->f_flags & O_NONBLOCK))
++ return -EAGAIN;
++
++ ret = wait_event_interruptible(c->rx_waitq, c->head != c->tail);
++ if (ret)
++ return -ERESTARTSYS;
++
++ for (i = 0; i < (count / sizeof(struct can_msg)); i++) {
++ if (c->head == c->tail)
++ break;
++
++ tmp = copy_to_user(buf, &c->head->msg, sizeof(struct can_msg));
++ if (tmp > 0) {
++ printk("copy_to_user could not copy %d bytes", ret);
++ ret = -EIO;
++ } else {
++ buf += sizeof(struct can_msg);
++ ret += sizeof(struct can_msg);
++ }
++
++ c->head = c->head->next;
++ kfree(c->head->prev);
++ }
++
++ return ret;
++}
++
++int oki_write(struct file *file, const char *buf, size_t count, loff_t * ppos)
++{
++ unsigned char i; /* counter, temp var */
++ unsigned char k; /* counter */
++ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
++ struct can_device *c = info_can[minor];
++ unsigned long v = (unsigned long)c->virt_addr_can;
++ struct can_msg tmp;
++ struct can_msg *txbuf = &tmp;
++
++ if (!buf || !count)
++ return 0;
++
++ /* be stricter than in read here, require multiples of whole msgs */
++ if (count % sizeof(struct can_msg)) {
++ printk("count must be N * sizeof(struct can_msg)!\n");
++ return -EINVAL;
++ }
++
++ /*
++ * This can be removed as soon as we have implemented support for
++ * writing multiple messages
++ */
++ if (count != sizeof(struct can_msg)) {
++ printk("FIXME: support writing multiple messages at once!\n");
++ return -EINVAL;
++ }
++
++ if (0 != copy_from_user(txbuf, buf, count)) {
++ printk("%s: Error: copy from user failed!\n", __FUNCTION__);
++ return -EIO;
++ }
++
++ DBG_OKI(KERN_ERR, ": WRITE minor %d\n", c->minor);
++ DBG_OKI(KERN_ERR, ": WRITE virt 0x%x\n", c->virt_addr_can);
++ DBG_OKI(KERN_ERR, ": WRITE id %d\n", txbuf->id);
++ DBG_OKI(KERN_ERR, ": WRITE dlc %d\n", txbuf->dlc);
++ DBG_OKI(KERN_ERR, ": WRITE rtr %d\n", txbuf->rtr);
++ DBG_OKI(KERN_ERR, ": WRITE ext %d\n", txbuf->ext);
++ for (i = 0; i < 8; i++)
++ DBG_OKI(KERN_ERR, ": WRITE data[%d] %d\n", i, txbuf->data[i]);
++
++ c->reg.cancont = readb(v + CANCONT);
++
++ CAN_DEBUG(CANCONT, "CANCONT");
++
++ if ((c->reg.cancont & CONT_FLAG_INIT) == CONT_FLAG_INIT) {
++ if (c->last_error_code_write < 1) {
++ c->last_error_code_write = 1;
++ DBG_OUT(KERN_ERR, ": /dev/can%d not initalised or switched off, do ioctl: COMMAND CAN_STS_CNTRL_ON \n",minor );
++ }
++ return -EAGAIN;
++ }
++
++ /* Check the status, so we can handle warning and bus off state */
++ check_status(c);
++
++ if (c->status == CAN_STS_WARNING) {
++ if (c->last_error_code_write < 2) {
++ c->last_error_code_write = 2;
++ DBG_OUT(KERN_ERR, ": /dev/can%d is in WARNING State, do ioctl STATUS\n",minor );
++ }
++ return -EAGAIN;
++ }
++
++ if (c->status == CAN_STS_BUS_OFF) {
++ if (c->last_error_code_write < 3) {
++ c->last_error_code_write = 3;
++ DBG_OUT(KERN_ERR, ": /dev/can%d is in BUS OFF State, do ioctl STATUS\n",minor );
++ }
++ return -EAGAIN;
++ }
++
++ c->status &= ~CAN_STS_TXOK;
++
++ /* Wait till everything has been written */
++ if (c->tx_in_progress) {
++ DBG_OKI(KERN_ERR, ": WRITE CAN%d BUSY\n", minor);
++ return -EBUSY;
++ } else {
++ c->tx_in_progress = 1;
++ CAN_DEBUG(IF1BUSY, " WRITE 2 for while IF1BUSY");
++ while ((c->reg.if1busy = readb(v + IF1BUSY)) & 0x80) ;
++
++ /* set, so that ID Register will get transfered */
++ c->reg.if1cmask = 0xB7;
++ writeb(c->reg.if1cmask, v + IF1CMASK);
++ CAN_DEBUG(IF1CMASK, " WRITE 3 for while IF1CMASK");
++ }
++
++ if (txbuf->ext == 0) {
++ /* DIR and WR */
++ c->reg.if1id[3] = 0xA0;
++ c->reg.if1id[3] |= (unsigned char)((txbuf->id >> 6) & 0x1F);
++ DBG_OKI(KERN_ERR, "WRITE c->reg.if1id[3] 0x%x\n",c->reg.if1id[3]);
++ writeb(c->reg.if1id[3], v + IF1ID3);
++ CAN_DEBUG(IF1ID3, " WRITE 4 IF1ID3");
++ c->reg.if1id[2] = (unsigned char)((txbuf->id << 2) & 0xFC);
++ DBG_OKI(KERN_ERR, "WRITE c->reg.if1id[2] 0x%x\n",c->reg.if1id[2]);
++ writeb(c->reg.if1id[2], v + IF1ID2);
++ CAN_DEBUG(IF1ID2, "WRITE 4 IF1ID2");
++ } else {
++ /* extended Frame */
++ c->reg.if1id[3] = 0xE0;
++ c->reg.if1id[3] += (unsigned char)((txbuf->id >> 24) & 0x1F);
++ c->reg.if1id[2] = (unsigned char)((txbuf->id >> 16) & 0xFF);
++ c->reg.if1id[1] = (unsigned char)((txbuf->id >> 8) & 0xFF);
++ c->reg.if1id[0] = (unsigned char)(txbuf->id & 0xFF);
++ writeb(c->reg.if1id[3], v + IF1ID3);
++ CAN_DEBUG(IF1ID3, "WRITE 4 IF1ID3");
++ writeb(c->reg.if1id[2], v + IF1ID2);
++ CAN_DEBUG(IF1ID2, "WRITE 4 IF1ID2");
++ writeb(c->reg.if1id[1], v + IF1ID1);
++ CAN_DEBUG(IF1ID1, "WRITE 4 IF1ID1");
++ writeb(c->reg.if1id[0], v + IF1ID0);
++ CAN_DEBUG(IF1ID1, "WRITE 4 IF1ID1");
++ }
++
++ k = (unsigned char)(((txbuf->dlc) <= 8) ? (txbuf->dlc) : 8);
++ for (i = 0; i < k; i++) {
++ c->reg.if1data[i] = txbuf->data[i];
++ writeb(c->reg.if1data[i], v + IF1DATA0 + i);
++ DBG_OKI(KERN_ERR, ": WRITE in for data[%d] %d\n",i,txbuf->data[i]);
++ CAN_DEBUG(IF1DATA0 + i, "WRITE 4 IF1DATA0 + i");
++ }
++ /* End of Buffer (EOB) */
++
++ c->reg.if1mcont[0] = 0x80 + (txbuf->dlc & 0x0F);
++ DBG_OKI(KERN_ERR, ": WRITE 5 if1mcont[0] 0x%x\n", c->reg.if1mcont[0]);
++ writeb(c->reg.if1mcont[0], v + IF1MCONT0);
++ CAN_DEBUG(IF1MCONT0, "WRITE 5 IF1MCONT0");
++
++ if (txbuf->rtr == 1) {
++ c->reg.if1id[3] &= 0xDF;
++ DBG_OKI(KERN_ERR, ": WRITE 6 if1id[3] 0x%x\n", c->reg.if1id[3]);
++ writeb(c->reg.if1id[3], v + IF1ID3);
++ CAN_DEBUG(IF1ID3, "WRITE 6 IF1ID3");
++ /* TXIE, TXRqst and RXIE */
++ c->reg.if1mcont[1] = 0x0D;
++ DBG_OKI(KERN_ERR, ": WRITE 6 if1mcont[1] 0x%x\n",c->reg.if1mcont[1]);
++ writeb(c->reg.if1mcont[1], v + IF1MCONT1);
++ CAN_DEBUG(IF1MCONT1, "WRITE 6 IF1MCONT1");
++ c->reg.if1creq = CAN_RTX_BUFFER;
++ DBG_OKI(KERN_ERR, ": WRITE 6 if1creq 0x%x\n", c->reg.if1creq);
++ writeb(c->reg.if1creq, v + IF1CREQ);
++ CAN_DEBUG(IF1CREQ, "WRITE 6 IF1CREQ");
++ } else {
++ c->reg.if1mcont[1] = 0x09;
++ DBG_OKI(KERN_ERR, ": WRITE 6 if1mcont[1] 0x%x\n",c->reg.if1mcont[1]);
++ writeb(c->reg.if1mcont[1], v + IF1MCONT1);
++ CAN_DEBUG(IF1MCONT1, "WRITE 6 IF1MCONT1");
++ c->reg.if1creq = CAN_TX_BUFFER;
++ DBG_OKI(KERN_ERR, ": WRITE 6 if1creq 0x%x\n", c->reg.if1creq);
++ writeb(c->reg.if1creq, v + IF1CREQ);
++ CAN_DEBUG(IF1CREQ, "WRITE 6 IF1CREQ");
++ }
++ return count;
++}
++
++int oki_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
++{
++ unsigned int minor = iminor(inode);
++ struct can_device *c = info_can[minor]; /* better ideas than using globals anyone? */
++ int ret = -ENOIOCTLCMD;
++ int new_options = 0;
++ void __user *argp = (void __user *)arg;
++ int __user *p = argp;
++ int cntr_ret;
++
++ switch (cmd) {
++ case COMMAND:
++ {
++ if (get_user(new_options, p) != 0)
++ return -EFAULT;
++
++ DBG_OKI(KERN_ERR, ": IOCTL COMMAND WITH %d\n", new_options);
++ cntr_ret = activate(c, new_options);
++ if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0)
++ return 0;
++ else
++ return ret;
++
++ break;
++ }
++ case CONFIG:
++ {
++ if (get_user(new_options, p) != 0)
++ return -EFAULT;
++
++ cntr_ret = set_baudrate(c, new_options);
++ if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0)
++ return 0;
++ else
++ return ret;
++
++ break;
++ }
++ case SEND:
++ break;
++ case RECEIVE:
++ break;
++ case STATUS:
++ {
++ int cntr_ret;
++ /* Check status */
++ cntr_ret = check_status(c);
++ if ((ret = put_user(cntr_ret, (int __user *)argp)) == 0)
++ return 0;
++ else
++ return ret;
++ break;
++ }
++ default:
++ return -ENOIOCTLCMD;
++ break;
++ }
++
++ return -ENOIOCTLCMD;
++}
++
++static unsigned int oki_poll(struct file *file, poll_table * wait)
++{
++ unsigned int minor = MINOR(file->f_dentry->d_inode->i_rdev);
++ struct can_device *c = info_can[minor];
++ unsigned int mask = 0;
++
++ poll_wait(file, &c->rx_waitq, wait);
++ if (c->head != c->tail)
++ mask |= POLLIN | POLLRDNORM;
++ return mask;
++}
++
++int check_status(struct can_device *c)
++{
++ int stat_reg;
++ unsigned long v = (unsigned long)c->virt_addr_can;
++
++ stat_reg = readb(v + CANSTAT);
++ DBG_OKI(KERN_DEBUG, "check_status canstat 0x%x\n", stat_reg);
++
++ /* Bus is in "Error Passive" state */
++ if ((stat_reg & 0x20) == 0) {
++ c->status &= ~CAN_STS_WARNING;
++ c->status &= ~CAN_STS_BUS_OFF;
++ }
++
++ if ((stat_reg & 0x60) == 0x60) {
++ if (c->last_error_code != (stat_reg & 0x7)) {
++ c->last_error_code = (stat_reg & 0x7);
++ }
++ c->status |= CAN_STS_WARNING;
++ }
++
++ if ((stat_reg & 0x80) == 0x80) {
++ if (c->last_error_code < 10) {
++ c->last_error_code = 10;
++ }
++ c->status |= CAN_STS_BUS_OFF;
++ }
++
++ /* clear overrun */
++ c->status &= ~CAN_STS_OVERRUN;
++ return c->status;
++}
++
++int activate(struct can_device *c, unsigned char new_status)
++{
++ unsigned long v = (unsigned long)c->virt_addr_can;
++
++ switch (new_status) {
++ case CAN_STS_CNTRL_OFF:
++ do {
++ c->reg.cancont |= CONT_FLAG_INIT;
++ writeb(c->reg.cancont, v + CANCONT);
++ }
++ while (!((c->reg.cancont = readb(v + CANCONT)) & CONT_FLAG_INIT));
++
++ c->status |= CAN_STS_RESET;
++
++ DBG_OKI(KERN_DEBUG, " /dev/can%d activate CAN_STS_CNTRL_OFF CANCONT 0x%x\n",c->minor,c->reg.cancont);
++ break;
++ case CAN_STS_CNTRL_ON:
++ do {
++ c->reg.cancont &= ~CONT_FLAG_INIT;
++ writeb(c->reg.cancont, v + CANCONT);
++ }
++ while (((c->reg.cancont = readb(v + CANCONT)) & CONT_FLAG_INIT));
++
++ c->status &= ~CAN_STS_RESET;
++
++ DBG_OKI(KERN_DEBUG, " /dev/can%d activate CAN_STS_CNTRL_ON CANCONT 0x%x\n",c->minor,c->reg.cancont);
++ break;
++ case CAN_STS_CNTRL_SLEEP:
++ break;
++ case CAN_STS_CNTRL_AWAKE:
++ break;
++ default:
++ break;
++ }
++
++ return c->status;
++}
++
++int oki_open(struct inode *inode, struct file *file)
++{
++ unsigned int minor = iminor(inode);
++ struct can_device *c = info_can[minor]; /* better ideas than using globals anyone? */
++
++ if (!atomic_dec_and_test(&c->can_opened)) {
++ DBG_OUT(KERN_ERR, ": /dev/can%d already opened.\n", minor);
++ atomic_inc(&c->can_opened);
++ return -EBUSY;
++ }
++ return 0;
++}
++
++int oki_release(struct inode *inode, struct file *file)
++{
++ unsigned int minor = iminor(inode);
++ struct can_device *c = info_can[minor]; /* better ideas than using globals anyone? */
++
++ atomic_dec(&c->can_opened);
++ if (!atomic_inc_and_test(&c->can_opened)) {
++ DBG_OUT(KERN_ERR, ": /dev/can%d open, busy.\n", minor);
++ return -EBUSY;
++ }
++
++ atomic_inc(&c->can_opened);
++ return 0;
++}
++
++int can_register(struct can_device *c)
++{
++ atomic_set(&c->can_opened, 1);
++
++ /* map memory */
++ c->virt_addr_can = ioremap(c->phys_addr_can, c->phys_size_can);
++ if (!c->virt_addr_can) {
++ DBG_OUT(KERN_ERR, ": Unable to remap /dev/can%d memory.\n", c->minor);
++ return -ENOMEM;
++ }
++
++ DBG_OUT(KERN_INFO, ": remap /dev/can%d memory physical 0x%x to virtual 0x%x.\n",c->minor,c->phys_addr_can,c->virt_addr_can);
++
++ /* Message buffers */
++ c->tail = kzalloc(sizeof(struct recbuf), GFP_KERNEL);
++ c->head = c->tail;
++
++ /* CAN init */
++ hw_init(c);
++
++ /* waitq init */
++ init_waitqueue_head(&c->rx_waitq);
++
++ /* Install IRQ handler */
++ if(0 != request_irq(c->irq, oki_irqhandler, c->irq_flags, "OKI_CAN", (void *)c)){
++ DBG_OUT(KERN_ERR, ": /dev/can%d cannot install IRQ-handler\n",c->minor);
++ return -ENOMEM;
++ }
++
++ DBG_OUT(KERN_INFO, ": /dev/can%d IRQ-handler installed.\n", c->minor);
++
++ return 0;
++}
++
++int __init oki_init(void)
++{
++ can_register(info_can[0]);
++#ifdef CONFIG_OKI_CAN_ML9620_2DEV
++ can_register(info_can[1]);
++#endif
++
++ /* Register char device */
++ if (register_chrdev(OKI_CAN_CHAR_MAJOR, OKI_CAN_DEVICE_NAME, &oki_fops)) {
++ DBG_OUT(KERN_ERR, "Can't allocate major number %d for CAN driver.\n",OKI_CAN_CHAR_MAJOR);
++ return -EIO;
++ }
++
++ DBG_OUT(KERN_INFO, ": Version: " OKI_CAN_VERSION " registered successfully.\n");
++ /*DBG_OUT(KERN_INFO, "Installed %d IRQ handlers for %d CAN devices.\n",irq_nr,can_dev); */
++
++ printk(KERN_INFO "Contec Steuerungstechnik und Automation Ges.m.b.H\n");
++ printk(KERN_INFO "Waldeck 1 / 6330 Kufstein / Austria\n");
++
++ return 0;
++}
++
++module_init(oki_init);
++
++void unregister_can(struct can_device *c)
++{
++ DBG_OUT(KERN_INFO, ": unregister /dev/can%d .\n", c->minor);
++ free_irq(c->irq, (void *)c);
++
++ if (c->virt_addr_can != NULL) {
++ iounmap(c->virt_addr_can);
++ } else {
++ DBG_OUT(KERN_ERR, ": /dev/can%d was not mapped, skipping iounmap!\n", c->minor);
++ }
++}
++
++void __exit oki_exit(void)
++{
++ unregister_can(info_can[0]);
++#ifdef CONFIG_OKI_CAN_ML9620_2DEV
++ unregister_can(info_can[1]);
++#endif
++ unregister_chrdev(OKI_CAN_CHAR_MAJOR, OKI_CAN_DEVICE_NAME);
++}
++
++module_exit(oki_exit);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Manfred Gruber <manfred.gruber@contec.at>");
++MODULE_DESCRIPTION("OKI ML9620 CAN Driver");
+diff --git a/drivers/char/can/oki_ml9620.h b/drivers/char/can/oki_ml9620.h
+new file mode 100644
+index 0000000..f8ece1e
+--- /dev/null
++++ b/drivers/char/can/oki_ml9620.h
+@@ -0,0 +1,397 @@
++/*
++ * drivers/char/can/oki_ml9620_core.h
++ *
++ * OKI ML9620 CAN Controler driver
++ *
++ * Author: Manfred Gruber <manfred.gruber@contec.at>
++ *
++ * Copyright 2004 (c) Manfred Gruber
++ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H
++ * Kufstein/Austria www.contec.at
++ *
++ * This driver was written for Contec Hypercontrol Micro9 Board:
++ * 1. CAN Controller is on Hypercontrol Micro9 CPU board
++ * 2. CAN Controller is on Hypercontrol Micro9 Eval board
++ *
++ * Contec uses this driver on their Hypercontrol Micro9 boards based on
++ * Cirrus Logic EP93XX,we have changed Adr-/Databus timinig to use OKI ML9620.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ *
++ */
++
++#ifndef _OKI_ML9620_CORE_H_
++#define _OKI_ML9620_CORE_H_
++
++#include <linux/can/oki_ml9620_ctrl.h>
++#include <linux/kernel.h>
++
++#define OKI_CAN_CHAR_MAJOR 91
++#define OKI_CAN_DEVICE_NAME "oki_ml9260"
++#define OKI_CAN_VERSION "0.08"
++
++#define OKI_CAN_MAX_IRQS 20
++#define PHYS_SIZE_CAN 0x00000100
++
++/* Contec */
++#ifdef CONFIG_OKI_CAN_ML9620_MICRO9
++#define CAN_CLOCK_8MHZ
++#define PHYS_ADDR_CAN0 0x20000000
++#define PHYS_ADDR_CAN1 0x21000000
++#define IRQ_CAN0 GPIO_IRQ4
++#define IRQ_CAN1 GPIO_IRQ10
++#ifdef CONFIG_GENERIC_HARDIRQS
++#define IRQ_FLAGS_CAN0 (SA_INTERRUPT)
++#define IRQ_FLAGS_CAN1 (SA_INTERRUPT)
++#else
++#define IRQ_FLAGS_CAN0 (SA_INTERRUPT | SA_SHIRQ)
++#define IRQ_FLAGS_CAN1 (SA_INTERRUPT | SA_SHIRQ)
++#endif
++#endif /* CONFIG_OKI_CAN_ML9620_MICRO9 */
++
++/* Gassner */
++#ifdef CONFIG_OKI_CAN_ML9620_GASSNER
++#define CAN_CLOCK_8MHZ
++#define PHYS_ADDR_CAN0 0x10000000
++#define PHYS_ADDR_CAN1 0x30000000
++#define IRQ_CAN0 GPIO_IRQ6 /* Line EGPIO6 (multiplexed) */
++#define IRQ_CAN1 GPIO_IRQ13 /* Line EGPIO13 (multiplexed) */
++#define IRQ_FLAGS_CAN0 (SA_INTERRUPT | SA_SHIRQ)
++#define IRQ_FLAGS_CAN1 (SA_INTERRUPT | SA_SHIRQ)
++#endif /* CONFIG_OKI_CAN_ML9620_GASSNER */
++
++char *err[7] = {
++ "Warning 1, Stuff Error",
++ "Warning 2, Form Error",
++ "Warning 3, ACK Error",
++ "Warning 4, Bits 1 Error",
++ "Warning 5, Bits 0 Error",
++ "Warning 6, CRC Error",
++ "Warning 7, MCU has produced this Error",
++};
++
++#define DRIVER_MAX_MINOR 2
++
++struct CANML9620REG {
++ unsigned char cancont;
++ unsigned char reserve1;
++ unsigned char canstat;
++ unsigned char reserve2;
++ unsigned char cantxerrc;
++ unsigned char canrxerrc;
++ unsigned char canbitt[2];
++ unsigned char canint[2];
++ unsigned char canopt;
++ unsigned char reserve3;
++ unsigned char canbpre;
++ unsigned char reserve4[3];
++
++ unsigned char if1creq;
++ unsigned char if1busy;
++ unsigned char if1cmask;
++ unsigned char reserve5;
++ unsigned char if1mask[4];
++ unsigned char if1id[4];
++ unsigned char if1mcont[2];
++ unsigned char if1data[8];
++ unsigned char reserve6[26];
++
++ unsigned char if2creq;
++ unsigned char if2busy;
++ unsigned char if2cmask;
++ unsigned char reserve7;
++ unsigned char if2mask[4];
++ unsigned char if2id[4];
++ unsigned char if2mcont[2];
++ unsigned char if2data[8];
++ unsigned char reserve8[42];
++
++ unsigned char cantreq[4];
++ unsigned char reserve9[12];
++
++ unsigned char canndata[4];
++ unsigned char reserve10[12];
++
++ unsigned char canipend[4];
++ unsigned char reserve11[12];
++
++ unsigned char canmval[4];
++ unsigned char reserve12[12];
++
++ unsigned char canstby;
++ unsigned char reserve13[12];
++};
++
++#define CANCONT 0x0
++#define RESERVE1 0x1
++#define CANSTAT 0x2
++#define RESERVE2 0x3
++#define CANTXERRC 0x4
++#define CANRXERRC 0x5
++#define CANBITT0 0x6
++#define CANBITT1 0x7
++#define CANINT0 0x8
++#define CANINT1 0x9
++#define CANOPT 0xA
++
++#define CANBPRE 0xC
++
++#define IF1CREQ 0x10
++#define IF1BUSY 0x11
++#define IF1CMASK 0x12
++
++#define IF1MASK0 0x14
++#define IF1MASK1 0x15
++#define IF1MASK2 0x16
++#define IF1MASK3 0x17
++
++#define IF1ID0 0x18
++#define IF1ID1 0x19
++#define IF1ID2 0x1A
++#define IF1ID3 0x1B
++
++#define IF1MCONT0 0x1C
++#define IF1MCONT1 0x1D
++
++#define IF1DATA0 0x1E
++#define IF1DATA1 0x1F
++#define IF1DATA2 0x20
++#define IF1DATA3 0x21
++#define IF1DATA4 0x22
++#define IF1DATA5 0x23
++#define IF1DATA6 0x24
++#define IF1DATA7 0x25
++
++#define IF2CREQ 0x40
++#define IF2BUSY 0x41
++#define IF2CMASK 0x42
++
++#define IF2MASK0 0x44
++#define IF2MASK1 0x45
++#define IF2MASK2 0x46
++#define IF2MASK3 0x47
++
++#define IF2ID0 0x48
++#define IF2ID1 0x49
++#define IF2ID2 0x4A
++#define IF2ID3 0x4B
++
++#define IF2MCONT0 0x4C
++#define IF2MCONT1 0x4D
++
++#define IF2DATA0 0x4E
++#define IF2DATA1 0x4F
++#define IF2DATA2 0x50
++#define IF2DATA3 0x51
++#define IF2DATA4 0x52
++#define IF2DATA5 0x53
++#define IF2DATA6 0x54
++#define IF2DATA7 0x55
++
++#define CANTREQ0 0x80
++#define CANTREQ1 0x81
++#define CANTREQ2 0x82
++#define CANTREQ3 0x83
++
++#define CANNDATA0 0x90
++#define CANNDATA1 0x91
++#define CANNDATA2 0x92
++#define CANNDATA3 0x93
++
++#define CANIPEND0 0xA0
++#define CANIPEND1 0xA1
++#define CANIPEND2 0xA2
++#define CANIPEND3 0xA3
++
++#define CANMVAL0 0xB0
++#define CANMVAL1 0xB1
++#define CANMVAL2 0xB2
++#define CANMVAL3 0xB3
++
++#define CANSTBY 0xC0
++struct recbuf {
++ struct can_msg msg;
++ struct recbuf *next;
++ struct recbuf *prev;
++};
++
++struct can_device {
++ /* Phys addresses and size */
++ unsigned long phys_addr_can;
++ unsigned long phys_size_can;
++ /* IRQ */
++ unsigned int irq;
++ unsigned long irq_flags;
++
++ /* Device node */
++ int minor;
++
++ /* waitqueue for read, poll */
++ wait_queue_head_t rx_waitq;
++
++ atomic_t can_opened;
++
++ struct recbuf *tail;
++ struct recbuf *head;
++
++ /* Virt addresses size */
++ unsigned char __iomem *virt_addr_can;
++
++ /* CAN-Baustein */
++ struct CANML9620REG reg;
++ unsigned short baudrate; /* baudrate */
++ unsigned short overrun; /* overrun counter */
++ struct can_msg msg; /* CAN message buffer */
++ int status; /* actual CAN status */
++ int last_error_code_write;
++ unsigned char tx_in_progress;
++ unsigned char last_error_code; /* LEC */
++ unsigned char last_error_code_debug; /* LEC when printed out */
++ spinlock_t can_lock;
++};
++
++/* Global Device Struct can0 */
++static struct can_device info_can0 = {
++ .phys_addr_can = PHYS_ADDR_CAN0,
++ .phys_size_can = PHYS_SIZE_CAN,
++ .irq = IRQ_CAN0,
++ .minor = 0,
++ .irq_flags = IRQ_FLAGS_CAN0,
++ .can_opened = ATOMIC_INIT(1),
++ .status = CAN_STS_NORMAL,
++};
++
++/* Global Device Struct can1 */
++static struct can_device info_can1 = {
++ .phys_addr_can = PHYS_ADDR_CAN1,
++ .phys_size_can = PHYS_SIZE_CAN,
++ .irq = IRQ_CAN1,
++ .irq_flags = IRQ_FLAGS_CAN1,
++ .minor = 1,
++ .can_opened = ATOMIC_INIT(1),
++ .status = CAN_STS_NORMAL,
++};
++
++static struct can_device *info_can[] = { &info_can0, &info_can1 };
++
++#define NUM_MSG 32
++
++#define CONT_FLAG_INIT 0x01
++#define CONT_FLAG_IE 0x02
++#define CONT_FLAG_SIE 0x04
++#define CONT_FLAG_EIE 0x08
++#define CONT_FLAG_CCE 0x40
++
++/* message buffers */
++
++#define CAN_STD_RX_BUFFER_START 1 /* CAN standard receive buffer */
++#define CAN_STD_RX_BUFFER_END 12 /* CAN standard receive buffer */
++#define CAN_EXT_RX_BUFFER 13 /* CAN extended receive buffer */
++
++#define CAN_TX_BUFFER 14 /* CAN transmit buffer */
++#define CAN_RTX_BUFFER 15 /* CAN remote frame transmit buffer */
++
++struct ML9620BDRATE {
++ unsigned char btiming0;
++ unsigned char btiming1;
++ unsigned char bpre;
++};
++
++const struct ML9620BDRATE bd_tbl[9] = {
++#ifdef CAN_CLOCK_16MHZ
++/* for 16 Mhz Quarz */
++/* bus timing 0 | bus timing 1 */
++/* SJW PRESCALER | SAM TSEG1 TSEG2 */
++ {0x23, 0x1C}, /* 10K bit/s */
++ {0x31, 0x1C}, /* 20K bit/s */
++ {0x13, 0x1C}, /* 50K bit/s */
++ {0x09, 0x1C}, /* 100K bit/s */
++ {0x07, 0x1C}, /* 125K bit/s */
++ {0x03, 0x1C}, /* 250K bit/s */
++ {0x01, 0x1C}, /* 500K bit/s */
++ {0x01, 0x16}, /* 800K bit/s */
++ {0x01, 0x14} /* 1M bit/s */
++#endif
++#ifdef CAN_CLOCK_8MHZ
++/* for 8 Mhz Quarz */
++/* bus timing 0 | bus timing 1 */
++/* SJW PRESCALER | SAM TSEG1 TSEG2 | CANBRPE */
++ {0x31, 0x1C, 0x01}, /* 10K bit/s */
++ {0x18, 0x1C, 0x00}, /* 20K bit/s */
++ {0x09, 0x1C, 0x00}, /* 50K bit/s */
++ {0x04, 0x1C, 0x00}, /* 100K bit/s */
++ {0x03, 0x1C, 0x00}, /* 125K bit/s */
++ {0x01, 0x1C, 0x00}, /* 250K bit/s */
++ {0x00, 0x1C, 0x00}, /* 500K bit/s */
++ {0x00, 0x16, 0x00}, /* 800K bit/s */
++ {0x00, 0x14, 0x00} /* 1M bit/s */
++#endif
++};
++
++/* DEBUG STUFF */
++
++#ifdef OKI_DEBUG
++#define CAN_DEBUG(REG,string) \
++{ \
++ DBG_OUT(KERN_ERR, " %s 0x%x\n",string,readb(v+REG)); \
++}
++#else
++#define CAN_DEBUG(REG,string)
++#endif
++
++#ifdef OKI_DEBUG
++#define DBG_OKI DBG_OUT
++#else
++#define DBG_OKI(...)
++#endif
++
++int drv_dbg = 7;
++
++void DBG_OUT(const char *type, const char *dbg_msg, ...)
++{
++ va_list ap;
++ char buf[1024];
++ int len;
++ unsigned int level;
++
++ va_start(ap, dbg_msg);
++ len = vsprintf(buf, dbg_msg, ap);
++ va_end(ap);
++ buf[len] = '\0';
++
++ if (0 == sscanf(type, "<%i>", &level))
++ printk(KERN_ALERT "%s", buf);
++
++ if (level > drv_dbg)
++ return;
++
++ switch (level) {
++ case 0:
++ printk(KERN_EMERG OKI_CAN_DEVICE_NAME "EMERG: %s", buf);
++ break;
++ case 1:
++ printk(KERN_ALERT OKI_CAN_DEVICE_NAME "%s", buf);
++ break;
++ case 2:
++ printk(KERN_CRIT OKI_CAN_DEVICE_NAME "%s", buf);
++ break;
++ case 3:
++ printk(KERN_ERR OKI_CAN_DEVICE_NAME "%s", buf);
++ break;
++ case 4:
++ printk(KERN_WARNING OKI_CAN_DEVICE_NAME "%s", buf);
++ break;
++ case 5:
++ printk(KERN_NOTICE OKI_CAN_DEVICE_NAME "%s", buf);
++ break;
++ case 6:
++ printk(KERN_INFO OKI_CAN_DEVICE_NAME "%s", buf);
++ break;
++ case 7:
++ printk(KERN_DEBUG OKI_CAN_DEVICE_NAME "%s", buf);
++ break;
++ }
++}
++#endif /* _OKI_ML9620_CORE_H_ */
+diff --git a/drivers/char/ds1337glue.c b/drivers/char/ds1337glue.c
+new file mode 100644
+index 0000000..c7d168b
+--- /dev/null
++++ b/drivers/char/ds1337glue.c
+@@ -0,0 +1,69 @@
++/*
++ * linux/arch/arm/mach-ep93xx/ds1337glue.c
++ *
++ * Copyright (C) 2005 Michael Burian
++ *
++ * 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.
++ *
++ * /dev/rtc interface for Dallas Semiconductor DS133[79]RTC I2C driver
++ *
++ * Also see "drivers/i2c/chips/ds1337.c"
++ *
++ */
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/rtc.h>
++#include <linux/miscdevice.h>
++#include <linux/poll.h>
++
++#include <asm/rtc.h>
++
++/* FIXME BEGIN: include this from "ds1337.h" as soon as there exists one */
++#warning FIXME: no official ds1337 interface available, hardcoding defaults.
++#define DS1337_GET_DATE 0
++#define DS1337_SET_DATE 1
++extern int ds1337_do_command(int bus, int cmd, void *arg);
++/* FIXME END */
++
++static int rtc_read_time(struct rtc_time *tm)
++{
++ return ds1337_do_command(0, DS1337_GET_DATE, (void*)(tm));
++}
++
++static int rtc_set_time(struct rtc_time *tm)
++{
++ return ds1337_do_command(0, DS1337_SET_DATE, (void*)(tm));
++}
++
++static struct rtc_ops dma03_rtc_ops = {
++ .owner = THIS_MODULE,
++ .read_time = rtc_read_time,
++ .set_time = rtc_set_time,
++};
++
++static int __init rtc_interface_init(void)
++{
++ int err;
++ printk(KERN_INFO "registering /dev/rtc interface for DS133[79]\n");
++
++ err = register_rtc(&dma03_rtc_ops);
++ if(err)
++ printk(KERN_ERR "could not register DS1337 /dev/rtc interface:"
++ " error=%d!\n",err);
++
++ return err;
++}
++
++static void __exit rtc_interface_exit(void)
++{
++ unregister_rtc(&dma03_rtc_ops);
++}
++
++MODULE_AUTHOR("Michael Burian");
++MODULE_DESCRIPTION("/dev/rtc interface for ds1337.c");
++MODULE_LICENSE("GPL");
++
++module_init(rtc_interface_init);
++module_exit(rtc_interface_exit);
+diff --git a/drivers/char/ep93xx-rtc.c b/drivers/char/ep93xx-rtc.c
+new file mode 100644
+index 0000000..399d0b0
+--- /dev/null
++++ b/drivers/char/ep93xx-rtc.c
+@@ -0,0 +1,376 @@
++/*
++ * Real Time Clock for Cirrus EP93xx
++ *
++ * Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * Support for realtime clock device on the Cirrus
++ * EP93xx family of devices.
++ *
++ * Based on rtc.c, and other rtc drivers.
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/errno.h>
++#include <linux/module.h>
++#include <linux/sysctl.h>
++#include <linux/rtc.h>
++#include <linux/poll.h>
++#include <linux/miscdevice.h>
++
++#include <asm/io.h>
++#include <asm/arch/regmap.h>
++
++#define RTC_VERSION "0.01"
++
++#define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */
++
++extern spinlock_t rtc_lock; /* seems to be only present in older rtc header? */
++static spinlock_t rtc_task_lock = SPIN_LOCK_UNLOCKED;
++static rtc_task_t *rtc_callback = NULL;
++static unsigned long rtc_status = 0;
++static unsigned long rtc_irq_data = 0;
++static DECLARE_WAIT_QUEUE_HEAD(rtc_wait);
++
++/*
++ * the 1 Hz real time interrupt
++ */
++
++irqreturn_t interrupt_1hz(int irq, void *dev_id, struct pt_regs *regs)
++{
++ static unsigned long x = 0;
++ static int i = 0;
++
++ rtc_irq_data += 0x100;
++ rtc_irq_data &= ~0xff;
++
++ wake_up_interruptible(&rtc_wait);
++
++ printk(KERN_ERR);
++ printk(" delta: %04ld", jiffies - x);
++ printk(" data: %08x", readl(RTCDR));
++ printk(" match: %08x", readl(RTCMR));
++ printk(" stat: %08x", readl(RTCSTAT));
++ printk(" load: %08x", readl(RTCLR));
++ printk(" ctrl: %08x", readl(RTCCR));
++ printk(" comp: %08x", readl(RTCSCOMP));
++ printk("\n");
++
++ x = jiffies;
++ i++;
++
++ if ((i & 0x7) == 0) {
++ writel(i << 5, RTCLR);
++ printk(KERN_ERR "NEW LOAD VALUE: %08x\n", i << 5);
++ }
++
++ writel(0, RTCEOI);
++
++ return IRQ_HANDLED;
++}
++
++/*
++ * the RTC match interrupt
++ */
++
++irqreturn_t interrupt_match(int irq, void *dev_id, struct pt_regs * regs)
++{
++ return IRQ_HANDLED;
++}
++
++/*
++ * the bulk of the usr interface is done here
++ */
++
++static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel)
++{
++ return -ENOSYS;
++}
++
++/*
++ * file operations for character device node
++ */
++
++static ssize_t rtc_read(struct file *file, char __user * buf, size_t count,
++ loff_t * ppos)
++{
++ unsigned long data;
++ ssize_t retval;
++ DECLARE_WAITQUEUE(wait, current);
++
++ if (count < sizeof(unsigned int))
++ 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)
++ break;
++
++ if (file->f_flags & O_NONBLOCK) {
++ retval = -EAGAIN;
++ goto out;
++ }
++
++ if (signal_pending(current)) {
++ retval = -ERESTARTSYS;
++ goto out;
++ }
++
++ schedule();
++ } while (1);
++
++ if (count < sizeof(unsigned long))
++ retval =
++ put_user(data, (unsigned int __user *)buf) ? : sizeof(int);
++ else
++ retval =
++ put_user(data,
++ (unsigned long __user *)buf) ? : sizeof(long);
++
++ out:
++ current->state = TASK_RUNNING;
++ remove_wait_queue(&rtc_wait, &wait);
++
++ return retval;
++}
++
++static unsigned int rtc_poll(struct file *file, poll_table * wait)
++{
++ return -ENOSYS;
++}
++
++static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ return rtc_do_ioctl(cmd, arg, 0);
++}
++
++static int rtc_open(struct inode *inode, struct file *file)
++{
++ spin_lock_irq(&rtc_lock);
++
++ if (rtc_status & RTC_IS_OPEN) {
++ spin_unlock_irq(&rtc_lock);
++ return -EBUSY;
++ }
++
++ rtc_status |= RTC_IS_OPEN;
++ rtc_irq_data = 0;
++ enable_irq(IRQ_1HZ);
++
++ spin_unlock_irq(&rtc_lock);
++ return 0;
++}
++
++static int rtc_release(struct inode *inode, struct file *file)
++{
++ spin_lock_irq(&rtc_lock);
++
++ disable_irq(IRQ_1HZ);
++ rtc_irq_data = 0;
++ rtc_status &= ~RTC_IS_OPEN;
++
++ spin_unlock_irq(&rtc_lock);
++
++ return 0;
++}
++
++static int rtc_fasync(int fd, struct file *filp, int on)
++{
++ return -ENOSYS;
++}
++
++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_dev = {
++ RTC_MINOR,
++ "rtc",
++ &rtc_fops
++};
++
++/*
++ * sysctl-tuning infrastructure.
++ */
++
++int no_proc(ctl_table * table, int write, struct file *filp,
++ void __user * buffer, size_t * lenp, loff_t * ppos)
++{
++ return -ENOSYS;
++}
++
++static ctl_table rtc_table[] = {
++ {
++ .ctl_name = 1,
++ .procname = "max-user-freq",
++ .data = NULL,
++ .maxlen = sizeof(int),
++ .mode = 0644,
++ .proc_handler = &no_proc,
++ },
++ {.ctl_name = 0}
++};
++
++static ctl_table rtc_root[] = {
++ {
++ .ctl_name = 1,
++ .procname = "rtc",
++ .maxlen = 0,
++ .mode = 0555,
++ .child = rtc_table,
++ },
++ {.ctl_name = 0}
++};
++
++static ctl_table dev_root[] = {
++ {
++ .ctl_name = CTL_DEV,
++ .procname = "dev",
++ .maxlen = 0,
++ .mode = 0555,
++ .child = rtc_root,
++ },
++ {.ctl_name = 0}
++};
++
++static struct ctl_table_header *sysctl_header;
++
++static int __init init_sysctl(void)
++{
++ sysctl_header = register_sysctl_table(dev_root, 0);
++ return 0;
++}
++
++static void __exit cleanup_sysctl(void)
++{
++ unregister_sysctl_table(sysctl_header);
++}
++
++/*
++ * Public functions from rtc.h
++ */
++
++EXPORT_SYMBOL(rtc_register);
++EXPORT_SYMBOL(rtc_unregister);
++EXPORT_SYMBOL(rtc_control);
++
++int rtc_register(rtc_task_t * task)
++{
++ if (task == NULL || task->func == NULL)
++ return -EINVAL;
++
++ spin_lock_irq(&rtc_lock);
++
++ if (rtc_status & RTC_IS_OPEN) {
++ spin_unlock_irq(&rtc_lock);
++ return -EBUSY;
++ }
++
++ spin_lock(&rtc_task_lock);
++
++ if (rtc_callback) {
++ spin_unlock(&rtc_task_lock);
++ spin_unlock_irq(&rtc_lock);
++ return -EBUSY;
++ }
++
++ rtc_status |= RTC_IS_OPEN;
++ rtc_callback = task;
++
++ spin_unlock(&rtc_task_lock);
++ spin_unlock_irq(&rtc_lock);
++
++ return 0;
++}
++
++int rtc_unregister(rtc_task_t * task)
++{
++ spin_lock_irq(&rtc_lock);
++ spin_lock(&rtc_task_lock);
++
++ if (rtc_callback != task) {
++ spin_unlock(&rtc_task_lock);
++ spin_unlock_irq(&rtc_lock);
++ return -ENXIO;
++ }
++
++ /* disable PIE/AIE/UIE interrupts */
++
++ rtc_status &= ~RTC_IS_OPEN;
++ rtc_callback = NULL;
++
++ spin_unlock(&rtc_task_lock);
++ spin_unlock_irq(&rtc_lock);
++
++ return 0;
++}
++
++int rtc_control(rtc_task_t * task, unsigned int cmd, unsigned long arg)
++{
++ spin_lock_irq(&rtc_task_lock);
++
++ if (rtc_callback != task) {
++ spin_unlock_irq(&rtc_task_lock);
++ return -ENXIO;
++ }
++
++ spin_unlock_irq(&rtc_task_lock);
++
++ return rtc_do_ioctl(cmd, arg, 1);
++}
++
++void rtc_get_rtc_time(struct rtc_time *rtc_tm)
++{
++}
++
++/*
++ * Module init/exit
++ */
++
++static int __init rtc_init(void)
++{
++ if (request_irq(IRQ_1HZ, interrupt_1hz, SA_INTERRUPT, "rtc-1hz", NULL)) {
++ printk(KERN_ERR "rtc: IRQ %d is not free.\n", IRQ_1HZ);
++ return -EIO;
++ }
++
++ if (misc_register(&rtc_dev)) {
++ free_irq(IRQ_1HZ, NULL);
++ return -ENODEV;
++ }
++
++ init_sysctl();
++
++ printk(KERN_INFO "Real Time Clock Driver v" RTC_VERSION "\n");
++ return 0;
++}
++
++static void __exit rtc_exit(void)
++{
++ cleanup_sysctl();
++ misc_deregister(&rtc_dev);
++ free_irq(IRQ_1HZ, NULL);
++}
++
++module_init(rtc_init);
++module_exit(rtc_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/char/ttml.c b/drivers/char/ttml.c
+new file mode 100644
+index 0000000..ba2cb8e
+--- /dev/null
++++ b/drivers/char/ttml.c
+@@ -0,0 +1,643 @@
++/*
++ * linux/drivers/char/ttml.c
++ *
++ * TTML TripDawg system devices.
++ *
++ * Copyright 2004, Ray Lehtiniemi
++ * Copyright 2004, Siconix, Inc
++ */
++
++#include <linux/module.h>
++#include <linux/config.h>
++
++#include <linux/spinlock.h>
++#include <linux/fs.h>
++#include <linux/device.h>
++#include <linux/cdev.h>
++#include <linux/major.h>
++#include <linux/init.h>
++#include <linux/errno.h>
++#include <linux/poll.h>
++#include <linux/ttml.h>
++#include <linux/timer.h>
++#include <linux/slab.h>
++
++#include <asm/io.h>
++#include <asm/uaccess.h>
++
++#include <asm/arch/regmap.h>
++#include <asm/arch/ssp.h>
++#include <asm/arch/ssp2.h>
++#include <asm/arch/mach-ttml.h>
++
++/* device open/release stuff */
++static DECLARE_MUTEX(mutex);
++static struct cdev ttml_cdev;
++static struct class *ttml_class;
++static int is_open[MAX_TTML_MINORS];
++
++#define minor_get(minor) is_open[(minor)-TTML_MINOR_LED] = 1
++#define minor_put(minor) is_open[(minor)-TTML_MINOR_LED] = 0
++#define minor_busy(minor) (is_open[(minor)-TTML_MINOR_LED] != 0)
++
++static struct {
++ int minor;
++ char *name;
++} devlist[] = {
++ {
++ TTML_MINOR_LED, "led"}, {
++ TTML_MINOR_BUZZER, "buzzer"}, {
++ TTML_MINOR_SPEEDO, "speedo"}, {
++ TTML_MINOR_GPIO, "gpio"}, {
++ TTML_MINOR_BUTTON, "button"}, {
++TTML_MINOR_WD, "wd"},};
++
++/* button and gpio event handling */
++static kmem_cache_t *event_cachep;
++static spinlock_t event_lock = SPIN_LOCK_UNLOCKED;
++static LIST_HEAD(button_events);
++static LIST_HEAD(gpio_events);
++static DECLARE_WAIT_QUEUE_HEAD(button_wait);
++static DECLARE_WAIT_QUEUE_HEAD(gpio_wait);
++
++enum ttml_events {
++ TTML_BUTTON_PRESS,
++ TTML_BUTTON_RELEASE,
++ TTML_PTO_RISE,
++ TTML_PTO_FALL,
++ TTML_IGNITION_RISE,
++ TTML_IGNITION_FALL,
++ TTML_SPARE_RISE,
++ TTML_SPARE_FALL,
++};
++
++struct ttml_event {
++ struct list_head l;
++ struct timeval t;
++ enum ttml_events e;
++};
++
++/* Button and GPIO event monitoring timer */
++
++static struct timer_list monitor_timer;
++static void handle_timer(unsigned long);
++
++static void setup_timer(void)
++{
++ monitor_timer.expires = jiffies + 1;
++ monitor_timer.data = 0;
++ monitor_timer.function = handle_timer;
++ add_timer(&monitor_timer);
++}
++
++static void handle_timer_button(void)
++{
++ static int state = 0;
++ int portf = readl(GPIO_PFDR);
++ int new = (portf & 0x04) ? 0 : 1;
++
++ if (state ^ new) {
++ struct ttml_event *b =
++ kmem_cache_alloc(event_cachep, GFP_KERNEL);
++ if (b != NULL) {
++ do_gettimeofday(&b->t);
++ b->t.tv_usec |=
++ ((new ? TTML_BUTTON_PRESS : TTML_BUTTON_RELEASE) <<
++ 24);
++ list_add(&b->l, &button_events);
++ wake_up_interruptible(&button_wait);
++ }
++ state = new;
++ }
++}
++
++static void handle_timer_pto(void)
++{
++ static int state = 0;
++ int portf = readl(GPIO_PFDR);
++ int new = (portf & 0x08) ? 1 : 0;
++
++ if (state ^ new) {
++ struct ttml_event *b =
++ kmem_cache_alloc(event_cachep, GFP_KERNEL);
++ if (b != NULL) {
++ do_gettimeofday(&b->t);
++ b->t.tv_usec |=
++ ((new ? TTML_PTO_RISE : TTML_PTO_FALL) << 24);
++ list_add(&b->l, &gpio_events);
++ wake_up_interruptible(&gpio_wait);
++ }
++ state = new;
++ }
++}
++
++static void handle_timer_ignition(void)
++{
++ static int state = 0;
++ int portf = readl(GPIO_PFDR);
++ int new = (portf & 0x02) ? 1 : 0;
++
++ if (state ^ new) {
++ struct ttml_event *b =
++ kmem_cache_alloc(event_cachep, GFP_KERNEL);
++ if (b != NULL) {
++ do_gettimeofday(&b->t);
++ b->t.tv_usec |=
++ ((new ? TTML_IGNITION_RISE : TTML_IGNITION_FALL) <<
++ 24);
++ list_add(&b->l, &gpio_events);
++ wake_up_interruptible(&gpio_wait);
++ }
++ state = new;
++ }
++}
++
++static void handle_timer_spare(void)
++{
++ static int state = 0;
++ int porta = readl(GPIO_PADR);
++ int new = (porta & 0x08) ? 1 : 0;
++
++ if (state ^ new) {
++ struct ttml_event *b =
++ kmem_cache_alloc(event_cachep, GFP_KERNEL);
++ if (b != NULL) {
++ do_gettimeofday(&b->t);
++ b->t.tv_usec |=
++ ((new ? TTML_SPARE_RISE : TTML_SPARE_FALL) << 24);
++ list_add(&b->l, &gpio_events);
++ wake_up_interruptible(&gpio_wait);
++ }
++ state = new;
++ }
++}
++
++static void handle_timer(unsigned long foo)
++{
++ handle_timer_button();
++ handle_timer_pto();
++ handle_timer_ignition();
++ handle_timer_spare();
++ setup_timer();
++}
++
++static int ttml_read_gpio(struct file *filp, char __user * buf, size_t size,
++ loff_t * off);
++static int ttml_read_button(struct file *filp, char __user * buf, size_t size,
++ loff_t * off);
++static unsigned int ttml_poll_gpio(struct file *filp,
++ struct poll_table_struct *poll);
++static unsigned int ttml_poll_button(struct file *filp,
++ struct poll_table_struct *poll);
++static int ttml_ioctl(struct inode *inode, struct file *filp,
++ unsigned int command, unsigned long arg);
++static int ttml_open(struct inode *inode, struct file *filp);
++static int ttml_release(struct inode *inode, struct file *filp);
++
++static struct file_operations ttml_fops = {
++ .owner = THIS_MODULE,
++ .ioctl = ttml_ioctl,
++ .open = ttml_open,
++ .release = ttml_release,
++};
++
++static struct file_operations ttml_fops_gpio = {
++ .owner = THIS_MODULE,
++ .read = ttml_read_gpio,
++ .poll = ttml_poll_gpio,
++ .ioctl = ttml_ioctl,
++ .open = ttml_open,
++ .release = ttml_release,
++};
++
++static struct file_operations ttml_fops_button = {
++ .owner = THIS_MODULE,
++ .read = ttml_read_button,
++ .poll = ttml_poll_button,
++ .ioctl = ttml_ioctl,
++ .open = ttml_open,
++ .release = ttml_release,
++};
++
++static int do_get_led(void __user * arg)
++{
++ struct ttml_ioctl_led a;
++ int porte = readl(GPIO_PEDR);
++ int portb = readl(GPIO_PBDR);
++
++ a.blue = (portb & 0x01) ? 1 : 0;
++ a.red = (porte & 0x02) ? 1 : 0;
++ a.yellow = (porte & 0x01) ? 1 : 0;
++
++ return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
++}
++
++static int do_get_buzzer(void __user * arg)
++{
++ struct ttml_ioctl_buzzer a;
++
++ a.buzzer1 = 0; /* FIXME */
++
++ return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
++}
++
++static int do_get_speedo(void __user * arg)
++{
++ struct ttml_ioctl_speedo a;
++ unsigned char msg[3] = { 0xaa, 0x82, 0xd7 };
++ unsigned char reply[10];
++ int err;
++
++ err = ssp_do_ttml(&ep93xx_ssp_micro, msg, 3, reply, 10);
++
++ if (err != 0)
++ return err;
++
++ a.instant = 0; /* FIXME */
++ a.average = (reply[1] << 8) | (reply[2]);
++
++ return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
++}
++
++static int do_get_gpio(void __user * arg)
++{
++ struct ttml_ioctl_gpio a;
++ int porta = readl(GPIO_PADR);
++ int portf = readl(GPIO_PFDR);
++
++ a.pto = (portf & 0x08) ? 0 : 1;
++ a.ignition = (portf & 0x02) ? 0 : 1;
++ a.spare = (porta & 0x08) ? 0 : 1;
++
++ return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
++}
++
++static int do_get_button(void __user * arg)
++{
++ struct ttml_ioctl_button a;
++ int portf = readl(GPIO_PFDR);
++
++ a.button1 = (portf & 0x04) ? 0 : 1;
++
++ return (copy_to_user(arg, &a, sizeof(a)) == sizeof(a)) ? -EIO : 0;
++}
++
++static int do_set_led(void __user * arg)
++{
++ struct ttml_ioctl_led a;
++ int porte = readl(GPIO_PEDR);
++ int portb = readl(GPIO_PBDR);
++
++ if (copy_from_user(&a, arg, sizeof(a)))
++ return -EIO;
++
++ if (a.yellow)
++ porte |= 0x01;
++ else
++ porte &= ~0x01;
++
++ if (a.red)
++ porte |= 0x02;
++ else
++ porte &= ~0x02;
++
++ if (a.blue)
++ portb |= 0x01;
++ else
++ portb &= ~0x01;
++
++ writel(porte, GPIO_PEDR);
++ writel(portb, GPIO_PBDR);
++
++ return 0;
++}
++
++static int do_set_buzzer(void __user * arg)
++{
++ struct ttml_ioctl_buzzer a;
++ unsigned char msg0[4] = { 0xaa, 0x93, 0x00, 0xc6 };
++ unsigned char msg1[4] = { 0xaa, 0x93, 0x01, 0xc7 };
++ unsigned char reply[10];
++ int err = 0;
++
++ if (copy_from_user(&a, arg, sizeof(a)))
++ return -EIO;
++
++ if (a.buzzer1)
++ err = ssp_do_ttml(&ep93xx_ssp_micro, msg1, 4, reply, 10);
++ else
++ err = ssp_do_ttml(&ep93xx_ssp_micro, msg0, 4, reply, 10);
++
++ return err;
++}
++
++static int ttml_read_gpio(struct file *filp, char __user * buf, size_t size,
++ loff_t * off)
++{
++ DECLARE_WAITQUEUE(wait, current);
++ struct ttml_event *g = NULL;
++ int retval = -EINVAL;
++
++ if (size != sizeof(struct timeval))
++ return -EINVAL;
++
++ add_wait_queue(&gpio_wait, &wait);
++
++ while (1) {
++ unsigned long flags;
++
++ __set_current_state(TASK_INTERRUPTIBLE);
++
++ spin_lock_irqsave(&event_lock, flags);
++ if (!list_empty(&gpio_events))
++ list_for_each_entry(g, &gpio_events, l) {
++ list_del(&g->l);
++ break;
++ }
++
++ spin_unlock_irqrestore(&event_lock, flags);
++
++ if (g != NULL)
++ break;
++
++ if (filp->f_flags & O_NONBLOCK) {
++ retval = -EAGAIN;
++ goto out;
++ }
++
++ if (signal_pending(current)) {
++ retval = -ERESTARTSYS;
++ goto out;
++ }
++
++ schedule();
++
++ };
++
++ if (copy_to_user(buf, &g->t, sizeof(struct timeval)))
++ retval = -EFAULT;
++ else
++ retval = sizeof(struct timeval);
++
++ kmem_cache_free(event_cachep, g);
++
++ out:
++ current->state = TASK_RUNNING;
++ remove_wait_queue(&gpio_wait, &wait);
++
++ return retval;
++}
++
++static unsigned int ttml_poll_gpio(struct file *filp,
++ struct poll_table_struct *poll)
++{
++ unsigned long flags;
++ int retval = 0;
++
++ poll_wait(filp, &gpio_wait, poll);
++
++ spin_lock_irqsave(&event_lock, flags);
++ if (!list_empty(&gpio_events))
++ retval = (POLLIN | POLLRDNORM);
++ spin_unlock_irqrestore(&event_lock, flags);
++
++ return retval;
++}
++
++static int ttml_read_button(struct file *filp, char __user * buf, size_t size,
++ loff_t * off)
++{
++ DECLARE_WAITQUEUE(wait, current);
++ struct ttml_event *b = NULL;
++ int retval = -EINVAL;
++
++ if (size != sizeof(struct timeval))
++ return -EINVAL;
++
++ add_wait_queue(&button_wait, &wait);
++
++ while (1) {
++ unsigned long flags;
++
++ __set_current_state(TASK_INTERRUPTIBLE);
++
++ spin_lock_irqsave(&event_lock, flags);
++ if (!list_empty(&button_events)) {
++ list_for_each_entry(b, &button_events, l) {
++ list_del(&b->l);
++ break;
++ }
++ }
++ spin_unlock_irqrestore(&event_lock, flags);
++
++ if (b != NULL)
++ break;
++
++ if (filp->f_flags & O_NONBLOCK) {
++ retval = -EAGAIN;
++ goto out;
++ }
++
++ if (signal_pending(current)) {
++ retval = -ERESTARTSYS;
++ goto out;
++ }
++
++ schedule();
++
++ };
++
++ if (copy_to_user(buf, &b->t, sizeof(struct timeval)))
++ retval = -EFAULT;
++ else
++ retval = sizeof(struct timeval);
++
++ kmem_cache_free(event_cachep, b);
++
++ out:
++ current->state = TASK_RUNNING;
++ remove_wait_queue(&button_wait, &wait);
++
++ return retval;
++}
++
++static unsigned int ttml_poll_button(struct file *filp,
++ struct poll_table_struct *poll)
++{
++ unsigned long flags;
++ int retval = 0;
++
++ poll_wait(filp, &button_wait, poll);
++
++ spin_lock_irqsave(&event_lock, flags);
++ if (!list_empty(&button_events))
++ retval = (POLLIN | POLLRDNORM);
++ spin_unlock_irqrestore(&event_lock, flags);
++
++ return retval;
++}
++
++static int ttml_ioctl(struct inode *inode, struct file *filp,
++ unsigned int command, unsigned long arg)
++{
++ void __user *p = (void __user *)arg;
++ const int minor = iminor(inode);
++ int err = -ENOSYS;
++
++ switch (command) {
++ case TTML_GET_LED:
++ if (minor == TTML_MINOR_LED)
++ err = do_get_led(p);
++ break;
++ case TTML_GET_BUZZER:
++ if (minor == TTML_MINOR_BUZZER)
++ err = do_get_buzzer(p);
++ break;
++ case TTML_GET_SPEEDO:
++ if (minor == TTML_MINOR_SPEEDO)
++ err = do_get_speedo(p);
++ break;
++ case TTML_GET_GPIO:
++ if (minor == TTML_MINOR_GPIO)
++ err = do_get_gpio(p);
++ break;
++ case TTML_GET_BUTTON:
++ if (minor == TTML_MINOR_BUTTON)
++ err = do_get_button(p);
++ break;
++ case TTML_SET_LED:
++ if (minor == TTML_MINOR_LED)
++ err = do_set_led(p);
++ break;
++ case TTML_SET_BUZZER:
++ if (minor == TTML_MINOR_BUZZER)
++ err = do_set_buzzer(p);
++ break;
++ }
++
++ return err;
++}
++
++static int ttml_open(struct inode *inode, struct file *filp)
++{
++ const int minor = iminor(inode);
++ int err = -EBUSY;
++
++ if (minor == TTML_MINOR_WD) {
++ unsigned char msg[3] = { 0xaa, 0x82, 0xd7 };
++ unsigned char reply[10];
++ ssp_do_ttml(&ep93xx_ssp_micro, msg, 3, reply, 10);
++ }
++
++ down(&mutex);
++ if (minor_busy(minor))
++ goto err;
++ minor_get(minor);
++ if (minor == TTML_MINOR_GPIO)
++ filp->f_op = &ttml_fops_gpio;
++ if (minor == TTML_MINOR_BUTTON)
++ filp->f_op = &ttml_fops_button;
++ err = 0;
++
++ err:
++ up(&mutex);
++ return err;
++}
++
++static int ttml_release(struct inode *inode, struct file *filp)
++{
++ down(&mutex);
++ minor_put(iminor(inode));
++ up(&mutex);
++ return 0;
++}
++
++static int __init ttml_init(void)
++{
++ dev_t dev = MKDEV(TTML_MAJOR, 240);
++ int err = -EIO;
++ int i;
++
++ err = -ENOMEM;
++ event_cachep = kmem_cache_create("ttml_event",
++ sizeof(struct ttml_event),
++ 0, 0, NULL, NULL);
++ if (event_cachep == NULL)
++ goto err;
++
++ err = -EIO;
++ if (register_chrdev_region(dev, MAX_TTML_MINORS, "ttml"))
++ goto err_uncache;
++
++ cdev_init(&ttml_cdev, &ttml_fops);
++
++ if (cdev_add(&ttml_cdev, dev, MAX_TTML_MINORS)) {
++ kobject_put(&ttml_cdev.kobj);
++ goto err_unreg;
++ }
++
++ ttml_class = class_create(THIS_MODULE, "ttml");
++
++ if (IS_ERR(ttml_class)) {
++ err = PTR_ERR(ttml_class);
++ cdev_del(&ttml_cdev);
++ goto err_unreg;
++ }
++
++ for (i = 0; i < ARRAY_SIZE(devlist); i++)
++ class_device_create(ttml_class,
++ MKDEV(TTML_MAJOR, devlist[i].minor),
++ NULL, "%s", devlist[i].name);
++
++ init_timer(&monitor_timer);
++ setup_timer();
++
++ printk(KERN_INFO "TTML system devices version 0.1\n");
++ return 0;
++
++ err_unreg:
++ unregister_chrdev_region(dev, MAX_TTML_MINORS);
++ err_uncache:
++ kmem_cache_destroy(event_cachep);
++ err:
++ printk(KERN_WARNING "unable to register ttml devices\n");
++ return err;
++}
++
++static void __exit ttml_exit(void)
++{
++ struct ttml_event *b;
++ int i;
++
++ /* stop our button polling timer */
++ del_timer_sync(&monitor_timer);
++
++ /* delete any events captured but not yet read */
++ list_for_each_entry(b, &button_events, l) {
++ list_del(&b->l);
++ kmem_cache_free(event_cachep, b);
++ }
++
++ list_for_each_entry(b, &gpio_events, l) {
++ list_del(&b->l);
++ kmem_cache_free(event_cachep, b);
++ }
++
++ /* free up the event cache */
++ kmem_cache_destroy(event_cachep);
++
++ /* clean up the device */
++ for (i = 0; i < ARRAY_SIZE(devlist); i++)
++ class_device_destroy(ttml_class,
++ MKDEV(TTML_MAJOR, devlist[i].minor));
++ class_destroy(ttml_class);
++ cdev_del(&ttml_cdev);
++ unregister_chrdev_region(MKDEV(TTML_MAJOR, 240), MAX_TTML_MINORS);
++}
++
++module_init(ttml_init);
++module_exit(ttml_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi");
++MODULE_DESCRIPTION("TTML system devices");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
+index 344001b..b5a7a90 100644
+--- a/drivers/char/watchdog/Kconfig
++++ b/drivers/char/watchdog/Kconfig
+@@ -148,6 +148,17 @@ config MPCORE_WATCHDOG
+ To compile this driver as a module, choose M here: the
+ module will be called mpcore_wdt.
+
++config EP93XX_WATCHDOG
++ tristate "EP93xx Watchdog"
++ depends on WATCHDOG && ARCH_EP93XX
++ help
++ Say Y here if to include support for the watchdog timer
++ in the Cirrus EP93xx family of devices. This driver can
++ be built as a module by choosing M. The module will
++ be called ep93xx_wdt.
++
++ Say N if you are unsure.
++
+ # X86 (i386 + ia64 + x86_64) Architecture
+
+ config ACQUIRE_WDT
+diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
+index cfd0a39..061671b 100644
+--- a/drivers/char/watchdog/Makefile
++++ b/drivers/char/watchdog/Makefile
+@@ -25,6 +25,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.
+ # ARM Architecture
+ obj-$(CONFIG_21285_WATCHDOG) += wdt285.o
+ obj-$(CONFIG_977_WATCHDOG) += wdt977.o
++obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
+ obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
+ obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
+ obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
+diff --git a/drivers/char/watchdog/ep93xx_wdt.c b/drivers/char/watchdog/ep93xx_wdt.c
+new file mode 100644
+index 0000000..a2a7a49
+--- /dev/null
++++ b/drivers/char/watchdog/ep93xx_wdt.c
+@@ -0,0 +1,210 @@
++/*
++ * drivers/watchdog/ep93xx_wdt.c
++ *
++ * Watchdog driver for Cirrus EP93xx family of devices.
++ *
++ * Author: Ray Lehtiniemi <rayl@mail.com>
++ *
++ * Copyright 2004 (c) Ray Lehtiniemi
++ * Based on ep93xx driver.
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++/*
++ Todo:
++
++ - test last rst from watchdog status
++ - test module loading
++ - test nowayout
++ - test all ioctl, add missing ones
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/fs.h>
++#include <linux/miscdevice.h>
++#include <linux/watchdog.h>
++#include <linux/init.h>
++
++#include <asm/hardware.h>
++#include <asm/bitops.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/arch/regmap.h>
++
++#define WD_VERSION "0.01"
++
++#ifdef CONFIG_WATCHDOG_NOWAYOUT
++static int nowayout = 1;
++#else
++static int nowayout = 0;
++#endif
++
++static unsigned long wdt_status;
++static unsigned long boot_status;
++
++#define WDT_IN_USE 0
++#define WDT_OK_TO_CLOSE 1
++
++static void wdt_enable(void)
++{
++ writel(0xaaaa, WATCHDOG);
++}
++
++static void wdt_disable(void)
++{
++ writel(0xaa55, WATCHDOG);
++}
++
++static void wdt_ping(void)
++{
++ writel(0x5555, WATCHDOG);
++}
++
++static int ep93xx_wdt_open(struct inode *inode, struct file *file)
++{
++ if (test_and_set_bit(WDT_IN_USE, &wdt_status))
++ return -EBUSY;
++
++ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
++
++ wdt_enable();
++
++ return 0;
++}
++
++static ssize_t
++ep93xx_wdt_write(struct file *file, const char __user * data, size_t len,
++ loff_t * ppos)
++{
++ /* Can't seek (pwrite) on this device */
++ if (*ppos != file->f_pos)
++ return -ESPIPE;
++
++ if (len) {
++ if (!nowayout) {
++ size_t i;
++
++ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
++
++ for (i = 0; i != len; i++) {
++ char c;
++
++ if (get_user(c, data + i))
++ return -EFAULT;
++
++ if (c == 'V')
++ set_bit(WDT_OK_TO_CLOSE, &wdt_status);
++ else
++ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
++ }
++ }
++ wdt_ping();
++ }
++
++ return len;
++}
++
++static struct watchdog_info ident = {
++ .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE,
++ .identity = "EP93xx Watchdog",
++};
++
++static int
++ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
++ unsigned long arg)
++{
++ int ret = -ENOIOCTLCMD;
++
++ switch (cmd) {
++ case WDIOC_GETSUPPORT:
++ ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
++ sizeof(ident)) ? -EFAULT : 0;
++ break;
++
++ case WDIOC_GETSTATUS:
++ ret = put_user(0, (int __user *)arg);
++ break;
++
++ case WDIOC_GETBOOTSTATUS:
++ ret = put_user(boot_status, (int __user *)arg);
++ break;
++
++ case WDIOC_GETTIMEOUT:
++ /* actually, it is 0.250 seconds.... */
++ ret = put_user(1, (int __user *)arg);
++ break;
++
++ case WDIOC_KEEPALIVE:
++ wdt_ping();
++ ret = 0;
++ break;
++ }
++ return ret;
++}
++
++static int ep93xx_wdt_release(struct inode *inode, struct file *file)
++{
++ if (test_bit(WDT_OK_TO_CLOSE, &wdt_status))
++ wdt_disable();
++ else
++ printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
++ "timer will not stop\n");
++
++ clear_bit(WDT_IN_USE, &wdt_status);
++ clear_bit(WDT_OK_TO_CLOSE, &wdt_status);
++
++ return 0;
++}
++
++static struct file_operations ep93xx_wdt_fops = {
++ .owner = THIS_MODULE,
++ .write = ep93xx_wdt_write,
++ .ioctl = ep93xx_wdt_ioctl,
++ .open = ep93xx_wdt_open,
++ .release = ep93xx_wdt_release,
++};
++
++static struct miscdevice ep93xx_wdt_miscdev = {
++ .minor = WATCHDOG_MINOR,
++ .name = "EP93xx Watchdog",
++ .fops = &ep93xx_wdt_fops,
++};
++
++static int __init ep93xx_wdt_init(void)
++{
++ int ret;
++
++ ret = misc_register(&ep93xx_wdt_miscdev);
++
++ boot_status = readl(WATCHDOG) & 0x01 ? 1 : 0;
++
++ printk("EP93xx Watchdog: Version " WD_VERSION "%s\n",
++ (readl(WATCHDOG) & 0x08) ? " (nCS1 disable detected)"
++ : "");
++
++ return ret;
++}
++
++static void __exit ep93xx_wdt_exit(void)
++{
++ misc_deregister(&ep93xx_wdt_miscdev);
++}
++
++module_init(ep93xx_wdt_init);
++module_exit(ep93xx_wdt_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>");
++MODULE_DESCRIPTION("EP93xx Watchdog");
++
++module_param(nowayout, int, 0);
++MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
++
++MODULE_LICENSE("GPL");
++MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
+diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
+index 4010fe9..895dfa8 100644
+--- a/drivers/i2c/busses/Kconfig
++++ b/drivers/i2c/busses/Kconfig
+@@ -95,6 +95,19 @@ config I2C_ELEKTOR
+ This support is also available as a module. If so, the module
+ will be called i2c-elektor.
+
++config I2C_EP93XX
++ tristate "Cirrus EP93XX interface"
++ depends on I2C && ARCH_EP93XX
++ select I2C_ALGOBIT
++ help
++ This supports the Cirrus EP93xx CPU family I2C bus. Choose this
++ if you want to access I2C devices connected to EECLK and EEDAT pins
++ of your EP93XX.
++
++ This support is also available as a module. If so, the module
++ will be called i2c-ep93xx.
++
++
+ config I2C_HYDRA
+ tristate "CHRP Apple Hydra Mac I/O I2C interface"
+ depends on I2C && PCI && PPC_CHRP && EXPERIMENTAL
+diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
+index f1df00f..fbb35f7 100644
+--- a/drivers/i2c/busses/Makefile
++++ b/drivers/i2c/busses/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_I2C_AMD756_S4882) += i2c-am
+ obj-$(CONFIG_I2C_AMD8111) += i2c-amd8111.o
+ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o
+ obj-$(CONFIG_I2C_ELEKTOR) += i2c-elektor.o
++obj-$(CONFIG_I2C_EP93XX) += i2c-ep93xx.o
+ obj-$(CONFIG_I2C_HYDRA) += i2c-hydra.o
+ obj-$(CONFIG_I2C_I801) += i2c-i801.o
+ obj-$(CONFIG_I2C_I810) += i2c-i810.o
+diff --git a/drivers/i2c/busses/i2c-ep93xx.c b/drivers/i2c/busses/i2c-ep93xx.c
+new file mode 100644
+index 0000000..1477bf3
+--- /dev/null
++++ b/drivers/i2c/busses/i2c-ep93xx.c
+@@ -0,0 +1,180 @@
++/* ------------------------------------------------------------------------ *
++ * i2c-ep933xx.c I2C bus glue for Cirrus EP93xx *
++ * ------------------------------------------------------------------------ *
++
++ Copyright (C) 2004 Michael Burian
++
++ Based on i2c-parport-light.c
++ Copyright (C) 2003-2004 Jean Delvare <khali@linux-fr.org>
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ * ------------------------------------------------------------------------ */
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/i2c-algo-bit.h>
++#include <asm/io.h>
++#include <asm/arch/regmap.h>
++
++/* 1/(2*clockfrequency) */
++#define EE_DELAY_USEC 50
++#define GPIOG_EECLK 1
++#define GPIOG_EEDAT 2
++
++/* ----- I2C algorithm call-back functions and structures ----------------- */
++
++static void ep93xx_setscl(void *data, int state)
++{
++ unsigned int val, dir;
++
++ val = readl(GPIO_PGDR);
++ dir = readl(GPIO_PGDDR);
++
++ /* Configure the clock line as output. */
++ dir |= GPIOG_EECLK;
++ writel(dir, GPIO_PGDDR);
++
++ /* Set clock line to state */
++ if (state)
++ val |= GPIOG_EECLK;
++ else
++ val &= ~GPIOG_EECLK;
++
++ writel(val, GPIO_PGDR);
++}
++
++static void ep93xx_setsda(void *data, int state)
++{
++ unsigned int val, dir;
++ val = readl(GPIO_PGDR);
++ dir = readl(GPIO_PGDDR);
++
++ /* Configure the data line as output. */
++ dir |= GPIOG_EEDAT;
++ writel(dir, GPIO_PGDDR);
++
++ /* Set data line to state */
++ if (state)
++ val |= GPIOG_EEDAT;
++ else
++ val &= ~GPIOG_EEDAT;
++
++ writel(val, GPIO_PGDR);
++}
++
++static int ep93xx_getscl(void *data)
++{
++ unsigned int val, dir;
++ val = readl(GPIO_PGDR);
++ dir = readl(GPIO_PGDDR);
++
++ /* Configure the clock line as input */
++ dir &= ~GPIOG_EECLK;
++ writel(dir, GPIO_PGDDR);
++
++ /* Return state of the clock line */
++ return (readl(GPIO_PGDR) & GPIOG_EECLK) ? 1 : 0;
++}
++
++static int ep93xx_getsda(void *data)
++{
++ unsigned int val, dir;
++ val = readl(GPIO_PGDR);
++ dir = readl(GPIO_PGDDR);
++
++ /* Configure the data line as input */
++ dir &= ~GPIOG_EEDAT;
++ writel(dir, GPIO_PGDDR);
++
++ /* Return state of the data line */
++ return (readl(GPIO_PGDR) & GPIOG_EEDAT) ? 1 : 0;
++}
++
++static struct i2c_algo_bit_data ep93xx_algo_data = {
++ .setsda = ep93xx_setsda,
++ .setscl = ep93xx_setscl,
++ .getsda = ep93xx_getsda,
++ .getscl = ep93xx_getscl,
++ .udelay = EE_DELAY_USEC,
++ .mdelay = EE_DELAY_USEC * 1000,
++ .timeout = HZ,
++};
++
++/* ----- I2c structure ---------------------------------------------------- */
++
++static struct i2c_adapter ep93xx_adapter = {
++ .owner = THIS_MODULE,
++ .class = I2C_CLASS_HWMON,
++ .id = I2C_HW_B_LP,
++ .algo_data = &ep93xx_algo_data,
++ .name = "EP93XX I2C interface",
++};
++
++/* ----- Module loading, unloading and information ------------------------ */
++
++static int __init i2c_ep93xx_init(void)
++{
++ unsigned long uiVal, uiDDR;
++
++ /* Read the current value of the GPIO data and data direction registers. */
++ uiVal = readl(GPIO_PGDR);
++ uiDDR = readl(GPIO_PGDDR);
++
++ /* If the GPIO pins have not been configured since reset, the data
++ * and clock lines will be set as inputs and with data value of 0.
++ * External pullup resisters are pulling them high.
++ * Set them both high before configuring them as outputs. */
++ uiVal |= (GPIOG_EEDAT | GPIOG_EECLK);
++ writel(uiVal, GPIO_PGDR);
++
++ /* Delay to meet the EE Interface timing specification. */
++ udelay(EE_DELAY_USEC);
++
++ /* Configure the EE data and clock lines as outputs. */
++ writel(0x3, GPIO_EEDRIVE); /* use open drain outputs! */
++ uiDDR |= (GPIOG_EEDAT | GPIOG_EECLK);
++ writel(uiDDR, GPIO_PGDDR);
++
++ /* Delay to meet the EE Interface timing specification. */
++ udelay(EE_DELAY_USEC);
++
++ /* Reset hardware to a sane state (SCL and SDA high) */
++ ep93xx_setsda(NULL, 1);
++ ep93xx_setscl(NULL, 1);
++
++ if (i2c_bit_add_bus(&ep93xx_adapter) < 0) {
++ printk(KERN_ERR "i2c-ep93xx: Unable to register with I2C\n");
++ return -ENODEV;
++ }
++
++ return 0;
++}
++
++static void __exit i2c_ep93xx_exit(void)
++{
++ i2c_bit_del_bus(&ep93xx_adapter);
++}
++
++MODULE_AUTHOR("Michael Burian");
++MODULE_DESCRIPTION("I2C bus glue for Cirrus EP93xx processors");
++MODULE_LICENSE("GPL");
++
++module_init(i2c_ep93xx_init);
++module_exit(i2c_ep93xx_exit);
+diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
+index f9fae28..45f9286 100644
+--- a/drivers/i2c/chips/Kconfig
++++ b/drivers/i2c/chips/Kconfig
+@@ -25,6 +25,18 @@ config SENSORS_DS1374
+ This driver can also be built as a module. If so, the module
+ will be called ds1374.
+
++config SENSORS_DS1307
++ tristate "Dallas Semiconductor DS1307 RTC"
++ depends on I2C && EXPERIMENTAL
++ help
++ If you say yes here you get support for the Dallas Semiconductor
++ DS1307 RTC. Usually only embedded devices will need this.
++
++ Only say yes here if your sure you have such a chip.
++
++ This driver can also be built as a module. If so, the module
++ will be called ds1307.
++
+ config SENSORS_EEPROM
+ tristate "EEPROM reader"
+ depends on I2C && EXPERIMENTAL
+diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
+index 46178b5..90be351 100644
+--- a/drivers/i2c/chips/Makefile
++++ b/drivers/i2c/chips/Makefile
+@@ -3,6 +3,7 @@
+ #
+
+ obj-$(CONFIG_SENSORS_DS1337) += ds1337.o
++obj-$(CONFIG_SENSORS_DS1307) += ds1307.o
+ obj-$(CONFIG_SENSORS_DS1374) += ds1374.o
+ obj-$(CONFIG_SENSORS_EEPROM) += eeprom.o
+ obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
+diff --git a/drivers/i2c/chips/ds1307.c b/drivers/i2c/chips/ds1307.c
+new file mode 100644
+index 0000000..76ea8b8
+--- /dev/null
++++ b/drivers/i2c/chips/ds1307.c
+@@ -0,0 +1,651 @@
++/*
++ * ds1307.c
++ *
++ * Device driver for Dallas Semiconductor's Real Time Controller DS1307.
++ *
++ * Copyright (C) 2002 Intrinsyc Software Inc.
++ *
++ * 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/config.h>
++#include <linux/module.h>
++#include <linux/version.h>
++
++#include <linux/kernel.h>
++#include <linux/poll.h>
++#include <linux/i2c.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/rtc.h>
++#include <linux/string.h>
++#include <linux/miscdevice.h>
++#include <linux/proc_fs.h>
++
++#include "ds1307.h"
++
++#undef DEBUG
++#ifdef DEBUG
++static unsigned int rtc_debug = DEBUG;
++#define DPRINTK(i,x...) do { if (rtc_debug > (i)) printk(x); } while (0)
++#else
++#define rtc_debug 0 /* gcc will remove all the debug code for us */
++#define DPRINTK(i,x...) do { } while (0)
++#endif
++
++static unsigned short slave_address = DS1307_I2C_SLAVE_ADDR;
++
++struct i2c_driver ds1307_driver;
++struct i2c_client *ds1307_i2c_client = 0;
++
++static unsigned short ignore[] = { I2C_CLIENT_END };
++static unsigned short normal_addr[] = { DS1307_I2C_SLAVE_ADDR, I2C_CLIENT_END };
++
++static struct i2c_client_address_data addr_data = {
++ normal_i2c: normal_addr,
++ probe: ignore,
++ ignore: ignore,
++ force: ignore,
++};
++
++static int ds1307_rtc_ioctl( struct inode *, struct file *, unsigned int, unsigned long);
++static int ds1307_rtc_open(struct inode *inode, struct file *file);
++static int ds1307_rtc_release(struct inode *inode, struct file *file);
++
++static struct file_operations rtc_fops = {
++ owner: THIS_MODULE,
++ ioctl: ds1307_rtc_ioctl,
++ open: ds1307_rtc_open,
++ release: ds1307_rtc_release,
++};
++
++static struct miscdevice ds1307_rtc_miscdev = {
++ RTC_MINOR,
++ "rtc",
++ &rtc_fops
++};
++
++static int ds1307_probe(struct i2c_adapter *adap);
++static int ds1307_detach(struct i2c_client *client);
++static int ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg);
++
++struct i2c_driver ds1307_driver = {
++ .owner = THIS_MODULE,
++ .name = "DS1307",
++ .id = I2C_DRIVERID_DS1307,
++ .flags = I2C_DF_NOTIFY,
++ .attach_adapter = ds1307_probe,
++ .detach_client = ds1307_detach,
++ .command = ds1307_command,
++};
++
++static spinlock_t ds1307_rtc_lock = SPIN_LOCK_UNLOCKED;
++
++static int
++ds1307_readram( char *buf, int len)
++{
++ unsigned long flags;
++ unsigned char ad[1] = { 0 };
++ int ret;
++ struct i2c_msg msgs[2] = {
++ { ds1307_i2c_client->addr , 0, 1, ad },
++ { ds1307_i2c_client->addr , I2C_M_RD, len, buf } };
++
++ spin_lock_irqsave(&ds1307_rtc_lock, flags);
++ ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
++ spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
++
++ return ret;
++}
++
++static void
++ds1307_dumpram( void)
++{
++ unsigned char buf[DS1307_RAM_SIZE];
++ int ret;
++
++ ret = ds1307_readram( buf, DS1307_RAM_SIZE);
++
++ if( ret > 0)
++ {
++ int i;
++ for( i=0; i<DS1307_RAM_SIZE; i++)
++ {
++ printk ("%02X ", buf[i]);
++ if( (i%8) == 7) printk ("\n");
++ }
++ printk ("\n");
++ }
++}
++
++static void
++ds1307_enable_clock( int enable)
++{
++ unsigned char buf[2], ad[1] = { 0 };
++ struct i2c_msg msgs[2] = {
++ { ds1307_i2c_client->addr , 0, 1, ad },
++ { ds1307_i2c_client->addr , I2C_M_RD, 1, buf }
++ };
++ unsigned char ctrl_info;
++ int ret;
++
++ DPRINTK(1, "%s()\n", __FUNCTION__);
++
++ if (enable)
++ ctrl_info = SQW_ENABLE | RATE_32768HZ;
++ else
++ ctrl_info = SQW_DISABLE;
++ ret = ds1307_command(ds1307_i2c_client, DS1307_SETCTRL, &ctrl_info);
++ DPRINTK(2, "%s: set ctrl rtn'd %d\n", __FUNCTION__, ret);
++
++ /* read addr 0 (Clock-Halt bit and second counter */
++ ret = i2c_transfer(ds1307_i2c_client->adapter, msgs, 2);
++ DPRINTK(2, "%s: %s msg xfer rtn'd %d\n", __FUNCTION__, enable ? "enable" : "disable", ret);
++
++ if (enable)
++ buf[1] = buf[0] & ~CLOCK_HALT; /* clear Clock-Halt bit */
++ else
++ buf[1] = buf[0] | CLOCK_HALT; /* set Clock-Halt bit */
++ buf[0] = 0; /* control register address on DS1307 */
++
++ ret = i2c_master_send(ds1307_i2c_client, (char *)buf, 2);
++ DPRINTK(2, "%s: master send rtn'd %d\n", __FUNCTION__, ret);
++}
++
++static int
++ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt);
++
++static int
++ds1307_attach(struct i2c_adapter *adap, int addr, int kind)
++{
++ struct i2c_client *c;
++
++ DPRINTK(1, "%s()\n", __FUNCTION__);
++
++ c = (struct i2c_client *)kmalloc(sizeof(*c), GFP_KERNEL);
++ if (!c)
++ return -ENOMEM;
++ memset(c, 0, sizeof(*c));
++
++ strcpy(c->name, "DS1307");
++ c->flags = 0;
++ c->addr = addr;
++ c->adapter = adap;
++ c->driver = &ds1307_driver;
++
++ ds1307_i2c_client = c;
++ ds1307_enable_clock(1);
++
++#define DS1307_SET_TIME_ON_BOOT
++#ifdef DS1307_SET_TIME_ON_BOOT
++ {
++ struct rtc_time dt;
++ ds1307_get_datetime(c, &dt);
++ xtime.tv_sec = mktime(dt.tm_year + 1900,
++ dt.tm_mon + 1, /* tm_mon starts from 0 */
++ dt.tm_mday,
++ dt.tm_hour,
++ dt.tm_min,
++ dt.tm_sec);
++ }
++#endif
++
++ return i2c_attach_client(c);
++}
++
++static int
++ds1307_probe(struct i2c_adapter *adap)
++{
++ DPRINTK(1, "%s()\n", __FUNCTION__);
++
++ return i2c_probe(adap, &addr_data, ds1307_attach);
++}
++
++static int
++ds1307_detach(struct i2c_client *client)
++{
++ DPRINTK(1, "%s()\n", __FUNCTION__);
++
++ i2c_detach_client(client);
++ ds1307_enable_clock(0);
++
++ return 0;
++}
++
++static void
++ds1307_convert_to_time( struct rtc_time *dt, char *buf)
++{
++ dt->tm_sec = BCD_TO_BIN(buf[0]);
++ dt->tm_min = BCD_TO_BIN(buf[1]);
++
++ if ( TWELVE_HOUR_MODE(buf[2]) )
++ {
++ dt->tm_hour = HOURS_12(buf[2]);
++ if (HOURS_AP(buf[2])) /* PM */
++ {
++ dt->tm_hour += 12;
++ }
++ }
++ else /* 24-hour-mode */
++ {
++ dt->tm_hour = HOURS_24(buf[2]);
++ }
++
++ dt->tm_mday = BCD_TO_BIN(buf[4]);
++ /* dt->tm_mon is zero-based */
++ dt->tm_mon = BCD_TO_BIN(buf[5]) - 1;
++ /* year is 1900 + dt->tm_year */
++ dt->tm_year = BCD_TO_BIN(buf[6]) + 100;
++
++ if (rtc_debug > 1)
++ {
++ printk("ds1307_get_datetime: year = %d\n", dt->tm_year);
++ printk("ds1307_get_datetime: mon = %d\n", dt->tm_mon);
++ printk("ds1307_get_datetime: mday = %d\n", dt->tm_mday);
++ printk("ds1307_get_datetime: hour = %d\n", dt->tm_hour);
++ printk("ds1307_get_datetime: min = %d\n", dt->tm_min);
++ printk("ds1307_get_datetime: sec = %d\n", dt->tm_sec);
++ }
++}
++
++static int
++ds1307_get_datetime(struct i2c_client *client, struct rtc_time *dt)
++{
++ unsigned char buf[7], addr[1] = { 0 };
++ struct i2c_msg msgs[2] = {
++ { 0, 0, 1, addr },
++ { 0, I2C_M_RD, 7, buf }
++ };
++ int ret = -EIO;
++
++ DPRINTK(1, "%s()\n", __FUNCTION__);
++
++ if (client) {
++
++ msgs[0].addr = client->addr;
++ msgs[1].addr = client->addr;
++
++ memset(buf, 0, sizeof(buf));
++
++ ret = i2c_transfer(client->adapter, msgs, 2);
++
++ if (ret == 2) {
++ ds1307_convert_to_time( dt, buf);
++ ret = 0;
++ } else {
++ DPRINTK(0, "%s: i2c_transfer() returned %d\n", __FUNCTION__, ret);
++ }
++ }
++ return ret;
++}
++
++static int
++ds1307_set_datetime(struct i2c_client *client, struct rtc_time *dt, int datetoo)
++{
++ unsigned char buf[8];
++ int ret, len = 4;
++
++ DPRINTK(1, "%s()\n", __FUNCTION__);
++
++ if (!client) return -EIO;
++
++ if (rtc_debug > 1)
++ {
++ printk("ds1307_set_datetime: tm_year = %d\n", dt->tm_year);
++ printk("ds1307_set_datetime: tm_mon = %d\n", dt->tm_mon);
++ printk("ds1307_set_datetime: tm_mday = %d\n", dt->tm_mday);
++ printk("ds1307_set_datetime: tm_hour = %d\n", dt->tm_hour);
++ printk("ds1307_set_datetime: tm_min = %d\n", dt->tm_min);
++ printk("ds1307_set_datetime: tm_sec = %d\n", dt->tm_sec);
++ }
++
++ buf[0] = 0; /* register address on DS1307 */
++ buf[1] = (BIN_TO_BCD(dt->tm_sec));
++ buf[2] = (BIN_TO_BCD(dt->tm_min));
++ buf[3] = (BIN_TO_BCD(dt->tm_hour));
++
++ if (datetoo) {
++ len = 8;
++ /* we skip buf[4] as we don't use day-of-week. */
++ buf[5] = (BIN_TO_BCD(dt->tm_mday));
++ buf[6] = (BIN_TO_BCD(dt->tm_mon + 1));
++ /* The year only ranges from 0-99, we are being passed an offset from 1900,
++ * and the chip calulates leap years based on 2000, thus we adjust by 100.
++ */
++ buf[7] = (BIN_TO_BCD(dt->tm_year - 100));
++ }
++ ret = i2c_master_send(client, (char *)buf, len);
++ if (ret == len)
++ ret = 0;
++ else
++ DPRINTK(0, "%s: i2c_master_send() returned %d\n", __FUNCTION__, ret);
++
++ return ret;
++}
++
++static int
++ds1307_get_ctrl(struct i2c_client *client, unsigned char *ctrl)
++{
++ unsigned char addr[1] = { 7 }; /* control register address on DS1307 */
++ struct i2c_msg msgs[2] = {
++ { 0, 0, 1, addr },
++ { 0, I2C_M_RD, 1, ctrl }
++ };
++ int ret = -EIO;
++
++ DPRINTK(1, "%s()\n", __FUNCTION__);
++
++ if (client) {
++
++ msgs[0].addr = client->addr;
++ msgs[1].addr = client->addr;
++
++ *ctrl = 0;
++
++ ret = i2c_transfer(client->adapter, msgs, 2);
++
++ if (ret == 2) {
++ DPRINTK(2, "%s: info %d\n", __FUNCTION__, *ctrl);
++ ret = 0;
++ } else {
++ DPRINTK(0, "%s: i2c_transfer() returned %d\n", __FUNCTION__, ret);
++ }
++ }
++
++ return ret;
++}
++
++static int
++ds1307_set_ctrl(struct i2c_client *client, unsigned char *cinfo)
++{
++ unsigned char buf[2];
++ int ret;
++
++ buf[0] = 7; /* control register address on DS1307 */
++ buf[1] = *cinfo;
++
++ DPRINTK(2, "%s: info %d\n", __FUNCTION__, buf[1]);
++
++ ret = i2c_master_send(client, (char *)buf, 2);
++
++ return ret;
++}
++
++static int
++ds1307_read_mem(struct i2c_client *client, struct rtc_mem *mem)
++{
++ unsigned char addr[1];
++ struct i2c_msg msgs[2] = {
++ { client->addr, 0, 1, addr },
++ { client->addr, I2C_M_RD, mem->nr, mem->data }
++ };
++
++ if ( (mem->loc < DS1307_RAM_ADDR_START) ||
++ ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
++ return -EINVAL;
++
++ addr[0] = mem->loc;
++
++ return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
++}
++
++static int
++ds1307_write_mem(struct i2c_client *client, struct rtc_mem *mem)
++{
++ unsigned char addr[1];
++ struct i2c_msg msgs[2] = {
++ { client->addr, 0, 1, addr },
++ { client->addr, 0, mem->nr, mem->data }
++ };
++
++ if ( (mem->loc < DS1307_RAM_ADDR_START) ||
++ ((mem->loc + mem->nr -1) > DS1307_RAM_ADDR_END) )
++ return -EINVAL;
++
++ addr[0] = mem->loc;
++
++ return i2c_transfer(client->adapter, msgs, 2) == 2 ? 0 : -EIO;
++}
++
++static int
++ds1307_command(struct i2c_client *client, unsigned int cmd, void *arg)
++{
++ DPRINTK(1, "%s: cmd %d\n", __FUNCTION__, cmd);
++
++ switch (cmd) {
++ case DS1307_GETDATETIME:
++ return ds1307_get_datetime(client, arg);
++
++ case DS1307_SETTIME:
++ return ds1307_set_datetime(client, arg, 0);
++
++ case DS1307_SETDATETIME:
++ return ds1307_set_datetime(client, arg, 1);
++
++ case DS1307_GETCTRL:
++ return ds1307_get_ctrl(client, arg);
++
++ case DS1307_SETCTRL:
++ return ds1307_set_ctrl(client, arg);
++
++ case DS1307_MEM_READ:
++ return ds1307_read_mem(client, arg);
++
++ case DS1307_MEM_WRITE:
++ return ds1307_write_mem(client, arg);
++
++ default:
++ return -EINVAL;
++ }
++}
++
++static int
++ds1307_rtc_open(struct inode *inode, struct file *file)
++{
++ return 0;
++}
++
++static int
++ds1307_rtc_release(struct inode *inode, struct file *file)
++{
++ return 0;
++}
++
++static int
++ds1307_rtc_ioctl( struct inode *inode, struct file *file,
++ unsigned int cmd, unsigned long arg)
++{
++ unsigned long flags;
++ struct rtc_time wtime;
++ int status = 0;
++
++ DPRINTK(2, "%s: cmd %c %x\n", __FUNCTION__, (char)(cmd>>8)&0xff, cmd&0xff);
++
++ switch (cmd) {
++ default:
++ case RTC_UIE_ON:
++ case RTC_UIE_OFF:
++ case RTC_PIE_ON:
++ case RTC_PIE_OFF:
++ case RTC_AIE_ON:
++ case RTC_AIE_OFF:
++ case RTC_ALM_SET:
++ case RTC_ALM_READ:
++ case RTC_IRQP_READ:
++ case RTC_IRQP_SET:
++ case RTC_EPOCH_READ:
++ case RTC_EPOCH_SET:
++ case RTC_WKALM_SET:
++ case RTC_WKALM_RD:
++ status = -EINVAL;
++ break;
++
++ case RTC_RD_TIME:
++ spin_lock_irqsave(&ds1307_rtc_lock, flags);
++ ds1307_command( ds1307_i2c_client, DS1307_GETDATETIME, &wtime);
++ spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
++
++ if( copy_to_user((void *)arg, &wtime, sizeof (struct rtc_time)))
++ status = -EFAULT;
++ break;
++
++ case RTC_SET_TIME:
++ if (!capable(CAP_SYS_TIME))
++ {
++ status = -EACCES;
++ break;
++ }
++
++ if (copy_from_user(&wtime, (struct rtc_time *)arg, sizeof(struct rtc_time)) )
++ {
++ status = -EFAULT;
++ break;
++ }
++
++ spin_lock_irqsave(&ds1307_rtc_lock, flags);
++ ds1307_command( ds1307_i2c_client, DS1307_SETDATETIME, &wtime);
++ spin_unlock_irqrestore(&ds1307_rtc_lock,flags);
++ break;
++ }
++
++ return status;
++}
++
++static char *
++ds1307_mon2str( unsigned int mon)
++{
++ char *mon2str[12] = {
++ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
++ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
++ };
++ if( mon > 11) return "error";
++ else return mon2str[ mon];
++}
++
++static int ds1307_rtc_proc_output( char *buf)
++{
++#define CHECK(ctrl,bit) ((ctrl & bit) ? "yes" : "no")
++ unsigned char ram[DS1307_RAM_SIZE];
++ int ret;
++
++ char *p = buf;
++
++ ret = ds1307_readram( ram, DS1307_RAM_SIZE);
++ if( ret > 0)
++ {
++ int i;
++ struct rtc_time dt;
++ char text[9];
++
++ p += sprintf(p, "DS1307 (64x8 Serial Real Time Clock)\n");
++
++ ds1307_convert_to_time( &dt, ram);
++ p += sprintf(p, "Date/Time : %02d-%s-%04d %02d:%02d:%02d\n",
++ dt.tm_mday, ds1307_mon2str(dt.tm_mon), dt.tm_year + 1900,
++ dt.tm_hour, dt.tm_min, dt.tm_sec);
++
++ p += sprintf(p, "Clock halted : %s\n", CHECK(ram[0],0x80));
++ p += sprintf(p, "24h mode : %s\n", CHECK(ram[2],0x40));
++ p += sprintf(p, "Square wave enabled : %s\n", CHECK(ram[7],0x10));
++ p += sprintf(p, "Freq : ");
++
++ switch( ram[7] & 0x03)
++ {
++ case RATE_1HZ:
++ p += sprintf(p, "1Hz\n");
++ break;
++ case RATE_4096HZ:
++ p += sprintf(p, "4.096kHz\n");
++ break;
++ case RATE_8192HZ:
++ p += sprintf(p, "8.192kHz\n");
++ break;
++ case RATE_32768HZ:
++ default:
++ p += sprintf(p, "32.768kHz\n");
++ break;
++
++ }
++
++ p += sprintf(p, "RAM dump:\n");
++ text[8]='\0';
++ for( i=0; i<DS1307_RAM_SIZE; i++)
++ {
++ p += sprintf(p, "%02X ", ram[i]);
++
++ if( (ram[i] < 32) || (ram[i]>126)) ram[i]='.';
++ text[i%8] = ram[i];
++ if( (i%8) == 7) p += sprintf(p, "%s\n",text);
++ }
++ p += sprintf(p, "\n");
++ }
++ else
++ {
++ p += sprintf(p, "Failed to read RTC memory!\n");
++ }
++
++ return p - buf;
++}
++
++static int ds1307_rtc_read_proc(char *page, char **start, off_t off,
++ int count, int *eof, void *data)
++{
++ int len = ds1307_rtc_proc_output (page);
++ if (len <= off+count) *eof = 1;
++ *start = page + off;
++ len -= off;
++ if (len>count) len = count;
++ if (len<0) len = 0;
++ return len;
++}
++
++static __init int ds1307_init(void)
++{
++ int retval=0;
++
++ DPRINTK(1, "%s()\n", __FUNCTION__);
++
++ if (slave_address != 0xffff)
++ {
++ DPRINTK(2, "%s: slave address is %#x\n", __FUNCTION__, slave_address);
++ normal_addr[0] = slave_address;
++ }
++
++ if (normal_addr[0] == 0xffff)
++ {
++ printk(KERN_ERR"I2C: Invalid slave address for DS1307 RTC (%#x)\n",
++ normal_addr[0]);
++ return -EINVAL;
++ }
++
++ retval = i2c_add_driver(&ds1307_driver);
++
++ if (retval==0)
++ {
++ misc_register (&ds1307_rtc_miscdev);
++ create_proc_read_entry (PROC_DS1307_NAME, 0, 0, ds1307_rtc_read_proc, NULL);
++ printk("I2C: DS1307 RTC driver successfully loaded\n");
++ if (rtc_debug > 2) ds1307_dumpram();
++ }
++ return retval;
++}
++
++static __exit void ds1307_exit(void)
++{
++ DPRINTK(1, "%s()\n", __FUNCTION__);
++ remove_proc_entry (PROC_DS1307_NAME, NULL);
++ misc_deregister(&ds1307_rtc_miscdev);
++ i2c_del_driver(&ds1307_driver);
++}
++
++module_init(ds1307_init);
++module_exit(ds1307_exit);
++
++MODULE_PARM (slave_address, "i");
++MODULE_PARM_DESC (slave_address, "I2C slave address for DS1307 RTC.");
++
++MODULE_AUTHOR ("Intrinsyc Software Inc.");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/i2c/chips/ds1307.h b/drivers/i2c/chips/ds1307.h
+new file mode 100644
+index 0000000..bf8cc20
+--- /dev/null
++++ b/drivers/i2c/chips/ds1307.h
+@@ -0,0 +1,54 @@
++/*
++ * ds1307.h
++ *
++ * Copyright (C) 2002 Intrinsyc Software Inc.
++ *
++ * 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 DS1307_H
++#define DS1307_H
++
++#define DS1307_I2C_SLAVE_ADDR 0x68
++
++#define DS1307_RAM_ADDR_START 0x08
++#define DS1307_RAM_ADDR_END 0x3F
++#define DS1307_RAM_SIZE 0x40
++
++#define PROC_DS1307_NAME "driver/ds1307"
++
++struct rtc_mem {
++ unsigned int loc;
++ unsigned int nr;
++ unsigned char *data;
++};
++
++#define DS1307_GETDATETIME 0
++#define DS1307_SETTIME 1
++#define DS1307_SETDATETIME 2
++#define DS1307_GETCTRL 3
++#define DS1307_SETCTRL 4
++#define DS1307_MEM_READ 5
++#define DS1307_MEM_WRITE 6
++
++#define SQW_ENABLE 0x10 /* Square Wave Enable */
++#define SQW_DISABLE 0x00 /* Square Wave disable */
++
++#define RATE_32768HZ 0x03 /* Rate Select 32.768KHz */
++#define RATE_8192HZ 0x02 /* Rate Select 8.192KHz */
++#define RATE_4096HZ 0x01 /* Rate Select 4.096KHz */
++#define RATE_1HZ 0x00 /* Rate Select 1Hz */
++
++#define CLOCK_HALT 0x80 /* Clock Halt */
++
++#define BCD_TO_BIN(val) (((val)&15) + ((val)>>4)*10)
++#define BIN_TO_BCD(val) ((((val)/10)<<4) + (val)%10)
++
++#define TWELVE_HOUR_MODE(n) (((n)>>6)&1)
++#define HOURS_AP(n) (((n)>>5)&1)
++#define HOURS_12(n) BCD_TO_BIN((n)&0x1F)
++#define HOURS_24(n) BCD_TO_BIN((n)&0x3F)
++
++#endif
+diff --git a/drivers/i2c/chips/ds1337.c b/drivers/i2c/chips/ds1337.c
+index 02682fb..6a28f08 100644
+--- a/drivers/i2c/chips/ds1337.c
++++ b/drivers/i2c/chips/ds1337.c
+@@ -338,12 +338,37 @@ exit:
+ static void ds1337_init_client(struct i2c_client *client)
+ {
+ s32 val;
++ u8 status, control;
++
++ /* On some boards, the RTC isn't configured by boot firmware.
++ * Handle that case by starting/configuring the RTC now.
++ */
++ status = i2c_smbus_read_byte_data(client, DS1337_REG_STATUS);
++ control = i2c_smbus_read_byte_data(client, DS1337_REG_CONTROL);
++
++ if ((status & 0x80) || (control & 0x80)) {
++ /* RTC not running */
++ u8 buf[16];
++ struct i2c_msg msg[1];
++
++ dev_dbg(&client->dev, "%s: RTC not running!\n", __FUNCTION__);
++
++ /* Initialize all, including STATUS and CONTROL to zero */
++ memset(buf, 0, sizeof(buf));
++ msg[0].addr = client->addr;
++ msg[0].flags = 0;
++ msg[0].len = sizeof(buf);
++ msg[0].buf = &buf[0];
++
++ i2c_transfer(client->adapter, msg, 1);
++ } else {
++ /* Running: ensure that device is set in 24-hour mode */
++ val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
++ if ((val >= 0) && (val & (1 << 6)))
++ i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
++ val & 0x3f);
++ }
+
+- /* Ensure that device is set in 24-hour mode */
+- val = i2c_smbus_read_byte_data(client, DS1337_REG_HOUR);
+- if ((val >= 0) && (val & (1 << 6)))
+- i2c_smbus_write_byte_data(client, DS1337_REG_HOUR,
+- val & 0x3f);
+ }
+
+ static int ds1337_detach_client(struct i2c_client *client)
+diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig
+index 1c81174..e0fcc08 100644
+--- a/drivers/ide/Kconfig
++++ b/drivers/ide/Kconfig
+@@ -314,6 +314,18 @@ config BLK_DEV_CMD640_ENHANCED
+ and your BIOS does not already do this for you, then say Y here.
+ Otherwise say N.
+
++config BLK_DEV_EP93XX
++ bool "EP93xx support"
++ depends on (ARCH_EP9312 || ARCH_EP9315)
++ help
++ If you want IDE support for your EP93xx based board say Y here.
++
++config BLK_DEV_IDEDMA_EP93XX
++ bool "EP93xx DMA support"
++ depends on BLK_DEV_EP93XX && EP93XX_DMA
++ help
++ If you want DMA support for your EP93xx based board say Y here.
++
+ config BLK_DEV_IDEPNP
+ bool "PNP EIDE support"
+ depends on PNP
+@@ -813,7 +825,7 @@ config BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ
+ depends BLK_DEV_IDE_AU1XXX
+
+ config IDE_ARM
+- def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK)
++ def_bool ARM && (ARCH_A5K || ARCH_CLPS7500 || ARCH_RPC || ARCH_SHARK || BLK_DEV_EP93XX)
+
+ config BLK_DEV_IDE_ICSIDE
+ tristate "ICS IDE interface support"
+@@ -1047,7 +1059,7 @@ config BLK_DEV_UMC8672
+ endif
+
+ config BLK_DEV_IDEDMA
+- def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA
++ def_bool BLK_DEV_IDEDMA_PCI || BLK_DEV_IDEDMA_PMAC || BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA || BLK_DEV_IDEDMA_EP93XX
+
+ config IDEDMA_IVB
+ bool "IGNORE word93 Validation BITS"
+diff --git a/drivers/ide/arm/Makefile b/drivers/ide/arm/Makefile
+index 6a78f07..cf0f91a 100644
+--- a/drivers/ide/arm/Makefile
++++ b/drivers/ide/arm/Makefile
+@@ -2,5 +2,6 @@
+ obj-$(CONFIG_BLK_DEV_IDE_ICSIDE) += icside.o
+ obj-$(CONFIG_BLK_DEV_IDE_RAPIDE) += rapide.o
+ obj-$(CONFIG_BLK_DEV_IDE_BAST) += bast-ide.o
++obj-$(CONFIG_BLK_DEV_EP93XX) += ide-ep93xx.o
+
+ EXTRA_CFLAGS := -Idrivers/ide
+diff --git a/drivers/ide/arm/ide-ep93xx.c b/drivers/ide/arm/ide-ep93xx.c
+new file mode 100644
+index 0000000..75fbbf5
+--- /dev/null
++++ b/drivers/ide/arm/ide-ep93xx.c
+@@ -0,0 +1,1957 @@
++/*****************************************************************************
++ *
++ * drivers/ide/ide-ep93xx.c
++ *
++ * Copyright (c) 2003 Cirrus Logic, Inc.
++ *
++ * Some code based in whole or in part on:
++ *
++ * linux/drivers/ide/ide-dma.c Version 4.13 May 21, 2003
++ *
++ * Copyright (c) 1999-2000 Andre Hedrick <andre@linux-ide.org>
++ * May be copied or modified under the terms of the GNU General Public License
++ *
++ * Portions Copyright Red Hat 2003
++ *
++ * Special Thanks to Mark for his Six years of work.
++ *
++ * Copyright (c) 1995-1998 Mark Lord
++ * May be copied or modified under the terms of the GNU General Public License
++ *
++ *
++ * Some code taken from the PowerMac implentation
++ *
++ * Copyright (C) 1998-2001 Paul Mackerras & Ben. Herrenschmidt
++ *
++ * 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
++ *
++ * ***************************************************************************
++ *
++ * Cirrus Logic's EP93XX architecture specific ide driver. This driver
++ * supports the following ide transfer modes:
++ * PIO modes 0 - 4
++ * MDMA modes 0 - 2
++ * UDMA modes 0 - 4
++ *
++ * 2/17/04 - TO - Initial DMA support. Only UDMA on ATA hard drives for now.
++ *
++ ****************************************************************************/
++#include <linux/ide.h>
++#include <linux/delay.h>
++#include <asm/io.h>
++#include <asm/ide.h>
++#include <asm/io.h>
++
++#include <asm/arch/ide.h>
++
++#include <asm/arch/dma.h>
++#include <asm/hardware.h>
++
++/*****************************************************************************
++ *
++ * Debugging macros
++ *
++ ****************************************************************************/
++#undef DEBUG
++ /* #define DEBUG 1 */
++#ifdef DEBUG
++#define DPRINTK( x... ) printk( ##x )
++#else
++#define DPRINTK( x... )
++#endif
++
++/*
++ * IDE control register mask used when setting the CS0n, CS1n and DA bits
++ * in this register.
++ */
++#define IDECR_REG_MASK (IDECtrl_CS0n | IDECtrl_CS1n | IDECtrl_DA_MASK)
++
++/*****************************************************************************
++ *
++ * Functions and macros for handling dma transfers.
++ *
++ ****************************************************************************/
++#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX
++
++/*****************************************************************************
++ *
++ * Our Physical Region Descriptor (PRD) table should be large enough
++ * to handle the biggest I/O request we are likely to see. Since requests
++ * can have no more than 256 sectors, and since the typical blocksize is
++ * two or more sectors, we could get by with a limit of 128 entries here for
++ * the usual worst case. Most requests seem to include some contiguous blocks,
++ * further reducing the number of table entries required.
++ *
++ * The driver reverts to PIO mode for individual requests that exceed
++ * this limit (possible with 512 byte blocksizes, eg. MSDOS f/s), so handling
++ * 100% of all crazy scenarios here is not necessary.
++ *
++ * As it turns out though, we must allocate a full 4KB page for this,
++ * so the two PRD tables (ide0 & ide1) will each get half of that,
++ * allowing each to have about 256 entries (8 bytes each) from this.
++ *
++ ****************************************************************************/
++#define PRD_BYTES 8
++#define PRD_ENTRIES (PAGE_SIZE / (2 * PRD_BYTES))
++
++/*****************************************************************************
++ *
++ * Global to keep track of the number of entries in the dma buffer
++ * table for each transfer.
++ *
++ ****************************************************************************/
++static int g_prd_count;
++static unsigned int g_prd_total;
++static unsigned int g_prd_returned;
++static unsigned int g_dma_table_base;
++
++/*****************************************************************************
++ *
++ * Global to set during the dma callback function to indicate that from
++ * the dma perspective, the transfer is complete.
++ *
++ ****************************************************************************/
++static unsigned int g_done;
++
++/*****************************************************************************
++ *
++ * The following is directly from ide-dma.c.
++ *
++ ****************************************************************************/
++struct drive_list_entry {
++ const char *id_model;
++ const char *id_firmware;
++};
++
++static const struct
++drive_list_entry drive_whitelist[] = {
++ {"Micropolis 2112A", "ALL"},
++ {"CONNER CTMA 4000", "ALL"},
++ {"CONNER CTT8000-A", "ALL"},
++ {"ST34342A", "ALL"},
++ {NULL, NULL}
++};
++
++static const struct
++drive_list_entry drive_blacklist[] = {
++ {"WDC AC11000H", "ALL"},
++ {"WDC AC22100H", "ALL"},
++ {"WDC AC32500H", "ALL"},
++ {"WDC AC33100H", "ALL"},
++ {"WDC AC31600H", "ALL"},
++ {"WDC AC32100H", "24.09P07"},
++ {"WDC AC23200L", "21.10N21"},
++ {"Compaq CRD-8241B", "ALL"},
++ {"CRD-8400B", "ALL"},
++ {"CRD-8480B", "ALL"},
++ {"CRD-8480C", "ALL"},
++ {"CRD-8482B", "ALL"},
++ {"CRD-84", "ALL"},
++ {"SanDisk SDP3B", "ALL"},
++ {"SanDisk SDP3B-64", "ALL"},
++ {"SANYO CD-ROM CRD", "ALL"},
++ {"HITACHI CDR-8", "ALL"},
++ {"HITACHI CDR-8335", "ALL"},
++ {"HITACHI CDR-8435", "ALL"},
++ {"Toshiba CD-ROM XM-6202B", "ALL"},
++ {"CD-532E-A", "ALL"},
++ {"E-IDE CD-ROM CR-840", "ALL"},
++ {"CD-ROM Drive/F5A", "ALL"},
++ {"RICOH CD-R/RW MP7083A", "ALL"},
++ {"WPI CDD-820", "ALL"},
++ {"SAMSUNG CD-ROM SC-148C", "ALL"},
++ {"SAMSUNG CD-ROM SC-148F", "ALL"},
++ {"SAMSUNG CD-ROM SC", "ALL"},
++ {"SanDisk SDP3B-64", "ALL"},
++ {"SAMSUNG CD-ROM SN-124", "ALL"},
++ {"PLEXTOR CD-R PX-W8432T", "ALL"},
++ {"ATAPI CD-ROM DRIVE 40X MAXIMUM", "ALL"},
++ {"_NEC DV5800A", "ALL"},
++ {NULL, NULL}
++};
++
++/*****************************************************************************
++ *
++ * This is directly from ide-dma.c
++ *
++ * in_drive_list - look for drive in black/white list
++ * @id: drive identifier
++ * @drive_table: list to inspect
++ *
++ * Look for a drive in the blacklist and the whitelist tables
++ * Returns 1 if the drive is found in the table.
++ *
++ ****************************************************************************/
++static int
++in_drive_list(struct hd_driveid *id, const struct drive_list_entry *drive_table)
++{
++ for (; drive_table->id_model; drive_table++)
++ if ((!strcmp(drive_table->id_model, id->model)) &&
++ ((!strstr(drive_table->id_firmware, id->fw_rev)) ||
++ (!strcmp(drive_table->id_firmware, "ALL"))))
++ return 1;
++ return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_intr() is the handler for disk read/write DMA interrupts
++ *
++ ****************************************************************************/
++ide_startstop_t ep93xx_ide_dma_intr(ide_drive_t * drive)
++{
++ int i;
++ byte stat, dma_stat;
++
++ DPRINTK("\n dma_intr \n");
++
++ /*
++ * Disable the dma for this transfer and cleanup.
++ */
++ dma_stat = ep93xx_ide_dma_end(drive);
++
++ /*
++ * Get status from the ide device.
++ */
++ stat = HWIF(drive)->INB(IDE_STATUS_REG);
++
++ if (OK_STAT(stat, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
++ if (!dma_stat) {
++ struct request *rq = HWGROUP(drive)->rq;
++
++ for (i = rq->nr_sectors; i > 0;) {
++ i -= rq->current_nr_sectors;
++ DRIVER(drive)->end_request(drive, 1);
++ }
++
++ return ide_stopped;
++ }
++
++ printk("%s: dma_intr: bad DMA status (dma_stat=%x)\n",
++ drive->name, dma_stat);
++ }
++
++ return DRIVER(drive)->error(drive, __FUNCTION__, stat);
++}
++
++/*****************************************************************************
++ *
++ * ide_build_sglist()
++ *
++ * Builds a table of buffers to be used by the dma. Each buffer consists
++ * of a region of memory which is contiguous in virtual memory.
++ *
++ ****************************************************************************/
++static int ide_build_sglist(ide_hwif_t * hwif, struct request *rq)
++{
++ struct buffer_head *buf_head;
++ struct scatterlist *sg = hwif->sg_table;
++ int nents = 0;
++
++ if (hwif->sg_dma_active)
++ BUG();
++
++ DPRINTK("\nbuild_sglist: sg_table 0x%x, ", hwif->sg_table);
++
++ /*
++ * Set up the direction of the command
++ */
++ if (rq->cmd == READ) {
++ hwif->sg_dma_direction = EP93XX_DMA_FROMDEVICE;
++ } else {
++ hwif->sg_dma_direction = EP93XX_DMA_TODEVICE;
++ }
++
++ /*
++ * Get a pointer to the buffer head.
++ */
++ buf_head = rq->bh;
++
++ do {
++ unsigned char *virt_addr = buf_head->b_data;
++ unsigned int size = buf_head->b_size;
++
++ if (nents >= PRD_ENTRIES) {
++ return 0;
++ }
++
++ while ((buf_head = buf_head->b_reqnext) != NULL) {
++ if ((virt_addr + size) !=
++ (unsigned char *)buf_head->b_data) {
++ break;
++ }
++
++ size += buf_head->b_size;
++ }
++ memset(&sg[nents], 0, sizeof(*sg));
++ sg[nents].address = virt_addr;
++ sg[nents].length = size;
++ nents++;
++ } while (buf_head != NULL);
++
++ /*
++ * This call to map_sg will return the number of entries
++ * for which DMAable memory could be mapped.
++ */
++ return ep93xx_map_sg(sg, nents, hwif->sg_dma_direction);
++}
++
++/****************************************************************************
++ *
++ * report_drive_dmaing()
++ *
++ ****************************************************************************/
++int report_drive_dmaing(ide_drive_t * drive)
++{
++ struct hd_driveid *id = drive->id;
++
++ if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
++ (id->dma_ultra & (id->dma_ultra >> 14) & 3)) {
++ if ((id->dma_ultra >> 15) & 1) {
++ /*
++ * UDMA enabled
++ */
++ printk(", UDMA(mode 7)");
++ } else {
++ /*
++ * UDMA enabled.
++ */
++ printk(", UDMA(133)");
++ }
++ } else if ((id->field_valid & 4) && (eighty_ninty_three(drive)) &&
++ (id->dma_ultra & (id->dma_ultra >> 11) & 7)) {
++ DPRINTK("\n report_drive_dmaing: %d \n", id->dma_ultra);
++ if ((id->dma_ultra >> 13) & 1) {
++ /*
++ * UDMA enabled!
++ */
++ printk(", UDMA(100)");
++ } else if ((id->dma_ultra >> 12) & 1) {
++ /*
++ * UDMA enabled.
++ */
++ printk(", UDMA(66)");
++ } else {
++ /*
++ * UDMA enabled.
++ */
++ printk(", UDMA(44)");
++ }
++ } else if ((id->field_valid & 4) &&
++ (id->dma_ultra & (id->dma_ultra >> 8) & 7)) {
++ if ((id->dma_ultra >> 10) & 1) {
++ /*
++ * UDMA enabled.
++ */
++ printk(", UDMA(33)");
++ } else if ((id->dma_ultra >> 9) & 1) {
++ /*
++ * UDMA enabled.
++ */
++ printk(", UDMA(25)");
++ } else {
++ /*
++ * UDMA enabled.
++ */
++ printk(", UDMA(16)");
++ }
++ } else if (id->field_valid & 4) {
++ /*
++ * Can be enabled.
++ */
++ printk(", (U)DMA capable, but not enabled");
++ } else {
++ /*
++ * maybe MDMA?
++ */
++ printk(", DMA");
++ }
++
++ return 1;
++}
++
++/*****************************************************************************
++ *
++ * ide_build_dmatable() prepares a dma request.
++ * Returns 0 if all went okay, returns 1 otherwise.
++ *
++ ****************************************************************************/
++int ide_build_dmatable(ide_drive_t * drive)
++{
++ unsigned int *table = HWIF(drive)->dmatable_cpu;
++ unsigned int count = 0;
++ int i;
++ struct scatterlist *sg;
++ unsigned int is_trm290_chipset = 0;
++
++ HWIF(drive)->sg_nents = i =
++ ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
++
++ if (!i)
++ return 0;
++
++ sg = HWIF(drive)->sg_table;
++
++ while (i && sg_dma_len(sg)) {
++ u32 cur_addr;
++ u32 cur_len;
++
++ cur_addr = sg_dma_address(sg);
++ cur_len = sg_dma_len(sg);
++
++ /* 1
++ * Fill in the dma table, without crossing any 64kB boundaries.
++ * Most hardware requires 16-bit alignment of all blocks,
++ * but the trm290 requires 32-bit alignment.
++ */
++ while (cur_len) {
++
++ if (count++ >= PRD_ENTRIES) {
++ printk("%s: DMA table too small\n",
++ drive->name);
++ goto use_pio_instead;
++ } else {
++ u32 xcount, bcount =
++ 0x10000 - (cur_addr & 0xffff);
++
++ if (bcount > cur_len)
++ bcount = cur_len;
++ *table++ = cpu_to_le32(cur_addr);
++ xcount = bcount & 0xffff;
++ if (is_trm290_chipset)
++ xcount = ((xcount >> 2) - 1) << 16;
++ if (xcount == 0x0000) {
++ /*
++ * Most chipsets correctly interpret a length of 0x0000 as 64KB,
++ * but at least one (e.g. CS5530) misinterprets it as zero (!).
++ * So here we break the 64KB entry into two 32KB entries instead.
++ */
++ if (count++ >= PRD_ENTRIES) {
++ printk
++ ("%s: DMA table too small\n",
++ drive->name);
++ goto use_pio_instead;
++ }
++ *table++ = cpu_to_le32(0x8000);
++ *table++ =
++ cpu_to_le32(cur_addr + 0x8000);
++ xcount = 0x8000;
++ }
++ *table++ = cpu_to_le32(xcount);
++ cur_addr += bcount;
++ cur_len -= bcount;
++ }
++ }
++ sg++;
++ i--;
++ }
++
++ if (count) {
++ if (!is_trm290_chipset)
++ *--table |= cpu_to_le32(0x80000000);
++ return count;
++ }
++ printk("%s: empty DMA table?\n", drive->name);
++
++ use_pio_instead:
++ /*
++ * Revert to PIO for this request.
++ */
++ HWIF(drive)->sg_dma_active = 0;
++ return 0;
++}
++
++/*****************************************************************************
++ *
++ * ide_destroy_dmatable()
++ *
++ * Teardown mappings after DMA has completed.
++ *
++ ****************************************************************************/
++void ide_destroy_dmatable(ide_drive_t * drive)
++{
++ /*
++ * Restore the original dma table base address.
++ */
++ HWIF(drive)->dmatable_cpu = g_dma_table_base;
++
++ /*
++ * Nothing much to do here.
++ */
++ HWIF(drive)->sg_dma_active = 0;
++}
++
++/*****************************************************************************
++ *
++ * ide_release_dma()
++ *
++ * This function releases the memory allocated for the scatter gather list
++ * and for the dma table, and frees the dma channel.
++ *
++ ****************************************************************************/
++void ep93xx_ide_release_dma(ide_hwif_t * hwif)
++{
++ /*
++ * Check if we have a valid dma handle.
++ */
++ if (hwif->hw.dma != NULL) {
++ /*
++ * Pause the DMA channel.
++ */
++ ep93xx_dma_pause(hwif->hw.dma, 1, 0);
++
++ /*
++ * Flush the DMA channel
++ */
++ ep93xx_dma_flush(hwif->hw.dma);
++ }
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_callback()
++ *
++ * Registered with the ep93xx dma driver and called at the end of the dma
++ * interrupt handler, this function should process the dma buffers.
++ *
++ ****************************************************************************/
++
++static void
++ep93xx_ide_callback(ep93xx_dma_int_t dma_int, ep93xx_dma_dev_t device,
++ unsigned int user_data)
++{
++ ide_drive_t *drive = (ide_drive_t *) user_data;
++ ide_hwif_t *hwif = HWIF(drive);
++ unsigned int temp;
++
++ /*
++ * Retrieve from the dma interface as many used buffers as are
++ * available.
++ */
++ while (ep93xx_dma_remove_buffer(hwif->hw.dma, &temp) == 0) {
++ g_prd_returned++;
++
++ }
++
++ /*
++ * Add new buffers if we have any available.
++ */
++ while (g_prd_count) {
++ /*
++ * Check if this is a read or write operation.
++ */
++ if (hwif->sg_dma_direction == 2) {
++ /*
++ * Set up buffers for a read op.
++ */
++ temp =
++ ep93xx_dma_add_buffer(hwif->hw.dma, hwif->dma_base,
++ *hwif->dmatable_cpu++,
++ *hwif->dmatable_cpu++, 0,
++ g_prd_count);
++ } else {
++ /*
++ * Set up buffers for a write op.
++ */
++ temp =
++ ep93xx_dma_add_buffer(hwif->hw.dma,
++ *hwif->dmatable_cpu++,
++ hwif->dma_base,
++ *hwif->dmatable_cpu++, 0,
++ g_prd_count);
++ }
++
++ /*
++ * Add a buffer to the dma interface.
++ */
++ if (temp != 0) {
++ /*
++ * This buffer didn't make it into the dma
++ * interface, so move the dma table pointer
++ * to the start of the current entry.
++ */
++ hwif->dmatable_cpu -= 4;
++ break;
++ }
++
++ /*
++ * Decrement the count of dmatable entries
++ */
++ g_prd_count--;
++ }
++
++ /*
++ * Check if the transfer is complete.
++ */
++ if (dma_int == DONE) {
++ g_done = 1;
++ }
++
++ if (g_prd_returned == g_prd_total) {
++ g_done = 1;
++ }
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_dma_timer_expiry()
++ *
++ *
++ * dma_timer_expiry - handle a DMA timeout
++ * @drive: Drive that timed out
++ *
++ * An IDE DMA transfer timed out. In the event of an error we ask
++ * the driver to resolve the problem, if a DMA transfer is still
++ * in progress we continue to wait (arguably we need to add a
++ * secondary 'I dont care what the drive thinks' timeout here)
++ * Finally if we have an interrupt we let it complete the I/O.
++ * But only one time - we clear expiry and if it's still not
++ * completed after WAIT_CMD, we error and retry in PIO.
++ * This can occur if an interrupt is lost or due to hang or bugs.
++ *
++ *
++ ****************************************************************************/
++static int ep93xx_idedma_timer_expiry(ide_drive_t * drive)
++{
++ ide_hwif_t *hwif = HWIF(drive);
++ u8 dev_stat = hwif->INB(IDE_ALTSTATUS_REG);
++ u8 irq_stat = ep93xx_ide_regs->IDECR.Value & IDECtrl_INTRQ;
++
++ printk(KERN_WARNING
++ "%s: dma_timer_expiry: dev status == 0x%02x, done= %d, irq= %d\n",
++ drive->name, dev_stat, g_done, irq_stat);
++
++ /*
++ * Check if the device is busy, or the dma engine is still working.
++ */
++ if ((dev_stat & 0x80) || !g_done) /* BUSY Stupid Early Timer !! */
++ return (2 * WAIT_CMD);
++
++ /*
++ * Clear the expiry handler in case we decide to wait more,
++ * next time timer expires it is an error
++ */
++ HWGROUP(drive)->expiry = NULL;
++
++ /*
++ * the device is not busy, so check if there's an error, or if the
++ * interrupt is asserted.
++ */
++ if (dev_stat & 0x01) /* ERROR */
++ return -1;
++
++ if (irq_stat || g_done) /* Got an Interrupt or the dma is done */
++ return WAIT_CMD;
++
++ return 0; /* Unknown status -- reset the bus */
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_config_ide_dma()
++ *
++ * This function allocates dma-able memory and configures the ep93xx dma
++ * interface for use with the ide interface. This only need be done
++ * once for the interface. So, if this is the second drive, we don't have
++ * much to do here.
++ *
++ ****************************************************************************/
++static int ep93xx_config_ide_dma(ide_drive_t * drive)
++{
++ DPRINTK("ep93xx_config_ide_dma\n");
++
++ /*
++ * Success.
++ */
++ return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_config_ide_device()
++ *
++ * This function sets up the ep93xx ide device for a dma transfer by first
++ * probing to find the best dma mode supported by the device.
++ *
++ * Returns a 0 for success, and a 1 otherwise.
++ *
++ ****************************************************************************/
++static unsigned int ep93xx_config_ide_device(ide_drive_t * drive)
++{
++ struct hd_driveid *id = drive->id;
++ byte transfer = 0;
++
++ DPRINTK("%s: ep93xx_config_ide_device - dma on\n", HWIF(drive)->name);
++
++ /*
++ * check if the device supports a udma mode.
++ */
++ if (transfer = (id->dma_ultra & 0x001F)) {
++ DPRINTK("IDE: udma xfer support, transfer = %d \n", transfer);
++
++ /*
++ * UDMA mode 4 support.
++ */
++ if (transfer & 0x10) {
++ transfer = XFER_UDMA_4;
++ }
++ /*
++ * UDMA mode 3 support.
++ */
++ else if (transfer & 0x08) {
++ transfer = XFER_UDMA_3;
++ }
++ /*
++ * UDMA mode 2.
++ */
++ else if (transfer & 0x04) {
++ transfer = XFER_UDMA_2;
++ }
++ /*
++ * UDMA mode 1.
++ */
++ else if (transfer & 0x02) {
++ transfer = XFER_UDMA_1;
++ }
++ /*
++ * UDMA mode 0.
++ */
++ else if (transfer & 0x01) {
++ transfer = XFER_UDMA_0;
++ }
++ }
++ /*
++ * The device doesn't support a udma mode, so check if it
++ * supports an mdma mode.
++ */
++ else if (transfer = (drive->id->dma_mword & 0x0007)) {
++ DPRINTK("IDE: mdma support, transfer = %d \n", transfer);
++
++ /*
++ * MDMA mode 2.
++ */
++ if (transfer & 0x04) {
++ transfer = XFER_MW_DMA_2;
++ }
++ /*
++ * MDMA mode 1.
++ */
++ else if (transfer & 0x02) {
++ transfer = XFER_MW_DMA_1;
++ }
++ /*
++ * MDMA mode 0.
++ */
++ else if (transfer & 0x01) {
++ transfer = XFER_MW_DMA_0;
++ }
++ }
++
++ if (transfer == 0) {
++ DPRINTK("IDE: config device failed \n");
++
++ /*
++ * Fail.
++ */
++ return 1;
++ }
++
++ if (ide_config_drive_speed(drive, transfer) == 0) {
++ printk("%s: %s selected\n", drive->name,
++ ide_xfer_verbose(transfer));
++
++ /*
++ * Hold on to this value for use later.
++ */
++ drive->current_speed = transfer;
++
++ /*
++ * Success, so turn on DMA.
++ */
++ return ep93xx_ide_dma_on(drive);
++ } else {
++ return ep93xx_ide_dma_off(drive);
++ }
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_set_pio()
++ *
++ * Configures the ep93xx controller for a PIO mode transfer.
++ *
++ ****************************************************************************/
++static void ep93xx_set_pio(void)
++{
++ /*
++ * Disable the interface.
++ */
++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 0;
++
++ /*
++ * Enable PIO mode of operation.
++ */
++ ep93xx_ide_regs->IDECFG.Field.PIO = 1;
++ ep93xx_ide_regs->IDECFG.Field.UDMA = 0;
++ ep93xx_ide_regs->IDECFG.Field.MDMA = 0;
++
++ /*
++ * Enable the IDE interface.
++ */
++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_rwproc()
++ *
++ * Initializes the ep93xx IDE controller interface with the transfer type,
++ * transfer mode, and transfer direction.
++ *
++ ****************************************************************************/
++static void ep93xx_rwproc(ide_drive_t * drive, int action)
++{
++ unsigned int temp;
++
++ DPRINTK("\nep93xx_rwproc \n");
++ /*
++ * Configure the IDE controller for the specified transfer mode.
++ */
++ switch (drive->current_speed) {
++ /*
++ * Configure for an MDMA operation.
++ */
++ case XFER_MW_DMA_0:
++ case XFER_MW_DMA_1:
++ case XFER_MW_DMA_2:
++ {
++ DPRINTK("\n ep93xx set up for MDMA \n");
++ ep93xx_ide_regs->IDECFG.Field.PIO = 0;
++ ep93xx_ide_regs->IDECFG.Field.UDMA = 0;
++ ep93xx_ide_regs->IDECFG.Field.MDMA = 1;
++ ep93xx_ide_regs->IDECFG.Field.MODE =
++ (0x3 & drive->current_speed);
++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
++ ep93xx_ide_regs->IDEMDMAOP.Field.RWOP = action;
++ ep93xx_ide_regs->IDEMDMAOP.Field.MEN = 1;
++ break;
++ }
++
++ /*
++ * Configure for a UDMA operation.
++ */
++ case XFER_UDMA_0:
++ case XFER_UDMA_1:
++ case XFER_UDMA_2:
++ case XFER_UDMA_3:
++ case XFER_UDMA_4:
++ {
++ DPRINTK("\n ep93xx set up for UDMA \n");
++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 0;
++ ep93xx_ide_regs->IDEUDMAOP.Field.UEN = 0;
++ ep93xx_ide_regs->IDECFG.Field.PIO = 0;
++ ep93xx_ide_regs->IDECFG.Field.MDMA = 0;
++ ep93xx_ide_regs->IDECFG.Field.UDMA = 0;
++ ep93xx_ide_regs->IDECFG.Field.WST = 0;
++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
++
++ ep93xx_ide_regs->IDECFG.Field.MODE =
++ (0x7 & drive->current_speed);
++ ep93xx_ide_regs->IDECFG.Field.UDMA = 1;
++ ep93xx_ide_regs->IDEUDMAOP.Field.RWOP = action;
++ temp = ep93xx_ide_regs->IDEUDMAOP.Value;
++ ep93xx_ide_regs->IDEUDMAOP.Field.UEN = 1;
++ temp = ep93xx_ide_regs->IDEUDMAOP.Value;
++
++ DPRINTK("\nIDE Regs: config - 0x%x, udmaop - 0x%x \n",
++ ep93xx_ide_regs->IDECFG.Value,
++ ep93xx_ide_regs->IDEUDMAOP.Value);
++
++ break;;
++ }
++
++ default:
++ {
++ break;
++ }
++ }
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_check()
++ *
++ * This function determines if the device supports dma transfers, and if it
++ * does, then enables dma.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_check(ide_drive_t * drive)
++{
++ ide_hwif_t *hwif = HWIF(drive);
++ struct hd_driveid *id = drive->id;
++
++ DPRINTK("%s: ep93xx_ide_dma_check \n", drive->name);
++
++ if (!id || !(id->capability & 1) || !hwif->autodma) {
++ /*
++ * Disable dma for this drive.
++ */
++ ep93xx_ide_dma_off(drive);
++ }
++
++ /*
++ * Consult the list of known "bad" drives
++ */
++ if (in_drive_list(id, drive_blacklist)) {
++ printk("%s: Disabling DMA for %s (blacklisted)\n",
++ drive->name, id->model);
++
++ /*
++ * Disable dma for this drive.
++ */
++ ep93xx_ide_dma_off(drive);
++ }
++
++ /*
++ * Check if the drive supports multiword dma or udma modes.
++ * If it does, then set the device up for that
++ * type of dma transfer, and call ep93xx_ide_dma_on.
++ */
++ return ep93xx_config_ide_device(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_host_off()
++ *
++ * This function disables dma for the host.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_host_off(ide_drive_t * drive)
++{
++ ide_hwif_t *hwif = HWIF(drive);
++
++ /*
++ * TODO: what's to be done here?
++ */
++ DPRINTK("%s: ep93xx_ide_dma_host_off() \n", drive->name);
++
++ /*
++ * Release the dma channel and all memory allocated for dma
++ * purposes.
++ */
++ ep93xx_ide_release_dma(hwif);
++
++ return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_off_quietly()
++ *
++ * This function, without announcing it, disables dma for the device.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_off_quietly(ide_drive_t * drive)
++{
++ DPRINTK("%s: ep93xx_ide_dma_off_quietly: \n", drive->name);
++
++ /*
++ * Clear the using_dma field to indicate that dma is disabled
++ * for this drive.
++ */
++ drive->using_dma = 0;
++
++ /*
++ * Disable dma on the host side.
++ */
++ ep93xx_ide_dma_host_off(drive);
++
++ return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_off()
++ *
++ * This function disables dma for the device.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_off(ide_drive_t * drive)
++{
++ printk("%s: DMA disabled\n", drive->name);
++
++ return ep93xx_ide_dma_off_quietly(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_on()
++ *
++ * This function enables dma for the device.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_on(ide_drive_t * drive)
++{
++ DPRINTK("%s: ep93xx_ide_dma_on: \n", drive->name);
++
++ if (drive->using_dma) {
++ DPRINTK("%s: ep93xx_ide_dma_on, already on! \n", drive->name);
++ return 0;
++ }
++
++ /*
++ * Set the using_dma field to indicate that dma is enabled.
++ */
++ drive->using_dma = 1;
++
++ /*
++ * Enable DMA on the host side.
++ */
++ return ep93xx_ide_dma_host_on(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_host_on()
++ *
++ * This function enables dma for the device.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_host_on(ide_drive_t * drive)
++{
++ DPRINTK("%s: ep93xx_ide_dma_host_on: \n", drive->name);
++
++ /*
++ * Enable the ep93xx dma interface for use with IDE.
++ */
++ return ep93xx_config_ide_dma(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_read()
++ *
++ * This function sets up a dma read operation.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_read(ide_drive_t * drive)
++{
++ unsigned int flags, result;
++ ide_hwif_t *hwif = HWIF(drive);
++
++ DPRINTK("%s: ep93xx_ide_dma_read: \n", drive->name);
++
++ /*
++ * Check if we are already transferring on this dma channel.
++ */
++ BUG_ON(hwif->sg_dma_active);
++
++ /*
++ * Configure DMA M2M channel flags for a source address hold, h/w
++ * initiated P2M transfer.
++ */
++ flags = (SOURCE_HOLD | TRANSFER_MODE_HW_P2M);
++
++ if (drive->current_speed & 0x20) {
++ flags |= (WS_IDE_MDMA_READ_WRITE << WAIT_STATES_SHIFT);
++
++ /*
++ * MDMA data register address.
++ */
++ hwif->dma_base = 0x800A001C;
++ } else {
++ flags |= (WS_IDE_UDMA_READ << WAIT_STATES_SHIFT);
++
++ /*
++ * UDMA data register address.
++ */
++ hwif->dma_base = 0x800a0024;
++ }
++
++ /*
++ * Configure the dma interface for this IDE operation.
++ */
++ if (ep93xx_dma_config(hwif->hw.dma, 0, flags, ep93xx_ide_callback,
++ (unsigned int)drive) != 0) {
++ DPRINTK("%s: ep93xx_ide_dma_read: ERROR- dma config failed",
++ drive->name);
++
++ /*
++ * Fail.
++ */
++ return 1;
++ }
++
++ /*
++ * Build the table of dma-able buffers.
++ */
++ if (!(g_prd_count = ide_build_dmatable(drive))) {
++ DPRINTK
++ ("%s: ep93xx_ide_dma_read: ERROR- failed to build dma table",
++ drive->name);
++
++ /*
++ * Fail, try PIO instead of DMA
++ */
++ return 1;
++ }
++
++ /*
++ * Indicate that we're waiting for dma.
++ */
++ drive->waiting_for_dma = 1;
++
++ hwif->sg_dma_active = 1;
++
++ /*
++ * test stuff
++ */
++ g_prd_total = g_prd_count;
++ g_prd_returned = 0;
++ g_dma_table_base = hwif->dmatable_cpu;
++
++ /*
++ * Prepare the dma interface with some buffers from the
++ * dma_table.
++ */
++ do {
++ /*
++ * Add a buffer to the dma interface.
++ */
++ result = ep93xx_dma_add_buffer(hwif->hw.dma, hwif->dma_base,
++ *hwif->dmatable_cpu++,
++ *hwif->dmatable_cpu++, 0,
++ g_prd_count);
++
++ if (result != 0) {
++ /*
++ * This buffer didn't make it into the dma
++ * interface, so move the dma table pointer
++ * to the start of the current entry.
++ */
++ hwif->dmatable_cpu -= 4;
++ break;
++ }
++
++ /*
++ * Decrement the count of dmatable entries
++ */
++ g_prd_count--;
++
++ } while (g_prd_count);
++
++ /*
++ * Check if this is a disk or cd drive.
++ */
++ if (drive->media == ide_disk) {
++ /*
++ * Send the read command to the device.
++ */
++ ide_execute_command(drive, WIN_READDMA, &ep93xx_ide_dma_intr,
++ 4 * WAIT_CMD, &ep93xx_idedma_timer_expiry);
++
++ }
++
++ /*
++ * Configure the ep93xx ide controller for a dma read operation.
++ */
++ ep93xx_rwproc(drive, 0);
++
++ /*
++ * initiate the dma transfer.
++ */
++ return ep93xx_ide_dma_begin(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_write()
++ *
++ * This function sets up a dma write operation.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_write(ide_drive_t * drive)
++{
++ unsigned int flags, result;
++ ide_hwif_t *hwif = HWIF(drive);
++
++ DPRINTK("%s: ep93xx_ide_dma_write: \n", drive->name);
++
++ /*
++ * Check if we are already transferring on this dma channel.
++ */
++ BUG_ON(hwif->sg_dma_active);
++
++ /*
++ * Configure DMA M2M channel flags for a destination address
++ * hold, h/w initiated M2P transfer.
++ */
++ flags = (DESTINATION_HOLD | TRANSFER_MODE_HW_M2P);
++
++ /*
++ * Determine if we need the MDMA or UDMA data register.
++ */
++ if (drive->current_speed & 0x20) {
++ flags |= (WS_IDE_MDMA_READ_WRITE << WAIT_STATES_SHIFT);
++
++ /*
++ * MDMA data register address.
++ */
++ hwif->dma_base = 0x800A0018;
++ } else {
++ flags |= (WS_IDE_UDMA_WRITE << WAIT_STATES_SHIFT);
++
++ /*
++ * UDMA data register address.
++ */
++ hwif->dma_base = 0x800a0020;
++ }
++
++ /*
++ * Configure the dma interface for this IDE operation.
++ */
++ if (ep93xx_dma_config(hwif->hw.dma, 0, flags, ep93xx_ide_callback,
++ (unsigned int)drive) != 0) {
++ return 1;
++ }
++
++ /*
++ * Build the table of dma-able buffers.
++ */
++ if (!(g_prd_count = ide_build_dmatable(drive))) {
++ /*
++ * Fail, try PIO instead of DMA
++ */
++ return 1;
++ }
++
++ /*
++ * Indicate that we're waiting for dma.
++ */
++ drive->waiting_for_dma = 1;
++
++ hwif->sg_dma_active = 1;
++
++ /*
++ * test stuff
++ */
++ g_prd_total = g_prd_count;
++ g_prd_returned = 0;
++ g_dma_table_base = hwif->dmatable_cpu;
++
++ /*
++ * Prepare the dma interface with some buffers from the
++ * dma_table.
++ */
++ do {
++ /*
++ * Add a buffer to the dma interface.
++ */
++ result =
++ ep93xx_dma_add_buffer(hwif->hw.dma, *hwif->dmatable_cpu++,
++ hwif->dma_base, *hwif->dmatable_cpu++,
++ 0, g_prd_count);
++
++ if (result != 0) {
++ /*
++ * This buffer didn't make it into the dma
++ * interface, so move the dma table pointer
++ * to the start of the current entry.
++ */
++ hwif->dmatable_cpu -= 4;
++ break;
++ }
++
++ /*
++ * Decrement the count of dmatable entries
++ */
++ g_prd_count--;
++
++ } while (g_prd_count);
++
++ /*
++ * Check if this is a disk or cd drive.
++ */
++ if (drive->media == ide_disk) {
++ /*
++ * Send the write dma command to the device.
++ */
++ ide_execute_command(drive, WIN_WRITEDMA, &ep93xx_ide_dma_intr,
++ 4 * WAIT_CMD, &ep93xx_idedma_timer_expiry);
++ }
++
++ /*
++ * Configure the ep93xx ide controller for a dma read operation.
++ */
++ ep93xx_rwproc(drive, 1);
++
++ /*
++ * initiate the dma transfer.
++ */
++ return ep93xx_ide_dma_begin(drive);
++
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_begin()
++ *
++ * This function initiates a dma transfer.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_begin(ide_drive_t * drive)
++{
++ ide_hwif_t *hwif = HWIF(drive);
++
++ DPRINTK("%s: ep93xx_ide_dma_begin: \n", drive->name);
++
++ /* Note that this is done *after* the cmd has
++ * been issued to the drive, as per the BM-IDE spec.
++ * The Promise Ultra33 doesn't work correctly when
++ * we do this part before issuing the drive cmd.
++ */
++ g_done = 0;
++
++ /*
++ * Start the dma transfer.
++ */
++ ep93xx_dma_start(hwif->hw.dma, 1, NULL);
++
++ /*
++ * TODO: not sure if we need to keep track of the end
++ * of the transfer from the dma perspective, but
++ * for now, let's do it.
++ */
++ return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_end()
++ *
++ * This function performs any tasks needed to cleanup after a dma transfer.
++ * Returns 1 if an error occured, and 0 otherwise.
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_end(ide_drive_t * drive)
++{
++ unsigned char dev_stat;
++ ide_hwif_t *hwif = HWIF(drive);
++
++ DPRINTK("%s: ep93xx_ide_dma_end: \n", drive->name);
++
++ /*
++ * Indicate there's no dma transfer currently in progress.
++ */
++ drive->waiting_for_dma = 0;
++
++ /*
++ * Put the dma interface into pause mode.
++ */
++ ep93xx_dma_pause(hwif->hw.dma, 1, 0);
++ ep93xx_dma_flush(hwif->hw.dma);
++
++ /*
++ * Enable PIO mode on the IDE interface.
++ */
++ ep93xx_set_pio();
++
++ /*
++ * Read the ide device status register. This clears the interrupt.
++ * TODO: should I read the alt status instead to prevent clearing
++ * an asserted interrupt??
++ */
++ dev_stat = hwif->INB(IDE_STATUS_REG);
++
++ /*
++ * Purge the contents of the dma table of buffer entries.
++ */
++ ide_destroy_dmatable(drive);
++
++ hwif->sg_dma_active = 0;
++
++ /*
++ * If the error bit is set in the device status register,
++ * return a positive value.
++ */
++ if (dev_stat & ERR_STAT) {
++ printk("ide_dma_end: device error \n");
++ return 1;
++ } else {
++ return 0;
++ }
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_test_irq()
++ *
++ * This function checks if the IDE interrupt is asserted and returns a
++ * 1 if it is, and 0 otherwise..
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_test_irq(ide_drive_t * drive)
++{
++ DPRINTK("%s: ep93xx_ide_dma_test_irq: \n", drive->name);
++
++ if (!drive->waiting_for_dma)
++ printk(KERN_WARNING "%s: (%s) called while not waiting\n",
++ drive->name, __FUNCTION__);
++
++ /*
++ * TODO: need to use the io macros to get this value.
++ * Return the value of the IDE interrupt bit.
++ */
++ return (ep93xx_ide_regs->IDECR.Value & IDECtrl_INTRQ);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_bad_drive()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_bad_drive(ide_drive_t * drive)
++{
++ DPRINTK("%s: ep93xx_ide_dma_bad_drive: \n", drive->name);
++
++ return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_good_drive()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_good_drive(ide_drive_t * drive)
++{
++ DPRINTK("%s: ep93xx_ide_dma_good_drive: \n", drive->name);
++
++ /*
++ * TODO: need to implement.
++ */
++ return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_count()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_count(ide_drive_t * drive)
++{
++ DPRINTK("%s: ep93xx_ide_dma_count: \n", drive->name);
++
++ return 0;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_verbose()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_verbose(ide_drive_t * drive)
++{
++ DPRINTK("%s: ep93xx_ide_dma_verbose: \n", drive->name);
++
++ printk(", %s ", ide_xfer_verbose(drive->current_speed));
++
++ return 1;
++
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_bad_timeout()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_timeout(ide_drive_t * drive)
++{
++ DPRINTK("%s: ep93xx_ide_dma_timeout: \n", drive->name);
++
++ printk(KERN_ERR "%s: timeout waiting for DMA\n", drive->name);
++ if (HWIF(drive)->ide_dma_test_irq(drive))
++ return 0;
++ return HWIF(drive)->ide_dma_end(drive);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_retune()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_retune(ide_drive_t * drive)
++{
++ DPRINTK("%s: ep93xx_ide_dma_retune\n", drive->name);
++ return 1;
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_dma_lostirq()
++ *
++ ****************************************************************************/
++int ep93xx_ide_dma_lostirq(ide_drive_t * drive)
++{
++ DPRINTK("%s: ep93xx_ide_dma_lostirq\n", drive->name);
++ printk("%s: DMA interrupt recovery\n", drive->name);
++
++ return 1;
++}
++
++#endif /* CONFIG_BLK_DEV_IDEDMA_EP93XX */
++
++/*****************************************************************************
++ *
++ * functions to set up the IDE control register and data register to read
++ * or write a byte of data to/from the specified IDE device register.
++ *
++ ****************************************************************************/
++static void ep93xx_ide_outb(u8 b, unsigned long addr)
++{
++ unsigned int uiIDECR;
++
++ DPRINTK("ep93xx_ide_outb, addr:%02lx data: %04x\n", addr, b);
++
++ /*
++ * Write the address out (CS0n, CS1n, DA) fields only.
++ */
++ uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
++ writel(uiIDECR, IDECtrl);
++
++ writel((unsigned int)b, IDEDataOut);
++
++ /*
++ * Toggle Write signal.
++ */
++ uiIDECR &= ~IDECtrl_DIOWn;
++ writel(uiIDECR, IDECtrl);
++ uiIDECR |= IDECtrl_DIOWn;
++ writel(uiIDECR, IDECtrl);
++}
++
++static void ep93xx_ide_outbsync(ide_drive_t * drive, u8 b, unsigned long addr)
++{
++ unsigned int uiIDECR;
++
++ DPRINTK("ep93xx_ide_outbsync, addr:%02lx data: %04x\n", addr, b);
++
++ /*
++ * Write the address out (CS0n, CS1n, DA) fields only.
++ */
++ uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
++ writel(uiIDECR, IDECtrl);
++
++ writel((unsigned int)b, IDEDataOut);
++
++ /*
++ * Toggle Write signal.
++ */
++ uiIDECR &= ~IDECtrl_DIOWn;
++ writel(uiIDECR, IDECtrl);
++ uiIDECR |= IDECtrl_DIOWn;
++ writel(uiIDECR, IDECtrl);
++}
++
++static unsigned char ep93xx_ide_inb(unsigned long addr)
++{
++ unsigned int uiIDECR;
++
++ DPRINTK("ep93xx_ide_inb addr: %04lx ", addr);
++
++ /*
++ * Write the address out (CS0n, CS1n, DA) fields only.
++ */
++ uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
++ writel(uiIDECR, IDECtrl);
++
++ /*
++ * Toggle Read signal.
++ */
++ uiIDECR &= ~IDECtrl_DIORn;
++ writel(uiIDECR, IDECtrl);
++ uiIDECR |= IDECtrl_DIORn;
++ writel(uiIDECR, IDECtrl);
++
++ DPRINTK("data: %02x\n", readl(IDEDataIn));
++ return (unsigned char)readl(IDEDataIn);
++}
++
++/*****************************************************************************
++ *
++ * functions to set up the IDE control register and data restister to read
++ * or write 16 bits of data to/from the specified IDE device register.
++ * These functions should only be used when reading/writing data to/from
++ * the data register.
++ *
++ ****************************************************************************/
++static void ep93xx_ide_outw(u16 w, unsigned long addr)
++{
++ unsigned int uiIDECR;
++
++ DPRINTK("ep93xx_ide_outw addr: %04lx data: %04x\n", addr, w);
++
++ /*
++ * Write the address out (CS0n, CS1n, DA) fields only.
++ */
++ uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
++ writel(uiIDECR, IDECtrl);
++
++ writel((unsigned int)w, IDEDataOut);
++
++ /*
++ * Toggle Write signal.
++ */
++ uiIDECR &= ~IDECtrl_DIOWn;
++ writel(uiIDECR, IDECtrl);
++ uiIDECR |= IDECtrl_DIOWn;
++ writel(uiIDECR, IDECtrl);
++}
++
++static u16 ep93xx_ide_inw(unsigned long addr)
++{
++ unsigned int uiIDECR;
++
++ DPRINTK("ep93xx_ide_inw addr: %04lx ", addr);
++
++ /*
++ * Write the address out (CS0n, CS1n, DA) fields only.
++ */
++ uiIDECR = (readl(IDECtrl) & ~IDECR_REG_MASK) | (addr & IDECR_REG_MASK);
++ writel(uiIDECR, IDECtrl);
++
++ /*
++ * Toggle Read signal.
++ */
++ uiIDECR &= ~IDECtrl_DIORn;
++ writel(uiIDECR, IDECtrl);
++ uiIDECR |= IDECtrl_DIORn;
++ writel(uiIDECR, IDECtrl);
++
++ DPRINTK("data: %04x\n", readl(IDEDataIn));
++ return (unsigned short)readl(IDEDataIn);
++}
++
++/*****************************************************************************
++ *
++ * functions to read/write a block of data to/from the ide device using
++ * PIO mode.
++ *
++ ****************************************************************************/
++static void ep93xx_ide_insw(unsigned long addr, void *buf, u32 count)
++{
++ unsigned short *data = (unsigned short *)buf;
++ unsigned char status;
++ DPRINTK("ep93xx_ide_insw\n");
++
++ /*
++ * Read in data from the data register 16 bits at a time.
++ */
++ while (count) {
++ /*
++ * Read the status register.
++ */
++ status = ep93xx_ide_inb((STATUSREGISTER << 2) + 2);
++
++ /*
++ * Check for the BSY to be clear and DRQ to be set.
++ */
++ if ((status & ATADRQ) && !(status & ATABSY)) {
++ *data = ep93xx_ide_inw(addr);
++ data++;
++ count--;
++ }
++ }
++}
++
++static void ep93xx_ide_outsw(unsigned long addr, void *buf, u32 count)
++{
++ unsigned short *data = (unsigned short *)buf;
++ unsigned char status;
++
++ DPRINTK("ep93xx_ide_outsw\n");
++
++ /*
++ * Write out data to the data register 16 bits at a time.
++ */
++ while (count) {
++ /*
++ * Read the status register.
++ */
++ status = ep93xx_ide_inb((STATUSREGISTER << 2) + 2);
++
++ /*
++ * Check for the BSY to be clear and DRQ to be set.
++ */
++ if ((status & ATADRQ) && !(status & ATABSY)) {
++ ep93xx_ide_outw(*data, addr);
++ data++;
++ count--;
++ }
++ }
++}
++
++static void ep93xx_ide_outl(u32 l, unsigned long addr)
++{
++ printk("ep93xx_ide_outl\n");
++}
++
++static u32 ep93xx_ide_inl(unsigned long addr)
++{
++ printk("ep93xx_ide_inl\n");
++ return 0;
++}
++
++static void ep93xx_ide_outsl(unsigned long addr, void *buf, u32 count)
++{
++ printk("ep93xx_ide_inl\n");
++}
++
++static void ep93xx_ide_insl(unsigned long addr, void *buf, u32 count)
++{
++ printk("ep93xx_ide_inl\n");
++}
++
++/*****************************************************************************
++ *
++ * Functions to read/write a block of data to/from the ide device using
++ * PIO mode, using an ATAPI interface.
++ *
++ ****************************************************************************/
++static void ep93xx_ide_insw_atapi(unsigned int addr, void *buf, int count)
++{
++ DPRINTK("ep93xx_ide_insw_atapi \n");
++
++ /*
++ * Convert count from bytes to half words.
++ */
++ if (count % 2) {
++ count = count / 2;
++ count++;
++ } else {
++ count = count / 2;
++ }
++
++ /*
++ * Call the function which will read in the data.
++ */
++ ep93xx_ide_insw(addr, buf, count);
++}
++
++static void ep93xx_ide_outsw_atapi(unsigned int addr, void *buf, int count)
++{
++ DPRINTK("ep93xx_ide_outsw_atapi \n");
++
++ /*
++ * Convert count from bytes to half words.
++ */
++ if (count % 2) {
++ count = count / 2;
++ count++;
++ } else {
++ count = count / 2;
++ }
++
++ /*
++ * Call the function which will write out the data.
++ */
++ ep93xx_ide_outsw(addr, buf, count);
++}
++
++void ep93xx_ata_input_data(ide_drive_t * drive, void *buffer, u32 count)
++{
++ DPRINTK("ep93xx_ata_input_data \n");
++
++ /*
++ * Read in the specified number of half words from the ide interface.
++ */
++ ep93xx_ide_insw(IDE_DATA_REG, buffer, count << 1);
++}
++
++void ep93xx_ata_output_data(ide_drive_t * drive, void *buffer, u32 count)
++{
++ DPRINTK("ep93xx_ata_output_data \n");
++
++ /*
++ * write the specified number of half words from the ide interface
++ * to the ide device.
++ */
++ ep93xx_ide_outsw(IDE_DATA_REG, buffer, count << 1);
++}
++
++void ep93xx_atapi_input_bytes(ide_drive_t * drive, void *buffer, u32 count)
++{
++ DPRINTK("ep93xx_atapi_input_bytes \n");
++
++ /*
++ * read in the specified number of bytes from the ide interface.
++ */
++ ep93xx_ide_insw_atapi(IDE_DATA_REG, buffer, count);
++}
++
++void ep93xx_atapi_output_bytes(ide_drive_t * drive, void *buffer, u32 count)
++{
++ DPRINTK("ep93xx_atapi_output_bytes \n");
++
++ /*
++ * Write the specified number of bytes from the ide interface
++ * to the ide device.
++ */
++ ep93xx_ide_outsw_atapi(IDE_DATA_REG, buffer, count);
++}
++
++/*****************************************************************************
++ *
++ * ep93xx_ide_init()
++ *
++ * This function sets up a pointer to the ep93xx specific ideproc funciton.
++ *
++ ****************************************************************************/
++void ep93xx_ide_init(struct hwif_s *hwif)
++{
++
++ DPRINTK("ep93xx_ide_init \n");
++
++ /*
++ * Set up the HW interface function pointers with the ep93xx specific
++ * function.
++ */
++ hwif->ata_input_data = ep93xx_ata_input_data;
++ hwif->ata_output_data = ep93xx_ata_output_data;
++ hwif->atapi_input_bytes = ep93xx_atapi_input_bytes;
++ hwif->atapi_output_bytes = ep93xx_atapi_output_bytes;
++
++ hwif->OUTB = ep93xx_ide_outb;
++ hwif->OUTBSYNC = ep93xx_ide_outbsync;
++ hwif->OUTW = ep93xx_ide_outw;
++ hwif->OUTL = ep93xx_ide_outl;
++ hwif->OUTSW = ep93xx_ide_outsw;
++ hwif->OUTSL = ep93xx_ide_outsl;
++
++ hwif->INB = ep93xx_ide_inb;
++ hwif->INW = ep93xx_ide_inw;
++ hwif->INL = ep93xx_ide_inl;
++ hwif->INSW = ep93xx_ide_insw;
++ hwif->INSL = ep93xx_ide_insl;
++
++#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX
++
++ DPRINTK("ep93xx_ide_init- dma enabled \n");
++
++ printk(" %s: SG-DMA", hwif->name);
++
++ /*
++ * Allocate dma-able memory space, in one consistent chunk. The call
++ * to alloc_consistent will return a virtual address and fill in a dma
++ * physical address. (arch/arm/mm/consistent.c)
++ *
++ */
++ hwif->dmatable_cpu = consistent_alloc(GFP_KERNEL | GFP_DMA,
++ PRD_ENTRIES * PRD_BYTES,
++ &hwif->dmatable_dma);
++
++ /*
++ * Check if we allocated memory for dma
++ */
++ if (hwif->dmatable_cpu == NULL) {
++ printk(" -- disabled, UNABLE TO ALLOCATE DMA TABLES\n");
++ return;
++ }
++
++ DPRINTK(" %s: EP93XX-DMA at 0x%x - 0x%x \n", hwif->name,
++ hwif->dmatable_dma,
++ (unsigned int)(hwif->dmatable_dma + (PRD_ENTRIES * PRD_BYTES)));
++
++ /*
++ * Allocate memory for the scatterlist structures.
++ */
++ hwif->sg_table = kmalloc(sizeof(struct scatterlist) * PRD_ENTRIES,
++ GFP_KERNEL);
++
++ /*
++ * Check if we allocated the memory we expected to.
++ */
++ if (hwif->sg_table == NULL) {
++ /*
++ * Fail, so clean up.
++ */
++ consistent_free(hwif->dmatable_cpu, PRD_ENTRIES * PRD_BYTES,
++ hwif->dmatable_dma);
++ printk(" -- disabled, UNABLE TO ALLOCATE DMA TABLES\n");
++ return;
++ }
++
++ /*
++ * Init the dma handle to 0. This field is used to hold a handle to the
++ * dma instance.
++ */
++ hwif->hw.dma = NULL;
++
++ /*
++ * Open an instance of the ep93xx dma interface.
++ */
++ if (ep93xx_dma_request(&hwif->hw.dma, hwif->name, DMA_IDE) != 0) {
++ /*
++ * Fail, so clean up.
++ */
++ consistent_free(hwif->dmatable_cpu, PRD_ENTRIES * PRD_BYTES,
++ hwif->dmatable_dma);
++ kfree(hwif->sg_table);
++ printk(" -- disabled, unable to allocate DMA channel.\n");
++ }
++
++ /*
++ * Now that we've got a dma channel allocated, set up the rest of the
++ * dma specific stuff.
++ */
++ else {
++ DPRINTK("\n ide init- dma channel allocated: %d \n",
++ hwif->hw.dma);
++
++ /*
++ * Enable dma support for atapi devices.
++ */
++ hwif->atapi_dma = 1;
++
++ /*
++ * TODO: how are these used?
++ */
++ hwif->mwdma_mask = 7; /* MW0..2 */
++ hwif->ultra_mask = 7; /* SW0..2 */
++
++ hwif->speedproc = NULL;
++ hwif->autodma = 1;
++
++ hwif->ide_dma_check = ep93xx_ide_dma_check;
++ hwif->ide_dma_host_off = ep93xx_ide_dma_host_off;
++ hwif->ide_dma_off_quietly = ep93xx_ide_dma_off_quietly;
++ hwif->ide_dma_off = ep93xx_ide_dma_off;
++ hwif->ide_dma_host_on = ep93xx_ide_dma_host_on;
++ hwif->ide_dma_on = ep93xx_ide_dma_on;
++ hwif->ide_dma_read = ep93xx_ide_dma_read;
++ hwif->ide_dma_write = ep93xx_ide_dma_write;
++ hwif->ide_dma_count = ep93xx_ide_dma_count;
++ hwif->ide_dma_begin = ep93xx_ide_dma_begin;
++ hwif->ide_dma_end = ep93xx_ide_dma_end;
++ hwif->ide_dma_test_irq = ep93xx_ide_dma_test_irq;
++ hwif->ide_dma_verbose = ep93xx_ide_dma_verbose;
++ hwif->ide_dma_timeout = ep93xx_ide_dma_timeout;
++ hwif->ide_dma_lostirq = ep93xx_ide_dma_lostirq;
++
++ printk(" capable%s\n", hwif->autodma ? ", auto-enable" : "");
++ }
++
++#endif
++}
+diff --git a/drivers/ide/arm/ide_arm.c b/drivers/ide/arm/ide_arm.c
+index 23488c4..cc411c2 100644
+--- a/drivers/ide/arm/ide_arm.c
++++ b/drivers/ide/arm/ide_arm.c
+@@ -20,6 +20,15 @@
+ # define IDE_ARM_HOST (1)
+ #endif
+
++/* FIXME: Part 1 of dirty hack to get IDE working for EP93XX Processor */
++#ifdef CONFIG_BLK_DEV_EP93XX
++#include <asm/arch/ide.h>
++#ifndef IRQ_HARDDISK
++# define IRQ_HARDDISK -1
++#endif
++#endif
++/* END OF HACK */
++
+ #ifdef CONFIG_ARCH_CLPS7500
+ # include <asm/arch/hardware.h>
+ #
+@@ -36,8 +45,15 @@ void __init ide_arm_init(void)
+ hw_regs_t hw;
+
+ memset(&hw, 0, sizeof(hw));
++
++/* FIXME: Part 2 of dirty hack to get IDE working for EP93XX Processor */
++#ifdef CONFIG_BLK_DEV_EP93XX
++ old_ide_init_default_hwifs();
++#else
+ ide_std_init_ports(&hw, IDE_ARM_IO, IDE_ARM_IO + 0x206);
+ hw.irq = IDE_ARM_IRQ;
+ ide_register_hw(&hw, NULL);
++#endif
+ }
++
+ }
+diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
+index 4a91774..68c06fa 100644
+--- a/drivers/input/keyboard/Kconfig
++++ b/drivers/input/keyboard/Kconfig
+@@ -193,4 +193,38 @@ config KEYBOARD_HIL
+ This driver implements support for HIL-keyboards attached
+ to your machine, so normally you should say Y here.
+
++config KEYBOARD_EP93XX
++ tristate "EP93xx Keyboard support"
++ depends on ARCH_EP93XX && INPUT && INPUT_KEYBOARD
++ default y
++ help
++ This is support for the Cirrus EP93xx Keyboards. Say yes here if you
++ have such a CPU, and choose some drivers below.
++
++config KEYBOARD_EP93XX_SPI
++ bool "EP93xx PS2 Keyboard support"
++ depends on KEYBOARD_EP93XX
++ help
++ Say Y here if you want support for a PS2 keyboard connected via SPI.
++
++config KEYBOARD_EP93XX_8X8
++ bool "EP93xx 8x8 keypad matrix support"
++ depends on KEYBOARD_EP93XX
++ help
++ Say Y here if you have a 8x8 keypad connected to your EP93xx.
++ You might want to generate a custom keymap for it.
++ If you do not have such a keypad, say N.
++
++config KEYBOARD_EP93XX_8X8_CYCLING
++ bool "EP93xx 8x8 keypad matrix keycode cycling support"
++ depends on KEYBOARD_EP93XX_8X8
++ help
++ Key cycling feature - assign more than one keycode per key.
++ If you press such a key more than twice per second, alternative
++ keycodes will be cycled through.
++ This should result in a behavoir similar to some mobile phones.
++ You might want to generate a custom keymap for this feature, too.
++ See the sourcecode for known limitations.
++ Say N unless you really need it.
++
+ endif
+diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile
+index 9ce0b87..7ac6fca 100644
+--- a/drivers/input/keyboard/Makefile
++++ b/drivers/input/keyboard/Makefile
+@@ -17,4 +17,6 @@ obj-$(CONFIG_KEYBOARD_CORGI) += corgikb
+ obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
+ obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
+ obj-$(CONFIG_KEYBOARD_HIL_OLD) += hilkbd.o
++obj-$(CONFIG_KEYBOARD_EP93XX_8X8) += ep93xx_kbd_8x8.o
++obj-$(CONFIG_KEYBOARD_EP93XX_SPI) += ep93xx_spi_kbd.o
+
+diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8.c b/drivers/input/keyboard/ep93xx_kbd_8x8.c
+new file mode 100644
+index 0000000..d772381
+--- /dev/null
++++ b/drivers/input/keyboard/ep93xx_kbd_8x8.c
+@@ -0,0 +1,482 @@
++/******************************************************************************
++ *
++ * File: linux/drivers/input/keyboard/ep93xx_kbd_8x8.c
++ *
++ * Purpose: Support for Cirrus EP93xx architecture core keyboard scanner.
++ *
++ *
++ * History: 2005-08-10 Michael Burian added "cycling keys" support
++ * 2004-05-28 Michael Burian ported to 2.6.6
++ *
++ * 010406 Norman Farquhar at LynuxWorks
++ *
++ * Initial version
++ * - Will scan keyboard and feed keyboard.c, which translates
++ * to input codes and puts them into tty console queue.
++ * - Raw mode tbd
++ * - keymaps other than default not supported
++ * - does not support standby mode yet
++ *
++ * Limitations:
++ * 1. The EP93xx is limited to supporting small keyboards
++ * and cannot handle full PC style keyboards and key usage:
++ * a) 64 key limit: 8x8 key matrix
++ * b) limited to 2 keys down MAXIMUM,
++ * which makes it impossible to support SHIFT+SHIFT+KEY
++ * states like shift-control or control-alt keys.
++ * 2. This means the default keyboard, 83key CherryG84-4001QAU/02,
++ * will have some dead keys.
++ *
++ *
++ * (c) Copyright 2001 LynuxWorks, Inc., San Jose, CA. All rights reserved.
++ *
++ *=============================================================================
++ * Overview of EP93xx Scan Keyboard driver
++ *=============================================================================
++ *
++ * The EP93xx scanned keyboard driver is a low-level hardware driver which
++ * supports the core logic scanned keyboard controller block of the
++ * EP93xx. These machines are embedded systems and this keyboard driver
++ * can support small keyboards.
++ *
++ * The keyboard driver does not have a normal device driver interface
++ * and instead interfaces to the keyboard.c driver through function calls.
++ * Note that not all interface function calls are implemented at this time.
++ * (see /asm/arch/keyboard.h for function definitions):
++ *
++ * ep93xxkbd_init
++ * initializes the scan keyboard hw.
++ *
++ * handle_scancode
++ * when scan controller generates interrupt, handler
++ * used to pass scan codes to queue in keyboard.c with this function call.
++ *
++ * UPDATE: Now this is inplemented right here and just used as a
++ * wrapper for the input layer
++ *
++ * Note that key scan codes will be delivered by this driver on both
++ * key down and key up events, using a coding similar to PC XT keyboard.
++ *
++ * Note however that scan compatibility and key code compatibility
++ * to PC standard are not required by Linux, and are not guaranteed.
++ *
++ ******************************************************************************/
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/sched.h>
++#include <linux/interrupt.h>
++#include <linux/input.h>
++#include <linux/init.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/arch/keyboard.h>
++#include <asm/hardware.h>
++
++#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING
++#include "ep93xx_kbd_8x8_keymap-cycling.h"
++#else
++#include "ep93xx_kbd_8x8_keymap.h"
++#endif
++
++#define EP93XX_KEYMAP_SIZE (8*8)
++
++/* #define DEBUG */
++
++#define KEYREG_KEY1_MASK 0x0000003F
++#define KEYREG_KEY1_SHIFT 0
++#define KEYREG_KEY2_MASK 0x00000Fc0
++#define KEYREG_KEY2_SHIFT 6
++
++#define KEYREG_KEY1ROW_MASK 0x00000007
++#define KEYREG_KEY1ROW_SHIFT 0
++#define KEYREG_KEY1COL_MASK 0x00000038
++#define KEYREG_KEY1COL_SHIFT 3
++
++#define KEYREG_KEY2ROW_MASK 0x000001c0
++#define KEYREG_KEY2ROW_SHIFT 6
++#define KEYREG_KEY2COL_MASK 0x00000E00
++#define KEYREG_KEY2COL_SHIFT 9
++
++#define KEYREG_1KEY 0x00001000
++#define KEYREG_2KEYS 0x00002000
++#define KEYREG_INT 0x00004000
++#define KEYREG_K 0x00008000
++
++#define SCANINIT_DIS3KY 0x00008000
++
++static struct input_dev *dev;
++
++#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING
++struct last_key_event {
++ unsigned long jiffies;
++ unsigned char scancode;
++};
++
++static struct last_key_event lke;
++
++/**
++ * handle_scancode - wrapper
++ *
++ * We need to do two things here:
++ * 1. wrap old style (2.4.x) to 2.6.x input subsystem
++ * 2. also implement the key cycling feature here.
++ * CYCLING FEATURE:
++ * If the same key is pressed withing 500ms, we send a delete
++ * character to delete the former key, and use the keycode from the next layer
++ * instead. This should result "mobile phone" like behavior.
++ * KNOWN BUG:
++ * This will mess up anything that depends on single keystrokes
++ * (raw mode, non canonical mode, hotkeys, ...)
++ * TODO 1:
++ * A possible fix would be to delay till we know for sure what key it is
++ * and send just that key, but in that case the user would have to type
++ * blindly. :(
++ * TODO 2:
++ * A possible enhancement to the fix would be to provide some kind of preview
++ * with an additional character device and write some userspace app to display
++ * it in a seperate dialog.
++ *
++ */
++static void handle_scancode(unsigned char scancode, int down)
++{
++ unsigned char row = (scancode & 0xF) - 1;
++ unsigned char col = ((scancode & 0x70) >> 4);
++ unsigned char index = row * 8 + col;
++ static int layer = 0;
++
++ /*
++ * straight forward processing in case of:
++ * "up" events
++ * repeated keypress events that happen after more than 500ms
++ * after different key has been pressed ( ignore up/down! )
++ * there are no alternative keycodes available
++ */
++ if (!down || time_before(lke.jiffies + msecs_to_jiffies(500), jiffies)
++ || (lke.scancode & 0x7f) != (scancode &0x7F) ||
++ (keycode[1][index] == KEY_RESERVED) ) {
++ /* no cycling: process straightforward */
++ input_report_key(dev, keycode[0][index], down);
++ input_sync(dev);
++
++ /* end cycling on all but up events */
++ if(down)
++ layer=0;
++ } else {
++ /*
++ * cycling mode:
++ *
++ * if we have an alternative keycode available:
++ * 1. pretend the former key was wrong (and delete it)
++ * 2. replace with the keycode from the next layer
++ */
++
++ /* suppress real "up" events, as we fake immediate "up" here */
++ if (!down)
++ return;
++
++ /* switch to next layer, with wraparound */
++ if(++layer >= 16)
++ layer = 0;
++
++ /* if alternative keycodes are available */
++ if (keycode[layer][index] != KEY_RESERVED) {
++ /* pretend former key was wrong and delete it */
++ input_report_key(dev, KEY_BACKSPACE, 1);
++ input_report_key(dev, KEY_BACKSPACE, 0);
++ } else {
++ /* no more valid keycodes? => switch to layer 0 */
++ layer=0;
++ return;
++ }
++
++ /* send alternative keycode */
++ input_report_key(dev, keycode[layer][index], 1);
++ input_report_key(dev, keycode[layer][index], 0);
++ input_sync(dev);
++
++
++ }
++ lke.scancode = scancode;
++ lke.jiffies = jiffies;
++}
++#else
++/**
++ * handle_scancode - wrapper
++ *
++ * wrap old style (2.4.x) to 2.6.x input subsystem
++ */
++static void handle_scancode(unsigned char scancode, int down)
++{
++ /* printk("handle_scancode(scancode=%04X, down=%d); %02X ", scancode, down, scancode &0x7f); */
++
++ unsigned char row = (scancode & 0xF) - 1;
++ unsigned char col = ((scancode & 0x70) >> 4);
++ unsigned char index = row * 8 + col;
++
++ input_report_key(dev, keycode[index], down);
++ input_sync(dev);
++
++ /* printk("index=%02X\n", index); */
++}
++#endif
++
++static irqreturn_t ep93xxkbd_irq_handler(int irq, void *dev_id,
++ struct pt_regs *regs)
++{
++ unsigned int keystat, key1, key2;
++ static unsigned int lastkeystat = 0, lastkey1 = 0, lastkey2 = 0;
++
++ /* Note: IRQ_KEY automatically disabled before entry, */
++ /* and reenabled after exit by Linux interrupt code. */
++
++ /* Reading status clears keyboard interrupt */
++
++ keystat = readl(KEY_REG) &
++ (KEYREG_KEY1COL_MASK | KEYREG_KEY1ROW_MASK |
++ KEYREG_KEY2COL_MASK | KEYREG_KEY2ROW_MASK |
++ KEYREG_1KEY | KEYREG_2KEYS);
++
++#ifdef DEBUG /* DEBUGGING */
++ if (keystat == lastkeystat)
++ printk("ep93xx_scan_keyb: spurious interrupt, stat %x\n",
++ keystat);
++ else
++ printk("ep93xx_scan_keyb: interrupt, stat %x\n", keystat);
++#endif
++ if (keystat & KEYREG_1KEY)
++ key1 =
++ KEYCODE((keystat & KEYREG_KEY1ROW_MASK) >>
++ KEYREG_KEY1ROW_SHIFT,
++ (keystat & KEYREG_KEY1COL_MASK) >>
++ KEYREG_KEY1COL_SHIFT);
++ else
++ key1 = 0; /* invalid */
++
++ if (keystat & KEYREG_2KEYS)
++ key2 =
++ KEYCODE((keystat & KEYREG_KEY2ROW_MASK) >>
++ KEYREG_KEY2ROW_SHIFT,
++ (keystat & KEYREG_KEY2COL_MASK) >>
++ KEYREG_KEY2COL_SHIFT);
++ else
++ key2 = 0; /* invalid */
++
++ /*
++ * This 'monster' decision tree is used to decide what to report
++ * when last key state has changed to current key state.
++ * This may involve up to 4 keys changing state simultaneously:
++ * lastkey1, lastkey2 going up and key1, key2 going down.
++ *
++ * We use keyboard scanner hardware guarantees to simplify the logic:
++ * key1 < key2 if both are valid
++ * key1 is valid if key2 is valid
++ *
++ * handle_scancode called with down and up scancodes
++ * scancode = keycode when down
++ * scancode = keycode|KBUP when up
++ *
++ * Note that if more than one keys change state in the same scan period,
++ * then we really do NOT know the order in which the key events occurred.
++ * Our default behavior is to always report key up events before key down
++ * events. However, multiple key up events or multiple key down events
++ * will be reported in no special order.
++ */
++ if (!(lastkeystat & (KEYREG_1KEY | KEYREG_2KEYS))) { /* No keys down lasttime */
++ if (key1)
++ handle_scancode(key1, 1);
++ if (key2)
++ handle_scancode(key2, 1);
++ } else if (lastkey1 == key1) { /* means key still down */
++ /* no change for key1 or lastkey1, both valid */
++ if (lastkey2 != key2) {
++ /* lastkey2 went up if valid, key2 went down if valid */
++ if (lastkey2)
++ handle_scancode(lastkey2 | KBUP, 0);
++ if (key2)
++ handle_scancode(key2, 1);
++ }
++ /* else no change for all keys */
++ } else if (key1)
++ { /* key1 valid and */
++ /* lastkey1 valid (because NOT no keys lasttime) */
++ if (lastkey1 == key2) {
++ /* no change for lastkey1 or key2 */
++ /* lastkey2 went up if valid, key1 went down */
++ if (lastkey2)
++ handle_scancode(lastkey2 | KBUP, 0);
++ handle_scancode(key1, 1);
++
++ } else {
++ /* we know: lastkey1 valid and went up, key1 valid */
++ handle_scancode(lastkey1 | KBUP, 0);
++
++ if (lastkey2 == key1) {
++ /* no change for lastkey2 or key1 */
++ /* key2 went down if valid */
++ if (key2)
++ handle_scancode(key2, 1);
++
++ } else {
++ if (lastkey2 != key2) {
++ /* lastkey2 went up if valid */
++ /* key2 went down if valid */
++ if (lastkey2)
++ handle_scancode(lastkey2 | KBUP,
++ 0);
++ if (key2)
++ handle_scancode(key2, 1);
++ }
++ /* else no change for lastkey2 or key2 */
++
++ /* key1 valid and went down */
++ handle_scancode(key1, 1);
++ }
++ }
++ } else {
++ /* key1 not valid and */
++ /* lastkey1 valid (because NOT no keys lasttime) */
++
++ /* key1 not valid means both key1, key2 not valid */
++ /* so lastkey1 went up and lastkey2 went up if valid */
++ handle_scancode(lastkey1 | KBUP, 0);
++ if (lastkey2)
++ handle_scancode(lastkey2 | KBUP, 0);
++ }
++
++ lastkeystat = keystat;
++ lastkey1 = key1;
++ lastkey2 = key2;
++ return IRQ_HANDLED;
++}
++
++int __init ep93xxkbd_init(void)
++{
++ int i = 3;
++ unsigned int uiTemp;
++ int error = 0;
++
++ dev = input_allocate_device();
++ if (!dev) {
++ printk(KERN_ERR "ep93xx_kbd_8x8: not enough memory for input device\n");
++ return -ENOMEM;
++ }
++
++ dev->name = "Cirrus EP93xx 8x8 keypad matrix driver";
++ dev->phys = "input0";
++ dev->id.bustype = BUS_HOST;
++ dev->evbit[0] = BIT(EV_KEY);
++
++ printk("%s\n", dev->name);
++
++ /* Make sure scanner enabled, active and that */
++ /* Keyboard ROW/COL interface enabled. */
++
++ uiTemp = readl(SYSCON_DEVCFG);
++
++ uiTemp &= ~(SYSCON_DEVCFG_KEYS | SYSCON_DEVCFG_GONK);
++
++ SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(uiTemp));
++
++ /* SYSCON locked automatically now after RSTCR written */
++
++ /* Enable Keyboard Clock and select clock rate
++ *
++ * TBD Boot ROM has already inited KTDIV = 0x20018004
++ * TBD Measured default 64usec scan period with scope.
++
++ * Assume that GPIO registers do not impact row,col pins since
++ * they are assigned to keyboard scanner.
++
++ * Setup Keyboard Scanner
++ *
++ * Note that we change the scanner parameters on the fly
++ * while it is running, which is okay. No need to disable
++ * scanner while tweaking these.
++ *
++ * TBD Keyboard scan rate will change as master clocks/dividers change
++ *
++ * For now, this gives us measured rate of about 480Hz row scan rate,
++ * which implies 60Hz full kbd scan rate. Together with debounce
++ * count of 3, means debounce period = 3/60Hz = 50ms>30ms recommended,
++ * so okay.
++ */
++ writel((0x00FC00FA | SCANINIT_DIS3KY), SCANINIT);
++
++ /*TBD If too much capacitance on keyboard */
++ /* writel( (0x00FC0020 | SCBACK | SCDIS3KEY), SCANINIT ); */
++
++ uiTemp = readl(SYSCON_KTDIV) | SYSCON_KTDIV_KEN;
++
++ SysconSetLocked(SYSCON_KTDIV, uiTemp);
++
++ error =
++ request_irq(IRQ_KEY, ep93xxkbd_irq_handler, 0,
++ "ep93xx_keypad_handler",
++ (void *)(ep93xxkbd_irq_handler));
++ if (error) {
++ printk("Error: %s could not allocate IRQ%d\n", dev->name, IRQ_KEY);
++ return error;
++ }
++ /* Note: request_irq has just enabled IRQ_KEY for us. */
++
++ /* Warning: We have initialized last key status to indicate
++ * all keys up which may not be the current hardware state.
++ *
++ * TBD If this is important to detect, to alert user
++ * TBD to a possibly faulty keyboard, then we could
++ * TBD manually scan the keyboard to verify all keys up.
++ *
++
++ * Three common cases here:
++ * 1. All keys up. This is normal, expected status of keyboard.
++ * 2. All keys up, although at some time ago during initialization
++ * a key was momentarily pressed, causing the hardware to latch it.
++ * 3. Some key is being held down now.
++ *
++ * Reading status clears any pending keyboard interrupt.
++ */
++
++ i = readl(KEY_REG);
++
++ /*
++ * We believe this will have the following impact on common cases:
++ *
++ * 1. No impact.
++ * 2. Momentary presses will be cleared out so they do not
++ * bother us. Although we get a spurious key up immediately because
++ * the keyboard hardware will see change from last
++ * latched status and current status, higher level keyboard driver
++ * should ignore.
++ * 3. Key being held will generate a new pending key down
++ * event which is acceptable.
++ *
++ * Now keyboard is active and will generate interrupts
++ * on key presses. Driver only needs to handle interrupts.
++ * There are NO driver ioctl or deinit functions in lowlevel.
++ */
++
++#ifdef CONFIG_KEYBOARD_EP93XX_8X8_CYCLING
++ for (i = 0; i < EP93XX_KEYMAP_SIZE * 16; i++)
++ set_bit(keycode[i/EP93XX_KEYMAP_SIZE][i%EP93XX_KEYMAP_SIZE], dev->keybit);
++#else
++ for (i = 0; i < EP93XX_KEYMAP_SIZE; i++)
++ set_bit(keycode[i], dev->keybit);
++#endif
++
++ input_register_device(dev);
++
++ return 0;
++}
++
++static void __exit ep93xxkbd_cleanup(void)
++{
++ writel(0x000000AA, SYSCON_SWLOCK); /* unlock SYSCON Software Lock */
++ writel(readl(SYSCON_KTDIV) & 0xFFFF7FFF, SYSCON_KTDIV); /* disable Key Matrix Clock KEN */
++ free_irq(IRQ_KEY, NULL);
++ input_unregister_device(dev);
++}
++
++module_init(ep93xxkbd_init);
++module_exit(ep93xxkbd_cleanup);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h
+new file mode 100644
+index 0000000..31fd4db
+--- /dev/null
++++ b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap-cycling.h
+@@ -0,0 +1,146 @@
++static unsigned char keycode[16][0x40] =
++{{
++ KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, 0, 0,
++ KEY_ESC, KEY_BACKSPACE, KEY_7, KEY_8, KEY_9, 0, 0, 0,
++ KEY_PROG1, KEY_PROG2, KEY_4, KEY_5, KEY_6, 0, 0, 0,
++ KEY_MENU, KEY_0, KEY_1, KEY_2, KEY_3, 0, 0, 0,
++ KEY_LEFTSHIFT, KEY_UP, KEY_TAB, 0, 0, 0, 0, 0,
++ KEY_LEFT, KEY_LEFTALT, KEY_RIGHT, 0, 0, 0, 0, 0,
++ KEY_LEFTCTRL, KEY_DOWN, KEY_ENTER, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, KEY_A, KEY_D, KEY_G, 0, 0, 0,
++ 0, 0, KEY_J, KEY_M, KEY_P, 0, 0, 0,
++ 0, KEY_DOT, KEY_S, KEY_V, KEY_Y, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, KEY_B, KEY_E, KEY_H, 0, 0, 0,
++ 0, 0, KEY_K, KEY_N, KEY_Q, 0, 0, 0,
++ 0, KEY_COMMA, KEY_T, KEY_W, KEY_Z, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, KEY_C, KEY_F, KEY_I, 0, 0, 0,
++ 0, 0, KEY_L, KEY_O, KEY_R, 0, 0, 0,
++ 0, KEY_SLASH, KEY_U, KEY_X, KEY_SPACE, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, KEY_KPASTERISK, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, KEY_KPPLUS, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, KEY_KPMINUS, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, KEY_EQUAL, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, KEY_SEMICOLON, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, KEY_APOSTROPHE, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, KEY_KPLEFTPAREN, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, KEY_KPRIGHTPAREN, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, KEY_LEFTBRACE, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, KEY_RIGHTBRACE, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ }, {
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++}};
+diff --git a/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h
+new file mode 100644
+index 0000000..65dca77
+--- /dev/null
++++ b/drivers/input/keyboard/ep93xx_kbd_8x8_keymap.h
+@@ -0,0 +1,11 @@
++static unsigned char keycode[0x40] =
++{
++ KEY_F1, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, 0, 0,
++ KEY_ESC, KEY_BACKSPACE, KEY_7, KEY_8, KEY_9, 0, 0, 0,
++ KEY_PROG1, KEY_PROG2, KEY_4, KEY_5, KEY_6, 0, 0, 0,
++ KEY_MENU, KEY_0, KEY_1, KEY_2, KEY_3, 0, 0, 0,
++ KEY_LEFTSHIFT, KEY_UP, KEY_TAB, 0, 0, 0, 0, 0,
++ KEY_LEFT, KEY_LEFTALT, KEY_RIGHT, 0, 0, 0, 0, 0,
++ KEY_LEFTCTRL, KEY_DOWN, KEY_ENTER, 0, 0, 0, 0, 0,
++ 0, 0, 0, 0, 0, 0, 0, 0,
++};
+diff --git a/drivers/input/keyboard/ep93xx_spi_kbd.c b/drivers/input/keyboard/ep93xx_spi_kbd.c
+new file mode 100644
+index 0000000..b6ad607
+--- /dev/null
++++ b/drivers/input/keyboard/ep93xx_spi_kbd.c
+@@ -0,0 +1,407 @@
++/******************************************************************************
++ *
++ * File: linux/drivers/char/ep93xx_spi_kbd.c
++ *
++ * Purpose: Support for SPI Keyboard for a Cirrus Logic EP93xx
++ *
++ * History:
++ *
++ * Limitations:
++ * Break and Print Screen keys not handled yet!
++ *
++ *
++ * Copyright 2003 Cirrus Logic Inc.
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ ******************************************************************************/
++
++/*
++ * FIXME: There are more parity problems than there ought to be.
++ * TODO: Track down
++ * WHERE: grep for "BAD_PARITY"
++ *
++ * WORKAROUND: Do not press too many keys and do not type too fast
++ * type key another time if it got lost
++ *
++ * WORKAROUND2: Use USB Keyboards or 8x8 matrix keypad instead
++ *
++ * FIXME2: Keymap should be done properly
++ */
++
++#include <linux/config.h>
++#include <linux/init.h>
++#include <linux/input.h>
++#include <linux/module.h>
++#include <asm/io.h>
++#include <asm/uaccess.h>
++#include <asm/hardware.h>
++#include <asm/arch/ssp-cirrus.h>
++
++#include "ep93xx_spi_kbd.h"
++
++#define EP93XX_MAX_KEY_DOWN_COUNT 6
++
++void DataCallback(unsigned int Data);
++static int g_SSP_Handle;
++static struct input_dev *ep93xxkbd_dev;
++
++#undef UART_HACK_DEBUG
++/* #define UART_HACK_DEBUG 1 */
++
++#if defined(UART_HACK_DEBUG) && defined(CONFIG_DEBUG_LL)
++char szBuf[256];
++#define DPRINTK( x... ) \
++ sprintf( szBuf, ##x ); \
++ printascii( szBuf );
++#else
++#define DPRINTK( x... )
++#endif
++
++struct key_down_tracker_t {
++ unsigned char scancode;
++ unsigned char count;
++};
++
++/*
++ * In the interest of efficiency, let's only allow 5 keys to be down
++ * at a time, maximum. So if anybody is having a temper tantrum on
++ * their keyboard, they may get stuck keys, but that's to be expected.
++ */
++
++#define MAX_KEYS_DOWN 8
++static struct key_down_tracker_t KeyTracker[MAX_KEYS_DOWN];
++
++static unsigned char SPI2KScan(unsigned int uiSPIValue, int *pValid);
++static void InitSniffer(void);
++static void KeySniffer(unsigned char scancode, int down);
++static void Check4StuckKeys(void);
++
++/**
++ * handle_scancode - wrapper
++ *
++ * wrap old style (2.4.x) to 2.6.x input subsystem
++ */
++static void handle_scancode(unsigned char scancode, int down)
++{
++ DPRINTK("handle_scancode(scancode=%04X, down=%d); %02X ", scancode,
++ down, scancode & 0x7f);
++
++ if (scancode > KSCAN_TABLE_SIZE)
++ scancode &= ~EXTENDED_KEY;
++
++ input_report_key(ep93xxkbd_dev, KScanCodeToVKeyTable[scancode], down);
++ input_sync(ep93xxkbd_dev);
++
++ DPRINTK("(virtual) scancode=%02X\n", scancode);
++}
++
++/**
++ * InitSniffer
++ *
++ * Clear our struct to indicate that no keys are down now.
++ * If somebody boots this thing while holding down keys, then they'll
++ * get what they deserve.
++ *
++ */
++static void InitSniffer(void)
++{
++ int i;
++
++ for (i = 0; i < MAX_KEYS_DOWN; i++) {
++ KeyTracker[i].count = 0;
++ KeyTracker[i].scancode = 0;
++ }
++}
++
++/**
++ * KeySniffer
++ *
++ * To prevent stuck keys, keep track of what keys are down. This information
++ * is used by Check4StuckKeys().
++ */
++static void KeySniffer(unsigned char scancode, int down)
++{
++ int i;
++
++ /*
++ * There are certain keys that will definately get held down
++ * and we can't interfere with that.
++ */
++ switch (scancode) {
++ case 0x12: /* left shift */
++ case 0x59: /* right shift */
++ case 0x14: /* left ctrl */
++ case 0x94: /* right ctrl */
++ case 0x11: /* left alt */
++ case 0x91: /* right alt */
++ case 0x58: /* caps lock */
++ case 0x77: /* Num lock */
++ /* printk("Snuff - %02x, %d\n", scancode, down); */
++ handle_scancode(scancode, down);
++ return;
++
++ default:
++ break;
++ }
++
++ /* printk("Sniff - %02x, %d\n", scancode, down ); */
++
++ /*
++ * Go thru our array, looking for the key. If it already
++ * is recorded, update its count.
++ * Also look for empty cells in the array in case we
++ * need one.
++ */
++ for (i = 0; i < MAX_KEYS_DOWN; i++) {
++ /* If this is a key up in our list then we are done. */
++ if (down == 0) {
++ if (KeyTracker[i].scancode == scancode) {
++ KeyTracker[i].count = 0;
++ KeyTracker[i].scancode = 0;
++ handle_scancode(scancode, down);
++ break;
++ }
++ }
++ /* Hey here's an unused cell. Save its index. */
++ else if (KeyTracker[i].count == 0) {
++ KeyTracker[i].scancode = scancode;
++ KeyTracker[i].count = 1;
++ handle_scancode(scancode, down);
++ break;
++ }
++ }
++}
++
++/**
++ * Check4StuckKeys
++ *
++ * When a key is held down longer than 1/2 sec, it start repeating
++ * 10 times a second. What we do is watch how long each key is
++ * held down. If longer than X where X is less than 1/2 second
++ * then we assume it is stuck and issue the key up. If we were
++ * wrong and the key really is being held down, no problem because
++ * the keyboard is about to start sending it to us repeatedly
++ * anyway.
++ */
++static void Check4StuckKeys(void)
++{
++ int i;
++
++ for (i = 0; i < MAX_KEYS_DOWN; i++) {
++ if (KeyTracker[i].count) {
++ KeyTracker[i].count++;
++ if (KeyTracker[i].count >= EP93XX_MAX_KEY_DOWN_COUNT) {
++ handle_scancode(KeyTracker[i].scancode, 0);
++ KeyTracker[i].count = 0;
++ KeyTracker[i].scancode = 0;
++ }
++ }
++ }
++}
++
++/**
++ * HandleKeyPress
++ *
++ * Checks if there are any keys in the FIFO and processes them if there are.
++ */
++void HandleKeyPress(unsigned int Data)
++{
++ static unsigned char ucKScan[4] = { 0, 0, 0, 0 };
++ static unsigned int ulNum = 0;
++ int bParityValid;
++
++ /*
++ * No keys to decode, but the timer went off and is calling us
++ * to check for stuck keys.
++ */
++ if (Data == -1) {
++ Check4StuckKeys();
++ return;
++ }
++ /*
++ * Read in the value from the SPI controller.
++ */
++ ucKScan[ulNum++] = SPI2KScan(Data, &bParityValid);
++
++ /*
++ * Bad parity? We should read the rest of the fifo and
++ * throw it away, because it will all be bad. Then the
++ * SSP will be reset when we close the SSP driver and
++ * all will be good again.
++ */
++ if (!bParityValid) {
++ /* printk("_BAD_PARITY_"); */
++ ulNum = 0;
++ }
++ /* If we have one character in the array, do the following. */
++ if (ulNum == 1) {
++ /*
++ * If it is a simple key without the extended scan code perform
++ * following.
++ */
++ if (ucKScan[0] < KSCAN_TABLE_SIZE) {
++ DPRINTK("1:Dn %02x\n", ucKScan[0]);
++ KeySniffer(ucKScan[0], 1);
++ ulNum = 0;
++ }
++ /*
++ * I don't know what type of character this is so erase the
++ * keys stored in the buffer and continue.
++ */
++ else if ((ucKScan[0] != 0xF0) && (ucKScan[0] != 0xE0)) {
++ DPRINTK("1:oops - %02x\n", ucKScan[0]);
++ ulNum = 0;
++ }
++ } else if (ulNum == 2) {
++ /*
++ * 0xF0 means that a key has been released.
++ */
++ if (ucKScan[0] == 0xF0) {
++ /*
++ * If it is a simple key without the extended scan code
++ * perform the following.
++ */
++ if (ucKScan[1] < KSCAN_TABLE_SIZE) {
++ DPRINTK("2:Up %02x %02x\n", ucKScan[0],
++ ucKScan[1]);
++ KeySniffer(ucKScan[1], 0);
++ ulNum = 0;
++ }
++ /*
++ * If it a extended kscan continue to get the next byte.
++ */
++ else if (ucKScan[1] != 0xE0) {
++ DPRINTK("2:oops - %02x %02x\n", ucKScan[0],
++ ucKScan[1]);
++ ulNum = 0;
++ }
++ }
++ /*
++ * Find out what extended code it is.
++ */
++ else if (ucKScan[0] == 0xE0 && ucKScan[1] != 0xF0) {
++ DPRINTK("2:Dn %02x %02x\n", ucKScan[0], ucKScan[1]);
++ KeySniffer(EXTENDED_KEY | ucKScan[1], 1);
++ ulNum = 0;
++ }
++ }
++ /* This means that an extended code key has been released. */
++ else if (ulNum == 3) {
++ /* 0xF0 means that a key has been released. */
++ if (ucKScan[0] == 0xE0 && ucKScan[1] == 0xF0) {
++ DPRINTK("3:Up %02x %02x %02x",
++ ucKScan[0], ucKScan[1], ucKScan[2]);
++ KeySniffer(EXTENDED_KEY | ucKScan[2], 0);
++ } else {
++ DPRINTK("3:oops - %02x %02x %02x\n",
++ ucKScan[0], ucKScan[1], ucKScan[2]);
++ }
++ ulNum = 0;
++ }
++}
++
++/**
++ * SPI2KScan - Get a character from the spi port if it is available.
++ *
++ * Below is a picture of the spi signal from the PS2.
++ *
++ * CK HHllllHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHHHLLLHllll
++ * DA HHHllllll000000111111222222333333444444555555666666777777ppppppssssssLLLLHHH
++ * ^ ^
++ * start bit important bit
++ *
++ * where: l = 8042 driving the line
++ * L = KEYBOARD driving the line
++ * 1..7 data
++ * = Parity 8042 driving
++ * s = stop 8042 driving
++ * = PARITY KEYBOARD driving the line
++ * S = STOP KEYBOARD driving the line
++ *
++ * In our design the value comes high bit first and is inverted. So we must
++ * convert it to low byte first and then inverted it back.
++ *
++ */
++static unsigned char SPI2KScan(unsigned int uiSPIValue, int *pValid)
++{
++ unsigned char ucKScan = 0;
++ unsigned int uiParity = 0;
++ unsigned int uiCount = 0;
++
++ for (uiCount = 1; uiCount < 10; uiCount++) {
++ uiParity += (uiSPIValue >> uiCount) & 0x1;
++ }
++
++ if (!(uiParity & 0x1) && (uiSPIValue & 0x401) == 0x400) {
++ *pValid = 1;
++
++ /* Invert the pattern. */
++ uiSPIValue = ~uiSPIValue;
++
++ /* Read in the value from the motorola spi file */
++ ucKScan = (unsigned char)((uiSPIValue & 0x004) << 5);
++ ucKScan |= (unsigned char)((uiSPIValue & 0x008) << 3);
++ ucKScan |= (unsigned char)((uiSPIValue & 0x010) << 1);
++ ucKScan |= (unsigned char)((uiSPIValue & 0x020) >> 1);
++ ucKScan |= (unsigned char)((uiSPIValue & 0x040) >> 3);
++ ucKScan |= (unsigned char)((uiSPIValue & 0x080) >> 5);
++ ucKScan |= (unsigned char)((uiSPIValue & 0x100) >> 7);
++ ucKScan |= (unsigned char)((uiSPIValue & 0x200) >> 9);
++ } else {
++ *pValid = 0;
++ }
++
++ return ucKScan;
++}
++
++int __init EP93XXSpiKbdInit(void)
++{
++ int i;
++
++ ep93xxkbd_dev = input_allocate_device();
++ if (!ep93xxkbd_dev) {
++ printk(KERN_ERR "ep93xxkbd: not enough memory for input device\n");
++ return -ENOMEM;
++ }
++
++ ep93xxkbd_dev->name = "Cirrus EP93xx PS/2 keyboard driver";
++ printk("%s\n", ep93xxkbd_dev->name);
++
++ ep93xxkbd_dev->evbit[0] = BIT(EV_KEY);
++
++ for (i = 0; i < KSCAN_TABLE_SIZE; i++)
++ set_bit(KScanCodeToVKeyTable[i], ep93xxkbd_dev->keybit);
++
++ input_register_device(ep93xxkbd_dev);
++
++ /* Open SSP driver for Keyboard input. */
++ g_SSP_Handle = SSPDriver->Open(PS2_KEYBOARD, HandleKeyPress);
++
++ InitSniffer();
++
++ DPRINTK("Leaving EP93XXSpiKbdInit()\n");
++
++ return 0;
++}
++
++void __exit EP93XXSpiKbdCleanup(void)
++{
++ SSPDriver->Close(g_SSP_Handle);
++ input_unregister_device(ep93xxkbd_dev);
++}
++
++module_init(EP93XXSpiKbdInit);
++module_exit(EP93XXSpiKbdCleanup);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/input/keyboard/ep93xx_spi_kbd.h b/drivers/input/keyboard/ep93xx_spi_kbd.h
+new file mode 100644
+index 0000000..7f4bd90
+--- /dev/null
++++ b/drivers/input/keyboard/ep93xx_spi_kbd.h
+@@ -0,0 +1,147 @@
++/*
++ * ep93xx_spi_kbd.h Keymap definitions (to be cleaned up)
++ */
++
++#define KSCAN_TABLE_SIZE 0x88
++
++#define EXTENDED_KEY 0x80
++
++/* This table is used to map the scan code to the Linux default keymap. */
++static unsigned int const KScanCodeToVKeyTable[KSCAN_TABLE_SIZE] = {
++ KEY_RESERVED, /* Scan Code 0x0 */
++ KEY_F9, /* Scan Code 0x1 */
++ KEY_RESERVED, /* Scan Code 0x2 */
++ KEY_F5, /* Scan Code 0x3 */
++ KEY_F3, /* Scan Code 0x4 */
++ KEY_F1, /* Scan Code 0x5 */
++ KEY_F2, /* Scan Code 0x6 */
++ KEY_F12, /* Scan Code 0x7 */
++ KEY_RESERVED, /* Scan Code 0x8 */
++ KEY_F10, /* Scan Code 0x9 */
++ KEY_F8, /* Scan Code 0xA */
++ KEY_F6, /* Scan Code 0xB */
++ KEY_F4, /* Scan Code 0xC */
++ KEY_TAB, /* Scan Code 0xD Tab */
++ KEY_GRAVE, /* Scan Code 0xE ' */
++ KEY_RESERVED, /* Scan Code 0xF */
++ KEY_RESERVED, /* Scan Code 0x10 */
++ KEY_LEFTALT, /* Scan Code 0x11 Left Menu */
++ KEY_LEFTSHIFT, /* Scan Code 0x12 Left Shift */
++ KEY_RESERVED, /* Scan Code 0x13 */
++ KEY_LEFTCTRL, /* Scan Code 0x14 */
++ KEY_Q, /* Scan Code 0x15 */
++ KEY_1, /* Scan Code 0x16 */
++ KEY_RESERVED, /* Scan Code 0x17 */
++ KEY_RESERVED, /* Scan Code 0x18 */
++ KEY_RESERVED, /* Scan Code 0x19 */
++ KEY_Z, /* Scan Code 0x1A */
++ KEY_S, /* Scan Code 0x1B */
++ KEY_A, /* Scan Code 0x1C */
++ KEY_W, /* Scan Code 0x1D */
++ KEY_2, /* Scan Code 0x1E */
++ KEY_RESERVED, /* Scan Code 0x1F */
++ KEY_RESERVED, /* Scan Code 0x20 */
++ KEY_C, /* Scan Code 0x21 */
++ KEY_X, /* Scan Code 0x22 */
++ KEY_D, /* Scan Code 0x23 */
++ KEY_E, /* Scan Code 0x24 */
++ KEY_4, /* Scan Code 0x25 */
++ KEY_3, /* Scan Code 0x26 */
++ KEY_RESERVED, /* Scan Code 0x27 */
++ KEY_RESERVED, /* Scan Code 0x28 */
++ KEY_SPACE, /* Scan Code 0x29 Space */
++ KEY_V, /* Scan Code 0x2A */
++ KEY_F, /* Scan Code 0x2B */
++ KEY_T, /* Scan Code 0x2C */
++ KEY_R, /* Scan Code 0x2D */
++ KEY_5, /* Scan Code 0x2E */
++ KEY_RESERVED, /* Scan Code 0x2F */
++ KEY_RESERVED, /* Scan Code 0x30 */
++ KEY_N, /* Scan Code 0x31 */
++ KEY_B, /* Scan Code 0x32 B */
++ KEY_H, /* Scan Code 0x33 */
++ KEY_G, /* Scan Code 0x34 */
++ KEY_Y, /* Scan Code 0x35 */
++ KEY_6, /* Scan Code 0x36 */
++ KEY_RESERVED, /* Scan Code 0x37 */
++ KEY_RESERVED, /* Scan Code 0x38 */
++ KEY_RESERVED, /* Scan Code 0x39 */
++ KEY_M, /* Scan Code 0x3A */
++ KEY_J, /* Scan Code 0x3B */
++ KEY_U, /* Scan Code 0x3C */
++ KEY_7, /* Scan Code 0x3D */
++ KEY_8, /* Scan Code 0x3E */
++ KEY_RESERVED, /* Scan Code 0x3F */
++ KEY_RESERVED, /* Scan Code 0x40 */
++ KEY_COMMA, /* Scan Code 0x41 */
++ KEY_K, /* Scan Code 0x42 */
++ KEY_I, /* Scan Code 0x43 */
++ KEY_O, /* Scan Code 0x44 */
++ KEY_0, /* Scan Code 0x45 */
++ KEY_9, /* Scan Code 0x46 */
++ KEY_RESERVED, /* Scan Code 0x47 */
++ KEY_RESERVED, /* Scan Code 0x48 */
++ KEY_DOT, /* Scan Code 0x49 */
++ KEY_SLASH, /* Scan Code 0x4A */
++ KEY_L, /* Scan Code 0x4B */
++ KEY_SEMICOLON, /* Scan Code 0x4C */
++ KEY_P, /* Scan Code 0x4D */
++ KEY_MINUS, /* Scan Code 0x4E */
++ KEY_RESERVED, /* Scan Code 0x4F */
++ KEY_RESERVED, /* Scan Code 0x50 */
++ KEY_RESERVED, /* Scan Code 0x51 */
++ KEY_APOSTROPHE, /* Scan Code 0x52 */
++ KEY_RESERVED, /* Scan Code 0x53 */
++ KEY_LEFTBRACE, /* Scan Code 0x54 */
++ KEY_EQUAL, /* Scan Code 0x55 */
++ KEY_BACKSPACE, /* Scan Code 0x56 */
++ KEY_RESERVED, /* Scan Code 0x57 */
++ KEY_CAPSLOCK, /* Scan Code 0x58 Caps Lock */
++ KEY_RIGHTSHIFT, /* Scan Code 0x59 Right Shift */
++ KEY_ENTER, /* Scan Code 0x5A */
++ KEY_RIGHTBRACE, /* Scan Code 0x5B */
++ KEY_RESERVED, /* Scan Code 0x5C */
++ KEY_BACKSLASH, /* Scan Code 0x5D */
++ KEY_RESERVED, /* Scan Code 0x5E */
++ KEY_RESERVED, /* Scan Code 0x5F */
++ KEY_RESERVED, /* Scan Code 0x60 */
++ KEY_BACKSLASH, /* Scan Code 0x61 ?? VK_BSLH, */
++ KEY_RESERVED, /* Scan Code 0x62 */
++ KEY_RESERVED, /* Scan Code 0x63 */
++ KEY_RESERVED, /* Scan Code 0x64 */
++ KEY_RESERVED, /* Scan Code 0x65 */
++ KEY_BACKSPACE, /* Scan Code 0x66 ?? VK_BKSP, */
++ KEY_RESERVED, /* Scan Code 0x67 */
++ KEY_RESERVED, /* Scan Code 0x68 */
++ KEY_KP1, /* Scan Code 0x69 */
++ KEY_RESERVED, /* Scan Code 0x6A */
++ KEY_KP4, /* Scan Code 0x6B */
++ KEY_KP7, /* Scan Code 0x6C */
++ KEY_RESERVED, /* Scan Code 0x6D */
++ KEY_RESERVED, /* Scan Code 0x6E */
++ KEY_RESERVED, /* Scan Code 0x6F */
++ KEY_KP0, /* Scan Code 0x70 */
++ KEY_KPDOT, /* Scan Code 0x71 DECIMAL?? */
++ KEY_KP2, /* Scan Code 0x72 */
++ KEY_KP5, /* Scan Code 0x73 */
++ KEY_KP6, /* Scan Code 0x74 */
++ KEY_KP8, /* Scan Code 0x75 */
++ KEY_ESC, /* Scan Code 0x76 */
++ KEY_NUMLOCK, /* Scan Code 0x77 */
++ KEY_F11, /* Scan Code 0x78 */
++ KEY_KPPLUS, /* Scan Code 0x79 */
++ KEY_KP3, /* Scan Code 0x7A */
++ KEY_KPMINUS, /* Scan Code 0x7B */
++ KEY_KPASTERISK, /* Scan Code 0x7C */
++ KEY_KP9, /* Scan Code 0x7D */
++ KEY_SCROLLLOCK, /* Scan Code 0x7E */
++ KEY_RESERVED, /* Scan Code 0x7F */
++ KEY_RESERVED, /* Scan Code 0x80 */
++ KEY_RESERVED, /* Scan Code 0x81 */
++ KEY_RESERVED, /* Scan Code 0x82 */
++ KEY_F7, /* Scan Code 0x83 */
++ KEY_RESERVED, /* Scan Code 0x84 */
++ KEY_RESERVED, /* Scan Code 0x85 */
++ KEY_RESERVED, /* Scan Code 0x86 */
++ KEY_RESERVED /* Scan Code 0x87 */
++};
+diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
+index 21d55ed..5453395 100644
+--- a/drivers/input/touchscreen/Kconfig
++++ b/drivers/input/touchscreen/Kconfig
+@@ -95,4 +95,15 @@ config TOUCHSCREEN_HP600
+ To compile this driver as a module, choose M here: the
+ module will be called hp680_ts_input.
+
++config TOUCHSCREEN_EP93XX
++ tristate "EP93xx touchscreen"
++ depends on ARCH_EP93XX
++ help
++ Say Y here if you have a touchscreen connected to your EP93xx CPU.
++
++ If unsure, say N.
++
++ To compile this driver as a module, choose M here: the
++ module will be called ep93xx_ts.
++
+ endif
+diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
+index 6842869..f8e6eb4 100644
+--- a/drivers/input/touchscreen/Makefile
++++ b/drivers/input/touchscreen/Makefile
+@@ -11,3 +11,4 @@ obj-$(CONFIG_TOUCHSCREEN_ELO) += elo.o
+ obj-$(CONFIG_TOUCHSCREEN_MTOUCH) += mtouch.o
+ obj-$(CONFIG_TOUCHSCREEN_MK712) += mk712.o
+ obj-$(CONFIG_TOUCHSCREEN_HP600) += hp680_ts_input.o
++obj-$(CONFIG_TOUCHSCREEN_EP93XX) += ep93xx_ts.o
+diff --git a/drivers/input/touchscreen/ep93xx_ts.c b/drivers/input/touchscreen/ep93xx_ts.c
+new file mode 100644
+index 0000000..fc4622e
+--- /dev/null
++++ b/drivers/input/touchscreen/ep93xx_ts.c
+@@ -0,0 +1,748 @@
++/*
++ * linux/drivers/char/ep93xx_ts.c
++ *
++ * Copyright (C) 2003-2004 Cirrus Corp.
++ *
++ * 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/types.h>
++#include <linux/delay.h>
++#include <linux/sched.h>
++#include <linux/init.h>
++#include <linux/interrupt.h>
++#include <linux/timer.h>
++#include <linux/input.h>
++#include <linux/pci.h>
++
++#include <asm/irq.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++
++/*
++ * To customize for a new touchscreen, there are various macros that
++ * have to be set. If you allow UART_HACK_DEBUG to be defined, you
++ * will get real time ts data scrolling up your serial terminal
++ * screen that will help you empirically determine good values for these.
++ *
++ *
++ * These are used as trigger levels to know when we have pen up/down
++ *
++ * The rules:
++ * 1. TS_HEAVY_INV_PRESSURE < TS_LIGHT_INV_PRESSURE because these
++ * are Inverse pressure.
++ * 2. Any touch lighter than TS_LIGHT_INV_PRESSURE is a pen up.
++ * 3. Any touch heavier than TS_HEAVY_INV_PRESSURE is a pen down.
++ */
++#define TS_HEAVY_INV_PRESSURE (0x1000 - pressure_max)
++#define TS_LIGHT_INV_PRESSURE (0x1000 - pressure_min)
++
++/*
++ * If the x, y, or inverse pressure changes more than these values
++ * between two succeeding points, the point is not reported.
++ */
++#define TS_MAX_VALID_PRESSURE_CHANGE (pressure_jitter)
++#define TS_MAX_VALID_XY_CHANGE (xy_jitter)
++
++/* old defaults */
++#if 0
++#define TS_X_MIN 0
++#define TS_Y_MIN 0
++#define TS_X_MAX 0xfff
++#define TS_Y_MAX 0xfff
++#endif
++
++/* "improved" defaults */
++#define TS_X_MIN 0x2d9
++#define TS_Y_MIN 0xd0a
++#define TS_X_MAX 0xd42
++#define TS_Y_MAX 0x2e0
++
++static uint16_t pressure_min = 0x001;
++static uint16_t pressure_max = 0x010;
++static uint16_t pressure_jitter = 0x300;
++static uint16_t xy_jitter = 0x100;
++module_param(pressure_min, ushort, 0);
++module_param(pressure_max, ushort, 0);
++module_param(pressure_jitter, ushort, 0);
++module_param(xy_jitter, ushort, 0);
++MODULE_PARM_DESC(pressure_min, "Minimum pressure (0 - 4095)");
++MODULE_PARM_DESC(pressure_max, "Maximum pressure (0 - 4095)");
++MODULE_PARM_DESC(pressure_jitter, "Minimum pressure jitter (0 - 4095)");
++MODULE_PARM_DESC(xy_jitter, "Minimum X-Y jitter (0 - 4095)");
++
++/* This is the minimum Z1 Value that is valid. */
++#define MIN_Z1_VALUE 0x50
++
++/*
++ * Settling delay for taking each ADC measurement. Increase this
++ * if ts is jittery.
++ */
++#define EP93XX_TS_ADC_DELAY_USEC 2000
++
++/* Delay between TS points. */
++
++#define EP93XX_TS_PER_POINT_DELAY_USEC 10000
++
++/*-----------------------------------------------------------------------------
++ * Debug messaging thru the UARTs
++ *-----------------------------------------------------------------------------
++ *
++ * Hello there! Are you trying to get this driver to work with a new
++ * touschscreen? Turn this on and you will get useful info coming
++ * out of your serial port.
++ */
++
++/* #define PRINT_CALIBRATION_FACTORS */
++#ifdef PRINT_CALIBRATION_FACTORS
++#define UART_HACK_DEBUG 1
++int iMaxX = 0, iMaxY = 0, iMinX = 0xfff, iMinY = 0xfff;
++#endif
++
++/*
++ * For debugging, let's spew messages out serial port 1 or 3 at 57,600 baud.
++ */
++#undef UART_HACK_DEBUG
++#if defined(UART_HACK_DEBUG) && defined (CONFIG_DEBUG_LL)
++static char szBuf[256];
++void UARTWriteString(char *msg);
++extern void printascii(const char *msg);
++#define DPRINTK( x... ) \
++ sprintf( szBuf, ##x ); \
++ printascii( szBuf );
++#else
++#define DPRINTK( x... )
++#endif
++
++#define TSSETUP_DEFAULT ( TSSETUP_NSMP_32 | TSSETUP_DEV_64 | \
++ ((128<<TSSETUP_SDLY_SHIFT) & TSSETUP_SDLY_MASK) | \
++ ((128<<TSSETUP_DLY_SHIFT) & TSSETUP_DLY_MASK) )
++
++#define TSSETUP2_DEFAULT (TSSETUP2_NSIGND)
++
++static unsigned int guiLastX, guiLastY;
++static unsigned int guiLastInvPressure;
++static int bCurrentPenDown;
++static DECLARE_MUTEX(open_sem);
++
++enum ts_mode_t {
++ TS_MODE_UN_INITIALIZED,
++ TS_MODE_HARDWARE_SCAN,
++ TS_MODE_SOFT_SCAN
++};
++
++static enum ts_mode_t gScanningMode;
++
++enum ts_states_t {
++ TS_STATE_STOPPED = 0,
++ TS_STATE_Z1,
++ TS_STATE_Z2,
++ TS_STATE_Y,
++ TS_STATE_X,
++ TS_STATE_DONE
++};
++
++struct ts_struct_t {
++ unsigned int uiX;
++ unsigned int uiY;
++ unsigned int uiZ1;
++ unsigned int uiZ2;
++ enum ts_states_t state;
++};
++
++static struct ts_struct_t sTouch;
++
++/*
++ * From the spec, here's how to set up the touch screen's switch registers.
++ */
++struct SwitchStructType {
++ unsigned int uiDetect;
++ unsigned int uiDischarge;
++ unsigned int uiXSample;
++ unsigned int uiYSample;
++ unsigned int uiSwitchZ1;
++ unsigned int uiSwitchZ2;
++};
++
++/*
++ * Here's the switch settings for a 4-wire touchscreen. See the spec
++ * for how to handle a 4, 7, or 8-wire.
++ */
++const static struct SwitchStructType sSwitchSettings =
++/* s28en=0
++ * TSDetect TSDischarge TSXSample TSYSample SwitchZ1 SwitchZ2
++ */
++{ 0x00403604, 0x0007fe04, 0x00081604, 0x00104601, 0x00101601, 0x00101608 };
++
++static void ep93xx_ts_set_direct(unsigned int uiADCSwitch);
++static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id, struct pt_regs *regs);
++static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id,
++ struct pt_regs *regs);
++static void ep93xx_hw_setup(void);
++static void ep93xx_hw_shutdown(void);
++static unsigned int CalculateInvPressure(void);
++static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff);
++static void TS_Soft_Scan_Mode(void);
++static void TS_Hardware_Scan_Mode(void);
++static void ProcessPointData(struct input_dev *dev);
++static void Set_Timer2_uSec(unsigned int Delay_mSec);
++static void Stop_Timer2(void);
++
++static irqreturn_t ep93xx_ts_isr(int irq, void *dev_id, struct pt_regs *regs)
++{
++ DPRINTK("isr\n");
++
++ /*
++ * Note that we don't clear the interrupt here. The interrupt
++ * gets cleared in TS_Soft_Scan_Mode when the TS ENABLE
++ * bit is cleared.
++ *
++
++ *
++ * Set the ts to manual polling mode and schedule a callback.
++ * That way we can return from the isr in a reasonable amount of
++ * time and process the touch in the callback after a brief delay.
++ */
++ TS_Soft_Scan_Mode();
++ return IRQ_HANDLED;
++}
++
++static int ep93xx_ts_open(struct input_dev *dev)
++{
++ int err;
++
++ if (down_trylock(&open_sem))
++ return -EBUSY;
++
++ err =
++ request_irq(IRQ_TOUCH, ep93xx_ts_isr, SA_INTERRUPT, "ep93xx_ts",
++ dev);
++ if (err) {
++ printk(KERN_WARNING
++ "ep93xx_ts: failed to get touchscreen IRQ\n");
++ return err;
++ }
++
++ err = request_irq(IRQ_TIMER2, ep93xx_timer2_isr,
++ SA_INTERRUPT, "ep93xx_timer2", dev);
++ if (err) {
++ printk(KERN_WARNING "ep93xx_ts: failed to get timer2 IRQ\n");
++ free_irq(IRQ_TOUCH, dev);
++ return err;
++ }
++
++ ep93xx_hw_setup();
++
++ return 0;
++}
++
++static void ep93xx_ts_close(struct input_dev *dev)
++{
++ Stop_Timer2();
++
++ ep93xx_hw_shutdown();
++
++ free_irq(IRQ_TIMER2, dev);
++ free_irq(IRQ_TOUCH, dev);
++
++ up(&open_sem);
++}
++
++static void ep93xx_hw_setup(void)
++{
++ unsigned int uiKTDIV, uiTSXYMaxMin;
++
++ /*
++ * Set the TSEN bit in KTDIV so that we are enabling the clock
++ * for the touchscreen.
++ */
++ uiKTDIV = readl(SYSCON_KTDIV);
++ uiKTDIV |= SYSCON_KTDIV_TSEN;
++ SysconSetLocked(SYSCON_KTDIV, uiKTDIV);
++
++ writel(TSSETUP_DEFAULT, TSSetup);
++ writel(TSSETUP2_DEFAULT, TSSetup2);
++
++ /* Set the the touch settings. */
++ writel(0xaa, TSSWLock);
++ writel(sSwitchSettings.uiDischarge, TSDirect);
++
++ writel(0xaa, TSSWLock);
++ writel(sSwitchSettings.uiDischarge, TSDischarge);
++
++ writel(0xaa, TSSWLock);
++ writel(sSwitchSettings.uiSwitchZ1, TSXSample);
++
++ writel(0xaa, TSSWLock);
++ writel(sSwitchSettings.uiSwitchZ2, TSYSample);
++
++ writel(0xaa, TSSWLock);
++ writel(sSwitchSettings.uiDetect, TSDetect);
++
++ /*
++ * X,YMin set to 0x40 = have to drag that many pixels for a new irq.
++ * X,YMax set to 0x40 = 1024 pixels is the maximum movement within the
++ * time scan limit.
++ */
++ uiTSXYMaxMin = (50 << TSMAXMIN_XMIN_SHIFT) & TSMAXMIN_XMIN_MASK;
++ uiTSXYMaxMin |= (50 << TSMAXMIN_YMIN_SHIFT) & TSMAXMIN_YMIN_MASK;
++ uiTSXYMaxMin |= (0xff << TSMAXMIN_XMAX_SHIFT) & TSMAXMIN_XMAX_MASK;
++ uiTSXYMaxMin |= (0xff << TSMAXMIN_YMAX_SHIFT) & TSMAXMIN_YMAX_MASK;
++ writel(uiTSXYMaxMin, TSXYMaxMin);
++
++ bCurrentPenDown = 0;
++ guiLastX = 0;
++ guiLastY = 0;
++ guiLastInvPressure = 0xffffff;
++
++ /* Enable the touch screen scanning engine. */
++
++ TS_Hardware_Scan_Mode();
++
++}
++
++static void ep93xx_hw_shutdown(void)
++{
++ unsigned int uiKTDIV;
++
++ DPRINTK("ep93xx_hw_shutdown\n");
++
++ sTouch.state = TS_STATE_STOPPED;
++ Stop_Timer2();
++
++ /*
++ * Disable the scanning engine.
++ */
++ writel(0, TSSetup);
++ writel(0, TSSetup2);
++
++ /*
++ * Clear the TSEN bit in KTDIV so that we are disabling the clock
++ * for the touchscreen.
++ */
++ uiKTDIV = readl(SYSCON_KTDIV);
++ uiKTDIV &= ~SYSCON_KTDIV_TSEN;
++ SysconSetLocked(SYSCON_KTDIV, uiKTDIV);
++
++}
++
++static irqreturn_t ep93xx_timer2_isr(int irq, void *dev_id,
++ struct pt_regs *regs)
++{
++ DPRINTK("%d", (int)sTouch.state);
++
++ switch (sTouch.state) {
++ case TS_STATE_STOPPED:
++ TS_Hardware_Scan_Mode();
++ break;
++
++ /*
++ * Get the Z1 value for pressure measurement and set up
++ * the switch register for getting the Z2 measurement.
++ */
++ case TS_STATE_Z1:
++ Set_Timer2_uSec(EP93XX_TS_ADC_DELAY_USEC);
++ sTouch.uiZ1 = ADCGetData(2, 200);
++ ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ2);
++ sTouch.state = TS_STATE_Z2;
++ break;
++
++ /*
++ * Get the Z2 value for pressure measurement and set up
++ * the switch register for getting the Y measurement.
++ */
++ case TS_STATE_Z2:
++ sTouch.uiZ2 = ADCGetData(2, 200);
++ ep93xx_ts_set_direct(sSwitchSettings.uiYSample);
++ sTouch.state = TS_STATE_Y;
++ break;
++
++ /*
++ * Get the Y value and set up the switch register for
++ * getting the X measurement.
++ */
++ case TS_STATE_Y:
++ sTouch.uiY = ADCGetData(4, 20);
++ ep93xx_ts_set_direct(sSwitchSettings.uiXSample);
++ sTouch.state = TS_STATE_X;
++ break;
++
++ /*
++ * Read the X value. This is the last of the 4 adc values
++ * we need so we continue on to process the data.
++ */
++ case TS_STATE_X:
++ Stop_Timer2();
++
++ sTouch.uiX = ADCGetData(4, 20);
++
++ writel(0xaa, TSSWLock);
++ writel(sSwitchSettings.uiDischarge, TSDirect);
++
++ sTouch.state = TS_STATE_DONE;
++
++ /* Process this set of ADC readings. */
++ ProcessPointData(dev_id);
++
++ break;
++
++ /* Shouldn't get here. But if we do, we can recover... */
++ case TS_STATE_DONE:
++ TS_Hardware_Scan_Mode();
++ break;
++ }
++
++ /* Clear the timer2 interrupt. */
++ writel(1, TIMER2CLEAR);
++ return IRQ_HANDLED;
++
++}
++
++/*---------------------------------------------------------------------
++ * ProcessPointData
++ *
++ * This routine processes the ADC data into usable point data and then
++ * puts the driver into hw or sw scanning mode before returning.
++ *
++ * We calculate inverse pressure (lower number = more pressure) then
++ * do a hystheresis with the two pressure values 'light' and 'heavy'.
++ *
++ * If we are above the light, we have pen up.
++ * If we are below the heavy we have pen down.
++ * As long as the pressure stays below the light, pen stays down.
++ * When we get above the light again, pen goes back up.
++ *
++ */
++static void ProcessPointData(struct input_dev *dev)
++{
++ int bValidPoint = 0;
++ unsigned int uiXDiff, uiYDiff, uiInvPressureDiff;
++ unsigned int uiInvPressure;
++
++ /* Calculate the current pressure. */
++ uiInvPressure = CalculateInvPressure();
++
++ DPRINTK(" X=0x%x, Y=0x%x, Z1=0x%x, Z2=0x%x, InvPressure=0x%x",
++ sTouch.uiX, sTouch.uiY, sTouch.uiZ1, sTouch.uiZ2,
++ uiInvPressure);
++
++ /*
++ * If pen pressure is so light that it is greater than the 'max' setting
++ * then we consider this to be a pen up.
++ */
++ if (uiInvPressure >= TS_LIGHT_INV_PRESSURE) {
++ DPRINTK(" -- up \n");
++ bCurrentPenDown = 0;
++/* input_report_key(dev, BTN_TOUCH, 0); */
++ input_report_abs(dev, ABS_PRESSURE, 0);
++ input_sync(dev);
++ TS_Hardware_Scan_Mode();
++ return;
++ }
++ /*
++ * Hystheresis:
++ * If the pen pressure is hard enough to be less than the 'min' OR
++ * the pen is already down and is still less than the 'max'...
++ */
++ if ((uiInvPressure < TS_HEAVY_INV_PRESSURE) ||
++ (bCurrentPenDown && (uiInvPressure < TS_LIGHT_INV_PRESSURE))) {
++ if (bCurrentPenDown) {
++ /*
++ * If pen was previously down, check the difference between
++ * the last sample and this one... if the difference between
++ * samples is too great, ignore the sample.
++ */
++ uiXDiff = abs(guiLastX - sTouch.uiX);
++ uiYDiff = abs(guiLastY - sTouch.uiY);
++ uiInvPressureDiff =
++ abs(guiLastInvPressure - uiInvPressure);
++
++ if ((uiXDiff < TS_MAX_VALID_XY_CHANGE) &&
++ (uiYDiff < TS_MAX_VALID_XY_CHANGE) &&
++ (uiInvPressureDiff < TS_MAX_VALID_PRESSURE_CHANGE))
++ {
++ DPRINTK(" -- valid(two) \n");
++ bValidPoint = 1;
++ } else {
++ DPRINTK(" -- INvalid(two) \n");
++ }
++ } else {
++ DPRINTK(" -- valid \n");
++ bValidPoint = 1;
++ }
++
++ /*
++ * If either the pen was put down or dragged make a note of it.
++ */
++ if (bValidPoint) {
++ guiLastX = sTouch.uiX;
++ guiLastY = sTouch.uiY;
++ guiLastInvPressure = uiInvPressure;
++ bCurrentPenDown = 1;
++ input_report_abs(dev, ABS_X, sTouch.uiX);
++ input_report_abs(dev, ABS_Y, sTouch.uiY);
++/* input_report_key(dev, BTN_TOUCH, 1); */
++ input_report_abs(dev, ABS_PRESSURE, 1);
++ input_sync(dev);
++ }
++
++ TS_Soft_Scan_Mode();
++ return;
++ }
++
++ DPRINTK(" -- fallout \n");
++ TS_Hardware_Scan_Mode();
++}
++
++static void ep93xx_ts_set_direct(unsigned int uiADCSwitch)
++{
++ unsigned int uiResult;
++
++ /* Set the switch settings in the direct register. */
++ writel(0xaa, TSSWLock);
++ writel(uiADCSwitch, TSDirect);
++
++ /* Read and throw away the first sample. */
++ do {
++ uiResult = readl(TSXYResult);
++ } while (!(uiResult & TSXYRESULT_SDR));
++
++}
++
++static unsigned int ADCGetData(unsigned int uiSamples, unsigned int uiMaxDiff)
++{
++ unsigned int uiResult, uiValue, uiCount, uiLowest, uiHighest, uiSum,
++ uiAve;
++
++ do {
++ /* Initialize our values. */
++ uiLowest = 0xfffffff;
++ uiHighest = 0;
++ uiSum = 0;
++
++ for (uiCount = 0; uiCount < uiSamples; uiCount++) {
++ /* Read the touch screen four more times and average. */
++ do {
++ uiResult = readl(TSXYResult);
++ } while (!(uiResult & TSXYRESULT_SDR));
++
++ uiValue =
++ (uiResult & TSXYRESULT_AD_MASK) >>
++ TSXYRESULT_AD_SHIFT;
++ uiValue =
++ ((uiValue >> 4) +
++ ((1 +
++ TSXYRESULT_X_MASK) >> 1)) & TSXYRESULT_X_MASK;
++
++ /* Add up the values. */
++ uiSum += uiValue;
++
++ /* Get the lowest and highest values. */
++ if (uiValue < uiLowest)
++ uiLowest = uiValue;
++
++ if (uiValue > uiHighest)
++ uiHighest = uiValue;
++
++ }
++
++ } while ((uiHighest - uiLowest) > uiMaxDiff);
++
++ /* Calculate the Average value. */
++ uiAve = uiSum / uiSamples;
++
++ return uiAve;
++}
++
++/**
++ * CalculateInvPressure
++ *
++ * Is the Touch Valid. Touch is not valid if the X or Y value is not
++ * in range and the pressure is not enough.
++ *
++ * Touch resistance can be measured by the following formula:
++ *
++ * Rx * X * Z2
++ * Rtouch = --------- * (-- - 1)
++ * 4096 Z1
++ *
++ * This is simplified in the ration of Rtouch to Rx. The lower the value, the
++ * higher the pressure.
++ *
++ * Z2
++ * InvPressure = X * (-- - 1)
++ * Z1
++ */
++static unsigned int CalculateInvPressure(void)
++{
++ unsigned int uiInvPressure;
++
++ /* Check to see if the point is valid. */
++ if (sTouch.uiZ1 < MIN_Z1_VALUE)
++ uiInvPressure = 0x10000;
++
++ /* Can omit the pressure calculation if you need to get rid of the division. */
++ else {
++ uiInvPressure =
++ ((sTouch.uiX * sTouch.uiZ2) / sTouch.uiZ1) - sTouch.uiX;
++ }
++
++ return uiInvPressure;
++}
++
++/**
++ * TS_Hardware_Scan_Mode
++ * Enables the ep93xx ts scanning engine so that when the pen goes down
++ * we will get an interrupt.
++ */
++static void TS_Hardware_Scan_Mode(void)
++{
++ unsigned int uiDevCfg;
++
++ DPRINTK("S\n");
++
++ /* Disable the soft scanning engine. */
++ sTouch.state = TS_STATE_STOPPED;
++ Stop_Timer2();
++
++ /*
++ * Clear the TIN (Touchscreen INactive) bit so we can go to
++ * automatic scanning mode.
++ */
++ uiDevCfg = readl(SYSCON_DEVCFG);
++ SysconSetLocked(SYSCON_DEVCFG,
++ ep93xx_SYSCON_DEVCFG(uiDevCfg & ~SYSCON_DEVCFG_TIN));
++
++ /*
++ * Enable the touch screen scanning state machine by setting
++ * the ENABLE bit.
++ */
++ writel((TSSETUP_DEFAULT | TSSETUP_ENABLE), TSSetup);
++
++ /* Set the flag to show that we are in interrupt mode. */
++ gScanningMode = TS_MODE_HARDWARE_SCAN;
++
++ /* Initialize TSSetup2 register. */
++ writel(TSSETUP2_DEFAULT, TSSetup2);
++
++}
++
++/**
++ * TS_Soft_Scan_Mode - Set the touch screen to manual polling mode.
++ */
++static void TS_Soft_Scan_Mode(void)
++{
++ unsigned int uiDevCfg;
++
++ DPRINTK("M\n");
++
++ if (gScanningMode != TS_MODE_SOFT_SCAN) {
++ /*
++ * Disable the touch screen scanning state machine by clearing
++ * the ENABLE bit.
++ */
++ writel(TSSETUP_DEFAULT, TSSetup);
++
++ /* Set the TIN bit so we can do manual touchscreen polling. */
++ uiDevCfg = readl(SYSCON_DEVCFG);
++ SysconSetLocked(SYSCON_DEVCFG,
++ ep93xx_SYSCON_DEVCFG(uiDevCfg |
++ SYSCON_DEVCFG_TIN));
++ }
++ /* Set the switch register up for the first ADC reading */
++ ep93xx_ts_set_direct(sSwitchSettings.uiSwitchZ1);
++
++ /*
++ * Initialize our software state machine to know which ADC
++ * reading to take
++ */
++ sTouch.state = TS_STATE_Z1;
++
++ /*
++ * Set the timer so after a mSec or two settling delay it will
++ * take the first ADC reading.
++ */
++ Set_Timer2_uSec(EP93XX_TS_PER_POINT_DELAY_USEC);
++
++ /* Note that we are in sw scanning mode not hw scanning mode. */
++ gScanningMode = TS_MODE_SOFT_SCAN;
++
++}
++
++static void Set_Timer2_uSec(unsigned int uiDelay_uSec)
++{
++ unsigned int uiClockTicks;
++
++ /*
++ * Stop timer 2
++ */
++ writel(0, TIMER2CONTROL);
++
++ uiClockTicks = ((uiDelay_uSec * 508) + 999) / 1000;
++ writel(uiClockTicks, TIMER2LOAD);
++ writel(uiClockTicks, TIMER2VALUE);
++
++ /*
++ * Set up Timer 2 for 508 kHz clock and periodic mode.
++ */
++ writel(0xC8, TIMER2CONTROL);
++
++}
++
++static void Stop_Timer2(void)
++{
++ writel(0, TIMER2CONTROL);
++}
++
++static struct input_dev *ep93xx_ts_dev;
++
++static int __init ep93xx_ts_init(void)
++{
++ ep93xx_ts_dev = input_allocate_device();
++ if (!ep93xx_ts_dev) {
++ printk(KERN_ERR "ep93xx_ts_dev: not enough memory for input device\n");
++ return -ENOMEM;
++ }
++
++ ep93xx_ts_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_ABS);
++ ep93xx_ts_dev->keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH);
++ ep93xx_ts_dev->keybit[LONG(BTN_RAW)] = BIT(BTN_RAW);
++
++ /* untested, I haven't got a touchscreen (yet) :( */
++ input_set_abs_params(ep93xx_ts_dev, ABS_X, 0, 4095, 0, 0);
++ input_set_abs_params(ep93xx_ts_dev, ABS_Y, 0, 4095, 0, 0);
++ input_set_abs_params(ep93xx_ts_dev, ABS_PRESSURE, 0, 1, 0, 0);
++
++ ep93xx_ts_dev->open = ep93xx_ts_open;
++ ep93xx_ts_dev->close = ep93xx_ts_close;
++ ep93xx_ts_dev->name = "Cirrus Logic EP93xx Touchscreen";
++ ep93xx_ts_dev->phys = "ep93xx_ts/input0";
++ ep93xx_ts_dev->id.bustype = BUS_HOST;
++ ep93xx_ts_dev->id.vendor = PCI_VENDOR_ID_CIRRUS;
++ ep93xx_ts_dev->id.product = 0x9300;
++
++ input_set_abs_params(ep93xx_ts_dev, ABS_X, TS_X_MIN, TS_X_MAX, 0, 0);
++ input_set_abs_params(ep93xx_ts_dev, ABS_Y, TS_Y_MIN, TS_Y_MAX, 0, 0);
++ input_register_device(ep93xx_ts_dev);
++
++ sTouch.state = TS_STATE_STOPPED;
++ gScanningMode = TS_MODE_UN_INITIALIZED;
++
++ printk(KERN_NOTICE
++ "EP93xx touchscreen driver configured for 4-wire operation\n");
++ return 0;
++}
++
++static void __exit ep93xx_ts_exit(void)
++{
++ input_unregister_device(ep93xx_ts_dev);
++}
++
++module_init(ep93xx_ts_init);
++module_exit(ep93xx_ts_exit);
++
++MODULE_DESCRIPTION("Cirrus EP93xx touchscreen driver");
++MODULE_SUPPORTED_DEVICE("touchscreen/ep93xx");
+diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
+index b9b77cf..4e0e427 100644
+--- a/drivers/mtd/maps/Kconfig
++++ b/drivers/mtd/maps/Kconfig
+@@ -137,6 +137,13 @@ config MTD_MAINSTONE
+ This provides a driver for the on-board flash of the Intel
+ 'Mainstone PXA27x evaluation board.
+
++config MTD_ADSFLASH
++ tristate "CFI Flash device mapped on ADS"
++ depends on ARM && MTD_CFI && MACH_ADSSPHERE && MTD_PARTITIONS
++ help
++ This enables access to on-board flash memory on ADS platforms that
++ have an Intel XScale PXA2xx CPU.
++
+ config MTD_OCTAGON
+ tristate "JEDEC Flash device mapped on Octagon 5066 SBC"
+ depends on X86 && MTD_JEDEC && MTD_COMPLEX_MAPPINGS
+@@ -639,5 +646,19 @@ config MTD_PLATRAM
+
+ This selection automatically selects the map_ram driver.
+
++config MTD_ZEFEERDZB
++ tristate "Map driver for DAVE Srl ZefeerDZB processor module"
++ depends on (MTD_CFI && MACH_ZEFEERDZB)
++ select MTD_PARTITIONS
++ help
++ Map driver for DAVE Srl ZefeerDZB processor module.
++
++config MTD_ZEFEERDZQ
++ tristate "Map driver for DAVE Srl ZefeerDZQ processor module"
++ depends on (MTD_CFI && MACH_ZEFEERDZQ)
++ select MTD_PARTITIONS
++ help
++ Map driver for DAVE Srl ZefeerDZQ processor module.
++
+ endmenu
+
+diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
+index 2f7e254..a821568 100644
+--- a/drivers/mtd/maps/Makefile
++++ b/drivers/mtd/maps/Makefile
+@@ -22,6 +22,7 @@ obj-$(CONFIG_MTD_AMD76XROM) += amd76xrom
+ obj-$(CONFIG_MTD_ICHXROM) += ichxrom.o
+ obj-$(CONFIG_MTD_TSUNAMI) += tsunami_flash.o
+ obj-$(CONFIG_MTD_LUBBOCK) += lubbock-flash.o
++obj-$(CONFIG_MTD_ADSFLASH) += ads-flash.o
+ obj-$(CONFIG_MTD_MAINSTONE) += mainstone-flash.o
+ obj-$(CONFIG_MTD_MBX860) += mbx860.o
+ obj-$(CONFIG_MTD_CEIVA) += ceiva.o
+@@ -72,3 +73,5 @@ obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o
+ obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o
+ obj-$(CONFIG_MTD_MTX1) += mtx-1_flash.o
+ obj-$(CONFIG_MTD_TQM834x) += tqm834x.o
++obj-$(CONFIG_MTD_ZEFEERDZB) += zefeerdzb.o
++obj-$(CONFIG_MTD_ZEFEERDZQ) += zefeerdzq.o
+diff --git a/drivers/mtd/maps/ads-flash.c b/drivers/mtd/maps/ads-flash.c
+new file mode 100644
+index 0000000..2428e9c
+--- /dev/null
++++ b/drivers/mtd/maps/ads-flash.c
+@@ -0,0 +1,221 @@
++/*
++ * Map driver for the ADS PXA Boards.
++ *
++ * 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/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++#include <asm/io.h>
++#include <asm/hardware.h>
++
++#ifdef CONFIG_MACH_ADSVIX
++#define NUM_CHIPS 1
++#else
++#define NUM_CHIPS 2
++#endif
++
++#ifdef CONFIG_PXA27x
++#define WINDOW_ADDR 0
++#elif defined(CONFIG_ARCH_EP93XX)
++#define WINDOW_ADDR 0x60000000
++#else
++#define WINDOW_ADDR 0x04000000
++#endif
++
++#define WINDOW_SIZE (NUM_CHIPS * 32*1024*1024)
++#define BLOCKSIZE (NUM_CHIPS * 0x20000)
++#define BANKWIDTH (NUM_CHIPS * 2)
++
++static void pxa_map_inval_cache(struct map_info *map, unsigned long from, ssize_t len)
++{
++ consistent_sync((char *)map->cached + from, len, DMA_FROM_DEVICE);
++}
++
++static struct map_info pxa_map = {
++ .name = "pxa",
++ .size = WINDOW_SIZE,
++ .phys = WINDOW_ADDR,
++ .virt = 0,
++ .cached = (void *)NULL,
++ .bankwidth = BANKWIDTH,
++ .inval_cache = pxa_map_inval_cache,
++};
++
++static struct mtd_partition ads_partitions[] = {
++ {
++ name: "boot",
++ size: BLOCKSIZE,
++ offset: 0,
++ }, {
++ name: "bootvars",
++ size: BLOCKSIZE,
++ offset: MTDPART_OFS_APPEND,
++ }, {
++ name: "zImage",
++ size: 0x00180000,
++ offset: MTDPART_OFS_APPEND,
++ }, {
++ name: "ramdisk.gz",
++ size: 0x00500000,
++ offset: MTDPART_OFS_APPEND,
++ }, {
++ name: "flashfs1",
++ size: MTDPART_SIZ_FULL,
++ offset: MTDPART_OFS_APPEND
++ }
++};
++
++unsigned char ads_flash_serial_id[32+2] = {0};
++
++static struct mtd_info *mymtd = NULL;
++static struct mtd_partition *parsed_parts = NULL;
++static int num_parts = 0;
++static const char *probes[] = {
++#ifdef CONFIG_MTD_CMDLINE_PARTS
++ "cmdlinepart",
++#endif
++#ifdef CONFIG_MTD_REDBOOT_PARTS
++ "RedBoot",
++#endif
++ NULL };
++
++// This implementation supports 1 or 2 chips.
++static void ads_get_flash_serial_id(int chips)
++{
++ map_word val;
++ unsigned int addr = 0x81 << chips;
++ unsigned int mask = chips == 1 ? 0xffff : 0xffffffff;
++ unsigned int tmp[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
++ int i;
++
++ /* read array mode */
++ // *(__u32 *)pxa_map.virt = 0x00FF00FF;
++ // *(__u16 *)pxa_map.virt = 0x00ff;
++ val.x[0] = 0x00ff00ff & mask;
++ map_write(&pxa_map, val, 0);
++
++ /* read id mode */
++ // *(__u32 *)pxa_map.virt = 0x00900090;
++ // *(__u16 *)pxa_map.virt = 0x0090;
++ val.x[0] = 0x00900090 & mask;
++ map_write(&pxa_map, val, 0);
++
++ for (i=0; i<8; i++) {
++ // tmp[i] = 0x0000ffff & *(__u32 *)(pxa_map.virt + addr);
++ // tmp[i] = *(__u16 *)(pxa_map.virt + addr);
++ val = map_read(&pxa_map, addr);
++ tmp[i] = val.x[0] & 0xffff;
++ addr += BANKWIDTH;
++ }
++
++ /* back to read array mode */
++ // *(__u32 *)pxa_map.virt = 0x00FF00FF;
++ // *(__u16 *)pxa_map.virt = 0x00ff;
++ val.x[0] = 0x00ff00ff & mask;
++ map_write(&pxa_map, val, 0);
++
++ sprintf(ads_flash_serial_id, "%04x%04x%04x%04x.%04x%04x%04x%04x",
++ tmp[7], tmp[6], tmp[5], tmp[4], tmp[3], tmp[2], tmp[1], tmp[0]);
++
++}
++
++static int __init init_pxa_flash(void)
++{
++ struct mtd_partition *parts;
++ char *part_type;
++ int rtn;
++
++ printk(KERN_NOTICE "Probing PXA flash at physical address 0x%08x\n", WINDOW_ADDR);
++ pxa_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
++ if (!pxa_map.virt) {
++ printk(KERN_ERR "Failed to ioremap flash\n");
++ return -EIO;
++ }
++
++ pxa_map.cached = __ioremap(WINDOW_ADDR, WINDOW_SIZE, L_PTE_CACHEABLE, 1);
++ if (!pxa_map.cached)
++ printk(KERN_WARNING "Failed to ioremap cached flash\n");
++
++ simple_map_init(&pxa_map);
++
++ mymtd = do_map_probe("cfi_probe", &pxa_map);
++ if (!mymtd) {
++ if (pxa_map.cached)
++ iounmap((void *)pxa_map.cached);
++ if (pxa_map.virt)
++ iounmap((void *)pxa_map.virt);
++ return -ENXIO;
++ }
++
++#ifdef CONFIG_MTD_CMDLINE_PARTS
++ pxa_map.name = "pxa";
++ rtn = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0);
++ if (rtn <= 0) {
++ pxa_map.name = "sa1100";
++ rtn = parse_mtd_partitions(mymtd, probes, &parsed_parts, 0);
++ }
++ if (rtn > 0) {
++ num_parts = rtn;
++ parts = parsed_parts;
++ part_type = "command line";
++ goto add_parts;
++ }
++#endif
++ num_parts = ARRAY_SIZE(ads_partitions);
++ parts = ads_partitions;
++ part_type = "static";
++add_parts:
++ if (num_parts) {
++ printk(KERN_NOTICE "Using %s partition definition\n", part_type);
++ add_mtd_partitions(mymtd, parts, num_parts);
++#if 0
++ if (mymtd->unlock) {
++ int i;
++ for (i = 0; i < num_parts; i++) {
++ // unlock partition
++ mymtd->unlock(mymtd, parts[num_parts - 1].offset,
++ parts[num_parts - 1].size);
++ }
++ }
++#endif
++ }
++ else {
++ add_mtd_device(mymtd);
++ }
++
++ ads_get_flash_serial_id(NUM_CHIPS);
++
++ return 0;
++}
++
++static void __exit cleanup_pxa_flash(void)
++{
++ if (mymtd) {
++ if (num_parts)
++ del_mtd_partitions(mymtd);
++ else
++ del_mtd_device(mymtd);
++ map_destroy(mymtd);
++ if (parsed_parts)
++ kfree(parsed_parts);
++ }
++ if (pxa_map.cached)
++ iounmap((void *)pxa_map.cached);
++ if (pxa_map.virt)
++ iounmap((void *)pxa_map.virt);
++}
++
++module_init(init_pxa_flash);
++module_exit(cleanup_pxa_flash);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/mtd/maps/zefeerdzb.c b/drivers/mtd/maps/zefeerdzb.c
+new file mode 100644
+index 0000000..bb47bc6
+--- /dev/null
++++ b/drivers/mtd/maps/zefeerdzb.c
+@@ -0,0 +1,134 @@
++/*
++ * $Id: zefeerdzb.c,v 1.8 2004/07/12 21:59:44 dwmw2 Exp $
++ *
++ * drivers/mtd/maps/zefeerdzb.c
++ *
++ * FLASH map for the DAVE Srl ZefeerDZB processor module.
++ *
++ *
++ * 2004 (c) DAVE Srl. This file is licensed under
++ * the terms of the GNU General Public License version 2. This program
++ * is licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++
++#if 0
++/* Support for ZELK <= 0.9.5 */
++#define WINDOW_ADDR 0x60000000
++#else
++#define WINDOW_ADDR 0x00000000
++#endif
++#define WINDOW_SIZE 0x00400000
++
++/* 128 kB U-Boot */
++#define ZEFEERDZB_PART0_OF 0
++#define ZEFEERDZB_PART0_SZ 0x20000
++/* 128 kB U-Boot env #1 */
++#define ZEFEERDZB_PART1_OF ZEFEERDZB_PART0_OF + ZEFEERDZB_PART0_SZ
++#define ZEFEERDZB_PART1_SZ 0x20000
++/* 128 kB U-Boot env #2 */
++#define ZEFEERDZB_PART2_OF ZEFEERDZB_PART1_OF + ZEFEERDZB_PART1_SZ
++#define ZEFEERDZB_PART2_SZ 0x20000
++/* Linux kernel */
++#define ZEFEERDZB_PART3_OF ZEFEERDZB_PART2_OF + ZEFEERDZB_PART2_SZ
++#define ZEFEERDZB_PART3_SZ (0x200000 - ZEFEERDZB_PART2_SZ - ZEFEERDZB_PART1_SZ - ZEFEERDZB_PART0_SZ)
++/* spare */
++#define ZEFEERDZB_PART4_OF ZEFEERDZB_PART3_OF + ZEFEERDZB_PART3_SZ
++#define ZEFEERDZB_PART4_SZ (0x400000 - ZEFEERDZB_PART3_SZ - ZEFEERDZB_PART2_SZ - ZEFEERDZB_PART1_SZ - ZEFEERDZB_PART0_SZ)
++
++static struct mtd_partition zefeerdzb_flash_partitions[] = {
++ {
++ .name = "U-Boot",
++ .offset = ZEFEERDZB_PART0_OF,
++ .size = ZEFEERDZB_PART0_SZ,
++ .mask_flags = MTD_WRITEABLE /* force read-only */
++ },
++ {
++ .name = "U-Boot environment #1",
++ .offset = ZEFEERDZB_PART1_OF,
++ .size = ZEFEERDZB_PART1_SZ,
++ },
++ {
++ .name = "U-Boot environment #2",
++ .offset = ZEFEERDZB_PART2_OF,
++ .size = ZEFEERDZB_PART2_SZ,
++ },
++ {
++ .name = "Linux kernel",
++ .offset = ZEFEERDZB_PART3_OF,
++ .size = ZEFEERDZB_PART3_SZ,
++ },
++ {
++ .name = "spare 1",
++ .offset = ZEFEERDZB_PART4_OF,
++ .size = ZEFEERDZB_PART4_SZ,
++ }
++};
++
++struct map_info zefeerdzb_flash_map = {
++ .name = "DAVE Srl ZefeerDZB",
++ .size = WINDOW_SIZE,
++ .bankwidth = 2,
++ .phys = WINDOW_ADDR,
++};
++
++#define NUM_ZEFEERDZB_FLASH_PARTITIONS \
++ (sizeof(zefeerdzb_flash_partitions)/sizeof(zefeerdzb_flash_partitions[0]))
++
++static struct mtd_info *zefeerdzb_mtd;
++
++int __init init_zefeerdzb_flash(void)
++{
++ printk(KERN_NOTICE "zefeerdzb: flash mapping: %x at %x\n",
++ WINDOW_SIZE, WINDOW_ADDR);
++
++ zefeerdzb_flash_map.virt =
++ (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
++
++ if (!zefeerdzb_flash_map.virt) {
++ printk("init_zefeerdzb_flash: failed to ioremap\n");
++ return -EIO;
++ }
++ simple_map_init(&zefeerdzb_flash_map);
++
++ zefeerdzb_mtd = do_map_probe("cfi_probe", &zefeerdzb_flash_map);
++
++ if (zefeerdzb_mtd) {
++ zefeerdzb_mtd->owner = THIS_MODULE;
++ return add_mtd_partitions(zefeerdzb_mtd,
++ zefeerdzb_flash_partitions,
++ NUM_ZEFEERDZB_FLASH_PARTITIONS);
++ }
++
++ return -ENXIO;
++}
++
++static void __exit cleanup_zefeerdzb_flash(void)
++{
++ if (zefeerdzb_mtd) {
++ del_mtd_partitions(zefeerdzb_mtd);
++ /* moved iounmap after map_destroy - armin */
++ map_destroy(zefeerdzb_mtd);
++ iounmap((void *)zefeerdzb_flash_map.virt);
++ }
++}
++
++module_init(init_zefeerdzb_flash);
++module_exit(cleanup_zefeerdzb_flash);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("DAVE Srl <info@dave-tech.it>");
++MODULE_DESCRIPTION
++ ("MTD map driver for the DAVE Srl ZefeerDZB processor module");
+diff --git a/drivers/mtd/maps/zefeerdzq.c b/drivers/mtd/maps/zefeerdzq.c
+new file mode 100644
+index 0000000..dc0e402
+--- /dev/null
++++ b/drivers/mtd/maps/zefeerdzq.c
+@@ -0,0 +1,142 @@
++/*
++ * $Id: zefeerdzq.c,v 1.8 2004/07/12 21:59:44 dwmw2 Exp $
++ *
++ * drivers/mtd/maps/zefeerdzq.c
++ *
++ * FLASH map for the DAVE Srl ZefeerDZQ processor module.
++ *
++ *
++ * 2004 (c) DAVE Srl. This file is licensed under
++ * the terms of the GNU General Public License version 2. This program
++ * is licensed "as is" without any warranty of any kind, whether express
++ * or implied.
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/kernel.h>
++#include <linux/init.h>
++
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/map.h>
++#include <linux/mtd/partitions.h>
++
++#include <asm/io.h>
++
++#if 0
++/* Support for ZELK <= 0.9.5 */
++#define WINDOW_ADDR 0x60000000
++#else
++#define WINDOW_ADDR 0x00000000
++#endif
++#define WINDOW_SIZE 0x01000000
++
++/* 128 kB U-Boot */
++#define ZEFEERDZQ_PART0_OF 0
++#define ZEFEERDZQ_PART0_SZ 0x20000
++/* 128 kB U-Boot env #1 */
++#define ZEFEERDZQ_PART1_OF ZEFEERDZQ_PART0_OF + ZEFEERDZQ_PART0_SZ
++#define ZEFEERDZQ_PART1_SZ 0x20000
++/* 128 kB U-Boot env #2 */
++#define ZEFEERDZQ_PART2_OF ZEFEERDZQ_PART1_OF + ZEFEERDZQ_PART1_SZ
++#define ZEFEERDZQ_PART2_SZ 0x20000
++/* Linux kernel */
++#define ZEFEERDZQ_PART3_OF ZEFEERDZQ_PART2_OF + ZEFEERDZQ_PART2_SZ
++#define ZEFEERDZQ_PART3_SZ (0x200000 - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ)
++/* ramdisk */
++#define ZEFEERDZQ_PART4_OF ZEFEERDZQ_PART3_OF + ZEFEERDZQ_PART3_SZ
++#define ZEFEERDZQ_PART4_SZ (0x400000 - ZEFEERDZQ_PART3_SZ - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ)
++/* spare */
++#define ZEFEERDZQ_PART5_OF ZEFEERDZQ_PART4_OF + ZEFEERDZQ_PART4_SZ
++#define ZEFEERDZQ_PART5_SZ (WINDOW_SIZE - ZEFEERDZQ_PART4_SZ - ZEFEERDZQ_PART3_SZ - ZEFEERDZQ_PART2_SZ - ZEFEERDZQ_PART1_SZ - ZEFEERDZQ_PART0_SZ)
++
++static struct mtd_partition zefeerdzq_flash_partitions[] = {
++ {
++ .name = "U-Boot",
++ .offset = ZEFEERDZQ_PART0_OF,
++ .size = ZEFEERDZQ_PART0_SZ,
++ .mask_flags = MTD_WRITEABLE /* force read-only */
++ },
++ {
++ .name = "U-Boot environment #1",
++ .offset = ZEFEERDZQ_PART1_OF,
++ .size = ZEFEERDZQ_PART1_SZ,
++ },
++ {
++ .name = "U-Boot environment #2",
++ .offset = ZEFEERDZQ_PART2_OF,
++ .size = ZEFEERDZQ_PART2_SZ,
++ },
++ {
++ .name = "Linux kernel",
++ .offset = ZEFEERDZQ_PART3_OF,
++ .size = ZEFEERDZQ_PART3_SZ,
++ },
++ {
++ .name = "spare 1",
++ .offset = ZEFEERDZQ_PART4_OF,
++ .size = ZEFEERDZQ_PART4_SZ,
++ },
++ {
++ .name = "spare 2",
++ .offset = ZEFEERDZQ_PART5_OF,
++ .size = ZEFEERDZQ_PART5_SZ,
++ }
++};
++
++struct map_info zefeerdzq_flash_map = {
++ .name = "DAVE Srl ZefeerDZQ",
++ .size = WINDOW_SIZE,
++ .bankwidth = 2,
++ .phys = WINDOW_ADDR,
++};
++
++#define NUM_ZEFEERDZQ_FLASH_PARTITIONS \
++ (sizeof(zefeerdzq_flash_partitions)/sizeof(zefeerdzq_flash_partitions[0]))
++
++static struct mtd_info *zefeerdzq_mtd;
++
++int __init init_zefeerdzq_flash(void)
++{
++ printk(KERN_NOTICE "zefeerdzq: flash mapping: %x at %x\n",
++ WINDOW_SIZE, WINDOW_ADDR);
++
++ zefeerdzq_flash_map.virt =
++ (unsigned long)ioremap(WINDOW_ADDR, WINDOW_SIZE);
++
++ if (!zefeerdzq_flash_map.virt) {
++ printk("init_zefeerdzq_flash: failed to ioremap\n");
++ return -EIO;
++ }
++ simple_map_init(&zefeerdzq_flash_map);
++
++ zefeerdzq_mtd = do_map_probe("cfi_probe", &zefeerdzq_flash_map);
++
++ if (zefeerdzq_mtd) {
++ zefeerdzq_mtd->owner = THIS_MODULE;
++ return add_mtd_partitions(zefeerdzq_mtd,
++ zefeerdzq_flash_partitions,
++ NUM_ZEFEERDZQ_FLASH_PARTITIONS);
++ }
++
++ return -ENXIO;
++}
++
++static void __exit cleanup_zefeerdzq_flash(void)
++{
++ if (zefeerdzq_mtd) {
++ del_mtd_partitions(zefeerdzq_mtd);
++ /* moved iounmap after map_destroy - armin */
++ map_destroy(zefeerdzq_mtd);
++ iounmap((void *)zefeerdzq_flash_map.virt);
++ }
++}
++
++module_init(init_zefeerdzq_flash);
++module_exit(cleanup_zefeerdzq_flash);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("DAVE Srl <info@dave-tech.it>");
++MODULE_DESCRIPTION
++ ("MTD map driver for the DAVE Srl ZefeerDZQ processor module");
+diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
+index 1fc4c13..8e79d32 100644
+--- a/drivers/mtd/nand/Kconfig
++++ b/drivers/mtd/nand/Kconfig
+@@ -109,6 +109,12 @@ config MTD_NAND_S3C2410_HWECC
+ currently not be able to switch to software, as there is no
+ implementation for ECC method used by the S3C2410
+
++config MTD_NAND_ZEFEEREVB
++ tristate "NAND Flash device on ZefeerEVB (L/H) board"
++ depends on (MACH_ZEFEERDZA || MACH_ZEFEERDZB || MACH_ZEFEERDZG || MACH_ZEFEERDZN || MACH_ZEFEERDZQ) && MTD_NAND
++ help
++ This enables the NAND flash driver on the ZefeerEVB Board (L or H version).
++
+ config MTD_NAND_DISKONCHIP
+ tristate "DiskOnChip 2000, Millennium and Millennium Plus (NAND reimplementation) (EXPERIMENTAL)"
+ depends on MTD_NAND && EXPERIMENTAL
+diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
+index 4174202..bee7760 100644
+--- a/drivers/mtd/nand/Makefile
++++ b/drivers/mtd/nand/Makefile
+@@ -18,5 +18,6 @@ obj-$(CONFIG_MTD_NAND_H1900) += h1910.o
+ obj-$(CONFIG_MTD_NAND_RTC_FROM4) += rtc_from4.o
+ obj-$(CONFIG_MTD_NAND_SHARPSL) += sharpsl.o
+ obj-$(CONFIG_MTD_NAND_NANDSIM) += nandsim.o
++obj-$(CONFIG_MTD_NAND_ZEFEEREVB) += zefeerevb.o
+
+ nand-objs = nand_base.o nand_bbt.o
+diff --git a/drivers/mtd/nand/zefeerevb.c b/drivers/mtd/nand/zefeerevb.c
+new file mode 100644
+index 0000000..b67e958
+--- /dev/null
++++ b/drivers/mtd/nand/zefeerevb.c
+@@ -0,0 +1,280 @@
++/*
++ * drivers/mtd/nand/zefeerevb.c
++ *
++ * Copyright (C) 2004 DAVE Srl (info@dave-tech.it)
++ *
++ *
++ *
++ * $Id: zefeerevb.c,v 1.4 2004/10/05 13:50:20 gleixner Exp $
++ *
++ * 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.
++ *
++ * Overview:
++ * This is a device driver for the NAND flash devices found on the
++ * ZefeerEVB board (Samsung K9F5608U0B 32MB).
++ */
++
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/module.h>
++#include <linux/mtd/mtd.h>
++#include <linux/mtd/nand.h>
++#include <linux/mtd/partitions.h>
++#include <asm/arch/regmap.h>
++#include <asm/arch/zefeerevb.h>
++#include <asm/io.h>
++
++#define USE_READY_BUSY_PIN
++/* see datasheets (tR) */
++#define NAND_BIG_DELAY_US 25
++#define NAND_SMALL_DELAY_US 10
++
++/* handy sizes */
++#define SZ_4M 0x00400000
++#define NAND_SMALL_SIZE 0x02000000
++#define NAND_EVB_MTD_NAME "zefeerevb-nand"
++
++/* Macros to perform I/O operations */
++#define MACRO_NAND_DISABLE_CE(nandptr) do \
++{ \
++ writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_nCE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_ENABLE_CE(nandptr) do \
++{ \
++ writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_nCE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_CTL_CLRALE(nandptr) do \
++{ \
++ writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_ALE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_CTL_SETALE(nandptr) do \
++{ \
++ writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_ALE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_CTL_CLRCLE(nandptr) do \
++{ \
++ writel(readl((volatile unsigned*)GPIO_PADR) & ~NAND_EVB_CLE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_CTL_SETCLE(nandptr) do \
++{ \
++ writel(readl((volatile unsigned*)GPIO_PADR) | NAND_EVB_CLE_GPIO_PIN, (volatile unsigned*)GPIO_PADR); \
++} while(0)
++
++#define MACRO_NAND_WAIT_READY(nand) \
++while ( !(readl((volatile unsigned*)GPIO_PADR) & NAND_EVB_RB_GPIO_PIN); )
++
++/*
++ * MTD structure for ZefeerEVB board
++ */
++static struct mtd_info *zefeerevb_mtd = NULL;
++
++/*
++ * Module stuff
++ */
++static int zefeerevb_fio_pbase = ZEFEEREVB_NAND_PADDR;
++
++#ifdef MODULE
++MODULE_PARM(zefeerevb_fio_pbase, "i");
++__setup("zefeerevb_fio_pbase=", zefeerevb_fio_pbase);
++#endif
++
++#ifdef CONFIG_MTD_PARTITIONS
++/*
++ * Define static partitions for flash devices
++ */
++static struct mtd_partition partition_info_evb[] = {
++ {name:"ZefeerEVB Nand Flash",
++ offset:0,
++ size:32 * 1024 * 1024}
++};
++
++#define NUM_PARTITIONS 1
++
++extern int parse_cmdline_partitions(struct mtd_info *master,
++ struct mtd_partition **pparts,
++ const char *mtd_id);
++#endif
++
++static void zefeerevb_hwcontrol(struct mtd_info *mtdinfo, int cmd)
++{
++ switch (cmd) {
++
++ case NAND_CTL_SETCLE:
++ MACRO_NAND_CTL_SETCLE((unsigned long)0);
++ break;
++ case NAND_CTL_CLRCLE:
++ MACRO_NAND_CTL_CLRCLE((unsigned long)0);
++ break;
++ case NAND_CTL_SETALE:
++ MACRO_NAND_CTL_SETALE((unsigned long)0);
++ break;
++ case NAND_CTL_CLRALE:
++ MACRO_NAND_CTL_CLRALE((unsigned long)0);
++ break;
++ case NAND_CTL_SETNCE:
++ MACRO_NAND_ENABLE_CE((unsigned long)0);
++ break;
++ case NAND_CTL_CLRNCE:
++ MACRO_NAND_DISABLE_CE((unsigned long)0);
++ break;
++ }
++}
++
++#ifdef USE_READY_BUSY_PIN
++/*
++ * read device ready pin
++ */
++static int zefeerevb_device_ready(struct mtd_info *minfo)
++{
++ return (readl((volatile unsigned *)GPIO_PADR) &
++ NAND_EVB_RB_GPIO_PIN);
++}
++#endif
++
++#ifdef CONFIG_MTD_PARTITIONS
++const char *part_probes_evb[] = { "cmdlinepart", NULL };
++#endif
++
++/*
++ * Main initialization routine
++ */
++static int __init zefeerevb_init(void)
++{
++ struct nand_chip *this;
++ const char *part_type = 0;
++ int mtd_parts_nb = 0;
++ struct mtd_partition *mtd_parts = 0;
++ void __iomem *zefeerevb_fio_base;
++ u32 tmp;
++
++ /* Init I/O pins */
++ MACRO_NAND_DISABLE_CE(0);
++ MACRO_NAND_CTL_CLRALE(0);
++ MACRO_NAND_CTL_CLRCLE(0);
++
++ tmp = (u32) readl(GPIO_PADDR);
++ tmp |=
++ (NAND_EVB_nCE_GPIO_PIN | NAND_EVB_CLE_GPIO_PIN |
++ NAND_EVB_ALE_GPIO_PIN);
++#ifdef USE_READY_BUSY_PIN
++ tmp &= ~NAND_EVB_RB_GPIO_PIN;
++#endif
++ writel(tmp, GPIO_PADDR);
++
++ /* Init I/O pins */
++ MACRO_NAND_DISABLE_CE(0);
++ MACRO_NAND_CTL_CLRALE(0);
++ MACRO_NAND_CTL_CLRCLE(0);
++
++ /* Set up chip select */
++ writel((0 << 30) | (0 << 28) | (0 << 27) | (0 << 26) | (0 << 11) |
++ (1 << 10) | (4 << 5) | (6 << 0), SMCBCR2);
++
++ /* Allocate memory for MTD device structure and private data */
++ zefeerevb_mtd = kmalloc(sizeof(struct mtd_info) +
++ sizeof(struct nand_chip), GFP_KERNEL);
++ if (!zefeerevb_mtd) {
++ printk
++ ("Unable to allocate ZefeerEVB NAND MTD device structure.\n");
++ return -ENOMEM;
++ }
++
++ /* map physical address */
++ zefeerevb_fio_base =
++ (void __iomem *)ioremap(zefeerevb_fio_pbase, SZ_4M);
++ if (!zefeerevb_fio_base) {
++ printk("ioremap ZefeerEVB NAND flash failed\n");
++ kfree(zefeerevb_mtd);
++ return -EIO;
++ }
++
++ /* Get pointer to private data */
++ this = (struct nand_chip *)(&zefeerevb_mtd[1]);
++
++ /* Initialize structures */
++ memset((char *)zefeerevb_mtd, 0, sizeof(struct mtd_info));
++ memset((char *)this, 0, sizeof(struct nand_chip));
++
++ /* Link the private data with the MTD structure */
++ zefeerevb_mtd->priv = this;
++
++ /* insert callbacks */
++ this->IO_ADDR_R = (void __iomem *)zefeerevb_fio_base;
++ this->IO_ADDR_W = (void __iomem *)zefeerevb_fio_base;
++ this->hwcontrol = zefeerevb_hwcontrol;
++#ifdef USE_READY_BUSY_PIN
++ this->dev_ready = zefeerevb_device_ready;
++#endif
++ this->chip_delay = NAND_SMALL_DELAY_US;
++
++ /* ECC mode */
++ this->eccmode = NAND_ECC_SOFT;
++
++ /* Scan to find existence of the device */
++ if (nand_scan(zefeerevb_mtd, 1)) {
++ iounmap((void *)zefeerevb_fio_base);
++ kfree(zefeerevb_mtd);
++ return -ENXIO;
++ }
++#ifdef CONFIG_MTD_PARTITIONS
++ zefeerevb_mtd->name = NAND_EVB_MTD_NAME;
++ mtd_parts_nb =
++ parse_mtd_partitions(zefeerevb_mtd, part_probes_evb, &mtd_parts, 0);
++ if (mtd_parts_nb > 0)
++ part_type = "command line";
++ else
++ mtd_parts_nb = 0;
++#endif
++ if (mtd_parts_nb == 0) {
++#ifdef CONFIG_MTD_PARTITIONS
++ mtd_parts = partition_info_evb;
++ mtd_parts_nb = NUM_PARTITIONS;
++#endif
++ part_type = "static";
++ }
++
++ /* Register the partitions */
++ printk(KERN_NOTICE "Using %s partition definition\n", part_type);
++ add_mtd_partitions(zefeerevb_mtd, mtd_parts, mtd_parts_nb);
++
++ /* Return happy */
++ return 0;
++}
++
++module_init(zefeerevb_init);
++
++#ifdef MODULE
++/*
++ * Clean up routine
++ */
++static void __exit zefeerevb_cleanup(void)
++{
++ struct nand_chip *this;
++
++ /* Release resources, unregister device(s) */
++ nand_release(zefeer_mtd);
++ nand_release(zefeerevb_mtd);
++
++ /* Release iomaps */
++ this = (struct nand_chip *)&zefeer_mtd[1];
++ iounmap((void *)this->zefeer_fio_base;
++ this = (struct nand_chip *)&zefeerevb_mtd[1];
++ iounmap((void *)this->zefeerevb_fio_base;
++ /* Free the MTD device structure */
++ kfree(zefeer_mtd);
++ kfree(zefeerevb_mtd);
++ }
++
++ module_exit(zefeerevb_cleanup);
++#endif
++ MODULE_LICENSE("GPL");
++ MODULE_AUTHOR("DAVE Srl <support-zefeer@dave-tech.it>");
++ MODULE_DESCRIPTION
++ ("MTD map driver for DAVE Srl ZefeerEVB (L/H) board");
+diff --git a/drivers/net/arm/Kconfig b/drivers/net/arm/Kconfig
+index 470364d..12afe1d 100644
+--- a/drivers/net/arm/Kconfig
++++ b/drivers/net/arm/Kconfig
+@@ -44,3 +44,13 @@ config ARM_ETHER00
+ will generate a suitable hw address based on the board serial
+ number (MTD support is required for this). Otherwise you will
+ need to set a suitable hw address using ifconfig.
++
++config EP93XX_ETHERNET
++ tristate "EP93xx Ethernet support"
++ depends on NET_ETHERNET && ARM && ARCH_EP93XX
++ select CRC32
++ select MII
++ help
++ This is a driver for the ethernet hardware included in EP93xx CPUs.
++ Say Y if you are building a kernel for EP93xx based devices.
++
+diff --git a/drivers/net/arm/Makefile b/drivers/net/arm/Makefile
+index b0d7068..c1539da 100644
+--- a/drivers/net/arm/Makefile
++++ b/drivers/net/arm/Makefile
+@@ -8,3 +8,4 @@ obj-$(CONFIG_ARM_ETHER00) += ether00.o
+ obj-$(CONFIG_ARM_ETHERH) += etherh.o
+ obj-$(CONFIG_ARM_ETHER3) += ether3.o
+ obj-$(CONFIG_ARM_ETHER1) += ether1.o
++obj-$(CONFIG_EP93XX_ETHERNET) += ep93xx_eth.o
+diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c
+new file mode 100644
+index 0000000..e314549
+--- /dev/null
++++ b/drivers/net/arm/ep93xx_eth.c
+@@ -0,0 +1,1412 @@
++/*
++ * ep93xx_eth.c
++ * Ethernet Device Driver for Cirrus Logic EP93xx.
++ *
++ * Copyright (C) 2003 by Cirrus Logic www.cirrus.com
++ * This software may be used and distributed according to the terms
++ * of the GNU Public License.
++ *
++ * This driver was written based on skeleton.c by Donald Becker and
++ * smc9194.c by Erik Stahlman.
++ *
++ * Getting a MAC address:
++ *
++ * Former versions of this driver got their MAC from I2C EEPROM or even used
++ * hardcoded ones. Unfortunately I had to remove the board dependant I2C stuff,
++ * and use a random generated MAC instead of the hardcoded one. Good news is
++ * the there is support for setting the MAC from userspace now. (see below)
++ *
++ * first consider some potential problems if you use this random generated MAC:
++ *
++ * you can no longer count on it to be really unique
++ * identifying a particular board over network will be difficult
++ * DHCP servers can no longer use the MAC for assigning static IPs
++ * DHCP servers with long leasetimes quickly run out of leases
++ * ...
++ *
++ * So how can you set a valid MAC from userspace then?
++ *
++ * Let's say you've just bought your OUI from IEEE and it's "aa:bb:cc"
++ * Now you'd like to assign the MAC for your EP93xx board with serial #5
++ * MAC = OUI<<24 + serial number = aa:bb:cc:00:00:05
++ *
++ * ifconfig eth0 hw ether aa:bb:cc:00:00:05 # first set the MAC
++ * ifconfig eth0 192.168.1.1 netmask 255.255.255.0 up # then set the IP
++ *
++ * Apart from hardcoding this lines in your startup scripts you could also use
++ * some userspace utility to read (and set) the MAC from eeprom, flash, ...
++ *
++ * History:
++ * 07/19/01 0.1 Sungwook Kim initial release
++ * 10/16/01 0.2 Sungwook Kim add workaround for ignorance of Tx request
++ * while sending frame
++ * add some error stuations handling
++ *
++ * 03/25/03 Melody Lee Modified for EP93xx
++ *
++ * 2004/2005 Michael Burian porting to linux-2.6
++ * 2005-10-12 Michael Burian fix problems when setting MAC with ifconfig
++ * 2005-10-30 Michael Burian cleanups, ethtool support
++ */
++
++/* TODO:
++ * 1. try if it's possible to use skbuff directly for RX/TX (avoid memcpy)
++ * 2. use kzalloc instead of kmalloc+memset
++ */
++
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/types.h>
++#include <linux/fcntl.h>
++#include <linux/interrupt.h>
++#include <linux/ioport.h>
++#include <linux/in.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++#include <linux/errno.h>
++#include <linux/init.h>
++#include <linux/netdevice.h>
++#include <linux/etherdevice.h>
++#include <linux/skbuff.h>
++#include <linux/dma-mapping.h>
++#include <linux/mii.h>
++#include <linux/crc32.h>
++#include <linux/random.h>
++#include <linux/ethtool.h>
++
++#include <asm/system.h>
++#include <asm/bitops.h>
++#include <asm/io.h>
++#include <asm/dma.h>
++#include <asm/irq.h>
++#include <asm/arch/hardware.h>
++
++#include "ep93xx_eth.h"
++
++#define DRV_NAME "ep93xx_eth"
++#define DRV_VERSION "2.8"
++#define DRV_DATE "2005-11-08"
++
++static const char *version = DRV_NAME ": version " DRV_VERSION " " DRV_DATE \
++ " Cirrus Logic\n";
++
++/* total number of device instance, 0 means the 1st instance. */
++static int num_of_instance;
++static struct net_device * ep93xx_etherdev;
++
++/*
++ * A List of default device port configuration for auto probing.
++ * At this time, the CPU has only one Ethernet device,
++ * but better to support multiple device configuration.
++ * Keep in mind that the array must end in zero.
++ */
++
++/* We get the MAC_BASE from include/asm-arm/arch-ep93xx/regmap.h */
++static struct {
++ unsigned int base_addr; /* base address, (0:end mark) */
++ int irq; /* IRQ number, (0:auto detect) */
++} port_list[] __initdata = {
++ {
++ MAC_BASE, 39}, {
++ 0 /* end mark */ , 0}
++};
++
++/*
++ * Some definitions belong to the operation of this driver.
++ * You should understand how it affect to driver before any modification.
++ */
++
++/* Interrupt Sources in Use */
++#define DEF_INT_SRC (IntEn_TxSQIE|IntEn_RxEOFIE|IntEn_RxEOBIE|IntEn_RxHDRIE)
++
++/*
++ * Length of Device Queue in number of entries
++ * (must be less than or equal to 255)
++ */
++
++/* length of Rx Descriptor Queue (4 or bigger) Must be power of 2. */
++#define LQRXD 64
++#define LQRXS LQRXD /* length of Rx Status Queue */
++
++/* length of Tx Descriptor Queue (4 or bigger) Must be power of 2. */
++#define LQTXD 8
++#define LQTXS LQTXD /* length of Tx Status Queue */
++
++/* Tx Queue fill-up level control */
++#define LVL_TXSTOP LQTXD - 2 /* level to ask the stack to stop Tx */
++#define LVL_TXRESUME 2 /* level to ask the stack to resume Tx */
++
++/* Rx Buffer length in byte */
++#define LRXB (1518+2+16) /* length of Rx buf, must be 4-byte aligned */
++#define LTXB LRXB
++
++#define EP93XX_DEF_MSG (NETIF_MSG_DRV | \
++ NETIF_MSG_PROBE | \
++ NETIF_MSG_LINK | \
++ NETIF_MSG_RX_ERR | \
++ NETIF_MSG_TX_ERR | \
++ NETIF_MSG_HW)
++
++#define DBG(lvl,msg,args...) do { printk(lvl"%s:%d: %s(): " msg, __FILE__, \
++ __LINE__, __FUNCTION__, ## args); } while (0)
++
++/*
++ * Custom Data Structures
++ */
++
++/*
++ * the information about the buffer passed to device.
++ * there are matching bufdsc informations
++ * for each Tx/Rx Descriptor Queue entry to trace
++ * the buffer within those queues.
++ */
++struct bufdsc {
++ /* virtual address representing the buffer passed to device */
++ void *vaddr;
++ /* free routine */
++ int (*free_rout) (void *buf);
++};
++
++/* device private information */
++struct ep93xx_priv {
++ /* static device information */
++ int id; /* device instance ID */
++ /* pointers to various queues (virtual address) */
++ struct rx_dsc *rdq; /* Rx Descriptor Queue */
++ struct rx_sts *rsq; /* Rx Status Queue */
++ struct tx_dsc *tdq; /* Tx Descriptor Queue */
++ struct tx_sts *tsq; /* Tx Status Queue */
++ unsigned char *rxbuf; /* base of Rx Buffer pool */
++ unsigned char *txbuf; /* base of Tx Buffer pool */
++ struct bufdsc *rxbd; /* Rx Buffers info */
++ struct bufdsc *txbd; /* Tx Buffers info */
++ /* physical addresses of the same queues */
++ dma_addr_t p_qbase; /* base */
++ dma_addr_t p_rdq; /* Rx Descriptor Queue */
++ dma_addr_t p_rsq; /* Rx Status Queue */
++ dma_addr_t p_tdq; /* Tx Descriptor Queue */
++ dma_addr_t p_tsq; /* Tx Status Queue */
++ dma_addr_t p_rxbuf; /* Rx Buffer pool */
++ dma_addr_t p_txbuf; /* Tx Buffer pool */
++ /* MII Bus ID of Ethernet PHY */
++ struct mii_if_info mii;
++ /* lock for mii when using ioctls */
++ spinlock_t mii_lock;
++ /* dynamic information, subject to clear when device open */
++ struct net_device_stats stats; /* statistic data */
++ /* next processing index of device queues */
++ int idx_rdq;
++ int idx_rsq;
++ int idx_tdqhead;
++ int idx_tdqtail;
++ int idx_tsq;
++ void __iomem *base_addr; /* base address */
++ u32 msg_enable;
++ int regs_len;
++};
++
++/*
++ * Internal Routines
++ */
++
++static inline unsigned int next_index(unsigned int idx_cur, unsigned int len)
++{
++ return (idx_cur + 1) % len; /* next array index */
++}
++
++static inline u32 _rdl(struct net_device *dev, u32 reg)
++{
++ return readl(((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
++}
++
++static inline void _wrl(struct net_device *dev, u32 val, u32 reg)
++{
++ writel(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
++}
++
++static inline void _wrw(struct net_device *dev, u16 val, u32 reg)
++{
++ writew(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
++}
++
++static inline void _wrb(struct net_device *dev, u8 val, u32 reg)
++{
++ writeb(val, ((struct ep93xx_priv *)(netdev_priv(dev)))->base_addr + reg);
++}
++
++/**
++ * wait_on_reg()
++ */
++static int wait_on_reg(struct net_device *dev, int reg, unsigned long mask, unsigned long expect)
++{
++ int i, dt;
++
++ for (i = 0; i < 10000; i++) {
++ dt = _rdl(dev, reg);
++ dt = (dt ^ expect) & mask;
++ if (0 == dt)
++ break;
++ }
++ return dt;
++}
++
++/**
++ * mdio_write()
++ */
++static void mdio_write(struct net_device *dev, int idPhy, int reg, int dt)
++{
++ wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy);
++ _wrl(dev, dt, REG_MIIData);
++ _wrl(dev, MIICmd_OP_WR | ((idPhy & 0x1f) << 5) | ((reg & 0x1f) << 0), REG_MIICmd);
++}
++
++/**
++ * mdio_read()
++ */
++static int mdio_read(struct net_device *dev, int idPhy, int reg)
++{
++ int dt;
++
++ wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy);
++ _wrl(dev, MIICmd_OP_RD | ((idPhy & 0x1f) << 5) | ((reg & 0x1f) << 0), REG_MIICmd);
++
++ wait_on_reg(dev, REG_MIISts, MIISts_Busy, ~MIISts_Busy);
++ dt = _rdl(dev, REG_MIIData);
++
++ return dt & 0xffff;
++}
++
++/**
++ * phy_init()
++ */
++static void phy_init(struct net_device *dev)
++{
++
++ u32 oldval;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ oldval = _rdl(dev, REG_SelfCTL);
++
++ /* Set MDC clock to be divided by 8 and disable PreambleSuppress bit */
++ _wrl(dev, 0x0e00, REG_SelfCTL);
++
++ if (mii_link_ok(&(priv->mii)))
++ mii_check_media(&(priv->mii), netif_msg_link(priv), 1);
++
++ /* restore the old value */
++ _wrl(dev, oldval, REG_SelfCTL);
++}
++
++/**
++ * devQue_start()
++ *
++ * make descriptor queues active
++ * allocate queue entries if needed
++ * and set device registers up to make it operational
++ * assume device has been initialized
++ */
++static int devQue_start(struct net_device *dev)
++{
++ int err;
++ int i;
++ void *buf;
++ u32 phy_addr;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ /* turn off device bus mastering */
++ _wrl(dev, BMCtl_RxDis | BMCtl_TxDis | _rdl(dev, REG_BMCtl), REG_BMCtl);
++ err = wait_on_reg(dev, REG_BMSts, BMSts_TxAct, ~BMSts_TxAct);
++ err |= wait_on_reg(dev, REG_BMSts, BMSts_RxAct, ~BMSts_RxAct);
++ if (err && netif_msg_hw(priv))
++ DBG(KERN_ERR, "%s: BM does not stop\n", dev->name);
++
++ /* Tx Status Queue */
++ memset(priv->tsq, 0, sizeof(priv->tsq[0]) * LQTXS);
++ priv->idx_tsq = 0;
++ _wrl(dev, priv->p_tsq, REG_TxSBA);
++ _wrl(dev, priv->p_tsq, REG_TxSCA);
++ _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSBL);
++ _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSCL);
++
++ /* Tx Descriptor Queue */
++ memset(priv->tdq, 0, sizeof(priv->tdq[0]) * LQTXD);
++ priv->idx_tdqhead = priv->idx_tdqtail = 0;
++ _wrl(dev, priv->p_tdq, REG_TxDBA);
++ _wrl(dev, priv->p_tdq, REG_TxDCA);
++ _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDBL);
++ _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDCL);
++
++ /* Rx Status Queue */
++ memset(priv->rsq, 0, sizeof(priv->rsq[0]) * LQRXS);
++ priv->idx_rsq = 0;
++ _wrl(dev, priv->p_rsq, REG_RxSBA);
++ _wrl(dev, priv->p_rsq, REG_RxSCA);
++ _wrw(dev, sizeof(priv->rsq[0]) * LQRXS, REG_RxSBL);
++ _wrw(dev, sizeof(priv->rsq[0]) * LQRXS, REG_RxSCL);
++
++ /* Rx Descriptor Queue */
++ memset(priv->rdq, 0, sizeof(priv->rdq[0]) * LQRXD);
++ phy_addr = priv->p_rxbuf;
++ for (i = 0; i < LQRXD; i++) {
++ priv->rdq[i].bi = i; /* index */
++ priv->rdq[i].ba = phy_addr; /* physical address */
++ priv->rdq[i].bl = LRXB; /* length */
++ phy_addr += LRXB;
++ }
++ priv->idx_rdq = 0;
++ _wrl(dev, priv->p_rdq, REG_RxDBA);
++ _wrl(dev, priv->p_rdq, REG_RxDCA);
++ _wrw(dev, sizeof(priv->rdq[0]) * LQRXD, REG_RxDBL);
++ _wrw(dev, sizeof(priv->rdq[0]) * LQRXD, REG_RxDCL);
++
++ /* init Rx Buffer Descriptors */
++ buf = priv->rxbuf;
++ for (i = 0; i < LQRXD; i++) {
++ priv->rxbd[i].vaddr = buf;
++ priv->rxbd[i].free_rout = NULL;
++ buf += LRXB;
++ }
++
++ /* init Tx Buffer Descriptors */
++ memset(priv->txbd, 0x0, sizeof(*priv->txbd) * LQTXD);
++
++ buf = priv->txbuf;
++ for (i = 0; i < LQTXD; i++) {
++ priv->txbd[i].vaddr = buf;
++ priv->txbd[i].free_rout = NULL;
++ buf += LTXB;
++ }
++
++ /* turn on device bus mastering */
++ _wrl(dev, BMCtl_TxEn | BMCtl_RxEn | _rdl(dev, REG_BMCtl), REG_BMCtl);
++ err = wait_on_reg(dev, REG_BMSts, BMSts_TxAct | BMSts_TxAct, BMSts_TxAct | BMSts_TxAct);
++ if (err && netif_msg_hw(priv))
++ DBG(KERN_ERR, "%s: BM does not start\n", dev->name);
++
++ /* Enqueue whole entries; this must be done after BM activation */
++ _wrl(dev, LQRXS, REG_RxSEQ); /* Rx Status Queue */
++ _wrl(dev, LQRXD, REG_RxDEQ); /* Rx Desc. queue */
++
++ return 0;
++}
++
++/**
++ * devQue_init()
++ * init device descriptor queues at system level
++ * device access is not recommended at this point
++ *
++ */
++static int devQue_init(struct net_device *dev)
++{
++ void *buf;
++ void *tmp;
++ int size, size2;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ /* verify device Tx/Rx Descriptor/Status Queue data size */
++ if (8 != sizeof(struct rx_dsc)) {
++ if (netif_msg_probe(priv))
++ DBG(KERN_ERR, "sizeof rx_dsc != 8 bytes!\n");
++ return -ENOMEM;
++ } else if (8 != sizeof(struct rx_sts)) {
++ if (netif_msg_probe(priv))
++ DBG(KERN_ERR, "sizeof rx_sts != 8 bytes!\n");
++ return -ENOMEM;
++ } else if (8 != sizeof(struct tx_dsc)) {
++ if (netif_msg_probe(priv))
++ DBG(KERN_ERR, "sizeof tx_dsc != 8 bytes!\n");
++ return -ENOMEM;
++ } else if (4 != sizeof(struct tx_sts)) {
++ if (netif_msg_probe(priv))
++ DBG(KERN_ERR, "sizeof tx_sts != 4 bytes!\n");
++ return -ENOMEM;
++ }
++
++ /*
++ allocate kernel memory for whole queues
++ best if non-cached memory block due to DMA access by the device
++ if CPU doesn't have bus snooping
++ */
++ size = sizeof(struct rx_dsc) * (LQRXD + 1) +
++ sizeof(struct rx_sts) * (LQRXS + 1) +
++ sizeof(struct tx_dsc) * (LQTXD + 1) +
++ sizeof(struct tx_sts) * (LQTXS + 1) + sizeof(unsigned long) * 4;
++
++ buf = tmp = dma_alloc_coherent(NULL, size, &priv->p_qbase, GFP_KERNEL | GFP_DMA);
++ if (!buf) {
++ if (netif_msg_probe(priv))
++ DBG(KERN_ERR, "no memory for queue\n");
++ return -ENOMEM;
++ }
++
++ /*
++ * assign memory to each queue
++ */
++ priv->rdq = buf;
++ buf = buf + sizeof(struct rx_dsc) * (LQRXD + 1);
++ priv->rsq = buf;
++ buf = buf + sizeof(struct rx_sts) * (LQRXS + 1);
++ priv->tdq = buf;
++ buf = buf + sizeof(struct tx_dsc) * (LQTXD + 1);
++ priv->tsq = buf;
++ buf = buf + sizeof(struct tx_sts) * (LQTXS + 1);
++
++ /*
++ * store physical address of each queue
++ */
++ priv->p_rdq = priv->p_qbase;
++ priv->p_rsq = priv->p_rdq + ((u32) priv->rsq - (u32) priv->rdq);
++ priv->p_tdq = priv->p_rdq + ((u32) priv->tdq - (u32) priv->rdq);
++ priv->p_tsq = priv->p_rdq + ((u32) priv->tsq - (u32) priv->rdq);
++
++ /*
++ * init queue entries
++ */
++ memset(priv->rdq, 0, sizeof(struct rx_dsc) * LQRXD);
++ memset(priv->rsq, 0, sizeof(struct rx_sts) * LQRXS);
++ memset(priv->tdq, 0, sizeof(struct tx_dsc) * LQTXD);
++ memset(priv->tsq, 0, sizeof(struct tx_sts) * LQTXS);
++
++ /* Allocate Rx Buffer
++ (We might need to copy from Rx buf to skbuff in whatever case,
++ because device bus master requires 32bit aligned Rx buffer address
++ but Linux network stack requires odd 16bit aligned Rx buf address) */
++ priv->rxbuf = dma_alloc_coherent(NULL, LRXB * LQRXD, &priv->p_rxbuf, GFP_KERNEL | GFP_DMA);
++
++ if (!priv->rxbuf) {
++ priv->rxbuf = NULL;
++ if (netif_msg_probe(priv))
++ DBG(KERN_ERR, "no memory for RxBuf\n");
++ goto err_free_qbase_1;
++ }
++
++ /* Allocate Tx Buffer */
++ priv->txbuf = dma_alloc_coherent(NULL, LTXB * LQTXD, &priv->p_txbuf, GFP_KERNEL | GFP_DMA);
++
++ if (!priv->txbuf) {
++ priv->txbuf = NULL;
++ if (netif_msg_probe(priv))
++ DBG(KERN_ERR, "no memory for TxBuf\n");
++ goto err_free_rxbuf_2;
++ }
++
++ /*
++ * allocate kernel memory for buffer descriptors
++ */
++ size2 = sizeof(struct bufdsc) * (LQRXD + LQTXD);
++ buf = kmalloc(size2, GFP_KERNEL);
++ if (!buf) {
++ if (netif_msg_probe(priv))
++ DBG(KERN_ERR, "no memory for buf desc\n");
++ goto err_free_txbuf_3;
++ }
++ memset(buf, 0x0, size2); /* clear with 0 */
++ priv->rxbd = buf;
++ priv->txbd = buf + sizeof(struct bufdsc) * LQRXD;
++
++ return 0;
++
++err_free_txbuf_3:
++ dma_free_coherent(NULL, LTXB * LQTXD, priv->txbuf, priv->p_txbuf);
++err_free_rxbuf_2:
++ dma_free_coherent(NULL, LRXB * LQRXD, priv->rxbuf, priv->p_rxbuf);
++err_free_qbase_1:
++ dma_free_coherent(NULL, size, tmp, priv->p_qbase);
++ return -ENOMEM;
++}
++
++/**
++ * devQue_cleanup()
++ * Release queue, Tx buffers and Rx buffers memory
++ * Only call after unregister_netdev
++ */
++static void devQue_cleanup(struct net_device *dev)
++{
++ int size;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ /* descriptor queues size */
++ size = sizeof(struct rx_dsc) * (LQRXD + 1) +
++ sizeof(struct rx_sts) * (LQRXS + 1) +
++ sizeof(struct tx_dsc) * (LQTXD + 1) +
++ sizeof(struct tx_sts) * (LQTXS + 1) + sizeof(unsigned long) * 4;
++
++ dma_free_coherent(NULL, size, priv->rdq, priv->p_qbase);
++ dma_free_coherent(NULL, LTXB * LQTXD, priv->txbuf, priv->p_txbuf);
++ dma_free_coherent(NULL, LRXB * LQRXD, priv->rxbuf, priv->p_rxbuf);
++ kfree(priv->rxbd);
++
++}
++
++/**
++ * set_multicast_tbl()
++ */
++static void set_multicast_tbl(struct net_device *dev, u8 *buf)
++{
++ int i;
++ unsigned char position;
++ struct dev_mc_list *cur_addr;
++
++ memset(buf, 0x00, 8);
++
++ cur_addr = dev->mc_list;
++ for (i = 0; i < dev->mc_count; i++, cur_addr = cur_addr->next) {
++
++ if (!cur_addr)
++ break;
++ if (!(*cur_addr->dmi_addr & 1))
++ continue; /* make sure multicast addr */
++ position = ether_crc_le(6, cur_addr->dmi_addr) >> 26;
++ buf[position >> 3] |= 1 << (position & 0x07);
++ }
++}
++
++/**
++ * ind_addr_wr()
++ */
++static int ind_addr_wr(struct net_device *dev, int afp, char *buf)
++{
++ u32 rxctl;
++ int i, len;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ afp &= 0x07;
++ if (4 == afp || 5 == afp) {
++ if (netif_msg_hw(priv))
++ DBG(KERN_ERR, "invalid afp value\n");
++ return -1;
++ }
++ len = (AFP_AFP_HASH == afp) ? 8 : 6;
++
++ rxctl = _rdl(dev, REG_RxCTL); /* turn Rx off */
++ _wrl(dev, ~RxCTL_SRxON & rxctl, REG_RxCTL);
++ _wrl(dev, afp, REG_AFP); /* load new address pattern */
++ for (i = 0; i < len; i++)
++ _wrb(dev, buf[i], REG_IndAD + i);
++ _wrl(dev, rxctl, REG_RxCTL); /* turn Rx back */
++
++ return 0;
++}
++
++/**
++ * rx_ctl()
++ */
++static int rx_ctl(struct net_device *dev, int sw)
++{
++ unsigned long tmp = _rdl(dev, REG_RxCTL);
++
++ /*
++ * Workaround for MAC lost 60-byte-long frames:
++ * must enable Runt_CRC_Accept bit
++ */
++ if (sw)
++ _wrl(dev, tmp | RxCTL_SRxON | RxCTL_RCRCA, REG_RxCTL);
++ else
++ _wrl(dev, tmp & ~RxCTL_SRxON, REG_RxCTL);
++
++ return 0;
++}
++
++/**
++ * chk_tx_lvl()
++ */
++static void chk_tx_lvl(struct net_device *dev)
++{
++ int filled;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ /* check Tx Descriptor Queue fill-up level */
++ filled = priv->idx_tdqhead - priv->idx_tdqtail;
++ if (filled < 0)
++ filled += LQTXD;
++
++ if (filled <= (LVL_TXRESUME + 1))
++ netif_wake_queue(dev);
++}
++
++/**
++ * cleanup_tx()
++ */
++static void cleanup_tx(struct net_device *dev)
++{
++ struct tx_sts *txsts;
++ int idxsts, bi;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ /*
++ * process Tx Status Queue (no need to limit processing of TxStatus
++ * Queue because each queue entry consist of 1 dword)
++ */
++ while (priv->tsq[priv->idx_tsq].flags & TXSTS_TXFP) {
++ idxsts = priv->idx_tsq;
++ priv->idx_tsq = next_index(priv->idx_tsq, LQTXS);
++ txsts = &priv->tsq[idxsts];
++ if (!(txsts->flags & TXSTS_TXFP)) { /* empty? */
++ if (netif_msg_tx_err(priv))
++ DBG(KERN_ERR, "QueTxSts is empty\n");
++ return;
++ }
++ txsts->flags &= ~TXSTS_TXFP; /* mark processed */
++
++ bi = txsts->bi & TXSTS_BI; /* buffer index */
++
++ /* statistics collection */
++ if (txsts->flags & TXSTS_TXWE) { /* Sent without error */
++ priv->stats.tx_packets++;
++ priv->stats.tx_bytes += ((struct tx_dsc *)(priv->txbd[bi].vaddr))->bl_af & TXDSC_BL;
++ } else { /* Tx failed due to error */
++ if (netif_msg_tx_err(priv))
++ DBG(KERN_ERR, "Tx failed QueTxSts");
++ priv->stats.tx_errors++;
++ if (txsts->flags & TXSTS_LCRS)
++ priv->stats.tx_carrier_errors++;
++ if (txsts->flags & TXSTS_TXU)
++ priv->stats.tx_fifo_errors++;
++ if (txsts->flags & TXSTS_ECOLL)
++ priv->stats.collisions++;
++ }
++
++ /* free Tx buffer */
++ if (priv->txbd[bi].free_rout) {
++ (*priv->txbd[bi].free_rout)(priv->txbd[bi].vaddr);
++ priv->txbd[bi].free_rout = NULL;
++ }
++
++ /* ahead Tx Descriptor Queue tail index */
++ priv->idx_tdqtail = next_index(priv->idx_tdqtail, LQTXD);
++ }
++}
++
++/**
++ * restart_tx()
++ */
++static int restart_tx(struct net_device *dev)
++{
++ int i;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ /* disable int */
++
++ /* turn off master INT control */
++ _wrl(dev, _rdl(dev, REG_GIntMsk) & ~GIntMsk_IntEn, REG_GIntMsk);
++
++ /* stop Tx and disable Tx DMA */
++ _wrl(dev, _rdl(dev, REG_TxCTL) & ~TxCTL_STxON, REG_TxCTL);
++ _wrl(dev, _rdl(dev, REG_BMCtl) | BMCtl_TxDis, REG_BMCtl);
++
++ /* reset Tx DMA */
++ _wrl(dev, BMCtl_TxChR | _rdl(dev, REG_BMCtl), REG_BMCtl);
++
++ /* release Tx buffers */
++ for (i = 0; i < LQTXD; i++) {
++ if (priv->txbd[i].free_rout) {
++ priv->txbd[i].free_rout(priv->txbd[i].vaddr);
++ priv->txbd[i].free_rout = NULL;
++ }
++ priv->stats.tx_dropped++;
++ }
++
++ /* init Tx Queues and flush cache */
++ memset(priv->tsq, 0, sizeof(priv->tsq[0]) * LQTXS);
++
++ /* init variables */
++ priv->idx_tsq = priv->idx_tdqhead = priv->idx_tdqtail = 0;
++
++ /* init registers */
++ wait_on_reg(dev, REG_BMSts, BMCtl_TxChR, ~BMCtl_TxChR);
++ _wrl(dev, priv->p_tsq, REG_TxSBA);
++ _wrl(dev, priv->p_tsq, REG_TxSCA);
++ _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSBL);
++ _wrw(dev, sizeof(priv->tsq[0]) * LQTXS, REG_TxSCL);
++ _wrl(dev, priv->p_tdq, REG_TxDBA);
++ _wrl(dev, priv->p_tdq, REG_TxDCA);
++ _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDBL);
++ _wrw(dev, sizeof(priv->tdq[0]) * LQTXD, REG_TxDCL);
++
++ /* start Tx and enable Tx DMA */
++ _wrl(dev, _rdl(dev, REG_TxCTL) | TxCTL_STxON, REG_TxCTL);
++ _wrl(dev, _rdl(dev, REG_BMCtl) | BMCtl_TxEn, REG_BMCtl);
++
++ /* enable int again */
++ _wrl(dev, _rdl(dev, REG_GIntMsk) | GIntMsk_IntEn, REG_GIntMsk);
++
++ return 0;
++}
++
++/**
++ * reset()
++ */
++static void reset(struct net_device *dev)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ /* soft reset command */
++ _wrb(dev, SelfCTL_RESET, REG_SelfCTL);
++ if (wait_on_reg(dev, REG_SelfCTL, SelfCTL_RESET, ~SelfCTL_RESET))
++ if (netif_msg_drv(priv))
++ DBG(KERN_WARNING, "Soft Reset does not self-clear\n");
++}
++
++/**
++ * eth_shutdown()- closes down the Ethernet module
++ *
++ * Make sure to:
++ * 1. disable all interrupt mask
++ * 2. disable Rx
++ * 3. disable Tx
++ *
++ * 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 int eth_shutdown(struct net_device *dev)
++{
++ reset(dev);
++ return 0;
++}
++
++/**
++ * eth_init() - Reset and initialize the device.
++ *
++ * Device should be initialized enough to function in polling mode.
++ * Tx and Rx must be disabled and no INT generation.
++ */
++static int eth_init(struct net_device *dev)
++{
++ /* reset device */
++ reset(dev);
++
++ /* init PHY */
++ phy_init(dev);
++
++ /* init MAC */
++
++ /*i Set MDC clock to be divided by 8 and enable PreambleSuppress bit */
++ _wrl(dev, 0x0f00, REG_SelfCTL);
++ /* mask Interrupt */
++ _wrl(dev, 0x00, REG_GIntMsk);
++ /* no Rx on at this point */
++ _wrl(dev, RxCTL_BA | RxCTL_IA0, REG_RxCTL);
++ _wrl(dev, 0x00, REG_TxCTL);
++ _wrl(dev, 0x00, REG_GT);
++ _wrl(dev, 0x00, REG_BMCtl);
++ /* Buffer Threshold */
++ _wrl(dev, (0x80 << 16) | (0x40 << 0), REG_RxBTH);
++ _wrl(dev, (0x80 << 16) | (0x40 << 0), REG_TxBTH);
++ /* Status Threshold */
++ _wrl(dev, (4 << 16) | (2 << 0), REG_RxSTH);
++ _wrl(dev, (4 << 16) | (2 << 0), REG_TxSTH);
++ /* Descriptor Threshold */
++ _wrl(dev, (4 << 16) | (2 << 0), REG_RxDTH);
++ _wrl(dev, (4 << 16) | (2 << 0), REG_TxDTH);
++ /* Max Frame Length & Tx Start Threshold */
++ _wrl(dev, ((1518 + 1) << 16) | (944 << 0), REG_MaxFL);
++
++ _rdl(dev, REG_TxCollCnt); /* clear Tx Collision Count */
++ _rdl(dev, REG_RxMissCnt); /* clear Rx Miss Counter */
++ _rdl(dev, REG_RxRntCnt); /* clear Rx Runt Counter */
++
++ /* clear Pending INT */
++ _rdl(dev, REG_IntStsC);
++ /* Tx on */
++ _wrl(dev, TxCTL_STxON | _rdl(dev, REG_TxCTL), REG_TxCTL);
++
++ /* Set MAC address */
++ ind_addr_wr(dev, AFP_AFP_IA0, &dev->dev_addr[0]);
++
++ /* init queue */
++ devQue_start(dev);
++
++ return 0;
++}
++
++/**
++ * rx_isr() - Receive Interrupt Service Routine
++ */
++static void rx_isr(struct net_device *dev)
++{
++ struct rx_sts *rxsts;
++ /* index of Rx Status Queue Head from device (next put point) */
++ int idx_rsqhead;
++ int idxsts;
++ int cnt_sts_processed, cnt_desc_processed;
++ char *dest;
++ struct sk_buff *skb;
++ int len;
++ unsigned int dt;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ /* get Current Rx Status Queue pointer */
++ dt = _rdl(dev, REG_RxSCA);
++
++ /* convert to array index */
++ idx_rsqhead = (dt - priv->p_rsq) / sizeof(priv->rsq[0]);
++ if (!(0 <= idx_rsqhead && idx_rsqhead < LQRXS)) {
++ if (netif_msg_rx_err(priv))
++ DBG(KERN_ERR, " invalid REG_RxSCA\n");
++ return;
++ }
++
++ /* process Rx (limit to idx_rsqhead due to cache) */
++ cnt_sts_processed = cnt_desc_processed = 0;
++ while (idx_rsqhead != priv->idx_rsq) {
++ idxsts = priv->idx_rsq;
++ priv->idx_rsq = next_index(priv->idx_rsq, LQRXS);
++ rxsts = &priv->rsq[idxsts];
++ if (!(rxsts->w1 & RXSTS_RFP)) { /* empty? */
++ if (netif_msg_rx_err(priv))
++ DBG(KERN_ERR, "QueRxSts empty\n");
++ return;
++ }
++ rxsts->w1 &= ~RXSTS_RFP; /* mark processed */
++
++ cnt_sts_processed++;
++
++ if (!(rxsts->w1 & RXSTS_EOB)) /* buffer has no data */
++ continue;
++
++ if ((rxsts->bi & RXSTS_BI) != priv->idx_rdq) {
++ if (netif_msg_rx_err(priv))
++ DBG(KERN_ERR, "unmatching idx_rdq\n");
++ continue;
++ }
++ priv->idx_rdq = next_index(priv->idx_rdq, LQRXD);
++ cnt_desc_processed++;
++
++ /* received a frame with error */
++ if (!((rxsts->w1 & RXSTS_EOF) && (rxsts->w1 & RXSTS_RWE))) {
++ if (netif_msg_rx_err(priv))
++ DBG(KERN_WARNING, "Rx error RxSts\n");
++ priv->stats.rx_errors++;
++ if (rxsts->w1 & RXSTS_OE)
++ priv->stats.rx_fifo_errors++;
++ if (rxsts->w1 & RXSTS_FE)
++ priv->stats.rx_frame_errors++;
++ if ((rxsts->w1 & RXSTS_RUNT) || (rxsts->w1 & RXSTS_EDATA))
++ priv->stats.rx_length_errors++;
++ if (rxsts->w1 & RXSTS_CRCE)
++ priv->stats.rx_crc_errors++;
++ continue;
++ }
++
++ len = rxsts->fl;
++
++ /* alloc buffer for protocal stack */
++ skb = dev_alloc_skb(len + 5);
++ if (NULL == skb) {
++ if (netif_msg_rx_err(priv))
++ DBG(KERN_ERR, "Low Memory, Rx dropped\n");
++ priv->stats.rx_dropped++;
++ continue;
++ }
++
++ /* odd 16 bit alignment to make protocal stack happy */
++ skb_reserve(skb, 2);
++ skb->dev = dev;
++ dest = skb_put(skb, len);
++ memcpy(dest, priv->rxbd[(rxsts->bi & RXSTS_BI)].vaddr, len);
++ skb->protocol = eth_type_trans(skb, dev);
++ /* pass Rx packet to system */
++ netif_rx(skb);
++ dev->last_rx = jiffies;
++ priv->stats.rx_packets++;
++ priv->stats.rx_bytes += len;
++ if (RXSTS_AM == (rxsts->w1 & RXSTS_AM))
++ priv->stats.multicast++;
++ }
++
++ /* enqueue */
++ _wrl(dev, cnt_sts_processed, REG_RxSEQ);
++ _wrl(dev, cnt_desc_processed, REG_RxDEQ);
++}
++
++/**
++ * tx_isr() - Transmit Interrupt Service Routine
++ */
++static int tx_isr(struct net_device *dev)
++{
++ cleanup_tx(dev);
++ chk_tx_lvl(dev); /* resume Tx if it was stopped */
++ return 0;
++}
++
++/**
++ * ep93xx_isr()
++ */
++static irqreturn_t ep93xx_isr(int irq, void *dev_id, struct pt_regs *pRegs)
++{
++ struct net_device *dev = dev_id;
++ int lpCnt;
++ u32 intS;
++
++ lpCnt = 0;
++ do {
++ /* get INT status and then clear */
++ intS = _rdl(dev, REG_IntStsC);
++
++ if (!intS)
++ break; /* no INT */
++ if (IntSts_RxSQ & intS)
++ rx_isr(dev); /* Rx INT */
++ if (IntSts_TxSQ & intS)
++ tx_isr(dev); /* Tx INT */
++ } while (lpCnt++ < 64); /* limit loop to serve other interrupts too */
++ return IRQ_HANDLED;
++}
++
++/* Exposed Driver Routines to the Outside World */
++
++/**
++ * ep93xx_get_stats()
++ */
++static struct net_device_stats *ep93xx_get_stats(struct net_device *dev)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ return &priv->stats;
++}
++
++/**
++ * ep93xx_set_multicast_list()
++ */
++static void ep93xx_set_multicast_list(struct net_device *dev)
++{
++ u8 tbl[8 + 1];
++
++ if (IFF_PROMISC & dev->flags) {
++ _wrl(dev, RxCTL_PA | _rdl(dev, REG_RxCTL), REG_RxCTL);
++
++ } else if (IFF_ALLMULTI & dev->flags) { /* receive all multicast addr */
++ _wrl(dev, RxCTL_MA | (~RxCTL_PA & _rdl(dev, REG_RxCTL)), REG_RxCTL);
++ memset(tbl, 0xff, 8);
++ ind_addr_wr(dev, AFP_AFP_HASH, &tbl[0]);
++
++ } else if (dev->mc_count) { /* set H/W multicasting filter */
++ _wrl(dev, RxCTL_MA | (~RxCTL_PA & _rdl(dev, REG_RxCTL)), REG_RxCTL);
++ set_multicast_tbl(dev, &tbl[0]);
++ ind_addr_wr(dev, AFP_AFP_HASH, &tbl[0]);
++
++ } else { /* no multicasting */
++ _wrl(dev, ~(RxCTL_PA | RxCTL_MA) & _rdl(dev, REG_RxCTL), REG_RxCTL);
++ }
++}
++
++/**
++ * ep93xx_tx_timeout()
++ */
++static void ep93xx_tx_timeout(struct net_device *dev)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ /* If we get here, some higher level has decided we are broken.
++ There should really be a "kick me" function call instead. */
++ if (netif_msg_tx_err(priv))
++ DBG(KERN_WARNING, "transmit timed out\n");
++
++ phy_init(dev);
++
++ /* kick Tx engine */
++ restart_tx(dev);
++
++ /* ask the Network Stack to resume Tx if there is room available */
++ chk_tx_lvl(dev);
++}
++
++/**
++ * ep93xx_start_xmit()
++ */
++static int ep93xx_start_xmit(struct sk_buff *skb, struct net_device *dev)
++{
++/* @swk check H/W defect of Tx Underrun Error caused by certain frame length */
++ struct tx_dsc *txdsc;
++ int idx_tdqhd;
++ int filled;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ idx_tdqhd = priv->idx_tdqhead;
++ txdsc = &priv->tdq[idx_tdqhd];
++
++ /* check Tx Descriptor Queue fill-up level */
++ filled = idx_tdqhd - priv->idx_tdqtail;
++ if (filled < 0)
++ filled += LQTXD;
++ filled += 1;
++
++ /* check Queue level */
++ if (LVL_TXSTOP <= filled) {
++ netif_stop_queue(dev); /* no more Tx allowed */
++ if (netif_msg_tx_err(priv))
++ DBG(KERN_INFO, "%s: Tx STOP requested\n", dev->name);
++ if (LVL_TXSTOP < filled) {
++ /* this situation can not be happen */
++ if (netif_msg_tx_err(priv))
++ DBG(KERN_ERR, "%s: Tx Request while stopped\n", dev->name);
++ return NETDEV_TX_BUSY;
++ }
++ }
++
++ /* fill up Tx Descriptor Queue entry */
++ if (skb->len < ETH_ZLEN) {
++ txdsc->bl_af = ETH_ZLEN & TXDSC_BL; /* also clears AF! */
++ skb = skb_padto(skb, ETH_ZLEN);
++ if (skb == NULL)
++ return NETDEV_TX_OK;
++ } else {
++ txdsc->bl_af = skb->len & TXDSC_BL; /* also clears AF! */
++ }
++ txdsc->ba = priv->p_txbuf + (idx_tdqhd * LTXB);
++ txdsc->bi_eof = (idx_tdqhd & TXDSC_BI) | TXDSC_EOF;
++
++ dev->trans_start = jiffies;
++
++ /* copy data to Tx buffer */
++ memcpy(priv->txbd[idx_tdqhd].vaddr, skb->data, skb->len);
++ priv->txbd[idx_tdqhd].free_rout = NULL;
++
++ /* Free the data buffer passed by upper layer */
++ dev_kfree_skb_any(skb);
++
++ /* ahead Tx Desc Queue */
++ priv->idx_tdqhead = next_index(priv->idx_tdqhead, LQTXD);
++ wmb();
++
++ /* Enqueue a Tx Descriptor to the device */
++ _wrl(dev, 1, REG_TxDEQ);
++
++ if (netif_msg_tx_queued(priv))
++ DBG(KERN_DEBUG, "%s: Tx packet queued\n", dev->name);
++
++ return NETDEV_TX_OK;
++}
++
++/**
++ * ep93xx_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 ep93xx_close(struct net_device *dev)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ free_irq(dev->irq, dev);
++
++ netif_stop_queue(dev);
++ eth_shutdown(dev);
++
++ if (netif_msg_ifdown(priv))
++ DBG(KERN_INFO, "%s: ep93xx_close()\n", dev->name);
++
++ return 0;
++}
++
++/**
++ * ep93xx_open() - Open and Initialize the board
++ *
++ * Set up everything, reset the card, etc ..
++ */
++static int ep93xx_open(struct net_device *dev)
++{
++ int status;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ /* clear dynamic device info */
++ memset(&priv->stats, 0, sizeof(priv->stats));
++ priv->idx_rdq = 0;
++ priv->idx_rsq = 0;
++ priv->idx_tdqhead = 0;
++ priv->idx_tdqtail = 0;
++ priv->idx_tsq = 0;
++
++ /* reset/init device */
++ status = eth_init(dev);
++ if (status != 0) {
++ return -EAGAIN;
++ }
++
++ /* turn on INT, turn on Rx */
++ status = request_irq(dev->irq, &ep93xx_isr, 0, DRV_NAME, dev);
++ if (status) {
++ if (netif_msg_ifup(priv))
++ DBG(KERN_ERR, "%s: unable to get IRQ\n", dev->name);
++ return status;
++ }
++
++ /* Enable interrupt driven operation. Also turn on Rx but no Tx. */
++ /* setup Interrupt sources */
++ _wrl(dev, DEF_INT_SRC, REG_IntEn);
++ /* turn on INT */
++ _wrl(dev, GIntMsk_IntEn, REG_GIntMsk);
++ /* turn on Rx */
++ rx_ctl(dev, 1);
++
++ /* link to upper layer */
++ netif_start_queue(dev);
++
++ if (netif_msg_ifup(priv))
++ DBG(KERN_INFO, "%s: irq=%d\n", dev->name, dev->irq);
++
++ return 0;
++}
++
++static int ep93xx_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ int rc;
++
++ if (!netif_running(dev))
++ return -EINVAL;
++
++ spin_lock_irq(&priv->mii_lock);
++ rc = generic_mii_ioctl(&priv->mii, if_mii(rq), cmd, NULL);
++ spin_unlock_irq(&priv->mii_lock);
++
++ return rc;
++}
++
++/*
++ * Ethtool support
++ */
++
++static void ep93xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
++{
++ strcpy(info->driver, DRV_NAME);
++ strcpy(info->version, DRV_VERSION);
++}
++
++static int ep93xx_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ spin_lock_irq(&priv->mii_lock);
++ mii_ethtool_gset(&priv->mii, cmd);
++ spin_unlock_irq(&priv->mii_lock);
++ return 0;
++}
++
++static int ep93xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ int rc;
++ spin_lock_irq(&priv->mii_lock);
++ rc = mii_ethtool_sset(&priv->mii, cmd);
++ spin_unlock_irq(&priv->mii_lock);
++ return rc;
++}
++
++static int ep93xx_nway_reset(struct net_device *dev)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ return mii_nway_restart(&priv->mii);
++}
++
++static u32 ep93xx_get_link(struct net_device *dev)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ return mii_link_ok(&priv->mii);
++}
++
++static u32 ep93xx_get_msglevel(struct net_device *dev)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ return priv->msg_enable;
++}
++
++static void ep93xx_set_msglevel(struct net_device *dev, u32 datum)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ priv->msg_enable = datum;
++}
++
++static void ep93xx_get_regs(struct net_device *dev, struct ethtool_regs *regs, void *regbuf)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ spin_lock_irq(&priv->mii_lock);
++ memcpy_fromio(regbuf, priv->base_addr, regs->len);
++ spin_unlock_irq(&priv->mii_lock);
++}
++
++static int ep93xx_get_regs_len(struct net_device *dev)
++{
++ struct ep93xx_priv *priv = netdev_priv(dev);
++ return priv->regs_len;
++}
++
++static struct ethtool_ops ep93xx_ethtool_ops = {
++ .get_drvinfo = ep93xx_get_drvinfo,
++ .get_settings = ep93xx_get_settings,
++ .set_settings = ep93xx_set_settings,
++ .get_regs = ep93xx_get_regs,
++ .get_regs_len = ep93xx_get_regs_len,
++ .nway_reset = ep93xx_nway_reset,
++ .get_link = ep93xx_get_link,
++ .get_msglevel = ep93xx_get_msglevel,
++ .set_msglevel = ep93xx_set_msglevel,
++};
++
++/**
++ * driver_init() - Logical driver initialization for an individual device
++ *
++ * Minimum device H/W access at this point
++ *
++ * Task:
++ * Initialize the structure if needed
++ * print out my vanity message if not done so already
++ * print out what type of hardware is detected
++ * print out the ethernet address
++ * find the IRQ
++ * set up my private data
++ * configure the dev structure with my subroutines
++ * actually GRAB the irq.
++ * GRAB the region
++ *
++ */
++static int __init driver_init(struct net_device *dev, u32 baseA, int irq)
++{
++ int i;
++ struct resource *res;
++ struct sockaddr sa;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ if (0 == num_of_instance)
++ printk("%s", version);
++
++ /* skip probing for a second one, we _know_ that it does not exist */
++ if (1 == num_of_instance)
++ return -ENODEV;
++
++ memset(dev->priv, 0x00, sizeof(struct ep93xx_priv));
++
++ /* device instance ID */
++ priv->id = num_of_instance;
++
++ /* mii stuff */
++ spin_lock_init(&priv->mii_lock);
++ priv->mii.dev = dev;
++ priv->mii.mdio_read = mdio_read;
++ priv->mii.mdio_write = mdio_write;
++ priv->mii.phy_id_mask = 0x1f;
++ priv->mii.reg_num_mask = 0x1f;
++ priv->msg_enable = EP93XX_DEF_MSG;
++ priv->regs_len = DEV_REG_SPACE;
++
++ priv->base_addr = (void *)(baseA);
++
++ dev->irq = irq;
++
++ res = request_mem_region(baseA, DEV_REG_SPACE, DRV_NAME);
++ if (res == NULL) {
++ if (netif_msg_probe(priv))
++ DBG(KERN_ERR, "request_mem_region failed!\n");
++ goto err_free_priv_1;
++ }
++
++ dev->open = &ep93xx_open;
++ dev->stop = &ep93xx_close;
++ dev->do_ioctl = &ep93xx_ioctl;
++ dev->hard_start_xmit = &ep93xx_start_xmit;
++ dev->tx_timeout = &ep93xx_tx_timeout;
++ dev->watchdog_timeo = HZ * 5;
++ dev->get_stats = &ep93xx_get_stats;
++ dev->set_multicast_list = &ep93xx_set_multicast_list;
++ dev->ethtool_ops = &ep93xx_ethtool_ops;
++
++ ether_setup(dev);
++
++ if (devQue_init(dev))
++ goto err_free_bd_memregion_irq_2;
++
++ reset(dev);
++
++ /*
++ * use a random MAC for now -
++ * don't forget to set a valid MAC later on with ifconfig
++ */
++ sa.sa_family = AF_INET;
++ random_ether_addr(sa.sa_data);
++ dev->set_mac_address(dev, &sa);
++
++ if (netif_msg_probe(priv)) {
++ printk(KERN_INFO DRV_NAME ": #%d at 0x%p IRQ:%d\n", priv->id, priv->base_addr, dev->irq);
++ printk(KERN_INFO DRV_NAME ": using random number");
++ for (i = 0; i < 6; i++)
++ printk("%c%02x", i ? ':' : ' ', dev->dev_addr[i]);
++
++ printk(" as MAC, don't forget to assign a valid MAC later!\n");
++ }
++ num_of_instance++;
++ return 0;
++
++err_free_bd_memregion_irq_2:
++ kfree(priv->rxbd);
++ disable_irq(dev->irq);
++ free_irq(dev->irq, dev);
++ release_mem_region((u32)priv->base_addr, DEV_REG_SPACE);
++err_free_priv_1:
++ kfree(dev->priv);
++ return -EAGAIN;
++}
++
++/**
++ * ep93xx_probe - probe for ep93xx device
++ *
++ * Probe for the one (and only) ethernet device found on
++ * EP93xx SOC CPU.
++ */
++static int __init ep93xx_probe(void)
++{
++ int err;
++ struct ep93xx_priv *priv;
++ struct net_device *dev = alloc_etherdev(sizeof(struct ep93xx_priv));
++
++ if (!dev)
++ return -ENODEV;
++
++ priv = netdev_priv(dev);
++
++ SET_MODULE_OWNER(dev);
++
++ sprintf(dev->name, "eth0");
++
++ priv->base_addr = (void *)(port_list[0].base_addr);
++
++ dev->irq = port_list[0].irq;
++
++ err = driver_init(dev, (u32)priv->base_addr, dev->irq);
++ if (err)
++ goto err_free_netdev;
++
++ err = register_netdev(dev);
++ if (err)
++ goto err_free_memregion_irq_1;
++
++ ep93xx_etherdev = dev;
++ disable_irq(dev->irq);
++ return 0;
++
++err_free_memregion_irq_1:
++ kfree(priv->rxbd);
++ disable_irq(dev->irq);
++ free_irq(dev->irq, dev);
++ release_mem_region((u32)priv->base_addr, DEV_REG_SPACE);
++err_free_netdev:
++ free_netdev(dev);
++ return err;
++}
++
++static void __exit ep93xx_exit(void)
++{
++ struct net_device *dev = ep93xx_etherdev;
++ struct ep93xx_priv *priv = netdev_priv(dev);
++
++ if (dev) {
++ unregister_netdev(dev);
++ devQue_cleanup(dev);
++ free_irq(dev->irq, dev);
++ release_mem_region((u32)priv->base_addr, DEV_REG_SPACE);
++ free_netdev(dev);
++ }
++}
++
++module_init(ep93xx_probe);
++module_exit(ep93xx_exit);
++MODULE_LICENSE("GPL");
+diff --git a/drivers/net/arm/ep93xx_eth.h b/drivers/net/arm/ep93xx_eth.h
+new file mode 100644
+index 0000000..1752eaf
+--- /dev/null
++++ b/drivers/net/arm/ep93xx_eth.h
+@@ -0,0 +1,355 @@
++/*
++ * ep93xx_eth.h
++ * : header file of Ethernet Device Driver for Cirrus Logic EP93xx.
++ *
++ * Copyright (C) 2003 by Cirrus Logic www.cirrus.com
++ * This software may be used and distributed according to the terms
++ * of the GNU Public License.
++ *
++ * This file contains device related information like register info
++ * and register access method macros for the Ethernet device
++ * embedded within Cirrus Logic's EP93xx SOC chip.
++ *
++ * Information contained in this file was obtained from
++ * the EP9312 Manual Revision 0.12 and 0.14 from Cirrus Logic.
++ *
++ * History
++ * 05/18/01 Sungwook Kim Initial release
++ * 03/25/2003 Melody Modified for EP92xx
++ */
++
++#ifndef _EP93xx_ETH_H_
++#define _EP93xx_ETH_H_
++
++/*
++ * Definition of the registers.
++ * For details, refer to the datasheet .
++ *
++ * Basically, most registers are 32 bits width register.
++ * But some are 16 bits and some are 6 or 8 bytes long.
++ */
++
++#define REG_RxCTL 0x0000 /*offset to Receiver Control Reg */
++#define RxCTL_PauseA (1<<20)
++#define RxCTL_RxFCE1 (1<<19)
++#define RxCTL_RxFCE0 (1<<18)
++#define RxCTL_BCRC (1<<17)
++#define RxCTL_SRxON (1<<16)
++#define RxCTL_RCRCA (1<<13)
++#define RxCTL_RA (1<<12)
++#define RxCTL_PA (1<<11)
++#define RxCTL_BA (1<<10)
++#define RxCTL_MA (1<<9)
++#define RxCTL_IAHA (1<<8)
++#define RxCTL_IA3 (1<<3)
++#define RxCTL_IA2 (1<<2)
++#define RxCTL_IA1 (1<<1)
++#define RxCTL_IA0 (1<<0)
++
++#define REG_TxCTL 0x0004 /*offset to Transmit Control Reg */
++#define TxCTL_DefDis (1<<7)
++#define TxCTL_MBE (1<<6)
++#define TxCTL_ICRC (1<<5)
++#define TxCTL_TxPD (1<<5)
++#define TxCTL_OColl (1<<3)
++#define TxCTL_SP (1<<2)
++#define TxCTL_PB (1<<1)
++#define TxCTL_STxON (1<<0)
++
++#define REG_TestCTL 0x0008 /*Test Control Reg, R/W */
++#define TestCTL_MACF (1<<7)
++#define TestCTL_MFDX (1<<6)
++#define TestCTL_DB (1<<5)
++#define TestCTL_MIIF (1<<4)
++
++#define REG_MIICmd 0x0010 /*offset to MII Command Reg, R/W */
++#define MIICmd_OP (0x03<<14)
++#define MIICmd_OP_RD (2<<14)
++#define MIICmd_OP_WR (1<<14)
++#define MIICmd_PHYAD (0x1f<<5)
++#define MIICmd_REGAD (0x1f<<0)
++
++#define REG_MIIData 0x0014 /*offset to MII Data Reg, R/W */
++#define MIIData_MIIData (0xffff<<0)
++
++#define REG_MIISts 0x0018 /*offset to MII Status Reg, R */
++#define MIISts_Busy (1<<0)
++
++#define REG_SelfCTL 0x0020 /*offset to Self Control Reg */
++#define SelfCTL_RWP (1<<7) /*Remote Wake Pin */
++#define SelfCTL_GPO0 (1<<5)
++#define SelfCTL_PUWE (1<<4)
++#define SelfCTL_PDWE (1<<3)
++#define SelfCTL_MIIL (1<<2)
++#define SelfCTL_RESET (1<<0)
++
++#define REG_IntEn 0x0024 /*Interrupt Enable Reg, R/W */
++#define IntEn_RWIE (1<<30)
++#define IntEn_RxMIE (1<<29)
++#define IntEn_RxBIE (1<<28)
++#define IntEn_RxSQIE (1<<27)
++#define IntEn_TxLEIE (1<<26)
++#define IntEn_ECIE (1<<25)
++#define IntEn_TxUHIE (1<<24)
++#define IntEn_MOIE (1<<18)
++#define IntEn_TxCOIE (1<<17)
++#define IntEn_RxROIE (1<<16)
++#define IntEn_MIIIE (1<<12)
++#define IntEn_PHYSIE (1<<11)
++#define IntEn_TIE (1<<10)
++#define IntEn_SWIE (1<<8)
++#define IntEn_TxSQIE (1<<3)
++#define IntEn_RxEOFIE (1<<2)
++#define IntEn_RxEOBIE (1<<1)
++#define IntEn_RxHDRIE (1<<0)
++
++#define REG_IntStsP 0x0028 /*offset to Interrupt Status Preserve Reg, R/W */
++#define REG_IntStsC 0x002c /*offset to Interrupt Status Clear Reg, R */
++#define IntSts_RWI (1<<30)
++#define IntSts_RxMI (1<<29)
++#define IntSts_RxBI (1<<28)
++#define IntSts_RxSQI (1<<27)
++#define IntSts_TxLEI (1<<26)
++#define IntSts_ECI (1<<25)
++#define IntSts_TxUHI (1<<24)
++#define IntSts_MOI (1<<18)
++#define IntSts_TxCOI (1<<17)
++#define IntSts_RxROI (1<<16)
++#define IntSts_MIII (1<<12)
++#define IntSts_PHYSI (1<<11)
++#define IntSts_TI (1<<10)
++#define IntSts_AHBE (1<<9)
++#define IntSts_SWI (1<<8)
++#define IntSts_OTHER (1<<4)
++#define IntSts_TxSQ (1<<3)
++#define IntSts_RxSQ (1<<2)
++
++#define REG_GT 0x0040 /*offset to General Timer Reg */
++#define GT_GTC (0xffff<<16)
++#define GT_GTP (0xffff<<0)
++
++#define REG_FCT 0x0044 /*offset to Flow Control Timer Reg */
++#define FCT_FCT (0x00ffffff<<0)
++
++#define REG_FCF 0x0048 /*offset to Flow Control Format Reg */
++#define FCF_MACCT (0xffff<<16)
++#define FCF_TPT (0xffff<<0)
++
++#define REG_AFP 0x004c /*offset to Address Filter Pointer Reg */
++#define AFP_AFP (0x07<<0) /*Address Filter Pointer
++ (bank control for REG_IndAD) */
++#define AFP_AFP_IA0 0 /*Primary Individual Address (MAC Addr) */
++#define AFP_AFP_IA1 1 /*Individual Address 1 */
++#define AFP_AFP_IA2 2 /*Individual Address 2 */
++#define AFP_AFP_IA3 3 /*Individual Address 3 */
++#define AFP_AFP_DTxP 6 /*Destination Address of Tx Pause Frame */
++#define AFP_AFP_HASH 7 /*Hash Table */
++
++#define REG_IndAD 0x0050 /*offset to Individual Address Reg,
++ n bytes, R/W */
++
++#define REG_GIntSts 0x0060 /*offset to Global Interrupt
++ Status Reg (writing 1 will clear) */
++#define REG_GIntROS 0x0068 /*offset to Global Interrupt
++ Status Read Only Reg */
++#define GIntSts_INT (1<<15) /*Global Interrupt Request Status */
++
++#define REG_GIntMsk 0x0064 /*offset to Global Interrupt Mask Reg */
++#define GIntMsk_IntEn (1<<15) /*Global Interrupt Enable */
++
++#define REG_GIntFrc 0x006c /*offset to Global Interrupt Force Reg */
++#define GIntFrc_INT (1<<15) /*Force to set GIntSts */
++
++#define REG_TxCollCnt 0x0070 /*Transmit Collision Count Reg, R */
++#define REG_RxMissCnt 0x0074 /*Receive Miss Count Reg, R */
++#define REG_RxRntCnt 0x0078 /*Receive Runt Count Reg, R */
++
++#define REG_BMCtl 0x0080 /*offset to Bus Master Control Reg, R/W */
++#define BMCtl_MT (1<<13)
++#define BMCtl_TT (1<<12)
++#define BMCtl_UnH (1<<11)
++#define BMCtl_TxChR (1<<10)
++#define BMCtl_TxDis (1<<9)
++#define BMCtl_TxEn (1<<8)
++#define BMCtl_EH2 (1<<6)
++#define BMCtl_EH1 (1<<5)
++#define BMCtl_EEOB (1<<4)
++#define BMCtl_RxChR (1<<2)
++#define BMCtl_RxDis (1<<1)
++#define BMCtl_RxEn (1<<0)
++
++#define REG_BMSts 0x0084 /*offset to Bus Master Status Reg, R */
++#define BMSts_TxAct (1<<7)
++#define BMSts_TP (1<<4)
++#define BMSts_RxAct (1<<3)
++#define BMSts_QID (0x07<<0)
++#define BMSts_QID_RxDt (0<<0)
++#define BMSts_QID_TxDt (1<<0)
++#define BMSts_QID_RxSts (2<<0)
++#define BMSts_QID_TxSts (3<<0)
++#define BMSts_QID_RxDesc (4<<0)
++#define BMSts_QID_TxDesc (5<<0)
++
++#define REG_RBCA 0x0088 /*offset to Receive Buffer
++ Current Address Reg, R */
++#define REG_TBCA 0x008c /*offset to Transmit Buffer
++ Current Address Reg, R */
++
++#define REG_RxDBA 0x0090 /*offset to Receive Descriptor Queue
++ Base Address Reg, R/W */
++#define REG_RxDBL 0x0094 /*offset to Receive Descriptor Queue
++ Base Length Reg, R/W, 16bits */
++#define REG_RxDCL 0x0096 /*offset to Receive Descriptor Queue
++ Current Length Reg, R/W, 16bits */
++#define REG_RxDCA 0x0098 /*offset to Receive Descriptor Queue
++ Current Address Reg, R/W */
++
++#define REG_RxDEQ 0x009c /*offset to Receive Descriptor
++ Enqueue Reg, R/W */
++#define RxDEQ_RDV (0xffff<<16) /*R 16bit; Receive Descriptor Value */
++#define RxDEQ_RDI (0xff<<0) /*W 8bit; Receive Descriptor Increment */
++
++#define REG_RxSBA 0x00a0 /*offset to Receive Status Queue
++ Base Address Reg, R/W */
++#define REG_RxSBL 0x00a4 /*offset to Receive Status Queue
++ Base Length Reg, R/W, 16bits */
++#define REG_RxSCL 0x00a6 /*offset to Receive Status Queue
++ Current Length Reg, R/W, 16bits */
++#define REG_RxSCA 0x00a8 /*offset to Receive Status Queue
++ Current Address Reg, R/W */
++
++#define REG_RxSEQ 0x00ac /*offset to Receive Status Queue
++ Current Address Reg, R/W */
++#define RxSEQ_RSV (0xffff<<16)
++#define RxSEQ_RSI (0xff<<0)
++
++#define REG_TxDBA 0x00b0 /*offset to Transmit Descriptor Queue
++ Base Address Reg, R/W */
++#define REG_TxDBL 0x00b4 /*offset to Transmit Descriptor Queue
++ Base Length Reg, R/W, 16bits */
++#define REG_TxDCL 0x00b6 /*offset to Transmit Descriptor Queue
++ Current Length Reg, R/W, 16bits */
++#define REG_TxDCA 0x00b8 /*offset to Transmit Descriptor Queue
++ Current Address Reg, R/W */
++
++#define REG_TxDEQ 0x00bc /*offset to Transmit Descriptor Queue
++ Current Address Reg, R/W */
++#define TxDEQ_TDV (0xffff<<16)
++#define TxDEQ_TDI (0xff<<0)
++
++#define REG_TxSBA 0x00c0 /*offset to Transmit Status Queue
++ Base Address Reg, R/W */
++#define REG_TxSBL 0x00c4 /*offset to Transmit Status Queue
++ Base Length Reg, R/W, 16bits */
++#define REG_TxSCL 0x00c6 /*offset to Transmit Status Queue
++ Current Length Reg, R/W, 16bits */
++#define REG_TxSCA 0x00c8 /*offset to Transmit Status Queue
++ Current Address Reg, R/W */
++
++#define REG_RxBTH 0x00d0 /*offset to Receive Buffer
++ Threshold Reg, R/W */
++#define RxBTH_RDHT (0x03ff<<16)
++#define RxBTH_RDST (0x03ff<<0)
++
++#define REG_TxBTH 0x00d4 /*offset to Transmit Buffer
++ Threshold Reg, R/W */
++#define TxBTH_TDHT (0x03ff<<16)
++#define TxBTH_TDST (0x03ff<<0)
++
++#define REG_RxSTH 0x00d8 /*offset to Receive Status
++ Threshold Reg, R/W */
++#define RxSTH_RSHT (0x003f<<16)
++#define RxSTH_RSST (0x003f<<0)
++
++#define REG_TxSTH 0x00dc /*offset to Transmit Status
++ Threshold Reg, R/W */
++#define TxSTH_TSHT (0x003f<<16)
++#define TxSTH_TSST (0x003f<<0)
++
++#define REG_RxDTH 0x00e0 /*offset to Receive Descriptor
++ Threshold Reg, R/W */
++#define RxDTH_RDHT (0x003f<<16)
++#define RxDTH_RDST (0x003f<<0)
++
++#define REG_TxDTH 0x00e4 /*offset to Transmit Descriptor
++ Threshold Reg, R/W */
++#define TxDTH_TDHT (0x003f<<16)
++#define TxDTH_TDST (0x003f<<0)
++
++#define REG_MaxFL 0x00e8 /*offset to Max Frame Length Reg, R/W */
++#define MaxFL_MFL (0x07ff<<16)
++#define MaxFL_TST (0x07ff<<0)
++
++#define REG_RxHL 0x00ec /*offset to Receive Header Length Reg, R/W */
++#define RxHL_RHL2 (0x07ff<<16)
++#define RxHL_RHL1 (0x03ff<<0)
++
++#define REG_MACCFG0 0x0100 /*offset to Test Reg #0, R/W */
++#define MACCFG0_DbgSel (1<<7)
++#define MACCFG0_LCKEN (1<<6)
++#define MACCFG0_LRATE (1<<5)
++#define MACCFG0_RXERR (1<<4)
++#define MACCFG0_BIT33 (1<<2)
++#define MACCFG0_PMEEN (1<<1)
++#define MACCFG0_PMEST (1<<0)
++
++#define REG_MACCFG1 0x0104 /*offset to Test Reg #1, R/W */
++#define REG_MACCFG2 0x0108 /*offset to Test Reg #2, R */
++#define REG_MACCFG3 0x010c /*offset to Test Reg #3, R */
++
++/*---------------------------------------------------------------
++ * Definition of Descriptor/Status Queue Entry
++ *-------------------------------------------------------------*/
++struct rx_dsc {
++ __be32 ba;
++ __be16 bl;
++ __be16 bi; /* let nsof flag be part of bi */
++};
++
++#define RXSTS_RFP 0x80000000
++#define RXSTS_RWE 0x40000000
++#define RXSTS_EOF 0x20000000
++#define RXSTS_EOB 0x10000000
++#define RXSTS_AM 0x00C00000
++#define RXSTS_OE 0x00100000
++#define RXSTS_FE 0x00080000
++#define RXSTS_RUNT 0x00040000
++#define RXSTS_EDATA 0x00020000
++#define RXSTS_CRCE 0x00010000
++
++#define RXSTS_BI 0x7FFF
++struct rx_sts { /* Receive Status Queue Entry */
++ __be32 w1;
++ __be16 fl;
++ __be16 bi; /* bi and rfp2 */
++};
++
++#define TXDSC_BL 0x0FFF
++#define TXDSC_AF 0x8000
++#define TXDSC_BI 0x7FFF
++#define TXDSC_EOF 0x8000
++struct tx_dsc { /* Transmit Descriptor Queue Entry */
++ __be32 ba; /*b31-0: physical Buffer Address */
++ __be16 bl_af; /* Buffer Length, Abort Frame */
++ __be16 bi_eof; /* Buffer Index, End Of Frame */
++};
++
++#define TXSTS_BI 0x7fff
++#define TXSTS_TXFP 0x80
++#define TXSTS_TXWE 0x40
++#define TXSTS_LCRS 0x10
++#define TXSTS_TXU 0x02
++#define TXSTS_ECOLL 0x01
++
++struct tx_sts {
++ __be16 bi;
++ u8 ncoll;
++ u8 flags;
++};
++
++/*
++ * Size of device registers occupied in memory/IO address map
++ */
++#define DEV_REG_SPACE 0x00010000
++
++#endif /* _EP93xx_ETH_H_ */
+diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig
+index 309eb55..b7e03e3 100644
+--- a/drivers/pcmcia/Kconfig
++++ b/drivers/pcmcia/Kconfig
+@@ -198,6 +198,19 @@ config PCMCIA_PXA2XX
+ help
+ Say Y here to include support for the PXA2xx PCMCIA controller
+
++config PCMCIA_EP93XX
++ tristate "EP93xx support"
++ depends on ARM && ARCH_EP93XX && PCMCIA
++ help
++ Say Y here to include support for the EP93xx PCMCIA controller
++
++config PCMCIA_ZEFEEREVBH
++ bool "ZefeerEVB-H support"
++ depends on ARM && ARCH_EP93XX && PCMCIA && PCMCIA_EP93XX && MACH_ZEFEERDZQ
++ help
++ Say Y here to include support for the PCMCIA interface on
++ ZefeerEVB-H board
++
+ config PCMCIA_PROBE
+ bool
+ default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X
+diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile
+index bcecf51..5878b5a 100644
+--- a/drivers/pcmcia/Makefile
++++ b/drivers/pcmcia/Makefile
+@@ -30,6 +30,7 @@ obj-$(CONFIG_HD64465_PCMCIA) += hd6446
+ obj-$(CONFIG_PCMCIA_SA1100) += sa11xx_core.o sa1100_cs.o
+ obj-$(CONFIG_PCMCIA_SA1111) += sa11xx_core.o sa1111_cs.o
+ obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_core.o pxa2xx_cs.o
++obj-$(CONFIG_PCMCIA_EP93XX) += ep93xx_core.o ep93xx_cs.o
+ obj-$(CONFIG_M32R_PCC) += m32r_pcc.o
+ obj-$(CONFIG_M32R_CFC) += m32r_cfc.o
+ obj-$(CONFIG_PCMCIA_AU1X00) += au1x00_ss.o
+@@ -39,6 +40,7 @@ obj-$(CONFIG_OMAP_CF) += omap_cf.o
+
+ sa11xx_core-y += soc_common.o sa11xx_base.o
+ pxa2xx_core-y += soc_common.o pxa2xx_base.o
++ep93xx_core-y += soc_common.o ep93xx_base.o
+
+ au1x00_ss-y += au1000_generic.o
+ au1x00_ss-$(CONFIG_MIPS_PB1000) += au1000_pb1x00.o
+@@ -69,3 +71,7 @@ pxa2xx_cs-$(CONFIG_ARCH_LUBBOCK) += pxa
+ pxa2xx_cs-$(CONFIG_MACH_MAINSTONE) += pxa2xx_mainstone.o
+ pxa2xx_cs-$(CONFIG_PXA_SHARPSL) += pxa2xx_sharpsl.o
+
++ep93xx_cs-$(CONFIG_MACH_ADSSPHERE) += ep93xx_adssphere.o
++ep93xx_cs-$(CONFIG_MACH_EDB9315) += ep93xx_edb9315.o
++ep93xx_cs-$(CONFIG_MACH_DMA03) += ep93xx_edb9315.o
++ep93xx_cs-$(CONFIG_PCMCIA_ZEFEEREVBH) += ep93xx_zefeerevbh.o
+diff --git a/drivers/pcmcia/ep93xx_adssphere.c b/drivers/pcmcia/ep93xx_adssphere.c
+new file mode 100644
+index 0000000..8e1a181
+--- /dev/null
++++ b/drivers/pcmcia/ep93xx_adssphere.c
+@@ -0,0 +1,190 @@
++/*
++ * linux/drivers/pcmcia/ep93xx_adssphere.c
++ *
++ * Adapted from pxa27x_mainstone.c
++ *
++ * Robert Whaley 2005 rwhaley@applieddata.net
++ *
++ * Adssphere PCMCIA specific routines.
++ *
++ * Created: May 12, 2004
++ * Author: Nicolas Pitre
++ * Copyright: MontaVista Software Inc.
++ *
++ * 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/kernel.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/device.h>
++
++#include <pcmcia/ss.h>
++
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++
++#include <asm/arch/adssphere.h>
++
++#include "soc_common.h"
++
++static struct pcmcia_irqs irqs[] = {
++ { 0, IRQ_GPIO1, "CF CD1" },
++ { 0, IRQ_GPIO2, "CF CD2" },
++ { 0, IRQ_GPIO3, "CF STSCHG/BVD1" },
++ { 0, IRQ_GPIO4, "CF SPKR/BVD2" },
++};
++
++
++static int adssphere_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
++{
++ int rtn;
++
++ if (skt->nr != 0)
++ return -ENXIO;
++
++ skt->irq = IRQ_GPIO6;
++
++ rtn = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
++
++ /* enable GPIO6 as interrupt */
++ writel(0x40, GPIO_INTEN);
++
++ /* enable GPIO1-4 and 6 as interrupt */
++ /* Note: 1-4 need to be edge triggered, but
++ then the irq vectors need to hit GPIOxEIO
++ which they don't currently do - no big deal
++ since CD and BVD are polled anyway */
++ /* writel(0x5e, GPIO_INTEN); */
++
++ return rtn;
++}
++
++static void adssphere_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
++{
++ soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
++}
++
++static void adssphere_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
++ struct pcmcia_state *state)
++{
++ unsigned long status;
++
++ status = inl(GPIO_PFDR);
++
++ state->detect = (status & PCMCIA_DETECT) ? 0 : 1;
++ state->ready = (status & PCMCIA_READY) ? 1 : 0;
++ state->bvd1 = (status & PCMCIA_BVD1) ? 1 : 0;
++ state->bvd2 = (status & PCMCIA_BVD2) ? 1 : 0;
++ state->vs_3v = (status & PCMCIA_VS_3V) ? 0 : 1;
++ state->vs_Xv = (status & PCMCIA_VS_XV) ? 0 : 1;
++ state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1;
++
++// printk("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state));
++}
++
++static int adssphere_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
++ const socket_state_t *state)
++{
++ unsigned long clrbits = 0, setbits = 0, cr0;
++ int ret = 0;
++
++ switch (state->Vcc) {
++ case 0: {
++ clrbits = ADSSPHERE_CR0_CF_33 | ADSSPHERE_CR0_CF_50;
++ setbits = 0;
++ break;
++ }
++ case 33: {
++ clrbits = ADSSPHERE_CR0_CF_50;
++ setbits = ADSSPHERE_CR0_CF_33;
++ break;
++ }
++ case 50: {
++ clrbits = ADSSPHERE_CR0_CF_33;
++ setbits = ADSSPHERE_CR0_CF_50;
++ break;
++ }
++ default:
++ printk(KERN_ERR "%s(): bad Vcc %u\n",
++ __FUNCTION__, state->Vcc);
++ ret = -1;
++ }
++
++ if (!ret && skt->nr == 0) {
++ cr0 = inl(ADSSPHERE_CR0);
++ cr0 &= ~clrbits;
++ cr0 |= setbits;
++ writel(cr0, ADSSPHERE_CR0);
++
++ if (state->flags & SS_RESET) {
++ /* see EP93xx User's Guide */
++ writel(0x15, PCMCIACNT);
++ } else {
++ /* CF mode - BIT1 for PCMCIA mode */
++ writel(0x11, PCMCIACNT);
++ }
++ }
++
++ return ret;
++}
++
++static void adssphere_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
++{
++}
++
++static void adssphere_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
++{
++}
++
++static struct pcmcia_low_level adssphere_pcmcia_ops = {
++ .owner = THIS_MODULE,
++ .hw_init = adssphere_pcmcia_hw_init,
++ .hw_shutdown = adssphere_pcmcia_hw_shutdown,
++ .socket_state = adssphere_pcmcia_socket_state,
++ .configure_socket = adssphere_pcmcia_configure_socket,
++ .socket_init = adssphere_pcmcia_socket_init,
++ .socket_suspend = adssphere_pcmcia_socket_suspend,
++ .nr = 1,
++};
++
++static struct platform_device *adssphere_pcmcia_device;
++
++static int __init adssphere_pcmcia_init(void)
++{
++ int ret;
++
++ adssphere_pcmcia_device = kmalloc(sizeof(*adssphere_pcmcia_device), GFP_KERNEL);
++ if (!adssphere_pcmcia_device)
++ return -ENOMEM;
++ memset(adssphere_pcmcia_device, 0, sizeof(*adssphere_pcmcia_device));
++ adssphere_pcmcia_device->name = "ep93xx-pcmcia";
++ adssphere_pcmcia_device->dev.platform_data = &adssphere_pcmcia_ops;
++
++ ret = platform_device_register(adssphere_pcmcia_device);
++ if (ret)
++ kfree(adssphere_pcmcia_device);
++
++ return ret;
++}
++
++static void __exit adssphere_pcmcia_exit(void)
++{
++ /*
++ * This call is supposed to free our adssphere_pcmcia_device.
++ * Unfortunately platform_device don't have a free method, and
++ * we can't assume it's free of any reference at this point so we
++ * can't free it either.
++ */
++ platform_device_unregister(adssphere_pcmcia_device);
++}
++
++module_init(adssphere_pcmcia_init);
++module_exit(adssphere_pcmcia_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/pcmcia/ep93xx_base.c b/drivers/pcmcia/ep93xx_base.c
+new file mode 100644
+index 0000000..2377989
+--- /dev/null
++++ b/drivers/pcmcia/ep93xx_base.c
+@@ -0,0 +1,190 @@
++/*======================================================================
++
++ Device driver for the PCMCIA control functionality of EP93xx
++ microprocessors. Derived from pxa2xx_base.c
++
++ The contents of this file may be used under the
++ terms of the GNU Public License version 2 (the "GPL")
++
++ (c) Ian Molton (spyro@f2s.com) 2003
++ (c) Stefan Eletzhofer (stefan.eletzhofer@inquant.de) 2003,4
++ (c) Robert Whaley (rwhaley@applieddata.net) 2005
++
++ derived from sa11xx_base.c
++
++ Portions created by John G. Dorsey are
++ Copyright (C) 1999 John G. Dorsey.
++
++ ======================================================================*/
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/config.h>
++#include <linux/ioport.h>
++#include <linux/kernel.h>
++#include <linux/spinlock.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++
++#include <pcmcia/cs_types.h>
++#include <pcmcia/ss.h>
++#include <pcmcia/bulkmem.h>
++#include <pcmcia/cistpl.h>
++
++#include "cs_internal.h"
++#include "soc_common.h"
++
++#define MIN(a,b) ((a)>(b) ? (b) : (a))
++
++#define MCXX_SETUP_MAX 0xff
++#define MCXX_ASST_MAX 0xff
++#define MCXX_HOLD_MAX 0x0f
++
++#define MCXX_SETUP_SHIFT 0
++#define MCXX_ASST_SHIFT 16
++#define MCXX_HOLD_SHIFT 8
++
++
++
++static inline u_int ep93xx_mcxx_hold(u_int pcmcia_cycle_ns,
++ u_int hclk_10khz)
++{
++ u_int code = pcmcia_cycle_ns * hclk_10khz;
++ return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
++}
++
++static inline u_int ep93xx_mcxx_asst(u_int pcmcia_cycle_ns,
++ u_int hclk_10khz)
++{
++ u_int code = pcmcia_cycle_ns * hclk_10khz;
++ return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
++}
++
++static inline u_int ep93xx_mcxx_setup(u_int pcmcia_cycle_ns,
++ u_int hclk_10khz)
++{
++ u_int code = pcmcia_cycle_ns * hclk_10khz;
++ return (code / 100000) + ((code % 100000) ? 1 : 0) - 1;
++}
++
++static int ep93xx_pcmcia_set_mcmem( int sock, int speed, int clock )
++{
++ writel(PC16BITSWIDE
++ | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
++ | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
++ | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
++ PC1COMMON);
++
++ return 0;
++}
++
++static int ep93xx_pcmcia_set_mcio( int sock, int speed, int clock )
++{
++ writel(PC16BITSWIDE
++ | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
++ | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
++ | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
++ PC1IO);
++
++ return 0;
++}
++
++static int ep93xx_pcmcia_set_mcatt( int sock, int speed, int clock )
++{
++ writel(PC16BITSWIDE
++ | (MIN(ep93xx_mcxx_setup(speed, clock), MCXX_SETUP_MAX) << MCXX_SETUP_SHIFT)
++ | (MIN(ep93xx_mcxx_asst(speed, clock), MCXX_ASST_MAX) << MCXX_ASST_SHIFT)
++ | (MIN(ep93xx_mcxx_hold(speed, clock), MCXX_HOLD_MAX) << MCXX_HOLD_SHIFT),
++ PC1ATTRIB);
++
++ return 0;
++}
++
++static int ep93xx_pcmcia_set_mcxx(struct soc_pcmcia_socket *skt, unsigned int clk)
++{
++ struct soc_pcmcia_timing timing;
++ int sock = skt->nr;
++
++ soc_common_pcmcia_get_timing(skt, &timing);
++
++ ep93xx_pcmcia_set_mcmem(sock, timing.mem, clk);
++ ep93xx_pcmcia_set_mcatt(sock, timing.attr, clk);
++ ep93xx_pcmcia_set_mcio(sock, timing.io, clk);
++
++ return 0;
++}
++
++static int ep93xx_pcmcia_set_timing(struct soc_pcmcia_socket *skt)
++{
++ unsigned int hclk = 10000; /* for now just hard code hclk to 100Mhz (in 10khz units)*/
++ return ep93xx_pcmcia_set_mcxx(skt, hclk);
++}
++
++int ep93xx_drv_pcmcia_probe(struct device *dev)
++{
++ int ret;
++ struct pcmcia_low_level *ops;
++ int first, nr;
++
++ if (!dev || !dev->platform_data)
++ return -ENODEV;
++
++ ops = (struct pcmcia_low_level *)dev->platform_data;
++ first = ops->first;
++ nr = ops->nr;
++
++ /* Provide our EP93xx specific timing routines. */
++ ops->set_timing = ep93xx_pcmcia_set_timing;
++
++ ret = soc_common_drv_pcmcia_probe(dev, ops, first, nr);
++
++ return ret;
++}
++EXPORT_SYMBOL(ep93xx_drv_pcmcia_probe);
++
++static int ep93xx_drv_pcmcia_suspend(struct device *dev, u32 state, u32 level)
++{
++ int ret = 0;
++ if (level == SUSPEND_SAVE_STATE)
++ ret = pcmcia_socket_dev_suspend(dev, state);
++ return ret;
++}
++
++static int ep93xx_drv_pcmcia_resume(struct device *dev, u32 level)
++{
++ int ret = 0;
++ if (level == RESUME_RESTORE_STATE)
++ {
++ ret = pcmcia_socket_dev_resume(dev);
++ }
++ return ret;
++}
++
++static struct device_driver ep93xx_pcmcia_driver = {
++ .probe = ep93xx_drv_pcmcia_probe,
++ .remove = soc_common_drv_pcmcia_remove,
++ .suspend = ep93xx_drv_pcmcia_suspend,
++ .resume = ep93xx_drv_pcmcia_resume,
++ .name = "ep93xx-pcmcia",
++ .bus = &platform_bus_type,
++};
++
++static int __init ep93xx_pcmcia_init(void)
++{
++ return driver_register(&ep93xx_pcmcia_driver);
++}
++
++static void __exit ep93xx_pcmcia_exit(void)
++{
++ driver_unregister(&ep93xx_pcmcia_driver);
++}
++
++module_init(ep93xx_pcmcia_init);
++module_exit(ep93xx_pcmcia_exit);
++
++MODULE_AUTHOR("Robert Whaley (whaley@applieddata.net)");
++MODULE_DESCRIPTION("Linux PCMCIA Card Services: EP93xx core socket driver");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/pcmcia/ep93xx_edb9315.c b/drivers/pcmcia/ep93xx_edb9315.c
+new file mode 100644
+index 0000000..519fc8d
+--- /dev/null
++++ b/drivers/pcmcia/ep93xx_edb9315.c
+@@ -0,0 +1,283 @@
++/*
++ * linux/drivers/pcmcia/ep93xx_edb9315.c
++ *
++ * Adapted from pxa27x_mainstone.c
++ *
++ * Edb9315 PCMCIA specific routines.
++ *
++ * Created: May 12, 2004
++ * Author: Nicolas Pitre
++ * Copyright: MontaVista Software Inc.
++ *
++ * 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/kernel.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/device.h>
++
++#include <pcmcia/ss.h>
++
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++
++#include <asm/arch/edb9315.h>
++
++#include "soc_common.h"
++
++static struct pcmcia_irqs irqs[] = {
++ { 0, IRQ_GPIO1, "CF CD1" },
++ { 0, IRQ_GPIO2, "CF CD2" },
++ { 0, IRQ_GPIO3, "CF STSCHG/BVD1" },
++ { 0, IRQ_GPIO4, "CF SPKR/BVD2" },
++};
++
++
++static int edb9315_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
++{
++ int rtn;
++
++ if (skt->nr == 0)
++ return -ENXIO;
++
++ skt->irq = IRQ_GPIO6;
++
++ rtn = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
++
++ /* enable GPIO6 as interrupt */
++ writel(0x40, GPIO_INTEN);
++
++ /* enable GPIO1-4 and 6 as interrupt */
++ /* Note: 1-4 need to be edge triggered, but
++ then the irq vectors need to hit GPIOxEIO
++ which they don't currently do - no big deal
++ since CD and BVD are polled anyway */
++ /* writel(0x5e, GPIO_INTEN); */
++
++ return rtn;
++}
++
++static void edb9315_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
++{
++ soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
++}
++
++static void edb9315_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
++ struct pcmcia_state *state)
++{
++ unsigned long status;
++
++ status = inl(GPIO_PFDR);
++
++ state->detect = (status & PCMCIA_DETECT) ? 0 : 1;
++ state->ready = (status & PCMCIA_READY) ? 1 : 0;
++ state->bvd1 = (status & PCMCIA_BVD1) ? 1 : 0;
++ state->bvd2 = (status & PCMCIA_BVD2) ? 1 : 0;
++ state->vs_3v = (status & PCMCIA_VS_3V) ? 0 : 1;
++ state->vs_Xv = (status & PCMCIA_VS_XV) ? 0 : 1;
++ state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1;
++
++// printk("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state));
++}
++
++/*
++ * We bit-bang the pcmcia power controller using this function.
++ */
++static void ep93xx_bitbang( unsigned long ulNewEEValue )
++{
++ unsigned long ulGdata;
++
++ ulGdata = inl( GPIO_PGDR );
++
++ ulGdata &= ~(GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0);
++
++ ulNewEEValue &= (GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0);
++
++ ulGdata |= ulNewEEValue;
++
++ outl( ulGdata, GPIO_PGDR );
++ ulGdata = inl( GPIO_PGDR ); // read to push write out wrapper
++
++ // Voltage controller's data sheet says minimum pulse width is
++ // one microsecond.
++ udelay(5);
++}
++
++static int
++ep93xx_set_voltage( u_short sock, u_char NewVcc )
++{
++ struct socket_info_t * skt = &socket_info[sock];
++ unsigned long ulSwitchSettings, ulDataBit, ulGdirection;
++ int i;
++
++ if (sock >= EP93XX_MAX_SOCK)
++ return -EINVAL;
++
++ if( skt->Vcc == NewVcc ){
++ DEBUG(3, "Power already set to %d\n", NewVcc );
++ return 0;
++ }
++
++ ulSwitchSettings = EE_ADDRESS | ENABLE;
++ switch( NewVcc )
++ {
++ case 0:
++ DEBUG(3, "Configure the socket for 0 Volts\n");
++ ulSwitchSettings |= AVCC_0V;
++ break;
++
++ case 50:
++ ulSwitchSettings |= AVCC_5V;
++ DEBUG(3, "Configure the socket for 5 Volts\n");
++ break;
++
++ case 33:
++ DEBUG(3, "Configure the socket for 3.3 Volts\n");
++ ulSwitchSettings |= AVCC_33V;
++ break;
++
++ default:
++ printk(KERN_ERR "%s(): unrecognized Vcc %u\n", __FUNCTION__,
++ NewVcc);
++ return -1;
++ }
++
++ //
++ // Configure the proper GPIO pins as outputs.
++ //
++ ep93xx_bitbang( GPIOA_EECLK | GPIOA_EEDAT );
++
++ //
++ // Read modify write the data direction register, set the
++ // proper lines to be outputs.
++ //
++ ulGdirection = inl( GPIO_PGDDR );
++ ulGdirection |= GPIOA_EECLK | GPIOA_EEDAT | GPIOA_SLA0;
++ outl( ulGdirection, GPIO_PGDDR );
++ ulGdirection = inl( GPIO_PGDDR ); // read to push write out wrapper
++
++ //
++ // Clear all except EECLK
++ // Lower the clock.
++ //
++ ep93xx_bitbang( GPIOA_EECLK );
++ ep93xx_bitbang( 0 );
++
++ //
++ // Serial shift the command word out to the voltage controller.
++ //
++ for( i=18 ; i>=0 ; --i )
++ {
++ if( (ulSwitchSettings >> i) & 0x1 )
++ ulDataBit = GPIOA_EEDAT;
++ else
++ ulDataBit = 0;
++
++ //
++ // Put the data on the bus and lower the clock.
++ // Raise the clock to latch the data in.
++ // Lower the clock again.
++ //
++ ep93xx_bitbang( ulDataBit );
++ ep93xx_bitbang( ulDataBit | GPIOA_EECLK );
++ ep93xx_bitbang( ulDataBit );
++ }
++
++ //
++ // Raise and lower the Latch.
++ // Raise EECLK, delay, raise EEDAT, leave them that way.
++ //
++ ep93xx_bitbang( GPIOA_SLA0 );
++ ep93xx_bitbang( 0 );
++ ep93xx_bitbang( GPIOA_EECLK );
++ ep93xx_bitbang( GPIOA_EECLK | GPIOA_EEDAT );
++
++ skt->Vcc = NewVcc;
++
++ DEBUG(3, "ep93xx_set_voltage - exit\n");
++
++ return 0;
++}
++
++static int edb9315_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
++ const socket_state_t *state)
++{
++ unsigned long clrbits = 0, setbits = 0, cr0;
++ int ret = 0;
++
++ ep93xx_set_voltage(skt->nr, state->Vxx);
++
++ if (!ret && skt->nr == 0) {
++
++ if (state->flags & SS_RESET) {
++ /* see EP93xx User's Guide */
++ writel(0x15, PCMCIACNT);
++ } else {
++ /* CF mode - BIT1 for PCMCIA mode */
++ writel(0x11, PCMCIACNT);
++ }
++ }
++
++ return ret;
++}
++
++static void edb9315_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
++{
++}
++
++static void edb9315_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
++{
++}
++
++static struct pcmcia_low_level edb9315_pcmcia_ops = {
++ .owner = THIS_MODULE,
++ .hw_init = edb9315_pcmcia_hw_init,
++ .hw_shutdown = edb9315_pcmcia_hw_shutdown,
++ .socket_state = edb9315_pcmcia_socket_state,
++ .configure_socket = edb9315_pcmcia_configure_socket,
++ .socket_init = edb9315_pcmcia_socket_init,
++ .socket_suspend = edb9315_pcmcia_socket_suspend,
++ .nr = 1,
++};
++
++static struct platform_device *edb9315_pcmcia_device;
++
++static int __init edb9315_pcmcia_init(void)
++{
++ int ret;
++
++ edb9315_pcmcia_device = kmalloc(sizeof(*edb9315_pcmcia_device), GFP_KERNEL);
++ if (!edb9315_pcmcia_device)
++ return -ENOMEM;
++ memset(edb9315_pcmcia_device, 0, sizeof(*edb9315_pcmcia_device));
++ edb9315_pcmcia_device->name = "ep93xx-pcmcia";
++ edb9315_pcmcia_device->dev.platform_data = &edb9315_pcmcia_ops;
++
++ ret = platform_device_register(edb9315_pcmcia_device);
++ if (ret)
++ kfree(edb9315_pcmcia_device);
++
++ return ret;
++}
++
++static void __exit edb9315_pcmcia_exit(void)
++{
++ /*
++ * This call is supposed to free our edb9315_pcmcia_device.
++ * Unfortunately platform_device don't have a free method, and
++ * we can't assume it's free of any reference at this point so we
++ * can't free it either.
++ */
++ platform_device_unregister(edb9315_pcmcia_device);
++}
++
++module_init(edb9315_pcmcia_init);
++module_exit(edb9315_pcmcia_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/pcmcia/ep93xx_zefeerevbh.c b/drivers/pcmcia/ep93xx_zefeerevbh.c
+new file mode 100644
+index 0000000..44d44ed
+--- /dev/null
++++ b/drivers/pcmcia/ep93xx_zefeerevbh.c
+@@ -0,0 +1,175 @@
++/*
++ * linux/drivers/pcmcia/ep93xx_zefeerevbh.c
++ *
++ * Adapted from ep93xx_zefeerevbh.c
++ *
++ *
++ * ZefeerEVB-H PCMCIA specific routines.
++ *
++ * Copyright: DAVE Srl <www.dave-tech.it>
++ *
++ * 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/kernel.h>
++#include <linux/errno.h>
++#include <linux/interrupt.h>
++#include <linux/device.h>
++
++#include <pcmcia/ss.h>
++
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <asm/irq.h>
++
++#include <asm/arch/zefeerevb.h>
++
++#include "soc_common.h"
++
++#if 0
++#define DPRINTK(fmt, args...) printk( "[%s:] \n" fmt, __FUNCTION__, ## args)
++#else
++#define DPRINTK(fmt, args...)
++#endif
++
++static struct pcmcia_irqs irqs[] = {
++ { 0, IRQ_GPIO1, "CF CD1" },
++ { 0, IRQ_GPIO2, "CF CD2" },
++ { 0, IRQ_GPIO3, "CF STSCHG/BVD1" },
++ { 0, IRQ_GPIO4, "CF SPKR/BVD2" },
++};
++
++
++static int zefeerevbh_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
++{
++ int rtn;
++ unsigned long tmp;
++
++ if (skt->nr != 0)
++ return -ENXIO;
++
++ /* Set interrupt lines as input */
++ tmp = readl(GPIO_PFDDR);
++ tmp = (tmp & (~((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 6))));
++ writel(tmp, GPIO_PFDDR);
++
++ skt->irq = IRQ_GPIO6;
++
++ rtn = soc_pcmcia_request_irqs(skt, irqs, ARRAY_SIZE(irqs));
++
++ /* enable GPIO6 as interrupt */
++ writel(0x40, GPIO_INTEN);
++
++ /* enable GPIO1-4 and 6 as interrupt */
++ /* Note: 1-4 need to be edge triggered, but
++ then the irq vectors need to hit GPIOxEIO
++ which they don't currently do - no big deal
++ since CD and BVD are polled anyway */
++ /* writel(0x5e, GPIO_INTEN); */
++
++ return rtn;
++}
++
++static void zefeerevbh_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
++{
++ soc_pcmcia_free_irqs(skt, irqs, ARRAY_SIZE(irqs));
++}
++
++static void zefeerevbh_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
++ struct pcmcia_state *state)
++{
++ unsigned long status;
++
++ status = inl(GPIO_PFDR);
++
++ state->detect = (status & PCMCIA_DETECT) ? 0 : 1;
++ state->ready = (status & PCMCIA_READY) ? 1 : 0;
++ state->bvd1 = (status & PCMCIA_BVD1) ? 1 : 0;
++ state->bvd2 = (status & PCMCIA_BVD2) ? 1 : 0;
++ state->vs_3v = (status & PCMCIA_VS_3V) ? 0 : 1;
++ state->vs_Xv = (status & PCMCIA_VS_XV) ? 0 : 1;
++ state->wrprot = (status & PCMCIA_WRPROT) ? 0 : 1;
++
++ DPRINTK("%s: nr: %d, status: %#x, state: %#x\n", __FUNCTION__, skt->nr, status, *((unsigned char *) state));
++}
++
++static int zefeerevbh_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
++ const socket_state_t *state)
++{
++
++ printk(KERN_INFO "[%s]: Vcc = %u, Vpp = %u\n", __FUNCTION__, state->Vcc, state->Vpp);
++
++ /* By default power handling is managed by external controller automatically */
++
++ if (skt->nr == 0) {
++ if (state->flags & SS_RESET) {
++ /* see EP93xx User's Guide */
++ writel(0x15, PCMCIACNT);
++ } else {
++ /* CF mode - BIT1 for PCMCIA mode */
++ writel(0x11, PCMCIACNT);
++ }
++ }
++
++
++ return 0;
++}
++
++static void zefeerevbh_pcmcia_socket_init(struct soc_pcmcia_socket *skt)
++{
++}
++
++static void zefeerevbh_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
++{
++}
++
++static struct pcmcia_low_level zefeerevbh_pcmcia_ops = {
++ .owner = THIS_MODULE,
++ .hw_init = zefeerevbh_pcmcia_hw_init,
++ .hw_shutdown = zefeerevbh_pcmcia_hw_shutdown,
++ .socket_state = zefeerevbh_pcmcia_socket_state,
++ .configure_socket = zefeerevbh_pcmcia_configure_socket,
++ .socket_init = zefeerevbh_pcmcia_socket_init,
++ .socket_suspend = zefeerevbh_pcmcia_socket_suspend,
++ .nr = 1,
++};
++
++static struct platform_device *zefeerevbh_pcmcia_device;
++
++static int __init zefeerevbh_pcmcia_init(void)
++{
++ int ret;
++
++ zefeerevbh_pcmcia_device = kmalloc(sizeof(*zefeerevbh_pcmcia_device), GFP_KERNEL);
++ if (!zefeerevbh_pcmcia_device)
++ return -ENOMEM;
++ memset(zefeerevbh_pcmcia_device, 0, sizeof(*zefeerevbh_pcmcia_device));
++ zefeerevbh_pcmcia_device->name = "ep93xx-pcmcia";
++ zefeerevbh_pcmcia_device->dev.platform_data = &zefeerevbh_pcmcia_ops;
++
++ ret = platform_device_register(zefeerevbh_pcmcia_device);
++ if (ret)
++ kfree(zefeerevbh_pcmcia_device);
++
++ return ret;
++}
++
++static void __exit zefeerevbh_pcmcia_exit(void)
++{
++ /*
++ * This call is supposed to free our zefeerevbh_pcmcia_device.
++ * Unfortunately platform_device don't have a free method, and
++ * we can't assume it's free of any reference at this point so we
++ * can't free it either.
++ */
++ platform_device_unregister(zefeerevbh_pcmcia_device);
++}
++
++module_init(zefeerevbh_pcmcia_init);
++module_exit(zefeerevbh_pcmcia_exit);
++
++MODULE_LICENSE("GPL");
+diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
+index 812bae6..15bfa5d 100644
+--- a/drivers/serial/Kconfig
++++ b/drivers/serial/Kconfig
+@@ -289,6 +289,25 @@ config SERIAL_CLPS711X_CONSOLE
+ your boot loader (lilo or loadlin) about how to pass options to the
+ kernel at boot time.)
+
++config SERIAL_EP93XX
++ tristate "EP93XX serial port support"
++ depends on ARM && ARCH_EP93XX
++ select SERIAL_CORE
++ help
++ Support for the serial ports included in the EP93xx CPU SOC.
++
++config SERIAL_EP93XX_CONSOLE
++ bool "Support for console on EP93XX serial port"
++ depends on SERIAL_EP93XX=y
++ select SERIAL_CORE_CONSOLE
++ help
++ Even if you say Y here, the currently visible virtual console
++ (/dev/tty0) will still be used as the system console by default, but
++ you can alter that using a kernel command line option such as
++ "console=ttyCL1". (Try "man bootparam" or see the documentation of
++ your boot loader (lilo or loadlin) about how to pass options to the
++ kernel at boot time.)
++
+ config SERIAL_S3C2410
+ tristate "Samsung S3C2410 Serial port support"
+ depends on ARM && ARCH_S3C2410
+diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
+index d7c7c71..ef074dc 100644
+--- a/drivers/serial/Makefile
++++ b/drivers/serial/Makefile
+@@ -26,6 +26,7 @@ obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250
+ obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o
+ obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o
+ obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o
++obj-$(CONFIG_SERIAL_EP93XX) += ep93xx.o
+ obj-$(CONFIG_SERIAL_PXA) += pxa.o
+ obj-$(CONFIG_SERIAL_SA1100) += sa1100.o
+ obj-$(CONFIG_SERIAL_S3C2410) += s3c2410.o
+diff --git a/drivers/serial/ep93xx.c b/drivers/serial/ep93xx.c
+new file mode 100644
+index 0000000..60f91a6
+--- /dev/null
++++ b/drivers/serial/ep93xx.c
+@@ -0,0 +1,863 @@
++/*
++ * drivers/serial/ep93xx.c
++ *
++ * Driver for EP93xx serial ports
++ *
++ * Based on drivers/serial/amba-pl011.c
++ *
++ * Copyright 1999 ARM Limited
++ * Copyright (C) 2000 Deep Blue Solutions Ltd.
++ * Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * 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
++ *
++ * $Id: ep93xx.c,v 1.42 2002/07/28 10:03:28 rmk Exp $
++ *
++ */
++
++/* todo:
++ * - correct major/minor numbers
++ * - implement request/release/verify port
++ * - from /dev/ttyAM0, 'stty -F /dev/ttyAM1 57600' not working right.
++ * looks like it changes the divisor, but it gets changed back as
++ * soon as you enter a char on /dev/ttyAM1.
++ * - do not enable modem status ints unless HW is setup
++ * - do not return modem status unless HW is setup
++ * - figure out a nice way to handle CL0 HDLC/modem, CL1 SIR IrDA,
++ * and CL2 HDLC/RS485
++ * - UART DMA operation?
++ * - handle icount fields rng and buf_overrun?
++ */
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/tty.h>
++#include <linux/device.h>
++#include <linux/sysrq.h>
++#include <linux/console.h>
++#include <linux/serial.h>
++
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/hardware/amba.h>
++#include <asm/arch/hardware.h>
++#include <asm/arch/clocks.h>
++
++#if defined(CONFIG_SERIAL_EP93XX_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
++#define SUPPORT_SYSRQ
++#endif
++
++#include <linux/serial_core.h>
++
++#if defined(CONFIG_ARCH_EP9312) || defined(CONFIG_ARCH_EP9315)
++#define UART_NR 3
++#else
++#define UART_NR 2
++#endif
++
++#define SERIAL_EP93XX_MAJOR 204
++#define SERIAL_EP93XX_MINOR 16
++
++#define ISR_PASS_LIMIT 256
++
++#define REG(port,name) ((port)->membase + (name) - EP93XX_APB_BASE - UART1_OFFSET)
++
++#define UARTDR(port) REG(port,UART1DR)
++#define UARTCR(port) REG(port,UART1CR)
++#define UARTFR(port) REG(port,UART1FR)
++#define UARTRSR(port) REG(port,UART1RSR)
++#define UARTECR(port) REG(port,UART1ECR)
++#define UARTMCR(port) REG(port,UART1MCR)
++#define UARTMSR(port) REG(port,UART1MSR)
++#define UARTIIR(port) REG(port,UART1IIR)
++#define UARTICR(port) REG(port,UART1ICR)
++#define UARTLCH(port) REG(port,UART1CR_H)
++#define UARTLCM(port) REG(port,UART1CR_M)
++#define UARTLCL(port) REG(port,UART1CR_L)
++
++#define UARTRSR_CREAD 0x100
++
++static void enable_clocks(struct uart_port *port)
++{
++ unsigned int devcfg = readl(SYSCON_DEVCFG);
++
++ switch (port->line) {
++ case 0:
++ devcfg |= SYSCON_DEVCFG_U1EN;
++ devcfg &= ~SYSCON_DEVCFG_MonG; /* handle this better... */
++ break;
++ case 1:
++ devcfg |= SYSCON_DEVCFG_U2EN;
++ break;
++ case 2:
++ devcfg |= SYSCON_DEVCFG_U3EN;
++ break;
++ }
++
++ SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(devcfg));
++}
++
++static void disable_clocks(struct uart_port *port)
++{
++ unsigned int devcfg = readl(SYSCON_DEVCFG);
++
++ switch (port->line) {
++ case 0:
++ devcfg &= ~SYSCON_DEVCFG_U1EN;
++ break;
++ case 1:
++ devcfg &= ~SYSCON_DEVCFG_U2EN;
++ break;
++ case 2:
++ devcfg &= ~SYSCON_DEVCFG_U3EN;
++ break;
++ }
++
++ SysconSetLocked(SYSCON_DEVCFG, ep93xx_SYSCON_DEVCFG(devcfg));
++}
++
++static int is_port_enabled(struct uart_port *port)
++{
++ unsigned int devcfg = readl(SYSCON_DEVCFG);
++
++ switch (port->line) {
++ case 0:
++ devcfg &= SYSCON_DEVCFG_U1EN;
++ break;
++ case 1:
++ devcfg &= SYSCON_DEVCFG_U2EN;
++ break;
++ case 2:
++ devcfg &= SYSCON_DEVCFG_U3EN;
++ break;
++ }
++
++ return devcfg ? 1 : 0;
++}
++
++static void ep93xxuart_stop_tx(struct uart_port *port)
++{
++ unsigned long cr = readl(UARTCR(port));
++ cr &= ~UARTCR_TIE;
++ writel(cr, UARTCR(port));
++}
++
++static void ep93xxuart_start_tx(struct uart_port *port)
++{
++ unsigned long cr = readl(UARTCR(port));
++ cr |= UARTCR_TIE;
++ writel(cr, UARTCR(port));
++}
++
++static void ep93xxuart_stop_rx(struct uart_port *port)
++{
++ unsigned long cr = readl(UARTCR(port));
++ cr &= ~(UARTCR_RIE | UARTCR_RTIE);
++ writel(cr, UARTCR(port));
++}
++
++static void ep93xxuart_enable_ms(struct uart_port *port)
++{
++ /* fixme: add an ms mask to a wrapper port struct */
++ if (port->line == 0) {
++ unsigned long cr = readl(UARTCR(port));
++ cr |= UARTCR_MSIE;
++ writel(cr, UARTCR(port));
++ }
++}
++
++#ifdef SUPPORT_SYSRQ
++static void ep93xxuart_rx_chars(struct uart_port *port, struct pt_regs *regs)
++#else
++static void ep93xxuart_rx_chars(struct uart_port *port)
++#endif
++{
++ struct tty_struct *tty = port->info->tty;
++ unsigned long fifo, chr, stat, flg;
++ unsigned int count = 256;
++
++ fifo = readl(UARTFR(port));
++ while (((fifo & UARTFR_RXFE) == 0) && count--) {
++
++ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
++ tty->flip.work.func((void *)tty);
++ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
++ printk(KERN_WARNING "TTY_DONT_FLIP set\n");
++ return;
++ }
++ }
++
++ chr = readl(UARTDR(port));
++ flg = TTY_NORMAL;
++
++ port->icount.rx++;
++
++ stat = readl(UARTRSR(port)) | UARTRSR_CREAD;
++
++ if (stat & (UARTRSR_FE | UARTRSR_PE | UARTRSR_OE | UARTRSR_BE)) {
++
++ writel(0, UARTECR(port));
++
++ if (stat & UARTRSR_BE) {
++ stat &= ~(UARTRSR_PE | UARTRSR_FE);
++ port->icount.brk++;
++ if (uart_handle_break(port))
++ goto ignore_char;
++ } else if (stat & UARTRSR_PE) {
++ port->icount.parity++;
++ } else if (stat & UARTRSR_FE) {
++ port->icount.frame++;
++ }
++
++ if (stat & UARTRSR_OE)
++ port->icount.overrun++;
++
++ stat &= port->read_status_mask;
++
++ if (stat & UARTRSR_BE)
++ flg = TTY_BREAK;
++ else if (stat & UARTRSR_PE)
++ flg = TTY_PARITY;
++ else if (stat & UARTRSR_FE)
++ flg = TTY_FRAME;
++ }
++
++ if (uart_handle_sysrq_char(port, chr, regs))
++ goto ignore_char;
++
++ if ((stat & port->ignore_status_mask) == 0) {
++ *tty->flip.flag_buf_ptr++ = flg;
++ *tty->flip.char_buf_ptr++ = chr;
++ tty->flip.count++;
++ }
++
++ if ((stat & UARTRSR_OE) && tty->flip.count < TTY_FLIPBUF_SIZE) {
++ *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
++ *tty->flip.char_buf_ptr++ = 0;
++ tty->flip.count++;
++ }
++
++ ignore_char:
++ fifo = readl(UARTFR(port));
++ }
++ tty_flip_buffer_push(tty);
++}
++
++static void ep93xxuart_tx_chars(struct uart_port *port)
++{
++ struct circ_buf *xmit = &port->info->xmit;
++ int count;
++
++ if (port->x_char) {
++ writel(port->x_char, UARTDR(port));
++ port->icount.tx++;
++ port->x_char = 0;
++ return;
++ }
++ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
++ ep93xxuart_stop_tx(port);
++ return;
++ }
++
++ count = port->fifosize >> 1;
++ do {
++ writel(xmit->buf[xmit->tail], UARTDR(port));
++ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
++ port->icount.tx++;
++ if (uart_circ_empty(xmit))
++ break;
++ } while (--count > 0);
++
++ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
++ uart_write_wakeup(port);
++
++ if (uart_circ_empty(xmit))
++ ep93xxuart_stop_tx(port);
++}
++
++static void ep93xxuart_modem_status(struct uart_port *port)
++{
++ unsigned int status = readl(UARTFR(port));
++
++ writel(0, UARTICR(port));
++
++ if (status & UARTMSR_DDCD)
++ uart_handle_dcd_change(port, status & UARTMSR_DCD);
++
++ if (status & UARTMSR_DDSR)
++ port->icount.dsr++;
++
++ if (status & UARTMSR_DCTS)
++ uart_handle_cts_change(port, status & UARTMSR_CTS);
++
++ if (status & (UARTMSR_DDCD | UARTMSR_DDSR | UARTMSR_DCTS))
++ wake_up_interruptible(&port->info->delta_msr_wait);
++}
++
++static irqreturn_t ep93xxuart_int(int irq, void *dev_id, struct pt_regs *regs)
++{
++ struct uart_port *port = dev_id;
++ unsigned int pass_counter = ISR_PASS_LIMIT;
++ int handled = 0;
++ unsigned long iir;
++
++ spin_lock(&port->lock);
++
++ iir = readl(UARTIIR(port));
++
++ if (iir) {
++ do {
++ if (iir & (UARTIIR_RIS | UARTIIR_RTIS))
++#ifdef SUPPORT_SYSRQ
++ ep93xxuart_rx_chars(port, regs);
++#else
++ ep93xxuart_rx_chars(port);
++#endif
++ if (iir & UARTIIR_TIS)
++ ep93xxuart_tx_chars(port);
++ if (iir & UARTIIR_MIS)
++ ep93xxuart_modem_status(port);
++
++ if (pass_counter-- == 0)
++ break;
++
++ iir = readl(UARTIIR(port));
++
++ } while (iir &
++ (UARTIIR_RIS | UARTIIR_RTIS | UARTIIR_TIS |
++ UARTIIR_MIS));
++ handled = 1;
++ }
++
++ spin_unlock(&port->lock);
++
++ return IRQ_RETVAL(handled);
++}
++
++static unsigned int ep93xxuart_tx_empty(struct uart_port *port)
++{
++ unsigned long status = readl(UARTFR(port));
++ return status & UARTFR_TXFE ? 0 : TIOCSER_TEMT; /* FIXME: klaus used UARTFR_BUSY? */
++}
++
++static unsigned int ep93xxuart_get_mctrl(struct uart_port *port)
++{
++ unsigned int result = 0;
++
++ /* fixme: use a wrapper struct w/ ms flags */
++ if (port->line == 0) {
++ unsigned int msr = readl(UARTMSR(port));
++ if (msr & UARTMSR_CTS)
++ result |= TIOCM_CTS;
++ if (msr & UARTMSR_DSR)
++ result |= TIOCM_DSR;
++ if (msr & UARTMSR_RI)
++ result |= TIOCM_RI;
++ if (msr & UARTMSR_DCD)
++ result |= TIOCM_CAR;
++ }
++ return result;
++}
++
++static void ep93xxuart_set_mctrl(struct uart_port *port, unsigned int mctrl)
++{
++ unsigned long mcr;
++
++ if (port->line == 0) {
++ mcr = readl(UARTMCR(port));
++ if (mctrl & TIOCM_RTS)
++ mcr |= UARTMCR_RTS;
++ else
++ mcr &= ~UARTMCR_RTS;
++ if (mctrl & TIOCM_DTR)
++ mcr |= UARTMCR_DTR;
++ else
++ mcr &= ~UARTMCR_DTR;
++ if (mctrl & TIOCM_OUT1)
++ mcr |= UARTMCR_OUT1;
++ else
++ mcr &= ~UARTMCR_OUT1;
++ if (mctrl & TIOCM_OUT2)
++ mcr |= UARTMCR_OUT2;
++ else
++ mcr &= ~UARTMCR_OUT2;
++ writel(mcr, UARTMCR(port));
++ }
++}
++
++/* FIXME: klaus grabbed the &port->lock spinlock here.. */
++static void ep93xxuart_break_ctl(struct uart_port *port, int break_state)
++{
++ unsigned long lch;
++
++ lch = readl(UARTLCH(port));
++ if (break_state)
++ lch |= UARTLCR_H_BRK;
++ else
++ lch &= ~UARTLCR_H_BRK;
++ writel(lch, UARTLCH(port));
++}
++
++static int ep93xxuart_startup(struct uart_port *port)
++{
++ unsigned int uartcr;
++ int retval;
++
++ retval = request_irq(port->irq, ep93xxuart_int, 0, "ep93xxuart", port);
++ if (retval)
++ return retval;
++
++ enable_clocks(port);
++
++ uartcr = readl(UARTCR(port));
++ uartcr |= UARTCR_UARTE | UARTCR_RIE | UARTCR_RTIE;
++ uartcr &= ~0x6;
++ writel(uartcr, UARTCR(port));
++
++ return 0;
++}
++
++static void ep93xxuart_shutdown(struct uart_port *port)
++{
++ unsigned int uartcr;
++ unsigned int linectl;
++
++ linectl = readl(UARTLCH(port));
++ linectl &= ~(UARTLCR_H_FEN | UARTLCR_H_BRK);
++ writel(linectl, UARTLCH(port));
++
++ uartcr = readl(UARTCR(port));
++ uartcr &= ~(UARTCR_UARTE | UARTCR_RIE | UARTCR_RTIE | UARTCR_TIE);
++ writel(uartcr, UARTCR(port));
++
++ disable_clocks(port);
++
++ free_irq(port->irq, port);
++}
++
++static void
++ep93xxuart_set_termios(struct uart_port *port, struct termios *termios,
++ struct termios *old)
++{
++ unsigned int baud, quot;
++ unsigned long flags;
++ unsigned long lch;
++
++ /* wait for fifo to drain.. is this needed? upper level should handle it.. */
++ if (is_port_enabled(port))
++ do {
++ flags = readl(UARTFR(port));
++ } while (flags & UARTFR_BUSY);
++
++ baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16);
++ quot = uart_get_divisor(port, baud);
++
++ switch (termios->c_cflag & CSIZE) {
++ case CS5:
++ lch = UARTLCR_H_WLEN_5_DATA;
++ break;
++ case CS6:
++ lch = UARTLCR_H_WLEN_6_DATA;
++ break;
++ case CS7:
++ lch = UARTLCR_H_WLEN_7_DATA;
++ break;
++ default:
++ lch = UARTLCR_H_WLEN_8_DATA;
++ break;
++ }
++
++ if (termios->c_cflag & CSTOPB)
++ lch |= UARTLCR_H_STP2;
++
++ if (termios->c_cflag & PARENB) {
++ lch |= UARTLCR_H_PEN;
++ if (!(termios->c_cflag & PARODD))
++ lch |= UARTLCR_H_EPS;
++ }
++
++ if (port->fifosize > 1)
++ lch |= UARTLCR_H_FEN;
++
++ spin_lock_irqsave(&port->lock, flags);
++
++ lch |= readl(UARTLCH(port)) & UARTLCR_H_BRK;
++
++ uart_update_timeout(port, termios->c_cflag, baud);
++
++ port->read_status_mask = UARTRSR_OE;
++ if (termios->c_iflag & INPCK)
++ port->read_status_mask |= UARTRSR_FE | UARTRSR_PE;
++ if (termios->c_iflag & (BRKINT | PARMRK))
++ port->read_status_mask |= UARTRSR_BE;
++
++ port->ignore_status_mask = 0;
++ if (termios->c_iflag & IGNPAR)
++ port->ignore_status_mask |= UARTRSR_FE | UARTRSR_PE;
++ if (termios->c_iflag & IGNBRK) {
++ port->ignore_status_mask |= UARTRSR_BE;
++ if (termios->c_iflag & IGNPAR)
++ port->ignore_status_mask |= UARTRSR_OE;
++ }
++ if ((termios->c_cflag & CREAD) == 0)
++ port->ignore_status_mask |= UARTRSR_CREAD;
++
++ quot -= 1;
++
++ writel(quot & 0xff, UARTLCL(port));
++ writel((quot >> 8) & 0xff, UARTLCM(port));
++ writel(lch, UARTLCH(port));
++
++ spin_unlock_irqrestore(&port->lock, flags);
++}
++
++static const char *ep93xxuart_type(struct uart_port *port)
++{
++ return port->type == PORT_EP93XX ? "uart-ep93xx" : NULL;
++}
++
++static void ep93xxuart_release_port(struct uart_port *port)
++{
++ /* update when we break up static io_desc maps */
++}
++
++static int ep93xxuart_request_port(struct uart_port *port)
++{
++ /* update when we break up static io_desc maps */
++ return 0;
++}
++
++static void ep93xxuart_config_port(struct uart_port *port, int flags)
++{
++ if (flags & UART_CONFIG_TYPE)
++ if (ep93xxuart_request_port(port) == 0)
++ port->type = PORT_EP93XX;
++
++ /* FIXME: handle UART_CONFIG_IRQ? */
++}
++
++static int ep93xxuart_verify_port(struct uart_port *port,
++ struct serial_struct *ser)
++{
++ if (ser->type != PORT_UNKNOWN && ser->type != PORT_EP93XX)
++ return -EINVAL;
++ if (ser->irq < 0 || ser->irq >= NR_IRQS)
++ return -EINVAL;
++ if (ser->baud_base < 9600)
++ return -EINVAL;
++ return 0;
++}
++
++static struct uart_ops ep93xx_pops = {
++ .tx_empty = ep93xxuart_tx_empty,
++ .set_mctrl = ep93xxuart_set_mctrl,
++ .get_mctrl = ep93xxuart_get_mctrl,
++ .stop_tx = ep93xxuart_stop_tx,
++ .start_tx = ep93xxuart_start_tx,
++ .stop_rx = ep93xxuart_stop_rx,
++ .enable_ms = ep93xxuart_enable_ms,
++ .break_ctl = ep93xxuart_break_ctl,
++ .startup = ep93xxuart_startup,
++ .shutdown = ep93xxuart_shutdown,
++ .set_termios = ep93xxuart_set_termios,
++ .type = ep93xxuart_type,
++ .release_port = ep93xxuart_release_port,
++ .request_port = ep93xxuart_request_port,
++ .config_port = ep93xxuart_config_port,
++ .verify_port = ep93xxuart_verify_port,
++};
++
++static struct uart_port ep93xx_ports[UART_NR] = {
++ {
++ .membase = (void *)UART1_BASE,
++ .mapbase = UART1_BASE,
++ .iotype = UPIO_MEM,
++ .irq = IRQ_UART1,
++ .uartclk = EP93XX_UART_CLK,
++ .fifosize = 16,
++ .ops = &ep93xx_pops,
++ .flags = UPF_BOOT_AUTOCONF,
++ },
++ {
++ .membase = (void *)UART2_BASE,
++ .mapbase = UART2_BASE,
++ .iotype = UPIO_MEM,
++ .irq = IRQ_UART2,
++ .uartclk = EP93XX_UART_CLK,
++ .fifosize = 16,
++ .ops = &ep93xx_pops,
++ .line = 1,
++ .flags = UPF_BOOT_AUTOCONF,
++ },
++#if UART_NR > 2
++ {
++ .membase = (void *)UART3_BASE,
++ .mapbase = UART3_BASE,
++ .iotype = UPIO_MEM,
++ .irq = IRQ_UART3,
++ .uartclk = EP93XX_UART_CLK,
++ .fifosize = 16,
++ .ops = &ep93xx_pops,
++ .line = 2,
++ .flags = UPF_BOOT_AUTOCONF,
++ }
++#endif
++};
++
++#ifdef CONFIG_SERIAL_EP93XX_CONSOLE
++/*
++ * Print a string to the serial port trying not to disturb
++ * any possible real use of the port...
++ *
++ * The console_lock must be held when we get here.
++ *
++ * Note that this is called with interrupts already disabled
++ */
++static void
++ep93xxuart_console_write(struct console *co, const char *s, unsigned int count)
++{
++ struct uart_port *port = ep93xx_ports + co->index;
++ unsigned long cr, cr2, fr;
++ int i;
++
++ /*
++ * Ensure that the port is enabled.
++ */
++ cr = readl(UARTCR(port));
++ cr2 = cr & ~(UARTCR_RIE | UARTCR_RTIE | UARTCR_TIE | UARTCR_MSIE);
++ writel((cr2 | UARTCR_UARTE), UARTCR(port));
++
++ /*
++ * Now, do each character
++ */
++ for (i = 0; i < count; i++) {
++ do {
++ fr = readl(UARTFR(port));
++ } while (fr & UARTFR_TXFF);
++ writel(s[i], UARTDR(port));
++ if (s[i] == '\n') {
++ do {
++ fr = readl(UARTFR(port));
++ } while (fr & UARTFR_TXFF);
++ writel('\r', UARTDR(port));
++ }
++ }
++
++ /*
++ * Finally, wait for transmitter to become empty
++ * and restore the uart state.
++ */
++ do {
++ fr = readl(UARTFR(port));
++ } while ((fr & UARTFR_TXFE) == 0);
++
++ writel(cr, UARTCR(port));
++}
++
++static void __init
++ep93xxuart_console_get_options(struct uart_port *port, int *baud,
++ int *parity, int *bits)
++{
++ if (readl(UARTCR(port)) & UARTCR_UARTE) {
++ unsigned long lch, quot;
++
++ lch = readl(UARTLCH(port));
++
++ *parity = 'n';
++ if (lch & UARTLCR_H_PEN) {
++ if (lch & UARTLCR_H_EPS)
++ *parity = 'e';
++ else
++ *parity = 'o';
++ }
++
++ if ((lch & UARTLCR_H_WLEN) == UARTLCR_H_WLEN_7_DATA)
++ *bits = 7;
++ else
++ *bits = 8;
++
++ quot =
++ ((readl(UARTLCM(port)) & 0xff) << 8) | (readl(UARTLCL(port))
++ & 0xff);
++
++ *baud = port->uartclk / (16 * (quot + 1));
++ }
++}
++
++static int __init ep93xxuart_console_setup(struct console *co, char *options)
++{
++ struct uart_port *port;
++ int baud = 57600;
++ int bits = 8;
++ int parity = 'n';
++ int flow = 'n';
++
++ /*
++ * Check whether an invalid uart number has been specified, and
++ * if so, search for the first available port that does have
++ * console support.
++ */
++ port = uart_get_console(ep93xx_ports, UART_NR, co);
++
++ /*
++ * Temporary fix.
++ */
++ spin_lock_init(&port->lock);
++
++ if (options)
++ uart_parse_options(options, &baud, &parity, &bits, &flow);
++ else
++ ep93xxuart_console_get_options(port, &baud, &parity, &bits);
++
++ return uart_set_options(port, co, baud, parity, bits, flow);
++}
++
++extern struct uart_driver ep93xx_reg;
++static struct console ep93xx_console = {
++ .name = "ttyAM",
++ .write = ep93xxuart_console_write,
++ .device = uart_console_device,
++ .setup = ep93xxuart_console_setup,
++ .flags = CON_PRINTBUFFER,
++ .index = -1,
++ .data = &ep93xx_reg,
++};
++
++static int __init ep93xxuart_console_init(void)
++{
++ register_console(&ep93xx_console);
++ return 0;
++}
++
++console_initcall(ep93xxuart_console_init);
++
++#define EP93XX_CONSOLE &ep93xx_console
++#else
++#define EP93XX_CONSOLE NULL
++#endif
++
++static struct uart_driver ep93xx_reg = {
++ .driver_name = "ttyAM",
++ .dev_name = "ttyAM",
++ .major = SERIAL_EP93XX_MAJOR,
++ .minor = SERIAL_EP93XX_MINOR,
++ .nr = UART_NR,
++ .cons = EP93XX_CONSOLE,
++};
++
++static int ep93xxuart_probe(struct amba_device *dev, void *id)
++{
++ int i;
++
++ for (i = 0; i < UART_NR; i++) {
++ if (ep93xx_ports[i].membase != (void *)dev->res.start)
++ continue;
++
++ ep93xx_ports[i].dev = &dev->dev;
++ uart_add_one_port(&ep93xx_reg, &ep93xx_ports[i]);
++ amba_set_drvdata(dev, &ep93xx_ports[i]);
++ break;
++ }
++
++ return 0;
++}
++
++static int ep93xxuart_remove(struct amba_device *dev)
++{
++ struct uart_port *p = amba_get_drvdata(dev);
++
++ if (p)
++ uart_remove_one_port(&ep93xx_reg, p);
++
++ amba_set_drvdata(dev, NULL);
++
++ return 0;
++}
++
++static int ep93xxuart_suspend(struct amba_device *dev, pm_message_t msg)
++{
++ struct uart_port *p = amba_get_drvdata(dev);
++
++ if (p)
++ uart_suspend_port(&ep93xx_reg, p);
++
++ return 0;
++}
++
++static int ep93xxuart_resume(struct amba_device *dev)
++{
++ struct uart_port *p = amba_get_drvdata(dev);
++
++ if (p)
++ uart_resume_port(&ep93xx_reg, p);
++
++ return 0;
++}
++
++static struct amba_id ep93xxuart_ids[] __initdata = {
++ { /* UART1 */
++ .id = 0x808c0000,
++ .mask = 0xffff0000,
++ },
++ { /* UART2 */
++ .id = 0x808d0000,
++ .mask = 0xffff0000,
++ },
++ { /* UART3 */
++ .id = 0x808e0000,
++ .mask = 0xffff0000,
++ },
++ {0, 0},
++};
++
++static struct amba_driver ep93xxuart_driver = {
++ .drv = {
++ .name = "uart-ep93xx",
++ },
++ .id_table = ep93xxuart_ids,
++ .probe = ep93xxuart_probe,
++ .remove = ep93xxuart_remove,
++ .suspend = ep93xxuart_suspend,
++ .resume = ep93xxuart_resume,
++};
++
++static int __init ep93xxuart_init(void)
++{
++ int ret;
++
++ printk(KERN_INFO "Serial: EP93xx driver $Revision: 1.42 $\n");
++
++ ret = uart_register_driver(&ep93xx_reg);
++ if (ret == 0) {
++ ret = amba_driver_register(&ep93xxuart_driver);
++ if (ret)
++ uart_unregister_driver(&ep93xx_reg);
++ }
++
++ return ret;
++}
++
++static void __exit ep93xxuart_exit(void)
++{
++ amba_driver_unregister(&ep93xxuart_driver);
++ uart_unregister_driver(&ep93xx_reg);
++}
++
++module_init(ep93xxuart_init);
++module_exit(ep93xxuart_exit);
++
++MODULE_AUTHOR("Ray Lehtiniemi");
++MODULE_DESCRIPTION("EP93XX generic serial driver $Revision: 1.42 $");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
+index 85dacc9..e57292f 100644
+--- a/drivers/usb/Kconfig
++++ b/drivers/usb/Kconfig
+@@ -22,6 +22,7 @@ config USB_ARCH_HAS_OHCI
+ default y if ARCH_LH7A404
+ default y if ARCH_S3C2410
+ default y if PXA27x
++ default y if ARCH_EP93XX
+ # PPC:
+ default y if STB03xxx
+ default y if PPC_MPC52xx
+diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
+new file mode 100644
+index 0000000..8aec2fb
+--- /dev/null
++++ b/drivers/usb/host/ohci-ep93xx.c
+@@ -0,0 +1,248 @@
++/*
++ * OHCI HCD (Host Controller Driver) for USB.
++ *
++ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
++ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
++ * (C) Copyright 2002 Hewlett-Packard Company
++ * (C) Copyright 2004 Ray Lehtiniemi
++ *
++ * EP93XX Bus Glue
++ *
++ * Written by Ray Lehtiniemi <rayl@mail.com>
++ * Based on SA-1111 glue.
++ *
++ * This file is licenced under the GPL.
++ */
++
++#include <asm/hardware.h>
++#include <asm/hardware/amba.h>
++
++#ifndef CONFIG_ARCH_EP93XX
++#error "This file is EP93xx bus glue. CONFIG_ARCH_EP93XX must be defined."
++#endif
++
++extern int usb_disabled(void);
++
++
++/*-------------------------------------------------------------------------*/
++
++static void ep93xx_start_hc(struct amba_device *dev)
++{
++ unsigned int pwrcnt;
++
++ printk(KERN_DEBUG __FILE__ ": starting EP93xx OHCI USB Controller\n");
++
++ pwrcnt = readl(SYSCON_PWRCNT);
++ pwrcnt |= SYSCON_PWRCNT_USHEN;
++ writel(pwrcnt, SYSCON_PWRCNT);
++}
++
++static void ep93xx_stop_hc(struct amba_device *dev)
++{
++ unsigned int pwrcnt;
++
++ printk(KERN_DEBUG __FILE__ ": stopping EP93xx OHCI USB Controller\n");
++
++ pwrcnt = readl(SYSCON_PWRCNT);
++ pwrcnt &= ~SYSCON_PWRCNT_USHEN;
++ writel(pwrcnt, SYSCON_PWRCNT);
++}
++
++/*-------------------------------------------------------------------------*/
++
++#if 0
++static void dump_hci_status(struct usb_hcd *hcd, const char *label)
++{
++ unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
++
++ dbg("%s USB_STATUS = { %s%s%s%s%s}", label,
++ ((status & USB_STATUS_IRQHCIRMTWKUP) ? "IRQHCIRMTWKUP " : ""),
++ ((status & USB_STATUS_IRQHCIBUFFACC) ? "IRQHCIBUFFACC " : ""),
++ ((status & USB_STATUS_NIRQHCIM) ? "" : "IRQHCIM "),
++ ((status & USB_STATUS_NHCIMFCLR) ? "" : "HCIMFCLR "),
++ ((status & USB_STATUS_USBPWRSENSE) ? "USBPWRSENSE " : ""));
++}
++#endif
++
++/*-------------------------------------------------------------------------*/
++
++void usb_hcd_ep93xx_remove(struct usb_hcd *, struct amba_device *);
++
++/* configure so an HC device and id are always provided */
++/* always called with process context; sleeping is OK */
++
++/**
++ * usb_hcd_ep93xx_probe - initialize ep93xx HCD
++ * Context: !in_interrupt()
++ *
++ * Allocates basic resources for this USB host controller, and
++ * then invokes the start() method for the HCD associated with it
++ * through the hotplug entry's driver_data.
++ *
++ * Store this function in the HCD's struct pci_driver as probe().
++ */
++int usb_hcd_ep93xx_probe(const struct hc_driver *driver,
++ struct amba_device *dev)
++{
++ int retval;
++ struct usb_hcd *hcd;
++
++ hcd = usb_create_hcd(driver, &dev->dev, "ep93xx");
++
++ if (!hcd)
++ return -ENOMEM;
++
++ hcd->rsrc_start = dev->res.start;
++ hcd->rsrc_len = dev->res.end - dev->res.start + 1;
++
++ hcd->regs = (void __iomem *)dev->res.start;
++
++ ep93xx_start_hc(dev);
++ ohci_hcd_init(hcd_to_ohci(hcd));
++
++ retval = usb_add_hcd(hcd, dev->irq[0], SA_INTERRUPT);
++ if (retval == 0)
++ return retval;
++
++ ep93xx_stop_hc(dev);
++
++ usb_put_hcd(hcd);
++ return retval;
++}
++
++/* may be called without controller electrically present */
++/* may be called with controller, bus, and devices active */
++
++/**
++ * usb_hcd_ep93xx_remove - shutdown processing for SA-1111-based HCDs
++ * @dev: USB Host Controller being removed
++ * Context: !in_interrupt()
++ *
++ * Reverses the effect of usb_hcd_ep93xx_probe(), first invoking
++ * the HCD's stop() method. It is always called from a thread
++ * context, normally "rmmod", "apmd", or something similar.
++ *
++ */
++void usb_hcd_ep93xx_remove(struct usb_hcd *hcd, struct amba_device *dev)
++{
++ usb_remove_hcd(hcd);
++ ep93xx_stop_hc(dev);
++ usb_put_hcd(hcd);
++}
++
++/*-------------------------------------------------------------------------*/
++
++static int __devinit ohci_ep93xx_start(struct usb_hcd *hcd)
++{
++ struct ohci_hcd *ohci = hcd_to_ohci(hcd);
++ int ret;
++
++ ohci_dbg(ohci, "ohci_ep93xx_start, ohci:%p", ohci);
++
++ if ((ret = ohci_init(ohci)) < 0)
++ return ret;
++
++ if ((ret = ohci_run(ohci)) < 0) {
++ err("can't start %s", hcd->self.bus_name);
++ ohci_stop(hcd);
++ return ret;
++ }
++
++ return 0;
++}
++
++/*-------------------------------------------------------------------------*/
++
++static const struct hc_driver ohci_ep93xx_hc_driver = {
++ .description = hcd_name,
++ .product_desc = "EP93xx OHCI",
++ .hcd_priv_size = sizeof(struct ohci_hcd),
++
++ /*
++ * generic hardware linkage
++ */
++ .irq = ohci_irq,
++ .flags = HCD_USB11,
++
++ /*
++ * basic lifecycle operations
++ */
++ .start = ohci_ep93xx_start,
++#ifdef CONFIG_PM
++ /* suspend: ohci_ep93xx_suspend, -- tbd */
++ /* resume: ohci_ep93xx_resume, -- tbd */
++#endif
++ .stop = ohci_stop,
++
++ /*
++ * managing i/o requests and associated device resources
++ */
++ .urb_enqueue = ohci_urb_enqueue,
++ .urb_dequeue = ohci_urb_dequeue,
++ .endpoint_disable = ohci_endpoint_disable,
++
++ /*
++ * scheduling support
++ */
++ .get_frame_number = ohci_get_frame,
++
++ /*
++ * root hub support
++ */
++ .hub_status_data = ohci_hub_status_data,
++ .hub_control = ohci_hub_control,
++};
++
++/*-------------------------------------------------------------------------*/
++
++static int ep93xxohci_probe(struct amba_device *dev, void *id)
++{
++ int ret = -ENODEV;
++
++ if (usb_disabled())
++ return -ENODEV;
++
++ ret = usb_hcd_ep93xx_probe(&ohci_ep93xx_hc_driver, dev);
++
++ return ret;
++}
++
++static int ep93xxohci_remove(struct amba_device *dev)
++{
++ struct usb_hcd *hcd = amba_get_drvdata(dev);
++
++ usb_hcd_ep93xx_remove(hcd, dev);
++
++ return 0;
++}
++
++static struct amba_id ep93xxohci_ids[] __initdata = {
++ {
++ .id = 0x80020000,
++ .mask = 0xffff0000,
++ },
++ {0, 0},
++};
++
++static struct amba_driver ep93xxohci_driver = {
++ .drv = {
++ .name = "ohci-ep93xx",
++ },
++ .id_table = ep93xxohci_ids,
++ .probe = ep93xxohci_probe,
++ .remove = ep93xxohci_remove,
++};
++
++static int __init ep93xxohci_init(void)
++{
++ printk(KERN_INFO "USB: EP93xx driver $Revision: 1.42 $\n");
++ return amba_driver_register(&ep93xxohci_driver);
++}
++
++static void __exit ep93xxohci_cleanup(void)
++{
++ amba_driver_unregister(&ep93xxohci_driver);
++}
++
++module_init(ep93xxohci_init);
++module_exit(ep93xxohci_cleanup);
+diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
+index bf1d9ab..bb525a2 100644
+--- a/drivers/usb/host/ohci-hcd.c
++++ b/drivers/usb/host/ohci-hcd.c
+@@ -909,6 +909,10 @@ MODULE_LICENSE ("GPL");
+ #include "ohci-pxa27x.c"
+ #endif
+
++#ifdef CONFIG_ARCH_EP93XX
++#include "ohci-ep93xx.c"
++#endif
++
+ #ifdef CONFIG_SOC_AU1X00
+ #include "ohci-au1xxx.c"
+ #endif
+@@ -923,6 +927,7 @@ MODULE_LICENSE ("GPL");
+ || defined(CONFIG_ARCH_OMAP) \
+ || defined (CONFIG_ARCH_LH7A404) \
+ || defined (CONFIG_PXA27x) \
++ || defined (CONFIG_ARCH_EP93XX) \
+ || defined (CONFIG_SOC_AU1X00) \
+ || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
+ )
+diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
+index cc8e3bf..1d46ab0 100644
+--- a/drivers/video/Kconfig
++++ b/drivers/video/Kconfig
+@@ -172,6 +172,122 @@ config FB_CLPS711X
+ Say Y to enable the Framebuffer driver for the CLPS7111 and
+ EP7212 processors.
+
++config FB_CX25871_I2C
++ tristate "Conexant CX25871 video encoder"
++ depends on I2C && EXPERIMENTAL
++ help
++
++ ! ! ! B R O K E N B R O K E N B R O K E N ! ! !
++
++ If you say yes here you get support for the Conexant CX25871
++ video encoder. Currently only EP93xx CPUs use this for some
++ NTSC setup. This setup should be done in ep93xxfb.c instead.
++ It is currently hardcoded here in cx25871, which is wrong, as
++ it will happen anytime instead of exactly when it is needed.
++ I've got no NTSC hardware, and no time to test this either.
++
++ Why I've written it then? Well I had to get I2C working and it
++ helped me on my way there.
++
++ If nobody cares about NTSC support for EP93xx it will go away soon!
++
++ Only say Y if you have such a chip and are prepared to fix the remaining
++ stuff yourself.
++
++ See ep93xxfb.[ch] and cx25871.c for details.
++
++ This driver can also be built as a module. If so, the module
++ will be called cx25871.
++
++config FB_EP93XX
++ bool "EP93XX Framebuffer support"
++ depends on FB && ARM && (ARCH_EP9312 || ARCH_EP9315)
++ select FB_CFB_FILLRECT
++ select FB_CFB_COPYAREA
++ select FB_CFB_IMAGEBLIT
++ help
++ Say Y here if you want support for the on EP93XX framebuffer.
++
++ You can also say M here to compile this as a module. However this
++ is not recommended as loading the module without a display can
++ be a problem. (Make sure you can login without display before you
++ say M or N here).
++
++ The module will be called ep93xxfb.
++choice
++ prompt "Display Type"
++ depends on FB_EP93XX
++ help
++ Choose the kind of display you want to attach to the EP93XX framebuffer.
++
++config FB_CRT_EP93XX
++ bool "CRT Display"
++
++config FB_LCD_EP93XX
++ bool "LCD Display"
++ help
++ Support for the Philips 640x480 Display on the EDB93XX evaluation board.
++
++config FB_LCD_EP93XX_SHARP
++ bool "LCD Display 320x200 SHARP"
++ help
++ Support for the Sharp LQ057Q3DC02 320x200 Color TFT LCD.
++
++config FB_LCD_EP93XX_SHARP_LQ64D343
++ bool "LCD Display 640x480 SHARP"
++ help
++ Support for the Sharp LQ64D343 640x480 Color TFT LCD.
++
++config FB_CX25871
++ bool "NTSC Display"
++ select FB_CX25871_I2C
++
++config FB_LCD_TX09D50VM1CCA
++ bool "LCD Display 240x320 Hitachi TX09D50VM1CCA"
++ help
++ Support for the Hitachi TX09D50VM1CCA 240x320 Color TFT LCD.
++
++endchoice
++
++choice
++ prompt "Display Color Depth"
++ depends on FB_EP93XX
++ default FB_EP93XX_8BPP
++ help
++ Choose the default color depth for you EP93xx display. Note that using
++ other than 8BPP depths tends to be slow.
++
++config FB_EP93XX_8BPP
++ bool "8bpp"
++ help
++ Use 8 bits per pixel (256 color).
++ Benefits: fastest available mode
++ Drawback: few colors available (might do for console work, though)
++
++config FB_EP93XX_16BPP_565
++ bool "16bpp_565"
++ help
++ Use 16 bits per pixel. Weighting red:green:blue is 5:6:5 bits.
++ Make sure your Xserver / Framebuffer based applications use exactly this
++ weighting.
++
++config FB_EP93XX_24BPP
++ bool "24bpp"
++ help
++ Use 24 bits per pixel. Weighting red:green:blue is 8:8:8 bits. Say Y here
++ if you want lots of colors and do not care that much about performance.
++
++
++
++config FB_EP93XX_32BPP
++ bool "32bpp"
++ help
++ Use 32 bits per pixel. Weighting transparent:red:green:blue is 8:8:8:8 bits.
++ Note that transparency is seldom implemented so this one is just slower and
++ consumes more memory than 24BPP.
++endchoice
++
++
+ config FB_SA1100
+ bool "SA-1100 LCD support"
+ depends on (FB = y) && ARM && ARCH_SA1100
+diff --git a/drivers/video/Makefile b/drivers/video/Makefile
+index aa434e7..82f680b 100644
+--- a/drivers/video/Makefile
++++ b/drivers/video/Makefile
+@@ -99,6 +99,8 @@ obj-$(CONFIG_FB_S3C2410) += s3c2410fb.
+ obj-$(CONFIG_FB_VESA) += vesafb.o
+ obj-$(CONFIG_FB_VGA16) += vga16fb.o vgastate.o
+ obj-$(CONFIG_FB_OF) += offb.o
++obj-$(CONFIG_FB_EP93XX) += ep93xxfb.o
++obj-$(CONFIG_FB_CX25871_I2C) += cx25871.o
+
+ # the test framebuffer is last
+ obj-$(CONFIG_FB_VIRTUAL) += vfb.o
+diff --git a/drivers/video/cx25871.c b/drivers/video/cx25871.c
+new file mode 100644
+index 0000000..816cbef
+--- /dev/null
++++ b/drivers/video/cx25871.c
+@@ -0,0 +1,200 @@
++/*
++ cx25871.c
++
++ Driver for the Conexant CX25871 VIDEO ENCODER
++
++ based on: ds1621.c
++
++
++
++
++ BIG FAT WARNING: THIS IS EXPERIMENTAL AND UNTESTED CODE
++
++
++
++
++
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++*/
++
++#include <linux/config.h>
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/ioport.h>
++#include <linux/delay.h>
++#include <linux/slab.h>
++#include <linux/i2c.h>
++#include <asm/io.h>
++
++/*
++ * assign an invalid (local use) id for now
++ * TODO: get an official one!
++ */
++#define I2C_DRIVERID_EP93XX 0xffff
++
++/* Addresses to scan */
++static unsigned short normal_i2c[] = { 0x44, I2C_CLIENT_END };
++static unsigned short normal_i2c_range[] = { I2C_CLIENT_END };
++
++I2C_CLIENT_INSMOD;
++
++static int cx25871_attach_adapter(struct i2c_adapter *adapter);
++static int cx25871_detect(struct i2c_adapter *adapter, int address, int kind);
++static void cx25871_init_client(struct i2c_client *client);
++static int cx25871_detach_client(struct i2c_client *client);
++
++/* This is the driver that will be inserted */
++static struct i2c_driver cx25871_driver = {
++ .owner = THIS_MODULE,
++ .name = "cx25871",
++ .id = I2C_DRIVERID_EP93XX,
++ .flags = I2C_DF_NOTIFY,
++ .attach_adapter = cx25871_attach_adapter,
++ .detach_client = cx25871_detach_client,
++};
++
++static int cx25871_id = 0;
++
++/* Cleanup and introduce cx25871 specific data, if necessary */
++struct cx25871_data {
++ struct i2c_client client;
++ struct semaphore update_lock;
++ char valid; /* !=0 if following fields are valid */
++ unsigned long last_updated; /* In jiffies */
++};
++
++static int cx25871_read_value(struct i2c_client *client, u8 reg)
++{
++ return i2c_smbus_read_byte_data(client, reg);
++}
++
++static int cx25871_write_value(struct i2c_client *client, u8 reg, u16 value)
++{
++ return i2c_smbus_write_byte_data(client, reg, value);
++}
++
++static void cx25871_init_client(struct i2c_client *client)
++{
++ /*FIXME: This should be done in ep93xxfb.c, shouldn't it? */
++
++ int _todo__fix_this_ugly_hack_;
++
++ cx25871_write_value(client, 0xB8, 0);
++ mdelay(1000);
++ /* After auto-configuration, setup pseudo-master mode BUT with EN_BLANKO bit cleared */
++ cx25871_write_value(client, 0xBA,
++ CX25871_REGxBA_SLAVER | CX25871_REGxBA_DACOFF);
++ cx25871_write_value(client, 0xC6, (CX25871_REGxC6_INMODE_MASK & 0x3));
++ cx25871_write_value(client, 0xC4, CX25871_REGxC4_EN_OUT);
++ cx25871_write_value(client, 0x32, 0);
++ cx25871_write_value(client, 0xBA, CX25871_REGxBA_SLAVER);
++}
++
++static int cx25871_attach_adapter(struct i2c_adapter *adapter)
++{
++ printk("cx25871_attach_adapter\n");
++ return i2c_probe(adapter, &addr_data, cx25871_detect);
++}
++
++/* This function is called by i2c_detect */
++int cx25871_detect(struct i2c_adapter *adapter, int address, int kind)
++{
++ struct i2c_client *new_client;
++ struct cx25871_data *data;
++ int err = 0;
++
++ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
++ | I2C_FUNC_SMBUS_WRITE_BYTE))
++ goto exit;
++
++ /* OK. For now, we presume we have a valid client. We now create the
++ client structure, even though we cannot fill it completely yet.
++ But it allows us to access cx25871_{read,write}_value. */
++ if (!(data = kmalloc(sizeof(struct cx25871_data), GFP_KERNEL))) {
++ err = -ENOMEM;
++ goto exit;
++ }
++ memset(data, 0, sizeof(struct cx25871_data));
++
++ new_client = &data->client;
++ i2c_set_clientdata(new_client, data);
++ new_client->addr = address;
++ new_client->adapter = adapter;
++ new_client->driver = &cx25871_driver;
++ new_client->flags = 0;
++
++ /* Fill in remaining client fields and put it into the global list */
++ strlcpy(new_client->name, "cx25871", I2C_NAME_SIZE);
++
++ new_client->id = cx25871_id++;
++ data->valid = 0;
++ init_MUTEX(&data->update_lock);
++
++ /* Tell the I2C layer a new client has arrived */
++ if ((err = i2c_attach_client(new_client)))
++ goto exit_free;
++ /* Initialize the EP93XX chip */
++ cx25871_init_client(new_client);
++
++/* Register sysfs hooks */
++#if 0
++ device_create_file(&new_client->dev, &dev_attr_alarms);
++ device_create_file(&new_client->dev, &dev_attr_temp1_input);
++ device_create_file(&new_client->dev, &dev_attr_temp1_min);
++ device_create_file(&new_client->dev, &dev_attr_temp1_max);
++#endif
++ return 0;
++
++/* OK, this is not exactly good programming practice, usually. But it is
++ very code-efficient in this case. */
++ exit_free:
++ kfree(data);
++ exit:
++ return err;
++}
++
++static int cx25871_detach_client(struct i2c_client *client)
++{
++ int err;
++
++ if ((err = i2c_detach_client(client))) {
++ dev_err(&client->dev, "Client deregistration failed, "
++ "client not detached.\n");
++ return err;
++ }
++
++ kfree(i2c_get_clientdata(client));
++
++ return 0;
++}
++
++static int __init cx25871_init(void)
++{
++ printk("cx25871_init\n");
++ return i2c_add_driver(&cx25871_driver);
++}
++
++static void __exit cx25871_exit(void)
++{
++ i2c_del_driver(&cx25871_driver);
++}
++
++MODULE_DESCRIPTION("Conexant CX25871 video encoder");
++MODULE_LICENSE("GPL");
++
++module_init(cx25871_init);
++module_exit(cx25871_exit);
+diff --git a/drivers/video/ep93xxfb.c b/drivers/video/ep93xxfb.c
+new file mode 100644
+index 0000000..475943a
+--- /dev/null
++++ b/drivers/video/ep93xxfb.c
+@@ -0,0 +1,787 @@
++/******************************************************************************
++ *
++ * File: linux/drivers/video/ep93xxfb.c
++ *
++ * Purpose: Framebuffer driver for EP9312/EP9315 evaluation board.
++ *
++ * based on:
++ * skeletonfb.c
++ * ep93xxfb.c from Linux 2.4.21-rmk1-cirrus-1-3-0
++ *
++ *******************************************************************************/
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/errno.h>
++#include <linux/delay.h>
++#include <linux/string.h>
++#include <linux/ctype.h>
++#include <linux/mm.h>
++#include <linux/tty.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/fb.h>
++#include <linux/device.h>
++#include <linux/dma-mapping.h>
++
++#include <asm/hardware.h>
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/mach-types.h>
++#include <asm/uaccess.h>
++#include <asm/pgtable.h>
++
++#include "ep93xxfb.h"
++
++/*
++#define DEBUG
++#define USE_PRINTASCII
++*/
++
++#ifdef DEBUG
++# if defined(CONFIG_DEBUG_LL) && defined(USE_PRINTASCII)
++extern void printascii(const char *);
++# define DPRINTK(fmt, args...) {char str[256];sprintf(str, "%s: " fmt, __FUNCTION__ , ## args);printascii(str);}
++# else
++# define DPRINTK(fmt, args...) printk("%s: " fmt, __FUNCTION__ , ## args)
++# endif
++#else
++# define DPRINTK(fmt, args...)
++#endif
++
++static struct fb_info info;
++static struct fb_fix_screeninfo ep93xxfb_fix;
++static struct fb_var_screeninfo ep93xxfb_var;
++static struct ep93xxfb_par ep93xxfb_par;
++static unsigned int pseudo_palette[MAX_PALETTE_NUM_ENTRIES];
++
++int __init ep93xxfb_init(void);
++static int ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green,
++ unsigned blue, unsigned transp,
++ struct fb_info *info);
++static int ep93xxfb_blank(int blank_mode, struct fb_info *info);
++int __init ep93xxfb_init(void);
++static void __exit ep93xxfb_cleanup(void);
++int __init ep93xxfb_setup(char *options);
++
++static struct fb_ops ep93xxfb_ops = {
++ .owner = THIS_MODULE,
++ .fb_setcolreg = ep93xxfb_setcolreg,
++ .fb_blank = ep93xxfb_blank,
++ .fb_fillrect = cfb_fillrect,
++ .fb_copyarea = cfb_copyarea,
++ .fb_imageblit = cfb_imageblit,
++};
++
++/*
++ * ep93xxfb_palette_write:
++ * Encode palette data to 24bit palette format.
++ * Write palette data to the master palette and inactive hw palette
++ * switch palettes. And handle asynchronous palette switches.
++ */
++static inline void
++ep93xxfb_palette_write(u_int regno, u_int red, u_int green,
++ u_int blue, u_int trans)
++{
++ unsigned int cont, i, pal;
++
++ /* Only supports color LUT, not gray LUT
++ *
++ * TBD if not in 4 or 8bpp, then does LUT logic operate?
++ * TBD or do we need to do nothing here?
++ *
++ * LCD: TBD RGB mapping may match spec p193.
++ *
++ * CRT: LUT RGB mapping is really R/G/B from high to low bits
++ * because really determined by wiring to video DAC.
++ * (disregard spec p 193 showing color LUT B/G/R order)
++ * Here are the details:
++ *
++ * Shift mode 1 directs LUT bits 7-2 onto P5-P0,
++ * LUT bits 15-10 onto P11-P6, and LUT bits 23-16
++ * onto P17-P12.
++ *
++ * Board wired P17-12 to video DAC Red inputs,
++ * P11-P6 wired to video DAC Green inputs, and
++ * P5-P0 wired to video DAC Blue inputs.
++ */
++ pal = ((red & 0xFF00) << 8) | (green & 0xFF00) | ((blue & 0xFF00) >> 8);
++
++ pseudo_palette[regno] = pal;
++
++ /* Two cases here:
++ * 1. If LUT switch is pending, then write inactive LUT and when
++ * switch happens, this new palette entry will be active.
++ * Race condition here between LUT switch and this write is okay
++ * since we fix it below.
++ *
++ * 2. If LUT switch is not pending, then write here is incomplete
++ * and whole palette will be written below.
++ */
++
++ writel(pal, COLOR_LUT + (regno << 2));
++
++ cont = readl(LUTCONT);
++
++ if ((cont & LUTCONT_STAT && cont & LUTCONT_RAM1) ||
++ (!(cont & LUTCONT_STAT) && !(cont & LUTCONT_RAM1))) {
++ /* LUT switch is no longer pending
++ *
++ * We do not know if write to LUT above really went
++ * to currently active LUT. So need to make sure that
++ * data gets into inactive LUT and switch LUTs.
++ *
++ * But currently inactive LUT may be out of date
++ * in more entries than just last write.
++ * Need to update currently inactive LUT for all writes
++ * which went to currently active LUT.
++ * Fully update the LUT now, which is a simpler policy
++ * than trying to track writes and do partial update of LUT.
++ * (Worstcase impact: we update palette every frame)
++ */
++
++ for (i = 0; i < 256; i++) // Update inactive LUT
++ {
++ writel(pseudo_palette[i],
++ (COLOR_LUT + (i << 2)));
++ }
++ /* Switch active LUTs next frame */
++ writel(cont ^ LUTCONT_RAM1, LUTCONT);
++ }
++}
++
++/**
++ * xxxfb_setcolreg - Optional function. Sets a color register.
++ * @regno: Which register in the CLUT we are programming
++ * @red: The red value which can be up to 16 bits wide
++ * @green: The green value which can be up to 16 bits wide
++ * @blue: The blue value which can be up to 16 bits wide.
++ * @transp: If supported the alpha value which can be up to 16 bits wide.
++ * @info: frame buffer info structure
++ *
++ * Set a single color register. The values supplied have a 16 bit
++ * magnitude which needs to be scaled in this function for the hardware.
++ * Things to take into consideration are how many color registers, if
++ * any, are supported with the current color visual. With truecolor mode
++ * no color palettes are supported. Here a psuedo palette is created
++ * which we store the value in pseudo_palette in struct fb_info. For
++ * pseudocolor mode we have a limited color palette. To deal with this
++ * we can program what color is displayed for a particular pixel value.
++ * DirectColor is similar in that we can program each color field. If
++ * we have a static colormap we don't need to implement this function.
++ *
++ * Returns negative errno on error, or zero on success.
++ */
++static int
++ep93xxfb_setcolreg(unsigned regno, unsigned red, unsigned green, unsigned blue,
++ unsigned transp, struct fb_info *info)
++{
++ if (regno >= MAX_PALETTE_NUM_ENTRIES) /* no. of hw registers */
++ return 1;
++ /*
++ * Program hardware... do anything you want with transp
++ */
++
++ /* grayscale works only partially under directcolor */
++ if (info->var.grayscale) {
++ /* grayscale = 0.30*R + 0.59*G + 0.11*B */
++ red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
++ }
++
++ /* Directcolor:
++ * var->{color}.offset contains start of bitfield
++ * var->{color}.length contains length of bitfield
++ * {hardwarespecific} contains width of DAC
++ * cmap[X] is programmed to (X << red.offset) | (X << green.offset) | (X << blue.offset)
++ * RAMDAC[X] is programmed to (red, green, blue)
++ *
++ * Pseudocolor:
++ * uses offset = 0 && length = DAC register width.
++ * var->{color}.offset is 0
++ * var->{color}.length contains widht of DAC
++ * cmap is not used
++ * DAC[X] is programmed to (red, green, blue)
++ * Truecolor:
++ * does not use RAMDAC (usually has 3 of them).
++ * var->{color}.offset contains start of bitfield
++ * var->{color}.length contains length of bitfield
++ * cmap is programmed to (red << red.offset) | (green << green.offset) |
++ * (blue << blue.offset) | (transp << transp.offset)
++ * RAMDAC does not exist
++ */
++#define CNVT_TOHW(val,width) ((((val)<<(width))+0x7FFF-(val))>>16)
++
++ switch (info->fix.visual) {
++ case FB_VISUAL_PSEUDOCOLOR:
++ /* Feed the dual 256x24 hardware LUT */
++ ep93xxfb_palette_write(regno, red, green, blue, transp);
++ break;
++ case FB_VISUAL_TRUECOLOR:
++ /* Truecolor has hardware independent palette */
++ if (regno >= 16)
++ return 1;
++
++ red = CNVT_TOHW(red, info->var.red.length);
++ green = CNVT_TOHW(green, info->var.green.length);
++ blue = CNVT_TOHW(blue, info->var.blue.length);
++ transp = CNVT_TOHW(transp, info->var.transp.length);
++ ((u32 *) (info->pseudo_palette))[regno] =
++ (red << info->var.red.offset) |
++ (green << info->var.green.offset) |
++ (blue << info->var.blue.offset) |
++ (transp << info->var.transp.offset);
++ break;
++ case FB_VISUAL_DIRECTCOLOR:
++ /* example here assumes 8 bit DAC. Might be different
++ * for your hardware */
++ red = CNVT_TOHW(red, 8);
++ green = CNVT_TOHW(green, 8);
++ blue = CNVT_TOHW(blue, 8);
++ /* hey, there is bug in transp handling... */
++ transp = CNVT_TOHW(transp, 8);
++ break;
++ }
++#undef CNVT_TOHW
++
++ return 0;
++}
++
++/**
++ * xxxfb_blank - NOT a required function. Blanks the display.
++ * @blank_mode: the blank mode we want.
++ * @info: frame buffer structure that represents a single frame buffer
++ *
++ * Blank the screen if blank_mode != 0, else unblank. Return 0 if
++ * blanking succeeded, != 0 if un-/blanking failed due to e.g. a
++ * video mode which doesn't support it. Implements VESA suspend
++ * and powerdown modes on hardware that supports disabling hsync/vsync:
++ * blank_mode == 2: suspend vsync
++ * blank_mode == 3: suspend hsync
++ * blank_mode == 4: powerdown
++ *
++ * Returns negative errno on error, or zero on success.
++ *
++ */
++static int ep93xxfb_blank(int blank_mode, struct fb_info *info)
++{
++#ifdef CONFIG_MACH_ADSSPHERE
++ void adssphere_blank(int blank_mode);
++
++ adssphere_blank(blank_mode);
++#endif
++
++ return 1;
++}
++
++static struct device ep93xxfb_device = {
++ .bus_id = "ep93xxfb",
++ .coherent_dma_mask = 0xffffffff,
++};
++
++/*
++ * ep9312fb_map_video_memory():
++ * 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 ep9312fb_map_video_memory(void)
++{
++ dma_addr_t handle;
++
++ ep93xxfb_par.dev = &ep93xxfb_device;
++
++ ep93xxfb_par.v_screen_base = dma_alloc_writecombine(ep93xxfb_par.dev,
++ FB_MAPPED_MEM_SIZE,
++ &handle,
++ GFP_KERNEL);
++
++ if (ep93xxfb_par.v_screen_base == NULL) {
++ printk(KERN_ERR "ep93xxfb: unable to allocate screen memory\n");
++ return -ENOMEM;
++ }
++
++ info.screen_base = ep93xxfb_par.v_screen_base;
++ info.fix.smem_start = (unsigned int)ep93xxfb_par.p_screen_base = handle;
++ info.fix.smem_len = FB_MAPPED_MEM_SIZE;
++
++ return 0;
++}
++
++static int ep93xxfb_probe_configuration(void)
++{
++ int xres, yres, bpp, pixelmode, total;
++ unsigned char lookup_bpp[] = {-1, -1, 8, -1, 16, -1, 24, 32};
++
++ pixelmode = readl(PIXELMODE);
++
++ bpp = lookup_bpp[PIXELMODE_P_MASK & pixelmode];
++
++ if (bpp < 0) return 0;
++
++ yres = readl(SCRNLINES);
++
++ if (yres == 0) return 0;
++
++ xres = (32 * readl(VLINESTEP)) / bpp;
++
++ if (xres == 0) return 0;
++
++ info.node = -1;
++ info.flags = FBINFO_FLAG_DEFAULT;
++
++ info.fix = ep93xxfb_fix;
++ info.var = ep93xxfb_var;
++ info.fbops = &ep93xxfb_ops;
++ info.pseudo_palette = pseudo_palette;
++
++ info.monspecs = monspecs;
++
++ strcpy(info.fix.id, "Cirrus EP93xx");
++ info.fix.type = FB_TYPE_PACKED_PIXELS;
++ info.fix.xpanstep = 0;
++ info.fix.ypanstep = 0;
++ info.fix.ywrapstep = 0;
++ info.fix.accel = FB_ACCEL_NONE;
++
++ info.var.xres = xres;
++ info.var.yres = yres;
++ info.var.xres_virtual = xres;
++ info.var.yres_virtual = yres;
++ info.var.bits_per_pixel = bpp;
++ info.var.activate = FB_ACTIVATE_NOW;
++ info.var.height = -1;
++ info.var.width = -1;
++
++ switch (bpp) {
++ case 8:
++ info.var.red.length = 8;
++ info.var.green.length = 8;
++ info.var.blue.length = 8;
++
++ info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
++ ep93xxfb_par.bits_per_pixel = 8;
++ break;
++ case 16:
++ info.var.red.length = 5;
++ info.var.green.length = 6;
++ info.var.blue.length = 5;
++ info.var.transp.length = 0;
++ info.var.red.offset = 11;
++ info.var.green.offset = 5;
++ info.var.blue.offset = 0;
++ info.var.transp.offset = 0;
++
++ info.fix.visual = FB_VISUAL_TRUECOLOR;
++ info.pseudo_palette = ep93xxfb_par.palette;
++
++ ep93xxfb_par.bits_per_pixel = 16;
++ break;
++ case 24:
++ info.var.red.length = 8;
++ info.var.blue.length = 8;
++ info.var.green.length = 8;
++ info.var.transp.length = 0;
++ info.var.red.offset = 16;
++ info.var.green.offset = 8;
++ info.var.blue.offset = 0;
++ info.var.transp.offset = 0;
++
++ info.fix.visual = FB_VISUAL_TRUECOLOR;
++
++ ep93xxfb_par.bits_per_pixel = 24;
++ break;
++ case 32:
++ info.var.red.length = 8;
++ info.var.blue.length = 8;
++ info.var.green.length = 8;
++ info.var.transp.length = 0;
++ info.var.red.offset = 16;
++ info.var.green.offset = 8;
++ info.var.blue.offset = 0;
++ info.var.transp.offset = 0;
++
++ info.fix.visual = FB_VISUAL_TRUECOLOR;
++
++ ep93xxfb_par.bits_per_pixel = 32;
++ break;
++ }
++
++ total = readl(HCLKSTOTAL);
++ info.var.hsync_len = (0x7ff & readl(HSYNCSTRTSTOP)) - ((0x07ff0000 & readl(HSYNCSTRTSTOP)) >> 16);
++ info.var.right_margin = ((0x07ff0000 & readl(HSYNCSTRTSTOP)) >> 16) - (0x7ff & readl(HACTIVESTRTSTOP));
++ info.var.left_margin = total - info.var.hsync_len - info.var.right_margin - xres + 1;
++
++ total = readl(VLINESTOTAL);
++ info.var.vsync_len = (0x7ff & readl(VSYNCSTRTSTOP)) - ((0x07ff0000 & readl(VSYNCSTRTSTOP)) >> 16);
++ info.var.upper_margin = total - (0x7ff & readl(VSYNCSTRTSTOP));
++ info.var.lower_margin = ((0x07ff0000 & readl(VSYNCSTRTSTOP)) >> 16) - yres + 1;
++
++ info.var.sync = 0;
++
++ info.var.vmode = FB_VMODE_NONINTERLACED;
++
++ info.fix.line_length = info.var.xres_virtual * info.var.bits_per_pixel / 8; // stride in bytes
++
++ info.par = &TimingValues[NULL_MODE];
++
++ ep93xxfb_par.screen_size = FB_MAX_MEM_SIZE;
++ ep93xxfb_par.palette_size = MAX_PALETTE_NUM_ENTRIES;
++ ep93xxfb_par.montype = 1; //TBD why not 0 since single entry?
++ ep93xxfb_par.currcon = 0; //TBD is this right?
++
++ return 1;
++}
++
++static void
++__init ep93xxfb_init_fbinfo(void)
++{
++ info.node = -1;
++ info.flags = FBINFO_FLAG_DEFAULT;
++
++ info.fix = ep93xxfb_fix;
++ info.var = ep93xxfb_var;
++ info.fbops = &ep93xxfb_ops;
++ info.pseudo_palette = pseudo_palette;
++ info.par = &ep93xxfb_par;
++
++ info.monspecs = monspecs;
++
++ strcpy(info.fix.id, "Cirrus EP93xx");
++ info.fix.type = FB_TYPE_PACKED_PIXELS;
++ info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
++ info.fix.xpanstep = 0;
++ info.fix.ypanstep = 0;
++ info.fix.ywrapstep = 0;
++ info.fix.accel = FB_ACCEL_NONE;
++
++ info.var.xres = TimingValues[DEFAULT_MODE].HRes;
++ info.var.yres = TimingValues[DEFAULT_MODE].VRes;
++ info.var.xres_virtual = TimingValues[DEFAULT_MODE].HRes;
++ info.var.yres_virtual = TimingValues[DEFAULT_MODE].VRes;
++ info.var.bits_per_pixel = 32;
++ info.var.red.length = 8;
++ info.var.green.length = 8;
++ info.var.blue.length = 8;
++ info.var.activate = FB_ACTIVATE_NOW;
++ info.var.height = -1;
++ info.var.width = -1;
++ info.var.vmode = FB_VMODE_NONINTERLACED;
++
++ /*
++ * setup initial parameters
++ */
++ info.var.xres = TimingValues[DEFAULT_MODE].HRes;
++ info.var.yres = TimingValues[DEFAULT_MODE].VRes;
++
++#ifdef CONFIG_FB_EP93XX_8BPP
++ DPRINTK("Default framebuffer is 8bpp.");
++ info.var.bits_per_pixel = 8;
++
++ info.var.red.length = 8;
++ info.var.green.length = 8;
++ info.var.blue.length = 8;
++
++ info.fix.visual = FB_VISUAL_PSEUDOCOLOR;
++ ep93xxfb_par.bits_per_pixel = 8;
++#endif /* CONFIG_FB_EP93XX_8BPP */
++#ifdef CONFIG_FB_EP93XX_16BPP_565
++ DPRINTK("Default framebuffer is 16bpp 565.");
++ info.var.bits_per_pixel = 16;
++
++ info.var.red.length = 5;
++ info.var.green.length = 6;
++ info.var.blue.length = 5;
++ info.var.transp.length = 0;
++ info.var.red.offset = 11;
++ info.var.green.offset = 5;
++ info.var.blue.offset = 0;
++ info.var.transp.offset = 0;
++ info.fix.visual = FB_VISUAL_TRUECOLOR;
++ info.pseudo_palette = ep93xxfb_par.palette;
++
++ ep93xxfb_par.bits_per_pixel = 16;
++#endif /* CONFIG_FB_EP93XX_16BPP */
++#ifdef CONFIG_FB_EP93XX_24BPP
++ DPRINTK("Default framebuffer is 24bpp.");
++ info.var.bits_per_pixel = 24;
++
++ info.var.red.length = 8;
++ info.var.blue.length = 8;
++ info.var.green.length = 8;
++ info.var.transp.length = 0;
++ info.var.red.offset = 16;
++ info.var.green.offset = 8;
++ info.var.blue.offset = 0;
++ info.var.transp.offset = 0;
++ info.fix.visual = FB_VISUAL_TRUECOLOR;
++
++ ep93xxfb_par.bits_per_pixel = 24;
++#endif /* CONFIG_FB_EP93XX_24BPP */
++#ifdef CONFIG_FB_EP93XX_32BPP
++ DPRINTK("Default framebuffer is 32bpp.");
++ info.var.bits_per_pixel = 32;
++
++ info.var.red.length = 8;
++ info.var.blue.length = 8;
++ info.var.green.length = 8;
++ info.var.transp.length = 0;
++ info.var.red.offset = 16;
++ info.var.green.offset = 8;
++ info.var.blue.offset = 0;
++ info.var.transp.offset = 0;
++ info.fix.visual = FB_VISUAL_TRUECOLOR;
++
++ ep93xxfb_par.bits_per_pixel = 32;
++#endif /* CONFIG_FB_EP93XX_32BPP */
++
++ info.var.activate = FB_ACTIVATE_NOW;
++ info.var.height = -1; /*TBD unknown */
++ info.var.width = -1; /*TBD unknown */
++
++ info.var.left_margin = TimingValues[DEFAULT_MODE].HFrontPorch;
++ info.var.right_margin = TimingValues[DEFAULT_MODE].HBackPorch;
++ info.var.upper_margin = TimingValues[DEFAULT_MODE].VFrontPorch;
++ info.var.lower_margin = TimingValues[DEFAULT_MODE].VBackPorch;
++ info.var.hsync_len = TimingValues[DEFAULT_MODE].HSyncWidth;
++ info.var.vsync_len = TimingValues[DEFAULT_MODE].VSyncWidth;
++ info.var.sync = 0;
++ info.var.vmode = FB_VMODE_NONINTERLACED;
++
++ info.fix.line_length = info.var.xres_virtual * info.var.bits_per_pixel / 8; /* stride in bytes */
++
++ info.par = &TimingValues[DEFAULT_MODE];
++
++ ep93xxfb_par.screen_size = FB_MAX_MEM_SIZE;
++ ep93xxfb_par.palette_size = MAX_PALETTE_NUM_ENTRIES;
++ ep93xxfb_par.montype = 1; /*TBD why not 0 since single entry? */
++ ep93xxfb_par.currcon = 0; /*TBD is this right? */
++}
++
++static int
++ep93xxfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info)
++{
++ u_long flags, ulVIDEOATTRIBS;
++ unsigned int total, uiDevCfg, uiBMAR;
++#ifdef CONFIG_FB_LCD_EP93XX
++ unsigned int uiPADDR, uiPADR;
++#endif
++ struct DisplayTimingValues *pTimingValues;
++
++ switch (var->bits_per_pixel) {
++ case 4:
++ ep93xxfb_par.visual = FB_VISUAL_PSEUDOCOLOR;
++ ep93xxfb_par.palette_size = 16;
++ break;
++ case 8:
++ ep93xxfb_par.visual = FB_VISUAL_PSEUDOCOLOR;
++ ep93xxfb_par.palette_size = 256;
++ break;
++ case 16:
++ ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR;
++ ep93xxfb_par.palette_size = 16;
++ break;
++ case 24:
++ ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR;
++ ep93xxfb_par.palette_size = 16;
++ break;
++ case 32:
++ ep93xxfb_par.visual = FB_VISUAL_TRUECOLOR;
++ ep93xxfb_par.palette_size = 16;
++ break;
++ default:
++ printk("ERROR! Bad bpp %d\n", var->bits_per_pixel);
++ return -EINVAL;
++ }
++
++ if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_TEST)
++ return 0;
++ else if (((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) &&
++ ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NXTOPEN))
++ return -EINVAL;
++
++ pTimingValues = (struct DisplayTimingValues *)info->par;
++
++ /* Disable interrupts and save status */
++ local_irq_save(flags);
++
++ printk("Configuring %dx%dx%dbpp\n", var->xres, var->yres,
++ var->bits_per_pixel);
++
++ /* Disable the video and outputs while changing the video mode. */
++ writel(0, VIDEOATTRIBS);
++ if (pTimingValues->RasterConfigure) {
++ pTimingValues->RasterConfigure((struct DisplayTimingValues *)info->par); /*pTimingValues); */
++ } else {
++ total = var->vsync_len + var->upper_margin + var->yres +
++ var->lower_margin - 1;
++
++ RasterSetLocked(VLINESTOTAL, total);
++
++ RasterSetLocked(VSYNCSTRTSTOP, total - var->lower_margin +
++ ((total -
++ (var->lower_margin + var->vsync_len)) << 16));
++
++ RasterSetLocked(VACTIVESTRTSTOP, var->yres + (total << 16));
++
++ /* Reverse start/stop since N_VBLANK output
++ * unblanked same as active
++ */
++ RasterSetLocked(VBLANKSTRTSTOP, var->yres + (total << 16));
++
++ RasterSetLocked(VCLKSTRTSTOP, total + (total << 16));
++
++ /* Now configure the Horizontal timings. */
++ total = var->hsync_len + var->left_margin + var->xres +
++ var->right_margin - 1;
++
++ RasterSetLocked(HCLKSTOTAL, total);
++
++ RasterSetLocked(HSYNCSTRTSTOP, total +
++ ((total - var->hsync_len) << 16));
++
++ RasterSetLocked(HACTIVESTRTSTOP, total - var->hsync_len -
++ var->left_margin +
++ ((var->right_margin - 1) << 16));
++
++ RasterSetLocked(HBLANKSTRTSTOP, total - var->hsync_len -
++ var->left_margin +
++ ((var->right_margin - 1) << 16));
++
++ RasterSetLocked(HCLKSTRTSTOP, total + (total << 16));
++
++ RasterSetLocked(LINECARRY, 0);
++
++ RasterSetLocked(VIDEOATTRIBS,
++ VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_SYNCEN |
++ VIDEOATTRIBS_DATAEN);
++ }
++
++ /* Configure the Frame Buffer size. */
++ writel((unsigned int)ep93xxfb_par.p_screen_base, VIDSCRNPAGE);
++ writel(var->yres, SCRNLINES);
++
++ /* Set up the Line size. */
++ total = var->xres * var->bits_per_pixel / 32;
++ writel((total - 1), LINELENGTH);
++ writel(total, VLINESTEP);
++
++ switch (var->bits_per_pixel) {
++ case 8:
++ writel((0x8 | PIXELMODE_P_8BPP | PIXELMODE_C_LUT), PIXELMODE);
++ break;
++ case 16:
++ writel(0x8 | PIXELMODE_P_16BPP |
++ ((PIXELMODE_C_565) << (PIXELMODE_C_SHIFT)), PIXELMODE);
++ break;
++ case 24:
++ writel(0x8 | PIXELMODE_P_24BPP |
++ ((PIXELMODE_C_888) << (PIXELMODE_C_SHIFT)), PIXELMODE);
++ break;
++ case 32:
++ writel(0x8 | PIXELMODE_P_32BPP |
++ ((PIXELMODE_C_888) << (PIXELMODE_C_SHIFT)), PIXELMODE);
++ break;
++ default:
++ printk("ERROR! Bad bpp %d\n", var->bits_per_pixel);
++ return -EINVAL;
++ }
++
++ uiDevCfg = readl(SYSCON_DEVCFG);
++ SysconSetLocked(SYSCON_DEVCFG,
++ ep93xx_SYSCON_DEVCFG(uiDevCfg | SYSCON_DEVCFG_RasOnP3));
++
++ if (pTimingValues->VDiv)
++ SysconSetLocked(SYSCON_VIDDIV, pTimingValues->VDiv);
++
++ uiBMAR = readl(SYSCON_BMAR);
++ writel((uiBMAR | 1), SYSCON_BMAR);
++
++ ulVIDEOATTRIBS = readl(VIDEOATTRIBS);
++ RasterSetLocked(VIDEOATTRIBS, ulVIDEOATTRIBS | VIDEOATTRIBS_EN |
++#if (defined(CONFIG_MACH_ZEFEERDZG) || defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ))
++ (1 << VIDEOATTRIBS_SDSEL_SHIFT));
++#else
++ (3 << VIDEOATTRIBS_SDSEL_SHIFT));
++#endif
++
++
++#ifdef CONFIG_FB_LCD_EP93XX
++ uiPADDR = readl(GPIO_PADDR) | 0x2;
++ writel(uiPADDR, GPIO_PADDR);
++
++ uiPADR = readl(GPIO_PADR) | 0x2;
++ writel(uiPADR, GPIO_PADR);
++#endif
++
++ local_irq_restore(flags);
++ return 0;
++}
++
++int __init ep93xxfb_init(void)
++{
++ char *option = NULL;
++ DPRINTK("ep93xxfb_init(void)\n");
++
++ /*
++ * For kernel boot options (in 'video=xxxfb:<options>' format)
++ */
++
++ fb_get_options("ep93xxfb", &option);
++ ep93xxfb_setup(option);
++
++ /* init all the important stuff in info */
++ if (!ep93xxfb_probe_configuration())
++ ep93xxfb_init_fbinfo();
++
++ /* Allocate and map framebuffer memory in system DRAM */
++ if (ep9312fb_map_video_memory() != 0)
++ return -ENOMEM;
++
++ /* This has to been done !!! */
++ fb_alloc_cmap(&info.cmap, MAX_PALETTE_NUM_ENTRIES, 0);
++
++ /* hard code, since we don't support modedb & friends yet */
++ ep93xxfb_set_var(&info.var, -1, &info);
++
++ if (register_framebuffer(&info) < 0)
++ return -EINVAL;
++
++ ep93xxfb_blank(FB_BLANK_UNBLANK, &info);
++
++ printk(KERN_INFO "fb%d: %s frame buffer device\n", info.node,
++ info.fix.id);
++
++ printk(KERN_INFO
++ "ep93xxfb: framebuffer at 0x%lx, mapped to 0x%p, size %dk\n",
++ info.fix.smem_start, info.screen_base, info.fix.smem_len / 1024);
++ printk(KERN_INFO
++ "ep93xxfb: mode is %dx%dx%d, linelength=%d, pages=%d\n",
++ ep93xxfb_var.xres, ep93xxfb_var.yres,
++ ep93xxfb_var.bits_per_pixel, info.fix.line_length,
++ screen_info.pages);
++
++ return 0;
++}
++
++static void __exit ep93xxfb_cleanup(void)
++{
++ DPRINTK("ep93xxfb_cleanup(void)\n");
++ unregister_framebuffer(&info);
++}
++
++int __init ep93xxfb_setup(char *options)
++{
++ DPRINTK("ep93xxfb_setup(char *options=\"%s\")\n", options);
++ /* TODO: Parse user speficied options (`video=ep93xxfb:') */
++ return 0;
++}
++
++module_init(ep93xxfb_init);
++module_exit(ep93xxfb_cleanup);
++
++MODULE_LICENSE("GPL");
++MODULE_AUTHOR("Michael Burian");
+diff --git a/drivers/video/ep93xxfb.h b/drivers/video/ep93xxfb.h
+new file mode 100644
+index 0000000..dec4857
+--- /dev/null
++++ b/drivers/video/ep93xxfb.h
+@@ -0,0 +1,287 @@
++/*
++ * ep93xxfb.h Cirrus Logic EP93xx Framebuffer header
++ */
++
++/*
++ * TODO:
++ * Still lot's of messy stuff here that belongs elsewhere.
++ *
++ * I'd say that each display / display family get an own header file
++ * maybe even the whole ep93xx stuff should get an own directory, just like ati
++ * It also could not hurt to test the NTSC stuff, which already was split into cx25871.c
++ * but not tested to work so far.
++ *
++ * Display initialisation should become human readable, it should be changed
++ * to reflect what's going on in hardware.
++ *
++ * This means we should say which PLL, prescaler, divider, ... is used instead
++ * of just saying VDIV = 0x0000c207, same goes for all the other hardcoded values.
++ *
++ * How will we handle higher clocked EP93xx once they are available?
++ *
++ */
++
++#define RasterSetLocked(registername,value) \
++ { \
++ writel( 0xAA, REALITI_SWLOCK ); \
++ writel( value, registername); \
++ }
++
++static void InitializeCX25871For640x480NTSC(void);
++
++struct ep93xxfb_par {
++ struct device *dev;
++ dma_addr_t p_screen_base;
++ unsigned char *v_screen_base;
++ unsigned long screen_size;
++ unsigned int palette_size;
++ unsigned int xres;
++ unsigned int yres;
++ unsigned int bits_per_pixel;
++ signed int montype;
++ unsigned int currcon;
++ unsigned int visual;
++ u16 palette[16]; /* Funky 16 table lookup used by "optional" Parameter. */
++};
++
++#define MAX_PALETTE_NUM_ENTRIES 256
++#define MAX_CRT_XRES 640
++#define MAX_CRT_YRES 480
++#define MAX_BPP 32
++#define FB_MAX_MEM_SIZE ((MAX_CRT_XRES * MAX_CRT_YRES * MAX_BPP)/8)
++#define FB_MAPPED_MEM_SIZE (PAGE_ALIGN(FB_MAX_MEM_SIZE + PAGE_SIZE))
++
++#define EP93XX_NAME "EP93XX"
++#define NR_MONTYPES 1
++
++/* Fake monspecs to fill in fbinfo structure */
++static struct fb_monspecs monspecs __initdata = {
++ {30000, 70000, 50, 65, 0} /* Generic */
++};
++
++#if defined (CONFIG_FB_LCD_EP93XX)
++#define DEFAULT_MODE 1
++#elif defined (CONFIG_FB_LCD_EP93XX_SHARP_LQ64D343)
++#define DEFAULT_MODE 2
++#elif defined (CONFIG_FB_CX25871)
++#define DEFAULT_MODE 3
++#elif defined (CONFIG_FB_CRT_EP93XX)
++#define DEFAULT_MODE 0
++#elif defined (CONFIG_FB_LCD_EP93XX_SHARP)
++#define DEFAULT_MODE 5
++#define CONFIG_FB_LCD_EP93XX 1 /*hack!!! FIXME: put whole display support into different files */
++#elif defined (CONFIG_FB_LCD_TX09D50VM1CCA)
++#define DEFAULT_MODE 6
++#else
++#error What Display Setting was that!!!
++#endif
++
++struct DisplayTimingValues {
++ const char *Name;
++ unsigned long DisplayID;
++ int (*RasterConfigure) (struct DisplayTimingValues * pTimingValues);
++ unsigned short Refresh;
++ unsigned long VDiv;
++
++ unsigned short HRes;
++ unsigned short HFrontPorch;
++ unsigned short HBackPorch;
++ unsigned short HSyncWidth;
++ unsigned short HTotalClocks;
++
++ unsigned short VRes;
++ unsigned short VFrontPorch;
++ unsigned short VBackPorch;
++ unsigned short VSyncWidth;
++ unsigned short VTotalClocks;
++};
++
++typedef int (*fRasterConfigure) (struct DisplayTimingValues *);
++
++enum DisplayType {
++ CRT_GENERIC,
++ Philips_LB064V02A1,
++ CX25871,
++ Sharp
++};
++
++static int Conexant_CX25871(struct DisplayTimingValues *pTimingValues);
++static int NecLCD(struct DisplayTimingValues *pTimingValues);
++
++#define TIMING_VALUES(NAME, DISPID, FUNC, REFRESH, VDIV, \
++ HRES, HFP, HBP, HSYNC, VRES, VFP, VBP, VSYNC) \
++{ \
++ Name:NAME, \
++ DISPID, FUNC, REFRESH, VDIV, \
++ HRES, HFP, HBP, HSYNC, (HRES + HFP + HBP + HSYNC), \
++ VRES, VFP, VBP, VSYNC, (VRES + VFP + VBP + VSYNC) \
++}
++
++/* TODO:
++ *
++ * This is a big, confusing mess right now.
++ * We really should see if we can do it like Documentation/fb/modedb.txt
++ * suggests.
++ *
++ * Fix it, probably by moving this into ep93xx_modes.c or something like that
++ */
++
++static struct DisplayTimingValues TimingValues[] = {
++ /* 640x480 Progressive Scan */
++ TIMING_VALUES("CRT_GENERIC", CRT_GENERIC,
++ (fRasterConfigure) NULL,
++ 60, 0x0000c108, 640, 16, 48, 96, 480, 11, 31, 2),
++ /* 640x480 Progressive Scan Philips LB064V02A1 on EDB9312 Board. */
++
++ /* Display can handle clocks from 22MHz(VDIV=0xc107)-28Mhz(VDIV=0xc106) */
++ TIMING_VALUES("Philips LB064V02A1", Philips_LB064V02A1,
++ 0,
++ 68, 0x0000c106, 640, 16, 48, 96, 480, 11, 31, 2),
++ /*fast refresh rate (26.7MHz) */
++ /*68, 0x0000c106, 640, 16, 48, 96, 480, 11, 31, 2), */
++ /*original setting (slowest refresh) (22.8MHz) */
++ /*68, 0x0000c107, 640, 16, 48, 96, 480, 11, 31, 2), */
++
++ /* Sharp LQ64D343 LCD Panel */
++ TIMING_VALUES("Sharp LQ64d343", CRT_GENERIC,
++ (fRasterConfigure) NULL,
++ 60, 0x0000c205, 640, 32, 32, 96, 480, 34, 34, 4),
++ /* NEC LCD Panel */
++ TIMING_VALUES("NEC", CRT_GENERIC,
++ NecLCD,
++ 60, 0x0000c204, 640, 32, 32, 96, 480, 34, 34, 4),
++ /* 640x480 NTSC Support for Conexant CX25871 */
++ TIMING_VALUES("Conexant CX25871", CX25871,
++ Conexant_CX25871,
++ 60, 0x0000c317, 640, 0, 0, 0, 480, 0, 0, 0),
++ /* 320x240 Sharp LCD Panel */
++ TIMING_VALUES("Sharp LQ057Q3DC02", CRT_GENERIC,
++ (fRasterConfigure) NULL,
++ 0, 0x0000c108, 320, 32, 32, 96, 240, 3, 3, 4),
++ /*
++ 240x320 Hitachi
++
++ Max pixel clock freq = 1/83ns ~= 12.048 MHz (VDiv = 0x0000c10a)
++ Typ pixel clock freq = 5.33 MHz (VDiv = 0x0000c125)
++ */
++ TIMING_VALUES("Hitachi TX09D50VM1CCA", CRT_GENERIC,
++ (fRasterConfigure)NULL,
++ 0, 0x0000c125, 240, 16/*HFP*/, 12/*HBP*/, 5/*HSYNC*/, 320, 3/*VFP*/, 3/*VBP*/, 1/*VSYNC*/),
++ /* NULL */
++ TIMING_VALUES("Unknown", CRT_GENERIC,
++ (fRasterConfigure) NULL,
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
++
++};
++
++#define NUM_TIMING_VALUES (sizeof(TimingValues)/sizeof(struct DisplayTimingValues))
++
++#define NULL_MODE (NUM_TIMING_VALUES-1)
++
++#define EE_DELAY_USEC 100
++#define EE_READ_TIMEOUT 100
++#define CX25871_DEV_ADDRESS 0x88
++#define CX25871_REGx32_AUTO_CHK 0x80
++#define CX25871_REGx32_DRVS_MASK 0x60
++#define CX25871_REGx32_DRVS_SHIFT 5
++#define CX25871_REGx32_SETUP_HOLD 0x10
++#define CX25871_REGx32_INMODE_ 0x08
++#define CX25871_REGx32_DATDLY_RE 0x04
++#define CX25871_REGx32_OFFSET_RGB 0x02
++#define CX25871_REGx32_CSC_SEL 0x01
++
++/* Register 0xBA */
++#define CX25871_REGxBA_SRESET 0x80
++#define CX25871_REGxBA_CHECK_STAT 0x40
++#define CX25871_REGxBA_SLAVER 0x20
++#define CX25871_REGxBA_DACOFF 0x10
++#define CX25871_REGxBA_DACDISD 0x08
++#define CX25871_REGxBA_DACDISC 0x04
++#define CX25871_REGxBA_DACDISB 0x02
++#define CX25871_REGxBA_DACDISA 0x01
++
++/* Register 0xC4 */
++#define CX25871_REGxC4_ESTATUS_MASK 0xC0
++#define CX25871_REGxC4_ESTATUS_SHIFT 6
++#define CX25871_REGxC4_ECCF2 0x20
++#define CX25871_REGxC4_ECCF1 0x10
++#define CX25871_REGxC4_ECCGATE 0x08
++#define CX25871_REGxC4_ECBAR 0x04
++#define CX25871_REGxC4_DCHROMA 0x02
++#define CX25871_REGxC4_EN_OUT 0x01
++
++/* Register 0xC6 */
++#define CX25871_REGxC6_EN_BLANKO 0x80
++#define CX25871_REGxC6_EN_DOT 0x40
++#define CX25871_REGxC6_FIELDI 0x20
++#define CX25871_REGxC6_VSYNCI 0x10
++#define CX25871_REGxC6_HSYNCI 0x08
++#define CX25871_REGxC6_INMODE_MASK 0x07
++#define CX25871_REGxC6_INMODE_SHIFT 0
++
++#define GPIOG_EEDAT 2
++#define GPIOG_EECLK 1
++
++static int Conexant_CX25871(struct DisplayTimingValues *pTimingValues)
++{
++ unsigned int uiTemp;
++ InitializeCX25871For640x480NTSC();
++
++ RasterSetLocked(VIDEOATTRIBS, 0);
++ uiTemp = readl(SYSCON_DEVCFG);
++ SysconSetLocked(SYSCON_DEVCFG, (uiTemp | SYSCON_DEVCFG_EXVC));
++
++ RasterSetLocked(VLINESTOTAL, 0x0257);
++ RasterSetLocked(VSYNCSTRTSTOP, 0x01FF022C); /* was 024c */
++ RasterSetLocked(VBLANKSTRTSTOP, 0x000001E0);
++ RasterSetLocked(VACTIVESTRTSTOP, 0x000001E0);
++ RasterSetLocked(VCLKSTRTSTOP, 0x07FF01E0);
++
++ RasterSetLocked(HCLKSTOTAL, 0x30F);
++ RasterSetLocked(HSYNCSTRTSTOP, 0x02c0030F);
++ RasterSetLocked(HBLANKSTRTSTOP, 0x00000280);
++ RasterSetLocked(HACTIVESTRTSTOP, 0x00000280);
++ RasterSetLocked(HCLKSTRTSTOP, 0x07ff0280);
++
++ RasterSetLocked(LINECARRY, 0);
++
++ RasterSetLocked(VIDEOATTRIBS,
++ VIDEOATTRIBS_DATAEN | VIDEOATTRIBS_SYNCEN);
++
++ return 0;
++}
++
++static int NecLCD(struct DisplayTimingValues *pTimingValues)
++{
++ RasterSetLocked(VIDEOATTRIBS, 0);
++
++ RasterSetLocked(VLINESTOTAL, 0x020c);
++ RasterSetLocked(VSYNCSTRTSTOP, 0x01fe0200); /* was 024c */
++ RasterSetLocked(VBLANKSTRTSTOP, 0x0000000);
++ RasterSetLocked(VACTIVESTRTSTOP, 0x020c01df);
++ RasterSetLocked(VCLKSTRTSTOP, 0x020c020c);
++
++ RasterSetLocked(HCLKSTOTAL, 0x323);
++ RasterSetLocked(HSYNCSTRTSTOP, 0x02c00321);
++ RasterSetLocked(HBLANKSTRTSTOP, 0x00000);
++ RasterSetLocked(HACTIVESTRTSTOP, 0x00100290);
++ RasterSetLocked(HCLKSTRTSTOP, 0x03230323);
++
++ RasterSetLocked(LINECARRY, 0);
++
++ RasterSetLocked(VIDEOATTRIBS, VIDEOATTRIBS_INVCLK |
++ VIDEOATTRIBS_PCLKEN | VIDEOATTRIBS_SYNCEN |
++ VIDEOATTRIBS_DATAEN);
++
++ return 0;
++}
++
++void InitializeCX25871For640x480NTSC(void)
++{
++/*
++ * If you need this see cx25871.[ch] and grep for "should be done".
++ * see if you can find a suitable and less messy way to do i2c stuff
++ * also see our patch against 2.6.11.7-ep93xx
++ */
++ printk("ERROR: InitializeCX25871For640x480NTSC unimplemented!\n");
++}
+diff --git a/include/asm-arm/arch-ep93xx/adssphere.h b/include/asm-arm/arch-ep93xx/adssphere.h
+new file mode 100644
+index 0000000..97874c1
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/adssphere.h
+@@ -0,0 +1,55 @@
++/*
++ * linux/include/asm-arm/arch-ep93xx/adssphere.h
++ *
++ * Copyright (C) 2005 Robert Whaley <rwhaley@applieddata.net>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef ASM_ARCH_ADSSPHERE_H
++#define ASM_ARCH_ADSSPHERE_H
++
++#define ADSSPHERE_BASE_VIRT 0xe2000000
++#define ADSSPHERE_BASE_PHYS 0xf0000000
++
++#define ADSSPHERE_CR0 (ADSSPHERE_BASE_VIRT+0x00)
++#define ADSSPHERE_CR1 (ADSSPHERE_BASE_VIRT+0x04)
++#define ADSSPHERE_SR (ADSSPHERE_BASE_VIRT+0x08)
++#define ADSSPHERE_CAN_ADDR (ADSSPHERE_BASE_VIRT+0x0c)
++#define ADSSPHERE_CAN_DATA (ADSSPHERE_BASE_VIRT+0x10)
++#define ADSSPHERE_FW_FW_NUM (ADSSPHERE_BASE_VIRT+0x14)
++#define ADSSPHERE_FW_FW_REV (ADSSPHERE_BASE_VIRT+0x18)
++#define ADSSPHERE_FW_BD_REV (ADSSPHERE_BASE_VIRT+0x1c)
++
++#define ADSSPHERE_CR0_CF_33 0x01
++#define ADSSPHERE_CR0_CF_50 0x02
++#define ADSSPHERE_CR0_COMEN 0x04
++#define ADSSPHERE_CR0_IRDA 0x08
++#define ADSSPHERE_CR0_USB 0x10
++#define ADSSPHERE_CR0_PWSAV 0x20
++
++#define ADSSPHERE_CR1_PNL_ON 0x01
++#define ADSSPHERE_CR1_PNL_EN 0x04
++#define ADSSPHERE_CR1_BL_ON 0x08
++#define ADSSPHERE_CR1_AMP_ON 0x10
++#define ADSSPHERE_CR1_CDC_ON 0x20
++#define ADSSPHERE_CR1_BTL_ON 0x40
++
++#define ADSSPHERE_SR1_SW0 0x01
++#define ADSSPHERE_SR1_SW1 0x02
++#define ADSSPHERE_SR1_SW2 0x04
++#define ADSSPHERE_SR1_SW3 0x08
++#define ADSSPHERE_SR1_HP 0x10
++
++#endif /* ASM_ARCH_ADSSPHERE_H */
+diff --git a/include/asm-arm/arch-ep93xx/clocks.h b/include/asm-arm/arch-ep93xx/clocks.h
+new file mode 100644
+index 0000000..acc8023
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/clocks.h
+@@ -0,0 +1,160 @@
++/*
++ *
++ * Filename: clocks.h
++ *
++ * Description: Header file for the clocks.
++ *
++ * Copyright(c) Cirrus Logic Corporation 2003, All Rights Reserved
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ */
++#include <asm/hardware.h>
++#ifndef _H_CLOCKS
++#define _H_CLOCKS
++
++/*
++ * How this file works:
++ * Choose your FCLOCK value this causes FDIV, HDIV, PDIV values to be set
++ *
++ * The Real FDIV, HDIV, and PDIV are set according to the following table.
++ * Processor runs at (PLL1 speed/PLL Divide specified by FDIV)
++ * AHB runs at (PLL1 speed/PLL Divide specified by HDIV)
++ * APB runs at AHB/(2^PDIV)
++ * ------------------------------------------------------------------
++ * HDIV PLL Divide FDIV PLL Divide
++ * 0 1 0 1
++ * 1 2 1 2
++ * 2 4 2 4
++ * 3 5 3 8
++ * 4 6 4 16
++ * 5 8
++ * 6 16
++ * 7 32
++ *
++ */
++
++/* there is some confusion here about MACH vs. ARCH. clean it up
++ once we get a nice clock management system going */
++#ifdef CONFIG_ARCH_EP9301
++#define FCLOCK 166
++#define EP93XX_UART_CLK 14745600
++#endif
++
++#ifdef CONFIG_MACH_EDB9302
++#define FCLOCK 200
++#define EP93XX_UART_CLK 14745600
++#endif
++
++#if defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || defined(CONFIG_MACH_ADSSPHERE)
++#define FCLOCK 200
++#define EP93XX_UART_CLK 14745600
++#endif
++
++#if defined(CONFIG_MACH_DMA03)
++#define FCLOCK 200
++#define EP93XX_UART_CLK 14745600
++#endif
++
++#ifdef CONFIG_MACH_ACC
++#define EP93XX_UART_CLK 24576000
++#endif
++
++#if defined(CONFIG_MACH_ZEFEERDZA)
++#define FCLOCK 166
++#define EP93XX_UART_CLK 14745600
++#endif
++
++#if defined(CONFIG_MACH_ZEFEERDZB) || defined(CONFIG_MACH_ZEFEERDZG) || \
++ defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ)
++#define FCLOCK 200
++#define EP93XX_UART_CLK 14745600
++#endif
++
++/*
++ * PLL1 Clock =442 Mhz
++ *
++ * FClock = 221 Mhz
++ * HCLock = 73 Mhz
++ * PClock = 46 Mhz
++ */
++#if (FCLOCK == 221)
++#define FDIV 1
++#define HDIV 5
++#define PDIV 1
++#define PRE_CLKSET1_VALUE 0x0080b3b6
++#define PLL1_CLOCK 442368000
++#endif /* (FCLOCK == 221) */
++
++/*
++ * PLL1 Clock =400 Mhz
++ *
++ * FClock = 200 Mhz
++ * HCLock = 100 Mhz
++ * PClock = 50 Mhz
++ *
++ */
++#if (FCLOCK == 200)
++#define FDIV 1
++#define HDIV 2
++#define PDIV 1
++#define PRE_CLKSET1_VALUE 0x0080a3d7
++#define PLL1_CLOCK 399974400
++#endif /* (FCLOCK == 200) */
++
++/*
++ * PLL1 Clock =368 Mhz
++ *
++ * FClock = 184 Mhz
++ * HCLock = 73 Mhz
++ * PClock = 46 Mhz
++ *
++ */
++#if (FCLOCK == 183)
++#define FDIV 1
++#define HDIV 4
++#define PDIV 1
++#define PRE_CLKSET1_VALUE 0x0080ab15
++#define PLL1_CLOCK 368640000
++#endif /* (FCLOCK == 183) */
++
++/*
++ * PLL1 Clock =332 Mhz
++ *
++ * FClock = 166 Mhz
++ * HCLock = 66 Mhz
++ * PClock = 33 Mhz
++ *
++ */
++#if (FCLOCK == 166)
++#define FDIV 1
++#define HDIV 3
++#define PDIV 1
++#define PRE_CLKSET1_VALUE 0x0080fa5a
++#define PLL1_CLOCK 332049067
++#endif /* (FCLOCK == 166) */
++
++#define CLKSET1_VALUE ( PRE_CLKSET1_VALUE | \
++ ( PDIV << SYSCON_CLKSET1_PCLK_DIV_SHIFT ) | \
++ ( HDIV << SYSCON_CLKSET1_HCLK_DIV_SHIFT ) | \
++ ( FDIV << SYSCON_CLKSET1_FCLK_DIV_SHIFT ) )
++
++/*
++ * Value for the PLL 2 register.
++ */
++#define CLKSET2_VALUE 0x300dc317
++#define PLL2_CLOCK 192000000
++
++#endif /* _H_CLOCKS */
+diff --git a/include/asm-arm/arch-ep93xx/crunch.h b/include/asm-arm/arch-ep93xx/crunch.h
+new file mode 100644
+index 0000000..db9fb2e
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/crunch.h
+@@ -0,0 +1,48 @@
++#ifndef __asm_crunch_h__
++#define __asm_crunch_h__
++
++#define CRUNCH_INIT 0x00900000
++#define CRUNCH_IRQ 58
++
++#ifndef __ASSEMBLY__
++
++/* enable the MaverickCrunch clock */
++static inline void crunch_enable(void)
++{
++ int tmp, aa = 0xAA;
++ int *lock = (int *)0xe09300c0;
++ int *syscfg = (int *)0xe0930080;
++
++ asm volatile ("str %3, [%1]\n\t"
++ "ldr %0, [%2]\n\t"
++ "orr %0, %0, #(1 << 23)\n\t"
++ "str %0, [%2]":"=r" (tmp)
++ :"r"(lock), "r"(syscfg), "r"(aa)
++ :"memory");
++}
++
++/* disable the MaverickCrunch clock */
++static inline void crunch_disable(void)
++{
++ int tmp, aa = 0xAA;
++ int *lock = (int *)0xe09300c0;
++ int *syscfg = (int *)0xe0930080;
++
++ asm volatile ("str %3, [%1]\n\t"
++ "ldr %0, [%2]\n\t"
++ "bic %0, %0, #(1 << 23)\n\t"
++ "str %0, [%2]":"=r" (tmp)
++ :"r"(lock), "r"(syscfg), "r"(aa)
++ :"memory");
++}
++
++unsigned int read_dspsc_low(void);
++unsigned int read_dspsc_high(void);
++void write_dspsc(unsigned int);
++void save_fpu(struct task_struct *);
++void restore_fpu(struct task_struct *);
++int setup_crunch(void);
++void crunch_init(void);
++#endif
++
++#endif /* __asm_crunch_h__ */
+diff --git a/include/asm-arm/arch-ep93xx/cx25871.h b/include/asm-arm/arch-ep93xx/cx25871.h
+new file mode 100644
+index 0000000..9d68ed9
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/cx25871.h
+@@ -0,0 +1,69 @@
++/*
++ * Filename: cx25871.h
++ *
++ * Description: Regisister Definitions and function prototypes for
++ * CX25871 NTSC/PAL encoder.
++ *
++ * Copyright(c) Cirrus Logic Corporation 2003, All Rights Reserved
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _H_CX25871
++#define _H_CX25871
++
++/* CS25871 Device Address. */
++#define CX25871_DEV_ADDRESS 0x88
++
++/* Register 0x32 */
++#define CX25871_REGx32_AUTO_CHK 0x80
++#define CX25871_REGx32_DRVS_MASK 0x60
++#define CX25871_REGx32_DRVS_SHIFT 5
++#define CX25871_REGx32_SETUP_HOLD 0x10
++#define CX25871_REGx32_INMODE_ 0x08
++#define CX25871_REGx32_DATDLY_RE 0x04
++#define CX25871_REGx32_OFFSET_RGB 0x02
++#define CX25871_REGx32_CSC_SEL 0x01
++
++/* Register 0xBA */
++#define CX25871_REGxBA_SRESET 0x80
++#define CX25871_REGxBA_CHECK_STAT 0x40
++#define CX25871_REGxBA_SLAVER 0x20
++#define CX25871_REGxBA_DACOFF 0x10
++#define CX25871_REGxBA_DACDISD 0x08
++#define CX25871_REGxBA_DACDISC 0x04
++#define CX25871_REGxBA_DACDISB 0x02
++#define CX25871_REGxBA_DACDISA 0x01
++
++/* Register 0xC4 */
++#define CX25871_REGxC4_ESTATUS_MASK 0xC0
++#define CX25871_REGxC4_ESTATUS_SHIFT 6
++#define CX25871_REGxC4_ECCF2 0x20
++#define CX25871_REGxC4_ECCF1 0x10
++#define CX25871_REGxC4_ECCGATE 0x08
++#define CX25871_REGxC4_ECBAR 0x04
++#define CX25871_REGxC4_DCHROMA 0x02
++#define CX25871_REGxC4_EN_OUT 0x01
++
++/* Register 0xC6 */
++#define CX25871_REGxC6_EN_BLANKO 0x80
++#define CX25871_REGxC6_EN_DOT 0x40
++#define CX25871_REGxC6_FIELDI 0x20
++#define CX25871_REGxC6_VSYNCI 0x10
++#define CX25871_REGxC6_HSYNCI 0x08
++#define CX25871_REGxC6_INMODE_MASK 0x07
++#define CX25871_REGxC6_INMODE_SHIFT 0
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/debug-macro.S b/include/asm-arm/arch-ep93xx/debug-macro.S
+new file mode 100644
+index 0000000..3d97614
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/debug-macro.S
+@@ -0,0 +1,56 @@
++/* linux/include/asm-arm/arch-ep93xx/debug-macro.S
++ *
++ * Debugging macro include header
++ *
++ * Copyright (C) 1994-1999 Russell King
++ * Moved from linux/arch/arm/kernel/debug.S by Ray Lehtiniemi
++ *
++ * 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.
++ *
++*/
++
++ .macro addruart,rx
++ mrc p15, 0, \rx, c1, c0
++ tst \rx, #1 @ MMU enabled?
++ ldreq \rx, =IO_BASE_PHYS @ System peripherals (phys address)
++ ldrne \rx, =IO_BASE_VIRT @ System peripherals (virt address)
++ orr \rx,\rx,#0x008c0000 @ Advance to UART1Base
++
++ @ We probe for the active serial port here.
++ @ We assume r1 can be clobbered.
++
++ @ see if UART1 is active
++ ldr r1, [\rx, #0x14] @UART1Ctrl
++ tst r1, #1
++
++ @ if UART1 is inactive advance to UART2
++ addeq \rx, \rx, #0x00010000
++ ldreq r1, [\rx, #0x14] @UART2Ctrl
++ tsteq r1, #1
++
++ @ if UART2 is inactive advance to UART3
++ addeq \rx, \rx, #0x00010000
++ ldreq r1, [\rx, #0x14] @UART3Ctrl
++ tsteq r1, #1
++
++ @ if all ports are inactive, then there is nothing we can do
++ moveq pc, lr
++ .endm
++
++ .macro senduart,rd,rx
++ strb \rd, [\rx] @ UARTxData
++ .endm
++
++ .macro waituart,rd,rx
++1001: ldr \rd, [\rx, #0x18] @ UARTxFlag
++ tst \rd, #0x20 @ TXFF = 0 when ok to transmit
++ bne 1001b
++ .endm
++
++ .macro busyuart,rd,rx
++1001: ldr \rd, [\rx, #0x18] @ UARTxFlag
++ tst \rd, #0x08 @ BUSY = 1 while transmitting
++ bne 1001b
++ .endm
+diff --git a/include/asm-arm/arch-ep93xx/dma.h b/include/asm-arm/arch-ep93xx/dma.h
+new file mode 100644
+index 0000000..d3b6493
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/dma.h
+@@ -0,0 +1,233 @@
++/*****************************************************************************
++ * linux/include/asm-arm/arch-ep93xx/dma.h
++ *
++ * Copyright (C) 2003 Cirrus Logic
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ ****************************************************************************/
++#ifndef __ASM_ARCH_DMA_H
++#define __ASM_ARCH_DMA_H
++
++#define MAX_DMA_ADDRESS 0xffffffff
++
++/*
++ * Not using the regular generic DMA interface for ep93xx.
++ */
++#define MAX_DMA_CHANNELS 0
++
++/*
++ * The ep93xx dma controller has 5 memory to peripheral (TX) channels, 5
++ * peripheral to memory (RX) channels and 2 memory to memory channels.
++ */
++#define MAX_EP93XX_DMA_M2P_CHANNELS 10
++#define MAX_EP93XX_DMA_M2M_CHANNELS 2
++
++/*
++ * The generic arm linux api does not support the ep93xx dma model, therefore
++ * we use a set of dma support functions written specifically for this dma
++ * controller.
++ */
++#define MAX_EP93XX_DMA_CHANNELS (MAX_EP93XX_DMA_M2P_CHANNELS + MAX_EP93XX_DMA_M2M_CHANNELS)
++
++/*****************************************************************************
++ *
++ * Max DMA buffer size
++ *
++ ****************************************************************************/
++#define DMA_MAX_BUFFER_BYTES 0xFFFF
++
++/*****************************************************************************
++ *
++ * typedefs
++ *
++ ****************************************************************************/
++
++/*****************************************************************************
++ *
++ * All devices which can use a DMA channel
++ *
++ * NOTE: There exist two types of DMA channels, those that transfer
++ * between an internal peripheral and memory (M2P/P2M), and
++ * those that transfer between an external peripheral and memory (M2M).
++ * This becomes a bit confusing when you take into account the fact
++ * that the M2M channels can also transfer between two specific
++ * internal peripherals and memory.
++ * The first 20 enumerated devices use the first type of channel (M2P/
++ * P2M). The last six enumerations are specific to the M2M channels.
++ *
++ ****************************************************************************/
++typedef enum {
++ /*
++ * Hardware device options for the 10 M2P/P2M DMA channels.
++ */
++ DMATx_I2S1 = 0x00000000, /* TX peripheral ports can be allocated an */
++ DMATx_I2S2 = 0x00000001, /* even numbered DMA channel. */
++ DMATx_AAC1 = 0x00000002,
++ DMATx_AAC2 = 0x00000003,
++ DMATx_AAC3 = 0x00000004,
++ DMATx_I2S3 = 0x00000005,
++ DMATx_UART1 = 0x00000006,
++ DMATx_UART2 = 0x00000007,
++ DMATx_UART3 = 0x00000008,
++ DMATx_IRDA = 0x00000009,
++ DMARx_I2S1 = 0x0000000A, /* RX perhipheral ports can be allocated an */
++ DMARx_I2S2 = 0x0000000B, /* odd numbered DMA channel. */
++ DMARx_AAC1 = 0x0000000C,
++ DMARx_AAC2 = 0x0000000D,
++ DMARx_AAC3 = 0x0000000E,
++ DMARx_I2S3 = 0x0000000F,
++ DMARx_UART1 = 0x00000010,
++ DMARx_UART2 = 0x00000011,
++ DMARx_UART3 = 0x00000012,
++ DMARx_IRDA = 0x00000013,
++
++ /*
++ * Device options for the 2 M2M DMA channels
++ */
++ DMA_MEMORY = 0x00000014,
++ DMA_IDE = 0x00000015,
++ DMARx_SSP = 0x00000016,
++ DMATx_SSP = 0x00000017,
++ DMATx_EXT_DREQ = 0x00000018,
++ DMARx_EXT_DREQ = 0x00000019,
++ UNDEF = 0x0000001A
++} ep93xx_dma_dev_t;
++
++/*****************************************************************************
++ *
++ * Enumerated type used as a parameter for a callback function.
++ * Indicates the type of interrupt.
++ *
++ ****************************************************************************/
++typedef enum {
++ /*
++ * Common interrupts
++ */
++ STALL,
++ NFB,
++
++ /*
++ * Specific to M2P channels
++ */
++ CHERROR,
++
++ /*
++ * Specific to M2M channels
++ */
++ DONE,
++ UNDEF_INT
++} ep93xx_dma_int_t;
++
++/*****************************************************************************
++ *
++ * Init flag bit defintions for M2P/P2M flags.
++ *
++ ****************************************************************************/
++
++/*
++ * Channel error interrupt enable.
++ */
++#define CHANNEL_ERROR_INT_ENABLE 0x00000001
++/*
++ * Determines how the channel state machine behaves in the NEXT state and
++ * in receipt of a peripheral error.
++ * 0 -> NEXT -> ON (ignore the peripheral error.)
++ * 1 -> NEXT -> STALL (effectively disable the channel.)
++ */
++#define EP93XX_DMA_ABORT 0x00000002
++/*
++ * Ignore channel error interrupt.
++ */
++#define IGNORE_CHANNEL_ERROR 0x00000004
++
++/*****************************************************************************
++ *
++ * Init flag bit defintions for M2M flags.
++ *
++ ****************************************************************************/
++
++/*
++ * Destination address hold. This should be set for IDE write transfers
++ */
++#define DESTINATION_HOLD 0x0000001
++/*
++ * Source Address hold. This should be set for IDE read transfers
++ */
++#define SOURCE_HOLD 0x0000002
++/*
++ * Transfer mode.
++ * 00 - s/w initiated M2M transfer
++ * 01 - h/w initiated external peripheral transfer - memory to external
++ * peripheral/IDE/SSP.
++ * 10 - h/w initiated external peripheral transfer - external
++ * peripheral/IDE/SSP to memory.
++ * 11 - not used.
++ */
++#define TRANSFER_MODE_MASK 0x000000C
++#define TRANSFER_MODE_SHIFT 2
++#define TRANSFER_MODE_SW 0x0000000
++#define TRANSFER_MODE_HW_M2P 0x0000004
++#define TRANSFER_MODE_HW_P2M 0x0000008
++/*
++ * Peripheral wait states count. Latency in HCLK cycles needed by the
++ * peripheral to de-assert its request line once the transfer is
++ * finished.
++ *
++ * IDE Operation Wait States
++ * -------------- ------------
++ * IDE MDMA read 0
++ * IDE MDMA write 0
++ * IDE UDMA read 1
++ * IDE UDMA write 2
++ */
++#define WAIT_STATES_MASK 0x00007F0
++#define WAIT_STATES_SHIFT 4
++#define WS_IDE_MDMA_READ_WRITE 0
++#define WS_IDE_UDMA_READ 1
++#define WS_IDE_UDMA_WRITE 2
++
++/*****************************************************************************
++ *
++ * Type definition for the callback function
++ *
++ ****************************************************************************/
++typedef void (*dma_callback) (ep93xx_dma_int_t dma_int,
++ ep93xx_dma_dev_t device, unsigned int user_data);
++
++/*****************************************************************************
++ *
++ * API function prototypes
++ *
++ ****************************************************************************/
++extern int ep93xx_dma_request(int *handle, const char *device_id,
++ ep93xx_dma_dev_t device);
++extern int ep93xx_dma_free(int handle);
++extern int ep93xx_dma_config(int handle, unsigned int flags_m2p,
++ unsigned int flags_m2m,
++ dma_callback callback, unsigned int user_data);
++extern int ep93xx_dma_add_buffer(int handle, unsigned int source,
++ unsigned int dest, unsigned int size,
++ unsigned int last, unsigned int buf_id);
++extern int ep93xx_dma_remove_buffer(int handle, unsigned int *buf_id);
++extern int ep93xx_dma_start(int handle, unsigned int channels,
++ unsigned int *handles);
++extern int ep93xx_dma_pause(int handle, unsigned int channels,
++ unsigned int *handles);
++extern int ep93xx_dma_flush(int handle);
++extern int ep93xx_dma_queue_full(int handle);
++extern int ep93xx_dma_get_position(int handle, unsigned int * buf_id,
++ unsigned int * total, unsigned int * current_frac);
++#endif /* _ASM_ARCH_DMA_H */
+diff --git a/include/asm-arm/arch-ep93xx/entry-macro.S b/include/asm-arm/arch-ep93xx/entry-macro.S
+new file mode 100644
+index 0000000..cab811e
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/entry-macro.S
+@@ -0,0 +1,39 @@
++/*
++ * include/asm-arm/arch-ep93xx/entry-macro.S
++ *
++ * Low-level IRQ helper macros for EP93XX-based platforms
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++ .macro disable_fiq
++ .endm
++
++ .macro get_irqnr_and_base, irqnr, irqstat, base, tmp
++ ldr \irqstat, =VIC0IRQSTATUS
++ ldr \irqstat, [\irqstat, #0] @ get masked status
++
++ mov \irqnr, #0
++1001: tst \irqstat, #1
++ bne 1003f
++ add \irqnr, \irqnr, #1
++ mov \irqstat, \irqstat, lsr #1
++ cmp \irqnr, #32
++ bcc 1001b
++ /* EQ will be set if we reach 32 */
++
++ ldr \irqstat, =VIC1IRQSTATUS
++ ldr \irqstat, [\irqstat, #0] @ get masked status
++
++1002: tst \irqstat, #1
++ bne 1003f
++ add \irqnr, \irqnr, #1
++ mov \irqstat, \irqstat, lsr #1
++ cmp \irqnr, #64
++ bcc 1002b
++ /* EQ will be set if we reach 64 */
++
++1003:
++ .endm
+diff --git a/include/asm-arm/arch-ep93xx/hardware.h b/include/asm-arm/arch-ep93xx/hardware.h
+new file mode 100644
+index 0000000..f390858
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/hardware.h
+@@ -0,0 +1,60 @@
++/*
++ * File: linux/include/asm-arm/arch-ep93xx/hardware.h
++ *
++ * Copyright (C) 2003 Cirrus Logic, Inc
++ *
++ * Copyright (C) 1999 ARM Limited.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef __ASM_ARCH_HARDWARE_H
++#define __ASM_ARCH_HARDWARE_H
++
++#include <asm/arch/clocks.h>
++#include <asm/arch/memory.h>
++#include <asm/arch/regmap.h>
++
++/*
++ * When adding your regs-*.h file here, please be careful to not have any
++ * macros being doubly defined. You may need to comment out a section of
++ * regmap.h to prevent that.
++ */
++#include <asm/arch/regs_ac97.h>
++#include <asm/arch/regs_dma.h>
++#include <asm/arch/regs_gpio.h>
++#include <asm/arch/regs_ide.h>
++#include <asm/arch/regs_i2s.h>
++#include <asm/arch/regs_irda.h>
++#include <asm/arch/regs_pcmcia.h>
++#include <asm/arch/regs_raster.h>
++#include <asm/arch/regs_spi.h>
++#include <asm/arch/regs_syscon.h>
++#include <asm/arch/regs_touch.h>
++#include <asm/arch/regs_uart.h>
++
++#include <asm/arch/regs_hardcode.h>
++
++#include <asm/arch/cx25871.h>
++
++/*
++ * Here's a safe way for calculating jiffies that won't break if the
++ * value of HZ changes.
++ */
++#ifndef MSECS_TO_JIFFIES
++#define MSECS_TO_JIFFIES(ms) (((ms)*HZ+999)/1000)
++#endif
++
++#endif /* __ASM_ARCH_HARDWARE_H */
+diff --git a/include/asm-arm/arch-ep93xx/ide.h b/include/asm-arm/arch-ep93xx/ide.h
+new file mode 100644
+index 0000000..7eb7faa
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/ide.h
+@@ -0,0 +1,235 @@
++/*****************************************************************************
++ * linux/include/asm-arm/arch-ep93xx/ide.h
++ *
++ * IDE definitions for the EP93XX architecture
++ *
++ *
++ * Copyright (c) 2003 Cirrus Logic, Inc., All rights reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ ****************************************************************************/
++#ifndef ASM_ARCH_IDE_H
++#define ASM_ARCH_IDE_H
++#include <asm/io.h>
++#include <asm/irq.h>
++#include <asm/hardware.h>
++#include <asm/scatterlist.h>
++
++/*
++ * Maximum number of IDE interfaces for this architecture is 1.
++ */
++#ifdef CONFIG_BLK_DEV_EP93XX
++#undef MAX_HWIFS
++#define MAX_HWIFS 1
++#endif
++/*
++ * Default PIO mode used for setting up DMA commands
++ */
++#define DEFAULT_PIO_MODE 4
++
++/*
++ * ATA Command Register addresses.
++ */
++
++#define DATAREGISTER 0x00
++#define ERRORREGISTER 0x01
++#define FEATURESREGISTER 0x01
++#define SECTORCOUNTREGISTER 0x02
++#define SECTORNUMBERREGISTER 0x03
++#define CYLINDERLOWREGISTER 0x04
++#define CYLINDERHIGHREGISTER 0x05
++#define DEVICEHEADREGISTER 0x06
++#define COMMANDREGISTER 0x07
++#define STATUSREGISTER 0x07
++
++/*
++ * ATA Control Register addresses.
++ */
++#define DEVICECONTROLREGISTER 0x06
++#define ALTERNATESTATUSREGISTER 0x06
++
++/*
++ * ATA Register Bit Masks
++ */
++#define ATASRST 0x04
++#define ATAnIEN 0x02
++#define ATADEV 0x10
++#define ATAABRT 0x04
++#define ATABSY 0x80
++#define ATADRDY 0x40
++#define ATADRQ 0x08
++#define ATAERR 0x01
++#define ATADEVFAULT 0x20
++#define ATAWRITEFAULT 0x20
++#define ATASERVICE 0x10
++#define ATACORRECTED 0x04
++#define ATAINDEX 0x02
++
++#ifdef CONFIG_BLK_DEV_IDEDMA_EP93XX
++
++#define EP93XX_DMA_TODEVICE 1
++#define EP93XX_DMA_FROMDEVICE 2
++
++/****************************************************************************
++ *
++ * Map a set of buffers described by scatterlist in streaming
++ * mode for DMA. This is the scather-gather version of the
++ * above pci_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 pci_map_single are
++ * the same here.
++ *
++ ****************************************************************************/
++static inline int
++ep93xx_map_sg(struct scatterlist *sg, unsigned int entries,
++ unsigned int direction)
++{
++ unsigned int loop;
++
++ for (loop = 0; loop < entries; loop++, sg++) {
++ consistent_sync(sg->__address, sg->length, direction);
++ sg->dma_address = virt_to_bus(sg->__address);
++ }
++
++ return entries;
++}
++
++#endif /* CONFIG_BLK_DEV_IDEDMA_EP93XX */
++
++/*****************************************************************************
++ *
++ * Set up a hw structure for a specified data port, control port and IRQ.
++ * This should follow whatever the default interface uses.
++ *
++ ****************************************************************************/
++static __inline__ void
++old_ide_init_hwif_ports(hw_regs_t * hw, int data_port, int ctrl_port, int *irq)
++{
++ unsigned long reg;
++ int i;
++ printk("ide_init_hwif_ports\n");
++ printk("ide_init_hwif_ports(hw=%p data_port=%08x, ctrl_port=%08x \n",
++ hw, data_port, ctrl_port);
++
++ /*
++ * Set up the IDE interface for PIO transfers, using the default PIO
++ * mode.
++ */
++ ep93xx_ide_regs->IDECFG.Field.PIO = 1;
++ ep93xx_ide_regs->IDECFG.Field.MODE = DEFAULT_PIO_MODE;
++ ep93xx_ide_regs->IDECFG.Field.WST = 0;
++
++ /*
++ * Enable the IDE interface.
++ */
++ ep93xx_ide_regs->IDECFG.Field.IDEEN = 1;
++
++ /*
++ * Set up the ide device command register offsets in the io_port array.
++ * This offset includes the register offset and the bit settings for
++ * CS0n and CS1n.
++ */
++ reg = (unsigned long)data_port;
++ for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
++ hw->io_ports[i] = (reg << 2) + 2;
++ reg += 1;
++
++ printk(" io_ports: %08lx\n", hw->io_ports[i]);
++ }
++
++ /*
++ * Set up the register offset for the device control registers.
++ * This offset includes the register offset and the bit settings for
++ * CS0n and CS1n.
++ */
++ reg = (unsigned long)ctrl_port;
++ hw->io_ports[IDE_CONTROL_OFFSET] = (reg << 2) + 1;
++ printk("-io_ports: %08lx\n", hw->io_ports[IDE_CONTROL_OFFSET]);
++
++ if (irq)
++ *irq = 0;
++
++}
++
++extern void ep93xx_ide_init(struct hwif_s *hwif);
++
++/*****************************************************************************
++ *
++ * This registers the standard ports for this architecture with the IDE
++ * driver.
++ *
++ ****************************************************************************/
++static __inline__ void old_ide_init_default_hwifs(void)
++{
++ hw_regs_t hw;
++
++ struct hwif_s *hwif;
++ unsigned int uiTemp;
++
++ /*
++ * Make sure the GPIO on IDE bits in the DEVCFG register are not set.
++ */
++ uiTemp =
++ readl(SYSCON_DEVCFG) & ~(SYSCON_DEVCFG_EonIDE |
++ SYSCON_DEVCFG_GonIDE |
++ SYSCON_DEVCFG_HonIDE);
++
++ SysconSetLocked(SYSCON_DEVCFG, uiTemp);
++
++ /*
++ * Initialize the IDE interface
++ */
++ old_ide_init_hwif_ports(&hw, DATAREGISTER, DEVICECONTROLREGISTER, NULL);
++
++ /*
++ * Get the interrupt.
++ */
++ hw.irq = IRQ_EIDE;
++
++ /*
++ * This is the dma channel number assigned to this IDE interface. Until
++ * dma is enabled for this interface, we set it to NO_DMA.
++ */
++ hw.dma = NO_DMA;
++
++ /*
++ * Kernels > 2.6.15-rcX crash when leaving this uninitialized
++ */
++ hw.dev = NULL;
++
++ /*
++ * Register the IDE interface, an ide_hwif_t pointer is passed in,
++ * which will get filled in with the hwif pointer for this interface.
++ */
++ ide_register_hw(&hw, &hwif);
++
++ /*
++ * Set up a pointer to the ep93xx ideproc function.
++ */
++ ep93xx_ide_init(hwif);
++
++ printk
++ ("Cirrus Logic EP93XX IDE initialization - driver version 1.0, 5/21/03. \n");
++}
++#endif /* ASM_ARCH_IDE_H */
+diff --git a/include/asm-arm/arch-ep93xx/io.h b/include/asm-arm/arch-ep93xx/io.h
+new file mode 100644
+index 0000000..7e2e087
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/io.h
+@@ -0,0 +1,29 @@
++/*
++ * File: linux/include/asm-arm/arch-ep93xx/io.h
++ *
++ * Copyright (C) 1999 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef __ASM_ARM_ARCH_IO_H
++#define __ASM_ARM_ARCH_IO_H
++
++#define IO_SPACE_LIMIT 0xffffffff
++
++#define __io(a) ((void __iomem *)(a))
++#define __mem_pci(a) (a)
++#define __mem_isa(a) (a)
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/irqs.h b/include/asm-arm/arch-ep93xx/irqs.h
+new file mode 100644
+index 0000000..7a58d27
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/irqs.h
+@@ -0,0 +1,150 @@
++/*
++ * File: linux/include/asm-arm/arch-ep93xx/irqs.h
++ *
++ * 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
++ */
++
++/*
++ * Linux IRQ interrupts definitions here.
++ * TBD not worth the effort to put duplicate bit defines in platform.h
++ *
++ * Current IRQ implementation
++ *
++ * 1. Current implementation does not support vectored
++ * interrupts. support for this feature may be
++ * added later.
++ * 2. FIQs are ignored. None are assigned.
++ * 3. All interrupts are assigned to IRQs.
++ * 5. IRQ numbers are same as interrupt bit numbers.
++ *
++ */
++
++/* First two interrupt bit assignments are unused. */
++#define IRQ_RFU0 0
++#define IRQ_RFU1 1
++
++#define IRQ_COMMRX 2
++#define IRQ_COMMTX 3
++
++/* Renamed TCXOI to TIMERX for consistency */
++#define IRQ_TIMER1 4
++#define IRQ_TIMER2 5
++
++#define IRQ_AAC 6
++
++#define IRQ_DMAM2P0 7
++#define IRQ_DMAM2P1 8
++#define IRQ_DMAM2P2 9
++#define IRQ_DMAM2P3 10
++#define IRQ_DMAM2P4 11
++#define IRQ_DMAM2P5 12
++#define IRQ_DMAM2P6 13
++#define IRQ_DMAM2P7 14
++#define IRQ_DMAM2P8 15
++#define IRQ_DMAM2P9 16
++
++#define IRQ_DMAM2M0 17
++#define IRQ_DMAM2M1 18
++
++#define IRQ_GPIO0 19
++#define IRQ_GPIO1 20
++#define IRQ_GPIO2 21
++#define IRQ_GPIO3 22
++
++#define IRQ_UARTRX1 23
++#define IRQ_UARTTX1 24
++#define IRQ_UARTRX2 25
++#define IRQ_UARTTX2 26
++#define IRQ_UARTRX3 27
++#define IRQ_UARTTX3 28
++
++#define IRQ_KEY 29
++#define IRQ_TOUCH 30
++#define IRQ_GRAPHICS 31
++
++/* TODO - this was IRQ_INTX, may need to make changes in code */
++#define IRQ_EXT0 32
++#define IRQ_EXT1 33
++#define IRQ_EXT2 34
++
++#define IRQ_64HZ 35
++#define IRQ_WEINT 36
++#define IRQ_RTC 37
++
++#define IRQ_IRDA 38
++#define IRQ_MAC 39
++
++#define IRQ_EXT3 40
++#define IRQ_EIDE IRQ_EXT3
++
++#define IRQ_PROG 41
++#define IRQ_1HZ 42
++#define IRQ_VSYNC 43
++#define IRQ_VIDEOFIFO 44
++
++#define IRQ_SSPRX 45
++#define IRQ_SSPTX 46
++
++#define IRQ_GPIO4 47
++
++#define IRQ_GPIO5 48
++#define IRQ_GPIO6 49
++#define IRQ_GPIO7 50
++
++#define IRQ_TIMER3 51
++
++#define IRQ_UART1 52
++#define IRQ_SSP 53
++
++#define IRQ_UART2 54
++#define IRQ_UART3 55
++
++#define IRQ_USH 56
++#define IRQ_PME 57
++#define IRQ_DSP 58
++#define IRQ_GPIO 59
++
++#define IRQ_RFU60 60
++#define IRQ_RFU61 61
++#define IRQ_RFU62 62
++#define IRQ_RFU63 63
++
++#ifdef CONFIG_ARCH_EP93XX_GPIO_IRQ
++#define IRQ_TO_BIT(irq) (1 << ((irq - NR_GLBL_IRQS) % 16))
++
++#define NR_GLBL_IRQS 64
++
++#define GPIO_IRQ0 64
++#define GPIO_IRQ1 65
++#define GPIO_IRQ2 66
++#define GPIO_IRQ3 67
++#define GPIO_IRQ4 68
++#define GPIO_IRQ5 69
++#define GPIO_IRQ6 70
++#define GPIO_IRQ7 71
++#define GPIO_IRQ8 72
++#define GPIO_IRQ9 73
++#define GPIO_IRQ10 74
++#define GPIO_IRQ11 75
++#define GPIO_IRQ12 76
++#define GPIO_IRQ13 77
++#define GPIO_IRQ14 78
++#define GPIO_IRQ15 79
++
++#define IRQ_CHAINED_GPIO(x) (NR_GLBL_IRQS + x)
++#define NR_IRQS IRQ_CHAINED_GPIO(16) /* with GPIO IRQs EP9315 has 80 IRQs */
++#else
++#define NR_IRQS 64 /* without GPIO IRQs EP9315 has 64 IRQs */
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/keyboard.h b/include/asm-arm/arch-ep93xx/keyboard.h
+new file mode 100644
+index 0000000..685ff17
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/keyboard.h
+@@ -0,0 +1,54 @@
++/*
++ * linux/include/asm-arm/arch-integrator/keyboard.h
++ *
++ * Copyright (C) 2000-2001 Deep Blue Solutions Ltd.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Keyboard driver definitions for the Integrator architecture
++ */
++#include <asm/irq.h>
++
++/* Scancode mapping is as follows:
++ *
++ * Scancode = keycode if key down event
++ * Scancode = keycode|KBUP if key up event
++ *
++ * Valid keycodes are 1..0x7F and are defined by the table
++ * in keymap_dave.map. Keycode 0 is reserved to mean invalid.
++ *
++ * Keycodes are computed from scanned key matrix as follows:
++ */
++
++#define KEYCODE( row, col) ( ((row)<<4) + (col) + 1)
++#define KBUP 0x80
++#define NR_SCANCODES 128 /*TBD used? */
++
++#ifdef CONFIG_EP93XX_KBD_SCANNED
++void __init ep93xx_scan_kbd_hw_init(void);
++#define kbd_init_hw() ep93xx_scan_kbd_hw_init()
++#elif defined CONFIG_EP93XX_KBD_SPI
++void __init EP93XXSpiKbdInit(void);
++#define kbd_init_hw() EP93XXSpiKbdInit()
++#elif defined CONFIG_EP93XX_KBD_USB
++void __init EP93XXUSBKbdInit(void);
++#define kbd_init_hw() EP93XXUSBKbdInit()
++#endif
++
++#ifdef kbd_sysrq_xlate
++#undef kbd_sysrq_xlate
++#define kbd_sysrq_xlate (1)
++#endif
++#define kbd_disable_irq() disable_irq( IRQ_KEY)
++#define kbd_enable_irq() enable_irq( IRQ_KEY)
+diff --git a/include/asm-arm/arch-ep93xx/mach-edb9302.h b/include/asm-arm/arch-ep93xx/mach-edb9302.h
+new file mode 100644
+index 0000000..829883a
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/mach-edb9302.h
+@@ -0,0 +1,20 @@
++/*
++ * linux/include/asm-arm/arch-ep93xx/mach-edb9302.h
++ *
++ * Copyright 2004 Ray Lehtiniemi
++ * Copyright 2004 Siconix, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++#ifndef __ASM_ARCH_MACHEDB9302_H
++#define __ASM_ARCH_MACHEDB9302_H
++
++#include <asm/arch/ssp2.h>
++
++extern struct ep93xx_ssp_slave ep93xx_ssp_flash;
++extern struct ep93xx_ssp_slave ep93xx_ssp_codec;
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/mach-ttml.h b/include/asm-arm/arch-ep93xx/mach-ttml.h
+new file mode 100644
+index 0000000..665873d
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/mach-ttml.h
+@@ -0,0 +1,23 @@
++/*
++ * linux/include/asm-arm/arch-ep93xx/mach-ttml.h
++ *
++ * Copyright 2004 Ray Lehtiniemi
++ * Copyright 2004 Siconix, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ */
++#ifndef __ASM_ARCH_MACHTTML_H
++#define __ASM_ARCH_MACHTTML_H
++
++#include <asm/arch/ssp2.h>
++
++extern struct ep93xx_ssp_slave ep93xx_ssp_micro;
++extern struct ep93xx_ssp_slave ep93xx_ssp_expansion;
++
++extern int ssp_do_ttml(struct ep93xx_ssp_slave *s, void *tx, int tlen, void *rx,
++ int rlen);
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/memory.h b/include/asm-arm/arch-ep93xx/memory.h
+new file mode 100644
+index 0000000..57e266e
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/memory.h
+@@ -0,0 +1,256 @@
++/*
++ * linux/include/asm-arm/arch-ep93xx/memory.h
++ *
++ * ******************************************************
++ * * CONFUSED? Read Documentation/IO-mapping.txt *
++ * ******************************************************
++ *
++ *
++ * Copyright (C) 1999 ARM Limited
++ * Copyright (C) 2002-2003 Cirrus Logic Corp.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef __ASM_ARCH_MMU_H
++#define __ASM_ARCH_MMU_H
++
++/*
++ * For EP93xx, SDRAM can be discontiguous, in a set number of blocks
++ * of equal size and (usually) equal spacing. The 9301 spacing isn't equal.
++ *
++ * SDRAM_START is the physical address of the start of SDRAM.
++ * SDRAM_NUMBER_OF_BLOCKS = # of blocks of SDRAM.
++ * Each block is of size SDRAM_BLOCK_SIZE and starts at a boundary
++ * of SDRAM_BLOCK_START_BOUNDARY.
++ *
++ * So memory blocks are at:
++ * SDRAM_START
++ * SDRAM_START + SDRAM_BLOCK_START_BOUNDARY
++ * SDRAM_START + (SDRAM_BLOCK_START_BOUNDARY * 2)
++ * SDRAM_START + (SDRAM_BLOCK_START_BOUNDARY * 3)
++ * so on
++ */
++
++#ifndef CONFIG_DISCONTIGMEM
++
++/*
++ * Single 32Meg block of physical memory physically located at 0 .
++ */
++#define SDRAM_START 0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS 1
++#define SDRAM_BLOCK_SIZE 0x02000000
++#define SDRAM_BLOCK_START_BOUNDARY 0x00000000
++
++#else /* CONFIG_DISCONTIGMEM */
++
++#if defined(CONFIG_MACH_EDB9301)
++/*
++ * 4 8Meg blocks at 0x0n000000, n={0145}
++ */
++#define SDRAM_START 0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS 4
++#define SDRAM_BLOCK_SIZE 0x00800000
++#define SDRAM_BLOCK_START_BOUNDARY 0x01000000
++#endif
++
++#if defined(CONFIG_MACH_TTML)
++#define SDRAM_START 0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS 1
++#define SDRAM_BLOCK_SIZE 0x02000000
++#define SDRAM_BLOCK_START_BOUNDARY 0x02000000
++#endif
++
++#if defined(CONFIG_MACH_EDB9302)
++/*
++ * 4 8Meg blocks at 0x0n000000, n={0145}
++ */
++#define SDRAM_START 0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS 4
++#define SDRAM_BLOCK_SIZE 0x00800000
++#define SDRAM_BLOCK_START_BOUNDARY 0x01000000
++#endif
++
++#if defined(CONFIG_MACH_EDB9312) || defined(CONFIG_MACH_EDB9315) || defined(CONFIG_MACH_ADSSPHERE)
++/*
++ * 2 32Meg blocks that are located physically at 0 and 64Meg.
++ */
++#define SDRAM_START 0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS 2
++#define SDRAM_BLOCK_SIZE 0x02000000
++#define SDRAM_BLOCK_START_BOUNDARY 0x04000000
++#endif
++
++#if defined(CONFIG_MACH_DMA03)
++/*
++ * 2 32Meg blocks that are located physically at 0 and 64Meg.
++ */
++#define SDRAM_START 0x00000000
++#define SDRAM_NUMBER_OF_BLOCKS 2
++#define SDRAM_BLOCK_SIZE 0x02000000
++#define SDRAM_BLOCK_START_BOUNDARY 0x04000000
++#endif
++
++#if defined(CONFIG_MACH_ACC)
++/*
++ * 8 8Meg blocks that are located physically at 0xC0000000
++ * total 64Meg.
++ */
++#define SDRAM_START 0xC0000000
++#define SDRAM_NUMBER_OF_BLOCKS 8
++#define SDRAM_BLOCK_SIZE 0x00800000
++#define SDRAM_BLOCK_START_BOUNDARY 0x01000000
++#endif
++
++#if defined(CONFIG_MACH_ZEFEERDZB)
++/*
++ * 2 8Meg blocks
++ */
++#define SDRAM_START 0xD0000000
++#define SDRAM_NUMBER_OF_BLOCKS 2
++#define SDRAM_BLOCK_SIZE 0x00800000
++#define SDRAM_BLOCK_START_BOUNDARY 0x01000000
++#endif
++
++#if defined(CONFIG_MACH_ZEFEERDZQ)
++/*
++ * 2 32Meg blocks
++ */
++#define SDRAM_START 0xD0000000
++#define SDRAM_NUMBER_OF_BLOCKS 2
++#define SDRAM_BLOCK_SIZE 0x02000000
++#define SDRAM_BLOCK_START_BOUNDARY 0x04000000
++#endif
++
++/*
++ * Here we are assuming EP93xx is configured to have two 32MB SDRAM
++ * areas with 32MB of empty space between them. So use 24 for the node
++ * max shift to get 64MB node sizes.
++ */
++#define NODE_MAX_MEM_SHIFT 26
++#define NODE_MAX_MEM_SIZE (1<<NODE_MAX_MEM_SHIFT)
++
++#endif /* CONFIG_DISCONTIGMEM */
++
++/*
++ * MEM_SIZE and PHYS_OFFSET are used to set size of SDRAM for
++ * initial page table in arch/arm/kernel/setup.c
++ * For ep93xx, PHYS_OFFSET is set to be SDRAM_START.
++ */
++#define MEM_SIZE (SDRAM_BLOCK_SIZE)
++
++/*
++ * If memory is not discontiguous, this is #defined in
++ * arch/arm/mm/init.c to be 1.
++ */
++#ifdef CONFIG_DISCONTIGMEM
++#define NR_NODES (SDRAM_NUMBER_OF_BLOCKS)
++#endif
++
++/*
++ * Where to load the ramdisk (virtual address, not physical) and how
++ * big to make it. (used in arch/arm/kernel/setup.c
++ * In both cases, when redboot loads the ramdisk image to 0x01000000,
++ * the processor will find it because the linux map is funny.
++ */
++#ifdef CONFIG_ARCH_EP9301
++#define RAMDISK_START_VIRT (0xC4000000)
++#else
++#define RAMDISK_START_VIRT (0xC1000000)
++#endif
++
++/*
++ * The ramdisk size comes from a make menuconfig option.
++ */
++#define RAMDISK_SIZE ((CONFIG_BLK_DEV_RAM_SIZE)<<10)
++
++/*
++ * Task size: 2GB (from 0 to base of IO in virtual space)
++ */
++#define TASK_SIZE UL(0x7f000000)
++
++/*
++ * This decides where the kernel will search for a free chunk of vm
++ * space during mmap's.
++ */
++#define TASK_UNMAPPED_BASE (0x40000000)
++
++/*
++ * Page offset: 3GB (start of kernel memory in virtual space)
++ * Phys offset: 0 (start of kernel memory in physical space)
++ */
++#define PAGE_OFFSET UL(0xC0000000)
++#define PHYS_OFFSET (SDRAM_START)
++
++/*
++ * We take advantage of the fact that physical and virtual address can be the
++ * same. The NUMA code is handling the large holes that might exist between
++ * all memory banks.
++ */
++#define __virt_to_phys__is_a_macro
++#define __virt_to_phys(vpage) ((vpage) - PAGE_OFFSET + PHYS_OFFSET)
++
++#define __phys_to_virt__is_a_macro
++#define __phys_to_virt(ppage) ((ppage) + PAGE_OFFSET - PHYS_OFFSET)
++
++/*
++ * Virtual view <-> DMA view memory address translations
++ * virt_to_bus: Used to translate the virtual address to an
++ * address suitable to be passed to set_dma_addr
++ * bus_to_virt: Used to convert an address for DMA operations
++ * to an address that the kernel can use.
++ */
++#define __virt_to_bus__is_a_macro
++#define __virt_to_bus(x) __virt_to_phys(x)
++
++#define __bus_to_virt__is_a_macro
++#define __bus_to_virt(x) __phys_to_virt(x)
++
++/*
++ * Note that this file is included by include/asm-arm/memory.h so
++ * the macros in this file have to play nice with those.
++ */
++#ifdef CONFIG_DISCONTIGMEM
++
++/*
++ * Given a kernel address, find the home node of the underlying memory.
++ */
++#define KVADDR_TO_NID(addr) \
++ (((unsigned long)(addr) - PAGE_OFFSET) >> NODE_MAX_MEM_SHIFT)
++
++/*
++ * Given a page frame number, convert it to a node id.
++ */
++#define PFN_TO_NID(pfn) \
++ (((pfn) - PHYS_PFN_OFFSET) >> (NODE_MAX_MEM_SHIFT - PAGE_SHIFT))
++
++/*
++ * Given a kaddr, ADDR_TO_MAPBASE finds the owning node of the memory
++ * and returns the mem_map of that node.
++ */
++#define ADDR_TO_MAPBASE(kaddr) NODE_MEM_MAP(KVADDR_TO_NID((unsigned long)(kaddr)))
++
++#define PFN_TO_MAPBASE(pfn) NODE_MEM_MAP(PFN_TO_NID(pfn))
++
++/*
++ * Given a kaddr, LOCAL_MAR_NR finds the owning node of the memory
++ * and returns the index corresponding to the appropriate page in the
++ * node's mem_map.
++ */
++#define LOCAL_MAP_NR(kaddr) \
++ (((unsigned long)(kaddr) & (NODE_MAX_MEM_SIZE - 1)) >> PAGE_SHIFT)
++
++#endif /* CONFIG_DISCONTIGMEM */
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/param.h b/include/asm-arm/arch-ep93xx/param.h
+new file mode 100644
+index 0000000..525face
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/param.h
+@@ -0,0 +1,21 @@
++/*
++ * linux/include/asm-arm/arch-integrator/param.h
++ *
++ * Copyright (C) 1999 ARM Limited
++ *
++ * 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
++ */
++
++/* #define HZ 100 */
+diff --git a/include/asm-arm/arch-ep93xx/platform.h b/include/asm-arm/arch-ep93xx/platform.h
+new file mode 100644
+index 0000000..d92833d
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/platform.h
+@@ -0,0 +1,43 @@
++/*
++ * linux/include/asm-arm/arch-ep93xx/platform.h
++ *
++ * Copyright (C) 2002-2003 Cirrus Logic, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef ASM_ARCH_PLATFORM_H
++#define ASM_ARCH_PLATFORM_H
++
++/*
++ * Timer definitions
++ *
++ * Use timers 1, 2, and 3. Do not use timer 4.
++ * Timers run at 508 kHz.
++ */
++
++/*
++ * These are useconds NOT ticks.
++ */
++#define mSEC_1 1000
++#define mSEC_5 (mSEC_1 * 5)
++#define mSEC_10 (mSEC_1 * 10)
++#define mSEC_25 (mSEC_1 * 25)
++#define SEC_1 (mSEC_1 * 1000)
++
++#ifndef __ASSEMBLY__
++extern struct sys_timer ep93xx_timer;
++#endif
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/regmap.h b/include/asm-arm/arch-ep93xx/regmap.h
+new file mode 100644
+index 0000000..7b3eeac
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regmap.h
+@@ -0,0 +1,1125 @@
++/*
++ * File: linux/include/asm-arm/arch-ep93xx/regmap.h
++ *
++ * Copyright (C) 2004 Ray Lehtiniemi
++ * Copyright (C) 2003 Cirrus Logic, Inc
++ * Copyright (C) 1999 ARM Limited.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef __ASM_ARCH_REGMAP_H
++#define __ASM_ARCH_REGMAP_H
++
++/*
++ * Here's the rules:
++ * - EP93xx register addresses in regmap.h are physical addresses.
++ *
++ * - io_p2v translates a physical address to a virtual one for the
++ * EP93xx's register space only. Don't use it for actual memory.
++ *
++ */
++
++#define IO_BASE_VIRT 0xE0000000 /* Virtual address of IO */
++#define IO_BASE_PHYS 0x80000000 /* Physical address of IO */
++
++/*
++ * The HW_REG macro assumes that the param is a virtual address
++ */
++#define HW_REG(reg) ((unsigned int volatile *)reg)
++
++/*
++ * Macro to get at IO space when running virtually.
++ * (Translates a physical address to a virtual address)
++ * First cast the pa to an unsigned int in case we are using this
++ * on a macro that is already cast as a pointer.
++ */
++
++#define io_p2v(x) ((x) - (IO_BASE_PHYS - IO_BASE_VIRT))
++#define io_v2p(x) ((x) - (IO_BASE_VIRT - IO_BASE_PHYS))
++
++/******************************************************************/
++/* EP93xx Memory Map and Register list */
++/******************************************************************/
++/* */
++/* 0000_0000 - 0000_ffff: Internal ROM/nSDCE3/nCS0 */
++/* 0001_0000 - 0fff_ffff: nSDCE3/nCS0 */
++/* 1000_0000 - 1fff_ffff: nCS1 */
++/* 2000_0000 - 2fff_ffff: nCS2 */
++/* 3000_0000 - 3fff_ffff: nCS3 */
++/* 4000_0000 - 4fff_ffff: Reserved */
++/* 5000_0000 - 5fff_ffff: Reserved */
++/* 6000_0000 - 6fff_ffff: nCS6 */
++/* 7000_0000 - 7fff_ffff: nCS7 */
++/* 8000_0000 - 800f_ffff: AHB Registers */
++/* 8010_0000 - 807f_ffff: Reserved */
++/* 8080_0000 - 8fff_ffff: APB Registers */
++/* 9000_0000 - bfff_ffff: Not Used */
++/* c000_0000 - cfff_ffff: nSDCE0 */
++/* d000_0000 - dfff_ffff: nSDCE1 */
++/* e000_0000 - efff_ffff: nSDCE2 */
++/* f000_0000 - ffff_ffff: nCS0/nSDCE3 */
++/* */
++/******************************************************************/
++
++/******************************************************************/
++/* EP93xx AHB Blocks */
++/******************************************************************/
++/* */
++/* Start End Usage */
++/* 8000_0000 8000_FFFF: DMA */
++/* 8001_0000 8001_FFFF: Ethernet MAC */
++/* 8002_0000 8002_FFFF: USB Host */
++/* 8003_0000 8003_FFFF: Raster */
++/* 8004_0000 8004_FFFF: Reserved */
++/* 8005_0000 8005_FFFF: Reserved */
++/* 8006_0000 8006_FFFF: SDRAM */
++/* 8007_0000 8007_FFFF: Reserved */
++/* 8008_0000 8008_FFFF: SMC */
++/* 8009_0000 8009_FFFF: Boot ROM physical address */
++/* 800A_0000 800A_FFFF: IDE */
++/* 800B_0000 800B_FFFF: VIC1 */
++/* 800C_0000 800C_FFFF: VIC2 */
++/* 800D_0000 800F_FFFF: Reserved */
++/* */
++/******************************************************************/
++
++#define EP93XX_AHB_BASE (IO_BASE_VIRT)
++
++/* 8000_0000 - 8000_ffff: DMA */
++#define DMA_OFFSET 0x000000
++#define DMA_BASE (EP93XX_AHB_BASE|DMA_OFFSET)
++#define DMAMP_TX_0_CONTROL (DMA_BASE+0x0000)
++#define DMAMP_TX_0_INTERRUPT (DMA_BASE+0x0004)
++#define DMAMP_TX_0_PPALLOC (DMA_BASE+0x0008)
++#define DMAMP_TX_0_STATUS (DMA_BASE+0x000C)
++#define DMAMP_TX_0_REMAIN (DMA_BASE+0x0014)
++#define DMAMP_TX_0_MAXCNT0 (DMA_BASE+0x0020)
++#define DMAMP_TX_0_BASE0 (DMA_BASE+0x0024)
++#define DMAMP_TX_0_CURRENT0 (DMA_BASE+0x0028)
++#define DMAMP_TX_0_MAXCNT1 (DMA_BASE+0x0030)
++#define DMAMP_TX_0_BASE1 (DMA_BASE+0x0034)
++#define DMAMP_TX_0_CURRENT1 (DMA_BASE+0x0038)
++
++#define DMAMP_RX_1_CONTROL (DMA_BASE+0x0040)
++#define DMAMP_RX_1_INTERRUPT (DMA_BASE+0x0044)
++#define DMAMP_RX_1_PPALLOC (DMA_BASE+0x0048)
++#define DMAMP_RX_1_STATUS (DMA_BASE+0x004C)
++#define DMAMP_RX_1_REMAIN (DMA_BASE+0x0054)
++#define DMAMP_RX_1_MAXCNT0 (DMA_BASE+0x0060)
++#define DMAMP_RX_1_BASE0 (DMA_BASE+0x0064)
++#define DMAMP_RX_1_CURRENT0 (DMA_BASE+0x0068)
++#define DMAMP_RX_1_MAXCNT1 (DMA_BASE+0x0070)
++#define DMAMP_RX_1_BASE1 (DMA_BASE+0x0074)
++#define DMAMP_RX_1_CURRENT1 (DMA_BASE+0x0078)
++
++#define DMAMP_TX_2_CONTROL (DMA_BASE+0x0080)
++#define DMAMP_TX_2_INTERRUPT (DMA_BASE+0x0084)
++#define DMAMP_TX_2_PPALLOC (DMA_BASE+0x0088)
++#define DMAMP_TX_2_STATUS (DMA_BASE+0x008C)
++#define DMAMP_TX_2_REMAIN (DMA_BASE+0x0094)
++#define DMAMP_TX_2_MAXCNT0 (DMA_BASE+0x00A0)
++#define DMAMP_TX_2_BASE0 (DMA_BASE+0x00A4)
++#define DMAMP_TX_2_CURRENT0 (DMA_BASE+0x00A8)
++#define DMAMP_TX_2_MAXCNT1 (DMA_BASE+0x00B0)
++#define DMAMP_TX_2_BASE1 (DMA_BASE+0x00B4)
++#define DMAMP_TX_2_CURRENT1 (DMA_BASE+0x00B8)
++
++#define DMAMP_RX_3_CONTROL (DMA_BASE+0x00C0)
++#define DMAMP_RX_3_INTERRUPT (DMA_BASE+0x00C4)
++#define DMAMP_RX_3_PPALLOC (DMA_BASE+0x00C8)
++#define DMAMP_RX_3_STATUS (DMA_BASE+0x00CC)
++#define DMAMP_RX_3_REMAIN (DMA_BASE+0x00D4)
++#define DMAMP_RX_3_MAXCNT0 (DMA_BASE+0x00E0)
++#define DMAMP_RX_3_BASE0 (DMA_BASE+0x00E4)
++#define DMAMP_RX_3_CURRENT0 (DMA_BASE+0x00E8)
++#define DMAMP_RX_3_MAXCNT1 (DMA_BASE+0x00F0)
++#define DMAMP_RX_3_BASE1 (DMA_BASE+0x00F4)
++#define DMAMP_RX_3_CURRENT1 (DMA_BASE+0x00F8)
++
++#define DMAMM_0_CONTROL (DMA_BASE+0x0100)
++#define DMAMM_0_INTERRUPT (DMA_BASE+0x0104)
++#define DMAMM_0_STATUS (DMA_BASE+0x010C)
++#define DMAMM_0_BCR0 (DMA_BASE+0x0110)
++#define DMAMM_0_BCR1 (DMA_BASE+0x0114)
++#define DMAMM_0_SAR_BASE0 (DMA_BASE+0x0118)
++#define DMAMM_0_SAR_BASE1 (DMA_BASE+0x011C)
++#define DMAMM_0_SAR_CURRENT0 (DMA_BASE+0x0124)
++#define DMAMM_0_SAR_CURRENT1 (DMA_BASE+0x0128)
++#define DMAMM_0_DAR_BASE0 (DMA_BASE+0x012C)
++#define DMAMM_0_DAR_BASE1 (DMA_BASE+0x0130)
++#define DMAMM_0_DAR_CURRENT0 (DMA_BASE+0x0134)
++#define DMAMM_0_DAR_CURRENT1 (DMA_BASE+0x013C)
++
++#define DMAMM_1_CONTROL (DMA_BASE+0x0140)
++#define DMAMM_1_INTERRUPT (DMA_BASE+0x0144)
++#define DMAMM_1_STATUS (DMA_BASE+0x014C)
++#define DMAMM_1_BCR0 (DMA_BASE+0x0150)
++#define DMAMM_1_BCR1 (DMA_BASE+0x0154)
++#define DMAMM_1_SAR_BASE0 (DMA_BASE+0x0158)
++#define DMAMM_1_SAR_BASE1 (DMA_BASE+0x015C)
++#define DMAMM_1_SAR_CURRENT0 (DMA_BASE+0x0164)
++#define DMAMM_1_SAR_CURRENT1 (DMA_BASE+0x0168)
++#define DMAMM_1_DAR_BASE0 (DMA_BASE+0x016C)
++#define DMAMM_1_DAR_BASE1 (DMA_BASE+0x0170)
++#define DMAMM_1_DAR_CURRENT0 (DMA_BASE+0x0174)
++#define DMAMM_1_DAR_CURRENT1 (DMA_BASE+0x017C)
++
++#define DMAMP_RX_5_CONTROL (DMA_BASE+0x0200)
++#define DMAMP_RX_5_INTERRUPT (DMA_BASE+0x0204)
++#define DMAMP_RX_5_PPALLOC (DMA_BASE+0x0208)
++#define DMAMP_RX_5_STATUS (DMA_BASE+0x020C)
++#define DMAMP_RX_5_REMAIN (DMA_BASE+0x0214)
++#define DMAMP_RX_5_MAXCNT0 (DMA_BASE+0x0220)
++#define DMAMP_RX_5_BASE0 (DMA_BASE+0x0224)
++#define DMAMP_RX_5_CURRENT0 (DMA_BASE+0x0228)
++#define DMAMP_RX_5_MAXCNT1 (DMA_BASE+0x0230)
++#define DMAMP_RX_5_BASE1 (DMA_BASE+0x0234)
++#define DMAMP_RX_5_CURRENT1 (DMA_BASE+0x0238)
++
++#define DMAMP_TX_4_CONTROL (DMA_BASE+0x0240)
++#define DMAMP_TX_4_INTERRUPT (DMA_BASE+0x0244)
++#define DMAMP_TX_4_PPALLOC (DMA_BASE+0x0248)
++#define DMAMP_TX_4_STATUS (DMA_BASE+0x024C)
++#define DMAMP_TX_4_REMAIN (DMA_BASE+0x0254)
++#define DMAMP_TX_4_MAXCNT0 (DMA_BASE+0x0260)
++#define DMAMP_TX_4_BASE0 (DMA_BASE+0x0264)
++#define DMAMP_TX_4_CURRENT0 (DMA_BASE+0x0268)
++#define DMAMP_TX_4_MAXCNT1 (DMA_BASE+0x0270)
++#define DMAMP_TX_4_BASE1 (DMA_BASE+0x0274)
++#define DMAMP_TX_4_CURRENT1 (DMA_BASE+0x0278)
++
++#define DMAMP_RX_7_CONTROL (DMA_BASE+0x0280)
++#define DMAMP_RX_7_INTERRUPT (DMA_BASE+0x0284)
++#define DMAMP_RX_7_PPALLOC (DMA_BASE+0x0288)
++#define DMAMP_RX_7_STATUS (DMA_BASE+0x028C)
++#define DMAMP_RX_7_REMAIN (DMA_BASE+0x0294)
++#define DMAMP_RX_7_MAXCNT0 (DMA_BASE+0x02A0)
++#define DMAMP_RX_7_BASE0 (DMA_BASE+0x02A4)
++#define DMAMP_RX_7_CURRENT0 (DMA_BASE+0x02A8)
++#define DMAMP_RX_7_MAXCNT1 (DMA_BASE+0x02B0)
++#define DMAMP_RX_7_BASE1 (DMA_BASE+0x02B4)
++#define DMAMP_RX_7_CURRENT1 (DMA_BASE+0x02B8)
++
++#define DMAMP_TX_6_CONTROL (DMA_BASE+0x02C0)
++#define DMAMP_TX_6_INTERRUPT (DMA_BASE+0x02C4)
++#define DMAMP_TX_6_PPALLOC (DMA_BASE+0x02C8)
++#define DMAMP_TX_6_STATUS (DMA_BASE+0x02CC)
++#define DMAMP_TX_6_REMAIN (DMA_BASE+0x02D4)
++#define DMAMP_TX_6_MAXCNT0 (DMA_BASE+0x02E0)
++#define DMAMP_TX_6_BASE0 (DMA_BASE+0x02E4)
++#define DMAMP_TX_6_CURRENT0 (DMA_BASE+0x02E8)
++#define DMAMP_TX_6_MAXCNT1 (DMA_BASE+0x02F0)
++#define DMAMP_TX_6_BASE1 (DMA_BASE+0x02F4)
++#define DMAMP_TX_6_CURRENT1 (DMA_BASE+0x02F8)
++
++#define DMAMP_RX_9_CONTROL (DMA_BASE+0x0300)
++#define DMAMP_RX_9_INTERRUPT (DMA_BASE+0x0304)
++#define DMAMP_RX_9_PPALLOC (DMA_BASE+0x0308)
++#define DMAMP_RX_9_STATUS (DMA_BASE+0x030C)
++#define DMAMP_RX_9_REMAIN (DMA_BASE+0x0314)
++#define DMAMP_RX_9_MAXCNT0 (DMA_BASE+0x0320)
++#define DMAMP_RX_9_BASE0 (DMA_BASE+0x0324)
++#define DMAMP_RX_9_CURRENT0 (DMA_BASE+0x0328)
++#define DMAMP_RX_9_MAXCNT1 (DMA_BASE+0x0330)
++#define DMAMP_RX_9_BASE1 (DMA_BASE+0x0334)
++#define DMAMP_RX_9_CURRENT1 (DMA_BASE+0x0338)
++
++#define DMAMP_TX_8_CONTROL (DMA_BASE+0x0340)
++#define DMAMP_TX_8_INTERRUPT (DMA_BASE+0x0344)
++#define DMAMP_TX_8_PPALLOC (DMA_BASE+0x0348)
++#define DMAMP_TX_8_STATUS (DMA_BASE+0x034C)
++#define DMAMP_TX_8_REMAIN (DMA_BASE+0x0354)
++#define DMAMP_TX_8_MAXCNT0 (DMA_BASE+0x0360)
++#define DMAMP_TX_8_BASE0 (DMA_BASE+0x0364)
++#define DMAMP_TX_8_CURRENT0 (DMA_BASE+0x0368)
++#define DMAMP_TX_8_MAXCNT1 (DMA_BASE+0x0370)
++#define DMAMP_TX_8_BASE1 (DMA_BASE+0x0374)
++#define DMAMP_TX_8_CURRENT1 (DMA_BASE+0x0378)
++
++#define DMA_ARBITRATION (DMA_BASE+0x0380)
++#define DMA_INTERRUPT (DMA_BASE+0x03C0)
++
++/*
++ * DMA Register Base addresses and Offsets
++ */
++#define DMA_M2P_TX_0_BASE DMAMP_TX_0_CONTROL
++#define DMA_M2P_RX_1_BASE DMAMP_RX_1_CONTROL
++#define DMA_M2P_TX_2_BASE DMAMP_TX_2_CONTROL
++#define DMA_M2P_RX_3_BASE DMAMP_RX_3_CONTROL
++#define DMA_M2M_0_BASE DMAMM_0_CONTROL
++#define DMA_M2M_1_BASE DMAMM_1_CONTROL
++#define DMA_M2P_RX_5_BASE DMAMP_RX_5_CONTROL
++#define DMA_M2P_TX_4_BASE DMAMP_TX_4_CONTROL
++#define DMA_M2P_RX_7_BASE DMAMP_RX_7_CONTROL
++#define DMA_M2P_TX_6_BASE DMAMP_TX_6_CONTROL
++#define DMA_M2P_RX_9_BASE DMAMP_RX_9_CONTROL
++#define DMA_M2P_TX_8_BASE DMAMP_TX_8_CONTROL
++
++#define M2P_OFFSET_CONTROL 0x0000
++#define M2P_OFFSET_INTERRUPT 0x0004
++#define M2P_OFFSET_PPALLOC 0x0008
++#define M2P_OFFSET_STATUS 0x000C
++#define M2P_OFFSET_REMAIN 0x0014
++#define M2P_OFFSET_MAXCNT0 0x0020
++#define M2P_OFFSET_BASE0 0x0024
++#define M2P_OFFSET_CURRENT0 0x0028
++#define M2P_OFFSET_MAXCNT1 0x0030
++#define M2P_OFFSET_BASE1 0x0034
++#define M2P_OFFSET_CURRENT1 0x0038
++
++#define M2M_OFFSET_CONTROL 0x0000
++#define M2M_OFFSET_INTERRUPT 0x0004
++#define M2M_OFFSET_STATUS 0x000C
++#define M2M_OFFSET_BCR0 0x0010
++#define M2M_OFFSET_BCR1 0x0014
++#define M2M_OFFSET_SAR_BASE0 0x0018
++#define M2M_OFFSET_SAR_BASE1 0x001C
++#define M2M_OFFSET_SAR_CURRENT0 0x0024
++#define M2M_OFFSET_SAR_CURRENT1 0x0028
++#define M2M_OFFSET_DAR_BASE0 0x002C
++#define M2M_OFFSET_DAR_BASE1 0x0030
++#define M2M_OFFSET_DAR_CURRENT0 0x0034
++#define M2M_OFFSET_DAR_CURRENT1 0x003C
++
++/*----------------------------------------------------------------*/
++/* 8001_0000 - 8001_ffff: Ether MAC */
++/*----------------------------------------------------------------*/
++#define MAC_OFFSET 0x010000
++#define MAC_BASE (EP93XX_AHB_BASE|MAC_OFFSET)
++
++#define MAC_RXCTL (MAC_BASE+0x00)
++#define MAC_TXCTL (MAC_BASE+0x04)
++#define MAC_TESTCTL (MAC_BASE+0x08)
++#define MAC_MIICMD (MAC_BASE+0x10)
++#define MAC_MIIDATA (MAC_BASE+0x14)
++#define MAC_MIISTS (MAC_BASE+0x18)
++#define MAC_SELFCTL (MAC_BASE+0x20)
++#define MAC_INTEN (MAC_BASE+0x24)
++#define MAC_INTSTSP (MAC_BASE+0x28)
++#define MAC_INTSTSC (MAC_BASE+0x2C)
++#define MAC_DIAGAD (MAC_BASE+0x38)
++#define MAC_DIAGDATA (MAC_BASE+0x3C)
++#define MAC_GT (MAC_BASE+0x40)
++#define MAC_FCT (MAC_BASE+0x44)
++#define MAC_FCF (MAC_BASE+0x48)
++#define MAC_AFP (MAC_BASE+0x4C)
++#define MAC_HASHTBL (MAC_BASE+0x50)
++#define MAC_INDAD (MAC_BASE+0x50)
++#define MAC_INDAD_UPPER (MAC_BASE+0x54)
++#define MAC_GIINTSTS (MAC_BASE+0x60)
++#define MAC_GIINTMSK (MAC_BASE+0x64)
++#define MAC_GIINTROSTS (MAC_BASE+0x68)
++#define MAC_GIINTFRC (MAC_BASE+0x6C)
++#define MAC_TXCOLLCNT (MAC_BASE+0x70)
++#define MAC_RXMISSCNT (MAC_BASE+0x74)
++#define MAC_RXRUNTCNT (MAC_BASE+0x78)
++#define MAC_BMCTL (MAC_BASE+0x80)
++#define MAC_BMSTS (MAC_BASE+0x84)
++#define MAC_RXBCA (MAC_BASE+0x88)
++#define MAC_RXDQBADD (MAC_BASE+0x90)
++#define MAC_RXDQBLEN (UINT16*)(MAC_BASE+0x94)
++#define MAC_RXDQCURLEN (UINT16*)(MAC_BASE+0x96)
++#define MAC_RXDCURADD (MAC_BASE+0x98)
++#define MAC_RXDENQ (MAC_BASE+0x9C)
++#define MAC_RXSTSQBADD (MAC_BASE+0xA0)
++#define MAC_RXSTSQBLEN (UINT16*)(MAC_BASE+0xA4)
++#define MAC_RXSTSQCURLEN (UINT16*)(MAC_BASE+0xA6)
++#define MAC_RXSTSQCURADD (MAC_BASE+0xA8)
++#define MAC_RXSTSENQ (MAC_BASE+0xAC)
++#define MAC_TXDQBADD (MAC_BASE+0xB0)
++#define MAC_TXDQBLEN (MAC_BASE+0xB4)
++#define MAC_TXDQCURLEN (MAC_BASE+0xB6)
++#define MAC_TXDQCURADD (MAC_BASE+0xB8)
++#define MAC_TXDENQ (MAC_BASE+0xBC)
++#define MAC_TXSTSQBADD (MAC_BASE+0xC0)
++#define MAC_TXSTSQBLEN (MAC_BASE+0xC4)
++#define MAC_TXSTSQCURLEN (MAC_BASE+0xC6)
++#define MAC_TXSTSQCURADD (MAC_BASE+0xC8)
++#define MAC_RXBUFTHRSHLD (MAC_BASE+0xD0)
++#define MAC_TXBUFTHRSHLD (MAC_BASE+0xD4)
++#define MAC_RXSTSTHRSHLD (MAC_BASE+0xD8)
++#define MAC_TXSTSTHRSHLD (MAC_BASE+0xDC)
++#define MAC_RXDTHRSHLD (MAC_BASE+0xE0)
++#define MAC_TXDTHRSHLD (MAC_BASE+0xE4)
++#define MAC_MAXFRMLEN (MAC_BASE+0xE8)
++#define MAC_RXHDRLEN (MAC_BASE+0xEC)
++
++#define MAC_FIFO (MAC_BASE+0x4000)
++#define MAC_FIFO_LEN 0xc000
++
++/*----------------------------------------------------------------*/
++/* 8002_0000 - 8002_ffff: USB */
++/*----------------------------------------------------------------*/
++#define USB_OFFSET 0x020000
++#define USB_BASE (EP93XX_AHB_BASE|USB_OFFSET)
++
++#define HCREVISION (USB_BASE+0x00)
++#define HCCONTROL (USB_BASE+0x04)
++#define HCCOMMANDSTATUS (USB_BASE+0x08)
++#define HCINTERRUPTSTATUS (USB_BASE+0x0C)
++#define HCINTERRUPTENABLE (USB_BASE+0x10)
++#define HCINTERRUPTDISABLE (USB_BASE+0x14)
++#define HCHCCA (USB_BASE+0x18)
++#define HCPERIODCURRENTED (USB_BASE+0x1C)
++#define HCCONTROLHEADED (USB_BASE+0x20)
++#define HCCONTROLCURRENTED (USB_BASE+0x24)
++#define HCBULKHEADED (USB_BASE+0x28)
++#define HCBULKCURRENTED (USB_BASE+0x2C)
++#define HCDONEHEAD (USB_BASE+0x30)
++#define HCFMINTERVAL (USB_BASE+0x34)
++#define HCFMREMAINING (USB_BASE+0x38)
++#define HCFMNUMBER (USB_BASE+0x3C)
++#define HCPERIODICSTART (USB_BASE+0x40)
++#define HCLSTHRESHOLD (USB_BASE+0x44)
++#define HCRHDESCRIPTORA (USB_BASE+0x48)
++#define HCRHDESCRIPTORB (USB_BASE+0x4C)
++#define HCRHSTATUS (USB_BASE+0x50)
++#define HCRHPORTSTATUS0 (USB_BASE+0x54)
++#define HCRHPORTSTATUS1 (USB_BASE+0x58) /* not in 9301 */
++#define HCRHPORTSTATUS2 (USB_BASE+0x5C)
++
++/* additional non-OHCI registers for controlling the AHB-HCI interface */
++#define USBCTRL (USB_BASE+0x80)
++#define USBHCISTS (USB_BASE+0x84)
++
++/* 8003_0000 - 8003_ffff: Raster */
++#define RASTER_OFFSET 0x030000
++#define RASTER_BASE (EP93XX_AHB_BASE|RASTER_OFFSET)
++#define VLINESTOTAL (RASTER_BASE+0x00)
++#define VSYNCSTRTSTOP (RASTER_BASE+0x04)
++#define VACTIVESTRTSTOP (RASTER_BASE+0x08)
++#define VCLKSTRTSTOP (RASTER_BASE+0x0C)
++#define HCLKSTOTAL (RASTER_BASE+0x10)
++#define HSYNCSTRTSTOP (RASTER_BASE+0x14)
++#define HACTIVESTRTSTOP (RASTER_BASE+0x18)
++#define HCLKSTRTSTOP (RASTER_BASE+0x1C)
++#define BRIGHTNESS (RASTER_BASE+0x20)
++#define VIDEOATTRIBS (RASTER_BASE+0x24)
++#define VIDSCRNPAGE (RASTER_BASE+0x28)
++#define VIDSCRNHPG (RASTER_BASE+0x2C)
++#define SCRNLINES (RASTER_BASE+0x30)
++#define LINELENGTH (RASTER_BASE+0x34)
++#define VLINESTEP (RASTER_BASE+0x38)
++#define LINECARRY (RASTER_BASE+0x3C)
++#define BLINKRATE (RASTER_BASE+0x40)
++#define BLINKMASK (RASTER_BASE+0x44)
++#define BLINKPATTRN (RASTER_BASE+0x48)
++#define PATTRNMASK (RASTER_BASE+0x4C)
++#define BG_OFFSET (RASTER_BASE+0x50)
++#define PIXELMODE (RASTER_BASE+0x54)
++#define PARLLIFOUT (RASTER_BASE+0x58)
++#define PARLLIFIN (RASTER_BASE+0x5C)
++#define CURSOR_ADR_START (RASTER_BASE+0x60)
++#define CURSOR_ADR_RESET (RASTER_BASE+0x64)
++#define CURSORSIZE (RASTER_BASE+0x68)
++#define CURSORCOLOR1 (RASTER_BASE+0x6C)
++#define CURSORCOLOR2 (RASTER_BASE+0x70)
++#define CURSORXYLOC (RASTER_BASE+0x74)
++#define CURSOR_DHSCAN_LH_YLOC (RASTER_BASE+0x78)
++#define REALITI_SWLOCK (RASTER_BASE+0x7C)
++#define GS_LUT (RASTER_BASE+0x80)
++#define REALITI_TCR (RASTER_BASE+0x100)
++#define REALITI_TISRA (RASTER_BASE+0x104)
++#define REALITI_TISRB (RASTER_BASE+0x108)
++#define CURSOR_TISR (RASTER_BASE+0x10C)
++#define REALITI_TOCRA (RASTER_BASE+0x110)
++#define REALITI_TOCRB (RASTER_BASE+0x114)
++#define FIFO_TOCRA (RASTER_BASE+0x118)
++#define FIFO_TOCRB (RASTER_BASE+0x11C)
++#define BLINK_TISR (RASTER_BASE+0x120)
++#define DAC_TISRA (RASTER_BASE+0x124)
++#define DAC_TISRB (RASTER_BASE+0x128)
++#define SHIFT_TISR (RASTER_BASE+0x12C)
++#define DACMUX_TOCRA (RASTER_BASE+0x130)
++#define DACMUX_TOCRB (RASTER_BASE+0x134)
++#define PELMUX_TOCR (RASTER_BASE+0x138)
++#define VIDEO_TOCRA (RASTER_BASE+0x13C)
++#define VIDEO_TOCRB (RASTER_BASE+0x140)
++#define YCRCB_TOCR (RASTER_BASE+0x144)
++#define CURSOR_TOCR (RASTER_BASE+0x148)
++#define VIDEO_TOCRC (RASTER_BASE+0x14C)
++#define SHIFT_TOCR (RASTER_BASE+0x150)
++#define BLINK_TOCR (RASTER_BASE+0x154)
++#define REALITI_TCER (RASTER_BASE+0x180)
++#define SIGVAL (RASTER_BASE+0x200)
++#define SIGCTL (RASTER_BASE+0x204)
++#define VSIGSTRTSTOP (RASTER_BASE+0x208)
++#define HSIGSTRTSTOP (RASTER_BASE+0x20C)
++#define SIGCLR (RASTER_BASE+0x210)
++#define ACRATE (RASTER_BASE+0x214)
++#define LUTCONT (RASTER_BASE+0x218)
++#define VBLANKSTRTSTOP (RASTER_BASE+0x228)
++#define HBLANKSTRTSTOP (RASTER_BASE+0x22C)
++#define LUT (RASTER_BASE+0x400)
++#define CURSORBLINK1 (RASTER_BASE+0x21C)
++#define CURSORBLINK2 (RASTER_BASE+0x220)
++#define CURSORBLINK (RASTER_BASE+0x224)
++#define EOLOFFSET (RASTER_BASE+0x230)
++#define FIFOLEVEL (RASTER_BASE+0x234)
++#define GS_LUT2 (RASTER_BASE+0x280)
++#define GS_LUT3 (RASTER_BASE+0x300)
++#define COLOR_LUT (RASTER_BASE+0x400)
++
++/* 8006_0000 - 8006_ffff: SDRAM */
++#define SDRAM_OFFSET 0x060000
++#define SDRAM_BASE (EP93XX_AHB_BASE|SDRAM_OFFSET)
++#define SDRAMGLOBALCFG (SDRAM_BASE+0x04)
++#define SDRAMREFRESHTIME (SDRAM_BASE+0x08) /* Refresh Timer */
++#define SDRAMBOOTSTATUS (SDRAM_BASE+0x0C)
++#define SDRAMCFG0 (SDRAM_BASE+0x10) /* Configuration Register 0 (nSDCS0) */
++#define SDRAMCFG1 (SDRAM_BASE+0x14) /* Configuration Register 1 (nSDCS1) */
++#define SDRAMCFG2 (SDRAM_BASE+0x18) /* Configuration Register 2 (nSDCS2) */
++#define SDRAMCFG3 (SDRAM_BASE+0x1C) /* Configuration Register 3 (nSDCS3) */
++
++/* 8008_0000 - 8008_ffff: SMC */
++#define SMC_OFFSET 0x080000
++#define SMC_BASE (EP93XX_AHB_BASE|SMC_OFFSET)
++#define SMCBCR0 (SMC_BASE+0x00) /* 0x8008.0000 Bank config register 0 */
++#define SMCBCR1 (SMC_BASE+0x04) /* 0x8008.0004 Bank config register 1 */
++#define SMCBCR2 (SMC_BASE+0x08) /* 0x8008.0008 Bank config register 2 */
++#define SMCBCR3 (SMC_BASE+0x0C) /* 0x8008.000C Bank config register 3 */
++#define SMCBCR6 (SMC_BASE+0x18) /* 0x8008.0018 Bank config register 6 */
++#define SMCBCR7 (SMC_BASE+0x1C) /* 0x8008.001C Bank config register 7 */
++#define PC1ATTRIB (SMC_BASE+0x20) /* 0x8008.0020 PC1 Attribute Register */
++#define PC1COMMON (SMC_BASE+0x24) /* 0x8008.0024 PC1 Common Register */
++#define PC1IO (SMC_BASE+0x28) /* 0x8008.0028 PC1 IO Register */
++#define PC2ATTRIB (SMC_BASE+0x30) /* 0x8008.0030 PC2 Attribute Register */
++#define PC2COMMON (SMC_BASE+0x34) /* 0x8008.0034 PC2 Common Register */
++#define PC2IO (SMC_BASE+0x38) /* 0x8008.0038 PC2 IO Register */
++#define PCMCIACNT (SMC_BASE+0x40) /* 0x8008.0040 PCMCIA control register */
++
++/* 8009_0000 - 8009_ffff: Boot ROM */
++#define BOOT_OFFSET 0x090000
++#define BOOT_BASE (EP93XX_AHB_BASE|BOOT_OFFSET)
++
++/* 800A_0000 - 800A_ffff: IDE Interface */
++#define IDE_OFFSET 0x0a0000
++#define IDE_BASE (EP93XX_AHB_BASE|IDE_OFFSET)
++/*#define IDECR (IDE_BASE+0x00)
++ *#define IDECFG (IDE_BASE+0x04)
++ *#define IDEMDMAOP (IDE_BASE+0x08)
++ *#define IDEUDMAOP (IDE_BASE+0x0C)
++ *#define IDEDATAOUT (IDE_BASE+0x10)
++ *#define IDEDATAIN (IDE_BASE+0x14)
++ *#define IDEMDMADATAOUT (IDE_BASE+0x18)
++ *#define IDEMDMADATAIN (IDE_BASE+0x1C)
++ *#define IDEUDMADATAOUT (IDE_BASE+0x20)
++ *#define IDEUDMADATAIN (IDE_BASE+0x24)
++ *#define IDEUDMASTATUS (IDE_BASE+0x28)
++ *#define IDEUDMADEBUG (IDE_BASE+0x2C)
++ *#define IDEUDMAWFST (IDE_BASE+0x30)
++ *#define IDEUDMARFST (IDE_BASE+0x34)
++ */
++
++/* 800B_0000 - 800B_FFFF: VIC 0 */
++#define VIC0_OFFSET 0x0B0000
++#define VIC0_BASE (EP93XX_AHB_BASE|VIC0_OFFSET)
++#define VIC0 (VIC0_BASE+0x000)
++#define VIC0IRQSTATUS (VIC0_BASE+0x000) /* R IRQ status register */
++#define VIC0FIQSTATUS (VIC0_BASE+0x004) /* R FIQ status register */
++#define VIC0RAWINTR (VIC0_BASE+0x008) /* R Raw interrupt status register */
++#define VIC0INTSELECT (VIC0_BASE+0x00C) /* R/W Interrupt select register */
++#define VIC0INTENABLE (VIC0_BASE+0x010) /* R/W Interrupt enable register */
++#define VIC0INTENCLEAR (VIC0_BASE+0x014) /* W Interrupt enable clear register */
++#define VIC0SOFTINT (VIC0_BASE+0x018) /* R/W Software interrupt register */
++#define VIC0SOFTINTCLEAR (VIC0_BASE+0x01C) /* R/W Software interrupt clear register */
++#define VIC0PROTECTION (VIC0_BASE+0x020) /* R/W Protection enable register */
++#define VIC0VECTADDR (VIC0_BASE+0x030) /* R/W Vector address register */
++#define VIC0DEFVECTADDR (VIC0_BASE+0x034) /* R/W Default vector address register */
++#define VIC0VECTADDR00 (VIC0_BASE+0x100) /* R/W Vector address 00 register */
++#define VIC0VECTADDR01 (VIC0_BASE+0x104) /* R/W Vector address 01 register */
++#define VIC0VECTADDR02 (VIC0_BASE+0x108) /* R/W Vector address 02 register */
++#define VIC0VECTADDR03 (VIC0_BASE+0x10C) /* R/W Vector address 03 register */
++#define VIC0VECTADDR04 (VIC0_BASE+0x110) /* R/W Vector address 04 register */
++#define VIC0VECTADDR05 (VIC0_BASE+0x114) /* R/W Vector address 05 register */
++#define VIC0VECTADDR06 (VIC0_BASE+0x118) /* R/W Vector address 06 register */
++#define VIC0VECTADDR07 (VIC0_BASE+0x11C) /* R/W Vector address 07 register */
++#define VIC0VECTADDR08 (VIC0_BASE+0x120) /* R/W Vector address 08 register */
++#define VIC0VECTADDR09 (VIC0_BASE+0x124) /* R/W Vector address 09 register */
++#define VIC0VECTADDR10 (VIC0_BASE+0x128) /* R/W Vector address 10 register */
++#define VIC0VECTADDR11 (VIC0_BASE+0x12C) /* R/W Vector address 11 register */
++#define VIC0VECTADDR12 (VIC0_BASE+0x130) /* R/W Vector address 12 register */
++#define VIC0VECTADDR13 (VIC0_BASE+0x134) /* R/W Vector address 13 register */
++#define VIC0VECTADDR14 (VIC0_BASE+0x138) /* R/W Vector address 14 register */
++#define VIC0VECTADDR15 (VIC0_BASE+0x13C) /* R/W Vector address 15 register */
++#define VIC0VECTCNTL00 (VIC0_BASE+0x200) /* R/W Vector control 00 register */
++#define VIC0VECTCNTL01 (VIC0_BASE+0x204) /* R/W Vector control 01 register */
++#define VIC0VECTCNTL02 (VIC0_BASE+0x208) /* R/W Vector control 02 register */
++#define VIC0VECTCNTL03 (VIC0_BASE+0x20C) /* R/W Vector control 03 register */
++#define VIC0VECTCNTL04 (VIC0_BASE+0x210) /* R/W Vector control 04 register */
++#define VIC0VECTCNTL05 (VIC0_BASE+0x214) /* R/W Vector control 05 register */
++#define VIC0VECTCNTL06 (VIC0_BASE+0x218) /* R/W Vector control 06 register */
++#define VIC0VECTCNTL07 (VIC0_BASE+0x21C) /* R/W Vector control 07 register */
++#define VIC0VECTCNTL08 (VIC0_BASE+0x220) /* R/W Vector control 08 register */
++#define VIC0VECTCNTL09 (VIC0_BASE+0x224) /* R/W Vector control 09 register */
++#define VIC0VECTCNTL10 (VIC0_BASE+0x228) /* R/W Vector control 10 register */
++#define VIC0VECTCNTL11 (VIC0_BASE+0x22C) /* R/W Vector control 11 register */
++#define VIC0VECTCNTL12 (VIC0_BASE+0x230) /* R/W Vector control 12 register */
++#define VIC0VECTCNTL13 (VIC0_BASE+0x234) /* R/W Vector control 13 register */
++#define VIC0VECTCNTL14 (VIC0_BASE+0x238) /* R/W Vector control 14 register */
++#define VIC0VECTCNTL15 (VIC0_BASE+0x23C) /* R/W Vector control 15 register */
++#define VIC0ITCR (VIC0_BASE+0x300) /* R/W Test control register */
++#define VIC0ITIP1 (VIC0_BASE+0x304) /* R Test input register (nVICIRQIN/nVICFIQIN) */
++#define VIC0ITIP2 (VIC0_BASE+0x308) /* R Test input register (VICVECTADDRIN) */
++#define VIC0ITOP1 (VIC0_BASE+0x30C) /* R Test output register (nVICIRQ/nVICFIQ) */
++#define VIC0ITOP2 (VIC0_BASE+0x310) /* R Test output register (VICVECTADDROUT) */
++#define VIC0PERIPHID0 (VIC0_BASE+0xFE0) /* R Peripheral ID register bits 7:0 */
++#define VIC0PERIPHID1 (VIC0_BASE+0xFE4) /* R Peripheral ID register bits 15:8 */
++#define VIC0PERIPHID2 (VIC0_BASE+0xFE8) /* R Peripheral ID register bits 23:16 */
++#define VIC0PERIPHID3 (VIC0_BASE+0xFEC) /* R Peripheral ID register bits 31:24 */
++
++/* 800C_0000 - 800C_FFFF: VIC 1 */
++#define VIC1_OFFSET 0x0C0000
++#define VIC1_BASE (EP93XX_AHB_BASE|VIC1_OFFSET)
++#define VIC1 (VIC1_BASE+0x000)
++#define VIC1IRQSTATUS (VIC1_BASE+0x000) /* R IRQ status register */
++#define VIC1FIQSTATUS (VIC1_BASE+0x004) /* R FIQ status register */
++#define VIC1RAWINTR (VIC1_BASE+0x008) /* R Raw interrupt status register */
++#define VIC1INTSELECT (VIC1_BASE+0x00C) /* R/W Interrupt select register */
++#define VIC1INTENABLE (VIC1_BASE+0x010) /* R/W Interrupt enable register */
++#define VIC1INTENCLEAR (VIC1_BASE+0x014) /* W Interrupt enable clear register */
++#define VIC1SOFTINT (VIC1_BASE+0x018) /* R/W Software interrupt register */
++#define VIC1SOFTINTCLEAR (VIC1_BASE+0x01C) /* R/W Software interrupt clear register */
++#define VIC1PROTECTION (VIC1_BASE+0x020) /* R/W Protection enable register */
++#define VIC1VECTADDR (VIC1_BASE+0x030) /* R/W Vector address register */
++#define VIC1DEFVECTADDR (VIC1_BASE+0x034) /* R/W Default vector address register */
++#define VIC1VECTADDR00 (VIC1_BASE+0x100) /* R/W Vector address 00 register */
++#define VIC1VECTADDR01 (VIC1_BASE+0x104) /* R/W Vector address 01 register */
++#define VIC1VECTADDR02 (VIC1_BASE+0x108) /* R/W Vector address 02 register */
++#define VIC1VECTADDR03 (VIC1_BASE+0x10C) /* R/W Vector address 03 register */
++#define VIC1VECTADDR04 (VIC1_BASE+0x110) /* R/W Vector address 04 register */
++#define VIC1VECTADDR05 (VIC1_BASE+0x114) /* R/W Vector address 05 register */
++#define VIC1VECTADDR06 (VIC1_BASE+0x118) /* R/W Vector address 06 register */
++#define VIC1VECTADDR07 (VIC1_BASE+0x11C) /* R/W Vector address 07 register */
++#define VIC1VECTADDR08 (VIC1_BASE+0x120) /* R/W Vector address 08 register */
++#define VIC1VECTADDR09 (VIC1_BASE+0x124) /* R/W Vector address 09 register */
++#define VIC1VECTADDR10 (VIC1_BASE+0x128) /* R/W Vector address 10 register */
++#define VIC1VECTADDR11 (VIC1_BASE+0x12C) /* R/W Vector address 11 register */
++#define VIC1VECTADDR12 (VIC1_BASE+0x130) /* R/W Vector address 12 register */
++#define VIC1VECTADDR13 (VIC1_BASE+0x134) /* R/W Vector address 13 register */
++#define VIC1VECTADDR14 (VIC1_BASE+0x138) /* R/W Vector address 14 register */
++#define VIC1VECTADDR15 (VIC1_BASE+0x13C) /* R/W Vector address 15 register */
++#define VIC1VECTCNTL00 (VIC1_BASE+0x200) /* R/W Vector control 00 register */
++#define VIC1VECTCNTL01 (VIC1_BASE+0x204) /* R/W Vector control 01 register */
++#define VIC1VECTCNTL02 (VIC1_BASE+0x208) /* R/W Vector control 02 register */
++#define VIC1VECTCNTL03 (VIC1_BASE+0x20C) /* R/W Vector control 03 register */
++#define VIC1VECTCNTL04 (VIC1_BASE+0x210) /* R/W Vector control 04 register */
++#define VIC1VECTCNTL05 (VIC1_BASE+0x214) /* R/W Vector control 05 register */
++#define VIC1VECTCNTL06 (VIC1_BASE+0x218) /* R/W Vector control 06 register */
++#define VIC1VECTCNTL07 (VIC1_BASE+0x21C) /* R/W Vector control 07 register */
++#define VIC1VECTCNTL08 (VIC1_BASE+0x220) /* R/W Vector control 08 register */
++#define VIC1VECTCNTL09 (VIC1_BASE+0x224) /* R/W Vector control 09 register */
++#define VIC1VECTCNTL10 (VIC1_BASE+0x228) /* R/W Vector control 10 register */
++#define VIC1VECTCNTL11 (VIC1_BASE+0x22C) /* R/W Vector control 11 register */
++#define VIC1VECTCNTL12 (VIC1_BASE+0x230) /* R/W Vector control 12 register */
++#define VIC1VECTCNTL13 (VIC1_BASE+0x234) /* R/W Vector control 13 register */
++#define VIC1VECTCNTL14 (VIC1_BASE+0x238) /* R/W Vector control 14 register */
++#define VIC1VECTCNTL15 (VIC1_BASE+0x23C) /* R/W Vector control 15 register */
++#define VIC1ITCR (VIC1_BASE+0x300) /* R/W Test control register */
++#define VIC1ITIP1 (VIC1_BASE+0x304) /* R Test input register (nVICIRQIN/nVICFIQIN) */
++#define VIC1ITIP2 (VIC1_BASE+0x308) /* R Test input register (VICVECTADDRIN) */
++#define VIC1ITOP1 (VIC1_BASE+0x30C) /* R Test output register (nVICIRQ/nVICFIQ) */
++#define VIC1ITOP2 (VIC1_BASE+0x310) /* R Test output register (VICVECTADDROUT) */
++#define VIC1PERIPHID0 (VIC1_BASE+0xFE0) /* R Peripheral ID register bits 7:0 */
++#define VIC1PERIPHID1 (VIC1_BASE+0xFE4) /* R Peripheral ID register bits 15:8 */
++#define VIC1PERIPHID2 (VIC1_BASE+0xFE8) /* R Peripheral ID register bits 23:16 */
++#define VIC1PERIPHID3 (VIC1_BASE+0xFEC) /* R Peripheral ID register bits 31:24 */
++
++/******************************************************************/
++/* EP93xx APB Blocks */
++/******************************************************************/
++/* */
++/* Start End Usage */
++/* 8080_0000 8080_FFFF: Reserved */
++/* 8081_0000 8081_FFFF: Timer */
++/* 8082_0000 8082_FFFF: I2S */
++/* 8083_0000 8083_FFFF: Security */
++/* 8084_0000 8084_FFFF: GPIO */
++/* 8085_0000 8085_FFFF: Reserved */
++/* 8086_0000 8086_FFFF: Reserved */
++/* 8087_0000 8087_FFFF: Reserved */
++/* 8088_0000 8088_FFFF: AC97 */
++/* 8089_0000 8089_FFFF: Reserved */
++/* 808A_0000 808A_FFFF: SPI */
++/* 808B_0000 808B_FFFF: IrDA */
++/* 808C_0000 808C_FFFF: UART1 */
++/* 808D_0000 808D_FFFF: UART2 */
++/* 808E_0000 808E_FFFF: UART3 */
++/* 808F_0000 808F_FFFF: Key Matrix */
++/* 8090_0000 8090_FFFF: Touch Screen */
++/* 8091_0000 8091_FFFF: PWM */
++/* 8092_0000 8092_FFFF: Real Time Clock */
++/* 8093_0000 8093_FFFF: Syscon */
++/* 8094_0000 8094_FFFF: Watchdog */
++/* 8095_0000 8FFF_FFFF: Reserved */
++/* */
++/******************************************************************/
++
++#define EP93XX_APB_BASE (IO_BASE_VIRT | 0x00800000)
++
++/*----------------------------------------------------------------*/
++/* 8081_0000 - 8081_ffff: Timers */
++/*----------------------------------------------------------------*/
++
++#define TIMERS_OFFSET 0x010000
++#define TIMERS_BASE (EP93XX_APB_BASE|TIMERS_OFFSET)
++
++#define TIMER1LOAD (TIMERS_BASE+0x00)
++#define TIMER1VALUE (TIMERS_BASE+0x04) /* RO */
++#define TIMER1CONTROL (TIMERS_BASE+0x08)
++#define TIMER1CLEAR (TIMERS_BASE+0x0C) /* WO */
++
++#define TIMER2LOAD (TIMERS_BASE+0x20)
++#define TIMER2VALUE (TIMERS_BASE+0x24) /* RO */
++#define TIMER2CONTROL (TIMERS_BASE+0x28)
++#define TIMER2CLEAR (TIMERS_BASE+0x2C) /* WO */
++
++#define TIMER3LOAD (TIMERS_BASE+0x80)
++#define TIMER3VALUE (TIMERS_BASE+0x84) /* RO */
++#define TIMER3CONTROL (TIMERS_BASE+0x88)
++#define TIMER3CLEAR (TIMERS_BASE+0x8C) /* WO */
++
++#define TIMER4VALUELOW (TIMERS_BASE+0x60)
++#define TIMER4VALUEHIGH (TIMERS_BASE+0x64)
++
++/* 8082_0000 - 8082_ffff: I2S */
++#define I2S_OFFSET 0x020000
++#define I2S_BASE (EP93XX_APB_BASE|I2S_OFFSET)
++
++#define I2STxClkCfg (I2S_BASE+0x00) /* 8082.0000 R/W Transmitter clock config register */
++#define I2SRxClkCfg (I2S_BASE+0x04) /* 8082.0004 R/W Receiver clock config register */
++#define I2SGlSts (I2S_BASE+0x08) /* 8082.0008 R/W SAI Global Status register. */
++#define I2SGlCtrl (I2S_BASE+0x0C) /* 8082.000C R/W SAI Global Control register */
++
++#define I2STX0Lft (I2S_BASE+0x10) /* 8082.0010 R/W Left TX data reg for channel 0 */
++#define I2STX0Rt (I2S_BASE+0x14) /* 8082.0014 R/W Right TX data reg for channel 0 */
++#define I2STX1Lft (I2S_BASE+0x18) /* 8082.0018 R/W Left TX data reg for channel 1 */
++#define I2STX1Rt (I2S_BASE+0x1C) /* 8082.001C R/W Right TX data reg for channel 1 */
++#define I2STX2Lft (I2S_BASE+0x20) /* 8082.0020 R/W Left TX data reg for channel 2 */
++#define I2STX2Rt (I2S_BASE+0x24) /* 8082.0024 R/W Right TX data reg for channel 2 */
++
++#define I2STXLinCtrlData (I2S_BASE+0x28) /* 8082.0028 R/W TX Line Control data register */
++#define I2STXCtrl (I2S_BASE+0x2C) /* 8082.002C R/W TX Control register */
++#define I2STXWrdLen (I2S_BASE+0x30) /* 8082.0030 R/W TX Word Length */
++#define I2STX0En (I2S_BASE+0x34) /* 8082.0034 R/W TX0 Channel Enable */
++#define I2STX1En (I2S_BASE+0x38) /* 8082.0038 R/W TX1 Channel Enable */
++#define I2STX2En (I2S_BASE+0x3C) /* 8082.003C R/W TX2 Channel Enable */
++
++#define I2SRX0Lft (I2S_BASE+0x40) /* 8082.0040 R Left RX data reg for channel 0 */
++#define I2SRX0Rt (I2S_BASE+0x44) /* 8082.0044 R Right RX data reg for channel 0 */
++#define I2SRX1Lft (I2S_BASE+0x48) /* 8082.0048 R Left RX data reg for channel 1 */
++#define I2SRX1Rt (I2S_BASE+0x4C) /* 8082.004c R Right RX data reg for channel 1 */
++#define I2SRX2Lft (I2S_BASE+0x50) /* 8082.0050 R Left RX data reg for channel 2 */
++#define I2SRX2Rt (I2S_BASE+0x54) /* 8082.0054 R Right RX data reg for channel 2 */
++
++#define I2SRXLinCtrlData (I2S_BASE+0x58) /* 8082.0058 R/W RX Line Control data register */
++#define I2SRXCtrl (I2S_BASE+0x5C) /* 8082.005C R/W RX Control register */
++#define I2SRXWrdLen (I2S_BASE+0x60) /* 8082.0060 R/W RX Word Length */
++#define I2SRX0En (I2S_BASE+0x64) /* 8082.0064 R/W RX0 Channel Enable */
++#define I2SRX1En (I2S_BASE+0x68) /* 8082.0068 R/W RX1 Channel Enable */
++#define I2SRX2En (I2S_BASE+0x6C) /* 8082.006C R/W RX2 Channel Enable */
++
++/* 8083_0000 - 8083_ffff: Security Block */
++#define SECURITY_OFFSET 0x030000
++#define SECURITY_BASE (EP93XX_APB_BASE|SECURITY_OFFSET)
++#define SECFLG (SECURITY_BASE+0x2400)
++#define SECEN (SECURITY_BASE+0x2410)
++#define UNIQID (SECURITY_BASE+0x2440)
++#define UNIQCHK (SECURITY_BASE+0x2450)
++#define UNIQVAL (SECURITY_BASE+0x2460)
++#define CLINBOOT (SECURITY_BASE+0x2480)
++#define CLINVADDR (SECURITY_BASE+0x2484)
++#define CLSETSKRNL (SECURITY_BASE+0x2488)
++#define CLSKRNL (SECURITY_BASE+0x248C)
++#define ITTMP (SECURITY_BASE+0x2490)
++#define ETBL1 (SECURITY_BASE+0x24A0)
++#define ETCL1 (SECURITY_BASE+0x24A4)
++#define ETAPL1 (SECURITY_BASE+0x24A8)
++#define ETSPTREG1 (SECURITY_BASE+0x24B0)
++#define ETSPTREG2 (SECURITY_BASE+0x24B4)
++#define ETSPTREG3 (SECURITY_BASE+0x24B8)
++
++#define SECID1 (SECURITY_BASE+0x2500)
++#define SECID2 (SECURITY_BASE+0x2504)
++#define SECCHK1 (SECURITY_BASE+0x2520)
++#define SECCHK2 (SECURITY_BASE+0x2524)
++#define SECVAL1 (SECURITY_BASE+0x2540)
++#define SECVAL2 (SECURITY_BASE+0x2544)
++
++#define UNIQID2 (SECURITY_BASE+0x2700)
++#define UNIQID3 (SECURITY_BASE+0x2704)
++#define UNIQID4 (SECURITY_BASE+0x2708)
++#define UNIQID5 (SECURITY_BASE+0x270C)
++#define UNIQCHK2 (SECURITY_BASE+0x2710)
++#define USRFLG (SECURITY_BASE+0x2714) /* llandre tells me this is also a CPU model flag */
++#define UNIQVAL2 (SECURITY_BASE+0x2720)
++#define UNIQVAL3 (SECURITY_BASE+0x2724)
++#define UNIQVAL4 (SECURITY_BASE+0x2728)
++#define TESTVAL (SECURITY_BASE+0x2744)
++#define TESTCHK (SECURITY_BASE+0x2754)
++#define ACHK1 (SECURITY_BASE+0x27A0)
++#define ACHK2 (SECURITY_BASE+0x27A4)
++#define PROCRESET (SECURITY_BASE+0x27A8)
++#define TESTIDR (SECURITY_BASE+0x27AC)
++#define AVAL1 (SECURITY_BASE+0x27B0)
++#define AVAL2 (SECURITY_BASE+0x27B4)
++#define AID1 (SECURITY_BASE+0x27C4)
++#define AID2 (SECURITY_BASE+0x27C8)
++#define ADYNREMAP (SECURITY_BASE+0x27D0)
++#define ALTTMP (SECURITY_BASE+0x27D4)
++#define PROCSIGN (SECURITY_BASE+0x27F0)
++
++#define ECLIDX (SECURITY_BASE+0x2800)
++#define ECLINE0 (SECURITY_BASE+0x2810)
++#define ECLINE1 (SECURITY_BASE+0x2814)
++#define ECLINE2 (SECURITY_BASE+0x2818)
++#define ECLINE3 (SECURITY_BASE+0x281C)
++#define ECLINE4 (SECURITY_BASE+0x2820)
++#define ECLINE5 (SECURITY_BASE+0x2824)
++#define ECLINE6 (SECURITY_BASE+0x2828)
++#define ECLINE7 (SECURITY_BASE+0x282C)
++#define ETWIDX1 (SECURITY_BASE+0x2840)
++#define ETWL1 (SECURITY_BASE+0x2844)
++#define ETWIDX2 (SECURITY_BASE+0x2848)
++#define ETWL2 (SECURITY_BASE+0x284C)
++
++#define ETSPT10 (SECURITY_BASE+0x4000)
++#define ETSPT11 (SECURITY_BASE+0x4004)
++#define ETSPT12 (SECURITY_BASE+0x4008)
++#define ETSPT13 (SECURITY_BASE+0x400C)
++
++#define ETSPT2000 (SECURITY_BASE+0x6000)
++#define ETSPT2020 (SECURITY_BASE+0x6020)
++#define ETSPT2024 (SECURITY_BASE+0x6024)
++
++/* 8084_0000 - 8084_ffff: GPIO */
++#define GPIO_OFFSET 0x040000
++#define GPIO_BASE (EP93XX_APB_BASE|GPIO_OFFSET)
++#define GPIO_PADR (GPIO_BASE+0x00)
++#define GPIO_PBDR (GPIO_BASE+0x04)
++#define GPIO_PCDR (GPIO_BASE+0x08)
++
++/* For support EP9301 - EP9302 arch */
++
++#if !defined(CONFIG_ARCH_EP9301) && !defined (CONFIG_ARCH_EP9302)
++#define GPIO_PDDR (GPIO_BASE+0x0C)
++#endif
++
++#define GPIO_PADDR (GPIO_BASE+0x10)
++#define GPIO_PBDDR (GPIO_BASE+0x14)
++#define GPIO_PCDDR (GPIO_BASE+0x18)
++
++/* For support EP9301 - EP9302 arch */
++
++#if !defined(CONFIG_ARCH_EP9301) && !defined (CONFIG_ARCH_EP9302)
++#define GPIO_PDDDR (GPIO_BASE+0x1C)
++#endif
++
++#define GPIO_PEDR (GPIO_BASE+0x20)
++#define GPIO_PEDDR (GPIO_BASE+0x24)
++#define GPIO_PFDR (GPIO_BASE+0x30)
++#define GPIO_PFDDR (GPIO_BASE+0x34)
++#define GPIO_PGDR (GPIO_BASE+0x38)
++#define GPIO_PGDDR (GPIO_BASE+0x3C)
++#define GPIO_PHDR (GPIO_BASE+0x40)
++#define GPIO_PHDDR (GPIO_BASE+0x44)
++#define GPIO_INTTYPE1 (GPIO_BASE+0x4C)
++#define GPIO_INTTYPE2 (GPIO_BASE+0x50)
++#define GPIO_FEOI (GPIO_BASE+0x54) /* WRITE ONLY - READ UNDEFINED */
++#define GPIO_INTEN (GPIO_BASE+0x58)
++#define GPIO_INTSTATUS (GPIO_BASE+0x5C)
++#define GPIO_RAWINTSTASUS (GPIO_BASE+0x60)
++#define GPIO_FDB (GPIO_BASE+0x64)
++#define GPIO_PAPINDR (GPIO_BASE+0x68)
++#define GPIO_PBPINDR (GPIO_BASE+0x6C)
++#define GPIO_PCPINDR (GPIO_BASE+0x70)
++#define GPIO_PDPINDR (GPIO_BASE+0x74)
++#define GPIO_PEPINDR (GPIO_BASE+0x78)
++#define GPIO_PFPINDR (GPIO_BASE+0x7C)
++#define GPIO_PGPINDR (GPIO_BASE+0x80)
++#define GPIO_PHPINDR (GPIO_BASE+0x84)
++#define GPIO_AINTTYPE1 (GPIO_BASE+0x90)
++#define GPIO_AINTTYPE2 (GPIO_BASE+0x94)
++#define GPIO_AEOI (GPIO_BASE+0x98) /* WRITE ONLY - READ UNDEFINED */
++#define GPIO_AINTEN (GPIO_BASE+0x9C)
++#define GPIO_INTSTATUSA (GPIO_BASE+0xA0)
++#define GPIO_RAWINTSTSTISA (GPIO_BASE+0xA4)
++#define GPIO_ADB (GPIO_BASE+0xA8)
++#define GPIO_BINTTYPE1 (GPIO_BASE+0xAC)
++#define GPIO_BINTTYPE2 (GPIO_BASE+0xB0)
++#define GPIO_BEOI (GPIO_BASE+0xB4) /* WRITE ONLY - READ UNDEFINED */
++#define GPIO_BINTEN (GPIO_BASE+0xB8)
++#define GPIO_INTSTATUSB (GPIO_BASE+0xBC)
++#define GPIO_RAWINTSTSTISB (GPIO_BASE+0xC0)
++#define GPIO_BDB (GPIO_BASE+0xC4)
++#define GPIO_EEDRIVE (GPIO_BASE+0xC8)
++/*#define Reserved (GPIO_BASE+0xCC) */
++#define GPIO_TCR (GPIO_BASE+0xD0) /* Test Registers */
++#define GPIO_TISRA (GPIO_BASE+0xD4) /* Test Registers */
++#define GPIO_TISRB (GPIO_BASE+0xD8) /* Test Registers */
++#define GPIO_TISRC (GPIO_BASE+0xDC) /* Test Registers */
++#define GPIO_TISRD (GPIO_BASE+0xE0) /* Test Registers */
++#define GPIO_TISRE (GPIO_BASE+0xE4) /* Test Registers */
++#define GPIO_TISRF (GPIO_BASE+0xE8) /* Test Registers */
++#define GPIO_TISRG (GPIO_BASE+0xEC) /* Test Registers */
++#define GPIO_TISRH (GPIO_BASE+0xF0) /* Test Registers */
++#define GPIO_TCER (GPIO_BASE+0xF4) /* Test Registers */
++
++/* 8088_0000 - 8088_ffff: Ac97 Controller (AAC) */
++#define AC97_OFFSET 0x080000
++#define AC97_BASE (EP93XX_APB_BASE|AC97_OFFSET)
++#define AC97DR1 (AC97_BASE+0x00) /* 8088.0000 R/W Data read or written from/to FIFO1 */
++#define AC97RXCR1 (AC97_BASE+0x04) /* 8088.0004 R/W Control register for receive */
++#define AC97TXCR1 (AC97_BASE+0x08) /* 8088.0008 R/W Control register for transmit */
++#define AC97SR1 (AC97_BASE+0x0C) /* 8088.000C R Status register */
++#define AC97RISR1 (AC97_BASE+0x10) /* 8088.0010 R Raw interrupt status register */
++#define AC97ISR1 (AC97_BASE+0x14) /* 8088.0014 R Interrupt Status */
++#define AC97IE1 (AC97_BASE+0x18) /* 8088.0018 R/W Interrupt Enable */
++#define AC97DR2 (AC97_BASE+0x20) /* 8088.0020 R/W Data read or written from/to FIFO2 */
++#define AC97RXCR2 (AC97_BASE+0x24) /* 8088.0024 R/W Control register for receive */
++#define AC97TXCR2 (AC97_BASE+0x28) /* 8088.0028 R/W Control register for transmit */
++#define AC97SR2 (AC97_BASE+0x2C) /* 8088.002C R Status register */
++#define AC97RISR2 (AC97_BASE+0x30) /* 8088.0030 R Raw interrupt status register */
++#define AC97ISR2 (AC97_BASE+0x34) /* 8088.0034 R Interrupt Status */
++#define AC97IE2 (AC97_BASE+0x38) /* 8088.0038 R/W Interrupt Enable */
++#define AC97DR3 (AC97_BASE+0x40) /* 8088.0040 R/W Data read or written from/to FIFO3. */
++#define AC97RXCR3 (AC97_BASE+0x44) /* 8088.0044 R/W Control register for receive */
++#define AC97TXCR3 (AC97_BASE+0x48) /* 8088.0048 R/W Control register for transmit */
++#define AC97SR3 (AC97_BASE+0x4C) /* 8088.004C R Status register */
++#define AC97RISR3 (AC97_BASE+0x50) /* 8088.0050 R Raw interrupt status register */
++#define AC97ISR3 (AC97_BASE+0x54) /* 8088.0054 R Interrupt Status */
++#define AC97IE3 (AC97_BASE+0x58) /* 8088.0058 R/W Interrupt Enable */
++#define AC97DR4 (AC97_BASE+0x60) /* 8088.0060 R/W Data read or written from/to FIFO4. */
++#define AC97RXCR4 (AC97_BASE+0x64) /* 8088.0064 R/W Control register for receive */
++#define AC97TXCR4 (AC97_BASE+0x68) /* 8088.0068 R/W Control register for transmit */
++#define AC97SR4 (AC97_BASE+0x6C) /* 8088.006C R Status register */
++#define AC97RISR4 (AC97_BASE+0x70) /* 8088.0070 R Raw interrupt status register */
++#define AC97ISR4 (AC97_BASE+0x74) /* 8088.0074 R Interrupt Status */
++#define AC97IE4 (AC97_BASE+0x78) /* 8088.0078 R/W Interrupt Enable */
++#define AC97S1DATA (AC97_BASE+0x80) /* 8088.0080 R/W Data received/transmitted on SLOT1 */
++#define AC97S2DATA (AC97_BASE+0x84) /* 8088.0084 R/W Data received/transmitted on SLOT2 */
++#define AC97S12DATA (AC97_BASE+0x88) /* 8088.0088 R/W Data received/transmitted on SLOT12 */
++#define AC97RGIS (AC97_BASE+0x8C) /* 8088.008C R/W Raw Global interrupt status register */
++#define AC97GIS (AC97_BASE+0x90) /* 8088.0090 R Global interrupt status register */
++#define AC97IM (AC97_BASE+0x94) /* 8088.0094 R/W Interrupt mask register */
++#define AC97EOI (AC97_BASE+0x98) /* 8088.0098 W Interrupt clear register */
++#define AC97GCR (AC97_BASE+0x9C) /* 8088.009C R/W Main Control register */
++#define AC97RESET (AC97_BASE+0xA0) /* 8088.00A0 R/W RESET control register. */
++#define AC97SYNC (AC97_BASE+0xA4) /* 8088.00A4 R/W SYNC control register. */
++#define AC97GCIS (AC97_BASE+0xA8) /* 8088.00A8 R Global chan FIFO int status register */
++
++/* 808A_0000 - 808A_ffff: SSP */
++#define SSP_OFFSET 0x0A0000
++#define SSP_BASE (EP93XX_APB_BASE|SSP_OFFSET)
++#define SSPCR0 (SSP_BASE+0x00)
++#define SSPCR1 (SSP_BASE+0x04)
++#define SSPDR (SSP_BASE+0x08)
++#define SSPSR (SSP_BASE+0x0c)
++#define SSPCPSR (SSP_BASE+0x10)
++#define SSPIIR (SSP_BASE+0x14)
++#define SSPICR (SSP_BASE+0x14)
++
++/* 808B_0000 - 808B_ffff: IrDA */
++#define IRDA_OFFSET 0x0B0000
++#define IRDA_BASE (EP93XX_APB_BASE|IRDA_OFFSET)
++#define IrEnable (IRDA_BASE+0x00)
++#define IrCtrl (IRDA_BASE+0x04)
++#define IrAdrMatchVal (IRDA_BASE+0x08)
++#define IrFlag (IRDA_BASE+0x0C)
++#define IrData (IRDA_BASE+0x10)
++#define IrDataTail1 (IRDA_BASE+0x14)
++#define IrDataTail2 (IRDA_BASE+0x18)
++#define IrDataTail3 (IRDA_BASE+0x1c)
++#define IrRIB (IRDA_BASE+0x20)
++#define IrTR0 (IRDA_BASE+0x24)
++#define IrDMACR (IRDA_BASE+0x28)
++#define SIRTR0 (IRDA_BASE+0x30)
++#define MISR (IRDA_BASE+0x80)
++#define MIMR (IRDA_BASE+0x84)
++#define MIIR (IRDA_BASE+0x88)
++#define FISR (IRDA_BASE+0x180)
++#define FIMR (IRDA_BASE+0x184)
++#define FIIR (IRDA_BASE+0x188)
++
++/* 808C_0000 - 808C_ffff: UART1 */
++#define UART1_OFFSET 0x0C0000
++#define UART1_BASE (EP93XX_APB_BASE|UART1_OFFSET)
++#define UART1DR (UART1_BASE+0x000)
++#define UART1RSR (UART1_BASE+0x004)
++#define UART1ECR (UART1_BASE+0x004)
++#define UART1CR_H (UART1_BASE+0x008)
++#define UART1CR_M (UART1_BASE+0x00C)
++#define UART1CR_L (UART1_BASE+0x010)
++#define UART1CR (UART1_BASE+0x014)
++#define UART1FR (UART1_BASE+0x018)
++#define UART1IIR (UART1_BASE+0x01C)
++#define UART1ICR (UART1_BASE+0x01C)
++#define UART1ILPR (UART1_BASE+0x020)
++#define UART1DMACR (UART1_BASE+0x028)
++#define UART1TMR (UART1_BASE+0x084)
++#define UART1MCR (UART1_BASE+0x100)
++#define UART1MSR (UART1_BASE+0x104)
++#define UART1TCR (UART1_BASE+0x108)
++#define UART1TISR (UART1_BASE+0x10C)
++#define UART1TOCR (UART1_BASE+0x110)
++#define HDLC1CR (UART1_BASE+0x20c)
++#define HDLC1AMV (UART1_BASE+0x210)
++#define HDLC1AMSK (UART1_BASE+0x214)
++#define HDLC1RIB (UART1_BASE+0x218)
++#define HDLC1SR (UART1_BASE+0x21c)
++
++/* 808d_0000 - 808d_ffff: UART2 */
++#define UART2_OFFSET 0x0D0000
++#define UART2_BASE (EP93XX_APB_BASE|UART2_OFFSET)
++#define UART2DR (UART2_BASE+0x00)
++#define UART2RSR (UART2_BASE+0x04) /* Read */
++#define UART2ECR (UART2_BASE+0x04) /* Write */
++#define UART2CR_H (UART2_BASE+0x08)
++#define UART2CR_M (UART2_BASE+0x0C)
++#define UART2CR_L (UART2_BASE+0x10)
++#define UART2CR (UART2_BASE+0x14)
++#define UART2FR (UART2_BASE+0x18)
++#define UART2IIR (UART2_BASE+0x1C) /* Read */
++#define UART2ICR (UART2_BASE+0x1C) /* Write */
++#define UART2ILPR (UART2_BASE+0x20)
++#define UART2DMACR (UART2_BASE+0x28)
++#define UART2TMR (UART2_BASE+0x84)
++
++/* 808e_0000 - 808e_ffff: UART3 */
++#define UART3_OFFSET 0x0E0000
++#define UART3_BASE (EP93XX_APB_BASE|UART3_OFFSET)
++#define UART3DR (UART3_BASE+0x00)
++#define UART3RSR (UART3_BASE+0x04) /* Read */
++#define UART3ECR (UART3_BASE+0x04) /* Write */
++#define UART3CR_H (UART3_BASE+0x08)
++#define UART3CR_M (UART3_BASE+0x0C)
++#define UART3CR_L (UART3_BASE+0x10)
++#define UART3CR (UART3_BASE+0x14)
++#define UART3FR (UART3_BASE+0x18)
++#define UART3IIR (UART3_BASE+0x1C) /* Read */
++#define UART3ICR (UART3_BASE+0x1C) /* Write */
++#define UART3ILPR (UART3_BASE+0x20)
++#define UART3DMACR (UART3_BASE+0x28)
++#define UART3TCR (UART3_BASE+0x80)
++#define UART3TISR (UART3_BASE+0x88)
++#define UART3TOCR (UART3_BASE+0x8C)
++#define UART3TMR (UART3_BASE+0x84)
++#define UART3MCR (UART3_BASE+0x100) /* Modem Control Reg */
++#define UART3MSR (UART3_BASE+0x104) /* Modem Status Reg */
++#define UART3HDLCCR (UART3_BASE+0x20C) /* HDLC Registers */
++#define UART3HDLCAMV (UART3_BASE+0x210) /* HDLC Registers */
++#define UART3HDLCAMSK (UART3_BASE+0x214) /* HDLC Registers */
++#define UART3HDLCCRIB (UART3_BASE+0x218) /* HDLC Registers */
++#define UART3HDLCSR (UART3_BASE+0x21C) /* HDLC Registers */
++
++/* 808f_0000 - 808f_ffff: KEY Matrix */
++#define KEY_OFFSET 0x0F0000
++#define KEY_BASE (EP93XX_APB_BASE|KEY_OFFSET)
++#define SCANINIT (KEY_BASE+0x00)
++#define KEY_DIAG (KEY_BASE+0x04)
++#define KEY_REG (KEY_BASE+0x08)
++#define KEY_TCR (KEY_BASE+0x10)
++#define KEY_TISR (KEY_BASE+0x14)
++#define KEY_TOCR (KEY_BASE+0x18)
++
++/* 8090_0000 - 8090_ffff: Analog Resistive Touchscreen */
++#define TOUCH_OFFSET 0x100000
++#define TOUCH_BASE (EP93XX_APB_BASE|TOUCH_OFFSET)
++#define TSSetup (TOUCH_BASE+0x00) /* R/W touchscreen controller setup control register. */
++#define TSXYMaxMin (TOUCH_BASE+0x04) /* R/W touchscreen controller max/min register. */
++#define TSXYResult (TOUCH_BASE+0x08) /* R touchscreen controller result register. */
++#define TSDischarge (TOUCH_BASE+0x0C) /* LOCKED R/W touchscreen Switch Matrix control register. */
++#define TSXSample (TOUCH_BASE+0x10) /* LOCKED R/W touchscreen Switch Matrix control register. */
++#define TSYSample (TOUCH_BASE+0x14) /* LOCKED R/W touchscreen Switch Matrix control register. */
++#define TSDirect (TOUCH_BASE+0x18) /* LOCKED R/W touchscreen Switch Matrix control register. */
++#define TSDetect (TOUCH_BASE+0x1C) /* LOCKED R/W touchscreen Switch Matrix control register. */
++#define TSSWLock (TOUCH_BASE+0x20) /* NA R/W touchscreen software lock register. */
++#define TSSetup2 (TOUCH_BASE+0x24) /* R/W touchscreen setup control register #2. */
++
++/* 8091_0000 - 8091_ffff: PWM */
++#define PWM_OFFSET 0x110000
++#define PWM_BASE (EP93XX_APB_BASE|PWM_OFFSET)
++#define PWM0_TC (PWM_BASE+0x00) /* 80910000 R/W PWM_0 Terminal Count */
++#define PWM0_DC (PWM_BASE+0x04) /* 80910004 R/W PWM_0 Duty Cycle */
++#define PWM0_EN (PWM_BASE+0x08) /* 80910008 R/W PWM_0 Enable */
++#define PWM0_INV (PWM_BASE+0x0C) /* 8091000C R/W PWM_0 Invert */
++#define PWM0_SYNC (PWM_BASE+0x10) /* 80910010 R/W PWM_0 Synchronous */
++#define PWM1_TC (PWM_BASE+0x20) /* 80910020 R/W PWM_1 Terminal Count */
++#define PWM1_DC (PWM_BASE+0x24) /* 80910024 R/W PWM_1 Duty Cycle */
++#define PWM1_EN (PWM_BASE+0x28) /* 80910028 R/W PWM_1 Enable */
++#define PWM1_INV (PWM_BASE+0x2C) /* 8091002C R/W PWM_1 Invert */
++#define PWM1_SYNC (PWM_BASE+0x30) /* 80910030 R/W PWM_1 Synchronous */
++
++/* 8092_0000 - 8092_ffff: RTC */
++#define RTC_OFFSET 0x120000
++#define RTC_BASE (EP93XX_APB_BASE|RTC_OFFSET)
++#define RTCDR (RTC_BASE+0x00)
++#define RTCMR (RTC_BASE+0x04)
++#define RTCSTAT (RTC_BASE+0x08) /* Read */
++#define RTCEOI (RTC_BASE+0x08) /* Write */
++#define RTCLR (RTC_BASE+0x0C)
++#define RTCCR (RTC_BASE+0x10)
++#define RTCSCOMP (RTC_BASE+0x108)
++
++/* 8093_0000 - 8093_ffff: CSC/Syscon PLL, clock control, & misc. stuff */
++#define SYSCON_OFFSET 0x130000
++#define SYSCON_BASE (EP93XX_APB_BASE|SYSCON_OFFSET)
++#define SYSCON_PWRSR (SYSCON_BASE+0x0000)
++#define SYSCON_PWRCNT (SYSCON_BASE+0x0004)
++#define SYSCON_HALT (SYSCON_BASE+0x0008)
++#define SYSCON_STBY (SYSCON_BASE+0x000c)
++#define SYSCON_BLEOI (SYSCON_BASE+0x0010)
++#define SYSCON_MCEOI (SYSCON_BASE+0x0014)
++#define SYSCON_TEOI (SYSCON_BASE+0x0018)
++#define SYSCON_STFCLR (SYSCON_BASE+0x001c)
++#define SYSCON_CLKSET1 (SYSCON_BASE+0x0020)
++#define SYSCON_CLKSET2 (SYSCON_BASE+0x0024)
++#define SYSCON_RESV00 (SYSCON_BASE+0x0028)
++#define SYSCON_RESV01 (SYSCON_BASE+0x002c)
++#define SYSCON_RESV02 (SYSCON_BASE+0x0030)
++#define SYSCON_RESV03 (SYSCON_BASE+0x0034)
++#define SYSCON_RESV04 (SYSCON_BASE+0x0038)
++#define SYSCON_RESV05 (SYSCON_BASE+0x003c)
++#define SYSCON_SCRREG0 (SYSCON_BASE+0x0040)
++#define SYSCON_SCRREG1 (SYSCON_BASE+0x0044)
++#define SYSCON_CLKTEST (SYSCON_BASE+0x0048)
++#define SYSCON_USBRESET (SYSCON_BASE+0x004c)
++#define SYSCON_APBWAIT (SYSCON_BASE+0x0050)
++#define SYSCON_BMAR (SYSCON_BASE+0x0054)
++#define SYSCON_BOOTCLR (SYSCON_BASE+0x0058)
++#define SYSCON_DEVCFG (SYSCON_BASE+0x0080)
++#define SYSCON_VIDDIV (SYSCON_BASE+0x0084)
++#define SYSCON_MIRDIV (SYSCON_BASE+0x0088)
++#define SYSCON_I2SDIV (SYSCON_BASE+0x008C)
++#define SYSCON_KTDIV (SYSCON_BASE+0x0090)
++#define SYSCON_CHIPID (SYSCON_BASE+0x0094)
++#define SYSCON_TSTCR (SYSCON_BASE+0x0098)
++#define SYSCON_SYSCFG (SYSCON_BASE+0x009C)
++#define SYSCON_SWLOCK (SYSCON_BASE+0x00C0)
++
++#define SYSCON_DEVCFG_KEYS 0x00000002
++#define SYSCON_DEVCFG_RasOnP3 0x00000010
++#define SYSCON_DEVCFG_GONK 0x08000000
++
++#define SYSCON_KTDIV_KEN 0x00008000
++
++/* 8094_0000 - 8094_ffff: Watchdog */
++#define WATCHDOG_OFFSET 0x140000
++#define WATCHDOG_BASE (EP93XX_APB_BASE|WATCHDOG_OFFSET)
++#define WATCHDOG (WATCHDOG_BASE+0x00)
++#define WDSTATUS (WATCHDOG_BASE+0x04)
++
++#endif /* __ASM_ARCH_HARDWARE_H */
+diff --git a/include/asm-arm/arch-ep93xx/regs_ac97.h b/include/asm-arm/arch-ep93xx/regs_ac97.h
+new file mode 100644
+index 0000000..efe0015
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_ac97.h
+@@ -0,0 +1,168 @@
++/*=============================================================================
++ * FILE: regs_ac97.h
++ *
++ * DESCRIPTION: Ac'97 Register Definition
++ *
++ * Copyright Cirrus Logic, 2001-2003
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *=============================================================================
++ */
++#ifndef _REGS_AC97_H_
++#define _REGS_AC97_H_
++
++/* Bit definitionses */
++#define AC97ISR_RIS 8
++#define AC97ISR_TIS 4
++#define AC97ISR_RTIS 2
++#define AC97ISR_TCIS 1
++
++#define AC97RGIS_SLOT1TXCOMPLETE 0x01
++#define AC97RGIS_SLOT2RXVALID 0x02
++#define AC97RGIS_GPIOTXCOMPLETE 0x04
++#define AC97RGIS_GPIOINTRX 0x08
++#define AC97RGIS_RWIS 0x10
++#define AC97RGIS_CODECREADY 0x20
++#define AC97RGIS_SLOT2TXCOMPLETE 0x40
++
++#define AC97SR_RXFE 0x0001
++#define AC97SR_TXFE 0x0002
++#define AC97SR_RXFF 0x0004
++#define AC97SR_TXFF 0x0008
++#define AC97SR_TXBUSY 0x0010
++#define AC97SR_RXOE 0x0020
++#define AC97SR_TXUE 0x0040
++
++#define AC97GSR_IFE 0x1
++#define AC97GSR_LOOP 0x2
++#define AC97GSR_OVERRIDECODECREADY 0x4
++
++#define AC97RESET_TIMEDRESET 0x1
++#define AC97RESET_FORCEDRESET 0x2
++#define AC97RESET_EFORCER 0x4
++
++#define AC97RXCR_REN 0x1
++
++#define AC97TXCR_TEN 0x1
++
++/*
++ * The Ac97 Codec registers, accessable through the Ac-link.
++ * These are not controller registers and are not memory mapped.
++ * Includes registers specific to CS4202 (Beavis).
++ */
++#define AC97_REG_OFFSET_MASK 0x0000007E
++
++#define AC97_00_RESET 0x00000000
++#define AC97_02_MASTER_VOL 0x00000002
++#define AC97_04_HEADPHONE_VOL 0x00000004
++#define AC97_06_MONO_VOL 0x00000006
++#define AC97_08_TONE 0x00000008
++#define AC97_0A_PC_BEEP_VOL 0x0000000A
++#define AC97_0C_PHONE_VOL 0x0000000C
++#define AC97_0E_MIC_VOL 0x0000000E
++#define AC97_10_LINE_IN_VOL 0x00000010
++#define AC97_12_CD_VOL 0x00000012
++#define AC97_14_VIDEO_VOL 0x00000014
++#define AC97_16_AUX_VOL 0x00000016
++#define AC97_18_PCM_OUT_VOL 0x00000018
++#define AC97_1A_RECORD_SELECT 0x0000001A
++#define AC97_1C_RECORD_GAIN 0x0000001C
++#define AC97_1E_RESERVED_1E 0x0000001E
++#define AC97_20_GENERAL_PURPOSE 0x00000020
++#define AC97_22_3D_CONTROL 0x00000022
++#define AC97_24_MODEM_RATE 0x00000024
++#define AC97_26_POWERDOWN 0x00000026
++#define AC97_28_EXT_AUDIO_ID 0x00000028
++#define AC97_2A_EXT_AUDIO_POWER 0x0000002A
++#define AC97_2C_PCM_FRONT_DAC_RATE 0x0000002C
++#define AC97_2E_PCM_SURR_DAC_RATE 0x0000002E
++#define AC97_30_PCM_LFE_DAC_RATE 0x00000030
++#define AC97_32_PCM_LR_ADC_RATE 0x00000032
++#define AC97_34_MIC_ADC_RATE 0x00000034
++#define AC97_36_6CH_VOL_C_LFE 0x00000036
++#define AC97_38_6CH_VOL_SURROUND 0x00000038
++#define AC97_3A_SPDIF_CONTROL 0x0000003A
++#define AC97_3C_EXT_MODEM_ID 0x0000003C
++#define AC97_3E_EXT_MODEM_POWER 0x0000003E
++#define AC97_40_LINE1_CODEC_RATE 0x00000040
++#define AC97_42_LINE2_CODEC_RATE 0x00000042
++#define AC97_44_HANDSET_CODEC_RATE 0x00000044
++#define AC97_46_LINE1_CODEC_LEVEL 0x00000046
++#define AC97_48_LINE2_CODEC_LEVEL 0x00000048
++#define AC97_4A_HANDSET_CODEC_LEVEL 0x0000004A
++#define AC97_4C_GPIO_PIN_CONFIG 0x0000004C
++#define AC97_4E_GPIO_PIN_TYPE 0x0000004E
++#define AC97_50_GPIO_PIN_STICKY 0x00000050
++#define AC97_52_GPIO_PIN_WAKEUP 0x00000052
++#define AC97_54_GPIO_PIN_STATUS 0x00000054
++#define AC97_56_RESERVED 0x00000056
++#define AC97_58_RESERVED 0x00000058
++#define AC97_5A_CRYSTAL_REV_N_FAB_ID 0x0000005A
++#define AC97_5C_TEST_AND_MISC_CTRL 0x0000005C
++#define AC97_5E_AC_MODE 0x0000005E
++#define AC97_60_MISC_CRYSTAL_CONTROL 0x00000060
++#define AC97_62_VENDOR_RESERVED 0x00000062
++#define AC97_64_DAC_SRC_PHASE_INCR 0x00000064
++#define AC97_66_ADC_SRC_PHASE_INCR 0x00000066
++#define AC97_68_RESERVED_68 0x00000068
++#define AC97_6A_SERIAL_PORT_CONTROL 0x0000006A
++#define AC97_6C_VENDOR_RESERVED 0x0000006C
++#define AC97_6E_VENDOR_RESERVED 0x0000006E
++#define AC97_70_BDI_CONFIG 0x00000070
++#define AC97_72_BDI_WAKEUP 0x00000072
++#define AC97_74_VENDOR_RESERVED 0x00000074
++#define AC97_76_CAL_ADDRESS 0x00000076
++#define AC97_78_CAL_DATA 0x00000078
++#define AC97_7A_VENDOR_RESERVED 0x0000007A
++#define AC97_7C_VENDOR_ID1 0x0000007C
++#define AC97_7E_VENDOR_ID2 0x0000007E
++
++#ifndef __ASSEMBLY__
++
++/* enum type for use with reg AC97_RECORD_SELECT */
++enum Ac97RecordSources {
++ RECORD_MIC = 0x0000,
++ RECORD_CD = 0x0101,
++ RECORD_VIDEO_IN = 0x0202,
++ RECORD_AUX_IN = 0x0303,
++ RECORD_LINE_IN = 0x0404,
++ RECORD_STEREO_MIX = 0x0505,
++ RECORD_MONO_MIX = 0x0606,
++ RECORD_PHONE_IN = 0x0707
++};
++
++#endif /* __ASSEMBLY__ */
++
++/*
++ * Sample rates supported directly in AC97_PCM_FRONT_DAC_RATE and
++ * AC97_PCM_LR_ADC_RATE.
++ */
++#define Ac97_Fs_8000 0x1f40
++#define Ac97_Fs_11025 0x2b11
++#define Ac97_Fs_16000 0x3e80
++#define Ac97_Fs_22050 0x5622
++#define Ac97_Fs_32000 0x7d00
++#define Ac97_Fs_44100 0xac44
++#define Ac97_Fs_48000 0xbb80
++
++/*
++ * RSIZE and TSIZE in AC97RXCR and AC97TXCR
++ */
++#define Ac97_SIZE_20 2
++#define Ac97_SIZE_18 1
++#define Ac97_SIZE_16 0
++#define Ac97_SIZE_12 3
++
++#endif /* _REGS_AC97_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_dma.h b/include/asm-arm/arch-ep93xx/regs_dma.h
+new file mode 100644
+index 0000000..926965d
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_dma.h
+@@ -0,0 +1,269 @@
++/*****************************************************************************
++ *
++ * linux/include/asm-arm/arch-ep93xx/regs_dma.h
++ *
++ * Register definitions for the ep93xx dma channel registers.
++ *
++ * Copyright (C) 2003 Cirrus Logic
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ ****************************************************************************/
++#ifndef _REGS_DMA_H_
++#define _REGS_DMA_H_
++
++/*****************************************************************************
++ * 0x8000.0000 -> 0x8000.003C M2P Channel 0 Registers (Tx)
++ * 0x8000.0040 -> 0x8000.007C M2P Channel 1 Registers (Rx)
++ * 0x8000.0080 -> 0x8000.00BC M2P Channel 2 Registers (Tx)
++ * 0x8000.00C0 -> 0x8000.00FC M2P Channel 3 Registers (Rx)
++ * 0x8000.0100 -> 0x8000.013C M2M Channel 0 Registers
++ * 0x8000.0140 -> 0x8000.017C M2M Channel 1 Registers
++ * 0x8000.0180 -> 0x8000.01BC Not Used
++ * 0x8000.01C0 -> 0x8000.01FC Not Used
++ * 0x8000.0200 -> 0x8000.023C M2P Channel 5 Registers (Rx)
++ * 0x8000.0240 -> 0x8000.027C M2P Channel 4 Registers (Tx)
++ * 0x8000.0280 -> 0x8000.02BC M2P Channel 7 Registers (Rx)
++ * 0x8000.02C0 -> 0x8000.02FC M2P Channel 6 Registers (Tx)
++ * 0x8000.0300 -> 0x8000.033C M2P Channel 9 Registers (Rx)
++ * 0x8000.0340 -> 0x8000.037C M2P Channel 8 Registers (Tx)
++ * 0x8000.0380 DMA Channel Arbitration register
++ * 0x8000.03C0 DMA Global Interrupt register
++ * 0x8000.03C4 -> 0x8000.03FC Not Used
++ *
++ *
++ * Internal M2P/P2M Channel Register Map
++ *
++ * Offset Name Access Bits Reset Value
++ * 0x00 CONTROL R/W 6 0
++ * 0x04 INTERRUPT R/W TC* 3 0
++ * 0x08 PPALLOC R/W 4 channel dependant
++ * (see reg description)
++ * 0x0C STATUS RO 8 0
++ * 0x10 reserved
++ * 0x14 REMAIN RO 16 0
++ * 0X18 Reserved
++ * 0X1C Reserved
++ * 0x20 MAXCNT0 R/W 16 0
++ * 0x24 BASE0 R/W 32 0
++ * 0x28 CURRENT0 RO 32 0
++ * 0x2C Reserved
++ * 0x30 MAXCNT1 R/W 16 0
++ * 0x34 BASE1 R/W 32 0
++ * 0X38 CURRENT1 RO 32 0
++ * 0X3C Reserved
++ *
++ * M2M Channel Register Map
++ * Offset Name Access Bits Reset Value
++ *
++ * 0x00 CONTROL R/W 22 0
++ * 0x04 INTERRUPT R/W TC* 3 0
++ * 0x08 Reserved
++ * 0x0C STATUS R/W TC* 14 0
++ * 0x10 BCR0 R/W 16 0
++ * 0x14 BCR1 R/W 16 0
++ * 0x18 SAR_BASE0 R/W 32 0
++ * 0x1C SAR_BASE1 R/W 32 0
++ * 0x20 Reserved
++ * 0x24 SAR_CURRENT0 RO 32 0
++ * 0x28 SAR_CURRENT1 RO 32 0
++ * 0x2C DAR_BASE0 R/W 32 0
++ * 0x30 DAR_BASE1 R/W 32 0
++ * 0x34 DAR_CURRENT0 RO 32 0
++ * 0X38 Reserved
++ * 0X3C DAR_CURRENT1 RO 32 0
++ * * Write this location once to clear the bit (see
++ * Interrupt/Status register description for which bits
++ * this rule applies to).
++ *
++ ****************************************************************************/
++
++#ifndef __ASSEMBLY__
++/*
++ * DMA Register Base addresses
++ */
++static unsigned int const DMAM2PChannelBase[10] = {
++ DMA_M2P_TX_0_BASE,
++ DMA_M2P_RX_1_BASE,
++ DMA_M2P_TX_2_BASE,
++ DMA_M2P_RX_3_BASE,
++ DMA_M2P_TX_4_BASE,
++ DMA_M2P_RX_5_BASE,
++ DMA_M2P_TX_6_BASE,
++ DMA_M2P_RX_7_BASE,
++ DMA_M2P_TX_8_BASE,
++ DMA_M2P_RX_9_BASE
++};
++
++static unsigned int const DMAM2MChannelBase[2] = {
++ DMA_M2M_0_BASE,
++ DMA_M2M_1_BASE
++};
++
++#endif /* __ASSEMBLY__ */
++
++/*----------------------------------------------------------------------------------*/
++/* M2P Registers */
++/*----------------------------------------------------------------------------------*/
++/*
++ * M2P CONTROL register bit defines
++ */
++#define CONTROL_M2P_STALLINTEN 0x00000001 /* Enables the STALL interrupt */
++#define CONTROL_M2P_NFBINTEN 0x00000002 /* Enables the NFB interrupt */
++#define CONTROL_M2P_CHERRORINTEN 0x00000008 /* Enables the ChError interrupt */
++#define CONTROL_M2P_ENABLE 0x00000010 /* Enables the channel */
++#define CONTROL_M2P_ABRT 0x00000020 /* Determines how DMA behaves in */
++ /* NEXT state with peripheral */
++ /* error */
++ /* 0: NEXT -> ON, ignore error */
++ /* 1: NEXT -> STALL, disable ch. */
++#define CONTROL_M2P_ICE 0x00000040 /* Ignore Channel Error */
++
++/*
++ * M2P INTERRUPT register bit defines
++ */
++#define INTERRUPT_M2P_STALLINT 0x00000001 /* Indicates channel stalled. */
++#define INTERRUPT_M2P_NFBINT 0x00000002 /* Indicates channel is hungry. */
++#define INTERRUPT_M2P_CHERRORINT 0x00000008 /* Peripheral detects error */
++
++/*
++ * STATUS register bit defines
++ */
++#define STATUS_M2P_STALL 0x00000001 /* A '1' indicates channel is */
++ /* stalled */
++#define STATUS_M2P_NFB 0x00000002 /* A '1' indicates channel has moved */
++ /* from NEXT state to ON state, but */
++ /* waiting for next buffer to be */
++ /* programmed. */
++#define STATUS_M2P_CHERROR 0x00000008 /* Enables the ChError interrupt */
++#define STATUS_M2P_CURRENT_MASK 0x00000030 /* Current state of the FSM */
++#define STATUS_M2P_CURRENT_SHIFT 4
++#define STATUS_M2P_NEXTBUFFER 0x00000040 /* Informs the int handler after an */
++ /* NFB int which pair of maxcnt and */
++ /* base regs to update. */
++#define STATUS_M2P_BYTES_MASK 0x0000f800 /* number of valid DMA data */
++#define STATUS_M2P_BYTES_SHIFT 7 /* currently in */
++ /* packer/unpacker */
++
++#define STATUS_M2P_DMA_NO_BUF 0x00000000
++#define STATUS_M2P_DMA_BUF_ON 0x00000010
++#define STATUS_M2P_DMA_BUF_NEXT 0x00000020
++
++/*
++ * Register masks to mask off reserved bits after reading register.
++ */
++#define M2P_MASK_PPALLOC 0x0000000f
++#define M2P_MASK_REMAIN 0x0000ffff
++#define M2P_MASK_MAXCNT0 0x0000ffff
++#define M2P_MASK_BASE0 0xffffffff
++#define M2P_MASK_CURRENT0 0xffffffff
++#define M2P_MASK_MAXCNT1 0x0000ffff
++#define M2P_MASK_BASE1 0xffffffff
++#define M2P_MASK_CURRENT1 0xffffffff
++
++/*----------------------------------------------------------------------------------*/
++/* M2M Registers */
++/*----------------------------------------------------------------------------------*/
++
++#define CONTROL_M2M_STALLINTEN 0x00000001 /* Enables the STALL interrupt */
++#define CONTROL_M2M_SCT 0x00000002 /* Source Copy Transfer. Setup a */
++ /* block transfer from 1 memory source */
++ /* location. */
++#define CONTROL_M2M_DONEINTEN 0x00000004 /* Enables the DONE interrupt which */
++ /* indicates if the xfer completed */
++ /* successfully */
++#define CONTROL_M2M_ENABLE 0x00000008 /* Enables the channel */
++#define CONTROL_M2M_START 0x00000010 /* Initiates the xfer. 'software trigger' */
++#define CONTROL_M2M_BWC_MASK 0x000001e0 /* Bandwidth control. Indicate number of */
++#define CONTROL_M2M_BWC_SHIFT 5 /* bytes in a transfer. */
++#define CONTROL_M2M_PW_MASK 0x00000600 /* Peripheral width. Used for xfers */
++#define CONTROL_M2M_PW_SHIFT 9 /* between memory and external peripheral. */
++ /* 00: byte, 01: halfword, 10: word. */
++#define CONTROL_M2M_DAH 0x00000800 /* Destination Address Hold */
++#define CONTROL_M2M_SAH 0x00001000 /* Source Address Hold */
++#define CONTROL_M2M_TM_MASK 0x00006000 /* Transfer Mode. 00: sw triggered, */
++#define CONTROL_M2M_TM_SHIFT 13 /* 01: hw initiated M2P, 01: hw initiated P2M */
++#define CONTROL_M2M_ETDP_MASK 0x00018000 /* End-of-Transfer/Terminal Count pin */
++#define CONTROL_M2M_ETDP_SHIFT 15 /* direction and polarity. */
++#define CONTROL_M2M_DACKP 0x00020000 /* DMA acknowledge pin polarity */
++
++#define CONTROL_M2M_DREQP_MASK 0x00180000 /* DMA request pin polarity. must be set */
++#define CONTROL_M2M_DREQP_SHIFT 19 /* before enable bit. */
++#define CONTROL_M2M_NFBINTEN 0x00200000 /* Enables generation of the NFB interrupt. */
++#define CONTROL_M2M_RSS_MASK 0x00c00000 /* Request source selection: */
++#define CONTROL_M2M_RSS_SHIFT 22 /* 000 - External DReq[0] */
++ /* 001 - External DReq[1] */
++ /* 01X - Internal SSPRx */
++ /* 10X - Internal SSPTx */
++ /* 11X - Internal IDE */
++#define CONTROL_M2M_NO_HDSK 0x01000000 /* No handshake. When set the peripheral doesn't */
++ /* require the regular handshake protocal. Must */
++ /* be set for SSP and IDE operations, optional */
++ /* for external peripherals. */
++#define CONTROL_M2M_PWSC_MASK 0xfe000000 /* Peripheral wait states count. Gives the latency */
++#define CONTROL_M2M_PWSC_SHIFT 25 /* (in PCLK cycles) needed by the peripheral to */
++ /* deassert its' request once the M2M xfer w/ DMA */
++ /* is complete. */
++
++/*
++ * M2M INTERRUPT register bit defines
++ */
++#define INTERRUPT_M2M_STALLINT 0x00000001 /* Stall interrupt indicates channel stalled. */
++#define INTERRUPT_M2M_DONEINT 0x00000002 /* Transaction done. */
++#define INTERRUPT_M2M_NFBINT 0x00000004 /* Next frame buffer interrupt indicates */
++ /* channel requires a new buffer */
++
++/*
++ * M2M STATUS register bit defines
++ */
++#define STATUS_M2M_STALL 0x00000001 /* A '1' indicates channel is stalled */
++#define STATUS_M2M_CURRENTSTATE_MASK 0x0000003e /* Indicates state of M2M Channel control */
++#define STATUS_M2M_CURRENTSTATE_SHIFT 1 /* FSM (0-2): */
++ /* 000 - IDLE, 001 - STALL, 010 - MEM_RD, */
++ /* 011 - MEM_WR, 100 - BWC_WAIT */
++ /* and M2M buffer FSM (3-2): */
++ /* 00 - NO_BUF, 01 - BUF_ON, 10 - BUF_NEXT */
++#define STATUS_M2M_DONE 0x00000040 /* Transfer completed successfully if 1. */
++#define STATUS_M2M_TCS_MASK 0x00000180 /* Terminal Count status. Indicates whether or */
++#define STATUS_M2M_TCS_SHIFT 7 /* or not the actual byte count reached */
++ /* programmed limit for buffer descriptor */
++#define STATUS_M2M_EOTS_MASK 0x00000600 /* End-of-Transfer status for buffer */
++#define STATUS_M2M_EOTS_SHIFT 9
++#define STATUS_M2M_NFB 0x00000800 /* A '1' indicates channel has moved */
++ /* from NEXT state to ON state, but the next */
++ /* byte count reg for next buffer has not been */
++ /* programmed yet. */
++#define STATUS_M2M_NB 0x00001000 /* NextBuffer status. Informs NFB service */
++ /* routine, after NFB int, which pair of buffer */
++ /* descriptor registers is free to update. */
++#define STATUS_M2M_DREQS 0x00002000 /* DREQ status. Reflects the status of the */
++ /* synchronized external peripherals DMA */
++ /* request signal. */
++
++/*
++ * Register masks to mask off reserved bits after reading register.
++ */
++#define M2M_MASK_BCR0 0x0000ffff
++#define M2M_MASK_BCR1 0x0000ffff
++#define M2M_MASK_SAR_BASE0 0xffffffff
++#define M2M_MASK_SAR_BASE1 0xffffffff
++#define M2M_MASK_SAR_CURRENT0 0xffffffff
++#define M2M_MASK_SAR_CURRENT1 0xffffffff
++#define M2M_MASK_DAR_BASE0 0xffffffff
++#define M2M_MASK_DAR_BASE1 0xffffffff
++#define M2M_MASK_DAR_CURRENT0 0xffffffff
++#define M2M_MASK_DAR_CURRENT1 0xffffffff
++
++#endif /* _REGS_DMA_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_gpio.h b/include/asm-arm/arch-ep93xx/regs_gpio.h
+new file mode 100644
+index 0000000..12397be
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_gpio.h
+@@ -0,0 +1,31 @@
++/*=======================================================================
++ *
++ * FILE: regs_gpio.h
++ *
++ * DESCRIPTION: GPIO Register Definition
++ *
++ * Copyright Cirrus Logic, 2001-2003
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *=======================================================================
++ */
++#ifndef _REGS_GPIO_H_
++#define _REGS_GPIO_H_
++
++/*
++ * This file intentionally blank.
++ */
++
++#endif /* _REGS_GPIO_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_hardcode.h b/include/asm-arm/arch-ep93xx/regs_hardcode.h
+new file mode 100644
+index 0000000..ecbc512
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_hardcode.h
+@@ -0,0 +1,110 @@
++/*
++ * File: linux/include/asm-arm/arch-ep93xx/regs_hardcode.h
++ *
++ * Handle 'Must-be-zero' and 'Must-be-one' values for various
++ * registers on different flavours of the EP93xx family.
++ *
++ * Copyright (C) 2004 Ray Lehtiniemi
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef __ASM_ARCH_HARDCODE_H
++#define __ASM_ARCH_HARDCODE_H
++
++#if defined(CONFIG_ARCH_EP9301)
++#define ep93xx_SYSCON_DEVCFG(v) (((v) & ~0x0460c220) | 0x08000d00)
++#define ep93xx_VIC0INTSELECT(v) (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTSELECT(v) (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_VIC0INTENABLE(v) (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTENABLE(v) (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_VIC0INTENCLEAR(v) (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTENCLEAR(v) (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_MAC_RXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_UART1MCR(v) (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_UART2TMR(v) (((v) & ~0x000000fd) | 0x00000000)
++#define ep93xx_IrCtrl(v) (((v) & ~0x00000001) | 0x00000000)
++#define ep93xx_RTCSCOMP(v) (((v) & ~0x00200000) | 0x00000000)
++
++/* cut'n'paste from 9301, verify this section... */
++#elif defined(CONFIG_ARCH_EP9302)
++#define ep93xx_SYSCON_DEVCFG(v) (((v) & ~0x0460c220) | 0x08000d00)
++#define ep93xx_VIC0INTSELECT(v) (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTSELECT(v) (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_VIC0INTENABLE(v) (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTENABLE(v) (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_VIC0INTENCLEAR(v) (((v) & ~0xf8080000) | 0x00000000)
++#define ep93xx_VIC1INTENCLEAR(v) (((v) & ~0x06879a04) | 0x00000000)
++#define ep93xx_MAC_RXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_UART1MCR(v) (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_UART2TMR(v) (((v) & ~0x000000fd) | 0x00000000)
++#define ep93xx_IrCtrl(v) (((v) & ~0x00000001) | 0x00000000)
++#define ep93xx_RTCSCOMP(v) (((v) & ~0x00200000) | 0x00000000)
++
++#elif defined(CONFIG_ARCH_EP9312)
++#define ep93xx_SYSCON_DEVCFG(v) (((v) & ~0x00000020) | 0x00000000)
++#define ep93xx_VIC0INTSELECT(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTSELECT(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC0INTENABLE(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTENABLE(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC0INTENCLEAR(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTENCLEAR(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_PIXELMODE(v) (((v) & ~0x00010000) | 0x00000000)
++#define ep93xx_MAC_RXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_UART1MCR(v) (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_UART2TMR(v) (((v) & ~0x000000fd) | 0x00000000)
++#define ep93xx_UART3MCR(v) (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_IrCtrl(v) (((v) & ~0x00000001) | 0x00000000)
++#define ep93xx_RTCSCOMP(v) (((v) & ~0x00200000) | 0x00000000)
++
++#elif defined(CONFIG_ARCH_EP9315)
++#define ep93xx_SYSCON_DEVCFG(v) (((v) & ~0x00000020) | 0x00000000)
++#define ep93xx_VIC0INTSELECT(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTSELECT(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC0INTENABLE(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTENABLE(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC0INTENCLEAR(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_VIC1INTENCLEAR(v) (((v) & ~0x00000000) | 0x00000000)
++#define ep93xx_PIXELMODE(v) (((v) & ~0x00010000) | 0x00000000)
++#define ep93xx_MAC_RXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXBUFTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXSTSTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_RXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_MAC_TXDTHRSHLD(v) (((v) & ~0x00030003) | 0x00000000)
++#define ep93xx_UART1MCR(v) (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_UART2TMR(v) (((v) & ~0x000000fd) | 0x00000000)
++#define ep93xx_UART3MCR(v) (((v) & ~0x000000e0) | 0x00000000)
++#define ep93xx_IrCtrl(v) (((v) & ~0x00000001) | 0x00000000)
++#define ep93xx_RTCSCOMP(v) (((v) & ~0x00200000) | 0x00000000)
++
++#endif
++
++#endif /* __ASM_ARCH_HARDWARE_H */
+diff --git a/include/asm-arm/arch-ep93xx/regs_i2s.h b/include/asm-arm/arch-ep93xx/regs_i2s.h
+new file mode 100644
+index 0000000..2ca60df
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_i2s.h
+@@ -0,0 +1,91 @@
++/*=============================================================================
++ *
++ * FILE: reg_i2s.h
++ *
++ * DESCRIPTION: ep93xx I2S Register Definition
++ *
++ * Copyright Cirrus Logic, 2001-2003
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ *=============================================================================
++ */
++#ifndef _REG_I2S_H_
++#define _REG_I2S_H_
++
++/* I2STXClkCfg bits */
++#define i2s_txcc_trls 0x00000001
++#define i2s_txcc_tckp 0x00000002
++#define i2s_txcc_trel 0x00000004
++#define i2s_txcc_mstr 0x00000008
++#define i2s_txcc_nbcg 0x00000010
++
++#define i2s_txcc_bcr_32x 0x00000020
++#define i2s_txcc_bcr_64x 0x00000040
++#define i2s_txcc_bcr_128x 0x00000060
++
++/* I2SRxClkCfg bits */
++#define i2s_rxcc_rrls 0x00000001
++#define i2s_rxcc_rckp 0x00000002
++#define i2s_rxcc_rrel 0x00000004
++#define i2s_rxcc_mstr 0x00000008
++#define i2s_rxcc_nbcg 0x00000010
++
++#define i2s_rxcc_bcr_32x 0x00000020
++#define i2s_rxcc_bcr_64x 0x00000040
++#define i2s_rxcc_bcr_128x 0x00000060
++
++/* I2SGlSts bits */
++#define TX0_UNDERFLOW 0x00000001
++#define TX1_UNDERFLOW 0x00000002
++#define TX2_UNDERFLOW 0x00000004
++
++#define RX0_OVERFLOW 0x00000008
++#define RX1_OVERFLOW 0x00000010
++#define RX2_OVERFLOW 0x00000020
++
++#define TX0_OVERFLOW 0x00000040
++#define TX1_OVERFLOW 0x00000080
++#define TX2_OVERFLOW 0x00000100
++
++#define RX0_UNDERFLOW 0x00000200
++#define RX1_UNDERFLOW 0x00000400
++#define RX2_UNDERFLOW 0x00000800
++
++#define TX0_FIFO_FULL 0x00001000
++#define TX0_FIFO_EMPTY 0x00002000
++#define TX0_FIFO_HALF_EMPTY 0x00004000
++
++#define RX0_FIFO_FULL 0x00008000
++#define RX0_FIFO_EMPTY 0x00010000
++#define RX0_FIFO_HALF_FULL 0x00020000
++
++#define TX1_FIFO_FULL 0x00040000
++#define TX1_FIFO_EMPTY 0x00080000
++#define TX1_FIFO_HALF_EMPTY 0x00100000
++
++#define RX1_FIFO_FULL 0x00200000
++#define RX1_FIFO_EMPTY 0x00400000
++#define RX1_FIFO_HALF_FULL 0x00800000
++
++#define TX2_FIFO_FULL 0x01000000
++#define TX2_FIFO_EMPTY 0x02000000
++#define TX2_FIFO_HALF_EMPTY 0x04000000
++
++#define RX2_FIFO_FULL 0x08000000
++#define RX2_FIFO_EMPTY 0x10000000
++#define RX2_FIFO_HALF_FULL 0x20000000
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/regs_ide.h b/include/asm-arm/arch-ep93xx/regs_ide.h
+new file mode 100644
+index 0000000..762ebfd
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_ide.h
+@@ -0,0 +1,250 @@
++/*****************************************************************************
++ *
++ * linux/include/asm-arm/arch-ep93xx/regs_ide.h
++ *
++ * Register definitions for the ep93xx ide registers.
++ *
++ * Copyright (C) 2003 Cirrus Logic
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++
++ *
++ ****************************************************************************/
++#ifndef _REGS_IDE_H_
++#define _REGS_IDE_H_
++
++#ifndef __ASSEMBLY__
++
++/*****************************************************************************
++ *
++ * IDE register definitions
++ *
++ ****************************************************************************/
++typedef struct _ide_regs_s {
++ union {
++ unsigned int Value;
++ } IDECR; /* 00 */
++
++ union {
++ struct {
++ unsigned int IDEEN:1; /* IDE master enable */
++ unsigned int PIO:1; /* Polled IO operation selection */
++ unsigned int MDMA:1; /* Multiword DMA operation selection */
++ unsigned int UDMA:1; /* Ultra DMA operation selection */
++ unsigned int MODE:4; /* Speed mode number (0 - 4 for PIO, */
++ /* 0 - 2 for MDMA, 0 - 4 for UDMA) */
++ unsigned int WST:2; /* Wait State for Turn. Number of */
++ /* HCLK cycles to hold the data bus */
++ /* after */
++ /* PIO write operation */
++ unsigned int RAZ:22; /* read only always zero */
++ } Field;
++ unsigned int Value;
++ } IDECFG; /* 04 */
++
++ union {
++ struct {
++ unsigned int MEN:1; /* Enable Multiword DMA operation. */
++ /* 1 - start mdma, 0 - terminate */
++ /* mdma operation by host. */
++ unsigned int RWOP:1; /* Read or write operation selection: */
++ /* 0 = read, 1 = write. */
++ unsigned int RAZ:30; /* read only always zero */
++ } Field;
++ unsigned int Value;
++ } IDEMDMAOP; /* 08 */
++
++ union {
++ struct {
++ unsigned int UEN:1; /* Enable Ultra DMA operation */
++ /* 1 - start udma, 0 - terminate */
++ /* udma operation by host. */
++ unsigned int RWOP:1; /* Read or write operation selection: */
++ /* 0 = read, 1 = write. */
++ unsigned int RAZ:30; /* read only always zero */
++ } Field;
++ unsigned int Value;
++ } IDEUDMAOP; /* 0C */
++
++ union {
++ unsigned int Value;
++ } IDEDATAOUT; /* 10 */
++
++ union {
++ unsigned int Value;
++ } IDEDATAIN; /* 14 */
++
++ union {
++ struct {
++ unsigned int IDEDD:32; /* IDE output data in the output buffer */
++ /* in MDMA mode. This register should */
++ /* only be written to by the DMA engine. */
++ } Field;
++ unsigned int Value;
++ } IDEMDMADATAOUT; /* 18 */
++
++ union {
++ struct {
++ unsigned int IDEDD:32; /* IDE input data in the input buffer */
++ /* in MDMA mode. */
++ } Field;
++ unsigned int Value;
++ } IDEMDMADATAIN; /* 1C */
++
++ union {
++ struct {
++ unsigned int IDEDD:32; /* IDE output data at the tail of the */
++ /* output buffer in UDMA mode. */
++ } Field;
++ unsigned int Value;
++ } IDEUDMADATAOUT; /* 20 */
++
++ union {
++ struct {
++ unsigned int IDEDD:32; /* IDE input data at teh head of the */
++ /* input buffer in UDMA mode. */
++ } Field;
++ unsigned int Value;
++ } IDEUDMADATAIN; /* 24 */
++
++ union {
++ struct {
++ unsigned int CS0n:1; /* Chip select pin 0 status. Should */
++ /* be driven to 1 (deasserted) in UDMA */
++ unsigned int CS1n:1; /* Chip select pin 1 status. Should */
++ /* be driven to 1 (deasserted) in UDMA */
++ unsigned int DA:3; /* Device address status, should be */
++ /* driven to 0 (deasserted) in UDMA */
++ unsigned int HSHD:1; /* HSTROBE (during data out) status, */
++ /* HDMARDYn (during data in) status, */
++ /* driven by UDMA state machine. */
++ unsigned int STOP:1; /* STOP (during data out) status, driven */
++ /* by UDMA state machine. */
++ unsigned int DM:1; /* DMACKn status, driven by UDMA state */
++ /* machine. */
++ unsigned int DDOE:1; /* DD bus output enable as controlled */
++ /* by UDMA state machine. */
++ unsigned int DMARQ:1; /* Synchronized version of DMARQ input */
++ /* from device. */
++ unsigned int DSDD:1; /* DSTROBE (during data in) and DDMARDYn */
++ /* (during data out) status from device. */
++ unsigned int RAZ1:5; /* reserved, always zero */
++ unsigned int DMAIDE:1; /* DMA request signal from UDMA state */
++ /* machine. */
++ unsigned int INTIDE:1; /* INT line generated by UDMA state */
++ /* machine. */
++ unsigned int SBUSY:1; /* UDMA state machine busy, not in idle */
++ /* state. */
++ unsigned int RAZ2:5; /* Reserved, always zero. */
++ unsigned int NDO:1; /* Error for data out not completed */
++ unsigned int NDI:1; /* Error for data in not completed */
++ unsigned int N4X:1; /* Error for data transferred not */
++ /* multiples of 4 32 bit words. */
++ unsigned int RAZ3:5; /* Reserved, always zero */
++ } Field;
++ unsigned int Value;
++ } IDEUDMASTATUS; /* 28 */
++
++ union {
++ struct {
++ unsigned int RWOE:1; /* Reset UDMA write data out error. */
++ unsigned int RWPTR:1; /* Reset UDMA write buffer ptr to 0. */
++ unsigned int RWDR:1; /* Reset UDMA write DMA request. */
++ unsigned int RROE:1; /* Reset UDMA read data in error. */
++ unsigned int RRPTR:1; /* Reset UDMA read buffer ptr to 0. */
++ unsigned int RRDR:1; /* Reset UDMA read DMA request. */
++ unsigned int RAZ:26; /* reserved, always zero */
++ } Field;
++ unsigned int Value;
++ } IDEUDMADEBUG; /* 2C */
++
++ union {
++ struct {
++ unsigned int HPTR:4; /* Head pointer in the write buffer */
++ unsigned int TPTR:4; /* Tail pointer in the write buffer */
++ unsigned int EMPTY:1; /* Write buffer empty status */
++ unsigned int HOM:1; /* Half or more entries in write buffer */
++ /* filled status */
++ unsigned int NFULL:1; /* Write buffer near full status */
++ unsigned int FULL:1; /* Write buffer full status */
++ unsigned int RAZ:4; /* Reserved, always zero */
++ unsigned int CRC:16; /* CRC result for data operation */
++ /* TODO: is there a CRC? */
++ } Field;
++ unsigned int Value;
++ } IDEUDMAWFST; /* 30 */
++
++ union {
++ struct {
++ unsigned int HPTR:4; /* Head pointer in the read buffer */
++ unsigned int TPTR:4; /* Tail pointer in the read buffer */
++ unsigned int EMPTY:1; /* Read buffer empty status */
++ unsigned int HOM:1; /* Half or more entries in read buffer */
++ /* filled status */
++ unsigned int NFULL:1; /* Read buffer near full status */
++ unsigned int FULL:1; /* Read buffer full status */
++ unsigned int RAZ:4; /* Reserved, always zero */
++ unsigned int CRC:16; /* CRC result for data operation */
++ /* TODO: is there a CRC? */
++ } Field;
++ unsigned int Value;
++ } IDEUDMARFST; /* 34 */
++
++} IDEREGISTERS;
++
++/*****************************************************************************
++ *
++ * Global Register Anchor Definitions (these address values will change)
++ *
++ ****************************************************************************/
++#ifdef CONFIG_BLK_DEV_EP93XX
++static volatile IDEREGISTERS *const ep93xx_ide_regs =
++ (IDEREGISTERS *) (IDE_BASE);
++#endif
++
++#endif /* Not __ASSEMBLY__ */
++
++#define IDECtrl HW_REG(io_p2v(0x800a0000))
++#define IDECfg HW_REG(io_p2v(0x800a0004))
++#define IDEMDMAOp HW_REG(io_p2v(0x800a0008))
++#define IDEUDMAOp HW_REG(io_p2v(0x800a000c))
++#define IDEDataOut HW_REG(io_p2v(0x800a0010))
++#define IDEDataIn HW_REG(io_p2v(0x800a0014))
++#define IDEMDMADataOut HW_REG(io_p2v(0x800a0018))
++#define IDEMDMADataIn HW_REG(io_p2v(0x800a001c))
++#define IDEUDMADataOut HW_REG(io_p2v(0x800a0020))
++#define IDEUDMADataIn HW_REG(io_p2v(0x800a0024))
++#define IDEUDMASts HW_REG(io_p2v(0x800a0028))
++#define IDEUDMADebug HW_REG(io_p2v(0x800a002c))
++#define IDEUDMAWrBufSts HW_REG(io_p2v(0x800a0030))
++#define IDEUDMARdBufSts HW_REG(io_p2v(0x800a0034))
++
++/*****************************************************************************
++ *
++ * Bit definitions for use with assembly code for the ide control register.
++ *
++ ****************************************************************************/
++#define IDECtrl_CS0n 0x00000001
++#define IDECtrl_CS1n 0x00000002
++#define IDECtrl_DA_MASK 0x0000001c
++#define IDECtrl_DA_SHIFT 2
++#define IDECtrl_DIORn 0x00000020
++#define IDECtrl_DIOWn 0x00000040
++#define IDECtrl_DASPn 0x00000080
++#define IDECtrl_DMARQ 0x00000100
++#define IDECtrl_INTRQ 0x00000200
++#define IDECtrl_IORDY 0x00000400
++
++#endif /* _REGS_IDE_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_irda.h b/include/asm-arm/arch-ep93xx/regs_irda.h
+new file mode 100644
+index 0000000..77edafa
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_irda.h
+@@ -0,0 +1,24 @@
++/*=======================================================================
++ *
++ * FILE: regs_irda.h
++ *
++ * DESCRIPTION: IrDA Register Definition
++ *
++ * Copyright Cirrus Logic, 2001-2003
++ *
++ *=======================================================================
++ */
++#ifndef _REGS_IRDA_H_
++#define _REGS_IRDA_H_
++
++/* Bit definitions */
++
++#define IrEnable_EN_NONE 0x00
++#define IrEnable_EN_SIR 0x01
++#define IrEnable_EN_MIR 0x02
++#define IrEnable_EN_FIR 0x03
++#define IrEnable_LBM 0x04
++#define IrEnable_MD 0x08
++#define IrEnable_FD 0x10
++
++#endif /* _REGS_IRDA_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_pcmcia.h b/include/asm-arm/arch-ep93xx/regs_pcmcia.h
+new file mode 100644
+index 0000000..6f731e7
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_pcmcia.h
+@@ -0,0 +1,72 @@
++/*
++ * linux/include/asm-arm/arch-ep93xx/regs-pcmcia.h
++ *
++ * Derived from:
++ * linux/include/asm-arm/arch-pxa/pxa-regs.h
++ *
++ * Author: Nicolas Pitre
++ * Created: Jun 15, 2001
++ * Copyright: MontaVista Software Inc.
++ *
++ * 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.
++ */
++
++/*
++ * Personal Computer Memory Card International Association (PCMCIA) sockets
++ * (from pxa-regs.h for compatibility)
++ */
++#ifndef _REGS_PCMCIA_H_
++#define _REGS_PCMCIA_H_
++
++#define PCMCIAPrtSp 0x04000000 /* PCMCIA Partition Space [byte] */
++#define PCMCIASp (4*PCMCIAPrtSp) /* PCMCIA Space [byte] */
++#define PCMCIAIOSp PCMCIAPrtSp /* PCMCIA I/O Space [byte] */
++#define PCMCIAAttrSp PCMCIAPrtSp /* PCMCIA Attribute Space [byte] */
++#define PCMCIAMemSp PCMCIAPrtSp /* PCMCIA Memory Space [byte] */
++
++#define PCMCIA0Sp PCMCIASp /* PCMCIA 0 Space [byte] */
++#define PCMCIA0IOSp PCMCIAIOSp /* PCMCIA 0 I/O Space [byte] */
++#define PCMCIA0AttrSp PCMCIAAttrSp /* PCMCIA 0 Attribute Space [byte] */
++#define PCMCIA0MemSp PCMCIAMemSp /* PCMCIA 0 Memory Space [byte] */
++
++#define PCMCIA1Sp PCMCIASp /* PCMCIA 1 Space [byte] */
++#define PCMCIA1IOSp PCMCIAIOSp /* PCMCIA 1 I/O Space [byte] */
++#define PCMCIA1AttrSp PCMCIAAttrSp /* PCMCIA 1 Attribute Space [byte] */
++#define PCMCIA1MemSp PCMCIAMemSp /* PCMCIA 1 Memory Space [byte] */
++
++
++#define _PCMCIA(Nb) /* PCMCIA [0..1] */ \
++ (0x40000000 + (Nb)*PCMCIASp)
++#define _PCMCIAIO(Nb) _PCMCIA (Nb) /* PCMCIA I/O [0..1] */
++#define _PCMCIAAttr(Nb) /* PCMCIA Attribute [0..1] */ \
++ (_PCMCIA (Nb) + 2*PCMCIAPrtSp)
++#define _PCMCIAMem(Nb) /* PCMCIA Memory [0..1] */ \
++ (_PCMCIA (Nb) + 3*PCMCIAPrtSp)
++
++#define _PCMCIA0 _PCMCIA (0) /* PCMCIA 0 */
++#define _PCMCIA0IO _PCMCIAIO (0) /* PCMCIA 0 I/O */
++#define _PCMCIA0Attr _PCMCIAAttr (0) /* PCMCIA 0 Attribute */
++#define _PCMCIA0Mem _PCMCIAMem (0) /* PCMCIA 0 Memory */
++
++#define _PCMCIA1 _PCMCIA (1) /* PCMCIA 1 */
++#define _PCMCIA1IO _PCMCIAIO (1) /* PCMCIA 1 I/O */
++#define _PCMCIA1Attr _PCMCIAAttr (1) /* PCMCIA 1 Attribute */
++#define _PCMCIA1Mem _PCMCIAMem (1) /* PCMCIA 1 Memory */
++
++#define PCATTRIB(sock) ((sock ==0) ? (PC1ATTRIB) : (PC2ATTRIB))
++#define PCCOMMON(sock) ((sock ==0) ? (PC1COMMON) : (PC2COMMON))
++#define PCIO(sock) ((sock ==0) ? (PC1IO) : (PC2IO))
++
++#define PC16BITSWIDE 0x80000000
++
++#define PCMCIA_WRPROT 0x01
++#define PCMCIA_DETECT 0x06
++#define PCMCIA_BVD1 0x08
++#define PCMCIA_BVD2 0x10
++#define PCMCIA_VS_3V 0x20
++#define PCMCIA_READY 0x40
++#define PCMCIA_VS_XV 0x80
++
++#endif /* _REGS_PCMCIA_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_raster.h b/include/asm-arm/arch-ep93xx/regs_raster.h
+new file mode 100644
+index 0000000..bfab3ed
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_raster.h
+@@ -0,0 +1,279 @@
++/*=============================================================================
++ *
++ * FILE: regs_raster.h
++ *
++ * DESCRIPTION: ep93xx Raster Engine Register Definition
++ *
++ * Copyright Cirrus Logic, 2001-2003
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ *=============================================================================
++ */
++#ifndef _REGS_RASTER_H_
++#define _REGS_RASTER_H_
++
++/* VLINESTOTAL Register Definitions */
++#define VLINESTOTAL_MASK 0x000007ff
++
++/* VSYNCSTRTSTOP Register Definitions */
++#define VSYNCSTRTSTOP_STRT_MASK 0x07ff0000
++#define VSYNCSTRTSTOP_STRT_SHIFT 0
++#define VSYNCSTRTSTOP_STOP_MASK 0x000007ff
++#define VSYNCSTRTSTOP_STOP_SHIFT 16
++
++/* VACTIVESTRTSTOP Register Definitions */
++#define VACTIVESTRTSTOP_STRT_MASK 0x07ff0000
++#define VACTIVESTRTSTOP_STRT_SHIFT 0
++#define VACTIVESTRTSTOP_STOP_MASK 0x000007ff
++#define VACTIVESTRTSTOP_STOP_SHIFT 16
++
++/* VCLKSTRTSTOP Register Definitions */
++#define VCLKSTRTSTOP_STRT_MASK 0x07ff0000
++#define VCLKSTRTSTOP_STRT_SHIFT 0
++#define VCLKSTRTSTOP_STOP_MASK 0x000007ff
++#define VCLKSTRTSTOP_STOP_SHIFT 16
++
++/* VBLANKSTRTSTOP Register Definitions */
++#define VBLANKSTRTSTOP_STRT_MASK 0x07ff0000
++#define VBLANKSTRTSTOP_STRT_SHIFT 0
++#define VBLANKSTRTSTOP_STOP_MASK 0x000007ff
++#define VBLANKSTRTSTOP_STOP_SHIFT 16
++
++/* HSYNCSTRTSTOP Register Definitions */
++#define HSYNCSTRTSTOP_STRT_MASK 0x07ff0000
++#define HSYNCSTRTSTOP_STRT_SHIFT 0
++#define HSYNCSTRTSTOP_STOP_MASK 0x000007ff
++#define HSYNCSTRTSTOP_STOP_SHIFT 16
++
++/* HACTIVESTRTSTOP Register Definitions */
++#define HACTIVESTRTSTOP_STRT_MASK 0x07ff0000
++#define HACTIVESTRTSTOP_STRT_SHIFT 0
++#define HACTIVESTRTSTOP_STOP_MASK 0x000007ff
++#define HACTIVESTRTSTOP_STOP_SHIFT 16
++
++/* HCLKSTRTSTOP Register Definitions */
++#define HCLKSTRTSTOP_STRT_MASK 0x07ff0000
++#define HCLKSTRTSTOP_STRT_SHIFT 0
++#define HCLKSTRTSTOP_STOP_MASK 0x000007ff
++#define HCLKSTRTSTOP_STOP_SHIFT 16
++
++/* BRIGHTNESS Register Definitions */
++#define BRIGHTNESS_MASK 0x0000ffff
++#define BRIGHTNESS_CNT_MASK 0x000000ff
++#define BRIGHTNESS_CNT_SHIFT 0
++#define BRIGHTNESS_CMP_MASK 0x0000ff00
++#define BRIGHTNESS_CMP_SHIFT 8
++
++/* VIDEOATTRIBS Register Definitions */
++#define VIDEOATTRIBS_MASK 0x001fffff
++#define VIDEOATTRIBS_EN 0x00000001
++#define VIDEOATTRIBS_PCLKEN 0x00000002
++#define VIDEOATTRIBS_SYNCEN 0x00000004
++#define VIDEOATTRIBS_DATAEN 0x00000008
++#define VIDEOATTRIBS_CSYNC 0x00000010
++#define VIDEOATTRIBS_VCPOL 0x00000020
++#define VIDEOATTRIBS_HSPOL 0x00000040
++#define VIDEOATTRIBS_BLKPOL 0x00000080
++#define VIDEOATTRIBS_INVCLK 0x00000100
++#define VIDEOATTRIBS_ACEN 0x00000200
++#define VIDEOATTRIBS_LCDEN 0x00000400
++#define VIDEOATTRIBS_RGBEN 0x00000800
++#define VIDEOATTRIBS_CCIREN 0x00001000
++#define VIDEOATTRIBS_PIFEN 0x00002000
++#define VIDEOATTRIBS_INTEN 0x00004000
++#define VIDEOATTRIBS_INT 0x00008000
++#define VIDEOATTRIBS_INTRLC 0x00010000
++#define VIDEOATTRIBS_EQUSER 0x00020000
++#define VIDEOATTRIBS_DHORZ 0x00040000
++#define VIDEOATTRIBS_DVERT 0x00080000
++#define VIDEOATTRIBS_BKPXD 0x00100000
++
++#define VIDEOATTRIBS_SDSEL_MASK 0x00600000
++#define VIDEOATTRIBS_SDSEL_SHIFT 21
++
++/* HBLANKSTRTSTOP Register Definitions */
++#define HBLANKSTRTSTOP_STRT_MASK 0x07ff0000
++#define HBLANKSTRTSTOP_STRT_SHIFT 0
++#define HBLANKSTRTSTOP_STOP_MASK 0x000007ff
++#define HBLANKSTRTSTOP_STOP_SHIFT 16
++
++/* LINECARRY Register Definitions */
++#define LINECARRY_LCARY_MASK 0x000007ff
++#define LINECARRY_LCARY_SHIFT 0
++
++/* BLINKRATE Register Definitons */
++#define BLINKRATE_MASK 0x000000ff
++
++/* BLINKMASK Register Definitons */
++#define BLINKMASK_MASK 0x00ffffff
++
++/* VIDSCRNPAGE Register Definitons */
++#define VIDSCRNPAGE_PAGE_MASK 0x0ffffffc
++
++/* VIDSCRNHPG Register Definitons */
++#define VIDSCRNHPG_MASK 0x0ffffffc
++
++/* SCRNLINES Register Definitons */
++#define SCRNLINES_MASK 0x000007ff
++
++/* LINELENGTH Register Definitons */
++#define LINELENGTH_MASK 0x000007ff
++
++/* VLINESTEP Register Definitons */
++#define VLINESTEP_MASK 0x00000fff
++
++/* REALITI_SWLOCK Register Definitons */
++#define REALITI_SWLOCK_MASK_WR 0xff
++#define REALITI_SWLOCK_MASK_R 0x1
++#define REALITI_SWLOCK_VALUE 0xaa
++
++/* LUTCONT Register Definitions */
++#define LUTCONT_MASK 0x00000003
++#define LUTCONT_SWTCH 0x00000001
++#define LUTCONT_STAT 0x00000002
++#define LUTCONT_RAM0 0
++#define LUTCONT_RAM1 1
++
++/* CURSORBLINK1 Register Definitions */
++#define CURSORBLINK1_MASK 0x00ffffff
++/* CURSORBLINK2 Register Definitions */
++#define CURSORBLINK2_MASK 0x00ffffff
++
++/* CURSORBLINK Register Definitions */
++#define CURSORBLINK_MASK 0x000001ff
++#define CURSORBLINK_RATE_MASK 0x000000ff
++#define CURSORBLINK_RATE_SHIFT 0
++#define CURSORBLINK_EN 0x00000100
++
++/* BLINKPATRN Register Definitions */
++#define BLINKPATRN_MASK 0x00ffffff
++
++/* PATRNMASK Register Definitions */
++#define PATRNMASK_MASK 0x00ffffff
++
++/* BG_OFFSET Register Definitions */
++#define BG_OFFSET_MASK 0x00ffffff
++
++/* PIXELMODE Register Definitions */
++#define PIXELMODE_P_MASK 0x00000007
++#define PIXELMODE_P_MUX_DISABLE 0x00000000
++#define PIXELMODE_P_4BPP 0x00000001
++#define PIXELMODE_P_8BPP 0x00000002
++#define PIXELMODE_P_16BPP 0x00000004
++#define PIXELMODE_P_24BPP 0x00000006
++#define PIXELMODE_P_32BPP 0x00000007
++#define PIXELMODE_P_SHIFT 0
++
++#define PIXELMODE_S_MASK 0x00000038
++#define PIXELMODE_S_SHIFT 3
++#define PIXELMODE_S_1PPC 0x0
++#define PIXELMODE_S_1PPCMAPPED 0x1
++#define PIXELMODE_S_2PPC 0x2
++#define PIXELMODE_S_4PPC 0x3
++#define PIXELMODE_S_8PPC 0x4
++#define PIXELMODE_S_223PPC 0x5
++#define PIXELMODE_S_DS223PPC 0x6
++#define PIXELMODE_S_UNDEF 0x7
++
++#define PIXELMODE_M_MASK 0x000003c0
++#define PIXELMODE_M_SHIFT 6
++#define PIXELMODE_M_NOBLINK 0
++#define PIXELMODE_M_ANDBLINK 1
++#define PIXELMODE_M_ORBLINK 2
++#define PIXELMODE_M_XORBLINK 3
++#define PIXELMODE_M_BGBLINK 4
++#define PIXELMODE_M_OFFSINGBLINK 5
++#define PIXELMODE_M_OFF888BLINK 6
++#define PIXELMODE_M_DIMBLINK 0xc
++#define PIXELMODE_M_BRTBLINK 0xd
++#define PIXELMODE_M_DIM888BLINK 0xe
++#define PIXELMODE_M_BRT888BLINK 0xf
++
++#define PIXELMODE_C_MASK 0x00003c00
++#define PIXELMODE_C_SHIFT 10
++#define PIXELMODE_C_LUT 0
++#define PIXELMODE_C_888 4
++#define PIXELMODE_C_565 5
++#define PIXELMODE_C_555 6
++#define PIXELMODE_C_GSLUT 8
++
++#define PIXELMODE_DSCAN 0x00004000
++#define PIXELMODE_TRBSW 0x00008000
++#define PIXELMODE_P13951 0x00010000
++
++/*PARLLIFOUT Register Defintions */
++#define PARLLIFOUT_DAT_MASK 0x0000000f
++#define PARLLIFOUT_DAT_SHIFT 0
++#define PARLLIFOUT_RD 0x00000010
++
++/*PARLLIFIN Register Defintions */
++#define PARLLIFIN_DAT_MASK 0x0000000f
++#define PARLLIFIN_DAT_SHIFT 0
++#define PARLLIFIN_CNT_MASK 0x000f0000
++#define PARLLIFIN_CNT_SHIFT 16
++#define PARLLIFIN_ESTRT_MASK 0x00f00000
++#define PARLLIFIN_ESTRT_SHIFT 20
++
++/* CURSORADRSTART Register Defintions */
++#define CURSOR_ADR_START_MASK 0xfffffffc
++
++/* CURSORADRSTART Register Defintions */
++#define CURSOR_ADR_RESET_MASK 0xfffffffc
++
++/* CURSORCOLOR1 Register Definitions */
++#define CURSORCOLOR1_MASK 0x00ffffff
++/* CURSORCOLOR2 Register Definitions */
++#define CURSORCOLOR2_MASK 0x00ffffff
++
++/* CURSORXYLOC Register Definitions */
++#define CURSORXYLOC_MASK 0x07ff87ff
++#define CURSORXYLOC_XLOC_MASK 0x000007ff
++#define CURSORXYLOC_XLOC_SHIFT 0
++#define CURSORXYLOC_CEN 0x00008000
++#define CURSORXYLOC_YLOC_MASK 0x07ff0000
++#define CURSORXYLOC_YLOC_SHIFT 16
++
++/* CURSOR_DSCAN_LH_YLOC Register Definitions */
++#define CURSOR_DSCAN_LH_YLOC_MASK 0x000087ff
++
++#define CURSOR_DSCAN_LH_YLOC_YLOC_MASK 0x000007ff
++#define CURSOR_DSCAN_LH_YLOC_YLOC_SHIFT 0
++#define CURSOR_DSCAN_LH_YLOC_CLHEN 0x00008000
++
++/* CURSORSIZE Register Definitions */
++#define CURSORSIZE_MASK 0x0000ffff
++
++#define CURSORSIZE_CWID_MASK 0x00000003
++#define CURSORSIZE_CWID_SHIFT 0
++#define CURSORSIZE_CWID_1_WORD 0
++#define CURSORSIZE_CWID_2_WORD 1
++#define CURSORSIZE_CWID_3_WORD 2
++#define CURSORSIZE_CWID_4_WORD 3
++
++#define CURSORSIZE_CLINS_MASK 0x000000fc
++#define CURSORSIZE_CLINS_SHIFT 2
++
++#define CURSORSIZE_CSTEP_MASK 0x00000300
++#define CURSORSIZE_CSTEP_SHIFT 8
++#define CURSORSIZE_CSTEP_1_WORD 0
++#define CURSORSIZE_CSTEP_2_WORD 1
++#define CURSORSIZE_CSTEP_3_WORD 2
++#define CURSORSIZE_CSTEP_4_WORD 3
++
++#define CURSORSIZE_DLNS_MASK 0x0000fc00
++#define CURSORSIZE_DLNS_SHIFT 10
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/regs_spi.h b/include/asm-arm/arch-ep93xx/regs_spi.h
+new file mode 100644
+index 0000000..a51d3dc
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_spi.h
+@@ -0,0 +1,76 @@
++/*=======================================================================
++ *
++ * FILE: regs_spi.h
++ *
++ * DESCRIPTION: SSP Register Definition
++ *
++ * Copyright Cirrus Logic, 2001-2003
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *=======================================================================
++ */
++
++#ifndef _REGS_SSP_H_
++#define _REGS_SSP_H_
++
++/* Bits in SSPCR0 */
++#define SSPCR0_DSS_MASK 0x0000000f
++#define SSPCR0_DSS_4BIT 0x00000003
++#define SSPCR0_DSS_5BIT 0x00000004
++#define SSPCR0_DSS_6BIT 0x00000005
++#define SSPCR0_DSS_7BIT 0x00000006
++#define SSPCR0_DSS_8BIT 0x00000007
++#define SSPCR0_DSS_9BIT 0x00000008
++#define SSPCR0_DSS_10BIT 0x00000009
++#define SSPCR0_DSS_11BIT 0x0000000a
++#define SSPCR0_DSS_12BIT 0x0000000b
++#define SSPCR0_DSS_13BIT 0x0000000c
++#define SSPCR0_DSS_14BIT 0x0000000d
++#define SSPCR0_DSS_15BIT 0x0000000e
++#define SSPCR0_DSS_16BIT 0x0000000f
++
++/* Bits in SSPCR1 */
++#define SSPC1_RIE 0x00000001
++#define SSPC1_TIE 0x00000002
++#define SSPC1_RORIE 0x00000004
++#define SSPC1_LBM 0x00000008
++#define SSPC1_SSE 0x00000010
++#define SSPC1_MS 0x00000020
++#define SSPC1_SOD 0x00000040
++
++#define SSPCR0_DSS_SHIFT 0
++#define SSPCR0_FRF_MASK 0x00000030
++#define SSPCR0_FRF_SHIFT 4
++#define SSPCR0_FRF_MOTOROLA (0 << SSPCR0_FRF_SHIFT)
++#define SSPCR0_FRF_TI (1 << SSPCR0_FRF_SHIFT)
++#define SSPCR0_FRF_NI (2 << SSPCR0_FRF_SHIFT)
++#define SSPCR0_SPO 0x00000040
++#define SSPCR0_SPH 0x00000080
++#define SSPCR0_SCR_MASK 0x0000ff00
++#define SSPCR0_SCR_SHIFT 8
++
++/* Bits in SSPSR */
++#define SSPSR_TFE 0x00000001 /* TX FIFO is empty */
++#define SSPSR_TNF 0x00000002 /* TX FIFO is not full */
++#define SSPSR_RNE 0x00000004 /* RX FIFO is not empty */
++#define SSPSR_RFF 0x00000008 /* RX FIFO is full */
++#define SSPSR_BSY 0x00000010 /* SSP is busy */
++
++/* Bits in SSPIIR */
++#define SSPIIR_RIS 0x00000001 /* RX FIFO IRQ status */
++#define SSPIIR_TIS 0x00000002 /* TX FIFO is not full */
++#define SSPIIR_RORIS 0x00000004 /* RX FIFO is full */
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/regs_syscon.h b/include/asm-arm/arch-ep93xx/regs_syscon.h
+new file mode 100644
+index 0000000..271cfcd
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_syscon.h
+@@ -0,0 +1,257 @@
++/*=============================================================================
++ *
++ * FILE: reg_syscon.h
++ *
++ * DESCRIPTION: ep93xx Syscon Register Definition
++ *
++ * Copyright Cirrus Logic, 2001-2003
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ *=============================================================================
++ */
++#ifndef _REGS_SYSCON_H_
++#define _REGS_SYSCON_H_
++
++#ifndef __ASSEMBLY__
++
++#define SysconSetLocked(registername,value) \
++ { \
++ writel( 0xAA, SYSCON_SWLOCK); \
++ writel( value, registername); \
++ }
++
++#endif /* Not __ASSEMBLY__ */
++
++/* SYSCON_CLKSET1 */
++#define SYSCON_CLKSET1_PLL1_X2IPD_SHIFT 0
++#define SYSCON_CLKSET1_PLL1_X2IPD_MASK 0x0000001f
++#define SYSCON_CLKSET1_PLL1_X2FBD2_SHIFT 5
++#define SYSCON_CLKSET1_PLL1_X2FBD2_MASK 0x000007e0
++#define SYSCON_CLKSET1_PLL1_X1FBD1_SHIFT 11
++#define SYSCON_CLKSET1_PLL1_X1FBD1_MASK 0x0000f800
++#define SYSCON_CLKSET1_PLL1_PS_SHIFT 16
++#define SYSCON_CLKSET1_PLL1_PS_MASK 0x00030000
++#define SYSCON_CLKSET1_PCLKDIV_SHIFT 18
++#define SYSCON_CLKSET1_PCLKDIV_MASK 0x000c0000
++#define SYSCON_CLKSET1_HCLKDIV_SHIFT 20
++#define SYSCON_CLKSET1_HCLKDIV_MASK 0x00700000
++#define SYSCON_CLKSET1_nBYP1 0x00800000
++#define SYSCON_CLKSET1_SMCROM 0x01000000
++#define SYSCON_CLKSET1_FCLKDIV_SHIFT 25
++#define SYSCON_CLKSET1_FCLKDIV_MASK 0x0e000000
++
++#define SYSCON_CLKSET1_HSEL 0x00000001
++#define SYSCON_CLKSET1_PLL1_EXCLKSEL 0x00000002
++
++#define SYSCON_CLKSET1_PLL1_P_MASK 0x0000007C
++#define SYSCON_CLKSET1_PLL1_P_SHIFT 2
++
++#define SYSCON_CLKSET1_PLL1_M1_MASK 0x00000780
++#define SYSCON_CLKSET1_PLL1_M1_SHIFT 7
++#define SYSCON_CLKSET1_PLL1_M2_MASK 0x0000F800
++#define SYSCON_CLKSET1_PLL1_M2_SHIFT 11
++#define SYSCON_CLKSET1_PLL1_PS_MASK 0x00030000
++#define SYSCON_CLKSET1_PLL1_PS_SHIFT 16
++#define SYSCON_CLKSET1_PCLK_DIV_MASK 0x000C0000
++#define SYSCON_CLKSET1_PCLK_DIV_SHIFT 18
++#define SYSCON_CLKSET1_HCLK_DIV_MASK 0x00700000
++#define SYSCON_CLKSET1_HCLK_DIV_SHIFT 20
++#define SYSCON_CLKSET1_SMCROM 0x01000000
++#define SYSCON_CLKSET1_FCLK_DIV_MASK 0x0E000000
++#define SYSCON_CLKSET1_FCLK_DIV_SHIFT 25
++
++#define SYSCON_CLKSET2_PLL2_EN 0x00000001
++#define SYSCON_CLKSET2_PLL2EXCLKSEL 0x00000002
++#define SYSCON_CLKSET2_PLL2_P_MASK 0x0000007C
++#define SYSCON_CLKSET2_PLL2_P_SHIFT 2
++#define SYSCON_CLKSET2_PLL2_M2_MASK 0x00000F80
++#define SYSCON_CLKSET2_PLL2_M2_SHIFT 7
++#define SYSCON_CLKSET2_PLL2_M1_MASK 0x0001F000
++#define SYSCON_CLKSET2_PLL2_M1 12
++#define SYSCON_CLKSET2_PLL2_PS_MASK 0x000C0000
++#define SYSCON_CLKSET2_PLL2_PS_SHIFT 18
++#define SYSCON_CLKSET2_USBDIV_MASK 0xF0000000
++#define SYSCON_CLKSET2_USBDIV_SHIFT 28
++
++/* DEV_CFG Register Defines */
++#define SYSCON_DEVCFG_SHena 0x00000001
++#define SYSCON_DEVCFG_KEYS 0x00000002
++#define SYSCON_DEVCFG_ADCPD 0x00000004
++#define SYSCON_DEVCFG_RAS 0x00000008
++#define SYSCON_DEVCFG_RASonP3 0x00000010
++#define SYSCON_DEVCFG_TTIC 0x00000020
++#define SYSCON_DEVCFG_I2SonAC97 0x00000040
++#define SYSCON_DEVCFG_I2SonSSP 0x00000080
++#define SYSCON_DEVCFG_EonIDE 0x00000100
++#define SYSCON_DEVCFG_PonG 0x00000200
++#define SYSCON_DEVCFG_GonIDE 0x00000400
++#define SYSCON_DEVCFG_HonIDE 0x00000800
++#define SYSCON_DEVCFG_HC1CEN 0x00001000
++#define SYSCON_DEVCFG_HC1IN 0x00002000
++#define SYSCON_DEVCFG_HC3CEN 0x00004000
++#define SYSCON_DEVCFG_HC3IN 0x00008000
++#define SYSCON_DEVCFG_ADCEN 0x00010000
++#define SYSCON_DEVCFG_TIN 0x00020000
++#define SYSCON_DEVCFG_U1EN 0x00040000
++#define SYSCON_DEVCFG_EXVC 0x00080000
++#define SYSCON_DEVCFG_U2EN 0x00100000
++#define SYSCON_DEVCFG_A1onG 0x00200000
++#define SYSCON_DEVCFG_A2onG 0x00400000
++#define SYSCON_DEVCFG_CPENA 0x00800000
++#define SYSCON_DEVCFG_U3EN 0x01000000
++#define SYSCON_DEVCFG_MonG 0x02000000
++#define SYSCON_DEVCFG_TonG 0x04000000
++#define SYSCON_DEVCFG_GonK 0x08000000
++#define SYSCON_DEVCFG_IonU2 0x10000000
++#define SYSCON_DEVCFG_D0onG 0x20000000
++#define SYSCON_DEVCFG_D1onG 0x40000000
++#define SYSCON_DEVCFG_SWRST 0x80000000
++
++/* VIDDIV Register Defines */
++#define SYSCON_VIDDIV_VDIV_MASK 0x0000007f
++#define SYSCON_VIDDIV_VDIV_SHIFT 0
++#define SYSCON_VIDDIV_PDIV_MASK 0x00000300
++#define SYSCON_VIDDIV_PDIV_SHIFT 8
++#define SYSCON_VIDDIV_PSEL 0x00002000
++#define SYSCON_VIDDIV_ESEL 0x00004000
++#define SYSCON_VIDDIV_VENA 0x00008000
++
++/* MIRDIV Register Defines */
++#define SYSCON_MIRDIV_MDIV_MASK 0x0000003f
++#define SYSCON_MIRDIV_MDIV_SHIFT 0
++#define SYSCON_MIRDIV_PDIV_MASK 0x00000300
++#define SYSCON_MIRDIV_PDIV_SHIFT 8
++#define SYSCON_MIRDIV_PSEL 0x00002000
++#define SYSCON_MIRDIV_ESEL 0x00004000
++#define SYSCON_MIRDIV_MENA 0x00008000
++
++/* I2SDIV Register Defines */
++#define SYSCON_I2SDIV_MDIV_MASK 0x0000007f
++#define SYSCON_I2SDIV_MDIV_SHIFT 0
++#define SYSCON_I2SDIV_PDIV_MASK 0x00000300
++#define SYSCON_I2SDIV_PDIV_SHIFT 8
++#define SYSCON_I2SDIV_PSEL 0x00002000
++#define SYSCON_I2SDIV_ESEL 0x00004000
++#define SYSCON_I2SDIV_MENA 0x00008000
++#define SYSCON_I2SDIV_SDIV 0x00010000
++#define SYSCON_I2SDIV_LRDIV_MASK 0x00060000
++#define SYSCON_I2SDIV_LRDIV_SHIFT 17
++#define SYSCON_I2SDIV_SPOL 0x00080000
++#define SYSCON_I2SDIV_DROP 0x00100000
++#define SYSCON_I2SDIV_ORIDE 0x20000000
++#define SYSCON_I2SDIV_SLAVE 0x40000000
++#define SYSCON_I2SDIV_SENA 0x80000000
++
++#define SYSCON_I2SDIV_PDIV_OFF 0x00000000
++#define SYSCON_I2SDIV_PDIV_2 0x00000100
++#define SYSCON_I2SDIV_PDIV_25 0x00000200
++#define SYSCON_I2SDIV_PDIV_3 0x00000300
++
++#define SYSCON_I2SDIV_LRDIV_32 0x00000000
++#define SYSCON_I2SDIV_LRDIV_64 0x00020000
++#define SYSCON_I2SDIV_LRDIV_128 0x00040000
++
++/* KTDIV Register Defines */
++#define SYSCON_KTDIV_KDIV 0x00000001
++#define SYSCON_KTDIV_KEN 0x00008000
++#define SYSCON_KTDIV_ADIV 0x00010000
++#define SYSCON_KTDIV_TSEN 0x80000000
++
++/* CHIPID Register Defines */
++#define SYSCON_CHIPID_ID_MASK 0x0000ffff
++#define SYSCON_CHIPID_ID_SHIFT 0
++#define SYSCON_CHIPID_PKID 0x00010000
++#define SYSCON_CHIPID_BND 0x00040000
++#define SYSCON_CHIPID_FAB_MASK 0x0e000000
++#define SYSCON_CHIPID_FAB_SHIFT 25
++#define SYSCON_CHIPID_REV_MASK 0xf0000000
++#define SYSCON_CHIPID_REV_SHIFT 28
++
++/* TESTCR Register Defines */
++#define SYSCON_TESTCR_TMODE_MASK 0x000000ff
++#define SYSCON_TESTCR_TMODE_SHIFT 0
++#define SYSCON_TESTCR_BONDO 0x00000100
++#define SYSCON_TESTCR_PACKO 0x00000800
++#define SYSCON_TESTCR_ETOM 0x00002000
++#define SYSCON_TESTCR_TOM 0x00004000
++#define SYSCON_TESTCR_OVR 0x00008000
++#define SYSCON_TESTCR_TonIDE 0x00010000
++#define SYSCON_TESTCR_RonG 0x00020000
++
++/* SYSCFG Register Defines */
++#define SYSCON_SYSCFG_LCSn1 0x00000001
++#define SYSCON_SYSCFG_LCSn2 0x00000002
++#define SYSCON_SYSCFG_LCSn3 0x00000004
++#define SYSCON_SYSCFG_LEECK 0x00000008
++#define SYSCON_SYSCFG_LEEDA 0x00000010
++#define SYSCON_SYSCFG_LASDO 0x00000020
++#define SYSCON_SYSCFG_LCSn6 0x00000040
++#define SYSCON_SYSCFG_LCSn7 0x00000080
++#define SYSCON_SYSCFG_SBOOT 0x00000100
++#define SYSCON_SYSCFG_FAB_MASK 0x0e000000
++#define SYSCON_SYSCFG_FAB_SHIFT 25
++#define SYSCON_SYSCFG_REV_MASK 0xf0000000
++#define SYSCON_SYSCFG_REV_SHIFT 28
++
++/* PWRSR Register Defines */
++#define SYSCON_PWRSR_CHIPMAN_MASK 0xFF000000
++#define SYSCON_PWRSR_CHIPMAN_SHIFT 24
++#define SYSCON_PWRSR_CHIPID_MASK 0x00FF0000
++#define SYSCON_PWRSR_CHIPID_SHIFT 16
++#define SYSCON_PWRSR_WDTFLG 0x00008000
++#define SYSCON_PWRSR_CLDFLG 0x00002000
++#define SYSCON_PWRSR_TEST_RESET 0x00001000
++#define SYSCON_PWRSR_RSTFLG 0x00000800
++#define SYSCON_PWRSR_SWRESET 0x00000400
++#define SYSCON_PWRSR_PLL2_LOCKREG 0x00000200
++#define SYSCON_PWRSR_PLL2_LOCK 0x00000100
++#define SYSCON_PWRSR_PLL1_LOCKREG 0x00000080
++#define SYSCON_PWRSR_PLL1_LOCK 0x00000040
++#define SYSCON_PWRSR_RTCDIV 0x0000003F
++
++/* PWRCNT Register Defines */
++#define SYSCON_PWRCNT_FIREN 0x80000000
++#define SYSCON_PWRCNT_UARTBAUD 0x20000000
++#define SYSCON_PWRCNT_USHEN 0x10000000
++#define SYSCON_PWRCNT_DMA_M2MCH1 0x08000000
++#define SYSCON_PWRCNT_DMA_M2MCH0 0x04000000
++#define SYSCON_PWRCNT_DMA_M2PCH8 0x02000000
++#define SYSCON_PWRCNT_DMA_M2PCH9 0x01000000
++#define SYSCON_PWRCNT_DMA_M2PCH6 0x00800000
++#define SYSCON_PWRCNT_DMA_M2PCH7 0x00400000
++#define SYSCON_PWRCNT_DMA_M2PCH4 0x00200000
++#define SYSCON_PWRCNT_DMA_M2PCH5 0x00100000
++#define SYSCON_PWRCNT_DMA_M2PCH2 0x00080000
++#define SYSCON_PWRCNT_DMA_M2PCH3 0x00040000
++#define SYSCON_PWRCNT_DMA_M2PCH0 0x00020000
++#define SYSCON_PWRCNT_DMA_M2PCH1 0x00010000
++
++/* BMAR Register Defines */
++#define BMAR_PRIORD_00 0x00000000
++#define BMAR_PRIORD_01 0x00000001
++#define BMAR_PRIORD_02 0x00000002
++#define BMAR_PRIORD_03 0x00000003
++#define BMAR_PRI_CORE 0x00000008
++#define BMAR_DMA_ENIRQ 0x00000010
++#define BMAR_DMA_ENFIQ 0x00000020
++#define BMAR_USB_ENIRQ 0x00000040
++#define BMAR_USB_ENFIQ 0x00000080
++#define BMAR_MAC_ENIRQ 0x00000100
++#define BMAR_MAC_ENFIQ 0x00000200
++#define BMAR_GRAPHICS_ENIRQ 0x00000400
++#define BMAR_GRAPHICS_ENFIQ 0x00000800
++
++#endif /* _REGS_SYSCON_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_touch.h b/include/asm-arm/arch-ep93xx/regs_touch.h
+new file mode 100644
+index 0000000..aad8a99
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_touch.h
+@@ -0,0 +1,94 @@
++/*=============================================================================
++ *
++ * FILE: regs_touch.h
++ *
++ * DESCRIPTION: Analog Touchscreen Register Definition
++ *
++ * Copyright Cirrus Logic, 2001-2003
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *=============================================================================
++ */
++#ifndef _REGS_TOUCH_H_
++#define _REGS_TOUCH_H_
++
++/*
++ *-----------------------------------------------------------------------------
++ * Individual bit #defines
++ *-----------------------------------------------------------------------------
++ */
++#define TSSETUP_SDLY_MASK 0x000003FF
++#define TSSETUP_SDLY_SHIFT 0
++#define TSSETUP_NSMP_4 0x00000000
++#define TSSETUP_NSMP_8 0x00000400
++#define TSSETUP_NSMP_16 0x00000800
++#define TSSETUP_NSMP_32 0x00000C00
++#define TSSETUP_NSMP_MASK 0x00000C00
++#define TSSETUP_DEV_4 0x00000000
++#define TSSETUP_DEV_8 0x00001000
++#define TSSETUP_DEV_12 0x00002000
++#define TSSETUP_DEV_16 0x00003000
++#define TSSETUP_DEV_24 0x00004000
++#define TSSETUP_DEV_32 0x00005000
++#define TSSETUP_DEV_64 0x00006000
++#define TSSETUP_DEV_128 0x00007000
++#define TSSETUP_ENABLE 0x00008000
++#define TSSETUP_DLY_MASK 0x03FF0000
++#define TSSETUP_DLY_SHIFT 16
++#define TSSETUP_TDTCT 0x80000000
++
++#define TSMAXMIN_XMIN_MASK 0x000000FF
++#define TSMAXMIN_XMIN_SHIFT 0
++#define TSMAXMIN_YMIN_MASK 0x0000FF00
++#define TSMAXMIN_YMIN_SHIFT 8
++#define TSMAXMIN_XMAX_MASK 0x00FF0000
++#define TSMAXMIN_XMAX_SHIFT 16
++#define TSMAXMIN_YMAX_MASK 0xFF000000
++#define TSMAXMIN_YMAX_SHIFT 24
++
++#define TSXYRESULT_X_MASK 0x00000FFF
++#define TSXYRESULT_X_SHIFT 0
++#define TSXYRESULT_AD_MASK 0x0000FFFF
++#define TSXYRESULT_AD_SHIFT 0
++#define TSXYRESULT_Y_MASK 0x0FFF0000
++#define TSXYRESULT_Y_SHIFT 16
++#define TSXYRESULT_SDR 0x80000000
++
++#define TSX_SAMPLE_MASK 0x00003FFF
++#define TSX_SAMPLE_SHIFT 0x00
++#define TSY_SAMPLE_MASK 0x3FFF0000
++#define TSY_SAMPLE_SHIFT 0x10
++
++#define TSSETUP2_TINT 0x00000001
++#define TSSETUP2_NICOR 0x00000002
++#define TSSETUP2_PINT 0x00000004
++#define TSSETUP2_PENSTS 0x00000008
++#define TSSETUP2_PINTEN 0x00000010
++#define TSSETUP2_DEVINT 0x00000020
++#define TSSETUP2_DINTEN 0x00000040
++#define TSSETUP2_DTMEN 0x00000080
++#define TSSETUP2_DISDEV 0x00000100
++#define TSSETUP2_NSIGND 0x00000200
++#define TSSETUP2_S28EN 0x00000400
++#define TSSETUP2_RINTEN 0x00000800
++
++#define TSXYRESULT_SDR 0x80000000
++
++/*
++ *-----------------------------------------------------------------------------
++ *-----------------------------------------------------------------------------
++ */
++
++#endif /* _REGS_TOUCH_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/regs_uart.h b/include/asm-arm/arch-ep93xx/regs_uart.h
+new file mode 100644
+index 0000000..cfadf4a
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/regs_uart.h
+@@ -0,0 +1,84 @@
++/*
++ * File: linux/include/asm-arm/arch-ep93xx/regs_uart.h
++ *
++ * Copyright (C) 2003 Cirrus Logic, Inc
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++
++#ifndef _REGS_UART_H_
++#define _REGS_UART_H_
++
++/* Bits in UARTRSR */
++#define UARTRSR_FE 0x00000001 /* Framing error */
++#define UARTRSR_PE 0x00000002 /* Parity error */
++#define UARTRSR_BE 0x00000004 /* Break error */
++#define UARTRSR_OE 0x00000008 /* Overrun error */
++
++/* Bits in UARTCR - UART1CR, UART2CR, or UART3CR */
++#define UARTLCR_H_BRK 0x00000001
++#define UARTLCR_H_PEN 0x00000002
++#define UARTLCR_H_EPS 0x00000004
++#define UARTLCR_H_STP2 0x00000008
++#define UARTLCR_H_FEN 0x00000010
++#define UARTLCR_H_WLEN 0x00000060
++#define UARTLCR_H_WLEN_8_DATA 0x00000060
++#define UARTLCR_H_WLEN_7_DATA 0x00000040
++#define UARTLCR_H_WLEN_6_DATA 0x00000020
++#define UARTLCR_H_WLEN_5_DATA 0x00000000
++
++/* Bits in UARTFR - UART1FR, UART2FR, or UART3FR */
++#define UARTFR_RSR_ERRORS 0x0000000F
++#define UARTFR_CTS 0x00000001
++#define UARTFR_DSR 0x00000002
++#define UARTFR_DCD 0x00000004
++#define UARTFR_BUSY 0x00000008
++#define UARTFR_RXFE 0x00000010
++#define UARTFR_TXFF 0x00000020
++#define UARTFR_RXFF 0x00000040
++#define UARTFR_TXFE 0x00000080
++
++/* Bits in UARTIIR */
++#define UARTIIR_MIS 0x00000001
++#define UARTIIR_RIS 0x00000002
++#define UARTIIR_TIS 0x00000004
++#define UARTIIR_RTIS 0x00000008
++
++/* Bits in UARTCR */
++#define UARTCR_UARTE 0x00000001
++#define UARTCR_MSIE 0x00000008
++#define UARTCR_RIE 0x00000010
++#define UARTCR_TIE 0x00000020
++#define UARTCR_RTIE 0x00000040
++#define UARTCR_LBE 0x00000080
++
++/* Bits in UARTMCR */
++#define UARTMCR_DTR 0x00000001
++#define UARTMCR_RTS 0x00000002
++#define UARTMCR_OUT1 0x00000004
++#define UARTMCR_OUT2 0x00000008
++#define UARTMCR_LOOP 0x00000010
++
++/* Bits in UARTMSR */
++#define UARTMSR_DCTS 0x00000001
++#define UARTMSR_DDSR 0x00000002
++#define UARTMSR_TERI 0x00000004
++#define UARTMSR_DDCD 0x00000008
++#define UARTMSR_CTS 0x00000010
++#define UARTMSR_DSR 0x00000020
++#define UARTMSR_RI 0x00000040
++#define UARTMSR_DCD 0x00000080
++
++#endif /* _REGS_UART_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/serial.h b/include/asm-arm/arch-ep93xx/serial.h
+new file mode 100644
+index 0000000..06ab737
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/serial.h
+@@ -0,0 +1,49 @@
++/*
++ * linux/include/asm-arm/arch-integrator/serial.h
++ *
++ * Copyright (C) 1999 ARM Limited
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef __ASM_ARCH_SERIAL_H
++#define __ASM_ARCH_SERIAL_H
++
++#include <asm/arch/platform.h>
++#include <asm/irq.h>
++
++/*
++ * This assumes you have a 1.8432 MHz clock for your UART.
++ *
++ * It'd be nice if someone built a serial card with a 24.576 MHz
++ * clock, since the 16550A is capable of handling a top speed of 1.5
++ * megabits/second; but this requires the faster clock.
++ */
++#define BASE_BAUD (1843200 / 16)
++
++#define _SER_IRQ0 IRQ_UARTINT0
++#define _SER_IRQ1 IRQ_UARTINT1
++
++#define RS_TABLE_SIZE 2
++
++#define STD_COM_FLAGS (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST)
++
++ /* UART CLK PORT IRQ FLAGS */
++#define STD_SERIAL_PORT_DEFNS \
++ { 0, BASE_BAUD, 0x3F8, _SER_IRQ0, STD_COM_FLAGS }, /* ttyS0 */ \
++ { 0, BASE_BAUD, 0x2F8, _SER_IRQ1, STD_COM_FLAGS }, /* ttyS1 */
++
++#define EXTRA_SERIAL_PORT_DEFNS
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/ssp-cirrus.h b/include/asm-arm/arch-ep93xx/ssp-cirrus.h
+new file mode 100644
+index 0000000..e29dc9d
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/ssp-cirrus.h
+@@ -0,0 +1,30 @@
++/*
++ *
++ * FILE: ssp.h
++ *
++ * DESCRIPTION: SSP Interface Driver Module implementation
++ *
++ * Copyright Cirrus Logic Corporation, 2001-2003. All rights reserved
++ *
++ */
++#ifndef _SSP_DRV_H_
++#define _SSP_DRV_H_
++
++enum SSPDeviceType {
++ PS2_KEYBOARD = 0,
++ I2S_CODEC = 1,
++ SERIAL_FLASH = 2
++};
++
++typedef void (*SSPDataCallback) (unsigned int Data);
++
++typedef struct _SSP_DRIVER_API {
++ int (*Open) (enum SSPDeviceType Device, SSPDataCallback Callback);
++ int (*Read) (int Handle, unsigned int Addr, unsigned int *pValue);
++ int (*Write) (int Handle, unsigned int Addr, unsigned int Value);
++ int (*Close) (int Handle);
++} SSP_DRIVER_API;
++
++extern SSP_DRIVER_API *SSPDriver;
++
++#endif /* _SSP_DRV_H_ */
+diff --git a/include/asm-arm/arch-ep93xx/ssp.h b/include/asm-arm/arch-ep93xx/ssp.h
+new file mode 100644
+index 0000000..9102233
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/ssp.h
+@@ -0,0 +1,121 @@
++/*
++ * ssp.h
++ *
++ * Copyright (C) 2004 Ray Lehtiniemi, All Rights Reserved.
++ * Copyright (C) 2004 Siconix, Inc., All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef SSP_H
++#define SSP_H
++
++#include <linux/list.h>
++#include <linux/completion.h>
++#include <asm/semaphore.h>
++
++struct ssp_master_ops;
++struct ssp_slave;
++
++struct ssp_transfer {
++
++ /* how many _bytes_ per unit of data */
++ int size;
++
++ /* how many units of data left to be clocked out */
++ int len;
++
++ /* how many units of data left to be clocked in */
++ int rlen;
++
++ /* buffer of units to shift out to slave */
++ void *tx;
++
++ /* buffer to hold units shifted in from slave */
++ void *rx;
++
++ /* signaled when complete */
++ struct completion *c;
++};
++
++struct ssp_master {
++
++ /* serialize access to the frontend */
++ struct semaphore sem;
++
++ /* synchronize the frontend and the backend */
++ struct completion completion;
++
++ /* the slave devices on this master */
++ struct list_head slave;
++
++ /* the active transfer on the bus */
++ struct ssp_transfer transfer;
++
++ /* methods for different master controllers */
++ struct ssp_master_ops *ops;
++};
++
++struct ssp_master_ops {
++
++ /* configure the master for accessing a particular slave */
++ int (*configure) (struct ssp_slave *);
++
++ /* enable the backend to start the transfer */
++ int (*enable) (struct ssp_transfer *);
++
++ /* disable the backend to stop the transfer */
++ int (*disable) (void);
++};
++
++struct ssp_slave {
++
++ /* our link in the masters list of slaves */
++ struct list_head list;
++
++ /* our master */
++ struct ssp_master *master;
++#if 0
++ /* the upper level protocol spoken by the device */
++ struct ssp_protocol *protocol;
++#endif
++ /* the phase and polarity modes we support */
++ unsigned long supported_modes;
++
++ /* our maximum clock rate, in Hz */
++ unsigned long max_clock_rate;
++
++ /* our data unit size, in bits */
++ int word_size;
++
++ /* our data unit size, in bytes */
++ int nbytes;
++
++ /* assert or negate the chip select line for this device */
++ void (*chip_select) (struct ssp_slave *, int);
++};
++
++/* manage the master-slave list */
++extern int ssp_add_slave(struct ssp_master *, struct ssp_slave *);
++extern void ssp_remove_slave(struct ssp_master *, struct ssp_slave *);
++
++/* perform a single transaction */
++extern int ssp_do(struct ssp_slave *s, int len, void *tx, void *rx);
++
++/* perform each step of a transaction */
++extern int ssp_start(struct ssp_slave *s); /* grab master, blocking */
++extern int ssp_trystart(struct ssp_slave *s); /* grab master, non-blocking */
++extern void ssp_select(struct ssp_slave *s); /* assert CS */
++extern int ssp_post(struct ssp_slave *s, int len, void *tx, void *rx); /* start a transfer */
++extern int ssp_wait(struct ssp_slave *s); /* wait for completion */
++ /*extern int ssp_disable (struct ssp_slave *s); *//* stop a transfer */
++extern void ssp_deselect(struct ssp_slave *s); /* negate CS */
++extern void ssp_finish(struct ssp_slave *s); /* release master */
++
++/* module stuff */
++extern int ssp_init(void);
++extern void ssp_exit(void);
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/ssp2.h b/include/asm-arm/arch-ep93xx/ssp2.h
+new file mode 100644
+index 0000000..93823a0
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/ssp2.h
+@@ -0,0 +1,29 @@
++/*
++ * ssp.h
++ *
++ * Copyright (C) 2004 Ray Lehtiniemi, All Rights Reserved.
++ * Copyright (C) 2004 Siconix, Inc., All Rights Reserved.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License version 2 as
++ * published by the Free Software Foundation.
++ */
++
++#ifndef SSP2_H
++#define SSP2_H
++
++#include <asm/arch/ssp.h>
++
++struct ep93xx_ssp_slave {
++ struct ssp_slave slave;
++ unsigned long cr0;
++ unsigned long cr1;
++ unsigned long cpsr;
++};
++
++extern struct ssp_master ep93xx_ssp_master;
++
++extern int ep93xx_ssp_init(void);
++extern void ep93xx_ssp_exit(void);
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/system.h b/include/asm-arm/arch-ep93xx/system.h
+new file mode 100644
+index 0000000..1030210
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/system.h
+@@ -0,0 +1,68 @@
++/*
++ * linux/include/asm-arm/arch-ep93xx/system.h
++ *
++ * Copyright (C) 1999 ARM Limited
++ * Copyright (C) 2000 Deep Blue Solutions Ltd
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef __ASM_ARCH_SYSTEM_H
++#define __ASM_ARCH_SYSTEM_H
++
++#include <asm/arch/platform.h>
++#include <asm/hardware.h>
++#include <asm/io.h>
++
++static void arch_idle(void)
++{
++ unsigned long val = readl(SYSCON_DEVCFG);
++ val = ep93xx_SYSCON_DEVCFG(val | SYSCON_DEVCFG_SHena);
++ SysconSetLocked(SYSCON_DEVCFG, val);
++ readl(SYSCON_HALT);
++}
++
++#if defined(CONFIG_MACH_TTML)
++
++#include <asm/arch/mach-ttml.h>
++extern __inline__ void arch_reset(char mode)
++{
++ /* reboot using micro */
++ unsigned char msg[4] = { 0xaa, 0x90, 0xa0, 0x65 };
++ unsigned char reply[10];
++ (void)ssp_do_ttml(&ep93xx_ssp_micro, msg, 4, reply, 10);
++ while (1) ;
++}
++
++#else
++
++extern __inline__ void arch_reset(char mode)
++{
++#if 1
++ /* reboot using SW_RESET bit in devcfg register */
++ unsigned long val = readl(SYSCON_DEVCFG);
++ SysconSetLocked(SYSCON_DEVCFG,
++ ep93xx_SYSCON_DEVCFG(val | SYSCON_DEVCFG_SWRST));
++ SysconSetLocked(SYSCON_DEVCFG,
++ ep93xx_SYSCON_DEVCFG(val & ~SYSCON_DEVCFG_SWRST));
++
++#else
++ /* reboot using 0.250 second onboard watchdog timeout */
++ writel(0xaaaa, WATCHDOG);
++ while (1) ;
++#endif
++}
++#endif
++
++#endif
+diff --git a/include/asm-arm/arch-ep93xx/timex.h b/include/asm-arm/arch-ep93xx/timex.h
+new file mode 100644
+index 0000000..87a7628
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/timex.h
+@@ -0,0 +1,26 @@
++/*
++ * linux/include/asm-arm/arch-integrator/timex.h
++ *
++ * Integrator architecture timex specifications
++ *
++ * Copyright (C) 1999 ARM Limited
++ *
++ * 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
++ */
++
++/*
++ * ??
++ */
++#define CLOCK_TICK_RATE (50000000 / 16)
+diff --git a/include/asm-arm/arch-ep93xx/uncompress.h b/include/asm-arm/arch-ep93xx/uncompress.h
+new file mode 100644
+index 0000000..f76de3c
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/uncompress.h
+@@ -0,0 +1,91 @@
++/*
++ * linux/include/asm-arm/arch-ep93xx/uncompress.h
++ *
++ * Copyright (C) 1999 ARM Limited
++ *
++ * 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 <asm/io.h>
++#include <asm/hardware.h>
++
++#if defined(CONFIG_MACH_ZEFEERDZA) || defined(CONFIG_MACH_ZEFEERDZB) || \
++ defined(CONFIG_MACH_ZEFEERDZG) || defined(CONFIG_MACH_ZEFEERDZN) || defined(CONFIG_MACH_ZEFEERDZQ)
++# define BAUDRATE ((EP93XX_UART_CLK/(16 * 115200)) - 1)
++#else
++# define BAUDRATE ((EP93XX_UART_CLK/(16 * 57600)) - 1)
++#endif
++
++#define HW_PREG(reg) ((unsigned int volatile *)(io_v2p(reg)))
++
++static void putstr(const char *s)
++{
++ while (*s) {
++ while (*HW_PREG(UART1FR) & UARTFR_TXFF) ;
++
++ *HW_PREG(UART1DR) = *s;
++
++ if (*s == '\n') {
++ while (*HW_PREG(UART1FR) & UARTFR_TXFF) ;
++
++ *HW_PREG(UART1DR) = '\r';
++ }
++ s++;
++ }
++ while (*HW_PREG(UART1FR) & UARTFR_BUSY) ;
++}
++
++static void EnableUart(void)
++{
++ /*
++ * Ensure that the base clock to the UARTS is 14.7456Mhz
++ * and that UART1 is enabled.
++ */
++ *HW_PREG(SYSCON_PWRCNT) = SYSCON_PWRCNT_UARTBAUD;
++
++ *HW_PREG(SYSCON_SWLOCK) = 0xaa;
++ *HW_PREG(SYSCON_DEVCFG) = (*HW_PREG(SYSCON_DEVCFG)) | SYSCON_DEVCFG_U1EN;
++
++ /* Disable the UARTS and clear out the old settings. */
++ *HW_PREG(UART1MCR) = 0;
++ *HW_PREG(UART1CR) = 0;
++ *HW_PREG(UART1RSR) = 0;
++ *HW_PREG(UART1CR_L) = 0;
++ *HW_PREG(UART1CR_M) = 0;
++ *HW_PREG(UART1CR_H) = 0;
++
++ /* Set the baud rate and framing */
++ *HW_PREG(UART1CR_L) = (BAUDRATE & 0x0FF);
++ *HW_PREG(UART1CR_M) = ((BAUDRATE >> 8) & 0x0FF);
++
++ /* 8 Data bits, No Parity, 1 Stop bit. */
++ *HW_PREG(UART1CR_H) = (UARTLCR_H_WLEN_8_DATA | UARTLCR_H_FEN);
++
++ /* Enable Uart */
++ *HW_PREG(UART1CR) = UARTCR_UARTE;
++}
++
++#if defined(CONFIG_MACH_ADSSPHERE)
++#define arch_decomp_setup()
++#else
++
++/* Called early before the UART is used for output by the compressed loader. */
++static void arch_decomp_setup(void)
++{
++ EnableUart();
++}
++#endif
++
++#define arch_decomp_wdog()
+diff --git a/include/asm-arm/arch-ep93xx/vmalloc.h b/include/asm-arm/arch-ep93xx/vmalloc.h
+new file mode 100644
+index 0000000..ec8f98d
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/vmalloc.h
+@@ -0,0 +1,32 @@
++/*
++ * linux/include/asm-arm/arch-integrator/vmalloc.h
++ *
++ * Copyright (C) 2000 Russell King.
++ *
++ * 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
++ */
++
++/*
++ * Just any arbitrary offset to the start of the vmalloc VM area: the
++ * current 8MB value just means that there will be a 8MB "hole" after the
++ * physical memory until the kernel virtual memory starts. That means that
++ * any out-of-bounds memory accesses will hopefully be caught.
++ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
++ * area for the same reason. ;)
++ */
++#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))
++#define VMALLOC_END (PAGE_OFFSET + 0x10000000)
+diff --git a/include/asm-arm/arch-ep93xx/zefeerevb.h b/include/asm-arm/arch-ep93xx/zefeerevb.h
+new file mode 100644
+index 0000000..2cb3f84
+--- /dev/null
++++ b/include/asm-arm/arch-ep93xx/zefeerevb.h
+@@ -0,0 +1,51 @@
++/*
++ * linux/include/asm-arm/arch-ep93xx/platform.h
++ *
++ * Copyright (C) 2004 DAVE Srl <www.dave-tech.it>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ */
++#ifndef ASM_ARCH_ZEFEEREVB_H
++#define ASM_ARCH_ZEFEEREVB_H
++
++#ifdef CONFIG_MACH_ZEFEER_EVBL_107
++/* GPIO pins used to drive NAND chip mounted on old EVB */
++/*
++ nCE = EGPIO2
++ CLE = EGPIO0
++ ALE = EGPIO1
++ R/B = EGPIO3
++*/
++# define NAND_EVB_nCE_GPIO_PIN (1 << 2)
++# define NAND_EVB_CLE_GPIO_PIN (1 << 0)
++# define NAND_EVB_ALE_GPIO_PIN (1 << 1)
++# define NAND_EVB_RB_GPIO_PIN (1 << 3)
++#else
++/* GPIO pins used to drive NAND chip mounted on EVB */
++/*
++ nCE = EGPIO6
++ CLE = EGPIO4
++ ALE = EGPIO5
++ R/B = EGPIO7
++*/
++# define NAND_EVB_nCE_GPIO_PIN (1 << 6)
++# define NAND_EVB_CLE_GPIO_PIN (1 << 4)
++# define NAND_EVB_ALE_GPIO_PIN (1 << 5)
++# define NAND_EVB_RB_GPIO_PIN (1 << 7)
++#endif
++
++#define ZEFEEREVB_NAND_PADDR 0x20000000
++
++#endif /* ASM_ARCH_ZEFEEREVB_H */
+diff --git a/include/asm-arm/irq.h b/include/asm-arm/irq.h
+index 59975ee..755d9de 100644
+--- a/include/asm-arm/irq.h
++++ b/include/asm-arm/irq.h
+@@ -38,6 +38,12 @@ extern void enable_irq(unsigned int);
+ #define IRQT_HIGH (__IRQT_HIGHLVL)
+ #define IRQT_PROBE (1 << 4)
+
++/*
++ * Flags for enable and disable debounce
++ */
++#define IRQT_DB ( 1 << 5 )
++#define IRQT_NOTDB ( 1 << 6 )
++
+ int set_irq_type(unsigned int irq, unsigned int type);
+ void disable_irq_wake(unsigned int irq);
+ void enable_irq_wake(unsigned int irq);
+diff --git a/include/asm-arm/procinfo.h b/include/asm-arm/procinfo.h
+index a9c75b2..556e5d8 100644
+--- a/include/asm-arm/procinfo.h
++++ b/include/asm-arm/procinfo.h
+@@ -56,5 +56,6 @@ extern unsigned int elf_hwcap;
+ #define HWCAP_VFP 64
+ #define HWCAP_EDSP 128
+ #define HWCAP_JAVA 256
++#define HWCAP_CRUNCH 512
+
+ #endif
+diff --git a/include/linux/can/oki_ml9620_ctrl.h b/include/linux/can/oki_ml9620_ctrl.h
+new file mode 100644
+index 0000000..d2cfbea
+--- /dev/null
++++ b/include/linux/can/oki_ml9620_ctrl.h
+@@ -0,0 +1,54 @@
++/*
++ * include/linux/can/oki_ml9620_ctrl.h
++ *
++ * OKI ML9620 CAN Controler driver
++ *
++ * Author: Manfred Gruber <manfred.gruber@contec.at>
++ *
++ * Copyright 2004 (c) Manfred Gruber
++ * Copyright 2004 (c) Contec Steuerungstechnik & Automation Ges.m.b.H
++ * Kufstein/Austria www.contec.at
++ *
++ * This driver was written for Contec hypercontrol Micro9 Board
++ * 1. CAN Controller is on Hypercontrol Micro9 CPU board
++ * 2. CAN Controller is on Hypercontrol Micro9 eval board
++ *
++ * This file is licensed under the terms of the GNU General Public
++ * License version 2. This program is licensed "as is" without any
++ * warranty of any kind, whether express or implied.
++ */
++
++#ifndef _OKI_ML9620_CTRL_H_
++#define _OKI_ML9620_CTRL_H_
++
++#ifdef __KERNEL__
++struct can_msg {
++ unsigned short id; /* identifier */
++ unsigned short dlc : 4; /* bitfield 4: data length code [0..8] */
++ unsigned short rtr : 1; /* bitfield 1: rtr bit */
++ unsigned short ext : 1; /* bitfield 1: extended ID */
++ unsigned short pad : 10; /* workaround alignment issues:
++ FIXME: completely remove that bitfield junk */
++ unsigned char data[8]; /* data bytes */
++};
++#endif
++
++#define CAN_STS_CNTRL_OFF 0 /*!< set CAN controller off */
++#define CAN_STS_CNTRL_ON 1 /*!< set CAN controller on */
++#define CAN_STS_CNTRL_SLEEP 2 /*!< set CAN controller sleep mode */
++#define CAN_STS_CNTRL_AWAKE 3 /*!< set CAN controller wake up */
++#define CAN_STS_NORMAL 0x00 /*!< CAN controller status normal */
++#define CAN_STS_RESET 0x01 /*!< CAN controller status reset */
++#define CAN_STS_WARNING 0x02 /*!< CAN controller status warning */
++#define CAN_STS_BUS_OFF 0x04 /*!< CAN controller status bus off */
++#define CAN_STS_SLEEPING 0x08 /*!< CAN controller status sleeping */
++#define CAN_STS_OVERRUN 0x10 /*!< CAN controller status overrun */
++#define CAN_STS_TXOK 0x20 /*!< CAN message transmitted */
++
++#define COMMAND 0
++#define CONFIG 1
++#define SEND 2
++#define RECEIVE 3
++#define STATUS 4
++
++#endif
+diff --git a/include/linux/input.h b/include/linux/input.h
+index 3c58233..8ea2247 100644
+--- a/include/linux/input.h
++++ b/include/linux/input.h
+@@ -414,6 +414,7 @@ struct input_absinfo {
+ #define BTN_STYLUS2 0x14c
+ #define BTN_TOOL_DOUBLETAP 0x14d
+ #define BTN_TOOL_TRIPLETAP 0x14e
++#define BTN_RAW 0x14f
+
+ #define BTN_WHEEL 0x150
+ #define BTN_GEAR_DOWN 0x150
+diff --git a/include/linux/irda.h b/include/linux/irda.h
+index 95dee17..3172c96 100644
+--- a/include/linux/irda.h
++++ b/include/linux/irda.h
+@@ -76,6 +76,7 @@ typedef enum {
+ IRDA_MCP2120_DONGLE = 9,
+ IRDA_ACT200L_DONGLE = 10,
+ IRDA_MA600_DONGLE = 11,
++ IRDA_EP93XX_SIR = 12,
+ } IRDA_DONGLE;
+
+ /* Protocol types to be used for SOCK_DGRAM */
+diff --git a/include/linux/sched.h b/include/linux/sched.h
+index b0ad6f3..2ee1652 100644
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -883,6 +883,11 @@ extern void __put_task_struct(struct tas
+ #define put_task_struct(tsk) \
+ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
+
++#ifdef CONFIG_EP93XX_CRUNCH
++#define PF_USEDCRUNCH 0x00200000 /* introduced to preserve PF_USEDFPU
++ meaning across the architecture */
++#endif
++
+ /*
+ * Per process flags
+ */
+diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
+index e3710d7..a1c9b53 100644
+--- a/include/linux/serial_core.h
++++ b/include/linux/serial_core.h
+@@ -124,6 +124,9 @@
+ /* Hilscher netx */
+ #define PORT_NETX 71
+
++/* Cirrus EP93xx family */
++#define PORT_EP93XX 65
++
+ #ifdef __KERNEL__
+
+ #include <linux/config.h>
+diff --git a/include/linux/ttml.h b/include/linux/ttml.h
+new file mode 100644
+index 0000000..2b0e327
+--- /dev/null
++++ b/include/linux/ttml.h
+@@ -0,0 +1,61 @@
++/*
++ * include/linux/ttml.h
++ *
++ * TTML TripDawg system devices.
++ *
++ * Copyright 2004, Ray Lehtiniemi
++ * Copyright 2004, Siconix, Inc
++ */
++
++#ifndef __TTML_H
++#define __TTML_H
++
++#define TTML_MAJOR MISC_MAJOR
++
++#define TTML_MINOR_LED 240
++#define TTML_MINOR_BUZZER 241
++#define TTML_MINOR_SPEEDO 242
++#define TTML_MINOR_GPIO 243
++#define TTML_MINOR_BUTTON 244
++#define TTML_MINOR_WD 245
++
++#define MAX_TTML_MINORS 6
++
++struct ttml_ioctl_led {
++ int blue;
++ int red;
++ int yellow;
++};
++
++struct ttml_ioctl_buzzer {
++ int buzzer1;
++};
++
++struct ttml_ioctl_speedo {
++ int instant;
++ int average;
++};
++
++struct ttml_ioctl_gpio {
++ int pto;
++ int ignition;
++ int spare;
++};
++
++struct ttml_ioctl_button {
++ int button1;
++ int portf;
++};
++
++#define TTML_IOCTL 't'
++
++#define TTML_GET_LED _IOR(TTML_IOCTL, 0, struct ttml_ioctl_led)
++#define TTML_GET_BUZZER _IOR(TTML_IOCTL, 1, struct ttml_ioctl_buzzer)
++#define TTML_GET_SPEEDO _IOR(TTML_IOCTL, 2, struct ttml_ioctl_speedo)
++#define TTML_GET_GPIO _IOR(TTML_IOCTL, 3, struct ttml_ioctl_gpio)
++#define TTML_GET_BUTTON _IOR(TTML_IOCTL, 4, struct ttml_ioctl_button)
++
++#define TTML_SET_LED _IOW(TTML_IOCTL, 16, struct ttml_ioctl_led)
++#define TTML_SET_BUZZER _IOW(TTML_IOCTL, 17, struct ttml_ioctl_buzzer)
++
++#endif
+diff --git a/include/net/irda/ep93xx_irda.h b/include/net/irda/ep93xx_irda.h
+new file mode 100644
+index 0000000..0ee919d
+--- /dev/null
++++ b/include/net/irda/ep93xx_irda.h
+@@ -0,0 +1,261 @@
++ /*********************************************************************
++ *
++ * Filename: ep93xx_irda.h
++ * Version: 0.2
++ * Description: Header for the EP93xx SOC IrDA driver.
++ * Status: Experimental.
++ *
++ * Copyright 2003 Cirrus Logic, Inc.
++ *
++ * Based on the ali-ircc.c implementation:
++ * Author: Benjamin Kong <benjamin_kong@ali.com.tw>
++ * Created at: 2000/10/16 03:46PM
++ * Modified at: 2001/1/3 02:55PM
++ * Modified by: Benjamin Kong <benjamin_kong@ali.com.tw>
++ *
++ * Copyright (c) 2000 Benjamin Kong <benjamin_kong@ali.com.tw>
++ * All Rights Reserved
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of
++ * the License, or (at your option) any later version.
++ *
++ * This program is 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:
++ * Free Software Foundation, Inc.
++ * 59 Temple Place, Suite 330
++ * Boston, MA 02111-1307 USA
++ ********************************************************************/
++
++#ifndef EP93XX_IRDA_H
++#define EP93XX_IRDA_H
++
++#include <linux/time.h>
++
++#include <linux/spinlock.h>
++#include <linux/pm.h>
++#include <asm/io.h>
++
++/*
++ * Number of DMA channels used
++ */
++#define DMA_COUNT 3
++
++/*
++ * TX/RX window queues
++ */
++#define MAX_TX_WINDOW 7
++#define MAX_RX_WINDOW 7
++
++struct ep93xx_chip {
++ char *name;
++ int iSIR_IRQ, iMFIR_IRQ;
++ ep93xx_dma_dev_t eSIR_DMATx;
++ ep93xx_dma_dev_t eMFIR_DMATx;
++ ep93xx_dma_dev_t eMFIR_DMARx;
++ int (*init) (struct ep93xx_chip * chip);
++};
++
++/* For storing entries in the status FIFO */
++
++struct st_fifo_entry {
++ int status;
++ int len;
++};
++
++struct st_fifo {
++ struct st_fifo_entry entries[MAX_RX_WINDOW];
++ int pending_bytes;
++ int head;
++ int tail;
++ int len;
++};
++
++struct frame_cb {
++ void *start; /* Start of frame in DMA mem */
++ int len; /* Lenght of frame in DMA mem */
++};
++
++struct tx_fifo {
++ struct frame_cb queue[MAX_TX_WINDOW]; /* Info about frames in queue */
++ int ptr; /* Currently being sent */
++ int len; /* Length of queue */
++ int free; /* Next free slot */
++ void *tail; /* Next free start in DMA mem */
++};
++
++/* Private data for each instance */
++struct ep93xx_irda_cb {
++ struct st_fifo st_fifo; /* Info about received frames */
++ struct tx_fifo tx_fifo; /* Info about frames to be transmitted */
++
++ struct net_device *netdev; /* Net device pointer */
++ struct net_device_stats stats; /* Net device stats */
++
++ struct irlap_cb *irlap; /* The link layer we are binded with */
++ struct qos_info qos; /* QoS capabilities for this device */
++
++ int iSIR_irq, iMFIR_irq; /* Interrupts used */
++
++ ep93xx_dma_dev_t ePorts[DMA_COUNT]; /* DMA port ids */
++
++ int iDMAh[DMA_COUNT]; /* handles for DMA channels */
++ dma_addr_t rx_dmaphysh, tx_dmaphysh;
++
++ int fifo_size; /* FIFO size */
++ iobuff_t tx_buff; /* Transmit buffer */
++ iobuff_t rx_buff; /* Receive buffer */
++
++ char *conv_buf; /* Buffer used for SIR conversion */
++
++ struct timeval stamp; /* ? */
++ struct timeval now; /* ? */
++
++ spinlock_t lock; /* Used for serializing operations */
++
++ __u32 flags; /* Interface flags */
++
++ __u8 direction; /* TX/RX flag */
++
++ __u32 speed; /* Currently used speed */
++ __u32 new_speed; /* New target tx/rx speed */
++
++ int index; /* Instance index */
++
++ int suspended; /* APM suspend flag */
++ struct pm_dev *dev; /* Power Management device */
++
++};
++
++/*
++ * DMA array handle index meanings
++ */
++#define DMA_SIR_TX 0
++#define DMA_MFIR_TX 1
++#define DMA_MFIR_RX 2
++
++/*
++ * Directional defines
++ */
++#define DIR_TX 0x01
++#define DIR_RX 0x02
++#define DIR_BOTH 0x03
++
++/*
++ * Modes support flag defines.
++ */
++#define CLK_SIR 0x01
++#define CLK_MIR 0x02
++#define CLK_FIR 0x04
++
++/* Name friendly bit defines for register accesses */
++
++/* UART2/SIR */
++#define U2RSR_OvnErr 0x08
++#define U2RSR_BrkErr 0x04
++#define U2RSR_PtyErr 0x02
++#define U2RSR_FrmErr 0x01
++
++#define U2CRH_WLen 0x60
++#define U2CRH_FEn 0x10
++#define U2CRH_Stp2 0x08
++#define U2CRH_EPS 0x04
++#define U2CRH_PEn 0x02
++#define U2CRH_Brk 0x01
++
++#define U2CR_LoopBk 0x80
++#define U2CR_RxTO 0x40
++#define U2CR_TxIrq 0x20
++#define U2CR_RxIrq 0x10
++#define U2CR_MdmStsIrq 0x08
++#define U2CR_SIRLowPwr 0x04
++#define U2CR_SIR 0x02
++#define U2CR_UART 0x01
++
++#define U2FR_TXFE 0x80
++#define U2FR_RXFF 0x40
++#define U2FR_TXFF 0x20
++#define U2FR_RXFE 0x10
++#define U2FR_BUSY 0x08
++#define U2FR_DCD 0x04
++#define U2FR_DSR 0x02
++#define U2FR_CTS 0x01
++
++#define U2IICR_RXTOIRQ 0x08
++#define U2IICR_TXIRQ 0x04
++#define U2IICR_RXIRQ 0x02
++#define U2IICR_MDMIRQ 0x01
++
++#define U2DMACR_DMAErr 0x04
++#define U2DMACR_TXDMA 0x02
++#define U2DMACR_RXDMA 0x01
++
++#define IrENABLE_SIR 0x01
++
++/* IrDA block - MIR/FIR */
++#define IrENABLE_FIR 0x03
++#define IrENABLE_MIR 0x02
++
++#define IrCONTROL_RXRP 0x40
++#define IrCONTROL_TXRP 0x20
++#define IrCONTROL_RXON 0x10
++#define IrCONTROL_TXON 0x08
++#define IrCONTROL_TXUNDER 0x04
++#define IrCONTROL_MIRBR 0x02
++
++#define IrFLAG_TXBUSY 0x200
++#define IrFLAG_RXINFRM 0x100
++#define IrFLAG_RXSYNC 0x80
++#define IrFLAG_EOF 0x40
++#define IrFLAG_WIDTHST 0x30
++#define IrFLAG_FIRFE 0x08
++#define IrFLAG_RXOR 0x04
++#define IrFLAG_CRCERR 0x02
++#define IrFLAG_RXABORT 0x01
++
++#define IrRIB_ByteCt 0x7FF0
++#define IrRIB_BUFFE 0x08
++#define IrRIB_BUFOR 0x04
++#define IrRIB_BUFCRCERR 0x02
++#define IrRIB_BUFRXABORT 0x01
++
++#define IrDMACR_DMAERR 0x04
++#define IrDMACR_DMATXE 0x02
++#define IrDMACR_DMARXE 0x01
++
++#define MFISR_RXFL 0x40
++#define MFISR_RXIL 0x20
++#define MFISR_RXFC 0x10
++#define MFISR_RXFS 0x08
++#define MFISR_TXFABORT 0x04
++#define MFISR_TXFC 0x02
++#define MFISR_TXSR 0x01
++
++#define MFIMR_RXFL 0x40
++#define MFIMR_RXIL 0x20
++#define MFIMR_RXFC 0x10
++#define MFIMR_RXFS 0x08
++#define MFIMR_TXABORT 0x04
++#define MFIMR_TXFC 0x02
++#define MFIMR_TXFS 0x01
++
++#define MFIIR_RXFL 0x40
++#define MFIIR_RXIL 0x20
++#define MFIIR_RXFC 0x10
++#define MFIIR_RXFS 0x08
++#define MFIIR_TXABORT 0x04
++#define MFIIR_TXFC 0x02
++#define MFIIR_TXFS 0x01
++
++#endif /* EP93XX_IRDA_H */
+diff --git a/init/do_mounts.c b/init/do_mounts.c
+index b27c110..29d2d52 100644
+--- a/init/do_mounts.c
++++ b/init/do_mounts.c
+@@ -410,7 +410,9 @@ void __init prepare_namespace(void)
+ root_device_name += 5;
+ }
+
+- is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR;
++ /* llandre */
++ /* To retrieve ramdisk from MTD partition we must add major 31 as suggested by rmk */
++ is_floppy = MAJOR(ROOT_DEV) == FLOPPY_MAJOR || MAJOR(ROOT_DEV) == 31;
+
+ if (initrd_load())
+ goto out;
+diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
+index 88e52dc..cda016b 100644
+--- a/sound/oss/Kconfig
++++ b/sound/oss/Kconfig
+@@ -1004,6 +1004,26 @@ config SOUND_AEDSP16
+ <file:Documentation/sound/oss/AudioExcelDSP16> to get more information
+ about this driver and its configuration.
+
++
++config SOUND_EP93XX_AC97
++ tristate "EP93xx AC97 Support"
++ depends on SOUND_OSS && ARCH_EP93XX
++ ---help---
++ AC97 sound support for Cirrus EP93xx
++
++config SOUND_EP93XX_AC97_CODEC_CS4297
++ bool "CS4297"
++ depends on SOUND_EP93XX_AC97
++ help
++ Say Y here if you have CS4297 Codec.
++
++config SOUND_EP93XX_AUDIO_PIO
++ bool "EP93xx AC97 in PIO mode"
++ depends on SOUND_EP93XX_AC97
++ ---help---
++ Run EP93XX AC97 in PIO MODE.
++ !!! NOT TESTED !!!
++
+ config SC6600
+ bool "SC-6600 based audio cards (new Audio Excel DSP 16)"
+ depends on SOUND_AEDSP16
+diff --git a/sound/oss/Makefile b/sound/oss/Makefile
+index 9bf3ee5..c7c1927 100644
+--- a/sound/oss/Makefile
++++ b/sound/oss/Makefile
+@@ -91,6 +91,9 @@ obj-$(CONFIG_SOUND_EMU10K1) += emu10k1/
+ obj-$(CONFIG_SOUND_CS4281) += cs4281/
+ obj-$(CONFIG_DMASOUND) += dmasound/
+
++obj-$(CONFIG_SOUND_EP93XX_I2S) += ep93xx-audio.o ep93xx-i2s.o
++obj-$(CONFIG_SOUND_EP93XX_AC97) += ep93xx-audio.o ep93xx-ac97.o
++
+ # Declare multi-part drivers.
+
+ sound-objs := \
+diff --git a/sound/oss/ac97_codec.c b/sound/oss/ac97_codec.c
+index fd25aca..c7c9a02 100644
+--- a/sound/oss/ac97_codec.c
++++ b/sound/oss/ac97_codec.c
+@@ -156,6 +156,8 @@ static const struct {
+ {0x43525931, "Cirrus Logic CS4299 rev A", &crystal_digital_ops},
+ {0x43525933, "Cirrus Logic CS4299 rev C", &crystal_digital_ops},
+ {0x43525934, "Cirrus Logic CS4299 rev D", &crystal_digital_ops},
++ {0x4352594d, "Cirrus Logic CS4201", &crystal_digital_ops},
++ {0x43525973, "Cirrus Logic CS4202", &crystal_digital_ops},
+ {0x43585430, "CXT48", &default_ops, AC97_DELUDED_MODEM },
+ {0x43585442, "CXT66", &default_ops, AC97_DELUDED_MODEM },
+ {0x44543031, "Diamond Technology DT0893", &default_ops},
+diff --git a/sound/oss/ep93xx-ac97.c b/sound/oss/ep93xx-ac97.c
+new file mode 100644
+index 0000000..a967f19
+--- /dev/null
++++ b/sound/oss/ep93xx-ac97.c
+@@ -0,0 +1,1200 @@
++/*
++ * Glue audio driver for the Cirrus EP93xx Ac97 Controller
++ *
++ * Copyright (c) 2003 Cirrus Logic Corp.
++ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License.
++ *
++ * This file taken from h3600-uda1341.c
++ * The mixer code is from ac97_codec.c
++ *
++ * History:
++ *
++ * 2000-05-21 Nicolas Pitre Initial UDA1341 driver release.
++ *
++ * 2000-07-?? George France Bitsy support.
++ *
++ * 2000-12-13 Deborah Wallach Fixed power handling for iPAQ/h3600
++ *
++ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
++ * the former sa1100-uda1341.c driver.
++ *
++ * 2001-07-13 Nicolas Pitre Fixes for all supported samplerates.
++ *
++ * 2003-04-04 adt Changes for Cirrus Logic EP93xx I2S
++ *
++ * 2003-04-25 adt Changes for Cirrus Logic EP93xx Ac97
++ *
++ * 2005-05-11 Manfred Gruber Ported this from Cirrus Logic Virgo 1-4-3 release
++ * to Kernel 2.6.11.X
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/fs.h>
++#include <linux/delay.h>
++#include <linux/pm.h>
++#include <linux/errno.h>
++#include <linux/sound.h>
++#include <linux/soundcard.h>
++#include <linux/bitops.h>
++
++#include <asm/semaphore.h>
++#include <asm/uaccess.h>
++#include <asm/hardware.h>
++#include <asm/dma.h>
++#include <asm/arch/clocks.h>
++#include <asm/io.h>
++#include <asm/arch/dma.h>
++#include <linux/dma-mapping.h>
++
++#include "ep93xx-audio.h"
++
++#undef DEBUG
++//#define DEBUG 1
++#ifdef DEBUG
++#define DPRINTK( x... ) printk( x )
++#else
++#define DPRINTK( x... )
++#endif
++
++#define AUDIO_NAME "ep93xx_ac97"
++
++#ifdef CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297
++#define AUDIO_SAMPLE_RATE_DEFAULT 48000
++#else
++#define AUDIO_SAMPLE_RATE_DEFAULT 44100
++#endif
++
++/* original check is not good enough in case FOO is greater than
++ * SOUND_MIXER_NRDEVICES because the supported_mixers has exactly
++ * SOUND_MIXER_NRDEVICES elements.
++ * before matching the given mixer against the bitmask in supported_mixers we
++ * check if mixer number exceeds maximum allowed size which is as mentioned
++ * above SOUND_MIXER_NRDEVICES */
++#define supported_mixer(FOO) \
++ ( (FOO >= 0) && \
++ (FOO < SOUND_MIXER_NRDEVICES) && \
++ codec_supported_mixers & (1<<FOO) )
++
++/*
++ * Available record sources.
++ * LINE1 refers to AUX in.
++ * IGAIN refers to input gain which means stereo mix.
++ */
++#define AC97_RECORD_MASK \
++ (SOUND_MASK_MIC | SOUND_MASK_CD | SOUND_MASK_IGAIN | SOUND_MASK_VIDEO |\
++ SOUND_MASK_LINE1 | SOUND_MASK_LINE | SOUND_MASK_PHONEIN)
++
++#define AC97_STEREO_MASK \
++ (SOUND_MASK_VOLUME | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_CD | \
++ SOUND_MASK_ALTPCM | SOUND_MASK_IGAIN | SOUND_MASK_LINE1 | SOUND_MASK_VIDEO)
++
++#define AC97_SUPPORTED_MASK \
++ (AC97_STEREO_MASK | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
++ SOUND_MASK_SPEAKER | SOUND_MASK_MIC | \
++ SOUND_MASK_PHONEIN | SOUND_MASK_PHONEOUT)
++
++/*
++ * Function prototypes.
++ */
++static int peek(unsigned int uiAddress);
++static int poke(unsigned int uiAddress, unsigned int uiValue);
++static void ep93xx_setup_src(void);
++static void ep93xx_set_samplerate(struct audio_stream_t *stream,
++ long lSampleRate);
++static void ep93xx_init_ac97_codec(void);
++static void ep93xx_set_hw_format(struct audio_stream_t *stream, long format);
++static void ep93xx_init_ac97_controller(void);
++static int ep93xx_mixer_ioctl(struct inode *inode, struct file *file, uint cmd,
++ ulong arg);
++static void ep93xx_audio_init(void *dummy);
++static int ep93xx_audio_ioctl(struct inode *inode, struct file *file, uint cmd,
++ ulong arg);
++
++static int ep93xx_audio_open(struct inode *inode, struct file *file);
++static int __init ep93xx_ac97_init(void);
++static void __exit ep93xx_ac97_exit(void);
++static void ep93xx_init_mixer(void);
++static void ep93xx_audio_enable(struct audio_stream_t *stream);
++static void ep93xx_audio_disable(struct audio_stream_t *stream);
++
++/*
++ * Statics
++ */
++// KERNEL2.4
++//static long audio_samplerate = AUDIO_SAMPLE_RATE_DEFAULT;
++static int ac_link_enabled = 0;
++static int codec_supported_mixers;
++
++/* this table has default mixer values for all OSS mixers. */
++struct mixer_defaults_t {
++ int mixer;
++ unsigned int value;
++};
++
++/*
++ * Default mixer settings that are set up during boot.
++ *
++ * These values are 16 bit numbers in which the upper byte is right volume
++ * and the lower byte is left volume or mono volume for mono controls.
++ *
++ * OSS Range for each of left and right volumes is 0 to 100 (0x00 to 0x64).
++ *
++ */
++static struct mixer_defaults_t mixer_defaults[SOUND_MIXER_NRDEVICES] = {
++ /* Outputs */
++ {SOUND_MIXER_VOLUME, 0x6464}, /* 0 dB *//* -46.5dB to 0 dB */
++ {SOUND_MIXER_ALTPCM, 0x6464}, /* 0 dB *//* -46.5dB to 0 dB */
++ {SOUND_MIXER_PHONEOUT, 0x6464}, /* 0 dB *//* -46.5dB to 0 dB */
++
++ /* PCM playback gain */
++ {SOUND_MIXER_PCM, 0x4b4b}, /* 0 dB *//* -34.5dB to +12dB */
++
++ /* Record gain */
++ {SOUND_MIXER_IGAIN, 0x0000}, /* 0 dB *//* 0 to +22.5 dB */
++
++ /* Inputs */
++ {SOUND_MIXER_MIC, 0x0000}, /* mute *//* -34.5dB to +12dB */
++ {SOUND_MIXER_LINE, 0x4b4b}, /* 0 dB *//* -34.5dB to +12dB */
++
++ /* Inputs that are not connected. */
++ {SOUND_MIXER_SPEAKER, 0x0000}, /* mute *//* -45dB to 0dB */
++ {SOUND_MIXER_PHONEIN, 0x0000}, /* mute *//* -34.5dB to +12dB */
++ {SOUND_MIXER_CD, 0x0000}, /* mute *//* -34.5dB to +12dB */
++ {SOUND_MIXER_VIDEO, 0x0000}, /* mute *//* -34.5dB to +12dB */
++ {SOUND_MIXER_LINE1, 0x0000}, /* mute *//* -34.5dB to +12dB */
++
++ {-1, 0} /* last entry */
++};
++
++static unsigned int guiOSS_Volume[SOUND_MIXER_NRDEVICES];
++
++/* table to scale scale from OSS mixer value to AC97 mixer register value */
++struct ac97_mixer_hw_t {
++ unsigned int offset;
++ int scale;
++};
++
++static struct ac97_mixer_hw_t ac97_hw[SOUND_MIXER_NRDEVICES] = {
++ [SOUND_MIXER_VOLUME] = {AC97_02_MASTER_VOL, 64},
++ [SOUND_MIXER_BASS] = {0, 0},
++ [SOUND_MIXER_TREBLE] = {0, 0},
++ [SOUND_MIXER_SYNTH] = {0, 0},
++ [SOUND_MIXER_PCM] = {AC97_18_PCM_OUT_VOL, 32},
++ [SOUND_MIXER_SPEAKER] = {AC97_0A_PC_BEEP_VOL, 32},
++ [SOUND_MIXER_LINE] = {AC97_10_LINE_IN_VOL, 32},
++ [SOUND_MIXER_MIC] = {AC97_0E_MIC_VOL, 32},
++ [SOUND_MIXER_CD] = {AC97_12_CD_VOL, 32},
++ [SOUND_MIXER_IMIX] = {0, 0},
++ [SOUND_MIXER_ALTPCM] = {AC97_04_HEADPHONE_VOL, 64},
++ [SOUND_MIXER_RECLEV] = {0, 0},
++ [SOUND_MIXER_IGAIN] = {AC97_1C_RECORD_GAIN, 16},
++ [SOUND_MIXER_OGAIN] = {0, 0},
++ [SOUND_MIXER_LINE1] = {AC97_16_AUX_VOL, 32},
++ [SOUND_MIXER_LINE2] = {0, 0},
++ [SOUND_MIXER_LINE3] = {0, 0},
++ [SOUND_MIXER_DIGITAL1] = {0, 0},
++ [SOUND_MIXER_DIGITAL2] = {0, 0},
++ [SOUND_MIXER_DIGITAL3] = {0, 0},
++ [SOUND_MIXER_PHONEIN] = {AC97_0C_PHONE_VOL, 32},
++ [SOUND_MIXER_PHONEOUT] = {AC97_06_MONO_VOL, 64},
++ [SOUND_MIXER_VIDEO] = {AC97_14_VIDEO_VOL, 32},
++ [SOUND_MIXER_RADIO] = {0, 0},
++ [SOUND_MIXER_MONITOR] = {0, 0},
++};
++
++/* the following tables allow us to go from OSS <-> ac97 quickly. */
++enum ac97_recsettings {
++ AC97_REC_MIC = 0,
++ AC97_REC_CD,
++ AC97_REC_VIDEO,
++ AC97_REC_AUX,
++ AC97_REC_LINE,
++ AC97_REC_STEREO, /* combination of all enabled outputs.. */
++ AC97_REC_MONO, /*.. or the mono equivalent */
++ AC97_REC_PHONE
++};
++
++static const unsigned int ac97_rm2oss[] = {
++ [AC97_REC_MIC] = SOUND_MIXER_MIC,
++ [AC97_REC_CD] = SOUND_MIXER_CD,
++ [AC97_REC_VIDEO] = SOUND_MIXER_VIDEO,
++ [AC97_REC_AUX] = SOUND_MIXER_LINE1,
++ [AC97_REC_LINE] = SOUND_MIXER_LINE,
++ [AC97_REC_STEREO] = SOUND_MIXER_IGAIN,
++ [AC97_REC_PHONE] = SOUND_MIXER_PHONEIN
++};
++
++/* indexed by bit position */
++static const unsigned int ac97_oss_rm[] = {
++ [SOUND_MIXER_MIC] = AC97_REC_MIC,
++ [SOUND_MIXER_CD] = AC97_REC_CD,
++ [SOUND_MIXER_VIDEO] = AC97_REC_VIDEO,
++ [SOUND_MIXER_LINE1] = AC97_REC_AUX,
++ [SOUND_MIXER_LINE] = AC97_REC_LINE,
++ [SOUND_MIXER_IGAIN] = AC97_REC_STEREO,
++ [SOUND_MIXER_PHONEIN] = AC97_REC_PHONE
++};
++
++static struct audio_stream_t ac97_output_stream0 = {
++ audio_num_channels:EP93XX_DEFAULT_NUM_CHANNELS,
++ audio_format:EP93XX_DEFAULT_FORMAT,
++ audio_stream_bitwidth:EP93XX_DEFAULT_BIT_WIDTH,
++ devicename:"Ac97_out",
++ dmachannel:{DMATx_AAC1, UNDEF, UNDEF},
++ sample_rate:0,
++ hw_bit_width:16,
++ bCompactMode:1,
++};
++
++static struct audio_stream_t ac97_input_stream0 = {
++ audio_num_channels:EP93XX_DEFAULT_NUM_CHANNELS,
++ audio_format:EP93XX_DEFAULT_FORMAT,
++ audio_stream_bitwidth:EP93XX_DEFAULT_BIT_WIDTH,
++ devicename:"Ac97_in",
++ dmachannel:{DMARx_AAC1, UNDEF, UNDEF},
++ sample_rate:0,
++ hw_bit_width:16,
++ bCompactMode:1,
++};
++
++static struct audio_hw_t ep93xx_ac97_hw = {
++ hw_enable:ep93xx_audio_enable,
++ hw_disable:ep93xx_audio_disable,
++ hw_clear_fifo:0,
++ client_ioctl:ep93xx_audio_ioctl,
++
++ set_hw_serial_format:ep93xx_set_hw_format,
++
++ txdmachannels:{DMATx_AAC1, DMATx_AAC2, DMATx_AAC3},
++ rxdmachannels:{DMARx_AAC1, DMARx_AAC2, DMARx_AAC3},
++
++ MaxTxDmaChannels:3,
++ MaxRxDmaChannels:3,
++
++ modcnt:0,
++};
++
++static struct audio_state_t ac97_audio_state0 = {
++ output_stream:&ac97_output_stream0,
++ input_stream:&ac97_input_stream0,
++ // KERNEL2.4 deleted internal sema intialisier, do it in function
++ hw:&ep93xx_ac97_hw,
++ wr_ref:0,
++ rd_ref:0,
++};
++
++/*
++ * peek
++ *
++ * Reads an AC97 codec register. Returns -1 if there was an error.
++ */
++static int peek(unsigned int uiAddress)
++{
++ unsigned int uiAC97RGIS, uiTemp;
++
++ if (!ac_link_enabled) {
++ DPRINTK
++ ("ep93xx ac97 peek: attempt to peek before enabling ac-link.\n");
++ return -1;
++ }
++
++ /*
++ * Check to make sure that the address is aligned on a word boundary
++ * and is 7E or less.
++ */
++ if (((uiAddress & 0x1) != 0) || (uiAddress > 0x007e)) {
++ return -1;
++ }
++
++ /*
++ * How it is supposed to work is:
++ * - The ac97 controller sends out a read addr in slot 1.
++ * - In the next frame, the codec will echo that address back in slot 1
++ * and send the data in slot 2. SLOT2RXVALID will be set to 1.
++ *
++ * Read until SLOT2RXVALID goes to 1. Reading the data in AC97S2DATA
++ * clears SLOT2RXVALID.
++ */
++
++ /*
++ * First, delay one frame in case of back to back peeks/pokes.
++ */
++ mdelay(1);
++
++ /*
++ * Write the address to AC97S1DATA, delay 1 frame, read the flags.
++ */
++ outl(uiAddress, AC97S1DATA);
++ uiTemp = inl(AC97GCR); /* read to push write out the wrapper */
++
++ udelay(21 * 4);
++ uiAC97RGIS = inl(AC97RGIS);
++
++ /*
++ * Return error if we timed out.
++ */
++ if (((uiAC97RGIS & AC97RGIS_SLOT1TXCOMPLETE) == 0) &&
++ ((uiAC97RGIS & AC97RGIS_SLOT2RXVALID) == 0)) {
++ DPRINTK("ep93xx-ac97 - peek failed reading reg 0x%02x.\n",
++ uiAddress);
++ return -1;
++ }
++
++ return (inl(AC97S2DATA) & 0x000fffff);
++}
++
++/*
++ * poke
++ *
++ * Writes an AC97 codec Register. Return -1 if error.
++ */
++static int poke(unsigned int uiAddress, unsigned int uiValue)
++{
++ unsigned int uiAC97RGIS, uiTemp;
++
++ if (!ac_link_enabled) {
++ DPRINTK
++ ("ep93xx ac97 poke: attempt to poke before enabling ac-link.\n");
++ return -1;
++ }
++
++ /*
++ * Check to make sure that the address is align on a word boundary and
++ * is 7E or less. And that the value is a 16 bit value.
++ */
++ if (((uiAddress & 0x1) != 0) || (uiAddress > 0x007e)) {
++ return -1;
++ }
++
++ /*
++ * First, delay one frame in case of back to back peeks/pokes.
++ */
++ mdelay(1);
++
++ /*
++ * Write the data to AC97S2DATA, then the address to AC97S1DATA.
++ */
++ outl(uiValue, AC97S2DATA);
++ outl(uiAddress, AC97S1DATA);
++ uiTemp = inl(AC97GCR); /* read to push writes out the wrapper */
++
++ /*
++ * Wait for the tx to complete, get status.
++ */
++ udelay(42);
++ uiAC97RGIS = inl(AC97RGIS);
++
++ /*
++ * Return error if we timed out.
++ */
++ if (!(inl(AC97RGIS) & AC97RGIS_SLOT1TXCOMPLETE)) {
++ DPRINTK
++ ("ep93xx-ac97: poke failed writing reg 0x%02x value 0x%02x.\n",
++ uiAddress, uiValue);
++ return -1;
++ }
++
++ return 0;
++}
++
++/*
++ * When we get to the multichannel case the pre-fill and enable code
++ * will go to the dma driver's start routine.
++ */
++static void ep93xx_audio_enable(struct audio_stream_t *stream)
++{
++ unsigned int uiTemp;
++
++ DPRINTK("ep93xx_audio_enable\n");
++
++ /*
++ * Enable the rx or tx channel
++ */
++ if (stream->dmachannel[0] == DMATx_AAC1) {
++ uiTemp = inl(AC97TXCR1);
++ outl((uiTemp | AC97TXCR_TEN), AC97TXCR1);
++ uiTemp = inl(AC97TXCR1);
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++ outl(inl(AC97IE1) | AC97ISR_TIS, AC97IE1);
++#endif
++ }
++
++ if (stream->dmachannel[0] == DMARx_AAC1) {
++ uiTemp = inl(AC97RXCR1);
++ outl((uiTemp | AC97RXCR_REN), AC97RXCR1);
++ uiTemp = inl(AC97RXCR1);
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++ outl(inl(AC97IE1) | AC97ISR_RIS, AC97IE1);
++#endif
++ }
++ //DPRINTK("ep93xx_audio_enable - EXIT\n");
++}
++
++static void ep93xx_audio_disable(struct audio_stream_t *stream)
++{
++ unsigned int uiControl, uiStatus;
++
++ DPRINTK("ep93xx_audio_disable\n");
++
++ /*
++ * Disable the rx or tx channel
++ */
++ if (stream->dmachannel[0] == DMATx_AAC1) {
++ uiControl = inl(AC97TXCR1);
++ if (uiControl & AC97TXCR_TEN) {
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++ outl(inl(AC97IE1) & ~AC97ISR_TIS, AC97IE1);
++#else
++ /*
++ * Wait for fifo to empty. We've shut down the dma
++ * so that should happen soon.
++ */
++ do {
++ uiStatus = inl(AC97SR1);
++ } while (((uiStatus & 0x82) == 0));
++ //} while( ((uiStatus & 0x20)!=0) ;&&
++ //((uiStatus & 0x82)==0) );
++#endif
++
++ outl((uiControl & ~AC97TXCR_TEN), AC97TXCR1);
++ uiControl = inl(AC97TXCR1);
++ }
++ }
++
++ if (stream->dmachannel[0] == DMARx_AAC1) {
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++ outl(inl(AC97IE1) & ~AC97ISR_RIS, AC97IE1);
++#endif
++ uiControl = inl(AC97RXCR1);
++ outl((uiControl & ~AC97RXCR_REN), AC97RXCR1);
++ uiControl = inl(AC97RXCR1);
++ }
++ //DPRINTK("ep93xx_audio_disable - EXIT\n");
++}
++
++/*
++ * ep93xx_setup_src
++ *
++ * Once the ac-link is up and all is good, we want to set the codec to a
++ * usable mode.
++ */
++static void ep93xx_setup_src(void)
++{
++ int iTemp;
++
++ /*
++ * Set the VRA bit to enable the SRC.
++ */
++ iTemp = peek(AC97_2A_EXT_AUDIO_POWER);
++ poke(AC97_2A_EXT_AUDIO_POWER, (iTemp | 0x1));
++
++ /*
++ * Set the DSRC/ASRC bits to enable the variable rate SRC.
++ */
++ iTemp = peek(AC97_60_MISC_CRYSTAL_CONTROL);
++ poke(AC97_60_MISC_CRYSTAL_CONTROL, (iTemp | 0x0300));
++}
++
++/*
++ * ep93xx_set_samplerate
++ *
++ * lFrequency - Sample Rate in Hz
++ * bTx - 1 to set Tx sample rate
++ * bRx - 1 to set Rx sample rate
++ */
++static void ep93xx_set_samplerate(struct audio_stream_t *stream,
++ long lSampleRate)
++{
++#ifndef CONFIG_SOUND_EP93XX_AC97_CODEC_CS4297
++ unsigned short usDivider, usPhase;
++
++ DPRINTK("ep93xx_set_samplerate - Fs = %d\n", (int)lSampleRate);
++
++ if ((lSampleRate < 7200) || (lSampleRate > 48000)) {
++ DPRINTK("ep93xx_set_samplerate - invalid Fs = %d\n",
++ (int)lSampleRate);
++ return;
++ }
++
++ /*
++ * Calculate divider and phase increment.
++ *
++ * divider = round( 0x1770000 / lSampleRate )
++ * Note that usually rounding is done by adding 0.5 to a floating
++ * value and then truncating. To do this without using floating
++ * point, I multiply the fraction by two, do the division, then add one,
++ * then divide the whole by 2 and then truncate.
++ * Same effect, no floating point math.
++ *
++ * Ph incr = trunc( (0x1000000 / usDivider) + 1 )
++ */
++
++ usDivider = (unsigned short)(((2 * 0x1770000 / lSampleRate) + 1) / 2);
++
++ usPhase = (0x1000000 / usDivider) + 1;
++
++ /*
++ * Write them in the registers. Spec says divider must be
++ * written after phase incr.
++ */
++ if (stream->dmachannel[0] == DMATx_AAC1) {
++ poke(AC97_2C_PCM_FRONT_DAC_RATE, usDivider);
++ poke(AC97_64_DAC_SRC_PHASE_INCR, usPhase);
++ }
++
++ if (stream->dmachannel[0] == DMARx_AAC1) {
++
++ poke(AC97_32_PCM_LR_ADC_RATE, usDivider);
++ poke(AC97_66_ADC_SRC_PHASE_INCR, usPhase);
++ }
++
++ DPRINTK("ep93xx_set_samplerate - phase = %d, divider = %d\n",
++ (unsigned int)usPhase, (unsigned int)usDivider);
++
++ /*
++ * We sorta should report the actual samplerate back to the calling
++ * application. But some applications freak out if they don't get
++ * exactly what they asked for. So we fudge and tell them what
++ * they want to hear.
++ */
++ stream->sample_rate = lSampleRate;
++
++ DPRINTK("ep93xx_set_samplerate - EXIT\n");
++#else
++ stream->sample_rate = AUDIO_SAMPLE_RATE_DEFAULT;
++#endif
++}
++
++/*
++ * ep93xx_set_hw_format
++ *
++ * Sets up whether the controller is expecting 20 bit data in 32 bit words
++ * or 16 bit data compacted to have a stereo sample in each 32 bit word.
++ */
++static void ep93xx_set_hw_format(struct audio_stream_t *stream, long format)
++{
++ int bCompactMode, uiTemp, iWidth;
++ unsigned long ulRegValue;
++
++ switch (format) {
++ /*
++ * Here's all the <=16 bit formats. We can squeeze both L and R
++ * into one 32 bit sample so use compact mode.
++ */
++ case AFMT_U8:
++ case AFMT_S8:
++ case AFMT_S16_LE:
++ case AFMT_U16_LE:
++ bCompactMode = 1;
++ ulRegValue = 0x00008018;
++ iWidth = 16;
++ break;
++
++ /*
++ * Add any other >16 bit formats here...
++ */
++ case AFMT_S32_BLOCKED:
++ default:
++ bCompactMode = 0;
++ ulRegValue = 0x00004018;
++ iWidth = 20;
++ break;
++ }
++
++ if (stream->dmachannel[0] == DMARx_AAC1) {
++ uiTemp = inl(AC97RXCR1);
++ if (ulRegValue != uiTemp) {
++ outl(ulRegValue, AC97RXCR1);
++ uiTemp = inl(AC97RXCR1);
++ }
++ stream->hw_bit_width = iWidth;
++ stream->bCompactMode = bCompactMode;
++ }
++
++ if (stream->dmachannel[0] == DMATx_AAC1) {
++ uiTemp = inl(AC97TXCR1);
++ if (ulRegValue != uiTemp) {
++ outl(ulRegValue, AC97TXCR1);
++ uiTemp = inl(AC97TXCR1);
++ }
++ stream->hw_bit_width = iWidth;
++ stream->bCompactMode = bCompactMode;
++ }
++
++}
++
++/*
++ * ep93xx_init_ac97_controller
++ *
++ * This routine sets up the Ac'97 Controller.
++ */
++static void ep93xx_init_ac97_controller(void)
++{
++ unsigned int uiDEVCFG, uiTemp;
++
++ DPRINTK("ep93xx_init_ac97_controller - enter\n");
++
++ /*
++ * Configure the multiplexed Ac'97 pins to be Ac97 not I2s.
++ * Configure the EGPIO4 and EGPIO6 to be GPIOS, not to be
++ * SDOUT's for the second and third I2S controller channels.
++ */
++ uiDEVCFG = inl(SYSCON_DEVCFG);
++
++ uiDEVCFG &= ~(SYSCON_DEVCFG_I2SonAC97 |
++ SYSCON_DEVCFG_A1onG | SYSCON_DEVCFG_A2onG);
++
++ SysconSetLocked(SYSCON_DEVCFG, uiDEVCFG);
++
++ /*
++ * Disable the AC97 controller internal loopback.
++ * Disable Override codec ready.
++ */
++ outl(0, AC97GCR);
++
++ /*
++ * Enable the AC97 Link.
++ */
++ uiTemp = inl(AC97GCR);
++ outl((uiTemp | AC97GSR_IFE), AC97GCR);
++ uiTemp = inl(AC97GCR); /* read to push write out the wrapper */
++
++ /*
++ * Set the TIMEDRESET bit. Will cause a > 1uSec reset of the ac-link.
++ * This bit is self resetting.
++ */
++ outl(AC97RESET_TIMEDRESET, AC97RESET);
++ uiTemp = inl(AC97GCR); /* read to push write out the wrapper */
++
++ /*
++ * Delay briefly, but let's not hog the processor.
++ */
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(5); /* 50 mSec */
++
++ /*
++ * Read the AC97 status register to see if we've seen a CODECREADY
++ * signal from the AC97 codec.
++ */
++ if (!(inl(AC97RGIS) & AC97RGIS_CODECREADY)) {
++ DPRINTK("ep93xx-ac97 - FAIL: CODECREADY still low!\n");
++ return;
++ }
++
++ /*
++ * Delay for a second, not hogging the processor
++ */
++ set_current_state(TASK_INTERRUPTIBLE);
++ schedule_timeout(HZ); /* 1 Sec */
++
++ /*
++ * Now the Ac-link is up. We can read and write codec registers.
++ */
++ ac_link_enabled = 1;
++
++ /*
++ * Set up the rx and tx channels
++ * Set the CM bit, data size=16 bits, enable tx slots 3 & 4.
++ */
++ ep93xx_set_hw_format(&ac97_output_stream0, EP93XX_DEFAULT_FORMAT);
++ ep93xx_set_hw_format(&ac97_input_stream0, EP93XX_DEFAULT_FORMAT);
++
++ DPRINTK("ep93xx-ac97 -- AC97RXCR1: %08x\n", inl(AC97RXCR1));
++ DPRINTK("ep93xx-ac97 -- AC97TXCR1: %08x\n", inl(AC97TXCR1));
++
++ DPRINTK("ep93xx_init_ac97_controller - EXIT - success\n");
++
++}
++
++/*
++ * ep93xx_init_ac97_codec
++ *
++ * Program up the external Ac97 codec.
++ *
++ */
++static void ep93xx_init_ac97_codec(void)
++{
++ DPRINTK("ep93xx_init_ac97_codec - enter\n");
++
++ ep93xx_setup_src();
++ ep93xx_set_samplerate(&ac97_output_stream0, AUDIO_SAMPLE_RATE_DEFAULT);
++ ep93xx_set_samplerate(&ac97_input_stream0, AUDIO_SAMPLE_RATE_DEFAULT);
++ ep93xx_init_mixer();
++
++ DPRINTK("ep93xx_init_ac97_codec - EXIT\n");
++
++}
++
++#ifdef DEBUG
++static void ep93xx_dump_ac97_regs(void)
++{
++ int i;
++ unsigned int reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7;
++
++ DPRINTK("---------------------------------------------\n");
++ DPRINTK(" : 0 2 4 6 8 A C E\n");
++
++ for (i = 0; i < 0x80; i += 0x10) {
++ reg0 = 0xffff & (unsigned int)peek(i);
++ reg1 = 0xffff & (unsigned int)peek(i + 0x2);
++ reg2 = 0xffff & (unsigned int)peek(i + 0x4);
++ reg3 = 0xffff & (unsigned int)peek(i + 0x6);
++ reg4 = 0xffff & (unsigned int)peek(i + 0x8);
++ reg5 = 0xffff & (unsigned int)peek(i + 0xa);
++ reg6 = 0xffff & (unsigned int)peek(i + 0xc);
++ reg7 = 0xffff & (unsigned int)peek(i + 0xe);
++
++ DPRINTK(" %02x : %04x %04x %04x %04x %04x %04x %04x %04x\n",
++ i, reg0, reg1, reg2, reg3, reg4, reg5, reg6, reg7);
++ }
++}
++#endif
++
++static void ep93xx_set_volume(unsigned int oss_channel, unsigned int oss_val) {
++ unsigned int left, right;
++ u16 val = 0;
++ struct ac97_mixer_hw_t *mh = &ac97_hw[oss_channel];
++
++ if (!mh->scale) {
++ DPRINTK
++ ("ep93xx-ac97.c: ep93xx_set_volume - not a valid OSS channel\n");
++ return;
++ }
++
++ /* cleanse input a little */
++ right = ((oss_val >> 8) & 0xff);
++ left = (oss_val & 0xff);
++
++ if (right > 100)
++ right = 100;
++ if (left > 100)
++ left = 100;
++
++ DPRINTK("ac97_codec: wrote OSS channel#%2d (ac97 reg 0x%02x), "
++ "l:%2d, r:%2d:", oss_channel, mh->offset, left, right);
++
++ if (AC97_STEREO_MASK & (1 << oss_channel)) {
++ /* stereo mixers */
++ if (oss_channel == SOUND_MIXER_IGAIN) {
++ right = ((100 - right) * (mh->scale - 1)) / 100;
++ left = ((100 - left) * (mh->scale - 1)) / 100;
++ if (right >= mh->scale)
++ right = mh->scale - 1;
++ if (left >= mh->scale)
++ left = mh->scale - 1;
++ right = (mh->scale - 1) - right;
++ left = (mh->scale - 1) - left;
++ val = (left << 8) | right;
++ } else {
++ if (left == 0 && right == 0) {
++ val = 0x8000;
++ } else {
++ right = ((100 - right) * (mh->scale - 1)) / 100;
++ left = ((100 - left) * (mh->scale - 1)) / 100;
++ if (right >= mh->scale)
++ right = mh->scale - 1;
++ if (left >= mh->scale)
++ left = mh->scale - 1;
++ val = (left << 8) | right;
++ }
++ }
++ } else if (left == 0) {
++ val = 0x8000;
++ } else if ((oss_channel == SOUND_MIXER_SPEAKER) ||
++ (oss_channel == SOUND_MIXER_PHONEIN) ||
++ (oss_channel == SOUND_MIXER_PHONEOUT)) {
++ left = ((100 - left) * (mh->scale - 1)) / 100;
++ if (left >= mh->scale)
++ left = mh->scale - 1;
++ val = left;
++ } else if (oss_channel == SOUND_MIXER_MIC) {
++ val = peek(mh->offset) & ~0x801f;
++ left = ((100 - left) * (mh->scale - 1)) / 100;
++ if (left >= mh->scale)
++ left = mh->scale - 1;
++ val |= left;
++ }
++ /*
++ * For bass and treble, the low bit is optional. Masking it
++ * lets us avoid the 0xf 'bypass'.
++ * Do a read, modify, write as we have two contols in one reg.
++ */
++ else if (oss_channel == SOUND_MIXER_BASS) {
++ val = peek(mh->offset) & ~0x0f00;
++ left = ((100 - left) * (mh->scale - 1)) / 100;
++ if (left >= mh->scale)
++ left = mh->scale - 1;
++ val |= (left << 8) & 0x0e00;
++ } else if (oss_channel == SOUND_MIXER_TREBLE) {
++ val = peek(mh->offset) & ~0x000f;
++ left = ((100 - left) * (mh->scale - 1)) / 100;
++ if (left >= mh->scale)
++ left = mh->scale - 1;
++ val |= left & 0x000e;
++ }
++
++ DPRINTK(" 0x%04x", val);
++
++ poke(mh->offset, val);
++
++#ifdef DEBUG
++ val = peek(mh->offset);
++ DPRINTK(" (read back 0x%04x)\n", val);
++#endif
++
++ guiOSS_Volume[oss_channel] = oss_val;
++}
++
++static void ep93xx_init_mixer(void)
++{
++ u16 cap;
++ int i;
++
++ /* mixer masks */
++ codec_supported_mixers = AC97_SUPPORTED_MASK;
++
++ cap = peek(AC97_00_RESET);
++ if (!(cap & 0x04)) {
++ codec_supported_mixers &=
++ ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE);
++ }
++ if (!(cap & 0x10)) {
++ codec_supported_mixers &= ~SOUND_MASK_ALTPCM;
++ }
++
++ /*
++ * Detect bit resolution of output volume controls by writing to the
++ * 6th bit (not unmuting yet)
++ */
++ poke(AC97_02_MASTER_VOL, 0xa020);
++ if (peek(AC97_02_MASTER_VOL) != 0xa020) {
++ ac97_hw[SOUND_MIXER_VOLUME].scale = 32;
++ }
++
++ poke(AC97_04_HEADPHONE_VOL, 0xa020);
++ if (peek(AC97_04_HEADPHONE_VOL) != 0xa020) {
++ ac97_hw[AC97_04_HEADPHONE_VOL].scale = 32;
++ }
++
++ poke(AC97_06_MONO_VOL, 0x8020);
++ if (peek(AC97_06_MONO_VOL) != 0x8020) {
++ ac97_hw[AC97_06_MONO_VOL].scale = 32;
++ }
++
++ /* initialize mixer channel volumes */
++ for (i = 0;
++ (i < SOUND_MIXER_NRDEVICES) && (mixer_defaults[i].mixer != -1);
++ i++) {
++ if (!supported_mixer(mixer_defaults[i].mixer)) {
++ continue;
++ }
++
++ ep93xx_set_volume(mixer_defaults[i].mixer,
++ mixer_defaults[i].value);
++ }
++
++}
++
++/*
++ * ac97_recmask_io
++ *
++ * Read or write the record source.
++ */
++static int ep93xx_read_recsource(void)
++{
++ unsigned int val;
++
++ /* read it from the card */
++ val = peek(AC97_1A_RECORD_SELECT);
++
++ DPRINTK("ac97_codec: ac97 recmask to set to 0x%04x\n", val);
++
++ return (1 << ac97_rm2oss[val & 0x07]);
++}
++
++static int ep93xx_set_recsource(int mask)
++{
++ unsigned int val;
++
++ /* Arg contains a bit for each recording source */
++ if (mask == 0) {
++ return 0;
++ }
++
++ mask &= AC97_RECORD_MASK;
++
++ if (mask == 0) {
++ return -EINVAL;
++ }
++
++ /*
++ * May have more than one bit set. So clear out currently selected
++ * record source value first (AC97 supports only 1 input)
++ */
++ val = (1 << ac97_rm2oss[peek(AC97_1A_RECORD_SELECT) & 0x07]);
++ if (mask != val)
++ mask &= ~val;
++
++ val = ffs(mask);
++ val = ac97_oss_rm[val - 1];
++ val |= val << 8; /* set both channels */
++
++ DPRINTK("ac97_codec: setting ac97 recmask to 0x%04x\n", val);
++
++ poke(AC97_1A_RECORD_SELECT, val);
++
++ return 0;
++}
++
++static int ep93xx_mixer_open(struct inode *inode, struct file *file)
++{
++ file->private_data = &ep93xx_ac97_hw;
++ return 0;
++}
++
++static int ep93xx_mixer_release(struct inode *inode, struct file *file)
++{
++ return 0;
++}
++
++static int
++ep93xx_mixer_ioctl(struct inode *inode, struct file *file, uint cmd, ulong arg)
++{
++ int val, nr;
++
++ struct audio_hw_t *hw = (struct audio_hw_t *)file->private_data;
++
++ DPRINTK("ep93xx_mixer_ioctl - enter. IOC_TYPE is %c \n",
++ _IOC_TYPE(cmd));
++
++ if (cmd == SOUND_MIXER_INFO) {
++ mixer_info info;
++ strncpy(info.id, "CS4202", sizeof(info.id));
++ strncpy(info.name, "Cirrus CS4202", sizeof(info.name));
++ info.modify_counter = hw->modcnt;
++ if (copy_to_user((void *)arg, &info, sizeof(info))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++ if (cmd == SOUND_OLD_MIXER_INFO) {
++ _old_mixer_info info;
++ strncpy(info.id, "CS4202", sizeof(info.id));
++ strncpy(info.name, "Cirrus CS4202", sizeof(info.name));
++ if (copy_to_user((void *)arg, &info, sizeof(info))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++
++ if ((_IOC_TYPE(cmd) != 'M') || (_SIOC_SIZE(cmd) != sizeof(int)))
++ return -EINVAL;
++
++ if (cmd == OSS_GETVERSION)
++ return put_user(SOUND_VERSION, (int *)arg);
++
++ nr = _IOC_NR(cmd);
++
++ if (_SIOC_DIR(cmd) == _SIOC_READ) {
++ switch (nr) {
++ case SOUND_MIXER_RECSRC:
++ /* Read the current record source */
++ val = ep93xx_read_recsource();
++ break;
++
++ case SOUND_MIXER_DEVMASK:
++ /* give them the supported mixers */
++ val = codec_supported_mixers;
++ break;
++
++ case SOUND_MIXER_RECMASK:
++ /* Arg contains a bit for each supported recording source */
++ val = AC97_RECORD_MASK;
++ break;
++
++ case SOUND_MIXER_STEREODEVS:
++ /* Mixer channels supporting stereo */
++ val = AC97_STEREO_MASK;
++ break;
++
++ case SOUND_MIXER_CAPS:
++ val = SOUND_CAP_EXCL_INPUT;
++ break;
++
++ default:
++ if (!supported_mixer(nr))
++ return -EINVAL;
++
++ val = guiOSS_Volume[nr];
++ break;
++
++ } /* switch */
++
++ return put_user(val, (int *)arg);
++ }
++
++ if (_SIOC_DIR(cmd) == (_SIOC_WRITE | _SIOC_READ)) {
++ if (get_user(val, (int *)arg))
++ return -EFAULT;
++
++ switch (nr) {
++ case SOUND_MIXER_RECSRC:
++ return ep93xx_set_recsource(val);
++
++ default:
++ if (!supported_mixer(nr))
++ return -EINVAL;
++
++ ep93xx_set_volume(nr, val);
++ hw->modcnt++;
++ return 0;
++ }
++ }
++
++ return -EINVAL;
++}
++
++static struct file_operations ep93xx_mixer_fops = {
++ owner:THIS_MODULE,
++ llseek:no_llseek,
++ ioctl:ep93xx_mixer_ioctl,
++ open:ep93xx_mixer_open,
++ release:ep93xx_mixer_release,
++};
++
++/*
++ * Audio interface
++ */
++static void ep93xx_audio_init(void *dummy)
++{
++ DPRINTK("ep93xx_audio_init - enter\n");
++
++ /*
++ * Init the controller, enable the ac-link.
++ * Initialize the codec.
++ */
++ ep93xx_init_ac97_controller();
++ ep93xx_init_ac97_codec();
++
++#ifdef DEBUG
++ ep93xx_dump_ac97_regs();
++#endif
++
++ DPRINTK("ep93xx_audio_init - EXIT\n");
++}
++
++static int ep93xx_audio_ioctl(struct inode *inode, struct file *file,
++ uint cmd, ulong arg)
++{
++ struct audio_state_t *state =
++ (struct audio_state_t *)file->private_data;
++ struct audio_stream_t *os = state->output_stream;
++ struct audio_stream_t *is = state->input_stream;
++ long val;
++ int ret = 0;
++
++ /*
++ * These are platform dependent ioctls which are not handled by the
++ * generic ep93xx-audio module.
++ */
++ switch (cmd) {
++ case SNDCTL_DSP_SPEED:
++
++ DPRINTK("ep93xx_audio_ioctl - SNDCTL_DSP_SPEED\n");
++
++ if (get_user(val, (int *)arg)) {
++ return -EFAULT;
++ }
++
++ if ((file->f_mode & FMODE_WRITE) && (val != os->sample_rate)) {
++ ep93xx_set_samplerate(os, val);
++ }
++ if ((file->f_mode & FMODE_READ) && (val != is->sample_rate)) {
++ ep93xx_set_samplerate(is, val);
++ }
++
++ return put_user(val, (long *)arg);
++
++ case SOUND_PCM_READ_RATE:
++ DPRINTK("ep93xx_audio_ioctl - SOUND_PCM_READ_RATE\n");
++ if (file->f_mode & FMODE_WRITE) {
++ return put_user(os->sample_rate, (long *)arg);
++ }
++ return put_user(is->sample_rate, (long *)arg);
++
++ default:
++ DPRINTK("ep93xx_audio_ioctl-->ep93xx_mixer_ioctl\n");
++ /* Maybe this is meant for the mixer (As per OSS Docs) */
++ return ep93xx_mixer_ioctl(inode, file, cmd, arg);
++ }
++
++ return ret;
++}
++
++static int ep93xx_audio_open(struct inode *inode, struct file *file)
++{
++ DPRINTK("ep93xx_audio_open\n");
++ return ep93xx_audio_attach(inode, file, &ac97_audio_state0);
++}
++
++/*
++ * Missing fields of this structure will be patched with the call
++ * to ep93xx_audio_attach().
++ */
++static struct file_operations ep93xx_audio_fops = {
++ open:ep93xx_audio_open,
++ owner:THIS_MODULE
++};
++
++static int audio_dev_id, mixer_dev_id;
++
++static int __init ep93xx_ac97_init(void)
++{
++ DPRINTK("ep93xx_ac97_init - enter\n");
++
++ // KERNEL2.4
++ sema_init(&ac97_audio_state0.sem, 1);
++
++ /*
++ * Enable audio early on, give the DAC time to come up.
++ */
++ ep93xx_audio_init(0);
++
++ /*
++ * Register devices using sound_core.c's devfs stuff
++ */
++ audio_dev_id = register_sound_dsp(&ep93xx_audio_fops, -1);
++ if (audio_dev_id < 0) {
++ DPRINTK
++ (" ep93xx_ac97_init: register_sound_dsp failed for dsp.\n");
++ return -ENODEV;
++ }
++
++ mixer_dev_id = register_sound_mixer(&ep93xx_mixer_fops, -1);
++ if (mixer_dev_id < 0) {
++ DPRINTK
++ (" ep93xx_ac97_init: register_sound_dsp failed for mixer.\n");
++ return -ENODEV;
++ }
++
++ printk(KERN_INFO "EP93xx Ac97 audio support initialized.\n");
++ return 0;
++}
++
++static void __exit ep93xx_ac97_exit(void)
++{
++ unregister_sound_dsp(audio_dev_id);
++ unregister_sound_mixer(mixer_dev_id);
++}
++
++module_init(ep93xx_ac97_init);
++module_exit(ep93xx_ac97_exit);
++
++MODULE_DESCRIPTION("Audio driver for the Cirrus EP93xx Ac97 controller.");
++MODULE_LICENSE("GPL");
++/* EXPORT_NO_SYMBOLS; */
+diff --git a/sound/oss/ep93xx-audio.c b/sound/oss/ep93xx-audio.c
+new file mode 100644
+index 0000000..7e00d6d
+--- /dev/null
++++ b/sound/oss/ep93xx-audio.c
+@@ -0,0 +1,3821 @@
++/*
++ * ep93xx-audio.c
++ *
++ * Common audio handling for the Cirrus EP93xx processor.
++ *
++ * Copyright (c) 2003 Cirrus Logic Corp.
++ * Copyright (C) 2000, 2001 Nicolas Pitre <nico@cam.org>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License.
++ *
++ * Taken from sa1100-audio.c
++ *
++ * This module handles the generic buffering/DMA/mmap audio interface for
++ * codecs connected to the EP93xx chip. All features depending on specific
++ * hardware implementations like supported audio formats or samplerates are
++ * relegated to separate specific modules.
++ *
++ *
++ * History:
++ *
++ * 2000-05-21 Nicolas Pitre Initial release.
++ *
++ * 2000-06-10 Erik Bunce Add initial poll support.
++ *
++ * 2000-08-22 Nicolas Pitre Removed all DMA stuff. Now using the
++ * generic SA1100 DMA interface.
++ *
++ * 2000-11-30 Nicolas Pitre - Validation of opened instances;
++ * - Power handling at open/release time instead
++ * of driver load/unload;
++ *
++ * 2001-06-03 Nicolas Pitre Made this file a separate module, based on
++ * the former sa1100-uda1341.c driver.
++ *
++ * 2001-07-22 Nicolas Pitre - added mmap() and realtime support
++ * - corrected many details to better comply
++ * with the OSS API
++ *
++ * 2001-10-19 Nicolas Pitre - brought DMA registration processing
++ * into this module for better ressource
++ * management. This also fixes a bug
++ * with the suspend/resume logic.
++ *
++ * 2003-04-04 Adapted for EP93xx I2S/Ac97 audio.
++ *
++ * 2004-04-23 Added support for multiple stereo streams.
++ *
++ * 2005-05-11 Manfred Gruber - Ported this from Cirrus Logic Virgo 1-4-3 release
++ * to Kernel 2.6.11.X
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/types.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/sched.h>
++#include <linux/poll.h>
++#include <linux/pm.h>
++#include <linux/errno.h>
++#include <linux/sound.h>
++#include <linux/soundcard.h>
++#include <linux/sysrq.h>
++#include <linux/delay.h>
++#include <linux/kernel_stat.h>
++#include <asm/arch/dma.h>
++#include <linux/dma-mapping.h>
++
++#include <asm/uaccess.h>
++//#include <asm/fiq.h>
++#include <asm/io.h>
++#include <asm/hardware.h>
++#include <asm/semaphore.h>
++#include <asm/arch/dma.h>
++#include <asm/arch/irqs.h>
++
++#include "ep93xx-audio.h"
++
++#undef DEBUG
++//#define DEBUG 1
++#ifdef DEBUG
++#define DPRINTK( fmt, arg... ) printk( fmt, ##arg )
++#else
++#define DPRINTK( fmt, arg... )
++#endif
++
++/* Mostly just prints what ioctls got called */
++//#define DEBUG 1
++#ifdef DEBUG
++#define DPRINTK_IOCTL( fmt, arg... ) printk( fmt, ##arg )
++#else
++#define DPRINTK_IOCTL( fmt, arg... )
++#endif
++
++/*
++ * Experiencing gaps in your audio? Try upping the AUDIO_NBFRAGS_DEFAULT!
++ * Experiencing memory problems? Try lowering them.
++ * DMA memory space is precious and rare on ARM.
++ *
++ */
++
++//
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++#define AUDIO_NBFRAGS_DEFAULT 31
++#define AUDIO_FRAGSIZE_DEFAULT 65536
++#define AUDIO_NBFRAGS_MAX 31
++#else
++#ifdef CONFIG_SOUND_EP93XX_AC97
++// Values changed from KERNEL2.4
++#define AUDIO_NBFRAGS_DEFAULT 4
++#define AUDIO_FRAGSIZE_DEFAULT 8192 // max is 65536
++#define AUDIO_NBFRAGS_MAX 4
++#else
++#define AUDIO_NBFRAGS_DEFAULT 16
++#define AUDIO_FRAGSIZE_DEFAULT 32768 // max is 65536
++#define AUDIO_NBFRAGS_MAX 16
++#endif
++#endif
++
++/*
++ * NEXT_BUF
++ *
++ * Translates to:
++ * stream->dma_buffer_index++;
++ * stream->dma_buffer_index %= stream->nbfrags;
++ * stream->dma_buffer = stream->buffers + stream->dma_buffer_index;
++ *
++ * So stream->dma_buffer always points to the stream->dma_buffer_index-nth element
++ * of stream->buffers.
++ */
++#define NEXT_BUF(_s_,_b_) { \
++ (_s_)->_b_##_index++; \
++ (_s_)->_b_##_index %= (_s_)->nbfrags; \
++ (_s_)->_b_ = (_s_)->buffers + (_s_)->_b_##_index; }
++
++#define AUDIO_ACTIVE(state) ((state)->rd_ref || (state)->wr_ref)
++
++/* Function prototypes */
++static __inline__ int copy_to_user_with_conversion
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount);
++
++static __inline__ int copy_from_user_with_conversion
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount);
++
++static void audio_dma_start(struct audio_state_t *state,
++ struct audio_stream_t *stream);
++static void audio_dma_pause(struct audio_state_t *state,
++ struct audio_stream_t *stream);
++static void audio_prime_dma(struct audio_state_t *state,
++ struct audio_stream_t *stream);
++
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++#define DMA_ADD_BUFFER pio_add_buffer
++#define DMA_CONFIG pio_config
++#define DMA_FLUSH pio_flush
++#define DMA_FREE pio_free
++#define DMA_GET_POSITION pio_get_position
++#define DMA_PAUSE pio_pause
++#define DMA_REMOVE_BUFFER pio_remove_buffer
++#define DMA_REQUEST pio_request
++#define DMA_START pio_start
++#else
++#define DMA_ADD_BUFFER ep93xx_dma_add_buffer
++#define DMA_CONFIG ep93xx_dma_config
++#define DMA_FLUSH ep93xx_dma_flush
++#define DMA_FREE ep93xx_dma_free
++#define DMA_GET_POSITION ep93xx_dma_get_position
++#define DMA_PAUSE ep93xx_dma_pause
++#define DMA_REMOVE_BUFFER ep93xx_dma_remove_buffer
++#define DMA_REQUEST ep93xx_dma_request
++#define DMA_START ep93xx_dma_start
++#endif
++
++#ifdef CONFIG_SOUND_EP93XX_AUDIO_PIO
++/*
++ * The maximum number of buffers accepted by the PIO interface.
++ */
++#define PIO_MAX_BUFFERS 32
++
++/*
++ * A convenienced macro to advance from one buffer to the next.
++ */
++#define PIO_NEXT(x) (((x) + 1) % PIO_MAX_BUFFERS)
++
++/*
++ * A structure to remember information about a buffer.
++ */
++struct pio_buffer {
++ unsigned int source;
++ unsigned int pos;
++ unsigned int size;
++ int buf_id;
++};
++
++/*
++ * A structure to remember information about a stream.
++ */
++struct pio_stream {
++ int assigned;
++ struct pio_buffer queue[PIO_MAX_BUFFERS];
++ ep93xx_dma_dev_t device;
++ int first;
++ int cur;
++ int last;
++ int bytes;
++ int pause;
++ dma_callback callback;
++ unsigned int user_data;
++};
++
++/*
++ * The twelve streams that we can handle.
++ */
++static struct pio_stream pio_streams[12];
++
++/*
++ * Reference counts for the two interrupt handlers.
++ */
++static int pio_irq_ref_count[2];
++
++/*
++ * The registers that enable the three I2S transmitters.
++ */
++static const unsigned int i2s_txenable[3] = {
++ I2STX0En,
++ I2STX1En,
++ I2STX2En
++};
++
++/*
++ * The flag that indicates a FIFO full condition on the three I2S transmitters.
++ */
++static const unsigned int i2s_txflag[3] = {
++ TX0_FIFO_FULL,
++ TX1_FIFO_FULL,
++ TX2_FIFO_FULL
++};
++
++/*
++ * The register that contains the left channel data for the three I2S
++ * transmitters.
++ */
++static const unsigned int i2s_tx_lft[3] = {
++ I2STX0Lft,
++ I2STX1Lft,
++ I2STX2Lft
++};
++
++/*
++ * The register that contains the right channel data for the three I2S
++ * transmitters.
++ */
++static const unsigned int i2s_tx_rt[3] = {
++ I2STX0Rt,
++ I2STX1Rt,
++ I2STX2Rt
++};
++
++/*
++ * The registers that enable the three I2S receivers.
++ */
++static const unsigned int i2s_rxenable[3] = {
++ I2SRX0En,
++ I2SRX1En,
++ I2SRX2En
++};
++
++/*
++ * The flag that indicates a FIFO empty condition on the three I2S receivers.
++ */
++static const unsigned int i2s_rxflag[3] = {
++ RX0_FIFO_EMPTY,
++ RX1_FIFO_EMPTY,
++ RX2_FIFO_EMPTY
++};
++
++/*
++ * The register that contains the left channel data for the three I2S
++ * receivers.
++ */
++static const unsigned int i2s_rx_lft[3] = {
++ I2SRX0Lft,
++ I2SRX1Lft,
++ I2SRX2Lft
++};
++
++/*
++ * The register that contains the right channel data for the three I2S
++ * receivers.
++ */
++static const unsigned int i2s_rx_rt[3] = {
++ I2SRX0Rt,
++ I2SRX1Rt,
++ I2SRX2Rt
++};
++
++/*
++ * The registers that contain the status for the three AC'97 transceivers.
++ */
++static const unsigned int ac97_status[3] = {
++ AC97SR1,
++ AC97SR2,
++ AC97SR3
++};
++
++/*
++ * The registers that contain the audio data for the three AC'97 transceivers.
++ */
++static const unsigned int ac97_data[3] = {
++ AC97DR1,
++ AC97DR2,
++ AC97DR3
++};
++
++/*
++ * The registers that control the three AC'97 transmitters.
++ */
++static const unsigned int ac97_txctrl[3] = {
++ AC97TXCR1,
++ AC97TXCR2,
++ AC97TXCR3
++};
++
++/*
++ * The registers that control the three AC'97 receivers.
++ */
++static const unsigned int ac97_rxctrl[3] = {
++ AC97RXCR1,
++ AC97RXCR2,
++ AC97RXCR3
++};
++
++/*
++ * The descriptor for our FIQ handler.
++ */
++static struct fiq_handler fh = { NULL, "pio_audio", NULL, NULL };
++
++/*
++ * Stack space for our FIQ handler.
++ */
++static unsigned char fiq_stack[1024];
++
++/*
++ * References to the labels in the inline assembly.
++ */
++extern void i2s_fiq_begin;
++extern void i2s_fiq_end;
++extern void ac97_fiq_begin;
++extern void ac97_fiq_end;
++
++/*
++ * The FIQ handler for I2S audio. This stub is copied into the vector area and
++ * simply calls the I2S interrupt handler.
++ */
++void pio_i2s_fiq_handler(void)
++{
++ __asm__ __volatile__("\n\
++i2s_fiq_begin:\n\
++ stmdb r13!, {r0-r7, lr}\n\
++ ldr r0, =pio_i2s_irq_handler\n\
++ mov lr, pc\n\
++ mov pc, r0\n\
++ ldmia r13!, {r0-r7, lr}\n\
++ subs pc, lr, #4\n\
++ .ltorg\n\
++i2s_fiq_end:");
++}
++
++/*
++ * The FIQ handler for AC'97 audio. This stub is copied into the vector area
++ * and simply calls the AC'97 interrupt handler.
++ */
++void pio_ac97_fiq_handler(void)
++{
++ __asm__ __volatile__("\n\
++ac97_fiq_begin:\n\
++ stmdb r13!, {r0-r7, lr}\n\
++ ldr r0, =pio_ac97_irq_handler\n\
++ mov lr, pc\n\
++ mov pc, r0\n\
++ ldmia r13!, {r0-r7, lr}\n\
++ subs pc, lr, #4\n\
++ .ltorg\n\
++ac97_fiq_end:");
++}
++
++/*
++ * The interrupt handler for I2S audio.
++ */
++static void pio_i2s_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++{
++ struct pio_stream *p;
++ struct pio_buffer *b;
++ int idx;
++
++ /*
++ * Increment the count of interrupts.
++ */
++ kstat.irqs[smp_processor_id()][IRQ_SAI]++;
++
++ /*
++ * Loop through the three transmitters.
++ */
++ for (idx = 0; idx < 3; idx++) {
++ /*
++ * Do nothing if this transmitter is not enabled.
++ */
++ if (!inl(i2s_txenable[idx]))
++ continue;
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[idx];
++
++ /*
++ * Loop while the transmit FIFO is not full.
++ */
++ while (!(inl(I2SGlSts) & i2s_txflag[idx])) {
++ /*
++ * If the stream is not assigned, is paused, or has no
++ * data, then write out silence.
++ */
++ if (!p->assigned || p->pause || (p->cur == p->last)) {
++ outl(0, i2s_tx_lft[idx]);
++ outl(0, i2s_tx_rt[idx]);
++ } else {
++ /*
++ * Get a pointer to the current buffer.
++ */
++ b = &p->queue[p->cur];
++
++ /*
++ * Write out the next sample.
++ */
++ outl(*(unsigned long *)b->source,
++ i2s_tx_lft[idx]);
++ outl(*(unsigned long *)(b->source + 4),
++ i2s_tx_rt[idx]);
++
++ /*
++ * Increment past the next sample.
++ */
++ b->source += 8;
++ b->pos += 8;
++
++ /*
++ * See if the buffer has been consumed.
++ */
++ if (b->pos == b->size) {
++ /*
++ * Increment the count of bytes
++ * transmitted.
++ */
++ p->bytes += b->size;
++
++ /*
++ * Go to the next buffer.
++ */
++ p->cur = PIO_NEXT(p->cur);
++
++ /*
++ * Call the callback if there is one.
++ */
++ if (p->callback)
++ p->callback(NFB, p->device,
++ p->user_data);
++ }
++ }
++ }
++ }
++
++ /*
++ * Loop through the three receivers.
++ */
++ for (idx = 0; idx < 3; idx++) {
++ /*
++ * Do nothing if this receiver is not enabled.
++ */
++ if (!inl(i2s_rxenable[idx]))
++ continue;
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[idx + 3];
++
++ /*
++ * Loop while the receive FIFO is not empty.
++ */
++ while (!(inl(I2SGlSts) & i2s_rxflag[idx])) {
++ /*
++ * If the stream is not assigned, is paused, or has no
++ * buffer space, then throw away the data.
++ */
++ if (!p->assigned || p->pause || (p->cur == p->last)) {
++ inl(i2s_rx_lft[idx]);
++ inl(i2s_rx_rt[idx]);
++ } else {
++ /*
++ * Get a pointer to the current buffer.
++ */
++ b = &p->queue[p->cur];
++
++ /*
++ * Read in the next sample.
++ */
++ *(unsigned long *)b->source =
++ inl(i2s_rx_lft[idx]);
++ *(unsigned long *)(b->source + 4) =
++ inl(i2s_rx_rt[idx]);
++
++ /*
++ * Increment past the next sample.
++ */
++ b->source += 8;
++ b->pos += 8;
++
++ /*
++ * See if the buffer has been consumed.
++ */
++ if (b->pos == b->size) {
++ /*
++ * Increment the count of bytes
++ * received.
++ */
++ p->bytes += b->size;
++
++ /*
++ * Go to the next buffer.
++ */
++ p->cur = PIO_NEXT(p->cur);
++
++ /*
++ * Call the callback if there is one.
++ */
++ if (p->callback)
++ p->callback(NFB, p->device,
++ p->user_data);
++ }
++ }
++ }
++ }
++
++ /*
++ * Clear any overrun or underrun conditions that may exist.
++ */
++ outl(0, I2SGlSts);
++}
++
++/*
++ * The interrupt handler for AC'97 audio.
++*/
++static void pio_ac97_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
++{
++ struct pio_stream *p;
++ struct pio_buffer *b;
++ int idx, cm;
++
++ /*
++ * Increment the count of interrupts.
++ */
++ kstat.irqs[smp_processor_id()][IRQ_AAC]++;
++
++ /*
++ * Loop through the three transmitters.
++ */
++ for (idx = 0; idx < 3; idx++) {
++ /*
++ * Do nothing if this transmitter is not enabled.
++ */
++ if (!(inl(ac97_txctrl[idx]) & AC97TXCR_TEN))
++ continue;
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[idx + 6];
++
++ /*
++ * See if this transmitter is in compact mode.
++ */
++ cm = inl(ac97_txctrl[idx]) & AC97TXCR_CM;
++
++ /*
++ * Loop while the transmit FIFO is not full.
++ */
++ while (!(inl(ac97_status[idx]) & AC97SR_TXFF)) {
++ /*
++ * If the stream is not assigned, is paused, or has no
++ * data, then write out silence.
++ */
++ if (!p->assigned || p->pause || (p->cur == p->last)) {
++ outl(0, ac97_data[idx]);
++ if (!cm)
++ outl(0, ac97_data[idx]);
++ } else {
++ /*
++ * Get a pointer to the current buffer.
++ */
++ b = &p->queue[p->cur];
++
++ /*
++ * Write out the next sample.
++ */
++ outl(*(unsigned long *)b->source,
++ ac97_data[idx]);
++
++ /*
++ * Increment past the next sample.
++ */
++ b->source += 4;
++ b->pos += 4;
++
++ /*
++ * Write another sample if we are not in
++ * compact mode.
++ */
++ if (!cm) {
++ outl(*(unsigned long *)b->source,
++ ac97_data[idx]);
++ b->source += 4;
++ b->pos += 4;
++ }
++
++ /*
++ * See if the buffer has been consumed.
++ */
++ if (b->pos == b->size) {
++ /*
++ * Increment the count of bytes
++ * transmitted.
++ */
++ p->bytes += b->size;
++
++ /*
++ * Go to the next buffer.
++ */
++ p->cur = PIO_NEXT(p->cur);
++
++ /*
++ * Call the callback if there is one.
++ */
++ if (p->callback)
++ p->callback(NFB, p->device,
++ p->user_data);
++ }
++ }
++ }
++ }
++
++ /*
++ * Loop through the three receivers.
++ */
++ for (idx = 0; idx < 3; idx++) {
++ /*
++ * Do nothing if this receiver is not enabled.
++ */
++ if (!(inl(ac97_rxctrl[idx]) & AC97RXCR_REN))
++ continue;
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[idx + 9];
++
++ /*
++ * See if this receiver is in compact mode.
++ */
++ cm = inl(ac97_rxctrl[idx]) & AC97RXCR_CM;
++
++ /*
++ * Loop while the receive FIFO is not empty.
++ */
++ while (!(inl(ac97_status[idx]) & AC97SR_RXFE)) {
++ /*
++ * If the stream is not assigned, is paused, or has no
++ * buffer space, then throw away the data.
++ */
++ if (!p->assigned || p->pause || (p->cur == p->last)) {
++ inl(ac97_data[idx]);
++ if (!cm)
++ inl(ac97_data[idx]);
++ } else {
++ /*
++ * Get a pointer to the current buffer.
++ */
++ b = &p->queue[p->cur];
++
++ /*
++ * Read in the next sample.
++ */
++ *(unsigned long *)b->source =
++ inl(ac97_data[idx]);
++
++ /*
++ * Increment past the next sample.
++ */
++ b->source += 4;
++ b->pos += 4;
++
++ /*
++ * Read another sample if we are not in compact
++ * mode.
++ */
++ if (!cm) {
++ *(unsigned long *)b->source =
++ inl(ac97_data[idx]);
++ b->source += 4;
++ b->pos += 4;
++ }
++
++ /*
++ * See if the buffer has been consumed.
++ */
++ if (b->pos == b->size) {
++ /*
++ * Increment the count of bytes
++ * received.
++ */
++ p->bytes += b->size;
++
++ /*
++ * Go to the next buffer.
++ */
++ p->cur = PIO_NEXT(p->cur);
++
++ /*
++ * Call the callback if there is one.
++ */
++ if (p->callback)
++ p->callback(NFB, p->device,
++ p->user_data);
++ }
++ }
++ }
++ }
++}
++
++/*
++ * Add a buffer to a PIO stream.
++ */
++static int
++pio_add_buffer(int handle, unsigned int source, unsigned int dest,
++ unsigned int size, unsigned int last, unsigned int buf_id)
++{
++ struct pio_stream *p;
++ struct pio_buffer *b;
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[handle];
++
++ /*
++ * Fail if there is not space for another buffer.
++ */
++ if (PIO_NEXT(p->last) == p->first)
++ return -1;
++
++ /*
++ * Get a pointer to the next buffer.
++ */
++ b = &p->queue[p->last];
++
++ /*
++ * Save the information about this buffer.
++ */
++ b->source = (unsigned int)phys_to_virt(source);
++ b->pos = 0;
++ b->size = size;
++ b->buf_id = buf_id;
++
++ /*
++ * Increment the last pointer.
++ */
++ p->last = PIO_NEXT(p->last);
++
++ /*
++ * Success.
++ */
++ return 0;
++}
++
++/*
++ * Configure a PIO stream.
++ */
++static int
++pio_config(int handle, unsigned int flags_m2p, unsigned int flags_m2m,
++ dma_callback callback, unsigned int user_data)
++{
++ struct pio_stream *p;
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[handle];
++
++ /*
++ * This puts the stream into pause mode.
++ */
++ p->pause = 1;
++
++ /*
++ * Save the callback function information.
++ */
++ p->callback = callback;
++ p->user_data = user_data;
++
++ /*
++ * Success.
++ */
++ return 0;
++}
++
++/*
++ * Flush all data from a PIO stream.
++ */
++static int pio_flush(int handle)
++{
++ struct pio_stream *p;
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[handle];
++
++ /*
++ * Disable interrupts.
++ */
++ clf();
++
++ /*
++ * Blast all buffer information from this stream.
++ */
++ p->first = 0;
++ p->cur = 0;
++ p->last = 0;
++ p->bytes = 0;
++
++ /*
++ * Enable interrupts.
++ */
++ stf();
++
++ /*
++ * Success.
++ */
++ return 0;
++}
++
++/*
++ * Free a PIO stream.
++ */
++static int pio_free(int handle)
++{
++ /*
++ * See if this is a I2S or AC'97 stream.
++ */
++ if (handle < 6) {
++ /*
++ * Decrement the I2S reference count.
++ */
++ pio_irq_ref_count[0]--;
++
++ /*
++ * See if the reference count is now zero.
++ */
++ if (pio_irq_ref_count[0] == 0) {
++ /*
++ * Make the I2S interrupt an IRQ instead of a FIQ.
++ */
++ outl(inl(VIC1INTSELECT) & ~(1 << (IRQ_SAI - 32)),
++ VIC1INTSELECT);
++
++ /*
++ * Disable I2S interrupts in the I2S block.
++ */
++ outl(0, I2STXCtrl);
++ outl(0, I2SRXCtrl);
++
++ /*
++ * Release the I2S interrupt.
++ */
++ free_irq(IRQ_SAI, (void *)&pio_i2s_irq_handler);
++
++ /*
++ * Release the FIQ.
++ */
++ release_fiq(&fh);
++ }
++ } else {
++ /*
++ * Decrement the AC'97 reference count.
++ */
++ pio_irq_ref_count[1]--;
++
++ /*
++ * See if the reference count is now zero.
++ */
++ if (pio_irq_ref_count[1] == 0) {
++ /*
++ * Make the AC'97 interrupt an IRQ instead of a FIQ.
++ */
++ outl(inl(VIC0INTSELECT) & ~(1 << IRQ_AAC),
++ VIC0INTSELECT);
++
++ /*
++ * Release the AC'97 interrupt.
++ */
++ free_irq(IRQ_AAC, (void *)&pio_ac97_irq_handler);
++
++ /*
++ * Release the FIQ.
++ */
++ release_fiq(&fh);
++ }
++ }
++
++ /*
++ * Mark this stream as unassigned.
++ */
++ pio_streams[handle].assigned = 0;
++
++ /*
++ * Success.
++ */
++ return 0;
++}
++
++/*
++ * Get the current position in a PIO stream.
++ */
++static int
++pio_get_position(int handle, unsigned int *buf_id, unsigned int *total,
++ unsigned int *current_frac)
++{
++ struct pio_stream *p;
++ struct pio_buffer *b;
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[handle];
++
++ /*
++ * Disable interrupts.
++ */
++ clf();
++
++ /*
++ * Get a pointer to the current buffer.
++ */
++ b = &p->queue[p->cur];
++
++ /*
++ * If the buffer is is being requested, then return it.
++ */
++ if (buf_id)
++ *buf_id = b->buf_id;
++
++ /*
++ * If the total bytes transferred is being requested, then return it.
++ */
++ if (total)
++ *total = p->bytes;
++
++ /*
++ * If the bytes transferred from the current buffer is being requested,
++ * then return it.
++ */
++ if (current_frac)
++ *current_frac = b->size - b->pos;
++
++ /*
++ * Enable interrupts.
++ */
++ stf();
++
++ /*
++ * Success.
++ */
++ return 0;
++}
++
++/*
++ * Pause a PIO stream.
++ */
++static int pio_pause(int handle, unsigned int channels, unsigned int *handles)
++{
++ struct pio_stream *p;
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[handle];
++
++ /*
++ * Pause the stream.
++ */
++ p->pause = 1;
++
++ /*
++ * Success.
++ */
++ return 0;
++}
++
++/*
++ * Remove a consumed buffer from a PIO stream.
++ */
++static int pio_remove_buffer(int handle, unsigned int *buf_id)
++{
++ struct pio_stream *p;
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[handle];
++
++ /*
++ * Fail if there are not consumed buffers.
++ */
++ if (p->first == p->cur)
++ return -1;
++
++ /*
++ * Return the ID of the next fully consumed buffer.
++ */
++ *buf_id = p->queue[p->first].buf_id;
++
++ /*
++ * Increment the first pointer.
++ */
++ p->first = PIO_NEXT(p->first);
++
++ /*
++ * Success.
++ */
++ return 0;
++}
++
++/*
++ * Request a PIO stream.
++ */
++static int
++pio_request(int *handle, const char *device_id, ep93xx_dma_dev_t device)
++{
++ struct pio_stream *p;
++ struct pt_regs regs;
++ int idx, error;
++
++ /*
++ * Get the stream index from the DMA device we are emulating.
++ */
++ switch (device) {
++ case DMATx_I2S1:
++ idx = 0;
++ break;
++ case DMATx_I2S2:
++ idx = 1;
++ break;
++ case DMATx_I2S3:
++ idx = 2;
++ break;
++ case DMARx_I2S1:
++ idx = 3;
++ break;
++ case DMARx_I2S2:
++ idx = 4;
++ break;
++ case DMARx_I2S3:
++ idx = 5;
++ break;
++ case DMATx_AAC1:
++ idx = 6;
++ break;
++ case DMATx_AAC2:
++ idx = 7;
++ break;
++ case DMATx_AAC3:
++ idx = 8;
++ break;
++ case DMARx_AAC1:
++ idx = 9;
++ break;
++ case DMARx_AAC2:
++ idx = 10;
++ break;
++ case DMARx_AAC3:
++ idx = 11;
++ break;
++ default:
++ return -ENODEV;
++ }
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[idx];
++
++ /*
++ * Fail if this stream is already assigned.
++ */
++ if (p->assigned)
++ return -EBUSY;
++
++ /*
++ * Initialize this stream.
++ */
++ memset(p->queue, 0, sizeof(p->queue));
++ p->device = device;
++ p->first = 0;
++ p->cur = 0;
++ p->last = 0;
++ p->bytes = 0;
++ p->pause = 0;
++ p->callback = 0;
++ p->user_data = 0;
++
++ /*
++ * Mark this stream as assigned.
++ */
++ p->assigned = 1;
++
++ /*
++ * See if this is a I2S or AC'97 stream.
++ */
++ if (idx < 6) {
++ /*
++ * If there is already a AC'97 stream in use, then do not allow
++ * I2S streams.
++ */
++ if (pio_irq_ref_count[1])
++ return -EBUSY;
++
++ /*
++ * See if there is another I2S stream.
++ */
++ if (pio_irq_ref_count[0] == 0) {
++ /*
++ * Claim the FIQ handler.
++ */
++ if (claim_fiq(&fh))
++ return -EBUSY;
++
++ /*
++ * Request the I2S interrupt.
++ */
++ error = request_irq(IRQ_SAI, pio_i2s_irq_handler,
++ SA_INTERRUPT, "i2s",
++ (void *)&pio_i2s_irq_handler);
++ if (error) {
++ release_fiq(&fh);
++ return error;
++ }
++
++ /*
++ * Set the FIQ mode registers.
++ */
++ regs.ARM_sp = (long)fiq_stack + sizeof(fiq_stack);
++ set_fiq_regs(&regs);
++
++ /*
++ * Set the FIQ handler.
++ */
++ set_fiq_handler(&i2s_fiq_begin,
++ &i2s_fiq_end - &i2s_fiq_begin);
++
++ /*
++ * Make the I2S interrupt a FIQ instead of an IRQ.
++ */
++ outl(inl(VIC1INTSELECT) | (1 << (IRQ_SAI - 32)),
++ VIC1INTSELECT);
++
++ /*
++ * Enable transmit half empty and receive half full
++ * interrupts in the I2S block.
++ */
++ outl(2, I2STXCtrl);
++ outl(2, I2SRXCtrl);
++ }
++
++ /*
++ * Increment the I2S interrupt reference count.
++ */
++ pio_irq_ref_count[0]++;
++ } else {
++ /*
++ * If there is already a I2S stream in use, then do not allow
++ * AC'97 streams.
++ */
++ if (pio_irq_ref_count[0])
++ return -EBUSY;
++
++ /*
++ * See if there is another AC'97 stream.
++ */
++ if (pio_irq_ref_count[1] == 0) {
++ /*
++ * Claim the FIQ handler.
++ */
++ if (claim_fiq(&fh))
++ return -EBUSY;
++
++ /*
++ * Request the AC'97 interrupt.
++ */
++ error = request_irq(IRQ_AAC, pio_ac97_irq_handler,
++ SA_INTERRUPT, "ac-97",
++ (void *)&pio_ac97_irq_handler);
++ if (error) {
++ release_fiq(&fh);
++ return error;
++ }
++
++ /*
++ * Set the FIQ mode registers.
++ */
++ regs.ARM_sp = (long)fiq_stack + sizeof(fiq_stack);
++ set_fiq_regs(&regs);
++
++ /*
++ * Set the FIQ handler.
++ */
++ set_fiq_handler(&ac97_fiq_begin,
++ &ac97_fiq_end - &ac97_fiq_begin);
++
++ /*
++ * Make the AC'97 interrupt a FIQ instead of an IRQ.
++ */
++ outl(inl(VIC0INTSELECT) | (1 << IRQ_AAC),
++ VIC0INTSELECT);
++ }
++
++ /*
++ * Increment the AC'97 interrupt reference count.
++ */
++ pio_irq_ref_count[1]++;
++ }
++
++ /*
++ * Return a handle to this stream.
++ */
++ *handle = idx;
++
++ /*
++ * Success.
++ */
++ return 0;
++}
++
++/*
++ * Start a PIO stream.
++ */
++static int pio_start(int handle, unsigned int channels, unsigned int *handles)
++{
++ struct pio_stream *p;
++
++ /*
++ * Get a pointer to this stream's structure.
++ */
++ p = &pio_streams[handle];
++
++ /*
++ * Start the stream.
++ */
++ p->pause = 0;
++
++ /*
++ * Success.
++ */
++ return 0;
++}
++#endif
++
++/*
++ * calculate_dma2usr_ratio_etc()
++ *
++ * For audio playback, we convert samples of arbitrary format to be 32 bit
++ * for our hardware. We're scaling a user buffer to a dma buffer. So when
++ * report byte counts, we scale them acording to the ratio of DMA sample
++ * size to user buffer sample size. When we report # of DMA fragments,
++ * we don't scale that. So:
++ * - The fragment size the app sees = (stream->fragsize/stream->dma2usr_ratio)
++ * - The # of fragments the app sees = stream->nbfrags
++ *
++ * User sample type can be stereo/mono/8/16/32 bit.
++ * DMA sample type will be either CM (compact mode) where two 16 bit
++ * samples together in a 32 bit word become a stereo sample or non-CM
++ * where each channel gets a 32 bit word.
++ *
++ * Any time usr sample type changes, we need to call this function.
++ *
++ * Also adjust the size and number of dma fragments if sample size changed.
++ *
++ * Input format Input sample Output sample size ratio (out:in)
++ * bits channels size (bytes) CM non-CM CM non-CM
++ * 8 mono 1 4 8 4:1 8:1
++ * 8 stereo 2 4 8 2:1 4:1
++ * 16 mono 2 4 8 2:1 4:1
++ * 16 stereo 4 4 8 1:1 2:1
++ *
++ * 24 mono 3 4 8 X 8:3 not a real case
++ * 24 stereo 6 4 8 X 8:6 not a real case
++ * 32 mono 4 4 8 X 2:1
++ * 32 stereo 8 4 8 X 1:1
++ *
++ */
++static void calculate_dma2usr_ratio_etc(struct audio_stream_t *stream)
++{
++ unsigned int dma_sample_size, user_sample_size;
++
++ if (stream->bCompactMode)
++ dma_sample_size = 4; /* each stereo sample is 2 * 16 bits */
++ else
++ dma_sample_size = 8; /* each stereo sample is 2 * 32 bits */
++
++ if (stream->audio_num_channels != 1) {
++ // If stereo 16 bit, user sample is 4 bytes.
++ // If stereo 8 bit, user sample is 2 bytes.
++ user_sample_size = stream->audio_stream_bitwidth / 4;
++ } else {
++ // If mono 16 bit, user sample is 2 bytes.
++ // If mono 8 bit, user sample is 1 bytes.
++ user_sample_size = stream->audio_stream_bitwidth / 8;
++ }
++
++ /*
++ * dma2usr_ratio = (4 or 8) / (4, 2, or 1) = 8, 4, 2, or 1
++ */
++ stream->dma2usr_ratio = dma_sample_size / user_sample_size;
++
++ DPRINTK(" samplesize: dma %d user %d dma/usr ratio %d\n",
++ dma_sample_size, user_sample_size, stream->dma2usr_ratio);
++ DPRINTK
++ (" requested: fragsize %d num frags %d total bytes %d total samples %d\n",
++ stream->requested_fragsize, stream->requested_nbfrags,
++ stream->requested_fragsize * stream->requested_nbfrags,
++ (stream->requested_fragsize * stream->requested_nbfrags) /
++ user_sample_size);
++ DPRINTK
++ (" usr : fragsize %d num frags %d total bytes %d total samples %d\n",
++ (stream->fragsize / stream->dma2usr_ratio), stream->nbfrags,
++ stream->fragsize * stream->nbfrags / stream->dma2usr_ratio,
++ (stream->fragsize * stream->nbfrags) / (stream->dma2usr_ratio *
++ user_sample_size));
++ DPRINTK
++ (" dma: fragsize %d num frags %d total bytes %d total samples %d\n",
++ stream->fragsize, stream->nbfrags,
++ stream->fragsize * stream->nbfrags,
++ (stream->fragsize * stream->nbfrags) / dma_sample_size);
++
++}
++
++/*
++ * audio_deallocate_buffers
++ *
++ * This function frees all buffers
++ */
++static void audio_deallocate_buffers(struct audio_state_t *state,
++ struct audio_stream_t *stream)
++{
++ int frag, i;
++
++ DPRINTK("EP93xx - audio_deallocate_buffers\n");
++
++ /* ensure DMA won't run anymore */
++ audio_dma_pause(state, stream);
++ stream->active = 0;
++ stream->stopped = 0;
++
++ for (i = 0; i < stream->NumDmaChannels; i++)
++ DMA_FLUSH(stream->dmahandles[i]);
++
++ if (stream->buffers) {
++ for (frag = 0; frag < stream->nbfrags; frag++) {
++ if (!stream->buffers[frag].master) {
++ continue;
++ }
++ // KERNEL2.4
++ //consistent_free(stream->buffers[frag].start,
++ // stream->buffers[frag].master,
++ // stream->buffers[frag].dma_addr);
++ dma_free_coherent(NULL, stream->buffers[frag].master,
++ stream->buffers[frag].start,
++ stream->buffers[frag].dma_addr);
++
++ }
++
++ /*
++ * Free the space allocated to the array of dma_buffer structs.
++ */
++ kfree(stream->buffers);
++ stream->buffers = NULL;
++ }
++
++ stream->buffered_bytes_to_play = 0;
++ stream->dma_buffer_index = 0;
++ stream->dma_buffer = NULL;
++ stream->bytecount = 0;
++ stream->getptrCount = 0;
++ stream->fragcount = 0;
++
++ DPRINTK("EP93xx - audio_deallocate_buffers - EXIT\n");
++}
++
++/*
++ * audio_allocate_buffers
++ *
++ * This function allocates the buffer structure array and buffer data space
++ * according to the current number of fragments and fragment size.
++ * Note that the output_stream and input_stream structs are allocated
++ * in ep93xx-ac97.c or ep93xx-i2s.c.
++ */
++static int audio_allocate_buffers(struct audio_state_t *state,
++ struct audio_stream_t *stream)
++{
++ int frag;
++ int dmasize = 0;
++ char *dmabuf = NULL;
++ dma_addr_t dmaphys = 0;
++ int buf_num = 0;
++
++ if (stream->buffers)
++ return -EBUSY;
++
++ DPRINTK("EP93xx audio_allocate_buffers\n");
++
++ /*
++ * Allocate space for the array of struct audio_buf_t structs.
++ */
++ stream->buffers = (struct audio_buf_t *)
++ kmalloc(sizeof(struct audio_buf_t) * stream->nbfrags, GFP_KERNEL);
++
++ if (!stream->buffers) {
++ DPRINTK("ep93xx-audio: unable to allocate audio memory\n ");
++ audio_deallocate_buffers(state, stream);
++ return -ENOMEM;
++ }
++
++ /*
++ * If the audio app hasn't requested a specific fragsize and nbfrags,
++ * we stay with our default.
++ */
++ if ((stream->requested_fragsize != 0)
++ && (stream->requested_nbfrags != 0)) {
++ /*
++ * Adjust the fragsize to take into account how big actual samples in
++ * the dma buffer are. Max dma buf size is 64K.
++ */
++ stream->fragsize =
++ stream->requested_fragsize * stream->dma2usr_ratio;
++ }
++
++ if (stream->fragsize > 65536)
++ stream->fragsize = 65536;
++ if (stream->fragsize < 8192)
++ stream->fragsize = 8192;
++
++ /*
++ * Adjust num of frags so we have as many samples of buffer as were requested
++ * even if the fragment size changed.
++ */
++ if ((stream->requested_fragsize != 0)
++ && (stream->requested_nbfrags != 0)) {
++ stream->nbfrags =
++ (stream->requested_fragsize * stream->requested_nbfrags *
++ stream->dma2usr_ratio)
++ / stream->fragsize;
++ }
++
++ if (stream->nbfrags < 2)
++ stream->nbfrags = 2;
++ if (stream->nbfrags > AUDIO_NBFRAGS_MAX)
++ stream->nbfrags = AUDIO_NBFRAGS_MAX;
++
++ memset(stream->buffers, 0,
++ sizeof(struct audio_buf_t) * stream->nbfrags);
++
++ /*
++ * Let's allocate non-cached memory for DMA buffers.
++ * We try to allocate all memory at once.
++ * If this fails (a common reason is memory fragmentation),
++ * then we allocate more smaller buffers.
++ */
++ for (frag = 0; frag < stream->nbfrags; frag++) {
++ struct audio_buf_t *dma_buffer = &stream->buffers[frag];
++
++ if (!dmasize) {
++ /*
++ * First try to allocate enough for all the frags that
++ * don't yet have memory allocated.
++ */
++ dmasize = (stream->nbfrags - frag) * stream->fragsize;
++ do {
++ // GRM
++ //dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,
++ // dmasize, &dmaphys);
++ dmabuf = dma_alloc_coherent(NULL,
++ dmasize, &dmaphys,
++ GFP_KERNEL |
++ GFP_DMA);
++
++ /*
++ * If that fails, try to allocate a chunk of memory
++ * that is one less fragment is size.
++ */
++ if (!dmabuf)
++ dmasize -= stream->fragsize;
++
++ /*
++ * Keep trying but the minimum we'll attempt is one
++ * fragment. If we can't even get that, give up.
++ */
++ } while (!dmabuf && dmasize);
++
++ /*
++ * If we do fail to allocate enough for all the frags,
++ * deallocate whatever we did get and quit.
++ */
++ if (!dmabuf) {
++ DPRINTK
++ ("ep93xx-audio: unable to allocate audio memory\n ");
++ audio_deallocate_buffers(state, stream);
++ return -ENOMEM;
++ }
++
++ DPRINTK
++ ("EP93xx allocated %d bytes: dmabuf=0x%08x dmaphys=0x%08x\n",
++ dmasize, (int)dmabuf, (int)dmaphys);
++
++ /*
++ * Success! Save the size of this chunk to use when we deallocate it.
++ */
++ dma_buffer->master = dmasize;
++ memzero(dmabuf, dmasize);
++ }
++
++ /*
++ * Save the start address of the dma_buffer fragment.
++ * We know the size of the fragment is fragsize.
++ */
++ dma_buffer->start = dmabuf;
++ dma_buffer->dma_addr = dmaphys;
++ dma_buffer->stream = stream;
++ dma_buffer->size = 0;
++ dma_buffer->sent = 0;
++ dma_buffer->num = buf_num++;
++
++ dma_buffer->owner = 0;
++
++ /*
++ * Now if we only allocated the minimal one frag of space, the
++ * dmasize will be ==0 after this subtraction so it will allocate more
++ * for the next frag. Otherwise, the next time(s) thru this for loop
++ * will dole out frag sized pieces of this big master chunk.
++ */
++ dmabuf += stream->fragsize;
++ dmaphys += stream->fragsize;
++ dmasize -= stream->fragsize;
++ }
++
++ /*
++ * Initialize the stream.
++ */
++ stream->buffered_bytes_to_play = 0;
++ stream->dma_buffer_index = 0; /* Init the current buffer index. */
++ stream->dma_buffer = &stream->buffers[0]; /* Point dma_buffer to the current buffer struct. */
++ stream->bytecount = 0;
++ stream->getptrCount = 0;
++ stream->fragcount = 0;
++
++ DPRINTK("EP93xx audio_allocate_buffers -- exit SUCCESS\n");
++ return 0;
++
++}
++
++/*
++ * audio_reset_buffers
++ *
++ * This function stops and flushes the dma, gets all buffers back
++ * from the DMA driver and resets them ready to be used again.
++ */
++static void audio_reset_buffers(struct audio_state_t *state,
++ struct audio_stream_t *stream)
++{
++ int frag, i;
++
++ audio_dma_pause(state, stream);
++ stream->active = 0;
++ stream->stopped = 0;
++
++ for (i = 0; i < stream->NumDmaChannels; i++)
++ DMA_FLUSH(stream->dmahandles[i]);
++
++ if (stream->buffers) {
++ for (frag = 0; frag < stream->nbfrags; frag++) {
++ struct audio_buf_t *dma_buffer = &stream->buffers[frag];
++ dma_buffer->size = 0;
++ dma_buffer->sent = 0;
++ dma_buffer->owner = 0;
++ }
++ }
++
++ stream->buffered_bytes_to_play = 0;
++ stream->bytecount = 0;
++ stream->getptrCount = 0;
++ stream->fragcount = 0;
++}
++
++/*
++ * DMA callback functions
++ */
++static void audio_dma_tx_callback
++ (ep93xx_dma_int_t DMAInt, ep93xx_dma_dev_t device, unsigned int user_data) {
++ unsigned int buf_id;
++ int handle, i;
++
++ struct audio_state_t *state = (struct audio_state_t *)user_data;
++ struct audio_stream_t *stream = state->output_stream;
++
++ /* DPRINTK( "audio_dma_tx_callback - %s\n", stream->devicename ); */
++
++ /*
++ * Get the DMA handle that corresponds to the dma channel
++ * that needs servicing. A multichannel audio stream will
++ * have a DMA handle for each stereo pair that it uses.
++ */
++ for (i = 0;
++ (i < stream->NumDmaChannels) && (stream->dmachannel[i] != device);
++ i++) ;
++ handle = stream->dmahandles[i];
++
++ if (stream->mapped) {
++ /*
++ * If we are mapped, get one dma buffer back and recycle it.
++ */
++ if (DMA_REMOVE_BUFFER(handle, &buf_id) >= 0) {
++ struct audio_buf_t *dma_buffer =
++ (struct audio_buf_t *)buf_id;
++
++ /* DPRINTK( "audio_dma_tx_callback - got dma buffer index=%d\n", buf_id); */
++
++ /* Accounting */
++ stream->buffered_bytes_to_play -= dma_buffer->size;
++
++ /* bytecount and fragcount will overflow */
++ stream->bytecount += dma_buffer->size;
++ if (stream->bytecount < 0)
++ stream->bytecount = 0;
++
++ stream->fragcount++;
++ if (stream->fragcount < 0)
++ stream->fragcount = 0;
++
++ dma_buffer->size = 0;
++
++ /* Recycle dma buffer */
++ dma_buffer->size = stream->fragsize;
++
++ DMA_ADD_BUFFER(handle, /* dma instance */
++ (unsigned int)dma_buffer->dma_addr, /* source */
++ 0, /* dest */
++ stream->fragsize, /* size */
++ 0, /* is the last chunk? */
++ (unsigned int)dma_buffer); /* buf id */
++
++ dma_buffer->sent = 1;
++ }
++ } else {
++ /*
++ * Get all buffers that are free'ed back and clear their semephores.
++ */
++ while (DMA_REMOVE_BUFFER(handle, &buf_id) >= 0) {
++ struct audio_buf_t *dma_buffer =
++ (struct audio_buf_t *)buf_id;
++
++ /* DPRINTK( "audio_dma_tx_callback - got dma buffer index=%d\n", buf_id); */
++
++ /* Accounting */
++ stream->buffered_bytes_to_play -= dma_buffer->size;
++
++ stream->bytecount += dma_buffer->size;
++ if (stream->bytecount < 0)
++ stream->bytecount = 0;
++
++ stream->fragcount++;
++ if (stream->fragcount < 0)
++ stream->fragcount = 0;
++
++ dma_buffer->size = 0;
++ dma_buffer->sent = 0;
++
++ /*
++ * Release the semaphore on this dma_buffer.
++ * If write is waiting on this dma_buffer then it can go
++ * ahead and fill it and send it to the dma.
++ */
++ dma_buffer->owner = 0;
++ }
++ }
++
++ /* And any process polling on write. */
++ wake_up(&stream->wq);
++}
++
++static void audio_dma_rx_callback
++ (ep93xx_dma_int_t DMAInt, ep93xx_dma_dev_t device, unsigned int user_data) {
++ unsigned int buf_id;
++ int handle, i;
++
++ struct audio_state_t *state = (struct audio_state_t *)user_data;
++ struct audio_stream_t *stream = state->input_stream;
++
++ //DPRINTK("audio_dma_rx_callback\n");
++
++ /*
++ * Get the DMA handle that corresponds to the dma channel
++ * that needs servicing. A multichannel audio stream will
++ * have a DMA handle for each stereo pair that it uses.
++ */
++ for (i = 0;
++ (i < stream->NumDmaChannels) && (stream->dmachannel[i] != device);
++ i++) ;
++ handle = stream->dmahandles[i];
++
++ /*
++ * Keep removing and recycling buffers as long as there are buffers
++ * to remove.
++ */
++ while (!DMA_REMOVE_BUFFER(handle, &buf_id)) {
++ struct audio_buf_t *dma_buffer = (struct audio_buf_t *)buf_id;
++
++ /* Accounting */
++ stream->bytecount += stream->fragsize;
++ if (stream->bytecount < 0)
++ stream->bytecount = 0;
++
++ stream->fragcount++;
++ if (stream->fragcount < 0)
++ stream->fragcount = 0;
++
++ /* Recycle dma buffer */
++ if (stream->mapped) {
++ DMA_ADD_BUFFER(handle, /* dma instance */
++ (unsigned int)dma_buffer->dma_addr, /* source */
++ 0, /* dest */
++ stream->fragsize, /* size */
++ 0, /* is the last chunk? */
++ (unsigned int)dma_buffer); /* buf id */
++ } else {
++ dma_buffer->size = stream->fragsize;
++ dma_buffer->owner = 0;
++ }
++
++ /* And any process polling on write. */
++ wake_up(&stream->wq);
++ }
++}
++
++/*
++ * audio_sync
++ *
++ * Wait until the last byte written to this device has been played.
++ */
++static int audio_sync(struct file *file)
++{
++ struct audio_state_t *state =
++ (struct audio_state_t *)file->private_data;
++ struct audio_stream_t *stream = state->output_stream;
++ struct audio_buf_t *dma_buffer;
++ int buf_wait_index;
++
++ DPRINTK("audio_sync - enter\n");
++
++ if (!(file->f_mode & FMODE_WRITE) || !stream->buffers || stream->mapped) {
++ DPRINTK("audio_sync - exit immediately.\n");
++ return 0;
++ }
++
++ /*
++ * Send current dma buffer if it contains data and hasn't been sent.
++ */
++ dma_buffer = stream->dma_buffer;
++
++ if (dma_buffer->size && !dma_buffer->sent) {
++ DPRINTK("audio_sync -- SENDING BUFFER index=%d size=%d\n",
++ stream->dma_buffer_index, dma_buffer->size);
++
++ while (dma_buffer->owner == 1)
++ schedule();
++ dma_buffer->owner = 1;
++ DMA_ADD_BUFFER(stream->dmahandles[0], /* dma instance */
++ (unsigned int)dma_buffer->dma_addr, /* source */
++ 0, /* dest */
++ dma_buffer->size, /* size */
++ 0, /* is the last chunk? */
++ (unsigned int)dma_buffer); /* dma_buffer id */
++ dma_buffer->sent = 1;
++ NEXT_BUF(stream, dma_buffer);
++ }
++
++ /*
++ * Let's wait for the last dma buffer we sent i.e. the one before the
++ * current dma_buffer_index. When we acquire the semaphore, this means either:
++ * - DMA on the buffer completed or
++ * - the buffer was already free thus nothing else to sync.
++ */
++ buf_wait_index =
++ ((stream->nbfrags + stream->dma_buffer_index -
++ 1) % stream->nbfrags);
++ dma_buffer = stream->buffers + buf_wait_index;
++
++ DPRINTK("audio_sync - waiting on down_interruptible\n");
++ while (dma_buffer->owner == 1) {
++ if (signal_pending(current))
++ return -ERESTARTSYS;
++ schedule();
++ }
++
++ DPRINTK("audio_sync - EXIT\n");
++ return 0;
++}
++
++//static int iWriteCount = 0;
++
++/*
++ * Need to convert to 32 bit stereo format:
++ * 16 bit signed
++ * 16 bit unsigned
++ * 8 bit signed
++ * 8 bit unsigned
++ */
++static int audio_write
++ (struct file *file,
++ const char *user_buffer, size_t src_count, loff_t * ppos) {
++ const char *user_buffer_start = user_buffer;
++ struct audio_state_t *state =
++ (struct audio_state_t *)file->private_data;
++ struct audio_stream_t *stream = state->output_stream;
++ unsigned int dma_xfer_count, src_xfer_count, expanded_count;
++ int ret = 0;
++// int i,j;
++
++ /* DPRINTK_IOCTL( "EP93xx - audio_write: count=%d\n", src_count ); */
++
++ // KERNEL2.4
++ /*if (ppos != &file->f_pos)
++ return -ESPIPE; */
++
++ if (stream->mapped)
++ return -ENXIO;
++
++ if (!access_ok(VERIFY_READ, user_buffer, src_count)) {
++ DPRINTK("access_ok failed for audio_write!!!!\n");
++ return -EFAULT;
++ }
++
++ /*
++ * Allocate dma buffers if we haven't already done so.
++ */
++ if (!stream->buffers && audio_allocate_buffers(state, stream))
++ return -ENOMEM;
++
++// if( iWriteCount > 40 )
++// {
++// for( i=0; i<4 ; i++ )
++// {
++// for( j=0; j<8 ; j++ )
++// {
++// printk("%02x ", user_buffer[(i*8)+j] );
++// }
++// printk("\n");
++// }
++// iWriteCount = 0;
++// }
++// iWriteCount++;
++
++ /*
++ * Stay in this loop until we have copied all of the file
++ * into user memory.
++ */
++ while (src_count > 0) {
++ struct audio_buf_t *dma_buffer = stream->dma_buffer;
++
++ /* Wait for a dma buffer to become free */
++ if (file->f_flags & O_NONBLOCK) {
++ ret = -EAGAIN;
++ if (dma_buffer->owner != 0)
++ break;
++ } else {
++ while (dma_buffer->owner == 1) {
++ if (signal_pending(current))
++ return -ERESTARTSYS;
++ schedule();
++ }
++ }
++
++ /*
++ * Feed the current dma buffer (stream->dma_buffer)
++ * This involves expanding sample size from the user_buffer
++ * to be 32 bit stereo for our dma.
++ */
++
++ /*
++ * How much space is left in the current dma buffer?
++ *
++ * dma_xfer_count is # of bytes placed into the dma buffer
++ * where each sample is 8 bytes (4 bytes left, 4 bytes right)
++ * because that's what the I2S is set up for - 32 bit samples.
++ */
++ dma_xfer_count = stream->fragsize - dma_buffer->size;
++
++ /*
++ * user_buffer is src_count (bytes) of whatever format.
++ * How big will src_count be when sample size is expanded
++ * to 32 bit samples for our hardware?
++ */
++ expanded_count = src_count * stream->dma2usr_ratio;
++
++ /*
++ * See if we can fit all the remaining user_buffer in
++ * the current dma buffer...
++ */
++ if (dma_xfer_count > expanded_count)
++ dma_xfer_count = expanded_count;
++
++ //DPRINTK( "EP93xx - audio_write: %d to dma_buffer # %d\n", dma_xfer_count, stream->dma_buffer_index );
++
++ src_xfer_count = copy_from_user_with_conversion(state,
++ dma_buffer->
++ start +
++ dma_buffer->
++ size,
++ user_buffer,
++ dma_xfer_count);
++ if (src_xfer_count <= 0)
++ return -EFAULT;
++
++ /*
++ * Increment dma buffer pointer.
++ */
++ dma_buffer->size += dma_xfer_count;
++
++ /*
++ * Increment user_buffer pointer.
++ * Decrement the user_buffer size count.
++ */
++ user_buffer += src_xfer_count;
++ src_count -= src_xfer_count;
++
++ /*
++ * If we haven't already started the DMA start it.
++ * But don't start it if we are waiting on a trigger.
++ */
++ if (!stream->active && !stream->stopped) {
++ stream->active = 1;
++ audio_dma_start(state, stream);
++ }
++
++ /*
++ * Note that we've 'downed' the semiphore for this buffer. But the
++ * dma driver doesn't know about it until we've added it to the DMA
++ * driver's buffer queue. So let's do that now.
++ */
++ dma_buffer->owner = 1;
++ DMA_ADD_BUFFER(stream->dmahandles[0], /* dma instance */
++ (unsigned int)dma_buffer->dma_addr, /* source */
++ 0, /* dest */
++ dma_buffer->size, /* size */
++ 0, /* is the last chunk? */
++ (unsigned int)dma_buffer); /* buf id */
++
++ /*
++ * Note that we added a buffer to play for the benefit of calculating
++ * ODELAY.
++ */
++ stream->buffered_bytes_to_play += dma_buffer->size;
++
++ /*
++ * Indicate that the dma buffer has been sent. Not the same as the
++ * buffer's semiphore.
++ */
++ dma_buffer->sent = 1;
++
++ NEXT_BUF(stream, dma_buffer);
++ }
++
++ /*
++ * Return the number of bytes transferred.
++ */
++ if ((int)user_buffer - (int)user_buffer_start)
++ ret = (int)user_buffer - (int)user_buffer_start;
++
++/* DPRINTK( "EP93xx - audio_write: return=%d\n", ret );*/
++ return ret;
++}
++
++/*
++ * audio_dma_start
++ *
++ * Our Ac97 has a specific start order that it likes. Enable the
++ * Ac97 channel AFTER enabling DMA. Our I2S is not so picky.
++ */
++void audio_dma_start(struct audio_state_t *state, struct audio_stream_t *stream)
++{
++ DMA_START(stream->dmahandles[0],
++ stream->NumDmaChannels, stream->dmahandles);
++
++ if (state->hw->hw_enable)
++ state->hw->hw_enable(stream);
++
++}
++
++/*
++ * audio_dma_pause
++ */
++void audio_dma_pause(struct audio_state_t *state, struct audio_stream_t *stream)
++{
++ DPRINTK("audio_dma_pause - enter\n");
++
++ DMA_PAUSE(stream->dmahandles[0],
++ stream->NumDmaChannels, stream->dmahandles);
++
++ if (state->hw->hw_disable)
++ state->hw->hw_disable(stream);
++
++ if (state->hw->hw_clear_fifo)
++ state->hw->hw_clear_fifo(stream);
++
++ DPRINTK("audio_dma_pause - EXIT\n");
++}
++
++static void audio_prime_dma(struct audio_state_t *state,
++ struct audio_stream_t *stream)
++{
++ int i;
++
++ DPRINTK("audio_prime_dma\n");
++
++ /*
++ * If we haven't already started the DMA start it.
++ * But don't start it if we are waiting on a trigger.
++ */
++ if (!stream->active && !stream->stopped) {
++ stream->active = 1;
++ audio_dma_start(state, stream);
++ }
++
++ for (i = 0; i < stream->nbfrags; i++) {
++ struct audio_buf_t *dma_buffer = stream->dma_buffer;
++
++ dma_buffer->owner = 1;
++ DMA_ADD_BUFFER(stream->dmahandles[0], /* dma instance */
++ (unsigned int)dma_buffer->dma_addr, /* source */
++ 0, /* dest */
++ stream->fragsize, /* size */
++ 0, /* is the last chunk? */
++ (unsigned int)dma_buffer); /* buf id */
++ NEXT_BUF(stream, dma_buffer);
++ }
++}
++
++/*
++ * audio_read
++ *
++ * Audio capture function.
++ */
++static int audio_read
++ (struct file *file, char *user_buffer, size_t count, loff_t * ppos) {
++ char *user_buffer_start = user_buffer;
++ struct audio_state_t *state =
++ (struct audio_state_t *)file->private_data;
++ struct audio_stream_t *stream = state->input_stream;
++ unsigned int user_buffer_xfer_count = 0, dma_buffer_xfer_count = 0;
++ int ret = 0;
++
++ DPRINTK("EP93xx - audio_read: count=%d\n", count);
++
++ // KERNEL2.4
++ /*if (ppos != &file->f_pos)
++ return -ESPIPE; */
++
++ if (stream->mapped)
++ return -ENXIO;
++
++ if (!access_ok(VERIFY_WRITE, user_buffer, count)) {
++ DPRINTK("access_ok failed for audio_read!!!!\n");
++ return -EFAULT;
++ }
++
++ if (!stream->active) {
++ if (!stream->buffers && audio_allocate_buffers(state, stream))
++ return -ENOMEM;
++
++ audio_prime_dma(state, stream);
++ }
++
++ while (count > 0) {
++ /*
++ * Get the current buffer.
++ */
++ struct audio_buf_t *dma_buffer = stream->dma_buffer;
++
++ /*
++ * Wait for a dma buffer to become full
++ */
++ if (file->f_flags & O_NONBLOCK) {
++ //DPRINTK("file->f_flags & O_NONBLOCK\n");
++ ret = -EAGAIN;
++ if (dma_buffer->owner != 0)
++ break;
++ } else {
++ while (dma_buffer->owner == 1) {
++ if (signal_pending(current))
++ return -ERESTARTSYS;
++ schedule();
++ }
++ }
++
++ /*
++ * If this is the first buffer captured,
++ * dump the first 8 samples of the dma buffer.
++ */
++ if (stream->bFirstCaptureBuffer) {
++ dma_buffer->size -= 64;
++ stream->bFirstCaptureBuffer = 0;
++ }
++
++ /*
++ * How much user buffer would a whole DMA buffer fill?
++ */
++ user_buffer_xfer_count =
++ dma_buffer->size / stream->dma2usr_ratio;
++
++ if (user_buffer_xfer_count > count)
++ user_buffer_xfer_count = count;
++
++ dma_buffer_xfer_count =
++ user_buffer_xfer_count * stream->dma2usr_ratio;
++
++ DPRINTK("dma_buffer: start=0x%08x fragsz=%d size=%d\n",
++ (int)dma_buffer->start, (int)stream->fragsize,
++ dma_buffer->size);
++
++ DPRINTK
++ ("user_buffer=0x%08x from=0x%08x user_count=%d dma_count=%d\n",
++ (int)user_buffer,
++ (int)dma_buffer->start + stream->fragsize -
++ dma_buffer->size, user_buffer_xfer_count,
++ dma_buffer_xfer_count);
++
++ if (copy_to_user_with_conversion(state,
++ user_buffer,
++ dma_buffer->start +
++ stream->fragsize -
++ dma_buffer->size,
++ user_buffer_xfer_count) <= 0)
++ return -EFAULT;
++
++ dma_buffer->size -= dma_buffer_xfer_count;
++
++ user_buffer += user_buffer_xfer_count;
++ count -= user_buffer_xfer_count;
++
++ /*
++ * Grab data from the current dma buffer
++ */
++ //DPRINTK("Read: read %d bytes from %d. dmabufsize=%d. count=%d\n",
++ // user_buffer_xfer_count, stream->dma_buffer_index,
++ // dma_buffer->size, count);
++
++ /*
++ * If there's still data in this buffer to be read, release
++ * the semiphore and don't give it back yet. We may come back
++ * and read from it in a minute when the app calls for another read.
++ */
++ if (dma_buffer->size > 0)
++ break;
++
++ /* Make current dma buffer available for DMA again */
++ dma_buffer->owner = 1;
++ DMA_ADD_BUFFER(stream->dmahandles[0], /* dma instance */
++ (unsigned int)dma_buffer->dma_addr, /* source */
++ 0, /* dest */
++ stream->fragsize, /* size */
++ 0, /* the last chunk? */
++ (unsigned int)dma_buffer); /* buf id */
++
++ NEXT_BUF(stream, dma_buffer);
++ }
++
++ if ((int)user_buffer - (int)user_buffer_start)
++ ret = (int)user_buffer - (int)user_buffer_start;
++
++ //DPRINTK("EP93xx - audio_read: return=%d\n", ret);
++
++ return ret;
++}
++
++static int audio_mmap(struct file *file, struct vm_area_struct *vma)
++{
++ struct audio_state_t *state =
++ (struct audio_state_t *)file->private_data;
++ struct audio_stream_t *stream = 0;
++ unsigned long size, vma_addr;
++ int i, ret;
++
++ if (vma->vm_pgoff != 0)
++ return -EINVAL;
++
++ if (vma->vm_flags & VM_WRITE) {
++ if (!state->wr_ref)
++ return -EINVAL;
++
++ stream = state->output_stream;
++ } else if (vma->vm_flags & VM_READ) {
++ if (!state->rd_ref)
++ return -EINVAL;
++
++ stream = state->input_stream;
++ } else {
++ return -EINVAL;
++ }
++
++ if (stream->mapped)
++ return -EINVAL;
++
++ size = vma->vm_end - vma->vm_start;
++
++ if (size != stream->fragsize * stream->nbfrags)
++ return -EINVAL;
++
++ if (!stream->buffers && audio_allocate_buffers(state, stream))
++ return -ENOMEM;
++
++ vma_addr = vma->vm_start;
++
++ for (i = 0; i < stream->nbfrags; i++) {
++ struct audio_buf_t *dma_buffer = &stream->buffers[i];
++
++ if (!dma_buffer->master) {
++ continue;
++ }
++ // KERNEL2.4
++ //ret = remap_page_range(vma_addr, dma_buffer->dma_addr, dma_buffer->master, vma->vm_page_prot);
++ ret =
++ remap_pfn_range(vma, vma_addr, dma_buffer->dma_addr,
++ dma_buffer->master, vma->vm_page_prot);
++
++ if (ret)
++ return ret;
++
++ vma_addr += dma_buffer->master;
++ }
++
++ stream->mapped = 1;
++
++ return 0;
++}
++
++static unsigned int audio_poll(struct file *file,
++ struct poll_table_struct *wait)
++{
++ struct audio_state_t *state =
++ (struct audio_state_t *)file->private_data;
++ struct audio_stream_t *is = state->input_stream;
++ struct audio_stream_t *os = state->output_stream;
++ unsigned int mask = 0;
++ int i;
++
++ DPRINTK("EP93xx - audio_poll(): mode=%s%s\n",
++ (file->f_mode & FMODE_READ) ? "r" : "",
++ (file->f_mode & FMODE_WRITE) ? "w" : "");
++
++ if (file->f_mode & FMODE_READ) {
++ /* Start audio input if not already active */
++ if (!is->active) {
++ if (!is->buffers && audio_allocate_buffers(state, is))
++ return -ENOMEM;
++
++ audio_prime_dma(state, is);
++ }
++
++ poll_wait(file, &is->wq, wait);
++ }
++
++ if (file->f_mode & FMODE_WRITE) {
++ if (!os->buffers && audio_allocate_buffers(state, os))
++ return -ENOMEM;
++
++ poll_wait(file, &os->wq, wait);
++ }
++
++ if (file->f_mode & FMODE_READ) {
++ if (is->mapped) {
++ /*
++ * if the buffer is mapped assume we care that there are
++ * more bytes available than when we last asked using
++ * SNDCTL_DSP_GETxPTR
++ */
++ if (is->bytecount != is->getptrCount)
++ mask |= POLLIN | POLLRDNORM;
++ } else {
++ for (i = 0; i < is->nbfrags; i++) {
++ if (is->buffers[i].owner != 0) {
++ mask |= POLLIN | POLLRDNORM;
++ break;
++ }
++ }
++ }
++ }
++
++ if (file->f_mode & FMODE_WRITE) {
++ if (os->mapped) {
++ if (os->bytecount != os->getptrCount)
++ mask |= POLLOUT | POLLWRNORM;
++ } else {
++ for (i = 0; i < os->nbfrags; i++) {
++ if (os->buffers[i].owner != 0) {
++ mask |= POLLOUT | POLLWRNORM;
++ break;
++ }
++ }
++ }
++ }
++
++ DPRINTK("EP93xx - audio_poll() returned mask of %s%s\n",
++ (mask & POLLIN) ? "r" : "", (mask & POLLOUT) ? "w" : "");
++
++ return mask;
++}
++
++/*
++ * audio_set_fragments
++ *
++ * Used to process SNDCTL_DSP_SETFRAGMENT.
++ *
++ * Argument is 0xMMMMSSSS where:
++ * MMMM sets number of fragments.
++ * SSSS sets dma fragment (dma_buffer) size. size = 2^SSSS bytes
++ */
++static int audio_set_fragments(struct audio_state_t *state,
++ struct audio_stream_t *stream, int val)
++{
++ if (stream->active)
++ return -EBUSY;
++
++ stream->requested_fragsize = 1 << (val & 0x000ffff);
++ stream->requested_nbfrags = (val >> 16) & 0x7FFF;
++
++ return 0;
++}
++
++static void print_audio_format(long format)
++{
++ switch (format) {
++ case AFMT_U8:
++ DPRINTK_IOCTL("AFMT_U8\n");
++ break;
++
++ case AFMT_S8:
++ DPRINTK_IOCTL("AFMT_S8\n");
++ break;
++
++ case AFMT_S32_BLOCKED:
++ DPRINTK_IOCTL("AFMT_S32_BLOCKED\n");
++ break;
++
++ case AFMT_S16_LE:
++ DPRINTK_IOCTL("AFMT_S16_LE\n");
++ break;
++
++ case AFMT_S16_BE:
++ DPRINTK_IOCTL("AFMT_S16_BE\n");
++ break;
++
++ case AFMT_U16_LE:
++ DPRINTK_IOCTL("AFMT_U16_LE\n");
++ break;
++
++ case AFMT_U16_BE:
++ default:
++ DPRINTK_IOCTL("AFMT_U16_BE\n");
++ break;
++ }
++}
++
++/*
++ * We convert to 24 bit samples that occupy 32 bits each.
++ * Formats we support:
++ *
++ * AFMT_U8
++ * AFMT_S16_LE Little endian signed 16
++ * AFMT_S8
++ * AFMT_U16_LE Little endian U16
++ * AFMT_S32_BLOCKED 32 bit little endian format, taken from the rme96xx driver.
++ *
++ */
++static long audio_set_format(struct audio_stream_t *stream, long val)
++{
++ DPRINTK_IOCTL("audio_set_format enter. Format requested (%d) ",
++ (int)val);
++ print_audio_format(val);
++
++ switch (val) {
++ case AFMT_QUERY:
++ break;
++
++ case AFMT_U8:
++ stream->audio_format = val;
++ stream->audio_stream_bitwidth = 8;
++ break;
++
++ case AFMT_S8:
++ stream->audio_format = val;
++ stream->audio_stream_bitwidth = 8;
++ break;
++
++ case AFMT_S32_BLOCKED:
++ stream->audio_format = val;
++ stream->audio_stream_bitwidth = 32;
++ break;
++
++ case AFMT_S16_LE:
++ case AFMT_S16_BE:
++ stream->audio_format = AFMT_S16_LE;
++ stream->audio_stream_bitwidth = 16;
++ break;
++
++ case AFMT_U16_LE:
++ case AFMT_U16_BE:
++ default:
++ stream->audio_format = AFMT_U16_LE;
++ stream->audio_stream_bitwidth = 16;
++ break;
++ }
++
++ DPRINTK_IOCTL("audio_set_format EXIT format set to be (%d) ",
++ (int)stream->audio_format);
++ print_audio_format((long)stream->audio_format);
++
++ return stream->audio_format;
++}
++
++static __inline__ unsigned long copy_to_user_U16_LE_CM
++ (struct audio_state_t *state,
++ const char *to, const char *from, unsigned long to_count) {
++ int total_to_count = to_count;
++ unsigned short *user_ptr = (unsigned short *)to; /* 16 bit user buffer */
++ short *dma_ptr = (short *)from;
++ short right, left;
++
++ /*
++ * Compact mode - left is the lower 16 bits. right is the upper 16 bits.
++ */
++
++ if (state->input_stream->audio_num_channels != 1) {
++ while (to_count > 0) {
++ right = *dma_ptr++;
++ left = *dma_ptr++;
++ __put_user(left ^ 0x8000, user_ptr++);
++ __put_user(right ^ 0x8000, user_ptr++);
++ to_count -= 4;
++ }
++ } else {
++ while (to_count > 0) {
++ dma_ptr++; /* skip right channel sample */
++ left = *dma_ptr++;
++ __put_user(left ^ 0x8000, user_ptr++);
++ to_count -= 2;
++ }
++ }
++
++ return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U16_LE
++ (struct audio_state_t *state,
++ const char *to, const char *from, unsigned long to_count) {
++ int total_to_count = to_count;
++ short *user_ptr = (short *)to; /* 16 bit user buffer */
++ int *dma_ptr = (int *)from; /* 32 bit dma buffer */
++
++ int shift = state->input_stream->hw_bit_width - 16;
++
++ if (state->input_stream->audio_num_channels != 1) {
++ while (to_count > 0) {
++ __put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000,
++ user_ptr++);
++ __put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000,
++ user_ptr++);
++ to_count -= 4;
++ }
++ } else {
++ while (to_count > 0) {
++ __put_user(((short)((*dma_ptr++) >> shift)) ^ 0x8000,
++ user_ptr++);
++ dma_ptr++; /* skip right channel sample */
++ to_count -= 2;
++ }
++ }
++
++ return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_S16_LE_CM
++ (struct audio_state_t *state,
++ const char *to, const char *from, unsigned long to_count) {
++ int total_to_count = to_count;
++ short *user_ptr = (short *)to; /* 16 bit user buffer */
++ short *dma_ptr = (short *)from;
++ short left, right;
++
++ /*
++ * Compact mode - left is the lower 16 bits. right is the upper 16 bits.
++ */
++
++ if (state->input_stream->audio_num_channels != 1) {
++ while (to_count > 0) {
++ right = *dma_ptr++;
++ left = *dma_ptr++;
++ __put_user(left, user_ptr++);
++ __put_user(right, user_ptr++);
++ to_count -= 4;
++ }
++ } else {
++ while (to_count > 0) {
++ dma_ptr++; /* skip right sample */
++ left = *dma_ptr++;
++ __put_user(left, user_ptr++);
++ to_count -= 2;
++ }
++ }
++
++ return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_S16_LE
++ (struct audio_state_t *state,
++ const char *to, const char *from, unsigned long to_count) {
++ int total_to_count = to_count;
++ short *user_ptr = (short *)to; /* 16 bit user buffer */
++ int *dma_ptr = (int *)from; /* 32 bit dma buffer */
++
++ int shift = state->input_stream->hw_bit_width - 16;
++
++ if (state->input_stream->audio_num_channels != 1) {
++ while (to_count > 0) {
++ __put_user((short)((*dma_ptr++) >> shift), user_ptr++);
++ __put_user((short)((*dma_ptr++) >> shift), user_ptr++);
++ to_count -= 4;
++ }
++ } else {
++ while (to_count > 0) {
++ __put_user((short)((*dma_ptr++) >> shift), user_ptr++);
++ dma_ptr++; /* skip right channel sample */
++ to_count -= 2;
++ }
++ }
++
++ return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_S8_CM
++ (struct audio_state_t *state,
++ const char *to, const char *from, unsigned long to_count) {
++ int total_to_count = to_count;
++ char *user_ptr = (char *)to; /* 8 bit user buffer */
++ unsigned short *dma_ptr = (unsigned short *)from; /* 16 bit dma buffer */
++ char right, left;
++
++ if (state->input_stream->audio_num_channels != 1) {
++ while (to_count > 0) {
++ right = ((char)(*dma_ptr++ >> 8));
++ left = ((char)(*dma_ptr++ >> 8));
++ __put_user(left, user_ptr++);
++ __put_user(right, user_ptr++);
++ to_count -= 2;
++ }
++ } else {
++ while (to_count > 0) {
++ dma_ptr++; /* skip right channel sample */
++ left = ((char)(*dma_ptr++ >> 8));
++ __put_user(left, user_ptr++);
++ to_count--;
++ }
++ }
++
++ return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_S8
++ (struct audio_state_t *state,
++ const char *to, const char *from, unsigned long to_count) {
++ int total_to_count = to_count;
++ char *user_ptr = (char *)to; /* 8 bit user buffer */
++ int *dma_ptr = (int *)from; /* 32 bit dma buffer */
++
++ int shift = state->input_stream->hw_bit_width - 8;
++
++ if (state->input_stream->audio_num_channels != 1) {
++ while (to_count > 0) {
++ __put_user((char)((*dma_ptr++) >> shift), user_ptr++);
++ __put_user((char)((*dma_ptr++) >> shift), user_ptr++);
++ to_count -= 2;
++ }
++ } else {
++ while (to_count > 0) {
++ __put_user((char)((*dma_ptr++) >> shift), user_ptr++);
++ dma_ptr++; /* skip right channel sample */
++ to_count--;
++ }
++ }
++
++ return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U8_CM
++ (struct audio_state_t *state,
++ const char *to, const char *from, unsigned long to_count) {
++ int total_to_count = to_count;
++ char *user_ptr = (char *)to; /* 8 bit user buffer */
++ unsigned short *dma_ptr = (unsigned short *)from; /* 16 bit dma buffer */
++ char right, left;
++
++ if (state->input_stream->audio_num_channels != 1) {
++ while (to_count > 0) {
++ right = ((char)(*dma_ptr++ >> 8)) ^ 0x80;
++ left = ((char)(*dma_ptr++ >> 8)) ^ 0x80;
++ __put_user(left, user_ptr++);
++ __put_user(right, user_ptr++);
++ to_count -= 2;
++ }
++ } else {
++ while (to_count > 0) {
++ dma_ptr++; /* skip right channel sample */
++ left = ((char)(*dma_ptr++ >> 8)) ^ 0x80;
++ __put_user(left, user_ptr++);
++ to_count--;
++ }
++ }
++
++ return total_to_count;
++}
++
++static __inline__ unsigned long copy_to_user_U8
++ (struct audio_state_t *state,
++ const char *to, const char *from, unsigned long to_count) {
++ int total_to_count = to_count;
++ char *user_ptr = (char *)to; /* 8 bit user buffer */
++ int *dma_ptr = (int *)from; /* 32 bit dma buffer */
++
++ int shift = state->input_stream->hw_bit_width - 8;
++
++ if (state->input_stream->audio_num_channels != 1) {
++ while (to_count > 0) {
++ __put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80,
++ user_ptr++);
++ __put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80,
++ user_ptr++);
++ to_count -= 2;
++ }
++ } else {
++ while (to_count > 0) {
++ __put_user(((char)((*dma_ptr++) >> shift)) ^ 0x80,
++ user_ptr++);
++ dma_ptr++; /* skip right channel sample */
++ to_count--;
++ }
++ }
++
++ return total_to_count;
++}
++
++/*
++ * Returns negative for error
++ * Returns # of bytes transferred out of the from buffer
++ * for success.
++ */
++static __inline__ int copy_to_user_with_conversion
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount) {
++ int ret = 0;
++
++ if (toCount == 0) {
++ DPRINTK("copy_to_user_with_conversion - nothing to copy!\n");
++ }
++
++ /*
++ * Compact Mode means that each 32 bit word has both the
++ * left and right sample in it.
++ */
++ if (state->input_stream->bCompactMode) {
++ switch (state->input_stream->audio_format) {
++ case AFMT_U8:
++ ret = copy_to_user_U8_CM(state, to, from, toCount);
++ break;
++
++ case AFMT_S16_LE:
++ ret = copy_to_user_S16_LE_CM(state, to, from, toCount);
++ break;
++
++ case AFMT_S8:
++ ret = copy_to_user_S8_CM(state, to, from, toCount);
++ break;
++
++ case AFMT_U16_LE:
++ ret = copy_to_user_U16_LE_CM(state, to, from, toCount);
++ break;
++
++ case AFMT_S32_BLOCKED:
++ default:
++ break;
++ }
++ } else {
++ switch (state->input_stream->audio_format) {
++ case AFMT_U8:
++ ret = copy_to_user_U8(state, to, from, toCount);
++ break;
++
++ case AFMT_S16_LE:
++ ret = copy_to_user_S16_LE(state, to, from, toCount);
++ break;
++
++ case AFMT_S8:
++ ret = copy_to_user_S8(state, to, from, toCount);
++ break;
++
++ case AFMT_U16_LE:
++ ret = copy_to_user_U16_LE(state, to, from, toCount);
++ break;
++
++ case AFMT_S32_BLOCKED:
++ default:
++ __copy_to_user((char *)to, from, toCount);
++ ret = toCount;
++ break;
++ }
++ }
++
++ return ret;
++}
++
++static __inline__ int copy_from_user_U16_LE_CM
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount) {
++ unsigned short *dma_buffer = (unsigned short *)to;
++ unsigned short *user_buffer = (unsigned short *)from;
++ unsigned short data;
++
++ int toCount0 = toCount;
++ int mono = (state->output_stream->audio_num_channels == 1);
++
++ /*
++ * Compact mode - left is the lower 16 bits. right is the upper 16 bits.
++ */
++
++ if (!mono) {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = data ^ 0x8000;
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = data ^ 0x8000;
++ toCount -= 4;
++ }
++ } else {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ data = data ^ 0x8000;
++ *dma_buffer++ = data;
++ *dma_buffer++ = data;
++ toCount -= 4;
++ }
++ }
++
++ /*
++ * Each mono or stereo 16 bit sample going in results
++ * in one stereo 32 bit sample going out. So
++ * mono = (2 bytes in)/(4 bytes out)
++ * stereo = (4 bytes in)/(4 bytes out)
++ */
++ if (mono) {
++ return toCount0 / 2;
++ }
++
++ return toCount0;
++}
++
++static __inline__ int copy_from_user_U16_LE
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount) {
++ int *dma_buffer = (int *)to;
++ int val;
++ unsigned short *user_buffer = (unsigned short *)from;
++ unsigned short data;
++
++ int toCount0 = toCount;
++ int mono = (state->output_stream->audio_num_channels == 1);
++ int shift = state->output_stream->hw_bit_width - 16;
++
++ if (!mono) {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = ((unsigned int)data ^ 0x8000) << shift;
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = ((unsigned int)data ^ 0x8000) << shift;
++ toCount -= 8;
++ }
++ } else {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ val = ((unsigned int)data ^ 0x8000) << shift;
++ *dma_buffer++ = val;
++ *dma_buffer++ = val;
++ toCount -= 8;
++ }
++ }
++
++ /*
++ * Each mono or stereo 16 bit sample going in results
++ * in a two 32 bit (left & right) samples going out. So
++ * mono = (2 bytes in)/(8 bytes out)
++ * stereo = (4 bytes in)/(8 bytes out)
++ */
++ if (mono)
++ return toCount0 / 4;
++
++ return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_S16_LE_CM
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount) {
++ short *dma_buffer = (short *)to;
++ unsigned short *user_buffer = (unsigned short *)from;
++ unsigned short data;
++
++ int toCount0 = toCount;
++ int mono = (state->output_stream->audio_num_channels == 1);
++
++ /*
++ * Compact mode - left is the lower 16 bits. right is the upper 16 bits.
++ */
++
++ if (!mono) {
++ __copy_from_user((char *)to, from, toCount);
++ } else {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = data;
++ *dma_buffer++ = data;
++ toCount -= 4;
++ }
++ }
++
++ /*
++ * Each mono or stereo 16 bit sample going in results
++ * in one stereo 32 bit sample going out. So
++ * mono = (2 bytes in)/(4 bytes out)
++ * stereo = (4 bytes in)/(4 bytes out)
++ */
++ if (mono)
++ return toCount0 / 2;
++
++ return toCount0;
++}
++
++static __inline__ int copy_from_user_S16_LE
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount) {
++ int *dma_buffer = (int *)to;
++ int val;
++ unsigned short *user_buffer = (unsigned short *)from;
++ unsigned short data;
++
++ int toCount0 = toCount;
++ int mono = (state->output_stream->audio_num_channels == 1);
++ int shift = state->output_stream->hw_bit_width - 16;
++
++ if (!mono) {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = (unsigned int)data << shift;
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = (unsigned int)data << shift;
++ toCount -= 8;
++ }
++ } else {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ val = (unsigned int)data << shift;
++ *dma_buffer++ = val;
++ *dma_buffer++ = val;
++ toCount -= 8;
++ }
++ }
++
++ /*
++ * Each mono or stereo 16 bit sample going in results
++ * in a two 32 bit samples (left & right) going out. So
++ * mono = (2 bytes in)/(8 bytes out)
++ * stereo = (4 bytes in)/(8 bytes out)
++ */
++ if (mono)
++ return toCount0 / 4;
++
++ return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_S8_CM
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount) {
++ short *dma_buffer = (short *)to;
++ short val;
++ unsigned char *user_buffer = (unsigned char *)from;
++ unsigned char data;
++
++ int toCount0 = toCount;
++ int mono = (state->output_stream->audio_num_channels == 1);
++
++ /*
++ * Compact mode - left is the lower 16 bits. right is the upper 16 bits.
++ */
++
++ if (!mono) {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = (unsigned short)data << 8;
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = (unsigned short)data << 8;
++ toCount -= 4;
++ }
++ } else {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ val = (unsigned short)data << 8;
++ *dma_buffer++ = val;
++ *dma_buffer++ = val;
++ toCount -= 4;
++ }
++ }
++
++ /*
++ * Each mono or stereo 8 bit sample going in results
++ * in one stereo 32 bit sample going out. So
++ * mono = (1 byte in)/(4 bytes out)
++ * stereo = (2 bytes in)/(4 bytes out)
++ */
++ if (mono)
++ return toCount0 / 4;
++
++ return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_S8
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount) {
++ int *dma_buffer = (int *)to;
++ int val;
++ unsigned char *user_buffer = (unsigned char *)from;
++ unsigned char data;
++
++ int toCount0 = toCount;
++ int mono = (state->output_stream->audio_num_channels == 1);
++ int shift = state->output_stream->hw_bit_width - 8;
++
++ if (!mono) {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = (unsigned int)data << shift;
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = (unsigned int)data << shift;
++ toCount -= 8;
++ }
++ } else {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ val = (unsigned int)data << shift;
++ *dma_buffer++ = val;
++ *dma_buffer++ = val;
++ toCount -= 8;
++ }
++ }
++
++ /*
++ * Each mono or stereo 8 bit sample going in results
++ * in a two 32 bit samples (left & right) going out. So
++ * mono = (1 byte in)/(8 bytes out)
++ * stereo = (2 bytes in)/(8 bytes out)
++ */
++ if (mono)
++ return toCount0 / 8;
++
++ return toCount0 / 4;
++}
++
++static __inline__ int copy_from_user_U8_CM
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount) {
++ unsigned short *dma_buffer = (unsigned short *)to;
++ unsigned short val;
++ unsigned char *user_buffer = (unsigned char *)from;
++ unsigned char data;
++
++ int toCount0 = toCount;
++ int mono = (state->output_stream->audio_num_channels == 1);
++
++ if (!mono) {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = ((unsigned short)data ^ 0x80) << 8;
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = ((unsigned short)data ^ 0x80) << 8;
++ toCount -= 4;
++ }
++ } else {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ val = ((unsigned short)data ^ 0x80) << 8;
++ *dma_buffer++ = val;
++ *dma_buffer++ = val;
++ toCount -= 4;
++ }
++ }
++
++ /*
++ * Each mono or stereo 8 bit sample going in results
++ * in one stereo 32 bit sample going out. So
++ * mono = (1 byte in)/(4 bytes out)
++ * stereo = (2 bytes in)/(4 bytes out)
++ */
++ if (mono)
++ return toCount0 / 4;
++
++ return toCount0 / 2;
++}
++
++static __inline__ int copy_from_user_U8
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount) {
++ unsigned int *dma_buffer = (unsigned int *)to;
++ unsigned int val;
++ unsigned char *user_buffer = (unsigned char *)from;
++ unsigned char data;
++
++ int toCount0 = toCount;
++ int mono = (state->output_stream->audio_num_channels == 1);
++ int shift = state->output_stream->hw_bit_width - 8;
++
++ if (!mono) {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = ((unsigned int)data ^ 0x80) << shift;
++ __get_user(data, user_buffer++);
++ *dma_buffer++ = ((unsigned int)data ^ 0x80) << shift;
++ toCount -= 8;
++ }
++ } else {
++ while (toCount > 0) {
++ __get_user(data, user_buffer++);
++ val = ((unsigned int)data ^ 0x80) << shift;
++ *dma_buffer++ = val;
++ *dma_buffer++ = val;
++ toCount -= 8;
++ }
++ }
++
++ /*
++ * Each mono or stereo 8 bit sample going in results
++ * in a two 32 bit samples (left & right) going out. So
++ * mono = (1 byte in)/(8 bytes out)
++ * stereo = (2 bytes in)/(8 bytes out)
++ */
++ if (mono)
++ return toCount0 / 8;
++
++ return toCount0 / 4;
++}
++
++/*
++ * Returns negative for error
++ * Returns # of bytes transferred out of the from buffer
++ * for success.
++ */
++static __inline__ int copy_from_user_with_conversion
++ (struct audio_state_t *state,
++ const char *to, const char *from, int toCount) {
++ int ret = 0;
++
++ if (toCount == 0) {
++ DPRINTK("copy_from_user_with_conversion - nothing to copy!\n");
++ }
++
++ /*
++ * Compact Mode means that each 32 bit word has both the
++ * left and right sample in it.
++ */
++ if (state->output_stream->bCompactMode) {
++ switch (state->output_stream->audio_format) {
++ case AFMT_U8:
++ ret = copy_from_user_U8_CM(state, to, from, toCount);
++ break;
++
++ case AFMT_S16_LE:
++ ret =
++ copy_from_user_S16_LE_CM(state, to, from, toCount);
++ break;
++
++ case AFMT_S8:
++ ret = copy_from_user_S8_CM(state, to, from, toCount);
++ break;
++
++ case AFMT_U16_LE:
++ ret =
++ copy_from_user_U16_LE_CM(state, to, from, toCount);
++ break;
++
++ case AFMT_S32_BLOCKED:
++ default:
++ break;
++ }
++ } else {
++ switch (state->output_stream->audio_format) {
++ case AFMT_U8:
++ ret = copy_from_user_U8(state, to, from, toCount);
++ break;
++
++ case AFMT_S16_LE:
++ ret = copy_from_user_S16_LE(state, to, from, toCount);
++ break;
++
++ case AFMT_S8:
++ ret = copy_from_user_S8(state, to, from, toCount);
++ break;
++
++ case AFMT_U16_LE:
++ ret = copy_from_user_U16_LE(state, to, from, toCount);
++ break;
++
++ case AFMT_S32_BLOCKED:
++ default:
++ __copy_from_user((char *)to, from, toCount);
++ ret = toCount;
++ break;
++ }
++ }
++
++ return ret;
++}
++
++static int audio_ioctl(struct inode *inode, struct file *file,
++ uint cmd, ulong arg)
++{
++ struct audio_state_t *state =
++ (struct audio_state_t *)file->private_data;
++ struct audio_stream_t *os = state->output_stream;
++ struct audio_stream_t *is = state->input_stream;
++ long val = 0;
++
++ switch (cmd) {
++ case SNDCTL_DSP_STEREO:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_STEREO\n");
++ if (get_user(val, (int *)arg) || (val > 1) || (val < 0))
++ return -EFAULT;
++
++ if (file->f_mode & FMODE_WRITE) {
++ if (os->audio_num_channels != (val + 1)) {
++ os->audio_num_channels = val + 1;
++ calculate_dma2usr_ratio_etc(os);
++ }
++ }
++
++ if (file->f_mode & FMODE_READ) {
++ if (is->audio_num_channels != (val + 1)) {
++ is->audio_num_channels = val + 1;
++ calculate_dma2usr_ratio_etc(is);
++ }
++ }
++
++ return put_user(val, (long *)arg);
++
++ case SNDCTL_DSP_CHANNELS:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_CHANNELS\n");
++ if (get_user(val, (int *)arg) || (val > 2) || (val < 0))
++ return -EFAULT;
++
++ // Calling with value of 0 is a query.
++ if (val == 0) {
++ if (file->f_mode & FMODE_WRITE)
++ val = os->audio_num_channels;
++ else
++ val = is->audio_num_channels;
++ } else {
++ if (file->f_mode & FMODE_WRITE) {
++ if (os->audio_num_channels != val) {
++ os->audio_num_channels = val;
++ calculate_dma2usr_ratio_etc(os);
++ }
++ }
++ if (file->f_mode & FMODE_READ) {
++ if (is->audio_num_channels != val) {
++ is->audio_num_channels = val;
++ calculate_dma2usr_ratio_etc(is);
++ }
++ }
++ }
++
++ return put_user(val, (long *)arg);
++
++ case SOUND_PCM_READ_CHANNELS:
++ DPRINTK_IOCTL("audio_ioctl - SOUND_PCM_READ_CHANNELS\n");
++ if (file->f_mode & FMODE_WRITE)
++ val = os->audio_num_channels;
++ else
++ val = is->audio_num_channels;
++ return put_user(val, (long *)arg);
++
++ case SNDCTL_DSP_SETFMT:
++ {
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETFMT\n");
++
++ if (get_user(val, (int *)arg))
++ return -EFAULT;
++
++ if (val != AFMT_QUERY) {
++ if ((file->f_mode & FMODE_WRITE)
++ && (val != os->audio_format)) {
++ audio_set_format(os, val);
++ calculate_dma2usr_ratio_etc(os);
++ if (state->hw->set_hw_serial_format)
++ state->hw->
++ set_hw_serial_format(os,
++ val);
++ }
++ if ((file->f_mode & FMODE_READ)
++ && (val != is->audio_format)) {
++ audio_set_format(is, val);
++ calculate_dma2usr_ratio_etc(is);
++ if (state->hw->set_hw_serial_format)
++ state->hw->
++ set_hw_serial_format(is,
++ val);
++ }
++ }
++
++ if (file->f_mode & FMODE_WRITE)
++ return put_user(os->audio_format, (long *)arg);
++ return put_user(is->audio_format, (long *)arg);
++ }
++
++ case SNDCTL_DSP_GETFMTS:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETFMTS\n");
++ return put_user((AFMT_U8 | AFMT_S8 | AFMT_S16_LE | AFMT_U16_LE),
++ (long *)arg);
++
++ case OSS_GETVERSION:
++ DPRINTK_IOCTL("audio_ioctl - OSS_GETVERSION\n");
++ return put_user(SOUND_VERSION, (int *)arg);
++
++ case SNDCTL_DSP_GETBLKSIZE:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETBLKSIZE\n");
++ if (file->f_mode & FMODE_WRITE)
++ return put_user(os->fragsize, (int *)arg);
++ return put_user(is->fragsize, (int *)arg);
++
++ case SNDCTL_DSP_GETCAPS:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETCAPS\n");
++ val = DSP_CAP_REALTIME | DSP_CAP_TRIGGER | DSP_CAP_MMAP;
++ if (is && os)
++ val |= DSP_CAP_DUPLEX;
++ return put_user(val, (int *)arg);
++
++ case SNDCTL_DSP_SETFRAGMENT:
++ {
++ int ret;
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETFRAGMENT\n");
++ if (get_user(val, (long *)arg))
++ return -EFAULT;
++
++ if (file->f_mode & FMODE_READ) {
++ ret = audio_set_fragments(state, is, val);
++ if (ret < 0)
++ return ret;
++ }
++
++ if (file->f_mode & FMODE_WRITE) {
++ ret = audio_set_fragments(state, os, val);
++ if (ret < 0)
++ return ret;
++ }
++
++ return 0;
++ }
++
++ case SNDCTL_DSP_SYNC:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SYNC\n");
++ return audio_sync(file);
++
++ case SNDCTL_DSP_SETDUPLEX:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETDUPLEX\n");
++ return 0;
++
++ case SNDCTL_DSP_POST:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_POST\n");
++ return 0;
++
++ case SNDCTL_DSP_GETTRIGGER:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETTRIGGER\n");
++ val = 0;
++
++ if (file->f_mode & FMODE_READ && is->active && !is->stopped)
++ val |= PCM_ENABLE_INPUT;
++
++ if (file->f_mode & FMODE_WRITE && os->active && !os->stopped)
++ val |= PCM_ENABLE_OUTPUT;
++
++ return put_user(val, (int *)arg);
++
++ case SNDCTL_DSP_SETTRIGGER:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_SETTRIGGER\n");
++ if (get_user(val, (int *)arg))
++ return -EFAULT;
++
++ if (file->f_mode & FMODE_READ) {
++ if (val & PCM_ENABLE_INPUT) {
++ if (!is->active) {
++ if (!is->buffers
++ && audio_allocate_buffers(state,
++ is))
++ return -ENOMEM;
++ audio_prime_dma(state, is);
++ }
++
++ if (is->stopped) {
++ is->stopped = 0;
++ os->active = 1;
++ audio_dma_start(state, is);
++ }
++ } else {
++ audio_dma_pause(state, is);
++ is->stopped = 1;
++ is->active = 0;
++ }
++ }
++
++ if (file->f_mode & FMODE_WRITE) {
++ if (val & PCM_ENABLE_OUTPUT) {
++ if (!os->active) {
++ if (!os->buffers
++ && audio_allocate_buffers(state,
++ os))
++ return -ENOMEM;
++
++ if (os->mapped)
++ audio_prime_dma(state, os);
++ }
++
++ if (os->stopped) {
++ os->stopped = 0;
++ os->active = 1;
++ audio_dma_start(state, os);
++ }
++ } else {
++ audio_dma_pause(state, os);
++ os->stopped = 1;
++ os->active = 0;
++ }
++ }
++ return 0;
++
++ case SNDCTL_DSP_GETOPTR:
++ case SNDCTL_DSP_GETIPTR:
++ {
++ count_info inf = { 0, };
++ struct audio_stream_t *stream =
++ (cmd == SNDCTL_DSP_GETOPTR) ? os : is;
++ int bytecount, fragcount, buf_num = 0;
++ unsigned int current_frac, buf_id;
++ // KERNEL2.4 SNIP
++ unsigned long flags;
++ unsigned int total = 0;
++ // KERNEL2.4 SNAP
++
++ DPRINTK_IOCTL
++ ("audio_ioctl - called SNDCTL_DSP_GETOPTR.\n");
++
++ if ((stream == is && !(file->f_mode & FMODE_READ)) ||
++ (stream == os && !(file->f_mode & FMODE_WRITE)))
++ return -EINVAL;
++
++ if (!stream->active)
++ return copy_to_user((void *)arg, &inf,
++ sizeof(inf));
++
++ // KERNEL2.4
++ //save_flags_cli(flags);
++ local_irq_save(flags);
++
++ // KERNEL2.4
++ //DMA_GET_POSITION( stream->dmahandles[0], &buf_id, 0,
++ // &current_frac );
++ DMA_GET_POSITION(stream->dmahandles[0], &buf_id, &total,
++ &current_frac);
++
++ /*
++ * Out of a set of nbfrags buffers, which one is the current one?
++ */
++ if (buf_id)
++ buf_num = ((struct audio_buf_t *)buf_id)->num;
++
++ /*
++ * The ep93xx-audio ISRs keep track of bytecount and fragcount.
++ * This bytecount isn't cleared except when the driver is opened
++ * or when it overflows.
++ */
++ bytecount = stream->bytecount;
++
++ /* so poll can tell if it changes */
++ stream->getptrCount = stream->bytecount;
++
++ /*
++ * Return the number of fragment transitions counted in our dma ISR
++ * since the previous call to this ioctl, then clear that counter.
++ */
++ fragcount = stream->fragcount;
++ stream->fragcount = 0;
++
++ // KERNEL2.4
++ //restore_flags(flags);
++ local_irq_restore(flags);
++
++ /*
++ * When reporting position to user app, scale byte counts and the
++ * ptr to reflect the difference in sample size between dma samples
++ * and user samples. But don't scale the # of fragments.
++ */
++ inf.blocks = fragcount;
++ inf.bytes =
++ (bytecount + current_frac) / stream->dma2usr_ratio;
++ inf.ptr =
++ ((buf_num * stream->fragsize) +
++ current_frac) / stream->dma2usr_ratio;
++
++ return copy_to_user((void *)arg, &inf, sizeof(inf));
++ }
++
++ case SNDCTL_DSP_GETODELAY:
++ {
++ int buffered_bytes_left, count;
++ //unsigned int current_frac;
++ // KERNEL2.4 SNIP
++ unsigned int current_frac = 0;
++ unsigned long flags;
++ unsigned int total = 0, buf_id = 0;
++ // KERNEL2.4SNAP
++
++ if (!(file->f_mode & FMODE_WRITE))
++ return -EINVAL;
++
++ DPRINTK_IOCTL
++ ("audio_ioctl - called SNDCTL_DSP_GETODELAY.\n");
++
++ // KERNEL2.4
++ //save_flags_cli(flags);
++ local_irq_save(flags);
++
++ // KERNEL2.4
++ //DMA_GET_POSITION( os->dmahandles[0], 0, 0, &current_frac );
++ DMA_GET_POSITION(os->dmahandles[0], &buf_id, &total,
++ &current_frac);
++
++ buffered_bytes_left = os->buffered_bytes_to_play;
++
++ // KERNEL2.4
++ //restore_flags(flags);
++ local_irq_restore(flags);
++
++ count =
++ (buffered_bytes_left -
++ current_frac) / os->dma2usr_ratio;
++
++ return put_user(count, (int *)arg);
++ }
++
++ case SNDCTL_DSP_GETOSPACE:
++ {
++ /*
++ * It looks like this code is assuming that nobody
++ * is writing the device while calling this ioctl
++ * which may be a reasonable assumption. I hope.
++ * Maybe.
++ */
++ audio_buf_info inf = { 0, };
++ int i;
++
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETOSPACE\n");
++
++ if (!(file->f_mode & FMODE_WRITE))
++ return -EINVAL;
++ if (!os->buffers && audio_allocate_buffers(state, os))
++ return -ENOMEM;
++
++ for (i = 0; i < os->nbfrags; i++) {
++ /*
++ * If the semaphore is 1, the buffer is available.
++ */
++ if (os->buffers[i].owner != 0) {
++ if (os->buffers[i].size == 0)
++ inf.fragments++;
++
++ inf.bytes +=
++ os->fragsize - os->buffers[i].size;
++ }
++ }
++
++ inf.fragsize = os->fragsize / os->dma2usr_ratio;
++ inf.fragstotal = os->nbfrags;
++ inf.bytes = inf.bytes / os->dma2usr_ratio;
++
++ return copy_to_user((void *)arg, &inf, sizeof(inf));
++ }
++
++ case SNDCTL_DSP_GETISPACE:
++ {
++ audio_buf_info inf = { 0, };
++ int i;
++
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_GETISPACE\n");
++
++ if (!(file->f_mode & FMODE_READ))
++ return -EINVAL;
++ if (!is->buffers && audio_allocate_buffers(state, is))
++ return -ENOMEM;
++
++ for (i = 0; i < is->nbfrags; i++) {
++ if (is->buffers[i].owner != 0) {
++ if (is->buffers[i].size == is->fragsize)
++ inf.fragments++;
++
++ inf.bytes += is->buffers[i].size;
++ }
++ }
++
++ inf.fragsize = is->fragsize / is->dma2usr_ratio;
++ inf.fragstotal = is->nbfrags;
++ inf.bytes = inf.bytes / is->dma2usr_ratio;
++
++ return copy_to_user((void *)arg, &inf, sizeof(inf));
++ }
++
++ case SNDCTL_DSP_NONBLOCK:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_NONBLOCK\n");
++ file->f_flags |= O_NONBLOCK;
++ return 0;
++
++ case SNDCTL_DSP_RESET:
++ DPRINTK_IOCTL("audio_ioctl - SNDCTL_DSP_RESET\n");
++ if (file->f_mode & FMODE_READ)
++ audio_reset_buffers(state, is);
++ if (file->f_mode & FMODE_WRITE)
++ audio_reset_buffers(state, os);
++ return 0;
++
++ default:
++ /*
++ * Let the client of this module handle the
++ * non generic ioctls
++ */
++ return state->hw->client_ioctl(inode, file, cmd, arg);
++ }
++
++ return 0;
++}
++
++static int audio_release(struct inode *inode, struct file *file)
++{
++ struct audio_state_t *state =
++ (struct audio_state_t *)file->private_data;
++ int i;
++
++ DPRINTK("EP93xx - audio_release -- enter. Write=%d Read=%d\n",
++ ((file->f_mode & FMODE_WRITE) != 0),
++ ((file->f_mode & FMODE_READ) != 0));
++
++ down(&state->sem);
++
++ if (file->f_mode & FMODE_READ) {
++ audio_deallocate_buffers(state, state->input_stream);
++
++ for (i = 0; i < state->input_stream->NumDmaChannels; i++)
++ DMA_FREE(state->input_stream->dmahandles[i]);
++
++ state->rd_ref = 0;
++ }
++
++ if (file->f_mode & FMODE_WRITE) {
++ /*
++ * Wait for all our buffers to play.
++ */
++ audio_sync(file);
++
++ /*
++ * audio_deallocate_buffers will pause and flush the dma
++ * then deallocate the buffers.
++ */
++ audio_deallocate_buffers(state, state->output_stream);
++ for (i = 0; i < state->output_stream->NumDmaChannels; i++)
++ DMA_FREE(state->output_stream->dmahandles[i]);
++
++ state->wr_ref = 0;
++ }
++
++ up(&state->sem);
++
++ DPRINTK("EP93xx - audio_release -- EXIT\n");
++
++ return 0;
++}
++
++/*
++ * ep93xx_clear_stream_struct
++ *
++ * Initialize stuff or at least clear it to zero for a stream structure.
++ */
++static void ep93xx_clear_stream_struct(struct audio_stream_t *stream)
++{
++
++ stream->dmahandles[0] = 0; /* handles for dma driver instances */
++ stream->dmahandles[1] = 0; /* handles for dma driver instances */
++ stream->dmahandles[2] = 0; /* handles for dma driver instances */
++ stream->NumDmaChannels = 0; /* 1, 2, or 3 DMA channels */
++ stream->TX_dma_ch_bitfield = 0; /* which dma channels used for strm */
++ stream->RX_dma_ch_bitfield = 0; /* which dma channels used for strm */
++ stream->buffers = 0; /* array of audio buffer structures */
++ stream->dma_buffer = 0; /* current buffer used by read/write */
++ stream->dma_buffer_index = 0; /* index for the pointer above... */
++ stream->fragsize = AUDIO_FRAGSIZE_DEFAULT; /* fragment i.e. buffer size */
++ stream->nbfrags = AUDIO_NBFRAGS_DEFAULT; /* nbr of fragments i.e. buffers */
++ stream->requested_fragsize = 0; /* This is ignored if 0 */
++ stream->requested_nbfrags = 0; /* This is ignored if 0 */
++ stream->bytecount = 0; /* nbr of processed bytes */
++ stream->getptrCount = 0; /* value of bytecount last time */
++ /* anyone asked via GETxPTR */
++ stream->fragcount = 0; /* nbr of fragment transitions */
++ stream->mapped = 0; /* mmap()'ed buffers */
++ stream->active = 0; /* actually in progress */
++ stream->stopped = 0; /* might be active but stopped */
++ stream->bFirstCaptureBuffer = 1; /* flag meaning there is junk in rx fifo */
++ stream->buffered_bytes_to_play = 0;
++
++ calculate_dma2usr_ratio_etc(stream);
++}
++
++/*
++ * ep93xx_audio_attach
++ *
++ * Initialize the state structure for read or write. Allocate dma channels.
++ * Currently each s is a stereo s (one dma channel).
++ *
++ */
++int ep93xx_audio_attach
++ (struct inode *inode, struct file *file, struct audio_state_t *state) {
++ int err, i;
++ struct audio_stream_t *os = state->output_stream;
++ struct audio_stream_t *is = state->input_stream;
++
++ DPRINTK("ep93xx_audio_attach -- enter. Write=%d Read=%d\n",
++ ((file->f_mode & FMODE_WRITE) != 0),
++ ((file->f_mode & FMODE_READ) != 0));
++
++ down(&state->sem);
++
++ /* access control */
++ if (((file->f_mode & FMODE_WRITE) && !os) ||
++ ((file->f_mode & FMODE_READ) && !is)) {
++ up(&state->sem);
++ return -ENODEV;
++ }
++
++ if (((file->f_mode & FMODE_WRITE) && state->wr_ref) ||
++ ((file->f_mode & FMODE_READ) && state->rd_ref)) {
++ up(&state->sem);
++ return -EBUSY;
++ }
++
++ /*
++ * Request DMA channels
++ */
++ if (file->f_mode & FMODE_WRITE) {
++ DPRINTK("ep93xx_audio_attach -- FMODE_WRITE\n");
++
++ state->wr_ref = 1;
++
++ ep93xx_clear_stream_struct(os);
++
++ err = DMA_REQUEST(&os->dmahandles[0],
++ os->devicename, os->dmachannel[0]);
++ if (err) {
++ up(&state->sem);
++ DPRINTK
++ ("ep93xx_audio_attach -- EXIT ERROR dma request failed\n");
++ return err;
++ }
++
++ err = DMA_CONFIG(os->dmahandles[0],
++ IGNORE_CHANNEL_ERROR,
++ 0, audio_dma_tx_callback, (unsigned int)state);
++ if (err) {
++ DMA_FREE(os->dmahandles[0]);
++ up(&state->sem);
++ DPRINTK
++ ("ep93xx_audio_attach -- EXIT ERROR dma config failed\n");
++ return err;
++ }
++
++ /*
++ * Assuming each audio stream is mono or stereo.
++ */
++ os->NumDmaChannels = 1;
++
++ /*
++ * Automatically set up the bit field of dma channels used for
++ * this stream.
++ */
++ for (i = 0; (i < state->hw->MaxTxDmaChannels); i++) {
++ if (os->dmachannel[i] == state->hw->txdmachannels[0])
++ os->TX_dma_ch_bitfield |= 1;
++
++ if (os->dmachannel[i] == state->hw->txdmachannels[1])
++ os->TX_dma_ch_bitfield |= 2;
++
++ if (os->dmachannel[i] == state->hw->txdmachannels[2])
++ os->TX_dma_ch_bitfield |= 4;
++ }
++
++ DPRINTK("DMA Tx channel bitfield = %x\n",
++ os->TX_dma_ch_bitfield);
++
++ if (state->hw->hw_clear_fifo)
++ state->hw->hw_clear_fifo(os);
++
++ init_waitqueue_head(&os->wq);
++ }
++
++ if (file->f_mode & FMODE_READ) {
++ state->rd_ref = 1;
++
++ ep93xx_clear_stream_struct(is);
++
++ err = DMA_REQUEST(&is->dmahandles[0],
++ is->devicename, is->dmachannel[0]);
++ if (err) {
++ up(&state->sem);
++ DPRINTK
++ ("ep93xx_audio_attach -- EXIT ERROR dma request failed\n");
++ return err;
++ }
++
++ err = DMA_CONFIG(is->dmahandles[0],
++ IGNORE_CHANNEL_ERROR,
++ 0, audio_dma_rx_callback, (unsigned int)state);
++ if (err) {
++ DMA_FREE(is->dmahandles[0]);
++ up(&state->sem);
++ DPRINTK
++ ("ep93xx_audio_attach -- EXIT ERROR dma config failed\n");
++ return err;
++ }
++
++ is->NumDmaChannels = 1;
++
++ /*
++ * Automatically set up the bit field of dma channels used for
++ * this stream.
++ */
++ for (i = 0; (i < state->hw->MaxRxDmaChannels); i++) {
++ if (is->dmachannel[i] == state->hw->rxdmachannels[0])
++ is->RX_dma_ch_bitfield |= 1;
++
++ if (is->dmachannel[i] == state->hw->rxdmachannels[1])
++ is->RX_dma_ch_bitfield |= 2;
++
++ if (is->dmachannel[i] == state->hw->rxdmachannels[2])
++ is->RX_dma_ch_bitfield |= 4;
++ }
++
++ DPRINTK("DMA Rx channel bitfield = %x\n",
++ is->RX_dma_ch_bitfield);
++
++ init_waitqueue_head(&is->wq);
++ }
++
++ /*
++ * Fill out the rest of the file_operations struct.
++ */
++ file->private_data = state;
++ file->f_op->release = audio_release;
++ file->f_op->write = audio_write;
++ file->f_op->read = audio_read;
++ file->f_op->mmap = audio_mmap;
++ file->f_op->poll = audio_poll;
++ file->f_op->ioctl = audio_ioctl;
++ file->f_op->llseek = no_llseek;
++
++ up(&state->sem);
++
++ DPRINTK("ep93xx_audio_attach -- EXIT\n");
++
++ return 0;
++}
++
++EXPORT_SYMBOL(ep93xx_audio_attach);
++
++MODULE_DESCRIPTION("Common audio handling for the Cirrus EP93xx processor");
++MODULE_LICENSE("GPL");
+diff --git a/sound/oss/ep93xx-audio.h b/sound/oss/ep93xx-audio.h
+new file mode 100644
+index 0000000..04a0581
+--- /dev/null
++++ b/sound/oss/ep93xx-audio.h
+@@ -0,0 +1,149 @@
++/*
++ * ep93xx-audio.h
++ *
++ * Common audio handling for the Cirrus Logic EP93xx
++ *
++ * Copyright (c) 2003 Cirrus Logic Corp.
++ * Copyright (c) 2000 Nicolas Pitre <nico@cam.org>
++ *
++ * Taken from sa1100-audio.h
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License.
++ */
++
++/*
++ * Getting this from the rme96xx driver. Has same numerical value
++ * as AC3. Hmmmm.
++ */
++#ifndef AFMT_S32_BLOCKED
++#define AFMT_S32_BLOCKED 0x0000400
++#endif
++
++#define EP93XX_DEFAULT_NUM_CHANNELS 2
++#define EP93XX_DEFAULT_FORMAT AFMT_S16_LE
++#define EP93XX_DEFAULT_BIT_WIDTH 16
++
++/*
++ * Buffer Management
++ */
++
++struct audio_buf_t {
++
++ int size; /* buffer size */
++ int sent; /* indicates that dma has the dma_buffer */
++ char *start; /* points to actual buffer */
++ dma_addr_t dma_addr; /* physical buffer address */
++ int owner;
++ struct semaphore sem; /* down before touching the buffer */
++ int master; /* owner for buffer allocation, */
++ /* contains size when true */
++ int num; /* which out of nbfrags buffers is this? */
++ struct audio_stream_t *stream; /* owning stream */
++
++};
++
++#define MAX_DEVICE_NAME 20
++
++struct audio_stream_t {
++
++ /* dma stuff */
++ int dmahandles[3]; /* handles for dma driver instances */
++ char devicename[MAX_DEVICE_NAME]; /* string - name of device */
++ int NumDmaChannels; /* 1, 2, or 3 DMA channels */
++ ep93xx_dma_dev_t dmachannel[3]; /* dma channel numbers */
++
++ struct audio_buf_t *buffers; /* array of audio buffer structures */
++ struct audio_buf_t *dma_buffer; /* current buffer used by read/write */
++ u_int dma_buffer_index; /* index for the pointer above... */
++
++ u_int fragsize; /* fragment i.e. buffer size */
++ u_int nbfrags; /* nbr of fragments i.e. buffers */
++ u_int requested_fragsize;
++ u_int requested_nbfrags;
++
++ int bytecount; /* nbr of processed bytes */
++ int getptrCount; /* value of bytecount last time */
++ /* anyone asked via GETxPTR */
++ int fragcount; /* nbr of fragment transitions */
++ wait_queue_head_t wq; /* for poll */
++ int mapped:1; /* mmap()'ed buffers */
++ int active:1; /* actually in progress */
++ int stopped:1; /* might be active but stopped */
++ u_int TX_dma_ch_bitfield; /* bit0 = txdma1, bit1= txdma2, etc */
++ u_int RX_dma_ch_bitfield; /* bit0 = rxdma1, bit1= rxdma2, etc */
++ int bFirstCaptureBuffer; /* flag meaning there is junk in rx fifo */
++
++ /*
++ * Data about the file format that we are configured to play.
++ */
++ long audio_num_channels; /* Range: 1 to 6 */
++ long audio_format;
++ long audio_stream_bitwidth; /* Range: 8, 16, 24, 32 */
++
++ long sample_rate; /* Fs in Hz. */
++
++ /*
++ * Data about how the audio controller and codec are set up.
++ */
++ int hw_bit_width; /* width of dac or adc */
++ int bCompactMode; /* set if 32bits == a stereo sample */
++
++ /*
++ * dma2usr_ratio = dma sample size (8 or 4 bytes) / usr sample size (8,4,2,1)
++ */
++ int dma2usr_ratio;
++
++ /*
++ * This provides a way of determining audio playback position that will not
++ * overflow. This is (size of buffers written) - (buffers we've gotten back)
++ */
++ int buffered_bytes_to_play;
++
++};
++
++/*
++ * No matter how many streams are going, we are using one hardware device.
++ * This struct describes that hardware.
++ */
++struct audio_hw_t {
++
++ ep93xx_dma_dev_t txdmachannels[3]; /* all dma channels available for */
++ ep93xx_dma_dev_t rxdmachannels[3]; /* this audio ctrlr */
++
++ int MaxTxDmaChannels; /* number of tx and rx channels */
++ int MaxRxDmaChannels; /* number of tx and rx channels */
++
++ /*
++ * Pointers to init, shutdown, and ioctl functions.
++ */
++ void (*hw_enable) (struct audio_stream_t * stream);
++ void (*hw_disable) (struct audio_stream_t * stream);
++ void (*hw_clear_fifo) (struct audio_stream_t * stream);
++ int (*client_ioctl) (struct inode *, struct file *, uint, ulong);
++ void (*set_hw_serial_format) (struct audio_stream_t *, long);
++
++ unsigned int modcnt; /* count the # of volume writes */
++
++};
++
++/*
++ * State structure for one instance
++ */
++struct audio_state_t {
++ struct audio_stream_t *output_stream;
++ struct audio_stream_t *input_stream;
++
++ struct audio_hw_t *hw; /* hw info */
++
++ int rd_ref:1; /* open reference for recording */
++ int wr_ref:1; /* open reference for playback */
++
++ struct semaphore sem; /* to protect against races in attach() */
++
++};
++
++/*
++ * Functions exported by this module
++ */
++extern int ep93xx_audio_attach(struct inode *inode, struct file *file,
++ struct audio_state_t *state);
diff --git a/packages/linux/ep93xx-kernel_2.6.15.bb b/packages/linux/ep93xx-kernel_2.6.15.bb
new file mode 100644
index 0000000000..4af3c65927
--- /dev/null
+++ b/packages/linux/ep93xx-kernel_2.6.15.bb
@@ -0,0 +1,19 @@
+DESCRIPTION = "Linux Kernel for Cirrus Logic ep39xxcompatible machines"
+SECTION = "kernel"
+LICENSE = "GPL"
+PR = "r0"
+
+SRC_URI = "ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-${PV}.tar.bz2 \
+ file://linux-2.6.15-ep93xx-gao19.diff;patch=1 \
+ file://defconfig"
+
+S = "${WORKDIR}/linux-${PV}"
+
+inherit kernel
+
+KERNEL_IMAGETYPE = "zImage"
+
+do_configure_prepend() {
+ install -m 0644 ${WORKDIR}/defconfig ${S}/.config
+}
+
diff --git a/packages/linux/linux-mtx-1-2.4.27/23-mtx-1_watchdog_autotrigger.patch b/packages/linux/linux-mtx-1-2.4.27/23-mtx-1_watchdog_autotrigger.patch
new file mode 100644
index 0000000000..c6bb0aae68
--- /dev/null
+++ b/packages/linux/linux-mtx-1-2.4.27/23-mtx-1_watchdog_autotrigger.patch
@@ -0,0 +1,98 @@
+--- linux/arch/mips/au1000/mtx-1/mtx-1_watchdog.c.orig 2005-03-22 17:18:01.000000000 +0100
++++ linux/arch/mips/au1000/mtx-1/mtx-1_watchdog.c 2005-07-06 12:10:06.000000000 +0200
+@@ -39,6 +39,7 @@
+ #include <linux/watchdog.h>
+ #include <linux/slab.h>
+ #include <linux/init.h>
++#include <asm/uaccess.h>
+
+ #include <asm/au1000.h>
+
+@@ -115,6 +116,8 @@
+
+ //---------[ File Functions ]-----------------
+
++static char restart_after_close;
++
+ static int mtx1wd_open (struct inode *inode, struct file *file)
+ {
+ if (MINOR(inode->i_rdev)!=WATCHDOG_MINOR) return -ENODEV;
+@@ -134,6 +137,10 @@
+
+ static int mtx1wd_release (struct inode *inode, struct file *file) {
+ if (MINOR(inode->i_rdev)==WATCHDOG_MINOR) {
++
++ if (restart_after_close)
++ start_wd_timer ();
++
+ }
+ MOD_DEC_USE_COUNT;
+ return 0;
+@@ -141,22 +148,53 @@
+
+
+ static ssize_t mtx1wd_write (struct file *file, const char *buf, size_t count, loff_t *ppos) {
+- if (ppos!=&file->f_pos)
+- return -ESPIPE;
+
+- if (count) {
+ mtx1_trigger_wd ();
+- return 1;
++
++ if (count > 0) {
++ char buffer[10];
++ int n = (count>9)?9:count;
++
++ if (copy_from_user (&buffer, buf, n))
++ return -EFAULT;
++ buffer[n]=0;
++
++ if (count >= 4 && strncmp("auto", buffer, 4)==0)
++ restart_after_close = 1;
++
++ else if (count >= 6 && strncmp("manual", buffer, 6)==0)
++ restart_after_close = 0;
++
++ return n;
+ }
+ return 0;
+ }
+
+
++static ssize_t mtx1wd_read (struct file *file, char *buf, size_t count, loff_t *ppos)
++{
++ char * state = restart_after_close ? "auto\n" : "manual\n";
++ int n = strlen(state)+1;
++
++ if (file->f_pos >= n)
++ return 0;
++
++ if (count < n)
++ return -EINVAL;
++
++ if(copy_to_user(buf, state, n))
++ return -EFAULT;
++
++ file->f_pos += n;
++
++ return n;
++}
++
+
+ static struct file_operations mtx1wd_fops = {
+ .owner = THIS_MODULE,
+ .llseek = NULL,
+- .read = NULL,
++ .read = mtx1wd_read,
+ .write = mtx1wd_write,
+ .readdir = NULL,
+ .poll = NULL,
+@@ -194,6 +232,8 @@
+ {
+ printk("MTX-1 watchdog driver\n");
+
++ restart_after_close = 0;
++
+ mtx1_enable_wd ();
+
+ //-- trigger it for the first time.
diff --git a/packages/linux/linux-mtx-1-2.4.27/24-mtx-1_sysbtn.patch b/packages/linux/linux-mtx-1-2.4.27/24-mtx-1_sysbtn.patch
new file mode 100644
index 0000000000..9c0808942a
--- /dev/null
+++ b/packages/linux/linux-mtx-1-2.4.27/24-mtx-1_sysbtn.patch
@@ -0,0 +1,257 @@
+diff -Nru linux-old/arch/mips/au1000/mtx-1/Makefile linux/arch/mips/au1000/mtx-1/Makefile
+--- linux-old/arch/mips/au1000/mtx-1/Makefile 2005-07-19 18:59:27.000000000 +0200
++++ linux/arch/mips/au1000/mtx-1/Makefile 2005-07-07 10:15:01.000000000 +0200
+@@ -15,6 +15,6 @@
+
+ O_TARGET := mtx-1.o
+
+-obj-y := init.o board_setup.o irqmap.o mtx-1_watchdog.o
++obj-y := init.o board_setup.o irqmap.o mtx-1_watchdog.o mtx-1_sysbtn.o
+
+ include $(TOPDIR)/Rules.make
+diff -Nru linux-old/arch/mips/au1000/mtx-1/irqmap.c linux/arch/mips/au1000/mtx-1/irqmap.c
+--- linux-old/arch/mips/au1000/mtx-1/irqmap.c 2005-07-19 17:42:05.000000000 +0200
++++ linux/arch/mips/au1000/mtx-1/irqmap.c 2005-07-06 13:37:25.000000000 +0200
+@@ -50,10 +50,11 @@
+ /* Need to define this.
+ */
+ au1xxx_irq_map_t au1xxx_irq_map[] = {
++ { AU1500_GPIO_207, INTC_INT_RISE_AND_FALL_EDGE, 0 },
+ { 0, 0, 0}
+ };
+
+-int au1xxx_nr_irqs = 0;
++int au1xxx_nr_irqs = 1;
+
+ #ifdef CONFIG_PCI
+
+diff -Nru linux-old/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c linux/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c
+--- linux-old/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c 1970-01-01 01:00:00.000000000 +0100
++++ linux/arch/mips/au1000/mtx-1/mtx-1_sysbtn.c 2005-07-07 10:29:24.000000000 +0200
+@@ -0,0 +1,226 @@
++/*
++ * Driver for the MTX-1 System Button.
++ *
++ * (c) Copyright 2005 4G Systems <info@4g-systems.biz>, All Rights Reserved.
++ * http://www.4g-systems.biz
++ *
++ * 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.
++ *
++ * Neither Michael Stickel nor 4G Systeme GmbH admit liability nor provide
++ * warranty for any of this software. This material is provided
++ * "AS-IS" and at no charge.
++ *
++ * (c) Copyright 2005 4G Systems <info@4g-systems.biz>
++ *
++ * Release 0.01.
++ *
++ * Author: Michael Stickel michael.stickel@4g-systems.biz
++ *
++ *
++ * After the module is loaded there is a device /dev/misc/btn
++ * that can be read. It returns one char '1' if the button
++ * has been pressed an '0' if it has been released.
++ */
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/version.h>
++#include <linux/types.h>
++#include <linux/errno.h>
++#include <linux/kernel.h>
++#include <linux/poll.h>
++#include <linux/sched.h>
++#include <linux/miscdevice.h>
++#include <linux/slab.h>
++#include <linux/init.h>
++#include <linux/irq.h>
++
++#include <asm/uaccess.h>
++
++#include <asm/au1000.h>
++
++
++#ifndef FALSE
++# define FALSE (0)
++#endif
++
++#ifndef TRUE
++# define TRUE (!FALSE)
++#endif
++
++
++//---------[ declarations ]-----------------
++
++
++static DECLARE_WAIT_QUEUE_HEAD(mtx1btn_wait_queue);
++static char state_changed;
++static char last_value;
++static char is_inuse;
++
++
++//---------[ Hardware Functions ]-----------------
++
++// The MTX-1 Button is attached to GPIO207.
++#define MTX1_GPIO2_SYSBTN (7)
++#define MTX1_SYSBTN_IRQ (AU1500_GPIO_207)
++
++
++static char mtx1_getbtn (int btnno)
++{
++ if (btnno==0) {
++ return (au_readl(GPIO2_PINSTATE) & (1<<MTX1_GPIO2_SYSBTN)) ? 0 : 1;
++ }
++ return 0;
++}
++
++static void mtx1_initbuttons (void)
++{
++ au_writel (au_readl(GPIO2_DIR) & ~(1<<MTX1_GPIO2_SYSBTN), GPIO2_DIR);
++}
++
++
++//---------[ Interrupt handling ]-----------------
++
++
++static void mtx1_btn_interrupt (int irq, void *private, struct pt_regs *regs)
++{
++ char value = mtx1_getbtn(0);
++ if (last_value != value)
++ {
++ last_value = value;
++ state_changed = 1;
++ wake_up (&mtx1btn_wait_queue);
++ }
++// kill_fasync(&async_queue, SIGIO, POLL_OUT);
++}
++
++
++static int mtx1_btn_startirq (void)
++{
++ if (!request_irq (MTX1_SYSBTN_IRQ, mtx1_btn_interrupt, 0 /* | SA_INTERRUPT */, "mtx1btn", (void *)&state_changed)) {
++ return 0;
++ }
++ return -1;
++}
++
++static int mtx1_btn_stopirq (void)
++{
++ free_irq(MTX1_SYSBTN_IRQ, (void *)&state_changed);
++ return 0;
++}
++
++
++
++//---------[ File Functions ]-----------------
++
++
++static int mtx1sysbtn_minor = -1;
++
++
++static int mtx1sysbtn_open (struct inode *inode, struct file *file)
++{
++ if (MINOR(inode->i_rdev)!=mtx1sysbtn_minor) return -ENODEV;
++ if (is_inuse) return -EBUSY;
++ is_inuse=1;
++ last_value = mtx1_getbtn(0);
++ state_changed = 0;
++ MOD_INC_USE_COUNT;
++ return 0;
++}
++
++
++static int mtx1sysbtn_release (struct inode *inode, struct file *file) {
++ if (MINOR(inode->i_rdev)==mtx1sysbtn_minor) {
++ is_inuse=0;
++ }
++ MOD_DEC_USE_COUNT;
++ return 0;
++}
++
++
++static ssize_t mtx1sysbtn_read (struct file *file, char *buf, size_t count, loff_t *ppos)
++{
++ if (count < 1)
++ return -EINVAL;
++ if (!state_changed)
++ interruptible_sleep_on (&mtx1btn_wait_queue);
++ state_changed = 0;
++ char c = last_value ? '1' : '0'; /* mtx1_getbtn(0) */
++ if(copy_to_user(buf, &c, 1))
++ return -EFAULT;
++ return 1;
++}
++
++
++static unsigned int mtx1sysbtn_poll (struct file *file, poll_table * wait)
++{
++ unsigned int mask = 0;
++
++ poll_wait (file, &mtx1btn_wait_queue, wait);
++
++ if (state_changed) // state changed since last time.
++ mask |= POLLIN | POLLRDNORM;
++
++ return mask;
++}
++
++
++static struct file_operations mtx1sysbtn_fops = {
++ .owner = THIS_MODULE,
++ .llseek = NULL,
++ .read = mtx1sysbtn_read,
++ .write = NULL,
++ .readdir = NULL,
++ .poll = mtx1sysbtn_poll,
++ .ioctl = NULL,
++ .mmap = NULL,
++ .open = mtx1sysbtn_open,
++ .flush = NULL,
++ .release = mtx1sysbtn_release
++};
++
++
++static struct miscdevice mtx1sysbtn_miscdev = {
++ MISC_DYNAMIC_MINOR /* SYSBTN_MINOR */ ,
++ "btn",
++ &mtx1sysbtn_fops
++};
++
++
++
++//---------[ Module Functions ]-----------------
++
++
++void __exit cleanup_mtx1_sysbtn (void)
++{
++ is_inuse = 1;
++ mtx1_btn_stopirq ();
++ misc_deregister(&mtx1sysbtn_miscdev);
++}
++
++
++int __init init_mtx1_sysbtn (void)
++{
++ printk("MTX-1 System Button driver\n");
++ is_inuse = 1;
++ mtx1_initbuttons ();
++ if (misc_register (&mtx1sysbtn_miscdev) >= 0) {
++ mtx1sysbtn_minor = mtx1sysbtn_miscdev.minor;
++ if (mtx1_btn_startirq () == 0) {
++ is_inuse=0;
++ return 0;
++ }
++ misc_deregister(&mtx1sysbtn_miscdev);
++ }
++ return 1;
++}
++
++__initcall(init_mtx1_sysbtn);
++__exitcall(cleanup_mtx1_sysbtn);
++
++MODULE_AUTHOR("Michael Stickel");
++MODULE_DESCRIPTION("Driver for the MTX-1 system button");
++MODULE_LICENSE("GPL");
++EXPORT_NO_SYMBOLS;
diff --git a/packages/linux/linux-mtx-1-2.4.27/25-mtx-sio2.diff b/packages/linux/linux-mtx-1-2.4.27/25-mtx-sio2.diff
new file mode 100644
index 0000000000..4f4775a960
--- /dev/null
+++ b/packages/linux/linux-mtx-1-2.4.27/25-mtx-sio2.diff
@@ -0,0 +1,12 @@
+--- linux.old/arch/mips/au1000/mtx-1/board_setup.c 2005-08-10 15:22:14.014147000 +0200
++++ linux/arch/mips/au1000/mtx-1/board_setup.c 2005-08-10 15:26:34.346571264 +0200
+@@ -78,8 +78,7 @@
+
+ // initialize sys_pinfunc:
+ // disable second ethernet port (SYS_PF_NI2)
+- // set U3/GPIO23 to GPIO23 (SYS_PF_U3)
+- au_writel( SYS_PF_NI2 | SYS_PF_U3, SYS_PINFUNC );
++ au_writel( SYS_PF_NI2, SYS_PINFUNC );
+
+ // initialize GPIO
+ au_writel( 0xFFFFFFFF, SYS_TRIOUTCLR );
diff --git a/packages/linux/linux-mtx-1-2.4.27/26-usbd-amd-pb1x00-kit-23may2003-update.diff b/packages/linux/linux-mtx-1-2.4.27/26-usbd-amd-pb1x00-kit-23may2003-update.diff
new file mode 100644
index 0000000000..feaf08c563
--- /dev/null
+++ b/packages/linux/linux-mtx-1-2.4.27/26-usbd-amd-pb1x00-kit-23may2003-update.diff
@@ -0,0 +1,130 @@
+diff -Nru a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c
+--- a/arch/mips/au1000/common/irq.c Fri Feb 27 14:22:51 2004
++++ b/arch/mips/au1000/common/irq.c Fri Feb 27 14:22:51 2004
+@@ -458,7 +458,14 @@
+ intc0_req0 |= au_readl(IC0_REQ0INT);
+
+ if (!intc0_req0) return;
+-
++#if 0
++ /*
++ * This is no longer required. The find first bit operation
++ * is almost as fast at finding the correct interrupt, whereas
++ * leaving this in adds a small amount of overhead to all other
++ * interrupts and therefore induces more latency which may
++ * actually cause USB problems.
++ */
+ /*
+ * Because of the tight timing of SETUP token to reply
+ * transactions, the USB devices-side packet complete
+@@ -469,7 +476,7 @@
+ do_IRQ(AU1000_USB_DEV_REQ_INT, regs);
+ return;
+ }
+-
++#endif
+ irq = au_ffs(intc0_req0) - 1;
+ intc0_req0 &= ~(1<<irq);
+ do_IRQ(irq, regs);
+diff -Nru a/arch/mips/defconfig-bosporus b/arch/mips/defconfig-bosporus
+--- a/arch/mips/defconfig-bosporus Fri Feb 27 14:22:51 2004
++++ b/arch/mips/defconfig-bosporus Fri Feb 27 14:22:51 2004
+@@ -606,8 +606,6 @@
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ CONFIG_AU1X00_UART=y
+ CONFIG_AU1X00_SERIAL_CONSOLE=y
+-# CONFIG_AU1X00_USB_TTY is not set
+-# CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nru a/arch/mips/defconfig-db1000 b/arch/mips/defconfig-db1000
+--- a/arch/mips/defconfig-db1000 Fri Feb 27 14:22:51 2004
++++ b/arch/mips/defconfig-db1000 Fri Feb 27 14:22:51 2004
+@@ -509,8 +509,6 @@
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ CONFIG_AU1X00_UART=y
+ CONFIG_AU1X00_SERIAL_CONSOLE=y
+-# CONFIG_AU1X00_USB_TTY is not set
+-# CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nru a/arch/mips/defconfig-db1100 b/arch/mips/defconfig-db1100
+--- a/arch/mips/defconfig-db1100 Fri Feb 27 14:22:51 2004
++++ b/arch/mips/defconfig-db1100 Fri Feb 27 14:22:51 2004
+@@ -516,8 +516,6 @@
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ CONFIG_AU1X00_UART=y
+ CONFIG_AU1X00_SERIAL_CONSOLE=y
+-# CONFIG_AU1X00_USB_TTY is not set
+-# CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nru a/arch/mips/defconfig-db1500 b/arch/mips/defconfig-db1500
+--- a/arch/mips/defconfig-db1500 Fri Feb 27 14:22:51 2004
++++ b/arch/mips/defconfig-db1500 Fri Feb 27 14:22:51 2004
+@@ -506,8 +506,6 @@
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ CONFIG_AU1X00_UART=y
+ CONFIG_AU1X00_SERIAL_CONSOLE=y
+-# CONFIG_AU1X00_USB_TTY is not set
+-# CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nru a/arch/mips/defconfig-pb1000 b/arch/mips/defconfig-pb1000
+--- a/arch/mips/defconfig-pb1000 Fri Feb 27 14:22:51 2004
++++ b/arch/mips/defconfig-pb1000 Fri Feb 27 14:22:51 2004
+@@ -569,8 +569,6 @@
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ CONFIG_AU1X00_UART=y
+ CONFIG_AU1X00_SERIAL_CONSOLE=y
+-# CONFIG_AU1X00_USB_TTY is not set
+-# CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nru a/arch/mips/defconfig-pb1100 b/arch/mips/defconfig-pb1100
+--- a/arch/mips/defconfig-pb1100 Fri Feb 27 14:22:51 2004
++++ b/arch/mips/defconfig-pb1100 Fri Feb 27 14:22:51 2004
+@@ -515,8 +515,6 @@
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ CONFIG_AU1X00_UART=y
+ CONFIG_AU1X00_SERIAL_CONSOLE=y
+-# CONFIG_AU1X00_USB_TTY is not set
+-# CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nru a/arch/mips/defconfig-pb1500 b/arch/mips/defconfig-pb1500
+--- a/arch/mips/defconfig-pb1500 Fri Feb 27 14:22:51 2004
++++ b/arch/mips/defconfig-pb1500 Fri Feb 27 14:22:51 2004
+@@ -619,8 +619,6 @@
+ # CONFIG_SERIAL_TXX9_CONSOLE is not set
+ CONFIG_AU1X00_UART=y
+ CONFIG_AU1X00_SERIAL_CONSOLE=y
+-# CONFIG_AU1X00_USB_TTY is not set
+-# CONFIG_AU1X00_USB_RAW is not set
+ # CONFIG_TXX927_SERIAL is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+diff -Nru a/drivers/char/Config.in b/drivers/char/Config.in
+--- a/drivers/char/Config.in Fri Feb 27 14:22:51 2004
++++ b/drivers/char/Config.in Fri Feb 27 14:22:51 2004
+@@ -91,14 +91,6 @@
+ if [ "$CONFIG_AU1X00_UART" = "y" ]; then
+ bool ' Enable Au1x00 serial console' CONFIG_AU1X00_SERIAL_CONSOLE
+ fi
+- dep_tristate ' Au1x00 USB TTY Device support' CONFIG_AU1X00_USB_TTY $CONFIG_SOC_AU1X00
+- if [ "$CONFIG_AU1000_USB_TTY" != "y" ]; then
+- dep_tristate ' Au1x00 USB Raw Device support' CONFIG_AU1X00_USB_RAW $CONFIG_SOC_AU1X00
+- fi
+- if [ "$CONFIG_AU1X00_USB_TTY" != "n" -o \
+- "$CONFIG_AU1X00_USB_RAW" != "n" ]; then
+- define_bool CONFIG_AU1X00_USB_DEVICE y
+- fi
+ fi
+ bool ' TXx927 SIO support' CONFIG_TXX927_SERIAL
+ if [ "$CONFIG_TXX927_SERIAL" = "y" ]; then
diff --git a/packages/linux/linux-mtx-1-2.4.27/27-usbd-amd-pb1x00-kit-23may2003-usbd.diff b/packages/linux/linux-mtx-1-2.4.27/27-usbd-amd-pb1x00-kit-23may2003-usbd.diff
new file mode 100644
index 0000000000..7766f71846
--- /dev/null
+++ b/packages/linux/linux-mtx-1-2.4.27/27-usbd-amd-pb1x00-kit-23may2003-usbd.diff
@@ -0,0 +1,15816 @@
+/home/sl/USB/PB1500/work/usbd-gpl/kits/amd-pb1x00-kit/amd-pb1x00-linux-2.4.21
+diff -Nru a/arch/mips/config-shared.in b/arch/mips/config-shared.in
+--- a/arch/mips/config-shared.in Fri Feb 27 14:22:51 2004
++++ b/arch/mips/config-shared.in Fri Feb 27 14:22:51 2004
+@@ -985,6 +985,7 @@
+ endmenu
+
+ source drivers/usb/Config.in
++source drivers/usbd/Config.in
+
+ source net/bluetooth/Config.in
+
+--- a/drivers/Makefile 2005-08-15 18:51:50.332030952 +0200
++++ b/drivers/Makefile 2005-08-15 18:53:08.938081016 +0200
+@@ -41,6 +41,7 @@
+ subdir-$(CONFIG_ISDN_BOOL) += isdn
+ subdir-$(CONFIG_ATM) += atm
+ subdir-$(CONFIG_FC4) += fc4
++subdir-$(CONFIG_USBD) += usbd
+
+ # CONFIG_HAMRADIO can be set without CONFIG_NETDEVICE being set -- ch
+ subdir-$(CONFIG_HAMRADIO) += net/hamradio
+diff -Nru a/drivers/usbd/Config.in b/drivers/usbd/Config.in
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/Config.in Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,58 @@
++#
++# USB device configuration from the device viewpoint (e.g. Linux running inside a USB device, not as host)
++#
++# Copyright (c) 2002-2003 Belcarra
++#
++#
++
++mainmenu_option next_comment
++
++comment 'USB clients (devices, not hosts)'
++
++tristate 'Support for USB Clients (USB Device, not USB Host)' CONFIG_USBD
++
++if [ "$CONFIG_USBD" = "y" -o "$CONFIG_USBD" = "m" ]; then
++ comment ''
++ bool ' Enable High Speed Descriptors' CONFIG_USBD_HIGH_SPEED
++
++ bool ' Do Not Use Serial Number in Device Descriptor (Default is no' CONFIG_USBD_NO_SERIAL_NUMBER
++ if [ "$CONFIG_USBD_NO_SERIAL_NUMBER" != "y" ]; then
++ string ' Default Serial number (string)' CONFIG_USBD_SERIAL_NUMBER_STR ""
++ fi
++
++ int ' Max Power (mA) (Default is zero, whick is self powered)' CONFIG_USBD_MAXPOWER "0"
++
++ comment ''
++
++ bool ' USBD Proc FS' CONFIG_USBD_PROCFS
++
++ tristate ' USBD Proc FS Module' CONFIG_USBD_PROCFSM $CONFIG_USBD
++
++ comment 'Function Drivers'
++
++ source drivers/usbd/network_fd/Config.in
++ source drivers/usbd/acm_fd/Config.in
++
++ source drivers/usbd/mouse_fd/Config.in
++
++ comment 'Bus Interface'
++
++ source drivers/usbd/au1x00_bi/Config.in
++
++ bool ' USB Device Register Tracing' CONFIG_USBD_BI_REGISTER_TRACE
++ if [ "$CONFIG_USBD" = "y" ]; then
++ bool ' USB Device Manual Enable' CONFIG_USBD_BI_DELAY_ENABLE
++ fi
++
++
++ #source drivers/usbd/l7205_bi/Config.in
++ #source drivers/usbd/sl11_bi/Config.in
++
++ #source drivers/usbd/cdc_fd/Config.in
++ #source drivers/usbd/serialnumber/Config.in
++ #source drivers/usbd/audio_fd/Config.in
++ #source drivers/usbd/eg_fd/Config.in
++ #source drivers/usbd/keyboard_fd/Config.in
++fi
++
++endmenu
+diff -Nru a/drivers/usbd/Makefile b/drivers/usbd/Makefile
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/Makefile Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,157 @@
++#
++# Makefile for the kernel USBD (device not host) drivers.
++#
++# Copyright (c) 2002 Belcarra
++# Copyright (C) 2001 Lineo, Inc.
++# Copyright (C) 2001 Hewlett-Packard Co.
++
++# Subdirs.
++# This is a bit complex, because some subdirs are for
++# proprietary code, and are simply not present in a
++# general distribution.
++
++TOPDIR ?= ../../..
++
++# The all-CAPS *_DIRS get nuked in the new versions
++# of Rules.make, so use only the subdir-* methods.
++subdir-y :=
++subdir-m :=
++subdir-n :=
++subdir- :=
++
++# Function Drivers
++subdir-$(CONFIG_USBD_ACM) += acm_fd
++subdir-$(CONFIG_USBD_MOUSE) += mouse_fd
++subdir-$(CONFIG_USBD_NETWORK) += network_fd
++
++#subdir-$(CONFIG_USBD_AUDIO) += audio_fd
++#subdir-$(CONFIG_USBD_EG) += eg_fd
++#subdir-$(CONFIG_USBD_KEYBOARD) += keyboard_fd
++#subdir-$(CONFIG_USBD_CDC) += cdc_fd
++
++# Bus Interface Drivers
++subdir-$(CONFIG_USBD_AU1X00_BUS) += au1x00_bi
++
++#subdir-$(CONFIG_USBD_OMAP_BUS) += omap_bi
++#subdir-$(CONFIG_USBD_TC86C001_BUS) += tc86c001_bi
++
++#subdir-$(CONFIG_USBD_SL11_BUS) += sl11_bi
++
++# The target object and module list name.
++
++O_TARGET := usbdev.o
++
++# Objects that export symbols.
++
++export-objs := usbd.o usbd-bops.o usbd-fops.o usbd-bi.o ep0.o
++
++# Multipart objects.
++
++list-multi := usbdcore.o
++usbdcore-objs := usbd.o ep0.o usbd-fops.o usbd-bops.o
++usbdprocfs-objs := usbd-procfs.o
++
++
++# Optional parts of multipart objects.
++
++# Object file lists.
++
++obj-y :=
++obj-m :=
++obj-n :=
++obj- :=
++
++# Each configuration option enables a list of files.
++
++obj-$(CONFIG_USBD) += usbdcore.o
++obj-$(CONFIG_USBD_PROCFSM) += usbdprocfs.o
++
++# Object files in subdirectories
++
++#
++obj-$(CONFIG_USBD_MONITOR) += monitor/monitor.o
++
++obj-$(CONFIG_USBD_ACM) += acm_fd/acm_fd.o
++obj-$(CONFIG_USBD_MOUSE) += mouse_fd/mouse_fd.o
++obj-$(CONFIG_USBD_NETWORK) += network_fd/network_fd.o
++
++#obj-$(CONFIG_USBD_AUDIO) += audio_fd/audio_fd.o
++#obj-$(CONFIG_USBD_EG) += eg_fd/eg_fd.o
++#obj-$(CONFIG_USBD_KEYBOARD) += keyboard_fd/keyboard_fd.o
++
++# Bus Interface Drivers
++obj-$(CONFIG_USBD_AU1X00_BUS) += au1x00_bi/au1x00_bi.o
++
++#obj-$(CONFIG_USBD_OMAP_BUS) += omap_bi/omap_bi.o
++#obj-$(CONFIG_USBD_TC86C001_BUS) += tc86c001_bi/tc86c001_bi.o
++
++#obj-$(CONFIG_USBD_SL11_BUS) += sl11_bi/sl11_bi.o
++
++
++# Yech. This isn't the best way to do this, but there isn't a config flag
++# common to all the possible bus interfaces
++
++
++# Extract lists of the multi-part drivers.
++# The 'int-*' lists are the intermediate files used to build the multi's.
++
++multi-y := $(filter $(list-multi), $(obj-y))
++multi-m := $(filter $(list-multi), $(obj-m))
++int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
++int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
++
++# Files that are both resident and modular: remove from modular.
++
++obj-m := $(filter-out $(obj-y), $(obj-m))
++int-m := $(filter-out $(int-y), $(int-m))
++
++# Translate to Rules.make lists.
++
++O_OBJS := $(filter-out $(export-objs), $(obj-y))
++OX_OBJS := $(filter $(export-objs), $(obj-y))
++M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
++MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
++MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
++MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
++
++# The global Rules.make.
++
++include $(TOPDIR)/Rules.make
++EXTRA_CFLAGS += -Wno-format -Wall
++
++# Link rules for multi-part drivers.
++
++usbdprocfs.o: $(usbdprocfs-objs)
++ $(LD) -r -o $@ $(usbdprocfs-objs)
++
++usbdcore.o: $(usbdcore-objs)
++ $(LD) -r -o $@ $(usbdcore-objs)
++
++# dependencies:
++
++usbd.o: usbd-build.h
++
++usbd-build.h:
++ echo "#define USBD_BUILD \"000\"" > $@
++
++# local
++
++%.h:%.p
++ release inc build < $< > $@
++ cp $@ $<
++
++release.h: release.p
++
++inc-build:
++ release inc build < release.p > release.h
++ cp release.h release.p
++
++
++menuconfig:
++ cd $(TOPDIR); make menuconfig
++
++xconfig:
++ cd $(TOPDIR); make xconfig
++
++
++
+diff -Nru a/drivers/usbd/acm_fd/Config.in b/drivers/usbd/acm_fd/Config.in
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/acm_fd/Config.in Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,27 @@
++#
++# CDC ACM Function Driver
++#
++# Copyright (C) 2003,2004 Belcarra
++#
++
++mainmenu_option next_comment
++comment "CDC ACM Function"
++
++dep_tristate ' CDC ACM Function' CONFIG_USBD_ACM $CONFIG_USBD
++if [ "$CONFIG_USBD_ACM" = "y" -o "$CONFIG_USBD_ACM" = "m" ]; then
++ hex 'VendorID (hex value)' CONFIG_USBD_ACM_VENDORID "12b9"
++ hex 'ProductID (hex value)' CONFIG_USBD_ACM_PRODUCTID "f002"
++ hex 'bcdDevice (binary-coded decimal)' CONFIG_USBD_ACM_BCDDEVICE "0100"
++
++ string 'iManufacturer (string)' CONFIG_USBD_ACM_MANUFACTURER "Belcarra"
++ string 'iProduct (string)' CONFIG_USBD_ACM_PRODUCT_NAME "Belcarra ACM Device"
++
++ string 'iConfiguration (string)' CONFIG_USBD_ACM_DESC "Acm Cfg"
++ string 'Comm Interface iInterface (string)' CONFIG_USBD_ACM_COMM_INTF "Comm Intf"
++ string 'Data Interface iInterface (string)' CONFIG_USBD_ACM_DATA_INTF "Data Intf"
++
++ bool ' ACM Tracing' CONFIG_USBD_ACM_TRACE
++ comment ''
++fi
++
++endmenu
+diff -Nru a/drivers/usbd/acm_fd/Makefile b/drivers/usbd/acm_fd/Makefile
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/acm_fd/Makefile Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,65 @@
++#
++# Function driver for a CDC ACM USB Device
++#
++# Copyright (c) 2003 Belcarra
++
++# Multipart objects.
++
++O_TARGET := acm_fd.o
++list-multi := acm_fd.o
++
++acm_fd-objs := acm.o trace.o
++
++# Objects that export symbols.
++export-objs := acm.o
++
++# Object file lists.
++
++obj-y :=
++obj-m :=
++obj-n :=
++obj- :=
++
++# Each configuration option enables a list of files.
++
++obj-$(CONFIG_USBD_ACM) += acm_fd.o
++
++# Extract lists of the multi-part drivers.
++# The 'int-*' lists are the intermediate files used to build the multi's.
++
++multi-y := $(filter $(list-multi), $(obj-y))
++multi-m := $(filter $(list-multi), $(obj-m))
++int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
++int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
++
++# Files that are both resident and modular: remove from modular.
++
++obj-m := $(filter-out $(obj-y), $(obj-m))
++int-m := $(filter-out $(int-y), $(int-m))
++
++# Translate to Rules.make lists.
++
++O_OBJS := $(filter-out $(export-objs), $(obj-y))
++OX_OBJS := $(filter $(export-objs), $(obj-y))
++M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
++MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
++MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
++MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
++
++# The global Rules.make.
++
++USBD=$(TOPDIR)/drivers/usbd
++ACMD=$(USBD)/acm_fd
++include $(TOPDIR)/Rules.make
++EXTRA_CFLAGS += -I$(ACMD) -I$(USBD) -Wno-unused -Wno-format
++EXTRA_CFLAGS_nostdinc += -I$(ACMD) -I$(USBD) -Wno-unused -Wno-format
++
++# Link rules for multi-part drivers.
++
++acm_fd.o: $(acm_fd-objs)
++ $(LD) -r -o $@ $(acm_fd-objs)
++
++# dependencies:
++
++acm.o: $(USBD)/usbd.h $(USBD)/usbd-bus.h $(USBD)/usbd-func.h
++
+diff -Nru a/drivers/usbd/acm_fd/acm.c b/drivers/usbd/acm_fd/acm.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/acm_fd/acm.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,1662 @@
++/*
++ * usbd/acm_fd/acm.c
++ *
++ * Copyright (c) 2003, 2004 Belcarra
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ *
++ * Note: this function driver requires the following endpoints:
++ *
++ * BULK-IN
++ * BULK-OUT
++ * INTERRUPT-IN
++ *
++ * This function driver cannot be used on devices (such as the StrongArm
++ * SA1100) that do not have and interrupt endpoint.
++ *
++ */
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++
++#include <usbd-export.h>
++#include <usbd-build.h>
++
++MODULE_AUTHOR ("sl@belcarra.com, tbr@belcarra.com");
++
++MODULE_DESCRIPTION ("Belcarra CDC-ACM Function");
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
++MODULE_LICENSE("GPL");
++#endif
++
++#define ACM_TRACE_NAME "acm_trace"
++
++#undef USE_TICKER
++#undef MCEL
++//#define MCEL 1
++//#define CONFIG_USBD_ACM_DATALOG 1
++#undef CONFIG_USBD_ACM_DATALOG
++#undef PST_FD_AVAILABLE
++
++#include <linux/init.h>
++#include <asm/uaccess.h>
++#include <linux/ctype.h>
++#include <linux/timer.h>
++#include <linux/interrupt.h>
++#include <asm/atomic.h>
++#include <linux/tty.h>
++#include <linux/tty_driver.h>
++#include <linux/tty_flip.h>
++#include <linux/smp_lock.h>
++#include <linux/slab.h>
++
++#include <usbd-chap9.h>
++#include <usbd-mem.h>
++#include <usbd.h>
++#include <usbd-func.h>
++
++#include "trace.h"
++// Define the low order 16 bits of an urb's memory address as it's ID for tracing.
++#define urbID(urb) (0xffff & (u32) (void *) urb)
++int acm_interrupts;
++
++USBD_MODULE_INFO ("acm_fd 2.1-beta");
++
++#define MAX_QUEUED_BYTES 256
++#define MAX_QUEUED_URBS 10 // Max for write
++
++#define MAX_RECV_URBS 2 // Max for receiving data
++#define RECV_RING_SIZE (MAX_RECV_URBS+1)
++
++// Endpoint indexes in acm_endpoint_requests[] and the endpoint map.
++#define BULK_OUT 0x00
++#define BULK_IN 0x01
++#define INT_IN 0x02
++#if !defined(CONFIG_USBD_ACM_DATALOG)
++#define ENDPOINTS 0x03
++#else
++#define DATALOG_BULK_IN 0x03
++#define ENDPOINTS 0x04
++#endif
++
++#define COMM_INTF 0x00
++#define DATA_INTF 0x01
++#if defined(CONFIG_USBD_ACM_DATALOG)
++#define DATALOG_INTF 0x02
++#define TESTCMD_INTF 0x03
++#endif
++
++#if defined(CONFIG_USBD_ACM_DATALOG) && defined(PST_FD_AVAILABLE)
++extern int pst_dev_create(struct usb_device_instance *device);
++extern void pst_dev_destroy(void);
++extern void ep0_process_vendor_request( struct urb *urb );
++extern int pst_urb_sent (struct urb *urb, int rc);
++#endif
++
++/* Module Parameters ************************************************************************* */
++
++static u32 vendor_id;
++static u32 product_id;
++static u32 max_queued_urbs = MAX_QUEUED_URBS;
++static u32 max_queued_bytes = MAX_QUEUED_BYTES;
++
++MODULE_PARM (vendor_id, "i");
++MODULE_PARM (product_id, "i");
++MODULE_PARM (max_queued_urbs, "i");
++MODULE_PARM (max_queued_bytes, "i");
++
++MODULE_PARM_DESC (vendor_id, "Device Vendor ID");
++MODULE_PARM_DESC (product_id, "Device Product ID");
++MODULE_PARM_DESC (max_queued_urbs, "Maximum TX Queued Urbs");
++MODULE_PARM_DESC (max_queued_bytes, "Maximum TX Queued Bytes");
++
++/*
++ * CDC ACM Configuration
++ *
++ * Endpoint, Class, Interface, Configuration and Device descriptors/descriptions
++ */
++
++/* Endpoints */
++static __u8 acm_alt_1[] = { 0x07, USB_DT_ENDPOINT, OUT, BULK, 0, 0x00, 0x00, };
++static __u8 acm_alt_2[] = { 0x07, USB_DT_ENDPOINT, IN, BULK, 0, 0x00, 0x00, };
++static struct usb_endpoint_descriptor *acm_alt_endpoints[] = {
++ (struct usb_endpoint_descriptor *) acm_alt_1,
++ (struct usb_endpoint_descriptor *) acm_alt_2, };
++u8 acm_alt_indexes[] = { BULK_OUT, BULK_IN, };
++
++static __u8 acm_comm_1[] = { 0x07, USB_DT_ENDPOINT, IN, INTERRUPT, 0, 0x00, 0x0a, };
++static struct usb_endpoint_descriptor *acm_comm_endpoints[] = { (struct usb_endpoint_descriptor *) acm_comm_1 };
++u8 acm_comm_indexes[] = { INT_IN, };
++
++static __u8 cdc_class_1[] = { 0x05, CS_INTERFACE, USB_ST_HEADER, 0x01, 0x01, /* CLASS_BDC_VERSION, CLASS_BDC_VERSION */ };
++static __u8 cdc_class_2[] = { 0x05, CS_INTERFACE, USB_ST_CMF, 0x03, 0x01, /* bMasterInterface: 0, bSlaveInterface: 1 */ };
++static __u8 cdc_class_3[] = { 0x05, CS_INTERFACE, USB_ST_UF, 0x00, 0x01, /* bMasterInterface: 0, bSlaveInterface: 1 */ };
++
++/* ACMF - c.f. Table 28
++ * currenty set to 0x2 - Support Set_Line_Coding etc,
++ *
++ * XXX Should we also set 0x4 - Supports Network_Notification?
++ */
++static __u8 cdc_class_4[] = { 0x04, CS_INTERFACE, USB_ST_ACMF, 0x02, };
++
++static struct usb_generic_class_descriptor *cdc_comm_class_descriptors[] =
++ { (struct usb_generic_class_descriptor *) cdc_class_1,
++ (struct usb_generic_class_descriptor *) cdc_class_2,
++ (struct usb_generic_class_descriptor *) cdc_class_3,
++ (struct usb_generic_class_descriptor *) cdc_class_4, };
++
++
++#if defined(CONFIG_USBD_ACM_DATALOG)
++
++#if 0
++/* This is used to get a specific INTERFACE number, by padding the list of interfaces. */
++static struct usb_alternate_description dummy_alternate_descriptions[] = {
++ { iInterface:"Dummy", },
++};
++#endif
++
++/* There is no way to request a specific ENDPOINT address, since that depends on
++ the bus interface hardware. */
++//#define DATA_LOG_IN_ENDPOINT 11
++
++static __u8 datalog_endpoint[] = {
++ 0x07, // bLength
++ USB_DT_ENDPOINT, // bDescriptorType // 0x5
++ /*DATA_LOG_IN_ENDPOINT |*/ IN, // bEndpointAddress
++ BULK, // bmAttributes
++ 0, 0x00, // wMaxPacketSize
++ 0x00, // bInterval
++};
++static struct usb_endpoint_descriptor *datalog_endpoints[] = { datalog_endpoint };
++u8 datalog_indexes[] = { DATALOG_BULK_IN, };
++
++
++// No endpoints needed for TestCmd interface.
++#endif
++
++/* Alternate Descriptors */
++// First two bytes are identical in all: bLength, bDescriptorType (0x09 0x04)
++static __u8 cdc_comm_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, COMM_INTF, 0x00, 0x00, // bInterfaceNumber, bAlternateSetting, bNumEndpoints
++ COMMUNICATIONS_INTERFACE_CLASS, COMMUNICATIONS_ACM_SUBCLASS, 0x01, 0x00, };
++
++static __u8 cdc_data_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, DATA_INTF, 0x00, 0x00, // bInterfaceNumber, bAlternateSetting, bNumEndpoints
++ DATA_INTERFACE_CLASS, COMMUNICATIONS_NO_SUBCLASS, COMMUNICATIONS_NO_PROTOCOL, 0x00, };
++
++
++#if defined(CONFIG_USBD_ACM_DATALOG)
++
++static __u8 datalog_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, DATALOG_INTF, 0x00, 0x00, // bInterfaceNumber, bAlternateSetting, bNumEndpoints
++ // bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface
++ 0xFF, 0x02, 0xFF, 0x00, };
++
++static __u8 testcmd_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, TESTCMD_INTF, 0x00, 0x00, // bInterfaceNumber, bAlternateSetting, bNumEndpoints
++ // bInterfaceClass, bInterfaceSubClass, bInterfaceProtocol, iInterface
++ 0xFF, 0x03, 0xFF, 0x00, };
++
++#endif
++
++/* Alternate Descriptions */
++static struct usb_alternate_description cdc_comm_alternate_descriptions[] = {
++ { iInterface: CONFIG_USBD_ACM_COMM_INTF,
++ interface_descriptor: (struct usb_interface_descriptor *)&cdc_comm_alternate_descriptor,
++ classes:sizeof (cdc_comm_class_descriptors) / sizeof (struct usb_generic_class_descriptor *),
++ class_list: cdc_comm_class_descriptors,
++ endpoint_list: acm_comm_endpoints,
++ endpoints:sizeof (acm_comm_endpoints) / sizeof(struct usb_endpoint_descriptor *),
++ endpoint_indexes: acm_comm_indexes,
++ }, };
++
++static struct usb_alternate_description cdc_data_alternate_descriptions[] = {
++ { iInterface: CONFIG_USBD_ACM_DATA_INTF,
++ interface_descriptor: (struct usb_interface_descriptor *)&cdc_data_alternate_descriptor,
++ endpoint_list: acm_alt_endpoints,
++ endpoints:sizeof (acm_alt_endpoints) / sizeof(struct usb_endpoint_descriptor *),
++ endpoint_indexes: acm_alt_indexes,
++ }, };
++
++#if defined(CONFIG_USBD_ACM_DATALOG)
++
++static struct usb_alternate_description datalog_alternate_descriptions[] = {
++ { iInterface:"Motorola MCU Data Logger",
++ interface_descriptor: (struct usb_interface_descriptor *)&datalog_alternate_descriptor,
++ endpoint_list: datalog_endpoints,
++ endpoints:sizeof (datalog_endpoints) / sizeof (struct usb_endpoint_descriptor *),
++ endpoint_indexes: datalog_indexes,
++ },
++};
++
++static struct usb_alternate_description testcmd_alternate_descriptions[] = {
++ { iInterface:"Motorola Test Command",
++ interface_descriptor: (struct usb_interface_descriptor *)&testcmd_alternate_descriptor,
++ },
++};
++#endif
++
++/* Interface Descriptions */
++static struct usb_interface_description cdc_interfaces[] = {
++ {
++ alternates:sizeof (cdc_comm_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list:cdc_comm_alternate_descriptions,
++ },
++
++ {
++ alternates:sizeof (cdc_data_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list:cdc_data_alternate_descriptions,
++ },
++
++#if defined(CONFIG_USBD_ACM_DATALOG)
++#if 0
++ // Space the INTERFACEs out by adding as many dummies as required (for now, none).
++ { alternate_list: dummy_alternate_descriptions, }, /* 0xN */
++#endif
++
++ { alternates:sizeof (datalog_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list:datalog_alternate_descriptions,
++ },
++
++ { alternates:sizeof (testcmd_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list:testcmd_alternate_descriptions,
++ },
++
++#endif
++
++};
++
++
++/* Configuration Descriptor and Description */
++static __u8 cdc_configuration_descriptor[sizeof(struct usb_configuration_descriptor)] = {
++ 0x09, USB_DT_CONFIG, 0x00, 0x00, sizeof (cdc_interfaces) / sizeof (struct usb_interface_description),
++ 0x01, 0x00, BMATTRIBUTE, BMAXPOWER, };
++
++struct usb_configuration_description acm_description[] = {
++ { iConfiguration: CONFIG_USBD_ACM_DESC,
++ configuration_descriptor: (struct usb_configuration_descriptor *)cdc_configuration_descriptor,
++ bNumInterfaces:sizeof (cdc_interfaces) / sizeof (struct usb_interface_description),
++ interface_list:cdc_interfaces,}, };
++
++static struct usb_device_descriptor acm_device_descriptor = {
++ bLength: sizeof(struct usb_device_descriptor),
++ bDescriptorType: USB_DT_DEVICE,
++ bcdUSB: __constant_cpu_to_le16(USB_BCD_VERSION),
++ bDeviceClass: COMMUNICATIONS_DEVICE_CLASS,
++ bDeviceSubClass: 0x02,
++ bDeviceProtocol: 0x00,
++ bMaxPacketSize0: 0x00,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_ACM_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_ACM_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_ACM_BCDDEVICE),
++};
++
++
++static struct usb_endpoint_request acm_endpoint_requests[ENDPOINTS+1] = {
++ { 1, 1, 0, USB_DIR_OUT | USB_ENDPOINT_BULK, 64, 512, },
++ { 1, 1, 0, USB_DIR_IN | USB_ENDPOINT_BULK, 64 /* * 4 */, 512, },
++ { 1, 0, 0, USB_DIR_IN | USB_ENDPOINT_INTERRUPT, 16, 64, },
++#if defined(CONFIG_USBD_ACM_DATALOG)
++ { 1, 1, 0, USB_DIR_IN | USB_ENDPOINT_BULK, 64, 512, },
++#endif
++ { 0, },
++};
++
++
++struct usb_device_description acm_device_description = {
++ device_descriptor: &acm_device_descriptor,
++ iManufacturer: CONFIG_USBD_ACM_MANUFACTURER,
++ iProduct: CONFIG_USBD_ACM_PRODUCT_NAME,
++#if !defined(CONFIG_USBD_NO_SERIAL_NUMBER) && defined(CONFIG_USBD_SERIAL_NUMBER_STR)
++ iSerialNumber: CONFIG_USBD_SERIAL_NUMBER_STR,
++#endif
++ endpointsRequested: ENDPOINTS,
++ requestedEndpoints: acm_endpoint_requests,
++};
++
++/* Missing atomic functions ******************************************************************** */
++
++static __inline__ int atomic_post_inc(volatile atomic_t *v)
++{
++ unsigned long flags;
++ int result;
++ local_irq_save(flags);
++ result = (v->counter)++;
++ local_irq_restore(flags);
++ return(result);
++}
++
++static __inline__ int atomic_pre_dec(volatile atomic_t *v)
++{
++ unsigned long flags;
++ int result;
++ local_irq_save(flags);
++ result = --(v->counter);
++ local_irq_restore(flags);
++ return(result);
++}
++
++/* ACM ***************************************************************************************** */
++/*
++ * Output and Input control lines and line errors.
++ */
++#define LINE_OUT_DTR 0x01
++#define LINE_OUT_RTS 0x02
++#define LINE_IN_DCD 0x01
++#define LINE_IN_DSR 0x02
++#define LINE_IN_BRK 0x04
++#define LINE_IN_RI 0x08
++#define LINE_IN_FRAMING 0x10
++#define LINE_IN_PARITY 0x20
++#define LINE_IN_OVERRUN 0x40
++
++/* ******************************************************************************************* */
++
++#define ACM_TTY_MAJOR 166
++#define ACM_TTY_MINOR 0
++#define ACM_TTY_MINORS 1
++
++struct acm_private {
++ struct usb_function_instance *function;
++ struct tty_driver *tty_driver;
++ int tty_driver_registered; // non-zero if tty_driver registered
++ int usb_driver_registered; // non-zero if usb function registered
++
++ struct tty_struct *tty; // non-null if tty open
++ struct tq_struct wqueue; // task queue for writer wakeup
++ struct tq_struct hqueue; // task queue for hangup
++ wait_queue_head_t open_wait; // wait queue for blocking open
++ int open_wait_count; // count of (possible) blocked
++ int exiting; // True if module exiting
++
++ unsigned char throttle; // non-zero if we are throttled
++ unsigned char clocal; // non-zero if clocal set
++ unsigned char connected; // non-zero if connected to host (configured)
++
++ unsigned int writesize; // packetsize * 4
++ unsigned int ctrlin; // line state device sends to host
++ unsigned int ctrlout; // line state device received from host
++
++ int exclusive;
++ atomic_t used;
++ atomic_t queued_bytes;
++ atomic_t queued_urbs;
++
++ /*TBR debug receive flow control */
++ unsigned long bytes_received;
++ unsigned long bytes_forwarded;
++ /*TBR end debug */
++
++ struct urb *recv_ring[RECV_RING_SIZE];
++ unsigned int rr_in_ndx;
++ unsigned int rr_out_ndx;
++
++ struct urb *int_urb; // pending interrupt urb
++};
++
++static struct acm_private acm_private;
++
++static int acm_send_int_notification(struct usb_function_instance *, int , int );
++static int acm_urb_sent_bulk (struct urb *urb, int rc);
++static int acm_urb_sent_int (struct urb *urb, int rc);
++static int acm_recv_urb (struct urb *urb, int rc);
++
++/* Serial Functions **************************************************************************** */
++
++static void acm_schedule(struct tq_struct *queue)
++{
++ TRACE_MSG1("task %p",queue);
++ RETURN_IF(!queue->data || queue->sync);
++ MOD_INC_USE_COUNT;
++ queue_task(queue, &tq_immediate);
++ mark_bh(IMMEDIATE_BH);
++ TRACE_MSG1("task %p scheduled and marked",queue);
++}
++
++
++static int block_until_ready(
++ struct tty_struct *tty,
++ struct file *filp,
++ struct acm_private *acm)
++{
++ unsigned long flags;
++ int rc = 0;
++
++ // FUTURE: check tty for non-blocking open...
++
++ local_irq_save(flags);
++ TRACE_MSG1("owc=%d --> at entry",acm->open_wait_count);
++ acm->open_wait_count += 1;
++ for (;;) {
++ if (tty_hung_up_p(filp)) {
++ TRACE_MSG("tty_hung_up_p()");
++ rc = -ERESTARTSYS;
++ break;
++ }
++ if (signal_pending(current)) {
++ TRACE_MSG("signal_pending()");
++ rc = -ERESTARTSYS;
++ break;
++ }
++ if (acm->exiting) {
++ TRACE_MSG("module exiting()");
++ rc = -ENODEV;
++ break;
++ }
++ if (acm->ctrlout & LINE_OUT_DTR) {
++ // OK, there's somebody on the other end, let's go...
++ TRACE_MSG("found DTR");
++ break;
++ }
++ TRACE_MSG1("owc=%d sleeping...",acm->open_wait_count);
++ interruptible_sleep_on(&acm->open_wait);
++ TRACE_MSG1("owc=%d got WAKEUP",acm->open_wait_count);
++ }
++ acm->open_wait_count -= 1;
++ TRACE_MSG1("owc=%d <-- at exit",acm->open_wait_count);
++ local_irq_restore(flags);
++ return(rc);
++}
++
++static void acm_hangup(void *private)
++{
++ //struct acm_private *acm = &acm_private;
++ struct acm_private *acm = (struct acm_private *) private;
++ struct tty_struct *tty = acm->tty;
++ TRACE_MSG("entered");
++
++ if (tty && !acm->clocal)
++ tty_hangup(tty);
++
++ wake_up_interruptible(&acm->open_wait);
++
++ MOD_DEC_USE_COUNT;
++ //printk (KERN_INFO"%s: MOD: %d connected: %d tty: %p clocal: %x\n",
++ // __FUNCTION__, MOD_IN_USE, acm->connected, tty, acm->clocal);
++ TRACE_MSG("exited");
++}
++
++static int acm_tty_open(struct tty_struct *tty, struct file *filp)
++{
++ struct acm_private *acm = &acm_private;
++ //struct usb_function_instance *function = acm->function;
++ int used;
++ int nonblocking;
++ int rc = 0;
++ unsigned long flags;
++
++ TRACE_MSG2("used=%d MOD=%d",atomic_read(&acm->used),MOD_IN_USE);
++ //printk (KERN_INFO"%s: bus: %p used: %d MOD: %d\n",
++ // __FUNCTION__, acm->function, atomic_read(&acm->used), MOD_IN_USE);
++ nonblocking = filp->f_flags & O_NONBLOCK;
++ /* Lock and increment used counter, save current value.
++ Check for exclusive open at the same time. */
++ local_irq_save(flags);
++ /* The value of acm->used controls MOD_{INC/DEC}_USE_COUNT, so
++ it has to be incremented unconditionally, and no early return
++ made until after USE_COUNT has been adjusted to match. */
++ used = atomic_post_inc(&acm->used);
++#ifdef MCEL
++ filp->f_flags |= O_EXCL; // QQQ Can we persuade MCEL to add this to their app?
++ if (nonblocking && !(acm->connected)) {
++ // QQQ Is MCEL actually using this "feature"? (See below for printk)
++ rc = -EINVAL;
++ } else
++#endif
++ if (filp->f_flags & O_EXCL) {
++ /* This is intended to be an exclusive open, so
++ make sure no one has the device open already, and
++ set the exclusive flag so no one can open it later. */
++ if (used > 0) {
++ // Someone already has it.
++ rc = -EBUSY;
++ } else {
++ acm->exclusive = 1;
++ set_bit(TTY_EXCLUSIVE, &tty->flags);
++ }
++ } else if (acm->exclusive != 0 && !suser()) {
++ // Only the superuser can do a normal open of an O_EXCL tty
++ rc = -EBUSY;
++ }
++ local_irq_restore(flags);
++ if (0 == used) {
++ // The value before incrementing was 0, this is the first open.
++ MOD_INC_USE_COUNT;
++ }
++ // OK, now it's safe to make an early return.
++ if (0 != rc) {
++#ifdef MCEL
++ // This can dissappear when the "feature" above does.
++ if (-EINVAL == rc)
++ printk(KERN_INFO "\nusb cable not connected!\n");
++#endif
++ return(rc);
++ }
++ /* To truly emulate the old dual-device approach of having a non-blocking
++ device (e.g cu0) and a blocking device (e.g. tty0) we would need to
++ track blocking and non-blocking opens separately. We don't. This
++ may lead to funny behavior in the multiple open case. */
++ if (0 == used) {
++ // First open.
++ TRACE_MSG2("FIRST OPEN nb=%x xo=%x",nonblocking,acm->exclusive);
++ //printk (KERN_INFO"%s: FIRST OPEN used_%sblock: s=%d, a=%d x=%d\n",
++ // __FUNCTION__,(nonblocking?"non":""), used, atomic_read(&acm->used),
++ // acm->exclusive);
++ tty->driver_data = acm;
++ acm->tty = tty;
++ tty->low_latency = 1;
++ acm->bytes_received = 0;
++ acm->bytes_forwarded = 0;
++ acm->ctrlin = LINE_IN_DCD | LINE_IN_DSR;
++ if (NULL != acm->function) {
++ TRACE_MSG1("sending notification ctrlin=%x",acm->ctrlin);
++ //printk (KERN_INFO"%s: sending ctrlin notification\n",__FUNCTION__);
++ rc = acm_send_int_notification(acm->function, CDC_NOTIFICATION_SERIAL_STATE,
++ acm->ctrlin);
++ }
++ }
++
++ if (0 == rc && !nonblocking) {
++ // Blocking open - all callers block until DTR shows up.
++ rc = block_until_ready(tty,filp,acm);
++ }
++
++ /* The tty layer calls acm_tty_close() even if this open fails,
++ so any cleanup (rc != 0) will be done there. */
++ TRACE_MSG2("used=%d rc=%d",atomic_read(&acm->used),rc);
++ return(rc);
++}
++
++static void acm_tty_close(struct tty_struct *tty, struct file *filp)
++{
++ struct acm_private *acm = tty->driver_data;
++ struct usb_function_instance *function = acm->function;
++ int used;
++
++ TRACE_MSG2("used=%d MOD=%d",atomic_read(&acm->used),MOD_IN_USE);
++ //printk (KERN_INFO"%s: function: %p used: %d MOD: %d\n",
++ // __FUNCTION__, function, atomic_read(&acm->used), MOD_IN_USE);
++
++ // lock and decrement used counter, save result
++ used = atomic_pre_dec(&acm->used);
++
++ // finished unless this is the last close
++ if (used <= 0) {
++ // This is the last close, clean up
++
++ acm->tty = NULL;
++ acm->ctrlin = 0x0;
++
++ if (acm->function) {
++ acm_send_int_notification(function, CDC_NOTIFICATION_SERIAL_STATE, acm->ctrlin);
++ }
++ /* This should never happen if this is the last close,
++ but it can't hurt to check. */
++ if (acm->open_wait_count) {
++ wake_up_interruptible(&acm->open_wait);
++ }
++ if (acm->exclusive) {
++ acm->exclusive = 0;
++ clear_bit(TTY_EXCLUSIVE, &tty->flags);
++ }
++ MOD_DEC_USE_COUNT;
++ TRACE_MSG1("LAST CLOSE r-f=%d",(acm->bytes_received-acm->bytes_forwarded));
++ //printk (KERN_INFO"%s: LAST CLOSE used: %d MOD: %d bytes_received: %lu forwarded: %lu\n",
++ // __FUNCTION__, atomic_read(&acm->used), MOD_IN_USE, acm->bytes_received,
++ // acm->bytes_forwarded);
++ }
++ TRACE_MSG("exited");
++}
++
++/* Transmit Function - called by serproto ****************************************************** */
++
++static int acm_tty_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
++{
++ struct acm_private *acm = tty->driver_data;
++ struct usb_function_instance *function = acm->function;
++ struct urb *urb;
++
++ TRACE_MSG1("count=%d",count);
++ //printk (KERN_INFO"%s: used: %d count: %d\n", __FUNCTION__, atomic_read(&acm->used), count);
++
++ RETURN_EINVAL_IF(!function);
++ TRACE_MSG("function OK");
++
++ // sanity check and are we connect
++ RETURN_EINVAL_IF(!atomic_read(&acm->used));
++ TRACE_MSG("used OK");
++ RETURN_ZERO_IF (!count || !acm->connected);
++ TRACE_MSG("connected OK");
++ RETURN_ZERO_IF(max_queued_urbs <= atomic_read(&acm->queued_urbs));
++ TRACE_MSG("max_queued_urbs OK");
++
++ // allocate a write urb
++ count = MIN(count, acm->writesize);
++
++ // XXX verify that we don't attempt to send wMaxPacketSize packets...
++ if (!(count % usbd_endpoint_wMaxPacketSize(function, BULK_OUT, 0))) //QQSV
++ count--;
++
++ //printk(KERN_INFO"%s:\n", __FUNCTION__);
++ RETURN_ENOMEM_IF (!(urb = usbd_alloc_urb (function, BULK_IN, count, acm_urb_sent_bulk)));
++ TRACE_MSG("alloc_urb OK");
++
++ if (from_user)
++ copy_from_user(urb->buffer, buf, count);
++ else
++ memcpy(urb->buffer, buf, count);
++ urb->privdata = acm;
++ urb->actual_length = count;
++ atomic_add(count, &acm->queued_bytes);
++ atomic_inc(&acm->queued_urbs);
++ usbd_send_urb(urb);
++ TRACE_MSG2("urbID#%04x --> %d",urbID(urb),count);
++ return count;
++}
++
++static int acm_tty_write_room(struct tty_struct *tty)
++{
++ struct acm_private *acm = &acm_private;
++ int rc;
++
++ TRACE_MSG("entered");
++ //printk (KERN_INFO"%s: used: %d queued: %d %d room: %d\n", __FUNCTION__, atomic_read(&acm->used),
++ // atomic_read(&acm->queued_urbs), atomic_read(&acm->queued_bytes),
++ // (max_queued_urbs > atomic_read(&acm->queued_urbs)) &&
++ // (max_queued_bytes > atomic_read(&acm->queued_bytes)) ? acm->writesize : 0);
++
++ RETURN_EINVAL_IF(!atomic_read(&acm->used));
++ TRACE_MSG("used OK");
++ rc = (!acm->function || max_queued_urbs <= atomic_read(&acm->queued_urbs) ||
++ max_queued_bytes <= atomic_read(&acm->queued_bytes) ) ? 0 : acm->writesize ;
++ TRACE_MSG1("--> %d",rc);
++ return(rc);
++}
++
++static int acm_tty_chars_in_buffer(struct tty_struct *tty)
++{
++ struct acm_private *acm = &acm_private;
++ int rc;
++ TRACE_MSG("entered");
++ RETURN_EINVAL_IF(!atomic_read(&acm->used));
++ TRACE_MSG("used OK");
++ RETURN_ZERO_IF(!acm->function);
++ TRACE_MSG("function OK");
++ rc = atomic_read(&acm->queued_bytes);
++ TRACE_MSG1("--> %d",rc);
++ return(rc);
++}
++
++static struct urb *acm_frwd_recv_urbs(struct tty_struct *tty, struct acm_private *acm)
++{
++ unsigned long flags;
++ struct urb *urb;
++
++ TRACE_MSG("entered");
++ //struct usb_function_instance *function = acm->function;
++
++ //if (acm->throttle)
++ // printk(KERN_INFO"%s: THROTTLED at 0\n", __FUNCTION__);
++
++ while (acm->rr_in_ndx != acm->rr_out_ndx && !acm->throttle) {
++ // Forward one URB from the receive ring
++ local_irq_save(flags);
++ urb = acm->recv_ring[acm->rr_out_ndx];
++ acm->recv_ring[acm->rr_out_ndx] = NULL;
++ acm->rr_out_ndx = (acm->rr_out_ndx + 1) % RECV_RING_SIZE;
++ local_irq_restore(flags);
++
++ if (urb->status == RECV_OK && tty) {
++ unsigned char *cp = urb->buffer;
++ int i;
++ int f = 0;
++ // Future: think about throttle part way through...
++ //printk(KERN_INFO"%s: ", __FUNCTION__);
++#define ACM_WORD_COPY
++#ifndef ACM_WORD_COPY
++ for (i = 0; i < urb->actual_length; i++) {
++ if (tty->flip.count >= TTY_FLIPBUF_SIZE) {
++ tty_flip_buffer_push(tty);
++ acm->bytes_forwarded += f;
++ f = 0;
++ }
++
++ //printk("%02x ", *cp);
++ tty_insert_flip_char(tty, *cp++, 0);
++ f += 1;
++
++ if (acm->throttle) {
++ //printk(KERN_INFO"%s: throttled at %d/%d\n", __FUNCTION__,i,urb->actual_length);
++ break;
++ }
++ }
++ //printk("\n");
++ tty_flip_buffer_push(tty);
++ acm->bytes_forwarded += f;
++#else
++ for (i = urb->actual_length; i > 0; i -= f) {
++ f = i;
++ if (tty->flip.count + f > TTY_FLIPBUF_SIZE) {
++ tty_flip_buffer_push(tty);
++ f = MIN(f, TTY_FLIPBUF_SIZE - tty->flip.count);
++ }
++ if (f <= 0) {
++ // Shouldn't happen...
++ printk(KERN_ERR"%s: %d bytes dropped\n", __FUNCTION__, i);
++ break;
++ }
++ memcpy(tty->flip.char_buf_ptr, cp, f); // see: arch/arm/lib/memcpy.S
++ cp += f;
++ tty->flip.count += f;
++ tty->flip.flag_buf_ptr += f;
++ tty->flip.char_buf_ptr += f; // w20146 - Jul 31
++ tty_flip_buffer_push(tty);
++ acm->bytes_forwarded += f;
++ }
++
++#endif
++ if (acm->throttle) {
++ printk(KERN_INFO"%s: THROTTLED at 1\n", __FUNCTION__);
++ }
++ }
++ else if (urb->status != RECV_OK)
++ printk(KERN_INFO"%s: !RECV_OK, dumping %d bytes\n", __FUNCTION__,urb->actual_length);
++ else
++ printk(KERN_INFO"%s: tty NULL\n", __FUNCTION__);
++
++ // Put urb back in line for a refill.
++ if (usbd_start_recv (urb)) {
++ // Bail if it can't be queued for refill.
++ printk(KERN_INFO"%s: usbd_start_recv() failed\n", __FUNCTION__);
++ return(urb);
++ }
++ }
++ TRACE_MSG("exited");
++ return(NULL);
++}
++
++static void acm_tty_throttle(struct tty_struct *tty)
++{
++ struct acm_private *acm = &acm_private;
++ TRACE_MSG("entered");
++ //uuu printk (KERN_INFO"%s:\n", __FUNCTION__);
++ if (acm && atomic_read(&acm->used))
++ acm->throttle = 1;
++ TRACE_MSG("exited");
++}
++
++static void acm_tty_unthrottle(struct tty_struct *tty)
++{
++ struct acm_private *acm = &acm_private;
++ struct urb *urb;
++ TRACE_MSG("entered");
++ //uuu printk (KERN_INFO"%s:\n", __FUNCTION__);
++ if (acm && atomic_read(&acm->used)) {
++ acm->throttle = 0;
++ // Forward any queued URBS.
++ if (NULL != (urb = acm_frwd_recv_urbs(tty,acm))) {
++ /* usbd_start_recv(urb) failed, so we need to dispose of this urb.
++ Count on someone else to replace it. */
++ usbd_dealloc_urb(urb);
++ }
++ }
++ TRACE_MSG("exited");
++}
++
++static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
++{
++ struct acm_private *acm = &acm_private;
++ struct usb_function_instance *function = acm->function;
++ unsigned int mask;
++ unsigned int newctrl;
++
++ TRACE_MSG("entered");
++ //printk (KERN_INFO"%s: used: %d\n", __FUNCTION__, atomic_read(&acm->used));
++ RETURN_EINVAL_IF(!atomic_read(&acm->used));
++
++#if 1 // temporary solution for IOCTL
++ if(cmd == TIOCMGET)
++ return put_user( acm->ctrlout & LINE_OUT_DTR ? TIOCM_DTR : 0 | TIOCM_CTS, (unsigned long *) arg);
++#endif
++
++ TRACE_MSG("--> -ENOIOCTLCMD");
++ return -ENOIOCTLCMD;
++
++#if 0
++ switch(cmd) {
++ case TCGETS:
++ case TCFLSH:
++ case TCSETS:
++ printk (KERN_INFO"%s: ignored cmd: %x\n", __FUNCTION__, cmd);
++ return 0;
++
++ case TCSETSW:
++
++ //user_termios_to_kernel_termios(&priv->termios, (struct termios *)arg);
++ printk (KERN_INFO"%s: ignored cmd: %x\n", __FUNCTION__, cmd);
++ return 0;
++
++ case TIOCMGET:
++ printk (KERN_INFO"%s: TIOCMGET: %04x\n", __FUNCTION__, acm->ctrlin & LINE_OUT_DTR ? TIOCM_DTR : 0 | TIOCM_CTS);
++ return put_user( acm->ctrlin & LINE_OUT_DTR ? TIOCM_DTR : 0 | TIOCM_CTS, (unsigned long *) arg);
++
++ case TIOCMSET:
++ case TIOCMBIS:
++ case TIOCMBIC:
++
++ printk (KERN_INFO"%s: TIOCM{SET,BIS,BIC}:\n", __FUNCTION__);
++ RETURN_EFAULT_IF (get_user(mask, (unsigned long *) arg));
++
++ printk (KERN_INFO"%s: TIOCM{SET,BIS,BIC}: %04x\n", __FUNCTION__, mask);
++
++ newctrl = acm->ctrlin;
++
++ mask = (mask & TIOCM_DTR ? LINE_IN_DCD|LINE_IN_DSR : 0)/* | (mask & TIOCM_RTS ? LINE_OUT_RTS : 0)*/;
++
++ switch(cmd) {
++ case TIOCMSET: newctrl = mask; break;
++ case TIOCMBIS: newctrl |= mask; break;
++ case TIOCMBIC: newctrl &= mask; break;
++ }
++ RETURN_ZERO_IF(acm->ctrlin == newctrl);
++
++ printk (KERN_INFO"%s: newctrl: %04x\n", __FUNCTION__, newctrl);
++ return acm_send_int_notification(function, CDC_NOTIFICATION_SERIAL_STATE, acm->ctrlin);
++
++ case 3:
++ return 0;
++ default:
++ printk (KERN_INFO"%s: unknown: %04x\n", __FUNCTION__, cmd);
++ break;
++ }
++ return -ENOIOCTLCMD;
++#endif
++}
++
++static void acm_tty_set_termios(struct tty_struct *tty, struct termios *termios_old)
++{
++ struct acm_private *acm = &acm_private;
++ struct termios *termios;
++
++ TRACE_MSG("entered");
++ //printk (KERN_INFO"%s: tty: %p\n", __FUNCTION__, tty);
++
++ RETURN_IF(!atomic_read(&acm->used) || !tty || !tty->termios);
++
++ termios = tty->termios;
++ acm->clocal = termios->c_cflag & CLOCAL;
++
++ //printk (KERN_INFO"%s: clocal: %d\n", __FUNCTION__, acm->clocal);
++ TRACE_MSG("exited");
++}
++
++/* ********************************************************************************************* */
++
++static void acm_wakeup_writers(void *private)
++{
++ struct acm_private *acm = &acm_private;
++ struct tty_struct *tty = acm->tty;
++
++ TRACE_MSG("entered");
++ MOD_DEC_USE_COUNT;
++
++ //printk (KERN_INFO"%s: MOD: %d connected: %d tty: %p\n", __FUNCTION__, MOD_IN_USE, acm->connected, tty);
++
++ RETURN_IF(!acm->connected || !atomic_read(&acm->used) || !tty);
++ TRACE_MSG("connected and used OK");
++
++ if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup) {
++ TRACE_MSG("ldisc wakeup");
++ (tty->ldisc.write_wakeup)(tty);
++ }
++
++ // printk (KERN_INFO"%s: write_wait wakeup\n", __FUNCTION__);
++ wake_up_interruptible(&tty->write_wait);
++ TRACE_MSG("exited");
++}
++
++
++/* ********************************************************************************************* */
++
++static int acm_tty_refcount;
++static struct tty_struct *acm_tty_table[ACM_TTY_MINORS];
++static struct termios *acm_tty_termios[ACM_TTY_MINORS];
++static struct termios *acm_tty_termios_locked[ACM_TTY_MINORS];
++
++static struct tty_driver acm_tty_driver = {
++ magic: TTY_DRIVER_MAGIC,
++ type: TTY_DRIVER_TYPE_SERIAL,
++ subtype: SERIAL_TYPE_NORMAL,
++ flags: TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,
++ driver_name: "acm-CDC",
++ name: "usb/acm/%d",
++ major: ACM_TTY_MAJOR,
++ num: ACM_TTY_MINORS,
++ minor_start: 0,
++
++ open: acm_tty_open,
++ close: acm_tty_close,
++ write: acm_tty_write,
++ write_room: acm_tty_write_room,
++ ioctl: acm_tty_ioctl,
++ throttle: acm_tty_throttle,
++ unthrottle: acm_tty_unthrottle,
++ chars_in_buffer: acm_tty_chars_in_buffer,
++ set_termios: acm_tty_set_termios,
++
++ refcount: &acm_tty_refcount,
++ table: acm_tty_table,
++ termios: acm_tty_termios,
++ termios_locked: acm_tty_termios_locked,
++};
++
++
++/* Transmit INTERRUPT ************************************************************************** */
++
++/**
++ * Generates a response urb on the notification (INTERRUPT) endpoint.
++ * Return a non-zero result code to STALL the transaction.
++ * CALLED from interrupt context.
++ */
++static int acm_send_int_notification(struct usb_function_instance *function, int bnotification, int data)
++{
++ struct acm_private *acm = &acm_private;
++ struct urb *urb = NULL;
++ struct cdc_notification_descriptor *notification;
++ unsigned long flags;
++ int rc;
++
++ //printk(KERN_INFO"%s: function: %p connected: %d DTR: %d\n", __FUNCTION__,
++ // function, acm->connected, acm->ctrlout & LINE_OUT_DTR);
++
++ local_irq_save(flags);
++ TRACE_MSG("entered");
++
++ do {
++ BREAK_IF(!function);
++ //BREAK_IF(!acm->connected || !acm->ctrlout & LINE_OUT_DTR);
++ BREAK_IF(!acm->connected);
++
++ //printk (KERN_INFO"%s: bnotification: %x data: %d int_urb: %p\n",
++ // __FUNCTION__, bnotification, data, acm->int_urb);
++
++ if (acm->int_urb) {
++ //uuu printk(KERN_INFO"%s: int_urb: %p\n", __FUNCTION__, acm->int_urb);
++ usbd_cancel_urb_irq(acm->int_urb);
++ acm->int_urb = NULL;
++ }
++
++ //printk(KERN_INFO"%s: AAA\n", __FUNCTION__);
++
++ //uuu printk(KERN_INFO"%s:\n", __FUNCTION__);
++ BREAK_IF(!(urb = usbd_alloc_urb (function, INT_IN,
++ sizeof(struct cdc_notification_descriptor), acm_urb_sent_int)));
++
++ //printk(KERN_INFO"%s: BBB\n", __FUNCTION__);
++
++ memset(urb->buffer, 0, urb->buffer_length);
++ urb->actual_length = sizeof(struct cdc_notification_descriptor);
++ urb->privdata = &acm_private;
++
++ // fill in notification structure
++ notification = (struct cdc_notification_descriptor *) urb->buffer;
++
++ notification->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
++ notification->bNotification = bnotification;
++
++ switch (bnotification) {
++ case CDC_NOTIFICATION_NETWORK_CONNECTION:
++ notification->wValue = data;
++ break;
++ case CDC_NOTIFICATION_SERIAL_STATE:
++ notification->wLength = cpu_to_le16(2);
++ *((unsigned short *)notification->data) = cpu_to_le16(data);
++ break;
++ }
++
++ acm->int_urb = urb;
++ //printk(KERN_INFO"%s: CCC\n", __FUNCTION__);
++ BREAK_IF(!(rc = usbd_send_urb (urb)));
++
++ //uuu printk(KERN_ERR"%s: usbd_send_urb failed err: %x\n", __FUNCTION__, rc);
++ acm->int_urb = urb;
++ urb->privdata = NULL;
++ usbd_dealloc_urb (urb);
++
++ } while(0);
++
++ TRACE_MSG1("urbID#%04x --> 0",urbID(urb));
++ local_irq_restore(flags);
++ //printk(KERN_INFO"%s: DDD\n", __FUNCTION__);
++ return 0;
++}
++
++/* Callback functions for TX urb completion (function chosen when urb is allocated) ***********/
++
++/* acm_urb_sent_bulk - called to indicate URB transmit finished
++ * @urb: pointer to struct urb
++ * @rc: result
++ */
++static int acm_urb_sent_bulk (struct urb *urb, int rc)
++{
++ struct acm_private *acm = &acm_private;
++ struct usb_function_instance *function;
++
++ acm_interrupts++;
++ TRACE_MSG2("entered urbID#%04x rc=%d",urbID(urb),rc);
++
++ if (!urb || !(function = urb->function_instance)) {
++ TRACE_MSG1("urbID#%04x --> -EINVAL",urbID(urb));
++ return(-EINVAL);
++ }
++ TRACE_MSG1("IN length=%d",urb->actual_length);
++
++ atomic_sub(urb->actual_length, &acm->queued_bytes);
++ atomic_dec(&acm->queued_urbs);
++ urb->privdata = NULL;
++ usbd_dealloc_urb (urb);
++ acm_schedule(&acm->wqueue);
++ TRACE_MSG1("urbID#%04x --> 0",urbID(urb));
++ return 0;
++}
++
++/* acm_urb_sent_int - called to indicate URB transmit finished
++ * @urb: pointer to struct urb
++ * @rc: result
++ */
++static int acm_urb_sent_int (struct urb *urb, int rc)
++{
++ struct acm_private *acm = &acm_private;
++ struct usb_function_instance *function;
++
++ acm_interrupts++;
++ TRACE_MSG2("entered urbID#%04x rc=%d",urbID(urb),rc);
++ //printk(KERN_INFO"%s: urb: %p function: %p rc: %d\n", __FUNCTION__, urb, urb->function_instance, rc);
++ if (!urb || !(function = urb->function_instance)) {
++ TRACE_MSG1("urbID#%04x --> -EINVAL",urbID(urb));
++ return(-EINVAL);
++ }
++ TRACE_MSG1("INT length=%d",urb->actual_length);
++
++ acm->int_urb = NULL;
++ usbd_dealloc_urb(urb);
++ TRACE_MSG1("urbID#%04x --> 0",urbID(urb));
++ return 0;
++}
++
++#if defined(CONFIG_USBD_ACM_DATALOG)
++/* acm_urb_sent_pst - called to indicate URB transmit finished
++ * @urb: pointer to struct urb
++ * @rc: result
++ */
++int acm_urb_sent_pst (struct urb *urb, int rc)
++{
++ struct acm_private *acm = &acm_private;
++ struct usb_function_instance *function;
++
++ acm_interrupts++;
++ TRACE_MSG2("entered urbID#%04x rc=%d",urbID(urb),rc);
++ //uuu printk(KERN_INFO"urb: %p function: %p rc: %d\n", urb, urb->function_instance, rc);
++ if (!urb || !(function = urb->function_instance)) {
++ TRACE_MSG1("urbID#%04x --> -EINVAL",urbID(urb));
++ return(-EINVAL);
++ }
++ TRACE_MSG1("PST length=%d",urb->actual_length);
++
++#if defined(PST_FD_AVAILABLE)
++ pst_urb_sent(urb, rc);
++#endif
++ urb->privdata = NULL;
++ usbd_dealloc_urb(urb);
++ TRACE_MSG1("urbID#%04x --> 0",urbID(urb));
++ return 0;
++}
++#endif
++
++/* USB Device Functions ************************************************************************ */
++
++/* acm_event_irq - process a device event
++ *
++ */
++void acm_event_irq (struct usb_function_instance *function, usb_device_event_t event, int data)
++{
++ struct acm_private *acm = &acm_private;
++ int i;
++
++ acm_interrupts++;
++ TRACE_MSG1("entered ev=%d",event);
++ switch (event) {
++
++#if defined(CONFIG_USBD_ACM_DATALOG)
++ case DEVICE_CREATE:
++#if defined(PST_FD_AVAILABLE)
++ if (0 != (ret = pst_dev_create(device)))
++ return;
++#endif
++ break;
++
++ case DEVICE_DESTROY:
++#if defined(PST_FD_AVAILABLE)
++ pst_dev_destroy();
++#endif
++ break;
++#endif
++
++ case DEVICE_CONFIGURED:
++ TRACE_MSG("CONFIGURED");
++ acm->connected = 1;
++ acm_schedule(&acm->wqueue);
++ for (i = 0; i < MAX_RECV_URBS; i++) {
++ struct urb *urb;
++ // printk(KERN_INFO"%s:\n", __FUNCTION__);
++ BREAK_IF(!(urb = usbd_alloc_urb(function, BULK_OUT,
++ usbd_endpoint_transferSize(function, BULK_OUT,usbd_high_speed(function)),
++ acm_recv_urb)));
++ if (usbd_start_recv(urb))
++ usbd_dealloc_urb(urb);
++ }
++ break;
++
++ case DEVICE_RESET:
++ case DEVICE_DE_CONFIGURED:
++ TRACE_MSG("RESET");
++ BREAK_IF(!acm->connected);
++ acm->connected = 0;
++ acm->int_urb = NULL;
++ acm_schedule(&acm->hqueue);
++ // XXX flush
++ // Release any queued urbs
++ break;
++
++ default: break;
++ }
++ TRACE_MSG("exited");
++}
++
++static int acm_recv_urb (struct urb *urb, int rc)
++{
++ /* Return 0 if urb has been accepted,
++ return 1 and expect caller to deal with urb release otherwise. */
++ struct acm_private *acm = &acm_private;
++ struct tty_struct *tty = acm->tty;
++ struct urb *furb;
++
++ acm_interrupts++;
++ TRACE_MSG1("entered rc=%d",rc);
++ //printk(KERN_INFO"%s: urb: %p rc=%d\n", __FUNCTION__, urb, rc);
++ if (RECV_CANCELLED == rc) {
++ TRACE_MSG1("cancelled URB=%p",urb);
++ usbd_dealloc_urb(urb);
++ return(0);
++ }
++ if (RECV_OK != rc) {
++ // Shouldn't happen, but...
++ // Reject it.
++ TRACE_MSG1("rejected URB=%p",urb);
++ //printk(KERN_INFO"%s: rejecting URB %p rc=%d\n", __FUNCTION__, urb, rc);
++ return(1);
++ }
++ // Queue it for forwarding, then kick off forwarding routine.
++ acm->bytes_received += urb->actual_length;
++ acm->recv_ring[acm->rr_in_ndx] = urb;
++ acm->rr_in_ndx = (acm->rr_in_ndx + 1) % RECV_RING_SIZE;
++ if (urb == (furb = acm_frwd_recv_urbs(tty,acm))) {
++ // Couldn't restart urb, tell the caller to dispose of it.
++ TRACE_MSG1("caller to release URB=%p",urb);
++ //printk(KERN_INFO"%s: caller to release URB %p rc=%d\n", __FUNCTION__, urb, rc);
++ return(1);
++ }
++ if (NULL != furb) {
++ /* Couldn't restart some other urb, but we can't tell the caller
++ about it, so we need to dispose of it ourselves. This should
++ only happen if the bi layer is shutting down, so we let someone
++ else allocate the replacement if one is needed. */
++ TRACE_MSG1("releasing URB=%p",urb);
++ usbd_dealloc_urb(urb);
++ }
++ TRACE_MSG("--> 0");
++ return(0);
++}
++
++/* acm_line_coding_urb_received - callback for sent URB
++ *
++ * Handles notification that an urb has been sent (successfully or otherwise).
++ *
++ * Returns non-zero for failure.
++ */
++static int acm_line_coding_urb_received (struct urb *urb, int urb_rc)
++{
++ TRACE_MSG2("urbID#%04x rc=%d",urbID(urb),urb_rc);
++
++ RETURN_EINVAL_IF (RECV_OK != urb_rc);
++
++ return -EINVAL; // caller will de-allocate
++}
++
++/* acm_recv_setup_irq - called to indicate urb has been received
++ */
++int acm_recv_setup_irq (struct usb_device_request *request)
++{
++ struct acm_private *acm = &acm_private;
++ struct usb_function_instance *function = acm->function;
++
++ acm_interrupts++;
++ TRACE_SETUP(request);
++
++ // verify that this is a usb class request per cdc-acm specification or a vendor request.
++ if (!(request->bmRequestType & (USB_REQ_TYPE_CLASS | USB_REQ_TYPE_VENDOR))) {
++ TRACE_MSG("--> 0");
++ return(0);
++ }
++
++ // determine the request direction and process accordingly
++ switch (request->bmRequestType & (USB_REQ_DIRECTION_MASK | USB_REQ_TYPE_MASK)) {
++
++ case USB_REQ_HOST2DEVICE | USB_REQ_TYPE_CLASS:
++ switch (request->bRequest) {
++ case CDC_CLASS_REQUEST_SEND_ENCAPSULATED: break;
++ case CDC_CLASS_REQUEST_SET_COMM_FEATURE: break;
++ case CDC_CLASS_REQUEST_CLEAR_COMM_FEATURE: break;
++ case CDC_CLASS_REQUEST_SET_LINE_CODING:
++ {
++ struct urb *urb;
++ int len = le16_to_cpu(request->wLength);
++ TRACE_MSG1("SET_LINE_CODING wLength=%d",len);
++ if (len <= 0) {
++ TRACE_MSG("(len<=0)--> 0");
++ return(0);
++ }
++ // Set up an ep0 recv urb for the rest of it.
++ urb = usbd_alloc_urb_ep0(function, len, acm_line_coding_urb_received);
++ if (NULL == urb) {
++ TRACE_MSG("no mem for ep0 recv urb");
++ return(-EINVAL);
++ }
++ if (usbd_start_recv(urb)) {
++ TRACE_MSG("usbd_start_recv() failed");
++ usbd_dealloc_urb(urb); // de-alloc if error
++ TRACE_MSG("--> -EINVAL");
++ return(-EINVAL);
++ }
++ }
++ break;
++ case CDC_CLASS_REQUEST_SET_CONTROL_STATE:
++ {
++ struct acm_private *acm = &acm_private;
++ unsigned int prev_ctrlout = acm->ctrlout;
++ acm->ctrlout = le16_to_cpu(request->wValue);
++
++ TRACE_MSG1("set control state, tty=%p",acm->tty);
++ //uuu printk(KERN_INFO"%s: tty: %p clocal: %x ctrlout: %02x DTR: %x\n",
++ //uuu __FUNCTION__, acm->tty, acm->clocal, acm->ctrlout, acm->ctrlout & LINE_OUT_DTR);
++
++ // schedule writers or hangup IFF open
++ BREAK_IF(!acm->tty);
++ TRACE_MSG1("set control state, ctrlout#%04x",acm->ctrlout);
++ // make sure there really is a state change
++ if ((acm->ctrlout ^ prev_ctrlout) & LINE_OUT_DTR) {
++ TRACE_MSG1("DTR state changed -> %x",(acm->ctrlout&LINE_OUT_DTR));
++ //printk(KERN_INFO"%s: tty: %p DTR state changed -> %u\n",
++ // __FUNCTION__, acm->tty, (acm->ctrlout&LINE_OUT_DTR));
++ acm_schedule(((acm->ctrlout & LINE_OUT_DTR) ? &acm->wqueue : &acm->hqueue));
++ // wake up blocked opens
++ if (acm->open_wait_count > 0) {
++ wake_up_interruptible(&acm->open_wait);
++ }
++ } // end of state change operation
++
++ // send notification if we have DCD
++ TRACE_MSG1("checking DCD ctrlin#%04x",acm->ctrlin);
++ BREAK_IF(!(acm->ctrlin & (LINE_IN_DCD | LINE_IN_DSR)));
++ TRACE_MSG1("tty=%p sending (DCD|DSR) notification",acm->tty);
++ acm_send_int_notification(function, CDC_NOTIFICATION_SERIAL_STATE, acm->ctrlin);
++ }
++ break;
++
++ case CDC_CLASS_REQUEST_SEND_BREAK: break;
++ default: break;
++ }
++ TRACE_MSG("--> 0");
++ return 0;
++
++ case USB_REQ_DEVICE2HOST | USB_REQ_TYPE_CLASS:
++ switch (request->bRequest) {
++ case CDC_CLASS_REQUEST_GET_ENCAPSULATED: break;
++ case CDC_CLASS_REQUEST_GET_COMM_FEATURE: break;
++ case CDC_CLASS_REQUEST_GET_LINE_CODING:
++ {
++ struct urb *urb;
++ struct cdc_acm_line_coding *results;
++ int len = le16_to_cpu(request->wLength);
++ if (len != sizeof(struct cdc_acm_line_coding)) {
++ TRACE_MSG2("(len=%d!=sz=%d--> -EINVAL",len,sizeof(struct cdc_acm_line_coding));
++ return -EINVAL;
++ }
++
++ if (!(urb = usbd_alloc_urb_ep0(function, len, NULL))) {
++ TRACE_MSG("(nomem)--> -EINVAL");
++ return -EINVAL;
++ }
++ results = (struct cdc_acm_line_coding *)urb->buffer;
++ results->dwDTERate = cpu_to_le16(0x1c200); // 115200
++ results ->bDataBits = 0x08;
++ urb->actual_length = len;
++ TRACE_MSG1("sending line coding urb=%p",(u32)(void*)urb);
++ if (!usbd_send_urb(urb)) {
++ TRACE_MSG("--> 0");
++ return(0);
++ }
++ usbd_dealloc_urb(urb);
++ TRACE_MSG("(send failed)--> -EINVAL");
++ return -EINVAL;
++ }
++ default: break;
++ }
++ TRACE_MSG("--> 0");
++ return 0;
++
++ case USB_REQ_HOST2DEVICE | USB_REQ_TYPE_VENDOR: break;
++ case USB_REQ_DEVICE2HOST | USB_REQ_TYPE_VENDOR: break;
++#if defined(PST_FD_AVAILABLE)
++ ep0_process_vendor_request( urb );
++ TRACE_MSG("--> 0");
++ return 0;
++#endif
++
++ default: break;
++ }
++ TRACE_MSG("--> 0");
++ return 0;
++}
++
++
++static int acm_function_enable (struct usb_function_instance *function)
++{
++ struct acm_private *acm = &acm_private;
++ acm_interrupts++;
++ TRACE_MSG("entered");
++ MOD_INC_USE_COUNT;
++ acm->function = function;
++ acm->writesize = usbd_endpoint_wMaxPacketSize(function, BULK_OUT, 0) * 4; // QQSV
++ TRACE_MSG("-> 0");
++ return 0;
++}
++
++static void acm_function_disable (struct usb_function_instance *function)
++{
++ struct acm_private *acm = &acm_private;
++ acm_interrupts++;
++ TRACE_MSG("entered");
++ acm->writesize = 0;
++ acm->function = NULL;
++ MOD_DEC_USE_COUNT;
++ TRACE_MSG("exited");
++}
++
++
++static struct usb_function_operations function_ops = {
++ event_irq: acm_event_irq,
++ recv_setup_irq: acm_recv_setup_irq,
++ function_enable: acm_function_enable,
++ function_disable: acm_function_disable,
++};
++
++static struct usb_function_driver function_driver = {
++ name: "acm-CDC",
++ fops:&function_ops,
++ device_description:&acm_device_description,
++ bNumConfigurations:sizeof (acm_description) / sizeof (struct usb_configuration_description),
++ configuration_description:acm_description,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_ACM_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_ACM_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_ACM_BCDDEVICE),
++};
++
++#if defined(USE_TICKER)
++/* usb ticker ********************************************************************************** */
++
++#define retrytime 10
++
++int ticker_terminating;
++int ticker_timer_set;
++
++static DECLARE_MUTEX_LOCKED (ticker_sem_start);
++static DECLARE_MUTEX_LOCKED (ticker_sem_work);
++
++void ticker_tick (unsigned long data)
++{
++ ticker_timer_set = 0;
++ up (&ticker_sem_work);
++}
++
++void udc_ticker_poke (void)
++{
++ up (&ticker_sem_work);
++}
++
++int ticker_thread (void *data)
++{
++ struct timer_list ticker;
++ // detach
++ lock_kernel ();
++ exit_mm (current);
++ exit_files (current);
++ exit_fs (current);
++
++ // setsid equivalent, used at start of kernel thread, no error checks needed, or at least none made :).
++ current->leader = 1;
++ current->session = current->pgrp = current->pid;
++ current->tty = NULL;
++ current->tty_old_pgrp = 0;
++ sprintf (current->comm, "acm_fd");
++
++ // setup signal handler
++ current->exit_signal = SIGCHLD;
++ spin_lock (&current->sigmask_lock);
++ flush_signals (current);
++ spin_unlock (&current->sigmask_lock);
++
++ // run at a high priority, ahead of sync and friends
++ current->policy = SCHED_OTHER;
++ unlock_kernel ();
++
++ // setup timer
++ init_timer (&ticker);
++ ticker.data = 0;
++ ticker.function = ticker_tick;
++
++ // let startup continue
++ up (&ticker_sem_start);
++
++ // process loop
++ for (ticker_timer_set = ticker_terminating = 0; !ticker_terminating;) {
++
++ struct acm_private * acm = &acm_private;
++
++ if (!ticker_timer_set) {
++ mod_timer (&ticker, jiffies + HZ * retrytime);
++ }
++
++ // wait for someone to tell us to do something
++ down (&ticker_sem_work);
++
++ // sanity checks before proceeding
++ BREAK_IF(ticker_terminating);
++ CONTINUE_IF(!(function = acm->function));
++ CONTINUE_IF(USBD_OK != bus->status);
++
++ // do what we need to do
++ acm_send_int_notification(function, CDC_NOTIFICATION_SERIAL_STATE, acm->ctrlin);
++ }
++
++ // remove timer, let the process stopping us know we are done and return
++ del_timer (&ticker);
++ up (&ticker_sem_start);
++ return 0;
++}
++#endif
++
++
++/* USB Module init/exit ************************************************************************ */
++/*
++ * acm_modinit - module init
++ *
++ */
++static int acm_modinit (void)
++{
++ int i;
++ printk (KERN_INFO "Copyright (c) 2003-2004 sl@belcarra.com\n");
++
++ if (0 != acm_trace_init(ACM_TRACE_NAME)) {
++ printk(KERN_ERR"%s: ERROR tracing configured, but init failed.\n", __FUNCTION__);
++ return -EINVAL;
++ }
++ TRACE_MSG("entered");
++
++ if (vendor_id)
++ function_driver.idVendor = cpu_to_le16(vendor_id);
++ if (product_id)
++ function_driver.idProduct = cpu_to_le16(product_id);
++ printk (KERN_INFO "%s: %s vendor_id: %04x product_id: %04x\n", __FUNCTION__,
++ __usbd_module_info, function_driver.idVendor, function_driver.idProduct);
++
++ // initialize private structure
++ acm_private.tty_driver = &acm_tty_driver;
++ acm_private.wqueue.routine = acm_wakeup_writers;
++ acm_private.wqueue.data = &acm_private;
++ acm_private.hqueue.routine = acm_hangup;
++ acm_private.hqueue.data = &acm_private;
++
++ init_waitqueue_head(&acm_private.open_wait);
++
++ for (i = 0; i < RECV_RING_SIZE; i++) {
++ acm_private.recv_ring[i] = NULL;
++ }
++ acm_private.rr_in_ndx = acm_private.rr_out_ndx = 0;
++
++ // register as tty driver
++ acm_tty_driver.init_termios = tty_std_termios;
++ acm_tty_driver.init_termios.c_cflag = B115200 | CS8 | CREAD | HUPCL | CLOCAL;
++ acm_tty_driver.init_termios.c_lflag &= ~(ECHO | ICANON);
++ THROW_IF(tty_register_driver(&acm_tty_driver), error);
++
++ tty_register_devfs(&acm_tty_driver, 0, ACM_TTY_MINOR);
++ acm_private.tty_driver_registered++;
++
++ // register as usb function driver
++ THROW_IF (usbd_register_function (&function_driver), error);
++ acm_private.usb_driver_registered++;
++
++#if defined(USE_TICKER)
++ // kickoff_thread - start management thread
++ //ticker_terminating = 0;
++ //kernel_thread (&ticker_thread, NULL, 0);
++ //down (&ticker_sem_start);
++#endif
++
++ CATCH(error) {
++ printk(KERN_ERR"%s: ERROR\n", __FUNCTION__);
++
++ if (acm_private.tty_driver_registered) {
++ tty_unregister_driver(&acm_tty_driver);
++ acm_private.tty_driver_registered = 0;
++ }
++ if (acm_private.usb_driver_registered) {
++ usbd_deregister_function (&function_driver);
++ acm_private.usb_driver_registered = 0;
++ }
++ TRACE_MSG("--> -EINVAL");
++ return -EINVAL;
++ }
++ TRACE_MSG("--> 0");
++ return 0;
++}
++
++void acm_wait_task(struct tq_struct *queue)
++{
++ TRACE_MSG1("entered data=%p",queue->data);
++ RETURN_IF(!queue->data);
++ queue->data = NULL;
++ while (queue->sync) {
++ //uuu printk(KERN_INFO"%s: waiting for queue: %p\n", __FUNCTION__, queue);
++ TRACE_MSG1("waiting for queue: %p",queue);
++ schedule_timeout(HZ);
++ }
++ TRACE_MSG("exited");
++}
++
++/* acm_modexit - module cleanup
++ */
++static void acm_modexit (void)
++{
++ unsigned long flags;
++ struct urb *urb;
++ TRACE_MSG("entered");
++
++#if defined(USE_TICKER)
++ // killoff_thread - stop management thread
++ //if (!ticker_terminating) {
++ // ticker_terminating = 1;
++ // up (&ticker_sem_work);
++ // down (&ticker_sem_start);
++ //}
++#endif
++
++ // Wake up any pending opens after setting the exiting flag.
++ local_irq_save(flags);
++ acm_private.exiting = 1;
++ if (acm_private.open_wait_count > 0) {
++ wake_up_interruptible(&acm_private.open_wait);
++ }
++ local_irq_restore(flags);
++
++ // verify no tasks are running
++ acm_wait_task(&acm_private.wqueue);
++ acm_wait_task(&acm_private.hqueue);
++
++ // de-register as tty and usb drivers
++ if (acm_private.tty_driver_registered) {
++ tty_unregister_driver(&acm_tty_driver);
++ }
++ if (acm_private.usb_driver_registered) {
++ usbd_deregister_function (&function_driver);
++ }
++
++ // Flush any urbs in the recv_ring.
++ while (acm_private.rr_in_ndx != acm_private.rr_out_ndx) {
++ // Remove and dealloc one URB from the receive ring
++ local_irq_save(flags);
++ urb = acm_private.recv_ring[acm_private.rr_out_ndx];
++ acm_private.recv_ring[acm_private.rr_out_ndx] = NULL;
++ acm_private.rr_out_ndx = (acm_private.rr_out_ndx + 1) % RECV_RING_SIZE;
++ local_irq_restore(flags);
++ // printk(KERN_INFO"%s: releasing URB %p\n", __FUNCTION__, urb);
++ usbd_dealloc_urb(urb);
++ }
++ acm_trace_exit(ACM_TRACE_NAME);
++}
++
++
++module_init (acm_modinit);
++module_exit (acm_modexit);
+diff -Nru a/drivers/usbd/acm_fd/trace.c b/drivers/usbd/acm_fd/trace.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/acm_fd/trace.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,530 @@
++/*
++ * usbd/acm_fd/trace.c
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2002 Lineo
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/version.h>
++
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++
++#include <linux/proc_fs.h>
++#include <linux/vmalloc.h>
++
++#include <asm/atomic.h>
++#include <asm/io.h>
++
++#include <linux/proc_fs.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6)
++#define USE_ADD_DEL_TIMER_FOR_USBADDR_CHECK 1
++#include <linux/timer.h>
++#else
++#undef USE_ADD_DEL_TIMER_FOR_USBADDR_CHECK
++#include <linux/tqueue.h>
++#endif
++
++#include <linux/netdevice.h>
++#include <linux/pci.h>
++#include <linux/cache.h>
++
++
++#if defined(CONFIG_ARCH_SA1100) || defined (CONFIG_ARCH_PXA)
++#include <asm/dma.h>
++#include <asm/mach/dma.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/hardware.h>
++#include <asm/types.h>
++#endif
++
++#if defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
++#include <asm/au1000.h>
++#include <asm/au1000_dma.h>
++#include <asm/mipsregs.h>
++#endif
++
++#if defined(CONFIG_ARCH_SAMSUNG)
++#include <asm/arch/timers.h>
++#include <asm/arch/hardware.h>
++#endif
++
++#if defined(CONFIG_ARCH_MX1ADS)
++#include "dbmx1_bi/dbmx1.h"
++#endif
++
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/pgalloc.h>
++
++#include <usbd-chap9.h>
++#include <usbd-mem.h>
++#include <usbd.h>
++#include <trace.h>
++
++
++int acm_trace_first;
++int acm_trace_last_read;
++int acm_trace_next;
++int acm_trace_total;
++acm_trace_t *acm_traces;
++
++extern int acm_interrupts;
++
++
++#if defined(CONFIG_USBD_ACM_TRACE) && defined(CONFIG_PROC_FS)
++
++acm_trace_t *ACM_TRACE_NEXT(char *fn, acm_trace_types_t acm_trace_type)
++{
++ acm_trace_t *p;
++ unsigned long flags;
++
++ // Get the next trace slot - this needs to be atomic.
++ local_irq_save (flags);
++ p = acm_traces + acm_trace_next;
++#if defined(TRACE_MAX_IS_2N)
++ acm_trace_next = (acm_trace_next + 1) & TRACE_MASK;
++ if (acm_trace_next == acm_trace_first) {
++ // We have wraparound, bump acm_trace_first
++ if (acm_trace_first == acm_trace_last_read) {
++ // We have to bump last read too.
++ acm_trace_last_read = (acm_trace_last_read + 1) & TRACE_MASK;
++ }
++ acm_trace_first = (acm_trace_first + 1) & TRACE_MASK;
++ }
++#else
++ if (TRACE_MAX <= ++acm_trace_next)
++ acm_trace_next = 0;
++
++ if (acm_trace_next == acm_trace_first) {
++ // We have wrap around, bump acm_trace_first
++ if (acm_trace_first == acm_trace_last_read) {
++ // We have to bump last read too.
++ if (TRACE_MAX <= ++acm_trace_last_read)
++ acm_trace_last_read = 0;
++ }
++ if (TRACE_MAX <= ++acm_trace_first)
++ acm_trace_first = 0;
++ }
++#endif
++ acm_trace_total++;
++ // End of next trace slot.
++ local_irq_restore (flags);
++
++#if defined(CONFIG_ARCH_SA1100) || defined (CONFIG_ARCH_PXA)
++ p->oscr = OSCR;
++#elif defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19)
++ p->cp0_count = __read_32bit_c0_register(CP0_COUNT);
++#else
++ p->cp0_count = read_c0_count();
++#endif
++#elif defined(CONFIG_ARCH_SAMSUNG)
++ //p->jiffies = jiffies;
++ //p->tcnt0 = *(volatile u32 *)TCNT0;
++ p->tcnt1 = *(volatile u32 *)TCNT1;
++#else
++ p->jiffies = jiffies;
++#endif
++#if defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
++ //p->sofs = au_readl(USBD_FRAMENUM);
++#endif
++#if defined(CONFIG_ARCH_MX1ADS)
++ p->sofs = USBD_FRAME & 0x3ff;
++#endif
++
++ p->interrupts = acm_interrupts;
++ p->acm_trace_type = acm_trace_type;
++ p->function = fn;
++
++ //printk(KERN_INFO"first: %d next: %d interrupts: %d oscr: %d\n", acm_trace_first, acm_trace_next, acm_interrupts, p->oscr);
++
++ return p;
++}
++
++/* Proc Filesystem *************************************************************************** */
++
++/* *
++ * acm_trace_proc_read - implement proc file system read.
++ * @file
++ * @buf
++ * @count
++ * @pos
++ *
++ * Standard proc file system read function.
++ */
++static ssize_t acm_trace_proc_read (struct file *file, char *buf, size_t count, loff_t * pos)
++{
++ unsigned long page;
++ int len = 0;
++ int index;
++ int oindex;
++ int previous;
++ unsigned long flags;
++
++ acm_trace_t px;
++ acm_trace_t ox;
++ acm_trace_t *o, *p;
++
++
++ MOD_INC_USE_COUNT;
++
++ /* Get the index of the entry to read and update last_read - this needs to be atomic. */
++ p = &px;
++ o = NULL;
++ oindex = index = (*pos)++;
++ local_irq_save (flags);
++
++#if defined(TRACE_MAX_IS_2N)
++ index = (acm_trace_first + index) & TRACE_MASK;
++#else
++ index += acm_trace_first;
++ if (index >= TRACE_MAX) {
++ index -= TRACE_MAX;
++ }
++#endif
++ // Are we at the end of the data?
++ if (((acm_trace_first < acm_trace_next) &&
++ (index >= acm_trace_first) && (index < acm_trace_next)) ||
++ ((acm_trace_first > acm_trace_next) &&
++ ((index < acm_trace_next) || (index >= acm_trace_first)))) {
++ // Nope, there's data to show.
++ memcpy(p,(acm_traces+index),sizeof(acm_trace_t));
++ // Is there a previous event?
++ previous = (index) ? (index - 1) : (TRACE_MAX - 1);
++ if (previous != acm_trace_next && acm_trace_total > 1) {
++ // There is a valid previous event.
++ o = &ox;
++ memcpy(o,(acm_traces+previous),sizeof(acm_trace_t));
++ }
++ acm_trace_last_read = index;
++ } else {
++ index = -1;
++ }
++ local_irq_restore (flags);
++ if (index < 0) {
++ // End of data.
++ return(0);
++ }
++
++ // get a page, max 4095 bytes of data...
++ if (!(page = get_free_page (GFP_KERNEL))) {
++ MOD_DEC_USE_COUNT;
++ return -ENOMEM;
++ }
++
++ len = 0;
++
++ if (oindex == 0) {
++#if defined(CONFIG_ARCH_SAMSUNG)
++ len += sprintf ((char *) page + len, " Index Ints Ticks [%d]\n", CONFIG_USBD_SMDK2500_BCLOCK );
++#else
++ len += sprintf ((char *) page + len, " Index Ints Ticks\n");
++#endif
++ }
++
++ //printk(KERN_INFO"first: %d next: %d index: %d %d prev: %d\n", acm_trace_first, acm_trace_next, oindex, index, previous);
++
++#if defined(CONFIG_ARCH_SA1100) || defined (CONFIG_ARCH_PXA) || defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
++ u32 ticks = 0;
++#elif defined(CONFIG_ARCH_SAMSUNG)
++ u32 ticks = 0;
++#else
++ u64 jifs = 0;
++#endif
++ unsigned char *cp;
++ unsigned int *ip;
++ int skip = 0;
++
++ /* If there is a previous trace event, we want to calculate how many
++ ticks have elapsed siince it happened. Unfortunately, determining
++ if there _is_ a previous event isn't obvious, since we have to watch
++ out for startup and wraparound. */
++ if (o != NULL) {
++
++#if defined(CONFIG_ARCH_SA1100) || defined (CONFIG_ARCH_PXA)
++ /*
++ * oscr is 3.6864 Mhz free running counter,
++ *
++ * 1/3.6864 = .2712
++ * 60/221 = .2714
++ *
++ */
++ if (o->oscr) {
++ ticks = (p->oscr > o->oscr) ? (p->oscr - o->oscr) : (o->oscr - p->oscr) ;
++ ticks = (ticks * 60) / 221;
++ }
++
++#elif defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
++ /*
++ * cp0_count is incrementing timer at system clock
++ */
++ if (o->cp0_count) {
++ ticks = (p->cp0_count > o->cp0_count) ?
++ (p->cp0_count - o->cp0_count) : (o->cp0_count - p->cp0_count) ;
++ ticks = ticks / CONFIG_USBD_AU1X00_SCLOCK;
++ }
++
++#elif defined(CONFIG_ARCH_SAMSUNG)
++ /*
++ * tcnt1 is a count-down timer running at the system bus clock
++ * The divisor must be set as a configuration value, typically 66 or 133.
++ */
++ if (o->tcnt1) {
++ ticks = (p->tcnt1 < o->tcnt1) ? (o->tcnt1 - p->tcnt1) : (p->tcnt1 - o->tcnt1) ;
++ ticks /= CONFIG_USBD_SMDK2500_BCLOCK;
++ }
++#else
++ if (o->jiffies) {
++ jifs = p->jiffies - acm_traces[previous].jiffies;
++ }
++#endif
++
++ if (o->interrupts != p->interrupts) {
++ skip++;
++ }
++ }
++
++ //printk(KERN_INFO"index: %d interrupts: %d\n", index, p->interrupts);
++ len += sprintf ((char *) page + len, "%s%6d %8d ", skip?"\n":"", index, p->interrupts);
++
++#if defined(CONFIG_ARCH_SA1100) || defined (CONFIG_ARCH_PXA) || defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
++ if (ticks > 1024*1024) {
++ len += sprintf ((char *) page + len, "%8dM ", ticks>>20);
++ }
++ else {
++ len += sprintf ((char *) page + len, "%8d ", ticks);
++ }
++#elif defined(CONFIG_ARCH_SAMSUNG)
++ //len += sprintf ((char *) page + len, "%8u ", p->jiffies);
++ //len += sprintf ((char *) page + len, "%8u ", p->tcnt0);
++ len += sprintf ((char *) page + len, "%8u ", p->tcnt1);
++ if (ticks > 1024*1024) {
++ len += sprintf ((char *) page + len, "%8dM ", ticks>>20);
++ }
++ else {
++ len += sprintf ((char *) page + len, "%8d ", ticks);
++ }
++#else
++ if (jifs > 1024) {
++ len += sprintf ((char *) page + len, "%4dK ", (int)jifs>>10);
++ }
++ else {
++ len += sprintf ((char *) page + len, "%4d ", (int)jifs);
++ }
++#endif
++#if defined(CONFIG_ARCH_MX1ADS)
++ len += sprintf ((char *) page + len, "%6d ", (int)p->sofs);
++#endif
++
++ switch (p->acm_trace_type) {
++ case acm_trace_msg_n:
++ len += sprintf ((char *) page + len, " -- %s: ",p->function);
++ len += sprintf ((char *) page + len, p->trace.msg.msg);
++ break;
++
++ case acm_trace_msg32_n:
++ len += sprintf ((char *) page + len, " -- %s: ",p->function);
++ len += sprintf ((char *) page + len, p->trace.msg32.msg, p->trace.msg32.val);
++ break;
++
++ case acm_trace_msg16_n:
++ len += sprintf ((char *) page + len, " -- %s: ",p->function);
++ len += sprintf ((char *) page + len, p->trace.msg16.msg, p->trace.msg16.val0, p->trace.msg16.val1);
++ break;
++
++ case acm_trace_msg8_n:
++ len += sprintf ((char *) page + len, " -- %s: ",p->function);
++ len += sprintf ((char *) page + len, p->trace.msg8.msg,
++ p->trace.msg8.val0, p->trace.msg8.val1, p->trace.msg8.val2, p->trace.msg8.val3);
++ break;
++
++ case acm_trace_setup_n:
++ cp = (unsigned char *)&p->trace.setup;
++ len += sprintf ((char *) page + len,
++ " -- %s: request [%02x %02x %02x %02x %02x %02x %02x %02x]",
++ p->function, cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
++ break;
++ }
++ len += sprintf ((char *) page + len, "\n");
++
++ // len == 0 is valid, it just means we've reached the end of the data.
++ if (len > count) {
++ len = -EINVAL;
++ }
++ else if (len > 0 && copy_to_user (buf, (char *) page, len)) {
++ len = -EFAULT;
++ }
++ free_page (page);
++ MOD_DEC_USE_COUNT;
++ return len;
++}
++
++/* *
++ * acm_trace_proc_write - implement proc file system write.
++ * @file
++ * @buf
++ * @count
++ * @pos
++ *
++ * Proc file system write function.
++ */
++static ssize_t acm_trace_proc_write (struct file *file, const char *buf, size_t count, loff_t * pos)
++{
++#define MAX_TRACE_CMD_LEN 64
++ char command[MAX_TRACE_CMD_LEN+1];
++ size_t n = count;
++ size_t l;
++ char c;
++
++ if (n > 0) {
++ l = MIN(n,MAX_TRACE_CMD_LEN);
++ if (copy_from_user (command, buf, l)) {
++ count = -EFAULT;
++ } else {
++ // flush remainder, if any
++ n -= l;
++ while (n > 0) {
++ // Not too efficient, but it shouldn't matter
++ if (copy_from_user (&c, buf + (count - n), 1)) {
++ count = -EFAULT;
++ break;
++ }
++ n -= 1;
++ }
++ // Terminate command[]
++ if (l > 0 && command[l-1] == '\n') {
++ l -= 1;
++ }
++ command[l] = 0;
++ }
++ }
++
++ if (0 >= count) {
++ printk(KERN_INFO"%s: count <= 0 %d\n", __FUNCTION__, count);
++ return count;
++ }
++
++ if (!strncmp("flush", command, 5)) {
++ /* Move pointers so that next read continues from last read point,
++ instead of all available messages - this needs to be atomic. */
++ unsigned long flags;
++
++ local_irq_save (flags);
++#if defined(TRACE_MAX_IS_2N)
++ acm_trace_first = (acm_trace_last_read + 1) & TRACE_MASK;
++#else
++ if (TRACE_MAX <= (acm_trace_first = acm_trace_last_read + 1)) {
++ acm_trace_first = 0;
++ }
++#endif
++ local_irq_restore (flags);
++ }
++
++ return count;
++}
++
++static struct file_operations acm_trace_proc_operations_functions = {
++ read:acm_trace_proc_read,
++ write:acm_trace_proc_write,
++};
++
++#if defined(CONFIG_ARCH_SAMSUNG)
++#endif
++
++/**
++ * acm_trace_init
++ *
++ * Return non-zero if not successful.
++ */
++int acm_trace_init (char *name)
++{
++ printk(KERN_INFO"%s: creating /proc/%s with %u entries\n", __FUNCTION__,name,TRACE_MAX);
++ if (!(acm_traces = vmalloc(sizeof(acm_trace_t) * TRACE_MAX))) {
++ printk(KERN_ERR"%s: malloc failed %p %d\n", __FUNCTION__, acm_traces, sizeof(acm_trace_t) * TRACE_MAX);
++ return -EINVAL;
++ }
++ memset(acm_traces, 0, sizeof(acm_trace_t) * TRACE_MAX);
++ acm_trace_last_read = TRACE_MAX - 1;
++
++ {
++ struct proc_dir_entry *p;
++
++ // create proc filesystem entries
++ if ((p = create_proc_entry (name, 0, 0)) == NULL) {
++ printk(KERN_INFO"%s PROC FS failed\n",name);
++ }
++ else {
++ p->proc_fops = &acm_trace_proc_operations_functions;
++ }
++ }
++#if defined(CONFIG_ARCH_SAMSUNG)
++ *(volatile u32 *)TMOD |= 0x3 << 3;
++#endif
++ printk(KERN_INFO"%s: OK\n", __FUNCTION__);
++ return 0;
++}
++
++/**
++ * acm_trace_exit - remove procfs entry, free trace data space.
++ */
++void acm_trace_exit (char *name)
++{
++ {
++ unsigned long flags;
++ local_irq_save (flags);
++ remove_proc_entry (name, NULL);
++ if (acm_traces) {
++ acm_trace_t *p = acm_traces;
++ acm_traces = NULL;
++ vfree(p);
++ }
++ local_irq_restore (flags);
++ }
++}
++
++
++#else
++int acm_trace_init (char *name)
++{
++ return 0;
++}
++
++void acm_trace_exit (char *name)
++{
++ return;
++}
++#endif
++
++/* End of FILE */
++
+diff -Nru a/drivers/usbd/acm_fd/trace.h b/drivers/usbd/acm_fd/trace.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/acm_fd/trace.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,268 @@
++/*
++ * usbd/acm_fd/trace.h
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2002 Lineo
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#if defined(CONFIG_ARCH_SAMSUNG)
++#ifndef CONFIG_USBD_SMDK2500_BCLOCK
++#define CONFIG_USBD_SMDK2500_BCLOCK 66
++#endif
++#endif
++
++/* Fast Trace Utility
++ This set of definitions and code is meant to provide a _fast_ debugging facility
++ (much faster than printk) so that time critical code can be debugged by looking
++ at a trace of events provided by reading a file in the procfs without affecting
++ the timing of events in the critical code.
++
++ The mechanism used it to allocate a (large) ring buffer of relatively small structures
++ that include location and high-res timestamp info, and up to 8 bytes of optional
++ data. Values are stored and timestamps are taken as the critical code runs, but
++ data formatting and display are done during the procfs read, when more time is
++ available :).
++
++ Note that there is usually some machine dependent code involved in getting the
++ high-res timestamp, and there may be other bits used just to keep the overall
++ time impact as low as possible.
++
++ varargs style macros were avoided because there seems to be no way to avoid
++ a run-time check on the number of arguments if they are used, and the time penalty
++ doesn't seem to be worth the gain in utility.
++ */
++
++typedef enum acm_trace_types {
++ acm_trace_setup_n, acm_trace_msg_n, acm_trace_msg32_n, acm_trace_msg16_n, acm_trace_msg8_n
++} acm_trace_types_t;
++
++typedef struct acm_trace_msg {
++ char *msg;
++} acm_trace_msg_t;
++
++typedef struct acm_trace_msg32 {
++ u32 val;
++ char *msg;
++} acm_trace_msg32_t;
++
++typedef struct acm_trace_msg16 {
++ u16 val0;
++ u16 val1;
++ char *msg;
++} acm_trace_msg16_t;
++
++typedef struct acm_trace_msg8 {
++ u8 val0;
++ u8 val1;
++ u8 val2;
++ u8 val3;
++ char *msg;
++} acm_trace_msg8_t;
++
++
++typedef struct trace {
++ acm_trace_types_t acm_trace_type;
++ char *function;
++ u32 interrupts;
++#if defined(CONFIG_ARCH_SA1100) || defined (CONFIG_ARCH_PXA)
++ u32 oscr;
++#elif defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
++ u32 cp0_count;
++#elif defined(CONFIG_ARCH_SAMSUNG)
++ //u32 tcnt0;
++ u32 tcnt1;
++ //u64 jiffies;
++#else
++ u64 jiffies;
++#endif
++#if defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || defined(CONFIG_ARCH_MX1ADS)
++ u64 sofs;
++#endif
++ union {
++ acm_trace_msg_t msg;
++ acm_trace_msg8_t msg8;
++ acm_trace_msg16_t msg16;
++ acm_trace_msg32_t msg32;
++
++ struct usb_device_request setup;
++
++ } trace;
++
++} acm_trace_t;
++
++#define TRACE_MAX_IS_2N 1
++#if defined(TRACE_MAX_IS_2N)
++#define TRACE_MAX 0x00008000
++#define TRACE_MASK 0x00007FFF
++#else
++#define TRACE_MAX 30000
++#endif
++
++extern int acm_trace_first;
++extern int acm_trace_last_read;
++extern int acm_trace_next;
++
++extern acm_trace_t *acm_traces;
++
++#ifdef CONFIG_USBD_ACM_TRACE
++
++acm_trace_t *ACM_TRACE_NEXT(char *fn, acm_trace_types_t acm_trace_type);
++
++#if 0
++static __inline__ acm_trace_t *ACM_TRACE_NEXT(char *fn, acm_trace_types_t acm_trace_type)
++{
++ acm_trace_t *p;
++ unsigned long flags;
++
++ // Get the next trace slot - this needs to be atomic.
++ local_irq_save (flags);
++ p = acm_traces + acm_trace_next;
++#if defined(TRACE_MAX_IS_2N)
++ acm_trace_next = (acm_trace_next + 1) & TRACE_MASK;
++ if (acm_trace_next == acm_trace_first) {
++ // We have wraparound, bump acm_trace_first
++ if (acm_trace_first == acm_trace_last_read) {
++ // We have to bump last read too.
++ acm_trace_last_read = (acm_trace_last_read + 1) & TRACE_MASK;
++ }
++ acm_trace_first = (acm_trace_first + 1) & TRACE_MASK;
++ }
++#else
++ if (TRACE_MAX <= ++acm_trace_next)
++ acm_trace_next = 0;
++
++ if (acm_trace_next == acm_trace_first) {
++ // We have wrap around, bump acm_trace_first
++ if (acm_trace_first == acm_trace_last_read) {
++ // We have to bump last read too.
++ if (TRACE_MAX <= ++acm_trace_last_read)
++ acm_trace_last_read = 0;
++ }
++ if (TRACE_MAX <= ++acm_trace_first)
++ acm_trace_first = 0;
++ }
++#endif
++ // End of next trace slot.
++ local_irq_restore (flags);
++
++#if defined(CONFIG_ARCH_SA1100) || defined (CONFIG_ARCH_PXA)
++ p->oscr = OSCR;
++#elif defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
++ //p->cp0_count = __read_32bit_c0_register(CP0_COUNT);
++ p->cp0_count = read_c0_count();
++#elif defined(CONFIG_ARCH_SAMSUNG)
++ //p->jiffies = jiffies;
++ //p->tcnt0 = *(volatile u32 *)TCNT0;
++ p->tcnt1 = *(volatile u32 *)TCNT1;
++#else
++ p->jiffies = jiffies;
++#endif
++#if defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100)
++ //p->sofs = au_readl(USBD_FRAMENUM);
++#endif
++
++ p->interrupts = udc_interrupts;
++ p->acm_trace_type = acm_trace_type;
++ p->function = fn;
++
++ acm_trace_next++;
++ acm_trace_next = (acm_trace_next == TRACE_MAX) ? 0 : acm_trace_next;
++
++ if (acm_trace_next == acm_trace_first) {
++ acm_trace_first++;
++ acm_trace_first = (acm_trace_first == TRACE_MAX) ? 0 : acm_trace_first;
++ }
++ //printk(KERN_INFO"first: %d next: %d interrupts: %d\n", acm_trace_first, acm_trace_next, udc_interrupts);
++
++ return p;
++}
++#endif
++
++static __inline__ void acm_trace_setup(char *fn, struct usb_device_request *setup)
++{
++ if (acm_traces) {
++ acm_trace_t *p = ACM_TRACE_NEXT(fn,acm_trace_setup_n);
++ memcpy(&p->trace.setup, setup, sizeof(struct usb_device_request));
++ }
++}
++#define TRACE_SETUP(setup) acm_trace_setup(__FUNCTION__,setup)
++
++static __inline__ void acm_trace_msg(char *fn, char *msg)
++{
++ if (acm_traces) {
++ acm_trace_t *p = ACM_TRACE_NEXT(fn,acm_trace_msg_n);
++ p->trace.msg.msg = msg;
++ }
++}
++#define TRACE_MSG(msg) acm_trace_msg(__FUNCTION__,msg)
++
++
++static __inline__ void acm_trace_msg_1xU32(char *fn, char *fmt, u32 val)
++{
++ if (acm_traces) {
++ acm_trace_t *p = ACM_TRACE_NEXT(fn,acm_trace_msg32_n);
++ p->trace.msg32.val = val;
++ p->trace.msg32.msg = fmt;
++ }
++}
++#define TRACE_MSG1(fmt,val) acm_trace_msg_1xU32(__FUNCTION__,fmt,(u32)val)
++
++static __inline__ void acm_trace_msg_2xU16(char *fn, char *fmt, u16 val0, u16 val1)
++{
++ if (acm_traces) {
++ acm_trace_t *p = ACM_TRACE_NEXT(fn,acm_trace_msg16_n);
++ p->trace.msg16.val0 = val0;
++ p->trace.msg16.val1 = val1;
++ p->trace.msg16.msg = fmt;
++ }
++}
++#define TRACE_MSG2(fmt,val0,val1) acm_trace_msg_2xU16(__FUNCTION__,fmt,(u16)val0,(u16)val1)
++
++static __inline__ void acm_trace_msg_4xU8(char *fn, char *fmt, u8 val0, u8 val1, u8 val2, u8 val3)
++{
++ if (acm_traces) {
++ acm_trace_t *p = ACM_TRACE_NEXT(fn,acm_trace_msg8_n);
++ p->trace.msg8.val0 = val0;
++ p->trace.msg8.val1 = val1;
++ p->trace.msg8.val2 = val2;
++ p->trace.msg8.val3 = val3;
++ p->trace.msg8.msg = fmt;
++ }
++}
++#define TRACE_MSG4(fmt,val0,val1,val2,val3) acm_trace_msg_4xU8(__FUNCTION__,fmt,(u8)val0,(u8)val1,(u8)val2,(u8)val3)
++
++#else
++
++#define TRACE_SETUP(setup)
++#define TRACE_MSG(msg)
++#define TRACE_MSG1(fmt,val)
++#define TRACE_MSG2(fmt,val0,val1)
++#define TRACE_MSG4(fmt,val0,val1,val2,val3)
++
++#endif
++
++int acm_trace_init (char *str);
++void acm_trace_exit (char *str);
++
+diff -Nru a/drivers/usbd/au1x00_bi/Config.in b/drivers/usbd/au1x00_bi/Config.in
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/au1x00_bi/Config.in Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,27 @@
++
++# USB device configuration from the device viewpoint (e.g. Linux running inside a USB device, not as host)
++#
++# Copyright (c) 2002-2003 Belcarra
++#
++
++#
++# CONFIG_SOC_AU1X00 and/or CONFIG_MIPS_AU1X00 are the new and preferred tags (as of 2.4.20)
++#
++# CONFIG_MIPS_AU1000, CONFIG_MIPS_AU1100, CONFIG_MIPS_AU1500 are deprecated (prior to 2.4.20)
++#
++
++if [ "$CONFIG_SOC_AU1X00" = "y" -o "$CONFIG_MIPS_AU1X00" = "y" -o "$CONFIG_CPU_AU1X00" = "y" -o "$CONFIG_MIPS_AU1500" = "y" -o "$CONFIG_MIPS_AU1100" = "y" -o "$CONFIG_MIPS_AU1000" = "y" ]
++then
++ mainmenu_option next_comment
++
++ comment 'AMD AU1X000 Bus Interface'
++
++ dep_tristate ' AU1X00 (AMD/Alchemy) support' CONFIG_USBD_AU1X00_BUS $CONFIG_USBD
++ if [ "$CONFIG_USBD_AU1X00_BUS" = "m" -o "$CONFIG_USBD_AU1X00_BUS" = "y" ]; then
++ int ' AU1X00 System Clock' CONFIG_USBD_AU1X00_SCLOCK 400
++ fi
++ define_bool CONFIG_AU1000_USB_DEVICE y
++ define_bool CONFIG_AU1X00_USB_DEVICE y
++
++ endmenu
++fi
+diff -Nru a/drivers/usbd/au1x00_bi/Makefile b/drivers/usbd/au1x00_bi/Makefile
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/au1x00_bi/Makefile Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,88 @@
++#
++# Makefile for the kernel USBD (device not host) drivers.
++#
++# Copyright (c) 2002 Belcarra
++
++# Subdirs.
++# This is a bit complex, because some subdirs are for
++# proprietary code, and are simply not present in a
++# general distribution.
++
++# The all-CAPS *_DIRS get nuked in the new versions
++# of Rules.make, so use only the subdir-* methods.
++subdir-y :=
++subdir-m :=
++subdir-n :=
++subdir- :=
++
++# The target object and module list name.
++
++O_TARGET := au1x00_bi.o
++
++# Objects that export symbols.
++
++export-objs :=
++
++# Multipart objects.
++
++au1x00_bi-objs := au1x00.o usbd-bi.o trace.o
++
++# Optional parts of multipart objects.
++
++# Object file lists.
++
++#obj-y := usbd-bi.o
++obj-y :=
++obj-m :=
++obj-n :=
++obj- :=
++
++# Each configuration option enables a list of files.
++
++obj-$(CONFIG_USBD_AU1X00_BUS) += au1x00_bi.o
++
++# Object files in subdirectories
++
++
++# Extract lists of the multi-part drivers.
++# The 'int-*' lists are the intermediate files used to build the multi's.
++
++multi-y := $(filter $(list-multi), $(obj-y))
++multi-m := $(filter $(list-multi), $(obj-m))
++int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
++int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
++
++# Files that are both resident and modular: remove from modular.
++
++obj-m := $(filter-out $(obj-y), $(obj-m))
++int-m := $(filter-out $(int-y), $(int-m))
++
++# Translate to Rules.make lists.
++
++O_OBJS := $(filter-out $(export-objs), $(obj-y))
++OX_OBJS := $(filter $(export-objs), $(obj-y))
++M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
++MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
++MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
++MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
++
++# The global Rules.make.
++
++include $(TOPDIR)/Rules.make
++USBD=$(TOPDIR)/drivers/usbd
++BI_DIR=$(USBD)/au1x00_bi
++EXTRA_CFLAGS += -Wno-missing-prototypes -Wno-unused -Wno-format -I$(USBD) -I$(BI_DIR)
++EXTRA_CFLAGS_nostdinc += -Wno-missing-prototypes -Wno-unused -Wno-format -I$(USBD) -I$(BI_DIR)
++
++vpath %.c $(USBD)
++
++# Link rules for multi-part drivers.
++
++au1x00_bi.o: $(au1x00_bi-objs)
++ $(LD) -r -o $@ $(au1x00_bi-objs)
++
++# dependencies:
++
++# local
++
++
+diff -Nru a/drivers/usbd/au1x00_bi/au1x00.c b/drivers/usbd/au1x00_bi/au1x00.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/au1x00_bi/au1x00.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,1268 @@
++/*
++ * usbd/au1x00_bi/au1x00.c -- USB Device Controller driver.
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2002 Lineo
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ *
++ * This program is free software; you can redistribute it and/or modify it under the terms of
++ * the GNU General Public License as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ * See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along with this program; if
++ * not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Notes
++ *
++ * 1. EP0 - packetsize of 8 does not work, this means that PIO cannot be used for IN (transmit).
++ * DMA must be used. Only 16, 32 and 64 are usable.
++ *
++ * Update: even though we couldn't program the endpoint size to 8, we just set it to 8 in the
++ * device descriptor and things work ok. This works and we don't need or use DMA for either
++ * direction for EP0.
++ *
++ * 2. For each BULK transfer the first N packets must be sent with the full packetsize and the
++ * last must be sent as a short packet. The packetsize must be set before enabling the DMA.
++ *
++ * 3. For IN endpoints an interrupt will be generated for EVERY IN packet including ones that
++ * will be NAK'd. To reduce overhead the interrupt should only be enabled when there is data
++ * being sent and we need to know when it has been sent.
++ *
++ * Update: for new silicon this is not true, the UDC will interrupt less often and will NAK
++ * until the interrupt is cleared.
++ *
++ * 4. The AU1x00 auto-acks many setup commands and is very sensitive to latency of the irq
++ * handler processing the interrupt and clearing the ep0 fifo. Like the pxa we need to spool the
++ * requests and process later when we receive a request for data. There is a special test in
++ * the bulk data receive handler to check if there are spooled requests to process.
++ *
++ * Update: this has been mostly mitigated by reducing all upper layer processing in recv_setup,
++ * event_irq etc so that they complete in less than a milli-second. This simplifies things and
++ * we can now pass UUT tests.
++ *
++ * 5. There is a time sensitive problem in au_in_epn(). Without a udelay(8) sending large
++ * packets will eventually stall interrupts.
++ *
++ * Update: this is not required for new silicon.
++ *
++ * 6. When receiving data (Bulk OUT) the UDC will not start NAKing until and unless the receive
++ * FIFO is full. This means that there is no reliable way to determine the end of one packet and
++ * the beginning of the next if there is any undue latency in handling the interrupt for the
++ * first packet.
++ *
++ * The Belcarra Windows and Macintosh network class drivers have an option that can be used
++ * to pad all outgoing packets to a multiple of 8 bytes. This helps eliminate this problem.
++ *
++ * Update: this is not a problem with new silicon, it NAK's until the interrupt is cleared.
++ *
++ * 8. The original AU1x00 UDC generated an interrupt for EVERY IN packet. If we do not have
++ * any data we need to disable the interrupt for the endpoint to eliminate the overhead
++ * for processing them. The interrupt must be re-enabled when DMA is finished and we
++ * actually want to know that the endpoint has finished.
++ *
++ * Leaving the interrupt enabled also interfers with the DMA process. It is not apparant
++ * why.
++ *
++ * Update: This has been fixed on the new silicon but it doesn't hurt to continue to do this.
++ *
++ * 9. The DMA functions replace the equivalent routines in au1100_dma.h except that they pass
++ * the actual struct dma_chan pointer instead of the channel number. The bounds checking and
++ * table lookup to derive this information amounts to a substantial increase in code size and
++ * latency which can simply be avoided by using the structure address directly and/or doing the
++ * equivalent i/o directly.
++ */
++
++
++#include <udc.h>
++#include "au1x00.h"
++
++#include <asm/io.h>
++#include <asm/au1000.h>
++#include <asm/au1000_dma.h>
++#include <asm/mipsregs.h>
++
++
++#ifdef CONFIG_MIPS_FREEHAND
++#include <linux/i2c.h>
++#include <linux/sensors.h> /* for reading serial number */
++#endif
++
++MODULE_AUTHOR ("sl@belcarra.com, tbr@belcarra.com");
++MODULE_DESCRIPTION ("USB Device AU1x00 Bus Interface");
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
++MODULE_LICENSE("GPL");
++#endif
++USBD_MODULE_INFO ("au1x00_bi 2.0-beta");
++const char *usbd_bi_module_info(void)
++{ return __usbd_module_info; }
++
++#undef CHECK_LATENCY
++#undef RECORD_LATENCY
++#undef MAX_INTR_LOOP_STATS 10
++#if defined(MAX_INTR_LOOP_STATS)
++static u32 interrupt_loop_stats[MAX_INTR_LOOP_STATS+1];
++#endif
++#ifdef RECORD_LATENCY
++#define CP0_COUNTS 50
++u32 cp0_counts[CP0_COUNTS];
++u32 cp0_record;
++#endif
++u32 cp0_count;
++unsigned int udc_interrupts;
++unsigned int udc_saw_bus_activity;
++int au_halt_dma_expired;
++u32 au1x00_new_silicon;
++u32 au1x00_inten;
++static int udc_connected_status;
++
++__u8 au1x00_config_bulk[25] = {
++ 0x04, (USB_ENDPOINT_CONTROL << 4) | (EP0_PACKETSIZE & 0x380) >> 7, // 1
++ (EP0_PACKETSIZE & 0x7F) << 1, 0x00, 0x00,
++ 0x24, (USB_ENDPOINT_BULK << 4) | USB_DIR_IN | (MAX_EPN_PACKET_SIZE & 0x380) >> 7, // 6
++ (MAX_EPN_PACKET_SIZE & 0x7F) << 1, 0x00, 0x02,
++ 0x34, (USB_ENDPOINT_BULK << 4) | USB_DIR_IN | (MAX_EPN_PACKET_SIZE & 0x380) >> 7, // 11
++ (MAX_EPN_PACKET_SIZE & 0x7F) << 1, 0x00, 0x03,
++ 0x44, (USB_ENDPOINT_BULK << 4) | USB_DIR_OUT | (MAX_EPN_PACKET_SIZE & 0x380) >> 7, // 16
++ (MAX_EPN_PACKET_SIZE & 0x7F) << 1, 0x00, 0x04,
++ 0x54, (USB_ENDPOINT_BULK << 4) | USB_DIR_OUT | (MAX_EPN_PACKET_SIZE & 0x380) >> 7, // 21
++ (MAX_EPN_PACKET_SIZE & 0x7F) << 1, 0x00, 0x05,
++};
++
++/* ********************************************************************************************* */
++/* Note - The endpoints names are confusing. To simplify mapping of the interrupt request lines
++ * we use a numbering of the physical endpoints of 0-5, which also matches the fifo numbering
++ * (see the config block).
++ *
++ * Physical FIFO Name Direction Logical
++ * 0 0 EP0 OUT 0
++ * 1 1 EP0 IN 0
++ * 2 2 EP1 IN 81
++ * 3 3 EP2 IN 82
++ * 4 4 EP3 OUT 3
++ * 5 5 EP4 OUT 4
++ *
++ * The ep_regs array maps a physical endpoint number to the registers required to access the udc
++ * for that endpoint. Note that ep0 is always accessed via 0. The epl2p array maps the logical
++ * addresses back to the physical number. The epp2l array maps the physical number to the
++ * logical endpoint address
++ */
++struct ep_regs ep_regs[6] = {
++ { rd: USBD_EP0RD, rds: USBD_EP0RDSTAT, /*rx_id: DMA_ID_USBDEV_EP0_RX,*/ cs: USBD_EP0CS, rx_str: "EP0 OUT RD",
++ wr: USBD_EP0WR, wrs: USBD_EP0WRSTAT, tx_id: DMA_ID_USBDEV_EP0_TX, tx_str: "EP0 IN WR",},
++ { rds: 0, wrs: 0, indma: -1, outdma: -1, },
++ { wr: NUSBD_EP1WR, wrs: NUSBD_EP1WRSTAT, tx_id: NDMA_ID_USBDEV_EP1_TX, cs: NUSBD_EP1CS, tx_str: "EP1 IN WR",},
++ { wr: NUSBD_EP2WR, wrs: NUSBD_EP2WRSTAT, tx_id: NDMA_ID_USBDEV_EP2_TX, cs: NUSBD_EP2CS, tx_str: "EP2 IN WR",},
++
++ { rd: NUSBD_EP3RD, rds: NUSBD_EP3RDSTAT, rx_id: NDMA_ID_USBDEV_EP3_RX, cs: NUSBD_EP3CS, rx_str: "EP3 OUT RD",},
++ { rd: NUSBD_EP4RD, rds: NUSBD_EP4RDSTAT, rx_id: NDMA_ID_USBDEV_EP4_RX, cs: NUSBD_EP4CS, rx_str: "EP4 OUT RD",},
++};
++__u8 epl2p[6] = { 0x00, 0x02, 0x03, 0x04, 0x05, 0x00, }; // map logical to physical
++__u8 epp2l[6] = { 0x00, 0x00, 0x81, 0x82, 0x03, 0x04, }; // map physical to logical
++
++static __inline__ void au_fifo_read(struct ep_regs *ep, unsigned char * cp, int bytes)
++{
++ u32 rd = ep->rd;
++ for (; bytes--; *cp++ = au_readl(rd));
++}
++
++static __inline__ void au_fifo_write(int ep, unsigned char * cp, int bytes)
++{
++ u32 wr = ep_regs[ep].wr;
++ for (; bytes--; au_writel(*cp++, wr));
++ ep_regs[ep].last = bytes;
++}
++
++void __inline__ au_inten(u32 inten)
++{
++ au1x00_inten = inten;
++ au_writel(au1x00_inten, USBD_INTEN);
++}
++
++void __inline__ udc_epn_interrupt_enable(int epn)
++{
++ au_inten(au1x00_inten | (1 << epn));
++}
++
++void __inline__ udc_epn_interrupt_disable(int epn)
++{
++ au_inten(au1x00_inten & ~(1 << epn));
++ au_writel((1 << epn) , USBD_INTSTAT);
++}
++
++static void __inline__ send_zlp(unsigned char epn)
++{
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep_regs[epn].wrs);
++ au_writel(0 << 1, ep_regs[epn].cs);
++ au_writel(0, ep_regs[epn].wr);
++}
++/* ********************************************************************************************* */
++#define AU_DMA_HALT_POLL 0x1000
++static void __inline__ au_halt_dma(struct dma_chan *chan)
++{
++ int i;
++ au_writel(DMA_GO, chan->io + DMA_MODE_CLEAR);
++ for (i = 0; i < AU_DMA_HALT_POLL; i++)
++ RETURN_IF (au_readl(chan->io + DMA_MODE_READ) & DMA_HALT);
++ au_halt_dma_expired++;
++}
++
++static int __inline__ au_get_dma_residue(struct dma_chan *chan)
++{
++ int curBufCntReg = (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) ? DMA_BUFFER1_COUNT : DMA_BUFFER0_COUNT;
++ return au_readl(chan->io + curBufCntReg) & DMA_COUNT_MASK;
++}
++
++static void __inline__ au_start_dma(struct dma_chan *chan, __u8 *bp, int len)
++{
++ if (au_readl(chan->io + DMA_MODE_READ) & DMA_AB) {
++ au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
++ au_writel(len & DMA_COUNT_MASK, chan->io + DMA_BUFFER1_COUNT);
++ au_writel(0, chan->io + DMA_BUFFER0_COUNT);
++ au_writel(virt_to_phys(bp), chan->io + DMA_BUFFER1_START);
++ au_writel(DMA_BE1, chan->io + DMA_MODE_SET);
++ }
++ else {
++ au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
++ au_writel(len & DMA_COUNT_MASK, chan->io + DMA_BUFFER0_COUNT);
++ au_writel(0, chan->io + DMA_BUFFER1_COUNT);
++ au_writel(virt_to_phys(bp), chan->io + DMA_BUFFER0_START);
++ au_writel(DMA_BE0, chan->io + DMA_MODE_SET);
++ }
++ au_writel(DMA_GO, chan->io + DMA_MODE_SET);
++}
++
++static void __inline__ au_start_dma_in(int indma, __u8 *bp, int len)
++{
++ au_start_dma(get_dma_chan(indma), bp, len);
++}
++
++static void __inline__ au_start_dma_out(int outdma, __u8 *bp, int wMaxPacketSize)
++{
++ dma_cache_inv((unsigned long) bp, wMaxPacketSize);
++ au_start_dma(get_dma_chan(outdma), bp, wMaxPacketSize);
++}
++
++static struct urb *au_rcv_complete_irq(struct usb_endpoint_instance *endpoint, int len, int urb_bad)
++{
++ return bi_rcv_complete_irq(endpoint, len, urb_bad);
++}
++
++/* ********************************************************************************************* */
++/* au_start_in_ep0 - start transmit
++ */
++static void au_start_in_ep0 (struct usb_endpoint_instance *endpoint, struct ep_regs *ep)
++{
++ struct urb *urb = endpoint->tx_urb;
++ int last = ep->last = endpoint->last = MIN (urb->actual_length - endpoint->sent, endpoint->wMaxPacketSize);
++ TRACE_MSG16("START IN EP0 SENT: %d SENDING: %d", endpoint->sent, last);
++ RETURN_IF ((urb->actual_length - endpoint->sent) <= 0);
++ au_writel(last << 1, ep->cs); // XXX
++ au_fifo_write(0, urb->buffer + endpoint->sent, last);
++ endpoint->last = last;
++}
++
++/* au_in_ep0 - called to service an endpoint zero IN interrupt, data sent
++ */
++static void au_in_ep0(struct usb_endpoint_instance *endpoint, struct ep_regs *ep)
++{
++ u32 cs;
++ struct urb *tx_urb;
++ int last;
++ TRACE_MSG32("EP0 IN: tx_urb: %p", (int)endpoint->tx_urb);
++ if ((cs = au_readl(ep->cs)) & USBDEV_CS_STALL) { // clear stall if present
++ TRACE_MSG32("CLEAR STALL %d", 0);
++ cs &= ~USBDEV_CS_STALL;
++ au_writel(cs, ep->cs);
++ return;
++ }
++ if (!(tx_urb = bi_tx_complete_irq(endpoint, 0))) { // wait for setup if no more data
++ endpoint->state = WAIT_FOR_SETUP;
++ return;
++ }
++ TRACE_MSG8("EP0 IN actual: %d last: %d sent: %d flags: %x", endpoint->tx_urb->actual_length,
++ endpoint->last, endpoint->sent, endpoint->tx_urb->flags);
++ if (bi_tx_sendzlp(endpoint)) { // check if tx_urb we have is finished
++ TRACE_MSG("EP0 IN BULK - sending ZLP");
++ tx_urb->flags &= ~USBD_URB_SENDZLP;
++ send_zlp(0);
++ bi_tx_complete_irq(endpoint, 0);
++ return;
++ }
++ if (tx_urb->actual_length > endpoint->sent) {
++ if ((tx_urb->actual_length - endpoint->sent) < endpoint->wMaxPacketSize)
++ TRACE_MSG32("EP0 IN starting short packet %d", tx_urb->actual_length - endpoint->sent);
++ else
++ TRACE_MSG32("EP0 IN LEFT TO SEND %d", tx_urb->actual_length - endpoint->sent);
++ au_start_in_ep0(endpoint, ep);
++ }
++}
++
++/* au_out_ep0 - called to service an endpoint zero OUT interrupt, data received
++ */
++static void au_out_ep0(struct usb_endpoint_instance *endpoint, struct ep_regs *ep)
++{
++ struct usb_device_request request;
++ int i;
++ u32 cs;
++ u32 bytes;
++ TRACE_MSG("EP0 OUT");
++ cs = au_readl(ep->cs); // check if host aborted transfer and flush the write fifo
++ bytes = au_readl(ep->rds) & USBDEV_FSTAT_FCNT_MASK;
++ if (endpoint->state == DATA_STATE_RECV) {
++ struct urb *rcv_urb = bi_rcv_next_irq(endpoint);
++ TRACE_MSG32("EP0 OUT: RECV: rcv_urb: %x", (int) rcv_urb);
++ if (rcv_urb) {
++ au_fifo_read(ep, rcv_urb->buffer + rcv_urb->actual_length, bytes);
++ if (au_rcv_complete_irq(endpoint, bytes, 0))
++ return;
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->rds);
++ endpoint->state = WAIT_FOR_SETUP;
++ send_zlp(0);
++ return;
++ }
++ endpoint->state = WAIT_FOR_SETUP;
++ }
++ bi_tx_cancelled_irq(endpoint);
++ bi_rcv_cancelled_irq(endpoint);
++ au_fifo_read(ep, (u8 *)&request, bytes);
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->wrs);
++ if (bytes != 8) {
++ TRACE_MSG32("ERROR SETUP SET not eight bytes: %d", bytes);
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->wrs);
++ return;
++ }
++ TRACE_MSG8("SETUP bmRequestType: %02x bRequest %02x state: %d status: %d", request.bmRequestType,
++ request.bRequest, usbd_bus->device_state, usbd_bus->status);
++ switch (request.bRequest) { // we need to simply ignore any of these
++ case USB_REQ_SET_ADDRESS: // Fake a bus reset IFF not state default and then process normally
++ BREAK_IF (usbd_bus->device_state == STATE_DEFAULT);
++ udc_saw_bus_activity = 0;
++ usbd_bus_event_irq (usbd_bus, DEVICE_RESET, 0);
++ usbd_bus_event_irq (usbd_bus, DEVICE_ADDRESS_ASSIGNED, 0);
++ break;
++ case USB_REQ_GET_DESCRIPTOR: // Fake a bus reset IFF suspended and then process normally
++ BREAK_IF (STATE_SUSPENDED != usbd_bus->device_state);
++ udc_saw_bus_activity = 0;
++ usbd_bus_event_irq (usbd_bus, DEVICE_RESET, 0);
++ usbd_bus_event_irq (usbd_bus, DEVICE_ADDRESS_ASSIGNED, 0);
++ break;
++ }
++ if (bi_recv_setup_irq(&request)) {
++ TRACE_MSG32("ep0 STALL %d", cs);
++ au_writel(USBDEV_CS_STALL, USBD_EP0CS);
++ return;
++ }
++ if (((request.bmRequestType & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) && le16_to_cpu (request.wLength)) {
++ TRACE_MSG32("ep0 Class H2D request %04x", le16_to_cpu(request.wLength));
++ endpoint->state = DATA_STATE_RECV;
++ return;
++ }
++ if ((request.bmRequestType & USB_REQ_DIRECTION_MASK) == USB_REQ_HOST2DEVICE) {
++ TRACE_MSG32("ep0 Class H2D request %04x", le16_to_cpu(request.wLength));
++ if ((request.bmRequestType & ~USB_REQ_DIRECTION_MASK)) {
++ TRACE_MSG32("ep0 Class or Vendor, send ZLP %d", cs);
++ send_zlp(0);
++ return;
++ }
++ }
++ TRACE_MSG32("ep0 Class D2H request %04x", le16_to_cpu(request.wLength));
++}
++/* ********************************************************************************************* */
++/* au_start_in_bulk - start transmit
++ * The au1x00 will start to send when the first byte is loaded into the FIFO, either by
++ * DMA or PIO. The packetsize must be set first.
++ */
++static void au_start_in_bulk (unsigned int epn, struct usb_endpoint_instance *endpoint, struct ep_regs *ep)
++{
++ struct urb *urb = endpoint->tx_urb;
++ unsigned char *bp = urb->buffer + endpoint->sent;
++ int indma = ep->indma;
++ int last;
++ TRACE_MSG32("START IN BULK %d", epn);
++ RETURN_IF (!urb || (( (urb->actual_length - endpoint->sent) == 0) && !(urb->flags & USBD_URB_SENDZLP)));
++ last = ep->last = endpoint->last = MIN (urb->actual_length - endpoint->sent, endpoint->wMaxPacketSize);
++ TRACE_MSG16("START IN BULK sent: %d last:%d", endpoint->sent, last);
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->wrs); // XXX
++ if (!last) {
++ if (endpoint->tx_urb->flags & USBD_URB_SENDZLP) {
++ TRACE_MSG("START IN BULK - zending ZLP");
++ send_zlp(epn);
++ endpoint->tx_urb->flags &= ~USBD_URB_SENDZLP;
++ }
++ return;
++ }
++ else if (au1x00_new_silicon && (8 >= last)) {
++ au_writel(last << 1, ep->cs);
++ au_fifo_write(epn, bp, last);
++ return;
++ }
++ if (!au1x00_new_silicon)
++ udc_epn_interrupt_disable(epn);
++ dma_cache_wback_inv((unsigned long) bp, last);
++ au_writel(last << 1, ep->cs);
++ au_start_dma_in(indma, bp, last);
++}
++
++static void au_in_bulk(unsigned int epn, struct ep_regs *ep, struct usb_endpoint_instance *endpoint)
++{
++ struct urb *tx_urb;
++ int rc = 0;
++ u32 cs = au_readl(ep->cs);
++ u32 wrs = au_readl(ep->wrs);
++ TRACE_MSG16("BULK IN EPN - cs: %x wrs: %x", cs, wrs);
++ if (!au1x00_new_silicon)
++ if (epn && (ep->last > 8)) {
++ TRACE_MSG16("BULK IN EPN - DMA ACTIVE epn %d last %d", epn, ep->last);
++ udc_epn_interrupt_disable(epn);
++ return;
++ }
++ if (wrs) { // check for underflow or overflow
++ rc = 1;
++ if (wrs & USBDEV_FSTAT_UF) {
++ TRACE_MSG16("BULK IN EPN - UF epn %d wrs: %x", epn, wrs);
++ rc = 1; // set rc to indicate an error
++ }
++ if (wrs & USBDEV_FSTAT_OF)
++ TRACE_MSG16("BULK IN EPN - OF epn %d wrs: %x", epn, wrs);
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->wrs); // flush the fifo
++ }
++ if (cs & USBDEV_CS_NAK) {
++ RETURN_IF (ep->last && ((wrs&0x1f) == ep->last));
++ rc = 1;
++ }
++ if (cs & USBDEV_CS_STALL) { // clear stall if present
++ TRACE_MSG32("BULK IN EPN - CLEAR STALL %d", epn);
++ cs &= ~USBDEV_CS_STALL;
++ au_writel(cs, ep->cs);
++ return;
++ }
++ TRACE_MSG8("BULK IN EPN epn: %d rc: %d last: %d sent: %d", epn, rc, endpoint->last, endpoint->sent);
++ if ((tx_urb = bi_tx_complete_irq(endpoint, rc))) {
++ if ((tx_urb->actual_length > endpoint->sent) || (endpoint->tx_urb->flags & USBD_URB_SENDZLP)) {
++ au_start_in_bulk(epl2p[endpoint->bEndpointAddress&0xf], endpoint, ep);
++ /* XXX magic delay - without this large packets will eventually stall the transmit
++ * XXX and all traffic in both directions will stop.
++ */
++ if (!au1x00_new_silicon)
++ udelay(8);
++ TRACE_MSG32("BULK IN EPN - LEFT TO SEND %d", tx_urb->actual_length - endpoint->sent);
++ return;
++ }
++ }
++ udc_epn_interrupt_disable(epn); // disable interrupts
++}
++
++/* au_start_in_iso - start transmit
++ * The au1x00 will start to send when the first byte is loaded into the FIFO, either by DMA or
++ * PIO. The packetsize must be set first.
++ */
++static void au_start_in_iso (unsigned int epn, struct usb_endpoint_instance *endpoint, struct ep_regs *ep)
++{
++ struct urb *urb = endpoint->tx_urb;
++ unsigned char *bp = urb->buffer + endpoint->sent;
++ int last;
++ TRACE_MSG16("START IN ISO actual: %d sent: %d", urb->actual_length, endpoint->sent);
++ RETURN_IF ((urb->actual_length - endpoint->sent) == 0);
++ last = ep->last = endpoint->last = MIN (urb->actual_length - endpoint->sent, endpoint->wMaxPacketSize);
++ TRACE_MSG16("START IN ISO last: %d packetSize: %d", last, endpoint->wMaxPacketSize);
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->wrs); // XXX
++ au1x00_new_silicon ? udc_epn_interrupt_enable : udc_epn_interrupt_disable (epn);
++ dma_cache_wback_inv((unsigned long) bp, last);
++ au_writel(last << 1, ep->cs);
++ au_start_dma_in(ep->indma, bp, last);
++}
++
++static void au_in_iso(unsigned int epn, struct ep_regs *ep, struct usb_endpoint_instance *endpoint)
++{
++ struct urb *tx_urb = bi_tx_complete_irq(endpoint, 0);
++ u32 cs = au_readl(ep->cs);
++ u32 wrs = au_readl(ep->wrs);
++ TRACE_MSG16("ISO IN EPN - cs: %x wrs: %x", cs, wrs);
++ if (!au1x00_new_silicon)
++ if (epn && (ep->last > 8)) {
++ udc_epn_interrupt_disable(epn);
++ return;
++ }
++ TRACE_MSG8("ISO IN EPN epn: %d last: %d sent: %d", epn, endpoint->last, endpoint->sent, 0);
++ ep->last = 0;
++ if ((tx_urb = endpoint->tx_urb) && (tx_urb->actual_length > endpoint->sent)) {
++ au_start_in_iso(epl2p[endpoint->bEndpointAddress&0xf], endpoint, ep);
++ /* XXX magic delay - without this large packets will eventually stall the transmit
++ * XXX and all traffic in both directions will stop.
++ */
++ if (!au1x00_new_silicon)
++ udelay(8);
++ TRACE_MSG32("ISO IN EPN - LEFT TO SEND %d", tx_urb->actual_length - endpoint->sent);
++ return;
++ }
++ else
++ TRACE_MSG("ISO IN EPN - nothing to send");
++ udc_epn_interrupt_disable(epn); // disable interrupts
++}
++/* ********************************************************************************************* */
++
++static void au_start_out_bulk(unsigned int epn, struct usb_endpoint_instance *endpoint, struct ep_regs *ep)
++{
++ int outdma = ep->outdma;
++ TRACE_MSG16("START OUT BULK %d %d", epn, endpoint->wMaxPacketSize);
++ if (!endpoint->rcv_urb) {
++ TRACE_MSG("START OUT BULK DISABLE");
++ udc_epn_interrupt_disable(epn);
++ return;
++ }
++ if (endpoint->rcv_error) {
++ TRACE_MSG("START OUT BULK reseting rcv_error");
++ endpoint->rcv_error = 0;
++ }
++ au_start_dma_out(outdma, endpoint->rcv_urb->buffer + endpoint->rcv_urb->actual_length, endpoint->wMaxPacketSize);
++}
++
++static void au_out_bulk(unsigned int epn, struct ep_regs *ep, struct usb_endpoint_instance *endpoint)
++{
++ int bytes = 0;
++ int outdma = ep->outdma;
++ struct dma_chan *chan = get_dma_chan(outdma);
++ struct urb *urb;
++ struct urb *completed_urb = NULL;
++ u32 cs;
++ u32 rds;
++ u32 nrds;
++ au_halt_dma(chan);
++ cs = au_readl(ep->cs);
++ rds = au_readl(ep->rds);
++ TRACE_MSG16("BULK OUT CS: %04x RD: %04x", cs, rds);
++ bytes = endpoint->wMaxPacketSize - au_get_dma_residue(chan);
++ if (!(urb = bi_rcv_next_irq(endpoint))) {
++ TRACE_MSG("BULK OUT EPN - no rcv_urb");
++ udc_epn_interrupt_disable(epn);
++ return;
++ }
++ /* The original AU1X00 UDC design will continue to receive data as long as there is room
++ * in the FIFO. We cannot tell when we are at the end of a packet and/or have the start
++ * of a new one.
++ *
++ * There are only two scenarios that are guaranteed (almost) to be correct:
++ *
++ * 64 bytes of data from DMA, empty fifo, continue Bulk OUT < 60 bytes of data and
++ * < 4 bytes in fifo, end Bulk OUT.
++ *
++ * There may be a third scenario that is ok:
++ *
++ * 0 bytes dma, 0 bytes in fifo, NAK
++ *
++ * Everything else is an error. In all cases we assume that it is safer to drop data
++ * than to accept it in error. This allows CRC or size protected encapsulations to
++ * notice bulk transfers received with errors.
++ *
++ * In general none of the policies or strategies are able to cope with all errors
++ * without missing errors and dropping good data. The intent is to minimize the amount
++ * of potentially bad data getting to the function driver while minimizing the amount of
++ * good data that is dropped.
++ *
++ * The new silicon mitigates this problem for non control endpoints because it will NAK
++ * additional data until the interrupt service flag is reset.
++ *
++ * Start with generic error tests, OF, UF or NAK indicate an error we cannot recover
++ * from, start flushing until end of current bulk transfer (wait for a short packet)
++ *
++ */
++ if (rds & (USBDEV_FSTAT_OF | USBDEV_FSTAT_UF)) {
++ TRACE_MSG16("BULK OUT FLUSHING %d length: %d", bytes, urb->actual_length);
++ THROW(start_flushing);
++ }
++ rds = rds & USBDEV_FSTAT_FCNT_MASK;
++ nrds = au_readl(ep->rds);
++ if (64 == bytes) {
++ TRACE_MSG16("BULK OUT 64 BYTES %d length: %d", bytes, urb->actual_length);
++ /* full size packet received, check that we are not flushing and that the FIFO
++ * does not have any data. If there is data in the FIFO we may not be able to
++ * restart DMA in time, so start flushing
++ */
++ if (endpoint->rcv_error) {
++ TRACE_MSG8("FULL PACKET bytes: %d rds: %d nrds: %d cp0: %d CONTINUE FLUSHING",
++ bytes, rds, nrds, cp0_count);
++ THROW(start_flushing);
++ }
++ if ((nrds > 6) && (nrds < 8) ) {
++ TRACE_MSG8("FIFO not empty bytes: %d rds: %d nrds: %d cp0: %d START FLUSHING nrds > 6 < 8",
++ bytes, rds, nrds, cp0_count);
++ THROW(start_flushing);
++ }
++ if (!urb->actual_length)
++ TRACE_MSG8("PACKET ok bytes: %d rds: %d nrds: %d cp0: %d ACCEPTING 64 bytes",
++ bytes, rds, nrds, cp0_count);
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->rds);
++ au_rcv_complete_irq(endpoint, 64, 0);
++ if (cs & USBDEV_CS_NAK)
++ if (nrds && (nrds < 8) ) {
++ TRACE_MSG8("NAK bytes: %d rds: %d nrds: %d cp0: %d START FLUSHING CS_NAK",
++ bytes, rds, nrds, cp0_count);
++ THROW(start_flushing);
++ }
++ }
++ else if ((cs & USBDEV_CS_NAK) && (!nrds || (nrds == 8)) ) {
++ TRACE_MSG16("BULK OUT NAK BYTES %d length: %d", bytes, urb->actual_length);
++ /* a nak'd packet may be ok to ignore IFF the FIFO is empty(?) or completely full.
++ */
++ if (endpoint->rcv_error) {
++ TRACE_MSG8("NAK bytes: %d rds: %d nrds: %d cp0: %d CONTINUE FLUSHING",
++ bytes, rds, nrds, cp0_count);
++ THROW(start_flushing);
++ }
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->rds);
++ }
++ else {
++ TRACE_MSG16("BULK OUT < 64 BYTES %d length: %d", bytes, urb->actual_length);
++ /* short packet by DMA, additional data for this packet in FIFO, more than 3
++ * bytes is probably an error.
++ */
++ if ((cs & USBDEV_CS_NAK) && nrds && (nrds < 8) ) {
++ TRACE_MSG8("BULK OUT NAK bytes: %d rds: %d nrds: %d cp0: %d START FLUSHING",
++ bytes, rds, nrds, cp0_count);
++ THROW(start_flushing);
++ }
++ if (nrds > 4) {
++ TRACE_MSG8("BULK OUT SHORT PACKET by DMA full FIFO bytes: %d rds: %d nrds: %d cp0: %d START FLUSHING",
++ bytes, rds, nrds, cp0_count);
++ THROW(start_flushing);
++ }
++ TRACE_MSG8("BULK OUT SHORT bytes: %d rds: %d nrds: %d cp0: %d reading fifo", bytes, rds, nrds, cp0_count);
++ au_fifo_read(ep, urb->buffer + urb->actual_length + bytes, nrds);
++ bytes += nrds;
++ TRACE_MSG32("BULK OUT < 64 BYTES %d", bytes);
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->rds);
++ if (!endpoint->rcv_error) {
++ TRACE_MSG("BULK OUT COMPLETED URB");
++ au_rcv_complete_irq(endpoint, bytes, 0);
++ }
++ else {
++ TRACE_MSG("BULK OUT - FLUSHING URB - reseting rcv_error");
++ endpoint->rcv_error = 0;
++ }
++ }
++ CATCH(start_flushing) {
++ TRACE_MSG("BULK OUT - START FLUSHING URB");
++ endpoint->rcv_error = 1;
++ endpoint->rcv_urb->actual_length = 0;
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->rds);
++ bytes = 0;
++ }
++ TRACE_MSG("BULK OUT - RESTARTING");
++ au_start_out_bulk(epn, endpoint, ep);
++}
++
++static void au_start_out_iso(unsigned int epn, struct usb_endpoint_instance *endpoint, struct ep_regs *ep)
++{
++ int outdma = ep->outdma;
++ RETURN_IF(!endpoint->rcv_urb);
++ au_start_dma_out(outdma, endpoint->rcv_urb->buffer + endpoint->rcv_urb->actual_length, endpoint->wMaxPacketSize);
++}
++
++static void au_out_iso(unsigned int epn, struct ep_regs *ep, struct usb_endpoint_instance *endpoint)
++{
++ int bytes = 0;
++ int outdma = ep->outdma;
++ struct dma_chan *chan = get_dma_chan(outdma);
++ struct urb *urb;
++ u32 cs;
++ u32 rds;
++ au_halt_dma(chan);
++ cs = au_readl(ep->cs);
++ rds = au_readl(ep->rds);
++ if (!endpoint) {
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->rds);
++ return;
++ }
++ if (!(urb = endpoint->rcv_urb)) {
++ TRACE_MSG16("ISO OUT EPN - rcv_urb was NULL bytes: %d rds: %d", bytes, rds);
++ au_rcv_complete_irq(endpoint, bytes, 1);
++ TRACE_MSG("ISO OUT setting rcv_error");
++ }
++ bytes = endpoint->wMaxPacketSize - au_get_dma_residue(chan);
++ rds = rds & USBDEV_FSTAT_FCNT_MASK;
++ au_fifo_read(ep, urb->buffer + urb->actual_length + bytes, rds);
++ bytes += rds;
++ au_writel(USBDEV_FSTAT_FLUSH | USBDEV_FSTAT_UF | USBDEV_FSTAT_OF, ep->rds);
++ au_rcv_complete_irq(endpoint, bytes, 0);
++ au_start_out_iso(epn, endpoint, ep);
++}
++/* ********************************************************************************************* */
++/* udc_tx_dma_done - TX DMA interrupt handler
++ */
++static void udc_tx_dma_done(int irq, void *dev_id, struct pt_regs *regs)
++{
++ int epn = (int) dev_id;
++ struct usb_endpoint_instance *endpoint = usbd_bus->endpoint_array + epn;
++ struct ep_regs *ep = &ep_regs[epn];
++ int residue;
++ int indma = irq - 6;
++ struct dma_chan *chan = get_dma_chan(indma);
++ u32 mode = au_readl(chan->io + DMA_MODE_READ);
++ udc_interrupts++;
++ TRACE_MSG32("TX DMA done: mode: %x", mode);
++ if (mode & DMA_D0)
++ au_writel(DMA_D0, chan->io + DMA_MODE_CLEAR);
++ if (mode & DMA_D1)
++ au_writel(DMA_D1, chan->io + DMA_MODE_CLEAR);
++ RETURN_IF (!epn);
++ au_halt_dma(chan);
++ residue = au_get_dma_residue(chan);
++ TRACE_MSG16("TX DMA IRQ - epn %d residue %d", epn, residue);
++ if (!au1x00_new_silicon) {
++ /* XXX magic delay - without this large packets will eventually stall the transmit
++ * XXX and all traffic in both directions will stop.
++ */
++ udelay(8);
++ bi_tx_complete_irq (endpoint, residue?1:0);
++ udc_epn_interrupt_enable(epl2p[endpoint->bEndpointAddress&0xf]);
++ }
++ ep->last = 0;
++}
++
++/* udc_int_req - usb interrupt handler
++ */
++static void udc_int_req (int irq, void *dev_id, struct pt_regs *regs)
++{
++ u32 intstat;
++ struct ep_regs *ep;
++#if defined(MAX_INTR_LOOP_STATS)
++ u32 loopcount = 0;
++#endif
++#ifdef RECORD_LATENCY
++ cp0_count = (read_c0_count(CP0_COUNT) - cp0_record) >> 9;
++ if (cp0_count < CP0_COUNTS)
++ cp0_counts[cp0_count]++;
++#endif
++#ifdef CHECK_LATENCY
++ u32 cp0_count = read_c0_count(CP0_COUNT);
++#endif
++ udc_interrupts++;
++#if 0
++ if (udc_interrupts > 2000) {
++ TRACE_MSG("UDC_INT call udc_disable_interrupts");
++ au_inten(0);
++ return;
++ }
++#endif
++ while (( intstat = au_readl(USBD_INTSTAT) & au1x00_inten)) { // read and reset interrupt status register
++
++ int epn;
++#if 1
++ for (epn = 2; epn < 6; epn++) {
++ CONTINUE_IF (!(intstat & (1 << epn)));
++#else
++ // NOT TESTED
++ u32 local_intstat = intstat;
++ TRACE_MSG16("INTSTAT: %04x %04x", intstat, au_readl(USBD_INTEN));
++ while (local_intstat & 0x3f) {
++ int epn = 31 - au_clz(local_intstat);
++ local_intstat &= ~(1<<epn);
++#endif
++ if (udc_saw_bus_activity) {
++ udc_saw_bus_activity = 0;
++ usbd_bus_event_irq (usbd_bus, DEVICE_BUS_ACTIVITY, 0);
++ }
++ ep = &ep_regs[epn];
++ switch(ep->eptype) {
++ case USB_DIR_IN | USB_ENDPOINT_BULK:
++ case USB_DIR_IN | USB_ENDPOINT_INTERRUPT:
++ //TRACE_MSG16("BULK IN %d %02x", epn, ep->eptype);
++ au_in_bulk(epn, ep, usbd_bus->endpoint_array + epn);
++ break;
++ case USB_DIR_IN | USB_ENDPOINT_ISOCHRONOUS:
++ //TRACE_MSG16("ISO IN %d %02x", epn, ep->eptype);
++ au_in_iso(epn, ep, usbd_bus->endpoint_array + epn);
++ break;
++ case USB_DIR_OUT | USB_ENDPOINT_BULK:
++ case USB_DIR_OUT | USB_ENDPOINT_INTERRUPT:
++ //TRACE_MSG16("BULK OUT %d %02x", epn, ep->eptype);
++ au_out_bulk(epn, ep, usbd_bus->endpoint_array + epn);
++ break;
++ case USB_DIR_OUT | USB_ENDPOINT_ISOCHRONOUS:
++ //TRACE_MSG16("ISO OUT %d %04d", epn, au_readl(NUSBD_FRAMENUM));
++ au_out_iso(epn, ep, usbd_bus->endpoint_array + epn);
++ break;
++ }
++ }
++ au_writel(intstat, USBD_INTSTAT); // Only clear the interrupt(s) AFTER servicing OUT
++ /* even though we disable the bulk-in interrupt (endpoint 2) prior to enabling
++ * DMA we always see one additional interrupt that is a NAK on that endpoint.
++ */
++ CONTINUE_IF(!(intstat & au1x00_inten));
++ /* handle control endpoint and suspend interrupt
++ */
++ if (intstat & ( ((1 << 0) | (1 << 1) | (1 << 3) | (1 << 5) | USBDEV_INT_SOF))) {
++ if (intstat & (1 << 0))
++ au_out_ep0(usbd_bus->endpoint_array + 0, &ep_regs[0]);
++ if (intstat & (1 << 1))
++ au_in_ep0(usbd_bus->endpoint_array + 0, &ep_regs[0]);
++ if (intstat & USBDEV_INT_SOF)
++ if (USBD_SUSPENDED == usbd_bus->status) {
++ TRACE_MSG("SUS - ACTIVITY");
++ udc_saw_bus_activity++;
++ }
++ }
++#if defined(MAX_INTR_LOOP_STATS)
++ loopcount += 1; // Gather stats on how many times this loop is performed.
++#endif
++ }
++#if defined(MAX_INTR_LOOP_STATS)
++ interrupt_loop_stats[MIN(loopcount, MAX_INTR_LOOP_STATS)]++;
++#endif
++#if defined(CHECK_LATENCY)
++ TRACE_MSG32("USB IRQ - %d", read_c0_count(CP0_COUNT) - cp0_count);
++#endif
++#if defined(RECORD_LATENCY)
++ cp0_record = read_c0_count(CP0_COUNT);
++#endif
++}
++
++/* udc_int_sus -suspend interrupt handler
++ */
++static void udc_int_sus (int irq, void *dev_id, struct pt_regs *regs)
++{
++ udc_interrupts++;
++ TRACE_MSG16("SUS - INACTIVE device: %d status: %d", usbd_bus->device_state, usbd_bus->status);
++ switch(usbd_bus->status) {
++ case USBD_OPENING:
++ case USBD_OK:
++ usbd_bus_event_irq (usbd_bus, DEVICE_BUS_INACTIVE, 0);
++ break;
++ default:
++ break;
++ }
++}
++/* ********************************************************************************************* */
++/* udc_start_endpoint_in - start transmit
++ */
++void udc_start_endpoint_in(struct usb_endpoint_instance *endpoint)
++{
++ int epn = epl2p[endpoint->bEndpointAddress&0xf];
++ struct ep_regs *ep = &ep_regs[epn];
++ TRACE_MSG16("UDC START IN %02x %d", endpoint->bEndpointAddress, epn);
++ TRACE_MSG16("UDC START IN len: %d flags: %x", (unsigned int)endpoint->tx_urb->actual_length, endpoint->tx_urb->flags);
++ switch(endpoint->bmAttributes & USB_ENDPOINT_MASK) {
++ case USB_ENDPOINT_CONTROL:
++ TRACE_MSG32("UDC START IN EP0 %p", (u32)endpoint->rcv_urb);
++ au_in_ep0(endpoint, ep);
++ break;
++ case USB_ENDPOINT_BULK:
++ case USB_ENDPOINT_INTERRUPT:
++ TRACE_MSG32("UDC START IN BULK %p", (u32)endpoint->rcv_urb);
++ au_start_in_bulk(epn, endpoint, ep);
++ break;
++ case USB_ENDPOINT_ISOCHRONOUS:
++ TRACE_MSG32("UDC START IN ISO %p", (u32)endpoint->rcv_urb);
++ au_start_in_iso(epn, endpoint, ep);
++ break;
++ }
++ if (au1x00_new_silicon)
++ udc_epn_interrupt_enable(epn);
++}
++
++/* udc_start_endpoint_out - start receive
++ */
++void udc_start_endpoint_out(struct usb_endpoint_instance *endpoint)
++{
++ int epn = epl2p[endpoint->bEndpointAddress&0xf];
++ struct ep_regs *ep = &ep_regs[epn];
++ TRACE_MSG16("UDC START OUT %02x %d", endpoint->bEndpointAddress, epn);
++ TRACE_MSG32("UDC START OUT len: %d", endpoint->rcv_urb->buffer_length);
++ switch(endpoint->bmAttributes & USB_ENDPOINT_MASK) {
++ case USB_ENDPOINT_CONTROL:
++ TRACE_MSG32("UDC START OUT EP0 %p", (u32)endpoint->rcv_urb);
++ break;
++ case USB_ENDPOINT_BULK:
++ case USB_ENDPOINT_INTERRUPT:
++ TRACE_MSG32("UDC START OUT BULK %p", (u32)endpoint->rcv_urb);
++ au_start_out_bulk(epn, endpoint, ep);
++ udc_epn_interrupt_enable(epn);
++ break;
++ case USB_ENDPOINT_ISOCHRONOUS:
++ TRACE_MSG32("UDC START OUT ISO %p", (u32)endpoint->rcv_urb);
++ au_start_out_iso(epn, endpoint, ep);
++ break;
++ }
++}
++
++void udc_cancel_in_irq(struct urb *urb)
++{
++ int epn = epl2p[urb->endpoint->bEndpointAddress&0xf];
++ struct ep_regs *ep = &ep_regs[epn];
++ TRACE_MSG("CANCEL IN URB");
++ au_in_bulk(epn, ep, urb->endpoint);
++}
++
++void udc_cancel_out_irq(struct urb *urb)
++{
++ int epn = epl2p[urb->endpoint->bEndpointAddress&0xf];
++ struct ep_regs *ep = &ep_regs[epn];
++ TRACE_MSG("CANCEL OUT URB");
++ if (epn)
++ au_out_bulk(epn, ep, urb->endpoint);
++}
++
++/* udc_init - initialize
++ */
++int udc_init (void)
++{
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19)
++#undef read_c0_prid
++#define read_c0_prid() read_32bit_cp0_register(CP0_PRID)
++#endif
++ u32 cp0_prid = read_c0_prid();
++ switch (cp0_prid & CP0_PRID_SOC_MASK) {
++ case CP0_PRID_AU1000:
++ case CP0_PRID_AU1100:
++ au1x00_new_silicon = (cp0_prid & CP0_PRID_REV_MASK) >= 4;
++ printk(KERN_INFO"%s: AU1100 cp0_prid: new: %d\n", __FUNCTION__, au1x00_new_silicon);
++ break;
++ case CP0_PRID_AU1500:
++ au1x00_new_silicon = (cp0_prid & CP0_PRID_REV_MASK) >= 2;
++ printk(KERN_INFO"%s: AU1500 cp0_prid: new: %d\n", __FUNCTION__, au1x00_new_silicon);
++ break;
++ default:
++ printk(KERN_INFO"%s: UNKNOWN CPU cp0_prid: %08x UNKNOWN UDC\n", __FUNCTION__, cp0_prid);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++/* udc_serial_init - set a serial number if available
++ */
++int udc_serial_init (void)
++{
++#if defined(CONFIG_MIPS_FREEHAND)
++ int length;
++ long data[16]; /* yeah a hack, but we KNOW it's 16 */
++ struct i2c_client *client;
++ char chData[16];
++ int i;
++
++ if (!(client = getFreeHandEepromClient())) {
++ printk(KERN_INFO"eeprom not ready when udc_serial_init called\n");
++ return -EINVAL;
++ }
++ eeprom_contents(client, SENSORS_PROC_REAL_READ, EEPROM_SYSCTL1, &length, (long *)data);
++
++ /* serial number is first 9 longs. But each long is just an ASCII char
++ * convert this to a string and then extract a 4 byte value from it
++ */
++ for (i = 0; i < 9; chData[i] = (char)data[i], i++); /* trunc, is ok */
++ chData[9] = 0; /* terminate string */
++ printk(KERN_INFO"%s: %s\n", __FUNCTION__, chData);
++ usbd_bus->serial_number_str = lstrdup(chData);
++ return 0;
++#else
++ return -EINVAL;
++#endif
++}
++
++/* udc_setup_ep - setup endpoint
++ */
++void udc_setup_ep (unsigned int epn, struct usb_endpoint_instance *endpoint)
++{
++ RETURN_IF (epn);
++ endpoint->state = WAIT_FOR_SETUP;
++}
++
++/* udc_attached - is the USB cable connected
++ * Return non-zero if cable is connected.
++ *
++ * udc_connect - enable pullup resistor
++ * Turn on the USB connection by enabling the pullup resistor.
++ *
++ * udc_disconnect - disable pullup resistor
++ * Turn off the USB connection by disabling the pullup resistor.
++ */
++
++#if defined(CONFIG_MIPS_PICOENGINE_MVCI)
++int udc_attached (void)
++{
++ return 1;
++}
++
++int udc_connected(void)
++{
++ return udc_connected_status;
++}
++
++void udc_connect (void)
++{
++ extern void pico_mvci_set_usb_pullup(int);
++ pico_mvci_set_usb_pullup(1);
++ udc_connected_status = 1;
++}
++
++void udc_disconnect (void)
++{
++ extern void pico_mvci_set_usb_pullup(int);
++ pico_mvci_set_usb_pullup(0);
++ udc_connected_status = 0;
++}
++
++#elif defined(CONFIG_MIPS_FREEHAND_NATIVE)
++/* have to do this because version A boards don't have pullups
++ * XXX checkme
++*/
++int udc_attached (void)
++{
++ return 1;
++}
++
++int udc_connected(void)
++{
++ return udc_connected_status;
++}
++
++void udc_connect (void)
++{
++ au1000gpio_set(GPIO01);
++ udc_connected_status = 1;
++}
++
++void udc_disconnect (void)
++{
++ au1000gpio_clear(GPIO01);
++ udc_connected_status = 0;
++}
++
++#endif
++
++/* udc_framenum - get current framenum
++ */
++int udc_framenum (void)
++{
++ return au_readl(NUSBD_FRAMENUM);
++}
++
++/* udc_all_interrupts - enable interrupts
++ */
++void udc_all_interrupts (void)
++{
++ au_inten(0x0033|USBDEV_INT_SOF); // Only enable receive interrupts.
++}
++
++/* udc_suspended_interrupts - enable suspended interrupts
++ */
++void udc_suspended_interrupts (void)
++{
++ au_inten(0x0033|USBDEV_INT_SOF);
++}
++
++/* udc_disable_interrupts - disable interrupts.
++ */
++void udc_disable_interrupts (void)
++{
++ au_inten(0);
++}
++
++/* udc_disable - disable the UDC
++ */
++void udc_disable (void)
++{
++ au_writel(0x0000, USBD_ENABLE);
++}
++
++/* udc_release_udc_irq - release UDC irq
++ */
++void udc_release_udc_irq (void)
++{
++ free_irq (AU1000_USB_DEV_REQ_INT, NULL);
++ free_irq (AU1000_USB_DEV_SUS_INT, NULL);
++#if defined(MAX_INTR_LOOP_STATS)
++ {
++ u32 lc;
++ for (lc = 0; lc <= MAX_INTR_LOOP_STATS; lc++)
++ if (interrupt_loop_stats[lc])
++ printk(KERN_ERR "%s: interrupt loopcount[%02u] %9u\n", __FUNCTION__, lc,interrupt_loop_stats[lc]);
++ printk(KERN_INFO"%s: halt_dma_expired: %d\n", __FUNCTION__, au_halt_dma_expired);
++ }
++#endif
++#ifdef RECORD_LATENCY
++ {
++ int i;
++ for (i = 0; i < CP0_COUNTS; i++)
++ if (cp0_counts[i])
++ printk(KERN_INFO"%s: cp0_counts[%d] %d\n", __FUNCTION__, i, cp0_counts[i]);
++ }
++#endif
++}
++
++/* udc_request_udc_irq - request UDC interrupt
++ */
++int udc_request_udc_irq (void)
++{
++ RETURN_EINVAL_IF (request_irq (AU1000_USB_DEV_REQ_INT, udc_int_req, SA_INTERRUPT, UDC_NAME "UDC Req", NULL));
++ if (request_irq (AU1000_USB_DEV_SUS_INT, udc_int_sus, SA_INTERRUPT, UDC_NAME "UDC Sus", NULL) != 0) {
++ udc_release_udc_irq();
++ free_irq (AU1000_USB_DEV_REQ_INT, NULL);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++static int request_dma(int ep, int id, char *str, void dma_done(int , void *, struct pt_regs *))
++{
++ int dma;
++ if ((dma = request_au1000_dma(id, str, dma_done, SA_INTERRUPT | SA_SAMPLE_RANDOM, (void *)ep)) < 0) {
++ printk(KERN_INFO"request_io[%d] dma: %d id: %x %s FAILED\n", ep, dma, id, str);
++ return -1;
++ }
++ return dma;
++}
++
++/* udc_request_io - request IO region
++ */
++int udc_request_io (void)
++{
++ int i;
++ for (i = 0; i < 6; i++) {
++ ep_regs[i].indma = ep_regs[i].tx_id ? request_dma(i, ep_regs[i].tx_id, ep_regs[i].tx_str, udc_tx_dma_done) : -1;
++ ep_regs[i].outdma = ep_regs[i].rx_id ? request_dma(i, ep_regs[i].rx_id, ep_regs[i].rx_str, NULL) : -1;
++ }
++ return 0;
++}
++
++/* udc_release_io - release IO region
++ */
++void udc_release_io (void)
++{
++ int j;
++ for (j = 0; j < 6; j++) {
++ struct ep_regs *ep = &ep_regs[j];
++ if (ep->indma != -1) {
++ free_au1000_dma(ep->indma);
++ ep->indma = -1;
++ }
++ if (ep->outdma != -1) {
++ free_au1000_dma(ep->outdma);
++ ep->outdma = -1;
++ }
++ }
++}
++
++int udc_assign_endpoint( __u8 physicalEndpoint, int used[6], struct usb_endpoint_map *endpoint_map, __u8 bmAttributes,
++ __u16 wMaxPacketSize, __u16 transferSize)
++{
++ struct ep_regs *ep = &ep_regs[physicalEndpoint];
++ RETURN_EINVAL_IF(used[physicalEndpoint]);
++ endpoint_map->bEndpointAddress[0] = epp2l[physicalEndpoint];
++ endpoint_map->physicalEndpoint[0] = physicalEndpoint;
++ endpoint_map->wMaxPacketSize[0] = wMaxPacketSize;
++ endpoint_map->transferSize[0] = transferSize;
++ endpoint_map->bmAttributes[0] = bmAttributes;
++ used[physicalEndpoint]++;
++ ep->eptype = bmAttributes & 0x83;
++ return 0;
++}
++
++int udc_request_endpoints(struct usb_endpoint_map *endpoint_map_array, int endpointsRequested,
++ struct usb_endpoint_request *requestedEndpoints)
++{
++ struct usb_device_description *device_description;
++ int i;
++ int used[6];
++ memset(used, 0, sizeof(used));
++ for (i = 0; i < endpointsRequested; i++) {
++ struct usb_endpoint_map *endpoint_map = endpoint_map_array + i;
++ u8 bmAttributes = requestedEndpoints[i].bmAttributes;
++ u16 transferSize = requestedEndpoints[i].fs_requestedTransferSize;
++ endpoint_map->bmAttributes[0] = bmAttributes;
++ endpoint_map->wMaxPacketSize[0] = 0x40;
++ switch(bmAttributes) {
++ case USB_DIR_OUT | USB_ENDPOINT_BULK:
++ case USB_DIR_OUT | USB_ENDPOINT_INTERRUPT:
++ case USB_DIR_OUT | USB_ENDPOINT_INTERRUPT | USB_ENDPOINT_OPT:
++ CONTINUE_IF(!udc_assign_endpoint(4, used, endpoint_map, bmAttributes, 0x40, transferSize));
++ CONTINUE_IF(!udc_assign_endpoint(5, used, endpoint_map, bmAttributes, 0x40, transferSize));
++ break;
++ case USB_DIR_OUT | USB_ENDPOINT_ISOCHRONOUS:
++ CONTINUE_IF(!udc_assign_endpoint(4, used, endpoint_map, bmAttributes, transferSize, transferSize));
++ CONTINUE_IF(!udc_assign_endpoint(5, used, endpoint_map, bmAttributes, transferSize, transferSize));
++ break;
++ case USB_DIR_IN | USB_ENDPOINT_BULK:
++ case USB_DIR_IN | USB_ENDPOINT_INTERRUPT:
++ case USB_DIR_IN | USB_ENDPOINT_INTERRUPT | USB_ENDPOINT_OPT:
++ CONTINUE_IF(!udc_assign_endpoint(2, used, endpoint_map, bmAttributes, 0x40, transferSize));
++ CONTINUE_IF(!udc_assign_endpoint(3, used, endpoint_map, bmAttributes, 0x40, transferSize));
++ break;
++ case USB_DIR_IN | USB_ENDPOINT_ISOCHRONOUS:
++ CONTINUE_IF(!udc_assign_endpoint(2, used, endpoint_map, bmAttributes, transferSize, transferSize));
++ CONTINUE_IF(!udc_assign_endpoint(3, used, endpoint_map, bmAttributes, transferSize, transferSize));
++ break;
++ }
++ CONTINUE_IF(bmAttributes & USB_ENDPOINT_OPT);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++int udc_set_endpoints(int endpointsRequested, struct usb_endpoint_map *endpoint_map_array)
++{
++ int i, j;
++ __u8 config[25];
++ __u8 *cp;
++ memcpy(config, au1x00_config_bulk, sizeof(config));
++ for (i = 0; i < endpointsRequested; i++) {
++ struct usb_endpoint_map *endpoint_map = endpoint_map_array + i;
++ int epreq = endpoint_map->bmAttributes[0];
++ int eptype = epreq & USB_ENDPOINT_MASK;
++ int epdir = epreq & USB_ENDPOINT_DIR_MASK ? 0x8 : 0;
++ int epsize = endpoint_map->wMaxPacketSize[0];
++ int epaddr = epp2l[endpoint_map->physicalEndpoint[0]];
++ CONTINUE_IF(!endpoint_map->physicalEndpoint[0] || (endpoint_map->physicalEndpoint[0] > 5));
++ cp = config + ((endpoint_map->physicalEndpoint[0] - 1) * 5);
++ cp[0] = (epaddr & 0xf) << 4 | 0x4;
++ cp[1] = (eptype << 4) | epdir | (epsize & 0x380) >> 7;
++ cp[2] = (epsize & 0x7F) << 1;
++ }
++ au_inten(0); // disable interrupts
++ au_writel(0x0002, USBD_ENABLE); // reset controller
++ udelay(100);
++ au_writel(0x0003, USBD_ENABLE); // enable controller
++ udelay(100);
++ for (cp = config, i = 0; i < 25; i++, au_writel(*cp++, USBD_CONFIG)); // feed the config into the UDC
++ return 0;
++}
++/* ********************************************************************************************* */
++struct udc_ops udc_ops = {
++ max_endpoints: UDC_MAX_ENDPOINTS,
++ ep0_packetsize: EP0_PACKETSIZE,
++ name: UDC_NAME,
++ start_endpoint_in: udc_start_endpoint_in,
++ start_endpoint_out: udc_start_endpoint_out,
++ request_endpoints: udc_request_endpoints,
++ set_endpoints: udc_set_endpoints,
++ cancel_in_irq: udc_cancel_in_irq,
++ cancel_out_irq: udc_cancel_out_irq,
++ setup_ep: udc_setup_ep,
++#if defined(CONFIG_MIPS_PICOENGINE_MVCI) ||defined(CONFIG_MIPS_FREEHAND_NATIVE)
++ attached: udc_attached,
++ connected: udc_connected,
++ connect: udc_connect,
++ disconnect: udc_disconnect,
++#endif
++ framenum: udc_framenum,
++ all_interrupts: udc_all_interrupts,
++ suspended_interrupts: udc_suspended_interrupts,
++ disable_interrupts: udc_disable_interrupts,
++ disable: udc_disable,
++ init: udc_init,
++ request_udc_irq: udc_request_udc_irq,
++ release_udc_irq: udc_release_udc_irq,
++ release_io: udc_release_io,
++ serial_init: udc_serial_init,
++ request_io: udc_request_io,
++};
++
+diff -Nru a/drivers/usbd/au1x00_bi/au1x00.h b/drivers/usbd/au1x00_bi/au1x00.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/au1x00_bi/au1x00.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,112 @@
++/*
++ * usbd/au1x00_bi/au1100.h
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2000, 2001, 2002 Lineo
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++
++/*
++ * au1100
++ *
++ * The au1100 does not seem to work properly with an 8 byte
++ * packetsize. So 16, 32 or 64 are the only valid values.
++ *
++ * Unfortunately this means that a DMA channel is required for
++ * EP0 transmit.
++ */
++
++#define EP0_PACKETSIZE 0x8
++
++#define UDC_MAX_ENDPOINTS 6
++
++#define UDC_NAME "AU1100"
++
++#define NUSBD_EP0RD 0xB0200000
++#define NUSBD_EP0WR 0xB0200004
++#define NUSBD_EP1WR 0xB0200008
++#define NUSBD_EP2WR 0xB020000C
++#define NUSBD_EP3RD 0xB0200010
++#define NUSBD_EP4RD 0xB0200014
++
++#define NUSBD_EP0CS 0xB0200024
++#define NUSBD_EP1CS 0xB0200028
++#define NUSBD_EP2CS 0xB020002C
++#define NUSBD_EP3CS 0xB0200030
++#define NUSBD_EP4CS 0xB0200034
++
++#define NUSBD_EP0RDSTAT 0xB0200040
++#define NUSBD_EP0WRSTAT 0xB0200044
++#define NUSBD_EP1WRSTAT 0xB0200048
++#define NUSBD_EP2WRSTAT 0xB020004C
++#define NUSBD_EP3RDSTAT 0xB0200050
++#define NUSBD_EP4RDSTAT 0xB0200054
++
++#define NUSBD_FRAMENUM 0xB0200038
++
++enum {
++ NDMA_ID_UART0_TX = 0,
++ NDMA_ID_UART0_RX,
++ NDMA_ID_GP04,
++ NDMA_ID_GP05,
++ NDMA_ID_AC97C_TX,
++ NDMA_ID_AC97C_RX,
++ NDMA_ID_UART3_TX,
++ NDMA_ID_UART3_RX,
++ NDMA_ID_USBDEV_EP0_RX,
++ NDMA_ID_USBDEV_EP0_TX,
++ NDMA_ID_USBDEV_EP1_TX,
++ NDMA_ID_USBDEV_EP2_TX,
++ NDMA_ID_USBDEV_EP3_RX,
++ NDMA_ID_USBDEV_EP4_RX,
++ NDMA_ID_I2S_TX,
++ NDMA_ID_I2S_RX,
++ NDMA_NUM_DEV
++};
++
++typedef struct ep_regs {
++ int rd;
++ int wr;
++ int cs;
++ int rds;
++ int wrs;
++ int rx_id;
++ int tx_id;
++ char * rx_str;
++ char * tx_str;
++ int indma;
++ int outdma;
++ int last;
++ int eptype;
++} ep_regs_t;
++
++#define MAX_EPN_PACKET_SIZE 64
++#define CP0_PRID_SOC_MASK 0xff000000
++#define CP0_PRID_AU1000 0x00000000
++#define CP0_PRID_AU1500 0x01000000
++#define CP0_PRID_AU1100 0x02000000
++#define CP0_PRID_REV_MASK 0x000000ff
++
+diff -Nru a/drivers/usbd/ep0.c b/drivers/usbd/ep0.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/ep0.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,565 @@
++/*
++ * usbd/ep0.c
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003, 2004 Belcarra
++ * Copyright (c) 2000, 2001, 2002 Lineo
++ * Copyright (c) 2001 Hewlett Packard
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@lineo.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++/*
++ * This function driver implements support for all of the USB 2.0 Chapter
++ * nine requests.
++ *
++ * Any request that is not required by Chapter nine is passed to the other
++ * function drivers recv_setup routine.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++//EXPORT_NO_SYMBOLS;
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <asm/uaccess.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++
++#include <linux/smp_lock.h>
++#include <linux/ctype.h>
++#include <linux/timer.h>
++#include <linux/string.h>
++
++#include "usbd-chap9.h"
++#include "usbd-mem.h"
++#include "usbd.h"
++#include "usbd-func.h"
++#include "usbd-bus.h" // for usbd_recv_setup_irq() definition
++#include "usbd-admin.h"
++
++struct usb_function_instance * ep0_function;
++
++/* C.f. 9.4 Standard Requests and table 9.3
++ *
++ * Encode valid requests into a bitmap for each recipient type for
++ * both directions.
++ *
++ */
++
++#define STD(x) (1<<(x+1))
++
++/* h2d_standard_requests and d2h_standard_requests
++ *
++ * These tables list all of the valid Chapter Nine requests. Any request
++ * not listed in these tables will NOT be processed by the EP0 function and
++ * will instead be passed to the appropriate function driver.
++ */
++u32 h2d_standard_requests[4] = {
++ // 0 - Device
++ STD(USB_REQ_CLEAR_FEATURE) |
++ STD(USB_REQ_SET_FEATURE) |
++ STD(USB_REQ_SET_ADDRESS) |
++ STD(USB_REQ_SET_DESCRIPTOR) |
++ STD(USB_REQ_GET_CONFIGURATION) |
++ STD(USB_REQ_SET_CONFIGURATION) ,
++ // 1 - Interface
++ STD(USB_REQ_CLEAR_FEATURE) |
++ STD(USB_REQ_SET_FEATURE) |
++ STD(USB_REQ_SET_INTERFACE) ,
++ // 2 - Endpoint
++ STD(USB_REQ_CLEAR_FEATURE) |
++ STD(USB_REQ_SET_FEATURE) ,
++ // 3 - Other
++ 0,
++};
++
++u32 d2h_standard_requests[4] = {
++ // 0 - Device
++ STD(USB_REQ_GET_STATUS) |
++ STD(USB_REQ_GET_DESCRIPTOR) ,
++ // 1 - Interface
++ STD(USB_REQ_GET_STATUS) |
++ STD(USB_REQ_GET_INTERFACE) ,
++ // 2 - Endpoint
++ STD(USB_REQ_GET_STATUS) |
++ STD(USB_REQ_SYNCH_FRAME) ,
++ // 3 - Other
++ 0,
++};
++
++
++/* Endpoint ZEro Configuration *************************************************************** */
++
++/* ep0_event_irq - respond to USB event
++ *
++ * Process USB events.
++ */
++static void ep0_event_irq (struct usb_function_instance *function, usb_device_event_t event, int dummy )
++{
++ switch (event) {
++ case DEVICE_CREATE:
++ default:
++ break;
++ }
++}
++
++/* copy_config - copy data into urb buffer
++ */
++static int copy_config (u8 *cp, void *data, int actual_length, int max_buf)
++{
++ int available = max_buf - actual_length;
++ int length = MIN(*(u8 *)data, available);
++
++ RETURN_ZERO_IF (!length);
++ memcpy (cp, data, length);
++ return length;
++}
++
++/* copy_config - copy data into urb buffer
++ */
++static int copy_endpoint (struct usb_function_instance *function, u8 *cp,
++ struct usb_endpoint_descriptor *endpoint, int endpoint_index, int actual_length, int max_buf, int hs)
++{
++ int available = max_buf - actual_length;
++ int length = MIN(endpoint->bLength, available);
++ struct usb_endpoint_descriptor endpoint_copy;
++
++ RETURN_ZERO_IF (!length);
++ memcpy (&endpoint_copy, endpoint, endpoint->bLength);
++ usbd_endpoint_update(function, endpoint_index, &endpoint_copy, hs);
++ memcpy (cp, &endpoint_copy, length);
++ return length;
++}
++
++/* usbd_get_descriptor - copy descriptor into urb buffer
++ *
++ * Return non-zero for error.
++ */
++int usbd_get_descriptor (struct usb_bus_instance *bus, u8 *buffer, int max, int descriptor_type, int index)
++{
++ struct usb_function_driver *function_driver = bus->function_instance->function_driver;
++ int actual_length = 0;
++
++ switch (descriptor_type) {
++ case USB_DESCRIPTOR_TYPE_DEVICE:
++ {
++ struct usb_device_descriptor *device_descriptor = function_driver->device_descriptor;
++
++ // copy descriptor for this device
++ actual_length += copy_config (buffer + actual_length, device_descriptor, actual_length, max);
++
++ // correct the correct control endpoint 0 max packet size into the descriptor
++ device_descriptor = (struct usb_device_descriptor *) buffer;
++ device_descriptor->bMaxPacketSize0 = bus->driver->maxpacketsize;
++ }
++ break;
++
++#ifdef CONFIG_USBD_HIGH_SPEED
++ case USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER: // c.f. 9.6.2 Device Qualifier
++ {
++ struct usb_device_qualifier_descriptor *device_qualifier_descriptor =
++ function_driver->device_qualifier_descriptor;
++
++ // copy descriptor for this device
++ actual_length += copy_config (buffer + actual_length, device_qualifier_descriptor, actual_length, max);
++
++ }
++ break;
++
++ case USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION:
++ case USB_DESCRIPTOR_TYPE_CONFIGURATION:
++ {
++ int hs = bus->HighSpeedFlag ? descriptor_type == USB_DESCRIPTOR_TYPE_CONFIGURATION:
++ descriptor_type == USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION;
++#else
++ case USB_DESCRIPTOR_TYPE_CONFIGURATION:
++ {
++ int hs = 0;
++#endif
++ int interface;
++
++ struct usb_configuration_instance *configuration_instance =
++ &function_driver->configuration_instance_array[index];
++
++ struct usb_configuration_descriptor *configuration_descriptor =
++ configuration_instance->configuration_descriptor;
++
++ RETURN_EINVAL_IF (!configuration_descriptor);
++ RETURN_EINVAL_IF (index > function_driver->device_descriptor->bNumConfigurations);
++
++ actual_length += copy_config (buffer + actual_length, configuration_descriptor, actual_length, max);
++
++ // iterate across bNumInterfaces for specified configuration
++ for (interface = 0; interface < configuration_descriptor->bNumInterfaces; interface++) {
++
++ int alternate;
++ struct usb_interface_instance *interface_instance =
++ configuration_instance->interface_instance_array + interface;
++
++ // iterate across interface alternates
++ for (alternate = 0; alternate < interface_instance->alternates; alternate++) {
++
++ int class;
++ int endpoint;
++
++ struct usb_alternate_instance *alternate_instance =
++ interface_instance->alternates_instance_array + alternate;
++
++ //struct usb_interface_descriptor *usb_interface_descriptor;
++
++ // copy descriptor for this interface
++ actual_length += copy_config (buffer + actual_length,
++ alternate_instance->interface_descriptor, actual_length, max);
++
++ // iterate across classes for this alternate interface
++ for (class = 0; class < alternate_instance->classes; class++)
++ actual_length += copy_config (buffer + actual_length,
++ *(alternate_instance->class_list + class), actual_length, max);
++
++ // iterate across endpoints for this alternate interface
++ //interface_descriptor = alternate_instance->interface_descriptor;
++
++ for (endpoint = 0; endpoint < alternate_instance->endpoints ; endpoint++) {
++
++ //printk(KERN_INFO"%s: endpoint: %d index: %d\n",
++ // __FUNCTION__, endpoint,
++ // alternate_instance->endpoint_indexes[endpoint]
++ // );
++ actual_length += copy_endpoint (bus->function_instance,
++ buffer + actual_length,
++ *(( alternate_instance->endpoint_list) + endpoint),
++ alternate_instance->endpoint_indexes[endpoint],
++ actual_length, max, hs);
++ }
++ }
++ }
++ }
++ break;
++
++ case USB_DESCRIPTOR_TYPE_STRING:
++ {
++ struct usb_string_descriptor *string_descriptor;
++ RETURN_EINVAL_IF (!(string_descriptor = usbd_get_string (index)));
++ actual_length += copy_config (buffer + actual_length, string_descriptor, actual_length, max);
++ }
++ break;
++
++ default:
++ return -EINVAL;
++ }
++ return actual_length;
++}
++
++/* ep0_recv_setup_irq - process a device request
++ *
++ * Process a received device request. If not a Chapter nine request pass it
++ * to the other loaded function driver recv_setup_irq() function.
++ *
++ * Return non-zero to indicate failure.
++ */
++static int ep0_recv_setup_irq (struct usb_device_request *request)
++{
++ struct usb_function_instance *function = ep0_function;
++ struct usb_bus_instance *bus = ep0_function->bus;
++
++#if 0
++ printk(KERN_INFO"%s: bus: %p bmRequestType:%02x bRequest:%02x wValue:%04x wIndex:%04x wLength:%04x %d\n", __FUNCTION__,
++ function->bus, request->bmRequestType, request->bRequest,
++ le16_to_cpu(request->wValue), le16_to_cpu(request->wIndex), le16_to_cpu(request->wLength),
++ request->bRequest);
++#endif
++
++ // handle USB Standard Request only (c.f. USB Spec table 9-2, D6..5 must be 0)
++
++ THROW_IF ((request->bmRequestType & USB_REQ_TYPE_MASK) != 0, non_standard);
++
++ THROW_IF(!( (request->bmRequestType & USB_DIR_IN ? d2h_standard_requests : h2d_standard_requests)
++ [request->bmRequestType & 0x3] & STD(request->bRequest)), non_standard );
++
++ CATCH(non_standard) {
++ return usbd_recv_setup_irq(bus->function_instance, request);
++ }
++
++ switch (bus->device_state) {
++ case STATE_CREATED:
++ case STATE_ATTACHED:
++ case STATE_POWERED:
++ return -EINVAL;
++
++ case STATE_INIT:
++ case STATE_DEFAULT:
++ switch (request->bRequest) {
++ case USB_REQ_GET_STATUS:
++ case USB_REQ_GET_INTERFACE:
++ case USB_REQ_SYNCH_FRAME:
++ case USB_REQ_CLEAR_FEATURE:
++ case USB_REQ_SET_FEATURE:
++ case USB_REQ_SET_DESCRIPTOR:
++ case USB_REQ_SET_INTERFACE:
++ printk(KERN_INFO"%s: bad device_state\n", __FUNCTION__);
++ return -EINVAL;
++
++ case USB_REQ_SET_CONFIGURATION:
++ case USB_REQ_SET_ADDRESS:
++ case USB_REQ_GET_DESCRIPTOR:
++ case USB_REQ_GET_CONFIGURATION:
++ break;
++ }
++ case STATE_ADDRESSED:
++ case STATE_CONFIGURED:
++ case STATE_SUSPENDED:
++ break;
++ case STATE_UNKNOWN:
++ printk(KERN_INFO"%s: suspended or unknown\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ // handle all requests that return data (direction bit set on bm RequestType)
++ if ((request->bmRequestType & USB_REQ_DIRECTION_MASK)) {
++
++ struct urb *urb;
++ int rc = 0;
++ switch (request->bRequest) {
++ case USB_REQ_SYNCH_FRAME:
++ case USB_REQ_CLEAR_FEATURE:
++ case USB_REQ_SET_FEATURE:
++ case USB_REQ_SET_ADDRESS:
++ case USB_REQ_SET_DESCRIPTOR:
++ case USB_REQ_SET_CONFIGURATION:
++ case USB_REQ_SET_INTERFACE:
++ printk(KERN_INFO"%s: bad direction\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ RETURN_EINVAL_IF(!le16_to_cpu(request->wLength));
++
++ // allocate urb, no callback, urb will be automatically de-allocated
++ RETURN_EINVAL_IF(!(urb = usbd_alloc_urb (function, 0, le16_to_cpu(request->wLength), NULL)));
++
++ switch (request->bRequest) {
++
++ case USB_REQ_GET_STATUS:
++ urb->actual_length = 2;
++ urb->buffer[0] = urb->buffer[1] = 0;
++ switch (request->bmRequestType & USB_REQ_RECIPIENT_MASK) {
++ case USB_REQ_RECIPIENT_DEVICE:
++ urb->buffer[0] = USB_STATUS_SELFPOWERED;
++ break;
++ case USB_REQ_RECIPIENT_INTERFACE:
++ break;
++ case USB_REQ_RECIPIENT_ENDPOINT:
++ urb->buffer[0] = usbd_endpoint_halted (function, le16_to_cpu(request->wIndex));
++ break;
++ case USB_REQ_RECIPIENT_OTHER:
++ urb->actual_length = 0;
++ default:
++ break;
++ }
++ rc = 0;
++
++ break;
++
++ case USB_REQ_GET_DESCRIPTOR:
++ rc = usbd_get_descriptor (bus, urb->buffer,
++ le16_to_cpu (request->wLength),
++ le16_to_cpu (request->wValue >> 8),
++ le16_to_cpu (request->wValue) & 0xff);
++ if (rc != -EINVAL) {
++ urb->actual_length = rc;
++ rc = 0;
++ }
++ break;
++
++ case USB_REQ_GET_CONFIGURATION:
++ urb->actual_length = 1;
++ urb->buffer[0] = bus->ConfigurationValue;
++ break;
++
++ case USB_REQ_GET_INTERFACE:
++ RETURN_EINVAL_IF(le16_to_cpu(request->wIndex) > bus->bNumInterfaces);
++ urb->actual_length = 1;
++ urb->buffer[0] = bus->alternates[le16_to_cpu(request->wIndex)];
++ break;
++ default:
++ rc = 1;
++ }
++
++ //printk(KERN_INFO"%s: actual: %d packetsize: %d wIndex: %d rc: %d\n", __FUNCTION__,
++ // urb->actual_length, urb->bus->driver->maxpacketsize, le16_to_cpu(request->wLength), rc);
++
++ if (!(urb->actual_length % urb->bus->driver->maxpacketsize) &&
++ (urb->actual_length < le16_to_cpu(request->wLength)))
++ {
++ //printk(KERN_INFO"%s: NEED ZLP\n", __FUNCTION__);
++ urb->flags |= USBD_URB_SENDZLP;
++ }
++ if (!rc)
++ RETURN_ZERO_IF(!usbd_send_urb(urb));
++ //printk(KERN_INFO"%s: failed urb: %p\n", __FUNCTION__, urb);
++ usbd_dealloc_urb(urb);
++ return -EINVAL;
++ }
++ // handle the requests that do not return data
++ else {
++
++ switch (request->bRequest) {
++
++ case USB_REQ_CLEAR_FEATURE:
++ case USB_REQ_SET_FEATURE:
++ switch (request->bmRequestType & USB_REQ_RECIPIENT_MASK) {
++ case USB_REQ_RECIPIENT_DEVICE:
++ // XXX DEVICE_REMOTE_WAKEUP or TEST_MODE would be added here
++ // XXX fall through for now as we do not support either
++ case USB_REQ_RECIPIENT_INTERFACE:
++ case USB_REQ_RECIPIENT_OTHER:
++ default:
++ return -EINVAL;
++
++ case USB_REQ_RECIPIENT_ENDPOINT:
++ if (le16_to_cpu(request->wValue) == USB_ENDPOINT_HALT)
++ return usbd_device_feature (function, le16_to_cpu (request->wIndex) & 0x7f,
++ request->bRequest == USB_REQ_SET_FEATURE);
++
++ else
++ return -EINVAL ;
++ }
++
++ case USB_REQ_SET_ADDRESS:
++ // check if this is a re-address, reset first if it is (this shouldn't be possible)
++ RETURN_EINVAL_IF (bus->device_state != STATE_DEFAULT);
++ usbd_bus_event (bus, DEVICE_ADDRESS_ASSIGNED, le16_to_cpu(request->wValue));
++ return 0;
++
++ case USB_REQ_SET_DESCRIPTOR:
++ // XXX should we support this?
++ // This would require allocating a rcv urb and using usbd_start_recv()
++ return -EINVAL;
++
++ case USB_REQ_SET_CONFIGURATION:
++ {
++ struct usb_function_driver *function_driver = bus->function_instance->function_driver;
++ int bNumConfigurations = function_driver->bNumConfigurations;
++ int bNumInterfaces;
++ u8 ConfigurationValue;
++
++
++ struct usb_configuration_instance *configuration_instance;
++ struct usb_configuration_descriptor *configuration_descriptor;
++
++ // get rid of previous interface and alternates
++ if (bus->bNumInterfaces && bus->alternates) {
++ bus->bNumInterfaces = 0;
++ lkfree(bus->alternates);
++ bus->alternates = NULL;
++ }
++
++ // c.f. 9.4.7 - the top half of wValue is reserved
++ //
++ // c.f. 9.4.7 - zero is the default or addressed state, in our case this
++ // is the same is configuration zero, but will be fixed in usbd.c when used.
++
++ ConfigurationValue = le16_to_cpu (request->wValue) & 0x7f;
++
++ RETURN_EINVAL_IF(ConfigurationValue > bNumConfigurations);
++
++ ConfigurationValue = ConfigurationValue ? 0 : ConfigurationValue -1;
++
++ configuration_instance = &function_driver->configuration_instance_array[ConfigurationValue];
++ configuration_descriptor = configuration_instance->configuration_descriptor;
++
++ RETURN_EINVAL_IF(!configuration_descriptor);
++
++ bNumInterfaces = configuration_instance->bNumInterfaces;
++
++ bus->ConfigurationValue = ConfigurationValue + 1;
++
++ // reset interface and alternate settings
++
++ RETURN_EINVAL_IF (!(bus->alternates = ckmalloc(bNumInterfaces, GFP_ATOMIC)));
++ bus->bNumInterfaces = bNumInterfaces;
++
++ //usbd_bus->device_event (bus, DEVICE_CONFIGURED, 0);
++ usbd_bus_event (bus, DEVICE_CONFIGURED, 0);
++ return 0;
++ }
++
++ case USB_REQ_SET_INTERFACE:
++ {
++ int interface = le16_to_cpu(request->wIndex);
++
++ RETURN_EINVAL_IF(interface > bus->bNumInterfaces);
++
++ bus->alternates[interface] = le16_to_cpu(request->wValue);
++ usbd_bus_event (bus, DEVICE_SET_INTERFACE, 0);
++ return 0;
++ }
++
++ case USB_REQ_GET_STATUS:
++ case USB_REQ_GET_DESCRIPTOR:
++ case USB_REQ_GET_CONFIGURATION:
++ case USB_REQ_GET_INTERFACE:
++ case USB_REQ_SYNCH_FRAME: // XXX should never see this (?)
++ printk(KERN_INFO"%s: unknown\n", __FUNCTION__);
++ return -EINVAL;
++ }
++ }
++ return -EINVAL;
++}
++
++
++/* ep0_function_enable - enable the endpoint zero function
++ *
++ * Return non-zero on failure.
++ */
++static int ep0_function_enable (struct usb_function_instance *function)
++{
++ ep0_function = function;
++ return 0;
++}
++
++/* ep0_function_disable - disable the endpoint zero function
++ */
++static void ep0_function_disable (struct usb_function_instance *function)
++{
++ ep0_function = NULL;
++}
++
++
++static struct usb_function_operations ep0_ops = {
++ event_irq: ep0_event_irq,
++ recv_setup_irq: ep0_recv_setup_irq,
++ function_enable: ep0_function_enable,
++ function_disable: ep0_function_disable,
++};
++
++struct usb_function_driver ep0_driver = {
++ name: "EP0",
++ fops: &ep0_ops,
++};
++
++EXPORT_SYMBOL(usbd_get_descriptor);
+diff -Nru a/drivers/usbd/mouse_fd/Config.in b/drivers/usbd/mouse_fd/Config.in
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/mouse_fd/Config.in Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,26 @@
++#
++# Mouse Function Driver
++#
++# Copyright (C) 2003 Belcarra
++#
++
++
++mainmenu_option next_comment
++
++comment "Random Mouse Function"
++dep_tristate ' Mouse Function' CONFIG_USBD_MOUSE $CONFIG_USBD
++
++if [ "$CONFIG_USBD_MOUSE" = "y" -o "$CONFIG_USBD_MOUSE" = "m" ]; then
++ hex 'VendorID (hex value)' CONFIG_USBD_MOUSE_VENDORID "12b9"
++ hex 'ProductID (hex value)' CONFIG_USBD_MOUSE_PRODUCTID "f003"
++ hex 'bcdDevice (binary-coded decimal)' CONFIG_USBD_MOUSE_BCDDEVICE "0100"
++
++ string 'iManufacturer (string)' CONFIG_USBD_MOUSE_MANUFACTURER "Belcarra"
++ #string 'iProduct (string)' CONFIG_USBD_MOUSE_PRODUCT_NAME "Belcarra Mouse"
++
++ string 'iConfiguration (string)' CONFIG_USBD_MOUSE_DESC "Acm Cfg"
++ string 'Comm Interface iInterface (string)' CONFIG_USBD_MOUSE_COMM_INTF "Comm Intf"
++ bool 'Mouse BH Test' CONFIG_USBD_MOUSE_BH
++
++fi
++endmenu
+diff -Nru a/drivers/usbd/mouse_fd/Makefile b/drivers/usbd/mouse_fd/Makefile
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/mouse_fd/Makefile Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,66 @@
++#
++# Function driver for a Mouse USB Device
++#
++# Copyright (c) 2003 Belcarra
++
++# Multipart objects.
++
++O_TARGET := mouse_fd.o
++list-multi := mouse_fd.o
++
++mouse_fd-objs := mouse.o
++
++# Objects that export symbols.
++export-objs := mouse.o
++
++# Object file lists.
++
++obj-y :=
++obj-m :=
++obj-n :=
++obj- :=
++
++# Each configuration option enables a list of files.
++
++obj-$(CONFIG_USBD_MOUSE) += mouse_fd.o
++
++# Extract lists of the multi-part drivers.
++# The 'int-*' lists are the intermediate files used to build the multi's.
++
++multi-y := $(filter $(list-multi), $(obj-y))
++multi-m := $(filter $(list-multi), $(obj-m))
++int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
++int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
++
++# Files that are both resident and modular: remove from modular.
++
++obj-m := $(filter-out $(obj-y), $(obj-m))
++int-m := $(filter-out $(int-y), $(int-m))
++
++# Translate to Rules.make lists.
++
++O_OBJS := $(filter-out $(export-objs), $(obj-y))
++OX_OBJS := $(filter $(export-objs), $(obj-y))
++M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
++MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
++MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
++MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
++
++# The global Rules.make.
++
++USBD=$(TOPDIR)/drivers/usbd
++MOUSED=$(USBD)/mouse_fd
++include $(TOPDIR)/Rules.make
++EXTRA_CFLAGS += -I$(MOUSED) -I$(USBD) -Wno-unused -Wno-format
++EXTRA_CFLAGS_nostdinc += -I$(MOUSED) -I$(USBD) -Wno-unused -Wno-format
++
++# Link rules for multi-part drivers.
++
++mouse_fd.o: $(mouse_fd-objs)
++ $(LD) -r -o $@ $(mouse_fd-objs)
++
++# dependencies:
++
++mouse.o: $(USBD)/usbd.h $(USBD)/usbd-bus.h $(USBD)/usbd-func.h
++
++
+diff -Nru a/drivers/usbd/mouse_fd/getmouse.c b/drivers/usbd/mouse_fd/getmouse.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/mouse_fd/getmouse.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,122 @@
++/*******************************************************************************
++ * File: FILE
++ * Module: MODULE
++ * Author: AUTHOR
++ * Date: DATE
++ *
++ * Notes:
++ *
++ * $Id$
++ *
++ * History:
++ * $Log$
++ *
++ ******************************************************************************/
++
++/*
++ *
++ *
++ * 3.2. Non-Canonical Input Processing
++ *
++ * In non-canonical input processing mode, input is not assembled into lines and
++ * input processing (erase, kill, delete, etc.) does not occur. Two parameters
++ * control the behavior of this mode: c_cc[VTIME] sets the character timer, and
++ * c_cc[VMIN] sets the minimum number of characters to receive before satisfying
++ * the read.
++ *
++ * If MIN > 0 and TIME = 0, MIN sets the number of characters to receive before
++ * the read is satisfied. As TIME is zero, the timer is not used.
++ *
++ * If MIN = 0 and TIME > 0, TIME serves as a timeout value. The read will be
++ * satisfied if a single character is read, or TIME is exceeded (t = TIME *0.1
++ * s). If TIME is exceeded, no character will be returned.
++ *
++ * If MIN > 0 and TIME > 0, TIME serves as an inter-character timer. The read
++ * will be satisfied if MIN characters are received, or the time between two
++ * characters exceeds TIME. The timer is restarted every time a character is
++ * received and only becomes active after the first character has been received.
++ *
++ * If MIN = 0 and TIME = 0, read will be satisfied immediately. The number of
++ * characters currently available, or the number of characters requested will be
++ * returned. According to Antonino (see contributions), you could issue a fcntl
++ * (fd, F_SETFL, FNDELAY); before reading to get the same result.
++ *
++ * By modifying newtio.c_cc[VTIME] and newtio.c_cc[VMIN] all modes described
++ * above can be tested.
++ *
++ */
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <termios.h>
++#include <stdio.h>
++
++#define BAUDRATE B1200
++#define MODEMDEVICE "/dev/ttyS0"
++#define _POSIX_SOURCE 1 /* POSIX compliant source */
++#define FALSE 0
++#define TRUE 1
++
++volatile int STOP=FALSE;
++
++main()
++{
++ int fd,c, res;
++ struct termios oldtio,newtio;
++ unsigned char buf[255];
++
++ int bytes;
++ unsigned char mouse[3];
++
++ fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
++ if (fd <0) {perror(MODEMDEVICE); exit(-1); }
++
++ tcgetattr(fd,&oldtio); /* save current port settings */
++
++ bzero(&newtio, sizeof(newtio));
++ newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
++ newtio.c_iflag = IGNPAR;
++ newtio.c_oflag = 0;
++
++ /* set input mode (non-canonical, no echo,...) */
++ newtio.c_lflag = 0;
++
++ newtio.c_cc[VTIME] = 0; /* inter-character timer unused */
++ newtio.c_cc[VMIN] = 1; /* blocking read until 5 chars received */
++
++ tcflush(fd, TCIFLUSH);
++ tcsetattr(fd,TCSANOW,&newtio);
++
++
++ bytes = 0;
++ while (STOP==FALSE) { /* loop for input */
++ unsigned char c;
++
++ res = read(fd,buf,1); /* returns after 5 chars have been input */
++ buf[res]=0; /* so we can printf... */
++ //fprintf(stderr, ":%02x:%d\n", buf[0], res);
++ //if (buf[0]=='z') STOP=TRUE;
++
++ c = buf[0];
++
++ if ( c & 0x40 ) {
++ bytes = 1;
++ mouse[0] = c;
++ }
++ else if (bytes == 1) {
++ bytes = 2;
++ mouse[1] = c;
++ }
++ else if (bytes == 2) {
++ bytes = 0;
++ mouse[2] = c;
++ fprintf(stderr, "%02x %02x %02x\n", mouse[0], mouse[1], mouse[2]);
++ //printf("%c%c%c", mouse[0], mouse[1], mouse[2]);
++ }
++ }
++ tcsetattr(fd,TCSANOW,&oldtio);
++}
++
++
++/* End of FILE */
+diff -Nru a/drivers/usbd/mouse_fd/mouse.c b/drivers/usbd/mouse_fd/mouse.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/mouse_fd/mouse.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,548 @@
++/*
++ * usbd/mouse_fd/mouse.c
++ *
++ * Copyright (c) 2003, 2004 Belcarra
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This is a test USB HID Function Driver designed to test and
++ * verify that INTERRUPT IN endpoints work properly.
++ *
++ * This emulates a simple USB mouse and generates a constant stream
++ * of small random mouse movements.
++ *
++ * To use simply load with something like:
++ *
++ * insmod mouse_fd.o vendor_id=0xffff product_id=0xffff
++ *
++ * And attach to a Windows box. Windows should recognize as a mouse and
++ * immediately start receiving a stream of data.
++ *
++ * To terminate simply unplug.
++ *
++ * The mouse driver has several other characteristics to allow testing of
++ * other features of the bus interface driver:
++ *
++ * - ep0 ZLP handling
++ *
++ * - ep0 delayed CONTROL READ
++ *
++ *
++ * Notes
++ *
++ * 1. The mouse driver is product name is hard coded to a string that will
++ * generate a string descriptor that is 32 bytes long. This will test
++ * most UDC's ep0 ZLP handling as it is a multiple of the most common
++ * UDC endpoint zero size. (An option can be added later to allow for
++ * 64 byte ep0 packetsize.)
++ *
++ * 2. The CONFIG_USBD_MOUSE_BH option can be enabled to delay the HID report
++ * to being generated by a bottom half handler. This will verify that
++ * the bus interface driver properly handles the case of a delayed
++ * CONTROL READ. I.e. when the usbd_recv_setup_irq() function returns
++ * zero for successful completion but there is no tx_urb containing the
++ * requested data. The bus interface driver must setup the conditions for
++ * ACK'ing the SETUP packet but then NAK the IN data for endpoint zero
++ * until the tx_urb is started later.
++ */
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++
++#include <usbd-export.h>
++#include <usbd-build.h>
++
++MODULE_AUTHOR ("sl@belcarra.com, tbr@belcarra.com");
++MODULE_LICENSE("PROPRIETARY");
++MODULE_DESCRIPTION ("Belcarra Random Walk MOUSE Function");
++
++#include <linux/init.h>
++#include <asm/uaccess.h>
++#include <linux/ctype.h>
++#include <linux/timer.h>
++#include <linux/interrupt.h>
++#include <asm/atomic.h>
++#include <linux/random.h>
++#include <linux/slab.h>
++
++#include "usbd-chap9.h"
++#include <usbd-mem.h>
++#include <usbd.h>
++#include <usbd-func.h>
++
++USBD_MODULE_INFO ("mouse_fd 2.0-beta");
++
++/* Module Parameters ************************************************************************* */
++
++static u32 vendor_id;
++static u32 product_id;
++
++MODULE_PARM (vendor_id, "i");
++MODULE_PARM (product_id, "i");
++
++MODULE_PARM_DESC (vendor_id, "Device Vendor ID");
++MODULE_PARM_DESC (product_id, "Device Product ID");
++
++/*
++ * ep0 testing.... ensure that this is exactly 16 bytes
++ */
++#undef CONFIG_USBD_MOUSE_PRODUCT_NAME
++#define CONFIG_USBD_MOUSE_PRODUCT_NAME "Belcarra Mouse"
++
++/*
++ * MOUSE Configuration
++ *
++ * Endpoint, Class, Interface, Configuration and Device descriptors/descriptions
++ */
++
++#define BULK_INT 0x00
++#define ENDPOINTS 0x01
++
++char MouseHIDReport[52] = {
++ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
++ 0x09, 0x02, // USAGE (Mouse)
++ 0xa1, 0x01, // COLLECTION (Application)
++ 0x09, 0x01, // USAGE (Pointer)
++ 0xa1, 0x00, // COLLECTION (Physical)
++ 0x05, 0x09, // USAGE_PAGE (Button)
++ 0x19, 0x01, // USAGE_MINIMUM (Button 1)
++ 0x29, 0x03, // USAGE_MAXIMUM (Button 3)
++ 0x15, 0x00, // LOGICAL_MINIMUM (0)
++ 0x25, 0x01, // LOGICAL_MAXIMUM (1)
++ 0x95, 0x03, // REPORT_COUNT (3)
++ 0x75, 0x01, // REPORT_SIZE (1)
++ 0x81, 0x02, // INPUT (Data,Var,Abs)
++ 0x95, 0x01, // REPORT_COUNT (1)
++ 0x75, 0x05, // REPORT_SIZE (5)
++ 0x81, 0x03, // INPUT (Cnst,Var,Abs)
++ 0x05, 0x01, // USAGE_PAGE (Generic Desktop)
++ 0x09, 0x30, // USAGE (X)
++ 0x09, 0x31, // USAGE (Y)
++ 0x09, 0x38, // USAGE (WHEEL)
++ 0x15, 0x81, // LOGICAL_MINIMUM (-127)
++ 0x25, 0x7f, // LOGICAL_MAXIMUM (127)
++ 0x75, 0x08, // REPORT_SIZE (8)
++ 0x95, 0x03, // REPORT_COUNT (3)
++ 0x81, 0x06, // INPUT (Data,Var,Rel)
++ 0xc0, // END_COLLECTION
++ 0xc0 // END_COLLECTION
++};
++
++struct usb_endpoint_descriptor mouse_data = {
++ bLength: 0x07,
++ bDescriptorType: USB_DT_ENDPOINT,
++ bEndpointAddress: IN,
++ bmAttributes: INTERRUPT,
++ wMaxPacketSize: __constant_cpu_to_le16(0x10),
++ bInterval: 0x01,
++};
++
++struct hid_descriptor mouse_hid = {
++ bLength: 0x09,
++ bDescriptorType: 0x21,
++ bcdHID: __constant_cpu_to_le16(0x110),
++ bCountryCode: 0x00,
++ bNumDescriptors: 0x01,
++ bReportType: 0x22,
++ wItemLength: __constant_cpu_to_le16(0x34),
++};
++
++static struct usb_endpoint_descriptor *mouse_default[] = { &mouse_data, };
++u8 mouse_indexes[] = { BULK_INT, };
++static struct usb_generic_class_descriptor *mouse_hid_descriptors[] = { (struct usb_generic_class_descriptor *)&mouse_hid, };
++
++/* Data Interface Alternate description(s)
++ */
++static __u8 mouse_data_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, 0x00, 0x00, // bInterfaceNumber, bAlternateSetting
++ sizeof (mouse_default) / sizeof(struct usb_endpoint_descriptor), // bNumEndpoints
++ 0x03, 0x01, 0x02, 0x00,
++};
++
++static struct usb_alternate_description mouse_data_alternate_descriptions[] = {
++ { iInterface:"Simple Mouse Interface - Interrupt",
++ interface_descriptor: (struct usb_interface_descriptor *)&mouse_data_alternate_descriptor,
++ classes:sizeof (mouse_hid_descriptors) / sizeof (struct usb_generic_class_descriptor *),
++ class_list: mouse_hid_descriptors,
++ endpoints:sizeof (mouse_default) / sizeof(struct usb_endpoint_descriptor *),
++ endpoint_list: mouse_default,
++ endpoint_indexes: mouse_indexes,
++ },
++};
++
++/* Interface description(s)
++ */
++static struct usb_interface_description mouse_interfaces[] = {
++ { alternates:sizeof (mouse_data_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list:mouse_data_alternate_descriptions,},
++};
++
++
++/* Configuration description(s)
++ */
++static __u8 mouse_configuration_descriptor[sizeof(struct usb_configuration_descriptor)] = {
++ 0x09, USB_DT_CONFIG, 0x00, 0x00, // wLength
++ sizeof (mouse_interfaces) / sizeof (struct usb_interface_description),
++ 0x01, 0x00, // bConfigurationValue, iConfiguration
++ BMATTRIBUTE, BMAXPOWER,
++};
++
++struct usb_configuration_description mouse_description[] = {
++ { configuration_descriptor: (struct usb_configuration_descriptor *)mouse_configuration_descriptor,
++ iConfiguration:"USB Simple Serial Configuration",
++ bNumInterfaces:sizeof (mouse_interfaces) / sizeof (struct usb_interface_description),
++ interface_list:mouse_interfaces,},
++};
++
++/* Device Description
++ */
++static struct usb_device_descriptor mouse_device_descriptor = {
++ bLength: sizeof(struct usb_device_descriptor),
++ bDescriptorType: USB_DT_DEVICE,
++ bcdUSB: __constant_cpu_to_le16(USB_BCD_VERSION),
++ bDeviceClass: 0x00,
++ bDeviceSubClass: 0x00,
++ bDeviceProtocol: 0x00,
++ bMaxPacketSize0: 0x00,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_MOUSE_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_MOUSE_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_MOUSE_BCDDEVICE),
++};
++
++static struct usb_endpoint_request mouse_endpoint_requests[ENDPOINTS+1] = {
++ { 1, 0, 0, USB_DIR_IN | USB_ENDPOINT_INTERRUPT, 16, 64, },
++ { 0, },
++};
++
++
++struct usb_device_description mouse_device_description = {
++ device_descriptor: &mouse_device_descriptor,
++ iManufacturer: CONFIG_USBD_MOUSE_MANUFACTURER,
++ iProduct: CONFIG_USBD_MOUSE_PRODUCT_NAME,
++#if !defined(CONFIG_USBD_NO_SERIAL_NUMBER) && defined(CONFIG_USBD_SERIAL_NUMBER_STR)
++ iSerialNumber: CONFIG_USBD_SERIAL_NUMBER_STR,
++#endif
++ endpointsRequested: ENDPOINTS,
++ requestedEndpoints: mouse_endpoint_requests,
++};
++
++
++/* MOUSE ***************************************************************************************** */
++
++struct mouse_private {
++ struct usb_function_instance *function;
++ struct tq_struct notification_bh;
++ int usb_driver_registered; // non-zero if usb function registered
++ unsigned char connected; // non-zero if connected to host (configured)
++ unsigned int writesize; // packetsize * 4
++ struct urb *tx_urb;
++ int wLength;
++ int x;
++ int y;
++ int last_x;
++ int last_y;
++ int n;
++};
++
++struct mouse_private mouse_private;
++
++
++/* Transmit Function *************************************************************************** */
++
++int get_xy[8] = {
++ 0, 0, 1, 1,
++ 0, 0, -1, -1,
++};
++
++void mouse_send(struct usb_function_instance *function)
++{
++ struct mouse_private *mouse = &mouse_private;
++ int new_x = 0;
++ int new_y = 0;
++ u8 random;
++
++ memset(mouse->tx_urb->buffer, 0, 4);
++ if (!mouse->n) {
++
++ get_random_bytes(&random, 1);
++
++ mouse->last_x = MAX(-4, MIN(4, mouse->last_x + get_xy[random & 0x7]));
++ mouse->last_y = MAX(-4, MIN(4, mouse->last_y + get_xy[(random >> 3) & 0x7]));
++ mouse->n = (random>>6) & 0x3;
++
++ new_x = mouse->x + mouse->last_x;
++ new_y = mouse->y + mouse->last_y;
++
++ mouse->tx_urb->buffer[1] = mouse->last_x;
++ mouse->x = new_x;
++ mouse->tx_urb->buffer[2] = mouse->last_y;
++ mouse->y = new_y;
++ mouse->tx_urb->actual_length = 4;
++#if 0
++ printk(KERN_INFO"%s: x: %4d y: %4d rand: %02x x: %2d y: %2d new_x: %4d new_y: %4d urb: %02x %02x %02x %02x\n",
++ __FUNCTION__,
++ mouse->x, mouse->y, random, x, y, new_x, new_y,
++ mouse->tx_urb->buffer[0], mouse->tx_urb->buffer[1],
++ mouse->tx_urb->buffer[2], mouse->tx_urb->buffer[3] );
++#endif
++ }
++ else if ((mouse->n)&1) {
++ mouse->n--;
++ }
++ else {
++ mouse->n--;
++ mouse->tx_urb->buffer[1] = mouse->last_x;
++ mouse->x = new_x;
++ mouse->tx_urb->buffer[2] = mouse->last_y;
++ mouse->y = new_y;
++ }
++ usbd_send_urb(mouse->tx_urb);
++}
++
++/* mouse_urb_sent - called to indicate URB transmit finished
++ * @urb: pointer to struct urb
++ * @rc: result
++ */
++int mouse_urb_sent (struct urb *urb, int rc)
++{
++ struct mouse_private *mouse = &mouse_private;
++ struct usb_function_instance *function = mouse->function;
++
++ RETURN_ZERO_IF(usbd_bus_status(function) == USBD_CLOSING);
++ RETURN_ZERO_IF(usbd_bus_status(function) != USBD_OK);
++ RETURN_ZERO_IF(usbd_device_state(function) != STATE_CONFIGURED);
++
++ mouse_send(function); // re-send
++ return 0;
++}
++
++/* USB Device Functions ************************************************************************ */
++
++/* mouse_event_irq - process a device event
++ *
++ */
++void mouse_event_irq (struct usb_function_instance *function, usb_device_event_t event, int data)
++{
++ struct mouse_private *mouse = &mouse_private;
++
++ switch (event) {
++ case DEVICE_CONFIGURED:
++ mouse->connected = 1;
++ if (!(mouse->tx_urb = usbd_alloc_urb (function, BULK_INT, 4, mouse_urb_sent)))
++ printk(KERN_INFO"%s: alloc failed\n", __FUNCTION__);
++ mouse_send(function); // start sending
++ break;
++
++ case DEVICE_RESET:
++ case DEVICE_DE_CONFIGURED:
++ BREAK_IF(!mouse->connected);
++ mouse->connected = 0;
++ if (mouse->tx_urb) {
++ usbd_dealloc_urb (mouse->tx_urb);
++ mouse->tx_urb = NULL;
++ }
++ break;
++ default:
++ break;
++ }
++}
++
++/* copy_config
++ * @urb: pointer to urb
++ * @data: pointer to configuration data
++ * @length: length of data
++ *
++ * Copy configuration data to urb transfer buffer if there is room for it.
++ */
++static int copy_report (struct urb *urb, void *data, int size, int max_buf)
++{
++ int available;
++ int length;
++
++ RETURN_EINVAL_IF (!urb);
++ RETURN_EINVAL_IF (!data);
++ RETURN_EINVAL_IF (!(length = size));
++ RETURN_EINVAL_IF ((available = max_buf - urb->actual_length) <= 0);
++
++ length = (length < available) ? length : available;
++ memcpy (urb->buffer + urb->actual_length, data, length);
++ urb->actual_length += length;
++ return 0;
++}
++
++/* mouse_send_hid - send an EP0 urb containing HID report
++ */
++static int mouse_send_hid (void *data)
++{
++ struct mouse_private *mouse = &mouse_private;
++ struct usb_function_instance *function = mouse->function;
++ struct urb *urb = usbd_alloc_urb_ep0(function, mouse->wLength, NULL);
++ RETURN_EINVAL_IF (copy_report(urb, MouseHIDReport, sizeof(MouseHIDReport), mouse->wLength));
++ RETURN_ZERO_IF(!usbd_send_urb(urb));
++ usbd_dealloc_urb(urb);
++ return -EINVAL;
++}
++
++#ifdef CONFIG_USBD_MOUSE_BH
++/* mouse_hid_bh - Bottom half handler to send a HID report
++ */
++static void mouse_hid_bh (void *data)
++{
++ struct usb_function_instance *function = mouse_private.function;
++ mouse_send_hid(function);
++ MOD_DEC_USE_COUNT;
++}
++
++/* mouse_schedule_bh - schedule a call for mouse_hid_bh
++ */
++static int mouse_schedule_bh (void)
++{
++ MOD_INC_USE_COUNT;
++ if (!schedule_task (&mouse_private.notification_bh)) {
++ MOD_DEC_USE_COUNT;
++ return -EINVAL;
++ }
++ return 0;
++}
++#endif /* CONFIG_USBD_MOUSE_BH */
++
++
++
++/* mouse_recv_setup_irq - called to indicate urb has been received
++ */
++int mouse_recv_setup_irq (struct usb_device_request *request)
++{
++ struct usb_function_instance *function = mouse_private.function;
++
++ /* verify that this is a usb class request per cdc-mouse specification or a vendor request.
++ * determine the request direction and process accordingly
++ */
++ switch (request->bmRequestType & (USB_REQ_DIRECTION_MASK | USB_REQ_TYPE_MASK)) {
++
++ case USB_REQ_HOST2DEVICE:
++ case USB_REQ_HOST2DEVICE | USB_REQ_TYPE_CLASS:
++ case USB_REQ_HOST2DEVICE | USB_REQ_TYPE_VENDOR:
++ return 0;
++
++ case USB_REQ_DEVICE2HOST :
++ case USB_REQ_DEVICE2HOST | USB_REQ_TYPE_CLASS:
++ case USB_REQ_DEVICE2HOST | USB_REQ_TYPE_VENDOR:
++
++ switch (request->bRequest) {
++ case USB_REQ_GET_DESCRIPTOR:
++ switch (le16_to_cpu(request->wValue)>>8) {
++ case HID_REPORT:
++ mouse_private.wLength = request->wLength;
++#ifdef CONFIG_USBD_MOUSE_BH
++ return mouse_schedule_bh();
++#else
++ return mouse_send_hid(function);
++#endif
++ }
++ default: break;
++ }
++ break;
++
++ default:
++ break;
++ }
++ return -EINVAL;
++}
++
++
++static int mouse_function_enable (struct usb_function_instance *function)
++{
++ struct mouse_private *mouse = &mouse_private;
++
++ MOD_INC_USE_COUNT;
++ mouse->function = function;
++ mouse->n = 0;
++ mouse->x = 0;
++ mouse->y = 0;
++ mouse->last_x = 0;
++ mouse->last_y = 0;
++
++ mouse->writesize = usbd_endpoint_wMaxPacketSize(function, BULK_INT, 0);
++
++ return 0;
++}
++
++static void mouse_function_disable (struct usb_function_instance *function)
++{
++ struct mouse_private *mouse = &mouse_private;
++ mouse->function = NULL;
++ mouse->writesize = 0;
++ mouse->function = NULL;
++ MOD_DEC_USE_COUNT;
++}
++
++static struct usb_function_operations function_ops = {
++ event_irq: mouse_event_irq,
++ recv_setup_irq: mouse_recv_setup_irq,
++ function_enable: mouse_function_enable,
++ function_disable: mouse_function_disable,
++};
++
++static struct usb_function_driver function_driver = {
++ name:"mouse-random",
++ fops:&function_ops,
++ device_description:&mouse_device_description,
++ bNumConfigurations:sizeof (mouse_description) / sizeof (struct usb_configuration_description),
++ configuration_description:mouse_description,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_MOUSE_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_MOUSE_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_MOUSE_BCDDEVICE),
++};
++
++
++/* USB Module init/exit ************************************************************************ */
++/*
++ * mouse_modinit - module init
++ *
++ */
++static int mouse_modinit (void)
++{
++ printk (KERN_INFO "%s: %s vendor_id: %04x product_id: %04x\n", __FUNCTION__, __usbd_module_info, vendor_id, product_id);
++
++ if (vendor_id)
++ function_driver.idVendor = cpu_to_le16(vendor_id);
++ if (product_id)
++ function_driver.idProduct = cpu_to_le16(product_id);
++
++ mouse_hid.wItemLength = cpu_to_le16(0x34); // XXX mips compiler bug.....
++
++ // register as usb function driver
++ THROW_IF (usbd_register_function (&function_driver), error);
++ mouse_private.usb_driver_registered++;
++#ifdef CONFIG_USBD_MOUSE_BH
++ mouse_private.notification_bh.routine = mouse_hid_bh;
++ mouse_private.notification_bh.data = NULL;
++#endif
++ CATCH(error) {
++ if (mouse_private.usb_driver_registered) {
++ usbd_deregister_function (&function_driver);
++ mouse_private.usb_driver_registered = 0;
++ }
++ return -EINVAL;
++ }
++ return 0;
++}
++
++/* mouse_modexit - module cleanup
++ */
++static void mouse_modexit (void)
++{
++ if (mouse_private.usb_driver_registered) {
++ usbd_deregister_function (&function_driver);
++ }
++}
++
++
++module_init (mouse_modinit);
++module_exit (mouse_modexit);
+diff -Nru a/drivers/usbd/network_fd/Config.in b/drivers/usbd/network_fd/Config.in
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/network_fd/Config.in Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,97 @@
++#
++# Network Function
++#
++# Copyright (C) 2002-2003 Belcarra
++#
++
++mainmenu_option next_comment
++comment "Network Function"
++
++dep_tristate ' Network Function Driver' CONFIG_USBD_NETWORK $CONFIG_USBD
++
++if [ "$CONFIG_USBD_NETWORK" = "y" -o "$CONFIG_USBD_NETWORK" = "m" ]; then
++
++ hex 'VendorID (hex value)' CONFIG_USBD_NETWORK_VENDORID "12b9"
++ hex 'ProductID (hex value)' CONFIG_USBD_NETWORK_PRODUCTID "f001"
++ hex 'bcdDevice (binary-coded decimal)' CONFIG_USBD_NETWORK_BCDDEVICE "0100"
++
++ string 'iManufacturer (string)' CONFIG_USBD_NETWORK_MANUFACTURER "Belcarra"
++ string 'iProduct (string)' CONFIG_USBD_NETWORK_PRODUCT_NAME "Belcarra BLAN Device"
++
++
++ comment ''
++ bool " MDLM-BLAN Networking mode (Personal Devices)" CONFIG_USBD_NETWORK_BLAN
++ if [ "$CONFIG_USBD_NETWORK_BLAN" = "y" ]; then
++ string ' iConfiguration (string)' CONFIG_USBD_NETWORK_BLAN_DESC "BLAN Net Cfg"
++ string ' iInterface (string)' CONFIG_USBD_NETWORK_BLAN_INTF "Comm/Data Intf"
++ fi
++
++ if [ "$CONFIG_USBD_NETWORK_BLAN" = "y" ]; then
++ bool " CRC" CONFIG_USBD_NETWORK_BLAN_CRC
++
++ if [ "$CONFIG_USBD_NETWORK_BLAN_CRC" = "y" ]; then
++
++ bool " Pad Before CRC (to wMaxPacketSize-1)" CONFIG_USBD_NETWORK_BLAN_PADBEFORE
++ bool " Pad After CRC" CONFIG_USBD_NETWORK_BLAN_PADAFTER
++ if [ "$CONFIG_USBD_NETWORK_BLAN" = "y" -a "$CONFIG_USBD_NETWORK_BLAN_PADAFTER" = "y" ]; then
++ int ' Pad multiple' CONFIG_USBD_NETWORK_BLAN_PADBYTES "8"
++ fi
++ bool " Fermat Randomizer" CONFIG_USBD_NETWORK_BLAN_FERMAT
++ fi
++ bool " Do not Set Time" CONFIG_USBD_NETWORK_BLAN_DO_NOT_SETTIME
++ bool " Request Hostname" CONFIG_USBD_NETWORK_BLAN_HOSTNAME
++ bool " Infrastructure Device" CONFIG_USBD_NETWORK_BLAN_NOBRIDGE
++ comment ''
++ fi
++
++ bool " MDLM-SAFE Networking mode (Bridge/Routers)" CONFIG_USBD_NETWORK_SAFE
++ if [ "$CONFIG_USBD_NETWORK_SAFE" = "y" ]; then
++ string ' Data Interface iConfiguration (string)' CONFIG_USBD_NETWORK_SAFE_DESC "SAFE Net Cfg"
++ string ' Data Interface iInterface (string)' CONFIG_USBD_NETWORK_SAFE_INTF "Data Intf"
++ fi
++
++
++ if [ "$CONFIG_USBD_NETWORK_SAFE" = "y" ]; then
++ bool " Do not Set Time" CONFIG_USBD_NETWORK_SAFE_DO_NOT_SETTIME
++ bool " CRC" CONFIG_USBD_NETWORK_SAFE_CRC
++ if [ "$CONFIG_USBD_NETWORK_SAFE_CRC" = "y" ]; then
++ bool " Pad Before CRC (to wMaxPacketSize-1)" CONFIG_USBD_NETWORK_SAFE_PADBEFORE
++ fi
++ bool " Infrastructure Device" CONFIG_USBD_NETWORK_SAFE_NOBRIDGE
++ comment ''
++ fi
++
++ bool " CDC Networking mode (Bridge/Routers)" CONFIG_USBD_NETWORK_CDC
++ if [ "$CONFIG_USBD_NETWORK_CDC" = "y" ]; then
++ string ' iConfiguration (string)' CONFIG_USBD_NETWORK_CDC_DESC "SAFE Net Cfg"
++ string ' Data Interface iInterface (string)' CONFIG_USBD_NETWORK_CDC_COMM_INTF "Comm Intf"
++ string ' Data (diabled) iInterface (string)' CONFIG_USBD_NETWORK_CDC_NODATA_INTF "Data (Disabled) Intf"
++ string ' Comm Interface iInterface (string)' CONFIG_USBD_NETWORK_CDC_DATA_INTF "Dat Intf"
++ fi
++
++ if [ "$CONFIG_USBD_NETWORK_SAFE" = "y" -a "$CONFIG_USBD_NETWORK_CDC" = "y" ]; then
++ comment 'Warning: CDC and MDLM-SAFE not allowed'
++ fi
++
++
++ bool " Failsafe BASIC Networking mode" CONFIG_USBD_NETWORK_BASIC
++ if [ "$CONFIG_USBD_NETWORK_BASIC" = "y" ]; then
++ string ' Data Interface iConfiguration (string)' CONFIG_USBD_NETWORK_BASIC_DESC "BASIC Net Cfg"
++ string ' Data Interface iInterface (string)' CONFIG_USBD_NETWORK_BASIC_INTF "Data Intf"
++ fi
++
++ bool " Failsafe BASIC2 Networking mode" CONFIG_USBD_NETWORK_BASIC2
++ if [ "$CONFIG_USBD_NETWORK_BASIC2" = "y" ]; then
++ string ' Data Interface iConfiguration (string)' CONFIG_USBD_NETWORK_BASIC2_DESC "BASIC Net Cfg"
++ string ' Comm Interface iInterface (string)' CONFIG_USBD_NETWORK_BASIC2_COMM_INTF "Comm Intf"
++ string ' Data Interface iInterface (string)' CONFIG_USBD_NETWORK_BASIC2_DATA_INTF "Data Intf"
++ fi
++
++
++ comment ''
++ bool ' Start Single Urb Test' CONFIG_USBD_NETWORK_START_SINGLE
++ bool ' EP0 Test' CONFIG_USBD_NETWORK_EP0TEST
++
++fi
++
++endmenu
+diff -Nru a/drivers/usbd/network_fd/Makefile b/drivers/usbd/network_fd/Makefile
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/network_fd/Makefile Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,66 @@
++#
++# Network Function Driver
++#
++# Copyright (C) 2002-2003 Belcarra
++
++
++O_TARGET := network_fd.o
++list-multi := network_fd.o
++
++network_fd-objs := network.o basic.o basic2.o blan.o cdc.o safe.o fermat.o
++
++# Objects that export symbols.
++export-objs := network.o
++
++
++# Object file lists.
++
++obj-y :=
++obj-m :=
++obj-n :=
++obj- :=
++
++# Each configuration option enables a list of files.
++
++obj-$(CONFIG_USBD_NETWORK) += network_fd.o
++
++# Extract lists of the multi-part drivers.
++# The 'int-*' lists are the intermediate files used to build the multi's.
++
++multi-y := $(filter $(list-multi), $(obj-y))
++multi-m := $(filter $(list-multi), $(obj-m))
++int-y := $(sort $(foreach m, $(multi-y), $($(basename $(m))-objs)))
++int-m := $(sort $(foreach m, $(multi-m), $($(basename $(m))-objs)))
++
++# Files that are both resident and modular: remove from modular.
++
++obj-m := $(filter-out $(obj-y), $(obj-m))
++int-m := $(filter-out $(int-y), $(int-m))
++
++# Translate to Rules.make lists.
++
++O_OBJS := $(filter-out $(export-objs), $(obj-y))
++OX_OBJS := $(filter $(export-objs), $(obj-y))
++M_OBJS := $(sort $(filter-out $(export-objs), $(obj-m)))
++MX_OBJS := $(sort $(filter $(export-objs), $(obj-m)))
++MI_OBJS := $(sort $(filter-out $(export-objs), $(int-m)))
++MIX_OBJS := $(sort $(filter $(export-objs), $(int-m)))
++
++# The global Rules.make.
++
++USBD=$(TOPDIR)/drivers/usbd
++NETWORKD=$(USBD)/network_fd
++include $(TOPDIR)/Rules.make
++EXTRA_CFLAGS += -I$(NETWORKD) -I$(USBD) -Wno-unused -Wno-format
++EXTRA_CFLAGS_nostdinc += -I$(NETWORKD) -I$(USBD) -Wno-unused -Wno-format
++
++# Link rules for multi-part drivers.
++
++network_fd.o: $(network_fd-objs)
++ $(LD) -r -o $@ $(network_fd-objs)
++
++# dependencies:
++
++network.o: network.h $(USBD)/usbd.h $(USBD)/usbd-bus.h $(USBD)/usbd-func.h
++
++
+diff -Nru a/drivers/usbd/network_fd/basic.c b/drivers/usbd/network_fd/basic.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/network_fd/basic.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,157 @@
++/*
++ * usbd/network_fd/basic.c - Network Function Driver
++ *
++ * Copyright (c) 2002, 2003, 2004 Belcarra
++ *
++ * By:
++ * Chris Lynne <cl@belcarra.com>
++ * Stuart Lynne <sl@belcarra.com>
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++#include <usbd-export.h>
++#include <usbd-build.h>
++
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/utsname.h>
++#include <linux/netdevice.h>
++
++#include <usbd-chap9.h>
++#include <usbd-mem.h>
++#include <usbd.h>
++#include <usbd-func.h>
++
++#include "network.h"
++
++
++#ifdef CONFIG_USBD_NETWORK_BASIC
++/* USB BASIC Configuration ******************************************************************** */
++
++/* BASIC Communication Interface Class descriptors
++ */
++static __u8 basic_data_1[] = { 0x07, USB_DT_ENDPOINT, OUT, BULK, 0, 0x00, 0x00, };
++static __u8 basic_data_2[] = { 0x07, USB_DT_ENDPOINT, IN, BULK, 0, 0x00, 0x00, };
++static __u8 basic_comm_1[] = { 0x07, USB_DT_ENDPOINT, IN, INTERRUPT,0, 0x00, 0x0a, };
++
++static struct usb_endpoint_descriptor *basic_default[] = {
++ (struct usb_endpoint_descriptor *) &basic_data_1,
++ (struct usb_endpoint_descriptor *) &basic_data_2,
++ (struct usb_endpoint_descriptor *) &basic_comm_1, };
++u8 basic_indexes[] = { BULK_OUT, BULK_IN, INT_IN, };
++
++/* BASIC Data Interface Alternate endpoints
++ */
++static __u8 basic_data_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, 0x00, 0x00, // bInterfaceNumber, bAlternateSetting
++ sizeof (basic_default) / sizeof(struct usb_endpoint_descriptor), // bNumEndpoints
++ LINEO_CLASS, LINEO_SUBCLASS_BASIC_NET, LINEO_BASIC_NET_CRC, 0x00,
++};
++
++static struct usb_alternate_description basic_data_alternate_descriptions[] = {
++ { iInterface: CONFIG_USBD_NETWORK_BASIC_INTF,
++ interface_descriptor: (struct usb_interface_descriptor *)&basic_data_alternate_descriptor,
++ endpoints:sizeof (basic_default) / sizeof(struct usb_endpoint_descriptor *),
++ endpoint_list: basic_default,
++ endpoint_indexes: basic_indexes,
++ },
++};
++
++
++/* BASIC Data Interface Alternate descriptions and descriptors
++ */
++
++/* BASIC Interface descriptions and descriptors
++ */
++struct usb_interface_description basic_interfaces[] = {
++ { alternates:sizeof (basic_data_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list:basic_data_alternate_descriptions,},
++};
++
++/* BASIC Configuration descriptions and descriptors
++ */
++__u8 basic_configuration_descriptor[sizeof(struct usb_configuration_descriptor)] = {
++ 0x09, USB_DT_CONFIG, 0x00, 0x00, // wLength
++ sizeof (basic_interfaces) / sizeof (struct usb_interface_description),
++ 0x01, 0x00, // bConfigurationValue, iConfiguration
++ BMATTRIBUTE, BMAXPOWER,
++};
++
++struct usb_configuration_description basic_description[] = {
++ { iConfiguration: CONFIG_USBD_NETWORK_BASIC_DESC,
++ configuration_descriptor: (struct usb_configuration_descriptor *)basic_configuration_descriptor,
++ bNumInterfaces:sizeof (basic_interfaces) / sizeof (struct usb_interface_description),
++ interface_list:basic_interfaces,},
++
++};
++
++/* BASIC Device Description
++ */
++static struct usb_device_descriptor basic_device_descriptor = {
++ bLength: sizeof(struct usb_device_descriptor),
++ bDescriptorType: USB_DT_DEVICE,
++ bcdUSB: __constant_cpu_to_le16(USB_BCD_VERSION),
++ bDeviceClass: COMMUNICATIONS_DEVICE_CLASS,
++ bDeviceSubClass: 0x02,
++ bDeviceProtocol: 0x00,
++ bMaxPacketSize0: 0x00,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_BCDDEVICE),
++};
++
++static struct usb_endpoint_request basic_endpoint_requests[ENDPOINTS+1] = {
++ { 1, 0, 0, USB_DIR_OUT | USB_ENDPOINT_BULK, MAXFRAMESIZE + 48, MAXFRAMESIZE + 512, },
++ { 1, 0, 0, USB_DIR_IN | USB_ENDPOINT_BULK, MAXFRAMESIZE + 48, MAXFRAMESIZE + 512, },
++ { 1, 0, 0, USB_DIR_IN | USB_ENDPOINT_INTERRUPT | USB_ENDPOINT_OPT, 16, 64, },
++ { 0, },
++};
++
++struct usb_device_description basic_device_description = {
++ device_descriptor: &basic_device_descriptor,
++ iManufacturer: CONFIG_USBD_NETWORK_MANUFACTURER,
++ iProduct: CONFIG_USBD_NETWORK_PRODUCT_NAME,
++#if !defined(CONFIG_USBD_NO_SERIAL_NUMBER) && defined(CONFIG_USBD_SERIAL_NUMBER_STR)
++ iSerialNumber:CONFIG_USBD_SERIAL_NUMBER_STR,
++#endif
++ endpointsRequested: ENDPOINTS,
++ requestedEndpoints: basic_endpoint_requests,
++};
++
++
++void basic_init (struct usb_function_instance *function)
++{
++ basic_data_alternate_descriptions[0].endpoints = Usb_network_private.have_interrupt ? 3 : 2;
++}
++
++struct usb_function_driver basic_function_driver = {
++ name: "network-BASIC",
++ fops: &network_fd_function_ops,
++ device_description: &basic_device_description,
++ bNumConfigurations: sizeof (basic_description) / sizeof (struct usb_configuration_description),
++ configuration_description: basic_description,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_BCDDEVICE),
++};
++#endif /* CONFIG_USBD_NETWORK_BASIC */
++
+diff -Nru a/drivers/usbd/network_fd/basic2.c b/drivers/usbd/network_fd/basic2.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/network_fd/basic2.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,198 @@
++/*
++ * usbd/network_fd/basic22.c - Network Function Driver
++ *
++ * Copyright (c) 2002, 2003, 2004 Belcarra
++ *
++ * By:
++ * Chris Lynne <cl@belcarra.com>
++ * Stuart Lynne <sl@belcarra.com>
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++#include <usbd-export.h>
++#include <usbd-build.h>
++
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/utsname.h>
++#include <linux/netdevice.h>
++
++#include <usbd-chap9.h>
++#include <usbd-mem.h>
++#include <usbd.h>
++#include <usbd-func.h>
++
++#include "network.h"
++
++
++#ifdef CONFIG_USBD_NETWORK_BASIC2
++/* USB BASIC Configuration ******************************************************************** */
++
++/*
++ * This provides a slight amplification of the basic configuration, it moves the
++ * interrupt endpoint (if available) to a separate interface, so that it is similiar
++ * to the cdc configuration
++ */
++
++/* BASIC Communication Interface Class descriptors
++ */
++static __u8 basic2_data_1[] = { 0x07, USB_DT_ENDPOINT, OUT, BULK, 0, 0x00, 0x00, };
++static __u8 basic2_data_2[] = { 0x07, USB_DT_ENDPOINT, IN, BULK, 0, 0x00, 0x00, };
++static __u8 basic2_comm_1[] = { 0x07, USB_DT_ENDPOINT, IN, INTERRUPT,0, 0x00, 0x0a, };
++
++static __u8 *basic2_comm_endpoints[] = {
++ (struct usb_endpoint_descriptor *) &basic2_comm_1, };
++
++static __u8 *basic2_data_endpoints[] = {
++ (struct usb_endpoint_descriptor *) &basic2_data_1,
++ (struct usb_endpoint_descriptor *) &basic2_data_2, };
++
++u8 basic2_comm_indexes[] = { INT_IN, };
++u8 basic2_data_indexes[] = { BULK_OUT, BULK_IN, };
++
++
++/* BASIC2 Data Interface Alternate endpoints
++ */
++
++static __u8 basic2_comm_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, 0x00, 0x00, // bInterfaceNumber, bAlternateSetting
++ sizeof (basic2_comm_endpoints) / sizeof(struct usb_endpoint_descriptor), // bNumEndpoints
++ COMMUNICATIONS_INTERFACE_CLASS, COMMUNICATIONS_NETWORK_SUBCLASS, VENDOR, 0x00,
++};
++static __u8 basic2_data_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, 0x01, 0x00, // bInterfaceNumber, bAlternateSetting
++ sizeof (basic2_data_endpoints) / sizeof(struct usb_endpoint_descriptor), // bNumEndpoints
++ DATA_INTERFACE_CLASS, COMMUNICATIONS_NO_SUBCLASS, COMMUNICATIONS_NO_PROTOCOL, 0x00,
++};
++
++static struct usb_alternate_description basic2_comm_alternate_descriptions[] = {
++ { iInterface: CONFIG_USBD_NETWORK_BASIC2_COMM_INTF,
++ interface_descriptor: (struct usb_interface_descriptor *)&basic2_comm_alternate_descriptor,
++ endpoints:sizeof (basic2_comm_endpoints) / sizeof(struct usb_endpoint_descriptor *),
++ endpoint_list:basic2_comm_endpoints,
++ endpoint_indexes:basic2_comm_indexes,
++ },
++};
++
++
++static struct usb_alternate_description basic2_data_alternate_descriptions[] = {
++ { iInterface: CONFIG_USBD_NETWORK_BASIC2_DATA_INTF,
++ interface_descriptor: (struct usb_interface_descriptor *)&basic2_data_alternate_descriptor,
++ endpoints:sizeof (basic2_data_endpoints) / sizeof(struct usb_endpoint_descriptor *),
++ endpoint_list: basic2_data_endpoints,
++ endpoint_indexes: basic2_data_indexes,
++ },
++};
++
++
++/* BASIC Data Interface Alternate descriptions and descriptors
++ */
++
++/* BASIC Interface descriptions and descriptors
++ */
++static struct usb_interface_description basic2_interfaces[] = {
++ { alternates:sizeof (basic2_comm_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list:basic2_comm_alternate_descriptions,},
++
++ { alternates:sizeof (basic2_data_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list:basic2_data_alternate_descriptions,},
++};
++
++
++/* BASIC Configuration descriptions and descriptors
++ */
++__u8 basic2_configuration_descriptor[sizeof(struct usb_configuration_descriptor)] = {
++ 0x09, USB_DT_CONFIG, 0x00, 0x00, // wLength
++ sizeof (basic2_interfaces) / sizeof (struct usb_interface_description),
++ 0x01, 0x00, // bConfigurationValue, iConfiguration
++ BMATTRIBUTE, BMAXPOWER,
++};
++
++struct usb_configuration_description basic2_description[] = {
++ { iConfiguration: CONFIG_USBD_NETWORK_BASIC2_DESC,
++ configuration_descriptor: (struct usb_configuration_descriptor *)basic2_configuration_descriptor,
++ bNumInterfaces:sizeof (basic2_interfaces) / sizeof (struct usb_interface_description),
++ interface_list:basic2_interfaces,},
++
++};
++
++/* BASIC Device Description
++ */
++static struct usb_device_descriptor basic2_device_descriptor = {
++ bLength: sizeof(struct usb_device_descriptor),
++ bDescriptorType: USB_DT_DEVICE,
++ bcdUSB: __constant_cpu_to_le16(USB_BCD_VERSION),
++ bDeviceClass: COMMUNICATIONS_DEVICE_CLASS,
++ bDeviceSubClass: 0x02,
++ bDeviceProtocol: 0x00,
++ bMaxPacketSize0: 0x00,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_BASIC2_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_BASIC2_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_BASIC2_BCDDEVICE),
++};
++
++static struct usb_endpoint_request basic2_endpoint_requests[ENDPOINTS+1] = {
++ { 1, 0, 0, USB_DIR_OUT | USB_ENDPOINT_BULK, MAXFRAMESIZE + 48, MAXFRAMESIZE + 512, },
++ { 1, 0, 0, USB_DIR_IN | USB_ENDPOINT_BULK, MAXFRAMESIZE + 48, MAXFRAMESIZE + 512, },
++ { 1, 0, 0, USB_DIR_IN | USB_ENDPOINT_INTERRUPT | USB_ENDPOINT_OPT, 16, 64, },
++ { 0, },
++};
++
++struct usb_device_description basic2_device_description = {
++ device_descriptor: &basic2_device_descriptor,
++ iManufacturer: CONFIG_USBD_NETWORK_MANUFACTURER,
++ iProduct: CONFIG_USBD_NETWORK_PRODUCT_NAME,
++#if !defined(CONFIG_USBD_NO_SERIAL_NUMBER) && defined(CONFIG_USBD_SERIAL_NUMBER_STR)
++ iSerialNumber:CONFIG_USBD_SERIAL_NUMBER_STR,
++#endif
++ endpointsRequested: ENDPOINTS,
++ requestedEndpoints: basic2_endpoint_requests,
++};
++
++
++void basic2_init (struct usb_function_instance *function)
++{
++ printk(KERN_INFO"%s:\n", __FUNCTION__);
++
++ basic2_comm_alternate_descriptions[0].endpoints = Usb_network_private.have_interrupt ? 1 : 0;
++
++ printk(KERN_INFO"%s: alternate: %p endpoints: %d\n", __FUNCTION__,
++ basic2_data_alternate_descriptions,
++ basic2_data_alternate_descriptions->endpoints
++ );
++
++ printk(KERN_INFO"%s: finis\n", __FUNCTION__);
++}
++
++
++struct usb_function_driver basic2_function_driver = {
++ name: "network-BASIC2",
++ fops: &network_fd_function_ops,
++ device_description: &basic2_device_description,
++ bNumConfigurations: sizeof (basic2_description) / sizeof (struct usb_configuration_description),
++ configuration_description: basic2_description,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_BASIC2_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_BASIC2_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_BASIC2_BCDDEVICE),
++};
++#endif /* CONFIG_USBD_NETWORK_BASIC2 */
++
+diff -Nru a/drivers/usbd/network_fd/blan.c b/drivers/usbd/network_fd/blan.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/network_fd/blan.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,251 @@
++/*
++ * usbd/network_fd/blan.c - Network Function Driver
++ *
++ * Copyright (c) 2002, 2003, 2004 Belcarra
++ *
++ * By:
++ * Chris Lynne <cl@belcarra.com>
++ * Stuart Lynne <sl@belcarra.com>
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++
++#include <usbd-export.h>
++#include <usbd-build.h>
++
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/utsname.h>
++#include <linux/netdevice.h>
++
++#include <usbd-chap9.h>
++#include <usbd-mem.h>
++#include <usbd.h>
++#include <usbd-func.h>
++
++#include "network.h"
++
++
++#ifdef CONFIG_USBD_NETWORK_BLAN
++/* USB BLAN Configuration ******************************************************************** */
++
++/*
++ * BLAN Ethernet Configuration
++ */
++
++/* Communication Interface Class descriptors
++ */
++
++static __u8 blan_data_1[] = { 0x07, USB_DT_ENDPOINT, OUT, BULK, 0, 0x00, 0x00, };
++static __u8 blan_data_2[] = { 0x07, USB_DT_ENDPOINT, IN, BULK, 0, 0x00, 0x00, };
++static __u8 blan_comm_1[] = { 0x07, USB_DT_ENDPOINT, IN, INTERRUPT,0, 0x00, 0x0a, };
++
++static __u8 blan_class_1[] = { 0x05, CS_INTERFACE, USB_ST_HEADER, 0x10, 0x01, /* CLASS_BDC_VERSION, CLASS_BDC_VERSION */ };
++static __u8 blan_class_2[] = { 0x15, CS_INTERFACE, USB_ST_MDLM, 0x00, 0x01, /* bcdVersion, bcdVersion */
++ 0x74, 0xf0, 0x3d, 0xbd, 0x1e, 0xc1, 0x44, 0x70, /* bGUID */
++ 0xa3, 0x67, 0x71, 0x34, 0xc9, 0xf5, 0x54, 0x37, /* bGUID */ };
++
++
++static __u8 blan_class_3[] = { 0x07, CS_INTERFACE, USB_ST_MDLMD, 0x01, 0x00, 0x00, 0x00, };
++
++static __u8 blan_class_4[] = { 0x0d, CS_INTERFACE, USB_ST_ENF,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x05, /* 1514 maximum frame size */
++ 0x00, 0x00, 0x00 , };
++
++static __u8 blan_class_5[] = { 0x07, CS_INTERFACE, USB_ST_NCT, 0x00, 0x00, 0x00, 0x00, };
++
++
++static struct usb_endpoint_descriptor *blan_alt_endpoints[] = {
++ (struct usb_endpoint_descriptor *) blan_data_1,
++ (struct usb_endpoint_descriptor *) blan_data_2,
++ (struct usb_endpoint_descriptor *) blan_comm_1, };
++
++u8 blan_alt_indexes[] = { BULK_OUT, BULK_IN, INT_IN, };
++
++static struct usb_generic_class_descriptor *blan_comm_class_descriptors[] = {
++ (struct usb_generic_class_descriptor *) blan_class_1,
++ (struct usb_generic_class_descriptor *) blan_class_2,
++ (struct usb_generic_class_descriptor *) blan_class_3,
++ (struct usb_generic_class_descriptor *) blan_class_4,
++ (struct usb_generic_class_descriptor *) blan_class_5, };
++
++
++/* Data Interface Alternate descriptions and descriptors
++ */
++static __u8 blan_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, 0x00, 0x00, // bInterfaceNumber, bAlternateSetting
++ sizeof (blan_alt_endpoints) / sizeof(struct usb_endpoint_descriptor), // bNumEndpoints
++ COMMUNICATIONS_INTERFACE_CLASS, COMMUNICATIONS_MDLM_SUBCLASS, COMMUNICATIONS_NO_PROTOCOL, 0x00,
++};
++
++static struct usb_alternate_description blan_alternate_descriptions[] = {
++ { iInterface: CONFIG_USBD_NETWORK_BLAN_INTF,
++ interface_descriptor: (struct usb_interface_descriptor *)&blan_alternate_descriptor,
++ classes:sizeof (blan_comm_class_descriptors) / sizeof (struct usb_generic_class_descriptor *),
++ class_list: blan_comm_class_descriptors,
++ endpoints:sizeof (blan_alt_endpoints) / sizeof(struct usb_endpoint_descriptor *),
++ endpoint_list: blan_alt_endpoints,
++ endpoint_indexes: blan_alt_indexes,
++ },
++};
++/* Interface descriptions and descriptors
++ */
++static struct usb_interface_description blan_interfaces[] = {
++ {
++ alternates: sizeof (blan_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list: blan_alternate_descriptions,
++ },
++};
++
++
++/* Configuration descriptions and descriptors
++ */
++
++static __u8 blan_configuration_descriptor[sizeof(struct usb_configuration_descriptor)] = {
++ 0x09, USB_DT_CONFIG, 0x00, 0x00, // wLength
++ sizeof (blan_interfaces) / sizeof (struct usb_interface_description),
++ 0x01, 0x00, // bConfigurationValue, iConfiguration
++ BMATTRIBUTE, BMAXPOWER,
++};
++
++struct usb_configuration_description blan_description[] = {
++ { iConfiguration: CONFIG_USBD_NETWORK_BLAN_DESC,
++ configuration_descriptor: (struct usb_configuration_descriptor *)blan_configuration_descriptor,
++ bNumInterfaces:sizeof (blan_interfaces) / sizeof (struct usb_interface_description),
++ interface_list:blan_interfaces, },
++};
++
++/* Device Description
++ */
++
++static struct usb_device_descriptor blan_device_descriptor = {
++ bLength: sizeof(struct usb_device_descriptor),
++ bDescriptorType: USB_DT_DEVICE,
++ bcdUSB: __constant_cpu_to_le16(USB_BCD_VERSION),
++ bDeviceClass: COMMUNICATIONS_DEVICE_CLASS,
++ bDeviceSubClass: 0x02,
++ bDeviceProtocol: 0x00,
++ bMaxPacketSize0: 0x00,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_BCDDEVICE),
++};
++
++static struct usb_endpoint_request blan_endpoint_requests[ENDPOINTS+1] = {
++ { 1, 0, 0, USB_DIR_OUT | USB_ENDPOINT_BULK, MAXFRAMESIZE + 48, MAXFRAMESIZE + 512, },
++ { 1, 0, 0, USB_DIR_IN | USB_ENDPOINT_BULK, MAXFRAMESIZE + 48, MAXFRAMESIZE + 512, },
++ { 1, 0, 0, USB_DIR_IN | USB_ENDPOINT_INTERRUPT | USB_ENDPOINT_OPT, 16, 64, },
++ { 0, },
++};
++
++struct usb_device_description blan_device_description = {
++ device_descriptor: &blan_device_descriptor,
++ iManufacturer: CONFIG_USBD_NETWORK_MANUFACTURER,
++ iProduct: CONFIG_USBD_NETWORK_PRODUCT_NAME,
++#if !defined(CONFIG_USBD_NO_SERIAL_NUMBER) && defined(CONFIG_USBD_SERIAL_NUMBER_STR)
++ iSerialNumber:CONFIG_USBD_SERIAL_NUMBER_STR,
++#endif
++ endpointsRequested: ENDPOINTS,
++ requestedEndpoints: blan_endpoint_requests,
++};
++
++
++void blan_init (struct usb_function_instance *function)
++{
++ struct usb_class_ethernet_networking_descriptor *ethernet;
++ struct usb_class_network_channel_descriptor *channel;
++
++ int len = 0;
++ char buf[255];
++
++ buf[0] = 0;
++
++ blan_alternate_descriptions[0].endpoints = Usb_network_private.have_interrupt ? 3 : 2;
++
++ // Update the iMACAddress field in the ethernet descriptor
++ {
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
++ char address_str[14];
++ snprintf(address_str, 13, "%02x%02x%02x%02x%02x%02x",
++ local_dev_addr[0], local_dev_addr[1], local_dev_addr[2],
++ local_dev_addr[3], local_dev_addr[4], local_dev_addr[5]);
++#else
++ char address_str[20];
++ sprintf(address_str, "%02x%02x%02x%02x%02x%02x",
++ local_dev_addr[0], local_dev_addr[1], local_dev_addr[2],
++ local_dev_addr[3], local_dev_addr[4], local_dev_addr[5]);
++#endif
++ //printk(KERN_INFO"%s: alloc mac string\n", __FUNCTION__);
++ if ((ethernet = (struct usb_class_ethernet_networking_descriptor *)blan_class_4))
++ ethernet->iMACAddress = usbd_alloc_string(address_str);
++ //printk(KERN_INFO"%s: alloc mac string finis\n", __FUNCTION__);
++ }
++ //printk(KERN_INFO"%s: alloc channel string\n", __FUNCTION__);
++ if ((channel = (struct usb_class_network_channel_descriptor *)blan_class_5))
++ channel->iName = usbd_alloc_string(system_utsname.nodename);
++ //printk(KERN_INFO"%s: alloc channel string finis\n", __FUNCTION__);
++
++#ifdef CONFIG_USBD_NETWORK_BLAN_PADBYTES
++ blan_class_3[6] = CONFIG_USBD_NETWORK_BLAN_PADBYTES;
++ len += sprintf(buf + len, "PADBYTES: %02x ", blan_class_3[6]);
++#endif
++#ifdef CONFIG_USBD_NETWORK_BLAN_PADBEFORE
++ blan_class_3[5] |= BMDATA_PADBEFORE;
++ len += sprintf(buf + len, "PADBEFORE: %02x ", blan_class_3[5]);
++#endif
++#ifdef CONFIG_USBD_NETWORK_BLAN_PADAFTER
++ blan_class_3[5] |= BMDATA_PADAFTER;
++ len += sprintf(buf + len, "PADAFTER: %02x ", blan_class_3[5]);
++#endif
++#ifdef CONFIG_USBD_NETWORK_BLAN_CRC
++ blan_class_3[5] |= BMDATA_CRC;
++ len += sprintf(buf + len, "CRC: %02x ", blan_class_3[5]);
++#endif
++#ifdef CONFIG_USBD_NETWORK_BLAN_FERMAT
++ blan_class_3[5] |= BMDATA_FERMAT;
++ len += sprintf(buf + len, "FERMAT: %02x ",blan_class_3[5]);
++#endif
++#ifdef CONFIG_USBD_NETWORK_BLAN_HOSTNAME
++ blan_class_3[5] |= BMDATA_HOSTNAME;
++ len += sprintf(buf + len, "HOSTNAME: %02x ",blan_class_3[5]);
++#endif
++#ifdef CONFIG_USBD_NETWORK_BLAN_NOBRIDGE
++ blan_class_3[4] |= BMNETWORK_NOBRIDGE;
++ len += sprintf(buf + len, "NOBRIDGE: %02x ",blan_class_3[4]);
++#endif
++ if (strlen(buf))
++ printk(KERN_INFO"%s: %s\n", __FUNCTION__, buf);
++}
++
++struct usb_function_driver blan_function_driver = {
++ name: "network-BLAN",
++ fops: &network_fd_function_ops,
++ device_description: &blan_device_description,
++ bNumConfigurations: sizeof (blan_description) / sizeof (struct usb_configuration_description),
++ configuration_description: blan_description,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_BCDDEVICE),
++};
++#endif /* CONFIG_USBD_NETWORK_BLAN */
++
+diff -Nru a/drivers/usbd/network_fd/cdc.c b/drivers/usbd/network_fd/cdc.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/network_fd/cdc.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,222 @@
++/*
++ * usbd/network_fd/cdc.c - Network Function Driver
++ *
++ * Copyright (c) 2002, 2003, 2004 Belcarra
++ *
++ * By:
++ * Chris Lynne <cl@belcarra.com>
++ * Stuart Lynne <sl@belcarra.com>
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ *
++ *
++ */
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++#include <usbd-export.h>
++#include <usbd-build.h>
++
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/utsname.h>
++#include <linux/netdevice.h>
++
++#include <usbd-chap9.h>
++#include <usbd-mem.h>
++#include <usbd.h>
++#include <usbd-func.h>
++
++#include "network.h"
++
++
++
++#ifdef CONFIG_USBD_NETWORK_CDC
++/* USB CDC Configuration ********************************************************************* */
++
++/* CDC Communication Interface Class descriptors
++ */
++static __u8 cdc_data_1[] = { 0x07, USB_DT_ENDPOINT, 0 | OUT, BULK, 0, 0x00, 0x00, };
++static __u8 cdc_data_2[] = { 0x07, USB_DT_ENDPOINT, 0 | IN, BULK, 0, 0x00, 0x00, };
++
++static __u8 cdc_comm_1[] = { 0x07, USB_DT_ENDPOINT, 0 | IN, INTERRUPT,0, 0x00, 0x0a, };
++
++static __u8 cdc_class_1[] = { 0x05, CS_INTERFACE, USB_ST_HEADER, 0x10, 0x01, /* CLASS_BDC_VERSION, CLASS_BDC_VERSION */ };
++static __u8 cdc_class_2[] = {
++ 0x0d, CS_INTERFACE, USB_ST_ENF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x05, /* 1514 maximum frame size */
++ 0x00, 0x00, 0x00 , };
++static __u8 cdc_class_3[] = { 0x05, CS_INTERFACE, USB_ST_UF, 0x00, 0x01, /* bMasterInterface, bSlaveInterface */};
++
++
++static __u8 *cdc_comm_class_descriptors[] = {
++ (struct usb_generic_class_descriptor *) &cdc_class_1,
++ (struct usb_generic_class_descriptor *) &cdc_class_2,
++ (struct usb_generic_class_descriptor *) &cdc_class_3, };
++
++static __u8 *cdc_data_endpoints[] = {
++ (struct usb_endpoint_descriptor *) &cdc_data_1,
++ (struct usb_endpoint_descriptor *) &cdc_data_2, };
++static __u8 *cdc_comm_endpoints[] = {
++ (struct usb_endpoint_descriptor *) &cdc_comm_1, };
++
++u8 cdc_comm_indexes[] = { INT_IN, };
++u8 cdc_data_indexes[] = { BULK_OUT, BULK_IN, };
++
++
++/* Data Interface Alternate descriptions and descriptors
++ */
++static __u8 cdc_comm_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, 0x00, 0x00, // bInterfaceNumber, bAlternateSetting
++ sizeof (cdc_comm_endpoints) / sizeof(struct usb_endpoint_descriptor), // bNumEndpoints
++ COMMUNICATIONS_INTERFACE_CLASS, COMMUNICATIONS_ENCM_SUBCLASS, COMMUNICATIONS_NO_PROTOCOL, 0x00,
++};
++static __u8 cdc_nodata_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, 0x01, 0x00, // bInterfaceNumber, bAlternateSetting
++ 0x00, // bNumEndpoints
++ DATA_INTERFACE_CLASS, COMMUNICATIONS_NO_SUBCLASS, COMMUNICATIONS_NO_PROTOCOL, 0x00,
++};
++static __u8 cdc_data_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, 0x01, 0x01, // bInterfaceNumber, bAlternateSetting
++ sizeof (cdc_data_endpoints) / sizeof(struct usb_endpoint_descriptor), // bNumEndpoints
++ DATA_INTERFACE_CLASS, COMMUNICATIONS_NO_SUBCLASS, COMMUNICATIONS_NO_PROTOCOL, 0x00,
++};
++
++static struct usb_alternate_description cdc_comm_alternate_descriptions[] = {
++ { iInterface: CONFIG_USBD_NETWORK_CDC_COMM_INTF,
++ interface_descriptor: (struct usb_interface_descriptor *)&cdc_comm_alternate_descriptor,
++ classes:sizeof (cdc_comm_class_descriptors) / sizeof (struct usb_generic_class_descriptor *),
++ class_list: cdc_comm_class_descriptors,
++ endpoints:sizeof (cdc_comm_endpoints) / sizeof(struct usb_endpoint_descriptor *),
++ endpoint_list: cdc_comm_endpoints,
++ endpoint_indexes: cdc_comm_indexes,
++ },
++};
++
++
++static struct usb_alternate_description cdc_data_alternate_descriptions[] = {
++ { iInterface: CONFIG_USBD_NETWORK_CDC_NODATA_INTF,
++ interface_descriptor: (struct usb_interface_descriptor *)&cdc_nodata_alternate_descriptor, },
++ { iInterface: CONFIG_USBD_NETWORK_CDC_DATA_INTF,
++ interface_descriptor: (struct usb_interface_descriptor *)&cdc_data_alternate_descriptor,
++ endpoints:sizeof (cdc_data_endpoints) / sizeof(struct usb_endpoint_descriptor *),
++ endpoint_list: cdc_data_endpoints,
++ endpoint_indexes: cdc_data_indexes,
++ },
++};
++
++/* Interface descriptions and descriptors
++ */
++struct usb_interface_description cdc_interfaces[] = {
++ { alternates:sizeof (cdc_comm_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list:cdc_comm_alternate_descriptions,},
++
++ { alternates:sizeof (cdc_data_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list:cdc_data_alternate_descriptions,},
++};
++
++/* Configuration descriptions and descriptors
++ */
++
++__u8 cdc_configuration_descriptor[sizeof(struct usb_configuration_descriptor)] = {
++ 0x09, USB_DT_CONFIG, 0x00, 0x00, // wLength
++ sizeof (cdc_interfaces) / sizeof (struct usb_interface_description),
++ 0x01, 0x00, // bConfigurationValue, iConfiguration
++ BMATTRIBUTE, BMAXPOWER,
++};
++
++struct usb_configuration_description cdc_description[] = {
++ { iConfiguration: CONFIG_USBD_NETWORK_CDC_DESC,
++ configuration_descriptor: (struct usb_configuration_descriptor *)cdc_configuration_descriptor,
++ bNumInterfaces:sizeof (cdc_interfaces) / sizeof (struct usb_interface_description),
++ interface_list:cdc_interfaces,},
++};
++
++
++
++/* Device Description
++ */
++
++static struct usb_device_descriptor cdc_device_descriptor = {
++ bLength: sizeof(struct usb_device_descriptor),
++ bDescriptorType: USB_DT_DEVICE,
++ bcdUSB: __constant_cpu_to_le16(USB_BCD_VERSION),
++ bDeviceClass: COMMUNICATIONS_DEVICE_CLASS,
++ bDeviceSubClass: 0x02,
++ bDeviceProtocol: 0x00,
++ bMaxPacketSize0: 0x00,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_BCDDEVICE),
++};
++
++static struct usb_endpoint_request cdc_endpoint_requests[ENDPOINTS+1] = {
++ { 1, 1, 1, USB_DIR_OUT | USB_ENDPOINT_BULK, MAXFRAMESIZE + 48, MAXFRAMESIZE + 512, },
++ { 1, 1, 1, USB_DIR_IN | USB_ENDPOINT_BULK, MAXFRAMESIZE + 48, MAXFRAMESIZE + 512, },
++ { 1, 0, 0, USB_DIR_IN | USB_ENDPOINT_INTERRUPT | USB_ENDPOINT_OPT, 16, 64, },
++ { 0, },
++};
++
++struct usb_device_description cdc_device_description = {
++ device_descriptor: &cdc_device_descriptor,
++ iManufacturer: CONFIG_USBD_NETWORK_MANUFACTURER,
++ iProduct: CONFIG_USBD_NETWORK_PRODUCT_NAME,
++#if !defined(CONFIG_USBD_NO_SERIAL_NUMBER) && defined(CONFIG_USBD_SERIAL_NUMBER_STR)
++ iSerialNumber:CONFIG_USBD_SERIAL_NUMBER_STR,
++#endif
++ endpointsRequested: ENDPOINTS,
++ requestedEndpoints: cdc_endpoint_requests,
++};
++
++
++
++void cdc_init (struct usb_function_instance *function)
++{
++ struct usb_class_ethernet_networking_descriptor *ethernet;
++
++ cdc_comm_alternate_descriptions[0].endpoints = Usb_network_private.have_interrupt ? 1 : 0;
++
++ // Update the iMACAddress field in the ethernet descriptor
++ {
++ char address_str[14];
++ snprintf(address_str, 13, "%02x%02x%02x%02x%02x%02x",
++ remote_dev_addr[0], remote_dev_addr[1], remote_dev_addr[2],
++ remote_dev_addr[3], remote_dev_addr[4], remote_dev_addr[5]);
++
++ if ((ethernet = (struct usb_class_ethernet_networking_descriptor *)cdc_class_2)) {
++ if (ethernet->iMACAddress) {
++ usbd_dealloc_string(ethernet->iMACAddress);
++ }
++ ethernet->iMACAddress = usbd_alloc_string(address_str);
++ }
++ }
++}
++
++
++struct usb_function_driver cdc_function_driver = {
++ name: "network-CDC",
++ fops: &network_fd_function_ops,
++ device_description: &cdc_device_description,
++ bNumConfigurations: sizeof (cdc_description) / sizeof (struct usb_configuration_description),
++ configuration_description: cdc_description,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_BCDDEVICE),
++};
++#endif /* CONFIG_USBD_NETWORK_CDC */
++
+diff -Nru a/drivers/usbd/network_fd/fermat.c b/drivers/usbd/network_fd/fermat.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/network_fd/fermat.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,132 @@
++/*
++ * usbd/network_fd/fermat.c - Network Function Driver
++ *
++ * Copyright (c) 2003, 2004 Belcarra
++ *
++ * By:
++ * Bruce Balden <balden@belcarra.com>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++
++#ifdef CONFIG_USBD_NETWORK_BLAN_FERMAT
++
++#include "fermat.h"
++
++#ifndef FERMAT_DEFINED
++typedef unsigned char BYTE;
++typedef struct fermat {
++ int length;
++ BYTE power[256];
++} FERMAT;
++#endif
++
++
++static int fermat_setup(FERMAT *p, int seed){
++ int i = 0;
++ unsigned long x,y;
++ y = 1;
++ do{
++ x = y;
++ p->power[i] = ( x == 256 ? 0 : x);
++ y = ( seed * x ) % 257;
++ i += 1;
++ }while( y != 1);
++ p->length = i;
++ return i;
++}
++
++static void fermat_xform(FERMAT *p, BYTE *data, int length){
++ BYTE *pw = p->power;
++ int i, j;
++ BYTE * q ;
++ for(i = 0, j=0, q = data; i < length; i++, j++, q++){
++ if(j>=p->length){
++ j = 0;
++ }
++ *q ^= pw[j];
++ }
++}
++
++static FERMAT default_fermat;
++static const int primitive_root = 5;
++void fermat_init(){
++ (void) fermat_setup(&default_fermat, primitive_root);
++}
++
++// Here are the public official versions.
++// Change the primitive_root above to another primitive root
++// if you need better scatter. Possible values are 3 and 7
++
++
++void fermat_encode(BYTE *data, int length){
++ fermat_xform(&default_fermat, data, length);
++}
++
++void fermat_decode(BYTE *data, int length){
++ fermat_xform(&default_fermat, data, length);
++}
++
++
++// Note: the seed must be a "primitive root" of 257. This means that
++// the return value of the setup routine must be 256 (otherwise the
++// seed is not a primitive root. The routine will still work fine
++// but will be less pseudo-random.
++
++#undef TEST
++#if TEST
++#include <stdio.h>
++#include <memory.h>
++
++// Use FERMAT in two ways: to encode, and to generate test data.
++
++main(){
++ //Note 3, 5, and 7 are primitive roots of 257
++ // 11 is not a primitive root
++ FERMAT three, five, seven;
++
++ FERMAT three2;
++ printf("Cycle lengths: 3,5,7 %d %d %d \n",
++ fermat_setup(&three, 3),
++ fermat_setup(&five, 5),
++ fermat_setup(&seven, 7));
++ three2=three; // Copy data from three
++ fermat_xform(&three,three2.power,three2.length);
++ fermat_xform(&five,three2.power,three2.length);
++ fermat_xform(&seven,three2.power,three2.length);
++ fermat_xform(&seven,three2.power,three2.length);
++ fermat_xform(&five,three2.power,three2.length);
++ fermat_xform(&three,three2.power,three2.length);
++
++ //At this stage, three2 and three should be identical
++ if(memcpy(&three,&three2,sizeof(FERMAT))){
++ printf("Decoded intact\n");
++ }
++
++ fermat_init();
++ fermat_encode(three2.power,256);
++
++}
++#endif
++
++#endif /* CONFIG_USBD_NETWORK_BLAN_FERMAT */
++
+diff -Nru a/drivers/usbd/network_fd/fermat.h b/drivers/usbd/network_fd/fermat.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/network_fd/fermat.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,39 @@
++/*
++ * usbd/network_fd/fermat.h - Network Function Driver
++ *
++ * Copyright (c) 2003, 2004 Belcarra
++ *
++ * By:
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ *
++ */
++
++#ifndef FERMAT_DEFINED
++#define FERMAT_DEFINED 1
++typedef unsigned char BYTE;
++typedef struct fermat {
++ int length;
++ BYTE power[256];
++} FERMAT;
++
++void fermat_init(void);
++void fermat_encode(BYTE *data, int length);
++void fermat_decode(BYTE *data, int length);
++#endif
++
++
+diff -Nru a/drivers/usbd/network_fd/network.c b/drivers/usbd/network_fd/network.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/network_fd/network.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,2112 @@
++/*
++ * usbd/network_fd/network.c - Network Function Driver
++ *
++ * Copyright (c) 2002, 2003, 2004 Belcarra
++ *
++ * By:
++ * Chris Lynne <cl@belcarra.com>
++ * Stuart Lynne <sl@belcarra.com>
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ *
++ * This network function driver intended to interoperate with
++ * Belcarra's USBLAN Class drivers.
++ *
++ * These are available for Windows, Linux and Mac OSX. For more
++ * information and to download a copy for testing:
++ *
++ * http://www.belcarra.com/usblan/
++ *
++ *
++ * Notes
++ *
++ * 1. If compiled into the kernel this driver can be used with NFSROOT to
++ * provide the ROOT filesystem. Please note that the kernel NFSROOT support
++ * (circa 2.4.20) can have problems if there are multiple interfaces. So
++ * it is best to ensure that there are no other network interfaces compiled
++ * in.
++ *
++ */
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++
++#include <usbd-export.h>
++#include <usbd-build.h>
++
++MODULE_AUTHOR ("sl@belcarra.com, balden@belcarra.com");
++
++
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
++MODULE_LICENSE("GPL");
++#endif
++
++MODULE_DESCRIPTION ("USB Network Function");
++
++
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/netdevice.h>
++#include <linux/skbuff.h>
++#include <linux/etherdevice.h>
++#include <net/arp.h>
++#include <linux/rtnetlink.h>
++#include <linux/smp_lock.h>
++#include <linux/ctype.h>
++#include <linux/time.h>
++#include <linux/timer.h>
++#include <linux/string.h>
++#include <linux/atmdev.h>
++#include <linux/pkt_sched.h>
++#include <linux/random.h>
++#include <linux/utsname.h>
++
++#include <linux/ip.h>
++#include <linux/if_ether.h>
++#include <linux/in.h>
++#include <linux/inetdevice.h>
++
++#include <linux/kmod.h>
++
++#include <asm/uaccess.h>
++#include <asm/system.h>
++
++#include <usbd-chap9.h>
++#include <usbd-mem.h>
++#include <usbd.h>
++#include <usbd-func.h>
++
++USBD_MODULE_INFO ("network_fd 2.0-beta");
++
++#include "network.h"
++#ifdef CONFIG_USBD_NETWORK_BLAN_FERMAT
++#include "fermat.h"
++#endif
++
++
++#if defined(CONFIG_USBD_NETWORK_CDC)
++
++static u32 cdc = 0;
++MODULE_PARM (cdc, "i");
++MODULE_PARM_DESC (cdc, "Enable CDC mode");
++void cdc_init(struct usb_function_instance *);
++
++extern struct usb_function_driver cdc_function_driver;
++
++#if defined(CONFIG_USBD_NETWORK_NETWORK_CDC_MYDHCPD)
++extern u_int8_t * checkfordhcp(struct net_device *net_device, u_int8_t *, int, int* );
++#endif
++
++#endif
++
++#ifdef CONFIG_USBD_NETWORK_BASIC
++static u32 basic = 0;
++MODULE_PARM (basic, "i");
++MODULE_PARM_DESC (basic, "Enable BASIC mode");
++void basic_init(struct usb_function_instance *);
++extern struct usb_function_driver basic_function_driver;
++#endif
++
++#ifdef CONFIG_USBD_NETWORK_BASIC2
++static u32 basic2 = 0;
++MODULE_PARM (basic, "i");
++MODULE_PARM_DESC (basic2, "Enable BASIC2 mode");
++void basic2_init(struct usb_function_instance *);
++extern struct usb_function_driver basic2_function_driver;
++#endif
++
++
++#ifdef CONFIG_USBD_NETWORK_SAFE
++static u32 safe = 0;
++MODULE_PARM (safe, "i");
++MODULE_PARM_DESC (safe, "Enable SAFE mode");
++void safe_init(struct usb_function_instance *);
++extern struct usb_function_driver safe_function_driver;
++#endif
++
++#ifdef CONFIG_USBD_NETWORK_BLAN
++static u32 blan = 0;
++MODULE_PARM (blan, "i");
++MODULE_PARM_DESC (blan, "Enable BLAN mode");
++void blan_init(struct usb_function_instance *);
++extern struct usb_function_driver blan_function_driver;
++#endif
++
++static struct usb_function_driver *function_driver = NULL;
++
++
++/* Module Parameters ************************************************************************* */
++
++wait_queue_head_t usb_netif_wq;
++#ifdef CONFIG_USBD_NET_NFS_SUPPORT
++int usb_is_configured;
++#endif
++
++#define CONFIG_USBD_NETWORK_ALLOW_SETID 1
++
++
++
++#ifdef CONFIG_USBD_NETWORK_ALLOW_SETID
++// override vendor ID
++static u32 vendor_id;
++MODULE_PARM (vendor_id, "i");
++MODULE_PARM_DESC (vendor_id, "vendor id");
++
++// override product ID
++static u32 product_id;
++MODULE_PARM (product_id, "i");
++MODULE_PARM_DESC (product_id, "product id");
++#endif
++
++// override local mac address
++#ifdef CONFIG_USBD_NETWORK_LOCAL_MACADDR
++static char *local_mac_address_str = CONFIG_USBD_NETWORK_LOCAL_MACADDR;
++#else
++static char *local_mac_address_str;
++#endif
++MODULE_PARM (local_mac_address_str, "s");
++MODULE_PARM_DESC (local_mac_address_str, "Local MAC");
++
++// override remote mac address
++#ifdef CONFIG_USBD_NETWORK_REMOTE_MACADDR
++static char *remote_mac_address_str = CONFIG_USBD_NETWORK_REMOTE_MACADDR;
++#else
++static char *remote_mac_address_str;
++#endif
++MODULE_PARM (remote_mac_address_str, "s");
++MODULE_PARM_DESC (remote_mac_address_str, "Remote MAC");
++
++
++#ifdef CONFIG_USBD_NETWORK_EP0TEST
++static u32 ep0test;
++MODULE_PARM (ep0test, "i");
++MODULE_PARM_DESC (ep0test, "Test EP0 String Handling - set to ep0 packetsize [8,16,32,64]");
++#endif
++
++
++static u32 zeroconf = 0;
++MODULE_PARM (zeroconf, "i");
++MODULE_PARM_DESC (zeroconf, "Use usbz%d for network name");
++
++#define NETWORK_CREATED 0x01
++#define NETWORK_REGISTERED 0x02
++#define NETWORK_DESTROYING 0x04
++#define NETWORK_ENABLED 0x08
++#define NETWORK_ATTACHED 0x10
++#define NETWORK_OPEN 0x20
++
++
++#define MCCI_ENABLE_CRC 0x03
++#define BELCARRA_GETMAC 0x04
++
++#define BELCARRA_SETTIME 0x04
++#define BELCARRA_SETIP 0x05
++#define BELCARRA_SETMSK 0x06
++#define BELCARRA_SETROUTER 0x07
++#define BELCARRA_SETDNS 0x08
++#define BELCARRA_PING 0x09
++#define BELCARRA_SETFERMAT 0x0a
++#define BELCARRA_HOSTNAME 0x0b
++
++
++#define RFC868_OFFSET_TO_EPOCH 0x83AA7E80 // RFC868 - seconds from midnight on 1 Jan 1900 GMT to Midnight 1 Jan 1970 GMT
++
++
++__u8 local_dev_addr[ETH_ALEN];
++
++__u8 remote_dev_addr[ETH_ALEN];
++static __u8 zeros[ETH_ALEN];
++
++static __u32 ip_addr;
++static __u32 router_ip;
++static __u32 network_mask;
++static __u32 dns_server_ip;
++
++/* Prevent overlapping of bus administrative functions:
++ *
++ * network_function_enable
++ * network_function_disable
++ * network_hard_start_xmit
++ */
++DECLARE_MUTEX(usbd_network_sem);
++
++
++struct net_device Network_net_device;
++struct usb_network_private Usb_network_private;
++
++static void network_send_int_blan(struct usb_function_instance *function, int connected );
++static void notification_schedule_bh (void);
++static int network_urb_sent_bulk (struct urb *urb, int urb_rc);
++static int network_urb_sent_int (struct urb *urb, int urb_rc);
++
++
++//_________________________________________________________________________________________________
++
++/*
++ * Synchronization
++ *
++ *
++ * Notification bottom half
++ *
++ * This is a scheduled task that will send an interrupt notification. Because it
++ * is called from the task scheduler context it needs to verify that the device is
++ * still usable.
++ *
++ * static int network_send_int_blan(struct usb_device_instance *, int )
++ * static void notification_bh (void *)
++ * void notification_schedule_bh (void)
++ *
++ *
++ * Netdevice functions
++ *
++ * These are called by the Linux network layer. They must be protected by irq locks
++ * if necessary to prevent interruption by IRQ level events.
++ *
++ * int network_init (struct net_device *net_device)
++ * void network_uninit (struct net_device *net_device)
++ * int network_open (struct net_device *net_device)
++ * int network_stop (struct net_device *net_device)
++ * struct net_device_stats *network_get_stats (struct net_device *net_device)
++ * int network_set_mac_addr (struct net_device *net_device, void *p)
++ * void network_tx_timeout (struct net_device *net_device)
++ * int network_set_config (struct net_device *net_device, struct ifmap *map)
++ * int network_stop (struct net_device *net_device)
++ * int network_hard_start_xmit (struct sk_buff *skb, struct net_device *net_device)
++ * int network_do_ioctl (struct net_device *net_device, struct ifreq *rp, int cmd)
++ *
++ *
++ * Data bottom half functions
++ *
++ * These are called from the bus bottom half handler.
++ *
++ * static int network_recv (struct usb_network_private *, struct net_device *, struct sk_buff *)
++ * int network_recv_urb (struct urb *)
++ * int network_urb_sent (struct urb *, int )
++ *
++ *
++ * Hotplug bottom half:
++ *
++ * This is a scheduled task that will send do a hotplug call. Because it is
++ * called from the task scheduler context it needs to verify that the
++ * device is still usable.
++ *
++ * static int hotplug_attach (__u32 ip, __u32 mask, __u32 router, int attach)
++ * static void hotplug_bh (void *data)
++ * void hotplug_schedule_bh (void)
++ *
++ *
++ * Irq level functions:
++ *
++ * These are called at interrupt time do process or respond to USB setup
++ * commands.
++ *
++ * int network_recv_setup_irq (struct usb_device_request *)
++ * void network_event_irq (struct usb_function_instance *function, usb_device_event_t event, int data)
++ *
++ *
++ * Enable and disable functions:
++ *
++ * void network_function_enable (struct usb_function_instance *, struct usb_function_instance *)
++ * void network_function_disable (struct usb_function_instance *function)
++ *
++ *
++ * Driver initialization and exit:
++ *
++ * static int network_create (void)
++ * static void network_destroy (void)
++ *
++ * int network_modinit (void)
++ * void network_modexit (void)
++ */
++
++//_________________________________________________________________________________________________
++
++/*
++ * If the following are defined we implement the crc32_copy routine using
++ * Duff's device. This will unroll the copy loop by either 4 or 8. Do not
++ * use these without profiling to test if it actually helps on any specific
++ * device.
++ */
++#undef CONFIG_USBD_NETWORK_CRC_DUFF4
++#undef CONFIG_USBD_NETWORK_CRC_DUFF8
++
++static __u32 *network_crc32_table;
++
++#define CRC32_INIT 0xffffffff // Initial FCS value
++#define CRC32_GOOD 0xdebb20e3 // Good final FCS value
++
++#define CRC32_POLY 0xedb88320 // Polynomial for table generation
++
++#define COMPUTE_FCS(val, c) (((val) >> 8) ^ network_crc32_table[((val) ^ (c)) & 0xff])
++
++//_________________________________________________________________________________________________
++// crc32_copy
++
++/**
++ * Generate the crc32 table
++ *
++ * return non-zero if malloc fails
++ */
++static int make_crc_table(void)
++{
++ u32 n;
++ RETURN_ZERO_IF(network_crc32_table);
++ RETURN_ENOMEM_IF(!(network_crc32_table = (u32 *)ckmalloc(256*4, GFP_KERNEL)));
++ for (n = 0; n < 256; n++) {
++ int k;
++ u32 c = n;
++ for (k = 0; k < 8; k++) {
++ c = (c & 1) ? (CRC32_POLY ^ (c >> 1)) : (c >> 1);
++ }
++ network_crc32_table[n] = c;
++ }
++ return 0;
++}
++
++#if !defined(CONFIG_USBD_NETWORK_CRC_DUFF4) && !defined(CONFIG_USBD_NETWORK_CRC_DUFF8)
++/**
++ * Copies a specified number of bytes, computing the 32-bit CRC FCS as it does so.
++ *
++ * dst Pointer to the destination memory area.
++ * src Pointer to the source memory area.
++ * len Number of bytes to copy.
++ * val Starting value for the CRC FCS.
++ *
++ * Returns Final value of the CRC FCS.
++ *
++ * @sa crc32_pad
++ */
++static __u32 __inline__ crc32_copy (__u8 *dst, __u8 *src, int len, __u32 val)
++{
++ for (; len-- > 0; val = COMPUTE_FCS (val, *dst++ = *src++));
++ return val;
++}
++
++#else /* DUFFn */
++
++/**
++ * Copies a specified number of bytes, computing the 32-bit CRC FCS as it does so.
++ *
++ * dst Pointer to the destination memory area.
++ * src Pointer to the source memory area.
++ * len Number of bytes to copy.
++ * val Starting value for the CRC FCS.
++ *
++ * Returns Final value of the CRC FCS.
++ *
++ * @sa crc32_pad
++ */
++static __u32 crc32_copy (__u8 *dst, __u8 *src, int len, __u32 val)
++{
++#if defined(CONFIG_USBD_NETWORK_CRC_DUFF8)
++ int n = (len + 7) / 8;
++ switch (len % 8)
++#elif defined(CONFIG_USBD_NETWORK_CRC_DUFF4)
++ int n = (len + 3) / 4;
++ switch (len % 4)
++#endif
++ {
++ case 0: do {
++ val = COMPUTE_FCS (val, *dst++ = *src++);
++#if defined(CONFIG_USBD_NETWORK_CRC_DUFF8)
++ case 7:
++ val = COMPUTE_FCS (val, *dst++ = *src++);
++ case 6:
++ val = COMPUTE_FCS (val, *dst++ = *src++);
++ case 5:
++ val = COMPUTE_FCS (val, *dst++ = *src++);
++ case 4:
++ val = COMPUTE_FCS (val, *dst++ = *src++);
++#endif
++ case 3:
++ val = COMPUTE_FCS (val, *dst++ = *src++);
++ case 2:
++ val = COMPUTE_FCS (val, *dst++ = *src++);
++ case 1:
++ val = COMPUTE_FCS (val, *dst++ = *src++);
++ } while (--n > 0);
++ }
++ return val;
++}
++#endif /* DUFFn */
++
++
++//_________________________________________________________________________________________________
++// crc32_pad
++
++/* crc32_pad - pad and calculate crc32
++ *
++ * Returns - CRC FCS
++ */
++static __u32 __inline__ crc32_pad (__u8 *dst, int len, __u32 val)
++{
++ for (; len-- > 0; val = COMPUTE_FCS (val, *dst++ = '\0'));
++ return val;
++}
++
++//_________________________________________________________________________________________________
++// network_send_int
++//
++
++/* network_send_int_blan - send an interrupt notification response
++ *
++ * Generates a response urb on the notification (INTERRUPT) endpoint.
++ * Return a non-zero result code to STALL the transaction.
++ *
++ * This is called from either a scheduled task or from the process context
++ * that calls network_open() or network_close().
++ *
++ */
++static void network_send_int_blan(struct usb_function_instance *function, int connected )
++{
++ struct urb *urb;
++ struct cdc_notification_descriptor *cdc;
++ int rc;
++ struct usb_network_private *network_private = &Usb_network_private;
++
++ //printk(KERN_INFO"%s: device: %p\n", __FUNCTION__, device);
++
++ /*
++ * This needs to lock out interrupts as network_event_irq can
++ * change the NETWORK_ATTACHED status
++ */
++ unsigned long flags;
++ local_irq_save(flags);
++ do {
++ BREAK_IF(!function);
++
++
++ BREAK_IF(network_private->network_type != network_blan);
++ BREAK_IF(!network_private->have_interrupt);
++
++ BREAK_IF(!(network_private->flags & NETWORK_ATTACHED));
++
++ //printk(KERN_INFO"%s: connected: %d network: %d %d\n", __FUNCTION__, connected,
++ // network_private->network_type, network_blan);
++
++ BREAK_IF(usbd_bus_status(function) != USBD_OK);
++
++ if (network_private->int_urb) {
++ printk(KERN_INFO"%s: int_urb: %p\n", __FUNCTION__, network_private->int_urb);
++ usbd_cancel_urb_irq(network_private->int_urb);
++ network_private->int_urb = NULL;
++ }
++
++ BREAK_IF(!(urb = usbd_alloc_urb (function, INT_IN,
++ sizeof(struct cdc_notification_descriptor), network_urb_sent_int)));
++
++ urb->actual_length = sizeof(struct cdc_notification_descriptor);
++ memset(urb->buffer, 0, sizeof(struct cdc_notification_descriptor));
++
++ cdc = (struct cdc_notification_descriptor *)urb->buffer;
++
++ cdc->bmRequestType = 0xa1;
++ cdc->bNotification = 0x00;
++ cdc->wValue = connected ? 0x01 : 0x00;
++ cdc->wIndex = 0x01; // XXX interface - check that this is correct
++
++
++ network_private->int_urb = urb;
++ //printk(KERN_INFO"%s: int_urb: %p\n", __FUNCTION__, urb);
++ BREAK_IF (!(rc = usbd_send_urb (urb)));
++
++ printk(KERN_ERR"%s: usbd_send_urb failed err: %x\n", __FUNCTION__, rc);
++ urb->privdata = NULL;
++ network_private->int_urb = NULL;
++ usbd_dealloc_urb (urb);
++
++ } while(0);
++ local_irq_restore(flags);
++}
++
++
++/* notification_bh - Bottom half handler to send a notification status
++ *
++ * Send a notification with open/close status
++ *
++ * It should not be possible for this to be called more than once at a time
++ * as it is only called via schedule_task() which protects against a second
++ * invocation.
++ */
++static void notification_bh (void *data)
++{
++ network_send_int_blan(Usb_network_private.function, Usb_network_private.flags & NETWORK_OPEN);
++ MOD_DEC_USE_COUNT;
++}
++
++/* notification_schedule_bh - schedule a call for notification_bh
++ */
++static void notification_schedule_bh (void)
++{
++ MOD_INC_USE_COUNT;
++ if (!schedule_task (&Usb_network_private.notification_bh))
++ MOD_DEC_USE_COUNT;
++}
++
++
++//______________________________________Network Layer Functions____________________________________
++
++/*
++ * In general because the functions are called from an independant layer it is necessary
++ * to verify that the device is still ok and to lock interrupts out to prevent in-advertant
++ * closures while in progress.
++ */
++
++/* network_init -
++ *
++ * Initializes the specified network device.
++ *
++ * Returns non-zero for failure.
++ */
++static int network_init (struct net_device *net_device)
++{
++ //printk(KERN_INFO"%s:\n", __FUNCTION__);
++ return 0;
++}
++
++
++/* network_uninit -
++ *
++ * Uninitializes the specified network device.
++ */
++static void network_uninit (struct net_device *net_device)
++{
++ //printk(KERN_INFO"%s:\n", __FUNCTION__);
++ return;
++}
++
++
++/* network_open -
++ *
++ * Opens the specified network device.
++ *
++ * Returns non-zero for failure.
++ */
++static int network_open (struct net_device *net_device)
++{
++ struct usb_network_private *network_private = &Usb_network_private;
++
++ // XXX should this be before or after the preceeding netif_running() test?
++ MOD_INC_USE_COUNT;
++ network_private->flags |= NETWORK_OPEN;
++ netif_wake_queue (net_device);
++ network_send_int_blan(network_private->function, 1);
++
++#ifdef CONFIG_USBD_NET_NFS_SUPPORT
++ if (!usb_is_configured) {
++ if (!in_interrupt()) {
++ printk(KERN_ERR"Please replug USB cable and then ifconfig host interface.\n");
++ interruptible_sleep_on(&usb_netif_wq);
++ }
++ else {
++ printk(KERN_ERR"Wanring! In interrupt\n");
++ }
++ }
++#endif
++ return 0;
++}
++
++
++/* network_stop -
++ *
++ * Stops the specified network device.
++ *
++ * Returns non-zero for failure.
++ */
++static int network_stop (struct net_device *net_device)
++{
++ struct usb_network_private *network_private = &Usb_network_private;
++
++ //printk(KERN_INFO"%s:\n", __FUNCTION__);
++
++ //netif_stop_queue (net_device);
++
++ network_private->flags &= ~NETWORK_OPEN;
++ network_send_int_blan(network_private->function, 0);
++
++ MOD_DEC_USE_COUNT;
++ return 0;
++}
++
++
++/* network_get_stats -
++ *
++ * Gets statistics from the specified network device.
++ *
++ * Returns pointer to net_device_stats structure with the required information.
++ */
++static struct net_device_stats *network_get_stats (struct net_device *net_device)
++{
++ struct usb_network_private *network_private = &Usb_network_private;
++ return &network_private->stats;
++}
++
++
++/* network_set_mac_addr
++ *
++ * Sets the MAC address of the specified network device. Fails if the device is in use.
++ *
++ * Returns non-zero for failure.
++ */
++static int network_set_mac_addr (struct net_device *net_device, void *p)
++{
++ struct sockaddr *addr = p;
++ unsigned long flags;
++
++ //printk(KERN_INFO"%s:\n", __FUNCTION__);
++
++ RETURN_EBUSY_IF(netif_running (net_device));
++ local_irq_save(flags);
++ memcpy (net_device->dev_addr, addr->sa_data, net_device->addr_len);
++ local_irq_restore(flags);
++ return 0;
++}
++
++
++/* network_tx_timeout -
++ *
++ * Tells the specified network device that its current transmit attempt has timed out.
++ */
++static void network_tx_timeout (struct net_device *net_device)
++{
++ struct usb_network_private *network_private = &Usb_network_private;
++#if 0
++ //printk(KERN_ERR"%s:\n", __FUNCTION__);
++ network_private->stats.tx_errors++;
++ network_private->stats.tx_dropped++;
++ usbd_cancel_urb_irq (network_private->bus, NULL);
++#endif
++#if 0
++ // XXX attempt to wakeup the host...
++ if ((network_private->network_type == network_blan) && (network_private->flags & NETWORK_OPEN)) {
++ notification_schedule_bh();
++ }
++#endif
++}
++
++
++/** network_set_config -
++ *
++ * Sets the specified network device's configuration. Fails if the device is in use.
++ *
++ * map An ifmap structure containing configuration values.
++ * Those values which are non-zero/non-null update the corresponding fields
++ * in net_device.
++ *
++ * Returns non-zero for failure.
++ */
++static int network_set_config (struct net_device *net_device, struct ifmap *map)
++{
++ RETURN_EBUSY_IF(netif_running (net_device));
++ if (map->base_addr)
++ net_device->base_addr = map->base_addr;
++ if (map->mem_start)
++ net_device->mem_start = map->mem_start;
++ if (map->irq)
++ net_device->irq = map->irq;
++ return 0;
++}
++
++
++/* network_change_mtu -
++ *
++ * Sets the specified network device's MTU. Fails if the new value is larger and
++ * the device is in use.
++ *
++ * Returns non-zero for failure.
++ */
++static int network_change_mtu (struct net_device *net_device, int mtu)
++{
++ struct usb_network_private *network_private = &Usb_network_private;
++
++ //printk(KERN_INFO"%s:\n", __FUNCTION__);
++
++ RETURN_EBUSY_IF(netif_running (net_device));
++ RETURN_EBUSY_IF(mtu > network_private->mtu);
++
++ net_device->mtu = mtu;
++ return 0;
++}
++
++//_________________________________________________________________________________________________
++// network_hard_start_xmit
++
++/* network_hard_start_xmit - start sending an skb
++ *
++ * Starts a network device's transmit function.
++ * Called by kernel network layer to transmit a frame on this device.
++ * Grab locks and pass to @c netproto_do_xmit().
++ * The network layer flow control is managed to prevent more than
++ * @c device->max_queue_entries from being outstanding.
++ *
++ * skb Pointer to the sk_buff structure to be sent.
++ * net_device Specifies the device by pointing to its net_device struct.
++ *
++ * Return non-zero (1) if busy.
++ */
++static int network_hard_start_xmit (struct sk_buff *skb, struct net_device *net_device)
++{
++ struct usb_network_private *network_private = &Usb_network_private;
++ struct usb_function_instance *function = network_private->function;
++ struct urb *urb = NULL;
++ int len = skb->len;
++ int rc = 1;
++ int in_pkt_sz;
++
++ down(&usbd_network_sem);
++ do {
++
++
++#if 0
++ printk(KERN_INFO"%s: %s len: %d encap: %d\n", __FUNCTION__, net_device->name, skb->len, network_private->encapsulation);
++ printk(KERN_INFO"start_xmit: len: %x head: %p data: %p tail: %p\n",
++ skb->len, skb->head, skb->data, skb->tail);
++ {
++ __u8 *cp = skb->data;
++ int i;
++ for (i = 0; i < skb->len; i++) {
++ if ((i%32) == 0) {
++ printk("\ntx[%2x] ", i);
++ }
++ printk("%02x ", *cp++);
++ }
++ printk("\n");
++ }
++#endif
++
++ THROW_IF(!(network_private->flags & NETWORK_ATTACHED), not_ok);
++ THROW_IF(!netif_carrier_ok (net_device), not_ok);
++ THROW_IF(usbd_bus_status(function) != USBD_OK, not_ok);
++
++#if defined(CONFIG_USBD_NETWORK_CDC)
++ // verify interface is enabled - non-zero altsetting means data is enabled
++ THROW_IF(!usbd_interface_AltSetting(function, DATA_INTF), not_ok);
++#endif
++ in_pkt_sz = usbd_endpoint_wMaxPacketSize(function, BULK_IN, usbd_high_speed(function));
++
++ // stop queue, it will be restart only when we are ready for another skb
++ netif_stop_queue (net_device);
++
++ // lock and update some stats
++ network_private->stopped++;
++ network_private->queued_entries++;
++ network_private->queued_bytes += skb->len;
++
++
++ // Set the timestamp for tx timeout
++ net_device->trans_start = jiffies;
++
++ switch (network_private->encapsulation) {
++ case simple_crc:
++ //printk(KERN_INFO"%s: BASIC_CRC\n", __FUNCTION__);
++ {
++ u32 crc;
++
++ // allocate urb 5 bytes larger than required
++ if (!(urb = usbd_alloc_urb (function, BULK_IN,
++ skb->len + 5 + in_pkt_sz, network_urb_sent_bulk )))
++ {
++ printk(KERN_ERR"%s: urb alloc failed len: %d endpoint: %02x\n",
++ __FUNCTION__, skb->len,
++ usbd_endpoint_bEndpointAddress(function, BULK_IN,
++ usbd_high_speed(function)));
++ return -ENOMEM;
++ }
++
++ // copy and crc skb->len bytes
++ crc = crc32_copy(urb->buffer, skb->data, skb->len, CRC32_INIT);
++ urb->actual_length = skb->len;
++
++ // add a pad byte if required to ensure a short packet, usbdnet driver
++ // will correctly handle pad byte before or after CRC, but the MCCI driver
++ // wants it before the CRC.
++ if ((urb->actual_length % in_pkt_sz) == (in_pkt_sz - 4)) {
++ crc = crc32_pad(urb->buffer + urb->actual_length, 1, crc);
++ urb->actual_length++;
++ }
++
++ // munge and append crc
++ crc = ~crc;
++ urb->buffer[urb->actual_length++] = crc & 0xff;
++ urb->buffer[urb->actual_length++] = (crc >> 8) & 0xff;
++ urb->buffer[urb->actual_length++] = (crc >> 16) & 0xff;
++ urb->buffer[urb->actual_length++] = (crc >> 24) & 0xff;
++
++ break;
++ }
++ default:
++ break;
++
++ }
++ if (!urb) {
++ printk(KERN_ERR"%s: unknown encapsulation\n", __FUNCTION__);
++ rc = -EINVAL;
++ break;
++ }
++
++ // save skb for netproto_done
++ urb->privdata = (void *) skb;
++#if 0
++ printk(KERN_INFO"start_xmit: len: %d : %d data: %p\n", skb->len, urb->actual_length, urb->buffer);
++ {
++ __u8 *cp = urb->buffer;
++ int i;
++ for (i = 0; i < urb->actual_length; i++) {
++ if ((i%32) == 0) {
++ printk("\ntx[%2x] ", i);
++ }
++ printk("%02x ", *cp++);
++ }
++ printk("\n");
++ }
++#endif
++#if defined(CONFIG_USBD_NETWORK_BLAN_FERMAT)
++ if (network_private->fermat) {
++ fermat_encode(urb->buffer, urb->actual_length);
++ }
++#endif
++
++ //printk(KERN_INFO"%s: urb: %p\n", __FUNCTION__, urb);
++ if ((rc = usbd_send_urb (urb))) {
++
++ printk(KERN_ERR"%s: FAILED: %d\n", __FUNCTION__, rc);
++ urb->privdata = NULL;
++ usbd_dealloc_urb (urb);
++
++ switch (rc) {
++
++ case -EINVAL:
++ case -EUNATCH:
++ printk(KERN_ERR"%s: not attached, send failed: %d\n", __FUNCTION__, rc);
++ network_private->stats.tx_errors++;
++ network_private->stats.tx_carrier_errors++;
++ netif_wake_queue (net_device);
++ break;
++
++ case -ENOMEM:
++ printk(KERN_ERR"%s: no mem, send failed: %d\n", __FUNCTION__, rc);
++ network_private->stats.tx_errors++;
++ network_private->stats.tx_fifo_errors++;
++ netif_wake_queue (net_device);
++ break;
++
++ case -ECOMM:
++ printk(KERN_ERR"%s: comm failure, send failed: %d %p\n", __FUNCTION__, rc, net_device);
++ network_private->stats.tx_dropped++;
++ break;
++
++ }
++ dev_kfree_skb_any (skb);
++ //rc = NET_XMIT_DROP; XXX this is what we should do, blows up on some 2.4.20 kernels
++ rc = 0;
++ break;
++ }
++
++ // XXX should we restart network queue
++ //printk(KERN_INFO"%s: OK: %d\n", __FUNCTION__, rc);
++ network_private->stats.tx_packets++;
++ network_private->stats.tx_bytes += len;
++
++ if ((network_private->queued_entries < network_private->max_queue_entries) &&
++ (network_private->queued_bytes < network_private->max_queue_bytes))
++ netif_wake_queue (net_device);
++
++ CATCH(not_ok) {
++ dev_kfree_skb_any (skb);
++ network_private->stats.tx_dropped++;
++ //netif_stop_queue(net_device); // XXX
++ //rc = NET_XMIT_DROP; XXX this is what we should do, blows up on some 2.4.20 kernels
++ rc = 0;
++ break;
++ }
++
++ } while (0);
++ up(&usbd_network_sem);
++ return rc;
++}
++
++
++/* network_do_ioctl - perform an ioctl call
++ *
++ * Carries out IOCTL commands for the specified network device.
++ *
++ * rp Points to an ifreq structure containing the IOCTL parameter(s).
++ * cmd The IOCTL command.
++ *
++ * Returns non-zero for failure.
++ */
++static int network_do_ioctl (struct net_device *net_device, struct ifreq *rp, int cmd)
++{
++ return -ENOIOCTLCMD;
++}
++
++//_________________________________________________________________________________________________
++
++struct net_device Network_net_device = {
++ get_stats: network_get_stats,
++ tx_timeout: network_tx_timeout,
++ do_ioctl: network_do_ioctl,
++ set_config: network_set_config,
++ set_mac_address: network_set_mac_addr,
++ hard_start_xmit: network_hard_start_xmit,
++ change_mtu: network_change_mtu,
++ init: network_init,
++ uninit: network_uninit,
++ open: network_open,
++ stop: network_stop,
++ priv: &Usb_network_private,
++};
++
++//_________________________________________________________________________________________________
++
++
++/* network_recv - function to process an received data URB
++ *
++ * Passes received data to the network layer. Passes skb to network layer.
++ *
++ * Returns non-zero for failure.
++ */
++static __inline__ int network_recv (struct usb_network_private *network_private,
++ struct net_device *net_device, struct sk_buff *skb)
++{
++ int rc;
++#if 0
++ printk(KERN_INFO"%s: len: %x head: %p data: %p tail: %p\n", __FUNCTION__,
++ skb->len, skb->head, skb->data, skb->tail);
++ {
++ __u8 *cp = skb->data;
++ int i;
++ for (i = 0; i < skb->len; i++) {
++ if ((i%32) == 0) {
++ printk("\nrx[%2x] ", i);
++ }
++ printk("%02x ", *cp++);
++ }
++ printk("\n");
++ }
++#endif
++
++ // refuse if no device present
++ if (!netif_device_present (net_device)) {
++ printk(KERN_INFO"%s: device not present\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ // refuse if no carrier
++ if (!netif_carrier_ok (net_device)) {
++ printk(KERN_INFO"%s: no carrier\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++ // refuse if the net device is down
++ if (!(net_device->flags & IFF_UP)) {
++ //printk(KERN_INFO"%s: not up net_dev->flags: %x\n", __FUNCTION__, net_device->flags);
++ network_private->stats.rx_dropped++;
++ return -EINVAL;
++ }
++
++ skb->dev = net_device;
++ skb->pkt_type = PACKET_HOST;
++ skb->protocol = eth_type_trans (skb, net_device);
++ skb->ip_summed = CHECKSUM_UNNECESSARY;
++
++ //printk(KERN_INFO"%s: len: %x head: %p data: %p tail: %p\n", __FUNCTION__,
++ // skb->len, skb->head, skb->data, skb->tail);
++
++
++ // pass it up to kernel networking layer
++ if ((rc = netif_rx (skb))) {
++ //printk(KERN_INFO"%s: netif_rx rc: %d\n", __FUNCTION__, rc);
++ }
++ network_private->stats.rx_bytes += skb->len;
++ network_private->stats.rx_packets++;
++
++ return 0;
++}
++
++//_________________________________________________________________________________________________
++
++/* network_recv_urb - callback to process a received URB
++ *
++ * Returns non-zero for failure.
++ */
++static int network_recv_urb (struct urb *urb, int rc)
++{
++ struct net_device *net_device;
++ struct usb_network_private *network_private = &Usb_network_private;
++ struct usb_function_instance *function = network_private->function;
++
++ struct sk_buff *skb = NULL;
++ int out_pkt_sz;
++
++ RETURN_EINVAL_IF(!(network_private->flags & NETWORK_ATTACHED));
++ RETURN_EINVAL_IF(!(net_device = &Network_net_device));
++
++ out_pkt_sz = usbd_endpoint_wMaxPacketSize(function, BULK_OUT, usbd_high_speed(function));
++
++#if 0
++ printk(KERN_INFO"%s: urb: %p len: %d maxtransfer: %d encap: %d\n", __FUNCTION__,
++ urb, urb->actual_length, network_private->maxtransfer, network_private->encapsulation);
++
++ {
++ __u8 *cp = urb->buffer;
++ int i;
++ for (i = 0; i < urb->actual_length; i++) {
++ if ((i%32) == 0) {
++ printk("\n[%2x] ", i);
++ }
++ printk("%02x ", *cp++);
++ }
++ printk("\n");
++ }
++#endif
++
++ THROW_IF(urb->status != RECV_OK, error);
++
++ // Is CDC active (we have received CONTROL WRITE setup packets indicating real CDC host)
++ switch (network_private->encapsulation) {
++ int len;
++ case simple_crc:
++
++ len = urb->actual_length;
++
++ // allocate skb of appropriate length, reserve 2 to align ip
++ THROW_IF(!(skb = dev_alloc_skb (len + 2)), error);
++ skb_reserve(skb, 2);
++
++#if defined(CONFIG_USBD_NETWORK_BLAN_PADAFTER)
++ {
++ /* This version simply checks for a correct CRC along the
++ * entire packet. Some UDC's have trouble with some packet
++ * sizes, this allows us to add pad bytes after the CRC.
++ */
++
++ u8 *dst = skb_put(skb, len - 1);
++ u8 *src = urb->buffer;
++ int copied;
++ u32 crc;
++
++ // XXX this should work, but the MIPS optimizer seems to get it wrong....
++ //copied = (len < out_pkt_sz) ? 0 : ((len / out_pkt_sz) - 1) * out_pkt_sz;
++
++ if (len < out_pkt_sz*2)
++ copied = 0;
++ else {
++ int pkts = ((len - out_pkt_sz) / out_pkt_sz);
++ copied = (pkts - 1) * out_pkt_sz;
++ }
++
++ len -= copied;
++ crc = CRC32_INIT;
++ for (; copied-- > 0 ; crc = COMPUTE_FCS (crc, *dst++ = *src++));
++
++ for (; (len-- > 0) && (CRC32_GOOD != crc); crc = COMPUTE_FCS (crc, *dst++ = *src++));
++
++ skb_trim(skb, skb->len - len - 4);
++
++ if (CRC32_GOOD != crc) {
++ //printk(KERN_INFO"%s: AAA frame: %03x\n", __FUNCTION__, urb->framenum);
++ THROW_IF(network_private->crc, crc_error);
++ }
++ else
++ network_private->crc = 1;
++ }
++#else
++ /*
++ * The CRC can be sent in two ways when the size of the transfer
++ * ends up being a multiple of the packetsize:
++ *
++ * |
++ * <data> <CRC><CRC><CRC><CRC>|<???> case 1
++ * <data> <NUL><CRC><CRC><CRC>|<CRC> case 2
++ * <data> <NUL><CRC><CRC><CRC><CRC>| case 3
++ * <data> <NUL><CRC><CRC><CRC>|<CRC> | case 4
++ * |
++ *
++ * This complicates CRC checking, there are four scenarios:
++ *
++ * 1. length is 1 more than multiple of packetsize with a trailing byte
++ * 2. length is 1 more than multiple of packetsize
++ * 3. length is multiple of packetsize
++ * 4. none of the above
++ *
++ * Finally, even though we always compute CRC, we do not actually throw
++ * things away until and unless we have previously seen a good CRC.
++ * This allows backwards compatibility with hosts that do not support
++ * adding a CRC to the frame.
++ *
++ */
++
++ // test if 1 more than packetsize multiple
++ if (1 == (len % out_pkt_sz)) {
++
++ // copy and CRC up to the packetsize boundary
++ u32 crc = crc32_copy(skb_put(skb, len - 1), urb->buffer, len - 1, CRC32_INIT);
++
++ // if the CRC is good then this is case 1
++ if (CRC32_GOOD != crc) {
++
++ crc = crc32_copy(skb_put(skb, 1), urb->buffer + len - 1, 1, crc);
++
++ if (CRC32_GOOD != crc) {
++ //crc_errors[len%64]++;
++ printk(KERN_INFO"%s: A CRC error %08x %03x\n", __FUNCTION__, crc, urb->framenum);
++ THROW_IF(network_private->crc, crc_error);
++ }
++ else
++ network_private->crc = 1;
++ }
++ else
++ network_private->crc = 1;
++ }
++ else {
++ u32 crc = crc32_copy(skb_put(skb, len), urb->buffer, len, CRC32_INIT);
++
++ if (CRC32_GOOD != crc) {
++ //crc_errors[len%64]++;
++ //printk(KERN_INFO"%s: CCC\n", __FUNCTION__);
++ THROW_IF(network_private->crc, crc_error);
++ }
++ else
++ network_private->crc = 1;
++ }
++ // trim IFF we are paying attention to crc
++ if (network_private->crc)
++ skb_trim(skb, skb->len - 4);
++#endif
++
++ // pass it up, free skb if non zero
++ THROW_IF(network_recv (network_private, net_device, skb), skb_error);
++
++ break;
++ default:
++ break;
++ }
++
++ // catch a simple error, just increment missed error and general error
++ CATCH(error) {
++
++ network_private->stats.rx_frame_errors++;
++ network_private->stats.rx_errors++;
++
++ // catch error where skb may need to be released
++ CATCH(skb_error) {
++
++ // catch a CRC error
++
++ // XXX We need to track whether we have seen a correct CRC, until then
++ // we ignore CRC errors.
++
++ CATCH(crc_error) {
++#if 0
++ printk(KERN_INFO"%s: urb: %p status: %d len: %d maxtransfer: %d encap: %d\n", __FUNCTION__,
++ urb, urb->status, urb->actual_length, network_private->maxtransfer,
++ network_private->encapsulation);
++
++ {
++ __u8 *cp = urb->buffer;
++ int i;
++ for (i = 0; i < urb->actual_length; i++) {
++ if ((i%32) == 0) {
++ printk("\n[%2x] ", i);
++ }
++ printk("%02x ", *cp++);
++ }
++ printk("\n");
++ }
++#endif
++ network_private->stats.rx_crc_errors++;
++ network_private->stats.rx_errors++;
++ }
++
++ // catch an overrun error
++ // (Only used if CONFIG_USBD_NETWORK_CDC is defined.)
++ //CATCH(fifo_error) {
++ // network_private->stats.rx_fifo_errors++;
++ // network_private->stats.rx_errors++;
++ //}
++
++ // if skb defined free it
++ if (skb)
++ dev_kfree_skb_any (skb);
++ }
++ network_private->stats.rx_dropped++;
++ //return -EINVAL;
++ }
++ //printk(KERN_INFO"%s: restart: %p\n", __FUNCTION__, urb);
++ return (usbd_start_recv (urb));
++}
++
++//_________________________________________________________________________________________________
++// network_urb_sent
++
++/* network_urb_sent_bulk - callback function to process a sent URB
++ *
++ * Handles notification that an urb has been sent (successfully or otherwise).
++ *
++ * urb Pointer to the urb that has been sent.
++ * rc Result code from the send operation.
++ *
++ * Returns non-zero for failure.
++ */
++static int network_urb_sent_bulk (struct urb *urb, int urb_rc)
++{
++ struct sk_buff *skb;
++ struct net_device *net_device;
++ unsigned long flags;
++ struct usb_network_private *network_private = &Usb_network_private;
++ struct usb_function_instance *function = network_private->function;
++ int rc = -EINVAL;
++
++ //printk(KERN_INFO"%s: urb: %p device: %p address: %x urb_rc: %d\n", __FUNCTION__,
++ // urb, urb->device, urb->endpoint->bEndpointAddress, urb_rc);
++
++ local_irq_save(flags);
++ do {
++
++ BREAK_IF(!urb);
++ BREAK_IF(!(function = urb->function_instance));
++
++ switch (urb_rc) {
++ case SEND_FINISHED_ERROR:
++ network_private->stats.tx_errors++;
++ network_private->stats.tx_dropped++;
++ break;
++ case SEND_FINISHED_CANCELLED:
++ network_private->stats.tx_errors++;
++ network_private->stats.tx_carrier_errors++;
++ break;
++ default:
++ break;
++ }
++
++ // XXX should we zap skb first if error?
++ RETURN_EINVAL_IF(!(network_private->flags & NETWORK_CREATED));
++
++ // retrieve skb pointer and unlink from urb pointers
++ skb = (struct sk_buff *) urb->privdata;
++
++ urb->privdata = NULL;
++ usbd_dealloc_urb (urb);
++
++ // tell netproto we are done with the skb, it will test for NULL
++ // netproto_done (interface, skb, urb_rc != SEND_FINISHED_OK);
++
++ BREAK_IF(!skb);
++ BREAK_IF(!(net_device = &Network_net_device));
++
++
++ network_private->avg_queue_entries += network_private->queued_entries;
++ network_private->queued_entries--;
++ network_private->samples++;
++ network_private->jiffies += jiffies - *(time_t *) (&skb->cb);
++ network_private->queued_bytes -= skb->len;
++
++ dev_kfree_skb_any (skb);
++
++ if (netif_queue_stopped (net_device)) {
++ netif_wake_queue (net_device);
++ network_private->restarts++;
++ }
++ rc = 0;
++
++ } while (0);
++ local_irq_restore(flags);
++ return rc;
++}
++
++/* network_urb_sent_int - callback for sent URB
++ *
++ * Handles notification that an urb has been sent (successfully or otherwise).
++ *
++ * Returns non-zero for failure.
++ */
++static int network_urb_sent_int (struct urb *urb, int urb_rc)
++{
++ struct usb_function_instance *function;
++ struct sk_buff *skb;
++ struct net_device *net_device;
++ unsigned long flags;
++ int rc = -EINVAL;
++ struct usb_network_private *network_private = &Usb_network_private;
++
++ //printk(KERN_INFO"%s: urb: %p device: %p address: %x urb_rc: %d\n", __FUNCTION__,
++ // urb, urb->device, urb->endpoint->bEndpointAddress, urb_rc);
++
++ local_irq_save(flags);
++ do {
++
++ BREAK_IF(!urb);
++ BREAK_IF(!(function = urb->function_instance));
++ //RETURN_EINVAL_IF(!(network_private->flags & NETWORK_ATTACHED));
++
++ //printk(KERN_INFO"%s: reseting int_urb: %p\n", __FUNCTION__, network_private->int_urb);
++ usbd_dealloc_urb (urb);
++ network_private->int_urb = NULL;
++ rc = 0;
++
++ } while (0);
++ local_irq_restore(flags);
++ return rc;
++}
++
++
++//_________________________________________________________________________________________________
++// network_recv_setup_irq
++//
++/* network_urb_received_ep0 - callback for sent URB
++ *
++ * Handles notification that an urb has been sent (successfully or otherwise).
++ *
++ * Returns non-zero for failure.
++ */
++static int network_urb_received_ep0 (struct urb *urb, int urb_rc)
++{
++ printk(KERN_INFO"%s: urb: %p status: %d\n", __FUNCTION__, urb, urb->status);
++
++ RETURN_EINVAL_IF (RECV_OK != urb->status);
++
++ printk(KERN_INFO"%s: %s\n", __FUNCTION__, urb->buffer);
++
++ return -EINVAL; // caller will de-allocate
++}
++
++/* network_recv_setup_irq - process a received SETUP URB
++ *
++ * Processes a received setup packet and CONTROL WRITE data.
++ * Results for a CONTROL READ are placed in urb->buffer.
++ *
++ * Returns non-zero for failure.
++ */
++static int network_recv_setup_irq (struct usb_device_request *request)
++{
++ struct usb_network_private *network_private = &Usb_network_private;
++ struct usb_function_instance *function = network_private->function;
++ struct urb *urb;
++
++
++ // Verify that this is a USB Class request per CDC specification or a vendor request.
++ RETURN_ZERO_IF (!(request->bmRequestType & (USB_REQ_TYPE_CLASS | USB_REQ_TYPE_VENDOR)));
++
++ // Determine the request direction and process accordingly
++ switch (request->bmRequestType & (USB_REQ_DIRECTION_MASK | USB_REQ_TYPE_MASK)) {
++
++ case USB_REQ_HOST2DEVICE | USB_REQ_TYPE_VENDOR:
++
++ switch (request->bRequest) {
++ case MCCI_ENABLE_CRC:
++ if (make_crc_table())
++ return -EINVAL;
++ network_private->encapsulation = simple_crc;
++ return 0;
++
++ case BELCARRA_PING:
++ //printk(KERN_INFO"%s: H2D VENDOR IP: %08x\n", __FUNCTION__, ip_addr);
++ if ((network_private->network_type == network_blan))
++ notification_schedule_bh();
++ break;
++
++#if !defined(CONFIG_USBD_NETWORK_BLAN_DO_NOT_SETTIME) || !defined(CONFIG_USBD_NETWORK_SAFE_DO_NOT_SETTIME)
++ case BELCARRA_SETTIME:
++ {
++ struct timeval tv;
++
++ // wIndex and wLength contain RFC868 time - seconds since midnight 1 jan 1900
++
++ tv.tv_sec = ntohl( request->wValue << 16 | request->wIndex);
++ tv.tv_usec = 0;
++
++ // convert to Unix time - seconds since midnight 1 jan 1970
++
++ tv.tv_sec -= RFC868_OFFSET_TO_EPOCH;
++
++ //printk(KERN_INFO"%s: H2D VENDOR TIME: %08x\n", __FUNCTION__, tv.tv_sec);
++
++ // set the time
++ do_settimeofday(&tv);
++ } break;
++#endif
++ case BELCARRA_SETIP:
++ ip_addr = ntohl( request->wValue << 16 | request->wIndex);
++ break;
++
++ case BELCARRA_SETMSK:
++ network_mask = ntohl( request->wValue << 16 | request->wIndex);
++ break;
++
++ case BELCARRA_SETROUTER:
++ router_ip = ntohl( request->wValue << 16 | request->wIndex);
++ break;
++
++ case BELCARRA_SETDNS:
++ dns_server_ip = ntohl( request->wValue << 16 | request->wIndex);
++ break;
++#ifdef CONFIG_USBD_NETWORK_BLAN_FERMAT
++ case BELCARRA_SETFERMAT:
++ network_private->fermat = 1;
++ break;
++#endif
++#ifdef CONFIG_USBD_NETWORK_BLAN_HOSTNAME
++ case BELCARRA_HOSTNAME:
++ //printk(KERN_INFO"%s: HOSTNAME\n", __FUNCTION__);
++ RETURN_EINVAL_IF(!(urb = usbd_alloc_urb_ep0(function, le16_to_cpu(request->wLength),
++ network_urb_received_ep0) ));
++ RETURN_ZERO_IF(!usbd_start_recv(urb)); // return if no error
++ usbd_dealloc_urb(urb); // de-alloc if error
++ return -EINVAL;
++#endif
++ }
++ return 0;
++#if 0
++ case USB_REQ_DEVICE2HOST | USB_REQ_TYPE_VENDOR:
++ urb->actual_length = 0;
++ switch (request->bRequest) {
++ case BELCARRA_GETMAC:
++ {
++ // copy and free the original buffer
++ memcpy(urb->buffer, Network_net_device.dev_addr, ETH_ALEN);
++ urb->actual_length = ETH_ALEN;
++ return 0;
++ }
++ }
++#endif
++ return 0;
++ default:
++ break;
++ }
++ return -EINVAL;
++}
++
++//______________________________________ Hotplug Functions ________________________________________
++
++#ifdef CONFIG_HOTPLUG
++
++#define AGENT "network_fd"
++
++/* hotplug_attach - call hotplug
++ */
++static int hotplug_attach (__u32 ip, __u32 mask, __u32 router, int attach)
++{
++ static int count = 0;
++ char *argv[3];
++ char *envp[10];
++ char ifname[20+12 + IFNAMSIZ];
++ int i;
++ char count_str[20];
++
++ RETURN_EINVAL_IF(!hotplug_path[0]);
++
++ argv[0] = hotplug_path;
++ argv[1] = AGENT;
++ argv[2] = 0;
++
++ sprintf (ifname, "INTERFACE=%s", Network_net_device.name);
++ sprintf (count_str, "COUNT=%d", count++);
++
++ i = 0;
++ envp[i++] = "HOME=/";
++ envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
++ envp[i++] = ifname;
++
++
++ if (attach) {
++ unsigned char *cp;
++ char ip_str[20+32];
++ char mask_str[20+32];
++ char router_str[20+32];
++ __u32 nh;
++
++ nh = htonl(ip);
++ cp = (unsigned char*) &nh;
++ sprintf (ip_str, "IP=%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
++
++ nh = htonl(mask);
++ cp = (unsigned char*) &nh;
++ sprintf (mask_str, "MASK=%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
++
++ nh = htonl(router);
++ cp = (unsigned char*) &nh;
++ sprintf (router_str, "ROUTER=%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]);
++
++ //printk (KERN_INFO "%s: attach %s %s %s\n", __FUNCTION__, ifname, ip_str, count_str);
++
++ envp[i++] = "ACTION=attach";
++ envp[i++] = ip_str;
++ envp[i++] = mask_str;
++ envp[i++] = router_str;
++ }
++ else {
++ //printk (KERN_INFO "%s: detach %s %s\n", __FUNCTION__, ifname, count_str);
++ envp[i++] = "ACTION=detach";
++ }
++
++ envp[i++] = count_str;
++ envp[i++] = 0;
++
++ return call_usermodehelper (argv[0], argv, envp);
++}
++
++
++/* hotplug_bh - bottom half handler to call hotplug script to signal ATTACH or DETACH
++ *
++ * Check connected status and load/unload as appropriate.
++ *
++ * It should not be possible for this to be called more than once at a time
++ * as it is only called via schedule_task() which protects against a second
++ * invocation.
++ */
++static void hotplug_bh (void *data)
++{
++ struct usb_network_private *network_private = &Usb_network_private;
++ struct usb_function_instance *function = network_private->function;
++
++ //printk(KERN_INFO"%s: BUS state: %d status: %d\n", __FUNCTION__, usbd_device_state(function), usbd_bus_status(function));
++
++ if (function && (USBD_OK == usbd_bus_status(function)) && (STATE_CONFIGURED == usbd_device_state(function))) {
++ if (hotplug_attached != network_private->hotplug_status) {
++ //printk(KERN_INFO"%s: ATTACH\n", __FUNCTION__);
++ network_private->hotplug_status = hotplug_attached;
++ hotplug_attach (ip_addr, network_mask, router_ip, 1);
++ }
++ }
++ else {
++ if (hotplug_detached != network_private->hotplug_status) {
++ //printk(KERN_INFO"%s: DETACH\n", __FUNCTION__);
++ network_private->hotplug_status = hotplug_detached;
++ hotplug_attach (ip_addr, network_mask, router_ip, 0);
++ }
++ }
++ MOD_DEC_USE_COUNT;
++}
++
++/* hotplug_schedule_bh - schedule a call to hotplug bottom half
++ */
++static void hotplug_schedule_bh (void)
++{
++ MOD_INC_USE_COUNT;
++ if (!schedule_task (&Usb_network_private.hotplug_bh))
++ MOD_DEC_USE_COUNT;
++}
++#endif /* CONFIG_HOTPLUG */
++
++
++//_________________________________________________________________________________________________
++
++#ifdef CONFIG_USBD_NETWORK_START_SINGLE
++#define NETWORK_START_URBS 1
++#else
++#define NETWORK_START_URBS 2
++#endif
++
++/* network_start_recv - start recv urb(s)
++ */
++void network_start_recv(struct usb_function_instance *function)
++{
++ int i;
++ for (i = 0; i < NETWORK_START_URBS; i++) {
++ struct urb *urb;
++ BREAK_IF(!(urb = usbd_alloc_urb (function, BULK_OUT,
++ usbd_endpoint_transferSize(function, BULK_OUT, usbd_high_speed(function)),
++ network_recv_urb)));
++ //printk(KERN_INFO"%s: i: %d start: %p\n", __FUNCTION__, i, urb);
++ if (usbd_start_recv(urb))
++ usbd_dealloc_urb(urb);
++ }
++}
++
++/* network_event_irg - Processes a USB event.
++ */
++static void network_event_irq (struct usb_function_instance *function, usb_device_event_t event, int data)
++{
++ struct usb_network_private *network_private = &Usb_network_private;
++
++ switch (event) {
++
++ case DEVICE_RESET:
++ case DEVICE_DESTROY:
++ case DEVICE_BUS_INACTIVE:
++ //printk(KERN_INFO"%s: RST %x\n", __FUNCTION__, ip_addr);
++ {
++ //printk(KERN_INFO"%s:\n", __FUNCTION__);
++ // Return if argument is null.
++
++ // XXX flush
++
++ network_private->flags &= ~NETWORK_ATTACHED;
++ network_private->int_urb = NULL;
++
++ // Disable our net-device.
++ // Apparently it doesn't matter if we should do this more than once.
++
++ netif_stop_queue(&Network_net_device);
++ netif_carrier_off(&Network_net_device);
++
++ // If we aren't already tearing things down, do it now.
++ if (!(network_private->flags & NETWORK_DESTROYING)) {
++ network_private->flags |= NETWORK_DESTROYING;
++ //network_private->device = NULL;
++ }
++ }
++ break;
++
++ case DEVICE_CONFIGURED:
++ case DEVICE_BUS_ACTIVITY:
++ //printk(KERN_INFO"%s: CFG %x\n", __FUNCTION__, ip_addr);
++ network_private->flags |= NETWORK_ATTACHED;
++
++ if ((network_private->network_type == network_blan) && (network_private->flags & NETWORK_OPEN))
++ notification_schedule_bh();
++
++ netif_carrier_on (&Network_net_device);
++ netif_wake_queue (&Network_net_device);
++
++ network_start_recv(function);
++
++#ifdef CONFIG_USBD_NET_NFS_SUPPORT
++ if (!usb_is_configured) {
++ wake_up(&usb_netif_wq);
++ usb_is_configured = 1;
++ }
++#endif
++ break;
++
++ case DEVICE_SET_INTERFACE:
++ // XXX if CDC then we can check device->alternates[1] and see if we should
++ // enable/disable data flow.
++ // XXX verify ep0.c SET_CONFIGURATION and SET_INTERFACE implmentation are
++ // complete before using this
++ break;
++
++ default:
++ return;
++ }
++#ifdef CONFIG_HOTPLUG
++ hotplug_schedule_bh();
++#endif
++}
++
++//_________________________________________________________________________________________________
++
++/* network_function_enable - enable the function driver
++ *
++ * Called for usbd_function_enable() from usbd_register_device()
++ */
++
++static int network_function_enable (struct usb_function_instance *function)
++{
++ //printk(KERN_INFO"%s: DOWN\n", __FUNCTION__);
++ down(&usbd_network_sem);
++ MOD_INC_USE_COUNT; // QQQ Should this be _before_ the down()?
++
++ // set the network device address from the local device address
++ memcpy(Network_net_device.dev_addr, local_dev_addr, ETH_ALEN);
++
++ //Usb_network_private.bus = function->bus;
++ Usb_network_private.function = function;
++ Usb_network_private.have_interrupt = usbd_endpoint_bEndpointAddress(function, INT_IN, usbd_high_speed(function)) ? 1 : 0;
++
++ Usb_network_private.flags |= NETWORK_ENABLED;
++
++#if defined(CONFIG_USBD_NETWORK_CDC)
++ cdc_init(function);
++#endif /* CONFIG_USBD_NETWORK_CDC */
++
++#ifdef CONFIG_USBD_NETWORK_BASIC
++ basic_init(function);
++#endif
++
++#ifdef CONFIG_USBD_NETWORK_BASIC2
++ basic2_init(function);
++#endif
++
++#ifdef CONFIG_USBD_NETWORK_SAFE
++ safe_init(function);
++#endif
++#ifdef CONFIG_USBD_NETWORK_BLAN
++ blan_init(function);
++#endif
++ up(&usbd_network_sem);
++ //printk(KERN_INFO"%s: UP\n", __FUNCTION__);
++ return 0;
++}
++
++/* network_functino_disable - disable the function driver
++ *
++ */
++static void network_function_disable (struct usb_function_instance *function)
++{
++ //printk(KERN_INFO"%s: DOWN\n", __FUNCTION__);
++ down(&usbd_network_sem);
++ Usb_network_private.flags &= ~NETWORK_ENABLED;
++ //Usb_network_private.bus = NULL;
++ Usb_network_private.function = NULL;
++ MOD_DEC_USE_COUNT; // QQQ Should this be _after_ the up()?
++ up(&usbd_network_sem);
++ //printk(KERN_INFO"%s: UP\n", __FUNCTION__);
++}
++
++struct usb_function_operations network_fd_function_ops = {
++ recv_setup_irq: network_recv_setup_irq,
++ event_irq: network_event_irq,
++ function_enable: network_function_enable,
++ function_disable: network_function_disable,
++};
++
++//_________________________________________________________________________________________________
++
++/* network_create - create and initialize network private structure
++ *
++ * Returns non-zero for failure.
++ */
++static int network_create (void)
++{
++ struct usb_network_private *network_private = &Usb_network_private;
++
++ //printk(KERN_INFO"%s:\n", __FUNCTION__);
++
++ // Set some fields to generic defaults and register the network device with the kernel networking code
++
++ memset(&network_private->stats, 0, sizeof network_private->stats);
++
++ ether_setup (&Network_net_device);
++ RETURN_EINVAL_IF (register_netdev(&Network_net_device));
++
++ netif_stop_queue (&Network_net_device);
++ netif_carrier_off (&Network_net_device);
++ Network_net_device.flags &= ~IFF_UP;
++
++ network_private->flags |= NETWORK_CREATED;
++
++ network_private->maxtransfer = MAXFRAMESIZE + 4 + 64;
++
++ network_private->flags |= NETWORK_REGISTERED;
++
++ network_private->network_type = network_unknown;
++
++ //printk(KERN_INFO"%s: finis\n", __FUNCTION__);
++ return 0;
++}
++
++/* network_destroy - destroy network private struture
++ *
++ * Destroys the network interface referenced by the global variable @c network_private.
++ */
++static void network_destroy (void)
++{
++ if (Usb_network_private.flags & NETWORK_REGISTERED) {
++ netif_stop_queue (&Network_net_device);
++ netif_carrier_off (&Network_net_device);
++ unregister_netdev (&Network_net_device);
++ }
++ Usb_network_private.flags = 0;
++}
++
++
++//______________________________________module_init and module_exit________________________________
++
++/* hexdigit -
++ *
++ * Converts characters in [0-9A-F] to 0..15, characters in [a-f] to 42..47, and all others to 0.
++ */
++static __u8 hexdigit (char c)
++{
++ return isxdigit (c) ? (isdigit (c) ? (c - '0') : (c - 'A' + 10)) : 0;
++}
++
++/* set_address -
++ */
++void set_address(char *mac_address_str, __u8 *dev_addr)
++{
++ int i;
++ if (mac_address_str && strlen(mac_address_str)) {
++ for (i = 0; i < ETH_ALEN; i++) {
++ dev_addr[i] =
++ hexdigit (mac_address_str[i * 2]) << 4 |
++ hexdigit (mac_address_str[i * 2 + 1]);
++ }
++ }
++ else {
++ get_random_bytes(dev_addr, ETH_ALEN);
++ dev_addr[0] = (dev_addr[0] & 0xfe) | 0x02;
++ }
++}
++
++/* macstrtest -
++ */
++int macstrtest(char *mac_address_str)
++{
++ int l = 0;
++
++ if (mac_address_str) {
++ l = strlen(mac_address_str);
++ }
++ return ((l != 0) && (l != 12));
++}
++
++/* network_modinit - driver intialization
++ *
++ * Returns non-zero for failure.
++ */
++static int network_modinit (void)
++{
++ network_type_t network_type = network_unknown;
++
++ init_waitqueue_head(&usb_netif_wq);
++
++
++ printk(KERN_INFO "Copyright (c) 2002-2004 Belcarra Technologies; www.belcarra.com; sl@belcarra.com\n");
++ printk(KERN_INFO "%s: %s vendor_id: %04x product_id: %04x\n", __FUNCTION__, __usbd_module_info, vendor_id, product_id);
++
++#ifdef CONFIG_USBD_NETWORK_BLAN_FERMAT
++ //printk(KERN_INFO "%s: fermat\n", __FUNCTION__);
++ fermat_init();
++#endif
++
++#if defined(CONFIG_USBD_NETWORK_CDC)
++ if (cdc) {
++ //printk(KERN_INFO "%s: cdc\n", __FUNCTION__);
++ network_type = network_cdc;
++ }
++#endif
++
++#ifdef CONFIG_USBD_NETWORK_BASIC
++ if (basic) {
++ THROW_IF (network_type != network_unknown, select_error);
++ //printk(KERN_INFO "%s: basic\n", __FUNCTION__);
++ network_type = network_basic;
++ }
++#endif
++
++#ifdef CONFIG_USBD_NETWORK_BASIC2
++ if (basic2) {
++ THROW_IF (network_type != network_unknown, select_error);
++ //printk(KERN_INFO "%s: basic2\n", __FUNCTION__);
++ network_type = network_basic2;
++ }
++#endif
++
++#ifdef CONFIG_USBD_NETWORK_BLAN
++ if (blan) {
++ //printk(KERN_INFO "%s: blan\n", __FUNCTION__);
++ THROW_IF (network_type != network_unknown, select_error);
++ network_type = network_blan;
++ }
++#endif
++
++#if defined(CONFIG_USBD_NETWORK_CDC)
++ if (network_type == network_unknown) {
++ //printk(KERN_INFO "%s: cdc\n", __FUNCTION__);
++ network_type = network_cdc;
++ }
++#endif
++
++ // still unknown - check for other bNumConfigurations
++
++ if (network_type == network_unknown) {
++#if defined(CONFIG_USBD_NETWORK_BASIC)
++ //printk(KERN_INFO "%s: basic\n", __FUNCTION__);
++ THROW_IF (network_type != network_unknown, select_error);
++ network_type = network_basic;
++#endif
++#if defined(CONFIG_USBD_NETWORK_BASIC2)
++ //printk(KERN_INFO "%s: basic2\n", __FUNCTION__);
++ THROW_IF (network_type != network_unknown, select_error);
++ network_type = network_basic2;
++#endif
++#if defined(CONFIG_USBD_NETWORK_SAFE)
++ //printk(KERN_INFO "%s: safe\n", __FUNCTION__);
++ THROW_IF (network_type != network_unknown, select_error);
++ network_type = network_safe;
++#endif
++#if defined(CONFIG_USBD_NETWORK_BLAN)
++ //printk(KERN_INFO "%s: blan\n", __FUNCTION__);
++ THROW_IF (network_type != network_unknown, select_error);
++ network_type = network_blan;
++#endif
++ }
++
++ // sanity check
++ THROW_IF (network_type == network_unknown, select_error);
++
++ // select the function driver descriptors based on network_type
++
++ switch (network_type) {
++
++#if defined(CONFIG_USBD_NETWORK_BASIC)
++ case network_basic:
++ //printk(KERN_INFO "%s: basic\n", __FUNCTION__);
++ function_driver = &basic_function_driver;
++ break;
++#endif
++
++#if defined(CONFIG_USBD_NETWORK_BASIC2)
++ case network_basic2:
++ //printk(KERN_INFO "%s: basic2\n", __FUNCTION__);
++ function_driver = &basic2_function_driver;
++ break;
++#endif
++
++#if defined(CONFIG_USBD_NETWORK_SAFE)
++ case network_safe:
++ //printk(KERN_INFO "%s: blan bNumConfigurations: %d\n", __FUNCTION__, blan_function_driver.bNumConfigurations);
++ function_driver = &safe_function_driver;
++ break;
++#endif
++#if defined(CONFIG_USBD_NETWORK_BLAN)
++ case network_blan:
++ //printk(KERN_INFO "%s: blan bNumConfigurations: %d\n", __FUNCTION__, blan_function_driver.bNumConfigurations);
++ function_driver = &blan_function_driver;
++ break;
++#endif
++
++#if defined(CONFIG_USBD_NETWORK_CDC)
++ case network_cdc:
++ function_driver = &cdc_function_driver;
++ break;
++#endif
++ default:
++ THROW(select_error);
++ break;
++ }
++
++ strncpy(Network_net_device.name, network_type == zeroconf ? "usbz0" : (network_blan ? "usbl0" : "usbb0"), 6);
++
++
++ THROW_IF (!function_driver, select_error);
++
++ CATCH(select_error) {
++ printk(KERN_INFO "%s: configuration selection error\n", __FUNCTION__);
++ return -EINVAL;
++ }
++
++
++#ifdef CONFIG_USBD_NETWORK_EP0TEST
++ /*
++ * ep0test - test that bus interface can do ZLP on endpoint zero
++ *
++ * This will artificially force iProduct string descriptor to be
++ * exactly the same as the endpoint zero packetsize. When the host
++ * requests this string it will request it not knowing the strength
++ * and will use a max length of 0xff. The bus interface driver must
++ * send a ZLP to terminate the transaction.
++ *
++ * The iProduct descriptor is used because both the Linux and
++ * Windows usb implmentations fetch this in a default enumeration.
++ *
++ */
++ if (ep0test) {
++ switch (ep0test) {
++ case 8: function_driver->device_description->iProduct = "012"; break;
++ case 16: function_driver->device_description->iProduct = "0123456"; break;
++ case 32: function_driver->device_description->iProduct = "0123456789abcde"; break;
++ case 64: function_driver->device_description->iProduct = "0123456789abcdef0123456789abcde"; break;
++ default: printk(KERN_ERR"%s: ep0test: bad value: %d, must be one of 8, 16, 32 or 64\n",
++ __FUNCTION__, ep0test); return -EINVAL;
++ break;
++ }
++ printk(KERN_INFO"%s: ep0test: iProduct set to: %s\n", __FUNCTION__,
++ function_driver->device_description->iProduct);
++ }
++ else
++ printk(KERN_INFO"%s: ep0test: not set\n", __FUNCTION__);
++#endif /* CONFIG_USBD_NETWORK_EP0TEST */
++
++
++#ifdef CONFIG_USBD_NETWORK_ALLOW_SETID
++ //printk(KERN_INFO"%s: checking idVendor: %04x idProduct: %04x\n", __FUNCTION__, vendor_id, product_id);
++
++ if (vendor_id)
++ function_driver->idVendor = cpu_to_le16(vendor_id);
++
++ if (product_id)
++ function_driver->idProduct = cpu_to_le16(product_id);
++#endif
++
++ if ((macstrtest(local_mac_address_str) || macstrtest(remote_mac_address_str))) {
++ printk(KERN_INFO"%s: bad size %s %s\n", __FUNCTION__, local_mac_address_str, remote_mac_address_str);
++ return -EINVAL;
++ }
++
++ set_address(local_mac_address_str, local_dev_addr);
++ set_address(remote_mac_address_str, remote_dev_addr);
++
++ RETURN_EINVAL_IF(network_create());
++
++ Usb_network_private.network_type = network_type;
++
++ Usb_network_private.notification_bh.routine = notification_bh;
++ Usb_network_private.notification_bh.data = NULL;
++
++#ifdef CONFIG_HOTPLUG
++ Usb_network_private.hotplug_bh.routine = hotplug_bh;
++ Usb_network_private.hotplug_bh.data = NULL;
++#endif
++
++ memcpy(Network_net_device.dev_addr, local_dev_addr, ETH_ALEN);
++
++ THROW_IF(make_crc_table(), error);
++
++ Usb_network_private.encapsulation = simple_crc;
++
++ THROW_IF(usbd_register_function (function_driver), error);
++
++ return 0;
++
++ CATCH(error) {
++ network_destroy();
++ return -EINVAL;
++ }
++}
++
++//_________________________________________________________________________________________________
++
++/* network_modexit - driver exit
++ *
++ * Cleans up the module. Deregisters the function driver and destroys the network object.
++ */
++static void network_modexit (void)
++{
++ //printk(KERN_INFO"%s: exiting\n", __FUNCTION__);
++
++ while (Usb_network_private.notification_bh.sync) {
++ printk(KERN_ERR"%s: waiting for notificationhotplug bh\n", __FUNCTION__);
++ schedule_timeout(10 * HZ);
++ }
++
++#ifdef CONFIG_HOTPLUG
++ while (Usb_network_private.hotplug_bh.sync) {
++ printk(KERN_ERR"%s: waiting for hotplug bh\n", __FUNCTION__);
++ schedule_timeout(10 * HZ);
++ }
++#endif
++
++ usbd_deregister_function (function_driver);
++ network_destroy();
++ if (network_crc32_table) {
++ lkfree(network_crc32_table);
++ network_crc32_table = NULL;
++ }
++}
++
++//_________________________________________________________________________________________________
++
++module_init (network_modinit);
++module_exit (network_modexit);
++
+diff -Nru a/drivers/usbd/network_fd/network.h b/drivers/usbd/network_fd/network.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/network_fd/network.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,203 @@
++/*
++ * usbd/network_fd/network.h - Network Function Driver
++ *
++ * Copyright (c) 2002, 2003, 2004 Belcarra
++ *
++ * By:
++ * Chris Lynne <cl@belcarra.com>
++ * Stuart Lynne <sl@belcarra.com>
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#ifndef NETWORK_FD_H
++#define NETWORK_FD_H 1
++
++typedef enum network_encapsulation {
++ simple_net, simple_crc,
++} network_encapsulation_t;
++
++typedef enum network_hotplug_status {
++ hotplug_unkown,
++ hotplug_attached,
++ hotplug_detached
++} network_hotplug_status_t;
++
++typedef enum network_type {
++ network_unknown,
++ network_blan,
++ network_safe,
++ network_cdc,
++ network_basic,
++ network_basic2,
++} network_type_t;
++
++struct usb_network_private {
++
++ struct net_device_stats stats; /* network device statistics */
++
++ int flags;
++ struct usb_function_instance *function;
++ unsigned int maxtransfer;
++ rwlock_t rwlock;
++
++ network_hotplug_status_t hotplug_status;
++ network_type_t network_type;
++
++ int state;
++
++ int mtu;
++ int crc;
++#if defined(CONFIG_USBD_NETWORK_BLAN_FERMAT)
++ int fermat;
++#endif
++
++ unsigned int stopped;
++ unsigned int restarts;
++
++ unsigned int max_queue_entries;
++ unsigned int max_queue_bytes;
++
++ unsigned int queued_entries;
++ unsigned int queued_bytes;
++
++ time_t avg_queue_entries;
++
++ time_t jiffies;
++ unsigned long samples;
++
++ int have_interrupt;
++
++ struct urb *int_urb;
++
++ network_encapsulation_t encapsulation;
++
++ struct tq_struct notification_bh;
++
++#ifdef CONFIG_HOTPLUG
++ struct tq_struct hotplug_bh;
++#endif
++};
++
++// XXX this needs to be co-ordinated with rndis.c maximum's
++#define MAXFRAMESIZE 2000
++
++#if !defined(CONFIG_USBD_MAXPOWER)
++ #define CONFIG_USBD_MAXPOWER 0
++#endif
++
++#if !defined(CONFIG_USBD_MANUFACTURER)
++ #define CONFIG_USBD_MANUFACTURER "Belcarra"
++#endif
++
++
++#if !defined(CONFIG_USBD_SERIAL_NUMBER_STR)
++ #define CONFIG_USBD_SERIAL_NUMBER_STR ""
++#endif
++
++/*
++ * Lineo specific
++ */
++
++#define VENDOR_SPECIFIC_CLASS 0xff
++#define VENDOR_SPECIFIC_SUBCLASS 0xff
++#define VENDOR_SPECIFIC_PROTOCOL 0xff
++
++/*
++ * Lineo Classes
++ */
++#define LINEO_CLASS 0xff
++
++#define LINEO_SUBCLASS_BASIC_NET 0x01
++#define LINEO_SUBCLASS_BASIC_SERIAL 0x02
++
++/*
++ * Lineo Protocols
++ */
++#define LINEO_BASIC_NET_CRC 0x01
++#define LINEO_BASIC_NET_CRC_PADDED 0x02
++
++#define LINEO_BASIC_SERIAL_CRC 0x01
++#define LINEO_BASIC_SERIAL_CRC_PADDED 0x02
++
++
++/*
++ * endpoint and interface indexes
++ */
++#define BULK_OUT 0x00
++#define BULK_IN 0x01
++#define INT_IN 0x02
++#define ENDPOINTS 0x03
++
++#define COMM_INTF 0x00
++#define DATA_INTF 0x01
++
++
++/* bmDataCapabilities */
++#define BMDATA_CRC 0x01
++#define BMDATA_PADBEFORE 0x02
++#define BMDATA_PADAFTER 0x04
++#define BMDATA_FERMAT 0x08
++#define BMDATA_HOSTNAME 0x10
++
++/* bmNetworkCapabilities */
++#define BMNETWORK_SET_PACKET_OK 0x01
++#define BMNETWORK_NOBRIDGE 0x02
++
++
++/*
++ * BLAN Data Plane
++ */
++//#define CONFIG_USBD_NETWORK_PADBYTES 8
++//#define CONFIG_USBD_NETWORK_PADAFTER 1
++//#undef CONFIG_USBD_NETWORK_PADBEFORE
++//#define CONFIG_USBD_NETWORK_CRC 1
++
++
++extern __u8 network_requested_endpoints[ENDPOINTS+1];
++extern __u16 network_requested_transferSizes[ENDPOINTS+1];
++extern struct usb_network_private Usb_network_private;
++extern __u8 local_dev_addr[ETH_ALEN];
++extern __u8 remote_dev_addr[ETH_ALEN];
++
++extern struct usb_function_operations network_fd_function_ops;
++extern struct usb_network_private Usb_network_private;
++
++struct usb_class_safe_networking_mdlm_descriptor {
++ __u8 bFunctionLength; // 0x06
++ __u8 bDescriptorType; // 0x24
++ __u8 bDescriptorSubtype; // 0x13
++ __u8 bGuidDescriptorType; // 0x00
++ __u8 bmNetworkCapabilities;
++ __u8 bmDataCapabilities;
++} __attribute__ ((packed));
++
++struct usb_class_blan_networking_mdlm_descriptor {
++ __u8 bFunctionLength; // 0x07
++ __u8 bDescriptorType; // 0x24
++ __u8 bDescriptorSubtype; // 0x13
++ __u8 bGuidDescriptorType; // 0x01
++ __u8 bmNetworkCapabilities;
++ __u8 bmDataCapabilities;
++ __u8 bPad;
++} __attribute__ ((packed));
++
++
++
++
++
++#endif /* NETWORK_FD_H */
+diff -Nru a/drivers/usbd/network_fd/safe.c b/drivers/usbd/network_fd/safe.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/network_fd/safe.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,224 @@
++/*
++ * usbd/network_fd/safe.c - Network Function Driver
++ *
++ * Copyright (c) 2002, 2003, 2004 Belcarra
++ *
++ * By:
++ * Chris Lynne <cl@belcarra.com>
++ * Stuart Lynne <sl@belcarra.com>
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ *
++ *
++ */
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++#include <usbd-export.h>
++#include <usbd-build.h>
++
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/utsname.h>
++#include <linux/netdevice.h>
++
++#include <usbd-chap9.h>
++#include <usbd-mem.h>
++#include <usbd.h>
++#include <usbd-func.h>
++
++#include "network.h"
++
++
++#ifdef CONFIG_USBD_NETWORK_SAFE
++/* USB SAFE Configuration ******************************************************************** */
++
++/*
++ * SAFE Ethernet Configuration
++ */
++
++/* Communication Interface Class descriptors
++ */
++
++static __u8 safe_data_1[] = { 0x07, USB_DT_ENDPOINT, OUT, BULK, 0, 0x00, 0x00, };
++static __u8 safe_data_2[] = { 0x07, USB_DT_ENDPOINT, IN, BULK, 0, 0x00, 0x00, };
++static __u8 safe_comm_1[] = { 0x07, USB_DT_ENDPOINT, IN, INTERRUPT,0, 0x00, 0x0a, };
++
++static __u8 safe_class_1[] = { 0x05, CS_INTERFACE, USB_ST_HEADER, 0x10, 0x01, /* CLASS_BDC_VERSION, CLASS_BDC_VERSION */ };
++static __u8 safe_class_2[] = { 0x15, CS_INTERFACE, USB_ST_MDLM, 0x00, 0x01, /* bcdVersion, bcdVersion */
++ 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, /* bGUID */
++ 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, /* bGUID */ };
++
++static __u8 safe_class_3[] = { 0x06, CS_INTERFACE, USB_ST_MDLMD, 0x00, 0x00, 0x00, /* bDetailData */ };
++
++static __u8 safe_class_4[] = { 0x0d, CS_INTERFACE, USB_ST_ENF,
++ 0x00, 0x00, 0x00, 0x00, 0x00, 0xea, 0x05, /* 1514 maximum frame size */
++ 0x00, 0x00, 0x00 , };
++
++
++static __u8 *safe_alt_endpoints[] = {
++ (struct usb_endpoint_descriptor *) &safe_data_1,
++ (struct usb_endpoint_descriptor *) &safe_data_2,
++ (struct usb_endpoint_descriptor *) &safe_comm_1, };
++static __u8 *safe_comm_class_descriptors[] = {
++ (struct usb_generic_class_descriptor *) &safe_class_1,
++ (struct usb_generic_class_descriptor *) &safe_class_2,
++ (struct usb_generic_class_descriptor *) &safe_class_3,
++ (struct usb_generic_class_descriptor *) &safe_class_4, };
++
++u8 safe_alt_indexes[] = { BULK_OUT, BULK_IN, INT_IN, };
++
++/* Data Interface Alternate descriptions and descriptors
++ */
++static __u8 safe_alternate_descriptor[sizeof(struct usb_interface_descriptor)] = {
++ 0x09, USB_DT_INTERFACE, 0x00, 0x00, // bInterfaceNumber, bAlternateSetting
++ sizeof (safe_alt_endpoints) / sizeof(struct usb_endpoint_descriptor), // bNumEndpoints
++ COMMUNICATIONS_INTERFACE_CLASS, COMMUNICATIONS_MDLM_SUBCLASS, COMMUNICATIONS_NO_PROTOCOL, 0x00,
++};
++
++static struct usb_alternate_description safe_alternate_descriptions[] = {
++ { iInterface: CONFIG_USBD_NETWORK_SAFE_INTF,
++ interface_descriptor: (struct usb_interface_descriptor *)&safe_alternate_descriptor,
++ classes:sizeof (safe_comm_class_descriptors) / sizeof (struct usb_generic_class_descriptor *),
++ class_list: safe_comm_class_descriptors,
++ endpoints:sizeof (safe_alt_endpoints) / sizeof(struct usb_endpoint_descriptor *),
++ endpoint_list: safe_alt_endpoints,
++ endpoint_indexes: safe_alt_indexes,
++ },
++};
++
++/* Interface descriptions and descriptors
++ */
++static struct usb_interface_description safe_interfaces[] = {
++ { alternates:sizeof (safe_alternate_descriptions) / sizeof (struct usb_alternate_description),
++ alternate_list:safe_alternate_descriptions, },
++};
++
++
++/* Configuration descriptions and descriptors
++ */
++
++static __u8 safe_configuration_descriptor[sizeof(struct usb_configuration_descriptor)] = {
++ 0x09, USB_DT_CONFIG, 0x00, 0x00, // wLength
++ sizeof (safe_interfaces) / sizeof (struct usb_interface_description),
++ 0x01, 0x00, // bConfigurationValue, iConfiguration
++ BMATTRIBUTE, BMAXPOWER,
++};
++
++struct usb_configuration_description safe_description[] = {
++ { iConfiguration: CONFIG_USBD_NETWORK_SAFE_DESC,
++ configuration_descriptor: (struct usb_configuration_descriptor *)safe_configuration_descriptor,
++ bNumInterfaces:sizeof (safe_interfaces) / sizeof (struct usb_interface_description),
++ interface_list:safe_interfaces, },
++};
++
++/* Device Description
++ */
++
++//static __u8 safe_device_descriptor[sizeof(struct usb_device_descriptor)] = {
++// 0x12, USB_DT_DEVICE,
++// 0x00, 0x02, // bcdUSB
++// COMMUNICATIONS_DEVICE_CLASS,
++// 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
++//};
++static struct usb_device_descriptor safe_device_descriptor = {
++ bLength: sizeof(struct usb_device_descriptor),
++ bDescriptorType: USB_DT_DEVICE,
++ bcdUSB: __constant_cpu_to_le16(USB_BCD_VERSION),
++ bDeviceClass: COMMUNICATIONS_DEVICE_CLASS,
++ bDeviceSubClass: 0x02,
++ bDeviceProtocol: 0x00,
++ bMaxPacketSize0: 0x00,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_BCDDEVICE),
++};
++
++static struct usb_endpoint_request safe_endpoint_requests[ENDPOINTS+1] = {
++ { 1, 0, 0, USB_DIR_OUT | USB_ENDPOINT_BULK, MAXFRAMESIZE + 48, MAXFRAMESIZE + 512, },
++ { 1, 0, 0, USB_DIR_IN | USB_ENDPOINT_BULK, MAXFRAMESIZE + 48, MAXFRAMESIZE + 512, },
++ { 1, 0, 0, USB_DIR_IN | USB_ENDPOINT_INTERRUPT | USB_ENDPOINT_OPT, 16, 64, },
++ { 0, },
++};
++
++struct usb_device_description safe_device_description = {
++ device_descriptor: &safe_device_descriptor,
++ iManufacturer: CONFIG_USBD_NETWORK_MANUFACTURER,
++ iProduct: CONFIG_USBD_NETWORK_PRODUCT_NAME,
++#if !defined(CONFIG_USBD_NO_SERIAL_NUMBER) && defined(CONFIG_USBD_SERIAL_NUMBER_STR)
++ iSerialNumber:CONFIG_USBD_SERIAL_NUMBER_STR,
++#endif
++ endpointsRequested: ENDPOINTS,
++ requestedEndpoints: safe_endpoint_requests,
++};
++
++void safe_init (struct usb_function_instance *function)
++{
++ struct usb_class_ethernet_networking_descriptor *ethernet;
++ int len = 0;
++ char buf[255];
++
++ buf[0] = 0;
++
++ safe_alternate_descriptions[0].endpoints = Usb_network_private.have_interrupt ? 3 : 2;
++
++ // Update the iMACAddress field in the ethernet descriptor
++ {
++ char address_str[14];
++ snprintf(address_str, 13, "%02x%02x%02x%02x%02x%02x",
++ remote_dev_addr[0], remote_dev_addr[1], remote_dev_addr[2],
++ remote_dev_addr[3], remote_dev_addr[4], remote_dev_addr[5]);
++ if ((ethernet = (struct usb_class_ethernet_networking_descriptor *)safe_class_4)) {
++ if (ethernet->iMACAddress) {
++ usbd_dealloc_string(ethernet->iMACAddress);
++ }
++ ethernet->iMACAddress = usbd_alloc_string(address_str);
++ }
++ }
++
++
++#ifdef CONFIG_USBD_NETWORK_SAFE_PADBEFORE
++ safe_class_3[5] |= BMDATA_PADBEFORE;
++ len += sprintf(buf + len, "PADBEFORE: %02x ", safe_class_3[5]);
++#endif
++#ifdef CONFIG_USBD_NETWORK_SAFE_CRC
++ safe_class_3[5] |= BMDATA_CRC;
++ len += sprintf(buf + len, "CRC: %02x ", safe_class_3[5]);
++#endif
++#ifdef CONFIG_USBD_NETWORK_SAFE_NOBRIDGE
++ safe_class_3[4] |= BMNETWORK_NOBRIDGE;
++ len += sprintf(buf + len, "NOBRIDGE: %02x ",safe_class_3[4]);
++#endif
++ if (strlen(buf))
++ printk(KERN_INFO"%s: %s\n", __FUNCTION__, buf);
++
++}
++
++struct usb_function_driver safe_function_driver = {
++ name: "network-SAFE",
++ fops: &network_fd_function_ops,
++ device_description: &safe_device_description,
++ bNumConfigurations: sizeof (safe_description) / sizeof (struct usb_configuration_description),
++ configuration_description: safe_description,
++ idVendor: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_VENDORID),
++ idProduct: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_PRODUCTID),
++ bcdDevice: __constant_cpu_to_le16(CONFIG_USBD_NETWORK_BCDDEVICE),
++};
++#endif /* CONFIG_USBD_NETWORK_SAFE */
++
+diff -Nru a/drivers/usbd/trace.c b/drivers/usbd/trace.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/trace.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,509 @@
++/*
++ * usbd/trace.c
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2002 Lineo
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/version.h>
++
++//EXPORT_NO_SYMBOLS;
++
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/pci.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++
++#include <linux/proc_fs.h>
++#include <linux/vmalloc.h>
++
++#include <asm/atomic.h>
++#include <asm/io.h>
++
++#include <linux/proc_fs.h>
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,6)
++#define USE_ADD_DEL_TIMER_FOR_USBADDR_CHECK 1
++#include <linux/timer.h>
++#else
++#undef USE_ADD_DEL_TIMER_FOR_USBADDR_CHECK
++#include <linux/tqueue.h>
++#endif
++
++#include <linux/pci.h>
++#include <linux/cache.h>
++
++
++#if defined(CONFIG_ARCH_SA1100) || defined (CONFIG_ARCH_PXA)
++#include <asm/dma.h>
++#include <asm/mach/dma.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/hardware.h>
++#include <asm/types.h>
++#endif
++
++#if defined(CONFIG_SOC_AU1X00) || \
++ defined(CONFIG_MIPS_AU1X00) || \
++ defined(CONFIG_CPU_AU1X00) || \
++ defined(CONFIG_MIPS_AU1000) || \
++ defined(CONFIG_MIPS_PB1500) || \
++ defined(CONFIG_MIPS_PB1100)
++
++#include <asm/au1000.h>
++#include <asm/au1000_dma.h>
++#include <asm/mipsregs.h>
++
++#endif /* defined(..) */
++
++#if defined(CONFIG_ARCH_SAMSUNG)
++#include <asm/arch/timers.h>
++#include <asm/arch/hardware.h>
++#endif /* defined(CONFIG_ARCH_SAMSUNG) */
++
++#if defined(CONFIG_ARCH_MX1ADS)
++#include "dbmx1_bi/dbmx1.h"
++#endif /* defined(CONFIG_ARCH_MX1ADS) */
++
++#include <asm/uaccess.h>
++#include <asm/io.h>
++#include <asm/pgtable.h>
++#include <asm/pgalloc.h>
++
++#include "usbd-chap9.h"
++#include "usbd-mem.h"
++#include "usbd.h"
++#include "usbd-func.h"
++#include "usbd-bus.h"
++
++#include "trace.h"
++#include "usbd-bi.h"
++
++
++int trace_first;
++int trace_next;
++trace_t *traces;
++
++#if defined(CONFIG_USBD_BI_REGISTER_TRACE) && defined(CONFIG_PROC_FS)
++
++trace_t *TRACE_NEXT(trace_types_t trace_type)
++{
++ trace_t *p;
++
++ p = traces + trace_next;
++
++ #if defined(CONFIG_ARCH_SA1100) || \
++ defined (CONFIG_ARCH_PXA)
++
++ p->oscr = OSCR;
++
++ #elif defined(CONFIG_SOC_AU1X00) || \
++ defined(CONFIG_MIPS_AU1X00) || \
++ defined(CONFIG_CPU_AU1X00) || \
++ defined(CONFIG_MIPS_AU1000) || \
++ defined(CONFIG_MIPS_PB1500) || \
++ defined(CONFIG_MIPS_PB1100)
++
++ #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,19)
++ p->cp0_count = __read_32bit_c0_register(CP0_COUNT);
++ #else
++ p->cp0_count = read_c0_count();
++ #endif
++
++ #elif defined(CONFIG_ARCH_SAMSUNG)
++ p->tcnt1 = *(volatile u32 *)TCNT1;
++ #else
++ p->jiffies = jiffies;
++ #endif
++
++ #if defined(CONFIG_SOC_AU1X00) || \
++ defined(CONFIG_MIPS_AU1X00) || \
++ defined(CONFIG_CPU_AU1X00) || \
++ defined(CONFIG_MIPS_AU1000) || \
++ defined(CONFIG_MIPS_PB1500) || \
++ defined(CONFIG_MIPS_PB1100)
++ //p->sofs = au_readl(USBD_FRAMENUM);
++ #endif
++
++ #if defined(CONFIG_ARCH_MX1ADS)
++ p->sofs = USBD_FRAME & 0x3ff;
++ #endif
++
++ p->interrupts = udc_interrupts;
++ p->trace_type = trace_type;
++
++ trace_next++;
++ trace_next = (trace_next == TRACE_MAX) ? 0 : trace_next;
++
++ if (trace_next == trace_first) {
++ trace_first++;
++ trace_first = (trace_first == TRACE_MAX) ? 0 : trace_first;
++ }
++
++ return p;
++}
++
++/* Proc Filesystem *************************************************************************** */
++
++static __inline__ char *nullchk(char *s)
++{
++ return s ? s : "(NULL)";
++}
++/* *
++ * trace_proc_read - implement proc file system read.
++ * @file
++ * @buf
++ * @count
++ * @pos
++ *
++ * Standard proc file system read function.
++ */
++static ssize_t trace_proc_read (struct file *file, char *buf, size_t count, loff_t * pos)
++{
++ unsigned long page;
++ int len = 0;
++ int index;
++ int oindex;
++ int previous;
++
++ #ifdef MODULE
++ MOD_INC_USE_COUNT;
++ #endif
++ // get a page, max 4095 bytes of data...
++ if (!(page = get_free_page (GFP_KERNEL))) {
++
++ #ifdef MODULE
++ MOD_DEC_USE_COUNT;
++ #endif
++ return -ENOMEM;
++ }
++
++ len = 0;
++ oindex = index = (*pos)++;
++
++ if (index == 0) {
++ #if defined(CONFIG_ARCH_SAMSUNG)
++ len += sprintf ((char *) page + len, " Index Ints Ticks [%d]\n", CONFIG_USBD_SMDK2500_BCLOCK );
++ #else
++ len += sprintf ((char *) page + len, " Index Ints Ticks\n");
++ #endif
++ }
++
++ index += trace_first;
++ if (index >= TRACE_MAX) {
++ index -= TRACE_MAX;
++ }
++ previous = (index) ? (index - 1) : (TRACE_MAX - 1);
++
++ //printk(KERN_INFO"first: %d next: %d index: %d %d prev: %d\n", trace_first, trace_next, oindex, index, previous);
++
++ if (
++ ((trace_first < trace_next) && (index >= trace_first) && (index < trace_next)) ||
++ ((trace_first > trace_next) && ((index < trace_next) || (index >= trace_first)))
++ )
++ {
++
++ #if defined(CONFIG_SOC_AU1X00) || \
++ defined(CONFIG_MIPS_AU1X00) || \
++ defined(CONFIG_CPU_AU1X00) || \
++ defined(CONFIG_MIPS_AU1000) || \
++ defined(CONFIG_MIPS_PB1500) || \
++ defined(CONFIG_MIPS_PB1100)
++
++ u32 ticks = 0;
++
++ #elif defined(CONFIG_ARCH_SAMSUNG)
++ u32 ticks = 0;
++ #elif defined(CONFIG_ARCH_SA1100) || defined (CONFIG_ARCH_PXA)
++ u32 ticks = 0;
++ u64 jifs = 0;
++ #else
++ u64 jifs = 0;
++ #endif
++
++ trace_t *p = traces + index;
++ unsigned char *cp;
++ int skip = 0;
++
++ if (oindex > 0) {
++ trace_t *o = traces + previous;
++
++ #if defined(CONFIG_ARCH_SA1100) || defined (CONFIG_ARCH_PXA)
++ /*
++ * oscr is 3.6864 Mhz free running counter,
++ *
++ * 1/3.6864 = .2712
++ * 60/221 = .2714
++ *
++ */
++ if (o->oscr) {
++ ticks = (p->oscr > o->oscr) ? (p->oscr - o->oscr) : (o->oscr - p->oscr) ;
++ ticks = (ticks * 60) / 221;
++ }
++
++ #elif defined(CONFIG_SOC_AU1X00) || \
++ defined(CONFIG_MIPS_AU1X00) || \
++ defined(CONFIG_CPU_AU1X00) || \
++ defined(CONFIG_MIPS_AU1000) || \
++ defined(CONFIG_MIPS_PB1500) || \
++ defined(CONFIG_MIPS_PB1100)
++ /*
++ * cp0_count is incrementing timer at system clock
++ */
++ if (o->cp0_count) {
++ ticks = (p->cp0_count > o->cp0_count) ?
++ (p->cp0_count - o->cp0_count) : (o->cp0_count - p->cp0_count) ;
++ ticks = ticks / CONFIG_USBD_AU1X00_SCLOCK;
++ }
++ #elif defined(CONFIG_ARCH_SAMSUNG)
++ /*
++ * tcnt1 is a count-down timer running at the system bus clock
++ * The divisor must be set as a configuration value, typically 66 or 133.
++ */
++ if (o->tcnt1) {
++ ticks = (p->tcnt1 < o->tcnt1) ? (o->tcnt1 - p->tcnt1) : (p->tcnt1 - o->tcnt1) ;
++ ticks /= CONFIG_USBD_SMDK2500_BCLOCK;
++ }
++ #else
++ if (o->jiffies) {
++ jifs = p->jiffies - traces[previous].jiffies;
++ }
++ #endif
++
++ if (o->interrupts != p->interrupts) {
++ skip++;
++ }
++ }
++
++ //printk(KERN_INFO"index: %d interrupts: %d\n", index, p->interrupts);
++ len += sprintf ((char *) page + len, "%s%6d %8d ", skip?"\n":"", index, p->interrupts);
++
++ #if defined(CONFIG_SOC_AU1X00) || \
++ defined(CONFIG_MIPS_AU1X00) || \
++ defined(CONFIG_CPU_AU1X00) || \
++ defined(CONFIG_MIPS_AU1000) || \
++ defined(CONFIG_MIPS_PB1500) || \
++ defined(CONFIG_MIPS_PB1100) || \
++ defined(CONFIG_ARCH_SA1100) || \
++ defined(CONFIG_ARCH_PXA)
++
++ if (ticks > 1024*1024) {
++ len += sprintf ((char *) page + len, "%8dM ", ticks>>20);
++ }
++ else {
++ len += sprintf ((char *) page + len, "%8d ", ticks);
++ }
++
++ #elif defined(CONFIG_ARCH_SAMSUNG)
++ //len += sprintf ((char *) page + len, "%8u ", p->jiffies);
++ //len += sprintf ((char *) page + len, "%8u ", p->tcnt0);
++ len += sprintf ((char *) page + len, "%8u ", p->tcnt1);
++ if (ticks > 1024*1024) {
++ len += sprintf ((char *) page + len, "%8dM ", ticks>>20);
++ }
++ else {
++ len += sprintf ((char *) page + len, "%8d ", ticks);
++ }
++ #else
++ if (jifs > 1024) {
++ len += sprintf ((char *) page + len, "%4d ", (int)jifs>>20);
++ }
++ else {
++ len += sprintf ((char *) page + len, "%4d ", (int)jifs);
++ }
++ #endif
++ #if defined(CONFIG_ARCH_MX1ADS)
++ len += sprintf ((char *) page + len, "%6d ", (int)p->sofs);
++ #endif
++
++ switch (p->trace_type) {
++ case trace_msg:
++ len += sprintf ((char *) page + len, " -- ");
++ len += sprintf ((char *) page + len, p->trace.msg.msg);
++ break;
++
++ case trace_w:
++ len += sprintf ((char *) page + len, " --> ");
++ len += sprintf ((char *) page + len, "[%8x] W %s", p->trace.msg32.val, nullchk(p->trace.msg32.msg));
++ break;
++
++ case trace_r:
++ len += sprintf ((char *) page + len, "<-- ");
++ len += sprintf ((char *) page + len, "[%8x] R %s", p->trace.msg32.val, nullchk(p->trace.msg32.msg));
++ break;
++
++ case trace_msg32:
++ len += sprintf ((char *) page + len, " -- ");
++ len += sprintf ((char *) page + len, p->trace.msg32.msg, p->trace.msg32.val);
++ break;
++
++ case trace_msg16:
++ len += sprintf ((char *) page + len, " -- ");
++ len += sprintf ((char *) page + len, p->trace.msg16.msg, p->trace.msg16.val0, p->trace.msg16.val1);
++ break;
++
++ case trace_msg8:
++ len += sprintf ((char *) page + len, " -- ");
++ len += sprintf ((char *) page + len, p->trace.msg8.msg,
++ p->trace.msg8.val0, p->trace.msg8.val1, p->trace.msg8.val2, p->trace.msg8.val3);
++ break;
++
++ case trace_setup:
++ cp = (unsigned char *)&p->trace.setup;
++ len += sprintf ((char *) page + len,
++ " -- request [%02x %02x %02x %02x %02x %02x %02x %02x]",
++ cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
++ break;
++
++ case trace_recv:
++ case trace_sent:
++ cp = (unsigned char *)&p->trace.sent;
++ len += sprintf ((char *) page + len,
++ "%s %s [%02x %02x %02x %02x %02x %02x %02x %02x]",
++ ( p->trace_type == trace_recv)?"<-- ":" -->",
++ ( p->trace_type == trace_recv)?"recv":"sent",
++ cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]);
++ break;
++ }
++ len += sprintf ((char *) page + len, "\n");
++ }
++
++ if ((len > count) || (len == 0))
++ len = -EINVAL;
++
++ else if (len > 0 && copy_to_user (buf, (char *) page, len))
++ len = -EFAULT;
++
++ free_page (page);
++ MOD_DEC_USE_COUNT;
++ return len;
++}
++
++/* *
++ * trace_proc_write - implement proc file system write.
++ * @file
++ * @buf
++ * @count
++ * @pos
++ *
++ * Proc file system write function, used to signal monitor actions complete.
++ * (Hotplug script (or whatever) writes to the file to signal the completion
++ * of the script.) An ugly hack.
++ */
++static ssize_t trace_proc_write (struct file *file, const char *buf, size_t count, loff_t * pos)
++{
++ return count;
++}
++
++static struct file_operations trace_proc_operations_functions = {
++ read:trace_proc_read,
++ write:trace_proc_write,
++};
++
++int trace_reinit (void)
++{
++ printk(KERN_INFO"%s:\n", __FUNCTION__);
++ //trace_first = trace_next = 0;
++ return 0;
++}
++
++/**
++ * udc_request_udc_io - request UDC io region
++ *
++ * Return non-zero if not successful.
++ */
++int trace_init (void)
++{
++ struct proc_dir_entry *p;
++ trace_first = trace_next = 0;
++ printk(KERN_INFO"%s:\n", __FUNCTION__);
++
++ if (!(traces = vmalloc(sizeof(trace_t) * TRACE_MAX))) {
++ printk(KERN_ERR"BITRACE malloc failed %p %d\n", traces, sizeof(trace_t) * TRACE_MAX);
++ return -EINVAL;
++ }
++
++ memset(traces, 0, sizeof(trace_t) * TRACE_MAX);
++
++ TRACE_MSG("init");
++ TRACE_MSG("test");
++
++ // create proc filesystem entries
++ if ((p = create_proc_entry ("bitrace", 0, 0)) == NULL)
++ printk(KERN_INFO"BITRACE PROC FS failed\n");
++ else
++ p->proc_fops = &trace_proc_operations_functions;
++
++ #if defined(CONFIG_ARCH_SAMSUNG)
++ *(volatile u32 *)TMOD |= 0x3 << 3;
++ #endif
++ return 0;
++}
++
++/**
++ * udc_release_io - release UDC io region
++ */
++void trace_exit (void)
++{
++ {
++ unsigned long flags;
++ local_irq_save (flags);
++ remove_proc_entry ("bitrace", NULL);
++ if (traces) {
++ trace_t *p = traces;
++ traces = 0;
++ vfree(p);
++ }
++ local_irq_restore (flags);
++ }
++}
++
++#else
++int trace_reinit (void)
++{
++ return 0;
++}
++
++int trace_init (void)
++{
++ return 0;
++}
++
++void trace_exit (void)
++{
++ return;
++}
++#endif
++
++/* End of FILE */
++
++
++//EXPORT_SYMBOL(trace_first);
++//EXPORT_SYMBOL(trace_next);
++//EXPORT_SYMBOL(traces);
++
+diff -Nru a/drivers/usbd/trace.h b/drivers/usbd/trace.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/trace.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,270 @@
++/*
++ * usbd/trace.h
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2002 Lineo
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#if defined(CONFIG_ARCH_SAMSUNG)
++#ifndef CONFIG_USBD_SMDK2500_BCLOCK
++#define CONFIG_USBD_SMDK2500_BCLOCK 66
++#endif
++#endif
++
++
++typedef enum trace_int_types {
++ trace_int_udc, trace_int_ep0, trace_int_in, trace_int_out, trace_int_int
++} trace_int_types_t;
++
++typedef struct trace_int {
++ u32 last;
++ u32 total;
++ u32 samples;
++} trace_int_t;
++
++
++typedef enum trace_types {
++ trace_setup, trace_msg, trace_msg32, trace_msg16, trace_msg8, trace_recv, trace_sent, trace_w, trace_r
++} trace_types_t;
++
++
++typedef struct trace_regs32 {
++ u32 reg;
++ char * msg;
++} trace_regs32_t;
++
++
++typedef struct trace_msg {
++ char *msg;
++} trace_msg_t;
++
++typedef struct trace_msg32 {
++ u32 val;
++ char *msg;
++} trace_msg32_t;
++
++typedef struct trace_msg16 {
++ u16 val0;
++ u16 val1;
++ char *msg;
++} trace_msg16_t;
++
++typedef struct trace_msg8 {
++ u8 val0;
++ u8 val1;
++ u8 val2;
++ u8 val3;
++ char *msg;
++} trace_msg8_t;
++
++
++typedef struct trace {
++ trace_types_t trace_type;
++ u32 interrupts;
++#if defined(CONFIG_ARCH_SA1100) || defined (CONFIG_ARCH_PXA)
++ u32 oscr;
++
++#elif defined(CONFIG_SOC_AU1X00) || defined(CONFIG_MIPS_AU1X00) || defined(CONFIG_CPU_AU1X00) || defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100)
++
++ u32 cp0_count;
++#elif defined(CONFIG_ARCH_SAMSUNG)
++ //u32 tcnt0;
++ u32 tcnt1;
++ //u64 jiffies;
++#else
++ u64 jiffies;
++#endif
++#if defined(CONFIG_SOC_AU1X00) || defined(CONFIG_MIPS_AU1X00) || defined(CONFIG_CPU_AU1X00) || defined(CONFIG_MIPS_AU1000) || defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_PB1100) || defined(CONFIG_ARCH_MX1ADS)
++ u64 sofs;
++#endif
++ union {
++ trace_msg_t msg;
++ trace_msg8_t msg8;
++ trace_msg16_t msg16;
++ trace_msg32_t msg32;
++
++ struct usb_device_request setup;
++ unsigned char recv[8];
++ unsigned char sent[8];
++
++ } trace;
++
++} trace_t;
++
++
++#define TRACE_MAX 10000
++
++extern int trace_first;
++extern int trace_next;
++
++extern trace_int_t *trace_ints;
++extern trace_t *traces;
++
++#ifdef CONFIG_USBD_BI_REGISTER_TRACE
++
++trace_t *TRACE_NEXT(trace_types_t trace_type);
++
++static __inline__ void TRACE_SETUP(struct usb_device_request *setup)
++{
++ if (traces) {
++ trace_t *p = TRACE_NEXT(trace_setup);
++ p->trace_type = trace_setup;
++ memcpy(&p->trace.setup, setup, sizeof(struct usb_device_request));
++ }
++}
++
++static __inline__ void TRACE_MSG(char *msg)
++{
++ if (traces) {
++ trace_t *p = TRACE_NEXT(trace_msg);
++ p->trace.msg.msg = msg;
++ }
++}
++
++static __inline__ void TRACE_W(char *msg, u32 val)
++{
++ if (traces) {
++ trace_t *p = TRACE_NEXT(trace_w);
++ p->trace.msg32.val = val;
++ p->trace.msg32.msg = msg;
++ }
++}
++
++static __inline__ void TRACE_R(char *msg, u32 val)
++{
++ if (traces) {
++ trace_t *p = TRACE_NEXT(trace_r);
++ p->trace.msg32.val = val;
++ p->trace.msg32.msg = msg;
++ }
++}
++
++static __inline__ void TRACE_MSG32(char *msg, u32 val)
++{
++ if (traces) {
++ trace_t *p = TRACE_NEXT(trace_msg32);
++ p->trace.msg32.val = val;
++ p->trace.msg32.msg = msg;
++ }
++}
++
++static __inline__ void TRACE_MSG16(char *msg, u16 val0, u16 val1)
++{
++ if (traces) {
++ trace_t *p = TRACE_NEXT(trace_msg16);
++ p->trace.msg16.val0 = val0;
++ p->trace.msg16.val1 = val1;
++ p->trace.msg16.msg = msg;
++ }
++}
++
++static __inline__ void TRACE_MSG8(char *msg, u8 val0, u8 val1, u8 val2, u8 val3)
++{
++ if (traces) {
++ trace_t *p = TRACE_NEXT(trace_msg8);
++ p->trace.msg8.val0 = val0;
++ p->trace.msg8.val1 = val1;
++ p->trace.msg8.val2 = val2;
++ p->trace.msg8.val3 = val3;
++ p->trace.msg8.msg = msg;
++ }
++}
++
++static __inline__ void TRACE_RECV(unsigned char *cp)
++{
++ if (traces) {
++ trace_t *p = TRACE_NEXT(trace_recv);
++ memcpy(&p->trace.recv, cp, 8);
++ }
++}
++
++static __inline__ void TRACE_RECVN(unsigned char *cp, int bytes)
++{
++ if (traces) {
++ trace_t *p = TRACE_NEXT(trace_recv);
++ memset(&p->trace.recv, 0, 8);
++ memcpy(&p->trace.recv, cp, bytes);
++ }
++}
++
++static __inline__ void TRACE_SENT(unsigned char *cp)
++{
++ if (traces) {
++ trace_t *p = TRACE_NEXT(trace_sent);
++ memcpy(&p->trace.sent, cp, 8);
++ }
++}
++
++#else
++
++static __inline__ void TRACE_SETUP(struct usb_device_request *setup)
++{
++}
++
++static __inline__ void TRACE_IRQS(u32 cr, u32 sr)
++{
++}
++
++static __inline__ void TRACE_RECV(unsigned char *cp)
++{
++}
++
++static __inline__ void TRACE_SENT(unsigned char *cp)
++{
++}
++
++static __inline__ void TRACE_W(char *msg, u32 val)
++{
++}
++
++static __inline__ void TRACE_R(char *msg, u32 val)
++{
++}
++
++static __inline__ void TRACE_MSG(char *msg)
++{
++}
++
++static __inline__ void TRACE_MSG32(char *msg, u32 val)
++{
++}
++
++static __inline__ void TRACE_MSG16(char *msg, u16 val0, u16 val1)
++{
++}
++
++static __inline__ void TRACE_MSG8(char *msg, u8 val0, u8 val1, u8 val2, u8 vale)
++{
++}
++static __inline__ void TRACE_RECVN(unsigned char *cp, int bytes)
++{
++}
++
++#endif
++
++int trace_init (void);
++int trace_reinit (void);
++void trace_exit (void);
++
+diff -Nru a/drivers/usbd/udc.h b/drivers/usbd/udc.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/udc.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,48 @@
++/*
++ * usbd/udc.h
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it under the terms of
++ * the GNU General Public License as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ * See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along with this program; if
++ * not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++#include <linux/kernel.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <linux/delay.h>
++#include <asm/atomic.h>
++#include <asm/irq.h>
++#include <asm/system.h>
++#include <asm/types.h>
++#include <asm/uaccess.h>
++#include <asm/io.h>
++
++#include <usbd-export.h>
++#include <usbd-build.h>
++#include <usbd-chap9.h>
++#include <usbd-mem.h>
++#include <usbd.h>
++#include <usbd-bus.h>
++#include <trace.h>
++#include <usbd-bi.h>
++
+diff -Nru a/drivers/usbd/usbd-admin.h b/drivers/usbd/usbd-admin.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-admin.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,61 @@
++/*
++ * usbd/usbd-admin.h
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++
++/*
++ * This defines the public interface to administer the USB Device Software.
++ *
++ * Specifically it allows the USB Device software to be:
++ *
++ * enabled enable a specific function driver for use
++ * disabled disable the USB Device Software
++ *
++ * disconnected disable the USB Pullup Resistor (also known as soft-connect)
++ * connected enable the USB Pullup Resistor
++ *
++ * pm_off perform required functions for Power Management off
++ * pm_on perform required functions for Power Management on
++ *
++ *
++ */
++
++int usbd_enable(char *);
++int usbd_enable_irq(char *);
++int usbd_disable(char *);
++int usbd_disable_irq(char *);
++
++int usbd_disconnect(char *);
++int usbd_connect(char *);
++int usbd_pm_on(char *);
++int usbd_pm_off(char *);
++
++#ifdef CONFIG_USBD_DEPRECATED
++int usbd_load(char *);
++int usbd_unload(char *);
++int usbd_replug(char *);
++int usbd_unplug(char *);
++#endif
++
+diff -Nru a/drivers/usbd/usbd-bi.c b/drivers/usbd/usbd-bi.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-bi.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,753 @@
++/*
++ * usbd/usbd-bi.c - USB Bus Interface Driver
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * By:
++ * Stuart Lynne <sl@belcara.com>,
++ * Tom Rushworth <tbr@belcara.com>,
++ * Bruce Balden <balden@belcara.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it under the terms of
++ * the GNU General Public License as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ * See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along with this program; if
++ * not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ * Notes
++ *
++ * 1. The usbd-bi layer has be re-implemented to re-factor the UDC layer in a way to
++ * simplify implementation of UDC drivers. As much of the complexity of dealing with the middle
++ * layers and buffer (urb) handling is provided for in the common bi layer.
++ *
++ * 2. TODO The udc interface will be further modified to allow the UDC to export a block of
++ * function pointers for the common bi layer to use. This will allow the common layer to
++ * implement default operations where the UDC does not provide an function. For example many UDC
++ * drivers do not provide full support for cable detection and usb pullup control. If these
++ * routines are not provided the common layer will supply defaults. This eliminates a reasonably
++ * larger amount of effectively unused code from many of the udc drivers.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++#include <linux/init.h>
++#include <linux/ctype.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <asm/uaccess.h>
++
++#include "usbd-chap9.h"
++#include "usbd-mem.h"
++#include "usbd.h"
++#include "usbd-bus.h"
++#include "usbd-func.h"
++#include "trace.h"
++#include "usbd-bi.h"
++#include "usbd-admin.h"
++
++#ifdef MODULE
++static char *serial_number_str;
++MODULE_PARM (serial_number_str, "s");
++MODULE_PARM_DESC (serial_number_str, "Serial Number");
++#else
++static char *serial_number_str;
++#endif
++
++struct usb_bus_instance *usbd_bus;
++int have_cable_irq;
++
++/* ******************************************************************************************* */
++
++int bi_attached (struct usb_bus_instance *bus)
++{
++ return udc_ops.attached ? udc_ops.attached () : 1;
++}
++
++int bi_connected (struct usb_bus_instance *bus)
++{
++ return udc_ops.connected ? udc_ops.connected () : 1;
++}
++
++int bi_disconnect (struct usb_bus_instance *bus, char *arg)
++{
++ RETURN_EINVAL_IF (in_interrupt ());
++ if (udc_ops.disconnect) udc_ops.disconnect ();
++ return 0;
++}
++
++int bi_connect (struct usb_bus_instance *bus, char *arg)
++{
++ RETURN_EINVAL_IF (in_interrupt ());
++ if (udc_ops.connect) udc_ops.connect ();
++ return 0;
++}
++
++int bi_request_endpoints(struct usb_endpoint_map *endpoint_map_array, int endpointsRequested,
++ struct usb_endpoint_request *requestedEndpoints)
++{
++ int i;
++ RETURN_EINVAL_IF (udc_ops.request_endpoints(endpoint_map_array, endpointsRequested, requestedEndpoints));
++ for (i = 0; i < endpointsRequested; i++) {
++ struct usb_endpoint_map *endpoint_map = endpoint_map_array + i;
++ TRACE_MSG8 ("address: %02x physical: %02x request: %02x size: %04x",
++ endpoint_map->bEndpointAddress[0], endpoint_map->physicalEndpoint[0],
++ endpoint_map->bmAttributes[0], endpoint_map->wMaxPacketSize[0]);
++ }
++ return 0;
++}
++int bi_set_endpoints(int endpointsRequested, struct usb_endpoint_map *endpoint_map_array)
++{
++ return udc_ops.set_endpoints ? udc_ops.set_endpoints(endpointsRequested, endpoint_map_array) : 0;
++}
++
++/* ******************************************************************************************* */
++/* bi_endpoint_halted - check if endpoint halted
++ * Used by the USB Device Core to check endpoint halt status.
++ */
++int bi_endpoint_halted (struct usb_bus_instance *bus, int endpoint_index)
++{
++ return udc_ops.endpoint_halted ? udc_ops.endpoint_halted(endpoint_index) : 0;
++}
++
++/* bi_device_feature - handle set/clear feature requests
++ * Used by the USB Device Core to check endpoint halt status.
++ */
++int bi_device_feature (struct usb_bus_instance *bus, int endpoint_index, int flag)
++{
++ return 0;
++}
++
++/* bi_disable_endpoints - disable udc and all endpoints
++ */
++static void bi_disable_endpoints (struct usb_bus_instance *bus)
++{
++ int i;
++ RETURN_IF (!bus || !bus->endpoint_array);
++ for (i = 1; i < udc_ops.max_endpoints; i++) {
++ struct usb_endpoint_instance *endpoint = (bus->endpoint_array + i);
++ CONTINUE_IF (!endpoint);
++ usbd_flush_endpoint (endpoint);
++ }
++}
++
++
++/* bi_device_event_irq - handle generic bus event
++ * Called by usb core layer to inform bus of an event.
++ */
++int bi_device_event_irq (struct usb_bus_instance *bus, usb_device_event_t event, int data)
++{
++ int epn;
++ int endpointsRequested = bus->function_instance->endpointsRequested;
++ struct usb_endpoint_map *endpoint_map_array = bus->function_instance->endpoint_map_array;
++
++ TRACE_MSG32 ("EVENT %x", event);
++ switch (event) {
++ case DEVICE_UNKNOWN:
++ break;
++
++ case DEVICE_INIT:
++ TRACE_MSG ("EVENT INIT");
++ break;
++
++ case DEVICE_CREATE:
++ TRACE_MSG ("EVENT CREATE");
++ bi_disable_endpoints (bus);
++ if (udc_ops.enable) udc_ops.enable ();
++ if (udc_ops.suspended_interrupts) udc_ops.suspended_interrupts ();
++ break;
++
++ case DEVICE_HUB_CONFIGURED:
++ TRACE_MSG ("EVENT HUB_CONFIGURED");
++ bi_connect (usbd_bus, NULL);
++ break;
++
++ case DEVICE_RESET:
++ TRACE_MSG ("EVENT RESET");
++ if (udc_ops.set_address) udc_ops.set_address (0);
++ if (udc_ops.reset_ep) udc_ops.reset_ep (0);
++ if (udc_ops.suspended_interrupts) udc_ops.suspended_interrupts ();
++ bi_disable_endpoints (bus);
++ break;
++
++ case DEVICE_ADDRESS_ASSIGNED:
++ TRACE_MSG ("EVENT ADDRESSED");
++ if (udc_ops.set_address) udc_ops.set_address (data);
++ if (udc_ops.all_interrupts) udc_ops.all_interrupts ();
++ break;
++
++ case DEVICE_CONFIGURED:
++ TRACE_MSG ("EVENT CONFIGURED");
++ // iterate across the physical endpoint instance array to enable the endpoints
++ if (udc_ops.setup_ep)
++ for (epn = 1; epn < bus->endpoints; epn++)
++ udc_ops.setup_ep (epn, bus->endpoint_array + epn);
++ return 0;
++
++ case DEVICE_DE_CONFIGURED:
++ TRACE_MSG ("EVENT DE-CONFIGURED");
++ break;
++
++ case DEVICE_SET_INTERFACE:
++ TRACE_MSG ("EVENT SET INTERFACE");
++ break;
++
++ case DEVICE_SET_FEATURE:
++ TRACE_MSG ("EVENT SET FEATURE");
++ break;
++
++ case DEVICE_CLEAR_FEATURE:
++ TRACE_MSG ("EVENT CLEAR FEATURE");
++ break;
++
++ case DEVICE_BUS_INACTIVE:
++ TRACE_MSG ("EVENT INACTIVE");
++ if (udc_ops.suspended_interrupts) udc_ops.suspended_interrupts (); // disable suspend interrupt
++ if (bi_attached (usbd_bus))
++ usbd_bus_event_irq (bus, DEVICE_RESET, 0);
++ break;
++
++ case DEVICE_BUS_ACTIVITY:
++ TRACE_MSG ("EVENT ACTIVITY");
++ if (udc_ops.all_interrupts) udc_ops.all_interrupts (); // enable suspend interrupt
++ break;
++
++ case DEVICE_POWER_INTERRUPTION:
++ TRACE_MSG ("POWER INTERRUPTION");
++ break;
++
++ case DEVICE_HUB_RESET:
++ TRACE_MSG ("HUB RESET");
++ break;
++
++ case DEVICE_DESTROY:
++ TRACE_MSG ("DEVICE DESTROY");
++ bi_disconnect (usbd_bus, NULL);
++ bi_disable_endpoints (bus);
++ if (udc_ops.disable_interrupts) udc_ops.disable_interrupts ();
++ if (udc_ops.disable) udc_ops.disable ();
++ break;
++
++ case DEVICE_CLOSE:
++ break;
++ }
++ return 0;
++}
++
++
++/* bi_start_endpoint_in
++ */
++int bi_start_endpoint_in (struct usb_bus_instance *bus, struct usb_endpoint_instance *endpoint)
++{
++ unsigned long flags;
++
++ //printk (KERN_INFO"%s: bus: %p status: %d\n", __FUNCTION__, bus, bus->status);
++
++ RETURN_ZERO_IF (!endpoint);
++ udc_interrupts++;
++
++ TRACE_MSG32 ("BI START ENDPOINT IN: tx_urb: %x", (int)endpoint->tx_urb);
++ local_irq_save (flags);
++ // call udc_start_endpoint_in IFF we didn't previously have a tx urb
++ if (!endpoint->tx_urb && bi_tx_next_irq (endpoint)) {
++ TRACE_MSG16 ("BI START ENDPOINT IN: bEndpointAddress: %x actual_length: %d",
++ (int)endpoint->bEndpointAddress, endpoint->tx_urb->actual_length);
++ udc_ops.start_endpoint_in (endpoint);
++ }
++ local_irq_restore (flags);
++ //printk (KERN_INFO"%s: finis\n", __FUNCTION__);
++ return 0;
++}
++
++/* bi_start_endpoint_out
++ */
++int bi_start_endpoint_out (struct usb_bus_instance *bus, struct usb_endpoint_instance *endpoint)
++{
++ unsigned long flags;
++
++ //printk (KERN_INFO"%s: bus: %p status: %d\n", __FUNCTION__, bus, bus->status);
++
++ RETURN_ZERO_IF (!endpoint);
++ udc_interrupts++;
++ TRACE_MSG32 ("BI START ENDPOINT OUT: rcv_urb: %x", (int)endpoint->rcv_urb);
++ local_irq_save (flags);
++ // call udc_start_endpoint_OUT IFF we didn't previously have a rcv urb
++ if (!endpoint->rcv_urb && bi_rcv_next_irq (endpoint)) {
++ TRACE_MSG16 ("BI START ENDPOINT OUT: bEndpointAddress: %x request_length: %d",
++ (int)endpoint->bEndpointAddress, endpoint->rcv_urb->request_length);
++ udc_ops.start_endpoint_out (endpoint);
++ }
++ local_irq_restore (flags);
++ //printk (KERN_INFO"%s: finis\n", __FUNCTION__);
++ return 0;
++}
++
++
++/* bi_cancel_urb_irq - cancel sending an urb
++ * Used by the USB Device Core to cancel an urb.
++ */
++int bi_cancel_urb_irq (struct urb *urb)
++{
++ RETURN_EINVAL_IF (!urb);
++ switch (urb->endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
++ case USB_DIR_IN:
++ //printk (KERN_INFO"%s: IN urb: %p\n", __FUNCTION__, urb);
++ // is this the active urb?
++ if (urb->endpoint->tx_urb == urb) {
++ urb->endpoint->tx_urb = NULL;
++ if (udc_ops.cancel_in_irq) udc_ops.cancel_in_irq (urb);
++ }
++ usbd_urb_sent_finished_irq (urb, SEND_FINISHED_CANCELLED);
++ break;
++
++ case USB_DIR_OUT:
++ //printk (KERN_INFO"%s: OUT urb: %p\n", __FUNCTION__, urb);
++ // is this the active urb?
++ if (urb->endpoint->rcv_urb == urb) {
++ urb->endpoint->rcv_urb = NULL;
++ if (udc_ops.cancel_out_irq) udc_ops.cancel_out_irq (urb);
++ }
++ TRACE_MSG ("CANCEL RECV URB");
++ usbd_urb_recv_finished_irq (urb, RECV_CANCELLED);
++ break;
++ }
++ return 0;
++}
++
++struct urb * bi_rcv_complete_irq (struct usb_endpoint_instance *endpoint, int len, int urb_bad)
++{
++ struct urb *rcv_urb;
++
++ // if we had an urb then update actual_length, dispatch if neccessary
++ if (likely ( (int) (rcv_urb = endpoint->rcv_urb))) {
++
++ //printk (KERN_ERR"%s: actual: %d buffer: %d\n",
++ // __FUNCTION__, rcv_urb->actual_length, rcv_urb->buffer_length);
++
++ TRACE_MSG8 ("BI RCV COMPLETE: actual: %d len: %d bad: %d: status: %d",
++ rcv_urb->actual_length, len, urb_bad, rcv_urb->status);
++
++ TRACE_MSG8 ("BI RCV COMPLETE: request: %d buffer: %d packet: %d transfer: %d",
++ rcv_urb->request_length, rcv_urb->buffer_length,
++ endpoint->wMaxPacketSize, endpoint->rcv_transferSize);
++
++ // check the urb is ok, are we adding data less than the packetsize
++ if (!urb_bad && !endpoint->rcv_error && (rcv_urb->bus->status == USBD_OK) && (len <= endpoint->wMaxPacketSize)) {
++
++ // increment the received data size
++ rcv_urb->actual_length += len;
++
++ // if the current received data is short (less than full packetsize) which
++ // indicates the end of the bulk transfer, we have received the maximum
++ // transfersize, or if we do not have enough room to receive another packet
++ // then pass this data up to the function driver
++
++ // XXX this needs to be fixed, for example the MSC driver
++ // has varying maximum sizes
++
++
++ if (
++ ( (len < endpoint->wMaxPacketSize) ||
++ (rcv_urb->actual_length >= endpoint->rcv_transferSize) ||
++ (rcv_urb->actual_length >= rcv_urb->request_length) ||
++ (rcv_urb->actual_length + endpoint->wMaxPacketSize > rcv_urb->buffer_length)))
++ {
++#if 0
++ int i;
++ for (i = 0; i < rcv_urb->actual_length; TRACE_RECV (rcv_urb->buffer + i), i+= 8);
++#endif
++ endpoint->rcv_urb = NULL;
++ rcv_urb->jiffies = jiffies;
++ rcv_urb->framenum = udc_ops.framenum ? udc_ops.framenum () : 0;
++ TRACE_MSG32 ("BI RCV COMPLETE: finished length: %d", rcv_urb->actual_length);
++ TRACE_MSG32 ("BI RCV COMPLETE: framenum: %x", (int) rcv_urb->framenum);
++ usbd_urb_recv_finished_irq (rcv_urb, RECV_OK);
++ rcv_urb = NULL;
++ }
++ }
++ else {
++ rcv_urb->actual_length = 0;
++ //endpoint->rcv_error = 1;
++ }
++ }
++
++ // if we don't have an urb see if we can get one
++ return bi_rcv_next_irq (endpoint);
++}
++
++struct urb * bi_tx_complete_irq (struct usb_endpoint_instance *endpoint, int restart)
++{
++ struct urb *tx_urb;
++
++ // if we have a tx_urb advance or reset, finish if complete
++ if ( (likely ( (int)tx_urb = endpoint->tx_urb))) {
++
++ TRACE_MSG32 ("BI TX CURRENT TX_URB: %p", (int)endpoint->tx_urb);
++ TRACE_MSG8 ("BI TX COMPLETE: actual: %d sent: %d last: %d: status: %d",
++ tx_urb->actual_length, endpoint->sent, endpoint->last, tx_urb->status);
++
++ if (likely (!restart)) {
++ int sent = endpoint->last;
++ endpoint->sent += sent;
++ endpoint->last -= sent;
++ }
++ else
++ endpoint->last = 0;
++
++ //printk (KERN_INFO"%s: act: %d last: %d sent: %d status: %d flags: %x\n", __FUNCTION__,
++ // endpoint->tx_urb->actual_length, endpoint->last, endpoint->sent,
++ // tx_urb->status, tx_urb->flags);
++
++ // XXX is the test for bEndpointAddress still appropriate for CONTROL WRITES
++ if ( ( (tx_urb->actual_length - endpoint->sent) <= 0) && ! (tx_urb->flags & USBD_URB_SENDZLP) ) {
++ //if (endpoint->bEndpointAddress)
++ tx_urb->jiffies = jiffies;
++ tx_urb->framenum = udc_ops.framenum ? udc_ops.framenum () : 0;
++ TRACE_MSG32 ("BI TX COMPLETE: finished tx_urb: %p", (int)tx_urb);
++ TRACE_MSG32 ("BI TX COMPLETE: framenum: %x", (int)tx_urb->framenum);
++ usbd_urb_sent_finished_irq (tx_urb, SEND_FINISHED_OK);
++ endpoint->tx_urb = NULL;
++ endpoint->last = endpoint->sent = 0;
++ }
++ }
++ return bi_tx_next_irq (endpoint);
++}
++
++/* ******************************************************************************************* */
++/* bi_udc_init_irq - initialize USB Device Controller
++ * Get ready to use the USB Device Controller.
++ * Register the interrupt handlers and optional IO region.
++ * Return non-zero for error.
++ */
++int bi_udc_init_irq (void)
++{
++ THROW_IF (udc_ops.request_udc_irq ? udc_ops.request_udc_irq () : 0, irq_err);
++ THROW_IF (udc_ops.request_io ? udc_ops.request_io () : 0, io_err);
++ THROW_IF (udc_ops.init ? udc_ops.init () : 0, init_err);
++ CATCH (irq_err) {
++ printk (KERN_ERR"%s: could not request USB IRQ\n", __FUNCTION__);
++ CATCH (io_err) {
++ CATCH (init_err) {
++ printk (KERN_ERR"%s: could not request USB IO space\n", __FUNCTION__);
++ if (udc_ops.release_io) udc_ops.release_io ();
++ }
++ if (udc_ops.release_udc_irq) udc_ops.release_udc_irq ();
++ }
++ printk (KERN_ERR"%s: error\n", __FUNCTION__);
++ return -EINVAL;
++ }
++ return 0;
++}
++
++
++/* bi_udc_exit - Stop using the USB Device Controller
++ * Stop using the USB Device Controller.
++ * Shutdown and free dma channels, de-register the interrupt handler.
++ */
++void bi_udc_exit (struct usb_bus_instance *bus)
++{
++ if (udc_ops.disable_ep) udc_ops.disable_ep (0);
++ bi_disable_endpoints (bus);
++ bi_disconnect (usbd_bus, NULL);
++ if (udc_ops.disable) udc_ops.disable ();
++ if (udc_ops.release_io) udc_ops.release_io ();
++ if (udc_ops.release_udc_irq) udc_ops.release_udc_irq ();
++}
++
++
++/* ************************************************************************************* */
++
++int bus_disable (struct usb_bus_instance *bus, char *arg);
++int bus_enable (struct usb_bus_instance *bus, char *arg);
++
++int bi_pm_off (struct usb_bus_instance *bus, char *arg)
++{
++ //printk (KERN_INFO"%s:\n", __FUNCTION__);
++ RETURN_EINVAL_IF (in_interrupt ());
++ return bus_disable (bus, arg);
++}
++
++int bi_pm_on (struct usb_bus_instance *bus, char *arg)
++{
++ //printk (KERN_INFO"%s:\n", __FUNCTION__);
++ RETURN_EINVAL_IF (in_interrupt ());
++ return bi_attached (usbd_bus) ? bus_enable (bus, arg) : 0;
++}
++
++int bi_fix_serial_number_str (struct usb_bus_instance *bus)
++{
++ char *sp, *dp;
++ for (sp = dp = usbd_bus->serial_number_str; sp && sp[0]; sp++) {
++ CONTINUE_IF (!isxdigit (sp[0]));
++ *dp++ = toupper (*sp);
++ }
++ if (dp)
++ *dp = '\0';
++ return 0;
++}
++
++int bi_serial_number (struct usb_bus_instance *bus, char *arg)
++{
++ char *sp, *dp;
++ RETURN_EINVAL_IF (in_interrupt ());
++ if (usbd_bus->serial_number_str)
++ lkfree (usbd_bus->serial_number_str);
++ usbd_bus->serial_number_str = lstrdup (arg);
++ bi_fix_serial_number_str (bus);
++ return 0;
++}
++
++
++/* ******************************************************************************************* */
++
++struct usb_bus_operations bi_ops = {
++ bus_enable: bus_enable,
++ bus_disable: bus_disable,
++ bus_pm_off: bi_pm_off,
++ bus_pm_on: bi_pm_on,
++ bus_serial_number: bi_serial_number,
++ start_endpoint_in: bi_start_endpoint_in,
++ start_endpoint_out: bi_start_endpoint_out,
++ cancel_urb_irq: bi_cancel_urb_irq,
++ endpoint_halted: bi_endpoint_halted,
++ device_feature: bi_device_feature,
++ device_event: bi_device_event_irq,
++ bus_disconnect: bi_disconnect,
++ bus_connect: bi_connect,
++ bus_attached: bi_attached,
++ bus_connected: bi_connected,
++ request_endpoints: bi_request_endpoints,
++ set_endpoints: bi_set_endpoints,
++};
++
++
++struct usb_bus_driver bi_driver = {
++ bops: &bi_ops,
++};
++
++void bi_cable_event_irq (void)
++{
++ (bi_attached (usbd_bus) ? usbd_enable_irq : usbd_disable_irq) (NULL);
++}
++
++void bi_cable_event (void)
++{
++ unsigned long flags;
++ local_irq_save (flags);
++ bi_cable_event_irq ();
++ local_irq_restore (flags);
++}
++
++
++/* Prevent overlapp of bi administrative functions mainly:
++ * bus_enable
++ * bus_disable
++ * bi_modinit
++ * bi_modexit
++ */
++DECLARE_MUTEX (usbd_bi_sem);
++
++int bus_disable_sem (struct usb_bus_instance *bus, char *arg)
++{
++ struct bi_data *data;
++ unsigned long flags;
++
++ RETURN_ZERO_IF (usbd_bus_state_enabled != bus->bus_state);
++ MOD_DEC_USE_COUNT;
++
++ bi_disconnect (usbd_bus, NULL);
++ if (udc_ops.disable) udc_ops.disable ();
++
++ local_irq_save (flags);
++ if (bus->device_state != STATE_ATTACHED) {
++ usbd_bus_event_irq (bus, DEVICE_RESET, 0);
++ usbd_bus_event_irq (bus, DEVICE_POWER_INTERRUPTION, 0);
++ usbd_bus_event_irq (bus, DEVICE_HUB_RESET, 0);
++ }
++ usbd_bus_event_irq (bus, DEVICE_DESTROY, 0);
++ bi_disable_endpoints (bus);
++ bi_udc_exit (bus);
++ local_irq_restore (flags);
++
++ usbd_disable_function (bus);
++ bus->bus_state = usbd_bus_state_disabled;
++ return 0;
++}
++
++int bus_disable (struct usb_bus_instance *bus, char *arg)
++{
++ RETURN_EINVAL_IF (in_interrupt ());
++ down (&usbd_bi_sem);
++ bus_disable_sem (bus, arg);
++ up (&usbd_bi_sem);
++ return 0;
++}
++
++void bi_startup_events(void)
++{
++ if (udc_ops.startup_events)
++ udc_ops.startup_events();
++ else {
++ usbd_bus_event_irq (usbd_bus, DEVICE_INIT, 0);
++ usbd_bus_event_irq (usbd_bus, DEVICE_CREATE, 0);
++ usbd_bus_event_irq (usbd_bus, DEVICE_HUB_CONFIGURED, 0);
++ usbd_bus_event_irq (usbd_bus, DEVICE_RESET, 0);
++ }
++}
++
++int bus_enable (struct usb_bus_instance *bus, char *arg)
++{
++ struct usb_endpoint_instance *endpoint;
++ int rc = -EINVAL;
++ unsigned long flags;
++
++ //printk (KERN_INFO "%s: %s bus_state: %d\n", __FUNCTION__, arg ? arg : " (NULL)", bus->bus_state);
++ RETURN_EINVAL_IF (in_interrupt ());
++
++ down (&usbd_bi_sem);
++ bus_disable_sem (bus, arg);
++ MOD_INC_USE_COUNT;
++
++ local_irq_save (flags);
++ do {
++ // check if we can see the UDC and register, then enable the function
++ BREAK_IF (bi_udc_init_irq ());
++ BREAK_IF (usbd_enable_function_irq (bus, arg));
++ rc = 0;
++
++ // setup endpoint zero
++ endpoint = bus->endpoint_array + 0;
++ endpoint->bEndpointAddress = 0;
++
++ //endpoint->tx_attributes = 0;
++ endpoint->wMaxPacketSize = udc_ops.ep0_packetsize;
++ endpoint->rcv_transferSize = 255; // XXX should this be higher
++ endpoint->wMaxPacketSize = udc_ops.ep0_packetsize;
++ if (udc_ops.setup_ep) udc_ops.setup_ep (0, endpoint);
++
++ // hopefully device enumeration will finish this process
++ bi_startup_events ();
++ trace_reinit ();
++ } while (0);
++ local_irq_restore (flags);
++ up (&usbd_bi_sem);
++
++ //printk (KERN_INFO"%s: finis\n", __FUNCTION__);
++ if (rc) {
++ printk (KERN_INFO "%s: failed\n", __FUNCTION__);
++ bi_udc_exit (NULL);
++ }
++ return rc;
++}
++
++/* ************************************************************************************* */
++
++static int bi_modinit (void)
++{
++ extern const char *usbd_bi_module_info (void);
++ //struct bi_data *data = NULL;
++ static int first = 0;
++
++ printk (KERN_INFO "%s: %s serial: \"%s\"\n", __FUNCTION__, usbd_bi_module_info (),
++ serial_number_str && strlen (serial_number_str) ? serial_number_str : "");
++
++ down (&usbd_bi_sem);
++
++ THROW_IF (trace_init (), error);
++ THROW_IF (usbd_bus, error);
++
++ // Set the UDC defaults
++ udc_ops.disable_interrupts ();
++ bi_disconnect (usbd_bus, NULL);
++
++ bi_driver.name = udc_ops.name;
++ bi_driver.max_endpoints = udc_ops.max_endpoints;
++ bi_driver.maxpacketsize = udc_ops.ep0_packetsize;
++
++ // register this bus interface driver and create the device driver instance
++ THROW_IF (! (usbd_bus = usbd_register_bus (&bi_driver)), error);
++
++ //THROW_IF (! (data = ckmalloc (sizeof (struct bi_data), GFP_KERNEL)), error);
++ //memset (data, 0, sizeof (struct bi_data));
++ //usbd_bus->privdata = data;
++
++ // see if we can scrounge up something to set a sort of unique device address
++ if (udc_ops.serial_init ? udc_ops.serial_init () : -EINVAL) {
++ if (serial_number_str && strlen (serial_number_str))
++ bi_serial_number (usbd_bus, serial_number_str);
++ }
++ else
++ bi_fix_serial_number_str (usbd_bus);
++
++ have_cable_irq = udc_ops.request_cable_irq ? !udc_ops.request_cable_irq () : 0;
++ up (&usbd_bi_sem);
++
++#if defined (MODULE) || !defined (CONFIG_USBD_BI_DELAY_ENABLE)
++ // if we are connected OR if we don't have a cable irq fake an attach event
++
++ // XXX this is not quite correct, if not attached then an enable
++ // will be required later if attached on a system that does not have
++ // cable event.
++ //
++ //if (!have_cable_irq || udc_attached ()) {
++ // Even if we have a cable irq, we need to check the current status,
++ // because the cable may have been attached before we installed the handler.
++
++ if (bi_attached (usbd_bus)) {
++ printk (KERN_INFO"%s: cable attached\n", __FUNCTION__);
++ bi_cable_event ();
++ }
++#endif
++ return 0;
++
++ CATCH (error) {
++ printk (KERN_ERR"%s: error loading module\n", __FUNCTION__);
++ //if (data)
++ // lkfree (data);
++ if (usbd_bus)
++ usbd_deregister_bus (usbd_bus);
++ usbd_bus = NULL;
++ trace_exit ();
++ up (&usbd_bi_sem);
++ printk (KERN_INFO"%s: UP\n", __FUNCTION__);
++ return -EINVAL;
++ }
++}
++
++#ifdef MODULE
++/* bi_modexit - This is *only* used for drivers compiled and used as a module.
++ */
++static void bi_modexit (void)
++{
++ down (&usbd_bi_sem);
++ RETURN_IF (!usbd_bus);
++
++ if (have_cable_irq)
++ udc_ops.release_cable_irq ();
++
++ bus_disable_sem (usbd_bus, NULL);
++
++ //if ( (usbd_bus->privdata))
++ // lkfree (usbd_bus->privdata);
++ //usbd_bus->privdata = NULL;
++
++ if (usbd_bus->serial_number_str)
++ lkfree (usbd_bus->serial_number_str);
++
++ usbd_deregister_bus (usbd_bus);
++ usbd_bus = NULL;
++ trace_exit ();
++}
++
++module_exit (bi_modexit);
++#endif
++
++module_init (bi_modinit);
++
+diff -Nru a/drivers/usbd/usbd-bi.h b/drivers/usbd/usbd-bi.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-bi.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,196 @@
++/*
++ * usbd/usbd-bi.h
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it under the terms of
++ * the GNU General Public License as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ * See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along with this program; if
++ * not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++struct udc_ops {
++
++ /* mandatory */
++ int max_endpoints;
++ int ep0_packetsize;
++ char *name;
++
++ void (*start_endpoint_in)
++ (struct usb_endpoint_instance *); /* start an IN urb */
++ void (*start_endpoint_out)
++ (struct usb_endpoint_instance *); /* start an OUT urb */
++
++ int (*request_endpoints)
++ (struct usb_endpoint_map *, int, struct usb_endpoint_request *);
++
++ /* optional */
++
++ int (*set_endpoints)
++ (int , struct usb_endpoint_map *);
++
++ void (*cancel_in_irq) (struct urb *urb); /* cancel active urb for IN endpoint */
++ void (*cancel_out_irq) (struct urb *urb); /* cancel active urb for OUT endpoint */
++
++ void (*reset_ep) (unsigned int ep); /* reset requested endpoint */
++ int (*endpoint_halted) (unsigned int ep); /* Return non-zero if requested endpoint is halted */
++
++ void (*set_address) (unsigned char address);/* set the device USB address */
++ int (* serial_init) (void); /* get device serial number if available */
++ void (*setup_ep) (unsigned int ep,
++ struct usb_endpoint_instance *endpoint); /* setup specified endpoint for use */
++ void (*disable_ep) (unsigned int ep); /* disable specified endpoint */
++ void (*stall_ep) (u32 ); /* stall endpoint */
++
++ int (*attached) (void); /* return non-zero if the USB cable connected */
++ int (*connected) (void); /* return non-zero if the USB pullup resistor is enabled */
++ void (*connect) (void); /* enable USB pullup resistor to enable connection to host */
++ void (*disconnect) (void); /* disable pullup resistor to disconnect from host */
++
++ int (*framenum) (void); /* fetch SOF framenum */
++
++ void (*all_interrupts) (void); /* enable all interrupts for normal operation */
++ void (*suspended_interrupts) (void); /* enable interrupts for suspended operation */
++ void (*disable_interrupts) (void); /* disable all interrupts */
++
++ void (*enable) (void); /* enable the UDC */
++ void (*disable) (void); /* disable the UDC */
++
++ void (*startup_events) (void); /* perform UDC specific USB events */
++ int (*init) (void); /* initialize USB Device Controller */
++
++ int (*request_udc_irq) (void); /* return non-zero if request for UDC interrupt fails */
++ int (*request_cable_irq) (void); /* return non-zero if request for Cable interrupt fails */
++ int (*request_io) (void); /* return non-zero if request UDC IO region fails */
++ void (*release_udc_irq) (void); /* release USB Device Controller interrupt */
++ void (*release_cable_irq) (void); /* release Cable interrupt */
++ void (*release_io) (void); /* release UDC IO region */
++};
++
++extern struct udc_ops udc_ops;
++extern unsigned int udc_interrupts;
++extern struct usb_bus_instance *usbd_bus;
++
++void bi_cable_event_irq (void); /* called from cradle interrupt handler */
++void bi_cable_event (void);
++
++/* bi_rcv_next_irq - complete a receive
++ * Called from rcv interrupt to complete.
++ */
++static __inline__ struct urb * bi_rcv_next_irq (struct usb_endpoint_instance *endpoint)
++{
++ if (!endpoint->rcv_urb)
++ if ( (endpoint->rcv_urb = usbd_first_urb_detached_irq (&endpoint->rdy)))
++ endpoint->rcv_urb->status = RECV_IN_PROGRESS;
++ TRACE_MSG32 ("BI RCV_URB: %p", (int)endpoint->rcv_urb);
++ return endpoint->rcv_urb;
++}
++
++
++/* bi_rcv_complete_irq - complete a receive
++ * Called from rcv interrupt to complete.
++ */
++struct urb * bi_rcv_complete_irq (struct usb_endpoint_instance *endpoint, int len, int urb_bad);
++
++static __inline__ void bi_rcv_cancelled_irq (struct usb_endpoint_instance *endpoint)
++{
++ struct urb *rcv_urb;
++
++ TRACE_MSG32 ("BI RCV CANCELLED: %p", (int) endpoint->rcv_urb);
++ RETURN_IF (! (rcv_urb = endpoint->rcv_urb));
++ printk (KERN_INFO"%s: rcv_urb: %p\n", __FUNCTION__, endpoint->rcv_urb);
++ usbd_urb_recv_finished_irq (rcv_urb, RECV_CANCELLED);
++ endpoint->sent = endpoint->last = 0;
++ endpoint->rcv_urb = NULL;
++ printk (KERN_INFO"%s: rcv_urb: %p\n", __FUNCTION__, endpoint->rcv_urb);
++}
++
++
++/* bi_tx_next_irq - complete a receive
++ * Called from tx interrupt to complete.
++ */
++static __inline__ struct urb * bi_tx_next_irq (struct usb_endpoint_instance *endpoint)
++{
++ if (!endpoint->tx_urb)
++ if ( (endpoint->tx_urb = usbd_first_urb_detached_irq (&endpoint->tx))) {
++#if 0
++ int i;
++ TRACE_MSG16 ("NEXT TX: length: %d flags: %x", endpoint->tx_urb->actual_length, endpoint->tx_urb->flags);
++ for (i = 0; i < endpoint->tx_urb->actual_length; TRACE_SENT (endpoint->tx_urb->buffer + i), i+= 8);
++#endif
++ endpoint->tx_urb->status = SEND_IN_PROGRESS;
++ }
++ TRACE_MSG32 ("BI TX NEXT TX_URB: %p", (int)endpoint->tx_urb);
++ return endpoint->tx_urb;
++}
++
++
++/* bi_tx_complete_irq - complete a transmit
++ * Called from tx interrupt to complete.
++ */
++struct urb * bi_tx_complete_irq (struct usb_endpoint_instance *endpoint, int restart);
++
++static __inline__ void bi_tx_cancelled_irq (struct usb_endpoint_instance *endpoint)
++{
++ struct urb *tx_urb;
++
++ TRACE_MSG32 ("BI TX CANCELLED: %p", (int) endpoint->tx_urb);
++ RETURN_IF (! (tx_urb = endpoint->tx_urb));
++ usbd_urb_sent_finished_irq (tx_urb, SEND_FINISHED_CANCELLED);
++ endpoint->sent = endpoint->last = 0;
++ endpoint->tx_urb = NULL;
++}
++
++static __inline__ int bi_tx_sendzlp (struct usb_endpoint_instance *endpoint)
++{
++ struct urb *tx_urb = endpoint->tx_urb;
++ RETURN_ZERO_IF (!tx_urb || (tx_urb->actual_length != endpoint->sent) || ! (tx_urb->flags & USBD_URB_SENDZLP));
++ tx_urb->flags &= ~USBD_URB_SENDZLP;
++ return 1;
++}
++
++/* bi_rcv_complete_irq - complete a receive
++ * Called from rcv interrupt to complete.
++ */
++static __inline__ void bi_rcv_fast_complete_irq (struct usb_endpoint_instance *endpoint, struct urb *rcv_urb)
++{
++ TRACE_MSG32 ("BI RCV FAST COMPLETE: %d", rcv_urb->actual_length);
++ usbd_urb_recv_finished_irq (rcv_urb, RECV_OK);
++}
++
++/* bi_recv_setup - process a device request
++ * Note that we verify if a receive urb has been queued for H2D with non-zero wLength
++ * and return -EINVAL to stall if the upper layers have not properly tested for and
++ * setup a receive urb in this case.
++ */
++static __inline__ int bi_recv_setup_irq (struct usb_device_request *request)
++{
++ struct usb_endpoint_instance *endpoint = usbd_bus->endpoint_array + 0;
++ TRACE_SETUP (request);
++ RETURN_EINVAL_IF (usbd_recv_setup_irq (usbd_bus->ep0, request)); // fail if already failed
++ RETURN_ZERO_IF ( (request->bmRequestType & USB_REQ_DIRECTION_MASK) == USB_REQ_DEVICE2HOST);
++ RETURN_ZERO_IF (!le16_to_cpu (request->wLength));
++ RETURN_EINVAL_IF (!endpoint->rcv_urb);
++ return 0;
++}
++
++/* bi_ep0_reset_irq - reset ep0 endpoint
++ */
++static void __inline__ bi_ep0_reset_endpoint_irq (struct usb_endpoint_instance *endpoint)
++{
++ bi_tx_cancelled_irq (endpoint);
++ bi_rcv_cancelled_irq (endpoint);
++ endpoint->sent = endpoint->last = 0;
++}
+diff -Nru a/drivers/usbd/usbd-bops.c b/drivers/usbd/usbd-bops.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-bops.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,889 @@
++/*
++ * usbd/usbd-bops.c - USB Device Prototype
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2000, 2001, 2002 Lineo
++ * Copyright (c) 2001 Hewlett Packard
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <asm/uaccess.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++#include <linux/smp_lock.h>
++#include <linux/ctype.h>
++#include <linux/timer.h>
++#include <linux/string.h>
++
++#include "usbd-chap9.h"
++#include "usbd-mem.h"
++#include "usbd.h"
++#include "usbd-func.h"
++#include "usbd-bus.h"
++
++/* Private defs from usbd-func.c *************************************************************** */
++/* Function driver enable/disable
++ *
++ * Called by usbd_enable_function/usbd_disable_function to call the selected
++ * function drivers function_enable or function_disable function.
++ */
++int usbd_function_enable (struct usb_bus_instance *, struct usb_function_instance *);
++void usbd_function_disable(struct usb_function_instance *);
++void usbd_func_event_irq(struct usb_bus_instance *, struct usb_function_instance *, usb_device_event_t , int );
++int usbd_strings_init (void);
++void usbd_strings_exit(void);
++void usbd_urb_callback (struct urb *urb, int rc);
++
++/* List support functions ******************************************************************** */
++
++/*
++ * Structure member address manipulation macros.
++ * These are used by client code (code using the urb_link routines), since
++ * the urb_link structure is embedded in the client data structures.
++ *
++ * Note: a macro offsetof equivalent to member_offset is defined in stddef.h
++ * but this is kept here for the sake of portability.
++ *
++ * p2surround returns a pointer to the surrounding structure given
++ * type of the surrounding structure, the name memb of the structure
++ * member pointed at by ptr. For example, if you have:
++ *
++ * struct foo {
++ * int x;
++ * float y;
++ * char z;
++ * } thingy;
++ *
++ * char *cp = &thingy.z;
++ *
++ * then
++ * &thingy == p2surround(struct foo, z, cp)
++ */
++
++#define _cv_(ptr) ((char*)(void*)(ptr))
++#define member_offset(type,memb) (_cv_(&(((type*)0)->memb))-(char*)0)
++#define p2surround(type,memb,ptr) ((type*)(void*)(_cv_(ptr)-member_offset(type,memb)))
++
++static inline struct usb_function_driver *list_entry_function (const struct list_head *le)
++{
++ return list_entry (le, struct usb_function_driver, drivers);
++}
++
++
++/*
++ * Append an urb_link (or a whole list of
++ * urb_links) to the tail of another list
++ * of urb_links.
++ */
++static __inline__ void urb_append_irq (urb_link * hd, struct urb *urb)
++{
++ if (hd && urb) {
++ urb_link *new = &urb->link;
++
++#ifdef C2L_SINGLETON_ONLY
++ // This _assumes_ the new urb is a singleton,
++ // but allows it to have an uninitialized link.
++ //printk(KERN_DEBUG"urb_append: hd: %p n:%p p:%p new: %p n:%p p:%p\n", hd, hd->next, hd->prev, new, new->next, new->prev);
++
++ new->prev = hd->prev;
++ new->next = hd;
++
++ hd->prev->next = new;
++ hd->prev = new;
++#else
++ // This allows the new urb to be a list of urbs,
++ // with new pointing at the first, but the link
++ // must be initialized.
++ // Order is important here...
++ urb_link *pul = hd->prev;
++ new->prev->next = hd;
++ hd->prev = new->prev;
++ new->prev = pul;
++ pul->next = new;
++#endif
++ }
++}
++
++/*
++ * Return the first urb_link in a list with a distinguished
++ * head "hd", or NULL if the list is empty. This will also
++ * work as a predicate, returning NULL if empty, and non-NULL
++ * otherwise.
++ *
++ * Called from interrupt.
++ */
++static __inline__ urb_link *first_urb_link_irq (urb_link * hd)
++{
++ urb_link *nx;
++ return (!hd || !(nx = hd->next) || (nx == hd)) ? NULL : nx;
++}
++
++/*
++ * Return the first urb in a list with a distinguished
++ * head "hd", or NULL if the list is empty.
++ *
++ * Called from interrupt.
++ */
++static __inline__ struct urb *first_urb_irq (urb_link * hd)
++{
++ urb_link *nx;
++ return (!(nx = first_urb_link_irq (hd))) ? NULL : p2surround (struct urb, link, nx);
++}
++
++/*
++ * Detach and return the first urb in a list with a distinguished
++ * head "hd", or NULL if the list is empty.
++ */
++struct urb *usbd_first_urb_detached_irq (urb_link * hd)
++{
++ struct urb *urb;
++ urb_link *ul;
++ RETURN_NULL_IF (!(urb = first_urb_irq (hd)));
++ ul = &urb->link;
++ ul->next->prev = ul->prev;
++ ul->prev->next = ul->next;
++ ul->prev = ul->next = ul;
++ return urb;
++}
++
++static __inline__ void urb_append(urb_link *hd, struct urb *urb)
++{
++ unsigned long flags;
++ local_irq_save (flags);
++ urb_append_irq(hd, urb);
++ local_irq_restore (flags);
++}
++
++/* usbd_urb_sent_finished_irq - tell function that an urb has been transmitted.
++ *
++ * Must be called from an interrupt or with interrupts disabled.
++ *
++ * Used by a USB Bus driver to pass a sent urb back to the function
++ * driver via the endpoints done queue.
++ */
++void usbd_urb_sent_finished_irq (struct urb *urb, int rc)
++{
++ //printk(KERN_INFO"%s: urb: %p\n", __FUNCTION__, urb);
++ urb->status = rc;
++ urb->jiffies = jiffies;
++ if (USBD_OK != urb->bus->status)
++ usbd_urb_callback(urb, urb->status);
++ else {
++ urb_append_irq (&(urb->endpoint->done), urb);
++ RETURN_IF ( urb->bus->device_bh.sync);
++ queue_task (&urb->bus->device_bh, &tq_immediate);
++ mark_bh (IMMEDIATE_BH);
++ }
++}
++
++
++/* usbd_urb_recv_finished_irq - tell function that an urb has been received.
++ *
++ * Must be called from an interrupt or with interrupts disabled.
++ *
++ * Used by a USB Bus driver to pass a sent urb back to the function
++ * driver via the endpoints done queue.
++ */
++void usbd_urb_recv_finished_irq (struct urb *urb, int rc)
++{
++ urb->status = rc;
++ urb->jiffies = jiffies;
++ if (USBD_OK != urb->bus->status)
++ usbd_urb_callback (urb, rc);
++ else {
++ urb_append_irq (&(urb->endpoint->rcv), urb);
++ RETURN_IF (urb->bus->device_bh.sync);
++ queue_task (&urb->bus->device_bh, &tq_immediate);
++ mark_bh (IMMEDIATE_BH);
++ }
++}
++
++
++/* first_urb_detached -
++ *
++ * Detach and return the first urb in a list with a distinguished
++ * head "hd", or NULL if the list is empty.
++ *
++ */
++static __inline__ struct urb *first_urb_detached (urb_link * hd)
++{
++ struct urb *urb;
++ unsigned long flags;
++ local_irq_save (flags);
++ urb = usbd_first_urb_detached_irq (hd);
++ local_irq_restore (flags);
++ return urb;
++}
++
++
++/* Private defs from usbd-fops.c *************************************************************** */
++
++
++extern struct usb_function_driver ep0_driver;
++extern struct list_head usbd_function_drivers;
++extern struct usb_bus_instance *usbd_bus_instance;
++
++#define LANGID_ENGLISH "\011"
++#define LANGID_US_ENGLISH "\004"
++#define LANGIDs LANGID_US_ENGLISH LANGID_ENGLISH
++
++/* usbd_flush_endpoint_irq - flush urbs from endpoint
++ *
++ * Iterate across the approrpiate tx or rcv list and cancel any outstanding urbs.
++ */
++void usbd_flush_endpoint_irq (struct usb_endpoint_instance *endpoint)
++{
++ struct urb *urb;
++ //printk(KERN_INFO"%s: bEndpointAddress: %d\n", __FUNCTION__, endpoint->bEndpointAddress);
++ if ((urb = endpoint->tx_urb))
++ usbd_cancel_urb_irq(urb);
++
++ for (; (urb = usbd_first_urb_detached_irq (&endpoint->tx)); usbd_cancel_urb_irq(urb));
++
++ if ((urb = endpoint->rcv_urb))
++ usbd_cancel_urb_irq(urb);
++
++ for (; (urb = usbd_first_urb_detached_irq (&endpoint->rdy)); usbd_cancel_urb_irq(urb));
++}
++
++/* usbd_flush_endpoint - flush urbs from endpoint
++ *
++ * Iterate across the approrpiate tx or rcv list and cancel any outstanding urbs.
++ */
++void usbd_flush_endpoint (struct usb_endpoint_instance *endpoint)
++{
++ unsigned long flags;
++ local_irq_save (flags);
++ usbd_flush_endpoint_irq(endpoint);
++ local_irq_restore (flags);
++}
++
++/* usbd_endpoint_halted
++ *
++ * Return non-zero if endpoint is halted.
++ */
++int usbd_endpoint_halted (struct usb_function_instance *function, int endpoint)
++{
++ //printk(KERN_INFO"%s:\n", __FUNCTION__);
++ return function->bus->driver->bops->endpoint_halted (function->bus, endpoint);
++}
++
++
++/* usbd_device_feature - set usb device feature
++ *
++ * Return non-zero if error
++ */
++int usbd_device_feature (struct usb_function_instance *function, int endpoint, int feature)
++{
++ //printk(KERN_INFO"%s:\n", __FUNCTION__);
++ return function->bus->driver->bops->device_feature (function->bus, endpoint, feature);
++}
++
++/* usbd_cancel_urb_irq - cancel an urb being sent
++ *
++ * Return non-zero if error
++ */
++int usbd_cancel_urb_irq (struct urb *urb)
++{
++ //printk(KERN_INFO"%s: urb: %p\n", __FUNCTION__, urb);
++ // XXX should we do usbd_dealloc_urb(urb);
++ return urb->bus->driver->bops->cancel_urb_irq (urb);
++}
++
++/* usbd_send_urb - submit a urb to send
++ *
++ * Used by a USB Function driver to submit data to be sent in an urb to the
++ * appropriate USB Bus driver via the endpoints transmit queue.
++ *
++ * Return non-zero if error
++ */
++int usbd_send_urb (struct urb *urb)
++{
++ //printk(KERN_INFO"%s: urb: %p length: %d\n", __FUNCTION__, urb, urb->actual_length);
++ //RETURN_EINVAL_IF (USBD_OK != urb->bus->status);
++ RETURN_EINVAL_IF (urb->endpoint->bEndpointAddress && (USBD_OK != urb->bus->status));
++ urb->status = SEND_IN_QUEUE;
++ urb->jiffies = jiffies;
++ urb_append (&(urb->endpoint->tx), urb);
++ return urb->bus->driver->bops->start_endpoint_in(urb->bus, urb->endpoint);
++}
++
++/* usbd_start_recv - recycle a received urb
++ *
++ * Used by a USB Function interface driver to recycle an urb.
++ *
++ * Return non-zero if error
++ */
++int usbd_start_recv (struct urb *urb)
++{
++ //printk(KERN_INFO"%s: urb: %p\n", __FUNCTION__, urb);
++ RETURN_EINVAL_IF (urb->endpoint->bEndpointAddress && (USBD_OK != urb->bus->status));
++ urb->actual_length = 0;
++ urb->status = RECV_IN_QUEUE;
++ urb->jiffies = jiffies;
++ urb_append (&(urb->endpoint->rdy), urb);
++ urb->bus->driver->bops->start_endpoint_out(urb->bus, urb->endpoint);
++ //printk(KERN_INFO"%s: finis\n", __FUNCTION__, urb);
++ return 0;
++}
++
++/* usbd_alloc_string_zero - allocate a string descriptor and return index number
++ *
++ * Find an empty slot in index string array, create a corresponding descriptor
++ * and return the slot number.
++ */
++__u8 usbd_alloc_string_zero (char *str)
++{
++ __u8 bLength;
++ __u16 *wData;
++ struct usb_string_descriptor *string;
++
++ RETURN_ZERO_IF(usb_strings[0] != NULL);
++
++ bLength = sizeof (struct usb_string_descriptor) + strlen (str);
++
++ RETURN_ZERO_IF(!(string = ckmalloc (bLength, GFP_KERNEL)));
++
++ string->bLength = bLength;
++ string->bDescriptorType = USB_DT_STRING;
++
++ for (wData = string->wData; *str; str += 2) {
++ *wData = (__u16) ((str[0] << 8 | str[1]));
++ wData++;
++ }
++ usb_strings[0] = string; // store in string index array
++ return 0;
++}
++
++
++int usbd_strings_init (void)
++{
++ //printk(KERN_INFO"%s: usb_strings: %p\n", __FUNCTION__, usb_strings);
++ RETURN_ZERO_IF(usb_strings);
++ usbd_maxstrings = MIN(usbd_maxstrings, 254);
++
++ RETURN_EINVAL_IF (!(usb_strings = ckmalloc (sizeof (struct usb_string_descriptor *) * usbd_maxstrings, GFP_KERNEL)));
++ if (usbd_alloc_string_zero (LANGIDs) != 0) {
++ lkfree (usb_strings);
++ return -1;
++ }
++ return 0;
++}
++
++void usbd_strings_exit(void)
++{
++ int i;
++ //printk(KERN_INFO"%s: usb_strings: %p\n", __FUNCTION__, usb_strings);
++ RETURN_IF (!usb_strings);
++ for (i = 0; i < usbd_maxstrings; i++)
++ usbd_dealloc_string(i);
++ lkfree (usb_strings);
++ usb_strings = NULL;
++}
++
++static usb_device_state_t event_states[DEVICE_CLOSE] = {
++ STATE_UNKNOWN, STATE_INIT, STATE_ATTACHED, STATE_POWERED,
++ STATE_DEFAULT, STATE_ADDRESSED, STATE_CONFIGURED, STATE_UNKNOWN,
++ STATE_UNKNOWN, STATE_UNKNOWN, STATE_ADDRESSED, STATE_SUSPENDED,
++ STATE_UNKNOWN, STATE_POWERED, STATE_ATTACHED,
++};
++
++static usb_device_status_t event_status[DEVICE_CLOSE+1] = {
++ USBD_UNKNOWN, // DEVICE_UNKNOWN
++ USBD_OPENING, // DEVICE_INIT
++ USBD_OPENING, // DEVICE_CREATE
++ USBD_OPENING, // DEVICE_HUB_CONFIGURED
++ USBD_RESETING, // DEVICE_RESET
++ USBD_OK, // DEVICE_ADDRESS_ASSIGNED
++ USBD_OK, // DEVICE_CONFIGURED
++ USBD_OK, // DEVICE_SET_INTERFACE
++ USBD_OK, // DEVICE_SET_FEATURE
++ USBD_OK, // DEVICE_CLEAR_FEATURE
++ USBD_OK, // DEVICE_DE_CONFIGURED
++ USBD_SUSPENDED, // DEVICE_BUS_INACTIVE
++ USBD_OK, // DEVICE_BUS_ACTIVITY
++ USBD_RESETING, // DEVICE_POWER_INTERRUPTION
++ USBD_RESETING, // DEVICE_HUB_RESET
++ USBD_CLOSING, // DEVICE_DESTROY
++ USBD_CLOSED, // DEVICE_CLOSE
++};
++
++/* usbd_device_event_irq - called to respond to various usb events
++ *
++ * Used by a Bus driver to indicate an event.
++ */
++void usbd_bus_event_irq (struct usb_bus_instance *bus, usb_device_event_t event, int data)
++{
++ RETURN_IF(!bus);
++
++ //printk(KERN_INFO"%s:\n", __FUNCTION__);
++ //printk(KERN_INFO"%s: --> event: %d status: %d state: %d\n", __FUNCTION__, event, bus->status, bus->device_state);
++ switch (event) {
++ case DEVICE_BUS_INACTIVE:
++ bus->suspended_state = bus->device_state;
++ //printk(KERN_INFO"%s: INACTIVE\n", __FUNCTION__);
++ /* FALL THROUGH */
++ default:
++ bus->device_state = event_states[event];
++ //printk(KERN_INFO"%s: DEFAUL\n", __FUNCTION__);
++ break;
++ case DEVICE_UNKNOWN:
++ //printk(KERN_INFO"%s: UNKNOWN\n", __FUNCTION__);
++ break;
++ case DEVICE_BUS_ACTIVITY:
++ bus->device_state = bus->suspended_state;
++ //printk(KERN_INFO"%s: ACTIVITY\n", __FUNCTION__);
++ break;
++
++ case DEVICE_SET_INTERFACE:
++ case DEVICE_SET_FEATURE:
++ case DEVICE_CLEAR_FEATURE:
++ //printk(KERN_INFO"%s: SET\n", __FUNCTION__);
++ break;
++ }
++
++ switch (event) {
++ case DEVICE_BUS_ACTIVITY:
++ case DEVICE_BUS_INACTIVE:
++ BREAK_IF(USBD_CLOSING != bus->status);
++ /* FALL THROUGH */
++ default:
++ bus->status = event_status[event];
++ //printk(KERN_INFO"%s: DEFAULT\n", __FUNCTION__);
++ break;
++ }
++ //printk(KERN_INFO"%s: <-- event: %d status: %d state: %d\n", __FUNCTION__, event, bus->status, bus->device_state);
++
++ // if we lost configuration then get rid of alternate settings
++ if ((bus->device_state != STATE_CONFIGURED) && bus->bNumInterfaces && bus->alternates) {
++ bus->bNumInterfaces = 0;
++ lkfree(bus->alternates);
++ bus->alternates = NULL;
++ }
++ bus->driver->bops->device_event (bus, event, data);
++ usbd_func_event_irq (bus, bus->ep0, event, data);
++ usbd_func_event_irq (bus, bus->function_instance, event, data);
++}
++
++
++/* usbd_bus_event
++ */
++void usbd_bus_event (struct usb_bus_instance *bus, usb_device_event_t event, int data)
++{
++ unsigned long flags;
++ local_irq_save (flags);
++ usbd_bus_event_irq (bus, event, data);
++ local_irq_restore (flags);
++}
++
++
++/* usbd_attached - return cable status
++ *
++ * Return non-zero if cable attached
++ */
++int usbd_attached (struct usb_bus_instance *bus)
++{
++ return bus->driver->bops->bus_attached (bus);
++}
++
++/* usbd_connected - return pullup resistor control status
++ * *
++ * * Return non-zero if pullup enabled
++ * */
++int usbd_connected (struct usb_bus_instance *bus)
++{
++ return bus->driver->bops->bus_connected (bus);
++}
++
++
++/* usbb bus bottom half ********************************************************************** */
++
++/*
++ * Note that all of the functions from here to the end of the file protect against
++ * overlapped operation using the usbd_bus_sem
++ *
++ * usbd_device_bh
++ *
++ * usbd_register_bus
++ * usbd_deregister_bus
++ * usbd_enable_function_irq
++ * usbd_disable_function
++ */
++DECLARE_MUTEX(usbd_bus_sem);
++
++
++/* usbd_device_bh -
++ *
++ * Bottom half handler to process sent or received urbs.
++ */
++void usbd_device_bh (void *data)
++{
++ int i;
++ struct usb_bus_instance *bus = data;
++ struct usb_endpoint_instance *endpoint;
++
++ RETURN_IF (!bus || !(endpoint = bus->endpoint_array));
++ down(&usbd_bus_sem);
++ // process received and sent urbs
++ for (i = 0; i < bus->endpoints; i++, endpoint++) {
++ struct urb *urb;
++ for (; (urb = first_urb_detached (&endpoint->rcv )); usbd_urb_callback (urb, urb->status));
++ for (; (urb = first_urb_detached (&endpoint->done)); usbd_urb_callback (urb, urb->status));
++ }
++ if (USBD_CLOSING == bus->status)
++ bus->device_bh.data = NULL;
++ up(&usbd_bus_sem);
++}
++
++
++/* usb-device USB BUS INTERFACE generic functions ******************************************** */
++
++/*
++ * Initialize an urb_link to be a single element list.
++ * If the urb_link is being used as a distinguished list head
++ * the list is empty when the head is the only link in the list.
++ */
++static __inline__ void urb_link_init (urb_link * ul)
++{
++ ul->prev = ul->next = ul;
++}
++
++/* usbd_register_bus - called by a USB BUS INTERFACE driver to register a bus driver
++ *
++ * Used by a USB Bus interface driver to register itself with the usb device layer.
++ *
++ * Return non-zero if error
++ */
++struct usb_bus_instance *usbd_register_bus (struct usb_bus_driver *driver)
++{
++ int i;
++ struct usb_bus_instance *bus = NULL;
++
++ //printk(KERN_INFO"%s: DOWN USBD_BUS_SEM\n", __FUNCTION__);
++ down(&usbd_bus_sem);
++ MOD_INC_USE_COUNT; // QQQ should this be before the down()?
++
++ THROW_IF(usbd_bus_instance, error);
++ THROW_IF((bus = ckmalloc (sizeof (struct usb_bus_instance), GFP_ATOMIC)) == NULL, error);
++
++ bus->driver = driver;
++ bus->endpoints = bus->driver->max_endpoints;
++
++ THROW_IF(!(bus->endpoint_array = ckmalloc(sizeof (struct usb_endpoint_instance) * bus->endpoints, GFP_ATOMIC)), error);
++
++ for (i = 0; i < bus->endpoints; i++) {
++ struct usb_endpoint_instance *endpoint = bus->endpoint_array + i;
++ endpoint->physical_endpoint = i;
++ urb_link_init (&endpoint->rcv);
++ urb_link_init (&endpoint->rdy);
++ urb_link_init (&endpoint->tx);
++ urb_link_init (&endpoint->done);
++ }
++
++ bus->admin[usbd_admin_enable] = driver->bops->bus_enable;
++ bus->admin[usbd_admin_disable] = driver->bops->bus_disable;
++ bus->admin[usbd_admin_disconnect] = driver->bops->bus_disconnect;
++ bus->admin[usbd_admin_connect] = driver->bops->bus_connect;
++ bus->admin[usbd_admin_pm_off] = driver->bops->bus_pm_off;
++ bus->admin[usbd_admin_pm_on] = driver->bops->bus_pm_on;
++ bus->admin[usbd_admin_serial_number] = driver->bops->bus_serial_number;
++
++ THROW_IF((bus->ep0 = ckmalloc (sizeof (struct usb_function_instance), GFP_ATOMIC)) == NULL, error)
++ bus->ep0->function_driver = &ep0_driver;
++ bus->ep0->endpointsRequested = 1;
++ THROW_IF(!(bus->ep0->endpoint_map_array = ckmalloc(sizeof(struct usb_endpoint_map) * 1, GFP_KERNEL)), error);
++
++ bus->device_state = STATE_CREATED;
++ bus->status = USBD_OPENING;
++
++ usbd_bus_instance = bus;
++
++ CATCH(error) {
++ if (bus) {
++ if (bus->endpoint_array)
++ lkfree(bus->endpoint_array);
++ lkfree(bus);
++ }
++ bus->endpoints = 0;
++ printk(KERN_INFO"%s: FAILED\n", __FUNCTION__);
++ bus = NULL;
++ MOD_DEC_USE_COUNT;
++ }
++
++ up(&usbd_bus_sem);
++ //printk(KERN_INFO"%s: UP USBD_BUS_SEM\n", __FUNCTION__);
++ return bus;
++}
++
++/* usbd_deregister_bus - called by a USB BUS INTERFACE driver to deregister a bus driver
++ *
++ * Used by a USB Bus interface driver to de-register itself with the usb device
++ * layer.
++ */
++void usbd_deregister_bus (struct usb_bus_instance *bus)
++{
++ //printk(KERN_INFO"%s: DOWN USBD_BUS_SEM\n", __FUNCTION__);
++ down(&usbd_bus_sem);
++
++ usbd_bus_instance = NULL;
++
++ if (bus->ep0) {
++ if (bus->ep0->endpoint_map_array)
++ lkfree(bus->ep0->endpoint_map_array);
++ lkfree(bus->ep0);
++ }
++
++ lkfree (bus->arg);
++ lkfree (bus->endpoint_array);
++ lkfree (bus);
++ bus->endpoints = 0;
++ MOD_DEC_USE_COUNT; // QQQ should this be after the up()?
++ up(&usbd_bus_sem);
++ //printk(KERN_INFO"%s: UP USBD_BUS_SEM\n", __FUNCTION__);
++}
++
++
++/* usb-device USB Device generic functions *************************************************** */
++
++/* usbd_enable_function_irq - called to enable the desired function
++ *
++ * Used by a USB Bus interface driver to create a virtual device.
++ *
++ * Return non-zero if error
++ */
++int usbd_enable_function_irq (struct usb_bus_instance *bus, char *arg)
++{
++ struct usb_function_instance *function = NULL;
++ struct list_head *lhd;
++ int len = 0;
++ int i;
++ int rc = -EINVAL;
++ int epn;
++
++ //printk(KERN_INFO"%s: DOWN USBD_BUS_SEM\n", __FUNCTION__);
++ down(&usbd_bus_sem);
++
++ if (arg && bus->arg)
++ lkfree(bus->arg);
++
++ if (arg) {
++ bus->arg = lstrdup(arg);
++ len = strlen(arg);
++ }
++
++ // initialize the strings pool
++ THROW_IF(usbd_strings_init (), error);
++
++ for (i = 1; i < bus->endpoints; i++) {
++ struct usb_endpoint_instance *endpoint = bus->endpoint_array + i;
++ endpoint->rcv_urb = endpoint->tx_urb = NULL;
++ }
++
++ list_for_each (lhd, &usbd_function_drivers) {
++ struct usb_function_driver *function_driver;
++ function_driver = list_entry_function (lhd);
++
++ printk(KERN_INFO"%s: check: [%s] %s\n", __FUNCTION__,
++ (arg?arg:""), function_driver->name);
++
++ // mode - single, either the first or a named function
++ CONTINUE_IF(arg && len && strncmp(function_driver->name, arg, len));
++
++ //printk(KERN_INFO"%s: found: %s\n", __FUNCTION__, function_driver->name);
++
++ THROW_IF (!(function = ckmalloc (sizeof (struct usb_function_instance), GFP_ATOMIC)), error);
++ function->function_driver = function_driver; // XXX
++
++ THROW_IF (!(function->endpoint_map_array = ckmalloc (sizeof(struct usb_endpoint_map) *
++ function->function_driver->device_description->endpointsRequested,
++ GFP_KERNEL)), error);
++
++ THROW_IF(bus->driver->bops->request_endpoints( function->endpoint_map_array,
++ function->function_driver->device_description->endpointsRequested,
++ function->function_driver->device_description->requestedEndpoints), error);
++
++ function->endpointsRequested = function->function_driver->device_description->endpointsRequested;
++ usbd_function_enable (bus, function);
++ break;
++ }
++
++ if (NULL == function && NULL != arg && 0 != len) {
++ printk(KERN_INFO"Unknown function driver (len=%d) [%s], known drivers:\n",len,arg);
++ list_for_each (lhd, &usbd_function_drivers) {
++ struct usb_function_driver *function_driver = list_entry_function (lhd);
++ printk(KERN_INFO" [%s]\n", function_driver->name);
++ }
++ }
++
++ THROW_IF (!(bus->function_instance = function), error);
++
++ THROW_IF(bus->driver->bops->set_endpoints( function->function_driver->device_description->endpointsRequested,
++ function->endpoint_map_array), error);
++ // device bottom half
++ bus->device_bh.routine = usbd_device_bh;
++ bus->device_bh.data = bus;
++ bus->status = USBD_OK;
++ bus->bus_state = usbd_bus_state_enabled;
++ bus->ep0->endpoint_map_array->endpoint = bus->endpoint_array;
++ THROW_IF (usbd_function_enable (bus, bus->ep0), error);
++
++ //printk(KERN_INFO"%s: %d endpoint: %p map: %p\n", __FUNCTION__, 0,
++ // bus->ep0->endpoint_map_array->endpoint,
++ // bus->ep0->endpoint_map_array);
++
++ // iterate across the logical endpoint map to copy appropriate information
++ // into the physical endpoint instance array
++
++ for (epn = 0; epn < bus->function_instance->endpointsRequested; epn++) {
++
++ struct usb_endpoint_map *endpoint_map = bus->function_instance->endpoint_map_array + epn;
++ int physicalEndpoint = endpoint_map->physicalEndpoint[0];
++ struct usb_endpoint_instance *endpoint = bus->endpoint_array + physicalEndpoint;
++
++ //printk(KERN_INFO"%s: %d endpoint: %p map: %p bEndpointAddress: %02x\n", __FUNCTION__,
++ // epn, endpoint, endpoint_map, endpoint_map->bEndpointAddress[0]);
++
++ endpoint_map->endpoint = endpoint;
++ endpoint->bEndpointAddress = endpoint_map->bEndpointAddress[0];
++ endpoint->bmAttributes = endpoint_map->bmAttributes[0];
++
++ switch(endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
++ case USB_DIR_IN:
++ endpoint->wMaxPacketSize = endpoint_map->wMaxPacketSize[0];
++ endpoint->last = 0;
++ endpoint->tx_urb = NULL;
++ break;
++
++ case USB_DIR_OUT:
++ endpoint->rcv_transferSize = endpoint_map->transferSize[0];
++ endpoint->wMaxPacketSize = endpoint_map->wMaxPacketSize[0];
++ endpoint->rcv_urb = NULL;
++ break;
++ }
++ }
++
++ rc = 0;
++
++ CATCH(error) {
++ printk(KERN_INFO"%s: FAILED\n", __FUNCTION__);
++ usbd_strings_exit();
++ }
++ up(&usbd_bus_sem);
++ //printk(KERN_INFO"%s: UP USBD_BUS_SEM\n", __FUNCTION__);
++ return rc;
++}
++
++/* usbd_disable_function - called to disable the current function
++ *
++ * Used by a USB Bus interface driver to destroy a virtual device.
++ */
++void usbd_disable_function (struct usb_bus_instance *bus)
++{
++ printk(KERN_INFO"%s: DOWN USBD_BUS_SEM\n", __FUNCTION__);
++ down(&usbd_bus_sem);
++ // prevent any more bottom half scheduling
++ bus->status = USBD_CLOSING;
++ up(&usbd_bus_sem);
++ //printk(KERN_INFO"%s: UP USBD_BUS_SEM\n", __FUNCTION__);
++
++ // wait for pending device bottom half to finish
++ while (bus->device_bh.data /*|| device->function_bh.data */) {
++
++ //printk(KERN_INFO"%s: waiting for usbd_device_bh %ld %p interrupt: %d\n", __FUNCTION__,
++ // bus->device_bh.sync, bus->device_bh.data, in_interrupt());
++
++ // This can probably be either, but for consistency's sake...
++ queue_task(&bus->device_bh, &tq_immediate);
++ mark_bh (IMMEDIATE_BH);
++ // schedule_task(&device->device_bh);
++
++ schedule_timeout (2000 * HZ);
++ }
++
++ //printk(KERN_INFO"%s: DOWN USBD_BUS_SEM\n", __FUNCTION__);
++ down(&usbd_bus_sem);
++
++ // tell the function driver to close
++ usbd_function_disable (bus->ep0);
++ usbd_function_disable (bus->function_instance);
++
++ // free alternates memory
++ if (/*bus->bNumInterfaces &&*/ bus->alternates) {
++ bus->bNumInterfaces = 0;
++ lkfree(bus->alternates);
++ bus->alternates = NULL;
++ }
++ if (bus->function_instance) {
++ if (bus->function_instance->endpoint_map_array)
++ lkfree(bus->function_instance->endpoint_map_array);
++ lkfree(bus->function_instance);
++ bus->function_instance = NULL;
++ }
++ usbd_strings_exit();
++ bus->status = USBD_CLOSED;
++ up(&usbd_bus_sem);
++ printk(KERN_INFO"%s: UP USBD_BUS_SEM\n", __FUNCTION__);
++}
++
++usb_device_state_t usbd_device_state(struct usb_function_instance *function)
++{
++ //printk(KERN_INFO"%s: %d\n", __FUNCTION__, function->bus->device_state);
++ return (function && function->bus) ? function->bus->device_state : STATE_UNKNOWN;
++}
++usb_device_state_t usbd_bus_state(struct usb_function_instance *function)
++{
++ //printk(KERN_INFO"%s: %d\n", __FUNCTION__, function->bus->bus_state);
++ return (function && function->bus) ? function->bus->bus_state : usbd_bus_state_unknown;
++}
++usb_device_status_t usbd_bus_status(struct usb_function_instance *function)
++{
++ //printk(KERN_INFO"%s: %d\n", __FUNCTION__, function->bus->status);
++ return (function && function->bus) ? function->bus->status : USBD_UNKNOWN;
++}
++
++EXPORT_SYMBOL(usbd_register_bus);
++EXPORT_SYMBOL(usbd_deregister_bus);
++EXPORT_SYMBOL(usbd_enable_function_irq);
++EXPORT_SYMBOL(usbd_disable_function);
++EXPORT_SYMBOL(usbd_attached);
++EXPORT_SYMBOL(usbd_send_urb);
++EXPORT_SYMBOL(usbd_start_recv);
++EXPORT_SYMBOL(usbd_flush_endpoint);
++EXPORT_SYMBOL(usbd_cancel_urb_irq);
++EXPORT_SYMBOL(usbd_bus_event_irq);
++EXPORT_SYMBOL(usbd_bus_event);
++EXPORT_SYMBOL(usbd_urb_sent_finished_irq);
++EXPORT_SYMBOL(usbd_urb_recv_finished_irq);
++EXPORT_SYMBOL(usbd_device_state);
++EXPORT_SYMBOL(usbd_bus_state);
++EXPORT_SYMBOL(usbd_bus_status);
++EXPORT_SYMBOL(usbd_first_urb_detached_irq);
++
+diff -Nru a/drivers/usbd/usbd-build.h b/drivers/usbd/usbd-build.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-build.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1 @@
++#define USBD_BUILD "000"
+diff -Nru a/drivers/usbd/usbd-bus.h b/drivers/usbd/usbd-bus.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-bus.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,316 @@
++/*
++ * usbd/usbd-bus.c - USB Device Bus Interface Driver Interface
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2000, 2001, 2002 Lineo
++ * Copyright (c) 2001 Hewlett Packard
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++/*
++ * This file contains the USB Bus Interface Driver Interface definitions.
++ *
++ * This is the interface between the bottom of the USB Core and the top of
++ * the Bus Interace Drivers and is comprised of:
++ *
++ * o public functions exported by the USB Core layer
++ *
++ * o structures and functions passed by the Function Driver to the USB
++ * Core layer
++ *
++ * USB Bus Interface Drivers are structured such that the upper edge
++ * implements interfaces to the USB Core layer to provide low level USB
++ * services and the lower edge interfaces to the actual USB Hardware
++ * (typically called the USB Device Controller or UDC.)
++ *
++ */
++
++struct usb_endpoint_map;
++
++/* Operations that the slave layer or function driver can use to interact
++ * with the bus interface driver.
++ *
++ * The send_urb() function is used by the usb-device endpoint 0 driver and
++ * function drivers to submit data to be sent.
++ *
++ * The cancel_urb() function is used by the usb-device endpoint 0 driver and
++ * function drivers to remove previously queued data to be sent.
++ *
++ * The endpoint_halted() function is used by the ep0 control function to
++ * check if an endpoint is halted.
++ *
++ * The device_feature() function is used by the ep0 control function to
++ * set/reset device features on an endpoint.
++ *
++ * The device_event() function is used by the usb device core to tell the
++ * bus interface driver about various events.
++ */
++struct usb_bus_operations {
++ int (*bus_enable) (struct usb_bus_instance *, char *);
++ int (*bus_disable) (struct usb_bus_instance *, char *);
++ int (*bus_disconnect) (struct usb_bus_instance *, char *);
++ int (*bus_connect) (struct usb_bus_instance *, char *);
++ int (*bus_pm_off) (struct usb_bus_instance *, char *);
++ int (*bus_pm_on) (struct usb_bus_instance *, char *);
++ int (*bus_serial_number) (struct usb_bus_instance *, char *);
++
++ int (*bus_attached) (struct usb_bus_instance *);
++ int (*bus_connected) (struct usb_bus_instance *);
++ int (*start_endpoint_in) (struct usb_bus_instance *, struct usb_endpoint_instance *);
++ int (*start_endpoint_out) (struct usb_bus_instance *, struct usb_endpoint_instance *);
++ int (*cancel_urb_irq) (struct urb *);
++ int (*endpoint_halted) (struct usb_bus_instance *, int);
++ int (*device_feature) (struct usb_bus_instance *, int, int);
++ int (*device_event) (struct usb_bus_instance *, usb_device_event_t, int);
++ int (*request_endpoints) (struct usb_endpoint_map *, int, struct usb_endpoint_request *);
++ int (*set_endpoints) (int , struct usb_endpoint_map *);
++};
++
++
++/* Endpoint Map
++ *
++ * An array of these structures is created by the bus interface driver to
++ * show what endpoints have been configured for the function driver.
++ */
++struct usb_endpoint_map {
++ u8 configuration;
++ u8 interface;
++ u8 alternate;
++ u8 bEndpointAddress[2]; // logical endpoint address
++ u16 wMaxPacketSize[2]; // packetsSize for requested endpoint
++ u8 bmAttributes[2]; // requested endpoint type
++ u16 transferSize[2]; // transferSize for bulk transfers
++ u8 physicalEndpoint[2]; // physical endpoint number
++ struct usb_endpoint_instance *endpoint;
++};
++
++
++/* Endpoint configuration
++ *
++ * Per endpoint configuration data. Used to track which function driver owns
++ * an endpoint.
++ *
++ */
++struct usb_endpoint_instance {
++ int bEndpointAddress; // logical endpoint address
++ int physical_endpoint; // physical endpoint address - bus interface specific
++ int bmAttributes; // endpoint type
++ u16 wMaxPacketSize; // packet size for requested endpoint
++
++ // control
++ int status; // halted
++ int state; // available for use by bus interface driver
++
++ // receive side
++ struct urb_link rcv; // received urbs
++ struct urb_link rdy; // empty urbs ready to receive
++ struct urb *rcv_urb; // active urb
++ __u32 rcv_transferSize; // maximum transfer size from function driver
++ int rcv_error; // current bulk-in has an error
++
++ // transmit side
++ struct urb_link tx; // urbs ready to transmit
++ struct urb_link done; // transmitted urbs
++ struct urb *tx_urb; // active urb
++
++ __u32 sent; // data already sent
++ __u32 last; // data sent in last packet XXX do we need this
++};
++
++/* endpoint zero states
++ */
++#define WAIT_FOR_SETUP 0
++#define DATA_STATE_XMIT 1
++#define DATA_STATE_NEED_ZLP 2
++#define WAIT_FOR_OUT_STATUS 3
++#define DATA_STATE_RECV 4
++#define DATA_STATE_PENDING_XMIT 5
++
++
++/* Bus Interface data structure
++ *
++ * Keep track of specific bus interface.
++ *
++ * This is passed to the usb-device layer when registering. It contains all
++ * required information about each real bus interface found such that the
++ * usb-device layer can create and maintain a usb-device structure.
++ *
++ * Note that bus interface registration is incumbent on finding specific
++ * actual real bus interfaces. There will be a registration for each such
++ * device found.
++ *
++ * The max_tx_endpoints and max_rx_endpoints are the maximum number of
++ * possible endpoints that this bus interface can support. The default
++ * endpoint 0 is not included in these counts.
++ *
++ */
++struct usb_bus_driver {
++ char *name;
++ u8 max_endpoints; // maximimum number of rx enpoints
++ u8 maxpacketsize;
++ u8 HighSpeedCapable;
++ struct usb_device_description *device_description;
++ struct usb_bus_operations *bops;
++};
++
++
++typedef enum usbd_admin {
++ usbd_admin_enable = 0,
++ usbd_admin_disable = 1,
++ usbd_admin_connect = 2,
++ usbd_admin_disconnect = 3,
++ usbd_admin_pm_off = 4,
++ usbd_admin_pm_on = 5,
++ usbd_admin_serial_number = 6
++} usbd_admin_t;
++
++typedef int (*usbd_admin_proc_t) (struct usb_bus_instance *, char *);
++
++
++/* Function configuration structure
++ *
++ * This is allocated for each configured instance of a function driver.
++ *
++ * It stores pointers to the usb_function_driver for the appropriate function,
++ * and pointers to the USB HOST requested usb_configuration_description and
++ * usb_interface_description.
++ *
++ * The privdata pointer may be used by the function driver to store private
++ * per instance state information.
++ *
++ */
++struct usb_function_instance {
++ struct usb_bus_instance *bus;
++ struct usb_function_driver *function_driver;
++ void *privdata; // private data for the function
++ __u8 endpointsRequested; // number of requested endpoints
++ struct usb_endpoint_map *endpoint_map_array; // map of endpoints requested by function driver
++};
++
++
++/* Bus Interface configuration structure
++ *
++ * This is allocated for each configured instance of a bus interface driver.
++ *
++ * It contains a pointer to the appropriate bus interface driver.
++ *
++ * The privdata pointer may be used by the bus interface driver to store private
++ * per instance state information.
++ */
++struct usb_bus_instance {
++
++ struct usb_bus_driver *driver;
++
++ usbd_admin_proc_t admin [8];
++
++ int endpoints;
++ struct usb_endpoint_instance *endpoint_array; // array of available configured endpoints
++
++ char *serial_number_str;
++
++ usb_device_status_t status; // device status
++ usbd_bus_state_t bus_state;
++ usb_device_state_t device_state; // current USB Device state
++ usb_device_state_t suspended_state; // previous USB Device state
++
++ struct usb_function_instance *ep0; // ep0 configuration
++ struct usb_function_instance *function_instance;
++
++
++ u8 HighSpeedFlag;
++ u8 ConfigurationValue; // current set configuration (zero is default)
++ u8 bNumInterfaces; // number of interfaces in the current configuration
++ u8 *alternates; // array[0..interfaces-1] of alternate settings for each interface
++
++ struct tq_struct device_bh; // runs as bottom half, equivalent to interrupt time
++
++ void *privdata; // private data for the bus interface
++ char *arg;
++};
++
++/* bus driver registration
++ *
++ * Called by bus interface drivers to register themselves when loaded
++ * or de-register when unloading.
++ */
++struct usb_bus_instance *usbd_register_bus (struct usb_bus_driver *);
++void usbd_deregister_bus (struct usb_bus_instance *);
++
++
++
++/* Enable/Disable Function
++ *
++ * Called by a bus interface driver to select and enable a specific function
++ * driver.
++ */
++int usbd_enable_function_irq (struct usb_bus_instance *, char *);
++void usbd_disable_function (struct usb_bus_instance *);
++
++
++void usbd_flush_endpoint_irq (struct usb_endpoint_instance *);
++void usbd_flush_endpoint (struct usb_endpoint_instance *);
++
++/*
++ * usbd_configure_device is used by function drivers (usually the control endpoint)
++ * to change the device configuration.
++ *
++ * usbd_device_event is used by bus interface drivers to tell the higher layers that
++ * certain events have taken place.
++ */
++void usbd_bus_event_irq (struct usb_bus_instance *, usb_device_event_t, int);
++void usbd_bus_event (struct usb_bus_instance *, usb_device_event_t, int);
++
++
++/**
++ * usbd_recv_setup_irq - process a received urb
++ * @urb: pointer to an urb structure
++ *
++ * Used by a USB Bus interface driver to pass received data in a URB to the
++ * appropriate USB Function driver.
++ *
++ * This function must return 0 for success and -EINVAL if the request
++ * is to be stalled.
++ *
++ * Not that if the SETUP is Host to Device with a non-zero wLength then there
++ * *MUST* be a valid receive urb queued OR the request must be stalled.
++ */
++int usbd_recv_setup_irq (struct usb_function_instance*, struct usb_device_request *);
++
++
++void usbd_urb_sent_finished_irq (struct urb *, int );
++void usbd_urb_recv_finished_irq (struct urb *, int );
++
++
++/*
++ * Detach and return the first urb in a list with a distinguished
++ * head "hd", or NULL if the list is empty.
++ */
++struct urb *usbd_first_urb_detached_irq (urb_link * hd);
++
++/*
++ * Get a descriptor
++ */
++int usbd_get_descriptor (struct usb_bus_instance *bus, u8 *buffer, int max, int descriptor_type, int index);
++
+diff -Nru a/drivers/usbd/usbd-chap9.h b/drivers/usbd/usbd-chap9.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-chap9.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,1054 @@
++/*
++ * usbd/usbd-chap9.h
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2000, 2001, 2002 Lineo
++ * Copyright (c) 2001 Hewlett Packard
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++
++/*
++ * USB Descriptors are used to build a configuration database for each USB
++ * Function driver.
++ *
++ */
++
++
++/*
++ * Device and/or Interface Class codes
++ */
++#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */
++#define USB_CLASS_AUDIO 1
++#define USB_CLASS_COMM 2
++#define USB_CLASS_HID 3
++#define USB_CLASS_PHYSICAL 5
++#define USB_CLASS_PRINTER 7
++#define USB_CLASS_MASS_STORAGE 8
++#define USB_CLASS_HUB 9
++#define USB_CLASS_DATA 10
++#define USB_CLASS_APP_SPEC 0xfe
++#define USB_CLASS_VENDOR_SPEC 0xff
++
++/*
++ * USB Device Request Types (bmRequestType)
++ * C.f. USB 2.0 Table 9-2
++ */
++#define USB_TYPE_STANDARD (0x00 << 5)
++#define USB_TYPE_CLASS (0x01 << 5)
++#define USB_TYPE_VENDOR (0x02 << 5)
++#define USB_TYPE_RESERVED (0x03 << 5)
++
++#define USB_RECIP_DEVICE 0x00
++#define USB_RECIP_INTERFACE 0x01
++#define USB_RECIP_ENDPOINT 0x02
++#define USB_RECIP_OTHER 0x03
++
++#define USB_DIR_OUT 0
++#define USB_DIR_IN 0x80
++#define USB_ENDPOINT_OPT 0x40
++
++
++
++/*
++ * Descriptor types
++ * C.f. USB Table 9-5
++ */
++#define USB_DT_DEVICE 0x01
++#define USB_DT_CONFIG 0x02
++#define USB_DT_STRING 0x03
++#define USB_DT_INTERFACE 0x04
++#define USB_DT_ENDPOINT 0x05
++
++
++
++#define USB_DT_HID (USB_TYPE_CLASS | 0x01)
++#define USB_DT_REPORT (USB_TYPE_CLASS | 0x02)
++#define USB_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
++#define USB_DT_HUB (USB_TYPE_CLASS | 0x09)
++
++/*
++ * Descriptor sizes per descriptor type
++ */
++#define USB_DT_DEVICE_SIZE 18
++#define USB_DT_CONFIG_SIZE 9
++#define USB_DT_INTERFACE_SIZE 9
++#define USB_DT_ENDPOINT_SIZE 7
++#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */
++#define USB_DT_HUB_NONVAR_SIZE 7
++#define USB_DT_HID_SIZE 9
++
++/*
++ * Endpoints
++ */
++#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */
++#define USB_ENDPOINT_DIR_MASK 0x80
++
++#define USB_ENDPOINT_MASK 0x03 /* in bmAttributes */
++#define USB_ENDPOINT_CONTROL 0x00
++#define USB_ENDPOINT_ISOCHRONOUS 0x01
++#define USB_ENDPOINT_BULK 0x02
++#define USB_ENDPOINT_INTERRUPT 0x03
++
++/*
++ * USB Packet IDs (PIDs)
++ */
++#define USB_PID_UNDEF_0 0xf0
++#define USB_PID_OUT 0xe1
++#define USB_PID_ACK 0xd2
++#define USB_PID_DATA0 0xc3
++#define USB_PID_PING 0xb4 /* USB 2.0 */
++#define USB_PID_SOF 0xa5
++#define USB_PID_NYET 0x96 /* USB 2.0 */
++#define USB_PID_DATA2 0x87 /* USB 2.0 */
++#define USB_PID_SPLIT 0x78 /* USB 2.0 */
++#define USB_PID_IN 0x69
++#define USB_PID_NAK 0x5a
++#define USB_PID_DATA1 0x4b
++#define USB_PID_PREAMBLE 0x3c /* Token mode */
++#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */
++#define USB_PID_SETUP 0x2d
++#define USB_PID_STALL 0x1e
++#define USB_PID_MDATA 0x0f /* USB 2.0 */
++
++/*
++ * Standard requests
++ */
++#define USB_REQ_GET_STATUS 0x00
++#define USB_REQ_CLEAR_FEATURE 0x01
++#define USB_REQ_SET_FEATURE 0x03
++#define USB_REQ_SET_ADDRESS 0x05
++#define USB_REQ_GET_DESCRIPTOR 0x06
++#define USB_REQ_SET_DESCRIPTOR 0x07
++#define USB_REQ_GET_CONFIGURATION 0x08
++#define USB_REQ_SET_CONFIGURATION 0x09
++#define USB_REQ_GET_INTERFACE 0x0A
++#define USB_REQ_SET_INTERFACE 0x0B
++#define USB_REQ_SYNCH_FRAME 0x0C
++
++/*
++ * HID requests
++ */
++#define USB_REQ_GET_REPORT 0x01
++#define USB_REQ_GET_IDLE 0x02
++#define USB_REQ_GET_PROTOCOL 0x03
++#define USB_REQ_SET_REPORT 0x09
++#define USB_REQ_SET_IDLE 0x0A
++#define USB_REQ_SET_PROTOCOL 0x0B
++
++
++/*
++ * USB Spec Release number
++ */
++
++#define USB_BCD_VERSION 0x0200
++
++/*
++ * Audio
++ */
++#define CS_AUDIO_UNDEFINED 0x20
++#define CS_AUDIO_DEVICE 0x21
++#define CS_AUDIO_CONFIGURATION 0x22
++#define CS_AUDIO_STRING 0x23
++#define CS_AUDIO_INTERFACE 0x24
++#define CS_AUDIO_ENDPOINT 0x25
++
++#define AUDIO_HEADER 0x01
++#define AUDIO_INPUT_TERMINAL 0x02
++#define AUDIO_OUTPUT_TERMINAL 0x03
++#define AUDIO_MIXER_UNIT 0x04
++#define AUDIO_SELECTOR_UNIT 0x05
++#define AUDIO_FEATURE_UNIT 0x06
++#define AUDIO_PROCESSING_UNIT 0x07
++#define AUDIO_EXTENSION_UNIT 0x08
++
++
++/*
++ * Device Requests (c.f Table 9-2)
++ */
++
++#define USB_REQ_DIRECTION_MASK 0x80
++#define USB_REQ_TYPE_MASK 0x60
++#define USB_REQ_RECIPIENT_MASK 0x1f
++
++#define USB_REQ_DEVICE2HOST 0x80
++#define USB_REQ_HOST2DEVICE 0x00
++
++#define USB_REQ_TYPE_STANDARD 0x00
++#define USB_REQ_TYPE_CLASS 0x20
++#define USB_REQ_TYPE_VENDOR 0x40
++
++#define USB_REQ_RECIPIENT_DEVICE 0x00
++#define USB_REQ_RECIPIENT_INTERFACE 0x01
++#define USB_REQ_RECIPIENT_ENDPOINT 0x02
++#define USB_REQ_RECIPIENT_OTHER 0x03
++
++/*
++ * get status bits
++ */
++
++#define USB_STATUS_SELFPOWERED 0x01
++#define USB_STATUS_REMOTEWAKEUP 0x02
++
++#define USB_STATUS_HALT 0x01
++
++/*
++ * descriptor types
++ */
++
++#define USB_DESCRIPTOR_TYPE_DEVICE 0x01
++#define USB_DESCRIPTOR_TYPE_CONFIGURATION 0x02
++#define USB_DESCRIPTOR_TYPE_STRING 0x03
++#define USB_DESCRIPTOR_TYPE_INTERFACE 0x04
++#define USB_DESCRIPTOR_TYPE_ENDPOINT 0x05
++#define USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 0x06
++#define USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION 0x07
++#define USB_DESCRIPTOR_TYPE_INTERFACE_POWER 0x08
++
++/*
++ * standard feature selectors
++ */
++#define USB_ENDPOINT_HALT 0x00
++#define USB_DEVICE_REMOTE_WAKEUP 0x01
++#define USB_TEST_MODE 0x02
++
++
++/* USB Requests
++ *
++ */
++
++struct usb_device_request {
++ __u8 bmRequestType;
++ __u8 bRequest;
++ __u16 wValue;
++ __u16 wIndex;
++ __u16 wLength;
++} __attribute__ ((packed));
++
++
++/*
++ * Class-Specific Request Codes
++ * C.f. CDC Table 46
++ */
++#define CDC_CLASS_REQUEST_SEND_ENCAPSULATED 0x00
++#define CDC_CLASS_REQUEST_GET_ENCAPSULATED 0x01
++
++#define CDC_CLASS_REQUEST_SET_COMM_FEATURE 0x02
++#define CDC_CLASS_REQUEST_GET_COMM_FEATURE 0x03
++#define CDC_CLASS_REQUEST_CLEAR_COMM_FEATURE 0x04
++
++#define CDC_CLASS_REQUEST_SET_LINE_CODING 0x20
++#define CDC_CLASS_REQUEST_GET_LINE_CODING 0x21
++
++#define CDC_CLASS_REQUEST_SET_CONTROL_STATE 0x22
++#define CDC_CLASS_REQUEST_SEND_BREAK 0x23
++
++/*
++ * Notification codes
++ * c.f. CDC Table 68
++ */
++
++#define CDC_NOTIFICATION_NETWORK_CONNECTION 0x00
++#define CDC_NOTIFICATION_RESPONSE_AVAILABLE 0x01
++#define CDC_NOTIFICATION_AUX_JACK_HOOK_STATE 0x08
++#define CDC_NOTIFICATION_RING_DETECT 0x09
++#define CDC_NOTIFICATION_SERIAL_STATE 0x20
++#define CDC_NOTIFICATION_CALL_STATE_CHANGE 0x28
++#define CDC_NOTIFICATION_LINE_STATE_CHANGE 0x29
++#define CDC_NOTIFICATION_CONNECTION_SPEED_CHANGE 0x2a
++
++/*
++ * HID - Class Descriptors
++ * C.f. 7.1.1
++ */
++#define HID 0x21
++#define HID_REPORT 0x22
++#define HID_PHYSICAL 0x23
++
++/*
++ * HID Descriptor
++ * C.f. E.8
++ */
++struct hid_descriptor {
++ u8 bLength;
++ u8 bDescriptorType;
++ u16 bcdHID;
++ u8 bCountryCode;
++ u8 bNumDescriptors;
++ u8 bReportType;
++ u16 wItemLength;
++} __attribute__((packed));
++
++/*
++ * ACM - Line Coding structure
++ * C.f CDC Table 50
++ */
++struct cdc_acm_line_coding {
++ __u32 dwDTERate;
++ __u8 bCharFormat;
++ __u8 bParityType;
++ __u8 bDataBits;
++} __attribute__((packed));
++
++/*
++ * ACM
++ * C.f CDC Table 50
++ */
++
++
++/*
++ * ACM
++ * C.f CDC Table 51
++ */
++
++
++/* USB Notification
++ *
++ */
++
++struct cdc_notification_descriptor {
++ __u8 bmRequestType;
++ __u8 bNotification;
++ __u16 wValue;
++ __u16 wIndex;
++ __u16 wLength;
++ __u8 data[2];
++} __attribute__ ((packed));
++
++
++
++
++/*
++ * communications class types
++ *
++ * c.f. CDC USB Class Definitions for Communications Devices
++ * c.f. WMCD USB CDC Subclass Specification for Wireless Mobile Communications Devices
++ *
++ */
++
++#define CLASS_BCD_VERSION 0x0110
++
++// c.f. CDC 4.1 Table 14
++#define AUDIO_CLASS 0x01
++#define COMMUNICATIONS_DEVICE_CLASS 0x02
++
++// c.f. CDC 4.2 Table 15
++#define COMMUNICATIONS_INTERFACE_CLASS 0x02
++
++// c.f. CDC 4.3 Table 16
++#define COMMUNICATIONS_NO_SUBCLASS 0x00
++#define COMMUNICATIONS_DLCM_SUBCLASS 0x01
++#define COMMUNICATIONS_ACM_SUBCLASS 0x02
++#define COMMUNICATIONS_TCM_SUBCLASS 0x03
++#define COMMUNICATIONS_MCCM_SUBCLASS 0x04
++#define COMMUNICATIONS_CCM_SUBCLASS 0x05
++#define COMMUNICATIONS_ENCM_SUBCLASS 0x06
++#define COMMUNICATIONS_ANCM_SUBCLASS 0x07
++
++#define AUDIO_CONTROL_SUBCLASS 0x01
++#define AUDIO_STREAMING_SUBCLASS 0x02
++
++// c.f. WMCD 5.1
++#define COMMUNICATIONS_WHCM_SUBCLASS 0x08
++#define COMMUNICATIONS_DMM_SUBCLASS 0x09
++#define COMMUNICATIONS_MDLM_SUBCLASS 0x0a
++#define COMMUNICATIONS_OBEX_SUBCLASS 0x0b
++
++// c.f. CDC 4.6 Table 18
++#define DATA_INTERFACE_CLASS 0x0a
++
++// c.f. CDC 4.7 Table 19
++#define COMMUNICATIONS_NO_PROTOCOL 0x00
++
++
++// c.f. CDC 5.2.3 Table 24
++// c.f. Audio Appendix A.4
++#define CS_UNDEFINED 0x20
++#define CS_DEVICE 0x21
++#define CS_CONFIG 0x22
++#define CS_STRING 0x23
++#define CS_INTERFACE 0x24
++#define CS_ENDPOINT 0x25
++
++// Audio Interface Class - c.f Appendix A.1
++#define AUDIO_INTERFACE_CLASS 0x01
++
++// Audio Interface Subclass - c.f Appendix A.2
++#define AUDIO_SUBCLASS_UNDEFINED 0x00
++#define AUDIO_AUDIOCONTROL 0x01
++#define AUDIO_AUDIOSTREAMING 0x02
++#define AUDIO_MIDISTREAMING 0x03
++
++// Audio Interface Proctol - c.f. Appendix A.3
++#define AUDIO_PR_PROTOCOL_UNDEFINED 0x00
++
++// Audio Class-Specific AC Interface Descriptor Subtypes - c.f. A.5
++#define AUDIO_AC_DESCRIPTOR_UNDEFINED 0x00
++#define AUDIO_AC_HEADER 0x01
++#define AUDIO_AC_INPUT_TERMINAL 0x02
++#define AUDIO_AC_OUTPUT_TERMINAL 0x03
++#define AUDIO_AC_MIXER_UNIT 0x04
++#define AUDIO_AC_SELECTOR_UNIT 0x05
++#define AUDIO_AC_FEATURE_UNIT 0x06
++#define AUDIO_AC_PROCESSING_UNIT 0x07
++#define AUDIO_AC_EXTENSION_UNIT 0x08
++
++// Audio Class-Specific AS Interface Descriptor Subtypes - c.f. A.6
++#define AUDIO_AS_DESCRIPTOR_UNDEFINED 0x00
++#define AUDIO_AS_GENERAL 0x01
++#define AUDIO_AS_FORMAT_TYPE 0x02
++#define AUDIO_AS_FORMAT_UNSPECFIC 0x03
++
++// Audio Class Processing Unit Processing Types - c.f. A.7
++#define AUDIO_PROCESS_UNDEFINED 0x00
++#define AUDIO_UP_DOWN_MUIX_PROCESS 0x01
++#define AUDIO_DOLBY_PROLOGIC_PROCESS 0x02
++#define AUDIO_3D_STEREO_EXTENDER_PROCESS 0x03
++#define AUDIO_REVERBERATION_PROCESS 0x04
++#define AUDIO_CHORUS_PROCESS 0x05
++#define AUDIO_DYN_RANGE_COMP_PROCESS 0x06
++
++// Audio Class-Specific Endpoint Descriptor Subtypes - c.f. A.8
++#define AUDIO_DESCRIPTOR_UNDEFINED 0x00
++#define AUDIO_EP_GENERAL 0x01
++
++// Audio Class-Specific Request Codes - c.f. A.9
++#define AUDIO_REQUEST_CODE_UNDEFINED 0x00
++#define AUDIO_SET_CUR 0x01
++#define AUDIO_GET_CUR 0x81
++#define AUDIO_SET_MIN 0x02
++#define AUDIO_GET_MIN 0x82
++#define AUDIO_SET_MAX 0x03
++#define AUDIO_GET_MAX 0x83
++#define AUDIO_SET_RES 0x04
++#define AUDIO_GET_RES 0x84
++#define AUDIO_SET_MEM 0x05
++#define AUDIO_GET_MEM 0x85
++#define AUDIO_GET_STAT 0xff
++
++
++
++
++
++
++/*
++ * bDescriptorSubtypes
++ *
++ * c.f. CDC 5.2.3 Table 25
++ * c.f. WMCD 5.3 Table 5.3
++ */
++
++#define USB_ST_HEADER 0x00
++#define USB_ST_CMF 0x01
++#define USB_ST_ACMF 0x02
++#define USB_ST_DLMF 0x03
++#define USB_ST_TRF 0x04
++#define USB_ST_TCLF 0x05
++#define USB_ST_UF 0x06
++#define USB_ST_CSF 0x07
++#define USB_ST_TOMF 0x08
++#define USB_ST_USBTF 0x09
++#define USB_ST_NCT 0x0a
++#define USB_ST_PUF 0x0b
++#define USB_ST_EUF 0x0c
++#define USB_ST_MCMF 0x0d
++#define USB_ST_CCMF 0x0e
++#define USB_ST_ENF 0x0f
++#define USB_ST_ATMNF 0x10
++
++#define USB_ST_WHCM 0x11
++#define USB_ST_MDLM 0x12
++#define USB_ST_MDLMD 0x13
++#define USB_ST_DMM 0x14
++#define USB_ST_OBEX 0x15
++#define USB_ST_CS 0x16
++#define USB_ST_CSD 0x17
++#define USB_ST_TCM 0x18
++
++
++
++/*
++ * commuications class description structures
++ *
++ * c.f. CDC 5.1
++ * c.f. WCMC 6.7.2
++ *
++ * XXX add the other dozen class descriptor description structures....
++ */
++
++struct usb_header_description {
++ __u8 bDescriptorSubtype;
++ __u16 bcdCDC;
++};
++
++struct usb_call_management_description {
++ __u8 bmCapabilities;
++ __u8 bDataInterface;
++};
++
++struct usb_abstract_control_description {
++ __u8 bmCapabilities;
++};
++
++struct usb_union_function_description {
++ __u8 bMasterInterface;
++ __u8 bSlaveInterface[1];
++ //__u8 bSlaveInterface[0]; // XXX FIXME
++};
++
++struct usb_ethernet_networking_description {
++ char *iMACAddress;
++ __u8 bmEthernetStatistics;
++ __u16 wMaxSegmentSize;
++ __u16 wNumberMCFilters;
++ __u8 bNumberPowerFilters;
++};
++
++struct usb_mobile_direct_line_model_description {
++ __u16 bcdVersion;
++ __u8 bGUID[16];
++};
++
++struct usb_mobile_direct_line_model_detail_description {
++ __u8 bGuidDescriptorType;
++ __u8 bDetailData[2];
++ //__u8 bDetailData[0]; // XXX FIXME
++};
++
++struct usb_class_description {
++ __u8 bDescriptorSubtype;
++ __u8 elements;
++ union {
++ struct usb_header_description header;
++ struct usb_call_management_description call_management;
++ struct usb_abstract_control_description abstract_control;
++ struct usb_union_function_description union_function;
++ struct usb_ethernet_networking_description ethernet_networking;
++ struct usb_mobile_direct_line_model_description mobile_direct;
++ struct usb_mobile_direct_line_model_detail_description mobile_direct_detail;
++ } description;
++};
++
++/* endpoint modifiers
++ * static struct usb_endpoint_description function_default_A_1[] = {
++ *
++ * {this_endpoint: 0, attributes: CONTROL, max_size: 8, polling_interval: 0 },
++ * {this_endpoint: 1, attributes: BULK, max_size: 64, polling_interval: 0, direction: IN},
++ * {this_endpoint: 2, attributes: BULK, max_size: 64, polling_interval: 0, direction: OUT},
++ * {this_endpoint: 3, attributes: INTERRUPT, max_size: 8, polling_interval: 0},
++ *
++ *
++ */
++#define OUT 0x00
++#define IN 0x80
++
++#define CONTROL 0x00
++#define ISOCHRONOUS 0x01
++#define BULK 0x02
++#define INTERRUPT 0x03
++
++
++/* configuration modifiers
++ */
++#define BMATTRIBUTE_RESERVED 0x80
++#define BMATTRIBUTE_SELF_POWERED 0x40
++
++/*
++ * The UUT tester specifically tests for MaxPower to be non-zero (> 0).
++ */
++#if !defined(CONFIG_USBD_MAXPOWER) || (CONFIG_USBD_MAXPOWER == 0)
++ #define BMATTRIBUTE BMATTRIBUTE_RESERVED | BMATTRIBUTE_SELF_POWERED
++ #define BMAXPOWER 1
++#else
++ #define BMATTRIBUTE BMATTRIBUTE_RESERVED
++ #define BMAXPOWER CONFIG_USBD_MAXPOWER
++#endif
++
++
++
++
++/*
++ * standard usb descriptor structures
++ */
++
++struct usb_endpoint_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType; // 0x5
++ __u8 bEndpointAddress;
++ __u8 bmAttributes;
++ __u16 wMaxPacketSize;
++ __u8 bInterval;
++} __attribute__ ((packed));
++
++struct usb_interface_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType; // 0x04
++ __u8 bInterfaceNumber;
++ __u8 bAlternateSetting;
++ __u8 bNumEndpoints;
++ __u8 bInterfaceClass;
++ __u8 bInterfaceSubClass;
++ __u8 bInterfaceProtocol;
++ __u8 iInterface;
++} __attribute__ ((packed));
++
++struct usb_configuration_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType; // 0x2
++ __u16 wTotalLength;
++ __u8 bNumInterfaces;
++ __u8 bConfigurationValue;
++ __u8 iConfiguration;
++ __u8 bmAttributes;
++ __u8 bMaxPower;
++} __attribute__ ((packed));
++
++struct usb_device_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType; // 0x01
++ __u16 bcdUSB;
++ __u8 bDeviceClass;
++ __u8 bDeviceSubClass;
++ __u8 bDeviceProtocol;
++ __u8 bMaxPacketSize0;
++ __u16 idVendor;
++ __u16 idProduct;
++ __u16 bcdDevice;
++ __u8 iManufacturer;
++ __u8 iProduct;
++ __u8 iSerialNumber;
++ __u8 bNumConfigurations;
++} __attribute__ ((packed));
++
++struct usb_string_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType; // 0x03
++ __u16 wData[0];
++} __attribute__ ((packed));
++
++struct usb_device_qualifier_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u16 bcdUSB;
++ __u8 bDeviceClass;
++ __u8 bDeviceSubClass;
++ __u8 bDeviceProtocol;
++ __u8 bMaxPacketSize0;
++ __u8 bNumConfigurations;
++ __u8 bReserved;
++} __attribute__ ((packed));
++
++struct usb_generic_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++} __attribute__ ((packed));
++
++struct usb_generic_class_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype;
++} __attribute__ ((packed));
++
++
++/*
++ * communications class descriptor structures
++ *
++ * c.f. CDC 5.2 Table 25c
++ */
++
++struct usb_class_function_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype;
++} __attribute__ ((packed));
++
++struct usb_class_function_descriptor_generic {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype;
++ __u8 bmCapabilities;
++} __attribute__ ((packed));
++
++struct usb_class_header_function_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x00
++ __u16 bcdCDC;
++} __attribute__ ((packed));
++
++struct usb_class_call_management_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x01
++ __u8 bmCapabilities;
++ __u8 bDataInterface;
++} __attribute__ ((packed));
++
++struct usb_class_abstract_control_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x02
++ __u8 bmCapabilities;
++} __attribute__ ((packed));
++
++struct usb_class_direct_line_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x03
++} __attribute__ ((packed));
++
++struct usb_class_telephone_ringer_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x04
++ __u8 bRingerVolSeps;
++ __u8 bNumRingerPatterns;
++} __attribute__ ((packed));
++
++struct usb_class_telephone_call_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x05
++ __u8 bmCapabilities;
++} __attribute__ ((packed));
++
++struct usb_class_union_function_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x06
++ __u8 bMasterInterface;
++ __u8 bSlaveInterface0[0];
++} __attribute__ ((packed));
++
++struct usb_class_country_selection_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x07
++ __u8 iCountryCodeRelDate;
++ __u16 wCountryCode0[0];
++} __attribute__ ((packed));
++
++
++struct usb_class_telephone_operational_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x08
++ __u8 bmCapabilities;
++} __attribute__ ((packed));
++
++
++struct usb_class_usb_terminal_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x09
++ __u8 bEntityId;
++ __u8 bInterfaceNo;
++ __u8 bOutInterfaceNo;
++ __u8 bmOptions;
++ __u8 bChild0[0];
++} __attribute__ ((packed));
++
++struct usb_class_network_channel_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x0a
++ __u8 bEntityId;
++ __u8 iName;
++ __u8 bChannelIndex;
++ __u8 bPhysicalInterface;
++} __attribute__ ((packed));
++
++struct usb_class_protocol_unit_function_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x0b
++ __u8 bEntityId;
++ __u8 bProtocol;
++ __u8 bChild0[0];
++} __attribute__ ((packed));
++
++struct usb_class_extension_unit_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x0c
++ __u8 bEntityId;
++ __u8 bExtensionCode;
++ __u8 iName;
++ __u8 bChild0[0];
++} __attribute__ ((packed));
++
++struct usb_class_multi_channel_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x0d
++ __u8 bmCapabilities;
++} __attribute__ ((packed));
++
++struct usb_class_capi_control_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x0e
++ __u8 bmCapabilities;
++} __attribute__ ((packed));
++
++struct usb_class_ethernet_networking_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x0f
++ __u8 iMACAddress;
++ __u32 bmEthernetStatistics;
++ __u16 wMaxSegmentSize;
++ __u16 wNumberMCFilters;
++ __u8 bNumberPowerFilters;
++} __attribute__ ((packed));
++
++struct usb_class_atm_networking_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x10
++ __u8 iEndSystermIdentifier;
++ __u8 bmDataCapabilities;
++ __u8 bmATMDeviceStatistics;
++ __u16 wType2MaxSegmentSize;
++ __u16 wType3MaxSegmentSize;
++ __u16 wMaxVC;
++} __attribute__ ((packed));
++
++
++struct usb_class_mdlm_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x12
++ __u16 bcdVersion;
++ __u8 bGUID[16];
++} __attribute__ ((packed));
++
++struct usb_class_mdlmd_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype; // 0x13
++ __u8 bGuidDescriptorType;
++ __u8 bDetailData[0];
++
++} __attribute__ ((packed));
++
++
++/*
++ * descriptor union structures
++ */
++
++struct usb_descriptor {
++ union {
++ struct usb_generic_descriptor generic;
++ struct usb_generic_class_descriptor generic_class;
++ struct usb_endpoint_descriptor endpoint;
++ struct usb_interface_descriptor interface;
++ struct usb_configuration_descriptor configuration;
++ struct usb_device_descriptor device;
++ struct usb_string_descriptor string;
++ } descriptor;
++
++} __attribute__ ((packed));
++
++struct usb_class_descriptor {
++ union {
++ struct usb_class_function_descriptor function;
++ struct usb_class_function_descriptor_generic generic;
++ struct usb_class_header_function_descriptor header_function;
++ struct usb_class_call_management_descriptor call_management;
++ struct usb_class_abstract_control_descriptor abstract_control;
++ struct usb_class_direct_line_descriptor direct_line;
++ struct usb_class_telephone_ringer_descriptor telephone_ringer;
++ struct usb_class_telephone_operational_descriptor telephone_operational;
++ struct usb_class_telephone_call_descriptor telephone_call;
++ struct usb_class_union_function_descriptor union_function;
++ struct usb_class_country_selection_descriptor country_selection;
++ struct usb_class_usb_terminal_descriptor usb_terminal;
++ struct usb_class_network_channel_descriptor network_channel;
++ struct usb_class_extension_unit_descriptor extension_unit;
++ struct usb_class_multi_channel_descriptor multi_channel;
++ struct usb_class_capi_control_descriptor capi_control;
++ struct usb_class_ethernet_networking_descriptor ethernet_networking;
++ struct usb_class_atm_networking_descriptor atm_networking;
++ struct usb_class_mdlm_descriptor mobile_direct;
++ struct usb_class_mdlmd_descriptor mobile_direct_detail;
++ } descriptor;
++
++} __attribute__ ((packed));
++
++
++/*
++ * Audio Status Word Format - c.f. Table 3.1
++ */
++#define AUDIO_STATUS_INTERRUPT_PENDING 1<<7
++#define AUDIO_STATUS_MEMORY_CONTENT_CHANGED 1<<6
++#define AUDIO_STATUS_ORIGINATOR_AUDIO_CONTROL_INTERFACE 0
++#define AUDIO_STATUS_ORIGINATOR_AUDIO_STREAMING_INTERFACE 1
++#define AUDIO_STATUS_ORIGINATOR_AUDIO_STREAMING_ENDPOINT 2
++#define AUDIO_STATUS_ORIGINATOR_AUDIOCONTROL_INTERFACE 0
++
++struct usb_audio_status_word {
++ __u8 bStatusType;
++ __u8 bOriginator;
++} __attribute__ ((packed));
++
++struct usb_audio_ac_interface_header_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype;
++ __u16 bcdADC;
++ __u16 wTotalLength;
++ __u8 binCollection;
++ __u8 bainterfaceNr[0];
++} __attribute__ ((packed));
++
++struct usb_audio_input_terminal_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype;
++ __u8 bTerminalID;
++ __u16 wTerminalType;
++ __u8 bAssocTerminal;
++ __u8 bNrChannels;
++ __u16 wChannelConfig;
++ __u8 iChannelNames;
++ __u8 iTerminal;
++} __attribute__ ((packed));
++
++struct usb_audio_input_terminal_description {
++ struct usb_audio_input_terminal_descriptor *audio_input_terminal_descriptor;
++ __u16 wTerminalType;
++ __u16 wChannelConfig;
++ char * iChannelNames;
++ char * iTerminal;
++};
++
++struct usb_audio_output_terminal_descriptor {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype;
++ __u8 bTerminalID;
++ __u16 wTerminalType;
++ __u8 bAssocTerminal;
++ __u8 bSourceID;
++ __u8 iTerminal;
++} __attribute__ ((packed));
++
++struct usb_audio_output_terminal_description {
++ struct usb_audio_output_terminal_descriptor *audio_output_terminal_descriptor;
++ __u16 wTerminalType;
++ char * iTerminal;
++};
++
++struct usb_audio_mixer_unit_descriptor_a {
++ __u8 bFunctionLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype;
++ __u8 bUniteID;
++ __u8 bNrinPins;
++} __attribute__ ((packed));
++
++struct usb_audio_mixer_unit_descriptor_b {
++ __u8 baSourceID;
++ __u8 bNrChannels;
++ __u16 wChannelConfig;
++ __u8 iChannelNames;
++ __u8 bmControls;
++ __u8 iMixer;
++} __attribute__ ((packed));
++
++struct usb_audio_mixer_unit_description {
++ struct usb_audio_mixer_unit_descriptor *audio_mixer_unit_descriptor;
++ __u16 wChannelConfig;
++ char * iMixer;
++};
++
++
++struct usb_audio_as_general_interface_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype;
++ __u8 bTerminalLink;
++ __u8 bDelay;
++ __u16 wFormatTag;
++} __attribute__ ((packed));
++
++struct usb_audio_as_general_interface_description {
++ struct usb_audio_as_general_interface_descriptor *audio_as_general_interface_descriptor;
++ __u16 wFormatTag;
++};
++
++struct usb_audio_as_format_type_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype;
++ __u8 bFormatType;
++ __u8 bNrChannels;
++ __u8 bSubFrameSize;
++ __u8 bBitResolution;
++ __u8 bSamFreqType;
++ __u8 iSamFreq[3];
++} __attribute__ ((packed));
++
++struct usb_audio_as_format_type_description {
++ struct usb_audio_as_format_type_descriptor *audio_as_format_type_descriptor;
++ __u16 wFormatTag;
++};
++
++
++
++
++struct usb_audio_descriptor {
++ union {
++ struct usb_audio_ac_interface_header_descriptor header;
++ struct usb_audio_input_terminal_descriptor input;
++ struct usb_audio_output_terminal_descriptor output;
++ } descriptor;
++} __attribute__ ((packed));
++
++
++
++struct usb_ac_endpoint_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bEndpointAddress;
++ __u8 bmAttributes;
++ __u16 wMaxPacketSize;
++ __u8 bInterval;
++ __u8 bRefresh;
++ __u8 bSynchAddress;
++} __attribute__ ((packed));
++
++
++struct usb_as_iso_endpoint_descriptor {
++ __u8 bLength;
++ __u8 bDescriptorType;
++ __u8 bDescriptorSubtype;
++ __u8 bmAttributes;
++ __u8 bLockDelayUnits;
++ __u16 wLockDelay;
++} __attribute__ ((packed));
++
++
+diff -Nru a/drivers/usbd/usbd-export.h b/drivers/usbd/usbd-export.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-export.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1 @@
++#define USBD_EXPORT_TAG "usbd-gpl-20040227-1420-usbd-amd-pb1x00-kit"
+diff -Nru a/drivers/usbd/usbd-fops.c b/drivers/usbd/usbd-fops.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-fops.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,589 @@
++/*
++ * usbd/usbd-fops.c - USB Function support
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2000, 2001, 2002 Lineo
++ * Copyright (c) 2001 Hewlett Packard
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/list.h>
++#include <asm/uaccess.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++
++#include <linux/smp_lock.h>
++#include <linux/ctype.h>
++#include <linux/timer.h>
++#include <linux/string.h>
++
++#include "usbd-chap9.h"
++#include "usbd-mem.h"
++#include "usbd.h"
++#include "usbd-func.h"
++#include "usbd-bus.h"
++
++
++struct usb_string_descriptor **usb_strings;
++
++extern struct list_head usbd_function_drivers;
++extern struct usb_bus_instance *usbd_bus_instance;
++
++
++/* usbd_get_string - find and return a string descriptor
++ *
++ * Find an indexed string and return a pointer to a it.
++ */
++struct usb_string_descriptor *usbd_get_string (__u8 index)
++{
++ RETURN_NULL_IF (index >= usbd_maxstrings);
++ return usb_strings[index];
++}
++
++/* usbd_alloc_string - allocate a string descriptor and return index number
++ *
++ * Find an empty slot in index string array, create a corresponding descriptor
++ * and return the slot number.
++ */
++__u8 usbd_alloc_string (char *str)
++{
++ int i;
++ struct usb_string_descriptor *string;
++ __u8 bLength;
++ __u16 *wData;
++
++ RETURN_ZERO_IF(!str || !strlen (str));
++
++ //printk(KERN_INFO"%s: %s\n", __FUNCTION__, str);
++
++ // find an empty string descriptor slot
++ for (i = 1; i < usbd_maxstrings; i++) {
++
++ CONTINUE_IF (usb_strings[i] != NULL);
++
++ bLength = sizeof (struct usb_string_descriptor) + 2 * strlen (str);
++
++ RETURN_ZERO_IF(!(string = ckmalloc (bLength, GFP_KERNEL)));
++
++ string->bLength = bLength;
++ string->bDescriptorType = USB_DT_STRING;
++
++ for (wData = string->wData; *str;)
++ *wData++ = (__u16) (*str++);
++
++ // store in string index array
++ usb_strings[i] = string;
++ return i;
++ }
++ return 0;
++}
++
++
++/* usbd_dealloc_string - deallocate a string descriptor
++ *
++ * Find and remove an allocated string.
++ */
++void usbd_dealloc_string (__u8 index)
++{
++ struct usb_string_descriptor *string;
++
++ if ((index < usbd_maxstrings) && (string = usb_strings[index])) {
++ usb_strings[index] = NULL;
++ lkfree (string);
++ }
++}
++
++/* usbd_alloc_urb - allocate an URB appropriate for specified endpoint
++ *
++ * Allocate an urb structure. The usb device urb structure is used to
++ * contain all data associated with a transfer, including a setup packet for
++ * control transfers.
++ */
++struct urb *usbd_alloc_urb (struct usb_function_instance *function, int endpoint_index,
++ int length, int (*callback) (struct urb *, int))
++{
++ struct urb *urb = NULL;
++ struct usb_endpoint_map *endpoint_map;
++ struct usb_endpoint_instance *endpoint;
++ unsigned long flags;
++
++ //printk(KERN_INFO"%s: %s\n", __FUNCTION__, function->function_driver->name);
++ RETURN_NULL_IF(!function);
++ RETURN_NULL_IF(!(endpoint_map = function->endpoint_map_array));
++ RETURN_NULL_IF(!(endpoint = endpoint_map[endpoint_index].endpoint));
++
++ local_irq_save(flags);
++ THROW_IF (!(urb = ckmalloc (sizeof (struct urb), GFP_ATOMIC)), error);
++ urb->endpoint = endpoint;
++ urb->bus = function->bus;
++ urb->function_instance = function;
++ urb->link.prev = urb->link.next = &urb->link;
++ urb->callback = callback;
++ urb->buffer_length = urb->actual_length = 0;
++
++ if (length) {
++ urb->request_length = length;
++
++ /* For receive we always overallocate to ensure that receiving another
++ * full sized packet when we are only expecting a short packet will
++ * not overflow the buffer
++ */
++ if (!endpoint->bEndpointAddress || endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) {
++ length = ((length / endpoint->wMaxPacketSize) + 1) * endpoint->wMaxPacketSize;
++ }
++ urb->buffer_length = length;
++
++ if (urb->endpoint && urb->endpoint->bEndpointAddress && urb->function_instance &&
++ urb->function_instance->function_driver->fops->alloc_urb_data)
++ {
++ THROW_IF(urb->function_instance->function_driver->fops->alloc_urb_data (urb, length), error);
++ }
++ else {
++ THROW_IF(!(urb->buffer = ckmalloc (length, GFP_ATOMIC)), error);
++ }
++ }
++
++ CATCH(error) {
++ printk(KERN_ERR"%s: dealloc %p\n", __FUNCTION__, urb);
++ usbd_dealloc_urb(urb);
++ urb = NULL;
++ }
++ local_irq_restore(flags);
++ //printk(KERN_INFO"%s: finis %p\n", __FUNCTION__, urb);
++ return urb;
++}
++
++struct urb *usbd_alloc_urb_ep0 (struct usb_function_instance *function, int length, int (*callback) (struct urb *, int))
++{
++ return usbd_alloc_urb(function->bus->ep0, 0, length, callback);
++}
++
++/* usbd_dealloc_urb - deallocate an URB and associated buffer
++ *
++ * Deallocate an urb structure and associated data.
++ */
++void usbd_dealloc_urb (struct urb *urb)
++{
++ RETURN_IF (!urb);
++ if (urb->buffer)
++ (urb->function_instance && urb->function_instance->function_driver->fops->dealloc_urb_data) ?
++ urb->function_instance->function_driver->fops->dealloc_urb_data : lkfree (urb->buffer);
++ lkfree (urb);
++}
++
++/* usbd_urb_callback - tell function that an urb has been transmitted.
++ *
++ * Must be called from an interrupt or with interrupts disabled.
++ *
++ * Used by a USB Bus driver to pass a sent urb back to the function
++ * driver via the endpoints done queue.
++ */
++void usbd_urb_callback (struct urb *urb, int rc)
++{
++ RETURN_IF (!urb);
++ if (!urb->callback || urb->callback(urb,rc))
++ usbd_dealloc_urb(urb);
++}
++
++
++/* usbd_recv_setup_irq - process a received urb
++ *
++ * Used by a USB Bus interface driver to pass received data in a URB to the
++ * appropriate USB Function driver.
++ */
++int usbd_recv_setup_irq (struct usb_function_instance *function, struct usb_device_request *request)
++{
++ return function->function_driver->fops->recv_setup_irq(request);
++}
++
++void *usbd_function_get_privdata(struct usb_function_instance *function)
++{
++ return(function->privdata);
++}
++
++void usbd_function_set_privdata(struct usb_function_instance *function, void *privdata)
++{
++ function->privdata = privdata;
++}
++
++int usbd_endpoint_wMaxPacketSize(struct usb_function_instance *function, int endpoint_index, int hs)
++{
++ struct usb_endpoint_map *endpoint_map;
++ RETURN_ZERO_IF(!(endpoint_map = function->endpoint_map_array));
++ return le16_to_cpu(endpoint_map[endpoint_index].wMaxPacketSize[hs]);
++}
++
++int usbd_endpoint_bEndpointAddress(struct usb_function_instance *function, int endpoint_index, int hs)
++{
++ struct usb_endpoint_map *endpoint_map;
++ RETURN_ZERO_IF(!(endpoint_map = function->endpoint_map_array));
++ return endpoint_map[endpoint_index].bEndpointAddress[hs];
++}
++
++int usbd_endpoint_transferSize(struct usb_function_instance *function, int endpoint_index, int hs)
++{
++ struct usb_endpoint_map *endpoint_map;
++ RETURN_ZERO_IF(!(endpoint_map = function->endpoint_map_array));
++ return endpoint_map[endpoint_index].transferSize[hs];
++}
++
++void usbd_endpoint_update(struct usb_function_instance *function, int endpoint_index,
++ struct usb_endpoint_descriptor *endpoint, int hs)
++{
++ endpoint->bEndpointAddress = usbd_endpoint_bEndpointAddress(function, endpoint_index, hs);
++ endpoint->wMaxPacketSize = usbd_endpoint_wMaxPacketSize(function, endpoint_index, hs);
++}
++
++int usbd_endpoint_interface(struct usb_function_instance *function, int endpoint_index)
++{
++ struct usb_endpoint_map *endpoint_map;
++ RETURN_ZERO_IF(!(endpoint_map = function->endpoint_map_array));
++ return endpoint_map[endpoint_index].interface;
++}
++
++int usbd_interface_AltSetting(struct usb_function_instance *function, int interface_index)
++{
++ // XXX TODO - per function modifications for composite devices
++ return function->bus->alternates[interface_index];
++}
++
++int usbd_ConfigurationValue(struct usb_function_instance *function)
++{
++ // XXX TODO - per function modifications for composite devices
++ return function->bus->ConfigurationValue;
++}
++
++int usbd_high_speed(struct usb_function_instance *function)
++{
++ // XXX TODO - per function modifications for composite devices
++ return function->bus->HighSpeedFlag;
++}
++
++/* usb-device USB FUNCTION generic functions ************************************************* */
++
++/* alloc_function_alternates - allocate alternate instance array
++ *
++ * Return a pointer to an array of alternate instances. Each instance contains a pointer
++ * to a filled in alternate descriptor and a pointer to the endpoint descriptor array.
++ *
++ * Returning NULL will cause the caller to cleanup all previously allocated memory.
++ */
++static struct usb_alternate_instance *alloc_function_alternates (int bInterfaceNumber,
++ struct usb_interface_description *interface_description,
++ int alternates, struct usb_alternate_description *alternate_description_array)
++{
++ int i;
++ struct usb_alternate_instance *alternate_instance_array;
++
++ // allocate array of alternate instances
++ RETURN_NULL_IF(!(alternate_instance_array = ckmalloc (sizeof (struct usb_alternate_instance) * alternates, GFP_KERNEL)));
++
++ // iterate across the alternate descriptions
++ for (i = 0; i < alternates; i++) {
++
++ struct usb_alternate_description *alternate_description = alternate_description_array + i;
++ struct usb_alternate_instance *alternate_instance = alternate_instance_array + i;
++ struct usb_interface_descriptor *interface_descriptor;
++
++ interface_descriptor = alternate_description->interface_descriptor;
++ if (interface_descriptor->bInterfaceNumber != bInterfaceNumber) {
++ printk(KERN_INFO"%s: bInterfaceNumber mis-match: %d should be %d\n", __FUNCTION__,
++ interface_descriptor->bInterfaceNumber, bInterfaceNumber);
++ lkfree(alternate_instance_array);
++ return NULL;
++ }
++
++ interface_descriptor->bNumEndpoints = alternate_description->endpoints;
++ interface_descriptor->iInterface = usbd_alloc_string (alternate_description->iInterface );
++
++ alternate_instance->class_list = alternate_description->class_list;
++ alternate_instance->classes = alternate_description->classes;
++ alternate_instance->endpoint_list = alternate_description->endpoint_list;
++ alternate_instance->endpoint_indexes = alternate_description->endpoint_indexes;
++
++ // save number of alternates, classes and endpoints for this alternate
++ alternate_instance->endpoints = alternate_description->endpoints;
++ alternate_instance->interface_descriptor = interface_descriptor;
++ }
++ return alternate_instance_array;
++}
++
++/* alloc_function_interfaces - allocate interface instance array
++ *
++ * Return a pointer to an array of interface instances. Each instance contains a pointer
++ * to a filled in interface descriptor and a pointer to the endpoint descriptor array.
++ *
++ * Returning NULL will cause the caller to cleanup all previously allocated memory.
++ */
++static struct usb_interface_instance *alloc_function_interfaces (int bNumInterfaces,
++ struct usb_interface_description *interface_description_array)
++{
++ int interface;
++ struct usb_interface_instance *interface_instance_array;
++
++ // allocate array of interface instances
++ RETURN_NULL_IF(!(interface_instance_array =
++ ckmalloc (sizeof (struct usb_interface_instance) * bNumInterfaces, GFP_KERNEL)));
++
++ // iterate across the interface descriptions
++ for (interface = 0; interface < bNumInterfaces; interface++) {
++
++ struct usb_interface_description *interface_description = interface_description_array + interface;
++ struct usb_interface_instance *interface_instance = interface_instance_array + interface;
++
++ interface_instance->alternates_instance_array =
++ alloc_function_alternates (interface, interface_description,
++ interface_description->alternates, interface_description->alternate_list);
++ interface_instance->alternates = interface_description->alternates;
++ }
++ return interface_instance_array;
++}
++
++
++/* alloc_function_configurations - allocate configuration instance array
++ *
++ * Return a pointer to an array of configuration instances. Each instance contains a pointer
++ * to a filled in configuration descriptor and a pointer to the interface instances array.
++ *
++ * Returning NULL will cause the caller to cleanup all previously allocated memory.
++ */
++static struct usb_configuration_instance *alloc_function_configurations (int bNumConfigurations,
++ struct usb_configuration_description *configuration_description_array)
++{
++ int i;
++ struct usb_configuration_instance *configuration_instance_array;
++
++ // allocate array
++ RETURN_NULL_IF(!(configuration_instance_array =
++ ckmalloc (sizeof (struct usb_configuration_instance) * bNumConfigurations, GFP_KERNEL)));
++ // fill in array
++ for (i = 0; i < bNumConfigurations; i++) {
++ int j;
++ int length;
++
++ struct usb_configuration_description *configuration_description = configuration_description_array + i;
++ struct usb_configuration_descriptor *configuration_descriptor;
++
++ configuration_descriptor = configuration_description->configuration_descriptor;
++
++ // setup fields in configuration descriptor
++ // XXX c.f. 9.4.7 zero is default, so config MUST BE 1 to n, not 0 to n-1
++ // XXX N.B. the configuration itself is fetched 0 to n-1.
++
++ configuration_descriptor->bConfigurationValue = i + 1;
++ configuration_descriptor->wTotalLength = 0;
++ configuration_descriptor->bNumInterfaces = configuration_description->bNumInterfaces;
++ configuration_descriptor->iConfiguration = usbd_alloc_string (configuration_description->iConfiguration);
++
++ // save the configuration descriptor in the configuration instance array
++ configuration_instance_array[i].configuration_descriptor = configuration_descriptor;
++
++ RETURN_NULL_IF (!(configuration_instance_array[i].interface_instance_array =
++ alloc_function_interfaces (configuration_description->bNumInterfaces,
++ configuration_description->interface_list)));
++
++ length = sizeof(struct usb_configuration_descriptor);
++
++ for (j = 0; j < configuration_descriptor->bNumInterfaces; j++) {
++
++ int alternate;
++ struct usb_interface_instance *interface_instance =
++ configuration_instance_array[i].interface_instance_array + j;
++
++ //printk(KERN_INFO"%s: len: %02x:%02d configuration\n", __FUNCTION__, length, length);
++ for (alternate = 0; alternate < interface_instance->alternates; alternate++) {
++ int class;
++ int endpoint;
++ struct usb_alternate_instance *alternate_instance =
++ interface_instance->alternates_instance_array + alternate;
++
++ length += sizeof (struct usb_interface_descriptor);
++
++ //printk(KERN_INFO"%s: len: %02x:%02d interface\n", __FUNCTION__, length, length);
++ for (class = 0; class < alternate_instance->classes; class++) {
++ struct usb_generic_class_descriptor * class_descriptor =
++ *(alternate_instance->class_list + class);
++ length += class_descriptor->bLength;
++ //printk(KERN_INFO"%s: len: %02x:%02d class\n", __FUNCTION__, length, length);
++ }
++
++ for (endpoint = 0; endpoint < alternate_instance->endpoints; endpoint++) {
++ struct usb_endpoint_descriptor * endpoint_descriptor =
++ *(alternate_instance->endpoint_list + endpoint);
++ length += endpoint_descriptor->bLength;
++ //printk(KERN_INFO"%s: len: %02x:%02d endpoint\n", __FUNCTION__, length, length);
++ }
++ }
++ }
++ configuration_descriptor->wTotalLength = cpu_to_le16 (length);
++ configuration_instance_array[i].bNumInterfaces = configuration_description->bNumInterfaces;
++ //printk(KERN_INFO"%s: configuration_instance_array[%d]: %p\n", __FUNCTION__, i,
++ // &configuration_instance_array[i]);
++ }
++ return configuration_instance_array;
++}
++
++
++void usbd_func_event_irq(struct usb_bus_instance *bus, struct usb_function_instance *function,
++ usb_device_event_t event , int data)
++{
++ function->function_driver->fops->event_irq(function, event, data);
++}
++
++
++/* usbd_register_function - register a usb function driver
++ *
++ * Used by a USB Function driver to register itself with the usb device layer.
++ *
++ * It will create a usb_function_instance structure.
++ *
++ * The user friendly configuration/interface/endpoint descriptions are compiled into
++ * the equivalent ready to use descriptor records.
++ *
++ * All function drivers must register before any bus interface drivers.
++ *
++ */
++int usbd_register_function (struct usb_function_driver *function_driver)
++{
++ MOD_INC_USE_COUNT;
++ list_add_tail (&function_driver->drivers, &usbd_function_drivers);
++ return 0;
++}
++
++
++/* usbd_deregister_function - called by a USB FUNCTION driver to deregister itself
++ *
++ * Called by a USB Function driver De-register a usb function driver.
++ */
++void usbd_deregister_function (struct usb_function_driver *function_driver)
++{
++ list_del (&function_driver->drivers);
++ MOD_DEC_USE_COUNT;
++}
++
++
++int usbd_function_enable (struct usb_bus_instance *bus, struct usb_function_instance *function)
++{
++ struct usb_function_driver *function_driver = function->function_driver;
++ struct usb_device_description *device_description;
++ struct usb_device_descriptor *device_descriptor;
++ int rc = 0;
++
++ function->bus = bus;
++
++ RETURN_EINVAL_IF(function_driver->fops->function_enable (function));
++ RETURN_ZERO_IF(!(device_description = function_driver->device_description));
++ RETURN_ZERO_IF(!(device_descriptor = device_description->device_descriptor));
++
++ device_descriptor->bMaxPacketSize0 = bus->driver->maxpacketsize;
++ device_descriptor->iManufacturer = usbd_alloc_string (device_description->iManufacturer);
++ device_descriptor->iProduct = usbd_alloc_string (device_description->iProduct);
++
++ if (bus->serial_number_str && strlen (bus->serial_number_str))
++ device_descriptor->iSerialNumber = usbd_alloc_string (bus->serial_number_str);
++ else
++ device_descriptor->iSerialNumber = usbd_alloc_string (device_description->iSerialNumber);
++
++ device_descriptor->bNumConfigurations = function_driver->bNumConfigurations;
++ device_descriptor->idVendor = function_driver->idVendor;
++ device_descriptor->idProduct = function_driver->idProduct;
++ device_descriptor->bcdDevice = function_driver->bcdDevice;
++
++ /* call alloc_function_configurations() to allocate the configuration descriptor array
++ */
++ RETURN_EINVAL_IF (!(function_driver->configuration_instance_array =
++ alloc_function_configurations (function_driver->bNumConfigurations,
++ function_driver->configuration_description)));
++ function_driver->device_descriptor = device_descriptor;
++ function_driver->device_qualifier_descriptor = device_description->device_qualifier_descriptor;
++ return rc;
++}
++
++
++void usbd_function_disable (struct usb_function_instance *function)
++{
++ int configuration;
++ struct usb_function_driver *function_driver = function->function_driver;
++ struct usb_configuration_instance *configuration_instance_array = function_driver->configuration_instance_array;
++
++ function->function_driver->fops->function_disable (function);
++
++ RETURN_IF(!function_driver->configuration_instance_array);
++
++ // iterate across the descriptors list and de-allocate all structures
++ if (function_driver->configuration_instance_array) {
++ for (configuration = 0; configuration < function_driver->bNumConfigurations; configuration++) {
++ int interface;
++ struct usb_configuration_instance *configuration_instance = configuration_instance_array + configuration;
++
++ for (interface = 0; interface < configuration_instance->bNumInterfaces; interface++) {
++
++ //int alternate;
++ struct usb_interface_instance *interface_instance =
++ configuration_instance->interface_instance_array + interface;
++
++ lkfree (interface_instance->alternates_instance_array);
++ }
++ lkfree (configuration_instance->interface_instance_array);
++ //usbd_dealloc_descriptor_strings( (struct usb_descriptor *)
++ // configuration_instance_array[configuration].configuration_descriptor);
++ }
++ }
++
++ //usbd_dealloc_descriptor_strings ((struct usb_descriptor *) function_driver->device_descriptor);
++ lkfree (configuration_instance_array);
++
++ function->bus = NULL;
++}
++
++EXPORT_SYMBOL(usbd_register_function );
++EXPORT_SYMBOL(usbd_deregister_function);
++EXPORT_SYMBOL(usbd_alloc_string);
++EXPORT_SYMBOL(usbd_dealloc_string);
++EXPORT_SYMBOL(usbd_get_string);
++EXPORT_SYMBOL(usbd_alloc_urb);
++EXPORT_SYMBOL(usbd_alloc_urb_ep0);
++EXPORT_SYMBOL(usbd_dealloc_urb);
++EXPORT_SYMBOL(usbd_recv_setup_irq);
++EXPORT_SYMBOL(usbd_urb_callback);
++EXPORT_SYMBOL(usbd_endpoint_halted);
++EXPORT_SYMBOL(usbd_device_feature);
++EXPORT_SYMBOL(usbd_function_get_privdata);
++EXPORT_SYMBOL(usbd_function_set_privdata);
++
++EXPORT_SYMBOL(usbd_endpoint_wMaxPacketSize);
++EXPORT_SYMBOL(usbd_endpoint_bEndpointAddress);
++EXPORT_SYMBOL(usbd_endpoint_interface);
++EXPORT_SYMBOL(usbd_endpoint_transferSize);
++EXPORT_SYMBOL(usbd_interface_AltSetting);
++EXPORT_SYMBOL(usbd_ConfigurationValue);
++EXPORT_SYMBOL(usbd_high_speed);
++EXPORT_SYMBOL(usbd_endpoint_update);
+diff -Nru a/drivers/usbd/usbd-func.h b/drivers/usbd/usbd-func.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-func.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,256 @@
++/*
++ * usbd/usbd-func.h - USB Device Function Driver Interface
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2000, 2001, 2002 Lineo
++ * Copyright (c) 2001 Hewlett Packard
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++/*
++ * This file contains the USB Function Driver Interface definitions.
++ *
++ * This is the interface between the bottom of the USB Function drivers and
++ * the top of the USB Core and is comprised of:
++ *
++ * o public functions exported by the USB Core layer
++ *
++ * o structures and functions passed by the Bus Interface Driver to the
++ * USB Core layer
++ *
++ *
++ * USB Function Drivers are structured such that the upper edge implements
++ * some specific function (network, serial, mass storage etc) and the lower
++ * edge interfaces to the USB Device Core for USB services.
++ *
++ */
++
++/*
++ * USB Function Driver structures
++ *
++ * Descriptors:
++ * struct usb_endpoint_description
++ * struct usb_interface_description
++ * struct usb_configuration_description
++ *
++ * Driver description:
++ * struct usb_function_driver
++ * struct usb_function_operations
++ *
++ */
++
++struct usb_function_operations {
++ int (*function_enable) (struct usb_function_instance *);
++ void (*function_disable) (struct usb_function_instance *);
++ void (*event_irq) (struct usb_function_instance *, usb_device_event_t, int);
++ int (*recv_setup_irq) (struct usb_device_request *);
++ int (*alloc_urb_data) (struct urb *, int);
++ void (*dealloc_urb_data) (struct urb *);
++};
++
++
++/*
++ * function driver definitions
++ */
++struct usb_alternate_instance {
++ struct usb_interface_descriptor *interface_descriptor;
++ int classes;
++ struct usb_generic_class_descriptor **class_list;
++ int endpoints;
++ struct usb_endpoint_descriptor **endpoint_list;
++ u8 *endpoint_indexes;
++};
++
++
++/*
++ * usb device description structures
++ */
++
++struct usb_alternate_description {
++ struct usb_interface_descriptor *interface_descriptor;
++ char *iInterface;
++
++ // list of CDC class descriptions for this alternate interface
++ u8 classes;
++ struct usb_generic_class_descriptor **class_list;
++
++ // list of endpoint descriptions for this alternate interface
++ u8 endpoints;
++ struct usb_endpoint_descriptor **endpoint_list;
++
++ // list of indexes into endpoint request map for each endpoint descriptor
++ u8 *endpoint_indexes;
++};
++
++struct usb_interface_description {
++ // list of alternate interface descriptions for this interface
++ u8 alternates;
++ struct usb_alternate_description *alternate_list;
++};
++
++struct usb_configuration_description {
++ struct usb_configuration_descriptor *configuration_descriptor;
++ char *iConfiguration;
++ // list of interface descriptons for this configuration
++ u8 bNumInterfaces;
++ struct usb_interface_description *interface_list;
++ int configuration_type;
++};
++
++struct usb_device_description {
++ struct usb_device_descriptor *device_descriptor;
++ struct usb_device_qualifier_descriptor *device_qualifier_descriptor;
++ char *iManufacturer;
++ char *iProduct;
++ char *iSerialNumber;
++ u8 endpointsRequested;
++ struct usb_endpoint_request *requestedEndpoints;
++ struct usb_function_endpoint_config *endpointConfig;
++};
++
++
++struct usb_interface_instance {
++ u8 alternates;
++ struct usb_alternate_instance *alternates_instance_array;
++};
++
++struct usb_configuration_instance {
++ int bNumInterfaces;
++ struct usb_configuration_descriptor *configuration_descriptor;
++ struct usb_interface_instance *interface_instance_array;
++ struct usb_function_driver *function_driver;
++};
++
++
++extern struct usb_string_descriptor **usb_strings;
++__u8 usbd_alloc_string (char *);
++void usbd_dealloc_string (__u8 );
++void usbd_dealloc_descriptor_strings (struct usb_descriptor *);
++struct usb_string_descriptor *usbd_get_string (__u8);
++
++
++
++
++/* Function Driver data structure
++ *
++ * Function driver and its configuration descriptors.
++ *
++ * This is passed to the usb-device layer when registering. It contains all
++ * required information about the function driver for the usb-device layer
++ * to use the function drivers configuration data and to configure this
++ * function driver an active configuration.
++ *
++ * Note that each function driver registers itself on a speculative basis.
++ * Whether a function driver is actually configured will depend on the USB
++ * HOST selecting one of the function drivers configurations.
++ *
++ * This may be done multiple times WRT to either a single bus interface
++ * instance or WRT to multiple bus interface instances. In other words a
++ * multiple configurations may be selected for a specific bus interface. Or
++ * the same configuration may be selected for multiple bus interfaces.
++ *
++ */
++struct usb_function_driver {
++ const char *name;
++ struct usb_function_operations *fops; // functions
++
++ // device & configuration descriptions
++ struct usb_device_description *device_description;
++ struct usb_configuration_description *configuration_description;
++ int bNumConfigurations;
++
++ u16 idVendor;
++ u16 idProduct;
++ u16 bcdDevice;
++
++ // constructed descriptors
++ struct usb_device_descriptor *device_descriptor;
++ struct usb_device_qualifier_descriptor *device_qualifier_descriptor;
++ struct usb_configuration_instance *configuration_instance_array;
++
++ struct list_head drivers; // linked list
++};
++
++
++struct usb_function_instance;
++
++/* function driver registration
++ *
++ * Called by function drivers to register themselves when loaded
++ * or de-register when unloading.
++ */
++//int usbd_strings_init(void);
++int usbd_register_function (struct usb_function_driver *);
++void usbd_deregister_function (struct usb_function_driver *);
++
++/* Access to function privdata
++ */
++void *usbd_function_get_privdata(struct usb_function_instance *function);
++void usbd_function_set_privdata(struct usb_function_instance *function, void *privdata);
++/*
++ * Called to queue urb's for send or recv
++ */
++int usbd_send_urb (struct urb *urb);
++int usbd_start_recv (struct urb *);
++
++/*
++ * queury endpoint astatus
++ */
++int usbd_endpoint_halted (struct usb_function_instance *, int);
++int usbd_device_feature (struct usb_function_instance *, int, int);
++
++
++/*
++ * query bus state and status
++ */
++usb_device_state_t usbd_device_state(struct usb_function_instance *);
++usbd_bus_state_t usbd_bus_state(struct usb_function_instance *);
++usb_device_status_t usbd_bus_status(struct usb_function_instance *);
++
++
++/* urb allocation
++ *
++ * Used to allocate and de-allocate urb structures.
++ * usb_cancel_urb is used to cancel a previously submitted data urb for sending.
++ */
++struct urb *usbd_alloc_urb (struct usb_function_instance *, int, int length, int (*callback) (struct urb *, int));
++struct urb *usbd_alloc_urb_ep0 (struct usb_function_instance *, int length, int (*callback) (struct urb *, int));
++void usbd_dealloc_urb (struct urb *urb);
++int usbd_alloc_urb_data (struct urb *, int);
++int usbd_cancel_urb_irq (struct urb *);
++
++/* endpoint information
++ *
++ * Used by function drivers to get specific endpoint information
++ */
++int usbd_endpoint_wMaxPacketSize(struct usb_function_instance *, int, int);
++int usbd_endpoint_bEndpointAddress(struct usb_function_instance *, int, int);
++int usbd_endpoint_transferSize(struct usb_function_instance *, int, int);
++int usbd_endpoint_interface(struct usb_function_instance *, int);
++int usbd_interface_AltSetting(struct usb_function_instance *, int);
++int usbd_ConfigurationValue(struct usb_function_instance *);
++void usbd_endpoint_update(struct usb_function_instance *, int , struct usb_endpoint_descriptor *, int);
++int usbd_high_speed(struct usb_function_instance *);
++
+diff -Nru a/drivers/usbd/usbd-mem.h b/drivers/usbd/usbd-mem.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-mem.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,146 @@
++/*
++ * usbd/usbd-mem.h
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2000, 2001, 2002 Lineo
++ * Copyright (c) 2001 Hewlett Packard
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++
++#ifndef MODULE
++#undef __init
++#define __init
++#undef __exit
++#define __exit
++#undef THIS_MODULE
++#define THIS_MODULE 0
++#endif
++
++#define USBD_MODULE_INFO(info) static const char __usbd_module_info[] = info " " USBD_BUILD " %D% %@%";
++
++
++#ifndef MIN
++#define MIN(a,b) ((a) < (b) ? (a) : (b))
++#endif
++#ifndef MAX
++#define MAX(a,b) ((a) > (b) ? (a) : (b))
++#endif
++#define CATCH(x) while(0) x:
++#define THROW(x) goto x
++#define THROW_IF(e, x) if (e) goto x;
++#define BREAK_IF(x) if (x) break;
++#define CONTINUE_IF(x) if (x) continue;
++#define RETURN_IF(x) if (x) return;
++#define RETURN_ZERO_IF(x) if (x) return 0;
++#define RETURN_EINVAL_IF(x) if (x) return -EINVAL;
++#define RETURN_EFAULT_IF(x) if (x) return -EFAULT;
++#define RETURN_ENOMEM_IF(x) if (x) return -ENOMEM;
++#define RETURN_EBUSY_IF(x) if (x) return -EBUSY;
++#define RETURN_NULL_IF(x) if (x) return NULL;
++#define unless(x) if(!(x))
++#define UNLESS(x) if(!(x))
++#define RETURN_UNLESS(x) UNLESS (x) return;
++#define RETURN_ZERO_UNLESS(x) UNLESS (x) return 0;
++#define CONTINUE_UNLESS(x) UNLESS (x) continue;
++
++
++#ifndef likely
++#define likely(x) x
++#endif
++
++#ifndef unlikely
++#define unlikely(x) x
++#endif
++
++#define ckmalloc(n,f) _ckmalloc(__FUNCTION__, __LINE__, n, f)
++#define lstrdup(str) _lstrdup(__FUNCTION__, __LINE__, str)
++#define lkfree(p) _lkfree(__FUNCTION__, __LINE__, p)
++
++#define MALLOC_TEST
++#undef MALLOC_DEBUG
++
++#ifdef MALLOC_TEST
++extern int usbd_mallocs;
++#endif
++
++
++static __inline__ void *_ckmalloc (char *func, int line, int n, int f)
++{
++ void *p;
++ if ((p = kmalloc (n, f)) == NULL) {
++ return NULL;
++ }
++ memset (p, 0, n);
++#ifdef MALLOC_TEST
++ ++usbd_mallocs;
++#endif
++#ifdef MALLOC_DEBUG
++ printk(KERN_INFO"%s: %p %s %d %d\n", __FUNCTION__, p, func, line, usbd_mallocs);
++#endif
++ return p;
++}
++
++static __inline__ char *_lstrdup (char *func, int line, char *str)
++{
++ int n;
++ char *s;
++ if (str && (n = strlen (str) + 1) && (s = kmalloc (n, GFP_ATOMIC))) {
++#ifdef MALLOC_TEST
++ ++usbd_mallocs;
++#endif
++#ifdef MALLOC_DEBUG
++ printk(KERN_INFO"%s: %p %s %d %d\n", __FUNCTION__, s, func, line, usbd_mallocs);
++#endif
++ return strcpy (s, str);
++ }
++ return NULL;
++}
++
++static __inline__ void _lkfree (char *func, int line, void *p)
++{
++ if (p) {
++#ifdef MALLOC_TEST
++ --usbd_mallocs;
++#endif
++#ifdef MALLOC_DEBUG
++ printk(KERN_INFO"%s: %p %s %d %d\n", __FUNCTION__, p, func, line, usbd_mallocs);
++#endif
++ kfree (p);
++#ifdef MALLOC_TEST
++ if (usbd_mallocs < 0) {
++ printk(KERN_INFO"%s: %p %s %d %d usbd_mallocs less zero!\n", __FUNCTION__, p, func, line, usbd_mallocs);
++ }
++#endif
++ }
++#ifdef MALLOC_DEBUG
++ else {
++ printk(KERN_INFO"%s: %s %d NULL\n", __FUNCTION__, func, line);
++ }
++#endif
++}
++
++
++
+diff -Nru a/drivers/usbd/usbd-procfs.c b/drivers/usbd/usbd-procfs.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd-procfs.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,337 @@
++/*
++ * usbd/usbd-procfs.c - USB Device Core Layer
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2000, 2001, 2002 Lineo
++ * Copyright (c) 2001 Hewlett Packard
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++
++EXPORT_NO_SYMBOLS;
++
++#include "usbd-export.h"
++#include "usbd-build.h"
++
++#ifdef MODULE
++MODULE_AUTHOR ("sl@lineo.com, tbr@lineo.com");
++MODULE_DESCRIPTION ("USB Device Core Support Procfs");
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
++MODULE_LICENSE("GPL");
++#endif
++
++#endif
++
++#include <linux/init.h>
++#include <linux/list.h>
++#include <linux/proc_fs.h>
++#include <asm/uaccess.h>
++#include <linux/slab.h>
++#include <linux/interrupt.h>
++
++#include <linux/smp_lock.h>
++#include <linux/ctype.h>
++#include <linux/timer.h>
++#include <linux/string.h>
++
++#include "usbd-chap9.h"
++#include "usbd-mem.h"
++#include "usbd.h"
++#include "usbd-func.h"
++#include "usbd-bus.h"
++
++USBD_MODULE_INFO ("usbdprocfs 2.0-beta");
++
++#define MAX_INTERFACES 2
++
++extern struct list_head usbd_function_drivers;
++extern struct usb_bus_instance *usbd_bus_instance;
++
++
++#ifdef CONFIG_USBD_PROCFS
++/* Proc Filesystem *************************************************************************** */
++
++
++/* *
++ * dohex
++ *
++ */
++static void dohexdigit (char *cp, unsigned char val)
++{
++ if (val < 0xa) {
++ *cp = val + '0';
++ } else if ((val >= 0x0a) && (val <= 0x0f)) {
++ *cp = val - 0x0a + 'a';
++ }
++}
++
++/* *
++ * dohex
++ *
++ */
++static void dohexval (char *cp, unsigned char val)
++{
++ dohexdigit (cp++, val >> 4);
++ dohexdigit (cp++, val & 0xf);
++}
++
++/* *
++ * dump_descriptor
++ */
++static int dump_descriptor (char *buf, char *sp)
++{
++ int num = *sp;
++ int len = 0;
++
++ //printk(KERN_INFO"%s: %p %d %d %d\n", __FUNCTION__, buf, *buf, buf[0], num);
++
++ while (sp && num--) {
++ dohexval (buf, *sp++);
++ buf += 2;
++ *buf++ = ' ';
++ len += 3;
++ }
++ len++;
++ *buf = '\n';
++ return len;
++}
++
++/* dump_descriptors
++ */
++static int dump_config_descriptor(char *buf, char *sp)
++{
++ struct usb_configuration_descriptor *config = (struct usb_configuration_descriptor *) sp;
++
++ int wTotalLength = le16_to_cpu(config->wTotalLength);
++ int bConfigurationValue = config->bConfigurationValue;
++ int interface;
++ int class;
++ int endpoint;
++ int total;
++
++ interface = class = endpoint = 0;
++
++ for (total = 0; wTotalLength; ) {
++ //printk(KERN_INFO"%s: wTotalLength: %d total: %d bLength: %d\n",
++ // __FUNCTION__, wTotalLength, total, sp[0]);
++ switch (sp[1]) {
++ case USB_DESCRIPTOR_TYPE_CONFIGURATION:
++ interface = class = endpoint = 0;
++ total += sprintf(buf + total, "\nConfiguration descriptor [%d ] ",
++ bConfigurationValue);
++ break;
++ case USB_DESCRIPTOR_TYPE_INTERFACE:
++ class = 0;
++ total += sprintf(buf + total, "\nInterface descriptor [%d:%d:%d ] ",
++ bConfigurationValue, ++interface, class);
++ break;
++ case USB_DESCRIPTOR_TYPE_ENDPOINT:
++ class = endpoint = 0;
++ total += sprintf(buf + total, "Endpint descriptor [%d:%d:%d:%d] ",
++ bConfigurationValue, interface, class, ++endpoint);
++ break;
++ default:
++ endpoint = 0;
++ total += sprintf(buf + total, "Class descriptor [%d:%d:%d ] ",
++ bConfigurationValue, interface, ++class);
++ break;
++ }
++ total += dump_descriptor(buf + total, sp);
++ wTotalLength -= sp[0];
++ sp += sp[0];
++ }
++ total += sprintf(buf + total, "\n");
++ return total;
++}
++
++/* *
++ * usbd_device_proc_read - implement proc file system read.
++ * @file
++ * @buf
++ * @count
++ * @pos
++ *
++ * Standard proc file system read function.
++ *
++ * We let upper layers iterate for us, *pos will indicate which device to return
++ * statistics for.
++ */
++static ssize_t usbd_device_proc_read_functions (struct file *file, char *buf, size_t count, loff_t * pos)
++{
++ unsigned long page;
++ int len = 0;
++ int index;
++
++ u8 config_descriptor[512];
++ int config_size;
++
++ //struct list_head *lhd;
++
++ // get a page, max 4095 bytes of data...
++ if (!(page = get_free_page (GFP_KERNEL))) {
++ return -ENOMEM;
++ }
++
++ len = 0;
++ index = (*pos)++;
++
++ if (index == 0) {
++ len += sprintf ((char *) page + len, "usb-device list\n");
++ }
++
++ //printk(KERN_INFO"%s: index: %d len: %d\n", __FUNCTION__, index, len);
++
++ if (usbd_bus_instance && usbd_bus_instance->function_instance) {
++ int configuration = index;
++ struct usb_function_instance *function_instance = usbd_bus_instance->function_instance;
++ struct usb_function_driver *function_driver = function_instance->function_driver;
++ struct usb_configuration_instance *configuration_instance_array = function_driver->configuration_instance_array;
++ if (configuration_instance_array) {
++
++ if (index == 0) {
++ len += sprintf ((char *) page + len, "\nDevice descriptor ");
++ len += dump_descriptor ((char *) page + len, (char *) function_driver->device_descriptor);
++#ifdef CONFIG_USBD_HIGH_SPEED
++ len += sprintf ((char *) page + len, "\nDevice Qualifier descriptor ");
++ len += dump_descriptor ((char *) page + len,
++ (char *) function_driver->device_qualifier_descriptor);
++#endif
++ }
++ if (configuration < function_driver->bNumConfigurations) {
++
++ if ((config_size = usbd_get_descriptor(usbd_bus_instance, config_descriptor,
++ sizeof(config_descriptor),
++ USB_DESCRIPTOR_TYPE_CONFIGURATION, 0)) > index) {
++ len += dump_config_descriptor((char *)page + len, config_descriptor );
++ }
++#ifdef CONFIG_USBD_HIGH_SPEED
++ if ((config_size = usbd_get_descriptor(usbd_bus_instance, config_descriptor,
++ sizeof(config_descriptor),
++ USB_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION, index)) > 0) {
++ len += dump_config_descriptor((char *)page + len, config_descriptor );
++ }
++
++#endif
++ }
++ else if (configuration == function_driver->bNumConfigurations) {
++ int i;
++ int k;
++ struct usb_string_descriptor *string_descriptor;
++
++ //len += sprintf ((char *) page + len, "\n\n");
++
++ if ((string_descriptor = usbd_get_string (0)) != NULL) {
++ len += sprintf ((char *) page + len, "String [%2d] ", 0);
++
++ for (k = 0; k < (string_descriptor->bLength / 2) - 1; k++) {
++ len += sprintf ((char *) page + len, "%02x %02x ",
++ string_descriptor->wData[k] >> 8,
++ string_descriptor->wData[k] & 0xff);
++ len++;
++ }
++ len += sprintf ((char *) page + len, "\n");
++ }
++
++ for (i = 1; i < usbd_maxstrings; i++) {
++
++ if ((string_descriptor = usbd_get_string (i)) != NULL) {
++
++ len += sprintf((char *)page+len, "String [%2d:%2d] ",
++ i, string_descriptor->bLength);
++
++ // bLength = sizeof(struct usb_string_descriptor) + 2*strlen(str)-2;
++
++ for (k = 0; k < (string_descriptor->bLength / 2) - 1; k++) {
++ *(char *) (page + len) = (char) string_descriptor->wData[k];
++ len++;
++ }
++ len += sprintf ((char *) page + len, "\n");
++ }
++ }
++ len += sprintf((char *)page + len, "\n--\n");
++ }
++ }
++ }
++
++ //printk(KERN_INFO"%s: len: %d count: %d\n", __FUNCTION__, len, count);
++
++ if (len > count) {
++ //printk(KERN_INFO"%s: len > count\n", __FUNCTION__);
++ //printk(KERN_INFO"%s", page);
++ len = -EINVAL;
++ }
++ else if ((len > 0) && copy_to_user (buf, (char *) page, len)) {
++ //printk(KERN_INFO"%s: EFAULT\n", __FUNCTION__);
++ len = -EFAULT;
++ }
++ else {
++ //printk(KERN_INFO"%s: OK\n", __FUNCTION__);
++ }
++ free_page (page);
++ return len;
++}
++
++static struct file_operations usbd_device_proc_operations_functions = {
++read:usbd_device_proc_read_functions,
++};
++
++#endif
++
++
++
++/* Module init ******************************************************************************* */
++
++
++static int usbd_procfs_init (void)
++{
++#ifdef CONFIG_USBD_PROCFS
++ {
++ struct proc_dir_entry *p;
++
++ // create proc filesystem entries
++ if ((p = create_proc_entry ("usb-functions", 0, 0)) == NULL)
++ return -ENOMEM;
++ p->proc_fops = &usbd_device_proc_operations_functions;
++ }
++#endif
++ return 0;
++}
++
++static void usbd_procfs_exit (void)
++{
++#ifdef CONFIG_USBD_PROCFS
++ // remove proc filesystem entry
++ remove_proc_entry ("usb-functions", NULL);
++#endif
++}
++
++module_init (usbd_procfs_init);
++module_exit (usbd_procfs_exit);
++
+diff -Nru a/drivers/usbd/usbd.c b/drivers/usbd/usbd.c
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd.c Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,663 @@
++/*
++ * usbd/usbd.c - USB Device Core Layer
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it under the terms of
++ * the GNU General Public License as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ * See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along with this program; if
++ * not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++#include <linux/config.h>
++#include <linux/module.h>
++#include <linux/kernel.h>
++#include <linux/version.h>
++#include <linux/interrupt.h>
++#include <linux/init.h>
++#include <asm/uaccess.h>
++#include <linux/slab.h>
++#include <linux/proc_fs.h>
++#include <linux/ctype.h>
++#include <linux/string.h>
++#if defined(CONFIG_PM)
++#include <linux/pm.h>
++#endif
++
++#include "usbd-export.h"
++#include "usbd-build.h"
++#include "usbd-chap9.h"
++#include "usbd-mem.h"
++#include "usbd.h"
++#include "usbd-func.h"
++#include "usbd-bus.h"
++#include "usbd-admin.h"
++
++MODULE_AUTHOR ("sl@lineo.com, tbr@lineo.com");
++MODULE_DESCRIPTION ("USB Device Core Support");
++#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,17)
++MODULE_LICENSE("GPL");
++#endif
++USBD_MODULE_INFO ("usbdcore 2.0-beta");
++
++int usbd_maxstrings = 20;
++extern int usbd_switch_init(void);
++LIST_HEAD (usbd_function_drivers); // list of all registered function modules
++struct usb_bus_instance *usbd_bus_instance;
++#ifdef MALLOC_TEST
++int usbd_mallocs;
++#endif
++
++/* ******************************************************************************************* */
++/*
++ * USBD Switch will make direct calls to the appropriate modinit/modexit and
++ * bus interface bi_modinit/bi_modexit functions to load and unload as appropriate.
++ *
++ *
++ * The following entry points are exported:
++ *
++ * int usbd_enable(void)
++ * int usbd_disable(char *name)
++ * int usbd_disconnect(char *name)
++ * int usbd_connect(char *name)
++ * int usbd_pm_on(char *name)
++ * int usbd_pm_off(char *name)
++ *
++ * int usbd_unload(void)
++ * int usbd_load(char *name)
++ * int usbd_unplug(char *name)
++ * int usbd_replug(char *name)
++ *
++ *
++ * If CONFIG_PROCFS is defined then the following commands can be given to /proc/usbd-switch:
++ *
++ * enable
++ * enable name
++ * disable
++ * disconnect
++ * connect
++ *
++ * serial_number
++ * debug
++ * nodebug
++ *
++ *
++ * There are four different styles of operations that can be used:
++ *
++ * 1. switch - change or configure the device function by sending any
++ * one of a number of commands to the switch interface [1] of
++ * usbd-switch:
++ *
++ * - echo "serial_number xxxxx" > /proc/usbd-switch
++ * - echo "enable network_fd" > /proc/usbd-switch
++ * - echo "disconnect" > /proc/usbd-switch
++ * - echo "connect" > /proc/usbd-switch
++ * - echo "disable" > /proc/usbd-switch
++ *
++ * serial_number - set the serial number string
++ * enable function - set current function and enable function and bus interface
++ * enable - enable current function and bus interface
++ * disable - disable bus interface and current function
++ * connect - enable current function and bus interface and connect pullup resistor
++ * disconnect - unload bus interface, current function and reset current function,
++ * and disconnect pullup resistor
++ *
++ * 2. simple power management
++ *
++ * - EXPORT_SYMBOL(usbd_enable);
++ * - EXPORT_SYMBOL(usbd_disable);
++ * - EXPORT_SYMBOL(usbd_disconnect);
++ * - EXPORT_SYMBOL(usbd_connect);
++ * - EXPORT_SYMBOL(usbd_pm_on);
++ * - EXPORT_SYMBOL(usbd_pm_off);
++ *
++ * Deprecated:
++ *
++ * - EXPORT_SYMBOL(usbd_load);
++ * - EXPORT_SYMBOL(usbd_unload);
++ * - EXPORT_SYMBOL(usbd_unplug);
++ * - EXPORT_SYMBOL(usbd_replug);
++ *
++ * usbd_enable() - load function and bus interface
++ * usbd_disable() - unload bus interface and function
++ *
++ * usbd_connect() - connect
++ * usbd_disconnect() - disconnect
++ *
++ * usbd_pm_on() - connect
++ * usbd_pm_off() - disconnect
++ *
++ * usbd_load() - load function and bus interface
++ * usbd_unload() - unload bus interface and function
++ * usbd_unplug() - disconnect
++ * usbd_replug() - connect
++ *
++ * 3. official power management CONFIG_PM [not tested yet]
++ *
++ * Perform unplug and plug functions appropriate for CONFIG_PM actions.
++ *
++ *
++ * N.B.
++ *
++ * [1] The switch interface is only available when the USB device stack
++ * and usbd-switch are compiled into the kernel. It is not available
++ * when the USB device stack consists of loadable modules.
++ *
++ * [2] Cable detection requires implementation of architecture specific
++ * code that knows about the appropriate interrupt, GPIO pins etc.
++ *
++ */
++
++
++extern struct list_head usbd_function_drivers;
++
++
++/*
++ * This is a table of function drivers that are compiled into the kernel.
++ */
++
++#define MAX_FUNC_NAME_LEN 64
++char current_function[MAX_FUNC_NAME_LEN+1];
++int switch_debug = 0;
++
++char *usbd_load_arg;
++
++int switch_exiting;
++struct tq_struct enable_bh;
++struct tq_struct disable_bh;
++
++
++
++/* ******************************************************************************************* */
++
++static DECLARE_MUTEX(usbd_sem); // protect against multiple administrative actions overlapping
++
++extern struct usb_bus_instance *usbd_bus_instance;
++
++char *usbd_admin_names[] = {
++ "enable", "disable", "connect", "disconnect", "pm_off", "pm_on", "serial_number",
++};
++
++char *usbd_admin_aliases[] = {
++ "load", "unload", "replug", "unplug", "pm_off", "pm_on", "serial_number_str",
++};
++
++
++/* usbd_admin -
++ */
++static int usbd_admin(usbd_admin_t usbd_admin_ndx, char *arg)
++{
++
++ printk(KERN_INFO"%s: %s current: %s arg: %s\n", __FUNCTION__,
++ usbd_admin_names[usbd_admin_ndx],
++ current_function[0] ? current_function : "(EMPTY)",
++ (arg && arg[0]) ? arg : "(EMPTY)");
++
++ RETURN_EINVAL_IF(in_interrupt() || down_interruptible(&usbd_sem));
++
++ /*
++ *
++ */
++ if (usbd_admin_ndx == usbd_admin_enable && (NULL == arg || 0 == *arg)) {
++ // s/enable/enable current_function/
++ arg = current_function;
++ }
++
++ THROW_IF(!usbd_bus_instance, error);
++
++ THROW_IF (!usbd_bus_instance->admin[usbd_admin_ndx] ||
++ usbd_bus_instance->admin[usbd_admin_ndx](usbd_bus_instance, arg), error);
++
++ if (usbd_admin_ndx == usbd_admin_enable && NULL != arg && arg != current_function) {
++ // update current_function
++ strncpy(current_function,arg,MAX_FUNC_NAME_LEN);
++ }
++
++ up(&usbd_sem);
++ return 0;
++
++ CATCH(error) {
++ printk(KERN_INFO"%s: %d error\n", __FUNCTION__, usbd_admin_ndx);
++
++ up(&usbd_sem);
++ return -ENODEV;
++ }
++}
++
++
++/* usbd_enable -
++ */
++int usbd_enable(char *arg)
++{
++ printk(KERN_INFO"%s:\n", __FUNCTION__);
++ RETURN_ZERO_IF(switch_exiting);
++ return usbd_admin(usbd_admin_enable, arg);
++}
++
++void usbd_enable_bh(void *arg)
++{
++ usbd_admin(usbd_admin_enable, (char *)arg);
++}
++
++int usbd_enable_irq(char *arg)
++{
++ RETURN_ZERO_IF(enable_bh.sync || switch_exiting);
++ schedule_task(&enable_bh);
++ return 0;
++}
++
++
++/* usbd_disable -
++ */
++int usbd_disable(char *arg)
++{
++ RETURN_ZERO_IF(switch_exiting);
++ return usbd_admin(usbd_admin_disable, arg);
++}
++
++void usbd_disable_bh(void *arg)
++{
++ usbd_admin(usbd_admin_disable, (char *)arg);
++}
++
++int usbd_disable_irq(char *arg)
++{
++ RETURN_ZERO_IF(disable_bh.sync || switch_exiting);
++ schedule_task(&disable_bh);
++ return 0;
++}
++
++/* usbd_load -
++ */
++int usbd_load(char *arg)
++{
++ if (arg && strlen(arg)) {
++ if ( usbd_load_arg)
++ lkfree(usbd_load_arg);
++ usbd_load_arg = lstrdup(arg);
++ }
++ return usbd_admin(usbd_admin_enable, arg);
++}
++
++/* usbd_unload -
++ */
++int usbd_unload(char *arg)
++{
++ return usbd_admin(usbd_admin_disable, arg);
++}
++
++
++/* usbd_connect -
++ */
++int usbd_connect(char *arg)
++{
++ return usbd_admin(usbd_admin_connect, arg);
++}
++
++/* usbd_disconnect -
++ */
++int usbd_disconnect(char *arg)
++{
++ return usbd_admin(usbd_admin_disconnect, arg);
++}
++
++
++/* usbd_replug -
++ */
++int usbd_replug(char *arg)
++{
++ return usbd_admin(usbd_admin_connect, arg);
++}
++
++/* usbd_unplug -
++ */
++int usbd_unplug(char *arg)
++{
++ return usbd_admin(usbd_admin_disconnect, arg);
++}
++
++
++
++/* usbd_pm_off -
++ */
++int usbd_pm_off(char *arg)
++{
++ return usbd_admin(usbd_admin_pm_off, arg);
++}
++
++/* usbd_pm_on -
++ */
++int usbd_pm_on(char *arg)
++{
++ return usbd_admin(usbd_admin_pm_on, arg);
++}
++
++
++
++
++/* ******************************************************************************************* */
++#ifdef CONFIG_USBD_PROCFS
++
++static int usbd_admin_procfs(char *arg)
++{
++ usbd_admin_t admin;
++ RETURN_EINVAL_IF(!arg || !strlen(arg));
++
++ for (admin = usbd_admin_enable; admin <= usbd_admin_serial_number; admin++) {
++ char *cp = usbd_admin_names[admin];
++ int len = strlen(cp);
++ if (!strncmp(arg, cp, len)) {
++ cp = arg + len;
++ while (cp && ((*cp == ' ') || (*cp == '\t'))) cp++;
++ return usbd_admin(admin, cp);
++ }
++ }
++
++ for (admin = usbd_admin_enable; admin <= usbd_admin_serial_number; admin++) {
++ char *cp = usbd_admin_aliases[admin];
++ int len = strlen(cp);
++ if (!strncmp(arg, cp, len)) {
++ cp = arg + len;
++ while (cp && ((*cp == ' ') || (*cp == '\t'))) cp++;
++ return usbd_admin(admin, cp);
++ }
++ }
++
++ return -EINVAL;
++}
++
++/* usbd_proc_switch_write - handle a user switch request
++ */
++static ssize_t usbd_proc_switch_write (struct file *file, const char *buf, size_t count, loff_t * pos)
++{
++
++ char command[MAX_FUNC_NAME_LEN+1];
++ size_t n = count;
++ size_t l;
++ char c;
++
++ command[0] = 0;
++ if (n > 0) {
++ l = MIN(n,MAX_FUNC_NAME_LEN);
++ if (copy_from_user (command, buf, l)) {
++ count = -EFAULT;
++ }
++ else {
++ if (l > 0 && command[l-1] == '\n') {
++ l -= 1;
++ }
++ command[l] = 0;
++ n -= l;
++ // flush remainder, if any
++ while (n > 0) {
++ // Not too efficient, but it shouldn't matter
++ if (copy_from_user (&c, buf + (count - n), 1)) {
++ count = -EFAULT;
++ break;
++ }
++ n -= 1;
++ }
++ }
++ }
++
++ if (0 >= count) {
++ printk(KERN_INFO"%s: count <= 0 %d\n", __FUNCTION__, count);
++ return count;
++ }
++
++ //printk(KERN_INFO"%s: %s\n", __FUNCTION__, command);
++ if (!usbd_admin_procfs(command)) {
++ // do nothing
++ //printk(KERN_INFO"%s: back\n", __FUNCTION__);
++ }
++
++
++ /*
++ * debug - increment switch_debug
++ */
++ else if (!strncmp("debug", command, 5)) {
++ switch_debug++;
++ if (switch_debug)
++ printk(KERN_INFO"%s: debug: %d\n", __FUNCTION__, switch_debug);
++ }
++ /*
++ * nodebug - reset switch_debug
++ */
++ else if (!strncmp("nodebug", command, 7)) {
++ switch_debug = 0;
++ if (switch_debug)
++ printk(KERN_INFO"%s: no debug\n", __FUNCTION__);
++ }
++
++ return count;
++}
++
++/* usbd_proc_switch_read - implement proc file system read.
++ * Standard proc file system read function.
++ */
++static ssize_t usbd_proc_switch_read (struct file *file, char *buf, size_t count, loff_t * pos)
++{
++ unsigned long page;
++ int len;
++ //int index;
++ char *bp,*ep;
++ struct list_head *lhd;
++
++ if ((*pos)++ > 0) {
++ /* This is the second time, we finished on the first time,
++ indicate we have no more data by returning 0. */
++ return(0);
++ }
++
++ // get a page, max 4095 bytes of data...
++ if (!(page = get_free_page (GFP_KERNEL))) {
++ return -ENOMEM;
++ }
++
++ bp = (char *) page;
++ ep = bp + 4095;
++
++ bp += sprintf(bp, "USB cable ");
++ if (NULL != usbd_bus_instance &&
++ NULL != usbd_bus_instance->driver &&
++ NULL != usbd_bus_instance->driver->bops &&
++ NULL != usbd_bus_instance->driver->bops->bus_attached &&
++ usbd_bus_instance->driver->bops->bus_attached(usbd_bus_instance)) {
++ bp += sprintf(bp, "at");
++ } else {
++ bp += sprintf(bp, "de");
++ }
++ bp += sprintf(bp, "tached");
++ bp += sprintf(bp, ", USB pullup resistor ");
++ if (NULL != usbd_bus_instance &&
++ NULL != usbd_bus_instance->driver &&
++ NULL != usbd_bus_instance->driver->bops &&
++ NULL != usbd_bus_instance->driver->bops->bus_connected &&
++ !usbd_bus_instance->driver->bops->bus_connected(usbd_bus_instance)) {
++ bp += sprintf(bp, "dis");
++ }
++ bp += sprintf(bp, "connected");
++ bp += sprintf(bp, "\nUSB Device function drivers:\n");
++ list_for_each (lhd, &usbd_function_drivers) {
++ struct usb_function_driver *fd = list_entry(lhd, struct usb_function_driver, drivers);
++ char enabled = '-';
++ if (usbd_bus_instance && usbd_bus_instance->function_instance &&
++ usbd_bus_instance->function_instance->function_driver == fd) {
++ enabled = '+';
++ }
++ if ((ep - bp) < 64) {
++ printk(KERN_INFO"%s: Too many usbd functions!\n", __FUNCTION__);
++ break;
++ }
++ bp += sprintf(bp," %c [%s]\n",enabled,fd->name);
++ }
++ len = bp - (char *) page;
++
++ if (len > 0 && copy_to_user (buf, (char *) page, len)) {
++ //printk(KERN_INFO"%s: EFAULT\n", __FUNCTION__);
++ len = -EFAULT;
++ } else {
++ //printk(KERN_INFO"%s: OK\n", __FUNCTION__);
++ }
++ free_page (page);
++ return len;
++}
++
++static struct file_operations usbd_proc_switch_functions = {
++ write:usbd_proc_switch_write,
++ read:usbd_proc_switch_read,
++};
++#endif
++
++
++/* ******************************************************************************************* */
++
++#if defined(CONFIG_PM)
++/* switch_pm_event
++ *
++ * Handle power management event
++ */
++static int switch_pm_event (struct pm_dev *dev, pm_request_t rqst, void *unused)
++{
++ switch (rqst) {
++ case PM_SUSPEND:
++ usbd_pm_off(usbd_load_arg);
++ break;
++ case PM_RESUME:
++ usbd_pm_on(usbd_load_arg);
++ break;
++ }
++ return 0;
++}
++#endif
++
++/* ******************************************************************************************* */
++
++
++
++/* ******************************************************************************************* */
++
++#if defined(CONFIG_PM)
++struct pm_dev *switch_pm_info;
++#endif
++
++/* usbd_switch_init
++ *
++ */
++int usbd_switch_init(void)
++{
++
++#ifdef CONFIG_USBD_PROCFS
++ struct proc_dir_entry *p;
++
++ // create proc filesystem entries
++ //printk(KERN_INFO"%s: creating /proc/usbd-switch\n", __FUNCTION__);
++ if ((p = create_proc_entry ("usbd-switch", 0666, 0)) == NULL) {
++ printk(KERN_ERR"%s: creating /proc/usbd-switch failed\n", __FUNCTION__);
++ return -ENOMEM;
++ }
++ p->proc_fops = &usbd_proc_switch_functions;
++#endif
++#ifdef CONFIG_PM
++ switch_pm_info = NULL;
++
++ if (!(switch_pm_info = pm_register (PM_USB_DEV, PM_SYS_UNKNOWN, switch_pm_event)))
++ return -ENOMEM;
++
++ switch_pm_info->state = 0;
++#endif
++ enable_bh.routine = usbd_enable_bh;
++ enable_bh.data = NULL;
++ disable_bh.routine = usbd_disable_bh;
++ disable_bh.data = NULL;
++ return 0;
++}
++
++void usbd_switch_exit (void)
++{
++ // This is *only* used for drivers compiled and used as a module.
++#ifdef CONFIG_PM
++ if (switch_pm_info)
++ pm_unregister_all(switch_pm_event);
++ switch_pm_info = NULL;
++#endif
++#ifdef CONFIG_USBD_PROCFS
++ remove_proc_entry("usbd-switch", NULL);
++#endif
++ switch_exiting = 1;
++ while (enable_bh.sync || disable_bh.sync) {
++ printk(KERN_INFO"%s: waiting for bh\n", __FUNCTION__);
++ schedule_timeout(10 * HZ);
++ }
++}
++
++
++
++/* Module init ******************************************************************************* */
++
++int usbd_switch_init(void);
++void usbd_switch_exit (void);
++
++static int usbd_device_init (void)
++{
++ printk (KERN_INFO "%s: %s %s\n", __FUNCTION__, __usbd_module_info, USBD_EXPORT_TAG);
++
++ usbd_switch_init();
++
++ return 0;
++}
++
++static void usbd_device_exit (void)
++{
++ //printk (KERN_INFO "%s: %s exiting\n", __FUNCTION__, __usbd_module_info);
++
++ usbd_switch_exit();
++
++ if ( usbd_load_arg)
++ lkfree(usbd_load_arg);
++
++#ifdef MALLOC_TEST
++ if (usbd_mallocs) printk(KERN_INFO"%s: usbd_mallocs non-zero! %d\n", __FUNCTION__, usbd_mallocs);
++#endif
++}
++
++module_init (usbd_device_init);
++module_exit (usbd_device_exit);
++
++EXPORT_SYMBOL(usbd_function_drivers);
++EXPORT_SYMBOL(usbd_maxstrings);
++
++EXPORT_SYMBOL(usbd_enable);
++EXPORT_SYMBOL(usbd_disable);
++EXPORT_SYMBOL(usbd_enable_irq);
++EXPORT_SYMBOL(usbd_disable_irq);
++
++EXPORT_SYMBOL(usbd_connect);
++EXPORT_SYMBOL(usbd_disconnect);
++EXPORT_SYMBOL(usbd_pm_on);
++EXPORT_SYMBOL(usbd_pm_off);
++
++EXPORT_SYMBOL(usbd_load);
++EXPORT_SYMBOL(usbd_unload);
++EXPORT_SYMBOL(usbd_unplug);
++EXPORT_SYMBOL(usbd_replug);
++
++
++EXPORT_SYMBOL(usbd_bus_instance);
++#ifdef MALLOC_TEST
++EXPORT_SYMBOL(usbd_mallocs);
++#endif
++
++
+diff -Nru a/drivers/usbd/usbd.h b/drivers/usbd/usbd.h
+--- /dev/null Wed Dec 31 16:00:00 1969
++++ b/drivers/usbd/usbd.h Fri Feb 27 14:22:51 2004
+@@ -0,0 +1,239 @@
++/*
++ * usbd/usbd.h
++ *
++ * Copyright (c) 2004 Belcarra
++ *
++ * Adapted from earlier work:
++ * Copyright (c) 2002, 2003 Belcarra
++ * Copyright (c) 2000, 2001, 2002 Lineo
++ * Copyright (c) 2001 Hewlett Packard
++ *
++ * By:
++ * Stuart Lynne <sl@belcarra.com>,
++ * Tom Rushworth <tbr@belcarra.com>,
++ * Bruce Balden <balden@belcarra.com>
++ *
++ * This program is free software; you can redistribute it and/or modify it under the terms of
++ * the GNU General Public License as published by the Free Software Foundation; either version 2
++ * of the License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
++ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
++ * See the GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License along with this program; if
++ * not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ *
++ */
++
++/*
++ * This file contains the USB Device Core Common definitions. It also contains definitions for
++ * functions that are commonly used by both Function Drivers and Bus Interface Drivers.
++ *
++ * Specifically:
++ *
++ * o public functions exported by the USB Core layer
++ *
++ * o common structures and definitions
++ *
++ */
++
++
++/*
++ * Device Events
++ *
++ * These are defined in the USB Spec (c.f USB Spec 2.0 Figure 9-1).
++ *
++ * There are additional events defined to handle some extra actions we need to have handled.
++ *
++ */
++typedef enum usb_device_event {
++
++ DEVICE_UNKNOWN, // bi - unknown event
++ DEVICE_INIT, // bi - initialize
++ DEVICE_CREATE, // bi -
++ DEVICE_HUB_CONFIGURED, // bi - bus has been plugged int
++ DEVICE_RESET, // bi - hub has powered our port
++
++ DEVICE_ADDRESS_ASSIGNED,// ep0 - set address setup received
++ DEVICE_CONFIGURED, // ep0 - set configure setup received
++ DEVICE_SET_INTERFACE, // ep0 - set interface setup received
++
++ DEVICE_SET_FEATURE, // ep0 - set feature setup received
++ DEVICE_CLEAR_FEATURE, // ep0 - clear feature setup received
++
++ DEVICE_DE_CONFIGURED, // ep0 - set configure setup received for ??
++
++ DEVICE_BUS_INACTIVE, // bi - bus in inactive (no SOF packets)
++ DEVICE_BUS_ACTIVITY, // bi - bus is active again
++
++ DEVICE_POWER_INTERRUPTION,// bi - hub has depowered our port
++ DEVICE_HUB_RESET, // bi - bus has been unplugged
++ DEVICE_DESTROY, // bi - device instance should be destroyed
++ DEVICE_CLOSE, // bi - device instance should be destroyed
++
++} usb_device_event_t;
++
++
++
++struct usb_bus_instance;
++struct usb_function_instance;
++
++typedef struct urb_link {
++ struct urb_link *next;
++ struct urb_link *prev;
++} urb_link;
++
++/* URB Status
++ *
++ */
++typedef enum usbd_urb_status {
++ SEND_IN_QUEUE,
++ SEND_IN_PROGRESS,
++ SEND_FINISHED_OK,
++ SEND_FINISHED_ERROR,
++ SEND_FINISHED_CANCELLED,
++ RECV_IN_QUEUE,
++ RECV_IN_PROGRESS,
++ RECV_OK,
++ RECV_ERROR,
++ RECV_CANCELLED
++} usbd_urb_status_t;
++
++
++
++/* USB Data structure
++ *
++ * This is used for both sending and receiving data.
++ *
++ * The callback function is used to let the function driver know when transmitted data has been
++ * sent.
++ *
++ * The callback function is set by the alloc_recv function when an urb is allocated for
++ * receiving data for an endpoint and used to call the function driver to inform it that data
++ * has arrived.
++ *
++ * Note that for OUT urbs the buffer is always allocated to a multiple of the packetsize that is
++ * 1 larger than the requested size. This prevents overflow if the host unexpectedly sends a
++ * full sized packet when we are expecting a short one (the host is always right..)
++ */
++
++struct urb {
++
++ struct usb_bus_instance *bus;
++ struct usb_function_instance *function_instance;
++ struct usb_endpoint_instance *endpoint;
++
++ int (*callback) (struct urb *, int);
++
++ u8 *buffer; // data received (OUT) or being sent (IN)
++ u32 request_length; // maximum data expected for OUT
++ u32 buffer_length; // allocated size of buffer
++ u32 actual_length; // actual data received (OUT or being sent (IN)
++ u32 flags;
++
++ void *privdata;
++
++ struct urb_link link;
++ usbd_urb_status_t status; // what is the current status of the urb
++ time_t jiffies; // timestamp for when urb was started or finished
++ u16 framenum; // SOF framenum when urb was finished
++};
++
++#define USBD_URB_SENDZLP 0x01
++
++
++/*
++ * Device State (c.f USB Spec 2.0 Figure 9-1)
++ *
++ * What state the usb device is in.
++ *
++ * Note the state does not change if the device is suspended, we simply set a
++ * flag to show that it is suspended.
++ *
++ */
++typedef enum usb_device_state {
++ STATE_INIT, // just initialized
++ STATE_CREATED, // just created
++ STATE_ATTACHED, // we are attached
++ STATE_POWERED, // we have seen power indication (electrical bus signal)
++ STATE_DEFAULT, // we been reset
++ STATE_ADDRESSED, // we have been addressed (in default configuration)
++ STATE_CONFIGURED, // we have seen a set configuration device command
++ STATE_SUSPENDED,
++ STATE_UNKNOWN, // destroyed
++} usb_device_state_t;
++
++/*
++ * Device status
++ *
++ * Overall state
++ */
++typedef enum usb_device_status {
++ USBD_OPENING, // we are currently opening
++ USBD_RESETING, // we are currently opening
++ USBD_OK, // ok to use
++ USBD_SUSPENDED, // we are currently suspended
++ USBD_CLOSING, // we are currently closing
++ USBD_CLOSED, // we are currently closing
++ USBD_UNKNOWN,
++} usb_device_status_t;
++
++/*
++ * Bus state
++ *
++ * enabled or disabled
++ */
++typedef enum usbd_bus_state {
++ usbd_bus_state_unknown,
++ usbd_bus_state_disabled,
++ usbd_bus_state_enabled
++} usbd_bus_state_t;
++
++
++
++/* Endpoint Request
++ *
++ * An array of these structures is initialized by each function driver to specify the endpoints
++ * it requires.
++ *
++ * The bus interface driver will attempt to fulfill these requests with the actual endpoints it
++ * has available.
++ *
++ * Note that in most cases the bEndpointAddress should be left as zero except for specialized
++ * function drivers that both require a specific value and know ahead of time that the specified
++ * value is legal for the bus interface driver being used.
++ */
++struct usb_endpoint_request {
++ u8 configuration; // configuration endpoint will be in
++ u8 interface; // interface endpoint will be in
++ u8 alternate; // altsetting for this request
++ u8 bmAttributes; // endpoint type AND direction
++ u16 fs_requestedTransferSize; // max full speed transfer size for this endpoint
++ u16 hs_requestedTransferSize; // max high speed transfer size for this endpoint
++ u8 bEndpointAddress; // specific bEndpointAddress function driver requires
++ u8 physical; // physical endpoint used
++};
++
++
++
++struct usb_function_operations;
++struct usb_function_driver;
++
++
++
++/*
++ * USB Bus Interface Driver structures
++ *
++ * Driver description:
++ *
++ * struct usb_bus_operations
++ * struct usb_bus_driver
++ *
++ */
++
++struct usb_bus_operations;
++struct usb_bus_driver;
++extern int usbd_maxstrings;
++
++
diff --git a/packages/linux/linux-mtx-1-2.4.27/29-au1000-pci-config-clear-errors.diff b/packages/linux/linux-mtx-1-2.4.27/29-au1000-pci-config-clear-errors.diff
new file mode 100644
index 0000000000..5da1cd61f8
--- /dev/null
+++ b/packages/linux/linux-mtx-1-2.4.27/29-au1000-pci-config-clear-errors.diff
@@ -0,0 +1,15 @@
+--- linux/arch/mips/au1000/common/pci_ops.c.orig 2005-08-24 17:36:25.000000000 +0200
++++ linux/arch/mips/au1000/common/pci_ops.c 2005-08-24 17:37:38.000000000 +0200
+@@ -259,7 +259,11 @@
+ *data = 0xffffffff;
+ error = -1;
+ } else if ((status >> 28) & 0xf) {
+- DBG("PCI ERR detected: status %x\n", status);
++ DBG("PCI ERR detected: device %d, status %x\n", device, ((status >> 28) & 0xf));
++
++ /* clear errors */
++ au_writel(status & 0xf000ffff, Au1500_PCI_STATCMD);
++
+ *data = 0xffffffff;
+ error = -1;
+ }
diff --git a/packages/linux/linux-mtx-1-2.4.27/defconfig-mtx-1 b/packages/linux/linux-mtx-1-2.4.27/defconfig-mtx-1
index 13234772ab..d31e979829 100644
--- a/packages/linux/linux-mtx-1-2.4.27/defconfig-mtx-1
+++ b/packages/linux/linux-mtx-1-2.4.27/defconfig-mtx-1
@@ -133,7 +133,12 @@ CONFIG_HOTPLUG=y
#
# PCMCIA/CardBus support
#
-# CONFIG_PCMCIA is not set
+CONFIG_PCMCIA=m
+CONFIG_CARDBUS=y
+# CONFIG_TCIC is not set
+# CONFIG_I82092 is not set
+# CONFIG_I82365 is not set
+# CONFIG_PCMCIA_AU1X00 is not set
#
# PCI Hotplug Support
@@ -156,7 +161,7 @@ CONFIG_BINFMT_ELF=y
# CONFIG_MIPS32_O32 is not set
# CONFIG_MIPS32_N32 is not set
# CONFIG_BINFMT_ELF32 is not set
-# CONFIG_BINFMT_MISC is not set
+CONFIG_BINFMT_MISC=m
# CONFIG_OOM_KILLER is not set
# CONFIG_CMDLINE_BOOL is not set
# CONFIG_PM is not set
@@ -183,7 +188,7 @@ 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_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_INTELEXT=y
CONFIG_MTD_CFI_AMDSTD=y
CONFIG_MTD_CFI_AMDSTD_RETRY=y
CONFIG_MTD_CFI_AMDSTD_RETRY_MAX=5
@@ -552,6 +557,11 @@ CONFIG_SR_EXTRA_DEVS=2
# CONFIG_SCSI_DEBUG is not set
#
+# PCMCIA SCSI adapter support
+#
+# CONFIG_SCSI_PCMCIA is not set
+
+#
# Fusion MPT device support
#
# CONFIG_FUSION is not set
@@ -655,6 +665,9 @@ CONFIG_AIRO=m
# CONFIG_PLX_HERMES is not set
# CONFIG_TMD_HERMES is not set
# CONFIG_PCI_HERMES is not set
+# CONFIG_PCMCIA_HERMES is not set
+# CONFIG_AIRO_CS is not set
+# CONFIG_PCMCIA_ATMEL is not set
CONFIG_NET_WIRELESS=y
#
@@ -671,6 +684,11 @@ CONFIG_SHAPER=m
# CONFIG_WAN is not set
#
+# PCMCIA network device support
+#
+# CONFIG_NET_PCMCIA is not set
+
+#
# Amateur Radio support
#
# CONFIG_HAMRADIO is not set
@@ -836,6 +854,12 @@ CONFIG_SENSORS_PCF8591=m
# Direct Rendering Manager (XFree86 DRI support)
#
# CONFIG_DRM is not set
+
+#
+# PCMCIA character devices
+#
+# CONFIG_PCMCIA_SERIAL_CS is not set
+# CONFIG_SYNCLINK_CS is not set
CONFIG_AU1X00_GPIO=m
# CONFIG_TS_AU1X00_ADS7846 is not set
@@ -1090,7 +1114,6 @@ CONFIG_USB_DEVICEFS=y
# CONFIG_USB_UHCI is not set
# CONFIG_USB_UHCI_ALT is not set
CONFIG_USB_OHCI=y
-CONFIG_USB_NON_PCI_OHCI=y
CONFIG_USB_AUDIO=m
CONFIG_USB_EMI26=m
CONFIG_USB_MIDI=m
@@ -1187,6 +1210,69 @@ CONFIG_USB_LCD=m
# CONFIG_USB_GADGET is not set
#
+# USB clients (devices, not hosts)
+#
+CONFIG_USBD=m
+# CONFIG_USBD_HIGH_SPEED is not set
+# CONFIG_USBD_NO_SERIAL_NUMBER is not set
+CONFIG_USBD_SERIAL_NUMBER_STR=""
+CONFIG_USBD_MAXPOWER=0
+CONFIG_USBD_PROCFS=y
+CONFIG_USBD_PROCFSM=m
+
+#
+# Network Function
+#
+CONFIG_USBD_NETWORK=m
+CONFIG_USBD_NETWORK_VENDORID=12b9
+CONFIG_USBD_NETWORK_PRODUCTID=f001
+CONFIG_USBD_NETWORK_BCDDEVICE=0100
+CONFIG_USBD_NETWORK_MANUFACTURER="Belcarra"
+## CONFIG_USBD_NETWORK_PRODUCT_NAME="Belcarra BLAN Device"
+## CONFIG_USBD_NETWORK_BLAN=y
+## CONFIG_USBD_NETWORK_BLAN_DESC="BLAN Net Cfg"
+## CONFIG_USBD_NETWORK_BLAN_INTF="Comm/Data Intf"
+# CONFIG_USBD_NETWORK_BLAN_CRC is not set
+# CONFIG_USBD_NETWORK_BLAN_DO_NOT_SETTIME is not set
+# CONFIG_USBD_NETWORK_BLAN_HOSTNAME is not set
+# CONFIG_USBD_NETWORK_BLAN_NOBRIDGE is not set
+CONFIG_USBD_NETWORK_SAFE=y
+CONFIG_USBD_NETWORK_SAFE_NOBRIDGE=y
+# CONFIG_USBD_NETWORK_CDC is not set
+# CONFIG_USBD_NETWORK_BASIC is not set
+# CONFIG_USBD_NETWORK_BASIC2 is not set
+# CONFIG_USBD_NETWORK_START_SINGLE is not set
+# CONFIG_USBD_NETWORK_EP0TEST is not set
+
+#
+# CDC ACM Function
+#
+CONFIG_USBD_ACM=m
+CONFIG_USBD_ACM_VENDORID=12b9
+CONFIG_USBD_ACM_PRODUCTID=f002
+CONFIG_USBD_ACM_BCDDEVICE=0100
+CONFIG_USBD_ACM_MANUFACTURER="Belcarra"
+CONFIG_USBD_ACM_PRODUCT_NAME="Belcarra ACM Device"
+CONFIG_USBD_ACM_DESC="Acm Cfg"
+CONFIG_USBD_ACM_COMM_INTF="Comm Intf"
+CONFIG_USBD_ACM_DATA_INTF="Data Intf"
+# CONFIG_USBD_ACM_TRACE is not set
+
+#
+# Random Mouse Function
+#
+# CONFIG_USBD_MOUSE is not set
+
+#
+# AMD AU1X000 Bus Interface
+#
+CONFIG_USBD_AU1X00_BUS=m
+CONFIG_USBD_AU1X00_SCLOCK=400
+CONFIG_AU1000_USB_DEVICE=y
+CONFIG_AU1X00_USB_DEVICE=y
+# CONFIG_USBD_BI_REGISTER_TRACE is not set
+
+#
# Bluetooth support
#
CONFIG_BLUEZ=m
diff --git a/packages/linux/linux-mtx-1_2.4.24.bb b/packages/linux/linux-mtx-1_2.4.24.bb
index 0a9e9a487e..b98f9fb638 100644
--- a/packages/linux/linux-mtx-1_2.4.24.bb
+++ b/packages/linux/linux-mtx-1_2.4.24.bb
@@ -26,7 +26,7 @@ SRC_URI = "cvs://cvs:cvs@ftp.linux-mips.org/home/cvs;module=linux;tag=linux_2_4_
S = "${WORKDIR}/linux"
-inherit kernel
+inherit module-base kernel
PACKAGE_ARCH = "mtx-1"
ARCH = "mips"
diff --git a/packages/linux/linux-mtx-1_2.4.27.bb b/packages/linux/linux-mtx-1_2.4.27.bb
index a73bdf6c25..31015634cc 100644
--- a/packages/linux/linux-mtx-1_2.4.27.bb
+++ b/packages/linux/linux-mtx-1_2.4.27.bb
@@ -3,7 +3,10 @@ MAINTAINER = "Bruno Randolf <bruno.randolf@4g-systems.biz>"
HOMEPAGE = "http://meshcube.org/meshwiki/"
LICENSE = "GPL"
KV = "${PV}"
-PR = "r3"
+PR = "r11"
+inherit module-base kernel
+
+PROVIDES = "virtual/kernel"
RDEPENDS = "mtd-utils"
SRC_URI = "cvs://cvs@ftp.linux-mips.org/home/cvs;module=linux;tag=linux_2_4_27 \
@@ -27,21 +30,29 @@ SRC_URI = "cvs://cvs@ftp.linux-mips.org/home/cvs;module=linux;tag=linux_2_4_27 \
file://19-kernel-make-depend.diff;patch=1 \
file://20-au1x00_ethernet_tx_stats.diff;patch=1 \
file://21-mtx-1-watchdog.diff;patch=1 \
+ file://23-mtx-1_watchdog_autotrigger.patch;patch=1 \
+ file://24-mtx-1_sysbtn.patch;patch=1 \
+ file://25-mtx-sio2.diff;patch=1 \
+ file://26-usbd-amd-pb1x00-kit-23may2003-update.diff;patch=1 \
+ file://27-usbd-amd-pb1x00-kit-23may2003-usbd.diff;patch=1 \
+ file://29-au1000-pci-config-clear-errors.diff;patch=1 \
file://defconfig-mtx-1"
S = "${WORKDIR}/linux"
-inherit kernel
-
COMPATIBLE_HOST = "mipsel.*-linux"
-PACKAGE_ARCH = "mtx-1"
ARCH = "mips"
KERNEL_OUTPUT = "arch/mips/zboot/images/mtx-1.flash.bin"
KERNEL_IMAGETYPE = "zImage.flash"
KERNEL_IMAGEDEST = "tmp"
+MTX_KERNEL_NON_PCI_OHCI = "yes"
+
do_configure_prepend() {
install -m 0644 ${WORKDIR}/defconfig-mtx-1 ${S}/.config
+ if [ "x${MTX_KERNEL_NON_PCI_OHCI}" == "xyes" ]; then
+ echo "CONFIG_USB_NON_PCI_OHCI=y" >> ${S}/.config
+ fi
}
pkg_postinst_kernel() {
diff --git a/packages/lirc/files/lircexec.init b/packages/lirc/files/lircexec.init
index d3329bdc37..3a8c1a306e 100755
--- a/packages/lirc/files/lircexec.init
+++ b/packages/lirc/files/lircexec.init
@@ -13,7 +13,7 @@ test -f /etc/lircrc || exit 0
case "$1" in
start)
echo -n "Starting lircexec daemon: irexec"
- start-stop-daemon --start --quiet --exec /usr/bin/irexec
+ start-stop-daemon --start --quiet --exec /usr/bin/irexec -- --daemon
echo "."
;;
stop)
@@ -26,7 +26,7 @@ case "$1" in
start-stop-daemon --stop --quiet --exec /usr/bin/irexec
sleep 1
echo -n "Starting lircexec daemon: irexec"
- start-stop-daemon --start --quiet --exec /usr/bin/irexec
+ start-stop-daemon --start --quiet --exec /usr/bin/irexec -- --daemon
echo "."
;;
*)
diff --git a/packages/lirc/lirc-modules_0.8.0.bb b/packages/lirc/lirc-modules_0.8.0.bb
index fb765d595c..f4411c76a5 100644
--- a/packages/lirc/lirc-modules_0.8.0.bb
+++ b/packages/lirc/lirc-modules_0.8.0.bb
@@ -6,7 +6,7 @@ MAINTAINER_nslu2 = "Matthias Goebl <matthias.goebl@goebl.net>"
LICENSE = "GPL"
DEPENDS = "virtual/kernel fakeroot-native setserial"
RDEPENDS_nslu2 = "setserial"
-PR = "r1"
+PR = "r2"
SRC_URI = "${SOURCEFORGE_MIRROR}/lirc/lirc-${PV}.tar.gz"
S = "${WORKDIR}/lirc-${PV}"
diff --git a/packages/lirc/lirc_0.8.0.bb b/packages/lirc/lirc_0.8.0.bb
index 9a9278425d..62ef3b5d3d 100644
--- a/packages/lirc/lirc_0.8.0.bb
+++ b/packages/lirc/lirc_0.8.0.bb
@@ -6,8 +6,7 @@ DESCRIPTION_append_lirc-remotes = " This package contains some config files for
DESCRIPTION_append_lirc-nslu2example = " This package contains a working config for RC5 remotes and a modified NSLU2."
SECTION = "console/network"
PRIORITY = "optional"
-MAINTAINER = "Michael 'Mickey' Lauer <mickey@Vanille.de>"
-MAINTAINER_nslu2 = "Matthias Goebl <matthias.goebl@goebl.net>"
+MAINTAINER = "Matthias Goebl <matthias.goebl@goebl.net>"
LICENSE = "GPL"
DEPENDS = "virtual/kernel libx11 libxau libsm ice"
DEPENDS_nslu2 = "virtual/kernel lirc-modules"
@@ -15,7 +14,7 @@ RDEPENDS = "lirc-modules"
RDEPENDS_lirc-x = "lirc"
RDEPENDS_lirc-exec = "lirc"
RDEPENDS_lirc-nslu2example = "lirc lirc-exec"
-PR = "r1"
+PR = "r2"
SRC_URI = "${SOURCEFORGE_MIRROR}/lirc/lirc-${PV}.tar.gz \
file://lircd.init file://lircmd.init"
diff --git a/packages/matchbox-panel/matchbox-panel-0.9.2/system-monitor-crash-fix.patch b/packages/matchbox-panel/matchbox-panel-0.9.2/system-monitor-crash-fix.patch
index c9a49fb881..51c141db03 100644
--- a/packages/matchbox-panel/matchbox-panel-0.9.2/system-monitor-crash-fix.patch
+++ b/packages/matchbox-panel/matchbox-panel-0.9.2/system-monitor-crash-fix.patch
@@ -1,23 +1,46 @@
---- matchbox-panel-0.9.2/applets/mb-applet-system-monitor.c.orig 2006-02-04 19:22:55.000000000 +0200
-+++ matchbox-panel-0.9.2/applets/mb-applet-system-monitor.c 2006-02-04 18:18:21.000000000 +0200
-@@ -37,6 +37,16 @@
+--- matchbox-panel-0.9.2/applets/mb-applet-system-monitor.c.orig 2006-02-07 20:08:09.000000000 +0200
++++ matchbox-panel-0.9.2/applets/mb-applet-system-monitor.c 2006-02-07 20:53:20.000000000 +0200
+@@ -37,6 +37,7 @@
# define _(text) (text)
#endif
-+#ifdef HAVE_LINUX_VER_H
-+#include <linux/version.h>
-+#else
-+#define LINUX_VERSION_CODE 0
-+#endif
-+
-+#ifndef KERNEL_VERSION
-+#define KERNEL_VERSION(a,b,c) (((a) << 16) | ((b) << 8) | (c))
-+#endif
+
#ifdef MB_HAVE_PNG
#define IMG_EXT "png"
#else
-@@ -112,71 +122,83 @@
+@@ -66,8 +67,30 @@
+ MBPixbufImage *ImgIcon = NULL, *ImgIconScaled = NULL, *ImgGraph = NULL;
+
+ int GraphHeight = 0, GraphWidth = 0;
+-
+ char *ThemeName;
++static int kernelver = 0;
++
++/* returns 1 if the kernel version is 2.6, 0 otherwise */
++int kernel_version(void)
++{
++ float v_nr=0;
++ FILE *version;
++
++ if ((version = fopen("/proc/version", "r")) == NULL)
++ {
++ fprintf(stderr, "mb-applet-system-monitor: failed to open /proc/version. Exiting\n");
++ exit(1);
++ }
++ fscanf(version, "%*s %*s %f", &v_nr);
++ fclose(version);
++
++ if (v_nr > 2.5)
++ return 1;
++ else
++ return 0;
++}
++
++
+
+ /* returns current CPU load in percent, 0 to 100 */
+ int system_cpu(void)
+@@ -112,71 +135,86 @@
int system_memory(void)
{
@@ -94,14 +117,15 @@
- msd.mem_percent = (100 * msd.mem_used) / msd.mem_max;
- //msd.swap_percent = (100 * msd.swap_used) / msd.swap_max;
--
++/*if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)*/
+
- /* memory info changed - update things */
- return 1;
- }
- /* nothing new */
- return 0;
-+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-+
++ if(kernelver)
++ {
+ rewind (mem);
+
+ fscanf (mem, "%*s %Ld %*s", &total);
@@ -126,15 +150,16 @@
+ shared = shared * 1024;
+ cache_total = cache_total * 1024;
+ cache_used = cache_total - (cache_free * 1024);
-+#else
++ }
++else
++ {
+ /*
+ total: used: free: shared: buffers: cached:
+ */
+ fscanf(mem, "%*s %Ld %Ld %Ld %Ld %Ld %Ld", &total, &used, &mfree,
+ &shared, &buffers, &cached);
+ fscanf(mem, "%*s %Ld %Ld", &cache_total, &cache_used);
-+
-+#endif
++ }
+
+ fclose(mem);
+
@@ -159,3 +184,12 @@
void
paint_callback (MBTrayApp *app, Drawable drw )
{
+@@ -340,6 +378,8 @@
+ &argc,
+ &argv );
+
++ kernelver = kernel_version();
++
+ msd.samples = 16;
+
+ if (msd.load) {
diff --git a/packages/matchbox-panel/matchbox-panel_0.9.2.bb b/packages/matchbox-panel/matchbox-panel_0.9.2.bb
index 4c037690b6..0e2ccf3f07 100644
--- a/packages/matchbox-panel/matchbox-panel_0.9.2.bb
+++ b/packages/matchbox-panel/matchbox-panel_0.9.2.bb
@@ -1,6 +1,6 @@
include matchbox-panel.inc
-PR="r9"
+PR="r10"
SRC_URI = "http://projects.o-hand.com/matchbox/sources/${PN}/0.9/${PN}-${PV}.tar.gz \
file://add_hostap.patch;patch=1 \
http://handhelds.org/~pb/mb-panel-0.9.2-polling.patch;patch=1 \
diff --git a/packages/meta/nylon-image-base.bb b/packages/meta/nylon-image-base.bb
index ce6c83d847..a4f6d17dd8 100644
--- a/packages/meta/nylon-image-base.bb
+++ b/packages/meta/nylon-image-base.bb
@@ -6,7 +6,8 @@ NYLON_BASE = "base-files base-passwd bash busybox \
nano ncurses netbase \
openssh sysvinit \
timezones tinylogin"
-
+
+DEPENDS = "virtual/kernel"
RDEPENDS = "kernel modutils-depmod modutils-modinfo \
${NYLON_BASE} ${BOOTSTRAP_EXTRA_RDEPENDS}"
@@ -17,5 +18,5 @@ IMAGE_LINGUAS = ""
# we dont need the kernel in the image
ROOTFS_POSTPROCESS_COMMAND = "rm -f ${IMAGE_ROOTFS}/tmp/zImage*"
-inherit image_ipk
+inherit image_ipk nylon-image
LICENSE = MIT
diff --git a/packages/meta/nylon-image-standard.bb b/packages/meta/nylon-image-standard.bb
index 2542e16f7a..8d10e9a30f 100644
--- a/packages/meta/nylon-image-standard.bb
+++ b/packages/meta/nylon-image-standard.bb
@@ -6,9 +6,10 @@ NYLON_STANDARD = "\
bridge-utils \
dnsmasq \
hostap-utils \
+ hostap-daemon \
linux-hotplug \
ifplugd iproute2 iptables \
- mobilemesh \
+ madwifi-modules \
nylon-scripts \
olsrd \
ppp pciutils \
@@ -16,7 +17,9 @@ NYLON_STANDARD = "\
shorewall \
tcpdump \
usbutils \
- wireless-tools"
+ wireless-tools \
+ wpa-supplicant \
+ yamonenv"
DEPENDS += "hostap-modules ntp \
${NYLON_STANDARD}"
diff --git a/packages/meta/slugos-image.bb b/packages/meta/slugos-image.bb
index c3c1b1c104..9434e5076f 100644
--- a/packages/meta/slugos-image.bb
+++ b/packages/meta/slugos-image.bb
@@ -7,7 +7,7 @@ DESCRIPTION = "Generic SlugOS image"
MAINTAINER = "NSLU2 Linux <nslu2-linux@yahoogroups.com>"
HOMEPAGE = "http://www.nslu2-linux.org"
LICENSE = "MIT"
-PR = "r25"
+PR = "r26"
# SLUGOS_IMAGENAME defines the name of the image to be build, if it
# is not set this package will be skipped!
@@ -111,8 +111,8 @@ python () {
# LinkSys have made "EraseAll" available, however, (this does overwrite RedBoot)
# it is a bad idea to produce flash images without a valid RedBoot - that allows
# an innocent user upgrade attempt to instantly brick the NSLU2.
-PACK_IMAGE_nslu2 = "nslu2_pack_image;"
-PACK_IMAGE_DEPENDS_nslu2 = "${@['', 'slugimage-native nslu2-linksys-firmware'][bb.data.getVar('SLUGOS_FLASH_IMAGE', d, 1) == 'yes']}"
+PACK_IMAGE += "${@['', 'nslu2_pack_image;'][bb.data.getVar('SLUGOS_FLASH_IMAGE', d, 1) == 'yes']}"
+PACK_IMAGE_DEPENDS += "${@['', 'slugimage-native nslu2-linksys-firmware'][bb.data.getVar('SLUGOS_FLASH_IMAGE', d, 1) == 'yes']}"
NSLU2_SLUGIMAGE_ARGS ?= ""
diff --git a/packages/meta/slugos-packages.bb b/packages/meta/slugos-packages.bb
index a5a1feeb94..64f021a938 100644
--- a/packages/meta/slugos-packages.bb
+++ b/packages/meta/slugos-packages.bb
@@ -154,6 +154,9 @@ SLUGOS_PACKAGES = "\
wget \
wireless-tools \
wpa-supplicant \
+ wview-sim wview-vpro wview-wxt510 \
+ wview-sim-mysql wview-vpro-mysql \
+ wview-wxt510-mysql \
zd1211 \
zip \
zlib \
diff --git a/packages/gpe-calendar/gpe-calendar-0.61/.mtn2git_empty b/packages/mozilla/firefox-1.0.7/.mtn2git_empty
index e69de29bb2..e69de29bb2 100644
--- a/packages/gpe-calendar/gpe-calendar-0.61/.mtn2git_empty
+++ b/packages/mozilla/firefox-1.0.7/.mtn2git_empty
diff --git a/packages/mozilla/firefox-1.0.7/firefox-cc-fix.patch b/packages/mozilla/firefox-1.0.7/firefox-cc-fix.patch
new file mode 100644
index 0000000000..e2df2a390c
--- /dev/null
+++ b/packages/mozilla/firefox-1.0.7/firefox-cc-fix.patch
@@ -0,0 +1,21 @@
+--- mozilla/js/src/Makefile.in 2004-03-31 09:38:54.000000000 -0700
++++ mozilla.new/js/src/Makefile.in 2004-11-12 16:29:32.856436952 -0700
+@@ -342,16 +342,10 @@
+
+ jsopcode.h jsopcode.c: jsopcode.tbl
+
+-ifeq (,$(CROSS_COMPILE)$(filter-out WINNT,$(OS_ARCH)))
++# OE hack - we copy this in
+ jsautocfg.h:
+ touch $@
+-else
+-jsautocfg.h: jscpucfg$(HOST_BIN_SUFFIX)
+- @rm -f $@ jsautocfg.tmp
+- ./jscpucfg > jsautocfg.tmp
+- mv jsautocfg.tmp $@
+-endif
+-
++
+ # jscpucfg is a strange target
+ # Needs to be built with the host compiler but needs to include
+ # the mdcpucfg for the target so it needs the appropriate target defines
diff --git a/packages/mozilla/firefox-1.0.7/jsautocfg.h b/packages/mozilla/firefox-1.0.7/jsautocfg.h
new file mode 100644
index 0000000000..05f3dad50a
--- /dev/null
+++ b/packages/mozilla/firefox-1.0.7/jsautocfg.h
@@ -0,0 +1,52 @@
+#ifndef js_cpucfg___
+#define js_cpucfg___
+
+/* Lovingly crafted by hand avoiding Mozilla stupidity */
+
+#define IS_LITTLE_ENDIAN 1
+#undef IS_BIG_ENDIAN
+
+#define JS_BYTES_PER_BYTE 1L
+#define JS_BYTES_PER_SHORT 2L
+#define JS_BYTES_PER_INT 4L
+#define JS_BYTES_PER_INT64 8L
+#define JS_BYTES_PER_LONG 4L
+#define JS_BYTES_PER_FLOAT 4L
+#define JS_BYTES_PER_DOUBLE 8L
+#define JS_BYTES_PER_WORD 4L
+#define JS_BYTES_PER_DWORD 8L
+
+#define JS_BITS_PER_BYTE 8L
+#define JS_BITS_PER_SHORT 16L
+#define JS_BITS_PER_INT 32L
+#define JS_BITS_PER_INT64 64L
+#define JS_BITS_PER_LONG 32L
+#define JS_BITS_PER_FLOAT 32L
+#define JS_BITS_PER_DOUBLE 64L
+#define JS_BITS_PER_WORD 32L
+
+#define JS_BITS_PER_BYTE_LOG2 3L
+#define JS_BITS_PER_SHORT_LOG2 4L
+#define JS_BITS_PER_INT_LOG2 5L
+#define JS_BITS_PER_INT64_LOG2 6L
+#define JS_BITS_PER_LONG_LOG2 5L
+#define JS_BITS_PER_FLOAT_LOG2 5L
+#define JS_BITS_PER_DOUBLE_LOG2 6L
+#define JS_BITS_PER_WORD_LOG2 5L
+
+#define JS_ALIGN_OF_SHORT 2L
+#define JS_ALIGN_OF_INT 4L
+#define JS_ALIGN_OF_LONG 4L
+#define JS_ALIGN_OF_INT64 4L
+#define JS_ALIGN_OF_FLOAT 4L
+#define JS_ALIGN_OF_DOUBLE 4L
+#define JS_ALIGN_OF_POINTER 4L
+#define JS_ALIGN_OF_WORD 4L
+
+#define JS_BYTES_PER_WORD_LOG2 2L
+#define JS_BYTES_PER_DWORD_LOG2 3L
+#define JS_WORDS_PER_DWORD_LOG2 2L
+
+#define JS_STACK_GROWTH_DIRECTION (-1)
+
+#endif /* js_cpucfg___ */
diff --git a/packages/mozilla/firefox-1.0.7/mozconfig b/packages/mozilla/firefox-1.0.7/mozconfig
new file mode 100644
index 0000000000..025b396ac7
--- /dev/null
+++ b/packages/mozilla/firefox-1.0.7/mozconfig
@@ -0,0 +1,53 @@
+. $topsrcdir/browser/config/mozconfig
+
+# use GTK+-2 widget set with XFT font rendering
+ac_add_options --enable-default-toolkit=gtk2
+ac_add_options --enable-xft
+ac_add_options --disable-freetype2
+
+# enable minimal profile support
+ac_add_options --disable-profilesharing
+ac_add_options --disable-profilelocking
+ac_add_options --enable-single-profile
+
+ac_add_options --with-system-zlib
+ac_add_options --with-system-jpeg
+ac_add_options --with-system-png
+
+ac_add_options --disable-accessibility
+ac_add_options --disable-composer
+#ac_add_options --enable-plaintext-editor-only
+ac_add_options --disable-mailnews
+ac_add_options --disable-ldap
+#ac_add_options --disable-postscript
+ac_add_options --disable-mathml
+ac_add_options --disable-jsd
+ac_add_options --disable-installer
+ac_add_options --disable-xprint
+ac_add_options --disable-necko-disk-cache
+
+# configure necko to allocate smaller network buffers
+ac_add_options --enable-necko-small-buffers
+
+# disable debug logging and tests
+#ac_add_options --disable-dtd-debug
+ac_add_options --disable-logging
+ac_add_options --disable-debug
+ac_add_options --disable-gtktest
+ac_add_options --disable-tests
+
+# build crypto module (PSM + NSS)
+ac_add_options --enable-crypto
+
+# build minimal set of protocol handlers
+ac_add_options --enable-necko-protocols=http,file,res,jar,ftp,about,viewsource
+
+# build minimal set of image decoders
+ac_add_options --enable-image-decoders=png,gif,jpeg
+
+#ac_add_options --enable-reorder
+#ac_add_options --enable-elf-dynstr-gc
+
+# enable static build
+#ac_add_options --disable-shared
+#ac_add_options --enable-static
diff --git a/packages/musicpd/mpd/mpd.init b/packages/musicpd/mpd/mpd.init
new file mode 100644
index 0000000000..98a75d0af7
--- /dev/null
+++ b/packages/musicpd/mpd/mpd.init
@@ -0,0 +1,32 @@
+#! /bin/sh
+#
+# > update-rc.d mpd defaults 20
+#
+
+test -f /usr/bin/mpd || exit 0
+test -f /etc/mpd.conf || exit 0
+
+case "$1" in
+ start)
+ echo -n "Starting music player daemon: mpd"
+ start-stop-daemon --start --quiet --exec /usr/bin/mpd
+ echo "."
+ ;;
+ stop)
+ echo -n "Stopping music player daemon: mpd"
+ start-stop-daemon --stop --quiet --exec /usr/bin/mpd
+ echo "."
+ ;;
+ restart|force-reload)
+ echo -n "Restarting music player daemon: mpd"
+ start-stop-daemon --start --quiet --exec /usr/bin/mpd
+ sleep 2
+ start-stop-daemon --stop --quiet --exec /usr/bin/mpd
+ echo "."
+ ;;
+ *)
+ echo "Usage: /etc/init.d/mpd {start|stop|restart|force-reload}"
+ exit 1
+esac
+
+exit 0
diff --git a/packages/nylon/nylon-scripts_cvs.bb b/packages/nylon/nylon-scripts_cvs.bb
index 0f98108623..b7ce512e87 100644
--- a/packages/nylon/nylon-scripts_cvs.bb
+++ b/packages/nylon/nylon-scripts_cvs.bb
@@ -10,6 +10,7 @@ PR = "r2"
SRC_URI = "http://meshcube.org/download/${PN}_${SRCDATE}.tgz"
S = "${WORKDIR}/${PN}"
+INHIBIT_PACKAGE_STRIP = "1"
do_install() {
(cd ${S}; tar -c --exclude .svn -f - . ) | tar -C ${D} -xpf -
diff --git a/packages/nylon/nylon-statistics.bb b/packages/nylon/nylon-statistics.bb
index 9216568b0d..e24d9c93e8 100644
--- a/packages/nylon/nylon-statistics.bb
+++ b/packages/nylon/nylon-statistics.bb
@@ -9,6 +9,7 @@ PR = "r1"
SRC_URI = "http://meshcube.org/download/${PN}_${SRCDATE}.tgz"
S = "${WORKDIR}/${PN}"
+INHIBIT_PACKAGE_STRIP = "1"
do_install() {
install -d ${D}/srv/www/cgi-bin
diff --git a/packages/nylon/simple-firewall.bb b/packages/nylon/simple-firewall.bb
new file mode 100644
index 0000000000..5698eb732a
--- /dev/null
+++ b/packages/nylon/simple-firewall.bb
@@ -0,0 +1,17 @@
+DESCRIPTION = "simple firewall configuratiopn script"
+SECTION = "base"
+PRIORITY = "optional"
+MAINTAINER = "Bruno Randolf <bruno.randolf@4g-systems.biz>"
+LICENSE = "GPL"
+DEPENDS = "virtual/kernel"
+SRCDATE = "20060114"
+PV = "cvs${SRCDATE}"
+
+INHIBIT_PACKAGE_STRIP = "1"
+
+SRC_URI = "http://meshcube.org/nylon/unstable/sources/${PN}_gruen.4g__${SRCDATE}.tar.gz"
+S = "${WORKDIR}/${PN}"
+
+do_install() {
+ (cd ${S}; tar -c --exclude .svn -f - . ) | tar -C ${D} -xpf -
+}
diff --git a/packages/libgpewidget/libgpewidget-0.100/.mtn2git_empty b/packages/radlib/.mtn2git_empty
index e69de29bb2..e69de29bb2 100644
--- a/packages/libgpewidget/libgpewidget-0.100/.mtn2git_empty
+++ b/packages/radlib/.mtn2git_empty
diff --git a/packages/radlib/radlib-common.inc b/packages/radlib/radlib-common.inc
new file mode 100644
index 0000000000..528515b2cd
--- /dev/null
+++ b/packages/radlib/radlib-common.inc
@@ -0,0 +1,58 @@
+SECTION = "libs"
+LICENSE = "BSD"
+DESCRIPTION = "radlib is a rapid application development library for unix interprocess communications, sockets, SHA utilities, CRC utilities and much more."
+MAINTAINER = "Mark Teel (mark@teel.ws)"
+HOMEPAGE = "http://www.radlib.teel.ws/"
+
+SRC_URI = "${SOURCEFORGE_MIRROR}/radlib/radlib-${PV}.tar.gz"
+
+S = "${WORKDIR}/radlib-${PV}"
+
+inherit autotools
+do_compile_prepend() {
+ rm -f ${STAGING_LIBDIR}/librad.a
+ rm -f ${STAGING_LIBDIR}/librad.la
+ rm -f ${STAGING_LIBDIR}/librad.so
+ rm -f ${STAGING_LIBDIR}/librad.so.0
+ rm -f ${STAGING_LIBDIR}/librad.so.0.0.0
+}
+
+headers = "radbuffers.h \
+ radconffile.h \
+ radcrc.h \
+ raddebug.h \
+ radevents.h \
+ radlist.h \
+ radmsgLog.h \
+ radmsgRouter.h \
+ radprocess.h \
+ radproclist.h \
+ radprocutils.h \
+ radqueue.h \
+ radsemaphores.h \
+ radsha.h \
+ radshmem.h \
+ radsocket.h \
+ radsortlist.h \
+ radstack.h \
+ radstates.h \
+ radsysdefs.h \
+ radsystem.h \
+ radsysutils.h \
+ radtimers.h \
+ radtimeUtils.h \
+ raddatabase.h \
+ radUDPsocket.h"
+
+do_stage () {
+ cd ${S}/src/.libs
+
+ oe_libinstall -so -a librad ${STAGING_LIBDIR}/
+ cd ${S}/h
+ for i in ${headers}; do
+ install -m 0644 $i ${STAGING_INCDIR}/
+ done
+ cd ${S}
+}
+
+
diff --git a/packages/radlib/radlib-mysql.inc b/packages/radlib/radlib-mysql.inc
new file mode 100644
index 0000000000..a6a5923343
--- /dev/null
+++ b/packages/radlib/radlib-mysql.inc
@@ -0,0 +1,6 @@
+DEPENDS = "mysql"
+
+export CFLAGS_append=" -I${STAGING_INCDIR}/mysql "
+
+EXTRA_OECONF = " --host=${TARGET_SYS} --prefix=${STAGING_DIR} --enable-mysql"
+
diff --git a/packages/radlib/radlib-mysql_2.6.2.bb b/packages/radlib/radlib-mysql_2.6.2.bb
new file mode 100644
index 0000000000..93375c8300
--- /dev/null
+++ b/packages/radlib/radlib-mysql_2.6.2.bb
@@ -0,0 +1,3 @@
+include radlib-common.inc
+include radlib-mysql.inc
+PR = "r0"
diff --git a/packages/radlib/radlib.inc b/packages/radlib/radlib.inc
new file mode 100644
index 0000000000..67357ebe55
--- /dev/null
+++ b/packages/radlib/radlib.inc
@@ -0,0 +1 @@
+EXTRA_OECONF = " --host=${TARGET_SYS} --prefix=${STAGING_DIR}"
diff --git a/packages/radlib/radlib_2.6.2.bb b/packages/radlib/radlib_2.6.2.bb
new file mode 100644
index 0000000000..be5f2d0257
--- /dev/null
+++ b/packages/radlib/radlib_2.6.2.bb
@@ -0,0 +1,3 @@
+include radlib-common.inc
+include radlib.inc
+PR = "r0"
diff --git a/packages/slugos-init/files/boot/disk b/packages/slugos-init/files/boot/disk
index 724dc3af5d..6dd7788197 100644
--- a/packages/slugos-init/files/boot/disk
+++ b/packages/slugos-init/files/boot/disk
@@ -20,6 +20,8 @@ then
# wait if required
test "$sleep" -gt 0 && sleep "$sleep"
#
+ # proc is needed for UUID mount
+ mount -t proc proc /proc
# Mount read-write because before exec'ing init
# If a UUID is given (in the environment) this
# is used in preference to the device, but if
diff --git a/packages/slugos-init/slugos-init_0.10.bb b/packages/slugos-init/slugos-init_0.10.bb
index ed183b9278..3f1ab456ac 100644
--- a/packages/slugos-init/slugos-init_0.10.bb
+++ b/packages/slugos-init/slugos-init_0.10.bb
@@ -4,7 +4,7 @@ PRIORITY = "required"
LICENSE = "GPL"
DEPENDS = "base-files devio"
RDEPENDS = "busybox devio"
-PR = "r56"
+PR = "r57"
SRC_URI = "file://boot/flash \
file://boot/disk \
diff --git a/packages/usbutils/usbutils_0.70.bb b/packages/usbutils/usbutils_0.70.bb
index 9c03730cbf..4e68f26d3b 100644
--- a/packages/usbutils/usbutils_0.70.bb
+++ b/packages/usbutils/usbutils_0.70.bb
@@ -5,9 +5,6 @@ LICENSE = "GPL"
PRIORITY = "optional"
DEFAULT_PREFERENCE = "1"
-PREMIRRORS_prepend () {
- ${SOURCEFORGE_MIRROR} http://unc.dl.sourceforge.net/sourceforge
-}
SRC_URI = "${SOURCEFORGE_MIRROR}/linux-usb/usbutils-${PV}.tar.gz"
S = "${WORKDIR}/usbutils-${PV}"
diff --git a/packages/vpnc/files/default.conf b/packages/vpnc/files/default.conf
new file mode 100644
index 0000000000..48b15eca6e
--- /dev/null
+++ b/packages/vpnc/files/default.conf
@@ -0,0 +1,19 @@
+# Comment out the options you need.
+# Verify your config with "vpnc --print-config".
+# You might also try "vpnc --long-help" or look into the documentation.
+
+# Needed (you will be prompted if this is missing):
+#IPSec gateway 10.1.2.3
+#IPSec ID YOURPEERSID
+#IPSec secret YOURPEERSSECRET
+#Xauth username YOURUSERNAME
+#Xauth password YOURPASSWORD
+
+# Optional:
+#UDP Encapsulate
+#UDP Encapsulation Port 10000
+#Noninteractive
+#No Detach
+#Debug 99
+#Interface name tun0
+#Script /etc/vpnc/vpnc-script
diff --git a/packages/vpnc/files/vpnc-script.patch b/packages/vpnc/files/vpnc-script.patch
new file mode 100644
index 0000000000..f50e41d575
--- /dev/null
+++ b/packages/vpnc/files/vpnc-script.patch
@@ -0,0 +1,30 @@
+--- vpnc-0.3.3.orig/vpnc-script 2005-05-05 19:05:18.000000000 +0200
++++ vpnc-0.3.3/vpnc-script 2006-02-07 23:31:50.000000000 +0100
+@@ -19,6 +19,7 @@
+ #set -x
+
+ OS="`uname -s`"
++mkdir -p /var/run/vpnc
+ DEFAULT_ROUTE_FILE=/var/run/vpnc/defaultroute
+ RESOLV_CONF_BACKUP=/var/run/vpnc/resolv.conf-backup
+
+@@ -219,7 +220,8 @@
+ do_ifconfig
+ set_vpngateway_route
+ if [ -n "$CISCO_SPLIT_INC" ]; then
+- for ((i = 0 ; i < CISCO_SPLIT_INC ; i++ )) ; do
++ CISCO_SPLIT_INC0=`expr "$CISCO_SPLIT_INC" - 1`
++ for i in `seq 0 "$CISCO_SPLIT_INC0"` ; do
+ eval NETWORK="\${CISCO_SPLIT_INC_${i}_ADDR}"
+ eval NETMASK="\${CISCO_SPLIT_INC_${i}_MASK}"
+ eval NETMASKLEN="\${CISCO_SPLIT_INC_${i}_MASKLEN}"
+@@ -239,7 +241,8 @@
+
+ do_disconnect() {
+ if [ -n "$CISCO_SPLIT_INC" ]; then
+- for ((i = 0 ; i < CISCO_SPLIT_INC ; i++ )) ; do
++ CISCO_SPLIT_INC0=`expr "$CISCO_SPLIT_INC" - 1`
++ for i in `seq 0 "$CISCO_SPLIT_INC0"` ; do
+ eval NETWORK="\${CISCO_SPLIT_INC_${i}_ADDR}"
+ eval NETMASK="\${CISCO_SPLIT_INC_${i}_MASK}"
+ eval NETMASKLEN="\${CISCO_SPLIT_INC_${i}_MASKLEN}"
diff --git a/packages/vpnc/vpnc_0.3.3.bb b/packages/vpnc/vpnc_0.3.3.bb
new file mode 100644
index 0000000000..5bcca982e4
--- /dev/null
+++ b/packages/vpnc/vpnc_0.3.3.bb
@@ -0,0 +1,24 @@
+DESCRIPTION = "A client for the Cisco3000 VPN Concentrator"
+SECTION = "console/network"
+PRIORITY = "optional"
+HOMEPAGE = "http://www.unix-ag.uni-kl.de/~massar/vpnc/"
+MAINTAINER = "Matthias Goebl <matthias.goebl@goebl.net>"
+LICENSE = "GPL"
+DEPENDS = "libgcrypt"
+RDEPENDS = "kernel-module-tun"
+PR = "r1"
+
+SRC_URI = "http://www.unix-ag.uni-kl.de/~massar/vpnc/vpnc-${PV}.tar.gz \
+ file://vpnc-script.patch;patch=1 \
+ file://default.conf"
+
+CFLAGS_append = ' -DVERSION=\\"${PV}\\"'
+LDFLAGS_append = " -lgcrypt -lgpg-error"
+
+do_install () {
+ oe_runmake 'DESTDIR=${D}' 'PREFIX=/usr' install
+ rm -f ${D}${sysconfdir}/vpnc/vpnc.conf #This file is useless
+ install ${WORKDIR}/default.conf ${D}${sysconfdir}/vpnc/default.conf
+}
+
+CONFFILES_${PN} = "${sysconfdir}/vpnc/default.conf"
diff --git a/packages/libgpewidget/libgpewidget-0.99/.mtn2git_empty b/packages/wview/.mtn2git_empty
index e69de29bb2..e69de29bb2 100644
--- a/packages/libgpewidget/libgpewidget-0.99/.mtn2git_empty
+++ b/packages/wview/.mtn2git_empty
diff --git a/packages/wview/wview-common.inc b/packages/wview/wview-common.inc
new file mode 100644
index 0000000000..0efeee271c
--- /dev/null
+++ b/packages/wview/wview-common.inc
@@ -0,0 +1,39 @@
+SECTION = "apps"
+LICENSE = "GPL"
+DESCRIPTION = "wview is a weather site generator and more for a variety of weather stations"
+MAINTAINER = "Mark Teel (mark@teel.ws)"
+HOMEPAGE = "http://www.wviewweather.com/"
+DEPENDS += " bash util-linux gd openssl curl update-rc.d"
+
+SRC_URI = "${SOURCEFORGE_MIRROR}/wview/wview-${PV}.tar.gz"
+
+S = "${WORKDIR}/wview-${PV}"
+
+inherit autotools
+
+EXTRA_OECONF += " --enable-wunderground"
+
+do_install_append() {
+ install -d ${D}/${sysconfdir}/init.d
+ install -d ${D}/${sysconfdir}/wview
+ install -d ${D}/${sysconfdir}/wview/html
+ install -d ${D}/${sysconfdir}/wview/alarms
+ install -m 755 ${S}/examples/NSLU2/wview ${D}/${sysconfdir}/init.d
+ install -m 644 ${S}/examples/conf/*.* ${D}/${sysconfdir}/wview
+ install -m 755 ${S}/examples/alarms/*.sh ${D}/${sysconfdir}/wview/alarms
+ install -m 644 ${S}/examples/html/*.* ${D}/${sysconfdir}/wview/html
+
+ install -d ${D}/var/wview
+ install -d ${D}/var/wview/archive
+ install -d ${D}/var/wview/alarms
+ install -d ${D}/var/wview/img
+ install -d ${D}/var/wview/noaa
+ install -m 644 ${S}/bin/img/*.* ${D}/var/wview/img
+
+ if test "x${D}" != "x"; then
+ D="-r ${D}"
+ else
+ D=""
+ fi
+ update-rc.d $D wview defaults 95 15
+}
diff --git a/packages/wview/wview-mysql.inc b/packages/wview/wview-mysql.inc
new file mode 100644
index 0000000000..3b9314eafd
--- /dev/null
+++ b/packages/wview/wview-mysql.inc
@@ -0,0 +1,7 @@
+DEPENDS += " radlib-mysql"
+
+export CFLAGS_append=" -I${STAGING_INCDIR}/mysql "
+export LDFLAGS_append=" -L${STAGING_LIBDIR}/mysql "
+
+EXTRA_OECONF += " --enable-mysql"
+
diff --git a/packages/wview/wview-sim-mysql_3.1.3.bb b/packages/wview/wview-sim-mysql_3.1.3.bb
new file mode 100644
index 0000000000..bc389691b0
--- /dev/null
+++ b/packages/wview/wview-sim-mysql_3.1.3.bb
@@ -0,0 +1,3 @@
+include wview-common.inc
+include wview-mysql.inc
+EXTRA_OECONF += " --enable-station-sim"
diff --git a/packages/wview/wview-sim_3.1.3.bb b/packages/wview/wview-sim_3.1.3.bb
new file mode 100644
index 0000000000..919e322f42
--- /dev/null
+++ b/packages/wview/wview-sim_3.1.3.bb
@@ -0,0 +1,4 @@
+include wview-common.inc
+include wview.inc
+EXTRA_OECONF += " --enable-station-sim"
+PR = "r0"
diff --git a/packages/wview/wview-vpro-mysql_3.1.3.bb b/packages/wview/wview-vpro-mysql_3.1.3.bb
new file mode 100644
index 0000000000..6ef4148662
--- /dev/null
+++ b/packages/wview/wview-vpro-mysql_3.1.3.bb
@@ -0,0 +1,3 @@
+include wview-common.inc
+include wview-mysql.inc
+EXTRA_OECONF += " --enable-station-vpro"
diff --git a/packages/wview/wview-vpro_3.1.3.bb b/packages/wview/wview-vpro_3.1.3.bb
new file mode 100644
index 0000000000..1933e077b5
--- /dev/null
+++ b/packages/wview/wview-vpro_3.1.3.bb
@@ -0,0 +1,4 @@
+include wview-common.inc
+include wview.inc
+EXTRA_OECONF += " --enable-station-vpro"
+PR = "r0"
diff --git a/packages/wview/wview-wxt510-mysql_3.1.3.bb b/packages/wview/wview-wxt510-mysql_3.1.3.bb
new file mode 100644
index 0000000000..e842aae4d6
--- /dev/null
+++ b/packages/wview/wview-wxt510-mysql_3.1.3.bb
@@ -0,0 +1,3 @@
+include wview-common.inc
+include wview-mysql.inc
+EXTRA_OECONF += " --enable-station-wxt510"
diff --git a/packages/wview/wview-wxt510_3.1.3.bb b/packages/wview/wview-wxt510_3.1.3.bb
new file mode 100644
index 0000000000..b7b0ef236d
--- /dev/null
+++ b/packages/wview/wview-wxt510_3.1.3.bb
@@ -0,0 +1,4 @@
+include wview-common.inc
+include wview.inc
+EXTRA_OECONF += " --enable-station-wxt510"
+PR = "r0"
diff --git a/packages/wview/wview.inc b/packages/wview/wview.inc
new file mode 100644
index 0000000000..9b2229d699
--- /dev/null
+++ b/packages/wview/wview.inc
@@ -0,0 +1,2 @@
+DEPENDS += " radlib"
+