diff options
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(®s); ++ ++ /* ++ * 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(®s); ++ ++ /* ++ * 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, ++ // ¤t_frac ); ++ DMA_GET_POSITION(stream->dmahandles[0], &buf_id, &total, ++ ¤t_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, ¤t_frac ); ++ DMA_GET_POSITION(os->dmahandles[0], &buf_id, &total, ++ ¤t_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 (¤t->sigmask_lock); ++ flush_signals (current); ++ spin_unlock (¤t->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" + |