Copyright (c) 2004-2005 Advanced Micro Devices, 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
Index: linux-2.6.11/Documentation/fb/geodefb.txt
===================================================================
--- /dev/null
+++ linux-2.6.11/Documentation/fb/geodefb.txt
@@ -0,0 +1,95 @@
+geodefb.txt
+
+This is the documentation for the AMD Geode LX framebuffer driver.
+
+Kernel Build Configuration Parameters
+-------------------------------------
+These kernel build parameters are operated using "make xconfig" or
+"make menuconfig" from the kernel source root directory.
+The parameter path to these parameters is:
+Device Drivers
+ Graphics Support
+ Support for frame buffer devices
+ AMD Geode generic framebuffer support
+ AMD Geode LX framebuffer driver
+ AMD Geode LX console acceleration
+ AMD Geode Framebuffer panel support
+
+Config_Param Value Definition
+============ ===== ==========
+FB_GEODE (y/m/n) Build AMD Geode generic framebuffer support
+FB_GEODE_LX (y/n) Build AMD Geode LX framebuffer driver (selects CIMARRON)
+FB_GEODE_ACCEL (y/n) Build AMD Geode LX console acceleration
+FB_GEODE_PANEL (y/n) Build AMD Geode Framebuffer panel support
+
+
+Kernel Boot Command Line Argument Options
+-----------------------------------------
+If the geodefb driver has been built into the kernel (not as a module), then
+driver setup options are available via the kernel cmdline interface.
+
+kernel boot command line argument options are available using:
+video=geodefb:[, ...]
+option strings are one of three types:
+identifier as in video=geodefb:off
+identifier=value as in video=geodefb:vfreq=85
+noidenfier as in video=geodefb:noflatpanel
+
+video=option Definition
+============ ==========
+off - specify this option to disable the geodefb.
+vfreq= - specifies the default vertical refresh (default 60)
+vmode= - specifies a mode text string. (default = 640x480@60-16)
+no/compression - disables/enables compression display acceleration (default disabled)
+maxmem - Maximum amount of memory to use for the FB (default 12288K)
+no/accel - disables/enables rendering accelerations (default enabled)
+
+if the module was build with CONFIG_FB_GEODE_PANEL applied
+no/flatpanel - disable/enables flatpanel operation (default enabled)
+no/fphwscale - disable/enables flatpanel hardware scaling (default enabled)
+
+
+Module Parameters:
+------------------
+If geodefb was built as a module, then parameters can be applied
+when the modules is installed (via insmod/modprobe or modules.conf).
+When installing the module, new options are specified as follows:
+modprobe geodefb ... or
+insmod /path/geodefb.ko ...
+
+Module parameters:
+parameter Definition
+========= ==========
+vfreq - Set initial video refresh rate in cycles per second
+vmode - Set initial mode to x@refresh-bpp
+compression - Compression support (0=disabled or 1=enabled)
+maxmem - Maximum amount of memory to use for the FB (in Kbytes)
+accel - HW accleration support (0=disabled or 1=enabled)
+
+if the module was build with CONFIG_FB_GEODE_PANEL applied
+flatpanel - Flatpanel support (0=disabled or 1=enabled)
+fphwscale - FP Hardware Scaling (0=disabled or 1=enabled)
+
+
+Video Modes:
+------------
+The permissible mode parameter values are:
+geometry
+ 640x480, 800x600, 1024x768, 1152x864, 1280x1024, 1600x1200, 1920x1600
+refresh
+ 56, 60, 70, 72, 75, 85, 90, 100
+bpp
+ 8, 16, 32
+
+The permissible mode parameter combinations are defined by the cimarron
+driver, and in cimarron by cim_modes.c.
+
+
+Notes:
+-----
+Since building the geodefb normally select the cimarron driver, please
+review the procedures for building cimarron. To have the framebuffer
+driver work properly with X windows, it is normally necessary to create
+device nodes for /dev/cimarron and possibly links for /dev/videox.
+See cimarron module and lxv4l2 module documentation.
+
Index: linux-2.6.11/Documentation/geode.txt
===================================================================
--- /dev/null
+++ linux-2.6.11/Documentation/geode.txt
@@ -0,0 +1,24 @@
+Running Linux on the AMD Geode Architecture
+=======================================
+
+Configuration Options
+
+The following options enable various Geode and CS5535 features:
+
+CONFIG_MGEODE_GX - Enable GX processor support
+CONFIG_MGEODE_LX - Enable LX processor support
+CONFIG_BLK_DEV_CS5535 - Enable IDE support for the CS5535 companion chip
+CONFIG_HW_RANDOM - Includes support for the LX hardware RNG
+CONFIG_FB_GEODE - Enable Geode framebuffer support
+ CONFIG_FB_GEODE_LX - Enable LX framebuffer support
+ CONFIG_FB_GEODE_ACCEL - Use acceleration for console drawing
+ CONFIG_FB_GEODE_PANEL - Support TFT panels
+CONFIG_USB_OHCI_HCD - Enable OHCI USB support for the CS5535 companion chip
+CONFIG_CIMARRON - (Usually selected automatically) - Support the LX graphics
+ abstraction layer.
+
+In addition - the following kernel option should be selected as a module
+if you are using the Geode ALSA driver modules:
+
+CONFIG_SND_AC97_CODEC
+
Index: linux-2.6.11/Documentation/usb/amd5536udc.txt
===================================================================
--- /dev/null
+++ linux-2.6.11/Documentation/usb/amd5536udc.txt
@@ -0,0 +1,184 @@
+-------------------------------------------------------------------------------
+Howto for Linux device driver for the AMD5536 USB Device Controller (UDC)
+for gadget driver stack
+-------------------------------------------------------------------------------
+
+Author: Thomas Dahlmann
+
+INTRODUCTION:
+
+The AMD5536 UDC is part of x86 southbridge AMD5536 and MIPS CPU Au1200.
+It is a DMA capable usb device controller. The usb port is shared
+between host and UDC. The on-chip UOC controller is used to switch the
+usb port between host, UDC and neutral. So amd5536uoc driver is needed
+to get the UDC operating.
+
+-------------------------------------------------------------------------------
+WHAT YOU NEED:
+-------------------------------------------------------------------------------
+
+copy/replace following files to /usr/src/linux/drivers/usb/gadget
+ amd5536udc.c
+ amd5536udc.h
+ amd5536uoc.c
+ amd5536uoc.h
+ ether.c
+ file_storage.c
+ zero.c
+ inode.c
+ gadget_chips.h
+ Makefile
+ Kconfig
+
+-------------------------------------------------------------------------------
+HOW TO INSTALL IT:
+-------------------------------------------------------------------------------
+
+change to directory /usr/src/linux
+
+configure gadget as module:
+ "make menuconfig"
+ under "Code maturity level options" choose "Prompt for development ..."
+ goto "Device Drivers"
+ goto "USB support" -> "USB Gadget support"
+ choose "Support for USB Gadgets" as module
+ under choice "USB Peripheral Controller" choose "AMD5536-UDC"
+ under "USB Gadget Drivers"
+ choose "Gadget Zero" as module or
+ choose "Ethernet Gagdet" as module or
+ choose "File-backed Storage Gadget" as module
+ exit and save config
+
+compile and install modules:
+ "make modules modules_install"
+
+-------------------------------------------------------------------------------
+HOW TO USE IT:
+-------------------------------------------------------------------------------
+
+*** How to load FILE-BACKED STORAGE gadget driver - mass storage ***
+enable USB mass storage support for linux host:
+ change to directory /usr/src/linux
+ "make menuconfig"
+ under "File systems" choose "DOS/FAT/NT filesystems"
+ choose "MSDOS fs support"
+ under "Device Drivers" under "SCSI device support"
+ choose "SCSI device support"
+ choose "SCSI generic support"
+ under "Device Drivers" under "USB support" in section
+ "USB Device Class drivers" choose
+ "USB Mass Storage support"
+ compile new kernel
+create disk file:
+ "dd bs=1M count=128 if=/dev/zero of=/tmp/disk"
+ => creates a 128Mbyte image file /tmp/disk
+load modules:
+ "modprobe amd5536udc"
+ "modprobe g_file_storage file=/tmp/disk"
+ Note: multiple file arguments are possible, each will be a separate
+ drive for the host side, furthermore devices such as /dev/hda
+ (whole disk will be used) or /dev/hda1 (partition) can be used
+ as argument too
+ "modprobe amd5536uoc"
+create a primary FAT16 disk partition via linux host site:
+ "fdisk /dev/sda", make FAT16 prim. partition
+ => "n", "p", "1", "", "", "t", "6", "w",
+ "mkdosfs /dev/sda1"
+ "sync"
+create primary disk partition via Windows XP host site:
+ right click on "My Computer"
+ choose "Manage" => "Disk Management"
+ choose usb disk and follow instructions of partition menu
+mount usb mass storage device on linux host:
+ make directory "/mnt/gadget/"
+ "mount -t msdos /dev/sda1 /mnt/gadget"
+
+*** How to access files of disk image on UDC side ***
+When files were copied from host to UDC mass storage device then files
+are inside the monolitic disk image (see above) on UDC side. This
+disk image can be mounted via the loopback device driver to a
+directory on UDC side to access these files.
+Steps on UDC side:
+ enable kernel support for loopback device
+ change to directory /usr/src/linux
+ "make menuconfig"
+ under "Block devices" choose "Loopback device support"
+ and recompile the kernel
+ determine offset inside disk image:
+ "fdisk -l -u disk_image", output is like:
+>> You must set cylinders.
+>> You can do this from the extra functions menu.
+>>
+>> Disk /tmp/disk128: 5 heads, 52 sectors, 0 cylinders
+>> Units = sectors of 1 * 512 bytes
+>>
+>> Device Boot Start End Blocks Id System
+>> /tmp/disk128p1 52 262079 131014 6 FAT16
+
+ get offset my multiplying start value by sector size:
+ 52 * 512 = 26624
+ mount disk image:
+ "mount -o loop,offset=26624 -t msdos disk_image /mnt"
+
+
+*** How to load ZERO gadget driver - simple BULK loop back ***
+load modules:
+UDC driver:
+ (a) Slave/Fifo mode: "modprobe amd5536udc use_dma=0"
+ (b) DMA Buffer Fill mode: "modprobe amd5536udc use_dma=1"
+ default:
+ (c) DMA PPBNDU mode: "modprobe amd5536udc"
+ (d) DMA PPBDU mode: "modprobe amd5536udc use_dma=1 use_dma_ppb=1 use_dma_ppb_du=1"
+ (e) fullspeed mode: "modprobe amd5536udc use_fullspeed=1", can be combined
+ with all dma modes
+ (f) special higspeed
+ tx buffer size: "modprobe amd5536udc hs_tx_buf="
+ example: "modprobe amd5536udc use_dma=1 hs_tx_buf=128"
+ => buffer size = 512 bytes (=bulk max packet)
+Gadget Zero driver:
+ (a) Bulk loop: "modprobe g_zero"
+ (b) Int loop: "modprobe g_zero use_interrupt_traffic=1"
+ (c) Source/Sink "modprobe g_zero loopdefault=0"
+ OUT data must all be zero's
+ (d) Source/Sink count "modprobe g_zero loopdefault=0 pattern=1"
+ each OUT packet must count modulo63 (0,1,..,62,0,1,..)
+UOC driver: "modprobe amd5536uoc"
+example:
+ "modprobe amd5536udc"
+ "modprobe g_zero"
+ "modprobe amd5536uoc"
+ => loads driver for DMA PPBNDU mode and Bulk loop
+
+
+*** How to use ETHERNET gadget driver (CDC protocol) ***
+ with Linux Host
+UDC side bringup:
+ load gadget modules
+ "modprobe amd5536udc"
+ "modprobe g_ether"
+ "modprobe amd5536uoc"
+ "ifconfig usb0 192.168.0.2"
+Host side bringup:
+ install support for CDC Ethernet:
+ change to directory /usr/src/linux
+ "make menuconfig"
+ under "Device Drivers" under "USB support" under
+ "USB Network adapters" choose
+ "Multi-purpose USB Networking Framework"
+ choose "CDC Ethernet support"
+ compile mew kernel
+ "modprobe CDCEther"
+ "ifconfig eth1 192.168.0.1"
+ note: assuming there is one network card assigned to eth0,
+ otherwise kernel messages of CDC Ethernet module show
+ which interface (ethX) is used
+Use network connection:
+ after bringup of host and UDC side it behaves like a normal
+ ethernet connection between host and UDC
+ test the connection:
+ host side: "ping -I eth1 192.168.0.2"
+ UDC side : "ping -I usb0 192.168.0.1"
+ note: the "-I" option assures that the USB cable is used, the
+ option can be omitted when the routing table is setup to avoid
+ using other network interfaces as eth0
+
Index: linux-2.6.11/Documentation/usb/amd5536uoc.txt
===================================================================
--- /dev/null
+++ linux-2.6.11/Documentation/usb/amd5536uoc.txt
@@ -0,0 +1,89 @@
+--------------------------------------------------------------------------
+Howto for Linux device driver for the AMD5536 USB Options Controller (UOC)
+--------------------------------------------------------------------------
+
+Author: Karsten Boge
+
+(1)Introduction
+===============
+
+The AMD5536 UOC is part of x86 southbridge AMD5536.
+The USB port is shared between the USB Host Controller
+and the USB Device Controller as defined in BIOS setup.
+The on-chip UOC controller is used to switch the
+usb port between host, UDC and neutral.
+The amd5536uoc driver is needed to get the
+USB Device Controller operating.
+
+(2) Patches
+===========
+
+udc.patch:
+ This containes the UDC driver as together
+ with the UOC driver
+
+(3) Driver source code installation
+===================================
+
+- New files for UOC:
+ drivers/usb/gadget/amd5536uoc.h
+ drivers/usb/gadget/amd5536uoc.c
+
+(4) BIOS setup
+==================
+
+ PCI Configuration
+ UDC: Enabled
+ OTG: Enabled
+ Port 4 assignment: Device
+
+(4) Config options
+==================
+
+ Support for USB Gadgets
+ USB Periheral Controller (?choice?)
+ (X) AMD5536UDC
+
+ The role of the UOC port can be defined
+ within the BIOS setup exclusively.
+
+ Selecting the amd5536udc driver results in
+ building the amd5536uoc driver too.
+ If "Support for USB Gadgets" is configured to be statically
+ linked both modules will be linked into the kernel image
+ otherwise an additional module called amd5536uoc will be built
+
+
+(5) Compile and install
+=======================
+
+ If global USB support is configured to be used as
+ kernel module (usbcore.o) (recomended):
+
+ make modules SUBDIRS=drivers/usb/gadget
+ make modules_install
+
+ If it's linked into the kernel image an new kernel
+ image must be compiled and created before.
+
+(6) Usage
+=========
+
+ modprobe amd5536uoc
+
+ This will load the module and other modules which provide
+ interfaces used by the UOC driver (usbcore, amd5536udc).
+
+ The amd5536uoc driver is needed to power up the uoc logic
+ which controls the pullup resistors connected to either
+ the D+ or D- USB pins.
+ The function of this pullup resistors is to signal the host
+ that a device is connected, and at which speed the device
+ operates.
+
+ Make sure the USB port is assigned to device within the
+ BIOS setup otherwise the modules will not be loaded.
+
+
+
+
Index: linux-2.6.11/MAINTAINERS
===================================================================
--- linux-2.6.11.orig/MAINTAINERS
+++ linux-2.6.11/MAINTAINERS
@@ -255,6 +255,13 @@ P: Ivan Kokshaysky
M: ink@jurassic.park.msu.ru
S: Maintained for 2.4; PCI support for 2.6.
+AMD GEODE PROCESSOR/CHIPSET SUPPORT
+P:
+M:
+L: info-linux@geode.amd.com
+W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html
+S: Supported
+
APM DRIVER
P: Stephen Rothwell
M: sfr@canb.auug.org.au
Index: linux-2.6.11/Makefile
===================================================================
--- linux-2.6.11.orig/Makefile
+++ linux-2.6.11/Makefile
@@ -1,7 +1,8 @@
VERSION = 2
PATCHLEVEL = 6
SUBLEVEL = 11
-EXTRAVERSION =
+AMDVERSION = 02.03.0100
+EXTRAVERSION = -geode-$(AMDVERSION)
NAME=Woozy Numbat
# *DOCUMENTATION*
Index: linux-2.6.11/arch/i386/Kconfig
===================================================================
--- linux-2.6.11.orig/arch/i386/Kconfig
+++ linux-2.6.11/arch/i386/Kconfig
@@ -178,6 +178,7 @@ config M386
- "Pentium-4" for the Intel Pentium 4 or P4-based Celeron.
- "K6" for the AMD K6, K6-II and K6-III (aka K6-3D).
- "Athlon" for the AMD K7 family (Athlon/Duron/Thunderbird).
+ - "Geode GX/LX" for AMD Geode GX and LX processors
- "Crusoe" for the Transmeta Crusoe series.
- "Efficeon" for the Transmeta Efficeon series.
- "Winchip-C6" for original IDT Winchip.
@@ -275,6 +276,21 @@ config MK8
use of some extended instructions, and passes appropriate optimization
flags to GCC.
+config MGEODE_GX
+ bool "Geode GX"
+ help
+ Select this for AMD Geode GX and LX processors.
+ Enables use of some extended instructions, and
+ passes appropriate optimization flags to GCC.
+
+config MGEODE_LX
+ bool "Geode LX"
+ help
+ Select this for AMD Geode LX processors.
+ Enables use of some extended instructions, allows
+ you to use various on-chip devices, and passes appropriate
+ optimization flags to GCC.
+
config MCRUSOE
bool "Crusoe"
help
@@ -358,9 +374,9 @@ config X86_XADD
config X86_L1_CACHE_SHIFT
int
- default "7" if MPENTIUM4 || X86_GENERIC
+ default "7" if MPENTIUM4 || X86_GENERIC
default "4" if X86_ELAN || M486 || M386
- default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2
+ default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_GX || MGEODE_LX
default "6" if MK7 || MK8 || MPENTIUMM
config RWSEM_GENERIC_SPINLOCK
@@ -424,12 +440,12 @@ config X86_INTEL_USERCOPY
config X86_USE_PPRO_CHECKSUM
bool
- depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON
+ depends on MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_GX || MGEODE_LX
default y
config X86_USE_3DNOW
bool
- depends on MCYRIXIII || MK7
+ depends on MCYRIXIII || MK7 || MGEODE_GX || MGEODE_LX
default y
config X86_OOSTORE
@@ -530,7 +546,7 @@ config PREEMPT_BKL
config X86_UP_APIC
bool "Local APIC support on uniprocessors" if !SMP
- depends on !(X86_VISWS || X86_VOYAGER)
+ depends on !(X86_VISWS || X86_VOYAGER || MGEODE_GX || MGEODE_LX)
---help---
A local APIC (Advanced Programmable Interrupt Controller) is an
integrated interrupt controller in the CPU. If you have a single-CPU
@@ -729,6 +745,7 @@ config HIGHMEM4G
config HIGHMEM64G
bool "64GB"
+ depends on !MGEODE_GX && !MGEODE_LX
help
Select this if you have a 32-bit processor and more than 4
gigabytes of physical RAM.
Index: linux-2.6.11/arch/i386/defconfig
===================================================================
--- linux-2.6.11.orig/arch/i386/defconfig
+++ linux-2.6.11/arch/i386/defconfig
@@ -1,21 +1,25 @@
#
# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.11-geode-2.00.00-pre1
+# Fri Jun 3 11:45:26 2005
#
CONFIG_X86=y
CONFIG_MMU=y
CONFIG_UID16=y
CONFIG_GENERIC_ISA_DMA=y
+CONFIG_GENERIC_IOMAP=y
#
# Code maturity level options
#
CONFIG_EXPERIMENTAL=y
CONFIG_CLEAN_COMPILE=y
-CONFIG_STANDALONE=y
+CONFIG_BROKEN_ON_SMP=y
#
# General setup
#
+CONFIG_LOCALVERSION=""
CONFIG_SWAP=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
@@ -23,18 +27,22 @@ CONFIG_POSIX_MQUEUE=y
CONFIG_SYSCTL=y
CONFIG_AUDIT=y
CONFIG_AUDITSYSCALL=y
-CONFIG_LOG_BUF_SHIFT=15
+CONFIG_LOG_BUF_SHIFT=14
CONFIG_HOTPLUG=y
+CONFIG_KOBJECT_UEVENT=y
# CONFIG_IKCONFIG is not set
# CONFIG_EMBEDDED is not set
CONFIG_KALLSYMS=y
+# 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 is not set
+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
#
# Loadable module support
@@ -43,6 +51,7 @@ 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
#
@@ -66,10 +75,12 @@ CONFIG_X86_PC=y
# CONFIG_MPENTIUMII is not set
# CONFIG_MPENTIUMIII is not set
# CONFIG_MPENTIUMM is not set
-CONFIG_MPENTIUM4=y
+# CONFIG_MPENTIUM4 is not set
# CONFIG_MK6 is not set
# CONFIG_MK7 is not set
# CONFIG_MK8 is not set
+# CONFIG_MGEODE_GX is not set
+CONFIG_MGEODE_LX=y
# CONFIG_MCRUSOE is not set
# CONFIG_MEFFICEON is not set
# CONFIG_MWINCHIPC6 is not set
@@ -80,27 +91,19 @@ CONFIG_MPENTIUM4=y
# CONFIG_X86_GENERIC is not set
CONFIG_X86_CMPXCHG=y
CONFIG_X86_XADD=y
-CONFIG_X86_L1_CACHE_SHIFT=7
+CONFIG_X86_L1_CACHE_SHIFT=5
CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
CONFIG_X86_WP_WORKS_OK=y
CONFIG_X86_INVLPG=y
CONFIG_X86_BSWAP=y
CONFIG_X86_POPAD_OK=y
-CONFIG_X86_GOOD_APIC=y
-CONFIG_X86_INTEL_USERCOPY=y
CONFIG_X86_USE_PPRO_CHECKSUM=y
+CONFIG_X86_USE_3DNOW=y
# CONFIG_HPET_TIMER is not set
-# CONFIG_HPET_EMULATE_RTC is not set
-CONFIG_SMP=y
-CONFIG_NR_CPUS=8
-CONFIG_SCHED_SMT=y
-CONFIG_PREEMPT=y
-CONFIG_X86_LOCAL_APIC=y
-CONFIG_X86_IO_APIC=y
-CONFIG_X86_TSC=y
-CONFIG_X86_MCE=y
-CONFIG_X86_MCE_NONFATAL=y
-CONFIG_X86_MCE_P4THERMAL=y
+# CONFIG_SMP is not set
+# CONFIG_PREEMPT is not set
+# CONFIG_X86_MCE is not set
# CONFIG_TOSHIBA is not set
# CONFIG_I8K is not set
# CONFIG_MICROCODE is not set
@@ -115,18 +118,16 @@ CONFIG_NOHIGHMEM=y
# CONFIG_HIGHMEM4G is not set
# CONFIG_HIGHMEM64G is not set
# CONFIG_MATH_EMULATION is not set
-CONFIG_MTRR=y
+# CONFIG_MTRR is not set
# CONFIG_EFI is not set
-CONFIG_IRQBALANCE=y
-CONFIG_HAVE_DEC_LOCK=y
# CONFIG_REGPARM is not set
#
# Power management options (ACPI, APM)
#
CONFIG_PM=y
-CONFIG_SOFTWARE_SUSPEND=y
-# CONFIG_PM_DISK is not set
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SOFTWARE_SUSPEND is not set
#
# ACPI (Advanced Configuration and Power Interface) Support
@@ -139,11 +140,14 @@ CONFIG_ACPI_SLEEP_PROC_FS=y
CONFIG_ACPI_AC=y
CONFIG_ACPI_BATTERY=y
CONFIG_ACPI_BUTTON=y
+# CONFIG_ACPI_VIDEO is not set
CONFIG_ACPI_FAN=y
CONFIG_ACPI_PROCESSOR=y
CONFIG_ACPI_THERMAL=y
# CONFIG_ACPI_ASUS is not set
+# CONFIG_ACPI_IBM is not set
# CONFIG_ACPI_TOSHIBA is not set
+CONFIG_ACPI_BLACKLIST_YEAR=0
# CONFIG_ACPI_DEBUG is not set
CONFIG_ACPI_BUS=y
CONFIG_ACPI_EC=y
@@ -151,6 +155,7 @@ CONFIG_ACPI_POWER=y
CONFIG_ACPI_PCI=y
CONFIG_ACPI_SYSTEM=y
# CONFIG_X86_PM_TIMER is not set
+# CONFIG_ACPI_CONTAINER is not set
#
# APM (Advanced Power Management) BIOS Support
@@ -173,19 +178,21 @@ CONFIG_PCI_GOANY=y
CONFIG_PCI_BIOS=y
CONFIG_PCI_DIRECT=y
CONFIG_PCI_MMCONFIG=y
-# CONFIG_PCI_USE_VECTOR is not set
+# CONFIG_PCIEPORTBUS is not set
CONFIG_PCI_LEGACY_PROC=y
CONFIG_PCI_NAMES=y
-CONFIG_ISA=y
-# CONFIG_EISA is not set
+# CONFIG_ISA is not set
# CONFIG_MCA is not set
# CONFIG_SCx200 is not set
#
-# PCMCIA/CardBus support
+# PCCARD (PCMCIA/CardBus) support
+#
+# CONFIG_PCCARD is not set
+
+#
+# PC-card bridges
#
-# CONFIG_PCMCIA is not set
-CONFIG_PCMCIA_PROBE=y
#
# PCI Hotplug Support
@@ -196,8 +203,8 @@ CONFIG_PCMCIA_PROBE=y
# Executable file formats
#
CONFIG_BINFMT_ELF=y
-CONFIG_BINFMT_AOUT=y
-CONFIG_BINFMT_MISC=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
#
# Device Drivers
@@ -206,7 +213,9 @@ CONFIG_BINFMT_MISC=y
#
# Generic Driver Options
#
-CONFIG_FW_LOADER=m
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
#
# Memory Technology Devices (MTD)
@@ -228,30 +237,36 @@ CONFIG_PARPORT_PC_CML1=y
#
# Plug and Play support
#
-CONFIG_PNP=y
-# CONFIG_PNP_DEBUG is not set
-
-#
-# Protocols
-#
-# CONFIG_ISAPNP is not set
-# CONFIG_PNPBIOS is not set
+# CONFIG_PNP is not set
#
# Block devices
#
CONFIG_BLK_DEV_FD=y
-# CONFIG_BLK_DEV_XD is not set
# CONFIG_PARIDE is not set
# CONFIG_BLK_CPQ_DA is not set
# CONFIG_BLK_CPQ_CISS_DA is not set
# CONFIG_BLK_DEV_DAC960 is not set
# CONFIG_BLK_DEV_UMEM is not set
+# CONFIG_BLK_DEV_COW_COMMON is not set
# CONFIG_BLK_DEV_LOOP is not set
# CONFIG_BLK_DEV_NBD is not set
-# CONFIG_BLK_DEV_CARMEL is not set
+# CONFIG_BLK_DEV_SX8 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_LBD=y
+# 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
@@ -262,6 +277,7 @@ 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_HD_IDE is not set
CONFIG_BLK_DEV_IDEDISK=y
CONFIG_IDEDISK_MULTI_MODE=y
@@ -270,26 +286,22 @@ CONFIG_BLK_DEV_IDECD=y
# 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=y
#
# IDE chipset support/bugfixes
#
CONFIG_IDE_GENERIC=y
-CONFIG_BLK_DEV_CMD640=y
-# CONFIG_BLK_DEV_CMD640_ENHANCED is not set
-# CONFIG_BLK_DEV_IDEPNP is not set
+# CONFIG_BLK_DEV_CMD640 is not set
CONFIG_BLK_DEV_IDEPCI=y
CONFIG_IDEPCI_SHARE_IRQ=y
# CONFIG_BLK_DEV_OFFBOARD is not set
-CONFIG_BLK_DEV_GENERIC=y
+# CONFIG_BLK_DEV_GENERIC is not set
# CONFIG_BLK_DEV_OPTI621 is not set
-CONFIG_BLK_DEV_RZ1000=y
+# CONFIG_BLK_DEV_RZ1000 is not set
CONFIG_BLK_DEV_IDEDMA_PCI=y
# CONFIG_BLK_DEV_IDEDMA_FORCED is not set
CONFIG_IDEDMA_PCI_AUTO=y
# CONFIG_IDEDMA_ONLYDISK is not set
-CONFIG_BLK_DEV_ADMA=y
# CONFIG_BLK_DEV_AEC62XX is not set
# CONFIG_BLK_DEV_ALI15X3 is not set
# CONFIG_BLK_DEV_AMD74XX is not set
@@ -299,6 +311,7 @@ CONFIG_BLK_DEV_ADMA=y
# CONFIG_BLK_DEV_CY82C693 is not set
# CONFIG_BLK_DEV_CS5520 is not set
# CONFIG_BLK_DEV_CS5530 is not set
+CONFIG_BLK_DEV_CS5535=y
# CONFIG_BLK_DEV_HPT34X is not set
# CONFIG_BLK_DEV_HPT366 is not set
# CONFIG_BLK_DEV_SC1200 is not set
@@ -313,7 +326,6 @@ CONFIG_BLK_DEV_PIIX=y
# CONFIG_BLK_DEV_TRM290 is not set
# CONFIG_BLK_DEV_VIA82CXXX is not set
# CONFIG_IDE_ARM is not set
-# CONFIG_IDE_CHIPSETS is not set
CONFIG_BLK_DEV_IDEDMA=y
# CONFIG_IDEDMA_IVB is not set
CONFIG_IDEDMA_AUTO=y
@@ -346,54 +358,35 @@ CONFIG_CHR_DEV_SG=y
#
# 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_BLK_DEV_3W_XXXX_RAID is not set
-# CONFIG_SCSI_7000FASST is not set
+# CONFIG_SCSI_3W_9XXX is not set
# CONFIG_SCSI_ACARD is not set
-# CONFIG_SCSI_AHA152X is not set
-# CONFIG_SCSI_AHA1542 is not set
# CONFIG_SCSI_AACRAID is not set
# CONFIG_SCSI_AIC7XXX is not set
# CONFIG_SCSI_AIC7XXX_OLD is not set
# CONFIG_SCSI_AIC79XX is not set
-CONFIG_SCSI_DPT_I2O=m
-# CONFIG_SCSI_ADVANSYS is not set
-# CONFIG_SCSI_IN2000 is not set
-# CONFIG_SCSI_MEGARAID is not set
-CONFIG_SCSI_SATA=y
-# CONFIG_SCSI_SATA_SVW is not set
-CONFIG_SCSI_ATA_PIIX=y
-# CONFIG_SCSI_SATA_PROMISE is not set
-CONFIG_SCSI_SATA_SX4=m
-# CONFIG_SCSI_SATA_SIL is not set
-CONFIG_SCSI_SATA_SIS=m
-# CONFIG_SCSI_SATA_VIA is not set
-# CONFIG_SCSI_SATA_VITESSE is not set
+# CONFIG_SCSI_DPT_I2O is not set
+# CONFIG_MEGARAID_NEWGEN is not set
+# CONFIG_MEGARAID_LEGACY is not set
+# CONFIG_SCSI_SATA is not set
# CONFIG_SCSI_BUSLOGIC is not set
-# CONFIG_SCSI_CPQFCTS is not set
# CONFIG_SCSI_DMX3191D is not set
-# CONFIG_SCSI_DTC3280 is not set
# CONFIG_SCSI_EATA is not set
# CONFIG_SCSI_EATA_PIO is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_GDTH is not set
-# CONFIG_SCSI_GENERIC_NCR5380 is not set
-# CONFIG_SCSI_GENERIC_NCR5380_MMIO is not set
# CONFIG_SCSI_IPS is not set
+# CONFIG_SCSI_INITIO is not set
# CONFIG_SCSI_INIA100 is not set
# CONFIG_SCSI_PPA is not set
# CONFIG_SCSI_IMM is not set
-# CONFIG_SCSI_NCR53C406A is not set
# CONFIG_SCSI_SYM53C8XX_2 is not set
-CONFIG_SCSI_IPR=m
-# CONFIG_SCSI_IPR_TRACE is not set
-# CONFIG_SCSI_IPR_DUMP is not set
-# CONFIG_SCSI_PAS16 is not set
-# CONFIG_SCSI_PSI240I is not set
-# CONFIG_SCSI_QLOGIC_FAS is not set
+# CONFIG_SCSI_IPR is not set
# CONFIG_SCSI_QLOGIC_ISP is not set
# CONFIG_SCSI_QLOGIC_FC is not set
# CONFIG_SCSI_QLOGIC_1280 is not set
@@ -403,22 +396,12 @@ CONFIG_SCSI_QLA2XXX=y
# CONFIG_SCSI_QLA2300 is not set
# CONFIG_SCSI_QLA2322 is not set
# CONFIG_SCSI_QLA6312 is not set
-# CONFIG_SCSI_QLA6322 is not set
-# CONFIG_SCSI_SYM53C416 is not set
# CONFIG_SCSI_DC395x is not set
# CONFIG_SCSI_DC390T is not set
-# CONFIG_SCSI_T128 is not set
-# CONFIG_SCSI_U14_34F is not set
-# CONFIG_SCSI_ULTRASTOR is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
#
-# Old CD-ROM drivers (not SCSI, not IDE)
-#
-# CONFIG_CD_NO_IDESCSI is not set
-
-#
# Multi-device support (RAID and LVM)
#
# CONFIG_MD is not set
@@ -431,33 +414,7 @@ CONFIG_SCSI_QLA2XXX=y
#
# IEEE 1394 (FireWire) support
#
-CONFIG_IEEE1394=y
-
-#
-# Subsystem Options
-#
-# CONFIG_IEEE1394_VERBOSEDEBUG is not set
-# CONFIG_IEEE1394_OUI_DB is not set
-# CONFIG_IEEE1394_EXTRA_CONFIG_ROMS is not set
-
-#
-# Device Drivers
-#
-
-#
-# Texas Instruments PCILynx requires I2C
-#
-CONFIG_IEEE1394_OHCI1394=y
-
-#
-# Protocol Drivers
-#
-# CONFIG_IEEE1394_VIDEO1394 is not set
-# CONFIG_IEEE1394_SBP2 is not set
-# CONFIG_IEEE1394_ETH1394 is not set
-# CONFIG_IEEE1394_DV1394 is not set
-CONFIG_IEEE1394_RAWIO=y
-# CONFIG_IEEE1394_CMP is not set
+# CONFIG_IEEE1394 is not set
#
# I2O device support
@@ -489,66 +446,11 @@ CONFIG_IP_MULTICAST=y
# CONFIG_INET_AH is not set
# CONFIG_INET_ESP is not set
# CONFIG_INET_IPCOMP is not set
-
-#
-# IP: Virtual Server Configuration
-#
-# CONFIG_IP_VS is not set
+# CONFIG_INET_TUNNEL is not set
+# CONFIG_IP_TCPDIAG is not set
+# CONFIG_IP_TCPDIAG_IPV6 is not set
# CONFIG_IPV6 is not set
-CONFIG_NETFILTER=y
-# CONFIG_NETFILTER_DEBUG is not set
-
-#
-# IP: Netfilter Configuration
-#
-CONFIG_IP_NF_CONNTRACK=y
-# CONFIG_IP_NF_FTP is not set
-# CONFIG_IP_NF_IRC is not set
-# CONFIG_IP_NF_TFTP is not set
-# CONFIG_IP_NF_AMANDA is not set
-CONFIG_IP_NF_QUEUE=y
-CONFIG_IP_NF_IPTABLES=y
-CONFIG_IP_NF_MATCH_LIMIT=y
-CONFIG_IP_NF_MATCH_IPRANGE=y
-CONFIG_IP_NF_MATCH_MAC=y
-CONFIG_IP_NF_MATCH_PKTTYPE=y
-CONFIG_IP_NF_MATCH_MARK=y
-CONFIG_IP_NF_MATCH_MULTIPORT=y
-CONFIG_IP_NF_MATCH_TOS=y
-CONFIG_IP_NF_MATCH_RECENT=y
-CONFIG_IP_NF_MATCH_ECN=y
-CONFIG_IP_NF_MATCH_DSCP=y
-CONFIG_IP_NF_MATCH_AH_ESP=y
-CONFIG_IP_NF_MATCH_LENGTH=y
-CONFIG_IP_NF_MATCH_TTL=y
-CONFIG_IP_NF_MATCH_TCPMSS=y
-CONFIG_IP_NF_MATCH_HELPER=y
-CONFIG_IP_NF_MATCH_STATE=y
-CONFIG_IP_NF_MATCH_CONNTRACK=y
-CONFIG_IP_NF_MATCH_OWNER=y
-CONFIG_IP_NF_FILTER=y
-CONFIG_IP_NF_TARGET_REJECT=y
-CONFIG_IP_NF_NAT=y
-CONFIG_IP_NF_NAT_NEEDED=y
-CONFIG_IP_NF_TARGET_MASQUERADE=y
-CONFIG_IP_NF_TARGET_REDIRECT=y
-CONFIG_IP_NF_TARGET_NETMAP=y
-CONFIG_IP_NF_TARGET_SAME=y
-# CONFIG_IP_NF_NAT_SNMP_BASIC is not set
-CONFIG_IP_NF_MANGLE=y
-CONFIG_IP_NF_TARGET_TOS=y
-CONFIG_IP_NF_TARGET_ECN=y
-CONFIG_IP_NF_TARGET_DSCP=y
-CONFIG_IP_NF_TARGET_MARK=y
-CONFIG_IP_NF_TARGET_CLASSIFY=y
-CONFIG_IP_NF_TARGET_LOG=y
-CONFIG_IP_NF_TARGET_ULOG=y
-CONFIG_IP_NF_TARGET_TCPMSS=y
-CONFIG_IP_NF_ARPTABLES=y
-CONFIG_IP_NF_ARPFILTER=y
-CONFIG_IP_NF_ARP_MANGLE=y
-CONFIG_IP_NF_TARGET_NOTRACK=m
-CONFIG_IP_NF_RAW=m
+# CONFIG_NETFILTER is not set
#
# SCTP Configuration (EXPERIMENTAL)
@@ -566,13 +468,12 @@ CONFIG_IP_NF_RAW=m
# CONFIG_NET_DIVERT is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_FASTROUTE 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
@@ -584,11 +485,10 @@ CONFIG_IP_NF_RAW=m
# CONFIG_IRDA is not set
# CONFIG_BT is not set
CONFIG_NETDEVICES=y
-CONFIG_DUMMY=m
+# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
-# CONFIG_NET_SB1000 is not set
#
# ARCnet devices
@@ -603,27 +503,18 @@ CONFIG_MII=y
# CONFIG_HAPPYMEAL is not set
# CONFIG_SUNGEM is not set
# CONFIG_NET_VENDOR_3COM is not set
-# CONFIG_LANCE is not set
-# CONFIG_NET_VENDOR_SMC is not set
-# CONFIG_NET_VENDOR_RACAL is not set
#
# Tulip family network device support
#
# CONFIG_NET_TULIP is not set
-# CONFIG_AT1700 is not set
-# CONFIG_DEPCA is not set
# CONFIG_HP100 is not set
-# CONFIG_NET_ISA is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
-# CONFIG_AC3200 is not set
-# CONFIG_APRICOT is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_CS89x0 is not set
# CONFIG_DGRS is not set
# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
@@ -641,7 +532,6 @@ CONFIG_8139TOO_PIO=y
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
-# CONFIG_NET_POCKET is not set
#
# Ethernet (1000 Mbit)
@@ -654,14 +544,14 @@ CONFIG_8139TOO_PIO=y
# CONFIG_YELLOWFIN is not set
# CONFIG_R8169 is not set
# CONFIG_SK98LIN is not set
+# CONFIG_VIA_VELOCITY is not set
# CONFIG_TIGON3 is not set
#
# Ethernet (10000 Mbit)
#
# CONFIG_IXGB is not set
-CONFIG_S2IO=m
-# CONFIG_S2IO_NAPI is not set
+# CONFIG_S2IO is not set
#
# Token Ring devices
@@ -724,6 +614,8 @@ CONFIG_SERIO_I8042=y
# CONFIG_SERIO_CT82C710 is not set
# CONFIG_SERIO_PARKBD is not set
# CONFIG_SERIO_PCIPS2 is not set
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
#
# Input Device Drivers
@@ -737,9 +629,6 @@ CONFIG_KEYBOARD_ATKBD=y
CONFIG_INPUT_MOUSE=y
CONFIG_MOUSE_PS2=y
# CONFIG_MOUSE_SERIAL is not set
-# CONFIG_MOUSE_INPORT is not set
-# CONFIG_MOUSE_LOGIBM is not set
-# CONFIG_MOUSE_PC110PAD is not set
# CONFIG_MOUSE_VSXXXAA is not set
# CONFIG_INPUT_JOYSTICK is not set
# CONFIG_INPUT_TOUCHSCREEN is not set
@@ -765,15 +654,14 @@ CONFIG_SERIAL_8250_NR_UARTS=4
#
# Non-8250 serial port support
#
+CONFIG_SERIAL_GEODE_UART2=y
CONFIG_SERIAL_CORE=y
CONFIG_UNIX98_PTYS=y
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=256
-CONFIG_PRINTER=y
-# CONFIG_LP_CONSOLE is not set
+# CONFIG_PRINTER is not set
# CONFIG_PPDEV is not set
# CONFIG_TIPAR is not set
-# CONFIG_QIC02_TAPE is not set
#
# IPMI
@@ -796,29 +684,12 @@ CONFIG_PRINTER=y
#
# Ftape, the floppy tape device driver
#
-CONFIG_AGP=y
-# CONFIG_AGP_ALI is not set
-# CONFIG_AGP_ATI is not set
-# CONFIG_AGP_AMD is not set
-# CONFIG_AGP_AMD64 is not set
-CONFIG_AGP_INTEL=y
-CONFIG_AGP_INTEL_MCH=m
-# CONFIG_AGP_NVIDIA is not set
-# CONFIG_AGP_SIS is not set
-# CONFIG_AGP_SWORKS is not set
-# CONFIG_AGP_VIA is not set
-# CONFIG_AGP_EFFICEON is not set
-CONFIG_DRM=y
-# CONFIG_DRM_TDFX is not set
-# CONFIG_DRM_GAMMA is not set
-# CONFIG_DRM_R128 is not set
-# CONFIG_DRM_RADEON is not set
-# CONFIG_DRM_I810 is not set
-CONFIG_DRM_I830=y
-# CONFIG_DRM_MGA is not set
-# CONFIG_DRM_SIS is not set
+# CONFIG_FTAPE is not set
+# CONFIG_AGP is not set
+# CONFIG_DRM is not set
# CONFIG_MWAVE is not set
# CONFIG_RAW_DRIVER is not set
+# CONFIG_HPET is not set
# CONFIG_HANGCHECK_TIMER is not set
#
@@ -827,6 +698,11 @@ CONFIG_DRM_I830=y
# CONFIG_I2C is not set
#
+# Dallas's 1-wire bus
+#
+# CONFIG_W1 is not set
+
+#
# Misc devices
#
# CONFIG_IBM_ASM is not set
@@ -851,7 +727,6 @@ CONFIG_DRM_I830=y
# Console display driver support
#
CONFIG_VGA_CONSOLE=y
-# CONFIG_MDA_CONSOLE is not set
CONFIG_DUMMY_CONSOLE=y
#
@@ -865,7 +740,6 @@ CONFIG_SOUND=y
CONFIG_SND=y
CONFIG_SND_TIMER=y
CONFIG_SND_PCM=y
-CONFIG_SND_RAWMIDI=y
CONFIG_SND_SEQUENCER=y
# CONFIG_SND_SEQ_DUMMY is not set
CONFIG_SND_OSSEMUL=y
@@ -878,7 +752,6 @@ CONFIG_SND_SEQUENCER_OSS=y
#
# Generic devices
#
-CONFIG_SND_MPU401_UART=y
# CONFIG_SND_DUMMY is not set
# CONFIG_SND_VIRMIDI is not set
# CONFIG_SND_MTPAV is not set
@@ -886,37 +759,12 @@ CONFIG_SND_MPU401_UART=y
# CONFIG_SND_MPU401 is not set
#
-# ISA devices
-#
-# CONFIG_SND_AD1848 is not set
-# CONFIG_SND_CS4231 is not set
-# CONFIG_SND_CS4232 is not set
-# CONFIG_SND_CS4236 is not set
-# CONFIG_SND_ES1688 is not set
-# CONFIG_SND_ES18XX is not set
-# CONFIG_SND_GUSCLASSIC is not set
-# CONFIG_SND_GUSEXTREME is not set
-# CONFIG_SND_GUSMAX is not set
-# CONFIG_SND_INTERWAVE is not set
-# CONFIG_SND_INTERWAVE_STB is not set
-# CONFIG_SND_OPTI92X_AD1848 is not set
-# CONFIG_SND_OPTI92X_CS4231 is not set
-# CONFIG_SND_OPTI93X is not set
-# CONFIG_SND_SB8 is not set
-# CONFIG_SND_SB16 is not set
-# CONFIG_SND_SBAWE is not set
-# CONFIG_SND_WAVEFRONT is not set
-# CONFIG_SND_CMI8330 is not set
-# CONFIG_SND_OPL3SA2 is not set
-# CONFIG_SND_SGALAXY is not set
-# CONFIG_SND_SSCAPE is not set
-
-#
# PCI devices
#
-CONFIG_SND_AC97_CODEC=y
+CONFIG_SND_AC97_CODEC=m
# CONFIG_SND_ALI5451 is not set
# CONFIG_SND_ATIIXP is not set
+# CONFIG_SND_ATIIXP_MODEM is not set
# CONFIG_SND_AU8810 is not set
# CONFIG_SND_AU8820 is not set
# CONFIG_SND_AU8830 is not set
@@ -925,6 +773,8 @@ CONFIG_SND_AC97_CODEC=y
# CONFIG_SND_CS46XX is not set
# CONFIG_SND_CS4281 is not set
# CONFIG_SND_EMU10K1 is not set
+# CONFIG_SND_EMU10K1X is not set
+# CONFIG_SND_CA0106 is not set
# CONFIG_SND_KORG1212 is not set
# CONFIG_SND_MIXART is not set
# CONFIG_SND_NM256 is not set
@@ -944,16 +794,18 @@ CONFIG_SND_AC97_CODEC=y
# CONFIG_SND_FM801 is not set
# CONFIG_SND_ICE1712 is not set
# CONFIG_SND_ICE1724 is not set
-CONFIG_SND_INTEL8X0=y
+# CONFIG_SND_INTEL8X0 is not set
# CONFIG_SND_INTEL8X0M is not set
# CONFIG_SND_SONICVIBES is not set
# CONFIG_SND_VIA82XX is not set
+# CONFIG_SND_VIA82XX_MODEM is not set
# CONFIG_SND_VX222 is not set
#
-# ALSA USB devices
+# USB devices
#
# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_USX2Y is not set
#
# Open Sound System
@@ -972,6 +824,10 @@ CONFIG_USB=y
CONFIG_USB_DEVICEFS=y
# CONFIG_USB_BANDWIDTH is not set
# CONFIG_USB_DYNAMIC_MINORS is not set
+CONFIG_USB_SUSPEND=y
+# CONFIG_USB_OTG is not set
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
#
# USB Host Controller Drivers
@@ -981,6 +837,7 @@ CONFIG_USB_EHCI_HCD=y
# CONFIG_USB_EHCI_ROOT_HUB_TT is not set
# CONFIG_USB_OHCI_HCD is not set
CONFIG_USB_UHCI_HCD=y
+# CONFIG_USB_SL811_HCD is not set
#
# USB Device Class drivers
@@ -989,9 +846,14 @@ CONFIG_USB_UHCI_HCD=y
# CONFIG_USB_BLUETOOTH_TTY is not set
# CONFIG_USB_MIDI is not set
# CONFIG_USB_ACM is not set
-CONFIG_USB_PRINTER=y
+# 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_RW_DETECT is not set
# CONFIG_USB_STORAGE_DATAFAB is not set
# CONFIG_USB_STORAGE_FREECOM is not set
# CONFIG_USB_STORAGE_ISD200 is not set
@@ -1002,7 +864,7 @@ CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_JUMPSHOT is not set
#
-# USB Human Interface Devices (HID)
+# USB Input Devices
#
CONFIG_USB_HID=y
CONFIG_USB_HIDINPUT=y
@@ -1013,7 +875,7 @@ CONFIG_USB_HIDINPUT=y
# CONFIG_USB_KBTAB is not set
# CONFIG_USB_POWERMATE is not set
# CONFIG_USB_MTOUCH is not set
-CONFIG_USB_EGALAX=m
+# CONFIG_USB_EGALAX is not set
# CONFIG_USB_XPAD is not set
# CONFIG_USB_ATI_REMOTE is not set
@@ -1022,7 +884,6 @@ CONFIG_USB_EGALAX=m
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_HPUSBSCSI is not set
#
# USB Multimedia devices
@@ -1034,7 +895,7 @@ CONFIG_USB_EGALAX=m
#
#
-# USB Network adaptors
+# USB Network Adapters
#
# CONFIG_USB_CATC is not set
# CONFIG_USB_KAWETH is not set
@@ -1057,22 +918,37 @@ CONFIG_USB_EGALAX=m
#
# 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=m
-CONFIG_USB_PHIDGETSERVO=m
+# 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_TEST 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
+
+#
+# InfiniBand support
+#
+# CONFIG_INFINIBAND is not set
+
+#
# File systems
#
CONFIG_EXT2_FS=y
@@ -1086,10 +962,15 @@ CONFIG_JBD=y
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=y
@@ -1100,6 +981,7 @@ CONFIG_ISO9660_FS=y
CONFIG_JOLIET=y
# CONFIG_ZISOFS is not set
CONFIG_UDF_FS=y
+CONFIG_UDF_NLS=y
#
# DOS/FAT/NT Filesystems
@@ -1107,6 +989,8 @@ CONFIG_UDF_FS=y
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
#
@@ -1118,6 +1002,7 @@ CONFIG_SYSFS=y
# CONFIG_DEVFS_FS is not set
# 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
@@ -1153,6 +1038,7 @@ CONFIG_LOCKD=y
CONFIG_EXPORTFS=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
@@ -1193,6 +1079,7 @@ CONFIG_NLS_CODEPAGE_437=y
# 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
@@ -1211,23 +1098,21 @@ CONFIG_NLS_ISO8859_1=y
#
# Profiling support
#
-CONFIG_PROFILING=y
-CONFIG_OPROFILE=y
+# CONFIG_PROFILING is not set
#
# Kernel hacking
#
# CONFIG_DEBUG_KERNEL is not set
-CONFIG_EARLY_PRINTK=y
-CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_BUGVERBOSE=y
# CONFIG_FRAME_POINTER is not set
+CONFIG_EARLY_PRINTK=y
CONFIG_4KSTACKS=y
-CONFIG_X86_FIND_SMP_CONFIG=y
-CONFIG_X86_MPPARSE=y
#
# Security options
#
+# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
#
@@ -1236,13 +1121,17 @@ CONFIG_X86_MPPARSE=y
# CONFIG_CRYPTO is not set
#
+# Hardware crypto devices
+#
+
+#
# Library routines
#
+# CONFIG_CRC_CCITT is not set
CONFIG_CRC32=y
CONFIG_LIBCRC32C=m
-CONFIG_X86_SMP=y
-CONFIG_X86_HT=y
+# CONFIG_CIMARRON is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_GENERIC_IRQ_PROBE=y
CONFIG_X86_BIOS_REBOOT=y
-CONFIG_X86_TRAMPOLINE=y
-CONFIG_X86_STD_RESOURCES=y
CONFIG_PC=y
Index: linux-2.6.11/arch/i386/kernel/apm.c
===================================================================
--- linux-2.6.11.orig/arch/i386/kernel/apm.c
+++ linux-2.6.11/arch/i386/kernel/apm.c
@@ -1061,22 +1061,23 @@ static int apm_engage_power_management(u
static int apm_console_blank(int blank)
{
- int error;
- u_short state;
+ int error, i;
+ u_short state;
+ u_short dev[3] = { 0x100, 0x1FF, 0x101 };
state = blank ? APM_STATE_STANDBY : APM_STATE_READY;
- /* Blank the first display device */
- error = set_power_state(0x100, state);
- if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) {
- /* try to blank them all instead */
- error = set_power_state(0x1ff, state);
- if ((error != APM_SUCCESS) && (error != APM_NO_ERROR))
- /* try to blank device one instead */
- error = set_power_state(0x101, state);
+
+ for (i = 0; i < 3; i++) {
+ error = set_power_state(dev[i], state);
+
+ if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
+ return 1;
+
+ if (error == APM_NOT_ENGAGED)
+ break;
}
- if ((error == APM_SUCCESS) || (error == APM_NO_ERROR))
- return 1;
- if (error == APM_NOT_ENGAGED) {
+
+ if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) {
static int tried;
int eng_error;
if (tried++ == 0) {
Index: linux-2.6.11/arch/i386/kernel/cpu/amd.c
===================================================================
--- linux-2.6.11.orig/arch/i386/kernel/cpu/amd.c
+++ linux-2.6.11/arch/i386/kernel/cpu/amd.c
@@ -145,6 +145,13 @@ static void __init init_amd(struct cpuin
set_bit(X86_FEATURE_K6_MTRR, c->x86_capability);
break;
}
+
+ if ( c->x86_model == 10 ) {
+ /* AMD Geode LX is model 10 */
+ /* placeholder for any needed mods */
+ break;
+ }
+
break;
case 6: /* An Athlon/Duron */
Index: linux-2.6.11/arch/i386/kernel/cpu/cyrix.c
===================================================================
--- linux-2.6.11.orig/arch/i386/kernel/cpu/cyrix.c
+++ linux-2.6.11/arch/i386/kernel/cpu/cyrix.c
@@ -346,6 +346,50 @@ static void __init init_cyrix(struct cpu
return;
}
+
+static void __init init_nsc(struct cpuinfo_x86 *c)
+{
+
+
+ /* Handle the National Semiconductor models with non-Cyrix init */
+ if ( (c->x86 == 5) && (c->x86_model >= 4 && c->x86_model <= 5)) {
+ /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+ 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+ clear_bit(0*32+31, c->x86_capability);
+
+ get_model_name(c);
+
+ switch ( c->x86_model ) {
+ case 4: /* GX1/SCxx00 */
+
+ /* TODO Finish up the GX1/SCxx00 detection */
+ /* GX1 uses bits 16 and 24 differently -
+ you could probably just do
+
+ clear_bit(0*32+16, &c->x86_capability);
+ clear_bit(0*32+24, &c->x86_capability);
+
+ since I don't think the kernel supports
+ FPU-CMOV or Cyrix MMX. Unsure tho.
+
+ Also checking GX1 cache here needs to be done -
+ display_cacheinfo() won't work according to
+ AMD specs.
+ */
+
+ break;
+
+ case 5: /* GX */
+ display_cacheinfo(c);
+ break;
+ }
+ } else {
+ /* invoke the 'base class' */
+ init_cyrix(c);
+ }
+}
+
+
/*
* Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected
* by the fact that they preserve the flags across the division of 5/2.
@@ -426,7 +470,7 @@ int __init cyrix_init_cpu(void)
static struct cpu_dev nsc_cpu_dev __initdata = {
.c_vendor = "NSC",
.c_ident = { "Geode by NSC" },
- .c_init = init_cyrix,
+ .c_init = init_nsc,
.c_identify = generic_identify,
};
Index: linux-2.6.11/drivers/char/hw_random.c
===================================================================
--- linux-2.6.11.orig/drivers/char/hw_random.c
+++ linux-2.6.11/drivers/char/hw_random.c
@@ -1,4 +1,10 @@
/*
+ Added support for the AMD Geode LX RNG
+ (c) Copyright 2004-2005 Advanced Micro Devices, Inc.
+
+
+ derived from
+
Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
(c) Copyright 2003 Red Hat Inc
@@ -95,6 +101,13 @@ static unsigned int via_data_present (vo
static u32 via_data_read (void);
#endif
+#ifdef CONFIG_MGEODE_LX
+static int __init geode_init(struct pci_dev *dev);
+static void geode_cleanup(void);
+static unsigned int geode_data_present (void);
+static u32 geode_data_read (void);
+#endif
+
struct rng_operations {
int (*init) (struct pci_dev *dev);
void (*cleanup) (void);
@@ -122,6 +135,9 @@ enum {
rng_hw_intel,
rng_hw_amd,
rng_hw_via,
+#ifdef CONFIG_MGEODE_LX
+ rng_hw_geode,
+#endif
};
static struct rng_operations rng_vendor_ops[] = {
@@ -139,6 +155,11 @@ static struct rng_operations rng_vendor_
/* rng_hw_via */
{ via_init, via_cleanup, via_data_present, via_data_read, 1 },
#endif
+
+#ifdef CONFIG_MGEODE_LX
+ /* rng_hw_geode */
+ { geode_init, geode_cleanup, geode_data_present, geode_data_read, 4 }
+#endif
};
/*
@@ -159,6 +180,10 @@ static struct pci_device_id rng_pci_tbl[
{ 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
{ 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
+#ifdef CONFIG_MGEODE_LX
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_geode },
+#endif
{ 0, }, /* terminate list */
};
MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
@@ -460,7 +485,55 @@ static void via_cleanup(void)
}
#endif
+#ifdef CONFIG_MGEODE_LX
+
+/***********************************************************************
+ *
+ * AMD Geode RNG operations
+ *
+ */
+
+static void __iomem *geode_rng_base = 0x0;
+
+#define GEODE_RNG_DATA_REG 0x50
+#define GEODE_RNG_STATUS_REG 0x54
+
+static u32 geode_data_read(void) {
+ u32 val;
+ val = *((u32 *) (geode_rng_base + GEODE_RNG_DATA_REG));
+ return val;
+}
+
+static unsigned int geode_data_present(void) {
+ u32 val;
+
+ val = *((u32 *) (geode_rng_base + GEODE_RNG_STATUS_REG));
+ return val;
+}
+
+static void geode_cleanup(void) {
+ iounmap(geode_rng_base);
+ geode_rng_base = NULL;
+}
+
+static int geode_init(struct pci_dev *dev) {
+ u32 rng_base = pci_resource_start(dev, 0);
+ if (!rng_base) return 1;
+
+ geode_rng_base = ioremap(rng_base, 0x58);
+
+ if (geode_rng_base == NULL) {
+ printk(KERN_ERR PFX "Cannot ioremap RNG memory\n");
+ return -EBUSY;
+ }
+
+ printk(KERN_INFO PFX "Geode RNG registers at %p\n", geode_rng_base);
+ return 0;
+}
+
+#endif
+
/***********************************************************************
*
* /dev/hwrandom character device handling (major 10, minor 183)
@@ -577,7 +650,7 @@ static int __init rng_init (void)
DPRINTK ("ENTER\n");
- /* Probe for Intel, AMD RNGs */
+ /* Probe for Intel, AMD, Geode RNGs */
for_each_pci_dev(pdev) {
ent = pci_match_device (rng_pci_tbl, pdev);
if (ent) {
Index: linux-2.6.11/drivers/char/vt_ioctl.c
===================================================================
--- linux-2.6.11.orig/drivers/char/vt_ioctl.c
+++ linux-2.6.11/drivers/char/vt_ioctl.c
@@ -36,6 +36,10 @@
char vt_dont_switch;
extern struct tty_driver *console_driver;
+/* Adding a notifier chain when we go from VT_TEXT to VT_GRAPHICS */
+
+struct notifier_block *console_notifier_list;
+
#define VT_IS_IN_USE(i) (console_driver->ttys[i] && console_driver->ttys[i]->count)
#define VT_BUSY(i) (VT_IS_IN_USE(i) || i == fg_console || vc_cons[i].d == sel_cons)
@@ -474,6 +478,7 @@ int vt_ioctl(struct tty_struct *tty, str
* XXX It should at least call into the driver, fbdev's definitely
* need to restore their engine state. --BenH
*/
+
if (!perm)
return -EPERM;
switch (arg) {
@@ -490,8 +495,17 @@ int vt_ioctl(struct tty_struct *tty, str
if (vt_cons[console]->vc_mode == (unsigned char) arg)
return 0;
vt_cons[console]->vc_mode = (unsigned char) arg;
+
if (console != fg_console)
return 0;
+
+ if (arg == KD_TEXT)
+ notifier_call_chain(&console_notifier_list,
+ CONSOLE_EVENT_SWITCH_TEXT, 0);
+ else if (arg == KD_GRAPHICS)
+ notifier_call_chain(&console_notifier_list,
+ CONSOLE_EVENT_SWITCH_GRAPHICS, 0);
+
/*
* explicitly blank/unblank the screen if switching modes
*/
Index: linux-2.6.11/drivers/ide/Kconfig
===================================================================
--- linux-2.6.11.orig/drivers/ide/Kconfig
+++ linux-2.6.11/drivers/ide/Kconfig
@@ -540,6 +540,14 @@ config BLK_DEV_CS5530
It is safe to say Y to this question.
+config BLK_DEV_CS5535
+ tristate "AMD CS5535 chipset support"
+ help
+ Include support for UDMA on the National Semiconductor/AMD 5535
+ chipset. This will automatically be detected and configured if found.
+
+ It is safe to say Y to this question.
+
config BLK_DEV_HPT34X
tristate "HPT34X chipset support"
help
Index: linux-2.6.11/drivers/ide/pci/Makefile
===================================================================
--- linux-2.6.11.orig/drivers/ide/pci/Makefile
+++ linux-2.6.11/drivers/ide/pci/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_BLK_DEV_ATIIXP) += atiixp.
obj-$(CONFIG_BLK_DEV_CMD64X) += cmd64x.o
obj-$(CONFIG_BLK_DEV_CS5520) += cs5520.o
obj-$(CONFIG_BLK_DEV_CS5530) += cs5530.o
+obj-$(CONFIG_BLK_DEV_CS5535) += cs5535.o
obj-$(CONFIG_BLK_DEV_SC1200) += sc1200.o
obj-$(CONFIG_BLK_DEV_CY82C693) += cy82c693.o
obj-$(CONFIG_BLK_DEV_HPT34X) += hpt34x.o
Index: linux-2.6.11/drivers/ide/pci/amd74xx.c
===================================================================
--- linux-2.6.11.orig/drivers/ide/pci/amd74xx.c
+++ linux-2.6.11/drivers/ide/pci/amd74xx.c
@@ -72,6 +72,7 @@ static struct amd_ide_chip {
{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 },
+ { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 }, /* AMD Hiddensee */
{ 0 }
};
@@ -487,6 +488,7 @@ static ide_pci_device_t amd74xx_chipsets
/* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"),
/* 13 */ DECLARE_NV_DEV("NFORCE-CK804"),
/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
+ /* 15 */ DECLARE_AMD_DEV("AMD5536"),
};
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
@@ -521,6 +523,7 @@ static struct pci_device_id amd74xx_pci_
#endif
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
Index: linux-2.6.11/drivers/ide/pci/cs5535.c
===================================================================
--- /dev/null
+++ linux-2.6.11/drivers/ide/pci/cs5535.c
@@ -0,0 +1,352 @@
+/*
+ * Copyright (c) 2004-2005 Advanced Micro Devices, 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING
+ * */
+/*
+ * */
+/*
+ * CS5535 documentation available from AMD.
+ * */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "ide-timing.h"
+#include "cs5535.h"
+
+#if defined(DISPLAY_CS5535_TIMINGS) && defined(CONFIG_PROC_FS)
+#include
+#include
+
+static u8 cs5535_proc = 0;
+static struct pci_dev *bmide_dev;
+static u8 w80 = 0;
+
+static int cs5535_get_info (char *buffer, char **addr, off_t offset, int count)
+{
+ char *p = buffer;
+ unsigned long bibma = pci_resource_start(bmide_dev, 4);
+
+ u8 c0 = 0;
+
+ /*
+ * at that point bibma+0x2 et bibma+0xa are byte registers
+ * to investigate:
+ */
+
+ c0 = inb_p((u16)bibma + 0x02);
+
+ p += sprintf(p, "\n "
+ "AMD/NS 5535 Chipset.\n");
+
+ p += sprintf(p, "--------------- drive0 --------- drive1 ------\n");
+ p += sprintf(p, "DMA enabled: %s %s\n",(c0&0x20) ? "yes" : "no ",
+ (c0&0x40) ? "yes" : "no ");
+
+ pci_read_config_byte(bmide_dev, CS5535_CABLE_DETECT, &c0);
+
+ p += sprintf(p, "80 Wire Cable: %s %s\n", (c0 & 1) ? "yes" : "no",
+ (c0 & 2) ? "yes" : "no");
+
+ return p-buffer;
+}
+
+#endif /* DISPLAY_CS5535_TIMINGS && CONFIG_PROC_FS */
+
+/* Format I PIO settings. We seperate out cmd and data for safer timings */
+
+static unsigned int cs5535_pio_cmd_timings[5] =
+{ 0xF7F4, 0x53F3, 0x13F1, 0x5131, 0x1131 };
+static unsigned int cs5535_pio_dta_timings[5] =
+{ 0xF7F4, 0xF173, 0x8141, 0x5131, 0x1131 };
+
+static unsigned int cs5535_mwdma_timings[3] =
+{ 0x7F0FFFF3, 0x7F035352, 0x7f024241 };
+
+static unsigned int cs5535_udma_timings[5] =
+{ 0x7F7436A1, 0x7F733481, 0x7F723261, 0x7F713161, 0x7F703061 };
+
+/* Macros to check if the register is the reset value - reset value is an
+ invalid timing and indicates the register has not been set previously */
+
+#define CS5535_BAD_PIO(timings) ( (timings&~0x80000000)==0x00009172 )
+#define CS5535_BAD_DMA(timings) ( (timings & 0x000FFFFF) == 0x00077771 )
+
+#define DEFAULT_PIO ( (cs5535_pio_cmd_timings[0] << 16) | cs5535_pio_dta_timings[0] )
+
+static u8 cs5535_get_bios_settings(int unit) {
+
+ u32 pio, dma, dummy;
+ int i;
+
+ rdmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, dma, dummy);
+ rdmsr(unit ? ATAC_CH0D1_PIO : ATAC_CH0D0_PIO, pio, dummy);
+
+ if (!CS5535_BAD_DMA(dma)) {
+ for(i = 0; i < 5; i++)
+ if (cs5535_udma_timings[i] == (dma & 0x7FFFFFFF))
+ return XFER_UDMA_0 + i;
+
+ for(i = 0; i < 3; i++)
+ if (cs5535_mwdma_timings[i] == (dma & 0x7FFFFFFF))
+ return XFER_MW_DMA_0 + i;
+ }
+
+ for(i = 0; i < 5; i++)
+ if ((pio & 0xFFFF) == cs5535_pio_dta_timings[i])
+ return XFER_PIO_0 + i;
+
+ return 0;
+}
+
+static u8 cs5535_get_pio_mode(int unit) {
+
+ u32 reg, dummy;
+ int i;
+
+ rdmsr(unit ? ATAC_CH0D1_PIO : ATAC_CH0D0_PIO, reg, dummy);
+
+ for(i = 0; i < 5; i++) {
+ if ((reg & 0xFFFF) == cs5535_pio_dta_timings[i])
+ return i;
+ }
+
+ BUG();
+ return 0;
+}
+
+static void cs5535_set_speed(ide_drive_t *drive, u8 speed) {
+
+ u32 reg, dummy;
+ int unit = drive->select.b.unit;
+
+ if (speed >= XFER_PIO_0 && speed <= XFER_PIO_4) {
+ u8 data1 = speed - XFER_PIO_0;
+ u8 data2 = cs5535_get_pio_mode(!unit);
+
+ u8 cmd = (data1 < data2) ? data1 : data2;
+
+ /* Write the other drive timings */
+ reg = (cs5535_pio_cmd_timings[cmd] << 16) | cs5535_pio_dta_timings[data2];
+ wrmsr(!unit ? ATAC_CH0D1_PIO : ATAC_CH0D0_PIO, reg, 0);
+
+ /* Write our drive timings*/
+ reg = (cs5535_pio_cmd_timings[cmd] << 16) | cs5535_pio_dta_timings[data1];
+ wrmsr(unit ? ATAC_CH0D1_PIO : ATAC_CH0D0_PIO, reg, 0);
+
+ /* Write the Format 1 bit in the DMA register */
+ rdmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, dummy);
+ wrmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg | 0x80000000, 0);
+ }
+ else {
+ rdmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, dummy);
+
+
+ if (speed >= XFER_UDMA_0 && speed <= XFER_UDMA_7)
+ reg = (reg & 0x80000000) | cs5535_udma_timings[speed - XFER_UDMA_0];
+ else if (speed >= XFER_MW_DMA_0 && speed <= XFER_MW_DMA_2)
+ reg = (reg & 0x80000000) | cs5535_mwdma_timings[speed - XFER_MW_DMA_0];
+ else {
+ printk(KERN_INFO "cs5535: Invalid speed 0x%x requested.\n", speed);
+ return;
+ }
+ wrmsr(unit ? ATAC_CH0D1_DMA : ATAC_CH0D0_DMA, reg, 0);
+ }
+}
+
+static int cs5535_set_drive(ide_drive_t *drive, u8 speed)
+{
+ if (speed != drive->current_speed)
+ ide_config_drive_speed(drive, speed);
+
+ cs5535_set_speed(drive, speed);
+
+ return 0;
+}
+
+/* tuneproc tunes the PIO speed of the device.
+ It is only called during init when autotune = IDE_TUNE_AUTO,
+ so we can avoid doing any default checking.
+*/
+
+static void cs5535_tuneproc (ide_drive_t *drive,u8 pio)
+{
+ u8 speed = 0;
+
+ if (pio == 255)
+ speed = ide_find_best_mode(drive, XFER_PIO | XFER_EPIO);
+ else if (pio < 100)
+ speed = XFER_PIO_0 + min_t(byte, pio, 5);
+ else if (pio < 200)
+ speed = XFER_MW_DMA_0 + min_t(byte, (pio - 100), 2);
+ else
+ speed = XFER_UDMA_0 + min_t(byte, (pio - 200), 7);
+
+ cs5535_set_drive(drive, speed);
+}
+
+static int cs5535_config_dma(ide_drive_t *drive) {
+
+ int unit = drive->select.b.unit;
+ u8 speed = 0;
+ unsigned long map = XFER_PIO | XFER_EPIO | XFER_MWDMA | XFER_UDMA | (w80) ? XFER_UDMA_66 : 0;
+
+ if (drive->autotune == IDE_TUNE_DEFAULT) {
+ drive->autotune = IDE_TUNE_NOAUTO;
+
+ speed = cs5535_get_bios_settings(unit);
+
+ if (speed != 0) {
+ if (!drive->init_speed)
+ drive->init_speed = speed;
+
+ drive->current_speed = speed;
+ }
+ }
+
+ if (!speed) {
+ speed = ide_find_best_mode(drive, map);
+ cs5535_set_drive(drive, speed);
+ }
+
+ if (drive->autodma && (speed & XFER_MODE) != XFER_PIO)
+ return HWIF(drive)->ide_dma_on(drive);
+
+ return HWIF(drive)->ide_dma_off_quietly(drive);
+}
+
+static unsigned int __init init_chipset_cs5535 (struct pci_dev *dev, const char *name)
+{
+ u8 bit;
+
+#if defined(DISPLAY_CS5535_TIMINGS) && defined(CONFIG_PROC_FS)
+ if (!cs5535_proc)
+ {
+ cs5535_proc = 1;
+ bmide_dev = dev;
+ ide_pci_create_host_proc("cs5535", cs5535_get_info);
+ }
+#endif
+
+ pci_read_config_byte(dev, CS5535_CABLE_DETECT, &bit);
+ w80 = bit & 1; /* Remember if we have a 80 wire cable */
+
+ return 0;
+}
+
+static void __init init_hwif_cs5535 (ide_hwif_t *hwif)
+{
+ unsigned long dummy;
+ u32 timings;
+
+ hwif->autodma = 0;
+ hwif->tuneproc = &cs5535_tuneproc;
+ hwif->speedproc = &cs5535_set_drive;
+ hwif->ide_dma_check = &cs5535_config_dma;
+
+ hwif->atapi_dma = 1;
+
+ /* We always support UDMA 0, 1 and 2 */
+
+ hwif->ultra_mask = 0x07;
+ hwif->mwdma_mask = 0x07;
+
+ /* If a 80 wire adapter is attached, add in 3 and 4 */
+ if (w80) hwif->ultra_mask |= 0x18;
+
+ hwif->udma_four = w80; /* w80 = 1 if a 80 conductor line is attached */
+
+ if (hwif->mate)
+ hwif->serialized = hwif->mate->serialized = 1;
+
+ hwif->drives[0].autotune = IDE_TUNE_DEFAULT;
+ hwif->drives[1].autotune = IDE_TUNE_DEFAULT;
+
+ rdmsr(ATAC_CH0D0_PIO,timings,dummy);
+
+ if (CS5535_BAD_PIO(timings)) {
+ wrmsr(ATAC_CH0D0_PIO, DEFAULT_PIO, 0);
+ hwif->drives[0].autotune = IDE_TUNE_AUTO;
+ }
+
+ rdmsr(ATAC_CH0D1_PIO,timings,dummy);
+
+ if (CS5535_BAD_PIO(timings)) {
+ wrmsr(ATAC_CH0D1_PIO,DEFAULT_PIO,0);
+ hwif->drives[1].autotune = IDE_TUNE_AUTO;
+ }
+
+ if (!noautodma) hwif->autodma = 1;
+
+ hwif->drives[0].autodma = hwif->autodma;
+ hwif->drives[1].autodma = hwif->autodma;
+}
+
+static int __devinit cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ ide_setup_pci_device(dev, &cs5535_chipsets[id->driver_data]);
+ return 0;
+}
+
+static struct pci_device_id cs5535_pci_tbl[] __devinitdata =
+{
+ { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_CS5535_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+ { 0, },
+};
+MODULE_DEVICE_TABLE(pci, cs5535_pci_tbl);
+
+static struct pci_driver driver = {
+ .name = "CS5535 IDE",
+ .id_table = cs5535_pci_tbl,
+ .probe = cs5535_init_one,
+};
+
+
+static int cs5535_ide_init(void)
+{
+ return ide_pci_register_driver(&driver);
+}
+
+static void cs5535_ide_exit(void)
+{
+ ide_pci_unregister_driver(&driver);
+}
+
+module_init(cs5535_ide_init);
+module_exit(cs5535_ide_exit);
+
+MODULE_AUTHOR("AMD");
+MODULE_DESCRIPTION("PCI driver module for AMD CS5535 IDE");
+MODULE_LICENSE("GPL");
+
Index: linux-2.6.11/drivers/ide/pci/cs5535.h
===================================================================
--- /dev/null
+++ linux-2.6.11/drivers/ide/pci/cs5535.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2004-2005 Advanced Micro Devices, 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
+ *
+ * The full GNU General Public License is included in this distribution in the
+ * file called COPYING
+ * */
+/*
+ * */
+/*
+ * */
+
+#ifndef CS5535_H
+#define CS5535_H
+
+#include
+#include
+#include
+
+#define DISPLAY_CS5535_TIMINGS
+
+#define MSR_ATAC_BASE 0x51300000
+#define ATAC_GLD_MSR_CAP (MSR_ATAC_BASE+0)
+#define ATAC_GLD_MSR_CONFIG (MSR_ATAC_BASE+0x01)
+#define ATAC_GLD_MSR_SMI (MSR_ATAC_BASE+0x02)
+#define ATAC_GLD_MSR_ERROR (MSR_ATAC_BASE+0x03)
+#define ATAC_GLD_MSR_PM (MSR_ATAC_BASE+0x04)
+#define ATAC_GLD_MSR_DIAG (MSR_ATAC_BASE+0x05)
+#define ATAC_IO_BAR (MSR_ATAC_BASE+0x08)
+#define ATAC_RESET (MSR_ATAC_BASE+0x10)
+#define ATAC_CH0D0_PIO (MSR_ATAC_BASE+0x20)
+#define ATAC_CH0D0_DMA (MSR_ATAC_BASE+0x21)
+#define ATAC_CH0D1_PIO (MSR_ATAC_BASE+0x22)
+#define ATAC_CH0D1_DMA (MSR_ATAC_BASE+0x23)
+#define ATAC_PCI_ABRTERR (MSR_ATAC_BASE+0x24)
+#define ATAC_BM0_CMD_PRIM 0x00
+#define ATAC_BM0_STS_PRIM 0x02
+#define ATAC_BM0_PRD 0x04
+
+#define CS5535_CABLE_DETECT 0x48
+
+static unsigned int init_chipset_cs5535(struct pci_dev *, const char *);
+static void init_hwif_cs5535(ide_hwif_t *);
+
+static ide_pci_device_t cs5535_chipsets[] __devinitdata = {
+ { /* 0 */
+ .name = "CS5535",
+ .init_chipset = init_chipset_cs5535,
+ .init_iops = NULL,
+ .init_hwif = init_hwif_cs5535,
+ .channels = 1,
+ .autodma = AUTODMA,
+ .enablebits = { {0x00,0x00,0x00} },
+ .bootable = ON_BOARD,
+ .extra = 0,
+ }
+};
+
+#endif /* CS5535_H */
Index: linux-2.6.11/drivers/serial/Kconfig
===================================================================
--- linux-2.6.11.orig/drivers/serial/Kconfig
+++ linux-2.6.11/drivers/serial/Kconfig
@@ -572,6 +572,17 @@ config SERIAL_AU1X00_CONSOLE
If you have an Alchemy AU1X00 processor (MIPS based) and you want
to use a console on a serial port, say Y. Otherwise, say N.
+config SERIAL_GEODE_UART2
+ bool "Enable AMD CS5535 UART2 as a serial port"
+ depends on MGEODE_GX || MGEODE_LX
+ default y
+ select SERIAL_CORE
+ help
+ Select this to allow the user to select the secondary CS5535 UART
+ as a 16550 serial port instead of the default DDC interface. The
+ UART2 can be selected by specifying geodeuart2 on the command
+ line.
+
config SERIAL_CORE
tristate
Index: linux-2.6.11/drivers/serial/Makefile
===================================================================
--- linux-2.6.11.orig/drivers/serial/Makefile
+++ linux-2.6.11/drivers/serial/Makefile
@@ -49,3 +49,4 @@ obj-$(CONFIG_SERIAL_M32R_SIO) += m32r_si
obj-$(CONFIG_SERIAL_MPSC) += mpsc.o
obj-$(CONFIG_ETRAX_SERIAL) += crisv10.o
obj-$(CONFIG_SERIAL_TXX9) += serial_txx9.o
+obj-$(CONFIG_SERIAL_GEODE_UART2) += cs5535_uart.o
Index: linux-2.6.11/drivers/serial/cs5535_uart.c
===================================================================
--- /dev/null
+++ linux-2.6.11/drivers/serial/cs5535_uart.c
@@ -0,0 +1,67 @@
+/*
+ * CS5535 UART2 driver
+ * Copyright 2004, AMD
+ */
+
+#include
+#include
+#include
+#include
+
+/* The CS5535 companion chip has two UARTs. This code enables the second
+ UART so other devices can use it. We do it here so we can expose the
+ port early enough for serial debugging
+*/
+
+/* Note - this does not check to see if the CS5535 actually exists */
+
+#define LO(b) (((1 << b) << 16) | 0x0000)
+#define HI(b) ((0x0000 << 16) | (1 << b))
+
+static u32 outtab[16] __initdata =
+{
+ 0x00,HI(4), 0x04,HI(4), 0x08,HI(4),
+ 0x0c,LO(4), 0x10,HI(4), 0x14,LO(4),
+ 0x18,LO(4), 0x1C,LO(4)
+};
+
+static u32 intab[16] __initdata = {
+ 0x20,HI(3), 0x24,LO(3), 0x28,LO(3),
+ 0x2C,LO(3), 0x34,HI(3), 0x38,LO(3),
+ 0x40,LO(3), 0x44,LO(3)
+};
+
+static int __init init_cs5535_uart2(char *str)
+{
+ u32 lo = 0, hi = 0;
+ u32 base; u32 i;
+
+ /* Enable UART2 instead of DDC */
+
+ rdmsr(0x51400014, lo, hi);
+ lo &= 0xFF8FFFFF;
+ lo |= 0x00500000; /* 0x2F8 ttyS1 */
+ wrmsr(0x51400014, lo, hi);
+
+ /* Set up the UART registers */
+ wrmsr(0x5140003E, 0x12, 0x00);
+
+ rdmsr(0x5140000C, lo, hi);
+ base = (u32)(lo & 0xFF00);
+
+ /* Enable the GPIO pins (in and out) */
+
+ for(i = 0; i < 16; i += 2) {
+ outl(outtab[i + 1], base + outtab[i]);
+ outl(intab[i + 1], base + intab[i]);
+ }
+
+ /* Enable the IRQ */
+
+ rdmsr(0x51400021,lo,hi);
+ lo &= 0x0FFFFFFF;
+ lo |= 0x30000000; /* IRQ 3 */
+ wrmsr(0x51400021,lo,hi);
+}
+
+__setup("geodeuart2", init_cs5535_uart2);
Index: linux-2.6.11/drivers/usb/gadget/Kconfig
===================================================================
--- linux-2.6.11.orig/drivers/usb/gadget/Kconfig
+++ linux-2.6.11/drivers/usb/gadget/Kconfig
@@ -86,6 +86,37 @@ config USB_NET2280
depends on USB_GADGET_NET2280
default USB_GADGET
+config USB_GADGET_AMD5536UDC
+ boolean "AMD5536UDC"
+ depends on PCI || SOC_AU1200
+ select USB_GADGET_DUALSPEED
+ help
+ AMD5536 UDC is a PCI based USB peripheral controller which
+ supports both full and high speed USB 2.0 data transfers.
+
+ It has six configurable endpoints, as well as endpoint zero
+ (for control transfers) and several endpoints with dedicated
+ functions.
+
+ Say "y" to link the driver statically, or "m" to build a
+ dynamically linked module called "amd5536udc" and force all
+ gadget drivers to also be dynamically linked.
+
+ If the AMD5536UDC driver is configured to be statically
+ linked this module will be linked into the kernel image
+ as well otherwise two additional modules called "amd5536udc"
+ and "amd5536uoc" will be built.
+
+ The AMD5536 USB device port can be used as
+ either a host port or a device port depending on
+ the assignment within the BIOS setup.
+ For more information, see Documentation/usb/amd5536uoc.txt
+
+config USB_AMD5536UDC
+ tristate
+ depends on USB_GADGET_AMD5536UDC
+ default USB_GADGET
+
config USB_GADGET_PXA2XX
boolean "PXA 2xx or IXP 4xx"
depends on ARCH_PXA || ARCH_IXP4XX
@@ -399,4 +430,20 @@ config USB_G_SERIAL
endchoice
+#
+# AMD5536 USB UOC options
+#
+
+config USB_GADGET_AMD5536UOC
+ boolean
+ depends on USB_GADGET_AMD5536UDC
+ default USB_GADGET_AMD5536UDC
+
+config USB_AMD5536UOC
+ tristate
+ depends on USB_GADGET_AMD5536UOC
+ default USB_GADGET
+
endmenu
+
+
Index: linux-2.6.11/drivers/usb/gadget/Makefile
===================================================================
--- linux-2.6.11.orig/drivers/usb/gadget/Makefile
+++ linux-2.6.11/drivers/usb/gadget/Makefile
@@ -3,6 +3,7 @@
#
obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o
obj-$(CONFIG_USB_NET2280) += net2280.o
+obj-$(CONFIG_USB_AMD5536UDC) += amd5536udc.o
obj-$(CONFIG_USB_PXA2XX) += pxa2xx_udc.o
obj-$(CONFIG_USB_GOKU) += goku_udc.o
obj-$(CONFIG_USB_OMAP) += omap_udc.o
@@ -28,3 +29,8 @@ obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
+#
+# AMD5536 USB UOC options
+#
+obj-$(CONFIG_USB_AMD5536UOC) += amd5536uoc.o
+
Index: linux-2.6.11/drivers/usb/gadget/amd5536udc.c
===================================================================
--- /dev/null
+++ linux-2.6.11/drivers/usb/gadget/amd5536udc.c
@@ -0,0 +1,4786 @@
+/*
+ * AMD 5536 UDC high/full speed USB device controller.
+ */
+
+/*
+ * Copyright (C) 2005 AMD (http://www.amd.com)
+ * Author: Thomas Dahlmann
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU 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
+ */
+
+/*****************************************************************************
+ * Defines
+ *****************************************************************************/
+
+/* debug control */
+#undef UDC_DEBUG
+//DISABLEDamd #define UDC_DEBUG 1
+#undef UDC_VERBOSE
+//DISABLEDamd #define UDC_VERBOSE
+//DISABLEDamd #define UDC_REGISTER_DUMP
+
+/* device driver registration of kernel 2.6.x usage */
+//#define UDC_USE_DRIVER_REGISTER
+
+/* Driver strings */
+#define UDC_MOD_DESCRIPTION "AMD 5536 UDC - USB Device Controller"
+#define UDC_DRIVER_VERSION_STRING "01.00.0204 - $Revision: #13 $"
+
+/* kernel version of new gadget stack generation (for 2.6.x) */
+#define UDC_NEW_GADGET_KERNEL KERNEL_VERSION(2,5,59)
+
+/*****************************************************************************
+ * Includes
+ *****************************************************************************/
+
+/* system */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#if LINUX_VERSION_CODE < UDC_NEW_GADGET_KERNEL
+#include
+#else
+#include
+#include
+#include
+#endif
+#include
+#include
+#include
+#include
+#include
+
+/* MIPS config */
+#ifdef CONFIG_SOC_AU1200
+#if LINUX_VERSION_CODE < UDC_NEW_GADGET_KERNEL
+#include
+#else
+#include
+#endif
+#ifndef CONFIG_USB_NON_PCI_OTGDEVICE
+#define CONFIG_USB_NON_PCI_OTGDEVICE
+#endif
+#endif
+
+/* gadget stack */
+#include
+#include
+#include
+
+/* udc specific */
+#include "amd5536udc.h"
+
+/* use RDE timer for new kernel only */
+#if LINUX_VERSION_CODE >= UDC_NEW_GADGET_KERNEL
+#define UDC_USE_TIMER
+#endif
+/*****************************************************************************
+ * Static Function Declarations
+ *****************************************************************************/
+
+void udc_tasklet_disconnect(unsigned long);
+#ifdef UDC_USE_TIMER
+void udc_timer_function(unsigned long v);
+void udc_pollstall_timer_function(unsigned long v);
+#endif
+static int udc_rxfifo_read_dwords(struct udc* dev, u32* buf, int dwords);
+static void empty_req_queue (struct udc_ep *);
+static int udc_probe (struct pci_dev *pdev, const struct pci_device_id *id);
+static void udc_remove (struct pci_dev *pdev);
+static void udc_basic_init (struct udc *dev);
+static void udc_setup_endpoints (struct udc *dev);
+static void udc_soft_reset(struct udc* dev);
+#ifdef UDC_DEBUG
+static void dump_buffer(u8* buf, u32 bytes);
+static int udc_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+static int udc_open (struct inode *inode, struct file *file);
+static int udc_release (struct inode *inode, struct file *file);
+#endif
+static struct udc_data_dma* udc_get_last_dma_desc(struct udc_request* req);
+static u32 udc_get_ppbdu_rxbytes(struct udc_request* req);
+static int udc_free_dma_chain(struct udc* dev, struct udc_request* req);
+static int udc_create_dma_chain(struct udc_ep* ep, struct udc_request* req, unsigned long buf_len, int gfp_flags);
+static inline int startup_registers(struct udc* dev);
+#ifdef CONFIG_SOC_AU1200
+void au1200_sync(void);
+#endif
+static int udc_remote_wakeup(struct udc* dev);
+#ifdef UDC_USE_DRIVER_REGISTER
+static int udc_suspend(struct udc* dev);
+static int udc_resume(struct udc* dev);
+#endif
+
+/*****************************************************************************
+ * Data
+ *****************************************************************************/
+
+/* description */
+static const char mod_desc [] = UDC_MOD_DESCRIPTION;
+static const char name [] = DRIVER_NAME_FOR_PRINT;
+
+/* structure to hold endpoint function pointers */
+static struct usb_ep_ops udc_ep_ops;
+
+/* received setup data */
+static union udc_setup_data setup_data;
+
+/* pointer to device object */
+static struct udc *udc;
+
+/* irq spin lock for soft reset */
+spinlock_t udc_irq_spinlock;
+/* stall spin lock */
+spinlock_t udc_stall_spinlock;
+
+/* TODO this is used for dma chaining, global gfp not good */
+static int udc_gfp_flags = 0;
+
+/* slave mode: pending bytes in rx fifo after nyet,
+used if EPIN irq came but no req was available */
+static unsigned int udc_rxfifo_pending = 0;
+
+/* count soft resets after suspend to avoid loop */
+static int soft_reset_occured = 0;
+#ifdef UDC_IPBUG_3958_WORKAROUND_SOFT_RESET_ON_USBRESET
+static int soft_reset_after_usbreset_occured = 0;
+#endif
+
+#ifdef UDC_USE_TIMER
+/* timer */
+static struct timer_list udc_timer;
+static int stop_timer = 0;
+int set_rde = -1;
+DECLARE_COMPLETION(on_exit);
+static struct timer_list udc_pollstall_timer;
+static int stop_pollstall_timer = 0;
+DECLARE_COMPLETION(on_pollstall_exit);
+#endif
+
+/* tasklet for usb disconnect */
+DECLARE_TASKLET(disconnect_tasklet, udc_tasklet_disconnect, (unsigned long) &udc);
+
+#ifdef CONFIG_USB_NON_PCI_OTGDEVICE
+static struct pci_dev pdev_dummy;
+static struct pci_dev* pdev = &pdev_dummy;
+#endif
+
+#ifdef UDC_IPBUG_3958_WORKAROUND
+/* CNAK pending field: bit0 = ep0in, bit16 = ep0out */
+static u32 cnak_pending = 0;
+#define UDC_QUEUE_CNAK(ep, num) \
+ if (readl(&((ep)->regs->ctl)) & AMD_BIT(UDC_EPCTL_NAK)) { \
+ DBG("NAK could not be cleared for ep%d\n", num); \
+ cnak_pending |= 1 << (num); \
+ (ep)->naking = 1; \
+ } \
+ else \
+ cnak_pending = cnak_pending & (~(1<<(num)));
+#else
+#define UDC_QUEUE_CNAK(ep, num) {}
+#endif
+#ifdef UDC_IPBUG_3958_WORKAROUND_RXFIFO_FLUSH
+/* rxfifo cleari/trash buffer */
+static u8 udc_rxfifo_trash[UDC_RXFIFO_SIZE];
+#endif
+
+#ifdef UDC_IPBUG_3943_WORKAROUND
+/* otg registering count */
+static u32 otg_reg_count = 0;
+#endif
+/* gadget registering count */
+static u32 gadget_bind_count = 0;
+
+/* endpoint names used for print */
+static const char ep0_string[] = "ep0in";
+static const char *ep_string[] = {
+ ep0_string,
+ "ep1in-int", "ep2in-bulk", "ep3in-bulk", "ep4in-bulk", "ep5in-bulk", "ep6in-bulk", "ep7in-bulk", "ep8in-bulk",
+ "ep9in-bulk", "ep10in-bulk", "ep11in-bulk", "ep12in-bulk", "ep13in-bulk", "ep14in-bulk", "ep15in-bulk", "ep0out",
+ "ep1out-bulk", "ep2out-bulk", "ep3out-bulk", "ep4out-bulk", "ep5out-bulk", "ep6out-bulk", "ep7out-bulk", "ep8out-bulk",
+ "ep9out-bulk", "ep10out-bulk", "ep11out-bulk", "ep12out-bulk", "ep13out-bulk", "ep14out-bulk", "ep15out-bulk"
+};
+
+#ifdef UDC_DEBUG
+/* driver callback functions */
+static struct file_operations udc_fops = {
+ owner: THIS_MODULE,
+
+ read: NULL,
+ write: NULL,
+ ioctl: udc_ioctl,
+ open: udc_open,
+ release: udc_release,
+};
+#endif
+
+/* PCI device parameters */
+static struct pci_device_id pci_id[] = {{
+ .vendor = UDC_PCI_VENID,
+ .device = UDC_PCI_DEVID,
+ .class = UDC_PCI_CLASS,
+ .class_mask = UDC_PCI_CLASS_MASK,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+},
+{}
+};
+
+#ifndef CONFIG_USB_NON_PCI_OTGDEVICE
+/* PCI functions */
+static struct pci_driver udc_pci_driver = {
+ .name = (char *) name,
+ .id_table = pci_id,
+ .probe = udc_probe,
+ .remove = udc_remove,
+};
+#endif
+
+#ifdef UDC_DEBUG
+/* data for debuging only */
+static unsigned long no_pref_req = 0;
+static unsigned long no_req = 0;
+static u32 same_cfg = 0;
+static u32 num_enums = 0;
+#endif
+
+/****** following flags can be set by module parameters */
+/* DMA usage flag */
+static int use_dma = 1;
+/* packet per buffer dma */
+static int use_dma_ppb = 1;
+/* with per descr. update */
+static int use_dma_ppb_du = 0;
+/* buffer fill mode */
+static int use_dma_bufferfill_mode = 0;
+/* full speed only mode */
+static int use_fullspeed = 0;
+/* tx buffer size for high speed */
+static unsigned long hs_tx_buf = UDC_EPIN_BUFF_SIZE;
+
+/* module parameters */
+MODULE_PARM (use_dma, "i");
+MODULE_PARM_DESC (use_dma, "true for DMA");
+MODULE_PARM (use_dma_ppb, "i");
+MODULE_PARM_DESC (use_dma_ppb, "true for DMA in packet per buffer mode");
+MODULE_PARM (use_dma_ppb_du, "i");
+MODULE_PARM_DESC (use_dma_ppb_du, "true for DMA in packet per buffer mode with descriptor update");
+MODULE_PARM (use_fullspeed, "i");
+MODULE_PARM_DESC (use_fullspeed, "true for fullspeed only");
+MODULE_PARM (hs_tx_buf, "l");
+MODULE_PARM_DESC (hs_tx_buf, "high speed tx buffer size for data endpoints in dwords");
+
+MODULE_DESCRIPTION (UDC_MOD_DESCRIPTION);
+MODULE_AUTHOR ("Thomas Dahlmann");
+MODULE_LICENSE("GPL");
+
+#ifndef CONFIG_USB_NON_PCI_OTGDEVICE
+MODULE_DEVICE_TABLE (pci, pci_id);
+#endif
+
+/*****************************************************************************
+ * Function Definitions
+ *****************************************************************************/
+
+/* AU specific */
+#ifdef CONFIG_SOC_AU1200
+void au1200_sync(void)
+{
+ au1200_sync_delay();
+}
+#endif
+
+#ifdef UDC_DEBUG
+/**
+ * Dumps byte read access
+ *
+ * \param a address pointer
+ * \return read byte
+ */
+static void print_td(struct udc_data_dma *p)
+{
+ INFO("td = %08lx: status=%08lx bufptr=%08lx next=%08lx\n",
+ (unsigned long) p,
+ (unsigned long) p->status,
+ (unsigned long) p->bufptr,
+ (unsigned long) p->next);
+}
+#endif
+
+/* printing registers --------------------------------------------------------*/
+/**
+ * Prints UDC device registers and endpoint irq registers
+ *
+ * \param dev pointer to device struct
+ */
+static void print_regs(struct udc* dev)
+{
+#ifndef UDC_IPBUG_3943_WORKAROUND
+ DBG( "------- Device registers -------\n");
+ DBG( "dev config = %08lx\n", (unsigned long) dev->regs->cfg);
+ DBG( "dev control = %08lx\n", (unsigned long) dev->regs->ctl);
+ DBG( "dev status = %08lx\n", (unsigned long) dev->regs->sts);
+ DBG( "\n");
+ DBG( "dev int's = %08lx\n", (unsigned long) dev->regs->irqsts);
+ DBG( "dev intmask = %08lx\n", (unsigned long) dev->regs->irqmsk);
+ DBG( "\n");
+ DBG( "dev ep int's = %08lx\n", (unsigned long) dev->regs->ep_irqsts);
+ DBG( "dev ep intmask = %08lx\n", (unsigned long) dev->regs->ep_irqmsk);
+ DBG( "\n");
+#endif
+ DBG( "USE DMA = %d\n", use_dma);
+ if (use_dma && use_dma_ppb && !use_dma_ppb_du) {
+ DBG( "DMA mode = PPBNDU (packet per buffer WITHOUT desc. update)\n");
+#ifndef UDC_DEBUG
+ INFO( "DMA mode (PPBNDU)\n");
+#endif
+ }
+ else if (use_dma && use_dma_ppb_du && use_dma_ppb_du) {
+ DBG( "DMA mode = PPBDU (packet per buffer WITH desc. update)\n");
+#ifndef UDC_DEBUG
+ INFO( "DMA mode (PPBDU)\n");
+#endif
+ }
+ if (use_dma && use_dma_bufferfill_mode) {
+ DBG( "DMA mode = BF (buffer fill mode)\n");
+#ifndef UDC_DEBUG
+ INFO( "DMA mode (BF)\n");
+#endif
+ }
+#ifndef UDC_DEBUG
+ if (!use_dma) {
+ INFO( "FIFO mode\n");
+ }
+#endif
+#ifdef UDC_USE_TIMER
+ INFO("RDE timer is used\n");
+#endif
+ DBG("-------------------------------------------------------\n");
+}
+
+/**
+ * Prints snapshot of ep registers
+ *
+ * \param dev pointer to device struct
+ */
+#ifdef UDC_DEBUG
+static void print_ep_regs(struct udc* dev, struct udc_ep_regs* ep_regs)
+{
+ INFO( "ep control = %08lx\n", (unsigned long) ep_regs->ctl);
+ INFO( "ep status = %08lx\n", (unsigned long) ep_regs->sts);
+ INFO( "--------------------------------\n");
+}
+
+/* TODO tdahlman: remove */
+/**
+ * Prints misc information, to be removed
+ *
+ * \param dev pointer to device struct
+ */
+static void print_misc(struct udc* dev)
+{
+ print_regs(dev);
+
+ if (use_dma) {
+
+ INFO("no_req=%ld no_pref_req=%ld\n", no_req, no_pref_req);
+ }
+}
+#endif
+
+/* driver functions ----------------------------------------------------------*/
+/**
+ * Called by OS for insmod
+ *
+ * \param inode file node
+ * \param file struct
+ * \return read byte
+ */
+#ifdef UDC_DEBUG
+static int udc_open (struct inode *inode, struct file *file)
+{
+ int retval = 0;
+
+#if LINUX_VERSION_CODE < UDC_NEW_GADGET_KERNEL
+ /* module use counter increment */
+ MOD_INC_USE_COUNT;
+#endif
+
+ return retval;
+}
+
+/**
+ * Called by OS for rmmod
+ *
+ * \param inode file node
+ * \param file file struct
+ * \return read byte
+ */
+static int udc_release (struct inode *inode, struct file *file)
+{
+ int retval = 0;
+
+#if LINUX_VERSION_CODE < UDC_NEW_GADGET_KERNEL
+ /* module use counter decrement */
+ MOD_DEC_USE_COUNT;
+#endif
+ return retval;
+}
+
+/**
+ * Called by OS for ioctl() from user space
+ *
+ * \param inode file node
+ * \param file file struct
+ * \param command ioctl command code
+ * \param argument ioctl argument
+ * \return 0 if success
+ */
+static int udc_ioctl (struct inode *inode,
+ struct file *file,
+ unsigned int command,
+ unsigned long argument)
+{
+ struct udc* dev = udc;
+
+ if (!dev)
+ return -EINVAL;
+
+ /* for testing PM */
+ switch (command)
+ {
+ case 1:
+ udc_remote_wakeup(udc);
+ break;
+ case 5:
+ udc_suspend(udc);
+ break;
+ case 6:
+ udc_resume(udc);
+ break;
+ }
+
+ INFO( "ioctl called\n");
+
+ //print_misc(dev);
+ return 0;
+}
+
+/**
+ * Prints a buffers contents
+ * \param buf pointer to buffer
+ * \param bytes number bytes to print
+ */
+static void dump_buffer(u8* buf, u32 bytes)
+{
+ int i;
+
+ printk("\nbuffer %lx = %d bytes:\n", (unsigned long) buf, bytes);
+ for (i = 0; i < bytes; i++) {
+ printk("%02x", *(buf + i));
+ if ((i+1)%16 == 0)
+ printk("\n");
+ }
+ printk("\n");
+}
+#endif
+
+/**
+ * Masks unused interrupts
+ *
+ * \param dev pointer to device struct
+ * \return 0 if success
+ */
+static int udc_mask_unused_interrupts(struct udc* dev)
+{
+ u32 tmp;
+
+ /* mask all dev interrupts */
+ tmp = AMD_BIT(UDC_DEVINT_SVC) |
+ AMD_BIT(UDC_DEVINT_ENUM) |
+ AMD_BIT(UDC_DEVINT_US) |
+ AMD_BIT(UDC_DEVINT_UR) |
+ AMD_BIT(UDC_DEVINT_ES) |
+ AMD_BIT(UDC_DEVINT_SI) |
+ AMD_BIT(UDC_DEVINT_SOF)|
+ AMD_BIT(UDC_DEVINT_SC);
+ writel(tmp, &dev->regs->irqmsk);
+
+ /* mask all ep interrupts */
+ writel(UDC_EPINT_MSK_DISABLE_ALL, &dev->regs->ep_irqmsk);
+
+ return 0;
+}
+
+/**
+ * Enables endpoint 0 interrupts
+ *
+ * \param dev pointer to device struct
+ * \return 0 if success
+ */
+static int udc_enable_ep0_interrupts(struct udc* dev)
+{
+ u32 tmp;
+
+ DBG("udc_enable_ep0_interrupts()\n");
+
+ /* read irq mask */
+ tmp = readl(&dev->regs->ep_irqmsk);
+ /* enable ep0 irq's */
+ tmp &= AMD_UNMASK_BIT(UDC_EPINT_IN_EP0)
+ & AMD_UNMASK_BIT(UDC_EPINT_OUT_EP0);
+ writel(tmp, &dev->regs->ep_irqmsk);
+
+ return 0;
+}
+
+/**
+ * Enables device interrupts for SET_INTF and SET_CONFIG
+ *
+ * \param dev pointer to device struct
+ * \return 0 if success
+ */
+static int udc_enable_dev_setup_interrupts(struct udc* dev)
+{
+ u32 tmp;
+
+ DBG("enable device interrupts for setup data\n");
+
+ /* read irq mask */
+ tmp = readl(&dev->regs->irqmsk);
+
+ /* enable SET_INTERFACE, SET_CONFIG and other needed irq's */
+ tmp &= AMD_UNMASK_BIT(UDC_DEVINT_SI)
+ & AMD_UNMASK_BIT(UDC_DEVINT_SC)
+ & AMD_UNMASK_BIT(UDC_DEVINT_UR)
+#ifndef UDC_IPBUG_3943_WORKAROUND
+ & AMD_UNMASK_BIT(UDC_DEVINT_US)
+#endif
+#ifndef UDC_IPBUG_3950_WORKAROUND
+ & AMD_UNMASK_BIT(UDC_DEVINT_SVC)
+#endif
+ & AMD_UNMASK_BIT(UDC_DEVINT_ENUM);
+ writel(tmp, &dev->regs->irqmsk);
+
+ return 0;
+}
+
+/**
+ * Calculates fifo start of endpoint based on preceeding endpoints
+ *
+ * \param ep pointer to ep struct
+ * \return 0 if success
+ */
+static int udc_set_txfifo_addr(struct udc_ep *ep)
+{
+ struct udc *dev;
+ u32 tmp;
+ int i;
+
+ if (!ep || !(ep->in))
+ return -EINVAL;
+
+ dev = ep->dev;
+ ep->txfifo = dev->txfifo;
+
+ /* traverse ep's */
+ for (i = 0; i < ep->num; i++) {
+ if (dev->ep[i].regs) {
+ /* read fifo size */
+ tmp = readl(&dev->ep[i].regs->bufin_framenum);
+ tmp = AMD_GETBITS(tmp, UDC_EPIN_BUFF_SIZE);
+ ep->txfifo+= tmp;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Enables endpoint, is called by gadget driver
+ *
+ * \param usbep pointer to ep struct
+ * \param desc pointer to endpoint descriptor
+ * \return 0 if success
+ */
+static int
+udc_enable (struct usb_ep *usbep, const struct usb_endpoint_descriptor *desc)
+{
+ struct udc_ep *ep;
+ struct udc *dev;
+ u32 tmp;
+ unsigned long iflags;
+ u8 udc_csr_epix;
+
+ VDBG("udc_enable()\n");
+
+ ep = container_of (usbep, struct udc_ep, ep);
+ if (!usbep
+ || usbep->name == ep0_string
+ || !desc
+ || desc->bDescriptorType != USB_DT_ENDPOINT) {
+ ERR("udc_enable: !usbep=%d !desc=%d ep->desc!=NULL=%d usbep->name==ep0_string=%d desc->bDescriptorType!=USB_DT_ENDPOINT=%d\n",
+ !usbep, !desc, ep->desc != NULL, usbep->name == ep0_string, desc->bDescriptorType != USB_DT_ENDPOINT);
+ return -EINVAL;
+ }
+
+ DBG("udc_enable() ep %d\n", ep->num);
+
+ dev = ep->dev;
+
+ /* exit on suspend */
+ if (dev->sys_suspended)
+ return -ESHUTDOWN;
+
+ if (!dev->driver
+ || dev->gadget.speed == USB_SPEED_UNKNOWN)
+ return -ESHUTDOWN;
+
+ spin_lock_irqsave (&dev->lock, iflags);
+ ep->desc = desc;
+
+ ep->halted = 0;
+
+ /* set traffic type */
+ tmp = readl(&dev->ep[ep->num].regs->ctl);
+ tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_EPCTL_ET);
+ writel(tmp, &dev->ep[ep->num].regs->ctl);
+
+ /* set max packet size */
+ tmp = readl(&dev->ep[ep->num].regs->bufout_maxpkt);
+ tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_EP_MAX_PKT_SIZE);
+ ep->ep.maxpacket = desc->wMaxPacketSize;
+ writel(tmp, &dev->ep[ep->num].regs->bufout_maxpkt);
+
+ /* IN ep */
+ if (ep->in) {
+
+ /* ep ix in UDC CSR register space */
+ udc_csr_epix = ep->num;
+
+ /* set buffer size (tx fifo entries) */
+ tmp = readl(&dev->ep[ep->num].regs->bufin_framenum);
+ /* double buffering: fifo size = 2 x max packet size */
+ tmp = AMD_ADDBITS(
+ tmp,
+ desc->wMaxPacketSize * UDC_EPIN_BUFF_SIZE_MULT /
+ UDC_DWORD_BYTES,
+ UDC_EPIN_BUFF_SIZE);
+ writel(tmp, &dev->ep[ep->num].regs->bufin_framenum);
+
+ /* calc. tx fifo base addr */
+ udc_set_txfifo_addr(ep);
+
+ /* flush fifo */
+ tmp = readl(&ep->regs->ctl);
+ tmp |= AMD_BIT(UDC_EPCTL_F);
+ writel(tmp, &ep->regs->ctl);
+
+ } /* OUT ep */
+ else {
+ /* ep ix in UDC CSR register space */
+ udc_csr_epix = ep->num - UDC_CSR_EP_OUT_IX_OFS;
+
+ /* set max packet size UDC CSR */
+ tmp = readl(&dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);
+ tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_CSR_NE_MAX_PKT);
+ writel(tmp, &dev->csr->ne[ep->num - UDC_CSR_EP_OUT_IX_OFS]);
+
+ if (ep->num != UDC_EP0OUT_IX)
+ dev->data_ep_enabled = 1;
+ }
+
+ /***** UDC CSR reg ****************************/
+ /* set ep values */
+ tmp = readl(&dev->csr->ne[udc_csr_epix]);
+ /* max packet */
+ tmp = AMD_ADDBITS(tmp, desc->wMaxPacketSize, UDC_CSR_NE_MAX_PKT);
+ /* ep number */
+ tmp = AMD_ADDBITS(tmp, desc->bEndpointAddress, UDC_CSR_NE_NUM);
+ /* ep direction */
+ tmp = AMD_ADDBITS(tmp, ep->in, UDC_CSR_NE_DIR);
+ /* ep type */
+ tmp = AMD_ADDBITS(tmp, desc->bmAttributes, UDC_CSR_NE_TYPE);
+ /* ep config */
+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_config, UDC_CSR_NE_CFG);
+ /* ep interface */
+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_intf, UDC_CSR_NE_INTF);
+ /* ep alt */
+ tmp = AMD_ADDBITS(tmp, ep->dev->cur_alt, UDC_CSR_NE_ALT);
+ /* write reg */
+ writel(tmp, &dev->csr->ne[udc_csr_epix]);
+
+ /* enable ep irq */
+ tmp = readl(&dev->regs->ep_irqmsk);
+ tmp &= AMD_UNMASK_BIT(ep->num);
+ writel(tmp, &dev->regs->ep_irqmsk);
+
+ /* clear NAK by writing CNAK */
+ /* avoid BNA for DMA, dont clear NAK until DMA desc. written */
+ if (!use_dma) {
+ tmp = readl(&ep->regs->ctl);
+ tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+ writel(tmp, &ep->regs->ctl);
+ ep->naking = 0;
+ UDC_QUEUE_CNAK(ep, ep->num);
+ }
+ tmp = desc->bEndpointAddress;
+ DBG( "%s enabled\n",
+ usbep->name);
+
+ spin_unlock_irqrestore (&dev->lock, iflags);
+ return 0;
+}
+/**
+ * Resets endpoint
+ *
+ * \param regs pointer to device register struct
+ * \param ep pointer to endpoint
+ */
+static void ep_init (struct udc_regs *regs, struct udc_ep *ep)
+{
+ u32 tmp;
+
+ VDBG("ep-%d reset\n", ep->num);
+ ep->desc = 0;
+ ep->ep.ops = &udc_ep_ops;
+ INIT_LIST_HEAD (&ep->queue);
+
+ ep->ep.maxpacket = (u16) ~0;
+ if (!(ep->dev->sys_suspended)) {
+ /* set NAK */
+ tmp = readl(&ep->regs->ctl);
+ tmp |= AMD_BIT(UDC_EPCTL_SNAK);
+ writel(tmp, &ep->regs->ctl);
+ ep->naking = 1;
+
+ /* disable interrupt */
+ tmp = readl(®s->ep_irqmsk);
+ tmp |= AMD_BIT(ep->num);
+ writel(tmp, ®s->ep_irqmsk);
+
+ if (ep->in) {
+ /* unset P and IN bit of potential former DMA */
+ tmp = readl(&ep->regs->ctl);
+ tmp &= AMD_UNMASK_BIT(UDC_EPCTL_P);
+ writel(tmp, &ep->regs->ctl);
+
+ tmp = readl(&ep->regs->sts);
+ tmp |= AMD_BIT(UDC_EPSTS_IN);
+ writel(tmp, &ep->regs->sts);
+
+ /* flush the fifo */
+ tmp = readl(&ep->regs->ctl);
+ tmp |= AMD_BIT(UDC_EPCTL_F);
+ writel(tmp, &ep->regs->ctl);
+
+ }
+ /* reset desc pointer */
+ writel(0, &ep->regs->desptr);
+ }
+
+
+}
+
+/**
+ * Disables endpoint, is called by gadget driver
+ *
+ * \param usbep pointer to ep struct
+ * \return 0 if success
+ */
+static int udc_disable (struct usb_ep *usbep)
+{
+ struct udc_ep *ep = NULL;
+ unsigned long iflags;
+
+ if (!usbep)
+ return -EINVAL;
+
+ ep = container_of (usbep, struct udc_ep, ep);
+ if (usbep->name == ep0_string
+ || !ep->desc)
+ return -EINVAL;
+
+ DBG("Disable ep-%d\n", ep->num);
+
+ spin_lock_irqsave(&ep->dev->lock, iflags);
+ empty_req_queue(ep);
+ ep_init(ep->dev->regs, ep);
+ spin_unlock_irqrestore(&ep->dev->lock, iflags);
+
+ return 0;
+}
+
+/**
+ * Allocates request packet, called by gadget driver
+ *
+ * \param _ep pointer to usb ep struct
+ * \param gfp_flags flags for kmalloc
+ * \return allocated request packet, 0 if error
+ */
+static struct usb_request *
+udc_alloc_request (struct usb_ep *usbep, int gfp)
+{
+ struct udc_request *req;
+ struct udc_data_dma *dma_desc;
+ struct udc_ep *ep;
+
+ VDBG("udc_alloc_req()\n");
+ if (!usbep)
+ return 0;
+
+ ep = container_of (usbep, struct udc_ep, ep);
+ /* TODO gfp flags used for dma chaining later - find better way */
+ udc_gfp_flags = gfp;
+
+ VDBG("udc_alloc_req(): ep%d\n", ep->num);
+ req = kmalloc (sizeof (struct udc_request), gfp);
+ if (!req)
+ return 0;
+
+ memset (req, 0, sizeof *req);
+ req->req.dma = DMA_DONT_USE;
+ INIT_LIST_HEAD (&req->queue);
+
+ if (ep->dma) {
+
+#if defined(CONFIG_MIPS)
+ gfp = GFP_ATOMIC | GFP_DMA;
+#endif
+ /* FIXME ep0 in requests are allocated from data pool here */
+ dma_desc = pci_pool_alloc (ep->dev->data_requests, gfp,
+ &req->td_phys);
+ if (!dma_desc) {
+ kfree (req);
+ return 0;
+ }
+
+ VDBG("udc_alloc_req: req = %lx dma_desc = %lx, req->td_phys = %lx\n",
+ (unsigned long) req, (unsigned long) dma_desc, (unsigned long)req->td_phys);
+ /* prevent from using desc. - set HOST BUSY */
+ dma_desc->status = AMD_ADDBITS(dma_desc->status,
+ UDC_DMA_STP_STS_BS_HOST_BUSY,
+ UDC_DMA_STP_STS_BS);
+ dma_desc->bufptr = __constant_cpu_to_le32 (DMA_DONT_USE);
+ req->td_data = dma_desc;
+ req->td_data_last = NULL;
+ req->chain_len = 1;
+ }
+
+ return &req->req;
+}
+
+/**
+ * Frees request packet, called by gadget driver
+ *
+ * \param usbep pointer to usb ep struct
+ * \param usbreq pointer to request packet to be freed
+ */
+static void
+udc_free_request (struct usb_ep *usbep, struct usb_request *usbreq)
+{
+ struct udc_ep *ep;
+ struct udc_request *req;
+
+ if (!usbep || !usbreq)
+ return;
+
+ ep = container_of (usbep, struct udc_ep, ep);
+ req = container_of (usbreq, struct udc_request, req);
+ VDBG("free_req req=%lx\n", (unsigned long) req);
+ WARN_ON(!list_empty (&req->queue));
+ if (req->td_data) {
+ VDBG("req->td_data=%lx\n", (unsigned long) req->td_data);
+
+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND
+ /* re-link broken chain */
+ if (req->td_data_last) {
+ req->td_data_last->next = req->td_data_last_next;
+ }
+#endif
+ /* free dma chain if created */
+ if (req->chain_len > 1) {
+ udc_free_dma_chain(ep->dev, req);
+ }
+
+ pci_pool_free (ep->dev->data_requests, req->td_data, req->td_phys);
+ }
+ kfree (req);
+}
+
+/* choose dma buffer allocation method */
+#undef USE_KMALLOC
+#if defined(CONFIG_X86)
+#define USE_KMALLOC
+/* FIXME TMP26: cached dma buffers seem no to work for 2.6.x to be
+ * examined */
+#elif defined(CONFIG_MIPS)
+/* MIPS kernel 2.4 */
+#if LINUX_VERSION_CODE < UDC_NEW_GADGET_KERNEL
+#if !defined(CONFIG_NONCOHERENT_IO)
+#define USE_KMALLOC
+#endif /* !defined(CONFIG_NONCOHERENT_IO) */
+#endif /* LINUX_VERSION_CODE < UDC_NEW_GADGET_KERNEL */
+#if LINUX_VERSION_CODE >= UDC_NEW_GADGET_KERNEL
+#ifdef CONFIG_DMA_COHERENT
+#define USE_KMALLOC
+#endif /* CONFIG_DMA_COHERENT */
+#endif /* LINUX_VERSION_CODE >= UDC_NEW_GADGET_KERNEL */
+#endif
+
+/**
+ * Allocates data buffer for request packet, called by gadget driver
+ *
+ * \param usbep pointer to usb ep struct
+ * \param bytes number bytes to allocate
+ * \param dma pointer to dma struct
+ * \param gfp_flags flags for allocate
+ * \return pointer to allocated buffer, 0 if error
+ */
+static void *
+udc_alloc_buffer (
+ struct usb_ep *usbep,
+ unsigned len,
+ dma_addr_t *dma,
+ int gfp
+)
+{
+ void *ptr;
+ struct udc_ep *ep;
+ VDBG("alloc_buffer(): %s\n", usbep->name);
+
+ ep = container_of (usbep, struct udc_ep, ep);
+ *dma = DMA_DONT_USE;
+
+ if (!usbep)
+ return 0;
+
+ if (ep->dma) {
+#if defined(USE_KMALLOC)
+
+#if defined(CONFIG_MIPS)
+ gfp = GFP_ATOMIC | GFP_DMA;
+#endif
+ ptr = kmalloc(len, gfp);
+
+ if (ptr)
+ *dma = virt_to_phys(ptr);
+
+#elif LINUX_VERSION_CODE >= UDC_NEW_GADGET_KERNEL
+ ptr = dma_alloc_coherent (&ep->dev->pdev->dev, len, dma, gfp);
+#elif defined (CONFIG_MIPS)
+ ptr = pci_alloc_consistent(ep->dev->pdev, len, dma);
+#else
+#error no memory allocator
+#endif
+ } else
+ ptr = kmalloc(len, gfp);
+
+ VDBG("alloc_buffer() ptr = %lx dma=%lx\n", (unsigned long) ptr, (unsigned long) *dma);
+ return ptr;
+}
+
+
+/**
+ * Free data buffer for request packet, called by gadget driver
+ *
+ * \param usbep pointer to usb ep struct
+ * \param buf pointer to buffer to be freed
+ * \param dma pointer to dma struct
+ * \param len number bytes to be freed
+ * \return pointer to allocated buffer, 0 if error
+ */
+static void
+udc_free_buffer (
+ struct usb_ep *usbep,
+ void *buf,
+ dma_addr_t dma,
+ unsigned len
+) {
+ struct udc_ep *ep;
+
+ VDBG ("ep %s - free buffer %lx\n", usbep->name, (unsigned long) buf);
+
+ /* null pointer ? */
+ if (!buf) {
+ return;
+ }
+
+ ep = container_of(usbep, struct udc_ep, ep);
+ if (!ep)
+ return;
+
+#ifndef USE_KMALLOC
+ if (dma != DMA_DONT_USE) {
+#if LINUX_VERSION_CODE >= UDC_NEW_GADGET_KERNEL
+ dma_free_coherent (&ep->dev->pdev->dev, len, buf, dma);
+#else
+ pci_free_consistent(ep->dev->pdev, len, buf, dma);
+#endif
+ } else
+#endif
+ {
+ if (!(ep->dma))
+ kfree (buf);
+ }
+
+}
+
+/**
+ * Write data to TX fifo for IN packets
+ *
+ * \param ep pointer to ep struct
+ * \param req pointer to request packet
+ * \return allocated request packet, 0 if error
+ */
+static void
+udc_txfifo_write (struct udc_ep *ep, struct usb_request *req)
+{
+ u8 *req_buf;
+ u32 *buf;
+ int i,j;
+ unsigned bytes = 0;
+ unsigned remaining = 0;
+
+ VDBG("udc_txfifo_write()\n");
+
+ if (!req || !ep)
+ return;
+
+ req_buf = req->buf + req->actual;
+ prefetch (req_buf);
+ remaining = req->length - req->actual;
+
+ buf = (u32*) req_buf;
+
+ bytes = ep->ep.maxpacket;
+ if (bytes > remaining)
+ bytes = remaining;
+
+ /* dwords first */
+ for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {
+ writel(*(buf + i), ep->txfifo);
+ }
+
+ /* remaining bytes must be written by byte access */
+ for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {
+ writeb((u8) (*(buf + i) >> (j << UDC_BITS_PER_BYTE_SHIFT)),
+ ep->txfifo);
+ }
+
+#ifdef UDC_IPBUG_2253_WORKAROUND
+ {
+ u32 tmp;
+
+ /* NAK if small packet until write confirm completed */
+ if (bytes < UDC_SMALL_PACKET) {
+ /* set NAK */
+ tmp = readl(&ep->regs->ctl);
+ tmp |= AMD_BIT(UDC_EPCTL_SNAK);
+ writel(tmp, &ep->regs->ctl);
+ ep->naking = 1;
+ wb_flush();
+ }
+
+ /* dummy write confirm */
+ writel(0, &ep->regs->confirm);
+
+ /* stop NAKing after small packet DMA */
+ if (ep->naking) {
+ /* clear NAK by writing CNAK */
+ tmp = readl(&ep->regs->ctl);
+ tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+ writel(tmp, &ep->regs->ctl);
+ ep->naking = 0;
+ UDC_QUEUE_CNAK(ep, ep->num);
+ }
+ }
+#else
+ /* dummy write confirm */
+ writel(0, &ep->regs->confirm);
+#endif
+}
+
+/**
+ * Read dwords from RX fifo for OUT transfers
+ *
+ * \param dev pointer to device struct
+ * \param buf pointer to buffer to be filled
+ * \param dwords number of dwords to be read
+ * \return allocated request packet, 0 if error
+ */
+static int udc_rxfifo_read_dwords(struct udc* dev, u32* buf, int dwords)
+{
+ int i;
+
+ VDBG("udc_read_dwords(): %d dwords\n", dwords);
+
+ for (i = 0; i < dwords; i++)
+ {
+ *(buf + i) = readl(dev->rxfifo);
+ }
+ return 0;
+}
+
+/**
+ * Read bytes from RX fifo for OUT transfers
+ *
+ * \param dev pointer to device struct
+ * \param buf pointer to buffer to be filled
+ * \param bytes number of bytes to be read
+ * \return allocated request packet, 0 if error
+ */
+static int udc_rxfifo_read_bytes(struct udc* dev, u8* buf, int bytes)
+{
+ int i,j;
+ u32 tmp;
+
+ VDBG("udc_read_bytes(): %d bytes\n", bytes);
+
+ /* dwords first */
+ for (i = 0; i < bytes / UDC_DWORD_BYTES; i++) {
+ *((u32*) (buf + (i<<2))) = readl(dev->rxfifo);
+ }
+
+ /* remaining bytes must be read by byte access */
+ if (bytes % UDC_DWORD_BYTES) {
+ tmp = readl(dev->rxfifo);
+ for (j = 0; j < bytes % UDC_DWORD_BYTES; j++) {
+ *(buf + (i<<2) + j) = (u8) (tmp & UDC_BYTE_MASK);
+ tmp = tmp >> UDC_BITS_PER_BYTE;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Read data from RX fifo for OUT transfers
+ *
+ * \param ep pointer to ep struct
+ * \param req pointer to request packet
+ * \return true if request completes for short or max packet, false otherwise
+ */
+static int
+udc_rxfifo_read(struct udc_ep *ep, struct udc_request *req)
+{
+ u8 *buf;
+ unsigned buf_space;
+ unsigned bytes = 0;
+ unsigned finished = 0;
+
+ /* received number bytes */
+ bytes = readl(&ep->regs->sts);
+ bytes = AMD_GETBITS(bytes, UDC_EPSTS_RX_PKT_SIZE);
+
+ buf_space = req->req.length - req->req.actual;
+ buf = req->req.buf + req->req.actual;
+ if (bytes > buf_space) {
+ if ((buf_space % ep->ep.maxpacket) != 0) {
+ ERR( "%s: received %d bytes, rx-buffer space = %d bytes => buffer overrun\n",
+ ep->ep.name, bytes, buf_space);
+ req->req.status = -EOVERFLOW;
+ }
+ bytes = buf_space;
+ }
+ req->req.actual += bytes;
+
+ /* last packet ? */
+ if (((bytes % ep->ep.maxpacket) != 0)
+ || (!bytes)
+ || ((req->req.actual == req->req.length) && !req->req.zero))
+ finished = 1;
+
+ /* read rx fifo bytes */
+ VDBG("ep %s: rxfifo read %d bytes\n", ep->ep.name, bytes);
+ udc_rxfifo_read_bytes(ep->dev, buf, bytes);
+
+ return finished;
+}
+
+/**
+ * create/re-init a DMA descriptor or a DMA descriptor chain
+ *
+ * \param ep pointer to endpoint struct
+ * \param req pointer to request packet
+ */
+static int prep_dma (struct udc_ep *ep, struct udc_request *req)
+{
+ int retval = 0;
+ u32 tmp;
+ VDBG("prep_dma\n");
+ VDBG("prep_dma ep%d req->td_data=%lx\n",
+ ep->num, (unsigned long) req->td_data);
+
+ /* set buffer pointer */
+ req->td_data->bufptr = req->req.dma;
+
+ /* set last bit */
+ req->td_data->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+
+ /* build/re-init dma chain if maxpkt scatter mode, not for EP0 */
+ if (use_dma_ppb && ep->num != UDC_EP0OUT_IX && ep->num != UDC_EP0IN_IX) {
+
+ retval = udc_create_dma_chain(ep, req, ep->ep.maxpacket, udc_gfp_flags);
+ if (retval != 0)
+ {
+ if (retval == -ENOMEM)
+ INFO("Out of DMA memory (allocation failed)\n");
+ return retval;
+ }
+ /*TODO better place ? */
+ if (ep->in) {
+ if (req->req.length == ep->ep.maxpacket) {
+ /* write tx bytes */
+ req->td_data->status = AMD_ADDBITS(req->td_data->status,
+ ep->ep.maxpacket,
+ UDC_DMA_IN_STS_TXBYTES);
+
+ }
+ }
+
+ }
+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND
+ else { /* EP0 */
+ /* point to itself */
+ req->td_data->next = req->td_phys;
+ }
+#endif
+
+ if (ep->in) {
+ VDBG("IN: use_dma_ppb=%d req->req.length=%d ep->ep.maxpacket=%d ep%d\n",
+ use_dma_ppb, req->req.length, ep->ep.maxpacket, ep->num);
+ /* if bytes < max packet then tx bytes must */
+ /* be written in packet per buffer mode */
+ if (!use_dma_ppb || req->req.length < ep->ep.maxpacket
+ || ep->num == UDC_EP0OUT_IX || ep->num == UDC_EP0IN_IX) {
+ /* write tx bytes */
+ req->td_data->status = AMD_ADDBITS(req->td_data->status,
+ req->req.length,
+ UDC_DMA_IN_STS_TXBYTES);
+ /* reset frame num */
+ req->td_data->status = AMD_ADDBITS(req->td_data->status,
+ 0,
+ UDC_DMA_IN_STS_FRAMENUM);
+ }
+ /* set HOST BUSY */
+ req->td_data->status
+ = AMD_ADDBITS(req->td_data->status,
+ UDC_DMA_STP_STS_BS_HOST_BUSY,
+ UDC_DMA_STP_STS_BS);
+ }
+ else {
+ VDBG("OUT set host ready\n");
+ /* set HOST READY */
+ req->td_data->status
+ = AMD_ADDBITS(req->td_data->status,
+ UDC_DMA_STP_STS_BS_HOST_READY,
+ UDC_DMA_STP_STS_BS);
+
+
+ /* clear NAK by writing CNAK */
+ if (ep->naking) {
+ tmp = readl(&ep->regs->ctl);
+ tmp |= AMD_BIT(UDC_EPCTL_CNAK);
+ writel(tmp, &ep->regs->ctl);
+ ep->naking = 0;
+ UDC_QUEUE_CNAK(ep, ep->num);
+ }
+
+ }
+
+ return retval;
+}
+
+/**
+ * Completes request packet
+ *
+ * \param ep pointer to ep struct
+ * \param req pointer to request packet
+ * \param sts status of request
+ */
+static void
+complete_req(struct udc_ep *ep, struct udc_request *req, int sts)
+{
+ struct udc *dev;
+ unsigned halted;
+
+ VDBG("complete_req(): ep%d\n", ep->num);
+
+ dev = ep->dev;
+ /* unmap DMA */
+ if (req->dma_mapping) {
+ if (ep->in)
+ pci_unmap_single(dev->pdev,
+ req->req.dma,
+ req->req.length,
+ PCI_DMA_TODEVICE);
+ else
+ pci_unmap_single(dev->pdev,
+ req->req.dma,
+ req->req.length,
+ PCI_DMA_FROMDEVICE);
+ req->dma_mapping = 0;
+ req->req.dma = DMA_DONT_USE;
+ }
+
+ halted = ep->halted;
+ ep->halted = 1;
+
+ /* set new status if pending */
+ if (req->req.status == -EINPROGRESS)
+ req->req.status = sts;
+
+ /* remove from ep queue */
+ list_del_init (&req->queue);
+
+ VDBG( "req %p => complete %d bytes at %s with sts %d\n",
+ &req->req, req->req.length, ep->ep.name, sts);
+ if (spin_is_locked(&dev->lock)) {
+ spin_unlock (&dev->lock);
+ req->req.complete (&ep->ep, &req->req);
+ spin_lock (&dev->lock);
+ }
+ else {
+ req->req.complete (&ep->ep, &req->req);
+ }
+ ep->halted = halted;
+}
+
+/**
+ * frees pci pool descriptors of a DMA chain
+ *
+ * \param dev pointer to device struct
+ * \param req pointer to request packet
+ * \return 0 if success
+ */
+static int udc_free_dma_chain(struct udc* dev, struct udc_request* req)
+{
+
+ int ret_val = 0;
+ struct udc_data_dma *td;
+ struct udc_data_dma *td_last = NULL;
+ unsigned int i;
+
+ DBG("free chain req = %lx\n", (unsigned long) req);
+
+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND
+ /* re-link broken chain */
+ if (req->td_data_last) {
+ req->td_data_last->next = req->td_data_last_next;
+ }
+#endif
+ /* do not free first desc., will be done by free for request */
+ td_last = req->td_data;
+#if defined (CONFIG_MIPS) && !defined(CONFIG_DMA_COHERENT)
+ td = UNCAC_ADDR(phys_to_virt(td_last->next));
+#else
+ td = phys_to_virt(td_last->next);
+#endif
+
+ for (i = 1; i < req->chain_len; i++) {
+
+ pci_pool_free (dev->data_requests, td,
+ (dma_addr_t) td_last->next);
+ td_last = td;
+#if defined (CONFIG_MIPS) && !defined(CONFIG_DMA_COHERENT)
+ td = UNCAC_ADDR(phys_to_virt(td_last->next));
+#else
+ td = phys_to_virt(td_last->next);
+#endif
+ }
+
+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND
+ req->td_data_last = NULL;
+#endif
+ return ret_val;
+}
+
+/**
+ * Iterates to the end of a DMA chain and returns last descriptor
+ *
+ * \param req pointer to request packet
+ * \return pointer to last descriptori of chain
+ */
+static struct udc_data_dma* udc_get_last_dma_desc(struct udc_request* req)
+{
+ struct udc_data_dma *td;
+
+ td = req->td_data;
+ while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) {
+#if defined (CONFIG_MIPS) && !defined(CONFIG_DMA_COHERENT)
+ td = UNCAC_ADDR(phys_to_virt(td->next));
+#else
+ td = phys_to_virt(td->next);
+#endif
+ }
+
+ return td;
+
+}
+
+/**
+ * Iterates to the end of a DMA chain and counts bytes received
+ *
+ * \param req pointer to request packet
+ * \return number of received bytes
+ */
+static u32 udc_get_ppbdu_rxbytes(struct udc_request* req)
+{
+ struct udc_data_dma *td;
+ u32 count;
+
+ td = req->td_data;
+ /* received number bytes */
+ count = AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES);
+
+ while (td && !(td->status & AMD_BIT(UDC_DMA_IN_STS_L))) {
+#if defined (CONFIG_MIPS) && !defined(CONFIG_DMA_COHERENT)
+ td = UNCAC_ADDR(phys_to_virt(td->next));
+#else
+ td = phys_to_virt(td->next);
+#endif
+ /* received number bytes */
+ if (td) {
+ count += AMD_GETBITS(td->status, UDC_DMA_OUT_STS_RXBYTES);
+ }
+ }
+
+ return count;
+
+}
+
+/**
+ * Creates or re-inits a DMA chain
+ *
+ * \param ep pointer to endpoint struct
+ * \param req pointer to request packet
+ * \param buf_len number of buffer bytes per descriptor (except last short)
+ */
+static int udc_create_dma_chain(struct udc_ep* ep, struct udc_request* req, unsigned long buf_len, int gfp_flags)
+{
+ unsigned long bytes = req->req.length;
+ unsigned int i;
+ dma_addr_t dma_addr;
+ struct udc_data_dma *td = NULL;
+ struct udc_data_dma *last = NULL;
+ unsigned long txbytes;
+ unsigned create_new_chain = 0;
+ unsigned len;
+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND
+ dma_addr_t last_next = DMA_DONT_USE;
+#endif
+
+ VDBG("udc_create_dma_chain: bytes=%ld buf_len=%ld\n", bytes, buf_len);
+ dma_addr = DMA_DONT_USE;
+
+ /* unset L bit in first desc for OUT */
+ if (!ep->in) {
+ req->td_data->status &= AMD_CLEAR_BIT(UDC_DMA_IN_STS_L);
+ }
+
+ /* alloc only new desc's if not already available */
+ len = req->req.length / ep->ep.maxpacket;
+ if (req->req.length % ep->ep.maxpacket) {
+ len++;
+ }
+
+ if (len > req->chain_len) {
+ /* shorter chain already allocated before */
+ if (req->chain_len > 1) {
+ udc_free_dma_chain(ep->dev, req);
+ }
+ req->chain_len = len;
+ create_new_chain = 1;
+ }
+
+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND
+ /* re-link broken chain */
+ if (req->td_data_last) {
+ req->td_data_last->next = req->td_data_last_next;
+ }
+ /* if only one td then last_next is root td */
+ last_next = req->td_phys;
+#endif
+
+ td = req->td_data;
+ /* gen. required number of descriptors and buffers */
+ for (i = buf_len; i < bytes; i += buf_len)
+ {
+ /* create or determine next desc. */
+ if (create_new_chain) {
+
+#if defined(CONFIG_MIPS)
+ gfp_flags = GFP_ATOMIC | GFP_DMA;
+#endif
+ td = pci_pool_alloc (ep->dev->data_requests, gfp_flags,
+ &dma_addr);
+ if (!td)
+ return -ENOMEM;
+
+ td->status = 0;
+ }
+ else if (i == buf_len)
+ {
+ /* first td */
+#if defined (CONFIG_MIPS) && !defined(CONFIG_DMA_COHERENT)
+ td = (struct udc_data_dma*) UNCAC_ADDR(phys_to_virt(req->td_data->next));
+#else
+ td = (struct udc_data_dma*) phys_to_virt(req->td_data->next);
+#endif
+ td->status = 0;
+ }
+ else {
+#if defined (CONFIG_MIPS) && !defined(CONFIG_DMA_COHERENT)
+ td = (struct udc_data_dma*) UNCAC_ADDR(phys_to_virt(last->next));
+#else
+ td = (struct udc_data_dma*) phys_to_virt(last->next);
+#endif
+ td->status = 0;
+ }
+
+
+ if (td) {
+ /* assign buffer */
+ td->bufptr = req->req.dma + i;
+ }
+ else {
+ break;
+ }
+
+ /* short packet ? */
+ if ((bytes - i) >= buf_len) {
+ txbytes = buf_len;
+ }
+ else {
+ /* short packet */
+ txbytes = bytes - i;
+ }
+
+ /* link td and assign tx bytes */
+ if (i == buf_len) {
+ if (create_new_chain) {
+ req->td_data->next = dma_addr;
+ }
+ else {
+ //req->td_data->next = virt_to_phys(td);
+ }
+ /* write tx bytes */
+ if (ep->in) {
+ /* first desc */
+ req->td_data->status = AMD_ADDBITS(req->td_data->status,
+ ep->ep.maxpacket,
+ UDC_DMA_IN_STS_TXBYTES);
+ /* second desc */
+ td->status = AMD_ADDBITS(td->status,
+ txbytes,
+ UDC_DMA_IN_STS_TXBYTES);
+ }
+
+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND
+ last_next = req->td_data->next;
+#endif
+ }
+ else {
+ if (create_new_chain) {
+ last->next = dma_addr;
+ }
+ else {
+ //last->next = virt_to_phys(td);
+ }
+ if (ep->in) {
+ /* write tx bytes */
+ td->status = AMD_ADDBITS(td->status,
+ txbytes,
+ UDC_DMA_IN_STS_TXBYTES);
+ }
+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND
+ last_next = last->next;
+#endif
+ }
+ last = td;
+ }
+ /* set last bit */
+ if (td) {
+ td->status |= AMD_BIT(UDC_DMA_IN_STS_L);
+ /* last desc. points to itself */
+#ifdef UDC_IPDEFECT_9000004946_WORKAROUND
+ /* remember broken chain next pointer */
+ req->td_data_last_next = td->next;
+ /* point to itself */
+ td->next = last_next;
+#endif
+ req->td_data_last = td;
+ }
+
+ return 0;
+}
+
+/**
+ * Enabling RX DMA
+ *
+ * \param dev pointer to UDC device object
+ */
+static inline void udc_set_rde(struct udc* dev)
+{
+ u32 tmp;
+
+ VDBG("udc_set_rde()\n");
+#ifdef UDC_USE_TIMER
+ /* stop RDE timer */
+ if (timer_pending(&udc_timer)) {
+ set_rde = 0;
+ mod_timer(&udc_timer, jiffies - 1);
+ }
+#endif
+ /* set RDE */
+ tmp = readl(&dev->regs->ctl);
+ tmp |= AMD_BIT(UDC_DEVCTL_RDE);
+ writel(tmp, &dev->regs->ctl);
+}
+
+/**
+ * Queues a request packet, called by gadget driver
+ *
+ * \param usbep pointer to usb ep struct
+ * \param usbreq pointer to request packet to be freed
+ * \param gfp flags for alloc
+ * \return 0 if success
+ */
+static int
+udc_queue (struct usb_ep *usbep, struct usb_request *usbreq, int gfp)
+{
+ int retval = 0;
+ unsigned long iflags;
+ struct udc_ep *ep;
+ struct udc_request *req;
+ struct udc *dev;
+ u32 tmp;
+
+ VDBG ("udc_queue()\n");
+
+ /* check the inputs */
+ req = container_of (usbreq, struct udc_request, req);
+ VDBG("!usbep=%d !req=%d !buf=%d !compl=%d !empty_list=%d \n",
+ !usbep, !usbreq, !usbreq->buf, !usbreq->complete,
+ !list_empty(&req->queue));
+
+ if (!usbep || !usbreq || !usbreq->complete || !usbreq->buf
+ || !list_empty (&req->queue))
+ return -EINVAL;
+
+ ep = container_of (usbep, struct udc_ep, ep);
+ if (!ep->desc && (ep->num != 0 && ep->num != UDC_EP0OUT_IX))
+ return -EINVAL;
+
+ VDBG("udc_queue(): ep%d-in=%d\n", ep->num, ep->in);
+ dev = ep->dev;
+
+ /* exit on suspend */
+ if (dev->sys_suspended)
+ return -ESHUTDOWN;
+
+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
+ return -ESHUTDOWN;
+
+ /* map dma (usally done before) */
+ if (ep->dma && usbreq->length != 0 && usbreq->dma == DMA_DONT_USE) {
+ VDBG("DMA map req %lx\n", (unsigned long) req);
+ if (ep->in)
+ usbreq->dma = pci_map_single(dev->pdev,
+ usbreq->buf,
+ usbreq->length,
+ PCI_DMA_TODEVICE);
+ else
+ usbreq->dma = pci_map_single(dev->pdev,
+ usbreq->buf,
+ usbreq->length,
+ PCI_DMA_FROMDEVICE);
+ req->dma_mapping = 1;
+ }
+
+ VDBG( "%s queue req %p, len %d req->td_data=%lx buf %p\n",
+ usbep->name, usbreq, usbreq->length, (unsigned long) req->td_data, usbreq->buf);
+
+ spin_lock_irqsave (&dev->lock, iflags);
+ usbreq->actual = 0;
+ usbreq->status = -EINPROGRESS;
+ req->dma_done = 0;
+
+ /* on empty queue just do first transfer */
+ if (list_empty (&ep->queue)) {
+ /* zlp */
+ if (ep->in && usbreq->lengt